mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-26 09:54:20 +00:00
Upload
Digital Research
This commit is contained in:
BIN
CONTRIBUTIONS/cpm1.4/tools/EXTRACT.EXE
Normal file
BIN
CONTRIBUTIONS/cpm1.4/tools/EXTRACT.EXE
Normal file
Binary file not shown.
BIN
CONTRIBUTIONS/cpm1.4/tools/HEXCON.EXE
Normal file
BIN
CONTRIBUTIONS/cpm1.4/tools/HEXCON.EXE
Normal file
Binary file not shown.
253
CONTRIBUTIONS/cpm1.4/tools/extract.c
Normal file
253
CONTRIBUTIONS/cpm1.4/tools/extract.c
Normal 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);
|
||||
}
|
||||
3
CONTRIBUTIONS/cpm1.4/tools/getbdos.bat
Normal file
3
CONTRIBUTIONS/cpm1.4/tools/getbdos.bat
Normal 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
|
||||
4
CONTRIBUTIONS/cpm1.4/tools/getccp.bat
Normal file
4
CONTRIBUTIONS/cpm1.4/tools/getccp.bat
Normal 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
|
||||
|
||||
10
CONTRIBUTIONS/cpm1.4/tools/getcpm.bat
Normal file
10
CONTRIBUTIONS/cpm1.4/tools/getcpm.bat
Normal 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
|
||||
|
||||
176
CONTRIBUTIONS/cpm1.4/tools/hexcon.c
Normal file
176
CONTRIBUTIONS/cpm1.4/tools/hexcon.c
Normal 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);
|
||||
}
|
||||
17
CONTRIBUTIONS/cpm1.4/tools/makebdos.bat
Normal file
17
CONTRIBUTIONS/cpm1.4/tools/makebdos.bat
Normal 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
|
||||
|
||||
|
||||
7
CONTRIBUTIONS/cpm1.4/tools/makeccp.bat
Normal file
7
CONTRIBUTIONS/cpm1.4/tools/makeccp.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
set savepath=%path%
|
||||
set path=..\tools2;%path%
|
||||
rmac os2ccp
|
||||
link os2ccp[l0]
|
||||
set path=%savepath%
|
||||
set savepath=
|
||||
Reference in New Issue
Block a user