]> git.sur5r.net Git - cc65/blob - libsrc/c64/emd/c64-dqbb.s
Merge branch 'master' into c1p
[cc65] / libsrc / c64 / emd / c64-dqbb.s
1 ;
2 ; Extended memory driver for the Double Quick Brown Box cartridge
3 ; Marco van den Heuvel, 2010-01-27
4 ;
5
6         .include        "zeropage.inc"
7
8         .include        "em-kernel.inc"
9         .include        "em-error.inc"
10
11
12         .macpack        generic
13
14
15 ; ------------------------------------------------------------------------
16 ; Header. Includes jump table
17
18 .segment        "JUMPTABLE"
19
20 ; Driver signature
21
22         .byte   $65, $6d, $64           ; "emd"
23         .byte   EMD_API_VERSION         ; EM API version number
24
25 ; Library reference
26
27         .addr   $0000
28
29 ; Jump table
30
31         .addr   INSTALL
32         .addr   UNINSTALL
33         .addr   PAGECOUNT
34         .addr   MAP
35         .addr   USE
36         .addr   COMMIT
37         .addr   COPYFROM
38         .addr   COPYTO
39
40 ; ------------------------------------------------------------------------
41 ; Constants
42
43 BASE                    = $8000
44 PAGES                   = ($C000 - BASE) / 256
45 TARGETLOC               = $200          ; Target location for copy/check code
46 CONTROL                 = $DE00
47
48 ; ------------------------------------------------------------------------
49 ; Data.
50
51 .proc   check
52 template:
53 .org    ::TARGETLOC             ; Assemble for target location
54 entry:
55         lda     $01
56         pha
57         lda     #$37
58         sta     $01
59         ldx     #$14
60         ldy     #$90
61         sty     CONTROL
62         lda     $8000
63         stx     CONTROL
64         cmp     $8000
65         bne     present
66         sty     CONTROL
67         inc     $8000
68         stx     CONTROL
69         cmp     $8000
70         beq     present
71         dec     $8000
72         ldy     #$00
73
74 done:   pla
75         sta     $01
76         rts
77
78 present:
79         sty     CONTROL
80         ldy     #$01
81         bne     done
82 .reloc
83 .endproc
84
85
86 .proc   copy
87 template:
88 .org    ::TARGETLOC             ; Assemble for target location
89 entry:
90 .proc   fetch
91         stx     CONTROL
92         ldx     $01
93         lda     #$37
94         sta     $01
95 address         := *+1          ; Patched at runtime
96         lda     ($00),y
97         stx     $01
98         ldx     #$90
99         stx     CONTROL
100         rts
101 .endproc
102
103 .proc   stash
104         stx     CONTROL
105         ldx     $01
106         ldy     #$37
107         sty     $01
108         ldy     #$00
109 address         := *+1          ; Patched at runtime
110         sta     ($00),y
111         stx     $01
112         ldx     #$90
113         stx     CONTROL
114         rts
115 .endproc
116 .reloc
117 .endproc
118
119
120 .bss
121
122 curpage:        .res    1               ; Current page number
123 window:         .res    256             ; Memory "window"
124
125 ; Since the functions above are copied to $200, the current contents of this
126 ; memory area must be saved into backup storage. Allocate enough space.
127 backup:         .res    .max (.sizeof (copy), .sizeof (check))
128
129
130
131 .code
132
133 ; ------------------------------------------------------------------------
134 ; INSTALL routine. Is called after the driver is loaded into memory. If
135 ; possible, check if the hardware is present and determine the amount of
136 ; memory available.
137 ; Must return an EM_ERR_xx code in a/x.
138 ;
139
140 INSTALL:
141         sei
142         jsr     backup_and_setup_check_routine
143         jsr     check::entry
144         cli
145         ldx     #.sizeof (check) - 1
146         jsr     restore_data
147         cpy     #$01
148         beq     @present
149         lda     #<EM_ERR_NO_DEVICE
150         ldx     #>EM_ERR_NO_DEVICE
151         rts
152
153 @present:
154         lda     #<EM_ERR_OK
155         ldx     #>EM_ERR_OK
156 ;       rts                     ; Run into UNINSTALL instead
157
158 ; ------------------------------------------------------------------------
159 ; UNINSTALL routine. Is called before the driver is removed from memory.
160 ; Can do cleanup or whatever. Must not return anything.
161 ;
162
163 UNINSTALL:
164         rts
165
166
167 ; ------------------------------------------------------------------------
168 ; PAGECOUNT: Return the total number of available pages in a/x.
169 ;
170
171 PAGECOUNT:
172         lda     #<PAGES
173         ldx     #>PAGES
174         rts
175
176 ; ------------------------------------------------------------------------
177 ; MAP: Map the page in a/x into memory and return a pointer to the page in
178 ; a/x. The contents of the currently mapped page (if any) may be discarded
179 ; by the driver.
180 ;
181
182 MAP:
183         sei
184         sta     curpage         ; Remember the new page
185         clc
186         adc     #>BASE
187         sta     ptr1+1
188         ldy     #0
189         sty     ptr1
190         jsr     backup_and_setup_copy_routine
191         ldx     #<ptr1
192         stx     copy::fetch::address
193 @L1:
194         ldx     #$14
195         jsr     copy::fetch
196         ldx     ptr1
197         sta     window,x
198         inc     ptr1
199         bne     @L1
200
201 ; Return the memory window
202
203         jsr     restore_copy_routine
204         lda     #<window
205         ldx     #>window                ; Return the window address
206         cli
207         rts
208
209 ; ------------------------------------------------------------------------
210 ; USE: Tell the driver that the window is now associated with a given page.
211
212 USE:    sta     curpage         ; Remember the page
213         lda     #<window
214         ldx     #>window                ; Return the window
215         rts
216
217 ; ------------------------------------------------------------------------
218 ; COMMIT: Commit changes in the memory window to extended storage.
219
220 COMMIT:
221         sei
222         lda     curpage         ; Get the current page
223         clc
224         adc     #>BASE
225         sta     ptr1+1
226         ldy     #0
227         sty     ptr1
228         jsr     backup_and_setup_copy_routine
229         ldx     #<ptr1
230         stx     copy::stash::address
231 @L1:
232         ldx     ptr1
233         lda     window,x
234         ldx     #$14
235         jsr     copy::stash
236         inc     ptr1
237         bne     @L1
238
239 ; Return the memory window
240
241         jsr     restore_copy_routine
242         cli
243         rts
244
245 ; ------------------------------------------------------------------------
246 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
247 ; describing the request is passed in a/x.
248 ; The function must not return anything.
249 ;
250
251
252 COPYFROM:
253         sei
254         pha
255         txa
256         pha
257         jsr     backup_and_setup_copy_routine
258         pla
259         tax
260         pla
261         jsr     setup
262
263 ; Setup is:
264 ;
265 ;   - ptr1 contains the struct pointer
266 ;   - ptr2 contains the linear memory buffer
267 ;   - ptr3 contains -(count-1)
268 ;   - ptr4 contains the page memory buffer plus offset
269 ;   - tmp1 contains zero (to be used for linear memory buffer offset)
270
271         lda     #<ptr4
272         sta     copy::fetch::address
273         jmp     @L3
274
275 @L1:
276         ldx     #$14
277         ldy     #0
278         jsr     copy::fetch
279         ldy     tmp1
280         sta     (ptr2),y
281         inc     tmp1
282         bne     @L2
283         inc     ptr2+1
284 @L2:
285         inc     ptr4
286         beq     @L4
287
288 ; Bump count and repeat
289
290 @L3:
291         inc     ptr3
292         bne     @L1
293         inc     ptr3+1
294         bne     @L1
295         jsr     restore_copy_routine
296         cli
297         rts
298
299 ; Bump page register
300
301 @L4:
302         inc     ptr4+1
303         jmp     @L3
304
305 ; ------------------------------------------------------------------------
306 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
307 ; describing the request is passed in a/x.
308 ; The function must not return anything.
309 ;
310
311 COPYTO:
312         sei
313         pha
314         txa
315         pha
316         jsr     backup_and_setup_copy_routine
317         pla
318         tax
319         pla
320         jsr     setup
321
322 ; Setup is:
323 ;
324 ;   - ptr1 contains the struct pointer
325 ;   - ptr2 contains the linear memory buffer
326 ;   - ptr3 contains -(count-1)
327 ;   - ptr4 contains the page memory buffer plus offset
328 ;   - tmp1 contains zero (to be used for linear memory buffer offset)
329
330         lda     #<ptr4
331         sta     copy::stash::address
332         jmp     @L3
333
334 @L1:
335         ldy     tmp1
336         lda     (ptr2),y
337         ldx     #$14
338         ldy     #0
339         jsr     copy::stash
340         inc     tmp1
341         bne     @L2
342         inc     ptr2+1
343 @L2:
344         inc     ptr4
345         beq     @L4
346
347 ; Bump count and repeat
348
349 @L3:
350         inc     ptr3
351         bne     @L1
352         inc     ptr3+1
353         bne     @L1
354         jsr     restore_copy_routine
355         cli
356         rts
357
358 ; Bump page register
359
360 @L4:
361         inc     ptr4+1
362         jmp     @L3
363
364 ; ------------------------------------------------------------------------
365 ; Helper function for COPYFROM and COPYTO: Store the pointer to the request
366 ; structure and prepare data for the copy
367
368 setup:
369         sta     ptr1
370         stx     ptr1+1          ; Save passed pointer
371
372 ; Get the page number from the struct and adjust it so that it may be used
373 ; with the hardware. That is: ptr4 has the page address and page offset
374 ; tmp2 will hold the bank value
375
376         ldy     #EM_COPY::PAGE
377         lda     (ptr1),y
378         clc
379         adc     #>BASE
380         sta     ptr4+1
381
382 ; Get the buffer pointer into ptr2
383
384         ldy     #EM_COPY::BUF
385         lda     (ptr1),y
386         sta     ptr2
387         iny
388         lda     (ptr1),y
389         sta     ptr2+1
390
391 ; Get the count, calculate -(count-1) and store it into ptr3
392
393         ldy     #EM_COPY::COUNT
394         lda     (ptr1),y
395         eor     #$FF
396         sta     ptr3
397         iny
398         lda     (ptr1),y
399         eor     #$FF
400         sta     ptr3+1
401
402 ; Get the page offset into ptr4 and clear tmp1
403
404         ldy     #EM_COPY::OFFS
405         lda     (ptr1),y
406         sta     ptr4
407         lda     #0
408         sta     tmp1
409
410 ; Done
411
412         rts
413
414 ; Helper routines for copying to and from the +256k ram
415
416 backup_and_setup_copy_routine:
417         ldx     #.sizeof (copy) - 1
418 @L1:
419         lda     copy::entry,x
420         sta     backup,x
421         lda     copy::template,x
422         sta     copy::entry,x
423         dex
424         bpl     @L1
425         rts
426
427 backup_and_setup_check_routine:
428         ldx     #.sizeof (check) - 1
429 @L1:
430         lda     check::entry,x
431         sta     backup,x
432         lda     check::template,x
433         sta     check::entry,x
434         dex
435         bpl     @L1
436         rts
437
438 restore_copy_routine:
439         ldx     #.sizeof (copy) - 1
440 restore_data:
441         lda     backup,x
442         sta     TARGETLOC,x
443         dex
444         bpl     restore_data
445         rts