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"
37 ; ------------------------------------------------------------------------
38 ; Header. Includes jump table
41 module_header _atrx130_emd
43 module_header _atr130_emd
48 .byte $65, $6d, $64 ; "emd"
49 .byte EMD_API_VERSION ; EM API version number
66 ; ------------------------------------------------------------------------
69 BANK = $4000 ; bank window
70 STACK = $0100 ; stack location
71 PAGES = 256 ; 4 x 16k banks
74 ; ------------------------------------------------------------------------
78 banks: .byte $E3,$E7,$EB,$EF ; 130XE banks for cpu banking
83 tax ; A is set by caller
85 stx $4000 ; change $4000
93 @2: sta $4000 ; restore
98 stackcopy: sei ; disable interrupts
99 @1: dex ; pre-decrement (full page x=0)
100 ldy #$FF ; this will be replaced STACK+3
102 lda $FF00,x ; address to copy from STACK+8,+9
103 ldy #$FF ; this will be replaced STACK+11
105 sta $FF00,x ; address to copy to STACK+16,+17
108 ldy #$FF ; portb_save STACK+23
110 cli ; enable interrupts
117 lda $FFFF ; STACK+7 +8
120 sta $FFFF ; STACK+15 +16
129 curpage: .byte $FF ; Current page number in bank (invalid)
130 curbank: .byte $FF ; Current bank number
133 window: .res 256 ; Memory "window"
134 portb_save: .res 1 ; portb state
139 ldx #stackcopy_end - stackcopy - 1
146 install_byte_transfer:
147 ldx #stackcopy_byte_end - stackcopy_byte - 1
148 @2: lda stackcopy_byte,x
155 ldx #stacktest_end - stacktest - 1
164 and #$C0 ; mask out bank
168 ror ; 64 pages in each bank
172 sta curbank ; Remember the new bank
173 txa ; bring back page
174 and #$3F ; mask out page
175 sta curpage ; curpage in bank
179 ; ------------------------------------------------------------------------
180 ; INSTALL routine. Is called after the driver is loaded into memory. If
181 ; possible, check if the hardware is present and determine the amount of
183 ; Must return an EM_ERR_xx code in a/x.
187 lda $D301 ; save state of portb
191 jsr install_test ; doesn't touch Y
194 lda $4000 ; test for extended memory
199 @1: lda #EM_ERR_NO_DEVICE
202 ; ------------------------------------------------------------------------
203 ; UNINSTALL routine. Is called before the driver is removed from memory.
204 ; Can do cleanup or whatever. Must not return anything.
211 ; ------------------------------------------------------------------------
212 ; PAGECOUNT: Return the total number of available pages in a/x.
220 ; ------------------------------------------------------------------------
221 ; MAP: Map the page in a/x into memory and return a pointer to the page in
222 ; a/x. The contents of the currently mapped page (if any) may be discarded
226 MAP: jsr setpage ; extract the bank/page
227 add #>BANK ; $4000 + page (carry is cleared)
239 jsr install_transfer ; Transfer one page
243 sta STACK+3 ; set bank to copy from
247 sta STACK+9 ; set copy from address
249 sta STACK+11 ; set portb restore
250 sta STACK+23 ; set final portb restore
254 sta STACK+17 ; set copy to address
256 ldx #0 ; full page copy
257 jsr STACK ; do the copy!
259 ; Return the memory window
262 ldx #>window ; Return the window address
266 ; ------------------------------------------------------------------------
267 ; USE: Tell the driver that the window is now associated with a given page.
269 USE: ;sta curpage ; Remember the page
270 jsr setpage ; extract bank/page
272 ldx #>window ; Return the window
275 ; ------------------------------------------------------------------------
276 ; COMMIT: Commit changes in the memory window to extended storage.
278 COMMIT: lda curpage ; Get the current page
280 beq commit_done ; Jump if no page mapped
293 ; Transfer one page/all bytes
295 jsr install_transfer ; Transfer one page
298 sta STACK+3 ; set bank to copy from
299 sta STACK+23 ; set final portb restore
303 sta STACK+9 ; set copy from address
306 sta STACK+11 ; set bank to copy to
310 sta STACK+17 ; set copy to address
312 ldx #0 ; full page copy
313 jsr STACK ; do the copy!
319 ; ------------------------------------------------------------------------
320 ; COPYFROM: Copy from extended into linear memory. A pointer to a structure
321 ; describing the request is passed in a/x.
322 ; The function must not return anything.
326 stx ptr3+1 ; Save the passed em_copy pointer
328 jsr install_byte_transfer ; install the stack copy routine
332 sta STACK+7 ; offset goes into BANK low
336 sta tmp1 ; save page for later
338 ;sta STACK+8 ; BANK + page goes into BANK high
342 sta STACK+15 ; buffer goes into dest low
345 sta STACK+16 ; buffer goes into dest high
348 lda (ptr3),y ; Get bytes in last page
351 lda (ptr3),y ; Get number of pages
354 lda tmp1 ; extract bank/page
355 jsr setpage ; sets curbank/curpage
357 add #>BANK ; add to BANK address
358 sta STACK+8 ; current page in bank
361 sta STACK+2 ; set bank in stack
363 sta STACK+10 ; set bank restore in stack
364 sta STACK+18 ; set final restore too
367 lda ptr4 ; check if count is zero
372 @4: jsr STACK ; copy one byte
384 @1: inc STACK+7 ; increment address in BANK
388 cmp #$80 ; we stepped outside bank
391 inc curbank ; get next bank
394 sta STACK+2 ; set new bank
395 lda #$40 ; set address back to $4000
398 @2: inc STACK+15 ; increment buffer address
402 @3: jmp copyfrom_copy ; copy another byte
407 ; ------------------------------------------------------------------------
408 ; COPYTO: Copy from linear into extended memory. A pointer to a structure
409 ; describing the request is passed in a/x.
410 ; The function must not return anything.
415 stx ptr3+1 ; Save the passed em_copy pointer
417 jsr install_byte_transfer ; install the stack copy routine
421 sta STACK+15 ; offset goes into BANK low
425 sta tmp1 ; save page for later
427 ;sta STACK+16 ; BANK + page goes into BANK high
431 sta STACK+7 ; buffer goes into dest low
434 sta STACK+8 ; buffer goes into dest high
437 lda (ptr3),y ; Get bytes in last page
440 lda (ptr3),y ; Get number of pages
443 lda tmp1 ; extract bank/page
444 jsr setpage ; sets curbank/curpage
446 add #>BANK ; add to BANK address
447 sta STACK+16 ; current page in bank
450 sta STACK+10 ; set bank in stack
452 sta STACK+2 ; set bank restore in stack
453 sta STACK+18 ; set final restore too
456 lda ptr4 ; check if count is zero
461 @4: jsr STACK ; copy one byte
473 @1: inc STACK+15 ; increment address in BANK
477 cmp #$80 ; we stepped outside bank
480 inc curbank ; get next bank
483 sta STACK+10 ; set new bank
484 lda #$40 ; set address back to $4000
487 @2: inc STACK+7 ; increment buffer address
491 @3: jmp copyto_copy ; copy another byte