; BOMBER - a tiny game - by Tylisha C. Andersen & Tenie Remmel
; the original idea for this was from a 256-byte-game contest
; our version has a score display & increasing speed each level
; and it is still only 256 bytes!
;
; commands:  <esc> = exit;  <space> = drop a bomb.

o           equ <offset>
b           equ <byte ptr>
w           equ <word ptr>

.model tiny
.code
.186
org 100h

;-----------------------------------------------------------

main:       xor   ax, ax            ; set video mode 0 (40x25)
            int   10h

            mov   ah, 1             ; turn off cursor
            mov   ch, 20h
            int   10h

            mov   ax, 1100h         ; set chars C0 and C1 to airplane bitmap
            mov   bx, 0F00h
            mov   cx, 2
            mov   dx, 0C0h
            mov   bp, o font1
            int   10h

            dec   cx                ; set char 00 to bomb bitmap
            xor   dx, dx
            mov   bp, o font2
            int   10h

            mov   dx, 0B800h        ; es = video memory; set the delay time
            mov   es, dx            ; to 01B800h (about 1/9 second)
            mov   b es:[78], 30h    ; draw the initial score

;-----------------------------------------------------------

m_bigloop:  mov   dl, dh            ; dx = (cx:dx / 256) for setting the
            mov   dh, cl            ; speed of the plane (see below)

            mov   si, 1996          ; si = end of screen (2000-4)
            mov   bx, 38            ; 38 bars to draw

m_randloop: mov   cx, ds:[046Ch]    ; generate random number
            xor   cx, bx            ; ds = 0 all but the first time
            xor   cx, di

            mov   ax, 7DB1h         ; ah = random color, al = 50% gray
            and   ah, cl
            inc   ah
            and   cx, 0Fh           ; bx = random length 1-16
            inc   cx

            mov   di, si            ; di = starting offset
m_barloop:  stosw                   ; draw this char
            sub   di, 82            ; next char
            loop  m_barloop         ; loop

            mov   ds, cx            ; ds = segment 0

            dec   si                ; next bar
            dec   si
            dec   bx                ; loop
            jnz   m_randloop

            imul  dx, 230           ; now cl:dx is speeded up by 10%
            adc   cl, ch            ;  (cx = 0, see above for dx)

            mov   di, 82            ; initial di for main loop
            mov   bx, 2000          ; bx = offset of bomb flag

            push  es                ; ds = video memory
            pop   ds

;-----------------------------------------------------------

m_mainloop: mov   ah, 86h           ; delay
            int   15h

            mov   b [di-2], 20h     ; clear char at [di-2]
            cmp   di, bx            ; made it to the bottom, start again
            je    m_bigloop

            mov   ax, 09C0h         ; draw bomber at current position
            stosw                   ; and move forward by one char
            inc   ax
            mov   [di], ax

            mov   ax, 01B1h         ; ah = 1, al = building char
            cmp   b [di+2], al      ; hit a building, game over
            je    m_gameover
            cmp   b [bx], ah        ; check if a bomb is falling
            jne   m_cont

;-----------------------------------------------------------

            mov   w [bx+si], 0720h  ; erase the bomb
            add   si, 80            ; move down 1 line
            sbb   b [bx], ch        ; clear bomb flag if off screen (ch = 0)
            jz    m_cont            ; jump if flag was cleared

            cmp   b [bx+si], al     ; test this position (al = 0B1h)
            mov   w [bx+si], 0E00h  ; draw the bomb again
            jne   m_cont            ; skip if not block

            push  si                ; save si
            mov   si, 78            ; offset of last char in score
m_incloop:  or    b [si], 30h       ; turn space into zero
            inc   b [si]            ; increment char
            cmp   b [si], '9'       ; if no carry, then quit
            jbe   m_incdone
            mov   b [si], '0'       ; otherwise, set to 0,
            dec   si                ; and continue
            dec   si
            jmp   m_incloop
m_incdone:  pop   si                ; restore si

;-----------------------------------------------------------

m_cont:     int   16h               ; check for a key (ah = 1, see above)
            jz    m_mainloop

            xor   ax, ax            ; get the key
            int   16h

            cmp   al, 1Bh           ; escape = done
            je    m_done
            sub   al, 20h           ; space = drop bomb:
            jnz   m_mainloop

            inc   ax                ; al = 1
            cmp   b [bx], al        ; if a bomb is already falling,
            je    m_mainloop        ; then do nothing, otherwise,
            lea   si, [di-1922]     ; set the bomb position
            mov   b [bx], al        ; set the bomb flag
            jmp   m_mainloop        ; loop

m_gameover: xchg  ax, cx            ; wait for a key (ch = 0)
            int   16h
m_done:     mov   ax, 3             ; restore text mode and return
            int   10h
            ret

;-----------------------------------------------------------

font1   db      000h,000h,000h,000h,000h,0C0h,040h,0F1h
        db      07Fh,07Fh,03Dh,01Bh,007h,00Fh,000h
        db      000h,000h,000h,000h,000h,03Ch,0EAh,0BFh
        db      0FFh,0EEh,0DCh,080h

font2   db      000h,000h,000h,000h,000h,018h,03Ch,066h
        db      0EBh,0E7h,0EBh,066h,03Ch,018h,000h

end main
