Incorporate the rest of JGH's MOS refactoring.

This commit is contained in:
Bobbi Webber-Manners 2021-08-09 21:27:44 -04:00
parent 62be805a80
commit e3a4537db4
18 changed files with 1694 additions and 1713 deletions

Binary file not shown.

View File

@ -153,13 +153,14 @@ WRTAUX MAC
* ... order matters! * ... order matters!
PUT LOADER PUT LOADER
PUT MAINMEM PUT MAINMEM
PUT AUX.MOS.WS PUT AUXMEM.MOSEQU
PUT AUX.AMOS.INIT PUT AUXMEM.INIT
PUT AUX.VDU PUT AUXMEM.VDU
PUT AUX.HOSTFS PUT AUXMEM.HOSTFS
PUT AUX.AMOS.KRNL PUT AUXMEM.KERNEL
PUT AUX.OSBW.ORIG * PUT AUXMEM.OSBW.ORIG
* PUT AUX.OSBW.JGH PUT AUXMEM.BYTWRD
PUT AUX.MISC PUT AUXMEM.CHARIO
PUT AUX.IRQ.VECS PUT AUXMEM.MISC

View File

@ -1,316 +0,0 @@
*********************************************************
* AppleMOS Host Filing System
* Routes MOS calls <-> ProDOS
*********************************************************
* OSFIND - open/close a file for byte access
FINDHND PHX
PHY
PHA
STX ZP1 ; Points to filename
STY ZP1+1
CMP #$00 ; A=$00 = close
BEQ :CLOSE
PHA
LDA #<MOSFILE+1
STA ZP2
LDA #>MOSFILE+1
STA ZP2+1
LDY #$00
:L1 LDA (ZP1),Y
>>> WRTMAIN
STA (ZP2),Y
>>> WRTAUX
INY
CMP #$0D ; Carriage return
BNE :L1
DEY
>>> WRTMAIN
STY MOSFILE ; Length (Pascal string)
>>> WRTAUX
PLA ; Recover options
>>> XF2MAIN,OFILE
:CLOSE >>> WRTMAIN
STY MOSFILE ; Write file number
>>> WRTAUX
>>> XF2MAIN,CFILE
OSFINDRET
>>> ENTAUX
PLY ; Value of A on entry
CPY #$00 ; Was it close?
BNE :S1
TYA ; Preserve A for close
:S1 PLY
PLX
RTS
* OSFSC - miscellanous file system calls
OSFSC LDA #<OSFSCM
LDY #>OSFSCM
JSR PRSTR
RTS
OSFSCM ASC 'OSFSC.'
DB $00
* OSGBPB - Get/Put a block of bytes to/from an open file
GBPBHND LDA #<OSGBPBM
LDY #>OSGBPBM
JMP PRSTR
OSGBPBM ASC 'OSGBPB.'
DB $00
* OSBPUT - write one byte to an open file
BPUTHND PHX
PHY
PHA ; Stash char to write
>>> WRTMAIN
STY MOSFILE ; File reference number
>>> WRTAUX
>>> XF2MAIN,FILEPUT
OSBPUTRET
>>> ENTAUX
CLC ; Means no error
PLA
PLY
PLX
RTS
* OSBGET - read one byte from an open file
BGETHND PHX
PHY
>>> WRTMAIN
STY MOSFILE ; File ref number
>>> WRTAUX
>>> XF2MAIN,FILEGET
OSBGETRET
>>> ENTAUX
CLC ; Means no error
CPY #$00 ; Check error status
BEQ :NOERR
SEC ; Set carry for error
BRA :EXIT
:NOERR CLC
:EXIT PLY
PLX
RTS
* OSARGS - adjust file arguments
* On entry, A=action
* X=>4 byte ZP control block
* Y=file handle
ARGSHND PHA
PHX
PHY
CPY #$00
BNE :HASFILE
CMP #$00 ; Y=0,A=0 => current file sys
BNE :S1
PLY
PLX
PLA
LDA #$09 ; Hosted filing system
RTS
:S1 CMP #$01 ; Y=0,A=1 => addr of CLI
BNE :S2
* TODO: Implement this for *RUN and *command
JSR BEEP
BRA :IEXIT
:S2 CMP #$FF ; Y=0,A=FF => flush all files
BNE :IEXIT
>>> WRTMAIN
STZ MOSFILE ; Zero means flush all
>>> WRTAUX
BRA :IFLUSH
:HASFILE >>> WRTMAIN
STY MOSFILE ; File ref num
STX MOSFILE+1 ; Pointer to ZP control block
>>> WRTAUX
CMP #$00 ; Y!=0,A=0 => read seq ptr
BNE :S3
>>> WRTMAIN
STZ MOSFILE+2 ; 0 means get pos
>>> WRTAUX
>>> XF2MAIN,TELL
:IEXIT BRA :IEXIT2
:IFLUSH BRA :FLUSH
:S3 CMP #$01 ; Y!=0,A=1 => write seq ptr
BNE :S4
>>> WRTMAIN
LDA $00,X
STA MOSFILE+2
LDA $01,X
STA MOSFILE+3
LDA $02,X
STA MOSFILE+4
>>> WRTAUX
>>> XF2MAIN,SEEK
:IEXIT2 BRA :EXIT
:S4 CMP #$02 ; Y!=0,A=2 => read file len
BNE :S5
>>> WRTMAIN
STA MOSFILE+2 ; Non-zero means get len
>>> WRTAUX
>>> XF2MAIN,TELL
:S5 CMP #$FF ; Y!=0,A=FF => flush file
BNE :EXIT
:FLUSH >>> XF2MAIN,FLUSH
:EXIT PLY
PLX
PLA
RTS
OSARGSRET
>>> ENTAUX
PLY
PLX
PLA
RTS
* OSFILE - perform actions on entire files
* On entry, A=action
* XY=>control block
* On exit, A=preserved if unimplemented
* A=0 object not found (not load/save)
* A=1 file found
* A=2 directory found
* XY preserved
* control block updated
FILEHND PHX
PHY
PHA
STX ZP1 ; LSB of parameter block
STY ZP1+1 ; MSB of parameter block
LDA #<FILEBLK
STA ZP2
LDA #>FILEBLK
STA ZP2+1
LDY #$00 ; Copy to FILEBLK in main mem
:L1 LDA (ZP1),Y
>>> WRTMAIN
STA (ZP2),Y
>>> WRTAUX
INY
CPY #$12
BNE :L1
LDA (ZP1) ; Pointer to filename->ZP2
STA ZP2
LDY #$01
LDA (ZP1),Y
STA ZP2+1
LDA #<MOSFILE+1 ; ZP1 is dest pointer
STA ZP1
LDA #>MOSFILE+1
STA ZP1+1
LDA (ZP2) ; Look at first char of filename
CMP #'9'+1
BCS :NOTDIGT
CMP #'0'
BCC :NOTDIGT
LDA #'N' ; Prefix numeric with 'N'
>>> WRTMAIN
STA (ZP1)
>>> WRTAUX
LDY #$01 ; Increment Y
DEC ZP2 ; Decrement source pointer
LDA ZP2
CMP #$FF
BNE :L2
DEC ZP2+1
BRA :L2
:NOTDIGT LDY #$00
:L2 LDA (ZP2),Y
>>> WRTMAIN
STA (ZP1),Y
>>> WRTAUX
INY
CMP #$21 ; Space or Carriage return
BCS :L2
DEY
>>> WRTMAIN
STY MOSFILE ; Length (Pascal string)
>>> WRTAUX
PLA ; Get action back
PHA
BEQ :S1 ; A=00 -> SAVE
CMP #$FF
BEQ :S2 ; A=FF -> LOAD
LDA #<OSFILEM ; If not implemented, print msg
LDY #>OSFILEM
JSR PRSTR
PLA
PHA
JSR OUTHEX
LDA #<OSFILEM2
LDY #>OSFILEM2
JSR PRSTR
PLA ; Not implemented, return unchanged
PLY
PLX
RTS
:S1 >>> XF2MAIN,SAVEFILE
:S2 >>> XF2MAIN,LOADFILE
OSFILERET
>>> ENTAUX
PLY ; Value of A on entry
CPY #$FF ; LOAD
BNE :S4 ; Deal with return from SAVE
CMP #$01 ; No file found
BNE :SL1
BRK
DB $D6 ; $D6 = Object not found
ASC 'File not found'
BRK
:SL1 CMP #$02 ; Read error
BNE :SL2
BRK
DB $CA ; $CA = Premature end, 'Data lost'
ASC 'Read error'
BRK
:SL2 LDA #$01 ; Return code - file found
BRA :EXIT
:S4 CPY #$00 ; Return from SAVE
BNE :S6
CMP #$01 ; Unable to create or open
BNE :SS1
BRK
DB $C0 ; $C0 = Can't create file to save
ASC 'Can'
DB $27
ASC 't save file'
BRK
:SS1 CMP #$02 ; Unable to write
BNE :S6
BRK
DB $CA ; $CA = Premature end, 'Data lost'
ASC 'Write error'
BRK
:S6 LDA #$00
:EXIT PLY
PLX
RTS
OSFILEM ASC 'OSFILE($'
DB $00
OSFILEM2 ASC ')'
DB $00
* Performs OSBYTE $7F EOF function
* File ref number is in X
CHKEOF >>> WRTMAIN
STX MOSFILE ; File reference number
>>> WRTAUX
>>> XF2MAIN,FILEEOF
CHKEOFRET
>>> ENTAUX
TAX ; Return code -> X
RTS

View File

@ -1,164 +0,0 @@
**********************************************************
* Interrupt Handlers, MOS redirection vectors etc.
**********************************************************
* IRQ/BRK handler
IRQBRKHDLR
PHA
>>> WRTMAIN
STA $45 ; A->$45 for ProDOS IRQ handlers
>>> WRTAUX
TXA
PHA
CLD
TSX
LDA $103,X ; Get PSW from stack
AND #$10
BEQ :IRQ ; IRQ
SEC
LDA $0104,X
SBC #$01
STA FAULT
LDA $0105,X
SBC #$00
STA FAULT+1
PLA
TAX
PLA
CLI
JMP (BRKV) ; Pass on to BRK handler
:IRQ >>> XF2MAIN,A2IRQ
IRQBRKRET
PLA ; TODO: Pass on to IRQ1V
TAX
PLA
NULLRTI RTI
PRERR LDY #$01
PRERRLP LDA (FAULT),Y
BEQ PRERR1
JSR OSWRCH
INY
BNE PRERRLP
NULLRTS
PRERR1 RTS
MOSBRKHDLR LDA #<MSGBRK
LDY #>MSGBRK
JSR PRSTR
JSR PRERR
JSR OSNEWL
JSR OSNEWL
STOP JMP STOP ; Cannot return from a BRK
MSGBRK DB $0D
ASC "ERROR: "
DB $00
RDROM LDA #<OSRDRMM
LDY #>OSRDRMM
JMP PRSTR
OSRDRMM ASC 'OSRDDRM.'
DB $00
EVENT LDA #<OSEVENM
LDY #>OSEVENM
JMP PRSTR
OSEVENM ASC 'OSEVEN.'
DB $00
GSINTGO LDA #<OSINITM
LDY #>OSINITM
JMP PRSTR
OSINITM ASC 'GSINITM.'
DB $00
GSRDGO LDA #<OSREADM
LDY #>OSREADM
JMP PRSTR
OSREADM ASC 'GSREAD.'
DB $00
* Default page 2 contents
DEFVEC DW NULLRTS ; $200 USERV
DW MOSBRKHDLR ; $202 BRKV
DW NULLRTI ; $204 IRQ1V
DW NULLRTI ; $206 IRQ2V
DW CLIHND ; $208 CLIV
DW BYTEHND ; $20A BYTEV
DW WORDHND ; $20C WORDV
DW WRCHHND ; $20E WRCHV
DW RDCHHND ; $210 RDCHV
DW FILEHND ; $212 FILEV
DW ARGSHND ; $214 ARGSV
DW BGETHND ; $216 BGETV
DW BPUTHND ; $218 BPUTV
DW GBPBHND ; $21A GBPBV
DW FINDHND ; $21C FINDV
DW NULLRTS ; $21E FSCV
ENDVEC
*
* Acorn MOS entry points at the top of RAM
* Copied from loaded code to high memory
*
MOSVEC ; Base of API entries here in loaded code
MOSAPI EQU $FFB6 ; Real base of API entries in real memory
ORG MOSAPI
* OPTIONAL ENTRIES
* ----------------
*OSSERV JMP NULLRTS ; FF95 OSSERV
*OSCOLD JMP NULLRTS ; FF98 OSCOLD
*OSPRSTR JMP OUTSTR ; FF9B PRSTRG
*OSFF9E JMP NULLRTS ; FF9E
*OSSCANHEX JMP RDHEX ; FFA1 SCANHX
*OSFFA4 JMP NULLRTS ; FFA4
*OSFFA7 JMP NULLRTS ; FFA7
*PRHEX JMP OUTHEX ; FFAA PRHEX
*PR2HEX JMP OUT2HEX ; FFAD PR2HEX
*OSFFB0 JMP NULLRTS ; FFB0
*OSWRRM JMP NULLRTS ; FFB3 OSWRRM
* COMPULSORY ENTRIES
* ------------------
VECSIZE DB ENDVEC-DEFVEC ; FFB6 VECSIZE Size of vectors
VECBASE DW DEFVEC ; FFB7 VECBASE Base of default vectors
OSRDRM JMP RDROM ; FFB9 OSRDRM Read byte from paged ROM
OSCHROUT JMP OUTCHAR ; FFBC CHROUT Send char to VDU driver
OSEVEN JMP EVENT ; FFBF OSEVEN Signal an event
GSINIT JMP GSINTGO ; FFC2 GSINIT Init string reading
GSREAD JMP GSRDGO ; FFC5 GSREAD Parse general string
NVWRCH JMP WRCHHND ; FFC8 NVWRCH Nonvectored WRCH
NVRDCH JMP RDCHHND ; FFCB NVRDCH Nonvectored RDCH
OSFIND JMP (FINDV) ; FFCE OSFIND
OSGBPB JMP (GBPBV) ; FFD1 OSGBPB
OSBPUT JMP (BPUTV) ; FFD4 OSBPUT
OSBGET JMP (BGETV) ; FFD7 OSBGET
OSARGS JMP (ARGSV) ; FFDA OSARGS
OSFILE JMP (FILEV) ; FFDD OSFILE
OSRDCH JMP (RDCHV) ; FFE0 OSRDCH
OSASCI CMP #$0D ; FFE3 OSASCI
BNE OSWRCH
OSNEWL LDA #$0A ; FFE7 OSNEWL
JSR OSWRCH
OSWRCR LDA #$0D ; FFEC OSWRCR
OSWRCH JMP (WRCHV) ; FFEE OSWRCH
OSWORD JMP (WORDV) ; FFF1 OSWORD
OSBYTE JMP (BYTEV) ; FFF4 OSBYTE
OSCLI JMP (CLIV) ; FFF7 OSCLI
NMIVEC DW NULLRTI ; FFFA NMIVEC
RSTVEC DW STOP ; FFFC RSTVEC
IRQVEC
* Assembler doesn't like running up to $FFFF, so we bodge a bit
MOSEND
ORG MOSEND-MOSAPI+MOSVEC
DW IRQBRKHDLR ; FFFE IRQVEC
MOSVEND
* Buffer for one 512 byte disk block in aux mem
AUXBLK DS $200

