2 ; Extended memory driver for the Atari 130XE memory standard
3 ; Shawn Jefferson, 2012-08-11
5 ; Banking Register $D301:
6 ; Bit 7: Self-Test on/off
8 ; Bit 5: Antic sees bank
13 ; Bit 0: OS RAM on/off
15 ; Masks: %11100011 $E3 Bank 0
16 ; %11100111 $E7 Bank 1
17 ; %11101011 $EB Bank 2
18 ; %11101111 $EF Bank 3
21 ; Based on the Extended memory driver for the Apple II auxiliary memory
23 ; Stefan Haubenthal, 2003-12-12
24 ; Ullrich von Bassewitz, 2002-12-02
27 .include "zeropage.inc"
29 .include "em-kernel.inc"
30 .include "em-error.inc"
36 ; ------------------------------------------------------------------------
37 ; Header. Includes jump table
43 .byte $65, $6d, $64 ; "emd"
44 .byte EMD_API_VERSION ; EM API version number
61 ; ------------------------------------------------------------------------
64 BANK = $4000 ; bank window
65 STACK = $0100 ; stack location
66 PAGES = 256 ; 4 x 16k banks
69 ; ------------------------------------------------------------------------
73 banks: .byte $E3,$E7,$EB,$EF ; 130XE banks for cpu banking
78 tax ; A is set by caller
80 stx $4000 ; change $4000
88 @2: sta $4000 ; restore
93 stackcopy: sei ; disable interrupts
94 @1: dex ; pre-decrement (full page x=0)
95 ldy #$FF ; this will be replaced STACK+3
97 lda $FF00,x ; address to copy from STACK+8,+9
98 ldy #$FF ; this will be replaced STACK+11
100 sta $FF00,x ; address to copy to STACK+16,+17
103 ldy #$FF ; portb_save STACK+23
105 cli ; enable interrupts
112 lda $FFFF ; STACK+7 +8
115 sta $FFFF ; STACK+15 +16
124 curpage: .byte $FF ; Current page number in bank (invalid)
125 curbank: .byte $FF ; Current bank number
128 window: .res 256 ; Memory "window"
129 portb_save: .res 1 ; portb state
134 ldx #stackcopy_end - stackcopy - 1
141 install_byte_transfer:
142 ldx #stackcopy_byte_end - stackcopy_byte - 1
143 @2: lda stackcopy_byte,x
150 ldx #stacktest_end - stacktest - 1
159 and #$C0 ; mask out bank
163 ror ; 64 pages in each bank
167 sta curbank ; Remember the new bank
168 txa ; bring back page
169 and #$3F ; mask out page
170 sta curpage ; curpage in bank
174 ; ------------------------------------------------------------------------
175 ; INSTALL routine. Is called after the driver is loaded into memory. If
176 ; possible, check if the hardware is present and determine the amount of
178 ; Must return an EM_ERR_xx code in a/x.
182 lda $D301 ; save state of portb
186 jsr install_test ; doesn't touch Y
189 lda $4000 ; test for extended memory
194 @1: lda #EM_ERR_NO_DEVICE
197 ; ------------------------------------------------------------------------
198 ; UNINSTALL routine. Is called before the driver is removed from memory.
199 ; Can do cleanup or whatever. Must not return anything.
206 ; ------------------------------------------------------------------------
207 ; PAGECOUNT: Return the total number of available pages in a/x.
215 ; ------------------------------------------------------------------------
216 ; MAP: Map the page in a/x into memory and return a pointer to the page in
217 ; a/x. The contents of the currently mapped page (if any) may be discarded
221 MAP: jsr setpage ; extract the bank/page
222 add #>BANK ; $4000 + page (carry is cleared)
234 jsr install_transfer ; Transfer one page
238 sta STACK+3 ; set bank to copy from
242 sta STACK+9 ; set copy from address
244 sta STACK+11 ; set portb restore
245 sta STACK+23 ; set final portb restore
249 sta STACK+17 ; set copy to address
251 ldx #0 ; full page copy
252 jsr STACK ; do the copy!
254 ; Return the memory window
257 ldx #>window ; Return the window address
261 ; ------------------------------------------------------------------------
262 ; USE: Tell the driver that the window is now associated with a given page.
264 USE: ;sta curpage ; Remember the page
265 jsr setpage ; extract bank/page
267 ldx #>window ; Return the window
270 ; ------------------------------------------------------------------------
271 ; COMMIT: Commit changes in the memory window to extended storage.
273 COMMIT: lda curpage ; Get the current page
275 beq commit_done ; Jump if no page mapped
288 ; Transfer one page/all bytes
290 jsr install_transfer ; Transfer one page
293 sta STACK+3 ; set bank to copy from
294 sta STACK+23 ; set final portb restore
298 sta STACK+9 ; set copy from address
301 sta STACK+11 ; set bank to copy to
305 sta STACK+17 ; set copy to address
307 ldx #0 ; full page copy
308 jsr STACK ; do the copy!
314 ; ------------------------------------------------------------------------
315 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
316 ; describing the request is passed in a/x.
317 ; The function must not return anything.
321 stx ptr3+1 ; Save the passed em_copy pointer
323 jsr install_byte_transfer ; install the stack copy routine
327 sta STACK+7 ; offset goes into BANK low
331 sta tmp1 ; save page for later
333 ;sta STACK+8 ; BANK + page goes into BANK high
337 sta STACK+15 ; buffer goes into dest low
340 sta STACK+16 ; buffer goes into dest high
343 lda (ptr3),y ; Get bytes in last page
346 lda (ptr3),y ; Get number of pages
349 lda tmp1 ; extract bank/page
350 jsr setpage ; sets curbank/curpage
352 add #>BANK ; add to BANK address
353 sta STACK+8 ; current page in bank
356 sta STACK+2 ; set bank in stack
358 sta STACK+10 ; set bank restore in stack
359 sta STACK+18 ; set final restore too
362 lda ptr4 ; check if count is zero
367 @4: jsr STACK ; copy one byte
379 @1: inc STACK+7 ; increment address in BANK
383 cmp #$80 ; we stepped outside bank
386 inc curbank ; get next bank
389 sta STACK+2 ; set new bank
390 lda #$40 ; set address back to $4000
393 @2: inc STACK+15 ; increment buffer address
397 @3: jmp copyfrom_copy ; copy another byte
402 ; ------------------------------------------------------------------------
403 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
404 ; describing the request is passed in a/x.
405 ; The function must not return anything.
410 stx ptr3+1 ; Save the passed em_copy pointer
412 jsr install_byte_transfer ; install the stack copy routine
416 sta STACK+15 ; offset goes into BANK low
420 sta tmp1 ; save page for later
422 ;sta STACK+16 ; BANK + page goes into BANK high
426 sta STACK+7 ; buffer goes into dest low
429 sta STACK+8 ; buffer goes into dest high
432 lda (ptr3),y ; Get bytes in last page
435 lda (ptr3),y ; Get number of pages
438 lda tmp1 ; extract bank/page
439 jsr setpage ; sets curbank/curpage
441 add #>BANK ; add to BANK address
442 sta STACK+16 ; current page in bank
445 sta STACK+10 ; set bank in stack
447 sta STACK+2 ; set bank restore in stack
448 sta STACK+18 ; set final restore too
451 lda ptr4 ; check if count is zero
456 @4: jsr STACK ; copy one byte
468 @1: inc STACK+15 ; increment address in BANK
472 cmp #$80 ; we stepped outside bank
475 inc curbank ; get next bank
478 sta STACK+10 ; set new bank
479 lda #$40 ; set address back to $4000
482 @2: inc STACK+7 ; increment buffer address
486 @3: jmp copyto_copy ; copy another byte