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
This commit is contained in:
cuz 2001-09-19 10:01:52 +00:00
parent 2ffb744316
commit e12444824f
8 changed files with 681 additions and 108 deletions

View file

@ -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)

8
libsrc/cbm510/README Normal file
View file

@ -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.

View file

@ -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

View file

@ -63,58 +63,50 @@ VIC_BG_COLOR3 = $24
; I/O $da00: SID 6581
; sid = $da00
SID_S1Lo = $00
SID_S1Hi = $01
SID_PB1Lo = $02
SID_PB1Hi = $03
SID_Ctl1 = $04
SID_AD1 = $05
SID_SUR1 = $06
Osc1 = $00
Osc2 = $07
Osc3 = $0e
SID_S2Lo = $07
SID_S2Hi = $08
SID_PB2Lo = $09
SID_PB2Hi = $0A
SID_Ctl2 = $0B
SID_AD2 = $0C
SID_SUR2 = $0D
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_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

View file

@ -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

View file

@ -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

498
libsrc/cbm510/mouse.s Normal file
View file

@ -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

62
libsrc/cbm510/readjoy.s Normal file
View file

@ -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