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