]> git.sur5r.net Git - cc65/blobdiff - libsrc/atari/shadow_ram_prepare.s
Use labels instead of segment load addresses to specify entry points
[cc65] / libsrc / atari / shadow_ram_prepare.s
index 2fc8ffbc3aa45b82b0152f44b9d9784bad31713e..78e7ba4f0de5c103cc9413c407b89cb78aef6cc8 100644 (file)
@@ -3,48 +3,52 @@
 ;
 ; Tasks:
 ; - move screen memory below load address
+; - copy ROM chargen to its new place
 ; - copy shadow RAM contents to their destination
 ;
 ; Christian Groessler, chris@groessler.org, 2013
 ;
 
+DEBUG   =       1
+
 .if .defined(__ATARIXL__)
 
-       .export         sramprep
+        .export         sramprep
         .import         __SRPREP_LOAD__, __SRPREP_SIZE__
-       .import         __SHADOW_RAM_LOAD__, __SHADOW_RAM_SIZE__
-       .import         __CHARGEN_LOAD__, __CHARGEN_SIZE__
-       .import         __SAVEAREA_LOAD__
+        .import         __SHADOW_RAM_LOAD__, __SHADOW_RAM_SIZE__
+        .import         __SHADOW_RAM_RUN__
+        .import         __CHARGEN_START__, __CHARGEN_SIZE__
+        .import         __SAVEAREA_LOAD__
 
         .include        "zeropage.inc"
         .include        "atari.inc"
-       .include        "save_area.inc"
+        .include        "save_area.inc"
 
 .macro print_string text
-       .local  start, cont
-       jmp     cont
-start: .byte   text, ATEOL
-cont:  ldx     #0              ; channel 0
-       lda     #<start
-       sta     ICBAL,x         ; address
-       lda     #>start
-       sta     ICBAH,x
-       lda     #<(cont - start)
-       sta     ICBLL,x         ; length
-       lda     #>(cont - start)
-       sta     ICBLH,x
-       lda     #PUTCHR
-       sta     ICCOM,x
-       jsr     CIOV
+        .local  start, cont
+        jmp     cont
+start:  .byte   text, ATEOL
+cont:   ldx     #0              ; channel 0
+        lda     #<start
+        sta     ICBAL,x         ; address
+        lda     #>start
+        sta     ICBAH,x
+        lda     #<(cont - start)
+        sta     ICBLL,x         ; length
+        lda     #>(cont - start)
+        sta     ICBLH,x
+        lda     #PUTCHR
+        sta     ICCOM,x
+        jsr     CIOV_org
 .endmacro
 
 ; ------------------------------------------------------------------------
-; Chunk header
+; EXE load chunk header
 
 .segment        "SRPREPHDR"
 
         .word   __SRPREP_LOAD__
-        .word   __SRPREP_LOAD__ + __SRPREP_SIZE__ - 1
+        .word   __SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__ - 1
 
 ; ------------------------------------------------------------------------
 ; Actual code
@@ -52,52 +56,64 @@ cont:       ldx     #0              ; channel 0
 .segment        "SRPREP"
 
 sramprep:
-       print_string "in sramprep"
+.ifdef DEBUG
+        print_string "entering stage #2"
+.endif
 
 ; save values of modified system variables and ports
-       lda     RAMTOP
-       sta     RAMTOP_save
-       lda     MEMTOP
-       sta     MEMTOP_save
-       lda     MEMTOP+1
-       sta     MEMTOP_save+1
-       lda     APPMHI
-       sta     APPMHI_save
-       lda     APPMHI+1
-       sta     APPMHI_save+1
-       lda     PORTB
-       sta     PORTB_save
 
-; disable BASIC
+        lda     RAMTOP
+        sta     RAMTOP_save
+        lda     MEMTOP
+        sta     MEMTOP_save
+        lda     MEMTOP+1
+        sta     MEMTOP_save+1
+        lda     APPMHI
+        sta     APPMHI_save
+        lda     APPMHI+1
+        sta     APPMHI_save+1
+        lda     PORTB
+        sta     PORTB_save
 
-       lda     PORTB
-       ora     #2
-       sta     PORTB
+; disable BASIC
 
+        lda     PORTB
+        ora     #2
+        sta     PORTB
 
-; ... change memory bla
+        .include "xlmemchk.inc" ; calculate lowest address used and new value for RAMTOP
 
-CMPVAL = 64+255+992            ; you may ask, why these values...   @@@ document
+        ldx     lowadr
+        stx     MEMTOP
+        lda     lowadr+1
+        sta     MEMTOP+1
+        lda     lodadr+1
+        sta     RAMTOP
 
