Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM.Z80.DE/PERSONAL/PCPM-86/BDOS 4.1/cmdio.c
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

145 lines
3.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cmdio.h"
static byte zeroes[16];
void zero_cmd(cmd_desc *cmdfile)
{
cmdfile->cs = cmdfile->ds = NULL;
cmdfile->cs_base = cmdfile->ds_base = 0;
cmdfile->cs_len = cmdfile->ds_len = 0;
cmdfile->cs_max = cmdfile->ds_max = 0;
}
void free_cmd (cmd_desc *cmdfile)
{
if (cmdfile->ds) free(cmdfile->ds);
if (cmdfile->cs) free(cmdfile->cs);
zero_cmd(cmdfile);
}
char *alloc_cmd(cmd_desc *cmdfile, long cs_len, long ds_len)
{
if (!cs_len || !ds_len) return "cs_len or ds_len is 0.";
cmdfile->cs = malloc(cs_len);
cmdfile->ds = malloc(ds_len);
if (!cmdfile->ds || !cmdfile->cs)
{
free_cmd(cmdfile);
return "Out of memory.";
}
return NULL;
}
char *load_cmd(char *filename, cmd_desc *cmdfile)
{
FILE *fp;
char *boo;
byte cmd_header[128];
fp = fopen(filename, "rb");
if (!fp) return "Failed to open file.";
if (fread(cmd_header, 1, sizeof(cmd_header), fp) < sizeof(cmd_header))
{
fclose(fp);
return "Too short to be a CMD file.";
}
cmdfile->cs_len = peekw(cmd_header, 1);
cmdfile->cs_base = peekw(cmd_header, 3);
cmdfile->cs_max = peekw(cmd_header, 5);
cmdfile->ds_len = peekw(cmd_header, 10);
cmdfile->ds_base = peekw(cmd_header, 12);
cmdfile->ds_max = peekw(cmd_header, 14);
if (!cmdfile->cs_len || !cmdfile->ds_len)
{
fclose(fp);
return "Not a 2-segment CMD file";
}
boo = alloc_cmd(cmdfile, 16 * cmdfile->cs_max, 16 * cmdfile->ds_max);
if (boo)
{
fclose(fp);
return boo;
}
if (fread(cmdfile->cs, 16, cmdfile->cs_len, fp) < cmdfile->cs_len)
{
fclose(fp);
free_cmd(cmdfile);
return "Failed to load code segment.";
}
if (fread(cmdfile->ds, 16, cmdfile->ds_len, fp) < cmdfile->ds_len)
{
fclose(fp);
free_cmd(cmdfile);
return "Failed to load data segment.";
}
fclose(fp);
cmdfile->cs_len *= 16L;
cmdfile->ds_len *= 16L;
cmdfile->cs_max *= 16L;
cmdfile->ds_max *= 16L;
return NULL;
}
void pokew(byte *base, word a, word v)
{
base[a ] = (v) & 0xFF;
base[a+1] = (v >> 8) & 0xFF;
}
word peekw(byte *base, word a)
{
return base[a] | (((word)base[a+1]) << 8);
}
char *save_cmd(char *cmdname, cmd_desc *cmdfile, int absolute)
{
FILE *fp;
word csparas, cmparas;
word dsparas, dmparas;
byte header[128];
csparas = cmdfile->cs_len >> 4;
dsparas = cmdfile->ds_len >> 4;
cmparas = cmdfile->cs_max >> 4;
dmparas = cmdfile->ds_max >> 4;
memset(header, 0, sizeof(header));
header[0] = 1; /* Code segment */
pokew(header, 1, csparas);
if (absolute) pokew(header, 3, cmdfile->cs_base);
pokew(header, 5, cmparas);
header[9] = 2; /* Data segment */
pokew(header, 10, dsparas);
if (absolute) pokew(header, 12, cmdfile->ds_base);
pokew(header, 14, dmparas);
fp = fopen(cmdname, "wb");
if (!fp)
{
return "Cannot open file to write.";
}
if (fwrite(header, 1, 128, fp) < 128 ||
fwrite(cmdfile->cs, 16, csparas, fp) < csparas ||
fwrite(cmdfile->ds, 16, dsparas, fp) < dsparas)
{
fclose(fp);
return "Error writing to CMD file";
}
/* Pack out to a multiple of 128 bytes */
while ((csparas + dsparas) & 7)
{
fwrite(zeroes, 1, 16, fp);
++dsparas;
}
fclose(fp);
return NULL;
}