View File

@ -1,398 +0,0 @@
************************
* OSWORD/OSBYTE dispatch
************************
BYTELOW EQU $01 ; (BWLOW-BWADDR)/2-1 Max low OSBYTE
BYTEHIGH EQU $7C ; First high OSBYTE
BYTEMAX EQU $87 ; (BWTOP-BWLOW)/2+BYTEHIGH-1
WORDOFF EQU $0C ; Word offset to start OSWORD tbl
WORDMAX EQU $06 ; (OSWEND-OSWBASE)/2-1 Max OSWORD
* OSWORD:
* On entry, A=action
* XY=>control block
* On exit, A=preserved
* X,Y,Cy trashed (except OSWORD 0)
* control block updated
*
WORDHND PHA
PHP
SEI
STA OSAREG ; Store registers
STX OSCTRL+0 ; Point to control block
STY OSCTRL+1
LDX #$08 ; X=SERVWORD
CMP #$E0 ; User OSWORD
BCS WORDGO1
CMP #WORDMAX+1
BCS BWFAIL ; Pass on to service call
ADC #WORDOFF
BCC BWCALL ; Call OSWORD routine
WORDGO1 LDA #WORDOFF+WORDMAX+1
BCS BWCALL ; Call User OSWORD routine
* OSBYTE:
* On entry, A=action
* X=first parameter
* Y=second parameter if A>$7F
* On exit, A=preserved
* X=first returned result
* Y=second returned result if A>$7F
* Cy=any returned status if A>$7F
*
BYTEHND PHA
PHP
SEI
STA OSAREG ; Store registers
STX OSXREG
STY OSYREG
LDX #$07 ; X=SERVBYTE
CMP #$A6
BCS BYTEGO1 ; OSBYTE &A6+
CMP #BYTEMAX+1
BCS BWFAIL ; Pass on to service call
CMP #BYTEHIGH
BCS BYTEGO2 ; High OSBYTEs
CMP #BYTELOW+1
BCS BWFAIL ; Pass on to service call
STZ OSYREG ; Prepare Y=0 for low OSBYTEs
BCC BYTEGO3
BYTEGO1 LDA #BYTEMAX+1 ; Index for BYTEVAR
BYTEGO2 SBC #BYTEHIGH-BYTELOW-1 ; Reduce OSBYTE number
BYTEGO3 ORA #$80 ; Will become CS=OSBYTE call
BWCALL ASL A ; Index into dispatch table
TAY ; Y=offset into dispatch table
* BIT FXNETCLAIM ; Check Econet intercept flag
* BPL BWNONET ; No intercept, skip past
* TXA ; Set A=BYTE or WORD call
* CLV ; Clear V
* JSR CALLNET ; Call Econet with X=call type
* BVS BWEXIT ; V set, claimed by NETV, return
BWNONET LDA BWADDR+1,Y ; Get routine address
STA OSINTWS+1
LDA BWADDR+0,Y
STA OSINTWS+0
LDA OSAREG ; Get A parameter back
LDY OSYREG ; Get Y parameter back
LDX OSXREG ; Get X parameter, set EQ from it
BCS BYTWRDGO ; Skip if OSBYTE call
LDY #$00 ; OSWORD call, enter with Y=0
LDA (OSCTRL),Y ; and A=first byte in CB, set EQ from it
SEC ; Enter routine with CS
BYTWRDGO JSR JMPADDR ; Call the routine
* Routines are entered with:
* A=OSBYTE call or first byte of OSWORD control block
* X=X parameter
* Y=OSBYTE Y parameter for A>$7F
* Y=$00 for OSBYTE A<$80
* Y=$00 for OSWORD so (OSCTRL),Y => first byte
* Carry Set
* EQ set from OSBYTE X or from OSWORD first byte
* X,Y,Cy from routine returned to caller
BWEXIT ROR A ; Move Carry to A
PLP ; Restore original flags
ROL A ; Move Carry back to flags
PLA ; Restore A
CLV ; Clear V = Actioned
RTS
BWFAIL
* JSR SERVICE ; Offer to sideways ROMs
* LDX OSXREG ; Get returned X
* CMP #$00
* BEQ BWEXIT ; Claimed, return
JSR UNSUPPBW ; *DEBUG*
LDX #$FF ; X=&FF if unclaimed (normally set within SERVICE)
PLP ; Restore IRQs
PLA ; Restore A
BIT SETV ; Set V = Not actioned
RTS
SETV ; JMP() is $6C, bit 6 set, use to set V
JMPADDR JMP (OSINTWS)
*************************
* OSBYTE DISPATCH TABLE *
*************************
BWADDR DW BYTE00 ; OSBYTE 0 - Machine host
* DW BYTE01 ; OSBYTE 1 - User flag
* DW BYTE02 ; OSBYTE 2 - OSRDCH source
* DW BYTE03 ; OSBYTE 3 - OSWRCH dest
* DW BYTE04 ; OSBYTE 4 - Cursor keys
BWLOW
DW BYTE7C ; OSBYTE 124 - Clear Escape
DW BYTE7D ; OSBYTE 125 - Set Escape
DW BYTE7E ; OSBYTE 126 - Ack. Escape
DW BYTE7F ; OSBYTE 127 - Read EOF
DW BYTE80 ; OSBYTE 128 - ADVAL
DW BYTE81 ; OSBYTE 129 - INKEY
DW BYTE82 ; OSBYTE 130 - Memory high word
DW BYTE83 ; OSBYTE 131 - MEMBOT
DW BYTE84 ; OSBYTE 132 - MEMTOP
DW BYTE85 ; OSBYTE 133 - MEMTOP for MODE
DW BYTE86 ; OSBYTE 134 - POS, VPOS
DW BYTE87 ; OSBYTE 135 - Character, MODE
* DW BYTE88 ; OSBYTE 136 - *CODE
* DW BYTE89 ; OSBYTE 137 - *MOTOR
* DW BYTE8A ; OSBYTE 138 - Buffer insert
* DW BYTE8B ; OSBYTE 139 - *OPT
* DW BYTE8C ; OSBYTE 140 - *TAPE
* DW BYTE8D ; OSBYTE 141 - *ROM
* DW BYTE8E ; OSBYTE 142 - Enter language
* DW BYTE8F ; OSBYTE 143 - Service call
BWTOP
DW BYTEVAR ; OSBYTE 166+ - R/W OSBYTE var
*************************
* OSWORD DISPATCH TABLE *
*************************
OSWBASE DW WORD00 ; OSWORD 0 - Read input line
DW WORD01 ; OSWORD 1 - Read elapsed time
DW WORD02 ; OSWORD 2 - Write eleapsed time
DW WORD03 ; OSWORD 3 - Read interval timer
DW WORD04 ; OSWORD 4 - Write interval timer
DW WORD05 ; OSWORD 5 - Read I/O memory
DW WORD06 ; OSWORD 6 - Write I/O memory
* DW WORD07 ; OSWORD 7 - SOUND
* DW WORD08 ; OSWORD 8 - ENVELOPE
* DW WORD09 ; OSWORD 9 - POINT
* DW WORD0A ; OSWORD 10 - Read character bitmap
* DW WORD0B ; OSWORD 11 - Read palette
* DW WORD0C ; OSWORD 12 - Write palette
* DW WORD0D ; OSWORD 13 - Read coordinates
OSWEND
DW WORDE0 ; OSWORD &E0+ - User OSWORD
* OSWORD &00 - Read a line of input
***********************************
* On entry, (OSCTRL)=>control block
* Y=0, A=(OSCTRL)
* On exit, Y=length of line, offset to <cr>
* CC = Ok, CS = Escape
*
WORD00 STZ ESCFLAG ;;;; DEBUG HACK
IF MAXLEN-OSTEXT-2
LDY #$04
:WORD00LP1 LDA (OSCTRL),Y ; Copy MAXLEN, MINCH, MAXCH to workspace
STA MAXLEN-2,Y
DEY
CPY #$02
BCS :WORD00LP1
:WORD00LP2 LDA (OSCTRL),Y ; (OSTEXT)=>line buffer
STA OSTEXT,Y
DEY
BPL :WORD00LP2
INY ; Initial line length = zero
ELSE
LDA (OSCTRL),Y ; Copy control block
STA OSTEXT,Y ; 0,1 => text
INY ; 2 = MAXLEN
CPY #$05 ; 3 = MINCHAR
BCC WORD00 ; 4 = MAXCHAR
LDY #$00 ; Initial line length = zero
FIN
* STY FXLINES ; Reset line counter
CLI
BEQ :WORD00LP ; Enter main loop
:WORD00BELL LDA #$07 ; $07=BELL
DEY ; Balance next INY
:WORD00NEXT INY ; Step to next character
:WORD00ECHO JSR OSWRCH ; Print character
:WORD00LP JSR OSRDCH
BCS :WORD00ESC ; Escape
* TAX ; Save character in X for a mo
* LDA FXVAR03 ; Get FX3 destination
* ROR A
* ROR A ; Move bit 1 into Carry
* TXA ; Get character back
* BCS :WORD00TEST ; VDU disabled, ignore VDU queue
* LDX FXVDUQLEN ; Get length of VDU queue
* BNE :WORD00ECHO ; Not zero, just print and loop
:WORD00TEST CMP #$7F ; Delete
BNE :WORD00CHAR
CPY #$00
BEQ :WORD00LP ; Nothing to delete
DEY ; Back up one character
BCS :WORD00ECHO ; Loop back to print DEL
:WORD00CHAR CMP #$15 ; Ctrl-U
BNE :WORD00INS ; No, insert character
LDA #$7F ; Delete character
INY ; Balance first DEY
:WORD00ALL DEY ; Back up one character
BEQ :WORD00LP ; Beginning of line
JSR OSWRCH ; Print DELETE
JMP :WORD00ALL ; Loop to delete all
:WORD00INS STA (OSTEXT),Y ; Store the character
CMP #$0D
BEQ :WORD00CR ; CR - Done
CPY MAXLEN
BCS :WORD00BELL ; Too long, beep
CMP MINCHAR
BCC :WORD00ECHO ; <MINCHAR, don't step to next
CMP MAXCHAR
BCC :WORD00NEXT ; <MAXCHAR, step to next
BEQ :WORD00NEXT ; =MAXCHAR, step to next
BCS :WORD00ECHO ; >MAXCHAR, don't step to next
:WORD00CR JSR OSNEWL
* JSR CALLNET ; Call Econet Vector with A=13
:WORD00ESC LDA ESCFLAG ; Get Escape flag
ROL A ; Carry=Escape state
RTS
* OSWORD &01 - Read elapsed time
* OSWORD &02 - Write elapsed time
* OSWORD &03 - Read countdown timer
* OSWORD &04 - Write countdown timer
************************************
* On entry, (OSCTRL)=>control block
* Y=0
WORD01 TYA ; Dummy, just return zero
:WORD01LP STA (OSCTRL),Y
INY
CPY #$05
BCC :WORD01LP
WORD04
WORD03
WORD02 RTS ; Dummy, do nothing
* OSWORD &05 - Read I/O memory
* OSWORD &06 - Write I/O memory
***********************************
* On entry, (OSCTRL)+0 address
* (OSCTRL)+4 byte read or written
* Y=0, A=(OSCTRL)
WORD05 JSR GETADDR ; Point to address, set X and Y
; needs to switch to main memory
LDA (OSINTWS) ; Get byte
; needs to switch back
STA (OSCTRL),Y ; Store it
RTS
WORD06 JSR GETADDR ; Point to address, set X and Y
LDA (OSCTRL),Y ; Get byte
; needs to switch to main memory
STA (OSINTWS) ; Store it
; needs to switch back
RTS
GETADDR STA OSINTWS+0 ; (OSINTWS)=>byte to read/write
INY
LDA (OSCTRL),Y
STA OSINTWS+1
LDY #$04 ; Point Y to data byte
RTS
* KERNEL/BWMISC.S
*****************
* Here until tidied
BYTE00 LDX #$0A ; $00 = identify Host
RTS
BYTE7C LDA ESCFLAG ; $7C = clear escape condition
AND #$7F ; Clear MSbit
STA ESCFLAG
RTS
BYTE7D ROR ESCFLAG ; $7D = set escape condition
RTS
BYTE7E LDA ESCFLAG ; $7E = ack detection of ESC
AND #$7F ; Clear MSB
STA ESCFLAG
LDX #$FF ; Means ESC condition cleared
RTS
BYTE7F PHY ; $7F = check for EOF
JSR CHKEOF
PLY
RTS
; $80 = read ADC or get buf stat
BYTE80 CPX #$00 ; X<0 => info about buffers
BMI :S80BUF ; X>=0 read ADC info
LDX #$00 ; ADC - just return 0
LDY #$00 ; ADC - just return 0
RTS
:S80BUF CPX #$FF ; Kbd buf
BEQ :S80KEY
CPX #$FE ; RS423
BEQ :NONE
:ONE LDX #$01 ; For outputs, 1 char free
RTS
:S80KEY LDX $C000 ; Keyboard data/strobe
AND #$80
BEQ :NONE
BRA :ONE
:NONE LDX #$00 ; No chars in buf
RTS
BYTE81 JSR GETKEY ; $81 = Read key with time lim
RTS
BYTE82 LDY #$00 ; $82 = read high order address
LDX #$00 ; $0000 for language processor
RTS
BYTE83 LDY #$0E ; $83 = read bottom of user mem
LDX #$00 ; $0E00
RTS
BYTE84 LDY #$80 ; $84 = read top of user mem
LDX #$00
RTS
BYTE85 LDY #$80 ; $85 = top user mem for mode
LDX #$00
RTS
BYTE86 LDY ROW ; $86 = read cursor pos
LDX COL
RTS
BYTE8B LDA #$00 ; $8B = *OPT
JMP (FSCV) ; Hand over to filing system
BYTEDA RTS ; $DA = clear VDU queue
BYTEEA LDX #$00 ; No tube
RTS ; $EA = Tube presence
UNSUPPBW
LDA #<OSBYTEM
LDY #>OSBYTEM
CPX #7
BEQ UNSUPGO
LDA #<OSWORDM
LDY #>OSWORDM
UNSUPGO JSR PRSTR
LDA OSAREG
JSR OUTHEX
LDA #<OSBM2
LDY #>OSBM2
JMP PRSTR
OSBYTEM ASC 'OSBYTE($'
DB $00
OSWORDM ASC 'OSWORD($'
DB $00
OSBM2 ASC ').'
DB $00
BYTEVAR LDX #$00
LDY #$00
BYTE87
WORDE0 RTS

