Title Sysgen - System Generation Program (8_Jan_85) ; ; Copyright (c) Digital Research -- 1976, 1977, 1978, 1979 ; Modified for Micro-Decision by Morrow Designs, Inc. ; 3_Sept_82 ; 8_Jan_85 ; .z80 aseg org 0100h ;---------------------------------------------------------------------- ; Equates ;-------- ; vers equ 20 ;x.x ndisks equ 5 ;number of disk drives secsiz equ 128 ;size of each sector log2sec equ 7 ;log 2 secsiz fcb equ 5ch ;default fcb location fcbcr equ fcb+32 ;current record location tpa equ 100h ;transient program area loadp equ 900h ;load point for system during load/store bdos equ 5h ;dos entry point boot equ 0 ;jmp to 'boot' to reboot system coni equ 1 ;console input function cono equ 2 ;console output function self equ 14 ;select disk openf equ 15 ;disk open function dreadf equ 20 ;disk read function maxtry equ 1 ;maximum number of retries on each read/write cr equ 0dh ;carriage return lf equ 0ah ;line feed stacksize equ 16 ;size of local stack sctcnt equ (loadp-tpa)/secsiz wboot equ 1 ;address of warm boot (other patch entry ;points are computed relative to wboot) seldsk equ 24 ;wboot+24 for disk select settrk equ 27 ;wboot+27 for set track function setsec equ 30 ;wboot+30 for set sector function setdma equ 33 ;wboot+33 for set dma address readf equ 36 ;wboot+36 for read function writf equ 39 ;wboot+39 for write function ;---------------------------------------------------------------------- ; begin the code section ;----------------------- ; jp start db 'Copyright (c) 1978, Digital Research ' ;---------------------------------------------------------------------- ; multiply the sector number in a by the sector size ;--------------------------------------------------- ; multsec: ld l,a ld h,0 ;sector number in hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ret ;with hl = sector * sector size ;---------------------------------------------------------------------- ; read console character to register a ;------------------------------------- ; getchar: ld c,coni call bdos cp 'a' or 20h ;convert to upper case before return ret c ;return if below lower case a cp ('z' or 20h) + 1 ret nc ;return if above lower case z and 5fh ret ;---------------------------------------------------------------------- ; write character from a to console ;---------------------------------- ; putchar: ld e,a ld c,cono call bdos ret ;---------------------------------------------------------------------- ; send carriage return, line feed ;-------------------------------- ; crlf: ld a,cr call putchar ld a,lf call putchar ret ;---------------------------------------------------------------------- ; print message addressed by h,l til zero with leading crlf ;---------------------------------------------------------- ; crmsg: push hl call crlf pop hl jp outmsg ;---------------------------------------------------------------------- ; output a message to the console ;-------------------------------- ; outmsg: ld a,(hl) or a ret z push hl ;message not yet completed call putchar pop hl inc hl jp outmsg ;---------------------------------------------------------------------- ; select disk given by register a ;-------------------------------- ; sel: ld c,a ld hl,(wboot) ld de,seldsk add hl,de ld e,0 jp (hl) ;---------------------------------------------------------------------- ; set up track ;------------- ; trk: ld hl,(wboot) ;address of boot entry ld de,settrk ;offset for settrk entry add hl,de jp (hl) ;gone to settrk ;---------------------------------------------------------------------- ; set up sector number ;--------------------- ; sec: ld hl,(wboot) ld de,setsec add hl,de jp (hl) ;---------------------------------------------------------------------- ; set dma address to value of b,c ;-------------------------------- ; dma: ld hl,(wboot) ld de,setdma add hl,de jp (hl) ;---------------------------------------------------------------------- ; perform read operation ;----------------------- ; read: ld hl,(wboot) ld de,readf add hl,de jp (hl) ;---------------------------------------------------------------------- ; perform write operaton ;----------------------- ; write: ld c,2 wrtd: ld hl,(wboot) ld de,writf add hl,de jp (hl) ;---------------------------------------------------------------------- ; disk read function ;------------------- ; dread: ld c,dreadf jp bdos ;---------------------------------------------------------------------- ; file open function ;------------------- ; open: ld c,openf jp bdos ;---------------------------------------------------------------------- ; get or put cp/m (rw=0 for read, 1 for write) disk is already selected ;---------------------------------------------------------------------- ; getput: ld hl,loadp ;load point in ram for cp/m during sysgen ld (dmaddr),hl ;clear track to 00 ld a,-1 ;start with track equal -1 ld (track),a ; read or write next track ;------------------------- ; rwtrk: ld hl,track inc (hl) ;track = track + 1 ld a,(ost) ;number of operating system tracks cp (hl) ;= track number ? jp z,endrw ;end of read or write ; otherwise notdone, go to next track ld c,(hl) ;track number ld b,0 call trk ;to set track ld a,-1 ;counts 0, 1, 2, . . . 25 ld (sector),a ;sector incremented before read or write ; read or write sector ;--------------------- ; rwsec: ld a,(spt) ;sectors per track ld hl,sector inc (hl) ;to next sector cp (hl) ;a=26 and m=0 1 2...25 (usually) jp z,endtrk ; read or write sector to or from current dma addr ld hl,sector ld e,(hl) ;sector number ld d,0 ;to de ld hl,tran ld b,(hl) ;tran(0) in b add hl,de ;sector translated ld c,(hl) ;value to c ready for select push bc ;save tran(0),tran(sector) ld b,0 call sec ;set up sector number pop bc ;recall tran(0),tran(sector) ld a,c ;tran(sector) sub b ;-tran(0) call multsec ;*sector size ex de,hl ;to de ld hl,(dmaddr) ;base dma address for this track add hl,de ;+(tran(sector)-tran(0))*secsiz ld b,h ld c,l ;to bc for sec call call dma ;dma address set from b,c ; dma address set, clear retry count xor a ld (retry),a ;set to zero retries trysec: ld a,(retry) ;try to read or write current sector cp maxtry ;too many retries? jp c,tryok ; past maxtries, message and ignore ld hl,errmsg call outmsg call getchar cp cr jp nz,reboot ; typed a cr, ok to ignore call crlf jp rwsec tryok: inc a ;ok to try read or write ld (retry),a ;&&& ld a,(rw) ;read or write? or a jp z,tryread call write ;must be write jp chkrw ;check for error returns tryread:call read chkrw: or a jp z,rwsec ;zero flag if r/w ok jp 0 ;error, warm boot ;---------------------------------------------------------------------- ; end of track ;------------- ; endtrk: ld a,(spt) ;sectors per track call multsec ;*secsiz ex de,hl ;to de ld hl,(dmaddr) ;base dma for this track add hl,de ;+spt*secsiz ld (dmaddr),hl ;ready for next track jp rwtrk ;for another track ;---------------------------------------------------------------------- ; end of read or write, return to caller ;--------------------------------------- ; endrw: ld a,(rw) ;see if read or a ret z ;return if read ld c,1 ;do last write again, call wrtd ;but force write of last sector or a ;check for error ret z ;return if no error ld hl,errmsg ;print error mesg. call outmsg call getchar ;get input cp cr ;see if cr jp nz,reboot ;reboot call crlf ;ignore ret ;---------------------------------------------------------------------- ; Main Entry Point ;----------------- ; start: ld sp,stack ;set local stack pointer ld hl,signon call outmsg ;check for default file load instead of get ld a,(fcb+1) ;blank if no file cp ' ' jp z,getsys ;skip to get system message if blank ld de,fcb ;try to open it call open inc a ;255 becomes 00 jp nz,rdok ;ok to read if not 255 ; file not present, error and reboot ld hl,nofile call crmsg jp reboot ; file present -- read to load point ;----------------------------------- ; rdok: xor a ld (fcbcr),a ;current record = 0 ;pre-read area from tpa to loadp ld c,sctcnt ;pre-read file prerd: push bc ;save count ld de,fcb ;input file control count call dread ;assume set to default buffer pop bc ;restore count or a jp nz,badrd ;cannot encounter end-of file dec c ;count down jp nz,prerd ;for another sector ; sectors skipped at beginning of file ld hl,loadp rdinp: push hl ld b,h ld c,l ;ready for dma call dma ;dma address set ld de,fcb ;ready for read call dread pop hl ;recall dma address or a ;00 if read ok jp nz,putsys ;assume eof if not. ;more to read, continue ld de,secsiz add hl,de ;hl is new load address jp rdinp ;eof encountered in input file ;----------------------------- ; badrd: ld hl,badfile call crmsg jp reboot getsys: ld hl,askget ;get system? call crmsg call getchar cp cr jp z,putsys ;skip if cr only sub 'a' ;normalize drive number cp ndisks ;valid drive? jp c,getc ;skip to getc if so call baddisk ;invalid drive number jp getsys ;to try again ;---------------------------------------------------------------------- ; select disk given by register a ;-------------------------------- ; getc: add a,'a' ld (gdisk),a ;to set message sub 'a' push af ; getsys, set rw to read and get the system call crlf ld hl,getmsg call outmsg call getchar cp cr jp nz,reboot call crlf pop af call sel ;to select the drive call fixskw xor a ld (rw),a call getput ld hl,done call outmsg ; put system ;----------- ; putsys: ld hl,askput call crmsg call getchar cp cr jp z,reboot sub 'a' cp ndisks jp c,putc call baddisk ; invalid drive name jp putsys ;to try again ;set disk from register c putc: add a,'a' ld (pdisk),a ;message set sub 'a' push af ; put system, set rw to write ld hl,putmsg call crmsg call getchar cp cr jp nz,reboot call crlf pop af call sel ;select dest drive call fixskw ld hl,rw ld (hl),1 call getput ;to put system back on diskette ld hl,done call outmsg jp putsys ;for another put operation reboot: ld a,0 call sel call crlf jp boot ; bad disk name ;-------------- ; baddisk: ld hl,qdisk call crmsg ret err: ld hl,serr call crmsg jp reboot nomtch: or a ;see if system s or d sided ld hl,smesg ;get single sided mesg. jp z,sing ;jmp if single ld hl,dmesg ;double sided mesg sing: call crmsg jp putsys fixskw: ld de,0ah ;offset to dpb pointer add hl,de ;add to dph pointer ld e,(hl) ;get dpb pointer inc hl ld d,(hl) ex de,hl ld a,(hl) ;get sectors/track ld (spt),a ;save push af ld de,13 ;offset to reserved tracks add hl,de ld a,(hl) ;reserved tracks ld (ost),a ;save pop af ;sectors/track ld e,a inc e rrca ;divide by 8 rrca rrca ld d,a ld c,1 ;first sector ld hl,tran ;pointer to table trlp0: ld b,8 ;logical sectors/physical sector trlp1: ld (hl),c ;store sector in table inc c ;increment sector inc hl ;increment pointer djnz trlp1 ;loop dec d ;see if done ret z ;return if done ld a,8 ;skew add a,c ;add to sector ld c,a cp e ;see if overflow jr c,trlp0 ;loop if no overflow ld c,9 jr trlp0 ;---------------------------------------------------------------------- ; Message Strings (8_Jan_85) ;--------------------------- ; signon: db 'Sysgen Version ' db vers/10+'0','.',vers mod 10+'0',' md2.0' db 0 askget: db 'Source Drive Name (or return to skip)',0 getmsg: db 'Source on ' gdisk: ds 1 ;filled in at get function db ', then press Return',0 askput: db 'Destination Drive Name (or return to reboot)',0 putmsg: db 'Destination on ' pdisk: ds 1 ;filled in at put function db ', then press Return',0 errmsg: db 'Permanent Error, press Return to Ignore',0 done: db 'Function Complete',0 qdisk: db 'Invalid Drive Name (use A, B, C, D, or E)',0 nofile: db 'No Source File on Disk',0 badfile:db 'Source File Incomplete',0 serr: db 'Wrong Version of CP/M',0 smesg: db 'Single Sided diskette cannot ' db 'accept Double Sided system',0ah,0 dmesg: db 'Double Sided diskette cannot ' db 'accept Single Sided system',0ah,0 page ;---------------------------------------------------------------------- ; Translate Table ;---------------- ; - sector numbers are translated here to decrease the sysgen time ; for missed sectors when slow controllers are involved. translation ; takes place according to the "skew" factor set above. ; ost: db 0 spt: db 0 tran: ds 80,0 ;---------------------------------------------------------------------- ; variables ;---------- ; sdisk: ds 1 ;selected disk for current operation track: ds 1 ;current track sector: ds 1 ;current sector rw: ds 1 ;read if 0, write if 1 dmaddr: ds 2 ;current dma address retry: ds 1 ;number of tries on this sector ds stacksize*2 stack: end