Removed temporary 'jgh' subdir

This commit is contained in:
Bobbi Webber-Manners 2021-08-09 21:23:14 -04:00
parent 55633be799
commit 62be805a80
11 changed files with 0 additions and 3272 deletions

View File

@ -1,164 +0,0 @@
* Load an Acorn BBC Micro ROM in aux memory and
* Provide an environment where it can run
* (c) Bobbi 2021 GPLv3
*
* Assembled with the Merlin 8 assembler.
XC ; 65c02
ORG $2000 ; Load addr of loader in main memory
* Monitor routines
BELL EQU $FBDD
PRBYTE EQU $FDDA
COUT1 EQU $FDED
CROUT EQU $FD8E
AUXMOVE EQU $C311
XFER EQU $C314
* Monitor ZP locations
A1L EQU $3C
A1H EQU $3D
A2L EQU $3E
A2H EQU $3F
A4L EQU $42
A4H EQU $43
* Used by XFER
STRTL EQU $3ED
STRTH EQU $3EE
* Reset vector (2 bytes + 1 byte checksum)
RSTV EQU $3F2
* IRQ vector
A2IRQV EQU $3FE
* MLI entry point
MLI EQU $BF00
* ProDOS MLI command numbers
QUITCMD EQU $65
GTIMECMD EQU $82
CREATCMD EQU $C0
DESTCMD EQU $C1
ONLNCMD EQU $C5
SPFXCMD EQU $C6
GPFXCMD EQU $C7
OPENCMD EQU $C8
READCMD EQU $CA
WRITECMD EQU $CB
CLSCMD EQU $CC
FLSHCMD EQU $CD
SMARKCMD EQU $CE
GMARKCMD EQU $CF
GEOFCMD EQU $D1
* IO Buffer for reading file (1024 bytes)
IOBUF0 EQU $4000 ; For loading ROM, OSFILE, *.
IOBUF1 EQU $4400 ; Four open files for langs
IOBUF2 EQU $4800
IOBUF3 EQU $4C00
IOBUF4 EQU $5000
* 512 byte buffer sufficient for one disk block
BLKBUF EQU $5200
BLKBUFEND EQU $5400
* Address in aux memory where ROM will be loaded
AUXADDR EQU $8000
* Address in aux memory where the MOS shim is located
AUXMOS1 EQU $2000 ; Temp staging area in Aux
EAUXMOS1 EQU $3000 ; End of staging area
AUXMOS EQU $D000 ; Final location in aux LC
* Macro for calls from aux memory to main memory
XFMAIN MAC
CLC ; Use main memory
CLV ; Use main ZP and LC
JMP XFER
EOM
* Called by code running in main mem to invoke a
* routine in aux memory
XF2AUX MAC
PHA
LDA $C08B ; R/W LC RAM, bank 1
LDA $C08B
LDA #<]1
STA STRTL
LDA #>]1
STA STRTH
PLA
SEC ; Use aux memory
BIT $FF58 ; Set V: use alt ZP and LC
JMP XFER
EOM
* Called by code running in aux mem to invoke a
* routine in main memory
XF2MAIN MAC
TSX
STX $0101 ; Save alt SP
PHA
LDA STRTL
STA STRTBCKL
LDA STRTH
STA STRTBCKH
LDA #<]1
STA STRTL
LDA #>]1
STA STRTH
PLA
CLC ; Use main mem
CLV ; Use main ZP and LC
JMP XFER
EOM
* Macro called on re-entry to aux memory
ENTAUX MAC
LDX $0101 ; Recover alt SP
TXS
PHA
LDA STRTBCKL
STA STRTL
LDA STRTBCKH
STA STRTH
PLA
EOM
* Macro called on re-entry to main memory
ENTMAIN MAC
LDX $0100 ; Recover SP
TXS
PHA ; Preserve parm in A
LDA $C081 ; Bank in ROM
LDA $C081
PLA
EOM
* Enable writing to main memory (for code running in aux)
WRTMAIN MAC
SEI ; Keeps IRQ handler easy
STA $C004 ; Write to main memory
EOM
* Go back to writing to aux (for code runnign in aux)
WRTAUX MAC
STA $C005 ; Write to aux memory
CLI ; Normal service resumed
EOM
* Code is all included from PUT files below ...
* ... order matters!
PUT LOADER
PUT MAINMEM
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,384 +0,0 @@
* 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

