diff --git a/libsrc/atari/Makefile b/libsrc/atari/Makefile index 068a244ba..b81b78abf 100644 --- a/libsrc/atari/Makefile +++ b/libsrc/atari/Makefile @@ -126,7 +126,7 @@ OBJS = _scrsize.o \ #-------------------------------------------------------------------------- # Drivers -EMDS = +EMDS = atari-130xe.emd JOYS = atari-stdjoy.joy atari-multijoy.joy diff --git a/libsrc/atari/atari-130xe.s b/libsrc/atari/atari-130xe.s new file mode 100644 index 000000000..6951bd346 --- /dev/null +++ b/libsrc/atari/atari-130xe.s @@ -0,0 +1,483 @@ +; +; Extended memory driver for the Atari 130XE memory standard +; Shawn Jefferson, 2012-08-11 +; +; Banking Register $D301: +; Bit 7: Self-Test on/off +; Bit 6: Unused +; Bit 5: Antic sees bank +; Bit 4: CPU sees bank +; Bit 3: bank control +; Bit 2: bank control +; Bit 1: BASIC on/off +; Bit 0: OS RAM on/off +; +; Masks: %11100011 $E3 Bank 0 +; %11100111 $E7 Bank 1 +; %11101011 $EB Bank 2 +; %11101111 $EF Bank 3 +; %11111111 $FF Off +; +; Based on the Extended memory driver for the Apple II auxiliary memory +; by +; Stefan Haubenthal, 2003-12-12 +; Ullrich von Bassewitz, 2002-12-02 +; + + .include "zeropage.inc" + + .include "em-kernel.inc" + .include "em-error.inc" + + + .macpack generic + + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.segment "JUMPTABLE" + +; Driver signature + + .byte $65, $6d, $64 ; "emd" + .byte EMD_API_VERSION ; EM API version number + +; Jump table. + + .word INSTALL + .word DEINSTALL + .word PAGECOUNT + .word MAP + .word USE + .word COMMIT + .word COPYFROM + .word COPYTO + +; ------------------------------------------------------------------------ +; Constants + +BANK = $4000 ; bank window +STACK = $0100 ; stack location +PAGES = 256 ; 4 x 16k banks + + +; ------------------------------------------------------------------------ +; Data. + +.rodata +banks: .byte $E3,$E7,$EB,$EF ; 130XE banks for cpu banking + +stacktest: sei + ldy banks + sty $D301 + tax ; A is set by caller + inx + stx $4000 ; change $4000 + ldy #$FF ; STACK+13 + sty $D301 + cmp $4000 ; changed? + beq @1 + sec ; error + bcs @2 +@1: clc +@2: sta $4000 ; restore + cli + rts +stacktest_end: + +stackcopy: sei ; disable interrupts +@1: dex ; pre-decrement (full page x=0) + ldy #$FF ; this will be replaced STACK+3 + sty $D301 ; set bank + lda $FF00,x ; address to copy from STACK+8,+9 + ldy #$FF ; this will be replaced STACK+11 + sty $D301 + sta $FF00,x ; address to copy to STACK+16,+17 + cpx #0 + bne @1 + ldy #$FF ; portb_save STACK+23 + sty $D301 + cli ; enable interrupts + rts +stackcopy_end: + +stackcopy_byte: sei + ldy #$FF ; STACK+2 + sty $D301 + lda $FFFF ; STACK+7 +8 + ldy #$FF ; STACK+10 + sty $D301 + sta $FFFF ; STACK+15 +16 + ldy #$FF ; STACK+18 + sty $D301 + cli + rts +stackcopy_byte_end: + + +.data +curpage: .byte $FF ; Current page number in bank (invalid) +curbank: .byte $FF ; Current bank number + +.bss +window: .res 256 ; Memory "window" +portb_save: .res 1 ; portb state + +.code + +install_transfer: + ldx #stackcopy_end - stackcopy - 1 +@1: lda stackcopy,x + sta STACK,x + dex + bpl @1 + rts + +install_byte_transfer: + ldx #stackcopy_byte_end - stackcopy_byte - 1 +@2: lda stackcopy_byte,x + sta STACK,x + dex + bpl @2 + rts + +install_test: + ldx #stacktest_end - stacktest - 1 +@3: lda stacktest,x + sta STACK,x + dex + bpl @3 + rts + +setpage: + tax ; save page + and #$C0 ; mask out bank + clc + ror + ror ; divide by 64 + ror ; 64 pages in each bank + ror + ror + ror + sta curbank ; Remember the new bank + txa ; bring back page + and #$3F ; mask out page + sta curpage ; curpage in bank + rts + + +; ------------------------------------------------------------------------ +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present and determine the amount of +; memory available. +; Must return an EM_ERR_xx code in a/x. +; + +INSTALL: + lda $D301 ; save state of portb + sta portb_save + tay + + jsr install_test ; doesn't touch Y + sty STACK+13 + + lda $4000 ; test for extended memory + jsr STACK + bcs @1 + lda #EM_ERR_OK + rts +@1: lda #EM_ERR_NO_DEVICE + rts + +; ------------------------------------------------------------------------ +; DEINSTALL routine. Is called before the driver is removed from memory. +; Can do cleanup or whatever. Must not return anything. +; + +DEINSTALL: + rts + + +; ------------------------------------------------------------------------ +; PAGECOUNT: Return the total number of available pages in a/x. +; + +PAGECOUNT: + lda #PAGES + rts + +; ------------------------------------------------------------------------ +; MAP: Map the page in a/x into memory and return a pointer to the page in +; a/x. The contents of the currently mapped page (if any) may be discarded +; by the driver. +; + +MAP: jsr setpage ; extract the bank/page + add #>BANK ; $4000 + page (carry is cleared) + sta ptr1+1 + ;ldy #$00 + ;sty ptr1 + + lda #window + sta ptr2+1 + +; Transfer one page + + jsr install_transfer ; Transfer one page + + ldx curbank + lda banks,x + sta STACK+3 ; set bank to copy from +; lda ptr1 +; sta STACK+8 + lda ptr1+1 + sta STACK+9 ; set copy from address + lda portb_save + sta STACK+11 ; set portb restore + sta STACK+23 ; set final portb restore + lda ptr2 + sta STACK+16 + lda ptr2+1 + sta STACK+17 ; set copy to address + + ldx #0 ; full page copy + jsr STACK ; do the copy! + +; Return the memory window + + lda #window ; Return the window address + + rts + +; ------------------------------------------------------------------------ +; USE: Tell the driver that the window is now associated with a given page. + +USE: ;sta curpage ; Remember the page + jsr setpage ; extract bank/page + lda #window ; Return the window + rts + +; ------------------------------------------------------------------------ +; COMMIT: Commit changes in the memory window to extended storage. + +COMMIT: lda curpage ; Get the current page + cmp #$FF + beq commit_done ; Jump if no page mapped + + clc + add #>BANK + sta ptr2+1 + ;ldy #$00 + ;sty ptr2 + + lda #window + sta ptr1+1 + +; Transfer one page/all bytes + + jsr install_transfer ; Transfer one page + + lda portb_save + sta STACK+3 ; set bank to copy from + sta STACK+23 ; set final portb restore + lda ptr1 + sta STACK+8 + lda ptr1+1 + sta STACK+9 ; set copy from address + ldx curbank + lda banks,x + sta STACK+11 ; set bank to copy to + ;lda ptr2 + ;sta STACK+16 + lda ptr2+1 + sta STACK+17 ; set copy to address + + ldx #0 ; full page copy + jsr STACK ; do the copy! + +commit_done: + rts + + +; ------------------------------------------------------------------------ +; COPYFROM: Copy from extended into linear memory. A pointer to a structure +; describing the request is passed in a/x. +; The function must not return anything. +; +COPYFROM: + sta ptr3 + stx ptr3+1 ; Save the passed em_copy pointer + + jsr install_byte_transfer ; install the stack copy routine + + ldy #EM_COPY::OFFS + lda (ptr3),y + sta STACK+7 ; offset goes into BANK low + + ldy #EM_COPY::PAGE + lda (ptr3),y + sta tmp1 ; save page for later + ;add #>BANK + ;sta STACK+8 ; BANK + page goes into BANK high + + ldy #EM_COPY::BUF + lda (ptr3),y + sta STACK+15 ; buffer goes into dest low + iny + lda (ptr3),y + sta STACK+16 ; buffer goes into dest high + + ldy #EM_COPY::COUNT + lda (ptr3),y ; Get bytes in last page + sta ptr4 + iny + lda (ptr3),y ; Get number of pages + sta ptr4+1 + + lda tmp1 ; extract bank/page + jsr setpage ; sets curbank/curpage + lda curpage + add #>BANK ; add to BANK address + sta STACK+8 ; current page in bank + ldx curbank + lda banks,x + sta STACK+2 ; set bank in stack + lda portb_save + sta STACK+10 ; set bank restore in stack + sta STACK+18 ; set final restore too + +copyfrom_copy: + lda ptr4 ; check if count is zero + bne @4 + lda ptr4+1 + beq done + +@4: jsr STACK ; copy one byte + + sec + lda ptr4 + sub #1 + sta ptr4 + bcs @1 + lda ptr4+1 + beq @1 + sub #1 + sta ptr4+1 + +@1: inc STACK+7 ; increment address in BANK + bne @2 + inc STACK+8 + lda STACK+8 + cmp #$80 ; we stepped outside bank + bne @2 + + inc curbank ; get next bank + ldx curbank + lda banks,x + sta STACK+2 ; set new bank + lda #$40 ; set address back to $4000 + sta STACK+8 + +@2: inc STACK+15 ; increment buffer address + bne @3 + inc STACK+16 + +@3: jmp copyfrom_copy ; copy another byte + +done: + rts + +; ------------------------------------------------------------------------ +; COPYTO: Copy from linear into extended memory. A pointer to a structure +; describing the request is passed in a/x. +; The function must not return anything. +; + +COPYTO: + sta ptr3 + stx ptr3+1 ; Save the passed em_copy pointer + + jsr install_byte_transfer ; install the stack copy routine + + ldy #EM_COPY::OFFS + lda (ptr3),y + sta STACK+15 ; offset goes into BANK low + + ldy #EM_COPY::PAGE + lda (ptr3),y + sta tmp1 ; save page for later + ;add #>BANK + ;sta STACK+16 ; BANK + page goes into BANK high + + ldy #EM_COPY::BUF + lda (ptr3),y + sta STACK+7 ; buffer goes into dest low + iny + lda (ptr3),y + sta STACK+8 ; buffer goes into dest high + + ldy #EM_COPY::COUNT + lda (ptr3),y ; Get bytes in last page + sta ptr4 + iny + lda (ptr3),y ; Get number of pages + sta ptr4+1 + + lda tmp1 ; extract bank/page + jsr setpage ; sets curbank/curpage + lda curpage + add #>BANK ; add to BANK address + sta STACK+16 ; current page in bank + ldx curbank + lda banks,x + sta STACK+10 ; set bank in stack + lda portb_save + sta STACK+2 ; set bank restore in stack + sta STACK+18 ; set final restore too + +copyto_copy: + lda ptr4 ; check if count is zero + bne @4 + lda ptr4+1 + beq done + +@4: jsr STACK ; copy one byte + + sec + lda ptr4 + sub #1 + sta ptr4 + bcs @1 + lda ptr4+1 + beq @1 + sub #1 + sta ptr4+1 + +@1: inc STACK+15 ; increment address in BANK + bne @2 + inc STACK+16 + lda STACK+16 + cmp #$80 ; we stepped outside bank + bne @2 + + inc curbank ; get next bank + ldx curbank + lda banks,x + sta STACK+10 ; set new bank + lda #$40 ; set address back to $4000 + sta STACK+16 + +@2: inc STACK+7 ; increment buffer address + bne @3 + inc STACK+8 + +@3: jmp copyto_copy ; copy another byte +