mirror of
https://github.com/bobbimanners/Applecorn.git
synced 2025-02-10 12:30:44 +00:00
Update from JGH. Doesn't build in Merlin-8 yet.
This commit is contained in:
parent
d31ea2636b
commit
3c1755ec08
164
jgh/applecorn.s
Normal file
164
jgh/applecorn.s
Normal file
@ -0,0 +1,164 @@
|
||||
* 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
|
384
jgh/auxmem.bytwrd.s
Normal file
384
jgh/auxmem.bytwrd.s
Normal file
@ -0,0 +1,384 @@
|
||||
* 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
|
||||
|
181
jgh/auxmem.chario.s
Normal file
181
jgh/auxmem.chario.s
Normal file
@ -0,0 +1,181 @@
|
||||
*********************************************************
|
||||
* 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
|
||||
|
437
jgh/auxmem.hostfs.s
Normal file
437
jgh/auxmem.hostfs.s
Normal file
@ -0,0 +1,437 @@
|
||||
* 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
|
||||
|
143
jgh/auxmem.init.s
Normal file
143
jgh/auxmem.init.s
Normal file
@ -0,0 +1,143 @@
|
||||
***********************************************************
|
||||
* 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
|
||||
|
438
jgh/auxmem.kernel.s
Normal file
438
jgh/auxmem.kernel.s
Normal file
@ -0,0 +1,438 @@
|
||||
*********************************************************
|
||||
* 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
|
||||
|
282
jgh/auxmem.misc.s
Normal file
282
jgh/auxmem.misc.s
Normal file
@ -0,0 +1,282 @@
|
||||
* 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
|
||||
|
61
jgh/auxmem.mosequ.s
Normal file
61
jgh/auxmem.mosequ.s
Normal file
@ -0,0 +1,61 @@
|
||||
* 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
|
||||
|
327
jgh/auxmem.vdu.s
Normal file
327
jgh/auxmem.vdu.s
Normal file
@ -0,0 +1,327 @@
|
||||
* 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
|
||||
|
112
jgh/loader.s
Normal file
112
jgh/loader.s
Normal file
@ -0,0 +1,112 @@
|
||||
* 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
|
||||
|
743
jgh/mainmem.s
Normal file
743
jgh/mainmem.s
Normal file
@ -0,0 +1,743 @@
|
||||
* 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user