realized the emulators were not mine, cant be in the repo

This commit is contained in:
Amber
2020-05-15 13:29:24 -04:00
parent e3235e2d02
commit 4643969cce
140 changed files with 0 additions and 42853 deletions

View File

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
The two files in this ZIP file are disassembled CP/M 2.2.
CPM22.ASM : CP/M 2.2 in 8080 mnemonics
CPM22.Z80 : CP/M 2.2 in Z80 mnemonics
Both files claim to implement a fix that affects operation in a sector
deblocking environment. The Z80 version does not look to have been optimized
for the Z80, it just uses Z80 mnemonics.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +0,0 @@
The following list of corrections should be made to the Personal CP/M 8-bit
version 1.0 documentation.
Programmer's Guide
page 2-10
BDOS function 2
text says 'CONSOLE INPUT'
should be 'CONSOLE OUTPUT'
page 2-45
BDOS function 33
'Entry Parameters' add after Register C line:
'Register DE: FCB Address'
page 2-49
BDOS function 35
replace information about values returned in registers with:
'Random record field of FCB set'
System Guide
Section 2
References to the BDOS size being 1100h bytes are incorrect.
The BDOS code segment is 1000h bytes, and the BDOS data
segment is 00BFh bytes. With the standard distibution,
BDOSH.REL and BDOSL.REL will link these in a separate area
from the BDOS code segment. OEMs that purchase the source
can set an assembly-time switch that will make the data areas
part of the code segment so that it will all be linked as one
segment of 1100h bytes if the BDOS will execute in RAM.
page 4-15
BIOS function WRITE
Entry Parameters: Register C = 0: normal sector write
1: write to directory sector
2: write to the first sector
of a new data block


View File

@@ -1,15 +0,0 @@
Please note: line 2528 in BDOS.MAC is corrupted. It should read
jp z,COPY$DIRLOC ;stop at end of dir
--------------------------
This zip file contains the original source for Personal CP/M 1.0.
If anybody figures out anything about this code, please drop an
email message to me at :
gaby@gaby.de
and I'll pass it on.
tnx

View File

@@ -1,834 +0,0 @@
stat:
do;
declare
cpmversion literally '20h'; /* requires 2.0 cp/m */
/* c p / m s t a t u s c o m m a n d (s t a t) */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/* status status status status status status */
/*
copyright(c) 1975, 1976, 1977, 1978, 1979, 1984
digital research
box 579
pacific grove, ca
93950
*/
/* modified 10/30/78 to fix the space computation */
/* modified 01/28/79 to remove despool dependencies */
/* modified 07/26/79 to operate under cp/m 2.0 */
/* modified 03/14/84 to remove iobyte modification for Personal CP/M */
declare jump byte data(0c3h),
jadr address data (.status);
/* jump to status */
/* function call 32 returns the address of the disk parameter
block for the currently selected disk, which consists of:
scptrk (2 by) number of sectors per track
blkshf (1 by) log2 of blocksize (2**blkshf=blksize)
blkmsk (1 by) 2**blkshf-1
extmsk (1 by) logical/physical extents
maxall (2 by) max alloc number
dirmax (2 by) size of directory-1
dirblk (2 by) reservation bits for directory
chksiz (2 by) size of checksum vector
offset (2 by) offset for operating system
*/
declare
/* fixed locations for cp/m */
bdosa literally '0006h', /* bdos base */
buffa literally '0080h', /* default buffer */
fcba literally '005ch', /* default file control block */
dolla literally '006dh', /* dollar sign position */
parma literally '006eh', /* parameter, if sent */
rreca literally '007dh', /* random record 7d,7e,7f */
rreco literally '007fh', /* high byte of random overflow */
sectorlen literally '128', /* sector length */
memsize address at(bdosa), /* end of memory */
rrec address at(rreca), /* random record address */
rovf byte at(rreco), /* overflow on getfile */
doll byte at(dolla), /* dollar parameter */
parm byte at(parma), /* parameter */
sizeset byte, /* true if displaying size field */
dpba address, /* disk parameter block address */
dpb based dpba structure
(spt address, bls byte, bms byte, exm byte, mxa address,
dmx address, dbl address, cks address, ofs address),
scptrk literally 'dpb.spt',
blkshf literally 'dpb.bls',
blkmsk literally 'dpb.bms',
extmsk literally 'dpb.exm',
maxall literally 'dpb.mxa',
dirmax literally 'dpb.dmx',
dirblk literally 'dpb.dbl',
chksiz literally 'dpb.cks',
offset literally 'dpb.ofs';
boot: procedure external;
/* reboot */
end boot;
mon1: procedure(f,a) external;
declare f byte, a address;
end mon1;
mon2: procedure(f,a) byte external;
declare f byte, a address;
end mon2;
mon3: procedure(f,a) address external;
declare f byte, a address;
end mon3;
status: procedure;
declare copyright(*) byte data (
' Copyright (c) 1984, Digital Research');
/* dummy outer procedure 'status' will start at 100h */
/* determine status of currently selected disk */
declare alloca address,
/* alloca is the address of the disk allocation vector */
alloc based alloca (1024) byte; /* allocation vector */
declare
true literally '1',
false literally '0',
forever literally 'while true',
cr literally '13',
lf literally '10';
printchar: procedure(char);
declare char byte;
call mon1(2,char);
end printchar;
crlf: procedure;
call printchar(cr);
call printchar(lf);
end crlf;
printb: procedure;
/* print blank character */
call printchar(' ');
end printb;
printx: procedure(a);
declare a address;
declare s based a byte;
do while s <> 0;
call printchar(s);
a = a + 1;
end;
end printx;
print: procedure(a);
declare a address;
/* print the string starting at address a until the
next 0 is encountered */
call crlf;
call printx(a);
end print;
break: procedure byte;
return mon2(11,0); /* console ready */
end break;
declare dcnt byte;
version: procedure byte;
/* returns current cp/m version # */
return mon2(12,0);
end version;
select: procedure(d);
declare d byte;
call mon1(14,d);
end select;
open: procedure(fcb);
declare fcb address;
dcnt = mon2(15,fcb);
end open;
search: procedure(fcb);
declare fcb address;
dcnt = mon2(17,fcb);
end search;
searchn: procedure;
dcnt = mon2(18,0);
end searchn;
cselect: procedure byte;
/* return current disk number */
return mon2(25,0);
end cselect;
setdma: procedure(dma);
declare dma address;
call mon1(26,dma);
end setdma;
getalloca: procedure address;
/* get base address of alloc vector */
return mon3(27,0);
end getalloca;
getlogin: procedure address;
/* get the login vector */
return mon3(24,0);
end getlogin;
writeprot: procedure;
/* write protect the current disk */
call mon1(28,0);
end writeprot;
getrodisk: procedure address;
/* get the read-only disk vector */
return mon3(29,0);
end getrodisk;
setind: procedure;
/* set file indicators for current fcb */
call mon1(30,fcba);
end setind;
set$dpb: procedure;
/* set disk parameter block values */
dpba = mon3(31,0); /* base of dpb */
end set$dpb;
getuser: procedure byte;
/* return current user number */
return mon2(32,0ffh);
end getuser;
setuser: procedure(user);
declare user byte;
call mon1(32,user);
end setuser;
getfilesize: procedure(fcb);
declare fcb address;
call mon1(35,fcb);
end getfilesize;
declare oldsp address, /* sp on entry */
stack(16) address; /* this program's stack */
declare
fcbmax literally '512', /* max fcb count */
fcbs literally 'memory',/* remainder of memory */
fcb(33) byte at (fcba), /* default file control block */
buff(128) byte at (buffa); /* default buffer */
declare bpb address; /* bytes per block */
set$bpb: procedure;
call set$dpb; /* disk parameters set */
bpb = shl(double(1),blkshf) * sectorlen;
end set$bpb;
select$disk: procedure(d);
declare d byte;
/* select disk and set bpb */
call select(d);
call set$bpb; /* bytes per block */
end select$disk;
getalloc: procedure(i) byte;
/* return the ith bit of the alloc vector */
declare i address;
return
rol(alloc(shr(i,3)), (i and 111b) + 1);
end getalloc;
declare
accum(4) byte, /* accumulator */
ibp byte; /* input buffer pointer */
compare: procedure(a) byte;
/* compare accumulator with four bytes addressed by a */
declare a address;
declare (s based a) (4) byte;
declare i byte;
do i = 0 to 3;
if s(i) <> accum(i) then return false;
end;
return true;
end compare;
scan: procedure;
/* fill accum with next input value */
declare (i,b) byte;
setacc: procedure(b);
declare b byte;
accum(i) = b; i = i + 1;
end setacc;
/* deblank input */
do while buff(ibp) = ' '; ibp=ibp+1;
end;
/* initialize accum length */
i = 0;
do while i < 4;
if (b := buff(ibp)) > 1 then /* valid */
call setacc(b); else /* blank fill */
call setacc(' ');
if b <= 1 or b = ',' or b = ':' or
b = '*' or b = '.' or b = '>' or
b = '<' or b = '=' then buff(ibp) = 1;
else
ibp = ibp + 1;
end;
ibp = ibp + 1;
end scan;
pdecimal: procedure(v,prec);
/* print value v with precision prec (10,100,1000)
with leading zero suppression */
declare
v address, /* value to print */
prec address, /* precision */
zerosup byte, /* zero suppression flag */
d byte; /* current decimal digit */
zerosup = true;
do while prec <> 0;
d = v / prec ; /* get next digit */
v = v mod prec;/* get remainder back to v */
prec = prec / 10; /* ready for next digit */
if prec <> 0 and zerosup and d = 0 then call printb; else
do; zerosup = false; call printchar('0'+d);
end;
end;
end pdecimal;
add$block: procedure(ak,ab);
declare (ak, ab) address;
/* add one block to the kilobyte accumulator */
declare kaccum based ak address; /* kilobyte accum */
declare baccum based ab address; /* byte accum */
baccum = baccum + bpb;
do while baccum >= 1024;
baccum = baccum - 1024;
kaccum = kaccum + 1;
end;
end add$block;
count: procedure(mode) address;
declare mode byte; /* true if counting 0's */
/* count kb remaining, kaccum set upon exit */
declare
ka address, /* kb accumulator */
ba address, /* byte accumulator */
i address, /* local index */
bit byte; /* always 1 if mode = false */
ka, ba = 0;
bit = 0;
do i = 0 to maxall;
if mode then bit = getalloc(i);
if not bit then call add$block(.ka,.ba);
end;
return ka;
end count;
abortmsg: procedure;
call print(.('** Aborted **',0));
end abortmsg;
userstatus: procedure;
/* display active user numbers */
declare i byte;
declare user(32) byte;
declare ufcb(*) byte data ('????????????',0,0,0);
call print(.('Active User :',0));
call pdecimal(getuser,10);
call print(.('Active Files:',0));
do i = 0 to last(user);
user(i) = false;
end;
call setdma(.fcbs);
call search(.ufcb);
do while dcnt <> 255;
if (i := fcbs(shl(dcnt and 11b,5))) <> 0e5h then
user(i and 1fh) = true;
call searchn;
end;
do i = 0 to last(user);
if user(i) then call pdecimal(i,10);
end;
end userstatus;
drivestatus: procedure;
declare
rpb address,
rpd address;
pv: procedure(v);
declare v address;
call crlf;
call pdecimal(v,10000);
call printchar(':');
call printb;
end pv;
/* print the characteristics of the currently selected drive */
call print(.(' ',0));
call printchar(cselect+'A');
call printchar(':');
call printx(.(' Drive Characteristics',0));
rpb = shl(double(1),blkshf); /* records/block=2**blkshf */
if (rpd := (maxall+1) * rpb) = 0 and (rpb <> 0) then
call print(.('65536: ',0)); else
call pv(rpd);
call printx(.('128 Byte Record Capacity',0));
call pv(count(false));
call printx(.('Kilobyte Drive Capacity',0));
call pv(dirmax+1);
call printx(.('32 Byte Directory Entries',0));
call pv(shl(chksiz,2));
call printx(.('Checked Directory Entries',0));
call pv((extmsk+1) * 128);
call printx(.('Records/ Extent',0));
call pv(rpb);
call printx(.('Records/ Block',0));
call pv(scptrk);
call printx(.('Sectors/ Track',0));
call pv(offset);
call printx(.('Reserved Tracks',0));
call crlf;
end drivestatus;
diskstatus: procedure;
/* display disk status */
declare login address, d byte;
login = getlogin; /* login vector set */
d = 0;
do while login <> 0;
if low(login) then
do; call select$disk(d);
call drivestatus;
end;
login = shr(login,1);
d = d + 1;
end;
end diskstatus;
match: procedure(va,vl) byte;
/* return index+1 to vector at va if match */
declare va address,
v based va (16) byte,
vl byte;
declare (i,j,match,sync) byte;
j,sync = 0;
do sync = 1 to vl;
match = true;
do i = 0 to 3;
if v(j) <> accum(i) then match=false;
j = j + 1;
end;
if match then return sync;
end;
return 0; /* no match */
end match;
declare devl(*) byte data
('VAL:USR:DSK:');
devreq: procedure byte;
/* process device request, return true if found */
declare
(i,j,items) byte;
items = 0;
do forever;
call scan;
if (i:=match(.devl,8)) = 0 then return items<>0;
items = items+1; /* found first/next item */
if i = 1 then /* list possible assignment */
do;
call print(.('Temp R/O Disk: d:=R/O',0));
call print(.('Set Indicator: d:filename.typ ',
'$R/O $R/W $SYS $DIR',0));
call print(.('Disk Status : DSK: d:DSK:',0));
call print(.('User Status : USR:',0));
end; else
if i = 2 then /* list user status values */
call userstatus;
else
if i = 3 then /* show the disk device status */
call diskstatus;
/* end of current item, look for more */
call scan;
if accum(0) = ' ' then return true;
if accum(0) <> ',' then
do; call print(.('Bad Delimiter',0));
return true;
end;
end; /* of do forever */
end devreq;
pvalue: procedure(v);
declare (d,zero) byte,
(k,v) address;
k = 10000;
zero = false;
do while k <> 0;
d = low(v/k); v = v mod k;
k = k / 10;
if zero or k = 0 or d <> 0 then
do; zero = true; call printchar('0'+d);
end;
end;
call printchar('k');
call crlf;
end pvalue;
comp$alloc: procedure;
alloca = getalloca;
call printchar(cselect+'A');
call printx(.(': ',0));
end comp$alloc;
prcount: procedure;
/* print the actual byte count */
call pvalue(count(true));
end prcount;
pralloc: procedure;
/* print allocation for current disk */
call print (.('Bytes Remaining On ',0));
call comp$alloc;
call prcount;
end pralloc;
prstatus: procedure;
/* print the status of the disk system */
declare (login, rodisk) address;
declare d byte;
login = getlogin; /* login vector set */
rodisk = getrodisk; /* read only disk vector set */
d = 0;
do while login <> 0;
if low(login) then
do; call select$disk(d);
call comp$alloc;
call printx(.('R/',0));
if low(rodisk) then
call printchar('O'); else
call printchar('W');
call printx(.(', Space: ',0));
call prcount;
end;
login = shr(login,1); rodisk = shr(rodisk,1);
d = d + 1;
end;
call crlf;
end prstatus;
setdisk: procedure;
if fcb(0) <> 0 then call select$disk(fcb(0)-1);
end setdisk;
getfile: procedure;
/* process file request */
declare
fnam literally '11', fext literally '12',
fmod literally '14',
frc literally '15', fln literally '15',
fdm literally '16', fdl literally '31',
ftyp literally '9',
rofile literally '9', /* read/only file */
infile literally '10'; /* invisible file */
declare
fcbn address, /* number of fcb's collected so far */
finx(fcbmax) address, /* index vector used during sort */
fcbe(fcbmax) address, /* extent counts */
fcbb(fcbmax) address, /* byte count (mod kb) */
fcbk(fcbmax) address, /* kilobyte count */
fcbr(fcbmax) address, /* record count */
bfcba address, /* index into directory buffer */
fcbsa address, /* index into fcbs */
bfcb based bfcba (32) byte, /* template over directory */
fcbv based fcbsa (16) byte; /* template over fcbs entry */
declare
i address, /* fcb counter during collection and display */
l address, /* used during sort and display */
k address, /* " */
m address, /* " */
kb byte, /* byte counter */
lb byte, /* byte counter */
mb byte, /* byte counter */
(b,f) byte, /* counters */
matched byte; /* used during fcbs search */
multi16: procedure;
/* utility to compute fcbs address from i */
fcbsa = shl(i,4) + .fcbs;
end multi16;
declare
scase byte; /* status case # */
declare
fstatlist(*) byte data('R/O',0,'R/W',0,'SYS',0,'DIR',0);
setfilestatus: procedure byte;
/* eventually, scase set r/o=0,r/w=1,dat=2,sys=3 */
declare
fstat(*) byte data('R/O R/W SYS DIR ');
if doll = ' ' then return false;
call move(4,.parm,.accum); /* $???? */
if accum(0) = 'S' and accum(1) = ' ' then
return not (sizeset := true);
/* must be a parameter */
if (scase := match(.fstat,4)) = 0 then
call print(.('Invalid File Indicator',0));
return true;
end setfilestatus;
printfn: procedure;
declare (k, lb) byte;
/* print file name */
do k = 1 to fnam;
if (lb := fcbv(k) and 7fh) <> ' ' then
do; if k = ftyp then call printchar('.');
call printchar(lb);
end;
end;
end printfn;
call set$bpb; /* in case default disk */
call setdisk;
sizeset = false;
scase = 255;
if setfilestatus then
do; if scase = 0 then return;
scase = scase - 1;
end; else
if fcb(1) = ' ' then /* no file named */
do; call pralloc;
return;
end;
/* read the directory, collect all common file names */
fcbn,fcb(0) = 0;
fcb(fext),fcb(fmod) = '?'; /* question mark matches all */
call search(fcba); /* fill directory buffer */
collect: /* label for debug */
do while dcnt <> 255;
/* another item found, compare it for common entry */
bfcba = shl(dcnt and 11b,5)+buffa; /* dcnt mod 4 * 32 */
matched = false; i = 0;
do while not matched and i < fcbn;
/* compare current entry */
call multi16;
do kb = 1 to fnam;
if bfcb(kb) <> fcbv(kb) then kb = fnam; else
/* complete match if at end */
matched = kb = fnam;
end;
i = i + 1;
end;
checkmatched: /* label for debug */
if matched then i = i - 1; else
do; /* copy to new position in fcbs */
fcbn = (i := fcbn) + 1;
call multi16;
/* fcbsa set to next to fill */
if (fcbn > fcbmax) or (fcbsa + 16) >= memsize then
do; call print(.('** Too Many Files **',0));
i = 0; fcbn = 1;
call multi16;
end;
/* save index to element for later sort */
finx(i) = i;
do kb = 0 to fnam;
fcbv(kb) = bfcb(kb);
end;
fcbe(i),fcbb(i),fcbk(i),fcbr(i) = 0;
end;
/* entry is at, or was placed at location i in fcbs */
fcbe(i) = fcbe(i) + 1; /* extent incremented */
/* record count */
fcbr(i) = fcbr(i) + bfcb(frc)
+ (bfcb(fext) and extmsk) * 128;
/* count kilobytes */
countbytes: /* label for debug */
lb = 1;
if maxall > 255 then lb = 2; /* double precision inx */
do kb = fdm to fdl by lb;
mb = bfcb(kb);
if lb = 2 then /* double precision inx */
mb = mb or bfcb(kb+1);
if mb <> 0 then /* allocated */
call add$block(.fcbk(i),.fcbb(i));
end;
call searchn; /* to next entry in directory */
end; /* of do while dcnt <> 255 */
display: /* label for debug */
/* now display the collected data */
if fcbn = 0 then call print(.('File Not Found',0)); else
if scase = 255 then /* display collected data */
do;
/* sort the file names in ascending order */
if fcbn > 1 then /* requires at least two to sort */
do; l = 1;
do while l > 0; /* bubble sort */
l = 0;
do m = 0 to fcbn - 2;
i = finx(m+1); call multi16; bfcba = fcbsa; i = finx(m);
call multi16; /* sets fcbsa, basing fcbv */
do kb = 1 to fnam; /* compare for less or equal */
if (b:=bfcb(kb)) < (f:=fcbv(kb)) then /* switch */
do; k = finx(m); finx(m) = finx(m + 1);
finx(m + 1) = k; l = l + 1; kb = fnam;
end;
else if b > f then kb = fnam; /* stop compare */
end;
end;
end;
end;
if sizeset then
call print(.(' Size ',0)); else
call crlf;
call printx(.(' Recs Bytes Ext Acc',0));
l = 0;
do while l < fcbn;
i = finx(l); /* i is the index to next in order */
call multi16; call crlf;
/* print the file length */
call move(16,.fcbv(0),fcba);
fcb(0) = 0;
if sizeset then
do; call getfilesize(fcba);
if rovf <> 0 then call printx(.('65536',0)); else
call pdecimal(rrec,10000);
call printb;
end;
call pdecimal(fcbr(i),10000); /* rrrrr */
call printb; /* blank */
call pdecimal(fcbk(i),10000); /* bbbbbk */
call printchar('k'); call printb;
call pdecimal(fcbe(i),1000); /* eeee */
call printb;
call printchar('R');
call printchar('/');
if rol(fcbv(rofile),1) then
call printchar('O'); else
call printchar('W');
call printb;
call printchar('A'+cselect); call printchar(':');
/* print filename.typ */
if (mb:=rol(fcbv(infile),1)) then call printchar('(');
call printfn;
if mb then call printchar(')');
l = l + 1;
end;
call pralloc;
end; else
setfileatt: /* label for debug */
/* set file attributes */
do;
l = 0;
do while l < fcbn;
if break then
do; call abortmsg; return;
end;
i = l;
call multi16;
call crlf;
call printfn;
do case scase;
/* set to r/o */
fcbv(rofile) = fcbv(rofile) or 80h;
/* set to r/w */
fcbv(rofile) = fcbv(rofile) and 7fh;
/* set to sys */
fcbv(infile) = fcbv(infile) or 80h;
/* set to dir */
fcbv(infile) = fcbv(infile) and 7fh;
end;
/* place name into default fcb location */
call move(16,fcbsa,fcba);
fcb(0) = 0; /* in case matched user# > 0 */
call setind; /* indicators set */
call printx(.(' set to ',0));
call printx(.fstatlist(shl(scase,2)));
l = l + 1;
end;
end;
end getfile;
setdrivestatus: procedure;
/* handle possible drive status assignment */
call scan; /* remove drive name */
call scan; /* check for = */
if accum(0) = '=' then
do; call scan; /* get assignment */
if compare(.('R/O ')) then
do; call setdisk; /* a: ... */
call writeprot;
end; else
call print(.('Invalid Disk Assignment',0));
end;
else /* not a disk assignment */
do; call setdisk;
if match(.devl,8) = 3 then call drive$status; else
call getfile;
end;
end setdrivestatus;
/* save stack pointer and reset */
oldsp = stackptr;
stackptr = .stack(length(stack));
/* process request */
if version < cpmversion then
call print(.('Wrong CP/M Version (Requires 2.0 or greater)',0));
else
do;
/* size display if $S set in command */
ibp = 1; /* initialize buffer pointer */
if fcb(0) = 0 and fcb(1) = ' ' then /* stat only */
call prstatus; else
do;
if fcb(0) <> 0 then
call setdrivestatus; else
do;
if not devreq then /* must be file name */
call getfile;
end;
end;
end;
/* restore old stack before exit */
stackptr = oldsp;
end status;
end;


View File

@@ -1,10 +0,0 @@
asm xsub0
rmac xsub1
link xsub1[os]
xsub
ddt xsub1.spr
ixsub0.hex
r
g0
save 4 xsubnew.com


View File

@@ -1,135 +0,0 @@
; xsub relocator version 2.2
version equ 20h
; xsub relocator program, included with the module
; to perform the move from 200h to the destination address
;
; copyright (c) 1979, 1980
; digital research
; box 579
; pacific grove, ca.
; 93950
;
org 100h
db (lxi or (b shl 3)) ;lxi b,module size
org $+2 ;skip address field
jmp start
db ' Extended Submit Vers '
db version/16+'0','.',version mod 16+'0'
nogo: db 'Xsub Already Present$'
badver: db 'Requires CP/M Version 2.0 or later$'
;
bdos equ 0005h ;bdos entry point
print equ 9 ;bdos print function
vers equ 12 ;get version number
ccplen equ 0800h ;size of ccp
module equ 200h ;module address
;
start:
; ccp's stack used throughout
push b ;save the module's length
lda bdos+1 ;xsub already present?
cpi 06h ;low address must be 06h
jnz loaderr
lhld bdos+1
inx h
inx h
inx h
lxi d,xsubcon
mvi c,4
present:
ldax d
cmp m
jnz continue
inx h
inx d
dcr c
jz loaderr
jmp present
;
loaderr:
; bdos or xsub not lowest module in memory, return to ccp
mvi c,print
lxi d,nogo ;already present message
call bdos ;to print the message
pop b ;recall length
ret ;to the ccp
;
continue:
mvi c,vers
call bdos ;version number?
cpi version ;2.0 or greater
jnc versok
;
; wrong version
mvi c,print
lxi d,badver
call bdos
pop b
ret ;to ccp
;
versok:
lxi h,bdos+2;address field of jump to bdos (top memory)
mov a,m ;a has high order address of memory top
dcr a ;page directly below bdos
sui (ccplen shr 8) ;-ccp pages
pop b ;recall length of module
push b ;and save it again
sub b ;a has high order address of reloc area
mov d,a
mvi e,0 ;d,e addresses base of reloc area
push d ;save for relocation below
;
lxi h,module;ready for the move
move: mov a,b ;bc=0?
ora c
jz reloc
dcx b ;count module size down to zero
mov a,m ;get next absolute location
stax d ;place it into the reloc area
inx d
inx h
jmp move
;
reloc: ;storage moved, ready for relocation
; hl addresses beginning of the bit map for relocation
pop d ;recall base of relocation area
pop b ;recall module length
push h ;save bit map base in stack
mov h,d ;relocation bias is in d
;
rel0: mov a,b ;bc=0?
ora c
jz endrel
;
; not end of the relocation, may be into next byte of bit map
dcx b ;count length down
mov a,e
ani 111b ;0 causes fetch of next byte
jnz rel1
; fetch bit map from stacked address
xthl
mov a,m ;next 8 bits of map
inx h
xthl ;base address goes back to stack
mov l,a ;l holds the map as we process 8 locations
rel1: mov a,l
ral ;cy set to 1 if relocation necessary
mov l,a ;back to l for next time around
jnc rel2 ;skip relocation if cy=0
;
; current address requires relocation
ldax d
add h ;apply bias in h
stax d
rel2: inx d ;to next address
jmp rel0 ;for another byte to relocate
;
endrel: ;end of relocation
pop d ;clear stacked address
; h has the high order 8-bits of relocated module address
mvi l,0
pchl ;go to relocated program
xsubcon:
db 'xsub'
end


View File

