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!
PUT LOADER
PUT MAINMEM
PUT AUX.MOS.WS
PUT AUX.AMOS.INIT
PUT AUX.VDU
PUT AUX.HOSTFS
PUT AUX.AMOS.KRNL
PUT AUX.OSBW.ORIG
* PUT AUX.OSBW.JGH
PUT AUX.MISC
PUT AUX.IRQ.VECS
PUT AUXMEM.MOSEQU
PUT AUXMEM.INIT
PUT AUXMEM.VDU
PUT AUXMEM.HOSTFS
PUT AUXMEM.KERNEL
* PUT AUXMEM.OSBW.ORIG
PUT AUXMEM.BYTWRD
PUT AUXMEM.CHARIO
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/CHARIO.S
*****************
* Character read and write
*
* OSWRCH handler
* All registers preserved
WRCHHND PHA
@ -17,7 +22,7 @@ WRCHHND PHA
RTS
* OSRDCH handler
* All registers preserved except A, carry
* All registers preserved except A, Carry
* Read a character from the keyboard
RDCHHND PHX
PHY
@ -28,6 +33,7 @@ RDCHHND PHX
BNE :S1
LDA CURS
BNE :S1
STZ CURS
STZ CURS+1
LDA CSTATE
@ -62,26 +68,11 @@ CURS DW $0000 ; Counter
CSTATE DB $00 ; Cursor on or off
OLDCHAR DB $00 ; Char under cursor
* Performs OSBYTE $80 function
* Read ADC channel or get buffer status
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
BYTE81 JSR GETKEY ; $81 = Read key with time lim
RTS
* Performs OSBYTE $81 INKEY$ function
* X,Y has time limit
* On exit, CC, Y=$00, X=key - key pressed
@ -125,75 +116,68 @@ NEGKEY LDX #$00 ; Unimplemented
LDY #$00
RTS
***********************************************************
* Helper functions
***********************************************************
* KERNEL/KEYBOARD.S
*******************
* Beep
BEEP PHA
PHX
LDX #$80
:L1 LDA $C030
JSR DELAY
INX
BNE :L1
PLX
PLA
KBDREAD
KEYPRESS LDA $C000
TAY
CMP #$80
BCC KEYNONE ; No key pressed
AND #$7F
STA $C010 ; Ack. keypress
BIT $C061
BMI KEYLALT ; Left Apple pressed
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
* 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
KEYRALT ; Right Apple key pressed
KEYLALT CMP #$40 ; Left Apple key pressed
BCS KEYCTRL
CMP #$30
BCC KEYOK ; <'0'
CMP #$3A
BCS KEYOK ; >'9'
KEYFUNC AND #$0F ; Convert Apple-Num to function key
ORA #$80
BIT $C062
BPL KEYFUNOK ; Left+Digit -> $8x
ORA #$90 ; Right+Digit -> $9x
BIT $C061
BPL KEYFUNOK
EOR #$30 ; Left+Right+Digit -> $Ax
KEYFUNOK SEC
RTS
KEYCTRL AND #$1F ; Apple-Letter -> Ctrl-Letter
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 OSTEXT
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
* Print hex nibble in A
PRNIB CMP #$0A
BCC :S1
CLC ; >= $0A
ADC #'A'-$0A
JSR OSWRCH
KEYCUR15
* BIT $C062
* BPL KEYCUR16 ; Right Apple not pressed
* LDA #$C9 ; Solid+Right -> COPY?
* SEC
* RTS
KEYCUR16 LDA #$09 ; Convert RGT to $09
KEYCURSR AND #$03
ORA #$CC ; Cursor keys $CC-$CF
SEC ; SEC=Ok
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
STRTBCKH EQU $9E
WARMSTRT EQU $9F ; Cold or warm start
MAGIC EQU $BC ; Arbitrary value
MOSSHIM
@ -95,22 +94,30 @@ MOSINIT STA $C005 ; Make sure we are writing aux
INC A4H
:S7 BRA :L2
:NORELOC
:NORELOC ; We should jump up into high memory here
:S8 STA $C00D ; 80 col on
STA $C003 ; Alt charset off
STA $C055 ; PAGE2
STZ ROW
STZ COL
JSR CLEAR
LDY WARMSTRT ; Don't lose this
LDX #$FF
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 #$35
:INITPG2 LDA DEFVEC,X
LDX #ENDVEC-DEFVEC-1
:INITPG2 LDA DEFVEC,X ; Set up vectors
STA $200,X
DEX
BPL :INITPG2
STY WARMSTRT ; Put it back
JSR CLEAR ; Initialise VDU driver
LDA #<:HELLO
LDY #>:HELLO
@ -141,3 +148,5 @@ MOSINIT STA $C005 ; Make sure we are writing aux
:OLDM ASC '(Use OLD to recover any program)'
DB $0D,$0D,$00

