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