-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathline.asm
483 lines (464 loc) · 11 KB
/
line.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
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
; RAM locations
SCREEN_LOC = $1e00
COLOR_LOC = $9600
BASIC_LOC = $1001
CHAR_LOC = $1800
; VIC registers
VIC_HORIZ = $9000
VIC_VERT = $9001
VIC_COLS = $9002
VIC_ROWS = $9003
VIC_RASTER = $9004
VIC_CHARLOC = $9005
VIC_MULTIC = $900e
;VIC_COLORS_LOC = $900f ; %11110000 => background, %111 => border
; Usable zero page locations (from "Mapping the VIC")
; $0 - $6
; $9 - $a
; $3b - $3c
; $92 - $96
; $9b - $9c
; $9e - $9f
; $a3 - $a5
; $a7 - $b1
; $b4 - $b6
; $bd - $bf
; $f7 - $fe
CHAR_POINTER = $0 ; Word
dx = $2
dy = $3
e1 = $4
e2 = $5
diff = $6 ; Word
xi = $8
yi = $9
pchar_buffer_max = $a ; Maximum is $40 or $80, when buffer size is 128 chars
char_ptr = $3b ; word
char_x = $93
char_y = $94
char_buffer_index = $95
coord_buffer_index = $96
cell = $9b
pixel = $9c
yi16 = $9e
line_x1 = $a7
line_y1 = $a8
line_x2 = $a9
line_y2 = $aa
zp_temp = $fb ; Word
zp_temp2 = $fd ; Ditto
; =================== Kernal calls ======================
kGetIn = $ffe4
kCharOut = $ffd2
; =================== Cassette buffer ===================
*=$33c
.pixel
!byte $80,$40,$20,$10,$8,$4,$2,$1
.coordBuffer
!byte $0, $0, $7f, $7f
!byte $7f, $0, $0, $7f
!byte $40, $0, $40, $7f
!byte $0, $40, $7f, $40
!byte $3a, $3d, $45, $3d
!byte $3a, $43, $45, $43
; =================== Basic stub ========================
* = BASIC_LOC
!byte $0b, $08
!byte $E3 ; BASIC_LOC line number
!byte $07, $9E
!byte '0' + main % 10000 / 1000
!byte '0' + main % 1000 / 100
!byte '0' + main % 100 / 10
!byte '0' + main % 10
!byte $00, $00, $00 ; End of basic
.screenBuffer
!fill 256, $0
; =================== Main loop =========================
main:
jsr initScreen
mainloop
jsr resetCoordBuffer
jsr setCoordsFromBuffer
jsr drawLine
jsr setCoordsFromBuffer
jsr drawLine
jsr setCoordsFromBuffer
jsr drawLine
jsr setCoordsFromBuffer
jsr drawLine
jsr setCoordsFromBuffer
jsr drawLine
jsr setCoordsFromBuffer
jsr drawLine
_wait sei
lda VIC_RASTER
cmp #80
cli
bne _wait
jmp swapScreen
rts
waitKey:
jsr kGetIn
beq waitKey
rts
; ============================================================================
; Setup
; ============================================================================
initScreen:
lda #$90 ; Screen size 16 x 16
sta VIC_COLS
lda #$20 ; Chars: 8x8
sta VIC_ROWS
lda #$24
sta VIC_VERT
lda #$10
sta VIC_HORIZ
lda #$fe ; Custom chars
sta VIC_CHARLOC
lda #<CHAR_LOC ; Char pointer - low
sta CHAR_POINTER
lda #>CHAR_LOC ; Char pointer - high
sta CHAR_POINTER + 1
cls:
ldy #$ff
lda #$0
- sta SCREEN_LOC, y
sta COLOR_LOC, y
dey
bne -
sta SCREEN_LOC, y
sta COLOR_LOC, y
rts
neg:
eor #$ff
clc
adc #1
rts
setChar:
ldy #$0
sty char_ptr + 1
ldy cell
lda .screenBuffer, y
bne +
lda char_buffer_index ; Save few cycles to do this instead of inc
adc #$1
sta char_buffer_index
sta .screenBuffer, y
+ asl
asl
rol char_ptr + 1
asl
sta char_ptr
rol char_ptr + 1
clc
lda char_ptr + 1
adc CHAR_POINTER + 1
sta char_ptr + 1
rts
swapScreen:
ldy #$7f ; Copy buffer to screen
- lda .screenBuffer, y
sta SCREEN_LOC, y
lda .screenBuffer+$80, y
sta SCREEN_LOC+$80, y
dey
bne -
lda .screenBuffer, y
sta SCREEN_LOC, y
lda .screenBuffer+$80, y
sta SCREEN_LOC+$80, y
lda #$0 ; clear buffer
ldy #$7f
sta .screenBuffer, y
sta .screenBuffer+$80, y
- dey
sta .screenBuffer, y
sta .screenBuffer+$80, y
bne -
ldx #$40 ; toggle char buffer index
ldy #$00
lda char_buffer_index
cmp #$40
bpl +
ldx #$80
ldy #$40
+ stx pchar_buffer_max
sty char_buffer_index
ldy #$ff ; clear chars
lda #$0
cpx #$80
bmi minloop
maxloop sta CHAR_LOC+$200, y
sta CHAR_LOC+$300, y
dey
bne maxloop
sta CHAR_LOC+$200, y
sta CHAR_LOC+$300, y
jmp mainloop
minloop sta CHAR_LOC, y
sta CHAR_LOC+$100, y
dey
bne minloop
sta CHAR_LOC, y
sta CHAR_LOC+$100, y
jmp mainloop
resetCoordBuffer:
ldy #$0
sty coord_buffer_index
rts
setCoordsFromBuffer:
ldy coord_buffer_index
lda .coordBuffer, y
sta line_x1
iny
lda .coordBuffer, y
sta line_y1
iny
lda .coordBuffer, y
sta line_x2
iny
lda .coordBuffer, y
sta line_y2
iny
sty coord_buffer_index
rts
initCharCoords:
ldy line_x1
tya
lsr
lsr
lsr
sta cell
tya
and #$7
sta char_x
ldy line_y1
tya
asl
and #$f0
clc
adc cell
sta cell
tya
and #$7
sta char_y
rts
swapCoords:
lda line_x1 ; Swap x
ldy line_x2
sty line_x1
sta line_x2
lda line_y1 ; Swap y
ldy line_y2
sty line_y1
sta line_y2
calcDeltaValues:
ldx #$1
sec
lda line_x2
sbc line_x1
bpl +
jsr neg
ldx #$ff
+ stx xi ; xinc/xdec
sta dx
ldx #$1
ldy #$10
sec
lda line_y2
sbc line_y1
bpl +
jsr neg
ldx #$ff
ldy #$f0
+ stx yi ; yinc/ydec
sty yi16 ; yinc/ydec for cell
sta dy
rts
; ============================================================================
; Bresenham line draw
; ============================================================================
toLiney:
jmp initLiney
drawLine:
lda #$0
sta diff + 1
jsr calcDeltaValues ; Acc = dy as result
cmp dx
bpl toLiney
tay
sec ; Init linex
sbc dx
asl
sta e1 ; e1 = 2 * dy - 2 * dx
tya
asl
sta e2 ; e2 = 2 * dy
sec
sbc dx ; diff = 2 * dy - dx
bpl +
dec diff + 1
+ sta diff
lda xi
bpl linex
jsr swapCoords ; Draw loop should always be from min to max
linex
jsr initCharCoords
ldy char_x ; Set current pixel
lda .pixel, y
sta pixel
jsr setChar
ldx line_x1 ; Loop index
loopx
ldy char_y ; Plot
lda pixel
ora (char_ptr), y
sta (char_ptr), y
cpx line_x2 ; Last coord-x reached?
beq end_loopx
inx
lda diff + 1
bmi dmix
clc
lda line_y1
adc yi
sta line_y1
lda yi
clc
adc char_y
sta char_y
bpl no_wrap ; If char_y < 0, wrap value to 7
lda #$7
sta char_y
jmp calc_cell
no_wrap
cmp #$8 ; If char_y > 7, mask value to 0-7
bmi shift_pixel
and #$7
sta char_y
calc_cell
clc
lda cell
adc yi16 ; Row up / down
sta cell
jsr setChar
shift_pixel
lda e1
beq inc_x
clc
adc diff
bpl +
dec diff + 1
+ sta diff
inc_x lsr pixel ; Inc pixel-x
bcc loopx
ror pixel
inc cell
jsr setChar
jmp loopx
dmix
lda diff
clc
adc e2
bcc +
inc diff + 1
+ sta diff
lsr pixel ; Inc pixel-x
bcc loopx
ror pixel ; Set pixel for next char
inc cell
jsr setChar
jmp loopx
end_loopx
rts
initLiney
sec
lda dx
tay
sbc dy
asl
sta e1 ; e1 = 2 * deltaX - 2 * deltaY
tya
asl
sta e2 ; e2 = 2 * deltaX
sec
sbc dy
bpl +
dec diff + 1
+ sta diff ; diff = 2 * deltaX - deltaY
lda yi
bpl liney
jsr swapCoords ; Draw loop should always be from min to max
liney
jsr initCharCoords
ldy char_x
lda .pixel, y
sta pixel
jsr setChar
ldx line_y1
loopy
ldy char_y ; Plot
lda pixel
ora (char_ptr), y
sta (char_ptr), y
cpx line_y2
beq end_loopy
inx
lda diff + 1
bmi dmiy
clc
lda xi
bmi +
lsr pixel ; Inc pixel-x
bcc cont
ror pixel ; Set pixel for next char
inc cell
jmp cont
+ asl pixel ; Dec pixel-x
bcc cont
rol pixel ; Set pixel for next char
dec cell
cont
lda e1
beq inc_char_y
clc
adc diff
bpl +
dec diff + 1
+ sta diff
inc_char_y
inc char_y
lda char_y
cmp #$8 ; If char_y > 7, move one row down
bmi loopy
and #$7 ; char_y range should be 0-7
sta char_y
clc
lda cell
adc #$10
sta cell
jsr setChar
jmp loopy
dmiy
lda diff
clc
adc e2
bcc +
inc diff + 1
+ sta diff
inc char_y
lda char_y
cmp #$8 ; If char_y > 7, move one row down
bmi loopy
and #$7
sta char_y
clc
lda cell
adc #$10
sta cell
jsr setChar
jmp loopy
end_loopy
rts
*=$1800
!fill 1024, $0