pouët.net

Relax by Řrřola [web]

; RELAX
; a 256-byte intro by Rrrola
; greets to everyone who's used MIDI in a tiny intro

; music algorithm: "Molecular music box" by Dr Duncan Lockerby
; setting: 18D29

  org 100h  ; assume ax=bx=0 si=100h sp=-2

  T equ $-2
  mov fs,ax   ; fs=0 (for timer)
  scasw  ; di=0
  pusha  ; adr:   -18 -16 -14 -12 -10  -8  -6  -4  -2
         ; stack:  di  si  bp  sp  bx  dx  cx  ax   0
         ; data:    0 100 9??  -2  0   cs  FF   0
         ; [-16]: SONGPOS

; Set video mode
  mov al,13h
CZ equ $-1 ;  -13037
  int 10h
  mov dx,3c8h
  salc
  out dx,al
  inc dx

; Palette: red and green imitate smoothstep
P:push ax
  mul al   ; x*x 12 bits
  imul bx,ax,10
  shr ax,5 ; 7 bits
  mul al   ; x*x*x*x (14)
  sub bx,ax
  mov al,bh
  out dx,al
  out dx,al
  pop ax
  out dx,al
  add ah,2Eh
  adc al,ch ; al:ah += 0x002E
C126:       ; -11.994
  loop P

MIDI:
  db 0x3F            ; aas
  db 0xC1,122,90h,42 ; sar word[bp+si-0x70],42
  db 91h             ; xchg ax,cx

  push 0a000h
C7: pop es

  fninit
  xor cx,cx

M:
; Play notes for the current tick?
  mov al,[fs:0x46c]
  jz F    ; first
  push ax
  sub al,4
  sub al,[si]
  pop ax
  js SKIP_MUSIC
F:mov [si],al

  pusha

  mov si,MIDI
  mov dx,331h
  outsb       ; 0x3F: UART simple mode
  dec dx
  outsb       ; 0xC1: Program change, channel 2
  outsb       ; 122: Seashore (channel 1 is the default Grand Piano)

  mov cl,31   ; max piano polyphony = 31
  xor ebp,ebp ; the cycle has 32 ticks: which ticks have played a note?
  mov ax,18   ; number of ticks between notes = initially +18
C18 equ $-2   ; D.F.A.c. eE.G.B.d (melody then switches to +29)
  mov di,[bx-16] ; song position
  inc word[bx-16]

N:pusha          ; bx = initially 0 (current note time)

  lea ax,[bx+di] ; song time minus note time
  and ax,801Fh   ; should it play yet? and on this tick?
  jnz O

  imul ax,cx,-12 ; 12 notes in octave
  add ax,34*7+12*31+5 ; first note is D
  div byte[byte si-MIDI-3+C7]  ; 7 notes in scale

  outsb       ; 0x90: Note On, channel 1
  out dx,al   ; note
  outsb       ; velocity 42
  cmp al,38   ; new seashore sound on lowest two notes
  ja O
  outsb       ; Note On, channel 2
  out dx,al   ; note 37 or 38
  out dx,al   ; velocity 37 or 38

O:popa
  bts ebp,ebx
  jnc B
  xor al,29^18; if there's a note on this tick, switch 18<->29
B:sub bx,ax   ; note time += 18 or 29

  loop N

  popa

SKIP_MUSIC:

; Draw the moon and the sea.
  xor di,di  ; loop: di=0
  mov cl,200
Y:mov bx,320

; Compute the perturbed Y after the reflection.
  mov ax,cx
  sub ax,100 ; y - 100
  push ax
  fild word[byte si-100h+CZ]
  fidiv word[-4-16]
  fiadd word[byte si-100h+T]
  fidiv word[byte si-100h+C18] ; a = (c / (y-100) + t) / 18
  fsin
  fmul dword[byte si-100h+C126]
  fistp word[-4-16]            ; dy = round(-12 * sin(a))
  pop dx
X:

  pusha

  xchg ax,bx  ; (x-160)^2 -> xx
  sub al,160
  imul al

  xchg ax,cx  ; reflection? (y<100)
  cmp al,100
  ja R
  neg al      ; y_new = 200-y + dy
  add al,200
  add al,dl
R:

  mov bl,-200 ; color gradient: (y_new-200)/2
  add bl,al
  sar bl,1

  sub al,150  ; (y_new-150)^2 -> yy
  imul al

  add cx,ax   ; 0x1000000 / (512 + xx + yy)
  mov dx,si
  add ch,2
  div cx

  shr bp,6    ; noise
  add ax,bp
  shr ax,7

  cmp ax,185  ; really bright?
  jb Z
  sub al,80   ; it's the moon
  add ax,ax   ; make it even brighter
  or ah,ah
  jz Q
  mov al,254  ; clamp to 254
  db 0x3D  ; cmp ax,NN: skip two bytes

;  jmp Q
Z:
;  cmp di,32000  ; stars didn't make it ;-)
;  jae K
;  xor cx,di
;  ror cx,cl
;  imul cx,5+96
;  test ch,ch
;  jnz K
;  shr ax,1
;  add al,96
;K:

  sub ax,bx  ; no moon: add gradient
Q:stosb
  popa

  inc di     ; new pixel, update noise
  add bp,di

  dec bx
  jnz X

  loop Y
  inc word[byte si-100h+T]
  
  in al,60h
  cmp al,1
  jnz M
I:
  ret