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