View File

@ -1,305 +0,0 @@
* OSWORD HANDLER
* On entry, A=action
* XY=>control block
* On exit, All preserved (except OSWORD 0)
* control block updated
WORDHND STX OSCTRL+0 ; Point to control block
STY OSCTRL+1
CMP #$00 ; OSWORD 0 read a line
BNE :S01
JMP OSWORD0
:S01 CMP #$01 ; OSWORD 1 read system clock
BNE :S02
JMP OSWORD1
:S02 CMP #$02 ; OSWORD 2 write system clock
BNE :S05
JMP OSWORD2
:S05 CMP #$05 ; OSWORD 5 read I/O memory
BNE :S06
JMP OSWORD5
:S06 CMP #$06 ; OSWORD 6 write I/O memory
BNE :UNSUPP
:UNSUPP PHA
LDA #<:OSWORDM ; Unimplemented, print msg
LDY #>:OSWORDM
JSR PRSTR
PLA
PHA
JSR OUTHEX
LDA #<:OSWRDM2
LDY #>:OSWRDM2
JSR PRSTR
PLA
RTS
:OSWORDM ASC 'OSWORD('
DB $00
:OSWRDM2 ASC ')'
DB $00
* OSRDLINE - Read a line of input
* On entry, (OSCTRL)=>control block
* On exit, Y=length of line, offset to <cr>
* CC = Ok, CS = Escape
*
OSWORD0 LDY #$04
:RDLNLP1 LDA (OSCTRL),Y ; Copy MAXLEN, MINCH, MAXCH to workspace
STA :MAXLEN-2,Y
DEY
CPY #$02
BCS :RDLNLP1
:RDLNLP2 LDA (OSCTRL),Y ; (ZP2)=>line buffer
STA ZP2,Y
DEY
BPL :RDLNLP2
INY
BRA :L1
:BELL LDA #$07 ; BELL
:R1 DEY
:R2 INY ; Step to next character
:R3 JSR OSWRCH ; Output character
:L1 JSR OSRDCH
BCS :EXIT
CMP #$08 ; Backspace
BEQ :RDDEL
CMP #$7F ; Delete
BEQ :RDDEL
CMP #$15 ; Ctrl-U
BNE :S2
INY ; Balance first DEY
:RDCTRLU DEY ; Back up one character
BEQ :L1 ; Beginning of line
LDA #$7F ; Delete
JSR OSWRCH
JMP :RDCTRLU
:RDDEL TYA
BEQ :L1 ; Beginning of line
DEY ; Back up one character
LDA #$7F ; Delete
BNE :R3 ; Jump back to delete
:S2 STA (ZP2),Y
CMP #$0D ; CR
BEQ :S3
CPY :MAXLEN
BCS :BELL ; Too long, beep
CMP :MINCH
BCC :R1 ; <MINCHAR, don't step to next
CMP :MAXCH
BEQ :R2 ; =MAXCHAR, step to next
BCC :R2 ; <MAXCHAR, step to next
BCS :R1 ; >MAXCHAR, don't step to next
:S3 JSR OSNEWL
:EXIT LDA ESCFLAG
ROL
RTS
:MAXLEN DB $00
:MINCH DB $00
:MAXCH DB $00
* OSWORD1 - Read system clock
OSWORD1 LDA #$00
LDY #$00
:L1 STA (OSCTRL),Y
INY
CPY #$05
BNE :L1
RTS
* OSWORD2 - Write system clock
OSWORD2 RTS ; Nothing to do
* OSWORD5 - Read I/O Processor memory
OSWORD5 LDA (OSCTRL) ; Fetch pointer into ZP2
STA ZP2
LDY #$01
LDA (OSCTRL),Y
STA ZP2+1
LDA (ZP2) ; Now read byte
LDY #$04 ; Save byte to XY+4
STA (OSCTRL),Y
RTS
* OSWORD6 - Write I/O Processor memory
OSWORD6 LDA (OSCTRL) ; Fetch pointer into ZP2
STA ZP2
LDY #$01
LDA (OSCTRL),Y
STA ZP2+1
LDY #$04 ; Byte to be written XY+4
LDA (OSCTRL),Y
STA (ZP2)
RTS
* OSBYTE HANDLER
* On entry, A=action
* X=first parameter
* Y=second parameter if A>$7F
* On exit, A=preserved
* X=first returned result
* Y=second returned result if A>$7F
* Cy=any returned status if A>$7F
BYTEHND PHA
JSR BYTECALLER
PLA
RTS
BYTECALLER
CMP #$00 ; $00 = identify MOS version
BNE :S02
LDX #$0A
RTS
:S02 CMP #$02 ; $02 = select input stream
BNE :S03
RTS ; Nothing to do
:S03 CMP #$03 ; $03 = select output stream
BNE :S0B
RTS ; Nothing to do
:S0B CMP #$0B ; $0B = set keyboard delay
BNE :S0C
RTS ; Nothing to do
:S0C CMP #$0C ; $0C = set keyboard rate
BNE :S0F
RTS ; Nothing to do
:S0F CMP #$0F ; $0F = flush buffers
BNE :S7C
RTS ; Nothing to do
:S7C CMP #$7C ; $7C = clear escape condition
BNE :S7D
LDA ESCFLAG
AND #$7F ; Clear MSbit
STA ESCFLAG
RTS
:S7D CMP #$7D ; $7D = set escape condition
BNE :S7E
ROR ESCFLAG
RTS
:S7E CMP #$7E ; $7E = ack detection of ESC
BNE :S7F
LDA ESCFLAG
AND #$7F ; Clear MSB
STA ESCFLAG
LDX #$FF ; Means ESC condition cleared
RTS
:S7F CMP #$7F ; $7F = check for EOF
BNE :S80
PHY
JSR CHKEOF
PLY
RTS
:S80 CMP #$80 ; $80 = read ADC or get buf stat
BNE :S81
CPX #$00 ; X<0 => info about buffers
BMI :S80BUF ; X>=0 read ADC info
LDX #$00 ; ADC - just return 0
LDY #$00 ; ADC - just return 0
RTS
:S80BUF CPX #$FF ; Kbd buf
BEQ :S80KEY
CPX #$FE ; RS423
BEQ :NONE
:ONE LDX #$01 ; For outputs, 1 char free
RTS
:S80KEY LDX $C000 ; Keyboard data/strobe
AND #$80
BEQ :NONE
BRA :ONE
:NONE LDX #$00 ; No chars in buf
RTS
:S81 CMP #$81 ; $81 = Read key with time lim
BNE :S82
JSR GETKEY
RTS
:S82 CMP #$82 ; $82 = read high order address
BNE :S83
LDY #$FF ; $FFFF for I/O processor
LDX #$FF
RTS
:S83 CMP #$83 ; $83 = read bottom of user mem
BNE :S84
LDY #$0E ; $0E00
LDX #$00
RTS
:S84 CMP #$84 ; $84 = read top of user mem
BNE :S85
LDY #$80
LDX #$00
RTS
:S85 CMP #$85 ; $85 = top user mem for mode
BNE :S86
LDY #$80
LDX #$00
RTS
:S86 CMP #$86 ; $86 = read cursor pos
BNE :S8B
LDY ROW
LDX COL
RTS
:S8B CMP #$8B ; $8B = *OPT
BNE :S8E
* TODO: Could implement some FS options here
* messages on/off, error behaviour
RTS ; Nothing to do (yet)
:S8E CMP #$8E ; $8E = Enter language ROM
BNE :SDA
LDA #$09 ; Print language name at $8009
LDY #$80
JSR PRSTR
JSR OSNEWL
JSR OSNEWL
CLC ; TODO: CLC or SEC?
LDA #$01
JMP AUXADDR
:SDA CMP #$DA ; $DA = clear VDU queue
BNE :SEA
RTS
:SEA CMP #$EA ; $EA = Tube presence
BNE :UNSUPP
LDX #$00 ; No tube
RTS
:UNSUPP PHX
PHY
PHA
LDA #<OSBYTEM
LDY #>OSBYTEM
JSR PRSTR
PLA
JSR OUTHEX
LDA #<OSBM2
LDY #>OSBM2
JSR PRSTR
PLY
PLX
RTS
OSBYTEM ASC 'OSBYTE($'
DB $00
OSBM2 ASC ').'
DB $00

245
aux.vdu.s
View File

@ -1,245 +0,0 @@
***********************************************************
* Apple //e VDU Driver for 80 column mode (PAGE2)
***********************************************************
* Clear to EOL
CLREOL LDA ROW
ASL
TAX
LDA SCNTAB,X ; LSB of row
STA ZP1
LDA SCNTAB+1,X ; MSB of row
STA ZP1+1
LDA COL
PHA
:L1 LDA COL
LSR
TAY
BCC :S1
>>> WRTMAIN
:S1 LDA #" "
STA (ZP1),Y
>>> WRTAUX
LDA COL
CMP #79
BEQ :S2
INC COL
BRA :L1
:S2 PLA
STA COL
RTS
* Clear the screen
CLEAR STZ ROW
STZ COL
:L1 JSR CLREOL
:S2 LDA ROW
CMP #23
BEQ :S3
INC ROW
BRA :L1
:S3 STZ ROW
STZ COL
RTS
* Print char in A at ROW,COL
PRCHRC PHA
LDA $C000 ; Kbd data/strobe
BMI :KEYHIT
:RESUME LDA ROW
ASL
TAX
LDA SCNTAB,X ; LSB of row address
STA ZP1
LDA SCNTAB+1,X ; MSB of row address
STA ZP1+1
LDA COL
LSR
TAY
BCC :S1
>>> WRTMAIN
:S1 PLA
ORA #$80
STA (ZP1),Y ; Screen address
>>> WRTAUX
RTS
:KEYHIT STA $C010 ; Clear strobe
AND #$7F
CMP #$13 ; Ctrl-S
BEQ :PAUSE
CMP #$1B ; Esc
BNE :RESUME
:ESC SEC
ROR ESCFLAG ; Set ESCFLAG
BRA :RESUME
:PAUSE STA $C010 ; Clear strobe
:L1 LDA $C000 ; Kbd data/strobe
BPL :L1
AND #$7F
CMP #$11 ; Ctrl-Q
BEQ :RESUME
CMP #$1B ; Esc
BEQ :ESC
BRA :PAUSE
* Return char at ROW,COL in A
GETCHRC LDA ROW
ASL
TAX
LDA SCNTAB,X
STA ZP1
LDA SCNTAB+1,X
STA ZP1+1
LDA COL
LSR
TAY
BCC :S1
STA $C002 ; Read main memory
:S1 LDA (ZP1),Y
STX $C003 ; Read aux mem again
RTS
* Perform backspace & delete operation
BACKSPC LDA COL
BEQ :S1
DEC COL
BRA :S2
:S1 LDA ROW
BEQ :S3
DEC ROW
STZ COL
:S2 LDA #' '
JSR PRCHRC
:S3 RTS
* Perform backspace/cursor left operation
NDBSPC LDA COL
BEQ :S1
DEC COL
BRA :S3
:S1 LDA ROW
BEQ :S3
DEC ROW
STZ COL
:S3 RTS
* Perform cursor right operation
CURSRT LDA COL
CMP #78
BCS :S1
INC COL
RTS
:S1 LDA ROW
CMP #22
BCS :S2
INC ROW
STZ COL
:S2 RTS
* Output character to VDU driver
* All registers trashable
OUTCHAR CMP #$00 ; NULL
BNE :T1
BRA :IDONE
:T1 CMP #$07 ; BELL
BNE :T2
JSR BEEP
BRA :IDONE
:T2 CMP #$08 ; Backspace
BNE :T3
JSR NDBSPC
BRA :DONE
:T3 CMP #$09 ; Cursor right
BNE :T4
JSR CURSRT
BRA :DONE
:T4 CMP #$0A ; Linefeed
BNE :T5
LDA ROW
CMP #23
BEQ :SCROLL
INC ROW
:IDONE BRA :DONE
:T5 CMP #$0B ; Cursor up
BNE :T6
LDA ROW
BEQ :DONE
DEC ROW
BRA :DONE
:T6 CMP #$0D ; Carriage return
BNE :T7
JSR CLREOL
STZ COL
BRA :DONE
:T7 CMP #$0C ; Ctrl-L
BNE :T8
JSR CLEAR
BRA :DONE
:T8 CMP #$1E ; Home
BNE :T9
STZ ROW
STZ COL
BRA :DONE
:T9 CMP #$7F ; Delete
BNE :T10
JSR BACKSPC
BRA :DONE
:T10 JSR PRCHRC
LDA COL
CMP #79
BNE :S2
STZ COL
LDA ROW
CMP #23
BEQ :SCROLL
INC ROW
BRA :DONE
:S2 INC COL
BRA :DONE
:SCROLL JSR SCROLL
STZ COL
JSR CLREOL
:DONE RTS
* Scroll whole screen one line
SCROLL LDA #$00
:L1 PHA
JSR SCR1LINE
PLA
INC
CMP #23
BNE :L1
RTS
* Copy line A+1 to line A
SCR1LINE ASL ; Dest addr->ZP1
TAX
LDA SCNTAB,X
STA ZP1
LDA SCNTAB+1,X
STA ZP1+1
INX ; Source addr->ZP2
INX
LDA SCNTAB,X
STA ZP2
LDA SCNTAB+1,X
STA ZP2+1
LDY #$00
:L1 LDA (ZP2),Y
STA (ZP1),Y
STA $C002 ; Read main mem
>>> WRTMAIN
LDA (ZP2),Y
STA (ZP1),Y
STA $C003 ; Read aux mem
>>> WRTAUX
INY
CPY #40
BNE :L1
RTS
* Addresses of screen rows in PAGE2
SCNTAB DW $800,$880,$900,$980,$A00,$A80,$B00,$B80
DW $828,$8A8,$928,$9A8,$A28,$AA8,$B28,$BA8
DW $850,$8D0,$950,$9D0,$A50,$AD0,$B50,$BD0

