mineassembly/mine.asm
2020-06-18 14:47:42 +02:00

810 lines
24 KiB
NASM

format MZ ;Specify the .EXE format
entry MainSeg:start
org 0100h
stack $3000
;org 100h ;specify origin
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Constants
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
COLUMNS = 16
LINES = 16
FIELDX = 20 - (COLUMNS/2)
FIELDY = 4
MAXMINES = 40
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
segment MainSeg
use16
start:
mov al,13h ;AX=0000 at program start
int 10h ;init mode 13h
push word 0A000h ;Requires 80186 or higher to PUSH IMMED
pop es ;ES now points to mode 13h screen segment
mov ax, DataSeg
mov ds, ax ;DS now points to our data segment
call createminefield ;Initialize the map with mines
call calculateminenumbers ;Populate the numbers
call drawfield ;Draw the map
jmp mainloop ;Main event and game loop
; Draw the field
drawfield:
mov cx, 00h
mov ax, 00h
drawfieldloop:
push cx
push ax
call getbmp
add cx, FIELDY ; Make sure we get the field displaced correctly
add ax, FIELDX
call drawbox
pop ax
pop cx
inc cx
cmp cx, LINES
jne drawfieldloop
mov cx, 0h
inc ax
cmp ax, COLUMNS
jne drawfieldloop
mov ax, [cursorx]
add ax, FIELDX
mov cx, [cursory]
add cx, FIELDY ; Make sure we get the cursor displaced correctly
mov bx, cursorbmp
call drawbox
call drawmineno
ret
getbmp:
push cx ; Store the values before scr$%&ing them
push ax
call peektable
pop ax ; Recover the values of AX and BX
pop cx
;;;;; Normal reading of the field, covering the cells
cmp dh, 01h ; Covered cell
je iscovered
cmp dh, 02h ; Flagged cell
je isflagged
cmp dx, 00009h ; There's a mine
je mine
cmp dx, 00008h
je puteight
cmp dx, 00007h
je putseven
cmp dx, 00006h
je putsix
cmp dx, 00005h
je putfive
cmp dx, 00004h
je putfour
cmp dx, 00003h
je putthree
cmp dx, 00002h
je puttwo
cmp dx, 00001h
je putone
;;;;;;;;;;;;;;; Uncomment this to see the field uncovered
; cmp dh, 02h ; Flagged cell
; je isflagged
; cmp dx, 00109h ; There's a mine
; je mine
; cmp dx, 00108h
; je puteight
; cmp dx, 00107h
; je putseven
; cmp dx, 00106h
; je putsix
; cmp dx, 00105h
; je putfive
; cmp dx, 00104h
; je putfour
; cmp dx, 00103h
; je putthree
; cmp dx, 00102h
; je puttwo
; cmp dx, 00101h
; je putone
mov bx, emptycell ; Point to the emptycell bitmap
ret
iscovered:
mov bx, covercell ; Point to the covered cell
ret
isflagged:
mov bx, flagbmp ; Point to the flag bitmap
ret
mine:
mov bx, minebmp ; Point to the mine cell
ret
putone:
mov bx, numone ; Point to the corresponding number cell
ret
puttwo:
mov bx, numtwo ; Point to the corresponding number cell
ret
putthree:
mov bx, numthree ; Point to the corresponding number cell
ret
putfour:
mov bx, numfour ; Point to the corresponding number cell
ret
putfive:
mov bx, numfive ; Point to the corresponding number cell
ret
putsix:
mov bx, numsix ; Point to the corresponding number cell
ret
putseven:
mov bx, numseven ; Point to the corresponding number cell
ret
puteight:
mov bx, numeight ; Point to the corresponding number cell
ret
drawmineno:
mov ax, 0200h ; Set cursor routine selection
mov bh, 00h ; Set to 0 for graphics modes
mov dx, 0013h ; Top row, centered (double digits)
int 10h
mov ax, 0
mov al, [minecount] ; Get mines
cmp ax, 10 ; See if we have to draw a zero or not
jge drawdecimal
push ax
mov cx, 00h ; Tell the system to draw a zero
call drawnumber
pop cx
jmp drawunits
drawdecimal:
mov ax, 0
mov al, byte [minecount]
mov cx, 10
div cl
push ax
mov cl, al
call drawnumber
pop ax
mov al, 00
mov cl, ah
drawunits:
push cx
mov ax, 0200h ; Set cursor routine selection
mov bh, 00h ; Set to 0 for graphics modes
mov dx, 0014h ; Top row, centered (double digits)
int 10h
pop cx
call drawnumber
ret
drawnumber:
mov al, cl
add ax, 30h ; We draw numbers, add 30h and you get the ascii code
mov ah, 09h ; Draw a character at current cursor position
mov cx, 01h ; Draw the character once
mov bh, 00h ; Black background
mov bl, 04h ; Red color
int 10h
ret
;Random subroutines here
initseed:
mov ah, 02Ch ;Select Get System Time function
int 021h ;Call DOS
add cx, dx ;Add the seconds and milliseconds to add more randomness
mov word [seed], cx ;In CX we have our new seed
ret
random:
mov ax, 25173 ;LCG multiplier
mul word [seed] ;DX:AX = LCG multiplier * seed
add ax, 13849 ;Add LCG increment value
mov word [seed], ax ;Update seed, AX has the random number now
ret
;This is thought to pick up from the registers the address of what we need to draw
;Draw it, and return. The params are:
;- AX -> X position
;- CX -> Y position
;- BX -> base memory address of the bitmap
drawbox:
push ax ;Save the X value for later
mov ax, cx ;Prepare for multiplications
mov dx, 320 * 8 ;The box is 8x8, the screen width is 320
mul dx
mov cx, ax ;Retrieve the line into CX
pop ax ;Retrieve the X value into AX register
mov dx, 8 ;The box is 8x8, each box is 8 pixel wide
mul dx ;We multiply the X value too for the 8x8
add cx, ax ;Now we've put in AX the pointer value
mov si, cx ;Set SI to the correct address we'll draw
mov cx, 00
mov ax, 00
mov dx, 00
drawloop:
mov al, byte [ds:bx] ;Current address in BX
cmp al, 0ffh ;This is transparent pixel, don't draw
je dontdraw
mov byte [es:si], al ;Put the pixel into RAM
dontdraw:
inc bx
inc cx
inc dx
cmp dx, 8 ;Sort of modulo
je jumplinedraw ;Time to increment SI in a more complex way
inc si
continuecomp:
cmp cx, 64 ;Compare CX the max the field will be
jne drawloop ;Continue
ret ;Return
jumplinedraw:
mov dx, 00h
add si, 313 ;Jump a whole line
jmp continuecomp ;Continue the routine
;This function populates the minefield with mines
createminefield:
call initseed ;Make sure we have a good seed
mov dx, 00h ;DX will be our pointer
mov bx, map ;BX our base pointer
cmfloop:
push dx ;Save our counters before generating random number
push bx
call random ;This leaves a random num in AX
pop bx ;Recover our counters
pop dx
cmp al, 0FFh ;Compare if it's greater than 240
je putmine ;Put a mine here
continuecreateminefield:
add bx, 02h
inc dx
cmp dx, COLUMNS * LINES ; Check we have done the whole map
jl cmfloop
cmp byte [minecount], MAXMINES ; Check we've put all mines!
jl createminefield
finishcreateminefield:
ret ; All is ok
putmine:
cmp byte [minecount], MAXMINES
jge finishcreateminefield
cmp word [ds:bx], 00109h ;Check memory for placed mine
je continuecreateminefield
inc byte [minecount]
mov word [ds:bx], 00109h ;Place mine
jmp continuecreateminefield
;This routine returns in DX the value of the cell pointed by CX (Y coord) and
;AX (X coord)
;Mangles AX, BX, CX and DX
peektable:
mov dx, 0 ;In case we return prematurely, we return nothing
cmp ax, COLUMNS ;If we are out of bounds, return
jge peekend
cmp cx, LINES
jge peekend
push ax ;Calculate offset
mov ax, cx
mov cx, COLUMNS
mul cx
mov cx, ax
pop ax
add ax, cx
mov cx, 2
mul cx
mov bx, map
add bx, ax
mov dx, word [ds:bx] ;Read
peekend:
ret
calcnumber:
push ax
push cx
call peektable
pop cx
cmp dx, 00109h
jne calcend
mov al, byte [tempnumber]
inc al
mov byte [tempnumber], al
calcend:
pop ax
ret
; We don't check Y bounds as we have surrounded the field array
; with padding zeroes, rendering this calculation correct if CX
; is below or beyond the limits
checksurroundings:
mov byte [tempnumber], 0
push ax
push cx
sub cx, 1
test ax, ax
jz axiszerofirstrow
sub ax, 1
call calcnumber
add ax, 1
axiszerofirstrow:
call calcnumber
add ax, 1
cmp ax, COLUMNS
je axoutboundsfirstrow
call calcnumber
axoutboundsfirstrow:
pop cx
pop ax
push ax
push cx
test ax, ax
jz axiszerosecondrow
sub ax, 1
call calcnumber
inc ax
axiszerosecondrow:
inc ax
cmp ax, COLUMNS
je axoutboundssecondrow
call calcnumber
axoutboundssecondrow:
pop cx
pop ax
push ax
push cx
add cx, 1
test ax, ax
jz axiszerothirdrow
sub ax, 1
call calcnumber
add ax, 1
axiszerothirdrow:
call calcnumber
add ax, 1
cmp ax, COLUMNS
je axoutboundsthirdrow
call calcnumber
axoutboundsthirdrow:
pop cx
mov bx, map
mov ax, cx
mov dx, COLUMNS
mul dx
mov dx, ax
pop ax
push ax
add dx, ax
mov ax, dx
mov dx, 2
mul dx
add bx, ax
pop ax
mov dx, 00100h
mov dl, byte [tempnumber]
mov word [ds:bx], dx
ret
;This routine checks the map and puts numbers down given the
;amount of mines around
calculateminenumbers:
mov ax, 0
mov cx, 0
cmnloop:
push ax
push cx
call peektable
pop cx
pop ax
cmp dx, 00109h
je cmncontinue
call checksurroundings
cmncontinue:
inc ax
cmp ax, COLUMNS
jl cmnloop
mov ax, 0
inc cx
cmp cx, LINES
jl cmnloop
ret
mainloop:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;This is where you do your mega-amazing tiny program.
;Write 8-bit values to A000:0000 to draw some pixels.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Check for user input or wanting to leave by pressing ESC
in al,60h ;read whatever is at keyboard port; looking for ESC which is #1
cmp al,48h
je upkey
cmp al,4bh
je leftkey
cmp al,4dh
je rightkey
cmp al,50h
je downkey
cmp al,39h
je space
cmp al,38h
je lalt
mov word [lastkeypressed], 0h ;Reset the current key as it is not one we are checking
cmp byte [wingame], 1
je winexit
dec al ;if ESC, AL now 0
jnz mainloop ;fall through if 0, jump otherwise
exit:
mov ax,03 ;AX=0000 due to mainloop exit condition
int 10h ;Switch back to text mode as a convenience
mov ah,4Ch ;Function to exit, now we are an EXE, do it correctly
mov al,00 ;Exit code as 0, everything went well
int 21h
winexit:
mov al,03 ;AX=0000 due to mainloop exit condition
int 10h ;Switch back to text mode as a convenience
mov dx, youwinstr
mov ah, 09h
int 21h
mov ah,4Ch ;Function to exit, now we are an EXE, do it correctly
mov al,00 ;Exit code as 0, everything went well
int 21h
gameover:
call drawfield
mov ax, 0
mov ah, 02Ch ;Get current system time
int 021h
mov bh, dh ;Get current seconds
waitloop:
mov ah, 02Ch
int 021h
sub dh, bh ;Get seconds elapsed
cmp dh, 2
jl waitloop
mov ah, 0
mov al,03 ;AX=0000 due to mainloop exit condition
int 10h ;Switch back to text mode as a convenience
mov dx, gameoverstr
mov ah, 09h
int 21h
mov ah,4Ch ;Function to exit, now we are an EXE, do it correctly
mov al,00 ;Exit code as 0, everything went well
int 21h
redraw:
call drawfield
jmp mainloop
leftkey:
cmp ax, [lastkeypressed]
je mainloop
mov [lastkeypressed], ax
mov ax, [cursorx]
dec ax
updatelateralmovement:
cmp ax, COLUMNS - 1
jg redraw
cmp ax, 0
jl redraw
mov [cursorx], ax
jmp redraw
rightkey:
cmp ax, [lastkeypressed]
je mainloop
mov [lastkeypressed], ax
mov ax, [cursorx]
inc ax
jmp updatelateralmovement
upkey:
cmp ax, [lastkeypressed]
je mainloop
mov [lastkeypressed], ax
mov cx, [cursory]
dec cx
updateverticalmovement:
cmp cx, LINES - 1
jg redraw
cmp cx, 0
jl redraw
mov [cursory], cx
jmp redraw
downkey:
cmp ax, [lastkeypressed]
je mainloop
mov [lastkeypressed], ax
mov cx, [cursory]
inc cx
jmp updateverticalmovement
space:
cmp ax, [lastkeypressed]
je mainloop
mov [lastkeypressed], ax
mov ax, [cursorx]
mov cx, [cursory]
call uncover
mov ax, [cursorx]
mov cx, [cursory]
call peektable
cmp dx, 00009h
je gameover
jmp redraw
lalt:
cmp ax, [lastkeypressed]
je mainloop
mov [lastkeypressed], ax
mov ax, [cursorx]
mov cx, [cursory]
call setflag
jmp redraw
getoffset:
cmp ax, COLUMNS ;If we are out of bounds, return
jl checky
ret
checky:
cmp cx, LINES
jl inbounds
ret
inbounds:
push ax ;Calculate offset
mov ax, cx
mov cx, COLUMNS
mul cx
mov cx, ax
pop ax
add ax, cx
mov cx, 2
mul cx
mov bx, map
add bx, ax
ret
uncover:
push ax ;Save coordinates
push cx
call getoffset
pop cx ;Recover them
pop ax
mov dx, word [ds:bx] ;Read
cmp dh, 00h ;Already uncovered
je terminateuncover
dec word [covered]
mov dh, 00h ;Set upperbit as 0
mov word [ds:bx], dx
cmp dx, 00000h ;If the cell is empty
je uncoveraround
terminateuncover:
ret
uncoveraround:
push ax
push cx
sub cx, 1
test ax, ax
jz unaxiszerofirstrow
sub ax, 1
call uncover
add ax, 1
unaxiszerofirstrow:
call uncover
add ax, 1
cmp ax, COLUMNS
je unaxoutboundsfirstrow
call uncover
unaxoutboundsfirstrow:
pop cx
pop ax
push ax
push cx
test ax, ax
jz unaxiszerosecondrow
sub ax, 1
call uncover
inc ax
unaxiszerosecondrow:
inc ax
cmp ax, COLUMNS
je unaxoutboundssecondrow
call uncover
unaxoutboundssecondrow:
pop cx
pop ax
push ax
push cx
add cx, 1
test ax, ax
jz unaxiszerothirdrow
sub ax, 1
call uncover
add ax, 1
unaxiszerothirdrow:
call uncover
add ax, 1
cmp ax, COLUMNS
je unaxoutboundsthirdrow
call uncover
unaxoutboundsthirdrow:
pop cx
pop ax
ret
setflag:
dec byte [minecount]
call getoffset
mov dx, word [ds:bx] ;Read
mov dh, 02h ;Set upperbit as 0
mov word [ds:bx], dx
call checkendgame
ret
checkendgame:
mov al, byte [minecount]
test al, al
jnz endcheckendgame
mov ax, word [covered]
sub ax, MAXMINES
jnz endcheckendgame
mov byte [wingame], 1
endcheckendgame:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Data segment
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
segment DataSeg
use16
lastkeypressed: dw 0
seed: dw 0
minecount: db 0
tempnumber: db 0
cursorx: dw 0
cursory: dw 0
covered: dw COLUMNS * LINES
wingame: db 0
gameoverstr: db "Game over!$"
youwinstr: db "You win!$"
;Game map. First 8 bytes are for the cell status
;the last 8 bytes are for the cell contents.
;
;Cell status: 0 covered, 1 uncovered, 2 flagged
;Cell content: 0 empty, 1-8 number, 9 mine
paddmapbf: dw COLUMNS dup 00h
map: dw COLUMNS * LINES dup 00h
paddmapaft: dw COLUMNS dup 00h
covercell: db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
db 0fh, 17h, 17h, 17h, 17h, 17h, 17h, 14h
db 0fh, 17h, 17h, 17h, 17h, 17h, 17h, 14h
db 0fh, 17h, 17h, 17h, 17h, 17h, 17h, 14h
db 0fh, 17h, 17h, 17h, 17h, 17h, 17h, 14h
db 0fh, 17h, 17h, 17h, 17h, 17h, 17h, 14h
db 0fh, 17h, 17h, 17h, 17h, 17h, 17h, 14h
db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
emptycell: db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
db 14h, 17h, 17h, 17h, 17h, 17h, 17h, 0fh
db 14h, 17h, 17h, 17h, 17h, 17h, 17h, 0fh
db 14h, 17h, 17h, 17h, 17h, 17h, 17h, 0fh
db 14h, 17h, 17h, 17h, 17h, 17h, 17h, 0fh
db 14h, 17h, 17h, 17h, 17h, 17h, 17h, 0fh
db 14h, 17h, 17h, 17h, 17h, 17h, 17h, 0fh
db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
minebmp: db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
db 14h, 10h, 17h, 10h, 17h, 17h, 10h, 0fh
db 14h, 17h, 10h, 10h, 10h, 10h, 17h, 0fh
db 14h, 17h, 10h, 10h, 0fh, 10h, 10h, 0fh
db 14h, 10h, 10h, 10h, 10h, 10h, 17h, 0fh
db 14h, 17h, 10h, 10h, 10h, 10h, 17h, 0fh
db 14h, 10h, 17h, 17h, 10h, 17h, 10h, 0fh
db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
flagbmp: db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
db 0fh, 17h, 17h, 04h, 10h, 17h, 17h, 14h
db 0fh, 17h, 04h, 04h, 10h, 17h, 17h, 14h
db 0fh, 04h, 04h, 04h, 10h, 17h, 17h, 14h
db 0fh, 17h, 17h, 17h, 10h, 17h, 17h, 14h
db 0fh, 17h, 17h, 17h, 10h, 17h, 17h, 14h
db 0fh, 17h, 10h, 10h, 10h, 10h, 10h, 14h
db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
numone: db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
db 14h, 17h, 17h, 17h, 01h, 17h, 17h, 0fh
db 14h, 17h, 17h, 01h, 01h, 17h, 17h, 0fh
db 14h, 17h, 01h, 17h, 01h, 17h, 17h, 0fh
db 14h, 17h, 17h, 17h, 01h, 17h, 17h, 0fh
db 14h, 17h, 17h, 17h, 01h, 17h, 17h, 0fh
db 14h, 17h, 01h, 01h, 01h, 01h, 01h, 0fh
db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
numtwo: db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
db 14h, 17h, 17h, 02h, 02h, 02h, 17h, 0fh
db 14h, 17h, 02h, 17h, 17h, 17h, 02h, 0fh
db 14h, 17h, 17h, 17h, 17h, 17h, 02h, 0fh
db 14h, 17h, 17h, 02h, 02h, 02h, 17h, 0fh
db 14h, 17h, 02h, 17h, 17h, 17h, 17h, 0fh
db 14h, 17h, 02h, 02h, 02h, 02h, 02h, 0fh
db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
numthree: db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
db 14h, 17h, 17h, 04h, 04h, 04h, 17h, 0fh
db 14h, 17h, 04h, 17h, 17h, 17h, 04h, 0fh
db 14h, 17h, 17h, 17h, 17h, 17h, 04h, 0fh
db 14h, 17h, 17h, 17h, 04h, 04h, 17h, 0fh
db 14h, 17h, 04h, 17h, 17h, 17h, 04h, 0fh
db 14h, 17h, 17h, 04h, 04h, 04h, 17h, 0fh
db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
numfour: db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
db 14h, 17h, 17h, 17h, 05h, 05h, 17h, 0fh
db 14h, 17h, 17h, 05h, 17h, 05h, 17h, 0fh
db 14h, 17h, 05h, 17h, 17h, 05h, 17h, 0fh
db 14h, 17h, 05h, 05h, 05h, 05h, 05h, 0fh
db 14h, 17h, 17h, 17h, 17h, 05h, 17h, 0fh
db 14h, 17h, 17h, 17h, 05h, 05h, 05h, 0fh
db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
numfive: db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
db 14h, 17h, 06h, 06h, 06h, 06h, 06h, 0fh
db 14h, 17h, 06h, 17h, 17h, 17h, 17h, 0fh
db 14h, 17h, 06h, 17h, 17h, 17h, 17h, 0fh
db 14h, 17h, 17h, 06h, 06h, 06h, 17h, 0fh
db 14h, 17h, 17h, 17h, 17h, 17h, 06h, 0fh
db 14h, 17h, 06h, 06h, 06h, 06h, 17h, 0fh
db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
numsix: db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
db 14h, 17h, 17h, 17h, 2bh, 2bh, 17h, 0fh
db 14h, 17h, 17h, 2bh, 17h, 17h, 17h, 0fh
db 14h, 17h, 2bh, 17h, 17h, 17h, 17h, 0fh
db 14h, 17h, 2bh, 2bh, 2bh, 2bh, 17h, 0fh
db 14h, 17h, 2bh, 17h, 17h, 17h, 2bh, 0fh
db 14h, 17h, 17h, 2bh, 2bh, 2bh, 17h, 0fh
db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
numseven: db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
db 14h, 17h, 35h, 35h, 35h, 35h, 35h, 0fh
db 14h, 17h, 17h, 17h, 17h, 17h, 35h, 0fh
db 14h, 17h, 17h, 17h, 17h, 35h, 17h, 0fh
db 14h, 17h, 17h, 17h, 35h, 17h, 17h, 0fh
db 14h, 17h, 17h, 17h, 35h, 17h, 17h, 0fh
db 14h, 17h, 17h, 17h, 35h, 17h, 17h, 0fh
db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
numeight: db 14h, 14h, 14h, 14h, 14h, 14h, 14h, 14h
db 14h, 17h, 17h, 40h, 40h, 40h, 17h, 0fh
db 14h, 17h, 40h, 17h, 17h, 17h, 40h, 0fh
db 14h, 17h, 17h, 40h, 40h, 40h, 17h, 0fh
db 14h, 17h, 40h, 17h, 17h, 17h, 40h, 0fh
db 14h, 17h, 40h, 17h, 17h, 17h, 40h, 0fh
db 14h, 17h, 17h, 40h, 40h, 40h, 17h, 0fh
db 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh, 0fh
cursorbmp: db 2ah, 2ah, 2ah, 2ah, 2ah, 2ah, 2ah, 2ah
db 2ah, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 2ah
db 2ah, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 2ah
db 2ah, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 2ah
db 2ah, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 2ah
db 2ah, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 2ah
db 2ah, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 2ah
db 2ah, 2ah, 2ah, 2ah, 2ah, 2ah, 2ah, 2ah