@ -1,181 +0,0 @@
*********************************************************
* Kernel / Misc
*********************************************************
* KERNEL/CHARIO.S
*****************
* Character read and write
*
* OSWRCH handler
* All registers preserved
WRCHHND PHA
PHX
PHY
* TODO Check any output redirections
* TODO Check any spool output
JSR OUTCHAR
* TODO Check any printer output
PLY
PLX
PLA
RTS
* OSRDCH handler
* All registers preserved except A, Carry
* Read a character from the keyboard
RDCHHND PHX
PHY
JSR GETCHRC
STA OLDCHAR
:L1 LDA CURS+1 ; Skip unless CURS=$8000
CMP #$80
BNE :S1
LDA CURS
BNE :S1
STZ CURS
STZ CURS+1
LDA CSTATE
ROR
BCS :S2
LDA #'_'
BRA :S3
:S2 LDA OLDCHAR
:S3 JSR PRCHRC
INC CSTATE
:S1 INC CURS
BNE :S4
INC CURS+1
:S4 LDA $C000 ; Keyboard data/strobe
BPL :L1
LDA OLDCHAR ; Erase cursor
JSR PRCHRC
LDA $C000
AND #$7F
STA $C010 ; Clear strobe
PLY
PLX
CMP #$1B ; Escape pressed?
BNE :S5
SEC ; Return CS
ROR ESCFLAG
SEC
RTS
:S5 CLC
RTS
CURS DW $0000 ; Counter
CSTATE DB $00 ; Cursor on or off
OLDCHAR DB $00 ; Char under cursor
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
* CS, Y=$FF - timeout
* CS, Y=$1B - escape
GETKEY TYA
BMI NEGKEY ; Negative INKEY
:L1 CPX #$00
BEQ :S1
LDA $C000 ; Keyb data/strobe
AND #$80
BNE :GOTKEY
JSR DELAY ; 1/100 sec
DEX
BRA :L1
:S1 CPY #$00
BEQ :S2
DEY
LDX #$FF
BRA :L1
:S2 LDA $C000 ; Keyb data/strobe
AND #$80
BNE :GOTKEY
LDY #$FF ; No key, time expired
SEC
RTS
:GOTKEY LDA $C000 ; Fetch char
AND #$7F
STA $C010 ; Clear strobe
CMP #27 ; Escape
BEQ :ESC
TAX
LDY #$00
CLC
RTS
:ESC ROR ESCFLAG
LDY #27 ; Escape
SEC
RTS
NEGKEY LDX #$00 ; Unimplemented
LDY #$00
RTS
* KERNEL/KEYBOARD.S
*******************
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
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
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

View File

@ -1,437 +0,0 @@
* 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

@ -1,143 +0,0 @@
***********************************************************
* BBC Micro 'virtual machine' in Apple //e aux memory
***********************************************************
ZP1 EQU $90 ; $90-$9f are Econet space
; so safe to use
ZP2 EQU $92
ZP3 EQU $94
ROW EQU $96 ; Cursor row
COL EQU $97 ; Cursor column
STRTBCKL EQU $9D
STRTBCKH EQU $9E
WARMSTRT EQU $9F ; Cold or warm start
MAGIC EQU $BC ; Arbitrary value
MOSSHIM
ORG AUXMOS ; MOS shim implementation
*
* Shim code to service Acorn MOS entry points using
* Apple II monitor routines
* This code is initially loaded into aux mem at AUXMOS1
* Then relocated into aux LC at AUXMOS by MOSINIT
*
* Initially executing at $3000 until copied to $D000
MOSINIT STA $C005 ; Make sure we are writing aux
STA $C000 ; Make sure 80STORE is off
LDA $C08B ; LC RAM Rd/Wt, 1st 4K bank
LDA $C08B
LDA WARMSTRT ; Don't relocate on restart
CMP #MAGIC
BEQ :NORELOC
LDA #<AUXMOS1 ; Relocate MOS shim
STA A1L
LDA #>AUXMOS1
STA A1H
LDA #<EAUXMOS1
STA A2L
LDA #>EAUXMOS1
STA A2H
LDA #<AUXMOS
STA A4L
LDA #>AUXMOS
STA A4H
:L1 LDA (A1L)
STA (A4L)
LDA A1H
CMP A2H
BNE :S1
LDA A1L
CMP A2L
BNE :S1
BRA :S4
:S1 INC A1L
BNE :S2
INC A1H
:S2 INC A4L
BNE :S3
INC A4H
:S3 BRA :L1
:S4 LDA #<MOSVEC-MOSINIT+AUXMOS1
STA A1L
LDA #>MOSVEC-MOSINIT+AUXMOS1
STA A1H
LDA #<MOSVEND-MOSINIT+AUXMOS1
STA A2L
LDA #>MOSVEND-MOSINIT+AUXMOS1
STA A2H
LDA #<MOSAPI
STA A4L
LDA #>MOSAPI
STA A4H
:L2 LDA (A1L)
STA (A4L)
LDA A1H
CMP A2H
BNE :S5
LDA A1L
CMP A2L
BNE :S5
BRA :S8
:S5 INC A1L
BNE :S6
INC A1H
:S6 INC A4L
BNE :S7
INC A4H
:S7 BRA :L2
:NORELOC
:S8 STA $C00D ; 80 col on
STA $C003 ; Alt charset off
STA $C055 ; PAGE2
STZ ROW
STZ COL
JSR CLEAR
STZ ESCFLAG
LDX #$35
:INITPG2 LDA DEFVEC,X
STA $200,X
DEX
BPL :INITPG2
LDA #<:HELLO
LDY #>:HELLO
JSR PRSTR
LDA #$09 ; Print language name at $8009
LDY #$80
JSR PRSTR
JSR OSNEWL
JSR OSNEWL
LDA WARMSTRT
CMP #MAGIC
BNE :S9
LDA #<:OLDM
LDY #>:OLDM
JSR PRSTR
:S9 LDA #MAGIC ; So we do not reloc again
STA WARMSTRT
CLC ; CLC=Entered from RESET
LDA #$01 ; $01=Entering application code
JMP AUXADDR ; Start Acorn ROM
* No return
:HELLO ASC 'Applecorn MOS v0.01'
DB $0D,$0D,$00
:OLDM ASC '(Use OLD to recover any program)'
DB $0D,$0D,$00

View File