@@ -1,232 +0,0 @@
; xsub 'Extended Submit Facility' version 2.2
;
;
;
; xsub loads below ccp, and feeds command lines to
; programs which read buffered input
;
bias equ 0000h ;bias for relocation
base equ 0ffffh ;no intercepts below here
wboot equ 0000h
bdos equ 0005h
bdosl equ bdos+1
dbuff equ 0080h
;
cr equ 0dh ;carriage return
lf equ 0ah ;line feed
modnum equ 14 ;module number position
pbuff equ 9 ;print buffer
rbuff equ 10 ;read buffer
openf equ 15 ;open file
closef equ 16 ;close file
delf equ 19 ;delete file
dreadf equ 20 ;disk read
dmaf equ 26 ;set dma function
;
;
org 0000h+bias
; initialize jmps to include xsub module
jmp start
ds 3
trapjmp:
jmp trap
db 'xsub'
start:
lhld wboot+1
shld savboot
lxi h,wstart
shld wboot+1
lhld bdosl
shld rbdos+1 ;real bdos entry
lxi h,trapjmp ;address to fill
shld bdosl ;jmp @0005 leads to trap
pop h ;ccp return address
shld ccpret
pchl ;back to ccp
;
savboot:
ds 2 ;warm boot saved and restored at end
;of submit file
;
wstart:
lxi sp,stack
mvi c,pbuff ;print message
CALL GET$SUBADDR
lxi d,actmsg
<EFBFBD> CNZ rbdos
lxi h,dbuff ;restore default buffer
shld udma
call rsetdma
lxi h,trapjmp
shld bdosl ;fixup low jump address
lhld ccpret ;back to ccp
pchl
actmsg: db cr,lf,'(xsub active)$'
;
trap: ;arrive here at each bdos call
pop h ;return address
push h ;back to stack
mov a,h ;high address
cpi base shr 8
jnc rbdos ;skip calls on bdos above here
mov a,c ;function number
cpi rbuff
jz rnbuff ;read next buffer
cpi dmaf ;set dma address?
jnz rbdos ;skip if not
xchg ;dma to hl
shld udma ;save it
xchg
rbdos: jmp 0000h ;filled in at initialization
;
setdma:
lxi d,combuf
SETDMA1:
mvi c,dmaf
JMP RBDOS
;
rsetdma:
lhld udma
xchg
JMP SETDMA1
;
GET$SUBADDR:
LHLD RBDOS+1
MVI L,09H
MOV E,M
INX H
MOV D,M
XCHG
MOV A,M
ORA A
RET
;
DELETE$SUB:
CALL GET$SUBADDR
MVI M,0
MVI C,DELF
LXI D,SUBFCB
;
<EFBFBD>fbdos:
push b
push d
call setdma
pop d
pop b
call rbdos
push psw
call rsetdma
pop psw
ret
;
cksub: ;check for sub file present
CALL GET$SUBADDR
RZ
INX H
LXI D,SUBS1
MVI C,20
;
MOVE:
INR C
MOVE1:
ORA C
DCR C
RZ
MOV A,M
STAX D
INX H
INX D
JMP MOVE1
;
rnbuff:
push d ;command address
call cksub ;sub file present?
pop d
mvi c,rbuff
ORA A
jz restor ;no sub file
;
push d
lda subrc ;length of file
ora a ;zero?
jz rbdos ;skip if so
dcr a ;length - 1
sta subcr ;next to read
mvi c,dreadf
lxi d,subfcb
call fbdos ;read record
ORA A
JZ READOK
CALL DELETE$SUB
MVI C,0
restor:
lhld savboot
<EFBFBD> shld wboot+1
jmp rbdos
READOK:
; now print the buffer with cr,lf
lxi h,combuf
mov e,m ;length
mvi d,0 ;high order 00
dad d ;to last character position
inx h
mvi m,cr
inx h
mvi m,lf
inx h
mvi m,'$'
mvi c,pbuff
lxi d,combuf+1
LDAX D
CPI 3
CNZ rbdos ;to print it
pop h ;.max length
lxi d,combuf
ldax d ;how long?
cmp m ;cy if ok
jc movlin
mov a,m ;max length
stax d ;truncate length
movlin:
mov c,a ;length to c
inr c ;+1
inx h ;to length of line
XCHG
CALL MOVE
CALL GET$SUBADDR
PUSH H ;.SUBFLAG
INX H ;.FCB(S1)
INX H ;.FCB(S2)
INX H ;.FCB(RC)
DCR M
POP H
CZ DELETE$SUB
LDA COMBUF+1 ;^C?
CPI 3
RNZ
MVI C,PBUFF
LXI D,CTLCMSG
CALL RBDOS
JMP WBOOT
;
subfcb:
db 1 ;a:
db '$$$ '
db 'SUB'
<EFBFBD> db 0
SUBS1:
DB 0,0
subrc:
ds 1
ds 16 ;map
subcr: ds 1
;
CTLCMSG:DB '^C$'
combuf: ds 131
udma: dw dbuff
ccpret: ds 2 ;ccp return address

View File

@@ -1,4 +0,0 @@
mount a transfer
mount b disk
mount c COBOL
go

View File

@@ -1,23 +0,0 @@
; Program "Call" called by "Testcall"; this is assembler version;
; compare with functionally equivalent COBOL version.
cseg
ldax b ; read first param: A = text length
loop:
dcr a ; count down length
rm ; finished
push psw
ldax d ; next byte from second param = text
inx d
push d
mov e,a
mvi c,6 ; CP/M function code
call 5 ; call CP/M to send character
pop d
pop psw
jmp loop
; End of demonstration program "Call"
end

View File

@@ -1,26 +0,0 @@
000000******************************************************************
000000*
000000* Program "Call" called by "Testcall"; this is COBOL version;
000000* compare with functionally equivalent assembler version.
000000*
000000******************************************************************
000000 Working-storage section.
000000 01 temp pic 9(2) comp.
000000 01 text-buffer value space.
000000 02 tbuf-table pic x occurs 80.
000000 Linkage section.
000000 01 mess-text.
000000 02 mtex-table pic x occurs 80.
000000 01 mess-size pic 9(2) comp.
000000 Procedure division using mess-size,mess-text.
000000 l.
000000 move 0 to temp perform move-byte until temp = mess-size.
000000 display text-buffer.
000000 exit program.
000000 move-byte.
000000 add 1 to temp move mtex-table (temp) to tbuf-table (temp).
000000******************************************************************
000000*
000000* End of demonstration program "Call"
000000*
000000******************************************************************

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,240 +0,0 @@
000000 IDENTIFICATION DIVISION.
000000******************************************************************
000000* *
000000* COPYRIGHT (C) 1982,1982 MICRO FOCUS LTD. *
000000* *
000000* MICRO FOCUS LTD. *
000000* 58, ACACIA ROAD, *
000000* ST. JOHNS WOOD, *
000000* LONDON NW8 6AG. *
000000* *
000000* TEL. 01 722 8843/4/5/6/7 *
000000* TELEX 28536 MICROF G *
000000* *
000000******************************************************************
000000*
000000 PROGRAM-ID. COMMAND LINE INTERPRETOR.
000000 AUTHOR. MICRO FOCUS LTD.
000000 INSTALLATION. MICRO FOCUS - SWINDON.
000000 DATE-WRITTEN. 6TH DECEMBER 1982.
000000 DATE-COMPILED. 6TH DECEMBER 1982.
000000*
000000 ENVIRONMENT DIVISION.
000000 SOURCE-COMPUTER. 8080.
000000 OBJECT-COMPUTER. 8080.
000000 SPECIAL-NAMES. CONSOLE IS CRT.
000000/*****************************************************************
000000* *
000000* DATA USED BY THE CLI TO STORE THE USER'S INSTRUCTIONS. *
000000* *
000000******************************************************************
000000*
000000 DATA DIVISION.
000000 WORKING-STORAGE SECTION.
000000*
000000 01 TEMP PIC 9(2) COMP.
000000 01 SUB1 PIC 9(2) COMP.
000000 01 SUB2 PIC 9(2) COMP.
000000 01 SUB2-SAV PIC 9(2) COMP.
000000 01 TMAX PIC 9(2) COMP.
000000 01 CHOICE PIC X.
000000*
000000 01 RTS-ROUTINES.
000000 02 POKE-CLI PIC X VALUE X"91".
000000 02 CHAIN PIC X VALUE X"84".
000000 02 GET-CHAR PIC X VALUE X"D8".
000000 02 SOUND-ALARM PIC X VALUE X"E5".
000000*
000000* DISPLAY LINES
000000*
000000 01 INIT-LINE.
000000 02 INIT-LINE-1 PIC X(68) VALUE "COBOL: A(nimate) C(ompile) D(
000000- "rive) F(orms2) Q(uit) R(un) S(witches)".
000000 02 FILLER PIC X(4).
000000 02 INIT-CHOICE PIC X.
000000*
000000 01 FILE-QUESTION-LINE.
000000 02 FQL-1 PIC X(22) VALUE "Enter name of file to ".
000000 02 VERB PIC X(8).
000000*
000000* COMMAND-LINE COMPONENTS
000000*
000000 01 SWITCH-AREA.
000000 02 FILLER PIC X VALUE "(".
000000 02 SWITCHES PIC X(40) VALUE SPACE.
000000*
000000 01 FILE-NAME PIC X(16).
000000*
000000 01 CLI-REST PIC X(80).
000000*
000000 01 WORK-AREA.
000000 02 WORK-BYTE PIC 9(2) OCCURS 80 COMP.
000000*
000000 01 OUTPUT-CLI VALUE SPACE.
000000 02 OUT-BYTE PIC 9(2) OCCURS 128 COMP.
000000*
000000 01 PROG-AREA.
000000 02 DRIVE PIC X VALUE SPACE.
000000 02 FILLER PIC X VALUE ":".
000000 02 PROG-NAME PIC X(16).
000000*
000000/*****************************************************************
000000* *
000000* MAIN ENTRY TO CLI PROGRAM. IS USED BY ORDINARY ENTRY TO *
000000* COMMAND LINE INTERPRETOR, AS WELL AS BY PROGRAMS WHICH ARE *
000000* RETURNING CONTROL TO THE CLI FOR CONTINUATION COMMANDS. *
000000* *
000000******************************************************************
000000*
000000 PROCEDURE DIVISION.
000000 MAIN-ENTRY.
000000*
000000* TEST IF SCREEN SHOULD BE CLEARED. IF "X" ON COMMAND LINE, THEN
000000* THIS IS A SECOND OR SUBSEQUENT ENTRY, AND THE SCREEN SHOULD
000000* NOT BE CLEARED.
000000*
000000 ACCEPT WORK-AREA FROM CONSOLE.
000000 IF WORK-AREA NOT = "X"
000000 DISPLAY SPACE.
000000 CALL SOUND-ALARM.
000000*
000000 LOOP.
000000 MOVE SPACE TO INIT-CHOICE.
000000 DISPLAY INIT-LINE.
000000 DISPLAY LOW-VALUE AT 0170.
000000 CALL GET-CHAR USING CHOICE.
000000 DISPLAY SPACE.
000000 MOVE CHOICE TO INIT-CHOICE.
000000 DISPLAY INIT-LINE.
000000*
000000 IF CHOICE = "A" OR "a"
000000 MOVE "ANIMATE:" TO VERB
000000 MOVE "ANIMATE.COM" TO PROG-NAME
000000 GO TO FILE-QUESTION.
000000 IF CHOICE = "C" OR "c"
000000 MOVE "COMPILE:" TO VERB
000000 MOVE "COBOL.COM" TO PROG-NAME
000000 GO TO FILE-QUESTION.
000000 IF CHOICE = "D" OR "d"
000000 GO TO DRIVE-SET.
000000 IF CHOICE = "F" OR "f"
000000 MOVE "FORMS2.COM" TO PROG-NAME
000000 MOVE 0 TO SUB2
000000 GO TO LOADER.
000000 IF CHOICE = "Q" OR "q"
000000 GO TO EXITING.
000000 IF CHOICE = "R" OR "r"
000000 MOVE "RUN:" TO VERB
000000 MOVE "RUN.COM" TO PROG-NAME
000000 GO TO FILE-QUESTION.
000000 IF CHOICE = "S" OR "s"
000000 GO TO SWITCH-SET.
000000 CALL SOUND-ALARM.
000000 GO TO LOOP.
000000*
000000/*****************************************************************
000000* *
000000* CODE TO HANDLE FILENAME OF PROGRAM TO BE COMPILED, ANIMATED *
000000* OR EXECUTED. *
000000* *
000000******************************************************************
000000*
000000 FILE-QUESTION.
000000 MOVE SPACE TO FILE-NAME.
000000 DISPLAY FILE-QUESTION-LINE AT 0201.
000000 ACCEPT FILE-NAME AT 0232.
000000 IF FILE-NAME = SPACES
000000 GO TO LOOP.
000000*
000000 PERFORM CLEAR-LINES.
000000 MOVE SPACE TO CLI-REST.
000000 DISPLAY "Any further command line ?" AT 0201.
000000 ACCEPT CLI-REST AT 0301.
000000*
000000 MOVE 0 TO SUB2.
000000 IF "RUN.COM" = PROG-NAME
000000 IF SPACE NOT = SWITCHES
000000 MOVE SWITCH-AREA TO WORK-AREA
000000 MOVE 41 TO TMAX
000000 MOVE 0 TO SUB1
000000 PERFORM TRANSFER-BUFFER
000000 ADD 1 TO SUB2
000000 MOVE 41 TO OUT-BYTE (SUB2).
000000 MOVE FILE-NAME TO WORK-AREA.
000000 MOVE 0 TO SUB1.
000000 MOVE 16 TO TMAX.
000000 PERFORM TRANSFER-BUFFER.
000000 MOVE CLI-REST TO WORK-AREA.
000000 MOVE 0 TO SUB1.
000000 MOVE 80 TO TMAX.
000000 PERFORM TRANSFER-BUFFER.
000000 IF SUB2 > 80
000000 GO TO CLI-OVF.
000000*
000000* COMMAND LINE NOW CREATED, CHAIN TO THE NEXT PROGRAM. THIS
000000* IS DONE BY SETTING A COMMAND LINE FOR THE RTS TO EXECUTE.
000000*
000000 LOADER.
000000 CALL POKE-CLI USING SUB2, OUTPUT-CLI.
000000 PERFORM CLEAR-LINES.
000000 DISPLAY "Loading ..." at 0201.
000000 DISPLAY LOW-VALUE AT 0301.
000000 IF DRIVE = SPACE
000000 CALL CHAIN USING PROG-NAME
000000 ELSE
000000 CALL CHAIN USING PROG-AREA.
000000*
000000/*****************************************************************
000000* *
000000* SUPPORT CLI ROUTINES, USED TO MANIPULATE THE FIELDS BEFORE *
000000* CONTROL IS TRANSFERRED TO A SUPPORT PROGRAM. *
000000* *
000000******************************************************************
000000*
000000 SWITCH-SET.
000000 MOVE SPACE TO SWITCHES.
000000 DISPLAY "Switches:" AT 0201.
000000 ACCEPT SWITCHES AT 0211.
000000 INSPECT SWITCHES REPLACING
000000 ALL "(" BY SPACE
000000 ALL ")" BY SPACE.
000000 GO TO LOOP.
000000*
000000 DRIVE-SET.
000000 DISPLAY "Enter Drive:" AT 0201.
000000 ACCEPT DRIVE AT 0214.
000000 GO TO LOOP.
000000*
000000 EXITING.
000000 DISPLAY "Returning to CP/M" AT 0201.
000000 DISPLAY LOW-VALUE AT 0301.
000000 STOP RUN.
000000*
000000/*****************************************************************
000000* *
000000* WORK ROUTINES USED TO MANIPULATE THE SCREEN. *
000000* *
000000******************************************************************
000000*
000000 CLI-OVF.
000000 PERFORM CLEAR-LINES.
000000 DISPLAY "Command buffer overflow" AT 0301.
000000 GO TO LOOP.
000000*
000000 CLEAR-LINES.
000000 MOVE SPACE TO WORK-AREA.
000000 DISPLAY WORK-AREA AT 0201.
000000 DISPLAY WORK-AREA AT 0301.
000000*
000000 TRANSFER-BUFFER.
000000 ADD 1 TO SUB1.
000000 ADD 1 TO SUB2.
000000 MOVE WORK-BYTE (SUB1) TO TEMP.
000000 IF TEMP NOT = 32
000000 MOVE SUB2 TO SUB2-SAV
000000 MOVE TEMP TO OUT-BYTE (SUB2).
000000 IF SUB1 < TMAX
000000 GO TO TRANSFER-BUFFER.
000000 MOVE SUB2-SAV TO SUB2.
000000 ADD 1 TO SUB2.
000000*

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,160 +0,0 @@
Compiler error; consult Technical Support
Illegal format : Data-name
Illegal format : Literal, or invalid use of ALL
Illegal format : Character
Data-name not unique
Too many data or procedure names declared
Illegal character in column 7 or continuation error
Nested COPY statement or unknown COPY file specified
'.' missing
Statement starts in wrong area of source line
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
'.' missing
DIVISION missing
SECTION missing
IDENTIFICATION missing
PROGRAM-ID missing
AUTHOR missing
INSTALLATION missing
DATE-WRITTEN missing
SECURITY missing
ENVIRONMENT missing
CONFIGURATION missing
SOURCE-COMPUTER missing
OBJECT-COMPUTER/SPECIAL-NAMES clause error
OBJECT-COMPUTER missing
Compiler error; consult Technical Support
SPECIAL-NAMES missing
SWITCH clause error or system name/mnemonic name error
DECIMAL-POINT clause error
CONSOLE clause error
Illegal currency symbol
'.' missing
DIVISION missing
SECTION missing
INPUT-OUTPUT missing
FILE-CONTROL missing
ASSIGN missing
SEQUENTIAL or RELATIVE or INDEXED missing
ACCESS missing on indexed/relative file
SEQUENTIAL or DYNAMIC missing or > 64 alternate keys
Illegal ORGANIZATION/ACCESS/KEY combination
Unrecognized phrase in SELECT clause
RERUN clause syntax error
SAME AREA clause syntax error
Missing or illegal file-name
DATA DIVISION missing
PROCEDURE DIVISION missing or unknown statement
Program collating sequence not defined
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
'.' missing
DIVISION missing
SECTION missing
File-name not specified in SELECT stmt or invalid CD name
RECORD SIZE integer missing or line sequential rec > 1024 bytes
Illegal level no (01-49),01 level reqd,or level hierarachy wrong
FD, CD or SD qualification syntax error
WORKING-STORAGE missing
PROCEDURE DIVISION missing or unknown statement
Data description qualifier or '.' missing
Incompatible PICTURE clause and qualifiers
BLANK illegal with non-numeric data-item
PICTURE clause too long
VALUE with non-elementary item,wrong data-type or value truncated
VALUE in error or illegal for PICTURE type
Non-elementary item has FILLER/SYNC/JUST/BLANK clause
Preceding item at this level has > 8192 bytes or 0 bytes
REDEFINES of unequal fields or different levels
Data storage exceeds 64K bytes
Compiler error; consult Technical Support
Data description qualifier inappropriate or repeated
REDEFINES data-name not declared
USAGE must be COMP,DISPLAY or INDEX
SIGN must be LEADING or TRAILING
SYNCHRONIZED must be LEFT or RIGHT
JUSTIFIED must be RIGHT
BLANK must be ZERO
OCCURS must be numeric, non-zero, unsigned or DEPENDING
VALUE must be literal, numeric literal or figurative constant
PICTURE string has illegal precedence or illegal char
INDEXED data-name missing or already declared
Numeric-edited PICTURE string is too large
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Unrecognized verb
IF....ELSE mismatch
Operand has wrong data-type, is not declared or '.' missing
Procedure not unique
Procedure name same as data-name
Name required
Wrong combination of data-types
Conditional statement not allowed in this context
Malformed subscript
ACCEPT/DISPLAY wrong or Communications syntax incorrect
Illegal syntax used with I-O verb
Invalid arithmetic statement
Invalid arithmetic expression
Compiler error; consult Technical Support
Invalid conditional expression
IF stmts nested too deep, or too many AFTERs in PERFORM stmt
Incorrect structure of PROCEDURE DIVISION
Reserved word missing or incorrectly used
Too many subscripts in one statement (internal buffer overflow)
Too many operands in one statement
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Inter-segment procedure name duplication
Unterminated condition at end of source
Operand has wrong data-type or not declared
Procedure name undeclared
INDEX data-name declared twice
Bad cursor control : illegal AT clause
KEY declaration missing or illegal
STATUS declaration missing
Bad STATUS record
Undefined inter-segment reference or error in ALTERed para
PROCEDURE DIVISION in error
USING parameter not declared in LINKAGE SECTION
USING parameter not level 01 or 77
USING parameter used twice in parameter list
FD missing
Compiler error; consult Technical Support
Incorrect structure of PROCEDURE DIVISION
Compiler error; consult Technical Support
Compiler error; consult Technical Support
Too many operands in one statement

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,83 +0,0 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. PI-CALC.
AUTHOR. PF/TR.
*
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
OBJECT-COMPUTER. MDS-800.
SPECIAL-NAMES. CONSOLE IS CRT.
*
DATA DIVISION.
WORKING-STORAGE SECTION.
*
01 SCREEN PIC X(1920).
*
01 DI-1 REDEFINES SCREEN.
02 FILLER PIC X(160).
02 DI-TX1 PIC X(160).
02 DI-TX2 PIC X(13).
02 DI-TERM PIC X(15).
02 FILLER PIC X(136).
02 DI-TX3 PIC X(6).
02 DI-PI PIC X(15).
02 FILLER PIC X(1415).
*
01 DI-2 REDEFINES SCREEN.
02 FILLER PIC X(333).
02 DI-TERM2 PIC X(15).
02 FILLER PIC X(142).
02 DI-PI2 PIC X(15).
02 FILLER PIC X(1415).
*
01 WORK-AREA.
02 PI PIC S9V9(14).
02 TERM PIC S9V9(14).
02 W PIC S9V9(14).
02 N PIC 9999.
02 N1 PIC 9999.
02 N2 PIC 9999.
02 ED PIC -9.9(12).
*
01 CONSTANTS.
02 TX1 PIC X(17) VALUE "CALCULATION OF PI".
02 TX2 PIC X(12) VALUE "NEXT TERM IS".
02 TX3 PIC X(5) VALUE "PI IS".
*
PROCEDURE DIVISION.
LA-START.
DISPLAY SPACE.
MOVE SPACE TO SCREEN.
MOVE TX1 TO DI-TX1.
MOVE TX2 TO DI-TX2.
MOVE TX3 TO DI-TX3.
MOVE 0.5 TO ED.
MOVE ED TO DI-TERM.
MOVE 3 TO ED.
MOVE ED TO DI-PI.
DISPLAY DI-1.
MOVE 0.5 TO PI.
MOVE 0.5 TO TERM.
MOVE 3 TO N.
LOOP.
MOVE N TO N2.
SUBTRACT 2 FROM N2.
MULTIPLY N2 BY N2.
MULTIPLY N2 BY TERM.
MOVE N TO N1.
SUBTRACT 1 FROM N1.
MULTIPLY N BY N1.
MULTIPLY 4 BY N1.
DIVIDE N1 INTO TERM.
IF TERM < 0.0000000000001 THEN GO TO HALT.
ADD TERM TO PI.
MOVE PI TO W.
MULTIPLY 6 BY W.
MOVE W TO ED.
MOVE ED TO DI-PI2.
MOVE TERM TO ED.
MOVE ED TO DI-TERM2.
DISPLAY DI-2.
ADD 2 TO N.
IF N < 100 GO TO LOOP.
HALT.
STOP RUN.

Binary file not shown.

View File

@@ -1,59 +0,0 @@
000010 IDENTIFICATION DIVISION.
000020 PROGRAM-ID. STOCK-FILE-SET-UP.
000030 AUTHOR. MICRO FOCUS LTD.
000040 ENVIRONMENT DIVISION.
000050 CONFIGURATION SECTION.
000060 SOURCE-COMPUTER. MDS-800.
000070 OBJECT-COMPUTER. MDS-800.
000075 SPECIAL-NAMES. CONSOLE IS CRT.
000080 INPUT-OUTPUT SECTION.
000090 FILE-CONTROL.
000100 SELECT STOCK-FILE ASSIGN "STOCK.IT"
000110 ORGANIZATION INDEXED
000120 ACCESS DYNAMIC
000130 RECORD KEY STOCK-CODE.
000140 DATA DIVISION.
000150 FILE SECTION.
000160 FD STOCK-FILE; RECORD 32.
000170 01 STOCK-ITEM.
000180 02 STOCK-CODE PIC X(4).
000190 02 PRODUCT-DESC PIC X(24).
000200 02 UNIT-SIZE PIC 9(4).
000210 WORKING-STORAGE SECTION.
000220 01 SCREEN-HEADINGS.
000230 02 ASK-CODE PIC X(21) VALUE "STOCK CODE < >".
000240 02 FILLER PIC X(59).
000250 02 ASK-DESC PIC X(16) VALUE "DESCRIPTION <".
000260 02 SI-DESC PIC X(25) VALUE " >".
000270 02 FILLER PIC X(39).
000280 02 ASK-SIZE PIC X(21) VALUE "UNIT SIZE < >".
000290 01 ENTER-IT REDEFINES SCREEN-HEADINGS.
000300 02 FILLER PIC X(16).
000310 02 CRT-STOCK-CODE PIC X(4).
000320 02 FILLER PIC X(76).
000330 02 CRT-PROD-DESC PIC X(24).
000340 02 FILLER PIC X(56).
000350 02 CRT-UNIT-SIZE PIC 9(4).
000360 02 FILLER PIC X.
000370 PROCEDURE DIVISION.
000380 SR1.
000390 DISPLAY SPACE.
000400 OPEN I-O STOCK-FILE.
000410 DISPLAY SCREEN-HEADINGS.
000420 NORMAL-INPUT.
000430 MOVE SPACE TO ENTER-IT.
000440 DISPLAY ENTER-IT.
000450 CORRECT-ERROR.
000460 ACCEPT ENTER-IT.
000470 IF CRT-STOCK-CODE = SPACE GO TO END-IT.
000480 IF CRT-UNIT-SIZE NOT NUMERIC GO TO CORRECT-ERROR.
000490 MOVE CRT-PROD-DESC TO PRODUCT-DESC.
000500 MOVE CRT-UNIT-SIZE TO UNIT-SIZE.
000510 MOVE CRT-STOCK-CODE TO STOCK-CODE.
000520 WRITE STOCK-ITEM; INVALID GO TO CORRECT-ERROR.
000530 GO TO NORMAL-INPUT.
000540 END-IT.
000550 CLOSE STOCK-FILE.
000560 DISPLAY SPACE.
000570 DISPLAY "END OF PROGRAM".
000580 STOP RUN.

View File

@@ -1,119 +0,0 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. GOODS-IN.
AUTHOR. MICRO FOCUS LTD.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. MDS-800.
OBJECT-COMPUTER. MDS-800.
SPECIAL-NAMES. CONSOLE IS CRT.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT STOCK-FILE ASSIGN "STOCK.IT"
ORGANIZATION INDEXED
ACCESS DYNAMIC
RECORD KEY STOCK-CODE.
SELECT TRANS-FILE
ASSIGN "STOCK.TRS"
ORGANIZATION SEQUENTIAL.
/
DATA DIVISION.
FILE SECTION.
FD STOCK-FILE; RECORD 32.
01 STOCK-ITEM.
02 STOCK-CODE PIC X(4).
02 STOCK-DESCRIPT PIC X(24).
02 UNIT-SIZE PIC 9(4).
FD TRANS-FILE; RECORD 30.
01 TRANS-RECORD.
02 TRAN-NO PIC 9(4).
02 TF-STOCK-CODE PIC X(4).
02 TF-QUANTITY PIC 9(8).
02 TF-ORDER-NO PIC X(6).
02 TF-DATE PIC X(8).
WORKING-STORAGE SECTION.
01 STOCK-INWARD-FORM.
02 PRG-TITLE PIC X(20) VALUE " GOODS INWARD".
02 FILLER PIC X(140).
02 CODE-HDNG PIC X(23) VALUE "STOCK CODE < >".
02 FILLER PIC X(57).
02 ORDER-NO-HDNG PIC X(23) VALUE "ORDER NO < >".
02 FILLER PIC X(57).
02 DATE-HDNG PIC X(24) VALUE "DELIVERY DATE MM/DD/YY".
02 FILLER PIC X(56).
02 UNITS-HDNG PIC X(23) VALUE "NO OF UNITS < >".
01 STOCK-RECEIPT REDEFINES STOCK-INWARD-FORM.
02 FILLER PIC X(178).
02 SR-STOCK-CODE PIC X(4).
02 FILLER PIC X(74).
02 SR-ORDER-NO PIC X(6).
02 FILLER PIC X(73).
02 SR-DATE.
04 SR-MM PIC 99.
04 FILLER PIC X.
04 SR-DD PIC 99.
04 FILLER PIC X.
04 SR-YY PIC 99.
02 FILLER PIC X(75).
02 SR-NO-OF-UNITS PIC 9(4).
01 CONFIRM-MSG REDEFINES STOCK-INWARD-FORM.
02 FILLER PIC X(184).
02 CM-STOCK-DESCRIPT PIC X(24).
02 FILLER PIC X(352).
02 UNIT-SIZE-HDNG PIC X(18).
02 CM-UNIT-SIZE PIC 9(4).
02 FILLER PIC X(58).
02 QUANTITY-HDNG PIC X(14).
02 CM-QUANTITY PIC 9(8).
02 FILLER PIC X(58).
02 OK-HDNG PIC X(3).
02 CM-Y-OR-N PIC X.
/
PROCEDURE DIVISION.
START-PROC.
OPEN I-O STOCK-FILE.
OPEN OUTPUT TRANS-FILE.
DISPLAY SPACE.
MOVE 0 TO TRAN-NO.
DISPLAY STOCK-INWARD-FORM.
GET-INPUT.
ACCEPT STOCK-RECEIPT.
IF SR-STOCK-CODE = SPACE GO TO END-IT.
IF SR-NO-OF-UNITS NOT NUMERIC GO TO INVALID-ENTRY.
MOVE SR-STOCK-CODE TO STOCK-CODE.
READ STOCK-FILE; INVALID GO TO INVALID-CODE.
*VALID ENTRY, CALCULATE AND DISPLAY TOTAL QUANTITY IN TO CONFIRM
MOVE STOCK-DESCRIPT TO CM-STOCK-DESCRIPT.
MOVE "UNIT SIZE" TO UNIT-SIZE-HDNG.
MOVE UNIT-SIZE TO CM-UNIT-SIZE.
MOVE "QUANTITY IN" TO QUANTITY-HDNG.
MOVE UNIT-SIZE TO TF-QUANTITY.
MULTIPLY SR-NO-OF-UNITS BY TF-QUANTITY.
MOVE TF-QUANTITY TO CM-QUANTITY.
MOVE "OK?" TO OK-HDNG.
DISPLAY CONFIRM-MSG.
ACCEPT CM-Y-OR-N AT 1004.
IF CM-Y-OR-N = "Y" PERFORM WRITE-TRANS.
*CLEAR INPUT DATA ON SCREEN
MOVE SPACE TO CONFIRM-MSG.
MOVE "MM/DD/YY" TO SR-DATE.
DISPLAY STOCK-RECEIPT.
DISPLAY CONFIRM-MSG.
GO TO GET-INPUT.
WRITE-TRANS.
ADD 1 TO TRAN-NO.
MOVE STOCK-CODE TO TF-STOCK-CODE.
MOVE SR-ORDER-NO TO TF-ORDER-NO.
MOVE GET-INPUT TO TF-DATE.
WRITE TRANS-RECORD.
INVALID-ENTRY.
DISPLAY "NON-NUMERIC NO OF UNITS" AT 0325.
GO TO GET-INPUT.
INVALID-CODE.
DISPLAY "INVALID CODE " AT 0325.
GO TO GET-INPUT.
END-IT.
CLOSE STOCK-FILE.
CLOSE TRANS-FILE.
DISPLAY SPACE.
DISPLAY "END OF PROGRAM".
STOP RUN.

View File

@@ -1,19 +0,0 @@
000000******************************************************************
000000*
000000* Program "Testcall" to demonstrate L/II COBOL calling mechanism
000000*
000000******************************************************************
000000 Working-storage section.
000000 01 progname pic x(4).
000000 01 message-size pic 9(2) comp value 60.
000000 01 message-text pic x(60) value
000000 "This message is sent via a called program to the screen.".
000000 Procedure division.
000000 move "call" to progname.
000000 call progname using message-size,message-text
000000 overflow display "call overflowed".
000000******************************************************************
000000*
000000* End of demonstration program "Testcall"
000000*
000000******************************************************************

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,2 +0,0 @@
#!/bin/bash
yaze -v

View File

@@ -1,3 +0,0 @@
#!/bin/bash
cd /usr/local/src/yaze-1.14/
yaze -v

View File

@@ -1,6 +0,0 @@
#!/bin/sh
rm -f disks/drive[ab].cpm
ln disks/library/cpm2-1.dsk disks/drivea.cpm
ln disks/library/cpm2-2.dsk disks/driveb.cpm
cpmsim

View File

@@ -1,6 +0,0 @@
#!/bin/sh
rm -f disks/drive[ab].cpm
ln disks/library/cpm3-1.dsk disks/drivea.cpm
ln disks/library/cpm3-2.dsk disks/driveb.cpm
cpmsim

View File

@@ -1,6 +0,0 @@
#!/bin/sh
rm -f disks/drive[ab].cpm
ln disks/library/mpm-1.dsk disks/drivea.cpm
ln disks/library/mpm-2.dsk disks/driveb.cpm
cpmsim -h

View File

@@ -1,32 +0,0 @@
CFLAGS= -O -s
all: format putsys bin2hex send receive bios.bin boot.bin
@echo "done"
format: format.c
cc $(CFLAGS) -o format format.c
cp format ..
putsys: putsys.c
cc $(CFLAGS) -o putsys putsys.c
bin2hex: bin2hex.c
cc $(CFLAGS) -o bin2hex bin2hex.c
cp bin2hex ..
send: send.c
cc $(CFLAGS) -o send send.c
cp send ..
receive: receive.c
cc $(CFLAGS) -o receive receive.c
cp receive ..
bios.bin: bios.asm
z80asm -vl -sn -x bios.asm
boot.bin: boot.asm
z80asm -vl -sn boot.asm
clean:
rm -f *.lis bios.bin boot.bin format putsys bin2hex receive send

View File

@@ -1,161 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
void help(char *name)
{
printf("%s - BINARY to Intel HEX file convertor version 1.00\n"\
"(c)BCL Vysoke Myto 2001 (benedikt@lphard.cz)\n\n",name);
printf("Usage: %s [-option] binfile hexfile\n"\
" -l Bytes to read from binary file\n"\
" -i Binary file starting offset\n"\
" -o Output file offset (where HEX data starts)\n"\
" -t Exclude EOF record\n"\
" -a Append to end of existing HEX file\n"\
" -q Quiet mode (no statistics are printed)\n", name);
}
int main(int argc,char *argv[])/*Main routine*/
{
char *ifile = NULL;
char *ofile = NULL;
char c;
FILE *inp, *outp;
int ch,csum;
int ofsa = 0;
int cnt = 0;
struct stat statbuf;
long int foffset = 0;
long int fsize = 0;
long int fsub;
long int fpoint = 0;
long int adrs = 0;
unsigned char quiet = 0;
unsigned char eofrec = 0;
unsigned char append = 0;
opterr = 0; //print error message if unknown option
while ((c = getopt (argc, argv, "l:i:o:taqv")) != -1)
switch (c) {
case 'l':
fsize = atol(optarg);
break;
case 'i':
foffset = atol(optarg);
break;
case 'o':
adrs = atol(optarg);
break;
case 't':
eofrec = 1;
break;
case 'a':
append = 1;
break;
case 'q':
quiet = 1;
break;
case 'v':
printf("%s - BINARY to Intel HEX file convertor version 1.00\n"\
"(c)BCL Vysoke Myto 2001 (benedikt@lphard.cz)\n",argv[0]);
return 0;
case '?':
help (argv[0]);
return 1;
}
if ((argc - optind) != 2) {
printf("ERROR: Missing input/output file.\n");
help(argv[0]);
return 1;
}
ifile = argv[optind];
ofile = argv[optind+1];
/*Open file check*/
if((inp = fopen(ifile, "rb")) == NULL){
printf("ERROR: Cannot open input file.\n");
return 1;
}
fseek (inp, foffset, SEEK_SET);
if (append == 0) {
if((outp = fopen(ofile, "wt")) == NULL){
printf("ERROR: Cannot open output file.\n");
return 1;
}
} else {
if((outp = fopen(ofile, "at")) == NULL){
printf("ERROR: Cannot re-open output file.\n");
return 1;
}
fseek (outp, 0, SEEK_END);
}
fstat(fileno(inp), &statbuf);
if (quiet == 0) printf("Input file size=%ld\n",statbuf.st_size);
if (foffset > statbuf.st_size) {
printf("ERROR: Input offset > input file length\n");
}
if ((fsize == 0) || (fsize > (statbuf.st_size - foffset)))
fsize = statbuf.st_size - foffset;
// fprintf(outp,":020000020000FC\n");/*Start Header*/
fsub = fsize - fpoint;
if (fsub > 0x20) {
fprintf(outp,":20%04X00",adrs);/*Hex line Header*/
csum = 0x20 + (adrs>>8) + (adrs & 0xFF);
adrs += 0x20;
}
else {
fprintf(outp, ":%02X%04X00", fsub,adrs);/*Hex line Header*/
csum = fsub + (adrs>>8) + (adrs & 0xFF);
adrs += fsub;
}
while (fsub > 0){
ch = fgetc(inp);
fprintf(outp,"%02X",ch);/*Put data*/
cnt++; fpoint++;
fsub = fsize - fpoint;
csum = ch + csum;
if((fsub == 0)||(cnt == 0x20)){
cnt = 0; csum = 0xFF & (~csum + 1);
fprintf(outp,"%02X\n",csum);/*Put checksum*/
if(fsub == 0) break;
if(adrs > 0xFFFF){
ofsa = 0x1000 + ofsa;
adrs = 0;
fprintf(outp,":02000002%04X",ofsa);/*Change offset address*/
csum = 0x02 + 0x02 + (ofsa>>8) + (ofsa & 0xFF);
csum = 0xFF & (~csum + 1);
fprintf(outp,"%02X\n", csum);
}
adrs = 0xFFFF & adrs;
if (fsub > 0x20) {
fprintf(outp,":20%04X00",adrs);/*Next Hex line Header*/
csum = 0x20 + (adrs>>8) + (adrs & 0xFF);
adrs += 0x20;
}
else {
if(fsub > 0){
fprintf(outp, ":%02X%04X00", fsub,adrs);/*Next Hex line Header*/
csum = fsub + (adrs>>8) + (adrs & 0xFF);
adrs += fsub;
}
}
}
}
if (eofrec == 0) fprintf(outp,":00000001FF\n");/*End footer*/
fflush (outp);
fstat(fileno(outp), &statbuf);
if (quiet == 0) printf("Output file size=%ld\n",statbuf.st_size);
fclose(inp);
fclose(outp);
return 0;
}

