mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-26 18:04:07 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
$title('tables for ddt86 assembler')
|
||||
$date(6/15/81)
|
||||
|
||||
asmtab: do;
|
||||
|
||||
$nolist
|
||||
$include(optab.lit)
|
||||
$list
|
||||
|
||||
declare op$tab (*) byte public data (
|
||||
aaa$in, 1, 037h, 0,
|
||||
aad$in, 2, 0d5h, 0ah,
|
||||
aam$in, 2, 0d4h, 0ah,
|
||||
aas$in, 1, 03fh, 0,
|
||||
adc$in, 9, 10h, 2,
|
||||
add$in, 9, 0, 0,
|
||||
and$in, 10, 20h, 4,
|
||||
call$in, 11, 0, 0,
|
||||
callf$in, 17, 0, 0,
|
||||
cbw$in, 1, 098h, 0,
|
||||
clc$in, 1, 0f8h, 0,
|
||||
cld$in, 1, 0fch, 0,
|
||||
cli$in, 1, 0fah, 0,
|
||||
cmc$in, 1, 0f5h, 0,
|
||||
cmp$in, 9, 38h, 7,
|
||||
cmpsb$in, 1, 0a6h, 0,
|
||||
cmpsw$in, 1, 0a7h, 0,
|
||||
cwd$in, 1, 099h, 0,
|
||||
daa$in, 1, 027h, 0,
|
||||
das$in, 1, 02fh, 0,
|
||||
dec$in, 7, 0, 0,
|
||||
div$in, 5, 0f6h, 6,
|
||||
esc$in, 13, 0d8h, 0,
|
||||
hlt$in, 1, 0f4h, 0,
|
||||
idiv$in, 5, 0f6h, 7,
|
||||
imul$in, 5, 0f6h, 5,
|
||||
in$in, 15, 0e4h, 0,
|
||||
inc$in, 7, 1, 0,
|
||||
int$in, 12, 0, 0,
|
||||
into$in, 1, 0ceh, 0,
|
||||
iret$in, 1, 0cfh, 0,
|
||||
ja$in, 3, 077h, 0,
|
||||
jae$in, 3, 073h, 0,
|
||||
jb$in, 3, 072h, 0,
|
||||
jbe$in, 3, 076h, 0,
|
||||
jc$in, 3, 072h, 0,
|
||||
jcxz$in, 3, 0e3h, 0,
|
||||
je$in, 3, 074h, 0,
|
||||
jg$in, 3, 07fh, 0,
|
||||
jge$in, 3, 07dh, 0,
|
||||
jl$in, 3, 07ch, 0,
|
||||
jle$in, 3, 07eh, 0,
|
||||
jmp$in, 11, 1, 0,
|
||||
jmpf$in, 17, 1, 0,
|
||||
jmps$in, 3, 0ebh, 0,
|
||||
jna$in, 3, 076h, 0,
|
||||
jnae$in, 3, 072h, 0,
|
||||
jnb$in, 3, 073h, 0,
|
||||
jnbe$in, 3, 077h, 0,
|
||||
jnc$in, 3, 073h, 0,
|
||||
jne$in, 3, 075h, 0,
|
||||
jng$in, 3, 07eh, 0,
|
||||
jnge$in, 3, 07ch, 0,
|
||||
jnl$in, 3, 07dh, 0,
|
||||
jnle$in, 3, 07fh, 0,
|
||||
jno$in, 3, 071h, 0,
|
||||
jnp$in, 3, 07bh, 0,
|
||||
jns$in, 3, 079h, 0,
|
||||
jnz$in, 3, 075h, 0,
|
||||
jo$in, 3, 070h, 0,
|
||||
jp$in, 3, 07ah, 0,
|
||||
jpe$in, 3, 07ah, 0,
|
||||
jpo$in, 3, 07bh, 0,
|
||||
js$in, 3, 078h, 0,
|
||||
jz$in, 3, 074h, 0,
|
||||
lahf$in, 1, 09fh, 0,
|
||||
lds$in, 6, 0c5h, 0,
|
||||
lea$in, 6, 08dh, 0,
|
||||
les$in, 6, 0c4h, 0,
|
||||
lock$in, 0ffh, 0f0h, 0,
|
||||
lodsb$in, 1, 0ach, 0,
|
||||
lodsw$in, 1, 0adh, 0,
|
||||
loop$in, 3, 0e2h, 0,
|
||||
loope$in, 3, 0e1h, 0,
|
||||
loopne$in, 3, 0e0h, 0,
|
||||
loopnz$in, 3, 0e0h, 0,
|
||||
loopz$in, 3, 0e1h, 0,
|
||||
mov$in, 20, 0, 0,
|
||||
movsb$in, 1, 0a4h, 0,
|
||||
movsw$in, 1, 0a5h, 0,
|
||||
mul$in, 5, 0f6h, 4,
|
||||
neg$in, 5, 0f6h, 3,
|
||||
nop$in, 1, 090h, 0,
|
||||
not$in, 5, 0f6h, 2,
|
||||
or$in, 10, 8, 1,
|
||||
out$in, 16, 0e6h, 0,
|
||||
pop$in, 21, 0, 0,
|
||||
popf$in, 1, 09dh, 0,
|
||||
push$in, 8, 1, 0,
|
||||
pushf$in, 1, 09ch, 0,
|
||||
rcl$in, 4, 0d0h, 2,
|
||||
rcr$in, 4, 0d0h, 3,
|
||||
rep$in, 0feh, 0f3h, 0,
|
||||
repe$in, 0feh, 0f3h, 0,
|
||||
repne$in, 0feh, 0f2h, 0,
|
||||
repnz$in, 0feh, 0f2h, 0,
|
||||
repz$in, 0feh, 0f3h, 0,
|
||||
ret$in, 14, 0c2h, 0,
|
||||
retf$in, 14, 0cah, 0,
|
||||
rol$in, 4, 0d0h, 0,
|
||||
ror$in, 4, 0d0h, 1,
|
||||
sahf$in, 1, 09eh, 0,
|
||||
sal$in, 4, 0d0h, 4,
|
||||
sar$in, 4, 0d0h, 7,
|
||||
sbb$in, 9, 18h, 3,
|
||||
scasb$in, 1, 0aeh, 0,
|
||||
scasw$in, 1, 0afh, 0,
|
||||
shl$in, 4, 0d0h, 4,
|
||||
shr$in, 4, 0d0h, 5,
|
||||
stc$in, 1, 0f9h, 0,
|
||||
std$in, 1, 0fdh, 0,
|
||||
sti$in, 1, 0fbh, 0,
|
||||
stosb$in, 1, 0aah, 0,
|
||||
stosw$in, 1, 0abh, 0,
|
||||
sub$in, 9, 28h, 5,
|
||||
test$in, 18, 0, 0,
|
||||
wait$in, 1, 09bh, 0,
|
||||
xchg$in, 19, 0, 0,
|
||||
xlat$in, 1, 0d7h, 0,
|
||||
xor$in, 10, 30h, 6
|
||||
);
|
||||
|
||||
end asm$tab;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
;
|
||||
; interface module for ddt86 assembler
|
||||
; 7/15/82
|
||||
;
|
||||
dgroup group dats
|
||||
dats segment public 'DATS'
|
||||
db '?'
|
||||
dats ends
|
||||
;
|
||||
cgroup group code
|
||||
extrn asm:near
|
||||
public ddtgetline
|
||||
public goddt
|
||||
public ddtset
|
||||
;
|
||||
code segment public 'CODE'
|
||||
assume cs:cgroup
|
||||
;
|
||||
assent proc
|
||||
org 2400h
|
||||
jmp asm
|
||||
assent endp
|
||||
;
|
||||
ddtgetline proc
|
||||
jmp $-22fah
|
||||
ddtgetline endp
|
||||
;
|
||||
goddt proc
|
||||
jmp $-22fah
|
||||
goddt endp
|
||||
;
|
||||
ddtset proc
|
||||
jmp $-22fah
|
||||
ddtset endp
|
||||
;
|
||||
code ends
|
||||
end
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* C P M . H */
|
||||
/* --------- */
|
||||
/* Copyright 1982 by Digital Research Inc. All rights reserved. */
|
||||
/* */
|
||||
/* Edits: */
|
||||
/* 6-Oct-83 whf Redefine reserved area in fcb for parsefn() return */
|
||||
/* 25-June-83 sw Add user number to file "fd" structure. */
|
||||
/* */
|
||||
/* This file contains CP/M specific definitions for the CP/M */
|
||||
/* C Run Time Library. */
|
||||
/* This file is intended only for inclusion with those functions */
|
||||
/* dealing directly with the BDOS, as well as any function which */
|
||||
/* has hardware dependent code (byte storage order, for instance). */
|
||||
/* */
|
||||
/* <portab.h> must be included BEFORE this file. */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* CP/M FCB definition
|
||||
*/
|
||||
|
||||
struct fcbtab /****************************/
|
||||
{ /* */
|
||||
BYTE drive; /* Disk drive field */
|
||||
BYTE fname[8]; /* File name */
|
||||
BYTE ftype[3]; /* File type */
|
||||
BYTE extent; /* Current extent number */
|
||||
BYTE s1,s2; /* "system reserved" */
|
||||
BYTE reccnt; /* Record counter */
|
||||
BYTE fpasswd[8]; /* Parsefn passwd area */
|
||||
BYTE fuser; /* Parsefn user# area */
|
||||
BYTE resvd[7]; /* More "system reserved" */
|
||||
LONG record; /* Note -- we overlap the */
|
||||
/* current record field to */
|
||||
/* make this useful. */
|
||||
}; /****************************/
|
||||
#define SECSIZ 128 /* size of CP/M sector */
|
||||
#define _MAXSXFR 1 /* max # sectors xferrable */
|
||||
#define _MAXSHFT 12 /* shift right BDOS rtn val */
|
||||
/* to obtain nsecs on err */
|
||||
/****************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* Channel Control Block (CCB) */
|
||||
/* */
|
||||
/* One CCB is allocated (statically) for each of the 16 possible open */
|
||||
/* files under C (including STDIN, STDOUT, STDERR). Permanent data */
|
||||
/* regarding the channel is kept here. */
|
||||
/* */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
struct ccb /************************************/
|
||||
{ /* */
|
||||
WORD flags; /*sw Flags byte */
|
||||
BYTE user; /*sw User # */
|
||||
BYTE chan; /* Channel number being used */
|
||||
LONG offset; /* File offset word (bytes) */
|
||||
LONG sector; /* Sector currently in buffer */
|
||||
LONG hiwater; /* High water mark */
|
||||
struct fcbtab fcb; /* File FCB (may have TTY info)*/
|
||||
BYTE buffer[SECSIZ]; /* Read/write buffer */
|
||||
}; /************************************/
|
||||
|
||||
#define MAXCCBS 16 /* Maximum # CC Blocks */
|
||||
extern struct ccb _fds[]; /* */ /* Declare storage */
|
||||
#define FD struct ccb /* FD Type definition */
|
||||
/************************************/
|
||||
/* Flags word bit definitions */
|
||||
/************************************/
|
||||
#define OPENED 0x01 /* Channel is OPEN */
|
||||
#define ISTTY 0x02 /* Channel open to TTT */
|
||||
#define ISLPT 0x04 /* Channel open to LPT */
|
||||
#define ISREAD 0x08 /* Channel open readonly */
|
||||
#define ISASCII 0x10 /* ASCII file attached */
|
||||
#define ATEOF 0x20 /* End of file encountered */
|
||||
#define DIRTY 0x40 /* Buffer needs writing */
|
||||
#define ISSPTTY 0x80 /* Special tty info */
|
||||
#define ISAUX 0x100 /*sw Auxiliary device */
|
||||
/************************************/
|
||||
#define READ 0 /* Read mode parameter for open */
|
||||
#define WRITE 1 /* Write mode */
|
||||
|
||||
/* CCB manipulation macros *************************************/
|
||||
#define _getccb(i) (&_fds[i]) /* Get CCB addr */
|
||||
|
||||
/* Error handling *************************************/
|
||||
EXTERN WORD errno; /* error place for assigning */
|
||||
EXTERN WORD __cpmrv; /* the last BDOS return value */
|
||||
EXTERN WORD _errcpm; /* place to save __cpmrv */
|
||||
#define RETERR(val,err) {errno=(err);_errcpm=__cpmrv;return(val);}
|
||||
/************************************/
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* B D O S F u n c t i o n D e f i n i t i o n s */
|
||||
/* ------------------------------------------------- */
|
||||
/* */
|
||||
/* Following are BDOS function definitions used by the C runtime */
|
||||
/* library. */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************/
|
||||
#if CPM68K /* */
|
||||
#define __OSIF(fn,arg) __BDOS((fn),(LONG)(arg)) /* CPM68K does it this way */
|
||||
#else /* */
|
||||
#define __OSIF(fn,arg) __BDOS((fn),(arg)) /* DRC does it this way */
|
||||
#endif /* */
|
||||
/****************************/
|
||||
#define EXIT 0 /* Exit to BDOS */
|
||||
#define CONIN 1 /* direct echoing con input */
|
||||
#define CONOUT 2 /* Direct console output */
|
||||
#define LSTOUT 5 /* Direct list device output*/
|
||||
#define CONIO 6 /* Direct console I/O */
|
||||
#define C_WRITESTR 9 /* Console string output */
|
||||
#define CONBUF 10 /* Read console buffer */
|
||||
#define OPEN 15 /* OPEN a disk file */
|
||||
#define CLOSE 16 /* Close a disk file */
|
||||
#define SEARCHF 17 /* Search for first */
|
||||
#define SEARCHN 18 /* Search for next */
|
||||
#define DELETE 19 /* Delete a disk file */
|
||||
#define CREATE 22 /* Create a disk file */
|
||||
#define F_RENAME 23 /* Rename a disk file */
|
||||
#define SETDMA 26 /* Set DMA address */
|
||||
#define USER 32 /*sw Get / set user number */
|
||||
#define B_READ 33 /* Read Random record */
|
||||
#define B_WRITE 34 /* Write Random record */
|
||||
#define FILSIZ 35 /* Compute File Size */
|
||||
#define SETMSC 44 /* Set Multi-Sector Count */
|
||||
#define P_CHAIN 47 /* Program Chain */
|
||||
#define SETVEC 61 /* Set exception vector */
|
||||
#define C_DELIMIT 110 /* Get/Set Output Delimiter */
|
||||
/****************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/* Other CP/M definitions */
|
||||
/****************************************************************************/
|
||||
#define TERM "CON:" /* Console file name */
|
||||
#define LIST "LST:" /* List device file name */
|
||||
#define EOFCHAR 0x1a /* End of file character-^Z */
|
||||
/****************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/* Hardware dependencies */
|
||||
/****************************************************************************/
|
||||
#include "machine.h" /* For which machine? */
|
||||
/****************************/
|
||||
#ifdef MC68000 || Z8000 /* 68K or Z8000 */
|
||||
#define HILO 1 /* used when bytes stored */
|
||||
#else /* */
|
||||
#define HILO 0 /* */
|
||||
#endif /* */
|
||||
/* */
|
||||
#if HILO /* Hi/Lo storage used in */
|
||||
struct { /* 68K */
|
||||
BYTE lbhihi; /* Use this for accessing */
|
||||
BYTE lbhilo; /* ordered bytes in 32 bit*/
|
||||
BYTE lblohi; /* LONG qtys. */
|
||||
BYTE lblolo; /* */
|
||||
}; /* */
|
||||
struct { /* Use this for accessing */
|
||||
WORD lwhi; /* ordered words in 32 bit*/
|
||||
WORD lwlo; /* LONG qtys. */
|
||||
}; /* */
|
||||
#else /****************************/
|
||||
struct { /* Lo/Hi storage use on */
|
||||
BYTE lblolo; /* PDP-11, VAX, 8086,... */
|
||||
BYTE lblohi; /* */
|
||||
BYTE lbhilo; /* */
|
||||
BYTE lbhihi; /* */
|
||||
}; /* */
|
||||
struct { /* */
|
||||
WORD lwlo; /* */
|
||||
WORD lwhi; /* */
|
||||
}; /* */
|
||||
#endif /****************************/
|
||||
/*************************** end of cpm.h ***********************************/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,596 @@
|
||||
$title('8086 disassembler')
|
||||
$date(5/14/81)
|
||||
$compact
|
||||
$optimize(2)
|
||||
|
||||
disem86: do;
|
||||
|
||||
declare
|
||||
cr literally '0dh',
|
||||
lf literally '0ah',
|
||||
true literally '1',
|
||||
false literally '0';
|
||||
|
||||
$include(optab.dat)
|
||||
|
||||
declare
|
||||
tab$ptrs (5) address public initial (.ops2, .ops3, .ops4, .ops5, .ops6);
|
||||
|
||||
declare
|
||||
left$bracket byte data ('['),
|
||||
right$bracket byte data (']');
|
||||
|
||||
declare
|
||||
alt$table$base address,
|
||||
alt$table based alt$table$base (16) byte,
|
||||
alt$table$ptrs (8) address external;
|
||||
|
||||
declare
|
||||
mod$bits byte,
|
||||
reg$bits byte,
|
||||
rm$bits byte,
|
||||
byte1$reg$bits byte,
|
||||
d$bit byte,
|
||||
s$bit byte,
|
||||
v$bit byte,
|
||||
w$bit byte,
|
||||
z$bit byte;
|
||||
|
||||
declare
|
||||
mnemonic$index byte, /* index into opcodes */
|
||||
instr$type byte,
|
||||
table$ptr address,
|
||||
table$char based table$ptr byte,
|
||||
disem$ptr pointer,
|
||||
disem$offset address at (.disem$ptr),
|
||||
disem$end address,
|
||||
disem$byte based disem$ptr (1) byte,
|
||||
disem$word based disem$ptr (1) address,
|
||||
b$or$w$flag byte,
|
||||
error$flag byte;
|
||||
|
||||
declare instr$table (512) byte external;
|
||||
|
||||
declare
|
||||
ax$reg literally '0',
|
||||
cx$reg literally '1',
|
||||
dx$reg literally '2',
|
||||
bx$reg literally '3',
|
||||
sp$reg literally '4',
|
||||
bp$reg literally '5',
|
||||
si$reg literally '6',
|
||||
di$reg literally '7';
|
||||
|
||||
declare
|
||||
al$reg literally '0',
|
||||
cl$reg literally '1',
|
||||
dl$reg literally '2',
|
||||
bl$reg literally '3',
|
||||
ah$reg literally '4',
|
||||
ch$reg literally '5',
|
||||
dh$reg literally '6',
|
||||
bh$reg literally '7';
|
||||
|
||||
declare
|
||||
es$reg literally '0',
|
||||
cs$reg literally '1',
|
||||
ss$reg literally '2',
|
||||
ds$reg literally '3';
|
||||
|
||||
declare
|
||||
reg16 (*) byte public initial ('AX', 'CX', 'DX', 'BX', 'SP', 'BP', 'SI', 'DI'),
|
||||
reg8 (*) byte public initial ('AL', 'CL', 'DL', 'BL', 'AH', 'CH', 'DH', 'BH'),
|
||||
segreg (*) byte public initial ('ES', 'CS', 'SS', 'DS');
|
||||
|
||||
conout: procedure (c) external;
|
||||
declare c byte;
|
||||
end conout;
|
||||
|
||||
comma: procedure;
|
||||
call conout (',');
|
||||
end comma;
|
||||
|
||||
printm: procedure (a) PUBLIC;
|
||||
declare a address;
|
||||
declare b based a byte;
|
||||
do while b <> '$';
|
||||
call conout (b);
|
||||
a = a + 1;
|
||||
end;
|
||||
end printm;
|
||||
|
||||
print$nibble: procedure (b);
|
||||
declare b byte;
|
||||
if b > 9 then call conout (b - 10 + 'A');
|
||||
else call conout (b + '0');
|
||||
end print$nibble;
|
||||
|
||||
print$byte: procedure (b);
|
||||
declare b byte;
|
||||
call print$nibble (shr (b, 4));
|
||||
call print$nibble (b and 0fh);
|
||||
end print$byte;
|
||||
|
||||
print$word: procedure (a) public;
|
||||
declare a address;
|
||||
call print$byte (high (a));
|
||||
call print$byte (low (a));
|
||||
end print$word;
|
||||
|
||||
error: procedure;
|
||||
call printm (.('??= $'));
|
||||
call print$byte (disem$byte (0));
|
||||
disem$offset = disem$offset + 1;
|
||||
end error;
|
||||
|
||||
set$bits: procedure;
|
||||
byte1$reg$bits = disem$byte (0) and 7;
|
||||
mod$bits = shr (disem$byte (1), 6);
|
||||
reg$bits = shr (disem$byte (1), 3) and 7;
|
||||
rm$bits = disem$byte (1) and 7;
|
||||
w$bit, z$bit = disem$byte (0) and 1;
|
||||
d$bit, s$bit, v$bit = shr (disem$byte (0), 1) and 1;
|
||||
end set$bits;
|
||||
|
||||
print$b$or$w: procedure;
|
||||
if w$bit then call printm (.('WORD $'));
|
||||
else call printm (.('BYTE $'));
|
||||
end print$b$or$w;
|
||||
|
||||
print$reg: procedure (reg$add, reg);
|
||||
declare reg$add address, reg byte;
|
||||
table$ptr = reg$add + shl (reg, 1);
|
||||
call conout (table$char);
|
||||
table$ptr = table$ptr + 1;
|
||||
call conout (table$char);
|
||||
end print$reg;
|
||||
|
||||
print$reg8: procedure (reg);
|
||||
declare reg byte;
|
||||
call print$reg (.reg8, reg);
|
||||
end print$reg8;
|
||||
|
||||
print$reg16: procedure (reg);
|
||||
declare reg byte;
|
||||
call print$reg (.reg16, reg);
|
||||
end print$reg16;
|
||||
|
||||
print$reg$8$or$16: procedure (reg$num);
|
||||
declare reg$num byte;
|
||||
if w$bit then call print$reg$16 (reg$num);
|
||||
else call print$reg$8 (reg$num);
|
||||
end print$reg$8$or$16;
|
||||
|
||||
print$2$reg$16: procedure (r1, r2);
|
||||
declare (r1, r2) byte;
|
||||
call print$reg$16 (r1);
|
||||
call conout ('+');
|
||||
call print$reg$16 (r2);
|
||||
end print$2$reg$16;
|
||||
|
||||
print$A$reg: procedure;
|
||||
if w$bit then call print$reg$16 (ax$reg);
|
||||
else call print$reg$8 (al$reg);
|
||||
end print$A$reg;
|
||||
|
||||
print$seg$reg: procedure (reg);
|
||||
declare reg byte;
|
||||
call print$reg (.seg$reg, reg);
|
||||
end print$seg$reg;
|
||||
|
||||
print$data$8: procedure;
|
||||
call print$byte (disem$byte (0));
|
||||
disem$offset = disem$offset + 1;
|
||||
end print$data$8;
|
||||
|
||||
print$data$16: procedure;
|
||||
call print$word (disem$word (0));
|
||||
disem$offset = disem$offset + 2;
|
||||
end print$data$16;
|
||||
|
||||
print$data$8$or$16: procedure;
|
||||
if w$bit then call print$data$16;
|
||||
else call print$data$8;
|
||||
end print$data$8$or$16;
|
||||
|
||||
print$data$sw: procedure;
|
||||
if rol (disem$byte (0), 1) then call print$word (0ff00h or disem$byte (0));
|
||||
else call print$word (disem$byte (0));
|
||||
disem$offset = disem$offset + 1;
|
||||
end print$data$sw;
|
||||
|
||||
print$signed$8: procedure;
|
||||
declare a address;
|
||||
a = disem$byte (0);
|
||||
if low (a) >= 80h then a = a or 0ff00h; /* sign extend to 16 bits */
|
||||
call print$word (disem$offset + a + 1);
|
||||
disem$offset = disem$offset + 1;
|
||||
end print$signed$8;
|
||||
|
||||
print$signed$16: procedure;
|
||||
call print$word (disem$offset + disem$word (0) + 2);
|
||||
disem$offset = disem$offset + 2;
|
||||
end print$signed$16;
|
||||
|
||||
print$direct$addr: procedure;
|
||||
call conout (left$bracket);
|
||||
call print$word (disem$word (0));
|
||||
call conout (right$bracket);
|
||||
disem$offset = disem$offset + 2;
|
||||
end print$direct$addr;
|
||||
|
||||
print$mod$rm: procedure;
|
||||
disem$offset = disem$offset + 1; /* point past mod/reg/rm byte */
|
||||
if mod$bits = 3 then
|
||||
do;
|
||||
call print$reg$8$or$16 (rm$bits);
|
||||
return;
|
||||
end;
|
||||
if b$or$w$flag then call print$b$or$w;
|
||||
if rm$bits = 6 and mod$bits = 0 then
|
||||
do;
|
||||
call print$direct$addr;
|
||||
return;
|
||||
end;
|
||||
if mod$bits = 1 then
|
||||
do;
|
||||
if (rm$bits <> 6) or (disem$byte (0) <> 0)
|
||||
then call print$byte (disem$byte (0));
|
||||
disem$offset = disem$offset + 1;
|
||||
end;
|
||||
else if mod$bits = 2 then
|
||||
do;
|
||||
call print$word (disem$word (0));
|
||||
disem$offset = disem$offset + 2;
|
||||
end;
|
||||
call conout (left$bracket);
|
||||
do case rm$bits;
|
||||
call print$2$reg$16 (3, 6);
|
||||
call print$2$reg$16 (3, 7);
|
||||
call print$2$reg$16 (5, 6);
|
||||
call print$2$reg$16 (5, 7);
|
||||
call print$reg$16 (6);
|
||||
call print$reg$16 (7);
|
||||
call print$reg$16 (5);
|
||||
call print$reg$16 (3);
|
||||
end;
|
||||
call conout (right$bracket);
|
||||
end print$mod$rm;
|
||||
|
||||
print$mod$reg$rm: procedure;
|
||||
if d$bit then
|
||||
do;
|
||||
call print$reg$8$or$16 (reg$bits);
|
||||
call conout (',');
|
||||
call print$mod$rm;
|
||||
end;
|
||||
else
|
||||
do;
|
||||
call print$mod$rm;
|
||||
call conout (',');
|
||||
call print$reg$8$or$16 (reg$bits);
|
||||
end;
|
||||
end print$mod$reg$rm;
|
||||
|
||||
print$mnemonic: procedure;
|
||||
declare (len, i) byte;
|
||||
len = 2;
|
||||
do while mnemonic$index >= opn$in (len - 1);
|
||||
len = len + 1;
|
||||
end;
|
||||
table$ptr = tab$ptrs (len - 2) + (mnemonic$index - opn$in (len - 2))
|
||||
* len;
|
||||
do i = 1 to 7;
|
||||
if i <= len then
|
||||
do;
|
||||
call conout (table$char);
|
||||
table$ptr = table$ptr + 1;
|
||||
end;
|
||||
else call conout (' ');
|
||||
end;
|
||||
disem$offset = disem$offset + 1;
|
||||
end print$mnemonic;
|
||||
|
||||
type1: procedure;
|
||||
call print$mnemonic;
|
||||
end type1;
|
||||
|
||||
type2: procedure;
|
||||
if disem$byte (1) = 0ah then
|
||||
do;
|
||||
call print$mnemonic;
|
||||
disem$offset = disem$offset + 1;
|
||||
end;
|
||||
else error$flag = true;
|
||||
end type2;
|
||||
|
||||
type3: procedure;
|
||||
call print$mnemonic;
|
||||
call print$reg$16 (byte1$reg$bits);
|
||||
end type3;
|
||||
|
||||
type4: procedure;
|
||||
declare temp byte;
|
||||
temp = shr (disem$byte (0), 3) and 3;
|
||||
call print$mnemonic;
|
||||
call print$segreg (temp);
|
||||
end type4;
|
||||
|
||||
type5: procedure;
|
||||
call print$mnemonic;
|
||||
call print$signed$8;
|
||||
end type5;
|
||||
|
||||
type6: procedure;
|
||||
call print$mnemonic;
|
||||
call print$signed$16;
|
||||
end type6;
|
||||
|
||||
type8: procedure; /* 7, 9 */
|
||||
call print$mnemonic;
|
||||
call print$mod$rm;
|
||||
end type8;
|
||||
|
||||
type10: procedure;
|
||||
call print$mnemonic;
|
||||
call print$data$8;
|
||||
end type10;
|
||||
|
||||
type11: procedure;
|
||||
call print$mnemonic;
|
||||
call print$data$16;
|
||||
end type11;
|
||||
|
||||
type12: procedure;
|
||||
call print$mnemonic;
|
||||
call conout ('3');
|
||||
end type12;
|
||||
|
||||
type13: procedure;
|
||||
declare temp address;
|
||||
call print$mnemonic;
|
||||
temp = disem$word (0);
|
||||
disem$offset = disem$offset + 2;
|
||||
call print$data$16;
|
||||
call conout (':');
|
||||
call print$word (temp);
|
||||
end type13;
|
||||
|
||||
type14: procedure; /* 15, 16, 17 */
|
||||
call print$mnemonic;
|
||||
call print$mod$reg$rm;
|
||||
end type14;
|
||||
|
||||
type18: procedure; /* 19, 20, 21 */
|
||||
call print$mnemonic;
|
||||
if d$bit then
|
||||
do;
|
||||
call print$direct$addr;
|
||||
call comma;
|
||||
call print$A$reg;
|
||||
end;
|
||||
else
|
||||
do;
|
||||
call print$A$reg;
|
||||
call comma;
|
||||
call print$direct$addr;
|
||||
end;
|
||||
end type18;
|
||||
|
||||
type22: procedure;
|
||||
call print$mnemonic;
|
||||
if d$bit then
|
||||
do;
|
||||
call print$data$8;
|
||||
call comma;
|
||||
call print$A$reg;
|
||||
end;
|
||||
else
|
||||
do;
|
||||
call print$A$reg;
|
||||
call comma;
|
||||
call print$data$8;
|
||||
end;
|
||||
end type22;
|
||||
|
||||
type23: procedure; /* 24 */
|
||||
call print$mnemonic;
|
||||
call print$A$reg;
|
||||
call comma;
|
||||
call print$data$8$or$16;
|
||||
end type23;
|
||||
|
||||
type25: procedure; /* 26 */
|
||||
call print$mnemonic;
|
||||
if d$bit then
|
||||
do;
|
||||
call print$reg$16 (dx$reg);
|
||||
call comma;
|
||||
call print$A$reg;
|
||||
end;
|
||||
else
|
||||
do;
|
||||
call print$A$reg;
|
||||
call comma;
|
||||
call print$reg$16 (dx$reg);
|
||||
end;
|
||||
end type25;
|
||||
|
||||
type27: procedure; /* 28, 29, 30 */
|
||||
call print$mnemonic;
|
||||
b$or$w$flag = true;
|
||||
call print$mod$rm;
|
||||
call comma;
|
||||
if v$bit then call print$reg$8 (cl$reg);
|
||||
else call conout ('1');
|
||||
end type27;
|
||||
|
||||
type31: procedure; /* 32 */
|
||||
call setbits;
|
||||
reg$bits = byte1$reg$bits;
|
||||
w$bit = shr (disem$byte (0), 3) and 1;
|
||||
call print$mnemonic;
|
||||
call print$reg$8$or$16 (reg$bits);
|
||||
call comma;
|
||||
call print$data$8$or$16;
|
||||
end type31;
|
||||
|
||||
type33: procedure;
|
||||
call print$mnemonic;
|
||||
call print$reg$16 (ax$reg);
|
||||
call comma;
|
||||
call print$reg$16 (byte1$reg$bits);
|
||||
end type33;
|
||||
|
||||
type34: procedure; /* 35 */
|
||||
call print$mnemonic;
|
||||
b$or$w$flag = true;
|
||||
call print$mod$rm;
|
||||
call comma;
|
||||
call print$data$8$or$16;
|
||||
end type34;
|
||||
|
||||
type36: procedure; /* 37 */
|
||||
w$bit = true; /* force 16 bit reg, mem */
|
||||
if reg$bits > 3 then
|
||||
do;
|
||||
error$flag = true;
|
||||
return;
|
||||
end;
|
||||
call print$mnemonic;
|
||||
if d$bit then
|
||||
do;
|
||||
call print$seg$reg (reg$bits);
|
||||
call comma;
|
||||
call print$mod$rm;
|
||||
end;
|
||||
else
|
||||
do;
|
||||
call print$mod$rm;
|
||||
call comma;
|
||||
call print$seg$reg (reg$bits);
|
||||
end;
|
||||
end type36;
|
||||
|
||||
type38: procedure;
|
||||
call print$mnemonic;
|
||||
call print$mod$rm;
|
||||
call comma;
|
||||
call print$data$8;
|
||||
end type38;
|
||||
|
||||
type39: procedure;
|
||||
if mod$bits = 3 then
|
||||
do;
|
||||
error$flag = true;
|
||||
return;
|
||||
end;
|
||||
call print$mnemonic;
|
||||
call print$reg$16 (reg$bits);
|
||||
call comma;
|
||||
call print$mod$rm;
|
||||
end type39;
|
||||
|
||||
type40: procedure; /* 41 */
|
||||
if mod$bits = 3 then
|
||||
do;
|
||||
error$flag = true;
|
||||
return;
|
||||
end;
|
||||
call print$mnemonic;
|
||||
b$or$w$flag = true;
|
||||
call print$mod$rm;
|
||||
call comma;
|
||||
call print$data$8$or$16;
|
||||
end type40;
|
||||
|
||||
type42: procedure;
|
||||
call print$mnemonic;
|
||||
call print$byte (shl (byte1$reg$bits, 3) or reg$bits);
|
||||
call comma;
|
||||
call print$mod$rm;
|
||||
end type42;
|
||||
|
||||
type44: procedure;
|
||||
call print$mnemonic;
|
||||
b$or$w$flag = true;
|
||||
call print$modrm;
|
||||
call comma;
|
||||
if s$bit = 1 and w$bit = 1 then call print$data$sw;
|
||||
else call print$data$8$or$16;
|
||||
end type44;
|
||||
|
||||
type45: procedure;
|
||||
b$or$w$flag = true;
|
||||
call type8;
|
||||
end type45;
|
||||
|
||||
dis: procedure;
|
||||
error$flag, b$or$w$flag = false;
|
||||
call set$bits;
|
||||
if instr$type = 26 then
|
||||
do;
|
||||
alt$table$base = alt$table$ptrs (mnemonic$index);
|
||||
mnemonic$index = alt$table (reg$bits * 2);
|
||||
instr$type = alt$table (reg$bits * 2 + 1);
|
||||
end;
|
||||
if instr$type > 28 then error$flag = true;
|
||||
else
|
||||
do case instr$type;
|
||||
error$flag = true;
|
||||
call type1;
|
||||
call type2;
|
||||
call type3;
|
||||
call type4;
|
||||
call type5;
|
||||
call type6;
|
||||
call type8;
|
||||
call type10;
|
||||
call type11;
|
||||
call type12;
|
||||
call type13;
|
||||
call type14;
|
||||
call type18;
|
||||
call type22;
|
||||
call type23;
|
||||
call type25;
|
||||
call type27;
|
||||
call type31;
|
||||
call type33;
|
||||
call type34;
|
||||
call type36;
|
||||
call type38;
|
||||
call type39;
|
||||
call type40;
|
||||
call type42;
|
||||
;
|
||||
call type44;
|
||||
call type45;
|
||||
end;
|
||||
if error$flag then call error;
|
||||
end dis;
|
||||
|
||||
disem: procedure (disloc) address public;
|
||||
declare disloc pointer;
|
||||
declare nprefix byte;
|
||||
disem$ptr = disloc;
|
||||
nprefix = 0;
|
||||
do while true;
|
||||
mnemonic$index = instr$table (disem$byte (0) * 2);
|
||||
instr$type = instr$table (disem$byte (0) * 2 + 1);
|
||||
if instr$type = 0ffh and nprefix < 3 then
|
||||
do;
|
||||
call print$mnemonic;
|
||||
nprefix = nprefix + 1;
|
||||
end;
|
||||
else
|
||||
do;
|
||||
if instr$type = 0ffh then instr$type = 1;
|
||||
call dis;
|
||||
return disem$offset;
|
||||
end;
|
||||
end;
|
||||
end disem;
|
||||
|
||||
end disem86;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
;
|
||||
; interface module for ddt86 disassembler
|
||||
; 7/15/82
|
||||
;
|
||||
dgroup group dats
|
||||
dats segment public 'DATS'
|
||||
db '?'
|
||||
dats ends
|
||||
cgroup group code
|
||||
extrn disem:near
|
||||
public boot
|
||||
public conin,conout
|
||||
code segment public 'CODE'
|
||||
assume cs:cgroup
|
||||
disent proc
|
||||
org 1500h
|
||||
jmp disem
|
||||
disent endp
|
||||
boot proc
|
||||
ret
|
||||
boot endp
|
||||
conin proc
|
||||
jmp $-1401h
|
||||
conin endp
|
||||
conout proc
|
||||
jmp $-1401h
|
||||
conout endp
|
||||
code ends
|
||||
end
|
||||
|
||||
@@ -0,0 +1,534 @@
|
||||
/**************************************************************************
|
||||
* G E N C C P M - generates an operating system
|
||||
*
|
||||
* Written by Bill Fitler Nov. 1982
|
||||
*
|
||||
* GENCCPM is designed to edit the system image for the operating system
|
||||
* and construct an initialized, loadable image for execution.
|
||||
* GENCCPM was originally designed for Concurrent CP/M-86 v2.0, and was
|
||||
* modelled after the old GENSYS.
|
||||
*
|
||||
* Revision history:
|
||||
* 10 Feb 84 whf: bug fixes: addmem, fixupxios_info, and qbuf limits (glp)
|
||||
* 08 Jan 84 glp: added support for Extended DPB
|
||||
* 15 Dec 83 fmb: changed ncondev,nciodev initialization
|
||||
* 5 Oct 83 whf: converted to DRC, broke apart modules, added ADDRs
|
||||
* 9 Sep 83 fmb: compiler bug fix for daend in gentables
|
||||
* 4 Aug 83 fmb: version number -> 3.1
|
||||
* 14 Jun 83 whf: fix flags & large xios bugs
|
||||
* 8 Jun 83 fmb: handles Multi-User Concurrent 3.1
|
||||
* 31 May 83 fmb: added sd_xpcns init for Multi-User CCP/M 3.1 .
|
||||
* 23 Feb 83 whf: add patch module
|
||||
* 25 Jan 83 whf: combine all modules for easier maintenance
|
||||
* 20 Jan 83 whf: handles SYSDAT overflow
|
||||
* 19 Nov 82 whf: added BDOS buffering generation.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
|
||||
/*******************************/
|
||||
/* for serialization purposes: */
|
||||
char *copynote = "COPYRIGHT (C) 1983, DIGITAL RESEARCH XXXX-0000-654321 $";
|
||||
/****************************************************/
|
||||
/* up front for patching: Note the internal EOS (0) */
|
||||
char *clearx = "\033H\033E\0\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
|
||||
/****************************************************/
|
||||
|
||||
/****** include files ********/
|
||||
#define MAINMODULE 1
|
||||
#include <genccpm.h>
|
||||
/*****************************/
|
||||
|
||||
#ifdef CCPM
|
||||
BYTE *edsysver = "GENCCPM v2.1 [2/7/84]\n";
|
||||
#endif
|
||||
#ifdef CMPM
|
||||
BYTE *edsysver = "GENCCPM v3.1 [2/7/84]\n";
|
||||
#endif
|
||||
|
||||
BYTE mainmtitle[50] = ""; /* room for title of main menu */
|
||||
MENU *mainmenu = NULLPTRI; /* pointers to main menu items */
|
||||
MENU *memmenu=NULLPTRI; /* memory management menu */
|
||||
MENU *syspmenu=NULLPTRI; /* system parameters menu */
|
||||
MENU *rspmenu=NULLPTRI; /* rsp edit menu */
|
||||
|
||||
/**************************************************************************/
|
||||
/* main module */
|
||||
/**************************************************************************/
|
||||
|
||||
main(ac,av)
|
||||
WORD ac;
|
||||
BYTE **av;
|
||||
{
|
||||
BYTE cmds[CMDSLEN]; /* input area of commands */
|
||||
BOOLEAN sysvalid(); /* is the system data valid? */
|
||||
|
||||
fprintf(stderr,edsysver);
|
||||
if( isatty(1) ) /* standard output to a tty? */
|
||||
clearit = clearx; /* yes, do clear screens */
|
||||
else clearit = ""; /* no, don't do clear screens */
|
||||
init_sysdat(); /* initialize system data */
|
||||
init_edsys(); /* initialize menus */
|
||||
if( ac>1 ) { /* if any command line arguments */
|
||||
copyargs(ac-1,av+1,cmds); /* simplify cmd parser */
|
||||
verbose = TRUE; /* turn on wordiness by default */
|
||||
domenu(cmds,mainmenu); /* do what they've asked for */
|
||||
}
|
||||
FOREVER { /* work with user for a while */
|
||||
if(doit) { /* does user want to quit? */
|
||||
if( sysvalid() ) /* has evrything been defined? */
|
||||
break; /* let them if everything okay */
|
||||
press_return(); /* let them view the message(s) */
|
||||
}
|
||||
printf("%s",clearit); /* clear the screen */
|
||||
prtmenu(mainmtitle,mainmenu); /* display user options */
|
||||
printf(PROMPT); /* prompt user */
|
||||
if( gets(cmds)!=cmds ){ /* on end of file */
|
||||
close(0); /* standard input */
|
||||
open("CON:",0); /* reopen to the console */
|
||||
close(1); /* standard output: assume redirection */
|
||||
open("CON:",1); /* reopen to console */
|
||||
clearit = clearx; /* do the clear screen routine */
|
||||
continue; /* force user to input blank line */
|
||||
}
|
||||
if( *cmds==NULL ) /* blank line of input */
|
||||
continue; /* don't bother with blank lines here */
|
||||
domenu(cmds,mainmenu); /* do what they've asked for */
|
||||
} /*****************************/
|
||||
/* we've got user input */
|
||||
make_sysfile(); /* construct system image/use old one*/
|
||||
gentables(); /* generate the tables */
|
||||
fixups(); /* odds and ends on the system image */
|
||||
wrapup(); /* close files, etc. */
|
||||
}
|
||||
|
||||
/* copyargs: copies args to cbuf for uniform parsing */
|
||||
copyargs(ac,av,cbuf)
|
||||
WORD ac;
|
||||
BYTE **av;
|
||||
BYTE *cbuf;
|
||||
{
|
||||
for( *cbuf=NULL; ac>0; --ac, ++av ) {
|
||||
strcat(cbuf,*av);
|
||||
strcat(cbuf," ");
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* init_sysdat: reads SYStem DATa info from:
|
||||
/* 1. SYSFILE, if it exists
|
||||
/* 2. SYSMOD, o.w. if this is the case, it also checks
|
||||
/* for existence of all other required modules
|
||||
/**************************************************************************/
|
||||
VOID init_sysdat()
|
||||
{
|
||||
REG WORD sf; /* file descriptor for SysData read */
|
||||
LONG grpseek(); /* seek the data group */
|
||||
UWORD goffs; /* loc of group */
|
||||
EXTERN DLIST *rsps, *dirsearch(); /* directory search fn */
|
||||
BYTE *addmem(); /* for initializing memory */
|
||||
BYTE *chkmodules(), *xlist[80]; /* list of missing modules */
|
||||
|
||||
printf("GENerate SYStem image for %s\n",VERLABEL);
|
||||
init_sds(sdat_area); /* initialize program ptrs */
|
||||
/***************************************************/
|
||||
if(chkmodules(xlist)==NULLPTR && (sf=BROPEN(SYSMOD)) > 0 ) {
|
||||
printf("Constructing new %s file\n",SYSFILE);
|
||||
/*** procedureize this? for cmd use */
|
||||
dogensys=TRUE; /* no SYSFILE, read from modules */
|
||||
if(grpseek(sf,GTYPDATA)<0) /* seek start of data group */
|
||||
CRASH("no data group in SYSDAT module\n");
|
||||
read(sf,sdat_area,SDLEN); /* read in the data group */
|
||||
/**** may have to init arbitrarily some MAX values here ****/
|
||||
xtrapds = *sd_pul; /* default number of extra process descriptors */
|
||||
totqcbs = *sd_qul; /* default number of qcbs */
|
||||
totopen = 0x40; /* arbitrary total open files & locked recs */
|
||||
qbuflen = *sd_qmalen; /* init'ed to bytes */
|
||||
rsps = dirsearch("*.RSP"); /* init RSP list */
|
||||
addmem("400,6000,400"); /* start out with this memory allocation */
|
||||
close(sf); /* don't need it for a while */
|
||||
|
||||
sf=BROPEN(XIOSMOD); /* let's go read the XIOS info */
|
||||
if( grpseek(sf,GTYPDATA) <= 0 ) /* if there is not a data group */
|
||||
grpseek(sf,GTYPCODE); /* use the code group instead */
|
||||
goffs = lseek( sf,0L,1 ); /* where did we end up? */
|
||||
initxios_info(sf,goffs); /* grab info from there */
|
||||
close(sf); /* don't need it for a while */
|
||||
|
||||
} else if( FALSE && /****** temporarily disable this option!!! ***/
|
||||
(sf=BROPEN(SYSFILE)) >= 0 ){ /* does SYSFILE exist? *******/
|
||||
printf("Editting %s file\n",SYSFILE);
|
||||
dogensys = FALSE; /* tell them not to gen a new system */
|
||||
grpseek(sf,GTYPDATA); /* get data module in OS */
|
||||
read(sf,sdat_area,SDLEN); /* read in the info */
|
||||
/**** may have to trace down some lists for MAX values ****/
|
||||
close(sf); /* don't need it for a while */
|
||||
} else { /***************************************************/
|
||||
if( xlist == NULLPTR ) {
|
||||
fprintf(stderr,"Can't find %s module\n",SYSMOD);
|
||||
} else {
|
||||
fprintf(stderr,"Can't find these modules:\n%s\n",xlist);
|
||||
}
|
||||
fprintf(stderr,"Please find the correct modules\n");
|
||||
exit(1);
|
||||
} /**** end module check ****/
|
||||
if( VERSION != *sd_mpmvn ){ /* a little version number checking */
|
||||
USERR("%s works on OS version %x\n",edsysver,VERSION);
|
||||
USERR("Sys Data area found was from OS version %x\n",*sd_mpmvn);
|
||||
USERR("Please find correct .SYS or %s files\n",MODEXT);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
#define RDAC 4 /* Read Access mode for 'access' */
|
||||
BYTE *
|
||||
chkmodules(badbuf) /* place to put missing module names */
|
||||
BYTE *badbuf;
|
||||
{
|
||||
|
||||
*badbuf=0;
|
||||
if( access(SYSMOD,RDAC) ) {strcat(badbuf,SYSMOD);strcat(badbuf," ");}
|
||||
if( access(SUPMOD,RDAC) ) {strcat(badbuf,SUPMOD);strcat(badbuf," ");}
|
||||
if( access(RTMMOD,RDAC) ) {strcat(badbuf,RTMMOD);strcat(badbuf," ");}
|
||||
if( access(MEMMOD,RDAC) ) {strcat(badbuf,MEMMOD);strcat(badbuf," ");}
|
||||
if( access(CIOMOD,RDAC) ) {strcat(badbuf,CIOMOD);strcat(badbuf," ");}
|
||||
if( access(BDOSMOD,RDAC) ) {strcat(badbuf,BDOSMOD);strcat(badbuf," ");}
|
||||
if( access(XIOSMOD,RDAC) ) {strcat(badbuf,XIOSMOD);strcat(badbuf," ");}
|
||||
if( *badbuf )
|
||||
return badbuf;
|
||||
else return NULLPTR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* init_edsys: initializes program variables and menus
|
||||
/**************************************************************************/
|
||||
|
||||
VOID init_edsys()
|
||||
{
|
||||
MENU *m; /* mainmenu pointer */
|
||||
MENU *me; /* memory partitions menu */
|
||||
MENU *s; /* sys params menu */
|
||||
MENU *r; /* rsp menu */
|
||||
MENU *bldmenu(); /* func to build the menu list */
|
||||
BYTE *drvmsg; /* destination drive message */
|
||||
BYTE *delmsg; /* delete old SYSFILE msg */
|
||||
BYTE getdrive(); /* get default drive */
|
||||
BYTE *help(); /* func to help user */
|
||||
BYTE *doxios(); /* func to do xios menu */
|
||||
BYTE *dosysp(); /* func to do sys param menu */
|
||||
BYTE *dorsp(); /* func to display & handle RSPs */
|
||||
BYTE *dolbl(); /* func to modify version label */
|
||||
BYTE *domem(); /* handle memory partitions */
|
||||
BYTE *doxbufs(); /* func to construct bdos buffers */
|
||||
BYTE *addmem(); /* add mem part */
|
||||
BYTE *delmem(); /* delete mem part */
|
||||
BYTE *rspinclude(); /* include a bunch of RSPs */
|
||||
BYTE *rspexclude(); /* exclude a bunch of RSPs */
|
||||
BYTE *doexit(); /* exit the main menu */
|
||||
|
||||
sprintf(mainmtitle,"*** %s %s Main Menu ***",VERLABEL,PROGNAME);
|
||||
destdrv = getdrive(); /* returns the default drive */
|
||||
drvmsg = malloc(50);
|
||||
sprintf(drvmsg,"%s Output To (Destination) Drive",SYSFILE);
|
||||
delmsg = malloc(55);
|
||||
sprintf(delmsg,"Delete (instead of rename) old %s file\n",SYSFILE);
|
||||
m=NULLPTR; me=NULLPTR; s=NULLPTR; r=NULLPTR; /* init menu pointers */
|
||||
|
||||
/***** initialize menus *****/
|
||||
m=bldmenu(m,MPROC,help,"help","GENCCPM Help");
|
||||
m=bldmenu(m,MBOOL,&verbose,"verbose","More Verbose GENCCPM Messages");
|
||||
m=bldmenu(m,MDRIV,&destdrv,"destdrive",drvmsg);
|
||||
m=bldmenu(m,MBOOL,&doclean,"deletesys",delmsg);
|
||||
|
||||
|
||||
m=bldmenu(m,MPROC,dosysp,"sysparams","Display/Change System Parameters");
|
||||
|
||||
s=bldmenu(s,MDRIV,sd_srchdisk,"sysdrive","System Drive");
|
||||
s=bldmenu(s,MDRIV,sd_tempdisk,"tmpdrive","Temporary File Drive");
|
||||
s=bldmenu(s,MBOOL,sd_dayfile,"cmdlogging","Command Day/File Logging at Console");
|
||||
s=bldmenu(s,MBOOL,sd_cmode,"compatmode","CP/M FCB Compatibility Mode");
|
||||
s=bldmenu(s,MWORD,sd_mmp,"memmax","Maximum Memory per Process (paragraphs)");
|
||||
s=bldmenu(s,MBYTE,sd_popen_max,"openmax","Open Files per Process Maximum");
|
||||
s=bldmenu(s,MBYTE,sd_plock_max,"lockmax","Locked Records per Process Maximum\n");
|
||||
|
||||
s=bldmenu(s,MWORD,sd_mpmseg,"osstart","Starting Paragraph of Operating System");
|
||||
s=bldmenu(s,MWORD,&totopen,"nopenfiles","Number of Open File and Locked Record Entries");
|
||||
s=bldmenu(s,MBYTE,&xtrapds,"npdescs","Number of Process Descriptors");
|
||||
s=bldmenu(s,MBYTE,&totqcbs,"nqcbs","Number of Queue Control Blocks");
|
||||
s=bldmenu(s,MWORD,&qbuflen,"qbufsize","Queue Buffer Total Size in bytes");
|
||||
s=bldmenu(s,MBYTE,sd_nflags,"nflags","Number of System Flags");
|
||||
|
||||
|
||||
m=bldmenu(m,MPROC,domem,"memory","Display/Change Memory Allocation Partitions");
|
||||
me=bldmenu(me,MPROC,addmem,"add","ADD Memory Partition(s)");
|
||||
me=bldmenu(me,MPROC,delmem,"delete","DELETE Memory Partition(s)");
|
||||
|
||||
|
||||
m=bldmenu(m,MPROC,doxbufs,"diskbuffers","Display/Change Disk Buffer Allocation");
|
||||
|
||||
if( dogensys )
|
||||
m=bldmenu(m,MPROC,dolbl,"oslabel","Display/Change Operating System Label");
|
||||
|
||||
m=bldmenu(m,MPROC,dorsp,"rsps","Display/Change RSP list\n");
|
||||
r=bldmenu(r,MPROC,rspinclude,"include","Include RSPs");
|
||||
r=bldmenu(r,MPROC,rspexclude,"exclude","Exclude RSPs");
|
||||
|
||||
|
||||
m=bldmenu(m,MPROC,doexit,"gensys","I'm finished changing things, go GEN a SYStem\n");
|
||||
|
||||
|
||||
mainmenu=m; /* assign now to longer name */
|
||||
memmenu=me; /* yah yah */
|
||||
syspmenu=s; /* " " */
|
||||
rspmenu=r; /* " " */
|
||||
}
|
||||
|
||||
|
||||
BYTE *
|
||||
doexit() /* this is really a boolean... */
|
||||
{
|
||||
doit = TRUE;
|
||||
return NULLPTR;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* sysvalid: validates system data.
|
||||
/* also calculates certain SYSDAT variables, in the course of validation.
|
||||
/**************************************************************************/
|
||||
#define BYTE_ADJUST(xx) if( xx > 0xFF ) xx = 0xFF
|
||||
#define ALIGN(xx) (((xx)+0xF) & 0xFFF0)
|
||||
|
||||
BOOLEAN
|
||||
sysvalid()
|
||||
{
|
||||
REG BOOLEAN isv; /* is valid? */
|
||||
BOOLEAN xiosvalid(); /* check xios info */
|
||||
LOCAL WORD nmparts; /* number of memory partitions */
|
||||
|
||||
isv = TRUE; /* innocent until proven guilty */
|
||||
if( totopen < *sd_popen_max ) {
|
||||
USERR("'nopenfiles' is less than 'openmax'. Please adjust.\n");
|
||||
isv = FALSE;
|
||||
}
|
||||
if( totopen < *sd_plock_max ) {
|
||||
USERR("'nopenfiles' is less than 'lockmax'. Please adjust.\n");
|
||||
isv = FALSE;
|
||||
}
|
||||
if( (nmparts=cntmlist(memroot)) <= 0 ) {
|
||||
USERR("Memory Partitions need to be adjusted\n");
|
||||
isv = FALSE;
|
||||
}
|
||||
if( !xiosvalid() ) { /* xios info needs work? */
|
||||
USERR("Disk Performance Buffers need to be adjusted\n");
|
||||
isv=FALSE;
|
||||
}
|
||||
if( !isv )
|
||||
USERR("Please correct the System Parameters\n");
|
||||
return isv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* make_sysfile: responsible for preparing SYSfile image for table generation
|
||||
/* and
|
||||
/* if( dousesys )
|
||||
/* doctors up SYSFILE for appropriate table generation and fixups
|
||||
/* else constructs a SYSfile from assembled modules
|
||||
/**************************************************************************/
|
||||
VOID make_sysfile()
|
||||
{
|
||||
BYTE fbuf[20]; /* file name buffer */
|
||||
|
||||
PUTDRV(fbuf,NEWSYS);
|
||||
unlink(fbuf); /* this is the file we'll be using */
|
||||
if( (fns=BWCREAT(fbuf))<0 ) { /* try to open for output */
|
||||
USERR("can't open new .SYS file (%s)\n",fbuf);
|
||||
exit(1);
|
||||
}
|
||||
if( dogensys )
|
||||
gensys(); /* make a new SYS file from modules */
|
||||
else edsys(); /* edit the old SYS file */
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* gensys: generates a new SYS file image from modules
|
||||
/**************************************************************************/
|
||||
VOID
|
||||
gensys()
|
||||
{
|
||||
WORD fxm; /* file descriptor for xios mod */
|
||||
BYTE fbuf[20];
|
||||
|
||||
if( doclean ) { /* clean up the SYSFILE first? */
|
||||
PUTDRV(fbuf,SYSFILE);
|
||||
unlink(fbuf); /* delete if there... */
|
||||
}
|
||||
if(verbose) printf("Generating new SYS file\n");
|
||||
FCHECK(fns); /* File error check */
|
||||
write(fns,cmdhdr,SECSIZ); /* write out a (dummy) command hdr */
|
||||
genfix(); /* remember the sysdat & sup fixups */
|
||||
clsup = xfergrp(SUPMOD,GTYPCODE);
|
||||
clos_label = writelbl(); /* write the OS label (returns 0 if none exists) */
|
||||
if( clos_label != 0 )
|
||||
*sd_verptr = clsup<<4; /* fill in offset of label rel sup code seg */
|
||||
genfix(); clrtm = xfergrp(RTMMOD,GTYPCODE);
|
||||
genfix(); clmem = xfergrp(MEMMOD,GTYPCODE);
|
||||
genfix(); clcio = xfergrp(CIOMOD,GTYPCODE);
|
||||
genfix(); clbdos= xfergrp(BDOSMOD,GTYPCODE);
|
||||
clnet = 0;
|
||||
|
||||
fxm = BROPEN(XIOSMOD); /* look at XIOS module */
|
||||
if( grpseek(fxm,GTYPDATA) >= 0){ /* is there a data group?*/
|
||||
USERR("XIOS has separate code and data (small model)");
|
||||
USERR("This is not supported in this O.S.: use 8080 model.");
|
||||
exit(1);
|
||||
} else {
|
||||
pure_xios = FALSE;
|
||||
clxios = 0;
|
||||
}
|
||||
cltotal = clsup+clos_label+clrtm+clmem+clcio+clbdos+clnet+clxios;
|
||||
/*** finished writing the code portion of NEWSYS ***/
|
||||
|
||||
fldstart = lseek(fns,0L,1); /* where in file SYSDAT gets written */
|
||||
dsstart = *sd_mpmseg + cltotal; /* where in memory SYSDAT gets loaded */
|
||||
dlsysdat = xfergrp(SYSMOD,GTYPDATA); /* system data area, fixed later */
|
||||
|
||||
if( pure_xios )
|
||||
dlxios = xferpart_grp(fxm,GTYPDATA,dlsysdat);
|
||||
else { genfix(); dlxios = xferpart_grp(fxm,GTYPCODE,dlsysdat); }
|
||||
close(fxm); /* don't need this file descriptor */
|
||||
dltotal = dlsysdat+dlxios; /* this will change later */
|
||||
/*** finished writing STATIC data portion of NEWSYS ***/
|
||||
|
||||
/*** fill in sysdat here ***/
|
||||
sd_supmod->ep_eseg = sd_supmod->ep_iseg = *sd_mpmseg;
|
||||
sd_rtmmod->ep_eseg = sd_rtmmod->ep_iseg = sd_supmod->ep_eseg+clsup+clos_label;
|
||||
sd_memmod->ep_eseg = sd_memmod->ep_iseg = sd_rtmmod->ep_eseg+clrtm;
|
||||
sd_ciomod->ep_eseg = sd_ciomod->ep_iseg = sd_memmod->ep_eseg+clmem;
|
||||
sd_bdosmod->ep_eseg = sd_bdosmod->ep_iseg = sd_ciomod->ep_eseg+clcio;
|
||||
sd_xiosmod->ep_eseg = sd_xiosmod->ep_iseg = sd_bdosmod->ep_eseg+clbdos;
|
||||
if( pure_xios ) /* compute xios offsets */
|
||||
sd_xiosmod->ep_ioff = 0; /* separate code */
|
||||
else sd_xiosmod->ep_ioff = dlsysdat<<4; /* mixed code & data, after sysdat */
|
||||
sd_xiosmod->ep_eoff = sd_xiosmod->ep_ioff + 3;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
genfix() /* subroutine to remember SYSDAT & Super fixups */
|
||||
{
|
||||
LONG fa;
|
||||
|
||||
fa = lseek(fns,0L,1); /* where are we in this file? */
|
||||
fixlater(fa+6,F_PUT,&dsstart); /* fix the SYSDAT address */
|
||||
fixlater(fa+8,F_PUT,&(sd_supmod->ep_eoff)); /* Supervisor entry offset */
|
||||
fixlater(fa+10,F_PUT,&(sd_supmod->ep_eseg)); /* " " segment */
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* edsys: edit the old SYS file image.
|
||||
/* - copies old sys file into new
|
||||
/* - if( donew_xios ) will patch in a new XIOS from module
|
||||
/**************************************************************************/
|
||||
VOID
|
||||
edsys()
|
||||
{
|
||||
if(verbose) printf("Editting old SYS file\n");
|
||||
write(fns,cmdhdr,SECSIZ); /* leave room for command hdr */
|
||||
cltotal = xfergrp(SYSFILE,GTYPCODE);
|
||||
dltotal = xfergrp(SYSFILE,GTYPDATA);
|
||||
if( donew_xios ) {
|
||||
; /* need to read 'xt' from XIOS module */
|
||||
} else {
|
||||
; /* need to init 'xt' from sysdat */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* fixups: inserts updated SYSDAT page into NEWSYS file, and does some
|
||||
/* address fixups
|
||||
/**************************************************************************/
|
||||
VOID fixups()
|
||||
{
|
||||
REG WORD ii; /* counter */
|
||||
ADDR gg; /* temp var */
|
||||
GROUP *cg, *dg; /* group ptrs */
|
||||
UWORD genmfl(); /* (re)Gen Memory Free List */
|
||||
|
||||
if(verbose) printf("Doing fixups\n");
|
||||
FCHECK(fns); /* File error check */
|
||||
/*** fixup the memory list ***/
|
||||
if(verbose) {
|
||||
printf("SYS image load map:\n");
|
||||
printf(" Code starts at %4.4x\n",*sd_mpmseg);
|
||||
printf(" Data starts at %4.4x\n",dsstart);
|
||||
printf(" Tables start at %4.4x\n",(dsotables>>4)+dsstart);
|
||||
printf(" RSPs start at %4.4x\n",(dsotables>>4)+dsstart+dltables);
|
||||
printf(" XIOS buffers start at %4.4x\n",rsvd_seg);
|
||||
printf(" End of OS at %4.4x\n",*sd_endseg);
|
||||
}
|
||||
|
||||
if( trimlist(*sd_mpmseg,*sd_endseg) ) { /* mem part list trimmed? */
|
||||
printf("Trimming memory partitions. New list:");
|
||||
dspmlist(memroot);
|
||||
lseek( fns, locmfl, 0 );
|
||||
gg = (dlsysdat+dlxios)<<4;
|
||||
genmfl(gg); /*****/
|
||||
}
|
||||
/*** fixup XIOS info ***/
|
||||
fixupxios_info(); /* fixes the buffer info (DPH info) */
|
||||
/*** fixup the command header ***/
|
||||
for( ii=0; ii<SECSIZ; ii++ ) /* zero out command header */
|
||||
cmdhdr[ii] = '\0';
|
||||
cg = cmdhdr; /* code group first */
|
||||
cg->gtype = GTYPCODE; /* init all code vars */
|
||||
cg->glen = cltotal; /* total length of code groups */
|
||||
cg->gmin = cltotal; /* min length of code group */
|
||||
cg->gabase = *sd_mpmseg; /* loads at absolute address */
|
||||
dg = cmdhdr + sizeof(*cg); /* data group next */
|
||||
dg->gtype = GTYPDATA; /* init all data vars */
|
||||
dg->glen = dltotal; /* total length of data group+tables */
|
||||
dg->gmin = dltotal; /* min length of data group */
|
||||
dg->gabase = cg->gabase+cltotal;/* abs addr of start of system data */
|
||||
lseek( fns, 0L, 0 ); /* seek the beginning of NEWSYS */
|
||||
write(fns,cmdhdr,SECSIZ); /* write out the command header */
|
||||
|
||||
/*** fixup the sysdat page ***/
|
||||
lseek(fns,fldstart,0); /* seek there in file */
|
||||
write(fns,sdat_area,SDLEN); /* put it into the file */
|
||||
|
||||
/*** take care of the little fixes ***/
|
||||
fixfile(); /* fixes from the list */
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* wrapup: closes files
|
||||
/**************************************************************************/
|
||||
VOID wrapup()
|
||||
{
|
||||
BYTE buf1[20], buf2[20];
|
||||
|
||||
if(verbose) printf("Wrapping up\n");
|
||||
FCHECK(fns); /* File error check */
|
||||
lseek(fns,0L,2); /* flush NEWSYS buffers? */
|
||||
if(strlen(edsysver) != write(fns,edsysver,strlen(edsysver))) {
|
||||
USERR("WRITE FAILURE - the disk may be too full\n");
|
||||
exit(1);
|
||||
}
|
||||
close(fns); /* all finished with NEWSYS */
|
||||
PUTDRV(buf1,OLDSYS); unlink(buf1);
|
||||
PUTDRV(buf2,SYSFILE); rename(buf2,buf1);
|
||||
PUTDRV(buf1,NEWSYS); rename(buf1,buf2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,747 @@
|
||||
/***************************************************************/
|
||||
/***************************************************************/
|
||||
/* genc2.c: more genccpm.cc, broken up for shorter compiles */
|
||||
/***************************************************************/
|
||||
/***************************************************************/
|
||||
#ifndef MAINMODULE
|
||||
#include <genccpm.h>
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* init_sds: points the system data pointers to the right place
|
||||
/**************************************************************************/
|
||||
VOID
|
||||
init_sds(sysdat)
|
||||
BYTE *sysdat; /* ptr to system data buffer */
|
||||
{
|
||||
sd_supmod = sysdat + 0x00; /* (4) */
|
||||
sd_rtmmod = sysdat + 0x08; /* (4) */
|
||||
sd_memmod = sysdat + 0x10; /* (4) */
|
||||
sd_ciomod = sysdat + 0x18; /* (4) */
|
||||
sd_bdosmod = sysdat + 0x20; /* (4) */
|
||||
sd_xiosmod = sysdat + 0x28; /* (4) */
|
||||
sd_netmod = sysdat + 0x30; /* (4) */
|
||||
sd_mpmseg = sysdat + 0x40;
|
||||
sd_rspseg = sysdat + 0x42;
|
||||
sd_endseg = sysdat + 0x44;
|
||||
sd_module_map = sysdat + 0x46;
|
||||
sd_ncns = sysdat + 0x47;
|
||||
sd_nlst = sysdat + 0x48;
|
||||
sd_nccb = sysdat + 0x49;
|
||||
sd_nflags = sysdat + 0x4A;
|
||||
sd_srchdisk = sysdat + 0x4B;
|
||||
sd_mmp = sysdat + 0x4C;
|
||||
sd_nslaves = sysdat + 0x4E;
|
||||
sd_dayfile = sysdat + 0x4F;
|
||||
sd_tempdisk = sysdat + 0x50;
|
||||
sd_tickspsec = sysdat + 0x51;
|
||||
sd_lul = sysdat + 0x52;
|
||||
sd_ccb = sysdat + 0x54;
|
||||
sd_flags = sysdat + 0x56;
|
||||
sd_mdul = sysdat + 0x58;
|
||||
sd_nxmds = sysdat + 0x58;
|
||||
sd_mfl = sysdat + 0x5A;
|
||||
sd_nmparts = sysdat + 0x5A;
|
||||
sd_pul = sysdat + 0x5C;
|
||||
sd_nxpd = sysdat + 0x5C;
|
||||
sd_qul = sysdat + 0x5E;
|
||||
sd_nqds = sysdat + 0x5D;
|
||||
sd_qmau = sysdat + 0x60; /* (4) */
|
||||
sd_qmastart = sysdat + 0x62;
|
||||
sd_qmalen = sysdat + 0x64;
|
||||
sd_verptr = sysdat + 0x78;
|
||||
sd_vn = sysdat + 0x7A;
|
||||
sd_mpmvn = sysdat + 0x7C;
|
||||
sd_ncondev = sysdat + 0x83;
|
||||
sd_nlstdev = sysdat + 0x84;
|
||||
sd_nciodev = sysdat + 0x85;
|
||||
sd_lcb = sysdat + 0x86;
|
||||
sd_popen_max = sysdat + 0x8A;
|
||||
sd_plock_max = sysdat + 0x8B;
|
||||
sd_cmode = sysdat + 0x90;
|
||||
sd_xpcns = sysdat + 0x9f;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* doxios: gets miscellaneous XIOS values from user */
|
||||
/************************************************************************/
|
||||
BYTE *
|
||||
doxios(bb,xmtitle) /* submenu for XIOS value mods */
|
||||
BYTE *bb; /* value passed in from menu */
|
||||
BYTE *xmtitle;
|
||||
{
|
||||
BYTE cmds[CMDSLEN]; /* space for additional commands */
|
||||
EXTERN BYTE *clearit;
|
||||
|
||||
if( bb != NULLPTR ) { /* if any "command line" arguments */
|
||||
domenu(bb); /* do what they've asked for */
|
||||
} else FOREVER { /* work with user for a while */
|
||||
printf("%s",clearit); /* clear screen */
|
||||
prtmenu(xmtitle); /* display user options */
|
||||
printf(PROMPT); /* prompt user */
|
||||
if( gets(cmds)!=cmds || /* on end of file */
|
||||
*cmds==NULL ) /* or blank line of input */
|
||||
break; /* exit interaction with user */
|
||||
domenu(cmds); /* do what they've asked for */
|
||||
} /*****************************/
|
||||
return NULLPTR; /* standard return... */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* dosysp: gets miscellaneous system paramaters from user */
|
||||
/************************************************************************/
|
||||
BYTE *
|
||||
dosysp(bb,smtitle) /* submenu for SYSP value mods */
|
||||
BYTE *bb; /* value passed in from menu */
|
||||
BYTE *smtitle;
|
||||
{
|
||||
BYTE cmds[CMDSLEN]; /* space for additional commands */
|
||||
EXTERN MENU *syspmenu; /* list of menu items for sysp menu */
|
||||
EXTERN BYTE *clearit;
|
||||
|
||||
if( bb != NULLPTR ) { /* if any "command line" arguments */
|
||||
domenu(bb,syspmenu); /* do what they've asked for */
|
||||
} else FOREVER { /* work with user for a while */
|
||||
printf("%s",clearit); /* clear screen */
|
||||
prtmenu(smtitle,syspmenu); /* display user options */
|
||||
printf(PROMPT); /* prompt user */
|
||||
if( gets(cmds)!=cmds || /* on end of file */
|
||||
*cmds==NULL ) /* or blank line of input */
|
||||
break; /* exit interaction with user */
|
||||
domenu(cmds,syspmenu); /* do what they've asked for */
|
||||
} /*****************************/
|
||||
return NULLPTR; /* standard return... */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* dorsp: handles rsp editting */
|
||||
/*************************************************************************/
|
||||
BYTE *
|
||||
dorsp(parm,xmtitle) /* handle RSP list editting */
|
||||
BYTE *parm; /* command value parameter */
|
||||
BYTE *xmtitle;
|
||||
{
|
||||
BYTE cmds[CMDSLEN]; /* space for additional commands */
|
||||
EXTERN MENU *rspmenu; /* list of menu items for rsp menu */
|
||||
EXTERN BYTE *clearit;
|
||||
|
||||
if( parm != NULLPTR ) { /* if any "command line" arguments */
|
||||
domenu(parm,rspmenu); /* do what they've asked for */
|
||||
} else FOREVER { /* work with user for a while */
|
||||
printf("%s",clearit); /* clear screen */
|
||||
rsp_display(rsps); /* display what they have to work with */
|
||||
prtmenu(xmtitle,rspmenu); /* display user options */
|
||||
printf(PROMPT); /* prompt user */
|
||||
if( gets(cmds)!=cmds || /* on end of file */
|
||||
*cmds==NULL ) /* or blank line of input */
|
||||
break; /* exit interaction with user */
|
||||
domenu(cmds,rspmenu); /* do what they've asked for */
|
||||
} /*****************************/
|
||||
return NULLPTR; /* standard return... */
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
BYTE *
|
||||
rspinclude(rs)
|
||||
BYTE *rs;
|
||||
{
|
||||
BYTE *bp, *cp, *ep; /* ptrs to take apart command str */
|
||||
DLIST *dd;
|
||||
|
||||
if( rs==NULLPTR || *rs==NULL )
|
||||
return "You need to say 'include=xx.rsp,yy.rsp,zz.rsp'";
|
||||
for( ep=rs; *ep; ++ep ) ; /* end of string pointer */
|
||||
for( bp=rs; bp<ep; bp=cp+1 ){ /* process each rsp spec */
|
||||
for( cp=bp; *cp && *cp!=','; ++cp ) ; /* find eos or comma */
|
||||
if( *cp == ',' ) *cp = '\0'; /* null terminate the spec */
|
||||
if( (dd=dirsearch(bp)) == NULLPTR )
|
||||
return "Can't find RSP to include";
|
||||
rspjoin(dd);
|
||||
}
|
||||
return NULLPTR;
|
||||
}
|
||||
|
||||
rspjoin(dd)
|
||||
DLIST *dd;
|
||||
{
|
||||
DLIST *rs;
|
||||
|
||||
if( rsps == NULLPTR )
|
||||
rsps = dd;
|
||||
else {
|
||||
for( rs=rsps; rs->dlnext != NULLPTR; rs=rs->dlnext ) ;
|
||||
rs->dlnext = dd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
BYTE *
|
||||
rspexclude(rs)
|
||||
BYTE *rs;
|
||||
{
|
||||
BYTE *bp, *cp, *ep;
|
||||
BOOLEAN rspzap();
|
||||
|
||||
if( rs==NULLPTR || *rs==NULL )
|
||||
return "You need to say 'exclude=aa.rsp,bb.rsp,cc.rsp'";
|
||||
for( ep=rs; *ep; ++ep ) ; /* find eos */
|
||||
for( bp=rs; bp<ep; bp=cp+1 ){ /* process each rsp spec */
|
||||
for( cp=bp; *cp && *cp!=','; ++cp ) ; /* find eos or comma */
|
||||
if( *cp == ',' ) *cp = '\0'; /* null terminate the spec */
|
||||
if( !rspzap(bp) )
|
||||
return "Can't find RSP to exclude";
|
||||
}
|
||||
return NULLPTR;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
rspzap(nm)
|
||||
BYTE *nm;
|
||||
{
|
||||
DLIST **qs, *ps, *rs;
|
||||
|
||||
if( *nm == '*' ) { /* zap entire list? */
|
||||
for( ps=rsps; ps!=NULLPTR; ps=rs ) {
|
||||
rs = ps->dlnext;
|
||||
free(ps);
|
||||
}
|
||||
rsps = NULLPTR;
|
||||
return TRUE;
|
||||
}
|
||||
for( qs= &rsps; *qs!=NULLPTR; qs = &rs->dlnext ) { /* zap part of list */
|
||||
rs = *qs;
|
||||
if( namematch(nm,rs->dlname) ) {
|
||||
*qs = rs->dlnext;
|
||||
free(rs);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE; /* thru loop, can't find it */
|
||||
}
|
||||
|
||||
namematch(s1,s2)
|
||||
BYTE *s1, *s2;
|
||||
{
|
||||
for( ; *s1 && *s2; ++s1, ++s2 )
|
||||
if( toupper(*s1) != toupper(*s2) )
|
||||
return FALSE;
|
||||
if( *s1 || *s2 )
|
||||
return FALSE;
|
||||
else return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
#define PAGEWIDTH 72
|
||||
rsp_display(rp)
|
||||
DLIST *rp;
|
||||
{
|
||||
WORD ii;
|
||||
|
||||
printf("\nRSPs to be included are:\n");
|
||||
for( ii=0; rp!=NULLPTR; rp = rp->dlnext ) {
|
||||
if( (ii += 15) > PAGEWIDTH ) {
|
||||
printf("\n");
|
||||
ii=15;
|
||||
}
|
||||
printf(" %12.12s",rp->dlname);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* grpseek: seeks in MOD file 'fd' to the start of a code/data group, */
|
||||
/* returns length (in bytes) of that group */
|
||||
/*************************************************************************/
|
||||
LONG
|
||||
grpseek(fde,gt)
|
||||
WORD fde; /* file descriptor */
|
||||
WORD gt; /* group type to look for */
|
||||
{
|
||||
WORD gc; /* group counter */
|
||||
LONG dps; /* pgphs to group base in file */
|
||||
GROUP grp; /* structure for Cmd Hdr info */
|
||||
|
||||
if( lseek(fde,0L,0) < 0 ) /* seek to beginning of file */
|
||||
CRASH("grp cmd header seek failed\n");
|
||||
dps=8; /* pgphs to start of load group */
|
||||
for( gc=0; gc<8; gc++ ) { /* search up to 8 groups in cmd hdr */
|
||||
read(fde,&grp,sizeof(grp)); /* read each group in header */
|
||||
if( grp.gtype == gt ) /* the group we want */
|
||||
break;
|
||||
dps += grp.glen; /* add in size of previous group */
|
||||
}
|
||||
if( grp.gtype != gt ) /* did we find the group? */
|
||||
return ((LONG) FAILURE); /* nope, so fail */
|
||||
dps = dps << 4; /* pgphs xfm to bytes */
|
||||
if( lseek(fde,dps,0) < 0 ) /* seek to start of data group */
|
||||
CRASH("grp group seek failed\n");
|
||||
return ((LONG)((grp.glen)<<4)); /* return group size in bytes */
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* xfer rtns: transfer a group from file 'module' to file NEWSYS (fns)
|
||||
/* returns number of paragraphs in the group
|
||||
/**************************************************************************/
|
||||
UWORD
|
||||
xfergrp(module,group_type)
|
||||
BYTE *module; /* module name */
|
||||
WORD group_type; /* code? or data? */
|
||||
{
|
||||
REG WORD fm; /* file descriptor for module */
|
||||
REG UWORD rv,xferpart_grp(); /* return value */
|
||||
|
||||
if( (fm=BROPEN(module)) < 0 ) /* open the module for binary reading */
|
||||
CRASH("can't find a system module\n");
|
||||
rv = xferpart_grp(fm,group_type,0);
|
||||
close(fm);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
UWORD
|
||||
xferpart_grp(fm,gt,skip)
|
||||
WORD fm; /* file descriptor for module */
|
||||
WORD gt; /* group type: code or data */
|
||||
UWORD skip; /* num pgphs to skip in this group */
|
||||
{
|
||||
REG WORD ii; /* counter */
|
||||
REG LONG xx, yy; /* long counters */
|
||||
BYTE xferbuf[BUFSIZ]; /* a transfer buffer */
|
||||
GROUP grp; /* a group area */
|
||||
|
||||
if( lseek(fm,0L,0) < 0 ) /* seek to beginning of file */
|
||||
CRASH("grp cmd header seek failed\n");
|
||||
yy = skip+8; /* num pgphs to skip + in cmd hdr */
|
||||
for( ii=0; ii<8; ++ii ) { /* read group hdrs in cmd hdr */
|
||||
read(fm,&grp,sizeof(grp));
|
||||
if( grp.gtype == gt )
|
||||
break;
|
||||
yy += grp.glen; /* count #pgphs in this group to skip */
|
||||
}
|
||||
if( grp.gtype!=gt ) CRASH("module doesn't have group\n");
|
||||
xx = yy << 4; /* cvt to bytes */
|
||||
if( lseek(fm,xx,0)<0 ) CRASH("couldn't seek in module\n");
|
||||
xx = grp.glen; xx -= skip; /* pgphs to xfer */
|
||||
for( yy=xx<<4; yy>0; yy-=ii ){ /* xfer bytes to NEWSYS */
|
||||
ii = ( yy > BUFSIZ ? BUFSIZ : yy ); /* num bytes per xfer */
|
||||
if( read(fm,xferbuf,ii) != ii ) CRASH("not enough bytes in module\n");
|
||||
write(fns,xferbuf,ii);
|
||||
}
|
||||
return (UWORD)(xx); /* convert to pgphs */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* help: prints out a help message */
|
||||
/**************************************************************************/
|
||||
|
||||
BYTE *helpm1[] = {
|
||||
"\n\n",
|
||||
#ifdef MCPM
|
||||
"\t\t*** GENCMPM Help Function ***",
|
||||
"\t\t=============================",
|
||||
" GENCMPM lets you edit and/or generate a system image from",
|
||||
#else
|
||||
"\t\t*** GENCCPM Help Function ***",
|
||||
"\t\t============================",
|
||||
" GENCCPM lets you edit and/or generate a system image from",
|
||||
#endif
|
||||
"operating system modules on the default drive. A detailed",
|
||||
"explanation of each parameter may be found in the Concurrent CP/M-86",
|
||||
"System Guide, Section 2.\n",
|
||||
#ifdef MCPM
|
||||
" GENCMPM assumes the default values shown within square",
|
||||
#else
|
||||
" GENCCPM assumes the default values shown within square",
|
||||
#endif
|
||||
"brackets. All numbers are Hexadecimal. To change a parameter,",
|
||||
"enter the parameter name followed by '=' and the new value. Type",
|
||||
"<CR> (a carriage return) to enter the assignment. You can make",
|
||||
"multiple assignments if you separate them by a space. No spaces",
|
||||
"are allowed within an assignment. Example:\n",
|
||||
"CHANGES? verbose=N sysdrive=A: openmax=1A <CR>\n",
|
||||
"Parameter names may be shortened to the minimum combination of",
|
||||
"letters unique to the currently displayed menu. Example:\n",
|
||||
"CHANGES? v=N sysd=A: op=1a <CR>\n",
|
||||
NULLPTRI
|
||||
};
|
||||
BYTE *helpm2[] = {
|
||||
"\n\n",
|
||||
"Sub-menus (the last few options without default values) are accessed",
|
||||
"by typing the sub-menu name followed by <CR>. You may enter",
|
||||
"multiple sub-menus, in which case each sub-menu will be displayed",
|
||||
"in order. Example:\n",
|
||||
"CHANGES? help sysparams rsps <CR>\n",
|
||||
"Enter <CR> alone to exit a menu, or a parameter name, '=' and the",
|
||||
"new value to assign a parameter. Multiple assignments may be",
|
||||
"entered, as in response to the Main Menu prompt.\n",
|
||||
NULLPTRI
|
||||
};
|
||||
|
||||
|
||||
BYTE *
|
||||
help(tx) /* print a helpful message to user */
|
||||
BYTE *tx;
|
||||
{
|
||||
REG BYTE **cpp; /* pointer to help strings */
|
||||
|
||||
for( cpp=helpm1; *cpp != NULLPTR; cpp++ )
|
||||
printf("%s\n",*cpp);
|
||||
press_return();
|
||||
for( cpp=helpm2; *cpp != NULLPTR; cpp++ )
|
||||
printf("%s\n",*cpp);
|
||||
press_return();
|
||||
return NULLPTR;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* memory list allocation */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
BYTE *
|
||||
domem(cmdval,memtitle)
|
||||
BYTE *cmdval;
|
||||
BYTE *memtitle;
|
||||
{
|
||||
WORD cntmlist(); /* does list validation */
|
||||
BOOLEAN okl; /* okay list */
|
||||
BYTE cmds[CMDSLEN]; /* place to put input */
|
||||
EXTERN MLIST *memroot; /* memory list root */
|
||||
EXTERN MENU *memmenu; /* memory edit menu */
|
||||
EXTERN BYTE *clearit;
|
||||
|
||||
okl = (cntmlist(memroot) > 0); /* overlap chk & condense */
|
||||
if(cmdval!=NULLPTR) {
|
||||
domenu(cmdval,memmenu); /* do the commands */
|
||||
okl = (cntmlist(memroot)>0);/* check the results */
|
||||
}
|
||||
if( !okl || cmdval==NULLPTR ) /* do we need to interact with user? */
|
||||
FOREVER { /* display, the edit */
|
||||
printf("%s",clearit); /* clear the screen (maybe) */
|
||||
dspmlist(memroot); /* here's what it looks like */
|
||||
prtmenu(memtitle,memmenu); /* here's how to edit */
|
||||
printf(PROMPT); /* what to do? */
|
||||
if( gets(cmds)!=cmds || *cmds==NULL ) { /* see if the want to get out */
|
||||
if(okl)
|
||||
break;
|
||||
else {
|
||||
printf("Please adjust memory partitions\n");
|
||||
press_return();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
domenu(cmds,memmenu); /* edit the memory list */
|
||||
okl = (cntmlist(memroot)>0);/* validate the memory list */
|
||||
}
|
||||
return NULLPTR; /* standard return */
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
BYTE *
|
||||
addmem(ms) /* add memory partitions */
|
||||
BYTE *ms; /* memory partition spec */
|
||||
{
|
||||
REG BYTE *pl; /* pointer to last addr spec */
|
||||
REG BYTE *ps; /* pointer to size spec */
|
||||
UWORD f, l, qq, s; /* values of spec */
|
||||
MLIST *intomlist(), *mnew; /* where to put them */
|
||||
EXTERN MLIST *memroot; /* memory partitions list */
|
||||
BYTE *badspec = "Add memory partition spec should look like:\n\tadd=first,last,size";
|
||||
BYTE *badval = "Spec: add=first,last,size\n\twhere last>first, size>80";
|
||||
BYTE *warnbig = "Warning: size too big, it will be truncated";
|
||||
BYTE *warnleft = "Warning: region not evenly divided by size, will adjust last partition";
|
||||
BYTE *rval;
|
||||
BYTE *index();
|
||||
|
||||
rval = NULLPTR; /* default return value */
|
||||
if( (pl=index(ms,','))==0) /* look for ptr to last addr */
|
||||
return badspec;
|
||||
else *pl++ = NULL; /* terminate first addr spec */
|
||||
if( (ps=index(pl,','))==0) /* look for ptr to size */
|
||||
return badspec;
|
||||
else *ps++ = NULL;
|
||||
f=atoih(ms); /* convert first addr spec */
|
||||
s=atoih(ps); /* convert size spec */
|
||||
if( *pl=='+' ) /* last addr relative to first? */
|
||||
l=atoih(pl+1)+f; /* yes, so calculate */
|
||||
else if( *pl==NULL || *pl=='*' ) {
|
||||
if( *pl=='*' ) /* last addr multiple of size? */
|
||||
l=atoih(pl+1); /* spec multiple */
|
||||
else l=1; /* default multiple=1 */
|
||||
l = f+l*s; /* s in paragraphs */
|
||||
} else l=atoih(pl); /* no, it's absolute address */
|
||||
if( l<=f || s==0 ) /* 1st validation check */
|
||||
return badval;
|
||||
if( s > l-f ) { /* 2nd validation check */
|
||||
rval = warnbig;
|
||||
s = l-f;
|
||||
}
|
||||
if( s<MINKMEM ) /* 3rd validation check */
|
||||
return "Memory partition must be at least 80 paragraphs";
|
||||
qq = ((l-f)/s)*s; /* make sure last == first + xx * s */
|
||||
if( qq != (l-f) ) { /* 4th validation check */
|
||||
rval = warnleft;
|
||||
l = f+qq;
|
||||
}
|
||||
mnew = (MLIST *)malloc(sizeof(*mnew)); /* make room */
|
||||
mnew->mlfirst = f;
|
||||
mnew->mllast = l;
|
||||
mnew->mlsize = s;
|
||||
memroot=intomlist(memroot,mnew); /* sorted insertion into list */
|
||||
return rval; /* everything okay */
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
BYTE *
|
||||
delmem(ms) /* delete memory partition */
|
||||
BYTE *ms;
|
||||
{
|
||||
REG WORD df, dl; /* delete first, last */
|
||||
MLIST **mm, **mn, *mo, *mp, *mq; /* necessary list ptrs */
|
||||
EXTERN MLIST *memroot; /* memory partitions list */
|
||||
BYTE *pl;
|
||||
WORD i;
|
||||
BYTE *badspec="To delete a memory partition, say\n\tdelete=1 or delete=1-3\n";
|
||||
|
||||
if( *ms == '*' ) { /* delete all? */
|
||||
for( mp=memroot; mp!=NULLPTR; mp=mq ) {
|
||||
mq = mp->mlnext; /* save the pointer before we free it */
|
||||
free(mp);
|
||||
}
|
||||
memroot = NULLPTR;
|
||||
return NULLPTR; /* everything okay */
|
||||
}
|
||||
if( (pl=index(ms,'-')) == 0 )
|
||||
pl=ms; /* point last to first */
|
||||
else *pl++ = NULL; /* else point to after 'dash' */
|
||||
df=atoi(ms); /* decimal conversion */
|
||||
dl=atoi(pl);
|
||||
for( i=1, mm=&memroot, mn=NULLPTR, mo=memroot;
|
||||
i<=dl && mo!=NULLPTR;
|
||||
++i ) {
|
||||
if( i==df ) mn=mm; /* found first, pt to ptr to */
|
||||
mm = &mo->mlnext; /* ptr to ptr */
|
||||
mo = mo->mlnext;
|
||||
}
|
||||
if( mn==NULLPTR || i<=dl ) /* check range of deletions */
|
||||
return badspec;
|
||||
mp = *mn; /* save ptr to deleted list */
|
||||
*mn = mo; /* cut them suckers out of the list */
|
||||
for( ; mp!=mo; mp=mq ) {
|
||||
mq = mp->mlnext;
|
||||
free(mp);
|
||||
}
|
||||
return NULLPTR; /* everything ok */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
dspmlist(mroot)
|
||||
MLIST *mroot;
|
||||
{
|
||||
MLIST *mn, *mo;
|
||||
REG WORD i, nump;
|
||||
|
||||
printf("\n\n");
|
||||
printf(" Addresses Partitions (in paragraphs)\n");
|
||||
printf(" # Start Last Size Qty \n");
|
||||
for( i=1, mn=mroot; mn!=NULLPTR; ++i, mn=mo ) {
|
||||
nump = (mn->mllast-mn->mlfirst) / mn->mlsize;
|
||||
printf("%2.2d. %4.4xh %4.4xh %4.4xh %4.4xh ",
|
||||
i,mn->mlfirst,mn->mllast,mn->mlsize,nump);
|
||||
if( (mo=mn->mlnext) != NULLPTR ) { /* do some checking */
|
||||
if( mn->mllast > mo->mlfirst )
|
||||
printf("**overlaps** ");
|
||||
if( mn->mlsize > mn->mllast-mn->mlfirst )
|
||||
printf("**partition too big** ");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
WORD
|
||||
cntmlist(mroot) /* check for overlaps, condense if possible */
|
||||
MLIST *mroot; /* returns number mem partitions, 0 if bad list */
|
||||
{
|
||||
MLIST *mn, *mo; /* ptr within list */
|
||||
REG BOOLEAN olap; /* partitions overlap or bad size */
|
||||
REG WORD nump; /* number of partitions this block */
|
||||
REG WORD totnump; /* keep the count going */
|
||||
|
||||
totnump = 0; /* total number partitions */
|
||||
olap = FALSE; /* innocent until proven guilty */
|
||||
for( mn=mroot; mn!=NULLPTR && (mo=mn->mlnext)!=NULLPTR; ) {
|
||||
if( mn->mlsize==mo->mlsize ){ /* partitions same size? */
|
||||
if( mn->mlfirst==mo->mlfirst && /* same partitions? */
|
||||
mn->mllast==mo->mllast ) {
|
||||
mn->mlnext=mo->mlnext;
|
||||
free(mo); /* mo is redundant, zap it */
|
||||
continue;
|
||||
} else
|
||||
if( mn->mllast==mo->mlfirst || /* adjacent partition? */
|
||||
mn->mllast==(mo->mlfirst-1) ) {
|
||||
mn->mllast=mo->mllast; /* make 1st partition bigger */
|
||||
mn->mlnext=mo->mlnext; /* zap out mo from list */
|
||||
free(mo); /* we don't need it any more */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( mn->mllast > mo->mlfirst )
|
||||
olap=TRUE; /* partitions overlap */
|
||||
nump = (mn->mllast-mn->mlfirst) / mn->mlsize;
|
||||
if( nump<=0 )
|
||||
olap=TRUE; /* size > partition */
|
||||
else totnump += nump; /* incr this count */
|
||||
mn=mo; /* continue through loop */
|
||||
}
|
||||
if( mn!=NULLPTR ) { /* catch the last in the loop */
|
||||
nump = (mn->mllast-mn->mlfirst) / mn->mlsize;
|
||||
if( nump<=0 )
|
||||
olap=TRUE; /* size > partition */
|
||||
else totnump += nump; /* incr this count */
|
||||
}
|
||||
if( olap )
|
||||
return 0; /* boo boo, return 0 */
|
||||
else return totnump; /* return num partitions */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
MLIST *
|
||||
intomlist(mroot,mi) /* insert mi into list mroot sorted */
|
||||
MLIST *mroot;
|
||||
MLIST *mi;
|
||||
{
|
||||
MLIST **mm; /* ptr to ptr to list */
|
||||
MLIST *mn; /* ptr to list */
|
||||
|
||||
for( mm=&mroot, mn=mroot;
|
||||
mn != NULLPTR && mi->mlfirst > mn->mlfirst; ){
|
||||
mm = &mn->mlnext;
|
||||
mn = mn->mlnext;
|
||||
}
|
||||
mi->mlnext = mn;
|
||||
*mm = mi;
|
||||
return mroot;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
UWORD /* returns new size of partition, 0 if not enough room */
|
||||
trimit(start,last,olds)
|
||||
UWORD start; /* start address of partition */
|
||||
UWORD last; /* end address of partition */
|
||||
UWORD olds; /* old partition size */
|
||||
{
|
||||
REG UWORD ss;
|
||||
|
||||
ss = last-start; /* size is in paragraphs */
|
||||
if( ss<MINKMEM ) return 0; /* sorry, too small */
|
||||
else if( ss<olds ) return ss-1; /* needs to be smaller */
|
||||
else return olds; /* fine just the way it is */
|
||||
}
|
||||
|
||||
WORD
|
||||
onbounds(start,size,nst)
|
||||
UWORD start; /* original starting boundary */
|
||||
UWORD size; /* partition size */
|
||||
UWORD nst; /* new starting address */
|
||||
{ /* returns addr>nst multiple of size from start */
|
||||
REG UWORD rr;
|
||||
|
||||
for( rr=start; rr<nst; rr += size )
|
||||
;
|
||||
return rr;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* trimlist: trims the memory list according to OS bounds */
|
||||
/**************************************************************************/
|
||||
|
||||
BOOLEAN /* returns TRUE iff any adjustments */
|
||||
trimlist(osstart,osend)
|
||||
UWORD osstart; /* starting pgph */
|
||||
UWORD osend; /* ending pgph */
|
||||
{
|
||||
EXTERN MLIST *memroot;
|
||||
REG MLIST **mm, *mn, *mo; /* ptrs into memlist */
|
||||
REG UWORD ss, zz; /* temp vars */
|
||||
LOCAL WORD adjusts; /* number of collisions */
|
||||
|
||||
adjusts = 0; /* we haven't adjusted anything yet */
|
||||
for( mm=&memroot, mn=memroot; mn!=NULLPTR; mn=*mm ) {
|
||||
if( mn->mlfirst < osstart ) {
|
||||
if( mn->mllast >= osstart ) { /** collision **/
|
||||
++adjusts; /* we're doing some adjusting */
|
||||
if( mn->mllast > osend ) { /* real big mem part? */
|
||||
mo = (MLIST *)malloc(sizeof *mo); /* set it up now, adjust it later */
|
||||
mo->mlfirst = onbounds(mn->mlfirst,mn->mlsize,osstart);
|
||||
mo->mllast = mn->mllast;
|
||||
mo->mlsize = mn->mlsize;
|
||||
mo->mlnext = mn->mlnext;
|
||||
mn->mlnext = mo;
|
||||
}
|
||||
if( (zz=trimit(mn->mlfirst,osstart-1,mn->mlsize)) > 0 ) {
|
||||
mn->mllast = osstart-1;
|
||||
mn->mlsize = zz; /* in case it was trimmed */
|
||||
} else { /* partitions too small, delete it */
|
||||
*mm = mn->mlnext;
|
||||
free(mn);
|
||||
continue; /* don't increment list ptr */
|
||||
}
|
||||
} /**** end collision ****/
|
||||
|
||||
} else if( mn->mlfirst < osend ) { /** collision **/
|
||||
++adjusts; /* we're doing some adjusting */
|
||||
if( mn->mllast <= osend ) { /* does part cross past os? */
|
||||
*mm = mn->mlnext; /* no, delete it */
|
||||
free(mn);
|
||||
continue;
|
||||
}
|
||||
ss = onbounds(mn->mlfirst,mn->mlsize,osend);
|
||||
if( (zz=trimit(osend,ss,mn->mlsize)) > 0 ){/* set up a smaller mem part */
|
||||
mo = (MLIST *)malloc(sizeof *mo);
|
||||
mo->mlfirst = osend+1;
|
||||
mo->mllast = ss;
|
||||
mo->mlsize = zz;
|
||||
mo->mlnext = mn;
|
||||
*mm = mo;
|
||||
mm = &mo->mlnext;
|
||||
}
|
||||
if( (zz=trimit(ss,mn->mllast,mn->mlsize)) > 0 ){
|
||||
mn->mlfirst = ss;
|
||||
mn->mlsize = zz;
|
||||
} else { /* partition too small, delete */
|
||||
*mm = mn->mlnext;
|
||||
free(mn);
|
||||
continue; /* don't bottom out on this loop */
|
||||
}
|
||||
} /**** end collision ****/
|
||||
|
||||
mm = &mn->mlnext; /* set up for next partition check */
|
||||
} /**** end FOR loop ***/
|
||||
return adjusts>0; /* returns TRUE if we adjusted */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,569 @@
|
||||
/*********************************************************************/
|
||||
/*********************************************************************/
|
||||
/* genc3.c
|
||||
/* EXPORTS gentable() - the routine which builds all the tables
|
||||
/*********************************************************************/
|
||||
/*********************************************************************/
|
||||
#ifndef MAINMODULE
|
||||
#include <genccpm.h>
|
||||
#endif
|
||||
|
||||
|
||||
MLOCAL UWORD rsp_last; /* link to previous RSP */
|
||||
MLOCAL UWORD rsp_seg; /* where next RSP seg gets written */
|
||||
|
||||
#define ALIGN(xx) (((xx)+0xF)&0xFFF0)
|
||||
#define BYTE_ADJUST(yy) if(yy>0xFF) yy=0xFF
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
UWORD /* return new offset */
|
||||
segwrite(nbs) /* pad to paragraph boundary */
|
||||
UWORD nbs; /* old offset */
|
||||
{
|
||||
REG UWORD nps;
|
||||
|
||||
if( nbs & 0xF ) { /* does it need padding? */
|
||||
nps = 0x10 - (nbs & 0xF); /* number pad bytes needed */
|
||||
write(fns,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",nps);
|
||||
return (nbs+nps);
|
||||
} else return nbs;
|
||||
}
|
||||
|
||||
UWORD /* return num paragraphs */
|
||||
padwrite(nbs) /* pad to paragraph boundary */
|
||||
UWORD nbs; /* num bytes needing padding */
|
||||
{
|
||||
return segwrite(nbs) >> 4; /* convert to pgphs */
|
||||
}
|
||||
|
||||
UWORD
|
||||
datwrite(from,size)
|
||||
BYTE *from;
|
||||
WORD size;
|
||||
{
|
||||
if( write(fns,from,size) != size ) {
|
||||
fprintf(stderr,"ERROR: Write to new SYS file failed\n");
|
||||
fprintf(stderr,"Out of room on disk?\n");
|
||||
exit(1);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
MLOCAL LONG oldladdr=0; /* save previous address for comparison */
|
||||
#define BIGWORD 0x0000ffffL
|
||||
chkaddr(uaddr) /* check for SYSDAT overflow */
|
||||
UWORD uaddr;
|
||||
{
|
||||
LONG laddr;
|
||||
|
||||
laddr = BIGWORD & uaddr;
|
||||
if( laddr < oldladdr ) {
|
||||
USERR("ERROR - System Data Area has grown too large\n");
|
||||
USERR("Try reducing the size of some of the tables\n");
|
||||
exit(1);
|
||||
}
|
||||
oldladdr = laddr; /* save for wrap around compare */
|
||||
}
|
||||
/* this is a kluge: I did it because I couldn't get the LONG cast */
|
||||
/* to work without doing sign extension... whf 1/20/83 */
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* EXPORT gentables: generates various tables in system data area,
|
||||
/* and handles RSPs
|
||||
/**************************************************************************/
|
||||
VOID gentables()
|
||||
{
|
||||
LOCAL WORD nmparts; /* number of memory partitions */
|
||||
LOCAL WORD nsat_items; /* number of SAT items in qmau */
|
||||
LOCAL UWORD damds; /* offset of beginning of tables */
|
||||
LOCAL UWORD daqbuf; /* offset of beginning of qbuf */
|
||||
LOCAL LONG daend; /* sys data offset: end of data area */
|
||||
LOCAL UWORD doffset; /* current offset into data area */
|
||||
LOCAL UWORD lastlink; /* helps link lists together */
|
||||
LOCAL WORD count; /* counts num list items being generated */
|
||||
LOCAL UWORD ucount; /* unsigned counter */
|
||||
LOCAL MLIST *mn; /* for trapsing down memroot */
|
||||
LOCAL WORD nump; /* local number partitions */
|
||||
LOCAL UWORD saddr; /* local starting addr */
|
||||
LOCAL WORD length; /* local partition length */
|
||||
BYTE buf[SECSIZ]; /* an area for writing */
|
||||
LOCAL LONG dmagic; /* fixup location for xt_alloc info */
|
||||
UWORD genmfl(); /* gen a memory free list */
|
||||
UWORD genxios(); /* go gen the xios disk buffers */
|
||||
DLIST *rs; /* ptr to rsp list */
|
||||
MD md; /* sample memory descriptor */
|
||||
PD pd; /* " process descriptor */
|
||||
QCB qcb; /* " queue control block */
|
||||
CCB ccb; /* " channel control block */
|
||||
LOCK lock; /* " lock list item */
|
||||
FLAG flg; /* " flag item */
|
||||
SATITEM sat; /* " sub allocation table item */
|
||||
|
||||
if(verbose) printf("Generating tables\n");
|
||||
FCHECK(fns); /* File error check */
|
||||
|
||||
/* pre-calculate certain vars */
|
||||
bufs_seg = 0; /* total buf segs allocated in rsvd_seg */
|
||||
if( (nmparts=cntmlist(memroot)) <= 0 )
|
||||
CRASH("invalid memory list, aborting\n");
|
||||
totpds = xtrapds + nmparts; /* 1 pd per memory partition, plus xtras */
|
||||
BYTE_ADJUST(totpds);
|
||||
totmds = (3*totpds) + nmparts + (nmparts>>1); /* 3 mds per process, plus */
|
||||
/* 1 per partition, plus extra for */
|
||||
/* memory allocator worst case */
|
||||
BYTE_ADJUST(totmds);
|
||||
nsat_items = (1+ (1+2*totqcbs)); /* 1 for header entry plus worst case */
|
||||
|
||||
dltotal = dlsysdat+dlxios; /* keep track of total data length in pgphs */
|
||||
doffset = dltotal << 4; /* calculate current data offset */
|
||||
dsotables = doffset; /* mark the start of tables */
|
||||
chkaddr(doffset); /* init the function */
|
||||
|
||||
/* MEMORY FREE LIST */
|
||||
locmfl = lseek(fns,0L,1); /* remember where we are writing this */
|
||||
doffset = genmfl(doffset); /* gen the mem free list */
|
||||
|
||||
lastlink = 0; /* UNUSED MEMORY DESCRIPTOR LIST */
|
||||
zfill(&md,sizeof md); /* init the mem descriptor */
|
||||
for( count=totmds-nmparts; count>0; --count ) { /* generate rest of mds */
|
||||
md.md_link = lastlink;
|
||||
lastlink = doffset;
|
||||
doffset += datwrite(&md,sizeof(md));
|
||||
}
|
||||
*sd_mdul = lastlink; /* store ptr to mds unused */
|
||||
|
||||
lastlink = 0; /* UNUSED PROCESS DESCRIPTOR LIST */
|
||||
zfill(&pd,sizeof(pd));
|
||||
for( count=totpds; count>0; --count ) {
|
||||
pd.pd_link = lastlink;
|
||||
lastlink = doffset;
|
||||
doffset += datwrite(&pd,sizeof(pd));
|
||||
}
|
||||
*sd_pul = lastlink; /* store ptr to pds unused */
|
||||
|
||||
lastlink = 0; /* UNUSED QUEUE CONTROL BLOCKS */
|
||||
zfill(&qcb,sizeof(qcb));
|
||||
for( count=totqcbs; count>0; --count ) {
|
||||
qcb.qc_link = lastlink;
|
||||
lastlink = doffset;
|
||||
doffset += datwrite(&qcb,sizeof(qcb));
|
||||
}
|
||||
*sd_qul = lastlink; /* store ptr to unused qcb list */
|
||||
|
||||
lastlink = 0; /* UNUSED LOCKED ITEMS LIST */
|
||||
zfill(&lock,sizeof(lock));
|
||||
for( count=totopen; count>0; --count ) {
|
||||
lock.lo_link = lastlink;
|
||||
lastlink = doffset;
|
||||
doffset += datwrite(&lock,sizeof(lock));
|
||||
}
|
||||
*sd_lul = lastlink; /* store ptr to unused lock items list */
|
||||
|
||||
*sd_ncns = xt.xt_nvcns; /* transfer info from XIOS to SYSDAT*/
|
||||
*sd_ncondev = xt.xt_nccbs;
|
||||
*sd_ccb = xt.xt_ccb;
|
||||
*sd_nlst = xt.xt_nlcbs;
|
||||
*sd_nlstdev = xt.xt_nlcbs;
|
||||
*sd_lcb = xt.xt_lcb;
|
||||
*sd_nciodev = *sd_ncondev + *sd_nlstdev;
|
||||
*sd_tickspsec = xt.xt_ticks_sec;
|
||||
|
||||
*sd_xpcns = xt.xt_xpcns; /* # physical consoles;FMB */
|
||||
*sd_flags = doffset; /* FLAG TABLE */
|
||||
flg.fl_status = -1;
|
||||
flg.fl_pd = -1;
|
||||
for( count= *sd_nflags; count>0; --count ) {
|
||||
doffset += datwrite(&flg,sizeof(flg));
|
||||
}
|
||||
|
||||
|
||||
|
||||
doffset = genxios(doffset); /* go gen the xios buffering info */
|
||||
chkaddr(doffset); /* is table space too big? */
|
||||
|
||||
doffset = segwrite(doffset); /* Q Sub Alloc Tab HEADER */
|
||||
*sd_qmastart = dsstart + (doffset>>4); /* fill in seg addr */
|
||||
daqbuf = doffset + sizeof(sat)*nsat_items;
|
||||
zfill(&sat,sizeof(sat));
|
||||
sat.sa_start = --nsat_items; /* decr before write */
|
||||
doffset += datwrite(&sat,sizeof(sat)); /* write the header */
|
||||
/* Q Sub Alloc Tab ENTRIES */
|
||||
sat.sa_start = daqbuf;
|
||||
sat.sa_length = qbuflen; /* byte value */
|
||||
*sd_qmalen = qbuflen>>4; /* pgph value */
|
||||
doffset += datwrite(&sat,sizeof(sat)); /* write the first sat entry */
|
||||
|
||||
zfill(&sat,sizeof(sat));
|
||||
for( count= --nsat_items; count>0; --count ) {
|
||||
doffset += datwrite(&sat,sizeof(sat));/* write the rest of the sat entries */
|
||||
}
|
||||
|
||||
zfill(buf,SECSIZ); /* Q BUFFER AREA */
|
||||
for( ucount=qbuflen; ucount>0; ucount -= length ) {
|
||||
length = (ucount>SECSIZ ? SECSIZ : ucount);
|
||||
doffset += datwrite(buf,length);
|
||||
}
|
||||
|
||||
chkaddr(doffset); /* too big? */
|
||||
daend = padwrite(doffset); /* end Q BUF AREA and TABLES */
|
||||
|
||||
dltables = daend - dltotal; /* compute length of tables in pgphs */
|
||||
dltotal = daend; /* keep track of total data length */
|
||||
|
||||
/*** now fill in the rsps ***/
|
||||
if(verbose) printf("Appending RSPs to system file\n");
|
||||
FCHECK(fns); /* File error check */
|
||||
rsp_last = 0;
|
||||
rsp_seg = dsstart + daend;
|
||||
for( rs=rsps; rs!=NULLPTR; rs=rs->dlnext ) /* follow the rsp list */
|
||||
xfer_rsp(rs->dlname);
|
||||
*sd_rspseg = rsp_last;
|
||||
dlrsps = rsp_seg - (dsstart + daend);
|
||||
dltotal += dlrsps;
|
||||
rsvd_seg = rsp_seg;
|
||||
length = xt.xt_alloc; /* how much memory is XIOS requesting */
|
||||
xt.xt_alloc = rsvd_seg+bufs_seg; /* this is the place they can use */
|
||||
dmagic = fldstart; /* location of SYSDAT in SYS file */
|
||||
dmagic += XTABALLOC; /* add in where xt_alloc goes to */
|
||||
fixlater(dmagic,F_PUT,&(xt.xt_alloc)); /* fix this number later on */
|
||||
bufs_seg += length; /* allocate requested space */
|
||||
*sd_endseg = rsvd_seg+bufs_seg; /* this is where we reserve to */
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* genmfl: writes out a memory free list, assuming file 'fns' is seeking
|
||||
/* correctly into file.
|
||||
/**************************************************************************/
|
||||
UWORD
|
||||
genmfl(doffset)
|
||||
UWORD doffset;
|
||||
{
|
||||
REG MLIST *mn; /* ptr into EDSYS mem list */
|
||||
LOCAL WORD nump;
|
||||
LOCAL UWORD lastlink, length, saddr; /* counter vars */
|
||||
MD md; /* mem desc struct */
|
||||
|
||||
*sd_mfl = doffset; /* gen this list forward */
|
||||
zfill(&md,sizeof(md)); /* init the data structure */
|
||||
for( mn=memroot; mn!=NULLPTR; mn=mn->mlnext ) {
|
||||
nump = (mn->mllast - mn->mlfirst) / mn->mlsize;
|
||||
saddr = mn->mlfirst; /* use this starting address */
|
||||
length = md.md_length = mn->mlsize; /* size in pgphs */
|
||||
for( ; nump>0; --nump ) { /* for each partition */
|
||||
doffset += sizeof(md); /* incr by sizeof object */
|
||||
lastlink = doffset; /* record address of where this will go */
|
||||
if( nump == 1 ) { /* on this group's last partition */
|
||||
length = md.md_length = mn->mllast-saddr; /* stick in rmdr */
|
||||
if( mn->mlnext == NULLPTR ) /* on the very last partition */
|
||||
lastlink=0; /* set end of list */
|
||||
}
|
||||
md.md_link = lastlink; /* thread the list */
|
||||
md.md_start = saddr; /* set the starting addr */
|
||||
write(fns,&md,sizeof(md)); /* put it into the NEWSYS file */
|
||||
saddr += length; /* next md starts here */
|
||||
}
|
||||
} /* finished with memory partitions */
|
||||
return doffset;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
VOID
|
||||
zfill(addr,num)
|
||||
BYTE *addr;
|
||||
WORD num;
|
||||
{
|
||||
for( ; num>0; --num )
|
||||
*addr++ = '\0';
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#define RSPHDR struct rsp_header
|
||||
RSPHDR {
|
||||
UWORD rs_link; /* link to other RSPs */
|
||||
WORD rs_sdatvar; /* SYSDAT offset: num copies */
|
||||
BYTE rs_ncopies; /* local: num copies */
|
||||
BYTE rs_space[11]; /* fill up rest of header */
|
||||
};
|
||||
|
||||
RSPHDR *rhdr; /* RSP's header */
|
||||
PD *rpd; /* RSP's process descriptor area */
|
||||
UDA *ruda; /* RSP's uda area */
|
||||
#define RHDRSIZE (sizeof(RSPHDR)+sizeof(PD)+sizeof(UDA))
|
||||
#define RHDRPGPHS (RHDRSIZE>>4)
|
||||
MLOCAL BYTE rh[RHDRSIZE]; /* where to read the RSP header */
|
||||
MLOCAL BYTE rspnbuf[9]; /* room for copy of pd name */
|
||||
MLOCAL BYTE *rspname; /* name of RSP */
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
xfer_rsp(rspnm)
|
||||
BYTE *rspnm; /* name of rsp */
|
||||
{
|
||||
LOCAL WORD fr; /* rsp file descriptor */
|
||||
LOCAL WORD ncs; /* number of copies */
|
||||
|
||||
rhdr = rh; /* init these vars */
|
||||
rpd = rh+sizeof(*rhdr); /* points to process descriptor */
|
||||
ruda = rh+sizeof(*rhdr)+sizeof(*rpd); /* points to user data area */
|
||||
if( (fr=BROPEN(rspnm)) < 0 ) {
|
||||
printf("can't open RSP %s\n",rspnm);
|
||||
exit(1);
|
||||
}
|
||||
if( grpseek(fr,GTYPDATA) > 0L){ /* is there a data group? */
|
||||
ncs = grab_hdr(fr);
|
||||
if( rpd->pd_mem == 0 )
|
||||
xfer_separate_rsp(fr,ncs);
|
||||
else xfer_pure_rsp(fr,ncs);
|
||||
} else {
|
||||
grpseek(fr,GTYPCODE);
|
||||
ncs = grab_hdr(fr);
|
||||
if( rpd->pd_mem == 0 )
|
||||
xfer_mixed_rsp(fr,ncs);
|
||||
else {
|
||||
USERR("RSP %s has non zero MEM field and no data group\n",
|
||||
rspnm);
|
||||
}
|
||||
}
|
||||
close(fr);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
WORD
|
||||
grab_hdr(fr)
|
||||
WORD fr;
|
||||
{
|
||||
REG WORD rv; /* return val */
|
||||
EXTERN BYTE sdat_area[];
|
||||
|
||||
rspname = NULLPTR; /* blank out this name */
|
||||
read(fr,rh,RHDRSIZE);
|
||||
strncpy(rspnbuf,rpd->pd_name,8);/* store this in case we need it */
|
||||
if( rhdr->rs_sdatvar != 0 ) {
|
||||
rspname = rspnbuf;
|
||||
rv = sdat_area[rhdr->rs_sdatvar] - 1;
|
||||
} else {
|
||||
if( rhdr->rs_ncopies > 0 )
|
||||
rspname = rspnbuf;
|
||||
rv = rhdr->rs_ncopies;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
xfer_separate_rsp(fr,ncs) /* (many) data and (many) code segs */
|
||||
WORD fr; /* file desc of RSP file */
|
||||
WORD ncs; /* number of copies */
|
||||
{
|
||||
WORD ii; /* counter */
|
||||
|
||||
for( ii=0; ii<=ncs; ++ii) {
|
||||
ruda->ud_dsinit = ruda->ud_esinit = ruda->ud_ssinit = rsp_seg;
|
||||
ruda->ud_csinit = rsp_seg + (grpseek(fr,GTYPDATA)>>4);
|
||||
rhdr->rs_ncopies = ii;
|
||||
if( rspname ) /* do we need to insert a modfied name? */
|
||||
putname(rpd->pd_name,rspname,ii);
|
||||
rhdr->rs_link = rsp_last; /* link together the list */
|
||||
rsp_last = rsp_seg; /* remember this for next time */
|
||||
write(fns,rh,RHDRSIZE); /* write out the RSP header */
|
||||
rsp_seg += RHDRPGPHS + xferpart_grp(fr,GTYPDATA,RHDRPGPHS);
|
||||
rsp_seg += xferpart_grp(fr,GTYPCODE,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
xfer_pure_rsp(fr,ncs) /* (many) data segs and one code segs */
|
||||
WORD fr; /* file desc of RSP file */
|
||||
WORD ncs; /* number of copies */
|
||||
{
|
||||
WORD ii; /* counter */
|
||||
|
||||
ruda->ud_csinit = rsp_seg + (1+ncs) * (grpseek(fr,GTYPDATA) >> 4);
|
||||
for( ii=0; ii<=ncs; ++ii) {
|
||||
ruda->ud_dsinit = ruda->ud_esinit = ruda->ud_ssinit = rsp_seg;
|
||||
rhdr->rs_ncopies = ii;
|
||||
if( rspname ) /* do we need to insert a modfied name? */
|
||||
putname(rpd->pd_name,rspname,ii);
|
||||
rpd->pd_mem = 8; /* magic ptr to md in rsphdr */
|
||||
rhdr->rs_link = rsp_last; /* link together the list */
|
||||
rsp_last = rsp_seg; /* remember this for next time */
|
||||
write(fns,rh,RHDRSIZE); /* write out the RSP header */
|
||||
rsp_seg += RHDRPGPHS + xferpart_grp(fr,GTYPDATA,RHDRPGPHS);
|
||||
}
|
||||
rsp_seg += xferpart_grp(fr,GTYPCODE,0);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
xfer_mixed_rsp(fr,ncs) /* (many) mixed code/data segs */
|
||||
WORD fr; /* file desc of RSP file */
|
||||
WORD ncs; /* number of copies */
|
||||
{
|
||||
WORD ii; /* counter */
|
||||
|
||||
for( ii=0; ii<=ncs; ++ii) {
|
||||
ruda->ud_csinit = ruda->ud_dsinit = ruda->ud_esinit =
|
||||
ruda->ud_ssinit = rsp_seg;
|
||||
rhdr->rs_ncopies = ii;
|
||||
if( rspname ) /* do we need to insert a modfied name? */
|
||||
putname(rpd->pd_name,rspname,ii);
|
||||
rhdr->rs_link = rsp_last; /* link together the list */
|
||||
rsp_last = rsp_seg; /* remember this for next time */
|
||||
write(fns,rh,RHDRSIZE); /* write out the RSP header */
|
||||
rsp_seg += RHDRPGPHS + xferpart_grp(fr,GTYPCODE,RHDRPGPHS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
putname(to,from,num)
|
||||
BYTE *to;
|
||||
BYTE *from;
|
||||
WORD num;
|
||||
{
|
||||
BYTE buf[15];
|
||||
BYTE *bp;
|
||||
WORD jj;
|
||||
|
||||
for( bp=buf, jj=0; *from && *from != ' ' && jj<8; ++jj )
|
||||
*bp++ = *from++;
|
||||
if( jj>6 )
|
||||
bp = buf+7;
|
||||
sprintf(bp,"%x ",num);
|
||||
for( bp=buf, jj=0; jj<8; jj++ )
|
||||
*to++ = *bp++;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* dolbl: modify operating system version label */
|
||||
/************************************************************************/
|
||||
#define MAXLBL 83
|
||||
|
||||
BYTE *
|
||||
dolbl(txt,lbtitle)
|
||||
BYTE *txt; /* cmd val */
|
||||
BYTE *lbtitle;
|
||||
{
|
||||
DLIST *sl, *psl; /* ptrs to system labels */
|
||||
BYTE mb[MAXLBL]; /* max size of each line */
|
||||
EXTERN BYTE *clearit;
|
||||
|
||||
sl = psl = syslbls; /* init ptrs */
|
||||
printf("%s\n%s\n",clearit,lbtitle);
|
||||
printf("Current message is:\n");
|
||||
if( syslbls==NULLPTR )
|
||||
printf("<null>\n");
|
||||
else for( ; sl != NULLPTR; sl = (psl=sl)->dlnext )
|
||||
printf("%s\n",sl->dlname);
|
||||
printf("\nAdd lines to message. Terminate by entering only RETURN:\n");
|
||||
FOREVER {
|
||||
if( gets(mb) != mb || *mb==NULL )
|
||||
break;
|
||||
sl = (DLIST *)malloc(sizeof(*sl)); /* alloc a list item */
|
||||
sl->dlname = malloc(sizeof(mb));
|
||||
strcpy(sl->dlname,mb); /* copy message to new space */
|
||||
sl->dlnext = NULLPTR;
|
||||
if( psl==NULLPTR ) /* new list? */
|
||||
syslbls = psl = sl; /* this will be the first line */
|
||||
else {
|
||||
psl->dlnext = sl;
|
||||
psl = psl->dlnext;
|
||||
}
|
||||
}
|
||||
return NULLPTR;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* writelbl: writes the OS label to the NEWSYS file, returning the length
|
||||
/* of the label (in pgphs)
|
||||
/************************************************************************/
|
||||
WORD
|
||||
_wrlbl(str) /* subroutine to writelbl */
|
||||
BYTE *str;
|
||||
{
|
||||
REG WORD slen;
|
||||
|
||||
slen=strlen(str); /* length of string to be written */
|
||||
write(fns,str,slen); /* write string to file NEWSYS */
|
||||
write(fns,"\015\012",2); /* cr,lf */
|
||||
return slen+2;
|
||||
}
|
||||
|
||||
WORD
|
||||
writelbl() /* returns num pgphs written */
|
||||
{
|
||||
REG WORD cc; /* count of chars output */
|
||||
DLIST *sl; /* list ptr */
|
||||
|
||||
cc = 0;
|
||||
|
||||
cc += _wrlbl(""); /* crlf */
|
||||
cc += _wrlbl(version); /* write out the version label */
|
||||
cc += _wrlbl(copyright); /* followed by copyright notice */
|
||||
for( sl=syslbls; sl!=NULLPTR; sl=sl->dlnext )
|
||||
cc += _wrlbl(sl->dlname); /* followed by all lines in OS label */
|
||||
cc += _wrlbl("$"); /* terminate message for printstr fn */
|
||||
return padwrite(cc); /* writes enough zeroes to pad to pgph bdry */
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* fixup routines: remembers and posthumously patches the SYS file
|
||||
/***************************************************************************/
|
||||
|
||||
FIX *fixroot = NULLPTRI; /* list of fixes */
|
||||
|
||||
fixlater(fa,ft,fp) /* records the fix in the list */
|
||||
LONG fa; /* addr within NEWSYS to fix */
|
||||
WORD ft; /* type of fix: F_ADD or F_PUT */
|
||||
WORD *fp; /* ptr to val used in fixing */
|
||||
{
|
||||
FIX *fx;
|
||||
|
||||
fx = (FIX *)malloc(sizeof *fx); /* alloc a list item */
|
||||
fx->f_addr = fa;
|
||||
fx->f_type = ft;
|
||||
fx->f_ptr = fp;
|
||||
fx->f_next = fixroot; /* insert at head of list */
|
||||
fixroot = fx;
|
||||
}
|
||||
|
||||
fixfile() /* does the fixes in the file */
|
||||
{
|
||||
FIX *fx;
|
||||
WORD fval; /* the value to stuff */
|
||||
LONG lastval;
|
||||
|
||||
lastval=lseek(fns,0L,2); /* end of file */
|
||||
|
||||
for( fx=fixroot; fx!=NULLPTR; fx = fx->f_next ) {
|
||||
if(fx->f_addr > lastval) { /* oops! past eof */
|
||||
printf("fixup addressing internal error: %X %x %x\n",fx->f_addr,fx->f_type,fx->f_ptr);
|
||||
continue;
|
||||
}
|
||||
if( lseek(fns,fx->f_addr,0) < 0L )
|
||||
CRASH("fixup seek failure\n");
|
||||
if( fx->f_type == F_ADD ) { /* F_ADD the value to what's there */
|
||||
read(fns,&fval,2);
|
||||
fval += *(fx->f_ptr);
|
||||
lseek(fns,-2L,1); /* backup to write */
|
||||
} else /* must be a F_PUT */
|
||||
fval = *(fx->f_ptr);
|
||||
write(fns,&fval,2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,766 @@
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* genc4.c - This module exports the following routines:
|
||||
/*
|
||||
/* initxios_info(xf,goff) 'xf' is XIOSMOD file descriptor, 'goff'
|
||||
/* is offset of data group in XIOSMOD (including header);
|
||||
/* this module inits the buffering info questions.
|
||||
/* doxbufs(txt,title) 'txt' is a command, 'title' is the prompt for this fn;
|
||||
/* this routine is called within the MENU module, and prompts user
|
||||
/* for xios info.
|
||||
/* xiosvalid() returns a BOOLEAN value indicating whether the xios info
|
||||
/* is valid.
|
||||
/* genxios(doffset) generates the buffers for the xios, starting at 'doffset'
|
||||
/* in the system data area.
|
||||
/* fixupxios_info() writes DPH fixups required by genxios
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifndef MAINMODULE
|
||||
#include <genccpm.h>
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* edsdisk.h : defines the data structures used in this module
|
||||
/**************************************************************************/
|
||||
|
||||
#define ADDR UWORD /* Address (offset) within SysDat */
|
||||
#define SEG UWORD /* Segment address (may be outside SysDat) */
|
||||
|
||||
#define DPH struct dph_item
|
||||
DPH { /* Disk Parameter Header structure */
|
||||
ADDR dph_xlt; /* Translation Table Address */
|
||||
BYTE dph_space[6]; /* reserved & Media Flag */
|
||||
ADDR dph_dpb; /* Disk Parameter Block Address */
|
||||
ADDR dph_csv; /* CheckSum Vector Address */
|
||||
ADDR dph_alv; /* Allocation Vector Address */
|
||||
ADDR dph_dirbcb; /* Dir Buffer Control Block Header Address */
|
||||
ADDR dph_datbcb; /* Data Buffer Control Block Header Address */
|
||||
SEG dph_hstbl; /* Hash Table Segment */
|
||||
};
|
||||
|
||||
#define EDPB struct edbp_item
|
||||
EDPB { /* Extended Disk Parameter Block entries */
|
||||
WORD edpb_extflag; /* Extended DPB flag */
|
||||
WORD edpb_nfats; /* Number of FATS */
|
||||
WORD edpb_nfatrecs; /* Number of records per FAT */
|
||||
WORD edpb_nclstrs; /* Number of clusters */
|
||||
WORD edpb_clsize; /* Cluster size */
|
||||
WORD edpb_fatadd; /* FAT address */
|
||||
};
|
||||
|
||||
#define DPB struct dpb_item
|
||||
DPB { /* Disk Parameter Block structure */
|
||||
WORD dpb_spt; /* Sectors Per Track */
|
||||
BYTE dpb_bsh; /* Allocation Block Shift Factor */
|
||||
BYTE dpb_blm; /* Allocation Block Mask */
|
||||
BYTE dpb_exm; /* Extent Mask */
|
||||
WORD dpb_dsm; /* Disk Storage Maximum */
|
||||
WORD dpb_drm; /* Directory Maximum */
|
||||
WORD dpb_dav; /* Directory Allocation Vector */
|
||||
WORD dpb_cks; /* Checksum Vector Size */
|
||||
WORD dpb_off; /* Track Offset */
|
||||
WORD dpb_psh; /* Physical Record Shift Factor */
|
||||
WORD dpb_phm; /* Physical Record Mask */
|
||||
};
|
||||
|
||||
#define BCBH struct bcbh_item
|
||||
BCBH { /* Buffer Control Block Header structure */
|
||||
ADDR bcbh_lr; /* BCB List Root */
|
||||
BYTE bcbh_pm; /* BCB Process Max */
|
||||
};
|
||||
|
||||
#define BCB struct bcb_item
|
||||
BCB { /* Buffer Control Block structure */
|
||||
BYTE bcb_drv; /* Drive */
|
||||
BYTE bcb_record[3]; /* Record Number */
|
||||
BYTE bcb_wflg; /* Write Pending Flag */
|
||||
BYTE bcb_seq; /* Sequential Access Counter */
|
||||
WORD bcb_track; /* Logical Track Number */
|
||||
WORD bcb_sector; /* Logical Translated Sector Number */
|
||||
UWORD bcb_bufptr; /* Buffer Offset (for DIRBCB) / Segment (for DATBCB) */
|
||||
ADDR bcb_link; /* Link to next BCB */
|
||||
WORD bcb_pdadr; /* Process Descriptor Address */
|
||||
};
|
||||
|
||||
|
||||
#define DINFO struct dirbuf_information
|
||||
DINFO {
|
||||
BOOLEAN d_modified; /* DPH was modified? */
|
||||
BOOLEAN d_hashing; /* user wants hashing? */
|
||||
WORD d_ndirbs; /* Num dir buffers */
|
||||
WORD d_sdirbs; /* Size dir buffers */
|
||||
WORD d_pmdirbs; /* Process Max Number Dir Buffs */
|
||||
WORD d_ndatbs; /* Num data buffers */
|
||||
WORD d_sdatbs; /* Size data buffers */
|
||||
WORD d_pmdatbs; /* Process Max Number Dir Buffs */
|
||||
WORD d_shash; /* Size of hash table */
|
||||
WORD d_alvsize; /* size of Alloc Vector area (in bytes ) */
|
||||
WORD d_blksize; /* size of disk Allocation Block */
|
||||
WORD d_csvsize; /* size of Checksum Vector area */
|
||||
};
|
||||
|
||||
/* end of edsdisk.h ********************************************************/
|
||||
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
WORD csfd; /* command file descriptor */
|
||||
WORD csgoff; /* group offset within command file */
|
||||
|
||||
cseek(offs) /* seek offset within Command File */
|
||||
ADDR offs;
|
||||
{
|
||||
lseek(csfd,(LONG) offs+csgoff, 0); /* compensate for cmd header */
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* Put special byte for buffer fills */
|
||||
#define ZBYTE (doffset&0xFF) /* the byte usually passed in */
|
||||
WORD
|
||||
bufwrite(size,byt)
|
||||
WORD size;
|
||||
BYTE byt;
|
||||
{
|
||||
WORD ss;
|
||||
|
||||
for( ss=size; ss>0; --ss )
|
||||
write(fns,&byt,1);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* Module local variables */
|
||||
#define DPHNUM 16 /* number of possible disks */
|
||||
ADDR *dphtab; /* table of offsets of Disk Parm Hdrs */
|
||||
DPH *dh[DPHNUM]; /* table of Disk Parm Hdrs */
|
||||
DINFO *di[DPHNUM]; /* table of info on DPHs */
|
||||
|
||||
|
||||
/* Module local predicates */
|
||||
#define ASKFOR(aa) ((aa) == 0xFFFF) /* Is this one we're sposed to ask for? */
|
||||
#define SHRMSK 0x8000 /* Is this shared with another drive? */
|
||||
#define SHARED(bb) ((bb)!=0xFFFF && (bb) & SHRMSK) /* Is this nd??bs field shared with another disk? */
|
||||
#define GETSHARED(cc) ((cc) & ~SHRMSK) /* Get the drive we share with */
|
||||
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* EXPORT
|
||||
/* initxios_info: gets whatever information GENSYS needs from xios
|
||||
/***************************************************************************/
|
||||
initxios_info(xf,goff) /* get info from xios file */
|
||||
WORD xf; /* xios file descriptor */
|
||||
WORD goff; /* group offset within xios file */
|
||||
{
|
||||
REG WORD ii; /* counter */
|
||||
DPB dd; /* a place to keep this info */
|
||||
EDPB ee; /* a place to keep this info */
|
||||
DPH *dph;
|
||||
DINFO *dinf;
|
||||
|
||||
csfd = xf; /* assign to global: set up cseek */
|
||||
csgoff = goff; /* assign to global */
|
||||
cseek(XTABLOC); /* go to where the XIOSTAB info is */
|
||||
read(xf,&xt,sizeof xt); /* read in the xios info */
|
||||
dphtab = xt.xt_dphtab; /* point to disk parm header table */
|
||||
|
||||
for( ii=0; ii<DPHNUM; ++ii ) { /* for each dph pointer */
|
||||
if( dphtab[ii] == 0 ) { /* is there a dph? */
|
||||
dh[ii]=NULLPTR;
|
||||
di[ii]=NULLPTR; /* no tickee, no washee */
|
||||
} else { /* aha! let's set up this info */
|
||||
dh[ii] = (DPH *)malloc(sizeof(DPH));
|
||||
di[ii] = (DINFO *)malloc(sizeof(DINFO));
|
||||
zfill(di[ii],sizeof(DINFO));
|
||||
cseek(dphtab[ii]);
|
||||
read(xf,dh[ii],sizeof(DPH));
|
||||
}
|
||||
} /* end of reading dph */
|
||||
for( ii=0; ii<DPHNUM; ++ii ) /* let's go thru it again */
|
||||
if( dh[ii] ) { /* if there's something there */
|
||||
dph = dh[ii];
|
||||
dinf = di[ii];
|
||||
cseek(dph->dph_dpb); /* point to the disk parm block */
|
||||
read(xf,&ee,sizeof(EDPB)); /* Read as though EDPB */
|
||||
if (ee.edpb_extflag == 0xFFFF) { /* Extended DPB */
|
||||
cseek(dph->dph_dpb+12); /* seek past extended info */
|
||||
} else {
|
||||
cseek(dph->dph_dpb);
|
||||
}
|
||||
read(xf,&dd,sizeof(DPB)); /* read DPH */
|
||||
dinf->d_blksize = 128 << dd.dpb_psh;
|
||||
dinf->d_csvsize = 0x7FFF & dd.dpb_cks;
|
||||
dinf->d_alvsize = (dd.dpb_dsm/8 + 1) * 2;
|
||||
dinf->d_shash = 4 * (1 + dd.dpb_drm);
|
||||
dinf->d_ndirbs = -1; /* ask for these by name! */
|
||||
dinf->d_ndatbs = -1;
|
||||
dinf->d_hashing = TRUE; /* default to hashing */
|
||||
} /* end of drive info init */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* EXPORT
|
||||
/* doxbufs: queries user for BDOS buffering info;
|
||||
/* exits only when all data valid
|
||||
/************************************************************************/
|
||||
BYTE *
|
||||
doxbufs(txt,bdtitle)
|
||||
BYTE *txt;
|
||||
BYTE *bdtitle;
|
||||
{
|
||||
BYTE cmds[CMDSLEN];
|
||||
BOOLEAN xiosvalid();
|
||||
EXTERN BYTE *clearit;
|
||||
|
||||
FOREVER {
|
||||
printf("%s",clearit); /* clear screen */
|
||||
printf("%s\n",bdtitle);
|
||||
dbufs_display(); /* display */
|
||||
printf("Drive (<CR> to exit) ? ");
|
||||
if( gets(cmds)!=cmds || *cmds==NULL ) { /* they hit <CR>? */
|
||||
if( xiosvalid() ) break;
|
||||
USERR("Please correct drive buffers information\n");
|
||||
press_return();
|
||||
continue;
|
||||
}
|
||||
askabout(cmds); /* go do what they want */
|
||||
}
|
||||
return NULLPTR; /* error msg for menu handler */
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* dbufs_display: display disk buffering info
|
||||
/************************************************************************/
|
||||
dbufs_display()
|
||||
{
|
||||
REG UWORD ii, jj, tot; /* counters */
|
||||
DPH *dph;
|
||||
DINFO *dinf;
|
||||
|
||||
tot = 0; /* init this */
|
||||
dcalcsizes(); /* check all the sizes */
|
||||
printf("\n\t*** Disk Buffering Information ***\n");
|
||||
printf(" Dir Max/Proc Data Max/Proc Hash Specified\n");
|
||||
printf("Drv Bufs Dir Bufs Bufs Dat Bufs -ing Buf Pgphs\n");
|
||||
printf("=== ==== ======== ==== ======== ==== =========\n");
|
||||
for( ii=0; ii<DPHNUM; ++ii ) { /*** for each drive ***/
|
||||
if( dphtab[ii]==0 ) continue; /* no DP Hdr for this drive */
|
||||
dph = dh[ii]; dinf = di[ii];
|
||||
printf(" %c: ",'A'+ii); /* print which drive */
|
||||
dspdnums(dph->dph_dirbcb,dinf->d_ndirbs,dinf->d_pmdirbs);
|
||||
dspdnums(dph->dph_datbcb,dinf->d_ndatbs,dinf->d_pmdatbs);
|
||||
if( ! ASKFOR(dph->dph_hstbl) )
|
||||
printf(" fixed ");
|
||||
else if( dinf->d_hashing )
|
||||
printf(" yes ");
|
||||
else printf(" no ");
|
||||
jj = dspdsize(dph,dinf);
|
||||
if( jj == -2 )
|
||||
printf(" fixed ");
|
||||
else if( jj == -1 )
|
||||
printf(" ?? ");
|
||||
else {
|
||||
printf(" %4.4x ",jj >> 4);
|
||||
tot += jj;
|
||||
}
|
||||
printf("\n");
|
||||
} /*** end for each drive ***/
|
||||
printf("Total paragraphs allocated to buffers: %x\n",tot >> 4);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* dspdsize: calculates a drive's user-requestable buffer size, in bytes
|
||||
/***************************************************************************/
|
||||
WORD
|
||||
dspdsize(dph,dinf) /* calculate size requested */
|
||||
DPH *dph; /* returns -1 if still needs info */
|
||||
DINFO *dinf; /* returns -2 if pre-allocated */
|
||||
{
|
||||
REG WORD siz;
|
||||
|
||||
siz=0;
|
||||
if( !ASKFOR(dph->dph_dirbcb) &&
|
||||
!ASKFOR(dph->dph_datbcb) &&
|
||||
!ASKFOR(dph->dph_hstbl) )
|
||||
return -2; /* nothing to say here */
|
||||
if( ASKFOR(dph->dph_dirbcb) ){
|
||||
if( ASKFOR(dinf->d_ndirbs) )
|
||||
return -1;
|
||||
if( !SHARED(dinf->d_ndirbs) )
|
||||
siz += dinf->d_sdirbs * dinf->d_ndirbs;
|
||||
}
|
||||
if( ASKFOR(dph->dph_datbcb) ){
|
||||
if( ASKFOR(dinf->d_ndatbs) )
|
||||
return -1;
|
||||
if( !SHARED(dinf->d_ndatbs) )
|
||||
siz += dinf->d_sdatbs * dinf->d_ndatbs;
|
||||
}
|
||||
if( ASKFOR(dph->dph_hstbl) ){
|
||||
if( dinf->d_hashing )
|
||||
siz += dinf->d_shash;
|
||||
}
|
||||
return siz;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* dspdnums: displays the data/dir buf numbers
|
||||
/***************************************************************************/
|
||||
dspdnums(nfix,ninput,npm) /* display subroutine */
|
||||
WORD nfix;
|
||||
WORD ninput;
|
||||
WORD npm;
|
||||
{
|
||||
if( !ASKFOR(nfix) )
|
||||
printf("fixed ");
|
||||
else if( SHARED(ninput) )
|
||||
printf("shares %c: ",'A'+GETSHARED(ninput));
|
||||
else {
|
||||
if( ASKFOR(ninput) )
|
||||
printf(" ?? ");
|
||||
else printf(" %2.2x ",ninput);
|
||||
if( ASKFOR(npm) )
|
||||
printf(" ?? ");
|
||||
else printf(" %2.2x ",npm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* dcalcsizes: calculates buffer sizes across shared buffers
|
||||
/***************************************************************************/
|
||||
dcalcsizes() /* make sure all the sizes are correct */
|
||||
{
|
||||
REG WORD ii, jj;
|
||||
REG WORD *pkk;
|
||||
DPH *dph;
|
||||
DINFO *dinf;
|
||||
|
||||
for( ii=0; ii<DPHNUM; ++ii ) /* init all sizes to zero */
|
||||
if(dphtab[ii]) {
|
||||
dinf = di[ii];
|
||||
dinf->d_sdirbs = dinf->d_sdatbs = 0;
|
||||
}
|
||||
for( ii=0; ii<DPHNUM; ++ii ) /* for each drive */
|
||||
if(dphtab[ii]) {
|
||||
dph = dh[ii];
|
||||
dinf = di[ii];
|
||||
if( ASKFOR(dph->dph_dirbcb) ) /* max out the size of a dirbuf */
|
||||
if( !ASKFOR(dinf->d_ndirbs) ) { /* if it's real data there */
|
||||
if( SHARED(dinf->d_ndirbs) ) {
|
||||
jj = GETSHARED(dinf->d_ndirbs);
|
||||
pkk = & ((di[jj])->d_sdirbs);
|
||||
} else
|
||||
pkk = & dinf->d_sdirbs;
|
||||
if( dinf->d_blksize > *pkk ) /* assign the maximum size found */
|
||||
*pkk = dinf->d_blksize;
|
||||
}
|
||||
if( ASKFOR(dph->dph_datbcb) ) /* max out the size of a data buf */
|
||||
if( !ASKFOR(dinf->d_ndatbs) ) {
|
||||
if( SHARED(dinf->d_ndatbs) ) {
|
||||
jj = GETSHARED(dinf->d_ndatbs);
|
||||
pkk = & ((di[jj])->d_sdatbs);
|
||||
} else
|
||||
pkk = & dinf->d_sdatbs;
|
||||
if( dinf->d_blksize > *pkk )
|
||||
*pkk = dinf->d_blksize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* ask user about a drive
|
||||
/***************************************************************************/
|
||||
askabout(drspec) /* ask user about a drive */
|
||||
BYTE *drspec;
|
||||
{
|
||||
REG WORD dr;
|
||||
DPH *dph;
|
||||
DINFO *dinf;
|
||||
BOOLEAN askhash();
|
||||
|
||||
if( *drspec == '*' ) {
|
||||
askstar(); /* get info, apply to all disks */
|
||||
return;
|
||||
}
|
||||
dr = toupper(*drspec) - 'A'; /* which drive do they want to fix? */
|
||||
if( dr<0 || dr>=DPHNUM || dphtab[dr]==0 || drspec[1] != ':') {
|
||||
USERR("Problem with '%s':\n",drspec);
|
||||
USERR("Please specify an existing drive between 'A:' and 'P:'\n");
|
||||
press_return();
|
||||
return;
|
||||
}
|
||||
dph = dh[dr];
|
||||
dinf = di[dr];
|
||||
if( dspdsize(dph,dinf) == -2 ) { /* is there anything to modify? */
|
||||
USERR("All buffers for %c: are fixed within the XIOS module.\n",
|
||||
dr+'A');
|
||||
USERR("You can't modify this fixed information in GENSYS.\n");
|
||||
press_return();
|
||||
return;
|
||||
}
|
||||
if( ASKFOR(dph->dph_dirbcb) ){
|
||||
dinf->d_ndirbs = asknd(1,FALSE); /* get directory info */
|
||||
dinf->d_pmdirbs = askpm(1,dinf->d_ndirbs);
|
||||
}
|
||||
if( ASKFOR(dph->dph_datbcb) ){
|
||||
dinf->d_ndatbs = asknd(2,(128==dinf->d_blksize)); /* get data info */
|
||||
dinf->d_pmdatbs = askpm(2,dinf->d_ndatbs);
|
||||
}
|
||||
if( ASKFOR(dph->dph_hstbl) ){
|
||||
dinf->d_hashing = askhash();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* askstar: asks buffering questions & applies to all ASKFOR/unanswered drives
|
||||
/****************************************************************************/
|
||||
askstar()
|
||||
{
|
||||
REG WORD dr;
|
||||
DPH *dph;
|
||||
DINFO *dinf;
|
||||
WORD andirbs, andirpms, andatbs, andatpms;
|
||||
BOOLEAN ahash, askhash();
|
||||
|
||||
andirbs = asknd(1,FALSE); /* Number of directory buffers? */
|
||||
andirpms = askpm(1,andirbs); /* Process Max Dir Bufs? */
|
||||
andatbs = asknd(2,FALSE); /* Number of data buffers? */
|
||||
andatpms = askpm(2,andatbs); /* Process Max Data Bufs? */
|
||||
ahash = askhash(); /* Hashing? */
|
||||
for( dr=0; dr<DPHNUM; ++dr )
|
||||
if( dphtab[dr] ) { /* for all existing drives */
|
||||
dph = dh[dr]; dinf = di[dr];
|
||||
if( ASKFOR(dph->dph_dirbcb) )
|
||||
if( ASKFOR(dinf->d_ndirbs) ) {
|
||||
dinf->d_ndirbs = andirbs;
|
||||
dinf->d_pmdirbs = andirpms;
|
||||
}
|
||||
if( ASKFOR(dph->dph_datbcb) )
|
||||
if( ASKFOR(dinf->d_ndatbs) ) {
|
||||
dinf->d_ndatbs = andatbs;
|
||||
dinf->d_pmdatbs = andatpms;
|
||||
}
|
||||
if( ASKFOR(dph->dph_hstbl) )
|
||||
dinf->d_hashing = ahash;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* asknd: ask the user for the number of dir/data buffers
|
||||
/***************************************************************************/
|
||||
WORD
|
||||
asknd(type,zero_ok)
|
||||
WORD type; /* 1=dir, 2=data */
|
||||
BOOLEAN zero_ok;
|
||||
{
|
||||
REG WORD val, jj;
|
||||
BYTE *name;
|
||||
BYTE cmds[CMDSLEN];
|
||||
DPH *dph;
|
||||
|
||||
if( type==1 ) name="directory"; else name="data";
|
||||
FOREVER {
|
||||
printf("Number of %s buffers, or drive to share with ? ",name);
|
||||
gets( cmds );
|
||||
if( cmds[1] != ':' ) {
|
||||
val = atoih(cmds);
|
||||
if( val > 0 && val <= 127 ) break;
|
||||
if(*cmds == '0') {
|
||||
if( zero_ok ) break;
|
||||
USERR("Number of buffers must be greater than 0\n");
|
||||
press_return();
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
val = toupper(*cmds) - 'A'; /* which drive do they want? */
|
||||
if( val>=0 && val<DPHNUM && dphtab[val]!=0) { /* a drive maybe? */
|
||||
dph = dh[val];
|
||||
if( type==1 ) jj = dph->dph_dirbcb;
|
||||
else jj = dph->dph_datbcb;
|
||||
if( ASKFOR(jj) ) {
|
||||
if( type==1 ) jj = di[val]->d_ndirbs;
|
||||
else jj = di[val]->d_ndatbs;
|
||||
if( !SHARED(jj) ) {
|
||||
val |= SHRMSK; /* turn on sharing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
USERR("Drive %c: is not available for sharing\n",'A'+val);
|
||||
press_return();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
USERR("Please input a number, or an existing drive from 'A:' to 'P:'\n");
|
||||
press_return();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/************************************/
|
||||
/* askpm: ask about process maximum
|
||||
/************************************/
|
||||
WORD
|
||||
askpm(type,pmmax)
|
||||
WORD type;
|
||||
WORD pmmax;
|
||||
{
|
||||
REG WORD val;
|
||||
BYTE *cmds[CMDSLEN];
|
||||
BYTE *name;
|
||||
|
||||
switch(type) { case 1: name="directory"; break; case 2: name="data"; }
|
||||
if( SHARED(pmmax) || pmmax<=0 )
|
||||
return 0;
|
||||
FOREVER { /* get input from user */
|
||||
printf("Maximum %s buffers per process [%x]? ",name,pmmax);
|
||||
gets( cmds );
|
||||
if( *cmds==NULL )
|
||||
val = pmmax; /* default value */
|
||||
else val = atoih(cmds);
|
||||
if( val > 0 && val <= pmmax ) break;
|
||||
USERR("Maximum must be > zero and <= %x\n",pmmax);
|
||||
press_return();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/*****************************************/
|
||||
/* askhash: ask user if they'd like to hash
|
||||
/*****************************************/
|
||||
BOOLEAN
|
||||
askhash()
|
||||
{
|
||||
REG WORD val;
|
||||
BYTE *cmds[CMDSLEN], *cp;
|
||||
|
||||
FOREVER {
|
||||
printf("Hashing [yes] ? ");
|
||||
gets( cmds );
|
||||
if( *cmds == NULL )
|
||||
return TRUE;
|
||||
for( cp=cmds; *cp; ++cp ) {
|
||||
if( *cp==' ' || *cp=='\t' ) {
|
||||
*cp = NULL;
|
||||
break;
|
||||
}
|
||||
if( isupper(*cp) )
|
||||
*cp = tolower(*cp);
|
||||
}
|
||||
if( (val=whichof(cmds,",yes,true,on,hashing,no,false,off")) > 0 )
|
||||
break;
|
||||
USERR("Please answer 'hashing', 'yes', or 'no'.\n");
|
||||
press_return();
|
||||
}
|
||||
return val<=4; /* TRUE iff answer was one of 1st four */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* EXPORT
|
||||
/* xiosvalid: validates that all the user-requestable info has been filled in
|
||||
/************************************************************************/
|
||||
BOOLEAN
|
||||
xiosvalid()
|
||||
{
|
||||
REG WORD ii;
|
||||
REG WORD ndph;
|
||||
|
||||
ndph = 0;
|
||||
for( ii=0; ii<DPHNUM; ++ii )
|
||||
if( dphtab[ii]!=0 ) {
|
||||
if( dspdsize(dh[ii],di[ii]) == -1 )
|
||||
return FALSE;
|
||||
++ndph;
|
||||
}
|
||||
if( ndph==0 ) {
|
||||
USERR("no dph information in xios header...");
|
||||
exit(1);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* EXPORT
|
||||
/* genxios: generates disk buffers (to be placed after the rest of the
|
||||
/* system tables.
|
||||
/*************************************************************************/
|
||||
#define OFF_BCBPTR 0xA
|
||||
#define OFF_DPHHTAB 0x12
|
||||
ADDR locrsvd_off; /* local reserved offset, for DIRBUF fix */
|
||||
|
||||
ADDR /* returns final offset */
|
||||
genxios(doffset) /* generate the disk buffers */
|
||||
ADDR doffset; /* offset in data file */
|
||||
{
|
||||
REG WORD ii, jj; /* counter */
|
||||
REG BOOLEAN dm; /* modified flag */
|
||||
REG ADDR lastlink; /* used for threading lists */
|
||||
ADDR locbufs_off; /* local buffer offset for DIRBUF grouping */
|
||||
LONG dmagic; /* where word needing fix goes into file */
|
||||
BCB bcb; /* place for organizing, calc for fixups */
|
||||
BCBH bcbh;
|
||||
DPH *dph;
|
||||
DINFO *dinf;
|
||||
BOOLEAN xiosvalid();
|
||||
|
||||
if( !xiosvalid() ) CRASH("invalid disk buffer information");
|
||||
|
||||
for( ii=0; ii<DPHNUM; ++ii ) /* allocate CHECK SUM VECTORS */
|
||||
if( dh[ii] ) { /* if there's something to look at */
|
||||
dph = dh[ii]; /* convenient ptr */
|
||||
dinf = di[ii];
|
||||
if( ASKFOR(dph->dph_csv) ){
|
||||
dinf->d_modified = TRUE;
|
||||
if( dinf->d_csvsize == 0 )
|
||||
dph->dph_csv=0;
|
||||
else {
|
||||
dph->dph_csv = doffset;
|
||||
doffset += bufwrite(dinf->d_csvsize,ZBYTE);
|
||||
}
|
||||
}
|
||||
}
|
||||
for( ii=0; ii<DPHNUM; ++ii ) /* allocate ALLOCATION TABLE VECTORS */
|
||||
if( dh[ii] ) { /* if there's something to look at */
|
||||
dph = dh[ii]; /* convenient ptr */
|
||||
dinf = di[ii];
|
||||
if( ASKFOR(dph->dph_alv) ){
|
||||
dinf->d_modified = TRUE;
|
||||
dph->dph_alv = doffset;
|
||||
doffset += bufwrite(dinf->d_alvsize,ZBYTE);
|
||||
}
|
||||
}
|
||||
locbufs_off = 0; /* amount (bytes) of local dir buffer*/
|
||||
for( ii=0; ii<DPHNUM; ++ii ) /* allocate DIR BCBs & BUFFERS */
|
||||
if( dh[ii] ) { /* if there's something to look at */
|
||||
dph = dh[ii]; /* convenient ptr */
|
||||
dinf = di[ii];
|
||||
if( ASKFOR(dph->dph_dirbcb) ){ /* DIR BCBs */
|
||||
dinf->d_modified = TRUE;
|
||||
if( ! SHARED(dinf->d_ndirbs) ) { /* take care of sharing later */
|
||||
lastlink=0; /* linker */
|
||||
zfill(&bcb,sizeof(BCB)); /* init to zeroes */
|
||||
bcb.bcb_drv = 0xFF;
|
||||
for( jj=dinf->d_ndirbs; jj>0; --jj ){
|
||||
bcb.bcb_link = lastlink;
|
||||
/* pts to loc of buffer relative to locrsvd_off */
|
||||
bcb.bcb_bufptr = locbufs_off;
|
||||
locbufs_off += dinf->d_sdirbs; /* increase buf size */
|
||||
/* calc where bcb will be written to, for fixlater */
|
||||
dmagic = lseek(fns,0L,1) + OFF_BCBPTR;
|
||||
fixlater(dmagic,F_ADD,&locrsvd_off);
|
||||
/* finally, write out the bcb info */
|
||||
lastlink = doffset; /* point to the bcb */
|
||||
doffset += datwrite(&bcb,sizeof bcb);
|
||||
}
|
||||
bcbh.bcbh_lr = lastlink; /* fill in the bcb hdr */
|
||||
bcbh.bcbh_pm = dinf->d_pmdirbs;
|
||||
dph->dph_dirbcb = doffset; /* link to head of list */
|
||||
/* write out a buffer control block hdr */
|
||||
doffset += datwrite(&bcbh,sizeof bcbh);
|
||||
}
|
||||
}
|
||||
}
|
||||
for( ii=0; ii<DPHNUM; ++ii ) /* allocate DATA BCBs & BUFFERS */
|
||||
if( dh[ii] ) { /* if there's something to look at */
|
||||
dph = dh[ii]; /* convenient ptr */
|
||||
dinf = di[ii];
|
||||
/* the bufs can go out of the system page, but the bcbs need to be in */
|
||||
if( ASKFOR(dph->dph_datbcb) ){ /* DATA BCBs: !!temporary!! */
|
||||
dinf->d_modified = TRUE;
|
||||
if( ! SHARED(dinf->d_ndatbs) ) { /* do sharing later */
|
||||
lastlink=0; /* linker */
|
||||
zfill(&bcb,sizeof(BCB)); /* init to zeroes */
|
||||
bcb.bcb_drv = 0xFF;
|
||||
for( jj=dinf->d_ndatbs; jj>0; --jj ){
|
||||
bcb.bcb_link = lastlink;
|
||||
bcb.bcb_bufptr = bufs_seg; /* point into reserved area */
|
||||
bufs_seg += (dinf->d_sdatbs) >>4; /* cvt to pgphs */
|
||||
/* calculate where the bcb.bcb_bufptr will be written in file */
|
||||
dmagic = lseek(fns,0L,1) + OFF_BCBPTR;
|
||||
fixlater(dmagic,F_ADD,&rsvd_seg); /* fix the bufptr */
|
||||
lastlink = doffset;
|
||||
/* write out a buffer control block */
|
||||
doffset += datwrite(&bcb,sizeof bcb);
|
||||
}
|
||||
bcbh.bcbh_lr = lastlink; /* fill in the bcb hdr */
|
||||
bcbh.bcbh_pm = dinf->d_pmdatbs;
|
||||
dph->dph_datbcb = doffset; /* link to head of list */
|
||||
/* write out a buffer control block hdr */
|
||||
doffset += datwrite(&bcbh,sizeof bcbh);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* now write the local directory buffers */
|
||||
locrsvd_off = doffset; /* address of directory buffer area */
|
||||
doffset += bufwrite(locbufs_off,ZBYTE); /* write out the buffers */
|
||||
|
||||
/* dmagic: magic number to add to dphtab[ii] */
|
||||
dmagic = OFF_DPHHTAB + fldstart;/* where in file does SYSDAT start */
|
||||
|
||||
for( ii=0; ii<DPHNUM; ++ii ) /* allocate HASH TABLES */
|
||||
if( dh[ii] ) { /* if there's something to look at */
|
||||
dph = dh[ii]; /* convenient ptr */
|
||||
dinf = di[ii];
|
||||
if( ASKFOR(dph->dph_hstbl) ) { /* HASH TABLE ALLOC */
|
||||
dinf->d_modified = TRUE;
|
||||
if( dinf->d_hashing ) {
|
||||
dph->dph_hstbl = bufs_seg; /* point into reserved area */
|
||||
bufs_seg += (dinf->d_shash) >>4; /* cvt bytes to pgphs */
|
||||
/* remember where the dph_hstbl word will be stored */
|
||||
/* so we can adjust bufs_seg by starting loc of rsvd_seg */
|
||||
fixlater(dmagic+dphtab[ii],F_ADD,&rsvd_seg);
|
||||
} else dph->dph_hstbl = 0;
|
||||
}
|
||||
} /**** end of processing ****/
|
||||
|
||||
for( ii=0; ii<DPHNUM; ++ii ) /* resolve shared buffers */
|
||||
if( dh[ii] ) {
|
||||
if( ASKFOR(dh[ii]->dph_dirbcb) ) {
|
||||
jj = GETSHARED(di[ii]->d_ndirbs);
|
||||
dh[ii]->dph_dirbcb = dh[jj]->dph_dirbcb;
|
||||
}
|
||||
if( ASKFOR(dh[ii]->dph_datbcb) ) {
|
||||
jj = GETSHARED(di[ii]->d_ndatbs);
|
||||
dh[ii]->dph_datbcb = dh[jj]->dph_datbcb;
|
||||
}
|
||||
} /* end resolve shared buffers */
|
||||
|
||||
return doffset;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* EXPORT
|
||||
/* fixupxios_info: does the fixup for the dph info in the xios
|
||||
/*************************************************************************/
|
||||
fixupxios_info() /* call from fixups */
|
||||
{
|
||||
REG WORD ii; /* counter */
|
||||
REG LONG dmagic; /* addr var */
|
||||
|
||||
for( ii=0; ii<DPHNUM; ++ii )
|
||||
if( dh[ii] ) /* if there's something to look at */
|
||||
if( di[ii]->d_modified ) {
|
||||
dmagic = fldstart + dphtab[ii];
|
||||
lseek(fns,dmagic,0); /* where to write to */
|
||||
write(fns,dh[ii],sizeof(DPH)); /* what to write */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,418 @@
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/* genc5.c: M E N U handling routines
|
||||
/*
|
||||
/* Written by Bill Fitler
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifndef MAINMODULE
|
||||
#include <genccpm.h>
|
||||
EXTERN BOOLEAN verbose; /* flag: be wordy */
|
||||
#endif
|
||||
|
||||
MLOCAL BOOLEAN eflag = FALSE; /* user error */
|
||||
|
||||
/**************************************************************************/
|
||||
/* bldmenu: builds a menu list from successive calls
|
||||
/**************************************************************************/
|
||||
MENU *
|
||||
bldmenu(muroot,typ,ptr,name,description)
|
||||
MENU *muroot; /* root of menu list (or NULLPTR) */
|
||||
WORD typ; /* type of menu item */
|
||||
BYTE *ptr; /* pointer to something... */
|
||||
BYTE *name; /* command name for this menu item */
|
||||
BYTE *description; /* long label for this item */
|
||||
{
|
||||
REG MENU *mu; /* ptr to created item */
|
||||
REG MENU *tmu; /* temp ptr for linked list scan */
|
||||
|
||||
mu = (MENU *)malloc(sizeof(*mu)); /* allocate memory for item */
|
||||
mu->mutype = typ;
|
||||
mu->muiptr = ptr;
|
||||
mu->muname = name;
|
||||
mu->mudesc = description;
|
||||
mu->munext = NULLPTR;
|
||||
if( muroot == NULLPTR ) /* if NULL list */
|
||||
return mu; /* return something to start with */
|
||||
for( tmu=muroot; tmu->munext != NULLPTR; tmu = tmu->munext )
|
||||
; /* append to end of list */
|
||||
tmu->munext = mu;
|
||||
return muroot; /* keep list in order */
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* domenu: executes the specified commands (in cbuf) from the menu (mnu)
|
||||
/**************************************************************************/
|
||||
#define CMDLEN 80
|
||||
#define USERR ++eflag;printf
|
||||
#define ECHK(fn) _errchk(fn,cmd,cmdval)
|
||||
|
||||
VOID
|
||||
domenu(cbuf,mnu)
|
||||
BYTE *cbuf; /* command buffer */
|
||||
MENU *mnu; /* table of menu specs */
|
||||
{
|
||||
REG MENU *mi; /* ptr to menu item */
|
||||
LOCAL BYTE cmd[CMDLEN]; /* place for command & value */
|
||||
LOCAL BYTE *cmdval; /* ptr within cmd */
|
||||
LOCAL BYTE *cp; /* temp char ptr */
|
||||
BYTE *msetbool(); /* set a boolean value */
|
||||
BYTE *msetbyte(); /* set a numeric byte value */
|
||||
BYTE *msetword(); /* set an integer pointer */
|
||||
BYTE *msettxt(); /* set a text value */
|
||||
BYTE *(*proc)(); /* procedure pointer */
|
||||
BYTE *msetdrv(); /* set a drive value */
|
||||
BYTE *_nxtcmd(); /* command parser */
|
||||
MENU *_fndcmd(); /* command lookup */
|
||||
|
||||
eflag = FALSE; /* no errors yet */
|
||||
while((cbuf=_nxtcmd(cbuf,cmd))){ /* while there are commands in cbuf */
|
||||
cmdval = NULLPTR; /* init value ptr for command */
|
||||
for( cp=cmd; *cp; cp++ ) { /* scan command for assign op */
|
||||
if( isupper(*cp) ) /* convert all commands to LOWER CASE */
|
||||
*cp = tolower(*cp);
|
||||
if( *cp == '=' ) { /* found? */
|
||||
*cp++ = NULL; /* terminate command */
|
||||
cmdval = cp; /* point value to after assign op */
|
||||
break; /* and terminate loop */
|
||||
}
|
||||
}
|
||||
if( (mi=_fndcmd(cmd,mnu)) == NULLPTR ){ /* scan menu commands */
|
||||
USERR("'%s' is not a command for this menu\n",cmd);
|
||||
} else { /******** cmd loop ********/
|
||||
switch(mi->mutype) { /* handle cmd type */
|
||||
case MBOOL: /** BOOLEAN command **/
|
||||
ECHK(msetbool(mi->muiptr,cmdval));
|
||||
break;
|
||||
case MBYTE: /** BYTE command **/
|
||||
ECHK(msetbyte(mi->muiptr,cmdval));
|
||||
break;
|
||||
case MWORD: /** INTEGER command **/
|
||||
ECHK(msetword(mi->muiptr,cmdval));
|
||||
break;
|
||||
case MTEXT: /** TEXT command **/
|
||||
ECHK(msettxt(mi->muiptr,cmdval));
|
||||
break;
|
||||
case MPROC: /** PROCEDURAL command **/
|
||||
proc = mi->muiptr; /* assign to function ptr */
|
||||
ECHK(((*proc)(cmdval,mi->mudesc)));
|
||||
break;
|
||||
case MDRIV: /** DRIVE letter command **/
|
||||
ECHK(msetdrv(mi->muiptr,cmdval));
|
||||
break;
|
||||
} /* end switch */
|
||||
} /********* end cmd loop *********/
|
||||
if(eflag) { /* user error? */
|
||||
press_return();
|
||||
*cbuf = NULL;
|
||||
} else if(verbose) /* are we being wordy? */
|
||||
prtmival(mi); /* let the user know what happened */
|
||||
} /**** end while loop ****/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _nxtcmd: parses cin into cout */
|
||||
BYTE *
|
||||
_nxtcmd(cin,cout) /* returns ptr to after next cmd */
|
||||
BYTE *cin; /* command in buf */
|
||||
BYTE *cout; /* command out buf */
|
||||
{
|
||||
/***** handle quoted strings??? *****/
|
||||
while( isspace(*cin) ) /* skip leading spaces */
|
||||
++cin;
|
||||
if( *cin == NULL ) /* check for EOS */
|
||||
return NULLPTR;
|
||||
while( *cin && !isspace(*cin) ) /* scan to eos or whitespace */
|
||||
*cout++ = *cin++; /* xfer to command out buf */
|
||||
*cout = NULL; /* null terminate command out buf */
|
||||
return cin; /* return ptr to after command */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _fndcmd: scans thru menu structure 'mu' looking for command name 'cn' */
|
||||
/* returns ptr to menu item or NULLPTR */
|
||||
MENU *
|
||||
_fndcmd(cn,mus)
|
||||
BYTE *cn; /* command name */
|
||||
MENU *mus; /* ptr to menu list */
|
||||
{
|
||||
REG WORD cnl; /* cmd name len */
|
||||
MENU *musave; /* extra ptr to menu item */
|
||||
|
||||
cnl = strlen(cn);
|
||||
for( ; ; mus = mus->munext) { /* scan menu list */
|
||||
if( mus==NULLPTR ) /* if we hit the end then fail */
|
||||
return NULLPTR;
|
||||
if( strncmp(cn,mus->muname,cnl) == 0 ) /* cn prefix of name?*/
|
||||
break; /* yes, we have a candidate */
|
||||
}
|
||||
musave = mus;
|
||||
for( mus=mus->munext; ; mus=mus->munext ) { /* finish scanning list */
|
||||
if( mus==NULLPTR ) /* if we hit the end then succeed */
|
||||
return musave; /* we reached end of list: found it! */
|
||||
if( strncmp(cn,mus->muname,cnl) == 0 )
|
||||
return NULLPTR; /* another match: ambiguous command */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _errchk: checks for error returns on functions */
|
||||
VOID
|
||||
_errchk(emsg,cm,cmv)
|
||||
BYTE *emsg; /* error message to check */
|
||||
BYTE *cm; /* command generating the error */
|
||||
BYTE *cmv; /* value generating the error */
|
||||
{
|
||||
if( emsg ) { /* non NULL error message return? */
|
||||
USERR("Error on command '%s",cm);
|
||||
if(cmv)
|
||||
USERR("=%s",cmv);
|
||||
USERR("': %s\n",emsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* msetbool: sets the BOOLEAN pointed to by 'bp' according to value in 'cvp' */
|
||||
BYTE * /* return NULLPTR, or ptr to err msg */
|
||||
msetbool(bp,cvp)
|
||||
BYTE *bp; /* pointer to boolean to set */
|
||||
BYTE *cvp; /* pointer to value to set to */
|
||||
{
|
||||
REG WORD bv;
|
||||
REG BYTE *tp;
|
||||
|
||||
if( cvp==NULLPTR ) /* no val: toggle boolean */
|
||||
bv = (*bp ? 4 : 1); /* toggle by setting bv index */
|
||||
else {
|
||||
for( tp=cvp; *tp; ++tp )
|
||||
if( isupper(*tp) ) *tp=tolower(*tp);
|
||||
if( (bv=whichof(cvp,",on,yes,true,off,no,false"))==0 )
|
||||
return "value must be 'yes' or 'no'";
|
||||
}
|
||||
if( bv < 4 )
|
||||
*bp = -1; /* zap to 0xFFFF */
|
||||
else *bp = 0; /* zap to zero */
|
||||
return NULLPTR;
|
||||
}
|
||||
|
||||
|
||||
BYTE *
|
||||
msetbyte(bp,cvp) /* set numeric BYTE value */
|
||||
BYTE *bp; /* ptr to BYTE to set */
|
||||
BYTE *cvp; /* value to set BYTE to */
|
||||
{
|
||||
REG WORD val; /* temp holding place */
|
||||
|
||||
val=0;
|
||||
if(cvp != NULLPTR) val=atoih(cvp); /* assume numbers are in HEX!! */
|
||||
if( cvp==NULLPTR || (val==0 && !isdigit(*cvp)) )
|
||||
return "value must be a number";
|
||||
if( val > 255 )
|
||||
return "value must be less than FF hex (255 decimal)";
|
||||
*bp = val;
|
||||
return NULLPTR;
|
||||
}
|
||||
|
||||
|
||||
BYTE *
|
||||
msetword(ip,cvp)
|
||||
WORD *ip; /* ptr to WORD to set */
|
||||
BYTE *cvp; /* value to set WORD to */
|
||||
{
|
||||
REG WORD val; /* temp holding place */
|
||||
|
||||
val=0;
|
||||
if(cvp != NULLPTR) val=atoih(cvp); /* assume numbers are in HEX!! */
|
||||
if( cvp==NULLPTR || (val==0 && !isdigit(*cvp)) )
|
||||
return "value must be an unsigned hex number between 0 and FFFFh";
|
||||
*ip = val;
|
||||
return NULLPTR;
|
||||
}
|
||||
|
||||
|
||||
WORD
|
||||
atoih(cp) /* conver ascii hex to word */
|
||||
BYTE *cp; /* buffer number */
|
||||
{
|
||||
REG WORD v; /* resulting value */
|
||||
REG BYTE cv; /* character value */
|
||||
BYTE *savcp; /* save orig ptr */
|
||||
|
||||
v = 0; savcp = cp; /* init value */
|
||||
for( cv = *cp; ; cv = *++cp ){ /* for each char in cp */
|
||||
if( isdigit(cv) )
|
||||
v = (v<<4) + (cv-'0'); /* convert digit and add */
|
||||
else { /* maybe it's a letter */
|
||||
if( isupper(cv) ) /* upper case letter? */
|
||||
cv = tolower(cv); /* convert it */
|
||||
if( cv<'a' || cv>'f') /* range check */
|
||||
break; /* terminate loop if failed */
|
||||
v = (v<<4)+(10+cv-'a'); /* convert letter and add */
|
||||
}
|
||||
}
|
||||
if( cp-savcp <= 4 )
|
||||
return v; /* return the value */
|
||||
else {
|
||||
*savcp |= 0x80;
|
||||
return 0; /* turn on hi bit, make isdigit test fail */
|
||||
}
|
||||
}
|
||||
|
||||
BYTE *
|
||||
msettxt(tp,cvp)
|
||||
BYTE **tp; /* place to store ptr to value */
|
||||
BYTE *cvp; /* value to set BYTEs to */
|
||||
{
|
||||
REG BYTE *tmp; /* temp ptr for allocated storage */
|
||||
|
||||
if( cvp==NULLPTR )
|
||||
cvp=""; /* point to null string, instead */
|
||||
tmp = malloc(1+strlen(cvp)); /* get space for string */
|
||||
strcpy(tmp,cvp); /* copy to allocated space */
|
||||
*tp = tmp; /* assign ptr */
|
||||
return NULLPTR;
|
||||
}
|
||||
|
||||
BYTE *
|
||||
msetdrv(dp,cvp)
|
||||
BYTE *dp; /* place to store ptr to value */
|
||||
BYTE *cvp; /* value to set DRIVE to */
|
||||
{
|
||||
REG WORD v; /* work place */
|
||||
|
||||
if( cvp!=NULLPTR ) { /* check for drive letter */
|
||||
if( isupper(*cvp) )
|
||||
*cvp = tolower(*cvp);
|
||||
v = *cvp - 'a'; /* convert drive spec to nibble */
|
||||
}
|
||||
if( cvp==NULLPTR || v<0 || v>15 || cvp[1] != ':' )
|
||||
return "you must specify a drive 'A:' thru 'P:'";
|
||||
*dp = v; /* looks okay, set it */
|
||||
return NULLPTR; /* no errors */
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* prtmenu: displays the menu labels, values and descriptors
|
||||
/**************************************************************************/
|
||||
VOID
|
||||
prtmenu(mtitle,mnu)
|
||||
BYTE *mtitle; /* title of menu */
|
||||
MENU *mnu; /* table specifying menu */
|
||||
{
|
||||
printf("\n\n%s\n",mtitle); /* give the menu a title */
|
||||
for( ; mnu!=NULLPTR; mnu = mnu->munext ) /* travel down list */
|
||||
prtmival(mnu);
|
||||
}
|
||||
|
||||
|
||||
prtmival(mnu) /* return ptr to value of item */
|
||||
MENU *mnu; /* item to get value of */
|
||||
{
|
||||
REG BYTE *ival;
|
||||
BYTE ivbuf[10]; /* local buf for display */
|
||||
BYTE *vbp; /* value byte ptr */
|
||||
WORD *vwp; /* value word ptr */
|
||||
WORD v; /* place to put value */
|
||||
|
||||
printf("%12.12s ",mnu->muname); /* first the name */
|
||||
ival = ivbuf; *ival = NULL; /* init value */
|
||||
switch(mnu->mutype) { /* now the value */
|
||||
case MBOOL:
|
||||
if( *(mnu->muiptr) )
|
||||
ival="[Y]";
|
||||
else ival="[N]";
|
||||
break;
|
||||
case MBYTE:
|
||||
vbp = mnu->muiptr;
|
||||
v = (*vbp & 0xFF);
|
||||
sprintf(ivbuf,"[%2.2x]",v); /* display in hex */
|
||||
break;
|
||||
case MWORD:
|
||||
vwp = mnu->muiptr;
|
||||
v = *vwp;
|
||||
sprintf(ivbuf,"[%4.4x]",v); /* display in hex */
|
||||
break;
|
||||
case MTEXT:
|
||||
vbp = *((BYTE **)mnu->muiptr); /* go get the char ptr */
|
||||
if( strlen(vbp) > 4 )
|
||||
sprintf(ivbuf,"[%-4.4s>",vbp);
|
||||
else sprintf(ivbuf,"[%s]",vbp);
|
||||
break;
|
||||
case MPROC:
|
||||
/* leave blank */
|
||||
break;
|
||||
case MDRIV:
|
||||
sprintf(ivbuf,"[%c:]",'A'+(*mnu->muiptr));
|
||||
break;
|
||||
}
|
||||
printf("%-6s ",ival);
|
||||
printf("%s\n",mnu->mudesc); /* finally the description */
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
/* whichof: scans the string 'set' (delimited by 1st char in 'set')
|
||||
/* for 1st occurrence of string 'sample'.
|
||||
/* Returns 0 if 'sample' not a prefix of any item in set or if
|
||||
/* 'sample' is a prefix of more than one item in set;
|
||||
/* delimiter# o.w.
|
||||
/* E.G. if set = ",on,yes,true,off,no,false" then
|
||||
/* whichof("yes",set) == 2;
|
||||
/* whichof("y",set) == 2;
|
||||
/* whichof("o",set) == 0;
|
||||
/* whichof("x",set) == 0;
|
||||
/* NOTE: results not guaranteed if item delimiter (*set) is in string 'sample',
|
||||
/* or if null item is in set (adjacent delimiters).
|
||||
/*************************************************************************/
|
||||
|
||||
/* first, a subroutine: */
|
||||
/* _wget: returns NULLPTR if sa not prefix of item in st; */
|
||||
/* returns end of item (ptr in st) otherwise */
|
||||
BYTE *_wget(sa,st,de)
|
||||
BYTE *sa;
|
||||
BYTE *st;
|
||||
BYTE de;
|
||||
{
|
||||
BYTE *s2;
|
||||
|
||||
for( ;; ) { /* do forever */
|
||||
for( s2=sa; *s2 && *s2 == *st; ){
|
||||
++s2; ++st; /* try match */
|
||||
}
|
||||
if( *s2 == NULL ){ /* success! we've matched all of sa */
|
||||
while( *st && *st != de ) ++st; /* adv to nxt delim */
|
||||
return( --st ); /* backup one char */
|
||||
}
|
||||
while( *st && *st != de ) /* no match, look for next item */
|
||||
++st; /* adv to nxt delim */
|
||||
if( *st == NULL )
|
||||
return( NULLPTR ); /* end of list */
|
||||
++st;
|
||||
}
|
||||
}
|
||||
|
||||
WORD whichof(sample,set)
|
||||
BYTE *sample;
|
||||
BYTE *set;
|
||||
{
|
||||
WORD sx;
|
||||
BYTE *sp, *np;
|
||||
|
||||
if( (sp=_wget(sample,set+1,*set)) == NULLPTR )
|
||||
return 0; /* not found */
|
||||
if( _wget(sample,sp+1,*set) != NULLPTR )
|
||||
return 0; /* ambiguous */
|
||||
for( sx=0, np=set; np<sp; np++ )
|
||||
if( *np == *set ) sx++; /* count delimiters */
|
||||
return sx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
/*******************************************************************/
|
||||
/*******************************************************************/
|
||||
/* genc5.c: */
|
||||
/* some miscellaneous functions which belong in the system library */
|
||||
/*******************************************************************/
|
||||
/*******************************************************************/
|
||||
#ifndef MAINMODULE
|
||||
#include <genccpm.h>
|
||||
#endif
|
||||
|
||||
#define FCB struct fcbstruct
|
||||
FCB {
|
||||
BYTE fcbdr; /* drive */
|
||||
BYTE fcbname[8]; /* name */
|
||||
BYTE fcbext[3]; /* extension */
|
||||
BYTE fcbrest[24]; /* all the rest */
|
||||
};
|
||||
|
||||
|
||||
#define FSEARCH(faddr) (__OSIF(17,faddr)&0xFF)
|
||||
#define NSEARCH(faddr) (__OSIF(18)&0xFF) /* doesn't use FCB */
|
||||
#define SETDMA(dma) __OSIF(26,dma) /* where to put dir info */
|
||||
#define SECSIZE 128
|
||||
#define AMASK 0x7F
|
||||
|
||||
/* dirsearch: returns a DLIST of names matching 'fs' */
|
||||
DLIST * /* returns list of names found in */
|
||||
dirsearch(fs) /* directory search for */
|
||||
BYTE *fs; /* file spec */
|
||||
{
|
||||
FCB f, *fp; /* use this FCB */
|
||||
REG WORD ret; /* ptr */
|
||||
DLIST *_newdli(), *ls; /* list */
|
||||
BYTE dmabuf[SECSIZE]; /* place for directory info */
|
||||
|
||||
fp = &f; /* everything else uses address */
|
||||
parsefn(fs,fp); /* fill fcb with filespec */
|
||||
SETDMA(dmabuf); /* tell em where to put it */
|
||||
if( (ret=FSEARCH(fp)) > 3 ) /* look for first occurrence */
|
||||
return NULLPTR; /* no luck */
|
||||
ls=_newdli(dmabuf+(ret<<5),NULLPTR); /* start off a list */
|
||||
while( (ret=NSEARCH(fp)) <= 3 ) { /* do all the search_nexts */
|
||||
ls = _newdli(dmabuf+(ret<<5),ls); /* link them together */
|
||||
}
|
||||
return ls;
|
||||
}
|
||||
|
||||
|
||||
DLIST *
|
||||
_newdli(f,lnk)
|
||||
FCB *f;
|
||||
DLIST *lnk;
|
||||
{
|
||||
REG WORD i;
|
||||
BYTE *np, nb[15]; /* name buffer */
|
||||
DLIST *newl; /* new list item */
|
||||
|
||||
/* make a pretty filename */
|
||||
np = nb;
|
||||
for( i=0; i<11; ++i ) /* zap out any high bits in filename */
|
||||
f->fcbname[i] &= AMASK; /* mask off attribute bits */
|
||||
for( i=0; i<8; ++i ) { /* handle name spec */
|
||||
if( f->fcbname[i] == ' ' ) /* end of name? */
|
||||
break; /* okay */
|
||||
*np++ = f->fcbname[i]; /* o.w. stuff into name buffer */
|
||||
}
|
||||
*np++ = '.'; /* tack this on */
|
||||
for( i=0; i<3; ++i ){ /* handle ext spec */
|
||||
if( f->fcbext[i] == ' ' ) /* end of ext? */
|
||||
break;
|
||||
*np++ = f->fcbext[i];
|
||||
}
|
||||
*np++ = NULL; /* null terminate string */
|
||||
/*************************************************************/
|
||||
|
||||
np = malloc(np-nb); /* save it away */
|
||||
strcpy(np,nb); /* do the copy */
|
||||
newl = (DLIST *)malloc(sizeof(*newl)); /* get ptr area set up */
|
||||
newl->dlname = np;
|
||||
newl->dlnext = lnk;
|
||||
return newl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
parsefn(fs,f)
|
||||
BYTE *fs; /* file spec */
|
||||
FCB *f; /* fcb */
|
||||
{
|
||||
REG WORD i;
|
||||
REG BYTE *cp;
|
||||
|
||||
for( cp=fs; *cp; cp++ ) /* make everything upper case */
|
||||
if( islower(*cp) )
|
||||
*cp = toupper(*cp);
|
||||
for( i=0; i<24; ++i ) /* init fcb */
|
||||
f->fcbrest[i] = 0;
|
||||
if( *(fs+1) == ':' ) { /* drive spec? */
|
||||
f->fcbdr = 1 + *fs - 'A'; /* 0=default, 1 = A:,... */
|
||||
fs += 2; /* skip dr spec */
|
||||
} else f->fcbdr = 0; /* default drive */
|
||||
for( i=0; *fs && *fs != '.' && i<8; fs++, ++i ) { /* NAME. */
|
||||
if( *fs == '*' ) { /* wildcard? */
|
||||
for( ; i<8; ++i ) /* fill up rest of name */
|
||||
f->fcbname[i]='?'; /* with search spec */
|
||||
for( ; *fs && *fs!='.'; fs++ ) /* ignore to end or '.' */
|
||||
;
|
||||
break; /* terminate loop */
|
||||
}
|
||||
f->fcbname[i] = *fs;
|
||||
}
|
||||
for( ; i<8; ++i ) /* fill up rest of name */
|
||||
f->fcbname[i] = ' '; /* with blanks */
|
||||
for( ; *fs; fs++ ) /* skip rest of name */
|
||||
if( *fs == '.' ) { /* end of name? */
|
||||
fs++; break; /* yes, so exit this loop */
|
||||
}
|
||||
for( i=0; *fs && i<3; fs++,++i ) { /* .EXT */
|
||||
if( *fs == '*' ){ /* wildcard */
|
||||
for( ; i<3; ++i )
|
||||
f->fcbext[i] = '?';
|
||||
break;
|
||||
}
|
||||
f->fcbext[i] = *fs;
|
||||
}
|
||||
for( ; i<3; ++i ) /* fill up rest of ext */
|
||||
f->fcbext[i] = ' '; /* with blanks */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* access: tests for existence: return NULL if exist, -1 o.w. */
|
||||
WORD
|
||||
access(fn)
|
||||
BYTE *fn;
|
||||
{
|
||||
FCB f; /* use this FCB */
|
||||
BYTE dmabuf[SECSIZE]; /* place for directory info */
|
||||
|
||||
parsefn(fn,&f); /* fill fcb with filespec */
|
||||
SETDMA(dmabuf); /* tell em where to put it */
|
||||
if( FSEARCH(&f) > 3 ) /* look for first occurrence */
|
||||
return -1; /* no luck */
|
||||
return 0;
|
||||
}
|
||||
|
||||
BYTE *
|
||||
gets(s)
|
||||
BYTE *s;
|
||||
{
|
||||
BYTE *sav;
|
||||
|
||||
if( fgets(s,32767,stdin) == NULLPTR )
|
||||
return NULLPTR;
|
||||
if( !isatty(0) ) /* reading from CON:? */
|
||||
fputs(s,stdout); /* echo if not */
|
||||
for( sav=s; *s && *s != '\n'; ++s )
|
||||
;
|
||||
*s = '\0';
|
||||
return sav;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
BYTE
|
||||
getdrive()
|
||||
{
|
||||
return __OSIF(25,0);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* press_return: let user look at screen */
|
||||
press_return()
|
||||
{
|
||||
BYTE bitbucket[40]; /* leave room */
|
||||
|
||||
if( !isatty(0) ) { /* stdin from CON:? */
|
||||
printf("Error in command file: terminating program\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("\07Press RETURN to continue ");
|
||||
if( gets(bitbucket)!=bitbucket )
|
||||
exit(1); /* eof, quit now */
|
||||
}
|
||||
|
||||
/* patch: provides a patch area */
|
||||
patch() /* should never get called */
|
||||
{
|
||||
int i;
|
||||
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
|
||||
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
|
||||
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
|
||||
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
|
||||
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
|
||||
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
|
||||
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
|
||||
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
|
||||
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
|
||||
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************/
|
||||
/*******************************************************************/
|
||||
/* T H E E N D
|
||||
/*******************************************************************/
|
||||
/*******************************************************************/
|
||||
|
||||
@@ -0,0 +1,507 @@
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/* genccpm.h - the include module(s) for genccpm.c
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/***** include files *****/
|
||||
#include <portab.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <cpm.h>
|
||||
/*************************/
|
||||
|
||||
/* New types for GENCCPM: */
|
||||
#define ADDR UWORD /* offset in system image */
|
||||
#define SEG UWORD /* segment in system image */
|
||||
#define FPTR LONG /* pointer into file */
|
||||
|
||||
/*******************************************/
|
||||
/* compiler differences */
|
||||
/* configured for Digital Research's C */
|
||||
#define BROPEN(fn) openb(fn,0) /* binary open for read */
|
||||
#define BWCREAT(fn) creatb(fn,1) /* binary creat for write */
|
||||
LONG lseek();
|
||||
BYTE *malloc();
|
||||
BYTE *gets();
|
||||
#define NULLPTRI 0 /* NULLPTR initializer */
|
||||
|
||||
/* compile time options: assume the "-dXXX" flag is used, where XXX is: */
|
||||
|
||||
/* #define CCPM /* this is a CCP/M EDSYS */
|
||||
#define CMPM /* this is an CMP/M EDSYS */
|
||||
|
||||
/**************************************************************************/
|
||||
#ifndef CCPM
|
||||
#ifndef CMPM
|
||||
ERROR: you must specify one of 'CMPM' or 'CCPM'
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CCPM
|
||||
#ifdef CMPM
|
||||
ERROR: these compile options are mutually exclusive: only 1 allowed!
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/* menu.h : include with progs using menu rtns
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define MENU struct menuitem
|
||||
MENU {
|
||||
WORD mutype; /* type of menu item */
|
||||
BYTE *muiptr; /* ptr to information for menu item */
|
||||
BYTE *muname; /* name of menu item */
|
||||
BYTE *mudesc; /* description of menu item */
|
||||
MENU *munext; /* ptr to next menu item */
|
||||
};
|
||||
|
||||
#define MBOOL 1
|
||||
#define MBYTE 2
|
||||
#define MWORD 3
|
||||
#define MTEXT 4
|
||||
#define MPROC 5
|
||||
#define MDRIV 6
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/* cpm.h - support for cpm types of calls
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#define SECSIZ 128
|
||||
#define BUFSIZ 512 /* should be in stdio.h */
|
||||
|
||||
/**************************************************************************/
|
||||
/* directory search support */
|
||||
#define DLIST struct dliststr /* directory list structure */
|
||||
DLIST {
|
||||
BYTE *dlname; /* file name */
|
||||
DLIST *dlnext; /* next item in list */
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
/* .CMD header record Group structure */
|
||||
#define GROUP struct cmdgrp
|
||||
GROUP { /* what a Cmd Hdr group looks like */
|
||||
BYTE gtype; /* type of group (see below) */
|
||||
UWORD glen; /* length in paragraphs of group */
|
||||
UWORD gabase; /* pgph addr for non-relocatable grp */
|
||||
UWORD gmin; /* min pgphs to alloc to group */
|
||||
UWORD gmax; /* max pgphs to alloc to group */
|
||||
};
|
||||
#define GTYPCODE 1 /* Code Group */
|
||||
#define GTYPDATA 2 /* Data Group */
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/* mpm.h - data structures peculiar to MP/M & Concurrent
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#define MINKMEM 80 /* minimum memory allocation in paragraphs */
|
||||
|
||||
#define XIOSTAB struct xios_table
|
||||
XIOSTAB {
|
||||
UBYTE xt_tick;
|
||||
UBYTE xt_ticks_sec;
|
||||
UBYTE xt_door;
|
||||
UBYTE xt_rsvd;
|
||||
UBYTE xt_xpcns; /* # physical consoles; FMB */
|
||||
UBYTE xt_nvcns;
|
||||
UBYTE xt_nccbs;
|
||||
UBYTE xt_nlcbs;
|
||||
UWORD xt_ccb;
|
||||
UWORD xt_lcb;
|
||||
UWORD xt_dphtab[16];
|
||||
UWORD xt_alloc;
|
||||
};
|
||||
#define XTABLEN (sizeof(XIOSTAB))
|
||||
#define XTABLOC (0X0c0cL)
|
||||
#define XTABALLOC (0X0c38L)
|
||||
|
||||
#define MD struct mem_descriptor
|
||||
MD {
|
||||
UWORD md_link;
|
||||
UWORD md_start;
|
||||
UWORD md_length;
|
||||
UWORD md_plist;
|
||||
UWORD md_unused;
|
||||
};
|
||||
|
||||
#define PD struct proc_descriptor
|
||||
PD {
|
||||
UWORD pd_link;
|
||||
UWORD pd_thread;
|
||||
UBYTE pd_stat;
|
||||
UBYTE pd_prior;
|
||||
UWORD pd_flag;
|
||||
BYTE pd_name[8];
|
||||
UWORD pd_uda;
|
||||
UBYTE pd_dsk;
|
||||
UBYTE pd_user;
|
||||
UBYTE pd_ldsk;
|
||||
UBYTE pd_luser;
|
||||
UWORD pd_mem;
|
||||
BYTE pd_restofit[24];
|
||||
};
|
||||
|
||||
#define LOCK struct lock_item
|
||||
LOCK {
|
||||
UWORD lo_link;
|
||||
UWORD lo_restofit[4];
|
||||
};
|
||||
|
||||
#define UDA struct uda_item
|
||||
UDA {
|
||||
BYTE ud_1space[0x50];
|
||||
UWORD ud_csinit;
|
||||
UWORD ud_dsinit;
|
||||
UWORD ud_esinit;
|
||||
UWORD ud_ssinit;
|
||||
BYTE ud_2space[0xA8]; /* uda is 0x100 bytes long */
|
||||
};
|
||||
|
||||
#define QCB struct qcb_descriptor
|
||||
QCB {
|
||||
UWORD qc_link;
|
||||
BYTE qc_restofit[26];
|
||||
};
|
||||
|
||||
#define FLAG struct flag_item
|
||||
FLAG {
|
||||
UBYTE fl_status;
|
||||
UWORD fl_pd;
|
||||
};
|
||||
|
||||
#define CCB struct ccb_item
|
||||
CCB {
|
||||
UWORD cc_attach;
|
||||
UWORD cc_queue;
|
||||
UBYTE cc_flag;
|
||||
UBYTE cc_startcol;
|
||||
UBYTE cc_column;
|
||||
UBYTE cc_nchar;
|
||||
UBYTE cc_mimic;
|
||||
UBYTE cc_msource;
|
||||
UBYTE cc_type;
|
||||
UBYTE cc_xdev;
|
||||
};
|
||||
|
||||
#define SATITEM struct sat_item
|
||||
SATITEM {
|
||||
UWORD sa_start;
|
||||
UWORD sa_length;
|
||||
UBYTE sa_nall;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/* here's the body of edsys.h
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef CCPM
|
||||
#define PROGNAME "GENCCPM"
|
||||
#define VERLABEL "Concurrent CP/M-86 2.1"
|
||||
#define VERSION 0x1421
|
||||
#else
|
||||
#define PROGNAME "GENCCPM"
|
||||
#define VERLABEL "Concurrent CP/M-86 3.1"
|
||||
#define VERSION 0x1431
|
||||
#endif
|
||||
#define SYSFILE "CCPM.SYS"
|
||||
#define NEWSYS "CCPM.$Y$"
|
||||
#define OLDSYS "CCPM.OLD"
|
||||
#define MODEXT ".CON"
|
||||
#define SUPMOD "SUP.CON"
|
||||
#define RTMMOD "RTM.CON"
|
||||
#define MEMMOD "MEM.CON"
|
||||
#define CIOMOD "CIO.CON"
|
||||
#define BDOSMOD "BDOS.CON"
|
||||
#define NETMOD "NET86.CON"
|
||||
#define SYSMOD "SYSDAT.CON"
|
||||
#define XIOSMOD "XIOS.CON"
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
#define USERR printf /* how to handle user errors */
|
||||
#define CRASH(fn) {fprintf(stderr,fn);exit(1);}
|
||||
#define FCHECK(sp) /* disable */
|
||||
/* if(ferror(sp)){printf("Error on output: out of space?");exit(1);} */
|
||||
#define DBGPRT printf
|
||||
#define CMDSLEN 80
|
||||
#define PROMPT "Changes? "
|
||||
|
||||
|
||||
/* memory list definition */
|
||||
#define MLIST struct memorylist
|
||||
MLIST {
|
||||
UWORD mlfirst; /* addr of 1st pgph */
|
||||
UWORD mllast; /* addr of last pgph */
|
||||
UWORD mlsize; /* partition size in K bytes */
|
||||
MLIST *mlnext; /* ptr to next item in list */
|
||||
};
|
||||
|
||||
/* ENTRY point structure decls */
|
||||
#define ENTRY struct entrypoint
|
||||
ENTRY {
|
||||
UWORD ep_eoff; /* entry offset */
|
||||
UWORD ep_eseg; /* entry segment */
|
||||
UWORD ep_ioff; /* init offset */
|
||||
UWORD ep_iseg; /* init segment */
|
||||
};
|
||||
|
||||
/* FIXup structure decls */
|
||||
#define FIX struct fixitem
|
||||
FIX {
|
||||
LONG f_addr; /* offset in file */
|
||||
WORD f_type; /* either F_ADD or F_PUT */
|
||||
WORD *f_ptr; /* ptr to value to add or put */
|
||||
FIX *f_next; /* next fixup item */
|
||||
};
|
||||
#define F_ADD 1 /* add value of value to word in file*/
|
||||
#define F_PUT 2 /* put value ... */
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* Program Globals:
|
||||
/* Keep all the globals defined in one file, for ease of access
|
||||
/* Definitions first, then declarations
|
||||
/**************************************************************************/
|
||||
|
||||
/******** definitions for the MAINMODULE **********/
|
||||
#ifdef MAINMODULE
|
||||
|
||||
/**************************************************************************/
|
||||
/* Edsys Program Globals
|
||||
/**************************************************************************/
|
||||
GLOBAL BYTE *copyright = "Copyright (C) 1983, Digital Research";
|
||||
GLOBAL BYTE *version = VERLABEL;
|
||||
GLOBAL BYTE *clearit; /* Home cursor & erase screen */
|
||||
GLOBAL BOOLEAN verbose=TRUE; /* flag to tell EDSYS to be wordy */
|
||||
GLOBAL BOOLEAN doit=FALSE; /* flag: tell EDSYS to do the rest of it */
|
||||
GLOBAL WORD fns = -1; /* File descriptor for New System file */
|
||||
GLOBAL BOOLEAN dogensys = FALSE; /* Gen System from scratch? */
|
||||
GLOBAL BOOLEAN doclean = FALSE; /* Clean SYSFILE first from destination drive? */
|
||||
GLOBAL BOOLEAN donew_xios = FALSE; /* edit in a NEW XIOS? */
|
||||
GLOBAL BOOLEAN pure_xios = FALSE; /* XIOS groups are pure (separate) code & data? */
|
||||
GLOBAL BYTE destdrv; /* where the SYSFILE goes */
|
||||
|
||||
/**************************************************************************/
|
||||
/* Sysfile Globals
|
||||
/**************************************************************************/
|
||||
GLOBAL WORD totmds; /* total number of memory descriptors */
|
||||
GLOBAL WORD totpds; /* total number of process descriptors */
|
||||
GLOBAL WORD xtrapds; /* number of pds wanted by user */
|
||||
GLOBAL WORD totqcbs; /* tot num q control blocks */
|
||||
GLOBAL UWORD qbuflen; /* length in bytes of q buf area */
|
||||
GLOBAL WORD totopen; /* total open files and locked records */
|
||||
|
||||
GLOBAL DLIST *rsps=NULLPTRI; /* list of RSP file names */
|
||||
GLOBAL DLIST *syslbls=NULLPTRI; /* lines of OS label */
|
||||
GLOBAL MLIST *memroot=NULLPTRI; /* memory partitions */
|
||||
GLOBAL XIOSTAB xt; /* xios info table */
|
||||
|
||||
#define SDLEN 0x210
|
||||
GLOBAL BYTE sdat_area[SDLEN]; /* where to store the SYSDAT info */
|
||||
GLOBAL BYTE cmdhdr[SECSIZ]; /* command header for NEWSYS */
|
||||
|
||||
/* module length information: lengths are in paragraphs */
|
||||
GLOBAL UWORD clsup; /* code length: supervisor */
|
||||
GLOBAL UWORD clos_label; /* code length: OS label */
|
||||
GLOBAL UWORD clrtm; /* " " : real time monitor */
|
||||
GLOBAL UWORD clmem; /* " " : memory manager */
|
||||
GLOBAL UWORD clcio; /* " " : char i/o */
|
||||
GLOBAL UWORD clbdos; /* " " : bdos */
|
||||
GLOBAL UWORD clnet; /* " " : network handler */
|
||||
GLOBAL UWORD clxios; /* " " : xios */
|
||||
GLOBAL UWORD cltotal; /* " " of all modules */
|
||||
GLOBAL UWORD dsstart; /* starting segment of system data */
|
||||
GLOBAL UWORD dlsysdat; /* data length: system data */
|
||||
GLOBAL UWORD dlxios; /* length of xios in data seg */
|
||||
GLOBAL UWORD dltables; /* length of tables */
|
||||
GLOBAL UWORD dsotables; /* starting offset of tables */
|
||||
GLOBAL UWORD dlrsps; /* length of rsps */
|
||||
GLOBAL UWORD dltotal; /* length of data, xios, tables & rsps */
|
||||
GLOBAL UWORD rsvd_seg; /* start of OS reserved (buffer) area (not in load image) */
|
||||
GLOBAL UWORD bufs_seg; /* ptr to allocated buffer at rsvd_seg */
|
||||
|
||||
/*** fixup locations ***/
|
||||
GLOBAL LONG fldstart; /* location of SYSDAT start */
|
||||
GLOBAL LONG locmfl; /* location in file of mem free list */
|
||||
|
||||
/**************************************************************************/
|
||||
/* system data variables for MP/M-86 or Concurrent CP/M-86 */
|
||||
/**************************************************************************/
|
||||
GLOBAL ENTRY * sd_supmod;
|
||||
GLOBAL ENTRY * sd_rtmmod;
|
||||
GLOBAL ENTRY * sd_memmod;
|
||||
GLOBAL ENTRY * sd_ciomod;
|
||||
GLOBAL ENTRY * sd_bdosmod;
|
||||
GLOBAL ENTRY * sd_xiosmod;
|
||||
GLOBAL ENTRY * sd_netmod;
|
||||
GLOBAL UWORD * sd_mpmseg;
|
||||
GLOBAL UWORD * sd_rspseg;
|
||||
GLOBAL UWORD * sd_endseg;
|
||||
GLOBAL UBYTE * sd_module_map;
|
||||
GLOBAL UBYTE * sd_ncns;
|
||||
GLOBAL UBYTE * sd_nlst;
|
||||
GLOBAL UBYTE * sd_nccb;
|
||||
GLOBAL UBYTE * sd_nflags;
|
||||
GLOBAL UBYTE * sd_srchdisk;
|
||||
GLOBAL UWORD * sd_mmp;
|
||||
GLOBAL UBYTE * sd_nslaves;
|
||||
GLOBAL UBYTE * sd_dayfile;
|
||||
GLOBAL UBYTE * sd_tempdisk;
|
||||
GLOBAL UBYTE * sd_tickspsec;
|
||||
GLOBAL UWORD * sd_lul;
|
||||
GLOBAL UWORD * sd_ccb;
|
||||
GLOBAL UWORD * sd_flags;
|
||||
GLOBAL UWORD * sd_mdul;
|
||||
GLOBAL UBYTE * sd_nxmds;
|
||||
GLOBAL UWORD * sd_mfl;
|
||||
GLOBAL UBYTE * sd_nmparts;
|
||||
GLOBAL UWORD * sd_pul;
|
||||
GLOBAL UBYTE * sd_nxpd;
|
||||
GLOBAL UWORD * sd_qul;
|
||||
GLOBAL UBYTE * sd_nqds;
|
||||
GLOBAL UWORD * sd_qmau;
|
||||
GLOBAL UWORD * sd_qmastart; /* segment start of q buffer */
|
||||
GLOBAL UWORD * sd_qmalen; /* length of q buffer */
|
||||
GLOBAL UWORD * sd_verptr; /* pts to SUP segment ver string */
|
||||
GLOBAL UWORD * sd_vn; /* F.12 version num */
|
||||
GLOBAL UWORD * sd_mpmvn; /* F.163 version num */
|
||||
GLOBAL UBYTE * sd_ncondev;
|
||||
GLOBAL UBYTE * sd_nlstdev;
|
||||
GLOBAL UBYTE * sd_nciodev;
|
||||
GLOBAL UWORD * sd_lcb;
|
||||
GLOBAL UBYTE * sd_plock_max;
|
||||
GLOBAL UBYTE * sd_popen_max;
|
||||
GLOBAL UBYTE * sd_cmode;
|
||||
GLOBAL UBYTE * sd_xpcns;
|
||||
|
||||
#else
|
||||
|
||||
/****** declarations for non MAINMODULE *******/
|
||||
|
||||
/**************************************************************************/
|
||||
/* Program Globals
|
||||
/**************************************************************************/
|
||||
EXTERN BYTE *copyright;
|
||||
EXTERN BYTE *version;
|
||||
EXTERN BYTE *clearit; /* Home cursor & erase screen */
|
||||
EXTERN BOOLEAN verbose; /* flag to tell EDSYS to be wordy */
|
||||
EXTERN BOOLEAN doit; /* flag: tell EDSYS to do the rest of it */
|
||||
EXTERN WORD fns; /* File descriptor for New System file */
|
||||
EXTERN BOOLEAN dogensys; /* Gen System from scratch? */
|
||||
EXTERN BOOLEAN doclean; /* Clean SYSFILE first from destination drive? */
|
||||
EXTERN BOOLEAN donew_xios; /* edit in a NEW XIOS? */
|
||||
EXTERN BOOLEAN pure_xios; /* XIOS groups are pure (separate) code & data? */
|
||||
EXTERN BYTE destdrv; /* where the SYSFILE goes */
|
||||
|
||||
/**************************************************************************/
|
||||
/* Sysfile Globals
|
||||
/**************************************************************************/
|
||||
EXTERN WORD totmds; /* total number of memory descriptors */
|
||||
EXTERN WORD totpds; /* total number of process descriptors */
|
||||
EXTERN WORD xtrapds; /* number of pds wanted by user */
|
||||
EXTERN WORD totqcbs; /* tot num q control blocks */
|
||||
EXTERN UWORD qbuflen; /* length in bytes of q buf area */
|
||||
EXTERN WORD totopen; /* total open files & locked records */
|
||||
|
||||
EXTERN DLIST *rsps; /* list of RSP file names */
|
||||
EXTERN DLIST *syslbls; /* lines of OS label */
|
||||
EXTERN MLIST *memroot; /* memory partitions */
|
||||
EXTERN XIOSTAB xt; /* xios info table */
|
||||
|
||||
EXTERN BYTE sdat_area[]; /* where to store the SYSDAT info */
|
||||
EXTERN BYTE *cmdhdr; /* command header for NEWSYS */
|
||||
|
||||
EXTERN UWORD clsup; /* code length: supervisor */
|
||||
EXTERN UWORD clos_label; /* code length: OS label */
|
||||
EXTERN UWORD clrtm; /* " " : real time monitor */
|
||||
EXTERN UWORD clmem; /* " " : memory manager */
|
||||
EXTERN UWORD clcio; /* " " : char i/o */
|
||||
EXTERN UWORD clbdos; /* " " : bdos */
|
||||
EXTERN UWORD clnet; /* " " : network handler */
|
||||
EXTERN UWORD clxios; /* " " : xios */
|
||||
EXTERN UWORD cltotal; /* " " of all modules */
|
||||
EXTERN UWORD dsstart; /* starting segment of system data */
|
||||
EXTERN UWORD dlsysdat; /* data length: system data */
|
||||
EXTERN UWORD dlxios; /* length of xios in data seg */
|
||||
EXTERN UWORD dltables; /* length of tables */
|
||||
EXTERN UWORD dsotables; /* starting offset of tables */
|
||||
EXTERN UWORD dlrsps; /* length of rsps */
|
||||
EXTERN UWORD dltotal; /* length of data, xios, tables & rsps */
|
||||
EXTERN UWORD rsvd_seg; /* start of OS reserved (buffer) area (not in load image) */
|
||||
EXTERN UWORD bufs_seg; /* ptr to allocated buffer at rsvd_seg */
|
||||
|
||||
/*** fixup locations ***/
|
||||
EXTERN LONG fldstart; /* location of SYSDAT start */
|
||||
EXTERN LONG locmfl; /* location in file of mem free list */
|
||||
|
||||
/***********************************************************/
|
||||
/* system data variables for MP/M-86 or Concurrent CP/M-86 */
|
||||
EXTERN ENTRY * sd_supmod;
|
||||
EXTERN ENTRY * sd_rtmmod;
|
||||
EXTERN ENTRY * sd_memmod;
|
||||
EXTERN ENTRY * sd_ciomod;
|
||||
EXTERN ENTRY * sd_bdosmod;
|
||||
EXTERN ENTRY * sd_xiosmod;
|
||||
EXTERN ENTRY * sd_netmod;
|
||||
EXTERN UWORD * sd_mpmseg;
|
||||
EXTERN UWORD * sd_rspseg;
|
||||
EXTERN UWORD * sd_endseg;
|
||||
EXTERN UBYTE * sd_module_map;
|
||||
EXTERN UBYTE * sd_ncns;
|
||||
EXTERN UBYTE * sd_nlst;
|
||||
EXTERN UBYTE * sd_nccb;
|
||||
EXTERN UBYTE * sd_nflags;
|
||||
EXTERN UBYTE * sd_srchdisk;
|
||||
EXTERN UWORD * sd_mmp;
|
||||
EXTERN UBYTE * sd_nslaves;
|
||||
EXTERN UBYTE * sd_dayfile;
|
||||
EXTERN UBYTE * sd_tempdisk;
|
||||
EXTERN UBYTE * sd_tickspsec;
|
||||
EXTERN UWORD * sd_lul;
|
||||
EXTERN UWORD * sd_ccb;
|
||||
EXTERN UWORD * sd_flags;
|
||||
EXTERN UWORD * sd_mdul;
|
||||
EXTERN UBYTE * sd_nxmds;
|
||||
EXTERN UWORD * sd_mfl;
|
||||
EXTERN UBYTE * sd_nmparts;
|
||||
EXTERN UWORD * sd_pul;
|
||||
EXTERN UBYTE * sd_nxpd;
|
||||
EXTERN UWORD * sd_qul;
|
||||
EXTERN UBYTE * sd_nqds;
|
||||
EXTERN UWORD * sd_qmau;
|
||||
EXTERN UWORD * sd_qmastart; /* segment start of q buffer */
|
||||
EXTERN UWORD * sd_qmalen; /* length of q buffer */
|
||||
EXTERN UWORD * sd_verptr; /* pts to SUP segment ver string */
|
||||
EXTERN UWORD * sd_vn; /* F.12 version num */
|
||||
EXTERN UWORD * sd_mpmvn; /* F.163 version num */
|
||||
EXTERN UBYTE * sd_ncondev;
|
||||
EXTERN UBYTE * sd_nlstdev;
|
||||
EXTERN UBYTE * sd_nciodev;
|
||||
EXTERN UWORD * sd_lcb;
|
||||
EXTERN UBYTE * sd_plock_max;
|
||||
EXTERN UBYTE * sd_popen_max;
|
||||
EXTERN UBYTE * sd_cmode;
|
||||
EXTERN UBYTE * sd_xpcns;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define PUTDRV(dd,nn) (sprintf(dd,"%c:%s",'A'+destdrv,nn))
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
drc genc1 -h
|
||||
drc genc2 -h
|
||||
drc genc3 -h
|
||||
drc genc4 -h
|
||||
drc genc5 -h
|
||||
drc genc6 -h
|
||||
link86 genccpm=genc1,genc2,genc3,genc4,genc5,genc6[libsyms
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
gentab: proc options (main);
|
||||
|
||||
/* generate tables for 8086 disassembler 12/23/80 */
|
||||
/* modified 5/14/81 */
|
||||
|
||||
declare
|
||||
opcnt (2:6) fixed (7) static initial (0,0,0,0,0),
|
||||
sum fixed (7),
|
||||
len fixed (7),
|
||||
line char (100) varying,
|
||||
infile file,
|
||||
outfile file,
|
||||
litfile file,
|
||||
opcode char (10) varying,
|
||||
i fixed (7),
|
||||
j fixed (15),
|
||||
n fixed (7),
|
||||
count fixed (15),
|
||||
chars (200) char (6) varying;
|
||||
|
||||
open file (infile) input stream title ('OP86.DAT');
|
||||
open file (outfile) print title ('OPTAB.DAT');
|
||||
open file (litfile) print title ('OPTAB.LIT');
|
||||
|
||||
on endpage (outfile) begin; end;
|
||||
on endpage (litfile) begin; end;
|
||||
|
||||
count = 0;
|
||||
|
||||
/* read op86.dat file into chars array */
|
||||
|
||||
get file (infile) list (opcode);
|
||||
do while (opcode ^= '$');
|
||||
count = count + 1;
|
||||
chars (count) = opcode;
|
||||
get file (infile) list (opcode);
|
||||
end;
|
||||
|
||||
/* create ascii opcode tables, 1 for each character length */
|
||||
|
||||
do i = 2 to 6;
|
||||
line = 'declare ops' || deblank (i) || ' (*) byte initial (';
|
||||
n = 0;
|
||||
do j = 1 to count;
|
||||
if length (chars (j)) = i then
|
||||
do;
|
||||
if n > 0 then line = line || ', ';
|
||||
if divide (n, 5, 7) * 5 = n then
|
||||
do;
|
||||
put file (outfile) skip list (line);
|
||||
line = '^I';
|
||||
end;
|
||||
n = n + 1;
|
||||
line = line || '''' || chars (j) || '''';
|
||||
opcnt (i) = opcnt (i) + 1;
|
||||
end;
|
||||
end;
|
||||
line = line || ');';
|
||||
put file (outfile) skip list (line);
|
||||
put file (outfile) skip;
|
||||
end;
|
||||
|
||||
/* create array containing # of opcodes of each length */
|
||||
|
||||
line = 'declare nops (5) byte public initial (';
|
||||
do i = 2 to 6;
|
||||
line = line || deblank (opcnt (i));
|
||||
if i < 6 then line = line || ', ';
|
||||
end;
|
||||
put file (outfile) skip list (line || ');');
|
||||
put file (outfile) skip;
|
||||
|
||||
/* create array containing starting index for each opcode length */
|
||||
|
||||
line = 'declare opn$in (*) byte public initial (';
|
||||
sum = 0;
|
||||
do i = 2 to 6;
|
||||
line = line || deblank (sum) || ', ';
|
||||
sum = sum + opcnt (i);
|
||||
end;
|
||||
put file (outfile) skip list (line || '255);');
|
||||
|
||||
/* create literals for starting indexes for each opcode length */
|
||||
|
||||
sum = 0;
|
||||
put file (litfile) skip list ('declare');
|
||||
do i = 2 to 6;
|
||||
put skip list (deblank (opcnt (i)), deblank (i) || '-character opcodes');
|
||||
line = '^I' || 'op' || deblank (i) ||
|
||||
'$in literally ''' || deblank (sum) || '''';
|
||||
if i = 6 then line = line || ';';
|
||||
else line = line || ',';
|
||||
put file (litfile) skip list (line);
|
||||
sum = sum + opcnt (i);
|
||||
opcnt (i) = 0;
|
||||
end;
|
||||
|
||||
/* create literals for position in opcode tables of each opcode */
|
||||
|
||||
put file (litfile) skip;
|
||||
put file (litfile) skip list ('declare');
|
||||
do j = 1 to count;
|
||||
len = length (chars (j));
|
||||
if index (chars (j), ':') > 0 then
|
||||
chars (j) = substr (chars (j), 1, len-1);
|
||||
line = '^I' || chars (j) || '$in literally '''
|
||||
|| 'op' || deblank (len) || '$in + '
|
||||
|| deblank (opcnt (len)) || '''';
|
||||
if j = count then line = line || ';';
|
||||
else line = line || ',';
|
||||
put file (litfile) skip list (line);
|
||||
opcnt (len) = opcnt (len) + 1;
|
||||
end;
|
||||
|
||||
deblank: proc (i) returns (char (10) varying);
|
||||
declare i fixed (7);
|
||||
declare temp char (10) varying;
|
||||
temp = char (i);
|
||||
return (substr (temp, verify (temp, ' ')));
|
||||
end deblank;
|
||||
|
||||
end gentab;
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
$title('instruction table for 8086 disassembler')
|
||||
$date(10/5/80)
|
||||
|
||||
instr86: do;
|
||||
|
||||
declare
|
||||
qq$in literally '0',
|
||||
alt1 literally '0',
|
||||
alt2 literally '1',
|
||||
alt3 literally '2',
|
||||
alt4 literally '3',
|
||||
alt5 literally '4',
|
||||
alt6 literally '5',
|
||||
alt7 literally '6',
|
||||
alt8 literally '7';
|
||||
|
||||
$include(optab.lit)
|
||||
|
||||
declare
|
||||
type$0 literally '0',
|
||||
type$1 literally '1',
|
||||
type$2 literally '2',
|
||||
type$3 literally '3',
|
||||
type$4 literally '4',
|
||||
type$5 literally '5',
|
||||
type$6 literally '6',
|
||||
type$7 literally '7',
|
||||
type$8 literally '7',
|
||||
type$9 literally '7',
|
||||
type$10 literally '8',
|
||||
type$11 literally '9',
|
||||
type$12 literally '10',
|
||||
type$13 literally '11',
|
||||
type$14 literally '12',
|
||||
type$15 literally '12',
|
||||
type$16 literally '12',
|
||||
type$17 literally '12',
|
||||
type$18 literally '13',
|
||||
type$19 literally '13',
|
||||
type$20 literally '13',
|
||||
type$21 literally '13',
|
||||
type$22 literally '14',
|
||||
type$23 literally '15',
|
||||
type$24 literally '15',
|
||||
type$25 literally '16',
|
||||
type$26 literally '16',
|
||||
type$27 literally '17',
|
||||
type$28 literally '17',
|
||||
type$29 literally '17',
|
||||
type$30 literally '17',
|
||||
type$31 literally '18',
|
||||
type$32 literally '18',
|
||||
type$33 literally '19',
|
||||
type$34 literally '20',
|
||||
type$35 literally '20',
|
||||
type$36 literally '21',
|
||||
type$37 literally '21',
|
||||
type$38 literally '22',
|
||||
type$39 literally '23',
|
||||
type$40 literally '24',
|
||||
type$41 literally '24',
|
||||
type$42 literally '25',
|
||||
type$43 literally '26',
|
||||
type$44 literally '27',
|
||||
type$45 literally '28';
|
||||
|
||||
declare
|
||||
prefix$type literally '0ffh';
|
||||
|
||||
declare alt$table$ptrs (8) address public data (
|
||||
.alt$1$tab,
|
||||
.alt$2$tab,
|
||||
.alt$3$tab,
|
||||
.alt$4$tab,
|
||||
.alt$5$tab,
|
||||
.alt$6$tab,
|
||||
.alt$7$tab,
|
||||
.alt$8$tab);
|
||||
|
||||
declare alt$1$tab (*) byte data (
|
||||
add$in, type$44,
|
||||
or$in, type$34,
|
||||
adc$in, type$44,
|
||||
sbb$in, type$44,
|
||||
and$in, type$34,
|
||||
sub$in, type$44,
|
||||
xor$in, type$34,
|
||||
cmp$in, type$44);
|
||||
|
||||
declare alt$2$tab (*) byte data (
|
||||
add$in, type$44,
|
||||
qq$in, type$0,
|
||||
adc$in, type$44,
|
||||
sbb$in, type$44,
|
||||
qq$in, type$0,
|
||||
sub$in, type$44,
|
||||
qq$in, type$0,
|
||||
cmp$in, type$44);
|
||||
|
||||
declare alt$3$tab (*) byte data (
|
||||
add$in, type$38,
|
||||
qq$in, type$0,
|
||||
adc$in, type$38,
|
||||
sbb$in, type$38,
|
||||
qq$in, type$0,
|
||||
sub$in, type$38,
|
||||
qq$in, type$0,
|
||||
cmp$in, type$38);
|
||||
|
||||
declare alt$4$tab (*) byte data (
|
||||
rol$in, type$29,
|
||||
ror$in, type$29,
|
||||
rcl$in, type$29,
|
||||
rcr$in, type$29,
|
||||
shl$in, type$29,
|
||||
shr$in, type$29,
|
||||
qq$in, type$0,
|
||||
sar$in, type$29);
|
||||
|
||||
declare alt$5$tab (*) byte data (
|
||||
rol$in, type$27,
|
||||
ror$in, type$27,
|
||||
rcl$in, type$27,
|
||||
rcr$in, type$27,
|
||||
shl$in, type$27,
|
||||
shr$in, type$27,
|
||||
qq$in, type$0,
|
||||
sar$in, type$27);
|
||||
|
||||
declare alt$6$tab (*) byte data (
|
||||
test$in, type$34,
|
||||
qq$in, type$0,
|
||||
not$in, type$45,
|
||||
neg$in, type$45,
|
||||
mul$in, type$45,
|
||||
imul$in, type$45,
|
||||
div$in, type$45,
|
||||
idiv$in, type$45);
|
||||
|
||||
declare alt$7$tab (*) byte data (
|
||||
inc$in, type$45,
|
||||
dec$in, type$45,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0);
|
||||
|
||||
declare alt$8$tab (*) byte data (
|
||||
inc$in, type$45,
|
||||
dec$in, type$45,
|
||||
call$in, type$9,
|
||||
callf$in, type$7,
|
||||
jmp$in, type$9,
|
||||
jmpf$in, type$7,
|
||||
push$in, type$7,
|
||||
qq$in, type$0);
|
||||
|
||||
/*
|
||||
instruction table for 8086 disassembler
|
||||
instruction is index into table
|
||||
there are 2 bytes per instruction:
|
||||
1. index into ascii opcode table
|
||||
2. instruction type (how many operands of what type, etc.)
|
||||
*/
|
||||
|
||||
declare instr$table (512) byte public data (
|
||||
add$in, type$14, /* 0 */
|
||||
add$in, type$15,
|
||||
add$in, type$16,
|
||||
add$in, type$17,
|
||||
add$in, type$23,
|
||||
add$in, type$24,
|
||||
push$in, type$4,
|
||||
pop$in, type$4,
|
||||
or$in, type$14,
|
||||
or$in, type$15,
|
||||
or$in, type$16,
|
||||
or$in, type$17,
|
||||
or$in, type$23,
|
||||
or$in, type$24,
|
||||
push$in, type$4,
|
||||
qq$in, type$0,
|
||||
adc$in, type$14, /* 10 */
|
||||
adc$in, type$15,
|
||||
adc$in, type$16,
|
||||
adc$in, type$17,
|
||||
adc$in, type$23,
|
||||
adc$in, type$24,
|
||||
push$in, type$4,
|
||||
pop$in, type$4,
|
||||
sbb$in, type$14,
|
||||
sbb$in, type$15,
|
||||
sbb$in, type$16,
|
||||
sbb$in, type$17,
|
||||
sbb$in, type$23,
|
||||
sbb$in, type$24,
|
||||
push$in, type$4,
|
||||
pop$in, type$4,
|
||||
and$in, type$14, /* 20 */
|
||||
and$in, type$15,
|
||||
and$in, type$16,
|
||||
and$in, type$17,
|
||||
and$in, type$23,
|
||||
and$in, type$24,
|
||||
es$in, prefix$type,
|
||||
daa$in, type$1,
|
||||
sub$in, type$14,
|
||||
sub$in, type$15,
|
||||
sub$in, type$16,
|
||||
sub$in, type$17,
|
||||
sub$in, type$23,
|
||||
sub$in, type$24,
|
||||
cs$in, prefix$type,
|
||||
das$in, type$1,
|
||||
xor$in, type$14, /* 30 */
|
||||
xor$in, type$15,
|
||||
xor$in, type$16,
|
||||
xor$in, type$17,
|
||||
xor$in, type$23,
|
||||
xor$in, type$24,
|
||||
ss$in, prefix$type,
|
||||
aaa$in, type$1,
|
||||
cmp$in, type$14,
|
||||
cmp$in, type$15,
|
||||
cmp$in, type$16,
|
||||
cmp$in, type$17,
|
||||
cmp$in, type$23,
|
||||
cmp$in, type$24,
|
||||
ds$in, prefix$type,
|
||||
aas$in, type$1,
|
||||
inc$in, type$3, /* 40 */
|
||||
inc$in, type$3,
|
||||
inc$in, type$3,
|
||||
inc$in, type$3,
|
||||
inc$in, type$3,
|
||||
inc$in, type$3,
|
||||
inc$in, type$3,
|
||||
inc$in, type$3,
|
||||
dec$in, type$3,
|
||||
dec$in, type$3,
|
||||
dec$in, type$3,
|
||||
dec$in, type$3,
|
||||
dec$in, type$3,
|
||||
dec$in, type$3,
|
||||
dec$in, type$3,
|
||||
dec$in, type$3,
|
||||
push$in, type$3, /* 50 */
|
||||
push$in, type$3,
|
||||
push$in, type$3,
|
||||
push$in, type$3,
|
||||
push$in, type$3,
|
||||
push$in, type$3,
|
||||
push$in, type$3,
|
||||
push$in, type$3,
|
||||
pop$in, type$3,
|
||||
pop$in, type$3,
|
||||
pop$in, type$3,
|
||||
pop$in, type$3,
|
||||
pop$in, type$3,
|
||||
pop$in, type$3,
|
||||
pop$in, type$3,
|
||||
pop$in, type$3,
|
||||
qq$in, type$0, /* 60 */
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
jo$in, type$5, /* 70 */
|
||||
jno$in, type$5,
|
||||
jb$in, type$5,
|
||||
jnb$in, type$5,
|
||||
jz$in, type$5,
|
||||
jnz$in, type$5,
|
||||
jbe$in, type$5,
|
||||
ja$in, type$5,
|
||||
js$in, type$5,
|
||||
jns$in, type$5,
|
||||
jp$in, type$5,
|
||||
jnp$in, type$5,
|
||||
jl$in, type$5,
|
||||
jnl$in, type$5,
|
||||
jle$in, type$5,
|
||||
jg$in, type$5,
|
||||
alt1, type$43, /* 80 */
|
||||
alt1, type$43,
|
||||
alt2, type$43,
|
||||
alt2, type$43,
|
||||
test$in, type$14,
|
||||
test$in, type$15,
|
||||
xchg$in, type$16,
|
||||
xchg$in, type$17,
|
||||
mov$in, type$14,
|
||||
mov$in, type$15,
|
||||
mov$in, type$16,
|
||||
mov$in, type$17,
|
||||
mov$in, type$36,
|
||||
lea$in, type$39,
|
||||
mov$in, type$37,
|
||||
pop$in, type$9,
|
||||
nop$in, type$1, /* 90 */
|
||||
xchg$in, type$33,
|
||||
xchg$in, type$33,
|
||||
xchg$in, type$33,
|
||||
xchg$in, type$33,
|
||||
xchg$in, type$33,
|
||||
xchg$in, type$33,
|
||||
xchg$in, type$33,
|
||||
cbw$in, type$1,
|
||||
cwd$in, type$1,
|
||||
callf$in, type$13,
|
||||
wait$in, type$1,
|
||||
pushf$in, type$1,
|
||||
popf$in, type$1,
|
||||
sahf$in, type$1,
|
||||
lahf$in, type$1,
|
||||
mov$in, type$18, /* A0 */
|
||||
mov$in, type$19,
|
||||
mov$in, type$20,
|
||||
mov$in, type$21,
|
||||
movsb$in, type$1,
|
||||
movsw$in, type$1,
|
||||
cmpsb$in, type$1,
|
||||
cmpsw$in, type$1,
|
||||
test$in, type$23,
|
||||
test$in, type$24,
|
||||
stosb$in, type$1,
|
||||
stosw$in, type$1,
|
||||
lodsb$in, type$1,
|
||||
lodsw$in, type$1,
|
||||
scasb$in, type$1,
|
||||
scasw$in, type$1,
|
||||
mov$in, type$31, /* B0 */
|
||||
mov$in, type$31,
|
||||
mov$in, type$31,
|
||||
mov$in, type$31,
|
||||
mov$in, type$31,
|
||||
mov$in, type$31,
|
||||
mov$in, type$31,
|
||||
mov$in, type$31,
|
||||
mov$in, type$32,
|
||||
mov$in, type$32,
|
||||
mov$in, type$32,
|
||||
mov$in, type$32,
|
||||
mov$in, type$32,
|
||||
mov$in, type$32,
|
||||
mov$in, type$32,
|
||||
mov$in, type$32,
|
||||
qq$in, type$0, /* C0 */
|
||||
qq$in, type$0,
|
||||
ret$in, type$11,
|
||||
ret$in, type$1,
|
||||
les$in, type$39,
|
||||
lds$in, type$39,
|
||||
mov$in, type$40,
|
||||
mov$in, type$41,
|
||||
qq$in, type$0,
|
||||
qq$in, type$0,
|
||||
retf$in, type$11,
|
||||
retf$in, type$1,
|
||||
int$in, type$12,
|
||||
int$in, type$10,
|
||||
into$in, type$1,
|
||||
iret$in, type$1,
|
||||
alt4, type$43, /* D0 */
|
||||
alt4, type$43,
|
||||
alt5, type$43,
|
||||
alt5, type$43,
|
||||
aam$in, type$2,
|
||||
aad$in, type$2,
|
||||
qq$in, type$0,
|
||||
xlat$in, type$1,
|
||||
esc$in, type$42,
|
||||
esc$in, type$42,
|
||||
esc$in, type$42,
|
||||
esc$in, type$42,
|
||||
esc$in, type$42,
|
||||
esc$in, type$42,
|
||||
esc$in, type$42,
|
||||
esc$in, type$42,
|
||||
loopne$in, type$5, /* E0 */
|
||||
loope$in, type$5,
|
||||
loop$in, type$5,
|
||||
jcxz$in, type$5,
|
||||
in$in, type$22,
|
||||
in$in, type$22,
|
||||
out$in, type$22,
|
||||
out$in, type$22,
|
||||
call$in, type$6,
|
||||
jmp$in, type$6,
|
||||
jmpf$in, type$13,
|
||||
jmps$in, type$5,
|
||||
in$in, type$25,
|
||||
in$in, type$26,
|
||||
out$in, type$25,
|
||||
out$in, type$26,
|
||||
lock$in, prefix$type, /* F0 */
|
||||
qq$in, type$0,
|
||||
repne$in, prefix$type,
|
||||
rep$in, prefix$type,
|
||||
hlt$in, type$1,
|
||||
cmc$in, type$1,
|
||||
alt6, type$43,
|
||||
alt6, type$43,
|
||||
clc$in, type$1,
|
||||
stc$in, type$1,
|
||||
cli$in, type$1,
|
||||
sti$in, type$1,
|
||||
cld$in, type$1,
|
||||
std$in, type$1,
|
||||
alt7, type$43,
|
||||
alt8, type$43);
|
||||
|
||||
end instr86;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* DRC stuff to run on ....
|
||||
*/
|
||||
/*#define MC68000 1 /* 68000 version */
|
||||
/*#define VAX 1*/ /* VAX Version */
|
||||
/*#define PDP11 1*/ /* PDP-11 Version*/
|
||||
#define CPM 1 /* CP/M Operating System*/
|
||||
/*#define UNIX 1*/ /* UNIX Operating System*/
|
||||
/*#define VMS 1*/ /* VMS Operating System*/
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
AAA
|
||||
AAD
|
||||
AAM
|
||||
AAS
|
||||
ADC
|
||||
ADD
|
||||
AND
|
||||
CALL
|
||||
CALLF
|
||||
CBW
|
||||
CLC
|
||||
CLD
|
||||
CLI
|
||||
CMC
|
||||
CMP
|
||||
CMPSB
|
||||
CMPSW
|
||||
CS:
|
||||
CWD
|
||||
DAA
|
||||
DAS
|
||||
DEC
|
||||
DIV
|
||||
DS:
|
||||
ES:
|
||||
ESC
|
||||
HLT
|
||||
IDIV
|
||||
IMUL
|
||||
IN
|
||||
INC
|
||||
INT
|
||||
INTO
|
||||
IRET
|
||||
JA
|
||||
JAE
|
||||
JB
|
||||
JBE
|
||||
JC
|
||||
JCXZ
|
||||
JE
|
||||
JG
|
||||
JGE
|
||||
JL
|
||||
JLE
|
||||
JMP
|
||||
JMPF
|
||||
JMPS
|
||||
JNA
|
||||
JNAE
|
||||
JNB
|
||||
JNBE
|
||||
JNC
|
||||
JNE
|
||||
JNG
|
||||
JNGE
|
||||
JNL
|
||||
JNLE
|
||||
JNO
|
||||
JNP
|
||||
JNS
|
||||
JNZ
|
||||
JO
|
||||
JP
|
||||
JPE
|
||||
JPO
|
||||
JS
|
||||
JZ
|
||||
LAHF
|
||||
LDS
|
||||
LEA
|
||||
LES
|
||||
LOCK
|
||||
LODSB
|
||||
LODSW
|
||||
LOOP
|
||||
LOOPE
|
||||
LOOPNE
|
||||
LOOPNZ
|
||||
LOOPZ
|
||||
MOV
|
||||
MOVSB
|
||||
MOVSW
|
||||
MUL
|
||||
NEG
|
||||
NOP
|
||||
NOT
|
||||
OR
|
||||
OUT
|
||||
POP
|
||||
POPF
|
||||
PUSH
|
||||
PUSHF
|
||||
RCL
|
||||
RCR
|
||||
REP
|
||||
REPE
|
||||
REPNE
|
||||
REPNZ
|
||||
REPZ
|
||||
RET
|
||||
RETF
|
||||
ROL
|
||||
ROR
|
||||
SAHF
|
||||
SAL
|
||||
SAR
|
||||
SBB
|
||||
SCASB
|
||||
SCASW
|
||||
SHL
|
||||
SHR
|
||||
SS:
|
||||
STC
|
||||
STD
|
||||
STI
|
||||
STOSB
|
||||
STOSW
|
||||
SUB
|
||||
TEST
|
||||
WAIT
|
||||
XCHG
|
||||
XLAT
|
||||
XOR
|
||||
$
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
declare ops2 (*) byte initial (
|
||||
'IN', 'JA', 'JB', 'JC', 'JE',
|
||||
'JG', 'JL', 'JO', 'JP', 'JS',
|
||||
'JZ', 'OR');
|
||||
|
||||
declare ops3 (*) byte initial (
|
||||
'AAA', 'AAD', 'AAM', 'AAS', 'ADC',
|
||||
'ADD', 'AND', 'CBW', 'CLC', 'CLD',
|
||||
'CLI', 'CMC', 'CMP', 'CS:', 'CWD',
|
||||
'DAA', 'DAS', 'DEC', 'DIV', 'DS:',
|
||||
'ES:', 'ESC', 'HLT', 'INC', 'INT',
|
||||
'JAE', 'JBE', 'JGE', 'JLE', 'JMP',
|
||||
'JNA', 'JNB', 'JNC', 'JNE', 'JNG',
|
||||
'JNL', 'JNO', 'JNP', 'JNS', 'JNZ',
|
||||
'JPE', 'JPO', 'LDS', 'LEA', 'LES',
|
||||
'MOV', 'MUL', 'NEG', 'NOP', 'NOT',
|
||||
'OUT', 'POP', 'RCL', 'RCR', 'REP',
|
||||
'RET', 'ROL', 'ROR', 'SAL', 'SAR',
|
||||
'SBB', 'SHL', 'SHR', 'SS:', 'STC',
|
||||
'STD', 'STI', 'SUB', 'XOR');
|
||||
|
||||
declare ops4 (*) byte initial (
|
||||
'CALL', 'IDIV', 'IMUL', 'INTO', 'IRET',
|
||||
'JCXZ', 'JMPF', 'JMPS', 'JNAE', 'JNBE',
|
||||
'JNGE', 'JNLE', 'LAHF', 'LOCK', 'LOOP',
|
||||
'POPF', 'PUSH', 'REPE', 'REPZ', 'RETF',
|
||||
'SAHF', 'TEST', 'WAIT', 'XCHG', 'XLAT');
|
||||
|
||||
declare ops5 (*) byte initial (
|
||||
'CALLF', 'CMPSB', 'CMPSW', 'LODSB', 'LODSW',
|
||||
'LOOPE', 'LOOPZ', 'MOVSB', 'MOVSW', 'PUSHF',
|
||||
'REPNE', 'REPNZ', 'SCASB', 'SCASW', 'STOSB',
|
||||
'STOSW');
|
||||
|
||||
declare ops6 (*) byte initial (
|
||||
'LOOPNE', 'LOOPNZ');
|
||||
|
||||
declare nops (5) byte public initial (12, 69, 25, 16, 2);
|
||||
|
||||
declare opn$in (*) byte public initial (0, 12, 81, 106, 122, 255);
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
|
||||
declare
|
||||
op2$in literally '0',
|
||||
op3$in literally '12',
|
||||
op4$in literally '81',
|
||||
op5$in literally '106',
|
||||
op6$in literally '122';
|
||||
|
||||
declare
|
||||
AAA$in literally 'op3$in + 0',
|
||||
AAD$in literally 'op3$in + 1',
|
||||
AAM$in literally 'op3$in + 2',
|
||||
AAS$in literally 'op3$in + 3',
|
||||
ADC$in literally 'op3$in + 4',
|
||||
ADD$in literally 'op3$in + 5',
|
||||
AND$in literally 'op3$in + 6',
|
||||
CALL$in literally 'op4$in + 0',
|
||||
CALLF$in literally 'op5$in + 0',
|
||||
CBW$in literally 'op3$in + 7',
|
||||
CLC$in literally 'op3$in + 8',
|
||||
CLD$in literally 'op3$in + 9',
|
||||
CLI$in literally 'op3$in + 10',
|
||||
CMC$in literally 'op3$in + 11',
|
||||
CMP$in literally 'op3$in + 12',
|
||||
CMPSB$in literally 'op5$in + 1',
|
||||
CMPSW$in literally 'op5$in + 2',
|
||||
CS$in literally 'op3$in + 13',
|
||||
CWD$in literally 'op3$in + 14',
|
||||
DAA$in literally 'op3$in + 15',
|
||||
DAS$in literally 'op3$in + 16',
|
||||
DEC$in literally 'op3$in + 17',
|
||||
DIV$in literally 'op3$in + 18',
|
||||
DS$in literally 'op3$in + 19',
|
||||
ES$in literally 'op3$in + 20',
|
||||
ESC$in literally 'op3$in + 21',
|
||||
HLT$in literally 'op3$in + 22',
|
||||
IDIV$in literally 'op4$in + 1',
|
||||
IMUL$in literally 'op4$in + 2',
|
||||
IN$in literally 'op2$in + 0',
|
||||
INC$in literally 'op3$in + 23',
|
||||
INT$in literally 'op3$in + 24',
|
||||
INTO$in literally 'op4$in + 3',
|
||||
IRET$in literally 'op4$in + 4',
|
||||
JA$in literally 'op2$in + 1',
|
||||
JAE$in literally 'op3$in + 25',
|
||||
JB$in literally 'op2$in + 2',
|
||||
JBE$in literally 'op3$in + 26',
|
||||
JC$in literally 'op2$in + 3',
|
||||
JCXZ$in literally 'op4$in + 5',
|
||||
JE$in literally 'op2$in + 4',
|
||||
JG$in literally 'op2$in + 5',
|
||||
JGE$in literally 'op3$in + 27',
|
||||
JL$in literally 'op2$in + 6',
|
||||
JLE$in literally 'op3$in + 28',
|
||||
JMP$in literally 'op3$in + 29',
|
||||
JMPF$in literally 'op4$in + 6',
|
||||
JMPS$in literally 'op4$in + 7',
|
||||
JNA$in literally 'op3$in + 30',
|
||||
JNAE$in literally 'op4$in + 8',
|
||||
JNB$in literally 'op3$in + 31',
|
||||
JNBE$in literally 'op4$in + 9',
|
||||
JNC$in literally 'op3$in + 32',
|
||||
JNE$in literally 'op3$in + 33',
|
||||
JNG$in literally 'op3$in + 34',
|
||||
JNGE$in literally 'op4$in + 10',
|
||||
JNL$in literally 'op3$in + 35',
|
||||
JNLE$in literally 'op4$in + 11',
|
||||
JNO$in literally 'op3$in + 36',
|
||||
JNP$in literally 'op3$in + 37',
|
||||
JNS$in literally 'op3$in + 38',
|
||||
JNZ$in literally 'op3$in + 39',
|
||||
JO$in literally 'op2$in + 7',
|
||||
JP$in literally 'op2$in + 8',
|
||||
JPE$in literally 'op3$in + 40',
|
||||
JPO$in literally 'op3$in + 41',
|
||||
JS$in literally 'op2$in + 9',
|
||||
JZ$in literally 'op2$in + 10',
|
||||
LAHF$in literally 'op4$in + 12',
|
||||
LDS$in literally 'op3$in + 42',
|
||||
LEA$in literally 'op3$in + 43',
|
||||
LES$in literally 'op3$in + 44',
|
||||
LOCK$in literally 'op4$in + 13',
|
||||
LODSB$in literally 'op5$in + 3',
|
||||
LODSW$in literally 'op5$in + 4',
|
||||
LOOP$in literally 'op4$in + 14',
|
||||
LOOPE$in literally 'op5$in + 5',
|
||||
LOOPNE$in literally 'op6$in + 0',
|
||||
LOOPNZ$in literally 'op6$in + 1',
|
||||
LOOPZ$in literally 'op5$in + 6',
|
||||
MOV$in literally 'op3$in + 45',
|
||||
MOVSB$in literally 'op5$in + 7',
|
||||
MOVSW$in literally 'op5$in + 8',
|
||||
MUL$in literally 'op3$in + 46',
|
||||
NEG$in literally 'op3$in + 47',
|
||||
NOP$in literally 'op3$in + 48',
|
||||
NOT$in literally 'op3$in + 49',
|
||||
OR$in literally 'op2$in + 11',
|
||||
OUT$in literally 'op3$in + 50',
|
||||
POP$in literally 'op3$in + 51',
|
||||
POPF$in literally 'op4$in + 15',
|
||||
PUSH$in literally 'op4$in + 16',
|
||||
PUSHF$in literally 'op5$in + 9',
|
||||
RCL$in literally 'op3$in + 52',
|
||||
RCR$in literally 'op3$in + 53',
|
||||
REP$in literally 'op3$in + 54',
|
||||
REPE$in literally 'op4$in + 17',
|
||||
REPNE$in literally 'op5$in + 10',
|
||||
REPNZ$in literally 'op5$in + 11',
|
||||
REPZ$in literally 'op4$in + 18',
|
||||
RET$in literally 'op3$in + 55',
|
||||
RETF$in literally 'op4$in + 19',
|
||||
ROL$in literally 'op3$in + 56',
|
||||
ROR$in literally 'op3$in + 57',
|
||||
SAHF$in literally 'op4$in + 20',
|
||||
SAL$in literally 'op3$in + 58',
|
||||
SAR$in literally 'op3$in + 59',
|
||||
SBB$in literally 'op3$in + 60',
|
||||
SCASB$in literally 'op5$in + 12',
|
||||
SCASW$in literally 'op5$in + 13',
|
||||
SHL$in literally 'op3$in + 61',
|
||||
SHR$in literally 'op3$in + 62',
|
||||
SS$in literally 'op3$in + 63',
|
||||
STC$in literally 'op3$in + 64',
|
||||
STD$in literally 'op3$in + 65',
|
||||
STI$in literally 'op3$in + 66',
|
||||
STOSB$in literally 'op5$in + 14',
|
||||
STOSW$in literally 'op5$in + 15',
|
||||
SUB$in literally 'op3$in + 67',
|
||||
TEST$in literally 'op4$in + 21',
|
||||
WAIT$in literally 'op4$in + 22',
|
||||
XCHG$in literally 'op4$in + 23',
|
||||
XLAT$in literally 'op4$in + 24',
|
||||
XOR$in literally 'op3$in + 68';
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* C P / M C R U N T I M E L I B H E A D E R F I L E
|
||||
* -------------------------------------------------------------
|
||||
* Copyright 1982 by Digital Research Inc. All rights reserved.
|
||||
*
|
||||
* This is an include file for assisting the user to write portable
|
||||
* programs for C.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define UCHARA 1 /* if char is unsigned */
|
||||
/*
|
||||
* Standard type definitions
|
||||
*/
|
||||
/***************************/
|
||||
#define BYTE char /* Signed byte */
|
||||
#define BOOLEAN int /* 2 valued (true/false) */
|
||||
#define WORD int /* Signed word (16 bits) */
|
||||
#define UWORD unsigned int /* unsigned word */
|
||||
|
||||
#define LONG long /* signed long (32 bits) */
|
||||
#define ULONG long /* Unsigned long */
|
||||
|
||||
|
||||
#define REG register /* register variable */
|
||||
#define LOCAL auto /* Local var on 68000 */
|
||||
#define EXTERN extern /* External variable */
|
||||
#define MLOCAL static /* Local to module */
|
||||
#define GLOBAL /**/ /* Global variable */
|
||||
#define VOID /**/ /* Void function return */
|
||||
#define DEFAULT int /* Default size */
|
||||
/***************************/
|
||||
#ifdef UCHARA
|
||||
#define UBYTE char /* Unsigned byte */
|
||||
#else
|
||||
#define UBYTE unsigned char /* Unsigned byte */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Miscellaneous Definitions: */
|
||||
/****************************************************************************/
|
||||
#define FAILURE (-1) /* Function failure return val */
|
||||
#define SUCCESS (0) /* Function success return val */
|
||||
#define YES 1 /* "TRUE" */
|
||||
#define NO 0 /* "FALSE" */
|
||||
#define FOREVER for(;;) /* Infinite loop declaration */
|
||||
#define NULL 0 /* Null pointer value */
|
||||
#define NULLPTR (char *) 0 /* */
|
||||
#define EOF (-1) /* EOF Value */
|
||||
#define TRUE (1) /* Function TRUE value */
|
||||
#define FALSE (0) /* Function FALSE value */
|
||||
|
||||
/*************************** end of portab.h ********************************/
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user