title 'DOSRELOC - make/replace MOVCPM (86/12/07)' ; *********************************************** ; * Allows creation of MOVDOS or MOVCPM system * ; * where custom bioses, CCPs, BDOS patches, * ; * etc. have been installed. * ; * * ; * Copyright (C) 1980, 1982, 1984, 1986 * ; * by C.B. Falconer (203) 281-1438 * ; * 680 Hartford Tpk., * ; * Hamden, Conn 06517 * ; * * ; * All rights reserved * ; *********************************************** ; * 86/12/07 No change, altered DOS+ ver. * ; *********************************************** ; * 1.2 86/11/13 - Added OsborneI configuration * ; * Now require 'G' 2nd parameter for any * ; * immediate execution. Fewer accidents. * ; * Added "save" size customization * ; *********************************************** ; * 85/11/19 - Intel mnemnonics, no change * ; *********************************************** ; * 1.1 10 Mar. 1984. Added Kaypro installation * ; * constants. Specify aseg for m80. cbf * ; *********************************************** ; ; *** WARNING *** special values installed in "reloc" ; for KAYPRO sign-on. Very klugy ; ; *********************************************** ; Generate a relocation image for CP/M 2.2 & variants ; Assumes that: ; 1. zero based image located at 0980h-22ffh ; 2. running system exists @(6)-0806h up ; Generates a relocation bit map at 05c0 thru 08ffh where each byte ; specifies relocation for 8 object bytes. The ms bit of the bit ; vector corresponds to the lower of the 8 object bytes. Note that ; the bootstrap image at 900h thru 97fh will be read in from the ; system disk. If the assemble time constant "boot" is false suitable ; boot images are assumed to exist and any existing relocation bits ; are preserved. ; ; Algorithm: Wherever the two systems differ by exactly the load ; address hi byte of the running system a relocation bit is generated, ; else we assume some random data value, and generate 0. ; ; As far as possible this code is dependant on the various assembly ; time constants below. This should ease adaptation to other DOS+ or ; CPM versions or other systems. This is organized to simplify the ; conditional assembly areas to ease adaptation to other assemblers. ; ; The zero based image is available, 80h bytes higher, in the standard ; "MOVCPM" program. The user will have to add a suitable bios and ; optional boot image. For DOS+ the distributed MOVDOS+ program ; contains all images in the correct locations and is based on this. ; ; Since DDT or DDTZ replaces ccp in operation, and modifies the sysfnc ; entry in addition, the bit vector generator will not run under DDTZ. ; In addition, since the data is modified when relocating, the program ; can not be run again without reloading a fresh image. The system ; self modifies to become, in turn: ; bit vector generator ; "movcpm" program ; error program ; ; true equ -1 false equ not true boot set true; false leaves the boot reloc bits ver equ 12; program version ; ; CPM version. Set only one value "true" cpm14 equ false cpm22 equ false dos24 equ true ; ; Host machine. Set only one value "true". ; This suffices for the configured machines. ; For others various customization equates must be modified. sssd equ false yale equ false kp83 equ true; early Kaypro II/4 only oz1 equ false; Osborne I, dd ; if NOT (sssd OR yale OR kp83 or oz1) +++ Error - set at least one system true +++ endif ; ; DOS+/CPM values cout equ 2; write char. tstr equ 9; write string reboot equ 0 sysfnc equ reboot+5 defcb equ reboot+05ch parm1 equ defcb+1 altfcb equ reboot+06ch parm2 equ altfcb+1 ; ; define minimum size to run DDTZ and MOVDOS+ if yale or sssd or oz1 minsiz equ 16*4 endif if kp83; allow for bank switch, bios above it minsiz equ 17*4+2 @sgnon equ 01dch; offset for cbf (f4) bios sign-on msg. endif; VERY klugy patch arrangement. ; ; cpmsiz cannot exceed 01a00h on SSSD systems. Others vary. ; Smaller values can be used where the bios allocation is less ; than the maximum storable on 51 sectors (tks 0 & 1) (SSSD) ; For standard systems this means biosiz must not exceed 0380h ; Note that the system may use further uninitialized memory. ; ; Anomalous to avoid nested ifs. Ease portability if kp83 biosiz equ 200h btsect equ 0; Kaypros native numbering scheme endif if yale biosiz equ 080h btsect equ 1; Uses standard sector numbering endif if sssd biosiz equ 0380h; Standard allocation btsect equ 1; endif if oz1 biosiz equ 0880h btsect equ 0; Actually unused boot set false endif ; if cpm22 or dos24; use the following syssiz equ 28; pages, ver 2.2 bios allowance ccpsiz equ 0800h; size of the ccp segment bdosiz equ 0e00h; size of bdos segment endif if cpm22 cpmver equ 22; cpmversion no. endif if dos24 cpmver equ 25 endif if cpm14; use the following syssiz equ 23; 23 pages, ver 1.4 bios allowance ccpsiz equ 0800h; size of the ccp segment bdosiz equ 0d00h; size of bdos segment cpmver equ 14; cpmversion no. endif btsize equ 080h; size of any boot image cpmsiz equ btsize+ccpsiz+bdosiz+biosiz; Total system size imgloc equ 0900h; location of the zero based image ; if sssd AND (cpmsiz gt 01a00h) +++ ERROR - can't handle this size bios +++ endif ; pages equ (imgloc+cpmsiz-1)/256 ; ; offset controls the default /n parameter when the system sets itself ; to the max. memory available. This moves DOS+ or CPM up the spec- ; ified number of 256 byte pages, where less than the normal alloca- ; tion for bios is required. 0 is equivalent to the original movcpm. ; Offsets that are non-divisible by 4 will report a /n size parameter. ; Similarly negative values can be used to reserve space at the top of ; memory for other uses if kp83 or sssd offset equ 0; in "pages" endif if yale offset equ 4; All bios except vector/dskparms in ROM endif if oz1 offset equ -5; in "pages", reserve 1.25 k at top. endif ; ; ******** END customization equates ********** ; ; control chars cr equ 0dh lf equ 0ah ; aseg; Absolute segment org 0100h ; nop; handy for debug begin: jmp start; to patch for reverse operation ; ; ************************************************* ; generate the relocation bit map and construct a revised version of ; "movdos+" or "movcpm" program. The new "movdos+" can generate the ; owners bios, ccp and bootstrap start: lxi sp,stack lxi d,signon mvi c,tstr call sysfnc; sign-on call ldboot; in case image needed if not boot; bypass booter area lxi h,bitv+btsize/16 endif if boot; include booter area lxi h,bitv endif shld bitvec lhld sysfnc+1 lxi d,-(ccpsiz+6) dad d; point to start of ccp mov a,h sta delta if boot; include booter area lxi d,-btsize endif if not boot; leave patch space lxi d,0 endif dad d xchg if not boot; count and zero base ptr for no boot lxi h,cpmbas+btsize; bypass booter lxi b,(cpmsiz+7-btsize)/8; ensure full bytes endif if boot; count & zero base to include booter lxi h,cpmbas lxi b,(cpmsiz+7)/8 endif call vect; make relocation vector lxi h,mvcpm shld begin+1; convert entry lxi d,dunmsg jmp exit ; ; make bit vector ; at entry, (hl)=^current zero based image byte ; (de)=^current running system byte ; (bc)=(bytes to examine)/8 ; (delta)=critical difference to signal relocation ; (bitvec)=^storage for generated bit vector ; a,f,b,c,d,e,h,l,bitvec,bitvec^ vect: push b lxi b,8; b:=0;c:=bit ctr. vect2: lda delta xchg sub m xchg add m cma adi 1; cy if result was 0 mov a,b adc a; 2*a+cy mov b,a inx d inx h dcr c jnz vect2; same vector byte push h lhld bitvec mov m,b inx h shld bitvec pop h pop b dcx b; count generated bytes mov a,b ora c jnz vect; do next byte ret ; ; load track 0 sector 1 (the bootstrap) just below ccp ; this is the booter that works with the current system ; a,f,b,c,d,e,h,l ldboot: if NOT oz1; which has no boot sector mvi c,0 mvi a,9; select drive call biosf lhld sysfnc+1 lxi d,-(ccpsiz+6)-128 dad d; find base of ccp-128 mov b,h mov c,l mvi a,12; set dma call biosf mvi c,btsect mvi a,11; set sector call biosf mvi c,0 mvi a,10; set track call biosf mvi a,13; read sector call biosf ora a lxi d,msg7 jnz exit; bad read ret ; ; transfer to bios function #(a) ; a,f+bios biosf: push h lhld reboot+1 mov l,a add a add l mov l,a xthl; restore hl, stack xfr adr endif; so plenty of room for bit map on Osborne ret ; ; ************************************************* ; replacement section for "movdos+" or "movcpm" to use the above ; generated bit map. Uses "movcpm" protocol, except that the size ; specification (e.g. "48") can be qualified by /1,/2, or /3 (e.g. ; "48/1") to move the final system up by 1, 2, or 3 256 byte ; increments. Thus the system can be relocated on any page boundary. ; ; interrogate system for top of contiguous (to 0) memory ; returns (hl)=^last functional location (+256*offset) ; a,f,h,l qmem: lxi h,0ffh; assumes 0..100h exists qmem1: inr h jz qmem2; full memory. mov a,m cma mov m,a; *** This are must not cmp m; *** end up on page location 0ffh cma; *** else it will self destruct. mov m,a; restore it jz qmem1 qmem2: dcr h; point to last location functional mov a,h adi offset mov h,a ret ; ; a replacement "movcpm" program mvcpm: lxi sp,stack lxi h,reboot shld begin+1; prevent a 2nd call lxi d,signon mvi c,tstr call sysfnc; sign-on lxi d,parm1 ldax d cpi ' ' jz mvcpm5; use max available cpi '?' jz mvcpm5; use max available lxi h,0; will hold mem address mvcpm1: ldax d inx d call qnum jc mvcpm2; not digit sui '0' mov c,l mov b,h dad h; 2* dad h; 4* dad b; 5* dad h; 10* mov c,a mvi b,0 dad b; incorporate value jmp mvcpm1 mvcpm2: dad h dad h; 4*, in pages cpi '/'; check for increment jnz mvcpm3; none ldax d inx d call qnum jc errer; bad input sui '0' cpi 4 jnc errer; bad input add l mov l,a; result in pages mvcpm3: mov a,h dcr a jm mvcpm4; less than 64k jnz errer; more than 64k ora l jnz errer; 64/n k, error mvcpm4: mov h,l mvi l,0; *256, form top address dcx h; form top available address jmp mvcpm6 mvcpm5: call qmem; find top available mvcpm6: lxi d,-syssiz*256; dad d; final loadpoint in (hl) inx h; to actual loadpoint mov a,h sta delta; hi byte of relocation point cpi minsiz-syssiz jc errer; specification too small mvi c,tstr lxi d,msg1 call sysfnc; advise call tdelt lxi d,msg1a mvi c,tstr call sysfnc call reloc; relocate data in place lda parm2 cpi 'G' jz exec; put in place and execute mvi c,tstr lxi d,msg2 call sysfnc call tdelt lxi d,msg3 jmp exit ; ; put the relocated image in place and execute it exec: mvi c,tstr lxi d,msg6 call sysfnc lxi d,cpmbas+btsize; ignore the booter area lda delta mov h,a mvi l,0 lxi b,cpmsiz-btsize; count to transfer push h; save for control xfr exec1: ldax d mov m,a inx h inx d dcx b mov a,b ora c jnz exec1; more to move pop h lxi d,ccpsiz+bdosiz dad d; form entry to bios cold start pchl ; ; output "delta" as nn[/n] size id ; a,f tdelt: push b push d push h lda delta adi syssiz; correct for top of memory mov b,a ani 3 mov c,a mov a,b rar rar ani 03fh mvi e,'0'-1 jnz tdelt1; not 64k mvi e,'6' mvi a,'4' jmp tdelt2 tdelt1: inr e sui 10 jp tdelt1; extract ms digit adi '0'+10 tdelt2: push b push psw mvi c,cout call sysfnc pop psw mov e,a mvi c,cout call sysfnc pop b mov a,c ora a jz tdelt9; no extra portion adi '0' push psw mvi c,cout mvi e,'/' call sysfnc pop psw mov e,a mvi c,cout call sysfnc tdelt9: pop h pop d pop b ret ; ; relocate the data image in place, using the ; global variable "delta" as the relocation amount ; a,f,b,c,d,e,h,l reloc: lxi h,bitv lxi d,cpmbas lxi b,(cpmsiz+7)/8 reloc1: push b; save byte counter lxi b,8 mov b,m; get reloc bits xchg reloc2: mov a,b add a mov b,a jnc reloc3; dont relocate this lda delta add m mov m,a reloc3: inx h; next object byte dcr c jnz reloc2; more bits to scan xchg inx h; next reloc bit vector pop b dcx b mov a,b ora c jnz reloc1; not done ; ******************************************** if kp83; ** special considerations for sign-on lda parm1 cpi ' ' rz; 64k max, leave native sign-on lxi d,parm1 lxi h,cpmbas+btsize+ccpsiz+bdosiz+@sgnon; SPECIAL VALUE mov a,m; for cbf bios --^ ONLY cpi '6' rnz; This is not the right version ldax d; Appears to be the right bios, mov m,a; go ahead and patch the sign-on inx d inx h ldax d mov m,a; crude 2 digits for now endif ; ******************************************** ret ; ; check (a) for ascii numeric char, carry if not ; f qnum: cpi '0' rc cpi '9'+1 cmc ret ; ; error exit errer: lxi d,msg5 ; " " exit: mvi c,tstr call sysfnc jmp reboot ; msg1: db 'Constructing $' msg1A: db 'k DOS+ System V. ' db cpmver/10+'0','.',cpmver MOD 10 + '0', ' for ' if sssd db 'SSSD std. system' endif if kp83 db 'Kaypro 2/4 (83)' endif if yale db 'Yale' endif if oz1 db 'Osborne I' endif db '$' msg2: db cr,lf,'Ready for "SYSGEN" or "SAVE ' db pages/10 + '0', pages MOD 10 +'0' db ' DOS$' msg3: db 'K.SYS"$' msg5: db 'Invalid system size$' msg6: db cr,lf,'Running new system$' msg7: db cr,lf,'Error reading bootstrap image$' dunmsg: db 'Now "SAVE ' db pages/10 + '0', pages MOD 10 +'0' db ' MOVDOS+.COM"$' signon: db cr,lf,'DOS+ Mover Ver. ' db ver/10+'0','.',ver mod 10+'0',cr,lf,'$' ; ; storage bitvec: ds 2 delta: ds 1 ds 64; run time stack stack: ds 0 ; ; the data base area org imgloc-(cpmsiz+7)/8 if $ lt stack +++ ERROR bios too large +++ endif bitv: ds (cpmsiz+7)/8; resultant bit vector cpmbas: ds cpmsiz; image of cpm system ; end