1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-22 12:30:41 +00:00

Complete redesign of the CBM610 support.

Use wrappers to call the kernal in bank 15 instead of implementing kernal
functionality within the cc65 libs (eats performance but is much smaller and
simpler).
Improved startup/shutdown code allows a return to the system bank without
calling the BASIC cold start vector.


git-svn-id: svn://svn.cc65.org/cc65/trunk@2793 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2003-12-20 23:13:26 +00:00
parent 018a68a2fe
commit a7042ddbe4
28 changed files with 1086 additions and 1033 deletions

View File

@ -144,7 +144,7 @@ c128lib:
# Commdore P500 / CBM 5x0
cbm510lib:
for i in cbm510 cbm common runtime conio dbg em joystick tgi zlib; do \
for i in cbm510 cbm common runtime conio dbg em joystick serial tgi zlib; do \
CC=$(CC) \
AS=$(AS) \
LD=$(LD) \
@ -161,7 +161,7 @@ cbm510lib:
# PET-II series
cbm610lib:
for i in cbm610 cbm common runtime conio dbg em joystick tgi zlib; do \
for i in cbm610 cbm common runtime conio dbg em joystick serial tgi zlib; do \
CC=$(CC) \
AS=$(AS) \
LD=$(LD) \
@ -172,6 +172,7 @@ cbm610lib:
done
mv cbm610/crt0.o cbm610.o
cp cbm610/*.emd .
cp cbm610/*.ser .
#-----------------------------------------------------------------------------
# GEOS on the C64/128

View File

@ -1,3 +1,5 @@
*.emd
*.joy
*.ser
*.tgi

View File

@ -14,10 +14,13 @@
%.o: %.s
@$(AS) -g -o $@ $(AFLAGS) $<
%.emd: %.o ../runtime/zeropage.o
%.emd: %.o ../runtime/zeropage.o extzp.o
@$(LD) -t module -o $@ $^
%.tgi: %.o ../runtime/zeropage.o
%.ser: %.o ../runtime/zeropage.o extzp.o
@$(LD) -t module -o $@ $^
%.tgi: %.o ../runtime/zeropage.o extzp.o
@$(LD) -t module -o $@ $^
#--------------------------------------------------------------------------
@ -32,48 +35,47 @@ OBJS = _scrsize.o \
cputc.o \
crt0.o \
crtc.o \
extzp.o \
kbhit.o \
kiec.o \
kernal.o \
kiobase.o \
kirq.o \
kplot.o \
kopen.o \
krdtim.o \
kreadst.o \
kscnkey.o \
kscreen.o \
ksetlfs.o \
ksetnam.o \
ksettim.o \
kudtim.o \
kupdst.o \
mainargs.o \
peeksys.o \
pokesys.o \
randomize.o \
revers.o \
rs232.o \
sysuname.o
#--------------------------------------------------------------------------
# Drivers
TGIS =
EMDS = cbm610-ram.emd
JOYS =
SERS = cbm610-stdser.ser
TGIS =
#--------------------------------------------------------------------------
# Targets
.PHONY: all clean zap
all: $(OBJS) $(EMDS) $(TGIS)
all: $(OBJS) $(EMDS) $(JOYS) $(SERS) $(TGIS)
../runtime/zeropage.o:
$(MAKE) -C $(dir $@) $(notdir $@)
clean:
@$(RM) $(OBJS) $(EMDS:.emd=.o) $(TGIS:.tgi=.o)
@$(RM) $(OBJS) $(EMDS:.emd=.o) $(JOYS:.joy=.o) $(SERS:.ser=.o) $(TGIS:.tgi=.o)
zap: clean
@$(RM) $(EMDS) $(TGIS)
@$(RM) $(EMDS) $(JOYS) $(SERS) $(TGIS)

View File

@ -5,15 +5,8 @@
;
.export screensize
.include "cbm610.inc"
.proc screensize
ldx #XSIZE
ldy #YSIZE
rts
.endproc
.import SCREEN
screensize = SCREEN

View File

@ -5,16 +5,16 @@
;
.export set_bank, sys_bank, restore_bank
.importzp ptr1
.importzp ptr1, segsave
.include "cbm610.inc"
.include "cbm610.inc"
.code
.proc sys_bank
pha
lda IndReg
sta IndSegSave
sta segsave
lda #$0F
sta IndReg
pla
@ -24,7 +24,7 @@
.proc set_bank
pha
lda IndReg
sta IndSegSave
sta segsave
pla
sta IndReg
rts
@ -32,7 +32,7 @@
.proc restore_bank
pha
lda IndSegSave
lda segsave
sta IndReg
pla
rts

View File

@ -7,7 +7,7 @@
.export _set_brk, _reset_brk
.export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc
.import _atexit
.import _atexit, BRKVec
.include "cbm610.inc"
@ -74,6 +74,8 @@ L1: lda #<brk_handler ; Set the break vector to our routine
.proc brk_handler
pla
sta _brk_01
pla
sta _brk_y
pla
@ -90,15 +92,11 @@ L1: lda #<brk_handler ; Set the break vector to our routine
pla ; PC high
sbc #0
sta _brk_pc+1
lda IndReg
sta _brk_01
lda ExecReg
sta IndReg
jsr uservec ; Call the user's routine
lda _brk_01
sta IndReg
sta IndReg
lda _brk_pc+1
pha

View File

@ -63,15 +63,20 @@ pagecount: .res 1 ; Number of available pages
INSTALL:
lda #$FF
sta curpage ; Invalidate the current page
sta pagecount ; Assume all memory available
ldx UsrMemTop+2
cpx #RAMBANK ; Top of memory in bank 2?
sec
jsr $FF99 ; MEMTOP
cmp #RAMBANK ; Top of memory in bank 2?
bne @L1 ; No: We can use all the memory
clc
adc UsrMemTop+1
@L1: sta pagecount
txa
sub #OFFS
tya
sbc #$00
sta pagecount
lda #<EM_ERR_OK
@L1: lda #<EM_ERR_OK
ldx #>EM_ERR_OK
; rts ; Run into UNINSTALL instead

View File

@ -0,0 +1,454 @@
;
; Serial driver for the builtin 6551 ACIA of the Commodore 610.
;
; Ullrich von Bassewitz, 2003-12-18
;
; The driver is based on the cc65 rs232 module, which in turn is based on
; Craig Bruce device driver for the Switftlink/Turbo-232.
;
; SwiftLink/Turbo-232 v0.90 device driver, by Craig Bruce, 14-Apr-1998.
;
; This software is Public Domain. It is in Buddy assembler format.
;
; This device driver uses the SwiftLink RS-232 Serial Cartridge, available from
; Creative Micro Designs, Inc, and also supports the extensions of the Turbo232
; Serial Cartridge. Both devices are based on the 6551 ACIA chip. It also
; supports the "hacked" SwiftLink with a 1.8432 MHz crystal.
;
; The code assumes that the kernal + I/O are in context. On the C128, call
; it from Bank 15. On the C64, don't flip out the Kernal unless a suitable
; NMI catcher is put into the RAM under then Kernal. For the SuperCPU, the
; interrupt handling assumes that the 65816 is in 6502-emulation mode.
;
.include "zeropage.inc"
.include "extzp.inc"
.include "ser-kernel.inc"
.include "ser-error.inc"
.include "cbm610.inc"
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
; Driver signature
.byte $73, $65, $72 ; "ser"
.byte SER_API_VERSION ; Serial API version number
; Jump table.
.word INSTALL
.word UNINSTALL
.word OPEN
.word CLOSE
.word GET
.word PUT
.word STATUS
.word IOCTL
.word IRQ
;----------------------------------------------------------------------------
;
; Global variables
;
.bss
RecvHead: .res 1 ; Head of receive buffer
RecvTail: .res 1 ; Tail of receive buffer
RecvFreeCnt: .res 1 ; Number of bytes in receive buffer
SendHead: .res 1 ; Head of send buffer
SendTail: .res 1 ; Tail of send buffer
SendFreeCnt: .res 1 ; Number of bytes in send buffer
Stopped: .res 1 ; Flow-stopped flag
RtsOff: .res 1 ;
; Send and receive buffers: 256 bytes each
RecvBuf: .res 256
SendBuf: .res 256
.rodata
; Tables used to translate RS232 params into register values
BaudTable: ; bit7 = 1 means setting is invalid
.byte $FF ; SER_BAUD_45_5
.byte $01 ; SER_BAUD_50
.byte $02 ; SER_BAUD_75
.byte $03 ; SER_BAUD_110
.byte $04 ; SER_BAUD_134_5
.byte $05 ; SER_BAUD_150
.byte $06 ; SER_BAUD_300
.byte $07 ; SER_BAUD_600
.byte $08 ; SER_BAUD_1200
.byte $09 ; SER_BAUD_1800
.byte $0A ; SER_BAUD_2400
.byte $0B ; SER_BAUD_3600
.byte $0C ; SER_BAUD_4800
.byte $0D ; SER_BAUD_7200
.byte $0E ; SER_BAUD_9600
.byte $0F ; SER_BAUD_19200
.byte $FF ; SER_BAUD_38400
.byte $FF ; SER_BAUD_57600
.byte $FF ; SER_BAUD_115200
.byte $FF ; SER_BAUD_230400
BitTable:
.byte $60 ; SER_BITS_5
.byte $40 ; SER_BITS_6
.byte $20 ; SER_BITS_7
.byte $00 ; SER_BITS_8
StopTable:
.byte $00 ; SER_STOP_1
.byte $80 ; SER_STOP_2
ParityTable:
.byte $00 ; SER_PAR_NONE
.byte $20 ; SER_PAR_ODD
.byte $60 ; SER_PAR_EVEN
.byte $A0 ; SER_PAR_MARK
.byte $E0 ; SER_PAR_SPACE
.code
;----------------------------------------------------------------------------
; INSTALL routine. Is called after the driver is loaded into memory. If
; possible, check if the hardware is present.
; Must return an SER_ERR_xx code in a/x.
;
; Since we don't have to manage the IRQ vector on the Plus/4, this is actually
; the same as:
;
; UNINSTALL routine. Is called before the driver is removed from memory.
; Must return an SER_ERR_xx code in a/x.
INSTALL:
UNINSTALL:
; Deactivate DTR and disable 6551 interrupts
lda #%00001010
jsr write_cmd
; Done, return an error code
lda #<SER_ERR_OK
tax ; A is zero
rts
;----------------------------------------------------------------------------
; PARAMS routine. A pointer to a ser_params structure is passed in ptr1.
; Must return an SER_ERR_xx code in a/x.
OPEN:
; Check if the handshake setting is valid
ldy #SER_PARAMS::HANDSHAKE ; Handshake
lda (ptr1),y
cmp #SER_HS_HW ; This is all we support
bne InvParam
; Initialize buffers
jsr InitBuffers
; Set the value for the control register, which contains stop bits, word
; length and the baud rate.
ldy #SER_PARAMS::BAUDRATE
lda (ptr1),y ; Baudrate index
tay
lda BaudTable,y ; Get 6551 value
bmi InvBaud ; Branch if rate not supported
sta tmp1
ldy #SER_PARAMS::DATABITS ; Databits
lda (ptr1),y
tay
lda BitTable,y
ora tmp1
sta tmp1
ldy #SER_PARAMS::STOPBITS ; Stopbits
lda (ptr1),y
tay
lda StopTable,y
ora tmp1
ora #%00010000 ; Receiver clock source = baudrate
ldy #ACIA::CTRL
jsr write
; Set the value for the command register. We remember the base value in
; RtsOff, since we will have to manipulate ACIA_CMD often.
ldy #SER_PARAMS::PARITY ; Parity
lda (ptr1),y
tay
lda ParityTable,y
ora #%00000001 ; DTR active
sta RtsOff
ora #%00001000 ; Enable receive interrupts
jsr write_cmd
; Done
lda #<SER_ERR_OK
tax ; A is zero
rts
; Invalid parameter
InvParam:
lda #<SER_ERR_INIT_FAILED
ldx #>SER_ERR_INIT_FAILED
rts
; Baud rate not available
InvBaud:
lda #<SER_ERR_BAUD_UNAVAIL
ldx #>SER_ERR_BAUD_UNAVAIL
rts
;----------------------------------------------------------------------------
; CLOSE: Close the port, disable interrupts and flush the buffer. Called
; without parameters. Must return an error code in a/x.
;
CLOSE:
; Stop interrupts, drop DTR
lda #%00001010
jsr write_cmd
; Initalize buffers.
jsr InitBuffers
; Return OK
lda #<SER_ERR_OK
tax ; A is zero
rts
;----------------------------------------------------------------------------
; GET: Will fetch a character from the receive buffer and store it into the
; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is
; return.
;
GET: ldx SendFreeCnt ; Send data if necessary
inx ; X == $FF?
beq @L1
lda #$00
jsr TryToSend
; Check for buffer empty
@L1: lda RecvFreeCnt
cmp #$ff
bne @L2
lda #<SER_ERR_NO_DATA
ldx #>SER_ERR_NO_DATA
rts
; Check for flow stopped & enough free: release flow control
@L2: ldx Stopped
beq @L3
cmp #63
bcc @L3
lda #$00
sta Stopped
lda RtsOff
ora #%00001000
jsr write_cmd
; Get byte from buffer
@L3: ldx RecvHead
lda RecvBuf,x
inc RecvHead
inc RecvFreeCnt
ldx #$00
sta (ptr1,x)
txa ; Return code = 0
rts
;----------------------------------------------------------------------------
; PUT: Output character in A.
; Must return an error code in a/x.
;
PUT:
; Try to send
ldx SendFreeCnt
inx ; X = $ff?
beq @L2
pha
lda #$00
jsr TryToSend
pla
; Put byte into send buffer & send
@L2: ldx SendFreeCnt
bne @L3
lda #<SER_ERR_OVERFLOW ; X is already zero
rts
@L3: ldx SendTail
sta SendBuf,x
inc SendTail
dec SendFreeCnt
lda #$ff
jsr TryToSend
lda #<SER_ERR_OK
tax
rts
;----------------------------------------------------------------------------
; STATUS: Return the status in the variable pointed to by ptr1.
; Must return an error code in a/x.
;
STATUS: lda #$0F
sta IndReg
ldy #ACIA::STATUS
lda (acia),y
ldx #0
sta (ptr1,x)
lda IndReg
sta ExecReg
txa ; SER_ERR_OK
rts
;----------------------------------------------------------------------------
; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
; specific data in ptr1, and the ioctl code in A.
; Must return an error code in a/x.
;
IOCTL: lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now
ldx #>SER_ERR_INV_IOCTL
rts
;----------------------------------------------------------------------------
; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
; registers are already save, no parameters are passed and no return code
; is expected.
;
IRQ: lda #$0F
sta IndReg ; Switch to the system bank
ldy #ACIA::STATUS
lda (acia),y ; Check ACIA status for receive interrupt
and #$08
beq @L9 ; Jump if no ACIA interrupt
ldy #ACIA::DATA
lda (acia),y ; Get byte from ACIA
ldx RecvFreeCnt ; Check if we have free space left
beq @L1 ; Jump if no space in receive buffer
ldy RecvTail ; Load buffer pointer
sta RecvBuf,y ; Store received byte in buffer
inc RecvTail ; Increment buffer pointer
dec RecvFreeCnt ; Decrement free space counter
cpx #33 ; Check for buffer space low
bcs @L9 ; Assert flow control if buffer space low
; Assert flow control if buffer space too low
@L1: lda RtsOff
ldy #ACIA::CMD
sta (acia),y
sta Stopped
; Done, switch back to the execution segment
@L9: lda ExecReg
sta IndReg
rts
;----------------------------------------------------------------------------
; Try to send a byte. Internal routine. A = TryHard
.proc TryToSend
sta tmp1 ; Remember tryHard flag
lda #$0F
sta IndReg ; Switch to the system bank
@L0: lda SendFreeCnt
cmp #$ff
beq @L3 ; Bail out
; Check for flow stopped
@L1: lda Stopped
bne @L3 ; Bail out
; Check that swiftlink is ready to send
@L2: ldy #ACIA::STATUS
lda (acia),y
and #$10
bne @L4
bit tmp1 ; Keep trying if must try hard
bmi @L0
; Switch back the bank and return
@L3: lda ExecReg
sta IndReg
rts
; Send byte and try again
@L4: ldx SendHead
lda SendBuf,x
ldy #ACIA::DATA
sta (acia),y
inc SendHead
inc SendFreeCnt
jmp @L0
.endproc
;----------------------------------------------------------------------------
; Initialize buffers
InitBuffers:
ldx #0
stx Stopped
stx RecvHead
stx RecvTail
stx SendHead
stx SendTail
dex ; X = 255
stx RecvFreeCnt
stx SendFreeCnt
rts
;----------------------------------------------------------------------------
; Write to the ACIA changing the indirect segment. Offset is in Y, value in A.
write_cmd:
ldy #ACIA::CMD
write: pha
lda #$0F
sta IndReg
pla
sta (acia),y
lda ExecReg
sta IndReg
rts

View File

@ -12,178 +12,31 @@
ExecReg = $0000
IndReg = $0001
; Up to $20 and $60-8F used by runtime and fixed values
; -----------------------------------
KbdScanBuf = $20 ; Intermediate for keyboard scan
; RS232 stuff
RecvHead = $21 ; Head of receive buffer
RecvTail = $22 ; Tail of receive buffer
RecvFreeCnt = $23 ; Number of bytes in receive buffer
SendHead = $24 ; Head of send buffer
SendTail = $25 ; Tail of send buffer
SendFreeCnt = $26 ; Number of bytes free in send buffer
FNAM_ADR := $90 ; File name address
FNAM_SEG := $92 ; Unused
SaveAdrLow = $93
SaveAdrHi = $94
SaveAdrSeg = $95
EndAdrLow = $96
EndAdrHi = $97
EndAdrSeg = $98
StartAdrLow = $99
StartAdrHi = $9A
StartAdrSeg = $9B
ST := $9C ; Status
FNAM_LEN := $9D
LFN := $9E
DEVNUM := $9F
SECADR := $A0
DefInpDev = $A1
DefOutDev = $A2
TapeBufPtr = $A3
TapeBufPtrSeg = $A5
rs232BufPtr = $A6
rs232BufPtrSeg = $A8
StopKeyFlag = $A9
CTemp = $AA
snsw1 = $AB
SegChgPtr = $AC
PChighSave = $AE
PClowSave = $AF
SRSave = $B0
ACSave = $B1
XRSave = $B2
YRSave = $B3
SPSave = $B4
IndSegSave = $B5
IRQSaveHi = $B7
IRQSaveLo = $B8
Adr1 = $B9
Adr2 = $BB
MoniCntr = $BD
MoniTmp = $BE
MoniDevNr = $BF
PgmKeyBuf = $C0
PgmKeyPtr = $C2
sedsal = $C4
sedeal = $C6
CharPtr = $C8
CURS_Y = $CA
CURS_X = $CB
;CharPtr = $C8
;CURS_Y = $CA
;CURS_X = $CB
GrafMode = $CC
LastIndex = $CD
LastLine = $CE
LastCol = $CF
crsw = $D0
KeyIndex = $D1
QuoteSw = $D2
Insrt = $D3
Config = $D4
LastLinePos = $D5
PgmKeyIndex = $D6
RepeatCount = $D7
RepeatDelay = $D8
sedt1 = $D9 ; Temp
sedt2 = $DA ; Temp, frequently used
PrtData = $DB
ScreenTop = $DC
ScreenBot = $DD
ScreenLeft = $DE
ScreenRight = $DF
ModKey = $E0
NorKey = $E1
BitTable = $E2
; ---------------------------------------------------------------------------
; Page 3 variables
;
; system ram vectors
;
IRQVec = $0300
BRKVec = $0302
NMIVec = $0304
openVec = $0306
closeVec = $0308
chkinVec = $030A
ckoutVec = $030C
clrchVec = $030E
basinVec = $0310
bsoutVec = $0312
stopVec = $0314
getinVec = $0316
clallVec = $0318
loadVec = $031A
saveVec = $031C
usrcmd = $031E
escvec = $0320
ctrlvec = $0322
secndVec = $0324
tksaVec = $0326
acptrVec = $0328
cioutVec = $032A
untlkVec = $032C
unlsnVec = $032E
listnVec = $0330
talkVec = $0332
;
;
;
LogicalAdrTable = $0334
FirstAdrTable = $033E
SecondAdrTable = $0348
SysMemBot = $0352
SysMemTop = $0355
UsrMemBot = $0358
UsrMemTop = $035B
TimOut = $035E
VerifyFlag = $035F
DevTabIndex = $0360
MsgFlag = $0361
CassBufPtr = $0362
t1 = $0363
t2 = $0364
XSave = $0365
SaveX = $0366
SaveXt = $0367
temp = $0368
alarm = $0369
TapeVec = $036A
LoadStAdr = $036F
CassMotFlag = $0375
m6551Ctrl = $0376
m6551Cmd = $0377
rs232status = $037A
dcddsr = $037B
rs232head = $037C
rs232tail = $037D
PgmKeyEnd = $0380
PgmKeySeg = $0382
PgmKeySize = $0383
RVS = $0397
linetmp = $0398
LastPrtChar = $0399
InsertFlag = $039A
ScrollFlag = $039B
FktTemp = $039C
PgmKeyIdx = $039D
LogScrollFlag = $039E
BellMode = $039F ; Bell on/off 00 = an
SegSave = $03A0
TabStopTable = $03A1 ; 80 bits for tabstops
KeyBuf = $03AB ; Keyboard buffer
FUNKEY_VEC = $03B5 ; Vector for function key handline
FunKeyTmp = $03B7
sedt3 = $03B9
MoniSegSave = $03f0
wstvec = $03F8
WstFlag = $03FA ; Warm start flag
; ---------------------------------------------------------------------------
@ -274,11 +127,12 @@ Env3 = $1C
; acia = $dd00
ADataReg = $00
AStatusReg = $01
ACmdReg = $02
ACtrlReg = $03
.struct ACIA
DATA .byte
STATUS .byte
CMD .byte
CTRL .BYTE
.endstruct
; I/O $de00: Triport #1 6525

View File

@ -5,44 +5,69 @@
;
.export _cgetc
.import plot, write_crtc
.import plot, write_crtc, sys_bank, restore_bank
.import cursor
.import sysp0: zp, sysp3: zp
.include "cbm610.inc"
_cgetc: lda KeyIndex ; Get number of characters
_cgetc: lda IndReg
pha
lda #$0F
sta IndReg ; Switch to the system bank
ldy #$D1
lda (sysp0),y ; Get number of keys in keyboard buffer
bne L2 ; Jump if there are already chars waiting
; Switch on the cursor if needed
lda cursor
beq L1 ; Jump if no cursor
beq L0 ; Jump if no cursor
jsr plot ; Set the current cursor position
ldy #$D4
lda (sysp0),y ; Get the cursor format
ldy #10
lda Config ; Cursor format
jsr write_crtc ; Set the cursor formar
jsr write_crtc ; Set the cursor format
L1: lda KeyIndex
beq L1
L0: ldy #$D1
L1: lda (sysp0),y ; Get the number of keys in the buffer
beq L1 ; Wait until we have some keys
ldy #10
lda #$20 ; Cursor off
jsr write_crtc
L2: ldx #$00 ; Get index
ldy KeyBuf ; Get first character in the buffer
sei
L3: lda KeyBuf+1,x ; Move up the remaining chars
sta KeyBuf,x
inx
cpx KeyIndex
bne L3
dec KeyIndex
cli
L2: ldy #$D1
lda (sysp0),y ; Get number of chars in buffer
tax
ldy #$AB
lda (sysp3),y ; Get first char from keyboard buffer
sta c ; Save for return
dex
txa
ldy #$D1
sta (sysp0),y
sei
jmp L4
L3: iny
lda (sysp3),y
dey
sta (sysp3),y
iny
L4: dex
bpl L3
cli
pla
sta IndReg ; Restore old segment
ldx #$00 ; High byte
tya ; First char from buffer
lda c ; First char from buffer
rts
.bss
c: .byte 0

View File

@ -6,6 +6,7 @@
.export _clrscr
.import plot
.import CURS_X: zp, CURS_Y: zp, CharPtr: zp
.include "cbm610.inc"

View File

@ -5,13 +5,13 @@
; void cputc (char c);
;
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
.exportzp CURS_X, CURS_Y
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
.import PLOT
.import _gotoxy
.import popa
.import _gotoxy
.import popa
.import ktmp: zp, crtc: zp, CURS_X: zp, CURS_Y: zp, CharPtr: zp
.include "cbm610.inc"
@ -79,13 +79,6 @@ L10: and #$7F
L11: ora #$40
bne cputdirect ; Branch always
; Set cursor position, calculate RAM pointers
plot: ldy CURS_X
ldx CURS_Y
clc
jmp PLOT
; Write one character to the screen without doing anything else, return X
; position in Y
@ -99,4 +92,61 @@ putchar:
stx IndReg
rts
; Set cursor position, calculate RAM pointers
plot: ldx CURS_Y
lda LineLSBTab,x
sta CharPtr
lda LineMSBTab,x
sta CharPtr+1
lda IndReg
pha
lda #$0F
sta IndReg
ldy #$00
clc
sei
sta (crtc),y
lda CharPtr
adc CURS_X
iny
sta (crtc),y
dey
lda #$0E
sta (crtc),y
iny
lda (crtc),y
and #$F8
sta ktmp
lda CharPtr+1
adc #$00
and #$07
ora ktmp
sta (crtc),y
cli
pla
sta IndReg
rts
; -------------------------------------------------------------------------
; Low bytes of the start address of the screen lines
.rodata
LineLSBTab:
.byte $00,$50,$A0,$F0,$40,$90,$E0,$30
.byte $80,$D0,$20,$70,$C0,$10,$60,$B0
.byte $00,$50,$A0,$F0,$40,$90,$E0,$30
.byte $80
; -------------------------------------------------------------------------
; High bytes of the start address of the screen lines
LineMSBTab:
.byte $D0,$D0,$D0,$D0,$D1,$D1,$D1,$D2
.byte $D2,$D2,$D3,$D3,$D3,$D4,$D4,$D4
.byte $D5,$D5,$D5,$D5,$D6,$D6,$D6,$D7
.byte $D7

View File

@ -4,17 +4,16 @@
; This must be the *first* file on the linker command line
;
.export _exit
.exportzp crtc, sid, IPCcia, cia, acia, tpi1, tpi2, ktab1
.exportzp ktab2, ktab3, ktab4, time, RecvBuf, SendBuf
.export _exit, BRKVec, UDTIM
.import initlib, donelib
.import condes, initlib, donelib
.import push0, callmain
.import __BSS_RUN__, __BSS_SIZE__
.import irq, nmi
.import k_irq, k_nmi
.import __BSS_RUN__, __BSS_SIZE__, __EXTZP_RUN__
.import __IRQFUNC_TABLE__, __IRQFUNC_COUNT__
.import SCNKEY
.include "zeropage.inc"
.include "extzp.inc"
.include "cbm610.inc"
@ -47,51 +46,31 @@
; that is overwritten later.
;
.code
.segment "BASICHDR"
; To make things more simple, make the code of this module absolute.
.org $0001
Head: .byte $03,$00,$11,$00,$0a,$00,$81,$20,$49,$b2,$30,$20,$a4,$20,$34,$00
.byte $03,$00,$11,$00,$0a,$00,$81,$20,$49,$b2,$30,$20,$a4,$20,$34,$00
.byte $19,$00,$14,$00,$87,$20,$4a,$00,$27,$00,$1e,$00,$97,$20,$32,$35
.byte $36,$aa,$49,$2c,$4a,$00,$2f,$00,$28,$00,$82,$20,$49,$00,$39,$00
.byte $32,$00,$9e,$20,$32,$35,$36,$00,$4f,$00,$3c,$00,$83,$20,$31,$32
.byte $30,$2c,$31,$36,$39,$2c,$31,$2c,$31,$33,$33,$2c,$30,$00,$00,$00
; Since we need some vectors to access stuff in the system bank for our own,
; we will include them here, starting from $60:
.res $60-*
crtc: .word $d800
sid: .word $da00
IPCcia: .word $db00
cia: .word $dc00
acia: .word $dd00
tpi1: .word $de00
tpi2: .word $df00
ktab1: .word $ea29
ktab2: .word $ea89
ktab3: .word $eae9
ktab4: .word $eb49
time: .dword $0000
RecvBuf: .word $0100 ; RS232 received buffer
SendBuf: .word $0200 ; RS232 send buffer
;------------------------------------------------------------------------------
; The code in the target bank when switching back will be put at the bottom
; of the stack. We will jump here to switch segments. The range $F2..$FF is
; not used by any kernal routine.
.res $F8-*
Back: ldx spsave
.segment "STARTUP"
Back: sei
ldx spsave
txs
lda IndReg
sta ExecReg
; The following code is a copy of the code that is poked in the system bank
; memory by the basic header program, it's only for documentation and not
; actually used here:
;------------------------------------------------------------------------------
; We are at $100 now. The following snippet is a copy of the code that is poked
; in the system bank memory by the basic header program, it's only for
; documentation and not actually used here:
sei
lda #$01
@ -99,57 +78,132 @@ Back: ldx spsave
; This is the actual starting point of our code after switching banks for
; startup. Beware: The following code will get overwritten as soon as we
; use the stack (since it's in page 1)!
; use the stack (since it's in page 1)! We jump to another location, since
; we need some space for subroutines that aren't used later.
tsx
stx spsave ; Save the system stackpointer
ldx #$FF
txs ; Set up our own stack
jmp Origin
; Hardware vectors, copied to $FFFA
.proc vectors
sta ExecReg
rts
nop
.word nmi ; NMI vector
.word 0 ; Reset - not used
.word irq ; IRQ vector
.endproc
; Initializers for the extended zeropage. See extzp.s
.proc extzp
.word $0100 ; sysp1
.word $0300 ; sysp3
.word $d800 ; crtc
.word $da00 ; sid
.word $db00 ; ipccia
.word $dc00 ; cia
.word $dd00 ; acia
.word $de00 ; tpi1
.word $df00 ; tpi2
.word $ea29 ; ktab1
.word $ea89 ; ktab2
.word $eae9 ; ktab3
.word $eb49 ; ktab4
.endproc
; The following code is part of the kernal call subroutine. It is copied
; to $FFAE
.proc callsysbank_15
php
pha
lda #$0F ; Bank 15
sta IndReg
sei
.endproc
; Save the old stack pointer from the system bank and setup our hw sp
Origin: tsx
stx spsave ; Save the system stackpointer
ldx #$FE ; Leave $1FF untouched for cross bank calls
txs ; Set up our own stack
; Initialize the extended zeropage
ldx #.sizeof(extzp)-1
L1: lda extzp,x
sta <__EXTZP_RUN__,x
dex
bpl L1
; Set the interrupt, NMI and other vectors
ldy #vectors_size-1
L0: lda vectors,y
sta $10000 - vectors_size,y
ldy #.sizeof(vectors)-1
L2: lda vectors,y
sta $10000 - .sizeof(vectors),y
dey
bpl L0
bpl L2
; Switch the indirect segment to the system bank
lda #$0F
sta IndReg
; Copy the kernal zero page ($90-$F2) from the system bank
; Setup the C stack
lda #$90
sta ptr1
lda #$00
sta ptr1+1
ldy #$62-1
L1: lda (ptr1),y
sta $90,y
dey
bpl L1
lda #.lobyte($FEB5 - .sizeof(callsysbank_15))
sta sp
lda #.hibyte($FEB5 - .sizeof(callsysbank_15))
sta sp+1
; Copy the page 3 vectors in place
; Setup the subroutine and jump vector table that redirects kernal calls to
; the system bank. Copy the bank switch routines starting at $FEB5 from the
; system bank into the current bank.
ldy #$00
L2: lda p3vectors,y
sta $300,y
iny
cpy #p3vectors_size
bne L2
; Copy the rest of page 3 from the system bank
ldy #.sizeof(callsysbank_15)-1 ; Copy the modified part
@L1: lda callsysbank_15,y
sta $FEB5 - .sizeof(callsysbank_15),y
dey
bpl @L1
lda #$00
sta ptr1
lda #$03
sta ptr1+1
L3: lda (ptr1),y
sta $300,y
iny
bne L3
lda #.lobyte($FEB5) ; Copy the ROM part
sta ptr1
lda #.hibyte($FEB5)
sta ptr1+1
ldy #$00
@L2: lda (ptr1),y
sta $FEB5,y
iny
cpy #<($FF6F-$FEB5)
bne @L2
; Setup the jump vector table
ldy #$00
ldx #45-1 ; Number of vectors
@L3: lda #$20 ; JSR opcode
sta $FF6F,y
iny
lda #.lobyte($FEB5 - .sizeof(callsysbank_15))
sta $FF6F,y
iny
lda #.hibyte($FEB5 - .sizeof(callsysbank_15))
sta $FF6F,y
iny
dex
bpl @L3
; Copy the stack from the system bank into page 3
ldy #$FF
L4: lda (sysp1),y
sta $300,y
dey
cpy spsave
bne L4
; Set the indirect segment to bank we're executing in
@ -186,64 +240,19 @@ Z3: sta (ptr1),y
iny
dex
bne Z3
Z4:
; Setup the C stack
lda #<$FF81
sta sp
lda #>$FF81
sta sp+1
; We expect to be in page 2 now
.if (* < $1FD)
jmp $200
.res $200-*
.endif
.if (* < $200)
.res $200-*,$EA
.endif
.if (* >= $2F0)
.error "Code range invalid"
.endif
; This code is in page 2, so we may now start calling subroutines safely,
; since the code we execute is no longer in the stack page.
; Call module constructors
jsr initlib
; Execute the program code
jmp Start
Z4: jmp Init
; ------------------------------------------------------------------------
; Additional data that we need for initialization and that's overwritten
; later
; We are at $200 now. We may now start calling subroutines safely, since
; the code we execute is no longer in the stack page.
vectors:
sta ExecReg
rts
.byte $01 ; Filler
.word nmi
.word 0 ; Reset - not used
.word irq
vectors_size = * - vectors
.segment "PAGE2"
p3vectors:
.word k_irq ; IRQ user vector
.word k_brk ; BRK user vector
.word k_nmi ; NMI user vector
p3vectors_size = * - p3vectors
; Call module constructors, enable chained IRQs afterwards.
; ------------------------------------------------------------------------
; This is the program code after setup. It starts at $400
.res $400-*
Start:
Init: jsr initlib
lda #.lobyte(__IRQFUNC_COUNT__*2)
sta irqcount
; Enable interrupts
@ -253,51 +262,140 @@ Start:
jsr callmain
; Call module destructors. This is also the _exit entry.
; Disable Call module destructors. This is also the _exit entry and the default entry
; point for the break vector.
_exit: jsr donelib ; Run module destructors
_exit: lda #$00
sta irqcount ; Disable custom irq handlers
jsr donelib ; Run module destructors
; Clear the start of the zero page, since it will be interpreted as a
; (garbage) BASIC program otherwise. This is also the default entry for
; the break vector.
; Adress the system bank
k_brk: sei
lda #$00
ldx #$3E
Clear: sta $02,x
dex
bne Clear
lda #$0F
sta IndReg
; Setup the welcome code at the stack bottom in the system bank. Use
; the F4/F5 vector to access the system bank
; Copy back the old system bank stack contents
lda #$0F
sta IndReg
ldy #$00
sty $F4
iny
sty $F5
ldy #reset_size-1
@L1: lda reset,y
sta ($F4),y
dey
bne @L1
jmp Back
ldy #$FF
@L1: lda $300,y
sta (sysp1),y
dey
cpy spsave
bne @L1
; ------------------------------------------------------------------------
; Code that is copied into the system bank at $100 when switching back
; Setup the welcome code at the stack bottom in the system bank.
reset: cli
jmp $8000 ; BASIC cold start
reset_size = * - reset
ldy #$00
lda #$58 ; CLI opcode
sta (sysp1),y
iny
lda #$60 ; RTS opcode
sta (sysp1),y
jmp Back
; -------------------------------------------------------------------------
; Data area - switch back to relocatable mode
; The IRQ handler goes into PAGE2. For performance reasons, and to allow
; easier chaining, we do handle the IRQs in the execution bank (instead of
; passing them to the system bank).
.reloc
; This is the mapping of the active irq register of the 6525 (tpi1):
;
; Bit 7 6 5 4 3 2 1 0
; | | | | ^ 50 Hz
; | | | ^ SRQ IEEE 488
; | | ^ cia
; | ^ IRQB ext. Port
; ^ acia
irq: pha
txa
pha
tya
pha
lda IndReg
pha
lda ExecReg
sta IndReg ; Be sure to address our segment
tsx
lda $105,x ; Get the flags from the stack
and #$10 ; Test break flag
bne dobrk
; It's an IRQ
cld
; Call chained IRQ handlers
ldy irqcount
beq irqskip
lda #<__IRQFUNC_TABLE__
ldx #>__IRQFUNC_TABLE__
jsr condes ; Call the functions
; Done with chained IRQ handlers, check the TPI for IRQs and handle them
irqskip:lda #$0F
sta IndReg
ldy #TPI::AIR
lda (tpi1),y ; Interrupt Register 6525
beq noirq
; 50/60Hz interrupt
cmp #%00000001 ; ticker irq?
bne irqend
jsr SCNKEY ; Poll the keyboard
jsr UDTIM ; Bump the time
; Done
irqend: ldy #TPI::AIR
sta (tpi1),y ; Clear interrupt
noirq: pla
sta IndReg
pla
tay
pla
tax
pla
nmi: rti
dobrk: jmp (BRKVec)
; -------------------------------------------------------------------------
; udtim routine for the 610. We will not check for the stop key here, since
; C programs will not use it.
;
.proc UDTIM
inc time
bne L9
inc time+1
bne L9
inc time+2
bne L9
inc time+3
L9: rts
.endproc
; -------------------------------------------------------------------------
; Page 3
.segment "PAGE3"
BRKVec: .addr _exit ; BRK indirect vector
; -------------------------------------------------------------------------
; Data area.
.data
spsave: .res 1
.bss
irqcount: .byte 0

View File

@ -5,7 +5,7 @@
;
.export write_crtc, read_crtc
.importzp crtc
.importzp crtc, ktmp
.include "cbm610.inc"
@ -13,7 +13,7 @@
; Write a value to the CRTC. The index is in Y, the value in A
.proc write_crtc
sta sedt1
sta ktmp
lda IndReg
pha
lda #$0F
@ -23,23 +23,23 @@
sei
sta (crtc),y
iny
lda sedt1
lda ktmp
sta (crtc),y
cli
pla
sta IndReg
lda sedt1
lda ktmp
rts
.endproc
.proc read_crtc
sty sedt1
sty ktmp
lda IndReg
pha
lda #$0F
sta IndReg
lda sedt1
lda ktmp
ldy #$00
sei
sta (crtc),y
@ -50,7 +50,7 @@
pla
sta IndReg
tya
ldy sedt1
ldy ktmp
rts
.endproc

13
libsrc/cbm610/extzp.inc Normal file
View File

@ -0,0 +1,13 @@
;
; Ullrich von Bassewitz, 2003-12-20
;
; Additional zero page locations for the CBM610.
;
; ------------------------------------------------------------------------
.globalzp sysp1, sysp3, crtc, sid, ipccia, cia, acia, tpi1, tpi2
.globalzp ktab1, ktab2, ktab3, ktab4
.globalzp sysp0, time, segsave, ktmp, CURS_X, CURS_Y, CharPtr

44
libsrc/cbm610/extzp.s Normal file
View File

@ -0,0 +1,44 @@
;
; Ullrich von Bassewitz, 2003-12-20
;
; Additional zero page locations for the CBM610.
; NOTE: This file is actually linked to an application with its full contents,
; so the program comes up with the values given in this file.
;
; ------------------------------------------------------------------------
.include "extzp.inc"
.segment "EXTZP" : zeropage
; The following values get initialized from a table in the startup code.
; While this sounds crazy, it has reasons that have to do with modules (and
; we have the space anyway). So when changing anything, be sure to adjust the
; initializer table
sysp1: .word $0000
sysp3: .word $0000
crtc: .word $0000
sid: .word $0000
ipccia: .word $0000
cia: .word $0000
acia: .word $0000
tpi1: .word $0000
tpi2: .word $0000
ktab1: .word $0000
ktab2: .word $0000
ktab3: .word $0000
ktab4: .word $0000
sysp0: .word $0000
time: .dword $0000
segsave: .byte 0
scanbuf: .byte 0
ktmp: .byte 0
CURS_X: .byte 0
CURS_Y: .byte 0
CharPtr: .word 0

View File

@ -1,16 +1,23 @@
;
; Ullrich von Bassewitz, 06.08.1998
; Ullrich von Bassewitz, 2003-12-20
;
; int kbhit (void);
;
.export _kbhit
.importzp sysp0
.import return0, return1
.include "cbm610.inc"
.proc _kbhit
lda KeyIndex ; Get number of characters
ldx IndReg
lda #$0F
sta IndReg
ldy #$D1 ; Number of keys in kbd buffer
lda (sysp0),y
stx IndReg
bne L1
jmp return0
L1: jmp return1

84
libsrc/cbm610/kernal.s Normal file
View File

@ -0,0 +1,84 @@
;
; Ullrich von Bassewitz, 2003-12-20
;
; CBM610 kernal functions
;
.export CINT
.export IOINIT
.export RAMTAS
.export RESTOR
.export VECTOR
.export SETMSG
.export SECOND
.export TKSA
.export MEMTOP
.export MEMBOT
.export SCNKEY
.export SETTMO
.export ACPTR
.export CIOUT
.export UNTLK
.export UNLSN
.export LISTEN
.export TALK
.export SETLFS
.export CLOSE
.export CHKIN
.export CKOUT
.export CLRCH
.export BASIN
.export BSOUT
.export LOAD
.export SAVE
.export STOP
.export GETIN
.export CLALL
.export PLOT
;-----------------------------------------------------------------------------
; All functions are available in the kernal jump table. Functions having
; replacements (usually short ones where the overhead of the cross bank call
; is not worth the trouble) are commented out.
CINT = $FF81
IOINIT = $FF84
RAMTAS = $FF87
RESTOR = $FF8A
VECTOR = $FF8D
SETMSG = $FF90
SECOND = $FF93
TKSA = $FF96
MEMTOP = $FF99
MEMBOT = $FF9C
SCNKEY = $FF9F
SETTMO = $FFA2
ACPTR = $FFA5
CIOUT = $FFA8
UNTLK = $FFAB
UNLSN = $FFAE
LISTEN = $FFB1
TALK = $FFB4
;READST = $FFB7
SETLFS = $FFBA
;SETNAM = $FFBD
;OPEN = $FFC0
CLOSE = $FFC3
CHKIN = $FFC6
CKOUT = $FFC9
CLRCH = $FFCC
BASIN = $FFCF
BSOUT = $FFD2
LOAD = $FFD5
SAVE = $FFD8
;SETTIM = $FFDB
;RDTIM = $FFDE
STOP = $FFE1
GETIN = $FFE4
CLALL = $FFE7
;UDTIM = $FFEA
;SCREEN = $FFED
PLOT = $FFF0
;IOBASE = $FFF3

View File

@ -1,246 +0,0 @@
;
; Ullrich von Bassewitz, 2003-12-18
;
; IEC bus routines for the 610.
;
.export TALK, LISTEN, SECOND, TKSA, CIOUT, UNTLK, UNLSN, ACPTR
.import UPDST
.import tpi1: zp, cia: zp
.include "cbm610.inc"
; -------------------------------------------------------------------------
; TALK subroutine
TALK: ora #$40
bne talk_listen
; -------------------------------------------------------------------------
; LISTEN subroutine
LISTEN: ora #$20
talk_listen:
pha
lda #$3F
ldy #TPI::DDRA
sta (tpi1),y
lda #$FF
ldy #CIA::PRA
sta (cia),y
ldy #CIA::DDRA
sta (cia),y
lda #$FA
ldy #TPI::PRA
sta (tpi1),y
lda CTemp
bpl LF268
lda (tpi1),y
and #$DF
sta (tpi1),y
lda snsw1
jsr transfer_byte
lda CTemp
and #$7F
sta CTemp
ldy #TPI::PRA
lda (tpi1),y
ora #$20
sta (tpi1),y
LF268: lda (tpi1),y ; TPI::PRA
and #$F7
sta (tpi1),y
pla
; jmp transfer_byte
; -------------------------------------------------------------------------
; Output A (without EOF flag)
transfer_byte:
eor #$FF
ldy #CIA::PRA
sta (cia),y
ldy #TPI::PRA
lda (tpi1),y
ora #$12
sta (tpi1),y
lda (tpi1),y
and #%11000000
beq LF2D4
lda #$80
jsr UPDST
bne LF304 ; Branch always
; Wait until NRFD is high
LF2D4: lda (tpi1),y
bpl LF2D4
and #$EF
sta (tpi1),y
LF2DE: jsr SetTimB32ms
bcc LF2E4 ; Branch always
LF2E3: sec
LF2E4: ldy #TPI::PRA
lda (tpi1),y
and #$40
bne LF2FC
ldy #CIA::ICR
lda (cia),y
and #$02
beq LF2E4
lda TimOut
bmi LF2DE
bcc LF2E3
lda #$01
jsr UPDST
LF2FC: ldy #TPI::PRA
lda (tpi1),y
ora #$10
sta (tpi1),y
LF304: lda #$FF
ldy #CIA::PRA
sta (cia),y
rts
; -------------------------------------------------------------------------
; Output secondary address after listen
SECOND: jsr transfer_byte
scatn: ldy #TPI::PRA
lda (tpi1),y
ora #$08
sta (tpi1),y
rts
; -------------------------------------------------------------------------
; Output secondary address
TKSA: jsr transfer_byte
LF283: ldy #TPI::PRA
lda (tpi1),y
and #$39
; A -> IEC control, data ready for input
set_listen:
ldy #TPI::PRA
sta (tpi1),y
lda #$C7
ldy #TPI::DDRA
sta (tpi1),y
lda #$00
ldy #CIA::DDRA
sta (cia),y
jmp scatn
; -------------------------------------------------------------------------
; CIOUT routine
CIOUT: pha
lda CTemp
bpl @L1
lda snsw1
jsr transfer_byte
lda CTemp
@L1: ora #$80
sta CTemp
pla
sta snsw1
rts
; -------------------------------------------------------------------------
; UNTALK/UNLISTEN
UNTLK: lda #$5F
bne LF2B1
UNLSN: lda #$3F
LF2B1: jsr talk_listen
lda #$F9
jmp set_listen
; -------------------------------------------------------------------------
; ACPTR routine
ACPTR: ldy #TPI::PRA
lda (tpi1),y
and #$B9
ora #$81
sta (tpi1),y
LF314: jsr SetTimB32ms
bcc LF31A
LF319: sec
LF31A: ldy #TPI::PRA
lda (tpi1),y
and #$10
beq LF33F
ldy #CIA::ICR
lda (cia),y
and #$02
beq LF31A ; Loop if not timeout
lda TimOut
bmi LF314
bcc LF319
lda #$02
jsr UPDST
ldy #TPI::PRA
lda (tpi1),y
and #$3D
sta (tpi1),y
lda #$0D
rts
LF33F: lda (tpi1),y ; TPI::PRA
and #$7F
sta (tpi1),y
and #$20
bne LF350
lda #$40
jsr UPDST
LF350: ldy #CIA::PRA
lda (cia),y
eor #$FF
pha
ldy #TPI::PRA
lda (tpi1),y
ora #$40
sta (tpi1),y
LF35E: lda (tpi1),y ; TPI::PRA
and #$10
beq LF35E
lda (tpi1),y
and #$BF
sta (tpi1),y
pla
rts
; -------------------------------------------------------------------------
; Set timer B to 32,64 ms and start it
SetTimB32ms:
lda #$FF ; 255*256*0,5 µs
ldy #CIA::TBHI
sta (cia),y ; as high byte, low byte = 0
lda #$11
ldy #CIA::CRB
sta (cia),y ; Start the timer
ldy #CIA::ICR
lda (cia),y ; Clear the interrupt flag
clc
rts

View File

@ -1,98 +0,0 @@
;
; Ullrich von Bassewitz, 28.09.1998
;
; IRQ routine for the 610.
;
.export irq, nmi, k_irq, k_nmi
.import SCNKEY, UDTIM, k_rs232
.importzp tpi1
.include "cbm610.inc"
; -------------------------------------------------------------------------
; This is the mapping of the active irq register of the 6525 (tpi1):
;
; Bit 7 6 5 4 3 2 1 0
; | | | | ^ 50 Hz
; | | | ^ SRQ IEEE 488
; | | ^ cia
; | ^ IRQB ext. Port
; ^ acia
; -------------------------------------------------------------------------
; IRQ entry point
.proc irq
pha
txa
pha
tya
pha
tsx
lda $104,x ; Get the flags from the stack
and #$10 ; Test break flag
bne L1
jmp (IRQVec)
L1: jmp (BRKVec)
.endproc
; -------------------------------------------------------------------------
; NMI entry point
.proc nmi
jmp (NMIVec)
.endproc
; -------------------------------------------------------------------------
; Kernal irq entry point. The IRQvec points here (usually).
k_irq:
lda IndReg ; Ind. Segment retten
pha
cld
lda #$0F
sta IndReg
ldy #TPI::AIR
lda (tpi1),y ; Interrupt Register 6525
beq noirq
; -------------------------------------------------------------------------
; 50/60Hz interrupt
cmp #%00000001 ; ticker irq?
bne irq1
jsr SCNKEY ; Poll the keyboard
jsr UDTIM ; Bump the time
; -------------------------------------------------------------------------
; UART interrupt
irq1: cmp #%00010000 ; interrupt from uart?
bne irqend
jsr k_rs232 ; Read character from uart
; -------------------------------------------------------------------------
; Done
irqend: ldy #TPI::AIR
sta (tpi1),y ; Clear interrupt
noirq: pla
sta IndReg
pla
tay
pla
tax
pla
k_nmi: rti

22
libsrc/cbm610/kopen.s Normal file
View File

@ -0,0 +1,22 @@
;
; Ullrich von Bassewitz, 2003-12-20
;
; OPEN kernal call.
;
; NOTE: The OPEN system call in the CBM610 kernal is different from the
; standard. It evaluates the carry flag and does a normal open if carry clear
; and some strange things (output sa 15 + name on IEC) if carry set. To be
; compatible with our CBM file stuff, we have to clear the carry before
; calling the real OPEN.
.export OPEN
.proc OPEN
clc
jmp $FFC0
.endproc

View File

@ -1,76 +0,0 @@
;
; Ullrich von Bassewitz, 28.09.1998
;
; PLOT routine for the 610.
;
.export PLOT
.importzp crtc
.include "cbm610.inc"
.proc PLOT
bcc set
ldx CURS_Y
ldy CURS_X
rts
set: stx CURS_Y
sty CURS_X
lda LineLSBTab,x
sta CharPtr
lda LineMSBTab,x
sta CharPtr+1
lda IndReg
pha
lda #$0F
sta IndReg
ldy #$00
clc
sei
sta (crtc),y
lda CharPtr
adc CURS_X
iny
sta (crtc),y
dey
lda #$0E
sta (crtc),y
iny
lda (crtc),y
and #$F8
sta sedt1
lda CharPtr+1
adc #$00
and #$07
ora sedt1
sta (crtc),y
cli
pla
sta IndReg
rts
.endproc
; -------------------------------------------------------------------------
; Low bytes of the start address of the screen lines
.rodata
LineLSBTab:
.byte $00,$50,$A0,$F0,$40,$90,$E0,$30
.byte $80,$D0,$20,$70,$C0,$10,$60,$B0
.byte $00,$50,$A0,$F0,$40,$90,$E0,$30
.byte $80
; -------------------------------------------------------------------------
; High bytes of the start address of the screen lines
LineMSBTab:
.byte $D0,$D0,$D0,$D0,$D1,$D1,$D1,$D2
.byte $D2,$D2,$D3,$D3,$D3,$D4,$D4,$D4
.byte $D5,$D5,$D5,$D5,$D6,$D6,$D6,$D7
.byte $D7

View File

@ -6,13 +6,20 @@
.export READST
.import sys_bank, restore_bank
.import sysp0: zp, ktmp: zp
.include "cbm610.inc"
.proc READST
lda ST ; Load status
rts ; Return to caller
jsr sys_bank
sty ktmp ; Save Y register
ldy #ST
lda (sysp0),y ; Load ST from system bank
ldy ktmp
jmp restore_bank ; Will set condition codes on A
.endproc

View File

@ -1,144 +0,0 @@
;
; Ullrich von Bassewitz, 28.09.1998
;
; Keyboard polling stuff for the 610.
;
.export SCNKEY
.importzp tpi2, ktab1, ktab2, ktab3, ktab4
.include "cbm610.inc"
.proc SCNKEY
lda #$FF
sta ModKey
sta NorKey
lda #$00
sta KbdScanBuf
ldy #TPI::PRB
sta (tpi2),y
ldy #TPI::PRA
sta (tpi2),y
jsr Poll
and #$3F
eor #$3F
bne L1
jmp NoKey
L1: lda #$FF
ldy #TPI::PRA
sta (tpi2),y
asl a
ldy #TPI::PRB
sta (tpi2),y
jsr Poll
pha
sta ModKey
ora #$30
bne L3 ; Branch always
L2: jsr Poll
L3: ldx #$05
ldy #$00
L4: lsr a
bcc L5
inc KbdScanBuf
dex
bpl L4
sec
ldy #TPI::PRB
lda (tpi2),y
rol a
sta (tpi2),y
ldy #TPI::PRA
lda (tpi2),y
rol a
sta (tpi2),y
bcs L2
pla
bcc NoKey ; Branch always
L5: ldy KbdScanBuf
sty NorKey
pla
asl a
asl a
asl a
bcc L6
bmi L7
lda (ktab2),y ; Shifted normal key
ldx GrafMode
beq L8
lda (ktab3),y ; Shifted key in graph mode
bne L8
L6: lda (ktab4),y ; Key with ctrl pressed
bne L8
L7: lda (ktab1),y ; Normal key
L8: tax
cpx #$FF ; Valid key?
beq Done
cpy LastIndex
beq Repeat
ldx #$13
stx RepeatDelay
ldx KeyIndex
cpx #$09
beq NoKey
cpy #$59
bne PutKey
cpx #$08
beq NoKey
sta KeyBuf,x
inx
bne PutKey
NoKey: ldy #$FF
Done: sty LastIndex
End: lda #$7F
ldy #TPI::PRA
sta (tpi2),y
ldy #TPI::PRB
lda #$FF
sta (tpi2),y
rts
Repeat: dec RepeatDelay
bpl End
inc RepeatDelay
dec RepeatCount
bpl End
inc RepeatCount
ldx KeyIndex
bne End
PutKey: sta KeyBuf,x
inx
stx KeyIndex
ldx #$03
stx RepeatCount
bne Done
.endproc
; Poll the keyboard port until it's stable
.proc Poll
ldy #TPI::PRC
L1: lda (tpi2),y
sta KeySave
lda (tpi2),y
cmp KeySave
bne L1
rts
.endproc
.bss
KeySave: .res 1

View File

@ -1,19 +0,0 @@
;
; Ullrich von Bassewitz, 2003-12-18
;
; SETLFS replacement function
;
.export SETLFS
.include "cbm610.inc"
.proc SETLFS
sta LFN
stx DEVNUM
sty SECADR
rts ; Return to caller
.endproc

View File

@ -10,14 +10,35 @@
.export SETNAM
.import sys_bank, restore_bank
.import sysp0: zp, ktmp: zp
.include "cbm610.inc"
.proc SETNAM
sta FNAM_LEN
stx FNAM_ADR
sty FNAM_ADR+1
rts
pha
jsr sys_bank
sty ktmp
txa
ldy #FNAM_ADR
sta (sysp0),y
lda ktmp
iny
sta (sysp0),y
lda ExecReg ; Assume name is always in this segment
ldy #FNAM_SEG
sta (sysp0),y
ldy #FNAM_LEN
pla
sta (sysp0),y
ldy ktmp
jmp restore_bank
.endproc

View File

@ -1,25 +0,0 @@
;
; Ullrich von Bassewitz, 28.09.1998
;
; udtim routine for the 610. We will not check for the stop key here, since
; C programs will not use it.
;
.export UDTIM
.importzp time
.proc UDTIM
inc time
bne L9
inc time+1
bne L9
inc time+2
bne L9
inc time+3
L9: rts
.endproc

View File

@ -1,20 +0,0 @@
;
; Ullrich von Bassewitz, 2003-12-18
;
; UPDST kernal call.
;
.export UPDST
.include "cbm610.inc"
.proc UPDST
ora ST
sta ST
rts
.endproc