2020-06-07 14:10:33 +02:00
|
|
|
format MZ ;Specify the .EXE format
|
|
|
|
entry MainSeg:start
|
|
|
|
org 0100h
|
|
|
|
stack $3000
|
2020-06-06 13:17:39 +02:00
|
|
|
|
2020-06-07 14:10:33 +02:00
|
|
|
;org 100h ;specify origin
|
2020-06-06 13:47:22 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;Constants
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
COLUMNS = 8
|
|
|
|
LINES = 8
|
2020-06-07 18:36:43 +02:00
|
|
|
FIELDX = 16
|
|
|
|
FIELDY = 4
|
2020-06-06 13:47:22 +02:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;Code
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
2020-06-07 14:10:33 +02:00
|
|
|
segment MainSeg
|
|
|
|
use16
|
|
|
|
|
2020-06-06 13:17:39 +02:00
|
|
|
start:
|
2020-06-07 14:10:33 +02:00
|
|
|
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
|
2020-06-07 17:47:54 +02:00
|
|
|
call createminefield ;Initialize the map with mines
|
|
|
|
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
|
2020-06-07 18:36:43 +02:00
|
|
|
call getbmp
|
2020-06-07 17:47:54 +02:00
|
|
|
add cx, FIELDY ; Make sure we get the field displaced correctly
|
|
|
|
add ax, FIELDX
|
|
|
|
call drawbox
|
|
|
|
pop ax
|
|
|
|
pop cx
|
|
|
|
inc cx
|
2020-06-07 18:36:43 +02:00
|
|
|
cmp cx, COLUMNS
|
2020-06-07 17:47:54 +02:00
|
|
|
jne drawfieldloop
|
2020-06-07 18:36:43 +02:00
|
|
|
mov cx, 0h
|
2020-06-07 17:47:54 +02:00
|
|
|
inc ax
|
2020-06-07 18:36:43 +02:00
|
|
|
cmp ax, LINES
|
2020-06-07 17:47:54 +02:00
|
|
|
jne drawfieldloop
|
|
|
|
ret
|
|
|
|
getbmp:
|
2020-06-07 18:36:43 +02:00
|
|
|
mov bx, map ; Store the base of the map in BX
|
|
|
|
push ax ; Don't mangle AX
|
|
|
|
mov ax, COLUMNS ; How many columns in AX
|
|
|
|
mul cx ; So we now multiply CX (Y coord) by COLUMNS
|
|
|
|
add bx, ax ; Add it to the pointer
|
|
|
|
pop ax ; Recover AX (X coord)
|
|
|
|
add bx, ax ; Add the X coord to BX, now we can read
|
|
|
|
cmp word [ds:bx], 0009h ; There's a mine
|
2020-06-07 17:47:54 +02:00
|
|
|
jne nomine
|
2020-06-07 18:36:43 +02:00
|
|
|
mov bx, minebmp ; Point to the mine bitmap
|
2020-06-07 17:47:54 +02:00
|
|
|
ret
|
|
|
|
nomine:
|
|
|
|
mov bx, covercell ; Point to the covered cell
|
|
|
|
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:
|
2020-06-07 18:36:43 +02:00
|
|
|
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
|
2020-06-07 17:47:54 +02:00
|
|
|
ret
|
2020-06-07 14:10:33 +02:00
|
|
|
|
|
|
|
;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
|
2020-06-07 17:47:54 +02:00
|
|
|
mov dx, 0A00h
|
|
|
|
mul dx
|
2020-06-07 14:10:33 +02:00
|
|
|
mov cx, ax ;Retrieve the line into CX
|
|
|
|
pop ax ;Retrieve the X value into AX register
|
2020-06-07 17:47:54 +02:00
|
|
|
mov dx, 08h
|
|
|
|
mul dx ;We multiply the X value too for the 8x8
|
2020-06-07 14:10:33 +02:00
|
|
|
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
|
|
|
|
mov byte [es:si], al ;Put the pixel into RAM
|
|
|
|
inc bx
|
|
|
|
inc cx
|
|
|
|
inc dx
|
|
|
|
cmp dx, 08h ;Sort of modulo
|
|
|
|
je jumplinedraw ;Time to increment SI in a more complex way
|
|
|
|
inc si
|
|
|
|
continuecomp:
|
|
|
|
cmp cx, 040h ;Compare CX to hex 64 (8x8)
|
|
|
|
jne drawloop ;Continue
|
|
|
|
ret ;Return
|
|
|
|
jumplinedraw:
|
|
|
|
mov dx, 00h
|
|
|
|
add si, 313 ;Jump a whole line
|
|
|
|
jmp continuecomp ;Continue the routine
|
2020-06-07 17:47:54 +02:00
|
|
|
|
|
|
|
;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
|
2020-06-07 18:36:43 +02:00
|
|
|
mov bx, map ;BX our base pointer
|
2020-06-07 17:47:54 +02:00
|
|
|
cmfloop:
|
|
|
|
push dx ;Save our counters before generating random number
|
|
|
|
push bx
|
|
|
|
call random ;This leaves a random num in AX
|
2020-06-07 18:36:43 +02:00
|
|
|
pop bx ;Recover our counters
|
2020-06-07 17:47:54 +02:00
|
|
|
pop dx
|
2020-06-07 18:36:43 +02:00
|
|
|
cmp al, 0FEh ;Compare if it's greater than 240
|
|
|
|
jg putmine ;Put a mine here
|
2020-06-07 17:47:54 +02:00
|
|
|
continuecreateminefield:
|
2020-06-07 18:36:43 +02:00
|
|
|
add bx, 02h
|
2020-06-07 17:47:54 +02:00
|
|
|
inc dx
|
|
|
|
cmp dx, COLUMNS * LINES ; Check we have done the whole map
|
2020-06-07 18:36:43 +02:00
|
|
|
jl cmfloop
|
2020-06-07 17:47:54 +02:00
|
|
|
cmp byte [minecount], 10 ; Check we've put all mines!
|
2020-06-07 18:36:43 +02:00
|
|
|
jl createminefield
|
2020-06-07 17:47:54 +02:00
|
|
|
finishcreateminefield:
|
|
|
|
ret ; All is ok
|
|
|
|
putmine:
|
|
|
|
cmp byte [minecount], 10
|
2020-06-07 18:36:43 +02:00
|
|
|
jge finishcreateminefield
|
|
|
|
cmp word [ds:bx], 00009h ;Check memory for placed mine
|
2020-06-07 17:47:54 +02:00
|
|
|
je continuecreateminefield
|
|
|
|
inc byte [minecount]
|
2020-06-07 18:36:43 +02:00
|
|
|
mov word [ds:bx], 00009h ;Place mine
|
2020-06-07 17:47:54 +02:00
|
|
|
jmp continuecreateminefield
|
2020-06-07 14:10:33 +02:00
|
|
|
|
2020-06-07 17:47:54 +02:00
|
|
|
;This routine checks the map and puts numbers down given the
|
|
|
|
;amount of
|
|
|
|
;calculateminenumbers:
|
|
|
|
; mov bx, [map]
|
|
|
|
; mov dx, 00h
|
2020-06-06 13:17:39 +02:00
|
|
|
|
|
|
|
mainloop:
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;This is where you do your mega-amazing tiny program.
|
|
|
|
;Write 8-bit values to A000:0000 to draw some pixels.
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
|
2020-06-07 14:10:33 +02:00
|
|
|
;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
|
|
|
|
dec al ;if ESC, AL now 0
|
|
|
|
jnz mainloop ;fall through if 0, jump otherwise
|
2020-06-06 13:47:22 +02:00
|
|
|
|
|
|
|
exit:
|
2020-06-06 13:17:39 +02:00
|
|
|
mov al,03 ;AX=0000 due to mainloop exit condition
|
|
|
|
int 10h ;Switch back to text mode as a convenience
|
2020-06-06 13:47:22 +02:00
|
|
|
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
|
2020-06-06 13:17:39 +02:00
|
|
|
|
|
|
|
upkey:
|
|
|
|
cmp ax, [lastkeypressed]
|
|
|
|
je mainloop
|
|
|
|
mov [lastkeypressed], ax
|
|
|
|
mov ah,02
|
|
|
|
mov dl,31h
|
|
|
|
int 21h
|
|
|
|
jmp mainloop
|
|
|
|
|
|
|
|
leftkey:
|
|
|
|
cmp ax, [lastkeypressed]
|
|
|
|
je mainloop
|
|
|
|
mov [lastkeypressed], ax
|
|
|
|
mov ah,02
|
|
|
|
mov dl,32h
|
|
|
|
int 21h
|
|
|
|
jmp mainloop
|
|
|
|
|
|
|
|
rightkey:
|
|
|
|
cmp ax, [lastkeypressed]
|
|
|
|
je mainloop
|
|
|
|
mov [lastkeypressed], ax
|
|
|
|
mov ah,02
|
|
|
|
mov dl,33h
|
|
|
|
int 21h
|
|
|
|
jmp mainloop
|
|
|
|
|
|
|
|
downkey:
|
|
|
|
cmp ax, [lastkeypressed]
|
|
|
|
je mainloop
|
|
|
|
mov [lastkeypressed], ax
|
|
|
|
mov ah,02
|
|
|
|
mov dl,34h
|
|
|
|
int 21h
|
|
|
|
jmp mainloop
|
|
|
|
|
|
|
|
space:
|
|
|
|
cmp ax, [lastkeypressed]
|
|
|
|
je mainloop
|
|
|
|
mov [lastkeypressed], ax
|
|
|
|
mov ah,02
|
|
|
|
mov dl,39h
|
|
|
|
int 21h
|
|
|
|
jmp mainloop
|
|
|
|
|
|
|
|
lalt:
|
|
|
|
cmp ax, [lastkeypressed]
|
|
|
|
je mainloop
|
|
|
|
mov [lastkeypressed], ax
|
|
|
|
mov ah,02
|
|
|
|
mov dl,38h
|
|
|
|
int 21h
|
|
|
|
jmp mainloop
|
|
|
|
|
2020-06-06 13:47:22 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2020-06-06 13:17:39 +02:00
|
|
|
;Data segment
|
2020-06-06 13:47:22 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2020-06-06 13:17:39 +02:00
|
|
|
|
2020-06-07 14:10:33 +02:00
|
|
|
segment DataSeg
|
|
|
|
use16
|
|
|
|
|
2020-06-06 13:17:39 +02:00
|
|
|
lastkeypressed: db 0
|
2020-06-07 17:47:54 +02:00
|
|
|
seed: dw 0
|
|
|
|
minecount: db 0
|
2020-06-07 14:10:33 +02:00
|
|
|
;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
|
2020-06-07 18:36:43 +02:00
|
|
|
map: dw COLUMNS * LINES dup 00h
|
2020-06-07 14:10:33 +02:00
|
|
|
|
|
|
|
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
|
2020-06-07 17:47:54 +02:00
|
|
|
|
|
|
|
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
|