386
auxmem.bytwrd.s Normal file
View File

@ -0,0 +1,386 @@
* KERNEL/OSWOSB.S
*****************
XC ; 65c02
*************************
* OSBYTE DISPATCH TABLE *
*************************
BYTWRDADDR DW BYTE00 ; OSBYTE 0 - Machine host
* DW BYTE01 ; OSBYTE 1 - User flag
* DW BYTE02 ; OSBYTE 2 - OSRDCH source
* DW BYTE03 ; OSBYTE 3 - OSWRCH dest
* DW BYTE04 ; OSBYTE 4 - Cursor keys
BYTWRDLOW
BYTESZLO EQU BYTWRDLOW-BYTWRDADDR
BYTELOW EQU BYTESZLO/2-1 ; Maximum low OSBYTE
BYTEHIGH EQU $7C ; First high OSBYTE
DW BYTE7C ; OSBYTE 124 - Clear Escape
DW BYTE7D ; OSBYTE 125 - Set Escape
DW BYTE7E ; OSBYTE 126 - Ack. Escape
DW BYTE7F ; OSBYTE 127 - Read EOF
DW BYTE80 ; OSBYTE 128 - ADVAL
DW BYTE81 ; OSBYTE 129 - INKEY
DW BYTE82 ; OSBYTE 130 - Memory high word
DW BYTE83 ; OSBYTE 131 - MEMBOT
DW BYTE84 ; OSBYTE 132 - MEMTOP
DW BYTE85 ; OSBYTE 133 - MEMTOP for MODE
DW BYTE86 ; OSBYTE 134 - POS, VPOS
DW BYTE87 ; OSBYTE 135 - Character, MODE
* DW BYTE88 ; OSBYTE 136 - *CODE
* DW BYTE89 ; OSBYTE 137 - *MOTOR
* DW BYTE8A ; OSBYTE 138 - Buffer insert
* DW BYTE8B ; OSBYTE 139 - *OPT
* DW BYTE8C ; OSBYTE 140 - *TAPE
* DW BYTE8D ; OSBYTE 141 - *ROM
* DW BYTE8E ; OSBYTE 142 - Enter language
* DW BYTE8F ; OSBYTE 143 - Service call
BYTWRDTOP
DW BYTEVAR ; OSBYTE 166+ - Read/Write OSBYTE variable
* Maximum high OSBYTE
BYTESZHI EQU BYTWRDTOP-BYTWRDLOW
BYTEMAX EQU BYTESZHI/2+BYTEHIGH-1
*************************
* OSWORD DISPATCH TABLE *
*************************
OSWBASE DW WORD00 ; OSWORD 0 - Read input line
DW WORD01 ; OSWORD 1 - Read elapsed time
DW WORD02 ; OSWORD 2 - Write eleapsed time
DW WORD03 ; OSWORD 3 - Read interval timer
DW WORD04 ; OSWORD 4 - Write interval timer
DW WORD05 ; OSWORD 5 - Read I/O memory
DW WORD06 ; OSWORD 6 - Write I/O memory
* DW WORD07 ; OSWORD 7 - SOUND
* DW WORD08 ; OSWORD 8 - ENVELOPE
* DW WORD09 ; OSWORD 9 - POINT
* DW WORD0A ; OSWORD 10 - Read character bitmap
* DW WORD0B ; OSWORD 11 - Read palette
* DW WORD0C ; OSWORD 12 - Write palette
* DW WORD0D ; OSWORD 13 - Read coordinates
OSWEND
DW WORDE0 ; OSWORD &E0+ - User OSWORD
* Offset to start of OSWORD table
WORDSZOFF EQU OSWBASE-BYTWRDADDR
WORDOFF EQU WORDSZOFF/2
* Maximum OSWORD
WORDSZ EQU OSWEND-OSWBASE
WORDMAX EQU WORDSZ/2-1
************************
* OSWORD/OSBYTE dispatch
************************
* OSWORD:
* On entry, A=action
* XY=>control block
* On exit, A=preserved
* X,Y,Cy trashed (except OSWORD 0)
* control block updated
*
WORDHND PHA
PHP
SEI
STA OSAREG ; Store registers
STX OSCTRL+0 ; Point to control block
STY OSCTRL+1
LDX #$08 ; X=SERVWORD
CMP #$E0 ; User OSWORD
BCS WORDGO1
CMP #WORDMAX+1
BCS BYTWRDFAIL ; Pass on to service call
ADC #WORDOFF
BCC BYTWRDCALL ; Call OSWORD routine
WORDGO1 LDA #WORDOFF+WORDMAX+1
BCS BYTWRDCALL ; Call User OSWORD routine
* OSBYTE:
* On entry, A=action
* X=first parameter
* Y=second parameter if A>$7F
* On exit, A=preserved
* X=first returned result
* Y=second returned result if A>$7F
* Cy=any returned status if A>$7F
*
BYTEHND PHA
PHP
SEI
STA OSAREG ; Store registers
STX OSXREG
STY OSYREG
LDX #$07 ; X=SERVBYTE
CMP #$A6
BCS BYTEGO1 ; OSBYTE &A6+
CMP #BYTEMAX+1
BCS BYTWRDFAIL ; Pass on to service call
CMP #BYTEHIGH
BCS BYTEGO2 ; High OSBYTEs
CMP #BYTELOW+1
BCS BYTWRDFAIL ; Pass on to service call
STZ OSYREG ; Prepare Y=0 for low OSBYTEs
BCC BYTEGO3
BYTEGO1 LDA #BYTEMAX+1 ; Index for BYTEVAR
BYTEGO2 SBC #BYTEHIGH-BYTELOW-1 ; Reduce OSBYTE number
BYTEGO3 ORA #$80 ; Will become CS=OSBYTE call
BYTWRDCALL ASL A ; Index into dispatch table
TAY ; Y=offset into dispatch table
* BIT FXNETCLAIM ; Check Econet intercept flag
* BPL BYTWRDNONET ; No intercept, skip past
* TXA ; Set A=BYTE or WORD call
* CLV ; Clear V
* JSR CALLNET ; Call Econet with X=call type
* BVS BYTWRDEXIT ; V now set, claimed by NETV
BYTWRDNONET LDA BYTWRDADDR+1,Y ; Get routine address
STA OSINTWS+1
LDA BYTWRDADDR+0,Y
STA OSINTWS+0
LDA OSAREG ; Get A parameter back
LDY OSYREG ; Get Y parameter back
LDX OSXREG ; Get X parameter, set EQ from it
BCS BYTWRDGO ; Skip if OSBYTE call
LDY #$00 ; OSWORD call, enter with Y=0
LDA (OSCTRL),Y ; and A=first byte in control block
SEC ; Enter routine with CS
BYTWRDGO JSR JMPADDR ; Call the routine
* Routines are entered with:
* A=OSBYTE call or first byte of OSWORD control block
* X=X parameter
* Y=OSBYTE Y parameter for A>$7F
* Y=$00 for OSBYTE A<$80
* Y=$00 for OSWORD so (OSCTRL),Y => first byte
* Carry Set
* EQ set from OSBYTE X or from OSWORD first byte
* X,Y,Cy from routine returned to caller
BYTWRDEXIT ROR A ; Move Carry to A
PLP ; Restore original flags
ROL A ; Move Carry back to flags
PLA ; Restore A
CLV ; Clear V = Actioned
RTS
BYTWRDFAIL
* JSR SERVICE ; Offer to sideways ROMs
* LDX OSXREG ; Get returned X
* CMP #$00
* BEQ BYTWRDEXIT ; Claimed, return
JSR UNSUPBYTWRD ; *DEBUG*
LDX #$FF ; X=&FF if unclaimed
PLP ; Restore IRQs
PLA ; Restore A
BIT SETV ; Set V = Not actioned
RTS
SETV ; JMP() is $6C, bit 6 set to set V
* JMPADDR JMP (OSINTWS)
* Merlin doesn't like the above
JMPADDR JMP ($00FA)
* OSWORD &00 - Read a line of input
***********************************
* On entry, (OSCTRL)=>control block
* Y=0, A=(OSCTRL)
* On exit, Y=length of line, offset to <cr>
* CC = Ok, CS = Escape
*
XC ; 65c02
WORD00 IF MAXLEN-OSTEXT-2
LDY #$04
:WORD00LP1 LDA (OSCTRL),Y ; Copy MAXLEN, MINCH, MAXCH to workspace
STA MAXLEN-2,Y
DEY
CPY #$02
BCS :WORD00LP1
:WORD00LP2 LDA (OSCTRL),Y ; (OSTEXT)=>line buffer
STA OSTEXT,Y
DEY
BPL :WORD00LP2
INY ; Initial line length = zero
ELSE
LDA (OSCTRL),Y ; Copy control block
STA OSTEXT,Y ; 0,1 => text
INY ; 2 = MAXLEN
CPY #$05 ; 3 = MINCHAR
BCC WORD00 ; 4 = MAXCHAR
LDY #$00 ; Initial line length = zero
FIN
* STY FXLINES ; Reset line counter
CLI
BEQ :WORD00LP ; Enter main loop
:WORD00BELL LDA #$07 ; $07=BELL
DEY ; Balance next INY
:WORD00NEXT INY ; Step to next character
:WORD00ECHO JSR OSWRCH ; Print character
:WORD00LP JSR OSRDCH
BCS :WORD00ESC ; Escape
* TAX ; Save character in X
* LDA FXVAR03 ; Get FX3 destination
* ROR A
* ROR A ; Move bit 1 into Carry
* TXA ; Get character back
* BCS :WORD00TEST ; VDU disabled, ignore
* LDX FXVDUQLEN ; Get length of VDU queue
* BNE :WORD00ECHO ; Not zero, just print
:WORD00TEST CMP #$7F ; Delete
BNE :WORD00CHAR
CPY #$00
BEQ :WORD00LP ; Nothing to delete
DEY ; Back up one character
BCS :WORD00ECHO ; Loop back to print DEL
:WORD00CHAR CMP #$15 ; Ctrl-U
BNE :WORD00INS ; No, insert character
LDA #$7F ; Delete character
INY ; Balance first DEY
:WORD00ALL DEY ; Back up one character
BEQ :WORD00LP ; Beginning of line
JSR OSWRCH ; Print DELETE
JMP :WORD00ALL ; Loop to delete all
:WORD00INS STA (OSTEXT),Y ; Store the character
CMP #$0D
BEQ :WORD00CR ; CR - Done
CPY MAXLEN
BCS :WORD00BELL ; Too long, beep
CMP MINCHAR
BCC :WORD00ECHO ; <MINCHAR, don't step to next
CMP MAXCHAR
BCC :WORD00NEXT ; <MAXCHAR, step to next
BEQ :WORD00NEXT ; =MAXCHAR, step to next
BCS :WORD00ECHO ; >MAXCHAR, don't step to next
:WORD00CR JSR OSNEWL
* JSR CALLNET ; Call Econet Vector, A=13
:WORD00ESC LDA ESCFLAG ; Get Escape flag
ROL A ; Carry=Escape state
RTS
* OSWORD &01 - Read elapsed time
* OSWORD &02 - Write elapsed time
* OSWORD &03 - Read countdown timer
* OSWORD &04 - Write countdown timer
************************************
* On entry, (OSCTRL)=>control block
* Y=0
WORD01 TYA ; Dummy, just return zero
:WORD01LP STA (OSCTRL),Y
INY
CPY #$05
BCC :WORD01LP
WORD04
WORD03
WORD02 RTS ; Dummy, do nothing
* OSWORD &05 - Read I/O memory
* OSWORD &06 - Write I/O memory
***********************************
* On entry, (OSCTRL)+0 address
* (OSCTRL)+4 byte read or written
* Y=0, A=(OSCTRL)
XC ; 65c02
WORD05 JSR GETADDR ; Point to address, set X and Y
* needs to switch to main memory
LDA (OSINTWS) ; Get byte
* needs to switch back
STA (OSCTRL),Y ; Store it
RTS
WORD06 JSR GETADDR ; Point to address, set X and Y
LDA (OSCTRL),Y ; Get byte
* needs to switch to main memory
STA (OSINTWS) ; Store it
* needs to switch back
RTS
GETADDR STA OSINTWS+0 ; (OSINTWS)=>byte to read/write
INY
LDA (OSCTRL),Y
STA OSINTWS+1
LDY #$04 ; Point Y to data byte
RTS
* KERNEL/BWMISC.S
*****************
* Here until tidied
BYTE00 LDX #$0A ; $00 = identify Host
RTS
BYTE7C LDA ESCFLAG ; $7C = clear escape condition
AND #$7F ; Clear MSbit
STA ESCFLAG
RTS
BYTE7D ROR ESCFLAG ; $7D = set escape condition
RTS
BYTE7E LDA ESCFLAG ; $7E = ack detection of ESC
AND #$7F ; Clear MSB
STA ESCFLAG
LDX #$FF ; Means ESC condition cleared
RTS
BYTE7F PHY ; $7F = check for EOF
JSR CHKEOF
PLY
RTS
BYTE82 LDY #$00 ; $82 = read high order address
LDX #$00 ; $0000 for language processor
RTS
BYTE83 LDY #$0E ; $83 = read bottom of user mem
LDX #$00 ; $0E00
RTS
BYTE84 LDY #$80 ; $84 = read top of user mem
LDX #$00
RTS
BYTE85 LDY #$80 ; $85 = top user mem for mode
LDX #$00
RTS
BYTE8B LDA #$00 ; $8B = *OPT
JMP (FSCV) ; Hand over to filing system
BYTEDA RTS ; $DA = clear VDU queue
BYTEEA LDX #$00 ; No tube
RTS ; $EA = Tube presence
UNSUPBYTWRD
LDA #<OSBYTEM
LDY #>OSBYTEM
CPX #7
BEQ UNSUPGO
LDA #<OSWORDM
LDY #>OSWORDM
UNSUPGO JSR PRSTR
LDA OSAREG
JSR OUTHEX
LDA #<OSBM2
LDY #>OSBM2
JMP PRSTR
OSBYTEM ASC 'OSBYTE($'
DB $00
OSWORDM ASC 'OSWORD($'
DB $00
OSBM2 ASC ').'
DB $00
BYTEVAR LDX #$00
LDY #$00
WORDE0 RTS

