ProDOS_Snippits/setup.system.s

338 lines
9.7 KiB
ArmAsm

; SETUP.SYSTEM by Sean Nolan
; Reworked to actually work by Chris RYU (September 2023)
;
; A Proposed Startup File Standard
;
; Published in Call-APPLE, November, 1987
; This program is in the public domain.
;
; This program mimics the ProDOS 16
; SYSTEM.SETUP convention. It can be used
; to install RAM disk drivers, clock
; drivers, and IIGS Classic Desk
; Accessories on bootup under ProDOS 8.
;
; This program loads and calls all BINary
; and SYStem files in a subdirectory named
; SETUPS. It then looks for the second
; system program in the volume directory
; whose name ends in ".SYSTEM", and runs
; that.
;
; TYP $FF ;save as a system file
; ... or append #ffbd00 to the filename for CiderPress support
.macpack apple2
; equates
CH := $24
IN2 := $280
FILETYPE := IN2+16
AUXCODE := IN2+31
RESET := $3F2
IOBUFFER := $B900
PRODOS := $BF00
QUITVECT := $BF03
DEVNUM := $BF30
BITMAP := $BF58
INIT := $FB2F
VTABZ := $FC24
HOME := $FC58
RDKEY := $FD0C
SETVID := $FE93
SETKBD := $FE89
SETNORM := $FE84
; boot code
.org $BD00 ;load at $2000, but run at $BD00
VOLNAME = * ;The first 17 bytes are overwritten with the
;name of the volume from which this was run.
LDX #%00000001 ;mark page $BD as free in the system bitmap
STX BITMAP+23 ;so we can put Online result in our code.
DEX ;relocate this program to $BD00-BEFF
LOOP1: LDA $2000,X
STA $BD00,X
LDA $2100,X
STA $BE00,X
INX
BNE LOOP1
DEX
TXS ;init stack pointer
JMP ENTER ;jump to relocated code
DIRNAME: .byte 6 ;DirName and VolName must be in the same page
scrcode "SETUPS"
; Get name of boot volume
ENTER: LDA DEVNUM ;get name of last volume accessed
STA ONLINEN
JSR PRODOS
.byte $C5 ;ONLINE
.word ONLINEP
.ifdef OLDANDBUSTED
; this maybe worked with old ProDOS?
LDA VOLNAME+1 ; 3
AND #$0F ; 2
TAX ; 1
INX ; 1
STX VOLNAME ; 3
STA VOLNAME+1 ; 3 = 13
.else
; this does what it was documented as trying to do
LDX VOLNAME+1 ; 3
INX ; 1
STX VOLNAME ; 3
LDA #'/' ; 2
STA VOLNAME+1 ; 3
NOP ; 1 -- for binary-size compatibility
.endif
LDA QUITVECT+1 ;save original quit vector
STA QUITMOD1+1
LDA QUITVECT+2
STA QUITMOD2+1
; Clean up before & after calling files
MAINLOOP: LDX #2 ;point Reset vector and ProDOS
LOOP3: LDA JUMP+1,X ;Quit vectors to MainLoop
STA RESET,X
LDA JUMP,X
STA QUITVECT,X
DEX
BPL LOOP3
TXS ;fix stack pointer (X=$FF)
JSR CLOSE ;close all open files
LDX #23 ;clear system bit map
LDA #0
LOOP2: STA BITMAP,X
DEX
BPL LOOP2
LDA #%11001111 ;mark pages 0,1,4-7 as used
STA BITMAP
LDA #%00000111 ;mark pages $BD-$BF as used
STA BITMAP+23
LDA $C082 ;Language card off
STA $C00C ;40-column
STA $C00E ;normal character set
STA $C000 ;80STORE off
JSR SETNORM ;normal
JSR INIT ;display text page 1
JSR SETVID ;PR#0
JSR SETKBD ;IN#0
;Make sure boot volume is around
;AND set prefix to the boot volume
VOLMOUNT: JSR HOME
JSR PRODOS ;set prefix to volume
.byte $C6 ;SET PREFIX
.word PFX2P
BCC VOLOK
LDX #13
LOOP6: LDA VOLTEXT-1,X ;print message "insert volume"
STA $5A8+4,X
DEX
BNE LOOP6
LOOP7: LDA VOLNAME+1,X ;print volume name
ORA #$80
STA $5A8+19,X
INX
CPX VOLNAME
BCC LOOP7
LDA #35 ;go to CH=35, CV=11
STA CH
LDA #11
JSR VTABZ
JSR RDKEY ;wait for keypress
JMP VOLMOUNT
; Get name of next file at IN2
VOLOK: JSR NEXTFILE ;get name of next file at IN2
BCS EXITLOOP ;if error, we're done with setup files
; Load and call setup file
JSR PRODOS ;set prefix to SETUPS
.byte $C6 ;SET PREFIX
.word PFX1P
JSR READFILE ;read in file whose name is at IN@
;and call it if there was no error.
JUMP: JMP MAINLOOP ;3 bytes here copied into ProDOS quit vector
.byte ($BD^$A5); 3 bytes here are copied into reset vector
EXITLOOP: INC RESET+2 ;scramble reset vector
QUITMOD1: LDA #0 ;restore original quit vector
STA QUITVECT+1
QUITMOD2: LDA #0
STA QUITVECT+2
; Look for second system program on disk
LDA #0 ;modify NextFile routine so that it searches
STA NUMBER+1 ;the volume directory for system files only.
STA CHEKTYPE+1
LDA #<VOLNAME ;NamePtr+1 does not bneed to be changed
STA NAMEPTR ;since VolName and DirName are in the same page
NEXTSYS: JSR NEXTFILE
BCS QUIT
LDX IN2 ;see if file ends with ".SYSTEM"
LDY #6
LOOP4: LDA IN2,X ;I expect pathname at IN2 in low ASCII
CMP SYSTEXT,Y
BNE NEXTSYS
DEX
DEY
BPL LOOP4
INC MOD+1
MOD: LDA #$FF ;the first .SYSTEM program we find is this
BEQ NEXTSYS ;one, so skip it and look for next one.
JSR READFILE ;if successful, never come back
QUIT: JSR PRODOS
.byte $65 ;QUIT
.word QUITP
SYSTEXT: .byte ".SYSTEM"
; Get name of next system file or binary file
;
; This routine is set up to look for both SYSTEM and
; BINary files in the SETUPs subdirectory. It is later
; modified to search for SYSTEM files only in the
; volume directory. The locations which are changed
; are ChekType+1, Number+1, and NamePtr (in the Open
; parametr list)
;
; Returns carry if not found, clear if found.
NEXTFILE: JSR PRODOS
.byte $C8 ;OPEN
.word OPENP
BCS CLOSE
LDA OPENN
STA MARKN
STA READN
JSR PRODOS ;Read in first 39 bytes of directory to
.byte $CA ;IN2. This gets the number of entries per
.word READP ;block and number of bytes per entry.
BCS CLOSE
LDA IN2+35 ;save number of bytes per directory entry
STA ENTSIZE+1
LDA IN2+36 ;save number of entries per directory block
STA ENTRIES+1
NEXTENT: INC NUMBER+1
NUMBER: LDA #0 ;self-modified operand
; Retrieve catalog entry #A
LDX #$FE ;build page index in X
LOOP5: INX
INX
ENTRIES: CMP #13
BCC OK
SBC ENTRIES+1
BCS LOOP5 ;always
OK: TAY
LDA #4 ;1st entry per directory block starts 4 bytes in
LOOP10: DEY
BMI OK2
CLC
ENTSIZE: ADC #39 ;add size of directory entry
BCC LOOP10
INX
BNE LOOP10 ;always
OK2: STA MARK ;save mark in file
STX MARK+1
JSR PRODOS ;set the mark
.byte $CE ;SET_MARK
.word MARKP
BCS CLOSE
JSR PRODOS ;read in directory info
.byte $CA ;READ
.word READP
BCS CLOSE
LDA IN2 ;make sure that file is not deleted
BEQ NEXTENT
AND #$0F
STA IN2
LDA FILETYPE ;make sure file type is correct
EOR #$FF ;we look for system programs...
BEQ CLOSE
CHEKTYPE: EOR #($06^$FF) ;...and binary ones.
BNE NEXTENT
CLOSE: PHP ;close all files - do not change carry
JSR PRODOS
.byte $CC ;CLOSE
.word CLOSEP
PLP
ANRTS: RTS
; Read file and call it.
; Name should be found at IN2
; Prefix must be set.
READFILE: LDX FILETYPE ;if a system program, set to read to $2000
LDA #$20
INX
BEQ SETDEST
LDX AUXCODE ;else, set to read in file at address
LDA AUXCODE+1 ;found in auxcode
SETDEST: STX READ2D
STA READ2D+1
JSR PRODOS ;Open file
.byte $C8 ;OPEN
.word OPENP
BCS CLOSE
LDA OPEN2N
STA READ2N
JSR PRODOS ;Read file into memory
.byte $CA ;READ
.word READ2P
JSR CLOSE
BCS ANRTS
JMP (READ2D) ;call the file just loaded
; ProDOS MLI parameter lists
ONLINEP: .byte 2 ;Online parameter list
ONLINEN: .byte 0
.word VOLNAME+1
;
PFX1P: .byte 1 ;to set prefix to SETUP
.word DIRNAME
;
PFX2P: .byte 1 ;to set prefix to volume directory
.word VOLNAME
;
QUITP: .byte 4,0,0,0,0,0,0
;
CLOSEP: .byte 1, 0 ;close all files
;
OPENP: .byte 3 ;open directory
NAMEPTR: .word DIRNAME ;pathname pointer
.word IOBUFFER
OPENN: .byte 0 ;reference number
;
MARKP: .byte 2 ;set mark in directory
MARKN: .byte 0
MARK: .byte 0, 0, 0
;
READP: .byte 4 ;read directory
READN: .byte 0
.word IN2 ;target address
.word 39 ;length
.word 2
;
OPEN2P: .byte 3 ;open setup or system file
.word IN2
.word IOBUFFER
OPEN2N: .byte 0
;
READ2P: .byte 4 ;read setup or system file
READ2N: .byte 0
READ2D: .byte 0, 0 ;destination of file is self-mod here
.word $B900-$800 ;ask for largest possible that will fit
.byte 0, 0
;
VOLTEXT: scrcode "INSERT VOLUME"