forked from NEO-SPECTRUMAN/SpecEmu
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathPentagonRenderer.asm
308 lines (235 loc) · 8.9 KB
/
PentagonRenderer.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
ASSUME ESI: PTR SpectrumGfx
PentagonPrepTopBorder:
mov [esi].ScreenVector, OFFSET PE_DrawTopBorder
mov [esi].UDCnt, 320/2
Align 16
PE_DrawTopBorder:
mov eax, [esi].BorderColour
PE_DrawTopBorder_1:
inc [esi].WaitTState
cmp ax, [edi]
jne PE_DTB_Changed
add edi, 2
dec [esi].UDCnt
jz PE_NextTopBorderLine
cmp ebx, [esi].WaitTState
jnc PE_DrawTopBorder_1
ret
PE_DTB_Changed:
mov [esi].ScreenVector, OFFSET PE_DrawTopBorder_Write
mov byte ptr [ebp], 1
mov [esi].FrameChanged, TRUE
jmp PE_DTB_Write
Align 16
PE_DrawTopBorder_Write:
mov eax, [esi].BorderColour
PE_DrawTopBorder_2:
inc [esi].WaitTState
PE_DTB_Write:
mov [edi], ax
add edi, 2
dec [esi].UDCnt
jz PE_NextTopBorderLine
cmp ebx, [esi].WaitTState
jnc PE_DrawTopBorder_2
ret
Align 4
PE_NextTopBorderLine:
NEXTSCANLINEADDR
mov eax, [esi].ScanTState
add eax, MACHINE.ScanlineCycles
mov [esi].ScanTState, eax
mov [esi].WaitTState, eax
add ebp, 3
dec [esi].TopBorderCnt
jz PE_PrepLeftBorder ; top border finished
mov [esi].ScreenVector, OFFSET PentagonPrepTopBorder
ret
; start actual screen area
Align 4
PE_PrepLeftBorder:
mov [esi].ScreenVector, OFFSET PE_DrawLeftBorder
mov [esi].UDCnt, 32/2
ret
Align 16
PE_DrawLeftBorder:
mov eax, [esi].BorderColour
PE_DrawLB1: inc [esi].WaitTState
.if ax != [edi]
mov [edi], ax
mov byte ptr [ebp], 1
mov [esi].FrameChanged, TRUE
.endif
add edi, 2
dec [esi].UDCnt
jz PE_PrepDisplayLine
cmp ebx, [esi].WaitTState
jnc PE_DrawLB1
ret
Align 4
PE_PrepDisplayLine:
inc ebp
sub [esi].WaitTState, 4
mov [esi].UDCnt, 16
mov [esi].FetchCycle, 0
mov [esi].ScreenVector, OFFSET PE_DrawDisplayLine
; prepare display/attr offsets for this scanline
mov eax, [DisplayTablePtr]
mov ecx, [eax]
mov eax, [eax+4]
add [DisplayTablePtr], 8
mov [esi].DisplayOffset, ecx
mov [esi].AttrOffset, eax
ret
Align 16
PE_DrawDisplayLine:
switch [esi].FetchCycle
add [esi].FetchCycle, 1
add [esi].WaitTState, 1
FETCHCYCLEOFFSET = 2
FETCHCYCLEOFFSET = FETCHCYCLEOFFSET - 1 ; safe to assume that the ULA address bus is loaded one cycle before sampling the data bus?
case FETCHCYCLEOFFSET
mov eax, [esi].DisplayOffset
add eax, [esi].zxDisplayOrg
mov al, [eax]
mov [esi].DisplayByte, al
case FETCHCYCLEOFFSET+1
mov eax, [esi].AttrOffset
add eax, [esi].zxDisplayOrg
mov al, [eax]
mov [esi].AttrByte, al
call Render_Pentagon_Character
case FETCHCYCLEOFFSET+2
mov eax, [esi].DisplayOffset
add eax, [esi].zxDisplayOrg
mov al, [eax]
mov [esi].DisplayByte, al
case FETCHCYCLEOFFSET+3
mov eax, [esi].AttrOffset
add eax, [esi].zxDisplayOrg
mov al, [eax]
mov [esi].AttrByte, al
call Render_Pentagon_Character
case 7
mov [esi].FetchCycle, 0
dec [esi].UDCnt
jz PE_PrepRightBorder
endsw
cmp ebx, [esi].WaitTState
jnc PE_DrawDisplayLine
ret
Align 4
PE_PrepRightBorder:
inc ebp
add [esi].WaitTState, 4
mov [esi].ScreenVector, OFFSET PE_DrawRightBorder
mov [esi].UDCnt, 32/2
ret
Align 16
PE_DrawRightBorder:
mov eax, [esi].BorderColour
PE_DrawRB1: inc [esi].WaitTState
.if ax != [edi]
mov [edi], ax
mov byte ptr [ebp], 1
mov [esi].FrameChanged, TRUE
.endif
add edi, 2
dec [esi].UDCnt
jz PE_PrepNextDisplayLine
cmp ebx, [esi].WaitTState
jnc PE_DrawRB1
ret
Align 4
PE_PrepNextDisplayLine:
NEXTSCANLINEADDR
inc [esi].CurrDisplayLine
inc ebp
mov edx, [esi].ScanTState
add edx, MACHINE.ScanlineCycles
mov [esi].ScanTState, edx
mov [esi].WaitTState, edx
cmp [esi].CurrDisplayLine, 192
jnc PE_PrepBottomBorder
mov [esi].ScreenVector, OFFSET PE_PrepLeftBorder
ret
Align 4
PE_PrepBottomBorder:
mov [esi].ScreenVector, OFFSET PE_DrawBottomBorder
mov [esi].UDCnt, 320/2
ret
Align 16
PE_DrawBottomBorder:
mov eax, [esi].BorderColour
PE_DrawBottomBorder_1:
inc [esi].WaitTState
cmp ax, [edi]
jne PE_DBB_Changed
add edi, 2
dec [esi].UDCnt
jz PE_NextBottomBorderLine
cmp ebx, [esi].WaitTState
jnc PE_DrawBottomBorder_1
ret
PE_DBB_Changed:
mov [esi].ScreenVector, OFFSET PE_DrawBottomBorder_Write
mov byte ptr [ebp], 1
mov [esi].FrameChanged, TRUE
jmp PE_DBB_Write
Align 16
PE_DrawBottomBorder_Write:
mov eax, [esi].BorderColour
PE_DrawBottomBorder_2:
inc [esi].WaitTState
PE_DBB_Write:
mov [edi], ax
add edi, 2
dec [esi].UDCnt
jz PE_NextBottomBorderLine
cmp ebx, [esi].WaitTState
jnc PE_DrawBottomBorder_2
ret
Align 4
PE_NextBottomBorderLine:
NEXTSCANLINEADDR
mov eax, [esi].ScanTState
add eax, MACHINE.ScanlineCycles
mov [esi].ScanTState, eax
mov [esi].WaitTState, eax
add ebp, 3
dec [esi].BottomBorderCnt
jz PE_VerticalRetrace ; bottom border finished
mov [esi].ScreenVector, OFFSET PE_PrepBottomBorder
ret
Align 4
PE_VerticalRetrace:
mov [esi].ScreenVector, OFFSET UScrExit
mov [esi].WaitTState, 180000
ret
Render_Pentagon_Character:
movzx eax, [esi].AttrByte ; eax = attribute byte
movzx ecx, [esi].DisplayByte ; ecx = display byte
test eax, 128
je @F ; flash bit clear
and eax, 127 ; clear Flash bit
xor cl, [esi].FlashInverterByte
@@: shl eax, 11 ; * 2048 (256 entries per colour * 8 bytes/entry)
lea eax, [eax+ecx*8] ; 8 bytes/entry
add eax, [esi].ptrSpecColourTable ; offset into DirectDraw colour mapping table
mov ecx, [eax] ; pick up 8 pixel colour values
mov eax, [eax+4]
.if ecx != [edi]
mov [edi], ecx
mov byte ptr [ebp], 1
mov [esi].FrameChanged, TRUE
.endif
.if eax != [edi+4]
mov [edi+4], eax
mov byte ptr [ebp], 1
mov [esi].FrameChanged, TRUE
.endif
add edi, 8
add [esi].DisplayOffset, 1
add [esi].AttrOffset, 1
ret
ASSUME ESI:NOTHING