]> git.sur5r.net Git - cc65/blob - libsrc/c64/c64-vdc.s
3e324e5d9891883c858b6adb41051f3fa465fd1b
[cc65] / libsrc / c64 / c64-vdc.s
1 ;
2 ; Extended memory driver for the VDC RAM available on all C128 machines
3 ; (based on code by Ullrich von Bassewitz)
4 ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl>
5 ; 06,20.12.2002
6
7         .include        "zeropage.inc"
8
9         .include        "em-kernel.inc"
10         .include        "em-error.inc"
11
12
13         .macpack        generic
14
15
16 ; ------------------------------------------------------------------------
17 ; Header. Includes jump table
18
19 .segment        "JUMPTABLE"
20
21 ; Driver signature
22
23         .byte   $65, $6d, $64           ; "emd"
24         .byte   $00                     ; EM API version number
25
26 ; Jump table.
27
28         .word   INSTALL
29         .word   DEINSTALL
30         .word   PAGECOUNT
31         .word   MAP
32         .word   USE
33         .word   COMMIT
34         .word   COPYFROM
35         .word   COPYTO
36
37 ; ------------------------------------------------------------------------
38 ; Constants
39
40 VDC_ADDR_REG      = $D600                 ; VDC address
41 VDC_DATA_REG      = $D601                 ; VDC data
42
43 VDC_DATA_HI       = 18                    ; used registers
44 VDC_DATA_LO       = 19
45 VDC_CSET          = 28
46 VDC_DATA          = 31
47
48 ; ------------------------------------------------------------------------
49 ; Data.
50
51 .data
52
53 pagecount:      .word  64                  ; $0000-$3fff as 16k default
54 curpage:        .word  $ffff               ; currently mapped-in page (invalid)
55
56 .bss
57
58 window:         .res    256                ; memory window
59
60 .code
61
62 ; ------------------------------------------------------------------------
63 ; INSTALL routine. Is called after the driver is loaded into memory. If
64 ; possible, check if the hardware is present and determine the amount of
65 ; memory available.
66 ; Must return an EM_ERR_xx code in a/x.
67 ;
68
69 INSTALL:
70         ; do test for VDC presence here???
71
72         ldx     #VDC_CSET       ; determine size of RAM...
73         jsr     vdcgetreg
74         sta     tmp1
75         ora     #%00010000
76         jsr     vdcputreg       ; turn on 64k
77
78         jsr     settestadr1     ; save original value of test byte
79         jsr     vdcgetbyte
80         sta     tmp2
81
82         lda     #$55            ; write $55 here
83         ldy     #ptr1
84         jsr     test64k         ; read it here and there
85         lda     #$aa            ; write $aa here
86         ldy     #ptr2
87         jsr     test64k         ; read it here and there
88
89         jsr     settestadr1
90         lda     tmp2
91         jsr     vdcputbyte      ; restore original value of test byte
92
93         lda     ptr1            ; do bytes match?
94         cmp     ptr1+1
95         bne     @have64k
96         lda     ptr2
97         cmp     ptr2+1
98         bne     @have64k
99
100         ldx     #VDC_CSET
101         lda     tmp1
102         jsr     vdcputreg       ; restore 16/64k flag
103         jmp     @endok          ; and leave default values for 16k
104
105 @have64k:
106         lda     #<256
107         ldx     #>256
108         sta     pagecount
109         stx     pagecount+1
110 @endok:
111         lda     #<EM_ERR_OK
112         ldx     #>EM_ERR_OK
113         rts
114
115 test64k:
116         sta     tmp1
117         sty     ptr3
118         lda     #0
119         sta     ptr3+1
120         jsr     settestadr1
121         lda     tmp1
122         jsr     vdcputbyte              ; write $55
123         jsr     settestadr1
124         jsr     vdcgetbyte              ; read here
125         pha
126         jsr     settestadr2
127         jsr     vdcgetbyte              ; and there
128         ldy     #1
129         sta     (ptr3),y
130         pla
131         dey
132         sta     (ptr3),y
133         rts
134
135 settestadr1:
136         ldy     #$02                    ; test page 2 (here)
137         .byte   $2c
138 settestadr2:
139         ldy     #$42                    ; or page 64+2 (there)
140         lda     #0
141         jmp     vdcsetsrcaddr
142
143 ; ------------------------------------------------------------------------
144 ; DEINSTALL routine. Is called before the driver is removed from memory.
145 ; Can do cleanup or whatever. Must not return anything.
146 ;
147
148 DEINSTALL:
149         ;on C128 restore font and clear the screen?
150         rts
151
152 ; ------------------------------------------------------------------------
153 ; PAGECOUNT: Return the total number of available pages in a/x.
154 ;
155
156 PAGECOUNT:
157         lda     pagecount
158         ldx     pagecount+1
159         rts
160
161 ; ------------------------------------------------------------------------
162 ; MAP: Map the page in a/x into memory and return a pointer to the page in
163 ; a/x. The contents of the currently mapped page (if any) may be discarded
164 ; by the driver.
165 ;
166
167 MAP:    sta     curpage
168         stx     curpage+1
169         sta     ptr1+1
170         ldy     #0
171         sty     ptr1
172
173         lda     #<window
174         sta     ptr2
175         lda     #>window
176         sta     ptr2+1
177
178         jsr     transferin
179
180         lda     #<window
181         ldx     #>window
182         rts
183
184 ; copy a single page from (ptr1):VDCRAM to (ptr2):RAM
185
186 transferin:
187         lda     ptr1
188         ldy     ptr1+1
189         jsr     vdcsetsrcaddr           ; set source address in VDC
190         ldy     #0
191         ldx     #VDC_DATA
192         stx     VDC_ADDR_REG
193 @L0:    bit     VDC_ADDR_REG
194         bpl     @L0
195         lda     VDC_DATA_REG            ; get 2 bytes at a time to speed-up
196         sta     (ptr2),y                ; (in fact up to 8 bytes could be fetched with special VDC config)
197         iny
198         lda     VDC_DATA_REG
199         sta     (ptr2),y
200         iny
201         bne     @L0
202         rts
203
204 ; ------------------------------------------------------------------------
205 ; USE: Tell the driver that the window is now associated with a given page.
206
207 USE:    sta     curpage
208         stx     curpage+1               ; Remember the page
209         lda     #<window
210         ldx     #>window                ; Return the window
211 done:   rts
212
213 ; ------------------------------------------------------------------------
214 ; COMMIT: Commit changes in the memory window to extended storage.
215
216 COMMIT:
217         lda     curpage                 ; jump if no page mapped
218         ldx     curpage+1
219         bmi     done
220         sta     ptr1+1
221         ldy     #0
222         sty     ptr1
223
224         lda     #<window
225         sta     ptr2
226         lda     #>window
227         sta     ptr2+1
228
229 ; fall through to transferout
230
231 ; copy a single page from (ptr2):RAM to (ptr1):VDCRAM
232
233 transferout:
234         lda     ptr1
235         ldy     ptr1+1
236         jsr     vdcsetsrcaddr           ; set source address in VDC
237         ldy     #0
238         ldx     #VDC_DATA
239         stx     VDC_ADDR_REG
240 @L0:    bit     VDC_ADDR_REG
241         bpl     @L0
242         lda     (ptr2),y                ; speedup does not work for writing
243         sta     VDC_DATA_REG
244         iny
245         bne     @L0
246         rts
247
248 ; ------------------------------------------------------------------------
249 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
250 ; describing the request is passed in a/x.
251 ; The function must not return anything.
252 ;
253
254 COPYFROM:
255         jsr     setup
256         beq     @L2                     ; Skip if no full pages
257
258 ; Copy full pages 
259
260 @L1:    jsr     transferin
261         inc     ptr1+1
262         inc     ptr2+1
263         dec     tmp1
264         bne     @L1
265
266 ; Copy the remainder of the page
267
268 @L2:    ldy     #EM_COPY_COUNT
269         lda     (ptr3),y                ; Get bytes in last page
270         beq     @L4
271         sta     tmp1
272
273 ; Transfer the bytes in the last page
274
275         ldy     #0
276         ldx     #VDC_DATA
277         stx     VDC_ADDR_REG
278 @L3:    bit     VDC_ADDR_REG
279         bpl     @L3
280         lda     VDC_DATA_REG
281         sta     (ptr2),y
282         iny
283         dec     tmp1
284         lda     tmp1
285         bne     @L3
286 @L4:    rts
287
288 ; ------------------------------------------------------------------------
289 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
290 ; describing the request is passed in a/x.
291 ; The function must not return anything.
292 ;
293
294 COPYTO:
295         jsr     setup
296         beq     @L2                     ; Skip if no full pages
297
298 ; Copy full pages 
299
300 @L1:    jsr     transferout
301         inc     ptr1+1
302         inc     ptr2+1
303         dec     tmp1
304         bne     @L1
305
306 ; Copy the remainder of the page
307
308 @L2:    ldy     #EM_COPY_COUNT
309         lda     (ptr3),y                ; Get bytes in last page
310         beq     @L4
311         sta     tmp1
312
313 ; Transfer the bytes in the last page
314
315         ldy     #0
316         ldx     #VDC_DATA
317         stx     VDC_ADDR_REG
318 @L3:    bit     VDC_ADDR_REG
319         bpl     @L3
320         lda     (ptr2),y
321         sta     VDC_DATA_REG
322         iny
323         dec     tmp1
324         lda     tmp1
325         bne     @L3
326 @L4:    rts
327
328 ;-------------------------------------------------------------------------
329 ; Helper functions to handle VDC ram
330 ;
331
332 vdcsetsrcaddr:
333         ldx     #VDC_DATA_LO
334         stx     VDC_ADDR_REG
335 @L0:    bit     VDC_ADDR_REG
336         bpl     @L0
337         sta     VDC_DATA_REG
338         dex
339         tya
340         stx     VDC_ADDR_REG
341         sta     VDC_DATA_REG
342         rts
343
344 vdcgetbyte:
345         ldx     #VDC_DATA
346 vdcgetreg:
347         stx     VDC_ADDR_REG
348 @L0:    bit     VDC_ADDR_REG
349         bpl     @L0
350         lda     VDC_DATA_REG
351         rts
352
353 vdcputbyte:
354         ldx     #VDC_DATA
355 vdcputreg:
356         stx     VDC_ADDR_REG
357 @L0:    bit     VDC_ADDR_REG
358         bpl     @L0
359         sta     VDC_DATA_REG
360         rts
361
362 ; ------------------------------------------------------------------------
363 ; Helper function for COPYFROM and COPYTO: Store the pointer to the request
364 ; structure and prepare data for the copy
365 ;
366
367 setup:
368         sta     ptr3
369         stx     ptr3+1                  ; Save the passed em_copy pointer
370
371         ldy     #EM_COPY_OFFS
372         lda     (ptr3),y
373         sta     ptr1
374         ldy     #EM_COPY_PAGE
375         lda     (ptr3),y
376         sta     ptr1+1                  ; From
377
378         ldy     #EM_COPY_BUF
379         lda     (ptr3),y
380         sta     ptr2
381         iny
382         lda     (ptr3),y
383         sta     ptr2+1                  ; To
384
385         ldy     #EM_COPY_COUNT+1
386         lda     (ptr3),y                ; Get number of pages
387         sta     tmp1
388         rts
389