From e12444824fb1e3d67fb0c3802d7cd03895aee595 Mon Sep 17 00:00:00 2001 From: cuz Date: Wed, 19 Sep 2001 10:01:52 +0000 Subject: [PATCH] Added condes IRQ routines and a README file. Made k_blncur a condes IRQ routine and moved it to cgetc.s. Added mouse and joystick routines. git-svn-id: svn://svn.cc65.org/cc65/trunk@951 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- libsrc/cbm510/Makefile | 3 +- libsrc/cbm510/README | 8 + libsrc/cbm510/cgetc.s | 56 +++++ libsrc/cbm510/io.inc | 86 ++++--- libsrc/cbm510/kblncur.s | 56 ----- libsrc/cbm510/kirq.s | 26 ++- libsrc/cbm510/mouse.s | 498 ++++++++++++++++++++++++++++++++++++++++ libsrc/cbm510/readjoy.s | 62 +++++ 8 files changed, 684 insertions(+), 111 deletions(-) create mode 100644 libsrc/cbm510/README delete mode 100644 libsrc/cbm510/kblncur.s create mode 100644 libsrc/cbm510/mouse.s create mode 100644 libsrc/cbm510/readjoy.s diff --git a/libsrc/cbm510/Makefile b/libsrc/cbm510/Makefile index 50fdf623c..3db93aacf 100644 --- a/libsrc/cbm510/Makefile +++ b/libsrc/cbm510/Makefile @@ -21,13 +21,14 @@ OBJS = _scrsize.o \ cputc.o \ crt0.o \ kbhit.o \ - kblncur.o \ kirq.o \ kplot.o \ kscnkey.o \ kudtim.o \ + mouse.o \ peeksys.o \ pokesys.o \ + readjoy.o \ rs232.o all: $(OBJS) diff --git a/libsrc/cbm510/README b/libsrc/cbm510/README new file mode 100644 index 000000000..d22b48168 --- /dev/null +++ b/libsrc/cbm510/README @@ -0,0 +1,8 @@ +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. The indirect segment is set to the +system bank when calling interrupt routines, this must must not be changed +when returning. + diff --git a/libsrc/cbm510/cgetc.s b/libsrc/cbm510/cgetc.s index 4cb75ccb4..1e966341d 100644 --- a/libsrc/cbm510/cgetc.s +++ b/libsrc/cbm510/cgetc.s @@ -5,6 +5,7 @@ ; .export _cgetc + .condes k_blncur, 2 .import cursor .include "zeropage.inc" @@ -90,6 +91,61 @@ L4: lda KeyBuf+1,x ; Move up the remaining chars @L9: sty CURS_FLAG ; Cursor on (Y = 0) rts + +.endproc + + +; ------------------------------------------------------------------------ +; Blink the cursor in the interrupt. A blinking cursor is only available if +; we use the cgetc() function, so we will export this IRQ handler only in +; case the module is included into a program. + + +.proc k_blncur + + lda CURS_FLAG ; Is the cursor on? + bne curend ; Jump if not + dec CURS_BLINK + bne curend + +; Re-initialize the blink counter + + lda #20 ; Initial value + sta CURS_BLINK + +; Load Y with the cursor X coordinate + + ldy CURS_X + +; Check if the cursor state was on or off before + + lda CURS_COLOR ; Load color behind cursor + lsr CURS_STATE ; Cursor currently displayed? + bcs curset ; Jump if yes + +; Cursor was off before, switch it on + + inc CURS_STATE ; Mark as displayed + lda (CRAM_PTR),y ; Get color behind cursor... + sta CURS_COLOR ; ...and remember it + lda CHARCOLOR ; Use character color + +; Set the cursor with color in A + +curset: sta (CRAM_PTR),y ; Store cursor color + lda ExecReg + sta IndReg ; Switch to our segment + lda (SCREEN_PTR),y + eor #$80 ; Toggle reverse flag + sta (SCREEN_PTR),y + +; Switch back to the system bank + + lda #$0F + sta IndReg + +curend: rts .endproc + diff --git a/libsrc/cbm510/io.inc b/libsrc/cbm510/io.inc index 9f9939d9e..3d1422d86 100644 --- a/libsrc/cbm510/io.inc +++ b/libsrc/cbm510/io.inc @@ -63,58 +63,50 @@ VIC_BG_COLOR3 = $24 ; I/O $da00: SID 6581 -; sid = $da00 - - Osc1 = $00 - Osc2 = $07 - Osc3 = $0e - - FreqLo = $00 - FreqHi = $01 - PulseF = $02 - PulseC = $03 - OscCtl = $04 - AtkDcy = $05 - SusRel = $06 - - FiCtlLo = $15 - FiCtlHi = $16 - Resonance = $17 - Volume = $18 - PotX = $19 - PotY = $1A - Random = $1B - Env3 = $1C - +SID_S1Lo = $00 +SID_S1Hi = $01 +SID_PB1Lo = $02 +SID_PB1Hi = $03 +SID_Ctl1 = $04 +SID_AD1 = $05 +SID_SUR1 = $06 + +SID_S2Lo = $07 +SID_S2Hi = $08 +SID_PB2Lo = $09 +SID_PB2Hi = $0A +SID_Ctl2 = $0B +SID_AD2 = $0C +SID_SUR2 = $0D + +SID_S3Lo = $0E +SID_S3Hi = $0F +SID_PB3Lo = $10 +SID_PB3Hi = $11 +SID_Ctl3 = $12 +SID_AD3 = $13 +SID_SUR3 = $14 + +SID_FltLo = $15 +SID_FltHi = $16 +SID_FltCtl = $17 +SID_Amp = $18 +SID_ADConv1 = $19 +SID_ADConv2 = $1A +SID_Noise = $1B +SID_Read3 = $1C ; I/O $db00: CIA 6526 Inter Process Communication - -; IPCcia = $db00 - - PortA = $00 - PortB = $01 - DDRA = $02 - DDRB = $03 - TimALo = $04 - TimAHi = $05 - TimBLo = $06 - TimBHi = $07 - TOD10 = $08 - TODsec = $09 - TODmin = $0A - TODhour = $0B - SerDataReg = $0C - IntCtrReg = $0D - CtrlA = $0E - CtrlB = $0F - - - ; I/O $dc00: CIA 6526 -; cia = $dc00 - +CIA_PRA = $00 +CIA_PRB = $01 +CIA_DDRA = $02 +CIA_DDRB = $03 +CIA_ICR = $0D +CIA_CRA = $0E +CIA_CRB = $0F ; I/O $dd00: ACIA 6551 diff --git a/libsrc/cbm510/kblncur.s b/libsrc/cbm510/kblncur.s deleted file mode 100644 index 11b12fa48..000000000 --- a/libsrc/cbm510/kblncur.s +++ /dev/null @@ -1,56 +0,0 @@ -; -; Ullrich von Bassewitz, 16.09.2001 -; - - .export k_blncur - - .include "zeropage.inc" - - -; ------------------------------------------------------------------------ -; Blink the cursor in the interrupt - -.proc k_blncur - - lda CURS_FLAG ; Is the cursor on? - bne curend ; Jump if not - dec CURS_BLINK - bne curend - -; Re-initialize the blink counter - - lda #20 ; Initial value - sta CURS_BLINK - -; Switch to the system bank, load Y with the cursor X coordinate - - lda #$0F - sta IndReg ; Access system bank - ldy CURS_X - -; Check if the cursor state was on or off before - - lda CURS_COLOR ; Load color behind cursor - lsr CURS_STATE ; Cursor currently displayed? - bcs curset ; Jump if yes - -; Cursor was off before, switch it on - - inc CURS_STATE ; Mark as displayed - lda (CRAM_PTR),y ; Get color behind cursor... - sta CURS_COLOR ; ...and remember it - lda CHARCOLOR ; Use character color - -; Set the cursor with color in A - -curset: sta (CRAM_PTR),y ; Store cursor color - lda ExecReg - sta IndReg ; Switch to our segment - lda (SCREEN_PTR),y - eor #$80 ; Toggle reverse flag - sta (SCREEN_PTR),y -curend: rts - -.endproc - - diff --git a/libsrc/cbm510/kirq.s b/libsrc/cbm510/kirq.s index a2a0d2eec..cd71693b2 100644 --- a/libsrc/cbm510/kirq.s +++ b/libsrc/cbm510/kirq.s @@ -5,7 +5,9 @@ ; .export irq, nmi, k_irq, k_nmi - .import k_blncur, k_scnkey, k_udtim, k_rs232 + .import k_scnkey, k_udtim, k_rs232 + .import condes + .import __IRQFUNC_TABLE__, __IRQFUNC_COUNT__ .importzp tpi1 .include "zeropage.inc" @@ -40,7 +42,7 @@ and #$10 ; Test break flag bne L1 jmp (IRQVec) -L1: jmp (BRKVec) +L1: jmp (BRKVec) .endproc @@ -70,16 +72,26 @@ k_irq: ; ------------------------------------------------------------------------- ; 50/60Hz interrupt - cmp #%00000001 ; ticker irq? + cmp #%00000001 ; ticker irq? bne irq1 - jsr k_blncur ; Blink the cursor - jsr k_scnkey ; Poll the keyboard - jsr k_udtim ; Bump the time + +; Call user IRQ handlers if we have any + + ldy #<(__IRQFUNC_COUNT__*2) + beq @L1 + lda #<__IRQFUNC_TABLE__ + ldx #>__IRQFUNC_TABLE__ + jsr condes ; Call the functions + +; Call replacement kernal IRQ routines + +@L1: jsr k_scnkey ; Poll the keyboard + jsr k_udtim ; Bump the time ; ------------------------------------------------------------------------- ; UART interrupt -irq1: cmp #%00010000 ; interrupt from uart? +irq1: cmp #%00010000 ; interrupt from uart? bne irqend jsr k_rs232 ; Read character from uart diff --git a/libsrc/cbm510/mouse.s b/libsrc/cbm510/mouse.s new file mode 100644 index 000000000..9ff1a4dc8 --- /dev/null +++ b/libsrc/cbm510/mouse.s @@ -0,0 +1,498 @@ +; +; Ullrich von Bassewitz, 19.09.2001 +; +; Routines for the 1351 proportional mouse. Parts of the code are from +; the Commodore 1351 mouse users guide. +; + + .export _mouse_init, _mouse_done + .export _mouse_hide, _mouse_show + .export _mouse_box, _mouse_info + .export _mouse_move, _mouse_pos + .export _mouse_buttons, _mouse_info + .condes MouseIRQ, 2 + + .import _readjoy + .import sys_bank, restore_bank + .import popax, addysp1 + .importzp vic, sid, ptr1, sp + + .include "zeropage.inc" + .include "io.inc" + + .macpack generic + + +.code + +; -------------------------------------------------------------------------- +; +; Constants +; + +SPRITE_HEIGHT = 21 +SPRITE_WIDTH = 24 +SCREEN_HEIGHT = 200 +SCREEN_WIDTH = 320 +XCORR = SPRITE_WIDTH + +; -------------------------------------------------------------------------- +; +; unsigned char __fastcall__ mouse_init (unsigned char type); +; + +.proc _mouse_init + lda Initialized ; Already initialized? + bne AlreadyInitialized ; Jump if yes + +; Initialize variables + + ldx #0 + lda #XCORR + sta XPos + stx XPos+1 + stx YPos + stx YPos+1 + stx OldPotX + stx OldPotY + stx XMin + stx XMin+1 ; XMin = 0 + lda #50 ; ## FIXME: This is the PAL value + sta YCorr + sta YPos + stx YPos+1 + sec + sbc #SPRITE_HEIGHT ; Sprite height in pixels + sta YMin + stx YMin+1 ; YMin = 29 + lda #SCREEN_HEIGHT ; Vertical screen res + add YCorr ; Add correction factor + sta YMax + stx YMax+1 + inx ; X = 1 + stx Invisible ; Mouse *not* visible + lda #<(SCREEN_WIDTH + SPRITE_WIDTH) + sta XMax + stx XMax+1 ; XMax = 320 + sprite width + +; Mouse successfully initialized + + lda #1 + sta Initialized + rts + +AlreadyInitialized: + lda #0 ; Error + rts + +.endproc + +; -------------------------------------------------------------------------- +; +; void mouse_done (void); +; + +_mouse_done: + + lda #0 + sta Initialized ; Reset the initialized flag + +; Disable the mouse sprite + +DisableSprite: + + ldx IndReg + lda #$0F + sta IndReg ; Switch to the system bank + + ldy #VIC_SPR_ENA + sei ; Disable interrupts + lda (vic),y + and #$FE ; Clear bit for sprite #0 + sta (vic),y ; Disable sprite + cli ; Enable interrupts + + stx IndReg ; Switch back the segment + rts + +; -------------------------------------------------------------------------- +; +; void mouse_hide (void); +; + +.proc _mouse_hide + + lda Invisible ; Get the flag + bne @L1 ; Jump if already invisible + jsr DisableSprite ; Disabe the mouse sprite +@L1: inc Invisible ; Set the flag to invisible + rts + +.endproc + +; -------------------------------------------------------------------------- +; +; void mouse_show (void); +; + +.proc _mouse_show + + lda Invisible ; Mouse invisible? + beq @L1 ; Jump if no + dec Invisible ; Set the flag + bne @L1 ; Jump if still invisible + + jsr sys_bank ; Switch to the system bank + + sei ; Disable interrupts + jsr MoveSprite1 ; Move the sprite to it's position + ldy #VIC_SPR_ENA + lda (vic),y ; Get sprite enable register + ora #$01 ; Enable sprite #0 + sta (vic),y ; Write back + cli ; Enable interrupts + + jsr restore_bank ; Switch back the bank + +@L1: rts + +.endproc + +; -------------------------------------------------------------------------- +; +; void __fastcall__ mouse_box (int minx, int miny, int maxx, int maxy); +; + +.proc _mouse_box + + ldy #0 ; Stack offset + + add YCorr ; Adjust the Y value + bcc @L1 + inx + clc +@L1: sei ; Disable interrupts + + sta YMax + stx YMax+1 ; maxy + + lda (sp),y + adc #XCORR + sta XMax + iny + lda (sp),y + adc #$00 + sta XMax+1 ; maxx + + iny + lda (sp),y + add YCorr + sta YMin + iny + lda (sp),y + adc #$00 + sta YMin+1 ; miny + + iny + lda (sp),y + add #XCORR + sta XMin + iny + lda (sp),y + adc #$00 + sta XMin+1 ; minx + + cli ; Enable interrupts + + jmp addysp1 ; Drop params, return + +.endproc + +; -------------------------------------------------------------------------- +; +; void __fastcall__ mouse_pos (struct mouse_pos* pos); +; /* Return the current mouse position */ +; + +.proc _mouse_pos + + sta ptr1 + stx ptr1+1 ; Remember the argument pointer + + ldy #0 ; Structure offset + sec ; Needed for the SBC later + + sei ; Disable interrupts + lda XPos ; Transfer the position + sbc #XCORR + sta (ptr1),y + lda XPos+1 + sbc #$00 + iny + sta (ptr1),y + lda YPos + ldx YPos+1 + cli ; Restore initial interrupt state + + sub YCorr ; Apply the Y correction value + bcs @L1 + dex +@L1: iny + sta (ptr1),y ; Store YPos + txa + iny + sta (ptr1),y + + rts ; Done + +.endproc + +; -------------------------------------------------------------------------- +; +; void __fastcall__ mouse_info (struct mouse_info* info); +; /* Return the state of the mouse buttons and the position of the mouse */ +; + +.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 +; call _mouse_pos to initialize the struct pointer and fill the position +; fields. + + jsr _mouse_pos + +; Fill in the button state + + jsr _mouse_buttons ; Will not touch ptr1 + ldy #4 + sta (ptr1),y + + rts + +.endproc + +; -------------------------------------------------------------------------- +; +; void __fastcall__ mouse_move (int x, int y); +; + +.proc _mouse_move + + add YCorr ; Add Y coordinate correction + bcc @L1 + inx + clc +@L1: sei + sta YPos + stx YPos+1 + cli + + jsr popax ; Get X + adc #XCORR ; Adjust X coordinate + bcc @L2 + inx +@L2: jsr sys_bank + sei + sta XPos + stx XPos+1 ; Set new position + jsr MoveSprite ; Move the sprite to the mouse pos + cli ; Enable interrupts + jsr restore_bank + + rts + +.endproc + +; -------------------------------------------------------------------------- +; +; unsigned char mouse_buttons (void); +; + +.proc _mouse_buttons + + lda #$00 ; Use port #0 + jmp _readjoy ; Same as joystick + +.endproc + + +; -------------------------------------------------------------------------- +; +; Mouse interrupt handler +; + +IRQDone:rts + +MouseIRQ: + lda Initialized ; Mouse initialized? + beq IRQDone ; Jump if no + + ldy #SID_ADConv1 + lda (sid),y ; Get mouse X movement + ldy OldPotX + jsr MoveCheck ; Calculate movement vector + sty OldPotX + +; Calculate the new X coordinate (--> a/y) + + add XPos + tay ; Remember low byte + txa + adc XPos+1 + tax + +; Limit the X coordinate to the bounding box + + cpy XMin + sbc XMin+1 + bpl @L1 + ldy XMin + ldx XMin+1 + jmp @L2 +@L1: txa + + cpy XMax + sbc XMax+1 + bmi @L2 + ldy XMax + ldx XMax+1 +@L2: sty XPos + stx XPos+1 + +; Calculate the Y movement vector + + ldy #SID_ADConv2 + lda (sid),y ; Get mouse Y movement + ldy OldPotY + jsr MoveCheck ; Calculate movement + sty OldPotY + +; Calculate the new Y coordinate (--> a/y) + + sta OldValue + lda YPos + sub OldValue + tay + stx OldValue + lda YPos+1 + sbc OldValue + tax + + cpy YMin + sbc YMin+1 + bpl @L3 + ldy YMin + ldx YMin+1 + jmp @L4 +@L3: txa + + cpy YMax + sbc YMax+1 + bmi @L4 + ldy YMax + ldx YMax+1 +@L4: sty YPos + stx YPos+1 + +; Move the mouse sprite to the current mouse position. Must be called +; with interrupts off and the system bank enabled. MoveSprite1 is an entry +; without checking. + +MoveSprite: + + lda Invisible ; Mouse visible? + bne Done ; Jump if no + +; Set the high X bit + +MoveSprite1: + ldy #VIC_SPR_HI_X + lda (vic),y ; Get high X bits of all sprites + and #$FE ; Clear bit for sprite #0 + ldx XPos+1 ; Test Y position + beq @L5 + ora #$01 ; Set high X bit +@L5: sta (vic),y ; Set hi X sprite values + +; Set the low X byte + + lda XPos + ldy #VIC_SPR0_X + sta (vic),y ; Set low byte + +; Set the Y position + + ldy YPos+1 ; Negative or too large? + bne Done ; Jump if yes + lda YPos + ldy #VIC_SPR0_Y + sta (vic),y ; Set Y position + +; Done + +Done: rts + +; -------------------------------------------------------------------------- +; +; Move check routine, called for both coordinates. +; +; Entry: y = old value of pot register +; a = current value of pot register +; Exit: y = value to use for old value +; x/a = delta value for position +; + +.proc MoveCheck + + sty OldValue + sta NewValue + ldx #$00 + + sub OldValue ; a = mod64 (new - old) + and #%01111111 + cmp #%01000000 ; if (a > 0) + bcs @L1 ; + lsr a ; a /= 2; + beq @L2 ; if (a != 0) + ldy NewValue ; y = NewValue + rts ; return + +@L1: ora #%11000000 ; else or in high order bits + cmp #$FF ; if (a != -1) + beq @L2 + sec + ror a ; a /= 2 + dex ; high byte = -1 (X = $FF) + ldy NewValue + rts + +@L2: txa ; A = $00 + rts + +.endproc + +; -------------------------------------------------------------------------- +; Data + +.bss + +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 + +Invisible: .res 1 ; Is the mouse invisible? +OldPotX: .res 1 ; Old hw counter values +OldPotY: .res 1 + +XPos: .res 2 ; Current mouse position, X +YPos: .res 2 ; Current mouse position, Y + +XMin: .res 2 ; X1 value of bounding box +YMin: .res 2 ; Y1 value of bounding box +XMax: .res 2 ; X2 value of bounding box +YMax: .res 2 ; Y2 value of bounding box + + diff --git a/libsrc/cbm510/readjoy.s b/libsrc/cbm510/readjoy.s new file mode 100644 index 000000000..0bbbd5c30 --- /dev/null +++ b/libsrc/cbm510/readjoy.s @@ -0,0 +1,62 @@ +; +; Ullrich von Bassewitz, 23.09.1998 +; +; unsigned readjoy (unsigned char joy); +; + + .export _readjoy + .import sys_bank, restore_bank + .importzp cia2, tmp1 + + .include "io.inc" + +; ------------------------------------------------------------------------ +; unsigned __fastcall__ readjoy (unsigned char joy); + + +.proc _readjoy + + jsr sys_bank ; Switch to the system bank + tax ; Save joystick number + +; Get the direction bits + + ldy #CIA_PRB + lda (cia2),y ; Read joystick inputs + sta tmp1 + +; Get the fire bits + + ldy #CIA_PRA + lda (cia2),y + +; Make the result value + + cpx #$00 ; Joystick 0? + bne @L1 ; Jump if no + +; Joystick 1, fire is in bit 6, direction in bit 0-3 + + asl a + jmp @L2 + +; Joystick 2, fire is in bit 7, direction in bit 5-7 + +@L1: ldy #$00 ; High byte of return value + lsr tmp1 + lsr tmp1 + lsr tmp1 + lsr tmp1 + +; Mask the relavant bits, get the fire bit + +@L2: asl a ; Fire bit into carry + lda tmp1 + and #$0F + bcc @L3 + ora #$10 +@L3: eor #$1F ; All bits are inverted + jmp restore_bank + +.endproc + -- 2.39.5