-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmenu.z80
449 lines (417 loc) · 10.3 KB
/
menu.z80
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
;;; menu.z80
menu_txt:
.dw $0505 ; x and y coordinates of menu
.db 4 ; width of menu (in bytes: sets of 8 pixels)
.db 3 ; # of menu options
.db "Option 1", 0
.db "Option 2", 0
.db "Option 3", 0
buildUnit_txt:
.dw $0503 ;XXYY x and y coordinates of menu
.db 4 ; width of menu (in bytes: sets of 8 pixels)
.db 18 ; # of menu options
.db "Infantry", 0
.db "Mech", 0
.db "Heavy Tank", 0
.db "Medium Tank", 0
.db "Small Tank", 0
.db "Recon", 0
.db "Transport", 0
.db "Giga Tank", 0
;;.db "Supply Truck",0
.db "Artillery", 0
.db "Rockets", 0
;;.db "Rail Turtle", 0
.db "AA Artillery", 0
.db "AA Tank", 0
.db "AA Missles", 0
.db "Fighter", 0
.db "Bomber", 0
.db "Assault Fgtr", 0
.db "Btl Copter", 0
.db "Trns Copter", 0
menuOptions: ; total number of items in the menu
.db 0
selected: ; currently selected option (0-X)
.db 0
menuCursorX:
.db 0
menuCursorY:
.db 0
textPos: ; pointer to the start of text data in the gbuf
.dw $0000
menuTop: ; id of first menu item shown on screen
.db 0
rectXY: ; $YYXX
.dw $0000
rectWH: ; $HHWW
.dw $0000
cursor_sprite:
.db %00100000
.db %00110000
.db %00111000
.db %00110000
.db %00100000
;; Run when user presses 2nd on the map
mapMenu:
ld bc, (cursorX) ; c = x, b = y
call getTile
;; hl points to tile position
ld a, (hl)
ld hl,buildUnit_txt
call loadScrollMenu
ret
loadScrollMenu:
push hl ; hl points to menu data
bcall(_GrBufClr)
pop hl
push hl
inc hl
inc hl
inc hl
ld a,(hl) ; number menu options = number of strings to draw
ld (menuOptions),a
ld b,a
inc hl
ld de,$0006 ; start at the top left of the buffer (with space for cursor)
drawStrings_loop: ; this draws all of our strings to the graph buffer in 2 columns
push bc ; save the counter
push de ; save our pencol value
ld (penCol),de
bcall(_VPutS)
pop de ; restores penCol/penRow to their previous value
pop bc
ld a,d ; move 6 pixels down
add a,6 ; remember, d holds the MSB, which gets drawn to (penRow)
ld d,a
cp 64-6 ; check if we've reached bottom of screen
jr c,$+5
ld de,$0036 ; if so, set penRow to 0 and draw in next column
djnz drawStrings_loop
ld hl,gbuf-6 ; because we add 6 to hl in the copyToStringBuf routine
ld de,appBackUpScreen
ld a,20 ; max number of entries
copyToStringBuf:
ld b,6 ; each line of text is 6 pixels tall
copyToStringBuf_loop:
push bc
ld bc,6 ; buffer is 12 bytes wide, with two columns, 6 bytes wide each
add hl,bc ; skips the other half of the graphbuffer
ldir ; copy the six bytes in gbuf to appBackupScreen
pop bc
djnz copyToStringBuf_loop
cp 11 ; if a = 10, then we need to draw the right side of the buffer
jr nz,$+5
ld hl,gbuf ; when we add 6, this will point to the right half
ld b,6
dec a
jr nz,copyToStringBuf
pop hl
ld e, (hl) ; x coord
inc hl
ld d, (hl) ; y coord
ld (rectXY),de
inc hl
ld c, (hl) ; width
ld b,(6*8)+1 ; height of textbox: 6 pixels*8 entries + 1 pixel beneath the text
ld (rectWH),bc
;; push de ; de = x/y coords of menu, we need to calculate text position
;; call drawRectangle
;; pop de
inc d ; + 1 jump past the top of the rectangle
ld hl,gbuf
ld c,e
ld b,0
add hl,bc
ld a,d
add a,a ; a*12 should hopefully fit in 8-bits
add a,d ; .. because the scrolling menu has to start off
add a,a ; .. high on the screen, or else it won't fit
add a,a ; a*12
ld c,a
add hl,bc
ld (textPos),hl ; this is where we will start copying the text in appBackupScreen to
ld a,e
add a,a
add a,a
add a,a ; x position was byte-aligned, so we must *8
ld e,a
inc d
ld (menuCursorX),de ; save cursor x and y values
xor a
ld (selected),a ; reset cursor to first menu item (position 0)
ld (menuTop),a
;; redraw the background
call drawTilemap ; draws our tilemap to the gbuf
call drawCursorOn ; draws the cursor over top of the gbuf
menuScroll:
ld de,(rectXY)
ld bc,(rectWH)
call drawRectangle
call fillTextBox
call drawMenuCursor ; draw sprite
call ionFastCopy
;; check if a key was pressed to quit the menu
ld a,group5
call getKey
rla
jp nc,quitMenu
ld a,group1
call getKey
cp diClear
jp z,quitMenu
ld a,group6
call getKey
cp di2nd
ld a,(selected)
jp z,releaseKeys
ld hl,menuScroll ; put menuScroll on the stack
push hl ; .. ret will jump to menuScroll
;; check keys
ld b,7 ; the delay's mask, must be all 1's: %1, %11, %111, %111, etc.
call slowArrows ; returns c if the delay isn't finished [famwars.z80]
ret c
ld hl,selected
rra ; check for down
jr nc,menuScrollDown ; if the bit is reset, down was pressed
bit 2,a
jr z,menuScrollUp ; normally up is the third bit, but here it's bit 2 because of the rra
ret
menuScrollUp:
;; check if cursor is at position 0, if so can't continue
ld a,(hl)
or a
ret z
ld a,(hl)
dec (hl) ; decreasing selected moves the cursor up
ld hl,menuTop
sub (hl)
ret nz
dec (hl)
ret
menuScrollDown:
;; check if menuOptions-1 = selected
ld a,(menuOptions) ; menuOptions starts at 1, wherease selected starts at 0
dec a ; .. so we need to subtract one
cp (hl) ; hl points to selected
ret z
inc (hl) ; increase selected moves cursor down
ld a,(hl)
ld hl,menuTop
sub (hl)
cp 8
ret c
inc (hl)
ret
;; Fills the text box with the proper text (based on menuTop value)
fillTextBox:
ld a,(menuTop)
ld l,a
add a,a
add a,l
add a,a ; a*6, each menu entry is 6 pixels tall
ld l,a
ld h,0
ld e,l
ld d,h
add hl,hl
add hl,de
add hl,hl ; hl*6, remember buffer is 6 bytes wide
ld de,appBackUpScreen
add hl,de
ex de,hl
ld hl,(textPos)
ld bc,$0806 ; 8 lines of text, 6 rows each
fillText_loopOut:
push bc
fillText_loopMid:
ld b,6 ; 6 bytes (first 6 columns of gbuf)
fillText_loopIn:
ld a,(de) ; text buffer
or (hl) ; graph buffer
ld (hl),a
inc hl
inc de
djnz fillText_loopIn
ld a,c
ld c,6
add hl,bc ; move graph buffer down one row
ld c,a
dec c
jr nz,fillText_loopMid
pop bc
djnz fillText_loopOut
ret
loadMenu:
ld e, (hl) ; x coord
inc hl
ld d, (hl) ; y coord
inc hl
ld c, (hl) ; width
inc hl
ld a, (hl) ; height/# menu options
add a, a ; x2
add a, (hl) ; x3
add a, a ; x6
inc a ; add an extra space underneath the text
ld b, a ; bc = $HHWW
drawMenu:
push de ; de = x/y coords of menu, we need to calculate text position
push hl ; hl = pointer to start of text data
call drawRectangle
pop hl
pop de
ld b,(hl) ; # menu options
ld a,b ; save number of menu options
ld (menuOptions),a ; .. so we can use it in the cursor routine
inc hl ; start of text data
inc d ; + 1 jump past the top of the rectangle
ld a,e
add a,a
add a,a
add a,a ; x position was byte-aligned, so we must *8
ld e,a
inc d
ld (menuCursorX),de ; save cursor x and y values
dec d
add a,6 ; shift text 6 pixels to the right (don't draw over top of box border)
ld e,a
drawMenu_loop:
push bc
push de
ld (penCol),de
bcall(_VPutS)
pop de
pop bc
ld a,d
add a,6
ld d,a
djnz drawMenu_loop
call releaseKeys
xor a
ld (selected),a ; reset cursor to first menu item (position 0)
menuCursor:
call drawMenuCursor ; draw sprite
call ionFastCopy
call drawMenuCursor ; erase sprite
;; check if a key was pressed to quit the menu
ld a,group5
call getKey
rla
jr nc,quitMenu
ld a,group1
call getKey
cp diClear
jr z,quitMenu
ld a,group6
call getKey
cp di2nd
ld a,(selected)
jp z,releaseKeys
ld hl,menuCursor ; put menuCursor on the stack
push hl ; .. ret will jump to menuCursor
;; check keys
ld b,7 ; the delay's mask, must be all 1's: %1, %11, %111, %111, etc.
call slowArrows ; returns c if the delay isn't finished [famwars.z80]
ret c
ld hl,selected
rra ; check for down
jr nc,menuCursorDown ; if the bit is reset, down was pressed
bit 2,a
jr z,menuCursorUp ; normally up is the third bit, but here it's bit 2 because of the rra
ret
menuCursorUp:
;; check if cursor is at position 0, if so can't continue
ld a,(hl)
or a
ret z
dec (hl) ; decreasing selected moves the cursor up
ret
menuCursorDown:
;; check if menuOptions-1 = selected
ld a,(menuOptions) ; menuOptions starts at 1, wherease selected starts at 0
dec a ; .. so we need to subtract one
cp (hl) ; hl points to selected
ret z
inc (hl) ; increase selected moves cursor down
ret
drawMenuCursor:
ld hl,menuTop ; the first menu item on screen
ld a,(selected) ; currently selected option
sub (hl) ; selected item - top menu item = cursor's position
ld l,a
add a,a ; x2
add a,l ; x3
add a,a ; x6
ld hl,(menuCursorX)
add a,h
ld e,a
ld a,l
ld b,5
ld ix,cursor_sprite
jp drawSprite_var
quitMenu:
scf
jp releaseKeys
;; Input:
;; X = c, Y = b
;; Output: tile in tilemap - hl
getTile:
ld hl, (mapWidth)
call multBL
add hl, bc
ld de, (mapPtr)
add hl, de
ret
;; multiplies HL=B*L
multBL:
ld e, l ; ld de,hl
ld d, 0
ld h, d ; clear out upper byte of HL
ld l, d
_:
add hl, de ; hl+de b times
djnz -_
ret
;;######################
drawRectangle:
;;# draws an outlined rectangle
;;# input:
;;# - de = starting x/y (de = $YYXX)
;;# - bc = width (in bytes) and height (pixels): $HHWW
;;######################
ld a, e ; x
ld l, d ; y
push bc ; save width/height
call getGbufOffset ; first find position in gbuf
pop bc ; c = width, b = height of rectangle
ld a, %01111111 ; outer pattern (draw %01111111 on the left, %11111110 on right)
ld e, $FF ; inner pattern: solid line
call rectangleRow ; draw the top row
drawRectangleMiddle:
ld a, %10000000 ; %10000000 on left, %00000001 on right
ld e, %00000000 ; erase what's inside
call rectangleRow ; draw the row
djnz drawRectangleMiddle ; repeat rectangleHeight times
ld a, %01111111 ; now draw the bottom row
ld e, $FF ; a solid line
;;a = outer byte
;;e = inner byte
rectangleRow:
push bc
ld (hl), a ; outer pattern into the address of hl
inc hl ; next byte in gbuf
ld b, c ; b = width
rectangleRow_loop:
ld (hl), e ; store inner pattern ($FF or $00)
inc hl ; next byte
djnz rectangleRow_loop ; repeat
rlca ; rotate outer byte (rotate left through carry accumulator)
ld (hl), a ; save right side of rectangle
pop bc ; restore width/height
ld a, 11
sub c ; c actually = width -1, since the first byte is drawn outside of the loop
ld d, 0
ld e, a
add hl, de ; add offset to gbuf (next row)
ret