forked from EtchedPixels/FUZIX
-
Notifications
You must be signed in to change notification settings - Fork 1
/
video.s
426 lines (408 loc) · 6.3 KB
/
video.s
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
.module dragonvideo
; Methods provided
.globl _vid256x192
.globl _plot_char
.globl _scroll_up
.globl _scroll_down
.globl _clear_across
.globl _clear_lines
.globl _cursor_on
.globl _cursor_off
.globl _cursor_disable
.globl _vtattr_notify
.globl _video_read
.globl _video_write
.globl _video_cmd
;
; Imports
;
.globl _fontdata_8x8
.globl _vidattr
include "kernel.def"
include "../kernel09.def"
.area .text
;
; Dragon video drivers
;
; SAM V2=1 V1=1 V0=-
; 6847 A/G=1 GM2=1 GM1=1 GM0=1
;
_vid256x192:
sta $ffc0
sta $ffc3
sta $ffc5
lda $ff22
anda #$07
ora #$f0
sta $ff22
rts
;
; Compute the video base address
; A = X, B = Y
;
vidaddr:
ldy #VIDEO_BASE
exg a,b
leay d,y ; 256 x Y + X
rts
;
; plot_char(int8_t y, int8_t x, uint16_t c)
;
_plot_char:
pshs y
lda 4,s
bsr vidaddr ; preserves X (holding the char)
tfr x,d
andb #$7F ; no high font bits
subb #$20 ; skip control symbols
rolb ; multiply by 8
rola
rolb
rola
rolb
rola
tfr d,x
leax _fontdata_8x8,x ; relative to font
ldb _vtattr
andb #0x3F ; drop the bits that don't affect our video
beq plot_fast
;
; General purpose plot with attributes, we only fastpath
; the simple case
;
clra
plot_loop:
sta _vtrow
ldb _vtattr
cmpa #7 ; Underline only applies on the bottom row
beq ul_this
andb #0xFD
ul_this:
cmpa #3 ; italic shift right for < 3
blt ital_1
andb #0xFB
bra maskdone
ital_1:
cmpa #5 ; italic shift right for >= 5
blt maskdone
bitb #0x04
bne maskdone
orb #0x40 ; spare bit borrow for bottom of italic
andb #0xFB
maskdone:
lda ,x+ ; now throw the row away for a bit
bitb #0x10
bne notbold
lsra
ora -1,x ; shift and or to make it bold
notbold:
bitb #0x04 ; italic by shifting top and bottom
beq notital1
lsra
notital1:
bitb #0x40
beq notital2
lsla
notital2:
bitb #0x02
beq notuline
lda #0xff ; underline by setting bottom row
notuline:
bitb #0x01 ; inverse or not: we are really in inverse
bne plot_inv ; by default so we complement except if
coma ; inverted
plot_inv:
bitb #0x20 ; overstrike or plot ?
bne overstrike
sta ,y
bra plotnext
overstrike:
anda ,y
sta ,y
plotnext:
leay 32,y
lda _vtrow
inca
cmpa #8
bne plot_loop
puls y,pc
;
; Fast path for normal attributes
;
plot_fast:
lda ,x+ ; simple 8x8 renderer for now
coma
sta 0,y
lda ,x+
coma
sta 32,y
lda ,x+
coma
sta 64,y
lda ,x+
coma
sta 96,y
lda ,x+
coma
sta 128,y
lda ,x+
coma
sta 160,y
lda ,x+
coma
sta 192,y
lda ,x+
coma
sta 224,y
puls y,pc
;
; void scroll_up(void)
;
_scroll_up:
pshs y
ldy #VIDEO_BASE
leax 256,y
vscrolln:
; Unrolled line by line copy
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
ldd ,x++
std ,y++
cmpx video_endptr
bne vscrolln
puls y,pc
;
; void scroll_down(void)
;
_scroll_down:
pshs y
ldy #VIDEO_END
leax -256,y
vscrolld:
; Unrolled line by line loop
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
ldd ,--x
std ,--y
cmpx video_startptr
bne vscrolld
puls y,pc
video_startptr:
.dw VIDEO_BASE
video_endptr:
.dw VIDEO_END
;
; clear_across(int8_t y, int8_t x, uint16_t l)
;
_clear_across:
pshs y
lda 4,s ; x into A, B already has y
jsr vidaddr ; Y now holds the address
tfr x,d ; Shuffle so we are writng to X and the counter
tfr y,x ; l is in d
lda #$ff
clearnext:
sta ,x
sta 32,x
sta 64,x
sta 96,x
sta 128,x
sta 160,x
sta 192,x
sta 224,x
leax 1,x
decb
bne clearnext
puls y,pc
;
; clear_lines(int8_t y, int8_t ct)
;
_clear_lines:
pshs y
clra ; b holds Y pos already
jsr vidaddr ; y now holds ptr to line start
tfr y,x
ldd #$ffff
lsl 4,s
lsl 4,s
lsl 4,s
wipel:
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
std ,x++
dec 4,s ; count of lines
bne wipel
puls y,pc
_cursor_on:
pshs y
lda 4,s
jsr vidaddr
tfr y,x
puls y
stx cursor_save
; Fall through
_cursor_off:
ldb _vtattr
bitb #0x80
bne nocursor
ldx cursor_save
com ,x
com 32,x
com 64,x
com 96,x
com 128,x
com 160,x
com 192,x
com 224,x
nocursor:
_vtattr_notify:
_cursor_disable:
rts
;
; These routines wortk in both 256x192x2 and 128x192x4 modes
; because everything in the X plane is bytewide.
;
_video_write:
clra ; clr C
bra tfr_cmd
_video_read:
coma ; set C
bra tfr_cmd ; go
;;; This does the job of READ & WRITE
;;; takes: C = direction 0=write, 1=read
;;; takes: X = transfer buffer ptr + 2
tfr_cmd:
pshs u,y ; save regs
orcc #$10 ; turn off interrupt - int might remap kernel
ldd #$80c0 ; this is writing
bcc c@ ; if carry clear then keep D write
exg a,b ; else flip D: now is reading
c@ sta b@+1 ; !!! self modify inner loop
stb b@+3 ; !!!
bsr vidptr ; U = screen addr
tfr x,y ; Y = ptr to Height, width
leax 4,x ; X = pixel data
;; outter loop: iterate over pixel rows
a@ lda 3,y ; count = width
pshs u ; save screen ptr
;; inner loop: iterate over columns
;; modify mod+1 and mod+3 to switch directions
b@ ldb ,x+ ; get a byte from src
stb ,u+ ; save byte to dest
deca ; bump counter
bne b@ ; loop
;; increment outer loop
puls u ; restore original screen ptr
leau 32,u ; add byte span of screen (goto next line)
dec 1,y ; bump row counter
bne a@ ; loop
puls u,y,pc ; restore regs, return
;
; Find the address we need on a pixel row basis
;
vidptr:
ldu #VIDEO_BASE
ldd ,x++ ; Y into B
lda #32
mul
leau d,u
ldd ,x++ ; X
leau d,u
rts
_video_cmd:
pshs u
bsr vidptr ; u now points to the screen
nextline:
pshs u ; save it for the next line
nextop:
ldb ,x+ ; op code, 0 = end of line
beq endline
oploop:
lda ,u ; do one screen byte
anda ,x
eora 1,x
sta ,u+
decb
bne oploop ; keep going for run
leax 2,x
bra nextop ; next triplet
endline:
puls u ; get position back
leau 32,u ; down one scan line
ldb ,x+ ; get next op - 0,0 means end and done
bne oploop
puls u,pc
.area .data
cursor_save:
.dw 0
_vtrow:
.db 0