mirror of
https://github.com/marketideas/qasm.git
synced 2026-10-25 13:02:45 +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
146 KiB
Plaintext
1 line
146 KiB
Plaintext
print nohdr
|
|
***********************************************************************************************
|
|
* *
|
|
* DOS 3.3 File System Translator for GS/OS *
|
|
* *
|
|
* Copyright Apple Computer Inc. 1988-1992 ALL RIGHTS RESERVED *
|
|
* *
|
|
* *
|
|
***********************************************************************************************
|
|
|
|
|
|
******* REVISION HISTORY: ***************************************************************
|
|
*
|
|
* August 15, 1988 Monte Benaresh
|
|
*
|
|
* Created this file and entered basic directives, includes, etc.
|
|
* At this point the preliminary ERS, version 0.1, is about to be
|
|
* released.
|
|
*
|
|
* Much of this file is based on the source for the ProDOS FST by
|
|
* Rob Turner.
|
|
*
|
|
* October 27, 1988 Monte Benaresh
|
|
*
|
|
* All the code needed for the OPEN call is essentially completed.
|
|
* Ported dispatch "shell" routines from the ProDOS FST v02.00.
|
|
* Existing source assembles, and code is about to be set up
|
|
* for testing under the GS/OS exerciser.
|
|
*
|
|
* November 17, 1988 Monte Benaresh
|
|
*
|
|
* The OPEN, VOLUME, and GET_FILE_INFO calls are now functional and
|
|
* the Finder will mount DOS 3.3 disks.
|
|
*
|
|
* August 13, 1989 Monte Benaresh
|
|
*
|
|
* All calls are now implemented, and the FST is just a few hours away
|
|
* from being called Alpha.
|
|
*
|
|
* August 14, 1989 Monte Benaresh
|
|
*
|
|
* Projectorized the source and created a makefile.
|
|
*
|
|
* 1.0 d17
|
|
* 10/08/90 CAF Changed the code in match_vcr to increment the vcr open count before
|
|
* trying to read in some blocks from the disk. I did this because SCM
|
|
* was throwing out the VCR when it got the disk_switched error from the
|
|
* appledisk5.25, so an FCR would be created with a link to no VCR - when
|
|
* you tried to close the FCR, SCM would die. Fixed following bugs:
|
|
* EDS213WMP - changed flush to check for pcount max = 2.
|
|
* EDS212WMP - changed parameter table to not include pcount as a parm.
|
|
* EDS205WMP - uncommented some existing code which fixed it.
|
|
* EDS207WMP - added a check for the resource_num parameter.
|
|
* EDS208WMP - fixed by match_vcr addition.
|
|
* EDS209WMP - fixed by EDS207WMP fix.
|
|
* EDS210WMP - changed code in open to preserve error number.
|
|
* EDS211WMP - fixed by commenting out code which copied old fcr
|
|
* into new fcr in open call.
|
|
* EDS222WMP - changed gfi to put total_blocks into aux_type for c0.
|
|
*
|
|
* 1.0 d18
|
|
* 10/15/90 CAF Fixed Bugs:
|
|
* EDS224WMP - Changed read code to skip the high bit stripping for dirs.
|
|
* 10/17/90 CAF Fixed Bugs:
|
|
* APG209WMP - Volume call was getting a $2C error because of a request
|
|
* count to the driver of $100, I changed this to a bouncing
|
|
* error.
|
|
* EDS226WMP - Same fix as APG209WMP
|
|
* EDS215WMP - The newline code for a single char was transferring the
|
|
* data backwards, so I changed the loop to go forwards. Also
|
|
* the local transfer count was not being returned correctly.
|
|
* EDS214WMP - The local transfer count in newline was not being returned
|
|
* correctly (it was being returned as 0), so the fst would
|
|
* sit and spin forever because the request_count was never met.
|
|
*
|
|
* 1.0 d19 - Beta Candidate
|
|
* 11/02/90 CAF Fixed Bugs:
|
|
* LYP225LWA - Changed volume size constants used in volume_s to correct values.
|
|
* LYP226LWA - Changed class 0 version of volume_s to not divide free block
|
|
* count by 2.
|
|
* LYP227LWA - Changed parse_path to check for a class 0 separator as well
|
|
* as a class 1 separator at the start of the pathname.
|
|
* LYP229LWA - Changed class 0 getfileinfo to check to see if the file is a directory
|
|
* before stuffing the total_blocks into the aux_type.
|
|
*
|
|
* 1.0 d20 - Beta Candidate
|
|
* 11/06/90 CAF Fixed Bugs:
|
|
* LYP227LWA - removed addition to parse_path added on 11/02/90, and changed
|
|
* get_dev_num_s to check for a duplicate volume error and mask it
|
|
* into a volume not found error.
|
|
* LYP230LWA - changed open to zero out the resource_blocks field.
|
|
*
|
|
* 1.0 d21 - Beta Candidate
|
|
* 11/06/90 CAF Fixed Bugs:
|
|
* LYP231LWA - changed open_setup to check to see if a volume is a dos
|
|
* volume and that it is online before trying to create a vcr
|
|
* for it.
|
|
* LYP228LWA - same as 231.
|
|
* Completely rewrote most of open_setup because the algorithm used in finding
|
|
* volumes and building vcr's was not handling the operation correctly.
|
|
* Fixed a bug in find_vol_online where it was not returning a vol_not_found
|
|
* error and so the call would not bounce to other fsts.
|
|
* Fixed get_dir_entry to update the vcr_dev if the disk moves.
|
|
* Fixed a bug in get_dir_entry where the drvr_dev_num was not being setup if the end_of_dir
|
|
* had been reached, so a subsequent get_last_dev call would not work correctly.
|
|
*
|
|
* 1.0 d22 - Beta Candidate
|
|
* 11/09/90 CAF Fixed a bug in parse_path where it was executing 16 bit code in 8 bit mode.
|
|
* Fixed a bug in open_setup where I was not setting up a pointer before a call, and
|
|
* so the fst was getting confused enough to cause SCM to commit hari-kari.
|
|
* LYP237LWA - Fixed a bug in open_setup that was causing vcrs to be dumped.
|
|
*
|
|
* 1.0 d23
|
|
* 11/28/90 CAF Fixed Bugs:
|
|
* LYP243LWA - changed newline code to strip the high bits off of text
|
|
* file data during xfer.
|
|
* LYP248LWA - changed some 8/16bit A errors in newline read.
|
|
* LYP247LWA - same as LYP248LWA
|
|
* LYP245LWA - same as LYP248LWA
|
|
* LYP246LWA - same as LYP248LWA
|
|
* LYP238LWA - changed pblock copy data to null out the blocks_used field.
|
|
* LYP241LWA - changed get_dir_entry to check for out of range values
|
|
* when base = 2.
|
|
*
|
|
* 1.0 d24
|
|
* 12/06/90 CAF Fixed Bugs:
|
|
* LYP249LWA - Fixed a bug in read where it wasn't taking into account
|
|
* the data_offset into a file.
|
|
* LYP252LWA - same as 249.
|
|
* LYP250LWA - Fixed a bug in newline_read where it wasn't using
|
|
* long index registers during the newline compare, and
|
|
* so any multiple of $100 would give a length of $00.
|
|
* Fixed a bug where newline mode with > 1 char would not work on text files.
|
|
*
|
|
* 1.0 d25
|
|
* 12/07/90 CAF Changed volume_s to output the volume name on a dup_vol error.
|
|
*
|
|
* 1.0 d26
|
|
* 12/18/90 CAF Fixed Bugs:
|
|
* LYP254LWA - changed open to not output blocks_used parameter.
|
|
* LYP255LWA - changed allocate_vcr to allow the starting search
|
|
* device (supposed_dev) to be setup by the caller.
|
|
*
|
|
* 1.0 d27
|
|
* 12/19/90 CAF Fixed Bugs:
|
|
* LYP256LWA - changed open to special case the directory file.
|
|
* LYP257LWA - changed gfi to special case a class 1 call on a directory.
|
|
* LYP258LWA - changed not_supported2 and not_supported to return drvr_wr_prot.
|
|
* LYP259LWA - changed not_supported2 and not_supported to return drvr_wr_prot.
|
|
* LYP260LWA - changed not_supported2 and not_supported to return drvr_wr_prot.
|
|
* LYP261LWA - changed not_supported2 and not_supported to return drvr_wr_prot.
|
|
* LYP262LWA - changed not_supported2 and not_supported to return drvr_wr_prot.
|
|
* LYP263LWA - changed not_supported2 and not_supported to return drvr_wr_prot.
|
|
*
|
|
* 1.0 b01
|
|
* 12/19/90 CAF/JEV Fixed a bug that was causing a vcr to be thrown out during a gfi call.
|
|
* Added "support" for judge_name call ($07).
|
|
*
|
|
* 1.0 b02 jev Changed how volume names are generated. It was felt that just 'DOS 3.3 Vxxxx' was
|
|
* all that was needed.
|
|
*
|
|
* 1.0 b03 jev Fixed Bug:
|
|
* BGK053LWA - changed error code from a $60 to $4A
|
|
* 3/31/91 jev changed vol_not_found error to unknown vol error if we try to access any
|
|
* other device other than an 5.25.
|
|
* 3/31/91 jev fixed problem with checking for correct pcount.
|
|
* 3/31/91 jev added error priority support. Added new flags in FST header
|
|
* to indicate apple format and read-only fst.
|
|
* 8/18/91 jev Fixed Bug:
|
|
* 86672 - add check in parsepath to check for path2 to see if
|
|
* it exsists or is too long even though we don't use it
|
|
* because we con't do a changepath. But we need to be a
|
|
* good FST and return $40 instead of a $45 if the path is bad.
|
|
* 8/19/91 jev Fixed Do_Option_list. Was not setting up the length of the data.
|
|
* 8/21/91 jev Changed max-pcnt for Judename call to 6. Fixes a bug reported by
|
|
* developer in which DOS3.3 returns a bad pcount error instead of an
|
|
* invalidFSTop for a judeName call.
|
|
*
|
|
* 9/18/91 jev fixed open call to resource fork. Any open call to a resource fork
|
|
* passed to this fst would return res_not_found error even the destination
|
|
* volume was not a DOS 3.3 volume. Moved this check to after the destination
|
|
* was located because this is a non-bouncing error and we don't want to return
|
|
* this error unless the destination belongs to us.
|
|
*
|
|
* 9/19/91 jev Fixed Bug:
|
|
* 86425 - open call with invalid access to any target would return
|
|
* invalid access even if the target was not a DOS 3.3 file.
|
|
* Moved access check to after the destination was located as above.
|
|
*
|
|
* 11/19/91 GAB Fixed occurances of returning VolumeNotFound errors when that
|
|
* particular error shouldn't be returned. (Confuses SCM's error
|
|
* priority logic.)
|
|
*
|
|
* Changed device_id routine so that it no longer performs a Status
|
|
* call to the device driver simply to have the dispatcher set the
|
|
* DIB pointer on direct page. The dispatcher has a call that will
|
|
* perform this service without getting the driver involved.
|
|
*
|
|
* 12/05/91 GAB Change maximum allowable pCount for ChangePath call to 3.
|
|
*
|
|
* 01/08/92 GAB Fixed READ call to properly initialize fde_ptr before it tries
|
|
* to use it. It was using an invalid pointer when it tried to
|
|
* retrieve the first track/sector list location out of the
|
|
* directory entry.
|
|
*
|
|
* Fixed READ call to decrement the destination pointer after
|
|
* moving an odd number of bytes out of the sector buffer. When
|
|
* moving an odd number of bytes, it moved the first byte, then
|
|
* incremented the destination pointer and performed the remainder
|
|
* of the move 2 bytes at a time. Once it had moved the remainder
|
|
* of the sector buffer to the caller's buffer, it was adjusting
|
|
* the destination pointer by the number of bytes moved (which
|
|
* skipped one byte, due to the initial increment). It was then
|
|
* going back to read the next sector to finish the call, but
|
|
* using the invalid (off-by-one) destination pointer.
|
|
*
|
|
* Changed 'brl' instructions to 'bra' wherever possible
|
|
*
|
|
* 02/07/92 MSD Changed version number to 01.00 (final).
|
|
*
|
|
* 02/19/92 - Monte Benaresh
|
|
* Added code to the OPEN call to zero-out the resource_eof field
|
|
* when the param is active, and changed to param copy tables for
|
|
* GET_DIR_ENTRY and GET_FILE_INFO to zero out the resource_eof
|
|
* and resource_blocks fields when those params are active.
|
|
*
|
|
* 19-Feb-92 Dave Lyons
|
|
* Rolled version to $0101 and v01.01 for Monte's change.
|
|
*
|
|
* 02/20/92 - Monte Benaresh
|
|
* Fixed problem in find_eof with 0-length text files.
|
|
* Bumped version to 1.02.
|
|
*
|
|
***********************************************************************************************
|
|
*
|
|
* BEGIN 6.0.1
|
|
*
|
|
* 26-May-92 Dave Lyons for 6.0.1
|
|
*
|
|
* Try changing name to "Apple II DOS 3.3" instead of just "DOS 3.3", to avoid
|
|
* confusion with MS-DOS.
|
|
*
|
|
* 7-Nov-92 DAL with jcm, version 1.3d12
|
|
*
|
|
* Added an entry to the end of fcr_to_pblk so that Open will stop when pcount is 15 instead
|
|
* of trashing a variable amount of memory past the end of the parameter block.
|
|
*
|
|
*
|
|
* 2-Apr-93 SS -- Changed version to $0103 for 6.0.1 (final)
|
|
*
|
|
* 5-May-93 DAL -- for 6.0.1d17
|
|
*
|
|
* Handle zero-length filenames like deleted directory entries, because the Finder
|
|
* gets really confused on a zero-length name, and it doesn't make much sense to
|
|
* begin with. Some DOS 3.3 disks have zero-length filenames to make the catalog
|
|
* look pretty.
|
|
*
|
|
***********************************************************************************************
|
|
|
|
machine M65816
|
|
string asis
|
|
|
|
print off
|
|
|
|
include 'my.all.macros'
|
|
include 'm16.debug'
|
|
;load 'C.Floor:MPW:aiigsincludes:my.cmn.d'
|
|
include 'my.common.equ'
|
|
include 'param.records'
|
|
include 'DOS.FST.identifiers'
|
|
|
|
print on
|
|
|
|
;======================================================================
|
|
;Below is the FST header definition used by GS/OS at boot time
|
|
;
|
|
;This PROC was adapted directly from the ProDOS FST v02.00 by Rob Turner
|
|
;
|
|
;======================================================================
|
|
|
|
|
|
EXPORT fst_header
|
|
fst_header PROC
|
|
import appl_call
|
|
import system_call
|
|
EXPORT code_start
|
|
code_start
|
|
|
|
DC.B 'FST ' ;Says I'm an FST
|
|
DC.L appl_call ;Process a normal application call
|
|
DC.L system_call ;Process an FST system call
|
|
DC.W my_id ;ID number (DOS 3.3) = $02
|
|
DC.W $1803 ;don't uppercase pathnames, not formattable, strip high bit(?).
|
|
;read-only,apple II format
|
|
DC.W $0103 ;Version 1.03 final
|
|
DC.W 256 ;block size
|
|
DC.L 560 ;Max Blocks (140K)
|
|
DC.L 32 ;Min Blocks-need at least 2 tracks.
|
|
DC.L $FFFFFFFF ;max file size in bytes.
|
|
DC.L $0000 ;reserved
|
|
DC.B @n_end-@n_strt ;length of next field
|
|
@n_strt DC.B 'Apple II DOS 3.3'
|
|
@n_end
|
|
dc.b @c_end-@c_strt ;length of comment
|
|
@c_strt DC.B 'DOS 3.3 FST v01.03'
|
|
;comment field
|
|
@c_end
|
|
DC.W 0000 ;reserved field
|
|
dc.b 'DOS 3.3 FST. Written by Monte Benaresh, maintained by Cary '
|
|
dc.b 'Farrier and Jack Valois. Tested by Linda Pan. '
|
|
dc.b 'Copyright 1992 Apple Computer'
|
|
|
|
|
|
ENDP
|
|
|
|
print off
|
|
include 'DOS.FST.storage'
|
|
print on
|
|
|
|
open_s PROCNAME ;shell for open call
|
|
|
|
import open
|
|
|
|
stz error
|
|
|
|
jsl lock_mem
|
|
|
|
; No need to check for the p_count here anymore. It is all done
|
|
; at the app entry point now.
|
|
;
|
|
;check_pcount
|
|
; lda class ;get the class of the call
|
|
; beq @class0 ;if class 0, no pcount
|
|
|
|
; lda p_cnt
|
|
; cmp #open1.pmax
|
|
; bcc @class0
|
|
; lda #invalid_pcount ;too big
|
|
; sta error
|
|
; bra exit
|
|
;@ok
|
|
|
|
; moved these checks into open call. we need to check to see if this
|
|
; is a DOS3.3 volume first before we return a non-bouncing error
|
|
; 9/17/91 JEV
|
|
|
|
;@check_access
|
|
; cmp #4 ;enough parameters for request_access?
|
|
; bcc @class0 ;no, can't check it
|
|
|
|
; ldy #open1.request_access
|
|
; lda [param_blk_ptr],y ;get the request access word
|
|
; and #%0000000000000010 ;check for write access
|
|
; beq @ok0 ;no write access
|
|
|
|
; lda #invalid_access
|
|
; sta error
|
|
; bra exit
|
|
;@ok0 ; opening resource fork?
|
|
; bra @class0
|
|
;
|
|
; lda p_cnt
|
|
; cmp #5
|
|
; bcc @class0 ; pcount too small ->
|
|
|
|
; ldy #open1.resource_number
|
|
; lda [<param_blk_ptr],y
|
|
; beq @class0 ; ok ->
|
|
|
|
; cmp #1 ; == 1?
|
|
; beq @class0 ; ok ->
|
|
; bne @range_err ; no ->
|
|
|
|
;
|
|
; lda #res_not_found
|
|
; sta error
|
|
; bra exit
|
|
|
|
;@range_err lda #parm_range_err
|
|
; sta error
|
|
; bra exit
|
|
|
|
@class0
|
|
jsr open
|
|
|
|
sta error ;save error
|
|
|
|
lda gen_buf_vp
|
|
tax
|
|
ora gen_buf_vp+2
|
|
beq @skip3
|
|
|
|
ldy gen_buf_vp+2
|
|
jsl release_seg
|
|
@skip3
|
|
exit
|
|
;brk $22
|
|
jsl unlock_mem
|
|
|
|
lda error ;restore error
|
|
cmp #1 ;set carry accordingly
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
|
|
;brk $11
|
|
|
|
jml sys_exit
|
|
|
|
error ds.w 1 ;temp storage for error code
|
|
|
|
ENDP
|
|
|
|
|
|
volume_s PROC ;shell for volume call
|
|
|
|
import volume
|
|
import free_sectors
|
|
import load_cat_secs
|
|
import match_vcr
|
|
import allocate_vcr
|
|
import device_id
|
|
|
|
;stz gen_buf_vp ;this is now done on entry
|
|
;stz gen_buf_vp+2
|
|
stz vcr_fcr_flags ;init flags
|
|
|
|
;brk $13
|
|
|
|
jsl lock_mem
|
|
jsr device_id ; we're looking for a device_id of $00
|
|
bcs err_done
|
|
beq @device_ok
|
|
lda #unknown_vol ; not a 5.25' drive return a bouncing error
|
|
bra err_done
|
|
@device_ok
|
|
lda class
|
|
beq @class0
|
|
@class1
|
|
; lda p_cnt
|
|
; cmp #volume1.pmax
|
|
; bcc @ok1
|
|
|
|
; lda #invalid_pcount
|
|
; brl exit
|
|
@ok1
|
|
ldy #volume1.vol_name ;copy pointer to direct page
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr+2
|
|
lda #vol_max_char+4 ;check the buffer size
|
|
cmp [user_ptr]
|
|
bcc @ok2
|
|
|
|
lda #vol_max_char+1 ;this is the size we need
|
|
ldy #$0002 ;point to string length field
|
|
sta [user_ptr],y ;let caller know what we need
|
|
lda #buff_too_small
|
|
;pha
|
|
;php
|
|
brl exit
|
|
@ok2
|
|
bra get_buffs
|
|
@class0
|
|
ldy #volume0.vol_name ;copy pointer to direct page
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr+2
|
|
|
|
get_buffs
|
|
lda #vol_name_buf ;get address of this internal buffer
|
|
sta <vol_name_ptr
|
|
|
|
lda #gen_buf_size ;let's get some buffer space for the vtoc & directory
|
|
jsl alloc_seg
|
|
bcc @ok
|
|
lda #out_of_mem ;can't get buffer space
|
|
brl done
|
|
@ok
|
|
stx gen_buf_vp ;4K buffer used by volume routine
|
|
sty gen_buf_vp+2
|
|
jsl deref
|
|
stx <gen_buf_ptr
|
|
sty <gen_buf_ptr+2
|
|
|
|
;lda gbuf_ptr
|
|
;sta <gen_buf_ptr
|
|
;lda gbuf_ptr+2
|
|
;sta <gen_buf_ptr+2
|
|
|
|
;brk $A9
|
|
|
|
|
|
jsr volume
|
|
bcc ok1
|
|
@vol_error ;volume identification failed
|
|
cmp #drvr_bad_parm ; bad parameter?
|
|
beq @mask ; yes ->
|
|
cmp #drvr_bad_count ; bad count because of the $100 request count?
|
|
bne err_done ; no, return the error back up ->
|
|
|
|
@mask lda #unknown_vol ;translate to bouncing error
|
|
err_done sec
|
|
brl done ;if error, pack up and leave
|
|
ok1
|
|
lda #<vol_name_buf ;set up our volume name for other routines
|
|
sta <volname_buf_ptr
|
|
lda #^vol_name_buf
|
|
sta <volname_buf_ptr+2
|
|
|
|
lda drvr_dev_num ; look in this device
|
|
sta supposed_dev
|
|
jsr allocate_vcr
|
|
bcc have_vcr
|
|
|
|
cmp #dup_volume ; duplicate volume error ?
|
|
bne err_done ; no ->
|
|
|
|
lda path_flag ; device name only?
|
|
and #$4000
|
|
beq name_out ; yes ->
|
|
|
|
err_bra lda #dup_volume ; no ->
|
|
bra err_done
|
|
|
|
*
|
|
* copy the volume name to the output buffer anyways
|
|
*
|
|
name_out lda class ;output the volume name
|
|
beq @class0
|
|
@class1
|
|
lda (vol_name_ptr) ;get volume name length
|
|
inc a ;account for leading character
|
|
ldy #2 ;point to start of g-string
|
|
sta [user_ptr],y ;set the length
|
|
|
|
lda <user_ptr
|
|
clc
|
|
adc #$0003 ;bump pointer to look at g-string plus room for�
|
|
;�leading '/' or ':'
|
|
sta <user_ptr
|
|
bcc @no_carry
|
|
inc <user_ptr+2
|
|
@no_carry
|
|
ldy #$0002 ;point to 1st char
|
|
bra @copy_string ;we're now ready to copy
|
|
|
|
@class0
|
|
lda (vol_name_ptr) ;get length
|
|
inc a ;account for leading character
|
|
sta [user_ptr]
|
|
@copy_string
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
|
|
ldy #$0002
|
|
@loop
|
|
lda (vol_name_ptr),y
|
|
beq @done ;if we hit a null, that's the end of the volume name
|
|
sta [user_ptr],y
|
|
iny
|
|
bpl @loop ;use bpl so if something weird happens, the most we'll�
|
|
;�trash is 32K!
|
|
@done
|
|
rep #%00100000
|
|
LONGA ON
|
|
|
|
lda class
|
|
bne @sep1
|
|
@sep0
|
|
ldy #1 ;point to space for '/'
|
|
lda [user_ptr],y
|
|
and #$FF00 ;erase the garbage
|
|
ora #'/' ;place the slash
|
|
sta [user_ptr],y
|
|
|
|
bra err_bra ; up ->
|
|
|
|
@sep1 ldy #1 ;point to space for ':'
|
|
lda [user_ptr],y
|
|
and #$FF00 ;erase the garbage
|
|
ora #':' ;place the colon
|
|
sta [user_ptr],y
|
|
|
|
bra err_bra ; up ->
|
|
|
|
****************
|
|
have_vcr
|
|
lda class ;here we go again!
|
|
beq @class0
|
|
@class1
|
|
lda (vol_name_ptr) ;get volume name length
|
|
inc a ;account for leading character
|
|
ldy #2 ;point to start of g-string
|
|
sta [user_ptr],y ;set the length
|
|
|
|
lda <user_ptr
|
|
clc
|
|
adc #$0003 ;bump pointer to look at g-string plus room for�
|
|
;�leading '/' or ':'
|
|
sta <user_ptr
|
|
bcc @no_carry
|
|
inc <user_ptr+2
|
|
@no_carry
|
|
ldy #$0002 ;point to 1st char
|
|
bra copy_string ;we're now ready to copy
|
|
|
|
@class0
|
|
lda (vol_name_ptr) ;get length
|
|
inc a ;account for leading character
|
|
sta [user_ptr]
|
|
copy_string
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
|
|
ldy #$0002
|
|
@loop
|
|
lda (vol_name_ptr),y
|
|
beq @done ;if we hit a null, that's the end of the volume name
|
|
sta [user_ptr],y
|
|
iny
|
|
bpl @loop ;use bpl so if something weird happens, the most we'll�
|
|
;�trash is 32K!
|
|
@done
|
|
rep #%00100000
|
|
LONGA ON
|
|
|
|
*
|
|
* output the total_blocks and free_blocks
|
|
*
|
|
lda class
|
|
bne @class1
|
|
@class0
|
|
ldy #1 ;point to space for '/'
|
|
lda [user_ptr],y
|
|
and #$FF00 ;erase the garbage
|
|
ora #'/' ;place the slash
|
|
sta [user_ptr],y
|
|
|
|
ldy #vtoc_sectors ;get # of sector per track
|
|
lda [vol_buf_ptr],y
|
|
and #32
|
|
bne @32a ;there are 32 sectors per track
|
|
lda #$230 ;# of 512-byte blocks on 5 1/4 volume
|
|
bra @stor
|
|
@32a
|
|
lda #$640 ;# of 512-byte blocks on a 3 1/2
|
|
@stor
|
|
ldy #volume0.total_blocks
|
|
sta [param_blk_ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [param_blk_ptr],y ;zero the high word
|
|
jsr free_sectors
|
|
ldy #volume0.free_blocks
|
|
sta [param_blk_ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [param_blk_ptr],y ;zero the high word
|
|
lda #my_id ;FST ID
|
|
ldy #volume0.file_sys_id
|
|
sta [param_blk_ptr],y
|
|
clc ;call successful
|
|
bra done
|
|
|
|
@class1
|
|
ldy #1 ;point to space for ':'
|
|
lda [user_ptr],y
|
|
and #$FF00 ;erase the garbage
|
|
ora #':' ;place the colon
|
|
sta [user_ptr],y
|
|
|
|
lda p_cnt
|
|
sta param_countdn
|
|
dec param_countdn ;this way we can use bmi
|
|
dec param_countdn ;dev_name
|
|
dec param_countdn ;vol_name
|
|
bmi done
|
|
;now we want total_blocks
|
|
ldy #vtoc_sectors ;get # of sector per track
|
|
lda [vol_buf_ptr],y
|
|
and #32
|
|
bne @32 ;there are 32 sectors per track
|
|
lda #$230 ;# of sectors on 5 1/4 volume
|
|
bra @store
|
|
@32 lda #$640 ;# of sectors on a 3 1/2
|
|
@store ldy #volume1.total_blocks
|
|
sta [param_blk_ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [param_blk_ptr],y ;zero the high word
|
|
dec param_countdn
|
|
bmi done
|
|
;get blocks free
|
|
jsr free_sectors
|
|
ldy #volume1.free_blocks
|
|
sta [param_blk_ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [param_blk_ptr],y ;zero the high word
|
|
dec param_countdn
|
|
bmi done
|
|
lda #my_id ;FST ID
|
|
ldy #volume1.file_sys_id
|
|
sta [param_blk_ptr],y
|
|
dec param_countdn
|
|
bmi done
|
|
lda #$0100 ;this is our "block" size
|
|
ldy #volume1.block_size
|
|
sta [param_blk_ptr],y
|
|
|
|
clc ;call successful
|
|
lda #0
|
|
exit
|
|
done pha
|
|
php
|
|
|
|
;jsl unlock_mem
|
|
bcc @no_error ;if no error, let VCR's stay
|
|
|
|
bit vcr_fcr_flags ;check whether we alocated a VCR
|
|
bpl @no_vcr ;high bit tells whether VCR was allocated
|
|
@cancel_vcr
|
|
ldy #vcr_open_cnt
|
|
lda #$0000
|
|
sta [vcr_ptr],y ;must zero the open count to release it!
|
|
|
|
ldy #vcr_id
|
|
lda [vcr_ptr],y ;get ID of the VCR
|
|
jsl release_vcr ;this invokes sys_remove_vol call to this fst
|
|
@no_vcr
|
|
@no_error
|
|
lda gen_buf_vp ;we may have to release this segment
|
|
tax
|
|
ora gen_buf_vp+2
|
|
beq @skip3
|
|
|
|
ldy gen_buf_vp+2
|
|
jsl release_seg
|
|
@skip3
|
|
|
|
plp
|
|
pla
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
|
|
;brk $88
|
|
|
|
jml sys_exit
|
|
|
|
param_countdn ds.w 1 ;local countdown var
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
free_sectors PROC ;determine the number of free sectors listed in the vtoc
|
|
;vtoc must be at vol_buf_ptr
|
|
;result is in accumulator
|
|
|
|
;first set up some looping limits
|
|
ldy #vtoc_sectors ;number of sectors per track
|
|
lda [vol_buf_ptr],y
|
|
and #$00FF ;take low byte
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a ;divide by 16 to get # of words of bitmap per track
|
|
sta words
|
|
stz result ;start with a clean slate
|
|
|
|
;let the loops begin!
|
|
ldy #vtoc_tracks ;# of tracks on the disk
|
|
lda [vol_buf_ptr],y
|
|
and #$00FF
|
|
sta track_index
|
|
@track_loop
|
|
lda words
|
|
sta words_index
|
|
lda track_index
|
|
dec a
|
|
bmi done
|
|
sta track_index
|
|
asl a
|
|
asl a ;multiply by 4 to get byte offset. this should clear carry
|
|
adc #vtoc_bitmap ;add offset to start of bitmap. carry should be clear
|
|
tay
|
|
@word_loop lda [vol_buf_ptr],y ;get a bitmap word
|
|
sta bitmap_temp
|
|
lda result
|
|
ldx #$0010
|
|
@bit_loop asl bitmap_temp
|
|
adc #$0000 ;carry set if we just shifted a high bit
|
|
dex
|
|
bne @bit_loop
|
|
sta result
|
|
dec words_index
|
|
beq @track_loop
|
|
iny
|
|
iny ;bump index to next word
|
|
bra @word_loop
|
|
done lda result ;this is a good place for the result
|
|
rts
|
|
|
|
|
|
words ds 1
|
|
result ds 1
|
|
track_index ds 1
|
|
words_index ds 1
|
|
bitmap_temp ds 1
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
get_file_info_s PROC ;shell for get_file_info call
|
|
|
|
import open_setup
|
|
import match_vcr
|
|
import load_cat_secs
|
|
import search_fcr
|
|
import check_dir
|
|
import get_file_info
|
|
import fill_param
|
|
import get_file_info0_f
|
|
import get_file_info1_f
|
|
import do_option_list
|
|
|
|
stz temp_vp
|
|
stz temp_vp+2
|
|
|
|
;brk $AC
|
|
|
|
jsl lock_mem
|
|
|
|
; lda class
|
|
; beq @class0
|
|
;@class1
|
|
; lda p_cnt
|
|
; cmp #get_file_info1.pmax
|
|
; bcc @ok
|
|
; lda #invalid_pcount
|
|
; brl error
|
|
;@ok
|
|
; bra do_it
|
|
;@class0
|
|
do_it
|
|
jsr open_setup ;among other things, this will find VCR for�
|
|
;�this volume name and verify identity
|
|
bcc @ok1
|
|
brl pack_up
|
|
|
|
@ok1
|
|
;jsr match_vcr ;find VCR for this volume name and verify identity
|
|
;bcc @ok2
|
|
;brl pack_up ;return with duplicate volume error
|
|
@ok2
|
|
;beq no_vcr
|
|
found_vcr ;we found the volume's vcr
|
|
stz good_vcr ;flag to say we have a vcr
|
|
|
|
ldy #vcr_buf_vp
|
|
lda [vcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [vcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
;stx gen_buf_ptr
|
|
;sty gen_buf_ptr+2 ;set up correct buffer for check_dir
|
|
stx vol_buf_ptr
|
|
sty vol_buf_ptr+2 ;set up correct buffer for check_dir
|
|
|
|
ldy #vcr_cat_sec_count
|
|
lda [vcr_ptr],y
|
|
sta cat_sec_count ;get that right, too
|
|
;bra have_vcr
|
|
|
|
no_vcr
|
|
;lda #$8000
|
|
;sta good_vcr ;keep flag to tell whether we have a vcr
|
|
;jsr load_cat_secs
|
|
;bcc check_file
|
|
;brl pack_up
|
|
@ok3
|
|
|
|
have_vcr
|
|
check_file ;was there a file to get info on?
|
|
lda (file_name_ptr) ;was there a filename?
|
|
bne handle_file
|
|
handle_vol
|
|
;a bunch of things get zeroes
|
|
stz aux_type ;fill the globals
|
|
stz eof+2
|
|
stz blks_used
|
|
|
|
lda cat_sec_count
|
|
inc a ;account for vtoc
|
|
ldx class
|
|
bne @1
|
|
sta blks_used
|
|
@1 xba
|
|
sta eof
|
|
lda #$000F
|
|
sta os_type
|
|
sta stor_type
|
|
lda #access_unlocked
|
|
sta access
|
|
|
|
bra stuff_globals
|
|
|
|
handle_file
|
|
;brk $02
|
|
|
|
;lda good_vcr ;did we have a valid vcr?
|
|
;bne chk_dir ;no, check the directory
|
|
|
|
ldy #vcr_open_cnt
|
|
lda [vcr_ptr],y ;see if any files are already open in this vcr
|
|
beq chk_dir ;we'll have to look in the directory
|
|
jsr search_fcr ;this routine will return number of fcr, for previous�
|
|
;�open of the file named in file_name_ptr, in old_fcr
|
|
;bcs chk_dir ;not found, check directory
|
|
bcc from_fcr ;fetch all info from fcr
|
|
|
|
chk_dir ;does this guy exist in the directory?
|
|
jsr check_dir ;this sub checks for filename in file_name_ptr
|
|
bcc @ok
|
|
lda #dir_error ;problem with the directory structure
|
|
brl pack_up
|
|
|
|
@ok
|
|
lda fde_index
|
|
bpl filename_good
|
|
file_not_here ;file not on this volume
|
|
lda #file_not_found
|
|
brl pack_up
|
|
|
|
filename_good ;file exists in directory
|
|
|
|
go_to_disk ;otherwise, we have to get it ourselves from disk
|
|
|
|
;lda #file_buf_size ;request segments for file buffers ***************
|
|
;jsl alloc_seg
|
|
;bcc @ok1
|
|
;lda #out_of_mem ;we *must* have those buffers!
|
|
;bra error
|
|
|
|
;@ok1
|
|
;stx temp_vp
|
|
;sty temp_vp+2
|
|
;jsl deref
|
|
;stx <fcr_buf_ptr
|
|
;sty <fcr_buf_ptr+2
|
|
;make it look like we have an FCR
|
|
;hopefully, the device number will be left over from
|
|
;the "volume" routine
|
|
|
|
lda gbuf_ptr ;use system gbuf
|
|
sta <fcr_buf_ptr
|
|
lda gbuf_ptr+2
|
|
sta <fcr_buf_ptr+2
|
|
|
|
lda #drvr_read
|
|
sta <drvr_call_num
|
|
jsr get_file_info ;get all the good stuff
|
|
bcc @ok2
|
|
bra error ;return with driver error
|
|
@ok2
|
|
stuff_globals ;now copy from globals to user param list
|
|
lda class
|
|
bne class1
|
|
class0
|
|
lda #$0001
|
|
sta p_cnt ;this will make the fill_param tables work right
|
|
|
|
|
|
lda os_type
|
|
cmp #$0F
|
|
bne @cont
|
|
lda #$230 ; auxtype = total blocks
|
|
sta aux_type
|
|
|
|
@cont lda #<get_file_info0_f
|
|
sta <fill_tabl ;set up for right parameter fill table
|
|
jsr fill_param
|
|
|
|
lda #0
|
|
bra pack_up ;all done!
|
|
|
|
class1
|
|
lda #<get_file_info1_f
|
|
sta <fill_tabl ;set up for right parameter fill table
|
|
jsr fill_param
|
|
|
|
lda p_cnt
|
|
cmp #8 ;do we need option list?
|
|
bcc @no_list
|
|
|
|
ldy #get_file_info1.option_list
|
|
jsr do_option_list
|
|
bcc @done
|
|
|
|
lda #buff_too_small
|
|
bra pack_up
|
|
@no_list
|
|
@done
|
|
lda #0
|
|
bra pack_up
|
|
|
|
from_fcr ;pull info out of the fcr and into the globals
|
|
ldy #fcr_access
|
|
lda [old_fcr_ptr],y
|
|
sta access
|
|
ldy #fcr_eof
|
|
lda [old_fcr_ptr],y
|
|
sta eof
|
|
iny
|
|
iny
|
|
lda [old_fcr_ptr],y
|
|
sta eof+2
|
|
ldy #fcr_aux
|
|
lda [old_fcr_ptr],y
|
|
sta aux_type
|
|
ldy #fcr_type
|
|
lda [old_fcr_ptr],y
|
|
sta os_type
|
|
ldy #fcr_blks_used
|
|
lda [old_fcr_ptr],y
|
|
sta blks_used
|
|
|
|
bra stuff_globals ;now give it all to the user
|
|
error
|
|
sec
|
|
pack_up
|
|
pha
|
|
|
|
;lda temp_vp
|
|
;tax
|
|
;ora temp_vp+2
|
|
;beq @skip1
|
|
;ldy temp_vp+2
|
|
;jsl release_seg
|
|
@skip1
|
|
lda gen_buf_vp
|
|
tax
|
|
ora gen_buf_vp+2
|
|
beq @skip3
|
|
ldy gen_buf_vp+2
|
|
jsl release_seg
|
|
@skip3
|
|
exit
|
|
;brk $22
|
|
|
|
jsl unlock_mem
|
|
|
|
pla
|
|
cmp #1
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
|
|
jml sys_exit
|
|
|
|
good_vcr ds 1
|
|
|
|
ENDP
|
|
|
|
|
|
get_dir_entry_s PROCNAME ;shell for the get_dir_entry call
|
|
|
|
import get_dir_entry
|
|
|
|
;brk $ED
|
|
|
|
jsl lock_mem
|
|
|
|
ldx <g_fcr_ptr ;SCM provides the FCR & VCR
|
|
ldy <g_fcr_ptr+2
|
|
jsl deref
|
|
stx <fcr_ptr
|
|
sty <fcr_ptr+2
|
|
|
|
ldx <g_vcr_ptr
|
|
ldy <g_vcr_ptr+2
|
|
jsl deref
|
|
stx <vcr_ptr
|
|
sty <vcr_ptr+2
|
|
|
|
lda #gen_buf_size ;let's get some buffer space for the vtoc & directory
|
|
jsl alloc_seg
|
|
bcc @mem_ok
|
|
|
|
lda #out_of_mem ;can't get buffer space
|
|
rts
|
|
@mem_ok
|
|
stx gen_buf_vp ;4K buffer used by volume routine
|
|
sty gen_buf_vp+2
|
|
jsl deref
|
|
stx <gen_buf_ptr
|
|
sty <gen_buf_ptr+2
|
|
|
|
;lda #file_buf_size ;request segments for file buffers for find_eof
|
|
;jsl alloc_seg
|
|
;bcc @ok1
|
|
;lda #out_of_mem ;we *must* have those buffers!
|
|
;bra exit2
|
|
@ok1
|
|
;stx temp_vp
|
|
;sty temp_vp+2
|
|
;jsl deref
|
|
;stx <fcr_buf_ptr
|
|
;sty <fcr_buf_ptr+2 ;make it look like we have an FCR
|
|
|
|
lda gbuf_ptr
|
|
sta <fcr_buf_ptr ;use system gbuf
|
|
lda gbuf_ptr+2
|
|
sta <fcr_buf_ptr+2
|
|
|
|
lda class
|
|
; beq @class0
|
|
;@class1
|
|
; WITH get_dir_entry1
|
|
|
|
; lda p_cnt
|
|
; cmp #pmax
|
|
; bcc @ok2
|
|
; lda #invalid_pcount
|
|
; sec
|
|
; bra exit
|
|
;@ok2
|
|
; ENDWITH
|
|
@class0
|
|
jsr get_dir_entry
|
|
|
|
exit
|
|
;pha
|
|
|
|
;lda temp_vp
|
|
;tax
|
|
;ora temp_vp+2
|
|
;beq @skip1
|
|
;ldy temp_vp+2
|
|
;jsl release_seg
|
|
@skip1
|
|
;pla
|
|
exit2 ;alternate exit which does not deallocate buffer
|
|
|
|
pha ;save error code
|
|
|
|
lda gen_buf_vp
|
|
tax
|
|
ora gen_buf_vp+2 ;is vp valid?
|
|
beq @skip3
|
|
|
|
ldy gen_buf_vp+2
|
|
jsl release_seg
|
|
@skip3
|
|
|
|
jsl unlock_mem
|
|
|
|
pla ;restore error
|
|
cmp #1
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
|
|
jml sys_exit
|
|
|
|
ENDP
|
|
|
|
|
|
read_s PROCNAME ;shell for the read call
|
|
import read, find_fde
|
|
|
|
jsl lock_mem
|
|
|
|
ldx <g_fcr_ptr ;set up real pointers to vp's to fcr & vcr provided�
|
|
ldy <g_fcr_ptr+2 ;�by the SCM
|
|
jsl deref
|
|
stx <fcr_ptr
|
|
sty <fcr_ptr+2
|
|
ldx <g_vcr_ptr
|
|
ldy <g_vcr_ptr+2
|
|
jsl deref
|
|
stx <vcr_ptr
|
|
sty <vcr_ptr+2
|
|
|
|
; init fde_ptr properly so that if we need to read anything out of the file
|
|
; directory entry, we won't be using an invalid pointer (and reading who-knows-what)
|
|
|
|
ldy #vcr_buf_vp ;set up correct buffer for find_fde
|
|
lda [vcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [vcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx vol_buf_ptr
|
|
sty vol_buf_ptr+2
|
|
|
|
ldy #fcr_fde_num
|
|
lda [fcr_ptr],y ;need these to set up ptr to fde
|
|
tax
|
|
ldy #fcr_cat_sec
|
|
lda [fcr_ptr],y
|
|
jsr find_fde ;this sets up fde_ptr
|
|
|
|
|
|
; lda class
|
|
; beq @class0
|
|
;@class1
|
|
; lda p_cnt
|
|
; cmp #read1.pmax
|
|
; bcc @ok1
|
|
; lda #invalid_pcount
|
|
; sec
|
|
; bra exit
|
|
;@ok1
|
|
;@class0
|
|
jsr read
|
|
exit
|
|
pha
|
|
php
|
|
|
|
jsl unlock_mem
|
|
|
|
plp
|
|
pla
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
jml sys_exit
|
|
|
|
ENDP
|
|
|
|
|
|
close_s PROCNAME ;shell for the CLOSE call
|
|
import close
|
|
|
|
jsl lock_mem
|
|
|
|
ldx <g_fcr_ptr ;set up real pointers to vp's to fcr & vcr provided�
|
|
ldy <g_fcr_ptr+2 ;�by the SCM
|
|
jsl deref
|
|
stx <fcr_ptr
|
|
sty <fcr_ptr+2
|
|
ldx <g_vcr_ptr
|
|
ldy <g_vcr_ptr+2
|
|
jsl deref
|
|
stx <vcr_ptr
|
|
sty <vcr_ptr+2
|
|
check_pcnt
|
|
; lda class
|
|
; beq @class0
|
|
;@class1
|
|
; WITH close1
|
|
|
|
; lda p_cnt
|
|
; cmp #pmax
|
|
; bcc @ok1
|
|
; lda #invalid_pcount
|
|
; sec
|
|
; bra exit
|
|
;@ok1
|
|
; ENDWITH
|
|
@class0
|
|
|
|
do_close
|
|
ldy #fcr_type
|
|
lda [fcr_ptr],y
|
|
cmp #$000F ;is it a directory?
|
|
beq free_fcr ;if directory file then don't release its buffer�
|
|
;�because it is shared with the VCR
|
|
ldy #fcr_buf_vp
|
|
lda [fcr_ptr],y ;get fcr buffer's vp so we can release it
|
|
tax
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y
|
|
tay
|
|
jsl release_seg
|
|
|
|
free_fcr
|
|
ldy #fcr_ref_num
|
|
lda [fcr_ptr],y
|
|
jsl release_fcr
|
|
bcc @ok1
|
|
lda #invalid_ref_num OR $8000 ;internal error
|
|
bra exit
|
|
@ok1
|
|
ldy #vcr_open_cnt
|
|
lda [vcr_ptr],y ;get the open count
|
|
bne @ok2 ;make sure open count isn't aleady 0
|
|
lda #8000 ;generic internal error
|
|
bra exit
|
|
@ok2
|
|
dec a ;one less open file
|
|
sta [vcr_ptr],y
|
|
|
|
no_err ;successful close
|
|
clc
|
|
lda #$0000
|
|
|
|
exit
|
|
pha
|
|
php
|
|
|
|
jsl unlock_mem
|
|
|
|
plp
|
|
pla
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
jml sys_exit
|
|
|
|
ENDP
|
|
|
|
|
|
get_dev_num_s PROCNAME ;shell for the GET_DEV_NUM call
|
|
|
|
import open_setup
|
|
import match_vcr
|
|
import find_vol_online
|
|
|
|
;brk $09
|
|
|
|
;stz gen_buf_vp
|
|
;stz gen_buf_vp+2
|
|
|
|
jsl lock_mem
|
|
|
|
check_pcnt
|
|
; lda class
|
|
; beq @class0
|
|
;@class1
|
|
; WITH get_dev_num1
|
|
|
|
; lda p_cnt
|
|
; cmp #pmax
|
|
; bcc @ok1
|
|
; lda #invalid_pcount
|
|
; sec
|
|
; bra exit
|
|
;@ok1
|
|
; ENDWITH
|
|
@class0
|
|
|
|
check_scm ;see whether SCM has done the work for us yet
|
|
lda <dev1_num ;is the number there already?
|
|
beq hard_way ;if not, we have to figure it out ourselves
|
|
easy_way
|
|
ldy #get_dev_num1.dev_num ;anticipate class 1
|
|
ldx class
|
|
bne @store ;class 1, store the value
|
|
@class0
|
|
ldy #get_dev_num0.dev_num
|
|
@store
|
|
sta [param_blk_ptr],y
|
|
|
|
bra no_err ;that's the whole show!
|
|
|
|
hard_way ;we have to find the volume ourselves
|
|
jsr open_setup ;init vars, set up buffers, put volume name in�
|
|
;�volname_buf_ptr
|
|
bcc @ok
|
|
cmp #dup_volume ; duplicate volume? if yes, that means that someone else
|
|
; will claim it...
|
|
bne @1
|
|
|
|
lda #unknown_vol
|
|
@1 sec
|
|
bra exit ;return with error
|
|
@ok
|
|
ldy #vcr_dev
|
|
lda [vcr_ptr],y ;get device number
|
|
bra easy_way ;we got it!
|
|
|
|
|
|
;have_name ;check for vcr with the given name
|
|
;jsr match_vcr ;find vcr for volume name in volname_buf_ptr
|
|
;bcc @ok
|
|
;lda #vol_not_found
|
|
;bra exit ;return with error
|
|
;@ok
|
|
;bne use_old_vcr ;if we got a match, use it
|
|
;stz supposed_dev
|
|
;jsr find_vol_online ;no vcr, walk the devices
|
|
;bcc @ok1
|
|
;lda #vol_not_found
|
|
;bra exit
|
|
@ok1
|
|
;lda <drvr_dev_num ;the answer is here
|
|
;bra easy_way ;mail it and we're done
|
|
|
|
use_old_vcr ;we have a vcr for the volume
|
|
;vcr_ptr points to it
|
|
;lda <dev1_num
|
|
;bra easy_way
|
|
|
|
|
|
no_err ;successful get_dev_num
|
|
clc
|
|
lda #$0000
|
|
|
|
exit
|
|
pha
|
|
php
|
|
|
|
lda gen_buf_vp
|
|
tax
|
|
ora gen_buf_vp+2
|
|
beq @skip3
|
|
ldy gen_buf_vp+2
|
|
jsl release_seg
|
|
@skip3
|
|
|
|
jsl unlock_mem
|
|
|
|
plp
|
|
pla
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
jml sys_exit
|
|
|
|
ENDP
|
|
|
|
|
|
get_eof_s PROCNAME ;shell for the GET_EOF call
|
|
|
|
jsl lock_mem
|
|
|
|
ldx <g_fcr_ptr ;set up real pointers to vp's to fcr & vcr provided�
|
|
ldy <g_fcr_ptr+2 ;�by the SCM
|
|
jsl deref
|
|
stx <fcr_ptr
|
|
sty <fcr_ptr+2
|
|
|
|
; ldx <g_vcr_ptr
|
|
; ldy <g_vcr_ptr+2
|
|
; jsl deref
|
|
; stx <vcr_ptr
|
|
; sty <vcr_ptr+2
|
|
check_pcnt
|
|
; lda class
|
|
; beq @class0
|
|
;@class1
|
|
; WITH get_eof1
|
|
|
|
; lda p_cnt
|
|
; cmp #pmax
|
|
; bcc @ok1
|
|
; lda #invalid_pcount
|
|
; sec
|
|
; bra exit
|
|
;@ok1
|
|
; ENDWITH
|
|
@class0
|
|
|
|
do_get_eof
|
|
ldy #fcr_eof
|
|
lda [fcr_ptr],y ;get the eof (of all things)
|
|
tax
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y ;high word
|
|
pha ;save accum
|
|
|
|
lda class
|
|
beq @class0
|
|
@class1
|
|
pla ;get back low word
|
|
|
|
ldy #get_eof1.eof+2
|
|
sta [param_blk_ptr],y
|
|
txa ;restore low word
|
|
dey
|
|
dey
|
|
sta [param_blk_ptr],y
|
|
|
|
bra no_err ;that's it!
|
|
@class0
|
|
pla ;get back low word
|
|
|
|
ldy #get_eof0.eof+2
|
|
sta [param_blk_ptr],y
|
|
txa ;restore low word
|
|
dey
|
|
dey
|
|
sta [param_blk_ptr],y
|
|
|
|
no_err
|
|
clc
|
|
lda #$0000
|
|
|
|
exit
|
|
pha
|
|
php
|
|
|
|
jsl unlock_mem
|
|
|
|
plp
|
|
pla
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
jml sys_exit
|
|
|
|
ENDP
|
|
|
|
|
|
get_mark_s PROCNAME ;shell for the GET_MARK call
|
|
|
|
jsl lock_mem
|
|
|
|
ldx <g_fcr_ptr ;set up real pointers to vp's to fcr & vcr provided�
|
|
ldy <g_fcr_ptr+2 ;�by the SCM
|
|
jsl deref
|
|
stx <fcr_ptr
|
|
sty <fcr_ptr+2
|
|
|
|
; ldx <g_vcr_ptr
|
|
; ldy <g_vcr_ptr+2
|
|
; jsl deref
|
|
; stx <vcr_ptr
|
|
; sty <vcr_ptr+2
|
|
check_pcnt
|
|
; lda class
|
|
; beq @class0
|
|
;@class1
|
|
; lda p_cnt
|
|
; cmp #get_mark1.pmax
|
|
; bcc @ok1
|
|
; lda #invalid_pcount
|
|
; sec
|
|
; bra exit
|
|
;@ok1
|
|
;@class0
|
|
|
|
do_get_mark
|
|
ldy #fcr_mark
|
|
lda [fcr_ptr],y ;get the mark (of all things)
|
|
tax
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y ;high word
|
|
pha ;save accum
|
|
|
|
lda class
|
|
beq @class0
|
|
@class1
|
|
pla ;get back low word
|
|
|
|
ldy #get_mark1.position+2
|
|
sta [param_blk_ptr],y
|
|
txa ;restore low word
|
|
dey
|
|
dey
|
|
sta [param_blk_ptr],y
|
|
|
|
bra no_err ;that's it!
|
|
@class0
|
|
pla ;get back low word
|
|
|
|
ldy #get_mark0.position+2
|
|
sta [param_blk_ptr],y
|
|
txa ;restore low word
|
|
dey
|
|
dey
|
|
sta [param_blk_ptr],y
|
|
|
|
no_err
|
|
clc
|
|
lda #$0000
|
|
|
|
exit
|
|
pha
|
|
php
|
|
|
|
jsl unlock_mem
|
|
|
|
plp
|
|
pla
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
jml sys_exit
|
|
|
|
ENDP
|
|
|
|
|
|
set_mark_s PROCNAME ;shell for the SET_MARK call
|
|
|
|
;brk $EF
|
|
|
|
jsl lock_mem
|
|
|
|
ldx <g_fcr_ptr ;set up real pointers to vp's to fcr & vcr provided�
|
|
ldy <g_fcr_ptr+2 ;�by the SCM
|
|
jsl deref
|
|
stx <fcr_ptr
|
|
sty <fcr_ptr+2
|
|
|
|
; ldx <g_vcr_ptr
|
|
; ldy <g_vcr_ptr+2
|
|
; jsl deref
|
|
; stx <vcr_ptr
|
|
; sty <vcr_ptr+2
|
|
check_pcnt
|
|
lda class
|
|
beq @class0
|
|
@class1
|
|
ldy #set_mark1.displacement
|
|
lda [param_blk_ptr],y
|
|
sta disp
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta disp+2
|
|
|
|
; lda p_cnt
|
|
; cmp #set_mark1.pmax
|
|
; bcc get_base
|
|
bra get_base
|
|
|
|
; lda #invalid_pcount
|
|
; sec
|
|
; brl exit
|
|
;@ok1
|
|
@class0
|
|
ldy #set_mark0.position
|
|
lda [param_blk_ptr],y
|
|
sta disp
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta disp+2
|
|
|
|
bra absolute ;class 0 displacement is always absolute
|
|
|
|
get_base ;fetch displacement from param block
|
|
ldy #set_mark1.base
|
|
lda [param_blk_ptr],y
|
|
beq absolute ;base = 0 --> mark = displacement
|
|
|
|
dec a
|
|
beq minus ;base = 1 --> mark = eof - displacement
|
|
|
|
dec a
|
|
beq add ;base = 2 --> mark = mark + displacement
|
|
|
|
dec a
|
|
beq subtract ;base = 3 --> mark = mark - displacement
|
|
|
|
bad_base ;if we get here, base had an invalid value
|
|
lda #parm_range_err ;base is out of range
|
|
brl exit ;can't continue
|
|
|
|
absolute ;set mark to (displacement)
|
|
lda disp
|
|
sta new_mark
|
|
lda disp+2
|
|
sta new_mark+2
|
|
bra validate_new_mark ;make sure it's in range, and we're done!
|
|
|
|
minus ;set mark to (eof - displacement)
|
|
ldy #fcr_eof
|
|
lda [fcr_ptr],y ;get eof
|
|
sec
|
|
sbc disp
|
|
sta new_mark
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y ;get high word of eof
|
|
sbc disp+2
|
|
bcs @no_underflow
|
|
|
|
lda #out_of_range ;position fell below 0
|
|
bra exit
|
|
@no_underflow
|
|
sta new_mark+2
|
|
|
|
bra set_new_mark ;new mark is guaranteed to be valid now
|
|
|
|
subtract ;set mark to (mark - displacement)
|
|
ldy #fcr_mark
|
|
lda [fcr_ptr],y
|
|
sec
|
|
sbc disp
|
|
sta new_mark
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y ;get high word of present mark
|
|
sbc disp+2
|
|
bcs @no_underflow
|
|
|
|
lda #out_of_range ;mark would go below 0
|
|
bra exit
|
|
@no_underflow
|
|
sta new_mark+2
|
|
|
|
bra set_new_mark ;new mark is guaranteed to be valid now
|
|
|
|
add ;set mark to (mark + displacement)
|
|
ldy #fcr_mark
|
|
lda [fcr_ptr],y
|
|
clc
|
|
adc disp
|
|
sta new_mark
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y ;get high word of mark
|
|
adc disp+2
|
|
bcc @no_overflow
|
|
|
|
lda #out_of_range ;new mark overflowed 32-bit range
|
|
bra exit
|
|
@no_overflow
|
|
sta new_mark+2
|
|
|
|
validate_new_mark ;check value of new mark against eof
|
|
lda new_mark+2
|
|
ldy #fcr_eof+2
|
|
cmp [fcr_ptr],y ;compare to high word of eof
|
|
bcc @in_range
|
|
|
|
bne @out_of_range
|
|
@maybe ;now check low words
|
|
dey
|
|
dey
|
|
lda [fcr_ptr],y ;get low word of eof
|
|
cmp new_mark
|
|
bcs @in_range
|
|
@out_of_range
|
|
lda #out_of_range
|
|
bra exit
|
|
@in_range
|
|
set_new_mark
|
|
lda new_mark
|
|
ldy #fcr_mark
|
|
sta [fcr_ptr],y ;set new mark
|
|
lda new_mark+2
|
|
iny
|
|
iny
|
|
sta [fcr_ptr],y ;that completes the new mark setting!
|
|
no_err
|
|
clc
|
|
lda #$0000
|
|
|
|
exit
|
|
pha
|
|
|
|
jsl unlock_mem
|
|
|
|
pla
|
|
cmp #1
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
|
|
jml sys_exit
|
|
|
|
disp ds.l 1 ;local copy of user parameter "displacement"
|
|
new_mark ds.l 1 ;scratch space for new mark value
|
|
|
|
ENDP
|
|
|
|
|
|
flush_s PROCNAME ;handle the FLUSH call
|
|
|
|
check_pcnt ;this is about all we do?
|
|
lda class
|
|
beq @class0
|
|
@class1
|
|
lda p_cnt
|
|
cmp #2+1 ;max pcount for FLUSH is 2
|
|
bcc @ok1
|
|
lda #invalid_pcount
|
|
sec
|
|
bra exit
|
|
@ok1
|
|
@class0
|
|
|
|
no_err
|
|
clc
|
|
lda #$0000
|
|
|
|
exit
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
jml sys_exit
|
|
|
|
ENDP
|
|
|
|
fst_specific_s PROCNAME ;shell for fst-specific calls
|
|
|
|
import set_text_mode
|
|
import get_text_mode
|
|
|
|
WITH fst_specific
|
|
|
|
ldy #command
|
|
lda [param_blk_ptr],y ;get command parameter
|
|
beq @bad_command ;0 not a valid command
|
|
|
|
dec a
|
|
bne @next1
|
|
|
|
jsr set_text_mode ;command = 1
|
|
bra exit
|
|
@next1
|
|
dec a
|
|
bne @next2
|
|
|
|
jsr get_text_mode ;command = 2
|
|
bra exit
|
|
@next2
|
|
@bad_command ;command number not valid
|
|
lda #invalid_fst_op
|
|
sec
|
|
exit
|
|
cmp #1
|
|
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
jml sys_exit
|
|
|
|
ENDWITH
|
|
|
|
ENDP
|
|
|
|
|
|
not_supported2 PROCNAME ;handle FST calls which are not supported because they require�
|
|
;�write operations
|
|
|
|
;this routine handles calls which take a pathname as a parameter
|
|
|
|
;if the pathname refers to a DOS 3.3 disk, we return an�
|
|
;�invalid_fst_op error
|
|
|
|
;if the pathname refers to a non-DOS 3.3 disk, we return a�
|
|
;�unknown_vol error, which allows the call to bounce to other�
|
|
;�FST's
|
|
|
|
import open_setup
|
|
|
|
;brk $AC
|
|
|
|
jsl lock_mem
|
|
check_volume ;the main thing is to know whom the volume belongs to
|
|
jsr open_setup ;this routine allocates a buffer, sets up name buffer�
|
|
;�pointers, parses the path provided by SCM,
|
|
|
|
bcs pack_up ;return with unknown_vol, or pathalogical error
|
|
@ok1
|
|
lda #drvr_wr_prot ;call was meant for us
|
|
pack_up
|
|
pha
|
|
|
|
lda gen_buf_vp
|
|
tax
|
|
ora gen_buf_vp+2
|
|
beq @skip3
|
|
ldy gen_buf_vp+2
|
|
jsl release_seg
|
|
@skip3
|
|
exit
|
|
;brk $22
|
|
|
|
jsl unlock_mem
|
|
|
|
pla
|
|
cmp #1
|
|
bcc @noErr
|
|
|
|
ora error_priority
|
|
@noErr
|
|
|
|
jml sys_exit
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
;======================================================================
|
|
;Below is the main entry point for ALL standard operating system calls.
|
|
;
|
|
;This PROC was adapted directly from the ProDOS FST v02.00 by Rob Turner
|
|
;
|
|
;Input: X = Call number * 2
|
|
; Y = Class number * 2
|
|
; A = undefined
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT appl_call
|
|
appl_call PROCNAME
|
|
|
|
import max_call
|
|
|
|
sta $FF0500 ;debug tag
|
|
|
|
phk ;set up our bank register
|
|
plb
|
|
|
|
rep #$30 ; 16 bit A & X
|
|
|
|
stz p_cnt ; zero it out
|
|
stz error_priority ; for bouncing errors
|
|
|
|
sty class ;keep this around for future reference
|
|
cpy #0
|
|
beq @class0
|
|
@class1
|
|
lda [param_blk_ptr] ;first word of class1 is always pcount
|
|
sta p_cnt ;save for future reference
|
|
|
|
lda pcount_tbl,x ; get the min/max pcount for this call
|
|
sep #$20 ; 8 bit accum. please
|
|
LONGA OFF
|
|
|
|
sta p_max_cnt
|
|
xba
|
|
sta p_min_cnt
|
|
lda p_cnt
|
|
|
|
cmp p_max_cnt ; Max pcount - pcount
|
|
bcs pcnt_err ; pcount too big
|
|
cmp p_min_cnt ; Min pcount - pcount
|
|
blt pcnt_err ; pcount too small
|
|
|
|
rep #$20 ; back to 16 bit accu.
|
|
LONGA ON
|
|
|
|
@class0
|
|
|
|
stz gen_buf_vp ;invalidate vp's until buf gets allocated
|
|
stz gen_buf_vp+2
|
|
|
|
cpx #end_tbl+1 ;check command number
|
|
bcs cmd_error
|
|
jmp (cmd_tbl,x) ;call the function
|
|
|
|
pcnt_err ; bad pcount in the call
|
|
|
|
rep #$20 ; back to 16 bit accu.
|
|
LONGA ON
|
|
lda #invalid_pcount
|
|
bra err
|
|
|
|
cmd_error ;bad command number, or not FST call
|
|
|
|
lda #bad_system_call
|
|
err sec
|
|
ora error_priority
|
|
jml sys_exit
|
|
|
|
not_supported ;call not supported by this FST
|
|
;we get here if the call takes a ref num as a parameter, in�
|
|
;�which case we are certain the call was meant for this FST
|
|
|
|
lda #drvr_wr_prot
|
|
bra err
|
|
|
|
not_implemented ; no handler for this call
|
|
lda #invalid_fst_op
|
|
bra err
|
|
|
|
cmd_tbl dc.w cmd_error ;undefined 00
|
|
DC.W not_supported2 ;CREATE 01
|
|
DC.W not_supported2 ;DESTROY 02
|
|
DC.W cmd_error ;OS_SHUTDOWN 03
|
|
DC.W not_supported2 ;CHANGE_PATH 04
|
|
DC.W not_supported2 ;SET_FILE_INFO 05
|
|
DC.W get_file_info_s ;GET_FILE_INFO 06
|
|
DC.W not_implemented ;JUDGE_NAME 07
|
|
DC.W volume_s ;VOLUME 08
|
|
DC.W cmd_error ;SET_PREFIX 09
|
|
DC.W cmd_error ;GET_PREFIX 0A
|
|
DC.W not_supported2 ;CLEAR_BACKUP 0B
|
|
DC.W cmd_error ;SET_SYS_PREFS 0C
|
|
DC.W cmd_error ;NULL 0D
|
|
DC.W cmd_error ;EXPAND_PATH 0E
|
|
DC.W cmd_error ;GET_SYS_PREFS 0F
|
|
DC.W open_s ;OPEN 10
|
|
DC.W cmd_error ;NEWLINE 11
|
|
DC.W read_s ;READ 12
|
|
DC.W not_supported ;WRITE 13
|
|
DC.W close_s ;CLOSE 14
|
|
DC.W flush_s ;FLUSH 15
|
|
DC.W set_mark_s ;SET_MARK 16
|
|
DC.W get_mark_s ;GET_MARK 17
|
|
DC.W not_supported ;SET_EOF 18
|
|
DC.W get_eof_s ;GET_EOF 19
|
|
DC.W cmd_error ;SET_LEVEL 1A
|
|
DC.W cmd_error ;GET_LEVEL 1B
|
|
DC.W get_dir_entry_s ;GET_DIR_ENTRY 1C
|
|
DC.W cmd_error ;BEGIN_SESSION 1D
|
|
DC.W cmd_error ;END_SESSION 1E
|
|
DC.W cmd_error ;SESSION_STATUS 1F
|
|
DC.W get_dev_num_s ;GET_DEV_NUM 20
|
|
DC.W cmd_error ;GET_LAST_DEV 21
|
|
DC.W cmd_error ;READ_BLOCK 22
|
|
DC.W cmd_error ;WRITE_BLOCK 23
|
|
DC.W not_supported ;FORMAT 24
|
|
DC.W not_supported ;ERASE_DISK 25
|
|
DC.W cmd_error ;RESET_CACHE 26
|
|
DC.W cmd_error ;GET_NAME 27
|
|
DC.W cmd_error ;GET_BOOT_VOL 28
|
|
DC.W cmd_error ;QUIT 29
|
|
DC.W cmd_error ;GET_VERSION 2A
|
|
DC.W cmd_error ;GET_FST_INFO 2B
|
|
DC.W cmd_error ;D_INFO 2C
|
|
DC.W cmd_error ;D_STATUS 2D
|
|
DC.W cmd_error ;D_CONTROL 2E
|
|
DC.W cmd_error ;D_READ 2F
|
|
DC.W cmd_error ;D_WRITE 30
|
|
DC.W cmd_error ;ALLOC_INT and BIND_INT 31
|
|
DC.W cmd_error ;DEALLOC_INT and UNBIND_INT 32
|
|
DC.W fst_specific_s ;FST_SPECIFIC 33
|
|
|
|
;EXPORT end_tbl
|
|
end_tbl equ * - cmd_tbl
|
|
|
|
;=====================================================================
|
|
; Below is the table used to check the pcount on the calls that are
|
|
; not supported. This should have been done in general for all the
|
|
; calls instead of doing it inline in each call. Oh well I didn't
|
|
; start this thing and "to each his own". If I had time I would go back
|
|
; and change all the calls, but we're too close to beta to do it now.
|
|
; jev 3/26/91
|
|
;=====================================================================
|
|
|
|
pcount_tbl DC.W cmd_error
|
|
DC.W max_pcnt7+min_pcnt1 ;CREATE 01
|
|
DC.W max_pcnt1+min_pcnt1 ;DESTROY 02
|
|
DC.W max_pcnt1+min_pcnt1 ;OS_SHUTDOWN 03
|
|
DC.W max_pcnt3+min_pcnt2 ;CHANGE_PATH 04
|
|
DC.W max_pcnt12+min_pcnt2 ;SET_FILE_INFO 05
|
|
DC.W max_pcnt12+min_pcnt1 ;GET_FILE_INFO 06
|
|
DC.W max_pcnt6+min_pcnt1 ;JUDGE_NAME 07
|
|
DC.W max_pcnt6+min_pcnt2 ;VOLUME 08
|
|
DC.W max_pcnt2+min_pcnt2 ;SET_PREFIX 09
|
|
DC.W max_pcnt2+min_pcnt2 ;GET_PREFIX 0A
|
|
DC.W max_pcnt1+min_pcnt1 ;CLEAR_BACKUP 0B
|
|
DC.W max_pcnt1+min_pcnt1 ;SET_SYS_PREFS 0C
|
|
DC.W max_pcnt0+min_pcnt0 ;NULL 0D
|
|
DC.W max_pcnt3+min_pcnt2 ;EXPAND_PATH 0E
|
|
DC.W max_pcnt1+min_pcnt1 ;GET_SYS_PREFS 0F
|
|
DC.W max_pcnt15+min_pcnt2 ;OPEN 10
|
|
DC.W max_pcnt4+min_pcnt4 ;NEWLINE 11
|
|
DC.W max_pcnt5+min_pcnt4 ;READ 12
|
|
DC.W max_pcnt5+min_pcnt4 ;WRITE 13
|
|
DC.W max_pcnt1+min_pcnt1 ;CLOSE 14
|
|
DC.W max_pcnt1+min_pcnt1 ;FLUSH 15
|
|
DC.W max_pcnt3+min_pcnt3 ;SET_MARK 16
|
|
DC.W max_pcnt2+min_pcnt2 ;GET_MARK 17
|
|
DC.W max_pcnt3+min_pcnt3 ;SET_EOF 18
|
|
DC.W max_pcnt2+min_pcnt2 ;GET_EOF 19
|
|
DC.W max_pcnt1+min_pcnt1 ;SET_LEVEL 1A
|
|
DC.W max_pcnt1+min_pcnt1 ;GET_LEVEL 1B
|
|
DC.W max_pcnt17+min_pcnt5 ;GET_DIR_ENTRY 1C
|
|
DC.W max_pcnt0+min_pcnt0 ;BEGIN_SESSION 1D
|
|
DC.W max_pcnt0+min_pcnt0 ;END_SESSION 1E
|
|
DC.W max_pcnt1+min_pcnt1 ;SESSION_STATUS 1F
|
|
DC.W max_pcnt2+min_pcnt2 ;GET_DEV_NUM 20
|
|
DC.W max_pcnt0+min_pcnt0 ;GET_LAST_DEV 21
|
|
DC.W max_pcnt0+min_pcnt0 ;READ_BLOCK 22
|
|
DC.W max_pcnt0+min_pcnt0 ;WRITE_BLOCK 23
|
|
DC.W max_pcnt4+min_pcnt3 ;FORMAT 24
|
|
DC.W max_pcnt4+min_pcnt3 ;ERASE_DISK 25
|
|
DC.W max_pcnt0+min_pcnt0 ;RESET_CACHE 26
|
|
DC.W max_pcnt1+min_pcnt1 ;GET_NAME 27
|
|
DC.W max_pcnt1+min_pcnt1 ;GET_BOOT_VOL 28
|
|
DC.W max_pcnt2+min_pcnt0 ;QUIT 29
|
|
DC.W max_pcnt1+min_pcnt1 ;GET_VERSION 2A
|
|
DC.W max_pcnt8+min_pcnt2 ;GET_FST_INFO 2B
|
|
DC.W max_pcnt11+min_pcnt2 ;D_INFO 2C
|
|
DC.W max_pcnt5+min_pcnt5 ;D_STATUS 2D
|
|
DC.W max_pcnt5+min_pcnt5 ;D_CONTROL 2E
|
|
DC.W max_pcnt6+min_pcnt6 ;D_READ 2F
|
|
DC.W max_pcnt6+min_pcnt6 ;D_WRITE 30
|
|
DC.W max_pcnt0+min_pcnt0 ;ALLOC_INT and BIND_INT 31
|
|
DC.W max_pcnt0+min_pcnt0 ;DEALLOC_INT and UNBIND_INT 32
|
|
DC.W max_pcnt17+min_pcnt1 ;FST_SPECIFIC 33
|
|
|
|
;EXPORT pend_tbl
|
|
pend_tbl equ * - pcount_tbl
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;Below is the main entry point for ALL FST system calls
|
|
;
|
|
;This PROC was adapted directly from the ProDOS FST v02.00 by Rob Turner
|
|
;
|
|
;
|
|
;Input: X = Call number * 2
|
|
; Y = Class number * 2
|
|
; A = undefined
|
|
;======================================================================
|
|
|
|
EXPORT system_call
|
|
system_call PROCNAME
|
|
|
|
sta $FF0510 ;debug tag
|
|
|
|
phk ;setup our bank register
|
|
plb
|
|
|
|
cpx #max_sys+1 ;maximum system calls
|
|
bcs sys_err
|
|
jmp (sys_tbl,x) ;call system routine
|
|
|
|
sys_err
|
|
lda #bad_system_call
|
|
rtl ;return error to the SCM
|
|
|
|
startup
|
|
|
|
jsl get_sys_gbuf ;get pointer to general 1K buffer
|
|
|
|
stx gbuf_ptr
|
|
sty gbuf_ptr+2
|
|
|
|
lda #$0001 ;set default text mode to clear high bits
|
|
sta text_flag
|
|
|
|
bra exit
|
|
shutdown
|
|
deferred_flush
|
|
|
|
exit
|
|
lda #$0000
|
|
clc
|
|
rtl
|
|
|
|
sys_remove_vol ;clean up a vcr before SCM throws it away
|
|
sta >$FE0358
|
|
|
|
ldx <g_vcr_ptr
|
|
ldy <g_vcr_ptr+2
|
|
stx <vcr_ptr
|
|
sty <vcr_ptr+2
|
|
|
|
ldy #vcr_buf_vp ;point to vp for the segment owned by the vcr
|
|
lda [g_vcr_ptr],y ;g_vcr_ptr contains a real pointer
|
|
tax
|
|
iny
|
|
iny
|
|
ora [g_vcr_ptr],y ;check that it's not 0
|
|
beq @invalid_vp
|
|
|
|
lda [g_vcr_ptr],y
|
|
tay
|
|
jsl release_seg ;throw away the 4K buffer
|
|
@invalid_vp
|
|
rtl ;return with any error
|
|
|
|
|
|
sys_tbl dc.w sys_err
|
|
DC.W startup ;set ready for work
|
|
DC.W shutdown ;get ready to quit
|
|
DC.W sys_remove_vol ;remove local data from VCR
|
|
DC.W deferred_flush ;flush deferred blocks.
|
|
|
|
max_sys equ * - sys_tbl
|
|
|
|
ENDP
|
|
|
|
|
|
match_vcr PROCNAME ;given a volume name, try to find a matching vcr.
|
|
;volume name in volname_buf_ptr
|
|
|
|
import throw_away
|
|
import find_vol_online
|
|
import cmp_vol_vcr
|
|
|
|
;this is a complicated task, so here is the pseudocode:
|
|
|
|
; try to find a VCR with the same volume name
|
|
;
|
|
; NOT FOUND: return with no match
|
|
;
|
|
; FOUND:
|
|
; is it mine?
|
|
; NO: try to discard it (no open files)
|
|
; SUCCESSFUL discard: return with no match
|
|
; CAN'T discard: return w/duplicate_vol error
|
|
;
|
|
; YES: find the disk online, checking in dev_num or last known
|
|
; device (error if failure)
|
|
;
|
|
; is the disk really the same as one that VCR refers to?
|
|
; YES: return with match
|
|
; NO: try to discard it (no open files)
|
|
; SUCCESSFUL discard: return with no match
|
|
; CAN'T discard: return w/dup_vol error
|
|
|
|
;check for vcr with same name
|
|
|
|
;brk $03
|
|
|
|
ldx <volname_buf_ptr
|
|
ldy <volname_buf_ptr+2
|
|
lda #$0000 ;tell find_vcr to search by name
|
|
jsl find_vcr ;see if a vcr exists for this volume
|
|
bcc same_name ;same name, see if it's mine
|
|
no_match
|
|
lda #0 ;report no match
|
|
clc
|
|
rts
|
|
same_name
|
|
jsl deref
|
|
stx <vcr_ptr
|
|
sty <vcr_ptr+2
|
|
ldy #vcr_fst_id
|
|
lda [vcr_ptr],y ;see if it's mine
|
|
cmp #my_id
|
|
beq mine
|
|
jsr throw_away
|
|
bcc no_match ;successful discard, return no match
|
|
|
|
dup_vol ;return with error
|
|
lda #dup_volume ;duplicate volume
|
|
sec
|
|
rts
|
|
mine ;it's mine
|
|
|
|
ldy #vcr_open_cnt ; <CAF> By incrementing the vcr open count, I
|
|
lda [<vcr_ptr],y ; fool SCM into not throwing away the vcr for
|
|
inc a ; this volume when the disk is accessed.
|
|
sta [<vcr_ptr],y
|
|
|
|
lda <dev1_num ;was a device number given by SCM?
|
|
bne verify_same ;if so, see if the vcr matches the online disk
|
|
|
|
;no dev_num given, search devices starting with the�
|
|
;�one it was last seen in
|
|
ldy #vcr_dev
|
|
lda [vcr_ptr],y ;find where it was last seen
|
|
sta supposed_dev
|
|
jsr find_vol_online ;find the physical disk
|
|
bcc verify_same ;we found one, check it
|
|
|
|
ldy #vcr_open_cnt ; <CAF> Restore the previous open count.
|
|
lda [<vcr_ptr],y
|
|
dec a
|
|
sta [<vcr_ptr],y
|
|
|
|
lda #vol_not_found
|
|
sec
|
|
rts
|
|
|
|
verify_same ;we have a disk with the same name, but let's check two full�
|
|
;�sectors' worth of data
|
|
|
|
ldy #vcr_open_cnt ; <CAF> Restore the previous open count.
|
|
lda [<vcr_ptr],y
|
|
dec a
|
|
sta [<vcr_ptr],y
|
|
|
|
jsr cmp_vol_vcr
|
|
bcs try_discard ;it's not the same, try to get rid of the VCR
|
|
match ;we have a match!
|
|
|
|
ldy #vcr_id
|
|
lda [vcr_ptr],y
|
|
clc
|
|
rts ;return with vcr_id in accum
|
|
|
|
try_discard
|
|
jsr throw_away ;try to throw away the incorrect vcr
|
|
bcs dup_vol ;can't, report duplicate volume
|
|
bra no_match ;otherwise, report no match
|
|
|
|
ENDP
|
|
|
|
|
|
export open_setup
|
|
open_setup PROCNAME ;perform basic setup for OPEN and GET_FILE_INFO
|
|
|
|
import parse_path
|
|
import volume
|
|
import find_vol_online
|
|
import allocate_vcr
|
|
import cmp_vol_vcr
|
|
import device_id
|
|
|
|
stz supposed_dev ;init to 0
|
|
stz valid_vcr
|
|
stz gen_buf_vp
|
|
stz gen_buf_vp+2
|
|
|
|
lda #gen_buf_size ;let's get some buffer space for the vtoc & directory
|
|
jsl alloc_seg
|
|
bcc @ok
|
|
lda #out_of_mem ;can't get buffer space
|
|
rts
|
|
@ok
|
|
stx gen_buf_vp ;4K buffer used by volume routine
|
|
sty gen_buf_vp+2
|
|
jsl deref
|
|
stx <gen_buf_ptr
|
|
sty <gen_buf_ptr+2
|
|
|
|
lda #name_buf
|
|
sta <volname_buf_ptr
|
|
lda #^name_buf
|
|
sta <volname_buf_ptr+2
|
|
|
|
lda #<file_buf ;get address of this internal buffer
|
|
sta <file_name_ptr
|
|
lda #^file_buf
|
|
sta <file_name_ptr+2
|
|
|
|
lda #<vol_name_buf ;get address of this internal buffer
|
|
sta <vol_name_ptr
|
|
lda #^vol_name_buf
|
|
sta <vol_name_ptr+2
|
|
|
|
;brk $12
|
|
|
|
jsr parse_path ;check path and break off filename and volume name
|
|
bcc @ok4
|
|
lda #bad_path_syntax
|
|
rts
|
|
|
|
* <CAF> 11/08/90
|
|
* ok, at this point we have allocated any buffers and broken down the pathname, and it
|
|
* is a valid dos pathname. now we must attempt to find the volume which is the target
|
|
* of this call. the target may actually belong to another FST, so this is what must
|
|
* be done:
|
|
*
|
|
* A. does a vcr exist?
|
|
* 1. yes -
|
|
* a. is it DOS?
|
|
* 1. yes -
|
|
* a. is it same volume?
|
|
* 1. yes - verify that has not been switched.
|
|
* a. if not switched, then done (goto B)
|
|
* b. if switched, start scanning from last seen device (goto A.2.a)
|
|
* 2. no - if no open files, then proceed as if it was not DOS (goto A.1.b)
|
|
* 2. no - act as if a vcr does not exist, so that if a volume is found, we can try
|
|
* to throw this vcr out (goto A.2.a)
|
|
* 2. no -
|
|
* a. find the dos volume in one of the devices. If the vcr exists, attempt to throw
|
|
* it out. If it was thrown out, then create the new vcr for the dos volume.
|
|
* done. (goto B)
|
|
* B. done
|
|
*
|
|
@ok4
|
|
lda <dev1_num
|
|
beq have_vol_name ;if 0 dev_num then we have our volume pointed�
|
|
;�to by volname_buf_ptr
|
|
|
|
sta <drvr_dev_num
|
|
jsr device_id ;check to see if this is a 5.25 device
|
|
bcs @exit ;failed to find the device
|
|
bne @exit ;can't deal with non-5.25 drives
|
|
|
|
jsr volume ;get name of volume in that device
|
|
;that routine will return a g-string in vol_name_ptr
|
|
bcc @ok5 ;can't recognize volume
|
|
@exit sec
|
|
lda #unknown_vol
|
|
rts ;return with bouncing error
|
|
@ok5
|
|
lda #<vol_name_buf ;this is our volume name for sure
|
|
sta <volname_buf_ptr
|
|
lda #^vol_name_buf
|
|
sta <volname_buf_ptr+2
|
|
|
|
* A. does a vcr exist?
|
|
have_vol_name
|
|
|
|
ldx <volname_buf_ptr
|
|
ldy <volname_buf_ptr+2
|
|
lda #$0000 ;tell find_vcr to search by name
|
|
jsl find_vcr ;see if a vcr exists for this volume
|
|
* 2. no -
|
|
bcs find_vol ; no vcr, so go look for volume ->
|
|
* 1. yes -
|
|
same_name
|
|
jsl deref
|
|
stx <vcr_ptr
|
|
sty <vcr_ptr+2
|
|
|
|
* a. is it DOS?
|
|
ldy #vcr_fst_id ; is it a vcr for a dos volume?
|
|
lda [vcr_ptr],y ;
|
|
cmp #my_id
|
|
* 1. yes -
|
|
beq mine ; yes ->
|
|
|
|
* 2. no - act as if a vcr does not exist, so that if a volume is found, we can try
|
|
* to throw this vcr out (goto A.2.a)
|
|
lab112 ldy #vcr_open_cnt ; no, any open files?
|
|
lda [<vcr_ptr],y
|
|
beq find_vol ; no, so lets act as if I haven't seen the vcr, and go try
|
|
; to find a dos volume with the same name.
|
|
|
|
*
|
|
* ok, I've found a vcr for a volume that has open files. this means that even if
|
|
* I were to find a dos volume of the same name, I couldn't mount it because of this volume.
|
|
* that means that now I must return either dup_vol or vol_not_found.
|
|
*
|
|
* dup_vol -> I found a dos volume online but couldn't mount it.
|
|
* vol_not_found -> couldn't find a dos volume of this name.
|
|
*
|
|
* what are the side effects of my just returning vol_not_found?
|
|
* - won't be able to tell if a duplicate volume has been inserted
|
|
*
|
|
*
|
|
stz supposed_dev ; we have no clue what device it might be in
|
|
jsr find_vol_online
|
|
|
|
lda #vol_not_found ; assume that we couldn't find it
|
|
bcc @1
|
|
brl exit ; couldn't find it ->
|
|
|
|
@1 lda #dup_volume ; was found, so error is a dup_volume error
|
|
brl exit ; ->
|
|
|
|
*
|
|
* I've found a vcr for a dos volume. check to see if it is the same volume.
|
|
*
|
|
* a. is it same volume?
|
|
mine ldy #vcr_buf_vp ;set up correct buffer for check_dir
|
|
lda [vcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [vcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx vol_buf_ptr
|
|
sty vol_buf_ptr+2
|
|
|
|
jsr cmp_vol_vcr ; same?
|
|
bcs @not_same ; no ->
|
|
|
|
* 1. yes - verify that has not been switched.
|
|
@same ldy #vcr_status
|
|
lda [<vcr_ptr],y
|
|
and #vcr_swapped
|
|
* a. if not switched, then done (goto B)
|
|
beq done ; not switched ->
|
|
* b. if switched, start scanning from last seen device (goto A.2.a)
|
|
ldy #vcr_dev ; get the last device it was in
|
|
lda [<vcr_ptr],y
|
|
sta supposed_dev
|
|
bra find_vol2 ; switched, so go find it ->
|
|
|
|
* 2. no - if no open files, then proceed as if it was not DOS (goto A.1.b)
|
|
@not_same bra lab112 ; lab112 checks vcr_open_cnt ->
|
|
|
|
* 2. no -
|
|
* a. find the (possibly) dos volume in one of the devices. If the vcr exists, attempt to throw
|
|
* it out. If it was thrown out, then create the new vcr for the dos volume.
|
|
* done. (goto B)
|
|
find_vol ; we have a volume name, but make sure that it is a dos disk in
|
|
; one of the drives
|
|
|
|
stz vcr_ptr ; zero out the vcr pointer so that I know if I only need to
|
|
stz vcr_ptr+2 ; update the device number
|
|
stz supposed_dev ; start at first device
|
|
|
|
find_vol2 stz myflag1 ; assume no prior vcr
|
|
|
|
lda vcr_ptr ; vcr?
|
|
ora vcr_ptr+2
|
|
beq @1 ; no ->
|
|
|
|
inc myflag1 ; set flag indicating that I have bumped the open count
|
|
ldy #vcr_open_cnt ; increment the open count so volume won't be lost
|
|
lda [<vcr_ptr],y ; the only time that this might not work would be if we are
|
|
inc a ; searching for a duplicate dos 3.3 volume, but that is not
|
|
sta [<vcr_ptr],y ; very likely.
|
|
|
|
@1 jsr find_vol_online
|
|
php
|
|
pha
|
|
|
|
lda myflag1
|
|
beq @2
|
|
|
|
ldy #vcr_open_cnt ; decrement the open count
|
|
lda [<vcr_ptr],y
|
|
dec a
|
|
sta [<vcr_ptr],y
|
|
stz myflag1
|
|
|
|
@2 pla
|
|
plp
|
|
bcs exit ; couldn't find it ->
|
|
|
|
lda vcr_ptr ; found a volume, did we have a vcr already?
|
|
ora vcr_ptr+2
|
|
beq @alloc ; no, go create one ->
|
|
|
|
ldy #vcr_dev ; yes, update the device number in the vcr
|
|
lda drvr_dev_num
|
|
sta [<vcr_ptr],y
|
|
|
|
ldy #vcr_status ; clear the disk swapped flag
|
|
lda [<vcr_ptr],y
|
|
and #$BFFF
|
|
sta [<vcr_ptr],y
|
|
|
|
bra done
|
|
|
|
@alloc jsr allocate_vcr ; found volume, allocate the vcr
|
|
bcs exit ; error ->
|
|
|
|
* B. done
|
|
done ldy #vcr_dev ; setup the drvr_dev_num
|
|
lda [<vcr_ptr],y
|
|
sta drvr_dev_num
|
|
|
|
clc
|
|
exit rts
|
|
|
|
myflag1 dc.w 0
|
|
|
|
ENDP
|
|
|
|
|
|
export fill_param
|
|
fill_param PROCNAME ;fill the user param list according to the table pointed to�
|
|
;�by fill_tabl. p_cnt must be correct
|
|
|
|
ldy #$0000-2 ;init index
|
|
ldx p_cnt ;keep countdown in x
|
|
@cpy_loop
|
|
iny
|
|
iny ;move to next word entry
|
|
lda (fill_tabl),y ;get the table entry
|
|
asl a ;test 2 highest bits
|
|
php ;save the results in carry and neg flags
|
|
bmi @no_copy ;if original bit 14 was set, don't copy
|
|
lsr a ;shift things back into place
|
|
phy ;save the present index
|
|
tay
|
|
lda global_params,y
|
|
ply
|
|
sta [param_blk_ptr],y
|
|
@no_copy
|
|
plp ;restore the first test result
|
|
bcc @cpy_loop ;should we decrement pcount?
|
|
dex ;decrement pcount
|
|
bne @cpy_loop ;if we're not done, keep looping
|
|
@done
|
|
rts
|
|
|
|
;now we have the param list fill tables:
|
|
|
|
;table to specify what data to copy from the fcr to the user
|
|
;parameter block. each position corresponds to the same position
|
|
;in the user parameter block.
|
|
;each word entry contains:
|
|
; bit 15 = decrement pcount--high for the 1st word in each parameter
|
|
; bit 14 = copy inhibit--if high, nothing gets copied for this word position
|
|
no_copy equ %0100000000000000
|
|
dec equ %1000000000000000
|
|
|
|
;the label 'g' is short for 'global_params' and is the address of the start�
|
|
;�of the table of global parameters. It is needed in the offset expression�
|
|
;�for each entry that represents a param to be copied, so I used a one-letter�
|
|
;�label for convenience.
|
|
|
|
*************************************************************
|
|
EXPORT get_file_info0_f
|
|
|
|
get_file_info0_f
|
|
|
|
dc.w no_copy ;pathname
|
|
dc.w no_copy
|
|
dc.w access - g ;access
|
|
dc.w os_type - g ;file_type
|
|
dc.w aux_type - g ;aux_type
|
|
dc.w null - g
|
|
dc.w stor_type - g ;storage_type
|
|
dc.w null - g ;create_date
|
|
dc.w null - g ;create_time
|
|
dc.w null - g ;mod_date
|
|
dc.w null - g ;mod_time
|
|
dc.w blks_used - g ;blocks_used
|
|
dc.w null - g + dec
|
|
|
|
*************************************************************
|
|
EXPORT get_file_info1_f
|
|
get_file_info1_f
|
|
|
|
dc.w no_copy ;pcount
|
|
dc.w no_copy ;pathname
|
|
dc.w no_copy + dec
|
|
dc.w access - g + dec ;access
|
|
dc.w os_type - g + dec ;file_type
|
|
dc.w aux_type - g ;aux_type
|
|
dc.w null - g + dec
|
|
dc.w stor_type - g + dec ;storage_type
|
|
dc.w null - g ;create_date_time
|
|
dc.w null - g
|
|
dc.w null - g
|
|
dc.w null - g + dec
|
|
dc.w null - g ;mod_date_time
|
|
dc.w null - g
|
|
dc.w null - g
|
|
dc.w null - g + dec
|
|
dc.w no_copy ;option_list
|
|
dc.w no_copy + dec
|
|
dc.w eof - g ;eof
|
|
dc.w eof+2 - g + dec
|
|
dc.w blks_used - g ;blocks_used
|
|
dc.w null - g + dec
|
|
|
|
;dc.w no_copy ;resource_eof
|
|
;dc.w no_copy + dec
|
|
;dc.w no_copy ;resource_blocks
|
|
;dc.w no_copy + dec
|
|
|
|
; Resource fork info now gets zeroed
|
|
; -- Monte Benaresh 2/19/92 for 6.0.1
|
|
|
|
dc.w null - g ;resource_eof
|
|
dc.w null - g + dec
|
|
dc.w null - g ;resource_blocks
|
|
dc.w null - g + dec
|
|
|
|
*************************************************************
|
|
EXPORT volume0_f
|
|
volume0_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT volume1_f
|
|
volume1_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT open0_f
|
|
open0_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT open1_f
|
|
open1_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT read0_f
|
|
read0_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT read1_f
|
|
read1_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT close0_f
|
|
close0_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT close1_f
|
|
close1_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT set_mark0_f
|
|
set_mark0_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT set_mark1_f
|
|
set_mark1_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT get_mark0_f
|
|
get_mark0_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT get_mark1_f
|
|
get_mark1_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
|
|
*************************************************************
|
|
EXPORT get_eof0_f
|
|
get_eof0_f ;this call is mostly special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT get_eof1_f
|
|
get_eof1_f ;this call is mostly special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT get_dir_entry0_f
|
|
|
|
get_dir_entry0_f
|
|
|
|
dc.w no_copy ;ref_num
|
|
dc.w no_copy ;flags
|
|
dc.w no_copy ;base
|
|
dc.w no_copy ;displacement
|
|
dc.w no_copy ;name
|
|
dc.w no_copy
|
|
dc.w entry_num - g ;entry_num
|
|
dc.w os_type - g ;file_type
|
|
dc.w eof - g ;eof
|
|
dc.w eof+2 - g
|
|
dc.w blks_used - g ;block_count
|
|
dc.w null - g
|
|
dc.w null - g ;create_date_time
|
|
dc.w null - g
|
|
dc.w null - g
|
|
dc.w null - g
|
|
dc.w null - g ;mod_date_time
|
|
dc.w null - g
|
|
dc.w null - g
|
|
dc.w null - g
|
|
dc.w access - g ;access
|
|
dc.w aux_type - g ;aux_type
|
|
dc.w null - g
|
|
dc.w fst_id - g + dec ;file_sys_id
|
|
|
|
*************************************************************
|
|
EXPORT get_dir_entry1_f
|
|
|
|
get_dir_entry1_f
|
|
|
|
dc.w no_copy ;pcount
|
|
dc.w no_copy + dec ;ref_num
|
|
dc.w no_copy + dec ;flags
|
|
dc.w no_copy + dec ;base
|
|
dc.w no_copy + dec ;displacement
|
|
dc.w no_copy ;name
|
|
dc.w no_copy + dec
|
|
dc.w entry_num - g + dec ;entry_num
|
|
dc.w os_type - g + dec ;file_type
|
|
dc.w eof - g ;eof
|
|
dc.w eof+2 - g + dec
|
|
dc.w blks_used - g ;block_count
|
|
dc.w null - g + dec
|
|
dc.w null - g ;create_date_time
|
|
dc.w null - g
|
|
dc.w null - g
|
|
dc.w null - g + dec
|
|
dc.w null - g ;mod_date_time
|
|
dc.w null - g
|
|
dc.w null - g
|
|
dc.w null - g + dec
|
|
dc.w access - g + dec ;access
|
|
dc.w aux_type - g ;aux_type
|
|
dc.w null - g + dec
|
|
dc.w fst_id - g + dec ;file_sys_id
|
|
dc.w no_copy ;option_list
|
|
dc.w no_copy + dec
|
|
|
|
;dc.w no_copy ;resource_eof
|
|
;dc.w no_copy + dec
|
|
;dc.w no_copy ;resource_blocks
|
|
;dc.w no_copy + dec
|
|
|
|
; Resource fork info now gets zeroed
|
|
; -- Monte Benaresh 2/19/92 for 6.0.1
|
|
|
|
dc.w null - g ;resource_eof
|
|
dc.w null - g + dec
|
|
dc.w null - g ;resource_blocks
|
|
dc.w null - g + dec
|
|
|
|
*************************************************************
|
|
EXPORT get_dev_num0_f
|
|
get_dev_num0_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
EXPORT get_dev_num1_f
|
|
get_dev_num1_f ;this call is all special-case, so this routine never gets called for it.
|
|
|
|
*************************************************************
|
|
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;new_rwts Read/write a given track/sector.
|
|
; Calculates: block = (16 * track) + sector
|
|
;
|
|
;Enter: JSR
|
|
;
|
|
; sector | track
|
|
;Input: A =|F|E|D|C|B|A|9|8|7|6|5|4|3|2|1|0|
|
|
; This is what you get if you do a 16-bit load on a
|
|
; track/sector entry typically found in a DOS 3.3
|
|
; data structure.
|
|
;
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..0
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..|___ high = device error, low = successful
|
|
; b = k
|
|
;
|
|
;uses: Good for reading sectors.
|
|
;
|
|
;======================================================================
|
|
|
|
longa on
|
|
longi on
|
|
new_rwts PROCNAME ;read/write a track/sector
|
|
xba ;switch track byte/sector byte
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
asl a ;get sector nibble flush left in byte
|
|
asl a
|
|
asl a
|
|
asl a
|
|
|
|
rep #%00100000 ;now open up to 16 bits
|
|
LONGA ON
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a ;calculation done--we have a block number
|
|
sta <drvr_blk_num ;put on parm list
|
|
stz <drvr_blk_num+2 ;clear high word
|
|
;make this call lda #drvr_read
|
|
;more general sta <drvr_call_num
|
|
lda #$0100 ;256-byte "blocks"
|
|
sta <drvr_blk_size
|
|
sta <drvr_req_cnt ;we only deal in whole blocks�
|
|
stz <drvr_req_cnt+2 ;�and only one at a time!
|
|
lda #my_id
|
|
sta <drvr_fst_num
|
|
stz <drvr_cache ;to hell with caching
|
|
@retry jsl dev_dispatcher ;go read
|
|
bcs @err
|
|
rts
|
|
@err
|
|
cmp #drvr_disk_sw
|
|
beq @retry
|
|
sec
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;find_fde Find the file descriptive entry #n in catalog sector #k
|
|
; in vol_name_buf.
|
|
;
|
|
;
|
|
;Enter: JSR
|
|
;
|
|
;
|
|
;Input: A = k, as in "catalog sector #k"
|
|
;
|
|
; X = n, as in "fde #n"
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..0
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..|___ high = error, low = successful
|
|
; b = k
|
|
; fde_ptr = longword pointer to first byte of that fde
|
|
;
|
|
;uses:
|
|
;
|
|
;======================================================================
|
|
|
|
find_fde PROCNAME ;find a file descriptive entry
|
|
cmp #max_cat_sec+1 ;see if in range
|
|
bcs @error ;range error
|
|
xba ;we now have a byte offset to start of that cat sector
|
|
adc #cat_strt_off ;add offset to first cat sector
|
|
adc #base_fde ;add base fde offset within catalog sector
|
|
cpx #max_fde+1 ;check range
|
|
bcs @error
|
|
@add dex ;decrement fde offset
|
|
bmi @fde_done ;we're done when we get below zero--loop 0 or more times
|
|
adc #fde_len ;add byte length of each fde
|
|
bra @add
|
|
@fde_done ;clc hopefully, carry will be clear
|
|
adc vol_buf_ptr ;finished product is address of fde in contiguous�
|
|
sta fde_ptr ;�buffer of catalog sectors
|
|
lda vol_buf_ptr+2 ;get high part
|
|
adc #$0000
|
|
sta fde_ptr+2
|
|
rts
|
|
@error
|
|
rts
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;
|
|
; load_fde_flag (added 6-May-93 DAL)
|
|
;
|
|
; This routine is similar to
|
|
; lda [fde_ptr]
|
|
; and #$00ff
|
|
; That first byte of an fde is $FF for a deleted entry.
|
|
;
|
|
; We also return $FF for a non-deleted entry if the filename is
|
|
; all blanks, which would be a zero-length filename.
|
|
;
|
|
;Enter: JSR
|
|
;
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; fde_ptr = points to a file-descriptive entry
|
|
;
|
|
;Output: A = first byte of fde, or $FF if the filename is blanks
|
|
; X = preserved
|
|
; Y = preserved
|
|
; P = nvmxdizc
|
|
; ..000.|.___ Z is conditioned for A
|
|
; b = k
|
|
;
|
|
;======================================================================
|
|
load_fde_flag PROC
|
|
|
|
lda [fde_ptr]
|
|
and #$00ff
|
|
beq @done ;beyond end of catalog--done
|
|
cmp #$00ff
|
|
beq @done ;a real deleted entry--done
|
|
|
|
*** If all 30 filename characters are blank, simulate a deleted entry
|
|
phy
|
|
phx
|
|
|
|
ldx #15
|
|
ldy #fde_name
|
|
@search lda [fde_ptr],y
|
|
cmp #$A0A0 ;blanks?
|
|
bne @nonBlank
|
|
iny
|
|
iny
|
|
dex
|
|
bne @search
|
|
|
|
lda #$00ff ;all blanks--simulate a deleted entry
|
|
bra @leave
|
|
|
|
@nonBlank lda [fde_ptr]
|
|
@leave plx
|
|
ply
|
|
|
|
@done and #$00FF
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;cmp_string Compare two class 1 strings pointed to by str1 and str2.
|
|
; Str2 is masked with cmp_mask. Maximum length is $8000
|
|
; bytes.
|
|
;
|
|
;Enter: JSR
|
|
;
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..0
|
|
; b = k
|
|
;
|
|
; str1_ptr = longword pointer to one string, usually from GS/OS
|
|
; str2_ptr = longword pointer to other string, possibly with high bits set,
|
|
; usually from DOS. This string gets masked with cmp_mask.
|
|
; cmp_mask = 8-bit value to be ANDed with each character in str2.
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..|___ high = compare false, low = compare true
|
|
; b = k
|
|
;
|
|
;uses: Good for comparing two strings.
|
|
;
|
|
;======================================================================
|
|
|
|
|
|
|
|
;let's try this using LONG accumulator!
|
|
cmp_string PROCNAME ;compare two strings
|
|
lda [str1_ptr] ;get string length
|
|
cmp [str2_ptr]
|
|
bne @different ;if they're not even the same length...
|
|
tay
|
|
bpl @ok
|
|
ldy #$7FFF ;in the unlikely event that y is greater than $7FFF, it�
|
|
;�is truncated to $7FFF
|
|
@ok iny ;point to last character
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
@loop lda [str2_ptr],y ;y must be signed POSITIVE
|
|
and cmp_mask ;user mask, maybe to strip high bit?
|
|
cmp [str1_ptr],y
|
|
bne @different
|
|
dey
|
|
bpl @loop
|
|
rep #%00100001 ;16-bit accum, carry clear
|
|
rts
|
|
@different sec
|
|
rep #%00100000 ;16-bit accum
|
|
rts
|
|
LONGA ON
|
|
|
|
ENDP
|
|
|
|
|
|
allocate_vcr PROCNAME ;find old VCR or allocate new one for volume�
|
|
;�found by the "volume" subroutine
|
|
|
|
;enter with
|
|
; volname_buf_ptr points to volume name
|
|
|
|
|
|
import load_cat_secs
|
|
import find_vol_online
|
|
|
|
|
|
;brk $A4
|
|
|
|
;do we need to allocate a VCR for this volume?
|
|
|
|
jsr match_vcr ;find vcr for volume name in volname_buf_ptr
|
|
bcc @ok
|
|
|
|
lda #dup_volume ;return with duplicate_volume error
|
|
rts
|
|
@ok
|
|
beq find_vol ;no match, find volume and allocate a new VCR
|
|
brl have_vcr ;if we got a match, don't allocate new VCR
|
|
find_vol
|
|
jsr find_vol_online ; supposed_dev is setup by the caller of allocate_vcr
|
|
bcc req_vcr
|
|
|
|
lda #vol_not_found
|
|
rts
|
|
req_vcr
|
|
lda #vcr_size
|
|
;ldx #<vol_name_buf
|
|
;ldy #^vol_name_buf
|
|
ldx <volname_buf_ptr
|
|
ldy <volname_buf_ptr+2
|
|
jsl alloc_vcr
|
|
|
|
;brk $AA
|
|
|
|
bcc @ok
|
|
lda #out_of_mem ;can't get new vcr
|
|
rts ;return carry set
|
|
@ok
|
|
jsl deref
|
|
stx <vcr_ptr
|
|
sty <vcr_ptr+2
|
|
|
|
lda #$8000
|
|
tsb vcr_fcr_flags ;set flag to say we allocated a VCR
|
|
fill_new_vcr
|
|
lda gen_buf_vp
|
|
ora gen_buf_vp+2 ;is there a valid buffer?
|
|
bne @have_gen_buf
|
|
@get_gen_buf
|
|
lda #gen_buf_size ;let's get some buffer space for the vtoc & directory
|
|
jsl alloc_seg
|
|
bcc @got_buf
|
|
lda #out_of_mem ;can't get buffer space
|
|
bra vol_vcr_err
|
|
@got_buf
|
|
stx gen_buf_vp ;4K buffer used by volume routine
|
|
sty gen_buf_vp+2
|
|
@have_gen_buf
|
|
ldy #vcr_fst_id
|
|
lda #my_id
|
|
sta [vcr_ptr],y
|
|
|
|
ldy #vcr_open_cnt
|
|
;lda #$FFFF ;this value will prevent a swap-out, but we understand�
|
|
;�it to be 0
|
|
lda #0
|
|
sta [vcr_ptr],y ;set open count to 0 since we just allocated this vcr
|
|
|
|
ldy #vcr_dev
|
|
lda <drvr_dev_num ;where did we find the disk?
|
|
sta [vcr_ptr],y
|
|
|
|
ldy #vcr_buf_vp ;index to virtual pointer to vtoc & directory buffers
|
|
lda gen_buf_vp ;transfer the vp's for the general buffer�
|
|
;�to the vol_buf now that we know�
|
|
;�that we want to keep them
|
|
tax ;save for deref
|
|
sta [vcr_ptr],y
|
|
iny
|
|
iny
|
|
lda gen_buf_vp+2
|
|
sta [vcr_ptr],y
|
|
tay ;set up for deref
|
|
jsl deref
|
|
|
|
stx vol_buf_ptr ;set up for rest of the FST
|
|
sty vol_buf_ptr+2
|
|
|
|
stz gen_buf_vp ;nail the original vp's so that we know�
|
|
stz gen_buf_vp+2 ;�not to release them later
|
|
load
|
|
ldy #vcr_open_cnt ; prevent swap out of vcr
|
|
lda [<vcr_ptr],y
|
|
inc a
|
|
sta [<vcr_ptr],y
|
|
|
|
jsr load_cat_secs ;load catalog sectors into vol_buf
|
|
|
|
php
|
|
pha
|
|
|
|
ldy #vcr_open_cnt ; restore original count
|
|
lda [<vcr_ptr],y
|
|
dec a
|
|
sta [<vcr_ptr],y
|
|
|
|
pla
|
|
plp
|
|
|
|
bcc load_ok
|
|
vol_vcr_err
|
|
pha ;save error code
|
|
@cancel_vcr
|
|
ldy #vcr_open_cnt
|
|
lda #$0000
|
|
sta [vcr_ptr],y ;must zero the open count to release it!
|
|
|
|
ldy #vcr_id
|
|
lda [vcr_ptr],y ;get ID of the VCR
|
|
jsl release_vcr ;this invokes sys_remove_vol call to this fst
|
|
|
|
lda #$8000
|
|
trb vcr_fcr_flags ;clear flag since we deallocated the VCR
|
|
|
|
pla ;restore error
|
|
sec
|
|
rts
|
|
|
|
load_ok
|
|
lda cat_sec_count ;enter catalog sector count into VCR
|
|
ldy #vcr_cat_sec_count
|
|
sta [vcr_ptr],y
|
|
|
|
bra vol_exit
|
|
|
|
have_vcr
|
|
;update old VCR
|
|
ldy #vcr_buf_vp ;get the vcr's buffer set up
|
|
lda [vcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [vcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
|
|
stx vol_buf_ptr
|
|
sty vol_buf_ptr+2
|
|
|
|
ldy #vcr_dev
|
|
lda <drvr_dev_num ;where did we find the disk?
|
|
sta [vcr_ptr],y
|
|
vol_exit
|
|
;lda gen_buf_vp ;we may have to release this segment
|
|
;tax ;save in case it's valid
|
|
;ora gen_buf_vp+2 ;null vp?
|
|
;beq @skip3
|
|
|
|
;ldy gen_buf_vp+2
|
|
;jsl release_seg ;release unused gen buf
|
|
@skip3
|
|
|
|
clc
|
|
rts ;that's all, folks!
|
|
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
volume PROCNAME ;check a device for a valid DOS 3.3 disk
|
|
;caller must set device in drvr_dev_num
|
|
;returns a volume name in vol_name_ptr
|
|
;carry set means that a DOS 3.3 disk was�
|
|
;�not found.
|
|
|
|
|
|
lda <gen_buf_ptr
|
|
sta <drvr_buf_ptr
|
|
lda <gen_buf_ptr+2
|
|
sta <drvr_buf_ptr+2
|
|
lda #drvr_read
|
|
sta <drvr_call_num
|
|
lda #$0011 ;get VTOC, always at track 17, sector 0
|
|
jsr new_rwts ;make driver call
|
|
bcc @ok
|
|
|
|
rts ;return error
|
|
|
|
@ok ;so, is it a DOS volume?
|
|
|
|
;brk 99
|
|
|
|
sep #$30 ;work with bytes
|
|
LONGI OFF
|
|
LONGA OFF
|
|
|
|
ldx #id_tbl_end-id_values-1 ;point to last entry in id tables
|
|
@loop1 lda id_offset,x ;get offset into VTOC
|
|
tay
|
|
@loop2 lda [drvr_buf_ptr],y ;get the actual value
|
|
cmp id_values,x ;compare to the table value
|
|
bne @false ;not the same
|
|
|
|
@loop3 dex
|
|
bmi confirmed ;table finished
|
|
|
|
tya
|
|
cmp id_offset,x ;skip over other entries for same position
|
|
beq @loop3
|
|
|
|
bra @loop1 ;move on to next compare
|
|
|
|
@false dex
|
|
bmi @failed
|
|
|
|
tya
|
|
cmp id_offset,x ;see if there's an alternate value for that offset
|
|
beq @loop2 ;yes, get a second chance
|
|
|
|
@failed sec
|
|
|
|
rep #$30 ;word accum
|
|
LONGA ON
|
|
LONGI ON
|
|
|
|
lda #unknown_vol ;return bouncing error
|
|
rts ;sorry, not a DOS volume
|
|
|
|
confirmed ;well, it looks like a DOS 3.3 volume!
|
|
|
|
rep #$31 ;word accum, carry clear
|
|
LONGA ON
|
|
LONGI ON
|
|
|
|
;now we must load the first directory sector!
|
|
ldy #vtoc_cat_link ;get the link to first catalog sector
|
|
lda [drvr_buf_ptr],y
|
|
bne @ok
|
|
lda #dir_error ;this is a weird error
|
|
rts
|
|
@ok
|
|
pha ;save this for a minute
|
|
lda <drvr_buf_ptr
|
|
sta <gen_buf_ptr
|
|
clc
|
|
adc #$0100 ;bump by a page
|
|
sta <drvr_buf_ptr
|
|
lda <drvr_buf_ptr+2
|
|
sta <gen_buf_ptr+2
|
|
adc #$0000
|
|
sta <drvr_buf_ptr+2
|
|
lda #drvr_read
|
|
sta <drvr_call_num
|
|
pla ;get back the track/sector
|
|
jsr new_rwts ;read the sector
|
|
bcc @ok1
|
|
|
|
; lda #error ;device error
|
|
rts
|
|
|
|
@ok1
|
|
generate_name ;now generate the name
|
|
ldy #$01FE ;point to end of area to be checksummed
|
|
lda #$0000 ;seed the checksum
|
|
clc ;this is part of the seed
|
|
@loop eor [gen_buf_ptr],y
|
|
ror a ;scramble bits
|
|
bpl @1 ;random condition
|
|
|
|
eor #$7FFF ;conditional flip of all but high bit
|
|
@1 dey
|
|
dey
|
|
bpl @loop
|
|
;we now have a 16-bit checksum in the accumulator
|
|
sta chksum
|
|
|
|
; and #$F800 ;take the high five bits
|
|
; lsr a
|
|
; lsr a ;use it as an index into word table
|
|
; xba
|
|
; tax
|
|
ldx #0 ;we no longer use the table of names
|
|
lda name_tabl,x ;this table contains word pointers to 2 bytes�
|
|
sta <namegen_ptr ;�before name strings
|
|
|
|
copy_alpha ;now copy the alphabetic part of the generated name to the buffer
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
|
|
ldy #$0002 ;we need this offset for the g-string
|
|
|
|
@loop
|
|
lda (namegen_ptr),y
|
|
beq @done
|
|
sta (vol_name_ptr),y
|
|
iny
|
|
cpy #alpha_len_limit ;just in case, we don't want to overflow our buffer
|
|
bne @loop
|
|
@done
|
|
|
|
rep #%00100000
|
|
LONGA ON
|
|
|
|
bcd stz bcd_result ;we're going to do a BCD calculation
|
|
stz bcd_result+2 ;1 *byte*/digit
|
|
lda chksum
|
|
and #$07FF ;get lowest 11 bits
|
|
sta bin_temp
|
|
@1000 sec
|
|
sbc #1000
|
|
bcc @100
|
|
sta bin_temp
|
|
lda bcd_result
|
|
adc #$1-1 ;carry is set
|
|
sta bcd_result
|
|
lda bin_temp
|
|
bra @1000
|
|
@100 lda bin_temp
|
|
sec
|
|
sbc #100
|
|
bcc @10
|
|
sta bin_temp
|
|
lda bcd_result
|
|
adc #$100-1 ;carry is set
|
|
sta bcd_result
|
|
bra @100
|
|
@10 lda bin_temp
|
|
sec
|
|
sbc #10
|
|
bcc @almost_done
|
|
sta bin_temp
|
|
lda bcd_result+2
|
|
adc #$1-1 ;carry is set
|
|
sta bcd_result+2
|
|
bra @10
|
|
@almost_done
|
|
;brk $ED
|
|
|
|
lda bin_temp
|
|
xba
|
|
adc bcd_result+2 ;take care of ones place. carry is clear
|
|
sta bcd_result+2
|
|
|
|
;we should now have the bcd value of lower 11 bits of the checksum in bcd_result.
|
|
lda bcd_result
|
|
adc #'00' ;get ascii for this digit. carry is clear.
|
|
sta (vol_name_ptr),y
|
|
iny
|
|
iny
|
|
lda bcd_result+2
|
|
adc #'00' ;get ascii for this digit. carry is clear.
|
|
sta (vol_name_ptr),y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta (vol_name_ptr),y
|
|
@done2
|
|
dey
|
|
dey ;adjust to find name length
|
|
tya
|
|
sta (vol_name_ptr) ;this completes the g-string
|
|
;we are done generating the name
|
|
|
|
rep #$31 ;long accum, carry clear
|
|
LONGA ON
|
|
LONGI ON
|
|
|
|
lda #$8000
|
|
sta error_priority ;any error now has priority
|
|
|
|
rts
|
|
|
|
; 1/4/91 jev Removed table of volume names. It was felt that it would not be
|
|
; appropriate to use the names from Prinston and that just DOS 3.3
|
|
; was what was aggreed on.
|
|
|
|
name_tabl ;this table contains word pointers to 3 bytes before the name strings
|
|
dc.w name1 - 2
|
|
; dc.w name2 - 2
|
|
; dc.w name3 - 2
|
|
; dc.w name4 - 2
|
|
; dc.w name5 - 2
|
|
; dc.w name6 - 2
|
|
; dc.w name7 - 2
|
|
; dc.w name8 - 2
|
|
; dc.w name9 - 2
|
|
; dc.w name10 - 2
|
|
; dc.w name11 - 2
|
|
; dc.w name12 - 2
|
|
; dc.w name13 - 2
|
|
; dc.w name14 - 2
|
|
; dc.w name15 - 2
|
|
; dc.w name16 - 2
|
|
; dc.w name17 - 2
|
|
; dc.w name18 - 2
|
|
; dc.w name19 - 2
|
|
; dc.w name20 - 2
|
|
; dc.w name21 - 2
|
|
; dc.w name22 - 2
|
|
; dc.w name23 - 2
|
|
; dc.w name24 - 2
|
|
; dc.w name25 - 2
|
|
; dc.w name26 - 2
|
|
; dc.w name27 - 2
|
|
; dc.w name28 - 2
|
|
; dc.w name29 - 2
|
|
; dc.w name30 - 2
|
|
; dc.w name31 - 2
|
|
; dc.w name32 - 2
|
|
|
|
;now we have the actual name data:
|
|
|
|
string C
|
|
|
|
name1 dc.b 'DOS 3.3 v'
|
|
; name2 dc.b 'HAMILTON'
|
|
; name3 dc.b 'DOD'
|
|
; name4 dc.b 'HENRY'
|
|
; name5 dc.b 'EDWARDS'
|
|
; name6 dc.b 'HOLDER'
|
|
; name7 dc.b 'WITHERSPOON'
|
|
; name8 dc.b 'PYNE'
|
|
; name9 dc.b 'SPELMAN'
|
|
; name10 dc.b 'MCCOSH'
|
|
; name11 dc.b 'WOOLWORTH'
|
|
; name12 dc.b 'PALMER'
|
|
; name13 dc.b 'JADWIN'
|
|
; name14 dc.b 'DILLON'
|
|
; name15 dc.b 'PROSPECT'
|
|
; name16 dc.b 'ALEXANDER'
|
|
; name17 dc.b 'FINE'
|
|
; name18 dc.b 'EQUAD'
|
|
; name19 dc.b 'FIRESTONE'
|
|
; name20 dc.b 'MATHEY'
|
|
; name21 dc.b 'NASSAU'
|
|
; name22 dc.b 'KRESGE'
|
|
; name23 dc.b 'MCCORMICK'
|
|
; name24 dc.b 'CLAPP'
|
|
; name25 dc.b 'WAWA'
|
|
; name26 dc.b 'TI'
|
|
; name27 dc.b 'CHARTER'
|
|
; name28 dc.b 'ELM'
|
|
; name29 dc.b 'COLONIAL'
|
|
; name30 dc.b 'QUAD'
|
|
; name31 dc.b 'TERRACE'
|
|
; name32 dc.b 'CAMPUS'
|
|
|
|
|
|
id_offset ;these are offsets into the VTOC of bytes which are checked in order
|
|
;to determine whether a disk is DOS 3.3 format:
|
|
|
|
dc.b $3 ;DOS release #
|
|
dc.b $27 ;# of T/S pairs per T/S list sector
|
|
dc.b $36,$37 ;# of bytes per sector
|
|
dc.b $31,$31 ;direction of track allocation (2 possible values)
|
|
dc.b $34,$34 ;# of tracks per disk (2 possible values??)
|
|
dc.b $35,$35 ;# of sectors per track (2 possible values??)
|
|
|
|
|
|
id_values ;these are the actual values required for a DOS 3.3 disk:
|
|
|
|
dc.b 3 ;DOS release #
|
|
dc.b $7A ;# of T/S pairs per T/S list sector
|
|
dc.b $00,$01 ;# of bytes per sector
|
|
dc.b $01,$FF ;direction of track allocation (2 possible values)
|
|
dc.b 35,50 ;# of tracks per disk (2 possible values??)
|
|
dc.b 16,32 ;# of sectors per track (2 possible values??)
|
|
id_tbl_end
|
|
|
|
;storage area
|
|
chksum ds 1
|
|
bin_temp ds 1
|
|
bcd_result ds.l 1
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
throw_away PROCNAME ;try to throw away the current vcr
|
|
|
|
ldy #vcr_open_cnt
|
|
lda [vcr_ptr],y ;see if I can throw this away
|
|
beq go_ahead
|
|
sec ;we can't throw it away
|
|
rts
|
|
|
|
go_ahead ldy #vcr_id
|
|
lda [vcr_ptr],y
|
|
jsl release_vcr
|
|
clc
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
cmp_vol_vcr PROCNAME ;compare vcr buffers to region read in by "volume" routine
|
|
|
|
ldy #vcr_buf_vp
|
|
lda [vcr_ptr],y ;set up some real pointers to this vcr's buffers
|
|
tax
|
|
iny
|
|
iny
|
|
lda [vcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx <ptr1
|
|
sty <ptr1+2 ;we are now ready to compare buffers
|
|
ldy #$01FE ;set index for compare
|
|
@loop2
|
|
lda [vol_buf_ptr],y ;get word from VOLUME routine
|
|
cmp [ptr1],y ;match with word from VCR
|
|
bne @different ;if any difference, go on to next dev
|
|
|
|
dey
|
|
dey
|
|
bpl @loop2
|
|
@same
|
|
clc ;if we get this far then they're identical
|
|
rts
|
|
@different
|
|
sec
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
device_id PROCNAME ;get the device ID of given device
|
|
;on entry:
|
|
; <drvr_dev_num must contain the number of the device
|
|
|
|
;on exit:
|
|
; carry clear: Accumulator contains device ID
|
|
; carry set: Accumulator contains device error
|
|
if 0 then
|
|
lda #drvr_status
|
|
sta <drvr_call_num
|
|
lda #$0002
|
|
sta <drvr_req_cnt ;we'd like just a word
|
|
stz <drvr_req_cnt+2
|
|
lda #ptr1 OR direct_base ;use this direct-page loc for the lousy 2 bytes
|
|
sta <drvr_slist_ptr
|
|
stz <drvr_slist_ptr+2
|
|
stz <drvr_stat_code ;$0000 means get device status
|
|
jsl dev_dispatcher
|
|
bcc @ok
|
|
rts ;return with driver error
|
|
@ok
|
|
ldy #$34 ;offset to device ID in DIB
|
|
lda [drvr_dib_ptr],y ;get the device id
|
|
|
|
rts
|
|
else
|
|
lda <drvr_dev_num
|
|
pha ;save for restoration
|
|
sta <drvr_buf_ptr ;store for dispatcher's use
|
|
stz <drvr_dev_num ;call the dispatcher directly
|
|
lda #$0001 ;call to get_dib_ptr
|
|
sta <drvr_call_num
|
|
jsl dev_dispatcher ;call the dispatcher
|
|
ply ;restore device number
|
|
sty <drvr_dev_num
|
|
bcs @done ;just punt on error
|
|
ldy #$34 ;offset to device ID in DIB
|
|
lda [drvr_dib_ptr],y ;get the device id
|
|
@done
|
|
rts
|
|
endif
|
|
|
|
ENDP
|
|
|
|
|
|
find_vol_online PROCNAME ;look for a volume in online devices
|
|
|
|
;enter with:
|
|
; volume name as g-string in volname_buf_ptr
|
|
; supposed_dev contains the number of the device where we expect�
|
|
; �to find the volume or 0 to walk all devices
|
|
|
|
;brk $05
|
|
|
|
ldx supposed_dev
|
|
bne recover_loop ;this is the case where we look for a lost disk
|
|
simple_loop ;this is the easy case: walk the device list
|
|
@dev_loop
|
|
inx
|
|
stx <drvr_dev_num
|
|
jsr volume ;who's in that drive?
|
|
bcc @chk_name ;my disk, verify that it's the right name
|
|
cmp #invalid_dev_num ;see if out of devices
|
|
;bne @next
|
|
beq not_found ;end of devs
|
|
@next
|
|
ldx <drvr_dev_num ;restore
|
|
bra @dev_loop
|
|
@chk_name
|
|
lda volname_buf_ptr ;set up pointers for cmp_string
|
|
sta <str1_ptr
|
|
lda volname_buf_ptr+2
|
|
sta <str1_ptr+2
|
|
lda vol_name_ptr
|
|
sta <str2_ptr
|
|
lda #^vol_name_buf
|
|
sta <str2_ptr+2
|
|
|
|
lda #$00FF
|
|
sta cmp_mask ;bit mask for ASCII characters
|
|
jsr cmp_string ;are the names the same?
|
|
bcc found ;right disk!
|
|
stz error_priority ;wrong disk, clear the error proirity
|
|
bra @next ;look for another
|
|
|
|
recover_loop ;find a lost disk
|
|
stx <drvr_dev_num ;start with the suspected location. X contains supposed_dev
|
|
jsr device_id ;get that device's ID
|
|
|
|
bcc @ok
|
|
rts ;return with driver error
|
|
@ok
|
|
sta dev_id ;save this value
|
|
|
|
@loop
|
|
jsr volume
|
|
bcc @chk_name2
|
|
cmp #invalid_dev_num ;see if out of devices
|
|
bne @next2
|
|
@wrap
|
|
stz <drvr_dev_num ;wrap down to start of list
|
|
@next2
|
|
ldx <drvr_dev_num
|
|
inx
|
|
cpx supposed_dev ;have we come full circle?
|
|
beq not_found ;if so, we're done
|
|
|
|
stx <drvr_dev_num
|
|
jsr device_id ;get that device's ID
|
|
|
|
bcc @ok1
|
|
cmp #invalid_dev_num
|
|
beq @wrap
|
|
rts ;return with driver error
|
|
@ok1
|
|
cmp dev_id ;same type of device?
|
|
beq @loop
|
|
bra @next2
|
|
@chk_name2
|
|
lda volname_buf_ptr ;set up pointers for cmp_string
|
|
sta str1_ptr
|
|
lda volname_buf_ptr+2
|
|
sta str1_ptr+2
|
|
lda vol_name_ptr
|
|
sta str2_ptr
|
|
lda #^vol_name_buf
|
|
sta str2_ptr+2
|
|
lda #$00FF
|
|
sta cmp_mask
|
|
jsr cmp_string ;are the names the same?
|
|
bcs @next2 ;wrong disk
|
|
|
|
found ;right disk
|
|
clc
|
|
rts
|
|
|
|
not_found lda #vol_not_found
|
|
sec
|
|
rts
|
|
|
|
dev_id ds 1
|
|
|
|
ENDP
|
|
|
|
|
|
search_fcr PROCNAME ;find an fcr by name in file_name_ptr
|
|
;checks that fcr belongs to vcr in vcr_ptr
|
|
|
|
stz old_fcr ;if we find a dup fcr, we'll save its number here
|
|
stz fcr_index ;walk the fcr's
|
|
loop inc fcr_index
|
|
lda fcr_index
|
|
jsl get_fcr
|
|
bcs not_found ;no match
|
|
|
|
@ok1 jsl deref
|
|
stx old_fcr_ptr
|
|
sty old_fcr_ptr+2
|
|
ldy #fcr_fst_id
|
|
lda [old_fcr_ptr],y ;is it mine?
|
|
cmp #my_id
|
|
bne loop
|
|
ldy #fcr_vcr_id
|
|
lda [old_fcr_ptr],y
|
|
ldy #vcr_id
|
|
cmp [vcr_ptr],y ;does it belong to the right volume?
|
|
bne loop
|
|
ldy #fcr_type
|
|
lda [old_fcr_ptr],y ;get filetype
|
|
cmp #$000F ;is it a directory file?
|
|
beq loop
|
|
ldy #fcr_path_name
|
|
lda [old_fcr_ptr],y ;get virtual pointer to the pathname
|
|
tax
|
|
iny
|
|
iny
|
|
lda [old_fcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx src_scratch
|
|
sty src_scratch+2
|
|
parse ;now parse off file name
|
|
sep #$20
|
|
longa off
|
|
|
|
ldy #4-1 ;start with second valid character
|
|
@loop2
|
|
iny
|
|
lda [src_scratch],y
|
|
cmp #':' ;look for colon before filename
|
|
bne @loop2
|
|
|
|
ldx #2-1 ;init ptr to dest string
|
|
@loop3
|
|
iny ;now copy filename to scratch buffer
|
|
inx
|
|
lda [src_scratch],y
|
|
sta scratch_str_buf,x
|
|
bne @loop3 ;if last character wasn't null, keep going
|
|
|
|
rep #$30
|
|
longa on
|
|
|
|
txa ;get final pointer
|
|
dec a
|
|
dec a ;adjust to string length
|
|
sta scratch_str_buf ;set length
|
|
|
|
ldx #<scratch_str_buf
|
|
ldy #^scratch_str_buf
|
|
|
|
stx <str2_ptr
|
|
sty <str2_ptr+2
|
|
;now set up for compare and see if the name matches
|
|
lda <file_name_ptr
|
|
sta <str1_ptr
|
|
lda #^file_buf
|
|
sta <str1_ptr+2
|
|
jsr cmp_string
|
|
bcs loop ;try next fcr in vcr's list
|
|
;at this point, we've found an fcr for a previous open of this file
|
|
lda fcr_index
|
|
sta old_fcr
|
|
@found_exit
|
|
clc
|
|
not_found
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
parse_path PROCNAME ;parse off the path1 string into volume and filename.
|
|
;outputs are g-strings pointed to by volname_buf_ptr (vol name)�
|
|
;�and file_name_ptr. These strings will contain null length�
|
|
;�words if they do not exist.
|
|
;this proc also checks length and syntax and returns�
|
|
;�with carry set if they are not valid.
|
|
lda <path_flag
|
|
and #$4000 ;make sure path1 is valid
|
|
bne @continue
|
|
|
|
@null rep #$30 ; ensure 16bit mode
|
|
|
|
lda #$0000 ;null out the strings
|
|
ldy #$0001
|
|
sta [volname_buf_ptr],y ;this takes care of the terminator nulls
|
|
sta (file_name_ptr),y
|
|
sta [volname_buf_ptr] ;this takes care of the length words
|
|
sta (file_name_ptr)
|
|
clc
|
|
rts
|
|
@continue
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
|
|
ldy #$0002 ;start of path1 string after length word
|
|
lda [path1_ptr],y ;get char
|
|
beq @null ;if terminator, set strings to null
|
|
cmp #':'
|
|
bne filename0
|
|
|
|
vol ;parse volume name
|
|
@loop iny
|
|
lda [path1_ptr],y
|
|
beq vol_end ;null means end of path string
|
|
cmp #':'
|
|
beq vol_end ;colon means end of the volume name
|
|
dey ;adjust for destination index
|
|
sta [volname_buf_ptr],y
|
|
iny ;adjust back
|
|
cpy #vol_max_char+3 ;over the volume name length limit?
|
|
bcc @loop
|
|
vol_end
|
|
dey ;index past last char in dest
|
|
lda #$00
|
|
sta [volname_buf_ptr],y ;place terminator
|
|
|
|
rep #%00100001 ;clear carry as well
|
|
LONGA ON
|
|
|
|
tya
|
|
sbc #2-1 ;adjust for length. carry is clear
|
|
sta [volname_buf_ptr] ;set the length word
|
|
iny
|
|
lda [path1_ptr],y ;refresh my memory...
|
|
and #$00FF
|
|
bne filename
|
|
lda #$0000 ;null out the strings
|
|
ldy #$0001
|
|
sta (file_name_ptr),y ;there is no filename
|
|
sta (file_name_ptr)
|
|
|
|
; We need to check to see if there might be a second pathname and if it might be bad.
|
|
; We do this because we are a good FST and we need to return the right error for calls
|
|
; like change path.
|
|
check2 lda path_flag
|
|
and #path2_mask ; is there a second path
|
|
bne check_path2 ; if so check it out.
|
|
clc
|
|
rts
|
|
bad_span sec
|
|
rts
|
|
check_path2 lda span2
|
|
beq bad_span
|
|
cmp #$001F ; carry is set if too big.
|
|
rts
|
|
|
|
filename0 dey ;adjustment
|
|
filename
|
|
ldx #$0002
|
|
stx temp_index ;this will be our index to the destination string
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
@loop iny
|
|
lda [path1_ptr],y
|
|
beq fn_end
|
|
cmp #':'
|
|
beq error ;sorry, can't have subdirectories!
|
|
tyx ;save source index
|
|
ldy temp_index ;get dest index
|
|
cmp #','
|
|
bne @not_comma
|
|
lda #':' ;translate commas to colons
|
|
@not_comma
|
|
sta (file_name_ptr),y
|
|
iny
|
|
cpy #fn_max_char+4
|
|
bcs error
|
|
sty temp_index
|
|
txy
|
|
bra @loop
|
|
fn_end
|
|
ldy temp_index
|
|
sta (file_name_ptr),y ;accum contains zero
|
|
|
|
rep #%00100000
|
|
LONGA ON
|
|
tya
|
|
dec a
|
|
dec a ;adjust for length
|
|
sta (file_name_ptr) ;set length word
|
|
bra check2 ;we're done with path1, now check path 2
|
|
error
|
|
rep #%00100000
|
|
LONGA ON
|
|
sec
|
|
rts
|
|
|
|
temp_index ds 1
|
|
|
|
ENDP
|
|
|
|
|
|
find_eof PROCNAME ;find the eof and aux_type for a file on an online volume
|
|
|
|
;on entry:
|
|
; volume's directory must be in vol_buf_ptr
|
|
; dev_num must be set up
|
|
; accum should contain T/S of first T/S list sector
|
|
|
|
;on exit:
|
|
; X = eof (low)
|
|
; Y = eof (high)
|
|
;
|
|
; for Text, A-, B-, S-types:
|
|
; A = total number of sectors used
|
|
;
|
|
; for Bin, Asoft, Int, Rel
|
|
; A = aux_type
|
|
|
|
|
|
ldx <fcr_buf_ptr ;set up buffer for driver
|
|
stx <drvr_buf_ptr
|
|
ldx <fcr_buf_ptr+2
|
|
stx <drvr_buf_ptr+2
|
|
stz data_secs_cnt
|
|
stz ts_secs_cnt
|
|
stz eof_scratch
|
|
stz eof_scratch+2
|
|
;load sectors with useful info -->T/S list & 1 data sect
|
|
pha
|
|
phy
|
|
ldy #vcr_open_cnt
|
|
lda [<vcr_ptr],y
|
|
inc a
|
|
sta [<vcr_ptr],y
|
|
ply
|
|
pla
|
|
jsr new_rwts ;read in 1st T/S list sector
|
|
php
|
|
pha
|
|
phy
|
|
ldy #vcr_open_cnt
|
|
lda [<vcr_ptr],y
|
|
dec a
|
|
sta [<vcr_ptr],y
|
|
ply
|
|
pla
|
|
plp
|
|
|
|
bcc @ok1
|
|
rts ;return with driver error
|
|
@ok1
|
|
lda dos_type ;this should contain the dos filetype
|
|
beq text ;text may be sparse
|
|
and #$0017 ;check for "easy" types: Int, Asoft, Bin, Rel
|
|
beq not_easy
|
|
brl easy ;go handle easy types
|
|
not_easy
|
|
@count
|
|
ldy #ts_list_start ;point to start of t/s list entries
|
|
inc ts_secs_cnt ;count T/S list sector
|
|
@loop
|
|
lda [drvr_buf_ptr],y ;get the entry
|
|
beq @empty
|
|
inc data_secs_cnt ;keep count of actual blocks used
|
|
iny
|
|
iny ;next entry
|
|
cpy #$0100
|
|
bne @loop ;get next unless we overflowed
|
|
lda #drvr_read
|
|
sta <drvr_call_num
|
|
ldy #ts_link ;offset in T/S sector to link bytes
|
|
lda [fcr_buf_ptr],y ;get the links
|
|
beq @done ;$0000 means no more links --> last T/S list sector
|
|
|
|
pha
|
|
phy
|
|
ldy #vcr_open_cnt
|
|
lda [<vcr_ptr],y
|
|
inc a
|
|
sta [<vcr_ptr],y
|
|
ply
|
|
pla
|
|
jsr new_rwts ;load next T/S list
|
|
php
|
|
pha
|
|
phy
|
|
ldy #vcr_open_cnt
|
|
lda [<vcr_ptr],y
|
|
dec a
|
|
sta [<vcr_ptr],y
|
|
ply
|
|
pla
|
|
plp
|
|
|
|
bcc @count ;if good, count valid t/s entries
|
|
rts ;return with driver error
|
|
@empty
|
|
@done
|
|
;assume file is all bytes in all allocated sectors
|
|
;calculate: eof = (sectors used) * 256
|
|
lda data_secs_cnt ;get the number of data sectors used
|
|
xba ;multiply low byte by 256
|
|
tax ;save this value
|
|
and #$FF00 ;clear (former) high byte
|
|
sta eof_scratch
|
|
txa ;get back that flipped sector count
|
|
and #$00FF ;now we want the other half
|
|
sta eof_scratch+2 ;all done!
|
|
lda data_secs_cnt
|
|
clc
|
|
adc ts_secs_cnt ;find total number of sectors used
|
|
brl eof_exit
|
|
text
|
|
@count
|
|
ldx #ts_list_start ;init offset to 1st entry in case all are 0
|
|
;** Monte Benaresh -- 2/20/92
|
|
ldy #ts_list_start ;point to start of T/S list entries
|
|
inc ts_secs_cnt ;count T/S list sector
|
|
@loop
|
|
lda [drvr_buf_ptr],y ;get the entry
|
|
beq @empty
|
|
tyx ;save in case it's the last non-zero
|
|
inc data_secs_cnt
|
|
@empty
|
|
iny
|
|
iny ;next entry
|
|
cpy #$0100
|
|
bne @loop ;get next unless we overflowed
|
|
lda #drvr_read
|
|
sta <drvr_call_num
|
|
ldy #ts_link ;offset in T/S sector to link bytes
|
|
lda [fcr_buf_ptr],y ;get the links
|
|
beq @done ;$0000 means no more links --> last T/S list sector
|
|
|
|
pha
|
|
phy
|
|
ldy #vcr_open_cnt
|
|
lda [<vcr_ptr],y
|
|
inc a
|
|
sta [<vcr_ptr],y
|
|
ply
|
|
pla
|
|
jsr new_rwts ;next t/s list
|
|
php
|
|
pha
|
|
phy
|
|
ldy #vcr_open_cnt
|
|
lda [<vcr_ptr],y
|
|
dec a
|
|
sta [<vcr_ptr],y
|
|
ply
|
|
pla
|
|
plp
|
|
bcc @count ;if good, count valid t/s entries
|
|
rts ;return with driver error
|
|
|
|
@done ;we have the last T/S list sector for a text file.
|
|
get_eof ;now we have to find the last valid (non-0) sector in the list
|
|
txa ;get that entry position so we can calculate
|
|
sec
|
|
sbc #ts_list_start ;subtract the offset to start of T/S list
|
|
lsr a ;divide by 2 to get # of sectors
|
|
xba ;turn it into a byte value
|
|
sta eof_scratch ;store temporary result = # of bytes in all but last�
|
|
;�data sector in this T/S list
|
|
lda <drvr_buf_ptr
|
|
adc #$0100 ;incr bufer ptr to next pg. carry should be clear
|
|
sta <drvr_buf_ptr
|
|
bcc @no_carry
|
|
inc <drvr_buf_ptr+2
|
|
@no_carry
|
|
lda #drvr_read
|
|
sta <drvr_call_num
|
|
txy ;restore the index
|
|
lda [fcr_buf_ptr],y
|
|
sta last_data_sec ;save this number in case we're successful
|
|
;
|
|
; next added 2/20/92 by Monte Benaresh
|
|
bne @real_sector
|
|
@no_sector
|
|
ldy #-1 ;will get incremented to 0 for eof
|
|
bra found_eof ;calculate now
|
|
@real_sector
|
|
; end 2/20/92
|
|
pha
|
|
phy
|
|
ldy #vcr_open_cnt
|
|
lda [<vcr_ptr],y
|
|
inc a
|
|
sta [<vcr_ptr],y
|
|
ply
|
|
pla
|
|
jsr new_rwts ;load in that last data sector
|
|
php
|
|
pha
|
|
phy
|
|
ldy #vcr_open_cnt
|
|
lda [<vcr_ptr],y
|
|
dec a
|
|
sta [<vcr_ptr],y
|
|
ply
|
|
pla
|
|
plp
|
|
|
|
bcc @ok
|
|
; lda #error return with driver error
|
|
rts
|
|
@ok
|
|
;may need special check for case where data fills last sec exactly!
|
|
ldy #$00FF ;offset to last byte
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
@loop2 lda [drvr_buf_ptr],y
|
|
bne found_eof ;when we hit a non-0, that's eof-1
|
|
dey ;back up to next one
|
|
bpl @loop2 ;keep going as long as we don't hit bottom
|
|
;if we hit bottom, just set eof to end at end of last�
|
|
;�sector. in effect this causes the fst to ignore the�
|
|
;�zero-filled sector.
|
|
found_eof rep #%00100001 ;clear carry, too
|
|
LONGA ON
|
|
iny ;eof points to *next* byte
|
|
tyx ;save that byte part
|
|
ldy #ts_sec_offset ;offset to offset number of 1st sector in this list
|
|
lda [fcr_buf_ptr],y ;get sector offset word
|
|
xba
|
|
tay
|
|
and #$FF00 ;keep high part --> byte offset
|
|
adc eof_scratch ;build this value. carry is clear from above
|
|
sta eof_scratch
|
|
tya
|
|
and #$00FF ;this is byte offset for the high word
|
|
adc eof_scratch+2 ;build high word with carry from low word
|
|
sta eof_scratch+2
|
|
txa ;get back that last byte part
|
|
adc eof_scratch ;carry should be clear
|
|
sta eof_scratch
|
|
lda eof_scratch+2
|
|
adc #$0000
|
|
sta eof_scratch+2
|
|
;find blks_used
|
|
lda data_secs_cnt
|
|
clc
|
|
adc ts_secs_cnt ;find total number of sectors used
|
|
bra eof_exit
|
|
|
|
easy ;filetypes Asoft, Int, Bin, and Rel contain their eof's!
|
|
lda <drvr_buf_ptr
|
|
clc
|
|
adc #$0100 ;incr buffer ptr to next pg.
|
|
sta <drvr_buf_ptr
|
|
lda <drvr_buf_ptr+2
|
|
adc #$0000 ;carry bank
|
|
sta <drvr_buf_ptr+2
|
|
lda #drvr_read
|
|
sta <drvr_call_num
|
|
ldy #ts_list_start ;offset to start of list entries
|
|
lda [fcr_buf_ptr],y ;get first data sector
|
|
sta last_data_sec
|
|
pha
|
|
phy
|
|
ldy #vcr_open_cnt
|
|
lda [<vcr_ptr],y
|
|
inc a
|
|
sta [<vcr_ptr],y
|
|
ply
|
|
pla
|
|
jsr new_rwts ;load in that last data sector
|
|
php
|
|
pha
|
|
phy
|
|
ldy #vcr_open_cnt
|
|
lda [<vcr_ptr],y
|
|
dec a
|
|
sta [<vcr_ptr],y
|
|
ply
|
|
pla
|
|
plp
|
|
bcc @ok
|
|
; lda #error return with driver error
|
|
rts
|
|
@ok
|
|
|
|
lda dos_type
|
|
ldy #$0000 ;offset to length bytes for Applesoft & Integer
|
|
and #�$FF83 ;mask out Applesoft, Integer and lock bits
|
|
beq @get_len ;get the length bytes
|
|
ldy #$0002 ;offset for binary and relocatable
|
|
@get_len
|
|
lda [drvr_buf_ptr],y
|
|
sta eof_scratch ;that's the eof, period.
|
|
lda #$0000
|
|
sta eof_scratch+2 ;never a high word for these filetypes
|
|
@get_aux ;find the aux type
|
|
lda dos_type
|
|
and #�$FF84 ;mask out Binary
|
|
beq @bin
|
|
cmp #$0001 ;is it integer?
|
|
bne @apsoft
|
|
lda #$0C00
|
|
bra eof_done
|
|
@apsoft
|
|
lda #$0801
|
|
bra eof_done
|
|
@bin lda [drvr_buf_ptr] ;for reloc & binary, 1st word is aux_type!
|
|
|
|
eof_done ;we now have the eof, for every type, stored safely in eof_scratch
|
|
eof_exit ldx eof_scratch
|
|
ldy eof_scratch+2 ;load eof into X & Y for caller
|
|
;on exit, A should contain either aux_type or blks_used
|
|
clc
|
|
rts
|
|
|
|
eof_scratch ds.l 1
|
|
data_secs_cnt ds 1
|
|
ts_secs_cnt ds 1
|
|
|
|
ENDP
|
|
|
|
|
|
load_cat_secs PROCNAME ;load the catalog sectors into vol_buf_ptr, up to�
|
|
;�max of 15 total
|
|
|
|
;at this point, the vtoc and the first catalog sector
|
|
;have been read in by the subroutine "volume"
|
|
lda <vol_buf_ptr
|
|
clc
|
|
adc #$0100 ;set to first cat sector
|
|
sta <drvr_buf_ptr
|
|
lda <vol_buf_ptr+2
|
|
adc #$0000 ;carry bank
|
|
sta <drvr_buf_ptr+2
|
|
ldx #14 ;max number of additional cat sectors
|
|
stx countdn
|
|
@loop
|
|
ldy #$0001 ;offset to LINK BYTES in LAST CAT SECTOR
|
|
lda [drvr_buf_ptr],y ;get track/sector of next cat sector
|
|
beq @cat_done ;last cat sector
|
|
;range checking?
|
|
pha
|
|
lda <drvr_buf_ptr
|
|
adc #$0100 ;bump to next sector. carry should be clear
|
|
sta <drvr_buf_ptr
|
|
lda <drvr_buf_ptr+2
|
|
adc #$0000 ;carry bank
|
|
sta <drvr_buf_ptr+2
|
|
lda #drvr_read
|
|
sta <drvr_call_num
|
|
pla ;restore track/sector request
|
|
jsr new_rwts ;go get it
|
|
bcc @ok
|
|
; lda #error return with driver error
|
|
rts
|
|
@ok dec countdn
|
|
bne @loop
|
|
@cat_done
|
|
lda #15
|
|
sec
|
|
sbc countdn ;total # of cat sectors
|
|
sta cat_sec_count ;this is the number of catalog sectors read in
|
|
|
|
clc
|
|
rts
|
|
|
|
countdn ds 1
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
check_dir PROCNAME ;check the directory sectors in vol_buf_ptr for�
|
|
;�the filename in file_name_ptr
|
|
lda file_name_ptr
|
|
sta str1_ptr
|
|
lda #^file_buf
|
|
sta str1_ptr+2
|
|
lda #$0000 ;cat sector numbers start at 0
|
|
@cat_loop ldx #$0000 ;same for fde's
|
|
@fde_loop sta cat_index
|
|
stx fde_index ;save these
|
|
jsr find_fde
|
|
bcc @ok
|
|
; lda #parm_range_err OR $8000 ;internal range error
|
|
rts ;error
|
|
@ok
|
|
*** changed 6-May-93 DAL
|
|
;;; lda [fde_ptr] ;first byte tells whether in use
|
|
;;; and #$00FF
|
|
jsr load_fde_flag
|
|
*** end 6-May-93
|
|
|
|
beq file_not_here ;a $00 means beyond last entry
|
|
cmp #$00FF
|
|
beq @next_fde ;inactive, go to next one
|
|
lda <fde_ptr
|
|
adc #fde_name-2 ;add offset to name field w/room for length word.
|
|
;carry should be clear
|
|
sta <str2_ptr
|
|
lda <fde_ptr+2
|
|
adc #$0000 ;carry bank
|
|
sta <str2_ptr+2
|
|
ldy #$1D+2 ;offset to last character in name
|
|
lda [str2_ptr] ;save this word before we crash it with length
|
|
pha
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
@loop lda [str2_ptr],y ;borrow this pointer before we give it to cmp_string
|
|
cmp #' ' OR $80 ;check for spaces used as padding (w/high bit set)
|
|
bne @nam_end
|
|
dey
|
|
bpl @loop ;as long as we don't hit bottom, keep going
|
|
; lda #dir_error ;name is all spaces!
|
|
plx
|
|
|
|
rep #$30 ;long a,x
|
|
sec
|
|
rts
|
|
@nam_end
|
|
dey ;adjust to string length
|
|
lda #$7F
|
|
sta cmp_mask ;set the compare mask
|
|
|
|
rep #%00100000
|
|
LONGA ON
|
|
tya
|
|
sta [str2_ptr] ;str2 is a g-string without the terminator
|
|
jsr cmp_string ;str1_ptr should contain file_name_ptr
|
|
pla ;restore that one word we stepped on
|
|
sta [str2_ptr]
|
|
bcc right_fde ;we got it!
|
|
@next_fde ldx fde_index
|
|
lda cat_index
|
|
inx ;next fde
|
|
cpx #$0007 ;check limit of 7 fde's per cat sector
|
|
bcc @fde_loop ;we're ok, check next fde
|
|
ina ;next catalog sector
|
|
cmp cat_sec_count ;past our limit?
|
|
bcc @cat_loop ;move on to next cat sector
|
|
file_not_here ;file not on this volume
|
|
lda #$FFFF
|
|
sta fde_index ;indicate file not found
|
|
clc
|
|
rts
|
|
|
|
right_fde clc ;success
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
export do_option_list
|
|
do_option_list PROCNAME ;return option list data to user buffer
|
|
;enter with:
|
|
; Y = offset in param block to option list ptr
|
|
|
|
;brk $05
|
|
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr+2
|
|
|
|
ora <user_ptr ;test for 0
|
|
beq done ;if $00000000, don't use it!
|
|
list_good
|
|
lda [user_ptr] ;get length word
|
|
cmp #4+2 ;need 4 bytes for overhead, 2 for data
|
|
bcs @ok
|
|
@too_small
|
|
sec ;this is an error
|
|
rts
|
|
@ok
|
|
lda #my_id ; my id is same as its length = 2
|
|
tay
|
|
sta [user_ptr],y
|
|
iny
|
|
iny ;offset to actual buffer
|
|
sta [user_ptr],y ;give user our FST ID
|
|
done
|
|
clc
|
|
rts ;that's all there is to it!
|
|
|
|
ENDP
|
|
|
|
|
|
export set_text_mode
|
|
set_text_mode PROCNAME ;handle FST-specific call
|
|
|
|
WITH fst_specific
|
|
|
|
lda p_cnt
|
|
cmp #3 ;check pcount
|
|
beq @pcount_ok
|
|
|
|
lda #invalid_pcount
|
|
sec
|
|
rts
|
|
@pcount_ok
|
|
ldy #param1 ;get parameter
|
|
lda [param_blk_ptr],y
|
|
cmp #1+1 ;range check
|
|
bcc @mode_ok
|
|
@bad_mode
|
|
lda #parm_range_err
|
|
sec
|
|
rts
|
|
@mode_ok
|
|
sta text_flag
|
|
|
|
lda #0 ;no error
|
|
clc
|
|
rts
|
|
|
|
ENDWITH
|
|
|
|
ENDP
|
|
|
|
|
|
export get_text_mode
|
|
get_text_mode PROCNAME ;handle FST-specific call
|
|
|
|
WITH fst_specific
|
|
|
|
lda p_cnt
|
|
cmp #3 ;check pcount
|
|
beq @pcount_ok
|
|
|
|
lda #invalid_pcount
|
|
sec
|
|
rts
|
|
@pcount_ok
|
|
lda text_flag
|
|
ldy #param1 ;get parameter
|
|
sta [param_blk_ptr],y
|
|
|
|
lda #0 ;no error
|
|
clc
|
|
rts
|
|
|
|
ENDWITH
|
|
|
|
ENDP
|
|
|
|
|
|
get_file_info PROCNAME ;get all necessary info for a file and stuff it into�
|
|
;�global variables
|
|
;fde_ptr must point to the file's fde
|
|
|
|
lda #storage_type ;if it's not the root directory, it gets this storage type
|
|
sta stor_type
|
|
|
|
ldy #fde_type
|
|
lda [fde_ptr],y ;get the filetype
|
|
tax
|
|
|
|
and #$0080 ;look at the lock bit
|
|
bne @locked
|
|
lda #access_unlocked
|
|
bra @store
|
|
|
|
@locked
|
|
lda #access_locked
|
|
@store
|
|
sta access
|
|
txa ;get back original fetch
|
|
and #$007F ;mask out high byte and lock bit
|
|
sta dos_type
|
|
translate_type ;determine corresponding filetype
|
|
ldx #8
|
|
@loop
|
|
lsr a
|
|
bcs @lookup
|
|
dex
|
|
bne @loop
|
|
@lookup
|
|
txa
|
|
asl a ;multiply by two for table
|
|
tax
|
|
lda type_table,x
|
|
sta os_type
|
|
lda dos_type
|
|
and #$0017 ;is it basic, Bin, or Rel?
|
|
beq not_easy
|
|
easy
|
|
ldy #fde_ts_link
|
|
lda [fde_ptr],y ;find_eof needs this
|
|
jsr find_eof
|
|
bcc @ok
|
|
rts ;return with driver error
|
|
@ok
|
|
sta aux_type
|
|
stx eof
|
|
sty eof+2
|
|
ldy #fde_sec_used
|
|
lda [fde_ptr],y ;we can trust the directory for these filetypes
|
|
sta blks_used
|
|
|
|
clc
|
|
rts
|
|
not_easy
|
|
ldy #fde_ts_link
|
|
lda [fde_ptr],y ;find_eof needs this
|
|
jsr find_eof
|
|
bcc @ok
|
|
rts ;return with driver error
|
|
@ok sta blks_used
|
|
stx eof
|
|
sty eof+2
|
|
stz aux_type
|
|
|
|
rts ;carry is clear
|
|
|
|
|
|
type_table ;lookup table to translate DOS filetypes to GS/OS(TM)
|
|
|
|
; GS/OS type DOS 3.3 type
|
|
; ---------- ------------
|
|
dc.w $04 ; ASCII Text File Text
|
|
dc.w $0F ; Directory (undefined)
|
|
dc.w $00 ; uncatgegorized B-type
|
|
dc.w $00 ; uncatgegorized A-type
|
|
dc.w $FE ; EDASM Relocatable Code File Relocatable
|
|
dc.w $00 ; uncatgegorized S-type
|
|
dc.w $06 ; Binary File Binary
|
|
dc.w $FC ; Applesoft Basic Program Applesoft Basic
|
|
dc.w $FA ; Integer Basic Program Integer Basic
|
|
dc.w $EE ; Classic Auto E-type
|
|
|
|
ENDP
|
|
|
|
|
|
get_dir_entry PROCNAME
|
|
|
|
;brk $1C
|
|
|
|
ldy #vcr_dev ; even if we don't access the device, set this up
|
|
lda [<vcr_ptr],y ; for get_last_dev.
|
|
sta drvr_dev_num
|
|
|
|
stz error ;we store the non-fatal error here
|
|
ldy #fcr_type
|
|
lda [fcr_ptr],y ;SCM promises to give me the right fcr
|
|
cmp #$000F ;is it a directory file?
|
|
beq @ok
|
|
lda #version_error OR $8000 ;internal error
|
|
sec
|
|
rts
|
|
@ok
|
|
lda class
|
|
beq @class0
|
|
@class1
|
|
ldy #get_dir_entry1.base
|
|
lda [param_blk_ptr],y ;get the base
|
|
sta base1
|
|
ldy #get_dir_entry1.displacement
|
|
lda [param_blk_ptr],y ;get displacement
|
|
sta displacement1
|
|
ldy #get_dir_entry1.name ;copy pointer to direct page
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr+2
|
|
bra chk_entry ;go validate the entry num
|
|
@class0
|
|
ldy #get_dir_entry0.base
|
|
lda [param_blk_ptr],y ;get the base
|
|
sta base1
|
|
ldy #get_dir_entry0.displacement
|
|
lda [param_blk_ptr],y ;get displacement
|
|
sta displacement1
|
|
|
|
ldy #fcr_blks_used
|
|
lda [fcr_ptr],y ;get number of sectors owned by this directory
|
|
dea ;account for vtoc
|
|
sta cat_sec_count ;we need this below
|
|
ldy #get_dir_entry0.name ;copy pointer to direct page
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr+2
|
|
|
|
;brk $1d
|
|
|
|
chk_entry
|
|
lda base1
|
|
tax ;save for a moment
|
|
ora displacement1 ;are they both zero?
|
|
beq special ;special funtion for base = displacement = 0
|
|
|
|
txa ;restore original base value
|
|
beq absolute
|
|
dea
|
|
beq add
|
|
dea
|
|
beq subtract
|
|
lda #parm_range_err
|
|
rts
|
|
special ;base and displacement are both zero
|
|
ldy #fcr_tot_ent
|
|
lda [fcr_ptr],y ;get the total number of valid entries
|
|
sta entry_num ;user gets this value here
|
|
|
|
lda #0
|
|
ldy #fcr_entry_num
|
|
sta [fcr_ptr],y ;reset entry number for this directory
|
|
|
|
brl fill_param_blk ;that all we do!
|
|
absolute
|
|
ldy #fcr_tot_ent
|
|
lda [fcr_ptr],y ;get the total number of valid entries
|
|
cmp displacement1
|
|
bcs @ok
|
|
lda #end_of_dir ;entry number too high
|
|
sec
|
|
rts
|
|
@ok
|
|
lda displacement1
|
|
sta entry_num
|
|
bra find_entry
|
|
add
|
|
ldy #fcr_entry_num
|
|
lda [fcr_ptr],y ;get the current entry number
|
|
clc
|
|
adc displacement1
|
|
sta entry_num
|
|
ldy #fcr_tot_ent
|
|
lda [fcr_ptr],y ;get the total number of valid entries
|
|
cmp entry_num ;range check
|
|
bcs find_entry
|
|
lda #end_of_dir
|
|
sec
|
|
rts
|
|
subtract
|
|
ldy #fcr_entry_num
|
|
lda [fcr_ptr],y ;get the current entry number
|
|
dec a
|
|
cmp displacement1
|
|
bcc @err ; out of range, displacement would make entry < 1
|
|
inc a
|
|
sec
|
|
sbc displacement1
|
|
sta entry_num
|
|
ldy #fcr_tot_ent
|
|
lda [fcr_ptr],y ;get the total number of valid entries
|
|
cmp entry_num ;range check
|
|
bcs find_entry
|
|
|
|
@err lda #end_of_dir
|
|
sec
|
|
rts
|
|
|
|
find_entry ;cycle through to nth directory entry
|
|
lda entry_num
|
|
ldy #fcr_entry_num
|
|
sta [fcr_ptr],y
|
|
sta countdown ;set this up for the loop
|
|
|
|
ldy #vcr_buf_vp ;get the vcr's buffer set up
|
|
lda [vcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [vcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx vol_buf_ptr
|
|
sty vol_buf_ptr+2
|
|
;now loop through valid entries
|
|
lda #$0000 ;cat sector numbers start at 0
|
|
@cat_loop
|
|
ldx #$0000 ;same for fde's
|
|
@fde_loop
|
|
sta cat_index
|
|
stx fde_index ;save these
|
|
jsr find_fde
|
|
bcc @ok
|
|
rts ;error
|
|
@ok
|
|
*** changed 6-May-93 DAL
|
|
;;; lda [fde_ptr] ;first byte tells whether in use
|
|
;;; and #$00FF
|
|
jsr load_fde_flag
|
|
*** end 6-May-93
|
|
bne @cont ;a $00 means beyond last entry
|
|
lda #end_of_dir OR $8000 ;internal error
|
|
sec
|
|
rts
|
|
@cont
|
|
cmp #$00FF
|
|
beq @inactive ;inactive, don't count it
|
|
dec countdown
|
|
beq right_fde ;if countdown hits 0, we've got our man
|
|
@inactive
|
|
ldx fde_index
|
|
lda cat_index
|
|
inx ;next fde
|
|
cpx #$0007 ;check limit of 7 fde's per cat sector
|
|
bcc @fde_loop ;we're ok, check next fde
|
|
ina ;next catalog sector
|
|
cmp cat_sec_count ;past our limit?
|
|
bcc @cat_loop ;move on to next cat sector
|
|
|
|
right_fde ;fde_ptr now points to the fde in question!
|
|
;now, alas, we have to go to disk for some of the info
|
|
ldy #vcr_name
|
|
lda [vcr_ptr],y ;get the vp's to volume name
|
|
tax
|
|
iny
|
|
iny
|
|
lda [vcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx volname_buf_ptr
|
|
sty volname_buf_ptr+2
|
|
ldy #vcr_dev
|
|
lda [vcr_ptr],y ;get last known device
|
|
sta supposed_dev
|
|
jsr find_vol_online
|
|
bcc @ok
|
|
lda #vol_not_found ;we must have the device online
|
|
rts
|
|
|
|
@ok ldy #vcr_dev ; has the volume moved?
|
|
lda [<vcr_ptr],y
|
|
cmp drvr_dev_num
|
|
beq @ok1 ; no ->
|
|
|
|
ldy #vcr_dev ; update the dev_num
|
|
lda drvr_dev_num
|
|
sta [<vcr_ptr],y
|
|
|
|
@ok1 jsr get_file_info
|
|
bcc @ok2
|
|
lda #dir_error
|
|
rts
|
|
@ok2 ;we now have all our file info in global variables
|
|
do_name
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
ldy #fde_sec_used-1 ;this points to the last byte of the filename
|
|
@loop
|
|
lda [fde_ptr],y
|
|
cmp #' ' OR $80 ;is it a space?
|
|
bne @set_len ;if not, we've found the last character
|
|
dey
|
|
bne @loop ;use bne just in case...
|
|
@set_len
|
|
rep #%00100001 ;16-bit accum, carry clear
|
|
LONGA ON
|
|
iny ;get past end
|
|
sty src_end
|
|
tya
|
|
sbc #fde_name-1 ;adjust for name len. note: carry is clear
|
|
sta name_len
|
|
ina
|
|
ina
|
|
ina ;add three
|
|
tay
|
|
lda [user_ptr]
|
|
sta usr_len ;this will be a worthwile investment
|
|
cpy usr_len
|
|
bcc @big_enough
|
|
lda #buff_too_small
|
|
sta error ;non-fatal
|
|
@big_enough
|
|
ldy #fde_name-1 ;this is our source pointer
|
|
lda #$0004-1
|
|
sta dest_ptr
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
@loop1
|
|
iny
|
|
cpy src_end
|
|
beq @name_done
|
|
ldx dest_ptr
|
|
inx
|
|
cpx usr_len ;check for end of user buffer
|
|
beq @name_done
|
|
stx dest_ptr
|
|
lda [fde_ptr],y
|
|
tyx
|
|
ldy dest_ptr
|
|
and #$7F ;strip high bits
|
|
cmp #':'
|
|
bne @not_colon
|
|
lda #',' ;replace colons with commas
|
|
@not_colon
|
|
sta [user_ptr],y
|
|
txy ;restore source pointer
|
|
bra @loop1
|
|
@name_done
|
|
rep #%00100001 ;16-bit accum, carry clear
|
|
LONGA ON
|
|
lda name_len
|
|
ldy #$0002
|
|
sta [user_ptr],y ;that sets the length word
|
|
|
|
fill_param_blk ;now fill in the user param block
|
|
lda class
|
|
bne @class1
|
|
@class0
|
|
lda #$0000
|
|
ldy #get_dir_entry0.flags
|
|
sta [param_blk_ptr],y ;indicate not extended file
|
|
|
|
lda #$0001
|
|
sta p_cnt ;this will make the fill_param tables work right
|
|
|
|
lda #<get_dir_entry0_f
|
|
sta <fill_tabl ;set up for right parameter fill table
|
|
jsr fill_param
|
|
bra all_done ;now take care of the name
|
|
@class1
|
|
lda #$0000 ;non_extended file
|
|
ldy #get_dir_entry1.flags
|
|
sta [param_blk_ptr],y
|
|
|
|
lda #<get_dir_entry1_f
|
|
sta <fill_tabl ;set up for right parameter fill table
|
|
jsr fill_param
|
|
|
|
lda p_cnt
|
|
cmp #15 ;do we need option list?
|
|
bcc @no_list
|
|
|
|
ldy #get_dir_entry1.option_list
|
|
jsr do_option_list
|
|
bcc @list_ok
|
|
|
|
lda #buff_too_small
|
|
sta error
|
|
@no_list
|
|
@list_ok
|
|
|
|
all_done
|
|
lda error
|
|
cmp #$0001 ;set carry
|
|
rts
|
|
|
|
src_end ds 1
|
|
dest_ptr ds 1
|
|
error ds 1
|
|
base1 ds 1
|
|
displacement1 ds 1
|
|
countdown ds 1
|
|
name_len ds 1
|
|
usr_len ds 1
|
|
|
|
ENDP
|
|
|
|
|
|
read_newline PROCNAME ;transfer a range of bytes according to newline
|
|
|
|
;pointer at src_scratch must be set to the start of the�
|
|
;�source range
|
|
|
|
;pointer at usr_ptr must be set to destination buffer
|
|
|
|
;byte_cnt must contain the maximum number of bytes�
|
|
;�to be transferred
|
|
|
|
;recent_xfer gets updated
|
|
|
|
;on exit, carry set means a newline character was encountered
|
|
newline
|
|
ldy #fcr_newline ;get the newline pointer
|
|
lda [fcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx nl_list_ptr
|
|
sty nl_list_ptr+2
|
|
ldy #fcr_mask
|
|
lda [fcr_ptr],y
|
|
sta <nl_msk
|
|
lda nl_len ;how many nl characters are we dealing with?
|
|
dea
|
|
bne slow_nl ;if more than 1 newline char, things slow down
|
|
fast_nl
|
|
lda [nl_list_ptr]
|
|
and #$00FF ;there's only one real byte there
|
|
sta <nl_char
|
|
|
|
ldy byte_cnt
|
|
beq end_nl2 ;check for degenerate case
|
|
ldy #0
|
|
|
|
sep #$30 ;short registers and accumulator
|
|
LONGA OFF
|
|
LONGI OFF
|
|
|
|
|
|
@loop phy
|
|
|
|
rep #$30
|
|
LONGA ON
|
|
LONGI ON
|
|
ldy #fcr_dos_type
|
|
lda [fcr_ptr],y ;get the DOS 3.3 filetype
|
|
sep #$30
|
|
LONGA OFF
|
|
LONGI OFF
|
|
bne @1 ;if NOT 0 (TEXT file) don't touch the data
|
|
ply
|
|
lda [<src_scratch],y ; xfer char
|
|
sta [<user_ptr],y
|
|
and #$7F ; strip the high bit for newline compare
|
|
bra @2 ; continue ->
|
|
|
|
@1 ply
|
|
lda [src_scratch],y
|
|
sta [user_ptr],y
|
|
@2 inc recent_xfer
|
|
and <nl_msk
|
|
cmp <nl_char
|
|
beq @hit_nl
|
|
|
|
rep #$30
|
|
LONGA ON
|
|
LONGI ON
|
|
iny
|
|
cpy byte_cnt
|
|
sep #$30
|
|
LONGA OFF
|
|
LONGI OFF
|
|
|
|
bcc @loop
|
|
|
|
rep #$30 ;16-bit accum, carry clear
|
|
LONGA ON
|
|
LONGI ON
|
|
clc
|
|
|
|
bra end_nl
|
|
@hit_nl
|
|
rep #$30 ;16-bit accum
|
|
LONGA ON
|
|
LONGI ON
|
|
|
|
sec ;indicate that newline was encountered
|
|
bra end_nl
|
|
|
|
slow_nl ldy #$0000
|
|
|
|
sep #$20 ;short accumulator
|
|
LONGA OFF
|
|
|
|
@loop phy
|
|
|
|
rep #$20
|
|
LONGA ON
|
|
ldy #fcr_dos_type
|
|
lda [fcr_ptr],y ;get the DOS 3.3 filetype
|
|
sep #$20
|
|
LONGA OFF
|
|
bne @1 ;if NOT 0 (TEXT file) don't touch the data
|
|
ply
|
|
lda [<src_scratch],y ; xfer char
|
|
sta [<user_ptr],y
|
|
and #$7F ; strip the high bit for newline compare
|
|
bra @2 ; continue ->
|
|
|
|
@1 ply
|
|
lda [src_scratch],y
|
|
sta [user_ptr],y
|
|
@2 inc recent_xfer
|
|
and <nl_msk
|
|
tyx
|
|
|
|
ldy nl_len
|
|
@cmp_loop dey
|
|
bmi @not_end ;we've run out of newline characters
|
|
cmp [nl_list_ptr],y
|
|
bne @cmp_loop
|
|
bra @hit_nl ;we've hit a newline character
|
|
|
|
@not_end txy ;restore buffer position
|
|
iny
|
|
cpy byte_cnt ;are we out of bytes anyway?
|
|
bne @loop
|
|
|
|
rep #$20 ;16-bit accum
|
|
LONGA ON
|
|
clc
|
|
|
|
bra end_nl
|
|
|
|
@hit_nl sec ;indicate that newline was encountered
|
|
|
|
end_nl rep #$30
|
|
LONGA ON
|
|
LONGI ON
|
|
end_nl2 rts
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
read PROCNAME ;handle the READ call
|
|
|
|
stz error ;errors go here
|
|
stz bytes_sent
|
|
stz bytes_sent+2
|
|
|
|
stz recent_xfer
|
|
|
|
;brk $42
|
|
|
|
find_offset ;figure out what the "data_offset" value is for this file
|
|
ldy #fcr_dos_type
|
|
lda [fcr_ptr],y
|
|
beq @pure_data ;0 means text
|
|
and #�$0003 ;mask off bits for Asoft & Integer
|
|
bne @not_basic
|
|
lda #$0002 ;basic files have 2 bytes before the real data
|
|
sta data_offset
|
|
bra fetch_fcr
|
|
@not_basic
|
|
and #�$0014 ;bits for binary & relocatable
|
|
bne @not_bin
|
|
lda #$0004 ;these types have 4 bytes before real data
|
|
sta data_offset
|
|
bra fetch_fcr
|
|
@not_bin
|
|
@pure_data ;the only types left are considered to have pure data
|
|
stz data_offset
|
|
|
|
fetch_fcr ;fetch stuff from fcr for handy reference
|
|
ldy #fcr_mask
|
|
lda [fcr_ptr],y ;get newline mask
|
|
sta nl_msk
|
|
ldy #fcr_newline_len
|
|
lda [fcr_ptr],y ;get newline list length
|
|
sta nl_len
|
|
ldy #fcr_eof
|
|
lda [fcr_ptr],y
|
|
sta eof
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y
|
|
sta eof+2
|
|
ldy #fcr_mark
|
|
lda [fcr_ptr],y
|
|
sta mark
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y
|
|
sta mark+2
|
|
ldy #fcr_buf_vp ;set up the pointer to the buffers
|
|
lda [fcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx <fcr_buf_ptr
|
|
sty <fcr_buf_ptr+2
|
|
;txa
|
|
|
|
lda class
|
|
beq @class0
|
|
@class1
|
|
ldy #read1.request_count
|
|
lda [param_blk_ptr],y
|
|
sta req_cnt
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta req_cnt+2
|
|
ldy #read1.data_buffer
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr+2
|
|
bra @fetch_done
|
|
@class0
|
|
ldy #read0.request_count
|
|
lda [param_blk_ptr],y
|
|
sta req_cnt
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta req_cnt+2
|
|
ldy #read0.data_buffer
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr+2
|
|
@fetch_done
|
|
check_mark ;must return error if mark = eof
|
|
lda mark
|
|
cmp eof
|
|
bne @not_equal
|
|
|
|
lda mark+2
|
|
cmp eof+2
|
|
bne @not_equal
|
|
|
|
lda #end_of_file
|
|
sta error
|
|
brl store_tcount ;return transfer count and exit
|
|
@not_equal
|
|
check_limits
|
|
;brk $A1
|
|
|
|
lda mark
|
|
clc
|
|
adc req_cnt
|
|
sta endmark
|
|
lda mark+2
|
|
adc req_cnt+2
|
|
bcs @too_big ;overflowed 32 bits!
|
|
sta endmark+2
|
|
cmp eof+2
|
|
bcc limit_ok
|
|
bne @too_big
|
|
@maybe
|
|
lda eof
|
|
cmp endmark
|
|
bcs limit_ok
|
|
@too_big
|
|
;lda #end_of_file
|
|
;sta error ;remember, it's non-fatal
|
|
lda eof+2
|
|
sta endmark+2
|
|
lda eof
|
|
sta endmark ;that's as far as we can go!
|
|
limit_ok
|
|
;now calculate needed scratch values
|
|
lda endmark
|
|
sec
|
|
sbc mark
|
|
sta bytes_left ;this is the maximum number of bytes left to transfer
|
|
lda endmark+2
|
|
sbc mark+2
|
|
sta bytes_left+2 ;this is the transfer count based on lesser of�
|
|
;�request count and (eof minus mark)
|
|
lda mark
|
|
clc
|
|
adc data_offset
|
|
sta phys_mark ;this is the "mark" for disk sectors
|
|
lda mark+2
|
|
adc #$0000
|
|
sta phys_mark+2
|
|
|
|
ldy #fcr_type
|
|
lda [fcr_ptr],y ;check for directory file
|
|
cmp #$000F
|
|
bne @normal
|
|
brl directory_file ;some weirdo wants to read the directory file
|
|
@normal
|
|
|
|
init_drvr ;initialize direct page driver vars
|
|
ldy #vcr_dev
|
|
lda [vcr_ptr],y ;where did we see the disk last?
|
|
sta <drvr_dev_num ;we'll trust this number for now
|
|
|
|
lda #drvr_read ;set up for reading sectors
|
|
sta <drvr_call_num
|
|
;now we have to locate the t/s list sector we need
|
|
|
|
find_sector ;this is the return point for the big sector loop
|
|
;bytes_sent, bytes_left, and phys_mark should be updated�
|
|
;�before iterating
|
|
|
|
;brk $49
|
|
|
|
lda phys_mark
|
|
xba
|
|
and #$00FF ;this is now low byte of sector num which contains mark
|
|
sta sec_num
|
|
lda phys_mark+2
|
|
xba
|
|
tax
|
|
and #$FF00
|
|
ora sec_num
|
|
sta sec_num
|
|
txa
|
|
and #$00FF
|
|
sta sec_num+2 ;this completes a 24-bit value for sec_num
|
|
|
|
;lda phys_mark
|
|
;ldy #$0000
|
|
check_ts
|
|
lda fcr_buf_ptr ;t/s list sectors go here
|
|
sta drvr_buf_ptr
|
|
lda fcr_buf_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
lda sec_num
|
|
ldy #ts_sec_offset
|
|
sec
|
|
sbc [fcr_buf_ptr],y ;do we have the right t/s list?
|
|
bcc start_over ;the one we have is too far, start from top
|
|
cmp #122 ;are we within the range of the one we want?
|
|
bcc have_ts ;if the difference is less than the capacity of a�
|
|
;�t/s list, then we have the right one
|
|
walk_ahead
|
|
ldy #ts_link
|
|
lda [fcr_buf_ptr],y
|
|
bne @ok1
|
|
lda #dir_error ;the linked list is bad
|
|
sec
|
|
rts
|
|
@ok1 jsr new_rwts ;go get that next t/s list sector
|
|
bra check_ts
|
|
start_over
|
|
ldy #fde_ts_link ;start from the first t/s list sector
|
|
lda [fde_ptr],y ;get the track/sector of first t/s list sector
|
|
jsr new_rwts
|
|
bcc @ok
|
|
rts ;return with driver error
|
|
@ok
|
|
bra check_ts
|
|
have_ts
|
|
;brk $43
|
|
;the accumulator contains the t/s entry offset number
|
|
asl a ;convert to word offset
|
|
adc #ts_list_start ;carry is clear
|
|
tay
|
|
lda [fcr_buf_ptr],y ;get the entry
|
|
bne @real ;if non-0 then it's a real sector
|
|
brl null_sect ;if the entry is zero, hopefully it's because we've hit�
|
|
;�a null portion of a sparse file
|
|
@real
|
|
sta data_sect ;save entry
|
|
ldy #fcr_data_sect
|
|
cmp [fcr_ptr],y ;is our sector already there?
|
|
beq xfer_data ;if it is, skip the driver call!
|
|
|
|
lda nl_msk ;is newline mode set?
|
|
bne double_buf ;if so, we have to bite the bullet on this one!
|
|
lda phys_mark
|
|
and #$00FF ;look at least sig byte
|
|
bne double_buf ;are we sector aligned?
|
|
lda bytes_left
|
|
cmp #$101
|
|
bcc double_buf ;if user gets partial sector, must double buffer
|
|
|
|
single_buf ;read the puppy right into the user's buffer!
|
|
lda user_ptr
|
|
sta drvr_buf_ptr
|
|
lda user_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
lda data_sect ;this was from the t/s list
|
|
jsr new_rwts
|
|
bcc @ok1
|
|
rts ;return with driver error
|
|
@ok1
|
|
lda #$0100
|
|
sta recent_xfer ;this is what we've transfered
|
|
brl next_sector ;we're done with this sector
|
|
double_buf
|
|
lda <fcr_buf_ptr
|
|
clc
|
|
adc #$100 ;second page of buffer is for data sectors
|
|
sta drvr_buf_ptr
|
|
lda <fcr_buf_ptr+2
|
|
adc #$0000
|
|
sta drvr_buf_ptr+2
|
|
lda data_sect
|
|
jsr new_rwts ;read in the sector
|
|
bcc @ok
|
|
rts ;return with driver error
|
|
@ok
|
|
ldy #fcr_data_sect
|
|
lda data_sect
|
|
sta [fcr_ptr],y ;make a record that we have this sector in the fcr buffer
|
|
xfer_data
|
|
lda phys_mark
|
|
and #$00FF ;this is the physical start position
|
|
sta sec_start ;save for later
|
|
ldy bytes_left+2
|
|
bne @rest_of_sec ;if this isn't 0, we're definitely going to the end of�
|
|
;�this sector
|
|
clc
|
|
adc bytes_left ;find physical end position
|
|
cmp #$0100+1 ;does it go past the end of the sector?
|
|
bcc @store
|
|
@rest_of_sec
|
|
lda #$0100
|
|
@store
|
|
sta sec_end ;the physical end position for this particular sector
|
|
sec
|
|
sbc sec_start ;now we have the number of bytes to be transfered�
|
|
;�from this sector
|
|
sta byte_cnt
|
|
|
|
lda sec_start ;get back least significant byte of start addr
|
|
clc
|
|
adc #$0100 ;bump to second page of fcr buffer
|
|
adc <fcr_buf_ptr
|
|
sta <src_scratch
|
|
lda <fcr_buf_ptr+2
|
|
adc #$0000
|
|
sta <src_scratch+2
|
|
|
|
ldx nl_msk
|
|
bne newline ;go do it the ugly way
|
|
|
|
;brk $47
|
|
|
|
lda byte_cnt ;this is the # of bytes to be moved from this sector
|
|
cmp #move_info_be ;check transfer value against the break-even point�
|
|
;�for using the move_info call
|
|
my_move
|
|
bcs use_mi
|
|
lsr a ;divide by 2
|
|
tax
|
|
bcc @even ;if no remainder, go move by word
|
|
|
|
;otherwise we transfer the odd byte
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
lda [src_scratch]
|
|
sta [user_ptr] ;that takes care of the blasted odd byte!
|
|
|
|
rep #%00100001 ;16-bit accum, carry clear
|
|
LONGA ON
|
|
inc src_scratch
|
|
bne @no_carry
|
|
inc src_scratch+2
|
|
@no_carry
|
|
inc user_ptr
|
|
bne @no_carry2
|
|
inc user_ptr+2
|
|
@no_carry2
|
|
@even
|
|
txa ;this is a word count
|
|
dea ;decrement effectively by 2 to point to the word
|
|
bmi @done
|
|
asl a
|
|
tay
|
|
@loop lda [src_scratch],y
|
|
sta [user_ptr],y
|
|
dey
|
|
dey
|
|
bpl @loop
|
|
@done ;transfer complete!
|
|
lda byte_cnt
|
|
sta recent_xfer ;the whole amount was transferred
|
|
lsr a ;did we increment user_ptr earlier?
|
|
bcc next_sector ;no, no need to fix it up...
|
|
lda user_ptr ;else we must decrement it once to account for
|
|
bne @1 ; the increment that we did above (for odd-size
|
|
dec user_ptr+2 ; move)
|
|
@1 dec user_ptr ;This ensures proper math when we update the pointer
|
|
bra next_sector ; at the end of the loop.
|
|
|
|
use_mi ;use move_info
|
|
pei src_scratch+2 ;high word of source pointer
|
|
pei src_scratch ;low word " " "
|
|
pei user_ptr+2 ;destination
|
|
pei user_ptr
|
|
pea $0000 ;high word of transfer count is always 0
|
|
lda byte_cnt
|
|
pha
|
|
pea move_sinc_dinc ;command word
|
|
jsl move_info
|
|
bcc @ok1
|
|
lda #$8000 ;internal generic error
|
|
rts
|
|
@ok1
|
|
lda byte_cnt
|
|
sta recent_xfer ;the whole amount was transferred
|
|
bra next_sector
|
|
newline
|
|
jsr read_newline
|
|
bcc next_sector ;we ran out of bytes, so get more
|
|
|
|
lda recent_xfer
|
|
clc
|
|
adc bytes_sent
|
|
sta bytes_sent
|
|
bcc @no_carry
|
|
inc bytes_sent+2
|
|
|
|
@no_carry clc ; all done, so compensate for the subtraction that
|
|
lda bytes_sent ; is performed during post_process for newline mode.
|
|
adc data_offset
|
|
sta bytes_sent
|
|
lda bytes_sent+2
|
|
adc #0
|
|
sta bytes_sent+2
|
|
|
|
brl post_process ;we hit a newline char, so return to caller
|
|
|
|
next_sector ;at this point, only recent_xfer should reflect what has been�
|
|
;�sent to the caller
|
|
lda recent_xfer
|
|
clc
|
|
adc bytes_sent
|
|
sta bytes_sent
|
|
bcc @no_carry
|
|
|
|
inc bytes_sent+2
|
|
@no_carry
|
|
lda bytes_left
|
|
sec
|
|
sbc recent_xfer
|
|
sta bytes_left
|
|
bcs @no_borrow
|
|
dec bytes_left+2
|
|
|
|
@no_borrow lda bytes_left ; done?
|
|
ora bytes_left+2
|
|
bne @1 ; maybe ->
|
|
|
|
clc ; all done, so compensate for the subtraction that
|
|
lda bytes_sent ; is performed during post_process for newline mode.
|
|
adc data_offset
|
|
sta bytes_sent
|
|
lda bytes_sent+2
|
|
adc #0
|
|
sta bytes_sent+2
|
|
brl post_process
|
|
|
|
; if in newline mode, then it will go negative when
|
|
; it is done, but only by the amount of data_offset...
|
|
@1 lda bytes_left ; check to see if there are any more bytes to xfer.
|
|
clc ; must add the data_offset or else the value may be
|
|
adc data_offset ; < 0.
|
|
sta @temp
|
|
lda bytes_left+2
|
|
adc #0
|
|
ora @temp
|
|
|
|
bne @more ;no more bytes left to transfer!
|
|
brl post_process
|
|
|
|
@temp dc.w 0
|
|
|
|
@more
|
|
lda recent_xfer
|
|
tax ;save for other calculations
|
|
clc
|
|
adc phys_mark ;update the physical mark
|
|
sta phys_mark
|
|
bcc @no_carry1
|
|
inc phys_mark+2
|
|
@no_carry1
|
|
txa ;get back recent_xfer
|
|
clc
|
|
adc user_ptr ;update user_ptr
|
|
sta user_ptr
|
|
bcc @no_carry3
|
|
inc user_ptr+2
|
|
@no_carry3
|
|
brl find_sector ;we're set to iterate
|
|
|
|
null_sect
|
|
lda nl_msk
|
|
beq @no_nl ;no newline if mask is 0
|
|
ldy nl_len
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
@loop dey
|
|
bmi @no_nl
|
|
lda [nl_list_ptr],y ;determine whether 0 is on the newline list
|
|
bne @loop ;fall through on a zero
|
|
|
|
sta [user_ptr] ;store the single zero in user's buffer
|
|
|
|
rep #%00110001 ;16-bit accum, carry clear
|
|
LONGA ON
|
|
inc bytes_sent
|
|
bne @no_carry
|
|
inc bytes_sent+2
|
|
@no_carry
|
|
lda bytes_left
|
|
sec
|
|
sbc #$0001
|
|
sta bytes_left
|
|
bcs @no_borrow
|
|
dec bytes_left+2
|
|
@no_borrow
|
|
brl post_process ;all done!
|
|
@no_nl
|
|
rep #%00110001 ;16-bit accum, carry clear
|
|
LONGA ON
|
|
|
|
lda phys_mark
|
|
and #$00FF ;this is the physical start position
|
|
sta sec_start ;save for later
|
|
ldy bytes_left+2
|
|
bne @rest_of_sec ;if this isn't 0, we're definitely going to the end of�
|
|
;�this sector
|
|
clc
|
|
adc bytes_left ;find physical end position
|
|
cmp #$0100+1 ;does it go past the end of the sector?
|
|
bcc @store
|
|
@rest_of_sec
|
|
lda #$0100
|
|
@store
|
|
sta sec_end ;the physical end position for this particular sector
|
|
sec
|
|
sbc sec_start ;now we have the number of bytes to be transfered�
|
|
;�from this sector
|
|
sta byte_cnt
|
|
lsr a ;divide by 2
|
|
tax
|
|
lda #$0000 ;null sectors contain zeros
|
|
bcc @even ;if no remainder, go move by word
|
|
|
|
sep #%00100000 ;work with bytes
|
|
LONGA OFF
|
|
sta [user_ptr] ;that takes care of the blasted odd byte!
|
|
|
|
rep #%00100001 ;16-bit accum, carry clear
|
|
LONGA ON
|
|
|
|
inc user_ptr
|
|
bne @no_carry2
|
|
inc user_ptr+2
|
|
@no_carry2
|
|
@even
|
|
txa ;this is a word count
|
|
dea ;decrement effectively by 2
|
|
bmi @done
|
|
asl a ;make it a byte value again
|
|
tay
|
|
lda #$0000
|
|
@loop1
|
|
sta [user_ptr],y
|
|
dey
|
|
dey
|
|
bpl @loop1
|
|
@done
|
|
lda byte_cnt
|
|
sta recent_xfer ;the whole amount was transferred
|
|
brl next_sector
|
|
|
|
directory_file ;read stuff from the directory file
|
|
lda nl_msk ;is newline mode set?
|
|
beq dir_no_nl ;if not, just shove the bytes over
|
|
@newline
|
|
lda bytes_left
|
|
sta byte_cnt ;only one word should be non-zero
|
|
stz byte_cnt+2
|
|
|
|
lda mark
|
|
clc
|
|
adc fcr_buf_ptr
|
|
sta src_scratch
|
|
lda mark+2
|
|
adc fcr_buf_ptr+2
|
|
sta src_scratch+2
|
|
|
|
jsr read_newline
|
|
lda recent_xfer
|
|
sta bytes_sent
|
|
stz bytes_sent+2 ;high word is always 0
|
|
bra post_process ;that's all there is to it!
|
|
|
|
dir_no_nl
|
|
lda mark ;get back least significant word of start addr
|
|
clc
|
|
adc fcr_buf_ptr
|
|
tax
|
|
lda mark+2
|
|
adc fcr_buf_ptr+2
|
|
pha ;high word of source pointer
|
|
phx ;low word " " "
|
|
pei user_ptr+2
|
|
pei user_ptr
|
|
pea $0000 ;high word of transfer count is always 0
|
|
lda bytes_left
|
|
pha
|
|
pea move_sinc_dinc ;command word
|
|
jsl move_info
|
|
bcc @ok1
|
|
lda #$8000 ;internal generic error
|
|
rts
|
|
@ok1
|
|
lda bytes_left
|
|
sta bytes_sent ;the whole amount was transferred
|
|
lda bytes_left+2
|
|
sta bytes_sent+2
|
|
;brl post_process
|
|
bra pack_up ; don't strip high bits on directory data ->
|
|
|
|
post_process sec ; subtract the data_offset from the amount
|
|
lda bytes_sent ; actually transferred.
|
|
sbc data_offset
|
|
sta bytes_sent
|
|
lda bytes_sent+2
|
|
sbc #0
|
|
sta bytes_sent+2
|
|
;clear high bit of each byte sent, if specified by mode
|
|
ldy #fcr_dos_type
|
|
lda [fcr_ptr],y ;get the DOS 3.3 filetype
|
|
bne pack_up ;if NOT 0 (TEXT file) don't touch the data
|
|
@text
|
|
lda text_flag ;this global flag decides the text transfer mode
|
|
beq pack_up ;if flag = 0, leave text as-is
|
|
|
|
;bra pack_up ;shunt-out this code for the time being
|
|
|
|
lda class
|
|
beq @class0
|
|
@class1
|
|
ldy #read1.data_buffer
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr+2
|
|
bra @clear_bit
|
|
@class0
|
|
ldy #read0.data_buffer
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta <user_ptr+2
|
|
@clear_bit
|
|
ldy bytes_sent+2
|
|
iny ;adjust for countdown
|
|
ldx bytes_sent
|
|
bne @not_0
|
|
|
|
dey ;account for low part = 0
|
|
|
|
txa
|
|
ora bytes_sent+2 ;are they both zero?
|
|
beq @done
|
|
@not_0
|
|
sty <clear_ctr ;this is the high part of the counter
|
|
|
|
ldy #0 ;init index
|
|
|
|
sep #$20
|
|
LONGA OFF
|
|
@loop
|
|
lda [user_ptr],y
|
|
and #$7F ;clear that archaic high bit
|
|
sta [user_ptr],y ;put it back
|
|
|
|
iny ;bump ptr
|
|
bne @no_carry1
|
|
|
|
inc <user_ptr+2 ;bump high part of pointer
|
|
@no_carry1
|
|
dex ;low part of counter
|
|
bne @loop
|
|
|
|
dec <clear_ctr ;high part of counter
|
|
bne @loop
|
|
@done
|
|
rep #$20
|
|
LONGA ON
|
|
pack_up ;square away all the values for the user param block before�
|
|
;�returning
|
|
;bytes_sent should reflect the total amount transfered during�
|
|
;�the entire call
|
|
ldy #fcr_mark
|
|
lda [fcr_ptr],y
|
|
clc
|
|
adc bytes_sent
|
|
sta [fcr_ptr],y ;update the file's mark
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y
|
|
adc bytes_sent+2
|
|
sta [fcr_ptr],y
|
|
store_tcount
|
|
lda class
|
|
bne @class1
|
|
@class0
|
|
ldy #read0.transfer_count
|
|
bra exit
|
|
|
|
@class1
|
|
ldy #read1.transfer_count
|
|
exit
|
|
lda bytes_sent
|
|
sta [param_blk_ptr],y
|
|
lda bytes_sent+2
|
|
iny
|
|
iny
|
|
sta [param_blk_ptr],y
|
|
|
|
lda error ;there may be a non-fatal error here
|
|
cmp #$0001 ;set carry to appropriate sign
|
|
rts
|
|
|
|
error ds 1
|
|
|
|
ENDP
|
|
|
|
export check_access
|
|
|
|
; check_access checks to see if the parameter block is specifying
|
|
; an invalid access for the open call. The things that it checks
|
|
; for are:
|
|
;
|
|
; Are we trying to open the resource fork of a file.
|
|
; Are we trying to open the file other than read only.
|
|
;
|
|
; If so it returns with the carry set and the accumulator set to the
|
|
; appropriate error. We do this here, instead of in the open_s routine
|
|
; because these are non_bouncing errors and we need to check this after
|
|
; we have determined that the target is a DOS file.
|
|
|
|
check_access PROCNAME
|
|
|
|
lda class ;get the class of the call
|
|
beq @done ;if class 0, no resource fork
|
|
|
|
lda p_cnt
|
|
cmp #4 ;enough parameters for request_access?
|
|
bcc @done ;no, can't check it
|
|
|
|
clc
|
|
ldy #open1.request_access
|
|
lda [param_blk_ptr],y ;get the request access word
|
|
and #%0000000000000010 ;check for write access
|
|
beq @checkRez ;no write access
|
|
|
|
lda #invalid_access
|
|
bra @access_err
|
|
@checkRez
|
|
lda p_cnt
|
|
cmp #5
|
|
bcc @done ; pcount too small ->
|
|
|
|
clc
|
|
ldy #open1.resource_number
|
|
lda [<param_blk_ptr],y
|
|
beq @done ; ok -> its not the resource fork
|
|
|
|
cmp #1 ; == to 1
|
|
beq @fork_err ; can't open resource fork
|
|
|
|
lda #parm_range_err ; bad value for ressource_number
|
|
bra @access_err
|
|
|
|
@fork_err
|
|
lda #res_not_found
|
|
@access_err
|
|
sec
|
|
@done
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
export open
|
|
open PROCNAME ;handle the OPEN call
|
|
|
|
;brk $49
|
|
|
|
stz vcr_fcr_flags ;init flags
|
|
|
|
jsr open_setup ;init vars, set up buffers, put volume name in�
|
|
;�volname_buf_ptr, verify that volume is�
|
|
;�online, mount the volume
|
|
bcc @ok
|
|
brl err_exit ;deallocate stuff on the way out
|
|
@ok
|
|
|
|
|
|
; we now have a valid vcr for the volume we want
|
|
|
|
; now see exactly what we're supposed to open
|
|
|
|
|
|
@process_file
|
|
;we now have a legal filename and a vcr
|
|
;now look for fcrs unless we just created the vcr
|
|
|
|
;brk $07
|
|
|
|
lda (file_name_ptr) ;was there a filename?
|
|
beq handle_vol
|
|
brl handle_file
|
|
|
|
handle_vol ;this section opens the volume "root" directory file
|
|
;first build string of vol name with leading colon
|
|
; but first check to see if for some reason the caller
|
|
;has specified the resource fork as the target or is trying
|
|
;to open this vol readWrite.
|
|
|
|
jsr check_access
|
|
bcc @h_vol ; nope! everythings OK here
|
|
brl err_exit ;deallocate stuff on the way out
|
|
@h_vol
|
|
lda vol_name_buf ;get length
|
|
inc a ;account for colon character
|
|
sta scratch_str_buf
|
|
|
|
sep #$20
|
|
LONGA OFF
|
|
|
|
lda #':'
|
|
ldy #2
|
|
sta scratch_str_buf,y ;place the colon
|
|
|
|
@loop
|
|
lda vol_name_buf,y
|
|
cmp #1 ;save zero status in carry
|
|
iny ;position one byte over in dest string
|
|
sta scratch_str_buf,y
|
|
bcs @loop ;if character was non-zero, loop
|
|
|
|
rep #$20
|
|
LONGA ON
|
|
|
|
ldx #<scratch_str_buf
|
|
ldy #^scratch_str_buf
|
|
lda #fcr_size
|
|
jsl alloc_fcr
|
|
bcc @ok
|
|
|
|
brl err_exit ;can't get FCR
|
|
@ok
|
|
jsl deref
|
|
stx fcr_ptr
|
|
sty fcr_ptr+2
|
|
|
|
lda #$4000
|
|
tsb vcr_fcr_flags ;set flag to say we allocated an FCR
|
|
|
|
;special fcr setup for root directory file
|
|
ldy #fcr_fst_id
|
|
lda #my_id
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #vcr_id
|
|
lda [vcr_ptr],y
|
|
ldy #fcr_vcr_id
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #vcr_buf_vp
|
|
lda [vcr_ptr],y ;the fcr has the same buffer as the vcr
|
|
tax
|
|
iny
|
|
iny
|
|
lda [vcr_ptr],y ;high word
|
|
ldy #fcr_buf_vp+2
|
|
sta [fcr_ptr],y
|
|
txa
|
|
dey
|
|
dey
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #fcr_mark ;zero the mark
|
|
lda #$0000
|
|
sta [fcr_ptr],y
|
|
iny
|
|
iny
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #fcr_eof+2
|
|
sta [fcr_ptr],y ;zero high word of eof
|
|
|
|
ldy #fcr_aux
|
|
sta [fcr_ptr],y ;zero aux_type
|
|
iny
|
|
iny
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #fcr_entry_num
|
|
sta [fcr_ptr],y ;zero the entry position for get_dir_entry
|
|
|
|
ldy #fcr_blks_used+2 ;set blocks used
|
|
sta [fcr_ptr],y ;zero high word
|
|
dey
|
|
dey
|
|
sta [fcr_ptr],y ;low word of blocks used
|
|
|
|
xba ;transform to byte value for EOF
|
|
ldy #fcr_eof
|
|
sta [fcr_ptr],y ;that's our EOF!
|
|
|
|
ldy #fcr_type
|
|
lda #$000F ;GS/OS directory file
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #fcr_access
|
|
lda #access_unlocked
|
|
sta [fcr_ptr],y
|
|
|
|
count_dir ;count entries in the directory
|
|
stz dir_cnt
|
|
lda #$0000 ;cat sector numbers start at 0
|
|
@cat_loop
|
|
ldx #$0000 ;same for fde's
|
|
@fde_loop
|
|
sta cat_index
|
|
stx fde_index ;save these
|
|
jsr find_fde
|
|
bcc @ok
|
|
brl err_exit ;error
|
|
@ok
|
|
*** changed 6-May-93 DAL
|
|
;;; lda [fde_ptr] ;first byte tells whether in use
|
|
;;; and #$00FF
|
|
jsr load_fde_flag
|
|
*** 6-May-93
|
|
beq @done ;a $00 means beyond last entry
|
|
cmp #$00FF
|
|
beq @inactive ;inactive, don't count it
|
|
inc dir_cnt
|
|
@inactive
|
|
ldx fde_index
|
|
lda cat_index
|
|
inx ;next fde
|
|
cpx #$0007 ;check limit of 7 fde's per cat sector
|
|
bcc @fde_loop ;we're ok, check next fde
|
|
ina ;next catalog sector
|
|
cmp cat_sec_count ;past our limit?
|
|
bcc @cat_loop ;move on to next cat sector
|
|
@done
|
|
lda dir_cnt
|
|
ldy #fcr_tot_ent
|
|
sta [fcr_ptr],y ;save this for get_dir_entry
|
|
|
|
ldy #vcr_open_cnt
|
|
lda [vcr_ptr],y
|
|
inc a
|
|
bne @not_first ;if it was $FFFF, increment it again
|
|
inc a
|
|
@not_first
|
|
sta [vcr_ptr],y
|
|
brl stuff_usr_prm_blk
|
|
|
|
handle_file
|
|
;brk $02
|
|
; ldy #vcr_open_cnt
|
|
; lda [vcr_ptr],y ;see if any files are already open in this vcr
|
|
; beq chk_dir ;if no open files, we'll have to look in the directory
|
|
;
|
|
; inc a ;this field is inited to $FFFF
|
|
; beq chk_dir ;check for $FFFF also
|
|
;
|
|
; jsr search_fcr ;this routine will return number of fcr for previous�
|
|
; ;�open of the file in old_fcr (0 means none found)
|
|
; bcc req_fcr ;we're ready to get a new fcr
|
|
|
|
chk_dir ;does this guy exist in the directory?
|
|
jsr check_dir ;this sub checks for filename in file_name_ptr
|
|
bcc @ok
|
|
|
|
lda #dir_error ;problem with the directory structure
|
|
brl err_exit
|
|
@ok
|
|
lda fde_index ;if negative, we didn't find the file
|
|
bpl req_fcr
|
|
|
|
file_not_here ;file not on this volume
|
|
lda #file_not_found
|
|
brl err_exit
|
|
|
|
;now we have to allocate a new fcr
|
|
;but first lets check to see what fork the caller is trying to open
|
|
|
|
req_fcr jsr check_access ;test for invalid operation
|
|
bcc @not_Rez ;if not resource fork
|
|
brl err_exit ;cleanup and return the appropriate error.
|
|
@not_Rez
|
|
;first build string of vol name with leading colon
|
|
lda vol_name_buf ;get length
|
|
inc a ;account for colon character
|
|
sta scratch_str_buf
|
|
|
|
sep #$20
|
|
LONGA OFF
|
|
|
|
lda #':'
|
|
ldy #2
|
|
sta scratch_str_buf,y ;place the colon
|
|
|
|
@loop
|
|
lda vol_name_buf,y
|
|
cmp #1 ;save zero status in carry
|
|
iny ;position one byte over in dest string
|
|
sta scratch_str_buf,y
|
|
bcs @loop ;if character was non-zero, loop
|
|
|
|
rep #$20
|
|
LONGA ON
|
|
|
|
ldx #<scratch_str_buf ;alloc_fcr now gets volume name
|
|
ldy #^scratch_str_buf
|
|
lda #fcr_size
|
|
jsl alloc_fcr
|
|
bcc @ok1
|
|
|
|
lda #out_of_mem ;can't get an fcr
|
|
brl err_exit
|
|
@ok1 ;SCM has successfully allocated the FCR
|
|
jsl deref
|
|
stx <fcr_ptr
|
|
sty <fcr_ptr+2
|
|
|
|
lda #$4000
|
|
tsb vcr_fcr_flags ;set flag to say we allocated an FCR
|
|
|
|
lda #file_buf_size ;request segments for file buffers
|
|
jsl alloc_seg
|
|
bcc @ok2
|
|
;can't get needed buffers, cancel the OPEN
|
|
lda #out_of_mem
|
|
brl err_exit
|
|
@ok2
|
|
tya ;stash the vp's in the fcr
|
|
ldy #fcr_buf_vp+2
|
|
sta [fcr_ptr],y
|
|
txa
|
|
dey
|
|
dey
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #vcr_open_cnt ;bump the open count in the vcr
|
|
lda [vcr_ptr],y
|
|
inc a
|
|
bne @not_first ;this field is inited to $FFFF
|
|
inc a
|
|
@not_first
|
|
sta [vcr_ptr],y
|
|
reset_mark
|
|
lda #$0000
|
|
ldy #fcr_mark ;offset to mark in fcr
|
|
sta [fcr_ptr],y
|
|
iny
|
|
iny
|
|
sta [fcr_ptr],y
|
|
|
|
; lda old_fcr ;what was the result of the fcr dup search?
|
|
; beq fill_new_fcr ;first open for this file
|
|
|
|
; brl copy_fcr ;let's not reinvent this wheel
|
|
|
|
fill_new_fcr
|
|
ldy #fcr_fde_num ;index to fde number of the file
|
|
lda fde_index
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #fcr_cat_sec ;sector where file's directory entry lives
|
|
lda cat_index
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #fcr_fst_id ;FST ID number
|
|
lda #my_id
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #vcr_id ;link to VCR
|
|
lda [vcr_ptr],y
|
|
ldy #fcr_vcr_id
|
|
sta [fcr_ptr],y
|
|
|
|
ldy #fde_type ;DOS 3.3 filetype
|
|
lda [fde_ptr],y
|
|
and #$007F ;mask high byte & lock bit
|
|
ldy #fcr_dos_type
|
|
sta [fcr_ptr],y
|
|
|
|
bra get_info ;now get info for param block
|
|
|
|
copy_fcr ;copy appropriate stuff from old to new fcr
|
|
|
|
;brk $31
|
|
|
|
stz copy_fcr_ctr
|
|
ldy #0 ;init index
|
|
@big_loop
|
|
lda copy_fcr_ctr ;get counter of number of bitmapped words
|
|
lsr a
|
|
tax
|
|
lda copy_tbl,x ;get bitmapped word
|
|
sta copy_fcr_temp
|
|
|
|
ldx #16 ;init counter
|
|
@loop
|
|
asl copy_fcr_temp
|
|
bcc @no_copy
|
|
|
|
lda [old_fcr_ptr],y
|
|
sta [fcr_ptr],y
|
|
@no_copy
|
|
iny
|
|
iny ;bump index by a word
|
|
|
|
dex ;decrement counter
|
|
bne @loop ;repeat for each bit
|
|
|
|
lda copy_fcr_ctr
|
|
bne @done ;if not 0, we're done (loop executes twice)
|
|
|
|
inc copy_fcr_ctr
|
|
bra @big_loop
|
|
@done
|
|
bra stuff_usr_prm_blk
|
|
|
|
get_info ;call get_file_info
|
|
;brk $01
|
|
|
|
ldy #fcr_buf_vp ;get the vp to the fcr's buffer
|
|
lda [fcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [fcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx <drvr_buf_ptr
|
|
stx <fcr_buf_ptr
|
|
sty <drvr_buf_ptr+2
|
|
sty <fcr_buf_ptr+2
|
|
;hopefully, the device number will be left over from
|
|
;the "volume" routine
|
|
lda #drvr_read
|
|
sta <drvr_call_num
|
|
|
|
ldy #fcr_fde_num
|
|
lda [fcr_ptr],y ;need these to set up ptr to fde
|
|
tax
|
|
ldy #fcr_cat_sec
|
|
lda [fcr_ptr],y
|
|
jsr find_fde ;this sets up fde_ptr
|
|
|
|
jsr get_file_info ;get all the good stuff
|
|
bcc @ok1
|
|
|
|
brl err_exit
|
|
@ok1 ;now copy from globals to the fcr
|
|
ldy #fcr_data_sect
|
|
lda last_data_sec
|
|
sta [fcr_ptr],y ;make note of number of sector in buffer
|
|
|
|
ldy #fcr_access
|
|
lda access
|
|
sta [fcr_ptr],y
|
|
ldy #fcr_eof
|
|
lda eof
|
|
sta [fcr_ptr],y
|
|
lda eof+2
|
|
iny
|
|
iny
|
|
sta [fcr_ptr],y
|
|
ldy #fcr_aux
|
|
lda aux_type
|
|
sta [fcr_ptr],y
|
|
ldy #fcr_type
|
|
lda os_type
|
|
sta [fcr_ptr],y
|
|
ldy #fcr_blks_used
|
|
lda blks_used
|
|
sta [fcr_ptr],y
|
|
lda #$0000
|
|
iny
|
|
iny
|
|
sta [fcr_ptr],y ;zero long word of blks_used
|
|
|
|
stuff_usr_prm_blk ;fill everything the user asked for
|
|
|
|
;brk $44
|
|
|
|
lda class ;get the class of the call
|
|
bne @class1
|
|
brl @class0
|
|
@class1
|
|
lda p_cnt
|
|
tax ;keep countdown in x
|
|
|
|
ldy #$0000-2 ;init Y for index to table in loop
|
|
@cpy_loop
|
|
iny
|
|
iny ;move to next word entry
|
|
lda fcr_to_pblk,y ;get the table entry
|
|
asl a ;test 2 highest bits
|
|
bcc @no_dec ;should we decrement pcount?
|
|
dex
|
|
bmi @special ;if we hit bottom, go on to the special cases
|
|
@no_dec
|
|
asl a ;test next bit
|
|
bcs @cpy_loop ;if original bit 14 was set, don't copy
|
|
lsr a
|
|
lsr a ;shift things back into place
|
|
phy ;save the present index
|
|
tay
|
|
lda [fcr_ptr],y
|
|
ply
|
|
sta [param_blk_ptr],y
|
|
bra @cpy_loop
|
|
@special ;handle special case parameters
|
|
ldx p_cnt
|
|
cpx #8 ;do we need aux_type?
|
|
bcc @done
|
|
|
|
ldy #open1.aux_type+2
|
|
lda #$0000
|
|
sta [param_blk_ptr],y ;zero the high word of aux_type
|
|
|
|
cpx #9 ;need storage type?
|
|
bcc @done
|
|
|
|
ldy #fcr_type
|
|
lda [fcr_ptr],y
|
|
cmp #$000F ;root directory?
|
|
beq @store_s_type ;filetype happens to equal storage type
|
|
|
|
lda #storage_type ;for regular files
|
|
@store_s_type
|
|
ldy #open1.storage_type
|
|
sta [param_blk_ptr],y
|
|
|
|
cpx #10
|
|
bcc @done
|
|
|
|
lda #$0000
|
|
ldy #open1.create_date_time
|
|
sta [param_blk_ptr],y
|
|
iny
|
|
iny
|
|
sta [param_blk_ptr],y
|
|
iny
|
|
iny
|
|
sta [param_blk_ptr],y
|
|
iny
|
|
iny
|
|
sta [param_blk_ptr],y
|
|
cpx #11
|
|
bcc @done
|
|
|
|
ldy #open1.mod_date_time
|
|
sta [param_blk_ptr],y
|
|
iny
|
|
iny
|
|
sta [param_blk_ptr],y
|
|
iny
|
|
iny
|
|
sta [param_blk_ptr],y
|
|
iny
|
|
iny
|
|
sta [param_blk_ptr],y
|
|
|
|
cpx #12
|
|
bcc @done
|
|
|
|
ldy #open1.option_list
|
|
jsr do_option_list ;this routine needs offset in param blk in Y
|
|
bcc @done
|
|
|
|
lda #buff_too_small
|
|
bra err_exit
|
|
@class0
|
|
ldy #fcr_ref_num
|
|
lda [fcr_ptr],y ;get ref num from FCR
|
|
ldy #open0.ref_num
|
|
sta [param_blk_ptr],y ;set reference number
|
|
@done
|
|
; Added zeroing of res eof
|
|
; -- Monte Benaresh 2/19/92 for 6.0.1
|
|
|
|
lda p_cnt ; res eof included?
|
|
cmp #$0E
|
|
bcc @d1 ; no ->
|
|
|
|
ldy #open1.resource_eof
|
|
lda #0
|
|
sta [<param_blk_ptr],y
|
|
iny
|
|
iny
|
|
sta [<param_blk_ptr],y
|
|
|
|
lda p_cnt ; res blocks included?
|
|
cmp #$0f
|
|
bcc @d1 ; no ->
|
|
|
|
ldy #open1.resource_blocks
|
|
lda #0
|
|
sta [<param_blk_ptr],y
|
|
iny
|
|
iny
|
|
sta [<param_blk_ptr],y
|
|
|
|
@d1 clc
|
|
lda #$0000
|
|
rts ;all done with open!
|
|
|
|
err_exit ;if an error occurs, return through here
|
|
|
|
;brk $91
|
|
|
|
pha ;save error code
|
|
|
|
|
|
bit vcr_fcr_flags ;that's the first time I've used this instruction!
|
|
php ;save result for VCR test below
|
|
bvc @no_fcr
|
|
@cancel_fcr
|
|
ldy #fcr_type
|
|
lda [fcr_ptr],y
|
|
cmp #$000F ;is it a directory?
|
|
beq @not_dir ;if directory file then don't release its buffer�
|
|
;�because it is shared with the VCR
|
|
ldy #fcr_buf_vp
|
|
lda [fcr_ptr],y ;get fcr buffer's vp so we can release it
|
|
tax
|
|
iny
|
|
iny
|
|
ora [fcr_ptr],y ;check for 0 vp
|
|
beq @invalid_vp
|
|
|
|
lda [fcr_ptr],y
|
|
tay
|
|
jsl release_seg
|
|
@not_dir
|
|
@invalid_vp
|
|
ldy #fcr_ref_num
|
|
lda [fcr_ptr],y ;get ref num
|
|
jsl release_fcr ;get rid of the FCR
|
|
|
|
ldy #vcr_open_cnt
|
|
lda [vcr_ptr],y
|
|
beq @open_cnt_ok ;if open count is 0, leave it alone
|
|
|
|
inc a ;check for $FFFF
|
|
beq @store_open_cnt ;change $FFFF to 0
|
|
@dec_open_cnt
|
|
dec a ;reverse inc
|
|
dec a ;now decrement
|
|
@store_open_cnt
|
|
sta [vcr_ptr],y ;Y reg should point to vcr_open_cnt
|
|
@open_cnt_ok
|
|
@no_fcr
|
|
plp ;restore result of bit instruction above
|
|
bpl @no_vcr ;high bit tells whether VCR was allocated
|
|
@cancel_vcr
|
|
ldy #vcr_open_cnt
|
|
lda #$0000
|
|
sta [vcr_ptr],y ;must zero the open count to release it!
|
|
|
|
ldy #vcr_id
|
|
lda [vcr_ptr],y ;get ID of the VCR
|
|
jsl release_vcr ;this invokes sys_remove_vol call to this fst
|
|
@no_vcr
|
|
pla ;restore error code
|
|
sec
|
|
rts
|
|
|
|
copy_tbl ;defines which words get copied into the new fcr for a multiply-opened
|
|
;file. A 0 entry indicates that the word does NOT get copied.
|
|
|
|
;dc.w %0001100000100111
|
|
; |
|
|
; first word in fcr
|
|
|
|
; last word in fcr
|
|
; |
|
|
;dc.w %0011111100000000
|
|
|
|
copy equ $1
|
|
no_copy equ 0
|
|
|
|
; ***** NOTE ***** The presence of comments after the line continuation *****
|
|
; character (\) is NOT officially supported by the MAX
|
|
; assembler but works fine for version 1.1d9.
|
|
|
|
; If errors are generated for these lines by a later
|
|
; version of the assembler, remove all text between the
|
|
; **************** '\' and the carriage return. | *****
|
|
; |
|
|
; |
|
|
; bit position field |
|
|
; ------------ ----- |
|
|
dc.w 0 ++ \ �
|
|
no_copy << 0 ++ \ fcr_ref_num
|
|
no_copy << 1 ++ \ fcr_path_name
|
|
no_copy << 2 ++ \ fcr_path_name (h)
|
|
copy << 3 ++ \ fcr_fst_id
|
|
copy << 4 ++ \ fcr_vcr_id (h)
|
|
no_copy << 5 ++ \ fcr_level
|
|
no_copy << 6 ++ \ fcr_newline
|
|
no_copy << 7 ++ \ fcr_newline (h)
|
|
no_copy << 8 ++ \ fcr_newline_len
|
|
no_copy << 9 ++ \ fcr_mask
|
|
copy << 10 ++ \ fcr_access
|
|
no_copy << 11 ++ \ fcr_buf_vp
|
|
no_copy << 12 ++ \ fcr_buf_vp (h)
|
|
copy << 13 ++ \ fcr_eof
|
|
copy << 14 ++ \ fcr_eof (h)
|
|
copy << 15 ; fcr_aux
|
|
|
|
dc.w 0 ++ \
|
|
no_copy << 0 ++ \ fcr_mark
|
|
no_copy << 1 ++ \ fcr_mark (h)
|
|
copy << 2 ++ \ fcr_type
|
|
copy << 3 ++ \ fcr_dos_type
|
|
copy << 4 ++ \ fcr_blks_used
|
|
copy << 5 ++ \ fcr_blks_used (h)
|
|
copy << 6 ++ \ fcr_cat_sec
|
|
copy << 7 ++ \ fcr_fde_num
|
|
no_copy << 8 ; fcr_data_sec
|
|
|
|
|
|
; These words were derived from this table:
|
|
|
|
;@copy equ $1
|
|
;@no_copy equ 0
|
|
|
|
|
|
; dc.w @no_copy ;fcr_ref_num
|
|
; dc.l @no_copy ;fcr_path_name
|
|
; dc.w @copy ;fcr_fst_id
|
|
; dc.w @copy ;fcr_vcr_id
|
|
; dc.w @no_copy ;fcr_level
|
|
; dc.l @no_copy ;fcr_newline
|
|
; dc.w @no_copy ;fcr_newline_len
|
|
; dc.w @no_copy ;fcr_mask
|
|
; dc.w @copy ;fcr_access
|
|
; ;fst-specific:
|
|
; dc.l @no_copy ;fcr_buf_vp
|
|
; dc.l @copy ;fcr_eof
|
|
; dc.w @copy ;fcr_aux
|
|
; dc.l @no_copy ;fcr_mark
|
|
; dc.w @copy ;fcr_type
|
|
; dc.w @copy ;fcr_dos_type
|
|
; dc.l @copy ;fcr_blks_used
|
|
; dc.w @copy ;fcr_cat_sec
|
|
; dc.w @copy ;fcr_fde_num
|
|
; dc.w @no_copy ;fcr_data_sec
|
|
|
|
|
|
fcr_to_pblk ;table to specify what data to copy from the fcr to the user
|
|
;parameter block. each position corresponds to the same position
|
|
;in the user parameter block.
|
|
;each word entry contains:
|
|
; bit 15 = decrement pcount--high for the 1st word in each parameter
|
|
; bit 14 = copy inhibit--if high, nothing gets copied for this word position
|
|
@no_copy equ %0100000000000000
|
|
@dec equ %1000000000000000
|
|
|
|
; dc.w @no_copy ++ @dec ;pcount
|
|
dc.w @no_copy ;pcount <CAF> removed the @dec because pcount is not an actual parm.
|
|
dc.w fcr_ref_num ++ @dec ;ref_num
|
|
dc.w @no_copy ++ @dec ;pathname (low)
|
|
dc.w @no_copy ;pathname (high)
|
|
dc.w @no_copy ++ @dec ;request access
|
|
dc.w @no_copy ++ @dec ;resource number
|
|
dc.w fcr_access ++ @dec ;access
|
|
dc.w fcr_type ++ @dec ;file_type
|
|
dc.w fcr_aux ++ @dec ;aux_type (low)
|
|
dc.w @no_copy ;aux_type (high)
|
|
dc.w @no_copy ++ @dec ;storage_type
|
|
dc.w @no_copy ++ @dec ;create_date_time (0)
|
|
dc.w @no_copy ;create_date_time (1)
|
|
dc.w @no_copy ;create_date_time (2)
|
|
dc.w @no_copy ;create_date_time (3)
|
|
dc.w @no_copy ++ @dec ;mod_date_time (0)
|
|
dc.w @no_copy ;mod_date_time (1)
|
|
dc.w @no_copy ;mod_date_time (2)
|
|
dc.w @no_copy ;mod_date_time (3)
|
|
dc.w @no_copy ++ @dec ;option_list (low)
|
|
dc.w @no_copy ;option_list (high)
|
|
dc.w fcr_eof ++ @dec ;eof (low)
|
|
dc.w fcr_eof+2 ;eof (high)
|
|
dc.w fcr_blks_used ++ @dec ;blocks_used (low)
|
|
dc.w @no_copy+2 ;blocks_used (high)
|
|
dc.w @no_copy ++ @dec ;resource_eof (low)
|
|
;no entry resource_eof (high)
|
|
dc.w @no_copy ++ @dec ;resource_blocks (low)
|
|
;no entry resource_blocks (high)
|
|
*** added 7-Nov-92 DAL to fix run-off-the-end-of-the-table problem
|
|
dc.w @no_copy++@dec
|
|
*** end 7-Nov-92
|
|
|
|
copy_fcr_temp ds.w 1
|
|
copy_fcr_ctr ds.w 1
|
|
;vcr_fcr_flags ds.w 1 ;bit 15 = VCR allocated during this call
|
|
;bit 14 = FCR allocated during this call
|
|
;these flags are read if an error occurs during the OPEN call�
|
|
;�so that any allocated structures may be released on abort
|
|
|
|
|
|
ENDP
|
|
|
|
END
|