]> git.sur5r.net Git - cc65/blob - libsrc/c64/emd/c64-c256k.s
Replaced whole bunch for Makefiles with a single generic Makefile.
[cc65] / libsrc / c64 / emd / c64-c256k.s
1 ;
2 ; Extended memory driver for the C256K memory expansion
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                    = $4000
40 PAGES                   = 3 * 256
41 TARGETLOC               = $200          ; Target location for copy/check code
42 PIA                     = $DFC0
43
44 ; ------------------------------------------------------------------------
45 ; Data.
46
47 .data
48
49
50 ; This function is used to copy code from and to the extended memory
51 .proc   copy
52 template:
53 .org    ::TARGETLOC             ; Assemble for target location
54 entry:
55         stx     PIA
56 stashop         = $91           ; 'sta' opcode
57 operation       := *            ; Location and opcode is patched at runtime
58 address         := *+1
59         lda     ($00),y
60         ldx     #$dc
61         stx     PIA
62         rts
63 .reloc
64 .endproc
65
66 ; This function is used to check for the existence of the extended memory
67 .proc   check
68 template:
69 .org    ::TARGETLOC
70 entry:
71         ldy     #$00            ; Assume hardware not present
72
73         lda     #$fc
74         sta     PIA
75         lda     $01
76         tax
77         and     #$f8
78         sta     $01
79         lda     $4000
80         cmp     $c000
81         bne     done            ; Jump if not found
82         inc     $c000
83         cmp     $4000
84         beq     done            ; Jump if not found
85
86         ; Hardware is present
87         iny
88 done:   stx     $01
89         ldx     #$dc
90         stx     PIA
91         rts
92 .reloc
93 .endproc
94
95
96
97 .bss
98
99 curpage:        .res    2       ; Current page number
100 curbank:        .res    1       ; Current bank
101 window:         .res    256     ; Memory "window"
102
103 ; Since the functions above are copied to $200, the current contents of this
104 ; memory area must be saved into backup storage. Allocate enough space.
105 backup:         .res    .max (.sizeof (copy), .sizeof (check))
106
107
108
109 .code
110 ; ------------------------------------------------------------------------
111 ; INSTALL routine. Is called after the driver is loaded into memory. If
112 ; possible, check if the hardware is present and determine the amount of
113 ; memory available.
114 ; Must return an EM_ERR_xx code in a/x.
115 ;
116
117 INSTALL:
118         lda     PIA+1           ; Select Peripheral Registers
119         ora     #4
120         sta     PIA+1
121         tax
122         lda     PIA+3
123         ora     #4
124         sta     PIA+3
125         tay
126
127         lda     #$DC            ; Set the default memory bank data
128         sta     PIA
129         lda     #$FE
130         sta     PIA+2
131
132         txa                     ; Select Data Direction Registers
133         and     #$FB
134         sta     PIA+1
135         tya
136         and     #$FB
137         sta     PIA+3
138
139         lda     #$FF            ; Set the ports to output
140         sta     PIA
141         sta     PIA+2
142
143         txa
144         and     #$C7
145         ora     #$30            ; Set CA1 and
146         sta     PIA+1           ; select Peripheral Registers
147         sty     PIA+3
148
149         jsr     backup_and_setup_check_routine
150         jsr     check::entry
151         cli
152         ldx     #.sizeof (check) - 1
153         jsr     restore_data
154         cpy     #$01
155         beq     @present
156         lda     #<EM_ERR_NO_DEVICE
157         ldx     #>EM_ERR_NO_DEVICE
158         rts
159
160 @present:
161         lda     #<EM_ERR_OK
162         ldx     #>EM_ERR_OK
163 ;       rts                     ; Run into UNINSTALL instead
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         rts
172
173
174 ; ------------------------------------------------------------------------
175 ; PAGECOUNT: Return the total number of available pages in a/x.
176 ;
177
178 PAGECOUNT:
179         lda     #<PAGES
180         ldx     #>PAGES
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:
190         sei
191         sta     curpage         ; Remember the new page
192         stx     curpage+1
193         jsr     adjust_page_and_bank
194         stx     curbank
195         clc
196         adc     #>BASE
197         sta     ptr1+1
198         ldy     #0
199         sty     ptr1
200         jsr     backup_and_setup_copy_routine
201         ldx     #<ptr1
202         stx     copy::address
203 @L1:
204         ldx     curbank
205         jsr     copy::entry
206         ldx     ptr1
207         sta     window,x
208         inc     ptr1
209         bne     @L1
210
211 ; Return the memory window
212
213         jsr     restore_copy_routine
214         lda     #<window
215         ldx     #>window                ; Return the window address
216         cli
217         rts
218
219 ; ------------------------------------------------------------------------
220 ; USE: Tell the driver that the window is now associated with a given page.
221
222 USE:    sta     curpage         ; Remember the page
223         stx     curpage+1
224         lda     #<window
225         ldx     #>window                ; Return the window
226         rts
227
228 ; ------------------------------------------------------------------------
229 ; COMMIT: Commit changes in the memory window to extended storage.
230
231 COMMIT:
232         sei
233         lda     curpage         ; Get the current page
234         ldx     curpage+1
235
236         jsr     adjust_page_and_bank
237         stx     curbank
238         clc
239         adc     #>BASE
240         sta     ptr1+1
241         ldy     #0
242         sty     ptr1
243         jsr     backup_and_setup_copy_routine
244         ldx     #<ptr1
245         stx     copy::address
246         ldx     #<copy::stashop
247         stx     copy::operation
248 @L1:
249         ldx     ptr1
250         lda     window,x
251         ldx     curbank
252         jsr     copy::entry
253         inc     ptr1
254         bne     @L1
255
256 ; Return the memory window
257
258         jsr     restore_copy_routine
259 done:
260         cli
261         rts
262
263 ; ------------------------------------------------------------------------
264 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
265 ; describing the request is passed in a/x.
266 ; The function must not return anything.
267 ;
268
269
270 COPYFROM:
271         sei
272         jsr     setup
273         jsr     backup_and_setup_copy_routine
274
275 ; Setup is:
276 ;
277 ;   - ptr1 contains the struct pointer
278 ;   - ptr2 contains the linear memory buffer
279 ;   - ptr3 contains -(count-1)
280 ;   - ptr4 contains the page memory buffer plus offset
281 ;   - tmp1 contains zero (to be used for linear memory buffer offset)
282 ;   - tmp2 contains the bank value
283
284         lda     #<ptr4
285         sta     copy::address
286         jmp     @L3
287
288 @L1:
289         ldx     tmp2
290         ldy     #0
291         jsr     copy::entry
292         ldy     tmp1
293         sta     (ptr2),y
294         inc     tmp1
295         bne     @L2
296         inc     ptr2+1
297 @L2:
298         inc     ptr4
299         beq     @L4
300
301 ; Bump count and repeat
302
303 @L3:
304         inc     ptr3
305         bne     @L1
306         inc     ptr3+1
307         bne     @L1
308         jsr     restore_copy_routine
309         cli
310         rts
311
312 ; Bump page register
313
314 @L4:
315         inc     ptr4+1
316         lda     ptr4+1
317         cmp     #$80
318         bne     @L3
319         lda     #>BASE
320         sta     ptr4+1
321         lda     tmp2
322         clc
323         adc     #$10
324         sta     tmp2
325         jmp     @L3
326
327 ; ------------------------------------------------------------------------
328 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
329 ; describing the request is passed in a/x.
330 ; The function must not return anything.
331 ;
332
333 COPYTO:
334         sei
335         jsr     setup
336         jsr     backup_and_setup_copy_routine
337
338 ; Setup is:
339 ;
340 ;   - ptr1 contains the struct pointer
341 ;   - ptr2 contains the linear memory buffer
342 ;   - ptr3 contains -(count-1)
343 ;   - ptr4 contains the page memory buffer plus offset
344 ;   - tmp1 contains zero (to be used for linear memory buffer offset)
345 ;   - tmp2 contains the bank value
346
347         lda     #<ptr4
348         sta     copy::address
349         lda     #<copy::stashop
350         sta     copy::operation
351         jmp     @L3
352
353 @L1:
354         ldy     tmp1
355         lda     (ptr2),y
356         ldx     tmp2
357         ldy     #0
358         jsr     copy::entry
359         inc     tmp1
360         bne     @L2
361         inc     ptr2+1
362 @L2:
363         inc     ptr4
364         beq     @L4
365
366 ; Bump count and repeat
367
368 @L3:
369         inc     ptr3
370         bne     @L1
371         inc     ptr3+1
372         bne     @L1
373         jsr     restore_copy_routine
374         cli
375         rts
376
377 ; Bump page register
378
379 @L4:
380         inc     ptr4+1
381         lda     ptr4+1
382         cmp     #$80
383         bne     @L3
384         lda     #>BASE
385         sta     ptr4+1
386         lda     tmp2
387         clc
388         adc     #$10
389         sta     tmp2
390         jmp     @L3
391
392 ; ------------------------------------------------------------------------
393 ; Helper function for COPYFROM and COPYTO: Store the pointer to the request
394 ; structure and prepare data for the copy
395
396 setup:
397         sta     ptr1
398         stx     ptr1+1                                  ; Save passed pointer
399
400 ; Get the page number from the struct and adjust it so that it may be used
401 ; with the hardware. That is: ptr4 has the page address and page offset
402 ; tmp2 will hold the bank value
403
404         ldy     #EM_COPY::PAGE+1
405         lda     (ptr1),y
406         tax
407         ldy     #EM_COPY::PAGE
408         lda     (ptr1),y
409         jsr     adjust_page_and_bank
410         clc
411         adc     #>BASE
412         sta     ptr4+1
413         stx     tmp2
414
415 ; Get the buffer pointer into ptr2
416
417         ldy     #EM_COPY::BUF
418         lda     (ptr1),y
419         sta     ptr2
420         iny
421         lda     (ptr1),y
422         sta     ptr2+1
423
424 ; Get the count, calculate -(count-1) and store it into ptr3
425
426         ldy     #EM_COPY::COUNT
427         lda     (ptr1),y
428         eor     #$FF
429         sta     ptr3
430         iny
431         lda     (ptr1),y
432         eor     #$FF
433         sta     ptr3+1
434
435 ; Get the page offset into ptr4 and clear tmp1
436
437         ldy     #EM_COPY::OFFS
438         lda     (ptr1),y
439         sta     ptr4
440         lda     #0
441         sta     tmp1
442
443 ; Done
444
445         rts
446
447 ; Helper routines for copying to and from the +256k ram
448
449 backup_and_setup_copy_routine:
450         ldx     #.sizeof (copy) - 1
451 @L1:
452         lda     copy::entry,x
453         sta     backup,x
454         lda     copy::template,x
455         sta     copy::entry,x
456         dex
457         bpl     @L1
458         rts
459
460 backup_and_setup_check_routine:
461         ldx     #.sizeof (check) - 1
462 @L1:
463         lda     check::entry,x
464         sta     backup,x
465         lda     check::template,x
466         sta     check::entry,x
467         dex
468         bpl     @L1
469         rts
470
471 restore_copy_routine:
472         ldx     #.sizeof (copy) - 1
473 restore_data:
474         lda     backup,x
475         sta     TARGETLOC,x
476         dex
477         bpl     restore_data
478         rts
479
480 ; Helper routine to correct for the bank and page
481 adjust_page_and_bank:
482         sta     tmp4
483         lda     #$0C
484         sta     tmp3
485         lda     tmp4
486         and     #$c0
487         lsr
488         lsr
489         ora     tmp3
490         sta     tmp3
491         txa
492         asl
493         asl
494         asl
495         asl
496         asl
497         asl
498         ora     tmp3
499         tax
500         lda     tmp4
501         and     #$3f
502         rts