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