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