View File

@@ -1,375 +0,0 @@
; CBIOS for Z80-Simulator
;
; Copyright (C) 1988-2006 by Udo Munk
;
MSIZE EQU 64 ;cp/m version memory size in kilobytes
;
; "bias" is address offset from 3400H for memory systems
; than 16K (referred to as "b" throughout the text).
;
BIAS EQU (MSIZE-20)*1024
CCP EQU 3400H+BIAS ;base of ccp
BDOS EQU CCP+806H ;base of bdos
BIOS EQU CCP+1600H ;base of bios
CDISK EQU 0004H ;current disk number 0=A,...,15=P
IOBYTE EQU 0003H ;intel i/o byte
;
; I/O ports
;
CONSTA EQU 0 ;console status port
CONDAT EQU 1 ;console data port
PRTSTA EQU 2 ;printer status port
PRTDAT EQU 3 ;printer data port
AUXDAT EQU 5 ;auxiliary data port
FDCD EQU 10 ;fdc-port: # of drive
FDCT EQU 11 ;fdc-port: # of track
FDCS EQU 12 ;fdc-port: # of sector
FDCOP EQU 13 ;fdc-port: command
FDCST EQU 14 ;fdc-port: status
DMAL EQU 15 ;dma-port: dma address low
DMAH EQU 16 ;dma-port: dma address high
;
ORG BIOS ;origin of this program
NSECTS EQU (BIOS-CCP)/128 ;warm start sector count
;
; jump vector for individual subroutines
;
JP BOOT ;cold start
WBOOTE: JP WBOOT ;warm start
JP CONST ;console status
JP CONIN ;console character in
JP CONOUT ;console character out
JP LIST ;list character out
JP PUNCH ;punch character out
JP READER ;reader character out
JP HOME ;move head to home position
JP SELDSK ;select disk
JP SETTRK ;set track number
JP SETSEC ;set sector number
JP SETDMA ;set dma address
JP READ ;read disk
JP WRITE ;write disk
JP LISTST ;return list status
JP SECTRAN ;sector translate
;
; fixed data tables for four-drive standard
; IBM-compatible 8" disks
;
; disk parameter header for disk 00
DPBASE: DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK00,ALL00
; disk parameter header for disk 01
DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK01,ALL01
; disk parameter header for disk 02
DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK02,ALL02
; disk parameter header for disk 03
DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK03,ALL03
;
; sector translate vector for the IBM 8" disks
;
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
DEFB 25,5,11,17 ;sectors 5,6,7,8
DEFB 23,3,9,15 ;sectors 9,10,11,12
DEFB 21,2,8,14 ;sectors 13,14,15,16
DEFB 20,26,6,12 ;sectors 17,18,19,20
DEFB 18,24,4,10 ;sectors 21,22,23,24
DEFB 16,22 ;sectors 25,26
;
; disk parameter block, common to all IBM 8" disks
;
DPBLK: DEFW 26 ;sectors per track
DEFB 3 ;block shift factor
DEFB 7 ;block mask
DEFB 0 ;extent mask
DEFW 242 ;disk size-1
DEFW 63 ;directory max
DEFB 192 ;alloc 0
DEFB 0 ;alloc 1
DEFW 16 ;check size
DEFW 2 ;track offset
;
; fixed data tables for 4MB harddisk
;
; disk parameter header
HDBASE: DEFW HDTRA,0000H
DEFW 0000H,0000H
DEFW DIRBF,HDBLK
DEFW CHKHD,ALLHD
;
; sector translate vector for the hardisk
;
HDTRA: DEFB 1,2,3,4,5,6,7,8,9,10
DEFB 11,12,13,14,15,16,17,18,19,20
DEFB 21,22,23,24,25,26,27,28,29,30
DEFB 31,32,33,34,35,36,37,38,39,40
DEFB 41,42,43,44,45,46,47,48,49,50
DEFB 51,52,53,54,55,56,57,58,59,60
DEFB 61,62,63,64,65,66,67,68,69,70
DEFB 71,72,73,74,75,76,77,78,79,80
DEFB 81,82,83,84,85,86,87,88,89,90
DEFB 91,92,93,94,95,96,97,98,99,100
DEFB 101,102,103,104,105,106,107,108,109,110
DEFB 111,112,113,114,115,116,117,118,119,120
DEFB 121,122,123,124,125,126,127,128
;
; disk parameter block for harddisk
;
HDBLK: DEFW 128 ;sectors per track
DEFB 4 ;block shift factor
DEFB 15 ;block mask
DEFB 0 ;extent mask
DEFW 2039 ;disk size-1
DEFW 1023 ;directory max
DEFB 255 ;alloc 0
DEFB 255 ;alloc 1
DEFW 0 ;check size
DEFW 0 ;track offset
;
; signon message
;
SIGNON: DEFM '64K CP/M Vers. 2.2 (CBIOS V1.1 for Z80SIM, '
DEFM 'Copyright 1988-2006 by Udo Munk)'
DEFB 13,10,0
;
; end of fixed tables
;
; individual subroutines to perform each function
; simplest case is to just perform parameter initialization
;
BOOT: LD SP,80H ;use space below buffer for stack
LD HL,SIGNON ;print message
BOOTL: LD A,(HL)
OR A
JP Z,BOOTC
LD C,A
CALL CONOUT
INC HL
JP BOOTL
BOOTC: XOR A ;zero in the accum
LD (IOBYTE),A ;clear the iobyte
LD (CDISK),A ;select disk zero
JP GOCPM ;initialize and go to cp/m
;
; simplest case is to read the disk until all sectors loaded
;
WBOOT: LD SP,80H ;use space below buffer for stack
LD C,0 ;select disk 0
CALL SELDSK
CALL HOME ;go to track 00
;
LD B,NSECTS ;b counts # of sectors to load
LD C,0 ;c has the current track number
LD D,2 ;d has the next sector to read
; note that we begin by reading track 0, sector 2 since sector 1
; contains the cold start loader, which is skipped in a warm start
LD HL,CCP ;base of cp/m (initial load point)
LOAD1: ;load one more sector
PUSH BC ;save sector count, current track
PUSH DE ;save next sector to read
PUSH HL ;save dma address
LD C,D ;get sector address to register c
CALL SETSEC ;set sector address from register c
POP BC ;recall dma address to b,c
PUSH BC ;replace on stack for later recall
CALL SETDMA ;set dma address from b,c
; drive set to 0, track set, sector set, dma address set
CALL READ
CP 00H ;any errors?
JP NZ,WBOOT ;retry the entire boot if an error occurs
; no error, move to next sector
POP HL ;recall dma address
LD DE,128 ;dma=dma+128
ADD HL,DE ;new dma address is in h,l
POP DE ;recall sector address
POP BC ;recall number of sectors remaining, and current trk
DEC B ;sectors=sectors-1
JP Z,GOCPM ;transfer to cp/m if all have been loaded
; more sectors remain to load, check for track change
INC D
LD A,D ;sector=27?, if so, change tracks
CP 27
JP C,LOAD1 ;carry generated if sector<27
; end of current track, go to next track
LD D,1 ;begin with first sector of next track
INC C ;track=track+1
; save register state, and change tracks
CALL SETTRK ;track address set from register c
JP LOAD1 ;for another sector
; end of load operation, set parameters and go to cp/m
GOCPM:
LD A,0C3H ;c3 is a jmp instruction
LD (0),A ;for jmp to wboot
LD HL,WBOOTE ;wboot entry point
LD (1),HL ;set address field for jmp at 0
;
LD (5),A ;for jmp to bdos
LD HL,BDOS ;bdos entry point
LD (6),HL ;address field of jump at 5 to bdos
;
LD BC,80H ;default dma address is 80h
CALL SETDMA
;
EI ;enable the interrupt system
LD A,(CDISK) ;get current disk number
LD C,A ;send to the ccp
JP CCP ;go to cp/m for further processing
;
;
; simple i/o handlers
;
; console status, return 0ffh if character ready, 00h if not
;
CONST: IN A,(CONSTA) ;get console status
RET
;
; console character into register a
;
CONIN: IN A,(CONDAT) ;get character from console
RET
;
; console character output from register c
;
CONOUT: LD A,C ;get to accumulator
OUT (CONDAT),A ;send character to console
RET
;
; list character from register c
;
LIST: LD A,C ;character to register a
OUT (PRTDAT),A
RET
;
; return list status (0 if not ready, 0xff if ready)
;
LISTST: IN A,(PRTSTA)
RET
;
; punch character from register c
;
PUNCH: LD A,C ;character to register a
OUT (AUXDAT),A
RET
;
; read character into register a from reader device
;
READER: IN A,(AUXDAT)
RET
;
;
; i/o drivers for the disk follow
;
; move to the track 00 position of current drive
; translate this call into a settrk call with parameter 00
;
HOME: LD C,0 ;select track 0
JP SETTRK ;we will move to 00 on first read/write
;
; select disk given by register C
;
SELDSK: LD HL,0000H ;error return code
LD A,C
CP 4 ;must be between 0 and 3
JR NC,SELHD ;no carry if 4,5,...
; disk number is in the proper range
; compute proper disk parameter header address
OUT (FDCD),A ;selekt disk drive
LD L,A ;L=disk number 0,1,2,3
ADD HL,HL ;*2
ADD HL,HL ;*4
ADD HL,HL ;*8
ADD HL,HL ;*16 (size of each header)
LD DE,DPBASE
ADD HL,DE ;HL=.dpbase(diskno*16)
RET
SELHD: CP 8 ;select the harddisk?
RET NZ ;no, error
OUT (FDCD),A ;select disk drive
LD HL,HDBASE ;HL=hdbase for harddisk
RET
;
; set track given by register c
;
SETTRK: LD A,C
OUT (FDCT),A
RET
;
; set sector given by register c
;
SETSEC: LD A,C
OUT (FDCS),A
RET
;
; translate the sector given by BC using the
; translate table given by DE
;
SECTRAN:
EX DE,HL ;HL=.trans
ADD HL,BC ;HL=.trans(sector)
LD L,(HL) ;L = trans(sector)
LD H,0 ;HL= trans(sector)
RET ;with value in HL
;
; set dma address given by registers b and c
;
SETDMA: LD A,C ;low order address
OUT (DMAL),A
LD A,B ;high order address
OUT (DMAH),A ;in dma
RET
;
; perform read operation
;
READ: XOR A ;read command -> A
JP WAITIO ;to perform the actual i/o
;
; perform a write operation
;
WRITE: LD A,1 ;write command -> A
;
; enter here from read and write to perform the actual i/o
; operation. return a 00h in register a if the operation completes
; properly, and 01h if an error occurs during the read or write
;
; in this case, we have saved the disk number in 'diskno' (0-3)
; the track number in 'track' (0-76)
; the sector number in 'sector' (1-26)
; the dma address in 'dmaad' (0-65535)
;
WAITIO: OUT (FDCOP),A ;start i/o operation
IN A,(FDCST) ;status of i/o operation -> A
RET
;
; the remainder of the CBIOS is reserved uninitialized
; data area, and does not need to be a part of the
; system memory image (the space must be available,
; however, between "begdat" and "enddat").
;
; scratch ram area for BDOS use
;
BEGDAT EQU $ ;beginning of data area
DIRBF: DEFS 128 ;scratch directory area
ALL00: DEFS 31 ;allocation vector 0
ALL01: DEFS 31 ;allocation vector 1
ALL02: DEFS 31 ;allocation vector 2
ALL03: DEFS 31 ;allocation vector 3
ALLHD: DEFS 255 ;allocation vector harddisk
CHK00: DEFS 16 ;check vector 0
CHK01: DEFS 16 ;check vector 1
CHK02: DEFS 16 ;check vector 2
CHK03: DEFS 16 ;check vector 3
CHKHD: DEFS 0 ;check vector harddisk
;
ENDDAT EQU $ ;end of data area
DATSIZ EQU $-BEGDAT ;size of data area
END ;of BIOS

View File

@@ -1,74 +0,0 @@
; CP/M 2.2 boot-loader for Z80-Simulator
;
; Copyright (C) 1988 by Udo Munk
;
ORG 0 ; mem base of boot
;
MSIZE EQU 64 ; mem size in kbytes
;
BIAS EQU (MSIZE-20)*1024 ; offset from 20k system
CCP EQU 3400H+BIAS ; base of the ccp
BIOS EQU CCP+1600H ; base of the bios
BIOSL EQU 0300H ; length of the bios
BOOT EQU BIOS
SIZE EQU BIOS+BIOSL-CCP ; size of cp/m system
SECTS EQU SIZE/128 ; # of sectors to load
;
; I/O ports
;
DRIVE EQU 10 ; fdc-port: # of drive
TRACK EQU 11 ; fdc-port: # of track
SECTOR EQU 12 ; fdc-port: # of sector
FDCOP EQU 13 ; fdc-port: command
FDCST EQU 14 ; fdc-port: status
DMAL EQU 15 ; dma-port: dma address low
DMAH EQU 16 ; dma-port: dma address high
;
; begin the load operation
;
COLD: LD BC,2 ; b=track 0, c=sector 2
LD D,SECTS ; d=# sectors to load
LD HL,CCP ; base transfer address
LD A,0 ; select drive A
OUT (DRIVE),A
;
; load the next sector
;
LSECT: LD A,B ; set track
OUT (TRACK),A
LD A,C ; set sector
OUT (SECTOR),A
LD A,L ; set dma address low
OUT (DMAL),A
LD A,H ; set dma adress high
OUT (DMAH),A
XOR A ; read sector
OUT (FDCOP),A
IN A,(FDCST) ; get status of fdc
CP 0 ; read successful ?
JP Z,CONT ; yes, continue
HALT ; no, halt cpu
CONT:
; go to next sector if load is incomplete
DEC D ; sects=sects-1
JP Z,BOOT ; head for the bios
;
; more sectors to load
;
; we aren't using a stack, so use <sp> as scratch register
; to hold the load address increment
;
LD SP,128 ; 128 bytes per sector
ADD HL,SP ; <hl> = <hl> + 128
;
INC C ; sector = sector + 1
LD A,C
CP 27 ; last sector of track ?
JP C,LSECT ; no, go read another
;
; end of track, increment to next track
;
LD C,1 ; sector = 1
INC B ; track = track + 1
JP LSECT ; for another group
END ; of boot loader

View File

@@ -1,69 +0,0 @@
/*
* CP/M 2.2 Formats a simulated Disk Drive
*
* Copyright (C) 1988-2006 by Udo Munk
*
* History:
* 29-APR-88 Development on TARGON/35 with AT&T Unix System V.3
* 11-MAR-93 comments in english
* 01-OCT-06 modified to compile on modern POSIX OS's
* 18-NOV-06 added a second harddisk
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <fcntl.h>
#define TRACK 77
#define SECTOR 26
#define HDTRACK 255
#define HDSECTOR 128
/*
* This program is able to format the following disk formats:
*
* drive A: 8" IBM SS,SD
* drive B: 8" IBM SS,SD
* drive C: 8" IBM SS,SD
* drive D: 8" IBM SS,SD
* drive I: 4MB harddisk
* drive J: 4MB harddisk
*/
int main(int argc, char *argv[])
{
register int i;
int fd;
char drive;
static unsigned char sector[128];
static char fn[] = "disks/drive?.cpm";
static char usage[] = "usage: format a | b | c | d | i | j";
if (argc != 2) {
puts(usage);
exit(1);
}
i = *argv[1];
if (argc != 2 ||
(i != 'a' && i != 'b' && i != 'c' && i != 'd' && i != 'i'
&& i != 'j')) {
puts(usage);
exit(1);
}
fn[11] = drive = (char) i;
memset((char *) sector, 0xe5, 128);
if ((fd = creat(fn, 0644)) == -1) {
perror("disk file");
exit(1);
}
if (drive != 'i' && drive != 'j') {
for (i = 0; i < TRACK * SECTOR; i++)
write(fd, (char *) sector, 128);
} else {
for (i = 0; i < HDTRACK * HDSECTOR; i++)
write(fd, (char *) sector, 128);
}
close(fd);
return(0);
}

View File

