org 0x100

init:
  mov al, 0x13        ; initialization code
  int 0x10
  push 0xa000-10
  pop  es
  mov ax, 0x251c
  mov dl, timer
  int 0x21
  mov bp, 1

top:
  mov ax, 0xcccd
  mul di              ; di * 0xcccd -> dx:ax

  ; dh -> y
  ; dl -> x
  mov [0x902], dx
continue:
  mov ax, 0x1329
  add dh, al
  div dh
  xchg dx, ax
  imul dl
  add dx, bp
  push ax
  push dx
  xor ah, dl
  mov al, ah
  mov ah, 0
  mov bx, [0x900]
  mov cl, [mod_table + bx]
  cmp cl, 0
  jz background
  div cl
  and ah, 0x10
  je  background
  pop dx
  pop ax
  mov al, 0x2c
  jmp short fxdone
background:
  pop dx
  pop ax
  sub dx, bp
  sub dx, bp
  xor ah, dl
  mov al, ah
  mov ah, 0
  mov cl, 0x31
  div cl
  mov al, ah
  and al, 0x10
  je  fxdone
  mov dx, [0x902]
  ror dh, 5     ; y coord / 16
  and dh, 0x07  ; y coord % 8
  add dh, 0x10  ; y coord + 16
  mov al, dh

fxdone:

  ; Store AL register in ES:[DI] and increase DI.
  stosb
  inc di
  inc di
  jnz top

  ; Music
  mov cx, bp
  and cx, 0x07
  jnz skip_play

  mov si, music
  mov dx, 0x330
  mov cl, 5
  rep  outsb
  inc dx
  outsb

  ; timer
  mov al, 220
  out 40h, al

skip_play:
  ; read a character from keyboard into AL
  in al, 0x60

  ; return to top of loop if AL != 1
  dec al
  jnz top

  ret

timer:
  inc bp
  mov cx, bp
  ror cx, 8
  and cx, 0x7
  mov byte [0x900], cl
  iret

mod_table:
  db 0x00, 0x17, 0x31, 0x19,
  db 0x16, 0x1c, 0x28, 0x18

music:
  db 0xc3  ; change instrument on channel 3
  db 89    ; Instrument: https://en.wikipedia.org/wiki/General_MIDI#Sound_Effects
  db 0x93  ; play note on channel 3
  db 35    ; deep "b" = note number 35
  db 127   ; play with volume = 127
