-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path58-plot-inverse-pixel-on-inverse-background.asm
208 lines (179 loc) · 7.35 KB
/
58-plot-inverse-pixel-on-inverse-background.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
; Example that is used in following article:
; Vývoj pro ZX Spectrum: dokončení realizace příkazu PLOT
; https://www.root.cz/clanky/vyvoj-pro-zx-spectrum-dokonceni-realizace-prikazu-plot/
;
; This article is part of series:
; "Vývoj pro slavné ZX Spectrum"
; https://www.root.cz/serialy/vyvoj-pro-slavne-zx-spectrum/
;
; Repository:
; https://github.com/tisnik/8bit-fame
;
; Example #58:
; Drawing inverse pixel without erasing background onto screen with inverse ASCII table.
;
; This source code is available at:
; https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/58-plot-inverse-pixel-on-inverse-background.asm
SCREEN_ADR equ $4000
CHAR_ADR equ $3c00
ENTRY_POINT equ $8000
org ENTRY_POINT
; Vstupní bod celého programu
start:
call fill_in_screen ; vyplnění obrazovky ASCII tabulkami
ld b, 0 ; x-ová souřadnice vykreslovaného pixelu
ld c, 0 ; y-ová souřadnice vykreslovaného pixelu
loop:
call plot_inverse ; vykreslení pixelu barvou papíru
call delay
inc b ; posun na další souřadnici
inc c
ld a, b
cp 192 ; test na ukončení smyčky
jr nz, loop ; opakovat, dokud není vykreslena celá šikmá "úsečka"
finito:
jr finito ; ukončit program nekonečnou smyčkou
delay:
; zpožďovací rutina
; nemění žádné registry
push bc ; uschovat hodnoty registrů, které se používají ve smyčkách
ld b, 20 ; počitadlo vnější zpožďovací smyčky
outer_loop:
ld c, 0 ; počitadlo vnitřní zpožďovací smyčky
inner_loop:
dec c ; snížení hodnoty počitadla (v první iteraci 256->255)
jr NZ, inner_loop ; opakovat, dokud není dosaženo nuly
djnz outer_loop ; opakovat vnější smyčku, nyní s počitadlem v B
pop bc ; obnovit hodnoty registrů změněných smyčkami
ret ; návrat z podprogramu
plot_inverse:
; varianta podprogramu pro vykreslení pixelu barvou papíru
;
; parametry:
; B - x-ová souřadnice (v pixelech)
; C - y-ová souřadnice (v pixelech)
call calc_pixel_address ; výpočet adresy pixelu
call calc_pixel_value ; výpočet ukládané hodnoty
ld d, (hl) ; přečíst původní hodnotu osmice pixelů
cpl ; inverze masky
and d ; použít vypočtenou masku pro vynulování jediného bitu
ld (hl), a ; zápis hodnoty pixelu (ostatních sedm pixelů se nezmění)
ret ; návrat z podprogramu
calc_pixel_value:
; parametry:
; B - x-ová souřadnice (v pixelech)
;
; návratové hodnoty:
; A - hodnota pixelu
push bc ; zapamatovat si hodnotu v registru B
ld a, b ; A: X7 X6 X5 X4 X3 X2 X1 X0
and %00000111 ; A: 0 0 0 0 0 X2 X1 X0
ld b, a ; počitadlo smyčky (neměníme příznaky)
ld a, %10000000 ; výchozí maska (neměníme příznaky)
jr z, end_calc ; pokud je nyní souřadnice nulová, zapíšeme výchozí masku + konec
next_shift:
srl a ; posunout masku doprava
djnz next_shift ; 1x až 7x
end_calc:
pop bc ; obnovit hodnotu v registru B
ret ; návrat z podprogramu
calc_pixel_address:
; parametry:
; B - x-ová souřadnice (v pixelech)
; C - y-ová souřadnice (v pixelech)
;
; návratové hodnoty:
; HL - adresa pro zápis pixelu
;
; pozměněné registry:
; A
;
; vzor adresy:
; 0 1 0 Y7 Y6 Y2 Y1 Y0 | Y5 Y4 Y3 X4 X3 X2 X1 X0
ld a, c ; všech osm bitů Y-ové souřadnice
and %00000111 ; pouze spodní tři bity y-ové souřadnice (Y2 Y1 Y0)
; A: 0 0 0 0 0 Y2 Y1 Y0
or %01000000 ; "posun" do obrazové paměti (na 0x4000)
ld h, a ; část horního bajtu adresy je vypočtena
; H: 0 1 0 0 0 Y2 Y1 Y0
ld a, c ; všech osm bitů Y-ové souřadnice
rra
rra
rra ; rotace doprava -> Y1 Y0 xx Y7 Y6 Y5 Y4 Y3
and %00011000 ; zamaskovat
; A: 0 0 0 Y7 Y6 0 0 0
or h ; a přidat k vypočtenému mezivýsledku
ld h, a ; H: 0 1 0 Y7 Y6 Y2 Y1 Y0
ld a, c ; všech osm bitů Y-ové souřadnice
rla
rla ; A: Y5 Y4 Y3 Y2 Y1 Y0 xx xx
and %11100000 ; A: Y5 Y4 Y3 0 0 0 0 0
ld l, a ; část spodního bajtu adresy je vypočtena
ld a, b ; všech osm bitů X-ové souřadnice
rra
rra
rra ; rotace doprava -> 0 0 0 X7 X6 X5 X4
and %00011111 ; A: 0 0 0 X7 X6 X5 X4 X3
or l ; A: Y5 Y3 Y3 X7 X6 X5 X4 X3
ld l, a ; spodní bajt adresy je vypočten
ret ; návrat z podprogramu
fill_in_screen:
; Vyplnění obrazovky snadno rozpoznatelným vzorkem - ASCII tabulkami
;
; vstupy:
; žádné
ld de, SCREEN_ADR ; adresa pro vykreslení prvního bloku znaků
call draw_ascii_table_inv ; vykreslení 96 znaků
call draw_ascii_table_inv ; vykreslení 96 znaků
call draw_ascii_table_inv ; vykreslení 96 znaků
call draw_ascii_table_inv ; vykreslení 96 znaků
ret ; návrat z podprogramu
draw_ascii_table_inv:
; Vytištění ASCII tabulky inverzně (barva inkoustu je barvou pozadí a naopak)
;
; vstupy:
; DE - adresa v obrazové paměti pro vykreslení znaku
ld a, ' ' ; kód vykreslovaného znaku
next_char:
push af ; uschovat akumulátor na zásobník
call draw_char_inv ; zavolat subrutinu pro vykreslení znaku
ld a, ' ' ; vykreslit za znakem mezeru
call draw_char_inv ; zavolat subrutinu pro vykreslení znaku
pop af ; obnovit akumulátor ze zásobníku
inc a ; ASCII kód dalšího znaku
cp ' ' + 96 ; jsme již na konci ASCII tabulky?
jr nz, next_char ; ne? potom pokračujeme
ret ; návrat z podprogramu
draw_char_inv:
; Vytištění jednoho inverzního znaku na obrazovku
;
; vstupy:
; A - kód znaku pro vykreslení
; DE - adresa v obrazové paměti pro vykreslení znaku
;
; výstupy:
; DE - adresa v obrazové paměti pro vykreslení dalšího znaku
;
; změněné registry:
; všechny
ld bc, CHAR_ADR ; adresa, od níž začínají masky znaků
ld h, c ; C je nulové, protože CHAR_ADR=0x3c00
ld l, a ; kód znaku je nyní ve dvojici HL
add hl, hl ; 2x
add hl, hl ; 4x
add hl, hl ; 8x
add hl, bc ; přičíst bázovou adresu masek znaků
ld b, 8 ; počitadlo zapsaných bajtů
ld c, d
loop2:
ld a,(hl) ; načtení jednoho bajtu z masky
cpl ; negace hodnoty v akumulátoru
ld (de),a ; zápis hodnoty na adresu (DE)
inc l ; posun na další bajt masky (nemusíme řešit přetečení do vyššího bajtu)
inc d ; posun na definici dalšího obrazového řádku
djnz loop2 ; vnitřní smyčka: blok s osmi zápisy
inc e
ret z ; D+=8,E=E+1=0
ld d, c
ret ; D=D,E=E+1
end ENTRY_POINT