@@ -1,106 +0,0 @@
/*
* Write the CP/M systemfiles to system tracks of drive A
*
* Copyright (C) 1988-2006 by Udo Munk
*
* History:
* 29-APR-88 Development on TARGON/35 with AT&T Unix System V.3
* 11-MAR-93 comments in english and ported to COHERENT 4.0
* 02-OCT-06 modified to compile on modern POSIX OS's
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <memory.h>
/*
* This program writes the CP/M 2.2 OS from the following files
* onto the system tracks of the boot disk (drivea.cpm):
*
* boot loader boot.bin (Mostek binary format)
* CCP cpm.bin (binary format)
* BDOS cpm.bin (binary format)
* BIOS bios.bin (Mostek binary format)
*/
int main(void)
{
unsigned char header[3];
unsigned char sector[128];
register int i;
int fd, drivea, readed;
/* open drive A for writing */
if ((drivea = open("../disks/drivea.cpm", O_WRONLY)) == -1) {
perror("file ../disks/drivea.cpm");
exit(1);
}
/* open boot loader (boot.bin) for reading */
if ((fd = open("boot.bin", O_RDONLY)) == -1) {
perror("file boot.bin");
exit(1);
}
/* read and check 3 byte header */
if ((readed = read(fd, (char *) header, 3)) != 3) {
perror("file boot.bin");
exit(1);
}
if (header[0] != 0xff || header[1] != 0 || header[2] != 0) {
puts("start adress of boot.bin <> 0");
exit(0);
}
/* read boot loader */
memset((char *) sector, 0, 128);
read(fd, (char *) sector, 128);
close(fd);
/* and write it to disk in drive A */
write(drivea, (char *) sector, 128);
/* open CP/M system file (cpm.bin) for reading */
if ((fd = open("cpm.bin", O_RDONLY)) == -1) {
perror("file cpm.bin");
exit(1);
}
/* position to CCP in cpm.bin, needed if created with SAVE or similar */
lseek(fd, (long) 17 * 128, 0);
/* read CCP and BDOS from cpm.bin and write them to disk in drive A */
for (i = 0; i < 44; i++) {
if ((readed = read(fd, (char *) sector, 128)) != 128) {
perror("file cpm.bin");
exit(1);
}
write(drivea, (char *) sector, 128);
}
close(fd);
/* open BIOS (bios.bin) for reading */
if ((fd = open("bios.bin", O_RDONLY)) == -1) {
perror("file bios.bin");
exit(1);
}
/* read and check 3 byte header */
if ((readed = read(fd, (char *) header, 3)) != 3) {
perror("file bios.bin");
exit(1);
}
if (header[0] != 0xff) {
puts("unknown format of bios.bin");
exit(0);
}
/* read BIOS from bios.bin and write it to disk in drive A */
i = 0;
while ((readed = read(fd, (char *) sector, 128)) == 128) {
write(drivea, (char *) sector, 128);
i++;
if (i == 6) {
puts("6 sectors written, can't write any more!");
goto stop;
}
}
if (readed > 0) {
write(drivea, (char *) sector, 128);
}
stop:
close(fd);
close(drivea);
return(0);
}

View File

@@ -1,56 +0,0 @@
/*
* Receive a file out of the named pipe "auxout" from CP/M simulation
*
* Copyright (C) 1988-2006 by Udo Munk
*
* History:
* 05-OKT-88 Development on TARGON/35 with AT&T Unix System V.3
* 11-MAR-93 comments in english and ported to COHERENT 4.0
* 01-OCT-06 modified to compile on modern POSIX OS's
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
int fdin, fdout;
int main(int argc, char *argv[])
{
char c;
void int_handler(void);
if (argc != 2) {
puts("usage: receive filname &");
exit(1);
}
if ((fdin = open("auxout", O_RDONLY)) == -1) {
perror("pipe auxout");
exit(1);
}
if ((fdout = creat(argv[1], 0644)) == -1) {
perror(argv[1]);
exit(1);
}
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGHUP, int_handler);
for (;;) {
if (read(fdin, &c, 1) == 1)
if (c != '\r')
write(fdout, &c, 1);
}
return(0);
}
void int_handler(void)
{
close(fdin);
close(fdout);
exit(0);
}

View File

@@ -1,57 +0,0 @@
/*
* Sends a file through named pipe "auxin" to the CP/M simulation
*
* Copyright (C) 1988-2006 by Udo Munk
*
* History:
* 05-OKT-88 Development on TARGON/35 with AT&T Unix System V.3
* 11-MAR-93 comments in english and ported to COHERENT 4.0
* 01-OCT-06 modified to compile on modern POSIX OS's
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
void sendbuf(int);
char buf[BUFSIZ];
char cr = '\r';
int fdout, fdin;
int main(int argc,char *argv[])
{
register int readed;
if (argc != 2) {
puts("usage: send filname &");
exit(1);
}
if ((fdin = open(argv[1], O_RDONLY)) == -1) {
perror(argv[1]);
exit(1);
}
if ((fdout = open("auxin", O_WRONLY)) == -1) {
perror("pipe auxin");
exit(1);
}
while ((readed = read(fdin, buf, BUFSIZ)) == BUFSIZ)
sendbuf(BUFSIZ);
if (readed)
sendbuf(readed);
close(fdin);
close(fdout);
return(0);
}
void sendbuf(int size)
{
register char *s = buf;
while (s - buf < size) {
if (*s == '\n')
write(fdout, (char *) &cr, 1);
write(fdout, s++, 1);
}
}

View File

@@ -1,13 +0,0 @@
CFLAGS= -O -s
all: putsys boot.bin
echo done
putsys: putsys.c
cc $(CFLAGS) -o putsys putsys.c
boot.bin: boot.asm
z80asm -vl -sn -fb boot.asm
clean:
rm -f *.lis putsys boot.bin

View File

@@ -1,582 +0,0 @@
; CP/M 3 BIOS for Z80-Simulator
;
; Copyright (C) 1989-2006 by Udo Munk
;
.Z80
;
; bdos functions
;
WARM EQU 0
BDOS EQU 5
PRINT EQU 9
OPEN EQU 15
READS EQU 20
DMA EQU 26
MULTI EQU 44
;
; i/o ports
;
CONSTA EQU 0 ;console status port
CONDAT EQU 1 ;console data port
PRTSTA EQU 2 ;printer status port
PRTDAT EQU 3 ;printer data port
AUXSTA EQU 4 ;auxilary status port
AUXDAT EQU 5 ;auxilary data port
FDCD EQU 10 ;fdc-port: # of drive
FDCT EQU 11 ;fdc-port: # of track
FDCS EQU 12 ;fdc-port: # of sector
FDCOP EQU 13 ;fdc-port: command
FDCST EQU 14 ;fdc-port: status
DMAL EQU 15 ;dma-port: dma address low
DMAH EQU 16 ;dma-port: dma address high
MMUINI EQU 20 ;initialize mmu
MMUSEL EQU 21 ;bank select mmu
CLKCMD EQU 25 ;clock command
CLKDAT EQU 26 ;clock data
;
; clock commands
;
GETSEC EQU 0 ;get seconds
GETMIN EQU 1 ;get minutes
GETHOU EQU 2 ;get hours
GETDAL EQU 3 ;get days low
GETDAH EQU 4 ;get days high
;
; character device mode byte fields
;
mb$input EQU 00000001B ;device may do input
mb$output EQU 00000010B ;device may do output
mb$in$out EQU mb$input+mb$output ;device may do both
baud$none EQU 0
;
; external references in scb
;
EXTRN @civec, @covec, @aovec, @aivec, @lovec, @bnkbf
EXTRN @crdma, @crdsk, @fx, @resel, @vinfo, @usrcd
EXTRN @ermde, @date, @hour, @min, @sec, @mxtpa
;
CSEG
;
; cp/m 3 jump vector for individual subroutines
;
JP BOOT ;perform cold start initialization
WBOOTE: JP WBOOT ;perform warm start initialization
JP CONST ;check for console input char ready
JP CONIN ;read console character in
JP CONOUT ;write console character out
JP LIST ;write list character out
JP AUXOUT ;write auxiliary output char
JP AUXIN ;read auxiliary input char
JP HOME ;move head to track 0 on selcted disk
JP SELDSK ;select disk drive
JP SETTRK ;set track number
JP SETSEC ;set sector number
JP SETDMA ;set dma address
JP READ ;read specified sector
JP WRITE ;write specified sector
JP LISTST ;return list status
JP SECTRAN ;translate logical to physical sector
JP CONOST ;return output status of console
JP AUXIST ;return input status of aux. port
JP AUXOST ;return output status of aux. port
JP DEVTBL ;return address of character i/o table
JP DEVINI ;initialize character i/o devices
JP DRVTBL ;return address of disk drive table
JP MULTIO ;set number of sectors to read/write
JP FLUSH ;flush deblocking buffers
JP MOVE ;memory to memory move
JP TIME ;time set/get signal
JP SELMEM ;select bank of memory
JP SETBNK ;specify bank for dma operation
JP XMOVE ;set bank for memory dma transfer
JP 0 ;reserved for system implementor
JP 0 ;reserved for future use
JP 0 ;reserved for future use
;
; drive table
;
DRIVES: DW DPH0
DW DPH1
DW DPH2
DW DPH3
DW 0
DW 0
DW 0
DW 0
DW DPH8
DW DPH9
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
;
; fixed data tables for IBM-compatible 8" disks
;
; disk parameter header
;
DPH0: DEFW TRANS ;sector translation table
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
DB 0 ;media flag
DEFW DPB0 ;disk parameter block
DEFW 0FFFEH ;checksum vector
DEFW 0FFFEH ;allocation vector
DEFW 0FFFEH ;directory buffer control block
DEFW 0FFFFH ;dtabcb not used
DEFW 0FFFEH ;hashing
DEFB 0 ;hash bank
DPH1: DEFW TRANS ;sector translation table
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
DB 0 ;media flag
DEFW DPB0 ;disk parameter block
DEFW 0FFFEH ;checksum vector
DEFW 0FFFEH ;allocation vector
DEFW 0FFFEH ;directory buffer control block
DEFW 0FFFFH ;dtabcb not used
DEFW 0FFFEH ;hashing
DEFB 0 ;hash bank
DPH2: DEFW TRANS ;sector translation table
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
DB 0 ;media flag
DEFW DPB0 ;disk parameter block
DEFW 0FFFEH ;checksum vector
DEFW 0FFFEH ;allocation vector
DEFW 0FFFEH ;directory buffer control block
DEFW 0FFFFH ;dtabcb not used
DEFW 0FFFEH ;hashing
DEFB 0 ;hash bank
DPH3: DEFW TRANS ;sector translation table
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
DB 0 ;media flag
DEFW DPB0 ;disk parameter block
DEFW 0FFFEH ;checksum vector
DEFW 0FFFEH ;allocation vector
DEFW 0FFFEH ;directory buffer control block
DEFW 0FFFFH ;dtabcb not used
DEFW 0FFFEH ;hashing
DEFB 0 ;hash bank
;
; sector translate vector for the IBM 8" disk
;
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
DEFB 25,5,11,17 ;sectors 5,6,7,8
DEFB 23,3,9,15 ;sectors 9,10,11,12
DEFB 21,2,8,14 ;sectors 13,14,15,16
DEFB 20,26,6,12 ;sectors 17,18,19,20
DEFB 18,24,4,10 ;sectors 21,22,23,24
DEFB 16,22 ;sectors 25,26
;
; disk parameter block for the IBM 8" disk
;
DPB0: DEFW 26 ;sectors per track
DEFB 3 ;block shift factor
DEFB 7 ;block mask
DEFB 0 ;extent mask
DEFW 242 ;disk size-1
DEFW 63 ;directory max
DEFB 192 ;alloc 0
DEFB 0 ;alloc 1
DEFW 16 ;check size
DEFW 2 ;track offset
DEFB 0,0 ;physical sector size and shift
;
; fixed data tables for 4mb harddisks
;
; disk parameter header
;
DPH8: DEFW HDTRA ;sector translation table
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
DB 0 ;media flag
DEFW DPB1 ;disk parameter block
DEFW 0FFFEH ;checksum vector
DEFW 0FFFEH ;allocation vector
DEFW 0FFFEH ;directory buffer control block
DEFW 0FFFFH ;dtabcb not used
DEFW 0FFFEH ;hashing
DEFB 0 ;hash bank
DPH9: DEFW HDTRA ;sector translation table
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
DB 0 ;media flag
DEFW DPB1 ;disk parameter block
DEFW 0FFFEH ;checksum vector
DEFW 0FFFEH ;allocation vector
DEFW 0FFFEH ;directory buffer control block
DEFW 0FFFFH ;dtabcb not used
DEFW 0FFFEH ;hashing
DEFB 0 ;hash bank
;
; sector translate vector for 4mb harddisk
;
HDTRA: DEFB 1,2,3,4,5,6,7,8,9,10
DEFB 11,12,13,14,15,16,17,18,19,20
DEFB 21,22,23,24,25,26,27,28,29,30
DEFB 31,32,33,34,35,36,37,38,39,40
DEFB 41,42,43,44,45,46,47,48,49,50
DEFB 51,52,53,54,55,56,57,58,59,60
DEFB 61,62,63,64,65,66,67,68,69,70
DEFB 71,72,73,74,75,76,77,78,79,80
DEFB 81,82,83,84,85,86,87,88,89,90
DEFB 91,92,93,94,95,96,97,98,99,100
DEFB 101,102,103,104,105,106,107,108,109,110
DEFB 111,112,113,114,115,116,117,118,119,120
DEFB 121,122,123,124,125,126,127,128
;
; disk parameter block for 4mb harddisk
;
DPB1: DEFW 128 ;sectors per track
DEFB 4 ;block shift factor
DEFB 15 ;block mask
DEFB 0 ;extent mask
DEFW 2039 ;disk size-1
DEFW 1023 ;directory max
DEFB 255 ;alloc 0
DEFB 255 ;alloc 1
DEFW 0 ;check size
DEFW 0 ;track offset
DEFB 0,0 ;physical sector size and shift
;
; character device table
;
CHRTBL: DEFB 'CRT '
DEFB mb$in$out
DEFB baud$none
DEFB 'LPT '
DEFB mb$output
DEFB baud$none
DEFB 'PTP '
DEFB mb$output
DEFB baud$none
DEFB 'PTR '
DEFB mb$input
DEFB baud$none
DEFB 0
;
; signon message
;
SIGNON: DEFB 13,10
DEFM 'BANKED BIOS3 V1.4 for Z80SIM, '
DEFM 'Copyright 1989-2006 by Udo Munk'
DEFB 13,10
DEFB 0
;
; small stack
;
DS 8
STACK:
;
; fcb for loading ccp
;
CCPFCB: DEFB 1,'CCP COM',0,0,0,0
DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CCPREC: DEFB 0,0,0
;
DSEG
;
; bios error messages
;
CCPOER: DEFB 13,10,'BIOS ERROR: cannot open CCP.COM',13,10,'$'
CCPIOE: DEFB 13,10,'BIOS ERROR: reading CCP.COM',13,10,'$'
;
CSEG
;
DRIVE: DEFB 0 ;drive to select
BANK: DEFB 0 ;bank to select for dma
;
; end of fixed tables
;
; individual subroutines to perform each function
;
DSEG
;
BOOT: LD B,1 ;indicate cold boot
;
LD HL,8000H
LD (@civec),HL ;CONSOLE:=CON for input
LD (@covec),HL ;CONSOLE:=CON for output
LD HL,4000H
LD (@lovec),HL ;LST:=LPT
LD HL,2000H
LD (@aovec),HL ;AUXOUT:=PTP
LD HL,1000H
LD (@aivec),HL ;AUXIN:=PTR
;
LD A,3 ;initialize 3 memory banks
OUT (MMUINI),A
JP WBOOT1
;
CSEG
;
WBOOT: LD B,0 ;indicate warm boot
WBOOT1: LD SP,STACK
;
; initialize low memory jumps in bank 1
;
LD A,1
CALL SELMEM
;
LD A,0C3H ;jmp instruction
LD (WARM),A
LD HL,WBOOTE ;warm boot enty point
LD (WARM+1),HL
LD (BDOS),A
LD HL,(@mxtpa) ;bdos entry point
LD (BDOS+1),HL
;
; print message on cold boot
;
LD A,B
OR A
JP Z,LDCCP
LD HL,SIGNON ;print message
WBOOT2: LD A,(HL)
OR A
JP Z,LDCCP
LD C,A
CALL CONOUT
INC HL
JP WBOOT2
;
; load ccp.com into tpa
;
LDCCP: XOR A ;initialize fcb
LD (CCPFCB+15),A
LD HL,0
LD (CCPREC),HL
LD DE,CCPFCB ;open file ccp.com
LD C,OPEN
CALL BDOS
LD DE,CCPOER
INC A
JP Z,CCPERR ;print error if file not found
LD DE,0100H ;setup DMA to tpa
LD C,DMA
CALL BDOS
LD DE,128 ;read up to 16KB
LD C,MULTI
CALL BDOS
LD DE,CCPFCB ;read the ccp into memory
LD C,READS
CALL BDOS
LD DE,CCPIOE
INC A
JP NZ,0100H ;start ccp
CCPERR: LD C,PRINT ;print error message
CALL BDOS
HALT
;
; character i/o drivers
;
DEVTBL: LD HL,CHRTBL
RET
;
; character device initialization
;
DEVINI: RET
;
; console in status, return 0ffh if character ready, 00h if not
;
CONST: IN A,(CONSTA)
RET
;
; console character input from register a
;
CONIN: IN A,(CONDAT)
RET
;
; console out status, return 0ffh if ready, 00h if not
CONOST: LD A,0FFH ;console out always ready
RET
;
; console character output from register c
;
CONOUT: LD A,C ;get to accumulator
OUT (CONDAT),A ;send character to console
RET
;
; list out status, return 0ffh if ready, 00h if not
;
LISTST: LD A,0FFH ;list out always ready
RET
;
; list character output from register C
;
LIST: LD A,C
OUT (PRTDAT),A
RET
;
; auxilary input status, 0ffh if ready, 00h if not
;
AUXIST: XOR A ;never ready, hardware not available yet
RET
;
; auxilary output status, 0ffh if ready, 00h if not
;
AUXOST: XOR A ;never ready, hadware not available yet
RET
;
; auxilary input
;
AUXIN: IN A,(AUXDAT)
RET
;
; auxilary output from register c
;
AUXOUT: LD A,C
OUT (AUXDAT),A
RET
;
;
; i/o drivers for the disks
;
DRVTBL: LD HL,DRIVES
RET
;
DSEG
;
; move to the track 00 position of current drive
; translate this call into a settrk call with parameter 00
;
HOME: LD C,0 ;select track 0
JP SETTRK ;we will move to 00 on first read/write
;
; select disk given by register C
;
SELDSK: LD HL,0000H ;error return code
LD A,C
LD (DRIVE),A
CP 4 ;disk drive 1-4?
JP C,SEL1 ;go
CP 8 ;harddisk 1?
JP Z,SEL1 ;go
CP 9 ;harddisk 2?
RET NZ ;no, error
; disk number is in the proper range
; return proper disk parameter header address
SEL1: LD L,C
LD H,0
ADD HL,HL ;drive index in hl
LD BC,DRIVES
ADD HL,BC ;get pointer to dph
LD A,(HL)
INC HL
LD H,(HL)
LD L,A
LD A,(DRIVE)
OUT (FDCD),A ;selekt disk drive
RET
;
; set track given by register c
;
SETTRK: LD A,C
OUT (FDCT),A
RET
;
; set sector given by register c
;
SETSEC: LD A,C
OUT (FDCS),A
RET
;
; translate the sector given by bc using the
; translate table given by de
;
SECTRAN:
EX DE,HL ;hl=.trans
ADD HL,BC ;hl=.trans(sector)
LD L,(HL) ;l = trans(sector)
LD H,0 ;hl= trans(sector)
RET ;with value in HL
;
; set dma address given by registers b and c
;
SETDMA: LD A,C ;low order address
OUT (DMAL),A
LD A,B ;high order address
OUT (DMAH),A
RET
;
CSEG
;
; perform read operation
;
READ: LD A,(BANK) ;switch to saved bank
OUT (MMUSEL),A
XOR A ;read command -> A
JP WAITIO ;to perform the actual i/o
;
; perform write operation
;
WRITE: LD A,(BANK) ;switch to saved bank
OUT (MMUSEL),A
LD A,1 ;write command -> A
;
; enter here from read and write to perform the actual i/o
; operation. return 00h in register a if the operation completes
; properly, and 01h if an error occurs during the read or write
;
WAITIO: OUT (FDCOP),A ;start i/o operation
XOR A ;reselect bank 0
OUT (MMUSEL),A
IN A,(FDCST) ;status of i/o operation -> A
RET
;
; nothing to do
;
MULTIO: XOR A
RET
;
; nothing to do
;
FLUSH: XOR A
RET
;
; memory move
;
MOVE: EX DE,HL
LDIR
EX DE,HL
RET
;
; select memory bank
SELMEM: OUT (MMUSEL),A
RET
;
; specify memory bank for dma operation
SETBNK: LD (BANK),A
RET
;
; xmove not implemented yet, hardware missing
;
XMOVE: RET
;
; get/set time
;
TIME:
LD A,C
CP 0FFH
RET Z ;we cannot set the UNIX time from here
LD A,GETSEC ;get seconds
OUT (CLKCMD),A
IN A,(CLKDAT)
LD (@sec),A
LD A,GETMIN ;get minutes
OUT (CLKCMD),A
IN A,(CLKDAT)
LD (@min),A
LD A,GETHOU ;get hours
OUT (CLKCMD),A
IN A,(CLKDAT)
LD (@hour),A
LD A,GETDAL ;get day
OUT (CLKCMD),A
IN A,(CLKDAT)
LD (@date),A
LD A,GETDAH
OUT (CLKCMD),A
IN A,(CLKDAT)
LD (@date+1),A
RET
;
ENDDAT EQU $ ;end
END ;of BIOS

View File

@@ -1,67 +0,0 @@
; CP/M 3 boot-loader for Z80-Simulator
;
; Copyright (C) 1989-2006 by Udo Munk
;
ORG 0 ; mem base of boot
;
BOOT EQU 0100H ; cpmldr runs at 0100H
SECTS EQU 51 ; # of sectors to load (26 * 2 - 1)
;
; I/O ports
;
DRIVE EQU 10 ; fdc-port: # of drive
TRACK EQU 11 ; fdc-port: # of track
SECTOR EQU 12 ; fdc-port: # of sector
FDCOP EQU 13 ; fdc-port: command
FDCST EQU 14 ; fdc-port: status
DMAL EQU 15 ; dma-port: dma address low
DMAH EQU 16 ; dma-port: dma address high
;
; begin the load operation
;
COLD: LD BC,2 ; b=track 0, c=sector 2
LD D,SECTS ; d=# sectors to load
LD HL,BOOT ; base transfer address
LD A,0 ; select drive A
OUT (DRIVE),A
;
; load the next sector
;
LSECT: LD A,B ; set track
OUT (TRACK),A
LD A,C ; set sector
OUT (SECTOR),A
LD A,L ; set dma address low
OUT (DMAL),A
LD A,H ; set dma adress high
OUT (DMAH),A
XOR A ; read sector
OUT (FDCOP),A
IN A,(FDCST) ; get status of fdc
CP 0 ; read successful ?
JP Z,CONT ; yes, continue
HALT ; no, halt cpu
CONT:
; go to next sector if load is incomplete
DEC D ; sects=sects-1
JP Z,BOOT ; head for the bios
;
; more sectors to load
;
; we aren't using a stack, so use <sp> as scratch register
; to hold the load address increment
;
LD SP,128 ; 128 bytes per sector
ADD HL,SP ; <hl> = <hl> + 128
;
INC C ; sector = sector + 1
LD A,C
CP 27 ; last sector of track ?
JP C,LSECT ; no, go read another
;
; end of track, increment to next track
;
LD C,1 ; sector = 1
INC B ; track = track + 1
JP LSECT ; for another group
END ; of boot loader

View File

@@ -1,212 +0,0 @@
; CP/M 3 LDRBIOS for Z80-Simulator
;
; Copyright (C) 1989-2006 by Udo Munk
;
.Z80
;
; I/O ports
;
CONSTA EQU 0 ;console status port
CONDAT EQU 1 ;console data port
FDCD EQU 10 ;fdc-port: # of drive
FDCT EQU 11 ;fdc-port: # of track
FDCS EQU 12 ;fdc-port: # of sector
FDCOP EQU 13 ;fdc-port: command
FDCST EQU 14 ;fdc-port: status
DMAL EQU 15 ;dma-port: dma address low
DMAH EQU 16 ;dma-port: dma address high
;
CSEG
;
; jump vector for individual subroutines
; * needs to be implemented
;
JP BOOT ; * perform cold start initialization
JP WBOOT ; perform warm start initialization
JP CONST ; check for console input char ready
JP CONIN ; read console character in
JP CONOUT ; * write console character out
JP LIST ; write list character out
JP AUXOUT ; write auxiliary output char
JP AUXIN ; read auxiliary input char
JP HOME ; * move head to track 0 on selcted disk
JP SELDSK ; * select disk drive
JP SETTRK ; * set track number
JP SETSEC ; * set sector number
JP SETDMA ; * set dma address
JP READ ; * read specified sector
JP WRITE ; write specified sector
JP LISTST ; return list status
JP SECTRAN ; * translate logical to physical sector
JP CONOST ; return output status of console
JP AUXIST ; return input status of aux. port
JP AUXOST ; return output status of aux. port
JP DEVTBL ; return address of character i/o table
JP DEVINI ; initialize character i/o devices
JP DRVTBL ; return address of disk drive table
JP MULTIO ; set number of sectors to read/write
JP FLUSH ; flush deblocking buffers
JP MOVE ; * memory to memory move
JP TIME ; time set/get signal
JP SELMEM ; select bank of memory
JP SETBNK ; specify bank for dma operation
JP XMOVE ; set bank for memory dma transfer
JP 0 ; reserved for system implementor
JP 0 ; reserved for future use
JP 0 ; reserved for future use
;
; fixed data tables for a IBM-compatible 8" disk
;
; disk parameter header
;
DPH0: DEFW TRANS ;sector translation table
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
DB 0 ;media flag
DEFW DPB0 ;disk parameter block
DEFW 0FFFEH ;checksum vector
DEFW 0FFFEH ;allocation vector
DEFW 0FFFEH ;directory buffer control block
DEFW 0FFFFH ;dtabcb not used
DEFW 0FFFFH ;hashing not used
DEFB 0 ;hash bank
;
; sector translate vector for the IBM 8" disk
;
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
DEFB 25,5,11,17 ;sectors 5,6,7,8
DEFB 23,3,9,15 ;sectors 9,10,11,12
DEFB 21,2,8,14 ;sectors 13,14,15,16
DEFB 20,26,6,12 ;sectors 17,18,19,20
DEFB 18,24,4,10 ;sectors 21,22,23,24
DEFB 16,22 ;sectors 25,26
;
; disk parameter block for the IBM 8" disk
;
DPB0: DEFW 26 ;sectors per track
DEFB 3 ;block shift factor
DEFB 7 ;block mask
DEFB 0 ;extent mask
DEFW 242 ;disk size-1
DEFW 63 ;directory max
DEFB 192 ;alloc 0
DEFB 0 ;alloc 1
DEFW 16 ;check size
DEFW 2 ;track offset
DEFB 0,0 ;physical sector size and shift
;
; signon message
;
SIGNON: DEFB 13,10
DEFM 'LDRBIOS3 V1.1 for Z80SIM, '
DEFM 'Copyright 1989-2006 by Udo Munk'
DEFB 13,10,0
;
; end of fixed tables
;
; individual subroutines to perform each function
;
BOOT: LD HL,SIGNON ;print message
BOOTL: LD A,(HL)
OR A
JP Z,WBOOT
LD C,A
CALL CONOUT
INC HL
JP BOOTL
;
; those are not implemented in loader bios
;
WBOOT:
CONST:
CONIN:
LIST:
AUXOUT:
AUXIN:
WRITE:
LISTST:
CONOST:
AUXIST:
AUXOST:
DEVTBL:
DEVINI:
DRVTBL:
MULTIO:
FLUSH:
TIME:
SELMEM:
SETBNK:
XMOVE: RET
;
; console character output from register c
;
CONOUT: LD A,C ;get to accumulator
OUT (CONDAT),A ;send character to console
RET
;
;
; i/o drivers for the disk follow
;
; move to the track 00 position of current drive
; translate this call into a settrk call with parameter 00
;
HOME: LD C,0 ;select track 0
JP SETTRK ;we will move to 00 on first read/write
;
; select disk given by register C
;
SELDSK: LD HL,0000H ;error return code
LD A,C
CP 0 ;we boot from drive 0 only
RET NZ ;return error
; disk number is in the proper range
; return proper disk parameter header address
OUT (FDCD),A ;selekt disk drive
LD HL,DPH0
RET
;
; set track given by register c
;
SETTRK: LD A,C
OUT (FDCT),A
RET
;
; set sector given by register c
;
SETSEC: LD A,C
OUT (FDCS),A
RET
;
; translate the sector given by BC using the
; translate table given by DE
;
SECTRAN:
EX DE,HL ;hl=.trans
ADD HL,BC ;hl=.trans(sector)
LD L,(HL) ;l = trans(sector)
LD H,0 ;hl= trans(sector)
RET ;with value in hl
;
; set dma address given by registers b and c
;
SETDMA: LD A,C ;low order address
OUT (DMAL),A
LD A,B ;high order address
OUT (DMAH),A ;in dma
RET
;
; perform read operation
;
READ: XOR A ;read command -> a
OUT (FDCOP),A ;start i/o operation
IN A,(FDCST) ;status of i/o operation -> a
RET
;
; memory move
;
MOVE: EX DE,HL
LDIR
EX DE,HL
RET
;
ENDDAT EQU $ ;end
END ;of bios

View File

@@ -1,59 +0,0 @@
/*
* Write the CP/M 3 systemfiles to system tracks of drive A
*
* Copyright (C) 1988-2006 by Udo Munk
*
* History:
* 29-APR-88 Development on TARGON/35 with AT&T Unix System V.3
* 11-MAR-93 comments in english and ported to COHERENT 4.0
* 02-OCT-06 modified to compile on modern POSIX OS's
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <memory.h>
/*
* This program writes the CP/M 3 OS from the following files
* onto the system tracks of the boot disk (drivea.cpm):
*
* boot loader boot.bin
* cpmldr cpmldr.bin
*/
int main(void)
{
unsigned char sector[128];
register int i;
int fd, drivea, readed;
/* open drive A for writing */
if ((drivea = open("../disks/drivea.cpm", O_WRONLY)) == -1) {
perror("file ../disks/drivea.cpm");
exit(1);
}
/* open boot loader (boot.bin) for reading */
if ((fd = open("boot.bin", O_RDONLY)) == -1) {
perror("file boot.bin");
exit(1);
}
/* read boot loader */
memset((char *) sector, 0, 128);
read(fd, (char *) sector, 128);
close(fd);
/* and write it to disk in drive A */
write(drivea, (char *) sector, 128);
/* open CP/M 3 cpmldr file (cpmldr.bin) for reading */
if ((fd = open("cpmldr.bin", O_RDONLY)) == -1) {
perror("file cpmldr.bin");
exit(1);
}
/* read from cpmldr.bin and write to disk in drive A */
while ((readed = read(fd, (char *) sector, 128)) == 128)
write(drivea, (char *) sector, 128);
write(drivea, (char *) sector, 128);
close(fd);
close(drivea);
return(0);
}

