Files
RomWBW/Source/CPM3/cpmldr.asm
b1ackmai1er 78f65522b7 Dev (#108)
* added hack to handle tunes

* quiet clean

* added chmod for execution

* suppress warnings

* Multi-boot fixes

* the windows build somehow thinks that these filesystems are cpm3.

* credit and primitive instructions

* Update sd.asm

Cosmetic fix.

* make compile shut up about conditionals

* Add bin2asm for linus and update build to process font files under linix

* fixed quoted double quote bug, added tests

* added tests

* added bin2asm for font file source creation

* Revert linux bin2asm font stuff

* added rule for font source generation

* build fonts

* added directory mapping cache.  if the same directory is being hit
as last run, we don't need to rebuild the map.  will likely break if
you are running more than one at a time, in that the cache will be
ineffective.  also, if the directory contents change, this will also break.

* removed strip.  breaks osx

* added directory tag so . isn't matched all over the place

* added real cache validation

* fixed build

* this file is copied from optdsk.lib or optcmd.lib

* install to ../HBIOS

* prerequisite verbosity

* diff soft failure and casefn speedup

* added lzsa

* added lzsa

* removed strip. breaks on osx

* added clobber

* added code to handle multiple platform rom builds with rom size override

* added align and 0x55 hex syntax

* default to hd64180

* added N8 capability

* added SBC_std.rom to default build

* added support for binary diff

* diff fixes

* clean, identical build.  font source generator emitted .align.  this does not match the windows build

* Upgrade NZCOM to latest

* Misc. Cleanup

* fixed expression parser bug : ~(1|2) returned 0xfe

* added diff build option

* Update Makefile

Makefile enhancement to better handle ncurses library from Bob Dunlop.

* Update sd.asm

Back out hack for uz80as now that Curt fixed it.

* Misc. Cleanup

* UNA Catchup

UNA support was lacking some of the more recent behavior changes.  This corrects most of it.

* Add github action for building RomWBW

* Bump Pre-release Version

* Update build.yml

Added "make clean" which will remove temporary files without removing final binary outputs.

* Update Makefile

Build all ROM variants by default in Linux/Mac build.

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update for GitHub Build

Case issue in TASM includes showing up in GitHub build.  This should correct that.

* Added an gitignore files to exclude generated files

* Removed Tunes/clean.cmd and Tunes/ReadMe.txt - as make clean removes them

* Build.sh: marked as executable

chmod +x Build.sh

* Fix to HBIOS/build.sh

When adding files to rom disk, if files were missing, it would error out.

It appears the intent is to skip non-existing files.

Updated to log out correctly for missing files - and continue operation.

* Update Microsoft NASCOM BASIC.docx

Nascom manual, text version by Jan S (full name unknown)

* Fix issue with Apps/Tune not making

If dest directory does not exist, fails to make Apps

* Create ReadMe.txt

* Update Makefile

* Update Build.sh

* Make .gitignores for Tools/unix more specific

* cpmtools Update

Updated cpmtools applications (Windows only).  Removed hack in diskdefs that is no longer required.

* HBIOS Proxy Temp Stack Enhancement

Reuse the bounce buffer area as the temporary stack space required briefly in HBX_INVOKE when transitioning banks.  Increases size of temporary stack space to 64 bytes.

* Update ReadMe.txt

* HBIOS - clean up TMPSTK

* Update hbios.asm

Minor cosmetic changes.

* Build Process Updates

Minor udpates to build process to improve consistency between Windows and Mac/Linux builds.

* Update hbios.asm

Add improved interrupt protection to HBIOS PEEK, POKE, and BNKCPY functions.

* hbios - wrap hbx_bnkcpy

* hbios - adjust hbx_peek hbx_poke guards

* Update hbios.asm

Adjusted used of DI/EI for PEEK and POKE to regain a bit of INTSTK space.  Added code so that HB_INVBNK can be used as a flag indicating if HBIOS is active, $FF is inactive, anything else means active.

* Add HBIOS MuTex

* Initial Nascom basic ecb-vdu graphics

set and reset for 80x25b screen with 256 character mod

* Finalize Pre-release 34

Final support for FreeRTOS

* Update nascom.asm

Optimization, cleanup, tabs and white spaces

* IDE & PPIDE Cleanup

* Clean up

Make version include files common.

* Update Makefile

* Update Makefile

* Build Test

* Build Test

* Build Fixes

* Update nascom.asm

Cleanup

* Update nascom.asm

Optimization

* hbios - temp stack tweak

* Update hbios.asm

Comments on HBX_BUF usage.

* Update nascom.asm

Optimization

* Update nascom.asm

Setup ECB-VDU build option, remove debug code

* Update nascom.asm

Set default build. update initialization

* Update nascom.asm

Make CLS clear vdu screen

* Update nascom.asm

Fixup top screen line not showing

* Add SC131 Support

Also cleaned up some ReadMe files.

* HBIOS SCZ180 - remove mutex special files

* HBIOS SCZ180 - adjust mutex comment

* Misc. Cleanup

Includes some minor improvements to contents in some disk images.

* Delete FAT.COM

Changing case of FAT.COM extension to lowercase.

* Create FAT.com

Completing change of case in extension of FAT.com.

* Update Makefile

Remove ROM variants that just have the HBIOS MUTEX enabled.  Users can easily enable this in a custom build.

* Cleanup

Removed hack from Images Makefile.  Fixed use of DEFSERCFG in various places.

* GitHub CI Updates

Adds automation of build and release assets upon release.

* Prerelease 36

General cleanup

* Build Script Cleanups

* Config File Cleanups

* Update RomWBW Architecture

General refresh for v2.9.2

* Update vdu.asm

Removed a hack in VDU driver that has existed for 8 years.  :-)

* Fix CONSOLE Constant

Rename CIODEV_CONSOLE constant to CIO_CONSOLE because it is a unit code, not a device type code.

Retabify TastyBasic.

* Minor Bug Fixes

- Disk assignment edge case
- CP/M 3 accidental fall thru
- Cosmetic updates

* Update util.z80

* Documentation Cleanup

* Documentation Update

* Documentation Update

* Documentation Updates

* Documentation Updates

* Create Common.inc

* Documentation Updates

* Documentation Updates

* doc - a few random fixes

* Documentation Cleanup

* Fix IM 0 Build Error in ACIA

* Documentation Updates

* Documentation Cleanup

* Remove OSLDR

The OSLDR application was badly broken and almost impossible to fix with new expanded OS support.

* Bug Fixes

- Init RAM disk at boot under CP/M 3
- Fix ACR activation in TUNE

* FD Motor Timeout

