-
Notifications
You must be signed in to change notification settings - Fork 0
/
remaining.z80
308 lines (284 loc) · 12.1 KB
/
remaining.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
tiles_drawn_last_time: defb 0
tiles_drawn_this_time: defb 0
; redraw_remaining_tiles_flags needs a bit of explanation
; if bit 0 is set: tiles are reordered since last time
; (this happens entirely within the render_remaining_tiles loop)
; if bit 1 is set: force redraw all tiles (including the 'x' which
; we would ordinarily skip after drawing it when level begins)
; (i.e. this flag is only set on the initial play field draw)
; if bit 2 is set: external game logic wants to trigger a redraw
; of the remaining tiles
redraw_remaining_tiles_flags: defb 0
REMAINING_REORDERED: equ 1
REMAINING_REDRAW_ALL_FORCE: equ 2
REMAINING_REDRAW_TRIGGER: equ 4
init_remaining_tiles_region:
ld c, 6
ld de, REMAINING_TILES_Y_OFFSET*128+(REMAINING_TILES_X_OFFSET_LEFT/2) - 2 - 4*128
@l2:
push de
ld b, 5
@l1:
push de
push bc
ld a, 0x00 ; BLACK
call fillrect_16x16_de_colorbyte_a
pop bc
pop de
ld a, e
add 8
ld e, a
djnz @-l1
pop de
ld a, d
add 8
ld d, a
dec c
jp nz, @-l2
ret
@draw_the_x:
ld hl, remaining_x+1
ld a, (ix+0)
add 48
ld (hl), a
dec hl
ld a, e
add REMAINING_TILES_TEXT_X_OFFSET/2
ld e, a
ld c, 0x11 ; WHITE
call print_text_hl_de
jp @done_drawing_this_tile
render_remaining_tiles:
; this draws the bitmaps AND the counts.
; but only draws what it needs to (compared to what it
; drew last time, and whether anything changed)
ld a, (redraw_remaining_tiles_flags)
and REMAINING_REDRAW_ALL_FORCE + REMAINING_REDRAW_TRIGGER ; need to draw?
ret z
; start off assuming tiles are not reordered
; (the above AND will have cleared the REMAINING_REORDERED flag)
; (the 'force' flag might be set though)
ld (redraw_remaining_tiles_flags), a
; We also need to count how many tiles we draw (starting from zero)
xor a
ld (tiles_drawn_this_time), a
; get setup to draw the first (top left) tile
ld ix, remaining_tiles
ld de, REMAINING_TILES_Y_OFFSET*128+(REMAINING_TILES_X_OFFSET_LEFT/2)
ld b, 8
ld c, 4 ; how many remaining in this column (we show two columns of four)
@next_tile:
; Work out what to draw and when to draw it
; First, assume the 'reordered' flag is clear
;
; If the reordered flag is still clear, and the count for this tile
; is the same as last time, do nothing for this tile
; If the reordered flag is still clear, and the count for this tile is
; different, but still > 0, then draw just the count
; If the count is zero (and wasn't last time, as already covered),
; then set the reordered flag to remind us that the
; order has now changed (but since the count is zero, don't need to
; draw this actual tile)
; If the reordered flag is set, draw the bitmap (and count) for this tile
; 1. Is the reordered flag set (or the force flag)? if so, need to redraw everything
; (except zero tiles)
ld a, (redraw_remaining_tiles_flags)
and REMAINING_REORDERED + REMAINING_REDRAW_ALL_FORCE
jr nz, @+reordered
; 2. Not reordered. Is the count the same as last time?
ld a, (ix+0) ; a = count of the "L"'th tile
cp (ix+8) ; compare with count of the "L"'th tile last time
jr z, @+same_as_last_time
; 3. ok, not the same as last time. Is it zero this time?
and a
jr nz, @+not_zero_must_just_be_different
ld a, (redraw_remaining_tiles_flags) ; it was zero. set the reordered flag, skip this tile
or REMAINING_REORDERED
ld (redraw_remaining_tiles_flags), a
jp @+skip_zero
@not_zero_must_just_be_different:
; 3. just draw the number
push bc
push de
ld a, d
add REMAINING_TILES_TEXT_Y_OFFSET/2
ld d, a
ld a, e
add REMAINING_TILES_TEXT_X_OFFSET/2 + 4 ; + 4 to skip the x and move to the digit
ld e, a
ld a, (ix+0)
ld c, 0x11 ; WHITE
call digit_a_xy_de
jp @+done_drawing_this_tile
@same_as_last_time:
; either was a zero this time (and last time)
; or was the same tile with the same remaining quantity this time and last time
; Figure out which and continue the loop, missing out the redrawing
; in the latter case since that's the whole point of this logic :-)
and a
jr z, @+skip_zero
jp @+totally_optimized_out_drawing_this_tile
@reordered:
; the order of this tile (or a previous one) has changed
; since last redraw, so unfortunately we have to draw all
; the bitmaps and counts
; We can still skip tiles with zero count thouh.
; 4. is the count of the "L"'th tile equal to zero
; (if so, don't draw it: we only show the remaining "non-zero" tiles)
ld a, (ix+0) ; a= count of the "L"'th tile
and a
jr z, @+skip_zero
; ok we gotta draw it. ah well, we tried to avoid this but
; sometimes you just gotta.
; find out which tile is the "L"'th tile (i.e. look at lower 3 bits of L)
ld a, ixl
and 7
add NUM_NON_TILES + 1
push bc
push de
push de
call draw_tile_at_de_tile_a
pop de
ld a, d
add REMAINING_TILES_TEXT_Y_OFFSET/2
ld d, a
; can we skip drawing the 'x'?
ld a, (redraw_remaining_tiles_flags)
and REMAINING_REDRAW_ALL_FORCE
jp nz, @draw_the_x
@skip_drawing_the_x: ; just draw the number (because the 'x' isn't changing)
ld a, e
add 4 + REMAINING_TILES_TEXT_X_OFFSET/2
ld e, a
ld a, (ix+0)
ld c, 0x11 ; WHITE
call digit_a_xy_de
@done_drawing_this_tile:
pop de
pop bc
@totally_optimized_out_drawing_this_tile:
; we drew a tile this time
; (even if we 'skipped it' in the case where the
; tile we should draw is unchanged since last time)
ld hl, tiles_drawn_this_time
inc (hl)
;
dec c
jr z, @next_column
ld a, d
add 8+(REMAINING_TILES_Y_SPACING/2)
ld d, a
@skip_zero:
inc ix
djnz @-next_tile
@remaining_blanks:
; we've finished drawing tiles and remaining counts
; (for the tiles where remaining counts > 0)
; keep a note of how many we drew this time, and compare to how
; many we drew last time.
; if we drew fewer this time, then we need to blank out the rest
ld hl, tiles_drawn_this_time
ld a, (tiles_drawn_last_time)
sub (hl)
jr c, @+DONE ; same number of tiles last time, no need to do any blanking
jr z, @+DONE ; FEWER number of tiles last time, no need to do any blanking
; ok, THIS time had fewer number of tiles
; we drew more tiles last time
; work out how many blanks to draw, and which columns
; if c==0 then left column complete and right column empty
; so blank right column
ld a, c
and a
jr z, @_blank_right_column
; else, if c > 0 (ie. 1, 2, 3, 4) then we didn't fill the
; left coumn, so there's maybe SOME blanking to do
bit 7, c
jr z, @_blank_left_column
; else, blank the right column
@_blank_right_column: ; so we need to blank the right columns
ld a, 4
add c
ret z ; no remaining blanks
ld c, a
@_blank_next_remaining_tile_right_column:
push bc
push de
push de
ld a, 0x00 ; BLACK
call fillrect_16x16_de_colorbyte_a
pop de
ld a, d
add REMAINING_TILES_TEXT_Y_OFFSET/2
ld d, a
ld a, e
add REMAINING_TILES_TEXT_X_OFFSET/2
ld e, a
; draw 16x8
ld a, 0x00 ; BLACK
call fillrect_16x8_de_colorbyte_a
pop de
pop bc
ld a, d
add 8+(REMAINING_TILES_Y_SPACING/2)
ld d, a
dec c
jr nz, @-_blank_next_remaining_tile_right_column
jp @+DONE
@_blank_left_column:
push bc
push de
push de
ld a, 0x00 ; BLACK
call fillrect_16x16_de_colorbyte_a
pop de
ld a, d
add REMAINING_TILES_TEXT_Y_OFFSET/2
ld d, a
ld a, e
add REMAINING_TILES_TEXT_X_OFFSET/2
ld e, a
; draw 16x8
ld a, 0x00 ; BLACK
call fillrect_16x8_de_colorbyte_a
pop de
pop bc
ld a, d
add 8+(REMAINING_TILES_Y_SPACING/2)
ld d, a
dec c
jr nz, @-_blank_left_column
ld c, 0
ld de, REMAINING_TILES_Y_OFFSET*128+(REMAINING_TILES_X_OFFSET_RIGHT/2)
jp @_blank_right_column
@next_column:
; c = 0 i.e. we've drawn four tiles in this column so advance to next column
ld de, REMAINING_TILES_Y_OFFSET*128+(REMAINING_TILES_X_OFFSET_RIGHT/2)
; neat trick, do NOT reset c. c is now zero. On next iteration, c will wrap to 255
; b is the real counter. c just tells us how many are left in this column
inc ix
dec b
jp nz, @-next_tile
jp @-remaining_blanks
@DONE:
; any cleanup / state change
; We drew all the tiles, so we don't need to do it again
; (unless someone sets this flag again)
xor a
ld (redraw_remaining_tiles_flags), a
; copy counts of tiles from last time to this time
; also record the number of tiles drawn THIS time, for NEXT time
ld a, (tiles_drawn_this_time)
ld (tiles_drawn_last_time), a
ld hl, remaining_tiles
ld de, remaining_tiles_last_time
LDI
LDI
LDI
LDI
LDI
LDI
LDI
LDI
ret
remaining_x: defm "*0"
defb 0