home *** CD-ROM | disk | FTP | other *** search
- ;
- ; S Y S G E N 2 9 . A S M
- ;
- ; This program allows a sysgen to/from system
- ; tracks with 29 sectors per track.
- ;
- ; Generated and modified from a disassembly by
- ; Willis E. Howard, III (1983).
- ;
- ; Useful constants.
- ; All equate variables in lower case.
- ;
- bell EQU 7 ;ASCII values
- bs EQU 8
- tab EQU 9
- lf EQU 10
- vt EQU 11
- ff EQU 12
- cr EQU 13
- ;
- boot EQU 0 ;Warm boot entry point
- wboot EQU 1 ;Warm boot vector address
- bdos EQU 5 ;BDOS entry point
- dfcb EQU 5CH ;Default FCB
- dmabuf EQU 80H ;Default DMA buffer
- buffer EQU 900H ;SYSGEN buffer begin
- maxdsk EQU 02H ;Maximum number of drives
- ;
- ; Set program origin
- ;
- ORG 0100H
- ;
- ; Jump over variables and subroutines
- ;
- JMP BEGIN
- ;
- DB ' '
- ;
- ; Total number of system tracks to read/write
- TRACKS:
- DB 2H
- ;
- ; Total number of sectors per system track
- ; Standard value is 26. Now set for 29 to
- ; get extended CBIOS.
- MXSEC:
- DB 1DH
- ;
- ; This is a list of the sectors, from 1 to MXSEC.
- ; The ordering should reflect the desired skew for
- ; your system. Now set for two. There is no real
- ; conversion of logical to physical sectors. This
- ; table just gives the ORDER in which sectors are
- ; read and written. Unused table space zero filled.
- SECLST:
- DB 1H,3H,5H,7H,9H,0BH,0DH,0FH,11H,13H,15H,17H,19H,1BH,1DH
- DB 2H,4H,6H,8H,0AH,0CH,0EH,10H,12H,14H,16H,18H,1AH,1CH
- DB 0H,0H,0H,0H,0H,0H,0H,0H,0H,0H,0H,0H,0H
- DB 0H,0H,0H,0H,0H,0H,0H,0H,0H,0H,0H,0H,0H
- DB 0H,0H,0H,0H,0H,0H,0H,0H,0H
- ;
- ; HL = A * 128
- ; This subroutine is used for calculating the offset
- ; of the track buffer for the sector given by A.
- MUL128:
- MOV L,A ;Put A in HL
- MVI H,00H
- DAD H ;Multiply by 128
- DAD H
- DAD H
- DAD H
- DAD H
- DAD H
- DAD H
- RET ;Now return
- ;
- ; Get a character from the console in upper case.
- CONIN:
- MVI C,01H ;Read console character code
- CALL bdos ;Do it through the BDOS
- CPI 'a' ;Less than 'a' is OK
- RC
- CPI '{' ;Greater than 'z' is OK
- RNC
- ANI '_' ;Wipe out LC bit
- RET
- ;
- ; Output A to the console
- CONOUT:
- MOV E,A ;Put the character in E
- MVI C,02H ;Write console character code
- CALL bdos ;Do it throught the BDOS
- RET
- ;
- ; Output a CR, LF
- CRLF:
- MVI A,cr ;CR out
- CALL CONOUT
- MVI A,lf ;LF out
- CALL CONOUT
- RET
- ;
- ; Output CR, LF and a string
- NLOUT:
- PUSH H
- CALL CRLF
- POP H
- ;
- ; Output just a string pointed to by HL and
- ; terminated with a zero byte
- PSTRING:
- MOV A,M ;Get the character
- ORA A
- RZ ;End on zero
- PUSH H
- CALL CONOUT ;Else, output it
- POP H
- INX H ;Next address
- JMP PSTRING ;And loop
- ;
- ; Select the disk given in A
- SELDSK:
- MOV C,A ;Disk given by C
- LHLD wboot ;Vector into BIOS
- LXI D,018H ;to select disk routine
- DAD D
- PCHL
- ;
- ; Set the track given in C
- SETTRK:
- LHLD wboot ;Vector into BIOS
- LXI D,01BH ;from wboot address
- DAD D ;to set track routine
- PCHL
- ;
- ; Set sector given in C
- SETSEC:
- LHLD wboot ;Get WBOOT address in BIOS
- LXI D,01EH ;Offset to set sector address
- DAD D ;Calculate it
- PCHL ;and jump
- ;
- ; Set DMA address, given in BC
- SETDMA:
- LHLD wboot ;Get WBOOT address in BIOS
- LXI D,021H ;Offset for set DMA routine
- DAD D ;Calculate
- PCHL ;and execute
- ;
- ; Read a sector
- READ:
- LHLD wboot ;Get WBOOT address in BIOS
- LXI D,024H ;Offset for read sector routine
- DAD D ;Calculate the address
- PCHL ;Jump to it
- ;
- ; Write a sector
- WRITE:
- LHLD wboot ;Get WBOOT address in BIOS
- LXI D,027H ;Offset for write sector routine
- DAD D ;Calculate the address
- PCHL ;Jump to it
- ;
- ; Read a sequential file sector
- READSQ:
- MVI C,014H ;Command code to read
- JMP bdos ;via the BDOS
- ;
- ; Open a file to read
- OPEN:
- MVI C,0FH ;Command code to open
- JMP bdos ;a file
- ;
- ; This subroutine will read or write the entire
- ; buffer starting at 'buffer', now set at 900H.
- ; TRACKS gives the number of tracks read/written, starting at 0.
- ; MXSEC gives the number of sectors read/written per track.
- ; SECLST determines the order in which sectors are read/written.
- RWSYS:
- LXI H,buffer ;Get the starting address
- SHLD POINTER ;and store it.
- MVI A,0FFH ;Get a -1 in track counter so that
- STA TRKCNT ;the first increment makes it 0.
- ;
- ; Come here to read/write another track.
- RWTRK:
- LXI H,TRKCNT ;Increment the track counter
- INR M
- LDA TRACKS ;Compare with the total for R/W
- CMP M
- JZ FINISH ;Finish off after total reached.
- ; ;Else begin the R/W track section
- MOV C,M ;Get the track counter
- CALL SETTRK ;and call the set track routine
- MVI A,0FFH ;Get a -1 in the sector counter so that
- STA SECCNT ;the first increment makes it 0.
- ;
- ; Come here to read/write another sector.
- RWSEC:
- LDA MXSEC ;Get the maximum sector count.
- LXI H,SECCNT ;Increment current sector count
- INR M ;and compare
- CMP M ;the two.
- JZ NEWBUF ;Jump if all sectors are written.
- ;
- LXI H,SECCNT ;Get the current sector count
- MOV E,M ;in DE but we can just
- MVI D,00H ;put a 0 in D.
- LXI H,SECLST ;This points to the sector list
- MOV B,M ;Save the first sector # in B
- DAD D ;Calculate the current sector #
- MOV C,M ;and save in C.
- PUSH B ;Save start and current numbers.
- CALL SETSEC ;Set the current sector number.
- POP B ;Restore both numbers.
- ;
- MOV A,C ;The difference gives number of sectors
- SUB B ;into the current track.
- CALL MUL128 ;*128 gives the byte count.
- ;
- XCHG ;We now add this byte count
- LHLD POINTER ;to the base address in memory for the
- DAD D ;start of the current track.
- MOV B,H ;Put the base address for the current
- MOV C,L ;sector in BC and set
- CALL SETDMA ;the DMA address.
- ;
- XRA A ;Set a zero in the
- STA TRYCNT ;retry count variable
- ;
- RWTRY:
- LDA TRYCNT ;Check for too many errors.
- CPI 10 ;Now set for 10.
- JC DOIT ;Jump if OK
- ;Else there were too many
- LXI H,RWERR ;Get string address
- CALL PSTRING ;and print error message
- CALL CONIN ;Get a console character
- CPI cr ;If CR, ignore
- JNZ EXIT ;Else, exit now.
- ;Get here to ignore error
- CALL CRLF ;Respond with CR, LF.
- JMP RWSEC ;Bravely get next sector.
- ;
- ; Perform the read or write
- DOIT:
- INR A ;Increment retry count
- STA TRYCNT ;and save it.
- LDA RWFLAG ;Check for read or write
- ORA A
- JZ DOREAD ;Zero means read.
- ;
- CALL WRITE ;Non-zero means write.
- JMP NEXT
- ;
- DOREAD:
- CALL READ
- ;
- NEXT:
- ORA A ;Check for errors
- JZ RWSEC ;Jump on none.
- ;
- JMP RWTRY ;On error, retry.
- ;
- ; Come here after a whole track has been read/written.
- ; This routine calculates the next base address for
- ; new track and stores it.
- NEWBUF:
- LDA MXSEC ;Get the maximum sector count
- CALL MUL128 ;in bytes.
- XCHG ;Put it in DE
- LHLD POINTER ;Get previous base address
- DAD D ;Add the offset
- SHLD POINTER ;and update the poiner
- JMP RWTRK
- ;
- ; Not really much to do to finish up.
- FINISH:
- RET
- ;
- ; This is the actual start of the SYSGEN program code.
- ; First, the system will be placed in the memory buffer
- ; starting at 900H. Then, this buffer can be written
- ; to the system tracks of any recognized disk. There
- ; are three ways for this program to load memory:
- ; 1) To read the system tracks of a disk.
- ; 2) To read a file, usually CPMxx.COM.
- ; 3) To use the copy already in memory.
- BEGIN:
- LXI SP,STACK ;Set the stack
- LXI H,VERSION ;Sign on with the version number
- CALL PSTRING
- LDA dfcb + 1 ;Check for a command line parameter
- CPI ' ' ;and if none,
- JZ GET ;then jump.
- ;
- ; This code is not documented in any of the
- ; Dig. Res. manuals that I have seen. If the
- ; SYSGEN command is followed with a file name as
- ;
- ; A>SYSGEN CPM60.COM
- ;
- ; then that file is loaded into memory. This code
- ; thus replaces the step
- ;
- ; A>DDT CPM60.COM
- ; DDT VERS 2.2
- ; NEXT PC
- ; 2300 0100
- ; -^C
- ; A>
- ;
- ; when you want to sysgen a system different from
- ; that on the system tracks of your system disk.
- ;
- ; Note that if you save memory after loading the
- ; system, cold loader and CBIOS with DDT, more
- ; than the 34 pages as stated in the Alteration
- ; Guide may be required. For 29 sectors/track,
- ; this corresponds to 29+8=37 pages.
- ;
- LXI D,dfcb ;Get the FCB
- CALL OPEN ;and open the file.
- INR A ;Check for errors and
- JNZ FILE ;jump on none.
- ;
- LXI H,NOFILE ;Get string address
- CALL NLOUT ;and print error message.
- JMP EXIT ;Then exit.
- ;
- ; First, we have to skip over the junk sectors.
- FILE:
- XRA A ;Get a zero as
- STA dfcb+32 ;current record
- MVI C,010H ;Count of trash sectors to read.
- ;
- TRASH:
- PUSH B ;Save the count.
- LXI D,dfcb ;Get FCB in DE and
- CALL READSQ ;read into default buffer.
- POP B ;restore count.
- ORA A ;On error
- JNZ SRCERR ;Report it.
- ;
- DCR C ;Check count
- JNZ TRASH ;and loop till all read.
- ;
- LXI H,buffer ;Get start address of memory buffer.
- ;
- ; Fill the memory buffer from the disk file.
- FILLBUF:
- PUSH H ;Save buffer address
- MOV B,H ;Put it in BC
- MOV C,L
- CALL SETDMA ;and set DMA address
- LXI D,dfcb
- CALL READSQ ;Read next sector
- POP H ;Restore pointer
- ORA A ;Check for more data
- JNZ SAVE ;Jump if all file read.
- ;
- LXI D,80H ;Sector size
- DAD D ;Next address
- JMP FILLBUF ;Loop.
- ;
- ; Report error in sequential read.
- SRCERR:
- LXI H,SHORT ;Get string address
- CALL NLOUT ;Output the message
- JMP EXIT ;Exit
- ;
- ; Get the system from disk system tracks.
- GET:
- LXI H,SNAME ;Ask for source drive.
- CALL NLOUT
- CALL CONIN ;Wait for reply.
- CPI cr ;On CR, skip memory load
- JZ SAVE ;and jump to save routine
- ;
- SUI 'A' ;Get a valid designator
- CPI maxdsk ;Check maximum drive #
- JC DOGET ;Jump if OK
- ;
- CALL IVDERR ;Else, report error
- JMP GET ;and try again.
- ;
- ; Perform read of system tracks to memory
- DOGET:
- ADI 'A' ;Make ASCII again.
- STA SDRIVE ;Store in the string.
- SUI 'A' ;Now select the disk
- CALL SELDSK
- CALL CRLF ;Output a CR, LF
- LXI H,SON ;and prompt for action.
- CALL PSTRING
- CALL CONIN ;Get reply
- CPI cr ;Anything but CR exits
- JNZ EXIT
- ;
- CALL CRLF ;Give a CR, LF reply
- XRA A ;and set the flag for READ
- STA RWFLAG
- CALL RWSYS ;Read now.
- LXI H,ALLOK ;Report read complete.
- CALL PSTRING ;Fall through for write.
- ;
- ; This section writes memory buffer to disk.
- ; No matter how memory was loaded, once the
- ; program gets here, it can not load memory again.
- ; The system can be written as many times as desired.
- SAVE:
- LXI H,DNAME ;Prompt for distination
- CALL NLOUT ;drive name.
- CALL CONIN ;Wait for a reply.
- CPI cr ;Anything but CR exits.
- JZ EXIT
- ;
- SUI 'A' ;Form code.
- CPI maxdsk ;Check maximum drive count.
- JC DOSAVE ;If OK, do it,
- ;Else error.
- CALL IVDERR ;Report error message
- JMP SAVE ;and try again.
- ;
- ; Perform save of memory buffer to system tracks.
- DOSAVE:
- ADI 'A' ;Make ASCII again and
- STA DDRIVE ;store in string.
- SUI 'A' ;Back to a code
- CALL SELDSK ;and select the disk.
- LXI H,DON
- CALL NLOUT ;Prompt for reply
- CALL CONIN ;Wait for reply
- CPI cr ;Anything but CR will exit
- JNZ EXIT
- ;
- CALL CRLF ;Give a CR,LF response
- LXI H,RWFLAG ;Set R/W flag to non-zero
- MVI M,01H ;for write.
- CALL RWSYS ;DO IT NOW
- LXI H,ALLOK ;Report done.
- CALL PSTRING
- JMP SAVE ;Go get another disk to write.
- ;
- ; Exit routine
- EXIT:
- MVI A,00H ;Select disk A:
- CALL SELDSK
- CALL CRLF ;Output CR, LF
- JMP boot ;Do a warm boot
- ;
- ; Invalid drive error
- IVDERR:
- LXI H,BADNAM ;Get string address
- CALL NLOUT ;Print message
- RET ;and return.
- ;
- ; Strings and variables
- VERSION:
- DB 'SYSGEN29 V 2.0',0H
- SNAME:
- DB 'Source drive name (or return to skip)',0H
- SON:
- DB 'Source on '
- SDRIVE:
- DB 0H
- DB ', then type return',0H
- DNAME:
- DB 'Destination drive name (or return to reboot)',0H
- DON:
- DB 'Destination on '
- DDRIVE:
- DB 0H
- DB ', then type return',0H
- RWERR:
- DB 'Permanent error, type return to ignore',0H
- ALLOK:
- DB 'Function complete',0H
- BADNAM:
- DB 'Invalid drive name (Use A OR B) ',0H
- NOFILE:
- DB 'No system file on disk',0H
- SHORT:
- DB 'System file incomplete',0H,0H
- TRKCNT:
- DB 0H ;Current track count
- SECCNT:
- DB 0H ;Current sector count
- RWFLAG:
- DB 0H ;Indicates a read or write
- POINTER:
- DW 0H ;Points to address to read/write
- TRYCNT:
- DB 0H ;Retry count
- ;
- DS 32
- STACK:
- END