View File

@@ -1,503 +0,0 @@
; MP/M 2 XIOS for Z80-Simulator
;
; Copyright (C) 1989-2006 by Udo Munk
;
.Z80
CSEG
;
; i/o ports
;
CONSTA EQU 0 ;console status port
CONDAT EQU 1 ;console data port
PRTSTA EQU 2 ;printer status port
PRTDAT EQU 3 ;printer data port
AUXSTA EQU 4 ;auxilary status port
AUXDAT EQU 5 ;auxilary data port
FDCD EQU 10 ;fdc-port: # of drive
FDCT EQU 11 ;fdc-port: # of track
FDCS EQU 12 ;fdc-port: # of sector
FDCOP EQU 13 ;fdc-port: command
FDCST EQU 14 ;fdc-port: status
DMAL EQU 15 ;dma-port: dma address low
DMAH EQU 16 ;dma-port: dma address high
MMUINI EQU 20 ;initialize mmu
MMUSEL EQU 21 ;bank select mmu
CLKCMD EQU 25 ;clock command
CLKDAT EQU 26 ;clock data
TIMER EQU 27 ;interrupt timer
;
; clock commands
;
GETSEC EQU 0 ;get seconds
GETMIN EQU 1 ;get minutes
GETHOU EQU 2 ;get hours
GETDAL EQU 3 ;get days low
GETDAH EQU 4 ;get days high
;
BDOS EQU 5 ;bdos calls
SETTD EQU 104 ;bdos set time and date
;
POLL EQU 131 ;xdos poll function
PLCI0 EQU 0 ;poll console in #0
FLAGSET EQU 133 ;xdos flag set function
SYSDATA EQU 154 ;xdos syste data address
;
; jump vector for individual subroutines
;
JP COMMONBASE ;commonbase
JP WARMSTART ;warm start
JP CONST ;console status
JP CONIN ;console character in
JP CONOUT ;console character out
JP LIST ;list character out
JP PUNCH ;not used by MP/M 2
JP READER ;not used by MP/M 2
JP HOME ;move head to home
JP SELDSK ;select disk
JP SETTRK ;set track numer
JP SETSEC ;set sector number
JP SETDMA ;set dma address
JP READ ;read disk
JP WRITE ;write disk
JP LISTST ;not used by MP/M 2
JP SECTRAN ;sector translate
JP SELMEMORY ;select memory
JP POLLDEVICE ;poll device
JP STARTCLOCK ;start clock
JP STOPCLOCK ;stop clock
JP EXITREGION ;exit region
JP MAXCONSOLE ;maximum console number
JP SYSTEMINIT ;system initialization
JP IDLE ;idle prozedure
;
COMMONBASE:
JP COLDSTART
SWTUSER:
JP $-$
SWTSYS: JP $-$
PDISP: JP $-$
XDOS: JP $-$
SYSDAT: DEFW $-$
;
COLDSTART:
WARMSTART:
LD C,0
JP XDOS ;system reset, terminate prozess
;
; MP/M II V2.0 Console Bios
;
CONST:
CALL PTBLJMP ;compute and jump to handler
DW PTSTI0
;
CONIN:
CALL PTBLJMP ;compute and jump to handle
DW PTIN0
;
CONOUT:
CALL PTBLJMP ;compute and jump to handler
DW PTOUT0
;
PTSTI0: IN A,(CONSTA) ;console 0 input
RET
;
PTIN0: LD C,POLL ;poll console 0 status in
LD E,PLCI0
CALL XDOS ;poll console 0
IN A,(CONDAT) ;read character
AND 7FH ;strip parity
RET
;
PTOUT0: LD A,C ;console 0 output
OUT (CONDAT),A
RET
;
PTBLJMP: ;compute and jump to handler
LD A,D
ADD A,A ;double table index for adress offset
POP HL ;return adress of jump table
LD E,A
LD D,0
ADD HL,DE ;table index * 2 + table base
LD E,(HL) ;get handler address
INC HL
LD D,(HL)
EX DE,HL
JP (HL) ;jump to computed handler
;
LIST:
LD A,C
OUT (PRTDAT),A
RET
;
; not used by MP/M 2
PUNCH:
READER:
LISTST:
RET
;
; MP/M II V2.0 Xios
;
; select/protect memory
; BC = address of memory descriptor
SELMEMORY:
LD HL,3 ;offset memory bank in memory descriptor
ADD HL,BC
LD A,(HL) ;get bank
OUT (MMUSEL),A ;and select it
RET
;
; poll character devices
;
POLLDEVICE:
JP PTSTI0 ;poll console 0 status in
;
; start clock
;
STARTCLOCK:
LD A,0FFH
LD (TICKN),A
RET
;
; stop clock
;
STOPCLOCK:
XOR A
LD (TICKN),A
RET
;
; exit region:
; enable interrupt if not preempted or in dispatcher
;
EXITREGION:
LD A,(PREEMP)
OR A
RET NZ
EI
RET
;
; maximum console number
;
MAXCONSOLE:
LD A,1
RET
;
; system initialization
; C MP/M debugger restart #
; DE MP/M entry point for debugger
; HL BIOS jump table address
;
SYSTEMINIT:
;
;doesn't work
PUSH HL
LD C,SYSDATA ;get system data page address
CALL XDOS
CALL SETTOD ;set tod from hardware clock
POP HL
;
LD A,8 ;initialize banked memory
OUT (MMUINI),A
LD B,A
;
SYS1: DEC B
LD A,B
OUT (MMUSEL),A ;select every bank and initialize
LD A,0C3H ;jp instruction
LD (0),A
LD (38H),A
LD (1),HL
PUSH HL
LD HL,INTHND
LD (39H),HL
POP HL
JP NZ,SYS1
;
LD HL,SIGNON ;print message
SYS2: LD A,(HL)
OR A
JP Z,SYS3
OUT (CONDAT),A
INC HL
JP SYS2
;
SYS3: IM 1
LD A,1 ;enable 20ms interrupt timer
OUT (TIMER),A
EI
RET
;
; set mp/m tod from hardware clock
; hl = tod address
;
SETTOD: LD A,GETDAL
OUT (CLKCMD),A
IN A,(CLKDAT)
LD (HL),A
INC HL
LD A,GETDAH
OUT (CLKCMD),A
IN A,(CLKDAT)
LD (HL),A
INC HL
LD A,GETHOU
OUT (CLKCMD),A
IN A,(CLKDAT)
LD (HL),A
INC HL
LD A,GETMIN
OUT (CLKCMD),A
IN A,(CLKDAT)
LD (HL),A
RET
;
; idle
;
IDLE: EI
HALT
RET
;
; interrupt handler
;
INTHND: LD (SVDHL),HL ;save registers
POP HL
LD (SVDRET),HL
PUSH AF
LD HL,0
ADD HL,SP
LD (SVDSP),HL
LD SP,INTSTK
PUSH DE
PUSH BC
LD A,0FFH ;set preempted flag
LD (PREEMP),A
LD A,(TICKN)
OR A ;test tick, indicates delayed process
JP Z,INTHND1
LD C,FLAGSET ;set flag #1 each tick
LD E,1
CALL XDOS
INTHND1:
LD HL,CNT50 ;decrement tick counter
DEC (HL)
JP NZ,INTDONE
LD (HL),50 ;set flag #2 each second
LD C,FLAGSET
LD E,2
CALL XDOS
INTDONE:
XOR A ;clear preempted flag
LD (PREEMP),A
POP BC ;restore registers
POP DE
LD HL,(SVDSP)
LD SP,HL
POP AF
LD HL,(SVDRET)
PUSH HL
LD HL,(PDISP+1) ;dispatch processes
PUSH HL
LD HL,(SVDHL)
RETI
;
; i/o drivers for disks
;
; move to the track 00 position of current drive
; translate this call into a settrk call with parameter 00
;
HOME: LD C,0 ;select track 0
JP SETTRK ;we will move to 00 on first read/write
;
; select disk given by register C
;
SELDSK: LD HL,0000H ;error return code
LD A,C
CP 4 ;must be between 0 and 3
JR NC,SELHD ;no carry if 4,5,...
; disk number is in the proper range
; compute proper disk parameter header address
OUT (FDCD),A ;selekt disk drive
LD L,A ;L=disk number 0,1,2,3
ADD HL,HL ;*2
ADD HL,HL ;*4
ADD HL,HL ;*8
ADD HL,HL ;*16 (size of each header)
LD DE,DPBASE
ADD HL,DE ;HL=.dpbase(diskno*16)
RET
SELHD: CP 8 ;select the harddisk?
RET NZ ;no, error
OUT (FDCD),A ;select disk drive
LD HL,HDBASE ;HL=hdbase for harddisk
RET
;
; set track given by register c
;
SETTRK: LD A,C
OUT (FDCT),A
RET
;
; set sector given by register c
;
SETSEC: LD A,C
OUT (FDCS),A
RET
;
; translate the sector given by BC using the
; translate table given by DE
;
SECTRAN:
EX DE,HL ;HL=.trans
ADD HL,BC ;HL=.trans(sector)
LD L,(HL) ;L = trans(sector)
LD H,0 ;HL= trans(sector)
RET ;with value in HL
;
; set dma address given by registers b and c
;
SETDMA: LD A,C ;low order address
OUT (DMAL),A
LD A,B ;high order address
OUT (DMAH),A ;in dma
RET
;
; perform read operation
;
READ: XOR A ;read command -> A
JP WAITIO ;to perform the actual i/o
;
; perform a write operation
;
WRITE: LD A,1 ;write command -> A
;
; enter here from read and write to perform the actual i/o
; operation. return a 00h in register a if the operation completes
; properly, and 01h if an error occurs during the read or write
;
; in this case, we have saved the disk number in 'diskno' (0-3)
; the track number in 'track' (0-76)
; the sector number in 'sector' (1-26)
; the dma address in 'dmaad' (0-65535)
;
WAITIO: OUT (FDCOP),A ;start i/o operation
IN A,(FDCST) ;status of i/o operation -> A
RET
;
; XIOS data segment
;
SIGNON: DEFB 13,10
DEFM 'MP/M 2 XIOS V1.1 for Z80SIM, '
DEFM 'Copyright 1989-2006 by Udo Munk'
DEFB 13,10,0
;
TICKN: DEFB 0 ;flag for tick
PREEMP: DEFB 0 ;preempted flag
TOD: DEFS 4 ;time of day
SVDHL: DEFS 2 ;save hl during interrupt
SVDRET: DEFS 2 ;save return address during interrupt
SVDSP: DEFS 2 ;save sp during interrupt
CNT50: DEFB 50 ;50 ticks a 20ms = 1 second
;interrupt stack
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
INTSTK:
;
; fixed data tables for four-drive standard
; IBM-compatible 8" disks
;
; disk parameter header for disk 00
DPBASE: DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK00,ALL00
; disk parameter header for disk 01
DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK01,ALL01
; disk parameter header for disk 02
DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK02,ALL02
; disk parameter header for disk 03
DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK03,ALL03
;
; sector translate vector for the IBM 8" disks
;
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
DEFB 25,5,11,17 ;sectors 5,6,7,8
DEFB 23,3,9,15 ;sectors 9,10,11,12
DEFB 21,2,8,14 ;sectors 13,14,15,16
DEFB 20,26,6,12 ;sectors 17,18,19,20
DEFB 18,24,4,10 ;sectors 21,22,23,24
DEFB 16,22 ;sectors 25,26
;
; disk parameter block, common to all IBM 8" disks
;
DPBLK: DEFW 26 ;sectors per track
DEFB 3 ;block shift factor
DEFB 7 ;block mask
DEFB 0 ;extent mask
DEFW 242 ;disk size-1
DEFW 63 ;directory max
DEFB 192 ;alloc 0
DEFB 0 ;alloc 1
DEFW 16 ;check size
DEFW 2 ;track offset
;
; fixed data tables for 4MB harddisk
;
; disk parameter header
HDBASE: DEFW HDTRA,0000H
DEFW 0000H,0000H
DEFW DIRBF,HDBLK
DEFW CHKHD,ALLHD
;
; sector translate vector for the hardisk
;
HDTRA: DEFB 1,2,3,4,5,6,7,8,9,10
DEFB 11,12,13,14,15,16,17,18,19,20
DEFB 21,22,23,24,25,26,27,28,29,30
DEFB 31,32,33,34,35,36,37,38,39,40
DEFB 41,42,43,44,45,46,47,48,49,50
DEFB 51,52,53,54,55,56,57,58,59,60
DEFB 61,62,63,64,65,66,67,68,69,70
DEFB 71,72,73,74,75,76,77,78,79,80
DEFB 81,82,83,84,85,86,87,88,89,90
DEFB 91,92,93,94,95,96,97,98,99,100
DEFB 101,102,103,104,105,106,107,108,109,110
DEFB 111,112,113,114,115,116,117,118,119,120
DEFB 121,122,123,124,125,126,127,128
;
; disk parameter block for harddisk
;
HDBLK: DEFW 128 ;sectors per track
DEFB 4 ;block shift factor
DEFB 15 ;block mask
DEFB 0 ;extent mask
DEFW 2039 ;disk size-1
DEFW 1023 ;directory max
DEFB 255 ;alloc 0
DEFB 255 ;alloc 1
DEFW 0 ;check size
DEFW 0 ;track offset
;
DIRBF: DEFS 128 ;scratch directory area
ALL00: DEFS 31 ;allocation vector 0
ALL01: DEFS 31 ;allocation vector 1
ALL02: DEFS 31 ;allocation vector 2
ALL03: DEFS 31 ;allocation vector 3
ALLHD: DEFS 255 ;allocation vector harddisk
CHK00: DEFS 16 ;check vector 0
CHK01: DEFS 16 ;check vector 1
CHK02: DEFS 16 ;check vector 2
CHK03: DEFS 16 ;check vector 3
CHKHD: DEFS 0 ;check vector harddisk
;
END

View File

@@ -1,177 +0,0 @@
; MP/M 2 LDRBIOS for Z80-Simulator
;
; Copyright (C) 1989-2006 by Udo Munk
;
ORG 1700H
;
; I/O ports
;
CONSTA EQU 0 ;console status port
CONDAT EQU 1 ;console data port
FDCD EQU 10 ;fdc-port: # of drive
FDCT EQU 11 ;fdc-port: # of track
FDCS EQU 12 ;fdc-port: # of sector
FDCOP EQU 13 ;fdc-port: command
FDCST EQU 14 ;fdc-port: status
DMAL EQU 15 ;dma-port: dma address low
DMAH EQU 16 ;dma-port: dma address high
;
; jump vector for individual subroutines
;
JP BOOT ;perform cold start initialization
JP WBOOT ;perform warm start initialization
JP CONST ;check for console input char ready
JP CONIN ;read console character in
JP CONOUT ;write console character out
JP LIST ;write list character out
JP AUXOUT ;write auxiliary output char
JP AUXIN ;read auxiliary input char
JP HOME ;move head to track 0 on selcted disk
JP SELDSK ;select disk drive
JP SETTRK ;set track number
JP SETSEC ;set sector number
JP SETDMA ;set dma address
JP READ ;read specified sector
JP WRITE ;write specified sector
JP LISTST ;return list status
JP SECTRAN ;translate logical to physical sector
;
; fixed data tables for a IBM-compatible 8" disk
;
; disk parameter header
;
DPH: DEFW TRANS,0000H
DEFW 0000H,0000H
DEFW DIRBF,DPBLK
DEFW CHK00,ALL00
;
; sector translate vector for the IBM 8" disk
;
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
DEFB 25,5,11,17 ;sectors 5,6,7,8
DEFB 23,3,9,15 ;sectors 9,10,11,12
DEFB 21,2,8,14 ;sectors 13,14,15,16
DEFB 20,26,6,12 ;sectors 17,18,19,20
DEFB 18,24,4,10 ;sectors 21,22,23,24
DEFB 16,22 ;sectors 25,26
;
; disk parameter block for the IBM 8" disk
;
DPBLK: DEFW 26 ;sectors per track
DEFB 3 ;block shift factor
DEFB 7 ;block mask
DEFB 0 ;extent mask
DEFW 242 ;disk size-1
DEFW 63 ;directory max
DEFB 192 ;alloc 0
DEFB 0 ;alloc 1
DEFW 16 ;check size
DEFW 2 ;track offset
;
; signon message
;
SIGNON: DEFB 13,10
DEFM 'LDRBIOS V1.0 for Z80SIM, '
DEFM 'Copyright 1989-2006 by Udo Munk'
DEFB 13,10,0
;
; end of fixed tables
;
; individual subroutines to perform each function
;
BOOT: LD HL,SIGNON ;print message
BOOTL: LD A,(HL)
OR A
JP Z,WBOOT
LD C,A
CALL CONOUT
INC HL
JP BOOTL
;
; those are not implemented in loader bios
;
WBOOT:
CONST:
CONIN:
LIST:
AUXOUT:
AUXIN:
WRITE:
LISTST:
RET
;
; console character output from register c
;
CONOUT: LD A,C ;get to accumulator
OUT (CONDAT),A ;send character to console
RET
;
;
; i/o drivers for the disk follow
;
; move to the track 00 position of current drive
; translate this call into a settrk call with parameter 00
;
HOME: LD C,0 ;select track 0
JP SETTRK ;we will move to 00 on first read/write
;
; select disk given by register C
;
SELDSK: PUSH BC
CALL BOOT ;signon message
POP BC
LD HL,0000H ;error return code
LD A,C
CP 0 ;we boot from drive 0 only
RET NZ ;return error
; disk number is in the proper range
; return proper disk parameter header address
OUT (FDCD),A ;selekt disk drive
LD HL,DPH
RET
;
; set track given by register c
;
SETTRK: LD A,C
OUT (FDCT),A
RET
;
; set sector given by register c
;
SETSEC: LD A,C
OUT (FDCS),A
RET
;
; translate the sector given by BC using the
; translate table given by DE
;
SECTRAN:
EX DE,HL ;hl=.trans
ADD HL,BC ;hl=.trans(sector)
LD L,(HL) ;l = trans(sector)
LD H,0 ;hl= trans(sector)
RET ;with value in hl
;
; set dma address given by registers b and c
;
SETDMA: LD A,C ;low order address
OUT (DMAL),A
LD A,B ;high order address
OUT (DMAH),A ;in dma
RET
;
; perform read operation
;
READ: XOR A ;read command -> a
OUT (FDCOP),A ;start i/o operation
IN A,(FDCST) ;status of i/o operation -> a
RET
;
BEGDAT EQU $
DIRBF: DEFS 128 ;scratch directory area
ALL00: DEFS 31 ;allocation vector
CHK00: DEFS 16 ;check vector
;
ENDDAT EQU $ ;end
DATSIZ EQU $-BEGDAT ;size of data area
END ;of bios

View File

@@ -1,74 +0,0 @@
CFLAGS= -O -c -Wall
LFLAGS= -s
OBJ = sim0.o \
sim1.o \
sim2.o \
sim3.o \
sim4.o \
sim5.o \
sim6.o \
sim7.o \
simctl.o \
simint.o \
iosim.o \
simfun.o \
simglb.o
all: ../auxin ../auxout ../cpmsim
@echo "done."
../auxin:
test -f ../auxin || mknod ../auxin p
../auxout:
test -f ../auxout || mknod ../auxout p
../cpmsim : $(OBJ)
cc $(OBJ) $(LFLAGS) -o ../cpmsim
sim0.c:
lnsrc
sim0.o : sim0.c sim.h simglb.h
cc $(CFLAGS) sim0.c
sim1.o : sim1.c sim.h simglb.h
cc $(CFLAGS) sim1.c
sim2.o : sim2.c sim.h simglb.h
cc $(CFLAGS) sim2.c
sim3.o : sim3.c sim.h simglb.h
cc $(CFLAGS) sim3.c
sim4.o : sim4.c sim.h simglb.h
cc $(CFLAGS) sim4.c
sim5.o : sim5.c sim.h simglb.h
cc $(CFLAGS) sim5.c
sim6.o : sim6.c sim.h simglb.h
cc $(CFLAGS) sim6.c
sim7.o : sim7.c sim.h simglb.h
cc $(CFLAGS) sim7.c
simctl.o : simctl.c sim.h simglb.h
cc $(CFLAGS) simctl.c
simint.o : simint.c sim.h simglb.h
cc $(CFLAGS) simint.c
iosim.o : iosim.c sim.h simglb.h
cc $(CFLAGS) iosim.c
simfun.o : simfun.c sim.h
cc $(CFLAGS) simfun.c
simglb.o : simglb.c sim.h
cc $(CFLAGS) simglb.c
clean:
rm -f *.o
ulnsrc

View File

