-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommon.asm
451 lines (371 loc) · 7.18 KB
/
common.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
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
450
451
; Common subroutines.
; The addresses that shall be used to access the currah HW.
; Used for mirroring tests.
address_1000h: defw 1000h
address_3000h: defw 3000h
address_3001h: defw 3001h
; Access the currah HW always with these routines.
; Write to address 1000h.
; a contains the byte to write.
write_1000h:
push hl
ld hl,(address_1000h)
ld (hl),a
pop hl
ret
; Read from address 1000h.
; Returns: a
read_1000h:
push hl
ld hl,(address_1000h)
ld a,(hl)
call display_vert_a
pop hl
ret
; Intonation.
; Write to address 3000h or 3001h
; de contains the pointer to address_3000h or address_3001h
write_300xh:
push hl
ex de,hl ; ld hl from de
push bc
ld c,(hl)
inc hl
ld b,(hl)
dec hl
push af
write_3000xh_self_modifying_code:
ld (bc),a
nop
pop af
pop bc
ex de,hl
pop hl
ret
write_300xh_mem_write:
ld (bc),a
nop
write_300xh_mem_read:
ld a,(bc)
nop
write_300xh_out:
out (c),a
write_300xh_in:
in a,(c)
; Sets the access to the 300xh addresses.
; mem write, read on in/out.
set_300xh_mem_write:
ld hl,write_300xh_mem_write
set_300xh:
ld bc,2
ld de,write_3000xh_self_modifying_code
ldir
ret
set_300xh_mem_read:
ld hl,write_300xh_mem_read
jr set_300xh
set_300xh_out:
ld hl,write_300xh_out
jr set_300xh
set_300xh_in:
ld hl,write_300xh_in
jr set_300xh
; Default initialization for the read/write routines.
; Uses 100h, 3000h and 3001 as addresses and memory read/write
; to access the addresses.
set_read_write_defaults:
; Use mem write for intonation
call set_300xh_mem_write
; Use address 3000h/3001h for intonation
ld hl,3000h
ld (address_3000h),hl
ld hl,3001h
ld (address_3001h),hl
; Use address 1000h fo6683r read/write allophone
ld hl,1000h
ld (address_1000h),hl
ret
; Turns the currah access (to 1000h and 3000/1h) on.
turn_currah_on:
; check if rom is enabled
ld a,(CS_ROM_VALUE_ADDRESS)
cp CS_ROM_VALUE
ret z ; Return if already enabled
; enable currah with a mem read
ld a,(0038h)
ret
; Turns the currah access (to 1000h and 3000/1h) off.
turn_currah_off:
; check if rom is enabled
ld a,(CS_ROM_VALUE_ADDRESS)
cp CS_ROM_VALUE
ret nz ; Return if already disabled
; disable currah with a mem read
ld a,(0038h)
ret
; Writes the output of a as a byte to the screen.
; Afterwards increases the y-position.
; Used to output the contents of the byte read from 1000h.
display_vert_a:
push hl
; just show in case of a change.
ld hl,display_prev_val
cp (hl)
jr z,display_vert_a_end
push af
; store current value
ld (hl),a
; has changed, so display it
ld hl,(display_ptr)
ld (hl),a
; increment y
inc h
ld a,h
and 07h
jr nz,display_l1
; overflow
ld a,h
sub a,08h ; correct h
ld h,a
; increment l
ld a,l
add a,020h
ld l,a
jr nc,display_l1
; overflow again to h
ld a,h
add a,08h
ld h,a
display_l1:
; check if too big
ld a,h
and 00011000b
xor 00011000b
jr nz,display_l2
; too big
ld l,DISPLAY_START_Y/8*020h
ld h,01000000b+(DISPLAY_START_Y & 0111b)
display_l2:
ld (display_ptr),hl
pop af
display_vert_a_end:
pop hl
ret
defc DISPLAY_START_Y = 17
display_ptr: defb DISPLAY_START_Y/8*020h, 01000000b+(DISPLAY_START_Y & 0111b)
display_prev_val: defb 0
; The print routines call the ZX Spectrum.
; Therefore the Currah ROM needs to be turned off.
print_string:
call turn_currah_off
jp print_string_address
print_number:
call turn_currah_off
jp print_number_address
; prints a hex number in bc.
print_hex_number:
call turn_currah_off
push bc
ld a,b
srl a
srl a
srl a
srl a
call print_hex_a
pop bc
ld a,b
and a,0fh
push bc
call print_hex_a
pop bc
push bc
ld a,c
srl a
srl a
srl a
srl a
call print_hex_a
pop bc
ld a,c
and a,0fh
jp print_hex_a
print_hex_a:
add '0'
cp '9'+1
jr c,print_hex_number_l1
add 'A'-'0'-10
print_hex_number_l1:
rst 10h
ret
; Clears left side and bottom 3rd.
clear_left_and_bottom:
; save
push af
push hl
push de
push bc
; left
xor a
ld hl,SCREEN
ld b,SCREEN_HEIGHT
ld de,SCREEN_WIDTH_IN_BYTES
clear_left_and_bottom_loop:
ld (hl),a
add hl,de
djnz clear_left_and_bottom_loop
; bottom
ld hl,SCREEN+16*SCREEN_WIDTH_IN_BYTES*8
ld de,SCREEN+16*SCREEN_WIDTH_IN_BYTES*8+1
ld bc,8*SCREEN_WIDTH_IN_BYTES*8-1
ld (hl),a
ldir
; restore
pop bc
pop de
pop hl
pop af
ret
; Displays the contents of all bits of a horizontally.
; Like an oszilloscope.
; Bit 0 is the lowest line, bit 7 the topmost.
; 'display_hor_a_delay_value' should be set to a suitable value.
; Depending on the caller function the drawn lines might be fast or slow.
; With this value the drawing speed can be adjusted.
display_hor_a:
ld (display_hor_a_value),a
; check if address needs to be incremented.
ld hl,display_hor_a_counter
dec (hl)
jr nz,display_hor_a_no_inc
ld a,(display_hor_a_delay_value)
ld (hl),a
ld a,(display_hor_a_rotation)
; rotate
rrc a
ld (display_hor_a_rotation),a
jr nc,display_hor_a_no_inc
; increment screen address
ld hl,(display_hor_a_address)
inc hl
ld (display_hor_a_address),hl
; check overflow
ld a,l
and 00011111b
call z,reset_display_hor_a
; clear all lines
xor a
ld de,-(00100000b)
set 2,h
ld (hl),a
inc h
ld (hl),a
add hl,de
ld (hl),a
dec h
ld (hl),a
add hl,de
ld (hl),a
inc h
ld (hl),a
add hl,de
ld (hl),a
dec h
ld (hl),a
res 2,h
ld de,00100000b
ld (hl),a
inc h
ld (hl),a
add hl,de
ld (hl),a
dec h
ld (hl),a
add hl,de
ld (hl),a
inc h
ld (hl),a
add hl,de
ld (hl),a
dec h
ld (hl),a
display_hor_a_no_inc:
ld de,-(00100000b)
; Display 1's in a
ld hl,(display_hor_a_address)
ld a,(display_hor_a_value)
call sub_display_hor_values
; Display 0's in a
ld hl,(display_hor_a_address)
inc h ; 0's
ld a,(display_hor_a_value)
xor 0ffh
call sub_display_hor_values
ret
; Displays either 0 or 1 points.
sub_display_hor_values:
ld b,4
ld c,a
display_hor_a_loop_ones:
set 2,h
rrc c ; rotate with carry
jr nc,display_hor_a_l1
; write to screen
ld a,(display_hor_a_rotation)
or (hl)
ld (hl),a
display_hor_a_l1:
; next bit, next line
res 2,h
rrc c ; rotate with carry
jr nc,display_hor_a_l2
; write to screen
ld a,(display_hor_a_rotation)
or (hl)
ld (hl),a
display_hor_a_l2:
; next bit, next line
add hl,de
djnz display_hor_a_loop_ones
ret
; Rests the values for the display_hor_a subroutine, so that it
; starts again on the left side.
reset_display_hor_a:
ld hl,0101010011100001b
ld (display_hor_a_address),hl
ld a,00000001b
ld (display_hor_a_rotation),a
ld a,(display_hor_a_delay_value)
ld (display_hor_a_counter),a
ret
; Pointer to current screen address, rotation and delay counter.
display_hor_a_address: defw 0
display_hor_a_rotation: defb 0
display_hor_a_counter: defb 0
display_hor_a_delay_value: defb 0
; Temporary store for the bits in a
display_hor_a_value: defb 0
; Displays for all 8 horizontal lines a marker indicating 0 at the left side.
display_hor_zero_markers:
call reset_display_hor_a
inc h
; set zero markers
ld a,00011100b
ld de,-(00100000b)
set 2,h
ld (hl),a ; zero marker
add hl,de
ld (hl),a ; zero marker
add hl,de
ld (hl),a ; zero marker
add hl,de
ld (hl),a ; zero marker
res 2,h
ld de,00100000b
ld (hl),a ; zero marker
add hl,de
ld (hl),a ; zero marker
add hl,de
ld (hl),a ; zero marker
add hl,de
ld (hl),a ; zero marker
ret