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