@@ -1,868 +0,0 @@
/*
* Z80SIM - a Z80-CPU simulator
*
* Copyright (C) 1987-2006 by Udo Munk
*
* This modul contains a complex I/O-simulation for running
* CP/M 2, CP/M 3, MP/M...
* Please note this this doesn't emulate any hardware which
* ever existed, we've got all virtual circuits in here!
*
* History:
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
* 19-MAY-89 Additions for CP/M 3.0 und MP/M
* 23-DEC-90 Ported to COHERENT 3.0
* 10-JUN-92 Some optimization done
* 25-JUN-92 Flush output of stdout only at every OUT to port 0
* 25-JUN-92 Comments in english and ported to COHERENT 4.0
* 05-OCT-06 modified to compile on modern POSIX OS's
* 18-NOV-06 added a second harddisk
*/
/*
* This module contains the I/O handlers for a simulation
* of the hardware required for a CP/M system.
*
* Used I/O ports:
*
* 0 - console status
* 1 - console data
*
* 2 - printer status
* 3 - printer data
*
* 4 - auxilary status
* 5 - auxilary data
*
* 10 - FDC drive
* 11 - FDC track
* 12 - FDC sector
* 13 - FDC command
* 14 - FDC status
*
* 15 - DMA destination address low
* 16 - DMA destination address high
*
* 20 - MMU initialization
* 21 - MMU bank select
*
* 25 - clock command
* 26 - clock data
* 27 - 20ms timer causing INT, only usable in IM 1
*
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include "sim.h"
#include "simglb.h"
/*
* Structure to describe a emulated floppy disk drive:
* pointer to filename
* pointer to file descriptor
* number of tracks
* number of sectors
*/
struct dskdef {
char *fn;
int *fd;
unsigned int tracks;
unsigned int sectors;
};
static BYTE drive; /* current drive A..P (0..15) */
static BYTE track; /* current track (0..255) */
static BYTE sector; /* current sektor (0..255) */
static BYTE status; /* status of last I/O operation on FDC */
static BYTE dmadl; /* current DMA adresse destination low */
static BYTE dmadh; /* current DMA adresse destination high */
static BYTE clkcmd; /* clock command */
static BYTE timer; /* 20ms timer */
static int drivea; /* fd for file "drivea.cpm" */
static int driveb; /* fd for file "driveb.cpm" */
static int drivec; /* fd for file "drivec.cpm" */
static int drived; /* fd for file "drived.cpm" */
static int drivee; /* fd for file "drivee.cpm" */
static int drivef; /* fd for file "drivef.cpm" */
static int driveg; /* fd for file "driveg.cpm" */
static int driveh; /* fd for file "driveh.cpm" */
static int drivei; /* fd for file "drivei.cpm" */
static int drivej; /* fd for file "drivej.cpm" */
static int drivek; /* fd for file "drivek.cpm" */
static int drivel; /* fd for file "drivel.cpm" */
static int drivem; /* fd for file "drivem.cpm" */
static int driven; /* fd for file "driven.cpm" */
static int driveo; /* fd for file "driveo.cpm" */
static int drivep; /* fd for file "drivep.cpm" */
static int printer; /* fd for file "printer.cpm" */
static int auxin; /* fd for pipe "auxin" */
static int auxout; /* fd for pipe "auxout" */
static int aux_in_eof; /* status of pipe "auxin" (<>0 means EOF) */
static int pid_rec; /* PID of the receiving process for auxiliary */
static char last_char; /* buffer for 1 character (console status) */
static struct dskdef disks[16] = {
{ "disks/drivea.cpm", &drivea, 77, 26 },
{ "disks/driveb.cpm", &driveb, 77, 26 },
{ "disks/drivec.cpm", &drivec, 77, 26 },
{ "disks/drived.cpm", &drived, 77, 26 },
{ "disks/drivee.cpm", &drivee, -1, -1 },
{ "disks/drivef.cpm", &drivef, -1, -1 },
{ "disks/driveg.cpm", &driveg, -1, -1 },
{ "disks/driveh.cpm", &driveh, -1, -1 },
{ "disks/drivei.cpm", &drivei, 255, 128 },
{ "disks/drivej.cpm", &drivej, 255, 128 },
{ "disks/drivek.cpm", &drivek, -1, -1 },
{ "disks/drivel.cpm", &drivel, -1, -1 },
{ "disks/drivem.cpm", &drivem, -1, -1 },
{ "disks/driven.cpm", &driven, -1, -1 },
{ "disks/driveo.cpm", &driveo, -1, -1 },
{ "disks/drivep.cpm", &drivep, -1, -1 }
};
/*
* MMU:
* ===
*
* +--------+
* 16KB | common |
* +--------+
* +--------+ +--------+ .......... +--------+
* | | | | | |
* 48KB | | | | .......... | |
* | bank 0 | | bank 1 | | bank n |
* +--------+ +--------+ .......... +--------+
*/
#define MAXSEG 16 /* max. number of memory banks */
#define SEGSIZ 49152 /* size of one bank = 48KBytes */
static char *mmu[MAXSEG]; /* MMU with pointers to the banks */
static int selbnk; /* current bank */
static int maxbnk; /* number of initialized banks */
/*
* Forward declaration of the I/O handlers for all used ports
*/
static BYTE io_trap(void);
static BYTE cond_in(void), cond_out(BYTE), cons_in(void), cons_out(BYTE);
static BYTE prtd_in(void), prtd_out(BYTE), prts_in(void), prts_out(BYTE);
static BYTE auxd_in(void), auxd_out(BYTE), auxs_in(void), auxs_out(BYTE);
static BYTE fdcd_in(void), fdcd_out(BYTE);
static BYTE fdct_in(void), fdct_out(BYTE);
static BYTE fdcs_in(void), fdcs_out(BYTE);
static BYTE fdco_in(void), fdco_out(BYTE);
static BYTE fdcx_in(void), fdcx_out(BYTE);
static BYTE dmal_in(void), dmal_out(BYTE);
static BYTE dmah_in(void), dmah_out(BYTE);
static BYTE mmui_in(void), mmui_out(BYTE), mmus_in(void), mmus_out(BYTE);
static BYTE clkc_in(void), clkc_out(BYTE), clkd_in(void), clkd_out(BYTE);
static BYTE time_in(void), time_out(BYTE);
static void int_timer(int);
static int to_bcd(int), get_date(struct tm *);
/*
* This array contains two function pointer for every
* active port, one for input and one for output.
*/
static BYTE (*port[256][2]) () = {
{ cons_in, cons_out }, /* port 0 */
{ cond_in, cond_out }, /* port 1 */
{ prts_in, prts_out }, /* port 2 */
{ prtd_in, prtd_out }, /* port 3 */
{ auxs_in, auxs_out }, /* port 4 */
{ auxd_in, auxd_out }, /* port 5 */
{ io_trap, io_trap }, /* port 6 */
{ io_trap, io_trap }, /* port 7 */
{ io_trap, io_trap }, /* port 8 */
{ io_trap, io_trap }, /* port 9 */
{ fdcd_in, fdcd_out }, /* port 10 */
{ fdct_in, fdct_out }, /* port 11 */
{ fdcs_in, fdcs_out }, /* port 12 */
{ fdco_in, fdco_out }, /* port 13 */
{ fdcx_in, fdcx_out }, /* port 14 */
{ dmal_in, dmal_out }, /* port 15 */
{ dmah_in, dmah_out }, /* port 16 */
{ io_trap, io_trap }, /* port 17 */
{ io_trap, io_trap }, /* port 18 */
{ io_trap, io_trap }, /* port 19 */
{ mmui_in, mmui_out }, /* port 20 */
{ mmus_in, mmus_out }, /* port 21 */
{ io_trap, io_trap }, /* port 22 */
{ io_trap, io_trap }, /* port 23 */
{ io_trap, io_trap }, /* port 24 */
{ clkc_in, clkc_out }, /* port 25 */
{ clkd_in, clkd_out }, /* port 26 */
{ time_in, time_out } /* port 27 */
};
/*
* This function initializes the I/O handlers:
* 1. Initialize all unused ports with the I/O trap handler.
* 2. Initialize the MMU with NULL pointers.
* 3. Open the files which emulates the disk drives. The file
* for drive A must be opened, or CP/M can't be booted.
* Errors for opening one of the other 15 drives results
* in a NULL pointer for fd in the dskdef structure,
* so that this drive can't be used.
* 4. Create and open the file "printer.cpm" for emulation
* of a printer.
* 5. Fork the process for receiving from the serial port.
* 6. Open the named pipes "auxin" and "auxout" for simulation
* of a serial port.
*/
void init_io(void)
{
register int i;
for (i = 28; i <= 255; i++) {
port[i][0] = io_trap;
port[i][1] = io_trap;
}
for (i = 0; i < MAXSEG; i++)
mmu[i] = NULL;
if ((*disks[0].fd = open(disks[0].fn, O_RDWR)) == -1) {
perror("file disks/drivea.cpm");
exit(1);
}
for (i = 1; i <= 15; i++)
if ((*disks[i].fd = open(disks[i].fn, O_RDWR)) == -1)
disks[i].fd = NULL;
if ((printer = creat("printer.cpm", 0644)) == -1) {
perror("file printer.cpm");
exit(1);
}
pid_rec = fork();
switch (pid_rec) {
case -1:
puts("can't fork");
exit(1);
case 0:
execlp("./receive", "receive", "auxiliary.cpm", (char *) NULL);
puts("can't exec receive process");
exit(1);
}
if ((auxin = open("auxin", O_RDONLY | O_NDELAY)) == -1) {
perror("pipe auxin");
exit(1);
}
if ((auxout = open("auxout", O_WRONLY)) == -1) {
perror("pipe auxout");
exit(1);
}
}
/*
* This function stops the I/O handlers:
*
* 1. The files emulating the disk drives are closed.
* 2. The file "printer.com" emulating a printer is closed.
* 3. The named pipes "auxin" and "auxout" are closed.
* 4. The receiving process for the serial port is stopped.
*/
void exit_io(void)
{
register int i;
for (i = 0; i <= 15; i++)
if (disks[i].fd != NULL)
close(*disks[i].fd);
close(printer);
close(auxin);
close(auxout);
kill(pid_rec, SIGHUP);
}
/*
* This function is called for every IN opcode from the
* CPU emulation. It calls the right handler for the
* port, from which input is wanted.
*/
BYTE io_in(BYTE adr)
{
return((*port[adr][0]) ());
}
/*
* This function is called for every OUT opcode from the
* CPU emulation. It calls the right handler for the port,
* to which output is wanted.
*/
BYTE io_out(BYTE adr, BYTE data)
{
(*port[adr][1]) (data);
return((BYTE) 0);
}
/*
* I/O trap handler
*/
static BYTE io_trap(void)
{
if (i_flag) {
cpu_error = IOTRAP;
cpu_state = STOPPED;
}
return((BYTE) 0);
}
/*
* I/O handler for read console status:
* 0xff : input available
* 0x00 : no input available
*/
static BYTE cons_in(void)
{
register int flags, readed;
if (last_char)
return((BYTE) 0xff);
if (cntl_c)
return((BYTE) 0xff);
if (cntl_bs)
return((BYTE) 0xff);
else {
flags = fcntl(0, F_GETFL, 0);
fcntl(0, F_SETFL, flags | O_NDELAY);
readed = read(0, &last_char, 1);
fcntl(0, F_SETFL, flags);
if (readed == 1)
return((BYTE) 0xff);
}
return((BYTE) 0);
}
/*
* I/O handler for write console status:
* no reaction
*/
static BYTE cons_out(BYTE data)
{
data = data;
return((BYTE) 0);
}
/*
* I/O handler for read console data:
* read one character from the terminal without echo
* and character transformations
*/
static BYTE cond_in(void)
{
char c;
aborted:
if (last_char) {
c = last_char;
last_char = '\0';
} else if (cntl_c) {
cntl_c--;
c = 0x03;
} else if (cntl_bs) {
cntl_bs--;
c = 0x1c;
} else if (read(0, &c, 1) != 1) {
goto aborted;
}
return((BYTE) c);
}
/*
* I/O handler for write console data:
* the output is written to the terminal
*/
static BYTE cond_out(BYTE data)
{
while ((write(fileno(stdout), (char *) &data, 1)) != 1)
;
fflush(stdout);
return((BYTE) 0);
}
/*
* I/O handler for read printer status:
* the printer is ready all the time
*/
static BYTE prts_in(void)
{
return((BYTE) 0xff);
}
/*
* I/O handler for write printer status:
* no reaction
*/
static BYTE prts_out(BYTE data)
{
data = data;
return((BYTE) 0);
}
/*
* I/O handler for read printer data:
* always read a 0 from the printer
*/
static BYTE prtd_in(void)
{
return((BYTE) 0);
}
/*
* I/O handler for write printer data:
* the output is written to file "printer.cpm"
*/
static BYTE prtd_out(BYTE data)
{
if (data != '\r')
while ((write(printer, (char *) &data, 1)) != 1)
;
return((BYTE) 0);
}
/*
* I/O handler for read aux status:
* return EOF status of the aux device
*/
static BYTE auxs_in(void)
{
return((BYTE) aux_in_eof);
}
/*
* I/O handler for write aux status:
* change EOF status of the aux device
*/
static BYTE auxs_out(BYTE data)
{
aux_in_eof = data;
return((BYTE) 0);
}
/*
* I/O handler for read aux data:
* read next byte from pipe "auxin"
*/
static BYTE auxd_in(void)
{
char c;
if (read(auxin, &c, 1) == 1)
return((BYTE) c);
else {
aux_in_eof = 0xff;
return((BYTE) 0x1a); /* CP/M EOF */
}
}
/*
* I/O handler for write aux data:
* write output to pipe "auxout"
*/
static BYTE auxd_out(BYTE data)
{
if (data != '\r')
write(auxout, (char *) &data, 1);
return((BYTE) 0);
}
/*
* I/O handler for read FDC drive:
* return the current drive
*/
static BYTE fdcd_in(void)
{
return((BYTE) drive);
}
/*
* I/O handler for write FDC drive:
* set the current drive
*/
static BYTE fdcd_out(BYTE data)
{
drive = data;
return((BYTE) 0);
}
/*
* I/O handler for read FDC track:
* return the current track
*/
static BYTE fdct_in(void)
{
return((BYTE) track);
}
/*
* I/O handler for write FDC track:
* set the current track
*/
static BYTE fdct_out(BYTE data)
{
track = data;
return((BYTE) 0);
}
/*
* I/O handler for read FDC sector
* return the current sector
*/
static BYTE fdcs_in(void)
{
return((BYTE) sector);
}
/*
* I/O handler for write FDC sector:
* set the current sector
*/
static BYTE fdcs_out(BYTE data)
{
sector = data;
return((BYTE) 0);
}
/*
* I/O handler for read FDC command:
* always returns 0
*/
static BYTE fdco_in(void)
{
return((BYTE) 0);
}
/*
* I/O handler for write FDC command:
* transfer one sector in the wanted direction,
* 0 = read, 1 = write
*
* The status byte of the FDC is set as follows:
* 0 - ok
* 1 - illegal drive
* 2 - illegal track
* 3 - illegal sector
* 4 - seek error
* 5 - read error
* 6 - write error
* 7 - illegal command to FDC
*/
static BYTE fdco_out(BYTE data)
{
register long pos;
if (disks[drive].fd == NULL) {
status = 1;
return((BYTE) 0);
}
if (track > disks[drive].tracks) {
status = 2;
return((BYTE) 0);
}
if (sector > disks[drive].sectors) {
status = 3;
return((BYTE) 0);
}
pos = (((long)track) * ((long)disks[drive].sectors) + sector - 1) << 7;
if (lseek(*disks[drive].fd, pos, 0) == -1L) {
status = 4;
return((BYTE) 0);
}
switch (data) {
case 0: /* read */
if (read(*disks[drive].fd, (char *) ram + (dmadh << 8) +
dmadl, 128) != 128)
status = 5;
else
status = 0;
break;
case 1: /* write */
if (write(*disks[drive].fd, (char *) ram + (dmadh << 8) +
dmadl, 128) != 128)
status = 6;
else
status = 0;
break;
default: /* illegal command */
status = 7;
break;
}
return((BYTE) 0);
}
/*
* I/O handler for read FDC status:
* returns status of last FDC operation,
* 0 = ok, else some error
*/
static BYTE fdcx_in(void)
{
return((BYTE) status);
}
/*
* I/O handler for write FDC status:
* no reaction
*/
static BYTE fdcx_out(BYTE data)
{
data = data;
return((BYTE) 0);
}
/*
* I/O handler for read lower byte of DMA address:
* return lower byte of current DMA address
*/
static BYTE dmal_in(void)
{
return((BYTE) dmadl);
}
/*
* I/O handler for write lower byte of DMA address:
* set lower byte of DMA address
*/
static BYTE dmal_out(BYTE data)
{
dmadl = data;
return((BYTE) 0);
}
/*
* I/O handler for read higher byte of DMA address:
* return higher byte of current DMA address
*/
static BYTE dmah_in(void)
{
return((BYTE) dmadh);
}
/*
* I/O handler for write higher byte of DMA address:
* set higher byte of the DMA address
*/
static BYTE dmah_out(BYTE data)
{
dmadh = data;
return((BYTE) 0);
}
/*
* I/O handler for read MMU initialization:
* return number of initialized MMU banks
*/
static BYTE mmui_in(void)
{
return((BYTE) maxbnk);
}
/*
* I/O handler for write MMU initialization:
* for the FIRST call the memory for the wanted number of banks
* is allocated and pointers to the memory is stored in the MMU array
*/
static BYTE mmui_out(BYTE data)
{
register int i;
if (mmu[0] != NULL)
return((BYTE) 0);
if (data > MAXSEG) {
printf("Try to init %d banks, available %d banks\n",
data, MAXSEG);
exit(1);
}
for (i = 0; i < data; i++) {
if ((mmu[i] = malloc(SEGSIZ)) == NULL) {
printf("can't allocate memory for bank %d\n", i+1);
exit(1);
}
}
maxbnk = data;
return((BYTE) 0);
}
/*
* I/O handler for read MMU bank select:
* return current selected MMU bank
*/
static BYTE mmus_in(void)
{
return((BYTE) selbnk);
}
/*
* I/O handler for write MMU bank select:
* if the current selected bank is not equal the wanted bank,
* the current bank is saved. Then the memory of the wanted
* bank is copied into the CPU address space and this bank is
* set to be the current one now.
*/
static BYTE mmus_out(BYTE data)
{
if (data > maxbnk) {
printf("Try to select unallocated bank %d\n", data);
exit(1);
}
if (data == selbnk)
return((BYTE) 0);
memcpy(mmu[selbnk], (char *) ram, SEGSIZ);
memcpy((char *) ram, mmu[data], SEGSIZ);
selbnk = data;
return((BYTE) 0);
}
/*
* I/O handler for read clock command:
* return last clock command
*/
static BYTE clkc_in(void)
{
return(clkcmd);
}
/*
* I/O handler for write clock command:
* set the wanted clock command
*/
static BYTE clkc_out(BYTE data)
{
clkcmd = data;
return((BYTE) 0);
}
/*
* I/O handler for read clock data:
* dependent from the last clock command the following
* informations are given from the system clock:
* 0 - seconds in BCD
* 1 - minutes in BCD
* 2 - hours in BCD
* 3 - low byte number of days since 1.1.1978
* 4 - high byte number of days since 1.1.1978
* for every other clock command a 0 is returned
*/
static BYTE clkd_in(void)
{
register struct tm *t;
register int val;
time_t Time;
time(&Time);
t = localtime(&Time);
switch(clkcmd) {
case 0: /* seconds in BCD */
val = to_bcd(t->tm_sec);
break;
case 1: /* minutes in BCD */
val = to_bcd(t->tm_min);
break;
case 2: /* hours in BCD */
val = to_bcd(t->tm_hour);
break;
case 3: /* low byte days */
val = get_date(t) & 255;
break;
case 4: /* high byte days */
val = get_date(t) >> 8;
break;
default:
val = 0;
break;
}
return((BYTE) val);
}
/*
* I/O handler for write clock data:
* under UNIX the system clock only can be set by the
* super user, so we do nothing here
*/
static BYTE clkd_out(BYTE data)
{
data = data;
return((BYTE) 0);
}
/*
* Convert an integer to BCD
*/
static int to_bcd(int val)
{
register int i = 0;
while (val >= 10) {
i += val / 10;
i <<= 4;
val %= 10;
}
i += val;
return (i);
}
/*
* Calculate number of days since 1.1.1978
* The Y2K bug here is intentional, CP/M 3 has a Y2K bug fix
*/
static int get_date(struct tm *t)
{
register int i;
register int val = 0;
for (i = 1978; i < 1900 + t->tm_year; i++) {
val += 365;
if (i % 4 == 0)
val++;
}
val += t->tm_yday + 1;
return(val);
}
/*
* I/O handler for write timer
*/
static BYTE time_out(BYTE data)
{
static struct itimerval tim;
static struct sigaction newact;
if (data == 1) {
timer = 1;
newact.sa_handler = int_timer;
sigaction(SIGALRM, &newact, NULL);
tim.it_value.tv_sec = 0;
tim.it_value.tv_usec = 20000;
tim.it_interval.tv_sec = 0;
tim.it_interval.tv_usec = 20000;
setitimer(ITIMER_REAL, &tim, NULL);
} else {
timer = 0;
newact.sa_handler = SIG_IGN;
sigaction(SIGALRM, &newact, NULL);
tim.it_value.tv_sec = 0;
tim.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &tim, NULL);
}
return((BYTE) 0);
}
/*
* I/O handler for read timer
*/
static BYTE time_in(void)
{
return(timer);
}
/*
* timer interrupt causes maskerable CPU interrupt
*/
static void int_timer(int sig)
{
int_type = INT_INT;
}

View File

@@ -1,14 +0,0 @@
# use this to link the common parts of Z80 simulation
ln ../../z80sim/sim0.c sim0.c
ln ../../z80sim/sim1.c sim1.c
ln ../../z80sim/sim2.c sim2.c
ln ../../z80sim/sim3.c sim3.c
ln ../../z80sim/sim4.c sim4.c
ln ../../z80sim/sim5.c sim5.c
ln ../../z80sim/sim6.c sim6.c
ln ../../z80sim/sim7.c sim7.c
ln ../../z80sim/simfun.c simfun.c
ln ../../z80sim/simint.c simint.c
ln ../../z80sim/simglb.c simglb.c
ln ../../z80sim/simglb.h simglb.h

View File

@@ -1,96 +0,0 @@
/*
* Z80SIM - a Z80-CPU simulator
*
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 28-SEP-87 Develoment on TARGON/35 with AT&T Unix System V.3
* 11-JAN-89 Release 1.1
* 08-FEB-89 Release 1.2
* 13-MAR-89 Release 1.3
* 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
* 23-DEC-90 Release 1.5 Ported to COHERENT 3.0
* 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
* and some optimization
* 25-JUN-92 Release 1.7 comments in english
* 02-OCT-06 Release 1.8 modified to compile on modern POSIX OS's
*/
/*
* The following defines may be activated, commented or modified
* by user for her/his own purpose.
*/
#define WANT_INT /* interrupt for MP/M */
/*#define WANT_SPC*/ /* CP/M doesn't work with SP over-/underrun */
/*#define WANT_PCC*/ /* CP/M doesn't work with PC overrun */
/*#define CNTL_C*/ /* don't abort simulation with cntl-c */
#define CNTL_BS /* emergency exit with cntl-\ :-) */
/*#define CNTL_Z*/ /* don't suspend simulation with cntl-z */
#define WANT_TIM /* run length measurement needed to adjust CPU speed */
/*#define HISIZE 1000*//* no history */
/*#define SBSIZE 10*/ /* no breakpoints */
/*
* The following lines of this file should not be modified by user
*/
#define COPYR "Copyright (C) 1987-2006 by Udo Munk"
#define RELEASE "1.9"
#define LENCMD 80 /* length of command buffers etc */
#define S_FLAG 128 /* bit definitions of CPU flags */
#define Z_FLAG 64
#define N2_FLAG 32
#define H_FLAG 16
#define N1_FLAG 8
#define P_FLAG 4
#define N_FLAG 2
#define C_FLAG 1
/* operation of simulated CPU */
#define SINGLE_STEP 0 /* single step */
#define CONTIN_RUN 1 /* continual run */
#define STOPPED 0 /* stop CPU because of error */
/* causes of error */
#define NONE 0 /* no error */
#define OPHALT 1 /* HALT op-code trap */
#define IOTRAP 2 /* IN/OUT trap */
#define OPTRAP1 3 /* illegal 1 byte op-code trap */
#define OPTRAP2 4 /* illegal 2 byte op-code trap */
#define OPTRAP4 5 /* illegal 4 byte op-code trap */
#define USERINT 6 /* user interrupt */
/* type of CPU interrupt */
#define INT_NONE 0
#define INT_NMI 1 /* non maskable interrupt */
#define INT_INT 2 /* maskable interrupt */
typedef unsigned short WORD; /* 16 bit unsigned */
typedef unsigned char BYTE; /* 8 bit unsigned */
#ifdef HISIZE
struct history { /* structure of a history entry */
WORD h_adr; /* address of execution */
WORD h_af; /* register AF */
WORD h_bc; /* register BC */
WORD h_de; /* register DE */
WORD h_hl; /* register HL */
WORD h_ix; /* register IX */
WORD h_iy; /* register IY */
WORD h_sp; /* register SP */
};
#endif
#ifdef SBSIZE
struct softbreak { /* structure of a breakpoint */
WORD sb_adr; /* address of breakpoint */
BYTE sb_oldopc; /* op-code at address of breakpoint */
int sb_passcount; /* pass counter of breakpoint */
int sb_pass; /* no. of pass to break */
};
#endif
#ifndef isxdigit
#define isxdigit(c) ((c<='f'&&c>='a')||(c<='F'&&c>='A')||(c<='9'&&c>='0'))
#endif

View File

@@ -1,92 +0,0 @@
/*
* Z80SIM - a Z80-CPU simulator
*
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
* 14-MAR-89 new option -l
* 23-DEC-90 Ported to COHERENT 3.0
* 06-OCT-06 modified to compile on modern POSIX OS's
*/
#include <unistd.h>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include "sim.h"
#include "simglb.h"
extern void cpu(void);
struct termios old_term, new_term;
/*
* This function gets the CP/M boot sector from first track/sector
* of disk drive A (file drivea.cpm) into memory started at 0.
* Then the Z80 CPU emulation is started and the system should boot.
*/
void mon(void)
{
register int fd;
if (!l_flag) {
if ((fd = open("disks/drivea.cpm", O_RDONLY)) == -1) {
perror("file disks/drivea.cpm");
return;
}
if (read(fd, (char *) ram, 128) != 128) {
perror("file disks/drivea.cpm");
return;
}
close(fd);
}
tcgetattr(0, &old_term);
new_term = old_term;
new_term.c_lflag &= ~(ICANON | ECHO);
new_term.c_iflag &= ~(IXON | IXANY | IXOFF);
new_term.c_iflag &= ~(IGNCR | ICRNL | INLCR);
new_term.c_cc[VMIN] = 1;
#ifndef CNTL_Z
new_term.c_cc[VSUSP] = 0;
#endif
tcsetattr(0, TCSADRAIN, &new_term);
cpu_state = CONTIN_RUN;
cpu_error = NONE;
cpu();
tcsetattr(0, TCSADRAIN, &old_term);
switch (cpu_error) {
case NONE:
break;
case OPHALT:
printf("\nHALT Op-Code reached at %04x\n",
(unsigned int)(PC - ram - 1));
break;
case IOTRAP:
printf("\nI/O Trap at %04x\n", (unsigned int)(PC - ram));
break;
case OPTRAP1:
printf("\nOp-code trap at %04x %02x\n",
(unsigned int)(PC - 1 - ram), *(PC - 1));
break;
case OPTRAP2:
printf("\nOp-code trap at %04x %02x %02x\n",
(unsigned int)(PC - 2 - ram), *(PC - 2), *(PC - 1));
break;
case OPTRAP4:
printf("\nOp-code trap at %04x %02x %02x %02x %02x\n",
(unsigned int)(PC - 4 - ram), *(PC - 4), *(PC - 3),
*(PC - 2), *(PC - 1));
break;
case USERINT:
puts("\nUser Interrupt");
break;
default:
printf("\nUnknown error %d\n", cpu_error);
break;
}
}

View File

@@ -1,6 +0,0 @@
# use this to unlink the common parts of Z80 simulation
rm sim[0-7].c
rm simfun.c
rm simint.c
rm simglb.[hc]

View File

@@ -1,22 +0,0 @@
Copyright (c) 1987-2006 Udo Munk
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,85 +0,0 @@
Usage:
z80asm -ofile -f[b|m|h] -l[file] -s[n|a] -x -v -dsymbol ... file ...
A maximum of 512 source files is allowed. If the filename of a source
doesn't have an extension the default extension ".asm" will be
concated. Source file names may have a path, the maximum length of
a full qualified filename is 2048 characters.
For relative paths the extension must be used, because all characters
after a "." would be used as extension!
Option o:
To override the default name of the output file. Without this option
the name of the output file becomes the name of the input file,
but with the extension ".bin". The output file may have a path,
the maximum length is limited to 2048 characters.
Option f:
Format of the output file:
-fb -> binary file
-fm -> binary file with Mostek header
-fh -> Intel hex
Option l:
Without this option no list file will be generated. With -l a list
file with the name of the source file but extension ".lis" will be
generated. An optional file name with path (2048 characters maximum)
may be added to this option.
Option s:
This option writes the unsorted symbol table (-s), sorted by name (-sn)
or sorted by address (-sa) into the list file. This option only works
together with option -l.
Option x:
Don't output data in pass 2 into object file for DEFS. This only works
if unallocated data isn't followed by any code or initialized data!
Usefull for CP/M BIOS's, where unallocated data doesn't need to be
part of the system image, if the complete image won't fit on the system
tracks.
Option v:
Verbose operation of the assembler.
Option d:
This option predefines symbols with a value of 0.
The number of this option is not limited in the command line.
Pseudo Operations:
Definition of symbols and allocation of memory:
ORG <expression> - set program address
<symbol> EQU <expression> - define constant symbol
<symbol> DEFL <expression> - define variable symbol
<symbol> DEFB <exp,'char',..> - write bytes in memory
<symbol> DEFW <exp,exp..> - write words (16 bits) in memory
<symbol> DEFM <'string'> - write character string in memory
<symbol> DEFS <expression> - reserve space in memory
Conditional assembly:
IFDEF <symbol> - assemble if symbol defined
IFNDEF <symbol> - assemble if symbol not defined
IFEQ <exp1,exp2> - assemble if equal
IFNEQ <exp1,exp2> - assemble if not equal
ELSE - else for all conditionals
ENDIF - end of conditional assembly
Manipulation of list file:
PAGE <expression> - number of lines/page
EJECT - skip to new page
LIST - listing on
NOLIST - listing off
TITLE <'string'> - define title for page header
Others:
INCLUDE <filename> - include another source file
PRINT <'string'> - print string to stdout in pass one

