]> git.sur5r.net Git - c128-kasse/blob - src/vdc_util.s
vdc: write 16bit addresses just like KERNAL does
[c128-kasse] / src / vdc_util.s
1 ;;; -*- tab-width: 8; -*-
2         .export         _vdc_read_reg, _vdc_read_addr, _vdc_read_mem
3         .export         _vdc_write_reg, _vdc_write_addr, _vdc_write_mem
4         .export         _vdc_load_thinfont
5         .import         popa, popax
6         .importzp       ptr1, ptr2
7         .include        "c128.inc"
8         .debuginfo      on
9
10 ;;; useful documentation:
11 ;;; - 6502 instruction/addressing mode overview
12 ;;;     - http://www.obelisk.me.uk/6502/index.html
13 ;;; - cc65 assembler interfacing with C
14 ;;;     - https://github.com/cc65/wiki/wiki/Parameter-passing-and-calling-conventions
15 ;;;     - https://github.com/cc65/wiki/wiki/Parameter-and-return-stacks
16 ;;;     - https://github.com/cc65/wiki/wiki/Using-runtime-zeropage-locations-in-assembly-language
17 ;;; - Programming the VDC
18 ;;;     - Chapter 10 of http: //www.pagetable.com/docs/Commodore%20128%20Programmer%27s%20Reference%20Guide.pdf
19
20 VDC_ADDR_REG    := 18
21 VDC_MEM_REG     := 31
22
23 ;;; unsigned char __fastcall__ vdc_read_reg (unsigned char reg);
24 _vdc_read_reg:
25         ldx #0                  ; clear high byte of return register
26 vdc_read_reg:       
27         sta VDC_INDEX
28
29 @wait:  bit VDC_INDEX           ; busy wait until vdc is ready
30         bpl @wait
31
32         lda VDC_DATA
33         rts
34
35 ;;; unsigned __fastcall__ vdc_read_addr (unsigned char reg);
36 _vdc_read_addr:
37         tay                     ; copy vdc register
38         iny                     ; next register is high byte of addr
39         jsr vdc_read_reg
40         tax                     ; save high byte in x return register
41         tya
42         jsr vdc_read_reg
43         rts
44
45 ;;; void __fastcall__ vdc_write_reg (unsigned char reg, unsigned char data);
46 _vdc_write_reg:
47         pha
48         jsr popa
49         tay
50         pla
51 vdc_write_reg:
52         sty VDC_INDEX
53
54 @wait:  bit VDC_INDEX           ; busy wait until vdc is ready
55         bpl @wait
56
57         sta VDC_DATA
58         rts
59
60 ;;; void __fastcall__ vdc_write_addr (unsigned char reg, unsigned addr);
61 _vdc_write_addr:
62         pha
63         jsr popa                ; this mustn't touch x (libsrc/runtime/popa.s)
64         tay                     ; vdc register
65         pla
66 vdc_write_addr:
67         pha
68         txa                     ; get high byte of addr
69         jsr vdc_write_reg
70         iny                     ; next vdc register is high byte of addr
71         pla
72         jsr vdc_write_reg
73         rts
74
75 ;;; void __fastcall__ vdc_read_mem (unsigned dest, unsigned src, unsigned n);
76 _vdc_read_mem:
77         sta ptr1                ; store n
78         stx ptr1+1
79
80         jsr popax
81         ldy #VDC_ADDR_REG
82         jsr vdc_write_addr
83
84         jsr popax
85         sta ptr2
86         stx ptr2+1
87
88         lda #VDC_MEM_REG
89         sta VDC_INDEX
90
91         ldy #0                  ; offset into dest
92
93         ;; first, loop over the high byte of n, 256 times
94         ldx ptr1+1              ; get high byte of n
95         beq @low                ; skip if zero
96
97 @cpyhi: bit VDC_INDEX
98         bpl @cpyhi
99
100         lda VDC_DATA
101         sta (ptr2),y
102         iny
103         bne @cpyhi              ; have we copied 256 bytes yet?
104
105         inc ptr2+1              ; adjust dest pointer
106         dex
107         bne @cpyhi              ; read 256 more bytes
108         
109 @low:   ldx ptr1                ; get low byte of n
110         beq @done               ; skip if zero
111         
112 @cpy:   bit VDC_INDEX
113         bpl @cpy
114
115         lda VDC_DATA
116         sta (ptr2),y
117         iny
118         dex
119         bne @cpy
120
121 @done:  rts
122
123 ;;; void __fastcall__ vdc_write_mem (unsigned dest, const void* src, unsigned n);
124 _vdc_write_mem:
125         sta ptr1                ; store n
126         stx ptr1+1
127
128         jsr popax
129         sta ptr2
130         stx ptr2+1
131
132         jsr popax
133         ldy #VDC_ADDR_REG
134         jsr vdc_write_addr
135
136         lda #VDC_MEM_REG
137         sta VDC_INDEX
138
139         ldy #0                  ; offset into dest
140
141         ;; first, loop over the high byte of n
142         ldx ptr1+1              ; get high byte of n
143         beq @low                ; skip if zero
144
145 @cpyhi: bit VDC_INDEX
146         bpl @cpyhi
147
148         lda (ptr2),y
149         sta VDC_DATA
150         iny
151         bne @cpyhi              ; have we copied 256 bytes yet?
152
153         inc ptr2+1              ; adjust dest pointer
154         dex
155         bne @cpyhi              ; read 256 more bytes
156         
157 @low:   ldx ptr1                ; get low byte of n
158         beq @done               ; skip if zero
159         
160 @cpy:   bit VDC_INDEX
161         bpl @cpy
162
163         lda (ptr2),y
164         sta VDC_DATA
165         iny
166         dex
167         bne @cpy
168
169 @done:  rts
170
171 ;;; void __fastcall__ vdc_load_thinfont (void);
172 _vdc_load_thinfont:
173         ;; save MMU register
174         lda $0
175         pha
176         lda $1
177         pha
178
179         ;; map in alternate font
180         lda #$FF
181         sta $0
182         lda #$33
183         sta $1
184
185         ;; call kernal load font routine
186         jsr $FF62
187         
188         ;; restore MMU
189         pla
190         sta $1
191         pla
192         sta $0
193         rts