View File

@ -2,6 +2,11 @@
* Kernel / Misc * Kernel / Misc
********************************************************* *********************************************************
* KERNEL/CHARIO.S
*****************
* Character read and write
*
* OSWRCH handler * OSWRCH handler
* All registers preserved * All registers preserved
WRCHHND PHA WRCHHND PHA
@ -17,7 +22,7 @@ WRCHHND PHA
RTS RTS
* OSRDCH handler * OSRDCH handler
* All registers preserved except A, carry * All registers preserved except A, Carry
* Read a character from the keyboard * Read a character from the keyboard
RDCHHND PHX RDCHHND PHX
PHY PHY
@ -28,6 +33,7 @@ RDCHHND PHX
BNE :S1 BNE :S1
LDA CURS LDA CURS
BNE :S1 BNE :S1
STZ CURS STZ CURS
STZ CURS+1 STZ CURS+1
LDA CSTATE LDA CSTATE
@ -62,26 +68,11 @@ CURS DW $0000 ; Counter
CSTATE DB $00 ; Cursor on or off CSTATE DB $00 ; Cursor on or off
OLDCHAR DB $00 ; Char under cursor OLDCHAR DB $00 ; Char under cursor
* Performs OSBYTE $80 function
* Read ADC channel or get buffer status BYTE81 JSR GETKEY ; $81 = Read key with time lim
OSBYTE80 CPX #$00 ; X=0 Last ADC channel
BNE :S1
LDX #$00 ; Fire button
LDY #$00 ; ADC never converted
RTS
:S1 BMI :S2
LDX #$00 ; X +ve, ADC value
LDY #$00
RTS
:S2 CPX #$FF ; X $FF = keyboard buf
BEQ :INPUT
CPX #$FE ; X $FE = RS423 i/p buf
BEQ :INPUT
LDX #$FF ; Spaced remaining in o/p
RTS
:INPUT LDX #$00 ; Nothing in input buf
RTS RTS
* Performs OSBYTE $81 INKEY$ function * Performs OSBYTE $81 INKEY$ function
* X,Y has time limit * X,Y has time limit
* On exit, CC, Y=$00, X=key - key pressed * On exit, CC, Y=$00, X=key - key pressed
@ -125,75 +116,68 @@ NEGKEY LDX #$00 ; Unimplemented
LDY #$00 LDY #$00
RTS RTS
*********************************************************** * KERNEL/KEYBOARD.S
* Helper functions *******************
***********************************************************
* Beep KBDREAD
BEEP PHA KEYPRESS LDA $C000
PHX TAY
LDX #$80 CMP #$80
:L1 LDA $C030 BCC KEYNONE ; No key pressed
JSR DELAY AND #$7F
INX STA $C010 ; Ack. keypress
BNE :L1 BIT $C061
PLX BMI KEYLALT ; Left Apple pressed
PLA BIT $C062
BMI KEYRALT ; Right Apple pressed
CMP #$09
BEQ KEYTAB
CMP #$08
BCC KEYOK ; <$08 not cursor key
CMP #$0C
BCC KEYCURSR
CMP #$15
BEQ KEYCUR15
KEYOK SEC ; SEC=Ok
KEYNONE RTS
KEYTAB LDA #$C9
; If cursors active, COPY
; else TAB
SEC
RTS RTS
* Delay approx 1/100 sec KEYRALT ; Right Apple key pressed
DELAY PHX KEYLALT CMP #$40 ; Left Apple key pressed
PHY BCS KEYCTRL
LDX #$00 CMP #$30
:L1 INX ; 2 BCC KEYOK ; <'0'
LDY #$00 ; 2 CMP #$3A
:L2 INY ; 2 BCS KEYOK ; >'9'
CPY #$00 ; 2 KEYFUNC AND #$0F ; Convert Apple-Num to function key
BNE :L2 ; 3 (taken) ORA #$80
CPX #$02 ; 2 BIT $C062
BNE :L1 ; 3 (taken) BPL KEYFUNOK ; Left+Digit -> $8x
PLY ORA #$90 ; Right+Digit -> $9x
PLX BIT $C061
BPL KEYFUNOK
EOR #$30 ; Left+Right+Digit -> $Ax
KEYFUNOK SEC
RTS
KEYCTRL AND #$1F ; Apple-Letter -> Ctrl-Letter
RTS RTS
* Print string pointed to by X,Y to the screen KEYCUR15
OUTSTR TXA * BIT $C062
* BPL KEYCUR16 ; Right Apple not pressed
* Print string pointed to by A,Y to the screen * LDA #$C9 ; Solid+Right -> COPY?
PRSTR STA OSTEXT+0 ; String in A,Y * SEC
STY OSTEXT+1 * RTS
:L1 LDA (OSTEXT) ; Ptr to string in OSTEXT KEYCUR16 LDA #$09 ; Convert RGT to $09
BEQ :S1 KEYCURSR AND #$03
JSR OSASCI ORA #$CC ; Cursor keys $CC-$CF
INC OSTEXT SEC ; SEC=Ok
BNE :L1
INC OSTEXT+1
BRA :L1
:S1 RTS
* Print XY in hex
OUT2HEX TYA
JSR OUTHEX
TAX ; Continue into OUTHEX
* Print hex byte in A
OUTHEX PHA
LSR
LSR
LSR
LSR
AND #$0F
JSR PRNIB
PLA
AND #$0F ; Continue into PRNIB
* Print hex nibble in A
PRNIB CMP #$0A
BCC :S1
CLC ; >= $0A
ADC #'A'-$0A
JSR OSWRCH
RTS RTS
:S1 ADC #'0' ; < $0A
JMP OSWRCH

439
auxmem.hostfs.s Normal file
View File

@ -0,0 +1,439 @@
* FILESYS.S
*********************************************************
* AppleMOS Host File System
*********************************************************
* OSFIND - open/close a file for byte access
FINDHND PHX
PHY
PHA
STX ZP1 ; Points to filename
STY ZP1+1
CMP #$00 ; A=$00 = close
BEQ :CLOSE
PHA
LDA #<MOSFILE+1
STA ZP2
LDA #>MOSFILE+1
STA ZP2+1
LDY #$00
:L1 LDA (ZP1),Y
>>> WRTMAIN
STA (ZP2),Y
>>> WRTAUX
INY
CMP #$0D ; Carriage return
BNE :L1
DEY
>>> WRTMAIN
STY MOSFILE ; Length (Pascal string)
>>> WRTAUX
PLA ; Recover options
>>> XF2MAIN,OFILE
:CLOSE >>> WRTMAIN
STY MOSFILE ; Write file number
>>> WRTAUX
>>> XF2MAIN,CFILE
OSFINDRET
>>> ENTAUX
PLY ; Value of A on entry
CPY #$00 ; Was it close?
BNE :S1
TYA ; Preserve A for close
:S1 PLY
PLX
RTS
* OSGBPB - Get/Put a block of bytes to/from an open file
GBPBHND LDA #<OSGBPBM
LDY #>OSGBPBM
JMP PRSTR
OSGBPBM ASC 'OSGBPB.'
DB $00
* OSBPUT - write one byte to an open file
BPUTHND PHX
PHY
PHA ; Stash char to write
>>> WRTMAIN
STY MOSFILE ; File reference number
>>> WRTAUX
>>> XF2MAIN,FILEPUT
OSBPUTRET
>>> ENTAUX
CLC ; Means no error
PLA
PLY
PLX
RTS
* OSBGET - read one byte from an open file
BGETHND PHX
PHY
>>> WRTMAIN
STY MOSFILE ; File ref number
>>> WRTAUX
>>> XF2MAIN,FILEGET
OSBGETRET
>>> ENTAUX
CLC ; Means no error
CPY #$00 ; Check error status
BEQ :NOERR
SEC ; Set carry for error
BRA :EXIT
:NOERR CLC
:EXIT PLY
PLX
RTS
* OSARGS - adjust file arguments
* On entry, A=action
* X=>4 byte ZP control block
* Y=file handle
ARGSHND PHA
PHX
PHY
CPY #$00
BNE :HASFILE
CMP #$00 ; Y=0,A=0 => current file sys
BNE :S1
PLY
PLX
PLA
LDA #105 ; 105=AppleFS filing system
RTS
:S1 CMP #$01 ; Y=0,A=1 => addr of CLI
BNE :S2
* TODO: Implement this for *RUN and *command
JSR BEEP
BRA :IEXIT
:S2 CMP #$FF ; Y=0,A=FF => flush all files
BNE :IEXIT
>>> WRTMAIN
STZ MOSFILE ; Zero means flush all
>>> WRTAUX
BRA :IFLUSH
:HASFILE >>> WRTMAIN
STY MOSFILE ; File ref num
STX MOSFILE+1 ; Pointer to ZP control block
>>> WRTAUX
CMP #$00 ; Y!=0,A=0 => read seq ptr
BNE :S3
>>> WRTMAIN
STZ MOSFILE+2 ; 0 means get pos
>>> WRTAUX
>>> XF2MAIN,TELL
:IEXIT BRA :IEXIT2
:IFLUSH BRA :FLUSH
:S3 CMP #$01 ; Y!=0,A=1 => write seq ptr
BNE :S4
>>> WRTMAIN
LDA $00,X
STA MOSFILE+2
LDA $01,X
STA MOSFILE+3
LDA $02,X
STA MOSFILE+4
>>> WRTAUX
>>> XF2MAIN,SEEK
:IEXIT2 BRA :EXIT
:S4 CMP #$02 ; Y!=0,A=2 => read file len
BNE :S5
>>> WRTMAIN
STA MOSFILE+2 ; Non-zero means get len
>>> WRTAUX
>>> XF2MAIN,TELL
:S5 CMP #$FF ; Y!=0,A=FF => flush file
BNE :EXIT
:FLUSH >>> XF2MAIN,FLUSH
:EXIT PLY
PLX
PLA
RTS
OSARGSRET
>>> ENTAUX
PLY
PLX
PLA
RTS
* OSFILE - perform actions on entire files
* On entry, A=action
* XY=>control block
* On exit, A=preserved if unimplemented
* A=0 object not found (not load/save)
* A=1 file found
* A=2 directory found
* XY preserved
* control block updated
FILEHND PHX
PHY
PHA
STX ZP1 ; LSB of parameter block
STY ZP1+1 ; MSB of parameter block
LDA #<FILEBLK
STA ZP2
LDA #>FILEBLK
STA ZP2+1
LDY #$00 ; Copy to FILEBLK in main mem
:L1 LDA (ZP1),Y
>>> WRTMAIN
STA (ZP2),Y
>>> WRTAUX
INY
CPY #$12
BNE :L1
LDA (ZP1) ; Pointer to filename->ZP2
STA ZP2
LDY #$01
LDA (ZP1),Y
STA ZP2+1
LDA #<MOSFILE+1 ; ZP1 is dest pointer
STA ZP1
LDA #>MOSFILE+1
STA ZP1+1
LDA (ZP2) ; Look at first char of filename
CMP #'9'+1
BCS :NOTDIGT
CMP #'0'
BCC :NOTDIGT
LDA #'N' ; Prefix numeric with 'N'
>>> WRTMAIN
STA (ZP1)
>>> WRTAUX
LDY #$01 ; Increment Y
DEC ZP2 ; Decrement source pointer
LDA ZP2
CMP #$FF
BNE :L2
DEC ZP2+1
BRA :L2
:NOTDIGT LDY #$00
:L2 LDA (ZP2),Y
>>> WRTMAIN
STA (ZP1),Y
>>> WRTAUX
INY
CMP #$21 ; Space or Carriage return
BCS :L2
DEY
>>> WRTMAIN
STY MOSFILE ; Length (Pascal string)
>>> WRTAUX
PLA ; Get action back
PHA
BEQ :S1 ; A=00 -> SAVE
CMP #$FF
BEQ :S2 ; A=FF -> LOAD
LDA #<OSFILEM ; If not implemented, print msg
LDY #>OSFILEM
JSR PRSTR
PLA
PHA
JSR OUTHEX
LDA #<OSFILEM2
LDY #>OSFILEM2
JSR PRSTR
PLA ; Not implemented, return unchanged
PLY
PLX
RTS
:S1 >>> XF2MAIN,SAVEFILE
:S2 >>> XF2MAIN,LOADFILE
OSFILERET
>>> ENTAUX
PLY ; Value of A on entry
CPY #$FF ; LOAD
BNE :S4 ; Deal with return from SAVE
CMP #$01 ; No file found
BNE :SL1
BRK
DB $D6 ; $D6 = Object not found
ASC 'File not found'
BRK
:SL1 CMP #$02 ; Read error
BNE :SL2
BRK
DB $CA ; $CA = Premature end, 'Data lost'
ASC 'Read error'
BRK
:SL2 LDA #$01 ; Return code - file found
BRA :EXIT
:S4 CPY #$00 ; Return from SAVE
BNE :S6
CMP #$01 ; Unable to create or open
BNE :SS1
BRK
DB $C0 ; $C0 = Can't create file to save
ASC 'Can'
DB $27
ASC 't save file'
BRK
:SS1 CMP #$02 ; Unable to write
BNE :S6
BRK
DB $CA ; $CA = Premature end, 'Data lost'
ASC 'Write error'
BRK
:S6 LDA #$00
:EXIT PLY
PLX
RTS
OSFILEM ASC 'OSFILE($'
DB $00
OSFILEM2 ASC ')'
DB $00
* OSFSC - miscellanous file system calls
*****************************************
* On entry, A=action, XY=>command line
* or A=action, X=param1, Y=param2
* On exit, A=preserved if unimplemented
* A=modified if implemented
* X,Y=any return values
*
FSCHND CMP #$01
BEQ CHKEOF ; A=0 - Read EOF
CMP #$02
BEQ FSCRUN ; A=2 - */filename
CMP #$04
BEQ FSCRUN ; A=4 - *RUN
CMP #$05
BEQ FSCCAT ; A=5 - *CAT
CMP #$09
BEQ FSCCAT ; A=9 - *EX
CMP #$0A
BEQ FSCCAT ; A=10 - *INFO
CMP #$0C
BEQ FSCREN ; A=12 - *RENAME
FSCRUN
FSCREN
LDA #<OSFSCM
LDY #>OSFSCM
JSR PRSTR
RTS
OSFSCM ASC 'OSFSC.'
DB $00
* Performs OSBYTE $7F EOF function
* File ref number is in X
CHKEOF >>> WRTMAIN
STX MOSFILE ; File reference number
>>> WRTAUX
>>> XF2MAIN,FILEEOF
CHKEOFRET
>>> ENTAUX
TAX ; Return code -> X
RTS
* Perform CAT
* A=5 *CAT, A=9 *EX, A=10 *INFO
FSCCAT >>> XF2MAIN,CATALOG
STARCATRET
>>> ENTAUX
JMP OSNEWL
RTS
* Print one block of a catalog. Called by CATALOG
* Block is in AUXBLK
PRONEBLK >>> ENTAUX
LDA AUXBLK+4 ; Get storage type
AND #$E0 ; Mask 3 MSBs
CMP #$E0
BNE :NOTKEY ; Not a key block
LDA #<:DIRM
LDY #>:DIRM
JSR PRSTR
SEC
:NOTKEY LDA #$00
:L1 PHA
PHP
JSR PRONEENT
PLP
BCC :L1X
JSR OSNEWL
:L1X PLA
INC
CMP #13 ; Number of dirents in block
CLC
BNE :L1
>>> XF2MAIN,CATALOGRET
:DIRM ASC 'Directory: '
DB $00
* Print a single directory entry
* On entry: A = dirent index in AUXBLK
PRONEENT TAX
LDA #<AUXBLK+4 ; Skip pointers
STA ZP3
LDA #>AUXBLK+4
STA ZP3+1
:L1 CPX #$00
BEQ :S1
CLC
LDA #$27 ; Size of dirent
ADC ZP3
STA ZP3
LDA #$00
ADC ZP3+1
STA ZP3+1
DEX
BRA :L1
:S1 LDY #$00
LDA (ZP3),Y
BEQ :EXIT ; Inactive entry
AND #$0F ; Len of filename
TAX
LDY #$01
:L2 CPX #$00
BEQ :S2
LDA (ZP3),Y
JSR OSWRCH
DEX
INY
BRA :L2
:S2 LDA #$20
JSR OSWRCH
INY
CPY #$15
BNE :S2
:EXIT RTS
* Handle *DIR (directory change) command
* On entry, ZP1 points to command line
STARDIR JSR EATSPC ; Eat leading spaces
BCC :S1 ; If no space found
RTS ; No argument
:S1 LDX #$01
:L3 LDA (ZP1),Y
CMP #$0D
BEQ :S3
>>> WRTMAIN
STA MOSFILE,X
>>> WRTAUX
INY
INX
BRA :L3
:S3 DEX
>>> WRTMAIN
STX MOSFILE ; Length byte
>>> WRTAUX
>>> XF2MAIN,SETPFX
STARDIRRET
>>> ENTAUX
RTS

