mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 14:11:48 -06:00
* 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 commitad80432252. * Revert "Update romldr.asm" This reverts commit4a9825cd57. * Revert "CP/M 3 Date Hack" This reverts commit153b494e61. * Revert "New ROMLDR and INTRTC driver" This reverts commitd9bed4563e. * 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>
1572 lines
37 KiB
NASM
1572 lines
37 KiB
NASM
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
|
||
|