-sys_ok:        lda     #<__SAVEAREA_LOAD__
-       sec
-       sbc     #<CMPVAL
-       sta     MEMTOP
-       sta     APPMHI
-       lda     #>__SAVEAREA_LOAD__
-       sbc     #>CMPVAL
-       sta     MEMTOP+1
-       sta     APPMHI+1
+       ; set APPMHI to MEMLO (+ 1 for sanity)
+        lda     MEMLO
+        clc
+        adc     #1
+        sta     APPMHI
+        lda     MEMLO+1
+        adc     #0
+        sta     APPMHI+1
 
-       lda     #>__SAVEAREA_LOAD__ - 1
-       sta     RAMTOP
-       
-       
 
-; ... issue ar GRAPHICS 0 call (copied'n'pasted from TGI drivers)
+; issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers) to move screen memory down
 
 
-       ldx     #$50            ; take any IOCB, hopefully free (@@@ fixme)
+        jsr     findfreeiocb
+.ifdef DEBUG           ; only check in debug version, this shouldn't really happen(tm)
+        beq     iocbok
+        print_string "Internal error, no free IOCB!"
+        jsr     delay
+        jsr     delay
+        jsr     delay
+        jsr     restore                 ; restore stuff we've changed
+        jmp     (DOSVEC)                ; abort loading
+iocbok:
+.endif
 
         ; Reopen it in Graphics 0
         lda     #OPEN
@@ -114,72 +130,250 @@ sys_ok:  lda     #<__SAVEAREA_LOAD__
         sta     ICBLL,x
         lda     #>screen_device_length
         sta     ICBLH,x
-        jsr     CIOV
-       bpl     okoko
-
-       print_string "GR 0 FAILED"
-       jsr     delay
-       jsr     delay
-       jsr     delay
+        jsr     CIOV_org
+        bpl     scrok
 
-       jmp xxx
+; shouldn't happen(tm)
+        print_string "Internal error, aborting..."
+        jsr     delay
+        jsr     delay
+        jsr     delay
+        jsr     restore                 ; restore stuff we've changed
+        jmp     (DOSVEC)                ; abort loading
 
-okoko:
 
-
-        ; Now close it again; we don't need it anymore :)
+scrok:  ; now close it again -- we don't need it anymore
         lda     #CLOSE
         sta     ICCOM,x
-        jsr     CIOV
-
-       print_string "GR 0 OKOKO"
-       jsr     delay
+        jsr     CIOV_org
 
 
+; copy chargen to low memory
 
+.ifdef DEBUG
+        print_string "copy chargen to low memory"
+.endif
 
+        lda     #>(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
+        sta     ptr3+1
+        lda     #<(__SRPREP_LOAD__ + __SRPREP_SIZE__ + __SHADOW_RAM_SIZE__)
+        sta     ptr3
+        beq     cg_addr_ok
 
+        ; page align the new chargen address
+        inc     ptr3+1
+        lda     #0
+        sta     ptr3
+
+cg_addr_ok:
+
+        lda     ptr3+1
+        and     #3
+        beq     cg_addr_ok2
+
+        ; align to next 1K boundary
+        lda     ptr3+1
+        and     #$fc
+        clc
+        adc     #4
+        sta     ptr3+1
+
+cg_addr_ok2:
+
+        lda     #<DCSORG
+        sta     ptr1
+        lda     #>DCSORG
+        sta     ptr1+1
+        lda     ptr3
+        sta     ptr2
+        lda     ptr3+1
+        pha                             ; needed later to set CHBAS/CHBASE
+        sta     ptr2+1
+        lda     #>__CHARGEN_SIZE__
+        sta     tmp2
+        lda     #<__CHARGEN_SIZE__
+        sta     tmp1
+        jsr     memcopy
+
+.ifdef DEBUG
+        print_string "now setting up high memory"
+.endif
+
+; disable ROM
+        sei
+        ldx     #0
+        stx     NMIEN                   ; disable NMI
+        lda     PORTB
+        and     #$fe
+        tax
+        pla                             ; get temp. chargen address
+        sta     WSYNC                   ; wait for horiz. retrace
+        stx     PORTB                   ; now ROM is mapped out
+
+; switch to temporary chargen
+
+        sta CHBASE
+        sta CHBAS
+
+; copy shadow RAM contents to their destination
+
+        lda     #<__SHADOW_RAM_SIZE__
+        bne     do_copy
+        lda     #>__SHADOW_RAM_SIZE__
+        beq     no_copy                 ; we have no shadow RAM contents
+
+        ; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
+do_copy:lda     #<__SHADOW_RAM_LOAD__
+        sta     ptr1
+        lda     #>__SHADOW_RAM_LOAD__
+        sta     ptr1+1
+        lda     #<__SHADOW_RAM_RUN__
+        sta     ptr2
+        lda     #>__SHADOW_RAM_RUN__
+        sta     ptr2+1
+        lda     #<__SHADOW_RAM_SIZE__
+        sta     tmp1
+        lda     #>__SHADOW_RAM_SIZE__
+        sta     tmp2
+
+        jsr     memcopy
+
+no_copy:
+
+; copy chargen to its new (final) location
+
+        lda     ptr3
+        sta     ptr1
+        lda     ptr3+1
+        sta     ptr1+1
+        lda     #<__CHARGEN_START__
+        sta     ptr2
+        lda     #>__CHARGEN_START__
+        sta     ptr2+1
+        lda     #>__CHARGEN_SIZE__
+        sta     tmp2
+        lda     #<__CHARGEN_SIZE__
+        sta     tmp1
+        jsr     memcopy
+
+; re-enable ROM
+
+        lda     PORTB
+        ora     #1
+        ldx     #>DCSORG
+        sta     WSYNC                   ; wait for horiz. retrace
+        sta     PORTB
+        stx     CHBASE
+        stx     CHBAS
+        lda     #$40
+        sta     NMIEN                   ; enable VB again
+        cli                             ; and enable IRQs
+
+.ifdef DEBUG
+        print_string "Stage #2 OK"
+        print_string "loading main chunk"
+        jsr     delay
+.endif
+        rts
 
