Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,253 @@
/* #include <conio.h> */
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct fcb // also directory entry
{
unsigned char user; // not used in CP/M 1.4
unsigned char name[8]; // file name
unsigned char type[3]; // file extension
unsigned char ext; // extent number
unsigned char notused[2];
unsigned char rc; // record count in this extent
unsigned char dm[16]; // single byte extent numbers
};
#define DIR_ENT_SZ 32 // size of one directory entry
#define SECT_SZ 128 // disk sector size
#define SPB 8 // sectors per block
#define DIR_BLOCKS 2 // 2 blocks reserved for directory
#define SPT 26 // sectors per track
#define RESERVED_TRACKS 2 // for cold boot, ccp and cpm
#define DIR_SECTORS (SPB * DIR_BLOCKS) // sectors for directory
#define DIR_LOCN (SPT * RESERVED_TRACKS) // offset of directory
#define DIR_ENT_PER_SEC (SECT_SZ / DIR_ENT_SZ) // directory entries per sector
unsigned char buff1[SPT * SECT_SZ]; // for de-interleaving
unsigned char buff2[SPT * SECT_SZ]; // "
unsigned char fsec [SECT_SZ];
char fname [20]; // file name for current extent
char fname2[20]; // currently open output file name, if any
FILE *in, // raw image file
*out; // extracted CP/M file
unsigned char exm[1024]; // map of processed blocks
// sector interleave table
unsigned char sectran[] = {
"\x01\x07\x0d\x13\x19\x05\x0b\x11"
"\x17\x03\x09\x0f\x15\x02\x08\x0e"
"\x14\x1a\x06\x0c\x12\x18\x04\x0a"
"\x10\x16\x00\x00\x00\x00\x00\x00"};
char temp[] = "junkimg.jnk"; // name of de-interleaved raw image file
/**************************************************
Read the input image file in gulps of 26 sectors, reorder using the
interleace table, and save the to the de-interleaved file
*/
void RemoveInterleave
(
char *fn1, // ram image file name
char * fn2, // reordered image file name
int flag // not used
)
{
int x;
in = fopen(fn1, "rb");
out = fopen(fn2, "wb");
while (fread(buff1, 1, sizeof(buff1), in)) // read a 'track'
{
for (x = 0; x < SPT; x++) // shuffle
{
memcpy(&buff2[x * SECT_SZ], &buff1[(sectran[x] - 1) * SECT_SZ], SECT_SZ);
}
fwrite(buff2, 1, sizeof(buff2), out);
}
fcloseall();
}
/**************************************************
Copy a file name or extension until a space character is found
or limit is reached.
*/
void copyuntil
(
char *dst, // destination for copy
char *src, // source for copy
int count // max copy length
)
{
while (*src != ' ' && count--)
{
*dst++ = *src++;
}
*dst = 0;
}
/**************************************************
Convert an 8,3 filename into name.ext format
*/
void MakeFilename
(
char *fname, // destination for file name
struct fcb *tfcb // pointer to fcb (directory entry)
)
{
copyuntil(fname, tfcb->name, 8); // copy name part
if (tfcb->type[0] != ' ') // if extension is non-blank
{
strcat(fname, "."); // add a dot
copyuntil(fname + strlen(fname), tfcb->type, 3);
}
}
/**************************************************
Read a logical CP/M sector from the image file. Sector is a logical
number based at the directory root. The reserved sectors(tracks)
are added.
*/
void ReadSector
(
unsigned char *where, // destination for read
int sectorno // logical sector number
)
{
fseek(in, (long)(DIR_LOCN + sectorno) * (long)SECT_SZ, SEEK_SET);
fread(where, 1, SECT_SZ, in);
}
/**************************************************
Construct the file name and copy all records in the specified extent into the
output file. If the file name differs from the previously processed file name
close the previous file and open a new one with the current name.
Since extents are psorecces in sorted order, including the extent number, this
results in recovered files.
*/
void CopyExtentToFile
(
struct fcb *tfcb, // pointer to fcb (directory entry)
int deleted // flag indicating a deleted extent
)
{
int x, // general counter
thisSect, // computed logical sector number
said; // flag for printing
static int extent; // logical extent number
MakeFilename(fname, tfcb); // extract filename
if (strcmp(fname2, fname)) // is it different from before?
{
if (out != NULL)
{
fclose(out);
}
out = fopen(fname, "wb"); // create new output file
strcpy(fname2, fname);
printf("Extracting %sfile %s\n", deleted ? "deleted " : "", fname);
extent = -1;
}
extent++;
//printf("%15s", fname);
for (x = 0; x < tfcb->rc; x++) // fetch record count sectors and save
{
if (!(x % SPB))
{
//printf(" %02x", tfcb->dm[x / SPB]);
}
if ((exm[tfcb->dm[x / SPB]] != 0) && !said)
{
said = 1;
printf(" extent %d has blocks used elsewhere\n");
}
exm[tfcb->dm[x / SPB]] = 1; // mark in block map
// convert logical sector to physical
thisSect = (tfcb->dm[x / SPB] * SPB) + (x % SPB);
ReadSector(fsec, thisSect); // load the file sector
fwrite(fsec, 1, SECT_SZ, out); // store in new file
}
//printf("\n");
}
/**************************************************
Compare routine for qsort of directory
*/
int compare
(
void *a, // pointer to key field 'a'
void *b // pointer to key field 'b'
)
{
return memcmp(a, b, 16); // compare keys
}
/**************************************************
*/
main
(
int argc, // count of command line arguments
char **argv // pointers to arguments
)
{
int x;
struct fcb *tfcb = (struct fcb *)buff1;
//printf("Dir locn %x\n", DIR_LOCN * SECT_SZ);
if (argc < 2)
{
printf("File name required for compare\n\n");
printf("Correct usage is:\n");
printf(" extract <filename>\n\n");
printf(" where <filename> is a diskette image file\n");
exit(1);
}
RemoveInterleave(argv[1], temp, 0);
in = fopen(temp, "rb");
// load the directory into memory
for (x = 0; x < DIR_SECTORS; x++)
{
ReadSector(buff1 + (x * SECT_SZ), x);
}
// sort the directory in [user], name and extent order
qsort(buff1, DIR_SECTORS, DIR_ENT_SZ, compare);
// process the sorted list
for (x = 0; x < (DIR_SECTORS * DIR_ENT_PER_SEC); x++)
{
if ((tfcb->name[0] != 0xe5) && (tfcb->name != 0))
{
CopyExtentToFile(tfcb, tfcb->user == 0xe5);
}
tfcb++;
}
fcloseall();
remove(temp);
}