View File

@ -13,7 +13,6 @@ COL EQU $97 ; Cursor column
STRTBCKL EQU $9D STRTBCKL EQU $9D
STRTBCKH EQU $9E STRTBCKH EQU $9E
WARMSTRT EQU $9F ; Cold or warm start WARMSTRT EQU $9F ; Cold or warm start
MAGIC EQU $BC ; Arbitrary value MAGIC EQU $BC ; Arbitrary value
MOSSHIM MOSSHIM
@ -95,22 +94,30 @@ MOSINIT STA $C005 ; Make sure we are writing aux
INC A4H INC A4H
:S7 BRA :L2 :S7 BRA :L2
:NORELOC :NORELOC ; We should jump up into high memory here
:S8 STA $C00D ; 80 col on :S8 STA $C00D ; 80 col on
STA $C003 ; Alt charset off STA $C003 ; Alt charset off
STA $C055 ; PAGE2 STA $C055 ; PAGE2
STZ ROW LDY WARMSTRT ; Don't lose this
STZ COL LDX #$FF
JSR CLEAR TXS ; Initialise stack
INX ; X=$00
TXA
:SCLR STA $0000,X ; Clear Kernel memory
STA $0200,X
STA $0300,X
INX
BNE :SCLR
STZ ESCFLAG LDX #ENDVEC-DEFVEC-1
:INITPG2 LDA DEFVEC,X ; Set up vectors
LDX #$35
:INITPG2 LDA DEFVEC,X
STA $200,X STA $200,X
DEX DEX
BPL :INITPG2 BPL :INITPG2
STY WARMSTRT ; Put it back
JSR CLEAR ; Initialise VDU driver
LDA #<:HELLO LDA #<:HELLO
LDY #>:HELLO LDY #>:HELLO
@ -141,3 +148,5 @@ MOSINIT STA $C005 ; Make sure we are writing aux
:OLDM ASC '(Use OLD to recover any program)' :OLDM ASC '(Use OLD to recover any program)'
DB $0D,$0D,$00 DB $0D,$0D,$00

View File

@ -2,36 +2,61 @@
* AppleMOS Kernel * AppleMOS Kernel
********************************************************* *********************************************************
BYTE8E PHP ; Save CLC=reset, SEC=not reset * KERNEL/SWROM.S
LDA #$09 ; $8E = enter language ROM ****************
LDY #$80 ; Print lang name at $8009
JSR PRSTR * OSBYTE $8E - Enter language ROM
*
BYTE8E PHP ; Save CLC=RESET, SEC=Not RESET
LDA #$08
STA FAULT+0
LDA #$80
STA FAULT+1
JSR PRERR ; Print ROM name with PRERR to set FAULT
JSR OSNEWL JSR OSNEWL
JSR OSNEWL JSR OSNEWL
PLP ; Get entry type back PLP ; Get entry type back
LDA #$01 LDA #$01
JMP AUXADDR JMP AUXADDR
SERVICE RTS
* OSBYTE $8F - Issue service call
* X=service call, Y=parameter
*
BYTE8F TXA
SERVICE LDX #$0F
BIT $8006
BPL :SERVSKIP ; No service entry
JSR $8003 ; Call service entry
TAX
BEQ :SERVDONE
:SERVSKIP LDX #$FF
:SERVDONE RTS
* KERNEL/OSCLI.S
****************
* OSCLI HANDLER * OSCLI HANDLER
* On entry, XY=>command string * On entry, XY=>command string
* TO DO: line pointer in XY should be in LPTR
*
CLIHND PHX CLIHND PHX
PHY PHY
STX ZP1+0 ; Pointer to CLI STX ZP1+0 ; Pointer to CLI
STY ZP1+1 STY ZP1+1
:L1 LDA (ZP1) :L1 LDA (ZP1)
CMP #'*' ; Trim any leading stars CMP #'*' ; Trim any leading stars
BEQ :NEXT BEQ :NEXT
CMP #' ' ; Trim any leading spaces CMP #' ' ; Trim any leading spaces
BEQ :NEXT BEQ :NEXT
BRA :TRIMMED BRA :TRIMMED
:NEXT INC ZP1 :NEXT INC ZP1
BNE :L1 BNE :L1
INC ZP1+1 INC ZP1+1
BRA :L1 BRA :L1
:TRIMMED CMP #'|' ; | is comment :TRIMMED CMP #'|' ; | is comment
BEQ :IEXIT BEQ :IEXIT
CMP #$0D ; Carriage return CMP #$0D ; Carriage return
BEQ :IEXIT BEQ :IEXIT
LDA #<:QUIT LDA #<:QUIT
STA ZP2 STA ZP2
@ -97,18 +122,22 @@ CLIHND PHX
BCS :ASKROM BCS :ASKROM
JSR STARHELP JSR STARHELP
BRA :EXIT BRA :EXIT
:ASKROM LDA $8006 ; Check service entry :ASKROM LDA $8006 ; Check for service entry
BPL :UNSUPP ; Only BASIC has no srvc entry BPL :UNSUPP ; No service entry
LDA ZP1 ; String in (OSLPTR),Y * LDA $8003 ; Check for service entry
* CMP #$4C ; Not a JMP?
* BNE :UNSUPP ; Only BASIC has no srvc entry
LDA ZP1 ; String in (OSLPTR),Y
STA OSLPTR STA OSLPTR
LDA ZP1+1 LDA ZP1+1
STA OSLPTR+1 STA OSLPTR+1
LDY #$00 LDY #$00
LDA #$04 ; Service 4 Unrecognized Cmd LDA #$04 ; Service 4 Unrecognized Cmd
LDX #$0F ; ROM slot LDX #$0F ; ROM slot
JSR $8003 ; Service entry point JSR $8003 ; Service entry point
TAX ; Check ret val TAX ; Check return
BEQ :EXIT ; Call claimed BEQ :EXIT ; Call claimed
:UNSUPP LDA #<:OSCLIM :UNSUPP LDA #<:OSCLIM
LDY #>:OSCLIM LDY #>:OSCLIM
JSR PRSTR JSR PRSTR
@ -122,7 +151,7 @@ CLIHND PHX
BEQ :PS1 BEQ :PS1
CMP #$00 CMP #$00
BEQ :PS1 BEQ :PS1
JSR $FFEE ; OSWRCH JSR OSWRCH
INY INY
BRA :PL1 BRA :PL1
:PS1 LDA #<:OSCLIM2 :PS1 LDA #<:OSCLIM2
@ -181,7 +210,7 @@ STRCMP LDY #$00
STARHELP LDA #<:MSG STARHELP LDA #<:MSG
LDY #>:MSG LDY #>:MSG
JSR PRSTR JSR PRSTR
LDA #$09 ; Language name LDA #$09 ; Language name
LDY #$80 LDY #$80
JSR PRSTR JSR PRSTR
LDA #<:MSG2 LDA #<:MSG2
@ -197,80 +226,22 @@ STARHELP LDA #<:MSG
STARQUIT >>> XF2MAIN,QUIT STARQUIT >>> XF2MAIN,QUIT
* Handle *CAT / *. command (list directory) * Handle *CAT / *. command (list directory)
STARCAT >>> XF2MAIN,CATALOG STARCAT JMP FSCCAT
STARCATRET
>>> ENTAUX
RTS
* Print one block of a catalog. Called by CATALOG
* Block is in AUXBLK
PRONEBLK >>> ENTAUX
LDA AUXBLK+4 ; Get storage type
AND #$E0 ; Mask 3 MSBs
CMP #$E0
BNE :NOTKEY ; Not a key block
LDA #<:DIRM
LDY #>:DIRM
JSR PRSTR
:NOTKEY LDA #$00
:L1 PHA
JSR PRONEENT
PLA
INC
CMP #13 ; Number of dirents in block
BNE :L1
>>> XF2MAIN,CATALOGRET
:DIRM ASC 'Directory: '
DB $00
* Print a single directory entry
* On entry: A = dirent index in AUXBLK
PRONEENT TAX
LDA #<AUXBLK+4 ; Skip pointers
STA ZP3
LDA #>AUXBLK+4
STA ZP3+1
:L1 CPX #$00
BEQ :S1
CLC
LDA #$27 ; Size of dirent
ADC ZP3
STA ZP3
LDA #$00
ADC ZP3+1
STA ZP3+1
DEX
BRA :L1
:S1 LDY #$00
LDA (ZP3),Y
BEQ :EXIT ; Inactive entry
AND #$0F ; Len of filename
TAX
LDY #$01
:L2 CPX #$00
BEQ :S2
LDA (ZP3),Y
JSR OSWRCH
DEX
INY
BRA :L2
:S2 JSR OSNEWL
:EXIT RTS
* Consume spaces in command line. Treat " as space! * Consume spaces in command line. Treat " as space!
* Return C set if no space found, C clear otherwise * Return C set if no space found, C clear otherwise
* Command line pointer in (ZP1),Y * Command line pointer in (ZP1),Y
EATSPC LDA (ZP1),Y ; Check first char is ... EATSPC LDA (ZP1),Y ; Check first char is ...
CMP #' ' ; ... space CMP #' ' ; ... space
BEQ :START BEQ :START
CMP #'"' ; Or quote mark CMP #'"' ; Or quote mark
BEQ :START BEQ :START
BRA :NOTFND BRA :NOTFND
:START INY :START INY
:L1 LDA (ZP1),Y ; Eat any additional ... :L1 LDA (ZP1),Y ; Eat any additional ...
CMP #' ' ; ... spaces CMP #' ' ; ... spaces
BEQ :CONT BEQ :CONT
CMP #'"' ; Or quote marks CMP #'"' ; Or quote marks
BNE :DONE BNE :DONE
:CONT INY :CONT INY
BRA :L1 BRA :L1
@ -287,7 +258,7 @@ EATWORD LDA (ZP1),Y
BEQ :SPC BEQ :SPC
CMP #'"' CMP #'"'
BEQ :SPC BEQ :SPC
CMP #$0D ; Carriage return CMP #$0D ; Carriage return
BEQ :EOL BEQ :EOL
INY INY
BRA EATWORD BRA EATWORD
@ -296,30 +267,6 @@ EATWORD LDA (ZP1),Y
:EOL SEC :EOL SEC
RTS RTS
* Handle *DIR (directory change) command
* On entry, ZP1 points to command line
STARDIR JSR EATSPC ; Eat leading spaces
BCC :S1 ; If no space found
RTS ; No argument
:S1 LDX #$01
:L3 LDA (ZP1),Y
CMP #$0D
BEQ :S3
>>> WRTMAIN
STA MOSFILE,X
>>> WRTAUX
INY
INX
BRA :L3
:S3 DEX
>>> WRTMAIN
STX MOSFILE ; Length byte
>>> WRTAUX
>>> XF2MAIN,SETPFX
STARDIRRET
>>> ENTAUX
RTS
* Add Y to ZP1 pointer. Clear Y. * Add Y to ZP1 pointer. Clear Y.
ADDZP1Y CLC ADDZP1Y CLC
TYA TYA
@ -334,18 +281,18 @@ ADDZP1Y CLC
* Decode ASCII hex digit in A * Decode ASCII hex digit in A
* Returns with carry set if bad char, C clear otherwise * Returns with carry set if bad char, C clear otherwise
HEXDIGIT CMP #'F'+1 HEXDIGIT CMP #'F'+1
BCS :BADCHAR ; char > 'F' BCS :BADCHAR ; char > 'F'
CMP #'A' CMP #'A'
BCC :S1 BCC :S1
SEC ; 'A' <= char <= 'F' SEC ; 'A' <= char <= 'F'
SBC #'A'-10 SBC #'A'-10
CLC CLC
RTS RTS
:S1 CMP #'9'+1 :S1 CMP #'9'+1
BCS :BADCHAR ; '9' < char < 'A' BCS :BADCHAR ; '9' < char < 'A'
CMP #'0' CMP #'0'
BCC :BADCHAR ; char < '0' BCC :BADCHAR ; char < '0'
SEC ; '0' <= char <= '9' SEC ; '0' <= char <= '9'
SBC #'0' SBC #'0'
CLC CLC
RTS RTS
@ -355,24 +302,24 @@ HEXDIGIT CMP #'F'+1
* Decode hex constant on command line * Decode hex constant on command line
* On entry, ZP1 points to command line * On entry, ZP1 points to command line
HEXCONST LDX #$00 HEXCONST LDX #$00
:L1 STZ :BUF,X ; Clear :BUF :L1 STZ :BUF,X ; Clear :BUF
INX INX
CPX #$04 CPX #$04
BNE :L1 BNE :L1
LDX #$00 LDX #$00
LDY #$00 LDY #$00
:L2 LDA (ZP1),Y ; Parse hex digits into :L2 LDA (ZP1),Y ; Parse hex digits into
JSR HEXDIGIT ; :BUF, left aligned JSR HEXDIGIT ; :BUF, left aligned
BCS :NOTHEX BCS :NOTHEX
STA :BUF,X STA :BUF,X
INY INY
INX INX
CPX #$04 CPX #$04
BNE :L2 BNE :L2
LDA (ZP1),Y ; Peek at next char LDA (ZP1),Y ; Peek at next char
:NOTHEX CPX #$00 ; Was it the first digit? :NOTHEX CPX #$00 ; Was it the first digit?
BEQ :ERR ; If so, bad hex constant BEQ :ERR ; If so, bad hex constant
CMP #' ' ; If whitespace, then okay CMP #' ' ; If whitespace, then okay
BEQ :OK BEQ :OK
CMP #$0D CMP #$0D
BEQ :OK BEQ :OK
@ -397,38 +344,38 @@ HEXCONST LDX #$00
:ZEROPAD DB $00,$00,$00 :ZEROPAD DB $00,$00,$00
:BUF DB $00,$00,$00,$00 :BUF DB $00,$00,$00,$00
ADDRBUF DW $0000 ; Used by HEXCONST ADDRBUF DW $0000 ; Used by HEXCONST
* Handle *LOAD command * Handle *LOAD command
* On entry, ZP1 points to command line * On entry, ZP1 points to command line
STARLOAD JSR CLRCB STARLOAD JSR CLRCB
JSR EATSPC ; Eat leading spaces JSR EATSPC ; Eat leading spaces
BCS :ERR BCS :ERR
JSR ADDZP1Y ; Advance ZP1 JSR ADDZP1Y ; Advance ZP1
LDA ZP1 ; Pointer to filename LDA ZP1 ; Pointer to filename
STA OSFILECB STA OSFILECB
LDA ZP1+1 LDA ZP1+1
STA OSFILECB+1 STA OSFILECB+1
JSR EATWORD ; Advance past filename JSR EATWORD ; Advance past filename
BCS :NOADDR ; No load address given BCS :NOADDR ; No load address given
LDA #$0D ; Carriage return LDA #$0D ; Carriage return
STA (ZP1),Y ; Terminate filename STA (ZP1),Y ; Terminate filename
INY INY
JSR EATSPC ; Eat any whitespace JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1 JSR ADDZP1Y ; Update ZP1
JSR HEXCONST JSR HEXCONST
BCS :ERR ; Bad hex constant BCS :ERR ; Bad hex constant
LDA ADDRBUF LDA ADDRBUF
STA OSFILECB+2 ; Load address LSB STA OSFILECB+2 ; Load address LSB
LDA ADDRBUF+1 LDA ADDRBUF+1
STA OSFILECB+3 ; Load address MSB STA OSFILECB+3 ; Load address MSB
:OSFILE LDX #<OSFILECB :OSFILE LDX #<OSFILECB
LDY #>OSFILECB LDY #>OSFILECB
LDA #$FF ; OSFILE load flag LDA #$FF ; OSFILE load flag
JSR OSFILE JSR OSFILE
:END RTS :END RTS
:NOADDR LDA #$FF ; Set OSFILECB+6 to non-zero :NOADDR LDA #$FF ; Set OSFILECB+6 to non-zero
STA OSFILECB+6 ; Means use the file's addr STA OSFILECB+6 ; Means use the file's addr
BRA :OSFILE BRA :OSFILE
:ERR JSR BEEP :ERR JSR BEEP
RTS RTS
@ -436,37 +383,37 @@ STARLOAD JSR CLRCB
* Handle *SAVE command * Handle *SAVE command
* On entry, ZP1 points to command line * On entry, ZP1 points to command line
STARSAVE JSR CLRCB STARSAVE JSR CLRCB
JSR EATSPC ; Eat leading space JSR EATSPC ; Eat leading space
BCS :ERR BCS :ERR
JSR ADDZP1Y ; Advance ZP1 JSR ADDZP1Y ; Advance ZP1
LDA ZP1 ; Pointer to filename LDA ZP1 ; Pointer to filename
STA OSFILECB STA OSFILECB
LDA ZP1+1 LDA ZP1+1
STA OSFILECB+1 STA OSFILECB+1
JSR EATWORD JSR EATWORD
BCS :ERR ; No start address given BCS :ERR ; No start address given
LDA #$0D ; Carriage return LDA #$0D ; Carriage return
STA (ZP1),Y ; Terminate filename STA (ZP1),Y ; Terminate filename
INY INY
JSR EATSPC ; Eat any whitespace JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1 JSR ADDZP1Y ; Update ZP1
JSR HEXCONST JSR HEXCONST
BCS :ERR ; Bad start address BCS :ERR ; Bad start address
LDA ADDRBUF LDA ADDRBUF
STA OSFILECB+10 STA OSFILECB+10
LDA ADDRBUF+1 LDA ADDRBUF+1
STA OSFILECB+11 STA OSFILECB+11
JSR EATSPC ; Eat any whitespace JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1 JSR ADDZP1Y ; Update ZP1
JSR HEXCONST JSR HEXCONST
BCS :ERR ; Bad end address BCS :ERR ; Bad end address
LDA ADDRBUF LDA ADDRBUF
STA OSFILECB+14 STA OSFILECB+14
LDA ADDRBUF+1 LDA ADDRBUF+1
STA OSFILECB+15 STA OSFILECB+15
LDX #<OSFILECB LDX #<OSFILECB
LDY #>OSFILECB LDY #>OSFILECB
LDA #$00 ; OSFILE save flag LDA #$00 ; OSFILE save flag
JSR OSFILE JSR OSFILE
:END RTS :END RTS
:ERR JSR BEEP :ERR JSR BEEP
@ -474,15 +421,11 @@ STARSAVE JSR CLRCB
* Handle *RUN command * Handle *RUN command
* On entry, ZP1 points to command line * On entry, ZP1 points to command line
STARRUN TYA STARRUN JSR ADDZP1Y
CLC LDX ZP1+0
ADC ZP1 LDY ZP1+1
TAX
LDA #$00
ADC ZP2
TAY
LDA #$04 LDA #$04
CALLFSCV JMP (FSCV) ; FSCV does the work CALLFSCV JMP (FSCV) ; Hand on to filing system
* Clear OSFILE control block to zeros * Clear OSFILE control block to zeros
CLRCB LDA #$00 CLRCB LDA #$00
@ -493,3 +436,5 @@ CLRCB LDA #$00
BNE :L1 BNE :L1
RTS RTS

