Files
Shawn Quick dfcaae62dd Add qlink, the disk tools, and a bootable ProDOS 8 image.
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.
2026-10-16 14:41:55 -07:00

1 line
281 KiB
Plaintext

print nohdr
*******************************************************************************
*
* GS/OS High Sierra File System Translator
*
* Version 03.00
* Written by Bryan Atsatt
*
* Thanks to Rob Turner for providing his ProDOS FST as a model
* and for letting me steal some of his routines!
*
* Copyright 1987-92 Apple Computer, Inc. All Rights Reserved.
*
*******************************************************************************
string asis
blanks off
pagesize 86
eject
*******************************************************************************
*
* REVISION HISTORY:
*
* Date By Description
*
* 2/1/88 BPA 00.01 a01 release.
* 2/3/88 BPA remove status call from setup_volume, changed polarity of
* disk switched bit in vcr_status.
* 2/8/88 BPA 00.02 a01 release.
* 2/16/88 BPA zero length strings converted to 'UNTITLED'. Removed reserved
* field checking from id_disk. Added vcr_device_id field to vcr
* and added support for non-CD-ROM devices to device_read.
* 2/26/88 BPA ISO support added, changed class 1 separator to colon.
* 2/29/88 BPA Forced directory bit of file_flags byte to 1 in find_file to
* fix problem found with Medline Knowledge Finder (ISO) disc.
* 00.03 a01 release.
* 3/16/88 BPA Changed device read to handle non-2k blocks by doing one 512
* byte block read. Changed id_disk so will only recognize 512
* and 2048 byte blocks.
* 3/18/88 BPA Fixed get_dir_entry so that if the search_assoc call changes
* the directory block in memory that the current_record is
* updated in the FCR.
* 3/21/88 BPA Fixed bug in make_gstring.
* 3/22/88 BPA Added status call to find_volume.
* 00.05 a01 release
* 3/23/88 BPA Removed status call from find_volume (!).
* 3/24/88 BPA Changed device_read to handle logical block sizes 512, 1024
* and 2048. SCSI.DRIVER changed so that CD-ROM default block
* size = 512.
* 3/28/88 BPA Changed setup_open_buf and build_fcr to force log_blk_size to
* 2k if file is a directory. Changed find_file to force
* log_blk_size to 2k. Changed decice_read to use trans_blk_size
* instead of log_blk_size. Changed all routines which update
* log_blk_size (except for setup_open_buf, build_fcr, and
* find_file) to update trans_blk_size as well. Fixed bug in
* get_name. Built device_dispatch to handle disk switched and
* offline errors.
* 3/29/88 BPA Changed setup_call to clear interleave_skip and interleave_size.
* Changed setup_open_buf to force log_blk_size only if file is
* claimed for get_dir_entry. Changed read_next_block and
* read_prev_block to handle differences betx log_blk_size and
* trans_blk_size.
* 3/30/88 BPA Added '.BAT' to default file type mapping table.
* 3/31/88 BPA File 'access' field returns full access ($C3) instead of read
* only ($01).
* 4/8/88 BPA Changed trans_blk_size to real_log_size. Changed to look for
* associated files before it's companion file. Changed
* get_dir_entry to skip associated file entries.
* 4/11/88 BPA Tested and fixed get_option_list.
* 4/18/88 BPA 00.05 a01 release
* 4/25/88 BPA Changed calc_open_block and changed set_end_block to use it.
* Changed get_dir_entry to handle zero length names.
* 00.06 a02 release
* 4/29/88 BPA Fixes for interleaved files.
* 5/2/88 BPA Additions for file and aux type handling of discs made using
* the GS/OS ISO 9660 Authoring Tool. Bug fixes.
* 00.07 a01 release
* 5/4/88 BPA Conversion to MPW.
* 5/31/88 BPA Enlarged string buffers to ensure that 37 character file names
* will fit. Fixed bugs in search_path_tbl and find_directory
* which assumed path table offsets and were wrong for ISO 9660.
* Changed find_dir_record so doesn't care if directory bit is set
* for entries whose name is 0 or 1.
* 6/6/88 BPA Changed h_file_sys_id to return iso_id for ISO 9660 volumes.
* Affects Volume and Get_Dir_Entry calls only.
* 6/30/88 BPA Added code to support the Apple Extensions to ISO 9660. Fixed
* bug in h_vol_name (was not checking for illegal length class 0
* names). Changed setup_call to save non-bouncing errors for
* calls that require pathnames; if process_path has no errors,
* and there is a saved error, it will return the saved error.
* 7/8/88 BPA Modified code to support Apple Extensions under High Sierra as
* well (added check_apple_ext and get_ext_type routines).
* 7/12/88 BPA Modified get_date_time to verify date/time and return default
* if illegal.
* 7/14/88 BPA Fixed get_date_time to handle zero date/time. Added code to do
* the ProDOS transformation on volume names. Fixed bug which
* caused duplicate volume error when ISO disk with open files
* is ejected and re-inserted by bumping the size of the date
* fields in the VCR by 1. Fixed blocks_used bug: log_blk_size
* set from vcr during calc_blocks.
* 7/21/88 BPA Added transform_gstring procedure, modified build_vcr to use it,
* changed find_volume so will not do transform.
* 7/22/88 BPA Changed apple_string to all uppercase.
* 7/26/88 BPA Fixed device_read so doesn't clear drvr_fst_num after it sets
* it to $000b. Fixed direct_read to set io_buffer = data_buffer.
* 7/27/88 BPA Modified get_dir_entry to return resource_eof and
* resource_blocks. Fixed get_option_list to handle 00 length
* option list buffer.
* 7/28/88 BPA Fixed filename transformation in find_volume to $2e5f. Changed
* search_dir from using log_blk_size to using constant
* sector_size. Changed find_file to force sector_size reads on
* read_next_block and to return file_not_found error if volume
* is High Sierra and resource_num is non-zero. Changed
* find_dir_record so never sets extended_flag if volume is High
* Sierra.
* 8/2/88 BPA Changed FST Attribute word in header so SCM will clear msb's
* in pathnames.
* 8/3/88 BPA Changed max_names to 9.
* 8/10/88 BPA Changed find_volume to look for invalid_dev_num instead of
* dev_not_found.
* 8/11/88 BPA Fixed bounce_errors list; was defined incorrectly. Updated
* version # in fst_header.
* 8/12/88 BPA Fixed find_volume so sets drvr_stat_code and then checks status
* word instead of vcr, and also undoes volume name transformation.
* Changed get_ext_type to handle padding field before signature.
* 8/16/88 BPA Changed version info to 2.0. Final!
* ------------
* 10/6/88 BPA Converted source so data is a record.
* 11/14/88 BPA Removed common equates from file and included them. Also
* reformatted source.
* 12/2/88 BPA v02.01d5 release.
* 1/11/89 BPA Cleared invisible bit of file flags in find file so that if
* call is get_file_info and file is a directory, the bit will not
* be set (fixes bug report RJHCAF237). Fixed calculation of
* open_buffer in setup_open_buf so uses byte size length from
* directory record instead of word (fixes BRC# 37728).
* 1/24/89 BPA Changed build_fcr so sets high bit of access word indicating
* that file is never modified.
* 2/15/89 BPA Changed build_fcr so when calls alloc_fcr uses pointer to full
* pathname rather than to filename.
* 2/17/89 BPA Changed build_fcr so when calls alloc_fcr uses pointer to
* volume name rather than full path, and so sets bit 14 of the
* fcr_access word if the file is the resource fork.
* 2/22/89 BPA Changed id_disk so if gets a drvr_bad_block error cuz volume is
* too small, will return unknown_vol err instead so will bounce.
* 2/23/89 BPA Changed get_file_type to ignore version # in file name (fixes
* CAF207LWA). Changed process_path to return res_not_found error
* instead of path_not_found error if resource_num is non-zero
* (fixes report CAF208LWA). Changed build_vcr so will toss a
* duplicate vcr if no open files even when it does not belong to
* me (fixes report CAF209LWA). Made a minor change to
* find_volume which MAY fix report CAF210LWA (I can't reproduce
* it but without the fix I can see how it could happen).
* 3/2/89 BPA Changed shutdown to respect warm_cold_flag and do nothing if
* warm shutdown. Changed get_option_list to return fst id and
* correctly handle small buffer conditions.
* 3/3/89 BPA Fixed get_option_list so if error and call is open, will
* release the fcr.
* 3/9/89 BPA Modified search_dir and find_file so will return path_not_found
* or file_not_found errors appropriately (fixes MJS246LWA).
* 3/10/89 BPA Modified find_directory to return a dir_error if directory has
* an XAR (fixes BRC 37350). Added support for version 2 of the
* Apple Extensions to ISO 9660.
* 4/6/89 BPA Fixed bug in get_option_list which caused data to be transfered
* when no XAR present, and fixed one which caused an end_of_dir
* error on the next get_dir_entry call after one which returned
* an XAR (XAR was read into open buffer instead of io_buffer).
* Added support for Apple Extensions on CD-ROM XA discs.
* 4/14/89 BPA Fixed process_path so will return res_not_found instead of
* file_not_found if looking for resource.
* 5/30/89 BPA Changed version number to 3.00 final.
* 6/6/89 BPA Fixed bug in search_dir which caused it to fail incorrectly in
* certain boundary conditions.
* 10/10/89 CAF Added check to id_disk which maps drvr_disk_sw error code to
* unknown_vol.
*
* Changes for System Disk 5.0.3
*
* 08/08/90 CAF device_dispatch now will re_try on a disk switched error always. It wasn't
* happening before during a volume call because no vcr was setup.
* 08/08/90 MSD Changed device_dispatch to retry the device access if the error
* was drvr_disk_sw and id_disk_flag is set. This is so drvr_disk_sw
* will not be returned from the Volume call, but will be returned
* during other calls (so that the FST can find out where the volume
* has moved to). It's ok to retry if all you want to do is find
* out which disk is there; it's not ok to retry otherwise.
* Thanks to Cheryl for pointing this out!!
*
* Changes for System Disk 6.0
*
* 2/07/91 CAE Added "support" for the JudgeName call.
* Enhancement - The Volume call will now setup the "vol_name"
* output parameter if a "dup_volume" error is being returned.
* 2/21/91 CAE Set bit 11 of the FST attributes word in the FST Header. This
* bit now indicates that the FST is read-only.
* Changed version number to 4.00 final.
* 3/05/91 CAE Added support for error priorities.
* 3/27/91 CAE Bug fix - The start_flags table contained an incorrect maximum
* pcount for SetFileInfo.
* 4/05/91 CAE Changed version number to 4.00 prototype.
* 12/05/91 GAB Change maximum allowable pCount for ChangePath.
* 12/18/91 MSD Moved checking of span1 from parse_path to process_path
* (after it sets the error priority bit) so it will find the
* volume first before checking the syntax. Added code to check
* volume name length (I'm assuming it must be less than 32).
* Changed version to 4.00 final.
*
* Changes for System Disk 6.0.1
*
* 25-Aug-92 DAL Changed version to 4.02 prototype.
* FSTSpecific map_enable and set_map_table now post volume-changed
* notifications for all of our online volumes.
*
* 2-Dec-92 DAL Changed VCR to have a Memory Manager handle to the path table,
* so we can allow path tables larger than 8K (the GS/OS Memory
* Manager limit). Handle is allocated when VCR is allocated.
* Handle is disposed when the VCR is released. To unlock the
* handle when it's not in use, the FST zeroes current_path_tbl_handle
* on the way way in and stores a path table handle there when a new
* one is allocated or an old one is dereferenced. On the way out,
* we unlock the handle stored in current_path_tbl_handle, if any.
* (When disposing a handle, we zero the variable if the handle being
* disposed is the same one stored, to avoid unlocking a handle we no
* longer own.) Instead of computing a path_table pointer by adding
* a constant to the vcr_ptr, we now dereference the vcr_path_tbl_handle
* field inside the vcr.
*
* Curiously, GS/OS Internal Snooper CDA has always displayed a 4-byte
* field for vcr_path_table, so no change is needed there. It used to
* display the first four bytes of the actual path table data.
*
* 2-Apr-93 SS Changed version to $0402 for 6.0.1 (final)
*
*******************************************************************************
eject
*******************************************************************************
*
* Forward addresses and entries
*
*******************************************************************************
entry fst_header
entry appl_call
entry system_call
entry startup
entry shutdown
entry kill_vcr
entry easy_calls
entry setup_call
entry activate_vcr
entry get_input
entry send_output
entry process_fields
entry field_handlers
entry add_separator
entry send_gstring
entry make_gstring
entry move_gstring
entry parse_path
entry get_name
entry long_multiply
entry long_divide
entry pro_date_time
entry get_date_time
entry calc_dow
entry get_option_list
entry transform_in_s
entry transform_in_f
entry transform_out
entry transform_vol
entry transform_gstring
entry transform_name
entry get_ext_type
entry get_file_type
entry write_protect
entry create
entry get_file_info
entry volume
entry id_disk
entry check_apple_ext
entry build_vcr
entry set_file_system
entry open
entry process_path
entry find_a_vcr
entry find_volume
entry find_file
entry find_directory
entry search_path_tbl
entry move_dir_record
entry clear_dir_recs
entry search_dir
entry build_fcr
entry get_dir_info
entry calc_blocks
entry read
entry transfer_data
entry setup_volume
entry direct_read
entry sector_read
entry block_read
entry device_read
entry device_dispatch
entry read_next_block
entry read_prev_block
entry read_with_flag
entry setup_open_buf
entry check_open_buf
entry set_end_block
entry close
entry set_mark
entry calc_open_block
entry update_fcr
entry get_mark
entry get_eof
entry get_dir_entry
entry find_dir_record
entry count_dir_recs
entry do_update
entry get_dev_num
entry fst_specific
entry map_enable
entry get_map_size
entry get_map_table
entry set_map_table
entry end_segment
entry invalid_op
entry cmd_error
entry nop
entry wp_error
entry clc_rtl
entry h_pcount
entry h_ref_num
entry h_pathname
entry h_dev_name
entry h_request_access
entry h_resource_num
entry h_data_buffer
entry h_request_count
entry h_cache_priority
entry h_position
entry h_base
entry h_displacement
entry h_access
entry h_file_type
entry h_aux_type
entry h_total_blocks
entry h_storage_type
entry h_create_date
entry h_mod_date
entry h_create_time
entry h_mod_time
entry h_blocks_used
entry h_create_date_time
entry h_mod_date_time
entry h_option_list
entry h_eof
entry h_resource_eof
entry h_resource_blocks
entry h_vol_name
entry h_free_blocks
entry h_file_sys_id
entry h_block_size
entry h_transfer_count
entry h_entry_num
entry h_dev_number
entry h_name
entry h_extended
entry h_command_num
entry my_sys_exit
entry setup_vcr
entry set_user_cache
entry common_read
entry condition_flag
entry next_block
entry device_read_b
entry find_our_volume
entry check_xa
eject
include 'common.equ.src'
include 'hw.equ.src'
include 'M16.Memory'
eject
*******************************************************************************
*
* High Sierra FST Equates
*
*******************************************************************************
*
* Volume Control Record Equates - FST Specific
*
vcr_total_blks equ vcr_dev+2 ;Total # blocks on volume.
vcr_block_size equ vcr_total_blks+4 ;Size of a logical block.
vcr_path_size equ vcr_block_size+2 ;Size of the path table.
vcr_root_dir equ vcr_path_size+4 ;Directory record for root dir.
vcr_create_dt equ vcr_root_dir+34 ;Create date & time.
vcr_mod_dt equ vcr_create_dt+17 ;Modification date & time.
vcr_state_flag equ vcr_mod_dt+17 ;Flags for volume status.
*** changed 2-Dec-92 DAL
;vcr_path_table equ vcr_state_flag+2 ;Path table.
vcr_path_tbl_handle equ vcr_state_flag+2 ;handle to path table (Memory Manager handle)
our_vcr_size equ vcr_path_tbl_handle+4 ;size of VCR (no longer varies with path table size)
*** end 2-Dec-92
*
* File Control Record Equates - FST Specific
*
fcr_position equ fcr_access+2 ;File mark.
fcr_entry_num equ fcr_position+4 ;Directory entry #.
fcr_start_rec equ fcr_entry_num+2 ;Start entry # of current dir block.
fcr_storage equ fcr_start_rec+2 ;Storage type.
fcr_eof equ fcr_storage+2 ;Eof.
fcr_blks equ fcr_eof+4 ;Blocks used.
fcr_open_block equ fcr_blks+4 ;Block # in open buffer.
fcr_open_mark equ fcr_open_block+4 ;Mark within open buffer.
fcr_skip_count equ fcr_open_mark+2 ;Interleave skip counter.
fcr_error_flag equ fcr_skip_count+2 ;Flag set if open buffer data invalid.
fcr_type_flag equ fcr_error_flag+2 ;Shows read or get_dir_entry access.
fcr_dir_record equ fcr_type_flag+2 ;Directory record. MUST BE LAST FIELD!
*
* FST direct page workspace equates.
*
io_buffer equ fst_start ;Pointer to io_buffer.
my_pblk equ io_buffer+4 ;Pointer to my parameter block.
my_vcr equ my_pblk+4 ;Pointer to my volume control record.
my_fcr equ my_vcr+4 ;Pointer to my file control record.
newline_ptr equ my_fcr+4 ;Pointer to newline list.
list_ptr equ newline_ptr+4 ;Field list pointer.
path_ptr equ list_ptr+4 ;Pointer to pathname.
dev_name equ path_ptr+4 ;Pointer to device name.
data_buffer equ dev_name+4 ;Pointer to data buffer.
path_table equ data_buffer+4 ;Pointer to path table.
entry_offset equ path_table+4 ;Offset to entry in path table.
fcr_dir_ptr equ entry_offset+2 ;Pointer to directory record in fcr.
open_buf_ptr equ fcr_dir_ptr+4 ;Pointer to open buffer in fcr.
dividend equ open_buf_ptr+4 ;32 bit dividend.
multiplier equ dividend ;32 bit multiplier.
divisor equ dividend+4 ;32 bit divisor.
multiplicand equ divisor ;32 bit multiplicand.
remainder equ divisor+4 ;32 bit remainder.
newline_char equ remainder+4 ;Will hold first byte of newline table.
bytes_left equ newline_char+2 ;# bytes till satisfy read request.
*
* FST direct page to save within device_dispatch call...
*
input_string equ bytes_left+4 ;Pointer to input string.
output_string equ input_string+4 ;Pointer to output string.
product equ input_string ;8 byte multiplication product.
temp0 equ output_string+4 ;Temporary storage.
temp1 equ temp0+2 ;Temporary storage.
length equ temp1+4 ;Length (temp).
drvr_dp_len equ drvr_blk_num+2-drvr_call_num ;Length of driver dp area.
fst_dp_len equ length+4-input_string ;Length of fst dp area.
misc_len equ $0060 ;Length of misc area.
*
* High Sierra Volume Descriptor equates.
* Suffix 0 (_0) equates are for High Sierra, suffix 1 (_1) equates are for ISO.
*
vol_start equ 16 ;Start sector for volume header.
vol_terminator equ 255 ;Terminator value.
vol_type_0 equ 8 ;Offset to type.
vol_id_end_0 equ 13 ;Offset to end of 'CDROM' string.
vol_version_0 equ 14 ;Offset to version.
vol_file_ver_0 equ 854 ;Offset to file structure standard ver.
vol_type_1 equ 0 ;Offset to type.
vol_id_end_1 equ 5 ;Offset to end of 'CD001' string.
vol_version_1 equ 6 ;Offset to version.
vol_file_ver_1 equ 881 ;Offset to file structure standard ver.
vol_id_start_0 equ 48 ;Offset to start of volume name.
vol_id_len_0 equ 79-vol_id_start_0 ;Length of volume name -1.
vol_spce_size_0 equ 88 ;Offset to blocks used.
vol_blk_size_0 equ 136 ;Offset to block size.
vol_path_size_0 equ 140 ;Offset to path table size.
vol_path_loc_0 equ 148 ;Offset to location of path table.
vol_root_dir_0 equ 180 ;Offset to root directory.
vol_root_len_0 equ 213-vol_root_dir_0+1 ;Length of root directory.
vol_create_dt_0 equ 790 ;Offset to create date & time.
vol_mod_dt_0 equ 806 ;Offset to modification date & time.
vol_dt_len_0 equ 821-vol_create_dt_0+1 ;Length of create & mod fields.
vol_id_start_1 equ 40 ;Offset to start of volume name.
vol_id_len_1 equ 71-vol_id_start_1 ;Length of volume name -1.
vol_spce_size_1 equ 80 ;Offset to blocks used.
vol_blk_size_1 equ 128 ;Offset to block size.
vol_path_size_1 equ 132 ;Offset to path table size.
vol_path_loc_1 equ 140 ;Offset to location of path table.
vol_root_dir_1 equ 156 ;Offset to root directory.
vol_root_len_1 equ 189-vol_root_dir_1+1 ;Length of root directory.
vol_create_dt_1 equ 813 ;Offset to create date & time.
vol_mod_dt_1 equ 830 ;Offset to modification date & time.
vol_dt_len_1 equ 846-vol_create_dt_1 ;Length of create & mod fields -1.
vol_sys_id_0 equ 16 ;Offset to system id.
vol_sys_id_1 equ 8 ;Offset to system id.
vol_xa_label_1 equ 1024 ;Offset to CD-ROM XA label.
*
* High Sierra Directory Record equates...
* Suffix 0 (_0) equates are for High Sierra, suffix 1 (_1) equates are for ISO.
*
dir_len_dr equ 0 ;Length of directory record.
dir_xar_len equ 1 ;Extended attribute record length.
dir_loc_extent equ 2 ;Location of extent.
dir_data_length equ 10 ;Length of data, in bytes.
dir_date_time equ 18 ;Recording date and time.
dir_flags_0 equ 24 ;File flags.
dir_flags_1 equ 25 ;File flags.
dir_int_size equ 26 ;Size of interleave.
dir_int_skip equ 27 ;Interleave skip factor.
dir_len_fi equ 32 ;Length of file identifier.
dir_file_id equ 33 ;File identifier.
max_rec_len equ 256 ;Max dir record length. Must be even!
dir_mask equ 2 ;Bit mask for dir bit of file_flags.
assoc_mask equ 4 ;Bit mask for assoc file bit of flags.
clear_invisible equ $fffe ;Bit mask for existence bit of flags.
*
* High Sierra Path Table equates...
* Suffix 0 (_0) equates are for High Sierra, suffix 1 (_1) equates are for ISO.
*
pt_loc_extent_0 equ 0 ;Offset to location of directory extent.
pt_loc_extent_1 equ 2 ;Offset to location of directory extent.
pt_len_di_0 equ 5 ;Offset to len_di in path table entry.
pt_len_di_1 equ 0 ;Offset to len_di in path table entry.
pt_di_offset_0 equ 3 ;Offset from len_di to identifier in path table entry.
pt_di_offset_1 equ 8 ;Offset from len_di to identifier in path table entry.
pt_xar_len_0 equ 4 ;Offset to xar len in path table entry.
pt_xar_len_1 equ 1 ;Offset to xar len in path table entry.
pt_parent_dir equ 6 ;Offset to parent_dir in path table.
pt_entry_len equ 8 ;Length of path table entry - len_di.
*
* General equates...
*
max_month equ 12 ;Max month value.
max_day equ 31 ;Max day value.
max_year equ 100 ;Max year value +1.
max_hour equ 60 ;Max hour value +1.
max_minute equ 60 ;Max minute value +1.
max_second equ 60 ;Max second value +1.
prodos_name_ln equ 16 ;Max length for class 0 output names +1.
phys_blk_size equ 512 ;Physical block size.
iso_bit equ $0001 ;State flag ISO version bit.
apple_bit equ $0002 ;State flag Apple Extensions bit.
prodos_bit equ $0004 ;State flag ProDOS Filename Transformation bit.
xa_bit equ $0008 ;State flag CD-ROM XA bit.
prodos_format equ $0001 ;Apple Extensions ProDOS format id.
sys_use_len equ 35 ;Length used to calculate for presence of sys use.
apple_str_len equ 28 ;Length of apple string.
xa_str_len equ 8 ;Length of xa_string.
xa_offset equ 14 ;System use offset for XA discs.
apple_sig1 equ $4142 ;Signature word 1 in SystemUse field.
apple_sig2 equ $4141 ;Signature word 2 in SystemUse field.
crossover equ $2b800 ;Size at which to switch calc_open_block.
type_file equ 1 ;Storage type for files.
type_extended equ 5 ;Storage type for extended files.
type_directory equ 13 ;Storage type for directories.
type_vol_dir equ 15 ;Storage type for volume directory.
file_type_dir equ 15 ;File type for directories.
set_extended equ $8000 ;Extended flag for get_dir_entry.
online_mask equ $0010 ;Mask for online bit of device status.
switched_mask equ $0001 ;Mask for switched bit of device status.
map_enable_off equ $0006 ;Offset into parm list for fst_specific.
map_size equ $0006 ;Offset into parm list for fst_specific.
map_buffer equ $0006 ;Offset into parm list for fst_specific.
get_file_call equ $06 ;Call number for get_file_info.
get_dir_call equ $1c ;Call number for get_dir_entry.
max_names equ 9 ;Max # of names in pathname.
separator0 equ $2f ;Class 0 separator ('/').
separator1 equ $3a ;Class 1 separator (':').
sector_size equ 2048 ;Size of a logical sector.
hs_id equ $000B ;Identifies high sierra file system.
iso_id equ $000C ;Identifies ISO 9660 file system.
path1_mask equ $4000 ;Used to determine if path1 is avail.
path2_mask equ $0040 ;Used to determine if path2 is avail.
space equ $20 ;Ascii space.
read_access equ $0001 ;Read access.
full_access equ $00c3 ;Full access.
user_cache_val equ $0001 ;User cache value.
in_cache equ $0002 ;Fst cache value.
max_base equ $0003 ;Maximum base value.
*
* Storage Type Equates
*
standard_type equ $0001 ;Standard file.
extended_type equ $0005 ;Extended file.
directory_type equ $000d ;Directory file.
*
* Local Equates...
*
map_ptr equ temp1 ;startup/get_file_type/fst_specific
day_of_mon equ temp0 ;calc_dow
leap_years equ temp1 ;calc_dow
option_list equ dividend ;get_option_list
max_len equ temp0 ;get_option_list
block_count equ temp1 ;get_option_list
current_dev equ temp0 ;id_disk
sector_number equ temp1 ;id_disk
vol_offset equ temp0 ;build_vcr.
path_size equ temp1 ;build_vcr.
device equ temp0 ;find_a_vcr
last_offset equ temp0 ;find_directory
start_record equ temp1 ;search_path_table
file_type equ temp0 ;search_dir
short_file_flag equ temp0 ;build_fcr
status_flag equ temp0 ;transfer_data
xfer_count equ temp1 ;transfer_data
source_ptr equ dividend ;transfer_data
log_block equ temp1 ;calc_open_block
old_vp equ list_ptr ;set_map_table
*
* General Equates...
*
len_bounce_tbl equ $000a ;Points to end of bouncing_errors table.
specific_len equ $0008 ;Length of fst specific dispatch table.
max_command_num equ $0004 ;Max fst specific command_num.
input_len equ $0018 ;Count of input parameters.
file_sys_len equ $001e ;Length of file_sys_table-2.
call_count equ $000f ;Count of handled calls.
max_call equ $0066 ;Last valid application call.
max_sys equ $0008 ;Last valid system call.
*
* Equates used to build the start_flags table...
*
path_used equ $0100 ;Path used bit.
vcr_used equ $0200 ;Vcr used bit.
fcr_used equ $0400 ;Fcr used bit.
max_mask equ $001f ;Isolate max pcount.
min_mask equ $00e0 ;Isolate min pcount.
max_class equ $0001 ;Maximum class #.
max_pcnt1 equ 1+1 ;Values for max pcounts.
max_pcnt2 equ 2+1
max_pcnt3 equ 3+1
max_pcnt4 equ 4+1
max_pcnt5 equ 5+1
max_pcnt6 equ 6+1
max_pcnt7 equ 7+1
max_pcnt8 equ 8+1
max_pcnt9 equ 9+1
max_pcnt10 equ 10+1
max_pcnt11 equ 11+1
max_pcnt12 equ 12+1
max_pcnt13 equ 13+1
max_pcnt14 equ 14+1
max_pcnt15 equ 15+1
max_pcnt16 equ 16+1
max_pcnt17 equ 17+1
min_pcnt1 equ $0020 ;Values for min pcounts.
min_pcnt2 equ $0040
min_pcnt3 equ $0060
min_pcnt4 equ $0080
min_pcnt5 equ $00A0
*
* Equates for field list tables...
*
field_mask equ $00ff ;Isolate field.
offset_mask equ $3f00 ;Isolate offset.
io_mask equ $4000 ;Isolate i/o flag.
terminate equ $8000 ;Terminator bit.
input equ $0000 ;Input bit.
output equ $4000 ;Output bit.
f_pcount equ $0000 ;(w) input.
f_ref_num equ $0001 ;(w) input/output.
f_pathname equ $0002 ;(ptr) input.
f_dev_name equ $0003 ;(ptr) input.
f_request_access equ $0004 ;(w) input.
f_resource_num equ $0005 ;(w) input.
f_data_buffer equ $0006 ;(ptr) input.
f_request_count equ $0007 ;(lw) input.
f_cache_priority equ $0008 ;(w) input.
f_position equ $0009 ;(lw) input/output.
f_base equ $000a ;(w) input.
f_displacement equ $000b ;(lw) input.
f_access equ $000c ;(w) output.
f_file_type equ $000d ;(w) output.
f_aux_type equ $000e ;(lw) output.
f_total_blocks equ $000f ;(lw) output.
f_storage_type equ $0010 ;(w) output.
f_create_date equ $0011 ;(w) output.
f_create_time equ $0012 ;(w) output.
f_mod_date equ $0013 ;(w) output.
f_mod_time equ $0014 ;(w) output.
f_blocks_used equ $0015 ;(lw) output.
f_create_date_time equ $0016 ;(4w) output.
f_mod_date_time equ $0017 ;(4w) output.
f_option_list equ $0018 ;(ptr) output.
f_eof equ $0019 ;(lw) output.
f_resource_eof equ $001a ;(lw) output.
f_resource_blocks equ $001b ;(lw) output.
f_vol_name equ $001c ;(ptr) output.
f_free_blocks equ $001d ;(lw) output.
f_file_sys_id equ $001e ;(w) output.
f_block_size equ $001f ;(w) output.
f_transfer_count equ $0020 ;(lw) output.
f_entry_num equ $0021 ;(w) output.
f_dev_number equ $0022 ;(w) output.
f_name equ $0023 ;(ptr) output.
f_extended equ $0024 ;(w) output.
f_command_num equ $0025 ;(w) input.
offset0 equ $0000
offset2 equ $0200
offset4 equ $0400
offset6 equ $0600
offset8 equ $0800
offsetA equ $0A00
offsetC equ $0C00
offsetE equ $0E00
offset10 equ $1000
offset12 equ $1200
offset14 equ $1400
offset16 equ $1600
offset18 equ $1800
offset1A equ $1A00
offset1C equ $1C00
offset1E equ $1E00
offset20 equ $2000
offset22 equ $2200
offset24 equ $2400
offset26 equ $2600
offset28 equ $2800
offset2A equ $2A00
offset2C equ $2C00
offset2E equ $2E00
offset30 equ $3000
offset32 equ $3200
offset34 equ $3400
offset36 equ $3600
offset3A equ $3a00
eject
*******************************************************************************
*
* FST HEADER
* Used by GS/OS at boot time.
*
*******************************************************************************
fst_header proc
code_start DC.B 'FST ' ;Load identification (4 bytes).
DC.L appl_call ;Entry point for application calls.
DC.L system_call ;Entry point for system calls.
DC.W HS_ID ;High Sierra FST id.
DC.W $9800 ;Flags: uppercase, clear msb, read-only.
DC.W $0402 ;Version 4.02 final
DC.W $800 ;Normal block size. (2k)
DC.L $57800 ;Maximum blocks/volume. (700Mb)
DC.L 4 ;Minimum blocks/volume. (8k)
DC.L $2bbf7800 ;Maximum file size. (699.97Mb)
DC.L 00000000 ;Reserved.
DC.B 11 ;Length of FST name.
DC.B 'High Sierra' ;Text of FST name.
DC.B 32 ;Length of comment.
DC.B 'High Sierra FST v04.02'
DC.W 0000 ;reserved field
DC.B endcredit-startcredit
startcredit DC.B 'Copyright 1987-1992 Apple Computer, Inc. '
DC.B 'Written by Bryan Atsatt.'
DC.B 'Tested by Cary Farrier'
endcredit
ENDP
eject
*******************************************************************************
*
* DATA STORAGE AREA
*
*******************************************************************************
data record export
*
* Miscellaneous constants/variables/storage...
*
apple_string DC.B 'APPLE COMPUTER, INC., TYPE: ' ;Apple Extensions.
xa_string dc.b 'CD-XA001' ;Must match this for CD-ROM XA.
hs_string DC.B 'CDROM' ;Must match this for High Sierra.
iso_string DC.B 'CD001' ;Must match this for ISO.
bounce_errors dc.w bad_system_call ;Bouncing errors list.
dc.w invalid_pcount
dc.w bad_path_syntax
dc.w vol_not_found
dc.w unknown_vol
dc.w not_block_dev
length_temp ds.b 2 ;Temporary length storage.
input_error ds.b 2 ;Storage for input error.
call DS.B 2 ;Current call #
trans_call DS.B 2 ;Translated call #.
class DS.B 2 ;Current class #.
real_log_size DS.B 2 ;Readl logical block size. MUST INIT!
io_buffer_vp DS.B 4 ;VP to io_buffer.
max_pcount DS.B 2 ;Maximum pcount.
min_pcount DS.B 2 ;Minuimum pcount.
flags DS.B 2 ;Startup flags word.
io_flag DS.B 2 ;I/O flag for process_fields.
file_name DS.B 45 ;File name in gstring format.
string_buffer DS.B 45 ;Temporary storage for strings.
name_count DS.B 2 ;Count of names in pathname.
name_offsets DS.B 8 ;Offsets to start of names in pathname.
temp_offsets DS.B 8 ;Temporary storage for offsets.
path_table_size DS.B 2 ;Path table size.
current_name DS.B 2 ;Current directory.
current_record DS.B 2 ;Current record.
record_number DS.B 2 ;Record number.
record_offset DS.B 2 ;Offset to record.
record_count DS.B 2 ;Record count.
cache_value DS.B 2 ;Value of drvr_cache at call start.
dir_record_0 DS.B max_rec_len ;Buffer for directory record 0.
dir_record_1 DS.B max_rec_len ;Buffer for directory record 1.
dir_length DS.B 4 ;Length of directory record.
start_block DS.B 4 ;First block of file/directory.
end_block DS.B 4 ;Last block of file/directory.
newline_length DS.B 2 ;Length of newline list.
newline_mask DS.B 2 ;Mask for newline.
interleave_size DS.B 2 ;# consecutive blocks in file extent.
interleave_skip DS.B 2 ;# blocks to skip btwx consecutive.
skip_count DS.B 2 ;# blocks till next skip.
open_mark DS.B 2 ;position mark within open_buffer.
send_flag DS.B 2 ;Flag for send_open_bufr routine.
status_list DS.B 6 ;Space for status list.
skip_read_flag DS.B 2 ;Flag used by read_next_block.
read_size DS.B 4 ;Size of multi-block read.
abs_block DS.B 4 ;Absolute block number.
read_count DS.B 2 ;Read block count.
id_disk_flag DS.B 2 ;1 = id_disk routine active, else 0.
state_flag DS.B 2 ;b0 = 1 if ISO version of High Sierra.
;b1 = 1 if Apple Extensions disc.
;b2 = 1 if ProDOS Transformation required.
error_priority DS.B 2 ;storage for error priority
*** added 2-Dec-92 DAL
current_path_tbl_handle ds.b 4 ;path table handle to unlock on the way out
*** end 2-Dec-92
untitled_str DC.B 'UNTITLED' ;Untitled string.
DC.B $00
*
* Miscellaneous storage that must be kept together so can be saved during
* the device_dispatch call...
*
* NOTE: If this section changes length, the misc_len equate MUST be changed!!!
*
gstring DS.B 45 ;Temp storage for gstrings.
volume_name DS.B 45 ;Volume name in gstring format.
current_device DS.B 2 ;Current device.
start_device DS.B 2 ;Start device.
log_blk_size DS.B 2 ;Logical block size. MUST INIT!
storage_drvr DS.B drvr_dp_len ;Space for driver dp save.
storage_fst DS.B fst_dp_len ;Space for fst dp save.
storage_misc DS.B 45+45+6 ;Space for misc save.
*
* D_info parameter table...
*
d_info_parms DC.W 8 ;Pcount.
d_info_device DC.W 0 ;Device number.
DC.L string_buffer ;Pointer to output string.
DC.W 0 ;Characteristics.
DC.L 0 ;Total blocks.
DC.W 0 ;Slot number.
DC.W 0 ;Unit number.
DC.W 0 ;Version number.
d_info_id DC.W 0 ;Device ID.
*
* File type map data and map_enable_flag...
*
map_buffer_vp DS.B 4 ;Storage for vp.
map_buffer_ptr DS.B 4 ;Storage for pointer.
default_map DC.W $000f ;Size of default map.
DC.B '.TXT' ;Record 0.
DC.B $00,$04
DC.B '.BAT' ;Record 1.
DC.B $00,$04
DC.B $00 ;Map terminator.
map_enable_flag DC.W 0001 ;Default is enabled.
*
* Dispatch table for fst_specific commands...
*
specific_cmds DC.W map_enable ;Map_enable.
DC.W get_map_size ;Get_map_size.
DC.W get_map_table ;Get_map_table.
DC.W set_map_table ;Set_map_table.
*
* Storage for input parameters...
*
pcount DC.W 00 ;Parameter count.
ref_num DC.W 00 ;File reference number.
request_access DC.W 00 ;Request access permissions.
resource_num DC.W 00 ;Resource number.
request_count DC.L 00 ;Request count.
cache_priority DC.W 00 ;Cache priority flag.
position DC.L 00 ;File mark.
base DC.W 00 ;Base.
displacement DC.L 00 ;Displacement.
command_num DC.W 00 ;Fst_specific command number.
*
* Storage for output parameters...
*
total_blocks DC.L 00 ;Total blocks.
storage_type DC.W 00 ;Storage type.
prodos_time DC.L 00 ;Prodos date/time.
blocks_used DC.L 00 ;Blocks used.
create_date_time ;Create_date_time structure.
second dc.b 00
minute dc.b 00
hour dc.b 00
year dc.b 00
day dc.b 00
month dc.b 00
null dc.b 00
weekday dc.b 00
default_date_time dc.b 00,00,12,88,00,00,00,06
mod_date_time DCB.B 8,00 ;Modification date and time.
eof DC.L 00 ;End of file.
resource_eof DC.L 00 ;Resource end of file.
resource_blocks DC.L 00 ;Resource blocks used.
block_size DC.W 00 ;Block size.
transfer_count DC.L 00 ;Transfer count.
entry_num DC.W 00 ;Entry number.
dev_number DC.W 00 ;Device number.
extended_flag DC.W 00 ;Extended flag.
*
* High Sierra and ISO Version Support
*
* Set_file_system will copy either hs_offsets or iso_offsets into the
* file_sys_table and all references to the labels in this table will be
* made as variables.
*
* High Sierra/ISO Field Offsets...
*
file_sys_table ;
vol_id_start DS.B 2 ;Offset to start of volume name.
vol_id_len DS.B 2 ;Length of volume name -1.
vol_space_size DS.B 2 ;Offset to blocks used.
vol_block_size DS.B 2 ;Offset to block size.
vol_path_size DS.B 2 ;Offset to path table size.
vol_path_loc DS.B 2 ;Offset to location of path table.
vol_root_dir DS.B 2 ;Offset to root directory.
vol_root_len DS.B 2 ;Length of root directory.
vol_create_dt DS.B 2 ;Offset to create date & time.
vol_mod_dt DS.B 2 ;Offset to modification date & time.
vol_dt_len DS.B 2 ;Length of create & mod fields.
dir_file_flags DS.B 2 ;File flags.
pt_loc_extent DS.B 2 ;Offset to location of directory extent.
pt_len_di DS.B 2 ;Offset to len_di in path table entry.
pt_di_offset ds.b 2 ;Offset from len_di to identifier in path table entry.
pt_xar_len ds.b 2 ;Offset to xar len in path table entry.
*
* High Sierra Field Offsets...
*
hs_offsets DC.W vol_id_start_0 ;Offset to start of volume name.
DC.W vol_id_len_0 ;Length of volume name -1.
DC.W vol_spce_size_0 ;Offset to blocks used.
DC.W vol_blk_size_0 ;Offset to block size.
DC.W vol_path_size_0 ;Offset to path table size.
DC.W vol_path_loc_0 ;Offset to loc of path table.
DC.W vol_root_dir_0 ;Offset to root directory.
DC.W vol_root_len_0 ;Length of root directory.
DC.W vol_create_dt_0 ;Offset to create date & time.
DC.W vol_mod_dt_0 ;Offset to mod date & time.
DC.W vol_dt_len_0 ;Length of create & mod fields.
DC.W dir_flags_0 ;File flags.
DC.W pt_loc_extent_0 ;Offset to loc of dir extent.
DC.W pt_len_di_0 ;Offset to len_di in path table.
DC.W pt_di_offset_0 ;Offset from len_di to identifier in path table entry.
DC.W pt_xar_len_0 ;Offset to xar len in path table entry.
*
* ISO Field Offsets...
*
iso_offsets DC.W vol_id_start_1 ;Offset to start of volume name.
DC.W vol_id_len_1 ;Length of volume name -1.
DC.W vol_spce_size_1 ;Offset to blocks used.
DC.W vol_blk_size_1 ;Offset to block size.
DC.W vol_path_size_1 ;Offset to path table size.
DC.W vol_path_loc_1 ;Offset to loc of path table.
DC.W vol_root_dir_1 ;Offset to root directory.
DC.W vol_root_len_1 ;Length of root directory.
DC.W vol_create_dt_1 ;Offset to create date & time.
DC.W vol_mod_dt_1 ;Offset to mod date & time.
DC.W vol_dt_len_1 ;Length of create & mod fields.
DC.W dir_flags_1 ;File flags.
DC.W pt_loc_extent_1 ;Offset to loc of dir extent.
DC.W pt_len_di_1 ;Offset to len_di in path table.
DC.W pt_di_offset_1 ;Offset from len_di to identifier in path table entry.
DC.W pt_xar_len_1 ;Offset to xar len in path table entry.
eject
*
* STARTUP TABLES
*
* The following table is used to translate GS/OS call #'s I handle
* to sequential values from 0 to 9, times 2.
*
handled_calls DC.B $01,$02,$04,$05,$06,$08,$0b,$10,$12,$14,$16,$17,$19,$1c,$20,$33
*
* The following table is used to setup and verify some parameters.
* Each call has a one word entry in the table with the following
* format:
*
* 1 - Max PCount for the call
* 2 - Min PCount for the call
* 3 - Pathnames used by call
* 4 - Volume control record used
* 5 - File control record used
* 6 - I/O buffer used
*
* |6|5|4|3| 2 | 1 |
* _______|_|_|_|_|_____|_________|
* | | | | | | | | | | | | | | | | |
* |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
* | | |
* 1 6 0 8 0 0
*
start_flags ;
DC.W max_pcnt7+min_pcnt1+path_used ;(01) Create
DC.W max_pcnt1+min_pcnt1+path_used ;(02) Destroy
DC.W max_pcnt3+min_pcnt2+path_used ;(04) Change_path
DC.W max_pcnt12+min_pcnt2+path_used ;(05) Set_file_info
DC.W max_pcnt12+min_pcnt2+path_used ;(06) Get_File_Info
DC.W max_pcnt6+min_pcnt2 ;(08) Volume
DC.W max_pcnt1+min_pcnt1+path_used ;(0B) Clr_backup_bit
DC.W max_pcnt15+min_pcnt2+path_used ;(10) Open
DC.W max_pcnt5+min_pcnt4+vcr_used+fcr_used ;(12) Read
DC.W max_pcnt1+min_pcnt1+vcr_used+fcr_used ;(14) Close
DC.W max_pcnt3+min_pcnt3+vcr_used+fcr_used ;(16) Set_mark
DC.W max_pcnt2+min_pcnt2+vcr_used+fcr_used ;(17) Get_mark
DC.W max_pcnt2+min_pcnt2+vcr_used+fcr_used ;(19) Get_eof
DC.W max_pcnt17+min_pcnt5+vcr_used+fcr_used ;(1C) Get_dir_entry
DC.W max_pcnt2+min_pcnt2+path_used ;(20) Get_dev_num
DC.W max_pcnt3+min_pcnt3 ;(33) Fst_specific
eject
* DISPATCH TABLES
*
cmd_tbl DC.W create ;($01) create
DC.W write_protect ;($02) destroy
DC.W cmd_error ;($03) unimplemented
DC.W write_protect ;($04) change_path
DC.W write_protect ;($05) set_file_info
DC.W get_file_info ;($06) get_file_info
DC.W invalid_op ;($07) judge_name
DC.W volume ;($08) volume
DC.W cmd_error ;($09) set_prefix
DC.W cmd_error ;($0A) get_prefix'
DC.W write_protect ;($0B) clear_backup_bit
DC.W cmd_error ;($0C) unimplemented
DC.W cmd_error ;($0D) unimplemented
DC.W cmd_error ;($0E) unimplemented
DC.W cmd_error ;($0F) unimplemented
DC.W open ;($10) open
DC.W cmd_error ;($11) newline
DC.W read ;($12) read
DC.W wp_error ;($13) write
DC.W close ;($14) close
DC.W nop ;($15) flush
DC.W set_mark ;($16) set_mark
DC.W get_mark ;($17) get_mark
DC.W wp_error ;($18) set_eof
DC.W get_eof ;($19) get_eof
DC.W cmd_error ;($1A) set_level
DC.W cmd_error ;($1B) get_level
DC.W get_dir_entry ;($1C) get_dir_entry
DC.W cmd_error ;($1D) unimplemented
DC.W cmd_error ;($1E) unimplemented
DC.W cmd_error ;($1F) unimplemented
DC.W get_dev_num ;($20) get_dev_num
DC.W cmd_error ;($21) get_last_dev
DC.W cmd_error ;($22) read_block
DC.W cmd_error ;($23) write_block
DC.W wp_error ;($24) format
DC.W wp_error ;($25) erase_disk
DC.W cmd_error ;($26) get_pathname
DC.W cmd_error ;($27) get_name
DC.W cmd_error ;($28) get_boot_vol
DC.W cmd_error ;($29) quit
DC.W cmd_error ;($2A) get_version
DC.W cmd_error ;($2B) get_fst_info
DC.W cmd_error ;($2C) d_info
DC.W cmd_error ;($2D) d_status
DC.W cmd_error ;($2E) d_control
DC.W cmd_error ;($2F) d_read
DC.W cmd_error ;($30) d_write
DC.W cmd_error ;($31) alloc_interrupt
DC.W cmd_error ;($32) dealloc_interrupt
DC.W fst_specific ;($33) fst_specific.
sys_tbl DC.W startup ;Initialize
DC.W shutdown ;Quit
DC.W kill_vcr ;was clc_rtl, 2-Dec-92 DAL
DC.W clc_rtl ;Do nothing call.
eject
* FIELD TABLES
*
* The following tables point to the field lists for class 0 and 1...
*
class0 DC.W call01_class0 ;Create.
DC.W call01_class0 ;Destroy.
DC.W call01_class0 ;Change_path.
DC.W call01_class0 ;Set_file_info.
DC.W call06_class0 ;Get_file_info.
DC.W call08_class0 ;Volume.
DC.W call01_class0 ;Clear_backup_bit.
DC.W call10_class0 ;Open.
DC.W call12_class0 ;Read.
DC.W call14_class0 ;Close.
DC.W call16_class0 ;Set_mark.
DC.W call17_class0 ;Get_mark.
DC.W call19_class0 ;Get_eof.
DC.W call1c_class0 ;Get_dir_entry.
DC.W call20_class0 ;Get_dev_num.
class1 DC.W call01_class1 ;Create.
DC.W call01_class1 ;Destroy.
DC.W call01_class1 ;Change_path.
DC.W call01_class1 ;Set_file_info.
DC.W call06_class1 ;Get_file_info
DC.W call08_class1 ;Volume.
DC.W call01_class1 ;Clear_backup_bit.
DC.W call10_class1 ;Open.
DC.W call12_class1 ;Read.
DC.W call14_class1 ;Close.
DC.W call16_class1 ;Set_mark.
DC.W call17_class1 ;Get_mark.
DC.W call19_class1 ;Get_eof.
DC.W call1c_class1 ;Get_dir_entry.
DC.W call20_class1 ;Get_dev_num.
DC.W call33_class1 ;Fst_specific.
*
* Each call has a list of one word entries with the following format:
*
* 1 - Field number times two
* 2 - Field offset
* 3 - I/O flag: 0 = input, 1 = output.
* 4 - Terminator: 1 = last entry in list.
*
* |4|3| 2 | 1 |
* |_|_|___________|_______________|
* | | | | | | | | | | | | | | | | |
* |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
* | | |
* 1 6 0 8 0 0
*
* Create, Destroy, Change_path, Set_file_info, Clear_backup_bit field lists...
*
call01_class0 DC.W 2*f_pathname+offset0+input+terminate
call01_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_pathname+offset2+input+terminate
*
* Get_file_info field lists...
*
call06_class0 DC.W 2*f_pathname+offset0+input
DC.W 2*f_access+offset4+output
DC.W 2*f_file_type+offset6+output
DC.W 2*f_aux_type+offset8+output
DC.W 2*f_storage_type+offsetc+output
DC.W 2*f_create_date+offsete+output
DC.W 2*f_create_time+offset10+output
DC.W 2*f_mod_date+offset12+output
DC.W 2*f_mod_time+offset14+output
DC.W 2*f_blocks_used+offset16+output+terminate
call06_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_pathname+offset2+input
DC.W 2*f_access+offset6+output
DC.W 2*f_file_type+offset8+output
DC.W 2*f_aux_type+offseta+output
DC.W 2*f_storage_type+offsete+output
DC.W 2*f_create_date_time+offset10+output
DC.W 2*f_mod_date_time+offset18+output
DC.W 2*f_option_list+offset20+output
DC.W 2*f_eof+offset24+output
DC.W 2*f_blocks_used+offset28+output
DC.W 2*f_resource_eof+offset2c+output
DC.W 2*f_resource_blocks+offset30+output+terminate
*
* Volume field lists...
*
call08_class0 DC.W 2*f_dev_name+offset0+input
DC.W 2*f_vol_name+offset4+output
DC.W 2*f_total_blocks+offset8+output
DC.W 2*f_free_blocks+offsetc+output
DC.W 2*f_file_sys_id+offset10+output+terminate
call08_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_dev_name+offset2+input
DC.W 2*f_vol_name+offset6+output
DC.W 2*f_total_blocks+offseta+output
DC.W 2*f_free_blocks+offsete+output
DC.W 2*f_file_sys_id+offset12+output
DC.W 2*f_block_size+offset14+output+terminate
*
* Open field lists...
*
call10_class0 DC.W 2*f_ref_num+offset0+output
DC.W 2*f_pathname+offset2+input+terminate
call10_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_ref_num+offset2+output
DC.W 2*f_pathname+offset4+input
DC.W 2*f_request_access+offset8+input
DC.W 2*f_resource_num+offseta+input
DC.W 2*f_access+offsetc+output
DC.W 2*f_file_type+offsete+output
DC.W 2*f_aux_type+offset10+output
DC.W 2*f_storage_type+offset14+output
DC.W 2*f_create_date_time+offset16+output
DC.W 2*f_mod_date_time+offset1e+output
DC.W 2*f_option_list+offset26+output
DC.W 2*f_eof+offset2a+output
DC.W 2*f_blocks_used+offset2e+output
DC.W 2*f_resource_eof+offset32+output
DC.W 2*f_resource_blocks+offset36+output+terminate
*
* Read field lists...
*
call12_class0 DC.W 2*f_ref_num+offset0+input
DC.W 2*f_data_buffer+offset2+input
DC.W 2*f_request_count+offset6+input
DC.W 2*f_transfer_count+offseta+output+terminate
call12_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_ref_num+offset2+input
DC.W 2*f_data_buffer+offset4+input
DC.W 2*f_request_count+offset8+input
DC.W 2*f_transfer_count+offsetc+output
DC.W 2*f_cache_priority+offset10+input+terminate
*
* Close field lists...
*
call14_class0 DC.W 2*f_ref_num+offset0+input+terminate
call14_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_ref_num+offset2+input+terminate
*
* Set_mark field lists...
*
call16_class0 DC.W 2*f_ref_num+offset0+input
DC.W 2*f_displacement+offset2+input+terminate
call16_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_ref_num+offset2+input
DC.W 2*f_base+offset4+input
DC.W 2*f_displacement+offset6+input+terminate
*
* Get_mark field lists...
*
call17_class0 DC.W 2*f_ref_num+offset0+input
DC.W 2*f_position+offset2+output+terminate
call17_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_ref_num+offset2+input
DC.W 2*f_position+offset4+output+terminate
*
* Get_eof field lists...
*
call19_class0 DC.W 2*f_ref_num+offset0+input
DC.W 2*f_eof+offset2+output+terminate
call19_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_ref_num+offset2+input
DC.W 2*f_eof+offset4+output+terminate
*
* Get_dir_entry field lists...
*
call1c_class0 DC.W 2*f_ref_num+offset0+input
DC.W 2*f_extended+offset2+output
DC.W 2*f_base+offset4+input
DC.W 2*f_displacement+offset6+input
DC.W 2*f_name+offset8+output
DC.W 2*f_entry_num+offsetc+output
DC.W 2*f_file_type+offsete+output
DC.W 2*f_eof+offset10+output
DC.W 2*f_blocks_used+offset14+output
DC.W 2*f_create_date_time+offset18+output
DC.W 2*f_mod_date_time+offset20+output
DC.W 2*f_access+offset28+output
DC.W 2*f_aux_type+offset2a+output
DC.W 2*f_file_sys_id+offset2e+output+terminate
call1c_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_ref_num+offset2+input
DC.W 2*f_extended+offset4+output
DC.W 2*f_base+offset6+input
DC.W 2*f_displacement+offset8+input
DC.W 2*f_name+offseta+output
DC.W 2*f_entry_num+offsete+output
DC.W 2*f_file_type+offset10+output
DC.W 2*f_eof+offset12+output
DC.W 2*f_blocks_used+offset16+output
DC.W 2*f_create_date_time+offset1a+output
DC.W 2*f_mod_date_time+offset22+output
DC.W 2*f_access+offset2a+output
DC.W 2*f_aux_type+offset2c+output
DC.W 2*f_file_sys_id+offset30+output
DC.W 2*f_option_list+offset32+output
DC.W 2*f_resource_eof+offset36+output
DC.W 2*f_resource_blocks+offset3A+output+terminate
*
* Get_dev_num field lists...
*
call20_class0 DC.W 2*f_dev_name+offset0+input
DC.W 2*f_dev_number+offset4+output+terminate
call20_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_dev_name+offset2+input
DC.W 2*f_dev_number+offset6+output+terminate
*
* Fst_specific field list (this is always a class 1 call)...
*
call33_class1 DC.W 2*f_pcount+offset0+input
DC.W 2*f_command_num+offset4+input+terminate
*
* The following table is a list of the field handler subroutine
* addresses...
*
handlers DC.W h_pcount ;(w) input.
DC.W h_ref_num ;(w) input/output.
DC.W h_pathname ;(ptr) input.
DC.W h_dev_name ;(ptr) input.
DC.W h_request_access ;(w) input.
DC.W h_resource_num ;(w) input.
DC.W h_data_buffer ;(ptr) input.
DC.W h_request_count ;(lw) input.
DC.W h_cache_priority ;(w) input.
DC.W h_position ;(lw) output.
DC.W h_base ;(w) input.
DC.W h_displacement ;(lw) input.
DC.W h_access ;(w) output.
DC.W h_file_type ;(w) output.
DC.W h_aux_type ;(lw) output.
DC.W h_total_blocks ;(lw) output.
DC.W h_storage_type ;(w) output.
DC.W h_create_date ;(w) output.
DC.W h_create_time ;(w) output.
DC.W h_mod_date ;(w) output.
DC.W h_mod_time ;(w) output.
DC.W h_blocks_used ;(lw) output.
DC.W h_create_date_time ;(4w) output.
DC.W h_mod_date_time ;(4w) output.
DC.W h_option_list ;(ptr) output.
DC.W h_eof ;(lw) output.
DC.W h_resource_eof ;(lw) output.
DC.W h_resource_blocks ;(lw) output.
DC.W h_vol_name ;(ptr) output.
DC.W h_free_blocks ;(lw) output.
DC.W h_file_sys_id ;(w) output.
DC.W h_block_size ;(w) output.
DC.W h_transfer_count ;(lw) output.
DC.W h_entry_num ;(w) output.
DC.W h_dev_number ;(w) output.
DC.W h_name ;(ptr) output.
DC.W h_extended ;(w) output.
DC.W h_command_num ;(w) input.
*
* Storage for process_fields...
*
field_num DS.B 2 ;Field number.
field_flags DS.B 2 ;Flags word for field.
field_count DS.B 2 ;Copy of pcount.
*
******************************************************************************
endr
eject
******************************************************************************
*
* Name: Appl_call
*
* Description: Entry point for all application calls. Called by GS/OS only.
* Validates call before passing control to call handler.
*
* Created: Oct 6, 1987
* Modified: Mar 5, 1991
* Author: Bryan Atsatt
*
* Entry: jml
*
* Input: A = undefined
* X = call number times 2
* Y = class number times 2
* P = nvmxdizc
* ..000...
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
*
* Exit: jml sys_exit
*
* Uses: Everything!
*
******************************************************************************
appl_call proc
with data
*
* Setup environment...
*
phk ;Setup our bank register.
plb
rep #$30 ;Make sure in 16 bit mode.
*** added 2-Dec-92 DAL -- Handle to unlock on the way out
stz current_path_tbl_handle+2
stz current_path_tbl_handle
*** end 2-Dec-92
*
* Call # valid?
*
cpx #max_call+1 ;In range?
bcc command_ok ;Yes.
brl cmd_error ;Nope.
*
* Yes, save drvr_cahce and clear id_disk_flag. Call ok?
*
command_ok lda drvr_cache ;Get value.
sta cache_value ;Save it.
stz id_disk_flag ;Clear flag.
phx ;Save x.
jsr setup_call ;Do setup parameters and validate.
plx ;Recover x.
bcs exit ;Bad call.
*
* Yes, so jsr to call handler...
*
jsr (cmd_tbl-2,x) ;Do call.
*
* Unlock memory, set drvr_cache back the way it was and exit...
*
exit php ;Save carry.
pha ;Save error code.
jsr unlock_mem ;Unlock memory.
lda cache_value ;Get old value.
sta drvr_cache ;Set cache value.
*** added 2-Dec-92 DAL -- Unlock current_path_tbl_handle, if any
lda current_path_tbl_handle+1 ;check middle word
beq @that_was_easy
lda current_path_tbl_handle+2
pha
lda current_path_tbl_handle
pha
_HUnlock
@that_was_easy
*** end 2-Dec-92
pla ;Recover error code.
plp ;Recover carry. Error?
bcs error_exit ;Yep.
lda #no_error ;No, so get no error code.
jml sys_exit ;Exit to GS/OS.
*
* We're reporting an error.
* Before exiting to SCM, put the error priority in the hi byte of the error code.
*
error_exit ora error_priority ;put error priority in hi byte
jml sys_exit ;exit to GS/OS
ENDP
eject
******************************************************************************
*
* Name: sys_call
*
* Description: Entry point for all FST system calls. Called by GS/OS only.
*
* Created: Oct 6, 1987
* Modified: Oct 6, 1987
* Author: Bryan Atsatt
*
* Entry: jsl
*
* Input: A = undefined
* X = call number times 2
* Y = class number times 2
* P = nvmxdizc
* ..000...
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* Exit: rtl
*
* Uses: Everything!
*
******************************************************************************
system_call proc
with data
*
* Setup environment...
*
phk ;Setup our bank register.
plb
*
* Call # valid?
*
cpx #max_sys+1 ;In range?
bcc valid ;Yep.
lda #bad_system_call ;Nope, get error code.
jmp my_sys_exit ;Unlock mem and exit w/carry set.
*
* Jump to call handler...
*
valid jmp (sys_tbl-2,x) ;Yes, so do it.
ENDP
eject
******************************************************************************
*
* Name: startup
*
* Description: Gets a buffer from GIM to be used as a general io buffer, and
* a buffer for the file_type_map and copies the default map into
* it. Also initializes log_blk_size and real_log_size.
*
* Created: Oct 6, 1987
* Modified: Mar 28, 1988
* Author: Bryan Atsatt
*
* Entry: jmp
*
* Input: A = undefined
* X = call number times 2
* Y = class number times 2
* P = nvmxdizc
* ..000...
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
*
* io_buffer_vp ;vp for io_buffer.
* map_buffer_vp ;vp for map_buffer.
*
* Exit: rtl
*
* Uses: io_buffer_vp
* map_buffer_vp
* temp1
* log_blk_size
* real_log_size
* alloc_seg (sub)
*
******************************************************************************
startup proc
with data
*
* Get memory for io_buffer and save vp...
*
lda #Sector_size ;Get size of sector.
jsr alloc_seg ;Get a hunk that size.
lda #out_of_mem ;Get error code in case full.
bcs exit ;Error, so exit with carry set.
stx io_buffer_vp ;Save it.
sty io_buffer_vp+2
*
* Get memory for map_buffer and save vp...
*
lda default_map ;Get size from default_map.
jsr alloc_seg ;Get a hunk that size.
lda #out_of_mem ;Get error code in case full.
bcs exit ;Error, so exit with carry set.
stx map_buffer_vp ;Save it.
sty map_buffer_vp+2
*
* Copy default map into map buffer...
*
jsl deref ;Dereference vp.
stx map_ptr ;Save pointer.
sty map_ptr+2
longa off ;Set 8 bit A.
sep #$20
ldy default_map ;Get map size.
copy_loop dey ;Done all?
bmi restore_a ;Yep.
lda default_map,y ;Nope, get byte.
sta [map_ptr],y ;Put it in buffer.
bra copy_loop ;And loop.
longa on ;Restore 16 bit A.
restore_a rep #$20
*
* Initialize log_blk_size and real_log_size...
*
lda #sector_size ;Get sector size (2k).
sta log_blk_size ;Init log_blk_size.
sta real_log_size ;Init real_log_size.
*
* Exit with no error...
*
clc ;Exit with no error.
exit rtl
ENDP
eject
******************************************************************************
*
* Name: shutdown
*
* Description: Releases 2k io_buffer and unlocks memory.
*
* Created: Oct 6, 1987
* Modified: Oct 6, 1987
* Author: Bryan Atsatt
*
* Entry: jmp
*
* Input: A = undefined
* X = call number times 2
* Y = class number times 2
* P = nvmxdizc
* ..000...
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
*
* Exit: rtl
*
* Uses: io_buffer_vp
*
******************************************************************************
shutdown proc
with data
*
* Are we doing a warm shutdown? Do nothing if so...
*
clc ;Precondition to no error.
lda >warm_cold_flag ;Get flag. Warm shutdown?
bne exit ;Yes, so do nothing.
*
* Release memory...
*
ldx io_buffer_vp ;Get virtual pointer.
ldy io_buffer_vp+2
jsr release_seg ;Free it up.
*
* Unlock memory and exit...
*
entry my_sys_exit
my_sys_exit ;
php ;Save carry.
pha ;Save error code.
jsr unlock_mem ;Unlock memory.
pla ;Recover error code.
plp ;Recover carry.
exit rtl ;Pass any errors back to Mike & Jim.
ENDP
*** added 2-Dec-92 DAL -- modeled after HFS FST
eject
******************************************************************************
*
* Name: kill_vcr
*
* Description: This routine is called by SCM when a VCR is being released.
*
* Entry: jmp
*
* Input: A = undefined
* X = call number times 2
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K (??? I don't think so --DAL)
*
* <vcr_ptr - ptr to vcr
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Exit: rtl
*
* Uses: all registers
*
* Called by: sys_entry
*
* Calls: DisposeHandle (Memory Manager)
*
******************************************************************************
kill_vcr PROC
with data
phk
plb ;SCM assumes we munge DBR
*
* Dispose of the Path Table Handle, if any
*
ldy #vcr_path_tbl_handle+1 ;check middle word ($0000=no handle)
lda [vcr_ptr],y
clc ;anticipate no error
beq done
ldy #vcr_path_tbl_handle+2 ;get offset path table handle, high word
lda [vcr_ptr],y
pha
dey
dey
lda [vcr_ptr],y ;get low word of handle
pha
_DisposeHandle
*
* If we just disposed of our current_path_tbl_handle, zero it out so we
* don't accidentally try to unlock it again.
*
php
pha
ldy #vcr_path_tbl_handle+2
lda [vcr_ptr],y
cmp current_path_tbl_handle+2
bne @not_same
dey
dey
lda [vcr_ptr],y
cmp current_path_tbl_handle
bne @not_same
stz current_path_tbl_handle+2
stz current_path_tbl_handle
@not_same pla
plp
done rtl ;return any errors to SCM
EndP
*** end 2-Dec-92
eject
******************************************************************************
*
* HERE ARE THE EASY-TO-HANDLE APPLICATION & SYSTEM CALLS
*
******************************************************************************
easy_calls proc
with data
export INVALID_OP
invalid_op ;
lda #invalid_fst_op ;Get invalid op error.
sec ;Indicate error.
rts ;Exit.
export CMD_ERROR
cmd_error ;
lda #bad_system_call ;Get bad call error.
sec ;Indicate error.
rts ;Exit.
export NOP
nop ;
clc ;Indicate no error.
rts ;Exit.
export WP_ERROR
wp_error ;
lda #drvr_wr_prot ;Get write-protect error.
sec ;Indicate error.
rts ;Exit.
export CLC_RTL
clc_rtl ;
clc ;Indicate no error.
rtl ;Exit.
ENDP
eject
******************************************************************************
*
* Name: setup_call
*
* Description: This routine is called at the start of each system call to
* setup parameters and check the validity of the call. If a
* VCR is used by the call and the media is swapped out, the
* system mount routine will be called.
*
* Also locks down all GS/OS managed memory.
*
* Created: Oct 6, 1987
* Modified: Mar 5, 1991
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = two times the call #.
* Y = two times the class #.
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = class of call, or error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0 if no error.
* 1 if error
* B = K
*
* call call number.
* class call class.
* trans_call translated call #.
* io_buffer points to 2k buffer.
* my_pblk points past to 1st param.
* my_vcr points to vcr, if used, else 00.
* path_table points to path table (if vcr used)
* log_blk_size size of block (if vcr used)
* real_log_size same as log_blk_size
* path_table_size size of path table (if vcr used)
* my_fcr points to fcr (if used).
* pcount pcount for call (0 if class 0).
* ref_num file reference number (if present).
* path_ptr pointer to pathname (if present).
* volume_name holds volume name (if pathname present).
* file_name holds file name (if pathname present).
* name_count # of names in pathname (if pathname present).
* name_offsets offsets to names in pathname (if present).
* dev_name pointer to device name (if present).
* request_access access permissions (if present).
* resource_num resource number (if present).
* data_buffer pointer to users data buffer (if present).
* request_count read count (if present).
* cache_priority cache value (if present, 0 if not).
* position file mark (if present).
* base base flag (if present).
* displacement displacement (if present).
*
* Exit: rts
*
* Uses: flags
* max_pcount
* min_pcount
* all storage above
* get_input (sub)
* parse_path (sub)
* mount_volume (sub)
*
* Each call has a one word entry in the table with the following
* format:
*
* 1 - Max PCount for the call
* 2 - Min PCount for the call
* 3 - Pathnames used by call
* 4 - Volume control record used
* 5 - File control record used
*
* |5|4|3| 2 | 1 |
* _________|_|_|_|_____|_________|
* | | | | | | | | | | | | | | | | |
* |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
* | | |
* 1 6 0 8 0 0
*
******************************************************************************
setup_call proc
with data
*
* Init some variables...
*
stz input_error ;Clear error.
stz name_count ;Clear it.
stz base ;Clear it.
stz interleave_size ;Clear it.
stz interleave_skip ;Clear it.
stz error_priority ;error priority is 0
*
* Set call and class...
*
txa ;Divide call # by 2.
lsr a
sta call ;Set current call.
tya ;Divide class # by 2.
lsr a
sta class ;Set current class.
*
* Is class valid?
*
cmp #max_class ;Valid?
beq class_ok ;Yep.
bcc class_ok ;Yep.
*
* No, so exit with invalid_class error...
*
lda #invalid_class ;Nope, so get error code.
sec ;Indicate error.
rts ;Exit.
*
* Yes, get translated call #. Exit if this is not a call I handle...
*
class_ok ldy #call_count ;Point to end of list.
call_loop lda handled_calls,y ;Get call #.
and #$00ff ;Clear high byte.
cmp call ;Is this the call?
beq valid_call ;Yep.
dey ;Nope, checked all?
bpl call_loop ;No, so loop.
clc ;Yes, so exit with carry clear.
rts
valid_call tya ;Get call #.
asl a ;Multiply by 2.
sta trans_call ;Save it.
tax ;Put in X.
*
* Get entry from start_flags and save it in flags.
*
lda start_flags,x ;Get flags word.
sta flags ;Save it.
*
* Set max_pcount and min_pcount...
*
and #max_mask ;Isolate max_pcount.
sta max_pcount ;Save it.
lda flags ;Get flags.
and #min_mask ;Isolate min_pcount.
asl a ;Get it in low byte.
asl a
asl a
xba
sta min_pcount ;Save it.
*
* Set my_pblk = param_blk_ptr...
*
lda param_blk_ptr ;Copy to my_pblk.
sta my_pblk
lda param_blk_ptr+2
sta my_pblk+2
*
* Get input parameters. Any Errors?
*
jsr get_input ;Get input. Any errors?
bcc input_ok ;Nope.
*
* Yep. If this call does not use a pathname, then exit with the error.
* If it does, check to see if it is a bouncing error and if so, exit with
* the error. If not, save error in input_error and continue...
*
tax ;Save error code.
lda flags ;Path used by call?
and #path_used
beq send_error ;Nope.
ldy #len_bounce_tbl ;Yes, is it a bouncing error?
txa
bounce_loop cmp bounce_errors,y
beq send_error ;Yep.
dey
dey
bpl bounce_loop
stx input_error ;Nope, save error.
bra input_ok ;And continue.
send_error txa ;Recover error code.
sec ;Indicate error.
rts ;Exit.
*
* Nope, get pointer to io_buffer and map_buffer, and lock memory...
*
input_ok ldx io_buffer_vp ;Get vp.
ldy io_buffer_vp+2
jsl deref ;Dereference it.
stx io_buffer ;Save pointer.
sty io_buffer+2
ldx map_buffer_vp ;Get vp.
ldy map_buffer_vp+2
jsl deref ;Dereference it.
stx map_buffer_ptr ;Save pointer.
sty map_buffer_ptr+2
jsl lock_mem ;Lock all memory.
*
* Do we need a VCR?
*
stz my_vcr ;Clear my_vcr in case don't need it.
stz my_vcr+2
lda flags ;Get flags.
and #vcr_used ;Need a vcr?
beq check_fcr ;Nope.
*
* Yes, so setup pointer to vcr and call setup_vcr...
*
ldx vcr_ptr ;Get VP from zp.
ldy vcr_ptr+2
jsl deref ;Dereference it.
stx my_vcr ;Save pointer.
sty my_vcr+2
jsr setup_vcr ;Get some of the vcr variables.
*
* Do we need a FCR?
*
check_fcr lda flags ;Get flags.
and #fcr_used ;Need a vcr?
beq check_path ;Nope.
*
* Yes, setup pointer to fcr...
*
ldx fcr_ptr ;Get VP from zp.
ldy fcr_ptr+2
jsl deref ;Dereference it.
stx my_fcr ;Save pointer.
sty my_fcr+2
*
* Do we need a pathname?
*
check_path lda flags ;Get flags.
and #path_used ;Need a pathname?
bne need_path ;Yes.
*
* Nope, so exit with carry clear...
*
clc ;Indicate no error.
rts ;exit.
*
* Yes, exit through parse_path...
*
need_path jmp parse_path ;Parse pathname.
ENDP
eject
******************************************************************************
*
* Name: activate_vcr
*
* Description: Marks vcr as active, gets new log_blk_size and real_log_size,
* sets pointer to the path table and gets the size of the path
* table. Also sets state_flag and calls set_file_system.
*
* NOTE: Contains an alternate entry point!
*
* Created: Oct 21, 1987
* Modified: Mar 28, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined.
* P = nvmxdizc
* ..000...
* B = K
*
* my_vcr points to current vcr.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* log_blk_size ;size of blocks on this volume
* real_log_size ;copy of log_blk_size
* path_table_size ;size of path table
* path_table ;pointer to path table
* state_flag ;b0 = 1 if ISO version of High Sierra.
* ;b1 = 1 if Apple Extensions disc.
* ;b2 = 1 if ProDOS Transformation required.
*
* Exit: rts
*
* Uses: all registers
* set_file_system (sub)
*
******************************************************************************
activate_vcr proc
with data
*
* Mark vcr as active...
*
ldy #vcr_status ;Get offset to status.
lda [my_vcr],y ;Get status.
and #vcr_swapped_in ;Clear swapped bit.
sta [my_vcr],y ;Save it.
*
* Set new log_blk_size and real_log_size ...
*
export SETUP_VCR
setup_vcr ;
ldy #vcr_block_size ;Get offset to block size.
lda [my_vcr],y ;Get size.
sta log_blk_size ;Set logical block size.
sta real_log_size ;Set real logical block size.
*
* Set path_table_size...
*
ldy #vcr_path_size ;Get offset to path table size.
lda [my_vcr],y ;Get size.
sta path_table_size ;Set new size.
*
* Make a pointer to path table...
*
*** changed 2-Dec-92 DAL
; clc ;Add offset to path table.
; lda #vcr_path_table
; adc my_vcr
; sta path_table
; lda #0
; adc my_vcr+2
; sta path_table+2
; use path_ptr as temporary direct page (restore when done)
pei <path_ptr+2
pei <path_ptr
ldy #vcr_path_tbl_handle+2
lda [my_vcr],y
sta current_path_tbl_handle+2
sta <path_ptr+2
dey
dey
lda [my_vcr],y
sta current_path_tbl_handle
sta <path_ptr
ldy #4
lda [<path_ptr],y
ora #$8000 ;brutally lock the handle
sta [<path_ptr],y
dey
dey
lda [<path_ptr],y
sta path_table+2
lda [<path_ptr]
sta path_table
pla
sta <path_ptr
pla
sta <path_ptr+2
*** end 2-Dec-92
*
* Copy vcr_state_flag to state_flag and exit thru set_file_system...
*
ldy #vcr_state_flag ;Get offset to flag.
lda [my_vcr],y ;Get flag.
sta state_flag ;Save flag.
jmp set_file_system ;Exit thru set_file_system.
ENDP
eject
******************************************************************************
*
* Name: get_input
*
* Description: Moves input parameters from callers parameter list to my
* storage area. Validates the parameters whose range is known.
* All fields which are not defined for the call will be zero.
*
* Created: Oct 14, 1987
* Modified: Oct 14, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined.
* P = nvmxdizc
* ..000...
* B = K
*
* class contains class #.
* trans_call contains translated call #.
*
* Output: A = undefined, or error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0 if no error.
* 1 if error
* B = K
*
* pcount pcount for call (0 if class 0).
* ref_num file reference number (if present).
* pathname pointer to pathname (if present).
* dev_name pointer to device name (if present).
* request_access access permissions (if present).
* resource_num resource number (if present).
* data_buffer pointer to users data buffer (if present).
* request_count read count (if present).
* cache_priority cache value (if present, 0 if not).
* position file mark (if present).
* base base flag (if present).
* displacement displacement (if present).
*
* Exit: rts
*
* Uses: all registers
* process_fields
*
******************************************************************************
get_input proc
with data
*
* Clear input variables...
*
ldy #input_len ;Point to last variable.
lda #0 ;Get zero.
clear_loop sta pcount,y ;Clear variable.
dey ;Done all?
dey
bpl clear_loop ;No, so loop.
*
* Initialize pcount to maximum value in case this is a class 0 call
* (see process_fields for more info)...
*
lda #$7fff ;Get max value.
sta pcount ;Set pcount.
*
* Process input fields and exit...
*
lda #input ;Select input.
jmp process_fields ;Process fields.
ENDP
eject
******************************************************************************
*
* Name: send_output
*
* Description: Sends output fields to callers parameter list.
*
* Created: Oct 15, 1987
* Modified: Oct 15, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined.
* P = nvmxdizc
* ..000...
* B = K
*
* pcount
* class
* trans_call
*
* Output: A = undefined, or error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0 if no error.
* 1 if error
* B = K
*
* Exit: rts
*
* Uses: all registers
* process_fields
*
******************************************************************************
send_output proc
with data
*
* Process output fields and exit...
*
lda #output ;Select output.
jmp process_fields ;Process 'em.
ENDP
eject
******************************************************************************
*
* Name: process_fields
*
* Description: This routine calls all of the field handler subroutines listed
* in the field list for the current call and class.
*
* Created: Oct 14, 1987
* Modified: Oct 14, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = 0 if requesting input, $4000 if requesting output.
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* class
* trans_call
* pcount ;must be initialized > max pcount!
*
* Output: A = error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0 if no error.
* 1 if error
* B = K
*
* Exit: rts
*
* Uses: all registers
* list_ptr
* io_flag
* field_count
* field_num
* field_flags
*
* The field list is a list of field flags words which have the
* following format:
*
* 1 - Field number times two
* 2 - Field offset
* 3 - I/O flag: 0 = input, 1 = output.
* 4 - Terminator: 1 = last entry in list.
*
* |4|3| 2 | 1 |
* |_|_|___________|_______________|
* | | | | | | | | | | | | | | | | |
* |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
* | | |
* 1 6 0 8 0 0
*
******************************************************************************
process_fields proc
with data
*
* Save requested direction and set list_ptr to point to correct list...
*
sta io_flag ;Save direction flag.
ldx trans_call ;Get translated call #.
lda class0,x ;Get class 0 address.
ldy class ;Is this a class 0 call?
beq set_ptr ;Yep.
lda class1,x ;Nope, so get class 1 address.
set_ptr sta list_ptr ;Set pointer.
*
* Set field_count = pcount. Pcount must be initialized at call start
* way out of range in case this is a class 0 call (if it's a class 1 call,
* the pcount field handler will set field_count equal to pcount).
* Field_count is used to control the number of fields to process...
*
lda pcount ;Copy pcount to field_count.
sta field_count
*
* Init field number...
*
lets_go ldy #0 ;Init offset.
*
* Save field number, get field flags and save it...
*
input_loop sty field_num ;Save field number.
lda (list_ptr),y ;Get field flags.
sta field_flags ;Save it.
*
* Does the i/o flag match the requested direction?
*
and #io_mask ;Isolate flag.
cmp io_flag ;Does it match request?
bne next_field ;Nope, so skip it.
*
* Yes, get field offset in Y and jsr to selected field handler...
*
lda field_flags ;Recover flags.
and #offset_mask ;Isolate offset.
xba ;Put in low byte.
tay ;Put in Y.
lda field_flags ;Recover flags.
and #field_mask ;Isolate field.
tax ;Use as index.
jsr (handlers,x) ;Execute handler.
bcs exit ;Error, so exit.
*
* Bump field number...
*
next_field ldy field_num ;Get field number.
iny ;Bump it.
iny
*
* Are we done with list?
*
lda field_flags ;Done with list?
bmi done ;Yes.
*
* Nope, have we used up all the fields present?
*
dec field_count ;Done all fields?
bpl input_loop ;Nope, so loop.
*
* Yes, so exit with carry clear...
*
done clc ;Indicate no errors.
exit rts ;Exit to caller.
ENDP
eject
******************************************************************************
*
* Name: field_handlers
*
* Description: This section is a collection of subroutines which handle
* each of the fields in the parameter lists. These routines
* should only be called by process_fields...
*
* Note: The h_vol_name routine is called directly from the "volume"
* procedure if id_disk has returned a dup_volume error. This is
* done so that the "vol_name" output parameter will be set up even
* though an error is being returned. This is the only case in
* which a parameter handler is called directly. 2/7/91 CAE
*
* Created: Oct 14, 1987
* Modified: June 30, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* io_flag
* trans_call
*
* Output: A = error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0 if no error.
* 1 if error
* B = K
*
* Exit: rts
*
* Uses: all registers
*
******************************************************************************
field_handlers proc
with data
*
* PCOUNT Field Handler: Input (w)
*
export H_PCOUNT
h_pcount ;
lda [my_pblk],y ;Get pcount.
cmp max_pcount ;< max?
bcs bad_pcount ;No, so bad.
cmp min_pcount ;>= min?
bcc bad_pcount ;No, so bad.
sta pcount ;Yep, so save it.
sta field_count ;Set count as well.
clc ;Indicate no error.
rts ;Exit.
bad_pcount lda #invalid_pcount ;No, get error code.
sec ;Set carry.
rts ;Exit.
*
* REF_NUM Field Handler: Input/Output (w)
*
export H_REF_NUM
h_ref_num ;
lda field_flags ;Get flags word.
and #io_mask ;Is input?
bne ref_out ;Nope.
lda [my_pblk],y ;Yes, get word.
sta ref_num ;Set parameter.
bra ref_exit ;Exit.
ref_out lda ref_num ;Get reference number.
sta [my_pblk],y ;Send it.
ref_exit clc ;Indicate ok.
rts ;Exit.
*
* PATHNAME Field Handler: Input (ptr)
*
export H_PATHNAME
h_pathname ;
clc ;Do nothing.
rts ;Exit.
*
* DEV_NAME Field Handler: Input (ptr)
*
export H_DEV_NAME
h_dev_name ;
clc ;Do nothing.
rts ;Exit.
*
* REQUEST_ACCESS Field Handler: Input (w)
*
export H_REQUEST_ACCESS
h_request_access ;
lda [my_pblk],y ;Get word.
beq access_ok ;Zero, so ok.
cmp #read_access ;Is read only?
bne access_bad ;Nope, so bad.
access_ok clc ;Indicate ok.
rts ;Exit.
access_bad lda #invalid_access ;No, so error.
sec ;Indicate error.
rts ;Exit.
*
* RESOURCE_NUM Field Handler: Input (w)
*
export H_RESOURCE_NUM
h_resource_num ;
lda [my_pblk],y ;Get word.
sta resource_num ;Save it.
clc ;No error.
rts ;Exit.
*
* DATA_BUFFER Field Handler: Input (ptr)
*
export H_DATA_BUFFER
h_data_buffer ;
lda [my_pblk],y ;Get low word of ptr.
sta data_buffer ;Save it.
iny ;Bump offset.
iny
lda [my_pblk],y ;Get high word of ptr.
and #$00ff ;Clear high byte.
sta data_buffer+2 ;Save it.
clc ;Indicate ok.
rts ;Exit.
*
* REQUEST_COUNT Field Handler: Input (lw)
*
export H_REQUEST_COUNT
h_request_count ;
lda [my_pblk],y ;Get low word of count.
sta request_count ;Save it.
iny ;Bump offset.
iny
lda [my_pblk],y ;Get high word of count.
sta request_count+2 ;Save it.
clc ;Indicate ok.
rts ;Exit.
*
* CACHE_PRIORITY Field Handler: Input (w)
*
export H_CACHE_PRIORITY
h_cache_priority ;
lda [my_pblk],y ;Get word.
beq good_priority ;Ok.
cmp #user_cache_val ;Valid priority?
bne bad_priority ;Nope.
good_priority sta cache_priority ;Save it.
clc ;No error.
rts ;Exit.
bad_priority lda #parm_range_err ;Get error code.
sec ;Indicate error.
rts ;Exit.
*
* POSITION Field Handler: Output (lw)
*
export H_POSITION
h_position ;
lda position ;Get low word.
ldx position+2 ;Get high word.
brl send_long_word ;Send it.
*
* BASE Field Handler: Input (w)
*
export H_BASE
h_base ;
lda [my_pblk],y ;Get word.
cmp #max_base+1 ;In range?
bcs bad_base ;Nope.
sta base ;Yes, save it.
rts ;Exit.
bad_base lda #parm_range_err ;Get error code.
rts ;Exit.
*
* DISPLACEMENT Field Handler: Input (lw)
*
export H_DISPLACEMENT
h_displacement ;
lda [my_pblk],y ;Get low word.
sta displacement ;Save it.
iny ;Bump offset.
iny
lda [my_pblk],y ;Get high word.
sta displacement+2 ;Save it.
clc ;Indicate ok.
rts ;Exit.
*
* ACCESS Field Handler: Output (w)
*
export H_ACCESS
h_access ;
ldx dir_file_flags ;Get offset to file flags.
lda dir_record_0,x ;Get flags.
and #1 ;Isolate existence bit.
asl a ;Shift it to invisible pos.
asl a
ora #full_access ;Add full access bits.
brl send_word ;Send it.
*
* FILE_TYPE Field Handler: Output (w)
*
export H_FILE_TYPE
h_file_type ;
ldx dir_file_flags ;Get offset to file flags.
lda dir_record_0,x ;Get flags.
ldx #file_type_dir ;Init file type to directory.
and #dir_mask ;Is it a directory?
bne send_hop ;Yes.
jsr get_ext_type ;Nope, do we have Apple Extensions info?
bcc send_hop ;Yep.
jsr get_file_type ;Nope, use map.
send_hop txa ;Put type in A.
brl send_word ;Send it.
*
* AUX_TYPE Field Handler: Output (lw)
*
export H_AUX_TYPE
h_aux_type ;
lda call ;Yes. Is this a get_file_info call?
cmp #get_file_call
bne check_apple ;Nope.
lda storage_type ;Yes, looking at volume directory?
cmp #type_vol_dir
bne check_apple ;Nope.
lda class ;Yes, is it a class zero call?
beq h_total_blocks ;Yes, so send total blocks.
send_zero brl h_free_blocks ;Nope, send zero long word.
check_apple jsr get_ext_type ;Do we have Apple Extensions info?
bcs send_zero ;Nope.
ldx #0000 ;Yep, clear high word.
brl send_long_word ;Send it.
*
* TOTAL_BLOCKS Field Handler: Output (lw)
*
export H_TOTAL_BLOCKS
h_total_blocks ;
phy ;Save offset.
ldy #vcr_total_blks+2 ;Get offset to high word.
lda [my_vcr],y ;Get high word.
tax ;Save it.
ldy #vcr_total_blks ;Get offset to low word.
lda [my_vcr],y ;Get low word.
ply ;Recover offset.
brl send_long_word ;Send it.
*
* STORAGE_TYPE Field Handler: Output (w)
*
export H_STORAGE_TYPE
h_storage_type ;
lda storage_type ;Get type.
brl send_word ;Send it.
*
* CREATE_DATE Field Handler: Output (w)
*
* NOTE: This must be called before mod_date, or mod_time
* so that the call to pro_date_time will occur!
*
export H_CREATE_DATE
h_create_date ;
phy ;Save offset.
jsr pro_date_time ;Get date & time.
ply ;Recover offset.
*
* MOD_DATE Field Handler: Output (w)
*
export H_MOD_DATE
h_mod_date ;
lda prodos_time ;Get year/mon/day
brl send_word ;Send it.
*
* CREATE_TIME Field Handler: Output (w)
* MOD_TIME Field Handler: Output (w)
*
export H_CREATE_TIME
h_create_time ;
export H_MOD_TIME
h_mod_time ;
lda prodos_time+2 ;Get hour/minute.
brl send_word ;Send it.
*
* BLOCKS_USED Field Handler: Output (lw)
*
export H_BLOCKS_USED
h_blocks_used ;
lda call ;Is this a get_dir_entry call?
cmp #get_dir_call
beq send_used ;Yes, so send blocks_used.
ldx storage_type ;Nope, is this a directory?
cpx #type_extended+1
bcc send_used ;Nope, so send blocks_used.
cmp #get_file_call ;Yes, is it a get_file_info call?
bne send_zero ;Nope, so this field undefined.
lda class ;Yes, is it a class zero call?
bne send_zero ;Nope, so this field undefined.
cpx #type_vol_dir ;Yes, is this the volume directory?
bne send_used ;Nope, so send blocks_used.
bra h_total_blocks ;Yes, so return total_blocks.
send_used lda blocks_used ;Get low word.
ldx blocks_used+2 ;Get high word.
bra send_long_word ;Send it.
*
* CREATE_DATE_TIME Field Handler: Output (4w)
* MOD_DATE_TIME Field Handler: Output (4w)
*
export H_CREATE_DATE_TIME
h_create_date_time ;
export H_MOD_DATE_TIME
h_mod_date_time ;
phy ;Save offset.
jsr get_date_time ;Get date & time.
ply ;Recover offset.
ldx #0 ;Init offset.
time_loop lda create_date_time,x ;Get word.
sta [my_pblk],y ;Send it.
iny ;Bump offsets.
iny
inx
inx
cpx #8 ;Done all?
bne time_loop ;No, so loop.
clc ;Yes, so clear carry.
rts ;Exit.
*
* OPTION_LIST Field Handler: Output (ptr)
*
export H_OPTION_LIST
h_option_list ;
lda [my_pblk],y ;Get low word of pointer.
tax ;Save it.
iny ;Bump offset.
iny
lda [my_pblk],y ;Get high byte of pointer.
and #$00ff ;Clear high byte.
jmp get_option_list ;Go get it.
*
* EOF Field Handler: Output (lw)
*
export H_EOF
h_eof ;
lda eof ;Get low word.
ldx eof+2 ;Get high word.
bra send_long_word ;Send it.
*
* RESOURCE_EOF Field Handler: Output (lw)
*
export H_RESOURCE_EOF
h_resource_eof ;
lda resource_eof ;Get low word.
ldx resource_eof+2 ;Get high word.
bra send_long_word ;Send it.
*
* RESOURCE_BLOCKS Field Handler: Output (lw)
*
export H_RESOURCE_BLOCKS
h_resource_blocks ;
lda resource_blocks ;Get low word.
ldx resource_blocks+2 ;Get high word.
bra send_long_word ;Send it.
*
* VOL_NAME Field Handler: Output (ptr)
*
export H_VOL_NAME
h_vol_name ;
phy ;Save offset.
lda #$2e5f ;Replace underscores with periods.
ldx #gstring
ldy #^gstring
jsr transform_name
ldx #gstring ;Point to volume name.
ldy #^gstring
jsr add_separator ;Add separator.
ply ;Recover offset.
lda class ;Is this a class 0 call?
bne send_name ;Nope.
lda gstring ;Yep, get length.
cmp #prodos_name_ln ;Legal length?
bcc send_name ;Yep.
lda #drvr_off_line ;Nope, return offline error.
rts ;Exit.
send_name ;
lda [my_pblk],y ;Get low word of pointer.
sta output_string ;Set low word.
iny ;Bump offset.
iny
lda [my_pblk],y ;Get high word of pointer.
and #$00ff ;Clear high byte.
sta output_string+2 ;Set high word.
ldx #gstring ;Point to volume name.
ldy #^gstring
jmp send_gstring ;Send it out.
*
* FREE_BLOCKS Field Handler: Output (lw)
*
export H_FREE_BLOCKS
h_free_blocks ;
ldx #0000 ;Always = 0.
txa
send_long_word sta [my_pblk],y ;Send low word.
iny ;Bump offset.
iny
txa ;Get high word.
send_word sta [my_pblk],y ;Send it.
clc ;Indicate no error.
rts ;Exit.
*
* FILE_SYS_ID Field Handler: Output (w)
*
export H_FILE_SYS_ID
h_file_sys_id ;
ldx #hs_id ;Get High Sierra Id.
lda state_flag ;Get flag.
and #iso_bit ;Iso?
beq send_id ;Nope.
ldx #iso_id ;Yes, change id.
send_id txa ;
bra send_word ;Send it.
*
* BLOCK_SIZE Field Handler: Output (w)
*
export H_BLOCK_SIZE
h_block_size ;
tyx ;Save offset.
ldy #vcr_block_size ;Get offset to size.
lda [my_vcr],y ;Get word
txy ;Recover offset.
bra send_word ;Send it.
*
* TRANSFER_COUNT Field Handler: Output (lw)
*
export H_TRANSFER_COUNT
h_transfer_count ;
lda transfer_count ;Get low word.
ldx transfer_count+2 ;Get high word.
bra send_long_word ;Send it.
*
* ENTRY_NUM Field Handler: Output (w)
*
export H_ENTRY_NUM
h_entry_num ;
lda entry_num ;Get entry #.
bra send_word ;Send it.
*
* DEV_NUMBER Field Handler: Output (w)
*
export H_DEV_NUMBER
h_dev_number ;
lda dev_number ;Get number
sta [my_pblk],y ;Send it.
clc ;No error.
rts ;Exit.
*
* NAME Field Handler: Output (ptr)
*
export H_NAME
h_name ;
lda dir_record_0+dir_len_fi ;Get length of name.
and #$00ff ;Clear high word.
sta gstring ;Put at start of gstring.
sta file_name ;(Make a copy for get_file_type)
tax ;Put in X.
longa off ;Set 8 bit A.
sep #$20
stz gstring+2,x ;Add zero delimiter.
stz file_name+2,x ;(Make a copy for get_file_type)
name_loop lda dir_record_0+dir_len_fi,x ;Get byte.
sta gstring+1,x ;Put in gstring.
sta file_name+1,x ;(Make a copy for get_file_type)
dex ;Done all?
bne name_loop ;No, so loop.
longa on ;Set 16 bit A.
rep #$20
lda class ;Get class.
pha ;Save it.
inc class ;Make sure we send a class 1 string.
phy ;Save Y.
jsr transform_out ;Transform it if needed.
ply ;Recover Y.
jsr send_name ;Do send.
pla ;Recover class.
sta class ;Restore it.
rts ;Exit.
*
* EXTENDED Field Handler: Output (w)
*
export H_EXTENDED
h_extended ;
lda extended_flag ;Get extended flag.
bra send_word ;Send it.
*
* COMMAND_NUM Field Handler: Input (w)
*
export H_COMMAND_NUM
h_command_num ;
lda [my_pblk],y ;Get command number.
cmp #max_command_num ;Is it in range?
bcs bad_command ;Nope.
sta command_num ;Yes, save it.
rts ;Exit
bad_command lda #parm_range_err ;Get error code.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: add_separator
*
* Description: This routine will insert a class 0 or 1 separator at the
* beginning of the gstring pointed to by X and Y.
*
* Created: Nov 6, 1987
* Modified: Nov 6, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = low byte of pointer to gstring
* Y = high byte of pointer to gstring
* P = nvmxdizc
* ..000...
* B = K
*
* class ;class of call.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Exit: rts
*
* Uses: all registers
* input_string
* length
*
******************************************************************************
add_separator proc
with data
*
* Save pointer, bump string length, and bump pointer...
*
stx input_string ;Save pointer.
sty input_string+2
lda [input_string] ;Get length.
tay ;Put in Y.
inc a ;Bump it.
sta [input_string] ;Save length.
inc input_string ;Bump pointer.
bne shift_it
inc input_string+2
*
* Shift string 1 byte to the right...
*
longa off ;Set 8 bit A.
shift_it sep #$20
shift_loop lda [input_string],y ;Get byte.
iny ;Bump offset.
sta [input_string],y ;Save byte.
dey ;Adjust offset.
dey ;Done all?
bne shift_loop ;No, so loop.
*
* Add separator and exit...
*
lda #separator0 ;Assume class 0.
ldx class ;Is our assumption right?
beq save_it ;Yes.
lda #separator1 ;Nope.
save_it iny ;Point at separator space.
sta [input_string],y ;Insert it.
longa on ;Set 16 bit A.
rep #$20
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: send_gstring
*
* Description: This routine will send a class 0 or 1 output string to the
* users name buffer. Should only be called by a field handler!!
*
* Created: Oct 15, 1987
* Modified: Nov 6, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = low byte of pointer to gstring
* Y = high byte of pointer to gstring
* P = nvmxdizc
* ..000...
* B = K
*
* class ;class of call.
* output_string ;points to output buffer.
*
* Output: A = error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0 if no error.
* 1 if error
* B = K
*
* Exit: rts
*
* Uses: all registers
* input_string
* output_string
* length
*
******************************************************************************
send_gstring proc
with data
*
* Save pointer, get string length, bump pointer by 1...
*
stx input_string ;Save pointer.
sty input_string+2
lda [input_string] ;Get string length in A.
sta length ;Save it.
inc input_string ;Bump pointer.
bne check_class
inc input_string+2
*
* Is this a class 0 call?
*
check_class ldy class ;Class 0?
bne class_1 ;Nope.
*
* Yes, so put a one byte length first and branch to send_string...
*
longa off ;Set 8 bit A.
sep #$20
ldy #0 ;Point to start of output string.
sta [output_string],y ;Put length.
bra send_string ;Continue.
*
* No, put a 1 word length first...
*
longa on ;Make sure 16 bit A.
class_1 ldy #2 ;Point to start of output string.
sta [output_string],y ;Put length word.
*
* Will string fit in caller's buffer?
*
clc ;Adjust for buffer length.
adc #0004
cmp [output_string] ;Will it fit?
bcc adjust ;Yep.
beq adjust ;Yep.
lda #buff_too_small ;No, get error code.
sec ;Indicate error.
rts ;Exit.
*
* Yes, bump pointer past length...
*
longa on ;Set 16 bit mode.
adjust rep #$20
clc ;Add 3 to pointer.
lda #3
adc output_string
sta output_string
lda #0
adc output_string+2
sta output_string+2
longa off ;Set 8 bit A.
sep #$20
*
* Now send the rest of the string and exit...
*
send_string ldy length ;Get length.
send_loop lda [input_string],y ;Get byte.
sta [output_string],y ;Save byte.
dey ;Done all?
bne send_loop ;No, so loop.
longa on ;Yes, restore 16 bit A.
rep #$20
clc ;Indicate ok.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: make_gstring
*
* Description: This routine will make a gstring from a High Sierra format
* string.
*
* Created: Oct 16, 1987
* Modified: Oct 16, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = offset to start of name from io_buffer
* X = undefined
* Y = maximum length of name -1
* P = nvmxdizc
* ..000...
* B = K
*
* io_buffer ;points to base of buffer to which A
* ;and Y are offsets.
*
* Output: A = undefined
* X = undefined
* Y = length of string
* P = nvmxdizc
* ..000..0
*
* B = K
*
* gstring ;holds gstring
*
* Exit: rts
*
* Uses: all registers
* input_string
* gstring
*
******************************************************************************
make_gstring proc
with data
*
* Point input_string to start of string...
*
clc ;Add A to io_buffer.
adc io_buffer
sta input_string ;Save in input_string.
lda #0
adc io_buffer+2
sta input_string+2
*
* Find real length of string. Zero length?
*
longa off ;Set 8 bit A.
sep #$20
length_loop lda [input_string],y ;Get byte.
cmp #space ;Is it a space?
bne hit_end ;No, so found end of string.
dey ;Yes, done all?
bpl length_loop ;Nope, so loop.
*
* Yes, so force to 'UNTITLED'...
*
iny ;Yes, so point to first byte.
un_loop lda untitled_str,y ;Get byte. End of string?
beq end_of_str ;Yes.
sta [input_string],y ;Nope, so stuff it.
iny ;Bump pointer.
bra un_loop ;And loop.
end_of_str dey ;Adjust length.
*
* Put length word in gstring and add null...
*
hit_end iny ;Add 1 to the length.
sty gstring ;Put length word.
lda #0 ;Get null.
sta gstring+2,y ;Add null to end of string.
dey ;Adjust Y.
*
* Now send the rest of the string, put length in Y and exit...
*
send_string lda [input_string],y ;Get byte.
sta gstring+2,y ;Save byte.
dey ;Done all?
bpl send_string ;Nope, so loop.
longa on ;Restore 16 bit A.
rep #$20
ldy gstring ;Get length.
clc ;Indicate ok.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: move_gstring
*
* Description: This routine will move a gstring from the gstring buffer to
* the selected address. No error checking is done on the string
* so be careful!
*
* Created: Oct 21, 1987
* Modified: Oct 21, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = low byte of pointer to destination buffer.
* Y = high byte of pointer to destination buffer.
* P = nvmxdizc
* ..000...
* B = K
*
* gstring contains gstring.
*
* Output: A = undefined
* X = undefined
* Y = length of string
* P = nvmxdizc
* ..000...
*
* B = K
*
* Exit: rts
*
* Uses: all registers
* output_string
* gstring
*
******************************************************************************
move_gstring proc
with data
*
* Save pointer to destination...
*
stx output_string ;Save pointer.
sty output_string+2
*
* Copy length...
*
lda gstring ;Get length.
sta [output_string] ;Move it.
*
* Copy remainder of string and exit...
*
longa off ;Set 8 bit A.
sep #$20
ldy #2 ;Point past length.
move_loop lda gstring,y ;Get byte.
sta [output_string],y ;Move it.
beq exit ;Exit if zero.
iny ;Otherwise point to next.
bra move_loop ;And loop.
longa on ;Set 16 bit A.
exit rep #$20
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: parse_path
*
* Description: Vaidates string, then copies first name in path to volume_name
* and last name to file_name (both in gstring format). Sets
* name_count to # of names found, and puts offsets to start of
* each name in name_offsets. If there is only a device name,
* will exit with name_count = 0.
*
* Created: Oct 21, 1987
* Modified: July 14, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* path1_ptr ;points to pathname.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* volume_name ;volume name in gstring format.
* file_name ;file name in gstring format.
* name_count ;# of names found. 0 if device only.
* name_offsets ;list of offsets to start of names.
*
* Uses: All registers
* path_ptr
* volume_name
* file_name
* name_count
* name_offsets
* transform_name (sub)
*
******************************************************************************
parse_path proc
with data
*
* Make sure that pathname 1 is defined and that its span is in range...
*
lda path_flag ;Get pathname flags.
and #path1_mask ;Is pathname 1 defined?
bne have_path ; yes, go look at it (18-Dec-91 MSD)
; This code commented out 18-Dec-91 MSD. Checking of the span was moved to
; process_path.
; beq check_device ;No, so see if we have a device #.
;
; lda span1 ;Get span1.
; cmp #32 ;In range?
; bcc have_path ;Yes.
; bra bad_path ;Nope, so bad.
*
* There is no pathname. If we have a device # then exit with name_count = 0,
* otherwise exit with a bad path error...
*
check_device stz name_count ;Clear count.
lda dev_num ;Do we have a device #?
beq bad_path ;Nope, so error.
clc ;Yes, so exit with carry clear.
rts
*
* We have a pathname, set path_ptr...
*
have_path lda path1_ptr ;Copy path1_ptr to path_ptr.
sta path_ptr
lda path1_ptr+2
sta path_ptr+2
*
* Validate string and build name_offsets list. Valid string?
*
ldy #3 ;Point past length & first separator.
ldx #0 ;Init name count.
lda dev_num ;Do we have a device #?
beq set_eight ;Nope.
inx ;Yes, so bump name count.
dey ;Adjust for no separator.
longa off ;Set 8 bit A.
set_eight sep #$20
new_name tya ;Get offset.
sta name_offsets,x ;Put in list.
check_loop cpy #255 ;Too many characters?
beq bad_path ;Yes, so bad.
lda [path_ptr],y ;No, get byte. End of string?
beq end_of_string ;Yep, so ok.
cmp #separator1 ;No, hit separator?
beq separator ;Yes.
cmp #'.' ;No, is this a valid character?
beq next_char ;Yes.
cmp #'0' ;Maybe.
bcc bad_path ;Nope.
cmp #'9'+1 ;Maybe.
bcc next_char ;Yes.
cmp #';' ;Maybe.
beq next_char ;Yes.
cmp #'A' ;Maybe.
bcc bad_path ;Nope.
cmp #'Z'+1 ;Maybe.
bcc next_char ;Yes.
cmp #'_' ;Maybe.
bne bad_path ;Nope.
next_char iny ;Point to next character.
bra check_loop ;Loop.
separator iny ;Point to next character.
inx ;Bump name count.
cpx #max_names ;Too many names?
bne new_name ;Nope, so loop.
*
* Nope, exit with bad path error...
*
longa on ;Set 16 bit A.
bad_path rep #$20
lda #bad_path_syntax ;Nope, get error code.
sec ;Indicate error.
rts ;Exit.
*
* Yes, save name_count and move first name to volume_name...
*
longa off ;Make sure 8 bit A.
end_of_string inx ;Zero adjust.
stx name_count ;Save count.
lda name_offsets ;Get offset to first name.
tay
ldx #0 ;Get offset into volume name.
copy_loop1 lda [path_ptr],y ;Get byte. End of string?
beq end_name_1 ;Yes.
cmp #separator1 ;End of name?
beq end_name_1 ;Yes.
sta volume_name+2,x ;No, put byte in volume name.
inx ;Bump offsets.
iny
; Begin 18-Dec-91 MSD
cpx #32 ; volume name too long?
bge bad_path ; yes, so couldn't be ours anyway
; End 18-Dec-91 MSD
bra copy_loop1 ;Loop.
end_name_1 lda #0 ;Terminate string.
sta volume_name+2,x
stx volume_name ;Put length word.
*
* Is there another name?
*
ldx name_count ;Get name count.
cpx #1 ;More than 1?
beq done ;Nope, so done.
*
* Yes, move last one to file_name...
*
dex ;Point to last offset.
lda name_offsets,x ;Get offset to last name.
tay
ldx #0 ;Get offset into file name.
copy_loop2 lda [path_ptr],y ;Get byte. End of string?
beq end_name_2 ;Yes.
cmp #separator1 ;End of name?
beq end_name_2 ;Yes.
sta file_name+2,x ;No, put byte in volume name.
inx ;Bump offsets.
iny
bra copy_loop2 ;Loop.
end_name_2 lda #0 ;Terminate string.
sta file_name+2,x
stx file_name ;Put length word.
*
* Done, exit with carry clear...
*
longa on ;Set 16 bit A.
done rep #$20
clc ;Indicate ok.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: get_name
*
* Description: Copies indicated name from the pathname to string_buffer.
*
* Created: Oct 22, 1987
* Modified: Mar 28, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = name index (no validity checking is done!)
* P = nvmxdizc
* ..000...
* B = K
*
* path_ptr ;points to pathname.
* name_offsets ;list of offsets to start of names.
*
* Output: A = undefined
* X = length of name
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* string_buffer ;name with length byte at start.
*
* Uses: All registers
* path_ptr
* name_offsets
* string_buffer
*
******************************************************************************
get_name proc
with data
*
* Move name to string buffer...
*
ldx #0 ;Init offset/counter.
txa ;Clear accumulator.
longa off ;Set 8 bit A.
sep #$20
lda name_offsets,y ;Get offset to start of name.
tay
move_loop lda [path_ptr],y ;Get byte. End of string?
beq hit_end ;Yes.
cmp #separator1 ;No, is it a separator?
beq hit_end ;Yes.
sta string_buffer+1,x ;No, add to buffer.
iny ;Bump offsets.
inx
bra move_loop ;Loop.
hit_end txa ;Put length in A (so is 8 bit).
sta string_buffer ;Save length.
longa on ;Set 16 bit A.
rep #$20
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: long_multiply
*
* Description: Does 32 bit multiplication. multiplicand * multiplier = product
*
* Created: Nov 30, 1987
* Modified: Nov 30, 1987
* Author: Bryan Atsatt (adapted from '6502 Software Design')
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* multiplier ;32 bit multiplier.
* multiplicand ;32 bit multiplicand.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* product ;64 bit product.
*
* Uses: All registers
* multiplier (a.k.a. dividend)
* multiplicand (a.k.a. divisor)
* product (a.k.a. input_string & output_string)
*
******************************************************************************
long_multiply proc
with data
*
* Initialize...
*
ldx #32 ;Get bit count.
lda #0 ;MUST BE ZEROED!
sta product+4 ;Clear upper 4 bytes of product.
sta product+6
*
* Do multiplication and exit...
*
next_bit lsr multiplier+2 ;Shift multiplier right. Bit set?
ror multiplier
bcc align ;Nope.
clc ;Yes, add product+4 to multiplicand.
lda product+4
adc multiplicand
sta product+4
lda product+6
adc multiplicand+2
align ror a ;Rotate 8 byte product right.
sta product+6
ror product+4
ror product+2
ror product
dex ;Done all bits?
bne next_bit ;Nope, so loop.
rts ;Yes, so exit.
ENDP
eject
******************************************************************************
*
* Name: long_divide
*
* Description: Does 32 bit division. dividend/divisor = dividend w/remainder.
*
* Created: Oct 29, 1987
* Modified: Oct 29, 1987
* Author: Bryan Atsatt (adapted from '6502 Software Design')
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* dividend ;32 bit dividend.
* divisor ;32 bit divisor.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* dividend ;quotient
* remainder ;remainder
*
* Uses: All registers
* dividend
* divisor
* remainder
*
******************************************************************************
long_divide proc
with data
*
* Initialize...
*
ldx #32 ;Get bit count.
stz remainder ;Clear remainder.
stz remainder+2
*
* Do division and exit...
*
div_loop asl dividend ;Shift dividend & quotient left.
rol dividend+2
rol remainder ;Shift partial dividend left.
rol remainder+2
sec ;Subtract low bytes.
lda remainder
sbc divisor
tay ;Save low result.
lda remainder+2 ;Subtract high bytes.
sbc divisor+2 ;Divisor > dividend?
bcc next_bit ;Yes.
inc dividend ;No, set bit in quotient.
sty remainder ;Enter result in partial dividend.
sta remainder+2
next_bit dex ;Done all bits?
bne div_loop ;No, so loop.
rts ;Yes, so exit.
ENDP
eject
******************************************************************************
*
* Name: pro_date_time
*
* Description: Converts recording date and time from dir_record_0 to prodos
* date/time format.
*
* Created: Nov 2, 1987
* Modified: Nov 2, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* prodos_time ;Holds date and time:
* _______________________________________________________________
* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
* | year | month | day |0 0 0 hour |0 0 minute |
* |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
*
* ;year = 1900-year
* ;month = 1-12
* ;day = 1-31
* ;hour = 0-23
* ;minute = 0-59
*
* Uses: All registers
* create_date_time
* prodos_time
* get_date_time (sub)
*
******************************************************************************
pro_date_time proc
with data
*
* Get the create_date_time...
*
jsr get_date_time ;Get it.
*
* Now convert it to prodos format and exit...
*
lda day ;Get day.
and #$00ff ;Clear high byte.
inc a ;Make it 1-31.
sta prodos_time ;Save it.
lda month ;Get month.
and #$00ff ;Clear high byte.
inc a ;Make it 1-12.
asl a ;Move to correct position.
asl a
asl a
asl a
asl a
ora prodos_time ;Insert it.
sta prodos_time ;Save it.
lda year ;Get year.
and #$00ff ;Clear high byte.
xba ;Move to correct position.
asl a
ora prodos_time ;Insert it.
sta prodos_time ;Save it.
lda hour ;Get hour.
and #$00ff ;Clear high byte.
xba ;Move to correct position.
sta prodos_time+2 ;Save it.
lda minute ;Get minute.
and #$00ff ;Clear high byte.
ora prodos_time+2 ;Insert it.
sta prodos_time+2 ;Save it.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: get_date_time
*
* Description: Converts recording date and time from dir_record_0 to GS/OS
* date/time format. If date/time is illegal, will set to
* Jan 1, 1988 12:00 am default.
*
* Created: Nov 2, 1987
* Modified: July 14, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* create_date_time ;Holds date and time:
*
* |<-- byte 7 -->|<-- byte 6 -->|<-- byte 5 -->|<-- byte 4 -->|
* _______________________________________________________________
* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
* | weekday | null | month | day |
* |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
*
* |<-- byte 3 -->|<-- byte 2 -->|<-- byte 1 -->|<-- byte 0 -->|
* _______________________________________________________________
* | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
* | year | hour | minute | second |
* |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
*
* ;year = year-1900
* ;month = 0-11
* ;day = 0-30
* ;weekday = 1-7, 1 = sunday
* ;hour = 0-23
* ;minute = 0-59
* ;second = 0-59
*
* Uses: All registers
*
******************************************************************************
get_date_time proc
with data
*
* Set 8 bit registers...
*
longa off ;Set 8 bit registers.
longi off
sep #$30
*
* Convert date and time...
*
lda dir_record_0+dir_date_time ;Get year.
cmp #max_year ;In range?
bcs use_default ;Nope.
sta year ;Yes, save it.
ldx dir_record_0+dir_date_time+1 ;Get month.
dex ;Make it 0-11.
stx month ;Save it.
cpx #max_month ;In range?
bcs use_default ;Nope.
ldy dir_record_0+dir_date_time+2 ;Get day.
dey ;Make it 0-30.
sty day ;Save it.
cpy #max_day ;In range?
bcs use_default ;Nope.
inx ;Bump month.
iny ;Bump day.
jsr calc_dow ;Calculate day of week.
sta weekday ;Save it.
stz null ;Clear null.
lda dir_record_0+dir_date_time+3 ;Get hour.
cmp #max_hour ;In range?
bcs use_default ;Nope.
sta hour ;Yes, save it.
lda dir_record_0+dir_date_time+4 ;Get minute.
cmp #max_minute ;In range?
bcs use_default ;Nope.
sta minute ;Yes, save it.
lda dir_record_0+dir_date_time+5 ;Get second.
cmp #max_second ;In range?
bcs use_default ;Nope.
sta second ;Yes, save it.
bra exit ;Exit.
*
* Date or time is bad, use default date/time...
*
use_default ldy #7 ;Copy default date/time.
copy_loop lda default_date_time,y
sta create_date_time,y
dey
bpl copy_loop
*
* Restore 16 bit registers and exit...
*
longa on ;Set 16 bit registers.
longi on
exit rep #$30
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: calc_dow
*
* Description: Calculates the day of the week for a given date.
*
* NOTE: Call with m & x set!
*
* Created: Nov 2, 1987
* Modified: Nov 2, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = year (year-1900)
* X = month (1-12)
* Y = day (1-31)
* P = nvmxdizc
* ..110...
* B = K
*
* Output: A = day of week
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..110...
* B = K
*
* Uses: All registers
* temp0
* temp1
*
******************************************************************************
calc_dow proc
with data
longa off
longi off
*
* Calculate the number of leap years since 1900...
*
sty day_of_mon ;Save day.
tay ;Save year.
lsr a ;Divide year by 4.
lsr a
sta leap_years ;Save it.
*
* If it's a leap year and it's Jan or Feb, subtract 1 from the year...
*
tya ;Get year back.
and #3 ;Is it a leap year?
bne continue ;Nope.
cpx #3 ;Yep, is it Jan or Feb?
bcs continue ;Nope.
dey ;Yes, adjust year.
*
* Now add up the number of leap years elapsed, the year, the day, and a
* constant for the month...
*
continue clc ;Prepare for add.
tya ;Get year.
adc leap_years ;Add # leap years.
adc day_of_mon ;Add day.
adc constant-1,x ;Add constant.
*
* Convert the result to a # in the range 1 to 7 and exit...
*
sec ;Prepare for subtract.
adjust_loop sbc #7 ;Subtact 7.
cmp #8 ;In range?
bcs adjust_loop ;No, so loop.
rts ;Exit.
constant DC.B 8,11,11,7,9,12,7,10,13,8,13
longa on
longi on
ENDP
eject
******************************************************************************
*
* Name: get_option_list
*
* Description: Load extended attribute record (if present) into option list
* buffer. If it gets an error when trying to read the data,
* will set transfer count to zero and exit with carry clear.
*
* Created: Nov 2, 1987
* Modified: Mar 2, 1989
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = high word of option list pointer.
* X = low word of option list pointer.
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* dir_record_0 ;holds directory record.
*
* Output: A = error code if error.
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* option list buffer: 1 = input: buffer size, inc. 1 & 2.
* 2 = output: required size, exc. 1 & 2.
* 3 = output: fst id.
* 4 = output: extended attribute record.
* _____________________
* | | | | | | | | | | | >
* | 1 | 2 | 3 | 4 <
* |_|_|_|_|_|_|_|_|_|_|_>
*
* Uses: All registers
* dividend
* data_buffer
* temp0
* temp1
*
******************************************************************************
get_option_list proc
with data
*
* Save pointer, exit if zero...
*
stx option_list ;Save low word.
sta option_list+2
ora option_list ;Zero?
bne check_buffer ;No, so ok.
clc ;Yes, so exit with no error.
rts
*
* Is the buffer big enough to hold the length? Parm_range_err if not...
*
check_buffer lda [option_list] ;Get buffer length.
cmp #4 ;Big enough to hold length?
bcs init_len ;Yes.
sec ;No, so parm_range_err.
lda #parm_range_err
brl error_exit ;Exit.
*
* Yes, so init length to 2 for the FST id...
*
init_len lda #2 ;Get minimum length.
sta length ;Save it.
*
* Is there an XAR for this file?
*
stz block_count ;Clear in case no XAR.
lda dir_record_0+dir_xar_len ;Do we have an XAR?
and #$00ff
beq no_xar ;Nope, so exit.
sta block_count ;Yes, save block count.
*
* Yes, set length to required size...
*
tax ;Use block_count as counter.
clc ;Prepare for add.
lda #2 ;Init size to include overhead.
add_loop adc log_blk_size ;Add logical block size.
dex ;Done all?
bne add_loop ;No, so loop.
sta length ;Yes, so save it.
*
* Set output length to required size...
*
no_xar ldy #2 ;Get offset to length.
lda length ;Get required length.
sta [option_list],y ;Stuff it in.
*
* Will the buffer hold the FST ID? Exit with buf_too_small error if not...
*
lda [option_list] ;Get length word.
cmp #0006 ;Will the id fit?
bcc full ;Nope.
*
* Yes, so stuff it in...
*
ldy #0004 ;Point to id area.
lda #hs_id ;Get fst id.
sta [option_list],y ;Stuff it in.
*
* Yes, set max_len to buffer size - 6 (carry set from above). Exit with
* buf_too_small error if max_len = 0...
*
lda [option_list] ;Get length word.
sbc #6 ;Adjust for overhead.
sta max_len ;Save it.
beq full ;Full if max_len zero.
*
* We're done with no error if there isn't an XAR...
*
lda block_count ;Is there an XAR?
beq ok_exit ;Nope, so done.
*
* We have an XAR. Make a pointer to data area...
*
clc ;Add 6 to option_list.
lda #6
adc option_list
sta data_buffer
lda #0
adc option_list+2
sta data_buffer+2
*
* Make sure io_buffer is pointed at the real io_buffer...
*
ldx io_buffer_vp ;Get vp.
ldy io_buffer_vp+2
jsl deref ;Dereference it.
stx io_buffer ;Save pointer.
sty io_buffer+2
*
* Get address of first block...
*
ldx dir_record_0+dir_loc_extent ;Get low word of block #.
lda dir_record_0+dir_loc_extent+2 ;Get high word.
*
* Read block into io_buffer. Exit on error...
*
read_loop jsr block_read ;Do read.
bcs error_exit ;Error, so set count to zero and exit.
*
* Send until we've filled caller's buffer or finished with block...
*
longa off ;Set 8 bit mode.
sep #$20
ldy #0 ;Init offset.
move_loop lda [io_buffer],y ;Get byte.
sta [data_buffer],y ;Send it.
iny ;Bump offset.
cpy max_len ;Full?
beq full ;Yes.
cpy log_blk_size ;No, run out of buffer?
bne move_loop ;Nope, so loop.
longa on ;Set 16 bit mode.
rep #$20
*
* Ran out of data. Add log_blk_size to transfer_count and get next block
* number (if there is one) and loop...
*
ldx drvr_blk_num ;Get current block.
lda drvr_blk_num+2
inx ;Bump it.
bne check_block
inc a
check_block dec block_count ;Done all blocks?
bne read_loop ;No, so loop.
*
* Done. Exit with carry clear...
*
ok_exit clc ;No error.
rts ;Exit.
*
* We've filled up the caller's buffer and there's more to go, so exit
* with a buffer too small error. If we're processing an open call, we
* must release the fcr...
*
longa on ;Set 16 bit mode.
full rep #$20
lda #buff_too_small ;Get error code.
sec ;Indicate error.
error_exit ldx call ;Doing an open call?
cpx #$10
bne real_exit ;No.
pha ;Yes, save error code.
lda [my_fcr] ;Get ref_num.
jsl release_fcr ;Release fcr.
pla ;Recover error code.
real_exit sec ;Make sure carry set.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: transform_in_s
*
* Description: Replaces all periods in string_buffer with underscores if
* ProDOS Transformation bit is set in state_flag.
*
* Created: June 30, 1988
* Modified: June 30, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_vcr ;points to current vcr.
* string_buffer ;holds name in pascal string format
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Uses: All registers
*
******************************************************************************
transform_in_s proc
with data
*
* Are we supposed to do the transformation? Exit if not...
*
ldy #vcr_state_flag ;Get offset to state flag in vcr.
lda [my_vcr],y ;Get state flags.
and #prodos_bit ;Prodos bit set?
beq exit ;Nope, so exit.
*
* Yes, replace all "." in string with "_" and exit...
*
lda string_buffer ;Get length of string
and #$00ff ;Clear high byte.
tay ;Point to end of string.
lda #$5f2e ;Get underscore and period.
longa off ;Set 8 bit A.
sep #$20
transform_loop cmp string_buffer,y ;Is period?
bne next ;Nope.
xba ;Yes, get underscore.
sta string_buffer,y ;Replace period.
xba ;Recover period.
next dey ;Done all?
bne transform_loop ;Nope, so loop.
longa on ;Yep, set 16 bit A.
rep #$20
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: transform_in_f
*
* Description: Replaces all periods in file_name with underscores and appends
* ".;1" if ProDOS Transformation bit is set in state_flag.
*
* Created: June 30, 1988
* Modified: June 30, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_vcr ;points to current vcr.
* file_name ;holds name in gstring format.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Uses: All registers
*
******************************************************************************
transform_in_f proc
with data
*
* Are we supposed to do the transformation? Exit if not...
*
ldy #vcr_state_flag ;Get offset to state flag in vcr.
lda [my_vcr],y ;Get state flags.
and #prodos_bit ;Prodos bit set?
beq exit ;Nope, so exit.
*
* Yes, replace all "." in string with "_"...
*
ldy file_name ;Point to end of string
lda #$5f2e ;Get underscore and period.
longa off ;Set 8 bit A.
sep #$20
transform_loop cmp file_name+1,y ;Is period?
bne next ;Nope.
xba ;Yes, get underscore.
sta file_name+1,y ;Replace period.
xba ;Recover period.
next dey ;Done all?
bne transform_loop ;Nope, so loop.
longa on ;Yep, set 16 bit A.
rep #$20
*
* Append ".;1" and exit...
*
ldy file_name ;Point to end of string.
lda #$3b2e ;Get period-semicolon.
sta file_name+2,y ;Append to name.
lda #$0031 ;Get "1" and string terminator.
sta file_name+4,y ;Append to name.
clc ;Add 3 to length.
lda #0003
adc file_name
sta file_name
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: transform_out
*
* Description: If ProDOS Transformation bit is set in state_flag, will strip
* ".;1" (if present) and replace all underscores with periods.
*
* Created: June 30, 1988
* Modified: June 30, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_vcr ;points to current vcr.
* gstring ;holds name in gstring format
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Uses: All registers
*
******************************************************************************
transform_out proc
with data
*
* Are we supposed to do the transformation? Exit if not...
*
ldy #vcr_state_flag ;Get offset to state flag in vcr.
lda [my_vcr],y ;Get state flags.
and #prodos_bit ;Prodos bit set?
beq exit ;Nope, so exit.
*
* Yes, strip ".;1" if present...
*
ldy gstring ;Point to end of string.
lda gstring,y ;Get last two characters.
cmp #$313b ;Are they ";1"?
bne transform ;Nope.
lda gstring-1,y ;Yep, back up one byte.
cmp #$3b2e ;Are they ".;"?
bne transform ;Nope.
dey ;Yes, so subtract 3 from length.
dey
dey
sty gstring ;Save new length.
lda #0 ;Re-terminate string at new position.
sta gstring+2,y
*
* Replace all "_" in string with "." and exit...
*
transform ldy gstring ;Point to end of string.
lda #$2e5f ;Get period and underscore.
longa off ;Set 8 bit A.
sep #$20
transform_loop cmp gstring+1,y ;Is underscore?
bne next ;Nope.
xba ;Yes, get period.
sta gstring+1,y ;Replace underscore.
xba ;Recover underscore.
next dey ;Done all?
bne transform_loop ;Nope, so loop.
longa on ;Yep, set 16 bit A.
rep #$20
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: transform_vol
*
* Description: Searches volume_name for character in low byte of A and if
* found, replaces it with character in high byte of A.
*
* Created: July 14, 1988
* Modified: July 14, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = character to match in low byte, replacement in high byte
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* volume_name ;holds name in gstring format
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Uses: All registers
*
******************************************************************************
transform_vol proc
with data
*
* Transform volume_name and exit...
*
ldy volume_name ;Point to end of string.
longa off ;Set 8 bit A.
sep #$20
transform_loop cmp volume_name+1,y ;Match?
bne next ;Nope.
xba ;Yes, get replacement character.
sta volume_name+1,y ;Replace.
xba ;Recover search character.
next dey ;Done all?
bne transform_loop ;Nope, so loop.
longa on ;Yep, set 16 bit A.
rep #$20
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: transform_gstring
*
* Description: If ProDOS transformation bit set in state flag, searches
* gstring for character in low byte of A and if found, replaces
* it with character in high byte of A.
*
* Created: July 21, 1988
* Modified: July 21, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = character to match in low byte, replacement in high byte
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* gstring ;holds name in gstring format
* state_flag ;b0 = 1 if ISO version of High Sierra.
* ;b1 = 1 if Apple Extensions disc.
* ;b2 = 1 if ProDOS Transformation required.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Uses: All registers
*
******************************************************************************
transform_gstring proc
with data
*
* Should we do the transform?
*
tax ;Save A.
lda state_flag ;Get state flag.
and #prodos_bit ;ProDOS bit set?
beq exit ;Nope, so exit.
txa ;Yes, recover A.
*
* Yep, transform gstring and exit...
*
ldy gstring ;Point to end of string.
longa off ;Set 8 bit A.
sep #$20
transform_loop cmp gstring+1,y ;Match?
bne next ;Nope.
xba ;Yes, get replacement character.
sta gstring+1,y ;Replace.
xba ;Recover search character.
next dey ;Done all?
bne transform_loop ;Nope, so loop.
longa on ;Yep, set 16 bit A.
rep #$20
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: transform_name
*
* Description: Searches gstring pointed to by X and Y for character in low
* byte of A and if found, replaces it with character in high
* byte of A.
*
* Created: July 14, 1988
* Modified: July 14, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = character to match in low byte, replacement in high byte
* X = low word of pointer to gstring.
* Y = high word of pointer to gstring.
* P = nvmxdizc
* ..000...
* B = K
*
* my_vcr ;points to current vcr.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Uses: All registers
* remainder
*
******************************************************************************
transform_name proc
with data
string_ptr set remainder ;Local direct page equate.
*
* Save pointer...
*
stx string_ptr ;Save low word.
sty string_ptr+2 ;Save high word.
tax ;Save A.
*
* Are we supposed to do the transformation? Exit if not...
*
ldy #vcr_state_flag ;Get offset to state flag in vcr.
lda [my_vcr],y ;Get state flags.
and #prodos_bit ;Prodos bit set?
beq exit ;Nope, so exit.
*
* Yes, get length and bump pointer...
*
lda [string_ptr] ;Get length of string
and #$00ff ;Clear high byte.
tay ;Point to end of string.
inc string_ptr ;Bump pointer. Rollover?
bne replace ;Nope.
inc string_ptr+2 ;Yep, bump high word.
*
* Replace characters and exit...
*
replace txa ;Get characters..
longa off ;Set 8 bit A.
sep #$20
transform_loop cmp [string_ptr],y ;Match?
bne next ;Nope.
xba ;Yes, get replacement.
sta [string_ptr],y ;Replace it.
xba ;Recover search character.
next dey ;Done all?
bne transform_loop ;Nope, so loop.
longa on ;Yep, set 16 bit A.
rep #$20
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: get_ext_type
*
* Description: Gets type and aux type from SystemUse field of directory record
* if SystemUse field and our signature are present.
*
* Created: July 8, 1988
* Modified: Apr 6, 1989
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_vcr ;points to current vcr
* dir_record_0 ;holds directory record
*
* Output: A = aux_type if no error
* X = file_type if no error
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Exit: rts
*
* Uses: all registers
*
******************************************************************************
get_ext_type PROC
with data
*
* Do we have a SystemUse field? Present if dir_record_length - dir_len_fi
* is >= sys_use_len (35)...
*
phy ;Save Y.
sec ;Prepare to subtract.
lda dir_record_0+dir_len_fi ;Get length of file name.
and #$00ff ;Clear high byte.
pha ;Save it.
lda dir_record_0 ;Get length of directory record.
and #$00ff ;Clear high byte.
sbc 1,s ;Do subtraction.
plx ;Recover length of file name.
cmp #sys_use_len ;Is >= sys_use_len?
bcc not_here ;Nope.
*
* Yes, adjust offset by one if we have a padding field...
*
lda dir_record_0+dir_len_fi+1,x ;Padding field?
and #$00ff
bne check_signature ;Nope.
inx ;Yes, so bump offset.
*
* Yes, do we have an apple signature?
*
check_signature ldy #0001 ;Set pass flag.
signature_loop lda dir_record_0+dir_len_fi+1,x ;Get SystemUseID signature.
cmp #apple_sig1 ;Is old signature?
beq old_sig ;Yes.
cmp #apple_sig2 ;No, is new signature?
beq new_sig ;Yes.
*
* No, is this an XA disc?
*
lda state_flag ;Get state_flag.
and #xa_bit ;Do we have an XA disc?
beq not_here ;Nope, so exit.
*
* Yes, have we bumped the offset already? Exit if so...
*
dey ;Done this already?
bne not_here ;Yes, so don't do it again.
*
* Nope, so bump offset past XA system_use stuff and re-try...
*
clc ;Bump offset.
txa
adc #xa_offset
tax
bra signature_loop ;Re-try.
*
* We have a new signature. See if we have a ProDOS field and, if so,
* adjust offset and continue on at get_type; else no extensions...
*
longa off ;Go to 8 bit regs.
longi off
new_sig sep #$30
search lda dir_record_0+dir_len_fi+4,x ;Get SystemUseID.
cmp #prodos_format ;Is it ProDOS?
bne next ;Nope.
inx ;Yes, adjust offset.
bra get_type ;Go get type.
next clc ;Point to next extensions.
txa
adc dir_record_0+dir_len_fi+3,x
tax
bcs not_here ;Done if rolled over.
adc #dir_len_fi+3 ;Checked all?
cmp dir_record_0
bcc search ;No, so keep looking.
bra not_here ;Yes, so no extensions.
*
* Yes, we have an old signature. Is this a ProDOS field?
*
longa on
longi on
old_sig lda dir_record_0+dir_len_fi+3,x ;Get SystemUseID.
and #$00ff ;Clear high byte.
cmp #prodos_format ;Is it prodos format?
bne not_here ;Nope.
*
* Yes, get file_type in X and aux_type in A and exit with carry clear...
*
get_type rep #$30 ;Make sure 16 bit A.
lda dir_record_0+dir_len_fi+4,x ;Get file_type.
and #$00ff ;Clear high byte.
tay ;Save it.
lda dir_record_0+dir_len_fi+5,x ;Get aux_type.
tyx ;Put file_type in X.
clc ;Indicate success.
ply ;Recover Y.
rts ;Exit.
*
* Data not here, so exit with carry set...
*
not_here rep #$30 ;Make sure 16 bit A.
sec ;Indicate failure.
ply ;Recover Y.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: get_file_type
*
* Description: Scans name in file_name buffer and tries to assign file type
* by matching entries in the file type map table.
*
* The file type map is a list of file name suffixes and associated
* file types. Each record is variable length and consists of an
* ascii string followed by a zero and a one byte file type. The
* table is terminated will a 1 byte null (00):
*
* map_size ;(w) size in bytes.
* record_0 ;file type record.
* record_1 ;file type record.
* null ;(b) map terminator.
*
* If no matching entry is found, the 'unknown' (00) type is
* returned.
*
* Created: Dec 3, 1987
* Modified: Feb 23, 1989
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* file_name ;holds name in gstring format
* map_buffer_ptr ;holds a pointer to the file type map
* map_enable_flag ;0 if disabled.
*
* Output: A = undefined
* X = file_type
* Y = unchanged
* P = nvmxdizc
* ..000...
* B = K
*
* Uses: All registers
* temp1
* length
*
******************************************************************************
get_file_type proc
with data
*
* If map_enable_flag is zero, then exit with unknown file type...
*
phy ;Save Y.
lda map_enable_flag ;Flag zero?
beq unknown ;Yep.
*
* Copy the pointer into map_ptr, init offset and set 8 bit accumulator...
*
lda map_buffer_ptr ;Get pointer.
ldx map_buffer_ptr+2
sta map_ptr ;Put in direct page pointer.
stx map_ptr+2
longa off ;Set 8 bit A.
sep #$20
*
* Set length_temp to either real length of file_name or length minus any
* version number...
*
ldy file_name ;Point to real end.
sty length_temp ;Init length_temp
version_check lda file_name+1,y ;Get byte.
cmp #';' ;Semicolon?
beq fix_length ;Yes, so must change length.
dey ;No, done all?
bne version_check ;No, so loop.
bra init_search ;Yes, so leave length alone.
fix_length dey ;Back up past semicolon.
sty length_temp ;Save new length.
*
* Have we checked all records? If so, exit with file type 00...
*
init_search ldy #2 ;Init offset past length.
record_loop lda [map_ptr],y ;Get byte. Zero?
beq exit ;Yes, so exit with file type 00.
*
* Nope, let's find the end of the string for this record and get its length...
*
ldx #0 ;Init count.
end_loop inx ;Bump count.
iny ;Bump offset.
lda [map_ptr],y ;Get byte. Zero?
bne end_loop ;Nope, so continue.
phy ;Yes, save offset.
stx length ;Save length.
dey ;Point to last character.
*
* Does the string match?
*
cpx length_temp ;String longer than file_name?
beq check_it ;Nope.
bcs next_record ;Yep, so don't check.
check_it ldx length_temp ;Get length of file_name.
match_loop lda [map_ptr],y ;Get character.
cmp file_name+1,x ;Match?
bne next_record ;Nope.
dey ;Yes, back up one.
dex
dec length ;Done with string?
bne match_loop ;Nope, so loop.
*
* Yes, so get file type, restore 16 bit accumulator and exit...
*
ply ;Recover offset.
iny ;Point to file type.
lda [map_ptr],y ;Get file type.
longa on ;Restore 16 bit A.
exit rep #$20
and #$00ff ;Clear high byte.
unknown tax ;Put file type in X.
ply ;Recover Y.
rts ;Exit.
*
* No, so let's point to the next record and loop...
*
next_record ply ;Recover offset.
iny ;Point to file type.
iny ;Point to next record.
bra record_loop ;Loop.
ENDP
eject
******************************************************************************
*
* Name: write_protect
*
* Description: A common handler for all calls which require writing to disk.
* Will call process_path, and if successful, will return a
* drvr_wr_prot error. Always returns an error.
*
* Created: Dec 14, 1987
* Modified: Dec 14, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = error code
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* B = K
*
* Uses: All registers
* process_path
*
******************************************************************************
write_protect proc
with data
*
* Go look for the requested file. Found?
*
jsr process_path ;Go find it.
bcs exit ;Error, so exit.
*
* Yes, but we can't write, so exit with write protect error...
*
lda #drvr_wr_prot ;Get error code.
sec ;Indicate error.
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: create
*
* Description: Removes any filename from pathname then jumps to write_protect.
*
* Created: May 2, 1988
* Modified: May 2, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = error code
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* B = K
*
* Uses: All registers
* write_protect
*
******************************************************************************
create proc
with data
*
* Decrement name_count if it is greater than 0, then jump to write_protect...
*
lda name_count ;Get count. Zero?
beq jump ;Yep.
dec name_count ;Nope, so decrement it by one.
jump jmp write_protect
ENDP
eject
******************************************************************************
*
* Name: get_file_info
*
* Description: Returns information about a file or directory.
*
* Created: Nov 3, 1987
* Modified: Nov 3, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Uses: All registers
* process_path (sub)
* send_output (sub)
*
******************************************************************************
get_file_info proc
with data
*
* Go find the file requested...
*
jsr process_path ;Go find it.
bcs error ;Error.
*
* Send the parameters back and exit...
*
jsr send_output ;Send 'em.
error rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: volume
*
* Description: Returns volume information from a High Sierra disk.
*
* Created: Oct 6, 1987
* Modified: Feb 7, 1991
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Exit: rts
*
* Uses: all registers
* id_disk (sub)
*
******************************************************************************
volume proc
with data
*
* Now ID the disk. Is it a High Sierra disk?
*
lda #in_cache ;Force block into cache.
sta drvr_cache
lda dev_num ;Get device # from zp.
jsr id_disk ;See if it's my kind of disk.
bcs got_error ;branch if we got an error
*
* Yes, so send the output parameters...
*
jsr send_output ;Send 'em.
*
* Set cache back to default value and exit...
*
export SET_USER_CACHE
set_user_cache ;
pha ;Save A.
lda cache_priority ;Get user setting.
sta drvr_cache ;Set cache value.
pla ;Recover A.
rts ;Exit
*
* We got an error from id_disk.
* If the error is "dup_volume" then we need to force the "vol_name" output parameter
* to be setup even though we're returning an error.
*
got_error cmp #dup_volume ;duplicate volume error?
bne error ;no - so we're done
ldy #4 ;get class 0 offset to the volname param
lda class ;get call class
beq doit ;branch if doing class 0
iny ;adjust param offset for class 1
iny
doit jsr h_vol_name ;setup the volname output param
bcs set_user_cache ;return output buffer errors
lda #dup_volume ;restore the dup_volume error
error sec ;indicate error
bra set_user_cache ;and exit
ENDP
eject
******************************************************************************
*
* Name: id_disk
*
* Description: Determines whether or not the media chosen is in High Sierra
* or ISO format. If so and there is no VCR for it, one is
* created; if there is a VCR then it is marked active.
*
* Created: Oct 7, 1987
* Author: Bryan Atsatt
* Modified: Feb 22, 1989 Added check for drvr_bad_block error.
* Oct 10, 1989 CAF. Added check for drvr_disk_sw error.
* Aug 8, 1990 MSD. Removed Cary's check for drvr_disk_sw.
* The device_dispatch routine now has a special
* case for drvr_disk_sw during id_disk.
*
* Entry: jsr
*
* Input: A = device number
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* gstring ;holds volume name.
* state_flag ;b0 = 1 if ISO version of High Sierra.
* ;b1 = 1 if Apple Extensions disc.
* ;b2 = 1 if ProDOS Transformation required.
*
* Uses: all registers
* id_disk_flag
* gstring
* temp0
* temp1
* drvr_dev_num
* drvr_call_num
* dev_id_ref
* drvr_dib_ptr
* sector_read (sub)
* build_vcr (sub)
*
******************************************************************************
id_disk proc
with data
*
* Save current device, init state_flag to 0 (high sierra), and make sure
* id_disk_flag is clear...
*
sta current_dev ;Save device #.
stz state_flag ;Clear state_flag.
stz id_disk_flag ;Clear id_disk_flag.
*
* Read in sector with id_disk_flag set, clear flag, then exit if error...
*
ldx #vol_start ;Init to volume start.
try_next stx sector_number ;Save low word of sector #.
lda #0 ;Get high word of sector #.
ldy current_dev ;Get driver number.
sty drvr_dev_num ;Set driver number.
inc id_disk_flag ;Set id_disk_flag.
jsr sector_read ;Read in the data.
stz id_disk_flag ;Clear flag.
bcc do_id ;Continue if no error.
cmp #drvr_bad_block ;Error. Is volume too small?
bne return_error ;Nope, some other error.
lda #unknown_vol ;Yes, so make into a bouncer.
return_error sec ;Re-set carry.
rts ;Exit.
*
* Ok, now look at the Volume Structure Standard Identifier.
* Is it 'CDROM' (High Sierra)?
*
longa off ;Set 8 bit A.
do_id sep #$20
ldx #4 ;Point to end of string.
ldy #vol_id_end_0 ;Point to end of identifier.
check_hs lda [io_buffer],y ;Get byte.
cmp hs_string,x ;Match?
bne iso ;Nope, so not High Sierra.
dey ;Yes, done all?
dex
bpl check_hs ;No, so loop.
bra high_sierra ;Yes, so it's High Sierra.
*
* No, is it 'CD001' (ISO)?
*
iso ldx #4 ;Point to end of string.
ldy #vol_id_end_1 ;Point to end of identifier.
check_iso lda [io_buffer],y ;Get byte.
cmp iso_string,x ;Match?
bne unknown_hop ;Nope, so not ISO either.
dey ;Yes, done all?
dex
bpl check_iso ;No, so loop.
*
* We have an ISO disk, so set the iso_bit in the state_flag. Is the Volume
* Structure Standard Version correct?
*
lda state_flag ;Get flag.
ora #iso_bit ;Set ISO bit.
sta state_flag ;Save flag.
ldy #vol_version_1 ;Point to version.
lda [io_buffer],y ;Get byte.
cmp #1 ;Is it a 1?
bne unknown_hop ;Nope, so not ISO.
*
* Yes. Is this a Standard File Structure Volume Descriptor?
*
ldy #vol_type_1 ;Point at type.
lda [io_buffer],y ;Get byte.
cmp #1 ;Is it a 1?
bne not_standard ;Nope, so it's not standard.
*
* Yes. Is the Logical Block Size either 512, 1024, or 2048 bytes?
*
ldy #vol_blk_size_1 ;Point at block size.
lda [io_buffer],y ;Get low byte of size.
bne unknown ;Unknown if not zero.
iny ;Point to high byte.
lda [io_buffer],y ;Get high byte.
cmp #>2048 ;2k?
beq chk_file_ver_1 ;Yep, so ok.
cmp #>1024 ;1k?
beq chk_file_ver_1 ;Yep, so ok.
cmp #>512 ;Nope, 512?
bne unknown ;Nope, so unknown.
*
* Yes. Is the File Structure Standard Version correct?
*
chk_file_ver_1 ldy #vol_file_ver_1 ;Point to file version.
lda [io_buffer],y ;Get byte.
beq check_id ;Ok if zero.
cmp #1 ;Is it a 1?
bne unknown ;Nope, so not an ISO disk either.
*
* Yes, so we have an ISO disk. See if disk conforms to Apple Extensions, and/or
* if it is an XA disc, then continue...
*
check_id ldy #vol_sys_id_1 ;Get offset to iso sys_id.
jsr check_apple_ext ;Check for Apple Extensions.
jsr check_xa ;Check for CD-ROM XA disc.
bra got_one ;Continue.
*
* We have a High Sierra disk. Is the Volume Structure Standard Version
* correct?
*
high_sierra ldy #vol_version_0 ;Point to version.
lda [io_buffer],y ;Get byte.
cmp #1 ;Is it a 1?
bne unknown ;Nope, so not High Sierra.
*
* Yes. Is this a Standard File Structure Volume Descriptor?
*
ldy #vol_type_0 ;Point at type.
lda [io_buffer],y ;Get byte.
cmp #1 ;Is it a 1?
bne not_standard ;Nope.
*
* Yes. Is the Logical Block Size either 512, 1024, or 2048 bytes?
*
ldy #vol_blk_size_0 ;Point at block size.
lda [io_buffer],y ;Get low byte of size.
bne unknown ;Unknown if not zero.
iny ;Point to high byte.
lda [io_buffer],y ;Get high byte.
cmp #>2048 ;2k?
beq chk_file_ver_0 ;Yep, so ok.
cmp #>1024 ;1k?
beq chk_file_ver_0 ;Yep, so ok.
cmp #>512 ;Nope, 512?
bne unknown ;Nope, so unknown.
*
* Yes. Is the File Structure Standard Version correct?
*
chk_file_ver_0 ldy #vol_file_ver_0 ;Point to file version.
lda [io_buffer],y ;Get byte.
beq got_one ;Ok if zero.
cmp #1 ;Is it a 1?
unknown_hop bne unknown ;Nope, so not High Sierra.
*
* Yes, so we have a High Sierra disk. See if disk conforms to Apple Extensions
* then continue...
*
ldy #vol_sys_id_0 ;Get offset to high sierra sys_id.
jsr check_apple_ext ;Check for Apple Extensions.
bra got_one ;Continue.
*
* It looks like we've got a High Sierra or ISO disk but we're not
* looking at the Standard File Volume Descriptor. Bump the sector # and
* loop back to start if this is not the Volume Descriptor Sequence Terminator.
* If it is the terminator, then we can't ID disk...
*
longa on ;Restore 16 bit A.
not_standard rep #$20
and #$00ff ;Clear high byte.
cmp #vol_terminator ;Is this a terminator type?
beq unknown ;Yes, so we can't ID the disk.
ldx sector_number ;Nope, get sector #.
inx ;Bump it one.
brl try_next ;Try next one.
*
* Not a High Sierra or ISO disk. Exit with unknown volume error...
*
longa on ;First restore 16 bit A.
unknown rep #$20
lda #unknown_vol ;Get error code.
sec ;Indicate error.
rts ;Exit to caller.
*
* Ok, we've got a High Sierra disk and we're looking at the Standard File
* Volume Descriptor. Exit through build_vcr...
*
longa on ;Restore 16 bit A.
got_one rep #$20
jmp build_vcr ;Exit thru build_vcr.
ENDP
eject
******************************************************************************
*
* Name: check_apple_ext
*
* Description: Sets state_flag Apple Extensions and ProDOS Transformation bits
* if present.
*
* Created: July 8, 1988
* Modified: July 8, 1988
* Author: Bryan Atsatt
*
* NOTE: This routine must be entered with 8 bit Accumulator!
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = offset to system identifier field in volume descriptor.
* P = nvmxdizc
* ..100...
* B = K
*
* io_buffer ;points to volume header
* state_flag ;b0 = 1 if ISO version of High Sierra.
* ;b1 = 0
* ;b2 = 0
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* state_flag ;b0 = 1 if ISO version of High Sierra.
* ;b1 = 1 if Apple Extensions disc.
* ;b2 = 1 if ProDOS Transformation required.
*
* Exit: rts
*
* Uses: state_flag
*
******************************************************************************
check_apple_ext proc
with data
longa off
*
* Does this disk conform to the Apple Extensions?
*
ldx #0 ;Point to start of apple_string.
id_loop lda [io_buffer],y ;Get byte.
cmp apple_string,x ;Match?
bne exit ;Nope, so exit.
iny ;Yes, bump offsets.
inx
cpx #apple_str_len ;Reached end?
bne id_loop ;Nope, so loop.
*
* Yes, so put ProDOS Filename Transformation bit into state_flag and set the
* apple_bit then exit...
*
lda [io_buffer],y ;Get byte.
and #prodos_format ;Isolate prodos transformation bit.
asl a ;Shift it to prodos_bit position.
asl a
ora #apple_bit ;Add apple_bit.
ora state_flag ;Add to current state_flag.
sta state_flag ;Save it.
exit rts ;Exit.
longa on
ENDP
eject
******************************************************************************
*
* Name: check_xa
*
* Description: Sets state_flag xa_bit if this is a CD-ROM XA disc.
*
* Created: Apr 6, 1989
* Modified: Apr 6, 1989
* Author: Bryan Atsatt
*
* NOTE: This routine must be entered with 8 bit Accumulator!
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..100...
* B = K
*
* io_buffer ;points to volume header
* state_flag ;b0 = 1 if ISO version of High Sierra.
* ;b1 = 1 if Apple Extensions disc.
* ;b2 = 1 if ProDOS Transformation required.
* ;b3 = 0
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* state_flag ;b0 = 1 if ISO version of High Sierra.
* ;b1 = 1 if Apple Extensions disc.
* ;b2 = 1 if ProDOS Transformation required.
* ;b3 = 1 of CD-ROM XA disc.
*
* Exit: rts
*
* Uses: state_flag
*
******************************************************************************
check_xa proc
with data
longa off
*
* Is this a CD-ROM XA disc?
*
ldx #0 ;Point to start of xa_string.
ldy #vol_xa_label_1 ;Point to label area.
id_loop lda [io_buffer],y ;Get byte.
cmp xa_string,x ;Match?
bne exit ;Nope, so exit.
iny ;Yes, bump offsets.
inx
cpx #xa_str_len ;Reached end?
bne id_loop ;Nope, so loop.
*
* Yes, so set xa_bit in state_flag and exit...
*
lda state_flag ;Get current flags.
ora #xa_bit ;Add to current state_flag.
sta state_flag ;Save it.
exit rts ;Exit.
longa on
ENDP
eject
******************************************************************************
*
* Name: build_vcr
*
* Description: Creates a new VCR if needed. If already present, it is
* marked active. Checks for duplicate volumes.
*
* NOTE: Should only be called by id_disk!!
*
* Created: Oct 8, 1987
* Modified: July 21, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* io_buffer ;points to volume header
* state_flag ;b0 = 1 if ISO version of High Sierra.
* ;b1 = 1 if Apple Extensions disc.
* ;b2 = 1 if ProDOS Transformation required.
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* my_vcr ;points to vcr.
* path_table ;points to path table.
* log_blk_size ;size of logical blocks for this disc.
* real_log_size ;copy of log_blk_size.
*
* Exit: rts
*
* Uses: all registers
* id_disk_flag
* my_vcr
* length
* temp0
* temp1
* set_file_system (sub)
* make_gstring (sub)
* block_read (sub)
* activate_vcr (sub)
* transform_name (sub)
* alloc_vcr (sys service)
* release_vcr (sys service)
* find_vcr (sys service)
* deref (sys service)
*
******************************************************************************
build_vcr proc
with data
*
* Set file system variables...
*
jsr set_file_system ;Set up for ISO or High Sierra.
*
* Make a gstring from volume name and transform if needed....
*
lda vol_id_start ;Get offset to start of name.
ldy vol_id_len ;Get length of name.
jsr make_gstring ;Make gstring.
lda #$2e5f ;Replace underscores with periods.
jsr transform_gstring
*
* Do we already have a VCR with this name?
*
lda #0000 ;Select search by name.
ldx #gstring ;Get pointer to volume name.
ldy #^gstring
jsl find_vcr ;Do search. Found?
bcs new_vcr ;Nope.
*
* Yes, does it belong to me?
*
jsl deref ;Yes, dereference VP.
stx my_vcr ;Save pointer.
sty my_vcr+2
ldy #vcr_fst_id ;Get offset to id.
lda [my_vcr],y ;Get id.
cmp #hs_id ;Is it mine?
bne check_active ;No, check if we can toss it.
*
* Yes, does the volume creation date & time match that in the vcr?
*
ldy vol_create_dt ;Get offset to create date & time.
ldx #vcr_create_dt ;Get offset into vcr.
lda vol_dt_len ;Get length of create + mod fields.
sta length ;Save it.
longa off ;Set 8 bit A.
sep #$20
cmp_loop lda [io_buffer],y ;Get byte.
sty vol_offset ;Save vol offset.
txy ;Get offset to vcr.
cmp [my_vcr],y ;Does it match?
bne check_active ;Nope, so see if it's active.
ldy vol_offset ;Yes, recover vol offset.
iny ;Bump it.
inx ;Bump vcr offset.
dec length ;Done all?
bne cmp_loop ;Nope, so loop.
longa on ;Set 16 bit A.
rep #$20
*
* Yes, so this is the same volume. Update the last known device,
* put state_flag in vcr, mark vcr as active and exit with the carry clear...
*
ldy #vcr_dev ;Get offset to device number.
lda drvr_dev_num ;Get device.
sta [my_vcr],y ;Update vcr.
ldy #vcr_state_flag ;Get offset to state_flag.
lda state_flag ;Get flag.
sta [my_vcr],y ;Save state word.
brl do_activate ;Continue.
*
* Exit with duplicate volume error...
*
duplicate lda #dup_volume ;Get error code.
sec ;Indicate error.
error_exit rts ;Exit.
*
* No, so we have a duplicate volume. If there are no open files then
* release the vcr and build a new one, otherwise exit with a duplicate
* volume error...
*
longa on ;Set 16 bit A.
check_active rep #$20
ldy #vcr_open_cnt ;Get offset to open count.
lda [my_vcr],y ;Any open?
bne duplicate ;Yes, so exit with error.
lda [my_vcr] ;Nope, get the volume ID.
jsl release_vcr ;Release vcr.
*
* Ok, we need to make a new vcr. First calculate size of vcr...
*
new_vcr ldy vol_path_size ;Get offset to path table size.
lda [io_buffer],y ;Get size.
sta path_table_size ;Save it.
sta path_size ;And again.
*** changed 2-Dec-92 DAL -- size of VCR is now a constant
;;; clc ;Add offset to path table.
;;; adc #vcr_path_table
lda #our_vcr_size
*** end 2-Dec-92
*
* Now allocate new vcr...
*
ldx #gstring ;Point to volume name.
ldy #^gstring
jsl alloc_vcr ;Allocate new vcr. Ok?
bcc alloc_ok ;Yes.
*
* Couldn't allocate. Exit with out of memory error...
*
lda #out_of_mem ;Get error code.
rts ;Exit.
*
* Fill in all the fields...
*
alloc_ok jsl deref ;Dereference vp.
stx my_vcr ;Save pointer.
sty my_vcr+2
*** added 2-Dec-92 DAL -- zero the path_tbl_handle field, in case we can't get the handle later
ldy #vcr_path_tbl_handle+2
lda #0
sta [my_vcr],y
dey
dey
sta [my_vcr],y
*** end 2-Dec-92
ldy #vcr_status ;Get offset to status.
lda #vcr_swapped ;Init to swapped.
sta [my_vcr],y
ldy #vcr_fst_id ;Get offset to fst id.
lda #hs_id ;Get id.
sta [my_vcr],y ;Save it.
ldy #vcr_dev ;Get offset to device.
lda drvr_dev_num ;Get current device.
sta [my_vcr],y ;Save it.
ldy vol_space_size ;Get offset to low word of size.
tyx ;Save it.
lda [io_buffer],y ;Get it.
ldy #vcr_total_blks ;Get offset to vcr.
sta [my_vcr],y ;Send low word.
txy ;Recover offset to low word of size.
iny ;Point to high word.
iny
lda [io_buffer],y ;Get it.
ldy #vcr_total_blks+2 ;Get offset to vcr.
sta [my_vcr],y ;Send high word.
ldy vol_block_size ;Get offset to block size.
lda [io_buffer],y ;Get it.
ldy #vcr_block_size ;Get offset into vcr.
sta [my_vcr],y ;Save it.
sta log_blk_size ;Set new log_blk_size.
sta real_log_size ;Set new real_log_size .
ldy #vcr_path_size ;Get offset to path table size.
lda path_table_size ;Get size.
sta [my_vcr],y ;Save it.
ldy vol_root_dir ;Get offset to root directory entry.
ldx #vcr_root_dir ;Get offset into vcr.
lda vol_root_len ;Get length of root dir.
sta length ;Save it.
dir_loop lda [io_buffer],y ;Get byte.
sty vol_offset ;Save vol offset.
txy ;Get offset to vcr.
sta [my_vcr],y ;Put byte in vcr.
ldy vol_offset ;Recover vol offset.
iny ;Bump it.
inx ;Bump vcr offset.
dec length ;Done all?
bne dir_loop ;Nope, so loop.
ldy vol_create_dt ;Get offset to create date & time.
ldx #vcr_create_dt ;Get offset into vcr.
lda vol_dt_len ;Get length of create + mod fields.
sta length ;Save it.
dt_loop lda [io_buffer],y ;Get byte.
sty vol_offset ;Save vol offset.
txy ;Get offset to vcr.
sta [my_vcr],y ;Put byte in vcr.
ldy vol_offset ;Recover vol offset.
iny ;Bump it.
inx ;Bump vcr offset.
dec length ;Done all?
bne dt_loop ;Nope, so loop.
ldy #vcr_state_flag ;Get offset to state_flag.
lda state_flag ;Get flag.
sta [my_vcr],y ;Put flag in vcr.
*** changed 2-Dec-92 DAL -- allocate a Memory Manager handle for the path table
;*
;* Now, we need to append the path table to the vcr. First make a
;* pointer to the path table...
;*
; clc ;Prepare to add.
; lda #vcr_path_table ;Get offset to path table.
; adc my_vcr ;Add to my_vcr ptr.
; sta path_table ;Save low word of pointer.
; lda #0 ;Do high word.
; adc my_vcr+2
; sta path_table+2
pha
pha ;space for NewHandle
pea 0 ;high word of size
lda path_table_size
pha ;low word of size
pha ;space for User ID
_MMStartUp ;use same User ID as our code (leave on stack)
pea $8000 ;handle initially locked
pha
pha ;garbage (ignored)
_NewHandle
plx
ply
bcs error
pei <path_ptr+2 ;preserve & use temporarily
pei <path_ptr
stx <path_ptr
sty <path_ptr+2
ldy #2
lda [<path_ptr],y
sta path_table+2
lda [<path_ptr]
sta path_table
ldy #vcr_path_tbl_handle+2
lda <path_ptr+2
sta [my_vcr],y
sta current_path_tbl_handle+2
dey
dey
lda <path_ptr
sta [my_vcr],y
sta current_path_tbl_handle
pla
sta <path_ptr
pla
sta <path_ptr+2
*** end 2-Dec-92
*
* Get the block number...
*
ldy vol_path_loc ;Get offset to path table location.
lda [io_buffer],y ;Get low word.
tax
iny ;Point to high word.
iny
lda [io_buffer],y ;Get high word.
*
* Set id_disk_flag, read in one block, clear id_disk_flag and exit if error...
*
read_loop inc id_disk_flag ;Set flag.
jsr block_read ;Do read.
stz id_disk_flag ;Clear flag. Read ok?
bcs error ;Nope.
*
* Append path_size bytes to path_table. Did we run out of data in the
* buffer?
*
ldy #0 ;Init offset.
append_loop lda [io_buffer],y ;Get byte.
sta [path_table],y ;Appen to vcr.
iny ;Bump offset.
iny
cpy log_blk_size ;Run out of buffer?
bcs read_more ;Yep.
cpy path_size ;No, moved all?
bcc append_loop ;No, so loop.
*
* No, activate_vcr and exit with carry clear...
*
do_activate jsr activate_vcr ;Activate it.
clc ;Clear carry.
rts ;Exit.
*
* Yes, adjust path_size, adjust path_table, bump block # and loop...
*
read_more sec ;Adjust path_size.
lda path_size
sbc log_blk_size
sta path_size
clc ;Adjust path_table.
lda path_table
adc log_blk_size
sta path_table
lda path_table+2
adc #0
sta path_table+2
ldx drvr_blk_num ;Get block #.
lda drvr_blk_num+2
inx ;Bump it.
bne read_loop ;Loop if didn't rollover.
inc a ;Rollover. Bump high word.
bra read_loop ;Loop.
*
* An error occured, free the vcr before exiting...
*
error pha ;Nope, save error code.
lda [my_vcr] ;Get the volume ID.
jsl release_vcr ;Release vcr.
pla ;Recover the error.
sec ;Indicate error.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: set_file_system
*
* Description: Copies either hs_offsets or iso_offsets into file_sys_table.
*
* Created: Feb 26, 1988
* Modified: Mar 23, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* state_flag ;b0 = 1 if ISO version of High Sierra.
* ;b1 = 1 if Apple Extensions disc.
* ;b2 = 1 if ProDOS Transformation required.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Exit: rts
*
* Uses: all registers
*
******************************************************************************
set_file_system proc
with data
*
* High Sierra or ISO?
*
ldy #file_sys_len ;Get length of table.
lda state_flag ;Get flag.
and #iso_bit ;Iso?
bne iso_loop ;Yes.
*
* High Sierra, so copy hs_offsets into file_sys_table...
*
hs_loop lda hs_offsets,y ;Get word.
sta file_sys_table,y ;Put in table.
dey ;Done all?
dey
bpl hs_loop ;Nope, so loop.
rts ;Yes, so exit.
*
* ISO, so copy iso_offsets into file_sys_table...
*
iso_loop lda iso_offsets,y ;Get word.
sta file_sys_table,y ;Put in table.
dey ;Done all?
dey
bpl iso_loop ;Nope, so loop.
rts ;Yes, so exit.
ENDP
eject
******************************************************************************
*
* Name: open
*
* Description: Opens file or directory and prepares for reading. Will build
* a new FCR if none exists.
*
* Created: Oct 20, 1987
* Modified: Oct 20, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Uses: All registers
* process_path
* build_fcr
* send_output
*
******************************************************************************
open proc
with data
*
* First go find the file requested...
*
jsr process_path ;Go find it.
bcs error ;Error.
*
* Now build the FCR if necessary...
*
jsr build_fcr ;Build fcr.
bcs error ;Error.
*
* Ok, we've opened the file. Send the output parameters and exit...
*
jsr send_output ;Send 'em.
error rts
ENDP
eject
******************************************************************************
*
* Name: process_path
*
* Description: Find location of file using full pathname. Will make sure
* that volume is online.
*
* Created: Oct 20, 1987
* Modified: Mar 5, 1991
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* dev_num ;holds device number if used.
* volume_name ;holds volume name.
* file_name ;holds file name.
* name_count ;# of names in path.
* name_offsets ;offsets to start of names in path.
* input_error ;set if input error.
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* storage_type ;1=file, 5=extended file, D=directory,
* or F=volume directory.
* dir_record_0 ;holds directory record.
* dir_record_1 ;holds associated dir record (if any).
* eof ;eof from dir_record_0.
* blocks_used ;blocks_used from dir_record_0.
* resource_eof ;eof from dir_record_1.
* resource_blocks ;blocks_used from dir_record_1.
* error_priority ;$8000 if we found the specified volume
*
* Uses: All registers
* find_a_vcr (sub)
* id_disk (sub)
* find_volume (sub)
* find_file (sub)
* get_dir_info (sub)
*
******************************************************************************
process_path proc
with data
*
* Clear out dir_record_0 and dir_record_1...
*
jsr clear_dir_recs ;Clear them.
*
* Make sure that all blocks read are cached...
*
lda #in_cache ;Cache 'em.
sta drvr_cache
*
* Do we have a device number or a volume name?
*
lda dev_num ;Is there a device #?
beq by_name ;No, so find by name.
*
* Device number. Do we have a vcr for it?
*
sta drvr_dev_num ;Set device number.
jsr find_a_vcr ;Do we have a vcr?
bcc check_file ;Yes.
*
* Nope, so id the disk. Exit if it's not mine, else continue on to
* check_file...
*
lda dev_num ;Get device #.
jsr id_disk ;Is it mine?
bcs error ;Nope, so exit.
bra check_file ;Yes.
*
* We have a volume name. Try to find the volume using volume_name...
*
by_name jsr find_volume ;Look for volume. Found?
bcs error ;Nope, so exit.
*
* Ok, we have the volume and my_vcr points to the vcr. Go find the file
* or directory. Found?
*
check_file lda #$8000 ;indicate that we found the volume
sta error_priority ;and it's my volume
; Begin 18-Dec-91 MSD: Make sure the maximum span is less than 32
; If not, return a bad path syntax error.
lda span1
cmp #32
bcc ok_path
lda #bad_path_syntax
bra error ; note: carry already set!
ok_path
; End 18-Dec-91 MSD
jsr find_file ;Go look for it. All ok?
bcs error ;Nope, so exit.
*
* Yes, so call get_dir_info and clear carry...
*
jsr get_dir_info ;Get parameters.
clc ;Indicate success.
*
* Restore user cache value. And exit if carry set. If clear and
* input_error set, exit with input_error...
*
error jsr set_user_cache ;Restore user cache value.
bcs check_error ;Exit if error.
lda input_error ;Was there an input error?
beq check_error ;Nope.
sec ;Yes, indicate error.
*
* If we have a path_not_found error and resource_num is non-zero, change
* the error to res_not_found...
*
check_error bcc exit ;No error, so exit.
cmp #path_not_found ;Path not found error?
beq check_resource ;Yes, so check for resource.
cmp #file_not_found ;No, file not found error?
sec ;(make sure carry set).
bne exit ;No, so exit.
check_resource ldx resource_num ;Yes, looking for resource?
beq exit ;No, so exit.
lda #res_not_found ;Yes, get other error code.
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: find_a_vcr
*
* Description: Looks for a vcr whose device # matches dev_num and whose
* id indicates that it belongs to me. Makes sure volume is
* online.
*
* Created: Oct 20, 1987
* Modified: Oct 20, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* dev_num ;device number to match.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = not found
* 0 = found
* B = K
*
* my_vcr ;Points to vcr if found.
*
* Uses: All registers
* temp0
* my_vcr
* setup_volume (sub)
*
******************************************************************************
find_a_vcr proc
with data
*
* Get vcr. Exit with carry set if checked all...
*
stz device ;Init to device 0.
loop inc device ;Bump device #
lda device ;Get it.
jsl get_vcr ;Get vcr.
bcc found_vcr ;Found.
rts ;Not found.
*
* Is this my vcr?
*
found_vcr jsl deref ;Dereference vp.
stx my_vcr ;Save pointer.
sty my_vcr+2
ldy #vcr_fst_id ;Get offset to fst id.
lda [my_vcr],y ;Get id.
cmp #hs_id ;Is it mine?
bne loop ;Nope, so loop.
*
* Yes, is it the right device #?
*
ldy #vcr_dev ;Get offset to device #.
lda [my_vcr],y ;Get #.
cmp dev_num ;Match?
bne loop ;Nope, so loop.
*
* Yes, exit thru setup_volume to make sure volume is online and setup some
* variables from the vcr...
*
jmp setup_volume ;Do setup.
ENDP
eject
******************************************************************************
*
* Name: find_volume
*
* Description: Looks for a volume whose name matches that in volume_name.
* If there is a vcr, will do a status call and if the volume
* has not been switched will return with carry clear.
*
* Created: Oct 20, 1987
* Modified: July 28, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* volume_name ;volume name to match.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = not found
* 0 = found
* B = K
*
* drvr_dev_num ;device number found.
* my_vcr ;Points to vcr.
*
* Uses: All registers
* my_vcr
* current_device
* start_device
* find_vcr (sub)
* id_disk (sub)
* transform_name (sub)
* dev_dispatcher (sys_service)
*
******************************************************************************
find_volume proc
with data
*
* Initialize...
*
lda #0001 ;Init device to 1.
sta current_device
stz start_device ;Clear start device.
*
* Look for vcr with volume_name. Found?
*
ldx #volume_name ;Get pointer to volume name.
ldy #^volume_name
lda #0000 ;Search by name.
jsl find_vcr ;Do search. Found one?
bcs check_device ;Nope.
*
* Yep, is it mine? Exit with unknown_vol error if not...
*
jsl deref ;Dereference pointer..
stx my_vcr ;Save it.
sty my_vcr+2
ldy #vcr_fst_id ;Get offset to id.
lda [my_vcr],y ;Get id.
cmp #hs_id ;Is it mine?
beq get_device ;Yes.
lda #unknown_vol ;No, get error code.
sec ;Indicate error.
rts ;Exit.
*
* Yep, get device # and setup to check it first...
*
get_device ldy #vcr_dev ;Get offset to device #.
lda [my_vcr],y ;Get device #.
sta drvr_dev_num ;Set driver device number.
sta current_device ;Set current.
sta start_device ;Set start.
*
* Has the vcr been marked as switched?
*
ldy #vcr_status ;Get offset to status.
lda [my_vcr],y ;Get word.
and #vcr_swapped ;Swapped?
bne check_id ;Yes, so must do search.
*
* No, so fire off a status call then check again. This will ensure that we
* know if the volume has been taken offline. If it has not been switched, then
* we can rest assured that the volume is present...
*
lda #drvr_status ;Set status command.
sta drvr_call_num
stz drvr_stat_code ;Set to status code 0. (!8/12/88)
lda #status_list ;Set status list pointer.
sta drvr_slist_ptr
lda #^status_list
sta drvr_slist_ptr+2
lda #6 ;Set request count.
sta drvr_req_cnt
stz drvr_req_cnt+2
jsl dev_dispatcher ;Do call. Error?
bcs check_id ;Yes, so go do id.
lda status_list ;Get status word. (!8/12/88)
and #switched_mask ;Swapped? (!8/12/88)
bne check_id ;Yes, so go do id.
clc ;Nope, so exit with carry clear.
rts
*
* Main loop.
* Need to check this device?
*
check_device lda start_device ;Get start device.
cmp current_device ;Same as current?
beq next_device ;Yes, so skip it cuz we already did it.
*
* Yes, id disk. Any errors?
*
check_id lda current_device ;Get current device #.
jsr id_disk ;Do id. Ok?
bcc check_match ;Yes.
*
* Yes. If it's a disk switched error, let's re-try id_disk. While this may
* look like an infinite loop, it's not because this error only occurs once per
* media transition...
*
cmp #drvr_disk_sw ;Is it a disk switched?
bne not_disksw ;Nope.
lda current_device ;Yes, get current device number.
bra check_id ;Re-try id_disk.
*
* Not a disk switched. If it's a device not found or duplicate volume error
* then exit, otherwise continue search...
*
not_disksw cmp #dup_volume ;Duplicate volume?
beq error ;Yes, so exit.
cmp #invalid_dev_num ;Checked all?
bne no_match ;No, so continue search.
no_such_vol lda #vol_not_found ;Get error code.
error sec ;Indicate error.
rts ;Exit.
*
* No error from id_disk. Does the name match?
*
check_match lda #$2e5f ;Get search and replace characters.
ldx #volume_name ;Get string address.
ldy #^volume_name
jsr transform_name ;Do transform if needed.
longa off ;Set 8 bit A.
sep #$20
ldy gstring ;Get length.
iny ;Bump it one for length word.
compare_loop lda volume_name,y ;Get byte.
cmp gstring,y ;Match?
bne undo_it ;Nope.
dey ;Yes, done all?
bpl compare_loop ;No, so loop.
longa on ;Set 16 bit A.
rep #$20
*
* Yes, so we've got it. Exit with carry clear...
*
found clc ;Indicate found.
rts ;Exit.
*
* No, undo transformation if necessary...
*
longa on ;Set 16 bit A.
undo_it rep #$20
lda #$5f2e ;Get search and replace characters.
ldx #volume_name ;Get string address.
ldy #^volume_name
jsr transform_name ;Do transform if needed.
*
* No, reset current_device if this is the start_device...
*
no_match lda current_device ;Get current.
cmp start_device ;Same as start?
bne next_device ;Nope.
stz current_device ;Yes, so reset current.
*
* Bump current device and loop...
*
next_device inc current_device ;Bump current.
bra check_device ;Loop.
ENDP
eject
******************************************************************************
*
* Name: find_file
*
* Description: Looks for a file whose name matches that in file_name.
*
* Created: Oct 21, 1987
* Modified: January 11, 1989
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_vcr ;points to vcr.
* file_name ;file name to match.
* name_count ;# of names in pathname.
* name_offsets ;offsets to start of names.
* drvr_dev_num ;device # of volume.
* resource_num ;associated file flag.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = not found
* 0 = found
* B = K
*
* storage_type ;1=file, 5=extended file, D=directory,
* or F=volume directory.
* dir_record_0 ;holds directory record.
* dir_record_1 ;holds associated file record if
* ;present and we were not looking for
* ;an associated file.
*
* Uses: All registers
* storave_type
* dir_record_0
* dir_record_1
* record_offset
* dir_length
* eof
* length
* log_blk_size
* transform_in_f (sub)
* activate_vcr (sub)
* find_directory (sub)
* block_read (sub)
* move_dir_record (sub)
* search_dir (sub)
* read_next_block (sub)
*
******************************************************************************
find_file proc
with data
*
* First, make sure the vcr is activated and the path table parameters
* are set up...
*
jsr activate_vcr ;Do activate.
*
* Get location of directory, set start_block, and read it in...
*
jsr find_directory ;Go find it.
bcs error ;Exit on error.
stx start_block ;Save start block.
sta start_block+2
ldy #sector_size ;Set to read 2k.
jsr device_read ;Read in block.
bcs error ;Exit on error.
*
* Copy first directory record to dir_record_0 (in case there is no file),
* force directory bit in file_flags to 1 (cuz sometimes not set), clear invisible
* bit in file_flags (in case call is get_file_info on a directory), and set
* end_block...
*
lda #0 ;Select dir_record_0.
sta record_offset ;Clear offset.
jsr move_dir_record ;Move it.
ldx dir_file_flags ;Get offset to file_flags. (2/29/88)
lda dir_record_0,x ;Get flags.
ora #dir_mask ;Set directory bit.
and #clear_invisible ;Clear invisible bit.
sta dir_record_0,x ;Save flags.
stz interleave_size ;Clear interleave values.
stz interleave_skip
ldx dir_record_0+dir_data_length ;Get low word of length.
lda dir_record_0+dir_data_length+2 ;Get high word of length.
jsr set_end_block ;Set end_block...
*
* Are we looking for a directory?
*
lda storage_type ;Get type.
cmp #type_file ;Is it a file?
beq transform ;Yes.
*
* Yes, so force log_blk_size to 2k. If resource_num is clear then branch to
* found, else exit with path_not_found error...
*
lda #sector_size ;Force log_blk_size to 2k.
sta log_blk_size
lda resource_num ;No, is resource_num set?
beq found ;Nope, so we're done.
lda #path_not_found ;Yes, get error code.
sec ;Indicate error.
rts ;Exit.
*
* Transform file_name if needed. If this is a High Sierra volume and resource_num
* is set, exit with a file_not_found error 'cuz we don't support associated files
* for High Sierra...
*
transform jsr transform_in_f ;Transform file_name string if needed.
lda resource_num ;Looking for associated file?
beq search_loop ;Nope.
lda state_flag ;Yes, is this a High Sierra volume?
and #iso_bit
beq not_found ;Yep, so error.
*
* We're looking for a file, so let's search for it. Found it?
*
search_loop lda resource_num ;Get associated file flag.
jsr search_dir ;Do search. Success?
bcc found_file ;Yes.
lda log_blk_size ;Save logical block size.
pha
lda #sector_size ;Force to sector size.
sta log_blk_size
jsr read_next_block ;Nope, get next directory block.
plx ;Restore logical block size.
stx log_blk_size
bcc search_loop ;Loop if no error.
*
* Not found. Exit with file not found error...
*
not_found lda #file_not_found ;Get error code.
error sec ;Indicate error.
rts ;Exit.
*
* Yes, move directory record to dir_record_0. If we found an associated file
* then set storage_type to extended...
*
found_file lda #0 ;Select dir_record_0.
jsr move_dir_record ;Move record.
lda extended_flag ;Did we find an associated file?
beq found ;Nope.
lda #type_extended ;Yes, set extended type.
sta storage_type
*
* Exit with carry clear...
*
found clc ;Indicate no error.
rts
ENDP
eject
******************************************************************************
*
* Name: find_directory
*
* Description: Searches path table for correct directory and returns block
* # of directory. Sets storage_type to indicate whether caller
* is looking for a file or a directory.
*
* Created: Oct 22, 1987
* Modified: Mar 10, 1989
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* path_ptr ;pointer to path name
* name_count ;# of names in pathname.
* name_offsets ;offsets to start of names.
*
* Output: A = high word of block #, or error code if error.
* X = low word of block #.
* Y = undefined
* P = nvmxdizc
* ..000..1 = not found
* 0 = found
* B = K
*
* storage_type ;1=file, D=directory, F=volume directory
* current_name ;points to file name offset if file.
*
* Uses: All registers
* my_vcr
* current_name
* string_buffer
* temp_offsets
* temp0
* record_number
* transform_in_s (sub)
* get_name (sub)
* search_path_tbl (sub)
*
******************************************************************************
find_directory proc
with data
*
* Start by setting up to point to volume name in case there is only a volume
* name, and set record_number to 1 (always the root directory). Init storage
* type to volume directory...
*
lda #type_vol_dir ;Init storage type to volume directory.
sta storage_type
stz current_name ;Point to volume name.
lda #0 ;Init last_offset to record 1.
ldx #1 ;Set record_number = 1.
*
* Main loop.
* Point to next name. Have we done them all?
*
walk_path stx current_record ;Save current record number.
sta last_offset ;Save last offset.
inc current_name ;Bump current name.
ldy current_name ;Get it.
cpy name_count ;Done all?
bcs dir_found ;Yes, so we've got it.
*
* Nope, set storage_type to directory and search the path table for name.
* Did we find it?
*
lda #type_directory ;Set storage type to directory.
sta storage_type
jsr get_name ;Put the name in string_buffer.
jsr transform_in_s ;Transform name if needed.
ldx #0 ;Get starting record #.
try_again jsr search_path_tbl ;Go look for it. Found?
bcs name_not_found ;Nope.
*
* Yes, loop if parent record matches the current record...
*
cpy current_record ;Match?
beq walk_path ;Yes, so loop.
*
* Doesn't match. Is there another one in the path table past the one
* we just found? (record # is in X from last search)
*
bra try_again ;Go look again.
*
* Name not found. Are we looking at the last name in the pathname?
*
name_not_found ldy current_name ;Get current.
iny ;Bump it one.
cpy name_count ;Was it the last one?
beq last_one ;Yes.
*
* Nope, so exit with path not found error...
*
lda #path_not_found ;Get error code.
sec ;Set carry.
rts ;Exit.
*
* Yes, we are, so assume it is a file name. Set storage_type to file...
*
last_one lda #type_file ;Set storage type to file.
sta storage_type
*
* We've got it. If this directory has an XAR on it, exit with a dir_error,
* else exit with block # in A and X and carry clear...
*
dir_found clc ;Point to XAR length.
lda last_offset
adc pt_xar_len
tay
lda [path_table],y ;Get length.
and #$00ff ;Make 1 byte. Zero?
beq get_location ;Yes, so ok.
lda #dir_error ;No, get error code.
sec ;Indicate error.
rts ;Exit.
get_location clc ;Calc offset to location of extent.
lda last_offset
adc pt_loc_extent
tay
lda [path_table],y ;Get low word of directory location.
tax ;Put in X.
iny ;Bump offset.
iny
lda [path_table],y ;Get high word of location in A.
clc ;Indicate found.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: search_path_tbl
*
* Description: Searches pathtable for name in string_buffer, starting one
* entry past the record # passed in X.
*
* Created: Oct 22, 1987
* Modified: May 31, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = starting record #. Set to 0 for full search.
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* string_buffer ;name to match.
* path_table ;pointer to pathtable.
* path_table_size ;size of pathtable.
*
* Output: A = entry_offset.
* X = record number.
* Y = parent record number.
* P = nvmxdizc
* ..000..1 = not found
* 0 = found
* B = K
*
* Uses: All registers
* string_buffer
* path_table
* entry_offset
* length
* record_number
* temp1
*
******************************************************************************
search_path_tbl proc
with data
*
* Save start_record and set record_number, length, and entry offset
* for first entry (the root directory), which we always want to skip
* because there is no name there...
*
stx start_record ;Save start record.
lda #1 ;Init record # and length to 1.
sta record_number
sta length
ldy #0 ;Init offset.
sty entry_offset ;Save it.
*
* Main loop.
* Bump offset to next entry and bump record #...
*
longa on ;Make sure in 16 bit mode.
next_entry rep #$20
clc ;Point to length byte.
lda length ;Get length.
bit #1 ;Is it odd?
beq its_even ;Nope.
inc a ;Yes, so bump length by 1.
its_even adc #pt_entry_len ;Add length to entry offset.
adc entry_offset ;Add it to current pointer.
tay ;Put back in y.
sty entry_offset ;Save offset to start of entry.
inc record_number ;Bump record number.
*
* Have we reached the end of the table?
*
cpy path_table_size ;Reached end?
bcs exit ;Yes, exit with carry set.
*
* No, does the name match? (Note: if branch above changes must clc
* before add).
*
tya ;Point Y at length byte.
adc pt_len_di
tay
adc pt_di_offset ;Point X at directory identifier.
tax
longa off ;Set 8 bit A.
sep #$20
lda [path_table],y ;Get length.
sta length ;Save it.
cmp string_buffer ;Match our length?
bne next_entry ;Nope, so next entry.
txy ;Yes, point to directory identifier.
ldx #0 ;Init offset to string_buffer.
check_loop lda string_buffer+1,x ;Get byte.
cmp [path_table],y ;Match?
bne next_entry ;Nope, so next entry.
iny ;Bump offsets.
inx
cpx length ;Done all?
bne check_loop ;No, so continue.
*
* Yes, are we past the starting record #?
*
longa on ;Restore 16 bit A.
rep #$20
lda start_record ;Get start record number.
cmp record_number ;Less than current?
bcs next_entry ;Nope, so continue.
*
* Yes, so get offset, record number and parent record, and exit with
* carry clear...
*
clc ;Point to pt_parent_dir.
lda #pt_parent_dir
adc entry_offset
tay
lda [path_table],y ;Get parent record #.
tay ;Put in Y.
lda entry_offset ;Get offset in A.
ldx record_number ;Get record number in X.
clc ;Indicate no errors.
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: move_dir_record
*
* Description: Copies directory record to dir_record 0 or 1.
*
* NOTE: Uses self-modifying code!
*
* Created: Oct 22, 1987
* Modified: Oct 29, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = destination: 0 = dir_record_0, 1 = dir_record_1
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* record_offset ;offset to start of record.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* dir_record_0 ;holds record 0.
* dir_record_1 ;holds record 1.
*
* Uses: All registers
* dir_record_0
* dir_record_1
* length
* output_string
*
******************************************************************************
move_dir_record proc
with data
*
* Set destination address...
*
ldx #dir_record_0 ;Get pointer to record 0.
tay ;Move to 0?
beq set_address ;Yes.
ldx #dir_record_1 ;Nope, get pointer to record 1.
set_address stx self_mod+1 ;Set pointer.
*
* Copy record and exit...
*
ldy record_offset ;Get offset to record.
lda [io_buffer],y ;Get length.
and #$00ff ;Make 1 byte.
sta length ;Save it.
ldx #0 ;Init offset to buffer.
copy_loop lda [io_buffer],y ;Get byte.
self_mod sta $ffff,x ;Put in record.
iny ;Bump offsets.
inx
cpx length ;Done all?
bne copy_loop ;No, so loop.
rts ;Yes, so exit.
ENDP
eject
******************************************************************************
*
* Name: clear_dir_recs
*
* Description: Clears both dir_record_0 and dir_record_1.
*
* Created: Nov 9, 1987
* Modified: Nov 9, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Uses: All registers
* dir_record_0
* dir_record_1
*
******************************************************************************
clear_dir_recs proc
with data
*
* Clear out dir_record_0 and dir_record_1 and exit...
*
ldx #max_rec_len-2 ;Point to end of record.
clear_loop stz dir_record_0,x ;Clear word.
stz dir_record_1,x ;Clear word.
dex ;Done all?
dex
bpl clear_loop ;No, so loop.
rts ;Yes, so exit.
ENDP
eject
******************************************************************************
*
* Name: search_dir
*
* Description: Searches directory in io_buffer for record with a file name
* that matches the name in file_name.
*
* Created: Oct 23, 1987
* Modified: Jun 6, 1989
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = 1 if looking for an associated file, 0 if not
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* file_name ;file name to match.
* io_buffer ;points to directory.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* record_offset ;offset to record.
* extended_flag ;1 if found a matching associated file.
* dir_record_1 ;holds associated file record if
* ;present and we were not looking for
* ;an associated file.
*
* Uses: All registers
* record_offset
* length
* temp0
*
******************************************************************************
search_dir proc
with data
*
* Save file_type, init record offset and clear extended_flag ...
*
sta file_type ;Save file type.
ldy #0 ;Init record offset.
sty extended_flag ;Clear extended_flag .
*
* Have we done all records?
*
search_loop sty record_offset ;Save offset.
cpy #sector_size ;Done all?
bcs not_found ;Yes, so not found.
lda [io_buffer],y ;No, get length of record.
and #$00ff ;We only want 1 byte. Zero?
beq not_found ;Yes, so not found.
sta length ;No, save it.
*
* No, does the name match?
*
clc ;Point to dir_len_fi.
tya
adc #dir_len_fi
tay
longa off ;Set 8 bit A.
sep #$20
lda [io_buffer],y ;Get length.
cmp file_name ;Match length?
bne next_record ;Nope.
iny ;Yes, point to file identifier.
ldx #0 ;Init offset to file_name.
check_loop lda file_name+2,x ;Get byte.
cmp [io_buffer],y ;Match?
bne next_record ;Nope.
iny ;Yes, bump offsets.
inx
cpx file_name ;Done all?
bne check_loop ;No, so continue.
*
* Yes, is this a file?
*
longa on ;Back to 16 bit A.
rep #$20
clc ;Point to dir_file_flags.
lda dir_file_flags
adc record_offset
tay
lda [io_buffer],y ;Get flags byte.
and #dir_mask ;Is this a file?
bne next_record ;Nope, so next record.
longa off ;Back to 8 bit A.
sep #$20
*
* Yes, does associated file bit match the file_type flag?
*
lda [io_buffer],y ;Get flags byte.
and #assoc_mask ;Isolate associated file bit.
lsr a ;Shift to bit 0.
lsr a
cmp file_type ;Is it what we're looking for?
beq found ;Yes, so exit.
*
* Nope. If this is an associated file then set extended_flag and copy
* directory record to dir_record_1...
*
cmp #1 ;Is it an associated file?
bne next_record ;Nope.
sta extended_flag ;Yes, so set flag.
ldx #0 ;Init offset to buffer.
ldy record_offset ;Get offset to record.
copy_loop lda [io_buffer],y ;Get byte.
sta dir_record_1,x ;Put in record.
iny ;Bump offsets.
inx
cpx length ;Done all?
bne copy_loop ;No, so loop.
*
* Skip to the next record...
*
longa on ;Make sure 16 bit mode.
next_record rep #$20
clc ;Add length to offset.
lda length
adc record_offset
tay
bra search_loop ;And loop.
*
* Yes, so exit with carry clear...
*
longa on ;Make sure 16 bit mode.
found rep #$20
clc ;Indicate success.
rts ;Exit.
*
* It's not here. Exit with file not found error...
*
longa on ;Make sure 16 bit mode.
not_found rep #$20
lda #file_not_found ;Get error code.
sec ;Indicate error.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: build_fcr
*
* Description: Create a new FCR. Uses the last name in the pathname as the
* FCR name, or, if there is only a device #, will use the volume
* name found by id_disk. Puts first block of file into the
* FCR; if the file is less than 1 block long, the FCR size is
* allocated accordingly.
*
* Created: Oct 29, 1987
* Modified: Feb 17, 1989
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* storage_type ;1=file, 5=extended file, D=directory,
* or F=volume directory.
* name_count ;# of names in path.
* name_offsets ;offsets to start of names in path.
* dir_record_0 ;holds directory record.
* dir_record_1 ;holds associated dir record (if any).
*
* Output: A = error code if error.
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* my_fcr ;Points to fcr.
* open_buf_ptr ;Points to open buffer in fcr.
*
* Uses: All registers
* my_fcr
* length
* temp0
* dir_length
*
******************************************************************************
build_fcr proc
with data
*
* If the file is a directory, set log_blk_size to 2k, else set it using the
* value in the vcr...
*
lda #sector_size ;Init log_blk_size to 2k.
sta log_blk_size
lda storage_type ;Get storage type.
cmp #type_directory ;Is this a directory?
bcs get_length ;Yep.
ldy #vcr_block_size ;Nope, get block size from vcr.
lda [my_vcr],y
sta log_blk_size ;Set new logical block size.
*
* Ok, now set length = to the smaller of eof or log_blk_size. Set
* short_file_flag if eof < 1 block and make sure length is even...
*
get_length lda log_blk_size ;Get log_blk_size.
sta length ;Set length
stz short_file_flag ;Clear flag.
lda dir_record_0+dir_data_length+2 ;Get high eof. Zero?
bne calc_size ;Nope, use log_blk_size.
lda dir_record_0+dir_data_length ;Get low eof. Zero?
cmp log_blk_size ;< log_blk_size?
bcs calc_size ;Nope.
inc short_file_flag ;Yes, set flag.
bit #1 ;Is eof odd?
beq set_length ;Nope.
inc a ;Yes, so make it even.
set_length sta length ;Save size.
*
* Calculate size of fcr and allocate it...
*
calc_size clc
lda #fcr_dir_record ;Get offset to dir_record.
adc dir_record_0 ;Add length of dir_record.
; 1/11/89 adc dir_record_1 ;Add length of assoc_record.
and #$00ff ;Clear high byte cuz lengths are bytes.
adc length ;Add size.
bcs mem_error ;Exit if too big.
ldx #gstring ;Get pointer to volume name.
ldy #^gstring
jsl alloc_fcr ;Allocate it.
bcc build_it ;Continue if no error.
*
* We couldn't allocate it, exit with out of memory error...
*
mem_error lda #out_of_mem ;Get error code.
rts ;Exit.
*
* Get pointer to fcr and dir_record in fcr...
*
build_it jsl deref ;Dereference vp.
stx my_fcr ;Save pointer.
sty my_fcr+2
clc ;Make a pointer to dir_record.
txa
adc #fcr_dir_record
sta fcr_dir_ptr
tya
adc #0
sta fcr_dir_ptr+2
*
* Copy directory record into fcr...
*
lda dir_record_0 ;Get length.
and #$00ff ;Make one byte.
sta dir_length ;Save it for later.
tay ;Use as offset.
longa off ;Set 8 bit A.
sep #$20
copy_loop dey ;Done all?
bmi continue ;Yes.
lda dir_record_0,y ;No, get byte.
sta [fcr_dir_ptr],y ;Put in fcr.
bra copy_loop ;Loop.
longa on ;Set 16 bit A.
continue rep #$20
*
* Get reference number...
*
ldy #fcr_ref_num ;Get offset to reference num.
lda [my_fcr],y ;Get #.
sta ref_num ;Save it.
*
* Set access to read only and indicate that the file is never modified by
* setting the high bit, and set bit 14 if this is a resource fork...
*
ldy #fcr_access ;Get offset to access.
lda #read_access+$8000 ;Set to read only.
ldx resource_num ;Resource fork?.
beq save_access ;Nope.
ora #%0100000000000000 ;Yes, so set bit 14.
save_access sta [my_fcr],y ;Save it.
*
* Set position, open_mark, entry_num, error_flag and type_flag to zero and
* start_record to one...
*
lda #0000 ;Get zero.
ldy #fcr_position ;Get offset to low word of position.
sta [my_fcr],y ;Clear it.
ldy #fcr_open_mark ;Get offset to mark.
sta [my_fcr],y ;Clear it.
ldy #fcr_position+2 ;Get offset to low word of position.
sta [my_fcr],y ;Clear it.
ldy #fcr_entry_num ;Get offset to entry_num.
sta [my_fcr],y ;Clear it.
ldy #fcr_error_flag ;Get offset to error_flag.
sta [my_fcr],y ;Clear it.
ldy #fcr_type_flag ;Get offset to type_flag.
sta [my_fcr],y ;Clear it.
inc a ;Get one.
ldy #fcr_start_rec ;Get offset to start_record.
sta [my_fcr],y ;Save it.
*
* Fill in fcr_storage...
*
ldy #fcr_storage ;Get offset to storage.
lda storage_type ;Get type.
sta [my_fcr],y ;Put in fcr.
*
* Fill in fcr_eof...
*
ldy #fcr_eof ;Get offset to low word.
lda eof ;Get low word.
sta [my_fcr],y ;Put in fcr.
ldy #fcr_eof+2 ;Get offset to high word.
lda eof+2 ;Get high word.
sta [my_fcr],y ;Put in fcr.
*
* Fill in fcr_blks...
*
ldy #fcr_blks ;Get offset to low word.
lda blocks_used ;Get low word.
sta [my_fcr],y ;Put in fcr.
ldy #fcr_blks+2 ;Get offset to high word.
lda blocks_used+2 ;Get high word.
sta [my_fcr],y ;Put in fcr.
*
* Set fcr_skip_count = interleave_size. If interleave_size = 0 then set
* fcr_skip_count to $ffff so that the calculation for direct reading will
* be happy...
*
ldy #fcr_skip_count ;Get offset to word.
lda dir_record_0+dir_int_size ;Get interleave_size.
and #$00ff ;Clear high byte. Zero?
bne save_skip ;Nope.
dec a ;Yes, so make $ffff.
save_skip sta [my_fcr],y ;Put in fcr.
*
* Calculate start block by adding the Extended Attribute Record (XAR) length
* to the Location of Extent, and put in fcr_open_block. Set drvr_blk_num...
*
do_open clc ;Prepare for add.
ldy #fcr_open_block ;Get offset to field.
lda dir_record_0+1 ;Get XAR length.
and #$00ff ;Make sure only 1 byte.
adc dir_record_0+dir_loc_extent ;Add low word of start block.
sta [my_fcr],y ;Put in fcr.
sta drvr_blk_num ;Save it.
ldy #fcr_open_block+2 ;Get offset to field.
lda dir_record_0+dir_loc_extent+2 ;Get high start block.
adc #0 ;Add in carry.
sta [my_fcr],y ;Put in fcr.
sta drvr_blk_num+2 ;Save it.
*
* Make pointer to open buffer in fcr...
*
clc ;Add dir_length to fcr_dir_ptr.
lda dir_length
adc fcr_dir_ptr
sta open_buf_ptr
tax
lda #0
adc fcr_dir_ptr+2
sta open_buf_ptr+2
*
* If short_file_flag is clear, set drvr_buf_ptr = open_buf_ptr. Otherwise,
* set it to io_buffer...
*
ldy short_file_flag ;Short file?
beq set_buf ;No, so use open_buf_ptr.
ldx io_buffer ;Yes, get pointer to io_buffer.
lda io_buffer+2
set_buf stx drvr_buf_ptr ;Set low word of drvr_buf_ptr.
sta drvr_buf_ptr+2 ;Set high word of drvr_buf_ptr.
*
* Read one block. Error?
*
lda log_blk_size ;Get log_blk_size.
sta drvr_req_cnt ;Set request count.
stz drvr_req_cnt+2
jsr common_read ;Do read. Error?
bcc keep_going ;Nope, so continue.
*
* Yes, so release fcr and exit...
*
pha ;Save error code.
lda [my_fcr] ;Get reference #.
jsl release_fcr ;Release fcr.
pla ;Get error code.
sec ;Indicate error.
rts ;Exit.
*
* No, if short_file_flag is set then we must copy the data from the io_buffer
* into our fcr...
*
keep_going lda short_file_flag ;Short file?
beq finish_up ;No, so finish up.
ldy length ;Point to end.
data_loop dey ;Done all?
dey
bmi finish_up ;Yes, so finish up.
lda [io_buffer],y ;No, get word.
sta [open_buf_ptr],y ;Put in fcr.
bra data_loop ;Loop.
*
* Update vcr_open_cnt, fcr_fst_id, and fcr_vol_id, and exit with
* carry clear...
*
finish_up ldy #vcr_open_cnt ;Get offset to field.
lda [my_vcr],y ;Get count.
inc a ;Bump it.
sta [my_vcr],y ;Save it.
ldy #fcr_fst_id ;Get offset to field.
lda #hs_id ;Get fst id.
sta [my_fcr],y ;Put in fcr.
ldy #fcr_vol_id ;Get offset to field.
lda [my_vcr] ;Get vol ID.
sta [my_fcr],y ;Put in fcr.
clc ;Indicate success.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: get_dir_info
*
* Description: Get information out of dir_rec_0 and dir_rec_1 and put it in
* the output parameter storage area...
*
* Created: Oct 30, 1987
* Modified: July 14, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* dir_record_0 ;holds directory record.
* dir_record_1 ;holds associated dir record (if any).
* my_vcr ;points to current vcr.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* eof ;eof from dir_record_0.
* blocks_used ;blocks_used from dir_record_0.
* resource_eof ;eof from dir_record_1.
* resource_blocks ;blocks_used from dir_record_1.
*
* Uses: All registers
*
******************************************************************************
get_dir_info proc
with data
*
* Save log_blk_size and set it from vcr...
*
lda log_blk_size ;Save current size.
pha
ldy #vcr_block_size ;Get size from vcr.
lda [my_vcr],y
sta log_blk_size ;Set new size.
*
* Fill in eof from dir_record_0...
*
ldy #dir_data_length ;Get offset to low word of data len.
lda dir_record_0,y ;Get low word.
sta eof ;Put in eof.
tax ;Save for division.
ldy #dir_data_length+2 ;Get offset to high word of data len.
lda dir_record_0,y ;Get high word.
sta eof+2 ;Put in eof.
*
* Fill in blocks_used from dir_record_0...
*
jsr calc_blocks ;Calculate blocks used.
stx blocks_used ;Save blocks_used.
sta blocks_used+2
*
* Fill in resource_eof from dir_record_1...
*
ldy #dir_data_length ;Get offset to low word of data length.
lda dir_record_1,y ;Get low word.
sta resource_eof ;Put in resource_eof.
tax ;Save for division.
ldy #dir_data_length+2 ;Get offset to high word of data len.
lda dir_record_1,y ;Get high word.
sta resource_eof+2 ;Put in resource_eof.
*
* Fill in resource_blocks from dir_record_1...
*
jsr calc_blocks ;Calculate blocks used.
stx resource_blocks ;Save resource_blocks.
sta resource_blocks+2
*
* Restore log_blk_size and exit...
*
pla ;Recover log_blk_size.
sta log_blk_size ;Restore it.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: calc_blocks
*
* Description: Calculates blocks_used from eof.
*
* Created: Oct 29, 1987
* Modified: Oct 29, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = high word of eof
* X = low word of eof
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* log_blk_size ;logical block size.
*
* Output: A = high word of blocks_used
* X = low word of blocks_used
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Uses: All registers
*
******************************************************************************
calc_blocks proc
with data
*
* Set dividend = eof. Exit if eof is zero...
*
stx dividend ;Save low word of eof.
sta dividend+2 ;Save high word of eof.
ora dividend ;Eof zero?
beq exit ;Yes, so exit.
*
* Set divisor = log_blk_size and do division...
*
do_divide lda log_blk_size ;Set divisor = log_blk_size.
sta divisor
stz divisor+2
jsr long_divide ;Do division.
*
* Bump count if remainder not zero...
*
lda remainder ;Remainder zero?
ora remainder+2
beq get_it ;Yes.
inc dividend ;No, bump count.
bne get_it
inc dividend+2
*
* Get blocks_used and exit...
*
get_it ldx dividend ;Get low word.
lda dividend+2 ;Get high word.
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: read
*
* Description: Read from an open file.
*
* Created: Nov 12, 1987
* Modified: May 2, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_vcr ;points to vcr.
* my_fcr ;points to fcr.
* request_count ;maximum number of bytes to read.
*
* Output: A = error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Uses: All registers
* send_flag
* request_count
* newline_length
* newline_mask
* newline_ptr
* newline_char
* eof
* position
* interleave_size
* interleave_skip
* interleave_next
* deref (system service)
* move_info (system service)
* setup_open_buf (sub)
* send_from_open (sub)
* read_next_block (sub)
* update_fcr (sub)
*
******************************************************************************
read proc
with data
*
* Set cache value using caller's cache_priority and clear transfer count...
*
lda cache_priority ;Get value.
sta drvr_cache ;Set/clear driver flag.
stz transfer_count ;Clear count.
stz transfer_count+2
*
* Exit thru send_output if request count is zero...
*
lda request_count ;Count zero?
ora request_count+2
bne continue ;Nope.
jmp send_output ;Yes, so exit.
*
* Check our fcr_type_flag and exit with invalid_access error if this FCR
* has been accessed by get_dir_entry. If the flag is clear, claim this file
* for reading by setting the flag to 1...
*
continue ldy #fcr_type_flag ;Get offset to type_flag.
lda [my_fcr],y ;Get flag. Set already?
bne check_flag ;Yes.
inc a ;No, so set it to 1.
sta [my_fcr],y
bra check_dir ;And continue.
check_flag cmp #1 ;Are we allowed to read this file?
bne bad_access ;Nope, so exit with error.
*
* If this is a directory and class is zero, exit with an invalid_access error...
*
check_dir ldy #fcr_storage ;Get offset to storage_type.
lda [my_fcr],y ;Get type.
cmp #type_directory ;Is it a directory?
bcc setup_vol ;Nope, so we're ok.
lda class ;Yes, is it class zero?
bne setup_vol ;Nope, so we're ok.
bad_access lda #invalid_access ;Yes, so exit with error.
brl error_exit
*
* Make sure volume is online and setup some variables from the vcr...
*
setup_vol jsr setup_volume ;Do setup. Online?
bcc online ;Yes.
rts ;Nope, so exit.
*
* Setup and check open buffer...
*
online jsr setup_open_buf ;Do it.
jsr check_open_buf ;Make sure data is valid.
bcc set_newline ;Continue if no error.
rts ;Else exit.
*
* Get newline mask from the FCR and save it. Is newline enabled?
*
set_newline ldy #fcr_mask ;Get offset to mask.
lda [my_fcr],y ;Get mask.
sta newline_mask ;Save it. Enabled?
beq skip_newline ;Nope.
*
* Yes, so get pointer to newline list, set newline_length and newline_char...
*
ldy #fcr_newline ;Get offset to vp.
lda [my_fcr],y ;Get low word.
tax ;Put in X.
iny ;Point to high word.
iny
lda [my_fcr],y ;Get high word.
tay ;Put in Y.
jsl deref ;Dereference vp.
stx newline_ptr ;Save pointer.
sty newline_ptr+2
ldy #fcr_newline_len ;Point at length.
lda [my_fcr],y ;Get it.
sta newline_length ;Save it.
lda [newline_ptr] ;Get first newline character.
sta newline_char ;Save it.
*
* Get current position and eof...
*
skip_newline ldy #fcr_eof ;Point to low word of eof.
lda [my_fcr],y ;Get low word.
sta eof ;Save it.
iny ;Point to high word.
iny
lda [my_fcr],y ;Get high word.
sta eof+2 ;Save it.
ldy #fcr_position ;Point to low word of position.
lda [my_fcr],y ;Get low word.
sta position ;Save it.
tax ;Keep for compare.
iny ;Point to high word.
iny
lda [my_fcr],y ;Get high word.
sta position+2 ;Save it.
*
* Exit with end_of_file error if position = eof...
*
cmp eof+2 ;Match?
bne set_bytes_left ;Nope.
cpx eof ;Maybe.
bne set_bytes_left ;Nope.
lda #end_of_file ;Yes, get error code.
bra error_exit
*
* Set bytes_left = eof - position. If bytes_left is larger than request_count
* then set bytes_left = request_count...
*
set_bytes_left sec ;Do it.
lda eof
sbc position
sta bytes_left
tax
lda eof+2
sbc position+2
sta bytes_left+2
cmp request_count+2 ;Bytes_left > request_count?
bcc check_size ;Nope.
bne set_to_request ;Yes.
cpx request_count ;Maybe.
bcc check_size ;Nope.
set_to_request ldx request_count ;Set bytes_left = request_count.
lda request_count+2
stx bytes_left
sta bytes_left+2
*
* If bytes_left is >= 16 Mb then set it to 16 Mb - 1...
*
check_size cmp #$0100 ;Too big?
bcc set_flag ;Nope.
lda #$ffff ;Yes, so squash it.
sta bytes_left
lda #$00ff
sta bytes_left+2
*
* Set send_flag. Do we have to watch for newline?
*
set_flag lda #1 ;Set send_flag.
sta send_flag
*
* Send data from open buffer. Did we satisfy the request?
*
read_loop jsr transfer_data ;Do send. Did we satisfy the request?
bne all_done ;Yep.
*
* No, do we have at least one block left in request and is newline disabled?
* (bytes_left is in X and Y)
*
lda newline_mask ;Newline enabled?
bne double_buffer ;Yes, so we must double buffer.
tya ;Bytes_left >= log_blk_size?
bne do_direct ;Yes.
cpx log_blk_size ;Maybe.
bcc double_buffer ;Nope.
*
* Yes, clear send_flag and read as many blocks as possible directly into
* data_buffer. Loop if no error...
*
do_direct stz send_flag ;Clear flag.
jsr direct_read ;Do it. Any errors?
bcc read_loop ;Nope.
bra error ;Yep.
*
* We must double_buffer, so point io_buffer back to open_buffer and set
* send_flag to force transfer_data to do the move_info...
*
double_buffer lda open_buf_ptr ;Get pointer to open_buffer.
ldx open_buf_ptr+2
sta io_buffer ;Set io_buffer.
stx io_buffer+2
lda #1 ;Set send_flag.
sta send_flag
*
* Read in next block. Loop if no error...
*
jsr read_next_block ;Read block.
bcc read_loop ;No error, so loop.
*
* We got an error while reading. Update fcr with position information,
* send transfer_count, and exit with carry set and error code in A...
*
error pha ;Save error code.
jsr all_done ;Do update.
pla ;Recover error code.
error_exit sec ;Indicate error.
rts ;Exit.
*
* Ok, we're done with the read. Did we manage to satisfy the request with
* the direct_read call? If so, we must restore the io_buffer pointer, set
* open_mark = log_blk_size, and set fcr_error_flag to indicate that the data
* in the open_buffer is not valid...
*
all_done lda send_flag ;Is flag clear?
bne do_update ;Nope.
lda open_buf_ptr ;Yes, get pointer to open_buffer.
ldx open_buf_ptr+2
sta io_buffer ;Restore io_buffer pointer.
stx io_buffer+2
lda log_blk_size ;Set open_mark = log_blk_size.
sta open_mark
sec ;Set fcr_error_flag.
jsr condition_flag
*
* Update fcr with current position information and send output...
*
do_update ldx drvr_blk_num ;Get current block #.
lda drvr_blk_num+2
jsr update_fcr ;Do update.
jsr send_output ;Send transfer_count.
*
* If this is a directory then we must exit with the fst_caution error code, else
* exit with carry clear...
*
ldy #fcr_storage ;Get offset to storage_type.
lda [my_fcr],y ;Get type.
cmp #type_directory ;Is it a directory?
bcc exit ;Nope, so we're ok.
lda #fst_caution ;Yes, so exit with error.
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: transfer_data
*
* Description: Transfer data from open_buffer to data_buffer and update
* position information.
*
* Created: Nov 17, 1987
* Modified: May 2, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* send_flag ;0 = do update only.
* data_buffer ;points to caller's buffer.
* open_buf_ptr ;points to open_buffer.
* eof ;end of file.
* newline_length ;length of newline table.
* newline_ptr ;pointer to newline table.
* newline_mask ;mask for newline character.
* newline_char ;first byte of newline table.
* position ;current file mark.
* open_mark ;current position within open buffer.
* transfer_count ;current bytes transfered.
* bytes_left ;# bytes till satisfy request.
* log_blk_size ;current size of blocks.
* read_size ;size used in multi-block reads.
*
* Output: A = status_flag: 0 = continue, 1 = satisfied request
* X = low word of bytes_left
* Y = high word of bytes_left
* P = nvmxdizc
* ..000...
* B = K
*
* position ;new file mark.
* open_mark ;new position within open buffer.
* transfer_count ;new bytes transfered.
* bytes_left ;# bytes till satisfy request.
*
* Uses: All registers
* temp0
* temp1
* dividend
* length
* position
* open_mark
* transfer_count
* request_count
* bytes_left
*
******************************************************************************
transfer_data proc
with data
*
* Clear status_flag and high word of xfer_count...
*
stz status_flag ;Clear flag.
stz xfer_count+2 ;Clear high word of count.
*
* If send_flag is clear it means that a block has been transfered directly
* to data_buffer. If that has happened, we set xfer_count = read_size, and
* skip to update...
*
lda send_flag ;Has a block been transfered directly?
bne check_buffer ;Nope.
lda read_size ;Yes, so set xfer_count = read_size.
sta xfer_count
lda read_size+2
sta xfer_count+2
brl update ;And continue at update...
*
* If open_mark = log_blk_size then there is nothing left in this block to
* transfer, so we reset open_mark to zero and exit with status_flag clear and
* bytes_left in X & Y...
*
check_buffer lda open_mark ;Get mark.
cmp log_blk_size ;Do we have anything left in here?
bne set_source ;Yep.
stz open_mark ;Nope, reset open_mark.
ldx bytes_left ;Get bytes_left.
ldy bytes_left+2
brl exit ;Exit.
*
* Set source_ptr = open_buf_ptr + open_mark...
*
set_source clc ;Do addition.
adc open_buf_ptr
sta source_ptr
lda #0
adc open_buf_ptr+2
sta source_ptr+2
*
* Init xfer_count to log_blk_size - open_mark...
*
sec ;Prepare for subtraction.
lda log_blk_size ;Get log_blk_size.
sbc open_mark ;Subtract open_mark.
sta xfer_count ;Save xfer_count.
*
* If bytes_left <= xfer_count then set status_flag to 1 and xfer_count to
* bytes_left...
*
ldx bytes_left+2 ;Is bytes_left <= xfer_count?
bne check_newline ;Nope.
cmp bytes_left ;Maybe.
bcc check_newline ;Nope, so use xfer_count.
lda bytes_left ;Yes, so set xfer_count = bytes_left.
sta xfer_count
inc status_flag ;Set status to 1.
*
* Do we have to watch for newline?
*
check_newline lda newline_mask ;Newline enabled?
beq fast_xfer ;No, so go fast.
*
* Yes, set short accumulator. Do we have to look at more than one newline
* character?
*
longa off ;Set 8 bit A.
sep #$20
dec newline_length ;Point to last byte. More than 1?
beq medium_xfer ;Nope.
*
* Yes, so we'll slow to a crawl and check each byte against the entire
* newline table after we transfer it...
*
ldy #0 ;Init offset.
slow_loop lda [source_ptr],y ;Get byte.
sta [data_buffer],y ;Put byte.
and newline_mask ;Mask it.
tyx ;Save offset.
ldy newline_length ;Point to end of newline table.
newline_loop cmp [newline_ptr],y ;Match byte?
beq hit_newline ;Yes.
dey ;Nope, checked all in table?
bpl newline_loop ;No, so loop.
txy ;Yes, recover offset.
iny ;Bump it.
cpy xfer_count ;Done all?
bne slow_loop ;No, so loop.
bra restore_a ;Yes, so continue.
*
* We only have to look at one newline character. Do transfer...
*
medium_xfer ldy #0 ;Init offset.
medium_loop lda [source_ptr],y ;Get byte.
sta [data_buffer],y ;Put byte.
and newline_mask ;Mask it.
cmp newline_char ;Match newline?
beq hit_newline_a ;Yep.
iny ;Nope, bump offset.
cpy xfer_count ;Done all?
bne medium_loop ;Nope.
bra restore_a ;Yep.
*
* We hit a newline character so set xfer_count to current offset +1, set
* set status_flag to 1, restore 16 bit accumulator and branch to update...
*
hit_newline txy ;Get offset.
hit_newline_a iny ;Bump count by 1.
sty xfer_count ;Reset xfer_count.
lda #1 ;Set status flag to 1.
sta status_flag
longa on ;Set 16 bit A.
restore_a rep #$20
inc newline_length ;Restore length.
bra update ;Continue.
*
* We don't have to check for newline so use move_info to move data into
* data_buffer...
*
fast_xfer pei source_ptr+2 ;Push source pointer.
pei source_ptr
pei data_buffer+2 ;Push destination pointer.
pei data_buffer
pea 0 ;Push transfer request count.
pei xfer_count
pea move_sinc_dinc
jsl move_info ;Do move.
*
* Ok, we've moved the data, now let's update the position information. If we
* did NOT satisfy the request, we must be finished with this block so reset
* open_mark to zero...
*
update lda status_flag ;Did we satisfy the request?
beq reset_mark ;No, so reset_mark.
*
* We satisfied the request, so set open_mark = open_mark + xfer_count. Ignore
* for now the case in which open_mark = log_blk_size; we handle that case at
* the beginning of this routine.
*
clc ;Do addition.
lda xfer_count
adc open_mark
reset_mark sta open_mark
*
* Set data_buffer and io_buffer = data_buffer + xfer_count. By pointing
* io_buffer at data_buffer we may be able to avoid double buffering by
* reading directly into the caller's buffer...
*
clc ;Do it.
lda xfer_count
tax
adc data_buffer
sta data_buffer
sta io_buffer
lda xfer_count+2
tay
adc data_buffer+2
sta data_buffer+2
sta io_buffer+2
*
* Set transfer_count = transfer_count + xfer_count...
*
clc ;Do it.
txa
adc transfer_count
sta transfer_count
tya
adc transfer_count+2
sta transfer_count+2
*
* Set position = position + xfer_count...
*
clc ;Do it.
txa
adc position
sta position
tya
adc position+2
sta position+2
*
* Set bytes_left = bytes_left - xfer_count...
*
sec ;Do it.
lda bytes_left
sbc xfer_count
sta bytes_left
tax
lda bytes_left+2
sbc xfer_count+2
sta bytes_left+2
tay
*
* Set status_flag if bytes_left = zero...
*
ora bytes_left ;Bytes_left = zero?
bne exit ;Nope.
inc status_flag ;Yes, so set status_flag.
*
* Get status_flag in A and exit...
*
exit lda status_flag ;Get status_flag.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: setup_volume
*
* Description: Sets up all volume specific variables, and checks to see if
* volume has been switched. Will call mount_message if needed.
*
* NOTE: There is an alternate entry point used by device_dispatch.
*
* Created: Nov 12, 1987
* Modified: Mar 28, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_vcr ;points to vcr.
*
* Output: A = error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Uses: All registers
* input_string
* find_volume (sub)
* activate_vcr (sub)
* mount_message (sub)
*
******************************************************************************
setup_volume proc
with data
*
* Get device number out of VCR and set drvr_dev_num...
*
ldy #vcr_dev ;Point to device #.
lda [my_vcr],y ;Get it.
sta drvr_dev_num ;Save it.
*
* Has a disk switch occured?
*
ldy #vcr_status ;Point to status.
lda [my_vcr],y ;Get word.
and #vcr_swapped ;Disk switch occured?
beq ok_exit ;Nope.
*
* Yes, get pointer to the vcr name and move it to volume_name...
*
export find_our_volume
find_our_volume ;
ldy #vcr_name ;Point to low word of name vp.
lda [my_vcr],y ;Get low word.
tax ;Put in X.
iny ;Point to high word.
iny
lda [my_vcr],y ;Get high word.
tay ;Put in Y.
jsl deref ;Dereference it.
stx input_string ;Save pointer.
sty input_string+2
lda [input_string] ;Get length.
and #$00ff ;Clear high byte.
tay ;Use as index.
iny ;Point to last char.
longa off ;Set 8 bit A.
sep #$20
lda #0 ;Get zero.
sta volume_name+1,y ;Delimit string.
copy_loop lda [input_string],y ;Move byte.
sta volume_name,y
dey ;Done all?
bpl copy_loop ;Nope, so loop.
longa on ;Set 16 bit A.
rep #$20
*
* See if we can find it by calling find_volume. Found?
*
mount_loop jsr find_volume ;Go look. Found?
bcc got_volume ;Yes.
*
* No, so call mount_message. First make volume name a class 0 name with a
* leading slash, do call, then restore volume name. Ok button pressed?
*
lda #$2e5f ;Replace underscores with periods.
ldx #volume_name
ldy #^volume_name
jsr transform_name
lda volume_name ;Get length word.
pha ;Save it.
inc a ;Make it one longer.
ora #$2f00 ;Add a slash (name must be <256 chars!)
sta volume_name ;Save it.
pea volume_name>>16 ;Push address of volume name string.
pea volume_name
lda #0001
jsl mount_message ;Do message.
plx ;Restore volume_name.
stx volume_name
pha ;Save button status.
lda #$5f2e ;Replace periods with underscores.
ldx #volume_name
ldy #^volume_name
jsr transform_name
pla ;Ok button pressed?
beq mount_loop ;Yes, so loop to re-try find_volume.
*
* User cancelled, so exit with a vol_not_found error...
*
lda #vol_not_found ;Get error code.
sec ;Set carry.
rts ;Exit.
*
* We have got the volume. Update vcr with device number...
*
got_volume ldy #vcr_dev ;Point to device # in vcr.
lda drvr_dev_num ;Get it.
sta [my_vcr],y ;Put in vcr.
*
* Activate vcr and exit with carry clear...
*
ok_exit jsr activate_vcr ;Activate it.
clc ;Indicate no error.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: direct_read
*
* Description: Reads as many blocks in one drvr_read call as possible for
* this file directly into the caller's buffer.
*
* Created: Nov 30, 1987
* Modified: July 26, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = low word of bytes_left
* Y = high word of bytes_left
* P = nvmxdizc
* ..000...
* B = K
*
* skip_count ;# blocks till interleave gap.
* log_blk_size ;logical block size.
* data_buffer ;points to caller's buffer.
*
* Output: A = error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* read_size ;# bytes read.
* io_buffer ;points to caller's buffer.
*
* Uses: All registers
* total_blocks
* multiplier (a.k.a. dividend)
* multiplicand (a.k.a. divisor)
* product (a.k.a. input_string & output_string)
* remainder
* long_divide (sub)
* long_multiply (sub)
*
******************************************************************************
direct_read proc
with data
*
* Set dividend = bytes_left...
*
stx dividend ;Set dividend = bytes_left.
sty dividend+2
*
* Point io_buffer to caller's buffer...
*
lda data_buffer ;Set io_buffer = data_buffer.
sta io_buffer
lda data_buffer+2
sta io_buffer+2
*
* Advance the block number and save it. This will also adjust skip_count to
* the correct value...
*
jsr next_block ;Get next block number.
bcs error_exit ;Error!
stx drvr_blk_num ;Set block number to read.
sta drvr_blk_num+2
*
* Can we read more than 1 block?
*
lda skip_count ;Get skip_count.
dec a ;Skip_count = 1?
bne do_calc ;Nope.
*
* No, so set total_blocks to 1 and read_size to log_blk_size, then skip
* calculation...
*
inc a ;Init total_blocks to 1.
sta total_blocks
lda log_blk_size ;Init read_size to log_blk_size.
ldx #0
bra do_read ;Continue.
*
* Yes, so we must do calculation. Set total_blocks = bytes_left/log_blk_size
* (since bytes_left cannot exceed 16 Mb - 1, and log_blk_size should never be
* smaller than 256 bytes, total_blocks cannont exceed $ffff). If total_blocks
* is greater than skip_count, set total_blocks and multiplier = skip_count...
*
do_calc lda log_blk_size ;Set divisor = log_blk_size.
sta divisor
stz divisor+2
jsr long_divide ;Do division.
lda dividend ;Set total_blocks = result.
sta total_blocks
cmp skip_count ;Is it larger than skip_count?
bcc calc_read_size ;Nope.
lda skip_count ;Yes, so set total_blocks = skip_count.
sta total_blocks
sta multiplier ;Set multiplier = skip_count.
stz multiplier+2
*
* And set read_size = total_blocks * log_blk_size...
*
calc_read_size lda log_blk_size ;Set multiplicand = log_blk_size.
sta multiplicand
stz multiplicand+2
jsr long_multiply ;Do multiplication.
lda product ;Set read_size = low lw of product.
ldx product+2
*
* Save read_size, set drvr_req_cnt = read_size, do the read and condition the
* fcr error flag. Exit if we get an error...
*
do_read sta read_size ;Save read_size.
stx read_size+2
sta drvr_req_cnt ;Set request count.
stx drvr_req_cnt+2
jsr device_read_b ;Do read.
jsr condition_flag ;Condition the error flag.
bcs error_exit ;Error, so exit.
*
* Now, we have to adjust drvr_blk_num and skip_count to account for the number
* of blocks we just read, and exit with carry clear...
*
dec total_blocks ;First, zero adjust total_blocks.
clc ;Add total_blocks to drvr_blk_num.
lda total_blocks
adc drvr_blk_num
sta drvr_blk_num
lda #0
adc drvr_blk_num+2
sta drvr_blk_num+2
sec ;Subtract total_blocks from skip_count.
lda skip_count
sbc total_blocks
sta skip_count
clc ;Indicate success.
error_exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: sector_read
*
* Description: Reads one sector into io_buffer.
*
* NOTE: this call should only be used by id_disk!! Sectors are
* only used to find the Standard File Volume Descriptor.
*
* Created: Oct 21, 1987
* Modified: Oct 21, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = HIGH word of block #.
* X = low word of block #.
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* drvr_dev_num ;device number to access.
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* log_blk_size ;set to 2k.
* real_log_size ;set to 2k.
*
* Exit: rts
*
* Uses: All registers
* device_read (sub)
*
******************************************************************************
sector_read proc
with data
*
* Set to read 2k bytes and continue through device_read...
*
ldy #sector_size ;Set to read 2k.
sty log_blk_size ;Set log_blk_size to 2k.
sty real_log_size ;Set real_log_size to 2k.
jmp device_read ;Do read and exit...
ENDP
eject
******************************************************************************
*
* Name: block_read
*
* Description: Reads one block of the current log_blk_size into io_buffer.
*
* Created: Oct 21, 1987
* Modified: Oct 21, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = HIGH word of block #.
* X = low word of block #.
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* drvr_dev_num ;device number to access.
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Exit: rts
*
* Uses: All registers
* device_read (sub)
*
******************************************************************************
block_read proc
with data
*
* Set to read log_blk_size bytes and continue on through device_read...
*
ldy log_blk_size ;Get log_blk_size.
jmp device_read ;Do read.
ENDP
eject
******************************************************************************
*
* Name: device_read
*
* Description: Sets common parameters and does read. Handles logical block
* sizes 512, 1024 and 2048.
*
* NOTE: There are two additional entry points in this routine.
*
* Created: Oct 7, 1987
* Modified: Mar 28, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = HIGH word of block #.
* X = low word of block #.
* Y = request count. Must be multiple of trans_blk_size!
* P = nvmxdizc
* ..000...
* B = K
*
* drvr_dev_num ;device number to read from
* real_log_size ;real logical block size
* ;(usually = log_blk_size)
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Exit: rts
*
* Uses: All registers
* Device Dispatcher
*
******************************************************************************
device_read proc
with data
*
* Set driver block #...
*
stx drvr_blk_num ;Set low word.
sta drvr_blk_num+2 ;Set high word.
*
* Set request count...
*
sty drvr_req_cnt ;Set it.
stz drvr_req_cnt+2
*
* Set to read into io_buffer...
*
export device_read_b
device_read_b ;
lda io_buffer ;Get low word of pointer.
sta drvr_buf_ptr ;Set low word of pointer.
lda io_buffer+2 ;Get high word of pointer.
sta drvr_buf_ptr+2 ;Set high word of pointer.
*
* Setup common driver parameters...
*
export common_read
common_read ;
lda #drvr_read ;Set read command.
sta drvr_call_num
lda #hs_id ;Get High Sierra id.
sta drvr_fst_num ;Set it.
lda #phys_blk_size ;Set block size.
sta drvr_blk_size
*
* If real_log_size is not equal to phys_blk_size (512) then branch to
* translate_blk, else do call and exit...
*
lda real_log_size ;Get real logical block size.
cmp #phys_blk_size ;Is it same as physical size?
bne translate_blk ;Nope.
jmp device_dispatch ;Yep, exit thru device_dispatch.
*
* We've got a non 512 byte block size. First save the current block #...
*
translate_blk pei drvr_blk_num ;Save current block #.
pei drvr_blk_num+2
*
* Multiply the block # by 2. Is real_log_size = 1024? If so then branch to
* read_it, else must be 2048 so multiply it by 2 again then do read...
*
asl drvr_blk_num ;Multiply block number by 2.
rol drvr_blk_num+2
cmp #1024 ;real_log_size = 1024?
beq read_it ;Yes.
asl drvr_blk_num ;Multiply block number by 2.
rol drvr_blk_num+2
read_it jsr device_dispatch ;Do call.
*
* Ok, we've done the read, now let's restore the block number and exit...
*
exit plx ;Restore block number.
stx drvr_blk_num+2
plx
stx drvr_blk_num
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: device_dispatch
*
* Description: Calls device dispatcher and checks for disk switched or offline
* error. If found and id_disk_flag is clear and my_vcr is set,
* will save current state, do a find_our_volume call, restore
* state, and retry call.
*
* This routine should only be called by device_read!!
*
* NOTE: The id_disk_flag is used to ensure that this routine can call
* itself safely thru find_our_volume -> find_volume -> id_disk.
*
*
* Created: Mar 28, 1988
* Modified: 8/8/90
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* id_disk_flag ;1 if id_disk routine called, else 0.
* my_vcr ;clear if not in use.
* drvr_dev_num ;device number to access.
* drvr_call_num ;call number.
* drvr_buf_ptr ;buffer pointer.
* drvr_req_cnt ;request count (if read).
* drvr_blk_num ;block number (if read).
* drvr_blk_size ;block size.
* drvr_fst_num ;FST id number.
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Exit: rts
*
* Uses: All registers
* find_our_volume (sub)
* Device Dispatcher (sys service)
*
*
* revision history
*
* 08/08/90 CAF now will re_try on a disk switched error always. It wasn't
* happening before during a volume call because no vcr was setup.
*
* 08/08/90 MSD. Changed to retry the device access if the error was
* drvr_disk_sw and id_disk_flag is set. This is so
* drvr_disk_sw will not be returned from the Volume call,
* but will be returned during other calls (so that the FST
* can find out where the volume has moved to).
* Thanks to Cheryl for pointing this out!!
*
******************************************************************************
device_dispatch proc
with data
;
; Cheryl says: Cary and Mark goofed. If we came from the id_disk routine
; and we get a disk switched error, then we can retry. Otherwise, the retry
; might access the wrong media (when we really need to go find out where it
; is after the disk switch).
;
*
* Call device dispatcher. Exit if no error, or if id_disk_flag is set, or if
* my_vcr is clear, or if error not disk switched or offline...
*
re_try jsl dev_dispatcher ;Do call.
bcc exit ;No error.
pha ;Save error.
cmp #drvr_disk_sw ;Disk switched error?
bne @no_disk_sw ; not disk_sw, so try other errors
lda id_disk_flag ; trying to id a disk?
beq check_flag ; no, so do usual stuff
pla ; clean up stack
bra re_try ; and try it again
@no_disk_sw
cmp #drvr_off_line ;Nope, offline?
bne error ;Nope.
lda id_disk_flag ;Yes, is id_disk_flag set?
bne error ;Yep, so exit with error.
; in middle of call, so fix up VCR
check_flag lda my_vcr ;Nope, is my_vcr clear?
ora my_vcr+2
bne save_state ;Nope, so let's see if we can recover.
error pla ;Get error code.
sec ;Make sure carry set.
exit rts ;Exit.
*
* We have a disk switched condition, so let's try to recover. Save all of the
* data that will be modified by calling find_our_volume...
*
save_state pla ;Fix stack.
ldx #drvr_dp_len-2 ;Save driver direct page space.
drvr_loop lda drvr_call_num,x
sta storage_drvr,x
dex
dex
bpl drvr_loop
ldx #fst_dp_len-2 ;Save fst direct page space.
fst_loop lda input_string,x
sta storage_fst,x
dex
dex
bpl fst_loop
ldx #misc_len-2 ;Save miscellaneous space.
misc_loop lda gstring,x
sta storage_misc,x
dex
dex
bpl misc_loop
*
* Call find_our_volume and save error code and status...
*
jsr find_our_volume ;Go look for it.
php ;Save status.
pha ;Save error code.
*
* Restore the state...
*
ldx #drvr_dp_len-2 ;Restore driver direct page space.
drvr_loop_r lda storage_drvr,x
sta drvr_call_num,x
dex
dex
bpl drvr_loop_r
ldx #fst_dp_len-2 ;Restore fst direct page space.
fst_loop_r lda storage_fst,x
sta input_string,x
dex
dex
bpl fst_loop_r
ldx #misc_len-2 ;Restore miscellaneous space.
misc_loop_r lda storage_misc,x
sta gstring,x
dex
dex
bpl misc_loop_r
*
* Recover call status and error code. Re-try call if no error, else exit...
*
pla ;Recover error code.
plp ;Recover status.
bcs exit ;Exit if error.
jmp re_try ;No error, so re-try call.
ENDP
eject
******************************************************************************
*
* Name: read_next_block
*
* Description: Reads next block of file or directory. Handles interleaved
* files; for directories, interleave_skip must be zero! Will
* set fcr_error_flag if error occurs during read.
*
* Handles differences between log_blk_size and trans_blk_size.
*
* NOTE: the entry point 'next_block' can be used to get the
* next block # without doing the read.
*
* Created: Nov 9, 1987
* Modified: Mar 29, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* log_blk_size ;logical block size.
* real_log_size ;usually same as log_blk_size.
* drvr_blk_num ;current directory block.
* end_block ;last block # of file/directory.
* interleave_size ;# contiguous blocks.
* interleave_skip ;# blocks between contiguous.
* skip_count ;# blocks till skip. Init to int._size!
*
* Interleaved file (blocks):
* ___________________________________________________________________
* | a | a | a | a | b | b | a | a | a | a | b | b | a | a | a |a | b >
* |___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___<
*
* for file 'a': interleave_size = 4
* interleave_skip = 2
*
* for file 'b': interleave_size = 2
* interleave_skip = 4
*
* Output: A = error code if error.
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Uses: All registers
* skip_read_flag
* drvr_blk_num
* skip_count
* read_with_flag (sub)
*
******************************************************************************
read_next_block proc
with data
*
* Clear skip_read_flag and continue...
*
stz skip_read_flag ;Clear flag.
bra check_trans ;Continue.
*
* Set skip_read_flag and continue...
*
export next_block
next_block ;
lda #$8000 ;Set flag.
sta skip_read_flag
*
* Is log_blk_size = trans_blk_size?
*
check_trans ldx drvr_blk_num ;Get low word of block #.
lda drvr_blk_num+2 ;Get high word of block #.
ldy real_log_size ;Get real logical size.
cpy log_blk_size ;Same as current logical size?
beq bump_block ;Yep.
*
* Nope, so we must be dealing with a directory. Add 4 to block number if
* real logical = 512, else add 2 (logical must be 1024). We can skip the
* interleave stuff 'cuz directories cannot be interleaved...
*
lda #4 ;Init offset to 4.
cpy #512 ;Logical = 512?
beq do_add ;Yep.
lda #2 ;Nope, so set offset to 2 (must be 1024)
do_add clc ;Add offset to block number.
adc drvr_blk_num
tax
lda #0
adc drvr_blk_num+2
bra check_end ;Continue.
*
* Yes, so bump block #...
*
bump_block inx ;Bump block #. Rollover?
bne check_int ;Nope.
inc a ;Yes, bump high word.
*
* Check for interleave gap and add in skip if needed...
*
check_int dec skip_count ;Time to skip?
bne check_end ;Nope.
tay ;Yes, save A.
lda interleave_size ;Interleave_size zero?
bne set_skip ;Nope.
dec a ;Yes, so make $ffff.
set_skip sta skip_count ;Reset skip_count.
clc ;Add interleave_skip to block #.
txa
adc interleave_skip
tax
tya
adc #0
*
* Did that put us past the end block? Exit if so...
*
check_end cmp end_block+2 ;Are we past end_block?
bcc ok ;Nope.
bne no_more ;Yes.
cpx end_block ;Maybe.
beq ok ;Nope.
bcs no_more ;Yes.
*
* Do read if skip_read_flag clear, else exit with carry clear...
*
ok clc ;Clear carry in case flag set.
bit skip_read_flag ;Flag set?
bmi exit ;Yep, so exit with carry set.
jmp read_with_flag ;Nope, so read block.
*
* At end, so exit with an end of directory error...
*
no_more lda #end_of_dir ;Get error code.
sec ;Indicate done.
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: read_prev_block
*
* Description: Reads previous block of file or directory. Will set
* fcr_error_flag if error occurs during read.
*
* Handles differences between log_blk_size and trans_blk_size.
*
* NOTE: This routine does not handle interleave!
*
* Created: Nov 6, 1987
* Modified: Mar 29, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* log_blk_size ;logical block size.
* real_log_size ;usually same as log_blk_size.
* drvr_blk_num ;current directory block.
* start_block ;first block # of file/directory.
*
* Output: A = error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Uses: All registers
* temp1
* drvr_blk_num
* read_with_flag (sub)
*
******************************************************************************
read_prev_block proc
with data
*
* Is log_blk_size = trans_blk_size?
*
ldx drvr_blk_num ;Get low word of block #.
lda drvr_blk_num+2 ;Get high word of block #.
ldy real_log_size ;Get real logical size.
cpy log_blk_size ;Same as logical size?
beq prev_block ;Yep.
*
* Nope, so we must be dealing with a directory. Subtract 4 from block number
* if logical = 2048, else subtract 2 (logical must be 1024). We can skip the
* interleave stuff 'cuz directories cannot be interleaved...
*
lda #4 ;Init offset to 4.
cpy #2048 ;Logical = 2048?
beq do_subtract ;Yep.
lda #2 ;Nope, so set offset to 2.
do_subtract sta temp1 ;Save offset.
sec ;Subtract offset from block number.
lda drvr_blk_num
sbc temp1
tax
lda drvr_blk_num+2
sbc #0
bra check_start ;Continue.
*
* Nope, so decrement block #...
*
prev_block dex ;Decrement it.
cpx #$ffff ;Did we rollover?
bne check_start ;Nope.
dec a ;Yep, so decrement high word.
*
* Did that put us before start_block? If not, exit thru read_with_flag...
*
check_start cmp start_block+2 ;Are we before start_block?
bcc no_more ;Yes.
bne ok ;Nope.
cpx start_block ;Maybe.
bcc no_more ;Yes.
ok jmp read_with_flag ;No, go read it.
*
* Yes, so exit with an end of directory error...
*
no_more lda #end_of_dir ;Get error code.
sec ;Indicate done.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: read_with_flag
*
* Description: Reads block and sets/clears FCR error flag.
*
* NOTE: The entry point 'condition_flag' can be used to
* set/clear the error flag only.
*
* Created: Nov 6, 1987
* Modified: Nov 6, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = high word of block #.
* X = low word of block #.
* Y = undefined
* P = nvmxdizc
* B = K
*
* my_fcr ;points to fcr.
*
* Output: A = error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Uses: All registers
* my_fcr
* block_read (sub)
*
******************************************************************************
read_with_flag proc
with data
*
* Do read...
*
jsr block_read ;Do read.
*
* Set error flag if carry set, else clear it and exit...
*
export condition_flag
condition_flag ;
tax ;Save error code.
lda #0 ;Assume no error.
bcc continue ;That was the right assumption.
lda #1 ;Error so get 1.
continue ldy #fcr_error_flag ;Get offset to error_flag.
sta [my_fcr],y ;Set/clear flag.
txa ;Recover error code.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: setup_open_buf
*
* Description: Setup pointers and variables for open_buffer. If file is a
* directory and it is claimed for get_dir_entry, forces
* log_blk_size to 2k. This is done AFTER the set_end_block call
* so that the end block will be set correctly.
*
* Created: Nov 6, 1987
* Modified: Jan 11, 1989
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_fcr ;points to fcr.
* log_blk_size ;current log_blk_size.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0 = error
* B = K
*
* io_buffer ;points to open_buffer in fcr.
* open_buf_ptr ;points to open_buffer in fcr.
* start_block ;starting block # of file/directory.
* end_block ;ending block # of file/directory.
* interleave_size ;# contiguous blocks.
* interleave_skip ;# blocks between contiguous blocks.
* skip_count ;# blocks till next skip.
* open_mark ;position within open buffer.
* log_blk_size ;2k if file is a directory.
*
* Uses: All registers
*
******************************************************************************
setup_open_buf proc
with data
*
* Point io_buffer at open_buffer in fcr...
*
clc ;Prepare for add.
ldy #fcr_dir_record ;Get offset to start of dir record.
lda [my_fcr],y ;Get length of directory.
and #$00ff ;Clear high byte (1/11/89).
adc #fcr_dir_record ;Add length to fcr_dir_record.
adc my_fcr ;Add to my_fcr.
sta io_buffer ;Save low word of pointer.
sta open_buf_ptr ;And again.
lda #0 ;Add carry to high word.
adc my_fcr+2
sta io_buffer+2 ;Save high word of pointer.
sta open_buf_ptr+2 ;And again.
*
* Set drvr_blk_num to open_block from fcr in case we need to read another
* block...
*
ldy #fcr_open_block ;Get offset.
lda [my_fcr],y ;Get low word.
sta drvr_blk_num ;Save it.
ldy #fcr_open_block+2 ;Get offset.
lda [my_fcr],y ;Get high word.
sta drvr_blk_num+2 ;Save it.
*
* Set interleave_size and interleave_skip...
*
ldy #fcr_dir_record+dir_int_size ;Get offset to size.
lda [my_fcr],y ;Get it.
and #$00ff ;Clear high byte.
sta interleave_size ;Save it.
ldy #fcr_dir_record+dir_int_skip ;Get offset to skip.
lda [my_fcr],y ;Get it.
and #$00ff ;Clear high byte.
sta interleave_skip ;Save it.
*
* Set start_block...
*
ldy #fcr_dir_record+dir_xar_len ;Point to xar_len.
lda [my_fcr],y ;Get length.
and #$00ff ;Clear high byte.
clc ;Prepare to add.
ldy #fcr_dir_record+dir_loc_extent ;Point to low word.
adc [my_fcr],y ;Add low word to len.
sta start_block ;Save it.
ldy #fcr_dir_record+dir_loc_extent+2 ;Point to high word.
lda [my_fcr],y ;Get high word.
adc #0 ;Add in carry.
sta start_block+2 ;Save it.
*
* Set end_block...
*
ldy #fcr_dir_record+dir_data_length ;Point to low word.
lda [my_fcr],y ;Get low word.
tax ;Save it.
ldy #fcr_dir_record+dir_data_length+2 ;Point to high word.
lda [my_fcr],y ;Get high word.
jsr set_end_block ;Set end_block.
*
* Set skip_count and open_mark...
*
ldy #fcr_skip_count ;Get offset to count.
lda [my_fcr],y ;Get it.
sta skip_count ;Save it.
ldy #fcr_open_mark ;Get offset to mark.
lda [my_fcr],y ;Get it.
sta open_mark ;Save it.
*
* Is this a directory? If so, and it is claimed for get_dir_entry, force
* log_blk_size to 2k, else exit...
*
ldy #fcr_storage ;Point at storage type.
lda [my_fcr],y ;Get type.
cmp #type_directory ;Is it a directory?
bcc exit ;Nope.
ldy #fcr_type_flag ;Yes, get offset to type flag.
lda [my_fcr],y ;Get flag.
cmp #2 ;Claimed for get_dir_entry?
bne exit ;Nope.
lda #sector_size ;Yes, force log_blk_size = 2k.
sta log_blk_size
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: check_open_buf
*
* Description: Tries to re-fill open_buffer if fcr_error_flag is set.
*
* Created: Nov 6, 1987
* Modified: Nov 6, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_fcr ;points to fcr.
* drvr_blk_num ;current open_block.
* io_buffer ;points to open_buffer in fcr.
*
* Output: A = error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* Uses: All registers
*
******************************************************************************
check_open_buf proc
with data
*
* Is error flag set?
*
ldy #fcr_error_flag ;Point to flag.
lda [my_fcr],y ;Get flag. Set?
bne re_read ;Yes.
clc ;No, so indicate ok.
rts ;Exit.
*
* Yes, so exit through read_with_flag...
*
re_read ldx drvr_blk_num ;Get block #.
lda drvr_blk_num+2
jmp read_with_flag ;Read it in.
ENDP
eject
******************************************************************************
*
* Name: set_end_block
*
* Description: Calculates and sets end_block.
*
* Created: Nov 6, 1987
* Modified: Apr 25, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = high word of file/directory length
* X = low word of file/directory length
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* start_block ;start_block.
* log_blk_size ;current log_blk_size.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* end_block ;ending block # of file/directory.
*
* Uses: All registers
* dividend
* remainder
* calc_open_block (sub)
*
******************************************************************************
set_end_block proc
with data
*
* Calculate end block, subtract 1 if open_mark (remainder) = 0, save it
* and exit...
*
jsr calc_open_block ;Calculate block.
ldy open_mark ;Open_mark = zero?
bne continue ;Nope.
dex ;Yep, subtract 1.
cpx #$ffff
bne continue
dec a
continue stx end_block ;Save end_block.
sta end_block+2
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: close
*
* Description: Closes a file.
*
* Created: Nov 3, 1987
* Modified: Nov 3, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_vcr ;points to vcr.
* my_fcr ;points to fcr.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0
* B = K
*
* Uses: All registers
* release_fcr (system)
* sys_death (system)
*
******************************************************************************
close proc
with data
*
* Release the FCR...
*
lda [my_fcr] ;Get reference #.
jsl release_fcr ;Release fcr.
*
* Decrement VCR open count and exit with carry clear if >= 0...
*
ldy #vcr_open_cnt ;Get offset to open count.
lda [my_vcr],y ;Get open count.
dec a ;Decrement it.
cmp #$ffff ;Rollover?
beq hara_kari ;Yes, we're in deep trouble!
sta [my_vcr],y ;Nope, so save it.
clc ;Indicate ok.
rts ;Exit.
*
* Something's terribly wrong here, and we have lost great face: we must commit
* hara-kari...
*
hara_kari lda #$000A ;Get error code for bad VCR.
jml sys_death ;Die.
ENDP
eject
*******************************************************************************
*
* Name: set_mark
*
* Description: Set file position marker and related variables. Will set
* fcr_error_flag if block # changes.
*
* Created: Nov 4, 1987
* Modified: Nov 13, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_fcr ;points to fcr.
* base ;0: mark = displacement.
* ;1: mark = eof - displacement.
* ;2: mark = mark + displacement.
* ;3: mark = mark - displacement.
*
* displacement ;offset.
*
* Output: A = error code if error
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0 if no error.
* 1 if error
* B = K
*
* fcr_open_block ;# of block in open_buffer.
* fcr_position ;new position.
* fcr_skip_count ;count to next interleave gap.
* fcr_open_mark ;position within open_buffer.
*
* Uses: All registers
* calc_open_block (sub)
* update_fcr (sub)
*
******************************************************************************
set_mark proc
with data
*
* Get current position and eof...
*
ldy #fcr_position ;Point to low word.
lda [my_fcr],y ;Get low word.
sta position ;Save it.
ldy #fcr_position+2 ;Point to high word.
lda [my_fcr],y ;Get high word.
sta position+2 ;Save it.
ldy #fcr_eof ;Point to low word.
lda [my_fcr],y ;Get low word.
sta eof ;Save it.
ldy #fcr_eof+2 ;Point to high word.
lda [my_fcr],y ;Get high word.
sta eof+2 ;Save it.
*
* Now branch to the correct handler...
*
ldx base ;Get base. Zero?
beq base_0 ;Yes.
dex ;No, 1?
beq base_1 ;Yes.
dex ;No, 2?
beq base_2 ;Yes.
*
* Set mark = mark - displacement, then branch to check_range...
*
sec ;Prepare for subtract.
lda position ;Do it.
sbc displacement
tax
lda position+2
sbc displacement+2
bcc bad_range ;Oops, went too far back!
bra check_range ;Continue.
*
* Set mark = mark + displacement, then branch to check_range...
*
base_2 clc ;Prepare for add.
lda position ;Do it.
adc displacement
tax
lda position+2
adc displacement+2
bra check_range ;Continue.
*
* Set mark = eof - displacement, then branch to check_range...
*
base_1 sec ;Prepare for subtract.
lda eof ;Do it.
sbc displacement
tax
lda eof+2
sbc displacement+2
bcc bad_range ;Oops, went too far back!
bra check_range ;Continue.
*
* Set mark = displacement. If displacement = current position then
* exit with carry clear...
*
base_0 ldx displacement ;Get new position.
lda displacement+2
cmp position+2 ;Match current?
bne check_range ;Nope.
cpx position ;Maybe.
bne check_range ;Nope.
clc ;Yes, so exit with carry clear.
rts
*
* Now see if position is past eof (high word of position is in A, low in X).
* Is it past?
*
check_range cmp eof+2 ;Past eof?
bcc position_ok ;Nope.
bne bad_range ;Yes.
cpx eof
bcc position_ok ;Nope.
beq position_ok ;Nope.
*
* Yes, so exit with an out of range error...
*
bad_range lda #out_of_range ;Get error code.
sec ;Indicate error.
error rts ;Exit.
*
* No, so calculate open_block. Set carry flag if block # has changed...
*
position_ok phx ;Save position.
pha
jsr setup_open_buf ;Setup open buffer.
pla ;Recover position.
plx
jsr calc_open_block ;Do calculation.
pha ;Save A.
ldy #fcr_open_block+2 ;Get offset to high word of block.
cmp [my_fcr],y ;Match?
bne changed ;Nope.
txa ;Get low word in A.
dey ;Point to low word of block.
dey
cmp [my_fcr],y ;Match?
bne changed ;Nope.
clc ;Yes, so clear carry.
bra recover_a
changed sec ;Block # has changed.
recover_a pla ;Recover low word of block #.
*
* Save flag, do update, and recover flag. Set fcr_error_flag if carry set
* and exit with carry clear...
*
php ;Save flag.
jsr update_fcr ;Do update.
plp ;Recover flag. Carry clear?
bcc exit ;Yep.
ldy #fcr_error_flag ;Get offset to error flag.
lda #0001 ;Set flag.
sta [my_fcr],y
clc ;Indicate no error.
exit rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: calc_open_block
*
* Description: Calculate block number from position. Handles interleave.
* If position is < 174k and file is interleaved, routine will
* use loop_calc, >= 174k will use long_calc. If file is not
* interleaved, will always use long_calc, in which case the
* worst case is 1.719 ms.
*
* The crossover point of 174k was determined by timing tests
* with both routines. Using long_calc for positions >=174k
* ensures that calc_open_block will never take longer than
* 3.332 ms to complete, and will be significantly faster for
* positions < 174k.
*
* Created: Nov 13, 1987
* Modified: Apr 25, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = high word of position
* X = low word of position
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_fcr ;points to fcr.
* start_block ;Starting block # of file/directory.
* interleave_skip ;# contiguous blocks.
* interleave_size ;# blocks between contiguous blocks.
*
* Output: A = high word of block #
* X = low word of block #
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* position ;new position.
* skip_count ;count to next interleave gap.
* open_mark ;position within open_buffer.
*
* Uses: All registers
* temp1
* dividend (a.k.a. multiplier)
* divisor (a.k.a. multiplicand
* remainder (a.k.a. input_string & output_string)
* position
* skip_count
* open_mark
*
******************************************************************************
calc_open_block proc
with data
*
* Calculate logical_block (position/log_blk_size) and set open_mark...
*
stx position ;Save position.
sta position+2
stx dividend ;Set dividend = position.
sta dividend+2
lda log_blk_size ;Set divisor = log_blk_size.
sta divisor
stz divisor+2
jsr long_divide ;Do division.
lda dividend ;Set log_block = result.
ldx dividend+2
sta log_block
stx log_block+2
lda remainder ;Set open_mark = remainder.
sta open_mark
*
* Ok, we've done the common calculation. If file is not interleaved or position
* is >= 174k then branch to long_calc, otherwise use loop_calc...
*
lda interleave_size ;Interleaved file?
beq zero_size ;Nope, so use long_calc.
lda position+2 ;Position >= 174k?
cmp #^crossover
bcc loop_calc ;Nope, so use loop calc.
lda position ;Maybe.
cmp #<crossover
bcs long_calc ;Yes, so use long_calc.
*
* Now we are going to increment the block # from start_block till we've done
* it logical_block times. Init skip_count to interleave_size (or $ffff if
* interleave_size is zero) and get start_block in X and A...
*
loop_calc lda interleave_size ;Get interleave_size. Zero?
bne set_skip ;Nope.
dec a ;Yes, so set to $ffff.
set_skip sta skip_count
ldx start_block ;Get start_block.
lda start_block+2
*
* Are we at the correct block? Exit if we are...
*
advance_loop dec dividend ;Decrement dividend.
ldy dividend ;Get it.
cpy #$ffff ;Rollover?
bne continue ;Nope.
dec dividend+2 ;Yep, decrement high word.
ldy dividend+2 ;Get it.
cpy #$ffff ;Rollover?
bne continue ;Nope.
rts ;Yes, so exit.
*
* No, so bump block #...
*
continue inx ;Bump block #. Rollover?
bne check_gap ;Nope.
inc a ;Yep.
*
* Loop if we're not at an interleave gap...
*
check_gap dec skip_count ;At a gap?
bne advance_loop ;Nope.
*
* We're at a gap. Reset skip_count to interleave_size ($ffff if zero), add
* interleave_skip to block #, and loop...
*
tay ;Save A.
lda interleave_size ;Get size. Zero?
bne reset_a ;Nope.
dec a ;Yes, so make $ffff.
reset_a sta skip_count ;Save it.
clc ;Add interleave_skip to block #.
txa
adc interleave_skip
tax
tya
adc #0
bra advance_loop ;Loop.
* LONG_CALC
* If interleave_size is zero we can skip most of the following calculations;
* all we have to do is set skip_count to $ffff and continue on at do_add...
*
long_calc lda interleave_size ;Get interleave_size. Zero?
bne calc_gap ;Nope.
zero_size dec a ;Yes, so set skip_count = $ffff.
sta skip_count
bra do_add ;Continue at do_add.
*
* Not zero so calculate gap_count (logical_block/interleave_size). Logical_block
* is already in dividend...
*
calc_gap sta divisor ;Set divisor = interleave_size.
stz divisor+2
jsr long_divide ;Do division.
*
* Calculate skip_count (interleave_size - remainder of last calculation). If
* result is zero, reset skip_count to interleave_size...
*
sec ;Do subtraction. Zero result?
lda interleave_size
sbc remainder
bne set_count ;Nope.
lda interleave_size ;Yes, so reset to interleave_size.
set_count sta skip_count ;Save count.
*
* Calculate absolute_block (start_block + logical_block
* + gap_count(interleave_skip)). gap_count is in multiplier (a.k.a. dividend)
* already. Exit with absolute_block in A and X...
*
lda interleave_skip ;Set multiplicand = interleave_skip.
sta multiplicand
stz multiplicand+2
jsr long_multiply ;Do multiplication.
clc ;Add logical_block.
lda product
adc log_block
sta log_block
lda product+2
adc log_block+2
sta log_block+2
do_add clc ;Add start_block.
lda log_block
adc start_block
tax
lda log_block+2
adc start_block+2
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: update_fcr
*
* Description: Fill in fcr position information.
*
* Created: Nov 17, 1987
* Modified: Nov 17, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = high word of block #
* X = low word of block #
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_fcr ;points to fcr.
* position ;new position.
* skip_count ;count to next interleave gap.
* open_mark ;position within open_buffer.
*
* Output: A = high word of block #
* X = low word of block #
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* fcr_position ;new position.
* fcr_open_block ;# of block in open_buffer.
* fcr_skip_count ;count to next interleave gap.
* fcr_open_mark ;position within open_buffer.
*
* Uses: All registers
*
******************************************************************************
update_fcr proc
with data
*
* Put block # in fcr...
*
pha ;Save high word of block.
ldy #fcr_open_block+2 ;Get offset to high word of field.
sta [my_fcr],y ;Fill it in.
dey ;Point to low word.
dey
txa ;Get low word.
sta [my_fcr],y ;Fill it in.
*
* Put position in fcr...
*
ldy #fcr_position ;Get offset to low word of field.
lda position ;Get low word of position.
sta [my_fcr],y ;Fill it in.
iny ;Point to high word.
iny
lda position+2 ;Get high word.
sta [my_fcr],y ;Fill it in.
*
* Put open_mark in fcr...
*
ldy #fcr_open_mark ;Get offset to field.
lda open_mark ;Get mark.
sta [my_fcr],y ;Fill it in.
*
* Put skip_count in fcr...
*
ldy #fcr_skip_count ;Get offset to field.
lda skip_count ;Get skip_count.
sta [my_fcr],y ;Fill it in.
*
* Recover high word of block # (low is in X) and exit...
*
pla ;Recover high word of block #.
rts ;Exit
ENDP
eject
******************************************************************************
*
* Name: get_mark
*
* Description: Gets mark for open file.
*
* Created: Nov 3, 1987
* Modified: Nov 3, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_fcr ;points to fcr.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0
* B = K
*
* Uses: All registers
*
******************************************************************************
get_mark proc
with data
*
* Copy position out of fcr...
*
ldy #fcr_position ;Get offset to low word of position.
lda [my_fcr],y ;Get low word.
sta position ;Save it.
ldy #fcr_position+2 ;Get offset to high word of position.
lda [my_fcr],y ;Get high word.
sta position+2 ;Save it.
*
* Send output and exit...
*
jmp send_output ;Send it.
ENDP
eject
******************************************************************************
*
* Name: get_eof
*
* Description: Gets eof for open file.
*
* Created: Nov 3, 1987
* Modified: Nov 3, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_fcr ;points to fcr.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0
* B = K
*
* Uses: All registers
*
******************************************************************************
get_eof proc
with data
*
* Copy eof out of fcr...
*
ldy #fcr_eof ;Get offset to low word of eof.
lda [my_fcr],y ;Get low word.
sta eof ;Save it.
ldy #fcr_eof+2 ;Get offset to high word of eof.
lda [my_fcr],y ;Get high word.
sta eof+2 ;Save it.
*
* Send output and exit...
*
jmp send_output ;Send it.
ENDP
eject
******************************************************************************
*
* Name: get_dir_entry
*
* Description: Returns directory information.
*
* Created: Nov 4, 1987
* Modified: Apr 8, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_fcr ;points to fcr.
* base ;0: entry_num = displacement.
* ;1: entry_num = entry_num+displacement.
* ;2: entry_num = entry_num-displacement.
* displacement ;entry number.
*
* Output: A = error code if carry set
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* entry_num ;entry number returned.
*
* Uses: All registers
* send_output (sub)
*
******************************************************************************
get_dir_entry proc
with data
*
* Is this fcr for a directory?
*
ldy #fcr_storage ;Get offset to storage type.
lda [my_fcr],y ;Get type.
cmp #type_directory ;Is it a directory?
bcs ok ;Yes.
*
* No, so exit with an error...
*
lda #version_error ;Get error code.
error_exit sec ;Indicate error.
rts ;Exit.
*
* Check our fcr_type_flag and exit with invalid_access error if this FCR
* has been accessed by read. If the flag is clear, claim this file
* for get_dir_entry by setting the flag to 2...
*
ok ldy #fcr_type_flag ;Get offset to type_flag.
lda [my_fcr],y ;Get flag. Set already?
bne check_flag ;Yes.
lda #2 ;No, so set it to 2.
sta [my_fcr],y
bra do_setup ;And continue.
check_flag cmp #2 ;Are we allowed to access this file?
beq do_setup ;Yep.
lda #invalid_access ;Nope, so exit with error.
bra error_exit
*
* Make sure volume is online and setup some variables from the vcr...
*
do_setup jsr setup_volume ;Do setup. Online?
bcs exit ;Nope.
*
* Turn on caching and set current entry_num...
*
lda #in_cache ;Turn on caching.
sta drvr_cache
ldy #fcr_entry_num ;Get offset.
lda [my_fcr],y ;Get entry_num.
sta entry_num ;Save it.
*
* Clear out dir_record_0 and dir_record_1, call setup_open_buf and
* check_open_buf...
*
jsr clear_dir_recs ;Clear em.
jsr setup_open_buf ;Setup pointers and variable.
jsr check_open_buf ;Make sure data in buffer is valid.
bcs exit ;Error.
*
* Branch to correct calculation routine or exit with error if base out
* of range...
*
ldx base ;Get base. Zero?
beq base_0 ;Yes.
dex ;No, 1?
beq base_1 ;Yes.
dex ;No, 2?
beq base_2 ;Yes.
lda #parm_range_err ;No, get error code.
sec ;Indicate error.
rts ;Exit.
*
* Set entry_num = entry_number - displacement...
*
base_2 sec ;Prepare for subtraction.
lda entry_num ;Do it.
sbc displacement
bcs save_it ;Continue.
hit_end lda #end_of_dir ;Passed beginning. Get error code.
error sec ;Indicate error.
exit rts ;Exit.
*
* Set entry_num = entry_number + displacement...
*
base_1 clc ;Prepare for addition.
lda entry_num ;Do it.
adc displacement
bcs hit_end ;Out of range!
bra save_it ;Continue.
*
* Set entry_num = displacement. If displacement is zero then we need to
* count the entries...
*
base_0 lda displacement ;Get displacement. Zero?
bne save_it ;Nope.
*
* Both base and displacement fields are zero, so we must count records
* in the directory. Go find record #1 then clear entry_num and clear it
* in the fcr too...
*
inc a ;Set entry_num to 1.
sta entry_num
jsr find_dir_record ;Go find it.
bcs error ;Error.
lda #0 ;Get zero.
sta entry_num ;Clear entry_num.
ldy #fcr_entry_num ;Point to entry_num in fcr.
sta [my_fcr],y ;Clear it.
*
* Count records in this block and add to entry_num...
*
count_loop jsr count_dir_recs ;Count them.
clc ;Add count to entry_num.
txa
adc entry_num ;Did we rollover?
bcc save_num ;Nope.
lda #$ffff ;Yes, so set to max.
save_num sta entry_num ;Save it.
sta current_record ;Save for do_update.
*
* Go get next block, update fcr and loop. Exit loop when we get an error
* from read_next_block...
*
jsr read_next_block ;Get next block. Error?
bcs got_error ;Yep.
inc current_record ;Nope, bump current by 1.
jsr do_update ;Update fcr.
bra count_loop ;Loop.
*
* We got an error. If it's not an end_of_dir error then exit, else find
* last record and exit thru count_exit...
*
got_error cmp #end_of_dir ;End of dir error?
bne error ;Nope, so real error.
jsr find_dir_record ;Get last record.
bcs error ;Error.
bra count_exit ;Exit.
*
* We're doing a normal call. Save entry_num and go search for it. Found?
*
save_it sta entry_num ;Save it.
jsr find_dir_record ;Go search. Found?
bcs error ;Nope, so error.
*
* Yes, so put entry_num in fcr...
*
ldy #fcr_entry_num ;Get offset to entry_num.
lda entry_num ;Get it.
sta [my_fcr],y ;Save it.
*
* Copy name to file_name...
*
lda dir_record_0+dir_len_fi ;Get name length.
and #$00ff ;Clear high byte.
sta file_name ;Put length in file_name.
tay ;Use as offset.
bne cont ;Continue if non-zero.
inc file_name ;Zero, so force length to 1.
lda #'AB' ;Set name to 'A'.
sta file_name+1
bra count_exit ;Exit.
longa off ;Set 8 bit A.
cont sep #$20
copy_name lda dir_record_0+dir_len_fi,y ;Get byte.
sta file_name+1,y ;Put in file_name.
dey ;Done all?
bne copy_name ;Nope, so loop.
longa on ;Set 16 bit A.
rep #$20
*
* Get eof & blocks_used, and exit thru send_output...
*
count_exit jsr get_dir_info ;Get eof & blocks_used.
jmp send_output ;Exit thru send_output.
ENDP
eject
******************************************************************************
*
* Name: find_dir_record
*
* Description: Searches directory for specific record and moves it to
* dir_record_0.
*
* Created: Nov 4, 1987
* Modified: July 28, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* entry_num ;entry to find.
* my_fcr ;points to fcr for directory.
*
* Output: A = error code if error.
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* dir_record_0 ;holds record if found.
* extended_flag ;$8000 if record has associated file.
*
* Uses: All registers
* current_record
* record_offset
* length
* io_buffer (points to open_buffer in fcr!)
* read_next_block (sub)
* read_prev_block (sub)
* move_dir_record (sub)
*
******************************************************************************
find_dir_record proc
with data
*
* Set current_record to record # of first record of the current directory
* block, and set extended_flag if b15 set...
*
stz extended_flag ;Clear extended_flag.
ldy #fcr_start_rec ;Get offset to start record.
lda [my_fcr],y ;Get start record.
and #set_extended ;Extended bit set?
beq set_record ;Nope.
sta extended_flag ;Yep, so set extended_flag.
set_record lda [my_fcr],y ;Recover start record.
and #$7fff ;Clear b15.
sta current_record ;Save it.
*
* Is current_record greater than entry_num?
*
cmp entry_num ;current_record > entry_num?
bcc search ;No, we're ok.
beq search ;No, we're ok.
*
* Yes, so get previous directory block, set new current record. Keep going
* back until we are before the entry we want or are exactly on it...
*
back_up jsr read_prev_block ;Get previous.
bcs error_hop ;Error.
jsr count_dir_recs ;Count records.
sec ;Adjust current record.
lda current_record
sbc record_count
sta current_record
stz extended_flag ;Clear extended flag.
jsr do_update ;Set new open_block and start_rec.
lda current_record ;Recover current record.
cmp entry_num ;Are we before the entry we want?
bcc search ;Yep.
beq at_entry ;No, we're right on it.
bra back_up ;Nope, so back up a block.
*
* We're on exactly the one we want. Are we looking at entry number 1?
*
at_entry cmp #1 ;Entry 1?
beq search ;Yep, so continue.
*
* No. This means that we want the first record in this block. Since we had
* to back up to get here, the extended_flag is not set correctly. To set it,
* we must read the previous block, call count_dir_recs, then re-read the
* current block...
*
jsr read_prev_block ;Read previous block.
bcs error_hop ;Exit on error.
jsr count_dir_recs ;Go set the extended_flag.
jsr read_next_block ;Recover block.
bcc read_ok ;Continue on no error.
error_hop brl error ;Exit on error.
read_ok jsr do_update ;Update fcr.
lda current_record ;Recover current record.
*
* Ok, we've got the starting block in the fcr (pointed to now by io_buffer) and
* we have the record # of the first record in this block. We're ready to start
* searching forwards. Init record_offset...
*
search ldy #0 ;Init offset.
tax ;Put current_record in X.
*
* Have we done all records in this block?
*
search_loop sty record_offset ;Save offset.
cpy log_blk_size ;Done all?
bcs next_block ;Yes, so next block.
lda [io_buffer],y ;No, get length of record.
and #$00ff ;Look at low byte only. Zero?
beq next_block ;Yes, so next block.
sta length ;Save length.
*
* No. Clear extended_flag and skip this record if the name is either a 0 or a 1.
* (carry is clear from cpy log_blk_size!)...
*
tya ;Get offset. (carry still clear!)
adc #dir_file_id ;Adjust to point to file name.
tay
lda [io_buffer],y ;Get 1st byte of name.
and #$00ff
cmp #2 ;Is it a 0 or a 1?
bcs check_dir ;Nope, so check it.
stz extended_flag ;Yes, clear flag.
bra skip_record ;Skip record.
*
* Is the file a directory? Clear extended flag and branch to check_record if so...
*
check_dir clc ;Adjust offset to point to file flags.
lda record_offset
adc dir_file_flags
tay
lda [io_buffer],y ;Get file flags.
and #dir_mask ;Is this a directory?
beq check_assoc ;Nope.
stz extended_flag ;Yes, clear flag.
bra check_record ;Continue.
*
* If the file is an associated file and this is an ISO 9660 volume, set extended_flag.
* If we are at the correct record number, copy record to dir_record_1 then skip
* record...
*
check_assoc lda [io_buffer],y ;Get file flags.
and #assoc_mask ;Is this an associated file?
beq check_record ;Nope.
lda state_flag ;Yep, is this a High Sierra volume?
and #iso_bit
beq skip_record ;Yep, so skip record.
lda #set_extended ;Nope, set flag.
sta extended_flag
cpx entry_num ;Are we at the correct record?
bne skip_record ;Nope.
pei length ;Yep, save length.
phx ;Save X.
lda #0001 ;Copy record to dir_record_1.
jsr move_dir_record
plx ;Recover X.
pla ;Restore length.
sta length
bra skip_record ;Skip record.
*
* Are we at the correct record?
*
check_record cpx entry_num ;Are we there yet, mom?
beq found ;Yes.
*
* No, so bump record # and clear extended_flag...
*
inx ;Bump record #.
stz extended_flag ;Clear flag.
*
* Skip to the next record...
*
skip_record clc ;Add length to offset.
lda length
adc record_offset
tay
bra search_loop ;And loop.
*
* Get next directory block. Set new current_record, call next_dir_block,
* update fcr, and loop...
*
next_block stx current_record ;Save record.
jsr read_next_block ;Get next.
bcs error ;Error.
jsr do_update ;Set new open_block and start_rec.
lda current_record ;Recover current record.
brl search ;Continue search.
*
* We found it. Move record to dir_record_0 and exit with carry clear...
*
found stx current_record ;Save current record.
lda #0 ;Select dir_record_0.
jsr move_dir_record ;Move it.
clc ;Indicate found.
error rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: count_dir_recs
*
* Description: Count # of records in directory block.
*
* Created: Nov 6, 1987
* Modified: July 28, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* io_buffer ;points to directory block.
* log_blk_size ;current log_blk_size.
*
* Output: A = undefined
* X = count
* Y = undefined
* P = nvmxdizc
* ..000..1 = error
* 0 = no error
* B = K
*
* record_count ;holds count.
* extended_flag ;$8000 if last entry is associated.
*
* Uses: All registers
* record_count
* length
*
******************************************************************************
count_dir_recs proc
with data
*
* Init offset, extended_flag and count...
*
ldy #0 ;Init offset.
sty extended_flag ;Clear extended_flag.
tyx ;Init count.
*
* Have we done all records in this block?
*
count_loop sty record_offset ;Save offset.
cpy log_blk_size ;Done all?
bcs done ;Yes, done.
lda [io_buffer],y ;No, get length of record.
and #$00ff ;Look at low byte only. Zero?
beq done ;Yes, so done.
sta length ;Save length.
*
* No. Is the file a directory? (carry is clear from cpy log_blk_size!)...
*
tya ;Get offset.
adc dir_file_flags ;Adjust to point to file flags.
tay
lda [io_buffer],y ;Get file flags.
and #dir_mask ;Is this a directory?
beq check_assoc ;Nope.
*
* Yes, clear extended_flag and skip this record if the name is either a 0 or a
* 1...
*
stz extended_flag ;Clear flag.
lda record_offset ;Get offset. (carry still clear!)
adc #dir_file_id ;Adjust to point to file name.
tay
lda [io_buffer],y ;Get 1st byte of name.
and #$00ff
cmp #2 ;Is it a 0 or a 1?
bcc skip_record ;Yes, so ignore it.
bra bump_record ;Nope, so bump record #.
*
* No, if the file is an associated file and the volume is High Sierra, set
* extended_flag and skip record...
*
check_assoc lda [io_buffer],y ;Get file flags.
and #assoc_mask ;Is this an associated file?
beq bump_record ;Nope.
lda state_flag ;Yep, is this a High Sierra volume?
and #iso_bit
beq skip_record ;Yep, so skip record.
lda #set_extended ;Nope, set flag.
sta extended_flag
bra skip_record ;Skip record.
*
* Bump record # and clear extended_flag...
*
bump_record inx ;Bump record #.
stz extended_flag ;Clear flag.
*
* Skip to the next record...
*
skip_record clc ;Add length to offset.
lda length
adc record_offset
tay
bra count_loop ;And loop.
*
* Save count and exit...
*
done stx record_count ;Save count.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: do_update
*
* Description: Sets fcr_open_block and fcr_start_record.
*
* Created: Nov 6, 1987
* Modified: Apr 8, 1988
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* current_record ;current record #.
* extended_flag ;$8000 if last record is associated.
* drvr_blk_num ;current block #.
*
* Output: A = current_record
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Uses: All registers
* current_record
* drvr_blk_num
*
******************************************************************************
do_update proc
with data
*
* Set fcr_open_block and fcr_start_rec and exit...
*
ldy #fcr_open_block ;Get offset to low word of open_block.
lda drvr_blk_num ;Get low word of current block.
sta [my_fcr],y ;Put in fcr.
ldy #fcr_open_block+2 ;Get offset to high word of open_block.
lda drvr_blk_num+2 ;Get high word of current block.
sta [my_fcr],y ;Put in fcr.
ldy #fcr_start_rec ;Get offset to start record.
lda current_record ;Get current record.
ora extended_flag ;Add id extended_flag.
sta [my_fcr],y ;Put in fcr.
rts ;Exit.
ENDP
eject
eject
******************************************************************************
*
* Name: get_dev_num
*
* Description: Get device number of requested volume.
*
* Created: Nov 3, 1987
* Modified: Nov 3, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0
* B = K
*
* Uses: All registers
*
******************************************************************************
get_dev_num proc
with data
*
* Did we get passed a device number?
*
lda dev_num ;Do we have a device #?
bne got_it ;Yes.
*
* No, so use the volume name to find it...
*
jsr process_path ;Go look. Found?
bcs error ;Nope.
lda drvr_dev_num ;Yes, get device number.
*
* Save device number, send output and exit...
*
got_it sta dev_number ;Save number.
jsr send_output ;Send it.
error rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: fst_specific
*
* Description: This routine is a dispatcher for the fst_specific calls. It
* uses command_num to dispatch to the correct routine.
*
* NOTE: These routines do not use send_output to return
* parameters, but do it themselves.
*
* Created: Dec 4, 1987
* Modified: Dec 4, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* command_num ;command_num
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Exit: rts
*
* Uses: all registers
*
******************************************************************************
fst_specific proc
with data
*
* Dispatch to the selected routine...
*
lda command_num ;Get command number.
asl a ;Multiply by 2.
tax ;Use as index.
jmp (specific_cmds,x) ;Jump to it.
ENDP
eject
******************************************************************************
*
* Name: post_volume_changed
*
* Description: This routine calls the GS/OS notification queue with a volume-
* changed event for every MS-DOS VCR that's swapped in.
*
* Created: 25-Aug-92
* Modified: 25-Aug-92
* Author: Dave Lyons
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* Exit: rts
*
* Uses: all registers
*
******************************************************************************
post_volume_changed proc Export
temp_ptr equ my_fcr
lda #$0001 ;Start with the first FST
more jsl get_vcr ;Ask for the VCR
bcs done ;Past the last VCR
jsl deref ;Deref VP into temp_ptr
stx <temp_ptr
sty <temp_ptr+2
ldy #vcr_fst_id
lda [<temp_ptr],y
cmp #highSierraFSID ;is it our volume?
beq @ours
cmp #iso9660FSID ;I said, is it our volume?
bne next_vcr
@ours
ldy #vcr_status
lda [<temp_ptr],y
and #vcr_swapped ; bit set if VCR swapped out
bne next_vcr
pea $2033 ; call number (for A) = FSTSpecific
ldy #vcr_dev ; get device number
lda [<temp_ptr],y
pha ; to be passed in X
pha ; undefined: passed in Y
lda #<volume_change ; get event code in A,X
ldx #^volume_change
jsl post_os_event ; signal the event
next_vcr lda #$0000 ;Value for get next vcr
bra more
done rts
EndP
eject
******************************************************************************
*
* Name: map_enable
*
* Description: This routine enables or disables file type mapping.
*
* Created: Dec 16, 1987
* Modified: Dec 16, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_pblk ;points to parameter block.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0
* B = K
*
* Exit: rts
*
* Uses: all registers
* my_pblk
* map_enable_flag
* temp1
*
******************************************************************************
map_enable proc
with data
*
* Setup pointer to current map...
*
lda map_buffer_ptr ;Get pointer.
ldx map_buffer_ptr+2
sta map_ptr ;Put in direct page pointer.
stx map_ptr+2
*
* Set map_enable_flag and exit with carry clear...
*
ldy #map_enable_off ;Get offset to map_enable.
lda [my_pblk],y ;Get flag.
cmp map_enable_flag ;added 25-Aug-92 DAL
sta map_enable_flag ;Save it.
*** added 25-Aug-92 DAL
beq @skip_changed
jsr post_volume_changed
@skip_changed
*** end 25-Aug-92
clc ;No error.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: get_map_size
*
* Description: This routine returns the size of the current file type map in
* the callers parameter block.
*
* Created: Dec 4, 1987
* Modified: Dec 4, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_pblk ;points to parameter block.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0
* B = K
*
* Exit: rts
*
* Uses: all registers
* my_pblk
* temp1
*
******************************************************************************
get_map_size proc
with data
*
* Setup pointer to current map...
*
lda map_buffer_ptr ;Get pointer.
ldx map_buffer_ptr+2
sta map_ptr ;Put in direct page pointer.
stx map_ptr+2
*
* Get length, stuff it into the parameter block, and exit with carry clear...
*
lda [map_ptr] ;Get length.
ldy #map_size ;Get offset to map_size.
sta [my_pblk],y ;Send length.
clc ;No error.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: get_map_table
*
* Description: This routine copies the current file type map into the buffer
* pointed to by the map_buffer parameter in the parameter list.
*
* NOTE: No checking is done on the size of the caller's buffer!
*
* Created: Dec 4, 1987
* Modified: Dec 4, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_pblk ;points to parameter block.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0
* B = K
*
* Exit: rts
*
* Uses: all registers
* my_pblk
* temp1
* data_buffer
*
******************************************************************************
get_map_table proc
with data
*
* Setup pointer to current map...
*
lda map_buffer_ptr ;Get pointer.
ldx map_buffer_ptr+2
sta map_ptr ;Put in direct page pointer.
stx map_ptr+2
*
* Get buffer pointer out of parameter list...
*
ldy #map_buffer ;Get offset to pointer.
lda [my_pblk],y ;Get low word of pointer.
sta data_buffer ;Save it.
iny ;Bump offset.
iny
lda [my_pblk],y ;Get high word of pointer.
sta data_buffer+2 ;Save it.
*
* Copy map to data_buffer and exit with carry clear...
*
lda [map_ptr] ;Get length of table.
tay ;Use as offset.
longa off ;Set 8 bit A.
sep #$20
copy_loop dey ;Done all?
bmi restore_a ;Yep.
lda [map_ptr],y ;Nope, get byte.
sta [data_buffer],y ;Put it in buffer.
bra copy_loop ;And loop.
longa on ;Restore 16 bit A.
restore_a rep #$20
clc ;No error.
rts ;Exit.
ENDP
eject
******************************************************************************
*
* Name: set_map_table
*
* Description: This routine replaces the current file type map with one
* provided by the caller.
*
* Created: Dec 4, 1987
* Modified: Dec 4, 1987
* Author: Bryan Atsatt
*
* Entry: jsr
*
* Input: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000...
* B = K
*
* my_pblk ;points to parameter block.
*
* Output: A = undefined
* X = undefined
* Y = undefined
* P = nvmxdizc
* ..000..0
* B = K
*
* Exit: rts
*
* Uses: all registers
* my_pblk
* temp1
* data_buffer
*
******************************************************************************
set_map_table proc
with data
*
* Save the current map_buffer_vp so we can release it after we successfully
* allocate a new one...
*
lda map_buffer_vp ;Get vp.
ldx map_buffer_vp+2
sta old_vp ;Save it.
stx old_vp+2
*
* Get buffer pointer out of parameter list...
*
ldy #map_buffer ;Get offset to pointer.
lda [my_pblk],y ;Get low word of pointer.
sta data_buffer ;Save it.
iny ;Bump offset.
iny
lda [my_pblk],y ;Get high word of pointer.
sta data_buffer+2 ;Save it.
*
* Get size of map and allocate memory for it. Exit with out_of_mem error
* if we couldn't allocate enough memory...
*
lda [data_buffer] ;Get size of map
jsr alloc_seg ;Get a hunk that size.
lda #out_of_mem ;Get error code in case full.
bcs exit ;Error, so exit with carry set.
stx map_buffer_vp ;Save new vp.
sty map_buffer_vp+2
jsl deref ;Dereference vp.
stx map_ptr ;Save pointer.
sty map_ptr+2
*
* Copy map into map buffer...
*
lda [data_buffer] ;Get length of table.
tay ;Use as offset.
longa off ;Set 8 bit A.
sep #$20
copy_loop dey ;Done all?
bmi restore_a ;Yep.
lda [data_buffer],y ;Nope, get byte.
sta [map_ptr],y ;Put it in buffer.
bra copy_loop ;And loop.
longa on ;Restore 16 bit A.
restore_a rep #$20
*
* Now let's deallocate the old map and exit with carry clear...
*
ldx old_vp ;Get old vp.
ldy old_vp+2
jsl release_seg ;Release it.
jsr post_volume_changed ;added 25-Aug-92 DAL
clc ;No error.
exit rts ;Exit.
ENDP
eject
*******************************************************************************
*
* END OF CODE
*
*******************************************************************************
end_segment proc
end_code ;
ENDP
eject
END