mirror of
https://github.com/marketideas/qasm.git
synced 2026-10-24 22:02:28 +00:00
Move the assembler to src/qasm. qlink links OMF 1.0 and 2.0 from a script. makeBin flattens a load file, qomf dumps OMF, and qpro builds ProDOS volumes. APW and MPW assemble through the ORCA front end. Relocatable modules emit OMF objects. Listings stay off unless -l is set. make boot assembles the GS/OS 6.0.1 ProDOS 8 kernel and BASIC.SYSTEM into an 800K volume. BASIC.SYSTEM accepts ls and pfx, and its splash reports PRODOS BASIC 2.0, copyright 1983-2026. IIGS.601.SRC is the source and the BASIC.SYSTEM oracle that image is built from.
1 line
518 KiB
Plaintext
1 line
518 KiB
Plaintext
print push
|
|
print off
|
|
|
|
string asis
|
|
|
|
include 'common.equ.src'
|
|
|
|
;------------------------------------------
|
|
;
|
|
; Equates from procedure
|
|
;
|
|
;------------------------------------------
|
|
CallStringToText equ 1 ;conditional code for JudgeName, 14-Apr-91 DAL
|
|
AllowLCPeriods equ 0 ;conditional code allowing blanks in names, 7-Aug-91 DAL
|
|
;(0 = no blanks allowed, 12-Aug-91 GAB)
|
|
|
|
debug_on equ 00 ;00 = debug off, <>0 = debug on
|
|
word equ 02 ;two bytes for a word
|
|
blk_size equ 512 ;standard size of a prodos block
|
|
delimiter equ $3A ;pathname delimiter = ":"
|
|
min_send_cnt equ $21 ;If read < 33 bytes use local routine
|
|
|
|
vcr_main equ vcr_dev+2
|
|
vol_reserved equ $0000 ;8 bytes of reserved field from disk
|
|
vol_mod equ vol_reserved+2 ;volume mod date
|
|
vol_create equ vol_reserved+8 ;create date/time from header
|
|
vol_version equ vol_create+4 ;version of OS that created file
|
|
vol_min_version equ vol_version+1 ;minimum version of OS that can access
|
|
vol_access equ vol_min_version+1 ;access for a file
|
|
vol_entry_len equ vol_access+1 ;entry length of each entry
|
|
vol_entries equ vol_entry_len+1 ;number of entries per block
|
|
vol_file_count equ vol_entries+1 ;number of files in volume directory
|
|
vol_bitmap_addr equ vol_file_count+2 ;starting block of bitmap
|
|
vol_total_blks equ vol_bitmap_addr+2 ;total number of blocks on disk
|
|
|
|
num_bitmap_blks equ vol_total_blks+2 ;total number of bitmap blocks
|
|
end_bitmap equ num_bitmap_blks+2 ;1st byte that starts all zeros
|
|
avail_bitmap equ end_bitmap+2 ;1st bitmap block(rel) with free space
|
|
curr_bitmap equ avail_bitmap+2 ;current bitmap(rel) block in memory
|
|
bitmap_dirty equ curr_bitmap+2 ;0 = bitmap clean, <> 0 = bitmap dirty
|
|
free_blocks equ bitmap_dirty+2 ;Free blocks on volume,$FFFF = unknown
|
|
vol_damaged equ free_blocks+2 ;stops writing to bad disk if <> 00
|
|
dirty_file_cnt equ vol_damaged+2 ;number of files that are open for writing and are dirty
|
|
bitmap_start equ dirty_file_cnt+4+vcr_main
|
|
pro_vcr_size equ bitmap_start+$200
|
|
bitmap_mod equ $FFFF
|
|
bitmap_unknown equ $FFFF
|
|
vcr_entry_length equ $000F
|
|
|
|
fcr_res_num equ $0000 ;resource number of this file
|
|
fcr_storage equ fcr_res_num+2 ;real storage type on disk
|
|
fcr_entry_type equ fcr_storage+2 ;storage type from directory entry
|
|
fcr_file_id equ fcr_entry_type+2 ;used to ID duplicate files
|
|
fcr_file_type equ fcr_file_id+2 ;file type
|
|
fcr_key_blk equ fcr_file_Type+1 ;key block of the file
|
|
fcr_blks_used equ fcr_key_blk+2 ;number of blocks used
|
|
fcr_eof equ fcr_blks_used+2 ;current end of file
|
|
fcr_create equ fcr_eof+3 ;create date/time ProDOS
|
|
fcr_vers equ fcr_create+4 ;version of o/s that made file
|
|
fcr_min_vers equ fcr_vers+1 ;min version of o/s allowed
|
|
fcr_disk_acc equ fcr_min_vers+1 ;file access
|
|
fcr_aux_type equ fcr_disk_acc+1 ;aux type for this file
|
|
fcr_modified equ fcr_aux_type+2 ;modified date of file
|
|
fcr_header_ptr equ fcr_modified+4 ;key block of dir owner
|
|
fcr_status equ fcr_header_ptr+2 ;offset: current status of file
|
|
gde_entry_num equ fcr_status+2 ;current entry for Get_Dir_Entry
|
|
gde_offset equ gde_entry_num+2 ;current offset to entry
|
|
gde_curr_blk equ gde_offset+2 ;current directory block loaded
|
|
gde_tot_files equ gde_curr_blk+2 ;total files in directory
|
|
fcr_curr_mark equ gde_tot_files+2 ;current file mark
|
|
fcr_blks_alloc equ fcr_curr_mark+4 ;current number of blks alloc
|
|
fcr_curr_eof equ fcr_blks_alloc+2 ;current end of file
|
|
fcr_parent equ fcr_curr_eof+4 ;block number of directory block
|
|
fcr_entry_offs equ fcr_parent+2 ;index to entry within parent block
|
|
data_blk_num equ fcr_entry_offs+2 ;block number of current data block
|
|
index_blk_num equ data_blk_num+2 ;block number of current index block
|
|
master_blk_num equ index_blk_num+2 ;block number of master index block
|
|
|
|
clr_global_clean equ $7FFF ;clear the global clean bit
|
|
set_global_clean equ $8000 ;set the file clean in the FCR
|
|
set_access_res equ $4000 ;set the resource fork bit in the FCR
|
|
ClrAllButAccess equ $3FFF ;clear the resource bit from access word.
|
|
|
|
fcr_fst_ptr equ fcr_access+2
|
|
fcr_io_start equ master_blk_num+2+fcr_fst_ptr
|
|
fcr_data_size equ fcr_io_start+$200
|
|
fcr_index_size equ fcr_io_start+$400
|
|
fcr_master_size equ fcr_io_start+$600
|
|
|
|
|
|
my_pblk_ptr equ fst_start
|
|
my_vcr_ptr equ my_pblk_ptr+4
|
|
prodos_vcr_ptr equ my_vcr_ptr+4
|
|
my_fcr_ptr equ prodos_vcr_ptr+4
|
|
pro_fcr_ptr equ my_fcr_ptr+4
|
|
gbuf_ptr equ pro_fcr_ptr+4
|
|
temp_ptr equ gbuf_ptr+4
|
|
temp2_ptr equ temp_ptr+4
|
|
temp3_ptr equ temp2_ptr+4
|
|
temp4_ptr equ temp3_ptr+4
|
|
temp5_ptr equ temp4_ptr+4
|
|
math_temp equ temp5_ptr+4
|
|
data_ptr equ math_temp+4
|
|
index_ptr equ data_ptr+4
|
|
master_ptr equ index_ptr+4
|
|
bitmap equ master_ptr+4
|
|
users_buf_ptr equ bitmap+4
|
|
sparse_ptr equ users_buf_ptr+4
|
|
newline_ptr equ sparse_ptr+4
|
|
pro_id equ $0001 ;identifies prodos fst
|
|
prodos_version equ $0005 ;current version of the PRODOS.
|
|
path1_mask equ $4000 ;used to determine if path1 is avail.
|
|
path2_mask equ $0040 ;used to determine if path2 is avail.
|
|
carry equ $01 ;used to set the carry
|
|
overflow equ $40 ;used to set the overflow flag
|
|
in_cache equ $8002
|
|
user_cache_val equ $0001
|
|
class_mask equ $E000
|
|
disk_protect equ $0004 ;bit to see if disk is protected
|
|
max_base equ $0003
|
|
pcount1 equ 1
|
|
pcount2 equ 2
|
|
pcount3 equ 3
|
|
pcount4 equ 4
|
|
pcount5 equ 5
|
|
pcount6 equ 6
|
|
pcount7 equ 7
|
|
pcount8 equ 8
|
|
pcount9 equ 9
|
|
write_call equ $13
|
|
|
|
read_enabled equ $0001 ;1=Read Enabled
|
|
write_enabled equ $0002 ;1=Write Enabled
|
|
backup_enabled equ $0020 ;1=Needs to be backed up
|
|
rename_enabled equ $0040 ;1=Rename allowed
|
|
destroy_enabled equ $0080 ;1=Destroy is enabled
|
|
read_access equ $01
|
|
write_access equ $02
|
|
invis_bit equ $04
|
|
read_write_acc equ $03
|
|
|
|
seedling_type equ $0010 ;$0000000 < EOF < $0000201
|
|
sapling_type equ $0020 ;$0000200 < EOF < $0020001
|
|
tree_type equ $0030 ;$0020000 < EOF < $1000000
|
|
pascal_area equ $0040 ;Area set aside for Pascal
|
|
resource_type equ $0050 ;Special type for resource files
|
|
purge_dir equ $0060 ;directory that contains pugred files
|
|
subdir_type equ $00D0 ;Subdirectory
|
|
subdir_header equ $00E0 ;First entry in sudbirectory
|
|
volume_header equ $00F0 ;First entry in the volume directory
|
|
vol_dir_start equ $0002 ;start of the volume directory
|
|
bitmap_strt_blk equ $0006 ;start of the volume bitmap
|
|
entry_length equ $0027
|
|
entries_per_block equ $000D
|
|
parent_index equ $0027
|
|
par_entry_num equ $0029
|
|
res_header equ 08 ;number of bytes in a header
|
|
res_map_size equ 382 ;size of map for info call
|
|
purge_index equ $0019 ;index to flag indicating purge files.
|
|
purgable_index equ $0029 ;index to total blocks
|
|
purge_flag equ $00FE
|
|
purge_verify equ $0004
|
|
header_file_cnt equ $0025 ;number of files in a directory
|
|
backup_on equ $20
|
|
backup_off equ $DF
|
|
file_type_index equ $10 ;look at page 168 (ProDOS 8 manual)
|
|
key_blk_index equ $11 ;index into disk entry
|
|
blks_used_index equ $13
|
|
eof_index equ $15
|
|
create_index equ $18
|
|
version_index equ $1C
|
|
min_version equ $1D
|
|
access_index equ $1E
|
|
aux_type_index equ $1F
|
|
last_mod_index equ $21
|
|
header_ptr_index equ $25
|
|
no_root equ $8000 ;indicates root level name is invalid
|
|
no_dup equ $4000 ;indicates duplicates are not valid
|
|
root_only equ $2000 ;allow only the root level in pathname
|
|
|
|
vol_mod_offset equ $16 ;offset to the volume mod date field
|
|
vol_acc_offset equ $22 ;offset to the volume access field
|
|
|
|
dir_file_type equ $0F
|
|
tool_locator equ $E10000
|
|
misc_tools equ $0003
|
|
read_time_hex equ $000D ;read the clock via misc_tools
|
|
|
|
set_time_stamp equ $0001
|
|
get_time_stamp equ set_time_stamp+$8000
|
|
set_upper_case equ $0002
|
|
get_upper_case equ set_upper_case+$8000
|
|
|
|
debugger_cmnd equ $0002
|
|
debugger_status equ debugger_cmnd+$8000
|
|
|
|
file_dirty equ $8000 ;ora masks to active field
|
|
data_active equ $4000
|
|
index_active equ $2000
|
|
master_active equ $1000
|
|
|
|
file_clean equ $7FFF ;and masks to deactivate field
|
|
data_inactive equ $BFFB
|
|
index_inactive equ $DFFD
|
|
master_inactive equ $EFFE
|
|
|
|
dirEntry_dirty equ $0008
|
|
dirEntry_clean equ ÅdirEntry_dirty ;'Å' is the assembler's one's complement operator
|
|
data_dirty equ $0004
|
|
data_clean equ $FFFB
|
|
index_dirty equ $0002
|
|
index_clean equ $FFFD
|
|
master_dirty equ $0001
|
|
master_clean equ $FFFE
|
|
|
|
hfs_id equ $0006 ;HFS FST ID
|
|
ashare_id equ $000D ;AppleShare FST ID
|
|
finfo_type equ 1 ;HFS FInfo entry type
|
|
xfinfo_type equ 2 ;HFS xFInfo entry type
|
|
|
|
;------------------------------------------
|
|
;
|
|
; Equates from procedure data
|
|
;
|
|
;------------------------------------------
|
|
drvr_bytes equ $1A ;start at byte $1A and $1B
|
|
path_used equ $0100
|
|
vcr_used equ $0200
|
|
fcr_used equ $0400
|
|
io_used equ $0800
|
|
clr_io_used equ $F7FF
|
|
flush_1st equ $1000
|
|
damage equ $2000
|
|
max_class1 equ $0020
|
|
max_class2 equ $0040
|
|
max_class3 equ $0060
|
|
max_class4 equ $0080
|
|
max_class5 equ $00A0
|
|
max_class6 equ $00C0
|
|
max_class7 equ $00E0
|
|
max_pcnt1 equ 1+1
|
|
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
|
|
do_dirty equ $4000
|
|
|
|
|
|
;-----------------------------------------------
|
|
;
|
|
; Forward addresses and entries
|
|
;
|
|
;-----------------------------------------------
|
|
|
|
ENTRY abs_to_rel
|
|
ENTRY activate_vcr
|
|
ENTRY add_free_blk
|
|
ENTRY add_index
|
|
ENTRY appl_call
|
|
ENTRY bitmap_changed
|
|
ENTRY bitmap_corrupt
|
|
ENTRY build_path
|
|
ENTRY build_the_fcr
|
|
ENTRY build_vcr
|
|
ENTRY calc_curr_mark
|
|
ENTRY change_path
|
|
ENTRY check_base
|
|
ENTRY check_dup
|
|
ENTRY check_vcr_first
|
|
ENTRY chk_allocation
|
|
ENTRY chk_vol_syntax
|
|
ENTRY clear_backup
|
|
ENTRY clear_index
|
|
ENTRY close
|
|
ENTRY clr_fcr_status
|
|
ENTRY clr_to_boundary
|
|
ENTRY cmd_error
|
|
ENTRY cmd_tbl
|
|
ENTRY create
|
|
ENTRY damaged_message
|
|
|
|
IF debug_on<>0 THEN
|
|
ENTRY debugger
|
|
ENDIF
|
|
ENTRY dec_blk_count
|
|
ENTRY deferred_flush
|
|
ENTRY destroy
|
|
ENTRY dev_with_mount
|
|
ENTRY device_call
|
|
ENTRY dow_convert
|
|
ENTRY end_read_write
|
|
ENTRY entry_to_gstr
|
|
ENTRY eof_to_blks
|
|
ENTRY erase_disk
|
|
ENTRY fast_read
|
|
ENTRY fill_io_buf
|
|
ENTRY find_file
|
|
ENTRY find_resource
|
|
ENTRY find_volume
|
|
ENTRY flush
|
|
ENTRY flush_blocks
|
|
ENTRY flush_data_blk
|
|
ENTRY flush_file
|
|
ENTRY flush_index
|
|
ENTRY force_bitmap
|
|
ENTRY format_disk
|
|
ENTRY fst_specific
|
|
ENTRY get_bit_block
|
|
ENTRY get_data_num
|
|
ENTRY get_dev_num
|
|
ENTRY get_dir_entry
|
|
ENTRY get_eof
|
|
ENTRY get_file_info
|
|
ENTRY get_index_blk
|
|
ENTRY get_mark
|
|
ENTRY get_next_fcr
|
|
ENTRY get_time
|
|
ENTRY get_write_blk
|
|
ENTRY id_disk
|
|
ENTRY issue_mount
|
|
ENTRY judge_name
|
|
ENTRY kill_bitmap
|
|
ENTRY load_data
|
|
ENTRY load_index
|
|
ENTRY make_entry_num
|
|
ENTRY mount_volume
|
|
ENTRY move_dir_entry
|
|
ENTRY move_vol_entry
|
|
ENTRY num_seq_blks
|
|
ENTRY open
|
|
ENTRY range_error
|
|
ENTRY read
|
|
ENTRY read_block
|
|
ENTRY read_with_cache
|
|
ENTRY reset_vcr
|
|
ENTRY sapling_seed
|
|
ENTRY save_curr_mark
|
|
ENTRY send_partial
|
|
ENTRY send_sparse_blk
|
|
ENTRY send_time
|
|
ENTRY set_eof
|
|
ENTRY set_fcr_status
|
|
ENTRY set_file_info
|
|
ENTRY set_mark
|
|
ENTRY set_user_cache
|
|
ENTRY setup_bitmap_ptr
|
|
ENTRY setup_curr_eof
|
|
ENTRY setup_curr_mark
|
|
ENTRY setup_io_buf
|
|
ENTRY setup_io_ptrs
|
|
ENTRY setup_my_fcr
|
|
ENTRY setup_my_vcr
|
|
ENTRY setup_name
|
|
ENTRY setup_vol_mesg
|
|
ENTRY show_damage
|
|
ENTRY shutdown
|
|
ENTRY slug_ripple
|
|
ENTRY standard_req
|
|
ENTRY startup
|
|
ENTRY sub_free_blk
|
|
ENTRY sys_remove_vol
|
|
ENTRY sys_tbl
|
|
ENTRY system_call
|
|
ENTRY tree_sapling
|
|
ENTRY update_key_blk
|
|
ENTRY update_mark_eof
|
|
ENTRY vol_to_buffer
|
|
ENTRY volume
|
|
ENTRY write
|
|
ENTRY write_block
|
|
ENTRY Chk_Dirty_Flag
|
|
ENTRY dirty_flags
|
|
|
|
print pop
|
|
;======================================================================
|
|
;
|
|
;ProDOS File System Translator for GS/OS
|
|
;
|
|
;Created: Feb 25, 1987
|
|
;Modified: Mar 16, 1988
|
|
;Author: Rob Turner
|
|
;
|
|
;
|
|
;Copyright Apple Computer Inc. 1987-92 ALL RIGHTS RESERVED
|
|
;
|
|
;======================================================================
|
|
|
|
PRINT GEN
|
|
msb off
|
|
longa on
|
|
longi on
|
|
|
|
;equates for the read call.
|
|
|
|
pblk_12_ref equ $0000 ;index to the reference number
|
|
pblk_12_buf equ pblk_12_ref+2 ;index to user's buffer pointer
|
|
pblk_12_req equ pblk_12_buf+4 ;index to request count
|
|
pblk_12_tran equ pblk_12_req+4 ;index to transfer count
|
|
pblk_12_cache equ pblk_12_tran+4 ;index to user provided cache priority
|
|
|
|
max_read_pcnt equ $0005
|
|
|
|
;equates used by open
|
|
|
|
pblk_10_access equ $000A
|
|
pblk_10_ftype equ pblk_10_access+2
|
|
pblk_10_aux equ pblk_10_ftype+2
|
|
pblk_10_storage equ pblk_10_aux+4
|
|
pblk_10_eof equ pblk_10_storage+2
|
|
pblk_10_num_res equ pblk_10_eof+4
|
|
pblk_10_create equ pblk_10_num_res+2
|
|
pblk_10_mod equ pblk_10_create+8
|
|
pblk_10_blks equ pblk_10_mod+8
|
|
pblk_10_map equ pblk_10_blks+4
|
|
|
|
;equates used by set_mark
|
|
|
|
pblk_16_base equ $0002
|
|
pblk_16_disp equ pblk_16_base+2
|
|
|
|
;equates used by get_mark
|
|
|
|
pblk_17_pos equ $0002
|
|
|
|
;equates used by get_eof
|
|
|
|
pblk_19_eof equ $0002
|
|
|
|
;equates used by send_info
|
|
|
|
pblk_s_access equ $0000
|
|
pblk_s_ftype equ pblk_s_access+2
|
|
pblk_s_aux equ pblk_s_ftype+2
|
|
pblk_s_storage equ pblk_s_aux+4
|
|
pblk_s_create equ pblk_s_storage+2
|
|
pblk_s_mod equ pblk_s_create+8
|
|
pblk_s_opt equ pblk_s_mod+8
|
|
pblk_s_eof equ pblk_s_opt+4
|
|
pblk_s_blks equ pblk_s_eof+4
|
|
pblk_s_res_eof equ pblk_s_blks+4
|
|
pblk_s_res_blk equ pblk_s_res_eof+4
|
|
|
|
;equates used by volume
|
|
|
|
pblk_08_vol equ $0004
|
|
pblk_08_tot equ pblk_08_vol+4
|
|
pblk_08_free equ pblk_08_tot+4
|
|
pblk_08_id equ pblk_08_free+4
|
|
pblk_08_size equ pblk_08_id+2
|
|
pblk_08_purge equ pblk_08_size+2
|
|
|
|
;equates used by set_file_info
|
|
|
|
pblk_05_accs equ $0004
|
|
pblk_05_ftype equ pblk_05_accs+2
|
|
pblk_05_aux equ pblk_05_ftype+2
|
|
pblk_05_create equ pblk_05_aux+6
|
|
pblk_05_mod equ pblk_05_create+8
|
|
pblk_05_opt equ pblk_05_mod+8
|
|
|
|
;equates used by get_file_info
|
|
|
|
pblk_06_map equ $0028
|
|
|
|
;equates used by set_eof
|
|
|
|
pblk_18_odisp equ $0002
|
|
pblk_18_base equ $0002
|
|
pblk_18_disp equ pblk_18_base+2
|
|
|
|
;equates used by create
|
|
|
|
pblk_01_accs equ $0004
|
|
pblk_01_ftype equ pblk_01_accs+2
|
|
pblk_01_aux equ pblk_01_ftype+2
|
|
pblk_01_stype equ pblk_01_aux+4
|
|
pblk_01_eof1 equ pblk_01_stype+2
|
|
pblk_01_eof2 equ pblk_01_eof1+4
|
|
|
|
pblk_01_old_time equ $000E
|
|
|
|
;equates used by get dir entry
|
|
|
|
pblk_1c_extend equ $0002
|
|
pblk_1c_disp equ $0002
|
|
pblk_1c_name equ pblk_1c_disp+2
|
|
pblk_1c_entry equ pblk_1c_name+4
|
|
pblk_1c_ftype equ pblk_1c_entry+2
|
|
pblk_1c_eof equ pblk_1c_ftype+2
|
|
pblk_1c_blks equ pblk_1c_eof+4
|
|
pblk_1c_create equ pblk_1c_blks+4
|
|
pblk_1c_mod equ pblk_1c_create+8
|
|
pblk_1c_access equ pblk_1c_mod+8
|
|
pblk_1c_aux equ pblk_1c_access+2
|
|
pblk_1c_id equ pblk_1c_aux+4
|
|
pblk_1c_opt equ pblk_1c_id+2
|
|
pblk_1c_res_eof equ pblk_1c_opt+4
|
|
pblk_1c_res_blks equ pblk_1c_res_eof+4
|
|
|
|
gde_max_base equ $0002
|
|
bad_file_format equ $004a
|
|
|
|
;equates used by judge_name 1/22/91 CAE
|
|
|
|
pblk_07_ntype equ $0002
|
|
pblk_07_syntax equ pblk_07_ntype+2
|
|
pblk_07_max_len equ pblk_07_syntax+4
|
|
pblk_07_name equ pblk_07_max_len+2
|
|
pblk_07_nflags equ pblk_07_name+4
|
|
|
|
;equates used by change_path 5-Dec-91 MSD
|
|
|
|
pblk_04_src equ $0000 ; (long) source pathname
|
|
pblk_04_dest equ $0004 ; (long) destination pathname
|
|
pblk_04_flags equ $0008 ; (word) $8000 = assume source is duplicate volume
|
|
|
|
; Revisions have been moved to the file "pro.fst.revisions" in the ProDOS project
|
|
; by Monte Benaresh on 6/21/90
|
|
|
|
;======================================================================
|
|
;Below is the FST header definition used by GS/OS at boot time
|
|
;======================================================================
|
|
|
|
EXPORT fst_header
|
|
fst_header PROC
|
|
EXPORT code_start
|
|
code_start
|
|
|
|
DC.B 'FST ' ;Says I'm a FST
|
|
DC.L appl_call ;Process a normal application call
|
|
DC.L system_call ;Process a FST system call
|
|
DC.W Pro_ID ;My ID number (ProDOS)
|
|
Export fst_attr
|
|
fst_attr DC.W $3003 ;(Uppercase pathnames if enabled), formattable, strip high bit.
|
|
DC.W $0402 ;Version 4.02 final
|
|
DC.W 512 ;block size
|
|
DC.L $10000 ;Max Blocks (32 meg)
|
|
DC.L $0007 ;Min Blocks
|
|
DC.L $01000000 ;max file size
|
|
DC.L $0000 ;reserved
|
|
DC.B 6
|
|
DC.B 'ProDOS'
|
|
|
|
string pascal
|
|
IF debug_on<>0 THEN
|
|
DC.B 'ProDOS FST w/Debugger v04.02'
|
|
ELSE
|
|
DC.B 'ProDOS FST v04.02'
|
|
ENDIF
|
|
|
|
DC.W 0000 ;reserved field
|
|
dc.b 'ProDOS FST written by Rob Turner. V4.02'
|
|
string asis
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;Below is the main entry point for ALL standard operating system calls.
|
|
;
|
|
;Input: X = Call number * 2
|
|
; Y = Class number * 2
|
|
; A = undefined
|
|
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT appl_call
|
|
appl_call PROC
|
|
import max_call
|
|
import write_occurred
|
|
import write_dev_num
|
|
import cp_device_flag
|
|
import fake_name_str
|
|
import error_priority
|
|
|
|
phk ;setup our bank register
|
|
plb
|
|
rep #$30
|
|
|
|
cpx #max_call+1 ;check command number
|
|
bcs cmd_error
|
|
jmp (cmd_tbl-2,x) ;call the function
|
|
|
|
EXPORT cmd_error
|
|
cmd_error
|
|
lda #bad_system_call
|
|
EXPORT error_exit
|
|
error_exit
|
|
sec
|
|
EXPORT main_exit
|
|
main_exit
|
|
IMPORT flags
|
|
|
|
; If we're reporting an error, then check cp_device_flag to see if we were
|
|
; renaming a duplicate volume. If so, we built a vcr with a fake name. Since we
|
|
; got an error at some point in the process, we need to find the vcr with the fake
|
|
; name and release it if it still exists. 1/22/91 CAE
|
|
|
|
pha ;save the error code
|
|
php ;save error flag
|
|
bcc @cont ;branch if no error
|
|
lda cp_device_flag ;did we build a vcr with a fake name?
|
|
bpl @cont ;no - so no need to clean up
|
|
|
|
ldx #fake_name_str ;get pointer to fake name string
|
|
ldy #^fake_name_str
|
|
lda #0000 ;search by name
|
|
jsl find_vcr
|
|
bcs @cont ;didn't find the vcr so we're ok
|
|
jsl deref ;dereference vcr pointer
|
|
stx <temp_ptr
|
|
sty <temp_ptr+2
|
|
lda [temp_ptr] ;get vcr id
|
|
jsl release_vcr ;release the vcr
|
|
@cont
|
|
jsl unlock_mem ;unlock the used handles
|
|
plp
|
|
php
|
|
bcc no_damage
|
|
|
|
lda 2,s ;get access to the error code
|
|
and #$00FF ;clear the garbage from the high byte please
|
|
cmp #drvr_bad_block ;the disk is probably bad
|
|
beq mark_damaged ;mark the volume as damaged
|
|
cmp #damaged_bitmap
|
|
beq mark_damaged
|
|
cmp #dir_error
|
|
bne no_damage ;the disk is still ok
|
|
|
|
mark_damaged
|
|
lda prodos_vcr_ptr ;make sure there is a vcr
|
|
ora prodos_vcr_ptr+2
|
|
beq no_damage
|
|
|
|
ldy #vol_damaged ;mark the VCR please
|
|
lda [prodos_vcr_ptr],y
|
|
inc a ;see if we have already told the user about the damage
|
|
beq no_damage ;we have told the user so skip the message
|
|
|
|
lda #$FFFF
|
|
sta [prodos_vcr_ptr],y
|
|
lda 1,s ;tell the user about the problem
|
|
jsr show_damage
|
|
|
|
no_damage
|
|
;
|
|
;Now we need to set the Global Clean Flag if we need to
|
|
;
|
|
lda pro_fcr_ptr ;make sure there is a fcr
|
|
ora pro_fcr_ptr+2
|
|
beq @no_fcr ;don't worry about it
|
|
|
|
lda flags ;There is a FCR now make sure it was used during the call.
|
|
and #fcr_used
|
|
beq @no_fcr ;no FCR is used by the call
|
|
|
|
ldy #fcr_status ;get the status out of the File Control Record
|
|
lda [pro_fcr_ptr],y
|
|
;
|
|
;If my bit (15) is set then the file is dirty so we must clear the Global_Clean Bit.
|
|
;
|
|
and #file_dirty ;clear all but the file dirty bit 15
|
|
eor #set_global_clean
|
|
sta math_temp
|
|
|
|
ldy #fcr_access
|
|
lda [my_fcr_ptr],y
|
|
and #clr_global_clean
|
|
ora math_temp
|
|
sta [my_fcr_ptr],y
|
|
;
|
|
;Now we need to see if we should check if the file has become dirty during the call
|
|
;
|
|
lda chk_dirty_flag
|
|
beq @no_fcr ;This call does not require processing
|
|
;
|
|
;Now lets see if the file was dirty at the beginning of the call. If it was then just
|
|
;exit. Otherwise update the dirty_file count in the VCR
|
|
;
|
|
lda dirty_flags
|
|
bne @no_fcr ;the file was dirty at the beginning
|
|
|
|
ldy #fcr_status ;get the status out of the File Control Record
|
|
lda [pro_fcr_ptr],y
|
|
and #file_dirty+data_dirty+index_dirty+master_dirty
|
|
beq @no_fcr ;The file is still clean
|
|
;
|
|
;Now we must update the dirty file count
|
|
;
|
|
ldy #dirty_file_cnt ;get the original count
|
|
lda [prodos_vcr_ptr],y
|
|
inc a
|
|
sta [prodos_vcr_ptr],y
|
|
@no_fcr
|
|
lda write_occurred ;see if a volume was modified during the call
|
|
beq @no_write ;no write occurred
|
|
|
|
lda call_number ;the call that was made by application
|
|
pha
|
|
ldx write_dev_num ;push the device number
|
|
phx
|
|
phy ;we do not care about Y
|
|
|
|
lda #volume_change ;this is the event code
|
|
ldx #^volume_change
|
|
jsl post_os_event ;post the event please
|
|
@no_write
|
|
plp ;restore error flag
|
|
pla ;restore error code
|
|
ora error_priority ;put error priority in hi byte 3/5/91 CAE
|
|
|
|
IF debug_on<>0 THEN
|
|
phx ;save X and Y please
|
|
phy
|
|
pha
|
|
php
|
|
jsr debugger
|
|
plp
|
|
pla
|
|
ply
|
|
plx
|
|
|
|
ENDIF
|
|
jml sys_exit
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;Below is the main entry point for ALL FST system calls
|
|
;
|
|
;Input: X = Call number * 2
|
|
; Y = Class number * 2
|
|
; A = undefined
|
|
|
|
EXPORT system_call
|
|
system_call PROC
|
|
import max_sys
|
|
|
|
phk ;setup our bank register
|
|
plb
|
|
|
|
cpx #max_sys+1 ;maximum system calls
|
|
bcs sys_err
|
|
jmp (sys_tbl-2,x) ;call system routine
|
|
|
|
sys_err ;
|
|
lda #bad_system_call
|
|
rtl ;return error to Jim and Mike
|
|
ENDP
|
|
|
|
IF debug_on<>0 THEN
|
|
include 'debugger'
|
|
ENDIF
|
|
|
|
;======================================================================
|
|
;Below are my dispatch tables for application and system calls
|
|
|
|
EXPORT dispatch_tables
|
|
dispatch_tables PROC
|
|
|
|
EXPORT cmd_tbl
|
|
cmd_tbl DC.W create ;create a file call
|
|
DC.W destroy ;delete a file
|
|
DC.W cmd_error
|
|
DC.W change_path ;rename or move a file or subdir
|
|
DC.W set_file_info ;alter directory info on a file
|
|
DC.W get_file_info ;return directory info on a file
|
|
DC.W judge_name ;judge a name
|
|
DC.W volume ;return information on a volume
|
|
DC.W cmd_error ;we don't handle 'Set_Prefix'
|
|
DC.W cmd_error ;we also don't handle 'Get_Prefix'
|
|
DC.W clear_backup ;clear the backup bit on a file
|
|
DC.W cmd_error ;RESERVED
|
|
DC.W cmd_error ;RESERVED
|
|
DC.W cmd_error ;RESERVED
|
|
DC.W cmd_error
|
|
DC.W open ;open a file or subdirectory
|
|
DC.W cmd_error ;we don't handle newline
|
|
DC.W read ;read 'n' bytes from a file
|
|
DC.W write ;write 'n' bytes to a file
|
|
DC.W close ;close a file or subdirectoy
|
|
DC.W flush ;flush a file(s)
|
|
DC.W set_mark ;set a file marker
|
|
DC.W get_mark ;return file marker
|
|
DC.W set_eof ;change EOF of a file
|
|
DC.W get_eof ;return EOF of a file
|
|
DC.W cmd_error ;system call
|
|
DC.W cmd_error ;system call
|
|
DC.W get_dir_entry ;return a entry from a directory
|
|
DC.W cmd_error ;RESERVED
|
|
DC.W cmd_error ;RESERVED
|
|
DC.W cmd_error ;RESERVED
|
|
DC.W get_dev_num ;Get_Dev_Num
|
|
DC.W cmd_error ;GS/OS handles 'Get_Last_Dev'
|
|
DC.W read_block ;read Block only in ProDOS fst
|
|
DC.W write_block ;write Block only in ProDOS fst
|
|
DC.W format_disk ;format media and build directory
|
|
DC.W erase_disk ;build directory structure
|
|
DC.W cmd_error ;reserved
|
|
DC.W cmd_error ;get name
|
|
DC.W cmd_error ;get boot vol
|
|
DC.W cmd_error ;quit
|
|
DC.W cmd_error ;get version
|
|
DC.W cmd_error ;get fst info
|
|
DC.W cmd_error ;device info
|
|
DC.W cmd_error ;device status
|
|
DC.W cmd_error ;device control
|
|
DC.W cmd_error ;device read
|
|
DC.W cmd_error ;device write
|
|
DC.W cmd_error ;alloc int
|
|
DC.W cmd_error ;dealloc int
|
|
DC.W fst_specific ;FST Specific
|
|
EXPORT end_tbl
|
|
end_tbl
|
|
EXPORT Max_call:EQU
|
|
Max_call equ end_tbl-cmd_tbl ;Last valid call I support
|
|
|
|
|
|
EXPORT sys_tbl
|
|
sys_tbl DC.W startup ;set ready for work
|
|
DC.W shutdown ;get ready to quit
|
|
DC.W sys_remove_vol ;remove local data from VCR
|
|
DC.W deferred_flush ;flush deferred blocks.
|
|
EXPORT max_sys:equ
|
|
max_sys equ *-sys_tbl
|
|
ENDP
|
|
|
|
|
|
;
|
|
; 22-Jan-92 MSD: Moved all non-zero items in the data to the start of
|
|
; the proc so that all of the zero bytes would be contiguous. This
|
|
; should help the FST sparsify itself (and reduce disk space).
|
|
;
|
|
|
|
;======================================================================
|
|
;below are virtual pointers returned by GS/OS. Init these to zero
|
|
;on startup
|
|
EXPORT data
|
|
data PROC
|
|
|
|
Export dummy_name
|
|
dummy_name dc.b 'cant.find.me' ;used to calculate the latest mod date
|
|
dc.w 00
|
|
EXPORT time_stamp_opt
|
|
time_stamp_opt DC.W 02 ;0 = files
|
|
; ;1 = files + subdirs
|
|
; ;2 = files + subdirs + subdirs to root
|
|
;
|
|
EXPORT dir_offset_tbl
|
|
dir_offset_tbl DC.W $0004 ;offsets to directory entries within
|
|
DC.W $002b ;a directory block
|
|
DC.W $0052
|
|
DC.W $0079
|
|
DC.W $00A0
|
|
DC.W $00C7
|
|
DC.W $00EE
|
|
DC.W $0115
|
|
DC.W $013C
|
|
DC.W $0163
|
|
DC.W $018A
|
|
DC.W $01B1
|
|
DC.W $01D8
|
|
|
|
export fake_name_str
|
|
fake_name_str DC.W 3 ;fake name string for VCR
|
|
DC.B $C
|
|
DC.B $A
|
|
DC.B $E
|
|
DC.B $00
|
|
|
|
export syntax_str
|
|
syntax_str DC.B end_text-start_text
|
|
start_text DC.B 'ProDOS names must begin with a letter. '
|
|
DC.B 'They may be up to 15 characters long and may contain '
|
|
DC.B 'letters, digits'
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
DC.B ', spaces'
|
|
endif ;end 7-Aug-91 DAL
|
|
DC.B ' and periods.'
|
|
end_text
|
|
|
|
EXPORT format_header
|
|
format_header ;
|
|
DC.W $0000 ;backword link is nill
|
|
DC.W $0003 ;forward link to block three
|
|
EXPORT new_vol_name
|
|
new_vol_name DC.B 00 ;length plus storage type
|
|
DS.B 15 ;fifteen bytes for the name
|
|
DS.B 2 ;eight bytes reserved
|
|
Export new_vol_mod
|
|
new_vol_mod ds.b 4 ;four byte for the Mod time
|
|
ds.b 2 ;2 bytes for the case bits
|
|
EXPORT new_vol_date
|
|
new_vol_date DS.B 4 ;create date for the volume
|
|
DC.B prodos_version
|
|
DC.B 00 ;minimum version (back to SOS 1.0)
|
|
DC.B $C3 ;access
|
|
DC.B $27 ;entry length (39)
|
|
DC.B $0D ;entries per block (13)
|
|
DC.W $0000 ;file count is nill
|
|
DC.W $0006 ;bitmap pointer
|
|
EXPORT new_tot_blks
|
|
new_tot_blks DC.W $0000 ;total number of blocks on the volume
|
|
|
|
EXPORT control_list
|
|
control_list ;partion string
|
|
DC.W $0E ;length increased by 2 7/26/90, see below
|
|
DC.B 'Apple_PRODOS'
|
|
dc.b 0,0 ;terminator nulls added 7/26/90 for compatibility with
|
|
;Macintosh-side FSM, by Matt Gulick, Monte Benaresh
|
|
|
|
Export key_blk_changed
|
|
key_blk_changed dc.w 00 ;used by set EOF to indicate that the file changed structure
|
|
|
|
;======================================================================
|
|
;below is the startup tables for each call. The table contains the
|
|
;following data:
|
|
;
|
|
; 1) Max PCount for the call
|
|
; 2) Max Class for the call
|
|
; 3) Pathnames used by call
|
|
; 4) volume control record used
|
|
; 5) file control record used.
|
|
; 6) io buffer used (data_ptr,Index_ptr,master_ptr)
|
|
; 7) flush file before call
|
|
; 8) damaged disk protect
|
|
; 9) Check Dirty Flag.
|
|
;
|
|
; |9|8|7|6|5|4|3| 2 | 1 |
|
|
; _|_|_|_|_|_|_|_|_____|_________|
|
|
; | | | | | | | | | | | | | | | | |
|
|
; |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
|
|
; | | |
|
|
; 1 6 0 8 0 0
|
|
|
|
|
|
EXPORT start_tbl
|
|
start_tbl
|
|
DC.W max_pcnt7+max_class1+path_used+damage ;Create
|
|
DC.W max_pcnt1+max_class1+path_used+damage ;Destroy
|
|
DC.W 0000
|
|
DC.W max_pcnt3+max_class1+path_used+damage ;ChangePath
|
|
; set max pCount=3 (5-Dec-91 MSD)
|
|
DC.W max_pcnt12+max_class1+path_used+damage ;SetFileInfo
|
|
DC.W max_pcnt12+max_class1+path_used ;GetFileInfo
|
|
DC.W max_pcnt6+max_class1 ;JudgeName
|
|
DC.W max_pcnt6+max_class1 ;Volume
|
|
DC.W 0000
|
|
DC.W 0000
|
|
DC.W max_pcnt1+max_class1+path_used+damage ;ClearBackup
|
|
DC.W 0000
|
|
DC.W 0000
|
|
DC.W 0000
|
|
DC.W 0000
|
|
DC.W max_pcnt15+max_class1+path_used ;Open
|
|
DC.W 0000
|
|
DC.W max_pcnt5+max_class1+vcr_used+fcr_used+io_used ;Read
|
|
DC.W max_pcnt5+max_class1+vcr_used+fcr_used+io_used+damage+do_dirty ;Write
|
|
DC.W max_pcnt1+max_class1+vcr_used+fcr_used+io_used ;Close
|
|
DC.W max_pcnt2+max_class1+vcr_used+fcr_used+io_used+damage ;Flush
|
|
DC.W max_pcnt4+max_class1+vcr_used+fcr_used+io_used ;SetMark
|
|
DC.W max_pcnt2+max_class1+fcr_used ;GetMark
|
|
DC.W max_pcnt3+max_class1+vcr_used+fcr_used+flush_1st+io_used+damage+do_dirty ;SetEof
|
|
DC.W max_pcnt2+max_class1+fcr_used ;GetEof
|
|
DC.W 0000
|
|
DC.W 0000
|
|
DC.W max_pcnt17+max_class1+vcr_used+fcr_used+io_used ;GetDirEntry
|
|
DC.W 0000
|
|
DC.W 0000
|
|
DC.W 0000
|
|
DC.W max_pcnt2+max_class1+path_used ;GetDevNum
|
|
DC.W 0000
|
|
DC.W 0000 ;ReadBlock
|
|
DC.W 0000 ;WriteBlock
|
|
DC.W max_pcnt6+max_class1+path_used ;Format
|
|
DC.W max_pcnt6+max_class1+path_used ;Erase
|
|
|
|
EXPORT gbuf_addr
|
|
gbuf_addr DC.L 0 ;pointer to general I/O buffer
|
|
EXPORT virtual
|
|
virtual DC.L 0 ;pointer to virtual memory after
|
|
; ;a call to 'Get_Segment'
|
|
EXPORT virtual2
|
|
virtual2 DC.L 00
|
|
|
|
;======================================================================
|
|
;data storage used
|
|
EXPORT hours
|
|
hours DC.W 00
|
|
EXPORT minutes
|
|
minutes DC.W 00
|
|
EXPORT year
|
|
year DC.W 00
|
|
EXPORT month
|
|
month DC.W 00
|
|
EXPORT day
|
|
day DC.W 00
|
|
EXPORT day_of_week
|
|
day_of_week DC.W 00
|
|
EXPORT pro_time
|
|
pro_time DC.L 00
|
|
|
|
Export write_occurred
|
|
write_occurred dc.w 00 ;IF non-zero on exit then a write occurred
|
|
Export write_dev_num ;device number that was written too
|
|
write_dev_num dc.w 00
|
|
|
|
Export curr_mod_date
|
|
curr_mod_date dc.l 00
|
|
|
|
Export case_bits ;case bits for the last pathname
|
|
case_bits dc.w 00
|
|
Export case_bit_pattern
|
|
case_bit_pattern dc.w 00
|
|
|
|
EXPORT src_dev_num
|
|
src_dev_num DC.W 00 ;used by change path
|
|
EXPORT src_start_blk
|
|
src_start_blk DC.W 00 ;''
|
|
EXPORT src_dir_blk
|
|
src_dir_blk DC.W 00 ;''
|
|
EXPORT src_offset
|
|
src_offset DC.W 00
|
|
|
|
EXPORT slug_block
|
|
slug_block DC.W 00 ;for slug ripple 'to root time stamp'
|
|
EXPORT slug_offset
|
|
slug_offset DC.W 00
|
|
EXPORT close_flag
|
|
close_flag DC.W 00 ;used to determine if we should call
|
|
; ;slug_ripple from flush_file
|
|
;
|
|
EXPORT src_slug_blk
|
|
src_slug_blk DC.W 00 ;used by change_path
|
|
EXPORT src_slug_offset
|
|
src_slug_offset DC.W 00
|
|
EXPORT dest_slug_blk
|
|
dest_slug_blk DC.W 00
|
|
EXPORT dest_slug_offset
|
|
dest_slug_offset DC.W 00
|
|
|
|
|
|
EXPORT dest_dev_num
|
|
dest_dev_num DC.W 00 ;used by change path
|
|
EXPORT dest_start_blk
|
|
dest_start_blk DC.W 00 ;''
|
|
EXPORT dest_dir_blk
|
|
dest_dir_blk DC.W 00 ;''
|
|
EXPORT dest_offset
|
|
dest_offset DC.W 00
|
|
EXPORT vol_rename_flag
|
|
vol_rename_flag DC.W 00 ;''
|
|
|
|
EXPORT direct_page
|
|
direct_page DS.B $4C ;used when we must mount a volume
|
|
EXPORT my_direct
|
|
my_direct DS.B $78 ;''
|
|
EXPORT world_flag
|
|
world_flag DC.W 00 ;detect re-entrent code
|
|
|
|
EXPORT def_dir_page
|
|
def_dir_page DS.B $4C ;used when we flush deferred blocks
|
|
EXPORT def_my_direct
|
|
def_my_direct DS.B $78 ;''
|
|
EXPORT def_vol_name
|
|
def_vol_name DS.B 20
|
|
EXPORT alloc_chk_flag
|
|
alloc_chk_flag DC.W 00 ;used by write routine
|
|
EXPORT seq_write_start
|
|
seq_write_start DC.L 00 ;pointer used by write routine
|
|
EXPORT seq_write_cnt
|
|
seq_write_cnt DC.W 00 ;sequential block counter
|
|
EXPORT seq_write_blk
|
|
seq_write_blk DC.W 00 ;starting block for sequential write
|
|
|
|
EXPORT path_searched
|
|
path_searched DC.W 00 ;set by find file.
|
|
;
|
|
EXPORT last_blk
|
|
last_blk DC.W 0 ;used by find_file to verify
|
|
; ;directory structure
|
|
;
|
|
;
|
|
EXPORT search_flag
|
|
search_flag DC.W 00 ;flag used by process path
|
|
; ; bit 15 = volume name not allowed
|
|
; ; bit 14 = search for new entry
|
|
; ; bit 13 = volume only allowed
|
|
;
|
|
EXPORT dir_start_blk
|
|
dir_start_blk DC.W 00 ;starting block of a directory
|
|
EXPORT dir_last_blk
|
|
dir_last_blk DC.W 00 ;last block read by find file
|
|
EXPORT free_dir_blk
|
|
free_dir_blk DC.W 00 ;1st dir block with a free entry
|
|
EXPORT free_dir_offset
|
|
free_dir_offset DC.W 00 ;offset to free entry in dir block
|
|
EXPORT searching_free
|
|
searching_free DC.W 00 ;flag that is used by Find_File
|
|
|
|
EXPORT blks_used1
|
|
blks_used1 DC.W 00 ;blks needed for data fork. (create)
|
|
EXPORT blks_used2
|
|
blks_used2 DC.W 00 ;blks needed for res. fork. (create)
|
|
EXPORT blocks_needed
|
|
blocks_needed DC.W 00 ;total blocks needed for files. (create)
|
|
EXPORT data_storage
|
|
data_storage DC.W 00 ;storage type for data fork
|
|
EXPORT res_storage
|
|
res_storage DC.W 00 ;storage type for resource fork
|
|
EXPORT res_tot_blks
|
|
res_tot_blks DC.W 00 ;used by create
|
|
EXPORT res_key_blk
|
|
res_key_blk DC.W 00 ;''
|
|
EXPORT some_free
|
|
some_free DC.W 00 ;used by find_free_blks
|
|
|
|
EXPORT volume_name
|
|
volume_name DS.B 20 ;holds the volume name of an input str
|
|
EXPORT gstring
|
|
gstring DS.B 20 ;holds gstrings
|
|
|
|
EXPORT search_length
|
|
search_length DC.W 00 ;used by 'find_file' routine
|
|
EXPORT search_name
|
|
search_name DS.B 17
|
|
|
|
|
|
EXPORT fcr_wanted
|
|
fcr_wanted DC.W 00 ;used by check_dup routine
|
|
EXPORT key_block
|
|
key_block DC.W 00 ;used by check_dup routine
|
|
|
|
EXPORT find_this_entry
|
|
find_this_entry DC.W 00 ;used by get dir entry
|
|
|
|
EXPORT entry_sto_type
|
|
entry_sto_type DC.W 00
|
|
EXPORT storage_type
|
|
storage_type DC.W 00 ;used by open
|
|
EXPORT alloc_entry
|
|
alloc_entry DC.B 00 ;used to give entry name a length word
|
|
EXPORT one_entry
|
|
one_entry DS.B 40 ;holds one directory entry
|
|
EXPORT files_key_block
|
|
files_key_block DC.W 00 ;used by open
|
|
|
|
EXPORT hold_path_ptr
|
|
hold_path_ptr DC.W 00
|
|
|
|
EXPORT data_eof
|
|
data_eof DC.L 00 ;used by create
|
|
EXPORT res_eof
|
|
res_eof DC.L 00 ;used by create
|
|
EXPORT tree_key_blk
|
|
tree_key_blk DC.W 00 ;used by create
|
|
EXPORT tree_blks
|
|
tree_blks DC.W 00 ;used by create
|
|
|
|
EXPORT parent_blk
|
|
parent_blk DC.W 00 ;used by the open routine
|
|
EXPORT entry_offset
|
|
entry_offset DC.W 00 ;used by the open routine
|
|
|
|
EXPORT num_of_res
|
|
num_of_res DC.W 00 ;used by open
|
|
|
|
EXPORT newline_len
|
|
newline_len DC.W 00
|
|
EXPORT newline_mask
|
|
newline_mask DC.W 00
|
|
EXPORT newline_char
|
|
newline_char DC.W 00
|
|
|
|
EXPORT base
|
|
base DC.W 00 ;used with calls that have base param
|
|
EXPORT displacement
|
|
displacement DC.L 00 ;used with calls that have displacement
|
|
|
|
EXPORT purge_addr
|
|
purge_addr DC.W 00 ;block address of purgable files
|
|
EXPORT new_last
|
|
new_last DC.W 00 ;used to cut back eof (SET_EOF)
|
|
|
|
EXPORT bitmap_blks
|
|
bitmap_blks DC.W 00 ;used to calc_free_blks
|
|
EXPORT last_bitmap
|
|
last_bitmap DC.W 00 ;'' ''
|
|
EXPORT first_free
|
|
first_free DC.W 00 ;'' ''
|
|
EXPORT bits
|
|
bits DC.W 00 ;used to count bits in calc_free_blks
|
|
EXPORT alloc_count
|
|
alloc_count DC.W 00 ;used by find_free_blks
|
|
EXPORT alloc_start
|
|
alloc_start DC.W 00 ;''
|
|
EXPORT byte_offset
|
|
byte_offset DC.W 00 ;''
|
|
|
|
EXPORT mark_changed
|
|
mark_changed DC.W 00 ;used by fill_io_buf (setmark=EOF case)
|
|
EXPORT user_cache
|
|
user_cache DC.W 00 ;default cache value for file reads
|
|
|
|
EXPORT create_time
|
|
create_time DC.L 00 ;used by set_file_info
|
|
EXPORT mod_time
|
|
mod_time DC.L 00 ;used by set_file_info
|
|
|
|
EXPORT first_free_bm
|
|
first_free_bm DC.W 00
|
|
|
|
EXPORT index_blks
|
|
index_blks DC.W 00 ;number of indexes needed for tree files
|
|
EXPORT data_indexes
|
|
data_indexes DC.W 00 ;used by create
|
|
EXPORT res_indexes
|
|
res_indexes DC.W 00 ;used by create.
|
|
|
|
EXPORT entries_blk_num
|
|
entries_blk_num DC.W 00
|
|
EXPORT files_examined
|
|
files_examined DC.W 00
|
|
EXPORT files_in_dir
|
|
files_in_dir DC.W 00
|
|
EXPORT pcount
|
|
pcount DC.W 00
|
|
EXPORT resource_num
|
|
resource_num DC.W 00
|
|
EXPORT access
|
|
access DC.W 00
|
|
EXPORT and_mask
|
|
and_mask DC.W 00
|
|
EXPORT curr_mark
|
|
curr_mark DC.L 00
|
|
EXPORT curr_eof
|
|
curr_eof DC.L 00
|
|
EXPORT tran_cnt
|
|
tran_cnt DC.L 00
|
|
EXPORT user_req_cnt
|
|
user_req_cnt DC.L 00
|
|
EXPORT entries_checked
|
|
entries_checked DC.W 00
|
|
EXPORT chars_checked
|
|
chars_checked DC.W 00
|
|
EXPORT name_length
|
|
name_length DC.W 00
|
|
EXPORT flush_entry
|
|
flush_entry dc.w 00 ;allows us to flush only the I/O buffer
|
|
EXPORT Users_access
|
|
users_access dc.w 00 ;used during the open call
|
|
|
|
Export dirty_flags ;flags at the beginning of the call
|
|
dirty_flags dc.w 00
|
|
Export flush_flags
|
|
flush_flags dc.w 00 ;used by the flush routines
|
|
|
|
export chk_dirty_flag ;flag used to indicate that the call can cause dirty blocks
|
|
chk_dirty_flag dc.w 00
|
|
export dirty_cnt_changed
|
|
dirty_cnt_changed dc.w 00 ;indicates that we have changed the dirty_cnt once
|
|
|
|
export new_eof
|
|
new_eof dc.l 00 ;used by set EOF
|
|
|
|
export cp_device_flag
|
|
cp_device_flag DC.W 00 ;1 = ChangePath using device name, else 0
|
|
|
|
export cp_flags ;Added 5-Dec-91 MSD
|
|
cp_flags DC.W 00 ;$8000 = assume source is duplicate volume
|
|
|
|
export cp_to_child ; non-zero if ChangePath trying to move an item
|
|
cp_to_child dc.w 00 ; into its own child (i.e. :A:B to :A:B:C).
|
|
|
|
export hfs_flag
|
|
hfs_flag DC.W 00 ;1 = we have HFS Finder Info, else 0
|
|
|
|
export hfs_finfo
|
|
hfs_finfo DS.B 32 ;storage area for HFS Finder Info
|
|
|
|
export error_priority
|
|
error_priority DC.W 00 ;storage for error priority
|
|
|
|
|
|
;======================================================================
|
|
;Data used by Format and Erase disk calls
|
|
|
|
EXPORT format_ctrl
|
|
format_ctrl DC.W 00 ;length of control list
|
|
|
|
EXPORT status_list
|
|
status_list DC.W 00 ;status code
|
|
EXPORT return_blks
|
|
return_blks DC.L 00000 ;number of blocks on device
|
|
|
|
EXPORT entries_offset
|
|
entries_offset dc.w 00 ;offset to directory entry
|
|
export gde_temp
|
|
gde_temp dc.w 00 ; temp used by GetDirEntry
|
|
|
|
;driver save area
|
|
|
|
EXPORT drvr_save
|
|
drvr_save DS.B $1b ;save room for direct page
|
|
|
|
;equates used by 'setup_params'
|
|
|
|
EXPORT class
|
|
class DC.W 00
|
|
EXPORT max_pcount
|
|
max_pcount DC.W 00
|
|
EXPORT flags
|
|
flags DC.W 00
|
|
|
|
*** added 28-Feb-92 DAL
|
|
;
|
|
; Used by chk_disk_protect to save the first 512 bytes of GBUF
|
|
;
|
|
export chk_protect_gbuf
|
|
chk_protect_gbuf ds.b 512
|
|
*** end 28-Feb-92 DAL
|
|
|
|
ENDP
|
|
|
|
expand_record Record
|
|
expand_flag dc.w 00
|
|
expand_file dc.w 00 ;used to indicate we are extending a file
|
|
expand_storage dc.w 00 ;storage type of the data fork on extension
|
|
expand_key_blk dc.w 00
|
|
expand_blks_used dc.w 00
|
|
expand_eof dc.l 00
|
|
|
|
endr
|
|
|
|
;==========================================================================
|
|
; Prodos universal boot loader. This is the second stage boot
|
|
; for all apple manufactured Apple II disk drives.
|
|
; It is located at block zero (0) of a ProDOS formatted disk(ette).
|
|
; Support for Apple /// has been removed to save space.
|
|
;
|
|
;Rev History:
|
|
;
|
|
;Jan 12, 1988 By Rob Turner
|
|
;
|
|
; Removed Apple /// (SOS) support and converted source to APW
|
|
;
|
|
;Jun 02, 1988 By Rob Turner
|
|
;
|
|
; Changed the boot code to handle a sparse ProDOS file.
|
|
;
|
|
;==========================================================================
|
|
|
|
boot_code_start proc
|
|
endp
|
|
|
|
msb off
|
|
longa off
|
|
longi off
|
|
MACHINE M6502
|
|
|
|
EXPORT boot_code
|
|
boot_code PROC temporg $000800
|
|
|
|
dcmd equ $42 ;disk command (=1 for read)
|
|
unit equ $43 ;(16*slot)+(128*(drive-1))
|
|
buff equ $44 ;ram address
|
|
blok equ $46 ;disk address
|
|
|
|
dent equ $48 ;device call entry address.
|
|
idxl equ $4a ;pointer to low page of index block
|
|
idxh equ $4c ;pointer to high page of index block
|
|
idxp equ $4e ;index byte pointer.
|
|
iobuff equ $60
|
|
|
|
; the following are for disk ii only:
|
|
|
|
dbuf equ $26
|
|
slotz equ $2b
|
|
oddbits equ $3c
|
|
sector equ $3d
|
|
trktmp equ $40
|
|
track equ $41
|
|
prior equ $50
|
|
trkn equ $51
|
|
rtrycnt equ $52
|
|
curtrk equ $53
|
|
trkcnt equ $54
|
|
*
|
|
q6l equ $c08c
|
|
motoron equ $c089
|
|
motoroff equ $c088
|
|
phaseoff equ $c080
|
|
nbuf1 equ $300
|
|
dnib equ $2d6
|
|
|
|
* directory dependent stuff...
|
|
|
|
clrscrn equ $fc58
|
|
scrn equ $5b1 ;5ae
|
|
dostyp equ $ff
|
|
sosid equ $c00
|
|
entlen equ sosid+$23
|
|
kernel equ $2000
|
|
|
|
|
|
zzstart equ $09F2
|
|
rd1 equ $09F2
|
|
rd1a equ $09F7
|
|
mod1 equ $0008
|
|
chg1 equ $FFF4
|
|
rd2 equ $09FB
|
|
rd3 equ $0A05
|
|
mod2 equ $001E
|
|
chg2 equ $FFD7
|
|
mod3 equ $0024
|
|
rdhd0 equ $0A15
|
|
chg3 equ $FFD1
|
|
rdhd1 equ $0A17
|
|
rdhd2 equ $0A19
|
|
rdhd3 equ $0A1B
|
|
rdhd4 equ $0A23
|
|
mod4 equ $003F
|
|
chg4 equ $FFB6
|
|
mod5 equ $0045
|
|
chg5a equ $0A38
|
|
mod6 equ $0047
|
|
chg6 equ $FFB4
|
|
rddt1 equ $0A3A
|
|
rddt1a equ $0A3C
|
|
rddt2 equ $0A3E
|
|
rddt3 equ $0A4E
|
|
rddt4 equ $0A50
|
|
rdchk equ $0A5F
|
|
mod7 equ $0076
|
|
chg7 equ $FFAC
|
|
nxttwo equ $0A6B
|
|
twobit equ $0A6D
|
|
zzzend equ $0A7F
|
|
chg5 equ $004B
|
|
goseek equ $0A83
|
|
|
|
|
|
;==========================================================================
|
|
;Main Entry Point For Booting Apple II Computer.
|
|
;==========================================================================
|
|
|
|
xboot DC.B $01 ;(prodos boot id)
|
|
entry sec ;(apple iii enters xboot 'ora $38')
|
|
bcs entry1 ;branch if not apple iii native mode.
|
|
jmp booterr ;Apple /// Boot.
|
|
|
|
entry1 sei ;disable interupts so we can boot on the IIGS with debugger
|
|
stx unit ;save unit number.
|
|
cmp #$03 ;for disk ii.
|
|
php ;save result, it may be irrelevent.
|
|
txa ;find out if disk ii.
|
|
and #$70 ;strip drive # if any.
|
|
lsr a
|
|
lsr a ;get slot address.
|
|
lsr a
|
|
lsr a
|
|
ora #$c0
|
|
sta dent+1
|
|
ldy #$ff ;look at last byte.
|
|
sty dent
|
|
plp ;restore carry (if disk ii & sect 0&2 read carry set).
|
|
iny ;make y=0
|
|
lda (dent),y ;get device entry addr.
|
|
bne ndsk2 ;branch if not disk ii (16 sector).
|
|
bcs isdsk2 ;branch if it is disk ii, but block 0 read.
|
|
lda #3 ;make rom read only sector 2
|
|
sta xboot ;to complete block 0
|
|
inc sector ;(was = 1)
|
|
lda dent+1 ;do rts to re-enter rom.
|
|
pha
|
|
lda #$5b
|
|
pha
|
|
rts ;go read sector 2 into $900.
|
|
|
|
isdsk2 sta trktmp ;make sure previous track =0
|
|
sta dent ;and dent points at beginning of slot
|
|
ldy #$5e ;move code from card to ram
|
|
mvboot lda (dent),y
|
|
sta zzstart-$5e,y
|
|
iny
|
|
cpy #$eb ;have we moved enough?
|
|
bne mvboot
|
|
ldx #6 ;now modify code to handle errors.
|
|
modboot ldy mods,x
|
|
lda chgs,x
|
|
sta zzstart,y
|
|
lda endcode,x
|
|
sta zzzend,x
|
|
dex
|
|
bpl modboot
|
|
lda #>d2io ;reset device entry
|
|
sta dent+1 ; to point at disk ii routines.
|
|
lda #<d2io ;get low addr (must be <$80)
|
|
ndsk2 ldy #0 ;make sure y=0 again.
|
|
cmp #$f9
|
|
bcs bterr1 ;branch if not bootable device.
|
|
sta dent ;save low adr of device call entry.
|
|
sty iobuff
|
|
sty idxl
|
|
sty idxh ;(y=0)
|
|
sty idxp
|
|
sty blok+1
|
|
iny
|
|
sty dcmd ;set read command.
|
|
iny
|
|
sty blok ; to read directory blocks
|
|
lda #$c ; 2-5 at $c00
|
|
sta iobuff+1
|
|
sta idxl+1
|
|
|
|
rddir jsr goread ;call read block routine.
|
|
bcs bterr2 ;give up on error.
|
|
inc iobuff+1
|
|
inc iobuff+1
|
|
inc blok
|
|
lda blok ;have all directory blocks been read?
|
|
cmp #6
|
|
bcc rddir ;loop if not.
|
|
|
|
lda sosid ;is it a prodos (sos) directory?
|
|
ora sosid+1
|
|
bterr1 bne bterr2 ;booterr ;branch if not.
|
|
lda #4 ;begin look-up with first entry past header.
|
|
bne nxdent1 ;branch always
|
|
nxdent lda idxl
|
|
nxdent1 clc
|
|
adc entlen ;bump to next directory entry.
|
|
tay ;save in y for now.
|
|
bcc nxdent2 ;branch if not a page cross.
|
|
inc idxl+1
|
|
lda idxl+1 ;check for new block.
|
|
lsr a ;if even then new block.
|
|
bcs nxdent2
|
|
cmp #$a ;have all file names been compared?
|
|
beq nopro ;branch if no pro.kernel.
|
|
ldy #4 ;else, begin at block beginning.
|
|
nxdent2 sty idxl ;note: this method treats garbage at
|
|
lda sysname ; the end of the dir block as an entry.
|
|
and #$f ;get target name length.
|
|
tay
|
|
lookpro lda (idxl),y ;look for matching name.
|
|
cmp sysname,y ;last to first method.
|
|
bne nxdent ;branch if no match.
|
|
dey ;else check all characters.
|
|
bpl lookpro ;including length/storage type.
|
|
|
|
ldy #$16 ;convert eof to blks.
|
|
lda (idxl),y
|
|
lsr a ;convert to blocks
|
|
adc blk_count
|
|
sta blk_count
|
|
|
|
; ldy #$10 ;get file type & index block addr.
|
|
; lda (idxl),y
|
|
; cmp #dostyp ;is it a system file?
|
|
; bne booterr
|
|
; iny
|
|
|
|
ldy #$11 ;starting block of the file
|
|
lda (idxl),y
|
|
sta blok
|
|
iny
|
|
lda (idxl),y
|
|
sta blok+1
|
|
lda #0 ;now set up to read kernel.
|
|
sta idxl
|
|
ldy #$1e ;read index block at $1e00 and
|
|
sty idxl+1 ; kernel at $2000
|
|
sty iobuff+1
|
|
iny
|
|
sty idxh+1
|
|
rdkernl jsr goread ;read index block.
|
|
bterr2 bcs booterr
|
|
|
|
inc iobuff+1 ;setup pointer for the next block please
|
|
inc iobuff+1
|
|
@sparse_return
|
|
ldy idxp ;get index pointer
|
|
inc idxp ;bump for next time.
|
|
|
|
lda (idxl),y
|
|
sta blok
|
|
lda (idxh),y ;high disk addr.
|
|
sta blok+1
|
|
ora (idxl),y ;if both=0 then done. (This was changed to handle sparse)
|
|
bne not_sparse
|
|
|
|
ldx #$01
|
|
lda #$00 ;clear the block please
|
|
tay
|
|
@1 sta (ioBuff),y
|
|
iny
|
|
bne @1 ;clear the low page
|
|
inc ioBuff+1 ;bump to the next page
|
|
nop
|
|
nop ;keep things aligned please
|
|
dex
|
|
bpl @1 ;clear the high page
|
|
dec blk_count
|
|
beq go_kernel
|
|
bne @sparse_return
|
|
not_sparse
|
|
dec blk_count ;are we done yet
|
|
bne rdkernl ;branch if more to read.
|
|
go_kernel
|
|
cli ;enable interupts before calling ProDOS
|
|
jmp kernel ;go execute kernel code.
|
|
|
|
nopro equ *
|
|
booterr equ *
|
|
jmp quitmes
|
|
|
|
blk_count dc.b 02
|
|
msb off
|
|
sysname DC.B $26
|
|
DC.B 'PRODOS'
|
|
|
|
goread lda iobuff
|
|
sta buff
|
|
lda iobuff+1
|
|
sta buff+1
|
|
jmp (dent)
|
|
*
|
|
mods DC.B mod1,mod2,mod3,mod4
|
|
DC.B mod5,mod6,mod7
|
|
*
|
|
chgs DC.B chg1**$FF,chg2**$FF,chg3**$FF,chg4**$FF
|
|
DC.B chg5**$FF,chg6**$FF,chg7**$FF
|
|
*
|
|
|
|
endcode equ *
|
|
ldx slotz
|
|
clc
|
|
rts
|
|
jmp seek
|
|
*
|
|
quitmes jsr clrscrn ;clear video.
|
|
ldy #meslen ;print message centered on screen.
|
|
prmess lda errmess,y
|
|
sta scrn,y
|
|
dey
|
|
bpl prmess
|
|
hang jmp hang
|
|
*
|
|
msb on
|
|
meslen equ 20
|
|
errmess DC.B 'UNABLE TO LOAD PRODOS'
|
|
|
|
|
|
********************************************************************************
|
|
* This code MUST be aligned to $16D ($96D Absolute) relative address. Otherwise
|
|
* disk][s will not work. This is a major pain in the butt.
|
|
********************************************************************************
|
|
|
|
setphase lda curtrk ;get current track
|
|
clrphase and #3 ;mask for 1 of 4 phases
|
|
rol a ;double for phaseon/off index
|
|
ora slotz
|
|
tax
|
|
lda phaseoff,x ;turn on/off one phase
|
|
lda #$2c
|
|
**************************
|
|
* *
|
|
* mswait subroutine *
|
|
* *
|
|
**************************
|
|
mswait ldx #$11
|
|
msw1 dex ;delay 86 usec.
|
|
bne msw1
|
|
sbc #$1 ;done 'n' intervals?
|
|
bne mswait ;(a-reg counts)
|
|
ldx slotz ;restore x-reg
|
|
rts
|
|
*
|
|
*
|
|
d2io lda blok ;figure out track & sector.
|
|
and #7 ;strip track for now.
|
|
cmp #4
|
|
and #3
|
|
php
|
|
asl a
|
|
plp
|
|
rol a ;now we have the first sector of block.
|
|
sta sector
|
|
lda blok+1 ;get high block #
|
|
lsr a ;shift hi addr to carry.
|
|
lda blok ;now figure track #
|
|
ror a
|
|
lsr a
|
|
lsr a
|
|
sta track
|
|
asl a
|
|
sta trkn
|
|
lda buff+1
|
|
sta dbuf+1
|
|
ldx slotz
|
|
lda motoron,x
|
|
jsr rdsector ;go read sector.
|
|
inc dbuf+1 ;bump address
|
|
inc sector
|
|
inc sector ;and sector #
|
|
bcs quitrd ;branch if error.
|
|
jsr rdsector
|
|
quitrd ldy motoroff,x
|
|
erretrn rts ;return error status in carry.
|
|
*
|
|
rdsector equ * ;do seek then read sector.
|
|
*
|
|
seek lda trktmp ;get track we're on.
|
|
asl a
|
|
sta curtrk
|
|
lda #$0
|
|
sta trkcnt ;halftrack count.
|
|
seek2 lda curtrk ;save curtrk for
|
|
sta prior ;delayed turnoff.
|
|
sec
|
|
sbc trkn ;delta-tracks.
|
|
beq seekend ;br if curtrk=destination
|
|
bcs out ;(move out, not in)
|
|
inc curtrk ;incr current track (in).
|
|
bcc skin ;(always taken)
|
|
out dec curtrk ;decr current track (out).
|
|
skin sec
|
|
step2 jsr setphase
|
|
lda prior
|
|
clc ;for phaseoff
|
|
jsr clrphase ;de-energize previous phase.
|
|
bne seek2 ;(always taken)
|
|
seekend equ *
|
|
*
|
|
rdsect1 ldy #$7f ;allow 127 mistakes.
|
|
sty rtrycnt
|
|
php
|
|
*
|
|
tryread plp ;fix stack.
|
|
|
|
rdhead sec ;anticipate error.
|
|
dec rtrycnt ;if = 0 then give up!
|
|
beq erretrn ;branch if can't fine/read sector.
|
|
clc ;indicate reading header.
|
|
rddata php ;carry set if reading sector.
|
|
rd0 dey ;every time y=0 decrement find count.
|
|
beq tryread
|
|
|
|
MACHINE M65816 ;start using 65816 code again
|
|
msb off
|
|
longa on
|
|
longi on
|
|
|
|
export boot_size:equ ;export the equate for Max
|
|
boot_size equ *-xboot
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;Pack_Time: This routine will read the time from the GS Clock and
|
|
; convert it to packed ProDOS disk format
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..0
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = low word of time
|
|
; Y = High word of time
|
|
;
|
|
; time is also stored at Pro_Time and Pro_Time+2
|
|
;
|
|
;Format of time:
|
|
;
|
|
; |<-------- X Register --------->|<-------- Y Register --------->|
|
|
; | | |
|
|
; |<--high Byte-->|<--low Byte-->|<--high Byte-->|<--low Byte-->|
|
|
; _______________________________________________________________
|
|
; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
|
; | year | month | day |0 0 0| hour |0 0| minute |
|
|
; |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
|
|
;
|
|
;
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: all register
|
|
; get_time (Subroutine that reads time)
|
|
; hours,minutes (data words)
|
|
; year,month,day
|
|
;
|
|
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT pack_time
|
|
pack_time PROC
|
|
|
|
stz pro_time
|
|
stz pro_time+2
|
|
|
|
jsr get_time ;read the time from tool set
|
|
|
|
;We call this entry point if the time parameters are setup and need
|
|
;only to be convert to the ProDOS format.
|
|
|
|
EXPORT convert_time
|
|
convert_time
|
|
lda day
|
|
sta pro_time ;save the day in prodos format
|
|
lda month
|
|
asl a
|
|
asl a
|
|
asl a
|
|
asl a
|
|
asl a ;shift to correct position
|
|
ora pro_time ;month is now happy
|
|
sta pro_time
|
|
lda year
|
|
|
|
; 27-Jan-92 MSD: Years outside the range 1940..2039 will be converted
|
|
; to "unknown" (i.e. all zeroes).
|
|
cmp #40 ; less than 1940?
|
|
blt @bad_year
|
|
cmp #140 ; 2040 or greater?
|
|
bge @bad_year
|
|
cmp #100 ; 2000..2039?
|
|
blt @got_year ; no, so leave as is
|
|
sbc #100 ; convert 2000..2039 to 0..39
|
|
@got_year
|
|
; End 27-Jan-92 MSD
|
|
|
|
xba
|
|
asl a ;shift year to upper 7 bits
|
|
ora pro_time
|
|
sta pro_time
|
|
tax ;return in X register too
|
|
lda minutes
|
|
sta pro_time+2
|
|
lda hours
|
|
xba
|
|
ora pro_time+2
|
|
sta pro_time+2
|
|
tay ;return in Y register
|
|
clc ; 27-Jan-92 MSD: valid date/time
|
|
rts
|
|
|
|
@bad_year ; year was bad, set date/time
|
|
ldx #0 ; to "unknown" (all zeroes).
|
|
txy
|
|
stx pro_time
|
|
sty pro_time+2
|
|
sec ; 27-Jan-92 MSD: invalid date/time
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;unpack_time: This routine will unpack a prodos time into a GS/OS time.
|
|
;
|
|
;Input: A = undefined
|
|
;
|
|
;Format of time:
|
|
;
|
|
; |<-------- X Register --------->|<-------- Y Register --------->|
|
|
; | | |
|
|
; |<--high Byte-->|<--low Byte-->|<--high Byte-->|<--low Byte-->|
|
|
; _______________________________________________________________
|
|
; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
|
; | year | month | day |x x x| hour |x x| minute |
|
|
; |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
|
|
;
|
|
; P = nvmxdizc
|
|
; ..000..0
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
; hours (Times are all hex format)
|
|
; minutes
|
|
; year
|
|
; month
|
|
; day
|
|
; day_of_week
|
|
;
|
|
;Uses: all register
|
|
; dow_convert (Subroutine)
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT unpack_time
|
|
unpack_time PROC
|
|
|
|
stx pro_time
|
|
sty pro_time+2
|
|
|
|
;Init time to zero (unknown)
|
|
|
|
jsr zero_date
|
|
|
|
txa
|
|
ora pro_time+2
|
|
beq end_unpack
|
|
|
|
lda pro_time
|
|
and #$001F ;isolate day
|
|
sta day
|
|
cmp #32 ;valid days are 01 to 31
|
|
bcs zero_date ;sorry bud you get unknown
|
|
|
|
tay ;save for DOW convert
|
|
txa ;get year/month/day again (X is still valid here)
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
and #$000F ;isolate month
|
|
sta month
|
|
cmp #13 ;is the month 13 or >?
|
|
bcs zero_date
|
|
|
|
tax
|
|
lda pro_time
|
|
xba
|
|
lsr a
|
|
and #$007F ;isolate the year
|
|
cmp #40 ;year = 40-99?
|
|
bcs @store_it ;yes, must be 1940-1999
|
|
adc #100 ;else must be 2000-2039, adjust
|
|
@store_it
|
|
sta year
|
|
jsr dow_convert ;go ahead and calculate the day of week
|
|
sta day_of_week
|
|
lda pro_time+2
|
|
and #$003F ;isolate minutes
|
|
sta minutes
|
|
cmp #60
|
|
bcs zero_date
|
|
|
|
lda pro_time+2
|
|
xba
|
|
and #$001F ;isolate hours
|
|
sta hours
|
|
cmp #24
|
|
bcc end_unpack
|
|
|
|
zero_date ;indicate that the date is unknown
|
|
stz hours
|
|
stz minutes
|
|
stz year
|
|
stz month
|
|
stz day
|
|
stz day_of_week
|
|
end_unpack rts
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;DOW_Convert:This routine convert Month,Day,Year into day of week
|
|
;
|
|
;Input: A = Year
|
|
; X = Month
|
|
; Y = Day
|
|
; P = saved
|
|
; b = k
|
|
;
|
|
;Output: A = day of week
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = restored
|
|
; b = k
|
|
;
|
|
;Uses: all register
|
|
; local temps
|
|
;
|
|
longa off
|
|
longi off
|
|
|
|
EXPORT dow_convert
|
|
dow_convert PROC
|
|
php
|
|
sep #$30
|
|
phy
|
|
tay
|
|
|
|
;Figure the number of leap years since 1900
|
|
|
|
lsr a
|
|
lsr a
|
|
sta dow_temp
|
|
|
|
;If it's a leap year and it's Jan or Feb subtract 1 from the total
|
|
|
|
tya ;get the year back
|
|
and #%00000011
|
|
bne stim015
|
|
cpx #03
|
|
bcs stim015
|
|
dey
|
|
|
|
;add the number of leap years elapsed, the year, a constant for the
|
|
;month, and the day
|
|
|
|
stim015
|
|
clc
|
|
tya ;get the year again
|
|
adc dow_temp ;# of leap years since 1900
|
|
adc wkmon-1,x
|
|
adc 1,s
|
|
ply ;clean the stack
|
|
|
|
;Now mod the result by seven, but exit in the range [1..7]
|
|
|
|
sec
|
|
stim016 ;
|
|
sbc #07
|
|
cmp #08
|
|
bcs stim016
|
|
plp ;restore mode
|
|
rts
|
|
|
|
dow_temp DC.B 0
|
|
|
|
wkmon DC.B $08,$0B,$0B,$07,$09,$0C,$07,$0A,$0D,$08,$0B,$0D
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;get_time: This routine will read the time from the GS Clock.
|
|
;
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..0
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; hours,minutes
|
|
; year,month,day ;all are setup with the time
|
|
; day_of_week
|
|
;
|
|
;uses: Misc tools ;(Gets hex time)
|
|
;
|
|
;======================================================================
|
|
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT get_time
|
|
get_time PROC
|
|
|
|
lda #0000 ;setup default time to zero
|
|
pha ;minutes,seconds result
|
|
pha ;year,hour results
|
|
pha ;month,day results
|
|
pha ;weekday,null results
|
|
|
|
ldx #(read_time_hex*$100)+misc_tools
|
|
jsl tool_locator
|
|
|
|
longa off
|
|
sep #$20
|
|
pla ;disregard seconds
|
|
pla
|
|
sta minutes
|
|
pla
|
|
sta hours
|
|
pla
|
|
sta year
|
|
pla
|
|
|
|
bcs no_inc1
|
|
inc a
|
|
no_inc1 sta day ;convert 0 to 30 -> 1 to 31
|
|
|
|
pla
|
|
bcs no_inc2
|
|
inc a
|
|
no_inc2 sta month ;convert 0 to 11 -> 1 to 12
|
|
|
|
pla ;null field
|
|
pla
|
|
sta day_of_week
|
|
longa on
|
|
rep #$30
|
|
rts
|
|
ENDP
|
|
|
|
|
|
;============================================================================
|
|
;
|
|
;Calc_Bit: This routine will convert a 16 bit block number into
|
|
; the correct index into the bitmap block, the correct pattern
|
|
; to indicate which bit it is, and which relative block in the
|
|
; bitmap contains the bit
|
|
;
|
|
;Input: X = Block number to convert
|
|
; m = 0
|
|
; x = 0
|
|
; b = k
|
|
;
|
|
;Output: A = Bit Pattern (Which bit that needs to be changed)
|
|
; Y = Byte offset into bitmap block that contains bit
|
|
; X = Relative Block number of the bitmap that contains the bit
|
|
; Carry Clr
|
|
; All other flags undefined
|
|
;
|
|
;Uses: Local Table
|
|
; All registers
|
|
;
|
|
|
|
EXPORT calc_bit
|
|
calc_bit PROC
|
|
|
|
txa ;X=Block number
|
|
and #$0007 ;isolate bit index
|
|
tay
|
|
lda bit_table,y ;get the bit pattern
|
|
and #$00FF ;table is a byte table
|
|
pha
|
|
txa ;now isolate byte index
|
|
and #$0FF8
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
tay ;Y=Offset into bitmap block
|
|
jsr abs_to_rel ;absolute to relative block number
|
|
pla ;A=Bit pattern
|
|
rts
|
|
|
|
EXPORT abs_to_rel
|
|
abs_to_rel
|
|
clc
|
|
txa ;now isolate relative block number
|
|
and #$F000
|
|
rol a
|
|
rol a
|
|
rol a
|
|
rol a
|
|
rol a
|
|
tax ;X=Relative block number in bitmap
|
|
rts
|
|
|
|
bit_table DC.B $80,$40,$20,$10,$08,$04,$02,$01
|
|
ENDP
|
|
|
|
;============================================================================
|
|
;Alloc_block This routine will allocate a block in the bitmap.
|
|
; If the block is not in memory then it will load it.
|
|
;
|
|
;Input: X = Block number that you want to allocate
|
|
; m = 0
|
|
; x = 0
|
|
; b = k
|
|
; prodos_vcr_ptr
|
|
;
|
|
;Output: carry clr = no error
|
|
; carry set = could not allocate
|
|
; A = error code if carry set
|
|
; 01 = User would not mount the volume
|
|
; all flags undefined
|
|
;
|
|
;Uses: All Registers
|
|
; Calc_bit (Subroutine)
|
|
; Get_Bit_block (Subroutine)
|
|
; bitmap_changed (Subroutine)
|
|
;
|
|
|
|
EXPORT alloc_block
|
|
alloc_block PROC
|
|
|
|
jsr calc_bit ;calculate bit(A),byte(Y),block(X)
|
|
pha
|
|
phy
|
|
jsr get_bit_block ;load the correct block if needed
|
|
ply
|
|
pla
|
|
tax ;save mask
|
|
bcs done ;could not load block from disk
|
|
and [bitmap],y ;is the block already allocated?
|
|
beq bitmap_corrupt ;the bitmap is in bad shape, sorry.
|
|
txa ;restore the AND mask
|
|
eor #$FFFF ;we need to flip the patterns
|
|
and [Bitmap],y ;clear the correct bit
|
|
sta [bitmap],y
|
|
jsr bitmap_changed ;update bitmap flags
|
|
jsr sub_free_blk ;adjust free block count
|
|
done rts
|
|
|
|
EXPORT bitmap_corrupt
|
|
bitmap_corrupt ;we get here if the bitmap is corrupt
|
|
lda #damaged_bitmap
|
|
sec
|
|
rts ;return the error
|
|
|
|
EXPORT sub_free_blk
|
|
sub_free_blk
|
|
ldy #free_blocks
|
|
lda [prodos_vcr_ptr],y
|
|
inc a
|
|
beq who_knows
|
|
dec a ;$FFFF = major problem
|
|
dec a
|
|
sta [prodos_vcr_ptr],y
|
|
who_knows
|
|
clc
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;============================================================================
|
|
;DeAlloc_block This routine will deallocate a block in the bitmap.
|
|
; If the bitmap block is not in memory then it will load it.
|
|
; The routine will also update the free block count if needed
|
|
;
|
|
;Input: X = Block number that you want to deallocate
|
|
; m = 0
|
|
; x = 0
|
|
; b = k
|
|
; prodos_vcr_ptr (must be setup)
|
|
; my_vcr_ptr (must be setup)
|
|
;
|
|
;Output: carry clr = no error
|
|
; carry set = could not allocate
|
|
; A = error code if carry set
|
|
; 01 = User would not mount the volume
|
|
; all flags undefined
|
|
;
|
|
;Uses: All Registers
|
|
; Calc_bit (Subroutine)
|
|
; Get_Bit_block (Subroutine)
|
|
;
|
|
|
|
EXPORT dealloc_block
|
|
dealloc_block PROC
|
|
|
|
jsr calc_bit ;calculate bit(A),byte(Y),block(X)
|
|
phx
|
|
pha
|
|
phy
|
|
jsr get_bit_block ;load the correct block if needed
|
|
ply
|
|
pla
|
|
plx
|
|
bcs done ;could not load block from disk
|
|
pha ;save the mask please
|
|
and [bitmap],y ;is the block already deallocated?
|
|
beq no_prob ;the block is currently allocated
|
|
pla ;fix the stack
|
|
bra bitmap_corrupt ;return the error please
|
|
|
|
no_prob ;
|
|
pla ;restore the mask please
|
|
ora [bitmap],y ;set the correct bit
|
|
sta [bitmap],y
|
|
|
|
;We have just deallocated some blocks so lets make sure the first bitmap block
|
|
;that contains available space is correct for the current VCR
|
|
|
|
ldy #avail_bitmap
|
|
txa ;relative block number
|
|
cmp [prodos_vcr_ptr],y
|
|
;
|
|
; 2/3/90 Mensch, Hauser,Benaresh
|
|
;
|
|
; Rob says that avail_bitmap should *ALWAYS* be equal to the lowest bitmap
|
|
; block that has space in it. So, the branch that was a BEQ should really be
|
|
; a BCS (BGE) this way, so it will work right.
|
|
;
|
|
|
|
bge go_changed ;the relative block num is the same
|
|
|
|
;If we freed up a block in a previously full bitmap then lets update the VCR
|
|
|
|
sta [prodos_vcr_ptr],y
|
|
|
|
go_changed
|
|
jsr add_free_blk
|
|
EXPORT bitmap_changed
|
|
bitmap_changed
|
|
clc
|
|
|
|
;==========================================================================
|
|
;This routine will mark the current bitmap block dirty. NOTE: This routine
|
|
;must not change the state of the carry.
|
|
|
|
ldy #bitmap_dirty
|
|
lda #bitmap_mod ;bitmap modified
|
|
sta [prodos_vcr_ptr],y
|
|
done rts
|
|
|
|
;==========================================================================
|
|
;This routine will add one to the free block count for a volume. If the
|
|
;number of free blocks is unknown then the routine will just exit.
|
|
|
|
EXPORT add_free_blk
|
|
add_free_blk
|
|
ldy #free_blocks
|
|
lda [prodos_vcr_ptr],y
|
|
inc a ;$FFFF = free block count unknown
|
|
beq end_free ;free block count is not known
|
|
sta [prodos_vcr_ptr],y
|
|
end_free
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
;==========================================================================
|
|
;get_bit_block: This routine will load in the correct bitmap block from
|
|
; disk. If the correct block is already loaded then the
|
|
; routine will just exit.
|
|
;
|
|
;Input: A = undefined
|
|
; X = relative block number to load
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; prodos_vcr_ptr (must be setup correctly)
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; bitmap (points to bitmap buffer)
|
|
; drvr_buf_ptr (same as bitmap)
|
|
;
|
|
;Uses: All registers
|
|
; device_call
|
|
; drvr_call_num
|
|
;
|
|
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT get_bit_block
|
|
get_bit_block PROC
|
|
|
|
phx ;save the block number
|
|
|
|
jsr setup_bitmap_ptr
|
|
|
|
stx drvr_buf_ptr
|
|
stx bitmap
|
|
sty drvr_buf_ptr+2
|
|
sty bitmap+2
|
|
|
|
pla ;retore relative block number
|
|
sta math_temp
|
|
ldy #curr_bitmap
|
|
cmp [prodos_vcr_ptr],y
|
|
beq good_exit
|
|
|
|
pha
|
|
|
|
;force dirty bitmap block back to disk if needed.
|
|
|
|
jsr force_bitmap ;force the bitmap to disk
|
|
bcc flushed
|
|
plx
|
|
rts
|
|
|
|
flushed
|
|
|
|
;If we get here we have to calculate the right block to read into memory
|
|
|
|
pla
|
|
clc
|
|
ldy #vol_bitmap_addr
|
|
adc [prodos_vcr_ptr],y
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcc read_ok
|
|
jsr kill_bitmap
|
|
sec
|
|
rts ;return the error
|
|
|
|
read_ok
|
|
|
|
;Now we need to update the current bitmap
|
|
|
|
ldy #curr_bitmap
|
|
lda math_temp
|
|
sta [prodos_vcr_ptr],y
|
|
|
|
good_exit
|
|
clc
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;calc_free_blks This routine will calculate the number of blocks that are
|
|
; free on a volume.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; prodos_vcr_ptr (must be setup correctly)
|
|
; drvr_dev_num (must be setup up)
|
|
;
|
|
;Output: A = error code if carry set otherwise total blocks free
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; device_call
|
|
; I/O buffer
|
|
;
|
|
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT calc_free_blks
|
|
calc_free_blks PROC
|
|
|
|
;before we start going to disk lets see if we already know the number of
|
|
;free blocks. IF free_blocks = $FFFF then free blocks are unknown.
|
|
|
|
ldy #free_blocks
|
|
lda [prodos_vcr_ptr],y
|
|
inc a
|
|
beq go_figure ;we need to calculate it
|
|
dec a ;A = total blocks
|
|
clc
|
|
rts
|
|
|
|
go_figure
|
|
jsr force_bitmap ;flush the bitmap if needed
|
|
|
|
;setup the buffer pointer to the general I/O buffer provided by GS/OS shell
|
|
|
|
stz first_free_bm ;indicate that we do not know free cnt
|
|
|
|
;First lets see if there is already a bitmap buffer allocated. If so
|
|
;lets use it as our I/O buffer.
|
|
|
|
jsr setup_bitmap_ptr
|
|
stx drvr_buf_ptr
|
|
sty drvr_buf_ptr+2
|
|
|
|
;read 512 bytes from the disk.
|
|
|
|
jsr standard_req
|
|
|
|
;go do a run on the bitmap calculating the number of blocks free
|
|
|
|
stz math_temp ;counts the free blocks
|
|
|
|
ldy #vol_bitmap_addr
|
|
lda [prodos_vcr_ptr],y
|
|
sta drvr_blk_num ;starting block number of bitmap
|
|
|
|
ldy #num_bitmap_blks
|
|
lda [prodos_vcr_ptr],y
|
|
sta bitmap_blks ;number of blocks in the bitmap
|
|
|
|
ldy #end_bitmap ;first byte that should be all zeros
|
|
lda [prodos_vcr_ptr],y
|
|
sta last_bitmap
|
|
|
|
ldy #avail_bitmap
|
|
lda [prodos_vcr_ptr],y
|
|
inc a
|
|
beq block_loop
|
|
dec a
|
|
tay ;save start
|
|
clc
|
|
adc drvr_blk_num ;adjust the starting block number
|
|
sta drvr_blk_num
|
|
|
|
phy
|
|
sec
|
|
lda bitmap_blks ;number of blocks to scan
|
|
sbc 1,s ;subtract start block number
|
|
sta bitmap_blks
|
|
pla
|
|
|
|
block_loop
|
|
jsr read_with_cache ;read in a block
|
|
bcc read_ok
|
|
jsr kill_bitmap
|
|
sec
|
|
rts ;we should not get any errors
|
|
|
|
bad_bitmap lda #damaged_bitmap
|
|
sec
|
|
rts
|
|
|
|
read_ok
|
|
|
|
;update the current bitmap in memory field.
|
|
sec
|
|
ldy #vol_bitmap_addr
|
|
lda drvr_blk_num
|
|
sbc [prodos_vcr_ptr],y
|
|
ldy #curr_bitmap
|
|
sta [prodos_vcr_ptr],y
|
|
|
|
;if this is the last block of the bitmap then verify ending with zeros.
|
|
|
|
dec bitmap_blks
|
|
bne not_last
|
|
ldy last_bitmap ;starting location that must be zero
|
|
beq not_last ;don't bother
|
|
|
|
zero_loop
|
|
cpy #$01FF ;are we near the end of the block?
|
|
bcs setup_index ;If we are this close the end
|
|
lda [drvr_buf_ptr],y
|
|
bne bad_bitmap
|
|
iny
|
|
iny
|
|
bra zero_loop
|
|
|
|
setup_index
|
|
ldy last_bitmap
|
|
tya
|
|
lsr a ;is it an even value?
|
|
bcc word_loop ;Yes, so fall into loop
|
|
iny ;make it even if it is not
|
|
cpy #$01FE ;is it now greater then one block
|
|
bcc word_loop ;no so fall into the loop
|
|
|
|
not_last
|
|
ldy #$01FE ;start scanning the block
|
|
|
|
word_loop
|
|
lda [drvr_buf_ptr],y
|
|
bne count_bits
|
|
return_loop dey
|
|
dey
|
|
bpl word_loop ;keep scanning the block please
|
|
|
|
lda bitmap_blks ;see if we are done
|
|
beq calc_done ;we are done
|
|
inc drvr_blk_num ;read next block please
|
|
bra block_loop
|
|
|
|
;Check to see if we already know the first bitmap block that contains
|
|
;free blocks. IF we do then just count the blocks free
|
|
|
|
count_bits
|
|
sta bits ;save bitmap word
|
|
|
|
lda first_free_bm
|
|
bne cont_count
|
|
|
|
;We now know the first bitmap block that contains available blocks, so lets
|
|
;save it please.
|
|
|
|
phy
|
|
sec
|
|
ldy #vol_bitmap_addr
|
|
lda drvr_blk_num
|
|
sta first_free_bm
|
|
sbc [prodos_vcr_ptr],y
|
|
ldy #avail_bitmap
|
|
sta [prodos_vcr_ptr],y
|
|
ply
|
|
|
|
cont_count
|
|
ldx #16 ;cycle thru word 16 times
|
|
lda bits ;get the bit count back
|
|
inc a ;special case $FFFF to speed calc
|
|
beq add_16
|
|
|
|
bit_loop
|
|
dex
|
|
bmi return_loop ;we have scanned the word
|
|
lsr bits
|
|
bcc bit_loop
|
|
inc math_temp ;advance the count please
|
|
bra bit_loop
|
|
|
|
add_16
|
|
clc
|
|
lda math_temp
|
|
adc #$0010 ;$FFFF = 16 blocks free
|
|
sta math_temp
|
|
bra return_loop
|
|
|
|
;When we get here we have counted all the blocks that are marked as free.
|
|
;Now we need to see if there are any blocks marked as purgable.
|
|
|
|
calc_done
|
|
lda math_temp ;number of blocks free
|
|
|
|
;Now lets update the VCR to indicate that we know the number of free blocks
|
|
|
|
save_and_exit
|
|
ldy #free_blocks
|
|
sta [prodos_vcr_ptr],y ;total free count
|
|
|
|
jsr set_user_cache ;restore cache ('A' and 'P' preserved)
|
|
clc
|
|
rts
|
|
|
|
EXPORT kill_bitmap
|
|
kill_bitmap
|
|
pha
|
|
lda #bitmap_unknown ;flag bitmap as unknown
|
|
ldy #curr_bitmap
|
|
sta [prodos_vcr_ptr],y
|
|
pla
|
|
rts
|
|
ENDP
|
|
|
|
|
|
;==========================================================================
|
|
;find_free_blks This routine will scan the bitmap looking for a sequence
|
|
; of blocks that are marked as free. The routine will always
|
|
; try to allocate the blocks in one large group. If a group
|
|
; cannot be found to satisfy the request count then this
|
|
; routine will allocate the first available block.
|
|
; At least one block MUST be free for allocation!!!!!!!!!!
|
|
;
|
|
;Input: A = number of blocks to allocate. ( 'n' blocks)
|
|
; X = starting block number for search. (might be minus 7 blks)
|
|
; prodos_vcr_ptr (must be setup)
|
|
; ^avail_bitmap (must be valid)
|
|
;
|
|
;output: A = error or number of blocks allocated. (1 or 'n')
|
|
; X = starting block number of allocated blocks
|
|
; P = nvmxdizc
|
|
; ..000..1 = no blocks allocated (error)
|
|
; 0 = allocated
|
|
;
|
|
;uses: calc_bits
|
|
; math_temp
|
|
;
|
|
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT find_free_blks
|
|
find_free_blks PROC
|
|
|
|
sta alloc_count ;number of blocks to allocate
|
|
stx alloc_start ;starting block number for search
|
|
stx first_free
|
|
|
|
jsr calc_bit ;absolute blk to relative blk.
|
|
;
|
|
; calc_bit results:
|
|
;
|
|
;A = bit mask $80 $40 $20 $10 $08 $04 $02 $01
|
|
;Y = byte offset in the bitmap buffer
|
|
;X = relative block number that contains the block number passed as input
|
|
;
|
|
sty byte_offset ;starting byte in block
|
|
xba
|
|
align_loop ; ;set blk num to byte boundary
|
|
asl a ;check bit position of user block num
|
|
bcs chk_avail ;ok here
|
|
dec first_free
|
|
bra align_loop ;check next bit
|
|
|
|
chk_avail
|
|
lda byte_offset ;are we word aligned?
|
|
lsr a
|
|
bcc aligned ;yes we are OK
|
|
|
|
dec byte_offset ;now set starting block to word boundary
|
|
sec
|
|
lda first_free
|
|
sbc #$0008
|
|
sta first_free ;everything should be word aligned now.
|
|
|
|
aligned
|
|
txa
|
|
ldy #avail_bitmap ;see if start is >= first free
|
|
cmp [prodos_vcr_ptr],y
|
|
bcs start_ok ;start is >= first free
|
|
lda [prodos_vcr_ptr],y
|
|
tax
|
|
ror a
|
|
ror a
|
|
ror a
|
|
ror a
|
|
ror a ;calc starting block number
|
|
sta first_free ;ex. rel blk #1 = blk #4096 or $1000
|
|
txa
|
|
stz byte_offset
|
|
|
|
start_ok
|
|
stz last_blk ;starting block for caller
|
|
stz math_temp ;reset the free block counter
|
|
|
|
tax ;now load in the bitmap block
|
|
next_blk
|
|
lda math_temp
|
|
pha ;save temp count
|
|
jsr get_bit_block
|
|
bcc got_block
|
|
ply ;fix the stack
|
|
rts ;return error please
|
|
|
|
got_block
|
|
pla ;reset temp count
|
|
sta math_temp
|
|
stz some_free ;indicates if ANY blocks are free!
|
|
|
|
ldy byte_offset ;start looking here for 1st free block
|
|
cpy #$01FF ;are we near then end?
|
|
bcc next_word
|
|
ldy #$01FE
|
|
|
|
next_word
|
|
ldx #16 ;scan all 16 bits
|
|
lda [bitmap],y ;get a bitmap word (16 blocks)
|
|
bne check_16 ;sorry no bits here.
|
|
|
|
stz math_temp ;reset the counter please.
|
|
stz last_blk
|
|
bra no_change
|
|
|
|
check_16
|
|
xba ;put bits in the right order
|
|
|
|
sta bits
|
|
sta some_free ;there are free blocks in this dir.
|
|
inc a ;check 16 please
|
|
bne scan_loop
|
|
;
|
|
;special case of all sixteen blocks allocated
|
|
;
|
|
clc
|
|
lda math_temp
|
|
adc #16 ;easy case
|
|
sta math_temp
|
|
lda last_blk ;do we have the starting blk yet?
|
|
bne chk_req_cnt ;we already have start block
|
|
lda first_free
|
|
sta last_blk
|
|
|
|
chk_req_cnt
|
|
lda math_temp ;see if we are done
|
|
cmp alloc_count
|
|
bcs req_filled ;request filled. We are done!!!
|
|
|
|
no_change
|
|
clc
|
|
lda first_free
|
|
adc #16 ;bump block number
|
|
sta first_free
|
|
bra bump_index ;go get the next word
|
|
|
|
scan_loop
|
|
lda math_temp ;see if we are done
|
|
cmp alloc_count
|
|
bcs req_filled ;request filled. We are done!!!
|
|
|
|
asl bits ;see if this block is available
|
|
bcc reset_count ;a used block
|
|
inc math_temp ;add one to block count
|
|
lda last_blk
|
|
bne next_bit
|
|
lda first_free
|
|
sta last_blk ;update start block
|
|
bra next_bit
|
|
|
|
reset_count
|
|
stz math_temp ;reset the counter
|
|
stz last_blk ;reset start block
|
|
next_bit ;
|
|
inc first_free ;bump the block number
|
|
dex
|
|
bne scan_loop
|
|
|
|
lda math_temp ;see if we are done
|
|
cmp alloc_count
|
|
bcs req_filled ;request filled. We are done!!!
|
|
|
|
bump_index
|
|
iny
|
|
iny
|
|
cpy #$01FF ;are we done?
|
|
bcc next_word ;not yet
|
|
|
|
ldy #curr_bitmap ;current loaded bitmap block
|
|
lda [prodos_vcr_ptr],y
|
|
inc a ;convert 0 to 'n' to 1 to 'n'+1
|
|
ldy #num_bitmap_blks
|
|
cmp [prodos_vcr_ptr],y
|
|
bcs find_one ;no more bitmap blocks to search!
|
|
|
|
jsr bump_1st_free ;bump to next block if needed.
|
|
|
|
stz byte_offset ;reset byte offset
|
|
ldx first_free
|
|
jsr abs_to_rel ;calc relative block number
|
|
jmp next_blk ;load in the next block
|
|
|
|
find_one ; ;allocate one block only
|
|
lda #$0001
|
|
ldx #$0000 ;start at block 0
|
|
jsr find_free_blks
|
|
rts
|
|
|
|
;now we need to update the bitmap blocks!
|
|
|
|
req_filled
|
|
ldx last_blk
|
|
ldy alloc_count
|
|
dey ;convert 1 to 'n' -> 0 to 'n-1'
|
|
alloc_loop ;
|
|
phy ;number of blocks wanted
|
|
phx ;block number to allocate
|
|
jsr alloc_block ;mark the block as used!
|
|
plx
|
|
ply
|
|
bcs bad_news
|
|
inx ;allocate the next block
|
|
dey
|
|
bpl alloc_loop
|
|
lda alloc_count ;user request satisfied
|
|
ldx last_blk ;starting block for allocation
|
|
clc ;no error
|
|
|
|
bad_news
|
|
rts
|
|
|
|
bump_1st_free
|
|
lda some_free ;is this block empty?
|
|
bne bad_news ;no...
|
|
|
|
ldy #avail_bitmap ;bump avail to next block if needed
|
|
lda [prodos_vcr_ptr],y
|
|
ldy #curr_bitmap
|
|
cmp [prodos_vcr_ptr],y
|
|
bne bad_news
|
|
|
|
ldy #avail_bitmap
|
|
lda [prodos_vcr_ptr],y
|
|
inc a
|
|
sta [prodos_vcr_ptr],y
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;free_vcr: This routine will free all memory associated with a
|
|
; volume control record.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; my_vcr_ptr (Points to main VCR)
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
; release_seg (system routine to release a vcr)
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT free_vcr
|
|
free_vcr PROC
|
|
|
|
lda [my_vcr_ptr] ;get the volume ID
|
|
jsl release_vcr ;and call the systems nuke vcr routine
|
|
rts
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;Remove_fcr: This routine will remove a FCR
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; my_fcr_ptr (must be setup)
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT remove_fcr
|
|
remove_fcr PROC
|
|
|
|
ldy #dirty_file_cnt ;check if bitmap needs to be flushed
|
|
lda [prodos_vcr_ptr],y
|
|
dec a
|
|
bne @did_flush ;we do not need to flush the bitmap
|
|
jsr force_bitmap ;force a dirty block to disk
|
|
bcs @error ;we have to be able to flush
|
|
@did_flush
|
|
ldy #vcr_open_cnt ;subtract one from the open count
|
|
lda [my_vcr_ptr],y
|
|
dec a
|
|
bmi die_die_die ;the system is very sick
|
|
sta [my_vcr_ptr],y ;Update the open count in the VCR
|
|
|
|
lda [my_fcr_ptr] ;reference number to remove
|
|
jsl release_fcr ;nuke the puppy
|
|
clc ;we are very happy now
|
|
@error
|
|
rts
|
|
|
|
die_die_die
|
|
lda #'SK'
|
|
jml sys_death
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;setup_params This routine is called at the beginning of each system
|
|
; call. It will setup parameters and verify certain fields
|
|
; of the os call. If a VCR is used and the media is swapped
|
|
; out of the system then the system mount routine will be called
|
|
;
|
|
;Input: A = undefined
|
|
; X = two times the call number
|
|
; Y = two times the class
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = class of call/2 (MUST be last instruction before RTS!!)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; pcount (contains pcount for call. 0=class0)
|
|
; my_pblk_ptr (points past pcount to first param)
|
|
; my_vcr_ptr (if available)
|
|
; prodos_vcr_ptr
|
|
; my_fcr_ptr (if available)
|
|
; pro_fcr_ptr
|
|
;
|
|
;Uses: All registers
|
|
; math_temp
|
|
; pcount
|
|
;
|
|
;What the table looks like and what fields we verify.
|
|
;
|
|
; 1) Max PCount for the call
|
|
; 2) Max Class for the call
|
|
; 3) Pathnames used by call
|
|
; 4) volume control record used
|
|
; 5) file control record used.
|
|
; 6) io buffer used.
|
|
; 7) flush file to disk
|
|
; 8) damaged disk protect
|
|
;
|
|
; |8|7|6|5|4|3| 2 | 1 |
|
|
; ___|_|_|_|_|_|_|_____|_________|
|
|
; | | | | | | | | | | | | | | | | |
|
|
; |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
|
|
; | | |
|
|
; 1 6 0 8 0 0
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT setup_params
|
|
setup_params PROC
|
|
|
|
;First we load the flags from the start table and save them for later
|
|
;use.
|
|
|
|
lda gbuf_addr ;setup the general buffer pointer
|
|
sta gbuf_ptr
|
|
lda gbuf_addr+2
|
|
sta gbuf_ptr+2
|
|
|
|
stz drvr_vol_id ;zero the volume ID(for Mike). Allow each call to set it up
|
|
stz search_flag ;indicate normal find file
|
|
stz prodos_vcr_ptr
|
|
stz prodos_vcr_ptr+2
|
|
stz my_vcr_ptr
|
|
stz my_vcr_ptr+2
|
|
stz pro_fcr_ptr
|
|
stz pro_fcr_ptr+2
|
|
|
|
stz case_bits ;indicate that the case is all upper.
|
|
|
|
stz slug_block ;indicate no slug_ripple
|
|
stz close_flag ;indicate that 'flush_file' will not
|
|
; ;call slug_ripple
|
|
stz expand_record.expand_file
|
|
stz expand_record.expand_flag
|
|
stz chk_dirty_flag ;do not check the VCR to see if the file is dirty
|
|
stz dirty_flags
|
|
stz dirty_cnt_changed
|
|
stz write_occurred ;If non-zero a write occurred to the disk.
|
|
|
|
stz cp_device_flag ;indicate normal ChangePath 1/22/91 CAE
|
|
stz cp_flags ;assume not a duplicate volume 5-Dec-91 MSD
|
|
stz error_priority ;error priority is 0 3/05/91 CAE
|
|
|
|
lda start_tbl-2,x ;get the flags for the call
|
|
sta flags
|
|
and #$001F
|
|
sta max_pcount
|
|
|
|
;Go ahead and setup the default parameters.
|
|
|
|
stz pcount
|
|
|
|
;Now verify the max class of the call.
|
|
;
|
|
;To do this we divide class by two and compare to the calls max class
|
|
|
|
tya
|
|
lsr a
|
|
sta class
|
|
beq class0 ;this is a OLD style call
|
|
|
|
lda flags
|
|
and #$00E0 ;clear other flags please
|
|
asl a
|
|
asl a
|
|
asl a
|
|
xba
|
|
cmp class
|
|
bcs good_class
|
|
lda #invalid_class
|
|
bra error_out
|
|
|
|
good_class
|
|
|
|
;Now we need to verify the max pcount for the new class calls
|
|
|
|
lda [param_blk_ptr]
|
|
cmp max_pcount
|
|
bcc good_pcount
|
|
|
|
lda #invalid_pcount
|
|
|
|
;Carry has to be set before calling error_out!!
|
|
|
|
error_out
|
|
jmp main_exit
|
|
|
|
good_pcount
|
|
|
|
;We get here if the pcount is good. We also get here with a 'BCC'
|
|
;so if this changes we must add a CLC to the following 'ADD'
|
|
|
|
sta pcount
|
|
|
|
lda param_blk_ptr ;CARRY CLEAR on entry!!!!
|
|
adc #$0002
|
|
sta my_pblk_ptr
|
|
lda param_blk_ptr+2
|
|
adc #$0000
|
|
sta my_pblk_ptr+2
|
|
bra cont01
|
|
|
|
class0
|
|
lda param_blk_ptr
|
|
sta my_pblk_ptr
|
|
lda param_blk_ptr+2
|
|
sta my_pblk_ptr+2
|
|
|
|
cont01
|
|
|
|
ldx #pro_id ;setup FST number for our FST.
|
|
stx drvr_fst_num
|
|
|
|
jsl lock_mem ;make sure data blocks do not move
|
|
|
|
|
|
lda dev_num ;move the device number to driver
|
|
sta drvr_dev_num ;direct page area
|
|
|
|
;when we get here we know that both class and pcount are valid.
|
|
;now we need to check if a VCR or FCR is used by the call.
|
|
|
|
lda flags
|
|
and #vcr_used
|
|
|
|
beq check_fcr ;no VCR is used by the call
|
|
|
|
;setup my pointer to the VCR and deref VP to my local data.
|
|
|
|
ldx vcr_ptr
|
|
ldy vcr_ptr+2
|
|
jsl deref
|
|
stx my_vcr_ptr
|
|
sty my_vcr_ptr+2
|
|
jsr setup_my_vcr
|
|
stx prodos_vcr_ptr
|
|
sty prodos_vcr_ptr+2
|
|
|
|
lda flags ;do we need to check damage?
|
|
and #damage
|
|
beq vol_ok ;this must be a read only call.
|
|
|
|
ldy #vol_damaged ;is this volume damaged??
|
|
lda [prodos_vcr_ptr],y
|
|
inc a ;Have I already showed the error message
|
|
bne vol_ok ;the disk is not damaged
|
|
sec
|
|
lda #invalid_access ;get the error code please
|
|
jmp main_exit
|
|
|
|
vol_ok ;
|
|
ldy #vcr_status ;see if the volume is swapped out
|
|
lda [my_vcr_ptr],y
|
|
and #vcr_swapped
|
|
beq check_fcr ;the volume is online.
|
|
|
|
lda call_number ;see if this is a close call.
|
|
and #$DFFF ;get rid of the class please
|
|
cmp #$0014 ;Compare class zero close call number
|
|
bne @do_mount ;we must do a mount message
|
|
|
|
ldy #bitmap_dirty ;See if the Bitmap is dirty
|
|
lda [prodos_vcr_ptr],y
|
|
bne @do_mount ;we need the disk bad!!!
|
|
|
|
ldy #dirty_file_cnt ;see if there open files on disk that are dirty?
|
|
lda [prodos_vcr_ptr],y
|
|
beq check_fcr ;no open dirty files so skip mount.
|
|
@do_mount
|
|
jsr mount_volume ;force the user to put our disk online
|
|
check_fcr
|
|
lda flags
|
|
and #fcr_used
|
|
beq check_path ;no FCR is used by the call
|
|
|
|
;setup my pointer to the FCR and deref VP to my local data.
|
|
|
|
ldx fcr_ptr
|
|
ldy fcr_ptr+2
|
|
jsl deref
|
|
stx my_fcr_ptr
|
|
sty my_fcr_ptr+2
|
|
|
|
jsr setup_my_fcr ;build pointer to local data
|
|
stx pro_fcr_ptr
|
|
sty pro_fcr_ptr+2
|
|
|
|
lda flags ;do we need to flush the file?
|
|
and #flush_1st
|
|
beq check_path ;no flush needed
|
|
|
|
ldy #fcr_status ;see if the file is dirty
|
|
lda [pro_fcr_ptr],y
|
|
and #file_dirty
|
|
beq check_path ;file is clean!
|
|
|
|
jsr setup_io_ptrs
|
|
jsr flush_file ;force dirty blocks to disk
|
|
tax
|
|
lda flags ;clear IO needed bit
|
|
and #clr_io_used
|
|
sta flags
|
|
txa
|
|
bcc check_path
|
|
jmp main_exit
|
|
|
|
;Moved the check_path code into a seperate routine and we now
|
|
;only check for bad spans after we have located the target vol
|
|
;and determined that it is indeed a ProDOS volume.
|
|
; 10/10/91 JEV
|
|
check_path
|
|
; lda flags
|
|
; and #path_used
|
|
; beq check_io_buf ;no pathname is used
|
|
|
|
;See if there are any pathnames available
|
|
|
|
; lda path_flag
|
|
; and #path1_mask
|
|
; beq check_path2
|
|
|
|
; lda span1
|
|
; beq bad_span ;added 11/12/90 CAE
|
|
; cmp #$0010
|
|
; bcc check_path2
|
|
|
|
;bad_span sec ;added 11/12/90 CAE
|
|
;backup lda #bad_path_syntax
|
|
; brl error_out
|
|
|
|
;check_path2 ;
|
|
|
|
;We don't check span2 here if we are doing a change path call
|
|
;we need to do some preprocessing first so that error priority
|
|
;gets setup properly for the change path call.. added 8/21/91 JEV
|
|
|
|
; lda call_number ;see if this is a changepath call.
|
|
; and #$DFFF ;get rid of the class please
|
|
; cmp #$0004 ;Compare with changepath call number
|
|
; beq check_io_buf ;just continue
|
|
|
|
; lda path_flag
|
|
; and #path2_mask
|
|
; beq check_io_buf
|
|
|
|
; lda span2
|
|
; beq bad_span ;added 11/12/90 CAE
|
|
; cmp #$0010
|
|
; bcs backup
|
|
|
|
check_io_buf ;
|
|
lda flags
|
|
and #io_used
|
|
beq end_buf_setup
|
|
|
|
;now we need to setup real pointers to the I/O buffer. There is only
|
|
;one I/O buffer for a file. However, the I/O buffer varies in it's size
|
|
;and structure.
|
|
|
|
jsr setup_io_ptrs
|
|
|
|
end_buf_setup
|
|
lda flags ;see if we need to check for file dirty
|
|
and #do_dirty
|
|
beq @exit
|
|
sta chk_dirty_flag ; 00 = do not check
|
|
ldy #fcr_status ;get the status out of the File Control Record
|
|
lda [pro_fcr_ptr],y
|
|
and #file_dirty+data_dirty+index_dirty+master_dirty
|
|
sta dirty_flags ;save the flags
|
|
@exit
|
|
lda class
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;check_spans This routine is called when a pathname is used and we
|
|
; we need to verify that the spans are valid. If they
|
|
; are incorrect then we bail out.
|
|
;
|
|
;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
|
|
; 0 = no error
|
|
;
|
|
EXPORT check_spans
|
|
check_spans PROC
|
|
|
|
lda path_flag
|
|
and #path1_mask
|
|
beq check_path2
|
|
|
|
lda span1
|
|
beq bad_span
|
|
cmp #$0010
|
|
bcc check_path2
|
|
|
|
bad_span sec
|
|
backup lda #bad_path_syntax
|
|
jmp main_exit
|
|
|
|
check_path2 ;
|
|
lda path_flag
|
|
and #path2_mask
|
|
beq @spans_ok
|
|
|
|
lda span2
|
|
beq bad_span
|
|
cmp #$0010
|
|
bcs backup
|
|
@spans_ok
|
|
rts
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;process_path This routine is called when a pathname needs to be
|
|
; processed and located on the disk. If the pathname is
|
|
; not a prodos name then we bail out.
|
|
;
|
|
;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
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; drvr_buf_ptr (points to the file entry)
|
|
; entry_offset (offset to entry within I/O buffer)
|
|
; parent_blk (entries parent block address)
|
|
;
|
|
;Uses: All registers
|
|
; math_temp
|
|
; pcount
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT process_path
|
|
process_path PROC
|
|
|
|
lda #in_cache ;put directories in the cache
|
|
sta drvr_cache
|
|
|
|
lda #path1_mask ;and mask for path_flag
|
|
ldx path1_ptr
|
|
ldy path1_ptr+2
|
|
jsr build_path
|
|
bcc @chk_root_only
|
|
brl dev_or_vol ;No path just a device # or vol. name
|
|
|
|
@chk_root_only
|
|
lda search_flag ;do we allow a pathname?
|
|
and #root_only
|
|
beq @path_ok
|
|
lda #bad_path_syntax
|
|
sec
|
|
rts ;return error to caller
|
|
|
|
@path_ok
|
|
|
|
;If we fall thru then we know that there is a pathname to find.
|
|
;We also know that there is either a volume name or device.
|
|
|
|
stx hold_path_ptr
|
|
sty hold_path_ptr+2
|
|
|
|
lda dev_num ;There is a device number
|
|
beq cont01 ;Find Volume Name
|
|
sta drvr_dev_num
|
|
|
|
;next call removed 2/26/90 by Monte Benaresh
|
|
;leaving the call in doesn't let the user swap a new volumeÉ
|
|
;Éinto a device and specify a device name in the path
|
|
|
|
;jsr check_vcr_first ;see if we have a vcr for it
|
|
;bcc find_path ;we do?
|
|
|
|
;Look on a specific device
|
|
|
|
go_id_disk
|
|
lda drvr_dev_num
|
|
jsr id_disk ;go and find out if it is our disk
|
|
;this also allocates a VCR if needed
|
|
bcc find_path ;I own the disk.
|
|
jmp main_exit ;return error to GS/OS
|
|
|
|
cont01 ;
|
|
jsr vol_to_buffer
|
|
jsr find_volume ;locate the volume
|
|
bcc find_path
|
|
jmp main_exit
|
|
|
|
find_path lda #$8000 ;indicate that we found the volume 3/5/91 CAE
|
|
sta error_priority ;and it's a ProDOS volume 3/5/91 CAE
|
|
|
|
;So it's one of our volumes, now check to see if we are using paths, and
|
|
;the spans are ok. 10/10/91 JEV
|
|
lda flags
|
|
and #path_used
|
|
beq check_damage ;no pathname is used
|
|
jsr check_spans ;so check them
|
|
|
|
check_damage lda flags ;is this a call to check the disk
|
|
and #damage
|
|
beq vol_good
|
|
|
|
jsr setup_my_vcr ;setup the pointer first
|
|
stx prodos_vcr_ptr
|
|
sty prodos_vcr_ptr+2
|
|
|
|
ldy #vol_damaged ;see if the volume is damaged
|
|
lda [prodos_vcr_ptr],y
|
|
beq vol_good
|
|
lda #dir_error ;write protected
|
|
jmp damaged_message
|
|
|
|
vol_good ;
|
|
lda drvr_dev_num
|
|
ldx hold_path_ptr
|
|
ldy hold_path_ptr+2
|
|
jsr find_file ;try to locate the file
|
|
bcc save_parent
|
|
cmp #drvr_disk_sw ;was the media switched?
|
|
beq go_id_disk
|
|
|
|
bit search_flag ;is 'file not found' ok for this call?
|
|
bvc not_ok ;no, tell caller about the error
|
|
cmp #file_not_found
|
|
bne not_ok ;this error cannot be handled!
|
|
sec
|
|
rts ;tell caller that an error occured.
|
|
|
|
not_ok ;
|
|
sec
|
|
jmp main_exit
|
|
|
|
save_parent ;
|
|
sta entry_offset ;offset to the entry within the blk
|
|
lda drvr_blk_num ;block number of parent
|
|
sta parent_blk
|
|
|
|
cont02 stx drvr_buf_ptr ;save pointer to name
|
|
sty drvr_buf_ptr+2
|
|
process_exit ;
|
|
jsr set_user_cache
|
|
rts
|
|
|
|
;If we get here we know that there is no pathname to process.
|
|
;We also know if there is no device number then 'volume_name' contains
|
|
;a volume name that I am suppose to open.
|
|
|
|
dev_or_vol ;
|
|
lda dev_num
|
|
beq use_vol_name ;we must have a volume name.
|
|
jsr id_disk ;go and find out if it is our disk
|
|
bcs to_main_exit
|
|
|
|
;Before we check to see if the volume name is legal we must see if the
|
|
;volume is online. The reason we do this is to be compatible with P16.
|
|
;
|
|
;Example:
|
|
; Create '/VOLUME' ;If '/VOLUME' is online then
|
|
; ;the error returned is 'BadPath'
|
|
; Create '/VOLUME' ;If '/VOLUME' is offline then
|
|
; ;the error returned is 'VolNotFound'
|
|
;
|
|
|
|
its_mine lda #$8000 ;indicate that we found the volume 3/5/91 CAE
|
|
sta error_priority ;and it's a ProDOS volume 3/5/91 CAE
|
|
|
|
check_root bit search_flag ;is a root level valid?
|
|
bpl continue1 ;no problem with root level.
|
|
|
|
lda #bad_path_syntax
|
|
sec
|
|
to_main_exit ;
|
|
jmp main_exit ;return error to M.A. and J.J.
|
|
|
|
continue1 ;
|
|
lda [drvr_buf_ptr] ;points to volume name
|
|
ora #volume_header ;add back in the storage type
|
|
sta [drvr_buf_ptr]
|
|
|
|
lda #vol_dir_start
|
|
sta parent_blk
|
|
lda #$0004
|
|
sta entry_offset
|
|
bra process_exit
|
|
|
|
use_vol_name ;
|
|
jsr find_volume ;locate the volume
|
|
bcc its_mine
|
|
jmp main_exit
|
|
|
|
EXPORT set_user_cache
|
|
set_user_cache ;
|
|
pha ;save entry offset
|
|
lda user_cache ;set cache to user setting
|
|
sta drvr_cache
|
|
pla
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;send_info This routine is called when we need to return the
|
|
; informational parameters from a directory entry.
|
|
; This routine is called by 'OPEN' and 'GET_FILE_INFO'
|
|
;WARNING:
|
|
; This routine assumes parameters are in a certain order.
|
|
; I did this so I could use that same routine across several
|
|
; calls!
|
|
;
|
|
;Input: A = number of entries to send
|
|
; X = low word pointer to start of parameters
|
|
; Y = high word pointer to start of parameters
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; one_entry (contians the info to send)
|
|
; drvr_buf_ptr (points to resource header block)
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
; math_temp
|
|
; temp_ptr
|
|
; one_entry
|
|
; time_routines
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT send_info
|
|
send_info PROC
|
|
|
|
stx temp_ptr
|
|
sty temp_ptr+2
|
|
|
|
;Save the number of entries the user wants.
|
|
|
|
sta math_temp
|
|
tax
|
|
bne continue
|
|
rts
|
|
|
|
;First we return the access as it is stored on disk.
|
|
|
|
continue ;
|
|
lda call_number ;is this a class one call?
|
|
and #$2000
|
|
beq class0
|
|
|
|
lda one_entry ;is this a volume entry?
|
|
and #$00F0 ;isolate the storage type
|
|
cmp #volume_header
|
|
bne not_vol
|
|
|
|
stz one_entry+aux_type_index
|
|
|
|
not_vol ;
|
|
cmp #subdir_type ;is it a subdir or volume?
|
|
bcc class0 ;no
|
|
|
|
stz one_entry+blks_used_index
|
|
|
|
class0 ;
|
|
ldy #pblk_s_access
|
|
lda one_entry+access_index
|
|
and #$00E7
|
|
sta [temp_ptr],y
|
|
dec math_temp
|
|
bne send_two
|
|
end_send1
|
|
clc
|
|
rts
|
|
|
|
;If we are here then we know the user wants the file type as well
|
|
|
|
send_two ;
|
|
ldy #pblk_s_ftype
|
|
lda one_entry+file_type_index
|
|
and #$00FF
|
|
sta [temp_ptr],y
|
|
dec math_temp
|
|
beq end_send1
|
|
|
|
;Now the user wants the aux type!
|
|
|
|
ldy #pblk_s_aux
|
|
lda one_entry+aux_type_index
|
|
sta [temp_ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [temp_ptr],y
|
|
dec math_temp
|
|
beq end_send1
|
|
|
|
;Also send the storage type of the file
|
|
|
|
ldy #pblk_s_storage
|
|
lda one_entry
|
|
and #$00F0
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
sta [temp_ptr],y
|
|
dec math_temp
|
|
beq end_send1
|
|
|
|
;Now convert the create date and send it to.
|
|
|
|
send_five ;
|
|
|
|
ldx one_entry+create_index
|
|
ldy one_entry+create_index+2
|
|
jsr unpack_time
|
|
ldy #pblk_s_create
|
|
jsr send_time
|
|
dec math_temp
|
|
beq end_send1
|
|
|
|
;Now convert the modification data and time
|
|
|
|
ldx one_entry+last_mod_index
|
|
ldy one_entry+last_mod_index+2
|
|
jsr unpack_time
|
|
ldy #pblk_s_mod
|
|
jsr send_time
|
|
dec math_temp
|
|
beq @go_to_end
|
|
|
|
; We now store the ProDOS FST ID in the 5th byte of the option list buffer
|
|
|
|
ldy #pblk_s_opt ;index to option list pointer
|
|
lda [temp_ptr],y ;get the address of the option list buffer
|
|
tax
|
|
iny
|
|
iny
|
|
lda [temp_ptr],y
|
|
tay
|
|
bne @save_fst_id
|
|
txa
|
|
beq @skip_save
|
|
@save_fst_id
|
|
pei temp_ptr ;save the working temp_ptr since I am going to use it
|
|
pei temp_ptr+2 ;to handle the option list pointer
|
|
|
|
stx temp_ptr
|
|
sty temp_ptr+2
|
|
;
|
|
;Now I need to verify the option list length. I need at least 6 bytes.
|
|
;
|
|
lda [temp_ptr] ;get the length of the option list
|
|
cmp #$0004 ;is the minimum count OK
|
|
bcc opt_range_err ;the user doesn't even have the minimum size>>>>
|
|
|
|
tax ;save the count for data area check
|
|
lda #$0002 ;length of the ProDOS FST ID.
|
|
tay
|
|
sta [temp_ptr],y ;save the number of bytes stored
|
|
txa
|
|
cmp #$0006
|
|
bcc opt_size_error
|
|
iny
|
|
iny
|
|
lda #pro_id
|
|
sta [temp_ptr],y
|
|
;new code added 2/13/91 CAE
|
|
txa
|
|
cmp #6+32 ;is buffer big enough to hold HFS Finder Info?
|
|
bcc @no_info ;no
|
|
lda one_entry ;yes - so check storage type
|
|
and #$00F0
|
|
cmp #resource_type ;is it a resource file?
|
|
bne @no_info ;no - so no HFS info
|
|
jsr get_hfs_info ;yes - so get the HFS info if we have it
|
|
@no_info
|
|
;end of new code
|
|
pla
|
|
sta temp_ptr+2 ;restore
|
|
pla
|
|
sta temp_ptr
|
|
@skip_save
|
|
dec math_temp ;Option List is included in PCount
|
|
@go_to_end beq end_send
|
|
|
|
;Give the EOF as well. If the storage type is a resource file then I will
|
|
;get the EOF info from the resource block instead of the directory entry
|
|
|
|
ldy #pblk_s_storage
|
|
lda one_entry
|
|
and #$00F0
|
|
cmp #resource_type
|
|
beq send_res_eof
|
|
|
|
ldy #pblk_s_eof ;send the EOF for the file
|
|
lda one_entry+eof_index+2
|
|
and #$00FF
|
|
tax
|
|
lda one_entry+eof_index
|
|
jsr store_longword
|
|
dec math_temp
|
|
beq end_send
|
|
|
|
ldy #pblk_s_blks ;send the number of blocks used
|
|
lda one_entry+blks_used_index
|
|
ldx #$0000
|
|
jsr store_longword
|
|
dec math_temp
|
|
beq end_send
|
|
|
|
ldy #pblk_s_res_eof ;send the resource eof
|
|
backup ;
|
|
lda #$0000
|
|
tax
|
|
jsr store_longword
|
|
dec math_temp
|
|
beq end_send
|
|
|
|
ldy #pblk_s_res_blk ;send the number of blocks used by res
|
|
bra backup ;please send a zero Mr. ProDOS.
|
|
|
|
end_send clc
|
|
rts
|
|
|
|
opt_range_err
|
|
pla
|
|
sta temp_ptr+2 ;restore
|
|
pla
|
|
sta temp_ptr
|
|
|
|
lda #parm_range_err
|
|
sec
|
|
rts
|
|
|
|
opt_size_error
|
|
pla
|
|
sta temp_ptr+2 ;restore
|
|
pla
|
|
sta temp_ptr
|
|
|
|
lda #buff_too_small
|
|
sec
|
|
rts
|
|
|
|
;Send the EOF and blocks used from the header block.
|
|
|
|
send_res_eof ;
|
|
ldy #$0000 ;go get the info please from fork 1
|
|
jsr get_res_info ;A/X = EOF, Y = Blocks Used
|
|
phy ;save the blocks used field
|
|
ldy #pblk_s_eof ;send the EOF for the file
|
|
jsr store_longword
|
|
ldy #pblk_s_blks ;send the Blocks used
|
|
|
|
pla ;restore the Blocks used field
|
|
dec math_temp ;now see if they want blocks used.
|
|
beq end_res_send ;not today kind sir.
|
|
|
|
ldx #$0000
|
|
jsr store_longword
|
|
dec math_temp ;are we done
|
|
beq end_res_send
|
|
|
|
ldy #$0100 ;go get the info please from fork 2
|
|
jsr get_res_info ;A/X = EOF, Y = Blocks Used
|
|
phy
|
|
ldy #pblk_s_res_eof ;send the EOF for the file
|
|
jsr store_longword
|
|
ldy #pblk_s_res_blk ;send the Blocks used
|
|
|
|
pla ;restore the Blocks used field
|
|
dec math_temp ;are we done
|
|
beq end_res_send
|
|
|
|
ldx #$0000 ;send the blocks used by the res. fork
|
|
jsr store_longword
|
|
|
|
end_res_send ;
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Grab the information from the resource block. first fork starts at
|
|
;offset $0000 in the header block. The second fork starts at offset $0100
|
|
;in the resource header block.
|
|
;
|
|
;format: storage_type (1 byte)
|
|
; key_block (2 bytes)
|
|
; blocks_used (2 bytes)
|
|
; eof (3 bytes)
|
|
|
|
get_res_info ;
|
|
lda [drvr_buf_ptr],y
|
|
and #$0003 ;check the storage type
|
|
beq file_dead ;this file is DOA
|
|
cmp #(tree_type/$10)+1
|
|
bcs file_dead
|
|
iny ;point to Key Block
|
|
|
|
iny
|
|
iny ;point to Blocks used
|
|
lda [drvr_buf_ptr],y
|
|
pha ;save blocks used for later
|
|
|
|
iny
|
|
iny ;point to EOF
|
|
lda [drvr_buf_ptr],y
|
|
pha ;save EOF low
|
|
iny
|
|
iny
|
|
lda [drvr_buf_ptr],y
|
|
and #$00FF ;clear any garbage
|
|
tax ;save EOF high
|
|
pla ;A = EOF Low
|
|
ply ;Y = Blocks used
|
|
rts ;A/X = EOF (A = Low) Y = Blocks Used
|
|
|
|
file_dead ;
|
|
sec ;sorry bad news
|
|
lda #bad_store_type
|
|
jmp main_exit ;no escape now!
|
|
|
|
|
|
;==========================================================================
|
|
;Get the HFS Finder Info if it has been stored in the resource block.
|
|
;The Finder Info is stored immediately after the mini-entry for the data fork,
|
|
;so it begins at offset $0008 in the block.
|
|
;
|
|
;format: entry size (1 byte)
|
|
; entry type (1 byte)
|
|
; HFS Finder Info (16 bytes)
|
|
; entry size (1 byte)
|
|
; entry type (1 byte)
|
|
; HFS Finder Info (16 bytes)
|
|
;
|
|
; entry_size = 18
|
|
; entry_type = 1 for first 16 bytes of Finder Info (FInfo)
|
|
; 2 for second 16 bytes of Finder Info (xFInfo)
|
|
;
|
|
;Note - the ProDOS FSM which runs on the Mac, has the ability to store only
|
|
; the first 16 bytes of Finder Info or only the second 16 bytes. So, we
|
|
; can't assume that both entries exist, or that they exist in a specific
|
|
; order.
|
|
;==========================================================================
|
|
entry get_hfs_info
|
|
get_hfs_info ;added 2/13/91 CAE
|
|
stz hfs_flag ;indicate that we have no HFS info
|
|
|
|
ldx #30
|
|
@zero_loop stz hfs_finfo,x ;zero out storage area for HFS info
|
|
dex ;since we may only find 1 entry
|
|
dex
|
|
bpl @zero_loop
|
|
|
|
ldy #8
|
|
@loop lda [drvr_buf_ptr],y ;get entry size from resource block
|
|
and #$00ff ;only want 1 byte
|
|
cmp #18 ;is it the right size for HFS info?
|
|
bne @done ;no - so we're done
|
|
iny
|
|
lda [drvr_buf_ptr],y ;yes - so get the entry type
|
|
and #$00ff ;only want 1 byte
|
|
cmp #finfo_type ;is it the first 16 bytes of HFS info?
|
|
bne @cont ;no
|
|
ldx #0 ;yes - so init index into storage area
|
|
jsr get_finfo ;and get the info
|
|
bra @loop ;loop
|
|
|
|
@cont cmp #xfinfo_type ;is it the second 16 bytes of HFS info?
|
|
bne @done ;no - so we're done
|
|
ldx #16 ;yes - so init index into storage area
|
|
jsr get_finfo ;and get the info
|
|
bra @loop ;loop
|
|
|
|
@done lda hfs_flag ;did we find any HFS info?
|
|
beq @exit ;no - so nothing to copy
|
|
|
|
ldx #0 ;init offsets
|
|
ldy #6
|
|
@copy_loop lda hfs_finfo,x ;copy the HFS Finder Info into the
|
|
sta [temp_ptr],y ;option list buffer
|
|
iny
|
|
iny
|
|
inx
|
|
inx
|
|
cpx #32
|
|
bcc @copy_loop
|
|
|
|
ldy #2
|
|
lda #2+32
|
|
sta [temp_ptr],y ;adjust the # of bytes stored
|
|
|
|
@exit rts ;return
|
|
|
|
|
|
get_finfo iny ;adjust offset
|
|
lda #8 ;we're going to copy 8 words
|
|
@loop pha ;save counter
|
|
lda [drvr_buf_ptr],y ;copy HFS Finder Info
|
|
sta hfs_finfo,x ;into storage area
|
|
iny ;adjust offsets
|
|
iny
|
|
inx
|
|
inx
|
|
pla ;retrieve counter
|
|
dec a
|
|
bne @loop ;loop until done
|
|
inc hfs_flag ;indicate that we found some HFS info
|
|
rts ;and return
|
|
|
|
|
|
;==========================================================================
|
|
|
|
store_longword ;
|
|
sta [temp_ptr],y ;store low order 16 bits of EOF
|
|
iny
|
|
iny
|
|
txa ;now store the upper 16 bits
|
|
and #$00FF
|
|
sta [temp_ptr],y
|
|
rts
|
|
|
|
|
|
;======================================================================
|
|
;This routine will store the time into the user's parameters block
|
|
|
|
EXPORT send_time
|
|
send_time ;
|
|
lda minutes
|
|
xba ;swap minutes and seconds
|
|
sta [temp_ptr],y
|
|
iny
|
|
iny
|
|
lda hours
|
|
sta [temp_ptr],y
|
|
iny
|
|
lda year
|
|
sta [temp_ptr],y
|
|
iny
|
|
lda day
|
|
beq zero_day ;the day is unknown
|
|
dec a ;convert to misc. tools hex format
|
|
zero_day ;
|
|
sta [temp_ptr],y
|
|
iny
|
|
lda month
|
|
beq zero_month
|
|
dec a ;convert to misc. tools hex format
|
|
zero_month ;
|
|
sta [temp_ptr],y
|
|
iny
|
|
lda day_of_week
|
|
xba ;swap day of week and null byte
|
|
sta [temp_ptr],y
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;chk_protected: This routine will see if a volume is write protected.
|
|
;
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; drvr_dev_num ;must be setup.
|
|
;
|
|
;Output: A = status Word ;see if driver ERS
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
;
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT chk_protected
|
|
chk_protected PROC
|
|
|
|
jsr save_drvr
|
|
|
|
lda #drvr_status ;issue a status call to the device
|
|
sta drvr_call_num
|
|
|
|
lda #^status_list ;setup a pointer to the status list
|
|
sta drvr_slist_ptr+2
|
|
lda #status_list
|
|
sta drvr_slist_ptr
|
|
|
|
lda #$0006 ;a six byte request count
|
|
sta drvr_req_cnt
|
|
stz drvr_req_cnt+2
|
|
lda #blk_size
|
|
sta drvr_blk_size
|
|
|
|
stz drvr_stat_code ;issue a 'driver status' call.
|
|
jsr device_call ;blast off!!
|
|
bcs status_error ;An error?
|
|
|
|
lda status_list ;get the return status
|
|
status_error php
|
|
pha
|
|
jsr restore_drvr
|
|
pla
|
|
plp
|
|
rts
|
|
|
|
save_drvr ldx #drvr_bytes ;number of bytes to save
|
|
save_it lda drvr_dev_num,x
|
|
sta drvr_save,x
|
|
dex
|
|
bpl save_it
|
|
rts
|
|
|
|
restore_drvr ldx #drvr_bytes
|
|
restore_it lda drvr_save,x
|
|
sta drvr_dev_num,x
|
|
dex
|
|
bpl restore_it
|
|
rts
|
|
|
|
EXPORT chk_disk_protect
|
|
chk_disk_protect
|
|
stz chk_prot_swap ; haven't got disk switched yet (20-Dec-91 MSD)
|
|
|
|
lda my_vcr_ptr ;see if we have a VCR
|
|
ora my_vcr_ptr+2
|
|
beq do_chk ;go ahead and do the check
|
|
|
|
ldy #vcr_status ;do I need to status the disk?
|
|
lda [my_vcr_ptr],y
|
|
and #vcr_wr_enable
|
|
beq do_chk ;yes we need to check the media
|
|
rts ;just return to the caller
|
|
|
|
do_chk ;
|
|
jsr chk_protected ;is the disk protected?
|
|
bcs big_problem
|
|
tax
|
|
and #$0010 ;is the disk offline?
|
|
beq not_in_drive ;there is no disk!!!
|
|
txa
|
|
and #$0001 ;disk switched??
|
|
bne not_in_drive ;disk has been switched!
|
|
txa
|
|
and #disk_protect
|
|
bne is_protected
|
|
|
|
lda my_vcr_ptr ;see if we have a VCR
|
|
ora my_vcr_ptr+2
|
|
beq no_change ;go ahead and set the vcr status flag
|
|
|
|
ldy #vcr_status ;set the 'No Status' bit
|
|
lda [my_vcr_ptr],y
|
|
ora #vcr_wr_enable ;no need to do the status next time
|
|
sta [my_vcr_ptr],y
|
|
|
|
no_change txa ;restore original status word
|
|
rts
|
|
|
|
|
|
is_protected sec
|
|
lda #drvr_wr_prot ;return write protect error to caller
|
|
|
|
big_problem jmp main_exit
|
|
|
|
not_in_drive
|
|
;
|
|
; Begin 20-Dec-91 MSD
|
|
;
|
|
; We got a disk switched status, so try to find the volume (ask the user if necessary).
|
|
; This will force a new VCR to be built, and my_vcr_ptr will point to it.
|
|
;
|
|
lda chk_prot_swap ; already switched once?
|
|
bne do_disk_sw ; yes, so return disk switched error
|
|
|
|
inc chk_prot_swap ; found one disk swithced status
|
|
|
|
*** added 28-Feb-92 DAL and GAB -- Save GBUF and important direct page stuff
|
|
jsr save_drvr
|
|
pei <gbuf_ptr+2
|
|
pei <gbuf_ptr
|
|
pea chk_protect_gbuf>>16
|
|
pea chk_protect_gbuf
|
|
pea 0
|
|
pea $0200 ; move 512 bytes
|
|
pea move_sinc_dinc
|
|
jsl move_info
|
|
*** end 28-Feb-92, part one
|
|
|
|
jsr mount_volume ; find the volume and build a VCR for it
|
|
|
|
*** added 28-Feb-92 DAL and GAB -- Restore GBUF and important direct-page stuff
|
|
php
|
|
pha
|
|
jsr restore_drvr
|
|
pea chk_protect_gbuf>>16
|
|
pea chk_protect_gbuf
|
|
pei <gbuf_ptr+2
|
|
pei <gbuf_ptr
|
|
pea 0
|
|
pea $0200 ; move 512 bytes
|
|
pea move_sinc_dinc
|
|
jsl move_info
|
|
pla
|
|
plp
|
|
*** end 28-Feb-92, part two
|
|
bcs big_problem ; better not be an error (we already found the path)
|
|
|
|
bra do_chk ; try the status again
|
|
|
|
do_disk_sw
|
|
sec
|
|
lda #drvr_disk_sw ; give up, 2 consecutive disk switched statuses
|
|
bra big_problem
|
|
|
|
;
|
|
; End 20-Dec-91 MSD
|
|
;
|
|
; The following code was commented out because we should really retry the status call.
|
|
;
|
|
; ldy #vcr_dev ;update the VCR status please
|
|
; lda [my_vcr_ptr],y
|
|
; cmp drvr_dev_num ;is this the same device?
|
|
; bne just_exit ;no
|
|
; ldy #vcr_status ;mark volume swapped
|
|
; lda [my_vcr_ptr],y
|
|
; ora #vcr_swapped ;disk has been removed from drive
|
|
; sta [my_vcr_ptr],y
|
|
;just_exit ;
|
|
; txa ;original status word
|
|
; rts
|
|
|
|
chk_prot_swap dc.w 0 ; flag for disk switched (20-Dec-91 MSD)
|
|
|
|
ENDP
|
|
;======================================================================
|
|
;Mount_volume: This routine is called when we need to force the user
|
|
; To give us our disk back.
|
|
;
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; my_vcr_ptr (points to needed VCR)
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
; find_volume
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT mount_volume
|
|
mount_volume PROC
|
|
|
|
jsr save_the_world ;save alot of data.
|
|
jsr setup_vol_mesg ;move the VCR name to local buffer
|
|
|
|
try_again jsr find_volume ;go get the volume
|
|
bcc volume_online ;go and update everything
|
|
jsr issue_mount ;issue a mount request
|
|
bcc try_again ;user said volume is now online
|
|
jsr restore_world ;restore everything please
|
|
rts
|
|
|
|
volume_online lda drvr_dev_num ;where the volume was found
|
|
jsr restore_world ;A is saved
|
|
sta drvr_dev_num
|
|
|
|
ldy #vcr_dev ;update with the new device number
|
|
sta [my_vcr_ptr],y
|
|
ldy #vcr_status ;indicate that the volume is online
|
|
lda [my_vcr_ptr],y
|
|
and #vcr_swapped_in
|
|
sta [my_vcr_ptr],y
|
|
clc
|
|
rts ;volume is back on-line
|
|
|
|
save_the_world php
|
|
phy
|
|
phx
|
|
pha
|
|
|
|
lda world_flag ;see if data already saved
|
|
bne to_sys_death ;debug
|
|
inc world_flag
|
|
|
|
ldx #$004A ;save the direct page data
|
|
save_direct lda drvr_dev_num,x
|
|
sta direct_page,x
|
|
dex
|
|
bpl save_direct
|
|
|
|
ldx #$0052 ;save my direct page
|
|
save_my_direct lda fst_start,x
|
|
sta my_direct,x
|
|
dex
|
|
bpl save_my_direct
|
|
|
|
bra save_rest_exit
|
|
|
|
restore_world php
|
|
phy
|
|
phx
|
|
pha
|
|
|
|
ldx #$004A ;save the direct page data
|
|
restore_direct lda direct_page,x
|
|
sta drvr_dev_num,x
|
|
dex
|
|
bpl restore_direct
|
|
|
|
ldx #$0052 ;save my direct page
|
|
restore_dp lda my_direct,x
|
|
sta fst_start,x
|
|
dex
|
|
bpl restore_dp
|
|
|
|
dec world_flag
|
|
|
|
save_rest_exit pla
|
|
plx
|
|
ply
|
|
plp
|
|
rts
|
|
|
|
|
|
to_sys_death jsl sys_death
|
|
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;build_path: This procedure will parse off the volume name out of a
|
|
; pathname if needed.
|
|
;
|
|
;Input: A = AND mask used on path_flag ($BFFF or $FFBF)
|
|
; X = low word pointer to pathname
|
|
; Y = high word pointer to pathname
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; path_flag ;GS/OS parameter (See common equates)
|
|
; dev_num ;GS/OS parameter
|
|
;
|
|
;Output: A = undefined
|
|
; X = low word pointer to pathname
|
|
; Y = high word pointer to pathname
|
|
; P = nvmxdizc
|
|
; ..000..1 = no pathname (device # or vol name only)
|
|
; 0 = X and Y contain a pathname pointer
|
|
; b = k
|
|
;
|
|
; volume_name ;if volume name is available
|
|
|
|
; ;e.g. no device number is given
|
|
;
|
|
;Uses: All registers
|
|
; temp_ptr
|
|
; path_flag
|
|
; dev_num
|
|
; and_mask
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT build_path
|
|
build_path PROC
|
|
|
|
sta and_mask ;setup by caller
|
|
|
|
;now adjust the pointer to point past the length word
|
|
|
|
inx
|
|
bne do_again
|
|
iny
|
|
do_again inx
|
|
bne cont
|
|
iny
|
|
|
|
cont
|
|
stx temp_ptr
|
|
sty temp_ptr+2 ;pointer to pathname
|
|
|
|
lda path_flag ;see if there is a pathname to process
|
|
and and_mask
|
|
bne proc_path ;there is a pathname so handle it
|
|
sec
|
|
rts ;device number the only thing available
|
|
|
|
proc_path ;
|
|
lda dev_num ;see if there is a device
|
|
beq no_device ;no device so isolate volume name
|
|
;tell caller device # and pathname
|
|
done
|
|
jsr set_case_bits ;save the case bits as needed please and convert to upper case
|
|
clc
|
|
rts
|
|
|
|
no_device ;
|
|
jsr vol_to_buffer ;out: A = terminator Y = length
|
|
pha ;save termination reason
|
|
iny
|
|
iny
|
|
tya ;length of name +1
|
|
ldy temp_ptr+2
|
|
clc
|
|
adc temp_ptr
|
|
tax
|
|
bcc do_end
|
|
iny ;adjust high word
|
|
do_end
|
|
pla ;restore terminator
|
|
bne done ;tell caller volume name and pathname!
|
|
pha
|
|
jsr set_case_bits ;set the case of the last path please
|
|
pla
|
|
sec ;tell caller volume name only!
|
|
rts
|
|
|
|
EXPORT vol_to_buffer
|
|
vol_to_buffer ;'build_path' has setup temp_ptr
|
|
ldy #$0001 ;to point past '/' in volume name
|
|
vol_name_loop
|
|
lda [temp_ptr],y
|
|
and #$00FF
|
|
beq loop_end ;we have hit the last character
|
|
cmp #delimiter ;see if it is a seperator
|
|
beq loop_end
|
|
|
|
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
cmp #$0020
|
|
bne @not_blank
|
|
lda #$002E ;make a blank into a period
|
|
@not_blank
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
cmp #$0061 ;check if we need to convert to upper case. "a"
|
|
bcc @no_upper
|
|
cmp #$007B ;check "z"+1
|
|
bcs @no_upper
|
|
and #$00DF ;convert to upper case
|
|
@no_upper
|
|
sta volume_name+1,y ;store name in buffer
|
|
iny
|
|
cpy #$0011 ;is length > 15 characters? -- 1/12/92 AEN
|
|
bcc vol_name_loop ;no, keep copying
|
|
lda #bad_path_syntax ;else we've got a bad pathname
|
|
sec
|
|
jmp main_exit
|
|
|
|
loop_end
|
|
tax ;save the terminating reason
|
|
lda #$0000 ;terminate the string with a null byte
|
|
sta volume_name+1,y
|
|
dey ;adjust string length
|
|
sty volume_name
|
|
txa
|
|
rts
|
|
;
|
|
;This routine will save the case bits for the last piece of the pathname and
|
|
;will convert the input string to all uppercase.
|
|
;
|
|
Export set_case_bits
|
|
set_case_bits
|
|
pha
|
|
phx
|
|
phy
|
|
|
|
|
|
ldy #$0000 ;start at the first character please
|
|
@outter_loop
|
|
lda #$4000 ;arm the case bit mask please
|
|
sta case_bit_pattern
|
|
stz case_bits
|
|
@inner_loop
|
|
lda [temp_ptr],y ;get the user's input character please
|
|
and #$00FF ;now check delimiters
|
|
beq @end_of_string
|
|
cmp #delimiter
|
|
beq @next_part ;do the next part of the path please
|
|
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
cmp #' '
|
|
bne @not_a_blank
|
|
lda #'.'
|
|
bra @was_a_blank
|
|
@not_a_blank
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
cmp #$0061 ;check if we need to convert to upper case. "a"
|
|
bcc @no_upper
|
|
cmp #$007B ;check "z"+1
|
|
bcs @no_upper
|
|
and #$00DF ;convert to upper case
|
|
@was_a_blank tax ;save the character please
|
|
lda case_bit_pattern
|
|
ora case_bits
|
|
sta case_bits ;save the case bit for this character
|
|
txa
|
|
@no_upper
|
|
sep #$20 ;8 Bit store
|
|
sta [temp_ptr],y ;save the character back please
|
|
rep #$20 ;back to 16 bit mode
|
|
lsr case_bit_pattern
|
|
iny ;move to the next position please
|
|
bra @inner_loop
|
|
|
|
@next_part
|
|
iny ;advance to the next part of the pathname
|
|
bra @outter_loop
|
|
|
|
@end_of_string
|
|
ply
|
|
plx
|
|
pla
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;Move_vol_name: This routine will move the volume name pointed to by
|
|
; drvr_buf_ptr into the buffer pointed to by the address
|
|
; in the X and Y registers
|
|
;
|
|
;Input: A = undefined
|
|
; X = low word pointer to the destination buffer
|
|
; Y = high word pointer to the destination buffer
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; drvr_buf_ptr ;points to the volume header in blk two
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; temp_ptr
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT move_vol_name
|
|
move_vol_name PROC
|
|
|
|
stx temp_ptr
|
|
sty temp_ptr+2
|
|
|
|
lda [drvr_buf_ptr]
|
|
and #$000F ;isolate name length
|
|
sta [temp_ptr] ;save the length in word format
|
|
tay
|
|
|
|
clc
|
|
lda temp_ptr
|
|
adc #$0002
|
|
sta temp_ptr
|
|
bcc ar1
|
|
inc temp_ptr+2
|
|
ar1 ;
|
|
|
|
longa off
|
|
sep #$20
|
|
move_loop ;
|
|
lda [drvr_buf_ptr],y
|
|
sta [temp_ptr],y
|
|
dey
|
|
bne move_loop
|
|
|
|
longa on
|
|
rep #$20
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;set_default_buf: sets up the default buffer pointer
|
|
;
|
|
;
|
|
;Enter: 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: A register
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT set_default_buf
|
|
set_default_buf PROC
|
|
|
|
lda gbuf_addr ;setup the general I/O buffer
|
|
sta drvr_buf_ptr
|
|
lda gbuf_addr+2
|
|
sta drvr_buf_ptr+2
|
|
rts
|
|
|
|
EXPORT standard_req
|
|
standard_req ;
|
|
lda #blk_size
|
|
sta drvr_req_cnt
|
|
stz drvr_req_cnt+2
|
|
rts
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;setup_my_vcr: this routine sets up a pointer to the prodos specific
|
|
; volume control record.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; my_vcr_ptr (Points to main VCR)
|
|
;
|
|
;Output: A = undefined
|
|
; X = low word of prodos vcr
|
|
; Y = high word of prodos vcr
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
; my_vcr_ptr
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT setup_my_vcr
|
|
setup_my_vcr PROC
|
|
|
|
clc
|
|
lda my_vcr_ptr
|
|
adc #vcr_dev+2 ;start of local data for vcr
|
|
tax
|
|
lda my_vcr_ptr+2
|
|
adc #$0000
|
|
tay
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;setup_my_fcr: this routine sets up a pointer to the prodos specific
|
|
; file control record data.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; my_fcr_ptr (Points to main FCR)
|
|
;
|
|
;Output: A = undefined
|
|
; X = low word of prodos fcr
|
|
; Y = high word of prodos fcr
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
; my_fcr_ptr
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT setup_my_fcr
|
|
setup_my_fcr PROC
|
|
|
|
clc
|
|
lda my_fcr_ptr
|
|
adc #fcr_access+2 ;start of local data for fcr
|
|
tax
|
|
lda my_fcr_ptr+2
|
|
adc #$0000
|
|
tay
|
|
rts
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;setup_io_ptrs this routine sets up pointers to the active data buffers
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; my_fcr_ptr (Points to main FCR)
|
|
; pro_fcr_ptr (points to specific data)
|
|
;
|
|
;Output: A = undefined
|
|
; X = low word of prodos vcr
|
|
; Y = high word of prodos vcr
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
; my_fcr_ptr
|
|
; math_temp
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT setup_io_ptrs
|
|
setup_io_ptrs PROC
|
|
|
|
stz data_ptr ;init the pointers
|
|
stz index_ptr
|
|
stz master_ptr
|
|
stz data_ptr+2
|
|
stz index_ptr+2
|
|
stz master_ptr+2
|
|
|
|
lda #fcr_io_start
|
|
sta math_temp ;save the start of the I/O buffer
|
|
|
|
ldy #fcr_status ;see if master index is active
|
|
lda [pro_fcr_ptr],y
|
|
and #master_active
|
|
beq no_master ;there is no master index block
|
|
|
|
clc
|
|
lda my_fcr_ptr
|
|
adc math_temp
|
|
sta master_ptr
|
|
lda my_fcr_ptr+2
|
|
adc #$0000
|
|
sta master_ptr+2
|
|
jsr next_block ;bump the pointer to the next block
|
|
|
|
no_master ;
|
|
ldy #fcr_status ;see if there is an index block
|
|
lda [pro_fcr_ptr],y
|
|
and #index_active
|
|
beq no_index ;there is no index block
|
|
|
|
clc
|
|
lda my_fcr_ptr
|
|
adc math_temp
|
|
sta index_ptr
|
|
lda my_fcr_ptr+2
|
|
adc #$0000
|
|
sta index_ptr+2
|
|
jsr next_block ;bump the pointer to the next block
|
|
|
|
no_index ;
|
|
ldy #fcr_status ;see if there is a data block
|
|
lda [pro_fcr_ptr],y
|
|
and #data_active
|
|
beq end_io_setup ;there is no data block
|
|
|
|
clc
|
|
lda my_fcr_ptr
|
|
adc math_temp
|
|
sta data_ptr
|
|
lda my_fcr_ptr+2
|
|
adc #$0000
|
|
sta data_ptr+2
|
|
|
|
end_io_setup ;
|
|
rts
|
|
|
|
next_block ;
|
|
clc
|
|
lda math_temp
|
|
adc #blk_size
|
|
sta math_temp
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;setup_bitmap_ptr: This routine will return a pointer to the bitmap
|
|
; buffer and setup 'bitmap' to point to the bitmap buffer
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; my_vcr_ptr (Points to main VCR)
|
|
;
|
|
;Output: A = undefined
|
|
; X = low word of bitmap
|
|
; Y = high word of bitmap
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; bitmap (bitmap pointer is setup)
|
|
;
|
|
;Uses: All registers
|
|
; my_vcr_ptr
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT setup_bitmap_ptr
|
|
setup_bitmap_ptr PROC
|
|
|
|
clc
|
|
lda my_vcr_ptr
|
|
adc #bitmap_start ;starting location of bitmap
|
|
sta bitmap
|
|
tax
|
|
lda my_vcr_ptr+2
|
|
adc #$0000
|
|
sta bitmap+2
|
|
tay
|
|
rts
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;clear_gbuf_low This routine will zero the lower half of the general
|
|
; buffer.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; gbuf_ptr
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
; gbuf_ptr
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT clear_gbuf_low
|
|
clear_gbuf_low PROC
|
|
|
|
lda #$0000
|
|
bra do_clear
|
|
EXPORT fill_gbuf_low
|
|
fill_gbuf_low ;
|
|
lda #$FFFF
|
|
|
|
do_clear ;
|
|
ldy #$01FE
|
|
clear ;
|
|
sta [gbuf_ptr],y
|
|
dey
|
|
dey
|
|
bpl clear
|
|
|
|
rts
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;clear_gbuf_hi. This routine will zero the upper half of the general
|
|
; buffer.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; gbuf_ptr
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
; gbuf_ptr
|
|
; temp3_ptr
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT clear_gbuf_high
|
|
clear_gbuf_high PROC
|
|
|
|
clc
|
|
lda gbuf_ptr
|
|
adc #$0200
|
|
sta temp3_ptr
|
|
lda gbuf_ptr+2
|
|
adc #$0000
|
|
sta temp3_ptr+2
|
|
|
|
ldy #$01FE
|
|
lda #$0000
|
|
clear ;
|
|
sta [temp3_ptr],y
|
|
dey
|
|
dey
|
|
bpl clear
|
|
|
|
rts
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;read_write_setup:
|
|
; this routine sets up common parameters between read/write
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; pcount ;for cache check
|
|
; my_pblk_ptr ;must be setup
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; user_buf_ptr
|
|
; user_req_cnt
|
|
; drvr_cache
|
|
; tran_cnt ;set to zero
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT read_write_setup
|
|
read_write_setup PROC
|
|
|
|
;Start code by turning off disk caching and setting up other parameters
|
|
lda user_cache
|
|
sta drvr_cache
|
|
stz tran_cnt
|
|
stz tran_cnt+2
|
|
|
|
lda pcount ;is cache priority avail?
|
|
cmp #$0005
|
|
bne no_cache
|
|
|
|
;If we get here then the user has provided a cache priority for the file.
|
|
;So we must verify that it is a legal value for caching.
|
|
|
|
get_priority ;
|
|
ldy #pblk_12_cache
|
|
lda [my_pblk_ptr],y
|
|
beq no_cache ;same as mine
|
|
cmp #user_cache_val
|
|
beq good_cache
|
|
bra param_err
|
|
|
|
good_cache ;
|
|
sta drvr_cache
|
|
|
|
;Setup a pointer to the user's buffer.
|
|
|
|
no_cache ;
|
|
|
|
ldy #pblk_12_buf
|
|
lda [my_pblk_ptr],y
|
|
sta users_buf_ptr
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
and #$00FF
|
|
sta users_buf_ptr+2
|
|
|
|
;Go ahead and zero the user's transfer count.
|
|
|
|
ldy #pblk_12_tran ;zero the transfer count
|
|
lda #$0000
|
|
sta [my_pblk_ptr],y
|
|
iny
|
|
iny
|
|
sta [my_pblk_ptr],y
|
|
|
|
;Now lets get the user's request count.
|
|
|
|
ldy #pblk_12_req
|
|
lda [my_pblk_ptr],y
|
|
sta user_req_cnt
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
sta user_req_cnt+2
|
|
tax
|
|
and #$FF00 ;is high byte zero?
|
|
beq good_cnt
|
|
|
|
param_err ;
|
|
sec
|
|
lda #parm_range_err
|
|
bra to_scm
|
|
|
|
;Handle the easy case of a request count of zero first.
|
|
|
|
good_cnt ;
|
|
txa
|
|
ora user_req_cnt
|
|
bne not_zero
|
|
clc
|
|
to_scm ;
|
|
jmp main_exit
|
|
|
|
not_zero ;
|
|
rts
|
|
ENDP
|
|
|
|
|
|
EXPORT rw_adjust
|
|
rw_adjust PROC ;read/write adjust
|
|
|
|
;==========================================================================
|
|
;adjust the buffer pointer by the number of bytes read
|
|
;
|
|
;IMPORTANT NOTES:
|
|
; drvr_req_cnt is always =< $0001FE00
|
|
; users_buf_ptr is always < $00FFFFFF
|
|
;
|
|
clc
|
|
lda users_buf_ptr
|
|
adc drvr_req_cnt
|
|
sta users_buf_ptr
|
|
lda users_buf_ptr+2
|
|
adc drvr_req_cnt+2
|
|
sta users_buf_ptr+2
|
|
|
|
;==========================================================================
|
|
;adjust the total number of bytes read from file
|
|
;
|
|
;IMPORTANT NOTES:
|
|
; tran_cnt is always =< $00FFFFFF
|
|
; drvr_req_cnt is always =< $0001FE00
|
|
;
|
|
;Carry is clear from the above addition.
|
|
|
|
lda tran_cnt
|
|
adc drvr_req_cnt
|
|
sta tran_cnt
|
|
lda tran_cnt+2
|
|
adc drvr_req_cnt+2
|
|
sta tran_cnt+2
|
|
|
|
;==========================================================================
|
|
;adjust the current file marker
|
|
;
|
|
;IMPORTANT NOTES:
|
|
; curr_mark is always =< $00FFFFFF
|
|
; drvr_req_cnt is always =< $0001FE00
|
|
;
|
|
|
|
lda curr_mark
|
|
adc drvr_req_cnt
|
|
sta curr_mark
|
|
lda curr_mark+2
|
|
adc drvr_req_cnt+2
|
|
sta curr_mark+2
|
|
|
|
;adjust the number of bytes remaining to send
|
|
|
|
sec
|
|
lda user_req_cnt
|
|
sbc drvr_req_cnt
|
|
sta user_req_cnt
|
|
lda user_req_cnt+2
|
|
sbc drvr_req_cnt+2
|
|
sta user_req_cnt+2
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;entry_to_offset This routine will convert the data from a directory
|
|
; header to an offset.
|
|
;
|
|
;Input: A = entry_number
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = entry_offset
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
|
|
longa on
|
|
longi on
|
|
EXPORT entry_to_offset
|
|
entry_to_offset PROC
|
|
|
|
and #$00FF
|
|
dec a
|
|
cmp #$000D ;is it out of range?
|
|
bcs error
|
|
asl a
|
|
tay
|
|
lda dir_offset_tbl,y
|
|
clc
|
|
error ;
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;Issue Mount:calls the Mount_Message Routine with a pointer to the name
|
|
; stored in Volume_name.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; volume_name ;must be setup
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; Mount_Message
|
|
;
|
|
|
|
EXPORT issue_mount
|
|
issue_mount PROC
|
|
|
|
lda volume_name
|
|
xba
|
|
sta volume_name
|
|
|
|
pea volume_name>>16
|
|
pea volume_name+1 ;push a pointer to the volume name
|
|
lda #$0001 ;1 = manditory mount!
|
|
jsl mount_message
|
|
tax ;get the result code
|
|
lda volume_name
|
|
xba
|
|
sta volume_name
|
|
txa ;restore result code 0 = ok 1 = cancel
|
|
bne cancel_mount
|
|
|
|
clc ;user selected OK
|
|
rts
|
|
|
|
cancel_mount ;
|
|
sec ;return volume not found error to user
|
|
lda #vol_not_found
|
|
rts
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;Damaged_message: This routine will tell the user that the disk cannot
|
|
; be written too. The routine will also jmp to the
|
|
; main exit routine.
|
|
;
|
|
;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
|
|
;
|
|
|
|
EXPORT damaged_message
|
|
damaged_message PROC
|
|
|
|
pha
|
|
jsr show_damage
|
|
jsl unlock_mem ;release any memory
|
|
sec
|
|
pla ;get the error code please
|
|
jml sys_exit
|
|
|
|
EXPORT show_damage
|
|
show_damage ;
|
|
jsr setup_vol_mesg ;move the name from the VCR to buffer
|
|
|
|
lda volume_name ;make Gstring a Pstring
|
|
xba
|
|
sta volume_name
|
|
|
|
pea $0003 ;message number three
|
|
pea volume_name>>16
|
|
pea volume_name+1 ;push a pointer to the volume name.
|
|
pea $0000
|
|
pea $0000 ;push dummy space.
|
|
jsl report_error
|
|
|
|
lda volume_name ;make Pstring a Gstring
|
|
xba
|
|
sta volume_name
|
|
rts
|
|
|
|
EXPORT setup_vol_mesg
|
|
setup_vol_mesg ;
|
|
ldy #vcr_name ;index to Name VP
|
|
lda [my_vcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [my_vcr_ptr],y
|
|
tay
|
|
jsl deref ;make a real pointer to vol name
|
|
stx temp_ptr
|
|
sty temp_ptr+2
|
|
|
|
lda [temp_ptr] ;get the length of the string
|
|
tay
|
|
iny
|
|
move_loop ;
|
|
lda [temp_ptr],y
|
|
sta volume_name,y
|
|
dey
|
|
bpl move_loop
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;read_with_mount:
|
|
; This routine with make a device read call and if an
|
|
; error occurs (other then the I/O error) the mount
|
|
; volume routine will be called.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; all parameters for the driver must be setup.
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; device_call
|
|
|
|
EXPORT read_with_mount
|
|
read_with_mount PROC
|
|
|
|
lda #drvr_read
|
|
bra do_call
|
|
|
|
EXPORT write_with_mount
|
|
write_with_mount
|
|
lda #drvr_write
|
|
|
|
do_call
|
|
sta drvr_call_num
|
|
jsr dev_with_mount
|
|
rts
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;read_with_cache:
|
|
;write_with_cache:
|
|
; This routine with make a device read/write call and
|
|
; store the data in the system cache. error occurs
|
|
; (other then the I/O error) the mount volume routine
|
|
; will be called.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; all parameters for the driver must be setup.
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; device_call
|
|
|
|
EXPORT read_with_cache
|
|
read_with_cache PROC
|
|
|
|
lda #drvr_read
|
|
bra continue
|
|
|
|
EXPORT write_with_cache
|
|
write_with_cache ;
|
|
lda #drvr_write
|
|
|
|
continue ;
|
|
sta drvr_call_num
|
|
|
|
lda [my_vcr_ptr] ;setup the Volume ID field
|
|
sta drvr_vol_id
|
|
|
|
lda drvr_cache ;save current cache setting
|
|
pha
|
|
lda #in_cache ;store this block in the cache
|
|
sta drvr_cache
|
|
|
|
jsr dev_with_mount
|
|
php ;save processor status 'A' = error code
|
|
tax ;save any error code
|
|
lda 2,s ;restore old cache value
|
|
sta drvr_cache
|
|
txa
|
|
plp ;restore carry bit
|
|
plx ;fix the stack
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;dev_with_mount This routine with make a device call and if an
|
|
; error occurs (other then the I/O error) the mount
|
|
; volume routine will be called.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; all parameters for the driver must be setup.
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; device_call
|
|
|
|
EXPORT dev_with_mount
|
|
dev_with_mount PROC
|
|
|
|
jsr device_call
|
|
bcs check_err
|
|
rts
|
|
check_err
|
|
cmp #drvr_disk_sw ;is this a disk switch error?
|
|
beq do_find ;go and find the volume please
|
|
cmp #drvr_off_line ;is the volume off-line?
|
|
beq do_find
|
|
sec
|
|
rts ;This is some real error from the user
|
|
do_find
|
|
jsr mount_volume
|
|
bcc dev_with_mount ;re-issue the original call please.
|
|
rts ;return the error please
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;Device_call:calls the dispatcher and trys to read or write. If the
|
|
; call returns a disk switched error then the routine will
|
|
; re-read the disk again.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; all parameters for the driver must be setup except for
|
|
; drvr_blk_size and drvr_fst_num, these are setup by the
|
|
; call. (ONLY if the call is a READ or WRITE)
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
;
|
|
|
|
EXPORT device_call
|
|
device_call PROC
|
|
|
|
lda drvr_call_num
|
|
cmp #drvr_status
|
|
bcs to_device ;just call the device
|
|
|
|
cmp #drvr_write
|
|
beq is_write
|
|
|
|
lda drvr_cache
|
|
and #$7FFF ;clear the deferred bit if not a write
|
|
sta drvr_cache
|
|
bra do_it
|
|
is_write
|
|
sta write_occurred ;indicate that a write occured during this call
|
|
lda drvr_dev_num ;save the device number that I have written too.
|
|
sta write_dev_num
|
|
do_it
|
|
lda #blk_size
|
|
sta drvr_blk_size
|
|
stz drvr_blk_num+2
|
|
|
|
to_device
|
|
jsl dev_dispatcher ;call the read routine
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;flush_bitmap: This routine forces a dirty bitmap to be written to
|
|
; disk. The bitmap will be written to disk only if the
|
|
; file counter is equal to zero.
|
|
;
|
|
;force_bitmap: same as flush_bitmap except the bitmap block is ALWAYS
|
|
; flushed.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; prodos_vcr_ptr
|
|
; my_vcr_ptr
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; drvr_buf_ptr
|
|
; dev_with_mount
|
|
;
|
|
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT flush_bitmap
|
|
flush_bitmap PROC
|
|
|
|
ldy #dirty_file_cnt ;see if there open files on disk?
|
|
lda [prodos_vcr_ptr],y
|
|
beq force_bitmap ;no open files so do flush.
|
|
clc
|
|
rts ;just exit.
|
|
|
|
EXPORT force_bitmap
|
|
force_bitmap ;This entry point force block to disk
|
|
|
|
ldy #bitmap_dirty
|
|
lda [prodos_vcr_ptr],y
|
|
beq no_change
|
|
|
|
;Get the device number first
|
|
|
|
ldy #vcr_dev
|
|
lda [my_vcr_ptr],y
|
|
sta drvr_dev_num
|
|
|
|
;We need to update the disk since the bitmap is corrupt
|
|
;First we calculate the block number of the block to write
|
|
|
|
ldy #vol_bitmap_addr
|
|
lda [prodos_vcr_ptr],y
|
|
ldy #curr_bitmap
|
|
clc
|
|
adc [prodos_vcr_ptr],y
|
|
sta drvr_blk_num
|
|
stz drvr_blk_num+2
|
|
|
|
;Get the address of where the bitmap block is located.
|
|
;setup drvr_buf_ptr to point to the bitmap buffer
|
|
|
|
jsr setup_bitmap_ptr
|
|
stx drvr_buf_ptr
|
|
sty drvr_buf_ptr+2
|
|
|
|
;setup the call to do a write
|
|
|
|
;Force the request count to 512 bytes
|
|
|
|
lda #blk_size
|
|
sta drvr_req_cnt
|
|
stz drvr_req_cnt+2
|
|
|
|
;Call the device.
|
|
jsr write_with_cache
|
|
bcc clear_dirty
|
|
rts
|
|
|
|
clear_dirty ;
|
|
ldy #bitmap_dirty
|
|
lda #$0000
|
|
sta [prodos_vcr_ptr],y
|
|
|
|
ldy #curr_bitmap ;see if this is first free block.
|
|
lda [prodos_vcr_ptr],y
|
|
|
|
ldy #avail_bitmap
|
|
cmp [prodos_vcr_ptr],y
|
|
bne no_change
|
|
inc a ;see if this is the last bitmap blk.
|
|
ldy #num_bitmap_blks
|
|
cmp [prodos_vcr_ptr],y
|
|
bcs no_change ;this is the last bitmap block
|
|
|
|
ldy #$01FE ;we must check first free
|
|
chk_first_free ;
|
|
lda [drvr_buf_ptr],y
|
|
bne no_change
|
|
dey
|
|
dey
|
|
bpl chk_first_free ;check the entire block please.
|
|
|
|
ldy #avail_bitmap ;bump avail to next block please
|
|
lda [prodos_vcr_ptr],y
|
|
inc a
|
|
sta [prodos_vcr_ptr],y
|
|
|
|
no_change ;
|
|
clc
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;flush_file: This routine will write any modified blocks to disk.
|
|
;
|
|
;Input: A = dev_number
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; pro_fcr_ptr (points to data to write)
|
|
; my_vcr_ptr (points to main VCR)
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
|
|
longa on
|
|
longi on
|
|
|
|
|
|
EXPORT flush_file
|
|
flush_file PROC
|
|
stz flush_entry ;indicate that we should flush everything
|
|
bra cont_flush
|
|
|
|
Entry do_fast_flush ;entry point used by the fast version of the flush call
|
|
do_fast_flush
|
|
lda #1 ;set flag
|
|
bra stuffit
|
|
|
|
EXPORT flush_io_Buffer
|
|
flush_io_buffer
|
|
lda #$FFFF ;do not flush the directory entry
|
|
stuffit
|
|
sta flush_entry
|
|
cont_flush
|
|
jsr standard_req
|
|
|
|
;First lets call flush bitmap which will update the bitmap for us
|
|
jsr flush_bitmap
|
|
bcs error_return ;return the error directly
|
|
|
|
;No we need to flush the file itself. We only flush blocks that need to
|
|
;be flushed. We will always update the file entry.
|
|
|
|
flushed ;
|
|
|
|
ldy #fcr_status ;get the status bits
|
|
lda [pro_fcr_ptr],y
|
|
sta flush_flags
|
|
bit #file_dirty ;see if there is anything to update
|
|
bne do_update
|
|
clc
|
|
error_return
|
|
rts ;file does not need to be updated
|
|
|
|
;First lets see if we need to update the master index block.
|
|
|
|
do_update
|
|
bit #master_dirty
|
|
beq check_index
|
|
|
|
ldy #master_blk_num ;get the block number
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num
|
|
beq clear_master ;master block is sparse so do not update disk
|
|
|
|
ldx master_ptr
|
|
ldy master_ptr+2
|
|
jsr flush_block
|
|
bcs error_return ;return the error code
|
|
|
|
clear_master ;
|
|
lda #master_clean
|
|
jsr clr_fcr_status ;mark master block as clean
|
|
|
|
;Update the index block if needed
|
|
|
|
check_index ;
|
|
lda flush_flags
|
|
bit #index_dirty ;is the index block dirty
|
|
beq check_data
|
|
jsr flush_index
|
|
bcs error_return
|
|
|
|
;Update the data block if needed.
|
|
|
|
check_data ;
|
|
lda flush_flags
|
|
bit #data_dirty ;is the data block dirty
|
|
beq update_entry
|
|
jsr flush_data_blk
|
|
bcs error_return
|
|
|
|
update_entry
|
|
lda flush_entry ;do we update the directory entry?
|
|
beq @do_entry ;yup, update the whole thing
|
|
bmi @just_data ;no, just flush the data blocks
|
|
; else we're doing a fast flush call here. flush dirty bitmap and
|
|
; dirty directory ('dirty' meaning that anything besides mod date
|
|
; and backup-bit have been changed).
|
|
jsr force_bitmap ;force the bitmap update
|
|
lda flush_flags ;is the directory dirty?
|
|
bit #dirEntry_dirty
|
|
bne @do_entry ;yes, so just go ahead and do the full flush
|
|
@just_data
|
|
clc
|
|
rts
|
|
@do_entry
|
|
lda #file_clean
|
|
jsr clr_fcr_status ;mark master block as clean
|
|
;
|
|
;Now lets update the VCR count to indicate that the file is clean
|
|
;
|
|
lda dirty_cnt_changed
|
|
bne @changed_once ;have we adjusted the number already?
|
|
|
|
inc dirty_cnt_changed
|
|
ldy #dirty_file_cnt
|
|
lda [prodos_vcr_ptr],y
|
|
beq @major_error
|
|
dec a
|
|
sta [prodos_vcr_ptr],y
|
|
jsr flush_bitmap ;now go and update the bitmap
|
|
bcs go_cannot_update
|
|
@major_error
|
|
@changed_once
|
|
jsr set_default_buf ;use the system buffer
|
|
jsr standard_req
|
|
jsr update_mod_time ;make sure we use the correct time
|
|
|
|
jsr get_parent ;load the I/O buffer with directory blk
|
|
go_cannot_update
|
|
bcs to_cannot_update
|
|
jsr verify_storage ;verify storage type
|
|
;
|
|
;Change for final release 8/16/88
|
|
;
|
|
;
|
|
; First we update the File Control Record to indicate the correct backup state
|
|
;
|
|
ldy #fcr_disk_acc ;update fcr along with dir entry
|
|
lda [pro_fcr_ptr],y
|
|
ora #backup_on
|
|
sta [pro_fcr_ptr],y
|
|
;
|
|
;Now we update the directory entry to indicate the correct backup state
|
|
;
|
|
ldy #access_index ;index to the access byte in a dir entry
|
|
lda [temp_ptr],y
|
|
ora #backup_on ;set the backup bit before update of disk
|
|
sta [temp_ptr],y
|
|
|
|
bcs to_cannot_update
|
|
|
|
;If the file is a resource file then only update the modification time.
|
|
;Otherwise update the entire directory entry.
|
|
|
|
ldy #fcr_file_id
|
|
lda [pro_fcr_ptr],y
|
|
ldy #fcr_key_blk
|
|
cmp [pro_fcr_ptr],y
|
|
beq entry_ok ;file is not a resource file
|
|
jsr update_resource ;update the resource header
|
|
bcs to_cannot_update ;cannot write info to disk!
|
|
jsr set_default_buf ;restore buffer pointer
|
|
|
|
ldy #fcr_modified ;index into FCR
|
|
lda [pro_fcr_ptr],y
|
|
ldy #last_mod_index ;index into directory block
|
|
sta [temp_ptr],y ;update the directory entry
|
|
ldy #fcr_modified+2
|
|
lda [pro_fcr_ptr],y
|
|
ldy #last_mod_index+2
|
|
sta [temp_ptr],y
|
|
bra update_disk ;now update the directory
|
|
|
|
;Move the entire directory info then write the block back to disk.
|
|
|
|
entry_ok ;
|
|
ldy #fcr_storage
|
|
lda [temp_ptr]
|
|
and #$FF0F ;clear current storage type
|
|
ora [pro_fcr_ptr],y ;adjust the storage type
|
|
sta [temp_ptr]
|
|
|
|
ldx #fcr_eof
|
|
ldy #fcr_curr_eof ;move the current EOF to disk EOF
|
|
lda [pro_fcr_ptr],y
|
|
phy
|
|
txy
|
|
sta [pro_fcr_ptr],y
|
|
inx
|
|
ply
|
|
iny
|
|
lda [pro_fcr_ptr],y
|
|
txy
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldy #fcr_header_ptr ;start at the end
|
|
ldx #header_ptr_index
|
|
|
|
blast_loop ;
|
|
lda [pro_fcr_ptr],y
|
|
phy
|
|
txy
|
|
sta [temp_ptr],y
|
|
dex
|
|
ply
|
|
dey
|
|
cpy #fcr_file_type
|
|
bne blast_loop
|
|
|
|
update_disk
|
|
jsr write_with_cache
|
|
to_cannot_update
|
|
bcs cannot_update
|
|
|
|
lda #dirEntry_clean
|
|
jsr clr_fcr_status ;mark directory entry as clean
|
|
|
|
lda close_flag ;should we update the directories?
|
|
ora time_stamp_opt ;check user's option for time stamp too
|
|
ora flush_flags ;and which type of flush we're doing
|
|
beq dont_bother ;no directory updates please
|
|
|
|
ldy #header_ptr_index
|
|
lda [temp_ptr],y
|
|
sta drvr_blk_num
|
|
cmp #vol_dir_start
|
|
beq dont_bother
|
|
|
|
jsr read_with_cache
|
|
bcs cannot_update
|
|
ldy #parent_index ;get the parent block number
|
|
lda [drvr_buf_ptr],y
|
|
sta slug_block ;save the block number
|
|
ldy #par_entry_num
|
|
lda [drvr_buf_ptr],y
|
|
jsr entry_to_offset
|
|
sta slug_offset
|
|
jsr slug_ripple ;do the slug ripple
|
|
rts
|
|
|
|
dont_bother ;
|
|
clc
|
|
cannot_update ;
|
|
rts
|
|
|
|
EXPORT flush_index
|
|
flush_index ;
|
|
ldy #index_blk_num ;get the block number
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num
|
|
beq clear_index ;the block is sparse so don't write it!
|
|
ldx index_ptr
|
|
ldy index_ptr+2
|
|
jsr flush_block
|
|
bcc clear_index
|
|
rts ;return the error code
|
|
|
|
clear_index ;
|
|
lda #index_clean
|
|
jsr clr_fcr_status ;mark master block as clean
|
|
rts
|
|
|
|
|
|
EXPORT flush_data_blk
|
|
flush_data_blk ;
|
|
ldy #data_blk_num ;get the block number
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num
|
|
beq clear_data ;the block is sparse so don't write it to disk
|
|
|
|
ldx data_ptr
|
|
ldy data_ptr+2
|
|
jsr flush_block2
|
|
bcc clear_data
|
|
rts ;return the error code
|
|
|
|
clear_data ;
|
|
lda #data_clean
|
|
jsr clr_fcr_status ;mark master block as clean
|
|
clc
|
|
rts
|
|
|
|
;If we get here then we are updating a resource file. So we need to update
|
|
;the resource header block with the following information.
|
|
;
|
|
; Storage Type
|
|
; key_block
|
|
; blocks used
|
|
; eof
|
|
;
|
|
|
|
update_resource ;
|
|
lda drvr_blk_num ;save the block number please
|
|
pha
|
|
|
|
jsr standard_req
|
|
jsr set_default_buf
|
|
inc drvr_buf_ptr+1
|
|
inc drvr_buf_ptr+1 ;use the high block of the buffer!!!
|
|
|
|
ldy #fcr_file_id ;index to header block
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num ;read in the block please
|
|
jsr read_with_cache
|
|
bcs end_res_update
|
|
|
|
ldy #fcr_res_num ;which resource are we updating?
|
|
lda [pro_fcr_ptr],y
|
|
xba ;make an index $0000 or $0100
|
|
tax ;point to start of header
|
|
|
|
ldy #fcr_storage ;stoarge type of file
|
|
lda [pro_fcr_ptr],y
|
|
lsr a ;convert $10,$20,$30 -> $1,$2,$3
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
txy ;index to storage type
|
|
sta [drvr_buf_ptr],y
|
|
inx ;advance to key block
|
|
|
|
ldy #fcr_key_blk
|
|
lda [pro_fcr_ptr],y
|
|
txy
|
|
sta [drvr_buf_ptr],y
|
|
inx
|
|
inx ;advance to blocks used
|
|
|
|
ldy #fcr_blks_used
|
|
lda [pro_fcr_ptr],y
|
|
txy
|
|
sta [drvr_buf_ptr],y
|
|
inx
|
|
inx ;advance to EOF
|
|
|
|
ldy #fcr_curr_eof
|
|
lda [pro_fcr_ptr],y
|
|
txy
|
|
sta [drvr_buf_ptr],y
|
|
inx
|
|
ldy #fcr_curr_eof+1
|
|
lda [pro_fcr_ptr],y
|
|
txy
|
|
sta [drvr_buf_ptr],y
|
|
|
|
jsr write_with_cache ;Update the disk
|
|
bcs end_res_update
|
|
|
|
clc
|
|
ldy #$0003 ;index to the blocks used data
|
|
lda [drvr_buf_ptr],y
|
|
ldy #$0103 ;index to blocks used resource
|
|
adc [drvr_buf_ptr],y
|
|
adc #$0001 ;add in the header block
|
|
|
|
ldy #blks_used_index ;index into directory block
|
|
sta [temp_ptr],y ;update the directory entry
|
|
clc
|
|
end_res_update
|
|
plx ;restore the block number
|
|
stx drvr_blk_num
|
|
rts
|
|
|
|
;==========================================================================
|
|
;This routine reads the GS clock and stores the time in the modification
|
|
;field of the current FCR.
|
|
|
|
update_mod_time ;
|
|
jsr pack_time ;time for mod date (X=low Y=high)
|
|
phy ;save high word
|
|
ldy #fcr_modified
|
|
txa
|
|
sta [pro_fcr_ptr],y
|
|
iny
|
|
iny
|
|
pla
|
|
sta [pro_fcr_ptr],y ;update high word
|
|
rts
|
|
|
|
;==========================================================================
|
|
;This routine will read in the parent block for a FCR and update the
|
|
;modification date.
|
|
;
|
|
;input: pro_fcr_ptr ;MUST be setup
|
|
;
|
|
;output: carry = error
|
|
; temp_ptr ;points to the file entry
|
|
|
|
get_parent ;
|
|
ldy #fcr_parent
|
|
lda [pro_fcr_ptr],y ;get the address of the directory blk
|
|
sta drvr_blk_num
|
|
jsr read_with_cache ;get the directory block please
|
|
bcc block_loaded
|
|
rts
|
|
|
|
block_loaded ;
|
|
ldy #fcr_entry_offs ;offset to directory entry
|
|
lda [pro_fcr_ptr],y
|
|
adc drvr_buf_ptr
|
|
sta temp_ptr
|
|
lda #$0000
|
|
adc drvr_buf_ptr+2
|
|
sta temp_ptr+2
|
|
clc
|
|
rts
|
|
|
|
;==========================================================================
|
|
;This routine verifies that the entry pointed to by 'temp_ptr' is a valid
|
|
;ProDOS entry. It verifies this by looking at the storage type.
|
|
|
|
verify_storage ;
|
|
lda [temp_ptr] ;get stoarge/length byte
|
|
and #$00F0 ;verify the storage type please
|
|
cmp #resource_type
|
|
beq good_entry
|
|
cmp #seedling_type
|
|
beq good_entry
|
|
cmp #sapling_type
|
|
beq good_entry
|
|
cmp #tree_type
|
|
beq good_entry
|
|
cmp #subdir_type
|
|
beq good_entry
|
|
|
|
lda #dir_error ;the directory must be damaged
|
|
sec
|
|
rts
|
|
|
|
good_entry clc
|
|
rts
|
|
|
|
;Force the block to disk
|
|
|
|
flush_block ;
|
|
stx drvr_buf_ptr
|
|
sty drvr_buf_ptr+2
|
|
jsr write_with_cache
|
|
rts
|
|
flush_block2 ;
|
|
stx drvr_buf_ptr
|
|
sty drvr_buf_ptr+2
|
|
jsr write_with_mount
|
|
rts
|
|
|
|
EXPORT clr_fcr_status
|
|
clr_fcr_status ;
|
|
ldy #fcr_status
|
|
and [pro_fcr_ptr],y
|
|
sta [pro_fcr_ptr],y
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;slug_ripple: This routine will time stamp the parent directories for ALL
|
|
; operations that require writing to the directory. This
|
|
; routine is SLOW and is very stupid on our type of system.
|
|
; It is put here for compatability only.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; drvr_buf_ptr (points to the directory entry)
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; device_dispatcher
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT slug_ripple
|
|
slug_ripple PROC
|
|
|
|
lda time_stamp_opt ;are we time stamping at all?
|
|
bne do_stamp
|
|
clc
|
|
rts
|
|
do_stamp
|
|
lda drvr_blk_num
|
|
pha
|
|
lda drvr_buf_ptr
|
|
pha
|
|
lda drvr_buf_ptr+2
|
|
pha
|
|
|
|
jsr pack_time ;get the time please
|
|
|
|
clc
|
|
lda gbuf_addr
|
|
adc #blk_size
|
|
sta drvr_buf_ptr
|
|
lda gbuf_addr+2
|
|
adc #$0000
|
|
sta drvr_buf_ptr+2
|
|
|
|
lda slug_block ;setup the block
|
|
bne @around
|
|
brl do_volume_mod ;no slug block, so time stamp the volume please
|
|
|
|
@around sta drvr_blk_num
|
|
|
|
slug_loop
|
|
jsr read_with_cache ;read in the block please
|
|
bcs end_slug_err
|
|
|
|
ldy slug_offset ;offset to the entry
|
|
lda [drvr_buf_ptr],y
|
|
and #$00F0 ;check the storage type
|
|
cmp #subdir_type
|
|
bne bad_slug_dir ;sorry bud
|
|
|
|
tya
|
|
clc
|
|
adc #last_mod_index
|
|
tay ;index to the last mod field
|
|
lda pro_time ;Get the time we are going to stamp with
|
|
sta [drvr_buf_ptr],y
|
|
lda pro_time+2
|
|
iny
|
|
iny
|
|
sta [drvr_buf_ptr],y
|
|
|
|
;new code added 3/15/91 CAE
|
|
ldy slug_offset ;offset to the entry
|
|
tya
|
|
clc
|
|
adc #access_index
|
|
tay ;index to the access field
|
|
lda [drvr_buf_ptr],y
|
|
ora #backup_on ;set the backup bit
|
|
sta [drvr_buf_ptr],y
|
|
;end of new code
|
|
|
|
jsr write_with_cache
|
|
bcs end_slug_err ;a major error
|
|
|
|
|
|
lda time_stamp_opt ;are we walking to root?
|
|
dec a
|
|
beq end_slug ;not today.
|
|
|
|
clc
|
|
lda slug_offset ;offset to the entry
|
|
adc #header_ptr_index ;point to the header pointer please
|
|
tay
|
|
lda [drvr_buf_ptr],y
|
|
cmp #vol_dir_start ;is this the root?
|
|
beq do_volume_mod ;set the volume modification date
|
|
|
|
cmp drvr_blk_num ;is the block already loaded?
|
|
beq block_loaded ;you bet-cha
|
|
sta drvr_blk_num ;next block to read
|
|
jsr read_with_cache
|
|
bcs end_slug_err ;sorry bud major error
|
|
|
|
block_loaded
|
|
ldy #parent_index
|
|
lda [drvr_buf_ptr],y
|
|
sta drvr_blk_num ;new block number
|
|
iny
|
|
iny ;get the entry number
|
|
lda [drvr_buf_ptr],y
|
|
jsr entry_to_offset
|
|
sta slug_offset ;the new offset
|
|
bra slug_loop ;ripple to the top.
|
|
|
|
bad_slug_dir
|
|
lda #dir_error
|
|
bra end_slug_err
|
|
|
|
end_slug
|
|
clc
|
|
|
|
end_slug_err
|
|
plx
|
|
stx drvr_buf_ptr+2
|
|
plx
|
|
stx drvr_buf_ptr
|
|
plx
|
|
stx drvr_blk_num
|
|
rts
|
|
;
|
|
;Now lets go and time stamp the volume please
|
|
;
|
|
do_volume_mod
|
|
lda #vol_dir_start ;Setup the block number for the Root
|
|
sta drvr_blk_num
|
|
jsr read_with_cache ;read in the block please
|
|
bcs end_slug_err ;I hate it with this happens
|
|
|
|
ldy #vol_mod_offset ;offset to the Mod time field for the volume
|
|
lda pro_time
|
|
sta [drvr_buf_ptr],y
|
|
iny
|
|
iny
|
|
lda pro_time+2
|
|
sta [drvr_buf_ptr],y ;store the time
|
|
|
|
;new code added 3/15/91 CAE
|
|
ldy #vol_acc_offset ;offset to the access field
|
|
lda [drvr_buf_ptr],y
|
|
ora #backup_on ;set the backup bit on disk
|
|
sta [drvr_buf_ptr],y
|
|
;end of new code
|
|
|
|
ldy #vol_mod ;update the VCR as well as the disk
|
|
lda pro_time
|
|
sta [prodos_vcr_ptr],y
|
|
iny
|
|
iny
|
|
lda pro_time+2
|
|
sta [prodos_vcr_ptr],y
|
|
|
|
;new code added 4/4/91 CAE
|
|
ldy #vol_access ;offset to the access field
|
|
lda [prodos_vcr_ptr],y
|
|
ora #backup_on ;set the backup bit in the VCR
|
|
sta [prodos_vcr_ptr],y ;so that the disk and VCR match
|
|
;end of new code
|
|
|
|
jsr write_with_cache
|
|
bcs end_slug_err ;a major error
|
|
bra end_slug ;no error, all is wonderful
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;extend_subdir This routine will extend a directory if needed.
|
|
;
|
|
;input: free_dir_blk ;dir blk with a empty entry.
|
|
; dir_start_blk ;starting block of the directory
|
|
; dir_last_blk ;last block of the directory
|
|
;
|
|
;output: free_dir_blk ;dir blk with a empty entry.
|
|
; free_dir_offset ;offset to directory entry within block
|
|
; dir_start_blk ;starting block of the directory
|
|
; dir_last_blk ;last block of the directory
|
|
;
|
|
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT extend_subdir
|
|
extend_subdir PROC
|
|
with expand_record
|
|
|
|
bit expand_file ;are we adding a directory entry?
|
|
bmi good_exit ;if we are expanding a file we donot need to extend the
|
|
;directory
|
|
|
|
lda free_dir_blk ;is there a free entry for this file?
|
|
bne good_exit ;do not extend the directory
|
|
|
|
lda dir_start_blk
|
|
cmp #vol_dir_start ;is this the root directory?
|
|
bne not_root
|
|
|
|
lda #vol_dir_full ;return an error please
|
|
sec
|
|
rts
|
|
|
|
not_root ;
|
|
lda #$0001 ;allocate one block for directory.
|
|
ldx dir_last_blk ;start looking here for next block
|
|
jsr find_Free_blks ;go and get one
|
|
bcs error_out ;error out
|
|
stx drvr_blk_num ;this is the new directory block
|
|
|
|
stx free_dir_blk ;new block number
|
|
lda #$0004 ;index to first free entry
|
|
sta free_dir_offset
|
|
|
|
jsr set_default_buf ;use the genaral buffer
|
|
jsr standard_req ;512 byte write
|
|
jsr clear_dir_buf ;clear the 512 byte general buffer
|
|
jsr append_last_blk
|
|
bcs error_out ;major problem
|
|
jsr update_forw_lnk ;update forward link to new block
|
|
bcs error_out
|
|
jsr update_parent ;update parents blocks used count
|
|
bcs error_out
|
|
good_exit ;
|
|
clc
|
|
error_out ;
|
|
rts ;extend complete
|
|
|
|
;==========================================================================
|
|
;Update_parent: This routine will update the blocks used and last mod date
|
|
; of the parent entry for the directory.
|
|
|
|
update_parent ;
|
|
lda dir_start_blk
|
|
sta drvr_blk_num ;key block for directory
|
|
jsr read_with_cache
|
|
bcs exit_update
|
|
|
|
ldy #parent_index
|
|
lda [gbuf_ptr],y ;get the parent block number
|
|
sta drvr_blk_num
|
|
|
|
ldy #par_entry_num
|
|
lda [gbuf_ptr],y
|
|
and #$00FF ;get the number
|
|
dec a
|
|
cmp #$000D ;number of entries
|
|
bcs bad_dir_bud
|
|
asl a ;times 2 for a word table
|
|
tay
|
|
lda dir_offset_tbl,y
|
|
sta entry_offset ;save offset to dir entry
|
|
|
|
jsr read_with_cache ;read in the parent block
|
|
bcs exit_update
|
|
ldy entry_offset
|
|
lda [gbuf_ptr],y
|
|
and #$00F0 ;is this a subdir entry?
|
|
cmp #subdir_type
|
|
bne bad_dir_bud
|
|
|
|
tyx
|
|
|
|
clc
|
|
tya
|
|
adc #$0013 ;index to blocks used for file
|
|
tay
|
|
lda [gbuf_ptr],y
|
|
inc a
|
|
sta [gbuf_ptr],y
|
|
iny
|
|
iny ;point to EOF
|
|
|
|
clc
|
|
lda [gbuf_ptr],y
|
|
adc #blk_size
|
|
sta [gbuf_ptr],y ;add 512 to the EOF field
|
|
bcc good_eof
|
|
iny
|
|
iny ;point to the third byte of EOF
|
|
longa off
|
|
sep #$20 ;short A
|
|
lda [gbuf_ptr],y
|
|
inc a
|
|
sta [gbuf_ptr],y
|
|
longa on
|
|
rep #$20
|
|
|
|
good_eof ;
|
|
clc
|
|
txa
|
|
adc #$0021 ;index to mod time
|
|
pha
|
|
jsr pack_time
|
|
ply ;index
|
|
lda pro_time
|
|
sta [gbuf_ptr],y ;update mod time
|
|
iny
|
|
iny
|
|
lda pro_time+2
|
|
sta [gbuf_ptr],y
|
|
|
|
jsr write_with_cache
|
|
exit_update ;
|
|
rts
|
|
|
|
bad_dir_bud ;
|
|
lda #dir_error ;bad directory block
|
|
sec
|
|
rts
|
|
|
|
|
|
;==========================================================================
|
|
;update_forw.. This routine will link the new directory block just
|
|
; allocated to the current last block of the directory.
|
|
|
|
update_forw_lnk ;
|
|
lda dir_last_blk
|
|
sta drvr_blk_num ;now read in the directory block.
|
|
jsr read_with_cache
|
|
bcs forw_exit ;major problems. sorry about droppings!
|
|
|
|
ldy #$0002 ;index to next pointer
|
|
lda [gbuf_ptr],y
|
|
bne bad_dir_bud
|
|
lda free_dir_blk ;forward link directory block.
|
|
sta [gbuf_ptr],y
|
|
jsr write_with_cache
|
|
forw_exit rts
|
|
|
|
;==========================================================================
|
|
;append_last.. This routine will link the new block to the previous
|
|
; block in the directory.
|
|
|
|
append_last_blk ;
|
|
lda dir_last_blk ;setup the backward link
|
|
sta [gbuf_ptr]
|
|
jsr write_with_cache
|
|
rts
|
|
|
|
clear_dir_buf ;
|
|
ldy #$01FE ;clear the general work buffer
|
|
lda #$0000
|
|
|
|
clear_dir ;
|
|
sta [gbuf_ptr],y
|
|
dey
|
|
dey
|
|
bpl clear_dir ;every body happy now!
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
;==========================================================================
|
|
;Chk_swapped: This routine will determine if the volume has been swapped
|
|
; If the volume has been swapped then we will request the
|
|
; user to put the volume back online.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; my_vcr_ptr ;pointer to vcr
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; temp_ptr
|
|
; volume_name
|
|
; find_volume
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT chk_swapped
|
|
chk_swapped PROC
|
|
|
|
;Now we have all of our data setup for the read. Now we need to see if
|
|
;the volume has been swapped out. If it has then we must go and find
|
|
;it again.
|
|
|
|
ldy #vcr_status
|
|
lda [my_vcr_ptr],y
|
|
and #vcr_swapped ;disk logged out?
|
|
beq disk_back
|
|
|
|
;Little Bo-Peep-Show has lost her disk and doesn't know where to find it!
|
|
;Therefore we will go and find it for her.
|
|
|
|
ldy #vcr_name
|
|
lda [my_vcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [my_vcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx temp_ptr
|
|
sty temp_ptr+2
|
|
|
|
;Now we have a pointer to the name but we must move it to 'volume_name'
|
|
|
|
lda [temp_ptr]
|
|
and #$000F
|
|
tay
|
|
dey
|
|
|
|
move_name ;
|
|
lda [temp_ptr],y
|
|
sta volume_name,y
|
|
dey
|
|
bpl move_name
|
|
|
|
;Now that we have moved the name to volume_name buffer we need to call
|
|
;'find_volume' and let it look for it.
|
|
|
|
jsr mount_volume
|
|
rts
|
|
|
|
disk_back ;
|
|
clc
|
|
rts
|
|
ENDP
|
|
;======================================================================
|
|
;ID.Disk: This file contains the code that will id the media
|
|
; to determine if the media is in ProDOS/SOS format.
|
|
; If the disk is a ProDOS disk and there is no VCR then
|
|
; a new VCR will be generated for that disk. If there is
|
|
; a VCR then it is marked active.
|
|
;
|
|
;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
|
|
;
|
|
; drvr_buf_ptr ;points to storage/vol name field
|
|
; ;with storage type removed
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
;
|
|
;Diagram of pointers and memory segments
|
|
;
|
|
; (I/O Buffer)
|
|
; ___________
|
|
; | | <--- pointed to by 'drvr_buf_ptr'
|
|
; | | <--- 'drvr_buf_ptr' later points to volume name
|
|
; |___________| |
|
|
; |____ 'temp3_ptr' points to data AFTER volume name area
|
|
;
|
|
;
|
|
; (vcr)
|
|
; ___________ <-- pointed to by 'my_vcr_ptr'
|
|
; | | ___________________
|
|
; | vol name -|------> |___________________| <-- pointed to by 'Temp2_Ptr'
|
|
; | |
|
|
; | |
|
|
; | |
|
|
; | | <-- pointed to by 'prodos_vcr_ptr'
|
|
; |___________|
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT id_disk
|
|
id_disk PROC
|
|
|
|
sta drvr_dev_num ;driver number
|
|
lda #drvr_read
|
|
sta drvr_call_num
|
|
lda #vol_dir_start ;starting block of directory
|
|
sta drvr_blk_num
|
|
stz drvr_blk_num+2
|
|
jsr standard_req
|
|
|
|
ldx gbuf_addr ;setup pointer to general I/O buffer
|
|
ldy gbuf_addr+2
|
|
stx drvr_buf_ptr
|
|
sty drvr_buf_ptr+2
|
|
|
|
try_again jsr device_call ;make a system call to drive
|
|
bcc id_no_error
|
|
; ;error code in X already but it may
|
|
; ;change in the future. currently
|
|
; ;all code is cast in jello
|
|
and #$00FF ;clear the dispatcher error code
|
|
beq id_no_error ;Dispatcher returning disk switched
|
|
cmp #drvr_disk_sw ;was the disk switched?
|
|
beq try_again
|
|
sec ;swapped out by device call routine
|
|
rts ;if the disk was switched
|
|
|
|
;======================================================================
|
|
;ID method used to determine disk is ProDOS format:
|
|
;
|
|
;(1) read in block two (First directory block)
|
|
;(2) backward link must be zero (first word)
|
|
;(3) storage type must be $F (high nibble: byte $04)
|
|
;(4) name length must be > $0 (low nibble: byte $04)
|
|
;(5) name must be valid syntax
|
|
;(6) minimum version must be $00 (byte $21)
|
|
;(7) entry length must be $27 (SOS/ProDOS size)
|
|
;(8) entries per block must be $0D
|
|
;
|
|
;If the above information causes problems with other disks then I will
|
|
;read in the second block of the directory and verify that the link
|
|
;fields are correct. This may cause a problem if there is no second
|
|
;block in the directory. If this is the case then I will check the
|
|
;bitmap allocation for correctness. If this fails then forget it.
|
|
;
|
|
;======================================================================
|
|
|
|
id_no_error lda [drvr_buf_ptr] ;load backward link
|
|
bne bad_format
|
|
ldy #$0021 ;offset to minimum version
|
|
lda [drvr_buf_ptr],y
|
|
and #$00FF
|
|
bne bad_format
|
|
|
|
|
|
;Now that we have checked both the backward link and version we now
|
|
;need to adjust the pointer to point to the storage/name length field
|
|
;within the block.
|
|
|
|
clc
|
|
lda drvr_buf_ptr
|
|
adc #$0004
|
|
sta drvr_buf_ptr
|
|
bcc ar
|
|
inc drvr_buf_ptr+2
|
|
|
|
ar ;
|
|
lda [drvr_buf_ptr] ;load storage/name length
|
|
tay
|
|
and #$00F0
|
|
cmp #$00F0 ;is it a volume directory type?
|
|
bne bad_format
|
|
tya
|
|
and #$000F ;isolate file name length
|
|
beq bad_format ;must be $01 to $0F
|
|
tay
|
|
;
|
|
;Now we need to verify that the name is a valid ProDOS filename
|
|
;
|
|
|
|
loop
|
|
lda [drvr_buf_ptr],y
|
|
and #$00FF
|
|
cmp #'A'
|
|
bcc numeric
|
|
cmp #'Z'+1
|
|
bcs bad_format
|
|
dey
|
|
bne loop
|
|
|
|
;If we get here then we need to check both the entry length and
|
|
;entries per block. If everything is OK then we will call a routine
|
|
;that will build a new vcr or mark the vcr as active
|
|
|
|
its_mine ;
|
|
ldy #$0023-4 ;index to entry length
|
|
lda [drvr_buf_ptr],y
|
|
cmp #$0D27 ;both entry length and entry per blk
|
|
bne bad_format
|
|
jsr build_vcr ;build a volume control record
|
|
rts ;note: error set be build_vcr
|
|
|
|
numeric ;
|
|
cmp #'0'
|
|
bcc period
|
|
cmp #'9'+1
|
|
bcs bad_format
|
|
continue dey
|
|
bne loop
|
|
|
|
bad_format ;
|
|
lda #unknown_vol ;I don't know what this disk is
|
|
sec
|
|
rts
|
|
|
|
period cmp #'.'
|
|
bne bad_format
|
|
bra continue
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;Build_VCR: This routine will add a new VCR if one is currently not
|
|
; allocated, if the VCR is allocated then it will be
|
|
; marked as active.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; drvr_buf_ptr (points to volume header)
|
|
; cp_device_flag = 1 if doing a ChangePath call and source is device #
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
; find_vcr (system subroutine)
|
|
; alloc_vcr (system subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT build_vcr
|
|
build_vcr PROC
|
|
|
|
jsr move_vol_entry ;move the entry to the work area
|
|
jsr entry_to_gstr
|
|
|
|
;
|
|
; If bit 15 of cp_flag is set, assume the source disk is a duplicate volume
|
|
; and fall into the code that handles duplicate volumes with open files.
|
|
; Since cp_device_flag is already set, it will cause a fake VCR to be allocated.
|
|
; 5-Dec-91 MSD
|
|
;
|
|
bit cp_flags ; should we assume the disk is a duplicate?
|
|
bpl @not_dup ; no, so do the usual
|
|
brl is_open ; yes, pretend duplicate volume with open files
|
|
@not_dup
|
|
|
|
; End of 5-Dec-91 MSD change.
|
|
|
|
;Call system routine to see if it can find a vcr with the same volume
|
|
;name. If the accum contains a zero then the routine will will
|
|
;use x and y as a pointer to a volume name. If the accum contains
|
|
;a non zero value then the routine will try to find a vcr with
|
|
;the same volume id.
|
|
|
|
ldx #gstring ;pointer to the volume name
|
|
ldy #^gstring
|
|
lda #0000 ;0000=search for vcr by name
|
|
jsl find_vcr
|
|
bcs no_vcr ;this name is not in any VCR
|
|
|
|
jsl deref ;convert virtual to real
|
|
stx my_vcr_ptr
|
|
sty my_vcr_ptr+2 ;setup pointer to VCR
|
|
|
|
ldy #vcr_fst_id
|
|
lda [my_vcr_ptr],y
|
|
cmp #pro_id ;is this my vcr
|
|
bne check_active ;if not, can we kick it out?
|
|
|
|
jsr setup_my_vcr ;make a pointer to my vcr stuff
|
|
stx prodos_vcr_ptr
|
|
sty prodos_vcr_ptr+2
|
|
|
|
bit drvr_fst_num ;are we looking at name only?
|
|
bmi name_only ;yes.
|
|
|
|
ldy #entry_length-18
|
|
compare_loop lda one_entry+16,y ;we add 16 so we pass the name field
|
|
cmp [prodos_vcr_ptr],y
|
|
bne check_active
|
|
dey
|
|
bpl compare_loop
|
|
|
|
name_only ;
|
|
ldy #vcr_dev ;update the last known device
|
|
lda drvr_dev_num
|
|
sta [my_vcr_ptr],y
|
|
|
|
jsr activate_vcr ;mark the vcr as swapped in
|
|
jsr reset_vcr ;reset blocks free etc.
|
|
clc
|
|
rts
|
|
|
|
sorry_dup ;
|
|
lda #dup_volume ;duplicate volume online
|
|
sec
|
|
rts
|
|
|
|
;If we get here it means that the volume name already exist in vcr.
|
|
;So I need to see if there are any open files on the volume. If there
|
|
;are no open files then I can kick the current vcr out of memory and
|
|
;build a new one. If there are open files then I will return a
|
|
;duplicate volume error. Note: I check to make sure that the volume
|
|
;header has not changed. This protects me from marking a volume as
|
|
;being swapped in and writing to it blindly if it has the same name.
|
|
|
|
; Note - If we get a duplicate volume error and cp_device_flag = 1 then ignore
|
|
; the error since we are doing a ChangePath call with a device # as the source.
|
|
; 1/22/91 CAE
|
|
|
|
check_active ;
|
|
; ldy #vcr_open_cnt
|
|
; lda [my_vcr_ptr],y
|
|
; bne sorry_dup ;files open so don't log in new volume
|
|
; jsr free_vcr ;free vcr pointed to by 'my_vcr_ptr'
|
|
|
|
ldy #vcr_open_cnt
|
|
lda [my_vcr_ptr],y ;any open files?
|
|
beq not_open ;no
|
|
is_open ;Added 5-Dec-91 MSD
|
|
lda cp_device_flag ;are we doing a special ChangePath call?
|
|
beq sorry_dup ;no - so report a duplicate volume error
|
|
ora #$8000 ;yes - so indicate we got a dup vol error
|
|
sta cp_device_flag
|
|
lda <drvr_dev_num ; 5-Feb-92 MSD: Force other VCR's for this
|
|
jsl swap_out ; 5-Feb-92 MSD: to be swapped out.
|
|
bra no_vcr ;and continue
|
|
|
|
not_open jsr free_vcr ;free vcr pointed to by 'my_vcr_ptr'
|
|
|
|
;below begins the grunt work. we now have to allocate a new vcr and
|
|
;setup all are fields.
|
|
|
|
; Note - If cp_device_flag = $8001 then we need to use a fake name for the VCR
|
|
; since we got a duplicate volume error. 1/22/91 CAE
|
|
|
|
no_vcr ldx #gstring ;pointer to the name
|
|
ldy #^gstring
|
|
lda cp_device_flag ;do we need to use fake name for vcr?
|
|
bpl @cont ;no
|
|
ldx #fake_name_str ;yes - so point to fake name string
|
|
ldy #^fake_name_str
|
|
@cont lda #pro_vcr_size ;number of bytes to allocate
|
|
jsl alloc_vcr
|
|
bcc alloc_ok
|
|
rts ;exit with the error
|
|
|
|
alloc_ok ; ;now build my data structures
|
|
jsl deref ;convert virtual to real address
|
|
stx my_vcr_ptr
|
|
sty my_vcr_ptr+2
|
|
jsr setup_my_vcr ;setup pointer to my data
|
|
stx prodos_vcr_ptr
|
|
sty prodos_vcr_ptr+2
|
|
|
|
ldy #vcr_fst_id ;indicate that this vcr is owned by me.
|
|
lda #pro_id
|
|
sta [my_vcr_ptr],y
|
|
|
|
ldy #vcr_dev ;convert to INY,INY
|
|
lda drvr_dev_num
|
|
sta [my_vcr_ptr],y
|
|
|
|
ldy #vcr_status
|
|
lda #0000 ;zero the status word
|
|
sta [my_vcr_ptr],y
|
|
|
|
ldy #entry_length-16
|
|
entry_loop lda one_entry+16,y
|
|
sta [prodos_vcr_ptr],y
|
|
dey
|
|
bpl entry_loop ;move the entire directory entry
|
|
|
|
;warning: if the 'BPL' instruction above changes, then the accum will
|
|
; have to be loaded with $FFFF directly.
|
|
|
|
tya ;now init free blocks to $FFFF. This
|
|
ldy #free_blocks ;indicates that free blks is unknown
|
|
sta [prodos_vcr_ptr],y
|
|
ldy #avail_bitmap
|
|
sta [prodos_vcr_ptr],y
|
|
ldy #curr_bitmap ;indicate we don't know about these
|
|
sta [prodos_vcr_ptr],y
|
|
|
|
;Now we need to calculate the number of bitmap blocks that are on
|
|
;the volume. We also calculate how many bytes in the last block must
|
|
;by zero. If these bytes are not zero then the bitmap is damaged
|
|
|
|
stz math_temp ;setup for even multiple of 4K
|
|
ldy #vol_total_blks ;convert total blocks to number of
|
|
; ;bitmap blocks on volume
|
|
lda [prodos_vcr_ptr],y
|
|
tax ;save total block count
|
|
and #$0FFF
|
|
beq calc_bitmap
|
|
inc math_temp
|
|
|
|
calc_bitmap ;
|
|
txa
|
|
and #$F000 ;clear unwanted garbage
|
|
rol a
|
|
rol a
|
|
rol a
|
|
rol a
|
|
rol a
|
|
adc math_temp ;add in for odd block size
|
|
ldy #num_bitmap_blks
|
|
sta [prodos_vcr_ptr],y
|
|
|
|
even_bit ;
|
|
txa
|
|
and #$0007
|
|
beq found_even_bit ;this is the block number we want
|
|
inx ;add one to the block count
|
|
bra even_bit ;keep trying to find byte boundary
|
|
|
|
found_even_bit ;
|
|
jsr calc_bit ;'Y' will equal byte index into blk
|
|
tya
|
|
ldy #end_bitmap ;first byte in the bitmap that must be
|
|
sta [prodos_vcr_ptr],y
|
|
; ;set to zero in the last blk of bitmap
|
|
clc
|
|
rts
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;activate_vcr: This routine will mark the vcr as being logged in
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; my_vcr_ptr (Points to main VCR)
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
; (the VCR is logged in)
|
|
;
|
|
;Uses: All registers
|
|
; my_vcr_ptr
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT activate_vcr
|
|
activate_vcr PROC
|
|
|
|
ldy #vcr_status
|
|
lda [my_vcr_ptr],y
|
|
and #vcr_swapped_in
|
|
sta [my_vcr_ptr],y
|
|
rts
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;Enrty_to_gstr This routine moves the name from the alloc_entry to
|
|
; gstring buffer. It will also append a null.
|
|
;
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; alloc_entry (contains the volume name)
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; gstring (contains gstring)
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT entry_to_gstr
|
|
entry_to_gstr PROC
|
|
|
|
ldy alloc_entry ;the length of the string
|
|
iny
|
|
iny ;point to null field
|
|
lda #$0000
|
|
sta gstring,y ;store the null
|
|
dey
|
|
|
|
php ;save current mode
|
|
longa off
|
|
sep #$20
|
|
loop ;
|
|
lda alloc_entry,y
|
|
sta gstring,y
|
|
dey
|
|
bpl loop
|
|
plp
|
|
rts
|
|
ENDP
|
|
|
|
|
|
;======================================================================
|
|
;Find_volume: This routine will locate a volume using the ID routine.
|
|
;
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; volume_name (contains the volume name to find)
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: All registers
|
|
; find_vcr (system subroutine)
|
|
; id_disk (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
; volume_name
|
|
; drvr_buf_ptr
|
|
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT find_volume
|
|
find_volume PROC
|
|
|
|
lda #$0001 ;start with device number 1
|
|
sta search_device
|
|
stz skip_dev
|
|
|
|
jsr chk_vol_syntax
|
|
|
|
ldx #volume_name ;try to find the volume in a vcr
|
|
ldy #^volume_name
|
|
lda #$0000
|
|
jsl find_vcr
|
|
bcs check_drive
|
|
|
|
;check to see if this vcr is mine
|
|
|
|
jsl deref ;convert to real pointer
|
|
stx my_vcr_ptr
|
|
sty my_vcr_ptr+2
|
|
|
|
ldy #vcr_fst_id
|
|
lda [my_vcr_ptr],y
|
|
cmp #pro_id
|
|
beq get_device
|
|
lda #unknown_vol ;tell caller its another fsts
|
|
sec
|
|
rts ;return
|
|
|
|
;setup the device number to check first
|
|
|
|
get_device
|
|
ldy #vcr_dev
|
|
lda [my_vcr_ptr],y
|
|
sta search_device
|
|
sta skip_dev ;indicate we are starting in the middle
|
|
bra do_id
|
|
|
|
check_drive
|
|
lda search_device
|
|
cmp skip_dev ;do I need to skip this one?
|
|
beq next_dev
|
|
do_id jsr id_disk
|
|
bcc compare_vol
|
|
|
|
cmp #invalid_dev_num ;have we looked at all the devices?
|
|
beq vol_not_avail
|
|
cmp #dup_volume ;is the volume a duplicate?
|
|
beq abort_search
|
|
bra check_search ;go ahead and try another drive.
|
|
|
|
vol_not_avail
|
|
lda #vol_not_found
|
|
|
|
abort_search
|
|
sec
|
|
rts ;sorry not today
|
|
|
|
next_dev
|
|
inc search_device
|
|
bra check_drive
|
|
|
|
compare_vol
|
|
lda [drvr_buf_ptr] ;get the length
|
|
and #$000F
|
|
cmp volume_name ;sixteen bit name length
|
|
bne check_search ;Cannot be the same
|
|
|
|
tay ;save the length
|
|
php
|
|
longa off
|
|
sep #$20 ;short accum for string compare
|
|
|
|
comp_loop
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
lda volume_name+1,y
|
|
cmp #' '
|
|
bne @not_blank
|
|
lda #'.'
|
|
@not_blank cmp [drvr_buf_ptr],y
|
|
else ;original code
|
|
lda [drvr_buf_ptr],y
|
|
cmp volume_name+1,y
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
|
|
bne not_same
|
|
dey
|
|
bne comp_loop
|
|
longa on ;keep the assembler in line
|
|
plp
|
|
clc
|
|
rts ;this is it.
|
|
|
|
not_same ;
|
|
plp
|
|
check_search ;
|
|
lda skip_dev
|
|
cmp search_device ;are we looking at a default drive?
|
|
bne next_dev ;no we are not.
|
|
stz search_device ;start the search from the beginning
|
|
bra next_dev
|
|
|
|
|
|
EXPORT chk_vol_syntax
|
|
chk_vol_syntax ;check the syntax of the volume name
|
|
longa off
|
|
longi off
|
|
sep #$30
|
|
ldy volume_name ;get the length word
|
|
;check the length first 10/10/91 JEV
|
|
cpy #$10
|
|
bcc vol_syntax_loop
|
|
bra syntax_death
|
|
|
|
vol_syntax_loop ;
|
|
lda volume_name+1,y
|
|
|
|
cpy #$0001 ;is this the first character
|
|
bne not_first
|
|
cmp #'a'
|
|
bcc not_lower
|
|
cmp #'z'+1
|
|
bcs syntax_death
|
|
and #$DF
|
|
|
|
not_lower ;
|
|
cmp #'A'
|
|
bcc syntax_death
|
|
cmp #'Z'+1
|
|
bcc good_syntax
|
|
|
|
syntax_death ;
|
|
longa on
|
|
longi on
|
|
rep #$30
|
|
lda #bad_path_syntax
|
|
sec
|
|
jmp main_exit
|
|
|
|
good_syntax ;
|
|
dey
|
|
bne vol_syntax_loop
|
|
rep #$30
|
|
rts
|
|
|
|
longa off
|
|
longi off
|
|
not_first ;
|
|
cmp #'a'
|
|
bcc not_lower2
|
|
cmp #'z'+1
|
|
bcs syntax_death
|
|
and #$DF
|
|
|
|
not_lower2 ;
|
|
|
|
cmp #'A'
|
|
bcc check_num
|
|
cmp #'Z'+1
|
|
bcs syntax_death
|
|
bra good_syntax
|
|
|
|
check_num ;
|
|
cmp #'0'
|
|
bcc check_period
|
|
cmp #'9'+1
|
|
bcs syntax_death
|
|
bra good_syntax
|
|
|
|
check_period ;
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
cmp #' '
|
|
bne @not_blank
|
|
lda #'.'
|
|
sta volume_name+1,y
|
|
bra good_syntax
|
|
@not_blank
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
cmp #'.'
|
|
bne syntax_death
|
|
bra good_syntax
|
|
|
|
;local data for find volume
|
|
|
|
search_device DC.W 00
|
|
skip_dev DC.W 00
|
|
|
|
ENDP
|
|
;======================================================================
|
|
;Find_File: This file contains the code that will locate a file on
|
|
; disk.
|
|
;
|
|
;revisions:
|
|
; apr 09 1987 ;added forward/backward link verify
|
|
; apr 09 1987 ;changed routine to read a block
|
|
; ;at a time instead of 1K
|
|
; apr 10 1987 ;added additional check for path
|
|
; ;searching.
|
|
; apr 27 1987 ;changed code to handle 'C' strings
|
|
; may 02 1987 ;added memory based tree routines
|
|
; ;so all accessed directories will
|
|
; ;be added into a b-tree.
|
|
; sep 14 1987 ;added support for searching for
|
|
; ;blank entries in the directory
|
|
;
|
|
;Input: A = device number
|
|
; X = low word: pointer to name
|
|
; Y = high word: pointer to name
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; drvr_vol_id
|
|
; my_vcr_ptr
|
|
; prodos_vcr_ptr
|
|
; search_flag ;IF bit 14 = 1 then search for blank
|
|
; ;blank entry in directory, as well
|
|
; ;as checking for duplicate file error.
|
|
;
|
|
;Format of pathname:
|
|
; 1) volume name is NOT part of the pathname
|
|
; 2) pathname begins with a length byte
|
|
; 3) each part of the pathname is seperated with a colon char.
|
|
; 4) pathname MUST end with a NULL char.
|
|
;
|
|
;Output: A = error code or offset to entry within the I/O buffer
|
|
; X = pointer to name (low word)
|
|
; Y = pointer to name (high word)
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; dir_start_blk ;starting block of last dir searched
|
|
; free_dir_blk ;first block with a blank entry
|
|
; free_dir_offset ;offset to first free entry within blk
|
|
; dir_last_blk ;block number that contains found file.
|
|
; or drvr_blk_num ;or the last block of the directory.
|
|
; path_searched ;if + then entire path NOT searched
|
|
; ;if - then the entire path was searched
|
|
; slug_block ;block number of the entry
|
|
; slug_offset ;offset to the entry.
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 1K bytes)
|
|
; temp_ptr
|
|
; gbuf_ptr
|
|
; path_level
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT find_file
|
|
find_file PROC
|
|
|
|
sta drvr_dev_num ;device number to search on
|
|
stx temp_ptr ;pointer to the name
|
|
sty temp_ptr+2
|
|
|
|
lda gbuf_addr
|
|
sta gbuf_ptr
|
|
sta drvr_buf_ptr
|
|
lda gbuf_addr+2
|
|
sta gbuf_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
stz curr_mod_date ;zero the latest mod date field
|
|
stz curr_mod_date+2
|
|
|
|
lda #vol_dir_start ;default starting block
|
|
sta dir_start_blk ;starting block for current directory
|
|
sta dir_last_blk ;last block read by find file
|
|
sta drvr_blk_num
|
|
stz drvr_blk_num+2
|
|
vcr_not_alloc
|
|
jsr standard_req
|
|
|
|
lda #drvr_read ;setup for reading
|
|
sta drvr_call_num
|
|
|
|
stz chars_checked
|
|
stz path_searched ;indicates if entire path searched
|
|
jsr setup_name ;setup first part to look for
|
|
stz entries_blk_num ;block that contains the entry
|
|
outter_loop ;
|
|
stz last_blk ;used to verify directory structure
|
|
stz free_dir_blk ;indicate no free dir entry
|
|
stz free_dir_offset
|
|
stz searching_free ;we are looking for free entries
|
|
|
|
search_loop ;
|
|
jsr read_with_cache ;issue the read command
|
|
bcs error_leave ;some error has occured
|
|
|
|
jsr verify_dir ;verify forward/backward links
|
|
bcs error_leave ;get out of here, links disagree
|
|
|
|
stz entries_checked ;reset file counter
|
|
ldy #0004 ;pass the link pointers
|
|
jsr check_block ;see if name is in the block
|
|
bcc found
|
|
|
|
bit searching_free ;are we looking for a free entry?
|
|
bpl check_active ;no we are looking for the file.
|
|
lda free_dir_blk ;Have we found a free entry yet?
|
|
beq load_next ;No, so load the next block
|
|
bit path_searched ;are we looking for the last name?
|
|
bpl load_next ;No.
|
|
bra no_more_blks ;yes, so return data
|
|
|
|
check_active ;
|
|
lda files_in_dir ;subtract off active entries checked
|
|
sbc files_examined
|
|
bcc dir_damaged ;the directory count does not match
|
|
beq not_found ;we have looked at all the files.
|
|
|
|
load_next ;
|
|
ldy #0002 ;check next link field
|
|
lda [gbuf_ptr],y ;get the forward link
|
|
beq no_more_blks ;cannot check any further
|
|
sta drvr_blk_num ;read this block next
|
|
sta dir_last_blk ;save last block read
|
|
bra search_loop
|
|
|
|
not_found ;
|
|
bit search_flag ;are we suppose to find a free entry?
|
|
bvc no_more_blks ;no we are not
|
|
lda free_dir_blk ;do we already have a free entry?
|
|
bne no_more_blks ;yes we do!
|
|
dec searching_free
|
|
bra load_next ;continue to look for a blank entry.
|
|
|
|
no_more_blks ;
|
|
lda path_searched ;was the entire path searched?
|
|
bne file_err ;yes the entire path was searched
|
|
lda #path_not_found ;a subdirectory was not found
|
|
sec
|
|
rts
|
|
file_err ;
|
|
lda #file_not_found ;you guessed it, no file today
|
|
sec ;sorry no file by that name
|
|
error_leave rts
|
|
|
|
;we get here if the total number of active files is greater then the
|
|
;total number of files in the directory
|
|
|
|
dir_damaged ;
|
|
lda #dir_error ;this is a bad directory
|
|
sec
|
|
rts
|
|
|
|
;If we get here then we have found the name we were looking for.
|
|
;Now we need to see if there is anymore pathname to process. If there
|
|
;is nothing left to process then we exit all happy. If there is more
|
|
;to process then we make sure that the entry we just found is a
|
|
;subdirectory. If it is not then we exit with file not found.
|
|
|
|
found ;
|
|
lda drvr_blk_num ;block number that contains entry
|
|
sta entries_blk_num ;block number that contains the entry
|
|
sta dir_last_blk ;last block read
|
|
sty entries_offset ;offset to the entry
|
|
|
|
tyx
|
|
ldy chars_checked
|
|
dey
|
|
lda [temp_ptr],y ;see if we are done
|
|
and #$00FF
|
|
beq find_success ;yes we have succeeded
|
|
|
|
txy
|
|
lda [gbuf_ptr],y ;see if type is directory
|
|
and #$00F0
|
|
cmp #$00D0 ;it is a directory
|
|
bne not_found ;can not go any further
|
|
|
|
lda drvr_blk_num ;save the entries block number for
|
|
sta slug_block ;slug ripple routine.
|
|
sty slug_offset ;offset to file entry.
|
|
|
|
tya
|
|
clc
|
|
adc #$0011 ;make index to key block pointer
|
|
tay
|
|
lda [gbuf_ptr],y
|
|
sta drvr_blk_num
|
|
sta dir_start_blk ;starting block for next directory
|
|
sta dir_last_blk ;save last block read
|
|
jsr setup_name ;setup next partial to find
|
|
|
|
jmp outter_loop
|
|
|
|
;Below is a happy place to be. This means that we have found the
|
|
;file that we were commissioned to find. So we will setup a pointer
|
|
;to the name and return to the caller. Isnt' that special.
|
|
|
|
find_success txa ;we have located the name
|
|
pha ;save the offset
|
|
clc
|
|
adc gbuf_ptr ;adjust buffer pointer
|
|
tax
|
|
lda #0000
|
|
adc gbuf_ptr+2
|
|
tay
|
|
|
|
pla ;offset (0 to 512)
|
|
clc
|
|
rts ;X,Y contains a pointer to the name
|
|
|
|
;==========================================================================
|
|
;verify dir: This routine will verify that the forward and backward
|
|
; links of the subdirectory agree with each other. If
|
|
; they do not then we will return a dir_error. The
|
|
; routine also makes sure that the parent pointer,
|
|
; entry length and entries per block are also correct.
|
|
;
|
|
;input: last_blk ;contains previous dir block
|
|
; entries_blk_num ;parents block number
|
|
; drvr_blk_num ;contains current block number
|
|
;
|
|
;output: A = error if carry set otherwise no error
|
|
|
|
verify_dir
|
|
lda last_blk ;the previous directory block
|
|
beq verify_parent ;this is a special case since
|
|
;no previous block has been read
|
|
cmp [gbuf_ptr]
|
|
beq dir_ok ;this is the way it should be
|
|
bad_dir ;
|
|
lda #dir_error ;this is a bad directory
|
|
sec
|
|
rts
|
|
dir_ok
|
|
lda drvr_blk_num ;setup last block for next time
|
|
sta last_blk
|
|
clc
|
|
rts
|
|
|
|
verify_parent ;
|
|
lda entries_blk_num ;skip check if zero
|
|
beq pass_parent ;don't bother checking parent
|
|
|
|
ldy #$0027 ;index to parent pointer
|
|
cmp [gbuf_ptr],y ;compare to childs parent
|
|
bne bad_dir ;parent/child don't match
|
|
|
|
pass_parent ldy #$0023 ;index to entry length/entries per blk
|
|
lda [gbuf_ptr],y
|
|
cmp #$0D27
|
|
bne bad_directory ;this is something I don't know about
|
|
|
|
ldy #$0025 ;index to total files in directory
|
|
lda [gbuf_ptr],y
|
|
sta files_in_dir
|
|
stz files_examined ;reset files examined
|
|
bra dir_ok
|
|
bad_directory
|
|
lda #version_error ;I don't know about this disk
|
|
sec
|
|
rts
|
|
|
|
;==========================================================================
|
|
;The following routine will look at all the entries within a directory
|
|
;block. The entry is skipped if it is a volume header, subdirectory
|
|
;header or an inactive entry. If an entry is found that is active then
|
|
;it is checked against the name we are looking for. If the name is
|
|
;found then we exit indicating that we have found the file. We
|
|
;continue to look for the name until we have looked at all the entries
|
|
;or the file is found.
|
|
|
|
check_block lda entries_checked
|
|
cmp #entries_per_block
|
|
beq check_done
|
|
inc a
|
|
sta entries_checked
|
|
|
|
lda [gbuf_ptr],y ;get the storage type
|
|
tax
|
|
and #$00F0 ;check for directories
|
|
cmp #$00F0 ;is this the volume Entry????
|
|
bne @chK_sub ;no it is not
|
|
|
|
jsr save_vol_mod ;save the volume modification if possible
|
|
bra next_entry
|
|
@chk_sub
|
|
cmp #$00E0
|
|
bcs next_entry ;skip headers
|
|
txa
|
|
and #$000F ;isolate name length
|
|
beq chk_need_free ;the entry is not active.
|
|
inc files_examined ;advance the number of active files
|
|
jsr save_latest_mod ;save the lastest mod date
|
|
jsr check_name
|
|
bcs next_entry
|
|
rts ;we have found it
|
|
|
|
chk_need_free ;
|
|
lda free_dir_blk ;block that contains a free entry
|
|
bne next_entry
|
|
lda drvr_blk_num
|
|
sta free_dir_blk ;save directory block number
|
|
sty free_dir_offset ;save offset to free entry
|
|
|
|
next_entry
|
|
tya
|
|
clc
|
|
adc #entry_length ;adjust pointer to next entry
|
|
tay
|
|
bra check_block
|
|
|
|
check_done sec ;sorry entry not found
|
|
rts
|
|
|
|
save_vol_mod
|
|
phy ;save directory entry index
|
|
phx
|
|
pha
|
|
|
|
ldy #vol_mod_offset ;get the mod date from the volume header
|
|
lda [gbuf_ptr],y
|
|
sta curr_mod_date
|
|
iny
|
|
iny
|
|
lda [gbuf_ptr],y
|
|
sta curr_mod_date+2
|
|
|
|
pla
|
|
plx
|
|
ply
|
|
rts
|
|
|
|
;Save_lastest_mod will save the lastest mod date that we find. The reason
|
|
;we do this is to allow the mod date to be returned for the volume header.
|
|
|
|
save_latest_mod
|
|
phy ;save directory entry index
|
|
phx
|
|
pha
|
|
|
|
tya
|
|
clc
|
|
adc #last_mod_index
|
|
tay
|
|
lda [gbuf_ptr],y
|
|
tax
|
|
cmp curr_mod_date ;see if the date is greater
|
|
bcc @not_greater
|
|
beq @check_time
|
|
iny
|
|
iny
|
|
lda [gbuf_ptr],y ;get the minutes etc.
|
|
sta curr_mod_date+2
|
|
stx curr_mod_date ;save the new latest date
|
|
bra @not_greater ;just exit
|
|
@check_time
|
|
iny
|
|
iny
|
|
lda [gbuf_ptr],y ;get the minutes etc.
|
|
and #$1F3F ;clear unused bits
|
|
cmp curr_mod_date+2
|
|
bcc @not_greater
|
|
sta curr_mod_date+2
|
|
stx curr_mod_date ;save the new latest date
|
|
|
|
@not_greater
|
|
pla
|
|
plx
|
|
ply
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Check name will examine the name to see if it is the one that
|
|
;we are looking for. If it is not then we return with carry set
|
|
;otherwise we return with carry clear.
|
|
|
|
check_name
|
|
cmp search_length
|
|
bne noway
|
|
sta name_length
|
|
phy ;save y during search
|
|
iny
|
|
|
|
ldx #0000
|
|
|
|
longa off
|
|
sep #$20
|
|
name_loop
|
|
|
|
lda [gbuf_ptr],y
|
|
cmp search_name,x
|
|
bne not_it
|
|
inx
|
|
iny
|
|
dec name_length
|
|
bne name_loop
|
|
rep #$30
|
|
ply
|
|
clc
|
|
rts
|
|
|
|
longa on
|
|
not_it
|
|
rep #$30
|
|
ply
|
|
noway sec
|
|
rts
|
|
|
|
;==========================================================================
|
|
;The following routine when called, will isolate the next name to
|
|
;locate. It does this by looking for the delimiter(delimiter = ':')
|
|
;The last delimiter is a null character.
|
|
|
|
EXPORT setup_name
|
|
setup_name
|
|
phy
|
|
ldy chars_checked ;index into source name
|
|
lda [temp_ptr],y ;are we done yet
|
|
and #$00FF
|
|
bne more_names
|
|
dec path_searched ;the entire path has been searched
|
|
ply
|
|
sec ;indicate we are thru
|
|
rts
|
|
more_names
|
|
longa off
|
|
longi on
|
|
sep #$20 ;short accumulator please
|
|
|
|
ldx #$0000
|
|
looper
|
|
lda [temp_ptr],y
|
|
beq end_path ;end of name and end of string
|
|
cmp #delimiter
|
|
beq end_name ;we found a delimiter
|
|
sta search_name,x
|
|
cpx #$0000 ;is this the first character?
|
|
bne not_first
|
|
|
|
cmp #'a'
|
|
bcc not_lower1
|
|
cmp #'z'+1
|
|
bcs syntax_prob
|
|
and #$DF
|
|
not_lower1
|
|
cmp #'A'
|
|
bcc syntax_prob
|
|
cmp #'Z'+1
|
|
bcc good_syntax
|
|
syntax_prob
|
|
longa on
|
|
longi on
|
|
rep #$20
|
|
lda #bad_path_syntax
|
|
sec
|
|
jmp main_exit ;return to Jim with the error
|
|
|
|
longa off
|
|
longi on
|
|
not_first
|
|
cmp #'a'
|
|
bcc not_lower2
|
|
cmp #'z'+1
|
|
bcs syntax_prob
|
|
and #$DF
|
|
not_lower2
|
|
cmp #'A'
|
|
bcc check_num
|
|
cmp #'Z'+1
|
|
bcs syntax_prob
|
|
good_syntax
|
|
inx
|
|
iny
|
|
bra looper
|
|
check_num
|
|
cmp #'0'
|
|
bcc check_period
|
|
cmp #'9'+1
|
|
bcs syntax_prob
|
|
bra good_syntax
|
|
check_period
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
cmp #' '
|
|
beq good_syntax
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
cmp #'.'
|
|
bne syntax_prob
|
|
bra good_syntax
|
|
end_path
|
|
dec path_searched+1 ;the entire path has been searched
|
|
end_name
|
|
iny
|
|
sty chars_checked
|
|
stx search_length
|
|
|
|
longa on
|
|
longi on
|
|
rep #$30
|
|
ply
|
|
clc
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;init the ProDOS fst
|
|
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT startup
|
|
startup PROC
|
|
|
|
jsl get_sys_gbuf ;get the systems general buffer
|
|
|
|
good ;
|
|
stx gbuf_addr
|
|
sty gbuf_addr+2 ;save pointer to general work buffer
|
|
|
|
clc
|
|
rtl
|
|
|
|
ENDP
|
|
EXPORT shutdown
|
|
shutdown PROC
|
|
clc
|
|
rtl
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;Sys_Remove_vol This file contains code that is called by the system
|
|
; to remove a volume control record (VCR).
|
|
;
|
|
;Input: A = undefined
|
|
; X = (call number * 2)
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT sys_remove_vol
|
|
sys_remove_vol PROC
|
|
|
|
clc
|
|
rtl
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;deferred_flush This file contains code that flush any deferred blocks
|
|
; blocks to disk. This routine is called when the stop
|
|
; session call is issued, and when swapout is called.
|
|
; Since the routine can be called from swapout it must
|
|
; save most of the direct page and local buffers.
|
|
;
|
|
;Input: A = undefined
|
|
; X = (call number * 2)
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT deferred_flush
|
|
deferred_flush PROC
|
|
;
|
|
;Save the world. We do this in case we are called by SwapOut.
|
|
;
|
|
jsr save_def ;save the deferred envirnoment
|
|
jsr standard_req ;write 512 bytes
|
|
lda #blk_size
|
|
sta drvr_blk_size
|
|
|
|
ldx vcr_ptr
|
|
ldy vcr_ptr+2
|
|
stx my_vcr_ptr
|
|
sty my_vcr_ptr+2
|
|
jsr setup_my_vcr
|
|
stx prodos_vcr_ptr
|
|
sty prodos_vcr_ptr+2
|
|
|
|
;
|
|
;Setup ID_Disk routine to ID by volume name ONLY!! This is important
|
|
;since block two is deferred and we are reading block two from the disk.
|
|
;Therefore the two blocks will problably not be the same.
|
|
;
|
|
|
|
lda #$8001 ;set the high bit of FST_NUM
|
|
sta drvr_fst_num ;to force device access
|
|
|
|
;
|
|
;Try to locate the volume we are trying to write too. We do this by
|
|
;calling 'find_Volume'. More then likely the volume is still in the
|
|
;same drive.
|
|
;
|
|
jsr mount_volume ;go and locate the volume please
|
|
bcs bad_bad_news ;we our up the creek!
|
|
|
|
;
|
|
;After finding the volume I will call the 'cache_flsh_def' routine. This
|
|
;routine will write all the deferred blocks to disk.
|
|
;
|
|
lda [my_vcr_ptr] ;setup the VOL ID
|
|
sta drvr_vol_id
|
|
|
|
jsl cache_flsh_def
|
|
bcc exit_deferred
|
|
;
|
|
;Now that we are here we must restore the world and return back to scm
|
|
;via an RTL instruction.
|
|
;
|
|
|
|
bad_bad_news ;
|
|
|
|
exit_deferred ;
|
|
jsr restore_def
|
|
clc
|
|
rtl
|
|
|
|
save_def ;
|
|
php
|
|
phy
|
|
phx
|
|
pha
|
|
|
|
ldx #$004A ;save the direct page data
|
|
save_direct ;
|
|
lda drvr_dev_num,x
|
|
sta def_dir_page,x
|
|
dex
|
|
bpl save_direct
|
|
ldx #$0052 ;save my direct page
|
|
save_my_direct ;
|
|
lda fst_start,x
|
|
sta def_my_direct,x
|
|
dex
|
|
bpl save_my_direct
|
|
ldx #19 ;save the volume name buffers
|
|
save_def_vol ;
|
|
lda volume_name,x
|
|
sta def_vol_name,x
|
|
dex
|
|
bpl save_def_vol
|
|
bra save_rest_exit
|
|
|
|
;======================================================================
|
|
|
|
restore_def ;
|
|
php
|
|
phy
|
|
phx
|
|
pha
|
|
|
|
ldx #$004A ;restore the direct page data
|
|
restore_direct ;
|
|
lda def_dir_page,x
|
|
sta drvr_dev_num,x
|
|
dex
|
|
bpl restore_direct
|
|
ldx #$0052 ;restore my direct page
|
|
restore_dp ;
|
|
lda def_my_direct,x
|
|
sta fst_start,x
|
|
dex
|
|
bpl restore_dp
|
|
ldx #19 ;restore the volume name buffers
|
|
restore_def_vol ;
|
|
lda def_vol_name,x
|
|
sta volume_name,x
|
|
dex
|
|
bpl restore_def_vol
|
|
|
|
save_rest_exit ;
|
|
pla
|
|
plx
|
|
ply
|
|
plp
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;Create: This file will create a new fresh file on disk.
|
|
;
|
|
;Input: A = undefined
|
|
; X = (call number * 2)
|
|
; Y = (class number * 2)
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = error code if carry set (exit via system exit routine)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
; find_file (subroutine)
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Pathname Pointer (4 Bytes)
|
|
; Access (2 Bytes)
|
|
; File Type (2 Bytes)
|
|
; Aux Type (4 Bytes)
|
|
; Storgae_type (2 Bytes)
|
|
; Create Date/Time (4 Bytes: ProDOS Format)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Pathname Pointer (4 Bytes)
|
|
; Access (2 Bytes: E3 if not supplied)
|
|
; File Type (2 Bytes: 00 if not supplied)
|
|
; Aux Type (4 Bytes: 00 if not supplied)
|
|
; Storage Type (2 Bytes: 01 if not supplied)
|
|
; Size Data Fork (4 Bytes: 00 if not supplied)
|
|
; Size Resource Fork (4 Bytes: 00 if not supplied)
|
|
;
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT create
|
|
|
|
create PROC
|
|
with expand_record
|
|
|
|
;Setup the defaults for the create call.
|
|
|
|
stz data_eof
|
|
stz data_eof+2
|
|
stz res_eof
|
|
stz res_eof+2
|
|
|
|
jsr setup_params
|
|
php
|
|
jsr do_create_path
|
|
jsr default_entry ;Build a Entry with All defaults!
|
|
plp
|
|
bne class1 ;this is a new wonder version
|
|
|
|
lda #$0005 ;set PCount for common setup
|
|
sta pcount
|
|
jsr create_common
|
|
|
|
ldy #pblk_01_old_time
|
|
lda [my_pblk_ptr],y ;load the old format time
|
|
tax
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
bne users_date ;user has supplied the data
|
|
txy
|
|
beq both_classes ;us the GS system clock for the time
|
|
|
|
users_date ;
|
|
and #$1F3F ;force the date to correct format.
|
|
beq clock_time ;use the GS clock time please
|
|
sta one_entry+create_index+2
|
|
clock_time ;
|
|
txa ;is the date field set?
|
|
beq both_classes ;use GS clock Date
|
|
stx one_entry+create_index
|
|
bra both_classes
|
|
|
|
class1
|
|
jsr create_common
|
|
|
|
both_classes
|
|
bit expand_flag ;are we expanding a current file?
|
|
bpl @no_expansion
|
|
|
|
lda one_entry+last_mod_index
|
|
pha
|
|
lda one_entry+last_mod_index+2
|
|
pha
|
|
lda storage_type
|
|
pha
|
|
lda one_entry
|
|
pha
|
|
jsr move_dir_entry ;copy the entry from the disk
|
|
pla
|
|
sta one_entry
|
|
pla
|
|
sta storage_type
|
|
pla
|
|
sta one_entry+last_mod_index+2
|
|
pla
|
|
sta one_entry+last_mod_index
|
|
|
|
@no_expansion
|
|
jsr eof_to_blks ;convert bytes to blocks
|
|
;
|
|
;Blocks needed := Data_fork_blks + Res_fork_blks + subdir_blks + storage
|
|
;
|
|
chk_dir ;
|
|
lda #$0000 ;assume zero
|
|
bit expand_file ;are we adding a directory entry?
|
|
bmi no_extend
|
|
ldx free_dir_blk ;is there room for a dir entry?
|
|
bne no_extend ;yes, so don't bump blks needed
|
|
inc a ;add one for directory block needed
|
|
no_extend
|
|
clc
|
|
adc blks_used1 ;blocks for data fork
|
|
clc
|
|
adc blks_used2 ;blocks for resource fork
|
|
sta blocks_needed ;save total blocks needed for file
|
|
bcs @no_room
|
|
|
|
lda storage_type ;if the file is an extended file then add
|
|
cmp #resource_type ;one block for the extended file header
|
|
bne @not_extended
|
|
inc blocks_needed ;bump the blocks needed
|
|
@not_extended
|
|
jsr calc_free_blks ;see if we have enough room for the file
|
|
bcs to_exit
|
|
|
|
bit expand_flag ;are we expanding a current file?
|
|
bpl @chk_sum ;no, so check the sum of the blocks needed
|
|
;
|
|
;We now know that we are extending a file, so we must check the blocks free against the
|
|
;number of blocks needed to add the resource fork. The blocks needed for the resource
|
|
;fork is equal to blks_used2 + 1 (for resource header blk). To compensate for the extra
|
|
;block needed, we will reduce the number of free blocks by 1, then compare against
|
|
;blks_used2 (blocks needed for resource fork).
|
|
;But first, we need to check if the number of free blocks is 0!! CAE 11-6-90
|
|
;
|
|
cmp #0 ;is free blocks = 0?
|
|
beq @no_room ;yes - so can't extend the file
|
|
|
|
dec a ;free blocks := free blocks -1; (compensate for header)
|
|
cmp blks_used2
|
|
bcs it_fits
|
|
bra @no_room ;sorry you cannot extend the file.
|
|
|
|
@chk_sum
|
|
cmp blocks_needed ;do we have enough?
|
|
bcs it_fits ;yes we do.
|
|
@no_room
|
|
lda #volume_full ;no room on volume
|
|
to_exit
|
|
sec
|
|
jmp main_exit
|
|
|
|
it_fits
|
|
jsr build_file ;go and make the file
|
|
bcs create_err
|
|
jsr force_bitmap ;make sure the bitmap is up to date
|
|
bcs create_err
|
|
jsr slug_ripple ;time stamp previous
|
|
create_err
|
|
jmp main_exit
|
|
|
|
;===============END OF THE CREATE CALL
|
|
|
|
|
|
;==========================================================================
|
|
;Build_file This routine will allocate all needed blocks and build
|
|
; the file. It will also handle directory extending etc.
|
|
;
|
|
;input: free_dir_blk ;dir blk with a empty entry.
|
|
; dir_start_blk ;starting block of the directory
|
|
; dir_last_blk ;last block of the directory
|
|
; used_blks1 ;blocks needed for data fork
|
|
; used_blks2 ;blocks needed for resource fork
|
|
; stoarge_type ;type of file to be created
|
|
; data_storage ;storage type of data fork
|
|
; res_storage ;storage type of resource fork
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
|
|
build_file ;
|
|
jsr extend_subdir ;extend the directory IF needed.
|
|
bcc chk_storage
|
|
rts
|
|
|
|
chk_storage ;
|
|
lda storage_type ;see what we are creating
|
|
cmp #subdir_type
|
|
bne chk_next1
|
|
jsr create_subdir ;make a subdirectory
|
|
bcs build_failed
|
|
bra write_dir_entry
|
|
|
|
chk_next1 ;
|
|
cmp #resource_type
|
|
bne chk_next2
|
|
jsr create_resource ;make a resource file
|
|
bcs build_failed
|
|
bra write_dir_entry
|
|
|
|
chk_next2 ;
|
|
cmp #tree_type
|
|
bne chk_next3
|
|
jsr create_tree ;make a tree file
|
|
bcs build_failed
|
|
bra write_dir_entry
|
|
|
|
chk_next3 ;
|
|
cmp #sapling_type
|
|
bne do_seedling
|
|
jsr create_sapling ;make a sapling file
|
|
bcs build_failed
|
|
bra write_dir_entry
|
|
|
|
build_failed ;
|
|
rts
|
|
|
|
do_seedling jsr create_seedling
|
|
bcs build_failed
|
|
|
|
write_dir_entry
|
|
|
|
jsr set_default_buf ;get ready to write the dir entry.
|
|
jsr standard_req
|
|
lda free_dir_blk ;where to store dir entry
|
|
sta drvr_blk_num
|
|
jsr read_with_cache ;read in the directory block
|
|
bcs build_failed ;this is real bad news! bitmap killed.
|
|
|
|
lda dir_start_blk
|
|
sta one_entry+header_ptr_index
|
|
;
|
|
;now let's save the case state of the file please
|
|
;
|
|
lda case_bits ;case bits for this file
|
|
beq @its_all_upper
|
|
bit fst_attr ;If the user has set all upper then skip case code
|
|
bmi @its_all_upper
|
|
ora #$8000 ;set the case active bit.
|
|
sta case_bits
|
|
sta one_entry+version_index
|
|
@its_all_upper
|
|
ldx #$0001
|
|
ldy free_dir_offset
|
|
lda one_entry
|
|
sta [gbuf_ptr],y
|
|
iny
|
|
move_it ;
|
|
lda one_entry,x ;move in the directory entry.
|
|
sta [gbuf_ptr],y
|
|
iny
|
|
iny
|
|
inx
|
|
inx
|
|
cpx #entry_length
|
|
bcc move_it
|
|
|
|
lda drvr_blk_num ;is this 'dir_start_blk'
|
|
cmp dir_start_blk ;If yes then do not write twice
|
|
beq write_once
|
|
|
|
jsr write_with_cache
|
|
bcs build_failed ;sorry, your disk is bad now
|
|
|
|
bit expand_flag ;are we expanding the file?
|
|
bmi chk_pcount ;don't change the number of files in the directory
|
|
|
|
lda dir_start_blk ;now update file count
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcs build_failed
|
|
|
|
write_once
|
|
bit expand_flag ;are we expanding the file? minus = yes
|
|
bmi dont_update_vcr ;don't change the number of files in the directory
|
|
|
|
ldy #header_file_cnt
|
|
lda [gbuf_ptr],y ;load current file count
|
|
inc a ;bump it by one
|
|
sta [gbuf_ptr],y
|
|
|
|
lda drvr_blk_num ;see if this is the volume header
|
|
cmp #vol_dir_start
|
|
bne dont_update_vcr
|
|
|
|
ldy #vol_file_count
|
|
lda [prodos_vcr_ptr],y
|
|
inc a ;bump file count in vcr also
|
|
sta [prodos_vcr_ptr],y
|
|
|
|
dont_update_vcr ;
|
|
jsr write_with_cache
|
|
bcs no_store_type
|
|
chk_pcount lda pcount
|
|
cmp #$0005 ;can we return the storage type
|
|
bcs do_store
|
|
rts
|
|
|
|
do_store ;
|
|
ldy #pblk_01_stype ;set the user's storage type
|
|
lda storage_type
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
sta [my_pblk_ptr],y
|
|
clc
|
|
no_store_type ;
|
|
rts ;exit with error / no error
|
|
|
|
|
|
;==========================================================================
|
|
;create_seed.. This routine will create a seedling file on disk.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = error code if carry set (exit via system exit routine)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; one_entry ;ready to be written to disk
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
|
|
create_seedling ;
|
|
lda #$0001 ;allocate one block please
|
|
sta one_entry+blks_used_index
|
|
; ;setup in default entry
|
|
ldx #$0000 ;start from the beginning.
|
|
jsr find_free_blks ;go and get it
|
|
bcs end_seed ;sorry.
|
|
stx one_entry+key_blk_index
|
|
stx drvr_blk_num
|
|
jsr set_default_buf
|
|
jsr standard_req ;write 512 bytes please
|
|
jsr clear_gbuf_low ;we must write zeros for seedling
|
|
jsr write_with_cache
|
|
end_seed rts
|
|
|
|
;==========================================================================
|
|
;create_sapl.. This routine will create a sapling file one disk.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = error code if carry set (exit via system exit routine)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; one_entry ;ready to be written to disk
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
|
|
create_sapling ;
|
|
jsr setup_index_ptr ;setup pointer for add index
|
|
jsr clear_gbuf_high ;clear high 512 bytes of general buffer
|
|
|
|
lda one_entry ;adjust the storage type
|
|
and #$FF0F ;clear old stoarge type
|
|
ora #sapling_type
|
|
sta one_entry
|
|
|
|
lda blks_used1 ;number of blocks needed for file
|
|
sta one_entry+blks_used_index
|
|
ldx #$0000 ;start from the beginning
|
|
jsr find_free_blks ;see if I have enough room?
|
|
bcs end_sapling
|
|
stx one_entry+key_blk_index
|
|
inx
|
|
stx math_temp
|
|
cmp blks_used1 ;did we get all the blocks needed?
|
|
beq big_sapling
|
|
|
|
|
|
stz first_free ;start from the beginning
|
|
ldy #$0000 ;starting index
|
|
ldx blks_used1
|
|
dex ;blocks to allocate
|
|
sapling_loop ;
|
|
jsr get_one_blk ;allocate another block
|
|
bcs end_sapling ;major problems
|
|
|
|
lda first_free ;block number
|
|
jsr add_index
|
|
iny
|
|
dex
|
|
beq write_sap_index
|
|
bra sapling_loop
|
|
|
|
end_sapling ;
|
|
rts
|
|
|
|
big_sapling ;
|
|
|
|
ldy #$0000 ;starting index value
|
|
ldx blks_used1 ;number of blocks allocated
|
|
dex ;minus one for index block
|
|
build_loop ;
|
|
lda math_temp ;block number
|
|
jsr add_index ;add block to the index
|
|
iny ;move to the next index
|
|
dex
|
|
beq write_sap_index ;write the block to disk
|
|
inc math_temp ;bump to the next block please
|
|
bra build_loop
|
|
|
|
write_sap_index ;
|
|
lda temp4_ptr ;pointer to index block
|
|
sta drvr_buf_ptr
|
|
lda temp4_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
jsr standard_req ;512 byte transfer
|
|
|
|
lda one_entry+key_blk_index
|
|
sta drvr_blk_num ;write the index
|
|
jsr write_with_cache
|
|
rts
|
|
|
|
;==========================================================================
|
|
;create_tree.. This routine will create a tree file one disk.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = error code if carry set (exit via system exit routine)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; one_entry ;ready to be written to disk
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
|
|
create_tree ;
|
|
sec ;allocate a 512 byte buffer please
|
|
lda #blk_size
|
|
jsl alloc_seg
|
|
bcs end_tree ;sorry out of memory!!
|
|
stx virtual
|
|
sty virtual+2 ;save the VP for release seg
|
|
jsl deref ;convert to a real pointer
|
|
stx temp2_ptr
|
|
sty temp2_ptr+2 ;save a pointer to buffer
|
|
|
|
lda #$0001 ;allocate one block for master index
|
|
ldx #$0000 ;start from the beginning
|
|
jsr find_free_blks
|
|
bcs end_tree
|
|
stx tree_key_blk ;save key block of tree file.
|
|
|
|
lda blks_used1
|
|
sta key_block ;save total blocks please
|
|
|
|
sec
|
|
lda blks_used1 ;remove overhead blocks from count
|
|
sbc data_indexes ;number of index blocks needed
|
|
dec a ;subtract one for master index block
|
|
sta tree_blks
|
|
|
|
ldy #$0000 ;starting index for master block
|
|
tree_loop ;
|
|
ldx #256 ;number of blocks to allocate
|
|
lda tree_blks
|
|
cmp #256 ;max blocks+1 in an index block
|
|
bcs use_max
|
|
tax ;use the remaining blocks
|
|
use_max ;
|
|
inx ;add one for index block itself
|
|
stx blks_used1 ;this is the amount to allocate
|
|
phy
|
|
jsr create_sapling ;build a sapling index
|
|
ply
|
|
bcs end_tree ;major problems
|
|
jsr add_master_index
|
|
iny ;advance to next index please
|
|
sec
|
|
lda tree_blks ;number of blocks left
|
|
sbc #256
|
|
sta tree_blks
|
|
beq write_tree
|
|
bcs tree_loop ;do another index block
|
|
|
|
write_tree ;
|
|
lda one_entry
|
|
and #$FF0F ;change storage to tree type
|
|
ora #tree_type
|
|
sta one_entry
|
|
|
|
lda key_block
|
|
sta one_entry+blks_used_index
|
|
|
|
lda temp2_ptr ;setup pointer for write
|
|
sta drvr_buf_ptr
|
|
lda temp2_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
lda tree_key_blk
|
|
sta drvr_blk_num
|
|
sta one_entry+key_blk_index
|
|
jsr write_with_cache
|
|
|
|
end_tree
|
|
php ;save error flag
|
|
pha ;save error if any
|
|
ldx virtual
|
|
ldy virtual+2
|
|
jsl release_seg ;give up the temp buffer
|
|
pla
|
|
plp
|
|
rts ;return any error
|
|
|
|
|
|
add_master_index
|
|
|
|
lda temp2_ptr ;setup pointer to master index block
|
|
sta temp4_ptr
|
|
lda temp2_ptr+2
|
|
sta temp4_ptr+2
|
|
|
|
lda one_entry+key_blk_index
|
|
jsr add_index
|
|
rts
|
|
|
|
|
|
;==========================================================================
|
|
;create_res... This routine will create a resource file.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = error code if carry set (exit via system exit routine)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; one_entry ;ready to be written to disk
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
; 512 bytes additional mem
|
|
|
|
create_resource ;
|
|
lda #prodos_version+(prodos_version*$100)
|
|
sta one_entry+version_index
|
|
|
|
clc
|
|
lda blks_used1
|
|
adc blks_used2
|
|
inc a ;add one for resource header
|
|
sta res_tot_blks
|
|
|
|
sec ;allocate a 512 byte buffer please
|
|
lda #blk_size
|
|
jsl alloc_seg
|
|
bcs @to_end ;sorry out of memory!!
|
|
stx virtual2
|
|
sty virtual2+2 ;save the VP for release seg
|
|
jsl deref ;convert to a real pointer
|
|
stx temp5_ptr ;real pointer to buffer
|
|
sty temp5_ptr+2
|
|
|
|
lda #$0001 ;allocate one block for resource header
|
|
ldx #$0000 ;start from the beginning
|
|
jsr find_free_blks
|
|
@to_end bcs end_resource
|
|
stx res_key_blk ;save key block of resource file.
|
|
|
|
lda data_storage ;go and create the correct data fork
|
|
jsr make_fork
|
|
bcs end_resource ;major problems
|
|
ldy #$0000
|
|
lda data_storage
|
|
jsr save_fork_info
|
|
;
|
|
;Below is a hack. Since the create call was written to add in a directory entry not update
|
|
;an entry, we have to full the update directory routine. To do this I copy in the directory
|
|
;block and entry offset into "free_dir_blk" and "free_dir_offset" This will make the
|
|
;directory update routine work. This is the way we make code do more then it was meant to do.
|
|
;
|
|
bit expand_file ;are we extending the file?
|
|
bpl @no_extend
|
|
lda dir_last_blk ;block number of the directory
|
|
sta free_dir_blk
|
|
lda entries_offset ;offset to the entry within the dir block
|
|
sta free_dir_offset
|
|
@no_extend
|
|
stz expand_file ;we are now thru with the data fork so reset the expand flag
|
|
stz one_entry+eof_index
|
|
stz one_entry+eof_index+1
|
|
|
|
lda blks_used2 ;setup for resource fork create
|
|
sta blks_used1
|
|
lda res_indexes
|
|
sta data_indexes ;used if we are creating a tree file.
|
|
|
|
lda res_storage ;go and create the correct res fork
|
|
jsr make_fork
|
|
bcs end_resource ;major problems
|
|
|
|
ldy #$0100
|
|
lda res_storage
|
|
jsr save_fork_info
|
|
|
|
write_res
|
|
lda one_entry
|
|
and #$FF0F ;change storage to resource type
|
|
ora #resource_type
|
|
sta one_entry
|
|
|
|
lda res_tot_blks
|
|
sta one_entry+blks_used_index
|
|
|
|
lda temp5_ptr ;setup pointer for write
|
|
sta drvr_buf_ptr
|
|
lda temp5_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
lda res_key_blk
|
|
sta drvr_blk_num
|
|
sta one_entry+key_blk_index
|
|
lda #blk_size
|
|
sta one_entry+eof_index
|
|
jsr write_with_cache
|
|
|
|
end_resource
|
|
pha
|
|
php
|
|
ldx virtual2 ;give back the 512 byte temp buffer
|
|
ldy virtual2+2
|
|
jsl release_seg
|
|
plp
|
|
pla
|
|
rts
|
|
|
|
|
|
make_fork ;A = storage type
|
|
bit expand_file ;are we expanding an existing file?
|
|
bpl @not_expanding
|
|
;
|
|
;If we are expanding an existing file I will setup the entry parameters as if I
|
|
;had just created the file. This way we will just bypass the create call.
|
|
;
|
|
lda expand_storage ;move the real storage type
|
|
sta data_storage
|
|
lda expand_key_blk ;move the real key block of the file
|
|
sta one_entry+key_blk_index
|
|
lda expand_blks_used
|
|
sta one_entry+blks_used_index
|
|
lda expand_eof
|
|
sta one_entry+eof_index
|
|
lda expand_eof+1
|
|
sta one_entry+eof_index+1
|
|
clc
|
|
rts
|
|
|
|
@not_expanding
|
|
cmp #seedling_type
|
|
bne res_sap
|
|
jsr create_seedling
|
|
rts
|
|
|
|
res_sap ;
|
|
cmp #sapling_type
|
|
bne res_tree
|
|
jsr create_sapling
|
|
rts
|
|
|
|
res_tree ;
|
|
jsr create_tree
|
|
rts
|
|
|
|
save_fork_info ;A = storage, Y = index into header
|
|
lsr a ;temp5_ptr = pointer to header
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
sta [temp5_ptr],y
|
|
iny
|
|
lda one_entry+key_blk_index
|
|
sta [temp5_ptr],y
|
|
iny
|
|
iny
|
|
lda one_entry+blks_used_index
|
|
sta [temp5_ptr],y
|
|
iny
|
|
iny
|
|
lda one_entry+eof_index
|
|
sta [temp5_ptr],y
|
|
iny
|
|
lda one_entry+eof_index+1
|
|
sta [temp5_ptr],y
|
|
rts
|
|
|
|
|
|
;==========================================================================
|
|
;create_subdir This routine will create a new subdirectory on disk
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = error code if carry set (exit via system exit routine)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; one_entry ;ready to be written to disk
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
;
|
|
|
|
create_subdir ;
|
|
jsr setup_index_ptr ;setup temp4_ptr to point to gbuf+$200
|
|
jsr clear_gbuf_high ;clear high 512 bytes of general buffer
|
|
|
|
lda #$000F ;force file type to subdirectory
|
|
sta one_entry+file_type_index
|
|
|
|
lda blks_used1 ;number of blocks needed for subdir.
|
|
sta one_entry+blks_used_index
|
|
tax
|
|
asl a ;convert blocks to EOF
|
|
sta one_entry+eof_index+1
|
|
|
|
txa
|
|
ldx #$0000 ;start from the beginning
|
|
jsr find_free_blks ;see if I have enough room?
|
|
bcs end_subdir ;major problem my friend
|
|
stx one_entry+key_blk_index
|
|
stx parent_blk
|
|
inx
|
|
stx math_temp
|
|
pha ;save number of blocks allocated
|
|
jsr make_sub_header ;build the header block to disk
|
|
pla
|
|
cmp blks_used1 ;did we get all the blocks needed?
|
|
beq seq_subdir ;yes we can make the directory seq
|
|
|
|
dec blks_used1
|
|
|
|
non_seq_loop ;
|
|
lda #$0001 ;allocate one block
|
|
ldx #$0000 ;start from the beginning
|
|
jsr find_free_blks
|
|
bcs end_subdir
|
|
stx math_temp ;the new block.
|
|
txa
|
|
ldx parent_blk ;block that needs to be written
|
|
jsr update_forward
|
|
bcs end_subdir
|
|
|
|
lda one_entry+key_blk_index
|
|
cmp parent_blk
|
|
bne no_clr
|
|
|
|
jsr clear_gbuf_high ;clear high 512 bytes of general buffer
|
|
|
|
no_clr ;
|
|
lda parent_blk ;update backward link please
|
|
sta [temp4_ptr]
|
|
lda math_temp ;this is the new block to write
|
|
sta parent_blk
|
|
dec blks_used1 ;see if we are done
|
|
bne non_seq_loop
|
|
lda #$0000
|
|
ldx math_temp
|
|
jsr update_forward
|
|
bcc end_subdir
|
|
rts
|
|
|
|
good_subdir
|
|
clc
|
|
|
|
end_subdir
|
|
php ;save error flag
|
|
pha
|
|
lda one_entry
|
|
and #$FF0F ;change storage to subdirectory
|
|
ora #subdir_type
|
|
sta one_entry
|
|
pla ;restore possible error code
|
|
plp ;restore error flag
|
|
rts
|
|
|
|
seq_subdir ;
|
|
lda #$0000 ;default forward link
|
|
ldy blks_used1
|
|
dey ;is there another block?
|
|
beq last_dir_blk
|
|
lda math_temp ;forward link
|
|
|
|
last_dir_blk ;
|
|
ldx one_entry+key_blk_index ;block to write to disk
|
|
jsr update_forward ;write the block to disk
|
|
bcs end_subdir ;bad news
|
|
jsr clear_gbuf_high ;clear high 512 bytes of general buffer
|
|
|
|
seq_sub_loop ;
|
|
dec blks_used1 ;see if we are done
|
|
beq good_subdir
|
|
|
|
lda drvr_blk_num ;this is the backward link now
|
|
sta [temp4_ptr]
|
|
|
|
lda #$0000
|
|
ldy blks_used1 ;is there more blocks to write?
|
|
dey
|
|
beq write_last ;no this is the last one
|
|
lda math_temp
|
|
inc a ;make a forward link
|
|
|
|
write_last ;
|
|
ldx math_temp ;block number to write
|
|
inc math_temp ;bump to the next block
|
|
jsr update_forward
|
|
bcc seq_sub_loop
|
|
bra end_subdir
|
|
|
|
|
|
;==========================================================================
|
|
;update_forward This routine will update the forward link of a directory
|
|
; block then write the block to disk.
|
|
;
|
|
;input: A = forward link
|
|
; X = block number to write
|
|
;
|
|
;output: A = error code if carry set
|
|
;
|
|
update_forward ;
|
|
ldy #$0002 ;forward link
|
|
sta [temp4_ptr],y
|
|
stx drvr_blk_num ;save block number to write
|
|
|
|
lda temp4_ptr ;setup pointer to block.
|
|
sta drvr_buf_ptr
|
|
lda temp4_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
jsr write_with_cache
|
|
rts ;update the disk!
|
|
|
|
;==========================================================================
|
|
;This routine will create the header block for the subdirectory.
|
|
;
|
|
;input: X = header block +1
|
|
; temp4_ptr = pointer to work buffer
|
|
|
|
make_sub_header ;
|
|
dex ;block number to write
|
|
stx drvr_blk_num
|
|
clc
|
|
lda temp4_ptr
|
|
sta drvr_buf_ptr
|
|
adc #$0004
|
|
sta temp_ptr
|
|
lda temp4_ptr+2 ;setup pointer for the write
|
|
sta drvr_buf_ptr+2
|
|
adc #$0000
|
|
sta temp_ptr+2 ;setup pointer to header
|
|
|
|
ldy #entry_length-1
|
|
move_header ;
|
|
lda one_entry,y
|
|
sta [temp_ptr],y
|
|
dey
|
|
dey
|
|
bpl move_header ;move the header into first block
|
|
|
|
ldy #access_index
|
|
lda [temp_ptr],y
|
|
and #$FF00
|
|
ora #$00C3
|
|
sta [temp_ptr],y
|
|
|
|
lda [temp_ptr]
|
|
and #$FF0F
|
|
ora #subdir_header
|
|
sta [temp_ptr]
|
|
|
|
ldy #$001F ;index to entry len and entries per blk
|
|
lda #$0D27 ;13 entries per blk and 39 byte entries
|
|
sta [temp_ptr],y
|
|
iny
|
|
iny ;point to file count
|
|
lda #$0000
|
|
sta [temp_ptr],y ;no files yet
|
|
iny
|
|
iny
|
|
lda free_dir_blk ;parent pointer
|
|
sta [temp_ptr],y
|
|
iny
|
|
iny
|
|
jsr make_entry_num
|
|
bcc go_on_please
|
|
jmp main_exit
|
|
|
|
go_on_please
|
|
sta [temp_ptr],y
|
|
|
|
ldy #$0010 ;clear reserved area
|
|
lda #$0000
|
|
clear_reserved
|
|
sta [temp_ptr],y
|
|
iny
|
|
iny
|
|
cpy #$0018
|
|
bcc clear_reserved
|
|
|
|
ldy #$0010 ;setup for no 'HUSTON'
|
|
lda #$0076
|
|
sta [temp_ptr],y
|
|
rts
|
|
|
|
EXPORT make_entry_num
|
|
make_entry_num
|
|
ldx #(12*2) ;index into offset table
|
|
lda free_dir_offset
|
|
offset_loop cmp dir_offset_tbl,x
|
|
beq found_offset
|
|
dex
|
|
dex
|
|
bpl offset_loop
|
|
|
|
lda #dir_error
|
|
sec
|
|
rts
|
|
|
|
found_offset
|
|
|
|
txa
|
|
lsr a ;divide by two
|
|
inc a ;add one to convert from zero based.
|
|
ora #$2700 ;add in parent entry length
|
|
clc
|
|
rts
|
|
|
|
;==========================================================================
|
|
;setup_index... This routine will setup temp4_ptr to point to the second
|
|
; half of the general work buffer supplied by GS/OS.
|
|
;==========================================================================
|
|
setup_index_ptr
|
|
clc
|
|
lda gbuf_ptr ;set temp4_ptr to point to second
|
|
adc #$0200 ;have of the general work buffer.
|
|
sta temp4_ptr
|
|
lda gbuf_ptr+2
|
|
adc #$0000
|
|
sta temp4_ptr+2
|
|
rts
|
|
|
|
;==========================================================================
|
|
;get_one_blk This routine will allocate one block from disk
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; gbuf_ptr
|
|
;
|
|
;Output: A = restored or error code if carry set.
|
|
; X = restored
|
|
; Y = restored
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; first_free ;block number allocated
|
|
;
|
|
;Uses: find_free_blks
|
|
;
|
|
;==========================================================================
|
|
|
|
get_one_blk
|
|
pha
|
|
phx
|
|
phy
|
|
|
|
lda #$0001 ;allocate one block
|
|
ldx first_free ;start at the beginning
|
|
jsr find_free_blks
|
|
bcs exit_with_err
|
|
stx first_free
|
|
bra exit_one_blk
|
|
|
|
exit_with_err
|
|
sta 5,s ;store the error code on the stack!
|
|
|
|
exit_one_blk
|
|
ply
|
|
plx
|
|
pla
|
|
rts
|
|
|
|
;==========================================================================
|
|
;add_index This routine will add in a block to an index buffer.
|
|
;
|
|
;Input: A = block number
|
|
; X = undefined
|
|
; Y = index into buffer
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; temp4_ptr
|
|
;
|
|
;Output: A = restored
|
|
; X = restored
|
|
; Y = restored
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: temp4_ptr
|
|
;
|
|
;==========================================================================
|
|
|
|
EXPORT add_index
|
|
add_index
|
|
phx
|
|
phy
|
|
pha
|
|
|
|
tya
|
|
ora #$0100 ;index to second half of buffer
|
|
tax
|
|
|
|
lda 1,s
|
|
longa off
|
|
sep #$20
|
|
sta [temp4_ptr],y ;store the low byte please
|
|
txy ;index to second half of buffer
|
|
xba ;high word of the block number
|
|
sta [temp4_ptr],y
|
|
longa on
|
|
rep #$20
|
|
|
|
pla ;restore A
|
|
ply ;restore Y
|
|
plx ;restore X
|
|
rts ;exit
|
|
|
|
|
|
;==========================================================================
|
|
;eof_to_blks This routine will convert the size of the file into the
|
|
; number of blocks needed to store the file on disk. The
|
|
; routine does NOT account for directory extension that is
|
|
; handled elsewhere, it does however account for storage
|
|
; type.
|
|
;
|
|
;Input: data_eof ;size of data fork
|
|
; res_eof ;size of resource fork
|
|
;
|
|
;output: blks_used1 ;blocks needed for data fork/subdir
|
|
; blks_used2 ;blocks needed for resource fork
|
|
;
|
|
;==========================================================================
|
|
EXPORT eof_to_blks
|
|
eof_to_blks
|
|
lda expand_file ;are we expanding a file or building a new one?
|
|
bpl @its_new
|
|
|
|
lda expand_blks_used
|
|
sta blks_used1 ;set the number of blocks needed for current file
|
|
bra do_res ;now do the resource fork
|
|
@its_new
|
|
lda data_eof+1 ;convert bytes to blocks
|
|
lsr a
|
|
sta blks_used1 ;blocks needed by data fork
|
|
beq bump_blks1 ;see if we need to round up
|
|
lda data_eof ;see if size is < 512
|
|
and #$01FF
|
|
beq do_res ;no need to bump
|
|
bump_blks1 ;
|
|
inc blks_used1
|
|
|
|
do_res
|
|
lda storage_type ;do we need resources?
|
|
cmp #resource_type
|
|
bne end_eof_conv ;not a resource file
|
|
|
|
lda res_eof+1 ;convert bytes to blocks
|
|
lsr a
|
|
sta blks_used2 ;blocks needed by data fork
|
|
beq bump_blks2 ;see if we need to round up
|
|
lda res_eof ;see if size is < 512
|
|
and #$01FF
|
|
beq end_eof_conv ;no need to bump resource size
|
|
bump_blks2 ;
|
|
inc blks_used2 ;add for resource file
|
|
|
|
end_eof_conv
|
|
lda expand_file ;are we expanding a file or building a new one?
|
|
bmi @skip_adjust ;since the blocks used is already the total skip adjust
|
|
|
|
lda blks_used1 ;add any storage overhead for data fork
|
|
jsr adjust_storage
|
|
sta blks_used1
|
|
sty data_storage ;storage type for data fork
|
|
stx data_indexes ;number of index blocks
|
|
@skip_adjust
|
|
lda blks_used2 ;add any storage overhead for res. fork
|
|
jsr adjust_storage
|
|
sta blks_used2
|
|
sty res_storage ;storage type for resource fork
|
|
stx res_indexes ;number if inedx blocks
|
|
rts
|
|
|
|
;==========================================================================
|
|
;do_create_path This routine will setup the flags needed to process the
|
|
; input pathname. we only return from the subroutine if
|
|
; everything with the pathname is OK.
|
|
;
|
|
;input: none
|
|
;
|
|
;output: seach_name is still valid from find file.
|
|
;
|
|
;==========================================================================
|
|
do_create_path
|
|
lda #no_root+no_dup ;root level or duplciate is not valid.
|
|
sta search_flag
|
|
jsr process_path
|
|
bcs no_dup_problem ;there is no duplicate file
|
|
;
|
|
;If the file already is on the disk we need to see if we are adding the resource
|
|
;fork. If we are adding the resource fork we will pull out the important information
|
|
;from the current file entry (data fork) and save if so we can use it to build the
|
|
;data fork of are new extended file
|
|
;
|
|
ldy #pblk_01_stype ;see if we are adding a resource fork to the file
|
|
lda [my_pblk_ptr],y ;get the input storage type
|
|
cmp #(resource_type/$10)+$8000
|
|
bne @not_an_extend
|
|
sta expand_file ;set the flag indicating we are extending the file
|
|
sta expand_flag ;expand_flag lives thru the entire call, whereas expand_file
|
|
;only lives thru the create data fork portion of the call.
|
|
;
|
|
;now lets setup the important information:
|
|
; storage type
|
|
; key block
|
|
; blks_used
|
|
; eof
|
|
;
|
|
;Remember drvr_buf_ptr points to the prodos directory entry
|
|
;
|
|
lda [drvr_buf_ptr] ;get the storage type please
|
|
and #$00F0 ;clear the garbage
|
|
cmp #resource_type ;see if the resource fork is already here.
|
|
beq @no_extend
|
|
cmp #tree_type+1 ;file must be a seedling sapling or tree
|
|
bcs @storage_err ;we cannot extend this file
|
|
sta expand_storage
|
|
sta data_storage ;this will be a 10,20 or 30 (seedling, sapling or tree)
|
|
|
|
ldy #key_blk_index
|
|
lda [drvr_buf_ptr],y
|
|
sta expand_key_blk ;save the key block for the data fork
|
|
|
|
ldy #blks_used_index
|
|
lda [drvr_buf_ptr],y
|
|
sta expand_blks_used
|
|
|
|
ldy #eof_index
|
|
lda [drvr_buf_ptr],y
|
|
sta expand_eof
|
|
iny
|
|
lda [drvr_buf_ptr],y
|
|
sta expand_eof+1
|
|
bra no_dup_problem
|
|
@no_extend
|
|
lda #resource_exist ;the resource already exist bud.
|
|
sec
|
|
bra real_problem
|
|
@storage_err
|
|
lda #res_add_err ;the resource cannot be added to this type file
|
|
sec
|
|
bra real_problem
|
|
@not_an_extend
|
|
sec
|
|
lda #dup_pathname
|
|
real_problem
|
|
sec
|
|
jmp main_exit
|
|
|
|
no_dup_problem
|
|
bit path_searched ;was the entire path searched?
|
|
bpl real_problem ;no, only a portion.
|
|
jsr chk_disk_protect ;is the volume write protected?
|
|
rts ;If protected, routine will not return
|
|
|
|
;==========================================================================
|
|
;adjust_storage This routine will add in the overhead of the storage type
|
|
; to the blocks used for a file.
|
|
;
|
|
;input: A = blocks
|
|
;
|
|
;output: A = blocks + overhead
|
|
; Y = storage type needed for size
|
|
; X = number of index blocks needed (for tree only)
|
|
;
|
|
;uses: math_temp
|
|
;
|
|
;Overhead:
|
|
; subdirectories: no overhead
|
|
; seedling: no overhead
|
|
; sapling: 1 block of overhead
|
|
; tree: ((blks div 256) + (blks mod 256)) + 1
|
|
;==========================================================================
|
|
|
|
adjust_storage
|
|
sta math_temp ;number of file blocks
|
|
stz index_blks ;no tree index blocks. (default)
|
|
|
|
ldy #subdir_type
|
|
ldx storage_type
|
|
cpx #subdir_type
|
|
beq end_overhead ;no overhead for directories
|
|
|
|
ldy #seedling_type ;this is a seedling type
|
|
|
|
cmp #$0002
|
|
bcc end_overhead ;no overhead
|
|
cmp #$0101 ;check high end of sapling
|
|
bcs data_tree ;this is a tree file
|
|
inc math_temp ;add one for sapling overhead
|
|
ldy #sapling_type
|
|
bra end_overhead
|
|
|
|
data_tree
|
|
lda math_temp+1 ;see how many sapling blocks we need
|
|
and #$00FF
|
|
sta index_blks ;number of index blocks needed
|
|
clc
|
|
adc math_temp
|
|
tax
|
|
lda math_temp
|
|
and #$00FF
|
|
beq no_extra
|
|
inc index_blks ;add one to number of indexes needed
|
|
inx
|
|
stx math_temp ;adjust for $xx01 thru $xxFF
|
|
|
|
no_extra
|
|
inx
|
|
stx math_temp ;add extra block for tree header.
|
|
ldy #tree_type
|
|
|
|
end_overhead
|
|
lda math_temp
|
|
ldx index_blks ;index blocks for the tree file.
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Default_entry: This routine will fill 'one_entry' with the default
|
|
;values for a file.
|
|
;
|
|
; storage type = seedling
|
|
; File Type = unknown ($00)
|
|
; Blks Used = $0001
|
|
; EOF = $000000
|
|
; Version = $05
|
|
; Minimum Version = $00
|
|
; access = $E3
|
|
; create date/time = Current Time
|
|
; mod date/time = Current Time
|
|
; aux type = $0000
|
|
;
|
|
;NOTE: The store operations happen in a certain order so as to not overwrite
|
|
; information already stored.
|
|
;==========================================================================
|
|
|
|
default_entry
|
|
ldy #$0026 ;zero the entry
|
|
lda #$0000
|
|
clr_name
|
|
sta one_entry,y
|
|
dey
|
|
dey
|
|
bpl clr_name
|
|
|
|
lda #seedling_type ;set the default storage type
|
|
sta storage_type
|
|
|
|
stz one_entry+file_type_index
|
|
lda #$0001
|
|
sta one_entry+blks_used_index
|
|
stz one_entry+eof_index
|
|
stz one_entry+eof_index+1
|
|
jsr pack_time ;read the GS Clock and set the current time
|
|
stx one_entry+create_index
|
|
sty one_entry+create_index+2
|
|
stx one_entry+last_mod_index
|
|
sty one_entry+last_mod_index+2
|
|
lda #prodos_version
|
|
sta one_entry+version_index
|
|
lda #$00E3
|
|
sta one_entry+access_index
|
|
stz one_entry+aux_type_index
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Create_Common: This routine will setup and verify parameters supplied
|
|
; by the caller. It will also move the file name into
|
|
; one_entry.
|
|
;
|
|
;input: my_pblk_ptr ;must point to pathname field
|
|
;
|
|
;output: returns to caller or jmps to sys_exit with error
|
|
;
|
|
; Access Byte:
|
|
; _______________________________
|
|
; | | | | | | | | |
|
|
; | 1 | 1 | 1 | | | 1 | 1 | 1 |
|
|
; |___|___|___|___|___|___|___|___|
|
|
; ^ ^ ^ ^ ^ ^
|
|
; | | | | | |
|
|
; | | | Invisible | Read-Enabled
|
|
; | | | Write-Enabled
|
|
; | | Backup-Enabled
|
|
; | Rename-Enabled
|
|
; Destroy-Enabled
|
|
;
|
|
;==========================================================================
|
|
|
|
create_common ;
|
|
|
|
ldy search_length ;length of name to create
|
|
longa off
|
|
sep #$20
|
|
name_loop lda search_name-1,y ;move name to directory entry
|
|
sta one_entry,y
|
|
dey
|
|
bne name_loop
|
|
lda search_length
|
|
ora storage_type ;add in the storage type
|
|
sta one_entry ;store storage/length byte
|
|
longa on
|
|
rep #$20
|
|
|
|
lda pcount ;see if we are done
|
|
dec a
|
|
bne cont01
|
|
rts
|
|
|
|
cont01
|
|
sta math_temp
|
|
|
|
ldy #pblk_01_accs ;check the access
|
|
lda [my_pblk_ptr],y
|
|
tax ;save access so we can verify range
|
|
and #$FF18 ;Destroy,Rename,Backup,Invisible,Write,Read
|
|
beq good_access ;no problem
|
|
|
|
not_in_range
|
|
sec
|
|
lda #parm_range_err
|
|
jmp main_exit ;no return from here
|
|
|
|
good_access ;WARNING zero is stored in half of aux.
|
|
txa
|
|
ora #backup_enabled ;force the backup bit please.
|
|
sta one_entry+access_index
|
|
|
|
dec math_temp ;see if any more fields?
|
|
beq to_end_common
|
|
|
|
ldy #pblk_01_ftype ;get the user's file type
|
|
lda [my_pblk_ptr],y
|
|
xba
|
|
bne not_in_range
|
|
xba ;put file type in low byte please
|
|
sep #$20 ;08 bit accum
|
|
sta one_entry+file_type_index
|
|
rep #$20 ;16 bit accum
|
|
|
|
cmp #dir_file_type ;set storage to SubDir incase PCount = 4
|
|
bne skip_storage ;do not setup the storage type
|
|
|
|
lda #subdir_type
|
|
sta storage_type
|
|
|
|
skip_storage
|
|
|
|
dec math_temp ;are we done?
|
|
beq end_common
|
|
|
|
ldy #pblk_01_aux+2 ;get the user's aux type
|
|
lda [my_pblk_ptr],y
|
|
bne not_in_range ;sorry bud
|
|
dey
|
|
dey
|
|
lda [my_pblk_ptr],y
|
|
sta one_entry+aux_type_index
|
|
|
|
dec math_temp ;are we done?
|
|
to_end_common
|
|
beq end_common ;yes
|
|
|
|
ldy #pblk_01_stype ;get the user's storage type
|
|
lda [my_pblk_ptr],y
|
|
and #$7FFF ;clear the expand file bit please
|
|
|
|
beq standard_file ;seedling is the default
|
|
xba
|
|
bne not_in_range ;parameter not valid
|
|
|
|
xba
|
|
cmp #(tree_type/$10)+1
|
|
bcc standard_file ;seedling is the default
|
|
cmp #(resource_type/$10)
|
|
beq force_resource
|
|
cmp #(subdir_type/$10)
|
|
bne not_in_range
|
|
lda #subdir_type
|
|
sta storage_type ;we are making a directory
|
|
bra next_parm
|
|
force_resource
|
|
lda #resource_type
|
|
sta storage_type
|
|
bra next_parm
|
|
|
|
standard_file
|
|
lda #seedling_type
|
|
sta storage_type
|
|
next_parm
|
|
lda storage_type ;if storage is subdirectory then force filetype
|
|
cmp #subdir_type
|
|
bne @not_subdir
|
|
|
|
lda #dir_file_type ;set file type to subdirectory
|
|
sep #$20
|
|
sta one_entry+file_type_index
|
|
rep #$20 ;16 bit accum
|
|
|
|
@not_subdir
|
|
dec math_temp ;are we done?
|
|
beq end_common
|
|
|
|
ldy #pblk_01_eof1+2 ;data fork EOF
|
|
jsr create_eof
|
|
stx data_eof
|
|
sty data_eof+2
|
|
|
|
dec math_temp ;is there a resource eof.
|
|
beq end_common
|
|
|
|
lda storage_type ;is this a resource file?
|
|
cmp #resource_type
|
|
bne end_common ;don't bother checking
|
|
|
|
ldy #pblk_01_eof2+2
|
|
jsr create_eof
|
|
stx res_eof
|
|
sty res_eof+2
|
|
|
|
end_common ;
|
|
rts
|
|
|
|
|
|
;==========================================================================
|
|
;Create_Eof: This routine returns the EOF supplied by the user
|
|
;
|
|
;Input: my_pblk_ptr (must be setup)
|
|
; Y register (index into parameter block)
|
|
;
|
|
;Output: X register = low word of EOF
|
|
; Y register = high word of EOF
|
|
; storage_type adjusted for correct eof
|
|
;
|
|
;==========================================================================
|
|
|
|
create_eof ;
|
|
lda [my_pblk_ptr],y
|
|
xba
|
|
bne not1_in_range ;I cannot make a file this large
|
|
xba
|
|
pha
|
|
dey
|
|
dey
|
|
lda [my_pblk_ptr],y ;get the low word
|
|
tax ;save low word of eof
|
|
ply ;save high word of eof
|
|
|
|
lda storage_type ;adjust storage type as needed
|
|
cmp #resource_type
|
|
beq end_create_eof
|
|
cmp #subdir_type
|
|
beq entry_to_bytes
|
|
|
|
tya ;see what type of file is needed
|
|
lsr a
|
|
beq not_tree ;this cannot be a tree file
|
|
cmp #$0002 ;still might be a sapling
|
|
bcs is_tree
|
|
txa ;if low word is zero then its a sapl.
|
|
beq make_sap
|
|
is_tree
|
|
lda #tree_type
|
|
sta storage_type
|
|
rts
|
|
not_tree
|
|
tya ;See if EOF greater then 512
|
|
bne make_sap ;This file must be a sapling file!
|
|
txa
|
|
cmp #$0201 ;is the eof < 512
|
|
bcc make_seedling
|
|
make_sap ;
|
|
lda #sapling_type
|
|
sta storage_type
|
|
rts
|
|
|
|
make_seedling ;
|
|
lda #seedling_type
|
|
sta storage_type
|
|
|
|
end_create_eof ;
|
|
rts ;exit to caller
|
|
|
|
not1_in_range ;
|
|
sec
|
|
lda #parm_range_err
|
|
jmp main_exit
|
|
|
|
entry_to_bytes ; ;convert file entries to bytes
|
|
tya ;check high byte of entries wanted
|
|
bne not1_in_range
|
|
cpx #1664 ;no more then 1663 entries for subdirs.
|
|
bcs not1_in_range
|
|
txa ;convert entries to bytes
|
|
pha
|
|
;
|
|
; Convert number of entries to bytes needed.
|
|
;
|
|
; Bytes := ((entries * 3) * 13 + ((entries / 13) + 5))
|
|
;
|
|
clc
|
|
asl a ;times 2
|
|
adc 1,s ;times 3
|
|
sta 1,s ;math_temp
|
|
|
|
asl a ;times 2
|
|
asl a ;times 4
|
|
adc 1,s ;times 5
|
|
adc 1,s ;times 6
|
|
asl a ;times 12
|
|
adc 1,s ;times 13
|
|
|
|
adc #13 ;add 13 for the header field needed
|
|
pha ;save partial
|
|
|
|
sub_loop ;
|
|
txa ;restore number if entries left
|
|
sec
|
|
sbc #13 ;subtract 13 entries
|
|
beq sub_done ;we are done
|
|
bcc sub_done
|
|
tax
|
|
clc
|
|
lda 1,s ;get the partial
|
|
adc #$0005 ;add in block overhead for each block
|
|
sta 1,s
|
|
bra sub_loop
|
|
|
|
sub_done plx ;save bytes in X register
|
|
pla ;clean up stack
|
|
rts
|
|
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;Destroy: This routine will delete a file from the disk.
|
|
;
|
|
;Created: may 28, 1987
|
|
;Modified: jun 04, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; find_file
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Pathname Pointer (4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Pathname Pointer (4 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT destroy
|
|
destroy PROC
|
|
|
|
;==========================================================================
|
|
;Go and setup the defaul parameters for the call.
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
|
|
;==========================================================================
|
|
;Process the file name and locate it.
|
|
;==========================================================================
|
|
|
|
jsr process_path
|
|
jsr chk_disk_protect
|
|
|
|
;==========================================================================
|
|
;Now that we have located the file we need to see if its OK to destroy it.
|
|
;
|
|
;We can delete any file except the volume header, or a file that is destroy
|
|
;disabled.
|
|
;==========================================================================
|
|
|
|
lda [drvr_buf_ptr]
|
|
and #$00F0
|
|
sta math_temp ;save the storage type for later
|
|
cmp #volume_header
|
|
bne check_access
|
|
|
|
wrong_access
|
|
lda #invalid_access
|
|
destroy_error
|
|
sec
|
|
destroy_exit
|
|
jmp main_exit
|
|
|
|
check_access
|
|
jsr move_dir_entry
|
|
|
|
ldy #access_index
|
|
lda [drvr_buf_ptr],y
|
|
and #destroy_enabled
|
|
beq wrong_access ;file is marked as 'destory disabled'
|
|
|
|
|
|
;==========================================================================
|
|
;make sure the file that they are deleting is NOT open
|
|
;==========================================================================
|
|
|
|
ldy #key_blk_index ;see if the file is open
|
|
lda [drvr_buf_ptr],y
|
|
sta files_key_block
|
|
stz fcr_wanted ;reset for search
|
|
|
|
look_loop
|
|
jsr get_next_fcr
|
|
bcs not_open
|
|
|
|
ldy #fcr_vol_id
|
|
lda [my_fcr_ptr],y ;get the Volume ID so we can make sure the file is on
|
|
cmp [my_vcr_ptr] ;the same volume.
|
|
bne look_loop ;File is on another volume
|
|
|
|
ldy #fcr_file_id
|
|
lda [pro_fcr_ptr],y ;see if this is the same file
|
|
cmp files_key_block
|
|
bne look_loop
|
|
lda #file_busy
|
|
bra destroy_error ;cannot delete an open file
|
|
|
|
not_open
|
|
|
|
ldy files_key_block
|
|
lda math_temp ;storage TYPE!!!
|
|
cmp #subdir_type
|
|
bne check_tree
|
|
|
|
;==========================================================================
|
|
;It's a directory so go ahead and try to delete it. We can only delete
|
|
;it if there are no files in the directory. Y=key block of the file
|
|
;==========================================================================
|
|
jsr kill_dir ;Y=key block
|
|
bra update_dir
|
|
|
|
check_tree ;
|
|
cmp #tree_type
|
|
bne check_sapling
|
|
|
|
;==========================================================================
|
|
;Go ahead and remove the tree file if you can. Y=Key block of the file
|
|
;==========================================================================
|
|
jsr kill_tree ;Y=Key block of the file
|
|
bra update_dir ;update the directory now
|
|
|
|
check_sapling ;
|
|
cmp #sapling_type
|
|
bne check_seedling
|
|
|
|
;==========================================================================
|
|
;it's a sapling file so remove it. Y=key block of the file
|
|
;==========================================================================
|
|
|
|
jsr kill_sapling
|
|
bra update_dir
|
|
|
|
check_seedling ;
|
|
cmp #seedling_type
|
|
bne check_res ;it better be a resource file
|
|
|
|
;==========================================================================
|
|
;This is a simple file to delete. Y=data block that needs to be deleted
|
|
;==========================================================================
|
|
|
|
jsr kill_seedling
|
|
bra update_dir
|
|
|
|
check_res
|
|
cmp #resource_type
|
|
bne wrong_type
|
|
|
|
;==========================================================================
|
|
;This is the hardest of the files to delete, since it is made up of many
|
|
;files. Y=key block of the file
|
|
;==========================================================================
|
|
|
|
jsr kill_resource
|
|
bra update_dir
|
|
|
|
wrong_type
|
|
lda #bad_store_type ;I should NEVER get this error!
|
|
brl destroy_error
|
|
|
|
|
|
update_dir
|
|
php
|
|
pha ;save the error code and flag
|
|
|
|
jsr flush_bitmap ;write out any left over bitmap changes
|
|
bcs piggy_back
|
|
|
|
;==========================================================================
|
|
;at this point we have removed all the blocks of the file. We now need
|
|
;to update the directory entry itself. The following parameters better
|
|
;be setup correctly or death and destruction will occur.
|
|
;
|
|
; entries_blk_num (block number of the entry to delete)
|
|
; entry_offset (offset to entry within the block)
|
|
; dir_start_blk (header block for this directory)
|
|
;
|
|
;==========================================================================
|
|
|
|
;==========================================================================
|
|
;Setup the buffer pointer and device parameters
|
|
;==========================================================================
|
|
|
|
jsr set_default_buf
|
|
|
|
;==========================================================================
|
|
;We want to load in the block that contains the files entry.
|
|
;==========================================================================
|
|
|
|
lda entries_blk_num
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcs piggy_back
|
|
|
|
;==========================================================================
|
|
;We have loaded the block, now lets zap the entry to indicate that it's
|
|
;dead.
|
|
;==========================================================================
|
|
|
|
ldy entry_offset
|
|
lda [drvr_buf_ptr],y
|
|
and #$FF00 ;clear storage type and name length
|
|
sta [drvr_buf_ptr],y
|
|
|
|
;==========================================================================
|
|
;before we write the block back to disk lets see if it is the key block
|
|
;This way we save an extra write to disk
|
|
;==========================================================================
|
|
|
|
lda [drvr_buf_ptr] ;check the previous link
|
|
beq update_header ;don't write block twice
|
|
|
|
;==========================================================================
|
|
;write the entries block back to disk.
|
|
;==========================================================================
|
|
|
|
jsr write_with_cache
|
|
bcc fix_header
|
|
piggy_back brl destroy_exit ;Major problems.
|
|
|
|
fix_header ;
|
|
|
|
;==========================================================================
|
|
;Now lets go and update the header of this directory.
|
|
;==========================================================================
|
|
|
|
lda dir_start_blk
|
|
sta drvr_blk_num
|
|
|
|
jsr read_with_cache
|
|
bcs piggy_back
|
|
|
|
update_header
|
|
lda [drvr_buf_ptr]
|
|
bne dir_damaged
|
|
|
|
ldy #$0023
|
|
lda [drvr_buf_ptr],y
|
|
cmp #$0D27
|
|
bne dir_damaged
|
|
|
|
ldy #header_file_cnt
|
|
lda [drvr_buf_ptr],y
|
|
dec a
|
|
bmi dir_damaged
|
|
sta [drvr_buf_ptr],y
|
|
|
|
ldx drvr_blk_num ;see if this is the root directory
|
|
cpx #vol_dir_start
|
|
bne not_root
|
|
|
|
pha
|
|
jsr setup_my_vcr
|
|
stx prodos_vcr_ptr
|
|
sty prodos_vcr_ptr+2
|
|
pla
|
|
ldy #vol_file_count ;update the file count in VCR also
|
|
|
|
sta [prodos_vcr_ptr],y
|
|
|
|
;==========================================================================
|
|
;write the header block back to disk.
|
|
;==========================================================================
|
|
|
|
not_root ;
|
|
jsr write_with_cache
|
|
bcs piggy_back
|
|
|
|
;==========================================================================
|
|
;Now we need to ripple back. This routine will time stamp all previous
|
|
;subdirectory files with the current time.
|
|
;==========================================================================
|
|
|
|
do_ripple ;
|
|
jsr slug_ripple
|
|
pla ;restore any error code
|
|
plp ;restore error flag from delete
|
|
bra piggy_back
|
|
|
|
dir_damaged ;
|
|
lda #dir_error
|
|
brl destroy_error
|
|
|
|
;==========================================================================
|
|
;==========================================================================
|
|
;===== END of MAIN CODE FOR DESTROY ======================================
|
|
;==========================================================================
|
|
;==========================================================================
|
|
|
|
kill_dir ;
|
|
|
|
;==========================================================================
|
|
;This routine is called when we are deleting a directory. Before we delete
|
|
;the directory we must make sure that there are NO files in the directory.
|
|
;
|
|
;input: Y = key block address of the directory
|
|
;==========================================================================
|
|
|
|
sty drvr_blk_num
|
|
jsr standard_req ;read of 512 bytes
|
|
jsr set_default_buf ;use GS/OS system work buffer
|
|
|
|
lda drvr_buf_ptr
|
|
sta temp_ptr
|
|
lda drvr_buf_ptr+2
|
|
sta temp_ptr+2
|
|
|
|
jsr read_with_cache
|
|
bcs dir_err_exit
|
|
|
|
lda [drvr_buf_ptr] ;the previous link better be zero
|
|
bne dir_damaged
|
|
ldy #$0023 ;verify that this is a directory
|
|
lda [drvr_buf_ptr],y
|
|
cmp #$0D27
|
|
bne dir_damaged
|
|
|
|
ldy #header_file_cnt
|
|
lda [drvr_buf_ptr],y
|
|
beq remove_dir ;it's ok to delete the directory
|
|
brl wrong_access
|
|
|
|
remove_dir ;
|
|
lda [drvr_buf_ptr]
|
|
beq first_block
|
|
cmp data_ptr
|
|
bne dir_damaged
|
|
|
|
first_block ;
|
|
ldx drvr_blk_num
|
|
stx data_ptr
|
|
|
|
dir_loop ;
|
|
jsr dealloc_block ;remove the block please
|
|
bcs dir_err_exit
|
|
|
|
lda temp_ptr
|
|
sta drvr_buf_ptr
|
|
lda temp_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
;==========================================================================
|
|
;Verify that the backward link is correct, and if it is then delete the blk
|
|
;==========================================================================
|
|
|
|
ldy #$0002 ;walk the forward links
|
|
lda [drvr_buf_ptr],y
|
|
sta drvr_blk_num
|
|
beq dir_done ;the forward link is nill so we are done
|
|
jsr read_with_cache
|
|
bcc remove_dir
|
|
|
|
dir_err_exit ;
|
|
rts
|
|
|
|
dir_done
|
|
clc
|
|
rts
|
|
|
|
kill_resource
|
|
sty drvr_blk_num
|
|
sty data_ptr ;save key block of the file
|
|
jsr standard_req
|
|
|
|
;==========================================================================
|
|
;Allocate a one block buffer
|
|
;==========================================================================
|
|
|
|
clc
|
|
lda #blk_size
|
|
jsl alloc_seg ;allocate a one block buffer
|
|
bcs res_err_exit
|
|
stx virtual
|
|
stx displacement
|
|
sty virtual+2 ;save the virtual pointer please
|
|
sty displacement+2
|
|
|
|
jsl deref ;convert this to a real address
|
|
stx drvr_buf_ptr ;save the address of the buffer
|
|
stx temp2_ptr
|
|
sty drvr_buf_ptr+2
|
|
sty temp2_ptr+2
|
|
|
|
jsr read_with_cache ;read in the resource header block
|
|
bcs res_err_exit
|
|
|
|
lda [temp2_ptr] ;get the storage type
|
|
and #$00FF
|
|
tax ;save storage type
|
|
ldy #$0001
|
|
lda [temp2_ptr],y
|
|
beq res_bad
|
|
tay ;key block of the resource
|
|
jsr zap_branch ;delete the resource
|
|
bcs res_err_exit
|
|
|
|
ldy #$0100
|
|
lda [temp2_ptr],y ;get the storage type
|
|
and #$00FF
|
|
tax ;save storage type
|
|
iny
|
|
lda [temp2_ptr],y
|
|
beq res_bad
|
|
tay ;key block of the resource
|
|
jsr zap_branch ;delete the resource
|
|
bcs res_err_exit
|
|
|
|
res_done
|
|
ldx displacement ;release memory used by the call
|
|
ldy displacement+2
|
|
jsl release_seg ;release the one block of head space
|
|
|
|
ldy data_ptr
|
|
jmp kill_seedling ;remove the last block now
|
|
|
|
;==========================================================================
|
|
res_bad
|
|
lda #out_of_range ;resource block is screwed up
|
|
res_err_exit
|
|
jsr free_header_buf
|
|
sec
|
|
rts
|
|
;===========================================================================
|
|
;this routine will delete a resource branch.
|
|
;X = storage type
|
|
;Y = key block
|
|
;output : carry clear = no error
|
|
;
|
|
zap_branch
|
|
dex
|
|
bne not_seedling
|
|
jsr kill_seedling
|
|
rts
|
|
not_seedling
|
|
dex
|
|
bne not_sapling
|
|
jsr kill_sapling
|
|
rts
|
|
not_sapling dex
|
|
bne @res_error ;file screwed up
|
|
jsr kill_tree
|
|
rts
|
|
@res_error
|
|
sec
|
|
rts
|
|
;==========================================================================
|
|
|
|
free_header_buf ;
|
|
pha ;save the error code
|
|
ldx displacement
|
|
ldy displacement+2
|
|
jsl release_seg ;release the one block of head space
|
|
pla
|
|
rts
|
|
|
|
;==========================================================================
|
|
;The following code will delete a tree file. It will also flip the index
|
|
;block and write it back out to disk.
|
|
;
|
|
;input: Y = key block of the file
|
|
;
|
|
;==========================================================================
|
|
kill_tree ;
|
|
sty drvr_blk_num
|
|
sty master_ptr
|
|
|
|
clc
|
|
lda gbuf_addr
|
|
adc #blk_size
|
|
sta drvr_buf_ptr
|
|
sta temp3_ptr
|
|
lda gbuf_addr+2
|
|
adc #$0000
|
|
sta drvr_buf_ptr+2
|
|
sta temp3_ptr+2
|
|
jsr standard_req
|
|
|
|
jsr read_with_cache
|
|
bcs master_error
|
|
|
|
lda #$0100 ;start at the last entry
|
|
pha
|
|
|
|
master_loop ;
|
|
lda temp3_ptr ;restore pointer to I/O buffer
|
|
sta temp_ptr
|
|
lda temp3_ptr+2
|
|
sta temp_ptr+2
|
|
|
|
inner_master ;
|
|
pla ;get the current index
|
|
dec a
|
|
bmi master_done
|
|
pha
|
|
tax
|
|
ora #$0100
|
|
tay
|
|
jsr get_and_flip ;get and flip the index block number
|
|
|
|
tay
|
|
beq inner_master
|
|
|
|
jsr kill_sapling
|
|
bcs master_pop
|
|
bra master_loop
|
|
|
|
master_done ;
|
|
ldx temp_ptr
|
|
ldy temp_ptr+2
|
|
lda master_ptr
|
|
jsr write_flipped ;write master index block flipped
|
|
bcs master_error
|
|
|
|
ldy master_ptr
|
|
bra kill_seedling
|
|
|
|
master_error ;
|
|
rts
|
|
|
|
master_pop ;
|
|
pla
|
|
sec
|
|
rts
|
|
|
|
;==========================================================================
|
|
;The following code will delete a sapling file. It will also flip the index
|
|
;block and write it back out to disk.
|
|
;
|
|
;input: Y = key block of the file
|
|
;
|
|
;==========================================================================
|
|
kill_sapling ;
|
|
|
|
;==========================================================================
|
|
;Now we need to read in the index block and deallocate all allocated blocks
|
|
;==========================================================================
|
|
|
|
sty drvr_blk_num
|
|
sty index_ptr ;save for later delete
|
|
|
|
jsr set_default_buf
|
|
lda drvr_buf_ptr
|
|
sta temp_ptr
|
|
lda drvr_buf_ptr+2
|
|
sta temp_ptr+2
|
|
|
|
jsr standard_req
|
|
jsr read_with_cache
|
|
bcs index_error
|
|
|
|
lda #$0100 ;start at the last entry
|
|
pha
|
|
|
|
index_loop ;
|
|
pla ;get the current index
|
|
dec a
|
|
bmi index_done
|
|
pha
|
|
tax
|
|
ora #$0100
|
|
tay
|
|
|
|
jsr get_and_flip ;get the block number from index buffer
|
|
|
|
tax
|
|
beq index_loop
|
|
jsr dealloc_block ;free the block up please
|
|
bcc index_loop
|
|
plx
|
|
rts
|
|
|
|
index_done ;
|
|
ldx temp_ptr
|
|
ldy temp_ptr+2
|
|
lda index_ptr
|
|
jsr write_flipped
|
|
bcc kill_index
|
|
index_error rts
|
|
|
|
kill_index ;
|
|
ldy index_ptr ;now release the last block please
|
|
|
|
;==========================================================================
|
|
;This routine will free up a seedling files block.
|
|
;
|
|
;input: Y = key block of the file.
|
|
;
|
|
;==========================================================================
|
|
|
|
kill_seedling ;
|
|
tyx
|
|
jsr dealloc_block
|
|
rts ;return error
|
|
|
|
|
|
;==========================================================================
|
|
;this routine will write a flipped index block to disk
|
|
;
|
|
;input:
|
|
; X = low word of buffer pointer
|
|
; Y = high word ''''
|
|
; A = block number
|
|
;
|
|
;Output:
|
|
; A = error if carry set
|
|
;
|
|
;==========================================================================
|
|
|
|
write_flipped ;
|
|
stx drvr_buf_ptr
|
|
sty drvr_buf_ptr+2
|
|
sta drvr_blk_num
|
|
jsr write_with_cache
|
|
rts
|
|
|
|
;==========================================================================
|
|
;This routine will flip the block number within an index block.
|
|
;
|
|
;input:
|
|
; X = Index into the lower half of the index block
|
|
; Y = Index into the higher half of the index block
|
|
; temp_ptr = pointer to the index block
|
|
;
|
|
;OutPut:
|
|
; A = Block number from index block
|
|
;
|
|
;==========================================================================
|
|
get_and_flip ;
|
|
longa off
|
|
sep #$20
|
|
|
|
lda [temp_ptr],y ;grab the high block number
|
|
xba ;put high block number in upper byte
|
|
phy ;save high byte index
|
|
|
|
txy
|
|
lda [temp_ptr],y ;get the low block number
|
|
|
|
xba ;restore high block number
|
|
sta [temp_ptr],y ;store high block number in low half
|
|
|
|
xba ;restore low block number
|
|
ply ;get high byte index
|
|
sta [temp_ptr],y ;store low block number in high half
|
|
|
|
longa on
|
|
rep #$20
|
|
rts
|
|
ENDP
|
|
;======================================================================
|
|
;Chnage_Path This file will RENAME or MOVE a file to a new directory
|
|
;
|
|
;Created: Nov 04, 1987
|
|
;Modified: Nov 04, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: From GS/OS jmp table
|
|
;
|
|
;Input: A = undefined
|
|
; X = (call number * 2)
|
|
; Y = (class number * 2)
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = error code if carry set (exit via system exit routine)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
; find_file (subroutine)
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Source Pathname Pointer (4 Bytes)
|
|
; Destination Path Pointer(4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Source Pathname Pointer (4 Bytes)
|
|
; Destination Path Pointer(4 Bytes)
|
|
; Flags (2 Bytes)
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT change_path
|
|
change_path PROC
|
|
|
|
jsr setup_params
|
|
|
|
; If the source is only a device # then set cp_device_flag to 1.
|
|
; This is a special case so that the Finder can rename a volume whose current name
|
|
; is a duplicate of another volume which has open files. 1/22/91 CAE
|
|
|
|
lda <path_flag ;get pathname flags
|
|
and #path1_mask ;is pathname 1 defined?
|
|
bne @not_dev ;yes
|
|
lda <dev_num ;do we have a device #?
|
|
beq @not_dev ;no
|
|
inc cp_device_flag ;yes - so indicate source was a device #
|
|
|
|
; If pCount was 3 or more, get the cp_flags from the parameter block. 5-Dec-91 MSD
|
|
|
|
lda pcount
|
|
cmp #3 ; did it include cp_flags?
|
|
blt @not_dev ; no, so leave cp_flags set to 0.
|
|
ldy #pblk_04_flags
|
|
lda [my_pblk_ptr],y ; get flags from param block
|
|
sta cp_flags
|
|
|
|
; End 5-Dec-91 MSD
|
|
|
|
@not_dev
|
|
|
|
jsr process_path ;see if the source file exist also sets up priority bit
|
|
;and now checks the spans. 10/10/91 JEV
|
|
|
|
jsr valid_change
|
|
bcs end_change
|
|
|
|
lda slug_block ;save for slug ripple routine
|
|
sta src_slug_blk
|
|
lda slug_offset
|
|
sta src_slug_offset
|
|
|
|
jsr chk_disk_protect
|
|
jsr save_src_parms
|
|
jsr move_dir_entry ;move entry into one_entry
|
|
jsr chk_open ;see if the file is currently open
|
|
bcs end_change
|
|
jsr process_dest ;find the destination name
|
|
bcs end_change
|
|
|
|
; 27-Jan-92 MSD: We let valid_change see if the source path is a subset of the
|
|
; destination path (i.e. we're trying to move an item into its own child). If
|
|
; that was the case, cp_to_child will be non-zero
|
|
|
|
lda cp_to_child ; were we moving into our own child?
|
|
beq @not_subset ; no, so do the move
|
|
|
|
lda #bad_path_syntax ; source path was a subset of destination path
|
|
sec
|
|
bra end_change
|
|
|
|
@not_subset
|
|
jsr save_dest_parms
|
|
jsr rename_or_move
|
|
|
|
end_change ;
|
|
pha ;save the error code
|
|
php
|
|
jsr flush_bitmap ;make sure the bitmap is OK!
|
|
plp ;restore error flag
|
|
pla ;restore error code if any
|
|
jmp main_exit
|
|
|
|
;======================================================================
|
|
|
|
chk_open
|
|
stz fcr_wanted ;start from the beginning
|
|
lda one_entry+key_blk_index
|
|
sta key_block
|
|
open_loop
|
|
jsr get_next_fcr
|
|
bcs end_chk_open
|
|
|
|
ldy #fcr_vol_id
|
|
lda [my_fcr_ptr],y ;get the Volume ID so we can make sure the file is on
|
|
cmp [my_vcr_ptr] ;the same volume.
|
|
bne open_loop ;File is on another volume
|
|
|
|
ldy #fcr_file_id
|
|
lda [pro_fcr_ptr],y
|
|
cmp key_block
|
|
bne open_loop
|
|
|
|
lda #file_busy
|
|
sec
|
|
rts
|
|
|
|
end_chk_open ; ;the file is not open
|
|
clc
|
|
rts
|
|
|
|
;======================================================================
|
|
|
|
rename_or_move ; ;what will we do?
|
|
lda src_dev_num
|
|
cmp dest_dev_num
|
|
bne bad_device ;cannot rename on different devices
|
|
lda src_start_blk
|
|
cmp dest_start_blk ;is the file in the same directory?
|
|
beq do_rename ;this can only be a rename
|
|
;
|
|
;IF here we are doing a change_path
|
|
;
|
|
jsr move_file ;do a change_path please
|
|
rts
|
|
|
|
;
|
|
;IF here we are doing a simple rename
|
|
;
|
|
do_rename
|
|
jsr rename_file
|
|
rts
|
|
|
|
bad_device
|
|
brl bad_path
|
|
|
|
;======================================================================
|
|
move_file
|
|
|
|
; First, we need to check the file/dir that we're moving to see if it's
|
|
; 'rename enabled'. If it isn't, then we need to make sure we're just
|
|
; doing a move and not a 'move and rename'.
|
|
; Added 3/15/91 CAE
|
|
|
|
jsr standard_req ;read in 512 bytes
|
|
jsr set_default_buf
|
|
lda src_dev_num
|
|
sta drvr_dev_num
|
|
lda src_dir_blk ;block that contains the entry
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcs to_end_move_file
|
|
|
|
clc
|
|
lda src_offset
|
|
adc #access_index
|
|
tay
|
|
lda [drvr_buf_ptr],y
|
|
and #rename_enabled ;can we rename the file?
|
|
bne @ok ;branch if rename is OK
|
|
|
|
ldy src_offset ;rename is not allowed so
|
|
lda [drvr_buf_ptr],y ;get file's name length
|
|
and #$000f ;strip off storage nibble and hi byte
|
|
cmp search_length ;same as dest name length?
|
|
beq @cont ;yes - so compare the names
|
|
|
|
@uh_oh rep #$20 ;ensure 16 bit mode
|
|
sec
|
|
lda #invalid_access ;report an error
|
|
rts
|
|
|
|
@cont tax ;calculate offset to end of dest name
|
|
dex ;and put in X
|
|
clc
|
|
adc src_offset ;calculate offset to end of file's name
|
|
tay ;in the dir entry and put in Y
|
|
|
|
longa off
|
|
sep #$20 ;begin 8 bit mode
|
|
|
|
@loop lda [drvr_buf_ptr],y ;compare file's name
|
|
cmp search_name,x ;to dest name
|
|
bne @uh_oh ;branch if mis-match
|
|
dey
|
|
dex
|
|
bpl @loop ;loop until done
|
|
|
|
longa on
|
|
rep #$20 ;begin 16 bit mode
|
|
@ok
|
|
|
|
; End of new code.
|
|
|
|
ldx free_dir_blk ;do we need to extend the directory?
|
|
bne no_extend
|
|
jsr calc_free_blks ;do we have a free block
|
|
bcs to_end_move_file ;NO we have an error
|
|
tax
|
|
bne not_full
|
|
brl full_disk
|
|
not_full
|
|
jsr extend_subdir ;grow the subdirectory
|
|
bcs end_move_file
|
|
|
|
lda free_dir_offset ;offset to directory entry
|
|
sta dest_offset
|
|
lda free_dir_blk ;block that contains entry
|
|
sta dest_dir_blk
|
|
|
|
no_extend
|
|
jsr standard_req ;512 bytes
|
|
jsr set_default_buf ;use the temp buffer
|
|
|
|
lda src_dir_blk ;move and delete the old entry
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcs end_move_file
|
|
jsr delete_entry ;move entry and delete it
|
|
jsr write_with_cache
|
|
to_end_move_file
|
|
bcs end_move_file
|
|
|
|
lda src_start_blk
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcs end_move_file
|
|
jsr dec_file_cnt
|
|
jsr write_with_cache
|
|
bcs end_move_file
|
|
jsr do_src_slug
|
|
|
|
lda dest_start_blk ;new header pointer
|
|
sta one_entry+header_ptr_index
|
|
lda dest_dir_blk ;block
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcs end_move_file
|
|
jsr move_old_entry
|
|
ldy dest_offset
|
|
jsr move_new_name ;rename the entry
|
|
jsr write_with_cache
|
|
bcs end_move_file
|
|
|
|
lda dest_start_blk ;now update the file count
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcs end_move_file
|
|
jsr inc_file_cnt
|
|
jsr write_with_cache
|
|
bcs end_move_file
|
|
jsr do_dest_slug
|
|
|
|
lda storage_type
|
|
and #$00F0 ;see if this is a subdirectory
|
|
cmp #subdir_type
|
|
bne move_done
|
|
jsr fix_subdir
|
|
rts
|
|
move_done
|
|
clc
|
|
end_move_file
|
|
rts
|
|
full_disk
|
|
lda #volume_full
|
|
sec
|
|
rts
|
|
do_src_slug
|
|
lda src_slug_blk
|
|
sta slug_block
|
|
lda src_slug_offset
|
|
sta slug_offset
|
|
bra do_slug
|
|
do_dest_slug
|
|
lda dest_slug_blk
|
|
sta slug_block
|
|
lda dest_slug_offset
|
|
sta slug_offset
|
|
do_slug
|
|
jsr slug_ripple
|
|
rts
|
|
fix_subdir
|
|
lda one_entry+key_blk_index
|
|
sta drvr_blk_num
|
|
jsr read_with_cache ;read in the key block
|
|
|
|
bcs end_fix_subdir
|
|
lda dest_dir_blk ;block number where entry is
|
|
ldy #parent_index
|
|
sta [drvr_buf_ptr],y
|
|
|
|
lda #subdir_header
|
|
sta storage_type
|
|
ldy #$0004 ;rename the subdirectory as well
|
|
jsr move_new_name
|
|
|
|
jsr make_entry_num
|
|
bcs end_fix_subdir
|
|
ldy #parent_index+2
|
|
sta [drvr_buf_ptr],y
|
|
jsr write_with_cache
|
|
end_fix_subdir
|
|
rts
|
|
|
|
dec_file_cnt
|
|
ldy #header_file_cnt
|
|
lda [drvr_buf_ptr],y
|
|
dec a ;update the file count for directory
|
|
bmi end_dec
|
|
sta [drvr_buf_ptr],y
|
|
jsr chk_vol_cnt ;pass the new count in the accum
|
|
end_dec
|
|
rts
|
|
|
|
inc_file_cnt
|
|
ldy #header_file_cnt
|
|
lda [drvr_buf_ptr],y
|
|
inc a ;update the file count for directory
|
|
sta [drvr_buf_ptr],y
|
|
jsr chk_vol_cnt ;pass the new count in the accum
|
|
rts
|
|
;
|
|
;The new count is in the accumulator
|
|
;
|
|
chk_vol_cnt
|
|
ldy drvr_blk_num ;our we updating the Root Level of the disk?
|
|
cpy #vol_dir_start
|
|
bne @not_vol
|
|
;
|
|
;Now we need to update the VCR
|
|
;
|
|
ldy #vol_file_count
|
|
sta [prodos_vcr_ptr],y
|
|
@not_vol
|
|
rts
|
|
|
|
delete_entry ;
|
|
ldx #$0000
|
|
ldy src_offset
|
|
delete_loop ; ;move the entry to one_entry
|
|
lda [drvr_buf_ptr],y
|
|
sta one_entry,x
|
|
iny
|
|
inx
|
|
cpx #entry_length
|
|
bne delete_loop
|
|
|
|
ldy src_offset
|
|
lda [drvr_buf_ptr],y
|
|
and #$FF00 ;clear storage/length field
|
|
sta [drvr_buf_ptr],y
|
|
rts
|
|
|
|
move_old_entry ;
|
|
ldx #$0000
|
|
ldy dest_offset
|
|
longa off
|
|
sep #$20
|
|
change_loop ;
|
|
lda one_entry,x
|
|
sta [drvr_buf_ptr],y
|
|
iny
|
|
inx
|
|
cpx #entry_length
|
|
bne change_loop
|
|
longa on
|
|
rep #$20
|
|
rts
|
|
|
|
|
|
;======================================================================
|
|
rename_file ;
|
|
jsr standard_req ;read in 512 bytes
|
|
jsr set_default_buf
|
|
lda src_dev_num
|
|
sta drvr_dev_num
|
|
lda src_dir_blk ;block that contains the entry
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcs end_rename
|
|
|
|
clc
|
|
lda src_offset
|
|
adc #access_index
|
|
tay
|
|
lda [drvr_buf_ptr],y
|
|
and #rename_enabled ;can we rename the file?
|
|
bne @10 ;rename is OK
|
|
sec
|
|
lda #invalid_access ;sorry bud
|
|
rts ;return with the error please
|
|
|
|
@10
|
|
clc
|
|
lda src_offset ;get the key block
|
|
adc #key_blk_index
|
|
tay
|
|
lda [drvr_buf_ptr],y
|
|
sta one_entry+key_blk_index
|
|
|
|
ldy src_offset ;offset the old name
|
|
lda [drvr_buf_ptr],y
|
|
and #$00F0 ;isolate the storage type
|
|
sta storage_type
|
|
cmp #volume_header
|
|
beq rename_vol
|
|
cmp #subdir_type
|
|
beq type_ok
|
|
cmp #seedling_type
|
|
beq type_ok
|
|
cmp #sapling_type
|
|
beq type_ok
|
|
cmp #tree_type
|
|
beq type_ok
|
|
cmp #resource_type
|
|
bne bad_type
|
|
type_ok ;
|
|
ldy src_offset
|
|
jsr move_new_name
|
|
jsr write_with_cache
|
|
bcs end_rename
|
|
lda storage_type
|
|
and #$00F0 ;clear the garbage
|
|
cmp #subdir_type
|
|
bne end_rename_clr
|
|
lda src_dir_blk
|
|
sta dest_dir_blk
|
|
lda src_offset
|
|
sta free_dir_offset
|
|
jsr fix_subdir
|
|
bcs end_rename
|
|
end_rename_clr
|
|
jsr slug_ripple ;ripple the time please
|
|
end_rename
|
|
rts
|
|
bad_type
|
|
lda #bad_store_type
|
|
sec
|
|
rts
|
|
|
|
;Rename a volume.
|
|
;
|
|
;Note - if cp_device_flag is $8001 then we're renaming a duplicate volume. In this
|
|
; case, don't call chk_boot_vol since the duplicate volume could have the same
|
|
; name as the boot volume and we don't want to change the boot prefix.
|
|
; 3/26/91 CAE
|
|
|
|
rename_vol
|
|
pei my_vcr_ptr
|
|
pei my_vcr_ptr+2
|
|
jsr Check_dup_dest ;see if the destination name is an active VCR
|
|
ply
|
|
sty my_vcr_ptr+2
|
|
ply
|
|
sty my_vcr_ptr
|
|
bcc @not_active
|
|
rts
|
|
@not_active
|
|
ldy volume_name ;terminate the new name with a null
|
|
lda #$0000
|
|
sta volume_name+2,y
|
|
|
|
; jsr chk_boot_vol ;moved after call to setup_name 3/26/91 CAE
|
|
|
|
lda #volume_name ;move the name to search_name and
|
|
sta temp_ptr ;do syntax checking on the name
|
|
lda #^volume_name
|
|
sta temp_ptr+2
|
|
lda #$0002 ;starting index for check
|
|
sta chars_checked
|
|
jsr setup_name
|
|
;following 2 lines added 3/26/91 CAE
|
|
lda cp_device_flag ;are we renaming a duplicate volume?
|
|
bmi @skip_chk ;yes - so don't change the boot prefix
|
|
jsr chk_boot_vol ;change boot prefix if renaming boot volume
|
|
@skip_chk
|
|
lda [my_vcr_ptr] ;get the VCR ID
|
|
ldx #volume_name ;pointer to the new name
|
|
ldy #^volume_name
|
|
jsl rename_vcr
|
|
|
|
@go_type_ok
|
|
clc
|
|
brl type_ok
|
|
|
|
;======================================================================
|
|
;We need to make sure that the destination name is not an allocated
|
|
;VCR with open files. If we find a VCR with open files then we should
|
|
;remove it or return duplicate volume error.
|
|
;======================================================================
|
|
Check_dup_dest
|
|
lda [my_vcr_ptr] ;get the VCR ID of the source
|
|
pha
|
|
|
|
ldx #volume_name ;pointer to the volume name
|
|
ldy #^volume_name
|
|
lda #0000 ;0000=search for vcr by name
|
|
jsl find_vcr
|
|
bcc @handle_dup
|
|
@no_dup_error
|
|
pla ;just fix the stack
|
|
clc
|
|
rts ;no problem
|
|
@handle_dup
|
|
jsl deref ;convert virtual to real
|
|
stx my_vcr_ptr
|
|
sty my_vcr_ptr+2 ;setup pointer to VCR
|
|
|
|
lda [my_vcr_ptr] ;get the VCR ID of the destination.
|
|
cmp 1,s ;is source = dest?
|
|
beq @no_dup_error
|
|
pla ;we must fix the stack
|
|
|
|
ldy #vcr_open_cnt
|
|
lda [my_vcr_ptr],y
|
|
bne @sorry_dup ;files open so don't log in new volume
|
|
jsr free_vcr ;free vcr pointed to by 'my_vcr_ptr'
|
|
clc
|
|
rts ;we are happy again!
|
|
|
|
@sorry_dup ;
|
|
lda #dup_volume ;duplicate volume online
|
|
sec
|
|
rts
|
|
|
|
|
|
;======================================================================
|
|
|
|
move_new_name
|
|
phy
|
|
ldx #14
|
|
lda #$0000
|
|
clear_old
|
|
sta [drvr_buf_ptr],y
|
|
iny
|
|
dex
|
|
bpl clear_old
|
|
ply
|
|
|
|
phy
|
|
ldx #$0000 ;index into new name
|
|
longa off
|
|
sep #$20 ;8 bit mode
|
|
lda storage_type
|
|
ora search_length
|
|
sta [drvr_buf_ptr],y
|
|
iny
|
|
name_store ;
|
|
lda search_name,x ;first ascii character
|
|
sta [drvr_buf_ptr],y
|
|
iny
|
|
inx
|
|
cpx search_length
|
|
bne name_store ;move the entire name
|
|
|
|
longa on
|
|
rep #$20
|
|
pla ;get index to the storage type
|
|
clc
|
|
adc #version_index
|
|
tay
|
|
|
|
lda storage_type
|
|
cmp #volume_header
|
|
beq @skip_case_save
|
|
|
|
@do_both lda case_bits ;set the case bits please
|
|
beq @do_save ;the case is all upper
|
|
|
|
bit fst_attr ;user does not want case info
|
|
bmi @do_save
|
|
ora #$8000 ;set the case on bit.
|
|
@do_save
|
|
sta [drvr_buf_ptr],y
|
|
rts
|
|
|
|
|
|
@skip_case_save
|
|
ldy #create_index+4-2;save the case bits please
|
|
jsr @do_both
|
|
ldy #vol_create-2
|
|
sta [prodos_vcr_ptr],y
|
|
rts
|
|
|
|
;======================================================================
|
|
chk_boot_vol ;change the boot prefix if needed
|
|
ldy src_offset ;original name of volume
|
|
lda [drvr_buf_ptr],y
|
|
and #$000F ;clear storage type etc.
|
|
inc a ;add one for leading ':'
|
|
sta def_vol_name ;length word
|
|
lda #'::' ;leading ':'
|
|
sta def_vol_name+2
|
|
|
|
iny ;point to the first character
|
|
ldx #$0000
|
|
boot_loop ;
|
|
lda [drvr_buf_ptr],y
|
|
sta def_vol_name+3,x
|
|
iny
|
|
inx
|
|
cpx #16 ;move the max number of characters
|
|
bne boot_loop
|
|
|
|
jsl get_boot_pfx ;get the pointer to the current volume
|
|
stx temp_ptr
|
|
sty temp_ptr+2
|
|
|
|
lda [temp_ptr] ;verify the length
|
|
cmp def_vol_name
|
|
bne not_same
|
|
tay ;use as index
|
|
iny ;get the last character please
|
|
|
|
longa off
|
|
sep #$20
|
|
boot_loop2
|
|
lda [temp_ptr],y
|
|
cmp #'a'
|
|
bcc @no_convert ;The character cannot be lower case
|
|
cmp #'z'+1
|
|
bcs @no_convert
|
|
and #$DF ;convert char to upper case for compare
|
|
@no_convert
|
|
cmp def_vol_name,y
|
|
bne not_same
|
|
dey
|
|
bpl boot_loop2 ;check the entire volume name
|
|
|
|
longa on
|
|
rep #$20
|
|
|
|
lda volume_name ;get the length word of the new name
|
|
tay
|
|
inc a ;add one for leading ':'
|
|
sta def_vol_name
|
|
lda #'::'
|
|
sta def_vol_name+2
|
|
new_boot ;
|
|
lda volume_name+1,y
|
|
sta def_vol_name+2,y
|
|
dey
|
|
bne new_boot
|
|
|
|
ldx #def_vol_name ;pointer to the new name
|
|
ldy #^def_vol_name
|
|
jsl set_boot_pfx
|
|
not_same
|
|
longa on
|
|
rep #$20
|
|
rts
|
|
|
|
;======================================================================
|
|
|
|
save_src_parms ;
|
|
lda drvr_dev_num ;save source info
|
|
sta src_dev_num
|
|
lda dir_start_blk ;starting block of directory
|
|
sta src_start_blk
|
|
lda entry_offset ;offset to directory entry
|
|
sta src_offset
|
|
lda parent_blk ;block that contains entry
|
|
sta src_dir_blk
|
|
rts
|
|
|
|
save_dest_parms ;
|
|
lda drvr_dev_num ;save source info
|
|
sta dest_dev_num
|
|
lda dir_start_blk ;starting block of directory
|
|
sta dest_start_blk
|
|
lda free_dir_offset ;offset to directory entry
|
|
sta dest_offset
|
|
lda free_dir_blk ;block that contains entry
|
|
sta dest_dir_blk
|
|
rts
|
|
|
|
;======================================================================
|
|
|
|
process_dest ;
|
|
lda path1_ptr ;save pathname one pointer
|
|
sta curr_mark
|
|
lda path1_ptr+2
|
|
sta curr_mark+2 ;temp save area!!!!!!!!!!!!!!!
|
|
lda dev1_num
|
|
sta curr_eof
|
|
lda path_flag
|
|
sta curr_eof+2 ;temp storage
|
|
|
|
lda path2_ptr ;make path two appear as path one
|
|
sta path1_ptr
|
|
lda path2_ptr+2
|
|
sta path1_ptr+2
|
|
|
|
lda dev2_num
|
|
sta dev_num
|
|
|
|
lda path_flag
|
|
and #path2_mask
|
|
xba
|
|
sta path_flag
|
|
;
|
|
;IF vol_rename_flag = minus then we are renaming the volume
|
|
;
|
|
bit vol_rename_flag
|
|
bpl normal_rename
|
|
lda #path1_mask
|
|
|
|
ldx path1_ptr
|
|
ldy path1_ptr+2
|
|
jsr build_path
|
|
|
|
lda src_dev_num
|
|
sta drvr_dev_num
|
|
lda src_start_blk
|
|
sta dir_start_blk
|
|
lda src_dir_blk
|
|
sta free_dir_blk
|
|
lda src_offset
|
|
sta free_dir_offset
|
|
jsr restore_path1
|
|
clc
|
|
rts
|
|
|
|
normal_rename ;
|
|
|
|
lda #no_dup ;duplicate not allowed
|
|
sta search_flag
|
|
jsr process_path ;find the destination
|
|
|
|
ldx slug_block ;save for slug_ripple routine
|
|
stx dest_slug_blk
|
|
ldx slug_offset
|
|
stx dest_slug_offset
|
|
|
|
bcs no_dup_problem
|
|
|
|
lda drvr_dev_num ;did the user enter the same name?
|
|
cmp src_dev_num
|
|
bne dup_prob ;duplicate filename
|
|
lda dir_start_blk
|
|
cmp src_start_blk
|
|
bne dup_prob
|
|
lda parent_blk ;block that contains entry
|
|
cmp src_dir_blk
|
|
bne dup_prob
|
|
lda entry_offset ;offset to directory entry
|
|
cmp src_offset
|
|
bne dup_prob
|
|
jsr restore_path1
|
|
clc
|
|
rts ;renaming the same file
|
|
|
|
dup_prob ;
|
|
jsr restore_path1
|
|
lda #dup_pathname
|
|
real_problem ;
|
|
sec
|
|
rts
|
|
|
|
no_dup_problem ;
|
|
pha
|
|
jsr restore_path1
|
|
pla
|
|
bit path_searched ;was the entire path searched?
|
|
bpl real_problem
|
|
clc
|
|
rts
|
|
|
|
restore_path1 ; ;restore path1 stuff
|
|
lda curr_mark
|
|
sta path1_ptr
|
|
lda curr_mark+2
|
|
sta path1_ptr+2
|
|
lda curr_eof
|
|
sta dev_num
|
|
lda curr_eof+2
|
|
sta path_flag
|
|
rts
|
|
|
|
;======================================================================
|
|
;Possible combinations of pathnames
|
|
;
|
|
;(1) .DEV1 --> /FOO (Rename)
|
|
;(2) /FOO1 --> /FOO (Rename)
|
|
;(3) /FOO1/PATHNAME --> /FOO1/NEWNAME (Rename)
|
|
;(4) /FOO1/SUB/FILE --> /FOO1/FILE (Change path)
|
|
;(5) .DEV1/FILE --> /FOO/NEW.NAME (Rename)
|
|
;(6) .DEV1/FILE --> /FOO/SUB/FILE (Change path)
|
|
;(7) /FOO/FILE --> .DEV1/SUB/NEW (Change path)
|
|
;(8) /FOO/FILE --> .DEV1/NEW (rename)
|
|
;
|
|
;Invalid Pathnames:
|
|
;
|
|
;(1) /FOO --> .DEV1
|
|
;(2) /FOO --> /FOO/FILE
|
|
;(3) /FOO/SUB/ --> /FOO/SUB/SUB1/SUB
|
|
;(4) /FOO/FILE --> /FOO
|
|
;(5) /FOO/FILE --> .DEV1
|
|
;
|
|
;======================================================================
|
|
|
|
valid_change
|
|
stz cp_to_child ; assume source is not a subset of dest
|
|
stz vol_rename_flag
|
|
lda path_flag
|
|
and #path2_mask ;there has to be a second pathname
|
|
beq to_bad_path
|
|
|
|
jsr setup_path1 ;Path1_ptr --> temp_ptr
|
|
jsr setup_path2 ;Path2_ptr --> temp2_ptr
|
|
|
|
;
|
|
;IF (Path1 = device_name) THEN
|
|
; (Path2 must be a volume name only)
|
|
;
|
|
;
|
|
lda path_flag ;is path1 a device name only?
|
|
and #path1_mask
|
|
bne not_device ;not just a device name
|
|
lda dev2_num
|
|
bne to_bad_path ;path2 cannot contain a device name
|
|
ldx temp2_ptr
|
|
ldy temp2_ptr+2
|
|
jsr scan_pass_vol ;pass the volume name IF possible
|
|
bcc to_bad_path ;there is more then just a volume name
|
|
;
|
|
;We are doing the following: '.DEV1' to '/FOO'
|
|
;
|
|
bra volume_rename
|
|
|
|
to_bad_path ;
|
|
brl bad_path
|
|
;
|
|
; IF (Path1 = volume_only) THEN
|
|
; (Path2 must be volume only)
|
|
;
|
|
not_device ;
|
|
lda dev1_num ;IF dev <> 00 THEN not volume only
|
|
bne chk_same_dev
|
|
ldx temp_ptr ;pointer to path1
|
|
ldy temp_ptr+2
|
|
jsr scan_pass_vol
|
|
bcc not_vol_only ;path1 <> volume only
|
|
;
|
|
; IF (path1 - volume) and ((path2 = device) or (path2 = dev/vol)) THEN
|
|
; bad_path_syntax
|
|
;
|
|
lda path_flag
|
|
and #path2_mask
|
|
beq to_bad_path
|
|
lda dev2_num ;is there a device name also?
|
|
bne a_bad_path
|
|
|
|
ldx temp2_ptr
|
|
ldy temp2_ptr+2
|
|
jsr scan_pass_vol ;pass the volume name IF possible
|
|
bcc to_bad_path ;path2 <> volume only
|
|
;
|
|
;We are doing the following: '/FOO1' to '/FOO'
|
|
;
|
|
volume_rename ;
|
|
dec vol_rename_flag
|
|
clc
|
|
rts
|
|
;
|
|
;IF (Path1 <> volume only) THEN
|
|
; (Path2 MUST be a pathname)
|
|
;
|
|
chk_same_dev ;
|
|
lda dev2_num ;is the rename on the same device?
|
|
beq not_vol_only
|
|
cmp dev1_num
|
|
a_bad_path bne to_bad_path
|
|
|
|
not_vol_only ;
|
|
lda path_flag
|
|
and #path2_mask ;is there a pathname?
|
|
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
beq to_bad_path
|
|
else ;original code
|
|
beq bad_path ;must be device name only
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
lda dev2_num ;IF (dev = true) and (path = true) THEN
|
|
bne path2_is_path ; (path2 = pathname)
|
|
|
|
ldx temp2_ptr
|
|
ldy temp2_ptr+2
|
|
jsr scan_pass_vol
|
|
bcs bad_path ;Path2 = volume name only!
|
|
stx temp2_ptr
|
|
sty temp2_ptr+2
|
|
;
|
|
;IF (path2 = path2-volume_name) and (path1 = volume_name) THEN
|
|
; Path1 := Path1-volume_name
|
|
;
|
|
lda dev1_num ;does path1 contain a volume name?
|
|
bne do_scan ;no it does not
|
|
ldx temp_ptr
|
|
ldy temp_ptr+2
|
|
jsr scan_pass_vol ;scan past the volume name
|
|
stx temp_ptr
|
|
sty temp_ptr+2
|
|
bra do_scan
|
|
|
|
;
|
|
; When Here Path1 and Path2 are both pathnames!
|
|
;
|
|
; IF (Path1 = dev) and (path2 = vol) THEN
|
|
; path2 := path2-volume name
|
|
;
|
|
path2_is_path ;
|
|
lda dev1_num ;does path1 contain a device name?
|
|
beq path1_volume ;NO
|
|
|
|
lda dev2_num ;does path2 contain a device name?
|
|
bne do_scan ;path1 and path2 contains device names
|
|
|
|
ldx temp2_ptr
|
|
ldy temp2_ptr+2 ;scan pass the volume name
|
|
jsr scan_pass_vol
|
|
stx temp2_ptr
|
|
sty temp2_ptr+2
|
|
bra do_scan ;everything is OK so far
|
|
|
|
;
|
|
; IF (path1 = volume) and (path2 = dev) THEN
|
|
; path1 := path1-volume_name
|
|
|
|
path1_volume ;
|
|
lda dev2_num ;does path2 contain a
|
|
beq do_scan ;Path1 and path2 contain volume names
|
|
|
|
;
|
|
; IF (path2 = dev) and (path1 = vol) THEN
|
|
; path1 := path1-volume_name
|
|
;
|
|
scan_path1 ;
|
|
ldx temp_ptr ;path1
|
|
ldy temp_ptr+2
|
|
jsr scan_pass_vol ;pass the volume name
|
|
stx temp_ptr
|
|
sty temp_ptr+2
|
|
|
|
;The following code was moved into the changepath code so
|
|
;that ProDOS conforms to the way AppleShare and HFS do a
|
|
;changepath. The check to see if the path1 is a subset
|
|
;of path2 should not be done until after we check to see
|
|
;if the path2 allready exsists. 10/3/91 JEV
|
|
;
|
|
; IF (path1 is a subset of path2) THEN
|
|
; set cp_to_child
|
|
|
|
;The following code has been changed to do a case-insensitive
|
|
;compare in order to fix a bug which was allowing illegal moves
|
|
;if the case of the pathnames was different. 1/22/91 CAE
|
|
|
|
do_scan ;
|
|
ldy #$0000 ;start scan at beginning
|
|
longa off
|
|
sep #$20
|
|
subset_loop ;
|
|
; lda [temp_ptr],y ;source file
|
|
; cmp [temp2_ptr],y ;destination
|
|
; bne more_chk
|
|
; iny
|
|
; bra subset_loop
|
|
|
|
lda [temp_ptr],y ;get source file char
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
cmp #' '
|
|
bne @not_blank1
|
|
lda #'.'
|
|
@not_blank1
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
cmp #'a' ;upper case?
|
|
bcc @its_upper1 ;yes
|
|
and #$DF ;no - so convert to upper case
|
|
@its_upper1 pha ;save char
|
|
lda [temp2_ptr],y ;get dest file char
|
|
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
cmp #' '
|
|
bne @not_blank2
|
|
lda #'.'
|
|
@not_blank2
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
cmp #'a' ;upper case?
|
|
bcc @its_upper2 ;yes
|
|
and #$DF ;no - so convert to upper case
|
|
@its_upper2 cmp 1,s ;same as source file char?
|
|
bne @no_match ;nope
|
|
pla ;yes - so clean up stack
|
|
iny ;adjust index
|
|
bra subset_loop ;and loop
|
|
@no_match pla ;clean up stack
|
|
|
|
more_chk ;
|
|
lda [temp2_ptr],y ;this cannot be a 'delimiter'
|
|
cmp #delimiter
|
|
longa on ;go ahead and fix the mode
|
|
rep #$20
|
|
bne paths_ok
|
|
lda [temp_ptr],y ;is this the end of the source?
|
|
and #$00FF
|
|
bne paths_ok ;not the end of source name
|
|
|
|
inc cp_to_child ; source was subset of dest! 27-Jan-92 MSD
|
|
|
|
paths_ok clc
|
|
rts
|
|
|
|
bad_path
|
|
lda #bad_path_syntax
|
|
sec
|
|
jmp main_exit
|
|
|
|
;======================================================================
|
|
|
|
scan_pass_vol ;
|
|
stx temp3_ptr ;pointer to the string
|
|
sty temp3_ptr+2
|
|
ldy #$0001
|
|
longa off
|
|
sep #$20
|
|
scanner ;
|
|
lda [temp3_ptr],y
|
|
beq scan_failed ;sorry volume name only
|
|
cmp #delimiter
|
|
beq scan_passed
|
|
iny
|
|
bra scanner
|
|
|
|
scan_passed ;
|
|
; 27-Jan-92 MSD: This routine was returning a pointer to the character
|
|
; before the pathname separator. It should have been returning a pointer
|
|
; to the character after the separator. Removed the DEY and changed a
|
|
; CLC to a SEC before adding (so it will add 1 to point past separator).
|
|
;
|
|
; dey
|
|
|
|
longa on
|
|
rep #$20 ;back to 16 bit mode
|
|
sec ; 27-Jan-92 MSD (was CLC)
|
|
tya
|
|
adc temp3_ptr
|
|
tax
|
|
lda #$0000
|
|
adc temp3_ptr+2
|
|
tay
|
|
clc ;not just a volume name
|
|
rts
|
|
|
|
scan_failed ;
|
|
longa on
|
|
rep #$20
|
|
; ldx temp3_ptr
|
|
ldy temp3_ptr+2 ;restore X and Y
|
|
sec
|
|
rts
|
|
|
|
;======================================================================
|
|
|
|
setup_path2 ;
|
|
ldx path2_ptr
|
|
ldy path2_ptr+2
|
|
inx
|
|
bne do_again
|
|
iny
|
|
do_again inx
|
|
bne cont
|
|
iny
|
|
cont ;
|
|
stx temp2_ptr ;pointer to pathname two
|
|
sty temp2_ptr+2
|
|
rts
|
|
|
|
;======================================================================
|
|
|
|
setup_path1 ;
|
|
ldx path1_ptr
|
|
ldy path1_ptr+2
|
|
inx
|
|
bne do2_again
|
|
iny
|
|
do2_again inx
|
|
bne cont2
|
|
iny
|
|
cont2 ;
|
|
stx temp_ptr ;pointer to pathname one
|
|
sty temp_ptr+2
|
|
rts
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;Set_file_info: This routine will alter information about a file on disk.
|
|
;
|
|
;Created: may 26, 1987
|
|
;Modified: jan 06, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; find_file
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Pathname Pointer (4 Bytes)
|
|
; Access (2 Bytes: Disk Format)
|
|
; File Type (2 Bytes)
|
|
; Aux Type (4 Bytes)
|
|
; Null Field (2 Bytes)
|
|
; Create Date/Time (4 Bytes: ProDOS Format)
|
|
; Mod Date/Time (4 Bytes: ProDOS Format)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Pathname Pointer (4 Bytes)
|
|
; Access (2 Bytes: Disk Format)
|
|
; File Type (2 Bytes)
|
|
; Aux Type (4 Bytes)
|
|
; Null Field (2 Bytes)
|
|
; Create Date/Time (8 Bytes: Misc. Tools Format)
|
|
; Mod Date/Time (8 Bytes: Misc. Tools Format)
|
|
; Option List (4 Bytes)
|
|
; Null Field (4 Bytes)
|
|
; Null Field (4 Bytes)
|
|
; Null Field (4 Bytes)
|
|
; Null Field (4 Bytes)
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT set_file_info
|
|
set_file_info PROC
|
|
|
|
;==========================================================================
|
|
;Indicate that we don't have any HFS Finder Info.
|
|
;==========================================================================
|
|
|
|
stz hfs_flag
|
|
|
|
;==========================================================================
|
|
;Reset all time fields to zero. This forces me to calculate the time if
|
|
;needed. However, if the create time is set to zero then the create date
|
|
;and time fields will be left unchanged.
|
|
;==========================================================================
|
|
|
|
stz mod_time
|
|
stz mod_time+2
|
|
|
|
stz create_time
|
|
stz create_time+2
|
|
|
|
;==========================================================================
|
|
;Go and setup the default parameters for the call.
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
php ;save class state
|
|
|
|
;==========================================================================
|
|
;Process the file name and locate it.
|
|
;==========================================================================
|
|
|
|
jsr process_path
|
|
jsr chk_disk_protect
|
|
|
|
;==========================================================================
|
|
;See if this is a volume header. If it is then return 'bad_path_syntax'
|
|
;==========================================================================
|
|
|
|
lda [drvr_buf_ptr]
|
|
and #$00F0
|
|
cmp #volume_header
|
|
bne ok_to_change
|
|
|
|
lda #bad_path_syntax
|
|
set_info_err ;
|
|
sec
|
|
set_info_exit ;
|
|
jmp main_exit
|
|
|
|
;==========================================================================
|
|
;Move the directory entry into one entry please
|
|
;==========================================================================
|
|
|
|
ok_to_change ;
|
|
jsr move_dir_entry
|
|
|
|
lda alloc_entry ;get the length word
|
|
ora storage_type ;add in the storage type
|
|
ora one_entry ;add in the 1st char of name
|
|
sta one_entry
|
|
|
|
plp ;restore class flag.
|
|
beq class0
|
|
|
|
;==========================================================================
|
|
;When we get here we know that this is a class one call.
|
|
;So now we start processing the parameters supplied.
|
|
;==========================================================================
|
|
|
|
dec pcount
|
|
dec pcount
|
|
|
|
jsr get_access ;setup the access field
|
|
|
|
dec pcount
|
|
bmi to_no_time_change
|
|
|
|
;==========================================================================
|
|
;go and grab the file type that the user has provided.
|
|
;If the storage type is a directory then we must nake sure the file
|
|
;type field is $0F, which indicates that the file is a directory.
|
|
;==========================================================================
|
|
|
|
jsr get_ftype
|
|
jsr set_dir_type
|
|
dec pcount
|
|
bmi to_no_time_change
|
|
|
|
;==========================================================================
|
|
;The user's has also provided the aux type.
|
|
;==========================================================================
|
|
|
|
jsr get_aux_type
|
|
|
|
;==========================================================================
|
|
;Skip all the null fields
|
|
;==========================================================================
|
|
dec pcount
|
|
dec pcount
|
|
bpl cont
|
|
to_no_time_change
|
|
brl no_time_change
|
|
cont
|
|
|
|
;==========================================================================
|
|
;user's has also provided the create data. Isn't that special!
|
|
;==========================================================================
|
|
|
|
ldy #pblk_05_create
|
|
jsr get_pblk_time
|
|
bcc @good1 ; 27-Jan-92 MSD:
|
|
ldy #$8000 ; invalid, but non-zero
|
|
@good1
|
|
stx create_time
|
|
sty create_time+2
|
|
|
|
dec pcount
|
|
bmi do_create_only
|
|
|
|
;==========================================================================
|
|
;Holly Cow Batman the user's has even given us the modification date!
|
|
;==========================================================================
|
|
|
|
ldy #pblk_05_mod
|
|
jsr get_pblk_time
|
|
bcc @good2 ; 27-Jan-92 MSD:
|
|
ldy #$8000 ; invalid, but non-zero
|
|
@good2
|
|
stx mod_time
|
|
sty mod_time+2
|
|
;new code added 2/13/91 CAE
|
|
dec pcount
|
|
bmi set_the_info
|
|
|
|
;==========================================================================
|
|
;An option list was also provided
|
|
;==========================================================================
|
|
|
|
jsr get_option_list
|
|
;end of new code
|
|
bra set_the_info
|
|
|
|
class0
|
|
;==========================================================================
|
|
;The old style call has to provide everything, So go ahead and get it.
|
|
;==========================================================================
|
|
|
|
jsr get_access
|
|
jsr get_ftype
|
|
jsr set_dir_type
|
|
jsr get_aux_type
|
|
|
|
;==========================================================================
|
|
;get the create date and time
|
|
;==========================================================================
|
|
|
|
ldy #$000E ;index to the create time
|
|
lda [my_pblk_ptr],y
|
|
sta create_time
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
sta create_time+2
|
|
|
|
;==========================================================================
|
|
;Get the modification date and time.
|
|
;==========================================================================
|
|
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
sta mod_time
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
sta mod_time+2
|
|
|
|
;==========================================================================
|
|
;We get to 'set_the_info' from both the class1 and class0 style calls.
|
|
;==========================================================================
|
|
|
|
set_the_info
|
|
jsr pack_time ;read the system clock please
|
|
;X & Y contain the date and time
|
|
|
|
lda mod_time ;did the user supply the date and time?
|
|
ora mod_time+2 ;(i.e. is the parameter != 0?)
|
|
beq @use_current ;yes, use the current date and time
|
|
ldx mod_time ;else use the user supplied values
|
|
lda mod_time+2
|
|
and #$1F3F ;make sure parameters are in range
|
|
tay
|
|
@use_current
|
|
stx one_entry+last_mod_index
|
|
sty one_entry+last_mod_index+2
|
|
|
|
do_create_only
|
|
lda create_time ;did the user supply a creation date & time?
|
|
ora create_time+2
|
|
beq no_time_change ;no, just leave it alone
|
|
lda create_time ;else copy user's values to entry
|
|
sta one_entry+create_index
|
|
lda create_time+2
|
|
and #$1F3F ;make sure parameters are in range
|
|
sta one_entry+create_index+2
|
|
|
|
no_time_change
|
|
ldy #entry_length-1
|
|
put_back ;
|
|
lda one_entry,y
|
|
sta [drvr_buf_ptr],y
|
|
dey
|
|
dey
|
|
bpl put_back
|
|
|
|
lda gbuf_addr
|
|
sta drvr_buf_ptr
|
|
lda gbuf_addr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
jsr standard_req
|
|
|
|
jsr write_with_cache
|
|
bcs all_done
|
|
|
|
jsr fix_the_fcr ;update the File Control Record if needed
|
|
jsr slug_ripple
|
|
bcs all_done
|
|
;new code code added 2/13/91 CAE
|
|
lda hfs_flag ;do we have any HFS info?
|
|
beq all_done ;no - so we're done
|
|
jsr store_hfs_info ;yes - so store it in the resource header
|
|
;end of new code
|
|
all_done jmp set_info_exit
|
|
|
|
;==========================================================================
|
|
;=============== END OF THE MAIN CODE FOR SET_FILE_INFO ===================
|
|
;==========================================================================
|
|
|
|
;==========================================================================
|
|
;Below is the subroutines used by SET_FILE_INFO.
|
|
;==========================================================================
|
|
;==========================================================================
|
|
;Now we see if the file is already open. We do this by calling
|
|
;get_next_fcr. If this routine finds a ProDOS FCR then we see if the key
|
|
;block is the same. If it is then we also update the FCR along with the
|
|
;disk
|
|
;==========================================================================
|
|
fix_the_fcr
|
|
stz fcr_wanted ;reset counter for Get_Next_FCR
|
|
|
|
look_loop ;
|
|
jsr get_next_fcr ;go grab a FCR
|
|
bcs no_fcr
|
|
|
|
ldy #fcr_vol_id
|
|
lda [my_fcr_ptr],y ;get the Volume ID so we can make sure the file is on
|
|
cmp [my_vcr_ptr] ;the same volume.
|
|
bne look_loop ;File is on another volume
|
|
|
|
ldy #fcr_file_id
|
|
lda [pro_fcr_ptr],y
|
|
cmp one_entry+key_blk_index
|
|
bne look_loop
|
|
|
|
;==========================================================================
|
|
;Save a modified Aux type please
|
|
;==========================================================================
|
|
|
|
ldy #fcr_aux_type ;update the aux type please
|
|
lda one_entry+aux_type_index
|
|
sta [pro_fcr_ptr],y
|
|
|
|
;==========================================================================
|
|
;Save file type please
|
|
;==========================================================================
|
|
|
|
ldy #fcr_file_type
|
|
lda one_entry+file_type_index
|
|
sep #$20 ;a short store
|
|
sta [pro_fcr_ptr],y
|
|
rep #$20
|
|
|
|
;==========================================================================
|
|
;Save create time please
|
|
;==========================================================================
|
|
|
|
ldy #fcr_create ;update the create time
|
|
lda one_entry+create_index
|
|
sta [pro_fcr_ptr],y
|
|
iny
|
|
iny
|
|
lda one_entry+create_index+2
|
|
sta [pro_fcr_ptr],y
|
|
|
|
no_fcr rts
|
|
|
|
;==========================================================================
|
|
;Store the user's access field in the
|
|
;==========================================================================
|
|
get_access
|
|
;
|
|
ldy #pblk_05_accs
|
|
lda [my_pblk_ptr],y
|
|
tax
|
|
and #$FF18 ;clear the reserved bits
|
|
bne bad_bits ;sorry bud you are out of range
|
|
longa off
|
|
sep #$20
|
|
txa
|
|
ora #backup_on ;force the backup bit on
|
|
sta one_entry+access_index
|
|
longa on
|
|
rep #$20
|
|
rts
|
|
|
|
bad_bits
|
|
lda #parm_range_err
|
|
brl set_info_err
|
|
|
|
;==========================================================================
|
|
;get_aux_type and store it
|
|
;==========================================================================
|
|
|
|
get_aux_type
|
|
ldy #pblk_05_aux+2
|
|
lda [my_pblk_ptr],y
|
|
bne range_problem
|
|
dey
|
|
dey
|
|
lda [my_pblk_ptr],y
|
|
sta one_entry+aux_type_index
|
|
rts
|
|
|
|
range_problem
|
|
lda #parm_range_err
|
|
brl set_info_err
|
|
|
|
;==========================================================================
|
|
;Get the file type
|
|
;==========================================================================
|
|
|
|
get_ftype
|
|
ldy #pblk_05_ftype
|
|
lda [my_pblk_ptr],y
|
|
tax
|
|
and #$FF00
|
|
bne range_problem
|
|
longa off
|
|
sep #$20
|
|
txa
|
|
sta one_entry+file_type_index
|
|
longa on
|
|
rep #$20
|
|
rts
|
|
|
|
;==========================================================================
|
|
;This routine is used to convert the extended date and time fields into
|
|
;ProDOS data and time fields
|
|
;==========================================================================
|
|
|
|
get_pblk_time
|
|
lda [my_pblk_ptr],y ;Get the second field so I can range check it
|
|
and #$00FF ;clear the minutes field
|
|
cmp #60
|
|
bcs range_problem
|
|
|
|
iny ;get the minutes field
|
|
lda [my_pblk_ptr],y
|
|
tax
|
|
and #$00FF
|
|
cmp #60 ;minutes are 00 to 59
|
|
bcs range_problem
|
|
sta minutes ;save the minutes field
|
|
txa
|
|
xba
|
|
and #$00FF
|
|
cmp #24 ;hours are 00 to 23
|
|
bcs range_problem
|
|
sta hours ;save the hours field
|
|
|
|
iny
|
|
iny
|
|
|
|
lda [my_pblk_ptr],y
|
|
tax
|
|
and #$00FF
|
|
sta year ;save the year as well
|
|
txa
|
|
xba
|
|
and #$00FF
|
|
cmp #31 ;days are 00 to 30
|
|
bcs range_problem
|
|
sta day ;don't forget the day now.
|
|
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
and #$00FF
|
|
sta month
|
|
cmp #12 ;month = 0 to 11
|
|
bcs range_problem
|
|
|
|
iny ;get the null/day of week field
|
|
lda [my_pblk_ptr],y
|
|
xba ;put null in the high byte for easy compare
|
|
cmp #$0008 ;max value is 7 for day of week
|
|
bcs range_problem
|
|
|
|
lda hours
|
|
ora minutes
|
|
ora year
|
|
ora day
|
|
ora month
|
|
beq use_clock
|
|
|
|
inc day
|
|
inc month ;comvert to ProDOS format
|
|
jsr convert_time ;convert the time to ProDOS format
|
|
rts
|
|
|
|
use_clock ;
|
|
tax ;return 0000 so we use the current time
|
|
txy
|
|
clc ; 27-Jan-92 MSD: date was valid
|
|
rts
|
|
|
|
;==========================================================================
|
|
;This routine will change the file type to $0F if the storage type of the
|
|
;file is a subdirectory
|
|
;==========================================================================
|
|
|
|
set_dir_type ;
|
|
lda storage_type ;if storage is a directory only allow
|
|
cmp #subdir_type ;file type of $0F please
|
|
bne norm_file
|
|
|
|
longa off ;short mode for a second please
|
|
sep #$20
|
|
lda #$000F ;File type for directories
|
|
sta one_entry+file_type_index
|
|
longa on
|
|
rep #$20 ;back to 16 bit mode
|
|
|
|
norm_file ;
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Get the option list info.
|
|
;
|
|
;The option list is structured as follows -
|
|
;
|
|
; word - buffer size
|
|
; word - data size
|
|
; word - FST ID
|
|
; additional data (FST-specific)
|
|
;==========================================================================
|
|
|
|
get_option_list ;added 2/13/91 CAE
|
|
|
|
; If the file is not a resource file then skip the option list since there's
|
|
; no place to store the info anyway.
|
|
|
|
lda storage_type ;get storage type
|
|
cmp #resource_type ;is it a resource file?
|
|
bne @done ;no - so skip option list
|
|
|
|
; Store ptr to option list buffer on direct page. Exit if ptr = 0.
|
|
|
|
ldy #pblk_05_opt
|
|
lda [my_pblk_ptr],y ;get option list ptr
|
|
sta <temp_ptr ;and store
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
and #$00ff ;clear hi byte
|
|
sta <temp_ptr+2
|
|
ora <temp_ptr ;is ptr 0?
|
|
beq @done ;yes - so done
|
|
|
|
; Is the buffer big enough to contain what we expect (ie. HFS Finder Info)?
|
|
|
|
lda [temp_ptr] ;get buffer size
|
|
cmp #6+32 ;is it big enough?
|
|
bcc @done ;no - so done
|
|
|
|
; The buffer is big enough so now check the data size to see if the data is
|
|
; really there. We expect a minimum of 34 bytes of data.
|
|
; NOTE - We need to check both the buffer size and the data size because in
|
|
; previous releases of GS/OS, the data size field was undefined.
|
|
|
|
ldy #2 ;get offset to data size field
|
|
lda [temp_ptr],y ;get data size
|
|
cmp #34 ;enough data?
|
|
bcc @done ;no - so done
|
|
|
|
; Check the FST ID. If it's not ProDOS, HFS or AppleShare then exit.
|
|
|
|
ldy #4 ;get offset to fst id field
|
|
lda [temp_ptr],y ;get the fst id
|
|
cmp #pro_id ;is it prodos?
|
|
beq @id_ok ;yes
|
|
cmp #hfs_id ;is it hfs?
|
|
beq @id_ok ;yes
|
|
cmp #ashare_id ;is it appleshare?
|
|
bne @done ;no - so done
|
|
@id_ok
|
|
|
|
; Copy the HFS Finder Info from the option list buffer into a storage area.
|
|
|
|
ldx #0 ;init offset into finfo storage
|
|
ldy #6 ;init offset into option list buffer
|
|
@finfo_loop lda [temp_ptr],y ;get word of finder info
|
|
sta hfs_finfo,x ;and save it in storage area
|
|
iny ;adjust offsets
|
|
iny
|
|
inx
|
|
inx
|
|
cpx #32
|
|
bcc @finfo_loop ;loop until done
|
|
|
|
inc hfs_flag ;indicate that we have HFS info
|
|
@done rts ;and return
|
|
|
|
;==========================================================================
|
|
;Store the HFS Finder Info in the resource header.
|
|
;The Finder Info is stored immediately after the mini-entry for the data fork,
|
|
;so it begins at offset $0008 in the block.
|
|
;
|
|
;format: entry size (1 byte)
|
|
; entry type (1 byte)
|
|
; HFS Finder Info (16 bytes)
|
|
; entry size (1 byte)
|
|
; entry type (1 byte)
|
|
; HFS Finder Info (16 bytes)
|
|
;
|
|
; entry_size = 18
|
|
; entry_type = 1 for first 16 bytes of Finder Info (FInfo)
|
|
; 2 for second 16 bytes of Finder Info (xFInfo)
|
|
;
|
|
;==========================================================================
|
|
|
|
store_hfs_info ;added 2/13/91 CAE
|
|
jsr set_default_buf
|
|
jsr standard_req
|
|
lda one_entry+key_blk_index
|
|
sta drvr_blk_num
|
|
stz drvr_blk_num+2
|
|
jsr read_with_cache ;get the resource header
|
|
bcs @error
|
|
|
|
lda #finfo_type ;get entry type
|
|
xba ;move it into the hi byte
|
|
ora #18 ;put entry size in lo byte
|
|
ldy #8
|
|
sta [drvr_buf_ptr],y ;and store in first entry
|
|
|
|
lda #xfinfo_type ;get entry type
|
|
xba ;move it into the hi byte
|
|
ora #18 ;put entry size in lo byte
|
|
ldy #8+18
|
|
sta [drvr_buf_ptr],y ;and store in second entry
|
|
|
|
ldx #0
|
|
ldy #10
|
|
@loop lda hfs_finfo,x ;copy the HFS Finder Info into
|
|
sta [drvr_buf_ptr],y ;the resource header
|
|
iny
|
|
iny
|
|
inx
|
|
inx
|
|
cpx #32 ;at end of second entry?
|
|
beq @loop_done ;yes
|
|
cpx #16 ;at end of first entry?
|
|
bne @loop ;no - so loop
|
|
iny ;yes - so skip over entry size
|
|
iny ;and entry type of second entry
|
|
bra @loop ;loop
|
|
@loop_done
|
|
jsr write_with_cache ;write out the header
|
|
@error rts ;and return
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;Get_file_info: This routine will return information about a file on disk.
|
|
; If the file is open and has been modified then the EOF
|
|
; and Blocks used fields come from the FCR. I do not
|
|
; return the current time for the modification time, since
|
|
; This would require a call to the SLOW clock routines.
|
|
;
|
|
;
|
|
;Created: May 23, 1987
|
|
;Modified: Aug 26, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; find_file
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Pathname Pointer (4 Bytes)
|
|
; Access (2 Bytes: Disk Format)
|
|
; File Type (2 Bytes)
|
|
; Aux Type (4 Bytes)
|
|
; Storage Type (2 Bytes)
|
|
; Create Date/Time (4 Bytes: ProDOS Format)
|
|
; Mod Date/Time (4 Bytes: ProDOS Format)
|
|
; Blocks Used (4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Pathname Pointer (4 Bytes)
|
|
; Access (2 Bytes: Disk format)
|
|
; File Type (2 Bytes)
|
|
; Aux Type (4 Bytes)
|
|
; Storage Type (2 Bytes)
|
|
; Create Date/Time (8 Bytes: Misc. Tools Format)
|
|
; Mod Date/Time (8 Bytes: Misc. Tools Format)
|
|
; Option List Pointer (4 Bytes)
|
|
; EOF Data Fork (4 Bytes)
|
|
; Blocks Used Data Fork (4 Bytes)
|
|
; EOF Resource Fork (4 Bytes)
|
|
; Blocks Used Res. Fork (4 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT get_file_info
|
|
get_file_info PROC
|
|
|
|
;==========================================================================
|
|
;Go and setup the defaul parameters for the call.
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
|
|
;==========================================================================
|
|
;Process the file name and locate it.
|
|
;==========================================================================
|
|
|
|
jsr process_path
|
|
|
|
;==========================================================================
|
|
;Move the directory entry into one entry please
|
|
;==========================================================================
|
|
|
|
jsr move_dir_entry ;move the entry to one_entry
|
|
lda one_entry ;add in the storage type
|
|
ora storage_type
|
|
sta one_entry
|
|
|
|
;==========================================================================
|
|
;If the file is a resource file then get the extended key block.
|
|
;(This code used to be below 'loop_done'. Moved here 3/13/91 CAE)
|
|
;==========================================================================
|
|
|
|
lda storage_type
|
|
cmp #resource_type
|
|
bne @cont
|
|
|
|
lda gbuf_addr
|
|
sta drvr_buf_ptr
|
|
lda gbuf_addr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
lda one_entry+key_blk_index
|
|
sta drvr_blk_num
|
|
stz drvr_blk_num+2
|
|
jsr read_with_cache
|
|
bcc @cont
|
|
brl get_exit
|
|
@cont
|
|
|
|
;==========================================================================
|
|
;Now we see if the file is already open. We do this by calling
|
|
;get_next_fcr. If this routine finds a ProDOS FCR then we see if the key
|
|
;block is the same. If it is then we get the EOF and Number of blocks
|
|
;used from the FCR instead of from disk.
|
|
;(Modified to handle resource files correctly 3/13/91 CAE)
|
|
;==========================================================================
|
|
|
|
stz fcr_wanted ;reset counter for Get_Next_FCR
|
|
look_loop
|
|
jsr get_next_fcr ;go grab a FCR
|
|
bcs loop_done
|
|
|
|
ldy #fcr_vol_id
|
|
lda [my_fcr_ptr],y ;get the Volume ID so we can make sure the file is on
|
|
cmp [my_vcr_ptr] ;the same volume.
|
|
bne look_loop ;File is on another volume
|
|
|
|
ldy #fcr_file_id
|
|
lda [pro_fcr_ptr],y
|
|
cmp one_entry+key_blk_index
|
|
bne look_loop
|
|
|
|
;Check the status bit to see if the file info is different from the info on disk.
|
|
;If not, then loop.
|
|
|
|
ldy #fcr_status
|
|
lda [pro_fcr_ptr],y
|
|
bpl look_loop
|
|
|
|
;Get the current EOF and current number of blocks allocated by the file.
|
|
|
|
ldy #fcr_curr_eof
|
|
lda [pro_fcr_ptr],y
|
|
sta one_entry+eof_index
|
|
iny
|
|
lda [pro_fcr_ptr],y
|
|
sta one_entry+eof_index+1
|
|
|
|
ldy #fcr_blks_used
|
|
lda [pro_fcr_ptr],y
|
|
sta one_entry+blks_used_index
|
|
|
|
;Check to see if we're dealing with a resource file.
|
|
;If so, copy the EOF and blocks_used info into the extended key block so send_info will
|
|
;use it.
|
|
|
|
lda storage_type
|
|
cmp #resource_type ;are we dealing with a resource file?
|
|
bne loop_done ;no - so we're done
|
|
|
|
lda [pro_fcr_ptr] ;get resource number
|
|
xba ;convert $0000 or $0001 into
|
|
tay ;$0000 or $0100
|
|
iny
|
|
iny
|
|
iny
|
|
|
|
lda one_entry+blks_used_index
|
|
sta [drvr_buf_ptr],y
|
|
iny
|
|
iny
|
|
lda one_entry+eof_index
|
|
sta [drvr_buf_ptr],y
|
|
iny
|
|
lda one_entry+eof_index+1
|
|
sta [drvr_buf_ptr],y
|
|
|
|
bra look_loop ;loop until done
|
|
loop_done
|
|
|
|
;==========================================================================
|
|
;Check to see if we're dealing with a volume header.
|
|
;==========================================================================
|
|
|
|
lda storage_type
|
|
cmp #volume_header
|
|
bne go_send_info
|
|
|
|
jsr calc_last_mod ;we need to calculate the last mod for the volume
|
|
jsr calc_free_blks ;A = free blocks
|
|
bcc have_free
|
|
jmp main_exit ;sorry there is an error
|
|
|
|
have_free
|
|
sta one_entry+blks_used_index
|
|
ldy #vol_total_blks
|
|
lda [prodos_vcr_ptr],y
|
|
sta one_entry+aux_type_index
|
|
sec
|
|
sbc one_entry+blks_used_index
|
|
sta one_entry+blks_used_index
|
|
|
|
go_send_info
|
|
lda pcount
|
|
beq old_style_info
|
|
|
|
clc
|
|
lda my_pblk_ptr
|
|
adc #$0004
|
|
tax
|
|
lda my_pblk_ptr+2
|
|
adc #$0000
|
|
tay
|
|
lda pcount
|
|
dec a
|
|
jsr send_info
|
|
bcs get_exit
|
|
clean_exit
|
|
clc
|
|
get_exit
|
|
jmp main_exit
|
|
|
|
old_style_info
|
|
|
|
;==========================================================================
|
|
;Just return the old style info for class 0 calls
|
|
;firts field is ACCESS
|
|
;==========================================================================
|
|
ldy #$0004
|
|
lda one_entry+access_index
|
|
and #$00E7
|
|
sta [my_pblk_ptr],y
|
|
|
|
;==========================================================================
|
|
;now send the FILE TYPE
|
|
;==========================================================================
|
|
iny
|
|
iny
|
|
lda one_entry+file_type_index
|
|
and #$00FF
|
|
sta [my_pblk_ptr],y
|
|
|
|
;==========================================================================
|
|
;go ahead and give them the AUX TYPE
|
|
;==========================================================================
|
|
iny
|
|
iny
|
|
lda one_entry+aux_type_index
|
|
sta [my_pblk_ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [my_pblk_ptr],y
|
|
|
|
;==========================================================================
|
|
;through in the storage type for good measure
|
|
;==========================================================================
|
|
iny
|
|
iny
|
|
lda one_entry
|
|
and #$00F0
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
sta [my_pblk_ptr],y
|
|
|
|
;==========================================================================
|
|
;how about the CREATE DATE and TIME
|
|
;==========================================================================
|
|
iny
|
|
iny
|
|
lda one_entry+create_index
|
|
sta [my_pblk_ptr],y
|
|
iny
|
|
iny
|
|
lda one_entry+create_index+2
|
|
sta [my_pblk_ptr],y
|
|
|
|
;==========================================================================
|
|
;Send the last MODIFICATION DATE and TIME
|
|
;==========================================================================
|
|
iny
|
|
iny
|
|
lda one_entry+last_mod_index
|
|
sta [my_pblk_ptr],y
|
|
iny
|
|
iny
|
|
lda one_entry+last_mod_index+2
|
|
sta [my_pblk_ptr],y
|
|
|
|
;==========================================================================
|
|
;and lastly, the number of blocks used.
|
|
;==========================================================================
|
|
iny
|
|
iny
|
|
lda one_entry+blks_used_index
|
|
sta [my_pblk_ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [my_pblk_ptr],y
|
|
bra clean_exit
|
|
|
|
;==========================================================================
|
|
;Calculate the modification date for the volume. We do this since the mod
|
|
;date is not stored on the disk. This should not be bad since the blocks
|
|
;are stored in the cache.
|
|
;
|
|
;Enter: jsr
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1= error
|
|
; b = k
|
|
;
|
|
; one_entry+last_mod_index ;is setup with the date
|
|
;
|
|
;==========================================================================
|
|
; Export calc_mod_date
|
|
calc_last_mod
|
|
lda drvr_dev_num ;pass in the device number
|
|
ldx #dummy_name ; and a pointer to the name
|
|
ldy #^dummy_name
|
|
jsr find_file ;this will fail but we do not care
|
|
|
|
lda curr_mod_date
|
|
tax
|
|
ora curr_mod_date+2
|
|
beq @same_time ;there are no files on the disk!
|
|
|
|
stx one_entry+last_mod_index
|
|
lda curr_mod_date+2
|
|
sta one_entry+last_mod_index+2
|
|
rts
|
|
@same_time
|
|
lda one_entry+create_index
|
|
sta one_entry+last_mod_index
|
|
lda one_entry+create_index+2
|
|
sta one_entry+last_mod_index+2
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;Judge_name: Returns information about ProDOS filename syntax.
|
|
; Modifies name (if supplied) to conform to ProDOS syntax.
|
|
;
|
|
;Note: This is a class 1 call only.
|
|
;
|
|
;Created: Jan 22, 1991
|
|
;Author: Cheryl Ewy
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; <temp_ptr
|
|
; <temp2_ptr
|
|
; <temp3_ptr
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; File System ID (2 Bytes)
|
|
; Name Type (2 Bytes)
|
|
; Syntax (4 Bytes)
|
|
; Max Len (2 Bytes)
|
|
; Name (4 Bytes)
|
|
; Name Flags (2 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT judge_name
|
|
judge_name PROC
|
|
|
|
|
|
name_flags equ temp2_ptr ;local equates
|
|
buf_size equ temp2_ptr+2
|
|
temp_val equ temp3_ptr
|
|
nul_flag equ temp3_ptr+2
|
|
|
|
max_len equ 15 ;maximum name length
|
|
|
|
; Setup the default parameters for the call.
|
|
|
|
jsr setup_params
|
|
|
|
; Init flags word to 0.
|
|
|
|
stz <name_flags
|
|
|
|
; Make sure the name_type input parameter is valid.
|
|
|
|
ldy #pblk_07_ntype
|
|
lda [my_pblk_ptr],y ;get name_type input param
|
|
cmp #4 ;is it < 4?
|
|
bcs bad_param ;no - so report error
|
|
|
|
; Minimum pcount is 3 so we'll always return a ptr to the syntax string.
|
|
|
|
lda #syntax_str ;get lo word of ptr to string
|
|
ldy #pblk_07_syntax
|
|
sta [my_pblk_ptr],y ;store it in output param
|
|
iny
|
|
iny
|
|
lda #^syntax_str ;get hi word of ptr to string
|
|
sta [my_pblk_ptr],y ;store it in output param
|
|
|
|
; Adjust the pcount to reflect the number of remaining parameters to deal with.
|
|
|
|
dec pcount ;done with file_sys_id param
|
|
dec pcount ;done with name_type param
|
|
dec pcount ;done with syntax param
|
|
|
|
; Return the maximum name length if requested.
|
|
|
|
dec pcount
|
|
bmi done
|
|
|
|
lda #max_len ;get maximum name length
|
|
ldy #pblk_07_max_len
|
|
sta [my_pblk_ptr],y ;store it in the max_len output param
|
|
|
|
; Get the ptr to the name buffer if supplied. The name buffer is a class 1 output buffer.
|
|
; If the ptr is 0 then there's no name to judge.
|
|
|
|
dec pcount
|
|
bmi done
|
|
|
|
ldy #pblk_07_name
|
|
lda [my_pblk_ptr],y ;get lo word of ptr to name buffer
|
|
sta <temp_ptr ;and store
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y ;get hi word of ptr to name buffer
|
|
and #$00ff ;mask off hi byte
|
|
sta <temp_ptr+2 ;and store
|
|
ora <temp_ptr ;is the ptr 0?
|
|
beq do_flags ;yes - so there's no name to judge
|
|
|
|
; Check the name buffer size to make sure the buffer is large enough to contain
|
|
; the maximum size name. If not, return an error.
|
|
|
|
lda [temp_ptr] ;get buffer size
|
|
cmp #max_len+4 ;is the buffer big enough?
|
|
bcc buf_err ;no - so return an error
|
|
sta <buf_size ;yes - so save buffer size
|
|
|
|
; Adjust <temp_ptr so that it points to the length word of the name string instead of
|
|
; to the buffer size word.
|
|
|
|
clc
|
|
lda <temp_ptr ;adjust ptr to point to the name length
|
|
adc #2
|
|
sta <temp_ptr
|
|
lda <temp_ptr+2
|
|
adc #0
|
|
sta <temp_ptr+2
|
|
|
|
; Judge the name.
|
|
|
|
jsr judge_it
|
|
|
|
; Return the name_flags parameter if requested.
|
|
|
|
do_flags dec pcount
|
|
bmi done
|
|
|
|
lda <name_flags ;get name_flags
|
|
ldy #pblk_07_nflags
|
|
sta [my_pblk_ptr],y ;store it in the output param
|
|
|
|
; Indicate no error and return.
|
|
|
|
done clc
|
|
jmp main_exit
|
|
|
|
|
|
; Return a parameter range error.
|
|
|
|
bad_param lda #parm_range_err
|
|
sec
|
|
jmp main_exit
|
|
|
|
|
|
; Return a buffer too small error.
|
|
|
|
buf_err lda #buff_too_small
|
|
sec
|
|
jmp main_exit
|
|
|
|
;--------------------------------------------------------------------------
|
|
|
|
judge_it
|
|
|
|
; If the name length = 0 then set the name string to "A", indicate that there
|
|
; was a syntax error, then return.
|
|
|
|
lda [temp_ptr] ;is the name length = 0?
|
|
bne @got_name ;no - so we have a name
|
|
@nameIsNull lda #1
|
|
sta [temp_ptr] ;set name length to 1
|
|
ldy #2
|
|
lda #'A'
|
|
sta [temp_ptr],y ;set name string to "A"
|
|
lda #$2000 ;set bit 13 of name_flags to indicate
|
|
tsb <name_flags ;that there was a syntax error
|
|
rts ;and return
|
|
@got_name
|
|
|
|
; We have a name to judge.
|
|
|
|
*** added 14-Apr-91 DAL -- call StringToText in the Misc Tools
|
|
if CallStringToText=1 then
|
|
pha ;space for StringToText result flags
|
|
pha ;space for StringToText result length
|
|
pea $6000 ;flags: force "English", allow expansion
|
|
ldx temp_ptr+2 ;push [temp_ptr]+2 -- input text
|
|
lda temp_ptr
|
|
clc
|
|
adc #2
|
|
bcc @ok
|
|
inx
|
|
@ok phx
|
|
pha
|
|
lda [temp_ptr]
|
|
pha ;push input string length
|
|
ldx temp_ptr+2 ;push [temp_ptr]-2 -- result buffer
|
|
lda temp_ptr
|
|
sec
|
|
sbc #2
|
|
bcs @ok2
|
|
dex
|
|
@ok2 phx
|
|
pha
|
|
ldx #$3b03
|
|
jsl $e10000
|
|
; _StringToText
|
|
pla ;printable length (ignore)
|
|
pla ;result flags
|
|
bpl @noChange
|
|
lda #$8000 ;set bit 15 = illegal characters
|
|
tsb <name_flags
|
|
@noChange
|
|
endif
|
|
*** end of 14-Apr-91 DAL
|
|
|
|
; Set bit 14 of name_flags if the name is too long.
|
|
; Note - we have to do this now because the name length may change.
|
|
|
|
lda [temp_ptr] ;get name length
|
|
*** added 29-Apr-91 DAL
|
|
beq @nameIsNull
|
|
*** end of 29-Apr-91 DAL
|
|
cmp #max_len+1 ;is it too long?
|
|
bcc @len_ok ;no
|
|
lda #$4000 ;yes - so set bit 14 of name_flags
|
|
tsb <name_flags ;to indicate name was too long
|
|
@len_ok
|
|
|
|
; Convert all illegal characters to NULs. They'll be converted to periods later.
|
|
|
|
lda [temp_ptr] ;get length of pathname
|
|
inc a ;adjust for extra length byte
|
|
tay
|
|
|
|
ldx #0 ;init to 0
|
|
|
|
longa off ;set 8 bit A
|
|
sep #$20
|
|
|
|
loop1 lda [temp_ptr],y ;get byte
|
|
|
|
cmp #'a'
|
|
bcc @check_upper
|
|
cmp #'z'+1
|
|
bcs @bad_char
|
|
bra @ok ;it's a lower-case letter
|
|
|
|
@check_upper cmp #'A'
|
|
bcc @check_num
|
|
cmp #'Z'+1
|
|
bcs @bad_char
|
|
bra @ok ;it's an upper-case letter
|
|
|
|
@check_num cmp #'0'
|
|
bcc @check_period
|
|
cmp #'9'+1
|
|
bcs @bad_char
|
|
bra @ok ;it's a number
|
|
|
|
@check_period cmp #'.'
|
|
beq @ok ;it's a period
|
|
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
cmp #' ' ;it's a blank
|
|
beq @ok
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
@bad_char lda #$00 ;it's an illegal character so
|
|
sta [temp_ptr],y ;replace char with a NUL
|
|
ldx #$8000 ;indicate illegal character found
|
|
@ok dey ;decrement offset
|
|
cpy #1
|
|
bne loop1 ;loop until done
|
|
|
|
longa on ;set 16 bit A
|
|
rep #$20
|
|
|
|
txa ;set bit 15 if an illegal
|
|
tsb <name_flags ;character was found
|
|
|
|
; If the name doesn't begin with a letter, then indicate that there was a syntax error.
|
|
; Note - we have to check this now because if the first character is illegal, it will
|
|
; be removed by the next section of code.
|
|
|
|
ldy #2
|
|
lda [temp_ptr],y ;get first 2 chars
|
|
and #$00ff ;only want first char
|
|
cmp #'A' ;is it a letter?
|
|
bcs @syntax_ok ;yes - so we're ok
|
|
lda #$2000 ;set bit 13 to indicate that
|
|
tsb <name_flags ;there was a syntax error
|
|
@syntax_ok
|
|
|
|
; Replace runs of 2 or more NULs with a single period.
|
|
; All leading and trailing NULs will be removed.
|
|
; Note - if no illegal characters were found, then skip this section.
|
|
|
|
lda <name_flags ;were there any illegal characters?
|
|
bpl skip_it ;no - so skip this section
|
|
|
|
lda [temp_ptr] ;get name length
|
|
inc a ;add 2 to account for the length bytes
|
|
inc a
|
|
sta <temp_val ;and save
|
|
|
|
longa off
|
|
sep #$20 ;set 8 bit A
|
|
|
|
ldx #2 ;init offsets
|
|
phx
|
|
stx <nul_flag ;init flag to indicate we've seen a NUL
|
|
|
|
loop2 ply ;get offset
|
|
cpy <temp_val ;are we done?
|
|
bcs loop2_done ;yes
|
|
lda [temp_ptr],y ;no - so read next character
|
|
iny ;adjust offset
|
|
phy ;and save
|
|
cmp #$00 ;is the char a NUL?
|
|
bne @not_nul ;no - so branch
|
|
ldy <nul_flag ;was the last character a NUL?
|
|
bne loop2 ;yes - so loop
|
|
inc <nul_flag ;no - so indicate we've seen a NUL
|
|
lda #'.' ;convert the NUL into a period
|
|
bra @store_char ;and store the period
|
|
|
|
@not_nul stz <nul_flag ;indicate we've seen a non-NUL
|
|
@store_char txy
|
|
sta [temp_ptr],y ;store the character
|
|
tyx
|
|
inx ;adjust offset
|
|
bra loop2 ;and loop
|
|
|
|
loop2_done lda <nul_flag ;was the last char read a NUL?
|
|
beq @ok ;no
|
|
cpx #2 ;yes - was it stored?
|
|
beq @ok ;no
|
|
dex ;yes - so don't count it
|
|
@ok
|
|
longa on
|
|
rep #$20 ;set 16 bit A
|
|
|
|
txa ;determine new name length
|
|
dec a
|
|
dec a
|
|
sta [temp_ptr] ;and store
|
|
skip_it
|
|
|
|
; If the name doesn't begin with a letter, insert an 'A' as the first character.
|
|
; If the buffer has no extra space, then lose the last character.
|
|
; Note - we need to check for a zero-length name in case all chars were illegal.
|
|
|
|
lda [temp_ptr] ;get name length
|
|
bne @not_zero ;branch if it's > 0
|
|
inc a ;name length is 0 so
|
|
sta [temp_ptr] ;set length to 1
|
|
bra stuff_a ;and insert the 'A'
|
|
@not_zero
|
|
ldy #2
|
|
lda [temp_ptr],y ;get first 2 chars
|
|
and #$00ff ;only want first char
|
|
cmp #'A' ;is it a letter?
|
|
bcs char1_ok ;yes - so we're ok
|
|
|
|
lda [temp_ptr] ;get name length
|
|
tay ;and save
|
|
clc
|
|
adc #4
|
|
cmp <buf_size ;does the buffer have any unused space?
|
|
bcs @lose_last ;no - so lose last char
|
|
iny ;yes - so save last char
|
|
tya
|
|
sta [temp_ptr] ;add 1 to name length
|
|
@lose_last
|
|
loop3 lda [temp_ptr],y ;move all chars over by 1
|
|
xba
|
|
sta [temp_ptr],y
|
|
dey
|
|
cpy #1
|
|
bne loop3
|
|
|
|
longa off
|
|
stuff_a sep #$20 ;set 8 bit A
|
|
|
|
ldy #2
|
|
lda #'A'
|
|
sta [temp_ptr],y ;stuff an 'A' in as first char
|
|
|
|
longa on
|
|
rep #$20 ;set 16 bit A
|
|
char1_ok
|
|
|
|
; If the name is too long then keep the first 7 chars, insert '..', keep the last 6 chars.
|
|
|
|
lda [temp_ptr] ;get name length
|
|
cmp #max_len+1 ;is it too long?
|
|
bcc length_ok ;no
|
|
|
|
ldy #9 ;get offset to 8th char
|
|
lda #'..'
|
|
sta [temp_ptr],y ;insert the '..'
|
|
|
|
lda [temp_ptr] ;get length of name
|
|
sec
|
|
sbc #4 ;subtract 4 to get offset
|
|
pha ;to last part of name to keep
|
|
|
|
longa off ;set 8 bit A
|
|
sep #$20
|
|
|
|
ldx #11 ;set offset after the '..' (10th char)
|
|
loop4 ply
|
|
lda [temp_ptr],y ;move the last 6 characters
|
|
iny ;so they are after the '..'
|
|
phy
|
|
txy
|
|
sta [temp_ptr],y
|
|
inx
|
|
cpx #17 ;are we done?
|
|
bne loop4 ;no - so loop
|
|
ply ;clean up stack
|
|
|
|
longa on ;set 16 bit A
|
|
rep #$20
|
|
|
|
lda #max_len ;adjust the name length
|
|
sta [temp_ptr]
|
|
length_ok
|
|
|
|
; Done with name.
|
|
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;Volume: This routine will return the volume information on a disk
|
|
;
|
|
;Note: This routine will now store the volume name in the user's
|
|
; buffer if a "duplicate volume" error is being returned.
|
|
; 1/22/91 CAE
|
|
;
|
|
;Created: may 24, 1987
|
|
;Modified: may 24, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; fill_io_buf
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Device Name Pointer (4 Bytes)
|
|
; Volume Name Pointer (4 Bytes)
|
|
; Total Blocks (4 Bytes)
|
|
; Free Blocks (4 Bytes)
|
|
; File System ID (2 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Device Name Pointer (4 Bytes)
|
|
; Volume Name Pointer (4 Bytes)
|
|
; Total Blocks (4 Bytes)
|
|
; Free Blocks (4 Bytes)
|
|
; File System ID (2 Bytes)
|
|
; Block Size (2 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT volume
|
|
volume PROC
|
|
|
|
;==========================================================================
|
|
;Call setup routine. This routine will verify input parameters like
|
|
; call class, max pcount and span. It will also setup
|
|
; any pointers that are used.
|
|
;
|
|
;The routine loads the class of the call as the last instruction before RTS
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
|
|
;==========================================================================
|
|
;Now lets go and and ID that puppy. The device number to ID is on ZP
|
|
;==========================================================================
|
|
|
|
lda #in_cache ;force block two into the cache
|
|
sta drvr_cache
|
|
|
|
stz dup_vol_flag ;init flag word to 0
|
|
lda dev_num
|
|
jsr id_disk ;go see if it belongs to me
|
|
jsr set_user_cache ;set cache back to default
|
|
bcc its_my_puppy
|
|
cmp #dup_volume ;got an error - is it 'duplicate volume'?
|
|
sec ;make sure carry is still set
|
|
bne vol_exit ;no - so exit with error
|
|
sta dup_vol_flag ;yes - so store error code in flag word
|
|
bra its_my_puppy ;and continue
|
|
|
|
vol_exit jmp main_exit
|
|
|
|
dup_vol_flag DS.B 2 ;non-zero if we've got a duplicate volume
|
|
|
|
|
|
;==========================================================================
|
|
;move the name into the user's buffer.
|
|
;==========================================================================
|
|
|
|
its_my_puppy
|
|
ldy #pblk_08_vol
|
|
|
|
lda [my_pblk_ptr],y
|
|
sta temp_ptr
|
|
tax
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
sta temp_ptr+2
|
|
|
|
stz case_bits ;all upper case please
|
|
|
|
lda fst_attr ;if the high bit is set skip Upper/Lower stuff
|
|
bmi @no_case_change
|
|
|
|
ldy #create_index-2 ;save the case bits please
|
|
lda [drvr_buf_ptr],y
|
|
bpl @no_case_change
|
|
asl a ;remove the case ON/OFF bit
|
|
sta case_bits
|
|
@no_case_change
|
|
|
|
lda pcount
|
|
bne class1
|
|
|
|
;==========================================================================
|
|
;before we send the name we have to add in the damn leading slash.
|
|
;==========================================================================
|
|
|
|
lda [drvr_buf_ptr]
|
|
and #$000F
|
|
sta math_temp ;save the length of the name
|
|
inc a
|
|
sta [temp_ptr] ;length of the name
|
|
inc temp_ptr
|
|
bne class0_name
|
|
inc temp_ptr+2
|
|
|
|
class0_name
|
|
ldy #$0001 ;start at the beginning
|
|
longa off
|
|
sep #$20 ;8 bit moves please
|
|
lda #'/'
|
|
sta [temp_ptr] ;store the leading slash
|
|
class0_loop ;
|
|
lda [drvr_buf_ptr],y
|
|
rep #$20
|
|
rol case_bits ;see if this char is lower case
|
|
sep #$20
|
|
bcc @its_upper
|
|
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
cmp #'.'
|
|
bne @not_lc_period
|
|
lda #0 ;let it ORA our 0 into a $20 (blank!)
|
|
@not_lc_period
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
ora #$20 ;set the lower case bit please
|
|
@its_upper
|
|
sta [temp_ptr],y
|
|
cpy math_temp
|
|
beq @were_done
|
|
iny
|
|
bra class0_loop
|
|
@were_done
|
|
longa on
|
|
rep #$20
|
|
|
|
;If dup_vol_flag is non-zero then we don't want to send the rest of the output
|
|
;parameters so just exit with the "duplicate volume" error.
|
|
|
|
lda dup_vol_flag ;check the flag
|
|
beq @no_error ;it's 0 so continue
|
|
sec ;we've got a duplicate volume so set carry
|
|
brl vol_exit ;and exit with the error
|
|
@no_error
|
|
|
|
;==========================================================================
|
|
;Since this is a class zero call lets set the pcount to three so all the
|
|
;parameters will be returned to the caller.
|
|
;==========================================================================
|
|
|
|
lda #$0003 ;setup pcount
|
|
sta pcount
|
|
bra do_bitmap
|
|
|
|
class1
|
|
|
|
;==========================================================================
|
|
;If we get here we need to verify that the buffer is large enought to hold
|
|
;the volume name.
|
|
;
|
|
;diagram
|
|
; ______________
|
|
; | Buffer size | W
|
|
; |--------------|
|
|
; | Name Length | W
|
|
; |--------------|
|
|
; | Leading '/' | B
|
|
; |--------------|
|
|
; | THE |
|
|
; | REST OF | 'n'
|
|
; | THE NAME |
|
|
; |______________|
|
|
;
|
|
;==========================================================================
|
|
|
|
lda [drvr_buf_ptr]
|
|
and #$000F
|
|
tax
|
|
inc a
|
|
sta math_temp ;save the size of the name + slash.
|
|
|
|
sec
|
|
lda [temp_ptr]
|
|
sbc #$0004 ;minus overhead
|
|
bmi too_small ;get out of here!
|
|
cmp math_temp
|
|
beq size_ok
|
|
bcs size_ok
|
|
|
|
ldy #$0002
|
|
lda math_temp
|
|
sta [temp_ptr],y ;store the length of the name
|
|
|
|
too_small ;
|
|
sec
|
|
lda #buff_too_small ;return the error
|
|
back_to_exit brl vol_exit
|
|
|
|
size_ok ;
|
|
|
|
;==========================================================================
|
|
;now move the name to the user's buffer.
|
|
;==========================================================================
|
|
|
|
ldy #$0002 ;index to the length result
|
|
lda math_temp
|
|
sta [temp_ptr],y
|
|
iny
|
|
iny
|
|
lda #delimiter+(delimiter*$100)
|
|
sta [temp_ptr],y
|
|
|
|
;==========================================================================
|
|
;adjust the pointer to point to the beginning of the name buffer.
|
|
;==========================================================================
|
|
phx
|
|
tya
|
|
clc
|
|
adc temp_ptr
|
|
sta temp_ptr
|
|
lda #$0000
|
|
adc temp_ptr+2
|
|
sta temp_ptr+2
|
|
|
|
ply
|
|
sty math_temp
|
|
ldy #$0001
|
|
longa off
|
|
sep #$20
|
|
class1_loop
|
|
|
|
lda [drvr_buf_ptr],y
|
|
rep #$20
|
|
rol case_bits ;see if this char is lower case
|
|
sep #$20
|
|
bcc @its_upper
|
|
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
cmp #'.'
|
|
bne @not_lc_period
|
|
lda #0 ;let it ORA our 0 into a $20 (blank)
|
|
@not_lc_period
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
ora #$20 ;set the lower case bit please
|
|
@its_upper
|
|
sta [temp_ptr],y
|
|
cpy math_temp ;are we done?
|
|
beq @were_done
|
|
iny
|
|
bra class1_loop
|
|
@were_done
|
|
longa on
|
|
rep #$20
|
|
|
|
;If dup_vol_flag is non-zero then we don't want to send the rest of the output
|
|
;parameters so just exit with the "duplicate volume" error.
|
|
|
|
lda dup_vol_flag ;check the flag
|
|
beq @no_error ;it's 0 so continue
|
|
sec ;we've got a duplicate volume so set carry
|
|
brl vol_exit ;and exit with the error
|
|
@no_error
|
|
|
|
;==========================================================================
|
|
;adjust the pcount to reflect the number of parameters that the user still
|
|
;wants.
|
|
;==========================================================================
|
|
|
|
dec pcount
|
|
dec pcount
|
|
|
|
do_bitmap ;
|
|
|
|
;==========================================================================
|
|
;now lets see if the caller wants the total blocks on the volume
|
|
;==========================================================================
|
|
|
|
dec pcount
|
|
bpl send_tot_blks
|
|
end_volume clc
|
|
backup2 brl vol_exit
|
|
|
|
send_tot_blks ;
|
|
ldy #vol_total_blks
|
|
lda [prodos_vcr_ptr],y
|
|
ldy #pblk_08_tot
|
|
sta [my_pblk_Ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [my_pblk_ptr],y
|
|
|
|
;==========================================================================
|
|
;see if the caller wants the number of free blocks. We call calc_free_blks
|
|
;to calculate the number of free blocks. The routine returns the TOTAL
|
|
;number of blocks available in the 'A' register.
|
|
;==========================================================================
|
|
dec pcount
|
|
bmi end_volume
|
|
|
|
jsr calc_free_blks
|
|
bcs backup2 ;some major error occured
|
|
|
|
ldy #pblk_08_free
|
|
sta [my_pblk_ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [my_pblk_ptr],y
|
|
|
|
;==========================================================================
|
|
;do they want the file system ID?
|
|
;==========================================================================
|
|
|
|
dec pcount
|
|
bmi end_volume ;no they do not!
|
|
|
|
lda #pro_id
|
|
ldy #pblk_08_id
|
|
sta [my_pblk_ptr],y
|
|
|
|
;==========================================================================
|
|
;do they want to know my block size?
|
|
;==========================================================================
|
|
|
|
dec pcount
|
|
bmi end_volume ;no they do not!
|
|
|
|
lda #blk_size
|
|
ldy #pblk_08_size
|
|
sta [my_pblk_ptr],y
|
|
bra end_volume
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;Clear_backup: This routine will clear the backup bit for a file.
|
|
;
|
|
;Created: may 27, 1987
|
|
;Modified: may 27, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; find_file
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Pathname pointer (4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Pathname pointer (4 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT clear_backup
|
|
clear_backup PROC
|
|
|
|
;==========================================================================
|
|
;Setup the general parameters.
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
|
|
;==========================================================================
|
|
;Process the file name and locate it. On exit 'drvr_buf_ptr' points to the
|
|
;file entry that we are suppose to act on.
|
|
;==========================================================================
|
|
|
|
jsr process_path
|
|
bcc good
|
|
clear_exit
|
|
jmp main_exit
|
|
|
|
good
|
|
jsr chk_disk_protect
|
|
|
|
ldy #access_index
|
|
longa off
|
|
sep #$20
|
|
|
|
;==========================================================================
|
|
;Clear the backup bit for the file/directory
|
|
;==========================================================================
|
|
|
|
lda [drvr_buf_ptr],y
|
|
and #backup_off ;clear the backup bit
|
|
sta [drvr_buf_ptr],y
|
|
|
|
; If we're dealing with a volume directory then we need to clear the backup bit
|
|
; in the VCR also so that the disk and VCR match. 4/5/91 CAE
|
|
|
|
lda [drvr_buf_ptr] ;get storage type
|
|
and #$F0 ;only want hi nibble
|
|
cmp #volume_header ;is this a volume directory?
|
|
bne @not_vol ;no - so branch
|
|
ldy #vol_access
|
|
lda [prodos_vcr_ptr],y
|
|
and #backup_off ;clear the backup bit in the vcr
|
|
sta [prodos_vcr_ptr],y
|
|
@not_vol
|
|
longa on
|
|
rep #$20
|
|
|
|
;==========================================================================
|
|
;Reset the I/O buffer pointer to the beginning of the buffer.
|
|
;The request count and all that stuff is still correct from the find file
|
|
;==========================================================================
|
|
|
|
lda gbuf_addr
|
|
sta drvr_buf_ptr
|
|
lda gbuf_addr+2
|
|
sta drvr_buf_ptr+2
|
|
jsr write_with_cache
|
|
bra clear_exit
|
|
|
|
ENDP
|
|
;======================================================================
|
|
;Open: This file contains code that is used to open a file on
|
|
; disk.
|
|
;
|
|
;Created: Apr 13, 1987
|
|
;Modified: Apr 16, 1988
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: From GS/OS jmp table
|
|
;
|
|
;Input: A = undefined
|
|
; X = (call number * 2)
|
|
; Y = (class number * 2)
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = error code if carry set (exit via system exit routine)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
; find_file (subroutine)
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Reference Number (2 Bytes)
|
|
; Pathname Pointer (4 Bytes)
|
|
; Reserved (4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Reference Number (2 Bytes)
|
|
; Pathname Pointer (4 Bytes)
|
|
; Request Access (2 Bytes: New Format)
|
|
; Resource Number (2 Bytes)
|
|
; (Returned Info)
|
|
; Access (2 Bytes)
|
|
; File Type (2 Bytes)
|
|
; Aux Type (4 Bytes)
|
|
; Storage Type (2 Bytes)
|
|
; Create Date/Time (8 Bytes: Misc. Tools Format)
|
|
; Mod Date/Time (8 Bytes: Misc. Tools Format)
|
|
; Option List Pointer (4 Bytes)
|
|
; EOF Data Fork (4 Bytes)
|
|
; Blocks Used Data Fork (4 Bytes)
|
|
; EOF Resource Fork (4 Bytes)
|
|
; Blocks Used Res. Fork (4 Bytes)
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT open
|
|
open PROC
|
|
|
|
;==========================================================================
|
|
;Setup the defaults for the open call.
|
|
;The defaults are set to OPEN resource number $0000(main data) and open file
|
|
;as permitted.
|
|
;==========================================================================
|
|
|
|
stz resource_num ;set resource to main data fork
|
|
stz access ;set users access to 'as permitted'
|
|
stz users_access ;set the users access please.
|
|
|
|
jsr setup_params
|
|
beq class0
|
|
|
|
jsr get_access ;get the user's access byte if avail
|
|
bcs class0 ;branch if no access provided
|
|
jsr get_res_num ;get the user's resource num if avail
|
|
|
|
class0 ;
|
|
;==========================================================================
|
|
;Now go and find the file we need. If the disk is not ProDOS then we
|
|
;never return from the call. It will automatically exit thru 'SYS_EXIT'
|
|
;==========================================================================
|
|
|
|
jsr process_path
|
|
|
|
;==========================================================================
|
|
;We get here when we have found the file and are ready to open it.
|
|
;This section of code expects 'drvr_buf_ptr' to point to the file name to open
|
|
;==========================================================================
|
|
|
|
open_the_file ;
|
|
jsr move_dir_entry ;put the disk entry in a common place
|
|
|
|
jsr verify_storage ;make sure I can deal with the file
|
|
bcs open_exit ;sorry bud
|
|
jsr check_dup ;see if this is a duplicate open
|
|
bcs open_exit ;yes this is a duplicate open
|
|
jsr build_the_fcr ;build the file control record
|
|
bcs open_exit
|
|
|
|
;==========================================================================
|
|
;Now that we have setup the entrire FCR we need to send back any info
|
|
;that the user requested.
|
|
;==========================================================================
|
|
|
|
ldy #$0000 ;default = Class zero type call
|
|
lda call_number ;determine class
|
|
and #class_mask
|
|
beq class0_call
|
|
ldy #$0002 ;index to ref field for new class calls
|
|
|
|
;==========================================================================
|
|
;Return the file reference number to the caller.
|
|
;==========================================================================
|
|
|
|
class0_call ;
|
|
lda [my_fcr_ptr]
|
|
sta [param_blk_ptr],y
|
|
|
|
jsr send_open_parms
|
|
bcc open_exit
|
|
pha
|
|
jsr remove_fcr ;remove this puppy
|
|
pla
|
|
sec
|
|
open_exit
|
|
jmp main_exit
|
|
|
|
|
|
;==========================================================================
|
|
;==========================================================================
|
|
;====== MAIN END OF OPEN CALL ============================================
|
|
;==========================================================================
|
|
;==========================================================================
|
|
|
|
;==========================================================================
|
|
;no see how many paremters the user would like with the open call.
|
|
;
|
|
;Enter: jsr
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;==========================================================================
|
|
|
|
send_open_parms ;
|
|
lda pcount
|
|
cmp #pcount5 ;see if there is more then 4 params
|
|
bcc end_send ;no additional parameters needed
|
|
sbc #pcount5-1
|
|
pha
|
|
|
|
;==========================================================================
|
|
;If we fall thru to here then we know the user wants to receive additional
|
|
;information with the open. So we start sending the number of field
|
|
;the user wants. The routine that sends the info expects the following:
|
|
;
|
|
; A = number of fields to send
|
|
; X = low word address of where to start storing the info
|
|
; Y = high word address ...
|
|
; one_entry = the entry from the disk
|
|
; drvr_buf_ptr = ptr to resource header block
|
|
;==========================================================================
|
|
|
|
clc ;make a pointer to data start
|
|
lda my_pblk_ptr
|
|
adc #$000A
|
|
tax
|
|
lda my_pblk_ptr+2
|
|
adc #$0000
|
|
tay
|
|
|
|
lda gbuf_addr ;set up pointer to resource header
|
|
sta drvr_buf_ptr
|
|
lda gbuf_addr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
lda one_entry
|
|
and #$FF0F ;clear garbage
|
|
ora entry_sto_type ;add in entry type from dir entry
|
|
sta one_entry
|
|
|
|
pla ;recall number of params wanted
|
|
jsr send_info
|
|
end_send
|
|
rts
|
|
|
|
;=============================================================================
|
|
;Now we check the storage type. The only storage types that I know about are:
|
|
;
|
|
;(1) seedling ($0010)
|
|
;(2) sapling ($0020)
|
|
;(3) tree ($0030)
|
|
;(4) pascal area (Access not allowed to pascal area)
|
|
;(5) resource ($0050)
|
|
;(6) purge_dir (access not allowed to purged directory)
|
|
;(7) subdir ($00D0)
|
|
;(8) subdir H (access not allowed to header entry)
|
|
;(9) vol header ($00F0)
|
|
;
|
|
;Enter: 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
|
|
;
|
|
;=============================================================================
|
|
|
|
verify_storage ;
|
|
lda storage_type
|
|
sta entry_sto_type
|
|
|
|
cmp #resource_type
|
|
beq setup_access
|
|
|
|
ldx resource_num ;make sure the resource number is zero
|
|
bne bad_resource
|
|
|
|
cmp #tree_type
|
|
beq setup_access
|
|
cmp #sapling_type
|
|
beq setup_access
|
|
cmp #seedling_type
|
|
beq setup_access
|
|
cmp #subdir_type
|
|
beq dir_access
|
|
cmp #volume_header
|
|
bne bad_storage
|
|
|
|
;=============================================================================
|
|
;If the file is a directory then we must set the access to read only
|
|
;=============================================================================
|
|
dir_access ;
|
|
lda access ;make sure user wants read only
|
|
beq force_read_only ;He wants as permitted, so force read
|
|
cmp #write_access
|
|
bcs bad_access
|
|
|
|
force_read_only ;
|
|
lda #read_access
|
|
sta access
|
|
clc
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Now we need to check the access. If the access is 'as_permitted' then we
|
|
;must convert the disk access to one of our types (read only, read write, etc)
|
|
;==========================================================================
|
|
|
|
setup_access ;
|
|
lda access
|
|
bne verify_access
|
|
|
|
;==========================================================================
|
|
;Load the disk based access byte
|
|
;==========================================================================
|
|
|
|
lda one_entry+access_index
|
|
and #read_access+write_access
|
|
beq bad_access ;read/write disabled?
|
|
|
|
ldx #write_access
|
|
lsr a
|
|
bcc set_access ;force write only access
|
|
ldx #read_access
|
|
lsr a
|
|
bcc set_access ;force read only access
|
|
ldx #read_access+write_access
|
|
set_access ;
|
|
stx access ;access now set from disk
|
|
exit_access ;
|
|
clc
|
|
rts
|
|
|
|
;==========================================================================
|
|
;make sure the user's access agrees with the disk based access.
|
|
;==========================================================================
|
|
verify_access ;
|
|
ldx one_entry+access_index
|
|
lsr a
|
|
bcc no_read ;user does not want read access
|
|
tay ;temp save
|
|
jsr chk_read
|
|
beq bad_access ;sorry bud
|
|
tya
|
|
|
|
no_read ;
|
|
lsr a ;does the user want write access?
|
|
bcc exit_access ;no
|
|
jsr chk_write
|
|
beq bad_access ;write access not allowed
|
|
clc
|
|
rts
|
|
|
|
chk_read ;
|
|
txa ;access byte from the disk
|
|
and #$0001 ;isolate read bit
|
|
rts
|
|
chk_write ;
|
|
txa ;access byte from disk
|
|
and #$0002
|
|
rts
|
|
|
|
|
|
bad_resource ;
|
|
lda #res_not_found
|
|
sec
|
|
rts
|
|
|
|
bad_access ;
|
|
lda #invalid_access
|
|
sec
|
|
rts
|
|
|
|
bad_storage lda #bad_store_type
|
|
sec
|
|
rts
|
|
|
|
;==========================================================================
|
|
;see if the user provided resource number.
|
|
;
|
|
;Enter: 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
|
|
;
|
|
;==========================================================================
|
|
get_res_num ;
|
|
lda pcount
|
|
cmp #$0004
|
|
bcc end_res ;no resource number provided
|
|
|
|
ldy #$0008
|
|
lda [my_pblk_ptr],y
|
|
beq end_res ;default resource number so exit
|
|
sta resource_num ;save the resource. must be zero
|
|
dec a
|
|
bne not_in_range ;not even close.
|
|
|
|
end_res ;
|
|
rts
|
|
|
|
;==========================================================================
|
|
;get_access This routine will load the user's access byte if available
|
|
;
|
|
;
|
|
;Enter: jsr
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = no more parameters
|
|
; 0 = more paramters may follow
|
|
; b = k
|
|
;
|
|
;==========================================================================
|
|
|
|
get_access
|
|
lda pcount
|
|
cmp #$0003
|
|
bcc no_params ;there is no parameters
|
|
|
|
ldy #$0006
|
|
lda [my_pblk_ptr],y
|
|
sta users_access ;save the user's access please.
|
|
beq end_access ;same as default access so exit
|
|
|
|
;==========================================================================
|
|
;access:
|
|
; 00 = open as permitted ;default value for open call
|
|
; 01 = open for reading only
|
|
; 02 = open for writing only
|
|
; 03 = open for reading and writing
|
|
;==========================================================================
|
|
|
|
sta access ;save user's choice
|
|
cmp #read_write_acc+1
|
|
bcc end_access
|
|
|
|
not_in_range ;
|
|
lda #parm_range_err ;I don't know what to do with this
|
|
jmp error_exit ;sorry bud
|
|
|
|
no_params ;
|
|
sec
|
|
rts
|
|
|
|
end_access ;
|
|
clc
|
|
rts
|
|
|
|
|
|
;==========================================================================
|
|
;Calculate the size of the root directory. This is a pain but we cannot
|
|
;assume that the root directory will be four blocks long. So we might as
|
|
;well put the directory blocks in the cache while we are at it
|
|
;
|
|
;Enter: jsr
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = no more parameters
|
|
; 0 = more paramters may follow
|
|
; b = k
|
|
;==========================================================================
|
|
|
|
EXPORT vol_file_size
|
|
vol_file_size
|
|
stz one_entry+eof_index+1
|
|
|
|
|
|
lda gbuf_addr
|
|
sta drvr_buf_ptr
|
|
lda gbuf_addr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
stz math_temp ;used to count the number of blocks
|
|
|
|
stz drvr_blk_num+2
|
|
lda #vol_dir_start
|
|
|
|
block_loop
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcc cont_blk
|
|
pha ;save the error code
|
|
jsr remove_fcr
|
|
pla
|
|
sec
|
|
jmp main_exit
|
|
|
|
cont_blk
|
|
inc math_temp
|
|
ldy #$0002
|
|
lda [drvr_buf_ptr],y
|
|
bne block_loop
|
|
|
|
end_blk_cnt ;
|
|
lda math_temp
|
|
sta one_entry+blks_used_index
|
|
xba
|
|
asl a ;times two for EOF
|
|
sta one_entry+eof_index
|
|
jsr set_user_cache
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;This routine will build the FCR.
|
|
;
|
|
;Enter: 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
|
|
;
|
|
;==========================================================================
|
|
|
|
EXPORT build_the_fcr
|
|
build_the_fcr PROC
|
|
|
|
;==========================================================================
|
|
;allocation size:
|
|
;
|
|
;directories 2 blocks
|
|
;read/write files 3 blocks
|
|
;read seedling 1 block
|
|
;read sapling 2 block
|
|
;read tree 3 blocks
|
|
;
|
|
;==========================================================================
|
|
|
|
ldy #data_active+index_active
|
|
lda #fcr_index_size ;two block I/O buffer for directories
|
|
ldx storage_type
|
|
cpx #subdir_type
|
|
bcs alloc_the_fcr
|
|
|
|
lda access ;see if the file is open for read only
|
|
cmp #read_access
|
|
bne norm_io_buf ;allocate a large I/O buffer
|
|
|
|
ldy #data_active
|
|
lda #fcr_data_size
|
|
cpx #seedling_type ;one block buffer for seedling files
|
|
beq alloc_the_fcr
|
|
|
|
ldy #data_active+index_active
|
|
lda #fcr_index_size
|
|
cpx #sapling_type ;two blocks for a sapling file
|
|
beq alloc_the_fcr
|
|
|
|
norm_io_buf ;
|
|
ldy #data_active+index_active+master_active
|
|
lda #fcr_master_size ;allocate three blocks for I/O buffer
|
|
|
|
;==========================================================================
|
|
;when we get here A = number of bytes wanted
|
|
;==========================================================================
|
|
|
|
alloc_the_fcr ;
|
|
phy
|
|
pha
|
|
|
|
; jsr entry_to_gstr ;convert to a gstring for mike
|
|
;
|
|
|
|
ldy #vcr_name ;pass in the name of the Volume please
|
|
lda [my_vcr_ptr],y ;get the VP please
|
|
tax
|
|
iny
|
|
iny
|
|
lda [my_vcr_ptr],y
|
|
tay ;High word of the VP
|
|
jsl deref ;convert the VP to a real pointer
|
|
;return X&Y pointer to the name
|
|
|
|
pei temp_ptr ;save the pointer I am going to use
|
|
pei temp_ptr+2
|
|
|
|
stx temp_ptr ;save the address of the string
|
|
sty temp_ptr+2
|
|
|
|
lda [temp_ptr] ;get the length word please
|
|
tay ;save the count
|
|
inc a ;add one for the :
|
|
sta gstring ;save the count
|
|
lda #'::'
|
|
sta gstring+2 ;save the seperator
|
|
|
|
inc temp_ptr
|
|
bne @01
|
|
inc temp_ptr+2
|
|
@01
|
|
lda [temp_ptr],y ;get a char please
|
|
sta gstring+2,y
|
|
dey
|
|
bne @01
|
|
|
|
pla
|
|
sta temp_ptr+2 ;restore the pointer I used
|
|
pla
|
|
sta temp_ptr
|
|
|
|
ldx #gstring ;pointer to the file name or Volume Name to Open
|
|
ldy #^gstring ;high word
|
|
pla ;restore I/O buffer size
|
|
sec ;better clear the buffer
|
|
jsl alloc_fcr ;build a new fcr for file
|
|
bcc success
|
|
ply
|
|
rts ;return with the error
|
|
|
|
success ;
|
|
jsl deref ;convert VP to RP
|
|
stx my_fcr_ptr
|
|
sty my_fcr_ptr+2
|
|
|
|
jsr setup_my_fcr ;build a pointer to local data
|
|
stx pro_fcr_ptr
|
|
sty pro_fcr_ptr+2 ;save pointer to my structure
|
|
|
|
ldy #vcr_open_cnt ;advance the open count please by one
|
|
lda [my_vcr_ptr],y
|
|
inc a
|
|
sta [my_vcr_ptr],y
|
|
|
|
ldy #fcr_status
|
|
lda #$0000 ;zero the status word
|
|
sta [pro_fcr_ptr],y
|
|
|
|
pla ;restore the I/O buffer active bits
|
|
jsr set_fcr_status
|
|
|
|
lda access ;save the user's access
|
|
ldy #fcr_access
|
|
ora #set_global_clean
|
|
ldx resource_num ;does the file contain a resource fork?
|
|
beq @store_access
|
|
ora #set_access_res ;set the access resource bit please
|
|
@store_access
|
|
sta [my_fcr_ptr],y
|
|
|
|
ldy #fcr_vol_id
|
|
lda [my_vcr_ptr] ;get the volume ID from the VCR
|
|
sta [my_fcr_ptr],y ;and save it in the new FCR
|
|
|
|
ldy #fcr_fst_id
|
|
lda #pro_id ;save the ownership id word
|
|
sta [my_fcr_ptr],y
|
|
|
|
;==========================================================================
|
|
;Now start saving data into my local data segment
|
|
;==========================================================================
|
|
|
|
lda resource_num ;save the resource number of the file
|
|
sta [pro_fcr_ptr]
|
|
|
|
ldy #fcr_entry_type
|
|
lda entry_sto_type ;save the storage type from dir entry
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldy #fcr_storage
|
|
lda storage_type ;save the storage type
|
|
sta [pro_fcr_ptr],y
|
|
|
|
cmp #volume_header ;if file is a volume then calc EOF
|
|
bne no_adjust2
|
|
|
|
jsr vol_file_size ;calculate the EOF for the root vol
|
|
|
|
no_adjust2 ;
|
|
|
|
ldy #fcr_curr_eof ;save the current EOF
|
|
lda one_entry+eof_index
|
|
sta [pro_fcr_ptr],y
|
|
iny
|
|
lda one_entry+eof_index+1
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldy #fcr_blks_used ;save the number of blocks used
|
|
lda one_entry+blks_used_index
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldy #fcr_parent
|
|
lda parent_blk ;save address of parent block number
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldy #fcr_entry_offs
|
|
lda entry_offset ;save offset to entry within parent blk
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldy #fcr_file_type ;move the directory entry into the FCR
|
|
|
|
entry_loop lda one_entry-fcr_file_type+$10,y
|
|
sta [pro_fcr_ptr],y
|
|
iny
|
|
cpy #fcr_header_ptr+1
|
|
bne entry_loop
|
|
|
|
jsr setup_io_ptrs ;build pointers to data structures
|
|
jsr setup_io_buf
|
|
bcc no_prob
|
|
pha
|
|
jsr remove_fcr ;remove this puppy
|
|
pla
|
|
sec
|
|
no_prob ;
|
|
rts
|
|
ENDP
|
|
;======================================================================
|
|
;check_dup: This routine will check for duplicate file entries.
|
|
; To do this I look to see if the starting block of
|
|
; the FCR is equal to the starting block of the file I am
|
|
; trying to open.
|
|
;
|
|
;Created: may 04, 1987
|
|
;Modified: may 06, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;
|
|
;Enter: from open call
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; one_entry (39 byte entry from disk)
|
|
; access (requested access for open)
|
|
;
|
|
;Output: A = error code if carry set. (duplicate error)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
; find_fcr (system routine to find a fcr
|
|
; my_fcr_ptr
|
|
; pro_fcr_ptr
|
|
; access
|
|
; resource_num
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT check_dup
|
|
check_dup PROC
|
|
|
|
stz fcr_wanted ;reset for get_next_fcr
|
|
|
|
lda one_entry+key_blk_index
|
|
sta key_block
|
|
|
|
next_loop ;
|
|
jsr get_next_fcr
|
|
bcs done
|
|
|
|
ldy #fcr_vol_id
|
|
lda [my_fcr_ptr],y ;get the Volume ID so we can make sure the file is on
|
|
cmp [my_vcr_ptr] ;the same volume.
|
|
bne next_loop ;File is on another volume
|
|
|
|
ldy #fcr_file_id ;index to key block of this file
|
|
lda [pro_fcr_ptr],y
|
|
cmp key_block ;is this the same block?
|
|
bne next_loop ;no problem with this file
|
|
|
|
;==========================================================================
|
|
;Now we need to see if the resource numbers are different.
|
|
;==========================================================================
|
|
|
|
lda [pro_fcr_ptr]
|
|
cmp resource_num
|
|
bne next_loop ;not the same resource
|
|
|
|
ldy #fcr_vol_id ;see if the file is on another volume
|
|
lda [my_fcr_ptr],y
|
|
cmp [my_vcr_ptr]
|
|
bne next_loop
|
|
|
|
ldy #fcr_access ;see if this file was open for writing
|
|
lda [my_fcr_ptr],y
|
|
and #ClrAllButAccess
|
|
cmp #write_access
|
|
bcs file_is_busy ;sorry this file is busy right now
|
|
|
|
;==========================================================================
|
|
;If we get here we know that the current file is the same and that it is
|
|
;open for read only. Therefore we must check the requested access of the
|
|
;file that we are currently opening. If the user wants read only access
|
|
;then there is no problem.
|
|
;==========================================================================
|
|
|
|
lda users_access ;did the user want "open_as_permitted"
|
|
beq open_as_perm ;user request open as permitted.
|
|
cmp #write_access
|
|
bcs file_is_busy
|
|
rts ;return carry clear indicating no dup
|
|
|
|
file_is_busy
|
|
lda #file_busy
|
|
sec
|
|
rts ;error out to caller
|
|
|
|
open_as_perm
|
|
; ldy #fcr_disk_acc
|
|
; lda [pro_fcr_ptr],y ;check disk assigned access.
|
|
; and #write_enabled ;is the file write enabled?
|
|
; bne file_is_busy ;yes it is, so die
|
|
|
|
lda #read_access
|
|
sta access ;change the user's access to Read Only.
|
|
|
|
done clc ;indicate no problem
|
|
rts
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;get_next_fcr: This routine will load find the next FCR that belongs
|
|
; to ProDOS.
|
|
;
|
|
;Created: may 23, 1987
|
|
;Modified: may 23, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;
|
|
;Enter: from open call
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; fcr_wanted (counter for FCR, reset by caller!)
|
|
;
|
|
;Output: A = undefiend
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error (end of FCRs)
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; pro_fcr_ptr
|
|
; my_fcr_ptr (points to the found FCR)
|
|
;
|
|
;Uses: All registers
|
|
; system_routines
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT get_next_fcr
|
|
get_next_fcr PROC
|
|
|
|
loop
|
|
lda fcr_wanted
|
|
inc a
|
|
sta fcr_wanted
|
|
jsl get_fcr ;see if this is a fcr
|
|
bcs done
|
|
|
|
jsl deref ;convert VP to RP
|
|
stx my_fcr_Ptr
|
|
sty my_fcr_ptr+2
|
|
|
|
ldy #fcr_fst_id ;see if this one is mine
|
|
lda [my_fcr_ptr],y
|
|
cmp #pro_id
|
|
bne loop ;not mine so who cares
|
|
|
|
jsr setup_my_fcr
|
|
stx pro_fcr_ptr
|
|
sty pro_fcr_ptr+2
|
|
|
|
clc
|
|
done
|
|
rts
|
|
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;move_dir_entry This routine will move the 39 byte entry pointed to by
|
|
; drvr_buf_ptr to one_entry. If the entry pointed to
|
|
; is a volume header then I will simulate a normal 39
|
|
; byte entry.
|
|
;
|
|
;Created: may 05, 1987
|
|
;Modified: may 05, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;
|
|
;Enter: from open call
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; drvr_buf_ptr (points to the 39 byte entry from disk)
|
|
; storage_type (original storage type of entry)
|
|
;
|
|
;Output: A = undefiend
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; one_entry (contains a 39 byte entry)
|
|
;
|
|
;Uses: All registers
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
; drvr_buf_ptr
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT move_dir_entry
|
|
move_dir_entry PROC
|
|
|
|
lda [drvr_buf_ptr] ;get the storage type
|
|
and #$00F0
|
|
sta storage_type
|
|
cmp #volume_header
|
|
beq simulate_entry ;simulate a reg. file entry
|
|
|
|
EXPORT move_vol_entry
|
|
move_vol_entry ;
|
|
|
|
start_move ldy #entry_length-1 ;just move a normal file entry
|
|
move_loop lda [drvr_buf_ptr],y
|
|
sta one_entry,y
|
|
dey
|
|
dey
|
|
bpl move_loop
|
|
lda alloc_entry
|
|
and #$0F00 ;clear all but the storage type
|
|
xba
|
|
sta alloc_entry ;convert length byte to word
|
|
rts
|
|
|
|
simulate_entry ;
|
|
jsr start_move ;move the basic entry
|
|
|
|
;==========================================================================
|
|
;below we setup the volume directory as a subdirectory. To do this
|
|
;we setup the following fields:
|
|
;==========================================================================
|
|
; File_type := $0F (directory File)
|
|
; Key_pointer := vol_dir_start (starting block for directory = 2)
|
|
; Blocks_used := (Calculated from disk)
|
|
; EOF := (Calculated from disk)
|
|
; AUX Type := $0000 (zero the aux field)
|
|
; Last_mod := $00000000 (don't have this info)
|
|
; Header Ptr := $0002 (Starting block of owning directory)
|
|
;==========================================================================
|
|
|
|
;==========================================================================
|
|
;Now setup the file type as a subdirectory entry
|
|
;==========================================================================
|
|
|
|
lda #dir_file_type
|
|
sta one_entry+file_type_index
|
|
|
|
;==========================================================================
|
|
;Now setup Key block pointer and header_ptr
|
|
;==========================================================================
|
|
|
|
lda #vol_dir_start
|
|
sta one_entry+key_blk_index
|
|
sta one_entry+header_ptr_index
|
|
|
|
;==========================================================================
|
|
;Zero the aux type and mod_date
|
|
;==========================================================================
|
|
|
|
stz one_entry+aux_type_index
|
|
stz one_entry+last_mod_index
|
|
stz one_entry+2+last_mod_index
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;setup_io_buf This routine will fill the I/O buffer with the correct
|
|
; data
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; one_entry (39 byte entry from disk)
|
|
; FCR (setup)
|
|
;
|
|
;Output: A = error code if carry set.
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
;==========================================================================
|
|
|
|
EXPORT setup_io_buf
|
|
setup_io_buf PROC
|
|
|
|
ldy #fcr_key_blk ;key block of the resource
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num
|
|
ldy #fcr_file_id
|
|
sta [pro_fcr_ptr],y ;save file id for duplicate checks
|
|
|
|
ldy #fcr_entry_type
|
|
lda [pro_fcr_ptr],y ;see if this is a resource file
|
|
cmp #resource_type
|
|
bne not_resource ;must be a standard file
|
|
|
|
jsr find_resource
|
|
bcc standard_file
|
|
|
|
nuke_it ;
|
|
rts
|
|
|
|
not_resource ;
|
|
cmp #subdir_type
|
|
bcc standard_file
|
|
|
|
lda #in_cache
|
|
sta drvr_cache
|
|
|
|
ldy #fcr_key_blk ;key block of the file
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num
|
|
|
|
ldx data_ptr
|
|
ldy data_ptr+2
|
|
jsr load_io_blk ;store one block into the I/O buffer
|
|
bcs nuke_it
|
|
|
|
ldy #data_blk_num
|
|
lda drvr_blk_num
|
|
sta [pro_fcr_ptr],y
|
|
clc
|
|
rts
|
|
|
|
standard_file ;
|
|
ldy #fcr_key_blk
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num
|
|
|
|
lda storage_type
|
|
cmp #tree_type
|
|
bne chk_sapling
|
|
|
|
ldx master_ptr
|
|
ldy master_ptr+2
|
|
jsr load_io_blk
|
|
bcc master_loaded
|
|
rts
|
|
|
|
master_loaded ;
|
|
ldy #master_blk_num
|
|
lda drvr_blk_num ;save the block num of the master block
|
|
sta [pro_fcr_ptr],y
|
|
jsr get_first_index ;load the address of the first index blk
|
|
sta drvr_blk_num
|
|
bra load_index
|
|
|
|
chk_sapling ;
|
|
cmp #sapling_type
|
|
bne do_seedling
|
|
|
|
load_index ;
|
|
ldx index_ptr
|
|
ldy index_ptr+2
|
|
jsr load_io_blk ;load in the index block
|
|
bcc cont_index
|
|
rts
|
|
|
|
cont_index ;
|
|
ldy #index_blk_num
|
|
lda drvr_blk_num ;save the block num of the index block
|
|
sta [pro_fcr_ptr],y
|
|
jsr get_first_index ;load the address of the first index blk
|
|
sta drvr_blk_num
|
|
|
|
do_seedling ;
|
|
ldx data_ptr
|
|
ldy data_ptr+2
|
|
jsr load_io_blk ;load in the seedling block
|
|
bcc cont_data
|
|
rts
|
|
|
|
cont_data ;
|
|
ldy #data_blk_num
|
|
lda drvr_blk_num
|
|
sta [pro_fcr_ptr],y
|
|
clc
|
|
rts ;return to user in happy camper mode
|
|
|
|
;==========================================================================
|
|
;this routine will read into the buffer pointed to by X and Y the block
|
|
;number countained in drvr_blk_num.
|
|
;==========================================================================
|
|
|
|
load_io_blk
|
|
stx drvr_buf_ptr
|
|
sty drvr_buf_ptr+2 ;save the pointer to the buffer
|
|
jsr read_with_cache
|
|
rts
|
|
|
|
;==========================================================================
|
|
;This routine will load into the accumulator the first block address from
|
|
;an index block.
|
|
;==========================================================================
|
|
get_first_index
|
|
longa off
|
|
sep #$20
|
|
ldy #blk_size/2
|
|
lda [drvr_buf_ptr],y
|
|
xba
|
|
lda [drvr_buf_ptr]
|
|
longa on
|
|
rep #$20
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
;==========================================================================
|
|
;set_fcr_status This routine will set bits in the FCR pointed to by
|
|
; 'pro_fcr_ptr'
|
|
;
|
|
;Input: A = ORA Mask
|
|
;
|
|
;OutPut: Operation complete
|
|
;
|
|
;Uses: A and Y registers
|
|
;==========================================================================
|
|
|
|
EXPORT set_fcr_status
|
|
set_fcr_status PROC
|
|
|
|
ldy #fcr_status
|
|
ora [pro_fcr_ptr],y
|
|
sta [pro_fcr_ptr],y
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;find_resource: This routine will read in the key block of a resource file
|
|
; and locate the resource fork. If the resource is available
|
|
; then this routine will replace the following fields in the fcr:
|
|
;
|
|
; 1) fst_key_blk := Key block of the resource
|
|
; 2) blocks used := blocks used by the resource
|
|
; 3) fst_eof := eof of resource
|
|
; 4) storage_type := storage type of the resource
|
|
;
|
|
;Input: drvr_blk_num = key block of resource file
|
|
;
|
|
;Output: Carry Set if error otherwise clear
|
|
;
|
|
;==========================================================================
|
|
|
|
EXPORT find_resource
|
|
find_resource PROC
|
|
|
|
;==========================================================================
|
|
;Setup the system buffer as our temp work area
|
|
;==========================================================================
|
|
|
|
lda gbuf_addr ;address of systems work buffer
|
|
sta drvr_buf_ptr
|
|
lda gbuf_addr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
lda #in_cache ;go ahead and store this block in cache
|
|
sta drvr_cache
|
|
jsr device_call
|
|
jsr set_user_cache ;restore user's cache value
|
|
bcc got_res_header
|
|
rts ;return error to caller
|
|
|
|
got_res_header ;
|
|
|
|
;==========================================================================
|
|
;open the correct fork.
|
|
;==========================================================================
|
|
|
|
lda resource_num ;calculate the resource
|
|
xba ;convert $0000 or $0001 into
|
|
tay ;$0000 or $0100
|
|
|
|
;==========================================================================
|
|
;Now we load the storage type, key block and eof
|
|
;==========================================================================
|
|
|
|
lda [drvr_buf_ptr],y
|
|
and #$0003 ;clear resource bits
|
|
beq bad_resource
|
|
cmp #(tree_type/$10)+1
|
|
bcc get_key_blk ;storage type ok
|
|
|
|
bad_resource ;
|
|
lda #res_not_found ;the file is damaged
|
|
sec
|
|
rts
|
|
|
|
get_key_blk ;
|
|
asl a ;convert $1,$2,$3 to $10,$20,$30
|
|
asl a
|
|
asl a
|
|
asl a
|
|
sta storage_type
|
|
|
|
iny ;now get the key block
|
|
lda [drvr_buf_ptr],y
|
|
beq bad_resource
|
|
sta files_key_block
|
|
iny
|
|
iny
|
|
|
|
;==========================================================================
|
|
;Now get the total blocks used field
|
|
;==========================================================================
|
|
|
|
lda [drvr_buf_ptr],y
|
|
sta one_entry+blks_used_index
|
|
tyx
|
|
ldy #fcr_blks_used
|
|
sta [pro_fcr_ptr],y
|
|
ldy #fcr_blks_alloc
|
|
sta [pro_fcr_ptr],y
|
|
txy
|
|
iny
|
|
iny
|
|
|
|
;==========================================================================
|
|
;Now load the new EOF for the resource. (EOF = three bytes)
|
|
;==========================================================================
|
|
|
|
lda [drvr_buf_ptr],y
|
|
sta one_entry+eof_index
|
|
tax ;low order 16 bits of resource
|
|
iny
|
|
lda [drvr_buf_ptr],y
|
|
sta one_entry+eof_index+1
|
|
|
|
;==========================================================================
|
|
;Now save the new EOF for this resource.
|
|
;==========================================================================
|
|
|
|
ldy #fcr_eof+1
|
|
sta [pro_fcr_ptr],y
|
|
ldy #fcr_curr_eof+1
|
|
|
|
sta [pro_fcr_ptr],y
|
|
txa ;store low order 16 bits
|
|
ldy #fcr_eof
|
|
sta [pro_fcr_ptr],y
|
|
ldy #fcr_curr_eof
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldy #fcr_storage
|
|
lda storage_type
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldy #fcr_key_blk
|
|
lda files_key_block
|
|
sta [pro_fcr_ptr],y ;save the key block as well
|
|
|
|
clc
|
|
rts ;exit all happy now!!!
|
|
|
|
ENDP
|
|
|
|
;======================================================================
|
|
;check_vcr_first: This routine trys to find a vcr from the device number
|
|
; in 'A'. If a vcr is found the no error is reported.
|
|
; otherwise the error is returned.
|
|
;
|
|
;Created: may 08, 1987
|
|
;Modified: may 08, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;
|
|
;Enter: from open call
|
|
;
|
|
;Input: A = device number to find
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; dev_num ;device number we are looking for
|
|
;
|
|
;Output: A = error code if carry set.
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; find_vcr
|
|
; math_temp
|
|
; my_vcr_ptr
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT check_vcr_first
|
|
check_vcr_first PROC
|
|
|
|
stz math_temp
|
|
search_loop ;
|
|
lda math_temp
|
|
inc a
|
|
sta math_temp
|
|
jsl get_vcr
|
|
bcc good
|
|
rts
|
|
|
|
;==========================================================================
|
|
;If we find a vcr then make sure that I own it.
|
|
;==========================================================================
|
|
|
|
good ;
|
|
jsl deref
|
|
stx my_vcr_ptr
|
|
sty my_vcr_ptr+2
|
|
ldy #vcr_fst_id
|
|
lda [my_vcr_ptr],y
|
|
cmp #pro_id
|
|
bne search_loop
|
|
|
|
ldy #vcr_dev ;is this the correct device
|
|
lda [my_vcr_ptr],y
|
|
cmp dev_num
|
|
bne search_loop
|
|
|
|
ldy #vcr_status
|
|
lda [my_vcr_ptr],y
|
|
and #vcr_swapped
|
|
bne do_mount
|
|
clc ;this is it.
|
|
rts
|
|
|
|
do_mount ;
|
|
jsr mount_volume
|
|
rts
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;Read: This file contains code used to read data from a file.
|
|
; The types of files supported are:
|
|
;
|
|
; 1) seedling
|
|
; 2) sapling
|
|
; 3) tree
|
|
; 4) directory
|
|
;
|
|
;Created: May 16, 1987
|
|
;Modified: Apr 16, 1988
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
; and lots of other stuff to.
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Reference Number (2 Bytes)
|
|
; Pointer to Data Buffer (4 Bytes)
|
|
; Request Count (4 Bytes)
|
|
; Transfer Count (4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Reference Number (2 Bytes)
|
|
; Pointer to Data Buffer (4 Bytes)
|
|
; Request Count (4 Bytes)
|
|
; Transfer Count (4 Bytes)
|
|
; Cache Priority (2 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT read
|
|
read PROC
|
|
|
|
lda #drvr_read ;setup for device read
|
|
sta drvr_call_num
|
|
|
|
;==========================================================================
|
|
;sets up parameters from GS/OS call block, and verifies class and max pcnt
|
|
;
|
|
;setup params returns the class in the Accumulator. It also does the
|
|
;load as the last instruction before the 'RTS'
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
jsr read_write_setup
|
|
|
|
;==========================================================================
|
|
;Go and get the newline length from the FCR and save it on zero page.
|
|
;==========================================================================
|
|
stz newline_len ;disable newline mode please
|
|
|
|
;==========================================================================
|
|
;We need to get the mask as well as the newline list pointer
|
|
;==========================================================================
|
|
ldy #fcr_mask
|
|
lda [my_fcr_ptr],y
|
|
sta newline_mask
|
|
beq no_newline
|
|
|
|
ldy #fcr_newline_len
|
|
lda [my_fcr_ptr],y
|
|
sta newline_len
|
|
beq no_newline ;ok I like this read
|
|
|
|
;==========================================================================
|
|
;Since newline is enabled we must dereference the newline VP and save it
|
|
;==========================================================================
|
|
|
|
ldy #fcr_newline
|
|
lda [my_fcr_ptr],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [my_fcr_ptr],y
|
|
tay
|
|
jsl deref
|
|
stx newline_ptr
|
|
sty newline_ptr+2
|
|
|
|
;==========================================================================
|
|
;When we finally get here we are thru with setting up the newline list
|
|
;==========================================================================
|
|
|
|
no_newline ;
|
|
ldy #vcr_dev
|
|
lda [my_vcr_ptr],y
|
|
sta drvr_dev_num
|
|
|
|
;==========================================================================
|
|
;Just to be complete I guess I should check if the file is read enabled.
|
|
;==========================================================================
|
|
|
|
ldy #fcr_access ;check the user's access privs.
|
|
lda [my_fcr_ptr],y
|
|
and #ClrAllButAccess
|
|
cmp #write_access ;does the file have write only access?
|
|
bne i_can_read ;read is allowed
|
|
|
|
lda #invalid_access
|
|
error_out ;
|
|
sec
|
|
jmp main_exit
|
|
|
|
|
|
I_can_read ;
|
|
|
|
;==========================================================================
|
|
;Now we need to move some variables from the FCR to zero page.
|
|
;We do this just to make it easy to get to the variables.
|
|
;
|
|
;First lets move the current file marker and EOF to direct page
|
|
;==========================================================================
|
|
|
|
jsr setup_curr_mark
|
|
jsr setup_curr_eof
|
|
|
|
;==========================================================================
|
|
;Now lets see if we are at the end of the file.
|
|
;IF curr_mark = EOF THEN return EOF error
|
|
;==========================================================================
|
|
|
|
lda curr_mark+2
|
|
cmp curr_eof+2
|
|
bcc not_eof
|
|
lda curr_mark
|
|
cmp curr_eof
|
|
bne not_eof
|
|
|
|
lda #end_of_file ;sorry no more bytes to read
|
|
bra error_out
|
|
|
|
not_eof ;
|
|
|
|
;==========================================================================
|
|
;OK go and get the storage type for the file
|
|
;We use this field to determine how to read the file.
|
|
;==========================================================================
|
|
|
|
ldy #fcr_storage
|
|
lda [pro_fcr_ptr],y
|
|
sta storage_type
|
|
|
|
jsr chk_swapped ;mount the volume if needed
|
|
bcc disk_online
|
|
jmp main_exit
|
|
disk_online ;
|
|
|
|
;==========================================================================
|
|
;when we get here we have found the lost volume. So we must reset our
|
|
;flags and change our device number, in both the VCR and FCR
|
|
;==========================================================================
|
|
|
|
lda drvr_dev_num ;new device number
|
|
ldy #vcr_dev
|
|
sta [my_vcr_ptr],y ;update VCR
|
|
|
|
ldy #vcr_status
|
|
lda [my_vcr_ptr],y
|
|
and #vcr_swapped_in ;set 'disk in' flag
|
|
sta [my_vcr_ptr],y
|
|
|
|
;==========================================================================
|
|
;Now the disk is ready to be talked to
|
|
;==========================================================================
|
|
|
|
disk_in ;
|
|
|
|
;==========================================================================
|
|
;Now we need to compare req_cnt to EOF.
|
|
;
|
|
;IF (req_count + curr_mark) > EOF THEN
|
|
; req_cnt := (EOF-curr_mark)
|
|
;
|
|
;NOTE: carry must be clear when we get here.
|
|
;==========================================================================
|
|
|
|
lda curr_mark
|
|
adc user_req_cnt
|
|
sta math_temp
|
|
lda curr_mark+2
|
|
adc user_req_cnt+2
|
|
|
|
cmp curr_eof+2
|
|
bcc not_greater ;no problem with request count
|
|
bne too_large
|
|
lda math_temp
|
|
cmp curr_eof ;check lower 16 bits
|
|
bcc not_greater
|
|
beq not_greater
|
|
|
|
too_large ;
|
|
|
|
;==========================================================================
|
|
;If the request is too large then we need to adjust the request count.
|
|
;==========================================================================
|
|
|
|
sec
|
|
lda curr_eof
|
|
sbc curr_mark
|
|
sta user_req_cnt
|
|
lda curr_eof+2
|
|
sbc curr_mark+2
|
|
sta user_req_cnt+2
|
|
|
|
not_greater ;
|
|
|
|
;==========================================================================
|
|
;Lets stop here and take a brief look at the current file marker.
|
|
;
|
|
;Diagram: (A) (B) (C)
|
|
;
|
|
; | | $00 to $7F | $00 to $FF | $000 to $1FF |
|
|
; | | | | |
|
|
; | MUST BE ZERO |<- master ->|<- index ->|<- Byte index ->|
|
|
; |_______________|_____________|_______________|_________________|
|
|
; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
|
; |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
|
|
; | | | | |
|
|
; 3 2 2 4 1 6 0 8 0 0
|
|
;
|
|
; (A) = Index into the master index block:
|
|
; This value goes upto 127. This means that the total
|
|
; number of index blocks that a file can contain is
|
|
; 127.
|
|
;
|
|
; (B) = Index into the index block:
|
|
; This value goes upto 255. This means that there
|
|
; can be upto 255 data blocks per index block.
|
|
;
|
|
; (C) = index into the data block:
|
|
; This value goes upto 512. This means that there
|
|
; can be upto 512 bytes of data in the data block.
|
|
;
|
|
;==========================================================================
|
|
|
|
|
|
;==========================================================================
|
|
;see if newline is enabled. If it is not then call the fast routines.
|
|
;otherwise fall into snell mode.
|
|
;==========================================================================
|
|
|
|
lda newline_len
|
|
beq fast_read ;runs like a bat out of hell!
|
|
dec a ;see if this is a single char newline
|
|
bne fast_read
|
|
lda [newline_ptr]
|
|
and #$00FF ;clear garbage byte
|
|
sta newline_char
|
|
|
|
EXPORT fast_read
|
|
fast_read ;
|
|
|
|
;==========================================================================
|
|
;If we get here we know that newline is disabled so we do not have to check
|
|
;each character that we read. This means that multiple blocks can be moved
|
|
;into the user's buffer directly without having to go into the I/O buffer.
|
|
;Note however that the last block is moved into the I/O buffer.
|
|
;
|
|
;before we can start sending multiply blocks we must empty the current
|
|
;data block that is in our buffer. If there are enough bytes to satisfy
|
|
;the read request we just send the bytes and exit.
|
|
;==========================================================================
|
|
|
|
single_block ;
|
|
|
|
jsr send_partial
|
|
bcc fast_loop
|
|
clc
|
|
brl end_read_write ;all done with read.
|
|
|
|
;==========================================================================
|
|
;First lets calculate how many bytes are left in this block.
|
|
;==========================================================================
|
|
|
|
fast_loop ;
|
|
lda user_req_cnt+2
|
|
bne do_seq_blks
|
|
lda user_req_cnt
|
|
cmp #blk_size+1
|
|
bcs do_seq_blks
|
|
|
|
jmp send_last ;we have less then 512 bytes left
|
|
|
|
do_seq_blks ;
|
|
|
|
;==========================================================================
|
|
;We know that the user still has more then 512 bytes to go before the read
|
|
;request is satisfied. So lets go and see if there are any sequential
|
|
;blocks that we can read. If there are no sequential blocks then we must
|
|
;get the block address our selves and issue a read of one block. This
|
|
;of course makes mister happy face very sad since he will have to double
|
|
;buffer.
|
|
;==========================================================================
|
|
lda storage_type
|
|
cmp #subdir_type
|
|
bcs single_block
|
|
|
|
jsr num_seq_blks ;see if there are any sequential blks
|
|
beq single_block
|
|
|
|
seq_avail ;
|
|
|
|
;==========================================================================
|
|
;when we get here we know that there are some sequential blocks that can
|
|
;be read. But we must see if the number of sequential blocks is less then
|
|
;the number of blocks wanted.
|
|
;==========================================================================
|
|
|
|
stx drvr_blk_num ;save block number for read
|
|
inc a
|
|
sta math_temp ;number of sequential blocks avail.
|
|
|
|
stz drvr_req_cnt
|
|
stz drvr_req_cnt+2
|
|
stz drvr_blk_num+2
|
|
|
|
lda user_req_cnt+1 ;first convert bytes wanted to blocks
|
|
lsr a
|
|
cmp math_temp
|
|
bcc use_users_size
|
|
lda math_temp ;use ALL sequential blocks.
|
|
|
|
use_users_size ;
|
|
|
|
asl a ;convert block count to bytes
|
|
sta drvr_req_cnt+1
|
|
|
|
;==========================================================================
|
|
;Now setup the buffer pointer to point to the user's buffer.
|
|
;==========================================================================
|
|
|
|
lda users_buf_ptr
|
|
sta drvr_buf_ptr
|
|
lda users_buf_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
jsr read_with_mount
|
|
bcc cont001 ;good.
|
|
jmp end_read_write
|
|
|
|
cont001 ;
|
|
jsr rw_adjust ;adjust the following:
|
|
; ;(1) user_buf_ptr
|
|
; ;(2) tran_cnt
|
|
; ;(3) curr_mark
|
|
; ;(4) user_req_cnt
|
|
|
|
jmp fast_loop
|
|
|
|
;==========================================================================
|
|
;
|
|
;==========================================================================
|
|
|
|
send_last ;
|
|
jsr send_partial
|
|
clc
|
|
|
|
;==========================================================================
|
|
;===== END of READ call. We save the processor status and error code =====
|
|
;===== We then send back the number of bytes that =====
|
|
;===== were read successfully. Then we restore any=====
|
|
;===== error condition and exit thru sys_exit. =====
|
|
;==========================================================================
|
|
|
|
EXPORT end_read_write
|
|
end_read_write ; ;common exit for read and write
|
|
php
|
|
pha
|
|
|
|
ldy #pblk_12_tran
|
|
lda tran_cnt
|
|
sta [my_pblk_ptr],y
|
|
iny
|
|
iny
|
|
lda tran_cnt+2
|
|
sta [my_pblk_ptr],y
|
|
|
|
;==========================================================================
|
|
;Save the current file marker after the read call completes.
|
|
;==========================================================================
|
|
jsr save_curr_mark
|
|
|
|
pla
|
|
plp
|
|
jmp main_exit
|
|
|
|
;==========================================================================
|
|
;bump_mark This routine will adjust the following fields:
|
|
;
|
|
; 1) users_buf_ptr := users_buf_ptr + bytes_sent
|
|
; 2) curr_mark := curr_mark + bytes_sent
|
|
; 3) user_req_cnt := user_req_cnt - bytes_sent
|
|
; 4) tran_cnt := tran_cnt+bytes_sent
|
|
;input:
|
|
; A = number of bytes to bump fields by.
|
|
;
|
|
;Uses: math_temp
|
|
;==========================================================================
|
|
|
|
EXPORT bump_mark
|
|
bump_mark ;
|
|
sta math_temp
|
|
clc
|
|
lda users_buf_ptr
|
|
adc math_temp
|
|
sta users_buf_ptr
|
|
|
|
bcc do_mark
|
|
inc users_buf_ptr+2
|
|
clc
|
|
do_mark ;
|
|
|
|
;==========================================================================
|
|
;IMPORTANT NOTES:
|
|
;
|
|
; users_buf_ptr is always =< $00FFFFFF
|
|
;
|
|
;WARNING! --> CARRY must be clear when we get here!
|
|
;==========================================================================
|
|
|
|
lda curr_mark
|
|
adc math_temp
|
|
sta curr_mark
|
|
bcc do_tran
|
|
inc curr_mark+2
|
|
clc
|
|
do_tran ;
|
|
|
|
;==========================================================================
|
|
;IMPORTANT NOTES:
|
|
;
|
|
; curr_mark+math_temp is always less the $00FFFFFF
|
|
;
|
|
;WARNING! --> CARRY must be clear when we get here!
|
|
;==========================================================================
|
|
|
|
lda tran_cnt
|
|
adc math_temp
|
|
sta tran_cnt
|
|
bcc do_req_cnt
|
|
inc tran_cnt+2
|
|
|
|
do_req_cnt ;
|
|
sec
|
|
lda user_req_cnt
|
|
sbc math_temp
|
|
sta user_req_cnt
|
|
bcs end_bump
|
|
dec user_req_cnt+2
|
|
|
|
end_bump rts
|
|
|
|
|
|
;==========================================================================
|
|
;Set_users_buf This routine moves the users buffer pointer into
|
|
; drvr_buf_ptr. This allows block read from a device driver
|
|
; to go directly to the users buffer.
|
|
;==========================================================================
|
|
|
|
set_users_buf ;
|
|
lda users_buf_ptr ;bypass my I/O buffer
|
|
sta drvr_buf_ptr
|
|
lda users_buf_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;send_partial This routine will send data from the current file marker to
|
|
; the end of the data buffer.
|
|
;
|
|
;Input: A = undefined
|
|
; X = indefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; curr_mark (must be correct)
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = data transfer complete
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; move_block
|
|
;==========================================================================
|
|
|
|
EXPORT send_partial
|
|
send_partial PROC
|
|
|
|
;==========================================================================
|
|
;first make sure the I/O buffer is filled to the brim.
|
|
;==========================================================================
|
|
|
|
jsr fill_io_buf
|
|
bcc filled_up ;buffer is now ok
|
|
jmp end_read_write
|
|
|
|
;==========================================================================
|
|
;lets see how many bytes are left in the currently loaded data block.
|
|
;==========================================================================
|
|
|
|
filled_up ;
|
|
lda curr_mark
|
|
and #$01FF
|
|
sta math_temp
|
|
sec
|
|
lda #blk_size ;Bytes_left := buf_size-curr_position
|
|
sbc math_temp
|
|
|
|
sta math_temp ;number of bytes left in buffer.
|
|
|
|
;==========================================================================
|
|
;now lets calculate how many bytes we need to send to the user
|
|
;==========================================================================
|
|
|
|
ldx user_req_cnt+2
|
|
bne send_all_bytes ;he wants as many as I can give
|
|
cmp user_req_cnt
|
|
beq send_all_bytes
|
|
bcc send_all_bytes
|
|
|
|
lda user_req_cnt ;the user wants less then I have
|
|
|
|
send_all_bytes ;
|
|
sta math_temp
|
|
tay
|
|
|
|
;==========================================================================
|
|
;If newline is enabled then we have to do processing on each character
|
|
;so we avoid the block move routine.
|
|
;==========================================================================
|
|
|
|
lda newline_len
|
|
bne check_newline
|
|
|
|
;==========================================================================
|
|
;If we get here then newline is disabled so use the block move instruction
|
|
;==========================================================================
|
|
|
|
clc
|
|
lda curr_mark ;adjust the starting position
|
|
and #$01FF
|
|
adc data_ptr
|
|
tax ;save low address of buf pointer
|
|
lda #$0000
|
|
adc data_ptr+2
|
|
|
|
cpy #min_send_cnt ;minimum bytes needed to use blk move
|
|
bcc send_small
|
|
|
|
pha ;push high word of buffer pointer
|
|
phx ;push low word of buffer pointer
|
|
|
|
pei users_buf_ptr+2 ;destination address
|
|
pei users_buf_ptr
|
|
pea $0000 ;high word of count
|
|
phy ;number of bytes to send
|
|
pea move_sinc_dinc
|
|
jsl move_info
|
|
bra end_partial
|
|
|
|
;==========================================================================
|
|
;This routine will transfer a request count of less than $20 characters to
|
|
;the user's buffer. We do this to speed things up.
|
|
;==========================================================================
|
|
|
|
send_small ;
|
|
stx temp_ptr
|
|
sta temp_ptr+2 ;pointer to the user's buffer
|
|
dey
|
|
tya
|
|
bmi end_partial ;zero bytes to move?
|
|
cmp #$0002 ;are we moving less then two bytes?
|
|
bcc send_8_bit
|
|
dec a ;second decrement for word check
|
|
ror a ;is it an even transfer?
|
|
bcs send_8_bit
|
|
dey
|
|
loop_16 ;
|
|
lda [temp_ptr],y
|
|
sta [users_buf_ptr],y
|
|
dey
|
|
dey
|
|
bpl loop_16
|
|
bra end_partial
|
|
|
|
send_8_bit ;
|
|
sep #$20 ;8 bit accum
|
|
loop_8 ;
|
|
lda [temp_ptr],y
|
|
sta [users_buf_ptr],y
|
|
dey
|
|
bpl loop_8
|
|
rep #$20
|
|
|
|
;==========================================================================
|
|
;Now that we have send the data adjust the pointers etc.
|
|
;==========================================================================
|
|
|
|
end_partial
|
|
lda math_temp
|
|
jsr bump_mark
|
|
lda user_req_cnt
|
|
ora user_req_cnt+2
|
|
beq all_done ;request count satisfied
|
|
|
|
ldy #fcr_status ;we are going to read another block so make sure
|
|
lda [pro_fcr_ptr],y ;the I/O buffer is clean
|
|
and #file_dirty
|
|
beq @not_dirty
|
|
jsr flush_io_buffer ;write the dirty blocks to disk
|
|
bcc @not_dirty
|
|
jmp main_exit
|
|
|
|
@not_dirty
|
|
clc
|
|
rts
|
|
|
|
all_done
|
|
sec
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Below is the code used to handle the newline checking. For this code we
|
|
;set the accumulator into 8 bit mode so we do not overflow the user's
|
|
;buffer.
|
|
;==========================================================================
|
|
|
|
check_newline ;
|
|
tax ;save newline length for a second
|
|
|
|
lda curr_mark ;isolate block index
|
|
and #$01FF
|
|
tay
|
|
|
|
sta entries_checked
|
|
sec
|
|
lda users_buf_ptr
|
|
sbc entries_checked
|
|
sta temp_ptr
|
|
lda users_buf_ptr+2
|
|
sbc #$0000
|
|
sta temp_ptr+2
|
|
|
|
clc
|
|
tya
|
|
adc math_temp ;calculate the last byte address
|
|
sta entries_checked
|
|
|
|
|
|
dex ;see if this is a special case
|
|
bne slow_read
|
|
php ;save the mode please
|
|
longa off
|
|
sep #$20 ;short accumulator
|
|
|
|
fast_newline ;
|
|
lda [data_ptr],y
|
|
sta [temp_ptr],y
|
|
and newline_mask
|
|
cmp newline_char
|
|
beq found_newline
|
|
iny
|
|
cpy entries_checked ;are we done yet
|
|
bne fast_newline
|
|
plp ;be nice and restore last mode please.
|
|
bra end_partial
|
|
|
|
found_newline ;
|
|
plp ;restore last mode please
|
|
longa on
|
|
|
|
;==========================================================================
|
|
;Number of bytes := Ending position minus starting position
|
|
; Y = ending position
|
|
; curr_mark = starting position
|
|
;==========================================================================
|
|
|
|
lda curr_mark
|
|
and #$01FF
|
|
sta math_temp
|
|
sec
|
|
tya
|
|
sbc math_temp
|
|
inc a
|
|
jsr bump_mark ;adjust the pointers etc
|
|
stz user_req_cnt
|
|
stz user_req_cnt+2
|
|
sec
|
|
rts
|
|
|
|
;==========================================================================
|
|
;This routine is called when there is more then one newline character to
|
|
;check. This routine is slower then the above newline read since I have
|
|
;to scan all newline characters against a list
|
|
;==========================================================================
|
|
|
|
slow_read ;
|
|
|
|
;==========================================================================
|
|
;newline_len := newline_len-1 So I can use it as an index into the newline
|
|
;list.
|
|
;==========================================================================
|
|
|
|
*** removed 13-Jul-92 DAL to make multi-character newline mode keep working across blocks
|
|
*** (newline_len was getting decremented farther and farther on each block...ouch!)
|
|
;;; dec newline_len
|
|
*** end 13-Jul-92, part 1 of 2
|
|
|
|
php
|
|
longa off
|
|
sep #$20
|
|
|
|
slow_newline ;
|
|
lda [data_ptr],y
|
|
sta [temp_ptr],y
|
|
and newline_mask
|
|
tyx ;save index first
|
|
ldy newline_len
|
|
*** added 13-Jul-92 DAL, because I took out a dec newline_len a few lines above
|
|
dey
|
|
*** end 13-Jul-92, part 2 of 2
|
|
|
|
next_newline ;
|
|
cmp [newline_ptr],y
|
|
beq found_one
|
|
dey
|
|
bpl next_newline
|
|
|
|
txy ;restore index first
|
|
iny
|
|
cpy entries_checked ;are we done yet
|
|
bne slow_newline
|
|
plp ;be nice and restore last mode please.
|
|
brl end_partial
|
|
|
|
found_one ;
|
|
txy ;restore Index first
|
|
bra found_newline
|
|
|
|
ENDP
|
|
|
|
|
|
;==========================================================================
|
|
;fill_io_buf: This routine will load into the I/O buffer the correct
|
|
; index and data blocks. It will also adjust the FCR data
|
|
;
|
|
; WARNING: curr_mark must not point beyond the current
|
|
; structure of the file, even though that mark may be within
|
|
; the file's EOF. This could happen if a file has a trailing
|
|
; portion which is all sparse from a position <128K to a
|
|
; position >128K. In this case the file is stored as a
|
|
; sapling, not a tree, but owns a sparse area that is
|
|
; logically within the "tree" range. In such a case,curr_mark
|
|
; must never be in that range when entering this routine.
|
|
;
|
|
;Input: A = undefined
|
|
; X = indefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; curr_mark (must be correct)
|
|
; master_ptr (must pointer to master index block)
|
|
; index_ptr (must point to the correct index block)
|
|
; data_ptr
|
|
; pro_fcr_ptr (points to prodos data in FCR)
|
|
;
|
|
;Output: A = error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; drvr_blk_num
|
|
; drvr_call_num
|
|
; drvr_buf_ptr
|
|
; drvr_req_cnt
|
|
; device_dispatcher
|
|
;
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT fill_io_buf
|
|
fill_io_buf PROC
|
|
|
|
stz data_flag ;flag says load data block
|
|
bra fill_up
|
|
|
|
EXPORT load_indexes
|
|
load_indexes ;
|
|
lda #$FFFF ;flag says do not load data block
|
|
sta data_flag
|
|
|
|
fill_up ;
|
|
stz mark_changed
|
|
jsr setup_curr_eof
|
|
|
|
lda curr_mark ;is the mark zero?
|
|
ora curr_mark+2
|
|
beq mark_ok ;yes so don't subtract one
|
|
|
|
lda curr_mark+2
|
|
cmp curr_eof+2 ;see if current mark = eof
|
|
bcc mark_ok
|
|
lda curr_mark
|
|
cmp curr_eof
|
|
bcc mark_ok ;no problem
|
|
|
|
sbc #$0001 ;curr_mark := curr_mark-1
|
|
sta curr_mark
|
|
|
|
lda curr_mark+2
|
|
sbc #$0000
|
|
sta curr_mark+2
|
|
|
|
dec mark_changed
|
|
|
|
mark_ok ;
|
|
jsr standard_req ;read 512 bytes only
|
|
ldy #fcr_storage ;see if this is a subdirectory.
|
|
lda [pro_fcr_ptr],y
|
|
cmp #subdir_type
|
|
bcc standard_file ;File is not a directory
|
|
jsr fill_directory ;fill it up bud!
|
|
jsr restore_mark ;fix it if it was changed!
|
|
rts ;return to caller
|
|
|
|
|
|
standard_file ;
|
|
jsr fill_index ;fill up the index block
|
|
bcc chk_data
|
|
rts ;major error
|
|
|
|
chk_data ;
|
|
bit data_flag ;'-' = fill index block only
|
|
bpl do_data
|
|
jsr restore_mark
|
|
rts
|
|
|
|
do_data ;
|
|
jsr fill_data ;fill the data buffer
|
|
jsr restore_mark
|
|
rts ;exit
|
|
|
|
restore_mark ;
|
|
php ;save error flag
|
|
pha ;save error code
|
|
bit mark_changed
|
|
bpl no_change
|
|
inc curr_mark
|
|
bne no_change
|
|
inc curr_mark+2
|
|
no_change ;
|
|
pla
|
|
plp
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Fill_index: This routine will fill up the index block if it can.
|
|
;
|
|
;Below is pascal type segment which indicates how fill_index works.
|
|
;
|
|
;IF master = defined THEN
|
|
; BEGIN
|
|
; blk_num := get_blk_address(curr_mark) ; {Get block address from index blk}
|
|
; IF blk_num = $0000 THEN
|
|
; sparse_blk(index_buffer) ; {Fill Index buffer with zeros}
|
|
; ELSE
|
|
; IF curr_blk <> blk_to_read THEN
|
|
; read_blk(index_buffer) ; {Load index block from disk}
|
|
; END
|
|
; ELSE {master undefined}
|
|
; IF curr_mark > $20000 THEN
|
|
; BEGIN
|
|
; IF sapling = defined THEN
|
|
; sparse_blk(index_buffer) {fill index block to zeros}
|
|
; ELSE
|
|
; BEGIN
|
|
; sparse_blk(data_buffer) ; {force data block to zeros}
|
|
; data_flag := data_flag-1 {This forces the calling routine
|
|
; to exit without loading the data
|
|
; block, since I have already loaded
|
|
; the blocks with zeros}
|
|
; END
|
|
; END
|
|
;
|
|
; WARNING: curr_mark must not point beyond the current
|
|
; structure of the file, even though that mark may be within
|
|
; the file's EOF. This could happen if a file has a trailing
|
|
; portion which is all sparse from a position <128K to a
|
|
; position >128K. In this case the file is stored as a
|
|
; sapling, not a tree, but owns a sparse area that is
|
|
; logically within the "tree" range. In such a case,curr_mark
|
|
; must never be in that range when entering this routine.
|
|
;
|
|
;==========================================================================
|
|
|
|
fill_index ;
|
|
|
|
ldy #fcr_status ;see if the master index block is
|
|
lda [pro_fcr_ptr],y ;active
|
|
and #master_active
|
|
beq no_master ;the master block is not defined
|
|
|
|
lda curr_mark+2 ;make an index into the index block
|
|
lsr a
|
|
and #$007F
|
|
tay
|
|
ora #$0100 ;build index for upper half of buffer
|
|
tax
|
|
|
|
lda [master_ptr],y
|
|
sta drvr_blk_num
|
|
txy
|
|
lda [master_ptr],y
|
|
sta drvr_blk_num+1 ;save the block number to read
|
|
stz drvr_blk_num+2
|
|
|
|
lda drvr_blk_num ;see if blk_num = $0000
|
|
beq sparse_index
|
|
|
|
ldy #index_blk_num ;see if the block is already loaded
|
|
cmp [pro_fcr_ptr],y
|
|
bne load_index
|
|
clc
|
|
rts ;no problem here
|
|
|
|
;==========================================================================
|
|
;If Y=$0100 then we know that the master index block is not really active
|
|
;If it were active then there would be a real index block. If this is the
|
|
;case then we should load in the index block if there is one available.
|
|
;==========================================================================
|
|
|
|
sparse_index ;
|
|
cpy #$0100 ;If non-first index is sparse then
|
|
bne zero_index ;zero the index block
|
|
|
|
ldy #fcr_storage ;is there an index block to load?
|
|
lda [pro_fcr_ptr],y
|
|
cmp #sapling_type
|
|
bne index_sparse ;just exit no index to load
|
|
|
|
ldy #fcr_key_blk
|
|
lda [pro_fcr_ptr],y
|
|
ldy #index_blk_num ;see if the block is already loaded
|
|
cmp [pro_fcr_ptr],y
|
|
beq index_sparse ;just exit since the block is loaded
|
|
sta drvr_blk_num
|
|
bra load_index
|
|
|
|
zero_index ;
|
|
jsr chk_index_clean ;make sure the current block is not dirty
|
|
bcc @no_problem
|
|
rts
|
|
@no_problem
|
|
ldy #index_blk_num ;see if the index block is sparse
|
|
lda [pro_fcr_ptr],y
|
|
beq index_sparse ;block is already sparse
|
|
|
|
ldx index_ptr
|
|
ldy index_ptr+2
|
|
jsr send_sparse_blk
|
|
|
|
ldy #index_blk_num
|
|
lda #$0000
|
|
sta [pro_fcr_ptr],y ;indicate index block loaded is sparse
|
|
|
|
index_sparse ;
|
|
clc
|
|
rts
|
|
|
|
load_index ;
|
|
jsr chk_index_clean ;make sure the current block is not dirty
|
|
bcc @no_problem
|
|
rts
|
|
@no_problem
|
|
lda index_ptr
|
|
sta drvr_buf_ptr
|
|
lda index_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
jsr read_with_cache ;read in the block please
|
|
bcc index_loaded
|
|
rts
|
|
|
|
index_loaded
|
|
ldy #index_blk_num
|
|
lda drvr_blk_num
|
|
sta [pro_fcr_ptr],y ;update the loaded block number field
|
|
rts
|
|
|
|
;==========================================================================
|
|
;If we get here we know that there is no master index block defined.
|
|
;==========================================================================
|
|
no_master
|
|
lda curr_mark+2 ;see if the mark > $20000
|
|
lsr a
|
|
and #$007F
|
|
bne index_pain
|
|
clc
|
|
rts
|
|
|
|
index_pain ;see if the index block is defined
|
|
stz drvr_blk_num
|
|
jsr chk_index_clean
|
|
bcc @its_clean
|
|
rts ;return the error
|
|
@its_clean
|
|
ldy #fcr_status
|
|
lda [pro_fcr_ptr],y
|
|
and #index_active
|
|
bne sparse_index ;make the index block all zeros
|
|
|
|
sparse_data
|
|
jsr chk_data_clean ;make sure the data block is OK
|
|
bcc @good_data
|
|
rts
|
|
@good_data
|
|
ldy #data_blk_num ;see if the block is already sparse
|
|
lda [pro_fcr_ptr],y
|
|
beq data_sparse ;data block is alreay sparse
|
|
|
|
ldx data_ptr
|
|
ldy data_ptr+2
|
|
|
|
jsr send_sparse_blk ;make the data block sparse
|
|
|
|
ldy #data_blk_num ;see if the block is already sparse
|
|
lda #$0000 ;indicate block is sparse
|
|
sta [pro_fcr_ptr],y
|
|
|
|
data_sparse ;
|
|
dec data_flag ;indicate to the main routine that the
|
|
clc ;data block does not need checking
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Chk_index_clean will determine if the current index block needs to be
|
|
;written to disk before the new block is loaded and will write it out if
|
|
;necessary.
|
|
;==========================================================================
|
|
chk_index_clean
|
|
phy
|
|
ldy #fcr_status ;we are going to read another block so make sure
|
|
lda [pro_fcr_ptr],y ;the I/O buffer is clean
|
|
and #index_dirty
|
|
beq @not_dirty ;easy case.
|
|
|
|
lda drvr_blk_num ;get the block number we want to load
|
|
ldy #index_blk_num ;see if the block is already loaded
|
|
cmp [pro_fcr_ptr],y
|
|
beq @not_dirty ;another easy case.
|
|
|
|
pha ;save the driver block number
|
|
jsr flush_index ;save the data to disk
|
|
plx ;get the drvr_blk_number back please
|
|
stx drvr_blk_num
|
|
ply
|
|
rts ;carry will return any error
|
|
|
|
@not_dirty
|
|
ply
|
|
clc
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Fill_data: This routine will fill up the data block if it can.
|
|
;
|
|
;Below is pascal type segment which indicates how Fill_data works.
|
|
;
|
|
;IF index = defined THEN
|
|
; BEGIN
|
|
; blk_num := get_blk_address(curr_mark) ; {Get block address from index blk}
|
|
; IF blk_num = $0000 THEN
|
|
; sparse_blk(data_buffer) ; {Fill Index buffer with zeros}
|
|
; ELSE
|
|
; IF curr_blk <> blk_to_read THEN
|
|
; read_blk(index_buffer) ; {Load index block from disk}
|
|
; END
|
|
; ELSE
|
|
; IF curr_mark > $200 THEN
|
|
; sparse_blk(data_buffer) ; {Clear the data buffer}
|
|
; ELSE
|
|
; read_blk(key_block) ; {main block for file}
|
|
;
|
|
;==========================================================================
|
|
|
|
fill_data ;
|
|
ldy #fcr_status
|
|
lda [pro_fcr_ptr],y
|
|
and #index_active
|
|
beq no_index ;there is no index buffer
|
|
|
|
jsr get_data_num ;setup drvr_blk_num from index blk
|
|
|
|
lda drvr_blk_num
|
|
bne not_sparse ;make the data block sparse
|
|
cpy #$0100 ;was it the 1st entry
|
|
bne sparse_data ;make data block sparse
|
|
|
|
lda curr_mark+2 ;see if the master index is zero
|
|
lsr a
|
|
and #$007F
|
|
bne sparse_data
|
|
|
|
ldy #fcr_storage ;is there an index block to load?
|
|
lda [pro_fcr_ptr],y
|
|
cmp #seedling_type
|
|
bne sparse_data ;make block sparse please
|
|
ldy #fcr_key_blk ;this is a seedling so load the block
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num
|
|
|
|
not_sparse ;
|
|
jsr chk_data_clean ;make sure the data buffer is OK
|
|
bcc @still_ok
|
|
rts
|
|
@still_ok
|
|
lda drvr_blk_num
|
|
ldy #data_blk_num ;see if the block is already loaded
|
|
cmp [pro_fcr_ptr],y
|
|
bne load_data
|
|
exit_fill_data ;
|
|
clc
|
|
rts ;no problem here
|
|
|
|
load_data ;
|
|
lda data_ptr
|
|
sta drvr_buf_ptr
|
|
lda data_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
jsr read_with_mount ;read in the block please
|
|
bcc store_data_num
|
|
rts
|
|
|
|
store_data_num ;
|
|
ldy #data_blk_num ;update current block loaded field
|
|
lda drvr_blk_num
|
|
sta [pro_fcr_ptr],y
|
|
rts
|
|
|
|
;==========================================================================
|
|
;If we get here we know that there is no index block loaded
|
|
;==========================================================================
|
|
|
|
no_index ;
|
|
lda curr_mark+1
|
|
lsr a
|
|
and #$00FF
|
|
beq @need_long
|
|
brl sparse_data ;make the data block sparse if needed
|
|
@need_long
|
|
ldy #fcr_key_blk
|
|
lda [pro_fcr_ptr],y
|
|
ldy #data_blk_num ;current block that is loaded
|
|
cmp [pro_fcr_ptr],y
|
|
bne reload_data
|
|
clc
|
|
rts ;block is already loaded
|
|
|
|
reload_data ;
|
|
sta drvr_blk_num
|
|
lda data_ptr
|
|
sta drvr_buf_ptr
|
|
lda data_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
jsr read_with_mount
|
|
bcc data_read
|
|
rts
|
|
|
|
data_read ;
|
|
ldy #data_blk_num
|
|
lda drvr_blk_num ;update the current block loaded
|
|
sta [pro_fcr_ptr],y
|
|
rts
|
|
|
|
;==========================================================================
|
|
EXPORT get_data_num
|
|
get_data_num ;
|
|
lda curr_mark+1
|
|
lsr a
|
|
and #$00FF
|
|
tay
|
|
ora #$0100
|
|
tax
|
|
|
|
lda [index_ptr],y ;setup the block number
|
|
sta drvr_blk_num
|
|
txy
|
|
lda [index_ptr],y
|
|
sta drvr_blk_num+1
|
|
stz drvr_blk_num+2
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Chk_data_clean will determine if the current data block needs to be
|
|
;written to disk before the new block is loaded
|
|
;==========================================================================
|
|
chk_data_clean
|
|
phy
|
|
ldy #fcr_status ;we are going to read another block so make sure
|
|
lda [pro_fcr_ptr],y ;the I/O buffer is clean
|
|
and #data_dirty
|
|
beq @not_dirty ;easy case.
|
|
|
|
lda drvr_blk_num ;get the block number we want to load
|
|
ldy #data_blk_num ;see if the block is already loaded
|
|
cmp [pro_fcr_ptr],y
|
|
beq @not_dirty ;another easy case.
|
|
|
|
pha ;save the driver block number
|
|
jsr flush_data_blk ;save the data to disk
|
|
plx ;get the drvr_blk_number back please
|
|
stx drvr_blk_num
|
|
ply
|
|
rts ;carry will return any error
|
|
|
|
@not_dirty
|
|
ply
|
|
clc
|
|
rts
|
|
|
|
|
|
fill_directory ;
|
|
|
|
;==========================================================================
|
|
;OK this file is a directory so lets handle this pain in the butt case.
|
|
;
|
|
;The way it works:
|
|
;
|
|
; The master index field contains the current block number
|
|
; that is loaded into the data buffer. So when I'm called
|
|
; with the current mark I calculate the block number that
|
|
; that is needed. If the block number is less then the
|
|
; current block number then I walk the backward links till
|
|
; I find the block needed. If the block wanted is greater
|
|
; then the current block I walk the links forward till I
|
|
; find the correct block, and at the end I update the FCR.
|
|
;
|
|
;==========================================================================
|
|
|
|
lda #in_cache
|
|
sta drvr_cache
|
|
|
|
lda data_ptr ;setup buffer pointer to data buffer
|
|
sta drvr_buf_ptr
|
|
lda data_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
|
|
lda curr_mark+1
|
|
lsr a ;bytes to blocks
|
|
sta math_temp
|
|
|
|
ldy #data_blk_num
|
|
lda [pro_fcr_ptr],y
|
|
sta entries_blk_num
|
|
|
|
ldy #master_blk_num
|
|
lda [pro_fcr_ptr],y
|
|
cmp math_temp
|
|
bne have_to_look
|
|
clc
|
|
rts
|
|
|
|
have_to_look ;
|
|
sta last_blk
|
|
bcs look_backward ;IF current > wanted THEN go backward
|
|
|
|
;==========================================================================
|
|
;Of we get here we walk thru the forward links till we find the right blk
|
|
;==========================================================================
|
|
|
|
forward_loop ;
|
|
ldy #$0002
|
|
lda [data_ptr],y
|
|
beq bad_dir_blk ;This should NEVER happen!!!!!
|
|
sta drvr_blk_num
|
|
jsr go_get_block ;go read the block
|
|
bcc ar16
|
|
rts ;return the error
|
|
|
|
ar16 ;
|
|
lda [data_ptr] ;verify backward links please
|
|
cmp entries_blk_num
|
|
beq cont16
|
|
lda #dir_error
|
|
bra dir_bad
|
|
|
|
cont16 ;
|
|
ldy #data_blk_num
|
|
lda drvr_blk_num
|
|
sta [pro_fcr_ptr],y
|
|
sta entries_blk_num ;update both the FCR and Link verify
|
|
|
|
inc last_blk ;advance the block counter
|
|
lda last_blk
|
|
cmp math_temp ;See if this the right bloc number
|
|
bne forward_loop ;go and get the next block
|
|
|
|
end_links ldy #master_blk_num ;update the current block
|
|
sta [pro_fcr_ptr],y
|
|
clc
|
|
rts
|
|
|
|
;==========================================================================
|
|
;We need to set the mark backward. So we need to walk the links backward
|
|
;==========================================================================
|
|
|
|
look_backward ;
|
|
lda [data_ptr]
|
|
beq bad_dir_blk ;This should NEVER happen!!!!!
|
|
sta drvr_blk_num
|
|
jsr go_get_block ;go read the block
|
|
bcc ar18
|
|
rts ;return the error
|
|
|
|
ar18 ;
|
|
ldy #$0002
|
|
lda [data_ptr],y
|
|
cmp entries_blk_num
|
|
bne dir_bad
|
|
|
|
lda drvr_blk_num
|
|
ldy #data_blk_num
|
|
sta [pro_fcr_ptr],y
|
|
sta entries_blk_num
|
|
|
|
dec last_blk ;advance the block counter
|
|
lda last_blk
|
|
cmp math_temp ;See if this the right bloc number
|
|
bne look_backward ;go and get the next block
|
|
bra end_links ;we are done
|
|
|
|
;==========================================================================
|
|
|
|
bad_dir_blk ;
|
|
lda #parm_range_err
|
|
dir_bad ;
|
|
sec
|
|
jmp main_exit
|
|
|
|
;==========================================================================
|
|
|
|
go_get_block ;
|
|
jsr standard_req
|
|
jsr read_with_cache ;issue the read call
|
|
rts
|
|
|
|
data_flag DC.W 00
|
|
|
|
ENDP
|
|
|
|
|
|
;==========================================================================
|
|
;send_sparse_blk: This routine will zero out 512 bytes of memory.
|
|
;
|
|
;Input: A = undefined
|
|
; X = low word pointer to buffer
|
|
; Y = high word pointer to buffer
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT send_sparse_blk
|
|
send_sparse_blk PROC
|
|
|
|
stx sparse_ptr
|
|
sty sparse_ptr+2
|
|
ldy #$01FE ;starting index
|
|
lda #$0000
|
|
sparse_loop ;
|
|
sta [sparse_ptr],y
|
|
dey
|
|
dey
|
|
bpl sparse_loop
|
|
rts
|
|
ENDP
|
|
|
|
|
|
|
|
;==========================================================================
|
|
;calc_seg_blks: This routine will calculate the number of sequential
|
|
; blocks in an index block. This routine will NOT calculate
|
|
; across index blocks.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; index_ptr (points to the index pointer)
|
|
; curr_mark (curr_mark must be on block boundary!)
|
|
;
|
|
;Output: A = number of blocks that are sequential
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; math_temp (just a temp counter)
|
|
; comp_temp = and_mask
|
|
; check_blk = entries_checked
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT num_seq_blks
|
|
num_seq_blks PROC
|
|
|
|
;==========================================================================
|
|
;Local equates for this routine
|
|
;==========================================================================
|
|
|
|
comp_temp equ and_mask ;(same ZP location different name)
|
|
check_blk equ entries_checked ;(same ZP location different name)
|
|
|
|
;==========================================================================
|
|
;Zero the counter and save the current file marker
|
|
;==========================================================================
|
|
|
|
stz math_temp
|
|
lda curr_mark
|
|
pha
|
|
lda curr_mark+2
|
|
pha
|
|
|
|
;==========================================================================
|
|
;first make sure the index blocks are loaded correctly
|
|
;==========================================================================
|
|
|
|
jsr load_indexes
|
|
|
|
;==========================================================================
|
|
;No go and get the first block from the Index block buffer.
|
|
;==========================================================================
|
|
|
|
jsr get_blk_num
|
|
sta check_blk
|
|
pha ;save starting block number
|
|
|
|
lda storage_type
|
|
cmp #subdir_type
|
|
bcs seq_exit ;always return zero for a directory
|
|
lda newline_len
|
|
bne seq_exit ;always return zero if newline enabled
|
|
|
|
calc_loop ;
|
|
|
|
;==========================================================================
|
|
;Calculate the index to the next block number.
|
|
;==========================================================================
|
|
|
|
jsr get_blk_num
|
|
bcs seq_exit ;we have looked at the entire block
|
|
dec a ;subtract one from the block
|
|
cmp #$FFFF ;see if this block is sparse
|
|
beq seq_exit ;this must be a sparse block!
|
|
cmp check_blk
|
|
bne seq_exit
|
|
inc a ;restore the block number
|
|
sta check_blk ;setup for next compare
|
|
inc math_temp
|
|
bra calc_loop
|
|
|
|
seq_exit ;
|
|
|
|
;==========================================================================
|
|
;restore the current marker and return the number of sequential blocks.
|
|
;==========================================================================
|
|
|
|
plx ;load X with starting block
|
|
pla
|
|
sta curr_mark+2
|
|
pla
|
|
sta curr_mark
|
|
|
|
lda math_temp ;return number of sequential blocks
|
|
rts
|
|
|
|
|
|
;==========================================================================
|
|
;get_blk_num: This routine will return the block number out of the index
|
|
; block based on the current file marker. It will also
|
|
; advance the file marker by 512 bytes.
|
|
;
|
|
;Input: curr_mark
|
|
;
|
|
;Output: carry set = end of block
|
|
; A = block number
|
|
;==========================================================================
|
|
|
|
get_blk_num ;
|
|
|
|
lda curr_mark+1
|
|
lsr a
|
|
and #$00FF
|
|
pha
|
|
tay
|
|
ora #$0100
|
|
tax
|
|
|
|
lda [index_ptr],y
|
|
and #$00FF
|
|
sta comp_temp
|
|
txy
|
|
lda [index_ptr],y
|
|
and #$00FF
|
|
xba
|
|
ora comp_temp
|
|
tax
|
|
|
|
clc
|
|
lda curr_mark
|
|
adc #blk_size
|
|
sta curr_mark
|
|
bcc ar11
|
|
inc curr_mark+2
|
|
clc
|
|
ar11 ;
|
|
txa ;block number
|
|
plx ;get the first index value
|
|
beq end_seq ;just set the carry
|
|
|
|
;==========================================================================
|
|
;WARNING!! --> Carry must be clear when we get here.
|
|
;==========================================================================
|
|
|
|
rts
|
|
|
|
end_seq ;
|
|
sec
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;setup_curr_mark This routine will load the current file marker out of the
|
|
; FCR and store it in curr_mark
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; pro_fcr_ptr (points to my FCR data)
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; curr_mark (contains current file marker)
|
|
;
|
|
;Uses: All registers
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT setup_curr_mark
|
|
setup_curr_mark PROC
|
|
|
|
ldy #fcr_curr_mark
|
|
lda [pro_fcr_ptr],y
|
|
sta curr_mark
|
|
iny
|
|
iny
|
|
lda [pro_fcr_ptr],y
|
|
sta curr_mark+2
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;setup_curr_eof This routine will load the current end of file out of the
|
|
; FCR and store it in curr_eof
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; pro_fcr_ptr (points to my FCR data)
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; curr_eof (contains current end fo file)
|
|
;
|
|
;Uses: All registers
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT setup_curr_eof
|
|
setup_curr_eof PROC
|
|
|
|
ldy #fcr_curr_eof
|
|
lda [pro_fcr_ptr],y
|
|
sta curr_eof
|
|
iny
|
|
iny
|
|
lda [pro_fcr_ptr],y
|
|
sta curr_eof+2
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;save_curr_mark This routine will save the current end of file into the
|
|
; FCR.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; pro_fcr_ptr (points to my FCR data)
|
|
; curr_mark
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Uses: A and Y registers
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT save_curr_mark
|
|
save_curr_mark PROC
|
|
|
|
ldy #fcr_curr_mark
|
|
lda curr_mark
|
|
sta [pro_fcr_ptr],y
|
|
iny
|
|
iny
|
|
lda curr_mark+2
|
|
sta [pro_fcr_ptr],y
|
|
rts
|
|
ENDP
|
|
;==========================================================================
|
|
;Write: This file contains code used to write data to a file.
|
|
; The types of files supported are:
|
|
;
|
|
; 1) seedling
|
|
; 2) sapling
|
|
; 3) tree
|
|
;
|
|
;Created: oct 06, 1987
|
|
;Modified: oct 15, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
; and lots of other stuff.
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Reference Number (2 Bytes)
|
|
; Pointer to Data Buffer (4 Bytes)
|
|
; Request Count (4 Bytes)
|
|
; Transfer Count (4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Reference Number (2 Bytes)
|
|
; Pointer to Data Buffer (4 Bytes)
|
|
; Request Count (4 Bytes)
|
|
; Transfer Count (4 Bytes)
|
|
; Cache Priority (2 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT write
|
|
write PROC
|
|
|
|
stz seq_write_cnt ;reset sequential block counter
|
|
jsr setup_params ;setup standard parameters
|
|
|
|
ldy #fcr_access ;see if the file is write protected
|
|
lda [my_fcr_ptr],y
|
|
and #ClrAllButAccess
|
|
cmp #write_access
|
|
bcs write_ok ;write access is enabled.
|
|
|
|
bad_access ; ;user cannot write to this file.
|
|
lda #invalid_access
|
|
sec
|
|
jmp main_exit
|
|
|
|
write_ok ;
|
|
ldy #vcr_dev ;last known location of volume
|
|
lda [my_vcr_ptr],y
|
|
sta drvr_dev_num ;I hope that the disk is still here.
|
|
|
|
jsr chk_disk_protect
|
|
|
|
not_protected ;
|
|
jsr read_write_setup
|
|
jsr setup_curr_mark
|
|
jsr setup_curr_eof
|
|
|
|
jsr setup_io_ptrs ;setup pointers to I/O buffer
|
|
jsr chk_swapped ;mount the volume if needed
|
|
bcc vol_online
|
|
jmp main_exit
|
|
|
|
;==========================================================================
|
|
; IF curr_mark NOT block_aligned THEN
|
|
;==========================================================================
|
|
vol_online ;
|
|
jsr users_to_drvrs ;move user's pointer to driver's ptr
|
|
jsr user_to_temp ;temp_ptr := user_buf_ptr
|
|
|
|
block_loop ;
|
|
lda curr_mark ;see if we are block aligned
|
|
and #$01FF
|
|
beq block_aligned ;yes we are block aligned
|
|
jsr partial_write ;write until data is block aligned.
|
|
bcs write_exit ;major problem
|
|
bra next_block
|
|
|
|
block_aligned ;
|
|
lda user_req_cnt+2 ;is req_cnt >= 512?
|
|
bne more_then_512
|
|
lda user_req_cnt
|
|
cmp #blk_size
|
|
bcc less_then_512
|
|
more_then_512 ;
|
|
jsr full_write ;transfer full 512 bytes.
|
|
bcs write_exit
|
|
bra next_block ;go to the next block please
|
|
|
|
;==========================================================================
|
|
;Less_then_512. we have less then 512 bytes to write.
|
|
;==========================================================================
|
|
less_then_512 ;
|
|
jsr partial_write ;write the partial block to disk
|
|
bcs write_exit ;major problem.
|
|
|
|
next_block ;
|
|
jsr rw_adjust ;adjust the following:
|
|
; ;(1) user_buf_ptr
|
|
; ;(2) tran_cnt
|
|
; ;(3) curr_mark
|
|
; ;(4) user_req_cnt
|
|
lda user_req_cnt+2 ;see if we are done yet
|
|
bne block_loop
|
|
lda user_req_cnt
|
|
bne block_loop
|
|
clc
|
|
|
|
write_exit
|
|
|
|
php
|
|
pha
|
|
bcc @10 ;there is no error so skip flush
|
|
|
|
jsr flush_file ;try to save the world
|
|
@10
|
|
jsr update_mark_eof ;make sure the mark is OK
|
|
|
|
ldy #fcr_curr_eof ;update the current end of file please
|
|
lda curr_eof
|
|
sta [pro_fcr_ptr],y
|
|
iny
|
|
iny
|
|
lda curr_eof+2
|
|
sta [pro_fcr_ptr],y
|
|
|
|
lda #file_dirty
|
|
jsr set_fcr_status ;indicate that something changed.
|
|
jsr standard_req ;make sure we write 512 bytes only
|
|
|
|
jsr flush_blocks ;flush any blocks to disk.
|
|
bcs write_failed ;bad news we cannot complete the flush!!!
|
|
;
|
|
;We know that the mark actually points to one past where the last byte is so
|
|
;lets reduce the mark by one please
|
|
;v00.06 a06
|
|
;
|
|
lda curr_mark
|
|
bne @no_high
|
|
dec curr_mark+2
|
|
@no_high
|
|
dec curr_mark
|
|
|
|
clc
|
|
jsr get_write_blk ;make sure I/O buffer is OK
|
|
bcs write_failed
|
|
txa ;block to load
|
|
beq holy_cow ;I hope not
|
|
jsr load_data ;load the data buffer please
|
|
bcs write_failed
|
|
holy_cow ;
|
|
inc curr_mark
|
|
bne @low_only
|
|
inc curr_mark+2
|
|
@low_only
|
|
|
|
pla ;restore error code
|
|
plp
|
|
jmp end_read_write ;exit thru wonder code in read file
|
|
|
|
write_failed
|
|
plx ;kill the old exit code
|
|
plp ;kill the old processor flag
|
|
sec ;make sure the error is set
|
|
jmp end_read_write ;exit please.
|
|
|
|
;==========================================================================
|
|
;Write blocks of 512 to disk
|
|
;==========================================================================
|
|
|
|
full_write
|
|
lda #blk_size
|
|
jsr range_chk_eof ;see if we overrun the EOF
|
|
bcs eof_error ;sorry we have an eof error
|
|
|
|
jsr standard_req ;transfer of 512 bytes
|
|
ldy #fcr_status ;see if the data block is dirty
|
|
lda [pro_fcr_ptr],y
|
|
and #data_dirty
|
|
beq clean_blk ;no flush needed
|
|
jsr flush_data_blk ;write the data block to disk
|
|
bcs write_exit ;get out of here with the error code
|
|
|
|
clean_blk ;
|
|
jsr user_to_temp ;temp_ptr := user_buf_ptr
|
|
clc
|
|
jsr get_write_blk ;is there a current block allocated?
|
|
bne block_allocated ;yes there is a block allocated.
|
|
|
|
jsr chk_sparse ;is the user's data sparse?
|
|
bcc do_flush ;data sparse so flush queued data blocks
|
|
; sec
|
|
jsr get_write_blk ;allocate a block please
|
|
bcc @no_error
|
|
brl write_exit ;cannot allocate a new block?
|
|
@no_error
|
|
pha
|
|
jsr user_to_temp ;point to user's buffer
|
|
pla
|
|
block_allocated ;
|
|
sta drvr_blk_num ;save the block number to write.
|
|
jsr user_to_data ;move user's data to data buffer
|
|
jsr write_data_blk ;write the data block to disk.
|
|
rts
|
|
|
|
do_flush ;
|
|
jsr flush_blocks ;issue the flush command
|
|
rts
|
|
|
|
user_to_data ;
|
|
lda users_buf_ptr ;setup driver buffer pointer to
|
|
sta drvr_buf_ptr ;point to the user's data!
|
|
lda users_buf_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
rts
|
|
|
|
eof_error
|
|
lda #out_of_range ;you have pushed me too far!!!
|
|
sec
|
|
rts
|
|
|
|
|
|
|
|
|
|
; ldy #$01FE ;move 512 bytes please
|
|
;user_loop anop
|
|
; lda [drvr_buf_ptr],y
|
|
; sta [data_ptr],y
|
|
; dey
|
|
; dey
|
|
; bpl user_loop
|
|
; rts
|
|
|
|
;==========================================================================
|
|
;partial_write: This routine will handle reading/writing a partial block
|
|
;
|
|
;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
|
|
;==========================================================================
|
|
|
|
partial_write ;
|
|
jsr build_index ;simulate a disk write
|
|
jsr range_chk_eof ;see if we overrun the EOF
|
|
bcs eof_error ;sorry we have an eof error
|
|
|
|
jsr standard_req ;we can only write 512 bytes!
|
|
jsr flush_blocks ;write any left over seq. blocks
|
|
bcs end_partial ;error condition
|
|
clc
|
|
jsr get_write_blk ;is there a current block allocated?
|
|
bne block_is_avail ;there is a block allocated.
|
|
|
|
; we know that the block is not allocated so check the data
|
|
|
|
jsr chk_sparse ;AND (data NOT sparse)
|
|
bcc is_sparse ;... (data IS sparse)
|
|
jsr get_write_blk ;allocate a block for the new data
|
|
bcs end_partial
|
|
pha ;save the block number
|
|
ldx data_ptr ;clear the new data block
|
|
ldy data_ptr+2
|
|
jsr clear_index
|
|
pla
|
|
block_is_avail ;
|
|
jsr load_data ;load in the data block
|
|
bcs end_partial
|
|
jsr user_to_temp
|
|
jsr merge_data ;add data to current block!
|
|
lda #file_dirty+data_dirty
|
|
jsr set_fcr_status ;indicate that something changed.
|
|
clc
|
|
rts
|
|
|
|
is_sparse ;
|
|
ldy #data_blk_num
|
|
lda [pro_fcr_ptr],y ;is block already loaded?
|
|
beq @sparse_loaded
|
|
|
|
ldy #fcr_status
|
|
lda [pro_fcr_ptr],y
|
|
and #data_dirty
|
|
beq @just_clear_buf ;no need to update the data block
|
|
|
|
jsr flush_data_blk
|
|
bcs end_partial
|
|
@just_clear_buf
|
|
ldx data_ptr ;clear the new data block
|
|
ldy data_ptr+2
|
|
jsr clear_index
|
|
|
|
ldy #data_blk_num
|
|
lda #$0000
|
|
sta [pro_fcr_ptr],y ;is block already loaded?
|
|
|
|
@sparse_loaded
|
|
jsr build_index ;simulate a disk write
|
|
sta drvr_req_cnt
|
|
stz drvr_req_cnt+2
|
|
clc
|
|
end_partial ;
|
|
rts
|
|
;==========================================================================
|
|
;Range_chk_eof This routine will make sure the write call will work with
|
|
; the three byte eof.
|
|
;
|
|
;Input: A = write_count
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; curr_eof ;the current eof
|
|
;
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
;==========================================================================
|
|
range_chk_eof
|
|
clc
|
|
adc curr_mark
|
|
lda #0000
|
|
adc curr_mark+2 ;check the high word
|
|
and #$FF00 ;clear the result
|
|
bne range_err
|
|
clc
|
|
rts
|
|
range_err
|
|
sec
|
|
rts
|
|
|
|
|
|
;==========================================================================
|
|
;write_data_blk This routine will write data blocks to disk. The code will
|
|
; determine if we can hold off writing to disk so we can
|
|
; gain performance by doing a multi-block transfer call.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; drvr_blk_num ;block number to write
|
|
; drvr_buf_ptr ;pointer to the data
|
|
;
|
|
;
|
|
;Output: A = error code if carry set otherwise undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
;==========================================================================
|
|
|
|
write_data_blk ;
|
|
lda seq_write_cnt ;do we have anything to write?
|
|
beq new_block ;no
|
|
lda drvr_blk_num ;is this a sequential block write?
|
|
dec a
|
|
cmp seq_write_blk
|
|
beq bump_seq ;bump the sequential counter
|
|
|
|
lda drvr_blk_num ;save block number to write
|
|
pha
|
|
lda drvr_buf_ptr
|
|
pha
|
|
lda drvr_buf_ptr+2
|
|
pha
|
|
jsr flush_blocks ;write any seq. blocks to disk
|
|
plx
|
|
stx drvr_buf_ptr+2
|
|
plx
|
|
stx drvr_buf_ptr
|
|
plx
|
|
stx drvr_blk_num
|
|
stz seq_write_cnt
|
|
bcs end_write_data ;error
|
|
|
|
new_block ;
|
|
inc seq_write_cnt ;advance the number of sequential blks
|
|
lda drvr_blk_num
|
|
sta seq_write_blk ;starting block for write call
|
|
|
|
jsr move_to_data_buf
|
|
|
|
lda drvr_buf_ptr
|
|
sta seq_write_start
|
|
lda drvr_buf_ptr+2
|
|
sta seq_write_start+2
|
|
end_write_data
|
|
lda #data_clean ;indicate that we have written block.
|
|
jsr clr_fcr_status
|
|
jsr standard_req ;set drvr_req_cnt to 512 bytes.
|
|
clc ;exit
|
|
rts
|
|
|
|
bump_seq
|
|
inc seq_write_cnt ;advance the block counter
|
|
inc seq_write_blk ;update new last sequential block
|
|
lda user_req_cnt+2
|
|
bne end_write_data
|
|
lda user_req_cnt
|
|
cmp #blk_size*2
|
|
bcs end_write_data
|
|
|
|
ldy #data_blk_num
|
|
lda drvr_blk_num
|
|
cmp [pro_fcr_ptr],y ;Should I Copy the data to the buffer
|
|
bne end_write_data ;Do not move the data.
|
|
|
|
jsr do_data_update
|
|
bra end_write_data
|
|
;
|
|
;This routine copies the user's data to the I/O Buffer
|
|
;
|
|
;input: A = block number
|
|
;
|
|
move_to_data_buf
|
|
ldy #data_blk_num
|
|
cmp [pro_fcr_ptr],y ;is block already loaded?
|
|
bne io_buf_ok ;don't worry about I/O buffer update
|
|
do_data_update
|
|
pei drvr_buf_ptr+2 ;address of user's data
|
|
pei drvr_buf_ptr
|
|
|
|
pei data_ptr+2 ;destination address
|
|
pei data_ptr
|
|
pea $0000 ;high word of count
|
|
pea blk_size ;number of bytes to send
|
|
pea move_sinc_dinc
|
|
jsl move_info
|
|
io_buf_ok rts
|
|
|
|
;==========================================================================
|
|
;flush_blocks: This routine will write out any data blocks that have not
|
|
; been written to disk. If will also make sure that the I/O
|
|
; buffer contains valid data.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = error code if carry set otherwise undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
;==========================================================================
|
|
EXPORT flush_blocks
|
|
flush_blocks ;
|
|
lda seq_write_cnt ;is there anything to write?
|
|
bne must_write
|
|
clc
|
|
rts
|
|
|
|
must_write ;
|
|
stz seq_write_cnt ;reset the sequential block counter
|
|
stz drvr_req_cnt ;setup the write count
|
|
asl a ;convert blocks to bytes
|
|
sta drvr_req_cnt+1
|
|
lsr a ;now get the starting block
|
|
dec a ;subtract one please
|
|
pha
|
|
sec
|
|
lda seq_write_blk
|
|
sbc 1,s
|
|
sta drvr_blk_num ;starting block number
|
|
pla ;fix the stack
|
|
|
|
lda seq_write_start
|
|
sta drvr_buf_ptr
|
|
lda seq_write_start+2
|
|
sta drvr_buf_ptr+2 ;pointer to the data
|
|
jsr write_with_mount
|
|
bcs flush_error
|
|
jsr standard_req
|
|
clc
|
|
flush_error ;
|
|
rts
|
|
|
|
|
|
|
|
;==========================================================================
|
|
;Set temp_ptr to the user's buffer pointer
|
|
;==========================================================================
|
|
|
|
user_to_temp ;
|
|
lda users_buf_ptr
|
|
sta temp_ptr ;set pointer to head of data
|
|
lda users_buf_ptr+2
|
|
sta temp_ptr+2
|
|
rts
|
|
|
|
users_to_drvrs ;
|
|
lda users_buf_ptr
|
|
sta drvr_buf_ptr ;set pointer to head of data
|
|
lda users_buf_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
rts
|
|
|
|
|
|
;==========================================================================
|
|
;merge_data: This routine will add in the user's data into the I/O
|
|
; buffer.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; curr_mark ;current file marker
|
|
; pro_fcr_ptr ;points to file control record
|
|
; data_ptr ;points to data block in I/O buffer.
|
|
; temp_ptr ;points to user data
|
|
; user_req_cnt ;used by build_index
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
;
|
|
; b = k
|
|
;
|
|
; drvr_req_cnt ;equals bytes moved
|
|
;
|
|
;
|
|
;uses: all registers
|
|
; math_temp
|
|
;==========================================================================
|
|
merge_data ;
|
|
jsr build_index ;'A' = 1 to $1FF
|
|
sta math_temp ;save count
|
|
sta drvr_req_cnt ;simulate a write to disk.
|
|
|
|
dec a ;A,X,Y perserved by 'update..' routine
|
|
pha
|
|
tay ;'Y' = 0 to $1FE (move count)
|
|
clc
|
|
lda curr_mark
|
|
and #$01FF
|
|
adc 1,s ;make index from END of buffer
|
|
tax ;index into data buffer
|
|
pla ;fix the stack
|
|
|
|
longa off ;block after the merge
|
|
sep #$20
|
|
|
|
merge_loop ;
|
|
lda [temp_ptr],y ;pointer to user's data
|
|
phy ;save user index
|
|
txy
|
|
sta [data_ptr],y ;store in the I/O buffer
|
|
dex
|
|
ply
|
|
dey
|
|
bpl merge_loop ;I/O buffer updated.
|
|
|
|
longa on
|
|
rep #$20
|
|
|
|
clc
|
|
lda curr_mark ;save the mark
|
|
pha
|
|
adc math_temp
|
|
sta curr_mark
|
|
lda curr_mark+2
|
|
pha
|
|
adc #$0000
|
|
sta curr_mark+2
|
|
|
|
jsr clr_to_boundary ;Clear to blk boundary
|
|
|
|
pla
|
|
sta curr_mark+2
|
|
pla
|
|
sta curr_mark
|
|
|
|
rts
|
|
|
|
|
|
;==========================================================================
|
|
;See if we have to deal with a sparse block.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; curr_mark ;current file marker
|
|
; pro_fcr_ptr ;pointer to file control record
|
|
; temp_ptr ;pointer to user's data buffer
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = sparse
|
|
; 0 = not sparse
|
|
; b = k
|
|
;
|
|
;uses: all registers
|
|
; math_temp
|
|
;
|
|
;FUNCTION sparse():boolean ;
|
|
; BEGIN
|
|
; index := (curr_mark MOD 512) ;
|
|
; sparse := true ;
|
|
; While (index < block_size) and (index < user_req) and (sparse = true) DO
|
|
; BEGIN
|
|
; IF data[index] <> 0 THEN
|
|
; sparse := flase
|
|
; index := index + 1 ;
|
|
; END
|
|
; END
|
|
;==========================================================================
|
|
chk_sparse ;
|
|
jsr user_to_temp ;temp_ptr := user_buf_ptr
|
|
jsr build_index
|
|
tay ;number of bytes to scan
|
|
dey ;force 1 to $0200 to 0 to $01FF
|
|
longa off
|
|
sep #$20 ;short accum for test
|
|
scan_loop ;
|
|
lda [temp_ptr],y ;pointer to user's data
|
|
bne non_sparse
|
|
dey
|
|
bpl scan_loop
|
|
longa on
|
|
rep #$20 ;restore 16 bit mode
|
|
clc
|
|
rts ;user data is all sparse
|
|
|
|
non_sparse ;
|
|
longa on
|
|
rep #$20 ;restore 16 bit mode
|
|
sec
|
|
rts
|
|
|
|
build_index ;
|
|
lda curr_mark ;number of bytes to check in user buf.
|
|
and #$01FF ;0 to $1FF
|
|
pha
|
|
sec
|
|
lda #blk_size ;calc number of bytes to scan
|
|
sbc 1,s ;range $0001 to $0200
|
|
ply ;fix the stack
|
|
|
|
ldy user_req_cnt+2 ;how many bytes do we need to write?
|
|
bne full_scan
|
|
|
|
cmp user_req_cnt
|
|
bcc full_scan
|
|
lda user_req_cnt
|
|
|
|
full_scan ;
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;update_mark_eof:
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; curr_mark ;current file marker
|
|
; curr_eof ;current end of file
|
|
; pro_fcr_ptr ;pointer to file control record
|
|
;
|
|
;Output: A = restored
|
|
; X = restored
|
|
; Y = restored
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
;
|
|
; b = k
|
|
;==========================================================================
|
|
EXPORT update_mark_eof
|
|
update_mark_eof PROC
|
|
|
|
pha
|
|
phx
|
|
phy
|
|
|
|
lda curr_mark+2
|
|
cmp curr_eof+2
|
|
bcc end_update ;EOF still OK
|
|
beq chk_low_eof
|
|
bra update_the_eof
|
|
|
|
chk_low_eof ;
|
|
lda curr_mark
|
|
cmp curr_eof
|
|
beq end_update
|
|
bcc end_update ;EOF still OK
|
|
|
|
update_the_eof ;
|
|
lda curr_mark+2
|
|
sta curr_eof+2 ;save the high byte
|
|
lda curr_mark
|
|
sta curr_eof ;save the low byte
|
|
|
|
end_update ;
|
|
ply
|
|
plx
|
|
pla
|
|
rts
|
|
ENDP
|
|
|
|
|
|
;==========================================================================
|
|
;get_write_blk: This routine will return the block number for the new data.
|
|
; If the file has a block allocated then that block number
|
|
; is returned otherwise a new block is allocated for the file.
|
|
; If the file needs to be expanded then it will be.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = allocate a new block if block not allocated
|
|
; 0 = just return current block number. (0 or blk num)
|
|
; b = k
|
|
;
|
|
; curr_mark ;current file marker
|
|
; pro_fcr_ptr ;points to file control record
|
|
;
|
|
;Output: A = block number of error code if carry set
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;
|
|
;uses: all registers
|
|
; math_temp
|
|
;==========================================================================
|
|
|
|
EXPORT get_write_blk
|
|
get_write_blk PROC
|
|
|
|
php ;save check flag.
|
|
php
|
|
pla
|
|
sta alloc_chk_flag
|
|
lsr a ;are we looking for a
|
|
bcs do_allocation
|
|
jsr chk_allocation
|
|
rts
|
|
;
|
|
;If here then we need to allocate or return the current block.
|
|
;
|
|
do_allocation ;
|
|
clc
|
|
lda curr_mark
|
|
adc #$0001
|
|
sta data_eof
|
|
lda curr_mark+2
|
|
adc #$0000
|
|
sta data_eof+2
|
|
jsr eof_to_blks ;convert current position to blks.
|
|
|
|
lda data_storage ;storage type needed (seed,sapling,tree)
|
|
cmp #seedling_type
|
|
bne sapling_case
|
|
brl add_new_block ;just go and get the block please
|
|
|
|
sapling_case ;
|
|
cmp #sapling_type
|
|
bne tree_case
|
|
;
|
|
;IF new_type = sapling THEN
|
|
; IF old_type = seedling THEN
|
|
; seedling_to_sapling
|
|
; ELSE
|
|
; add_index
|
|
;
|
|
;
|
|
ldy #fcr_storage ;current storage type
|
|
lda [pro_fcr_ptr],y
|
|
cmp #seedling_type
|
|
bne add_new_block
|
|
jsr seed_to_sap ;convert a seedling to a sapling
|
|
bcc add_new_block
|
|
rts
|
|
|
|
;
|
|
;IF new_type = tree THEN
|
|
; IF old_type = seedling THEN
|
|
; BEGIN
|
|
; seedling_to_sapling
|
|
; sapling_to_tree
|
|
; END
|
|
; ELSE
|
|
; IF old_type = sapling THEN
|
|
; sapling_to_tree
|
|
; ELSE
|
|
; IF old_type = tree THEN
|
|
; BEGIN
|
|
; IF master_index[curr_mark] = nil THEN
|
|
; add_master_index
|
|
; add_index
|
|
; END
|
|
;
|
|
|
|
tree_case ;
|
|
ldy #fcr_storage ;current storage type
|
|
lda [pro_fcr_ptr],y
|
|
cmp #seedling_type
|
|
bne not_seed
|
|
jsr seed_to_sap ;convert seedling to a sapling
|
|
bcs abort_tree
|
|
jsr sapling_to_tree ;convert a sapling to a tree
|
|
bcc add_new_block
|
|
abort_tree rts
|
|
|
|
not_seed ;
|
|
cmp #sapling_type ;is this a sapling file
|
|
bne not_sapling
|
|
jsr sapling_to_tree ;convert a sapling to a tree
|
|
bcs abort_tree
|
|
bra add_new_block
|
|
|
|
not_sapling ;
|
|
lda curr_mark+2 ;see if the index block is allocated
|
|
lsr a
|
|
ldx master_ptr
|
|
ldy master_ptr+2
|
|
jsr get_index_blk ;get the index block out of master blk
|
|
tax
|
|
bne add_new_block ;we do not need to add an index block
|
|
jsr tree_to_tree ;add a new index block
|
|
bcs abort_tree
|
|
|
|
;==========================================================================
|
|
;Now lets see if we need to add a new block or return the current block.
|
|
;==========================================================================
|
|
add_new_block ;
|
|
jsr calc_free_blks ;make sure that we have a block avail.
|
|
bcs abort_tree ;just exit
|
|
tax
|
|
bne we_have_room
|
|
brl out_of_room
|
|
|
|
we_have_room ;
|
|
ldy #master_blk_num ;see if we should even have looked at
|
|
lda [pro_fcr_ptr],y
|
|
beq no_master ;there is no master block for this file
|
|
|
|
lda curr_mark+2 ;see if we need the master index block
|
|
lsr a
|
|
ldx master_ptr ;get the block number from index block
|
|
ldy master_ptr+2
|
|
jsr get_index_blk ;A = block number
|
|
tax
|
|
bne cont01 ;there is an index block
|
|
|
|
ldy #fcr_status ;see if old index needs to be flushed
|
|
lda [pro_fcr_ptr],y
|
|
and #index_dirty
|
|
beq no_index_flush
|
|
jsr flush_index
|
|
bcs abort_tree ;exit
|
|
|
|
no_index_flush ;
|
|
ldx master_ptr
|
|
ldy master_ptr+2
|
|
lda curr_mark+2
|
|
lsr a ;now build a new index block
|
|
jsr new_block
|
|
bcs abort_tree ;sorry major problem
|
|
pha ;save the block number
|
|
lda #master_dirty+index_dirty+file_dirty
|
|
jsr set_fcr_status ;indicate master block dirty
|
|
ldx index_ptr ;clear the new buffer
|
|
ldy index_ptr+2
|
|
jsr clear_index
|
|
pla
|
|
ldy #index_blk_num
|
|
sta [pro_fcr_ptr],y
|
|
|
|
cont01 ;
|
|
ldy #index_blk_num
|
|
cmp [pro_fcr_ptr],y ;is the block loaded?
|
|
beq no_master ;no problem
|
|
sta key_block ;save the block wanted.
|
|
jsr flush_index ;write any dirty blocks to disk
|
|
bcs end_write_blk ;major problems
|
|
|
|
lda key_block ;load in the index block please
|
|
pha
|
|
jsr load_index
|
|
plx ;restore block number
|
|
bcs end_write_blk
|
|
txa
|
|
ldy #index_blk_num
|
|
sta [pro_fcr_ptr],y
|
|
|
|
no_master ;
|
|
lda curr_mark+1
|
|
lsr a
|
|
and #$00FF
|
|
ldx index_ptr ;get the block number from index block
|
|
ldy index_ptr+2
|
|
jsr get_index_blk ;A = block number
|
|
tax
|
|
bne have_blk
|
|
|
|
ldy #fcr_status ;see if data block needs to be written
|
|
lda [pro_fcr_ptr],y
|
|
and #data_dirty
|
|
beq data1_clean
|
|
jsr flush_data_blk
|
|
bcs end_write_blk
|
|
|
|
data1_clean ;
|
|
ldx index_ptr
|
|
ldy index_ptr+2
|
|
lda curr_mark+1
|
|
lsr a ;now build a new index block
|
|
and #$00FF
|
|
jsr new_block
|
|
bcs end_write_blk ;sorry major problem
|
|
pha ;save the block number
|
|
ldy #data_blk_num
|
|
sta [pro_fcr_ptr],y ;save the new block number
|
|
lda #index_dirty+file_dirty+data_dirty
|
|
jsr set_fcr_status ;indicate master block dirty
|
|
pla
|
|
have_blk ;
|
|
jsr load_data
|
|
bcs end_write_blk
|
|
lda drvr_blk_num
|
|
clc
|
|
end_write_blk ;
|
|
rts
|
|
|
|
|
|
EXPORT load_data
|
|
load_data ; ;input A= block to load
|
|
ldy #data_blk_num
|
|
cmp [pro_fcr_ptr],y ;is block already loaded?
|
|
beq exit_load_data
|
|
|
|
pha ;save the block to load
|
|
ldy #fcr_status
|
|
lda [pro_fcr_ptr],y
|
|
and #data_dirty
|
|
beq dont_update
|
|
|
|
jsr flush_data_blk
|
|
bcs end_load_data
|
|
dont_update ;
|
|
lda data_ptr
|
|
sta drvr_buf_ptr
|
|
lda data_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
lda 1,s ;get the block number to load
|
|
sta drvr_blk_num
|
|
jsr read_with_mount ;read in the new data block
|
|
bcs end_load_data
|
|
|
|
ldy #data_blk_num ;update current loaded block
|
|
lda drvr_blk_num
|
|
sta [pro_fcr_ptr],y
|
|
pla
|
|
exit_load_data ;
|
|
clc
|
|
sta drvr_blk_num
|
|
rts
|
|
|
|
end_load_data ;
|
|
plx ;fix the stack please
|
|
sec
|
|
rts
|
|
|
|
;==========================================================================
|
|
;new_block: This routine will allocate a new block from the system
|
|
; and add the block number in the index block pointed to
|
|
; by the X and Y registers.
|
|
;
|
|
;Input: A = index
|
|
; X = low word pointer to index block
|
|
; Y = high word pointer to index block
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = block number allocated or error code
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;
|
|
;uses: all registers
|
|
; temp4_ptr
|
|
;==========================================================================
|
|
new_block ;
|
|
stx temp4_ptr ;pointer to the index block
|
|
sty temp4_ptr+2
|
|
pha ;save the index
|
|
jsr calc_free_blks ;make sure that we a free block
|
|
bcs add_failed
|
|
tax
|
|
beq to_no_room
|
|
lda #$0001 ;allocate one block
|
|
ldx #$0000 ;start at block zero
|
|
jsr find_free_blks
|
|
bcs add_failed
|
|
phx ;save the block number
|
|
jsr bump_blks_used
|
|
lda 3,s ;get the index please
|
|
tay ;save the low index
|
|
ora #$0100
|
|
tax ;save the high index
|
|
pla
|
|
longa off
|
|
sep #$20 ;8 bit mode
|
|
sta [temp4_ptr],y
|
|
xba
|
|
txy
|
|
sta [temp4_ptr],y
|
|
longa on
|
|
rep #$20 ;16 bit mode
|
|
xba
|
|
plx ;fix the stack
|
|
clc
|
|
rts
|
|
|
|
add_failed plx ;fix the stack
|
|
rts
|
|
|
|
to_no_room pla ;fix the stack
|
|
brl out_of_room
|
|
|
|
|
|
bump_blks_used ;
|
|
ldy #fcr_blks_used
|
|
lda [pro_fcr_ptr],y
|
|
inc a ;advance the blocks used count
|
|
sta [pro_fcr_ptr],y
|
|
lda #dirEntry_dirty ;the directory entry needs updating when flushed
|
|
jsr set_fcr_status
|
|
rts
|
|
|
|
;==========================================================================
|
|
;get_index_blk: This routine will load a block number out of an index block
|
|
;
|
|
;Input: A = index
|
|
; X = low word pointer to index block
|
|
; Y = high word pointer to index block
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = block number
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;uses: all registers
|
|
; temp_ptr
|
|
;==========================================================================
|
|
|
|
EXPORT get_index_blk
|
|
get_index_blk ;
|
|
stx temp_ptr
|
|
sty temp_ptr+2
|
|
tax ;low word index
|
|
ora #$0100 ;high word index
|
|
tay
|
|
longa off
|
|
sep #$20 ;8 bit accum
|
|
lda [temp_ptr],y ;get the high word block number
|
|
xba
|
|
txy
|
|
lda [temp_ptr],y ;get the low word block number
|
|
longa on
|
|
rep #$20 ;16 bit accum
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Convert a seedling file into a sapling file.
|
|
;==========================================================================
|
|
seed_to_sap ;
|
|
jsr flush_blocks ;flush anydata still around
|
|
bcc do_sap
|
|
rts
|
|
do_sap ;
|
|
jsr calc_free_blks ;see how many blocks we have
|
|
tax
|
|
bne lots_of_room
|
|
brl out_of_room ;sorry bud not today
|
|
|
|
lots_of_room ;
|
|
lda #$0001 ;go get me a new block
|
|
ldx #$0000 ;start looking at block zero
|
|
jsr find_free_blks
|
|
bcs end_to_sap
|
|
txa ;new key block
|
|
pha
|
|
|
|
ldy index_ptr
|
|
sty temp4_ptr
|
|
ldy index_ptr+2
|
|
sty temp4_ptr+2
|
|
|
|
dec a ;see if we should flip data and index
|
|
ldy #fcr_key_blk ;
|
|
cmp [pro_fcr_ptr],y
|
|
beq do_flip
|
|
|
|
txa
|
|
ldy #index_blk_num
|
|
sta [pro_fcr_ptr],y ;save the new index block number
|
|
jsr bump_blks_used
|
|
|
|
ldy #fcr_key_blk ;data block address
|
|
lda [pro_fcr_ptr],y
|
|
ldy #$0000 ;store as first entry in index block
|
|
jsr add_index
|
|
|
|
lda #index_active+index_dirty+file_dirty
|
|
jsr set_fcr_status ;mark index block active
|
|
pla ;restore key block
|
|
ldx #sapling_type
|
|
jsr update_new_type
|
|
rts
|
|
|
|
end_to_sap ;
|
|
rts
|
|
|
|
do_flip ;
|
|
ldy #fcr_status ;see if the data block is dirty
|
|
lda [pro_fcr_ptr],y
|
|
and #data_dirty
|
|
beq onward
|
|
jsr flush_data_blk
|
|
bcc onward
|
|
plx ;fix the stack!!!!
|
|
rts
|
|
|
|
onward ;
|
|
ldy #fcr_key_blk ;load in the data block
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num
|
|
ldy #data_blk_num
|
|
sta [pro_fcr_ptr],y ;update current data block
|
|
|
|
lda data_ptr
|
|
sta drvr_buf_ptr
|
|
lda data_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
jsr read_with_mount ;read in the data block
|
|
bcc onward2
|
|
plx ;fix the stack
|
|
rts
|
|
|
|
onward2 ;
|
|
pla ;get the new block number
|
|
ldy #data_blk_num
|
|
sta [pro_fcr_ptr],y ;now the data block has changed
|
|
ldy #$0000 ;store as first entry in index block
|
|
jsr add_index
|
|
|
|
lda #index_active+index_dirty+file_dirty+data_dirty
|
|
jsr set_fcr_status ;mark index block active
|
|
jsr bump_blks_used
|
|
|
|
ldy #fcr_key_blk
|
|
lda [pro_fcr_ptr],y
|
|
ldy #index_blk_num
|
|
sta [pro_fcr_ptr],y ;now the index is new
|
|
ldx #sapling_type
|
|
jsr update_new_type
|
|
rts
|
|
|
|
out_of_room ;
|
|
lda #volume_full
|
|
sec
|
|
rts
|
|
|
|
sapling_to_tree ;
|
|
jsr calc_free_blks ;see how many blocks we have
|
|
tax
|
|
beq out_of_room ;sorry bud not today
|
|
lda #$0001 ;go get me a new block
|
|
ldx #$0000 ;start looking at block zero
|
|
jsr find_free_blks
|
|
bcs end_to_tree
|
|
txa ;new key block
|
|
pha
|
|
ldy #master_blk_num
|
|
sta [pro_fcr_ptr],y ;save the master index blk num
|
|
jsr bump_blks_used
|
|
|
|
lda master_ptr
|
|
sta temp4_ptr
|
|
lda master_ptr+2
|
|
sta temp4_ptr+2
|
|
|
|
ldy #fcr_key_blk ;current data block
|
|
lda [pro_fcr_ptr],y
|
|
ldy #$0000 ;store as first entry in index block
|
|
jsr add_index
|
|
lda #master_active+master_dirty+file_dirty
|
|
jsr set_fcr_status ;mark index block active
|
|
pla ;restore key block
|
|
ldx #tree_type
|
|
jsr update_new_type
|
|
end_to_tree ;
|
|
rts
|
|
|
|
tree_to_tree ;
|
|
jsr calc_free_blks ;see how many blocks we have
|
|
tax
|
|
|
|
beq out_of_room ;sorry bud not today
|
|
lda #$0001 ;go get me a new block
|
|
ldx #$0000 ;start looking at block zero
|
|
jsr find_free_blks
|
|
bcs end_to_tree
|
|
phx ;save the block number
|
|
|
|
lda master_ptr
|
|
sta temp4_ptr
|
|
lda master_ptr+2
|
|
sta temp4_ptr+2
|
|
jsr bump_blks_used ;must not use X register
|
|
|
|
lda curr_mark+2
|
|
lsr a
|
|
tay ;index into master block
|
|
txa ;new index block
|
|
|
|
jsr add_index
|
|
lda #master_dirty+file_dirty
|
|
jsr set_fcr_status ;indicate master index block is dirty
|
|
ldy #fcr_status ;see if current index block is dirty
|
|
lda [pro_fcr_ptr],y
|
|
and #index_dirty
|
|
beq mister_clean
|
|
jsr flush_index
|
|
bcc mister_clean
|
|
plx ;fix the stack
|
|
rts
|
|
mister_clean ;
|
|
ldy #index_blk_num ;the current index block
|
|
pla ;restore new index block number
|
|
sta [pro_fcr_ptr],y
|
|
lda #index_dirty+file_dirty
|
|
jsr set_fcr_status ;indicate that this block is dirty
|
|
ldx index_ptr
|
|
ldy index_ptr+2 ;clear the current index
|
|
jsr clear_index
|
|
clc
|
|
rts
|
|
|
|
EXPORT clear_index
|
|
clear_index ;
|
|
stx temp4_ptr ;zero out the buffer pointed to by
|
|
sty temp4_ptr+2 ;X and Y
|
|
ldy #$01FE
|
|
lda #$0000
|
|
clr_index sta [temp4_ptr],y
|
|
dey
|
|
dey
|
|
bpl clr_index
|
|
rts
|
|
|
|
;==========================================================================
|
|
;update_new_type:
|
|
; This routine will update the FCR to reflect the new storage
|
|
; type, and key block for a file
|
|
;
|
|
;Input: A = new key block
|
|
; X = new storage type
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; pro_fcr_ptr ;points to file control record
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;uses: all registers
|
|
;==========================================================================
|
|
|
|
update_new_type ;
|
|
pha ;save new key block
|
|
ldy #fcr_key_blk
|
|
sta [pro_fcr_ptr],y
|
|
ldy #fcr_entry_type
|
|
lda [pro_fcr_ptr],y ;is this a resource type?
|
|
cmp #resource_type
|
|
beq is_resource
|
|
|
|
txa ;save the new storage type
|
|
sta [pro_fcr_ptr],y
|
|
lda 1,s ;save the new key block
|
|
ldy #fcr_file_id
|
|
sta [pro_fcr_ptr],y
|
|
|
|
is_resource ;
|
|
pla ;fix the stack
|
|
ldy #fcr_storage ;store the new storage type
|
|
txa
|
|
sta [pro_fcr_ptr],y
|
|
jsr flush_file ;force directory update.
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;chk_allocation:
|
|
; This routine will return the block number of a data block
|
|
; if the file contains a data block
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefin
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; pro_fcr_ptr ;points to file control record
|
|
;
|
|
;Output: A = block number if 'z' = 0
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error and 'z' flag valid
|
|
; 1 = no block allocated
|
|
; 0 = A = block number
|
|
; b = k
|
|
;
|
|
;
|
|
;uses: all registers
|
|
;==========================================================================
|
|
|
|
;==========================================================================
|
|
;IF (curr_mark = tree) AND (storage <> tree) THEN
|
|
; no_block allocated
|
|
;
|
|
;==========================================================================
|
|
|
|
EXPORT chk_allocation
|
|
chk_allocation PROC ;see if there is block allocated.
|
|
|
|
lda curr_mark+2 ;see if we need the master index block
|
|
lsr a
|
|
ldx master_ptr ;get the block number from index block
|
|
ldy master_ptr+2
|
|
jsr get_index_blk ;A = block number
|
|
tax
|
|
bne cont01 ;there is an index block
|
|
;
|
|
;IF (type = tree) AND (index = sparse) THEN block_not_allocated
|
|
;
|
|
chk_tree ;
|
|
ldy #fcr_storage
|
|
lda [pro_fcr_ptr],y
|
|
cmp #tree_type ;does this puppy even have a master blk?>
|
|
bne chk_sapling ;there is no master index block
|
|
clc
|
|
rts
|
|
|
|
;
|
|
;IF (type <> tree) AND (curr_mark = tree) THEN block_not_allocated
|
|
;
|
|
chk_sapling ;
|
|
lda curr_mark+2 ;is the mark in tree range
|
|
lsr a
|
|
beq index_loaded ;mark not in tree range
|
|
bra no_block
|
|
|
|
cont01 ;
|
|
ldy #index_blk_num
|
|
cmp [pro_fcr_ptr],y ;is the block already loaded?
|
|
beq index_loaded
|
|
pha ;save the block number
|
|
ldy #fcr_status
|
|
lda [pro_fcr_ptr],y
|
|
and #index_dirty ;is the current index dirty?
|
|
beq index1_clean
|
|
jsr flush_index
|
|
bcc index1_clean
|
|
plx
|
|
rts
|
|
index1_clean ;
|
|
pla ;retore block number
|
|
ldy #index_blk_num
|
|
sta [pro_fcr_ptr],y ;save the new block please
|
|
jsr load_index
|
|
bcc index_loaded
|
|
rts
|
|
|
|
index_loaded ;
|
|
lda curr_mark+1
|
|
lsr a
|
|
and #$00FF
|
|
ldx index_ptr ;get the block number from index block
|
|
ldy index_ptr+2
|
|
jsr get_index_blk ;A = block number
|
|
tax
|
|
bne exit_chk_alloc
|
|
;
|
|
;IF (type = sapling) AND (data = sparse) THEN block_not_allocated
|
|
;
|
|
ldy #fcr_storage
|
|
lda [pro_fcr_ptr],y
|
|
cmp #sapling_type ;does this puppy even have an index blk
|
|
bcc chk_seedling ;there is no index block
|
|
txa ;reset the flag please
|
|
|
|
exit_chk_alloc ;
|
|
clc
|
|
rts
|
|
|
|
chk_seedling
|
|
lda curr_mark+1
|
|
lsr a
|
|
and #$00FF
|
|
beq get_key_blk ;mark < 512
|
|
no_block
|
|
ldx #$0000
|
|
sep #$02 ;set the 'Z' flag
|
|
clc
|
|
rts
|
|
|
|
get_key_blk ;
|
|
ldy #fcr_key_blk
|
|
lda [pro_fcr_ptr],y
|
|
tax ;setup the x register with the block number
|
|
clc
|
|
rts
|
|
|
|
EXPORT load_index
|
|
load_index
|
|
;enter with A = block number
|
|
|
|
;next 3 lines added 8/6/90 by Monte Benaresh
|
|
pha ;save block # for a moment
|
|
jsr standard_req ;set drvr_req_cnt to $200
|
|
pla ;restore block number
|
|
|
|
sta drvr_blk_num
|
|
lda index_ptr
|
|
sta drvr_buf_ptr
|
|
lda index_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
jsr read_with_cache
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;Clr_to_boundary This routine will clear data from the current EOF
|
|
; to the end of the block.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; curr_mark ;current file marker
|
|
; curr_eof ;current end of file
|
|
; pro_fcr_ptr ;points to file control record
|
|
; data_ptr ;points to data block in I/O buffer.
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
;
|
|
; b = k
|
|
;
|
|
;
|
|
; IF (eof >= (curr_mark AND $FE00 + 512)) THEN
|
|
; EXIT(clr_to_boundary)
|
|
; IF eof > curr_mark THEN
|
|
; clear_index := eof
|
|
; ELSE
|
|
; clear_index := curr_mark
|
|
; clear_block
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT clr_to_boundary
|
|
clr_to_boundary PROC
|
|
|
|
lda curr_eof
|
|
pha
|
|
lda curr_eof+2 ;save the current end of file
|
|
pha
|
|
|
|
lda curr_mark
|
|
pha ;save the current mark
|
|
lda curr_mark+2
|
|
pha
|
|
|
|
lda curr_mark ;if block aligned then exit
|
|
and #$01FF
|
|
bne not_aligned
|
|
brl exit_clr ;we do not have to clear anything
|
|
|
|
not_aligned
|
|
|
|
;
|
|
;curr_mark := ((curr_mark and $FE00) + 512) ;
|
|
;
|
|
clc
|
|
lda curr_mark ;move to a block boundary
|
|
and #$FE00
|
|
adc #blk_size ;add in 512 bytes
|
|
sta curr_mark
|
|
lda curr_mark+2
|
|
adc #$0000
|
|
sta curr_mark+2
|
|
;
|
|
; IF (eof >= (curr_mark AND $FE00 + 512)) THEN
|
|
; EXIT(clr_to_boundary)
|
|
;
|
|
lda curr_eof+2
|
|
cmp curr_mark+2
|
|
beq chk_low
|
|
bcs exit_clr ;EOF not in this block
|
|
bcc second_if ;continue process
|
|
chk_low ;
|
|
lda curr_eof
|
|
cmp curr_mark
|
|
bcs exit_clr ;EOF not in this block
|
|
|
|
;
|
|
; IF EOF < curr_mark AND $FE00 THEN
|
|
; clear_index := curr_mark
|
|
;
|
|
second_if ;
|
|
lda 3,s ;get the low word of the mark
|
|
and #$FE00
|
|
sta curr_mark
|
|
|
|
lda curr_eof+2
|
|
cmp 1,s ;check high word
|
|
beq second_low
|
|
bcs third_if ;EOF is in this block
|
|
bcc use_mark ;EOF not in this block
|
|
second_low ;
|
|
lda curr_eof
|
|
cmp curr_mark
|
|
bcs third_if ;EOF is in the block
|
|
bcc use_mark ;EOF not in this block
|
|
|
|
;
|
|
; IF eof > curr_mark THEN
|
|
; clear_index := eof
|
|
;
|
|
third_if ;
|
|
lda curr_eof+2 ;is eof > curr_mark
|
|
cmp 1,s ;high word of curr_mark
|
|
beq third_low
|
|
bcs use_eof ;clear from EOF
|
|
bcc use_mark ;clear from current mark
|
|
third_low ;
|
|
lda curr_eof
|
|
cmp 3,s
|
|
bcs use_eof ;use the eof as the value
|
|
|
|
use_mark ;
|
|
lda 3,s ;get the low word of current mark
|
|
and #$01FF ;clear garbage
|
|
beq exit_clr ;do not clear the buffer
|
|
bra do_clear
|
|
|
|
use_eof ;
|
|
lda curr_eof
|
|
and #$01FF
|
|
beq exit_clr ;do not clear the buffer
|
|
|
|
do_clear
|
|
tay ;make an index into block
|
|
iny
|
|
cpy #blk_size
|
|
beq exit_clr
|
|
tya ;can we clear the block fast
|
|
lsr a
|
|
bcc clear_it_fast
|
|
|
|
lda #$0000 ;clear value
|
|
longa off
|
|
sep #$20 ;8 bit mode
|
|
bra enter ;start the loop
|
|
clear_it
|
|
sta [data_ptr],y
|
|
iny
|
|
enter
|
|
cpy #blk_size ;are we done
|
|
bcc clear_it
|
|
longa on
|
|
rep #$20
|
|
bra exit_clr
|
|
|
|
clear_it_fast
|
|
lda #$0000
|
|
bra enter_fast
|
|
fast_loop
|
|
sta [data_ptr],y
|
|
iny
|
|
iny
|
|
enter_fast
|
|
cpy #$0200 ;are we done
|
|
bcc fast_loop
|
|
|
|
|
|
exit_clr ;
|
|
pla ;restore the curr_mark
|
|
sta curr_mark+2
|
|
pla
|
|
sta curr_mark
|
|
|
|
pla
|
|
sta curr_eof+2 ;restore the current end of file
|
|
pla
|
|
sta curr_eof
|
|
lda #data_dirty+file_dirty
|
|
jsr set_fcr_status
|
|
rts
|
|
ENDP
|
|
;==========================================================================
|
|
;Close: This routine will close a file.
|
|
;
|
|
;Created: aug 04, 1987
|
|
;Modified: aug 04, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; fill_io_buf
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Reference Number (2 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Reference Number (2 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT close
|
|
close PROC
|
|
|
|
;==========================================================================
|
|
;First preprocess the call to setup the needed parameters.
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
dec close_flag ;call slug ripple please
|
|
jsr flush_file ;force data to the disk
|
|
bcc flushed
|
|
jmp main_exit
|
|
|
|
flushed ;
|
|
jsr remove_fcr
|
|
jmp main_exit
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;flush: This routine will flush a file.
|
|
;
|
|
;Created: aug 04, 1987
|
|
;Modified: aug 04, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; fill_io_buf
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Reference Number (2 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Reference Number (2 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT flush
|
|
flush PROC
|
|
|
|
;==========================================================================
|
|
;First preprocess the call to setup the needed parameters.
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
dec close_flag ;call slug_ripple please
|
|
|
|
; New code added March 27, 1990 to support fast/slow flush,
|
|
; by Monte Benaresh, based on Andy Stadler's proposed
|
|
; changes.
|
|
|
|
lda pcount ;check number of params given by caller
|
|
cmp #2 ;did he specify type of flush?
|
|
bcc slow_flush ;too few, default to full flush
|
|
|
|
choose_flush ;caller specified type of flush
|
|
; valid flush types are:
|
|
; $0000 = full flush, data and directory blocks
|
|
; $8000 = fast flush, data blocks only
|
|
|
|
ldy #4 ;offset to flush type in param block
|
|
lda [param_blk_ptr],y ;get flush type
|
|
|
|
asl a ;get high bit
|
|
beq flush_type_ok ;low bits must be 0!
|
|
|
|
bad_flush_type ;invalid value for flush type
|
|
lda #parm_range_err
|
|
sec
|
|
bra flush_done ;return with error
|
|
|
|
flush_type_ok ;get here with high bit of flush type in carry
|
|
bcc slow_flush ;flush type was $0000
|
|
|
|
fast_flush ;flush type was $8000
|
|
jsr do_fast_flush ;write out all dirty data blocks, dirty
|
|
; bitmap blocks, and the directory entry
|
|
; only if it's been changed (mod date doesn't count!)
|
|
bra flush_done ;handle error elsewhere
|
|
slow_flush
|
|
jsr flush_file ;force data to the disk
|
|
|
|
flush_done
|
|
jmp main_exit
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;Set_mark: This routine will set a file position marker.
|
|
;
|
|
;Created: may 23, 1987
|
|
;Modified: may 23, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; fill_io_buf
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Reference Number (2 Bytes)
|
|
; File Position (4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Reference Number (2 Bytes)
|
|
; Base (2 Bytes)
|
|
; 00 = Absolute
|
|
; 01 = Backward From EOF
|
|
; 02 = Forward From Current Mark
|
|
; 03 = Backward From Current Mark
|
|
; Displacement (4 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT set_mark
|
|
set_mark PROC
|
|
|
|
;==========================================================================
|
|
;First preprocess the call to setup the needed parameters.
|
|
;==========================================================================
|
|
stz base
|
|
jsr setup_params
|
|
beq class0
|
|
|
|
;==========================================================================
|
|
;Fall thru if this is a class1 call
|
|
;==========================================================================
|
|
ldy #pblk_16_base
|
|
jsr check_base
|
|
ldy #pblk_16_disp
|
|
bra main_entry
|
|
|
|
class0 ;
|
|
|
|
;==========================================================================
|
|
;If this is a class zero call then setup an index to the file position
|
|
;and continue on.
|
|
;==========================================================================
|
|
ldy #$0002 ;index to displacement
|
|
|
|
main_entry ;
|
|
|
|
;==========================================================================
|
|
;Save the user's requested displacement
|
|
;==========================================================================
|
|
|
|
lda [my_pblk_ptr],y
|
|
sta displacement
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
|
|
sta displacement+2
|
|
|
|
;==========================================================================
|
|
;Setup 'curr_eof' and 'curr_mark'
|
|
;
|
|
; IF (curr_mark < 00) or (curr_mark > EOF) THEN
|
|
; BEGIN
|
|
; Error:= position_out_of_range_error
|
|
; EXIT(Set_Mark)
|
|
; END
|
|
;==========================================================================
|
|
|
|
jsr calc_curr_mark
|
|
bcc set_the_mark
|
|
lda #out_of_range
|
|
|
|
set_mark_exit
|
|
jmp main_exit
|
|
|
|
set_the_mark
|
|
;==========================================================================
|
|
;refill I/O buffer with the new data blocks needed.
|
|
;==========================================================================
|
|
|
|
jsr fill_io_buf
|
|
bcs set_mark_exit
|
|
|
|
;==========================================================================
|
|
;go and update the FCR with the new curr_mark.
|
|
;==========================================================================
|
|
|
|
jsr save_curr_mark
|
|
clc
|
|
|
|
;==========================================================================
|
|
;Exit all happy since the call was successful
|
|
;==========================================================================
|
|
|
|
bra set_mark_exit
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;check_base This routine will verify that the base is within range
|
|
;
|
|
;Created: may 23, 1987
|
|
;Modified: may 23, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;
|
|
;Enter: jsr
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = offset to base field
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
; BASE (contains value of the base)
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT check_base
|
|
check_base PROC
|
|
|
|
lda [my_pblk_ptr],y
|
|
cmp #max_base+1
|
|
bcs range_error
|
|
sta base
|
|
rts
|
|
|
|
EXPORT range_error
|
|
range_error ;
|
|
lda #parm_range_err
|
|
jmp main_exit
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;calc_curr_mark This routine will calculate the current mark for a file
|
|
; given BASE and DISPLACEMENT as input.
|
|
;
|
|
;Created: may 23, 1987
|
|
;Modified: may 23, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;
|
|
;Enter: jsr
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; BASE (base from param block)
|
|
; $00 = Absolute
|
|
; $01 = Backward From EOF
|
|
; $02 = Forward From Current Mark
|
|
; $03 = Backward From Current Mark
|
|
;
|
|
; DISPLACEMENT (displacement from param block)
|
|
; pro_fcr_ptr (pointer to my data in FCR
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; .<<000..1 = error if out of range
|
|
; | 0 = no error
|
|
; |
|
|
; |__ 1 = error out of range any cases
|
|
; 0 = result greater then current EOF
|
|
;
|
|
; b = k
|
|
;
|
|
; curr_mark (contains correct position for mark)
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT calc_curr_mark
|
|
calc_curr_mark PROC
|
|
|
|
;==========================================================================
|
|
;Setup the current EOF
|
|
;==========================================================================
|
|
jsr setup_curr_eof
|
|
|
|
;==========================================================================
|
|
;Setup the current file marker.
|
|
;==========================================================================
|
|
jsr setup_curr_mark
|
|
|
|
;==========================================================================
|
|
;Now we need to decide which way we need to move the mark.
|
|
;==========================================================================
|
|
|
|
lda base
|
|
beq absolute
|
|
dec a
|
|
beq back_from_eof
|
|
dec a
|
|
beq forward_mark
|
|
|
|
;==========================================================================
|
|
;If we fall thru to here then we need to set the mark backward from the
|
|
;current mark.
|
|
;==========================================================================
|
|
|
|
backward_mark ;
|
|
sec
|
|
lda curr_mark
|
|
sbc displacement
|
|
sta curr_mark
|
|
lda curr_mark+2
|
|
sbc displacement+2
|
|
sta curr_mark+2
|
|
bcs mark_ok
|
|
bad_range ;
|
|
sep #carry+overflow ;set both carry and overflow flags
|
|
rts ;exit with carry set to indicate error
|
|
|
|
;==========================================================================
|
|
;User wants to set the mark backward from the current end of file
|
|
;==========================================================================
|
|
|
|
back_from_eof ;
|
|
sec
|
|
lda curr_eof
|
|
sbc displacement
|
|
sta curr_mark
|
|
lda curr_eof+2
|
|
sbc displacement+2
|
|
sta curr_mark+2
|
|
bcc bad_range
|
|
|
|
mark_ok ;
|
|
clc
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Set the mark forward from the current mark.
|
|
;==========================================================================
|
|
|
|
forward_mark ;
|
|
clc
|
|
lda curr_mark
|
|
adc displacement
|
|
sta curr_mark
|
|
lda curr_mark+2
|
|
adc displacement+2
|
|
sta curr_mark+2
|
|
bcc check_range
|
|
|
|
greater_EOF ;
|
|
clv ;mark greater then current EOF!
|
|
rts ;bad mark bud!
|
|
|
|
;==========================================================================
|
|
;Set the file marker to an absolute position.
|
|
;==========================================================================
|
|
|
|
absolute ;
|
|
lda displacement
|
|
sta curr_mark
|
|
lda displacement+2
|
|
sta curr_mark+2
|
|
|
|
check_range ;
|
|
|
|
;==========================================================================
|
|
;Make sure the curr_mark =< EOF.
|
|
;==========================================================================
|
|
|
|
lda curr_mark+2
|
|
cmp curr_eof+2
|
|
beq check_low_word ;more checking to do
|
|
bcs greater_eof ;value is greater then EOF
|
|
rts ;carry clear no problem
|
|
|
|
check_low_word ;
|
|
lda curr_mark
|
|
cmp curr_eof
|
|
beq good_mark
|
|
bcs greater_eof ;value is greater then EOF
|
|
|
|
good_mark ;
|
|
clc
|
|
rts
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;Get_mark: This routine will return the file position marker.
|
|
;
|
|
;Created: may 23, 1987
|
|
;Modified: may 23, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Reference Number (2 Bytes)
|
|
; File Position (4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Reference Number (2 Bytes)
|
|
; File Position (4 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT get_mark
|
|
get_mark PROC
|
|
|
|
;==========================================================================
|
|
;Call standard setup routine.
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
|
|
;==========================================================================
|
|
;Get the current file marker out of the FCR data area
|
|
;==========================================================================
|
|
|
|
ldy #fcr_curr_mark
|
|
lda [pro_fcr_ptr],y
|
|
tax ;save low word
|
|
iny
|
|
iny
|
|
lda [pro_fcr_ptr],y
|
|
|
|
;==========================================================================
|
|
;Store the current file position into the user's parameter block.
|
|
;==========================================================================
|
|
|
|
ldy #pblk_17_pos+2 ;file position
|
|
sta [my_pblk_ptr],y
|
|
dey
|
|
dey
|
|
txa
|
|
sta [my_pblk_ptr],y
|
|
clc
|
|
jmp main_exit
|
|
ENDP
|
|
;==========================================================================
|
|
;Set_eof: This routine will set the EOF of a file.
|
|
;
|
|
;Created: jun 15, 1987
|
|
;Modified: jun 15, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Reference Number (2 Bytes)
|
|
; File Position (4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Reference Number (2 Bytes)
|
|
; Base (2 Bytes)
|
|
; 00 = Absolute
|
|
; 01 = Backward From EOF
|
|
; 02 = Forward From Current Mark
|
|
; 03 = Backward From Current Mark
|
|
; Displacement (4 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT set_eof
|
|
set_eof PROC
|
|
|
|
stz base ;set default to absolute
|
|
stz key_blk_changed
|
|
;==========================================================================
|
|
;Call standard setup routine.
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
beq class0 ;this is an old style call
|
|
|
|
;==========================================================================
|
|
;Now lets go and setup the base parameter please
|
|
;==========================================================================
|
|
|
|
ldy #pblk_18_base
|
|
jsr check_base
|
|
ldy #pblk_18_disp
|
|
bra main_entry
|
|
|
|
Class0 ;
|
|
ldy #pblk_18_odisp
|
|
|
|
main_entry ;
|
|
lda [my_pblk_ptr],y
|
|
sta displacement
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
sta displacement+2
|
|
|
|
;==========================================================================
|
|
;make sure the file is write enabled.
|
|
;==========================================================================
|
|
ldy #fcr_access
|
|
lda [my_fcr_ptr],y
|
|
and #ClrAllButAccess
|
|
cmp #write_access
|
|
bcs set_eof_ok
|
|
lda #invalid_access
|
|
bra set_eof_error
|
|
|
|
set_eof_ok ;
|
|
|
|
jsr chk_disk_protect
|
|
|
|
;==========================================================================
|
|
;Get the current end of file out of the FCR data area and call routine
|
|
;that will calculate the new eof. The new value for the EOF is returned
|
|
;in 'curr_mark'
|
|
;==========================================================================
|
|
|
|
;brk $B2
|
|
|
|
jsr calc_curr_mark
|
|
php ;save results
|
|
lda curr_mark
|
|
sta displacement
|
|
lda curr_mark+2
|
|
sta displacement+2
|
|
plp
|
|
|
|
;Following code changed 7/21/90 by Monte Benaresh
|
|
|
|
;Since setup_real_eof finds the last physically allocated EOF of
|
|
;the file, and since that number can be greater than the logical
|
|
;EOF (when pre-allocated blocks exist beyond the logical EOF) or
|
|
;less (when a trailing portion of the file is entirely sparse),
|
|
;we need to call setup_real_eof before deciding whether we need
|
|
;to cut blocks.
|
|
|
|
;bcc less_or_equal ;new EOF is =< current EOF
|
|
;bvc eof_greater ;new EOF is > current EOF
|
|
|
|
bcc calc_ok ;new EOF is =< current EOF
|
|
bvc calc_ok ;new EOF is > current EOF
|
|
|
|
;The following error code was changed from "parm_range_err"
|
|
;to "out_of_range". 1/22/91 CAE
|
|
bad_eof ;
|
|
lda #out_of_range ;position out of range
|
|
set_eof_error
|
|
sec
|
|
set_eof_exit
|
|
jmp main_exit
|
|
calc_ok
|
|
;next call added 8/6/90 by Monte Benaresh to fix bug
|
|
;introduced by change of 7/21/90
|
|
|
|
jsr flush_file ;force any dirty blocks to disk
|
|
bcs set_eof_error ;Major problems bud.
|
|
|
|
jsr setup_real_eof ;generate EOF based on allocation not logical
|
|
bcs set_eof_error ;Major problems bud.
|
|
|
|
;code added 7/21/90 by Monte Benaresh (see note above)
|
|
|
|
lda curr_eof+2 ;this points to last physical allocation
|
|
cmp displacement+2 ;determine whether we need to cut blocks
|
|
bcc eof_greater
|
|
bne less_or_equal ;this line added 8/8/90 by Monte Benaresh
|
|
|
|
lda curr_eof
|
|
cmp displacement
|
|
bcs less_or_equal
|
|
;
|
|
|
|
eof_greater
|
|
lda displacement+2
|
|
and #$FF00
|
|
bne bad_eof
|
|
save_eof
|
|
jsr update_fcr_eof
|
|
lda key_blk_changed ;Did the Key Block for the file change?
|
|
beq @no_key_changed
|
|
jsr flush_file ;update both the Bitmap and Directory please
|
|
bra set_eof_exit
|
|
@no_key_changed
|
|
jsr flush_io_buffer ;update the disk please
|
|
bra set_eof_exit ;we are out of here
|
|
|
|
;If we get here we know that the new EOF is equal to (easy) or less then
|
|
;(hard) the current ("real") EOF. If the EOF is less then the current eof then
|
|
;we must release blocks from the disk.
|
|
|
|
less_or_equal
|
|
jsr flush_file ;force any dirty blocks to disk
|
|
bcs set_eof_error ;Major problems bud.
|
|
|
|
;jsr setup_real_eof ;generate EOF based on allocation not logical
|
|
;bcs set_eof_error ;Major problems bud.
|
|
;last 2 lines not needed now -- Monte Benaresh, 7/21/90
|
|
|
|
lda displacement+2
|
|
cmp curr_eof+2
|
|
bne must_be_less ;the new eof is less then old eof
|
|
lda displacement
|
|
cmp curr_eof
|
|
;bne must_be_less
|
|
beq save_eof ;same as what caller wants, but save this EOF
|
|
;since it was calculated by setup_real_eof
|
|
;Monte Benaresh -- 7/21/90
|
|
|
|
;next 2 removed 7/21/90
|
|
;clc
|
|
;bra set_eof_exit ;nothing to do
|
|
|
|
must_be_less
|
|
|
|
;If we get here we know the new EOF is less then the old EOF so we must
|
|
;do the cut back.
|
|
|
|
;convert current eof into relative block number
|
|
;last_block := ((current_eof-1) DIV 512)
|
|
|
|
;last_block = $0000 to $7FFF
|
|
|
|
lda curr_eof
|
|
ora curr_eof+2 ;if zero DO NOT subtract one
|
|
beq no_sub1
|
|
|
|
lda curr_eof
|
|
bne ar1
|
|
dec curr_eof+2
|
|
ar1 dec curr_eof
|
|
|
|
no_sub1
|
|
lda curr_eof+1 ;convert EOF to blocks
|
|
lsr a
|
|
sta last_blk ;save block number of last block
|
|
beq save_eof ;file is already a seedling
|
|
|
|
;convert new_eof into relative block number
|
|
;new_last := ((displacement-1) DIV 512)
|
|
|
|
;new_last = $0000 to $7FFF
|
|
|
|
lda displacement
|
|
sta tran_cnt
|
|
lda displacement+2
|
|
sta tran_cnt+2
|
|
|
|
lda tran_cnt
|
|
ora tran_cnt+2 ;if zero DO NOT subtract one
|
|
beq no_sub
|
|
|
|
lda tran_cnt
|
|
bne ar2
|
|
dec tran_cnt+2
|
|
ar2 dec tran_cnt
|
|
|
|
no_sub
|
|
lda tran_cnt+1 ;convert EOF to blocks
|
|
lsr a
|
|
sta new_last ;save block number of last block
|
|
|
|
;WHILE last_blk <> new_last DO
|
|
|
|
while_loop
|
|
lda last_blk
|
|
cmp new_last
|
|
beq save_eof ;just exit with new EOF
|
|
|
|
;We now need to remove the last block in the file
|
|
|
|
jsr cut_block ;reduce blocks by one
|
|
bcs update_and_exit ;error occured
|
|
dec last_blk
|
|
bra while_loop
|
|
|
|
update_and_exit
|
|
pha
|
|
jsr update_fcr_eof
|
|
pla
|
|
sec
|
|
brl set_eof_error
|
|
|
|
;Update the FCR with the new EOF value. Also mark the FCR dirty
|
|
|
|
update_fcr_eof
|
|
ldy #fcr_eof
|
|
lda displacement ;store the NEW eof in the FCR
|
|
tax
|
|
sta curr_eof
|
|
sta [pro_fcr_ptr],y
|
|
iny
|
|
lda displacement+1
|
|
sta [pro_fcr_ptr],y
|
|
sta curr_eof+1
|
|
|
|
ldy #fcr_curr_eof ;update working EOF as well
|
|
txa
|
|
sta [pro_fcr_ptr],y
|
|
iny
|
|
lda displacement+1
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldy #fcr_status
|
|
lda [pro_fcr_ptr],y ;update file status word
|
|
ora #file_dirty ;we need to write to disk on close
|
|
sta [pro_fcr_ptr],y
|
|
|
|
;IF the new EOF is =< curr_mark THEN
|
|
; curr_mark := EOF
|
|
|
|
jsr setup_curr_mark
|
|
jsr fill_io_buf ;added 1/23/90 to fix "Bredon" sparse file shrink bug
|
|
bcc @filledUp
|
|
rts
|
|
@filledUp
|
|
lda curr_mark+2
|
|
cmp displacement+2
|
|
beq check_lower
|
|
bcs adjust_mark
|
|
bra adjust_buffer ;current_mark < new EOF
|
|
check_lower
|
|
lda curr_mark
|
|
cmp displacement
|
|
beq no_adjust
|
|
bcs adjust_mark
|
|
no_adjust
|
|
bra adjust_buffer
|
|
|
|
adjust_mark
|
|
lda displacement
|
|
sta curr_mark
|
|
lda displacement+2
|
|
sta curr_mark+2
|
|
jsr save_curr_mark ;update the FCR
|
|
adjust_buffer
|
|
jsr clr_to_boundary
|
|
clc
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Cut_block: This routine will remove the last block from the file.
|
|
;
|
|
;Input: last_blk (contains relative block number to delete. 0 thur n)
|
|
;
|
|
;output: A = error code if carry set.
|
|
;
|
|
; WARNING: last_blk must not point beyond the current
|
|
; structure of the file, even though that block num may be within
|
|
; the file's EOF. This could happen if a file has a trailing
|
|
; portion which is all sparse from a position <128K to a
|
|
; position >128K. In this case the file is stored as a
|
|
; sapling, not a tree, but owns a sparse area that is
|
|
; logically within the "tree" range. In such a case, last_blk
|
|
; must never be in that range when entering this routine.
|
|
;
|
|
|
|
cut_block
|
|
|
|
;The first thing we do is to convert last_blk into a mark value.
|
|
|
|
stz curr_mark
|
|
stz curr_mark+2
|
|
|
|
lda last_blk
|
|
asl a
|
|
sta curr_mark+1
|
|
|
|
jsr load_indexes ;load the I/O buffer correctly
|
|
bcc @no_error
|
|
rts
|
|
@no_error
|
|
|
|
;After we call data_blk_num we know that drvr_blk_num contains the data
|
|
;block that is to be removed from the file.
|
|
|
|
jsr get_data_num ;setup drvr_blk_num
|
|
ldx drvr_blk_num
|
|
beq gone ;sparse block
|
|
jsr dealloc_block ;remove the block please
|
|
bcc dec_gone
|
|
|
|
rts ;return error
|
|
dec_gone
|
|
jsr dec_blk_count ;blks_used := blks_used-1
|
|
gone
|
|
|
|
;IF (index_block = true) AND (deleted_entry > 1) THEN
|
|
; BEGIN
|
|
|
|
;if this is anything but a seedling, we must check whether it's time toÉ
|
|
;Érelease an index block and possibly change storage type
|
|
|
|
ldy #fcr_storage ;IF (index_block = true)
|
|
lda [pro_fcr_ptr],y
|
|
cmp #sapling_type
|
|
bcs index_true ;index_block = TRUE
|
|
rts ;we MUST be done
|
|
|
|
index_true
|
|
lda curr_mark+1 ;AND (deleted_entry > 1) THEN
|
|
lsr a
|
|
and #$00FF
|
|
cmp #$0002
|
|
bcc first_ELSE ;deleting first or second entry
|
|
|
|
; zero_index(deleted_blk) ; ;clear the entry from index block
|
|
; index_dirty := true ; ;and mark index dirty
|
|
|
|
;fall through if not on 1st or 2nd entry
|
|
not_sapling
|
|
jsr zero_one_index ;zero an entry in index blk
|
|
update_eof
|
|
clc
|
|
rts
|
|
|
|
; END
|
|
;ELSE
|
|
; IF (index_block = true) and (one_entry = true) and (storage = sapling) THEN
|
|
; BEGIN
|
|
; convert_sapling_to_seedling
|
|
; END
|
|
|
|
first_else ;we know index_block = true
|
|
cmp #$0001 ;did we just delete entry #0?
|
|
bcc second_else ;check tree case
|
|
|
|
ldy #fcr_storage
|
|
lda [pro_fcr_ptr],y
|
|
cmp #sapling_type ;(stoarge = sapling)?
|
|
bne not_sapling
|
|
|
|
jsr zero_one_index
|
|
jsr sapling_seed ;convert the sapling file to seedling
|
|
bcc update_eof
|
|
rts
|
|
|
|
; ELSE
|
|
; IF (index_block = true) and (one_entry = true) and (storage = tree) THEN
|
|
; BEGIN
|
|
|
|
second_else ;we are deleting the 1st entry in index blk
|
|
jsr remove_index ;remove the index and update master
|
|
bcc cont01
|
|
rts
|
|
|
|
cont01 ;did we just eliminate 2nd index block?
|
|
lda curr_mark+2
|
|
lsr a
|
|
and #$007F ;see if we are going to be a sapling
|
|
cmp #$0001 ;see if there is only one entry left
|
|
bne update_eof ;no conversion yet
|
|
|
|
jsr tree_sapling
|
|
bcc update_eof
|
|
rts
|
|
|
|
;===============END of CUT_BLOCK
|
|
|
|
;==========================================================================
|
|
;This routine will setup curr_eof with the EOF based on blocks allocated
|
|
;to the file instead of logical EOF. For example, an file can have an
|
|
;EOF of 0, but have hundreds of blocks allocated to it. This happens
|
|
;when a file is created with a request to pre-allocate space.
|
|
;Diagram: (A) (B) (C)
|
|
;
|
|
; | | $00 to $7F | $00 to $FF | $000 to $1FF |
|
|
; | | | | |
|
|
; | MUST BE ZERO |<- master ->|<- index ->|<- Byte index ->|
|
|
; |_______________|_____________|_______________|_________________|
|
|
; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
|
; |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
|
|
; | | | | |
|
|
; 3 2 2 4 1 6 0 8 0 0
|
|
;
|
|
; WARNING: Index blocks must be clean because they will be
|
|
; overwritten!
|
|
;
|
|
;==========================================================================
|
|
setup_real_eof
|
|
stz new_eof
|
|
stz new_eof+2 ;init new eof
|
|
|
|
ldy #fcr_storage
|
|
lda [pro_fcr_ptr],y
|
|
cmp #tree_type ;(storage = tree)?
|
|
beq @calc_tree
|
|
cmp #sapling_type
|
|
beq @calc_sapling
|
|
clc
|
|
rts ;seedling works OK
|
|
@calc_tree
|
|
ldx master_ptr ;setup pointer to master index block
|
|
ldy master_ptr+2
|
|
jsr get_last_index ;get the lndex to the last index block out of master index
|
|
clc ;A=index $00 thru $7F, X = block number.
|
|
asl A ;double index
|
|
sta new_eof+2
|
|
|
|
txa ;load block if needed
|
|
ldy #index_blk_num
|
|
cmp [pro_fcr_ptr],y ;is the block already loaded?
|
|
beq @calc_sapling
|
|
|
|
jsr load_index ;load in the index block
|
|
;bcc @calc_sapling
|
|
bcc @index_ok ;changed 8/7/90 by Monte Benaresh
|
|
|
|
rts ;sorry friend no EOF change today!
|
|
@index_ok ;next lines added 8/7/90 by Monte Benaresh
|
|
ldy #index_blk_num
|
|
lda drvr_blk_num ;save the block num of the index block
|
|
sta [pro_fcr_ptr],y
|
|
@calc_sapling
|
|
ldx index_ptr ;get address of the index block in memory
|
|
ldy index_ptr+2
|
|
jsr get_last_index ;get the lndex to the last data block out of index block
|
|
clc ;A=index $00 thru $FF, X is not used!
|
|
asl A ;double index
|
|
ora new_eof+1 ;set the new value
|
|
sta new_eof+1
|
|
|
|
clc
|
|
lda new_eof
|
|
adc #blk_size
|
|
|
|
;change added 6/21/90 by Monte Benaresh
|
|
|
|
;reverted 7/21/90 by Monte Benaresh because the "fix" could cause new_eof
|
|
;to point to a sparse portion of the file that was out of the range of
|
|
;the current structure (e.g., beyond the 128K mark in a sapling), a
|
|
;condition which is illegal for the cut_block routine which gets called
|
|
;by set_eof
|
|
|
|
sta curr_eof
|
|
lda new_eof+2
|
|
adc #$0000
|
|
sta curr_eof+2 ;update the global EOF that is used by SET_EOF
|
|
clc
|
|
rts
|
|
|
|
;==========================================================================
|
|
;Get_Last_index will walk an index block looking for the last valid entry.
|
|
;
|
|
;input: X&Y = pointer to index buffer
|
|
;
|
|
;output: A = index offset 0 thru $FF
|
|
; X = block number
|
|
|
|
get_last_index
|
|
stx temp2_ptr ;setup pointer to lower half of the buffer
|
|
sty temp2_ptr+2
|
|
clc
|
|
txa
|
|
adc #$0100 ;point to high half of the index block
|
|
sta temp3_ptr
|
|
tya
|
|
adc #$0000
|
|
sta temp3_ptr+2
|
|
|
|
ldy #$00FF ;start from end of index block
|
|
@loop
|
|
longa off
|
|
sep #$20
|
|
lda [temp3_ptr],y ;grab the high block number
|
|
xba ;put high block number in upper byte
|
|
lda [temp2_ptr],y ;get the low block number
|
|
longa on
|
|
rep #$20
|
|
tax ;check for zero
|
|
bne @done ;we have the block number
|
|
dey
|
|
bpl @loop ;try the next location
|
|
sec
|
|
rts
|
|
@done
|
|
tya
|
|
clc ;A=Index, X = block number
|
|
rts
|
|
|
|
;==========================================================================
|
|
;This routine will zero out one entry in the master index block. It will
|
|
;also mark the index block as being dirty and decrement the block count
|
|
|
|
remove_index
|
|
ldy #index_blk_num ;is the index block sparse?
|
|
lda [pro_fcr_ptr],y
|
|
bne @not_sparse ;there is an index block
|
|
rts
|
|
|
|
@not_sparse jsr dec_blk_count
|
|
|
|
lda curr_mark+2
|
|
lsr a
|
|
and #$007F
|
|
tay
|
|
ora #$0100
|
|
tax
|
|
|
|
longa off
|
|
sep #$20
|
|
lda [master_ptr],y
|
|
sta drvr_blk_num ;save the one we are deleting
|
|
|
|
lda #$00
|
|
sta [master_ptr],y ;zero the deleted entry please
|
|
txy
|
|
|
|
lda [master_ptr],y
|
|
sta drvr_blk_num+1 ;high byte of one to delete
|
|
|
|
lda #$00
|
|
sta [master_ptr],y
|
|
longa on
|
|
rep #$20
|
|
|
|
ldy #fcr_status
|
|
lda [pro_fcr_ptr],y
|
|
ora #master_dirty+file_dirty
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldx drvr_blk_num ;remove the index block please
|
|
jsr dealloc_block
|
|
rts
|
|
|
|
;==========================================================================
|
|
;This routine will zero out one entry in the current index block. It will
|
|
;also mark the index block as being dirty
|
|
;==========================================================================
|
|
|
|
zero_one_index
|
|
ldy #index_blk_num ;is the index block sparse?
|
|
lda [pro_fcr_ptr],y
|
|
bne @not_sparse ;there is an index block
|
|
rts
|
|
|
|
@not_sparse lda curr_mark+1
|
|
lsr a
|
|
and #$00FF
|
|
tay
|
|
ora #$0100
|
|
tax
|
|
longa off
|
|
sep #$20
|
|
lda #$00
|
|
sta [index_ptr],y ;zero the deleted entry please
|
|
txy
|
|
sta [index_ptr],y
|
|
longa on
|
|
rep #$20
|
|
|
|
ldy #fcr_status
|
|
lda [pro_fcr_ptr],y
|
|
ora #index_dirty+file_dirty
|
|
sta [pro_fcr_ptr],y
|
|
rts
|
|
|
|
EXPORT dec_blk_count
|
|
dec_blk_count ; reduce number of blocks used by a file by one
|
|
|
|
ldy #fcr_blks_used
|
|
lda [pro_fcr_ptr],y
|
|
dec a
|
|
|
|
;next 2 checks removed 8/5/90 by Monte Benaresh:
|
|
; The bmi is wrong since a 16-megabyte file can have
|
|
; $8041 blocks,
|
|
;
|
|
; The beq doesn't do anything except return without updating
|
|
; the directory.
|
|
|
|
;beq bad_news
|
|
;bmi bad_news
|
|
|
|
sta [pro_fcr_ptr],y
|
|
lda #dirEntry_dirty ;the directory entry needs updating when flushed
|
|
jsr set_fcr_status
|
|
bad_news
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;sapling_seed: This routine will convert a sapling file into a seedling
|
|
; file. (I hope) Of course in the long run it will do the
|
|
; conversion.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; pro_fcr_ptr (points to VCR local data)
|
|
; index_ptr (MUST point to the index block)
|
|
;
|
|
;Output: A = error code if carry set otherwise undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; pro_fcr_ptr
|
|
;
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT sapling_seed
|
|
sapling_seed PROC
|
|
|
|
;==========================================================================
|
|
;Grab the first entry out of the index block. This is to become the new
|
|
;key pointer for the file.
|
|
;==========================================================================
|
|
|
|
lda [index_ptr]
|
|
sta drvr_blk_num
|
|
ldy #blk_size-$0100
|
|
lda [index_ptr],y
|
|
sta drvr_blk_num+1
|
|
|
|
lda #$0000 ;now delete the block from the index
|
|
sta [index_ptr]
|
|
sta [index_ptr],y ;get the high byte
|
|
|
|
ldx drvr_blk_num
|
|
jsr update_key_blk
|
|
|
|
ldy #fcr_storage
|
|
lda #seedling_type
|
|
tax
|
|
sta [pro_fcr_ptr],y ;change storage type to seedling
|
|
|
|
ldy #fcr_entry_type
|
|
lda [pro_fcr_ptr],y
|
|
cmp #resource_type
|
|
beq is_res_type1
|
|
txa
|
|
sta [pro_fcr_ptr],y
|
|
is_res_type1 ;
|
|
jsr dec_blk_count ;reduce count by one
|
|
|
|
lda #index_clean
|
|
jsr clr_fcr_status ;do not write a index block
|
|
|
|
ldy #index_blk_num
|
|
lda [pro_fcr_ptr],y ;block number for index block
|
|
tax ;used by deallocate
|
|
beq exit
|
|
lda #$0000
|
|
sta [pro_fcr_ptr],y ;zero the block number
|
|
jsr dealloc_block ;remove the block please
|
|
bcc exit
|
|
rts
|
|
|
|
exit ;
|
|
stz curr_mark ;reload the correct blocks
|
|
stz curr_mark+2
|
|
jsr fill_io_buf
|
|
rts
|
|
|
|
;==========================================================================
|
|
;We need to see if this is a resource file. IF it not then we need to
|
|
;update both the key block and file id fields. Otherwise we only adjust
|
|
;the key block field.
|
|
;
|
|
;input: X = new key block
|
|
;==========================================================================
|
|
EXPORT update_key_blk
|
|
update_key_blk ;
|
|
ldy #fcr_file_id
|
|
lda [pro_fcr_ptr],y
|
|
ldy #fcr_key_blk ;update the key block pointer
|
|
cmp [pro_fcr_ptr],y
|
|
bne only_key_blk ;update only the key block
|
|
|
|
txa
|
|
ldy #fcr_file_id
|
|
sta [pro_fcr_ptr],y
|
|
|
|
only_key_blk ;
|
|
txa
|
|
ldy #fcr_key_blk
|
|
sta [pro_fcr_ptr],y
|
|
inc key_blk_changed ;indicate that the key block has changed
|
|
rts
|
|
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;tree_sapling: This routine will convert a tree file into a sapling
|
|
; file. (I hope) Of course in the long run it will do the
|
|
; conversion.
|
|
;
|
|
;Input: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
; pro_fcr_ptr (points to VCR local data)
|
|
; master_ptr (MUST point to the master block)
|
|
;
|
|
;Output: A = error code if carry set otherwise undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; pro_fcr_ptr
|
|
;
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT tree_sapling
|
|
tree_sapling PROC
|
|
|
|
;==========================================================================
|
|
;Grab the first entry out of the master index block. This is to become the
|
|
;new key pointer for the file.
|
|
;==========================================================================
|
|
|
|
stz curr_mark ;force mark to zero for correct
|
|
stz curr_mark+2 ;loading of index blocks
|
|
|
|
jsr fill_io_buf ;make sure the I/O buffer looks Ok
|
|
bcc have_index
|
|
rts
|
|
|
|
have_index ;
|
|
lda [master_ptr]
|
|
sta drvr_blk_num
|
|
ldy #blk_size-$0100
|
|
lda [master_ptr],y
|
|
and #$00FF ;clear any garbage left
|
|
sta drvr_blk_num+1
|
|
|
|
lda #$0000
|
|
sta [master_ptr] ;clear the last entry please
|
|
sta [master_ptr],y
|
|
|
|
jsr dec_blk_count
|
|
|
|
ldx drvr_blk_num
|
|
jsr update_key_blk
|
|
|
|
ldy #fcr_storage
|
|
lda #sapling_type
|
|
tax
|
|
sta [pro_fcr_ptr],y ;change storage type to sapling
|
|
|
|
ldy #fcr_entry_type
|
|
lda [pro_fcr_ptr],y
|
|
cmp #resource_type
|
|
beq is_res_type2
|
|
txa
|
|
sta [pro_fcr_ptr],y
|
|
|
|
is_res_type2 ;
|
|
lda #master_clean
|
|
jsr clr_fcr_status ;do not write a index block
|
|
|
|
ldy #master_blk_num
|
|
lda [pro_fcr_ptr],y ;block number for master index block
|
|
tax ;used by deallocate
|
|
beq exit
|
|
lda #$0000
|
|
sta [pro_fcr_ptr],y ;zero the block number
|
|
jsr dealloc_block ;remove the block please
|
|
rts
|
|
|
|
exit ;
|
|
clc
|
|
rts
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;Get_eof: This routine will return the current EOF for an open file.
|
|
;
|
|
;Created: may 23, 1987
|
|
;Modified: may 23, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Reference Number (2 Bytes)
|
|
; EOF (4 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Reference Number (2 Bytes)
|
|
; EOF (4 Bytes)
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT get_eof
|
|
get_eof PROC
|
|
|
|
;==========================================================================
|
|
;Call standard setup routine.
|
|
;==========================================================================
|
|
|
|
jsr setup_params
|
|
|
|
;==========================================================================
|
|
;Get the current end of file out of the FCR data area
|
|
;==========================================================================
|
|
|
|
ldy #fcr_curr_eof
|
|
lda [pro_fcr_ptr],y
|
|
tax ;save low word
|
|
iny
|
|
iny
|
|
lda [pro_fcr_ptr],y
|
|
|
|
ldy #pblk_19_eof+2
|
|
sta [my_pblk_ptr],y
|
|
dey
|
|
dey
|
|
txa
|
|
sta [my_pblk_ptr],y
|
|
clc
|
|
jmp main_exit
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;Get_dir_entry: This routine will return a single entry from a directory.
|
|
;
|
|
;
|
|
;Created: Nov 10, 1987
|
|
;Modified: Nov 10, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; find_file
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Reference number (2 Bytes)
|
|
; RESERVED (2 Bytes)
|
|
; Base (2 Bytes)
|
|
; $0000 = Absolute
|
|
; $0001 = Forward releative
|
|
; $0002 = Backward relative
|
|
; Displacement (2 Bytes)
|
|
; Pointer to name buffer (4 Bytes)
|
|
; Entry Number (2 Bytes) Absolute entry read
|
|
; File Type (2 Bytes)
|
|
; EOF (4 Bytes)
|
|
; Blocks Used (4 Bytes)
|
|
; Create Date/Time (8 Bytes: Misc. Tools Format)
|
|
; Mod Date/Time (8 Bytes: Misc. Tools Format)
|
|
; Access (2 Bytes)
|
|
; Aux Type (4 Bytes)
|
|
; File System Id (2 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes: Minimum = 5)
|
|
; Reference Number (2 Bytes)
|
|
; RESERVED (2 Bytes)
|
|
; Base (2 Bytes)
|
|
; $0000 = Absolute
|
|
; $0001 = Forward releative
|
|
; $0002 = Backward relative
|
|
; Displacement (2 Bytes)
|
|
; Pointer to name buffer (4 Bytes)
|
|
; Entry Number (2 Bytes) Absolute entry read
|
|
; File Type (2 Bytes)
|
|
; EOF (4 Bytes)
|
|
; Blocks Used (4 Bytes)
|
|
; Create Date/Time (8 Bytes: Misc. Tools Format)
|
|
; Mod Date/Time (8 Bytes: Misc. Tools Format)
|
|
; Access (2 Bytes)
|
|
; Aux Type (4 Bytes)
|
|
; File System Id (2 Bytes)
|
|
; Option List Pointer (4 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT get_dir_entry
|
|
get_dir_entry PROC
|
|
import gde_temp
|
|
|
|
jsr setup_params ;general setup routine
|
|
php ;save status
|
|
lda my_pblk_ptr+2
|
|
sta temp2_ptr+2
|
|
clc
|
|
lda my_pblk_ptr
|
|
sta temp2_ptr ;save a pointer for extended bit
|
|
adc #$0004 ;pass ref # and Reserved fields
|
|
sta my_pblk_ptr
|
|
bcc not_high
|
|
inc my_pblk_ptr+2
|
|
not_high ;
|
|
|
|
plp
|
|
bne class1 ;this is a new call
|
|
|
|
lda #$000E ;make PCount = to class 0 normal
|
|
sta pcount
|
|
|
|
class1 ;
|
|
ldy #fcr_storage ;make sure this is a directory
|
|
lda [pro_fcr_ptr],y
|
|
cmp #subdir_type
|
|
bcs type_ok
|
|
|
|
sec
|
|
lda #bad_file_format
|
|
jmp main_exit
|
|
|
|
type_ok ;
|
|
lda [my_pblk_ptr] ;load the base field
|
|
sta base ;save user's base value
|
|
cmp #gde_max_base+1
|
|
bcc base_good
|
|
|
|
lda #parm_range_err
|
|
gde_exit ;
|
|
jmp main_exit
|
|
|
|
directory_err ;
|
|
sec
|
|
lda #dir_error ;report error to user
|
|
bra gde_exit
|
|
|
|
base_good ;
|
|
|
|
ldy #pblk_1c_name
|
|
lda [my_pblk_ptr],y
|
|
sta temp_ptr ;save the pointer
|
|
iny
|
|
iny
|
|
lda [my_pblk_ptr],y
|
|
and #$00FF ;clear the garbage
|
|
sta temp_ptr+2
|
|
|
|
ldy #pblk_1c_disp ;offset to displacement
|
|
lda [my_pblk_ptr],y
|
|
sta displacement
|
|
ora base ;is base and displacement zero?
|
|
bne nothing_special
|
|
|
|
jsr reset_gde ;reset the call please
|
|
|
|
nothing_special ;
|
|
ldy #pblk_1c_extend ;clear the extended word
|
|
lda #$0000
|
|
sta [temp2_ptr],y
|
|
|
|
jsr standard_req
|
|
|
|
ldy #gde_curr_blk ;have we loaded a directory yet?
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num
|
|
bne dir_loaded ;yes.
|
|
|
|
ldy #fcr_key_blk ;key block of the directory
|
|
lda [pro_fcr_ptr],y
|
|
sta drvr_blk_num
|
|
jsr read_gde_blk ;read in a block please
|
|
bcs gde_exit ;bad news bud
|
|
|
|
lda [index_ptr] ;make sure this is a directory
|
|
bne directory_err
|
|
|
|
ldy #$0004 ;index to storage type
|
|
lda [index_ptr],y
|
|
tax
|
|
and #$00F0 ;check the storage type
|
|
cmp #subdir_header
|
|
bcc directory_err ;a bad directory
|
|
txa
|
|
and #$000F ;check the name length
|
|
beq directory_err
|
|
|
|
ldy #header_file_cnt
|
|
lda [index_ptr],y ;save the header file count
|
|
ldy #gde_tot_files
|
|
sta [pro_fcr_ptr],y
|
|
|
|
ldy #gde_curr_blk ;save the current block also
|
|
lda drvr_blk_num
|
|
sta [pro_fcr_ptr],y
|
|
|
|
lda #$0004 ;save gde_offset
|
|
ldy #gde_offset
|
|
sta [pro_fcr_ptr],y
|
|
|
|
dir_loaded ;
|
|
ldy #gde_offset
|
|
lda [pro_fcr_ptr],y ;setup the current offset
|
|
sta entry_offset
|
|
|
|
lda base ;see if we are returning total files
|
|
tax
|
|
ora displacement
|
|
bne not_first
|
|
|
|
jsr send_tot_files
|
|
clc
|
|
jmp main_exit ;exit back to caller
|
|
|
|
not_first ;
|
|
ldy #gde_entry_num
|
|
lda [pro_fcr_ptr],y
|
|
sta math_temp ;current entry number
|
|
tay
|
|
|
|
txa ;restore base
|
|
beq absolute ;do absolute entry please
|
|
dec a
|
|
beq forward ;do forward relative please
|
|
|
|
backward ;
|
|
sec
|
|
tya ;get the last entry we looked at
|
|
sbc displacement ;entry that we want
|
|
bcc end_dir_err
|
|
bne find_entry ;go find the entry please
|
|
end_dir_err ;
|
|
sec
|
|
lda #end_of_dir
|
|
jmp main_exit
|
|
|
|
absolute ;
|
|
lda displacement ;get this entry please
|
|
bra to_forward
|
|
forward ;
|
|
clc
|
|
tya ;get the current entry please
|
|
adc displacement
|
|
bcs end_dir_err ;over flow!
|
|
to_forward ;
|
|
ldy #gde_tot_files ;see if we need to look
|
|
cmp [pro_fcr_ptr],y
|
|
beq find_entry
|
|
bcs end_dir_err
|
|
|
|
find_entry ;
|
|
ldy entry_offset ;pre-load the entry offset
|
|
sta find_this_entry ;save entry number to find
|
|
cmp math_temp ;compare to current entry
|
|
beq send_entry ;we have the correct entry
|
|
bcc search_backward ;do a backward search
|
|
|
|
search_forward ;
|
|
cpy #$01FF
|
|
beq get_forward_blk ;go read the next block please
|
|
jsr add_entry_len
|
|
forward_loop ;
|
|
lda [index_ptr],y ;load the entry please
|
|
and #$00F0 ;is this entry active?
|
|
beq search_forward ;look at the next entry please
|
|
sty entry_offset ;save the offset
|
|
inc math_temp ;bump the current entry by one
|
|
lda math_temp
|
|
cmp find_this_entry ;is this the correct entry
|
|
bne search_forward
|
|
bra send_entry
|
|
get_forward_blk ;
|
|
ldy #$0002 ;index to forward link
|
|
lda [index_ptr],y
|
|
beq end_dir_err ;sorry no more directory blocks
|
|
sta drvr_blk_num
|
|
jsr read_gde_blk ;load the block please
|
|
ldy #$0004 ;index to first entry
|
|
bcc forward_loop
|
|
jmp main_exit ;tell user about the error
|
|
|
|
search_backward ;
|
|
cpy #$0004
|
|
beq get_back_blk ;go read the prev block please
|
|
jsr sub_entry_len
|
|
backward_loop ;
|
|
lda [index_ptr],y ;load the entry please
|
|
and #$00F0 ;is this entry active?
|
|
beq search_backward ;look at the next entry please
|
|
sty entry_offset ;save the offset
|
|
dec math_temp ;bump the current entry by one
|
|
lda math_temp
|
|
cmp find_this_entry ;is this the correct entry
|
|
bne search_backward
|
|
bra send_entry
|
|
get_back_blk ;
|
|
lda [index_ptr]
|
|
beq end_dir_err ;sorry no more directory blocks
|
|
sta drvr_blk_num
|
|
jsr read_gde_blk ;load the block please
|
|
ldy #$01FF ;index to first entry
|
|
bcc backward_loop
|
|
jmp main_exit ;tell user about the error
|
|
|
|
send_entry ;
|
|
ldy #gde_curr_blk
|
|
lda drvr_blk_num
|
|
sta [pro_fcr_ptr],y ;save the current dir block
|
|
ldy #gde_entry_num
|
|
lda math_temp
|
|
sta [pro_fcr_ptr],y ;save the current entry number
|
|
ldy #gde_offset
|
|
lda entry_offset
|
|
sta [pro_fcr_ptr],y ;save the entry offset
|
|
tay
|
|
|
|
stz res_storage ;default is type is not resource
|
|
lda [index_ptr],y ;get the storage type
|
|
and #$00F0
|
|
cmp #resource_type
|
|
bne not_extended
|
|
ldy #pblk_1c_extend
|
|
lda #$8000
|
|
sta [temp2_ptr],y
|
|
sta res_storage ;type of file is extended
|
|
|
|
not_extended ;
|
|
;
|
|
;Now move the entry into the user's data area
|
|
;
|
|
lda entry_offset
|
|
clc
|
|
adc index_ptr
|
|
sta drvr_buf_ptr
|
|
lda #$0000
|
|
adc index_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
jsr move_dir_entry ;move the entry to 'one_entry'
|
|
|
|
lda #buff_too_small ;assume user screwed up
|
|
sta math_temp
|
|
|
|
lda [temp_ptr]
|
|
cmp #$0004
|
|
bcc no_name ;sorry no name avail
|
|
|
|
ldy #$0002 ;store the name length
|
|
lda alloc_entry
|
|
sta [temp_ptr],y
|
|
clc
|
|
adc #$0004
|
|
cmp [temp_ptr] ;load the buffer size
|
|
beq len_ok ;length is ok
|
|
bcc len_ok
|
|
;
|
|
;(BufferSize - 4)
|
|
; sec
|
|
|
|
lda [temp_ptr] ;use the user's buf length
|
|
sbc #$0004
|
|
beq no_name ;a buffer size of 4 was used so store length only.
|
|
bcc no_name ;do not send any of the name
|
|
bra do_name ;use the user's length as count to send.
|
|
len_ok ;
|
|
stz math_temp ;no error
|
|
lda alloc_entry ;number of bytes to move
|
|
;
|
|
;Code added to fix a bug cataloging a bad disk.
|
|
;
|
|
bne do_name
|
|
lda #dir_error ;the directory entry is bad
|
|
sta math_temp
|
|
bra end_gde ;exit with the error please
|
|
do_name
|
|
tay ;number of bytes to send
|
|
|
|
clc ;make pointer to ascii string
|
|
lda temp_ptr
|
|
adc #$0003
|
|
sta temp_ptr
|
|
lda temp_ptr+2
|
|
adc #$0000
|
|
sta temp_ptr+2
|
|
|
|
stz case_bits ;all upper case is the defalut
|
|
lda fst_attr ;if the high bit is set skip Upper/Lower stuff
|
|
bmi @its_upper
|
|
|
|
lda one_entry+version_index
|
|
bpl @its_upper
|
|
asl a ;remove the case ON/OFF bit
|
|
sta case_bits ;set the case bits for this file.
|
|
@its_upper
|
|
sty gde_temp ;save the count please
|
|
|
|
ldy #$0001 ;start at the front
|
|
longa off
|
|
sep #$20
|
|
looper
|
|
lda one_entry,y
|
|
rep #$20
|
|
rol case_bits ;see if this char is lower case
|
|
sep #$20
|
|
bcc @its_upper
|
|
|
|
if AllowLCPeriods then ;added 7-Aug-91 DAL
|
|
cmp #'.'
|
|
bne @not_lc_period
|
|
lda #0 ;let it ORA our 0 into a $20 (blank)
|
|
@not_lc_period
|
|
endif ;end 7-Aug-91 DAL
|
|
|
|
ora #$20 ;set the lower case bit please
|
|
@its_upper
|
|
sta [temp_ptr],y
|
|
cpy gde_temp
|
|
beq @we_done
|
|
iny
|
|
bra looper ;move the name to the user's buffer
|
|
@we_done
|
|
longa on
|
|
rep #$20
|
|
|
|
lda math_temp
|
|
cmp #buff_too_small ;if the error was buffer too small then leave it.
|
|
beq no_name
|
|
|
|
stz math_temp ;reset the error code please
|
|
no_name
|
|
sec ;adjust the pcount please
|
|
lda pcount
|
|
sbc #$0005
|
|
sta pcount
|
|
beq end_gde
|
|
jsr send_gde_stuff ;send the info that the user wants
|
|
end_gde ;
|
|
lda math_temp ;was there an error?
|
|
cmp #$0001
|
|
jmp main_exit
|
|
|
|
send_gde_stuff ;
|
|
lda my_pblk_ptr
|
|
sta temp_ptr
|
|
lda my_pblk_ptr+2
|
|
sta temp_ptr+2
|
|
|
|
ldy #pblk_1c_entry ;return the absolute entry
|
|
lda find_this_entry
|
|
sta [temp_ptr],y
|
|
dec pcount
|
|
beq to_end_send_gde
|
|
|
|
ldy #pblk_1c_ftype
|
|
lda one_entry+file_type_index
|
|
and #$00FF
|
|
sta [temp_ptr],y
|
|
dec pcount
|
|
beq to_end_send_gde
|
|
|
|
lda res_storage ;is the file extended?
|
|
bpl @not_extended ;no it is not
|
|
jsr load_ext_blk ;load in the extended block please
|
|
@not_extended
|
|
jsr send_data_eof ;send the eof for data fork
|
|
|
|
dec pcount
|
|
beq to_end_send_gde
|
|
|
|
jsr send_data_blks ;send the blks_used for data fork
|
|
|
|
dec pcount
|
|
beq to_end_send_gde
|
|
|
|
ldx one_entry+create_index
|
|
ldy one_entry+create_index+2
|
|
jsr unpack_time
|
|
ldy #pblk_1c_create
|
|
jsr send_time
|
|
dec pcount
|
|
beq to_end_send_gde
|
|
|
|
ldx one_entry+last_mod_index
|
|
ldy one_entry+last_mod_index+2
|
|
jsr unpack_time
|
|
ldy #pblk_1c_mod
|
|
jsr send_time
|
|
dec pcount
|
|
beq to_end_send_gde
|
|
|
|
lda one_entry+access_index
|
|
and #$00E7
|
|
ldy #pblk_1c_access
|
|
sta [temp_ptr],y
|
|
dec pcount
|
|
beq to_end_send_gde
|
|
|
|
lda one_entry+aux_type_index
|
|
ldy #pblk_1c_aux
|
|
sta [temp_ptr],y
|
|
lda #$0000
|
|
iny
|
|
iny
|
|
sta [temp_ptr],y
|
|
dec pcount ;does the user want FST ID?
|
|
to_end_send_gde
|
|
beq end_send_gde ;No
|
|
|
|
lda #pro_id
|
|
ldy #pblk_1c_id
|
|
sta [temp_ptr],y
|
|
|
|
dec pcount ;Skip the option list please
|
|
beq end_send_gde
|
|
;==========================================================================
|
|
; We now store the ProDOS FST ID in the 5th byte of the option list buffer
|
|
;==========================================================================
|
|
|
|
ldy #pblk_1c_opt ;index to option list pointer
|
|
lda [temp_ptr],y ;get the address of the option list buffer
|
|
tax
|
|
iny
|
|
iny
|
|
lda [temp_ptr],y
|
|
tay
|
|
bne @save_fst_id
|
|
txa
|
|
beq @skip_save
|
|
@save_fst_id
|
|
pei temp_ptr ;save the working temp_ptr since I am going to use it
|
|
pei temp_ptr+2 ;to handle the option list pointer
|
|
|
|
stx temp_ptr
|
|
sty temp_ptr+2
|
|
;
|
|
;Now I need to verify the option list length. I need at least 6 bytes.
|
|
;
|
|
lda [temp_ptr] ;get the length of the option list
|
|
cmp #$0004 ;is the minimum count OK
|
|
bcs @min_ok ;the user has the min
|
|
|
|
lda #parm_range_err ;store the error
|
|
bra option_list_err
|
|
@min_ok
|
|
tax ;save the count for data area check
|
|
lda #$0002 ;length of the ProDOS FST ID.
|
|
tay
|
|
sta [temp_ptr],y ;save the number of bytes stored
|
|
txa
|
|
cmp #$0006
|
|
bcs @size_fine
|
|
|
|
lda #buff_too_small ;store the error
|
|
bra option_list_err
|
|
@size_fine
|
|
iny
|
|
iny
|
|
lda #pro_id
|
|
sta [temp_ptr],y
|
|
;new code added 2/13/91 CAE
|
|
txa
|
|
cmp #6+32 ;is buffer big enough to hold HFS Finder Info?
|
|
bcc @no_info ;no
|
|
lda res_storage ;is the file extended?
|
|
bpl @no_info ;no - so no HFS info
|
|
jsr get_hfs_info ;yes - so get the HFS info if we have it
|
|
@no_info
|
|
;end of new code
|
|
pla
|
|
sta temp_ptr+2 ;restore
|
|
pla
|
|
sta temp_ptr
|
|
@skip_save
|
|
dec pcount ;does the user want resource eof?
|
|
beq end_send_gde ;no
|
|
|
|
jsr send_res_eof ;send the resource EOF please
|
|
|
|
dec pcount ;does the user want resource blocks?
|
|
beq end_send_gde ;no
|
|
jsr send_res_blks
|
|
|
|
end_send_gde
|
|
rts
|
|
|
|
option_list_err
|
|
sta math_temp
|
|
pla
|
|
sta temp_ptr+2 ;restore
|
|
pla
|
|
sta temp_ptr
|
|
rts
|
|
|
|
send_data_eof
|
|
lda res_storage ;is the file extended?
|
|
bpl @not_extended
|
|
|
|
ldy #$0005 ;index to EOF field
|
|
lda [drvr_buf_ptr],y
|
|
sta one_entry+eof_index
|
|
iny
|
|
lda [drvr_buf_ptr],y
|
|
sta one_entry+eof_index+1
|
|
@not_extended
|
|
ldy #pblk_1c_eof
|
|
lda one_entry+eof_index
|
|
sta [temp_ptr],y
|
|
iny
|
|
iny
|
|
lda one_entry+eof_index+2
|
|
and #$00FF
|
|
sta [temp_ptr],y
|
|
rts
|
|
|
|
send_data_blks
|
|
lda res_storage ;is the file extended?
|
|
bpl @not_extended
|
|
|
|
ldy #$0003 ;index to blocks used field
|
|
lda [drvr_buf_ptr],y
|
|
sta one_entry+blks_used_index
|
|
|
|
@not_extended
|
|
lda one_entry+blks_used_index
|
|
ldy #pblk_1c_blks
|
|
sta [temp_ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [temp_ptr],y ;Zero the high word
|
|
rts
|
|
|
|
send_res_eof
|
|
lda res_storage ;is the file extended?
|
|
bpl @not_extended
|
|
|
|
ldy #$0105 ;index to eof field
|
|
lda [drvr_buf_ptr],y
|
|
tax ;low word of eof
|
|
iny
|
|
iny
|
|
lda [drvr_buf_ptr],y
|
|
and #$00FF
|
|
tay ;upper word of EOF
|
|
txa ;save low word in 'A'
|
|
tyx ;save upper word in 'X'
|
|
bra @send_res_eof
|
|
|
|
@not_extended lda #$0000 ;eof is nothing
|
|
tax
|
|
@send_res_eof
|
|
ldy #pblk_1c_res_eof
|
|
sta [temp_ptr],y
|
|
iny
|
|
iny
|
|
txa
|
|
sta [temp_ptr],y ;save upper word please
|
|
rts
|
|
|
|
send_res_blks
|
|
lda res_storage ;is the file extended?
|
|
bpl @not_extended
|
|
|
|
ldy #$0103 ;index to blocks used field
|
|
lda [drvr_buf_ptr],y
|
|
bra @send_res_blks
|
|
|
|
@not_extended lda #$0000 ;no blocks
|
|
|
|
@send_res_blks
|
|
ldy #pblk_1c_res_blks
|
|
sta [temp_ptr],y
|
|
iny
|
|
iny
|
|
lda #$0000
|
|
sta [temp_ptr],y ;save upper word please
|
|
rts
|
|
|
|
add_entry_len
|
|
tya
|
|
clc
|
|
adc #entry_length
|
|
tay
|
|
rts
|
|
|
|
sub_entry_len
|
|
tya
|
|
sec
|
|
sbc #entry_length
|
|
tay
|
|
rts
|
|
|
|
send_tot_files ;
|
|
lda pcount ;is there room
|
|
cmp #$0006
|
|
bcc end_tot
|
|
|
|
ldy #gde_tot_files
|
|
lda [pro_fcr_ptr],y ;get the total number of entries
|
|
ldy #pblk_1c_entry
|
|
sta [my_pblk_ptr],y
|
|
end_tot
|
|
rts
|
|
|
|
reset_gde
|
|
lda #$0000 ;reset gde by zero all data
|
|
ldy #gde_entry_num
|
|
sta [pro_fcr_ptr],y
|
|
ldy #gde_offset
|
|
sta [pro_fcr_ptr],y
|
|
ldy #gde_curr_blk
|
|
sta [pro_fcr_ptr],y
|
|
ldy #gde_tot_files
|
|
sta [pro_fcr_ptr],y
|
|
rts
|
|
|
|
read_gde_blk
|
|
lda index_ptr ;pointer to GDE buffer
|
|
sta drvr_buf_ptr
|
|
lda index_ptr+2
|
|
sta drvr_buf_ptr+2
|
|
jsr read_with_cache ;read in directory block
|
|
rts
|
|
load_ext_blk
|
|
jsr set_default_buf ;use the standard buffer please
|
|
jsr standard_req
|
|
lda one_entry+key_blk_index
|
|
sta drvr_blk_num
|
|
jsr read_with_cache
|
|
bcc @no_problem
|
|
jmp main_exit ;abort please
|
|
@no_problem
|
|
rts
|
|
|
|
ENDP
|
|
;==========================================================================
|
|
;get_dev_num This file contains code that will find a volume and return
|
|
; a device number.
|
|
;
|
|
;Created: aug 17, 1987
|
|
;Modified: aug 17, 1987
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: jml
|
|
;
|
|
;Input: A = undefined
|
|
; X = call number times 2
|
|
; Y = class times 2
|
|
; 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
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
; and lots of other stuff to.
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Dev/Vol Name Pointer (4 Bytes)
|
|
; Device Number (2 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Dev/Vol Name Pointer (4 Bytes)
|
|
; Device Number (2 Bytes)
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT get_dev_num
|
|
get_dev_num PROC
|
|
|
|
jsr setup_params ;go ahead do your thing
|
|
lda dev_num ;did the shell find a device?
|
|
bne have_device
|
|
lda #no_dup ;allow me to handle file not found
|
|
sta search_flag
|
|
jsr process_path ;do ahead and find the volume
|
|
bcc no_err ;no problem
|
|
|
|
cmp #file_not_found ;was the error file not found?
|
|
bne @dev_err_exit
|
|
lda dev_num
|
|
bne no_err ;give him the device number
|
|
lda #bad_path_syntax
|
|
@dev_err_exit
|
|
sec
|
|
jmp main_exit
|
|
|
|
no_err
|
|
lda drvr_dev_num
|
|
have_device ;
|
|
ldy #$0004 ;return the device number
|
|
sta [my_pblk_ptr],y
|
|
clc
|
|
jmp main_exit
|
|
|
|
ENDP
|
|
;======================================================================
|
|
;read_block and write_block calls
|
|
;
|
|
; This routine will read or write
|
|
; one block from the device number specified
|
|
;
|
|
;created: mar 23, 1987
|
|
;modified: jan 06, 1988
|
|
;author: Rob Turner
|
|
;
|
|
;Enter: jmp
|
|
;
|
|
;input: param_blk_ptr = pointer to user's parameter block
|
|
; A = undefined
|
|
; X = call number * 2
|
|
; Y = class of call (0 thru 7)
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;output: A = error code if carry set otherwise undefined
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;uses: all register
|
|
; param_blk_ptr (direct page)
|
|
; uses dispatcher (system call)
|
|
;
|
|
;exit: via common exit routine
|
|
;
|
|
;Call Format for Both Read and Write:
|
|
;
|
|
;Class 0 Device Number (2 Bytes)
|
|
; Pointer to Data Buffer (4 Bytes)
|
|
; Block Number (2 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Device Number (2 Bytes)
|
|
; Pointer to Data Buffer (4 Bytes)
|
|
; Block Number (2 Bytes)
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
EXPORT read_block
|
|
read_block PROC
|
|
|
|
lda #drvr_read
|
|
bra common_block ;common code for block read/write
|
|
|
|
EXPORT write_block
|
|
write_block ;
|
|
lda #drvr_write ;do a write call
|
|
|
|
common_block ;
|
|
sta drvr_call_num
|
|
tya
|
|
lsr a
|
|
tay
|
|
dey ;y = class of the call
|
|
bmi class0 ;old style call...
|
|
|
|
class1 ;
|
|
lda [param_blk_ptr] ;get the PCount
|
|
cmp #0003 ;min and max PCount for this call
|
|
beq good_pcount
|
|
lda #invalid_pcount ;I have a headache tonight
|
|
|
|
error_out ;
|
|
sec
|
|
read_out ;
|
|
jmp main_exit
|
|
|
|
good_pcount ;
|
|
iny
|
|
|
|
class0 ;
|
|
iny ;make index to 'Device Number'
|
|
lda [param_blk_ptr],y
|
|
sta drvr_dev_num
|
|
phy
|
|
jsr chk_owner ;see if this is my disk
|
|
ply
|
|
bcs error_out
|
|
iny
|
|
iny ;index to the buffer pointer
|
|
lda [param_blk_ptr],y
|
|
sta drvr_buf_ptr
|
|
iny
|
|
iny
|
|
lda [param_blk_ptr],y
|
|
sta drvr_buf_ptr+2
|
|
iny
|
|
iny ;index to the block number
|
|
lda [param_blk_ptr],y
|
|
sta drvr_blk_num
|
|
stz drvr_blk_num+2
|
|
|
|
;init all other parameters that the driver/dispatcher will use
|
|
|
|
lda #blk_size
|
|
sta drvr_req_cnt ;read one block only
|
|
stz drvr_req_cnt+2
|
|
|
|
try_again jsr device_call ;call the driver
|
|
bcs check_error
|
|
bra read_out ;error is returned
|
|
|
|
check_error ;
|
|
cmp #drvr_disk_sw ;disk switched behind my back?
|
|
bne error_out
|
|
stz prodos_vcr_ptr ;indicate that we do not know the owner.
|
|
stz prodos_vcr_ptr+2
|
|
bra try_again ;tell the user
|
|
|
|
;======================================================================
|
|
;chk_owner: This routine will try to find a VCR associated with
|
|
; the device we are going to write to. If we find the
|
|
|
|
; VCR we will see if it is a ProDOS volume, if it is then
|
|
; we will mark the bitmap undefined. If the bitmap is dirty
|
|
; or there are open files on the volume we will not allow
|
|
; the caller to write to the disk.
|
|
;======================================================================
|
|
|
|
chk_owner
|
|
lda drvr_dev_num ;see if there is a VCR
|
|
sta dev_num
|
|
jsr check_vcr_first
|
|
bcs exit_owner ;there is no VCR
|
|
jsr setup_my_vcr
|
|
stx prodos_vcr_ptr
|
|
sty prodos_vcr_ptr+2
|
|
jsr reset_vcr
|
|
rts
|
|
exit_owner
|
|
stz prodos_vcr_ptr ;indicate that we do not know the owner.
|
|
stz prodos_vcr_ptr+2
|
|
clc
|
|
rts
|
|
|
|
|
|
EXPORT reset_vcr
|
|
reset_vcr
|
|
lda drvr_call_num
|
|
cmp #drvr_write ;is this a write block call?
|
|
beq @is_write
|
|
clc
|
|
rts
|
|
|
|
@is_write
|
|
ldy #bitmap_dirty ;see if the bitmap is dirty
|
|
lda [prodos_vcr_ptr],y
|
|
bne no_action ;sorry not tonight
|
|
ldy #vcr_open_cnt ;see if files are open
|
|
lda [my_vcr_ptr],y
|
|
bne no_action
|
|
|
|
lda #$FFFF ;reset the volume please
|
|
ldy #curr_bitmap ;flush bitmap blocks
|
|
sta [prodos_vcr_ptr],y
|
|
ldy #free_blocks ;unknown free block count
|
|
sta [prodos_vcr_ptr],y
|
|
ldy #avail_bitmap
|
|
sta [prodos_vcr_ptr],y
|
|
clc
|
|
rts
|
|
|
|
no_action ;
|
|
lda #invalid_access
|
|
sec
|
|
rts
|
|
|
|
ENDP
|
|
;======================================================================
|
|
;format/Erase This file will format or erase of volume
|
|
;
|
|
;Created: dec 05, 1987
|
|
;Modified: mar 15, 1988
|
|
;Author: Rob Turner
|
|
;
|
|
;Enter: From GS/OS jmp table
|
|
;
|
|
;Input: A = undefined
|
|
; X = (call number * 2)
|
|
; Y = (class number * 2)
|
|
; P = nvmxdizc
|
|
; ..000...
|
|
; b = k
|
|
;
|
|
;Output: A = error code if carry set (exit via system exit routine)
|
|
; X = undefined
|
|
; Y = undefined
|
|
; P = nvmxdizc
|
|
; ..000..1 = error
|
|
; 0 = no error
|
|
; b = k
|
|
;
|
|
;Uses: All registers
|
|
; Device Dispatcher (subroutine)
|
|
; General I/O Buffer (1K buffer, I read 512 bytes)
|
|
;
|
|
;Call Format:
|
|
;
|
|
;Class 0 Device Name Pointer (4 Bytes)
|
|
; Volume Name Pointer (4 Bytes)
|
|
; FST ID (2 Bytes)
|
|
;
|
|
;Class 1 PCount (2 Bytes)
|
|
; Device Name Pointer (4 Bytes)
|
|
; Volume Name Pointer (4 Bytes)
|
|
; FST ID (2 Bytes)
|
|
;
|
|
;======================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT format_disk
|
|
format_disk PROC
|
|
import boot_size
|
|
|
|
jsr setup_params ;standard setup routine
|
|
** 2/28/92 GAB
|
|
jsr check_spans ;make sure the volume name isn't too long
|
|
**
|
|
lda dev_num ;move device number from SCM to
|
|
sta drvr_dev_num ;driver area on direct page
|
|
jsr clear_any_vcrs ;keep VCRs in order
|
|
jsr setup_vol_name ;move the volume name please
|
|
|
|
jsr hard_format ;issue a hard format please
|
|
bcs init_exit
|
|
bra continue
|
|
|
|
EXPORT erase_disk
|
|
erase_disk ;
|
|
jsr setup_params ;standard setup routine
|
|
** 2/28/92 GAB
|
|
jsr check_spans ;make sure the volume name isn't too long
|
|
**
|
|
lda dev_num ;move device number from SCM to
|
|
sta drvr_dev_num ;driver area on direct page
|
|
jsr clear_any_vcrs ;keep VCRs in order
|
|
jsr setup_vol_name ;move the volume name please
|
|
|
|
continue ;
|
|
jsr set_partition ;assign the partion map name
|
|
;
|
|
;Start of code that will write to disk
|
|
;
|
|
jsr write_boot_code ;write the boot code out to disk
|
|
bcs init_exit
|
|
jsr build_directory ;build the directory please
|
|
bcs init_exit
|
|
jsr build_bitmap ;build the correct bitmap please
|
|
init_exit ;
|
|
jmp main_exit
|
|
|
|
;======================================================================
|
|
;setup_vol_name This routine will verify the volume name is ok, and
|
|
; move the name into the format header.
|
|
;======================================================================
|
|
|
|
setup_vol_name ;
|
|
clc
|
|
lda path2_ptr
|
|
adc #$0003
|
|
sta temp_ptr ;setup pointer to the name
|
|
lda path2_ptr+2
|
|
adc #$0000
|
|
sta temp_ptr+2
|
|
|
|
jsr set_case_bits ;setup the case please (Temp_Ptr is Input)
|
|
|
|
lda temp_ptr ;subtract one from the pointer.
|
|
bne @do_low
|
|
dec temp_ptr+2
|
|
@do_low dec temp_ptr
|
|
|
|
lda #$0001
|
|
sta chars_checked ;parameter for setup_name
|
|
jsr setup_name
|
|
|
|
ldy #15 ;first clear the format header
|
|
lda #$0000
|
|
clr_loop ;
|
|
sta new_vol_name,y
|
|
dey
|
|
bpl clr_loop
|
|
|
|
lda search_length ;length of the volume name
|
|
and #$000F
|
|
tay
|
|
ora #volume_header
|
|
sta new_vol_name ;the length is now stored
|
|
|
|
longa off
|
|
sep #$20 ;8 bit Accum
|
|
move_vol ;
|
|
lda search_name-1,y
|
|
sta new_vol_name,y
|
|
dey
|
|
bne move_vol
|
|
longa on
|
|
rep #$20 ;16 bit Accum
|
|
|
|
;
|
|
;Save the case please
|
|
;
|
|
stz new_vol_date-2 ;zap any old data that might be around
|
|
lda case_bits ;get the user's case
|
|
beq @skip_save
|
|
ora #$8000
|
|
sta new_vol_date-2
|
|
@skip_save
|
|
jsr pack_time ;set the create date
|
|
stx new_vol_date
|
|
stx new_vol_mod
|
|
sty new_vol_date+2
|
|
sty new_vol_mod+2 ;set the mod time to the create time
|
|
rts
|
|
|
|
;======================================================================
|
|
;hard_format: This routine will issue the hard format call to the
|
|
; device driver.
|
|
;======================================================================
|
|
|
|
hard_format ;
|
|
lda #drvr_control ;issue hard format call to device
|
|
sta drvr_call_num
|
|
|
|
lda #drvr_format ;issue the format call
|
|
sta drvr_ctrl_code
|
|
|
|
lda #^format_ctrl
|
|
sta drvr_clist_ptr+2
|
|
lda #format_ctrl
|
|
sta drvr_clist_ptr
|
|
|
|
lda #$0002 ;length of control list
|
|
sta drvr_req_cnt
|
|
stz drvr_req_cnt+2
|
|
|
|
jsr device_call ;issue the format call to the device
|
|
bcc formatted
|
|
cmp #drvr_disk_sw ;is it a disk switched problem?
|
|
beq hard_format ;try again
|
|
sec
|
|
formatted ;
|
|
rts ;return with the error code.
|
|
|
|
;======================================================================
|
|
;indicate_erase This routine will tell the driver what name to store
|
|
; in the device partion map.
|
|
;======================================================================
|
|
|
|
set_partition ;
|
|
lda #drvr_control ;setup for a control call
|
|
sta drvr_call_num
|
|
|
|
lda #$0006 ;setup control code
|
|
sta drvr_ctrl_code
|
|
|
|
lda #^control_list ;setup pointer to the parameter list
|
|
sta drvr_clist_ptr+2
|
|
lda #control_list
|
|
sta drvr_clist_ptr
|
|
|
|
stz drvr_req_cnt
|
|
stz drvr_req_cnt+2 ;no request count
|
|
jsr device_call
|
|
rts
|
|
|
|
;======================================================================
|
|
;write_boot_code This routine will write out to disk the ProDOS
|
|
; boot code. Note that the SOS boot code has
|
|
; been removed from the boot blocks. This means that
|
|
; a disk formatted with the ProDOS FST cannot be booted
|
|
; on the Apple ///.
|
|
;======================================================================
|
|
|
|
write_boot_code ;
|
|
jsr set_default_buf ;use general work buffer
|
|
jsr standard_req ;512 byte write
|
|
jsr clear_gbuf_low ;clear the working buffer with zeros.
|
|
|
|
lda #drvr_write
|
|
sta drvr_call_num
|
|
stz drvr_blk_num
|
|
stz drvr_blk_num+2
|
|
|
|
ldy #boot_size-2 ;move the boot code to please
|
|
boot_loop ;
|
|
lda boot_code_start,y
|
|
sta [drvr_buf_ptr],y
|
|
dey
|
|
bpl boot_loop
|
|
|
|
re_boot ;
|
|
jsr device_call ;issue the device call please
|
|
bcc boot_done
|
|
cmp #drvr_disk_sw
|
|
beq re_boot ;try again
|
|
sec
|
|
boot_done ;
|
|
rts
|
|
|
|
;======================================================================
|
|
;Build_directory This routine will build the first four blocks of the
|
|
; directory.
|
|
;======================================================================
|
|
|
|
build_directory
|
|
jsr get_dev_blks ;get the number of blocks on the device.
|
|
bcs exit_dir ;sorry we are out of here.
|
|
sta new_tot_blks ;number of blocks on the volume
|
|
|
|
jsr set_default_buf ;use general work buffer
|
|
jsr standard_req ;512 byte write
|
|
jsr clear_gbuf_low ;clear the working buffer with zeros.
|
|
|
|
lda #drvr_write ;setup for write calls
|
|
sta drvr_call_num
|
|
lda #vol_dir_start
|
|
sta drvr_blk_num
|
|
stz drvr_blk_num+2
|
|
|
|
ldy #entry_length+2 ;now move the entry to work buffer
|
|
header_loop ;
|
|
lda format_header,y
|
|
sta [drvr_buf_ptr],y
|
|
dey
|
|
bpl header_loop
|
|
|
|
;
|
|
;Write Block Two To Disk
|
|
;
|
|
jsr device_call ;issue the device call please
|
|
bcs exit_dir
|
|
;
|
|
;Write Block Three To Disk
|
|
;
|
|
jsr clear_gbuf_low ;clear the block again
|
|
ldx #vol_dir_start ;backward link to block 2
|
|
ldy #vol_dir_start+2 ;forward link to block 3
|
|
jsr do_dir_blk ;write directory block to disk
|
|
bcs exit_dir
|
|
;
|
|
;Write Block Four To Disk
|
|
;
|
|
ldx #vol_dir_start+1 ;Backward link to block 3
|
|
ldy #vol_dir_start+3 ;Forward link to block 5
|
|
jsr do_dir_blk
|
|
bcs exit_dir
|
|
;
|
|
;Write Block Five To Disk
|
|
;
|
|
ldx #vol_dir_start+2 ;Backward link to block 4
|
|
ldy #$0000 ;Forward link NIL
|
|
jsr do_dir_blk
|
|
exit_dir ;
|
|
rts
|
|
|
|
do_dir_blk ;
|
|
|
|
txa ;previous link
|
|
sta [drvr_buf_ptr]
|
|
tya
|
|
ldy #$0002 ;index to forward link
|
|
sta [drvr_buf_ptr],y
|
|
inc drvr_blk_num ;move to the next block please
|
|
jsr device_call ;issue write call
|
|
rts
|
|
|
|
;======================================================================
|
|
;build_bitmap This routine will build a bitmap for the device
|
|
; being formatted.
|
|
;======================================================================
|
|
|
|
build_bitmap ;
|
|
lda #bitmap_strt_blk ;starting block number of bitmap
|
|
sta drvr_blk_num
|
|
;
|
|
;Calculate the number of bitmap blocks needed for this volume
|
|
;
|
|
ldx #$0001 ;default = one bitmap block
|
|
lda new_tot_blks ;number of blocks on volume
|
|
count_blks ;
|
|
sec
|
|
sbc #4096 ;one bitmap block
|
|
beq end_count
|
|
bcc end_count
|
|
inx ;add one to the block count
|
|
bra count_blks
|
|
|
|
end_count ;
|
|
stx bitmap_blks ;total number of bitmap blocks
|
|
txa
|
|
clc
|
|
adc #$0005 ;add in boot blks and directory
|
|
sta last_bitmap ;blk number of last bitmap blk
|
|
|
|
jsr fill_gbuf_low ;allocate 4096 blocks please
|
|
|
|
ldx last_bitmap ;block number of last bitmap block
|
|
dir_build ;
|
|
jsr alloc_bit_blk ;allocate a bitmap block please
|
|
dex ;allocate the next block please
|
|
bpl dir_build
|
|
bra chk_last ;see if we are done
|
|
|
|
full_loop ;
|
|
jsr fill_gbuf_low ;allocate 4096 blocks
|
|
|
|
chk_last ;
|
|
lda drvr_blk_num ;our we done?
|
|
cmp last_bitmap
|
|
beq clear_to_end ;yes we are
|
|
|
|
jsr device_call ;issue write call
|
|
bcs end1_bitmap
|
|
inc drvr_blk_num ;move to the next block please
|
|
bra full_loop
|
|
|
|
|
|
clear_to_end ; ;clear from last bit to the end
|
|
lda new_tot_blks
|
|
tax
|
|
and #$0FFF ;do we need to clear anything?
|
|
beq just_write
|
|
txa ;we must clear some bits
|
|
and #$0007 ;are we byte aligned?
|
|
beq fast_clr ;yes we are
|
|
jsr alloc_bit_blk ;allocate the odd block
|
|
inx
|
|
stx new_tot_blks
|
|
bra clear_to_end
|
|
fast_clr ;
|
|
jsr calc_bit ;get the index please
|
|
|
|
lda #$0000
|
|
fast_loop sta [drvr_buf_ptr],y
|
|
iny
|
|
iny ;WARNING! we might overwrite a byte
|
|
cpy #$0200 ;past $200 this is OK with a 1K buffer
|
|
bcc fast_loop ;since we are using 512 bytes only
|
|
just_write ;
|
|
jsr device_call ;issue write call
|
|
end1_bitmap ;
|
|
rts
|
|
|
|
alloc_bit_blk ;
|
|
phx ;save the block number
|
|
jsr calc_bit ;convert block number to bit pattern
|
|
eor #$FFFF ;clear the correct bit please
|
|
and [drvr_buf_ptr],y
|
|
sta [drvr_buf_ptr],y
|
|
plx ;restore block number
|
|
rts
|
|
|
|
;======================================================================
|
|
;get_dev_blks This routine will return the number of blocks on
|
|
; the volume.
|
|
;
|
|
;Output: A = number of blocks
|
|
;======================================================================
|
|
|
|
get_dev_blks ;
|
|
lda #drvr_status ;issue a status call to the device
|
|
sta drvr_call_num
|
|
|
|
lda #^status_list ;setup a pointer to the status list
|
|
sta drvr_slist_ptr+2
|
|
lda #status_list
|
|
sta drvr_slist_ptr
|
|
|
|
lda #$0006 ;a six byte request count
|
|
sta drvr_req_cnt
|
|
stz drvr_req_cnt+2
|
|
|
|
lda #blk_size
|
|
sta drvr_blk_size
|
|
|
|
stz drvr_stat_code ;issue a 'driver status' call.
|
|
jsr device_call ;blast off!!
|
|
bcs holy_cow_batman ;An error?
|
|
|
|
ldx #$FFFF ;a 32 meg volume
|
|
lda return_blks+2 ;return the blocks please
|
|
bne big_boy
|
|
ldx return_blks
|
|
cpx #$0007
|
|
bcc range_problem ;sorry this device is too small
|
|
big_boy ;
|
|
txa ;number of blocks on volume
|
|
clc
|
|
holy_cow_batman
|
|
rts
|
|
|
|
range_problem
|
|
lda #drvr_bad_block ;we will not do it.
|
|
sec
|
|
rts
|
|
|
|
;======================================================================
|
|
;This routine will mark any VCR's that are logged on this device as
|
|
;being swapped. This will allow any FST to rebuild the VCR after the
|
|
;media has been erased or formatted.
|
|
;======================================================================
|
|
|
|
clear_any_vcrs ;
|
|
lda dev_num ;device number we are going to erase
|
|
jsl swap_out ;mark volumes offline
|
|
rts
|
|
ENDP
|
|
|
|
;==========================================================================
|
|
;This file contians the calls the handle FST specific calls
|
|
;
|
|
;created: Mar 19, 1988
|
|
;modified: Mar 19, 1988
|
|
;Author: Rob Turner
|
|
;
|
|
;
|
|
;==========================================================================
|
|
longa on
|
|
longi on
|
|
|
|
EXPORT fst_specific
|
|
fst_specific PROC
|
|
|
|
ldy #$0004 ;index to command number
|
|
lda [param_blk_ptr],y
|
|
cmp #set_time_stamp
|
|
beq set_time
|
|
cmp #get_time_stamp
|
|
beq get_time
|
|
cmp #set_upper_case
|
|
beq set_fst_attr ;set the Upper case flag please
|
|
cmp #get_upper_case
|
|
beq get_fst_attr
|
|
|
|
IF debug_on<>0 THEN
|
|
jsr fst_debug ;check special commands for debugger
|
|
bra exit ;exit with error
|
|
ENDIF
|
|
lda #invalid_fst_op
|
|
bra error_out
|
|
|
|
parm_range
|
|
lda #parm_range_err ;parameter out of range
|
|
bra error_out
|
|
|
|
bad_pcnt
|
|
lda #invalid_pcount
|
|
|
|
error_out
|
|
sec
|
|
exit
|
|
jmp main_exit
|
|
|
|
;==========================================================================
|
|
;This call allows the user to set the time stamp option. Below is the valid
|
|
;list of values.
|
|
;
|
|
; $0000 = Time stamp files only
|
|
; $0001 = Time stamp file + Parent Directory
|
|
; $0002 = Time stamp file + all directories to the root
|
|
;
|
|
;==========================================================================
|
|
set_time
|
|
lda [param_blk_ptr] ;verify the Pcount
|
|
cmp #$0003
|
|
bne bad_pcnt
|
|
iny
|
|
iny ;point to the stamp size
|
|
lda [param_blk_ptr],y
|
|
cmp #$0003
|
|
bcs parm_range ;sorry bad
|
|
sta time_stamp_opt
|
|
clc
|
|
bra exit
|
|
|
|
;==========================================================================
|
|
;This call returns the current time stamp option. Below is the valid
|
|
;list of values.
|
|
;
|
|
; $0000 = Time stamp files only
|
|
; $0001 = Time stamp file + Parent Directory
|
|
; $0002 = Time stamp file + all directories to the root
|
|
;
|
|
;==========================================================================
|
|
get_time
|
|
lda [param_blk_ptr] ;verify the Pcount
|
|
cmp #$0003
|
|
bne bad_pcnt
|
|
iny
|
|
iny ;point to the stamp size
|
|
lda time_stamp_opt
|
|
sta [param_blk_ptr],y
|
|
clc
|
|
bra exit
|
|
|
|
|
|
;==========================================================================
|
|
;This call allows the user to set the upper case state to on or off
|
|
;If set to off all file names will be returned in upper case, otherwise
|
|
;they will be returned in the cae they were created in.
|
|
;
|
|
; $0000 = Turn OFF upper/lower case
|
|
; $0001 = Return case as created/renamed
|
|
;
|
|
;==========================================================================
|
|
set_fst_attr
|
|
lda [param_blk_ptr] ;verify the Pcount
|
|
cmp #$0003
|
|
bne bad_pcnt
|
|
iny
|
|
iny ;point to the input parameter
|
|
lda [param_blk_ptr],y
|
|
beq @set_high_bit
|
|
dec a
|
|
bne parm_range ;sorry bad
|
|
|
|
lda fst_attr ;clear the bit please
|
|
and #$7FFF
|
|
sta fst_attr
|
|
clc
|
|
bra exit
|
|
@set_high_bit
|
|
lda fst_attr ;turn off upper/lower case.
|
|
ora #$8000
|
|
sta fst_attr
|
|
clc
|
|
bra exit
|
|
|
|
;==========================================================================
|
|
;This call allows the user to get the upper case state.
|
|
;
|
|
; $0000 = files are returned in all UPPERCASE
|
|
; $0001 = Return case as created/renamed
|
|
;
|
|
;==========================================================================
|
|
get_fst_attr
|
|
lda [param_blk_ptr] ;verify the Pcount
|
|
cmp #$0003
|
|
bne bad_pcnt
|
|
iny
|
|
iny ;point to the input parameter
|
|
ldx #$0000
|
|
lda fst_attr
|
|
bmi @return_zero
|
|
inx
|
|
@return_zero
|
|
txa
|
|
sta [param_blk_ptr],y
|
|
clc
|
|
bra exit
|
|
ENDP
|
|
|
|
EXPORT end_segment
|
|
end_segment PROC
|
|
EXPORT end_code
|
|
end_code
|
|
ENDP
|
|
end |