- Made FDC motor timeout smaller and more consistent across different speed CPUs
- Added "boot" messaging to RTC

* Cleanup

* Cleanup

- Fix SuperZAP to work under NZCOM and ZPM3
- Finalize standard config files

* Minor Changes

- Slight change to ZAP configuration
- Added ZSDOS.ZRL to NZCOM image

* ZDE Upgrade

- Upgraded ZDE 1.6 -> 1.6a

* Config File Tuning

* Pre-release for Testing

* cfg - mutex consistent config language

* Bump to Version 3.0

* Update SD Card How-To

Thanks David!

* update ReadMe.md

Remove some odd `\`.

* Update ReadMe.txt

* Update ReadMe.md

* Update Generated Doc Files

* Improve XModem Startup

- Extended startup timeout for XM.COM so that it doesn't timeout so quickly while host is selecing a file to send.
- Updated SD Card How-To from David Reese.

* XModem Timing Refinements

* TMS Driver Z180 Improvements

- TMS driver udpated to insert Z180 I/O waitstates internally so other code can run at full speed.
- Updated How-To documents from David.
- Fixed TUNE app to properly restore Z180 I/O waitstates after manipulating them.

* CLRDIR and ZDE updates

- CLRDIR has been updated by Max Scane for CP/M 3 compatibility.
- A minor issue in the preconfigured ZDE VT100 terminal escape sequences was corrected.

* Fix Auto CRT Console Switch on CP/M 3

* Handle lack of RTC better

DSRTC driver now correctly returns an error if there is no RTC present.

* Minor RTC Updates

* Finalize v3.0.1

Cleanup release for v3.0

* New ROMLDR and INTRTC driver

- Refactored romldr.asm
- Added new periodic timer based RTC driver

* CP/M 3 Date Hack

- Hack to allow INTRTC to increment time without destroying the date

* Update romldr.asm

Work around minor Linux build inconsistency

* Update Apps for New Version

* Revert "Update Apps for New Version"

This reverts commit ad80432252.

* Revert "Update romldr.asm"

This reverts commit 4a9825cd57.

* Revert "CP/M 3 Date Hack"

This reverts commit 153b494e61.

* Revert "New ROMLDR and INTRTC driver"

This reverts commit d9bed4563e.

* Start v3.1 Development

* Update FDISK80.COM

Updated FDISK80 to allow reserving up to 256 slices.

* Update sd.asm

For Z180 CSIO, ensure that xmit is finished, before asserting CS for next transaction.

* Add RC2014 UART, Improve SD protocol fix

- RC2014 and related platforms will autodetect a UART at 0xA0 and 0xA8
- Ensure that CS fully brackets all SD I/O

* ROMLDR Improvements

.com files can now be started from CP/M and size of .com files has been reduced so they always fit.

* Update commit.yml

Run commit build in all branches

* Update commit.yml

Run commit build for master and dev branches

* Improved clock driver auto-detect/fallback

* SIO driver now CTC aware

The SIO driver can now use a CTC (if available) to provide much more flexible baud rate programming.

* CTC driver fine tuning

* Update xmdm125.asm

Fixed a small issue in core XM125 code that caused a file write error message to not be displayed when it should be.

* CF Card compatibility improvement

Older CF Cards did not reset IDE registers to defaults values when reset.  Implemented a work around.

* Update ACIA detection

ACIA should no longer be detected if there is also a UART module in the system.

* Handle CTC anomaly

Small update to accommodate CTC behavior that occurs when the CTC trigger is more than half the CTC clock.

* Update acia.asm

Updated ACIA detection to use primary ACIA port instead of phantom port.

* Update acia.asm

Fix bug in ACIA detection.

Thanks Alan!

* MacOS Build Improvement

Build script updated to improve compatibility with MacOS.

Credit to Fredrik Axtelius for this.

* HBIOS Makefile - use env vars for target

Allow build ROM targets to be restricted to just one platform thru use of ENV vars:

ROM_PLATFORM - if defined to a known platform, only this platform is build - defaults to std config
ROM_CONFIG - sets the desired platform config - defaults to std

if the above ENVs are not defined, builds all ROMs

* Added some more gitignores

* Whitespace changes (crlf)

* HBIOS: Force the assembly to fail for vdu drivers if function table count is not correct

* Whitespace: trailing whitespaces

* makefile: updated some make scripts to use  when calling subdir makefiles

* linux build: update to Build.sh fix for some platforms

The initialization of the Rom dat file used the pipe (|) operator to build an initial empty file.

But the pipe operator | may sometimes return a non-zero exit code for some linux platforms, if the
the streams are closed before dd has fully processed the stream.

This issue occured on a travis linux ubuntu image.

Solution was to change to redirection.

* Bump version

* Enhance CTC periodic timer

Add ability to use TIMER mode in CTC driver to generate priodic interrupts.

* HBIOS: Added support for sound drivers

New sound driver support with initial support for the SN76489 chip

New build configuration entry:
* SN76489ENABLE

Ports are currently locked in with:
* SN76489_PORT_LEFT       .EQU    $FC     ; PORTS FOR ACCESSING THE SN76489 CHIP (LEFT)
* SN76489_PORT_RIGHT      .EQU    $F8     ; PORTS FOR ACCESSING THE SN76489 CHIP (LEFT)

* Miscellaneous Cleanup

No functional changes.

Co-authored-by: curt mayer <curt@zen-room.org>
Co-authored-by: Wayne Warthen <wwarthen@gmail.com>
Co-authored-by: ed <linux@maidavale.org>
Co-authored-by: Dean Netherton <dnetherton@dius.com.au>
Co-authored-by: ed <ed@maidavale.org>
Co-authored-by: Phillip Stevens <phillip.stevens@gmail.com>
Co-authored-by: Dean Netherton <dean.netherton@gmail.com>
2020-04-24 06:17:22 +08:00

1572 lines
37 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
title 'CP/M V3.0 Loader'
; Copyright (C) 1982
; Digital Research
; Box 579, Pacific Grove
; California, 93950
; Revised:
; 01 Nov 82 by Bruce Skidmore
base equ $
abase equ base-0100h
cr equ 0dh
lf equ 0ah
fcb equ abase+005ch ;default FCB address
buff equ abase+0080h ;default buffer address
;
; System Equates
;
resetsys equ 13 ;reset disk system
printbuf equ 09 ;print string
open$func equ 15 ;open function
read$func equ 20 ;read sequential
setdma$func equ 26 ;set dma address
;
; Loader Equates
;
comtop equ abase+80h
comlen equ abase+81h
bnktop equ abase+82h
bnklen equ abase+83h
osentry equ abase+84h
cseg
lxi sp,stackbot
call bootf ;first call is to Cold Boot
mvi c,resetsys ;Initialize the System
call bdos
mvi c,printbuf ;print the sign on message
lxi d,signon
call bdos
mvi c,open$func ;open the CPM3.SYS file
lxi d,cpmfcb
call bdos
cpi 0ffh
lxi d,openerr
jz error
lxi d,buff
call setdma$proc
call read$proc ;read the load record
lxi h,buff
lxi d,mem$top
mvi c,6
cloop:
mov a,m
stax d
inx d
inx h
dcr c
jnz cloop
call read$proc ;read display info
mvi c,printbuf ;print the info
lxi d,buff
call bdos
;
; Main System Load
;
;
; Load Common Portion of System
;
lda res$len
mov h,a
lda mem$top
call load
;
; Load Banked Portion of System
;
lda bank$len
ora a
jz execute
mov h,a
lda bank$top
call load
;
; Execute System
;
execute:
lxi h,fcb+1
mov a,m
cpi '$'
jnz execute$sys
inx h
mov a,m
cpi 'B'
cz break
execute$sys:
lxi sp,osentry$adr
ret
;
; Load Routine
;
; Input: A = Page Address of load top
; H = Length in pages of module to read
;
load:
ora a ;clear carry
mov d,a
mvi e,0
mov a,h
ral
mov h,a ;h = length in records of module
loop:
xchg
lxi b,-128
dad b ;decrement dma address by 128
xchg
push d
push h
call setdma$proc
call read$proc
pop h
pop d
dcr h
jnz loop
ret
;
; Set DMA Routine
;
setdma$proc:
mvi c,setdma$func
call bdos
ret
;
; Read Routine
;
read$proc:
mvi c,read$func ;Read the load record
lxi d,cpmfcb ;into address 80h
call bdos
ora a
lxi d,readerr
rz
;
; Error Routine
;
error:
mvi c,printbuf ;print error message
call bdos
di
hlt
break:
db 0ffh
ret
cpmfcb:
db 0,'CPM3 SYS',0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0,0
openerr:
db cr,lf
db 'CPMLDR error: failed to open CPM3.SYS'
db cr,lf,'$'
readerr:
db cr,lf
db 'CPMLDR error: failed to read CPM3.SYS'
db cr,lf,'$'
signon:
db cr
db lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf
db lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf
db 'CP/M V3.0 Loader',cr,lf
db 'Copyright (C) 1998, Caldera Inc. '
db cr,lf,'$'
maclib makedate
@BDATE ;[JCE] Build date
db 0,0,0,0
stackbot:
mem$top:
ds 1
res$len:
ds 1
bank$top:
ds 1
bank$len:
ds 1
osentry$adr:
ds 2
; title 'CP/M 3.0 LDRBDOS Interface, Version 3.1 Nov, 1982'
;*****************************************************************
;*****************************************************************
;** **
;** B a s i c D i s k O p e r a t i n g S y s t e m **
;** **
;** I n t e r f a c e M o d u l e **
;** **
;*****************************************************************
;*****************************************************************
;
; Copyright (c) 1978, 1979, 1980, 1981, 1982
; Digital Research
; Box 579, Pacific Grove
; California
;
; Nov 1982
;
;
; equates for non graphic characters
;
rubout equ 7fh ; char delete
tab equ 09h ; tab char
cr equ 0dh ; carriage return
lf equ 0ah ; line feed
ctlh equ 08h ; backspace
;
serial: db 0,0,0,0,0,0
;
; Enter here from the user's program with function number in c,
; and information address in d,e
;
bdos:
bdose: ; Arrive here from user programs
xchg! shld info! xchg ; info=de, de=info
mov a,c! cpi 14! jc bdose2
sta fx ; Save disk function #
xra a! sta dircnt
lda seldsk! sta olddsk ; Save seldsk
bdose2:
mov a,e! sta linfo ; linfo = low(info) - don't equ
lxi h,0! shld aret ; Return value defaults to 0000
shld resel ; resel = 0
; Save user's stack pointer, set to local stack
dad sp! shld entsp ; entsp = stackptr
lxi sp,lstack ; local stack setup
lxi h,goback ; Return here after all functions
push h ; jmp goback equivalent to ret
mov a,c! cpi nfuncs! jnc high$fxs ; Skip if invalid #
mov c,e ; possible output character to c
lxi h,functab! jmp bdos$jmp
; look for functions 100 ->
high$fxs:
sbi 100! jc lret$eq$ff ; Skip if function < 100
bdos$jmp:
mov e,a! mvi d,0 ; de=func, hl=.ciotab
dad d! dad d! mov e,m! inx h! mov d,m ; de=functab(func)
lhld info ; info in de for later xchg
xchg! pchl ; dispatched
; dispatch table for functions
functab:
dw func$ret, func1, func2, func3
dw func$ret, func$ret, func6, func$ret
dw func$ret, func9, func10, func11
diskf equ ($-functab)/2 ; disk funcs
dw func12,func13,func14,func15
dw func16,func17,func18,func19
dw func20,func21,func22,func23
dw func24,func25,func26,func27
dw func28,func29,func30,func31
dw func32,func33,func34,func35
dw func36,func37,func38,func39
dw func40,func42,func43
dw func44,func45,func46,func47
dw func48,func49,func50
nfuncs equ ($-functab)/2
entsp: ds 2 ; entry stack pointer
; 40 level stack
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
lstack:
page
title 'CP/M 3.0 LDRBDOS Interface, Version 3.1 July, 1982'
;*****************************************************************
;*****************************************************************
;** **
;** B a s i c D i s k O p e r a t i n g S y s t e m **
;** **
;** C o n s o l e P o r t i o n **
;** **
;*****************************************************************
;*****************************************************************
;
; July, 1982
;
;
; console handlers
conout:
;compute character position/write console char from C
;compcol = true if computing column position
lda compcol! ora a! jnz compout
;write the character, then compute the column
;write console character from C
push b ;recall/save character
call conoutf ;externally, to console
pop b ;recall the character
compout:
mov a,c ;recall the character
;and compute column position
lxi h,column ;A = char, HL = .column
cpi rubout! rz ;no column change if nulls
inr m ;column = column + 1
cpi ' '! rnc ;return if graphic
;not graphic, reset column position
dcr m ;column = column - 1
mov a,m! ora a! rz ;return if at zero
;not at zero, may be backspace or eol
mov a,c ;character back to A
cpi ctlh! jnz notbacksp
;backspace character
dcr m ;column = column - 1
ret
notbacksp:
;not a backspace character, eol?
cpi lf! rnz ;return if not
;end of line, column = 0
mvi m,0 ;column = 0
ret
;
;
tabout:
;expand tabs to console
mov a,c! cpi tab! jnz conout ;direct to conout if not
;tab encountered, move to next tab pos
tab0:
mvi c,' '! call conout ;another blank
lda column! ani 111b ;column mod 8 = 0 ?
jnz tab0 ;back for another if not
ret
;
print:
;print message until M(BC) = '$'
LXI H,OUTDELIM
ldax b! CMP M! rz ;stop on $
;more to print
inx b! push b! mov c,a ;char to C
call tabout ;another character printed
pop b! jmp print
;
;
func2: equ tabout
;write console character with tab expansion
;
func9:
;write line until $ encountered
xchg ;was lhld info
mov c,l! mov b,h ;BC=string address
jmp print ;out to console
;
sta$ret:
;store the A register to aret
sta aret
func$ret:
ret ;jmp goback (pop stack for non cp/m functions)
;
setlret1:
;set lret = 1
mvi a,1! jmp sta$ret
;
func1: equ func$ret
;
func3: equ func$ret
;
func6: equ func$ret
;
func10: equ func$ret
func11: equ func$ret
;
; data areas
;
compcol:db 0 ;true if computing column position
; end of BDOS Console module
;**********************************************************************
;*****************************************************************
;
; Error Messages
md equ 24h
err$msg: db cr,lf,'BDOS ERR: ',md
err$select: db 'Select',md
err$phys: db 'Perm.',md
;*****************************************************************
;*****************************************************************
;
; common values shared between bdosi and bdos
aret: ds 2 ; address value to return
lret equ aret ; low(aret)
;*****************************************************************
;*****************************************************************
;** **
;** b a s i c d i s k o p e r a t i n g s y s t e m **
;** **
;*****************************************************************
;*****************************************************************
; literal constants
true equ 0ffh ; constant true
false equ 000h ; constant false
enddir equ 0ffffh ; end of directory
byte equ 1 ; number of bytes for "byte" type
word equ 2 ; number of bytes for "word" type
; fixed addresses in low memory
tbuff equ 0080h ; default buffer location
; error message handlers
sel$error:
; report select error
lxi b,err$msg
call print
lxi b,err$select
jmp goerr1
goerr:
lxi b,err$msg
call print
lxi b,err$phys
goerr1:
call print
di ! hlt
bde$e$bde$m$hl:
mov a,e! sub l! mov e,a
mov a,d! sbb h! mov d,a
rnc! dcr b! ret
bde$e$bde$p$hl:
mov a,e! add l! mov e,a
mov a,d! adc h! mov d,a
rnc! inr b! ret
shl3bv:
inr c
shl3bv1:
dcr c! rz
dad h! adc a! jmp shl3bv1
compare:
ldax d! cmp m! rnz
inx h! inx d! dcr c! rz
jmp compare
;
; local subroutines for bios interface
;
move:
; Move data length of length c from source de to
; destination given by hl
inr c ; in case it is zero
move0:
dcr c! rz ; more to move
ldax d! mov m,a ; one byte moved
inx d! inx h ; to next byte
jmp move0
selectdisk:
; Select the disk drive given by register D, and fill
; the base addresses curtrka - alloca, then fill
; the values of the disk parameter block
mov c,d ; current disk# to c
; lsb of e = 0 if not yet logged - in
call seldskf ; hl filled by call
; hl = 0000 if error, otherwise disk headers
mov a,h! ora l! rz ; Return with C flag reset if select error
; Disk header block address in hl
mov e,m! inx h! mov d,m! inx h ; de=.tran
inx h ! inx h
shld curtrka! inx h! inx h ; hl=.currec
shld curreca! inx h! inx h ; hl=.buffa
inx h! inx h
inx h! inx h
; de still contains .tran
xchg! shld tranv ; .tran vector
lxi h,dpbaddr ; de= source for move, hl=dest
mvi c,addlist! call move ; addlist filled
; Now fill the disk parameter block
lhld dpbaddr! xchg ; de is source
lxi h,sectpt ; hl is destination
mvi c,dpblist! call move ; data filled
; Now set single/double map mode
lhld maxall ; largest allocation number
mov a,h ; 00 indicates < 255
lxi h,single! mvi m,true ; Assume a=00
ora a! jz retselect
; high order of maxall not zero, use double dm
mvi m,false
retselect:
; C flag set indicates successful select
stc
ret
home:
; Move to home position, then offset to start of dir
call homef
xra a ; constant zero to accumulator
lhld curtrka! mov m,a! inx h! mov m,a ; curtrk=0000
lhld curreca! mov m,a! inx h! mov m,a ; currec=0000
inx h! mov m,a ; currec high byte=00
ret
pass$arecord:
lxi h,arecord
mov e,m! inx h! mov d,m! inx h! mov b,m
ret
rdbuff:
; Read buffer and check condition
call pass$arecord
call readf ; current drive, track, sector, dma
diocomp: ; Check for disk errors
ora a! rz
mov c,a
cpi 3! jc goerr
mvi c,1! jmp goerr
seekdir:
; Seek the record containing the current dir entry
lhld dcnt ; directory counter to hl
mvi c,dskshf! call hlrotr ; value to hl
mvi b,0! xchg
lxi h,arecord
mov m,e! inx h! mov m,d! inx h! mov m,b
ret
seek:
; Seek the track given by arecord (actual record)
lhld curtrka! mov c,m! inx h! mov b,m ; bc = curtrk
push b ; s0 = curtrk
lhld curreca! mov e,m! inx h! mov d,m
inx h! mov b,m ; bde = currec
lhld arecord! lda arecord+2! mov c,a ; chl = arecord
seek0:
mov a,l! sub e! mov a,h! sbb d! mov a,c! sbb b
push h ; Save low(arecord)
jnc seek1 ; if arecord >= currec then go to seek1
lhld sectpt! call bde$e$bde$m$hl ; currec = currec - sectpt
pop h! xthl! dcx h! xthl ; curtrk = curtrk - 1
jmp seek0
seek1:
lhld sectpt! call bde$e$bde$p$hl ; currec = currec + sectpt
pop h ; Restore low(arecord)
mov a,l! sub e! mov a,h! sbb d! mov a,c! sbb b
jc seek2 ; if arecord < currec then go to seek2
xthl! inx h! xthl ; curtrk = curtrk + 1
push h ; save low (arecord)
jmp seek1
seek2:
xthl! push h ; hl,s0 = curtrk, s1 = low(arecord)
lhld sectpt! call bde$e$bde$m$hl ; currec = currec - sectpt
pop h! push d! push b! push h ; hl,s0 = curtrk,
; s1 = high(arecord,currec), s2 = low(currec),
; s3 = low(arecord)
xchg! lhld offset! dad d
mov b,h! mov c,l! shld track
call settrkf ; call bios settrk routine
; Store curtrk
pop d! lhld curtrka! mov m,e! inx h! mov m,d
; Store currec
pop b! pop d!
lhld curreca! mov m,e! inx h! mov m,d
inx h! mov m,b ; currec = bde
pop b ; bc = low(arecord), de = low(currec)
mov a,c! sub e! mov l,a ; hl = bc - de
mov a,b! sbb d! mov h,a
call shr$physhf
mov b,h! mov c,l
lhld tranv! xchg ; bc=sector#, de=.tran
call sectran ; hl = tran(sector)
mov c,l! mov b,h ; bc = tran(sector)
shld sector
call setsecf ; sector selected
lhld curdma! mov c,l! mov b,h! jmp setdmaf
shr$physhf:
lda physhf! mov c,a! jmp hlrotr
; file control block (fcb) constants
empty equ 0e5h ; empty directory entry
recsiz equ 128 ; record size
fcblen equ 32 ; file control block size
dirrec equ recsiz/fcblen ; directory fcbs / record
dskshf equ 2 ; log2(dirrec)
dskmsk equ dirrec-1
fcbshf equ 5 ; log2(fcblen)
extnum equ 12 ; extent number field
maxext equ 31 ; largest extent number
ubytes equ 13 ; unfilled bytes field
namlen equ 15 ; name length
reccnt equ 15 ; record count field
dskmap equ 16 ; disk map field
nxtrec equ fcblen
; utility functions for file access
dm$position:
; Compute disk map position for vrecord to hl
lxi h,blkshf! mov c,m ; shift count to c
lda vrecord ; current virtual record to a
dmpos0:
ora a! rar! dcr c! jnz dmpos0
; a = shr(vrecord,blkshf) = vrecord/2**(sect/block)
mov b,a ; Save it for later addition
mvi a,8! sub m ; 8-blkshf to accumulator
mov c,a ; extent shift count in register c
lda extval ; extent value ani extmsk
dmpos1:
; blkshf = 3,4,5,6,7, c=5,4,3,2,1
; shift is 4,3,2,1,0
dcr c! jz dmpos2
ora a! ral! jmp dmpos1
dmpos2:
; Arrive here with a = shl(ext and extmsk,7-blkshf)
add b ; Add the previous shr(vrecord,blkshf) value
; a is one of the following values, depending upon alloc
; bks blkshf
; 1k 3 v/8 + extval * 16
; 2k 4 v/16+ extval * 8
; 4k 5 v/32+ extval * 4
; 8k 6 v/64+ extval * 2
; 16k 7 v/128+extval * 1
ret ; with dm$position in a
getdma:
lhld info! lxi d,dskmap! dad d! ret
getdm:
; Return disk map value from position given by bc
call getdma
dad b ; Index by a single byte value
lda single ; single byte/map entry?
ora a! jz getdmd ; Get disk map single byte
mov l,m! mov h,b! ret ; with hl=00bb
getdmd:
dad b ; hl=.fcb(dm+i*2)
; double precision value returned
mov a,m! inx h! mov h,m! mov l,a! ret
index:
; Compute disk block number from current fcb
call dm$position ; 0...15 in register a
sta dminx
mov c,a! mvi b,0! call getdm ; value to hl
shld arecord! mov a,l! ora h! ret
atran:
; Compute actual record address, assuming index called
; arecord = shl(arecord,blkshf)
lda blkshf! mov c,a
lhld arecord! xra a! call shl3bv
shld arecord! sta arecord+2
shld arecord1 ; Save low(arecord)
; arecord = arecord or (vrecord and blkmsk)
lda blkmsk! mov c,a! lda vrecord! ana c
mov b,a ; Save vrecord & blkmsk in reg b & blk$off
sta blk$off
lxi h,arecord! ora m! mov m,a! ret
getexta:
; Get current extent field address to hl
lhld info! lxi d,extnum! dad d ; hl=.fcb(extnum)
ret
getrcnta:
; Get reccnt address to hl
lhld info! lxi d,reccnt! dad d! ret
getfcba:
; Compute reccnt and nxtrec addresses for get/setfcb
call getrcnta! xchg ; de=.fcb(reccnt)
lxi h,(nxtrec-reccnt)! dad d ; hl=.fcb(nxtrec)
ret
getfcb:
; Set variables from currently addressed fcb
call getfcba ; addresses in de, hl
mov a,m! sta vrecord ; vrecord=fcb(nxtrec)
xchg! mov a,m! sta rcount ; rcount=fcb(reccnt)
call getexta ; hl=.fcb(extnum)
lda extmsk ; extent mask to a
ana m ; fcb(extnum) and extmsk
sta extval
ret
setfcb:
; Place values back into current fcb
call getfcba ; addresses to de, hl
mvi c,1
lda vrecord! add c! mov m,a ; fcb(nxtrec)=vrecord+seqio
xchg! lda rcount! mov m,a ; fcb(reccnt)=rcount
ret
hlrotr:
; hl rotate right by amount c
inr c ; in case zero
hlrotr0: dcr c! rz ; return when zero
mov a,h! ora a! rar! mov h,a ; high byte
mov a,l! rar! mov l,a ; low byte
jmp hlrotr0
hlrotl:
; Rotate the mask in hl by amount in c
inr c ; may be zero
hlrotl0: dcr c! rz ; return if zero
dad h! jmp hlrotl0
set$cdisk:
; Set a "1" value in curdsk position of bc
lda seldsk
push b ; Save input parameter
mov c,a ; Ready parameter for shift
lxi h,1 ; number to shift
call hlrotl ; hl = mask to integrate
pop b ; original mask
mov a,c! ora l! mov l,a
mov a,b! ora h! mov h,a ; hl = mask or rol(1,curdsk)
ret
test$vector:
lda seldsk
mov c,a! call hlrotr
mov a,l! ani 1b! ret ; non zero if curdsk bit on
getdptra:
; Compute the address of a directory element at
; positon dptr in the buffer
lhld buffa! lda dptr
; hl = hl + a
add l! mov l,a! rnc
; overflow to h
inr h! ret
clr$ext:
; fcb ext = fcb ext & 1fh
call getexta! mov a,m! ani 0001$1111b! mov m,a!
ret
subdh:
; Compute hl = de - hl
mov a,e! sub l! mov l,a! mov a,d! sbb h! mov h,a
ret
get$buffa:
push d! lxi d,10! dad d
mov e,m! inx h! mov d,m
xchg! pop d! ret
rddir:
; Read a directory entry into the directory buffer
call seek$dir
lda phymsk! ora a! jz rddir1
mvi a,3
call deblock$dir! jmp setdata
rddir1:
call setdir ; directory dma
shld buffa! call seek
call rdbuff ; directory record loaded
setdata:
; Set data dma address
lhld dmaad! jmp setdma ; to complete the call
setdir:
; Set directory dma address
lhld dirbcba
call get$buffa
setdma:
; hl=.dma address to set (i.e., buffa or dmaad)
shld curdma! ret
end$of$dir:
; Return zero flag if at end of directory, non zero
; if not at end (end of dir if dcnt = 0ffffh)
lxi h,dcnt
mov a,m ; may be 0ffh
inx h! cmp m ; low(dcnt) = high(dcnt)?
rnz ; non zero returned if different
; high and low the same, = 0ffh?
inr a ; 0ffh becomes 00 if so
ret
set$end$dir:
; Set dcnt to the end of the directory
lxi h,enddir! shld dcnt! ret
read$dir:
; Read next directory entry, with c=true if initializing
lhld dirmax! xchg ; in preparation for subtract
lhld dcnt! inx h! shld dcnt ; dcnt=dcnt+1
; while(dirmax >= dcnt)
call subdh ; de-hl
jc set$end$dir
; not at end of directory, seek next element
; initialization flag is in c
lda dcnt! ani dskmsk ; low(dcnt) and dskmsk
mvi b,fcbshf ; to multiply by fcb size
read$dir1:
add a! dcr b! jnz read$dir1
; a = (low(dcnt) and dskmsk) shl fcbshf
sta dptr ; ready for next dir operation
ora a! rnz ; Return if not a new record
push b ; Save initialization flag c
call rd$dir ; Read the directory record
pop b ; Recall initialization flag
ret
compext:
; Compare extent# in a with that in c, return nonzero
; if they do not match
push b ; Save c's original value
push psw! lda extmsk! cma! mov b,a
; b has negated form of extent mask
mov a,c! ana b! mov c,a ; low bits removed from c
pop psw! ana b ; low bits removed from a
sub c! ani maxext ; Set flags
pop b ; Restore original values
ret
get$dir$ext:
; Compute directory extent from fcb
; Scan fcb disk map backwards
call getfcba ; hl = .fcb(vrecord)
mvi c,16! mov b,c! inr c! push b
; b=dskmap pos (rel to 0)
get$de0:
pop b
dcr c
xra a ; Compare to zero
get$de1:
dcx h! dcr b ; Decr dskmap position
cmp m! jnz get$de2 ; fcb(dskmap(b)) ~= 0
dcr c! jnz get$de1
; c = 0 -> all blocks = 0 in fcb disk map
get$de2:
mov a,c! sta dminx
lda single! ora a! mov a,b
jnz get$de3
rar ; not single, divide blk idx by 2
get$de3:
push b! push h ; Save dskmap position & count
mov l,a! mvi h,0 ; hl = non-zero blk idx
; Compute ext offset from last non-zero
; block index by shifting blk idx right
; 7 - blkshf
lda blkshf! mov d,a! mvi a,7! sub d
mov c,a! call hlrotr! mov b,l
; b = ext offset
lda extmsk! cmp b! pop h! jc get$de0
; Verify computed extent offset <= extmsk
call getexta! mov c,m
cma! ani maxext! ana c! ora b
; dir ext = (fcb ext & (~ extmsk) & maxext) | ext offset
pop b ; Restore stack
ret ; a = directory extent
search:
; Search for directory element of length c at info
lhld info! shld searcha ; searcha = info
mov a,c! sta searchl ; searchl = c
call set$end$dir ; dcnt = enddir
call home ; to start at the beginning
searchn:
; Search for the next directory element, assuming
; a previous call on search which sets searcha and
; searchl
mvi c,false! call read$dir ; Read next dir element
call end$of$dir! jz lret$eq$ff
; not end of directory, scan for match
lhld searcha! xchg ; de=beginning of user fcb
call getdptra ; hl = buffa+dptr
lda searchl! mov c,a ; length of search to c
mvi b,0 ; b counts up, c counts down
mov a,m! cpi empty! jz searchn
searchloop:
mov a,c! ora a! jz endsearch
; Scan next character if not ubytes
mov a,b! cpi ubytes! jz searchok
; not the ubytes field, extent field?
cpi extnum ; may be extent field
jz searchext ; Skip to search extent
ldax d
sub m! ani 7fh ; Mask-out flags/extent modulus
jnz searchn ; Skip if not matched
jmp searchok ; matched character
searchext:
ldax d
; Attempt an extent # match
push b ; Save counters
mov c,m ; directory character to c
call compext ; Compare user/dir char
pop b ; Recall counters
ora a ; Set flag
jnz searchn ; Skip if no match
searchok:
; current character matches
inx d! inx h! inr b! dcr c
jmp searchloop
endsearch:
; entire name matches, return dir position
xra a
sta lret ; lret = 0
; successful search -
; return with zero flag reset
mov b,a! inr b
ret
lret$eq$ff:
; unsuccessful search -
; return with zero flag set
; lret,low(aret) = 0ffh
mvi a,255 ! mov b,a ! inr b ! jmp sta$ret
open:
; Search for the directory entry, copy to fcb
mvi c,namlen! call search
rz ; Return with lret=255 if end
; not end of directory, copy fcb information
open$copy:
call getexta ! mov a,m ! push a ; save extent to check for extent
; folding - move moves entire dir FCB
call getdptra! xchg ; hl = .buff(dptr)
lhld info ; hl=.fcb(0)
mvi c,nxtrec ; length of move operation
call move ; from .buff(dptr) to .fcb(0)
; Note that entire fcb is copied, including indicators
call get$dir$ext! mov c,a
pop a ! mov m,a ; restore extent
; hl = .user extent#, c = dir extent#
; above move set fcb(reccnt) to dir(reccnt)
; if fcb ext < dir ext then fcb(reccnt) = fcb(reccnt) | 128
; if fcb ext = dir ext then fcb(reccnt) = fcb(reccnt)
; if fcb ext > dir ext then fcb(reccnt) = 0
set$rc: ; hl=.fcb(ext), c=dirext
mvi b,0
xchg! lxi h,(reccnt-extnum)! dad d
ldax d! sub c! jz set$rc2
mov a,b! jnc set$rc1
mvi a,128! mov b,m
set$rc1:
mov m,a! mov a,b! sta actual$rc! ret
set$rc2:
sta actual$rc
mov a,m! ora a! rnz ; ret if rc ~= 0
lda dminx! ora a! rz ; ret if no blks in fcb
lda fx! cpi 15! rz ; ret if fx = 15
mvi m,128 ; rc = 128
ret
restore$rc:
; hl = .fcb(extnum)
; if actual$rc ~= 0 then rcount = actual$rc
push h
lda actual$rc! ora a! jz restore$rc1
lxi d,(reccnt-extnum)! dad d
mov m,a! xra a! sta actual$rc
restore$rc1:
pop h! ret
open$reel:
; Close the current extent, and open the next one
; if possible.
call getexta
mov a,m! mov c,a
inr c! call compext
jz open$reel3
mvi a,maxext! ana c! mov m,a ; Incr extent field
mvi c,namlen! call search ; Next extent found?
; not end of file, open
call open$copy
open$reel2:
call getfcb ; Set parameters
xra a! sta vrecord! jmp sta$ret ; lret = 0
open$reel3:
inr m ; fcb(ex) = fcb(ex) + 1
call get$dir$ext! mov c,a
; Is new extent beyond dir$ext?
cmp m! jnc open$reel4 ; no
dcr m ; fcb(ex) = fcb(ex) - 1
jmp set$lret1
open$reel4:
call restore$rc
call set$rc! jmp open$reel2
seqdiskread:
; Sequential disk read operation
; Read the next record from the current fcb
call getfcb ; sets parameters for the read
lda vrecord! lxi h,rcount! cmp m ; vrecord-rcount
; Skip if rcount > vrecord
jc recordok
; not enough records in the extent
; record count must be 128 to continue
cpi 128 ; vrecord = 128?
jnz setlret1 ; Skip if vrecord<>128
call open$reel ; Go to next extent if so
; Check for open ok
lda lret! ora a! jnz setlret1 ; Stop at eof
recordok:
; Arrive with fcb addressing a record to read
call index ; Z flag set if arecord = 0
jz setlret1 ; Reading unwritten data
; Record has been allocated
call atran ; arecord now a disk address
lda phymsk! ora a ; if not 128 byte sectors
jnz read$deblock ; go to deblock
call setdata ; Set curdma = dmaad
call seek ; Set up for read
call rdbuff ; Read into (curdma)
jmp setfcb ; Update FCB
curselect:
lda seldsk! inr a! jz sel$error
dcr a! lxi h,curdsk! cmp m! rz
; Skip if seldsk = curdsk, fall into select
select:
; Select disk info for subsequent input or output ops
mov m,a ; curdsk = seldsk
mov d,a ; Save seldsk in register D for selectdisk call
lhld dlog! call test$vector ; test$vector does not modify DE
mov e,a! push d ; Send to seldsk, save for test below
call selectdisk! pop h ; Recall dlog vector
jnc sel$error ; returns with C flag set if select ok
; Is the disk logged in?
dcr l ; reg l = 1 if so
rz ; yes - drive previously logged in
lhld dlog! mov c,l! mov b,h ; call ready
call set$cdisk! shld dlog ; dlog=set$cdisk(dlog)
ret
set$seldsk:
lda linfo! sta seldsk! ret
reselectx:
xra a! sta high$ext! jmp reselect1
reselect:
; Check current fcb to see if reselection necessary
mvi a,80h! mov b,a! dcr a! mov c,a ; b = 80h, c = 7fh
lhld info! lxi d,7! xchg! dad d
mov a,m! ana b
; fcb(7) = fcb(7) & 7fh
mov a,m! ana c! mov m,a
; high$ext = 80h & fcb(8)
inx h! mov a,m! ana b! sta high$ext
; fcb(8) = fcb(8) & 7fh
mov a,m! ana c! mov m,a
; fcb(ext) = fcb(ext) & 1fh
call clr$ext
; if fcb(rc) & 80h
; then fcb(rc) = 80h, actual$rc = fcb(rc) & 7fh
; else actual$rc = 0
call getrcnta! mov a,m! ana b! jz reselect1
mov a,m! ana c! mov m,b
reselect1:
sta actual$rc
lxi h,0
shld fcbdsk ; fcbdsk = 0
mvi a,true! sta resel ; Mark possible reselect
lhld info! mov a,m ; drive select code
ani 1$1111b ; non zero is auto drive select
dcr a ; Drive code normalized to 0..30, or 255
sta linfo ; Save drive code
cpi 0ffh! jz noselect
; auto select function, seldsk saved above
mov a,m! sta fcbdsk ; Save drive code
call set$seldsk
noselect:
call curselect
mvi a,0 ! lhld info ! mov m,a
ret
;
; individual function handlers
;
func12 equ func$ret
func13:
; Reset disk system - initialize to disk 0
lxi h,0! shld dlog
xra a! sta seldsk
dcr a! sta curdsk
lxi h,tbuff! shld dmaad ; dmaad = tbuff
jmp setdata ; to data dma address
func14:
; Select disk info
call set$seldsk ; seldsk = linfo
jmp curselect
func15:
; Open file
call reselectx
call open! call openx ; returns if unsuccessful, a = 0
ret
openx:
call end$of$dir! rz
call getfcba! mov a,m! inr a! jnz openxa
dcx d! dcx d! ldax d! mov m,a
openxa:
; open successful
pop h ; Discard return address
mvi c,0100$0000b
ret
func16 equ func$ret
func17 equ func$ret
func18 equ func$ret
func19 equ func$ret
func20:
; Read a file
call reselect
jmp seqdiskread
func21 equ func$ret
func22 equ func$ret
func23 equ func$ret
func24 equ func$ret
func25: lda seldsk ! jmp sta$ret
func26: xchg ! shld dmaad
jmp setdata
func27 equ func$ret
func28: equ func$ret
func29 equ func$ret
func30 equ func$ret
func31 equ func$ret
func32 equ func$ret
func33 equ func$ret
func34 equ func$ret
func35 equ func$ret
func36 equ func$ret
func37 equ func$ret
func38 equ func$ret
func39 equ func$ret
func40 equ func$ret
func42 equ func$ret
func43 equ func$ret
func44 equ func$ret
func45 equ func$ret
func46 equ func$ret
func47 equ func$ret
func48 equ func$ret
func49 equ func$ret
func50 equ func$ret
func100 equ func$ret
func101 equ func$ret
func102 equ func$ret
func103 equ func$ret
func104 equ func$ret
func105 equ func$ret
func106 equ func$ret
func107 equ func$ret
func108 equ func$ret
func109 equ func$ret
goback:
; Arrive here at end of processing to return to user
lda fx! cpi 15! jc retmon
lda olddsk! sta seldsk ; Restore seldsk
lda resel! ora a! jz retmon
lhld info! mvi m,0 ; fcb(0)=0
lda fcbdsk! ora a! jz goback1
; Restore fcb(0)
mov m,a ; fcb(0)=fcbdsk
goback1:
; fcb(8) = fcb(8) | high$ext
inx h! lda high$ext! ora m! mov m,a
; fcb(rc) = fcb(rc) | actual$rc
call getrcnta! lda actual$rc! ora m! mov m,a
; return from the disk monitor
retmon:
lhld entsp! sphl
lhld aret! mov a,l! mov b,h
ret
;
; data areas
;
dlog: dw 0 ; logged-in disks
curdma ds word ; current dma address
buffa: ds word ; pointer to directory dma address
;
; curtrka - alloca are set upon disk select
; (data must be adjacent, do not insert variables)
; (address of translate vector, not used)
cdrmaxa:ds word ; pointer to cur dir max value (2 bytes)
curtrka:ds word ; current track address (2)
curreca:ds word ; current record address (3)
drvlbla:ds word ; current drive label byte address (1)
lsn$add:ds word ; login sequence # address (1)
; +1 -> bios media change flag (1)
dpbaddr:ds word ; current disk parameter block address
checka: ds word ; current checksum vector address
alloca: ds word ; current allocation vector address
dirbcba:ds word ; dir bcb list head
dtabcba:ds word ; data bcb list head
hash$tbla:
ds word
ds byte
addlist equ $-dpbaddr ; address list size
;
; buffer control block format
;
; bcb format : drv(1) || rec(3) || pend(1) || sequence(1) ||
; 0 1 4 5
;
; track(2) || sector(2) || buffer$add(2) ||
; 6 8 10
;
; link(2)
; 12
;
; sectpt - offset obtained from disk parm block at dpbaddr
; (data must be adjacent, do not insert variables)
sectpt: ds word ; sectors per track
blkshf: ds byte ; block shift factor
blkmsk: ds byte ; block mask
extmsk: ds byte ; extent mask
maxall: ds word ; maximum allocation number
dirmax: ds word ; largest directory number
dirblk: ds word ; reserved allocation bits for directory
chksiz: ds word ; size of checksum vector
offset: ds word ; offset tracks at beginning
physhf: ds byte ; physical record shift
phymsk: ds byte ; physical record mask
dpblist equ $-sectpt ; size of area
;
; local variables
;
blk$off: ds byte ; record offset within block
dir$cnt: ds byte ; direct i/o count
tranv: ds word ; address of translate vector
linfo: ds byte ; low(info)
dminx: ds byte ; local for diskwrite
actual$rc:
ds byte ; directory ext record count
single: ds byte ; set true if single byte allocation map
olddsk: ds byte ; disk on entry to bdos
rcount: ds byte ; record count in current fcb
extval: ds byte ; extent number and extmsk
vrecord:ds byte ; current virtual record
curdsk:
adrive: db 0ffh ; current disk
arecord:ds word ; current actual record
ds byte
arecord1: ds word ; current actual block# * blkmsk
;******** following variable order critical *****************
high$ext: ds byte ; fcb high ext bits
;xfcb$read$only: ds byte
; local variables for directory access
dptr: ds byte ; directory pointer 0,1,2,3
;
; local variables initialized by bdos at entry
;
fcbdsk: ds byte ; disk named in fcb
phy$off: ds byte
curbcba: ds word
track: ds word
sector: ds word
read$deblock:
mvi a,1! call deblock$dta
jmp setfcb
column db 0
outdelim: db '$'
dmaad: dw 0080h
seldsk: db 0
info: dw 0
resel: db 0
fx: db 0
dcnt: dw 0
searcha: dw 0
searchl: db 0
; **************************
; Blocking/Deblocking Module
; **************************
deblock$dir:
lhld dirbcba
jmp deblock
deblock$dta:
lhld dtabcba
deblock:
; BDOS Blocking/Deblocking routine
; a = 1 -> read command
; a = 2 -> write command
; a = 3 -> locate command
; a = 4 -> flush command
; a = 5 -> directory update
push a ; Save z flag and deblock fx
; phy$off = low(arecord) & phymsk
; low(arecord) = low(arecord) & ~phymsk
call deblock8
lda arecord! mov e,a! ana b! sta phy$off
mov a,e! ana c! sta arecord
shld curbcba! call getbuffa! shld curdma
call deblock9
; Is command flush?
pop a! push a! cpi 4
jnc deblock1 ; yes
; Is referenced physical record
;already in buffer?
call compare! jz deblock45 ; yes
xra a
deblock1:
call deblock10
; Read physical record buffer
mvi a,2! call deblock$io
call deblock9 ; phypfx = adrive || arecord
call move! mvi m,0 ; zero pending flag
deblock45:
; recadd = phybuffa + phy$off*80h
lda phy$off! inr a! lxi d,80h! lxi h,0ff80h
deblock5:
dad d! dcr a! jnz deblock5
xchg! lhld curdma! dad d
; If deblock command = locate
; then buffa = recadd; return
pop a! cpi 3! jnz deblock6
shld buffa! ret
deblock6:
xchg! lhld dmaad! lxi b,80h
; If deblock command = read
jmp move$tpa ; then move to dma
deblock8:
lda phymsk! mov b,a! cma! mov c,a! ret
deblock9:
lhld curbcba! lxi d,adrive! mvi c,4! ret
deblock10:
lxi d,4
deblock11:
lhld curbcba! dad d! ret
deblock$io:
; a = 0 -> seek only
; a = 1 -> write
; a = 2 -> read
push a! call seek
pop a! dcr a
cp rdbuff
; Move track & sector to bcb
call deblock10! inx h! inx h
lxi d,track! mvi c,4! jmp move
org base+((($-base)+255) and 0ff00h)-1
db 0
; Bios equates
bios$pg equ $
bootf equ bios$pg+00 ; 00. cold boot
conoutf equ bios$pg+12 ; 04. console output function
homef equ bios$pg+24 ; 08. disk home function
seldskf equ bios$pg+27 ; 09. select disk function
settrkf equ bios$pg+30 ; 10. set track function
setsecf equ bios$pg+33 ; 11. set sector function
setdmaf equ bios$pg+36 ; 12. set dma function
sectran equ bios$pg+48 ; 16. sector translate
movef equ bios$pg+75 ; 25. memory move function
readf equ bios$pg+39 ; 13. read disk function
move$out equ movef
move$tpa equ movef
end