@ -1,438 +0,0 @@
*********************************************************
* AppleMOS Kernel
*********************************************************
* 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
LDA #$01
JMP AUXADDR
* 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
STY ZP1+1
:L1 LDA (ZP1)
CMP #'*' ; Trim any leading stars
BEQ :NEXT
CMP #' ' ; Trim any leading spaces
BEQ :NEXT
BRA :TRIMMED
:NEXT INC ZP1
BNE :L1
INC ZP1+1
BRA :L1
:TRIMMED CMP #'|' ; | is comment
BEQ :IEXIT
CMP #$0D ; Carriage return
BEQ :IEXIT
LDA #<:QUIT
STA ZP2
LDA #>:QUIT
STA ZP2+1
JSR STRCMP
BCS :S1
JSR STARQUIT
BRA :IEXIT
:S1 LDA #<:CAT
STA ZP2
LDA #>:CAT
STA ZP2+1
JSR STRCMP
BCS :S2
JSR STARCAT
BRA :IEXIT
:S2 LDA #<:CAT2
STA ZP2
LDA #>:CAT2
STA ZP2+1
JSR STRCMP
BCS :S3
JSR STARCAT
BRA :IEXIT
:S3 LDA #<:DIR
STA ZP2
LDA #>:DIR
STA ZP2+1
JSR STRCMP
BCS :S4
JSR STARDIR
BRA :IEXIT
:S4 LDA #<:LOAD
STA ZP2
LDA #>:LOAD
STA ZP2+1
JSR STRCMP
BCS :S5
JSR STARLOAD
BRA :EXIT
:S5 LDA #<:SAVE
STA ZP2
LDA #>:SAVE
STA ZP2+1
JSR STRCMP
BCS :S6
JSR STARSAVE
:IEXIT BRA :EXIT
:S6 LDA #<:RUN
STA ZP2
LDA #>:RUN
STA ZP2+1
JSR STRCMP
BCS :S7
JSR STARRUN
BRA :EXIT
:S7 LDA #<:HELP
STA ZP2
LDA #>:HELP
STA ZP2+1
JSR STRCMP
BCS :ASKROM
JSR STARHELP
BRA :EXIT
: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 return
BEQ :EXIT ; Call claimed
:UNSUPP LDA #<:OSCLIM
LDY #>:OSCLIM
JSR PRSTR
PLY
PLX
STX ZP3
STY ZP3+1
LDY #$00
:PL1 LDA (ZP3),Y
CMP #$0D
BEQ :PS1
CMP #$00
BEQ :PS1
JSR $FFEE ; OSWRCH
INY
BRA :PL1
:PS1 LDA #<:OSCLIM2
LDY #>:OSCLIM2
JSR PRSTR
RTS
:EXIT PLY
PLX
RTS
:QUIT ASC 'QUIT'
DB $00
:CAT ASC 'CAT'
DB $00
:CAT2 ASC '.'
DB $00
:DIR ASC 'DIR'
DB $00
:LOAD ASC 'LOAD'
DB $00
:SAVE ASC 'SAVE'
DB $00
:RUN ASC 'RUN'
DB $00
:HELP ASC 'HELP'
DB $00
:OSCLIM ASC 'OSCLI('
DB $00
:OSCLIM2 ASC ').'
DB $00
* String comparison for OSCLI
* Compares str in ZP1 with null-terminated str in ZP2
* Clear carry if match, set carry otherwise
* Leaves (ZP1),Y pointing to char after verb
STRCMP LDY #$00
:L1 LDA (ZP2),Y
BEQ :PMATCH
CMP (ZP1),Y
BNE :MISMTCH
INY
BRA :L1
:PMATCH LDA (ZP1),Y
CMP #$0D
BEQ :MATCH
CMP #' '
BEQ :MATCH
CMP #'"'
BEQ :MATCH
BRA :MISMTCH
:MATCH CLC
RTS
:MISMTCH SEC
RTS
* Print *HELP test
STARHELP LDA #<:MSG
LDY #>:MSG
JSR PRSTR
LDA #$09 ; Language name
LDY #$80
JSR PRSTR
LDA #<:MSG2
LDY #>:MSG2
JSR PRSTR
RTS
:MSG DB $0D
ASC 'Applecorn MOS v0.01'
DB $0D,$0D,$00
:MSG2 DB $0D,$00
* Handle *QUIT command
STARQUIT >>> XF2MAIN,QUIT
* Handle *CAT / *. command (list directory)
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
BEQ :START
CMP #'"' ; Or quote mark
BEQ :START
BRA :NOTFND
:START INY
:L1 LDA (ZP1),Y ; Eat any additional ...
CMP #' ' ; ... spaces
BEQ :CONT
CMP #'"' ; Or quote marks
BNE :DONE
:CONT INY
BRA :L1
:DONE CLC
RTS
:NOTFND SEC
RTS
* Consume chars in command line until space or " is found
* Command line pointer in (ZP1),Y
* Returns with carry set if EOL
EATWORD LDA (ZP1),Y
CMP #' '
BEQ :SPC
CMP #'"'
BEQ :SPC
CMP #$0D ; Carriage return
BEQ :EOL
INY
BRA EATWORD
:SPC CLC
RTS
:EOL SEC
RTS
* Add Y to ZP1 pointer. Clear Y.
ADDZP1Y CLC
TYA
ADC ZP1
STA ZP1
LDA #$00
ADC ZP1+1
STA ZP1+1
LDY #$00
RTS
* Decode ASCII hex digit in A
* Returns with carry set if bad char, C clear otherwise
HEXDIGIT CMP #'F'+1
BCS :BADCHAR ; char > 'F'
CMP #'A'
BCC :S1
SEC ; 'A' <= char <= 'F'
SBC #'A'-10
CLC
RTS
:S1 CMP #'9'+1
BCS :BADCHAR ; '9' < char < 'A'
CMP #'0'
BCC :BADCHAR ; char < '0'
SEC ; '0' <= char <= '9'
SBC #'0'
CLC
RTS
:BADCHAR SEC
RTS
* Decode hex constant on command line
* On entry, ZP1 points to command line
HEXCONST LDX #$00
: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
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
BEQ :OK
CMP #$0D
BEQ :OK
:ERR SEC
RTS
:OK LDA :BUF-4,X
ASL
ASL
ASL
ASL
ORA :BUF-3,X
STA ADDRBUF+1
LDA :BUF-2,X
ASL
ASL
ASL
ASL
ORA :BUF-1,X
STA ADDRBUF
CLC
RTS
:ZEROPAD DB $00,$00,$00
:BUF DB $00,$00,$00,$00
ADDRBUF DW $0000 ; Used by HEXCONST
* Handle *LOAD command
* On entry, ZP1 points to command line
STARLOAD JSR CLRCB
JSR EATSPC ; Eat leading spaces
BCS :ERR
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
INY
JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1
JSR HEXCONST
BCS :ERR ; Bad hex constant
LDA ADDRBUF
STA OSFILECB+2 ; Load address LSB
LDA ADDRBUF+1
STA OSFILECB+3 ; Load address MSB
:OSFILE LDX #<OSFILECB
LDY #>OSFILECB
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
BRA :OSFILE
:ERR JSR BEEP
RTS
* Handle *SAVE command
* On entry, ZP1 points to command line
STARSAVE JSR CLRCB
JSR EATSPC ; Eat leading space
BCS :ERR
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
INY
JSR EATSPC ; Eat any whitespace
JSR ADDZP1Y ; Update ZP1
JSR HEXCONST
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 HEXCONST
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
JSR OSFILE
:END RTS
:ERR JSR BEEP
RTS
* Handle *RUN command
* On entry, ZP1 points to command line
STARRUN JSR ADDZP1Y
LDX ZP1+0
LDY ZP1+1
LDA #$04
CALLFSCV JMP (FSCV) ; Hand on to filing system
* Clear OSFILE control block to zeros
CLRCB LDA #$00
LDX #$00
:L1 STA OSFILECB,X
INX
CPX #18
BNE :L1
RTS

