home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
norge.freeshell.org (192.94.73.8)
/
192.94.73.8.tar
/
192.94.73.8
/
pub
/
computers
/
cpm
/
alphatronic
/
DRIPAK.ZIP
/
CPM_3-0
/
SOURCES
/
GENCPM.PLM
< prev
next >
Wrap
Text File
|
1982-12-31
|
43KB
|
1,479 lines
$title('CP/M 3 System Generation')
gencpm:
do;
/*
Copyright (C) 1982
Digital Research
P.O. Box 579
Pacific Grove, CA 93950
*/
/*
Revised:
02 Dec 82 by Bruce Skidmore
*/
declare true literally '0FFH';
declare false literally '0';
declare forever literally 'while true';
declare boolean literally 'byte';
declare cr literally '0dh';
declare lf literally '0ah';
mon1:
procedure (func,info) external;
declare func byte;
declare info address;
end mon1;
mon2:
procedure (func,info) byte external;
declare func byte;
declare info address;
end mon2;
relfix:
procedure byte external;
end relfix;
setbuf:
procedure external;
end setbuf;
getdef:
procedure external;
end getdef;
crtdef:
procedure external;
end crtdef;
declare reset label external;
declare fcb (1) byte external;
declare fcb16 (1) byte external;
declare tbuff (1) byte external;
declare maxb address external;
declare bitmap (128) byte external;
declare FCBin address public;
declare bios$fcb (36) byte initial (
0,'BNKBIOS3','SPR',0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
declare res$fcb (36) byte initial (
0,'RESBDOS3','SPR',0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
declare bnk$fcb (36) byte initial (
0,'BNKBDOS3','SPR',0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
declare FCBout (36) byte initial (
0,'CPM3 ','SYS',0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
declare data$fcb (36) byte public initial (
0,'GENCPM ','DAT',0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
declare offset byte public;
declare prgsiz address public;
declare bufsiz address public;
declare codsiz address public;
declare bios$pg byte public;
declare scb$pg byte public;
declare res$pg byte public;
declare bnk$pg byte public;
declare bnk$off byte public;
declare res$len byte public;
declare non$bnk byte public;
declare dma address public;
declare hexASCII (16) byte public data (
'0123456789ABCDEF');
declare lnbfr (14) byte public initial (12);
declare sctbfr (1) structure (
record (128) byte) public at (.memory);
declare fcb$msg (13) byte initial (' . $');
declare query boolean public;
/*
B D O S P r o c e d u r e & F u n c t i o n C a l l s
*/
system$reset:
procedure public;
call mon1 (0,0);
end system$reset;
write$console:
procedure (char) public;
declare char byte;
if display then
call mon1 (2,char);
end write$console;
print$console$buffer:
procedure (buffer$address) public;
declare buffer$address address;
if display then
call mon1 (9,buffer$address);
end print$console$buffer;
read$console$buffer:
procedure (buffer$address) public;
declare buffer$address address;
declare buf based buffer$address (1) byte;
buf(1) = 0;
if automatic then
do;
if not query then
return;
end;
call mon1 (10,buffer$address);
buf(buf(1)+2) = 0;
end read$console$buffer;
crlf:
procedure public;
call write$console (cr);
call write$console (lf);
end crlf;
error:
procedure(term$code,err$type,err$msg$adr) public;
declare (term$code,err$type) byte;
declare err$msg$adr address;
display = true;
call print$console$buffer (.(cr,lf,
'ERROR: $'));
call print$console$buffer (err$msg$adr);
if err$type = 1 then
call print$console$buffer(.fcb$msg);
call crlf;
if term$code then
call system$reset;
if automatic and not query then
do;
fcb(1),
fcb16(1) = ' ';
goto reset;
end;
end error;
open$file:
procedure (fcb$address) byte public;
declare fcb$address address;
declare fcb based fcb$address (1) byte;
fcb(12), /* ex = 0 */
fcb(32) = 0; /* cr = 0 */
return mon2 (15,fcb$address);
end open$file;
close$file:
procedure (fcb$address) public;
declare fcb$address address;
call mon1 (16,fcb$address);
end close$file;
delete$file:
procedure (fcb$address) public;
declare fcb$address address;
call mon1 (19,fcb$address);
end delete$file;
read$record:
procedure (fcb$address) public;
declare fcb$address address;
if mon2 (20,fcb$address) <> 0 then
do;
call error(true,1,.(
'Reading file: $'));
end;
end read$record;
write$record:
procedure (fcb$address) public;
declare fcb$address address;
if mon2 (21,fcb$address) <> 0 then
do;
call error(true,1,.(
'Writing file: ','$'));
end;
end write$record;
create$file:
procedure (fcb$address) public;
declare fcb$address address;
declare fcb based fcb$address (1) byte;
if mon2 (22,fcb$address) = 255 then
do;
call error(true,0,.(
'Directory full','$'));
end;
fcb(32) = 0; /* set cr = 0 */
end create$file;
set$DMA$address:
procedure (DMA$address) public;
declare DMA$address address;
call mon1 (26,DMA$address);
end set$DMA$address;
read$random$record:
procedure (fcb$address) public;
declare fcb$address address;
if mon2 (33,fcb$address) <> 0 then
do;
call error(true,1,.(
'Reading file: ','$'));
end;
end read$random$record;
write$random$record:
procedure (fcb$address) public;
declare fcb$address address;
if mon2 (34,fcb$address) <> 0 then
do;
call error(true,1,.(
'Writing file: ','$'));
end;
end write$random$record;
set$random$record:
procedure (fcb$address) public;
declare fcb$address address;
call mon1 (36,fcb$address);
end set$random$record;
/*
D a t a S t r u c t u r e s
*/
declare automatic boolean;
declare display boolean public;
declare nmb$sect address;
declare link address at (.memory);
declare bios$atts(3) address public;
declare res$atts(3) address public;
declare bnk$atts(3) address public;
declare res$bios$len byte public;
declare res$base byte public;
declare pg$dif byte public;
declare xmove$implemented boolean public;
declare os$top address;
declare system$data (256) byte;
declare common$len byte public at (.system$data(1));
declare banked$len byte public at (.system$data(3));
declare sys$entry address public at (.system$data(4));
declare prt$msg$ptr byte;
declare dont$hash boolean;
declare wordadr address;
declare word based wordadr address;
declare len byte;
declare off address;
declare res$flg byte;
declare save$mem$top byte;
declare drvtbl$adr address public;
declare drvtbl based drvtbl$adr (16) address;
declare dph$adr address public;
declare dph based dph$adr structure (
xlt address,
scratch1(4) address,
scratch2 byte,
mf byte,
dpb address,
csv address,
alv address,
dirbcb address,
dtabcb address,
hash address,
hbank byte);
declare dpb$adr address public;
declare dpb based dpb$adr structure (
spt address,
bsh byte,
blm byte,
exm byte,
dsm address,
drm address,
al0 byte,
al1 byte,
cks address,
off address,
psh byte,
phm byte);
declare bnk$swt boolean external;
declare dbl$alv boolean external;
declare mem$top byte external;
declare bnk$top byte external;
declare lerror boolean external;
declare bdrive byte external;
declare con$wid byte external;
declare con$pag byte external;
declare bck$spc boolean external;
declare rubout boolean external;
declare prt$msg boolean external;
declare hash(16) boolean external;
declare num$seg byte external;
declare crdatf boolean external;
declare mem$tbl (17) structure(
base byte,
len byte,
bank byte,
attr address) external;
declare record(16) structure(
size address,
attr byte,
altbnks byte,
no$dirrecs byte,
no$dtarecs byte,
ovlydir$dr byte,
ovlydta$dr byte,
dir$resp byte,
dta$resp byte) external;
declare quest(157) boolean external;
declare hash$data(16) address public;
declare hash$space address public;
declare alloc(16) address public;
declare alloc$space address public;
declare chk(16) address public;
declare chk$space address public;
/*
L o c a l P r o c e d u r e s
*/
movef:
procedure (count,source$adr,dest$adr) public;
declare count byte;
declare (source$adr,dest$adr) address;
if count = 0
then return;
else call move (count,source$adr,dest$adr);
end movef;
shift$left:
procedure (pattern, count) address public;
declare count byte;
declare pattern address;
if count = 0
then return pattern;
else return shl(pattern,count);
end shift$left;
upper:
procedure(b) byte public;
declare b byte;
if b < ' ' then return cr; /* all non-graphics */
/* translate alpha to upper case */
if b >= 'a' and b <= 'z' then
b = b and 101$1111b; /* upper case */
return b;
end upper;
valid$drive:
procedure(drv) boolean public;
declare drv byte;
if (drv >= 0) and (drv <= 15) then
return true;
call error(false,0,.('Invalid drive.$'));
return false;
end valid$drive;
get$response:
procedure (val$adr) public;
declare val$adr address;
declare val based val$adr byte;
call write$console ('(');
if val = 0ffh
then call write$console ('Y');
else call write$console ('N');
call print$console$buffer (.(') ? ','$'));
call read$console$buffer (.lnbfr);
if lnbfr(1) = 0
then return; /* accept default */
val = (upper(lnbfr(2)) = 'Y');
end get$response;
dsply$hex:
procedure (val) public;
declare val byte;
call write$console (hexASCII(shr (val,4)));
call write$console (hexASCII(val and 0fh));
end dsply$hex;
dsply$hex$adr:
procedure (val) public;
declare val address;
call write$console (' ');
call dsply$hex (high (val));
call dsply$hex (low (val));
call write$console ('H');
end dsply$hex$adr;
dsply$hex$high$adr:
procedure (val) public;
declare val byte;
call dsply$hex$adr (double (val)*256);
end dsply$hex$high$adr;
dsply$dec$adr:
procedure (val) public;
declare val address;
declare big address;
declare (digit,i) byte;
declare pdigit boolean;
pdigit = false;
digit = '0';
big = 10000;
if val = 0 then
call write$console(digit);
else
do;
do i = 0 to 4;
do while val >= big;
pdigit = true;
digit = digit + 1;
val = val - big;
end;
if pdigit then
do;
call write$console(digit);
digit = '0';
end;
big = big / 10;
end;
end;
end dsply$dec$adr;
dsply$param:
procedure (val,base) public;
declare (val,base) byte;
call write$console ('(');
if base = 10 then
do;
call write$console ('#');
call dsply$dec$adr(double(val));
end;
else
do;
call dsply$hex (val);
end;
call print$console$buffer (.(') ? ','$'));
end dsply$param;
get$param:
procedure (string$adr,val$adr,pbase) public;
declare (string$adr,val$adr) address;
declare pbase byte;
declare base byte;
declare val based val$adr byte;
declare string based string$adr (1) byte;
declare char byte;
declare lbindx byte;
prompt$read:
procedure;
call print$console$buffer (string$adr);
if string(0) = ' ' then
do;
call write$console ('(');
call dsply$hex (val);
do lbindx = 1 to 2;
val$adr = val$adr + 1;
if (lbindx=2) and (not bnk$swt) then
do;
val = 0;
end;
else
do;
call write$console (',');
call dsply$hex (val);
end;
end;
val$adr = val$adr - 2;
call print$console$buffer (.(') ? ','$'));
end;
else
do;
call dsply$param (val,pbase);
end;
base = 16;
lbindx = 1;
call read$console$buffer (.lnbfr);
end prompt$read;
call prompt$read;
if lnbfr(1) = 0 then
do;
/* accept default value */
call crlf;
return;
end;
val = 0;
do while (char := upper(lnbfr(lbindx:=lbindx+1))) <> cr;
if char = ',' then
do;
val$adr = val$adr + 1;
val = 0;
base = 16;
end;
else
do;
if char = '#' then
do;
base = 10;
end;
else
do;
char = char - '0';
if (base = 16) and (char > 9) then
do;
if char > 16
then char = char - 7;
else char = 255;
end;
if char < base then
do;
val = val*base + char;
end;
else
do;
char,
val = 0;
call error (false,0,.(
'Bad character, re-enter $'));
call prompt$read;
val = 0;
end;
end;
end;
end;
call crlf;
end get$param;
get$seg:
procedure(type,record$size) byte public;
declare (type,k,seg$no) byte;
declare (record$size,max$attr) address;
if not bnk$swt then
return 0;
seg$no = 0ffh;
max$attr = 0ffffh;
do k = 1 to num$seg;
if mem$tbl(k).attr >= record$size then
if type = 1 then
do;
if (mem$tbl(k).bank = 0) and
(mem$tbl(k).attr < max$attr) then
do;
seg$no = k;
max$attr = mem$tbl(k).attr;
end;
end;
else
do;
if (mem$tbl(k).bank <> 0) and
(mem$tbl(k).attr < max$attr) then
do;
seg$no = k;
max$attr = mem$tbl(k).attr;
end;
end;
end;
if (seg$no = 0ffh) and (type = 2) then
do k = 1 to num$seg;
if (mem$tbl(k).attr >= record$size) and
(mem$tbl(k).bank = 0) and
(mem$tbl(k).attr < max$attr) then
do;
seg$no = k;
max$attr = mem$tbl(k).attr;
end;
end;
return seg$no;
end get$seg;
plm:
procedure public;
st$ascii$hex:
procedure(string$adr,val);
declare string$adr address;
declare string based string$adr (6) byte;
declare val address;
declare i byte;
string(0) = ' ';
string(1) = ' ';
string(2) = hexASCII(shr(high(val),4));
string(3) = hexASCII(high(val) and 0fh);
string(4) = hexASCII(shr(low(val),4));
string(5) = hexASCII(low(val) and 0fh);
end st$ascii$hex;
setup$scb:
procedure;
declare scb$adr address;
declare scb$dat based scb$adr (100) byte;
scb$adr = .memory + shl(double(scb$pg-res$pg),8) + 09ch;
scb$dat(13h) = bdrive;
scb$dat(1ah) = con$wid;
scb$dat(1ch) = con$pag;
scb$dat(2eh) = bck$spc;
scb$dat(2fh) = rubout;
call movef(5,.(012h,07h,0,0,0),.scb$dat(58h)); /* December 15, 1982 */
if not lerror then
scb$dat(57h) = scb$dat(57h) and 7fh;
if not dbl$alv and not bnk$swt then
scb$dat(57h) = scb$dat(57h) or 0100$0000B;
else
scb$dat(57h) = scb$dat(57h) and 1011$1111B;
scb$dat(5eh) = bnk$top;
end setup$scb;
get$drvtbl$adr:
procedure address;
declare temp$adr address;
declare temp2 based temp$adr address;
declare temp3 address;
temp$adr = .memory(43h);
temp3 = temp2 + 1 + .memory;
temp$adr = temp3;
if temp2 = 0fffeh
then res$flg = 2;
else res$flg = 0;
if temp2 < 0fffeh
then return temp2 + .memory;
else return 0ffffh;
end get$drvtbl$adr;
page$chop:
procedure;
declare i byte;
drvtbl$adr = get$drvtbl$adr;
dont$hash = true;
if (drvtbl$adr <> 0ffffh) then
do;
do i = 0 to 15;
if drvtbl(i) <> 0 then
do;
dph$adr = drvtbl(i) + .memory;
if dph.hash <> 0ffffh then
dont$hash = false;
end;
end;
if dont$hash and not bnk$swt then
res$flg = 2;
else
res$flg = 0;
end;
end page$chop;
get$xmove:
procedure boolean;
declare xmove$adr address;
declare xmove$val based xmove$adr byte;
call movef(2,.memory(58h),.xmove$adr);
xmove$adr = xmove$adr + .memory;
if xmove$val = 0c9h /* ret instr. */ then
return false;
else
return true;
end get$xmove;
display$layout:
procedure(string$adr,base,length);
declare string$adr address;
declare base address;
declare length byte;
call print$console$buffer (.(cr,lf,' ','$'));
call print$console$buffer (string$adr);
call write$console(' ');
call dsply$hex$adr (base);
call write$console(' ');
call dsply$hex$high$adr (length);
if prt$msg then
do;
call movef(12,string$adr,.system$data(prt$msg$ptr));
prt$msg$ptr = prt$msg$ptr + 12;
call st$ascii$hex(.system$data(prt$msg$ptr),base);
prt$msg$ptr = prt$msg$ptr + 6;
call st$ascii$hex(.system$data(prt$msg$ptr),
double(length)*256);
prt$msg$ptr = prt$msg$ptr + 6;
call movef(3,.(cr,lf,' '),.system$data(prt$msg$ptr));
prt$msg$ptr = prt$msg$ptr + 3;
end;
end display$layout;
reloc$module:
procedure (fcb$adr);
declare fcb$adr address;
FCBin = fcb$adr;
if relfix <> 0 then
do;
call error(true,1,.('Disk read error: $'));
end;
call close$file(fcb$adr);
end reloc$module;
load:
procedure (fcb$adr,atts$adr);
declare fcb$adr address;
declare atts$adr address;
declare atts based atts$adr (3) address;
declare (i,rdcnt) byte;
prgsiz = atts(0);
bufsiz = atts(1);
codsiz = atts(2);
call movef(8,fcb$adr+1,.fcb$msg);
call movef(3,fcb$adr+9,.fcb$msg+9);
if shr(prgsiz+255,7) > nmb$sect then
do;
call error(true,1,.('File cannot fit into GENCPM buffer: ','$'));
end;
rdcnt = low(shr(prgsiz-1,7)) + 1;
i = 0;
do while (i < rdcnt);
call set$dma$address(dma:=.sctbfr(i));
call read$record(fcb$adr);
i = i + 1;
end;
call movef(128,dma,.bitmap); /* copy the last sector read, into */
/* the bitmap buffer, relocation */
/* info might be that last sector */
dma = prgsiz + .memory;
end load;
wrtbuf:
procedure (wrtlen,wrtoff$adr);
declare (i,wrtlen,wrtcnt) byte;
declare wrtoff$adr address;
declare wrtoff based wrtoff$adr address;
if wrtlen <> 0 then
do;
call movef(8,.FCBout+1,.fcb$msg);
call movef(3,.FCBout+9,.fcb$msg+9);
FCBout(33) = low(wrtoff);
FCBout(34) = high(wrtoff);
call write$random$record(.FCBout);
dma = dma + low(256 - low(dma - .memory));
wrtcnt = wrtlen * 2 - 1;
do i = 0 to wrtcnt;
call set$dma$address(dma:=dma-80h);
call write$record(.FCBout);
end;
call set$random$record(.FCBout);
call movef(2,.FCBout(33),wrtoff$adr);
end;
end wrtbuf;
get$file$info:
procedure;
declare fcb$adr address;
declare atts$adr address;
declare file$atts based atts$adr(3) address;
declare header$record structure (
fill1 byte,
psize address,
fill2 byte,
dsize address,
fill3 (4) byte,
csize address,
fill4 (116) byte) at (.memory);
get$atts:
procedure;
call movef(8,fcb$adr+1,.fcb$msg);
call movef(3,fcb$adr+9,.fcb$msg+9);
if open$file(fcb$adr) = 0ffh
then call error(true,1,.('Unable to open: $'));
call set$dma$address(.header$record);
call read$record(fcb$adr);
file$atts(0) = header$record.psize;
file$atts(1) = header$record.dsize;
file$atts(2) = header$record.csize;
call read$record(fcb$adr);
end get$atts;
if not bnk$swt then
do;
call movef(8,.('BDOS3 '),.res$fcb+1);
call movef(8,.('BIOS3 '),.bios$fcb+1);
end;
else
do;
fcb$adr = .bnk$fcb;
atts$adr = .bnk$atts;
call get$atts;
end;
fcb$adr = .bios$fcb;
atts$adr = .bios$atts;
call get$atts;
fcb$adr = .res$fcb;
atts$adr = .res$atts;
call get$atts;
end get$file$info;
need$tbl:
procedure byte;
declare (all$some,i) byte;
all$some = false;
if drvtbl$adr = 0ffffh
then return false;
else
do i = 0 to 15;
if drvtbl(i) <> 0 then
do;
dph$adr = drvtbl(i) + .memory;
/* zero the reserved bytes in the DPH */
call movef(9,.(0,0,0,0,0,0,0,0,0),dph$adr+2);
if (dph.dirbcb = 0fffeh) or (dph.dtabcb = 0fffeh) or
(dph.hash = 0fffeh) or (dph.alv = 0fffeh) or
(dph.csv = 0fffeh)
then all$some = true;
end;
end;
return all$some;
end need$tbl;
setup$hash:
procedure;
declare (i,j,printed,seg$no,seg0$no,h$bank,hohash) byte;
declare (size,h$attr,max$attr,max0$attr) address;
declare nohash boolean;
printed = false;
nohash = true;
do i = 0 to 15;
dph$adr = drvtbl(i) + .memory;
if drvtbl(i) <> 0 then
do;
if dph.hash < 0fffeh then
nohash = false;
if dph.hash = 0fffeh then
do;
if not printed then
do;
printed = true;
call print$console$buffer(.
(lf,cr,'Setting up directory hash tables:',
lf,cr,'$'));
end;
query = quest(27 + i);
dpb$adr = dph.dpb + .memory;
size = shl(dpb.drm+1,2);
call print$console$buffer(.
(' Enable hashing for drive $'));
call write$console('A'+i);
call print$console$buffer(.(': $'));
call get$response(.hash(i));
call crlf;
if not hash(i) then
do;
dph.hash = 0ffffh;
end;
else
if not bnk$swt then
do;
nohash = false;
hash$data(i) = size;
hash$space = hash$space + size;
end;
else
do;
if (seg$no := get$seg(2,size)) = 0ffh then
call error(false,0,.(
'Unable to allocate space for hash table.$'));
else
do;
dph.hbank = mem$tbl(seg$no).bank;
dph.hash = shl(double(mem$tbl(seg$no).base),8) +
(shl(double(mem$tbl(seg$no).len),8) -
mem$tbl(seg$no).attr);
mem$tbl(seg$no).attr = mem$tbl(seg$no).attr - size;
end;
end;
end;
end;
end;
if (not bnk$swt) and (nohash) then
do;
res$flg = 2;
scb$pg = scb$pg + 2;
res$pg = res$pg + 2;
end;
end setup$hash;
get$alloc$chk:
procedure;
declare (i,dbl$alloc) byte;
declare printed boolean;
do i = 0 to 15;
alloc(i) = 0;
chk(i) = 0;
end;
if not dbl$alv and not bnk$swt then
dbl$alloc = 1;
else
dbl$alloc = 2;
alloc$space = 0;
chk$space = 0;
printed = false;
do i = 0 to 15;
if drvtbl(i) <> 0 then
do;
dph$adr = drvtbl(i) + .memory;
dpb$adr = dph.dpb + .memory;
if dph.alv = 0fffeh then
do;
call print$console$buffer(.(cr,lf,
'Setting up Allocation vector for drive $'));
call write$console('A'+i);
call write$console(':');
printed = true;
alloc(i) = (dpb.dsm/8 + 1) * dbl$alloc;
alloc$space = alloc$space + alloc(i);
end;
if dph.csv = 0fffeh then
do;
call print$console$buffer(.(cr,lf,
'Setting up Checksum vector for drive $'));
call write$console('A'+i);
call write$console(':');
printed = true;
chk(i) = (dpb.drm + 4)/4;
chk$space = chk$space + chk(i);
dpb.cks = (dpb.cks and 8000h) or chk(i);
end;
end;
end;
if printed then
call crlf;
end get$alloc$chk;
setup$mem$seg$tbl:
procedure;
declare (i,j,ok,accept,mlow,mhigh,tlow,thigh) byte;
declare mem$temp address;
/* Create first memory segment table entry */
mem$tbl(0).base = bnk$pg;
mem$tbl(0).len = bnk$top - bnk$pg;
mem$tbl(0).attr = 0;
mem$tbl(0).bank = 0;
accept = false;
call print$console$buffer(
.(lf,cr,
'*** Bank 1 and Common are not included ***',
lf,cr,
'*** in the memory segment table. ***',
lf,cr,lf,cr,'$'));
query = quest(10);
call get$param (.('Number of memory segments $'),
.num$seg,10);
call print$console$buffer(.(cr,lf,
'CP/M 3 Base,size,bank ($'));
call dsply$hex(mem$tbl(0).base);
call write$console(',');
call dsply$hex(mem$tbl(0).len);
call write$console(',');
call dsply$hex(mem$tbl(0).bank);
call print$console$buffer(.(')',lf,cr,'$'));
do while not accept;
/* Bank switched memory segment table input */
call print$console$buffer (.(cr,lf,
'Enter memory segment table:',lf,cr,'$'));
do j = 1 to num$seg;
ok = false;
do while not ok;
query = quest(11 + j - 1);
call get$param (.(' Base,size,bank ','$'),
.mem$tbl(j),16);
mem$tbl(j).attr = shl(double(mem$tbl(j).len),8);
if mem$tbl(j).len = 0 then
do;
call error(false,0,.(
'Zero length segment not allowed.$'));
end;
else
if mem$tbl(j).bank = 1 then
do;
call error(false,0,.(
'Bank one not allowed.$'));
end;
else
do;
tlow = mem$tbl(j).base;
mem$temp = double(tlow) + double(mem$tbl(j).len);
if (high(mem$temp) <> 0) or (low(mem$temp) > bnk$top) then
do;
call print$console$buffer(.(cr,lf,'ERROR: ',
'Memory conflict - segment trimmed.',
cr,lf,'$'));
mem$tbl(j).len = bnk$top - tlow;
mem$tbl(j).attr = shl(double(bnk$top - tlow),8);
end;
else
do;
thigh = low(mem$temp);
i = 0;
ok = true;
do while ((i < j) and ok);
mlow = mem$tbl(i).base;
mhigh = mlow + mem$tbl(i).len;
if mem$tbl(i).bank = mem$tbl(j).bank then
do;
if (mhigh >= thigh) and (tlow >= mlow) then
do;
call error(false,0,.(
'Memory conflict - cannot trim segment.$'));
ok = false;
end;
else
if ((thigh > mhigh) and (mhigh > tlow)) then
do;
call print$console$buffer(.(cr,lf,'ERROR: ',
'Memory conflict - segment trimmed.',
cr,lf,'$'));
mem$tbl(j).base = mhigh;
ok = false;
end;
else
if ((thigh > mlow) and (mlow > tlow)) then
do;
call print$console$buffer(.(cr,lf,'ERROR: ',
'Memory conflict - segment trimmed.',
cr,lf,'$'));
mem$tbl(j).len = mlow - tlow;
mem$tbl(j).attr = shl(double(mlow-tlow),8);
ok = false;
end;
end;
i = i + 1;
end;
end;
end;
end;
end;
call crlf;
do j = 0 to num$seg;
if j = 0 then
call print$console$buffer (.(' CP/M 3 Sys ','$'));
else
do;
call print$console$buffer (.(' Memseg No. ','$'));
call dsply$hex(j-1);
end;
call dsply$hex$high$adr (mem$tbl(j).base);
call dsply$hex$high$adr (mem$tbl(j).len);
if bnk$swt then
do;
call print$console$buffer (.(' Bank ','$'));
call dsply$hex (mem$tbl(j).bank);
end;
call crlf;
end;
query = false;
accept = true;
call print$console$buffer (.(cr,lf,
'Accept new memory segment table entries ','$'));
call get$response (.accept);
end; /* do while not accept */
call crlf;
end setup$mem$seg$tbl;
get$default$file:
procedure;
declare ret byte;
call print$console$buffer(.(
'Default entries are shown in (parens).',cr,lf,
'Default base is Hex, precede entry with # for decimal',
cr,lf,'$'));
if (ret:=open$file(.data$fcb)) <> 255 then
do;
call movef(8,.data$fcb+1,.fcb$msg);
call movef(3,.data$fcb+9,.fcb$msg+9);
call print$console$buffer(.(
cr,lf,'Use GENCPM.DAT for defaults $'));
ret = 0ffh;
call get$response(.ret);
call crlf;
if ret then
call getdef;
call close$file(.data$fcb);
end;
else
do;
display = true;
automatic = false;
end;
end get$default$file;
setup$system$dat:
procedure;
declare (i,j,ok,temp) byte;
ok = false;
call get$default$file;
do while not ok;
query = quest(155);
call crlf;
call print$console$buffer(.('Create a new GENCPM.DAT file $'));
call get$response(.crdatf);
query = quest(0);
call crlf;
call crlf;
call print$console$buffer(.('Display Load Map at Cold Boot $'));
call get$response(.prt$msg);
call crlf;
call crlf;
query = quest(1);
con$wid = con$wid + 1;
call get$param (.('Number of console columns $'),
.con$wid,10);
con$wid = con$wid - 1;
query = quest(2);
con$pag = con$pag + 1;
call get$param (.('Number of lines in console page $'),
.con$pag,10);
con$pag = con$pag - 1;
query = quest(3);
call print$console$buffer(.
('Backspace echoes erased character $'));
call get$response (.bck$spc);
call crlf;
query = quest(4);
call print$console$buffer(.
('Rubout echoes erased character $'));
call get$response (.rubout);
call crlf;
call crlf;
query = quest(5);
err1:
call print$console$buffer(.('Initial default drive ($'));
call write$console('A'+bdrive);
call print$console$buffer(.(':) ? $'));
call read$console$buffer(.lnbfr);
if lnbfr(1) <> 0 then
do;
temp = upper(lnbfr(2))-'A';
if not valid$drive(temp) then
goto err1;
bdrive = temp;
end;
call crlf;
call crlf;
query = quest(6);
call get$param (.('Top page of memory $'),
.mem$top,16);
os$top = shl(double(mem$top),8) + 100h;
query = quest(7);
call print$console$buffer(.('Bank switched memory $'));
call get$response (.bnk$swt);
call crlf;
non$bnk = not bnk$swt;
if bnk$swt then
do;
query = quest(8);
call get$param (.('Common memory base page $'),
.bnk$top,16);
call crlf;
query = quest(9);
call print$console$buffer(.('Long error messages $'));
call get$response(.lerror);
call crlf;
end;
else
do;
query = quest(156);
call crlf;
call print$console$buffer(.('Double allocation vectors $'));
call get$response(.dbl$alv);
call crlf;
bnk$top = 0;
end;
query = false;
ok = true;
call crlf;
call print$console$buffer(.('Accept new system definition $'));
call get$response(.ok);
call crlf;
end;
save$mem$top = mem$top;
mem$top = mem$top + 1;
rubout = not rubout;
end setup$system$dat;
setup$CPM80$sys:
procedure;
declare i byte;
call print$console$buffer (.( cr,lf,lf,
'CP/M 3.0 System Generation',cr,lf,
'Copyright (C) 1982, Digital Research',
cr,lf,cr,lf,'$'));
call delete$file (.fcbout);
call create$file (.fcbout);
FCBout(32) = 0;
do i = 0 to 127;
system$data(i) = 0;
end;
do i = 128 to 255;
system$data(i) = '$';
end;
prt$msg$ptr = 128;
call movef(3,.(cr,lf,' '),.system$data(prt$msg$ptr));
prt$msg$ptr = 131;
call movef(8,.FCBout+1,.fcb$msg);
call movef(3,.FCBout+9,.fcb$msg+9);
call set$DMA$address (.sctbfr);
call write$record (.FCBout);
call write$record (.FCBout);
end setup$CPM80$sys;
initialization:
procedure;
declare i byte;
nmb$sect = shr ((maxb-.sctbfr+1),7);
do i = 0 to 15;
hash$data(i) = 0;
end;
hash$space = 0;
if fcb(1) = 'A' then
do;
automatic = true;
display = false;
do i = 0 to 154;
quest(i) = false;
end;
end;
else
do;
automatic = false;
display = true;
end;
if fcb16(1) = 'D' then
do;
display = true;
end;
query = false;
end initialization;
/*
G E N C P M M a i n P r o g r a m
*/
res$flg = 0;
display = true;
call setup$CPM80$sys;
call initialization;
call setup$system$dat;
call get$file$info;
if bios$atts(2) <> 0
then res$bios$len = high(bios$atts(2) + 255);
else res$bios$len = high(bios$atts(0) + 255);
bios$pg = mem$top - res$bios$len;
bnk$off = bnk$top - (high(bios$atts(0) + 255) - res$bios$len);
bnk$pg = bnk$off - high(bnk$atts(0) + 255);
call load(.bios$fcb,.bios$atts);
call page$chop;
if not bnk$swt then
do;
scb$pg = bios$pg - (3 - res$flg);
res$pg = bios$pg - high(res$atts(0) + 255) + res$flg;
end;
else
do;
scb$pg = bios$pg - 1;
res$pg = bios$pg - high(res$atts(0) + 255);
end;
if need$tbl then
do;
call get$alloc$chk;
if bnk$swt then
do;
bnk$off = bnk$top - (high(bios$atts(0) + alloc$space +
chk$space + 255) - res$bios$len);
bnk$pg = bnk$off - high(bnk$atts(0) + 255);
xmove$implemented = get$xmove;
call setup$mem$seg$tbl;
if (not xmove$implemented) then
do len = 0 to 15;
record(len).altbnks = false;
end;
end;
else
xmove$implemented = false;
if not dont$hash then
call setup$hash;
call setbuf;
end;
res$len = res$bios$len;
offset = bios$pg;
call reloc$module(.bios$fcb);
if bnk$swt
then call display$layout(.('BNKBIOS3 SPR$'),
double(bios$pg)*256,res$bios$len);
else call display$layout(.('BIOS3 SPR$'),
double(bios$pg)*256,res$bios$len);
if not bnk$swt then
do;
len = res$bios$len;
off = 2;
call wrtbuf(len,.off);
common$len = len;
banked$len = 0;
end;
else
do;
len = high(bios$atts(0) + 255) - res$bios$len;
off = (high(res$atts(0) + 255) + res$bios$len) * 2 + 2;
call display$layout(.('BNKBIOS3 SPR$'),double(bnk$off)*256,len);
call wrtbuf(len,.off);
banked$len = len;
len = res$bios$len;
off = 2;
dma = dma - 80h;
call wrtbuf(len,.off);
common$len = len;
end;
res$len = high(res$atts(0) + 255) - res$flg;
offset = res$pg;
call load(.res$fcb,.res$atts);
call reloc$module(.res$fcb);
call setup$scb;
dma = dma - (res$flg * 256);
len = high(res$atts(0) + 255) - res$flg;
if not bnk$swt
then call display$layout(.('BDOS3 SPR$'),double(res$pg)*256,len);
else call display$layout(.('RESBDOS3 SPR$'),double(res$pg)*256,len);
call wrtbuf(len,.off);
common$len = common$len + len;
if bnk$swt then
do;
res$len = 0ffh;
offset = bnk$pg;
call load(.bnk$fcb,.bnk$atts);
call reloc$module(.bnk$fcb);
len = high(bnk$atts(0) + 255);
off = off + (high(bios$atts(0) + 255) - res$bios$len) * 2;
call display$layout(.('BNKBDOS3 SPR$'),double(bnk$pg)*256,len);
call wrtbuf(len,.off);
banked$len = banked$len + len;
end;
if not prt$msg then prt$msg$ptr = prt$msg$ptr - 3;
call movef(12,.(lf,cr,' 64K TPA',lf,cr),.system$data(prt$msg$ptr));
res$pg = shr(res$pg,2);
system$data(prt$msg$ptr+3) = res$pg/10 + '0';
system$data(prt$msg$ptr+4) = res$pg mod 10 + '0';
prt$msg$ptr = prt$msg$ptr + 12;
sys$entry = bios$pg * 256;
call movef(36,.('Copyright (C) 1982, Digital Research'),.system$data(10h));
call movef(6,.memory,.system$data(35h)); /* Copy Serial No. into header */
FCBout(33) = 0; FCBout(34) = 0; FCBout(35) = 0;
system$data(0) = mem$top;
system$data(2) = bnk$top;
call movef(8,.FCBout+1,.fcb$msg);
call movef(3,.FCBout+9,.fcb$msg+9);
call set$DMA$address(.system$data);
call write$random$record(.FCBout);
FCBout(33) = 1;
call set$DMA$address(.system$data(128));
call write$random$record(.FCBout);
call close$file(.fcbout);
if crdatf then
do; /* create a new data file for GENCPM */
crdatf = false;
mem$top = save$mem$top;
rubout = not rubout;
call movef(8,.data$fcb+1,.fcb$msg);
call movef(3,.data$fcb+9,.fcb$msg+9);
call crtdef;
end;
display = true;
call print$console$buffer (.(cr,lf,lf,
'*** CP/M 3.0 SYSTEM GENERATION DONE ***','$'));
return;
end plm;
end gencpm;