-xxx:
+.include "findfreeiocb.inc"
 
+; routine taken from http://www.obelisk.demon.co.uk/6502/algorithms.html
+;
+; copy memory
+; ptr1      - source
+; ptr2      - destination
+; tmp2:tmp1 - len
+
+.proc   memcopy
+
+        ldy     #0
+        ldx     tmp2
+        beq     last
+pagecp: lda     (ptr1),y
+        sta     (ptr2),y
+        iny
+        bne     pagecp
+        inc     ptr1+1
+        inc     ptr2+1
+        dex
+        bne     pagecp
+last:   cpy     tmp1
+        beq     done
+        lda     (ptr1),y
+        sta     (ptr2),y
+        iny
+        bne     last
+done:   rts
 
+.endproc
 
 
+; clean up after a fatal error
 
+restore:lda     RAMTOP_save
+        sta     RAMTOP
+        lda     MEMTOP_save
+        sta     MEMTOP
+        lda     MEMTOP_save+1
+        sta     MEMTOP+1
+        lda     APPMHI_save
+        sta     APPMHI
+        lda     APPMHI_save+1
+        sta     APPMHI+1
         rts
 
+
+.ifdef DEBUG
+
+.byte "HERE ****************** HERE ***************>>>>>>"
+
+sramsize:
+        .word   __SHADOW_RAM_SIZE__
+
 ; short delay
-.proc  delay
-
-       lda     #10
-l:     jsr     delay1
-       clc
-       sbc     #0
-       bne     l
-       rts
-
-delay1:        ldx     #0
-       ldy     #0
-loop:  dey
-       bne     loop
-       dex
-       bne     loop
-       rts
+.proc   delay
+
+        lda     #10
+l:      jsr     delay1
+        clc
+        sbc     #0
+        bne     l
+        rts
+
+delay1: ldx     #0
+        ldy     #0
+loop:   dey
+        bne     loop
+        dex
+        bne     loop
+        rts
 
 .endproc
 
-screen_device: .byte "S:",0
+.endif          ; .ifdef DEBUG
+
+screen_device:  .byte "S:",0
 screen_device_length = * - screen_device
 
-       .byte   " ** srprep ** end-->"
+.ifdef DEBUG
+        .byte   " ** srprep ** end-->"
+.endif
+
+; ------------------------------------------------------------------------
+; Provide an empty SHADOW_RAM segment in order that the linker is happy
+; if the user program doesn't have a SHADOW_RAM segment.
+
+.segment        "SHADOW_RAM"
+
 
 ; ------------------------------------------------------------------------
-; Chunk "trailer" - sets INITAD
+; EXE load chunk "trailer" - sets INITAD
 
 .segment        "SRPREPTRL"
 
         .word   INITAD
         .word   INITAD+1
-        .word   __SRPREP_LOAD__
+        .word   sramprep
 
-.endif ; .if .defined(__ATARIXL__)
+.endif  ; .if .defined(__ATARIXL__)