mirror of
https://github.com/marketideas/qasm.git
synced 2026-10-24 22:02:28 +00:00
Move the assembler to src/qasm. qlink links OMF 1.0 and 2.0 from a script. makeBin flattens a load file, qomf dumps OMF, and qpro builds ProDOS volumes. APW and MPW assemble through the ORCA front end. Relocatable modules emit OMF objects. Listings stay off unless -l is set. make boot assembles the GS/OS 6.0.1 ProDOS 8 kernel and BASIC.SYSTEM into an 800K volume. BASIC.SYSTEM accepts ls and pfx, and its splash reports PRODOS BASIC 2.0, copyright 1983-2026. IIGS.601.SRC is the source and the BASIC.SYSTEM oracle that image is built from.
1 line
60 KiB
Plaintext
1 line
60 KiB
Plaintext
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; ;
|
|
; ProDOS boot code ;
|
|
; ;
|
|
; Copyright Apple Computer, Inc. 1986-1989,1993 ;
|
|
; ;
|
|
; All Rights Reserved ;
|
|
; ;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;
|
|
; REVISION HISTORY
|
|
;
|
|
; System 6.0.1
|
|
;
|
|
; 27-Oct-92 Dave Lyons
|
|
;
|
|
; If the user hits the "8" key before we run, then we load and run
|
|
; System/P8 insteasd of System/Start.GS.OS.
|
|
;
|
|
; 6-May-93 Dave Lyons, with Steve Stephenson & Jim Murphy
|
|
;
|
|
; Added CreateRAM5, to compensate for a ROM 3 bug that fails to create
|
|
; RAM5 if you have 8 Megs of RAM.
|
|
;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
MACHINE M65816
|
|
string asis
|
|
blanks off
|
|
|
|
entry startup
|
|
entry readinfile
|
|
entry getbootname
|
|
entry getfstname
|
|
entry dp_start
|
|
entry get_filename
|
|
entry find_file_entry
|
|
entry read_block
|
|
entry getblknum
|
|
entry moveblock
|
|
entry fst_name
|
|
entry start_path
|
|
entry start_p8_path
|
|
entry startup_err
|
|
entry not_a_gs
|
|
entry wrong_rom
|
|
entry wrong_rom2
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; equates
|
|
;-------------------------------------------------------------------------------
|
|
|
|
; Direct Page Storage
|
|
|
|
save_d equ 0 ;space to save direct register
|
|
case_bits equ 2 ;upper/lower case info for volume name
|
|
path_len equ 4 ;length of partial pathname
|
|
path_index equ 6 ;index into partial pathname
|
|
path_ptr equ 8 ;pointer to partial pathname
|
|
buffer_ptr equ 12 ;pointer to memory buffer
|
|
file_eof equ 16 ;eof of file
|
|
indexblkoff equ 18 ;offset into an index block
|
|
num_blks equ 20 ;number of blocks to read in
|
|
entryadr equ 22 ;address of file entry
|
|
entrylen equ 24 ;length of file entry
|
|
entsperblk equ 26 ;# of file entries per dir block
|
|
numentries equ 28 ;count of # of file entries to check
|
|
entsactive equ 30 ;active entry count
|
|
entrieschkd equ 32 ;# of file entries checked so far
|
|
nfilestochk equ 34 ;total # of file entries to check
|
|
header_flag equ 36 ;non-zero if reading header block
|
|
name_len equ 38 ;length of volume name
|
|
lopage equ 40
|
|
hipage equ 42
|
|
filename equ 44 ;local storage for filename (16 bytes)
|
|
|
|
|
|
; Stack frame for readinfile
|
|
|
|
eof_return equ 8
|
|
atype_return equ 6
|
|
ftype_return equ 4
|
|
|
|
; Stack frame for moveblock
|
|
|
|
Source equ 15 ; 4-byte source address
|
|
Dest equ 11 ; 4-byte destination address
|
|
Count equ 07 ; 4-byte transfer count
|
|
ReturnMove equ 05 ; 3-byte return address
|
|
TempCount equ 03 ; 2-byte temporary transfer count
|
|
|
|
; START.GS.OS location equate
|
|
|
|
start_loc equ $006800 ; where START.GS.OS is loaded
|
|
|
|
; block buffer equates
|
|
|
|
blkbuf equ $003000 ; bank 0 block buffer
|
|
indexblkbuf equ blkbuf+$0200 ; bank 0 index block buffer
|
|
|
|
; cache equates
|
|
|
|
cache1 equ blkbuf+$0400 ; first block cache
|
|
cache2 equ blkbuf+$0600 ; second block cache
|
|
|
|
; GS/OS error equates
|
|
|
|
file_not_found equ $46
|
|
|
|
; volume directory equates
|
|
|
|
voldir equ $02 ; block number of start of volume dir
|
|
|
|
; directory block offsets
|
|
|
|
fwdlink equ $02 ; offset to forward block link
|
|
namelen equ $04 ; offset to volname length byte
|
|
casebits equ $1A ; offset to upper/lower case info (word)
|
|
entlen equ $23 ; offset to file entry length byte
|
|
entsinblk equ $24 ; offset to # of entries in block
|
|
filecount equ $25 ; offset to # of active entries
|
|
hdr_offset equ $04 ; offset to header in directory block
|
|
|
|
; file entry offsets
|
|
|
|
storagetype equ $00 ; offset to storage type - hi nibble
|
|
filetype equ $10 ; offset to file type - 1 byte
|
|
keypntr equ $11 ; offset to key block of file - 2 bytes
|
|
eof equ $15 ; offset to eof - 3 bytes
|
|
auxtype equ $1f ; offset to aux type - 2 bytes
|
|
|
|
; emulation zero page equates
|
|
|
|
devcmd equ $42 ; Device command
|
|
devunit equ $43 ; Device unit number for device I/O.
|
|
devbuf equ $44 ; Block buffer for device I/O.
|
|
devblk equ $46 ; Device block number for device I/O.
|
|
|
|
; monitor equates
|
|
|
|
idroutine equ $fe1f ; //GS id routine
|
|
setvid equ $fe93 ; Does a PR#0 to put COUT1 in CSW.
|
|
setnorm equ $fe84 ; Normal white text on black backround.
|
|
init equ $fb2f ; Text pg1; text mode; sets 40/80 col w
|
|
home equ $fc58 ; Monitor's clear screen routine.
|
|
|
|
; hardware equates
|
|
|
|
clr80col equ $c000 ; disable 80 column store
|
|
clr80vid equ $c00c ; disable 80 column hardware
|
|
clraltchar equ $c00e ; normal lc, flashing uc
|
|
|
|
; language card soft switch equates
|
|
|
|
romin equ $c081 ; enable rom read, 2 reads write enb LC ram
|
|
|
|
; misc. equates
|
|
|
|
mslot equ $07f8 ; slot # of boot device
|
|
screen equ $05a8 ; Row 11 of 40 column screen
|
|
screen2 equ $06a8 ; Row 13 of 40 column screen
|
|
emulstack equ $010100 ; emulation stack ptr is saved here
|
|
|
|
|
|
|
|
;===============================================================================
|
|
; jump table
|
|
;===============================================================================
|
|
|
|
EXPORT jump_table
|
|
jump_table PROC
|
|
|
|
longa on
|
|
longi on
|
|
|
|
jmp |startup ;3 bytes
|
|
nop ;1 byte of padding
|
|
DC.W readinfile ;offset into table = 4
|
|
DC.W getbootname ;offset into table = 6
|
|
DC.W getfstname ;offset into table = 8
|
|
DC.W getfstname-jump_table ;size of permanent code
|
|
EXPORT aux_value ;aux type of START.GS.OS file
|
|
aux_value DC.W 0 ;offset into table = 12
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
;===============================================================================
|
|
; readinfile
|
|
;
|
|
; Entry is in 16-bit native mode.
|
|
; Exit is in 16-bit native mode.
|
|
; Data bank register is preserved.
|
|
; Direct register is preserved.
|
|
;
|
|
; Inputs: 4 bytes - space for eof result
|
|
; 2 bytes - space for aux type result
|
|
; 2 bytes - space for file type result
|
|
; 4 bytes - pointer to partial pathname of file to read
|
|
; 4 bytes - pointer to buffer to read file into
|
|
;
|
|
; Outputs: c - 0 if file read successful, 1 if not
|
|
; A - error code if c=1
|
|
; file's eof on stack (4 bytes)
|
|
; file's auxtype on stack (2 bytes)
|
|
; file's filetype on stack (2 bytes)
|
|
;
|
|
; This routine will find the requested file and read it into memory.
|
|
; The file's eof, auxtype and filetype are returned on the stack.
|
|
; The partial pathname is class 1 format; the filenames are separated
|
|
; by colons; there are no leading or trailing colons.
|
|
;
|
|
; NOTE - this routine assumes the file being read is a sapling file !!
|
|
;=============================================================================
|
|
|
|
EXPORT readinfile
|
|
readinfile PROC
|
|
|
|
longa on
|
|
longi on
|
|
|
|
;save current direct register and set it to point to our data area
|
|
|
|
tdc
|
|
pea dp_start
|
|
pld
|
|
sta <save_d
|
|
|
|
;pull inputs off stack
|
|
|
|
plx ;pull return address off stack
|
|
pla ;pull pointer to buffer off stack
|
|
sta <buffer_ptr ;and save
|
|
pla
|
|
sta <buffer_ptr+2
|
|
pla ;pull pointer to pathname off stack
|
|
sta <path_ptr ;and save
|
|
pla
|
|
sta <path_ptr+2
|
|
phx ;push return address back on stack
|
|
|
|
;initialize pathname information
|
|
|
|
lda #1
|
|
sta <path_index ;initialize index into pathname
|
|
lda [<path_ptr] ;get length of pathname
|
|
inc a ;add 1 for extra length byte
|
|
sta <path_len ;and save
|
|
|
|
;initialize entryadr to 0
|
|
|
|
stz <entryadr
|
|
|
|
;save data bank register and set it to bank $00
|
|
|
|
phb
|
|
phk
|
|
plb
|
|
|
|
;pull filename off pathname and find its file entry
|
|
;continue until have found file entry for final filename in pathname
|
|
|
|
file_loop
|
|
jsr get_filename ;extract next filename from pathname
|
|
bcs found_last ;carry set if at end of pathname
|
|
jsr find_file_entry ;find the file entry for the filename
|
|
bcs err_ret ;if carry set, error is in A
|
|
bra file_loop
|
|
|
|
;we now have the file entry for the file we are to load...
|
|
|
|
;get the file's eof, save it for later and return it on the stack
|
|
|
|
found_last
|
|
ldy #eof ;get eof and save for later
|
|
lda (<entryadr),y
|
|
sta <file_eof
|
|
sta eof_return,s ;and return on stack
|
|
iny ;get third byte (word) too
|
|
iny
|
|
lda (<entryadr),y
|
|
and #$00ff ;high byte must be $00
|
|
sta <file_eof+2
|
|
sta eof_return+2,s
|
|
|
|
;get the file's aux type and return it on the stack
|
|
|
|
ldy #auxtype ;offset to aux type
|
|
lda (<entryadr),y ;get aux type from file entry
|
|
sta atype_return,s ;return on stack
|
|
|
|
;get the file's file type and return it on the stack
|
|
|
|
ldy #filetype ;offset to file type
|
|
lda (<entryadr),y ;get file type from file entry
|
|
and #$00ff ;only lo byte is valid
|
|
sta ftype_return,s ;return on stack
|
|
|
|
;read in file's key block
|
|
|
|
ldy #keypntr ;Key block pointer offset.
|
|
lda (<entryadr),y ;Load key blk pointer.
|
|
tay ;Save in Y for Readblock call.
|
|
ldx #indexblkbuf ;set up ptr to index block buffer
|
|
lda #0 ;buffer is in bank $00
|
|
jsr read_block
|
|
bcs err_ret ;if carry set, A contains error
|
|
|
|
;now, read the file into memory
|
|
|
|
lda <file_eof+1 ;how many blocks do we read in????
|
|
lsr a ;divide by 2
|
|
tax ;save in x while we check for leftovers
|
|
lda <file_eof ;get low word of eof
|
|
and #$01ff ;we only want to test low 9 bits
|
|
beq num_blks_ok ;= then we already have the correct num
|
|
inx ;add one for safety
|
|
num_blks_ok
|
|
stx <num_blks ;save as our counter
|
|
ldx #$ffff ;offset into index table-1
|
|
stx <indexblkoff
|
|
|
|
read_all
|
|
inc <indexblkoff ; increment index into index block
|
|
lda #indexblkbuf ; Set up to get the data block
|
|
ldy <indexblkoff ; address of the file on disk.
|
|
jsr getblknum ; Get the block number in Y.
|
|
lda <buffer_ptr+2 ; put ptr to buffer in A and X
|
|
ldx <buffer_ptr
|
|
jsr read_block ; Read 1st data block.
|
|
bcc rdok1 ; Branch if successful read.
|
|
err_ret
|
|
plb ; restore data bank register
|
|
pha ; save error code
|
|
lda <save_d
|
|
tcd ; restore direct register
|
|
pla ; retrieve error code
|
|
rts ; carry set, error code in A
|
|
|
|
rdok1
|
|
|
|
;now we must decrement the number of blocks counter by 1 block
|
|
|
|
dec <num_blks
|
|
beq done
|
|
|
|
;now we must increment pointer by 1 block
|
|
|
|
clc
|
|
lda <buffer_ptr ;low word of destination pointer
|
|
adc #$0200 ;add one block
|
|
sta <buffer_ptr
|
|
bcc read_all
|
|
inc <buffer_ptr+2
|
|
bra read_all
|
|
|
|
;done with read - return to caller
|
|
|
|
done
|
|
plb ;restore data bank register
|
|
lda <save_d
|
|
tcd ;restore direct register
|
|
clc ;indicate no error
|
|
rts ;back to caller
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
;===============================================================================
|
|
; get_filename
|
|
;
|
|
; Entry is in 16-bit native mode.
|
|
; Exit is in 16-bit native mode.
|
|
; Data bank register is set to bank $00 on entry and exit.
|
|
; Direct register is set to point to local data area on entry and exit.
|
|
;
|
|
; Inputs: <path_ptr - points to a pathname
|
|
; <path_index - contains the current index into the pathname
|
|
; <path_len - contains the length of the pathname
|
|
;
|
|
; Outputs: c - 1 if at end of pathname, else 0
|
|
; <filename - contains the extracted filename in class 0 format
|
|
; with no leading or trailing separators
|
|
;
|
|
; This routine extracts the next local filename from a pathname.
|
|
;===============================================================================
|
|
|
|
EXPORT get_filename
|
|
get_filename PROC
|
|
|
|
longa off
|
|
longi off
|
|
sep #$30 ; ***** begin 8-bit mode *****
|
|
|
|
ldy <path_index ;get current index into pathname
|
|
cpy <path_len ;are we at end of pathname?
|
|
bcs done ;yes - so return carry set
|
|
|
|
ldx #0 ;initialize index into filename
|
|
|
|
loop
|
|
iny
|
|
lda [<path_ptr],y ;get next character from pathname
|
|
cmp #':' ;if it's ':', we're at end of filename
|
|
beq cont
|
|
inx
|
|
sta <filename,x ;store character in local string
|
|
cpy <path_len ;are we at the end of the pathname?
|
|
bne loop ;no - so continue
|
|
|
|
cont
|
|
sty <path_index ;save new index into pathname
|
|
stx <filename ;store length of filename
|
|
clc ;indicate no error
|
|
|
|
done
|
|
longa on
|
|
longi on
|
|
rep #$30 ; ***** return to 16-bit mode *****
|
|
|
|
rts
|
|
ENDP
|
|
|
|
|
|
|
|
;===============================================================================
|
|
; find_file_entry
|
|
;
|
|
; Entry is in 16-bit native mode.
|
|
; Exit is in 16-bit native mode.
|
|
; Data bank register is set to bank $00 on entry and exit.
|
|
; Direct register is set to point to local data area on entry and exit.
|
|
;
|
|
; Inputs: <entryadr - contains 0 if volume directory should be searched
|
|
; else contains the address of the file entry of the
|
|
; directory to be searched
|
|
; <filename - contains the filename we are searching for
|
|
;
|
|
; Outputs: c - 0 if file entry found, 1 if not
|
|
; A - contains error code if c=1
|
|
; <entryadr - contains address of file entry if c=0
|
|
;
|
|
; This routine will look through a directory for the entry of a specified file.
|
|
;===============================================================================
|
|
|
|
EXPORT find_file_entry
|
|
find_file_entry PROC
|
|
|
|
longa on
|
|
longi on
|
|
|
|
stz <entrieschkd ; Init running no. of checked entries.
|
|
lda #1
|
|
sta <header_flag ;indicate that we're reading header blk
|
|
|
|
ldy #voldir
|
|
lda <entryadr ;if entryadr=0 then read volume dir
|
|
beq next_block
|
|
|
|
ldy #storagetype ;offset to storage type
|
|
lda (<entryadr),y ;get storage type
|
|
and #$00f0 ;need hi nibble of lo byte only
|
|
cmp #$00d0 ;is it a subdirectory?
|
|
bne nofile ;no - so report an error
|
|
|
|
ldy #keypntr ;offset to key block pointer
|
|
lda (<entryadr),y ;get key blk pointer
|
|
tay ;put in Y for Readblock call
|
|
|
|
next_block
|
|
ldx #blkbuf ;set up ptr to block buffer
|
|
lda #0 ;bank
|
|
jsr read_block ;read the block
|
|
bcs readerr ;if carry set, A contains error
|
|
|
|
lda <header_flag ;was this a header block?
|
|
beq not_hdr ;no
|
|
lda |blkbuf+entlen ;get length of file entry
|
|
and #$00ff ;zero hi byte
|
|
sta <entrylen ;and save
|
|
lda |blkbuf+entsinblk ;get # of entries in block
|
|
and #$00ff ;zero hi byte
|
|
sta <entsperblk ;and save
|
|
lda |blkbuf+filecount ;get # of active entries in dir
|
|
sta <nfilestochk ;and save
|
|
not_hdr
|
|
|
|
jsr chkdirblk ; Go look for file.
|
|
bcc gotit ; Branch if file found.
|
|
clc ; update # of entries checked
|
|
lda <entsactive
|
|
adc <entrieschkd
|
|
sta <entrieschkd
|
|
cmp <nfilestochk ; Have we compared all entries?
|
|
beq nofile ; Branch if so..no match found.
|
|
|
|
ldx #fwdlink ; Load forward directory
|
|
ldy |blkbuf,x ; block pointer.
|
|
beq nofile ; Branch if no more dir to search.
|
|
stz <header_flag
|
|
bra next_block ; Go check next directory block.
|
|
|
|
nofile
|
|
lda #file_not_found ;set error #
|
|
readerr
|
|
sec ;indicate error
|
|
rts
|
|
|
|
gotit
|
|
clc ;indicate no error
|
|
rts
|
|
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; chkdirblk
|
|
;
|
|
; Entry is in 16-bit native mode.
|
|
; Exit is in 16-bit native mode.
|
|
; Data bank register is set to bank $00 on entry and exit.
|
|
; Direct register is set to point to local data area on entry and exit.
|
|
;
|
|
; Inputs: directory block is in 'blkbuf'
|
|
; <entsperblk - contains # of file entries per block
|
|
; <entrylen - contains length of file entry
|
|
;
|
|
; Outputs: c - 0 if file entry found, 1 if not
|
|
; <entryadr - contains address of file entry if c=0
|
|
; <entsactive - contains # of active entries checked
|
|
;
|
|
; Checks a given directory block for a file entry with a given filename.
|
|
;-------------------------------------------------------------------------------
|
|
|
|
chkdirblk
|
|
longa on
|
|
longi on
|
|
|
|
stz <entsactive ; Init active entry count to zero.
|
|
lda <entsperblk ; Save number of entries per blk
|
|
sta <numentries ; in a working temp.
|
|
|
|
lda #blkbuf ; Adjust address of
|
|
clc ; directory block past
|
|
adc #4 ; the block pointers.
|
|
sta <entryadr ; And store in entry pointer.
|
|
|
|
ldx <header_flag
|
|
beq notheader ; Branch if not a key dir blk.
|
|
|
|
chknxtentry
|
|
clc ; Adjust to next entry.
|
|
lda <entryadr
|
|
adc <entrylen
|
|
sta <entryadr
|
|
dec <numentries ; One less entry to search.
|
|
beq notfound ; Branch if no more entries.
|
|
notheader
|
|
lda (<entryadr) ; Is entry active?
|
|
and #$00ff ; Strip off hi byte.
|
|
beq chknxtentry ; not active so check next entry
|
|
inc <entsactive ; Update active entry count.
|
|
jsr check_name ; Is this the entry we're looking for?
|
|
bcs chknxtentry ; no - so check next entry
|
|
rts ; carry is clear
|
|
|
|
notfound
|
|
sec ; indicate entry not found
|
|
rts
|
|
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; check_name
|
|
;
|
|
; Entry is in 16-bit native mode.
|
|
; Exit is in 16-bit native mode.
|
|
; Data bank register is set to bank $00 on entry and exit.
|
|
; Direct register is set to point to local data area on entry and exit.
|
|
;
|
|
; Inputs: <entryadr - contains address of file entry to check
|
|
; <filename - contains filename to match
|
|
;
|
|
; Outputs: c - 0 if filename matches, 1 if not
|
|
;
|
|
; Checks a file entry for a match to a specified filename.
|
|
;-------------------------------------------------------------------------------
|
|
|
|
check_name
|
|
longa off
|
|
longi off
|
|
sep #$30 ;***** begin 8-bit mode *****
|
|
|
|
lda (<entryadr) ; Get length of filename.
|
|
and #$0f ; Strip off hi nibble.
|
|
cmp <filename ; Are the filenames the same length?
|
|
bne nomatch ; no
|
|
tay ; xfer filename length to Y
|
|
tax ; and X
|
|
nxtchar lda (<entryadr),y ; compare filename
|
|
cmp <filename,x
|
|
bne nomatch ; they're not the same
|
|
dey
|
|
dex
|
|
bne nxtchar ; Go check next char in filename.
|
|
clc ; signify match
|
|
rep #$30 ;***** return to 16-bit mode *****
|
|
rts
|
|
|
|
nomatch
|
|
sec ; Signify no match.
|
|
rep #$30 ;***** return to 16-bit mode *****
|
|
rts
|
|
ENDP
|
|
|
|
|
|
|
|
;===============================================================================
|
|
; getblknum
|
|
;
|
|
; Entry is in 16-bit native mode.
|
|
; Exit is in 16-bit native mode.
|
|
; Data bank register is set to bank $00 on entry and exit.
|
|
; Direct register is set to point to local data area on entry and exit.
|
|
;
|
|
; Inputs: A - Memory address of index block.
|
|
; Y - Offset into index block.
|
|
;
|
|
; Outputs: Y - Returns block number from index block.
|
|
;
|
|
; Getblknum will return the block number wanted from the given index block.
|
|
;===============================================================================
|
|
|
|
EXPORT getblknum
|
|
getblknum PROC
|
|
|
|
longa on
|
|
longi on
|
|
|
|
sta <lopage ; Store index blk adr. in z-page.
|
|
clc ; Now calculate adr. of hi page
|
|
adc #256 ; of index block for indexing reasons..
|
|
sta <hipage ; And store it.
|
|
|
|
longa off
|
|
sep #$20 ; ***** begin 8-bit m *****
|
|
|
|
lda (<hipage),y ; Get hi byte of block number.
|
|
xba ; Save in lo byte of A.
|
|
lda (<lopage),y ; Get the low byte of the block number.
|
|
|
|
longa on
|
|
rep #$20 ; ***** return to 16 bit m *****
|
|
|
|
tay ; Return block number in Y.
|
|
rts ; Done.
|
|
ENDP
|
|
|
|
|
|
|
|
;===============================================================================
|
|
; read_block
|
|
;
|
|
; This is the new READ_BLOCK routine.
|
|
; A call structure for an extended SmartPort interface will
|
|
; be built for the requested block. If the ProDOS interface
|
|
; is indicated then the extended SmartPort call will be
|
|
; translated into a ProDOS call prior to passing control to
|
|
; the firmware interface. ProDOS calls will be followed by
|
|
; a block move call.
|
|
; If read_block gets a $2E error (disk switched) it will retry the call once.
|
|
;
|
|
; This routine uses a very simple form of block caching. The first two blocks
|
|
; read are copied into two cache areas in memory. Then, when we need to read
|
|
; these blocks again, they are just copied from the cache instead of read from
|
|
; the device. This is done to speed up booting of GS/OS since we know that the
|
|
; first two blocks read are the volume directory block and the SYSTEM directory
|
|
; block. These blocks are needed repeatedly during boot so we save a little
|
|
; time by caching them.
|
|
;
|
|
; ENTRY: via a 'JSR'
|
|
; A Reg = Buffer address (high word)
|
|
; X Reg = Buffer address (low word)
|
|
; Y Reg = Sparse Flag if $0000 or block number
|
|
; Bank Reg = $00
|
|
; Dir Reg = Local data area
|
|
; P Reg = N V M X D I Z C E
|
|
; x x 0 0 0 x x x 0
|
|
;
|
|
; EXIT: via a 'RTS'
|
|
; A Reg = Error code
|
|
; X Reg = Unknown
|
|
; Y Reg = Unknown
|
|
; Bank Reg = $00
|
|
; Dir Reg = Local data area
|
|
; P Reg = N V M X D I Z C E
|
|
; x x 0 0 0 x x 0 0 if no error occured
|
|
; x x 0 0 0 x x 1 0 if error occured
|
|
;
|
|
;===============================================================================
|
|
|
|
EXPORT read_block
|
|
read_block PROC
|
|
|
|
longa on
|
|
longi on
|
|
|
|
phd ;save current direct register
|
|
pea $0000 ;set up emulation zero page
|
|
pld
|
|
|
|
; Assume that an extended SmartPort call will be issued and
|
|
; setup the data neccessary for the call.
|
|
; Also, set up data neccessary for a ProDOS call.
|
|
|
|
stz |retry_flag ;initialize the retry flag
|
|
|
|
sta |sp_buffer+2
|
|
stx |sp_buffer
|
|
stx <devbuf
|
|
sty |sp_block
|
|
sty <devblk
|
|
stz |sp_block+2
|
|
lda |slot_num ; get $Cnxx
|
|
asl a
|
|
asl a
|
|
asl a
|
|
asl a
|
|
and #$7000
|
|
ora #$0001 ; or in a read command
|
|
sta <devcmd
|
|
sta |save_devcmd ;save it in case we need to retry call
|
|
|
|
; if Y=0, then transfer 512 bytes of 0
|
|
|
|
cpy #0 ; should we transfer 512 bytes of zero?
|
|
bne realblock ; no
|
|
lda |sp_buffer+2 ; set bank address of buffer
|
|
sta <devbuf+2
|
|
ldy #510
|
|
lda #0
|
|
zero_loop sta [<devbuf],y ; transfer 512 bytes of zero
|
|
dey
|
|
dey
|
|
bpl zero_loop
|
|
pld ; restore direct register
|
|
clc ; indicate no error
|
|
rts
|
|
|
|
; Y<>0 so we need to transfer a real block
|
|
;
|
|
; First, check to see if the block we want is in cache1 and if so, copy it
|
|
; from the cache into the destination buffer
|
|
|
|
realblock
|
|
cpy |cache1_num ; is the block in the first cache?
|
|
bne check2 ; no
|
|
lda |sp_buffer+2 ; set bank address of buffer
|
|
sta <devbuf+2
|
|
ldy #510
|
|
cache1_loop lda |cache1,y ; copy block from cache1 into buffer
|
|
sta [<devbuf],y
|
|
dey
|
|
dey
|
|
bpl cache1_loop
|
|
cache_ret
|
|
pld ; restore direct register
|
|
clc ; indicate no error
|
|
rts
|
|
|
|
; The block we want is not in cache1 so check to see if it's in cache2 and
|
|
; if so, copy it from the cache into the destination buffer
|
|
|
|
check2
|
|
cpy |cache2_num ; is the block in the second cache?
|
|
bne notcached ; no
|
|
lda |sp_buffer+2 ; set bank address of buffer
|
|
sta <devbuf+2
|
|
ldy #510
|
|
cache2_loop lda |cache2,y ; copy block from cache2 into buffer
|
|
sta [<devbuf],y
|
|
dey
|
|
dey
|
|
bpl cache2_loop
|
|
bra cache_ret
|
|
|
|
notcached ; the block is not cached so read it
|
|
|
|
; Determine if the SmartPort or ProDOS interface will be called.
|
|
|
|
make_the_call
|
|
lda |godev+2 ; will ProDOS or SmartPort be called?
|
|
bmi go_prodos
|
|
|
|
; Call the SmartPort interface.
|
|
|
|
jsr stack_futz ; call the SmartPort interface
|
|
bra read_done
|
|
|
|
; Call the ProDOS interface.
|
|
; The data must be double buffered if a bank other than $00
|
|
; is indicated. If the buffer is in bank $00 then no double
|
|
; buffering will take place.
|
|
|
|
go_prodos
|
|
lda |sp_buffer+2 ; buffer in bank $00?
|
|
bne dbl_buffer ; no, so need to double buffer
|
|
jsr stack_futz ; call the ProDOS interface
|
|
bra read_done
|
|
|
|
; The bank address is not in bank $00 so data must be double buffered
|
|
; through bank $00 since ProDOS devices support only a word wide
|
|
; buffer address in bank $00.
|
|
|
|
dbl_buffer
|
|
lda #blkbuf ; read block into temporary buffer
|
|
sta <devbuf
|
|
jsr stack_futz ; call the ProDOS interface
|
|
bcs read_done
|
|
|
|
; Copy data from bank $00 to ultimate destination.
|
|
|
|
pea blkbuf>>16 ; high word source address ptr
|
|
pea blkbuf ; low word source address ptr
|
|
lda |sp_buffer+2 ; high word dest. address ptr
|
|
pha
|
|
lda |sp_buffer ; low word dest. address ptr
|
|
pha
|
|
pea $0000 ; high word block size
|
|
pea $0200 ; low word block size
|
|
jsr moveblock ; move'em
|
|
clc ; make sure no error
|
|
|
|
read_done
|
|
and #$00FF ; mask off hi byte of error code if any
|
|
bcc no_error
|
|
bit #$0040 ;is it a soft error?
|
|
bne no_error ;yes - so ignore it
|
|
cmp #$002e ;was it disk switched?
|
|
bne report_err ;no - so report it
|
|
ldx |retry_flag ;have we already retried the call?
|
|
bne report_err ;yes - so report the error
|
|
inc |retry_flag ;no - so retry the call
|
|
lda |sp_buffer ;set up ZP params again in case the
|
|
sta <devbuf ;firmware trashed them
|
|
lda |sp_block
|
|
sta <devblk
|
|
lda |save_devcmd
|
|
sta <devcmd
|
|
bra make_the_call ;make the call again
|
|
|
|
report_err
|
|
sec ;make sure carry is set
|
|
bra done
|
|
|
|
no_error
|
|
clc ;make sure carry is clear
|
|
|
|
; Check to see if cache1 is used, and if not, copy the block into it.
|
|
|
|
lda |cache1_num ; is the first cache used?
|
|
bne check_2 ; yes
|
|
lda |sp_block ; no - so save block number
|
|
sta |cache1_num
|
|
lda |sp_buffer+2 ; set the bank address of the buffer
|
|
sta <devbuf+2
|
|
lda |sp_buffer ; restore buffer address since the
|
|
sta <devbuf ; firmware may have trashed it
|
|
ldy #510
|
|
cache1_loop2 lda [<devbuf],y ; copy block into first cache
|
|
sta |cache1,y
|
|
dey
|
|
dey
|
|
bpl cache1_loop2
|
|
bra done
|
|
|
|
; Cache1 was already used so check cache2.
|
|
|
|
check_2
|
|
lda |cache2_num ; is the second cache used?
|
|
bne done ; yes - so no more cache space
|
|
lda |sp_block ; no - so save block number
|
|
sta |cache2_num
|
|
lda |sp_buffer+2 ; set the bank address of the buffer
|
|
sta <devbuf+2
|
|
lda |sp_buffer ; restore buffer address since the
|
|
sta <devbuf ; firmware may have trashed it
|
|
ldy #510
|
|
cache2_loop2 lda [<devbuf],y ; copy block into second cache
|
|
sta |cache2,y
|
|
dey
|
|
dey
|
|
bpl cache2_loop2
|
|
|
|
clc ; indicate no error
|
|
|
|
done
|
|
pld ; restore direct register
|
|
rts
|
|
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; Time to stack futz and call the card.
|
|
|
|
stack_futz
|
|
tsc ; temporary save of native stack ptr
|
|
tax
|
|
sep #$20 ;***** begin 8-bit m *****
|
|
longa off
|
|
xba ; get stack pointer page
|
|
dec a ; is stack in page $01?
|
|
beq alreadypg1 ; yes
|
|
lda #$01 ; else set page 1 stack
|
|
xba
|
|
lda >emulstack ; get emulation stack ptr
|
|
tcs ; set emulation stack ptr
|
|
alreadypg1 phx ; save native mode stack ptr
|
|
sec
|
|
xce ;***** begin emulation mode *****
|
|
longi off
|
|
|
|
; Call either the ProDOS or SmartPort firmware interface.
|
|
|
|
EXPORT godev
|
|
godev
|
|
jsr $C000 ; call firmware interface.
|
|
nop ; 5 NOP's may be replaced by a
|
|
nop ; SmartPort call structure.
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
; Return to native mode after returning from firmware call.
|
|
|
|
php ; preserve carry status
|
|
clc
|
|
xce ;***** begin 8-bit native mode *****
|
|
plp ; restore carry status
|
|
rep #$30 ;***** begin 16-bit mode *****
|
|
longa on
|
|
longi on
|
|
plx ; restore native stack ptr
|
|
txs
|
|
rts
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; The following data must reside with the read_block routine
|
|
|
|
EXPORT read_plist
|
|
read_plist ;SmartPort read call data structure
|
|
DC.B 3 ; parameter count (fixed)
|
|
DC.B 1 ; unit number (fixed)
|
|
sp_buffer DC.L 0 ; buffer ptr (dynamic)
|
|
sp_block DC.L 0 ; block ptr (dynamic)
|
|
|
|
EXPORT slot_num
|
|
slot_num DS.B 2 ;slot number of boot device
|
|
|
|
retry_flag DS.B 2
|
|
|
|
save_devcmd DS.B 2
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; cache data - must be in permanent code area
|
|
;
|
|
; When GLoader saves the permanent code area in the language card, cache1_num
|
|
; and cache2_num must be 0 so that when GQuit moves the code back to bank 0
|
|
; to reload GS/OS, the code will know that the cache is not valid.
|
|
; So, the startup routine must zero cache1_num and cache2_num just before it
|
|
; transfers control to GLoader.
|
|
; Because of this, cache1_num and cache2_num are initialized to 1 so that
|
|
; we don't waste time caching during the startup routine since the cache will
|
|
; be marked as invalid as soon as control is transfered to GLoader.
|
|
|
|
EXPORT cache1_num
|
|
cache1_num DC.W 1 ; number of block in cache1
|
|
EXPORT cache2_num
|
|
cache2_num DC.W 1 ; number of block in cache2
|
|
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
;===============================================================================
|
|
; moveblock
|
|
;
|
|
; Moves a block of data from a source location to a destination location.
|
|
;
|
|
; Calling sequence:
|
|
; Place machine in full native mode (e=0, m=0, x=0)
|
|
; Push high order word of source pointer onto stack
|
|
; Push low order word of source pointer
|
|
; Push high order word of destination pointer
|
|
; Push low order word of destination pointer
|
|
; Push high order word of transfer count
|
|
; Push low order word of transfer count
|
|
; jsr MoveBlock
|
|
;
|
|
; Outputs: None
|
|
;
|
|
; Notes: The high byte of Source, Dest, and Count must be zero
|
|
; The source and destination blocks must not overlap
|
|
; This routine contains self modifying code--it cannot run in ROM
|
|
;===============================================================================
|
|
|
|
EXPORT moveblock
|
|
moveblock PROC
|
|
|
|
longa on
|
|
longi on
|
|
|
|
pha ; push two bytes on stack for TempCount
|
|
phd ; save D
|
|
tsc ; make direct page correspond to stack
|
|
tcd
|
|
|
|
; get ready to do the move
|
|
|
|
phb ; save DBR on stack (MVN trashes it)
|
|
|
|
lda Count
|
|
ora Count+2
|
|
beq MoveAbort
|
|
|
|
ldx Source ; X = low word of Source
|
|
ldy Dest ; Y = low word of Dest
|
|
|
|
; set up the self modifying code to contain dst src
|
|
|
|
lda Dest+2 ; make sure high byte of Dest is 0
|
|
and #$00FF
|
|
sta Dest+2
|
|
lda Source+2 ; get source bank
|
|
and #$00FF ; make sure high byte of Source is 0
|
|
xba
|
|
ora Dest+2 ; or in destination bank (high byte must be zero)
|
|
sta >DoMove+1 ; put bank values into MVN instruction (danger)
|
|
|
|
; decrement Count because it contains actual transfer count whereas
|
|
; remainder of routine assumes it contains transfer count - 1
|
|
|
|
lda Count
|
|
bne ArA1
|
|
dec Count+2
|
|
ArA1 dec Count
|
|
|
|
; initialize TempCount
|
|
|
|
lda Count
|
|
sta TempCount
|
|
bra mdFirst
|
|
|
|
; main move loop
|
|
|
|
mdMore sta Count+2 ; more bytes to move
|
|
lda >DoMove+1 ; A = SrcDst banks
|
|
cpx #$0001 ; bank cross? if X=0
|
|
bcs mdXNot0
|
|
adc #$0100 ; add 1 to source bank
|
|
mdXNot0 cpy #$0000 ; did destination cross bank?
|
|
bne mdYIs0
|
|
inc a
|
|
mdYIs0 sta >DoMove+1
|
|
mdFirst
|
|
txa ; if count > -X then bank cross
|
|
eor #$FFFF
|
|
cmp TempCount
|
|
bcs mdXOk
|
|
sta TempCount ; only move -X bytes
|
|
mdXOk tya ; will destination cross bank?
|
|
eor #$FFFF
|
|
cmp TempCount
|
|
bcs mdYOk
|
|
sta TempCount ; only move -Y bytes
|
|
mdYOk lda TempCount ; get the number of bytes to move
|
|
|
|
; the following 3 bytes are the actual move instruction
|
|
; this routine dynamically modifies the source and destination banks
|
|
|
|
DoMove DC.B $54 ; opcode for MVN
|
|
DC.W $0000 ; destination/source bank
|
|
|
|
lda Count ; Count = Count - bytes moved
|
|
clc ; actual bytes moved 1 more than count
|
|
sbc TempCount
|
|
sta Count
|
|
sta TempCount
|
|
lda Count+2
|
|
sbc #$0000
|
|
bpl mdMore
|
|
|
|
; clean up everything before returning
|
|
|
|
MoveAbort
|
|
plb ; restore DBR
|
|
|
|
lda ReturnMove ; move return address past parameters
|
|
sta Source+2
|
|
|
|
pld ; restore D
|
|
tsc ; set S to proper value
|
|
clc
|
|
adc #$000e
|
|
tcs ;fix up stack
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
;===============================================================================
|
|
; getbootname
|
|
;
|
|
; Entry is in 16-bit native mode.
|
|
; Exit is in 16-bit native mode.
|
|
; Direct register is preserved.
|
|
;
|
|
; Inputs: 4 bytes - pointer to space for volume name
|
|
;
|
|
; Outputs: c - 0 if successful, 1 if not
|
|
; A - error code if c=1
|
|
;
|
|
; This routine will return the name of the boot volume.
|
|
; The string must be in class 1 format and must contain a leading colon but
|
|
; not a trailing colon.
|
|
;
|
|
; Modified 4/27/89 to handle upper/lower case volume names. CAE
|
|
;=============================================================================
|
|
|
|
EXPORT getbootname
|
|
getbootname PROC
|
|
|
|
longa on
|
|
longi on
|
|
|
|
;save current direct register and set it to point to our data area
|
|
|
|
tdc
|
|
pea dp_start
|
|
pld
|
|
sta <save_d
|
|
|
|
;pull inputs off stack
|
|
|
|
plx ;pull return address off stack
|
|
pla ;pull pointer to string off stack
|
|
sta <path_ptr ;and save
|
|
pla
|
|
sta <path_ptr+2
|
|
phx ;push return address back on stack
|
|
|
|
;read block 2 of the boot volume
|
|
|
|
lda #0 ;bank
|
|
ldx #blkbuf ;ptr to block buffer
|
|
ldy #voldir ;block # to read
|
|
jsr read_block ;read the block
|
|
bcs done
|
|
|
|
;copy volume name into caller's area
|
|
|
|
stz <case_bits ;init to all upper case
|
|
lda |blkbuf+casebits ;get upper/lower case info for volume name
|
|
bpl cont ;it's not valid
|
|
asl a ;it's valid, so get rid of the ON/OFF bit
|
|
sta <case_bits ;and save the case bits
|
|
cont
|
|
lda |blkbuf+namelen ;get length of volume name
|
|
and #$000f ;strip off hi byte and type nibble
|
|
sta <name_len ;save for later
|
|
inc a ;add 1 for leading colon
|
|
sta [<path_ptr] ;store in output string as length word
|
|
|
|
longa off
|
|
longi off
|
|
sep #$30 ; ***** begin 8-bit mode *****
|
|
|
|
ldx #0 ;init index into volume name
|
|
ldy #2 ;init index into output string
|
|
lda #':' ;add a colon at start of output string
|
|
sta [<path_ptr],y
|
|
|
|
loop
|
|
inx
|
|
iny
|
|
|
|
lda |blkbuf+namelen,x ;copy volume name into output string
|
|
rep #$20 ;16-bit mode for the rotate
|
|
rol <case_bits ;should this char be upper or lower case?
|
|
sep #$20 ;back to 8-bit mode
|
|
bcc its_upper ;leave it upper case
|
|
ora #$20 ;make the char lower case
|
|
its_upper
|
|
sta [<path_ptr],y
|
|
cpx <name_len ;done?
|
|
bne loop ;no
|
|
|
|
longa on
|
|
longi on
|
|
rep #$30 ; ***** return to 16-bit mode *****
|
|
|
|
clc ;indicate no error
|
|
|
|
done
|
|
pha ;save error code if any
|
|
lda <save_d ;restore direct register
|
|
tcd
|
|
pla ;restore error code
|
|
stz |cache1_num ;zero out the cache info in case the
|
|
stz |cache2_num ;wrong disk is in the drive
|
|
rts
|
|
ENDP
|
|
|
|
|
|
|
|
;===============================================================================
|
|
; getfstname
|
|
;
|
|
; Entry is in 16-bit native mode.
|
|
; Exit is in 16-bit native mode.
|
|
; Data bank register is preserved.
|
|
; Direct register is preserved.
|
|
;
|
|
; Inputs: 4 bytes - pointer to space for fst name
|
|
;
|
|
; Outputs: none
|
|
;
|
|
; This routine will return the name of the start fst in class 1 format
|
|
; with no leading or trailing separators.
|
|
;=============================================================================
|
|
|
|
EXPORT getfstname
|
|
getfstname PROC
|
|
|
|
longa on
|
|
longi on
|
|
|
|
;save current direct register and set it to point to our data area
|
|
|
|
tdc
|
|
pea dp_start
|
|
pld
|
|
sta <save_d
|
|
|
|
;pull inputs off stack
|
|
|
|
plx ;pull return address off stack
|
|
pla ;pull pointer to string off stack
|
|
sta <path_ptr ;and save
|
|
pla
|
|
sta <path_ptr+2
|
|
phx ;push return address back on stack
|
|
|
|
;save data bank register and set it to bank $00
|
|
|
|
phb
|
|
phk
|
|
plb
|
|
|
|
;copy start fst name into caller's area
|
|
|
|
lda |fst_name ;get length of fst name
|
|
inc a ;add 1 for extra length byte
|
|
tay
|
|
|
|
longa off
|
|
longi off
|
|
sep #$30 ; ***** begin 8-bit mode *****
|
|
|
|
loop lda |fst_name,y ;copy fst name into output string
|
|
sta [<path_ptr],y
|
|
dey
|
|
bpl loop
|
|
|
|
longa on
|
|
longi on
|
|
rep #$30 ; ***** return to 16-bit mode *****
|
|
|
|
; restore data bank register and direct register and return to caller
|
|
|
|
plb ;restore data bank register
|
|
lda <save_d ;restore direct register
|
|
tcd
|
|
rts
|
|
ENDP
|
|
|
|
|
|
|
|
;===============================================================================
|
|
; startup
|
|
;
|
|
; Exit is in 16-bit native mode.
|
|
; Data bank register is set to bank $00 on exit.
|
|
; Direct register is set to $0000 on exit.
|
|
; Stack is set to $01ff on exit.
|
|
;
|
|
; This routine is called by the disk boot firmware.
|
|
; It first verifies that it is running on a //GS with the correct ROM and then
|
|
; it loads in /v/SYSTEM/START.GS.OS and transfers control to it.
|
|
;
|
|
; The aux type of the file START.GS.OS contains the boot time information
|
|
; used by the graphics splash screen. So, after START.GS.OS is read in, its
|
|
; aux type is stored at the end of the jump table. Then, when we transfer
|
|
; control to START.GS.OS, GLoader will pick up the aux type value from the end
|
|
; of the jump table and pass it to the graphics splash screen routine.
|
|
;===============================================================================
|
|
|
|
EXPORT startup
|
|
startup PROC
|
|
|
|
longa on
|
|
longi on
|
|
|
|
; At onset, we don't know what machine we are being run on.
|
|
; If we are not being run on an Apple //GS we must hang with an error message.
|
|
|
|
; The following code will run on both the 65816 and 6502 processors
|
|
; to ensure 8 bit processing.
|
|
|
|
tsx ;save stack pointer.
|
|
lda #$3030
|
|
nop ;required filler.
|
|
pha ;push $30 on stack.
|
|
plp ;and retrieve for full 8 bit mode.
|
|
|
|
longa off
|
|
longi off
|
|
|
|
txs ;restore stack.
|
|
|
|
; The above code looks like the following for a 6502...
|
|
; (this code essentially does nothing on a 6502)
|
|
|
|
; tsx
|
|
; lda #$30
|
|
; bmi nop ; will never be taken....
|
|
; pha
|
|
; plp
|
|
; txs
|
|
|
|
lda romin ;bank in rom.
|
|
sec ;go into //GS id routine with c set
|
|
jsr idroutine ;are we on a //GS?
|
|
bcs to_showerrmsg ;no
|
|
cpy #$01 ;is rom revision 01 or greater?
|
|
bcc to_showerrmsg ;no
|
|
|
|
;We must be in emulation mode on a //GS (Fern said so, and if he is
|
|
;wrong he must put in the stack futz for us).
|
|
|
|
pea $0000 ;ensure zero page at $000000
|
|
pld
|
|
|
|
phk ;set data bank to code bank
|
|
plb
|
|
|
|
*** ROM Version is still in Y!
|
|
|
|
*** added 6-May-93 DAL/SS -- create a RAM disk on an 8 Meg ROM 3 machine, since
|
|
*** the ROM accidentally decided we couldn't have one
|
|
cpy #3
|
|
bne @notROM3
|
|
jsr CreateRAM5
|
|
@notROM3
|
|
*** end 6-May-93
|
|
|
|
jsr id_sp ; setup readblock for proper interface
|
|
|
|
clc
|
|
xce ; ***** begin native mode *****
|
|
rep #$30 ; ***** begin 16-bit mode *****
|
|
longa on
|
|
longi on
|
|
|
|
lda #$01ff ;set stack to $01ff
|
|
tcs
|
|
|
|
*** added 27-Oct-92 DAL -- If they hit "8", run System/P8 instead of Start.GS.OS
|
|
lda $C000
|
|
and #$00ff
|
|
cmp #$00b8 ;'8'
|
|
beq GoProDOS8
|
|
*** end 27-Oct-92
|
|
|
|
;Now, read in the /v/SYSTEM/START.GS.OS file
|
|
|
|
pha ;8 byte space for results
|
|
pha
|
|
pha
|
|
pha
|
|
pea start_path>>16 ;ptr to partial pathname
|
|
pea start_path
|
|
pea 0 ;pointer to mem location for START.GS.OS
|
|
pea start_loc
|
|
jsr readinfile ;find START.GS.OS and read it in
|
|
bcc read_ok
|
|
pha ;error #
|
|
pea $0000
|
|
pea startup_err ;address of error msg
|
|
fatal ldx #$1503 ;call sysfailmgr to report error
|
|
jsl $E10000 ;doesn't return
|
|
|
|
read_ok pla ;ignore filetype
|
|
pla ;get auxtype
|
|
sta |aux_value ;and store at end of jump table
|
|
pla ;ignore eof
|
|
pla
|
|
|
|
stz |cache1_num ;zero out these two items so that
|
|
stz |cache2_num ;caching is now active
|
|
|
|
;Now, transfer control to START.GS.OS
|
|
|
|
jmp >start_loc
|
|
|
|
to_showerrmsg jmp showerrmsg
|
|
|
|
*** added 27-Oct-92 DAL
|
|
GoProDOS8 sta $C010 ;clear keyboard strobe (eat the "8")
|
|
|
|
pha ;8 byte space for results
|
|
pha
|
|
pha
|
|
pha
|
|
pea start_p8_path>>16 ;ptr to partial pathname
|
|
pea start_p8_path
|
|
pea 0 ;pointer to mem location for P8
|
|
pea start_loc
|
|
jsr readinfile ;find System/P8 and read it in
|
|
bcc read_p8_ok
|
|
pha ;error #
|
|
lda #0
|
|
pha
|
|
pha ;error message string
|
|
bra fatal
|
|
|
|
read_p8_ok pla ;discard filetype
|
|
pla ;discard auxtype
|
|
pla ;low word of EOF
|
|
dec a
|
|
sta p8_length+1
|
|
pla ;discard EOF high word
|
|
ldx #p8_jumper
|
|
ldy #$0200 ;move code to $200
|
|
lda #p8_jump_end-p8_jumper
|
|
mvn 0,0
|
|
jmp $0200
|
|
|
|
p8_jumper ldx #start_loc
|
|
ldy #$2000 ;move P8 to $2000
|
|
p8_length lda #$7777 ;length of P8 (modified)
|
|
mvn 0,0
|
|
sec
|
|
xce
|
|
longa off
|
|
longi off
|
|
ldx #$FF
|
|
txs
|
|
jmp $2000
|
|
p8_jump_end
|
|
|
|
*** end 27-Oct-92
|
|
|
|
*** 6-May-93 DAL/SS -- Create RAM5 if necessary (we already know we're on ROM 3)
|
|
CreateRAM5 clc
|
|
xce
|
|
rep #$30
|
|
longa on
|
|
longi on
|
|
|
|
NumBanks equ $E11624 ;Number of 64K banks in machine
|
|
DiskHandle equ $E11646
|
|
MaxDiskParm equ $E102F7 ;inside the Battery RAM buffer (max RAM5 size, N*32K)
|
|
|
|
phb
|
|
pea $E1E1
|
|
plb
|
|
plb
|
|
|
|
lda |DiskHandle+1
|
|
bne @noProblem ;already have a RAM5 handle
|
|
|
|
lda |MaxDiskParm
|
|
and #$00ff
|
|
beq @noProblem
|
|
|
|
lda |NumBanks
|
|
cmp #$80
|
|
bcc @noProblem
|
|
|
|
*** make a stack frame
|
|
phd
|
|
tsc
|
|
sec
|
|
sbc #$0020
|
|
tcs
|
|
inc a
|
|
tcd
|
|
|
|
phk
|
|
per @return-1
|
|
pea #$00BC-1
|
|
lda #$81 ;pretend like we have *almost* 8 megs, to make ROM check happy
|
|
jmp >$FC14D1 ;jump into the middle of MakeDisk, right after TotalMem
|
|
@return tsc
|
|
clc
|
|
adc #$0020
|
|
tcs
|
|
pld
|
|
|
|
*** now reboot if we created a new RAM5
|
|
lda |DiskHandle+1
|
|
beq @noProblem ;failed to create one
|
|
|
|
plb ;restore B to $00
|
|
stz $03f3 ;trash $3f3 and $3f4
|
|
sec
|
|
xce
|
|
longa off
|
|
longi off
|
|
sei
|
|
jmp $fa62 ;Reset!
|
|
|
|
@noProblem plb
|
|
|
|
sec
|
|
xce
|
|
longa off
|
|
longi off
|
|
|
|
rts
|
|
|
|
*** end 6-May-93
|
|
|
|
;-------------------------------------------------------------------------------
|
|
|
|
showerrmsg
|
|
longa off
|
|
longi off
|
|
|
|
; enter this routine with 'c'=1 for wrong system error
|
|
; enter this routine with 'c'=0 for wrong rom in system
|
|
|
|
php ;save 'c' around setup stuff
|
|
lda romin ; rom in for monitor's home routine.
|
|
sta clr80vid ; disable 80 column hardware.
|
|
sta clraltchar ; switch in primary char set.
|
|
sta clr80col ; disable 80 column store.
|
|
jsr init ; text pg1; text mode; set 40 col window
|
|
jsr setvid ; does a 'pr#0'(puts in cout1 in csw)
|
|
jsr setnorm ; normal white chars on black backround
|
|
jsr home ; clear screen
|
|
plp ;well, which message gets shown
|
|
|
|
ldy not_a_gs ; get length of message
|
|
bcs printerr
|
|
ldy wrong_rom ; get length of message
|
|
|
|
printerr
|
|
lda not_a_gs,y
|
|
bcs printerr2
|
|
lda wrong_rom,y
|
|
|
|
printerr2
|
|
sta screen,y ; store directly to screen
|
|
dey
|
|
bne printerr
|
|
bcs hang ; if 'wrong system' msg, we're done
|
|
|
|
ldy wrong_rom2 ; now put up second line of
|
|
nextline ; the 'wrong rom' msg
|
|
lda wrong_rom2,y
|
|
sta screen2,y ; store directly to screen
|
|
dey
|
|
bne nextline
|
|
|
|
hang jmp hang ; just hang'n around.
|
|
|
|
|
|
eject
|
|
;-------------------------------------------------------------------------------
|
|
;
|
|
; Identify if SmartPort interface exists on startup.
|
|
;
|
|
; ENTRY: via a 'JSR'
|
|
; $0043 = ProDOS unit number
|
|
; $07F8 = $Cn
|
|
; A Reg = Unknown
|
|
; X Reg = Unknown
|
|
; Y Reg = Unknown
|
|
; Bank Reg = $00
|
|
; Dir Reg = $0000
|
|
; P Reg = N V M X D I Z C E
|
|
; x x 1 1 0 x x x 1
|
|
;
|
|
; EXIT: via a 'RTS'
|
|
; A Reg = Unknown
|
|
; X Reg = Unknown
|
|
; Y Reg = Unknown
|
|
; Bank Reg = $00
|
|
; Dir Reg = $0000
|
|
; P Reg = N V M X D I Z C E
|
|
; x x 1 1 0 x x x 1
|
|
;
|
|
;-------------------------------------------------------------------------------
|
|
|
|
id_sp
|
|
longa off
|
|
longi off
|
|
|
|
lda |mslot
|
|
ora #$C0 ; create $Cn00 for (card),y addressing
|
|
sta <devbuf+1
|
|
sta |godev+2
|
|
sta |slot_num+1 ; save for read_block routine
|
|
stz <devbuf
|
|
jsr get_pro_entry ; determine prodos entry point
|
|
sta |godev+1 ; set $CnXX (ProDOS entry point)
|
|
ldy #$07 ; $Cn07 = $00 if SmartPort interface
|
|
lda (<devbuf),y
|
|
bne not_sp
|
|
ldy #$FB ; $CnFB bit 7 set if extended SmartPort
|
|
lda (<devbuf),y
|
|
bpl not_sp
|
|
|
|
; Host interface supports extended SmartPort calls. Now need to know
|
|
; if the device supports extended SmartPort calls.
|
|
|
|
jsr get_pro_entry ; need $Cn00 + ($CnFF)
|
|
adc #$03 ; SmartPort = $Cn00 + ($CnFF) + 3
|
|
sta sp_stat+1
|
|
lda <devbuf+1
|
|
sta |godev+2
|
|
sta sp_stat+2
|
|
|
|
sp_stat
|
|
jsr $C000 ; call SmartPort
|
|
DC.B 0 ; command = status call
|
|
DC.W s_plist ; param list pointer
|
|
|
|
sp_ret
|
|
lda |sp_subtype ; is device extended?
|
|
bpl not_sp ; no
|
|
|
|
; Device and host are extended. Set up the readblock call
|
|
; to use a SmartPort call structure. The parameter in SP_SUBTYPE
|
|
; indicates whether read should use the ProDOS or SmartPort interface.
|
|
; Bit 7 = 0 if ProDOS should be used.
|
|
|
|
lda |sp_stat+1 ; point at SmartPort entry
|
|
sta |godev+1
|
|
ldx #$04
|
|
sp_setup_loop
|
|
lda |call_data,x
|
|
sta |godev+3,x
|
|
dex
|
|
bpl sp_setup_loop
|
|
not_sp
|
|
rts
|
|
|
|
; <devbuf must contain $Cn00 on entry to this routine.
|
|
|
|
get_pro_entry
|
|
ldy #$FF ; SP entry = $Cn00 + ($CnFF) + 3
|
|
clc
|
|
lda (<devbuf),y
|
|
rts
|
|
|
|
s_plist DC.B 3 ; parameter count
|
|
DC.B 1 ; unit
|
|
DC.W s_list ; pointer to status list
|
|
DC.B 3 ; DIB status call
|
|
|
|
s_list DC.B 0 ; status byte
|
|
DC.W 0 ; low word block count
|
|
DC.B 0 ; high block count
|
|
DC.B 0 ; id string length
|
|
DC.B $20 ; id string
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
DC.B $20
|
|
sp_type DC.B 0 ; type
|
|
sp_subtype DC.B 0 ; subtype
|
|
sp_version DC.W 0 ; version number
|
|
DS.B 7 ; added 2/1/89 CAE for 3rd party devices
|
|
|
|
call_data DC.B $41 ; extended read call
|
|
DC.L read_plist ; parameter list pointer
|
|
|
|
ENDP
|
|
|
|
;===============================================================================
|
|
;
|
|
; pb_data
|
|
;
|
|
;===============================================================================
|
|
|
|
EXPORT pb_data
|
|
pb_data PROC
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; strings
|
|
;-------------------------------------------------------------------------------
|
|
|
|
EXPORT start_path
|
|
start_path DC.W 18 ;class 1 string
|
|
DC.B 'SYSTEM:START.GS.OS'
|
|
|
|
*** added 27-Oct-92 DAL
|
|
EXPORT start_p8_path
|
|
start_p8_path DC.W 9 ;class 1 string
|
|
DC.B 'SYSTEM:P8'
|
|
*** end 27-Oct-92
|
|
|
|
EXPORT fst_name
|
|
fst_name DC.W 7 ;class 1 string
|
|
DC.B 'PRO.FST'
|
|
|
|
EXPORT startup_err
|
|
startup_err DC.B 40
|
|
DC.B 'Unable to load START.GS.OS file. Error=$'
|
|
|
|
msb on
|
|
|
|
EXPORT not_a_gs
|
|
not_a_gs DC.B 35
|
|
DC.B 'GS/OS REQUIRES APPLE IIGS HARDWARE '
|
|
|
|
EXPORT wrong_rom
|
|
wrong_rom DC.B 38
|
|
DC.B 'GS/OS needs ROM version 01 or greater.'
|
|
EXPORT wrong_rom2
|
|
wrong_rom2 DC.B 34
|
|
DC.B 'See your dealer for a ROM upgrade.'
|
|
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; Direct Page Start Address
|
|
; NOTE - no code or data can follow this label or it will be overwritten
|
|
;-------------------------------------------------------------------------------
|
|
|
|
EXPORT dp_start
|
|
dp_start
|
|
|
|
ENDP
|
|
|
|
END |