]> git.sur5r.net Git - cc65/blob - libsrc/c64/c64-c256k.s
New extended memory driver for the C256K memory extension. Written and
[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     #$29
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         ldx     #$0A
216         jsr     restore_data
217         lda     #<window
218         ldx     #>window                ; Return the window address
219         cli
220         rts
221
222 ; ------------------------------------------------------------------------
223 ; USE: Tell the driver that the window is now associated with a given page.
224
225 USE:    sta     curpage         ; Remember the page
226         stx     curpage+1
227         lda     #<window
228         ldx     #>window                ; Return the window
229         rts
230
231 ; ------------------------------------------------------------------------
232 ; COMMIT: Commit changes in the memory window to extended storage.
233
234 COMMIT:
235         sei
236         lda     curpage         ; Get the current page
237         ldx     curpage+1
238
239         jsr     adjust_page_and_bank
240         stx     curbank
241         clc
242         adc     #>BASE
243         sta     ptr1+1
244         ldy     #0
245         sty     ptr1
246         jsr     backup_and_setup_copy_routine
247         ldx     #<ptr1
248         stx     VECC256K
249         ldx     #<STASHOPCODE
250         stx     STASHC256K
251 @L1:
252         ldx     ptr1
253         lda     window,x
254         ldx     curbank
255         jsr     TRANSFERC256K
256         inc     ptr1
257         bne     @L1
258
259 ; Return the memory window
260
261         ldx     #$0A
262         jsr     restore_data
263 done:
264         cli
265         rts
266
267 ; ------------------------------------------------------------------------
268 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
269 ; describing the request is passed in a/x.
270 ; The function must not return anything.
271 ;
272
273
274 COPYFROM:
275         sei
276         jsr     setup
277         jsr     backup_and_setup_copy_routine
278
279 ; Setup is:
280 ;
281 ;   - ptr1 contains the struct pointer
282 ;   - ptr2 contains the linear memory buffer
283 ;   - ptr3 contains -(count-1)
284 ;   - ptr4 contains the page memory buffer plus offset
285 ;   - tmp1 contains zero (to be used for linear memory buffer offset)
286 ;   - tmp2 contains the bank value
287
288         lda     #<ptr4
289         sta     VECC256K
290         jmp     @L3
291
292 @L1:
293         ldx     tmp2
294         ldy     #0
295         jsr     TRANSFERC256K
296         ldy     tmp1
297         sta     (ptr2),y
298         inc     tmp1
299         bne     @L2
300         inc     ptr2+1
301 @L2:
302         inc     ptr4
303         beq     @L4
304
305 ; Bump count and repeat
306
307 @L3:
308         inc     ptr3
309         bne     @L1
310         inc     ptr3+1
311         bne     @L1
312         ldx     #$0A
313         jsr     restore_data
314         cli
315         rts
316
317 ; Bump page register
318
319 @L4:
320         inc     ptr4+1
321         lda     ptr4+1
322         cmp     #$80
323         bne     @L3
324         lda     #>BASE
325         sta     ptr4+1
326         lda     tmp2
327         clc
328         adc     #$10
329         sta     tmp2
330         jmp     @L3
331
332 ; ------------------------------------------------------------------------
333 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
334 ; describing the request is passed in a/x.
335 ; The function must not return anything.
336 ;
337
338 COPYTO:
339         sei
340         jsr     setup
341         jsr     backup_and_setup_copy_routine
342
343 ; Setup is:
344 ;
345 ;   - ptr1 contains the struct pointer
346 ;   - ptr2 contains the linear memory buffer
347 ;   - ptr3 contains -(count-1)
348 ;   - ptr4 contains the page memory buffer plus offset
349 ;   - tmp1 contains zero (to be used for linear memory buffer offset)
350 ;   - tmp2 contains the bank value
351
352         lda     #<ptr4
353         sta     VECC256K
354         lda     #<STASHOPCODE
355         sta     STASHC256K
356         jmp     @L3
357
358 @L1:
359         ldy     tmp1
360         lda     (ptr2),y
361         ldx     tmp2
362         ldy     #0
363         jsr     TRANSFERC256K
364         inc     tmp1
365         bne     @L2
366         inc     ptr2+1
367 @L2:
368         inc     ptr4
369         beq     @L4
370
371 ; Bump count and repeat
372
373 @L3:
374         inc     ptr3
375         bne     @L1
376         inc     ptr3+1
377         bne     @L1
378         ldx     #$0A
379         jsr     restore_data
380         cli
381         rts
382
383 ; Bump page register
384
385 @L4:
386         inc     ptr4+1
387         lda     ptr4+1
388         cmp     #$80
389         bne     @L3
390         lda     #>BASE
391         sta     ptr4+1
392         lda     tmp2
393         clc
394         adc     #$10
395         sta     tmp2
396         jmp     @L3
397
398 ; ------------------------------------------------------------------------
399 ; Helper function for COPYFROM and COPYTO: Store the pointer to the request
400 ; structure and prepare data for the copy
401
402 setup:
403         sta     ptr1
404         stx     ptr1+1                                  ; Save passed pointer
405
406 ; Get the page number from the struct and adjust it so that it may be used
407 ; with the hardware. That is: ptr4 has the page address and page offset
408 ; tmp2 will hold the bank value
409
410         ldy     #EM_COPY::PAGE+1
411         lda     (ptr1),y
412         tax
413         ldy     #EM_COPY::PAGE
414         lda     (ptr1),y
415         jsr     adjust_page_and_bank
416         clc
417         adc     #>BASE
418         sta     ptr4+1
419         stx     tmp2
420
421 ; Get the buffer pointer into ptr2
422
423         ldy     #EM_COPY::BUF
424         lda     (ptr1),y
425         sta     ptr2
426         iny
427         lda     (ptr1),y
428         sta     ptr2+1
429
430 ; Get the count, calculate -(count-1) and store it into ptr3
431
432         ldy     #EM_COPY::COUNT
433         lda     (ptr1),y
434         eor     #$FF
435         sta     ptr3
436         iny
437         lda     (ptr1),y
438         eor     #$FF
439         sta     ptr3+1
440
441 ; Get the page offset into ptr4 and clear tmp1
442
443         ldy     #EM_COPY::OFFS
444         lda     (ptr1),y
445         sta     ptr4
446         lda     #0
447         sta     tmp1
448
449 ; Done
450
451         rts
452
453 ; Helper routines for copying to and from the +256k ram
454
455 backup_and_setup_copy_routine:
456         ldx     #.sizeof (c256kcopycode) - 1
457 @L1:
458         lda     TRANSFERC256K,x
459         sta     backup,x
460         lda     c256kcopycode,x
461         sta     TRANSFERC256K,x
462         dex
463         bpl     @L1
464         rts
465
466 backup_and_setup_check_routine:
467         ldx     #.sizeof (c256kcheckcode) - 1
468 @L1:
469         lda     CHECKC256K,x
470         sta     backup,x
471         lda     c256kcheckcode,x
472         sta     CHECKC256K,x
473         dex
474         bpl     @L1
475         rts
476
477 restore_data:
478         lda     backup,x
479         sta     CHECKC256K,x
480         dex
481         bpl     restore_data
482         rts
483
484 ; Helper routine to correct for the bank and page
485 adjust_page_and_bank:
486         sta     tmp4
487         lda     #$0C
488         sta     tmp3
489         lda     tmp4
490         and     #$c0
491         lsr
492         lsr
493         ora     tmp3
494         sta     tmp3
495         txa
496         asl
497         asl
498         asl
499         asl
500         asl
501         asl
502         ora     tmp3
503         tax
504         lda     tmp4
505         and     #$3f
506         rts