View File

@@ -1,54 +0,0 @@
Quickstart to run CP/M and MP/M on the Z80-CPU simulation
1. Change to directory ~/z80pack/cpmsim/srcsim
make
make clean
This compiles the CPU and hardware emulation needed to run CP/M and MP/M.
2. Change to directory ~/z80pack/cpmsim/srccpm2
make
make clean
This compiles support programs (see below), installs named pipes and so on.
3. Make backup copies of your distribution disks!
cd ~/z80pack/cpmsim/disks/library
cp *.dsk ../backups
4. Change to directory ~/z80pack/cpmsim
cpm2 - run CP/M 2.2
cpm3 - run CP/M 3.0
mpm - this boots CP/M 2, run command mpm to boot MP/M 2
Usage of the support programs:
format: to create an empty disk image for the CP/M simulation.
input: format <a | b | c | d | i | j>
output: in directory disks files drivea.cpm, driveb.cpm,
drivec.cpm, drived.cpm, drivei.cpm and drivej.cpm
bin2hex:converts binary files to Intel hex.
receive:This is a process spawned by cpmsim. It reads from the named
pipe auxout and writes all input from the pipe to the file,
which is given as first argument. cpmsim spawns this process
with the output filename auxiliary.cpm. Inside the simulator
this pipe is connected to I/O-port 5, which is assigned
to the CP/M device PUN:. So everything you write from CP/M
to device PUN: goes into the file auxiliary.cpm on the
UNIX host.
send: This process is to send a file from the UNIX host to the
simulator. Type send <filename> &, and then run cpmsim.
The process writes all data from file into the named pipe
auxin, which is also connected to I/O-port 5, which is
assigned to the CP/M device RDR:. You may use this to
transfer a file from the UNIX host to the simulator.
Under CP/M type pip file=RDR: to read the data send from
the process on the UNIX host.
If you use PIP to transfer files between the UNIX host and the
simulator, you can only use ASCII files, because pip uses cntl-z
for EOF! To transfer a binary file from the UNIX host to the
simulator convert it to Intel hex format with bin2hex. This
can be converted back to a binary file under CP/M with the LOAD
command.

View File

@@ -1,41 +0,0 @@
CFLAGS = -c -O
LFLAGS = -s
OBJ = z80amain.o \
z80atab.o \
z80anum.o \
z80aout.o \
z80arfun.o \
z80apfun.o \
z80aopc.o \
z80aglb.o
z80asm : $(OBJ)
cc $(OBJ) $(LFLAGS) -o z80asm
z80amain.o : z80amain.c z80a.h z80aglb.h
cc $(CFLAGS) z80amain.c
z80atab.o : z80atab.c z80a.h z80aglb.h
cc $(CFLAGS) z80atab.c
z80anum.o : z80anum.c z80a.h z80aglb.h
cc $(CFLAGS) z80anum.c
z80aout.o : z80aout.c z80a.h z80aglb.h
cc $(CFLAGS) z80aout.c
z80arfun.o : z80arfun.c z80a.h z80aglb.h
cc $(CFLAGS) z80arfun.c
z80apfun.o : z80apfun.c z80a.h z80aglb.h
cc $(CFLAGS) z80apfun.c
z80aopc.o : z80aopc.c z80a.h
cc $(CFLAGS) z80aopc.c
z80aglb.o : z80aglb.c z80a.h
cc $(CFLAGS) z80aglb.c
clean:
rm -f core *.o z80asm

View File

@@ -1,144 +0,0 @@
/*
* Z80 - Assembler
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 17-SEP-1987 Development under Digital Research CP/M 2.2
* 28-JUN-1988 Switched to Unix System V.3
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
*/
/*
* OS dependant definitions
*/
#define LENFN 2048 /* max. filename length */
#define READA "r" /* file open mode read ascii */
#define WRITEA "w" /* file open mode write ascii */
#define WRITEB "w" /* file open mode write binary */
/*
* various constants
*/
#define REL "1.3"
#define COPYR "Copyright (C) 1987-2006 by Udo Munk"
#define SRCEXT ".asm" /* filenamen extension source */
#define OBJEXT ".bin" /* filenamen extension object */
#define LSTEXT ".lis" /* filenamen extension listing */
#define OUTBIN 1 /* format of object: binary */
#define OUTMOS 2 /* Mostek binaer */
#define OUTHEX 3 /* Intel hex */
#define OUTDEF OUTMOS /* default object format */
#define COMMENT ';' /* inline comment character */
#define LINCOM '*' /* comment line if in columne 1 */
#define LABSEP ':' /* label separator */
#define STRSEP '\'' /* string separator */
#define ENDFILE "END" /* end of source */
#define MAXFN 512 /* max. no. source files */
#define MAXLINE 128 /* max. line length source */
#define PLENGTH 65 /* default lines/page in listing */
#define SYMSIZE 8 /* max. symbol length */
#define INCNEST 5 /* max. INCLUDE nesting depth */
#define IFNEST 5 /* max IF.. nesting depth */
#define HASHSIZE 500 /* max. entries in symbol hash array */
#define OPCARRAY 256 /* size of object buffer */
#define SYMINC 100 /* start size of sorted symbol array */
/*
* structure opcode table
*/
struct opc {
char *op_name; /* opcode name */
int (*op_fun) (); /* function pointer code generation */
int op_c1; /* first base opcode*/
int op_c2; /* second base opcode */
};
/*
* structure operand table
*/
struct ope {
char *ope_name; /* operand name */
int ope_sym; /* symbol value operand */
};
/*
* structure symbol table entries
*/
struct sym {
char *sym_name; /* symbol name */
int sym_wert; /* symbol value */
struct sym *sym_next; /* next entry */
};
/*
* structure nested INCLUDE's
*/
struct inc {
unsigned inc_line; /* line counter for listing */
char *inc_fn; /* filename */
FILE *inc_fp; /* file pointer */
};
/*
* definition of operand symbols
* definitions for registers A, B, C, D, H, L and (HL)
* are defined as the bits used in operands and may not
* be changed!
*/
#define REGB 0 /* register B */
#define REGC 1 /* register C */
#define REGD 2 /* register D */
#define REGE 3 /* register E */
#define REGH 4 /* register H */
#define REGL 5 /* register L */
#define REGIHL 6 /* register indirect HL */
#define REGA 7 /* register A */
#define REGI 8 /* register I */
#define REGR 9 /* register R */
#define REGAF 10 /* register pair AF */
#define REGBC 11 /* register pair BC */
#define REGDE 12 /* register pair DE */
#define REGHL 13 /* register pair HL */
#define REGIX 14 /* register IX */
#define REGIY 15 /* register IY */
#define REGSP 16 /* register SP */
#define REGIBC 17 /* register indirect BC */
#define REGIDE 18 /* register indirect DE */
#define REGIIX 19 /* register indirect IX */
#define REGIIY 20 /* register indirect IY */
#define REGISP 21 /* register indirect SP */
#define FLGNC 30 /* flag no carry */
#define FLGNZ 31 /* flag not zerro */
#define FLGZ 32 /* flag zerro */
#define FLGM 33 /* flag minus */
#define FLGP 34 /* flag plus */
#define FLGPE 35 /* flag parrity even */
#define FLGPO 36 /* flag parrity odd */
#define NOOPERA 98 /* no operand */
#define NOREG 99 /* operand isn't register */
/*
* definitions of error numbers for error messages in listfile
*/
#define E_ILLOPC 0 /* illegal opcode */
#define E_ILLOPE 1 /* illegal operand */
#define E_MISOPE 2 /* missing operand */
#define E_MULSYM 3 /* multiple defined symbol */
#define E_UNDSYM 4 /* undefined symbol */
#define E_VALOUT 5 /* value out of bounds */
#define E_MISPAR 6 /* missing parren */
#define E_MISHYP 7 /* missing string separator */
#define E_MEMOVR 8 /* memory override (ORG) */
#define E_MISIFF 9 /* missing IF at ELSE or ENDIF */
#define E_IFNEST 10 /* to many IF's nested */
#define E_MISEIF 11 /* missing ENDIF */
#define E_INCNEST 12 /* to many INCLUDE's nested */
/*
* definition fatal errors
*/
#define F_OUTMEM 0 /* out of memory */
#define F_USAGE 1 /* usage: .... */
#define F_HALT 2 /* assembly halted */
#define F_FOPEN 3 /* can't open file */
#define F_INTERN 4 /* internal error */

View File

@@ -1,67 +0,0 @@
/*
* Z80 - Assembler
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 17-SEP-1987 Development under Digital Research CP/M 2.2
* 28-JUN-1988 Switched to Unix System V.3
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
*/
/*
* this module contains all global variables other
* than CPU specific tables
*/
#include <stdio.h>
#include "z80a.h"
char *infiles[MAXFN], /* source filenames */
objfn[LENFN + 1], /* object filename */
lstfn[LENFN + 1], /* listing filename */
*srcfn, /* filename of current processed source file */
line[MAXLINE], /* buffer for one line souce */
tmp[MAXLINE], /* temporary buffer */
label[SYMSIZE+1], /* buffer for label */
opcode[MAXLINE], /* buffer for opcode */
operand[MAXLINE], /* buffer for operand */
ops[OPCARRAY], /* buffer for generated object code */
title[MAXLINE]; /* buffer for titel of souce */
int list_flag, /* flag for option -l */
sym_flag, /* flag for option -s */
ver_flag, /* flag for option -v */
dump_flag, /* flag for option -x */
pc, /* programm counter */
pass, /* processed pass */
iflevel, /* IF nesting level */
gencode = 1, /* flag for conditional object code */
errors, /* error counter */
errnum, /* error number in pass 2 */
sd_flag, /* list flag for PSEUDO opcodes */
/* = 0: address from <val>, data from <ops> */
/* = 1: address from <sd_val>, data from <ops>*/
/* = 2: no address, data from <ops> */
/* = 3: address from <sd_val>, no data */
/* = 4: suppress whole line */
sd_val, /* output value for PSEUDO opcodes */
prg_adr, /* start address of programm */
prg_flag, /* flag for prg_adr valid */
out_form = OUTDEF, /* format of object file */
symsize; /* size of symarray */
FILE *srcfp, /* file pointer for current source */
*objfp, /* file pointer for object code */
*lstfp, /* file pointer for listing */
*errfp; /* file pointer for error output */
unsigned
c_line, /* current line no. in current source */
s_line, /* line no. counter for listing */
p_line, /* no. printed lines on page */
ppl = PLENGTH, /* page length */
page; /* no. of pages for listing */
struct sym
*symtab[HASHSIZE], /* symbol table */
**symarray; /* sorted symbol table */

View File

@@ -1,62 +0,0 @@
/*
* Z80 - Assembler
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 17-SEP-1987 Development under Digital Research CP/M 2.2
* 28-JUN-1988 Switched to Unix System V.3
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
*/
/*
* global variable declarations
*/
extern char *infiles[],
objfn[],
lstfn[],
*srcfn,
line[],
tmp[],
label[],
opcode[],
operand[],
ops[],
title[];
extern int list_flag,
sym_flag,
ver_flag,
dump_flag,
pc,
pass,
iflevel,
gencode,
errors,
errnum,
sd_flag,
sd_val,
prg_adr,
prg_flag,
out_form,
symsize,
no_opcodes,
no_operands;
extern FILE *srcfp,
*objfp,
*lstfp,
*errfp;
extern unsigned c_line,
s_line,
p_line,
ppl,
page;
extern struct sym *symtab[],
**symarray;
extern struct opc opctab[];
extern struct ope opetab[];

View File

@@ -1,503 +0,0 @@
/*
* Z80 - Assembler
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 17-SEP-1987 Development under Digital Research CP/M 2.2
* 28-JUN-1988 Switched to Unix System V.3
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
*/
/*
* main module, handles the options and runs 2 passes over the sources
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "z80a.h"
#include "z80aglb.h"
void init(void), options(int, char *[]);
void usage(void), fatal(int, char *);
void pass1(void), p1_file(char *);
void pass2(void), p2_file(char *);
void open_o_files(char *), get_fn(char *, char *, char *);
char *get_label(char *, char *);
char *get_opcode(char *, char *);
char *get_arg(char *, char *);
extern void asmerr(int);
extern void lst_line(int, int);
extern void lst_sym(void);
extern void lst_sort_sym(int);
extern void obj_header(void);
extern void obj_end(void);
extern void obj_writeb(int);
extern struct opc *search_op(char *);
extern int put_sym(char *, int);
extern void put_label(void);
extern int copy_sym(void);
extern void n_sort_sym(int);
extern void a_sort_sym(int);
static char *errmsg[] = { /* error messages for fatal() */
"out of memory: %s", /* 0 */
"usage: z80asm -ofile -f[b|m|h] -l[file] -s[n|a] {-x} -v -dsymbol ... file ...",
"Assembly halted", /* 2 */
"can't open file %s", /* 3 */
"internal error: %s" /* 4 */
};
main(int argc, char *argv[])
{
int len;
init();
options(argc, argv);
printf("Z80 - Assembler Release %s, %s\n", REL, COPYR);
pass1();
pass2();
if (list_flag) {
switch (sym_flag) {
case 0: /* no symbol table */
break;
case 1: /* unsorted symbol table */
lst_sym();
break;
case 2: /* symbol table sorted by name */
len = copy_sym();
n_sort_sym(len);
lst_sort_sym(len);
break;
case 3: /* symbol table sorted by address */
len = copy_sym();
a_sort_sym(len);
lst_sort_sym(len);
break;
default:
break;
}
fclose(lstfp);
}
return(errors);
}
/*
* initialization
*/
void init(void)
{
errfp = stdout;
}
/*
* process options
*/
void options(int argc, char *argv[])
{
register char *s, *t;
register int i;
while (--argc > 0 && (*++argv)[0] == '-')
for (s = argv[0]+1; *s != '\0'; s++)
switch (*s) {
case 'o':
case 'O':
if (*++s == '\0') {
puts("name missing in option -o");
usage();
}
get_fn(objfn, s, OBJEXT);
s += (strlen(s) - 1);
break;
case 'l':
case 'L':
if (*(s + 1) != '\0') {
get_fn(lstfn, ++s, LSTEXT);
s += (strlen(s) - 1);
}
list_flag = 1;
break;
case 's':
case 'S':
if (*(s + 1) == '\0')
sym_flag = 1;
else if ((*(s + 1) == 'n') || (*(s + 1) == 'N'))
sym_flag = 2;
else if ((*(s + 1) == 'a') || (*(s + 1) == 'A'))
sym_flag = 3;
else {
printf("unknown option -%s\n", s);
usage();
}
s += (strlen(s) - 1);
break;
case 'x':
case 'X':
dump_flag = 1;
break;
case 'f':
case 'F':
if ((*(s + 1) == 'b') || (*(s + 1) == 'B'))
out_form = OUTBIN;
else if ((*(s + 1) == 'm') || (*(s + 1) == 'M'))
out_form = OUTMOS;
else if ((*(s + 1) == 'h') || (*(s + 1) == 'H'))
out_form = OUTHEX;
else {
printf("unknown option -%s\n", s);
usage();
}
s += (strlen(s) - 1);
break;
case 'd':
case 'D':
if (*++s == '\0') {
puts("name missing in option -d");
usage();
}
t = tmp;
while (*s)
*t++ = islower(*s) ? toupper(*s++)
: *s++;
s--;
*t = '\0';
if (put_sym(tmp, 0))
fatal(F_OUTMEM, "symbols");
break;
case 'v':
case 'V':
ver_flag = 1;
break;
default :
printf("unknown option %c\n", *s);
usage();
}
i = 0;
while ((argc--) && (i < MAXFN)) {
if ((infiles[i] = malloc(LENFN + 1)) == NULL)
fatal(F_OUTMEM, "filenames");
get_fn(infiles[i], *argv++, SRCEXT);
i++;
}
if (i == 0) {
printf("no input file given\n");
usage();
}
}
/*
* error in options, print usage
*/
void usage(void)
{
fatal(F_USAGE, NULL);
}
/*
* print error messages and abort
*/
void fatal(int i, char *arg)
{
printf(errmsg[i], arg);
putchar('\n');
exit(1);
}
/*
* Pass 1:
* - process all source files
*/
void pass1(void)
{
register int fi;
pass = 1;
pc = 0;
fi = 0;
if (!ver_flag)
puts("Pass 1");
open_o_files(infiles[fi]);
while (infiles[fi] != NULL) {
if (!ver_flag)
printf(" Read %s\n", infiles[fi]);
p1_file(infiles[fi]);
fi++;
}
if (errors) {
fclose(objfp);
unlink(objfn);
printf("%d error(s)\n", errors);
fatal(F_HALT, NULL);
}
}
/*
* Pass 1:
* - process one source file
*
* Input: name of source file
*/
void p1_file(char *fn)
{
c_line = 0;
srcfn = fn;
if ((srcfp = fopen(fn, READA)) == NULL)
fatal(F_FOPEN, fn);
while (p1_line())
;
fclose(srcfp);
if (iflevel)
asmerr(E_MISEIF);
}
/*
* Pass 1:
* - process one line of source
*
* Output: 1 line processed
* 0 EOF
*/
int p1_line(void)
{
register char *p;
register int i;
register struct opc *op;
if ((p = fgets(line, MAXLINE, srcfp)) == NULL)
return(0);
c_line++;
p = get_label(label, p);
p = get_opcode(opcode, p);
p = get_arg(operand, p);
if (strcmp(opcode, ENDFILE) == 0)
return(0);
if (*opcode) {
if ((op = search_op(opcode)) != NULL) {
i = (*op->op_fun)(op->op_c1, op->op_c2);
if (gencode)
pc += i;
} else
asmerr(E_ILLOPC);
} else
if (*label)
put_label();
return(1);
}
/*
* Pass 2:
* - process all source files
*/
void pass2(void)
{
register int fi;
pass = 2;
pc = 0;
fi = 0;
if (!ver_flag)
puts("Pass 2");
obj_header();
while (infiles[fi] != NULL) {
if (!ver_flag)
printf(" Read %s\n", infiles[fi]);
p2_file(infiles[fi]);
fi++;
}
obj_end();
fclose(objfp);
printf("%d error(s)\n", errors);
}
/*
* Pass 2:
* - process one source file
*
* Input: name of source file
*/
void p2_file(char *fn)
{
c_line = 0;
srcfn = fn;
if ((srcfp = fopen(fn, READA)) == NULL)
fatal(F_FOPEN, fn);
while (p2_line())
;
fclose(srcfp);
}
/*
* Pass 2:
* - process one line of source
*
* Output: 1 line processed
* 0 EOF
*/
int p2_line(void)
{
register char *p;
register int op_count;
register struct opc *op;
if ((p = fgets(line, MAXLINE, srcfp)) == NULL)
return(0);
c_line++;
s_line++;
p = get_label(label, p);
p = get_opcode(opcode, p);
p = get_arg(operand, p);
if (strcmp(opcode, ENDFILE) == 0) {
lst_line(pc, 0);
return(0);
}
if (*opcode) {
op = search_op(opcode);
op_count = (*op->op_fun)(op->op_c1, op->op_c2);
if (gencode) {
lst_line(pc, op_count);
obj_writeb(op_count);
pc += op_count;
} else {
sd_flag = 2;
lst_line(0, 0);
}
} else {
sd_flag = 2;
lst_line(0, 0);
}
return(1);
}
/*
* open output files:
* input is filename of source file
* list and object filenames are build from source filename if
* not given by options
*/
void open_o_files(char *source)
{
register char *p;
if (*objfn == '\0')
strcpy(objfn, source);
if ((p = strrchr(objfn, '.')) != NULL)
strcpy(p, OBJEXT);
else
strcat(objfn, OBJEXT);
if (out_form == OUTHEX)
objfp = fopen(objfn, WRITEA);
else
objfp = fopen(objfn, WRITEB);
if (objfp == NULL)
fatal(F_FOPEN, objfn);
if (list_flag) {
if (*lstfn == '\0')
strcpy(lstfn, source);
if ((p = strrchr(lstfn, '.')) != NULL)
strcpy(p, LSTEXT);
else
strcat(lstfn, LSTEXT);
if ((lstfp = fopen(lstfn, WRITEA)) == NULL)
fatal(F_FOPEN, lstfn);
errfp = lstfp;
}
}
/*
* create a filename in "dest" from "src" and "ext"
*/
void get_fn(char *dest, char *src, char *ext)
{
register int i;
register char *sp, *dp;
i = 0;
sp = src;
dp = dest;
while ((i++ < LENFN) && (*sp != '\0'))
*dp++ = *sp++;
*dp = '\0';
if ((strrchr(dest,'.') == NULL) &&
(strlen(dest) <= (LENFN - strlen(ext))))
strcat(dest, ext);
}
/*
* get labels, constants and variables from source line
* convert names to upper case and truncate length of name
*/
char *get_label(char *s, char *l)
{
register int i;
i = 0;
if (*l == LINCOM)
goto comment;
while (!isspace(*l) && *l != COMMENT && *l != LABSEP && i < SYMSIZE) {
*s++ = islower(*l) ? toupper(*l++) : *l++;
i++;
}
comment:
*s = '\0';
return(l);
}
/*
* get opcode into s from source line l
* converts to uper case
*/
char *get_opcode(char *s, char *l)
{
if (*l == LINCOM)
goto comment;
while (!isspace(*l) && *l != COMMENT && *l != LABSEP)
l++;
if (*l == LABSEP)
l++;
while (*l == ' ' || *l == '\t')
l++;
while (!isspace(*l) && *l != COMMENT)
*s++ = islower(*l) ? toupper(*l++) : *l++;
comment:
*s = '\0';
return(l);
}
/*
* get operand into s from source line l
* converts to upper case
* strings inside of 's are copied without changes
*/
char *get_arg(char *s, char *l)
{
if (*l == LINCOM)
goto comment;
while (*l == ' ' || *l == '\t')
l++;
while (*l != '\n' && *l != COMMENT) {
if (isspace(*l)) {
l++;
continue;
}
if (*l != STRSEP) {
*s++ = islower(*l) ? toupper(*l) : *l;
l++;
continue;
}
*s++ = *l++;
if (*(s - 2) == 'F') /* EX AF,AF' !!!!! */
continue;
while (*l != STRSEP) {
if (*l == '\n' || *l == '\0' || *l == COMMENT)
goto comment;
*s++ = *l++;
}
*s++ = *l++;
}
comment:
*s = '\0';
return(l);
}

View File

@@ -1,309 +0,0 @@
/*
* Z80 - Assembler
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 17-SEP-1987 Development under Digital Research CP/M 2.2
* 28-JUN-1988 Switched to Unix System V.3
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
*/
/*
* modul with numercial computation and conversion
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "z80a.h"
#include "z80aglb.h"
#ifndef isxdigit
#define isxdigit(c) (isdigit(c) || (c>='a' && c<='f') || (c>='A' && c<='F'))
#endif
/*
* definitions of operator symbols for expression parser
*/
#define OPEDEC 1 /* decimal number */
#define OPEHEX 2 /* hexadecimal number */
#define OPEOCT 3 /* octal number */
#define OPEBIN 4 /* binary number */
#define OPESUB 5 /* arithmetical - */
#define OPEADD 6 /* arithmetical + */
#define OPEMUL 7 /* arithmetical * */
#define OPEDIV 8 /* arithmetical / */
#define OPEMOD 9 /* arithmetical modulo */
#define OPESHL 10 /* logical shift left */
#define OPESHR 11 /* logical shift right */
#define OPELOR 12 /* logical OR */
#define OPELAN 13 /* logical AND */
#define OPEXOR 14 /* logical XOR */
#define OPECOM 15 /* logical complement */
#define OPESYM 99 /* symbol */
extern struct sym *get_sym(char *);
extern void asmerr(int);
/*
* recursive expression parser
*
* Input: pointer to argument rest string
*
* Output: computed value
*/
int eval(char *s)
{
register char *p;
register int val;
char word[MAXLINE];
struct sym *sp;
val = 0;
while (*s) {
p = word;
if (*s == '(') {
s++;
while (*s != ')') {
if (*s == '\0') {
asmerr(E_MISPAR);
goto eval_break;
}
*p++ = *s++;
}
*p = '\0';
s++;
val = eval(word);
continue;
}
if (*s == STRSEP) {
s++;
while (*s != STRSEP) {
if (*s == '\n' || *s == '\0') {
asmerr(E_MISHYP);
goto hyp_error;
}
*p++ = *s++;
}
s++;
hyp_error:
*p = '\0';
val = strval(word);
continue;
}
if (isari(*s))
*p++ = *s++;
else
while (!isspace(*s) && !isari(*s) && (*s != '\0'))
*p++ = *s++;
*p = '\0';
switch (get_type(word)) {
case OPESYM: /* symbol */
if (strcmp(word, "$") == 0) {
val = pc;
break;
}
if (strlen(word) > SYMSIZE)
word[SYMSIZE] = '\0';
if ((sp = get_sym(word)) != NULL)
val = sp->sym_wert;
else
asmerr(E_UNDSYM);
break;
case OPEDEC: /* decimal number */
val = atoi(word);
break;
case OPEHEX: /* hexadecimal number */
val = axtoi(word);
break;
case OPEBIN: /* binary number */
val = abtoi(word);
break;
case OPEOCT: /* octal number */
val = aotoi(word);
break;
case OPESUB: /* arithmetical - */
val -= eval(s);
goto eval_break;
case OPEADD: /* arithmetical + */
val += eval(s);
goto eval_break;
case OPEMUL: /* arithmetical * */
val *= eval(s);
goto eval_break;
case OPEDIV: /* arithmetical / */
val /= eval(s);
goto eval_break;
case OPEMOD: /* arithmetical modulo */
val %= eval(s);
goto eval_break;
case OPESHL: /* logical shift left */
val <<= eval(s);
goto eval_break;
case OPESHR: /* logical shift right */
val >>= eval(s);
goto eval_break;
case OPELOR: /* logical OR */
val |= eval(s);
goto eval_break;
case OPELAN: /* logical AND */
val &= eval(s);
goto eval_break;
case OPEXOR: /* logical XOR */
val ^= eval(s);
goto eval_break;
case OPECOM: /* logical complement */
val = ~(eval(s));
goto eval_break;
}
}
eval_break:
return(val);
}
/*
* get typ of operand
*
* Input: pointer to string with operand
*
* Output: operand typ
*/
int get_type(char *s)
{
if (isdigit(*s)) { /* numerical operand */
if (isdigit(*(s + strlen(s) - 1))) /* decimal number */
return(OPEDEC);
else if (*(s + strlen(s) - 1) == 'H') /* hexadecimal number */
return(OPEHEX);
else if (*(s + strlen(s) - 1) == 'B') /* binary number */
return(OPEBIN);
else if (*(s + strlen(s) - 1) == 'O') /* octal number */
return(OPEOCT);
} else if (*s == '-') /* arithmetical operand - */
return(OPESUB);
else if (*s == '+') /* arithmetical operand + */
return(OPEADD);
else if (*s == '*') /* arithmetical operand * */
return(OPEMUL);
else if (*s == '/') /* arithmetical operand / */
return(OPEDIV);
else if (*s == '%') /* arithmetical modulo */
return(OPEMOD);
else if (*s == '<') /* logical shift left */
return(OPESHL);
else if (*s == '>') /* logical shift rigth */
return(OPESHR);
else if (*s == '|') /* logical OR */
return(OPELOR);
else if (*s == '&') /* logical AND */
return(OPELAN);
else if (*s == '^') /* logical XOR */
return(OPEXOR);
else if (*s == '~') /* logical complement */
return(OPECOM);
return(OPESYM); /* operand is symbol */
}
/*
* check a character for arithmetical operators
* +, -, *, /, %, <, >, |, &, ~ and ^
*/
int isari(int c)
{
return((c) == '+' || (c) == '-' || (c) == '*' ||
(c) == '/' || (c) == '%' || (c) == '<' ||
(c) == '>' || (c) == '|' || (c) == '&' ||
(c) == '~' || (c) == '^');
}
/*
* conversion of string with hexadecimal number to integer
* format: nnnnH or 0nnnnH if 1st digit > 9
*/
int axtoi(char *str)
{
register int num;
num = 0;
while (isxdigit(*str)) {
num *= 16;
num += *str - ((*str <= '9') ? '0' : '7');
str++;
}
return(num);
}
/*
* conversion of string with octal number to integer
* format: nnnnO
*/
int aotoi(char *str)
{
register int num;
num = 0;
while ('0' <= *str && *str <= '7') {
num *= 8;
num += (*str++) - '0';
}
return(num);
}
/*
* conversion of string with binary number to integer
* format: nnnnnnnnnnnnnnnnB
*/
int abtoi(char *str)
{
register int num;
num = 0;
while ('0' <= *str && *str <= '1') {
num *= 2;
num += (*str++) - '0';
}
return(num);
}
/*
* convert ASCII string to integer
*/
int strval(char *str)
{
register int num;
num = 0;
while (*str) {
num <<= 8;
num += (int) *str++;
}
return(num);
}
/*
* check value for range -256 < value < 256
* Output: value if in range, otherwise 0 and error message
*/
int chk_v1(int i)
{
if (i >= -255 && i <= 255)
return(i);
else {
asmerr(E_VALOUT);
return(0);
}
}
/*
* check value for range -128 < value < 128
* Output: value if in range, otherwise 0 and error message
*/
int chk_v2(int i)
{
if (i >= -127 && i <= 127)
return(i);
else {
asmerr(E_VALOUT);
return(0);
}
}