View File

@ -1,282 +0,0 @@
* 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
LDX #$80
: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 ; Store A in $45 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
*
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
* 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,61 +0,0 @@
* MOSEQU.S
*******************************
* BBC MOS WORKSPACE LOCATIONS *
*******************************
* $00-$8F Language workspace
* $90-$9F Network workspace
* $A0-$A7 NMI workspace
* $A8-$AF Non-MOS *command workspace
* $B0-$BF Temporary filing system workspace
* $C0-$CF Persistant filing system workspace
* $D0-$DF VDU driver workspace
* $E0-$EE Internal MOS workspace
* $EF-$FF MOS API workspace
FSFLAG1 EQU $E2
FSFLAG2 EQU $E3
GSFLAG EQU $E4
GSCHAR EQU $E5
OSTEXT EQU $E6 ; $E6 => text string
MAXLEN EQU OSTEXT+2 ; $E8
MINCHAR EQU OSTEXT+3 ; $E9
MAXCHAR EQU OSTEXT+4 ; $EA
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 variable
* $0290-$02ED
* $02EE-$02FF MOS control block
USERV EQU $200 ; USER vector
BRKV EQU $202 ; BRK vector
CLIV EQU $208 ; OSCLI vector
BYTEV EQU $20A ; OSBYTE vector
WORDV EQU $20C ; OSWORD vector
WRCHV EQU $20E ; OSWRCH vector
RDCHV EQU $210 ; OSRDCH vector
FILEV EQU $212 ; OSFILE vector
ARGSV EQU $214 ; OSARGS vector
BGETV EQU $216 ; OSBGET vector
BPUTV EQU $218 ; OSBPUT vector
GBPBV EQU $21A ; OSGBPB vector
FINDV EQU $21C ; OSFIND vector
FSCV EQU $21E ; FSCV misc file ops
OSFILECB EQU $2EE ; OSFILE control block

View File

@ -1,327 +0,0 @@
* 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
; TAY
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
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 :IDONE
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 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
BEQ :T7A
CMP #$16
BNE :T8
LDA VDUQ+8
EOR #$07
AND #$01
TAX
STA $C00C,X
:T7A JSR CLEAR
BRA :DONE
:T8 CMP #$1E ; Home
BNE :T9
STZ ROW
STZ COL
BRA :DONE
:T9 CMP #$7F ; Delete
BNE :T10
JSR DELETE
BRA :DONE
:T10 CMP #$20
BCC :DONE
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
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

View File