310
auxmem.misc.s Normal file
View File

@ -0,0 +1,310 @@
* MISC.S
********
* Misc functions and API entry block
*
* OSBYTE $80 - ADVAL
************************************
* Read input device or buffer status
BYTE80 LDY #$00 ; Prepare return=&00xx
TXA ; X<0 - info about buffers
BMI ADVALBUF ; X>=0 - read input devices
*
* TEST CODE
CPX #$7F
BNE ADVALNONE
ADVALWAIT JSR KBDREAD
BCC ADVALWAIT
TAX
RTS
* TEST CODE
*
ADVALNONE LDX #$00 ; Input, just return 0
RTS
ADVALBUF INX
BEQ :ADVALKBD ; Fake keyboard buffer
INX
BEQ :ADVALOK ; Serial input, return 0
LDX #$01 ; For outputs, return 1 char free
RTS
:ADVALKBD BIT $C000 ; Test keyboard data/strobe
BPL :ADVALOK ; No Strobe, return 0
INX ; Strobe, return 1
:ADVALOK RTS
******************
* Helper functions
******************
* Beep
BEEP PHA
PHX
*
* A nicer beep
* 1.023MHz clock
*
PHY
LDY #$00 ; 2cy duration
*
* $C1 975cy = 524.6Hz = C5 slightly sharp
* (actually sounds like E5 on my Casio)
* $6B 546cy = 936.8Hz = A5# sharp - close to Apple BEEP
* $60 491cy = 1041.7Hz = C6 slightly sharp
*
:L1 LDX #$60 ; 2cy pitch 2cy
*------------------------------------------------
:L2 DEX ; 2cy 193 * 2cy
BNE :L2 ; 3cy/2cy 192 * 3cy + 1 * 2cy
*------------------------------------------------
* 964cy
LDA $C030 ; 4cy 4cy
DEY ; 2cy 2cy
BNE :L1 ; 2cy/3cy 3cy
PLY ; 975cy = 524.6Hz = C5
*
* LDX #$20
*:L1 LDA $C030
* JSR DELAY
* INX
* BNE :L1
*
PLX
PLA
RTS
* Delay approx 1/100 sec
DELAY PHX
PHY
LDX #$00
:L1 INX ; 2
LDY #$00 ; 2
:L2 INY ; 2
CPY #$00 ; 2
BNE :L2 ; 3 (taken)
CPX #$02 ; 2
BNE :L1 ; 3 (taken)
PLY
PLX
RTS
* Print string pointed to by X,Y to the screen
OUTSTR TXA
* Print string pointed to by A,Y to the screen
PRSTR STA OSTEXT+0 ; String in A,Y
STY OSTEXT+1
:L1 LDA (OSTEXT) ; Ptr to string in ZP3
BEQ :S1
JSR OSASCI
INC OSTEXT
BNE :L1
INC OSTEXT+1
BRA :L1
:S1 RTS
* Print XY in hex
OUT2HEX TYA
JSR OUTHEX
TAX ; Continue into OUTHEX
* Print hex byte in A
OUTHEX PHA
LSR
LSR
LSR
LSR
AND #$0F
JSR PRNIB
PLA
AND #$0F ; Continue into PRNIB
* JSR PRNIB
* RTS
* Print hex nibble in A
PRNIB CMP #$0A
BCC :S1
CLC ; >= $0A
ADC #'A'-$0A
JSR OSWRCH
RTS
:S1 ADC #'0' ; < $0A
JMP OSWRCH
**********************************************************
* Interrupt Handlers, MOS redirection vectors etc.
**********************************************************
* IRQ/BRK handler
IRQBRKHDLR
PHA
* >>> WRTMAIN
* STA $45 ; A->$45 for ProDOS IRQ handlers
* >>> WRTAUX
* Mustn't enable IRQs within the IRQ handler
* Do this manually, as we have complete control at this point
STA $C004 ; Write to main memory
STA $45 ; $45=A for ProDOS IRQ handlers
STA $C005 ; Write to aux memory
;
TXA
PHA
CLD
TSX
LDA $103,X ; Get PSW from stack
AND #$10
BEQ :IRQ ; IRQ
SEC
LDA $0104,X
SBC #$01
STA FAULT
LDA $0105,X
SBC #$00
STA FAULT+1
PLA
TAX
PLA
CLI
JMP (BRKV) ; Pass on to BRK handler
:IRQ >>> XF2MAIN,A2IRQ ; Bounce to Apple IRQ handler
IRQBRKRET
PLA ; TODO: Pass on to IRQ1V
TAX
PLA
NULLRTI RTI
PRERR LDY #$01
PRERRLP LDA (FAULT),Y
BEQ PRERR1
JSR OSWRCH
INY
BNE PRERRLP
NULLRTS
PRERR1 RTS
MOSBRKHDLR LDA #<MSGBRK
LDY #>MSGBRK
JSR PRSTR
JSR PRERR
JSR OSNEWL
JSR OSNEWL
STOP JMP STOP ; Cannot return from a BRK
MSGBRK DB $0D
ASC "ERROR: "
DB $00
RDROM LDA #<OSRDRMM
LDY #>OSRDRMM
JMP PRSTR
OSRDRMM ASC 'OSRDDRM.'
DB $00
EVENT LDA #<OSEVENM
LDY #>OSEVENM
JMP PRSTR
OSEVENM ASC 'OSEVEN.'
DB $00
GSINTGO LDA #<OSINITM
LDY #>OSINITM
JMP PRSTR
OSINITM ASC 'GSINITM.'
DB $00
GSRDGO LDA #<OSREADM
LDY #>OSREADM
JMP PRSTR
OSREADM ASC 'GSREAD.'
DB $00
* Default page 2 contents
DEFVEC DW NULLRTS ; $200 USERV
DW MOSBRKHDLR ; $202 BRKV
DW NULLRTI ; $204 IRQ1V
DW NULLRTI ; $206 IRQ2V
DW CLIHND ; $208 CLIV
DW BYTEHND ; $20A BYTEV
DW WORDHND ; $20C WORDV
DW WRCHHND ; $20E WRCHV
DW RDCHHND ; $210 RDCHV
DW FILEHND ; $212 FILEV
DW ARGSHND ; $214 ARGSV
DW BGETHND ; $216 BGETV
DW BPUTHND ; $218 BPUTV
DW GBPBHND ; $21A GBPBV
DW FINDHND ; $21C FINDV
DW FSCHND ; $21E FSCV
ENDVEC
*
* Acorn MOS entry points at the top of RAM
* Copied from loaded code to high memory
*
* Base of API entries here in loaded code
MOSVEC
* Real base of API entries in real memory
MOSAPI EQU $FFB6
ORG MOSAPI
* OPTIONAL ENTRIES
* ----------------
*OSSERV JMP NULLRTS ; FF95 OSSERV
*OSCOLD JMP NULLRTS ; FF98 OSCOLD
*OSPRSTR JMP OUTSTR ; FF9B PRSTRG
*OSFF9E JMP NULLRTS ; FF9E
*OSSCANHEX JMP RDHEX ; FFA1 SCANHX
*OSFFA4 JMP NULLRTS ; FFA4
*OSFFA7 JMP NULLRTS ; FFA7
*PRHEX JMP OUTHEX ; FFAA PRHEX
*PR2HEX JMP OUT2HEX ; FFAD PR2HEX
*OSFFB0 JMP NULLRTS ; FFB0
*OSWRRM JMP NULLRTS ; FFB3 OSWRRM
* COMPULSARY ENTRIES
* ------------------
VECSIZE DB ENDVEC-DEFVEC ; FFB6 VECSIZE Size of vectors
VECBASE DW DEFVEC ; FFB7 VECBASE Base of default vectors
OSRDRM JMP RDROM ; FFB9 OSRDRM Read byte from paged ROM
OSCHROUT JMP OUTCHAR ; FFBC CHROUT Send char to VDU driver
OSEVEN JMP EVENT ; FFBF OSEVEN Signal an event
GSINIT JMP GSINTGO ; FFC2 GSINIT Init string reading
GSREAD JMP GSRDGO ; FFC5 GSREAD Parse general string
NVWRCH JMP WRCHHND ; FFC8 NVWRCH Nonvectored WRCH
NVRDCH JMP RDCHHND ; FFCB NVRDCH Nonvectored RDCH
OSFIND JMP (FINDV) ; FFCE OSFIND
OSGBPB JMP (GBPBV) ; FFD1 OSGBPB
OSBPUT JMP (BPUTV) ; FFD4 OSBPUT
OSBGET JMP (BGETV) ; FFD7 OSBGET
OSARGS JMP (ARGSV) ; FFDA OSARGS
OSFILE JMP (FILEV) ; FFDD OSFILE
OSRDCH JMP (RDCHV) ; FFE0 OSRDCH
OSASCI CMP #$0D ; FFE3 OSASCI
BNE OSWRCH
OSNEWL LDA #$0A ; FFE7 OSNEWL
JSR OSWRCH
OSWRCR LDA #$0D ; FFEC OSWRCR
OSWRCH JMP (WRCHV) ; FFEE OSWRCH
OSWORD JMP (WORDV) ; FFF1 OSWORD
OSBYTE JMP (BYTEV) ; FFF4 OSBYTE
OSCLI JMP (CLIV) ; FFF7 OSCLI
NMIVEC DW NULLRTI ; FFFA NMIVEC
RSTVEC DW STOP ; FFFC RSTVEC
IRQVEC
* Assembler doesn't like running up to $FFFF, so we bodge a bit
MOSEND
ORG MOSEND-MOSAPI+MOSVEC
DW IRQBRKHDLR ; FFFE IRQVEC
MOSVEND
* Buffer for one 512 byte disk block in aux mem
AUXBLK DS $200

