]> git.sur5r.net Git - cc65/commitdiff
Redesigned the IRQ and BREAK logic, debugged the mouse routines
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 13 Sep 2001 15:27:19 +0000 (15:27 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 13 Sep 2001 15:27:19 +0000 (15:27 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@898 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/c128/README [new file with mode: 0644]
libsrc/c128/break.s
libsrc/c128/c128.inc
libsrc/c128/crt0.s
libsrc/c128/mouse.s

diff --git a/libsrc/c128/README b/libsrc/c128/README
new file mode 100644 (file)
index 0000000..a1af617
--- /dev/null
@@ -0,0 +1,6 @@
+Implementation notes:
+
+CONDES routines with a type code of 2 are used to implement interrupt
+handlers. Note that these are called as soon as the program is started,
+so they have to cope with this.
+
index 6f4cfe42059eed8c697da9a520e6c1fbaf049f52..0ecdc85ec862dc364befca9b948b62c400f11239 100644 (file)
@@ -8,7 +8,8 @@
                .export         _set_brk, _reset_brk
        .destructor     _reset_brk
        .export         _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc
-       .importzp       ptr1
+       .import         BRKStub, BRKOld, BRKInd
+       .importzp       ptr1
 
        .include        "c128.inc"
 
@@ -20,18 +21,11 @@ _brk_y:             .res    1
 _brk_sr:       .res    1
 _brk_pc:       .res    2
 
-oldvec:        .res    2               ; Old vector
-
-
 .data
-uservec:       jmp     $FFFF           ; Patched at runtime
+uservec:       jmp     $FFFF           ; Patched at runtime
 
 .code
 
-; Where will we put the break stub?
-stub_addr      = $0E00                 ; BASIC sprite area
-
-
 
 ; Set the break vector
 .proc  _set_brk
@@ -39,26 +33,26 @@ stub_addr   = $0E00                 ; BASIC sprite area
        sta     uservec+1
        stx     uservec+2       ; Set the user vector
 
-       lda     oldvec
-       ora     oldvec+1        ; Did we save the vector already?
-               bne     L2              ; Jump if we installed the handler already
+       lda     BRKOld+1
+       ora     BRKOld+2        ; Did we save the vector already?
+               bne     @L1             ; Jump if we installed the handler already
 
-       lda     BRKVec
-       sta     oldvec
+       lda     BRKVec          ; Save the old vector
+       sta     BRKOld+1
        lda     BRKVec+1
-       sta     oldvec+1        ; Save the old vector
+       sta     BRKOld+2
+
+       lda     #<BRKStub       ; Set the break vector to our stub
+       ldx     #>BRKStub
+       sta     BRKVec
+       stx     BRKVec+1
 
-       ldy     #stub_size-1    ; Copy our stub into the low mem area
-L1:    lda     brk_stub,y
-       sta     stub_addr,y
-       dey
-       bpl     L1
+       lda     #<brk_handler   ; Set the indirect vector to our handler
+       ldx     #>brk_handler
+       sta     BRKInd+1
+       stx     BRKInd+2
 
-L2:            lda     #<stub_addr     ; Set the break vector to our stub
-       sta     BRKVec
-       lda     #>stub_addr
-       sta     BRKVec+1
-       rts
+@L1:           rts
 
 .endproc
 
@@ -66,12 +60,14 @@ L2:         lda     #<stub_addr     ; Set the break vector to our stub
 ; Reset the break vector
 .proc  _reset_brk
 
-       lda     oldvec
-       bne     @L1
-       ldx     oldvec
-       beq     @L9             ; Jump if vector not installed
-@L1:   sta     BRKVec
-       stx     BRKVec+1
+       lda     BRKOld+1
+       ldx     BRKOld+2
+       beq     @L9             ; Jump if vector not installed
+       sta     BRKVec
+       stx     BRKVec+1
+       lda     #$00
+       sta     BRKOld+1        ; Clear the saved vector
+       sta     BRKOld+2
 @L9:   rts
 
 .endproc
@@ -115,11 +111,3 @@ L2:        lda     #<stub_addr     ; Set the break vector to our stub
 .endproc
 
 
-brk_stub:
-       .org    stub_addr
-               pla                     ; Get original MMU value
-       sta     MMU_CR          ; Re-enable our config
-       jmp     brk_handler     ; Jump to the user handler
-       .reloc
-
-stub_size      = * - brk_stub
index 7bfcfcd074d5fe5cdc43e974bf4cd6624426d70b..d97abd48c81b2925f2bddffcab7d409fbbad6a4a 100644 (file)
@@ -23,6 +23,7 @@ CRAM_PTR              = $E2           ; Pointer to current char in color RAM
 
 CHARCOLOR       = $F1
 FKEY_COUNT             = $D1           ; Characters for function key
+INIT_STATUS    = $A04          ; Flag: Reset/NMI Status
 FKEY_LEN       = $1000         ; Function key lengths
 FKEY_TEXT      = $100A         ; Function key texts
 
index cabef41da6b1ff5666f8c08eefd52a3920ac4e53..a1c97ce76cc3979d89de33133955e404b97482e2 100644 (file)
@@ -4,13 +4,22 @@
 ; This must be the *first* file on the linker command line
 ;
 
-       .export         _exit
-       .import         initlib, donelib
-       .import         initconio, doneconio, zerobss
-       .import         push0, _main
+       .export         _exit
+       .export         BRKStub, BRKOld, BRKInd
+       .import         condes, initlib, donelib
+       .import         initconio, doneconio, zerobss
+       .import         push0, _main
+       .import         __IRQFUNC_TABLE__, __IRQFUNC_COUNT__
+       .import         __RAM_START__, __RAM_SIZE__
 
-       .include        "c128.inc"
-       .include        "../cbm/cbm.inc"
+       .include        "c128.inc"
+       .include        "../cbm/cbm.inc"
+
+; ------------------------------------------------------------------------
+; Constants
+
+CC65_MMU_CFG   = $0E   ; Bank 0 with kernal ROM
+IRQInd         = $2FD  ; JMP $0000 - used as indirect IRQ vector
 
 ; ------------------------------------------------------------------------
 ; Define and export the ZP variables for the C64 runtime
@@ -74,8 +83,8 @@ L1:   lda     sp,x
 
        lda     MMU_CR          ; Get current memory configuration...
                pha                     ; ...and save it for later
-       lda     #$0E            ; Bank0 with kernal ROM
-       sta     MMU_CR
+               lda     #CC65_MMU_CFG   ; Bank0 with kernal ROM
+       sta     MMU_CR
 
 ; Clear the BSS data
 
@@ -89,10 +98,10 @@ L1: lda     sp,x
                tsx
                stx     spsave          ; save system stk ptr
 
-       lda     #<$C000
-       sta     sp
-       lda     #>$C000
-       sta     sp+1
+       lda     #<(__RAM_START__ + __RAM_SIZE__)
+       sta     sp
+       lda     #>(__RAM_START__ + __RAM_SIZE__)
+               sta     sp+1            ; Set argument stack ptr
 
 ; Call module constructors
 
@@ -102,17 +111,43 @@ L1:       lda     sp,x
 
        jsr     initconio
 
+; If we have IRQ functions, chain our stub into the IRQ vector
+
+        lda     #<__IRQFUNC_COUNT__
+       beq     NoIRQ1
+       lda     IRQVec
+               ldx     IRQVec+1
+       sta     IRQInd+1
+       stx     IRQInd+2
+       lda     #<IRQStub
+       ldx     #>IRQStub
+       sei
+       sta     IRQVec
+       stx     IRQVec+1
+       cli
+
 ; Pass an empty command line
 
-       jsr     push0           ; argc
-       jsr     push0           ; argv
+NoIRQ1:        jsr     push0           ; argc
+       jsr     push0           ; argv
 
        ldy     #4              ; Argument size
                jsr     _main           ; call the users code
 
-; Call module destructors. This is also the _exit entry.
+; This is also the _exit entry. Reset the IRQ vector if we chained it.
+
+_exit:  lda     #<__IRQFUNC_COUNT__
+       beq     NoIRQ2
+       lda     IRQInd+1
+       ldx     IRQInd+2
+       sei
+       sta     IRQVec
+       stx     IRQVec+1
+       cli
+
+; Run module destructors
 
-_exit: jsr     donelib         ; Run module destructors
+NoIRQ2: jsr            donelib
 
 ; Reset the conio stuff
 
@@ -120,9 +155,9 @@ _exit:      jsr     donelib         ; Run module destructors
 
 ; Reset stack and the MMU
 
-       ldx     spsave          ; Patched at runtime
+       ldx     spsave
        txs
-               lda     mmusave         ; Patched at runtime
+               lda     mmusave
        sta     MMU_CR
 
 ; Copy back the zero page stuff
@@ -137,9 +172,52 @@ L2:        lda     zpsave,x
 
        jmp     RESTOR
 
+; ------------------------------------------------------------------------
+; The C128 has ROM parallel to the RAM starting from $4000. The startup code
+; above will change this setting so that we have RAM from $0000-$BFFF. This
+; works quite well with the exception of interrupts: The interrupt handler
+; is in ROM, and the ROM switches back to the ROM configuration, which means
+; that parts of our program may not be accessible. Since the crt0 module is
+; the first module in the program, it will always be below $4000 and always
+; in RAM. So we place several short stubs here that switch back our ROM
+; config before calling our user defined handlers. These stubs are only
+; used if any other code uses the interrupt or break vectors. They are dead
+; code otherwise, but since there is no other way to keep them in low memory,
+; they have to go here.
+
+IRQStub:
+       cld                             ; Just to be sure
+       lda     MMU_CR                  ; Get old register value
+       pha                             ; And save on stack
+       lda     #CC65_MMU_CFG           ; Bank 0 with kernal ROM
+       sta     MMU_CR
+       ldy     #<(__IRQFUNC_COUNT__*2)
+               lda     #<__IRQFUNC_TABLE__
+       ldx     #>__IRQFUNC_TABLE__
+       jsr     condes                  ; Call the functions
+       pla                             ; Get old register value
+       sta     MMU_CR
+               jmp     IRQInd                  ; Jump to the save IRQ vector
+
+
+BRKStub:
+       pla                             ; Get original MMU_CR value
+       sta     MMU_CR                  ; And set it
+               jmp     BRKInd                  ; Jump indirect to break
+
+
+; ------------------------------------------------------------------------
+; Data
+
 .data
 zpsave:        .res    zpspace
 
+; Old break vector preceeded by a jump opcode
+BRKOld: jmp     $0000
+
+; Indirect vectors preceeded by a jump opcode
+BRKInd: jmp     $0000
+
 .bss
 spsave:        .res    1
 mmusave:.res   1
index 20a7b48a2030ba77766babf2509318e7ded3ef82..493d297fc4d3fe5ce6f47a2fd10875cd7a412d92 100644 (file)
@@ -10,6 +10,7 @@
        .export         _mouse_box, _mouse_info
        .export         _mouse_move, _mouse_pos
        .export         _mouse_buttons, _mouse_info
+       .condes         MouseIRQ, 2
 
        .import         _readjoy
                .import         popa, popax, addysp1
@@ -39,10 +40,11 @@ XCORR               = SPRITE_WIDTH
 ;                                       unsigned char type);
 ;
 
-_mouse_init:
+.proc  _mouse_init
+
        jsr     popa                    ; Ignore type and port
 
-               ldy     OldIRQ+1                ; Already initialized?
+               lda     Initialized             ; Already initialized?
                bne     AlreadyInitialized      ; Jump if yes
 
 ; Initialize variables
@@ -75,49 +77,53 @@ _mouse_init:
        sta     XMax
        stx     XMax+1                  ; XMax = 320 + sprite width
 
-; Remember the old IRQ vector
+; Save the old init status and reset bit 0. This will disable the BASIC
+; IRQ handler which will otherwise try to manage the mouse sprite on its
+; own
 
-       lda     IRQVec
-       sta     OldIRQ       
-       lda     IRQVec+1
-       sta     OldIRQ+1
+        lda    INIT_STATUS
+       sta     OldInitStatus
+       and     #$FE
+       sta     INIT_STATUS
 
-; Set our own IRQ vector. We cheat here to save a few bytes of code:
-; The function is expected to return a value not equal to zero on success,
-; and since we know that the high byte of the IRQ handler address is never
-; zero, we will return just this byte.
+; Mouse successfully initialized
 
-       ldx     #<MouseIRQ
-       lda     #>MouseIRQ
-       bne     SetIRQ                  ; Branch always
+        lda     #1
+       sta     Initialized
+       rts
 
 AlreadyInitialized:
-       lda     #0                      ; Error
+       lda     #0                      ; Error
        rts
 
+.endproc
+
 ; --------------------------------------------------------------------------
 ;
 ; void mouse_done (void);
 ;
 
-_mouse_done:
-               ldx     OldIRQ                  ; Initialized?
-       lda     OldIRQ+1
-       beq     Done                    ; Jump if no
-       ldy     #0
-       sty     OldIRQ+1                ; Reset the initialized flag
-SetIRQ:        sei                             ; Disable interrupts
-       stx     IRQVec                  ; Set the new/old vector
-       sta     IRQVec+1
-       cli                             ; Enable interrupts
-Done:  rts
+.proc  _mouse_done
+
+               lda     Initialized             ; Initialized?
+               beq     @L1                     ; Jump if no
+       lda     #0
+               sta     Initialized             ; Reset the initialized flag
+       lda     OldInitStatus           ; Load the old BASIC int bit
+       and     #$01                    ; Mask it
+       ora     INIT_STATUS             ; Restore the old state
+       sta     INIT_STATUS
+@L1:   rts
+
+.endproc
 
 ; --------------------------------------------------------------------------
 ;
 ; void mouse_hide (void);
 ;
 
-_mouse_hide:
+.proc  _mouse_hide
+
                lda     Invisible               ; Get the flag
        bne     @L1                     ; Jump if already invisible
 
@@ -130,12 +136,15 @@ _mouse_hide:
 @L1:   inc     Invisible               ; Set the flag to invisible
        rts
 
+.endproc
+
 ; --------------------------------------------------------------------------
 ;
 ; void mouse_show (void);
 ;
 
-_mouse_show:
+.proc  _mouse_show
+
        lda     Invisible               ; Mouse invisible?
        beq     @L1                     ; Jump if no
                dec     Invisible               ; Set the flag
@@ -150,12 +159,15 @@ _mouse_show:
 
 @L1:   rts
 
+.endproc
+
 ; --------------------------------------------------------------------------
 ;
 ; void __fastcall__ mouse_box (int minx, int miny, int maxx, int maxy);
 ;
 
-_mouse_box:
+.proc  _mouse_box
+
        ldy     #0                      ; Stack offset
 
        add     YCorr                   ; Adjust the Y value
@@ -197,13 +209,16 @@ _mouse_box:
 
        jmp     addysp1                 ; Drop params, return
 
+.endproc
+
 ; --------------------------------------------------------------------------
 ;
 ; void __fastcall__ mouse_pos (struct mouse_pos* pos);
 ; /* Return the current mouse position */
 ;
 
-_mouse_pos:
+.proc  _mouse_pos
+
                sta     ptr1
        stx     ptr1+1                  ; Remember the argument pointer
 
@@ -233,13 +248,15 @@ _mouse_pos:
 
        rts                             ; Done
 
+.endproc
+
 ; --------------------------------------------------------------------------
 ;
 ; void __fastcall__ mouse_info (struct mouse_info* info);
 ; /* Return the state of the mouse buttons and the position of the mouse */
 ;
 
-_mouse_info:
+.proc  _mouse_info
 
 ; We're cheating here to keep the code smaller: The first fields of the
 ; mouse_info struct are identical to the mouse_pos struct, so we will just
@@ -256,12 +273,15 @@ _mouse_info:
 
        rts
 
+.endproc
+
 ; --------------------------------------------------------------------------
 ;
 ; void __fastcall__ mouse_move (int x, int y);
 ;
 
-_mouse_move:
+.proc  _mouse_move
+
        add     YCorr                   ; Add Y coordinate correction
        bcc     @L1
        inx
@@ -283,23 +303,32 @@ _mouse_move:
 
        rts
 
+.endproc
+
 ; --------------------------------------------------------------------------
 ;
 ; unsigned char mouse_buttons (void);
 ;
 
-_mouse_buttons:
+.proc  _mouse_buttons
+
        lda     #$00                    ; Use port #0
        jmp     _readjoy                ; Same as joystick
 
+.endproc
+
 ; --------------------------------------------------------------------------
 ;
 ; Mouse interrupt handler
-;
+;       
+
+IRQDone:rts
 
 MouseIRQ:
-       cld
-       lda     SID_ADConv1             ; Get mouse X movement
+
+       lda     Initialized             ; Mouse initialized?
+               beq     IRQDone                 ; Jump if no
+       lda     SID_ADConv1             ; Get mouse X movement
        ldy     OldPotX
        jsr     MoveCheck               ; Calculate movement vector
        sty     OldPotX
@@ -364,14 +393,39 @@ MouseIRQ:
 @L4:   sty     YPos
        stx     YPos+1
 
-; Move the mouse sprite if it is enabled
+; Move the mouse sprite to the current mouse position. Must be called
+; with interrupts off. MoveSprite1 is an entry without checking.
+
+MoveSprite:
+
+       lda     Invisible               ; Mouse visible?
+               bne     Done                    ; Jump if no
+
+; Set the high X bit
+
+MoveSprite1:
+       lda     VIC_SPR_HI_X            ; Get high X bits of all sprites
+       and     #$FE                    ; Clear bit for sprite #0
+       ldy     XPos+1                  ; Test Y position
+       beq     @L5
+               ora     #$01                    ; Set high X bit
+@L5:   sta     VIC_SPR_HI_X            ; Set hi X sprite values
+
+; Set the low X byte
+
+       lda     XPos
+               sta     VIC_SPR0_X              ; Set low byte
 
-       jsr     MoveSprite              ; Move the sprite
+; Set the Y position
 
-; Jump to the next IRQ handler
+       ldy     YPos+1                  ; Negative or too large?
+               bne     Done                    ; Jump if yes
+       lda     YPos
+       sta     VIC_SPR0_Y              ; Set Y position
 
-       jmp     (OldIRQ)
+; Done
 
+Done:   rts
 
 ; --------------------------------------------------------------------------
 ;
@@ -383,7 +437,8 @@ MouseIRQ:
 ;              x/a = delta value for position
 ;
 
-MoveCheck:
+.proc  MoveCheck
+
        sty     OldValue
        sta     NewValue
        ldx     #$00
@@ -409,50 +464,15 @@ MoveCheck:
 @L2:           txa                             ; A = $00
        rts
 
-; --------------------------------------------------------------------------
-;
-; Move the mouse sprite to the current mouse position. Must be called
-; with interrupts off. MoveSprite1 is an entry without checking.
-;
-
-MoveSprite:
-
-       lda     Invisible               ; Mouse visible?
-               bne     MoveSpriteDone          ; Jump if no
-
-; Set the high X bit
-
-MoveSprite1:
-       lda     VIC_SPR_HI_X            ; Get high X bits of all sprites
-       and     #$FE                    ; Clear bit for sprite #0
-       ldy     XPos+1                  ; Test Y position
-       beq     @L1
-               ora     #$01                    ; Set high X bit
-@L1:   sta     VIC_SPR_HI_X            ; Set hi X sprite values
-
-; Set the low X byte
-
-       lda     XPos
-               sta     VIC_SPR0_X              ; Set low byte
-
-; Set the Y position
-
-       ldy     YPos+1                  ; Negative or too large?
-       bne     MoveSpriteDone          ; Jump if yes
-       lda     YPos
-       sta     VIC_SPR0_Y              ; Set Y position
-
-; Done
-
-MoveSpriteDone:
-       rts
+.endproc
 
 ; --------------------------------------------------------------------------
 ; Data
 
 .bss
 
-OldIRQ:                .res    2               ; Old IRQ vector
+Initialized:           .res    1               ; True if mouse initialized
+OldInitStatus: .res    1               ; Old IRQ flag value
 OldValue:      .res    1               ; Temp for MoveCheck routine
 NewValue:      .res    1               ; Temp for MoveCheck routine
 YCorr:         .res    1               ; Correction for Y coordinate