mirror of
https://github.com/romychs/ocean-240.2
synced 2026-04-21 10:43:18 +03:00
2785 lines
61 KiB
NASM
2785 lines
61 KiB
NASM
; =======================================================
|
|
; Ocean-240.2
|
|
; CP/M BDOS at 0xC800:D5FF
|
|
;
|
|
; Disassembled by Romych 2025-09-09
|
|
; ======================================================
|
|
|
|
INCLUDE "io.inc"
|
|
INCLUDE "equates.inc"
|
|
INCLUDE "external_ram.inc"
|
|
|
|
IFNDEF BUILD_ROM
|
|
OUTPUT bdos.bin
|
|
ENDIF
|
|
|
|
MODULE BDOS
|
|
|
|
ORG 0xC800
|
|
|
|
bdos_start:
|
|
LD SP, HL
|
|
LD D, 0x00
|
|
NOP
|
|
NOP
|
|
LD L, E
|
|
bdos_enter:
|
|
JP bdos_entrance
|
|
|
|
bdos_pere_addr: dw bdos_persub
|
|
bdos_sele_addr: dw bdos_selsub
|
|
bdos_rode_addr: dw bdos_rodsub
|
|
bdos_rofe_addr: dw bdos_rofsub
|
|
|
|
; -------------------------------------------------------
|
|
; BDOS Handler
|
|
; Inp: C - func no
|
|
; DE - parameter
|
|
; Out: A or HL - result
|
|
; -------------------------------------------------------
|
|
bdos_entrance:
|
|
EX DE, HL
|
|
LD (TM_VARS.bdos_info), HL
|
|
EX DE, HL
|
|
LD A, E
|
|
LD (TM_VARS.bdos_linfo), A
|
|
LD HL, 0x00 ; return val default = 0
|
|
LD (TM_VARS.bdos_aret), HL
|
|
|
|
; Save user's stack pointer, set to local stack
|
|
ADD HL,SP
|
|
LD (TM_VARS.bdos_entsp), HL
|
|
LD SP, TM_VARS.bdos_usercode ; local stack setup
|
|
XOR A
|
|
LD (TM_VARS.bdos_fcbdsk), A ; fcbdsk,resel=false
|
|
LD (TM_VARS.bdos_resel), A
|
|
LD HL, bdos_goback
|
|
PUSH HL ; jmp goback equivalent to ret
|
|
LD A, C
|
|
CP BDOS_NFUNCS
|
|
RET NC
|
|
LD C, E ; possible output character to C
|
|
LD HL, functab ; DE=func, HL=.ciotab
|
|
LD E, A
|
|
LD D, 0x00
|
|
ADD HL, DE
|
|
ADD HL, DE
|
|
LD E, (HL)
|
|
INC HL
|
|
LD D, (HL) ; DE=functab(func)
|
|
LD HL, (TM_VARS.bdos_info) ; info in DE for later xchg
|
|
EX DE, HL
|
|
JP (HL) ; dispatched
|
|
|
|
; -------------------------------------------------------
|
|
; BDOS function handlers address table
|
|
; -------------------------------------------------------
|
|
functab:
|
|
dw BIOS.wboot_f
|
|
dw bdos_func1
|
|
dw bdos_tabout
|
|
dw bdos_func3
|
|
dw BIOS.punch_f
|
|
dw BIOS.list_f
|
|
dw bdos_func6
|
|
dw bdos_func7
|
|
dw bdos_func8
|
|
dw bdos_func9
|
|
dw bdos_read
|
|
dw bdos_func11
|
|
dw bdos_get_version
|
|
dw bdos_reset_disks
|
|
dw bdos_select_disk
|
|
dw bdos_open_file
|
|
dw bdos_close_file
|
|
dw bdos_search_first
|
|
dw bdos_search_next
|
|
dw bdos_rm_dir
|
|
dw bdos_read_file
|
|
dw bdos_write_file
|
|
dw bdos_make_file
|
|
dw bdos_ren_file
|
|
dw bdos_get_login_vec
|
|
dw bdos_get_cur_drive
|
|
dw bdos_set_dma_addr
|
|
dw bdos_get_logvect
|
|
dw bdos_set_ro
|
|
dw bdos_wr_protect
|
|
dw bdos_set_ind
|
|
dw bdos_get_dpb
|
|
dw bdos_set_user
|
|
dw bdos_rand_read
|
|
dw bdos_rand_write
|
|
dw bdos_compute_fs
|
|
dw bdos_set_random
|
|
dw bdos_reset_drives
|
|
dw bdos_not_impl
|
|
dw bdos_not_impl
|
|
dw bdos_rand_write_z
|
|
|
|
; -------------------------------------------------------
|
|
; Report permanent error
|
|
; -------------------------------------------------------
|
|
bdos_persub:
|
|
LD HL,permsg ; = 'B'
|
|
CALL bdos_errflag
|
|
CP BDOS_CTLC
|
|
JP Z, EXT_RAM.JP_WBOOT
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Report select error
|
|
; -------------------------------------------------------
|
|
bdos_selsub:
|
|
LD HL,selmsg ;= 'S'
|
|
JP bdos_wait_err
|
|
|
|
; -------------------------------------------------------
|
|
; Report write to read/only disk
|
|
; -------------------------------------------------------
|
|
bdos_rodsub:
|
|
LD HL,rodmsg ;= 'R'
|
|
JP bdos_wait_err
|
|
|
|
; -------------------------------------------------------
|
|
; Report read/only file
|
|
; -------------------------------------------------------
|
|
bdos_rofsub:
|
|
LD HL,rofmsg ;= 'F'
|
|
|
|
; -------------------------------------------------------
|
|
; Wait for response before boot
|
|
; -------------------------------------------------------
|
|
bdos_wait_err:
|
|
CALL bdos_errflag
|
|
JP EXT_RAM.JP_WBOOT
|
|
|
|
; -------------------------------------------------------
|
|
; Error messages
|
|
; -------------------------------------------------------
|
|
dskmsg:
|
|
db 'Bdos Err On '
|
|
dskerr:
|
|
db " : $"
|
|
permsg:
|
|
db "Bad Sector$"
|
|
selmsg:
|
|
db "Select$"
|
|
rofmsg:
|
|
db "File "
|
|
rodmsg:
|
|
db "R/O$"
|
|
|
|
; -------------------------------------------------------
|
|
; Report error to console, message address in HL
|
|
; -------------------------------------------------------
|
|
bdos_errflag:
|
|
PUSH HL
|
|
CALL bdos_crlf
|
|
LD A, (TM_VARS.bdos_curdsk)
|
|
ADD A,'A'
|
|
LD (dskerr), A ;= ' '
|
|
LD BC,dskmsg ;= 'B'
|
|
CALL bdos_print
|
|
POP BC
|
|
CALL bdos_print
|
|
|
|
; -------------------------------------------------------
|
|
; Console handlers
|
|
; Read console character to A
|
|
; -------------------------------------------------------
|
|
bdos_conin:
|
|
LD HL, TM_VARS.bdos_kbchar
|
|
LD A, (HL)
|
|
LD (HL), 0x00
|
|
OR A
|
|
RET NZ
|
|
;no previous keyboard character ready
|
|
JP BIOS.conin_f
|
|
; -------------------------------------------------------
|
|
; Read character from console with echo
|
|
; -------------------------------------------------------
|
|
bdos_conech:
|
|
CALL bdos_conin
|
|
CALL bdos_echoc
|
|
RET C
|
|
PUSH AF
|
|
LD C, A
|
|
CALL bdos_tabout
|
|
POP AF
|
|
RET
|
|
; -------------------------------------------------------
|
|
; Echo character if cr, lf, tab, or backspace
|
|
; -------------------------------------------------------
|
|
bdos_echoc:
|
|
CP ASCII_CR
|
|
RET Z
|
|
CP ASCII_LF
|
|
RET Z
|
|
CP ASCII_TAB
|
|
RET Z
|
|
CP ASCII_BS
|
|
RET Z
|
|
CP ' '
|
|
RET
|
|
; -------------------------------------------------------
|
|
; check for character ready
|
|
; -------------------------------------------------------
|
|
bdos_conbrk:
|
|
LD A, (TM_VARS.bdos_kbchar)
|
|
OR A
|
|
JP NZ,conb1 ; skip if active kbchar
|
|
CALL BIOS.const_f
|
|
AND 0x1
|
|
RET Z ; return if no char ready
|
|
CALL BIOS.conin_f
|
|
CP CTLS
|
|
JP NZ,conb0
|
|
CALL BIOS.conin_f
|
|
CP CTLC
|
|
JP Z, EXT_RAM.JP_WBOOT
|
|
XOR A
|
|
RET
|
|
conb0:
|
|
LD (TM_VARS.bdos_kbchar), A ; character in A, save it
|
|
conb1:
|
|
LD A, 0x1 ; return with true set in accumulator
|
|
RET
|
|
bdos_conout:
|
|
|
|
LD A, (TM_VARS.bdos_compcol) ; Compute character position/write con...
|
|
; compcol = true if computing column ...
|
|
OR A
|
|
JP NZ,compout
|
|
PUSH BC
|
|
|
|
CALL bdos_conbrk
|
|
POP BC
|
|
PUSH BC
|
|
|
|
CALL BIOS.conout_f
|
|
POP BC
|
|
PUSH BC
|
|
; May be copying to the list device
|
|
LD A, (TM_VARS.bdos_listcp)
|
|
OR A
|
|
CALL NZ, BIOS.list_f
|
|
POP BC
|
|
|
|
; -------------------------------------------------------
|
|
; Compute column position
|
|
; -------------------------------------------------------
|
|
compout:
|
|
LD A, C
|
|
; recall the character
|
|
; and compute column position
|
|
LD HL, TM_VARS.bdos_column
|
|
CP RUB_OUT
|
|
RET Z
|
|
INC (HL)
|
|
CP ' '
|
|
RET NC
|
|
|
|
; not graphic, reset column position
|
|
DEC (HL)
|
|
LD A, (HL)
|
|
OR A
|
|
RET Z
|
|
|
|
LD A, C
|
|
CP ASCII_BS
|
|
JP NZ, notbacksp
|
|
; backspace character
|
|
DEC (HL)
|
|
RET
|
|
|
|
notbacksp:
|
|
CP ASCII_LF
|
|
RET NZ
|
|
LD (HL), 0x00
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Send C character with possible preceding up-arrow
|
|
; -------------------------------------------------------
|
|
bdos_ctlout:
|
|
LD A, C
|
|
CALL bdos_echoc ; cy if not graphic (or special case)
|
|
JP NC, bdos_tabout ; skip if graphic, tab, cr, lf, or ctlh
|
|
PUSH AF
|
|
LD C, CTL
|
|
CALL bdos_conout ; up arrow
|
|
POP AF
|
|
OR 0x40 ; becomes graphic letter
|
|
LD C, A ; ready to print
|
|
; (drop through to tabout)
|
|
|
|
bdos_tabout:
|
|
LD A, C
|
|
; Expand tabs to console
|
|
CP ASCII_TAB
|
|
JP NZ, bdos_conout
|
|
|
|
bpc_no_tabpos:
|
|
LD C,' '
|
|
CALL bdos_conout
|
|
LD A, (TM_VARS.bdos_column)
|
|
AND 00000111b ; column mod 8 = 0 ?
|
|
JP NZ, bpc_no_tabpos
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Back-up one screen position
|
|
; -------------------------------------------------------
|
|
bdos_backup:
|
|
CALL bdos_pctlh
|
|
LD C, ' '
|
|
CALL BIOS.conout_f
|
|
; -------------------------------------------------------
|
|
; Send ctlh to console without affecting column count
|
|
; -------------------------------------------------------
|
|
bdos_pctlh:
|
|
LD C, ASCII_BS
|
|
JP BIOS.conout_f
|
|
|
|
; -------------------------------------------------------
|
|
; print #, cr, lf for ctlx, ctlu, ctlr functions
|
|
; then move to strtcol (starting column)
|
|
; -------------------------------------------------------
|
|
bdos_crlfp:
|
|
LD C, '#'
|
|
CALL bdos_conout
|
|
CALL bdos_crlf
|
|
crlfp0:
|
|
LD A, (TM_VARS.bdos_column)
|
|
LD HL, TM_VARS.bdos_strtcol
|
|
CP (HL)
|
|
RET NC
|
|
LD C, ' '
|
|
CALL bdos_conout
|
|
JP crlfp0
|
|
|
|
; -------------------------------------------------------
|
|
; Out carriage return line feed sequence
|
|
; -------------------------------------------------------
|
|
|
|
bdos_crlf:
|
|
LD C, ASCII_CR
|
|
CALL bdos_conout
|
|
LD C, ASCII_LF
|
|
JP bdos_conout
|
|
|
|
; -------------------------------------------------------
|
|
; Print $-ended message BC -> str
|
|
; -------------------------------------------------------
|
|
bdos_print:
|
|
LD A, (BC)
|
|
CP '$'
|
|
RET Z
|
|
INC BC
|
|
PUSH BC
|
|
LD C, A
|
|
CALL bdos_tabout
|
|
POP BC
|
|
JP bdos_print
|
|
|
|
; -------------------------------------------------------
|
|
; Buffered console input
|
|
; Reads characters from the keyboard into a memory buffer
|
|
; until RETURN is pressed.
|
|
; Inp: C=0Ah
|
|
; DE=address or zero
|
|
; -------------------------------------------------------
|
|
bdos_read:
|
|
LD A, (TM_VARS.bdos_column)
|
|
LD (TM_VARS.bdos_strtcol), A
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD C, (HL)
|
|
INC HL
|
|
PUSH HL
|
|
LD B, 0x00
|
|
; B = current buffer length,
|
|
; C = maximum buffer length,
|
|
; HL= next to fill - 1
|
|
readnx:
|
|
PUSH BC
|
|
PUSH HL
|
|
readn1:
|
|
CALL bdos_conin
|
|
AND 0x7f
|
|
POP HL
|
|
POP BC
|
|
CP 0xd
|
|
JP Z,readen
|
|
CP 0xa
|
|
JP Z,readen
|
|
CP 0x8
|
|
JP NZ,noth
|
|
LD A, B
|
|
OR A
|
|
JP Z,readnx
|
|
DEC B
|
|
LD A, (TM_VARS.bdos_column)
|
|
LD (TM_VARS.bdos_compcol), A
|
|
JP linelen
|
|
noth:
|
|
CP 0x7f ; not a backspace
|
|
JP NZ, notrub
|
|
LD A, B
|
|
OR A
|
|
JP Z, readnx
|
|
LD A, (HL)
|
|
DEC B
|
|
DEC HL
|
|
JP rdech1
|
|
notrub:
|
|
CP 0x5
|
|
JP NZ, note
|
|
PUSH BC
|
|
PUSH HL
|
|
|
|
CALL bdos_crlf
|
|
XOR A
|
|
LD (TM_VARS.bdos_strtcol), A
|
|
JP readn1
|
|
note:
|
|
CP 0x10
|
|
JP NZ,notp
|
|
PUSH HL
|
|
LD HL, TM_VARS.bdos_listcp
|
|
LD A, 0x1
|
|
SUB (HL)
|
|
LD (HL), A
|
|
POP HL
|
|
JP readnx
|
|
notp:
|
|
CP 0x18
|
|
JP NZ, notx
|
|
POP HL
|
|
backx:
|
|
LD A, (TM_VARS.bdos_strtcol)
|
|
LD HL, TM_VARS.bdos_column
|
|
CP (HL)
|
|
JP NC, bdos_read
|
|
DEC (HL)
|
|
|
|
CALL bdos_backup
|
|
JP backx
|
|
notx:
|
|
CP 0x15
|
|
JP NZ, notu
|
|
|
|
CALL bdos_crlfp
|
|
POP HL
|
|
JP bdos_read
|
|
notu:
|
|
CP 0x12
|
|
JP NZ, rdecho
|
|
linelen:
|
|
PUSH BC
|
|
|
|
CALL bdos_crlfp
|
|
POP BC
|
|
POP HL
|
|
PUSH HL
|
|
PUSH BC
|
|
rep0:
|
|
LD A, B
|
|
OR A
|
|
JP Z, rep1
|
|
INC HL
|
|
LD C, (HL)
|
|
DEC B
|
|
PUSH BC
|
|
PUSH HL
|
|
CALL bdos_ctlout
|
|
POP HL
|
|
POP BC
|
|
JP rep0
|
|
rep1:
|
|
PUSH HL
|
|
LD A, (TM_VARS.bdos_compcol)
|
|
OR A
|
|
JP Z, readn1
|
|
LD HL, TM_VARS.bdos_column
|
|
SUB (HL)
|
|
LD (TM_VARS.bdos_compcol), A
|
|
; move back compcol-column spaces
|
|
|
|
backsp:
|
|
CALL bdos_backup
|
|
LD HL, TM_VARS.bdos_compcol
|
|
DEC (HL)
|
|
JP NZ, backsp
|
|
JP readn1
|
|
|
|
rdecho:
|
|
INC HL
|
|
LD (HL), A
|
|
INC B
|
|
rdech1:
|
|
PUSH BC
|
|
PUSH HL
|
|
LD C, A
|
|
|
|
CALL bdos_ctlout
|
|
POP HL
|
|
POP BC
|
|
LD A, (HL)
|
|
CP 0x3
|
|
LD A, B
|
|
JP NZ, notc
|
|
CP 0x1
|
|
JP Z, EXT_RAM.JP_WBOOT
|
|
notc:
|
|
CP C
|
|
JP C,readnx
|
|
|
|
; End of read operation, store blen
|
|
readen:
|
|
POP HL
|
|
LD (HL), B
|
|
LD C, 0xd
|
|
JP bdos_conout
|
|
|
|
; -------------------------------------------------------
|
|
; Console input with echo (C_READ)
|
|
; Out: A=L=character
|
|
; -------------------------------------------------------
|
|
|
|
bdos_func1:
|
|
CALL bdos_conech
|
|
JP bdos_ret_a
|
|
|
|
; -------------------------------------------------------
|
|
; Console input chartacter
|
|
; Out: A=L=ASCII character
|
|
; -------------------------------------------------------
|
|
bdos_func3:
|
|
CALL BIOS.reader_f
|
|
JP bdos_ret_a
|
|
|
|
; -------------------------------------------------------
|
|
; Direct console I/O
|
|
; Inp: E=code.
|
|
; E=code. Returned values (in A) vary.
|
|
; 0xff Return a character without echoing if one is
|
|
; waiting; zero if none
|
|
; 0xfe Return console input status. Zero if no
|
|
; character is waiting
|
|
; Out: A
|
|
; -------------------------------------------------------
|
|
bdos_func6:
|
|
LD A, C
|
|
INC A
|
|
JP Z, dirinp ; ff?
|
|
INC A
|
|
JP Z, BIOS.const_f ; fe?
|
|
JP BIOS.conout_f ; con out otherwise
|
|
dirinp:
|
|
CALL BIOS.const_f
|
|
OR A
|
|
JP Z, bdos_ret_mon
|
|
CALL BIOS.conin_f
|
|
JP bdos_ret_a
|
|
|
|
; -------------------------------------------------------
|
|
; Get I/O byte
|
|
; Out: [3] = I/O byte.
|
|
; -------------------------------------------------------
|
|
bdos_func7:
|
|
LD A, (EXT_RAM.bdos_ioloc)
|
|
JP bdos_ret_a
|
|
|
|
; -------------------------------------------------------
|
|
; Set I/O byte
|
|
; Inp: E=I/O byte.
|
|
; -------------------------------------------------------
|
|
bdos_func8:
|
|
LD HL, EXT_RAM.bdos_ioloc
|
|
LD (HL), C
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Out $-ended string
|
|
; Inp: DE -> string.
|
|
; -------------------------------------------------------
|
|
bdos_func9:
|
|
EX DE, HL
|
|
LD C,L
|
|
LD B, H
|
|
JP bdos_print
|
|
|
|
; -------------------------------------------------------
|
|
; Get console status
|
|
; Inp: A=L=status
|
|
; -------------------------------------------------------
|
|
bdos_func11:
|
|
CALL bdos_conbrk
|
|
bdos_ret_a:
|
|
LD (TM_VARS.bdos_aret), A
|
|
bdos_not_impl:
|
|
RET
|
|
|
|
setlret1:
|
|
LD A, 0x1
|
|
JP bdos_ret_a
|
|
|
|
; -------------------------------------------------------
|
|
; Report select error
|
|
; -------------------------------------------------------
|
|
bdos_sel_error:
|
|
LD HL, bdos_sele_addr ;= C8A5h
|
|
bdos_goerr:
|
|
LD E, (HL) ;= C8A5h
|
|
INC HL
|
|
LD D, (HL) ; ->bdos_sele_addr+1
|
|
EX DE, HL
|
|
JP (HL) ; ->bdos_selsub
|
|
|
|
; -------------------------------------------------------
|
|
; Move C bytes from [DE] to [HL]
|
|
; -------------------------------------------------------
|
|
bdos_move:
|
|
|
|
INC C
|
|
bmove_nxt:
|
|
DEC C
|
|
RET Z
|
|
LD A, (DE)
|
|
LD (HL), A
|
|
INC DE
|
|
INC HL
|
|
JP bmove_nxt
|
|
|
|
; -------------------------------------------------------
|
|
; Select the disk drive given by curdsk, and fill
|
|
; the base addresses curtrka - alloca, then fill
|
|
; the values of the disk parameter block
|
|
; -------------------------------------------------------
|
|
dbos_selectdisk:
|
|
LD A, (TM_VARS.bdos_curdsk)
|
|
LD C, A
|
|
CALL BIOS.seldsk_f ; HL filled by call
|
|
; HL = 0000 if error, otherwise disk headers
|
|
LD A, H
|
|
OR L
|
|
RET Z
|
|
LD E, (HL)
|
|
INC HL
|
|
LD D, (HL)
|
|
INC HL
|
|
LD (TM_VARS.bdos_cdrmaxa), HL
|
|
INC HL
|
|
INC HL
|
|
LD (TM_VARS.bdos_curtrka), HL
|
|
INC HL
|
|
INC HL
|
|
LD (TM_VARS.bdos_curreca), HL
|
|
INC HL
|
|
INC HL
|
|
EX DE, HL
|
|
LD (TM_VARS.bdos_tranv), HL ; .tran vector
|
|
LD HL, TM_VARS.bdos_buffa ; DE= source for move, HL=dest
|
|
LD C, ADDLIST
|
|
CALL bdos_move
|
|
; Fill the disk parameter block
|
|
LD HL, (TM_VARS.bdos_dpbaddr)
|
|
EX DE, HL
|
|
LD HL, TM_VARS.dbos_sectpt
|
|
LD C, DBPLIST
|
|
CALL bdos_move
|
|
; Set single/double map mode
|
|
LD HL, (TM_VARS.bdos_maxall) ; largest allocation number
|
|
LD A, H
|
|
LD HL, TM_VARS.bdos_single
|
|
LD (HL), 0xFF
|
|
OR A
|
|
JP Z, retselect
|
|
LD (HL), 0x00
|
|
retselect:
|
|
LD A, 0xff
|
|
OR A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Move to home position, then offset to start of dir
|
|
; -------------------------------------------------------
|
|
bdos_home:
|
|
CALL BIOS.home_f
|
|
XOR A
|
|
LD HL, (TM_VARS.bdos_curtrka)
|
|
LD (HL), A
|
|
INC HL
|
|
LD (HL), A
|
|
LD HL, (TM_VARS.bdos_curreca)
|
|
LD (HL), A
|
|
INC HL
|
|
LD (HL), A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Read buffer and check condition
|
|
; -------------------------------------------------------
|
|
bdos_rdbuff:
|
|
CALL BIOS.read_f
|
|
JP diocomp ; check for i/o errors
|
|
|
|
; -------------------------------------------------------
|
|
; Write buffer and check condition
|
|
; Inp: C - write type
|
|
; 0 - normal write operation
|
|
; 1 - directory write operation
|
|
; 2 - start of new block
|
|
; -------------------------------------------------------
|
|
bdos_wrbuff:
|
|
CALL BIOS.write_f
|
|
|
|
; -------------------------------------------------------
|
|
; Check for disk errors
|
|
; -------------------------------------------------------
|
|
diocomp:
|
|
OR A
|
|
RET Z
|
|
LD HL, bdos_pere_addr ;= C899h
|
|
JP bdos_goerr
|
|
|
|
; -------------------------------------------------------
|
|
; Seek the record containing the current dir entry
|
|
; -------------------------------------------------------
|
|
bdos_seekdir:
|
|
LD HL, (TM_VARS.bdos_dcnt)
|
|
LD C, DSK_SHF
|
|
CALL bdos_hlrotr
|
|
LD (TM_VARS.bdos_arecord), HL
|
|
LD (TM_VARS.bdos_drec), HL
|
|
|
|
; -------------------------------------------------------
|
|
; Seek the track given by arecord (actual record)
|
|
; local equates for registers
|
|
; -------------------------------------------------------
|
|
bdos_seek:
|
|
LD HL, TM_VARS.bdos_arecord
|
|
LD C, (HL)
|
|
INC HL
|
|
LD B, (HL)
|
|
LD HL, (TM_VARS.bdos_curreca)
|
|
LD E, (HL)
|
|
INC HL
|
|
LD D, (HL)
|
|
LD HL, (TM_VARS.bdos_curtrka)
|
|
LD A, (HL)
|
|
INC HL
|
|
LD H, (HL)
|
|
LD L, A
|
|
bseek_l0:
|
|
LD A, C
|
|
SUB E
|
|
LD A, B
|
|
SBC A, D
|
|
JP NC, bseek_l1
|
|
PUSH HL
|
|
LD HL, (TM_VARS.dbos_sectpt)
|
|
LD A, E
|
|
SUB L
|
|
LD E, A
|
|
LD A, D
|
|
SBC A, H
|
|
LD D, A
|
|
POP HL
|
|
DEC HL
|
|
JP bseek_l0
|
|
bseek_l1:
|
|
PUSH HL
|
|
LD HL, (TM_VARS.dbos_sectpt)
|
|
ADD HL, DE
|
|
JP C, bseek_l2
|
|
LD A, C
|
|
SUB L
|
|
LD A, B
|
|
SBC A, H
|
|
JP C, bseek_l2
|
|
EX DE, HL
|
|
POP HL
|
|
INC HL
|
|
JP bseek_l1
|
|
bseek_l2:
|
|
POP HL
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
; Stack contains (lowest) BC=arecord, DE=currec, HL=curtrk
|
|
EX DE, HL
|
|
LD HL, (TM_VARS.bdos_offset)
|
|
ADD HL, DE
|
|
LD B, H
|
|
LD C,L
|
|
CALL BIOS.settrk_f
|
|
POP DE
|
|
LD HL, (TM_VARS.bdos_curtrka)
|
|
LD (HL), E
|
|
INC HL
|
|
LD (HL), D
|
|
POP DE
|
|
LD HL, (TM_VARS.bdos_curreca)
|
|
LD (HL), E
|
|
INC HL
|
|
LD (HL), D
|
|
POP BC
|
|
LD A, C
|
|
SUB E
|
|
LD C, A
|
|
LD A, B
|
|
SBC A, D
|
|
LD B, A
|
|
LD HL, (TM_VARS.bdos_tranv)
|
|
EX DE, HL
|
|
CALL BIOS.sectran_f
|
|
LD C,L
|
|
LD B, H
|
|
JP BIOS.setsec_f
|
|
|
|
; -------------------------------------------------------
|
|
; Compute disk map position for vrecord to HL
|
|
; -------------------------------------------------------
|
|
bdos_dm_position:
|
|
LD HL, TM_VARS.bdos_blkshf
|
|
LD C, (HL)
|
|
LD A, (TM_VARS.bdos_vrecord)
|
|
dmpos_l0:
|
|
OR A
|
|
RRA
|
|
DEC C
|
|
JP NZ, dmpos_l0
|
|
; A = shr(vrecord, blkshf) = vrecord/2**(sect/block)
|
|
LD B, A
|
|
LD A, 0x8
|
|
SUB (HL)
|
|
LD C, A
|
|
LD A, (TM_VARS.bdos_extval)
|
|
dmpos_l1:
|
|
DEC C
|
|
JP Z, dmpos_l2
|
|
OR A
|
|
RLA
|
|
JP dmpos_l1
|
|
dmpos_l2:
|
|
ADD A, B
|
|
RET ; with dm_position in A
|
|
|
|
; -------------------------------------------------------
|
|
; Return disk map value from position given by BC
|
|
; -------------------------------------------------------
|
|
dbos_getdm:
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD DE, DSK_MAP
|
|
ADD HL, DE
|
|
ADD HL, BC
|
|
LD A, (TM_VARS.bdos_single)
|
|
OR A
|
|
JP Z,getdmd
|
|
LD L, (HL)
|
|
LD H, 0x00
|
|
RET
|
|
|
|
getdmd:
|
|
ADD HL, BC
|
|
LD E, (HL)
|
|
INC HL
|
|
LD D, (HL)
|
|
EX DE, HL
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Compute disk block number from current FCB
|
|
; -------------------------------------------------------
|
|
bdos_index:
|
|
CALL bdos_dm_position
|
|
LD C, A
|
|
LD B, 0x00
|
|
CALL dbos_getdm
|
|
LD (TM_VARS.bdos_arecord), HL
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Called following index to see if block allocated
|
|
; -------------------------------------------------------
|
|
bdos_allocated:
|
|
LD HL, (TM_VARS.bdos_arecord)
|
|
LD A,L
|
|
OR H
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Compute actual record address, assuming index called
|
|
; -------------------------------------------------------
|
|
bdos_atran:
|
|
LD A, (TM_VARS.bdos_blkshf)
|
|
LD HL, (TM_VARS.bdos_arecord)
|
|
bdatarn_l0:
|
|
ADD HL, HL
|
|
DEC A
|
|
JP NZ, bdatarn_l0
|
|
LD (TM_VARS.bdos_arecord1), HL
|
|
LD A, (TM_VARS.bdos_blmsk)
|
|
LD C, A
|
|
LD A, (TM_VARS.bdos_vrecord)
|
|
AND C
|
|
OR L
|
|
LD L, A
|
|
LD (TM_VARS.bdos_arecord), HL
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Get current extent field address to A
|
|
; -------------------------------------------------------
|
|
bdos_getexta:
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD DE, EXT_NUM
|
|
ADD HL, DE ; HL -> .fcb(extnum)
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Compute reccnt and nxtrec addresses for get/setfcb
|
|
; -------------------------------------------------------
|
|
bdos_getfcba:
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD DE,REC_CNT
|
|
ADD HL, DE
|
|
EX DE, HL
|
|
LD HL, 0x11 ; (nxtrec-reccnt)
|
|
ADD HL, DE
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Set variables from currently addressed fcb
|
|
; -------------------------------------------------------
|
|
bdos_getfcb:
|
|
CALL bdos_getfcba
|
|
LD A, (HL)
|
|
LD (TM_VARS.bdos_vrecord), A
|
|
EX DE, HL
|
|
LD A, (HL)
|
|
LD (TM_VARS.bdos_rcount), A
|
|
CALL bdos_getexta
|
|
LD A, (TM_VARS.bdos_extmsk)
|
|
AND (HL)
|
|
LD (TM_VARS.bdos_extval), A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Place values back into current fcb
|
|
; -------------------------------------------------------
|
|
bdos_setfcb:
|
|
CALL bdos_getfcba
|
|
LD A, (TM_VARS.bdos_seqio)
|
|
CP 0x2
|
|
JP NZ, bsfcb_l0
|
|
XOR A
|
|
bsfcb_l0:
|
|
LD C, A
|
|
LD A, (TM_VARS.bdos_vrecord)
|
|
ADD A, C
|
|
LD (HL), A
|
|
EX DE, HL
|
|
LD A, (TM_VARS.bdos_rcount)
|
|
LD (HL), A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Rotate HL right by C bits
|
|
; -------------------------------------------------------
|
|
bdos_hlrotr:
|
|
INC C
|
|
bhlr_nxt:
|
|
DEC C
|
|
RET Z
|
|
LD A, H
|
|
OR A
|
|
RRA
|
|
LD H, A
|
|
LD A,L
|
|
RRA
|
|
LD L, A
|
|
JP bhlr_nxt
|
|
|
|
; -------------------------------------------------------
|
|
; Compute checksum for current directory buffer
|
|
; -------------------------------------------------------
|
|
bdos_compute_cs:
|
|
LD C, REC_SIZ ; size of directory buffer
|
|
LD HL, (TM_VARS.bdos_buffa)
|
|
XOR A
|
|
bcompcs_l0:
|
|
ADD A, (HL)
|
|
INC HL
|
|
DEC C
|
|
JP NZ, bcompcs_l0
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Rotate HL left by C bits
|
|
; -------------------------------------------------------
|
|
bdos_hlrotl:
|
|
INC C
|
|
brothll_nxt:
|
|
DEC C
|
|
RET Z
|
|
ADD HL, HL
|
|
JP brothll_nxt
|
|
|
|
; -------------------------------------------------------
|
|
; Set a "1" value in curdsk position of BC
|
|
; -------------------------------------------------------
|
|
bdos_set_cdisk:
|
|
PUSH BC
|
|
LD A, (TM_VARS.bdos_curdsk)
|
|
LD C, A
|
|
LD HL, 0x1
|
|
CALL bdos_hlrotl
|
|
POP BC
|
|
LD A, C
|
|
OR L
|
|
LD L, A
|
|
LD A, B
|
|
OR H
|
|
LD H, A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Return true if dir checksum difference occurred
|
|
; -------------------------------------------------------
|
|
bdos_nowrite:
|
|
LD HL, (TM_VARS.bdos_rodsk)
|
|
LD A, (TM_VARS.bdos_curdsk)
|
|
LD C, A
|
|
CALL bdos_hlrotr
|
|
LD A,L
|
|
AND 0x1
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Temporarily set current drive to be read-only;
|
|
; attempts to write to it will fail
|
|
; -------------------------------------------------------
|
|
bdos_set_ro:
|
|
LD HL, TM_VARS.bdos_rodsk
|
|
LD C, (HL)
|
|
INC HL
|
|
LD B, (HL)
|
|
|
|
CALL bdos_set_cdisk
|
|
LD (TM_VARS.bdos_rodsk), HL
|
|
; high water mark in directory goes to max
|
|
LD HL, (TM_VARS.bdos_dirmax)
|
|
INC HL
|
|
EX DE, HL
|
|
LD HL, (TM_VARS.bdos_cdrmaxa)
|
|
LD (HL), E
|
|
INC HL
|
|
LD (HL), D
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Check current directory element for read/only status
|
|
; -------------------------------------------------------
|
|
bdos_check_rodir:
|
|
CALL bdos_getdptra
|
|
|
|
; -------------------------------------------------------
|
|
; Check current buff(dptr) or fcb(0) for r/o status
|
|
; -------------------------------------------------------
|
|
bdos_check_rofile:
|
|
LD DE,RO_FILE
|
|
ADD HL, DE
|
|
LD A, (HL)
|
|
RLA
|
|
RET NC
|
|
LD HL, bdos_rofe_addr ;= C8B1h
|
|
JP bdos_goerr
|
|
|
|
; -------------------------------------------------------
|
|
; Check for write protected disk
|
|
; -------------------------------------------------------
|
|
bdos_check_write:
|
|
CALL bdos_nowrite
|
|
RET Z
|
|
LD HL, bdos_rode_addr ;= C8ABh
|
|
JP bdos_goerr
|
|
|
|
; -------------------------------------------------------
|
|
; Compute the address of a directory element at
|
|
; positon dptr in the buffer
|
|
; -------------------------------------------------------
|
|
bdos_getdptra:
|
|
LD HL, (TM_VARS.bdos_buffa)
|
|
LD A, (TM_VARS.bdos_dptr)
|
|
|
|
; -------------------------------------------------------
|
|
; HL = HL + A
|
|
; -------------------------------------------------------
|
|
bdos_hl_add_a:
|
|
ADD A,L
|
|
LD L, A
|
|
RET NC
|
|
INC H
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Compute the address of the module number
|
|
; bring module number to accumulator
|
|
; (high order bit is fwf (file write flag)
|
|
; -------------------------------------------------------
|
|
bdos_getmodnum:
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD DE, MOD_NUM
|
|
ADD HL, DE
|
|
LD A, (HL)
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Clear the module number field for user open/make
|
|
; -------------------------------------------------------
|
|
bdos_clr_modnum:
|
|
CALL bdos_getmodnum
|
|
LD (HL), 0x00
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Set fwf (file write flag)
|
|
; -------------------------------------------------------
|
|
setfwf:
|
|
CALL bdos_getmodnum
|
|
OR FWF_MASK
|
|
LD (HL), A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Return cy if cdrmax > dcnt
|
|
; -------------------------------------------------------
|
|
bdos_compcdr:
|
|
LD HL, (TM_VARS.bdos_dcnt)
|
|
EX DE, HL ; DE = directory counter
|
|
LD HL, (TM_VARS.bdos_cdrmaxa) ; HL=.cdrmax
|
|
LD A, E
|
|
SUB (HL)
|
|
INC HL
|
|
LD A, D
|
|
SBC A, (HL)
|
|
;Condition dcnt - cdrmax produces cy if cdrmax>dcnt
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; If not (cdrmax > dcnt) then cdrmax = dcnt+1
|
|
; -------------------------------------------------------
|
|
bdos_setcdr:
|
|
CALL bdos_compcdr
|
|
RET C
|
|
INC DE
|
|
LD (HL), D
|
|
DEC HL
|
|
LD (HL), E
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; HL = DE - HL
|
|
; -------------------------------------------------------
|
|
bdos_de_sub_hl:
|
|
LD A, E
|
|
SUB L
|
|
LD L, A
|
|
LD A, D
|
|
SBC A, H
|
|
LD H, A
|
|
RET
|
|
|
|
bdos_newchecksum:
|
|
LD C, TRUE
|
|
|
|
bdos_checksum:
|
|
LD HL, (TM_VARS.bdos_drec)
|
|
EX DE, HL
|
|
LD HL, (TM_VARS.BYTE_ram_ba66)
|
|
CALL bdos_de_sub_hl
|
|
RET NC
|
|
PUSH BC
|
|
CALL bdos_compute_cs
|
|
LD HL, (TM_VARS.BYTE_ram_ba57)
|
|
EX DE, HL
|
|
LD HL, (TM_VARS.bdos_drec)
|
|
ADD HL, DE
|
|
POP BC
|
|
INC C
|
|
JP Z, initial_cs
|
|
CP (HL)
|
|
RET Z
|
|
CALL bdos_compcdr
|
|
RET NC
|
|
CALL bdos_set_ro
|
|
RET
|
|
initial_cs:
|
|
LD (HL), A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Write the current directory entry, set checksum
|
|
; -------------------------------------------------------
|
|
bdos_wrdir:
|
|
CALL bdos_newchecksum
|
|
CALL bdos_setdir
|
|
LD C, 0x1
|
|
CALL bdos_wrbuff
|
|
JP bdos_setdata
|
|
|
|
; -------------------------------------------------------
|
|
; Read a directory entry into the directory buffer
|
|
; -------------------------------------------------------
|
|
bdos_rd_dir:
|
|
CALL bdos_setdir
|
|
CALL bdos_rdbuff
|
|
|
|
; -------------------------------------------------------
|
|
; Set data dma address
|
|
; -------------------------------------------------------
|
|
bdos_setdata:
|
|
LD HL, TM_VARS.bdos_dmaad
|
|
JP bdos_set_dma
|
|
|
|
; -------------------------------------------------------
|
|
; Set directory dma address
|
|
; -------------------------------------------------------
|
|
bdos_setdir:
|
|
LD HL, TM_VARS.bdos_buffa
|
|
|
|
; -------------------------------------------------------
|
|
; HL=.dma address to set (i.e., buffa or dmaad)
|
|
; -------------------------------------------------------
|
|
bdos_set_dma:
|
|
LD C, (HL)
|
|
INC HL
|
|
LD B, (HL)
|
|
JP BIOS.setdma_f
|
|
|
|
; -------------------------------------------------------
|
|
; Copy the directory entry to the user buffer
|
|
; after call to search or searchn by user code
|
|
; -------------------------------------------------------
|
|
bdos_dir_to_user:
|
|
LD HL, (TM_VARS.bdos_buffa)
|
|
EX DE, HL
|
|
LD HL, (TM_VARS.bdos_dmaad)
|
|
LD C,REC_SIZ
|
|
JP bdos_move
|
|
|
|
; -------------------------------------------------------
|
|
; return zero flag if at end of directory, non zero
|
|
; if not at end (end of dir if dcnt = 0ffffh)
|
|
; -------------------------------------------------------
|
|
bdos_end_of_dir:
|
|
LD HL, TM_VARS.bdos_dcnt
|
|
LD A, (HL)
|
|
INC HL
|
|
CP (HL)
|
|
RET NZ
|
|
INC A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Set dcnt to the end of the directory
|
|
; -------------------------------------------------------
|
|
bdos_set_end_dir:
|
|
LD HL, ENDDIR
|
|
LD (TM_VARS.bdos_dcnt), HL
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Read next directory entry, with C=true if initializing
|
|
; -------------------------------------------------------
|
|
bdos_read_dir:
|
|
LD HL, (TM_VARS.bdos_dirmax)
|
|
EX DE, HL
|
|
LD HL, (TM_VARS.bdos_dcnt)
|
|
INC HL
|
|
LD (TM_VARS.bdos_dcnt), HL
|
|
CALL bdos_de_sub_hl
|
|
JP NC, bdrd_l0
|
|
JP bdos_set_end_dir
|
|
bdrd_l0:
|
|
LD A, (TM_VARS.bdos_dcnt)
|
|
AND DSK_MSK
|
|
LD B, FCB_SHF
|
|
bdrd_l1:
|
|
ADD A, A
|
|
DEC B
|
|
JP NZ, bdrd_l1
|
|
LD (TM_VARS.bdos_dptr), A
|
|
OR A
|
|
RET NZ
|
|
PUSH BC
|
|
CALL bdos_seekdir
|
|
CALL bdos_rd_dir
|
|
POP BC
|
|
JP bdos_checksum
|
|
|
|
; -------------------------------------------------------
|
|
; Given allocation vector position BC, return with byte
|
|
; containing BC shifted so that the least significant
|
|
; bit is in the low order accumulator position. HL is
|
|
; the address of the byte for possible replacement in
|
|
; memory upon return, and D contains the number of shifts
|
|
; required to place the returned value back into position
|
|
; -------------------------------------------------------
|
|
bdos_getallocbit:
|
|
LD A, C
|
|
AND 00000111b
|
|
INC A
|
|
LD E, A
|
|
LD D, A
|
|
LD A, C
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
AND 00011111b
|
|
LD C, A
|
|
LD A, B
|
|
ADD A, A
|
|
ADD A, A
|
|
ADD A, A
|
|
ADD A, A
|
|
ADD A, A
|
|
OR C
|
|
LD C, A
|
|
LD A, B
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
AND 00011111b
|
|
LD B, A
|
|
LD HL, (TM_VARS.bdos_alloca) ; Base address of allocation vector
|
|
ADD HL, BC
|
|
LD A, (HL)
|
|
ga_rotl:
|
|
RLCA
|
|
DEC E
|
|
JP NZ, ga_rotl
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; BC is the bit position of ALLOC to set or reset. The
|
|
; value of the bit is in register E.
|
|
; -------------------------------------------------------
|
|
bdos_setallocbit:
|
|
PUSH DE
|
|
CALL bdos_getallocbit
|
|
AND 11111110b
|
|
POP BC
|
|
OR C
|
|
|
|
; -------------------------------------------------------
|
|
; Byte value from ALLOC is in register A, with shift count
|
|
; in register C (to place bit back into position), and
|
|
; target ALLOC position in registers HL, rotate and replace
|
|
; -------------------------------------------------------
|
|
bdos_sab_rotr:
|
|
RRCA
|
|
DEC D
|
|
JP NZ, bdos_sab_rotr
|
|
LD (HL), A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Scan the disk map addressed by dptr for non-zero
|
|
; entries, the allocation vector entry corresponding
|
|
; to a non-zero entry is set to the value of C (0,1)
|
|
; -------------------------------------------------------
|
|
bdos_scandm:
|
|
CALL bdos_getdptra
|
|
; HL addresses the beginning of the directory entry
|
|
LD DE, DSK_MAP
|
|
ADD HL, DE
|
|
PUSH BC
|
|
LD C, 0x11 ; fcblen-dskmap+1 - size of single b...
|
|
scandm_l0:
|
|
POP DE
|
|
DEC C
|
|
RET Z
|
|
PUSH DE
|
|
LD A, (TM_VARS.bdos_single)
|
|
OR A
|
|
JP Z, scandm_l1
|
|
PUSH BC
|
|
PUSH HL
|
|
LD C, (HL)
|
|
LD B, 0x00
|
|
JP scandm_l2
|
|
scandm_l1:
|
|
DEC C
|
|
PUSH BC
|
|
LD C, (HL)
|
|
INC HL
|
|
LD B, (HL)
|
|
PUSH HL
|
|
scandm_l2:
|
|
LD A, C
|
|
OR B
|
|
JP Z, scandm_l3
|
|
LD HL, (TM_VARS.bdos_maxall)
|
|
LD A,L
|
|
SUB C
|
|
LD A, H
|
|
SBC A, B
|
|
CALL NC, bdos_setallocbit
|
|
scandm_l3:
|
|
POP HL
|
|
INC HL
|
|
POP BC
|
|
JP scandm_l0
|
|
|
|
; -------------------------------------------------------
|
|
; Initialize the current disk
|
|
; lret = false, set to true if $ file exists
|
|
; compute the length of the allocation vector - 2
|
|
; -------------------------------------------------------
|
|
bdos_initialize:
|
|
LD HL, (TM_VARS.bdos_maxall)
|
|
LD C, 0x3
|
|
CALL bdos_hlrotr
|
|
INC HL
|
|
LD B, H
|
|
LD C,L
|
|
LD HL, (TM_VARS.bdos_alloca)
|
|
binitial_l0:
|
|
LD (HL), 0x00
|
|
INC HL
|
|
DEC BC
|
|
LD A, B
|
|
OR C
|
|
JP NZ, binitial_l0
|
|
LD HL, (TM_VARS.bdos_dirblk)
|
|
EX DE, HL
|
|
LD HL, (TM_VARS.bdos_alloca)
|
|
LD (HL), E
|
|
INC HL
|
|
LD (HL), D
|
|
CALL bdos_home
|
|
LD HL, (TM_VARS.bdos_cdrmaxa)
|
|
LD (HL), 0x3
|
|
INC HL
|
|
LD (HL), 0x00
|
|
CALL bdos_set_end_dir
|
|
binitial_l2:
|
|
LD C, TRUE
|
|
CALL bdos_read_dir
|
|
CALL bdos_end_of_dir
|
|
RET Z
|
|
CALL bdos_getdptra
|
|
LD A, EMPTY
|
|
CP (HL)
|
|
JP Z, binitial_l2
|
|
LD A, (TM_VARS.bdos_usercode)
|
|
CP (HL)
|
|
JP NZ, sbdos_pdollar
|
|
INC HL
|
|
LD A, (HL)
|
|
SUB '$'
|
|
JP NZ, sbdos_pdollar
|
|
; dollar file found, mark in lret
|
|
DEC A
|
|
LD (TM_VARS.bdos_aret), A
|
|
|
|
sbdos_pdollar:
|
|
LD C, 0x1
|
|
CALL bdos_scandm
|
|
CALL bdos_setcdr
|
|
JP binitial_l2
|
|
|
|
; -------------------------------------------------------
|
|
; copy directory location to lret following
|
|
; delete, rename, ...
|
|
; -------------------------------------------------------
|
|
bdos_copy_dirloc:
|
|
LD A, (TM_VARS.bdos_dirloc)
|
|
JP bdos_ret_a
|
|
|
|
; -------------------------------------------------------
|
|
; Compare extent# in A with that in C, return nonzero
|
|
; if they do not match
|
|
; -------------------------------------------------------
|
|
bdos_compex:
|
|
PUSH BC
|
|
PUSH AF
|
|
LD A, (TM_VARS.bdos_extmsk)
|
|
CPL
|
|
LD B, A
|
|
LD A, C
|
|
AND B
|
|
LD C, A
|
|
POP AF
|
|
AND B
|
|
SUB C
|
|
AND MAX_EXT
|
|
POP BC
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Search for directory element of length C at info
|
|
; -------------------------------------------------------
|
|
bdos_search:
|
|
LD A, 0xff
|
|
LD (TM_VARS.bdos_dirloc), A
|
|
LD HL, TM_VARS.bdos_searchl
|
|
LD (HL), C
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD (TM_VARS.bdos_searcha), HL
|
|
CALL bdos_set_end_dir
|
|
CALL bdos_home
|
|
|
|
; -------------------------------------------------------
|
|
; search for the next directory element, assuming
|
|
; a previous call on search which sets searcha and
|
|
; searchl
|
|
; -------------------------------------------------------
|
|
bdos_searchn:
|
|
LD C, FALSE
|
|
CALL bdos_read_dir
|
|
CALL bdos_end_of_dir
|
|
JP Z, bdos_search_fin
|
|
LD HL, (TM_VARS.bdos_searcha)
|
|
EX DE, HL
|
|
LD A, (DE)
|
|
CP EMPTY
|
|
JP Z, search_next
|
|
PUSH DE
|
|
CALL bdos_compcdr
|
|
POP DE
|
|
JP NC, bdos_search_fin
|
|
search_next:
|
|
CALL bdos_getdptra
|
|
LD A, (TM_VARS.bdos_searchl)
|
|
LD C, A
|
|
LD B, 0x00
|
|
search_loop:
|
|
LD A, C
|
|
OR A
|
|
JP Z, search_end
|
|
LD A, (DE)
|
|
CP 0x3f
|
|
JP Z, search_ok
|
|
LD A, B
|
|
CP 0xd
|
|
JP Z, search_ok
|
|
CP 0xc
|
|
LD A, (DE)
|
|
JP Z, search_ext
|
|
SUB (HL)
|
|
AND 0x7f
|
|
JP NZ, bdos_searchn
|
|
JP search_ok
|
|
; A has fcb character attempt an extent # match
|
|
search_ext:
|
|
PUSH BC
|
|
LD C, (HL)
|
|
CALL bdos_compex
|
|
POP BC
|
|
JP NZ, bdos_searchn
|
|
; current character matches
|
|
search_ok:
|
|
INC DE
|
|
INC HL
|
|
INC B
|
|
DEC C
|
|
JP search_loop
|
|
; entiry name matches, return dir position
|
|
search_end:
|
|
LD A, (TM_VARS.bdos_dcnt)
|
|
AND 0x3
|
|
LD (TM_VARS.bdos_aret), A
|
|
LD HL, TM_VARS.bdos_dirloc
|
|
LD A, (HL)
|
|
RLA
|
|
RET NC
|
|
XOR A
|
|
LD (HL), A
|
|
RET
|
|
|
|
; end of directory, or empty name
|
|
bdos_search_fin:
|
|
CALL bdos_set_end_dir
|
|
LD A, 0xff
|
|
JP bdos_ret_a
|
|
|
|
; -------------------------------------------------------
|
|
; Delete the currently addressed file
|
|
; -------------------------------------------------------
|
|
bdos_delete:
|
|
CALL bdos_check_write
|
|
LD C, EXT_NUM
|
|
CALL bdos_search
|
|
bdelete_l0:
|
|
CALL bdos_end_of_dir
|
|
RET Z
|
|
CALL bdos_check_rodir
|
|
CALL bdos_getdptra
|
|
LD (HL), EMPTY
|
|
LD C, 0x00
|
|
CALL bdos_scandm
|
|
CALL bdos_wrdir
|
|
CALL bdos_searchn
|
|
JP bdelete_l0
|
|
|
|
; -------------------------------------------------------
|
|
; Given allocation vector position BC, find the zero bit
|
|
; closest to this position by searching left and right.
|
|
; if found, set the bit to one and return the bit position
|
|
; in hl. if not found (i.e., we pass 0 on the left, or
|
|
; maxall on the right), return 0000 in hl
|
|
; -------------------------------------------------------
|
|
bdos_get_block:
|
|
LD D, B
|
|
LD E, C
|
|
bgb_lefttst:
|
|
LD A, C
|
|
OR B
|
|
JP Z, bgb_righttst
|
|
DEC BC
|
|
PUSH DE
|
|
PUSH BC
|
|
CALL bdos_getallocbit
|
|
RRA
|
|
JP NC, bgb_retblock
|
|
POP BC
|
|
POP DE
|
|
|
|
bgb_righttst:
|
|
LD HL, (TM_VARS.bdos_maxall)
|
|
LD A, E
|
|
SUB L
|
|
LD A, D
|
|
SBC A, H
|
|
JP NC, bgb_retblock0
|
|
INC DE
|
|
PUSH BC
|
|
PUSH DE
|
|
LD B, D
|
|
LD C, E
|
|
CALL bdos_getallocbit
|
|
RRA
|
|
JP NC, bgb_retblock
|
|
POP DE
|
|
POP BC
|
|
JP bgb_lefttst
|
|
bgb_retblock:
|
|
RLA
|
|
INC A
|
|
CALL bdos_sab_rotr
|
|
POP HL
|
|
POP DE
|
|
RET
|
|
bgb_retblock0:
|
|
LD A, C
|
|
OR B
|
|
JP NZ, bgb_lefttst
|
|
LD HL, 0x00
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Copy the entire file control block
|
|
; -------------------------------------------------------
|
|
bdos_copy_fcb:
|
|
LD C, 0x00
|
|
LD E, FCB_LEN
|
|
; -------------------------------------------------------
|
|
; copy fcb information starting at C for E bytes
|
|
; into the currently addressed directory entry
|
|
; -------------------------------------------------------
|
|
dbos_copy_dir:
|
|
PUSH DE
|
|
LD B, 0x00
|
|
LD HL, (TM_VARS.bdos_info)
|
|
ADD HL, BC
|
|
EX DE, HL
|
|
CALL bdos_getdptra
|
|
POP BC
|
|
CALL bdos_move
|
|
|
|
; -------------------------------------------------------
|
|
; Enter from close to seek and copy current element
|
|
; -------------------------------------------------------
|
|
bdos_seek_copy:
|
|
CALL bdos_seekdir
|
|
JP bdos_wrdir
|
|
|
|
; -------------------------------------------------------
|
|
; Rename the file described by the first half of
|
|
; the currently addressed file control block. the
|
|
; new name is contained in the last half of the
|
|
; currently addressed file conrol block. the file
|
|
; name and type are changed, but the reel number
|
|
; is ignored. the user number is identical
|
|
; -------------------------------------------------------
|
|
bdos_rename:
|
|
CALL bdos_check_write
|
|
LD C, EXT_NUM
|
|
CALL bdos_search
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD A, (HL)
|
|
LD DE, 0x10
|
|
ADD HL, DE
|
|
LD (HL), A
|
|
brn_l0:
|
|
CALL bdos_end_of_dir
|
|
RET Z
|
|
CALL bdos_check_rodir
|
|
LD C, DSK_MAP
|
|
LD E, EXT_NUM
|
|
CALL dbos_copy_dir
|
|
CALL bdos_searchn
|
|
JP brn_l0
|
|
|
|
; -------------------------------------------------------
|
|
; Set file indicators for current fcb
|
|
; -------------------------------------------------------
|
|
bdos_indicators:
|
|
LD C, EXT_NUM
|
|
CALL bdos_search
|
|
bdi_l0:
|
|
CALL bdos_end_of_dir
|
|
RET Z
|
|
LD C, 0x00
|
|
LD E, EXT_NUM
|
|
CALL dbos_copy_dir
|
|
CALL bdos_searchn
|
|
JP bdi_l0
|
|
|
|
; -------------------------------------------------------
|
|
; Search for the directory entry, copy to FCB
|
|
; -------------------------------------------------------
|
|
open:
|
|
LD C,NAM_LEN
|
|
CALL bdos_search
|
|
CALL bdos_end_of_dir
|
|
RET Z
|
|
|
|
bdos_open_copy:
|
|
CALL bdos_getexta
|
|
LD A, (HL)
|
|
PUSH AF
|
|
PUSH HL
|
|
CALL bdos_getdptra
|
|
EX DE, HL
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD C, 0x20
|
|
PUSH DE
|
|
CALL bdos_move
|
|
CALL setfwf
|
|
POP DE
|
|
LD HL, 0xc
|
|
ADD HL, DE
|
|
LD C, (HL)
|
|
LD HL, 0xf
|
|
ADD HL, DE
|
|
LD B, (HL)
|
|
POP HL
|
|
POP AF
|
|
LD (HL), A
|
|
LD A, C
|
|
CP (HL)
|
|
LD A, B
|
|
JP Z, bdos_open_rcnd
|
|
LD A, 0x00
|
|
JP C, bdos_open_rcnd
|
|
LD A, 0x80
|
|
|
|
bdos_open_rcnd:
|
|
LD HL, (TM_VARS.bdos_info) ; A has record count to fill
|
|
LD DE,REC_CNT
|
|
ADD HL, DE
|
|
LD (HL), A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; HL = .fcb1(i), DE = .fcb2(i),
|
|
; if fcb1(i) = 0 then fcb1(i) := fcb2(i)
|
|
; -------------------------------------------------------
|
|
bdos_mergezero:
|
|
LD A, (HL)
|
|
INC HL
|
|
OR (HL)
|
|
DEC HL
|
|
RET NZ
|
|
LD A, (DE)
|
|
LD (HL), A
|
|
INC DE
|
|
INC HL
|
|
LD A, (DE)
|
|
LD (HL), A
|
|
DEC DE
|
|
DEC HL
|
|
RET
|
|
|
|
bdos_close:
|
|
XOR A
|
|
LD (TM_VARS.bdos_aret), A
|
|
LD (TM_VARS.bdos_dcnt), A
|
|
LD (TM_VARS.bdos_dcnt_hi), A
|
|
CALL bdos_nowrite
|
|
RET NZ
|
|
CALL bdos_getmodnum
|
|
AND FWF_MASK
|
|
RET NZ
|
|
LD C,NAM_LEN
|
|
CALL bdos_search
|
|
CALL bdos_end_of_dir
|
|
RET Z
|
|
LD BC, DSK_MAP
|
|
CALL bdos_getdptra
|
|
ADD HL, BC
|
|
EX DE, HL
|
|
LD HL, (TM_VARS.bdos_info)
|
|
ADD HL, BC
|
|
LD C, 0x10 ; (fcblen-dskmap) ;length of single ...
|
|
bdos_merge0:
|
|
LD A, (TM_VARS.bdos_single)
|
|
OR A
|
|
JP Z, bdos_merge
|
|
LD A, (HL)
|
|
OR A
|
|
LD A, (DE)
|
|
JP NZ, bdm_fcbnzero
|
|
LD (HL), A
|
|
bdm_fcbnzero:
|
|
OR A
|
|
JP NZ, bdm_buffnzero
|
|
LD A, (HL)
|
|
LD (DE), A
|
|
bdm_buffnzero:
|
|
CP (HL)
|
|
JP NZ, bdm_mergerr
|
|
JP bdm_dmset ; merged ok
|
|
bdos_merge:
|
|
CALL bdos_mergezero
|
|
EX DE, HL
|
|
CALL bdos_mergezero
|
|
EX DE, HL
|
|
LD A, (DE)
|
|
CP (HL)
|
|
JP NZ, bdm_mergerr
|
|
INC DE
|
|
INC HL
|
|
LD A, (DE)
|
|
CP (HL)
|
|
JP NZ, bdm_mergerr
|
|
DEC C
|
|
bdm_dmset:
|
|
INC DE
|
|
INC HL
|
|
DEC C
|
|
JP NZ, bdos_merge0
|
|
LD BC, 0xffec ; -(fcblen-extnum)
|
|
ADD HL, BC
|
|
EX DE, HL
|
|
ADD HL, BC
|
|
LD A, (DE)
|
|
CP (HL)
|
|
JP C, bdm_endmerge
|
|
LD (HL), A
|
|
LD BC, 0x3 ; (reccnt-extnum)
|
|
ADD HL, BC
|
|
EX DE, HL
|
|
ADD HL, BC
|
|
LD A, (HL)
|
|
LD (DE), A
|
|
bdm_endmerge:
|
|
LD A, 0xff
|
|
LD (TM_VARS.bdos_fcb_copied), A
|
|
JP bdos_seek_copy
|
|
bdm_mergerr:
|
|
LD HL, TM_VARS.bdos_aret
|
|
DEC (HL)
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Create a new file by creating a directory entry
|
|
; then opening the file
|
|
; -------------------------------------------------------
|
|
bdos_make:
|
|
CALL bdos_check_write
|
|
LD HL, (TM_VARS.bdos_info)
|
|
PUSH HL
|
|
LD HL, TM_VARS.bdos_efcb
|
|
; Save FCB address, look for 0xE5
|
|
LD (TM_VARS.bdos_info), HL
|
|
LD C, 0x1
|
|
CALL bdos_search
|
|
CALL bdos_end_of_dir
|
|
POP HL
|
|
LD (TM_VARS.bdos_info), HL
|
|
RET Z
|
|
EX DE, HL
|
|
LD HL, NAM_LEN
|
|
ADD HL, DE
|
|
LD C, 0x11 ; fcblen-namlen
|
|
XOR A
|
|
bdm_set0:
|
|
LD (HL), A
|
|
INC HL
|
|
DEC C
|
|
JP NZ, bdm_set0
|
|
LD HL,U_BYTES
|
|
ADD HL, DE
|
|
LD (HL), A ; Current record within extent?
|
|
CALL bdos_setcdr
|
|
CALL bdos_copy_fcb
|
|
JP setfwf
|
|
|
|
; -------------------------------------------------------
|
|
; Close the current extent, and open the next one
|
|
; if possible. RMF is true if in read mod
|
|
; -------------------------------------------------------
|
|
bdos_open_reel:
|
|
XOR A
|
|
LD (TM_VARS.bdos_fcb_copied), A
|
|
CALL bdos_close
|
|
CALL bdos_end_of_dir
|
|
RET Z
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD BC, EXT_NUM
|
|
ADD HL, BC
|
|
LD A, (HL)
|
|
INC A
|
|
AND MAX_EXT
|
|
LD (HL), A
|
|
JP Z, bor_open_mod
|
|
LD B, A
|
|
LD A, (TM_VARS.bdos_extmsk)
|
|
AND B
|
|
LD HL, TM_VARS.bdos_fcb_copied
|
|
AND (HL)
|
|
JP Z, bor_open_reel0
|
|
JP bor_open_reel1
|
|
bor_open_mod:
|
|
LD BC, 0x2 ; (modnum-extnum)
|
|
ADD HL, BC
|
|
INC (HL)
|
|
LD A, (HL)
|
|
AND MAX_MOD
|
|
JP Z, bor_oper_r_err
|
|
bor_open_reel0:
|
|
LD C,NAM_LEN
|
|
CALL bdos_search
|
|
CALL bdos_end_of_dir
|
|
JP NZ, bor_open_reel1
|
|
LD A, (TM_VARS.bdos_rfm)
|
|
INC A
|
|
JP Z, bor_oper_r_err
|
|
CALL bdos_make
|
|
CALL bdos_end_of_dir
|
|
JP Z, bor_oper_r_err
|
|
JP bor_open_reel2
|
|
bor_open_reel1:
|
|
CALL bdos_open_copy
|
|
bor_open_reel2:
|
|
CALL bdos_getfcb
|
|
XOR A
|
|
JP bdos_ret_a
|
|
bor_oper_r_err:
|
|
CALL setlret1
|
|
JP setfwf
|
|
|
|
; -------------------------------------------------------
|
|
; Sequential disk read operation
|
|
; -------------------------------------------------------
|
|
bdos_seq_disk_read:
|
|
LD A, 0x1
|
|
LD (TM_VARS.bdos_seqio), A
|
|
; drop through to diskread
|
|
|
|
bdos_disk_read:
|
|
LD A, TRUE
|
|
LD (TM_VARS.bdos_rfm), A
|
|
CALL bdos_getfcb
|
|
LD A, (TM_VARS.bdos_vrecord)
|
|
LD HL, TM_VARS.bdos_rcount
|
|
CP (HL)
|
|
JP C, bdr_recordok
|
|
CP 128
|
|
JP NZ, bdr_diskeof
|
|
CALL bdos_open_reel
|
|
XOR A
|
|
LD (TM_VARS.bdos_vrecord), A
|
|
LD A, (TM_VARS.bdos_aret)
|
|
OR A
|
|
JP NZ, bdr_diskeof
|
|
bdr_recordok:
|
|
CALL bdos_index
|
|
CALL bdos_allocated
|
|
JP Z, bdr_diskeof
|
|
CALL bdos_atran
|
|
CALL bdos_seek
|
|
CALL bdos_rdbuff
|
|
JP bdos_setfcb
|
|
bdr_diskeof:
|
|
JP setlret1
|
|
|
|
; -------------------------------------------------------
|
|
; Sequential write disk
|
|
; -------------------------------------------------------
|
|
bdos_seq_disk_write:
|
|
LD A, 0x1
|
|
LD (TM_VARS.bdos_seqio), A
|
|
bdos_disk_write:
|
|
LD A, FALSE
|
|
LD (TM_VARS.bdos_rfm), A
|
|
CALL bdos_check_write
|
|
LD HL, (TM_VARS.bdos_info)
|
|
CALL bdos_check_rofile
|
|
CALL bdos_getfcb
|
|
LD A, (TM_VARS.bdos_vrecord)
|
|
CP 0x80 ; lstrec+1
|
|
JP NC,setlret1
|
|
CALL bdos_index
|
|
CALL bdos_allocated
|
|
LD C, 0x00
|
|
JP NZ, bdw_disk_wr1
|
|
CALL bdos_dm_position
|
|
LD (TM_VARS.bdos_dminx), A
|
|
LD BC, 0x00
|
|
OR A
|
|
JP Z, bdw_nopblock
|
|
LD C, A
|
|
DEC BC
|
|
CALL dbos_getdm
|
|
LD B, H
|
|
LD C,L
|
|
bdw_nopblock:
|
|
CALL bdos_get_block
|
|
LD A,L
|
|
OR H
|
|
JP NZ, bdw_block_ok
|
|
LD A, 0x2
|
|
JP bdos_ret_a
|
|
bdw_block_ok:
|
|
LD (TM_VARS.bdos_arecord), HL
|
|
EX DE, HL
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD BC, DSK_MAP
|
|
ADD HL, BC
|
|
LD A, (TM_VARS.bdos_single)
|
|
OR A
|
|
LD A, (TM_VARS.bdos_dminx)
|
|
JP Z, bdw_alloc_w
|
|
CALL bdos_hl_add_a
|
|
LD (HL), E
|
|
JP bdw_disk_wru
|
|
bdw_alloc_w:
|
|
LD C, A
|
|
LD B, 0x00
|
|
ADD HL, BC
|
|
ADD HL, BC
|
|
LD (HL), E
|
|
INC HL
|
|
LD (HL), D
|
|
; Disk write to previously unallocated block
|
|
bdw_disk_wru:
|
|
LD C, 0x2
|
|
bdw_disk_wr1:
|
|
LD A, (TM_VARS.bdos_aret)
|
|
OR A
|
|
RET NZ
|
|
PUSH BC
|
|
CALL bdos_atran
|
|
LD A, (TM_VARS.bdos_seqio)
|
|
DEC A
|
|
DEC A
|
|
JP NZ, bdw_disk_wr11
|
|
POP BC
|
|
PUSH BC
|
|
LD A, C
|
|
DEC A
|
|
DEC A
|
|
JP NZ, bdw_disk_wr11
|
|
PUSH HL
|
|
LD HL, (TM_VARS.bdos_buffa)
|
|
LD D, A
|
|
bdw_fill0:
|
|
LD (HL), A
|
|
INC HL
|
|
INC D
|
|
JP P, bdw_fill0
|
|
CALL bdos_setdir
|
|
LD HL, (TM_VARS.bdos_arecord1)
|
|
LD C, 0x2
|
|
bdw_fill1:
|
|
LD (TM_VARS.bdos_arecord), HL
|
|
PUSH BC
|
|
CALL bdos_seek
|
|
POP BC
|
|
CALL bdos_wrbuff
|
|
LD HL, (TM_VARS.bdos_arecord)
|
|
LD C, 0x00
|
|
LD A, (TM_VARS.bdos_blmsk)
|
|
LD B, A
|
|
AND L
|
|
CP B
|
|
INC HL
|
|
JP NZ, bdw_fill1
|
|
POP HL
|
|
LD (TM_VARS.bdos_arecord), HL
|
|
CALL bdos_setdata
|
|
bdw_disk_wr11:
|
|
CALL bdos_seek
|
|
POP BC
|
|
PUSH BC
|
|
CALL bdos_wrbuff
|
|
POP BC
|
|
LD A, (TM_VARS.bdos_vrecord)
|
|
LD HL, TM_VARS.bdos_rcount
|
|
CP (HL)
|
|
JP C, bdw_disk_wr2
|
|
LD (HL), A
|
|
INC (HL)
|
|
LD C, 0x2
|
|
bdw_disk_wr2:
|
|
DEC C
|
|
DEC C
|
|
JP NZ, bwd_no_update
|
|
PUSH AF
|
|
CALL bdos_getmodnum
|
|
AND 0x7f ; (not fwfmsk) and 0ffh
|
|
LD (HL), A
|
|
POP AF
|
|
bwd_no_update:
|
|
CP LST_REC
|
|
JP NZ, bdw_disk_wr3
|
|
LD A, (TM_VARS.bdos_seqio)
|
|
CP 0x1
|
|
JP NZ, bdw_disk_wr3
|
|
CALL bdos_setfcb
|
|
CALL bdos_open_reel
|
|
LD HL, TM_VARS.bdos_aret
|
|
LD A, (HL)
|
|
OR A
|
|
JP NZ, bdw_no_space
|
|
DEC A
|
|
LD (TM_VARS.bdos_vrecord), A
|
|
bdw_no_space:
|
|
LD (HL), 0x00
|
|
bdw_disk_wr3:
|
|
JP bdos_setfcb
|
|
|
|
; -------------------------------------------------------
|
|
; Random access seek operation, C=0ffh if read mode
|
|
; FCB is assumed to address an active file control block
|
|
; (modnum has been set to 1100$0000b if previous bad seek)
|
|
; -------------------------------------------------------
|
|
bdos_rseek:
|
|
XOR A
|
|
LD (TM_VARS.bdos_seqio), A
|
|
bdos_rseek1:
|
|
PUSH BC
|
|
LD HL, (TM_VARS.bdos_info)
|
|
EX DE, HL
|
|
LD HL,RAN_REC
|
|
ADD HL, DE
|
|
LD A, (HL)
|
|
AND 7Fh
|
|
PUSH AF
|
|
LD A, (HL)
|
|
RLA
|
|
INC HL
|
|
LD A, (HL)
|
|
RLA
|
|
AND 00011111b
|
|
LD C, A
|
|
LD A, (HL)
|
|
RRA
|
|
RRA
|
|
RRA
|
|
RRA
|
|
AND 0xf
|
|
LD B, A
|
|
POP AF
|
|
INC HL
|
|
LD L, (HL)
|
|
INC L
|
|
DEC L
|
|
LD L, 0x6
|
|
JP NZ, brs_seek_err
|
|
LD HL, NXT_REC
|
|
ADD HL, DE
|
|
LD (HL), A
|
|
LD HL, 0xc
|
|
ADD HL, DE
|
|
LD A, C
|
|
SUB (HL)
|
|
JP NZ, brs_close
|
|
LD HL,MOD_NUM
|
|
ADD HL, DE
|
|
LD A, B
|
|
SUB (HL)
|
|
AND 0x7f
|
|
JP Z, brs_seek_ok
|
|
brs_close:
|
|
PUSH BC
|
|
PUSH DE
|
|
CALL bdos_close
|
|
POP DE
|
|
POP BC
|
|
LD L, 0x3 ; Cannot close error #3
|
|
LD A, (TM_VARS.bdos_aret)
|
|
INC A
|
|
JP Z, brs_bad_seek
|
|
LD HL, EXT_NUM
|
|
ADD HL, DE
|
|
LD (HL), C
|
|
LD HL, MOD_NUM
|
|
ADD HL, DE
|
|
LD (HL), B
|
|
CALL open
|
|
LD A, (TM_VARS.bdos_aret)
|
|
INC A
|
|
JP NZ, brs_seek_ok
|
|
POP BC
|
|
PUSH BC
|
|
LD L, 0x4 ; Seek to unwritten extent #4
|
|
INC C
|
|
JP Z, brs_bad_seek
|
|
CALL bdos_make
|
|
LD L, 0x5 ; Cannot create new extent #5
|
|
LD A, (TM_VARS.bdos_aret)
|
|
INC A
|
|
JP Z, brs_bad_seek
|
|
brs_seek_ok:
|
|
POP BC
|
|
XOR A
|
|
JP bdos_ret_a
|
|
brs_bad_seek:
|
|
PUSH HL
|
|
CALL bdos_getmodnum
|
|
LD (HL), 11000000b
|
|
POP HL
|
|
brs_seek_err:
|
|
POP BC
|
|
LD A,L
|
|
LD (TM_VARS.bdos_aret), A
|
|
JP setfwf
|
|
|
|
; -------------------------------------------------------
|
|
; Random disk read operation
|
|
; -------------------------------------------------------
|
|
bdos_rand_disk_read:
|
|
LD C, TRUE
|
|
CALL bdos_rseek
|
|
CALL Z, bdos_disk_read
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Random disk write operation
|
|
; -------------------------------------------------------
|
|
bdos_rand_disk_write:
|
|
LD C, FALSE
|
|
CALL bdos_rseek
|
|
CALL Z, bdos_disk_write
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Compute random record position for
|
|
; getfilesize/setrandom
|
|
; -------------------------------------------------------
|
|
bdos_compute_rr:
|
|
EX DE, HL
|
|
ADD HL, DE
|
|
LD C, (HL)
|
|
LD B, 0x00
|
|
LD HL, EXT_NUM
|
|
ADD HL, DE
|
|
LD A, (HL)
|
|
RRCA
|
|
AND 0x80
|
|
ADD A, C
|
|
LD C, A
|
|
LD A, 0x00
|
|
ADC A, B
|
|
LD B, A
|
|
LD A, (HL)
|
|
RRCA
|
|
AND 0xf
|
|
ADD A, B
|
|
LD B, A
|
|
LD HL,MOD_NUM
|
|
ADD HL, DE
|
|
LD A, (HL)
|
|
ADD A, A
|
|
ADD A, A
|
|
ADD A, A
|
|
ADD A, A
|
|
PUSH AF
|
|
ADD A, B
|
|
LD B, A
|
|
PUSH AF
|
|
POP HL
|
|
LD A,L
|
|
POP HL
|
|
OR L
|
|
AND 0x1
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Compute logical file size for current FCB
|
|
; -------------------------------------------------------
|
|
bdos_get_file_size:
|
|
LD C, EXT_NUM
|
|
CALL bdos_search
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD DE,RAN_REC
|
|
ADD HL, DE
|
|
PUSH HL
|
|
LD (HL), D
|
|
INC HL
|
|
LD (HL), D
|
|
INC HL
|
|
LD (HL), D
|
|
bgf_get_size:
|
|
CALL bdos_end_of_dir
|
|
JP Z, bgf_set_size
|
|
CALL bdos_getdptra
|
|
LD DE,REC_CNT
|
|
CALL bdos_compute_rr
|
|
POP HL
|
|
PUSH HL
|
|
LD E, A
|
|
LD A, C
|
|
SUB (HL)
|
|
INC HL
|
|
LD A, B
|
|
SBC A, (HL)
|
|
INC HL
|
|
LD A, E
|
|
SBC A, (HL)
|
|
JP C, bgf_get_nxt_size
|
|
LD (HL), E
|
|
DEC HL
|
|
LD (HL), B
|
|
DEC HL
|
|
LD (HL), C
|
|
bgf_get_nxt_size:
|
|
CALL bdos_searchn
|
|
JP bgf_get_size
|
|
bgf_set_size:
|
|
POP HL
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Set the random record count bytes of the FCB to the number
|
|
; of the last record read/written by the sequential I/O calls.
|
|
; Inp: DE -> FCB
|
|
; -------------------------------------------------------
|
|
bdos_set_random:
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD DE,NXT_REC
|
|
|
|
CALL bdos_compute_rr
|
|
LD HL,RAN_REC
|
|
ADD HL, DE ; HL = .fcb(ranrec)
|
|
LD (HL), C
|
|
INC HL
|
|
LD (HL), B
|
|
INC HL
|
|
LD (HL), A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Select disk info for subsequent input or output ops
|
|
; -------------------------------------------------------
|
|
bdos_select:
|
|
LD HL, (TM_VARS.bdos_dlog)
|
|
LD A, (TM_VARS.bdos_curdsk)
|
|
LD C, A
|
|
CALL bdos_hlrotr
|
|
PUSH HL
|
|
EX DE, HL
|
|
CALL dbos_selectdisk
|
|
POP HL
|
|
CALL Z, bdos_sel_error
|
|
LD A,L
|
|
RRA
|
|
RET C
|
|
LD HL, (TM_VARS.bdos_dlog)
|
|
LD C,L
|
|
LD B, H
|
|
CALL bdos_set_cdisk
|
|
LD (TM_VARS.bdos_dlog), HL
|
|
JP bdos_initialize
|
|
|
|
; -------------------------------------------------------
|
|
; Select disc
|
|
; Inp: E=drive number 0 for A:, 1 for B: up to 15 for P
|
|
; Out: L=A=0 - ok or 0FFh - error
|
|
; -------------------------------------------------------
|
|
bdos_select_disk:
|
|
LD A, (TM_VARS.bdos_linfo)
|
|
LD HL, TM_VARS.bdos_curdsk
|
|
CP (HL)
|
|
RET Z
|
|
LD (HL), A
|
|
JP bdos_select
|
|
|
|
; -------------------------------------------------------
|
|
bdos_reselect:
|
|
LD A, TRUE
|
|
LD (TM_VARS.bdos_resel), A
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD A, (HL)
|
|
AND 00011111b
|
|
DEC A
|
|
LD (TM_VARS.bdos_linfo), A
|
|
CP 30
|
|
JP NC, brs_noselect
|
|
LD A, (TM_VARS.bdos_curdsk)
|
|
LD (TM_VARS.bdos_olddsk), A
|
|
LD A, (HL)
|
|
LD (TM_VARS.bdos_fcbdsk), A
|
|
AND 11100000b
|
|
LD (HL), A
|
|
CALL bdos_select_disk
|
|
brs_noselect:
|
|
LD A, (TM_VARS.bdos_usercode)
|
|
LD HL, (TM_VARS.bdos_info)
|
|
OR (HL)
|
|
LD (HL), A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Return version number
|
|
; -------------------------------------------------------
|
|
bdos_get_version:
|
|
LD A, DVERS ; 0x22 - v2.2
|
|
JP bdos_ret_a
|
|
|
|
; -------------------------------------------------------
|
|
; Reset disk system - initialize to disk 0
|
|
; -------------------------------------------------------
|
|
bdos_reset_disks:
|
|
LD HL, 0x00
|
|
LD (TM_VARS.bdos_rodsk), HL
|
|
LD (TM_VARS.bdos_dlog), HL
|
|
XOR A
|
|
LD (TM_VARS.bdos_curdsk), A
|
|
LD HL, EXT_RAM.std_dma_buff
|
|
LD (TM_VARS.bdos_dmaad), HL
|
|
|
|
CALL bdos_setdata
|
|
JP bdos_select
|
|
|
|
; -------------------------------------------------------
|
|
; Open file
|
|
; Inp: DE -> FCB
|
|
; Out: BA and HL - error.
|
|
; -------------------------------------------------------
|
|
bdos_open_file:
|
|
CALL bdos_clr_modnum
|
|
CALL bdos_reselect
|
|
JP open
|
|
|
|
; -------------------------------------------------------
|
|
; Close file
|
|
; Inp: DE -> FCB
|
|
; Out: BA and HL - error.
|
|
; -------------------------------------------------------
|
|
bdos_close_file:
|
|
CALL bdos_reselect
|
|
JP bdos_close
|
|
|
|
; -------------------------------------------------------
|
|
; Search for first occurrence of a file
|
|
; Inp: DE -> FCB
|
|
; Out: BA and HL - error.
|
|
; -------------------------------------------------------
|
|
bdos_search_first:
|
|
LD C, 0x00
|
|
EX DE, HL
|
|
LD A, (HL)
|
|
CP '?'
|
|
JP Z, bsf_qselect
|
|
CALL bdos_getexta
|
|
LD A, (HL)
|
|
CP '?'
|
|
CALL NZ, bdos_clr_modnum
|
|
CALL bdos_reselect
|
|
LD C, NAM_LEN
|
|
bsf_qselect:
|
|
CALL bdos_search
|
|
JP bdos_dir_to_user
|
|
|
|
; -------------------------------------------------------
|
|
; Search for next occurrence of a file name
|
|
; Inp: DE -> FCB
|
|
; Out: BA and HL - error.
|
|
; -------------------------------------------------------
|
|
bdos_search_next:
|
|
LD HL, (TM_VARS.bdos_searcha)
|
|
LD (TM_VARS.bdos_info), HL
|
|
CALL bdos_reselect
|
|
CALL bdos_searchn
|
|
JP bdos_dir_to_user
|
|
|
|
; -------------------------------------------------------
|
|
; Remove directory
|
|
; Inp: DE -> FCB
|
|
; Out: BA and HL - error.
|
|
; -------------------------------------------------------
|
|
bdos_rm_dir:
|
|
CALL bdos_reselect
|
|
CALL bdos_delete
|
|
JP bdos_copy_dirloc
|
|
|
|
; -------------------------------------------------------
|
|
; Read next 128b record
|
|
; Inp: DE -> FCB
|
|
; Out: BA and HL - error.
|
|
; A=0 - Ok,
|
|
; 1 - end of file,
|
|
; 9 - invalid FCB,
|
|
; 10 - media changed,
|
|
; 0FFh - hardware error.
|
|
; -------------------------------------------------------
|
|
bdos_read_file:
|
|
CALL bdos_reselect
|
|
JP bdos_seq_disk_read
|
|
|
|
; -------------------------------------------------------
|
|
; Write next 128b record
|
|
; Inp: DE -> FCB
|
|
; Out: BA and HL - error.
|
|
; A=0 - Ok,
|
|
; 1 - directory full,
|
|
; 2 - disc full,
|
|
; 9 - invalid FCB,
|
|
; 10 - media changed,
|
|
; 0FFh - hardware error.
|
|
; -------------------------------------------------------
|
|
bdos_write_file:
|
|
CALL bdos_reselect
|
|
JP bdos_seq_disk_write
|
|
|
|
; -------------------------------------------------------
|
|
; Create file
|
|
; Inp: DE -> FCB.
|
|
; Out: Error in BA and HL
|
|
; A=0 - Ok,
|
|
; 0FFh - directory is full.
|
|
; -------------------------------------------------------
|
|
bdos_make_file:
|
|
CALL bdos_clr_modnum
|
|
CALL bdos_reselect
|
|
JP bdos_make
|
|
|
|
; -------------------------------------------------------
|
|
; Rename file. New name, stored at FCB+16
|
|
; Inp: DE -> FCB.
|
|
; Out: Error in BA and HL
|
|
; A=0-3 if successful;
|
|
; A=0FFh if error.
|
|
; -------------------------------------------------------
|
|
bdos_ren_file:
|
|
CALL bdos_reselect
|
|
CALL bdos_rename
|
|
JP bdos_copy_dirloc
|
|
|
|
; -------------------------------------------------------
|
|
; Return bitmap of logged-in drives
|
|
; Out: bitmap in HL.
|
|
; -------------------------------------------------------
|
|
bdos_get_login_vec:
|
|
LD HL, (TM_VARS.bdos_dlog)
|
|
JP sthl_ret
|
|
|
|
; -------------------------------------------------------
|
|
; Return current drive
|
|
; Out: A - currently selected drive. 0 => A:, 1 => B: etc.
|
|
; -------------------------------------------------------
|
|
bdos_get_cur_drive:
|
|
LD A, (TM_VARS.bdos_curdsk)
|
|
JP bdos_ret_a
|
|
|
|
; -------------------------------------------------------
|
|
; Set DMA address
|
|
; Inp: DE - address of DMA buffer
|
|
; -------------------------------------------------------
|
|
bdos_set_dma_addr:
|
|
EX DE, HL
|
|
LD (TM_VARS.bdos_dmaad), HL
|
|
JP bdos_setdata
|
|
|
|
; -------------------------------------------------------
|
|
; Return the login vector address
|
|
; Out: HL - address
|
|
; -------------------------------------------------------
|
|
bdos_get_logvect:
|
|
LD HL, (TM_VARS.bdos_alloca)
|
|
JP sthl_ret
|
|
|
|
; -------------------------------------------------------
|
|
; Temporarily set current drive to be read-only
|
|
; -------------------------------------------------------
|
|
bdos_wr_protect:
|
|
LD HL, (TM_VARS.bdos_rodsk)
|
|
JP sthl_ret
|
|
|
|
; -------------------------------------------------------
|
|
; Set file indicators
|
|
; -------------------------------------------------------
|
|
bdos_set_ind:
|
|
CALL bdos_reselect
|
|
CALL bdos_indicators
|
|
JP bdos_copy_dirloc
|
|
|
|
; -------------------------------------------------------
|
|
; Return address of disk parameter block
|
|
; -------------------------------------------------------
|
|
bdos_get_dpb:
|
|
LD HL, (TM_VARS.bdos_dpbaddr)
|
|
sthl_ret:
|
|
LD (TM_VARS.bdos_aret), HL
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Get/set user number
|
|
; Inp: E - number 0-15. If E=0FFh, returns number in A.
|
|
;
|
|
; -------------------------------------------------------
|
|
bdos_set_user:
|
|
LD A, (TM_VARS.bdos_linfo)
|
|
CP 0xff
|
|
JP NZ, bsu_set_user
|
|
LD A, (TM_VARS.bdos_usercode)
|
|
JP bdos_ret_a
|
|
bsu_set_user:
|
|
AND 0x1f
|
|
LD (TM_VARS.bdos_usercode), A
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Random read. Record specified in the random record count area of the FCB, at the DMA address*
|
|
; Inp: DE -> FCB
|
|
; Out: Error codes in BA and HL.
|
|
; -------------------------------------------------------
|
|
bdos_rand_read:
|
|
CALL bdos_reselect
|
|
JP bdos_rand_disk_read
|
|
|
|
; -------------------------------------------------------
|
|
; Random access write record.
|
|
; Record specified in the random record count area of the FCB, at the DMA address
|
|
; Inp: DE -> FCB
|
|
; Out: Error codes in BA and HL.
|
|
; -------------------------------------------------------
|
|
bdos_rand_write:
|
|
|
|
CALL bdos_reselect
|
|
JP bdos_rand_disk_write
|
|
|
|
; -------------------------------------------------------
|
|
; Compute file size.
|
|
; Set the random record count bytes of the FCB to the
|
|
; number of 128-byte records in the file.
|
|
; -------------------------------------------------------
|
|
bdos_compute_fs:
|
|
CALL bdos_reselect
|
|
JP bdos_get_file_size
|
|
|
|
; -------------------------------------------------------
|
|
; Selectively reset disc drives
|
|
; Inp: DE - bitmap of drives to reset.
|
|
; Out: A=0 - Ok, 0FFh if error
|
|
; -------------------------------------------------------
|
|
bdos_reset_drives:
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD A,L
|
|
CPL
|
|
LD E, A
|
|
LD A, H
|
|
CPL
|
|
LD HL, (TM_VARS.bdos_dlog)
|
|
AND H
|
|
LD D, A
|
|
LD A,L
|
|
AND E
|
|
LD E, A
|
|
LD HL, (TM_VARS.bdos_rodsk)
|
|
EX DE, HL
|
|
LD (TM_VARS.bdos_dlog), HL
|
|
LD A,L
|
|
AND E
|
|
LD L, A
|
|
LD A, H
|
|
AND D
|
|
LD H, A
|
|
LD (TM_VARS.bdos_rodsk), HL
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Arrive here at end of processing to return to user
|
|
; -------------------------------------------------------
|
|
bdos_goback:
|
|
LD A, (TM_VARS.bdos_resel)
|
|
OR A
|
|
JP Z, bdos_ret_mon
|
|
LD HL, (TM_VARS.bdos_info)
|
|
LD (HL), 0x00
|
|
LD A, (TM_VARS.bdos_fcbdsk)
|
|
OR A
|
|
JP Z, bdos_ret_mon
|
|
LD (HL), A
|
|
LD A, (TM_VARS.bdos_olddsk)
|
|
LD (TM_VARS.bdos_linfo), A
|
|
CALL bdos_select_disk
|
|
|
|
; -------------------------------------------------------
|
|
; Return from the disk monitor
|
|
; -------------------------------------------------------
|
|
bdos_ret_mon:
|
|
LD HL, (TM_VARS.bdos_entsp)
|
|
LD SP, HL
|
|
LD HL, (TM_VARS.bdos_aret)
|
|
LD A,L
|
|
LD B, H
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Random disk write with zero fill of
|
|
; unallocated block
|
|
; -------------------------------------------------------
|
|
bdos_rand_write_z:
|
|
CALL bdos_reselect
|
|
LD A, 0x2
|
|
LD (TM_VARS.bdos_seqio), A
|
|
LD C, FALSE
|
|
CALL bdos_rseek1
|
|
CALL Z, bdos_disk_write
|
|
RET
|
|
|
|
; -------------------------------------------------------
|
|
; Initialized data ?
|
|
; -------------------------------------------------------
|
|
filler:
|
|
db 0xF1, 0xE1
|
|
|
|
; -------------------------------------------------------
|
|
; Filler to align blocks in ROM
|
|
; -------------------------------------------------------
|
|
LAST EQU $
|
|
CODE_SIZE EQU LAST-0xC800
|
|
FILL_SIZE EQU 0xE00-CODE_SIZE
|
|
|
|
DISPLAY "| BDOS\t| ",/H,bdos_start," | ",/H,CODE_SIZE," | ",/H,FILL_SIZE," |"
|
|
|
|
FILLER
|
|
DS FILL_SIZE, 0xFF
|
|
|
|
ENDMODULE
|
|
|
|
IFNDEF BUILD_ROM
|
|
OUTEND
|
|
ENDIF
|