View File

@ -1,9 +1,7 @@
* AUX.MOS.WS.S * MOSEQU.S
* (c) Bobbi 2021 GPLv3 *******************************
* BBC MOS WORKSPACE LOCATIONS *
*********************************************************** *******************************
* Acorn MOS Workspace Locations
***********************************************************
* $00-$8F Language workspace * $00-$8F Language workspace
* $90-$9F Network workspace * $90-$9F Network workspace
@ -19,27 +17,28 @@ FSFLAG1 EQU $E2
FSFLAG2 EQU $E3 FSFLAG2 EQU $E3
GSFLAG EQU $E4 GSFLAG EQU $E4
GSCHAR EQU $E5 GSCHAR EQU $E5
OSTEXT EQU $E6 OSTEXT EQU $E6 ; $E6 => text string
MAXLEN EQU OSTEXT+2 ; $E8 MAXLEN EQU OSTEXT+2 ; $E8
MINCHAR EQU OSTEXT+3 ; $E9 MINCHAR EQU OSTEXT+3 ; $E9
MAXCHAR EQU OSTEXT+4 ; $EA MAXCHAR EQU OSTEXT+4 ; $EA
OSTEMP EQU $EB OSTEMP EQU $EB ; $EB
OSKBD1 EQU $EC ; Kbd workspace OSKBD1 EQU $EC ; $EC kbd ws
OSKBD2 EQU $ED OSKBD2 EQU OSKBD1+1 ; $ED kbd ws
OSKBD3 EQU $EE OSKBD3 EQU OSKBD1+2 ; $EE kbd ws
OSAREG EQU $EF OSAREG EQU $EF ; $EF A register
OSXREG EQU OSAREG+1 ; $F0 OSXREG EQU OSAREG+1 ; $F0 X register
OSYREG EQU OSXREG+1 ; $F1 OSYREG EQU OSXREG+1 ; $F1 Y register
OSCTRL EQU OSXREG OSCTRL EQU OSXREG ; $F0 (XY)=>control block
OSLPTR EQU $F2 OSLPTR EQU $F2 ; $F2 => command line
* ;
OSINTWS EQU $FA ; IRQ ZP pointer OSINTWS EQU $FA ; $FA IRQ ZP pointer, use when IRQs off
OSINTA EQU $FC ; IRQ A-reg store OSINTA EQU $FC ; $FC IRQ register A store
FAULT EQU $FD ; Error message pointer FAULT EQU $FD ; $FD Error message pointer
ESCFLAG EQU $FF ; Escape status ESCFLAG EQU $FF ; $FF Escape status
* $0200-$0235 Vectors * $0200-$0235 Vectors
* $0236-$028F OSBYTE variables * $0236-$028F OSBYTE variable
* $0290-$02ED * $0290-$02ED
* $02EE-$02FF MOS control block * $02EE-$02FF MOS control block
@ -61,3 +60,4 @@ FSCV EQU $21E ; FSCV misc file ops
OSFILECB EQU $2EE ; OSFILE control block OSFILECB EQU $2EE ; OSFILE control block

331
auxmem.vdu.s Normal file
View File

@ -0,0 +1,331 @@
* VDU.S
****************************************************
* Apple //e VDU Driver for 40/80 column mode (PAGE2)
****************************************************
**********************************
* VDU DRIVER WORKSPACE LOCATIONS *
**********************************
* $00D0-$00DF VDU driver zero page workspace
VDUSTATUS EQU $D0 ; $D0 VDU status
VDUZP1 EQU VDUSTATUS+1 ; $D1
VDUCOL EQU VDUSTATUS+2 ; $D2 text column
VDUROW EQU VDUSTATUS+3 ; $D3 text row
VDUADDR EQU VDUSTATUS+4 ; $D4 address of current char cell
FXVDUQLEN EQU $D1 ; TEMP HACK
VDUCHAR EQU $D6 ; TEMP HACK
VDUQ EQU $D7 ; TEMP HACK
* Clear to EOL
CLREOL LDA ROW
ASL
TAX
LDA SCNTAB,X ; LSB of row
STA ZP1
LDA SCNTAB+1,X ; MSB of row
STA ZP1+1
LDA COL
PHA
STZ COL
:L1 LDA COL
LSR
TAY
BCC :S1
>>> WRTMAIN
:S1 LDA #" "
STA (ZP1),Y
>>> WRTAUX
LDA COL
CMP #79
BEQ :S2
INC COL
BRA :L1
:S2 PLA
STA COL
RTS
* Clear the screen
CLEAR STZ ROW
STZ COL
:L1 JSR CLREOL
:S2 LDA ROW
CMP #23
BEQ :S3
INC ROW
BRA :L1
:S3 STZ ROW
STZ COL
RTS
* Print char in A at ROW,COL
PRCHRC PHA
LDA $C000 ; Kbd data/strobe
BMI :KEYHIT
:RESUME LDA ROW
ASL
TAX
LDA SCNTAB,X ; LSB of row address
STA ZP1
LDA SCNTAB+1,X ; MSB of row address
STA ZP1+1
LDA COL
BIT $C01F
BPL :S1A ; 40-col
LSR
BCC :S1
:S1A >>> WRTMAIN
:S1 TAY
PLA
EOR #$80
STA (ZP1),Y ; Screen address
>>> WRTAUX
RTS
:KEYHIT STA $C010 ; Clear strobe
AND #$7F
CMP #$13 ; Ctrl-S
BEQ :PAUSE
CMP #$1B ; Esc
BNE :RESUME
:ESC SEC
ROR ESCFLAG ; Set ESCFLAG
BRA :RESUME
:PAUSE STA $C010 ; Clear strobe
:L1 LDA $C000 ; Kbd data/strobe
BPL :L1
AND #$7F
CMP #$11 ; Ctrl-Q
BEQ :RESUME
CMP #$1B ; Esc
BEQ :ESC
BRA :PAUSE
* Return char at ROW,COL in A and X, MODE in Y
BYTE87
GETCHRC LDA ROW
ASL
TAX
LDA SCNTAB,X
STA ZP1
LDA SCNTAB+1,X
STA ZP1+1
LDA COL
BIT $C01F
BPL :S1A ; 40-col
LSR
BCC :S1
:S1A STA $C002 ; Read main memory
:S1 TAY
LDA (ZP1),Y
EOR #$80
STA $C003 ; Read aux mem again
TAX
LDY #$00
BIT $C01F
BMI :GETCHOK
INY
:GETCHOK RTS
BYTE86 LDY ROW ; $86 = read cursor pos
LDX COL
RTS
* Perform backspace & delete operation
DELETE JSR BACKSPC
* LDA COL
* BEQ :S1
* DEC COL
* BRA :S2
*:S1 LDA ROW
* BEQ :S3
* DEC ROW
* LDA #79
* STA COL
:S2 LDA #' '
JSR PRCHRC
:S3 RTS
* Perform backspace/cursor left operation
BACKSPC LDA COL
BEQ :S1
DEC COL
BRA :S3
:S1 LDA ROW
BEQ :S3
DEC ROW
LDA #39
BIT $C01F
BPL :S2
LDA #79
:S2 STA COL
:S3 RTS
** Perform cursor right operation
*CURSRT LDA COL
* CMP #78
* BCS :S1
* INC COL
* RTS
*:S1 LDA ROW
* CMP #22
* BCS :S2
* INC ROW
* STZ COL
*:S2 RTS
* Output character to VDU driver
* All registers trashable
OUTCHAR
*
* Quick'n'nasty VDU queue
LDX FXVDUQLEN
BNE ADDTOQ
CMP #$01
BEQ ADDQ ; One param
CMP #$11
BCC OUTCHARGO ; Zero param
CMP #$20
BCS OUTCHARGO ; Print chars
ADDQ STA VDUCHAR ; Save initial character
AND #$0F
TAX
LDA QLEN,X
STA FXVDUQLEN
BEQ OUTCHARGO1
QDONE RTS
QLEN DB -0,-1,-2,-5,-0,-0,-1,-9
DB -8,-5,-0,-0,-4,-4,-0,-2
ADDTOQ STA VDUQ-256+9,X
INC FXVDUQLEN
BNE QDONE
OUTCHARGO1 LDA VDUCHAR
* end nasty hack
*
OUTCHARGO CMP #$00 ; NULL
BNE :T1
BRA :IDONE
:T1 CMP #$07 ; BELL
BNE :T2
JSR BEEP
BRA :IDONE
:T2 CMP #$08 ; Backspace
BNE :T3
JSR BACKSPC
BRA :IDONE
:T3 CMP #$09 ; Cursor right
BNE :T4
* JSR CURSRT
JSR VDU09
BRA :IDONE
:T4 CMP #$0A ; Linefeed
BNE :T5
LDA ROW
CMP #23
BEQ SCROLL
INC ROW
:IDONE RTS
; BRA :DONE
:T5 CMP #$0B ; Cursor up
BNE :T6
LDA ROW
BEQ :IDONE
DEC ROW
BRA :IDONE
:T6 CMP #$0D ; Carriage return
BNE :T7
* JSR CLREOL
STZ COL
BRA :IDONE
:T7 CMP #$0C ; Ctrl-L
BEQ :T7A
CMP #$16
BNE :T8
LDA VDUQ+8
EOR #$07
AND #$01
TAX
STA $C00C,X
:T7A JSR CLEAR
BRA :IDONE
:T8 CMP #$1E ; Home
BNE :T9
STZ ROW
STZ COL
BRA :IDONE
:T9 CMP #$7F ; Delete
BNE :T10
JSR DELETE
BRA :IDONE
:T10 CMP #$20
BCC :IDONE
JSR PRCHRC
* Perform cursor right operation
VDU09 LDA COL
CMP #39
BCC :S2
BIT $C01F
BPL :T11
CMP #79
BCC :S2
:T11 STZ COL
LDA ROW
CMP #23
BEQ SCROLL
INC ROW
:DONE RTS
; BRA :DONE
:S2 INC COL
BRA :DONE
SCROLL JSR SCROLLER
* STZ COL
JSR CLREOL
;:DONE
RTS
* Scroll whole screen one line
SCROLLER LDA #$00
:L1 PHA
JSR SCR1LINE
PLA
INC
CMP #23
BNE :L1
RTS
* Copy line A+1 to line A
SCR1LINE ASL ; Dest addr->ZP1
TAX
LDA SCNTAB,X
STA ZP1
LDA SCNTAB+1,X
STA ZP1+1
INX ; Source addr->ZP2
INX
LDA SCNTAB,X
STA ZP2
LDA SCNTAB+1,X
STA ZP2+1
LDY #$00
:L1 LDA (ZP2),Y
STA (ZP1),Y
STA $C002 ; Read main mem
>>> WRTMAIN
LDA (ZP2),Y
STA (ZP1),Y
STA $C003 ; Read aux mem
>>> WRTAUX
INY
CPY #40
BNE :L1
RTS
* Addresses of screen rows in PAGE2
SCNTAB DW $800,$880,$900,$980,$A00,$A80,$B00,$B80
DW $828,$8A8,$928,$9A8,$A28,$AA8,$B28,$BA8
DW $850,$8D0,$950,$9D0,$A50,$AD0,$B50,$BD0

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
for file in APPLECORN LOADER MAINMEM AUX.AMOS.INIT AUX.AMOS.KRNL AUX.HOSTFS AUX.IRQ.VECS AUX.MISC AUX.MOS.WS AUX.OSBW.JGH AUX.OSBW.ORIG AUX.VDU; do for file in APPLECORN AUXMEM.BYTWRD AUXMEM.CHARIO AUXMEM.HOSTFS AUXMEM.INIT AUXMEM.KERNEL AUXMEM.MISC AUXMEM.MOSEQU AUXMEM.VDU LOADER MAINMEM; do
cadius extractfile applecorn.po /APPLECORN/${file}.S . cadius extractfile applecorn.po /APPLECORN/${file}.S .
rm _FileInformation.txt rm _FileInformation.txt
cadius clearhighbit ${file}.S\#040000 cadius clearhighbit ${file}.S\#040000

View File

@ -110,3 +110,5 @@ START STZ :BLOCKS
:BLOCKS DB 0 ; Counter for blocks read :BLOCKS DB 0 ; Counter for blocks read

View File

@ -741,3 +741,5 @@ FBSTRT DW $0000 ; Start address for SAVE
FBEND DW $0000 ; End address for SAVE FBEND DW $0000 ; End address for SAVE
DW $0000 DW $0000