View File

@@ -1,172 +0,0 @@
/*
* Z80 - Assembler
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 17-SEP-1987 Development under Digital Research CP/M 2.2
* 28-JUN-1988 Switched to Unix System V.3
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
*/
/*
* opcode tables
*/
#include <stdio.h>
#include "z80a.h"
extern int op_1b(), op_2b(), op_pupo(), op_ex(), op_ld();
extern int op_call(), op_ret(), op_jp(), op_jr(), op_djnz(), op_rst();
extern int op_add(), op_adc(), op_sub(), op_sbc(), op_cp();
extern int op_inc(), op_dec(), op_or(), op_xor(), op_and();
extern int op_rl(), op_rr(), op_sla(), op_sra(), op_srl(), op_rlc(), op_rrc();
extern int op_out(), op_in(), op_im();
extern int op_set(), op_res(), op_bit();
extern int op_org(), op_dl(), op_equ();
extern int op_ds(), op_db(), op_dw(), op_dm();
extern int op_misc();
extern int op_cond();
extern int op_glob();
/*
* opcode table:
* includes entries for all opcodes and pseudo ops other than END
* must be sorted in ascending order!
*/
struct opc opctab[] = {
{ "ADC", op_adc, 0, 0 },
{ "ADD", op_add, 0, 0 },
{ "AND", op_and, 0, 0 },
{ "BIT", op_bit, 0, 0 },
{ "CALL", op_call, 0, 0 },
{ "CCF", op_1b, 0x3f, 0 },
{ "CP", op_cp, 0, 0 },
{ "CPD", op_2b, 0xed, 0xa9 },
{ "CPDR", op_2b, 0xed, 0xb9 },
{ "CPI", op_2b, 0xed, 0xa1 },
{ "CPIR", op_2b, 0xed, 0xb1 },
{ "CPL", op_1b, 0x2f, 0 },
{ "DAA", op_1b, 0x27, 0 },
{ "DEC", op_dec, 0, 0 },
{ "DEFB", op_db, 0, 0 },
{ "DEFL", op_dl, 0, 0 },
{ "DEFM", op_dm, 0, 0 },
{ "DEFS", op_ds, 0, 0 },
{ "DEFW", op_dw, 0, 0 },
{ "DI", op_1b, 0xf3, 0 },
{ "DJNZ", op_djnz, 0, 0 },
{ "EI", op_1b, 0xfb, 0 },
{ "EJECT", op_misc, 1, 0 },
{ "ELSE", op_cond, 98, 0 },
{ "ENDIF", op_cond, 99, 0 },
{ "EQU", op_equ, 0, 0 },
{ "EX", op_ex, 0, 0 },
{ "EXTRN", op_glob, 1, 0 },
{ "EXX", op_1b, 0xd9, 0 },
{ "HALT", op_1b, 0x76, 0 },
{ "IFDEF", op_cond, 1, 0 },
{ "IFEQ", op_cond, 3, 0 },
{ "IFNDEF", op_cond, 2, 0 },
{ "IFNEQ", op_cond, 4, 0 },
{ "IM", op_im, 0, 0 },
{ "IN", op_in, 0, 0 },
{ "INC", op_inc, 0, 0 },
{ "INCLUDE", op_misc, 6, 0 },
{ "IND", op_2b, 0xed, 0xaa },
{ "INDR", op_2b, 0xed, 0xba },
{ "INI", op_2b, 0xed, 0xa2 },
{ "INIR", op_2b, 0xed, 0xb2 },
{ "JP", op_jp, 0, 0 },
{ "JR", op_jr, 0, 0 },
{ "LD", op_ld, 0, 0 },
{ "LDD", op_2b, 0xed, 0xa8 },
{ "LDDR", op_2b, 0xed, 0xb8 },
{ "LDI", op_2b, 0xed, 0xa0 },
{ "LDIR", op_2b, 0xed, 0xb0 },
{ "LIST", op_misc, 2, 0 },
{ "NEG", op_2b, 0xed, 0x44 },
{ "NOLIST", op_misc, 3, 0 },
{ "NOP", op_1b, 0, 0 },
{ "OR", op_or, 0, 0 },
{ "ORG", op_org, 0, 0 },
{ "OTDR", op_2b, 0xed, 0xbb },
{ "OTIR", op_2b, 0xed, 0xb3 },
{ "OUT", op_out, 0, 0 },
{ "OUTD", op_2b, 0xed, 0xab },
{ "OUTI", op_2b, 0xed, 0xa3 },
{ "PAGE", op_misc, 4, 0 },
{ "POP", op_pupo, 1, 0 },
{ "PRINT", op_misc, 5, 0 },
{ "PUBLIC", op_glob, 2, 0 },
{ "PUSH", op_pupo, 2, 0 },
{ "RES", op_res, 0, 0 },
{ "RET", op_ret, 0, 0 },
{ "RETI", op_2b, 0xed, 0x4d },
{ "RETN", op_2b, 0xed, 0x45 },
{ "RL", op_rl, 0, 0 },
{ "RLA", op_1b, 0x17, 0 },
{ "RLC", op_rlc, 0, 0 },
{ "RLCA", op_1b, 0x07, 0 },
{ "RLD", op_2b, 0xed, 0x6f },
{ "RR", op_rr, 0, 0 },
{ "RRA", op_1b, 0x1f, 0 },
{ "RRC", op_rrc, 0, 0 },
{ "RRCA", op_1b, 0x0f, 0 },
{ "RRD", op_2b, 0xed, 0x67 },
{ "RST", op_rst, 0, 0 },
{ "SBC", op_sbc, 0, 0 },
{ "SCF", op_1b, 0x37, 0 },
{ "SET", op_set, 0, 0 },
{ "SLA", op_sla, 0, 0 },
{ "SRA", op_sra, 0, 0 },
{ "SRL", op_srl, 0, 0 },
{ "SUB", op_sub, 0, 0 },
{ "TITLE", op_misc, 7, 0 },
{ "XOR", op_xor, 0, 0 }
};
/*
* compute no. of table entries for search_op()
*/
int no_opcodes = sizeof(opctab) / sizeof(struct opc);
/*
* table with reserverd operand words: registers and flags
* must be sorted in ascending order!
*/
struct ope opetab[] = {
{ "(BC)", REGIBC },
{ "(DE)", REGIDE },
{ "(HL)", REGIHL },
{ "(IX)", REGIIX },
{ "(IY)", REGIIY },
{ "(SP)", REGISP },
{ "A", REGA },
{ "AF", REGAF },
{ "B", REGB },
{ "BC", REGBC },
{ "C", REGC },
{ "D", REGD },
{ "DE", REGDE },
{ "E", REGE },
{ "H", REGH },
{ "HL", REGHL },
{ "I", REGI },
{ "IX", REGIX },
{ "IY", REGIY },
{ "L", REGL },
{ "M", FLGM },
{ "NC", FLGNC },
{ "NZ", FLGNZ },
{ "P", FLGP },
{ "PE", FLGPE },
{ "PO", FLGPO },
{ "R", REGR },
{ "SP", REGSP },
{ "Z", FLGZ }
};
/*
* compute no. of table entries
*/
int no_operands = sizeof(opetab) / sizeof(struct ope);

View File

@@ -1,360 +0,0 @@
/*
* Z80 - Assembler
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 17-SEP-1987 Development under Digital Research CP/M 2.2
* 28-JUN-1988 Switched to Unix System V.3
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
*/
/*
* module for output functions to list, object and error files
*/
#include <stdio.h>
#include <string.h>
#include "z80a.h"
#include "z80aglb.h"
void flush_hex(void);
int chksum(void);
void btoh(unsigned char, char **);
extern void fatal(int, char *);
static char *errmsg[] = { /* error messages for asmerr() */
"illegal opcode", /* 0 */
"illegal operand", /* 1 */
"missing operand", /* 2 */
"multiply defined symbol", /* 3 */
"undefined symbol", /* 4 */
"value out of range", /* 5 */
"missing )", /* 6 */
"missing string separator", /* 7 */
"memory override", /* 8 */
"missing IF", /* 9 */
"IF nesting to deep", /* 10 */
"missing ENDIF", /* 11 */
"INCLUDE nesting to deep" /* 12 */
};
#define MAXHEX 32 /* max no bytes/hex record */
static unsigned short hex_adr; /* current address in hex record */
static int hex_cnt; /* current no bytes in hex buffer */
static unsigned char hex_buf[MAXHEX]; /* buffer for one hex record */
static char hex_out[MAXHEX*2+11]; /* ASCII buffer for one hex record */
/*
* print error message to listfile and increase error counter
*/
void asmerr(int i)
{
if (pass == 1) {
fprintf(errfp, "Error in file: %s Line: %d\n", srcfn, c_line);
fprintf(errfp, errmsg[i]);
fprintf(errfp, "\n\n");
} else
errnum = i;
errors++;
}
/*
* begin new page in listfile
*/
void lst_header(void)
{
fprintf(lstfp, "\fZ80-Assembler\t\tRelease %s\t\t\t\tPage %d\n", REL,
++page);
fprintf(lstfp, "Source file: %s\n", srcfn);
fprintf(lstfp, "Title: %s\n", title);
p_line = 3;
}
/*
* print header for source lines
*/
void lst_attl(void)
{
fprintf(lstfp, "\nLOC OBJECT CODE LINE STMT SOURCE CODE\n");
p_line += 2;
}
/*
* print one line into listfile, if -l option set
*/
void lst_line(int val, int opanz)
{
register int i;
if (!list_flag || sd_flag == 4) {
sd_flag = 0;
return;
}
if ((p_line >= ppl) || (c_line == 1)) {
lst_header();
lst_attl();
}
switch (sd_flag) {
case 0:
fprintf(lstfp, "%04x ", val & 0xffff);
break;
case 1:
fprintf(lstfp, "%04x ", sd_val & 0xffff);
break;
case 2:
fprintf(lstfp, " ");
break;
case 3:
fprintf(lstfp, "%04x ", sd_val & 0xffff);
goto no_data;
default:
fatal(F_INTERN, "illegal listflag for function lst_line");
break;
}
if (opanz >= 1) fprintf(lstfp, "%02x ", ops[0] & 0xff);
else fprintf(lstfp, " ");
if (opanz >= 2) fprintf(lstfp, "%02x ", ops[1] & 0xff);
else fprintf(lstfp, " ");
if (opanz >= 3) fprintf(lstfp, "%02x ", ops[2] & 0xff);
else fprintf(lstfp, " ");
if (opanz >= 4) fprintf(lstfp, "%02x ", ops[3] & 0xff);
else fprintf(lstfp, " ");
no_data:
fprintf(lstfp, "%6d %6d %s", c_line, s_line, line);
if (errnum) {
fprintf(errfp, "=> %s", errmsg[errnum]);
putc('\n', errfp);
errnum = 0;
p_line++;
}
sd_flag = 0;
p_line++;
if (opanz > 4 && sd_flag == 0) {
opanz -= 4;
i = 4;
sd_val = val;
while (opanz > 0) {
if (p_line >= ppl) {
lst_header();
lst_attl();
}
s_line++;
sd_val += 4;
fprintf(lstfp, "%04x ", sd_val & 0xffff);
if (opanz-- > 0) fprintf(lstfp, "%02x ",
ops[i++] & 0xff);
else fprintf(lstfp, " ");
if (opanz-- > 0) fprintf(lstfp, "%02x ",
ops[i++] & 0xff);
else fprintf(lstfp, " ");
if (opanz-- > 0) fprintf(lstfp, "%02x ",
ops[i++] & 0xff);
else fprintf(lstfp, " ");
if (opanz-- > 0) fprintf(lstfp, "%02x ",
ops[i++] & 0xff);
else fprintf(lstfp, " ");
fprintf(lstfp, "%6d %6d\n", c_line, s_line);
p_line++;
}
}
}
/*
* print symbol table into listfile unsorted
*/
void lst_sym(void)
{
register int i, j;
register struct sym *np;
p_line = j = 0;
strcpy(title,"Symboltable");
for (i = 0; i < HASHSIZE; i++) {
if (symtab[i] != NULL) {
for (np = symtab[i]; np != NULL; np = np->sym_next) {
if (p_line == 0) {
lst_header();
fputs("\n", lstfp);
p_line += 1;
}
fprintf(lstfp, "%-8s %04x\t", np->sym_name,
np->sym_wert & 0xffff);
if (++j == 4) {
fprintf(lstfp, "\n");
if (p_line++ >= ppl)
p_line = 0;
j = 0;
}
}
}
}
}
/*
* print sorted symbol table into listfile
*/
void lst_sort_sym(int len)
{
register int i, j;
p_line = i = j = 0;
strcpy(title, "Symboltable");
while (i < len) {
if (p_line == 0) {
lst_header();
fputs("\n", lstfp);
p_line += 1;
}
fprintf(lstfp, "%-8s %04x\t", symarray[i]->sym_name,
symarray[i]->sym_wert & 0xffff);
if (++j == 4) {
fprintf(lstfp, "\n");
if (p_line++ >= ppl)
p_line = 0;
j = 0;
}
i++;
}
}
/*
* write header record into object file
*/
void obj_header(void)
{
switch (out_form) {
case OUTBIN:
break;
case OUTMOS:
putc(0xff, objfp);
putc(prg_adr & 0xff, objfp);
putc(prg_adr >> 8, objfp);
break;
case OUTHEX:
hex_adr = prg_adr;
break;
}
}
/*
* write end record into object file
*/
void obj_end(void)
{
switch (out_form) {
case OUTBIN:
break;
case OUTMOS:
break;
case OUTHEX:
flush_hex();
fprintf(objfp, ":0000000000\n");
break;
}
}
/*
* write opcodes in ops[] into object file
*/
void obj_writeb(int opanz)
{
register int i;
switch (out_form) {
case OUTBIN:
fwrite(ops, 1, opanz, objfp);
break;
case OUTMOS:
fwrite(ops, 1, opanz, objfp);
break;
case OUTHEX:
for (i = 0; opanz; opanz--) {
if (hex_cnt >= MAXHEX)
flush_hex();
hex_buf[hex_cnt++] = ops[i++];
}
break;
}
}
/*
* write <count> bytes 0xff into object file
*/
void obj_fill(int count)
{
switch (out_form) {
case OUTBIN:
while (count--)
putc(0xff, objfp);
break;
case OUTMOS:
while (count--)
putc(0xff, objfp);
break;
case OUTHEX:
flush_hex();
hex_adr += count;
break;
}
}
/*
* create a hex record in ASCII and write into object file
*/
void flush_hex(void)
{
char *p;
register int i;
if (!hex_cnt)
return;
p = hex_out;
*p++ = ':';
btoh((unsigned char) hex_cnt, &p);
btoh((unsigned char) (hex_adr >> 8), &p);
btoh((unsigned char) (hex_adr & 0xff), &p);
*p++ = '0';
*p++ = '0';
for (i = 0; i < hex_cnt; i++)
btoh(hex_buf[i], &p);
btoh((unsigned char) chksum(), &p);
*p++ = '\n';
*p = '\0';
fwrite(hex_out, 1, strlen(hex_out), objfp);
hex_adr += hex_cnt;
hex_cnt = 0;
}
/*
* convert unsigned char into ASCII hex and copy to string at p
* increase p by 2
*/
void btoh(unsigned char byte, char **p)
{
register unsigned char c;
c = byte >> 4;
*(*p)++ = (c < 10) ? (c + '0') : (c - 10 + 'A');
c = byte & 0xf;
*(*p)++ = (c < 10) ? (c + '0') : (c - 10 + 'A');
}
/*
* computer checksum for Intel hex record
*/
int chksum(void)
{
register int i, j, sum;
sum = hex_cnt;
sum += hex_adr >> 8;
sum += hex_adr & 0xff;
for (i = 0; i < hex_cnt; i++) {
j = hex_buf[i];
sum += j & 0xff;
}
return (0x100 - (sum & 0xff));
}

View File

@@ -1,446 +0,0 @@
/*
* Z80 - Assembler
* Copyright (C) 1987-2006 by Udo Munk
*
* History:
* 17-SEP-1987 Development under Digital Research CP/M 2.2
* 28-JUN-1988 Switched to Unix System V.3
* 22-OCT-2006 changed to ANSI C for modern POSIX OS's
*/
/*
* processing of all PSEUDO ops
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "z80a.h"
#include "z80aglb.h"
extern void fatal(int, char *);
extern void p1_file(char *);
extern void p2_file(char *);
extern int eval(char *);
extern void asmerr(int);
extern void lst_header(void);
extern void lst_attl(void);
extern void lst_line(int, int);
extern void obj_fill(int);
extern struct sym *get_sym(char *);
extern int put_sym(char *, int);
extern void put_label(void);
/*
* ORG
*/
int op_org(void)
{
register int i;
if (!gencode)
return(0);
i = eval(operand);
if (i < pc) {
asmerr(E_MEMOVR);
return(0);
}
if (pass == 1) { /* PASS 1 */
if (!prg_flag) {
prg_adr = i;
prg_flag++;
}
} else { /* PASS 2 */
if (++prg_flag > 2)
obj_fill(i - pc);
sd_flag = 2;
}
pc = i;
return(0);
}
/*
* EQU
*/
int op_equ(void)
{
if (!gencode)
return(0);
if (pass == 1) { /* Pass 1 */
if (get_sym(label) == NULL) {
sd_val = eval(operand);
if (put_sym(label, sd_val))
fatal(F_OUTMEM, "symbols");
} else
asmerr(E_MULSYM);
} else { /* Pass 2 */
sd_flag = 1;
sd_val = eval(operand);
}
return(0);
}
/*
* DEFL
*/
int op_dl(void)
{
if (!gencode)
return(0);
sd_flag = 1;
sd_val = eval(operand);
if (put_sym(label, sd_val))
fatal(F_OUTMEM, "symbols");
return(0);
}
/*
* DEFS
*/
int op_ds(void)
{
register int val;
if (!gencode)
return(0);
if (pass == 1)
if (*label)
put_label();
sd_val = pc;
sd_flag = 3;
val = eval(operand);
if ((pass == 2) && !dump_flag)
obj_fill(val);
pc += val;
return(0);
}
/*
* DEFB
*/
int op_db(void)
{
register int i;
register char *p;
register char *s;
if (!gencode)
return(0);
i = 0;
p = operand;
if (pass == 1)
if (*label)
put_label();
while (*p) {
if (*p == STRSEP) {
p++;
while (*p != STRSEP) {
if (*p == '\n' || *p == '\0') {
asmerr(E_MISHYP);
goto hyp_error;
}
ops[i++] = *p++;
if (i >= OPCARRAY)
fatal(F_INTERN, "Op-Code buffer overflow");
}
p++;
} else {
s = tmp;
while (*p != ',' && *p != '\0')
*s++ = *p++;
*s = '\0';
ops[i++] = eval(tmp);
if (i >= OPCARRAY)
fatal(F_INTERN, "Op-Code buffer overflow");
}
if (*p == ',')
p++;
}
hyp_error:
return(i);
}
/*
* DEFM
*/
int op_dm(void)
{
register int i;
register char *p;
if (!gencode)
return(0);
i = 0;
p = operand;
if (pass == 1)
if (*label)
put_label();
if (*p != STRSEP) {
asmerr(E_MISHYP);
return(0);
}
p++;
while (*p != STRSEP) {
if (*p == '\n' || *p == '\0') {
asmerr(E_MISHYP);
break;
}
ops[i++] = *p++;
if (i >= OPCARRAY)
fatal(F_INTERN, "Op-Code buffer overflow");
}
return(i);
}
/*
* DEFW
*/
int op_dw(void)
{
register int i, len, temp;
register char *p;
register char *s;
if (!gencode)
return(0);
p = operand;
i = len = 0;
if (pass == 1)
if (*label)
put_label();
while (*p) {
s = tmp;
while (*p != ',' && *p != '\0')
*s++ = *p++;
*s = '\0';
if (pass == 2) {
temp = eval(tmp);
ops[i++] = temp & 0xff;
ops[i++] = temp >> 8;
if (i >= OPCARRAY)
fatal(F_INTERN, "Op-Code buffer overflow");
}
len += 2;
if (*p == ',')
p++;
}
return(len);
}
/*
* EJECT, LIST, NOLIST, PAGE, PRINT, TITLE, INCLUDE
*/
int op_misc(int op_code, int dummy)
{
register char *p, *d;
static char fn[LENFN];
static int incnest;
static struct inc incl[INCNEST];
if (!gencode)
return(0);
sd_flag = 2;
switch(op_code) {
case 1: /* EJECT */
if (pass == 2)
p_line = ppl;
break;
case 2: /* LIST */
if (pass == 2)
list_flag = 1;
break;
case 3: /* NOLIST */
if (pass == 2)
list_flag = 0;
break;
case 4: /* PAGE */
if (pass == 2)
ppl = eval(operand);
break;
case 5: /* PRINT */
if (pass == 1) {
p = operand;
while (*p) {
if (*p != STRSEP)
putchar(*p++);
else
p++;
}
putchar('\n');
}
break;
case 6: /* INCLUDE */
if (incnest >= INCNEST) {
asmerr(E_INCNEST);
break;
}
incl[incnest].inc_line = c_line;
incl[incnest].inc_fn = srcfn;
incl[incnest].inc_fp = srcfp;
incnest++;
p = line;
d = fn;
while(isspace(*p)) /* ignore white space until INCLUDE */
p++;
while(!isspace(*p)) /* ignore INCLUDE */
p++;
while(isspace(*p)) /* ignore white space until filename */
p++;
while(!isspace(*p) && *p != COMMENT) /* get filename */
*d++ = *p++;
*d = '\0';
if (pass == 1) { /* PASS 1 */
if (!ver_flag)
printf(" Include %s\n", fn);
p1_file(fn);
} else { /* PASS 2 */
sd_flag = 2;
lst_line(0, 0);
if (!ver_flag)
printf(" Include %s\n", fn);
p2_file(fn);
}
incnest--;
c_line = incl[incnest].inc_line;
srcfn = incl[incnest].inc_fn;
srcfp = incl[incnest].inc_fp;
printf(" Resume %s\n", srcfn);
if (list_flag && (pass == 2)) {
lst_header();
lst_attl();
}
sd_flag = 4;
break;
case 7: /* TITLE */
if (pass == 2) {
p = line;
d = title;
while (isspace(*p)) /* ignore white space until TITLE */
p++;
while (!isspace(*p)) /* ignore TITLE */
p++;
while (isspace(*p)) /* ignore white space until text */
p++;
if (*p == STRSEP)
p++;
while (*p != '\n' && *p != STRSEP && *p != COMMENT)
*d++ = *p++;
*d = '\0';
}
break;
default:
fatal(F_INTERN, "illegal opcode for function op_misc");
break;
}
return(0);
}
/*
* IFDEF, IFNDEF, IFEQ, IFNEQ, ELSE, ENDIF
*/
int op_cond(int op_code, int dummy)
{
register char *p, *p1, *p2;
static int condnest[IFNEST];
switch(op_code) {
case 1: /* IFDEF */
if (iflevel >= IFNEST) {
asmerr(E_IFNEST);
break;
}
condnest[iflevel++] = gencode;
if (gencode)
if (get_sym(operand) == NULL)
gencode = 0;
break;
case 2: /* IFNDEF */
if (iflevel >= IFNEST) {
asmerr(E_IFNEST);
break;
}
condnest[iflevel++] = gencode;
if (gencode)
if (get_sym(operand) != NULL)
gencode = 0;
break;
case 3: /* IFEQ */
if (iflevel >= IFNEST) {
asmerr(E_IFNEST);
break;
}
condnest[iflevel++] = gencode;
p = operand;
if (!*p || !(p1 = strchr(operand, ','))) {
asmerr(E_MISOPE);
break;
}
if (gencode) {
p2 = tmp;
while (*p != ',')
*p2++ = *p++;
*p2 = '\0';
if (eval(tmp) != eval(++p1))
gencode = 0;
}
break;
case 4: /* IFNEQ */
if (iflevel >= IFNEST) {
asmerr(E_IFNEST);
break;
}
condnest[iflevel++] = gencode;
p = operand;
if (!*p || !(p1 = strchr(operand, ','))) {
asmerr(E_MISOPE);
break;
}
if (gencode) {
p2 = tmp;
while (*p != ',')
*p2++ = *p++;
*p2 = '\0';
if (eval(tmp) == eval(++p1))
gencode = 0;
}
break;
case 98: /* ELSE */
if (!iflevel)
asmerr(E_MISIFF);
else
if ((iflevel == 0) || (condnest[iflevel - 1] == 1))
gencode = !gencode;
break;
case 99: /* ENDIF */
if (!iflevel)
asmerr(E_MISIFF);
else
gencode = condnest[--iflevel];
break;
default:
fatal(F_INTERN, "illegal opcode for function op_cond");
break;
}
sd_flag = 2;
return(0);
}
/*
* EXTRN and PUBLIC
*/
int op_glob(int op_code, int dummy)
{
if (!gencode)
return(0);
sd_flag = 2;
switch(op_code) {
case 1: /* EXTRN */
break;
case 2: /* PUBLIC */
break;
default:
fatal(F_INTERN, "illegal opcode for function op_glob");
break;
}
return(0);
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More