]> git.sur5r.net Git - cc65/commitdiff
New extended memory driver for the C256K memory extension. Written and
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 4 Feb 2010 19:19:17 +0000 (19:19 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 4 Feb 2010 19:19:17 +0000 (19:19 +0000)
contributed by Marco van den Heuvel with several changes by me.

git-svn-id: svn://svn.cc65.org/cc65/trunk@4577 b7a2c559-68d2-44c3-8de9-860c34a00d81

doc/c64.sgml
libsrc/c64/Makefile
libsrc/c64/c64-c256k.s [new file with mode: 0755]

index e912882112fa3beaec253758aa5abe1cd525c3ff..eca6cec0111ad266b13527322802afb4427bcaa7 100644 (file)
@@ -165,6 +165,10 @@ configuration.
 
 <descrip>
 
+  <tag><tt/c64-c256k.emd/</tag>
+  A driver for the C64 256K memory expansion. This driver offers 768 pages of
+  256 bytes each. Written and contributed by Marco van den Heuvel.
+
   <tag><tt/c64-georam.emd/</tag>
   A driver for the Berkeley Softworks GeoRam cartridge. The driver will
   determine the available RAM from the connected cartridge. It supports 64KB
index 747516a8a64ae1eafaee337e575519054cd498b0..12680767649ed0f0fbcb1d369c39fb5ff24334ed 100644 (file)
@@ -71,7 +71,8 @@ OBJS =        _scrsize.o              \
 #--------------------------------------------------------------------------
 # Drivers
 
-EMDS =  c64-georam.emd          \
+EMDS =  c64-c256k.emd           \
+        c64-georam.emd          \
         c64-isepic.emd          \
         c64-ram.emd             \
         c64-ramcart.emd         \
diff --git a/libsrc/c64/c64-c256k.s b/libsrc/c64/c64-c256k.s
new file mode 100755 (executable)
index 0000000..0578f33
--- /dev/null
@@ -0,0 +1,506 @@
+;
+; Extended memory driver for the C256K memory expansion
+; Marco van den Heuvel, 2010-01-27
+;
+
+        .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  UNINSTALL
+        .word  PAGECOUNT
+        .word  MAP
+        .word  USE
+        .word  COMMIT
+        .word  COPYFROM
+        .word  COPYTO
+
+; ------------------------------------------------------------------------
+; Constants
+
+BASE                    = $4000
+PAGES                   = 3 * 256
+CHECKC256K              = $0200
+TRANSFERC256K           = $0200
+STASHOPCODE             = $91
+pia                     = $DFC0
+
+; ------------------------------------------------------------------------
+; Data.
+
+.data
+
+
+; This function is used to copy code from and to the extended memory
+.proc   c256kcopycode
+.org    ::TRANSFERC256K         ; Assemble for target location
+        stx     pia
+::STASHC256K    := *            ; Location and opcode is patched at runtime
+::VECC256K      := *+1
+        lda     ($00),y
+        ldx     #$dc
+        stx     pia
+        rts
+.reloc
+.endproc
+
+; This function is used to check for the existence of the extended memory
+.proc   c256kcheckcode
+.org    ::CHECKC256K
+        ldy     #$00            ; Assume hardware not present
+
+        lda     #$fc
+        sta     pia
+        lda     $01
+        tax
+        and     #$f8
+        sta     $01
+        lda     $4000
+        cmp     $c000
+        bne     done            ; Jump if not found
+        inc     $c000
+        cmp     $4000
+        beq     done            ; Jump if not found
+
+        ; Hardware is present
+        iny
+done:   stx     $01
+        ldx     #$dc
+        stx     pia
+        rts
+.reloc
+.endproc
+
+; Since the functions above are copied to $200, the current contents of this
+; memory area must be saved into backup storage. Calculate the amount of
+; space necessary.
+.if     .sizeof (c256kcopycode) > .sizeof (c256kcheckcode)
+backupspace     = .sizeof (c256kcopycode)
+.else
+backupspace     = .sizeof (c256kcheckcode)
+.endif
+
+
+.bss
+
+curpage:        .res           2       ; Current page number
+curbank:        .res   1       ; Current bank
+backup:         .res           backupspace     ; Backup area of data in the location
+                                ; where the copy and check routines will be
+window:         .res           256     ; Memory "window"
+
+
+.code
+; ------------------------------------------------------------------------
+; 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    pia+1           ; Select Peripheral Registers
+        ora    #4
+        sta    pia+1
+        tax
+        lda    pia+3
+        ora    #4
+        sta    pia+3
+        tay
+
+        lda    #$DC            ; Set the default memory bank data
+        sta    pia
+        lda    #$FE
+        sta    pia+2
+
+        txa                    ; Select Data Direction Registers
+        and    #$FB
+        sta    pia+1
+        tya
+        and    #$FB
+        sta    pia+3
+
+        lda    #$FF            ; Set the ports to output
+        sta    pia
+        sta    pia+2
+
+        txa
+        and    #$C7
+        ora    #$30            ; Set CA1 and
+        sta    pia+1           ; select Peripheral Registers
+        sty    pia+3
+
+        jsr    backup_and_setup_check_routine
+        jsr    CHECKC256K
+        cli
+        ldx    #$29
+        jsr    restore_data
+        cpy    #$01
+        beq    @present
+        lda    #<EM_ERR_NO_DEVICE
+        ldx    #>EM_ERR_NO_DEVICE
+        rts
+
+@present:
+        lda    #<EM_ERR_OK
+        ldx    #>EM_ERR_OK
+;       rts                    ; Run into UNINSTALL instead
+
+; ------------------------------------------------------------------------
+; UNINSTALL routine. Is called before the driver is removed from memory.
+; Can do cleanup or whatever. Must not return anything.
+;
+
+UNINSTALL:
+        rts
+
+
+; ------------------------------------------------------------------------
+; PAGECOUNT: Return the total number of available pages in a/x.
+;
+
+PAGECOUNT:
+        lda    #<PAGES
+        ldx    #>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:
+        sei
+        sta    curpage         ; Remember the new page
+        stx    curpage+1
+        jsr    adjust_page_and_bank
+        stx    curbank
+        clc
+        adc    #>BASE
+        sta    ptr1+1
+        ldy    #0
+        sty    ptr1
+        jsr    backup_and_setup_copy_routine
+        ldx    #<ptr1
+        stx     VECC256K
+@L1:
+        ldx    curbank
+        jsr    TRANSFERC256K
+        ldx    ptr1
+        sta    window,x
+        inc    ptr1
+        bne    @L1
+
+; Return the memory window
+
+        ldx    #$0A
+        jsr    restore_data
+        lda    #<window
+        ldx    #>window                ; Return the window address
+        cli
+        rts
+
+; ------------------------------------------------------------------------
+; USE: Tell the driver that the window is now associated with a given page.
+
+USE:    sta    curpage         ; Remember the page
+        stx    curpage+1
+        lda    #<window
+        ldx    #>window                ; Return the window
+        rts
+
+; ------------------------------------------------------------------------
+; COMMIT: Commit changes in the memory window to extended storage.
+
+COMMIT:
+        sei
+        lda    curpage         ; Get the current page
+        ldx    curpage+1
+
+        jsr    adjust_page_and_bank
+        stx    curbank
+        clc
+        adc    #>BASE
+        sta    ptr1+1
+        ldy    #0
+        sty    ptr1
+        jsr    backup_and_setup_copy_routine
+        ldx    #<ptr1
+        stx     VECC256K
+        ldx    #<STASHOPCODE
+        stx    STASHC256K
+@L1:
+        ldx    ptr1
+        lda    window,x
+        ldx    curbank
+        jsr    TRANSFERC256K
+        inc    ptr1
+        bne    @L1
+
+; Return the memory window
+
+        ldx    #$0A
+        jsr    restore_data
+done:
+        cli
+        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:
+        sei
+        jsr    setup
+        jsr    backup_and_setup_copy_routine
+
+; Setup is:
+;
+;   - ptr1 contains the struct pointer
+;   - ptr2 contains the linear memory buffer
+;   - ptr3 contains -(count-1)
+;   - ptr4 contains the page memory buffer plus offset
+;   - tmp1 contains zero (to be used for linear memory buffer offset)
+;   - tmp2 contains the bank value
+
+        lda    #<ptr4
+        sta     VECC256K
+        jmp    @L3
+
+@L1:
+        ldx    tmp2
+        ldy    #0
+        jsr    TRANSFERC256K
+        ldy    tmp1
+        sta    (ptr2),y
+        inc    tmp1
+        bne    @L2
+        inc    ptr2+1
+@L2:
+        inc    ptr4
+        beq    @L4
+
+; Bump count and repeat
+
+@L3:
+        inc    ptr3
+        bne    @L1
+        inc    ptr3+1
+        bne    @L1
+        ldx    #$0A
+        jsr    restore_data
+        cli
+        rts
+
+; Bump page register
+
+@L4:
+        inc    ptr4+1
+        lda    ptr4+1
+        cmp    #$80
+        bne    @L3
+        lda    #>BASE
+        sta    ptr4+1
+        lda    tmp2
+        clc
+        adc    #$10
+        sta    tmp2
+        jmp    @L3
+
+; ------------------------------------------------------------------------
+; 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:
+        sei
+        jsr    setup
+        jsr    backup_and_setup_copy_routine
+
+; Setup is:
+;
+;   - ptr1 contains the struct pointer
+;   - ptr2 contains the linear memory buffer
+;   - ptr3 contains -(count-1)
+;   - ptr4 contains the page memory buffer plus offset
+;   - tmp1 contains zero (to be used for linear memory buffer offset)
+;   - tmp2 contains the bank value
+
+        lda    #<ptr4
+        sta     VECC256K
+        lda    #<STASHOPCODE
+        sta    STASHC256K
+        jmp    @L3
+
+@L1:
+        ldy    tmp1
+        lda    (ptr2),y
+        ldx    tmp2
+        ldy    #0
+        jsr    TRANSFERC256K
+        inc    tmp1
+        bne    @L2
+        inc    ptr2+1
+@L2:
+        inc    ptr4
+        beq    @L4
+
+; Bump count and repeat
+
+@L3:
+        inc    ptr3
+        bne    @L1
+        inc    ptr3+1
+        bne    @L1
+        ldx    #$0A
+        jsr    restore_data
+        cli
+        rts
+
+; Bump page register
+
+@L4:
+        inc    ptr4+1
+        lda    ptr4+1
+        cmp     #$80
+        bne    @L3
+        lda    #>BASE
+        sta    ptr4+1
+        lda    tmp2
+        clc
+        adc    #$10
+        sta    tmp2
+        jmp    @L3
+
+; ------------------------------------------------------------------------
+; Helper function for COPYFROM and COPYTO: Store the pointer to the request
+; structure and prepare data for the copy
+
+setup:
+        sta    ptr1
+        stx    ptr1+1                                  ; Save passed pointer
+
+; Get the page number from the struct and adjust it so that it may be used
+; with the hardware. That is: ptr4 has the page address and page offset
+; tmp2 will hold the bank value
+
+        ldy    #EM_COPY::PAGE+1
+        lda    (ptr1),y
+        tax
+        ldy    #EM_COPY::PAGE
+        lda    (ptr1),y
+        jsr    adjust_page_and_bank
+        clc
+        adc    #>BASE
+        sta    ptr4+1
+        stx    tmp2
+
+; Get the buffer pointer into ptr2
+
+        ldy    #EM_COPY::BUF
+        lda    (ptr1),y
+        sta    ptr2
+        iny
+        lda    (ptr1),y
+        sta    ptr2+1
+
+; Get the count, calculate -(count-1) and store it into ptr3
+
+        ldy    #EM_COPY::COUNT
+        lda    (ptr1),y
+        eor    #$FF
+        sta    ptr3
+        iny
+        lda    (ptr1),y
+        eor    #$FF
+        sta    ptr3+1
+
+; Get the page offset into ptr4 and clear tmp1
+
+        ldy    #EM_COPY::OFFS
+        lda    (ptr1),y
+        sta    ptr4
+        lda    #0
+        sta    tmp1
+
+; Done
+
+        rts
+
+; Helper routines for copying to and from the +256k ram
+
+backup_and_setup_copy_routine:
+        ldx    #.sizeof (c256kcopycode) - 1
+@L1:
+        lda            TRANSFERC256K,x
+        sta    backup,x
+        lda    c256kcopycode,x
+        sta    TRANSFERC256K,x
+        dex
+        bpl    @L1
+        rts
+
+backup_and_setup_check_routine:
+        ldx    #.sizeof (c256kcheckcode) - 1
+@L1:
+        lda    CHECKC256K,x
+        sta    backup,x
+        lda    c256kcheckcode,x
+        sta    CHECKC256K,x
+        dex
+        bpl    @L1
+        rts
+
+restore_data:
+        lda    backup,x
+        sta    CHECKC256K,x
+        dex
+        bpl    restore_data
+        rts
+
+; Helper routine to correct for the bank and page
+adjust_page_and_bank:
+        sta    tmp4
+        lda    #$0C
+        sta     tmp3
+        lda    tmp4
+        and    #$c0
+        lsr
+        lsr
+        ora    tmp3
+        sta    tmp3
+        txa
+        asl
+        asl
+        asl
+        asl
+        asl
+        asl
+        ora    tmp3
+        tax
+        lda    tmp4
+        and    #$3f
+        rts