View File

@@ -0,0 +1,3 @@
@echo off
rem extract the BDOS image from cpm.com
call ..\tools\getcpm ..\binaries\cpm.com bdos.bin 1200 d00

View File

@@ -0,0 +1,4 @@
@echo off
rem extract the CCP image from cpm.com
call ..\tools\getcpm ..\binaries\cpm.com ccp.bin a00 800

View File

@@ -0,0 +1,10 @@
@echo off
rem #1 = inputfn, #2 outputfn #3 = addr, #4 = lth
rem build a script for debug
echo rcx>dbg.bat
echo %4>>dbg.bat
echo n%2>>dbg.bat
echo w%3>>dbg.bat
echo q>>dbg.bat
call debug %1 <dbg.bat

View File

@@ -0,0 +1,176 @@
/*
Intel hex to binary converter Converts the specified file to binary
*/
#include <stdio.h>
#include <conio.h>
#include <assert.h>
typedef struct image_t
{
unsigned lowaddress, highaddress;
} image_t;
//void LoadHexFile(char *fn, unsigned char *where, image_t *im);
#define LINE_SIZE 500 // max size of input hex line
#define MAX_IMG_SZ 0x4000
// Intel hex-file record types
#define RT_DATA 0
#define RT_EOF 1
static int hexsum;
static unsigned char *lyne;
/******************************************************************************
Get a hexadecimal nybble from the input stream. Increment the pointer.
*/
static int getnib(char **bt)
{
int x = **bt - '0';
if (x > 9)
{
x -= 7;
}
(*bt)++;
return x;
}
/******************************************************************************
Get a single unsigned byte (2 nibbles) from the input stream. Increment the
pointer and add the fetched byte to the line checksum
*/
static unsigned long gethex(char **bt)
{
int x;
x = getnib(bt) << 4;
x |= getnib(bt);
hexsum += x;
return x;
}
/******************************************************************************
Get an unsigned short from the input stream, The pointer and the line checksum
are maintained.
*/
static unsigned long getshort(char **bt)
{
unsigned short ret;
ret = gethex(bt) << 8;
ret |= gethex(bt);
return ret;
}
/******************************************************************************
Load the specified Intel format hex file into memory as a binary
image. Returns the file loaded in 'prog' with the base and limit filled in
as im->lowaddress and im->highaddress respectively.
*/
void LoadHexFile(char *fn, unsigned char *prog, image_t *im, unsigned limit)
{
char *p1; // pointer to hex input text
FILE *ff = fopen(fn, "rb");
int lth; // line length byte
unsigned address, // current line address
offset; // 0 offset of first byte
int rt; // record type
unsigned char kh; // fetched byte from hex file
printf("Converting %s\n", fn);
lyne = (unsigned char*)malloc(LINE_SIZE);
im->lowaddress = 0xffff;
im->highaddress = 0;
while (fgets(p1 = lyne, LINE_SIZE, ff))
{
if (*p1++ != ':') // all good Intel hex file have this
{
break;
}
hexsum = 0;
lth = gethex(&p1); // fetch length of line
address = getshort(&p1); // fetch target address
if ((rt = gethex(&p1)) == RT_EOF) // fetch record type
{
break; // end of file
}
switch(rt)
{
default:
printf("Invalid record type %02x\n", rt);
getch();
break;
case RT_DATA: // data bytes
if (address < im->lowaddress)
{
assert(im->highaddress == 0);
im->lowaddress = address;
offset = address;
}
while (lth--)
{
kh = (unsigned char)gethex(&p1);
if ((address - offset) > limit)
{
printf("Hex file too large\n");
getch();
exit(0);
}
*(prog + address++ - offset) = kh;
}
if (address > im->highaddress)
{
im->highaddress = address;
}
break;
}
kh = (unsigned char)gethex(&p1);
if (hexsum & 0xff)
{
printf("Hex conversion error\n");
getch();
exit(0);
}
}
free(lyne);
fclose(ff);
}
/******************************************************************************
Convert the specified Intel format hex file <argv[1]> into memory as a binary
image. Saves the binary image as <argv[2]>.
*/
void main(int argc, char **argv)
{
image_t img;
FILE *out;
char *where = (char*)malloc(MAX_IMG_SZ);
memset(where, 0, MAX_IMG_SZ);
LoadHexFile(argv[1], where, &img, MAX_IMG_SZ);
out = fopen(argv[2], "wb");
fwrite(where, 1, img.highaddress - img.lowaddress, out);
fclose(out);
}

View File

@@ -0,0 +1,17 @@
set :F0:=..\isis\plm80
set :F1:=..\isis\utils
set :F2:=.
set :F3:=..\isis\asm80
..\isis\utils\isis :F0:plm80 :F2:bdos.plm
..\isis\utils\isis :F3:asm80 :F2:bdosi.src
..\isis\utils\isis :F1:link :F2:bdosi.obj,:F2:bdos.obj,:F1:plm80.lib to :F2:bdos.mod
del bdosi.obj
del bdos.obj
..\isis\utils\isis :F1:locate :F2:bdos.mod code(0800h) stacksize(0)
del bdos.mod
..\isis\utils\isis :F1:objhex :F2:bdos to :F2:bdos.hex
del bdos
..\tools\hexcon bdos.hex bdos.abs
del bdos.hex

View File

@@ -0,0 +1,7 @@
@echo off
set savepath=%path%
set path=..\tools2;%path%
rmac os2ccp
link os2ccp[l0]
set path=%savepath%
set savepath=