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
57 ; ------------------------------------------------------------------------
60 BANK = $4000 ; bank window
61 STACK = $0100 ; stack location
62 PAGES = 256 ; 4 x 16k banks
65 ; ------------------------------------------------------------------------
69 banks: .byte $E3,$E7,$EB,$EF ; 130XE banks for cpu banking
74 tax ; A is set by caller
76 stx $4000 ; change $4000
84 @2: sta $4000 ; restore
89 stackcopy: sei ; disable interrupts
90 @1: dex ; pre-decrement (full page x=0)
91 ldy #$FF ; this will be replaced STACK+3
93 lda $FF00,x ; address to copy from STACK+8,+9
94 ldy #$FF ; this will be replaced STACK+11
96 sta $FF00,x ; address to copy to STACK+16,+17
99 ldy #$FF ; portb_save STACK+23
101 cli ; enable interrupts
108 lda $FFFF ; STACK+7 +8
111 sta $FFFF ; STACK+15 +16
120 curpage: .byte $FF ; Current page number in bank (invalid)
121 curbank: .byte $FF ; Current bank number
124 window: .res 256 ; Memory "window"
125 portb_save: .res 1 ; portb state
130 ldx #stackcopy_end - stackcopy - 1
137 install_byte_transfer:
138 ldx #stackcopy_byte_end - stackcopy_byte - 1
139 @2: lda stackcopy_byte,x
146 ldx #stacktest_end - stacktest - 1
155 and #$C0 ; mask out bank
159 ror ; 64 pages in each bank
163 sta curbank ; Remember the new bank
164 txa ; bring back page
165 and #$3F ; mask out page
166 sta curpage ; curpage in bank
170 ; ------------------------------------------------------------------------
171 ; INSTALL routine. Is called after the driver is loaded into memory. If
172 ; possible, check if the hardware is present and determine the amount of
174 ; Must return an EM_ERR_xx code in a/x.
178 lda $D301 ; save state of portb
182 jsr install_test ; doesn't touch Y
185 lda $4000 ; test for extended memory
190 @1: lda #EM_ERR_NO_DEVICE
193 ; ------------------------------------------------------------------------
194 ; DEINSTALL routine. Is called before the driver is removed from memory.
195 ; Can do cleanup or whatever. Must not return anything.
202 ; ------------------------------------------------------------------------
203 ; PAGECOUNT: Return the total number of available pages in a/x.
211 ; ------------------------------------------------------------------------
212 ; MAP: Map the page in a/x into memory and return a pointer to the page in
213 ; a/x. The contents of the currently mapped page (if any) may be discarded
217 MAP: jsr setpage ; extract the bank/page
218 add #>BANK ; $4000 + page (carry is cleared)
230 jsr install_transfer ; Transfer one page
234 sta STACK+3 ; set bank to copy from
238 sta STACK+9 ; set copy from address
240 sta STACK+11 ; set portb restore
241 sta STACK+23 ; set final portb restore
245 sta STACK+17 ; set copy to address
247 ldx #0 ; full page copy
248 jsr STACK ; do the copy!
250 ; Return the memory window
253 ldx #>window ; Return the window address
257 ; ------------------------------------------------------------------------
258 ; USE: Tell the driver that the window is now associated with a given page.
260 USE: ;sta curpage ; Remember the page
261 jsr setpage ; extract bank/page
263 ldx #>window ; Return the window
266 ; ------------------------------------------------------------------------
267 ; COMMIT: Commit changes in the memory window to extended storage.
269 COMMIT: lda curpage ; Get the current page
271 beq commit_done ; Jump if no page mapped
284 ; Transfer one page/all bytes
286 jsr install_transfer ; Transfer one page
289 sta STACK+3 ; set bank to copy from
290 sta STACK+23 ; set final portb restore
294 sta STACK+9 ; set copy from address
297 sta STACK+11 ; set bank to copy to
301 sta STACK+17 ; set copy to address
303 ldx #0 ; full page copy
304 jsr STACK ; do the copy!
310 ; ------------------------------------------------------------------------
311 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
312 ; describing the request is passed in a/x.
313 ; The function must not return anything.
317 stx ptr3+1 ; Save the passed em_copy pointer
319 jsr install_byte_transfer ; install the stack copy routine
323 sta STACK+7 ; offset goes into BANK low
327 sta tmp1 ; save page for later
329 ;sta STACK+8 ; BANK + page goes into BANK high
333 sta STACK+15 ; buffer goes into dest low
336 sta STACK+16 ; buffer goes into dest high
339 lda (ptr3),y ; Get bytes in last page
342 lda (ptr3),y ; Get number of pages
345 lda tmp1 ; extract bank/page
346 jsr setpage ; sets curbank/curpage
348 add #>BANK ; add to BANK address
349 sta STACK+8 ; current page in bank
352 sta STACK+2 ; set bank in stack
354 sta STACK+10 ; set bank restore in stack
355 sta STACK+18 ; set final restore too
358 lda ptr4 ; check if count is zero
363 @4: jsr STACK ; copy one byte
375 @1: inc STACK+7 ; increment address in BANK
379 cmp #$80 ; we stepped outside bank
382 inc curbank ; get next bank
385 sta STACK+2 ; set new bank
386 lda #$40 ; set address back to $4000
389 @2: inc STACK+15 ; increment buffer address
393 @3: jmp copyfrom_copy ; copy another byte
398 ; ------------------------------------------------------------------------
399 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
400 ; describing the request is passed in a/x.
401 ; The function must not return anything.
406 stx ptr3+1 ; Save the passed em_copy pointer
408 jsr install_byte_transfer ; install the stack copy routine
412 sta STACK+15 ; offset goes into BANK low
416 sta tmp1 ; save page for later
418 ;sta STACK+16 ; BANK + page goes into BANK high
422 sta STACK+7 ; buffer goes into dest low
425 sta STACK+8 ; buffer goes into dest high
428 lda (ptr3),y ; Get bytes in last page
431 lda (ptr3),y ; Get number of pages
434 lda tmp1 ; extract bank/page
435 jsr setpage ; sets curbank/curpage
437 add #>BANK ; add to BANK address
438 sta STACK+16 ; current page in bank
441 sta STACK+10 ; set bank in stack
443 sta STACK+2 ; set bank restore in stack
444 sta STACK+18 ; set final restore too
447 lda ptr4 ; check if count is zero
452 @4: jsr STACK ; copy one byte
464 @1: inc STACK+15 ; increment address in BANK
468 cmp #$80 ; we stepped outside bank
471 inc curbank ; get next bank
474 sta STACK+10 ; set new bank
475 lda #$40 ; set address back to $4000
478 @2: inc STACK+7 ; increment buffer address
482 @3: jmp copyto_copy ; copy another byte