@ -1,112 +0,0 @@
* LOADER.S
* (c) Bobbi 2021 GPLv3
*
* Applecorn loader code
* Loads Acorn ROM file (16KB) from disk and writes it
* to aux memory starting at $08000. Copies Applecorn MOS
* to aux memory starting at AUXMOS1 and jumps to it.
* (Note that the MOS code will relocate itself to $D000.)
START STZ :BLOCKS
LDX #$00
:L1 LDA HELLO,X ; Signon message
BEQ :S1
JSR COUT1
INX
BRA :L1
:S1 JSR CROUT
JSR SETPRFX
JSR DISCONN
STA $C009 ; Alt ZP on
STZ $9F ; WARMSTRT - set cold!
STA $C008 ; Alt ZP off
LDA #<ROMFILE
STA OPENPL+1
LDA #>ROMFILE
STA OPENPL+2
JSR OPENFILE ; Open ROM file
BCC :S2
LDX #$00
:L2 LDA CANTOPEN,X
BEQ :ER1
JSR COUT1
INX
BRA :L2
BRA :S2
:ER1 JSR CROUT
JSR BELL
RTS
:S2 LDA OPENPL+5 ; File reference number
STA READPL+1
:L3 LDA #'.'+$80 ; Read file block by block
JSR COUT1
JSR RDFILE
BCS :S3 ; EOF (0 bytes left) or some error
LDA #<BLKBUF ; Source start addr -> A1L,A1H
STA A1L
LDA #>BLKBUF
STA A1H
LDA #<BLKBUFEND ; Source end addr -> A2L,A2H
STA A2L
LDA #>BLKBUFEND
STA A2H
LDA #<AUXADDR ; Dest in aux -> A4L, A4H
STA A4L
LDA #>AUXADDR
LDX :BLOCKS
:L4 CPX #$00
BEQ :S25
INC
INC
DEX
BRA :L4
:S25 STA A4H
SEC ; Copy Main -> Aux
JSR AUXMOVE
INC :BLOCKS
BRA :L3
:S3 LDA OPENPL+5 ; File reference number
STA CLSPL+1
JSR CLSFILE
LDA #<MOSSHIM ; Start address of MOS shim
STA A1L
LDA #>MOSSHIM
STA A1H
LDA #<MOSSHIM+$1000 ; End address of MOS shim
STA A2L
LDA #>MOSSHIM+$1000
STA A2H
LDA #<AUXMOS1 ; To AUXMOS1 in aux memory
STA A4L
LDA #>AUXMOS1
STA A4H
SEC ; Copy MOS from Main->Aux
JSR AUXMOVE
LDA #<RESET ; Set reset vector->RESET
STA RSTV
LDA #>RESET
STA RSTV+1
EOR #$A5 ; Checksum
STA RSTV+2
TSX ; Save SP at $0100
STX $0100
>>> XF2AUX,AUXMOS1
:BLOCKS DB 0 ; Counter for blocks read

View File

