630 lines
18 KiB
C
630 lines
18 KiB
C
/*
|
|
|
|
Copyright (c) 2015-2017, John Forecast
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
JOHN FORECAST BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of John Forecast shall not
|
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from John Forecast.
|
|
|
|
*/
|
|
|
|
/* cdc1700_msos5.c: CDC1700 MSOS 5 trace and debugging support
|
|
*/
|
|
|
|
#include "cdc1700_defs.h"
|
|
|
|
extern uint16 M[], Preg, Areg, Qreg;
|
|
|
|
extern char INTprefix[];
|
|
|
|
extern uint16 doADDinternal(uint16, uint16);
|
|
|
|
/*
|
|
* Information about monitor requests.
|
|
*/
|
|
#define RQ_SYSDIRREAD 0 /* System directory read (monitor only) */
|
|
#define RQ_READ 1 /* Normal read */
|
|
#define RQ_WRITE 2 /* Normal write */
|
|
#define RQ_STATUS 3 /* I/O request status */
|
|
#define RQ_FREAD 4 /* Formatted read */
|
|
#define RQ_EXIT 5 /* Unprotected exit */
|
|
#define RQ_FWRITE 6 /* Formatted write */
|
|
#define RQ_LOADER 7 /* Relocatable binary loader */
|
|
#define RQ_TIMER 8 /* Schedule program with delay */
|
|
#define RQ_SCHDLE 9 /* Schedule program */
|
|
#define RQ_SPACE 10 /* Allocate core */
|
|
#define RQ_CORE 11 /* Unprotected core bounds */
|
|
#define RQ_RELEAS 12 /* Release core */
|
|
#define RQ_GTFILE 13 /* Access permanent file in program library */
|
|
#define RQ_MOTION 14 /* Tape motion */
|
|
#define RQ_TIMPT1 15 /* Schedule directory program with delay */
|
|
#define RQ_INDIR 16 /* Indirect (use another parameter list) */
|
|
#define RQ_PTNCOR 17 /* Allocate partitioned core */
|
|
#define RQ_SYSCHD 18 /* Schedule directory program */
|
|
#define RQ_DIRCHD 19 /* Enable/Disable system directory scheduling */
|
|
|
|
/*
|
|
* Masks for default fields in the first parameter word.
|
|
*/
|
|
#define D 0x4000 /* Part 1 request indicator */
|
|
#define RQ 0x3E00 /* Request code */
|
|
#define X 0x0100 /* Relative/indirect indicator */
|
|
#define RP 0x00F0 /* Request priority */
|
|
#define CP 0x000F /* Completion priority */
|
|
|
|
#define TELETYPE 0x04 /* Console TTY LU */
|
|
|
|
/*
|
|
* Well-known locations within MSOS 5.
|
|
*/
|
|
#define LIBLU 0x00C2 /* Library LU */
|
|
#define CREXTB 0x00E9 /* Extended communications region */
|
|
|
|
#define LOG1A 28 /* Offset to LOG1A table address */
|
|
|
|
/*
|
|
* Queueable requests have a completion address as the second parameter.
|
|
* Note that INDIR requests may or may not be queueable depending on the
|
|
* target parameter list.
|
|
*/
|
|
t_bool queueable[] = {
|
|
TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
|
|
TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE
|
|
};
|
|
|
|
const char *indent[] = {
|
|
"", " ", " ", " ", " ", " ", " ", " ", " "
|
|
};
|
|
|
|
const char mode[] = { 'B', 'A' };
|
|
const char luchr[] = { ' ', 'R', 'I', '?' };
|
|
const char rel[] = { '0', '1' };
|
|
const char part1[] = { '0', '1' };
|
|
const char exitind[] = { '0', '1' };
|
|
const char units[] = {
|
|
'0', '1', '2', '3', '?', '?', '?', '?',
|
|
'?', '?', '?', '?', '?', '?', '?', '?'
|
|
};
|
|
|
|
const char *density[] = {
|
|
"", "800 BPI", "556 BPI", "200 BPI", "1600 BPI", "???", "???", "???",
|
|
"???", "???", "???", "???", "???", "???", "???", "???"
|
|
};
|
|
|
|
const char *action[] = {
|
|
"", "BSR", "EOF", "REW", "UNL", "FSF", "BSF", "ADR",
|
|
"???", "???", "???", "???", "???", "???", "???", "???"
|
|
};
|
|
|
|
uint32 seqno = 0;
|
|
|
|
#define END(s) &s[strlen(s)]
|
|
|
|
/*
|
|
* Character representation.
|
|
*/
|
|
const char *charRep[128] = {
|
|
"<00>", "<01>", "<02?", "<03>", "<04>", "<05>", "<06>", "<07>",
|
|
"<08>", "<09>", "<0A>", "<0B>", "<0C>", "<0D>", "<0E>", "<0F>",
|
|
"<10>", "<11>", "<12>", "<13>", "<14>", "<15>", "<16>", "<17>",
|
|
"<18>", "<19>", "<1A>", "<1B>", "<1C>", "<1D>", "<1E>", "<1F>",
|
|
" ", "!", "\"", "#", "$", "%", "&", "'",
|
|
"(", ")", "*", "+", ",", "-", ".", "/",
|
|
"0", "1", "2", "3", "4", "5", "6", "7",
|
|
"8", "9", ":", ";", "<", "=", ">", "?",
|
|
"@", "A", "B", "C", "D", "E", "F", "G",
|
|
"H", "I", "J", "K", "L", "M", "N", "O",
|
|
"P", "Q", "R", "S", "T", "U", "V", "W",
|
|
"X", "Y", "Z", "[", "\\", "]", "^", "_",
|
|
"<60>", "<61>", "<62>", "<63>", "<64>", "<65>", "<66>", "<67>",
|
|
"<68>", "<69>", "<6A>", "<6B>", "<6C>", "<6D>", "<6E>", "<6F>",
|
|
"<70>", "<71>", "<72>", "<73>", "<74>", "<75>", "<76>", "<77>",
|
|
"<78>", "<79>", "<7A>", "<7B>", "<7C>", "<7D>", "<7E>", "<7F>",
|
|
};
|
|
|
|
/*
|
|
* Check if a logical unit is a mass storage device.
|
|
*/
|
|
t_bool isMassStorage(uint16 lu)
|
|
{
|
|
uint16 extbv4 = M[CREXTB];
|
|
uint16 log1a = M[extbv4 + LOG1A];
|
|
|
|
if ((lu > 0) && (lu <= M[log1a])) {
|
|
uint16 physDev = M[log1a + lu];
|
|
|
|
/*
|
|
* Check if equipment class is 2 (Mass storage)
|
|
*/
|
|
if ((M[physDev + 8] & 0x3800) == 0x1000)
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Get the mass storage sector address associated with a read/write
|
|
* request.
|
|
*/
|
|
uint32 getMSA(uint16 reqCode, uint16 param)
|
|
{
|
|
if (reqCode == RQ_SYSDIRREAD)
|
|
return M[param + 6];
|
|
|
|
if ((M[param] & D) == 0) {
|
|
uint16 sa = M[param + 5];
|
|
|
|
if ((M[param] & X) == 0) {
|
|
if ((sa & 0x8000) != 0) {
|
|
sa &= 0x7FFF;
|
|
return (M[sa + 1] << 15) | (M[sa + 2] & 0x7FFF);
|
|
}
|
|
} else {
|
|
if ((sa & 0x8000) != 0) {
|
|
sa = param + (sa & 0x7FFF);
|
|
return (M[sa + 1] << 15) | (M[sa + 2] & 0x7FFF);
|
|
}
|
|
}
|
|
}
|
|
return (M[param + 6] << 15) | (M[param + 7] & 0x7FFF);
|
|
}
|
|
|
|
/*
|
|
* Parameter conversion routines. Based on the assembly source code of MSOS 5
|
|
* available on bitsavers.
|
|
*/
|
|
|
|
/*
|
|
* Convert Logical Unit parameter to absolute value
|
|
*/
|
|
static uint16 luabs(uint16 param, uint16 lu, uint16 a)
|
|
{
|
|
switch (a) {
|
|
case ' ':
|
|
break;
|
|
|
|
case 'R':
|
|
if ((lu & 0x200) != 0)
|
|
lu |= 0xFC00;
|
|
lu = doADDinternal(param, lu);
|
|
break;
|
|
|
|
case 'I':
|
|
lu = M[lu];
|
|
if ((lu & 0x8000) != 0)
|
|
lu = doADDinternal(lu, 0x7FFF);
|
|
break;
|
|
|
|
case 3:
|
|
lu = 0xFFFF;
|
|
break;
|
|
}
|
|
return lu;
|
|
}
|
|
|
|
/*
|
|
* Convert Starting Address parameter to absolute value
|
|
*/
|
|
static uint16 spabs(uint16 param)
|
|
{
|
|
uint16 sa = M[param + 5];
|
|
|
|
/*
|
|
* If the D bit is set, the starting address must be absolute.
|
|
*/
|
|
if ((M[param] & D) != 0)
|
|
return sa;
|
|
|
|
if ((M[param] & X) == 0) {
|
|
if ((sa & 0x8000) != 0)
|
|
sa = M[sa & 0x7FFF];
|
|
} else {
|
|
if ((sa & 0x8000) != 0)
|
|
sa = param + (M[param + (sa & 0x7FFF)] & 0x7FFF);
|
|
else sa = param + sa;
|
|
}
|
|
return sa;
|
|
}
|
|
|
|
/*
|
|
* Convert Number of words to absolute value
|
|
*/
|
|
static uint16 npabs(uint16 param)
|
|
{
|
|
uint16 nw = M[param + 4];
|
|
|
|
/*
|
|
* If the D bit is set, the number of words must be absolute.
|
|
*/
|
|
if ((M[param] & D) != 0)
|
|
return nw;
|
|
|
|
if ((nw & 0x8000) != 0) {
|
|
nw = nw + (((M[param] & X) != 0) ? (param & 0x7FFF) : 0);
|
|
if ((nw & 0x8000) != 0)
|
|
nw = doADDinternal(nw, 0x7FFF);
|
|
nw = M[nw];
|
|
if ((nw & 0x8000) != 0)
|
|
nw = doADDinternal(nw, 0x7FFF);
|
|
}
|
|
return nw;
|
|
}
|
|
|
|
/*
|
|
* Convert completion address to absolute value
|
|
*/
|
|
static char *cpabs(uint16 param, char *buf)
|
|
{
|
|
uint16 ca = M[param + 1];
|
|
|
|
/*
|
|
* Only absolutize the completion address if one is specified.
|
|
*/
|
|
if (ca != 0) {
|
|
/*
|
|
* If the D bit is set, the completion address must be absolute.
|
|
*/
|
|
if ((M[param] & D) == 0) {
|
|
if ((ca & 0x8000) != 0) {
|
|
/*
|
|
* If negative, System directory reference
|
|
*/
|
|
sprintf(buf, "SYSDIR(%u)", ca & 0x7FFF);
|
|
return buf;
|
|
} else {
|
|
if ((M[param] & X) != 0) {
|
|
if ((param & 0x8000) == 0)
|
|
param = doADDinternal(param, 0x8000);
|
|
ca = doADDinternal(ca, param);
|
|
}
|
|
}
|
|
if ((ca & 0x8000) != 0)
|
|
ca = doADDinternal(ca, 0x7FFF);
|
|
}
|
|
}
|
|
sprintf(buf, "$%04X", ca);
|
|
return buf;
|
|
}
|
|
|
|
/*
|
|
* Describe motion parameters
|
|
*/
|
|
static void motion(uint16 param, char *d)
|
|
{
|
|
uint16 commands = M[param + 4];
|
|
|
|
if ((commands & 0xF) != 0)
|
|
sprintf(END(d), " Density = %s\r\n", density[commands & 0xF]);
|
|
|
|
if ((commands & 0x8000) == 0) {
|
|
if ((commands & 0xF000) != 0) {
|
|
sprintf(END(d), " Actions = %s", action[(commands & 0xF000) >> 12]);
|
|
if ((commands & 0xF00) != 0) {
|
|
sprintf(END(d), ",%s", action[(commands & 0xF00) >> 8]);
|
|
if ((commands & 0xF0) != 0)
|
|
sprintf(END(d), ",%s", action[(commands & 0xF0) >> 4]);
|
|
}
|
|
sprintf(END(d), "\r\n");
|
|
}
|
|
} else {
|
|
sprintf(END(d), " Repeat = %s, %u times\r\n",
|
|
action[(commands & 0x7000) >> 12], commands & 0xFFF);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Generate a test representation of a write to the console teletype. If the
|
|
* text is too long to fix (> 50 chars) it will be truncated.
|
|
*/
|
|
#define MAXTEXT 50
|
|
|
|
char *textRep(uint16 start, uint16 len)
|
|
{
|
|
int i;
|
|
static char text[64];
|
|
size_t text_space = sizeof (text) - 1;
|
|
|
|
text[0] = '\0';
|
|
|
|
for (i = 0; (i < (2 * len)) && (text_space >= MAXTEXT); i++) {
|
|
uint16 ch = M[start];
|
|
|
|
if ((i & 1) == 0)
|
|
ch >>= 8;
|
|
else start++;
|
|
ch &= 0x7F;
|
|
|
|
strncpy(&text[strlen(text)], charRep[ch], text_space);
|
|
text_space -= strlen(charRep[ch]);
|
|
}
|
|
return text;
|
|
}
|
|
|
|
/*
|
|
* Dump MSOS5 request information.
|
|
*/
|
|
void MSOS5request(uint16 param, uint16 depth)
|
|
{
|
|
uint16 reqCode = (M[param] & RQ) >> 9;
|
|
char partOne = part1[(M[param] & D) >> 14];
|
|
char relative = rel[(M[param] & X) >> 8];
|
|
uint16 completion = M[param + 1];
|
|
const char *request;
|
|
char parameters[128], details[512];
|
|
char luadr;
|
|
uint16 lu, abslu, abss, abswd, i;
|
|
uint32 sector;
|
|
t_bool secondary = FALSE;
|
|
|
|
parameters[0] = '\0';
|
|
details[0] = '\0';
|
|
|
|
if (depth == 0) {
|
|
/*
|
|
* Check for INDIR request with 15-bit addressing.
|
|
*/
|
|
if ((M[param] & 0x8000) != 0) {
|
|
fprintf(DBGOUT, "%sMSOS5(%06u): [RQ: $%04X]%sINDIR $%04X,0\r\n",
|
|
INTprefix, seqno++, param, indent[depth & 0x7],
|
|
M[param] & 0x7FFF);
|
|
MSOS5request(M[param] & 0x7FFF, depth + 1);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ((M[param] & 0x8000) != 0) {
|
|
/*
|
|
* Secondary scheduler call
|
|
*/
|
|
secondary = TRUE;
|
|
reqCode = RQ_SCHDLE;
|
|
}
|
|
/*
|
|
* Check for invalid monitor requests
|
|
*/
|
|
if (reqCode > RQ_DIRCHD) {
|
|
fprintf(DBGOUT, "%sUnknown MSOS5 request (code %u)\r\n",
|
|
INTprefix, reqCode);
|
|
return;
|
|
}
|
|
|
|
if (queueable[reqCode]) {
|
|
char temp[16];
|
|
|
|
if (secondary)
|
|
sprintf(details, " Compl = $%04X\r\n", M[param + 1]);
|
|
else sprintf(details, " Compl = %s\r\n", cpabs(param, temp));
|
|
}
|
|
|
|
switch (reqCode) {
|
|
case RQ_SYSDIRREAD:
|
|
request = "*SYSDIRREAD*";
|
|
goto rw;
|
|
|
|
case RQ_READ:
|
|
request = "READ";
|
|
goto rw;
|
|
|
|
case RQ_WRITE:
|
|
request = "WRITE";
|
|
goto rw;
|
|
|
|
case RQ_STATUS:
|
|
request = "STATUS";
|
|
luadr = luchr[(M[param + 1] & 0xC00) >> 10];
|
|
lu = M[param + 1] & 0x3FF;
|
|
sprintf(parameters, "%u, 0, %c, 0, %c", lu, luadr, partOne);
|
|
|
|
sprintf(END(details), " LU = %u\r\n", luabs(param, lu, luadr));
|
|
break;
|
|
|
|
case RQ_FREAD:
|
|
request = "FREAD";
|
|
goto rw;
|
|
|
|
case RQ_EXIT:
|
|
request = "EXIT";
|
|
/* No parameters */
|
|
break;
|
|
|
|
case RQ_FWRITE:
|
|
request = "FWRITE";
|
|
rw:
|
|
luadr = luchr[(M[param + 3] & 0xC00) >> 10];
|
|
lu = M[param + 3] & 0x3FF;
|
|
sprintf(parameters, "%u, $%04X, $%04X, %u, %c, %u, %u, %c, %c, %c",
|
|
lu, completion, M[param + 5], M[param + 4],
|
|
mode[(M[param + 3] & 0x1000) >> 12],
|
|
(M[param] & RP) >> 4, M[param] & CP,
|
|
luadr, relative, partOne);
|
|
|
|
if (reqCode == RQ_SYSDIRREAD) {
|
|
abslu = M[LIBLU];
|
|
abss = completion;
|
|
} else {
|
|
abslu = luabs(param, lu, luadr);
|
|
abss = spabs(param);
|
|
}
|
|
abswd = npabs(param);
|
|
|
|
sprintf(END(details), " LU = %u\r\n", abslu);
|
|
sprintf(END(details), " Start = $%04X\r\n", abss);
|
|
sprintf(END(details), " Words = %u ($%04X)\r\n", abswd, abswd);
|
|
|
|
if (isMassStorage(abslu))
|
|
sprintf(END(details), " MSA = $%08X\r\n", getMSA(reqCode, param));
|
|
|
|
/*
|
|
* If this a write to the console teletype, generate a partial
|
|
* representation of the text being written so that we can correlate
|
|
* our current location with the output.
|
|
*/
|
|
if (abslu == TELETYPE) {
|
|
if ((M[param + 3] & 0x1000) != 0) {
|
|
if ((reqCode == RQ_WRITE) || (reqCode == RQ_FWRITE)) {
|
|
sprintf(END(details), " Text = %s\r\n",
|
|
textRep(spabs(param), npabs(param)));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RQ_LOADER:
|
|
request = "LOADER";
|
|
sprintf(parameters, "[A: %04X, Q: %04X, lu: %u, t: %u, tna: %04X]",
|
|
Areg, Qreg, (Areg & 0xFFF0) >> 4, Areg & 0xF, Qreg);
|
|
break;
|
|
|
|
case RQ_TIMER:
|
|
request = "TIMER";
|
|
sprintf(parameters, "$%04X, %u, %c, %u, %c, %c",
|
|
M[param + 1], M[param] & 0xF,
|
|
relative, M[param + 2],
|
|
units[(M[param] & 0xF0) >> 4], partOne);
|
|
break;
|
|
|
|
case RQ_SCHDLE:
|
|
request = secondary ? "Secondary SCHDLE" : "SCHDLE";
|
|
sprintf(parameters, "$%04X, %u, %c, %c",
|
|
M[param + 1], M[param] & CP, relative, partOne);
|
|
break;
|
|
|
|
case RQ_SPACE:
|
|
request = "SPACE";
|
|
sprintf(parameters, "%u, $%04X, %u, %u, %c, %c",
|
|
M[param + 4], M[param + 1],
|
|
(M[param] & RP) >> 4, M[param] & CP, relative, partOne);
|
|
break;
|
|
|
|
case RQ_CORE:
|
|
request = "CORE";
|
|
sprintf(parameters, "[A: %04X, Q: %04X]", Areg, Qreg);
|
|
break;
|
|
|
|
case RQ_RELEAS:
|
|
request = "RELEAS";
|
|
sprintf(parameters, "$%04X, %c, %c, %c",
|
|
M[param + 1], exitind[M[param] & 0x01], relative, partOne);
|
|
break;
|
|
|
|
case RQ_GTFILE:
|
|
request = "GTFILE";
|
|
sprintf(parameters, "$%04X, $%04X, $%04X, $%04X, $%04X, %c, %u, %u, %c",
|
|
M[param + 1], M[param + 7], M[param + 5],
|
|
M[param + 4], M[param + 6], relative,
|
|
(M[param] & RP) >> 4, M[param] & CP, partOne);
|
|
|
|
/*
|
|
* The reference manual does not correctly document the GTFILE request.
|
|
* According to the MSOS 5.0 source code, there is a 10th parameter
|
|
* which is used in calculating the address of the name block.
|
|
*/
|
|
i = M[param + 7];
|
|
if ((i & 0x8000) == 0) {
|
|
i = doADDinternal(M[param + 10], i);
|
|
if ((M[param] & D) == 0) {
|
|
i = doADDinternal(i, 0x8000);
|
|
i &= 0x7FFF;
|
|
}
|
|
} else i &= 0x7FFF;
|
|
|
|
sector = (M[param + 8] << 16) | M[param + 9];
|
|
|
|
if (sector != 0)
|
|
sprintf(END(details), " Sector = %u\r\n", sector);
|
|
else sprintf(END(details), " Name = %c%c%c%c%c%c\r\n",
|
|
(M[i] >> 8) & 0xFF, M[i] & 0xFF,
|
|
(M[i + 1] >> 8) & 0xFF, M[i + 1] & 0xFF,
|
|
(M[i + 2] >> 8) & 0xFF, M[i + 2] & 0xFF);
|
|
break;
|
|
|
|
case RQ_MOTION:
|
|
request = "MOTION";
|
|
luadr = luchr[(M[param + 3] & 0xC00) >> 10];
|
|
lu = M[param + 3] & 0x3FF;
|
|
sprintf(parameters, "%u, $%04X, %u, %u, %u, %u, %u, %u, %c, %c, %c, %c",
|
|
lu, M[param + 1],
|
|
(M[param + 4] & 0xF000) >> 12,
|
|
(M[param + 4] & 0xF00) >> 8,
|
|
(M[param + 4] & 0xF0) >> 4, M[param + 4] & 0xF,
|
|
(M[param] & RP) >> 4, M[param] & CP,
|
|
luadr, relative, partOne,
|
|
mode[(M[param + 3] & 0x1000) >> 12]);
|
|
|
|
sprintf(END(details), " LU = %u\r\n", luabs(param, lu, luadr));
|
|
motion(param, details);
|
|
break;
|
|
|
|
case RQ_TIMPT1:
|
|
request = "TIMPT1";
|
|
sprintf(parameters, "$%04X, %u, 0, %u, %c",
|
|
M[param + 1], M[param] & 0xF,
|
|
M[param + 2], units[(M[param] & 0xF0) >> 4]);
|
|
break;
|
|
|
|
case RQ_INDIR:
|
|
fprintf(DBGOUT, "%sMSOS5(%06u): [RQ: $%04X]%sINDIR $%04X,1\r\n",
|
|
INTprefix, seqno++, param, indent[depth & 0x7], M[param + 1]);
|
|
MSOS5request(M[param + 1], depth + 1);
|
|
return;
|
|
|
|
case RQ_PTNCOR:
|
|
request = "PTNCOR";
|
|
sprintf(parameters, "%u, $%04X, %u, %u, %u, %c, %c",
|
|
M[param + 4], M[param + 1], M[param + 5],
|
|
(M[param] & RP) >> 4, M[param] & CP,
|
|
relative, partOne);
|
|
break;
|
|
|
|
case RQ_SYSCHD:
|
|
request = "SYSCHD";
|
|
sprintf(parameters, "$%04X, %u",
|
|
M[param + 1], M[param & 0xF]);
|
|
break;
|
|
|
|
case RQ_DIRCHD:
|
|
switch (M[param] & 0xFF) {
|
|
case 0:
|
|
request = "ENSCHD";
|
|
sprintf(parameters, "$%04X", M[param + 1]);
|
|
break;
|
|
|
|
case 0xFF:
|
|
request = "DISCHD";
|
|
sprintf(parameters, "$%04X", M[param + 1]);
|
|
break;
|
|
|
|
default:
|
|
request = "SYSCHD";
|
|
strcpy(parameters, "Invalid directory scheduling code");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
request = "*Unknown*";
|
|
sprintf(parameters, "Request code: %d", (M[param] & 0x3E00) >> 9);
|
|
break;
|
|
}
|
|
fprintf(DBGOUT, "%sMSOS5(%06u): [RQ: $%04X]%s%s %s\r\n",
|
|
INTprefix, seqno++, param, indent[depth & 0x7], request, parameters);
|
|
if (details[0] != '\0')
|
|
fprintf(DBGOUT, "%s\r\n", details);
|
|
}
|