Title Floppy Disk Backup Program for MD-HD (22_Oct_84) ; ; Copyright 1984 ; Morrow Designs, Inc. ; San Leandro, Ca. ; John Zalabak ; .z80 Aseg org 0100h ;---------------------------------------------------------------------- ; Index (22_Oct_84) ;------------------ ; ; Backup_Main Main Proceedure of Backup ; Save_State Get the Entry Conditions ; Find_Drives Check the Drive Configuration ; Get_Mtab_Pntr Get a Pointer to an Mtab ; Check_Revision Check Versions/Revisions ; Restore_State Restore the Entry State ; ; Make_a_Copy Make a Copy of a Floppy Disk ; Save_Disk Save all Tracks on a Floppy Disk ; Read_Flp_Track Read a Track from the Floppy Disk ; Write_Dsk_Track Write a Track to the Save File ; ; Restore_a_Copy Restore a Disk from a File ; Res ter Erase a character from the console screen ; Pause_for_Rtn Wait the Return Key ; Get_Character Get a Character from the Console ; Put_Character Put a Character to the Console ; ; Divide 16 bit Divide ; Multiply 16 bit Multiply ; Extended_Bios Call the Extended Bios Entry ; Get_Buffer Read a Buffer (Extended Bios) ; Put_Buffer Write a Buffer (Extended Bios) ; Print_Message Print a Message on the Console ; ; Data Areas page 60 ;---------------------------------------------------------------------- ; General Equates (4_Oct_84) ;--------------------------- ; ;Revision Numbers Frev equ 20h ;Format Program Revision Level Ccl equ 1 ;Bios Compatibility Level Rrl equ 19h ;Rom Revision Level ;Bios/Bdos Equates Bios_Entry equ 0 ;Bios Entry Point Bdos_Entry equ 5 ;Bdos: Entry Vector Location Bdos_PString equ 9 ; Print a Sting on the Console Bdos_ConBuf_In equ 10 ; Read Console input buffer Bdos_Ret_Ver equ 12 ; Return CP/M version Bdos_Select equ 14 ; Select Disk Bdos_Open_File equ 15 ; Open a File Bdos_Close_File equ 16 ; Close a File Bdos_Search equ 17 ; Search for File Bdos_Delete equ 19 ; Delete a File Bdos_Read_Seq equ 20 ; Read Sequential Bdos_Write_Seq equ 21 ; Write Sequential Bdos_Make_File equ 22 ; Make a File Bdos_Crnt_Disk equ 25 ; Return the Current Disk Number Bdos_Set_DMA equ 26 ; Set the DMA Address ;Extended Bios Function Calls EB_Get_Sys_Mem equ 0 ;Read from System Memory EB_Put_Sys_Mem equ 1 ;Write to System Memory EB_Get_RamDatY equ 2 ;Read RamDatY and Apif EB_Get_Mtabs equ 3 ;Read the System Mtabs EB_Get_Dpbs equ 5 ;Read the System Dpbs EB_Char_Tbl equ 6 ;Read the Character Table EB_Format equ 9 ;Format a Track EB_Execute equ 14 ;Execute a in the System Bank EB_Verify_D e f Character Table Rrl_Offset equ 0 ;Rom Revision Level from Start of ID Frame Vnum_Offset equ 04h ;To Numb Log Drives from Start of Char Table ConIn_Offset equ 9 ;Bios Console Input Offset ConOut_Offset equ 0Ch ; " Console Output Offset ConSt_Offset equ 33h ; " Console Status Offset SetTrk_Offset equ 1Eh ; " Jump Table Set Track Offset HstDsk_Offset equ 0 ;Drive Number from Start of Apif HstTrk_Offset equ 1 ;Track " " " " " HstSec_Offset equ 3 ;Sector " " " " " Ex_Offset equ 12 ;Fcb offset to Extent Cr_Offset equ 32 ; " " " Current Record OpFlag_Offset equ 2Eh ;Offset to OpFlag from start of RamDatY ;Length Definitions L_Sector_Length equ 80h ;Logical Sector Length Descriptor_Leng equ 9+15+1 ;Combined Length of Mtab/Dpb (Md3 format) Fcb_Length equ 36 ;Length of a Fcb Fcb1 equ 5Ch ;Location of First Default Fcb ;Termination Codes Again equ 'A' ;Repeat previous format again Restart equ 'R' ;Restart format program Exit equ Control_C ;Exit to Cp/m ;Message Codes Err_Cpm_Rev equ 10 ;Cpm Revision is NOT Cpm 3 Err_Ccp_Rev equ 11 ;Bios Compatability Rev too low Err_Rom_Rev equ 12 ;Rom Revision is too low No_Hard_Disk equ 13 ;Couldn't find a Hard Disk Mtab No_Floppy_Disk equ 14 ;Couldn't find a Floppy Disk Mtab General_Error equ 16 ;All Purpose Error Code Msg_Banner equ 20 ;Title Banner Msg_Reading equ 21 ;Reading from Floppy Msg_Writing equ 22 ;Writing to Floppy Msg_Pause equ 23 ;Pause for Input Prompt Msg_CrLf equ 60 ;New Line ;Non Printing Ascii Equates Control_C equ 03h ;Control C (Force CPM Warm Boot) Bell equ 07h ;Console Bell BackSpace equ 08h ;Back Space One Character Tab equ 09h ;Tab Lf equ 0Ah ;Line Feed Cr equ 0Dh ;Carriage Return ess Response_Max equ 10h ;Maximum Length of the Response Buffer @SerUR equ 6 ;Suppress Error Response Flag @SerD equ 7 ;Suppress Error Display Flag @DblMed equ 2 ;Single/Double Sided Media Flag $HdMsk equ 00011100b ;Head Mask (DskDef0) $HrdDsk equ 00000010b ;Mask Byte for Hard Disk (DskDef0) @HrdDsk equ 1 ;Bit test for " " " $SizMsk equ 00000011b ;Sector Size Mask (DskDef1) page ;====================================================================== ; Main Line of Format Routine (22_Oct_84) ;======================================== ; Backup_Main: ld sp,Local_Stack ;Set the Stack Pointer BuLp1: ld a,Msg_Banner ;Repeat call Print_Message ; Print the Opening Message call Save_State ; Save the Entry Conditions or a ; If (Can't find disk drives) jr nz,Quit ; Quit call Check_Revision ; Check Revisions and C-Level or a ; If (Wrong Revisions) jr nz,Quit ; Quit call Make_a_Copy ; Copy the Disk or a ; If (There was an Error) jr nz,Quit ; Quit call Restore_a_Copy ; Restore a Disk Copy or a ; If (There was an Error) jp z,Ok ; Quit Quit: cp Control_C ; If (Abort wasn't due to Control C) call nz,Print_Message Ok: call Restore_State ;Restore the Entry State jp Bios_Entry ;Exit page ;====================================================================== ; Get the Entry Conditions (22_Oct_84) ;===================================== ; Save_State: ld a,(Fcb1+1) ;If (the default Fcb is Active) cp ' ' jr z,SsSk1 ld hl,Fcb1 ; HL:= Source (User Fcb) ld de,Default_Fcb ; DE:= Destination (Save of Fcb) ld bc,12 ; BC:= Length (only the name field) ldir ; Save the Fcb ld a,0FFh ld (File_Active),a ; Set File to Active SsSk1: ld c,Bdos_Crnt_Disk ;Re Convert to Absolute Drive Number ld (Default_Fcb),a ; Install the Drive Number ld a,0 ret ; Return ;---------------------------------------------------------------------- ; Check the Drive Configuration (18_Oct_84) ;------------------------------------------ ; 1) This routine finds the First Hard Disk and the First Floppy Disk ; Drives in the System Mtabs. ; Find_Drives: ld a,EB_Char_Tbl ;Read the Character Table call Get_Buffer ;Read the Character Table ld hl,Buffer ;HL:= Base of Character Table ld de,Vnum_Offset ;DE:= Offset to Numb Log Drives add hl,de ld b,(hl) ;B:= Number of Drives push bc ld a,EB_Get_Mtabs call Get_Buffer ;Read the System Mtabs pop bc ld a,0 ;A:= Current Drive FdLp1: push af call Get_Mtab_Pntr ;Repeat HL:= Pointer to DskDef0 pop af bit @HrdDsk,(hl) ; If (Current Drive eq Hard Disk) jr nz,FdSk1 ; Break inc a ; Increment the Current Drive cp b jr nz,FdLp1 ;Until (All Drives have been Checked) ld a,No_Hard_Disk ;If (Hard Disk Not Found) ret ; Return Error FdSk1: ld (Fixed_Drive),a ;Install Hard Disk Drive Number ld a,0 ;A:= Current Drive FdLp2: push af call Get_Mtab_Pntr ;Repeat HL:= Pointer to DskDef0 pop af bit @HrdDsk,(hl) ; If (Current Drive eq Floppy) jr z,FdSk2 ; Break inc a ; Increment the Current Drive cp b jr nz,FdLp2 ;Until (All Drives have been Checked) ld a,No_Floppy_Disk ;If (Floppy Disk Not Found) ret ; Return Error FdSk2: ld (Floppy_Drive),a ;Save Floppy Disk Number ld a,0 ;A:= Ok Return Status ret ;Return page ;---------------------------------------------------------------------- ; Get a Pointer to an Mtab (18_Oct_84) ;------------------------------------- ; 1) This routine returns the HL register p t into the Buffer ; HL -> Returned pointing to the start of the desired mtab ; Get_Mtab_Pntr: sla a sla a sla a sla a ld e,a ld d,0 ;DE:= Floppy_Drive * 16 ld hl,Buffer ;HL:= Base of Mtabs add hl,de ;HL:= Pointer to Start of Current Mtab ret page ;====================================================================== ; Check Versions/Revisions (22_Oct_84) ;===================================== ; 1) This routine checks the CP/M version, the Bios Compatibility ; level and the Rom Revision Level. ; Check_Revision: ld c,Bdos_Ret_Ver ;C:= Return version Bdos call call Bdos_Entry ;Get the Cpm Revision ld a,0F0h and l cp 30h ;If (this is NOT Cp/m 3) ld a,Err_Cpm_Rev ; A:= Error Code ret nz ; Return ld a,EB_Char_Tbl ;A:= Get Char Table Function call Get_Buffer ;Read the Character Table ld a,(Buffer+Ccl_Offset) cp Ccl ;If (Compatibility Level NOT in Range) ld a,Err_Ccp_Rev ; A:= Error Code ret c ; Return ld a,EB_ID_Frame ;A:= Read Rom ID Frame call Extended_Bios ;Read the ID Frame ld a,(Buffer+Rrl_Offset) cp Rrl ;If (Rom Rev NOT in Range) ld a,Err_Rom_Rev ; A:= Error Code ret c ; Return ld a,0 ;A:= No Error ret ;Return page ;====================================================================== ; Restore the Entry State (18_Oct_84) ;==================================== ; Restore_State: ld c,Bdos_Delete ;C:= Delete a File ld de,Fcb1 ;DE:= Destination (Default Dma) call Bdos_Entry ;Delete the Save File ld c,Bdos_Select ;C:= Select Disk Function ld a,(Initial_Drive) ld e,a ;E:= Drive to Select call Bdos_Entry ;Reselect the Entry Drive ld a,0 ret ;Return page ;====================================================================== ; M se_for_Rtn ;Prompt User cp Control_C ;If (Response eq Control C) ret z ; Return ;Set Disk Characteristics (will be set by the foreign program) ld hl,80 ld (Logical_Tracks),hl ld hl,36 ld (Logical_Spt),hl ld hl,9 ld (Physical_Spt),hl ld hl,512 ld (P_Sector_Leng),hl ld de,Buffer ;DE:= Start of Local Buffer ld c,Bdos_Set_DMA ;C:= Set DMA Address Function call Bdos_Entry ;Set the Dma Address ld hl,Default_Fcb ;HL:= Save Fcb ld de,Fcb1 ;DE:= Working Fcb ld bc,Fcb_Length ;BC:= Length of Entire Fcb ldir ;Install the Fcb ld de,Fcb1 ;DE:= Start of Command_Fcb ld c,Bdos_Delete ;C:= Delete File Function call Bdos_Entry ;Delete the Temp File ld de,Fcb1 ;DE:= Start of Command_Fcb ld c,Bdos_Make_File ;C:= Open File Function call Bdos_Entry ;Open the command file cp 0FFh ;If (file can't be opened) ld a,General_Error ; General Error Code ret z ; Return call Save_Disk or a ;If (There was an Error) ret nz ; Return ld de,Fcb1 ;DE:= Pointer to FCB1 ld c,Bdos_Close_File ;C:= Close file function call Bdos_Entry ;Close the command file cp 0FFh ;If (There was an Error) ld a,General_Error ; A:= Error Code ret z ; Return ld a,0 ;A:= No Error ret ;Return page ;---------------------------------------------------------------------- ; Save all Tracks on a Floppy Disk (22_Oct_84) ;--------------------------------------------- ; Save_Disk: ld hl,(Logical_Tracks) dec hl ld (Current_Track),hl ;Initialize Current_Track to Last Track RdLp1: ld a,(Floppy_Drive) ;Loop ld (Apif+HstDsk_Offset),a ; Install The Drive Number call Read_Flp_Track ; Read a Track from the Floppy or a ; If (There was an Error) ret nz ; Return call Write_Dsk_Track ; Write Lp1 page ;---------------------------------------------------------------------- ; Read a Track from the Floppy Disk (22_Oct_84) ;---------------------------------------------- ; 1) This routine reads a track from the Floppy Disk. ; 2) Register Usage: ; A -> Returned 0 for NO errors ; ----> All other registers are destroyed ; Read_Flp_Track: ld hl,(Current_Track) ld (Apif+HstTrk_Offset),hl ;Initialize the Track Number ld a,Cr call Put_Character call Print_Number ld hl,(Physical_Spt) ld (Sector_Count),hl ;Initialize the Sector Count ld hl,1 ld (Current_Sector),hl ;Initialize the Current Sector RdfLp1: ld hl,(Current_Sector) ;Repeat ld (Apif+HstSec_Offset),hl ; Install the Sector Number ld ix,Apif ; IX:= Start of Local Apif ld a,EB_Read_Host ; A:= Read Host Function call Extended_Bios ; Read a Sector From Floppy Disk or a ; If (There was an Error) ld a,General_Error ; A:= Error Code ret nz ; Return ld de,(P_Sector_Leng) ; DE:= Length of One Sector ld hl,(Current_Sector) ; HL:= Current Sector dec hl ; (0 Based Sector Number) call Multiply ; HL:= Offset to Current Sector ld de,Buffer ; DE:= Start of the Buffer add hl,de ; HL:= Pointer to Sector Addr ex de,hl ; DE:= Destination (in Local Buffer) ld hl,Sys_Disk_Buffer ; HL:= Source (System Disk Buffer) ld bc,(P_Sector_Leng) ; BC:= Length (Length of 1 Sector) ld a,EB_Get_Sys_Mem ; A:= Read Disk Buffer Function call Extended_Bios ; Move the Sector Into Place call Next_Phy_Sector or a jr nz,RdfLp1 ;Until (All Sectors Have Been Read) ret ;Return page ;---------------------------------------------------------------------- ; Write a Track to the Save File (22_Oct_84) ;------------------------------------------- ; ld de,Fcb1 ; DE:= Start of Command_Fcb ld c,Bdos_Write_Seq ; C:= Write Sequential Function call Bdos_Entry ; Write the Next record pop de pop bc or a ; If (There was an Error) ld a,General_Error ; A:= Error Code ret nz ; Return ld hl,L_Sector_Length add hl,de ex de,hl ; DE:= Next Sector Address dec bc ; Decrement the Sector Length ld a,b or c jr nz,WfLp1 ;Until (All sectors have been written) ret ;Return page ;====================================================================== ; Restore a Disk from a File (22_Oct_84) ;======================================= ; Restore_a_Copy: ld a,Msg_Banner call Print_Message ;Print Title Banner ld a,Msg_Writing call Print_Message ;Print Writing to Floppy call Pause_for_Rtn ;Prompt User cp Control_C ;If (Response eq Control C) ret z ; Return ld de,Buffer ;DE:= Start of Local Buffer ld c,Bdos_Set_DMA ;C:= Set DMA Address Function call Bdos_Entry ;Set the Dma Address ld hl,Default_Fcb ;HL:= Save Fcb ld de,Fcb1 ;DE:= Working Fcb ld bc,Fcb_Length ;BC:= Length of Entire Fcb ldir ;Install the Fcb ld de,Fcb1 ;DE:= Start of Command_Fcb ld c,Bdos_Open_File ;C:= Open File Function call Bdos_Entry ;Open the command file cp 0FFh ;If (file can't be opened) ld a,General_Error ; General Error Code ret z ; Return call Restore_Disk or a ;If (There was an Error) ret nz ; Return ld de,Fcb1 ;DE:= Pointer to FCB1 ld c,Bdos_Close_File ;C:= Close file function call Bdos_Entry ;Close the command file cp 0FFh ;If (There was No Error) ld a,General_Error ; A:= Error Code ret z ; Return ld a,0 ;A:= No Error ret ;Return page ;----------------------------------------------------------------- nt_Track to Last Track WrLp1: ld a,(Floppy_Drive) ;Loop ld (Apif+HstDsk_Offset),a ; Install The Drive Number call Read_Dsk_Track ; Read a Track from the File or a ; If (There was an Error) ret nz ; Return call Write_Flp_Track ; Write a Track to the Floppy or a ; If (There was an Error) ret nz ; Return ld hl,(Current_Track) ; If (Current_Track eq 0) ld a,h or l ret z ; Return dec hl ld (Current_Track),hl ; Decrement the Track Count jr WrLp1 ret ;Return page ;---------------------------------------------------------------------- ; Read a Track from the Save File (22_Oct_84) ;-------------------------------------------- ; Read_Dsk_Track: ld bc,(Logical_Spt) ;BC:= Logical Sectors/Track ld de,Buffer ;DE:= Load Address RfLp1: push bc push de ;Repeat ld c,Bdos_Set_DMA ; C:= Set DMA Address Function call Bdos_Entry ; Set the Dma Address ld de,Fcb1 ; DE:= Start of Command_Fcb ld c,Bdos_Read_Seq ; C:= Read Sequential Function call Bdos_Entry ; Read the Next record pop de pop bc or a ; If (There was an Error) ld a,General_Error ; A:= Error Code ret nz ; Return RfSk1: ld hl,L_Sector_Length add hl,de ex de,hl ; DE:= Next Sector Address dec bc ; Decrement the Sector Length ld a,b or c jr nz,RfLp1 ;Until (All sectors have been read) ret ;Return page ;---------------------------------------------------------------------- ; Write a Track to the Floppy Disk (22_Oct_84) ;--------------------------------------------- ; 1) This routine writes a Track to the Floppy Disk. ; 2) Register Usage: ; A -> Returned 0 for NO Errors. ; ----> All other registers are destroyed ; Write_Flp_Track: ld hl,(Current_Track) ld (Apif+HstTrk_Offset),hl ;Initi Dos_Mtab_Dpb ;DE:= Pointer to Mtab/Dpb ; ld a,EB_Format ;A:= Format a Track Function ; call Extended_Bios ;Format the Track ; ; ld a,d ;A:= Returned Status ; ld a,General_Error ; or a ;If (There was an Error) ; ret nz ; Return ;Write the Track ld hl,(Physical_Spt) ld (Sector_Count),hl ;Initialize the Sector Count ld hl,1 ld (Current_Sector),hl ;Initialize the Current Sector WrfLp1: ld hl,(Current_Sector) ;Repeat ld (Apif+HstSec_Offset),hl ; Install the Sector Number ld de,(P_Sector_Leng) ; DE:= Length of One Sector ld hl,(Current_Sector) ; HL:= Current Sector dec hl ; (0 Based Sector Number) call Multiply ; HL:= Offset to Current Sector ld de,Buffer ; DE:= Start of the Buffer add hl,de ; HL:= Source (in Local Buffer) ld de,Sys_Disk_Buffer ; DE:= Destination (Sys Buffer) ld bc,(P_Sector_Leng) ; BC:= Length (Length of 1 Sector) ld a,EB_Put_Sys_Mem ; A:= Write to System Memory call Extended_Bios ; Move Buffer into Disk Buffer ld ix,Apif ; IX:= Local APIF ld a,EB_Write_Host ; A:= Write Host Function call Extended_Bios ; Write a Sector to the Disk or a ; If (There was an Error) ld a,General_Error ; General Error Code ret nz ; Return call Next_Phy_Sector ; Get the Next Sector or a jr nz,WrfLp1 ;Until (All Sectors have been Written) ret ;Return page ;---------------------------------------------------------------------- ; Calculate the Next Physical Sector (17_Oct_84) ;----------------------------------------------- ; 1) This routine checks if all the sectors have been accessed and ; adjusts the next sector accordingly (based on a skew of 2). ; 2) Register Usage: ; A -> Returned 0 for last sector. ; HL -> Returned equal to the Current Sector Number ; ----> No oth inc hl ld (Current_Sector),hl ;Current_Sector:= Current_Sector * 2 push hl push de ld de,(Physical_Spt) ;DE:= Maximum Number of Sectors or a ;(Clear Carry but don't touch accm) sbc hl,de ;If (Sector Count le Maximum Sectors) pop de pop hl ret c ; Return ret z ld hl,2 ;Else ld (Current_Sector),hl ; Current_Sector:= 2 ret ; Return page ;---------------------------------------------------------------------- ; Erase a Character from the Console Screen (1_Oct_84) ;----------------------------------------------------- ; 1) This routine erases one character from the console screen. ; 2) None of the Registers are effected. ; Erase_Character: push af ld a,BackSpace call Put_Character ;Backup over the Character ld a,' ' call Put_Character ;Print a Space over the Character ld a,BackSpace call Put_Character ;Backup the cursor pop af ret ;Return ;---------------------------------------------------------------------- ; Wait for the Return Key to be Pressed (3_Oct_84) ;------------------------------------------------- ; 1) This routine prints a prompting message and then loops, waiting ; for either a carriage return or a Control C to by typed. ; 2) Register Usage: ; A -> Returned equal to ReStart or Control_C (Exit) ; ----> None of the other registers are effected ; Pause_for_Rtn: push bc push de push hl ld a,Msg_Pause call Print_Message ;Print the Prompt pop hl pop de pop bc PrLp1: call Get_Character ;Loop Wait for the Response cp Control_C ; If (Response eq Return to CP/M) ret z ; Return cp Cr ; If (Response eq Cr) ld a,ReStart ; A:= ReStart ret z ; Return call Erase_Character ; Else Erase the Character jr PrLp1 page ;--------------------- os jump table and then echoes the ; character by calling Put_Character. ; 2) Notice that Control Characters are echoed as spaces. ; 2) Register Usage: ; A -> On exit holds the character read ; ----> No other register effected ; Get_Character: push bc push de push hl ld de,(Bios_Entry+1) ld e,0 ;DE:= Base of Bios Jump Table ld hl,ConIn_Offset ;HL:= Offset to ConIn Jump in Bios Table add hl,de ;HL:= Pointer to ConIn Jump ld a,EB_Execute ;A:= Execute in the System Bank call Extended_Bios ;Get a Character push af cp 20h ;If (Character is Control) jr nc,GcSk1 ld a,' ' ; Echo a Space GcSk1: call Put_Character ;Echo the Character pop af pop hl pop de pop bc ret ;Return page ;---------------------------------------------------------------------- ; Put a Character to the Console (1_Oct_84) ;------------------------------------------ ; 1) This routine prints one character on the console screen by ; vectoring through the bios jump table. ; 2) Register Usage: ; A -> On entry and exit holds the character printed ; ----> No other register effected ; Put_Character: push bc push de push hl push af ld c,a ;C:= Character to Print ld de,(Bios_Entry+1) ld e,0 ;DE:= Base of Bios Jump Table ld hl,ConOut_Offset ;HL:= Offset to ConOut Jump in Bios Table add hl,de ;HL:= Pointer to ConOut Jump ld a,EB_Execute ;A:= Execute in the System Bank call Extended_Bios ;Print the Character pop af pop hl pop de pop bc ret ;Return page ;---------------------------------------------------------------------- ; Print a Number in the Current Base (1_Oct_84) ;---------------------------------------------- ; 1) This routine prints the 16 bit number (passed in the HL) in ascii ; is Zero) or h jr nz,Dsk1 ld a,' ' ; call Put_Character ; Print a Space ld a,'0' call Put_Character ; Print the zero ret ; Return Dsk1: ld bc,0FFFFh push bc ;Put end flag on stack DLp2: ld bc,(Output_Radix) ;Repeat divisor:= Current Radix call divide ; Divide push hl ; Save the remainder ld hl,9 or a sbc hl,de ex de,hl ; (Move quotient to dividend) jp c,DLp2 ;Until (quotient is less than 9) DLp3: ld a,l ;While (Result eq 0) or a jr nz,DLp4 ld a,' ' call Put_Character ; Print a Space pop hl ; Get the next number jr DLp3 DLp4: add a,'0' ;Repeat Convert number to ascii call Put_Character ; Print the number pop hl ; Get the next number ld a,l cp 0FFh jr nz,DLp4 ;Until (end of stack flag has been read) ret ;Return page ;---------------------------------------------------------------------- ; 16 bit Divide ;-------------- ; divide 16-bit number in [hl] by [bc] ; on exit, [de] is 16-bit quotient, [hl] is remainder ; Divide: add hl,hl ;hi *2 ex de,hl ;[de] becomes lo ld hl,0 ;init hi ld a,16 ;16 bits divid0: adc hl,hl ;Repeat hi *2 or a ; clear borrow sbc hl,bc ; sbc hl,bc ;hi=hi-divisor ccf ; invert borrow for shift later jr c,divid1 ; if borrow { adc hl,bc ; Restore the value of the HL ccf divid1: ex de,hl ; get lo adc hl,hl ; lo *2 + remainder ex de,hl dec a ; count-- jr nz,divid0 ;Until (bit count eq 0) ret page ;---------------------------------------------------------------------- ; 16 bit Multiply ;---------------- ; 1) This routine multiplies the contents of the HL register by the ; contents of the DE register leaving the result in the HL register. ; 2) Register Usage: ; BC -> [Preser de pop bc ; (Restore Registers) ret ; (Return) MuSk1: ld a,b rra ld b,a ld a,c rra ld c,a jr nc,MuSk2 add hl,de MuSk2: ex de,hl add hl,hl ex de,hl jr MuLp1 page ;---------------------------------------------------------------------- ; Call the Bios Extended Bios (Cold Boot) Entry Point (1_Aug_84) ;--------------------------------------------------------------- ; 1) The Cold Boot Entry point to the bios (1st entry in the bios ; jump table) is located by looking at locations 1 & 2 which ; point to the warm boot address (the desired address + 3). ; Extended_Bios: push hl ;Save the HL Register Pair ld hl,(1) ;HL:= Warm Boot Address ld l,0 ;HL:= Cold Boot Address ex (sp),hl ;HL:= Entry Value; Stack:= Cold Boot Entry ret ;Goto The Cold Boot entry ;---------------------------------------------------------------------- ; Move system memory into the local buffer (30_Jul_84) ;----------------------------------------------------- ; 1) This routine forces the destination to be the local buffer, calls ; the cold start (extended bios functions) entry point, and then saves ; the registers. ; 2) Enter with Accm equal to the extended bios function desired ; Get_Buffer: ld de,Buffer ;DE:= Pointer to Local Buffer call Extended_Bios ;Move System Memory into local buffer ld (Save_BC),bc ;Save the returned registers ld (Save_DE),de ld (Save_HL),hl ret ;Return ;---------------------------------------------------------------------- ; Put the Local Buffer into System Memory (30_Jul_84) ;---------------------------------------------------- ; 1) This is the inverse of GetBuf; It replaces the system's memory ; with the contents of the local buffer. ; Put_Buffer: ld a,1 ;Function_1: --------------------------------------------------------------------- ; Print a Message on the Console (25_Sept_84) ;-------------------------------------------- ; 1) This routine prints the message string, whose code is passed in the ; accm, on the console. ; 2) Register Usage: ; A -> Has Message Code on entry and exit ; B -> Counter ; C -> Holds copy of Message Code ; DE -> Used to hold pointers/Bdos print string functions ; HL -> Used to hold pointers ; Print_Message: ld c,a ;C:= Message Code to Find ld b,Max_Message ld hl,Msg_Table ;HL:= Start of the Message Table PmLp1: ld a,(hl) ;Repeat A:= Table's Message Code inc hl ld e,(hl) inc hl ld d,(hl) ; DE:= Pointer to String inc hl ; (HL equal to start next entry) cp c ; If (Code eq table) jr z,Pmprn ; Goto Print djnz PmLp1 ;Until (the whole tables been checked) ld de,NoCode ;(Pointer:= 'Unrecognized Message') PmPrn: push bc ld c,Bdos_PString ;C:= Bdos Print String Function call Bdos_Entry ;Print the Message pop bc ld a,c ;A:= Message Code ret page ;---------------------------------------------------------------------- ; Message Vector Table (19_Oct_84) ;--------------------------------- ; Msg_Table: db Err_Cpm_Rev ;Cpm Revision is NOT Cpm 3 dw EMrCpm db Err_Ccp_Rev ;Bios Compatability Rev too low dw EMrCcp db Err_Rom_Rev ;Rom Revision is too low dw EMrRom db Msg_Banner ;Title Banner dw MsgOpn db Msg_Reading ;Reading from Floppy dw MsgRd db Msg_Writing ;Writing to Floppy dw MsgWr db Msg_Pause ;Pause for Input Prompt dw MsgPas db General_Error ;General Error Code dw Err db Msg_CrLf ;New Line dw CrLf End_Table: Max_Message equ ( (End_Table - Msg_Table)/3 ) + 1 page ;-------------- ight,Cr,Lf,Tab db 'This version of Format Requires Cbios rev ' db ((Ccl and 0F0h) shr 4) + '0' db ' or higher.' db Cr,Lf,'$' EMrRom: db Esc,Bright,Cr,Lf,Tab db 'This version of Format Requires Rom Revision ' db ((Rrl and 0F0h) shr 4) + '0', '.', (Rrl and 0Fh) + '0' db ' or higher.' db Cr,Lf,'$' Err: db Esc,Bright,Cr,Lf,Lf,Tab db 'General Error $' NoCode: db Cr,Lf,Tab db 'Unrecognized Error $' page ;---------------------------------------------------------------------- ; Message Strings (19_Oct_84) ;---------------------------- ; MsgOpn: db Clear_Screen,Esc,Dim,Cr db 'MD-HD ' db Esc,Bright db 'Floppy Disk Backup ' db Esc,Dim db 'Program Rev ' db ((FRev and 0F0h) shr 4) + '0', '.', (FRev and 0Fh) + '0' db Tab,Tab,Tab,' Copyright 1984' db Cr,Lf db 'Morrow Designs Inc.' db Tab,Tab,Tab,Tab,Tab,Tab,'San Leandro, Ca' db Esc,Bright,Cr,Lf,'$' MsgRd: db Esc,Dim,Cr,Lf,Lf,Tab db 'Ready to ' db Esc,Bright db 'Read ' db Esc,Dim db 'the Floppy Disk' db Esc,Bright,'$' MsgWr: db Esc,Dim,Cr,Lf,Lf,Tab db 'Ready to ' db Esc,Bright db 'Write ' db Esc,Dim db 'to the Floppy Disk' db Esc,Bright,'$' MsgPas: db Cr,Lf,Tab db Esc,Dim db 'Press ' db Esc,Bright db 'RETURN ' db Esc,Dim,7 db 'when you are ready to continue. ' db Esc,Bright,'$' CrLf: db Cr,Lf,'$' page ;---------------------------------------------------------------------- ; Data Area (18_Oct_84) ;---------------------- ; Output_Radix: dw 10 ;Current Radix File_Active: db 0 ;File_Active Flag ;Initial Drive Assignments Initial_Drive: db 0 ;Current Drive when program started Fixed_Drive: db 0 ;Hard Disk Drive Floppy_Drive: db 0 ;Format Disk Number ;Read/Write Floppy Track Parameters Current_Sector: dw 0 ;Cur DE: dw 0 ; " " " " DE " " Save_HL: dw 0 ; " " " " HL " " ;Floppy Disk Characteristics Logical_Tracks: dw 0 ;Highest Logical Track Number Logical_Spt: dw 0 ;Number of Logical Sectors/Track Physical_Spt: dw 0 ;Number of Physical Sectors/Track P_Sector_Leng: dw 0 ;Physical Sector Length ;Floppy Disk Skew/Gap Table MsDos_Gap_Skew: db 50,85,80 db 9,8,7,6,5,4,3,2,1 ;Mtab Definition MsDos_Mtab_Dpb: db 0,4,0,0,0 ;Double Density Mtab db 0,0,0,0 ;Dpb Definition dw 36 ;secs per track db 3 ;block shift db 7 ;block mask db 1 ;extnt mask dw 350 ;disk size-1 dw 111 ;directory max db 0F0h ;alloc0 db 0 ;alloc1 dw 32 ;check size dw 2 ;offset Default_Fcb: db 0 db 'SAVEFILE$$$',0 ;Save File Name for Disk Data ds 24,0 page ;---------------------------------------------------------------------- ; Default Application Interface area (26_Sept_84) ;------------------------------------------------ ; Apif: db 0 ;(HSTDSK) BDOS Drive Number (1st floppy) dw 0000 ;(HSTTRK) Desired Cylinder (lo,hi) dw 0 ;(HSTSEC) Desired Sector (lo,hi) db 0 ;(SECCNT) Number of sectors to transfer db 10 ;(RETRY) Retry Count dw Sys_Disk_Buffer ;(HSTBUF) Buffer Address (lo,hi) db 0 ;(ERFLAG) Error Code db 18h ;(OPFLAG) Options Flag dw 0 ;(PHYTRK) Physical track number (lo,hi) db 0 ;(PHYSEC) Physical sector number db 0 ;(PHYHD) Desired Head db 0 ;(PHYDRV) Physical Drive Number dw 0 ;(IOADD) Execution Address (lo,hi) page ;---------------------------------------------------------------------- ; Local Buffers (3_Oct_84) ;------------------------- ; ds 40h ;Local Stack Space Local_Stack: dw 0 Buffer: ds 10h,0 ;Local Buffer (up