# 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) \
# 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) \
done
mv cbm610/crt0.o cbm610.o
cp cbm610/*.emd .
+ cp cbm610/*.ser .
#-----------------------------------------------------------------------------
# GEOS on the C64/128
*.emd
+*.joy
+*.ser
*.tgi
-
+
%.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 $@ $^
#--------------------------------------------------------------------------
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)
;
.export screensize
-
- .include "cbm610.inc"
-
-.proc screensize
-
- ldx #XSIZE
- ldy #YSIZE
- rts
-
-.endproc
+ .import SCREEN
+
+ screensize = SCREEN
;
.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
.proc set_bank
pha
lda IndReg
- sta IndSegSave
+ sta segsave
pla
sta IndReg
rts
.proc restore_bank
pha
- lda IndSegSave
+ lda segsave
sta IndReg
pla
rts
.export _set_brk, _reset_brk
.export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc
- .import _atexit
+ .import _atexit, BRKVec
.include "cbm610.inc"
.proc brk_handler
+ pla
+ sta _brk_01
pla
sta _brk_y
pla
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
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
--- /dev/null
+;
+; 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
+
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
; ---------------------------------------------------------------------------
; 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
;
.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
.export _clrscr
.import plot
+ .import CURS_X: zp, CURS_Y: zp, CharPtr: zp
.include "cbm610.inc"
; 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"
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
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
; 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"
; 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
; 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
-
- lda #$90
- sta ptr1
- lda #$00
- sta ptr1+1
- ldy #$62-1
-L1: lda (ptr1),y
- sta $90,y
- dey
- bpl L1
-
-; Copy the page 3 vectors in place
-
- ldy #$00
-L2: lda p3vectors,y
- sta $300,y
- iny
- cpy #p3vectors_size
- bne L2
+; Setup the C stack
-; Copy the rest of page 3 from the system bank
+ lda #.lobyte($FEB5 - .sizeof(callsysbank_15))
+ sta sp
+ lda #.hibyte($FEB5 - .sizeof(callsysbank_15))
+ sta sp+1
- lda #$00
- sta ptr1
- lda #$03
- sta ptr1+1
-L3: lda (ptr1),y
- sta $300,y
- iny
- bne L3
+; 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 #.sizeof(callsysbank_15)-1 ; Copy the modified part
+@L1: lda callsysbank_15,y
+ sta $FEB5 - .sizeof(callsysbank_15),y
+ dey
+ bpl @L1
+
+ 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
iny
dex
bne Z3
-Z4:
+Z4: jmp Init
-; Setup the C stack
+; ------------------------------------------------------------------------
+; We are at $200 now. We may now start calling subroutines safely, since
+; the code we execute is no longer in the stack page.
- lda #<$FF81
- sta sp
- lda #>$FF81
- sta sp+1
+.segment "PAGE2"
-; We expect to be in page 2 now
+; Call module constructors, enable chained IRQs afterwards.
-.if (* < $1FD)
- jmp $200
- .res $200-*
-.endif
-.if (* < $200)
- .res $200-*,$EA
-.endif
-.if (* >= $2F0)
-.error "Code range invalid"
-.endif
+Init: jsr initlib
+ lda #.lobyte(__IRQFUNC_COUNT__*2)
+ sta irqcount
-; 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
+; Enable interrupts
- jsr initlib
+ cli
-; Execute the program code
+; Push arguments and call main()
- jmp Start
+ jsr callmain
-; ------------------------------------------------------------------------
-; Additional data that we need for initialization and that's overwritten
-; later
-
-vectors:
- sta ExecReg
- rts
- .byte $01 ; Filler
- .word nmi
- .word 0 ; Reset - not used
- .word irq
-vectors_size = * - vectors
+; Disable Call module destructors. This is also the _exit entry and the default entry
+; point for the break vector.
-p3vectors:
- .word k_irq ; IRQ user vector
- .word k_brk ; BRK user vector
- .word k_nmi ; NMI user vector
-p3vectors_size = * - p3vectors
+_exit: lda #$00
+ sta irqcount ; Disable custom irq handlers
+ jsr donelib ; Run module destructors
+; Adress the system bank
-; ------------------------------------------------------------------------
-; This is the program code after setup. It starts at $400
+ lda #$0F
+ sta IndReg
- .res $400-*
+; Copy back the old system bank stack contents
-Start:
+ ldy #$FF
+@L1: lda $300,y
+ sta (sysp1),y
+ dey
+ cpy spsave
+ bne @L1
-; Enable interrupts
+; Setup the welcome code at the stack bottom in the system bank.
- cli
+ ldy #$00
+ lda #$58 ; CLI opcode
+ sta (sysp1),y
+ iny
+ lda #$60 ; RTS opcode
+ sta (sysp1),y
+ jmp Back
-; Push arguments and call main()
+; -------------------------------------------------------------------------
+; 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).
- jsr callmain
+; 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)
-; Call module destructors. This is also the _exit entry.
+; -------------------------------------------------------------------------
+; udtim routine for the 610. We will not check for the stop key here, since
+; C programs will not use it.
+;
-_exit: jsr donelib ; Run module destructors
+.proc UDTIM
-; 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.
+ inc time
+ bne L9
+ inc time+1
+ bne L9
+ inc time+2
+ bne L9
+ inc time+3
+L9: rts
-k_brk: sei
- lda #$00
- ldx #$3E
-Clear: sta $02,x
- dex
- bne Clear
+.endproc
-; Setup the welcome code at the stack bottom in the system bank. Use
-; the F4/F5 vector to access the system bank
+; -------------------------------------------------------------------------
+; Page 3
- 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
+.segment "PAGE3"
-; ------------------------------------------------------------------------
-; Code that is copied into the system bank at $100 when switching back
+BRKVec: .addr _exit ; BRK indirect vector
-reset: cli
- jmp $8000 ; BASIC cold start
-reset_size = * - reset
; -------------------------------------------------------------------------
-; Data area - switch back to relocatable mode
-
- .reloc
+; Data area.
.data
spsave: .res 1
-
+.bss
+irqcount: .byte 0
;
.export write_crtc, read_crtc
- .importzp crtc
+ .importzp crtc, ktmp
.include "cbm610.inc"
; 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
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
pla
sta IndReg
tya
- ldy sedt1
+ ldy ktmp
rts
.endproc
--- /dev/null
+;
+; 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
+
--- /dev/null
+;
+; 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
+
+
+
+
;
-; 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
--- /dev/null
+;
+; 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
+
+++ /dev/null
-;
-; 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
-
+++ /dev/null
-;
-; 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
-
-
--- /dev/null
+;
+; 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
+
+
+
+++ /dev/null
-;
-; 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
.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
+++ /dev/null
-;
-; 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
-
-
+++ /dev/null
-;
-; 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
-
-
.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
+++ /dev/null
-;
-; 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
-
-
+++ /dev/null
-;
-; Ullrich von Bassewitz, 2003-12-18
-;
-; UPDST kernal call.
-;
-
- .export UPDST
-
- .include "cbm610.inc"
-
-.proc UPDST
-
- ora ST
- sta ST
- rts
-
-.endproc
-
-
-