-
Notifications
You must be signed in to change notification settings - Fork 2
/
utils.asm
124 lines (103 loc) · 2.78 KB
/
utils.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
global getkey
global sleep
global draw_cell
global cls
global shutdown
bits 16
CELL_SIZE equ 10
X_CELL_COUNT equ 32
X_RESOLUTION equ 320
VGA_SEGMENT equ 0xA000
section .text
getkey:
; Not using the stack so not pushing ebp etc
; int16/ah=11h: Keyboard: Check for enhanced stroke
mov ah, 0x11
int 0x16
; ZF clear if keystroke available: return it.
jne return_popped_key
; else: return 0
mov eax, 0
retf
return_popped_key:
; int16/ah=10h: Keyboard: Get enhanced stroke
mov ah, 0x10
int 0x16
; Returns character in AL, scan code in AH. Clear top half of ax
mov ah, 0
retf
sleep:
pushad
; int15/ah=86h: sleep in microseconds
mov ah, 0x86
; cx - high word
; dx - low word
; 150,000 = 0x249F0. Approximate and zero-out dx
mov cx, 0x2
xor dx, dx
int 15h
popad
retf
draw_cell:
; set up stack
pushad
mov ebp, esp
; normally xy = ebp+8, colour = ebp+12 since stack has ret ptr +
; ebp, but I'm using pushad to save bytes, so we have 8 dwords on stack +
; ret ptr. So xy = ebp+36, colour = ebp+40 etc
; set es segment to VGA segment and keep this for the duration of this func
mov eax, VGA_SEGMENT
mov es, ax
; store the remaining Y increments in bx
mov ebx, CELL_SIZE
draw_line:
; decrement Y counter
dec bx
; calculate initial VGA X offset into di
mov eax, [ds:ebp+36] ; load X coord into al, Y coord into ah
mov dl, ah ; load Y coord into dl
mov ecx, CELL_SIZE
mul cl ; mul X coord by 10, store in ax
mov edi, eax ; store result in edi
mov al, dl ; load Y coord into dl
; mov cx, CELL_SIZE -- Don't need to do this, CELL_SIZE already in ecx
mul cl ; mul by 10
add ax, bx ; add on current Y counter
mov ecx, X_RESOLUTION
mul cx ; multiply by X resolution
add di, ax
; write a row of pixels of the given colour
mov ecx, CELL_SIZE
mov al, [ds:ebp+40]
rep stosb
cmp bx, 0
jne draw_line
; who knows what GCC expects; set es back to 0
xor ax, ax
mov es, ax
; tear down stack
mov esp, ebp
popad
retf
cls:
pushad
mov ax, VGA_SEGMENT
mov es, ax ; set es segment
; set game area to grey
mov cx, 320 * 160
xor di, di
mov al, 0x14
rep stosb
; We rely on the buffer starting black to keep the non-game area black.
xor ax, ax
mov es, ax ; reset es segment
popad
retf
shutdown:
mov ax, 0x5301 ; connect to real-mode APM services
xor bx, bx ; device id 0 - APM BIOS
int 0x15 ; call APM
mov ax, 0x5307 ; set power state
mov bx, 0x0001 ; on all devices
mov cx, 0x0003 ; to Off
int 0x15 ; call APM