View File

@ -2,36 +2,61 @@
* AppleMOS Kernel
*********************************************************
BYTE8E PHP ; Save CLC=reset, SEC=not reset
LDA #$09 ; $8E = enter language ROM
LDY #$80 ; Print lang name at $8009
JSR PRSTR
* KERNEL/SWROM.S
****************
* 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
PLP ; Get entry type back
PLP ; Get entry type back
LDA #$01
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
* On entry, XY=>command string
* TO DO: line pointer in XY should be in LPTR
*
CLIHND PHX
PHY
STX ZP1+0 ; Pointer to CLI
STX ZP1+0 ; Pointer to CLI
STY ZP1+1
:L1 LDA (ZP1)
CMP #'*' ; Trim any leading stars
CMP #'*' ; Trim any leading stars
BEQ :NEXT
CMP #' ' ; Trim any leading spaces
CMP #' ' ; Trim any leading spaces
BEQ :NEXT
BRA :TRIMMED
:NEXT INC ZP1
BNE :L1
INC ZP1+1
BRA :L1
:TRIMMED CMP #'|' ; | is comment
:TRIMMED CMP #'|' ; | is comment
BEQ :IEXIT
CMP #$0D ; Carriage return
CMP #$0D ; Carriage return
BEQ :IEXIT
LDA #<:QUIT
STA ZP2
@ -97,18 +122,22 @@ CLIHND PHX
BCS :ASKROM
JSR STARHELP
BRA :EXIT
:ASKROM LDA $8006 ; Check service entry
BPL :UNSUPP ; Only BASIC has no srvc entry
LDA ZP1 ; String in (OSLPTR),Y
:ASKROM LDA $8006 ; Check for service entry
BPL :UNSUPP ; No service entry
* 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
LDA ZP1+1
STA OSLPTR+1
LDY #$00
LDA #$04 ; Service 4 Unrecognized Cmd
LDX #$0F ; ROM slot
JSR $8003 ; Service entry point
TAX ; Check ret val
BEQ :EXIT ; Call claimed
LDA #$04 ; Service 4 Unrecognized Cmd
LDX #$0F ; ROM slot
JSR $8003 ; Service entry point
TAX ; Check return
BEQ :EXIT ; Call claimed
:UNSUPP LDA #<:OSCLIM
LDY #>:OSCLIM
JSR PRSTR
@ -122,7 +151,7 @@ CLIHND PHX
BEQ :PS1
CMP #$00
BEQ :PS1
JSR $FFEE ; OSWRCH
JSR OSWRCH
INY
BRA :PL1
:PS1 LDA #<:OSCLIM2
@ -181,7 +210,7 @@ STRCMP LDY #$00
STARHELP LDA #<:MSG
LDY #>:MSG
JSR PRSTR
LDA #$09 ; Language name
LDA #$09 ; Language name
LDY #$80
JSR PRSTR
LDA #<:MSG2
@ -197,80 +226,22 @@ STARHELP LDA #<:MSG
STARQUIT >>> XF2MAIN,QUIT
* Handle *CAT / *. command (list directory)
STARCAT >>> XF2MAIN,CATALOG
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
STARCAT JMP FSCCAT
* Consume spaces in command line. Treat " as space!
* Return C set if no space found, C clear otherwise
* Command line pointer in (ZP1),Y
EATSPC LDA (ZP1),Y ; Check first char is ...
CMP #' ' ; ... space
EATSPC LDA (ZP1),Y ; Check first char is ...
CMP #' ' ; ... space
BEQ :START
CMP #'"' ; Or quote mark
CMP #'"' ; Or quote mark
BEQ :START
BRA :NOTFND
:START INY
:L1 LDA (ZP1),Y ; Eat any additional ...
CMP #' ' ; ... spaces
:L1 LDA (ZP1),Y ; Eat any additional ...
CMP #' ' ; ... spaces
BEQ :CONT
CMP #'"' ; Or quote marks
CMP #'"' ; Or quote marks
BNE :DONE
:CONT INY
BRA :L1
@ -287,7 +258,7 @@ EATWORD LDA (ZP1),Y
BEQ :SPC
CMP #'"'
BEQ :SPC
CMP #$0D ; Carriage return
CMP #$0D ; Carriage return
BEQ :EOL
INY
BRA EATWORD
@ -296,30 +267,6 @@ EATWORD LDA (ZP1),Y
:EOL SEC
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.
ADDZP1Y CLC
TYA
@ -334,18 +281,18 @@ ADDZP1Y CLC
* Decode ASCII hex digit in A
* Returns with carry set if bad char, C clear otherwise
HEXDIGIT CMP #'F'+1
BCS :BADCHAR ; char > 'F'
BCS :BADCHAR ; char > 'F'
CMP #'A'
BCC :S1
SEC ; 'A' <= char <= 'F'
SEC ; 'A' <= char <= 'F'
SBC #'A'-10
CLC
RTS
:S1 CMP #'9'+1
BCS :BADCHAR ; '9' < char < 'A'
BCS :BADCHAR ; '9' < char < 'A'
CMP #'0'
BCC :BADCHAR ; char < '0'
SEC ; '0' <= char <= '9'
BCC :BADCHAR ; char < '0'
SEC ; '0' <= char <= '9'
SBC #'0'
CLC
RTS
@ -355,24 +302,24 @@ HEXDIGIT CMP #'F'+1
* Decode hex constant on command line
* On entry, ZP1 points to command line
HEXCONST LDX #$00
:L1 STZ :BUF,X ; Clear :BUF
:L1 STZ :BUF,X ; Clear :BUF
INX
CPX #$04
BNE :L1
LDX #$00
LDY #$00
:L2 LDA (ZP1),Y ; Parse hex digits into
JSR HEXDIGIT ; :BUF, left aligned
:L2 LDA (ZP1),Y ; Parse hex digits into
JSR HEXDIGIT ; :BUF, left aligned
BCS :NOTHEX
STA :BUF,X
INY
INX
CPX #$04
BNE :L2
LDA (ZP1),Y ; Peek at next char
:NOTHEX CPX #$00 ; Was it the first digit?
BEQ :ERR ; If so, bad hex constant
CMP #' ' ; If whitespace, then okay
LDA (ZP1),Y ; Peek at next char
:NOTHEX CPX #$00 ; Was it the first digit?
BEQ :ERR ; If so, bad hex constant
CMP #' ' ; If whitespace, then okay
BEQ :OK
CMP #$0D
BEQ :OK
@ -397,38 +344,38 @@ HEXCONST LDX #$00
:ZEROPAD DB $00,$00,$00
:BUF DB $00,$00,$00,$00
ADDRBUF DW $0000 ; Used by HEXCONST
ADDRBUF DW $0000 ; Used by HEXCONST
* Handle *LOAD command
* On entry, ZP1 points to command line
STARLOAD JSR CLRCB
JSR EATSPC ; Eat leading spaces
JSR EATSPC ; Eat leading spaces
BCS :ERR
JSR ADDZP1Y ; Advance ZP1
LDA ZP1 ; Pointer to filename
JSR ADDZP1Y ; Advance ZP1
LDA ZP1 ; Pointer to filename
STA OSFILECB
LDA ZP1+1
STA OSFILECB+1
JSR EATWORD ; Advance past filename
BCS :NOADDR ; No load address given
LDA #$0D ; Carriage return
STA (ZP1),Y ; Terminate filename
JSR EATWORD ; Advance past filename
BCS :NOADDR ; No load address given
LDA #$0D ; Carriage return
STA (ZP1),Y ; Terminate filename
INY
JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1
JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1
JSR HEXCONST
BCS :ERR ; Bad hex constant
BCS :ERR ; Bad hex constant
LDA ADDRBUF
STA OSFILECB+2 ; Load address LSB
STA OSFILECB+2 ; Load address LSB
LDA ADDRBUF+1
STA OSFILECB+3 ; Load address MSB
STA OSFILECB+3 ; Load address MSB
:OSFILE LDX #<OSFILECB
LDY #>OSFILECB
LDA #$FF ; OSFILE load flag
LDA #$FF ; OSFILE load flag
JSR OSFILE
:END RTS
:NOADDR LDA #$FF ; Set OSFILECB+6 to non-zero
STA OSFILECB+6 ; Means use the file's addr
:NOADDR LDA #$FF ; Set OSFILECB+6 to non-zero
STA OSFILECB+6 ; Means use the file's addr
BRA :OSFILE
:ERR JSR BEEP
RTS
@ -436,37 +383,37 @@ STARLOAD JSR CLRCB
* Handle *SAVE command
* On entry, ZP1 points to command line
STARSAVE JSR CLRCB
JSR EATSPC ; Eat leading space
JSR EATSPC ; Eat leading space
BCS :ERR
JSR ADDZP1Y ; Advance ZP1
LDA ZP1 ; Pointer to filename
JSR ADDZP1Y ; Advance ZP1
LDA ZP1 ; Pointer to filename
STA OSFILECB
LDA ZP1+1
STA OSFILECB+1
JSR EATWORD
BCS :ERR ; No start address given
LDA #$0D ; Carriage return
STA (ZP1),Y ; Terminate filename
BCS :ERR ; No start address given
LDA #$0D ; Carriage return
STA (ZP1),Y ; Terminate filename
INY
JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1
JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1
JSR HEXCONST
BCS :ERR ; Bad start address
BCS :ERR ; Bad start address
LDA ADDRBUF
STA OSFILECB+10
LDA ADDRBUF+1
STA OSFILECB+11
JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1
JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1
JSR HEXCONST
BCS :ERR ; Bad end address
BCS :ERR ; Bad end address
LDA ADDRBUF
STA OSFILECB+14
LDA ADDRBUF+1
STA OSFILECB+15
LDX #<OSFILECB
LDY #>OSFILECB
LDA #$00 ; OSFILE save flag
LDA #$00 ; OSFILE save flag
JSR OSFILE
:END RTS
:ERR JSR BEEP
@ -474,15 +421,11 @@ STARSAVE JSR CLRCB
* Handle *RUN command
* On entry, ZP1 points to command line
STARRUN TYA
CLC
ADC ZP1
TAX
LDA #$00
ADC ZP2
TAY
STARRUN JSR ADDZP1Y
LDX ZP1+0
LDY ZP1+1
LDA #$04
CALLFSCV JMP (FSCV) ; FSCV does the work
CALLFSCV JMP (FSCV) ; Hand on to filing system
* Clear OSFILE control block to zeros
CLRCB LDA #$00
@ -493,3 +436,5 @@ CLRCB LDA #$00
BNE :L1
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
* (c) Bobbi 2021 GPLv3
***********************************************************
* Acorn MOS Workspace Locations
***********************************************************
* MOSEQU.S
*******************************
* BBC MOS WORKSPACE LOCATIONS *
*******************************
* $00-$8F Language workspace
* $90-$9F Network workspace
@ -19,27 +17,28 @@ FSFLAG1 EQU $E2
FSFLAG2 EQU $E3
GSFLAG EQU $E4
GSCHAR EQU $E5
OSTEXT EQU $E6
OSTEXT EQU $E6 ; $E6 => text string
MAXLEN EQU OSTEXT+2 ; $E8
MINCHAR EQU OSTEXT+3 ; $E9
MAXCHAR EQU OSTEXT+4 ; $EA
OSTEMP EQU $EB
OSKBD1 EQU $EC ; Kbd workspace
OSKBD2 EQU $ED
OSKBD3 EQU $EE
OSAREG EQU $EF
OSXREG EQU OSAREG+1 ; $F0
OSYREG EQU OSXREG+1 ; $F1
OSCTRL EQU OSXREG
OSLPTR EQU $F2
*
OSINTWS EQU $FA ; IRQ ZP pointer
OSINTA EQU $FC ; IRQ A-reg store
FAULT EQU $FD ; Error message pointer
ESCFLAG EQU $FF ; Escape status
OSTEMP EQU $EB ; $EB
OSKBD1 EQU $EC ; $EC kbd ws
OSKBD2 EQU OSKBD1+1 ; $ED kbd ws
OSKBD3 EQU OSKBD1+2 ; $EE kbd ws
OSAREG EQU $EF ; $EF A register
OSXREG EQU OSAREG+1 ; $F0 X register
OSYREG EQU OSXREG+1 ; $F1 Y register
OSCTRL EQU OSXREG ; $F0 (XY)=>control block
OSLPTR EQU $F2 ; $F2 => command line
;
OSINTWS EQU $FA ; $FA IRQ ZP pointer, use when IRQs off
OSINTA EQU $FC ; $FC IRQ register A store
FAULT EQU $FD ; $FD Error message pointer
ESCFLAG EQU $FF ; $FF Escape status
* $0200-$0235 Vectors
* $0236-$028F OSBYTE variables
* $0236-$028F OSBYTE variable
* $0290-$02ED
* $02EE-$02FF MOS control block
@ -61,3 +60,4 @@ FSCV EQU $21E ; FSCV misc file ops
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
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 .
rm _FileInformation.txt
cadius clearhighbit ${file}.S\#040000

View File

@ -110,3 +110,5 @@ START STZ :BLOCKS
: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
DW $0000