@ -1,743 +0,0 @@
* MAINMEM.S
* (c) Bobbi 2021 GPL v3
*
* Code that runs on the Apple //e in main memory.
* This code is mostly glue between the BBC Micro code
* which runs in aux mem and Apple II ProDOS.
* Trampoline in main memory used by aux memory IRQ handler
* to invoke Apple II / ProDOS IRQs in main memory
A2IRQ >>> ENTMAIN
JSR A2IRQ2
>>> XF2AUX,IRQBRKRET
A2IRQ2 PHP ; Fake things to look like IRQ
JMP (A2IRQV) ; Call Apple II ProDOS ISR
* Set prefix if not already set
SETPRFX LDA #GPFXCMD
STA :OPC7 ; Initialize cmd byte to $C7
:L1 JSR MLI
:OPC7 DB $00
DW GSPFXPL
LDX $0300
BNE RTSINST
LDA $BF30
STA ONLPL+1 ; Device number
JSR MLI
DB ONLNCMD
DW ONLPL
LDA $0301
AND #$0F
TAX
INX
STX $0300
LDA #$2F
STA $0301
DEC :OPC7
BNE :L1
RTSINST RTS
* Disconnect /RAM ramdrive to avoid aux corruption
* Stolen from Beagle Bros Extra K
DISCONN LDA $BF98
AND #$30
CMP #$30
BNE :S1
LDA $BF26
CMP $BF10
BNE :S2
LDA $BF27
CMP $BF11
BEQ :S1
:S2 LDY $BF31
:L1 LDA $BF32,Y
AND #$F3
CMP #$B3
BEQ :S3
DEY
BPL :L1
BMI :S1
:S3 LDA $BF32,Y
STA $0302
:L2 LDA $BF33,Y
STA $BF32,Y
BEQ :S4
INY
BNE :L2
:S4 LDA $BF26
STA $0300
LDA $BF27
STA $0301
LDA $BF10
STA $BF26
LDA $BF11
STA $BF27
DEC $BF31
:S1 RTS
* Reset handler - invoked on Ctrl-Reset
* XFER to AUXMOS ($C000) in aux, AuxZP on, LC on
RESET TSX
STX $0100
>>> XF2AUX,AUXMOS
RTS
* Copy 512 bytes from BLKBUF to AUXBLK in aux LC
COPYAUXBLK
LDA $C08B ; R/W LC RAM, bank 1
LDA $C08B
STA $C009 ; Alt ZP (and Alt LC) on
LDY #$00
:L1 LDA BLKBUF,Y
STA $C005 ; Write aux mem
STA AUXBLK,Y
STA $C004 ; Write main mem
CPY #$FF
BEQ :S1
INY
BRA :L1
:S1 LDY #$00
:L2 LDA BLKBUF+$100,Y
STA $C005 ; Write aux mem
STA AUXBLK+$100,Y
STA $C004 ; Write main mem
CPY #$FF
BEQ :S2
INY
BRA :L2
:S2 STA $C008 ; Alt ZP off
LDA $C081 ; Bank the ROM back in
LDA $C081
RTS
* ProDOS file handling for MOS OSFIND OPEN call
* Options in A: $40 'r', $80 'w', $C0 'rw'
OFILE >>> ENTMAIN
PHA ; Preserve arg for later
CMP #$80 ; Write mode
BNE :S0
LDA #<MOSFILE ; Attempt to destroy file
STA DESTPL+1
LDA #>MOSFILE
STA DESTPL+2
JSR MLI
DB DESTCMD
DW DESTPL
LDA #<MOSFILE ; Attempt to create file
STA CREATEPL+1
STA OPENPL+1
LDA #>MOSFILE
STA CREATEPL+2
STA OPENPL+2
LDA #$C3 ; Access unlocked
STA CREATEPL+3
LDA #$06 ; Filetype BIN
STA CREATEPL+4
LDA #$00 ; Auxtype
STA CREATEPL+5
LDA #$00
STA CREATEPL+6
LDA #$01 ; Storage type - file
STA CREATEPL+7
LDA $BF90 ; Current date
STA CREATEPL+8
LDA $BF91
STA CREATEPL+9
LDA $BF92 ; Current time
STA CREATEPL+10
LDA $BF93
STA CREATEPL+11
JSR CRTFILE
:S0 LDA #$00 ; Look for empty slot
JSR FINDBUF
STX BUFIDX
CPX #$00
BNE :S1
LDA #<IOBUF1
LDY #>IOBUF1
BRA :S4
:S1 CPX #$01
BNE :S2
LDA #<IOBUF2
LDY #>IOBUF2
BRA :S4
:S2 CPX #$02
BNE :S3
LDA #<IOBUF3
LDY #>IOBUF3
BRA :S4
:S3 CPX #$03
BNE :NOTFND ; Out of buffers really
LDA #<IOBUF4
LDY #>IOBUF4
:S4 STA OPENPL2+3
STY OPENPL2+4
LDA #<MOSFILE
STA OPENPL2+1
LDA #>MOSFILE
STA OPENPL2+2
JSR MLI
DB OPENCMD
DW OPENPL2
BCS :NOTFND
LDA OPENPL2+5 ; File ref number
LDX BUFIDX
CPX #$FF
BEQ FINDEXIT
STA FILEREFS,X ; Record the ref number
BRA FINDEXIT
:NOTFND LDA #$00
FINDEXIT >>> XF2AUX,OSFINDRET
BUFIDX DB $00
* ProDOS file handling for MOS OSFIND CLOSE call
CFILE >>> ENTMAIN
LDA MOSFILE ; File ref number
STA CLSPL+1
JSR CLSFILE
LDA MOSFILE
JSR FINDBUF
CPX #$FF
BEQ :S1
LDA #$00
STA FILEREFS,X
:S1 JMP FINDEXIT
* Map of file reference numbers to IOBUF1..4
FILEREFS DB $00,$00,$00,$00
* Search FILEREFS for value in A
FINDBUF LDX #$00
:L1 CMP FILEREFS,X
BEQ :END
INX
CPX #$04
BNE :L1
LDX #$FF ; $FF for not found
:END RTS
* ProDOS file handling for MOS OSBGET call
* Returns with char read in A and error num in Y (or 0)
FILEGET >>> ENTMAIN
LDA MOSFILE ; File ref number
STA READPL2+1
JSR MLI
DB READCMD
DW READPL2
BCC :NOERR
TAY ; Error number in Y
BRA :EXIT
:NOERR LDY #$00
LDA BLKBUF
:EXIT >>> XF2AUX,OSBGETRET
* ProDOS file handling for MOS OSBPUT call
* Enters with char to write in A
FILEPUT >>> ENTMAIN
STA BLKBUF ; Char to write
LDA MOSFILE ; File ref number
STA WRITEPL+1
LDA #$01 ; Bytes to write
STA WRITEPL+4
LDA #$00
STA WRITEPL+5
JSR WRTFILE
>>> XF2AUX,OSBPUTRET
* ProDOS file handling for OSBYTE $7F EOF
* Returns EOF status in A ($FF for EOF, $00 otherwise)
FILEEOF >>> ENTMAIN
LDA MOSFILE ; File ref number
STA GEOFPL+1
STA GMARKPL+1
JSR MLI
DB GEOFCMD
DW GEOFPL
BCS :ISEOF ; If error, just say EOF
JSR MLI
DB GMARKCMD
DW GMARKPL
BCS :ISEOF ; If error, just say EOF
LDA GEOFPL+2 ; Subtract Mark from EOF
SEC
SBC GMARKPL+2
STA :REMAIN
LDA GEOFPL+3
SBC GMARKPL+3
STA :REMAIN+1
LDA GEOFPL+4
SBC GMARKPL+4
STA :REMAIN+2
LDA :REMAIN ; Check bytes remaining
BNE :NOTEOF
LDA :REMAIN+1
BNE :NOTEOF
LDA :REMAIN+2
BNE :NOTEOF
:ISEOF LDA #$FF
BRA :EXIT
:NOTEOF LDA #$00
:EXIT >>> XF2AUX,CHKEOFRET
:REMAIN DS 3 ; Remaining bytes
* ProDOS file handling for OSARGS flush commands
FLUSH >>> ENTMAIN
LDA MOSFILE ; File ref number
STA FLSHPL+1
JSR MLI
DB FLSHCMD
DW FLSHPL
>>> XF2AUX,OSARGSRET
* ProDOS file handling for OSARGS set ptr command
SEEK >>> ENTMAIN
LDA MOSFILE ; File ref number
STA GMARKPL+1 ; GET_MARK has same params
LDA MOSFILE+2 ; Desired offset in MOSFILE[2..4]
STA GMARKPL+2
LDA MOSFILE+3
STA GMARKPL+3
LDA MOSFILE+4
STA GMARKPL+4
JSR MLI
DB SMARKCMD
DW GMARKPL
>>> XF2AUX,OSARGSRET
* ProDOS file handling for OSARGS get ptr command
* and for OSARGs get length command
TELL >>> ENTMAIN
LDA MOSFILE ; File ref number
STA GMARKPL+1
LDA MOSFILE+2 ; Mode (0=pos, otherwise len)
CMP #$00
BEQ :POS
JSR MLI
DB GEOFCMD
DW GMARKPL ; MARK parms same as EOF parms
BRA :S1
:POS JSR MLI
DB GMARKCMD
DW GMARKPL
:S1 LDX MOSFILE+1 ; Pointer to ZP control block
BCS :ERR
LDA $C08B ; R/W LC RAM, bank 1
LDA $C08B
STA $C009 ; Alt ZP on
LDA GMARKPL+2
STA $00,X
LDA GMARKPL+3
STA $01,X
LDA GMARKPL+4
STA $02,X
STZ $03,X
STA $C008 ; Alt ZP off
LDA $C081 ; Bank the ROM back in
LDA $C081
:EXIT >>> XF2AUX,OSARGSRET
:ERR LDX MOSFILE+1 ; Address of ZP control block
LDA $C08B
LDA $C08B
STA $C009
STZ $00,X
STZ $01,X
STZ $02,X
STZ $03,X
STZ $C008
LDA $C081
LDA $C081
BRA :EXIT
* ProDOS file handling for MOS OSFILE LOAD call
* Return A=0 if successful
* A=1 if file not found
* A=2 if read error
LOADFILE >>> ENTMAIN
STZ :BLOCKS
LDA #<MOSFILE
STA OPENPL+1
LDA #>MOSFILE
STA OPENPL+2
JSR OPENFILE
BCS :NOTFND ; File not found
:L1 LDA OPENPL+5 ; File ref number
STA READPL+1
JSR RDFILE
BCC :S1
CMP #$4C ; EOF
BEQ :EOF
BRA :READERR
:S1 LDA #<BLKBUF
STA A1L
LDA #>BLKBUF
STA A1H
LDA #<BLKBUFEND
STA A2L
LDA #>BLKBUFEND
STA A2H
LDA FBEXEC ; If FBEXEC is zero, use addr
CMP #$00 ; in the control block
BEQ :CBADDR
; Otherwise use the file addr
* TODO Issue GET_FILE_INFO MLI call to get file load addr
:CBADDR LDA FBLOAD
STA A4L
LDA FBLOAD+1
LDX :BLOCKS
:L2 CPX #$00
BEQ :S2
INC
INC
DEX
BRA :L2
:S2 STA A4H
SEC ; Main -> AUX
JSR AUXMOVE
INC :BLOCKS
BRA :L1
:NOTFND LDA #$01 ; Nothing found
PHA
BRA :EXIT
:READERR LDA #$02 ; Read error
BRA :EOF2
:EOF LDA #$00 ; Success
:EOF2 LDA OPENPL+5 ; File ref num
STA CLSPL+1
JSR CLSFILE
:EXIT >>> XF2AUX,OSFILERET
:BLOCKS DB $00
* ProDOS file handling for MOS OSFILE SAVE call
* Return A=0 if successful
* A=1 if unable to create/open
* A=2 if error during save
SAVEFILE >>> ENTMAIN
LDA #<MOSFILE ; Attempt to destroy file
STA DESTPL+1
LDA #>MOSFILE
STA DESTPL+2
JSR MLI
DB DESTCMD
DW DESTPL
STZ :BLOCKS
LDA #<MOSFILE
STA CREATEPL+1
STA OPENPL+1
LDA #>MOSFILE
STA CREATEPL+2
STA OPENPL+2
LDA #$C3 ; Access unlocked
STA CREATEPL+3
LDA #$06 ; Filetype BIN
STA CREATEPL+4
LDA FBLOAD ; Auxtype = load address
STA CREATEPL+5
LDA FBLOAD+1
STA CREATEPL+6
LDA #$01 ; Storage type - file
STA CREATEPL+7
LDA $BF90 ; Current date
STA CREATEPL+8
LDA $BF91
STA CREATEPL+9
LDA $BF92 ; Current time
STA CREATEPL+10
LDA $BF93
STA CREATEPL+11
JSR CRTFILE
BCS :FWD1 ; :CANTOPEN error
JSR OPENFILE
BCS :FWD1 ; :CANTOPEN error
SEC ; Compute file length
LDA FBEND
SBC FBSTRT
STA :LEN
LDA FBEND+1
SBC FBSTRT+1
STA :LEN+1
:L1 LDA FBSTRT ; Setup for first block
STA A1L
STA A2L
LDA FBSTRT+1
STA A1H
STA A2H
INC A2H ; $200 = 512 bytes
INC A2H
LDA OPENPL+5 ; File ref number
STA WRITEPL+1
LDA #$00 ; 512 byte request count
STA WRITEPL+4
LDA #$02
STA WRITEPL+5
LDX :BLOCKS
:L2 CPX #$00 ; Adjust for subsequent blks
BEQ :S1
INC A1H
INC A1H
INC A2H
INC A2H
DEX
BRA :L2
:FWD1 BRA :CANTOPEN ; Forwarding call from above
:S1 LDA :LEN+1 ; MSB of length remaining
CMP #$02
BCS :S2 ; MSB of len >= 2 (not last)
CMP #$00 ; If no bytes left ...
BNE :S3
LDA :LEN
BNE :S3
BRA :NORMALEND
:S3 LDA FBEND ; Adjust for last block
STA A2L
LDA FBEND+1
STA A2H
LDA :LEN
STA WRITEPL+4 ; Remaining bytes to write
LDA :LEN+1
STA WRITEPL+5
:S2 LDA #<BLKBUF
STA A4L
LDA #>BLKBUF
STA A4H
CLC ; Aux -> Main
JSR AUXMOVE
LDA OPENPL+5 ; File ref number
STA WRITEPL+1
JSR WRTFILE
BCS :WRITEERR
BRA :UPDLEN
:ENDLOOP INC :BLOCKS
BRA :L1
:UPDLEN SEC ; Update length remaining
LDA :LEN
SBC WRITEPL+4
STA :LEN
LDA :LEN+1
SBC WRITEPL+5
STA :LEN+1
BRA :ENDLOOP
:CANTOPEN
LDA #$01 ; Can't open/create
BRA :EXIT
:WRITEERR
LDA OPENPL+5 ; File ref num
STA CLSPL+1
JSR CLSFILE
LDA #$02 ; Write error
BRA :EXIT
:NORMALEND
LDA OPENPL+5 ; File ref num
STA CLSPL+1
JSR CLSFILE
LDA #$00 ; Success!
BCC :EXIT ; If close OK
LDA #$02 ; Write error
:EXIT >>> XF2AUX,OSFILERET
:LEN DW $0000
:BLOCKS DB $00
* Quit to ProDOS
QUIT INC $3F4 ; Invalidate powerup byte
STA $C054 ; PAGE2 off
JSR MLI
DB QUITCMD
DW QUITPL
RTS
* Obtain catalog of current PREFIX dir
CATALOG >>> ENTMAIN
JSR MLI ; Fetch prefix into BLKBUF
DB GPFXCMD
DW GPFXPL
BNE CATEXIT ; If prefix not set
LDA #<BLKBUF
STA OPENPL+1
LDA #>BLKBUF
STA OPENPL+2
JSR OPENFILE
BCS CATEXIT ; Can't open dir
CATREENTRY
LDA OPENPL+5 ; File ref num
STA READPL+1
JSR RDFILE
BCC :S1
CMP #$4C ; EOF
BEQ :EOF
BRA :READERR
:S1 JSR COPYAUXBLK
>>> XF2AUX,PRONEBLK
:READERR
:EOF LDA OPENPL+5 ; File ref num
STA CLSPL+1
JSR CLSFILE
CATEXIT >>> XF2AUX,STARCATRET
* PRONEBLK call returns here ...
CATALOGRET
>>> ENTMAIN
BRA CATREENTRY
* Set the prefix
SETPFX >>> ENTMAIN
JSR MLI
DB SPFXCMD
DW SPFXPL
BCC :S1
JSR BELL ; Beep on error
:S1 >>> XF2AUX,STARDIRRET
* Create disk file
CRTFILE JSR MLI
DB CREATCMD
DW CREATEPL
RTS
* Open disk file
OPENFILE JSR MLI
DB OPENCMD
DW OPENPL
RTS
* Close disk file
CLSFILE JSR MLI
DB CLSCMD
DW CLSPL
RTS
* Read 512 bytes into BLKBUF
RDFILE JSR MLI
DB READCMD
DW READPL
RTS
* Write data in BLKBUF to disk
WRTFILE JSR MLI
DB WRITECMD
DW WRITEPL
RTS
HELLO ASC "Applecorn - (c) Bobbi 2021 GPLv3"
HEX 00
CANTOPEN ASC "Unable to open BASIC.ROM"
HEX 00
ROMFILE STR "BASIC.ROM"
* ProDOS Parameter lists for MLI calls
OPENPL HEX 03 ; Number of parameters
DW $0000 ; Pointer to filename
DW IOBUF0 ; Pointer to IO buffer
DB $00 ; Reference number returned
OPENPL2 HEX 03 ; Number of parameters
DW $0000 ; Pointer to filename
DW $0000 ; Pointer to IO buffer
DB $00 ; Reference number returned
CREATEPL HEX 07 ; Number of parameters
DW $0000 ; Pointer to filename
DB $00 ; Access
DB $00 ; File type
DW $0000 ; Aux type
DB $00 ; Storage type
DW $0000 ; Create date
DW $0000 ; Create time
DESTPL HEX 01 ; Number of parameters
DW $0000 ; Pointer to filename
READPL HEX 04 ; Number of parameters
DB $00 ; Reference number
DW BLKBUF ; Pointer to data buffer
DW 512 ; Request count
DW $0000 ; Trans count
READPL2 HEX 04 ; Number of parameters
DB #00 ; Reference number
DW BLKBUF ; Pointer to data buffer
DW 1 ; Request count
DW $0000 ; Trans count
WRITEPL HEX 04 ; Number of parameters
DB $01 ; Reference number
DW BLKBUF ; Pointer to data buffer
DW $00 ; Request count
DW $0000 ; Trans count
CLSPL HEX 01 ; Number of parameters
DB $00 ; Reference number
FLSHPL HEX 01 ; Number of parameters
DB $00 ; Reference number
ONLPL HEX 02 ; Number of parameters
DB $00 ; Unit num
DW $301 ; Buffer
GSPFXPL HEX 01 ; Number of parameters
DW $300 ; Buffer
GPFXPL HEX 01 ; Number of parameters
DW BLKBUF ; Buffer
SPFXPL HEX 01 ; Number of parameters
DW MOSFILE ; Buffer
GMARKPL HEX 02 ; Number of parameters
DB $00 ; File reference number
DB $00 ; Mark (24 bit)
DB $00
DB $00
GEOFPL HEX 02 ; Number of parameters
DB $00 ; File reference number
DB $00 ; EOF (24 bit)
DB $00
DB $00
QUITPL HEX 04 ; Number of parameters
DB $00
DW $0000
DB $00
DW $0000
* Buffer for Acorn MOS filename
MOSFILE DS 64 ; 64 bytes max prefix/file len
* Acorn MOS format OSFILE param list
FILEBLK
FBPTR DW $0000 ; Pointer to name (in aux)
FBLOAD DW $0000 ; Load address
DW $0000
FBEXEC DW $0000 ; Exec address
DW $0000
FBSTRT DW $0000 ; Start address for SAVE
DW $0000
FBEND DW $0000 ; End address for SAVE
DW $0000