mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-22 16:04:18 +00:00
163 lines
4.0 KiB
C
163 lines
4.0 KiB
C
/****************************************************************
|
|
* *
|
|
* CP/M-68K Loader *
|
|
* *
|
|
* This is the main routine for the CP/M-68K Loader. *
|
|
* It has one entry point, ldcpm, which is called from *
|
|
* the assembly language routine called startld found in *
|
|
* ldrif.s. startld just sets up the stack. *
|
|
* *
|
|
* Configured for Alcyon C on the VAX *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "stdio.h" /* Standard I/O declarations */
|
|
|
|
#define ALCYON TRUE /* TRUE if compiling with the ALCYON 68K C compiler */
|
|
#define SECLEN 128 /* CP/M sector length */
|
|
|
|
|
|
/* Declare EXTERN functions */
|
|
|
|
EXTERN WORD _bdos(); /* Loader BDOS entry point */
|
|
EXTERN startld(); /* Assembly routine to set up stack & retry */
|
|
EXTERN BYTE *bios1(); /* bios entry point for get segment table */
|
|
EXTERN move(); /* general purpose byte mover */
|
|
|
|
|
|
#define conout(ch) _bdos(2,ch)
|
|
#define seldsk(dsk) _bdos(14,dsk)
|
|
#define open(fcbp) _bdos(15,0,fcbp)
|
|
#define read(fcbp) _bdos(20,0,fcbp)
|
|
#define setdma(p) _bdos(26,0,p)
|
|
|
|
|
|
/* Define the data structures used in ldcpm */
|
|
struct fcb
|
|
{
|
|
UBYTE drvcode; /* drive code, must be 0 for loader BDOS */
|
|
/* (auto disk select not supported) */
|
|
UBYTE fname[11]; /* includes file name and type fields */
|
|
UBYTE sys_info[4]; /* ex, s1, s2, rc. These are don't cares */
|
|
UBYTE dskmap[16]; /* disk map, also a don't care */
|
|
UBYTE cur_rec; /* current record field */
|
|
};
|
|
|
|
struct hdr
|
|
{
|
|
WORD magic; /* magic number. We only recognize 0x601a */
|
|
LONG size[5]; /* sizes of code, data, bss, sym tbl, stack */
|
|
BYTE *tstart; /* start address of text segment */
|
|
WORD rlbflg; /* relocation bits suppressed flag */
|
|
};
|
|
|
|
struct segtbl
|
|
{ /* memory segment table from LDRBIOS */
|
|
WORD entrys; /* number of segments, must be 1 */
|
|
BYTE *start; /* low memory address */
|
|
LONG length; /* length of segment */
|
|
};
|
|
|
|
|
|
/**********************/
|
|
/* Global Variables */
|
|
/**********************/
|
|
|
|
BYTE buffer[SECLEN]; /* 128 byte dma buffer to read program headers */
|
|
|
|
/* We need 1 FCB to read CPM.SYS. */
|
|
/* Unfortunately, due to a bug in the Alcyon compiler, we can't initialize */
|
|
/* them in a straightforward way. So: */
|
|
/*sw No longer true. Deleted klutz. */
|
|
|
|
struct fcb cpmfcb =
|
|
{ 0, /* drive code */
|
|
'C','P','M',' ',' ',' ',' ',' ','S','Y','S'
|
|
};
|
|
|
|
/**************************/
|
|
/* Utility Routines */
|
|
/**************************/
|
|
|
|
pstring(p)
|
|
/* print string */
|
|
REG BYTE *p;
|
|
{
|
|
while (*p) conout(*p++);
|
|
}
|
|
|
|
|
|
badload(errtype)
|
|
/* Load failed. Print message and try again */
|
|
REG WORD errtype;
|
|
{
|
|
REG WORD i;
|
|
|
|
switch (errtype)
|
|
{
|
|
case 0: pstring("\r\nBoot error.");
|
|
startld();
|
|
|
|
case 1: pstring("\n\rOpen or Read error on ");
|
|
break;
|
|
|
|
case 2: pstring("\n\rBad file format on ");
|
|
}
|
|
pstring("CPM.SYS");
|
|
startld();
|
|
}
|
|
|
|
|
|
/********************
|
|
* load subroutine *
|
|
********************/
|
|
|
|
BYTE *load(fcbp)
|
|
/* load the file pointed to by fcbp and return pointer to load point */
|
|
REG struct fcb *fcbp;
|
|
{
|
|
REG BYTE *p;
|
|
REG struct hdr *hp;
|
|
REG LONG length;
|
|
|
|
setdma( buffer );
|
|
if ( open(fcbp) >= 255 ) badload(1);
|
|
fcbp->cur_rec = 0;
|
|
if ( read(fcbp) ) badload(1);
|
|
hp = buffer;
|
|
if ( (hp->magic != 0x601a) || ! (hp->rlbflg) )
|
|
badload(2);
|
|
p = hp->tstart;
|
|
length = hp->size[0] + hp->size[1];
|
|
move(&buffer[sizeof *hp], p, SECLEN - (sizeof *hp));
|
|
/* move the first record minus header to load point */
|
|
p += SECLEN - (sizeof *hp);
|
|
length -= SECLEN - (sizeof *hp);
|
|
while (length > 0L)
|
|
{
|
|
setdma(p);
|
|
if ( read(fcbp) ) badload(1);
|
|
p += SECLEN;
|
|
length -= SECLEN;
|
|
}
|
|
return(hp->tstart);
|
|
}
|
|
|
|
|
|
/***************************
|
|
* ldcpm main routine *
|
|
***************************/
|
|
|
|
ldcpm()
|
|
|
|
{
|
|
WORD (*gocpm)();
|
|
|
|
if (seldsk(0)) badload(0);
|
|
gocpm = load(&cpmfcb); /* load the CP/M system */
|
|
pstring("\r\n\nCP/M-68K(tm) Version 1.2 03/20/84 ");
|
|
pstring("\n\rCopyright (c) 1984 Digital Research, Inc.\r\n\n");
|
|
(*gocpm)(); /* jump to the CCP */
|
|
}
|
|
|