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