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