home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
recreation
/
zipdebug
/
b055s
/
c
/
ZIP
< prev
next >
Wrap
Text File
|
1993-06-29
|
195KB
|
8,029 lines
/* Output from p2c, the Pascal-to-C translator */
/* From input file "pas.ZIP" */
#include "p2c/p2c.h"
#ifndef ZIPEXT_H
#include "h.zip_ext"
#endif
/* Abort current command */
#define InterpreterNumber 6
#define InterpreterChar 'n'
#define Date "29-Jun-93"
#define Debugging false
#define MaxSpecTxtAdrsPageNo 1
#define MaxSpecTxtPageNo 3
#define MaxEntryPointCnt 1999
#define MaxStack 511
#define MaxMaxNumWords 70
#define MaxScreenWidth 256
#define MaxLineIndex 255
#define HighByteMask 65280
#define IntToCardConst 0
#define MaxPageNo 2047
#define MaxSubPageNo 0
#define MinMemSpace 4096
#define PrinterName "Listing"
typedef Char anAddrString[80];
typedef enum {
NoError, IllMultiOpdOp, IllNoOpdOp, IllTwoOpdOp, IllOneOpdOp,
StackUnderflow, StackOverflow, IllObjDataLoad, DivideByZero, MissingOpd,
MissingObjData, IllObjPropertyStore, IllZCodeType, NotImplemented,
KeyboardBreak, BreakPoint, OutputBufferUndefined, PC_Overflow, PC_Underflow,
TooManySeparators, TooManyLocalVariables, TooManyParameters, IllNumOperands,
IllOutputChar, IllScreenMode, NoPrinter, IllOutputMode
} InternalErrors;
typedef int CharSet[9];
typedef enum {
Nothing, Quit, NewAdv, Info, Help, VerifyCode, DumpOption, List, TextList,
GoSub, cDumpBytes, DumpWords, ListEntryPoints, ListObject, ListVocabulary,
ListZState, ListReg, Step, Run, Trace, Break, ModifyWords, ModifyBytes,
BPT_Cmd, SwitchToStep, SwitchToTrace, ListCalls
} Commands;
typedef enum {
NoDump, CodeDump, TextDump, UnpackedDump
} DumpStates;
typedef enum {
CallNever, CallKeyPress, CallTimeOut
} CallEvents;
typedef struct tMiscInfo {
uchar CodeType; /* $00 */
uchar ConfigFlags; /* $01 */
uchar ReleaseHigh; /* $02 */
uchar ReleaseLow; /* $03 */
uchar NumReadWriteBytesHigh; /* $04 */
uchar NumReadWriteBytesLow; /* $05 */
uchar StartPageNo; /* $06 */
uchar StartIndex; /* $07 */
uchar VocabPageNo; /* $08 */
uchar VocabPageIndex; /* $09 */
uchar ObjPageNo; /* $0A */
uchar ObjPageIndex; /* $0B */
uchar DataPageNo; /* $0C */
uchar DataPageIndex; /* $0D */
uchar SaveStateSizeHigh; /* $0E */
uchar SaveStateSizeLow; /* $0F */
uchar ScriptStatusHigh; /* $10 */
uchar ScriptStatusLow; /* $11 */
Char SerialNumber[6];
uchar SpecialPageNo; /* $18 */
uchar SpecialIndex; /* $19 */
uchar EndPageNo; /* $1A */
uchar EndPageIndex; /* $1B */
uchar ChkSumHigh; /* $1C */
uchar ChkSumLow; /* $1D */
uchar mInterpreterNumber; /* $1E */
uchar mInterpreterVersion; /* $1F */
uchar ScreenHeight; /* $20 */
uchar ScreenWidth; /* $21 */
uchar Left; /* $22 */
uchar Right; /* $23 */
uchar Top; /* $24 */
uchar Bottom; /* $25 */
uchar Unknown1; /* $26 */
uchar Unknown2; /* $27 */
uchar CodeStartPageNo; /* $28 */
uchar CodeStartIndex; /* $29 */
uchar Unused13; /* $2A */
uchar Unused14; /* $2B */
uchar Unknown3; /* $2C */
uchar Unknown4; /* $2D */
uchar Unknown5; /* $2E */
uchar Unused21; /* $2F */
uchar Unused22; /* $30 */
uchar Unused23; /* $31 */
uchar Unused24; /* $32 */
uchar Unused25; /* $33 */
uchar Unused26; /* $34 */
uchar Unknown6; /* $35 */
uchar Unused3[0xca];
} tMiscInfo;
typedef enum {
OntoScreen, IntoBuffer, ToStoryOutput
} OutputTypes;
typedef enum {
FromDC, FromIPC
} SourceTypes;
typedef enum {
UndefinedBPT, UserBPT, RunBPT, TraceBPT
} BPT_Types;
typedef struct aBPT *PtrBPT;
typedef struct aBPT {
int BPT_PageNo;
int BPT_PageIndex;
int HitCnt;
int BPT_No;
int OrgByte1;
int OrgByte2;
int OrgByte3;
PtrBPT NextBPT;
char BPT_Type;
} aBPT;
typedef union Registers {
int a[16];
struct {
int r0;
int r1;
int r2;
int r3;
int r4;
int r5;
int r6;
int r7;
int r8;
int r9;
int r10;
int r11;
int r12;
int r13;
int r14;
int r15;
} U1;
} Registers;
typedef union Operands {
int a[8];
struct {
int s0;
int s1;
int s2;
int s3;
int s4;
int s5;
int s6;
int s7;
} U1;
} Operands;
typedef int CountArray[256];
typedef aPage StoryFileBuffer[MaxSubPageNo + 1];
typedef Char aWord[9];
typedef ShortInteger aPackedWord[3];
Static Char CodeVersion;
Static Char StoryName[256];
Static tMiscInfo MiscInfo;
Static int WordNumChars;
Static int ObjRecSize;
Static int ObjOffset;
Static int ReleaseNo;
Static int PageCnt;
Static uchar *PagePtrs[MaxPageNo + 1];
Static uchar *DataPagePtrs[MaxPageNo + 1];
Static int DC_PageNo;
Static int DC_PageIndex;
Static int OldPageNo;
Static int OldIndex;
Static int BackPageNo;
Static int BackIndex;
Static int EndPageNo;
Static int EndPageIndex;
Static int TextPageNo;
Static int TextPageIndex;
Static int OldTextPageNo;
Static int OldTextPageIndex;
Static int BackTxtPageNo;
Static int BackTxtIndex;
Static int CodeEndPageIndex;
Static int CodeEndPageNo;
Static int InstPageNo;
Static int InstPageIndex;
Static int NewInstPageNo;
Static int NewInstPageIndex;
Static int EndIPC_PageNo;
Static int EndIPC_PageIndex;
Static int BackIPC_PageNo;
Static int BackIPC_PageIndex;
Static int OldIPC_PageNo;
Static int OldIPC_PageIndex;
Static int BPT_PageNo;
Static int BPT_PageIndex;
Static int FirstInstPageNo;
Static int FirstInstPageIndex;
Static boolean DisWithIds;
Static boolean DisBPTs;
Static boolean Statistics;
Static boolean RestartOperations;
Static boolean ChkLineChars;
Static boolean WriteDump;
Static char GlobalDumpState;
Static int DumpCnt;
Static int LineCnt;
Static Char Dump[256];
Static Char BreakKey;
Static Char ExitKey;
Static Char HexChars[16];
Static Char Char1Table[25];
Static Char Char23Table[24];
Static CharSet Char1Set;
Static CharSet Char23Set;
Static Char GlobalTextBuffer[256];
Static Char KeyBuffer[80];
Static int ReadIndex;
Static int WriteIndex;
Static boolean PrintListing;
Static FILE *Printer;
Static boolean SaveEntryPoints;
Static boolean TryRegList;
Static int EntryIndex;
Static int EntryPoints[MaxEntryPointCnt + 1];
Static int CmdCode;
Static int IPC_PageNo;
Static int IPC_PageIndex;
Static int SP;
Static int MSP;
Static int NumCallParams;
Static int AccA;
Static int AccB;
Static int AccC;
Static int AccD;
Static int OpdCnt;
Static Operands Opd;
Static Registers R;
Static int Stack[MaxStack + 1];
Static boolean Running;
Static boolean Tracing;
Static boolean Stepping;
Static boolean CrashInternal;
Static boolean DebugVocab;
Static boolean InStory;
Static boolean FaultNotImplemented;
Static int CursorX;
Static int CursorY;
Static int StoryCursorX;
Static int StoryCursorY;
Static int NonWindowCursorX;
Static int NonWindowCursorY;
Static int WindowCursorX;
Static int WindowCursorY;
Static int ScreenMode;
Static int StoryScreenMode;
Static int FormatMode;
Static int ComMode;
Static int OutputMode;
Static boolean ScreenEnabled;
Static boolean BufferEnabled;
Static boolean DirectEnabled;
Static boolean WindowEnabled;
Static boolean WritingInWindow;
Static boolean PrinterTried;
Static boolean PrinterOpen;
Static int BufferPageNo;
Static int BufferPageIndex;
Static int BufferIndex;
Static int LineIndex;
Static int LineNo;
Static int ScrollTop;
Static int StoryScrollTop;
Static Char LineBuffer[MaxLineIndex + 1];
Static Char Spaces[256];
Static CharSet TerminatorSet;
Static char Cmd;
Static Char CmdLine[256];
Static int FirstObj;
Static int LastObj;
Static int FirstHigh;
Static int LastHigh;
Static int RegNo;
Static int BPT_No;
Static int BPT_IdCnt;
Static PtrBPT BPT_List;
Static CountArray ExecCnt;
Static int CmpShift;
Static void HandleError(boolean WriteLastInst, Char Message[256],
boolean Crash);
Static void InternalError(char Error);
Static void SetLength(Char S[256], int Length) {
S[Length] = '\0';
/* p2c: pas.ZIP, line 248:
* Note: Modification of string length may translate incorrectly [146] */
} /* SetLength */
Static void OpenPrinter(void) {
if (PrinterTried || PrinterOpen)
return;
if (Printer != NULL)
Printer = freopen(PrinterName, "w", Printer);
else
Printer = fopen(PrinterName, "w");
_SETIO(Printer != NULL, FileNotFound);
PrinterTried = true;
PrinterOpen = (P_ioresult == 0);
if (!PrinterOpen)
InternalError(NoPrinter);
} /* OpenPrinter */
Static boolean PrinterEnabled(void) {
boolean PrinterEnabled_ReturnValue;
uchar ScriptLow;
boolean Enabled;
PrinterEnabled_ReturnValue = false;
if (PagePtrs[0] == NULL)
return PrinterEnabled_ReturnValue;
ScriptLow = PagePtrs[0][17];
Enabled = TstBit(ScriptLow, 0);
if (!Enabled)
return PrinterEnabled_ReturnValue;
if (!PrinterOpen)
OpenPrinter();
if (PrinterOpen)
return true;
return PrinterEnabled_ReturnValue;
} /* PrinterEnabled */
Static void PositionCursor(void) {
GotoXY(CursorX, CursorY);
} /* PositionCursor */
Static void MoveCursorUp(void) {
if (CursorY > 0) {
--CursorY;
PositionCursor();
}
} /* MoveCursorUp */
Static void MoveCursorDown(void) {
if (CursorY < ScreenHeight - 1) {
++CursorY;
PositionCursor();
}
} /* MoveCursorDown */
Static void MoveCursorRight(void) {
if (CursorX < ScreenWidth - 1) {
++CursorX;
PositionCursor();
}
} /* MoveCursorRight */
Static void MoveCursorLeft(void) {
if (CursorX > 0) {
--CursorX;
PositionCursor();
}
} /* MoveCursorLeft */
Static void ClearCh(void) {
PositionCursor();
WriteRawChOnScreen(' ');
PositionCursor();
} /* ClearCh */
Static void EraseCh(void) {
if (CursorX <= 0)
return;
MoveCursorLeft();
WriteRawChOnScreen(' ');
PositionCursor();
} /* EraseCh */
Static void ZM_GotoXY(int x, int y) {
CursorX = x - 1;
CursorY = y - 1;
PositionCursor();
} /* ZM_GotoXY */
Static void SetScreenMode(void) {
switch (ScreenMode) {
case 0: /* Normal */
NormalOn();
break;
case 1: /* Inverse */
InverseOn();
break;
case 2: /* Bold */
BoldOn();
break;
case 4: /* Italic */
ItalicOn();
break;
case 8: /* Title/Subtitle? */
ExtraOn();
break;
default:
InternalError(IllScreenMode);
break;
}
} /* SetScreenMode */
Static void ClearLines(int FirstLine, int LastLine) {
int LineCnt;
SaveTextAttributes();
ScreenMode = 0;
SetScreenMode();
for (LineCnt = FirstLine; LineCnt <= LastLine; ++LineCnt) {
GotoXY(0, LineCnt);
ClearToEOL();
}
RestoreTextAttributes();
PositionCursor();
} /* ClearLines */
Static void NewLine(void) {
CursorX = 0;
++CursorY;
if (CursorY >= ScreenHeight) {
ScrollLinesUp(ScrollTop - 1);
CursorY = ScreenHeight - 1;
}
PositionCursor();
ClearToEOL();
} /* NewLine */
Static void InitScreen(void) {
SetupTerminal(&ScreenWidth, &ScreenHeight);
ScrollTop = 1;
LineCnt = 0;
ClearScreen();
CursorOff();
CursorX = 0;
CursorY = 0;
ScreenMode = 0;
SetScreenMode();
} /* InitSCreen */
Static void ResetScreen(void) {
ScreenMode = 0;
SetScreenMode();
CursorOff();
ResetTerminal();
} /* ResetSCreen */
Static void ScreenCh(Char Ch) {
WriteRawChOnScreen(Ch);
++CursorX;
/*
IF CursorX>=Pred(ScreenWidth) THEN BEGIN
CursorX:=0;
PositionCursor;
END;
*/
} /* ScreenCh */
Static void PrintCh(Char Ch) {
ScreenCh(Ch);
if (PrintListing)
putc(Ch, Printer);
} /* PrintCh */
Static void ZM_ScreenCh(Char Ch) {
if (Ch < ' ')
InternalError(IllOutputChar);
WriteChOnScreen(Ch);
++CursorX;
/*
IF CursorX>=Pred(ScreenWidth) THEN BEGIN
CursorX:=0;
PositionCursor;
END;
*/
} /* ZM_ScreenCh */
Static void ZM_PrintCh(Char Ch) {
ZM_ScreenCh(Ch);
if (PrintListing)
putc(Ch, Printer);
} /* ZM_PrintCh */
Static void InitExecCnt(void) {
int Cnt;
for (Cnt = 0; Cnt <= 255; ++Cnt)
ExecCnt[Cnt] = 0;
} /* InitExecCnt */
Static void Push(int Value) {
if (SP > MaxStack) {
InternalError(StackOverflow);
} else {
Stack[SP] = Value;
++SP;
}
} /* Push */
Static int Pop(void) {
if (SP > 0) {
--SP;
return (Stack[SP]);
}
InternalError(StackUnderflow);
} /* Pop */
Static void ChkAddress(int *PageNo, int *PageIndex) {
while (*PageIndex > 255) {
*PageIndex -= 256;
++*PageNo;
}
while (*PageIndex < 0) {
*PageIndex += 256;
--*PageNo;
}
if (CodeVersion < '3')
return;
if (*PageNo > CodeEndPageNo) {
InternalError(PC_Overflow);
} else if (*PageNo < 0)
InternalError(PC_Underflow);
} /* ChkAddress */
Static void Inc(int *PageNo, int *PageIndex, int Increment) {
*PageIndex += Increment;
ChkAddress(PageNo, PageIndex);
} /* Inc */
Static void Dec(int *PageNo, int *PageIndex, int Increment) {
*PageIndex -= Increment;
ChkAddress(PageNo, PageIndex);
} /* Inc */
Static void ExpandAddress(int AddressHigh, int AddressLow, int *PageNo,
int *PageIndex) {
*PageNo = AddressHigh;
*PageIndex = AddressLow;
ShiftLeft(PageNo, PageIndex);
if (CodeVersion >= '4') {
ShiftLeft(PageNo, PageIndex);
if (CodeVersion >= '6')
ShiftLeft(PageNo, PageIndex);
}
ChkAddress(PageNo, PageIndex);
} /* ExpandAddress */
Static void PrintByte(int Value, int Format) {
int SpaceCnt;
int Expanded;
Expanded = Value;
if (Format >= 2) {
for (SpaceCnt = 3; SpaceCnt <= Format; ++SpaceCnt)
PrintCh(' ');
PrintCh(HexChars[Nibble(Expanded, 1)]);
}
PrintCh(HexChars[Nibble(Expanded, 0)]);
} /* PrintByte */
Static void PrintWord(int Value, int Format) {
int LowByte;
int HighByte;
SplitWord(Value, &LowByte, &HighByte);
PrintByte(HighByte, Format - 2);
PrintByte(LowByte, 2);
} /* PrintWord */
Static void PrintInteger(int Value) {
int DigitCnt;
int Digit;
int WriteCnt;
if (Value < 0) {
PrintCh('-');
Value = -Value;
}
DigitCnt = 0;
while (Value > 0) {
Push(Value % 10);
++DigitCnt;
Value /= 10;
}
if (DigitCnt == 0) {
PrintCh('0');
return;
}
for (WriteCnt = 1; WriteCnt <= DigitCnt; ++WriteCnt) {
Digit = Pop();
PrintCh(Digit + '0');
}
} /* PrintInteger */
Static void PrintString(Char S[256]) {
int ChrCnt;
int FORLIM;
FORLIM = strlen(S);
for (ChrCnt = 1; ChrCnt <= FORLIM; ++ChrCnt)
PrintCh(S[ChrCnt - 1]);
} /* PrintString */
Static void LineInterpreter(char *Cmd, Char CmdLine[256]);
Static void PrintStatusLine(void);
Static void WriteLineBuffer(void) {
int ChrCnt;
int FORLIM;
if (ScreenEnabled) {
FORLIM = LineIndex;
for (ChrCnt = 0; ChrCnt < FORLIM; ++ChrCnt)
ZM_ScreenCh(LineBuffer[ChrCnt]);
}
if (PrinterEnabled() && !WritingInWindow) {
FORLIM = LineIndex;
for (ChrCnt = 0; ChrCnt < FORLIM; ++ChrCnt)
putc(LineBuffer[ChrCnt], Printer);
}
LineIndex = 0;
} /* WriteLineBuffer */
Static void PutChInStoryBuffer(Char Ch) {
int IndexPageNo;
int IndexPageIndex;
if (BufferPageNo < 0)
InternalError(OutputBufferUndefined);
IndexPageNo = BufferPageNo;
IndexPageIndex = BufferPageIndex;
Inc(&IndexPageNo, &IndexPageIndex, BufferIndex);
PagePtrs[IndexPageNo][IndexPageIndex] = Ch;
++BufferIndex;
} /* PutChInStoryBuffer */
Static void ZM_NewLine(void) {
Char WaitKey;
int OldCursorX;
int OldCursorY;
boolean OldPrintListing;
if (BufferEnabled) {
PutChInStoryBuffer('\015');
return;
}
OldPrintListing = PrintListing;
PrintListing = false;
if (ScreenEnabled && !WritingInWindow) {
if (LineNo >= ScreenHeight) {
PrintStatusLine();
PositionCursor();
OldCursorX = CursorX;
OldCursorY = CursorY;
LineNo = ScrollTop;
CursorOn();
PrintString("[MORE]");
WaitKey = ReadKeyWithNoEcho(-1);
CursorOff();
CursorX = OldCursorX;
CursorY = OldCursorY;
PositionCursor();
ClearToEOL();
}
++LineNo;
}
WriteLineBuffer();
if (ScreenEnabled)
NewLine();
if (PrinterEnabled())
putc('\n', Printer);
PrintListing = OldPrintListing;
} /* ZM_NewLine */
Static void PutChInLineBuffer(Char Ch) {
int LastIndex;
int CutIndex;
int PutIndex;
if (Ch < ' ') {
if (ChkLineChars)
InternalError(IllOutputChar);
goto _L2;
}
LineBuffer[LineIndex] = Ch;
if (LineIndex + CursorX < ScreenWidth) {
++LineIndex;
/*
END ELSE IF WritingInWindow AND (CursorY + 1>=ScrollTop - 1) THEN BEGIN
WriteLineBuffer;
*/
} else {
LastIndex = LineIndex;
CutIndex = LineIndex;
while (CutIndex > 0) {
if (CutIndex + CursorX < ScreenWidth && LineBuffer[CutIndex] == ' ')
goto _L1;
--CutIndex;
}
CutIndex = LineIndex;
_L1:
LineIndex = CutIndex;
ZM_NewLine();
if (LineBuffer[CutIndex] == ' ')
++CutIndex;
PutIndex = 0;
while (CutIndex <= LastIndex) {
LineBuffer[PutIndex] = LineBuffer[CutIndex];
++CutIndex;
++PutIndex;
}
LineIndex = PutIndex;
}
_L2: ;
} /* PutChInLineBuffer */
Static void PutChToStoryOutput(Char Ch) {
if (Ch == EOL()) {
ZM_NewLine();
return;
}
if (BufferEnabled) {
PutChInStoryBuffer(Ch);
return;
}
if (!(ScreenEnabled | PrinterEnabled()))
return;
if (DirectEnabled) {
if (ScreenEnabled)
ZM_ScreenCh(Ch);
/*
IF PrinterEnabled THEN BEGIN
Write(Printer,Ch);
END;
*/
} else {
PutChInLineBuffer(Ch);
}
} /* PutChToStoryOutput */
Static void PutIntToStoryOutput(int Int) {
int DigitCnt;
int Digit;
int WriteCnt;
if (Int < 0) {
PutChToStoryOutput('-');
Int = -Int;
}
DigitCnt = 0;
while (Int > 0) {
Push(Int % 10);
++DigitCnt;
Int /= 10;
}
if (DigitCnt == 0) {
PutChToStoryOutput('0');
return;
}
for (WriteCnt = 1; WriteCnt <= DigitCnt; ++WriteCnt) {
Digit = Pop();
PutChToStoryOutput(Digit + '0');
}
} /* PutIntToStoryOutput */
Static jmp_buf _JL999;
Static void ChkWait(void) {
Char Key;
if (KeyPressed()) {
Key = ReadKeyWithNoEcho(-1);
if (Key != ExitKey) {
KeyBuffer[WriteIndex] = Key;
++WriteIndex;
if (WriteIndex > 79)
WriteIndex = 0;
} else {
if (PrintListing)
fprintf(Printer, "\n\n");
NewLine();
WriteDump = (GlobalDumpState != NoDump);
longjmp(_JL999, 1);
}
}
NewLine();
if (PrintListing)
putc('\n', Printer);
++LineCnt;
} /* ChkWait */
Static void DisposePages(void) {
int DisposeCnt;
for (DisposeCnt = PageCnt - 1; DisposeCnt >= 0; --DisposeCnt) {
if (PagePtrs[DisposeCnt] != NULL)
Free(PagePtrs[DisposeCnt]);
if (DataPagePtrs[DisposeCnt] != NULL)
Free(DataPagePtrs[DisposeCnt]);
}
PageCnt = 0;
} /* DisposePages */
Static void ReadPages(void) {
int SubPageCnt;
int EndPageNo;
int EndPageIndex;
int DataEndPageNo;
union {
tMiscInfo M;
aPage P;
} SwapPage;
Char FileName[256];
FILE *StoryData;
FILEBUFNC(StoryData,StoryFileBuffer);
StoryData = NULL;
if (PageCnt > 0)
DisposePages();
strcpy(FileName, StoryName);
if (!FileExists(StoryName))
HandleError(false, "Story file not found.", false);
if (StoryData != NULL)
StoryData = freopen(FileName, "rb", StoryData);
else
StoryData = fopen(FileName, "rb");
if (StoryData == NULL)
_EscIO(FileNotFound);
RESETBUF(StoryData, StoryFileBuffer);
memcpy(SwapPage.P, AGETFBUF(StoryData, StoryFileBuffer)[0],
signedsizeof(aPage));
MiscInfo = SwapPage.M;
CodeVersion = MiscInfo.CodeType + '0';
DataEndPageNo = MiscInfo.NumReadWriteBytesHigh;
if (CodeVersion <= '2') {
CodeEndPageNo = MaxPageNo - 1;
CodeEndPageIndex = 255;
} else {
ExpandAddress(MiscInfo.EndPageNo, MiscInfo.EndPageIndex, &EndPageNo,
&EndPageIndex);
CodeEndPageNo = EndPageNo;
CodeEndPageIndex = EndPageIndex;
if (CodeEndPageNo > MaxPageNo)
HandleError(false, "Story too large.", false);
}
while ((PageCnt <= CodeEndPageNo) & (!BUFEOF(StoryData))) {
for (SubPageCnt = 0; SubPageCnt <= MaxSubPageNo; ++SubPageCnt)
{ /* MemAvail<SizeOf(aPage)+MinMemSpace */
if (false) {
DisposePages();
HandleError(false, "Not enough memory to load story.", false);
}
if (PageCnt <= CodeEndPageNo) {
PagePtrs[PageCnt] = Malloc(signedsizeof(aPage));
memcpy(PagePtrs[PageCnt],
AGETFBUF(StoryData, StoryFileBuffer)[SubPageCnt],
signedsizeof(aPage));
if (PageCnt <= DataEndPageNo) {
DataPagePtrs[PageCnt] = Malloc(signedsizeof(aPage));
memcpy(DataPagePtrs[PageCnt],
AGETFBUF(StoryData, StoryFileBuffer)[SubPageCnt],
signedsizeof(aPage));
}
++PageCnt;
}
}
GET(StoryData, StoryFileBuffer);
}
if (CodeVersion >= '3' && PageCnt < CodeEndPageNo) {
DisposePages();
HandleError(false, "Story file incomplete.", false);
}
if (!BUFEOF(StoryData)) {
PrintString("Story file too long. Story only requires");
PrintWord(CodeEndPageNo + 1, 5);
PrintString("00 bytes on disk.");
ChkWait();
}
PrintString("Loaded");
PrintWord(PageCnt, 5);
PrintString(" pages.");
ChkWait();
ChkWait();
if (StoryData != NULL)
fclose(StoryData);
} /* ReadPages */
Static void ReloadData(void) {
int DataPageCnt;
int NumDataPages;
DataPageCnt = 0;
NumDataPages = MiscInfo.NumReadWriteBytesHigh;
while (DataPageCnt < NumDataPages) {
memcpy(PagePtrs[DataPageCnt], DataPagePtrs[DataPageCnt],
signedsizeof(aPage));
++DataPageCnt;
}
} /* ReloadData */
Static void ExecuteSubRoutine(int Address);
Static boolean ReadKey(boolean ZMachineOp, Char *Key, int TimeOut,
char CallEvent, int CallAddress) {
boolean ReadKey_ReturnValue;
Char SpecialKey;
SpecialKey = '\0';
*Key = '\0';
ReadKey_ReturnValue = true;
PositionCursor();
if (ReadIndex != WriteIndex) {
*Key = KeyBuffer[ReadIndex];
++ReadIndex;
if (ReadIndex > 79)
ReadIndex = 0;
} else {
do {
*Key = ReadKeyWithNoEcho(TimeOut);
if (ZMachineOp && *Key == '\0') {
if (CallEvent == CallTimeOut && CallAddress > 0)
ExecuteSubRoutine(CallAddress);
}
} while (*Key == '\0' && CallEvent != CallKeyPress);
}
if (ZMachineOp && *Key != '\0') {
SpecialKey = '\0';
if (*Key == UpArrow()) {
SpecialKey = 129;
} else if (*Key == DownArrow()) {
SpecialKey = 130;
} else if (*Key == LeftArrow()) {
SpecialKey = 131;
} else if (*Key == RightArrow()) {
SpecialKey = 132;
} else if (*Key == NumericSW()) {
SpecialKey = 146;
} else if (*Key == NumericS()) {
SpecialKey = 147;
} else if (*Key == NumericSE()) {
SpecialKey = 148;
} else if (*Key == NumericW()) {
SpecialKey = 149;
} else if (*Key == NumericCentre()) {
SpecialKey = 150;
} else if (*Key == NumericE()) {
SpecialKey = 151;
} else if (*Key == NumericNW()) {
SpecialKey = 152;
} else if (*Key == NumericN()) {
SpecialKey = 153;
} else if (*Key == NumericNE()) {
SpecialKey = 154;
} else if (IsFuncKey(*Key))
SpecialKey = FuncKeyNo(*Key) + 132;
if (SpecialKey != '\0') {
ReadKey_ReturnValue = false;
*Key = SpecialKey;
}
}
if (CallEvent == CallKeyPress) {
if (CallAddress > 0)
ExecuteSubRoutine(CallAddress);
}
return ReadKey_ReturnValue;
} /* ReadKey */
Static boolean ReadLine(boolean ZMachineOp, Char Line[256], int MaxLineLength,
int TimeOut, int TimeOutCallAddress) {
int Index;
Char Key;
boolean Finished;
boolean GotLine;
int FORLIM;
SaveTextAttributes();
ScreenMode = 0;
SetScreenMode();
if (ZMachineOp) {
WriteLineBuffer();
PrintStatusLine();
LineNo = ScrollTop;
}
Index = strlen(Line);
CursorOn();
Finished = false;
GotLine = true;
if (TimeOut >= 0)
EnableTimer();
do {
if (!ReadKey(ZMachineOp, &Key, TimeOut, CallTimeOut, TimeOutCallAddress)) {
Index = 1;
Line[0] = Key;
GotLine = false;
Finished = true;
}
if (!Finished) {
if (Key >= ' ' && Key <= '~') {
if (Index >= MaxLineLength) {
RingBell();
} else {
ScreenCh(Key);
++Index;
if (ZMachineOp && isupper(Key))
Key = _tolower(Key);
Line[Index - 1] = Key;
}
} else if ((Key == Backspace()) | (Key == DeleteChar())) {
if (Index > 0) {
--Index;
EraseCh();
} else {
RingBell();
}
} else if (Key == KeyToDeleteLine()) {
for (; Index >= 1; --Index)
EraseCh();
Index = 0;
} else if (Key == BreakKey && ZMachineOp) {
RestoreTextAttributes();
CursorOff();
InternalError(KeyboardBreak);
} else if (Key == EOL())
Finished = true;
else
RingBell();
}
} while (!Finished);
if (TimeOut >= 0)
DisableTimer();
SetLength(Line, Index);
if (GotLine)
NewLine();
RestoreTextAttributes();
CursorOff();
if (!ZMachineOp)
return GotLine;
if (!GotLine)
return GotLine;
if (!PrinterEnabled())
return GotLine;
FORLIM = strlen(Line);
for (Index = 1; Index <= FORLIM; ++Index)
putc(Line[Index - 1], Printer);
putc('\n', Printer);
return GotLine;
} /* ReadLine */
Static void WriteCh(Char Line[256], Char Ch) {
int Pos;
Pos = strlen(Line) + 1;
SetLength(Line, Pos);
Line[Pos - 1] = Ch;
} /* WriteCh */
Static void DumpByte(Char Line[256], int Value) {
int Expanded;
Expanded = Value;
WriteCh(Line, ' ');
WriteCh(Line, HexChars[Nibble(Expanded, 1)]);
WriteCh(Line, HexChars[Nibble(Expanded, 0)]);
} /* DumpByte */
Static void AddByte(Char Line[256], int Value) {
int Expanded;
Expanded = Value;
WriteCh(Line, HexChars[Nibble(Expanded, 1)]);
WriteCh(Line, HexChars[Nibble(Expanded, 0)]);
} /* AddByte */
Static void AddWord(Char Line[256], int Value) {
int LowByte;
int HighByte;
SplitWord(Value, &LowByte, &HighByte);
AddByte(Line, HighByte);
AddByte(Line, LowByte);
} /* AddWord */
Static int GetByteDC(void) {
int GetByteDC_ReturnValue;
int Value;
ChkAddress(&DC_PageNo, &DC_PageIndex);
Value = PagePtrs[DC_PageNo][DC_PageIndex];
GetByteDC_ReturnValue = Value;
Inc(&DC_PageNo, &DC_PageIndex, 1);
if (WriteDump) {
DumpByte(Dump, Value);
++DumpCnt;
} else if (GlobalDumpState != UnpackedDump)
DumpCnt = 11;
return GetByteDC_ReturnValue;
} /* GetByteDC */
Static int GetByteIPC(void) {
int GetByteIPC_ReturnValue;
ChkAddress(&IPC_PageNo, &IPC_PageIndex);
GetByteIPC_ReturnValue = PagePtrs[IPC_PageNo][IPC_PageIndex];
Inc(&IPC_PageNo, &IPC_PageIndex, 1);
return GetByteIPC_ReturnValue;
} /* GetByteIPC */
Static int GetWordDC(void) {
int LowByte;
int HighByte;
HighByte = GetByteDC();
LowByte = GetByteDC();
return (JoinBytes(LowByte, HighByte));
} /* GetWordDC */
Static int GetWordIPC(void) {
int LowByte;
int HighByte;
HighByte = GetByteIPC();
LowByte = GetByteIPC();
return (JoinBytes(LowByte, HighByte));
} /* GetWordIPC */
Static void CalcCallAddress(int Address, int *CallPageNo, int *CallPageIndex) {
int StartPageNo;
int StartPageIndex;
*CallPageNo = 0;
*CallPageIndex = Address;
ShiftLeft(CallPageNo, CallPageIndex);
if (CodeVersion >= '4') {
ShiftLeft(CallPageNo, CallPageIndex);
if (CodeVersion >= '6') {
StartPageNo = MiscInfo.CodeStartPageNo;
StartPageIndex = MiscInfo.CodeStartIndex;
ShiftLeft(&StartPageNo, &StartPageIndex);
ShiftLeft(&StartPageNo, &StartPageIndex);
ShiftLeft(&StartPageNo, &StartPageIndex);
*CallPageNo += StartPageNo;
*CallPageIndex += StartPageIndex;
}
}
ChkAddress(CallPageNo, CallPageIndex);
} /* CalcCallAddress */
Static void StringToNumber(int *Number, anAddrString NumString) {
int DigitCnt;
Char HexDigit;
int FORLIM;
*Number = 0;
FORLIM = strlen(NumString);
for (DigitCnt = 1; DigitCnt <= FORLIM; ++DigitCnt) {
HexDigit = NumString[DigitCnt - 1];
if (islower(HexDigit))
HexDigit = _toupper(HexDigit);
if (HexDigit >= 'A')
*Number = *Number * 16 + HexDigit - 'A' + 10;
else
*Number = *Number * 16 + HexDigit - '0';
}
} /* StringToNumber */
Static void WriteText(Char TextType, char OutputType, char SourceType,
Char TextBuffer[256]);
/* Local variables for WriteText: */
struct WriteText_LocalVariables {
Char TextType;
char OutputType;
char SourceType;
Char *TextBuffer;
jmp_buf _JL888;
int ChByte;
int ChType;
int ChBuffer;
int ChCnt;
int PackIndex;
int LineIndex;
int LineLength;
boolean TextEnd;
int Three;
int ThreeLow;
int ThreeHigh;
/* PACKED RECORD CASE Integer OF
1:(Word:Integer);
2:(Chars:PACKED ARRAY [0..2] OF 0..31);
3:(PackedChars:0..32767;
TextEnd:Boolean)
END; */
Char TextLine[256];
int StartIndex;
int StartPageNo;
boolean OldWriteDump;
boolean IsVocabulary;
boolean Error;
} ;
Local void HandleEndOfText(struct WriteText_LocalVariables *WriteText_Vars);
Local void GetCh(int *Ch, boolean *TextEnd,
struct WriteText_LocalVariables *WriteText_Vars) {
if (*TextEnd) {
HandleEndOfText(WriteText_Vars);
longjmp(WriteText_Vars->_JL888, 1);
}
if (WriteText_Vars->PackIndex == 0) {
if (WriteText_Vars->SourceType == FromIPC)
WriteText_Vars->Three = GetWordIPC();
else
WriteText_Vars->Three = GetWordDC();
SplitWord(WriteText_Vars->Three, &WriteText_Vars->ThreeLow,
&WriteText_Vars->ThreeHigh);
*Ch = land(lsr(WriteText_Vars->ThreeHigh, 2), 31);
} else if (WriteText_Vars->PackIndex == 1) {
*Ch = lor(land(lsr(WriteText_Vars->ThreeLow, 5), 7),
lsl(land(WriteText_Vars->ThreeHigh, 3), 3));
} else {
*Ch = land(WriteText_Vars->ThreeLow, 31);
*TextEnd = TstBit(WriteText_Vars->Three, 15);
WriteText_Vars->PackIndex = -1;
}
++WriteText_Vars->PackIndex;
if (WriteText_Vars->IsVocabulary) {
WriteText_Vars->Error = !*TextEnd;
++WriteText_Vars->ChCnt;
*TextEnd = (WriteText_Vars->ChCnt == WordNumChars);
}
if (GlobalDumpState == UnpackedDump) {
DumpByte(Dump, *Ch);
++DumpCnt;
}
} /* GetCh */
Local int GetBuffer(struct WriteText_LocalVariables *WriteText_Vars) {
int GetBuffer_ReturnValue;
if (WriteText_Vars->ChType > 127)
return WriteText_Vars->ChBuffer;
GetBuffer_ReturnValue = WriteText_Vars->ChType;
WriteText_Vars->ChType = 255;
return GetBuffer_ReturnValue;
} /* GetCnt */
Local void DumpText(struct WriteText_LocalVariables *WriteText_Vars) {
int SpaceCnt;
int NumSpaces;
SetLength(WriteText_Vars->TextLine, WriteText_Vars->LineIndex);
if (WriteText_Vars->OutputType == OntoScreen) {
PrintCh(WriteText_Vars->TextType);
PrintWord(WriteText_Vars->StartPageNo, 5);
PrintByte(WriteText_Vars->StartIndex, 2);
PrintCh(':');
PrintString(Dump);
if (*WriteText_Vars->TextLine != '\0') {
if (GlobalDumpState > CodeDump)
NumSpaces = (12 - DumpCnt) * 3;
else
NumSpaces = 3;
for (SpaceCnt = 1; SpaceCnt <= NumSpaces; ++SpaceCnt)
PrintCh(' ');
PrintCh('|');
PrintString(WriteText_Vars->TextLine);
PrintCh('|');
}
if (WriteText_Vars->SourceType == FromDC) {
WriteText_Vars->StartPageNo = DC_PageNo;
WriteText_Vars->StartIndex = DC_PageIndex;
} else {
WriteText_Vars->StartPageNo = IPC_PageNo;
WriteText_Vars->StartIndex = IPC_PageIndex;
}
ChkWait();
} else {
strcat(WriteText_Vars->TextBuffer, WriteText_Vars->TextLine);
}
WriteText_Vars->LineIndex = 0;
*Dump = '\0';
DumpCnt = 0;
} /* DumpText */
Local void PutCh(Char Ch, struct WriteText_LocalVariables *WriteText_Vars) {
int ChrCnt;
Char ByteString[256];
int FORLIM;
if (WriteText_Vars->OutputType == ToStoryOutput) {
PutChToStoryOutput(Ch);
return;
}
if (Ch == EOL()) {
DumpText(WriteText_Vars);
return;
}
if (DumpCnt > 11 || WriteText_Vars->LineIndex > WriteText_Vars->LineLength)
DumpText(WriteText_Vars);
++WriteText_Vars->LineIndex;
if (Ch >= ' ' && Ch <= '~') {
WriteText_Vars->TextLine[WriteText_Vars->LineIndex - 1] = Ch;
return;
}
PutCh('(', WriteText_Vars);
*ByteString = '\0';
AddByte(ByteString, Ch);
FORLIM = strlen(ByteString);
for (ChrCnt = 1; ChrCnt <= FORLIM; ++ChrCnt)
PutCh(ByteString[ChrCnt - 1], WriteText_Vars);
PutCh(')', WriteText_Vars);
} /* PutCh */
Local void HandleEndOfText(struct WriteText_LocalVariables *WriteText_Vars) {
if (WriteText_Vars->LineIndex > 0 ||
*Dump != '\0' && GlobalDumpState == UnpackedDump)
DumpText(WriteText_Vars);
if (WriteText_Vars->IsVocabulary) {
if (WriteText_Vars->Error)
strcat(WriteText_Vars->TextBuffer, "E");
}
WriteDump = WriteText_Vars->OldWriteDump;
} /* HandleEndOfText */
Local void WriteSpecialText(struct WriteText_LocalVariables *WriteText_Vars) {
int SpecialNo;
int AdrsPageNo;
int AdrsIndex;
int ChrCnt;
Char SpecialBuffer[256];
int FORLIM;
GetCh(&SpecialNo, &WriteText_Vars->TextEnd, WriteText_Vars);
AdrsIndex = SpecialNo * 2 + (WriteText_Vars->ChByte - 1) * 64 +
MiscInfo.SpecialIndex;
AdrsPageNo = MiscInfo.SpecialPageNo;
ChkAddress(&AdrsPageNo, &AdrsIndex);
if (GlobalDumpState > CodeDump) {
if (WriteText_Vars->LineIndex > 0 || *Dump != '\0')
DumpText(WriteText_Vars);
}
Push(DC_PageNo);
Push(DC_PageIndex);
DC_PageNo = AdrsPageNo;
DC_PageIndex = AdrsIndex;
AdrsPageNo = GetByteDC() * 2;
AdrsIndex = GetByteDC() * 2;
ChkAddress(&AdrsPageNo, &AdrsIndex);
DC_PageNo = AdrsPageNo;
DC_PageIndex = AdrsIndex;
if (WriteText_Vars->OutputType == ToStoryOutput) {
WriteText('S', ToStoryOutput, FromDC, SpecialBuffer);
} else {
WriteText('S', IntoBuffer, FromDC, SpecialBuffer);
FORLIM = strlen(SpecialBuffer);
for (ChrCnt = 1; ChrCnt <= FORLIM; ++ChrCnt)
PutCh(SpecialBuffer[ChrCnt - 1], WriteText_Vars);
}
WriteText_Vars->ChType = 255;
if (GlobalDumpState > CodeDump) {
*Dump = '\0';
DumpCnt = 0;
WriteText_Vars->StartPageNo = AdrsPageNo;
WriteText_Vars->StartIndex = AdrsIndex;
}
DC_PageIndex = Pop();
DC_PageNo = Pop();
} /* WriteSpecialText */
Static void WriteText(Char TextType_, char OutputType_, char SourceType_,
Char TextBuffer_[256]) {
struct WriteText_LocalVariables V;
int Buffer;
int PreviousCh;
V.TextType = TextType_;
V.OutputType = OutputType_;
V.SourceType = SourceType_;
V.TextBuffer = TextBuffer_;
if (setjmp(V._JL888))
goto _L888;
V.OldWriteDump = WriteDump;
*V.TextBuffer = '\0';
WriteDump = (GlobalDumpState == TextDump && V.OutputType != ToStoryOutput);
V.PackIndex = 0;
V.LineIndex = 0;
*Dump = '\0';
DumpCnt = 0;
V.TextEnd = false;
V.ChCnt = 0;
if (V.SourceType == FromDC) {
V.StartPageNo = DC_PageNo;
V.StartIndex = DC_PageIndex;
} else {
V.StartPageNo = IPC_PageNo;
V.StartIndex = IPC_PageIndex;
}
V.ChBuffer = 0;
V.ChType = 255;
V.IsVocabulary = (V.TextType == 'V');
V.Error = false;
if (GlobalDumpState > CodeDump)
V.LineLength = 20;
else
V.LineLength = 64;
do {
GetCh(&V.ChByte, &V.TextEnd, &V);
if (V.ChByte == 0) {
PutCh(' ', &V);
} else if (CodeVersion <= '2') {
if (V.ChByte == 1) {
if (CodeVersion == '1')
PutCh(EOL(), &V);
else
WriteSpecialText(&V);
} else if (V.ChByte < 4) {
Buffer = GetBuffer(&V) + V.ChByte + 2;
while (Buffer >= 3)
Buffer -= 3;
V.ChType = Buffer;
} else if (V.ChByte < 6) {
Buffer = GetBuffer(&V) + V.ChByte;
while (Buffer >= 3)
Buffer -= 3;
V.ChBuffer = Buffer;
} else {
Buffer = GetBuffer(&V);
if (Buffer == 0) {
PutCh(V.ChByte + 91, &V);
} else if (Buffer == 1) {
PutCh(V.ChByte + 59, &V);
} else {
Buffer = V.ChByte - 7;
if (Buffer == 0 && CodeVersion == '2') {
PutCh(EOL(), &V);
} else if (Buffer < 0) {
GetCh(&V.ChByte, &V.TextEnd, &V);
GetCh(&Buffer, &V.TextEnd, &V);
Buffer = lor(land(V.ChByte * 32, 255), Buffer);
if (Buffer == 9 && CodeVersion == '1')
PutCh(' ', &V);
else
PutCh(Buffer, &V);
} else if (CodeVersion == '1')
PutCh(Char1Table[Buffer], &V);
else
PutCh(Char23Table[Buffer - 1], &V);
}
}
} else if (CodeVersion >= '3') {
if (V.ChByte < 4) {
WriteSpecialText(&V);
} else if (V.ChByte < 6) {
Buffer = V.ChByte - 3;
PreviousCh = GetBuffer(&V);
if (PreviousCh == 0 && (Buffer == 0 || V.ChType > 127)) {
V.ChType = Buffer;
} else {
V.ChBuffer = Buffer;
if (PreviousCh != V.ChBuffer)
V.ChBuffer = 0;
}
} else {
PreviousCh = GetBuffer(&V);
if (PreviousCh == 0) {
PutCh(V.ChByte + 91, &V);
} else if (PreviousCh == 1) {
PutCh(V.ChByte + 59, &V);
} else {
Buffer = V.ChByte - 7;
if (Buffer < 0) {
GetCh(&V.ChByte, &V.TextEnd, &V);
GetCh(&Buffer, &V.TextEnd, &V);
PutCh(lor(land(V.ChByte * 32, 255), Buffer), &V);
} else if (Buffer == 0)
PutCh(EOL(), &V);
else
PutCh(Char23Table[Buffer - 1], &V);
}
}
}
} while (!V.TextEnd);
HandleEndOfText(&V);
_L888: ;
} /* WriteText */
Static boolean CodeCorrect(ShortInteger *CodeChkSum) {
ShortInteger ChkSum;
int NumDataPages;
int PageCnt;
int ByteCnt;
int ChkSumLow;
int ChkSumHigh;
uchar *ChkPagePtr;
ChkSum = 0;
NumDataPages = MiscInfo.NumReadWriteBytesHigh;
ChkPagePtr = DataPagePtrs[0];
ByteCnt = 64;
while (ByteCnt < 256) {
ChkSum += ChkPagePtr[ByteCnt];
++ByteCnt;
}
PageCnt = 1;
while (PageCnt < CodeEndPageNo) {
if (PageCnt <= NumDataPages)
ChkPagePtr = DataPagePtrs[PageCnt];
else
ChkPagePtr = PagePtrs[PageCnt];
ByteCnt = 0;
while (ByteCnt < 256) {
ChkSum += ChkPagePtr[ByteCnt];
++ByteCnt;
}
++PageCnt;
}
ByteCnt = 0;
ChkPagePtr = PagePtrs[CodeEndPageNo];
while (ByteCnt < CodeEndPageIndex) {
ChkSum += ChkPagePtr[ByteCnt];
++ByteCnt;
}
*CodeChkSum = ChkSum;
SplitWord(ChkSum, &ChkSumLow, &ChkSumHigh);
return (ChkSumLow == MiscInfo.ChkSumLow && ChkSumHigh == MiscInfo.ChkSumHigh);
} /* CodeCorrect */
Static void SaveEntryPoint(int EntryAddress) {
int EntryCnt;
if (!SaveEntryPoints)
return;
EntryAddress = land(EntryAddress, 65535);
EntryCnt = EntryIndex - 1;
while (EntryCnt >= 0 && EntryPoints[EntryCnt] != EntryAddress)
--EntryCnt;
if (EntryCnt >= 0)
return;
if (EntryIndex <= MaxEntryPointCnt) {
EntryPoints[EntryIndex] = EntryAddress;
++EntryIndex;
return;
}
PrintString("Warning: No more room to save entry points");
RingBell();
NewLine();
} /* SaveEntryPoint */
Static void RemoveEntry(int EntryPageNo, int EntryPageIndex) {
int EntryCnt;
int PageNo;
int PageIndex;
boolean Found;
EntryCnt = EntryIndex - 1;
Found = false;
while (!Found && EntryCnt >= 0) {
CalcCallAddress(EntryPoints[EntryCnt], &PageNo, &PageIndex);
if (PageNo == EntryPageNo && PageIndex == EntryPageIndex)
Found = true;
else
--EntryCnt;
}
if (!Found) {
PrintString("Error: Entry point not found:");
PrintWord(EntryPageNo, 5);
PrintByte(EntryPageIndex, 2);
ChkWait();
return;
}
++EntryCnt;
while (EntryCnt < EntryIndex) {
EntryPoints[EntryCnt - 1] = EntryPoints[EntryCnt];
++EntryCnt;
}
--EntryIndex;
} /* RemoveEntry */
Static void DisRegList(int NumRegsToInit) {
boolean OldWriteDump;
int RegCnt;
int RegValue;
int FirstPage;
int FirstIndex;
int AddressPageNo;
int AddressIndex;
int CodeStartPageNo;
int CodeStartPageIndex;
int EntryAddress;
Char RegLine[256];
FirstPage = DC_PageNo;
FirstIndex = DC_PageIndex - 1;
if (FirstIndex < 0) {
FirstIndex += 256;
--FirstPage;
}
if ((FirstIndex & 1) != 0 || CodeVersion >= '4' && (FirstIndex & 3) != 0) {
PrintString("Error: Illegal entry point.");
RingBell();
NewLine();
longjmp(_JL999, 1);
}
if (NumRegsToInit > 15) {
PrintString("Error: Too much register data:");
PrintByte(NumRegsToInit, 3);
RingBell();
NewLine();
longjmp(_JL999, 1);
}
OldWriteDump = WriteDump;
WriteDump = false;
AddressPageNo = FirstPage;
AddressIndex = FirstIndex;
if (CodeVersion >= '6') {
CodeStartPageNo = MiscInfo.CodeStartPageNo;
CodeStartPageIndex = MiscInfo.CodeStartIndex;
ShiftLeft(&CodeStartPageNo, &CodeStartPageIndex);
ShiftLeft(&CodeStartPageNo, &CodeStartPageIndex);
ShiftLeft(&CodeStartPageNo, &CodeStartPageIndex);
AddressPageNo -= CodeStartPageNo;
AddressIndex -= CodeStartPageIndex;
ChkAddress(&AddressPageNo, &AddressIndex);
}
ShiftRight(&AddressPageNo, &AddressIndex);
if (CodeVersion >= '4')
ShiftRight(&AddressPageNo, &AddressIndex);
EntryAddress = JoinBytes(AddressIndex, AddressPageNo);
SaveEntryPoint(EntryAddress);
if (CodeVersion < '5') {
RegCnt = 0;
do {
++RegCnt;
if (RegCnt == 1 || strlen(RegLine) + 5 > ScreenWidth) {
if (RegCnt > 1) {
PrintString(RegLine);
ChkWait();
}
strcpy(RegLine, "R");
WriteCh(RegLine, ' ');
if (RegCnt > 1) {
AddWord(RegLine, DC_PageNo);
AddByte(RegLine, DC_PageIndex);
} else {
AddWord(RegLine, FirstPage);
AddByte(RegLine, FirstIndex);
}
strcat(RegLine, ":");
strcat(RegLine, " ");
if (RegCnt > 1) {
strcat(RegLine, " ");
strcat(RegLine, " ");
} else {
AddByte(RegLine, NumRegsToInit);
}
WriteCh(RegLine, ' ');
}
if (RegCnt <= NumRegsToInit) {
RegValue = GetWordDC();
AddWord(RegLine, RegValue);
WriteCh(RegLine, ' ');
}
} while (RegCnt < NumRegsToInit);
} else {
strcpy(RegLine, "R");
WriteCh(RegLine, ' ');
AddWord(RegLine, FirstPage);
AddByte(RegLine, FirstIndex);
strcat(RegLine, ":");
strcat(RegLine, " ");
AddByte(RegLine, NumRegsToInit);
}
PrintString(RegLine);
ChkWait();
WriteDump = OldWriteDump;
} /* DisRegList */
Static void GetJump(char SourceType, boolean *TrueJump, int *Distance) {
int Offset;
int HighByte;
int LowByte;
if (SourceType == FromDC)
Offset = GetByteDC();
else
Offset = GetByteIPC();
*TrueJump = cTrueJump(Offset);
if (cShort(Offset)) {
Offset = cDistance(Offset);
} else {
HighByte = cDistance(Offset);
if (SourceType == FromDC)
LowByte = GetByteDC();
else
LowByte = GetByteIPC();
Offset = JoinBytes(LowByte, HighByte);
if (TstBit(Offset, 13))
Offset = lor(Offset, -16384);
}
*Distance = Offset;
} /* GetJump */
Static void CalcJump(int FromPageNo, int FromPageIndex, int *ToPageNo,
int *ToPageIndex, int Offset) {
int DestPageNo;
int DestIndex;
int HighByte;
int LowByte;
SplitWord(Offset - 2, &LowByte, &HighByte);
if (CodeVersion < '4')
DestPageNo = lsl(HighByte, 1);
else
DestPageNo = lsl(HighByte, 2);
DestPageNo = lor(land(DestPageNo, HighByteMask), HighByte);
DestIndex = FromPageIndex + LowByte;
while (DestIndex >= 256) {
DestIndex -= 256;
++DestPageNo;
}
while (DestIndex < 0) {
DestIndex += 256;
--DestPageNo;
}
DestPageNo += FromPageNo;
if (CodeVersion < '4')
DestPageNo = land(DestPageNo, 511);
else
DestPageNo = land(DestPageNo, 1023);
*ToPageNo = DestPageNo;
*ToPageIndex = DestIndex;
} /* CalcJump */
Static void PutBPTCode(PtrBPT WrkBPT) {
int PageNo;
int PageIndex;
PageNo = WrkBPT->BPT_PageNo;
PageIndex = WrkBPT->BPT_PageIndex;
WrkBPT->OrgByte1 = PagePtrs[PageNo][PageIndex];
PagePtrs[PageNo][PageIndex] = 0; /* BPT #xx #xx */
Inc(&PageNo, &PageIndex, 1);
WrkBPT->OrgByte2 = PagePtrs[PageNo][PageIndex];
PagePtrs[PageNo][PageIndex] = WrkBPT->BPT_No;
Inc(&PageNo, &PageIndex, 1);
WrkBPT->OrgByte3 = PagePtrs[PageNo][PageIndex];
PagePtrs[PageNo][PageIndex] = WrkBPT->BPT_Type;
} /* PutBPTCode */
Static void PutOrgCode(PtrBPT WrkBPT) {
int PageNo;
int PageIndex;
PageNo = WrkBPT->BPT_PageNo;
PageIndex = WrkBPT->BPT_PageIndex;
PagePtrs[PageNo][PageIndex] = WrkBPT->OrgByte1;
Inc(&PageNo, &PageIndex, 1);
PagePtrs[PageNo][PageIndex] = WrkBPT->OrgByte2;
Inc(&PageNo, &PageIndex, 1);
PagePtrs[PageNo][PageIndex] = WrkBPT->OrgByte3;
} /* PutOrgCode */
Static void SetBPT(int BPT_No, int BPT_PageNo, int BPT_PageIndex,
char BPT_Type) {
PtrBPT NewBPT;
++BPT_IdCnt;
NewBPT = Malloc(signedsizeof(aBPT));
NewBPT->BPT_No = BPT_No;
NewBPT->HitCnt = 0;
NewBPT->BPT_PageNo = BPT_PageNo;
NewBPT->BPT_PageIndex = BPT_PageIndex;
NewBPT->BPT_Type = BPT_Type;
NewBPT->NextBPT = BPT_List;
BPT_List = NewBPT;
PutBPTCode(NewBPT);
} /* SetBPT */
Static void ClearBPT(int BPT_No) {
PtrBPT WrkBPT;
PtrBPT PredBPT;
boolean Cleared;
Cleared = false;
WrkBPT = BPT_List;
PredBPT = NULL;
while (WrkBPT != NULL) {
if (WrkBPT->BPT_No != BPT_No) {
PredBPT = WrkBPT;
WrkBPT = WrkBPT->NextBPT;
continue;
}
PutOrgCode(WrkBPT);
if (PredBPT == NULL)
BPT_List = WrkBPT->NextBPT;
else
PredBPT->NextBPT = WrkBPT->NextBPT;
Free(WrkBPT);
WrkBPT = NULL;
Cleared = true;
}
if (!Cleared)
HandleError(false, "Break-point not found.", false);
} /* ClearBPT */
Static void PrintBPTs(void) {
PtrBPT WrkBPT;
PrintString("Current BPT-Id:");
PrintByte(BPT_IdCnt, 3);
ChkWait();
WrkBPT = BPT_List;
while (WrkBPT != NULL) {
PrintWord(WrkBPT->BPT_PageNo, 4);
PrintByte(WrkBPT->BPT_PageIndex, 2);
PrintString(": BPT #");
PrintByte(WrkBPT->BPT_No, 2);
PrintString(" hits=");
PrintWord(WrkBPT->HitCnt, 4);
switch (WrkBPT->BPT_Type) {
case UndefinedBPT:
PrintString(" undefined");
break;
case UserBPT:
PrintString(" user");
break;
case RunBPT:
PrintString(" run");
break;
case TraceBPT:
PrintString(" trace");
break;
}
ChkWait();
WrkBPT = WrkBPT->NextBPT;
}
} /* PrintBPTs */
typedef Char MnemString[256];
/* Local variables for Disassemble: */
struct Disassemble_LocalVariables {
boolean GetCmdCode;
boolean DumpText;
boolean NextCouldBeEntryPoint;
boolean NextShouldBeEntryPoint;
boolean InstIsBPT;
Char CmdLine[256];
} ;
Local void WriteAddressMode(Char Line[256], int AddressMode,
struct Disassemble_LocalVariables *Disassemble_Vars) {
if (!Disassemble_Vars->GetCmdCode) {
strcat(Line, "Rx");
return;
}
if (AddressMode == 0) {
WriteCh(Line, 'S');
return;
}
if (AddressMode < 16) {
WriteCh(Line, 'R');
WriteCh(Line, HexChars[Nibble(AddressMode - 1, 0)]);
} else {
WriteCh(Line, '*');
AddWord(Line, (AddressMode - 16) * 2);
}
} /* WriteAddressMode */
Local void DisAddressMode(boolean Load, boolean Indirect,
struct Disassemble_LocalVariables *Disassemble_Vars) {
int AddressMode;
if (Disassemble_Vars->GetCmdCode)
AddressMode = GetByteDC();
if (!Load) {
strcat(Disassemble_Vars->CmdLine, "->");
strcat(Disassemble_Vars->CmdLine, " ");
}
if (Indirect)
WriteCh(Disassemble_Vars->CmdLine, '(');
if (Disassemble_Vars->GetCmdCode) {
if (AddressMode == 0) {
if (Load)
WriteCh(Disassemble_Vars->CmdLine, '-');
else
WriteCh(Disassemble_Vars->CmdLine, '+');
}
WriteAddressMode(Disassemble_Vars->CmdLine, AddressMode, Disassemble_Vars);
} else {
strcat(Disassemble_Vars->CmdLine, "Rx");
}
if (Indirect)
WriteCh(Disassemble_Vars->CmdLine, ')');
} /* DisAddressMode */
Local void WriteJump(int Distance,
struct Disassemble_LocalVariables *Disassemble_Vars) {
int DestPageNo;
int DestIndex;
if (!Disassemble_Vars->GetCmdCode)
return;
CalcJump(DC_PageNo, DC_PageIndex, &DestPageNo, &DestIndex, Distance);
AddWord(Disassemble_Vars->CmdLine, DestPageNo);
AddByte(Disassemble_Vars->CmdLine, DestIndex);
} /* WriteJump */
Local void DisJump(struct Disassemble_LocalVariables *Disassemble_Vars) {
int Distance;
boolean TrueJump;
if (!Disassemble_Vars->GetCmdCode)
return;
GetJump(FromDC, &TrueJump, &Distance);
if (TrueJump)
strcat(Disassemble_Vars->CmdLine, "TJP");
else
strcat(Disassemble_Vars->CmdLine, "FJP");
strcat(Disassemble_Vars->CmdLine, " ");
if (Distance == 0) {
strcat(Disassemble_Vars->CmdLine, "RTF");
return;
}
if (Distance == 1)
strcat(Disassemble_Vars->CmdLine, "RTT");
else
WriteJump(Distance, Disassemble_Vars);
} /* DisJump */
Local void IllegalCmd(struct Disassemble_LocalVariables *Disassemble_Vars) {
Char Mnem[256];
strcpy(Mnem, "$");
AddByte(Mnem, CmdCode);
if (*Disassemble_Vars->CmdLine == '\0')
strcpy(Disassemble_Vars->CmdLine, " ");
strinsert(Mnem, (void *)Disassemble_Vars->CmdLine, 1);
Disassemble_Vars->NextCouldBeEntryPoint = true;
Disassemble_Vars->NextShouldBeEntryPoint = (CmdCode == 0);
} /* IllegalCmd */
Local void HandleEntryAddress(int EntryAddress,
struct Disassemble_LocalVariables *Disassemble_Vars) {
int PageNo;
int PageIndex;
WriteCh(Disassemble_Vars->CmdLine, '#');
SaveEntryPoint(EntryAddress);
CalcCallAddress(EntryAddress, &PageNo, &PageIndex);
AddWord(Disassemble_Vars->CmdLine, PageNo);
AddByte(Disassemble_Vars->CmdLine, PageIndex);
} /* HandleEntryAddress */
Local void CheckIfRegList(struct Disassemble_LocalVariables *Disassemble_Vars) {
int EntryCnt;
int ListPageNo;
int ListIndex;
int AddressPageNo;
int AddressIndex;
int Value1;
int Value2;
int Code;
boolean GotRegList;
boolean FetchedNext;
GotRegList = false;
FetchedNext = false;
ListPageNo = DC_PageNo;
ListIndex = DC_PageIndex;
Code = GetByteDC();
if (Code < 16 &&
(CodeVersion <= '3' && (ListIndex & 1) == 0 ||
CodeVersion >= '4' && CodeVersion <= '5' && (ListIndex & 3) == 0 ||
CodeVersion >= '6' && (ListIndex & 3) == 0)) {
EntryCnt = EntryIndex - 1;
while (EntryCnt >= 0 && !GotRegList) {
CalcCallAddress(EntryPoints[EntryCnt], &AddressPageNo, &AddressIndex);
if (AddressPageNo == ListPageNo && AddressIndex == ListIndex)
GotRegList = true;
else
--EntryCnt;
}
if (!GotRegList && (Disassemble_Vars->NextCouldBeEntryPoint ||
Disassemble_Vars->NextShouldBeEntryPoint)) {
if (CodeVersion < '5') {
if (Code == 0) {
Value1 = GetByteDC();
GotRegList = (Value1 != 0);
FetchedNext = true;
} else {
GotRegList = (Disassemble_Vars->NextShouldBeEntryPoint ||
(unsigned)Code < 32 && ((1 << Code) & 0x3f0038e) != 0);
}
if (!GotRegList && (unsigned)Code < 32 && ((1 << Code) & 0x7c70) != 0) {
Value1 = GetByteDC();
Value2 = GetByteDC();
FetchedNext = true;
GotRegList = (((unsigned)Code < 32 && ((1 << Code) & 0x4040) != 0 &&
(Value1 == 0 || Value2 == 0)) ||
((unsigned)Code < 32 &&
((1 << Code) & 0xe3c30) != 0 && Value1 == 0));
/* OIN,INS */
/* TSF,SEF,CLF,LDP,LPA,LNP */
}
} else {
GotRegList = false;
}
}
}
if (!GotRegList || FetchedNext) {
DC_PageIndex = ListIndex;
DC_PageNo = ListPageNo;
if (GotRegList)
Code = GetByteDC();
}
Disassemble_Vars->NextCouldBeEntryPoint = false;
Disassemble_Vars->NextShouldBeEntryPoint = false;
if (GotRegList)
DisRegList(Code);
} /* CheckIfRegList */
Local void GetTwoOperands(struct Disassemble_LocalVariables *Disassemble_Vars) {
int Wrk0;
int Wrk1;
int Op5;
Op5 = cOp5(CmdCode);
if (!((Op5 < 25 || Op5 < 26 && CodeVersion == '4' ||
Op5 < 29 && CodeVersion >= '5') &&
(Op5 != 0 || Disassemble_Vars->InstIsBPT)))
return;
WriteCh(Disassemble_Vars->CmdLine, ' ');
if (TstBit(CmdCode, 6)) { /* DLS,IGT,SEW */
DisAddressMode(true, (unsigned)Op5 < 32 && ((1 << Op5) & 0x2030) != 0,
Disassemble_Vars);
} else {
if (Disassemble_Vars->GetCmdCode)
Wrk0 = GetByteDC();
if ((unsigned)Op5 < 32 && ((1 << Op5) & 0x2030) != 0) {
WriteAddressMode(Disassemble_Vars->CmdLine, Wrk0, Disassemble_Vars);
} else if ((Op5 == 25 || Op5 == 26) && Disassemble_Vars->GetCmdCode) {
HandleEntryAddress(Wrk0, Disassemble_Vars);
} else {
WriteCh(Disassemble_Vars->CmdLine, '#');
if (Disassemble_Vars->GetCmdCode)
AddByte(Disassemble_Vars->CmdLine, Wrk0);
else
strcat(Disassemble_Vars->CmdLine, "xx");
}
}
WriteCh(Disassemble_Vars->CmdLine, ' ');
if (TstBit(CmdCode, 5)) {
DisAddressMode(true, false, Disassemble_Vars);
} else {
WriteCh(Disassemble_Vars->CmdLine, '#');
if (Disassemble_Vars->GetCmdCode) {
Wrk1 = GetByteDC();
AddByte(Disassemble_Vars->CmdLine, Wrk1);
} else {
strcat(Disassemble_Vars->CmdLine, "xx");
}
}
WriteCh(Disassemble_Vars->CmdLine, ' ');
/* CFC */
/* CPC */
} /* GetTwoOperands */
Local void ListTwoOperandOperation(struct Disassemble_LocalVariables *Disassemble_Vars) {
int Op5;
MnemString CmdMnem;
Op5 = cOp5(CmdCode);
if (Op5 >= 29 || Op5 == 0 && !Disassemble_Vars->InstIsBPT) {
IllegalCmd(Disassemble_Vars);
return;
}
switch (Op5) {
case 8:
case 9:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
/* LOR,AND,LDW,LDB,LDP,LPA,LNP,ADD,SUB,MUL,DIV,MOD,CFC */
DisAddressMode(false, false, Disassemble_Vars);
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 10:
/* EQU,LES,GRT,DLS,IGT,OIN,TST,LOR,AND,TSF */
DisJump(Disassemble_Vars);
break;
}
switch (Op5) {
case 0:
strcpy(CmdMnem, "BPT");
break;
case 1:
strcpy(CmdMnem, "EQU");
break;
case 2:
strcpy(CmdMnem, "LES");
break;
case 3:
strcpy(CmdMnem, "GRT");
break;
case 4:
strcpy(CmdMnem, "DLS");
break;
case 5:
strcpy(CmdMnem, "IGT");
break;
case 6:
strcpy(CmdMnem, "OIN");
break;
case 7:
strcpy(CmdMnem, "TST");
break;
case 8:
strcpy(CmdMnem, "LOR");
break;
case 9:
strcpy(CmdMnem, "AND");
break;
case 10:
strcpy(CmdMnem, "TSF");
break;
case 11:
strcpy(CmdMnem, "SEF");
break;
case 12:
strcpy(CmdMnem, "CLF");
break;
case 13:
strcpy(CmdMnem, "SEW");
break;
case 14:
strcpy(CmdMnem, "INS");
break;
case 15:
strcpy(CmdMnem, "LDW");
break;
case 16:
strcpy(CmdMnem, "LDB");
break;
case 17:
strcpy(CmdMnem, "LDP");
break;
case 18:
strcpy(CmdMnem, "LPA");
break;
case 19:
strcpy(CmdMnem, "LNP");
break;
case 20:
strcpy(CmdMnem, "ADD");
break;
case 21:
strcpy(CmdMnem, "SUB");
break;
case 22:
strcpy(CmdMnem, "MUL");
break;
case 23:
strcpy(CmdMnem, "DIV");
break;
case 24:
strcpy(CmdMnem, "MOD");
break;
case 25:
strcpy(CmdMnem, "CFC");
break;
case 26:
strcpy(CmdMnem, "CPC");
break;
case 27:
strcpy(CmdMnem, "N27");
break;
case 28:
strcpy(CmdMnem, "RTM");
break;
}
if (*Disassemble_Vars->CmdLine == '\0')
strcpy(Disassemble_Vars->CmdLine, CmdMnem);
else
strinsert(CmdMnem, (void *)Disassemble_Vars->CmdLine, 1);
} /* TwoOperandOperation */
/* Local variables for GetOneOperand: */
struct GetOneOperand_LocalVariables {
struct Disassemble_LocalVariables *Disassemble_Vars;
} ;
Local void WriteImmediate(int Value, int Op4,
struct GetOneOperand_LocalVariables *GetOneOperand_Vars) {
if ((unsigned)Op4 < 32 && ((1 << Op4) & 0x4060) != 0) { /* INC,DEC,MVE */
WriteAddressMode(GetOneOperand_Vars->Disassemble_Vars->CmdLine, Value,
GetOneOperand_Vars->Disassemble_Vars);
return;
}
if (Op4 == 12 && GetOneOperand_Vars->Disassemble_Vars->GetCmdCode)
{ /* JMP */
WriteJump(Value, GetOneOperand_Vars->Disassemble_Vars);
return;
}
if (GetOneOperand_Vars->Disassemble_Vars->GetCmdCode &&
(Op4 == 8 || Op4 == 15 && CodeVersion >= '5'))
{ /* CFC */
HandleEntryAddress(Value, GetOneOperand_Vars->Disassemble_Vars);
return;
}
/* CPC */
WriteCh(GetOneOperand_Vars->Disassemble_Vars->CmdLine, '#');
if (GetOneOperand_Vars->Disassemble_Vars->GetCmdCode)
AddWord(GetOneOperand_Vars->Disassemble_Vars->CmdLine, Value);
else
strcat(GetOneOperand_Vars->Disassemble_Vars->CmdLine, "xxxx");
} /* WriteImmediate */
Local void GetOneOperand(struct Disassemble_LocalVariables *Disassemble_Vars) {
struct GetOneOperand_LocalVariables V;
int ImmediateValue;
int Op4;
V.Disassemble_Vars = Disassemble_Vars;
Op4 = cOp4(CmdCode);
WriteCh(Disassemble_Vars->CmdLine, ' ');
switch (cMode(CmdCode)) {
case 0:
if (Disassemble_Vars->GetCmdCode)
ImmediateValue = GetWordDC();
WriteImmediate(ImmediateValue, Op4, &V);
break;
case 1:
if (Disassemble_Vars->GetCmdCode)
ImmediateValue = GetByteDC();
WriteImmediate(ImmediateValue, Op4, &V);
break;
case 2: /* INC,DEC,MVE */
DisAddressMode(true, (unsigned)Op4 < 32 && ((1 << Op4) & 0x4060) != 0,
Disassemble_Vars);
break;
}
} /* GetOneOperand */
Local void ListOneOperandOperation(struct Disassemble_LocalVariables *Disassemble_Vars) {
int Op4;
MnemString CmdMnem;
Op4 = cOp4(CmdCode);
WriteCh(Disassemble_Vars->CmdLine, ' ');
if ((unsigned)Op4 < 32 && ((1 << Op4) & 0x411e) != 0 ||
Op4 == 15 && CodeVersion < '5')
{ /* NXO,FSO,PTO,LPS,CFC,MVE,NEG */
DisAddressMode(false, false, Disassemble_Vars);
WriteCh(Disassemble_Vars->CmdLine, ' ');
}
/* NEG */
if ((unsigned)Op4 < 32 && ((1 << Op4) & 0x7) != 0) /* EQN,NXO,FSO */
DisJump(Disassemble_Vars);
switch (Op4) {
case 0:
strcpy(CmdMnem, "EQN");
break;
case 1:
strcpy(CmdMnem, "NXO");
break;
case 2:
strcpy(CmdMnem, "FSO");
break;
case 3:
strcpy(CmdMnem, "PTO");
break;
case 4:
strcpy(CmdMnem, "LPS");
break;
case 5:
strcpy(CmdMnem, "INC");
break;
case 6:
strcpy(CmdMnem, "DEC");
break;
case 7:
strcpy(CmdMnem, "WSB");
break;
case 8:
if (CodeVersion < '4') {
strcpy(CmdMnem, "$");
AddByte(CmdMnem, CmdCode);
Disassemble_Vars->NextCouldBeEntryPoint = true;
} else {
strcpy(CmdMnem, "CFC");
}
break;
case 9:
strcpy(CmdMnem, "RMO");
break;
case 10:
strcpy(CmdMnem, "WTO");
break;
case 11:
strcpy(CmdMnem, "RTN");
Disassemble_Vars->NextCouldBeEntryPoint = true;
break;
case 12:
strcpy(CmdMnem, "JMP");
Disassemble_Vars->NextCouldBeEntryPoint = true;
break;
case 13:
strcpy(CmdMnem, "WSW");
break;
case 14:
strcpy(CmdMnem, "MVE");
break;
case 15:
if (CodeVersion < '5')
strcpy(CmdMnem, "NEG");
else
strcpy(CmdMnem, "CPC");
break;
}
strinsert(CmdMnem, (void *)Disassemble_Vars->CmdLine, 1);
} /* OneOperandOperation */
/* Local variables for GetMultipleOperands: */
struct GetMultipleOperands_LocalVariables {
struct Disassemble_LocalVariables *Disassemble_Vars;
boolean PureMultiple;
boolean Indirect;
int BitlCnt;
int Value;
int Op5;
} ;
Local void WriteImmediateValueOrCallAddress(boolean IsWord,
struct GetMultipleOperands_LocalVariables *GetMultipleOperands_Vars) {
if (GetMultipleOperands_Vars->Indirect) {
WriteAddressMode(GetMultipleOperands_Vars->Disassemble_Vars->CmdLine,
GetMultipleOperands_Vars->Value,
GetMultipleOperands_Vars->Disassemble_Vars);
return;
}
if ((GetMultipleOperands_Vars->PureMultiple &&
((GetMultipleOperands_Vars->BitlCnt == 3 &&
(GetMultipleOperands_Vars->Op5 == 0 ||
GetMultipleOperands_Vars->Op5 == 25)) ||
(GetMultipleOperands_Vars->BitlCnt == 7 &&
(GetMultipleOperands_Vars->Op5 == 12 ||
GetMultipleOperands_Vars->Op5 == 26)) ||
(GetMultipleOperands_Vars->BitlCnt == 1 &&
GetMultipleOperands_Vars->Op5 == 22))) ||
(!GetMultipleOperands_Vars->PureMultiple &&
GetMultipleOperands_Vars->BitlCnt == 3 &&
(GetMultipleOperands_Vars->Op5 == 25 ||
GetMultipleOperands_Vars->Op5 == 26))) {
HandleEntryAddress(GetMultipleOperands_Vars->Value,
GetMultipleOperands_Vars->Disassemble_Vars);
return;
}
WriteCh(GetMultipleOperands_Vars->Disassemble_Vars->CmdLine, '#');
if (IsWord)
AddWord(GetMultipleOperands_Vars->Disassemble_Vars->CmdLine,
GetMultipleOperands_Vars->Value);
else
AddByte(GetMultipleOperands_Vars->Disassemble_Vars->CmdLine,
GetMultipleOperands_Vars->Value);
} /* WriteImmediateValueOrCallAddress */
Local void GetMultipleOperands(boolean Extended, boolean NewMultiple,
struct Disassemble_LocalVariables *Disassemble_Vars) {
struct GetMultipleOperands_LocalVariables V;
int Mode;
boolean ListEnd;
V.Disassemble_Vars = Disassemble_Vars;
V.Op5 = cOp5(CmdCode);
V.PureMultiple = (NewMultiple || CmdCode >= 224); /* $E0 */
if (Extended) {
Mode = GetWordDC();
V.BitlCnt = 7;
} else {
Mode = GetByteDC();
V.BitlCnt = 3;
}
ListEnd = false;
WriteCh(Disassemble_Vars->CmdLine, ' ');
while (!ListEnd) {
V.Indirect = (V.BitlCnt == 3 &&
(CmdCode == 233 ||
(!V.PureMultiple && (unsigned)V.Op5 < 32 &&
((1 << V.Op5) & 0x2030) != 0)));
/* PUL */
/* DLS,IGT,SEW */
switch (Bittle(Mode, V.BitlCnt)) {
case 0:
V.Value = GetWordDC();
WriteImmediateValueOrCallAddress(true, &V);
break;
case 1:
V.Value = GetByteDC();
WriteImmediateValueOrCallAddress(false, &V);
break;
case 2:
DisAddressMode(true, V.Indirect, Disassemble_Vars);
break;
case 3:
ListEnd = true;
break;
}
if (ListEnd)
break;
WriteCh(Disassemble_Vars->CmdLine, ' ');
if (V.BitlCnt > 0)
--V.BitlCnt;
else
ListEnd = true;
}
} /* GetMultipleOperands */
Local void ListMultipleOperandOperation(boolean NewVersion,
struct Disassemble_LocalVariables *Disassemble_Vars) {
int Op5;
MnemString CmdMnem;
Op5 = cOp5(CmdCode);
if (Op5 >= 12 && CodeVersion < '4' || Op5 >= 24 && CodeVersion < '5') {
IllegalCmd(Disassemble_Vars);
return;
}
if ((unsigned)Op5 < 32 && ((1 << Op5) & 0xc01081) != 0 ||
CodeVersion >= '5' && (Op5 == 4 || Op5 == 24) ||
CodeVersion >= '6' && Op5 == 9)
/* CFC,RND,CFC,INK,BEQ */
DisAddressMode(false, false, Disassemble_Vars);
/* INP */
/* NEG */
/* PUL */
if (Op5 == 23) {
WriteCh(Disassemble_Vars->CmdLine, ' ');
DisJump(Disassemble_Vars);
}
if (Op5 == 31)
DisJump(Disassemble_Vars);
switch (Op5) {
case 0:
strcpy(CmdMnem, "CFC");
break;
case 1:
strcpy(CmdMnem, "STW");
break;
case 2:
strcpy(CmdMnem, "STB");
break;
case 3:
strcpy(CmdMnem, "STP");
break;
case 4:
strcpy(CmdMnem, "INP");
break;
case 5:
strcpy(CmdMnem, "WTC");
break;
case 6:
strcpy(CmdMnem, "WTI");
break;
case 7:
strcpy(CmdMnem, "RND");
break;
case 8:
strcpy(CmdMnem, "PSH");
break;
case 9:
strcpy(CmdMnem, "PUL");
break;
case 10:
strcpy(CmdMnem, "SPL");
break;
case 11:
strcpy(CmdMnem, "POS");
break;
case 12:
strcpy(CmdMnem, "CFC");
break;
case 13:
strcpy(CmdMnem, "ERS");
break;
case 14:
strcpy(CmdMnem, "ERL");
break;
case 15:
strcpy(CmdMnem, "GYX");
break;
case 16:
strcpy(CmdMnem, "NO2");
break;
case 17:
strcpy(CmdMnem, "SCM");
break;
case 18:
strcpy(CmdMnem, "FRM");
break;
case 19:
strcpy(CmdMnem, "OUT");
break;
case 20:
strcpy(CmdMnem, "COM");
break;
case 21:
strcpy(CmdMnem, "BEL");
break;
case 22:
strcpy(CmdMnem, "INK");
break;
case 23:
strcpy(CmdMnem, "BEQ");
break;
case 24:
strcpy(CmdMnem, "NEG");
break;
case 25:
strcpy(CmdMnem, "CPC");
break;
case 26:
strcpy(CmdMnem, "CPC");
break;
case 27:
strcpy(CmdMnem, "PRS");
break;
case 28:
strcpy(CmdMnem, "PAK");
break;
case 29:
strcpy(CmdMnem, "BCP");
break;
case 30:
strcpy(CmdMnem, "WTA");
break;
case 31:
strcpy(CmdMnem, "MNP");
break;
}
strinsert(CmdMnem, (void *)Disassemble_Vars->CmdLine, 1);
} /* ListMultipleOperandOperation */
Local void ListNewMultipleOperandOperation(struct Disassemble_LocalVariables *Disassemble_Vars) {
MnemString CmdMnem;
if (CmdCode >= 29) {
IllegalCmd(Disassemble_Vars);
return;
}
if ((unsigned)CmdCode < 32 && ((1 << CmdCode) & 0x8061f) != 0) {
/* SVE,RSE,LSL,ASL,FNT,X09,X10,X19 */
DisAddressMode(false, false, Disassemble_Vars);
}
if ((unsigned)CmdCode < 32 && ((1 << CmdCode) & 0x1000040) != 0)
/* TSB,X24 */
DisJump(Disassemble_Vars);
switch (CmdCode) {
case 0:
strcpy(CmdMnem, "SVE");
break;
case 1:
strcpy(CmdMnem, "RSE");
break;
case 2:
strcpy(CmdMnem, "LSL");
break;
case 3:
strcpy(CmdMnem, "ASL");
break;
case 4:
strcpy(CmdMnem, "FNT");
break;
case 5:
strcpy(CmdMnem, "CLR");
break;
case 6:
strcpy(CmdMnem, "TSB");
break;
case 7:
strcpy(CmdMnem, "SET");
break;
case 8:
strcpy(CmdMnem, "SWD");
break;
case 9:
strcpy(CmdMnem, "X09");
break;
case 10:
strcpy(CmdMnem, "X10");
break;
case 11:
strcpy(CmdMnem, "X11");
break;
case 12:
strcpy(CmdMnem, "X12");
break;
case 13:
strcpy(CmdMnem, "X13");
break;
case 14:
strcpy(CmdMnem, "X14");
break;
case 15:
strcpy(CmdMnem, "X15");
break;
case 16:
strcpy(CmdMnem, "X16");
break;
case 17:
strcpy(CmdMnem, "X17");
break;
case 18:
strcpy(CmdMnem, "X18");
break;
case 19:
strcpy(CmdMnem, "X19");
break;
case 20:
strcpy(CmdMnem, "X20");
break;
case 21:
strcpy(CmdMnem, "X21");
break;
case 22:
strcpy(CmdMnem, "X22");
break;
case 23:
strcpy(CmdMnem, "X23");
break;
case 24:
strcpy(CmdMnem, "X24");
break;
case 25:
strcpy(CmdMnem, "X25");
break;
case 26:
strcpy(CmdMnem, "X26");
break;
case 27:
strcpy(CmdMnem, "X27");
break;
case 28:
strcpy(CmdMnem, "X28");
break;
}
if (*CmdMnem != '\0')
strinsert(CmdMnem, (void *)Disassemble_Vars->CmdLine, 1);
} /* ListNewMultipleOperandOperation */
Local void ListNoOperandOperation(struct Disassemble_LocalVariables *Disassemble_Vars) {
MnemString CmdMnem;
int Op4;
Op4 = cOp4(CmdCode);
if (Op4 >= 14 && CodeVersion < '5') {
IllegalCmd(Disassemble_Vars);
} else {
if ((unsigned)Op4 < 32 && ((1 << Op4) & 0xa060) != 0)
{ /* SVE,RSO,VFY,jmpop */
if (Op4 != 15)
WriteCh(Disassemble_Vars->CmdLine, ' ');
if (CodeVersion < '4' || Op4 == 15)
DisJump(Disassemble_Vars);
else
DisAddressMode(false, false, Disassemble_Vars);
}
Disassemble_Vars->DumpText = ((unsigned)Op4 < 32 &&
((1 << Op4) & 0xc) != 0 &&
Disassemble_Vars->GetCmdCode);
switch (Op4) {
case 0:
strcpy(CmdMnem, "RTT");
Disassemble_Vars->NextCouldBeEntryPoint = true;
break;
case 1:
strcpy(CmdMnem, "RTF");
Disassemble_Vars->NextCouldBeEntryPoint = true;
break;
case 2:
strcpy(CmdMnem, "WTX");
break;
case 3:
strcpy(CmdMnem, "WTR");
Disassemble_Vars->NextCouldBeEntryPoint = true;
break;
case 4:
strcpy(CmdMnem, "NOP");
break;
case 5:
strcpy(CmdMnem, "SVE");
break;
case 6:
strcpy(CmdMnem, "RSO");
break;
case 7:
strcpy(CmdMnem, "RST");
break;
case 8:
strcpy(CmdMnem, "RPL");
Disassemble_Vars->NextCouldBeEntryPoint = true;
break;
case 9:
if (CodeVersion < '5')
strcpy(CmdMnem, "DSC");
else
strcpy(CmdMnem, "PMP");
break;
case 10:
strcpy(CmdMnem, "END");
break;
case 11:
strcpy(CmdMnem, "NWL");
break;
case 12:
strcpy(CmdMnem, "PSL");
break;
case 13:
strcpy(CmdMnem, "VFY");
break;
case 14:
if (Disassemble_Vars->GetCmdCode) {
CmdCode = GetByteDC();
GetMultipleOperands(false, true, Disassemble_Vars);
if (CmdCode >= 224) { /* $E0 */
ListMultipleOperandOperation(true, Disassemble_Vars);
} else if (CmdCode < 192)
ListNewMultipleOperandOperation(Disassemble_Vars);
else
ListTwoOperandOperation(Disassemble_Vars);
goto _L0;
}
strcpy(CmdMnem, "EXS");
break;
case 15:
*CmdMnem = '\0';
Disassemble_Vars->NextCouldBeEntryPoint = true;
break;
}
if (*Disassemble_Vars->CmdLine == '\0')
strcpy(Disassemble_Vars->CmdLine, " ");
strinsert(CmdMnem, (void *)Disassemble_Vars->CmdLine, 1);
}
_L0: ;
/* $C0 */
} /* ListNoOperandOperation */
Static void Disassemble(int NumLines, boolean GetCmdCode_) {
struct Disassemble_LocalVariables V;
PtrBPT WrkBPT;
int BPT_No;
int BPT_Type;
int DisInstPageNo;
int DisInstPageIndex;
int SpaceCnt;
int FORLIM;
V.GetCmdCode = GetCmdCode_;
if (DC_PageNo != OldPageNo || DC_PageIndex != OldIndex) {
BackPageNo = OldPageNo;
BackIndex = OldIndex;
OldPageNo = DC_PageNo;
OldIndex = DC_PageIndex;
}
LineCnt = 0;
V.InstIsBPT = false;
V.NextCouldBeEntryPoint = true;
V.NextShouldBeEntryPoint = false;
while (LineCnt < NumLines && EndPageNo < 0 ||
(DC_PageNo <= EndPageNo &&
(DC_PageNo != EndPageNo || DC_PageIndex <= EndPageIndex))) {
if (V.GetCmdCode) {
DisInstPageNo = DC_PageNo;
DisInstPageIndex = DC_PageIndex;
CmdCode = GetByteDC();
if (CmdCode == 0) {
BPT_No = GetByteDC();
if (BPT_No > 0) {
BPT_Type = GetByteDC();
if (BPT_Type == TraceBPT || BPT_Type == RunBPT ||
BPT_Type == UserBPT) {
WrkBPT = BPT_List;
while (WrkBPT != NULL) {
if (WrkBPT->BPT_No == BPT_No)
goto _L1;
WrkBPT = WrkBPT->NextBPT;
}
_L1:
V.InstIsBPT = (WrkBPT != NULL);
if (V.InstIsBPT && !DisBPTs)
PutOrgCode(WrkBPT);
}
}
}
DC_PageIndex = DisInstPageIndex;
DC_PageNo = DisInstPageNo;
if (TryRegList)
CheckIfRegList(&V);
}
DumpCnt = 0;
*V.CmdLine = '\0';
*Dump = '\0';
V.DumpText = false;
if (V.GetCmdCode) {
strcpy(Dump, "C");
WriteCh(Dump, ' ');
AddWord(Dump, DC_PageNo);
AddByte(Dump, DC_PageIndex);
WriteCh(Dump, ':');
CmdCode = GetByteDC();
}
if (CmdCode < 128) { /* $80 */
GetTwoOperands(&V);
ListTwoOperandOperation(&V);
} else if (CmdCode < 176) {
GetOneOperand(&V);
ListOneOperandOperation(&V);
} else if (CmdCode < 192) {
ListNoOperandOperation(&V);
} else {
if (V.GetCmdCode) /* $EC, extended CFC */
GetMultipleOperands(CmdCode == 236 || CmdCode == 250, false, &V);
else
strcat(V.CmdLine, " multiple ");
/* $FA, extended CPC */
if (CmdCode < 224) /* $E0 */
ListTwoOperandOperation(&V);
else
ListMultipleOperandOperation(false, &V);
}
if (V.InstIsBPT && !DisBPTs) {
PutBPTCode(WrkBPT);
Dump[1] = '-';
V.InstIsBPT = false;
}
if (V.GetCmdCode) {
PrintString(Dump);
FORLIM = (12 - DumpCnt) * 3;
for (SpaceCnt = 1; SpaceCnt <= FORLIM; ++SpaceCnt)
PrintCh(' ');
PrintString(V.CmdLine);
} else {
PrintString(V.CmdLine);
LineCnt = 1;
}
ChkWait();
if (V.DumpText)
WriteText('T', OntoScreen, FromDC, GlobalTextBuffer);
}
/* $B0 */
/* $C0 */
} /* Disassemble */
Static void PrintReg(int RegNo) {
Char RegName[256];
strcpy(RegName, "R*=");
RegName[1] = HexChars[RegNo];
PrintString(RegName);
PrintWord(R.a[RegNo], 4);
} /* PrintReg */
Static void SaveCursorState(void) {
if (InStory) {
StoryCursorX = CursorX;
StoryCursorY = CursorY;
SaveTextAttributes();
ScreenMode = 0;
SetScreenMode();
StoryScrollTop = ScrollTop;
if (WindowEnabled) {
if (ScrollTop == ScreenHeight)
ScrollTop = ScreenHeight - 5;
ZM_GotoXY(1, ScreenHeight);
}
}
InStory = false;
} /* SaveCursorState */
Static void RestoreCursorState(void) {
InStory = true;
RestoreTextAttributes();
ScrollTop = StoryScrollTop;
if (!WindowEnabled)
return;
CursorX = StoryCursorX;
CursorY = StoryCursorY;
PositionCursor();
} /* RestoreCursorState */
Static void PrintZState(void) {
int RegCnt;
int StackCnt;
SaveCursorState();
PrintString("IPC=");
PrintWord(IPC_PageNo, 4);
PrintByte(IPC_PageIndex, 2);
PrintString(" SP=");
PrintWord(SP, 4);
PrintString(" MSP=");
PrintWord(MSP, 4);
PrintString(" TOS=");
for (StackCnt = 1; StackCnt <= 9; ++StackCnt) {
if (SP >= StackCnt)
PrintWord(Stack[SP - StackCnt], 4);
else
PrintString("----");
PrintCh(' ');
}
ChkWait();
for (RegCnt = 0; RegCnt <= 15; ++RegCnt) {
if (RegCnt == 8)
ChkWait();
PrintReg(RegCnt);
PrintCh(' ');
}
ChkWait();
} /* PrintZState */
Static void SetInterpreterConfiguration(void) {
int Wrk;
union {
tMiscInfo *mp;
uchar *pp;
} H;
H.pp = PagePtrs[0];
H.mp->mInterpreterNumber = CodeVersion - '0';
H.mp->mInterpreterVersion = _toupper(InterpreterChar);
H.mp->ScreenWidth = ScreenWidth;
H.mp->ScreenHeight = ScreenHeight - 1;
H.mp->Left = 0;
H.mp->Right = ScreenWidth;
H.mp->Top = 0;
H.mp->Bottom = ScreenHeight - 1;
H.mp->Unknown1 = 1;
H.mp->Unknown2 = 1;
H.mp->Unknown3 = 9;
H.mp->Unknown4 = 2;
Wrk = MiscInfo.ConfigFlags;
SetBit(&Wrk, 4);
SetBit(&Wrk, 5);
H.mp->ConfigFlags = Wrk;
MiscInfo.ConfigFlags = Wrk;
} /* SetInterpreterConfiguration */
Static void CalcObjAdrs(int ObjNo, int *ObjPageNo, int *ObjPageIndex,
int FieldOffset) {
*ObjPageNo = MiscInfo.ObjPageNo;
*ObjPageIndex = MiscInfo.ObjPageIndex;
Inc(ObjPageNo, ObjPageIndex, ObjNo * ObjRecSize + ObjOffset + FieldOffset);
} /* CalcObjAdrs */
Static void RemoveObj(int ObjNo) {
int ObjPageNo;
int ObjPageIndex;
int ParentObj;
int FirstObj;
int WrkObj;
int ParentPageNo;
int ParentPageIndex;
int PrevObj;
int PrevPageNo;
int PrevPageIndex;
int LowByte;
int HighByte;
if (CodeVersion < '4') {
CalcObjAdrs(ObjNo, &ObjPageNo, &ObjPageIndex, 4);
ParentObj = PagePtrs[ObjPageNo][ObjPageIndex];
} else {
CalcObjAdrs(ObjNo, &ObjPageNo, &ObjPageIndex, 6);
HighByte = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&ObjPageNo, &ObjPageIndex, 1);
LowByte = PagePtrs[ObjPageNo][ObjPageIndex];
ParentObj = JoinBytes(LowByte, HighByte);
}
if (ParentObj == 0)
return;
if (CodeVersion < '4') {
CalcObjAdrs(ParentObj, &ParentPageNo, &ParentPageIndex, 6);
FirstObj = PagePtrs[ParentPageNo][ParentPageIndex]; /* PTO.FSO */
} else {
CalcObjAdrs(ParentObj, &ParentPageNo, &ParentPageIndex, 10);
HighByte = PagePtrs[ParentPageNo][ParentPageIndex];
Inc(&ParentPageNo, &ParentPageIndex, 1);
LowByte = PagePtrs[ParentPageNo][ParentPageIndex];
FirstObj = JoinBytes(LowByte, HighByte);
}
if (FirstObj == ObjNo) {
Inc(&ObjPageNo, &ObjPageIndex, 1);
/* PTO.FSO:=OBJ.NXO */
if (CodeVersion < '4') {
PagePtrs[ParentPageNo][ParentPageIndex] = PagePtrs[ObjPageNo]
[ObjPageIndex];
} else {
AccB = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&ObjPageNo, &ObjPageIndex, 1);
PagePtrs[ParentPageNo][ParentPageIndex] = PagePtrs[ObjPageNo]
[ObjPageIndex];
Inc(&ParentPageNo, &ParentPageIndex, -1);
PagePtrs[ParentPageNo][ParentPageIndex] = AccB;
}
} else {
WrkObj = FirstObj;
do {
PrevObj = WrkObj;
/* WrkObj:=PrevObj.NXO */
if (CodeVersion < '4') {
CalcObjAdrs(PrevObj, &PrevPageNo, &PrevPageIndex, 5);
WrkObj = PagePtrs[PrevPageNo][PrevPageIndex];
} else {
CalcObjAdrs(PrevObj, &PrevPageNo, &PrevPageIndex, 8);
HighByte = PagePtrs[PrevPageNo][PrevPageIndex];
Inc(&PrevPageNo, &PrevPageIndex, 1);
LowByte = PagePtrs[PrevPageNo][PrevPageIndex];
WrkObj = JoinBytes(LowByte, HighByte);
}
} while (WrkObj != ObjNo);
Inc(&ObjPageNo, &ObjPageIndex, 1);
/* PrevObj.NXO:=OBJ.NXO */
if (CodeVersion < '4') {
PagePtrs[PrevPageNo][PrevPageIndex] = PagePtrs[ObjPageNo][ObjPageIndex];
} else {
AccB = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&ObjPageNo, &ObjPageIndex, 1);
PagePtrs[PrevPageNo][PrevPageIndex] = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&PrevPageNo, &PrevPageIndex, -1);
PagePtrs[PrevPageNo][PrevPageIndex] = AccB;
}
}
/* OBJ.NXO:=0 */
/* OBJ.PTO:=0 */
PagePtrs[ObjPageNo][ObjPageIndex] = 0;
Inc(&ObjPageNo, &ObjPageIndex, -1);
PagePtrs[ObjPageNo][ObjPageIndex] = 0;
if (CodeVersion < '4')
return;
Inc(&ObjPageNo, &ObjPageIndex, -1);
PagePtrs[ObjPageNo][ObjPageIndex] = 0;
Inc(&ObjPageNo, &ObjPageIndex, -1);
PagePtrs[ObjPageNo][ObjPageIndex] = 0;
} /* RemoveObj */
Static void InsertObj(int ObjNo, int IntoObjNo) {
int ObjPageNo;
int ObjPageIndex;
int IntoPageNo;
int IntoPageIndex;
int Next;
int LowByte;
int HighByte;
RemoveObj(ObjNo);
if (CodeVersion < '4') {
CalcObjAdrs(ObjNo, &ObjPageNo, &ObjPageIndex, 4);
/* ObjNo.PTO:=IntoObjNo */
PagePtrs[ObjPageNo][ObjPageIndex] = IntoObjNo;
CalcObjAdrs(IntoObjNo, &IntoPageNo, &IntoPageIndex, 6);
/* ObjNo.NXO:=PTO.FSO */
/* PTO.FSO:=ObjNo */
Inc(&ObjPageNo, &ObjPageIndex, 1);
Next = PagePtrs[IntoPageNo][IntoPageIndex];
PagePtrs[IntoPageNo][IntoPageIndex] = ObjNo;
PagePtrs[ObjPageNo][ObjPageIndex] = Next;
return;
}
CalcObjAdrs(ObjNo, &ObjPageNo, &ObjPageIndex, 6);
SplitWord(IntoObjNo, &LowByte, &HighByte);
PagePtrs[ObjPageNo][ObjPageIndex] = HighByte;
Inc(&ObjPageNo, &ObjPageIndex, 1);
PagePtrs[ObjPageNo][ObjPageIndex] = LowByte;
CalcObjAdrs(IntoObjNo, &IntoPageNo, &IntoPageIndex, 10);
Inc(&ObjPageNo, &ObjPageIndex, 1);
SplitWord(ObjNo, &LowByte, &HighByte);
Next = PagePtrs[IntoPageNo][IntoPageIndex];
PagePtrs[IntoPageNo][IntoPageIndex] = HighByte;
PagePtrs[ObjPageNo][ObjPageIndex] = Next;
Inc(&IntoPageNo, &IntoPageIndex, 1);
Inc(&ObjPageNo, &ObjPageIndex, 1);
Next = PagePtrs[IntoPageNo][IntoPageIndex];
PagePtrs[IntoPageNo][IntoPageIndex] = LowByte;
PagePtrs[ObjPageNo][ObjPageIndex] = Next;
} /* InsertObj */
Static boolean ObjInObj(int ObjNo, int InObjNo) {
int ObjPageNo;
int ObjPageIndex;
int ParentObj;
int LowByte;
int HighByte;
if (CodeVersion < '4') {
CalcObjAdrs(ObjNo, &ObjPageNo, &ObjPageIndex, 4);
ParentObj = PagePtrs[ObjPageNo][ObjPageIndex];
return (ParentObj == InObjNo);
}
CalcObjAdrs(ObjNo, &ObjPageNo, &ObjPageIndex, 6);
HighByte = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&ObjPageNo, &ObjPageIndex, 1);
LowByte = PagePtrs[ObjPageNo][ObjPageIndex];
ParentObj = JoinBytes(LowByte, HighByte);
return (ParentObj == InObjNo);
} /* ObjInObj */
Static boolean TestFlag(int ObjNo, int FlagNo) {
int ObjPageNo;
int ObjPageIndex;
int FlagsHigh;
int FlagsLow;
CalcObjAdrs(ObjNo, &ObjPageNo, &ObjPageIndex, FlagNo / 16 * 2);
FlagsHigh = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&ObjPageNo, &ObjPageIndex, 1);
FlagsLow = PagePtrs[ObjPageNo][ObjPageIndex];
return (TstBit(JoinBytes(FlagsLow, FlagsHigh), 15 - (FlagNo & 15)));
} /* TestFlag */
Static void SetFlag(int ObjNo, int FlagNo, boolean Value) {
int ObjPageNo;
int ObjPageIndex;
int HighPageNo;
int HighPageIndex;
int Flags;
int FlagsLow;
int FlagsHigh;
CalcObjAdrs(ObjNo, &ObjPageNo, &ObjPageIndex, FlagNo / 16 * 2);
FlagsHigh = PagePtrs[ObjPageNo][ObjPageIndex];
HighPageNo = ObjPageNo;
HighPageIndex = ObjPageIndex;
Inc(&ObjPageNo, &ObjPageIndex, 1);
FlagsLow = PagePtrs[ObjPageNo][ObjPageIndex];
Flags = JoinBytes(FlagsLow, FlagsHigh);
if (Value)
SetBit(&Flags, 15 - (FlagNo & 15));
else
ClrBit(&Flags, 15 - (FlagNo & 15));
SplitWord(Flags, &FlagsLow, &FlagsHigh);
PagePtrs[ObjPageNo][ObjPageIndex] = FlagsLow;
PagePtrs[HighPageNo][HighPageIndex] = FlagsHigh;
} /* SetFlag */
Static int GetWord(int GetMode) {
int DataPageNo;
int DataPageIndex;
int LowByte;
int HighByte;
if (GetMode == 0) {
return (Pop());
} else if (GetMode < 16) {
return (R.a[GetMode - 1]);
} else {
DataPageIndex = MiscInfo.DataPageIndex + (GetMode - 16) * 2;
DataPageNo = MiscInfo.DataPageNo;
ChkAddress(&DataPageNo, &DataPageIndex);
HighByte = PagePtrs[DataPageNo][DataPageIndex];
++DataPageIndex;
if (DataPageIndex >= 256) {
DataPageIndex = 0;
++DataPageNo;
}
LowByte = PagePtrs[DataPageNo][DataPageIndex];
return (JoinBytes(LowByte, HighByte));
}
} /* GetWord */
Static void PutWord(int theWord, int PutMode) {
int DataPageNo;
int DataPageIndex;
int LowByte;
int HighByte;
if (PutMode == 0) {
Push(theWord);
return;
}
if (PutMode < 16) {
R.a[PutMode - 1] = theWord;
return;
}
DataPageIndex = MiscInfo.DataPageIndex + (PutMode - 16) * 2;
DataPageNo = MiscInfo.DataPageNo;
ChkAddress(&DataPageNo, &DataPageIndex);
SplitWord(theWord, &LowByte, &HighByte);
PagePtrs[DataPageNo][DataPageIndex] = HighByte;
++DataPageIndex;
if (DataPageIndex >= 256) {
DataPageIndex = 0;
++DataPageNo;
}
PagePtrs[DataPageNo][DataPageIndex] = LowByte;
} /* PutWord */
Static void GetAccA(int GetMode) {
AccA = GetWord(GetMode);
if (GetMode == 0)
Push(AccA);
} /* GetAccA */
Static void PutAccA(int PutMode) {
int Discard;
if (PutMode == 0)
Discard = Pop();
PutWord(AccA, PutMode);
} /* PutAccA */
Static void PrintStatusLine(void) {
int Data0;
int Data1;
int Data2;
int RoomPageNo;
int RoomPageIndex;
int NamePageNo;
int NamePageIndex;
int OldCursorX;
int OldCursorY;
boolean OldPrintListing;
Char RoomName[256];
if (CodeVersion >= '4')
return;
OldPrintListing = PrintListing;
PrintListing = false;
SaveTextAttributes();
ScreenMode = 1;
SetScreenMode();
OldCursorX = CursorX;
OldCursorY = CursorY;
GotoXY(0, 0);
SetLength(Spaces, ScreenWidth);
PrintString(Spaces);
Data0 = GetWord(16);
Data1 = GetWord(17);
Data2 = GetWord(18);
CalcObjAdrs(Data0, &RoomPageNo, &RoomPageIndex, 7);
NamePageNo = PagePtrs[RoomPageNo][RoomPageIndex];
Inc(&RoomPageNo, &RoomPageIndex, 1);
NamePageIndex = PagePtrs[RoomPageNo][RoomPageIndex];
Inc(&NamePageNo, &NamePageIndex, 1);
Push(DC_PageNo);
Push(DC_PageIndex);
DC_PageNo = NamePageNo;
DC_PageIndex = NamePageIndex;
WriteText('N', IntoBuffer, FromDC, RoomName);
DC_PageIndex = Pop();
DC_PageNo = Pop();
GotoXY(1, 0);
PrintString(RoomName);
GotoXY(ScreenWidth - 20, 0);
if (TstBit(MiscInfo.ConfigFlags, 1)) {
PrintString("Time:");
PrintCh(' ');
if (Data1 == 0) {
PrintString("12");
} else if (Data1 > 12)
PrintInteger(Data1 - 12);
else
PrintInteger(Data1);
PrintCh(':');
if (Data2 < 10)
PrintCh('0');
PrintInteger(Data2);
if (Data1 < 12)
PrintString("am");
else
PrintString("pm");
} else {
PrintString("Score:");
PrintCh(' ');
PrintInteger(Data1);
PrintCh('/');
PrintInteger(Data2);
}
RestoreTextAttributes();
PrintListing = OldPrintListing;
CursorX = OldCursorX;
CursorY = OldCursorY;
PositionCursor();
} /* PrintStatusLine */
Static int GetPropertyNo(int ObjDataPageNo, int ObjDataPageIndex) {
if (CodeVersion < '4')
return (land(PagePtrs[ObjDataPageNo][ObjDataPageIndex], 31));
else
return (land(PagePtrs[ObjDataPageNo][ObjDataPageIndex], 63));
} /* GetPropertyNo */
Static int GetPropertySize(int *ObjDataPageNo, int *ObjDataPageIndex,
boolean FetchNext) {
int Data;
Data = PagePtrs[*ObjDataPageNo][*ObjDataPageIndex];
if (CodeVersion < '4') {
return (land(lsr(Data, 5), 7) + 1);
} else if (TstBit(Data, 7)) {
if (FetchNext)
Inc(ObjDataPageNo, ObjDataPageIndex, 1);
return (land(PagePtrs[*ObjDataPageNo][*ObjDataPageIndex], 63));
} else if (TstBit(Data, 6))
return 2;
else
return 1;
} /* GetPropertySize */
Static int DoGetWord(void) {
return (GetWord(GetByteIPC()));
} /* DoGetWord */
Static void DoPutWord(int theWord) {
PutWord(theWord, GetByteIPC());
} /* DoPutWord */
Static void Call(int Address, boolean IsFunc, int NumParams) {
int LowByte;
int HighByte;
int CallPageNo;
int CallPageIndex;
int NumLocalVariables;
int RegCnt;
int FORLIM;
if (Address == 0) {
if (IsFunc)
DoPutWord(0);
return;
}
Push(MSP);
Push(NewInstPageNo);
Push(NewInstPageIndex);
LowByte = IPC_PageIndex;
HighByte = IsFunc;
Push(JoinBytes(LowByte, HighByte));
Push(IPC_PageNo);
CalcCallAddress(Address, &CallPageNo, &CallPageIndex);
IPC_PageIndex = CallPageIndex;
IPC_PageNo = CallPageNo;
NumLocalVariables = GetByteIPC();
if (NumLocalVariables > 15)
InternalError(TooManyLocalVariables);
for (RegCnt = 0; RegCnt < NumLocalVariables; ++RegCnt) {
Push(R.a[RegCnt]);
if (CodeVersion <= '4')
R.a[RegCnt] = GetWordIPC();
else
R.a[RegCnt] = 0;
}
Push(NumCallParams);
NumCallParams = NumParams;
if (CodeVersion >= '4') {
if (NumCallParams > NumLocalVariables)
InternalError(TooManyParameters);
}
FORLIM = NumCallParams;
for (RegCnt = 0; RegCnt < FORLIM; ++RegCnt)
R.a[RegCnt] = Opd.a[RegCnt + 1];
Push(NumLocalVariables);
MSP = SP;
} /* Call */
Static void ResetZMachine(void) {
int RegCnt;
SP = 0;
MSP = 0;
NumCallParams = 0;
if (CodeVersion <= '5') {
IPC_PageNo = MiscInfo.StartPageNo;
IPC_PageIndex = MiscInfo.StartIndex;
} else {
IPC_PageNo = 0;
IPC_PageIndex = 0;
Call(JoinBytes(MiscInfo.StartIndex, MiscInfo.StartPageNo), 0, 0);
}
StoryScreenMode = 0;
ScreenMode = 0;
FormatMode = 0;
ComMode = 0;
OutputMode = 0;
ScreenEnabled = true;
BufferEnabled = false;
DirectEnabled = false;
WindowEnabled = false;
WritingInWindow = false;
BufferPageNo = -1;
BufferPageIndex = -1;
BufferIndex = 0;
LineIndex = 0;
ScrollTop = (CodeVersion <= '3') + 1;
StoryScrollTop = ScrollTop;
LineNo = ScrollTop;
SetInterpreterConfiguration();
for (RegCnt = 0; RegCnt <= 15; ++RegCnt)
R.a[RegCnt] = 0;
} /* ResetZMachine */
Static void ExecuteSingleInstruction(void);
Local void ExecuteOrgCode(PtrBPT WrkBPT) {
PutOrgCode(WrkBPT);
ExecuteSingleInstruction();
PutBPTCode(WrkBPT);
} /* ExecuteOrgCode */
Local void ExecuteBPT(void) {
int BPT_No;
int BPT_Type;
PtrBPT WrkBPT;
BPT_No = GetByteIPC();
BPT_Type = GetByteIPC();
if (BPT_No == 0 ||
BPT_Type != TraceBPT && BPT_Type != RunBPT && BPT_Type != UserBPT)
InternalError(BreakPoint);
WrkBPT = BPT_List;
while (WrkBPT != NULL) {
if (WrkBPT->BPT_No == BPT_No)
goto _L1;
WrkBPT = WrkBPT->NextBPT;
}
_L1:
if (WrkBPT == NULL)
InternalError(BreakPoint);
if (WrkBPT->BPT_PageNo != NewInstPageNo ||
WrkBPT->BPT_PageIndex != NewInstPageIndex)
InternalError(BreakPoint);
IPC_PageNo = NewInstPageNo;
IPC_PageIndex = NewInstPageIndex;
if (Stepping && BPT_Type == UserBPT ||
FirstInstPageNo == IPC_PageNo && FirstInstPageIndex == IPC_PageIndex) {
ExecuteOrgCode(WrkBPT);
return;
}
DC_PageNo = IPC_PageNo;
DC_PageIndex = IPC_PageIndex;
if (BPT_Type == UserBPT) {
ChkWait();
RingBell();
++WrkBPT->HitCnt;
PrintString("Stopped by user BPT #");
PrintByte(BPT_No, 2);
PrintString(" hit=");
PrintWord(WrkBPT->HitCnt, 4);
ChkWait();
} else if (BPT_Type == RunBPT && Running || BPT_Type == TraceBPT && Tracing)
ClearBPT(BPT_No);
Running = false;
if (Stepping) {
Cmd = SwitchToStep;
} else {
PrintZState();
Disassemble(1, true);
}
longjmp(_JL999, 1);
} /* ExecuteBPT */
Local void Return(int Value) {
int NumLocalVariables;
int RegCnt;
int Discard;
int HighByte;
boolean IsFunc;
SP = MSP;
NumLocalVariables = Pop();
NumCallParams = Pop();
for (RegCnt = NumLocalVariables - 1; RegCnt >= 0; --RegCnt)
R.a[RegCnt] = Pop();
IPC_PageNo = Pop();
SplitWord(Pop(), &IPC_PageIndex, &HighByte);
IsFunc = HighByte & 1;
Discard = Pop();
Discard = Pop();
MSP = Pop();
if (IPC_PageNo == 0 && IPC_PageIndex == 0)
InternalError(NotImplemented);
if (IsFunc)
DoPutWord(Value);
} /* Return */
Local void HandleTrue(void) {
boolean TrueJump;
int Distance;
GetJump(FromIPC, &TrueJump, &Distance);
if (!TrueJump)
return;
if (Distance == 0) {
Return(0);
return;
}
if (Distance == 1)
Return(1);
else
CalcJump(IPC_PageNo, IPC_PageIndex, &IPC_PageNo, &IPC_PageIndex, Distance);
} /* HandleTrue */
Local void HandleFalse(void) {
boolean TrueJump;
int Distance;
GetJump(FromIPC, &TrueJump, &Distance);
if (TrueJump)
return;
if (Distance == 0) {
Return(0);
return;
}
if (Distance == 1)
Return(1);
else
CalcJump(IPC_PageNo, IPC_PageIndex, &IPC_PageNo, &IPC_PageIndex, Distance);
} /* HandleFalse */
Local void WTX(int *TextPageNo, int *TextPageIndex, boolean IncCnt) {
int SavePageNo;
int SavePageIndex;
Push(IPC_PageNo);
Push(IPC_PageIndex);
IPC_PageNo = *TextPageNo;
IPC_PageIndex = *TextPageIndex;
WriteText('T', ToStoryOutput, FromIPC, GlobalTextBuffer);
SavePageNo = IPC_PageNo;
SavePageIndex = IPC_PageIndex;
IPC_PageIndex = Pop();
IPC_PageNo = Pop();
if (IncCnt) {
*TextPageNo = SavePageNo;
*TextPageIndex = SavePageIndex;
}
} /* WTX */
Local boolean SavedState(void) {
boolean SavedState_ReturnValue;
boolean OldPrintListing;
int PageCnt;
int NumPagesToSave;
int LowByte;
int HighByte;
int RegCnt;
int SaveIndex;
Char Answer;
Char FileName[256];
Char UnixName[256];
FILE *SaveFile;
Char STR1[256];
Char STR2[256];
FILEBUFNC(SaveFile,aPage);
SaveFile = NULL;
SavedState_ReturnValue = false;
ZM_NewLine();
OldPrintListing = PrintListing;
PrintListing = false;
PrintString("Save file name -->");
PrintCh(' ');
SetLength(FileName, 0);
ReadLine(true, FileName, 79, -1, 0);
if (*FileName != '\0') {
sprintf(FileName, "%s%s", StateDirectory(STR1), strcpy(STR2, FileName));
Answer = 'y';
if (FileExists(FileName)) {
PrintString("File already exists. Overwrite it (y/n)?");
PrintCh(' ');
CursorOn();
Answer = ReadKeyWithNoEcho(-1);
CursorOff();
if (Answer == 'Y')
Answer = 'y';
if (Answer == 'y')
PrintString("yes");
else
PrintString("no");
ChkWait();
}
if (Answer == 'y') {
strcpy(UnixName, FileName);
if (SaveFile != NULL)
SaveFile = freopen(UnixName, "wb", SaveFile);
else
SaveFile = fopen(UnixName, "wb");
if (SaveFile == NULL)
_EscIO(FileNotFound);
SETUPBUF(SaveFile, aPage);
PageCnt = 0;
NumPagesToSave = MiscInfo.SaveStateSizeHigh;
AGETFBUF(SaveFile, aPage)[0] = MiscInfo.ReleaseHigh;
AGETFBUF(SaveFile, aPage)[1] = MiscInfo.ReleaseLow;
SplitWord(IPC_PageNo, &LowByte, &HighByte);
AGETFBUF(SaveFile, aPage)[2] = HighByte;
AGETFBUF(SaveFile, aPage)[3] = LowByte;
AGETFBUF(SaveFile, aPage)[4] = IPC_PageIndex;
SplitWord(SP, &LowByte, &HighByte);
AGETFBUF(SaveFile, aPage)[5] = HighByte;
AGETFBUF(SaveFile, aPage)[6] = LowByte;
SplitWord(MSP, &LowByte, &HighByte);
AGETFBUF(SaveFile, aPage)[7] = HighByte;
AGETFBUF(SaveFile, aPage)[8] = LowByte;
AGETFBUF(SaveFile, aPage)[9] = NumCallParams;
SaveIndex = 10;
for (RegCnt = 0; RegCnt <= 14; ++RegCnt) {
SplitWord(R.a[RegCnt], &LowByte, &HighByte);
AGETFBUF(SaveFile, aPage)[SaveIndex] = HighByte;
AGETFBUF(SaveFile, aPage)[SaveIndex + 1] = LowByte;
SaveIndex += 2;
}
PUT(SaveFile, aPage);
SaveIndex = 0;
RegCnt = 0;
for (RegCnt = 0; RegCnt <= MaxStack; ++RegCnt) {
SplitWord(Stack[RegCnt], &LowByte, &HighByte);
if (SaveIndex > 255) {
PUT(SaveFile, aPage);
SaveIndex = 0;
}
AGETFBUF(SaveFile, aPage)[SaveIndex] = HighByte;
AGETFBUF(SaveFile, aPage)[SaveIndex + 1] = LowByte;
SaveIndex += 2;
}
PUT(SaveFile, aPage);
while (PageCnt < NumPagesToSave) {
memcpy(AGETFBUF(SaveFile, aPage), PagePtrs[PageCnt],
signedsizeof(aPage));
PUT(SaveFile, aPage);
++PageCnt;
}
SavedState_ReturnValue = (PageCnt == NumPagesToSave);
}
}
ClosePageFile(&SaveFile);
PrintListing = OldPrintListing;
if (SaveFile != NULL)
fclose(SaveFile);
return SavedState_ReturnValue;
} /* SavedState */
Local boolean RestoredState(void) {
boolean RestoredState_ReturnValue;
boolean OldPrintListing;
boolean BugVersion;
int PageCnt;
int NumPagesToSave;
int RegCnt;
int SaveIndex;
Char FileName[256];
Char UnixName[256];
FILE *SaveFile;
Char STR1[256];
Char STR2[256];
FILEBUFNC(SaveFile,aPage);
SaveFile = NULL;
RestoredState_ReturnValue = false;
ZM_NewLine();
OldPrintListing = PrintListing;
PrintListing = false;
PrintString("Save file name -->");
PrintCh(' ');
SetLength(FileName, 0);
ReadLine(true, FileName, 79, -1, 0);
if (*FileName != '\0') {
sprintf(FileName, "%s%s", StateDirectory(STR1), strcpy(STR2, FileName));
if (!FileExists(FileName)) {
PrintString("File not found.");
ChkWait();
} else {
strcpy(UnixName, FileName);
NumPagesToSave = MiscInfo.SaveStateSizeHigh;
PageCnt = 0;
if (SaveFile != NULL)
SaveFile = freopen(UnixName, "rb", SaveFile);
else
SaveFile = fopen(UnixName, "rb");
if (SaveFile == NULL)
_EscIO(FileNotFound);
RESETBUF(SaveFile, aPage);
BugVersion = (AGETFBUF(SaveFile, aPage)[0] == 0) &
(AGETFBUF(SaveFile, aPage)[1] == 0);
if (((MiscInfo.ReleaseHigh != AGETFBUF(SaveFile, aPage)[0]) |
(MiscInfo.ReleaseLow != AGETFBUF(SaveFile, aPage)[1])) &&
!BugVersion) {
PrintString("Save file has wrong release number.");
ChkWait();
} else {
if (BugVersion) {
PrintString("IPC, registers and stack will not be restored.");
ChkWait();
GET(SaveFile, aPage);
} else {
IPC_PageNo = JoinBytes(AGETFBUF(SaveFile, aPage)[3],
AGETFBUF(SaveFile, aPage)[2]);
IPC_PageIndex = AGETFBUF(SaveFile, aPage)[4];
SP = JoinBytes(AGETFBUF(SaveFile, aPage)[6],
AGETFBUF(SaveFile, aPage)[5]);
MSP = JoinBytes(AGETFBUF(SaveFile, aPage)[8],
AGETFBUF(SaveFile, aPage)[7]);
NumCallParams = AGETFBUF(SaveFile, aPage)[9];
SaveIndex = 10;
for (RegCnt = 0; RegCnt <= 14; ++RegCnt) {
R.a[RegCnt] = JoinBytes(AGETFBUF(SaveFile, aPage)[SaveIndex + 1],
AGETFBUF(SaveFile, aPage)[SaveIndex]);
SaveIndex += 2;
}
GET(SaveFile, aPage);
SaveIndex = 0;
RegCnt = 0;
for (RegCnt = 0; RegCnt <= MaxStack; ++RegCnt) {
if (SaveIndex > 255) {
GET(SaveFile, aPage);
SaveIndex = 0;
}
Stack[RegCnt] = JoinBytes(AGETFBUF(SaveFile, aPage)[SaveIndex + 1],
AGETFBUF(SaveFile, aPage)[SaveIndex]);
SaveIndex += 2;
}
}
GET(SaveFile, aPage);
while ((PageCnt < NumPagesToSave) & (!BUFEOF(SaveFile))) {
memcpy(PagePtrs[PageCnt], AGETFBUF(SaveFile, aPage),
signedsizeof(aPage));
++PageCnt;
GET(SaveFile, aPage);
}
SetInterpreterConfiguration();
RestoredState_ReturnValue = (PageCnt == NumPagesToSave);
}
}
}
ClosePageFile(&SaveFile);
PrintListing = OldPrintListing;
if (SaveFile != NULL)
fclose(SaveFile);
return RestoredState_ReturnValue;
} /* RestoredState */
Local void GetObjPropertyPtr(int ObjNo, int *ObjDataPageNo,
int *ObjDataPageIndex) {
int ObjPageNo;
int ObjPageIndex;
if (CodeVersion < '4')
CalcObjAdrs(ObjNo, &ObjPageNo, &ObjPageIndex, 7);
else
CalcObjAdrs(ObjNo, &ObjPageNo, &ObjPageIndex, 12);
*ObjDataPageNo = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&ObjPageNo, &ObjPageIndex, 1);
*ObjDataPageIndex = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(ObjDataPageNo, ObjDataPageIndex,
PagePtrs[*ObjDataPageNo][*ObjDataPageIndex] * 2 + 1);
} /* GetObjPropertyPtr */
Local void GetMultipleOperands_(boolean Extended) {
int Mode;
boolean Continue;
int BitlCnt;
if (Extended) {
Mode = GetWordIPC();
BitlCnt = 7;
} else {
Mode = GetByteIPC();
BitlCnt = 3;
}
Continue = true;
OpdCnt = 0;
while (Continue) {
switch (Bittle(Mode, BitlCnt)) {
case 0:
Opd.a[OpdCnt] = GetWordIPC();
break;
case 1:
Opd.a[OpdCnt] = GetByteIPC();
break;
case 2:
Opd.a[OpdCnt] = DoGetWord();
break;
case 3:
Continue = false;
break;
}
if (!Continue)
break;
++OpdCnt;
if (BitlCnt > 0)
--BitlCnt;
else
Continue = false;
}
} /* GetMultipleOperands */
Local void StoreWord(void) {
int DestPageNo;
int DestIndex;
int LowByte;
int HighByte;
if (OpdCnt != 3)
InternalError(IllNumOperands);
SplitWord(Opd.U1.s0, &DestIndex, &DestPageNo);
DestIndex += Opd.U1.s1 * 2;
ChkAddress(&DestPageNo, &DestIndex);
SplitWord(Opd.U1.s2, &LowByte, &HighByte);
PagePtrs[DestPageNo][DestIndex] = HighByte;
Inc(&DestPageNo, &DestIndex, 1);
PagePtrs[DestPageNo][DestIndex] = LowByte;
} /* StoreWord */
Local void StoreByte(void) {
int DestPageNo;
int DestIndex;
if (OpdCnt != 3)
InternalError(IllNumOperands);
SplitWord(Opd.U1.s0, &DestIndex, &DestPageNo);
Inc(&DestPageNo, &DestIndex, Opd.U1.s1);
PagePtrs[DestPageNo][DestIndex] = Opd.U1.s2;
} /* StoreByte */
Local void StoreProperty(void) {
int ObjDataPageNo;
int ObjDataIndex;
int LowByte;
int HighByte;
if (OpdCnt != 3)
InternalError(IllNumOperands);
GetObjPropertyPtr(Opd.U1.s0, &ObjDataPageNo, &ObjDataIndex);
_L30:
AccA = GetPropertyNo(ObjDataPageNo, ObjDataIndex);
if (AccA == 0)
InternalError(MissingObjData);
if (AccA != Opd.U1.s1) {
Inc(&ObjDataPageNo, &ObjDataIndex,
GetPropertySize(&ObjDataPageNo, &ObjDataIndex, true) + 1);
goto _L30;
}
AccA = GetPropertySize(&ObjDataPageNo, &ObjDataIndex, true);
Inc(&ObjDataPageNo, &ObjDataIndex, 1);
SplitWord(Opd.U1.s2, &LowByte, &HighByte);
if (AccA == 1) {
PagePtrs[ObjDataPageNo][ObjDataIndex] = LowByte;
return;
}
if (AccA != 2) {
InternalError(IllObjPropertyStore);
return;
}
PagePtrs[ObjDataPageNo][ObjDataIndex] = HighByte;
Inc(&ObjDataPageNo, &ObjDataIndex, 1);
PagePtrs[ObjDataPageNo][ObjDataIndex] = LowByte;
} /* StoreProperty */
/* Local variables for PackWord: */
struct PackWord_LocalVariables {
ShortInteger *Pkd;
int PkdCnt;
} ;
Local void PutInPkd(int Value, struct PackWord_LocalVariables *PackWord_Vars) {
int WordNo;
int FieldNo;
int HighByte;
int LowByte;
if (PackWord_Vars->PkdCnt >= WordNumChars)
return;
WordNo = PackWord_Vars->PkdCnt / 3;
FieldNo = PackWord_Vars->PkdCnt % 3;
SplitWord(PackWord_Vars->Pkd[WordNo], &LowByte, &HighByte);
switch (FieldNo) {
case 0:
HighByte = lor(land(HighByte, 3), land(lsl(Value, 2), 124));
break;
case 1:
HighByte = lor(land(HighByte, 252), land(lsr(Value, 3), 3));
LowByte = lor(land(LowByte, 31), land(lsl(Value, 5), 224));
break;
case 2:
LowByte = lor(land(LowByte, 224), land(Value, 31));
break;
}
PackWord_Vars->Pkd[WordNo] = JoinBytes(LowByte, HighByte);
++PackWord_Vars->PkdCnt;
} /* PutInPkd */
Local void PackWord(aWord Word, aPackedWord Pkd_) {
struct PackWord_LocalVariables V;
int ChrCnt;
int SmallShift;
int TableIndex;
int LowByte;
int HighByte;
Char WrkCh;
V.Pkd = Pkd_;
V.Pkd[0] = 5285;
V.Pkd[1] = 5285;
V.Pkd[2] = 5285;
V.PkdCnt = 0;
SmallShift = 'a' - 6;
for (ChrCnt = 0; ChrCnt <= 8; ++ChrCnt) {
WrkCh = Word[ChrCnt];
if (WrkCh == '\0') {
PutInPkd(5, &V);
} else if (islower(WrkCh)) {
PutInPkd(WrkCh - SmallShift, &V);
} else {
PutInPkd(5, &V);
if (CodeVersion == '1') {
if (P_inset(WrkCh, Char1Set)) {
TableIndex = 1;
while (WrkCh != Char1Table[TableIndex - 1])
++TableIndex;
PutInPkd(TableIndex + 6, &V);
} else {
PutInPkd(6, &V);
PutInPkd(land(lsr(WrkCh, 5), 3), &V);
PutInPkd(land(WrkCh, 31), &V);
}
} else if (P_inset(WrkCh, Char23Set)) {
TableIndex = 1;
while (WrkCh != Char23Table[TableIndex - 1])
++TableIndex;
PutInPkd(TableIndex + 7, &V);
} else {
PutInPkd(6, &V);
PutInPkd(land(lsr(WrkCh, 5), 3), &V);
PutInPkd(land(WrkCh, 31), &V);
}
}
}
if (CodeVersion >= '4') {
SplitWord(V.Pkd[2], &LowByte, &HighByte);
HighByte = lor(HighByte, 128);
V.Pkd[2] = JoinBytes(LowByte, HighByte);
} else {
SplitWord(V.Pkd[1], &LowByte, &HighByte);
HighByte = lor(HighByte, 128);
V.Pkd[1] = JoinBytes(LowByte, HighByte);
}
if (DebugVocab) {
ChkWait();
PrintWord(V.Pkd[2], 4);
PrintWord(V.Pkd[1], 4);
PrintWord(V.Pkd[0], 4);
ChkWait();
}
V.Pkd[0] += CmpShift;
V.Pkd[1] += CmpShift;
V.Pkd[2] += CmpShift;
} /* PackWord */
/* Local variables for ParseSentence: */
struct ParseSentence_LocalVariables {
int LinePageNo;
int LinePageIndex;
int VocabPageNo;
int VocabPageIndex;
Char WrkCh;
int EntryLength;
int InputIndex;
int InputLength;
aPackedWord Pkd;
} ;
Local void GetCh_(struct ParseSentence_LocalVariables *ParseSentence_Vars) {
if (ParseSentence_Vars->InputIndex > ParseSentence_Vars->InputLength) {
ParseSentence_Vars->WrkCh = EOL();
return;
}
ParseSentence_Vars->WrkCh = PagePtrs[ParseSentence_Vars->LinePageNo]
[ParseSentence_Vars->LinePageIndex];
if (isupper(ParseSentence_Vars->WrkCh))
ParseSentence_Vars->WrkCh = _tolower(ParseSentence_Vars->WrkCh);
Inc(&ParseSentence_Vars->LinePageNo, &ParseSentence_Vars->LinePageIndex, 1);
++ParseSentence_Vars->InputIndex;
} /* GetCh */
Local void BackCh(struct ParseSentence_LocalVariables *ParseSentence_Vars) {
Dec(&ParseSentence_Vars->LinePageNo, &ParseSentence_Vars->LinePageIndex, 1);
--ParseSentence_Vars->InputIndex;
} /* BackCh */
Local int GetVocabByte(struct ParseSentence_LocalVariables *ParseSentence_Vars) {
int GetVocabByte_ReturnValue;
GetVocabByte_ReturnValue = PagePtrs[ParseSentence_Vars->VocabPageNo]
[ParseSentence_Vars->VocabPageIndex];
Inc(&ParseSentence_Vars->VocabPageNo, &ParseSentence_Vars->VocabPageIndex,
1);
return GetVocabByte_ReturnValue;
} /* GetVocabByte */
Local int SearchWord(int StartPageNo, int StartPageIndex, int NumWords,
struct ParseSentence_LocalVariables *ParseSentence_Vars) {
int Wrk;
int LowerNum;
int UpperNum;
int MiddlePageNo;
int MiddlePageIndex;
int HighByte;
int LowByte;
int WordPageNo;
int WordPageIndex;
ParseSentence_Vars->VocabPageNo = StartPageNo;
ParseSentence_Vars->VocabPageIndex = StartPageIndex;
WordPageNo = ParseSentence_Vars->VocabPageNo;
WordPageIndex = ParseSentence_Vars->VocabPageIndex;
if (NumWords == 0) {
return 0;
} else if (NumWords == 1) {
if (DebugVocab) {
DC_PageNo = WordPageNo;
DC_PageIndex = WordPageIndex;
WriteText('V', OntoScreen, FromDC, GlobalTextBuffer);
}
HighByte = GetVocabByte(ParseSentence_Vars);
LowByte = GetVocabByte(ParseSentence_Vars);
Wrk = JoinBytes(LowByte, HighByte);
if (Wrk + CmpShift != ParseSentence_Vars->Pkd[0]) {
return 0;
} else {
HighByte = GetVocabByte(ParseSentence_Vars);
LowByte = GetVocabByte(ParseSentence_Vars);
Wrk = JoinBytes(LowByte, HighByte);
if (Wrk + CmpShift != ParseSentence_Vars->Pkd[1]) {
return 0;
} else if (CodeVersion < '4') {
return (JoinBytes(WordPageIndex, WordPageNo));
} else {
HighByte = GetVocabByte(ParseSentence_Vars);
LowByte = GetVocabByte(ParseSentence_Vars);
Wrk = JoinBytes(LowByte, HighByte);
if (Wrk + CmpShift != ParseSentence_Vars->Pkd[2])
return 0;
else
return (JoinBytes(WordPageIndex, WordPageNo));
}
}
} else {
LowerNum = NumWords / 2;
if (NumWords & 1)
UpperNum = LowerNum;
else
UpperNum = LowerNum - 1;
Inc(&ParseSentence_Vars->VocabPageNo, &ParseSentence_Vars->VocabPageIndex,
ParseSentence_Vars->EntryLength * LowerNum);
WordPageNo = ParseSentence_Vars->VocabPageNo;
WordPageIndex = ParseSentence_Vars->VocabPageIndex;
if (DebugVocab) {
DC_PageNo = WordPageNo;
DC_PageIndex = WordPageIndex;
WriteText('V', OntoScreen, FromDC, GlobalTextBuffer);
}
MiddlePageNo = ParseSentence_Vars->VocabPageNo;
MiddlePageIndex = ParseSentence_Vars->VocabPageIndex;
Inc(&MiddlePageNo, &MiddlePageIndex, ParseSentence_Vars->EntryLength);
HighByte = GetVocabByte(ParseSentence_Vars);
LowByte = GetVocabByte(ParseSentence_Vars);
Wrk = JoinBytes(LowByte, HighByte) + CmpShift;
if (ParseSentence_Vars->Pkd[0] < Wrk) {
return (SearchWord(StartPageNo, StartPageIndex, LowerNum,
ParseSentence_Vars));
} else if (ParseSentence_Vars->Pkd[0] > Wrk) {
return (SearchWord(MiddlePageNo, MiddlePageIndex, UpperNum,
ParseSentence_Vars));
} else {
HighByte = GetVocabByte(ParseSentence_Vars);
LowByte = GetVocabByte(ParseSentence_Vars);
Wrk = JoinBytes(LowByte, HighByte) + CmpShift;
if (ParseSentence_Vars->Pkd[1] < Wrk) {
return (SearchWord(StartPageNo, StartPageIndex, LowerNum,
ParseSentence_Vars));
} else if (ParseSentence_Vars->Pkd[1] > Wrk) {
return (SearchWord(MiddlePageNo, MiddlePageIndex, UpperNum,
ParseSentence_Vars));
} else if (CodeVersion < '4') {
return (JoinBytes(WordPageIndex, WordPageNo));
} else {
HighByte = GetVocabByte(ParseSentence_Vars);
LowByte = GetVocabByte(ParseSentence_Vars);
Wrk = JoinBytes(LowByte, HighByte) + CmpShift;
if (ParseSentence_Vars->Pkd[2] < Wrk) {
return (SearchWord(StartPageNo, StartPageIndex, LowerNum,
ParseSentence_Vars));
} else if (ParseSentence_Vars->Pkd[2] > Wrk)
return (SearchWord(MiddlePageNo, MiddlePageIndex, UpperNum,
ParseSentence_Vars));
else
return (JoinBytes(WordPageIndex, WordPageNo));
}
}
}
} /* SearchWord */
Local void ParseSentence(int LinePageNo_, int LinePageIndex_,
int ParsedPageNo, int ParsedPageIndex,
int VocabPageNo_, int VocabPageIndex_,
int DiscardNullWordInfoOffset) {
struct ParseSentence_LocalVariables V;
int LowByte;
int HighByte;
int WordStartIndex;
int NumVocabWords;
int VocabStartPageNo;
int VocabStartPageIndex;
int ParsedStartPageNo;
int ParsedStartPageIndex;
int ChrCnt;
int MaxNumWords;
int NumWords;
int WordChCnt;
int NumSeparators;
int SeparatorCnt;
CharSet SeparatorSet;
aWord Word;
aWord InitWord;
CharSet SET;
V.LinePageNo = LinePageNo_;
V.LinePageIndex = LinePageIndex_;
V.VocabPageNo = VocabPageNo_;
V.VocabPageIndex = VocabPageIndex_;
Inc(&V.LinePageNo, &V.LinePageIndex, 1); /* skip max length */
V.InputLength = PagePtrs[V.LinePageNo][V.LinePageIndex];
V.InputIndex = 1;
Inc(&V.LinePageNo, &V.LinePageIndex, 1); /* skip length */
NumSeparators = GetVocabByte(&V);
if (NumSeparators > 10)
InternalError(TooManySeparators);
P_expset(SeparatorSet, 0);
for (SeparatorCnt = 1; SeparatorCnt <= NumSeparators; ++SeparatorCnt)
P_addset(SeparatorSet, GetVocabByte(&V));
V.EntryLength = GetVocabByte(&V);
HighByte = GetVocabByte(&V);
LowByte = GetVocabByte(&V);
NumVocabWords = JoinBytes(LowByte, HighByte);
VocabStartPageNo = V.VocabPageNo;
VocabStartPageIndex = V.VocabPageIndex;
ParsedStartPageNo = ParsedPageNo;
ParsedStartPageIndex = ParsedPageIndex;
MaxNumWords = PagePtrs[ParsedPageNo][ParsedPageIndex];
if (MaxNumWords == 0 || MaxNumWords > MaxMaxNumWords) {
MaxNumWords = MaxMaxNumWords;
PagePtrs[ParsedPageNo][ParsedPageIndex] = MaxNumWords;
}
Inc(&ParsedPageNo, &ParsedPageIndex, 2);
for (ChrCnt = 0; ChrCnt <= 8; ++ChrCnt)
InitWord[ChrCnt] = '\0';
NumWords = 0;
GetCh_(&V);
BackCh(&V);
while (V.WrkCh != EOL() && NumWords < MaxNumWords) {
memcpy(Word, InitWord, signedsizeof(aWord));
WordStartIndex = V.InputIndex;
GetCh_(&V);
if (!(((!P_inset(V.WrkCh, TerminatorSet)) |
P_inset(V.WrkCh, SeparatorSet)) & (V.WrkCh != EOL())))
continue;
Word[0] = V.WrkCh;
WordChCnt = 1;
if (!P_inset(V.WrkCh, SeparatorSet)) {
GetCh_(&V);
while ((V.WrkCh != EOL()) & (!(P_inset(V.WrkCh, SeparatorSet) |
P_inset(V.WrkCh, TerminatorSet)))) {
if (WordChCnt < WordNumChars)
Word[WordChCnt] = V.WrkCh;
GetCh_(&V);
++WordChCnt;
}
BackCh(&V);
}
if (DebugVocab) {
ChkWait();
for (ChrCnt = 0; ChrCnt < WordChCnt; ++ChrCnt)
PrintCh(Word[ChrCnt]);
PrintCh(',');
PrintByte(WordChCnt, 2);
}
PackWord(Word, V.Pkd);
SplitWord(SearchWord(VocabStartPageNo, VocabStartPageIndex, NumVocabWords,
&V), &LowByte, &HighByte);
if (DebugVocab) {
PrintByte(HighByte, 2);
PrintByte(LowByte, 2);
ChkWait();
}
if (DiscardNullWordInfoOffset == 1 && LowByte == 0 && HighByte == 0) {
/* do not store offset to word info */
Inc(&ParsedPageNo, &ParsedPageIndex, 2);
} else {
PagePtrs[ParsedPageNo][ParsedPageIndex] = HighByte;
Inc(&ParsedPageNo, &ParsedPageIndex, 1);
PagePtrs[ParsedPageNo][ParsedPageIndex] = LowByte;
Inc(&ParsedPageNo, &ParsedPageIndex, 1);
}
PagePtrs[ParsedPageNo][ParsedPageIndex] = WordChCnt;
Inc(&ParsedPageNo, &ParsedPageIndex, 1);
/* IF CodeVersion>='5' THEN BEGIN */
++WordStartIndex;
/* END; */
PagePtrs[ParsedPageNo][ParsedPageIndex] = WordStartIndex;
Inc(&ParsedPageNo, &ParsedPageIndex, 1);
++NumWords;
}
ParsedPageNo = ParsedStartPageNo;
ParsedPageIndex = ParsedStartPageIndex;
Inc(&ParsedPageNo, &ParsedPageIndex, 1);
PagePtrs[ParsedPageNo][ParsedPageIndex] = NumWords;
} /* ParseSentence */
Local void ZMachineInput(void) {
int LinePageNo;
int LinePageIndex;
int VocabPageNo;
int VocabPageIndex;
int ChPageNo;
int ChPageIndex;
int LineLength;
int MaxLineLength;
int ChrCnt;
int ParsedPageNo;
int ParsedPageIndex;
boolean GotLine;
Char InputLine[256];
int FORLIM;
if (OpdCnt < 1)
InternalError(MissingOpd);
if (OpdCnt > 4)
InternalError(IllNumOperands);
if (OpdCnt < 4) {
Opd.U1.s3 = 0;
if (OpdCnt < 3) {
Opd.U1.s2 = -1;
if (OpdCnt < 2)
Opd.U1.s1 = 0;
}
}
SplitWord(Opd.U1.s0, &LinePageIndex, &LinePageNo);
SplitWord(Opd.U1.s1, &ParsedPageIndex, &ParsedPageNo);
MaxLineLength = PagePtrs[LinePageNo][LinePageIndex];
if (MaxLineLength >= ScreenWidth)
MaxLineLength = ScreenWidth - 1;
ChPageNo = LinePageNo;
ChPageIndex = LinePageIndex;
if (CodeVersion >= '5') {
Inc(&ChPageNo, &ChPageIndex, 1); /* skip max length */
LineLength = PagePtrs[ChPageNo][ChPageIndex];
for (ChrCnt = 1; ChrCnt <= LineLength; ++ChrCnt) {
Inc(&ChPageNo, &ChPageIndex, 1);
InputLine[ChrCnt - 1] = PagePtrs[ChPageNo][ChPageIndex];
}
ChPageNo = LinePageNo;
ChPageIndex = LinePageIndex;
} else {
LineLength = 0;
}
SetLength(InputLine, LineLength);
GotLine = ReadLine(true, InputLine, MaxLineLength, Opd.U1.s2, Opd.U1.s3);
if (!GotLine && CodeVersion >= '5') {
DoPutWord(InputLine[0]);
return;
}
Inc(&ChPageNo, &ChPageIndex, 1); /* skip max length */
PagePtrs[ChPageNo][ChPageIndex] = strlen(InputLine); /* store length */
FORLIM = strlen(InputLine);
for (ChrCnt = 1; ChrCnt <= FORLIM; ++ChrCnt) {
Inc(&ChPageNo, &ChPageIndex, 1);
PagePtrs[ChPageNo][ChPageIndex] = InputLine[ChrCnt - 1];
}
Inc(&ChPageNo, &ChPageIndex, 1);
if (ParsedPageNo != 0 || ParsedPageIndex != 0) {
VocabPageNo = MiscInfo.VocabPageNo;
VocabPageIndex = MiscInfo.VocabPageIndex;
ParseSentence(LinePageNo, LinePageIndex, ParsedPageNo, ParsedPageIndex,
VocabPageNo, VocabPageIndex, 0);
}
if (CodeVersion >= '5')
DoPutWord(10); /* we have an input line */
} /* ZMachineInput */
Local void WriteSingleCharacter(void) {
if (OpdCnt != 1)
InternalError(IllNumOperands);
PutChToStoryOutput(Opd.U1.s0);
} /* WriteSingleCharacter */
Local void WriteInteger(void) {
if (OpdCnt != 1)
InternalError(IllNumOperands);
PutIntToStoryOutput(Opd.U1.s0);
} /* WriteInteger */
Local void ZMachineRandom(void) {
boolean Negative;
int RandomNo;
if (OpdCnt != 1)
InternalError(IllNumOperands);
if (Opd.U1.s0 == 0) {
DoPutWord(0);
return;
}
Negative = (Opd.U1.s0 < 0);
if (Negative)
Opd.U1.s0 = -Opd.U1.s0;
RandomNo = Random();
if (RandomNo < 0)
RandomNo = -RandomNo;
RandomNo = RandomNo % Opd.U1.s0 + 1;
if (Negative)
DoPutWord(-RandomNo);
else
DoPutWord(RandomNo);
} /* ZMachineRandom */
Local void SplitScreen(void) {
int OldScrollTop;
ScreenMode = 0;
SetScreenMode();
if (Opd.U1.s0 == 0) {
WindowEnabled = false;
ScrollTop = (CodeVersion <= '3') + 1;
LineNo = ScrollTop;
return;
}
if (Opd.U1.s0 >= ScreenHeight)
return;
WindowEnabled = true;
NonWindowCursorX = 0;
NonWindowCursorY = ScreenHeight - 1;
WindowCursorX = 0;
WindowCursorY = (CodeVersion <= '3');
OldScrollTop = ScrollTop;
ScrollTop = Opd.U1.s0 + (CodeVersion <= '3') + 1;
if (OldScrollTop > ScrollTop)
LineNo += ScrollTop - OldScrollTop;
if (ScrollTop >= LineNo)
LineNo = ScrollTop;
if (CodeVersion < '4')
ClearLines(1, ScrollTop - 2);
ZM_GotoXY(1, ScreenHeight);
} /* SplitScreen */
Local void ChooseWindow(void) {
if (CodeVersion >= '5')
WriteLineBuffer();
if (!WindowEnabled)
return;
if (Opd.U1.s0 == 0) {
if (!WritingInWindow)
return;
if (CodeVersion >= '4') {
WindowCursorX = CursorX;
WindowCursorY = CursorY;
}
WritingInWindow = false;
CursorX = NonWindowCursorX;
CursorY = NonWindowCursorY;
PositionCursor();
return;
}
if (Opd.U1.s0 != 1)
return;
if (WritingInWindow)
return;
if (CodeVersion >= '4') {
NonWindowCursorX = CursorX;
NonWindowCursorY = CursorY;
}
WritingInWindow = true;
CursorX = WindowCursorX;
CursorY = WindowCursorY;
PositionCursor();
} /* ChooseWindow */
Local void EraseArea(void) {
if (Opd.U1.s0 == 0) {
ClearLines(ScrollTop - 1, ScreenHeight - 1);
ZM_GotoXY(1, ScreenHeight);
return;
}
if (Opd.U1.s0 == 1) {
if (WritingInWindow) {
ClearLines(0, ScrollTop - 2);
ZM_GotoXY(1, ScrollTop);
} else {
ClearScreen();
}
return;
}
if (Opd.U1.s0 != -1)
return;
WindowEnabled = false;
ScrollTop = (CodeVersion <= '3') + 1;
LineNo = ScrollTop;
ClearScreen();
} /* EraseArea */
Local void DoGotoXY(void) {
if (CodeVersion >= '5') {
WriteLineBuffer();
ZM_GotoXY(Opd.U1.s1, Opd.U1.s0);
} else if (DirectEnabled && WritingInWindow)
ZM_GotoXY(Opd.U1.s1, Opd.U1.s0);
} /* DoGotoXY */
Local void ChangeSCreenMode(void) {
WriteLineBuffer();
ScreenMode = Opd.U1.s0;
SetScreenMode();
} /* ChangeScreenMode */
Local void SetFormatMode(void) {
FormatMode = Opd.U1.s0;
switch (FormatMode) {
case 0:
WriteLineBuffer();
DirectEnabled = true;
break;
case 1:
DirectEnabled = false;
break;
}
} /* SetFormatMode */
Local void SetOutputMode(void) {
int DestPageNo;
int DestIndex;
int LowByte;
int HighByte;
switch (Opd.U1.s0) {
case 1:
ScreenEnabled = true;
break;
case -1:
ScreenEnabled = false;
break;
case 2:
LowByte = PagePtrs[0][17];
SetBit(&LowByte, 0);
PagePtrs[0][17] = LowByte;
break;
case -2:
LowByte = PagePtrs[0][17];
ClrBit(&LowByte, 0);
PagePtrs[0][17] = LowByte;
break;
case 3:
if (OpdCnt >= 2) {
BufferEnabled = true;
SplitWord(Opd.U1.s1, &BufferPageIndex, &BufferPageNo);
BufferIndex = 2;
} else {
InternalError(MissingOpd);
}
break;
case -3:
if (BufferEnabled) {
BufferEnabled = false;
DestPageNo = BufferPageNo;
DestIndex = BufferPageIndex;
Inc(&DestPageNo, &DestIndex, BufferIndex);
PagePtrs[DestPageNo][DestIndex] = 0;
SplitWord(BufferIndex - 2, &LowByte, &HighByte);
PagePtrs[BufferPageNo][BufferPageIndex] = HighByte;
Inc(&BufferPageNo, &BufferPageIndex, 1);
PagePtrs[BufferPageNo][BufferPageIndex] = LowByte;
BufferPageNo = -1;
BufferPageIndex = -1;
} else {
InternalError(OutputBufferUndefined);
}
break;
default:
InternalError(IllOutputMode);
break;
}
} /* SetOutputMode */
Local void SetComMode(void) {
ComMode = Opd.U1.s0;
} /* SetComMode */
Local void InputKey(void) {
Char InpKey;
if (CodeVersion >= '5')
WriteLineBuffer();
if (OpdCnt < 1 || OpdCnt > 3)
InternalError(IllNumOperands);
if (OpdCnt < 3) {
Opd.U1.s2 = 0;
if (OpdCnt < 2)
Opd.U1.s1 = -1;
}
if (Opd.U1.s0 != 1) {
DoPutWord(0);
return;
}
WriteLineBuffer();
PrintStatusLine();
LineNo = ScrollTop;
PositionCursor();
CursorOn();
if (Opd.U1.s1 >= 0)
EnableTimer();
ReadKey(true, &InpKey, Opd.U1.s1, CallKeyPress, Opd.U1.s2);
CursorOff();
if (Opd.U1.s1 >= 0)
DisableTimer();
if (InpKey == EOL())
InpKey = '\015';
DoPutWord(InpKey);
if (InpKey == BreakKey)
InternalError(KeyboardBreak);
} /* InputKey */
Local void BlockEqual(void) {
int SourcePageNo;
int SourceIndex;
int Increment;
boolean WordCompare;
int LowByte;
int HighByte;
if (OpdCnt > 4)
InternalError(IllNumOperands);
if (OpdCnt < 4) {
Opd.U1.s3 = 130; /* default is word compare */
if (OpdCnt < 3)
InternalError(MissingOpd);
}
if (Opd.U1.s3 >= 128) {
WordCompare = true;
Increment = Opd.U1.s3 - 128;
} else {
WordCompare = false;
Increment = Opd.U1.s3;
}
SplitWord(Opd.U1.s1, &SourceIndex, &SourcePageNo);
ChkAddress(&SourcePageNo, &SourceIndex);
if (WordCompare) {
while (Opd.U1.s2 > 0) {
HighByte = PagePtrs[SourcePageNo][SourceIndex];
Inc(&SourcePageNo, &SourceIndex, 1);
LowByte = PagePtrs[SourcePageNo][SourceIndex];
Dec(&SourcePageNo, &SourceIndex, 1);
if (JoinBytes(LowByte, HighByte) == Opd.U1.s0)
goto _L231;
Inc(&SourcePageNo, &SourceIndex, Increment);
--Opd.U1.s2;
}
} else {
while (Opd.U1.s2 > 0) {
LowByte = PagePtrs[SourcePageNo][SourceIndex];
if (LowByte == Opd.U1.s0)
goto _L231;
Inc(&SourcePageNo, &SourceIndex, Increment);
--Opd.U1.s2;
}
}
DoPutWord(0);
HandleFalse();
goto _L230;
_L231:
DoPutWord(JoinBytes(SourceIndex, SourcePageNo));
HandleTrue();
_L230: ;
} /* BlockEqual */
Local void Parse(void) {
int LinePageNo;
int LinePageIndex;
int ParsedPageNo;
int ParsedPageIndex;
int VocabPageNo;
int VocabPageIndex;
if (OpdCnt > 4)
InternalError(IllNumOperands);
if (OpdCnt < 4) {
Opd.U1.s3 = 0;
if (OpdCnt < 3) {
Opd.U1.s2 = 0;
if (OpdCnt < 2)
InternalError(MissingOpd);
}
}
SplitWord(Opd.U1.s0, &LinePageIndex, &LinePageNo);
SplitWord(Opd.U1.s1, &ParsedPageIndex, &ParsedPageNo);
if (Opd.U1.s2 != 0) {
SplitWord(Opd.U1.s2, &VocabPageIndex, &VocabPageNo);
} else {
VocabPageNo = MiscInfo.VocabPageNo;
VocabPageIndex = MiscInfo.VocabPageIndex;
}
ParseSentence(LinePageNo, LinePageIndex, ParsedPageNo, ParsedPageIndex,
VocabPageNo, VocabPageIndex, Opd.U1.s3);
} /* Parse */
Local void PackCharacters(void) {
int Cnt;
int NumChars;
int ChPageNo;
int ChPageIndex;
int PkdPageNo;
int PkdPageIndex;
int LowByte;
int HighByte;
aPackedWord Pkd;
aWord Word;
if (OpdCnt < 4)
InternalError(MissingOpd);
if (OpdCnt > 4)
InternalError(IllNumOperands);
SplitWord(Opd.U1.s0, &ChPageIndex, &ChPageNo);
Inc(&ChPageNo, &ChPageIndex, Opd.U1.s2);
SplitWord(Opd.U1.s3, &PkdPageIndex, &PkdPageNo);
NumChars = Opd.U1.s1;
if (NumChars > WordNumChars)
NumChars = WordNumChars;
for (Cnt = 0; Cnt < NumChars; ++Cnt) {
Word[Cnt] = PagePtrs[ChPageNo][ChPageIndex];
Inc(&ChPageNo, &ChPageIndex, 1);
}
for (Cnt = NumChars; Cnt <= 8; ++Cnt) {
Word[Cnt] = 0;
Inc(&ChPageNo, &ChPageIndex, 1);
}
PackWord(Word, Pkd);
for (Cnt = 0; Cnt <= 2; ++Cnt) {
SplitWord(Pkd[Cnt], &LowByte, &HighByte);
PagePtrs[PkdPageNo][PkdPageIndex] = HighByte;
Inc(&PkdPageNo, &PkdPageIndex, 1);
PagePtrs[PkdPageNo][PkdPageIndex] = LowByte;
Inc(&PkdPageNo, &PkdPageIndex, 1);
}
} /* PackCharacters */
Local void BlockCopy(void) {
int EndPageNo;
int EndIndex;
int SourcePageNo;
int SourceIndex;
int DestPageNo;
int DestIndex;
boolean Negative;
if (OpdCnt != 3)
InternalError(IllNumOperands);
SplitWord(Opd.U1.s0, &SourceIndex, &SourcePageNo);
SplitWord(Opd.U1.s1, &DestIndex, &DestPageNo);
if (DestPageNo == SourcePageNo && DestIndex == SourceIndex)
return;
if (Opd.U1.s2 == 0)
return;
if (Opd.U1.s2 < 0) {
Negative = true;
Opd.U1.s2 = -Opd.U1.s2;
} else {
Negative = false;
}
if (DestPageNo == 0 && DestIndex == 0) {
do {
PagePtrs[SourcePageNo][SourceIndex] = 0;
Inc(&SourcePageNo, &SourceIndex, 1);
--Opd.U1.s2;
} while (Opd.U1.s2 != 0);
return;
}
EndPageNo = SourcePageNo;
EndIndex = SourceIndex;
Inc(&EndPageNo, &EndIndex, Opd.U1.s2);
if (Negative || SourcePageNo > DestPageNo ||
SourcePageNo == DestPageNo && SourceIndex > DestIndex ||
EndPageNo < DestPageNo ||
EndPageNo == DestPageNo && EndIndex < DestIndex) {
do {
PagePtrs[DestPageNo][DestIndex] = PagePtrs[SourcePageNo][SourceIndex];
Inc(&DestPageNo, &DestIndex, 1);
Inc(&SourcePageNo, &SourceIndex, 1);
--Opd.U1.s2;
} while (Opd.U1.s2 != 0);
return;
}
Inc(&SourcePageNo, &SourceIndex, Opd.U1.s2);
Inc(&DestPageNo, &DestIndex, Opd.U1.s2);
do {
Dec(&SourcePageNo, &SourceIndex, 1);
Dec(&DestPageNo, &DestIndex, 1);
PagePtrs[DestPageNo][DestIndex] = PagePtrs[SourcePageNo][SourceIndex];
--Opd.U1.s2;
} while (Opd.U1.s2 != 0);
} /* BlockCopy */
Local void WriteTextArea(void) {
int SourcePageNo;
int SourceIndex;
int Cnt;
int StartX;
int StartY;
Char Ch;
int FORLIM;
SplitWord(Opd.U1.s0, &SourceIndex, &SourcePageNo);
if (Opd.U1.s1 <= 0)
return;
Push(ScreenMode);
if (OpdCnt < 2 || OpdCnt > 3)
InternalError(IllNumOperands);
if (OpdCnt < 3) {
Opd.U1.s2 = 1;
OpdCnt = 3;
}
StartX = CursorX;
StartY = CursorY;
while (Opd.U1.s2 > 0) {
FORLIM = Opd.U1.s1;
for (Cnt = 1; Cnt <= FORLIM; ++Cnt) {
Ch = PagePtrs[SourcePageNo][SourceIndex];
if (Ch < ' ')
InternalError(IllOutputChar);
PutChToStoryOutput(Ch);
Inc(&SourcePageNo, &SourceIndex, 1);
}
--Opd.U1.s2;
if (Opd.U1.s2 <= 0)
break;
CursorX = StartX;
CursorY = StartY;
MoveCursorDown();
StartX = CursorX;
StartY = CursorY;
}
ScreenMode = Pop();
} /* WriteTextArea */
Local void MinimalNumCallParams(void) {
if (OpdCnt != 1)
InternalError(IllNumOperands);
if (Opd.U1.s0 <= NumCallParams)
HandleTrue();
else
HandleFalse();
} /* MinimalNumCallParams */
Local void ExecuteMultipleOperandOperation(boolean NewVersion) {
switch (cOp5(CmdCode)) {
case 0: /* CFC */
Call(Opd.U1.s0, true, OpdCnt - 1);
break;
case 1: /* STW */
StoreWord();
break;
case 2: /* STB */
StoreByte();
break;
case 3: /* STP */
StoreProperty();
break;
case 4: /* INP */
ZMachineInput();
break;
case 5: /* WTC */
WriteSingleCharacter();
break;
case 6: /* WTI */
WriteInteger();
break;
case 7: /* RND */
ZMachineRandom();
break;
case 8: /* PSH */
Push(Opd.U1.s0);
break;
case 9: /* PUL */
AccA = Pop();
PutAccA(Opd.U1.s0);
if (CodeVersion >= '6')
DoPutWord(AccA); /* ??? */
break;
case 10: /* SPL */
SplitScreen();
break;
case 11: /* POS */
ChooseWindow();
break;
case 12: /* CFC */
Call(Opd.U1.s0, true, OpdCnt - 1);
break;
case 13: /* ERS */
EraseArea();
break;
case 14: /* ERL */
if (Opd.U1.s0 == 1)
ClearToEOL();
break;
case 15: /* GYX */
DoGotoXY();
break;
case 16: /* M16 */
InternalError(NotImplemented);
break;
case 17: /* SCM */
ChangeSCreenMode();
break;
case 18: /* FRM */
SetFormatMode();
break;
case 19: /* OUT */
SetOutputMode();
break;
case 20: /* COM */
SetComMode();
break;
case 21: /* BEL */
RingBell();
break;
case 22: /* INK */
InputKey();
break;
case 23: /* BEQ */
BlockEqual();
break;
case 24: /* NEG */
DoPutWord(lnot(Opd.U1.s0));
break;
case 25: /* CPC */
Call(Opd.U1.s0, false, OpdCnt - 1);
break;
case 26: /* CPC */
Call(Opd.U1.s0, false, OpdCnt - 1);
break;
case 27: /* PRS */
Parse();
break;
case 28: /* PAK */
PackCharacters();
break;
case 29: /* BCP */
BlockCopy();
break;
case 30: /* WTA */
WriteTextArea();
break;
case 31: /* MNP */
MinimalNumCallParams();
break;
}
} /* ExecuteMultipleOperandOperation */
Local void LogicalShiftLeft(void) {
if (OpdCnt != 2)
InternalError(IllNumOperands);
if (Opd.U1.s1 >= 0)
DoPutWord(lsl(Opd.U1.s0, Opd.U1.s1));
else
DoPutWord(lsr(Opd.U1.s0, -Opd.U1.s1));
} /* LogicalShiftLeft */
Local void ArithmeticShiftLeft(void) {
if (OpdCnt != 2)
InternalError(IllNumOperands);
if (Opd.U1.s1 >= 0) {
DoPutWord(lsl(Opd.U1.s0, Opd.U1.s1));
return;
}
if (Opd.U1.s0 >= 0)
DoPutWord(lsr(Opd.U1.s0, -Opd.U1.s1));
else
DoPutWord(lnot(lsr(lnot(Opd.U1.s0), -Opd.U1.s1)));
} /* ArithmeticShiftLeft */
Local void SwitchFont(void) {
WriteLineBuffer();
if (SwitchToFont(Opd.U1.s0))
DoPutWord(1);
else
DoPutWord(0);
} /* SwitchFont */
Local void ClearFlag(void) {
InternalError(NotImplemented);
} /* ClearFlag */
Local void SetFlag_(void) {
InternalError(NotImplemented);
} /* SetFlag */
Local void TestByteArray(void) {
InternalError(NotImplemented);
HandleFalse();
} /* TestByteArray */
Local void SWD(void) {
InternalError(NotImplemented);
} /* SWD */
Local void X09(void) {
InternalError(NotImplemented);
DoPutWord(0);
} /* X09 */
Local void X10(void) {
InternalError(NotImplemented);
DoPutWord(0);
} /* X10 */
Local void X11(void) {
InternalError(NotImplemented);
} /* X11 */
Local void X12(void) {
InternalError(NotImplemented);
} /* X12 */
Local void X13(void) {
InternalError(NotImplemented);
} /* X13 */
Local void X14(void) {
InternalError(NotImplemented);
} /* X14 */
Local void X15(void) {
InternalError(NotImplemented);
} /* X15 */
Local void X16(void) {
InternalError(NotImplemented);
} /* X16 */
Local void X17(void) {
InternalError(NotImplemented);
} /* X17 */
Local void X18(void) {
InternalError(NotImplemented);
} /* X18 */
Local void X19(void) {
InternalError(NotImplemented); /* ??? */
DoPutWord(0);
} /* X19 */
Local void X20(void) {
InternalError(NotImplemented);
} /* X20 */
Local void X21(void) {
InternalError(NotImplemented);
} /* X21 */
Local void X22(void) {
InternalError(NotImplemented);
} /* X22 */
Local void X23(void) {
InternalError(NotImplemented);
} /* X23 */
Local void X24(void) {
InternalError(NotImplemented);
HandleFalse(); /* ??? */
} /* X24 */
Local void X25(void) {
InternalError(NotImplemented);
} /* X25 */
Local void X26(void) {
InternalError(NotImplemented);
} /* X26 */
Local void X27(void) {
InternalError(NotImplemented);
} /* X27 */
Local void X28(void) {
InternalError(NotImplemented);
} /* X28 */
Local void ExecuteNewMultipleOperandOperation(void) {
switch (CmdCode) {
case 0: /* SVE */
if (SavedState())
DoPutWord(1);
else
DoPutWord(0);
break;
case 1: /* RSE */
if (RestoredState())
DoPutWord(2);
else
DoPutWord(0);
break;
case 2: /* LSL */
LogicalShiftLeft();
break;
case 3: /* ASL */
ArithmeticShiftLeft();
break;
case 4: /* FNT */
SwitchFont();
break;
case 5: /* CLR */
ClearFlag();
break;
case 6: /* TSB */
TestByteArray();
break;
case 7: /* SET */
SetFlag_();
break;
case 8: /* SWD */
SWD();
break;
case 9: /* X09 */
X09();
break;
case 10: /* X10 */
X10();
break;
case 11: /* X11 */
X11();
break;
case 12: /* X12 */
X12();
break;
case 13: /* X13 */
X13();
break;
case 14: /* X14 */
X14();
break;
case 15: /* X15 */
X15();
break;
case 16: /* X16 */
X16();
break;
case 17: /* X17 */
X17();
break;
case 18: /* X18 */
X18();
break;
case 19: /* X19 */
X19();
break;
case 20: /* X20 */
X20();
break;
case 21: /* X21 */
X21();
break;
case 22: /* X22 */
X22();
break;
case 23: /* X23 */
X23();
break;
case 24: /* X24 */
X24();
break;
case 25: /* X25 */
X25();
break;
case 26: /* X26 */
X26();
break;
case 27: /* X27 */
X27();
break;
case 28: /* X28 */
X28();
break;
default:
InternalError(NotImplemented);
break;
}
} /* ExecuteNewMultipleOperandOperations */
Local void GetOneOperand_(void) {
switch (cMode(CmdCode)) {
case 0:
Opd.U1.s0 = GetWordIPC();
break;
case 1:
Opd.U1.s0 = GetByteIPC();
break;
case 2:
Opd.U1.s0 = DoGetWord();
break;
}
OpdCnt = 1;
} /* GetOneOperand */
Local void ExecuteOneOperandOperation(void) {
int Op4;
int AddressHigh;
int AddressIndex;
int ObjPageNo;
int ObjPageIndex;
int WrkObj;
int LowByte;
int HighByte;
Op4 = cOp4(CmdCode);
switch (Op4) {
case 0: /* EQN */
if (Opd.U1.s0 == 0)
HandleTrue();
else
HandleFalse();
break;
case 1: /* NXO */
if (CodeVersion < '4') {
CalcObjAdrs(Opd.U1.s0, &ObjPageNo, &ObjPageIndex, 5);
WrkObj = PagePtrs[ObjPageNo][ObjPageIndex];
} else {
CalcObjAdrs(Opd.U1.s0, &ObjPageNo, &ObjPageIndex, 8);
HighByte = PagePtrs[ObjPageNo][ObjPageIndex];
++ObjPageIndex;
if (ObjPageIndex >= 256) {
++ObjPageNo;
ObjPageIndex = 0;
}
LowByte = PagePtrs[ObjPageNo][ObjPageIndex];
WrkObj = JoinBytes(LowByte, HighByte);
}
DoPutWord(WrkObj);
if (WrkObj == 0)
HandleFalse();
else
HandleTrue();
break;
case 2: /* FSO */
if (CodeVersion < '4') {
CalcObjAdrs(Opd.U1.s0, &ObjPageNo, &ObjPageIndex, 6);
WrkObj = PagePtrs[ObjPageNo][ObjPageIndex];
} else {
CalcObjAdrs(Opd.U1.s0, &ObjPageNo, &ObjPageIndex, 10);
HighByte = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&ObjPageNo, &ObjPageIndex, 1);
LowByte = PagePtrs[ObjPageNo][ObjPageIndex];
WrkObj = JoinBytes(LowByte, HighByte);
}
DoPutWord(WrkObj);
if (WrkObj == 0)
HandleFalse();
else
HandleTrue();
break;
case 3: /* PTO */
if (CodeVersion < '4') {
CalcObjAdrs(Opd.U1.s0, &ObjPageNo, &ObjPageIndex, 4);
WrkObj = PagePtrs[ObjPageNo][ObjPageIndex];
} else {
CalcObjAdrs(Opd.U1.s0, &ObjPageNo, &ObjPageIndex, 6);
HighByte = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&ObjPageNo, &ObjPageIndex, 1);
LowByte = PagePtrs[ObjPageNo][ObjPageIndex];
WrkObj = JoinBytes(LowByte, HighByte);
}
DoPutWord(WrkObj);
break;
case 4: /* LPS */
SplitWord(Opd.U1.s0 - 1, &AddressIndex, &AddressHigh);
DoPutWord(GetPropertySize(&AddressHigh, &AddressIndex, false));
break;
case 5: /* INC */
GetAccA(Opd.U1.s0);
++AccA;
PutAccA(Opd.U1.s0);
break;
case 6: /* DEC */
GetAccA(Opd.U1.s0);
--AccA;
PutAccA(Opd.U1.s0);
break;
case 7: /* WSB */
SplitWord(Opd.U1.s0, &AccC, &AccB);
WTX(&AccB, &AccC, false);
break;
case 8: /* ???/CFC */
if (CodeVersion < '4')
InternalError(IllOneOpdOp);
else
Call(Opd.U1.s0, true, OpdCnt - 1);
break;
case 9: /* RMO */
RemoveObj(Opd.U1.s0);
break;
case 10: /* WTO */
if (CodeVersion < '4')
CalcObjAdrs(Opd.U1.s0, &ObjPageNo, &ObjPageIndex, 7);
else
CalcObjAdrs(Opd.U1.s0, &ObjPageNo, &ObjPageIndex, 12);
AddressHigh = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&ObjPageNo, &ObjPageIndex, 1);
AddressIndex = PagePtrs[ObjPageNo][ObjPageIndex];
Inc(&AddressHigh, &AddressIndex, 1);
WTX(&AddressHigh, &AddressIndex, false);
break;
case 11: /* RTN */
Return(Opd.U1.s0);
break;
case 12: /* JMP */
CalcJump(IPC_PageNo, IPC_PageIndex, &IPC_PageNo, &IPC_PageIndex,
Opd.U1.s0);
break;
case 13: /* WSW */
AddressHigh = 0;
ShiftLeft(&AddressHigh, &Opd.U1.s0);
if (CodeVersion >= '4')
ShiftLeft(&AddressHigh, &Opd.U1.s0);
ChkAddress(&AddressHigh, &Opd.U1.s0);
WTX(&AddressHigh, &Opd.U1.s0, false);
break;
case 14: /* MVE */
GetAccA(Opd.U1.s0);
DoPutWord(AccA);
break;
case 15: /* NEG/CPC */
if (CodeVersion < '5')
DoPutWord(lnot(Opd.U1.s0));
else
Call(Opd.U1.s0, false, OpdCnt - 1);
break;
}/* CASE */
} /* ExecuteOneOperandOperation */
Local void GetTwoOperands_(void) {
if (TstBit(CmdCode, 6))
Opd.U1.s0 = DoGetWord();
else
Opd.U1.s0 = GetByteIPC();
if (TstBit(CmdCode, 5))
Opd.U1.s1 = DoGetWord();
else
Opd.U1.s1 = GetByteIPC();
OpdCnt = 2;
} /* GetTwoOperands */
Local void ExecuteTwoOperandOperation(void) {
int EquCnt;
int AddressHigh;
int AddressIndex;
int ObjDataPageNo;
int ObjDataPageIndex;
int LowByte;
int HighByte;
int FORLIM;
switch (cOp5(CmdCode)) {
case 0:
ExecuteBPT();
break;
case 1: /* EQU */
if (OpdCnt < 2)
InternalError(MissingOpd);
FORLIM = OpdCnt;
for (EquCnt = 1; EquCnt < FORLIM; ++EquCnt) {
if (Opd.U1.s0 == Opd.a[EquCnt]) {
HandleTrue();
goto _L100;
}
}
HandleFalse();
_L100: ;
break;
case 2: /* LES */
if (Opd.U1.s0 < Opd.U1.s1)
HandleTrue();
else
HandleFalse();
break;
case 3: /* GRT */
if (Opd.U1.s0 > Opd.U1.s1)
HandleTrue();
else
HandleFalse();
break;
case 4: /* DLS */
GetAccA(Opd.U1.s0);
--AccA;
PutAccA(Opd.U1.s0);
if (AccA < Opd.U1.s1)
HandleTrue();
else
HandleFalse();
break;
case 5: /* IGT */
GetAccA(Opd.U1.s0);
++AccA;
PutAccA(Opd.U1.s0);
if (AccA > Opd.U1.s1)
HandleTrue();
else
HandleFalse();
break;
case 6: /* OIN */
if (ObjInObj(Opd.U1.s0, Opd.U1.s1))
HandleTrue();
else
HandleFalse();
break;
case 7: /* TST */
if (land(Opd.U1.s0, Opd.U1.s1) != Opd.U1.s1)
HandleFalse();
else
HandleTrue();
break;
case 8: /* LOR */
DoPutWord(lor(Opd.U1.s0, Opd.U1.s1));
break;
case 9: /* AND */
DoPutWord(land(Opd.U1.s0, Opd.U1.s1));
break;
case 10: /* TSF */
if (TestFlag(Opd.U1.s0, Opd.U1.s1))
HandleTrue();
else
HandleFalse();
break;
case 11: /* SEF */
SetFlag(Opd.U1.s0, Opd.U1.s1, true);
break;
case 12: /* CLF */
SetFlag(Opd.U1.s0, Opd.U1.s1, false);
break;
case 13: /* SEW */
AccA = Opd.U1.s1;
PutAccA(Opd.U1.s0);
break;
case 14: /* INS */
InsertObj(Opd.U1.s0, Opd.U1.s1);
break;
case 15: /* LDW */
SplitWord(Opd.U1.s0, &AddressIndex, &AddressHigh);
Inc(&AddressHigh, &AddressIndex, Opd.U1.s1 * 2);
HighByte = PagePtrs[AddressHigh][AddressIndex];
Inc(&AddressHigh, &AddressIndex, 1);
LowByte = PagePtrs[AddressHigh][AddressIndex];
DoPutWord(JoinBytes(LowByte, HighByte));
break;
case 16: /* LDB */
SplitWord(Opd.U1.s0, &AddressIndex, &AddressHigh);
Inc(&AddressHigh, &AddressIndex, Opd.U1.s1);
DoPutWord(PagePtrs[AddressHigh][AddressIndex]);
break;
case 17: /* LDP */
GetObjPropertyPtr(Opd.U1.s0, &ObjDataPageNo, &ObjDataPageIndex);
_L170:
AccA = GetPropertyNo(ObjDataPageNo, ObjDataPageIndex);
if (AccA > Opd.U1.s1) {
Inc(&ObjDataPageNo, &ObjDataPageIndex,
GetPropertySize(&ObjDataPageNo, &ObjDataPageIndex, true) + 1);
goto _L170;
}
if (AccA < Opd.U1.s1) {
ObjDataPageNo = MiscInfo.ObjPageNo;
ObjDataPageIndex = MiscInfo.ObjPageIndex;
Inc(&ObjDataPageNo, &ObjDataPageIndex, (Opd.U1.s1 - 1) * 2);
HighByte = PagePtrs[ObjDataPageNo][ObjDataPageIndex];
Inc(&ObjDataPageNo, &ObjDataPageIndex, 1);
LowByte = PagePtrs[ObjDataPageNo][ObjDataPageIndex];
} else {
AccA = GetPropertySize(&ObjDataPageNo, &ObjDataPageIndex, true);
Inc(&ObjDataPageNo, &ObjDataPageIndex, 1);
if (AccA == 1) {
LowByte = PagePtrs[ObjDataPageNo][ObjDataPageIndex];
HighByte = 0;
} else if (AccA == 2) {
HighByte = PagePtrs[ObjDataPageNo][ObjDataPageIndex];
Inc(&ObjDataPageNo, &ObjDataPageIndex, 1);
LowByte = PagePtrs[ObjDataPageNo][ObjDataPageIndex];
} else {
InternalError(IllObjDataLoad);
}
}
DoPutWord(JoinBytes(LowByte, HighByte));
break;
case 18: /* LPA */
GetObjPropertyPtr(Opd.U1.s0, &ObjDataPageNo, &ObjDataPageIndex);
_L180:
AccA = GetPropertyNo(ObjDataPageNo, ObjDataPageIndex);
if (AccA > Opd.U1.s1) {
Inc(&ObjDataPageNo, &ObjDataPageIndex,
GetPropertySize(&ObjDataPageNo, &ObjDataPageIndex, true) + 1);
goto _L180;
}
if (AccA < Opd.U1.s1) {
DoPutWord(0);
} else {
AccA = GetPropertySize(&ObjDataPageNo, &ObjDataPageIndex, true);
DoPutWord(ObjDataPageNo * 256 + ObjDataPageIndex + 1);
}
break;
case 19: /* LNP */
GetObjPropertyPtr(Opd.U1.s0, &ObjDataPageNo, &ObjDataPageIndex);
if (Opd.U1.s1 == 0) {
DoPutWord(GetPropertyNo(ObjDataPageNo, ObjDataPageIndex));
} else {
_L190:
AccA = GetPropertyNo(ObjDataPageNo, ObjDataPageIndex);
if (AccA > Opd.U1.s1) {
Inc(&ObjDataPageNo, &ObjDataPageIndex,
GetPropertySize(&ObjDataPageNo, &ObjDataPageIndex, true) + 1);
goto _L190;
}
if (AccA < Opd.U1.s1) {
DoPutWord(0);
} else {
Inc(&ObjDataPageNo, &ObjDataPageIndex,
GetPropertySize(&ObjDataPageNo, &ObjDataPageIndex, true) + 1);
DoPutWord(GetPropertyNo(ObjDataPageNo, ObjDataPageIndex));
}
}
break;
case 20: /* ADD */
DoPutWord(Opd.U1.s0 + Opd.U1.s1);
break;
case 21: /* SUB */
DoPutWord(Opd.U1.s0 - Opd.U1.s1);
break;
case 22: /* MUL */
DoPutWord(Opd.U1.s0 * Opd.U1.s1);
break;
case 23: /* DIV */
if (Opd.U1.s1 == 0)
InternalError(DivideByZero);
else
DoPutWord(Opd.U1.s0 / Opd.U1.s1);
break;
case 24: /* MOD */
DoPutWord(Opd.U1.s0 % Opd.U1.s1);
break;
case 25: /* CFC */
Call(Opd.U1.s0, true, OpdCnt - 1);
break;
case 26: /* CPC */
Call(Opd.U1.s0, false, OpdCnt - 1);
break;
case 27: /* N27 */
InternalError(NotImplemented);
break;
case 28: /* RTM */
MSP = Opd.U1.s1;
Return(Opd.U1.s0);
break;
}
} /* ExecuteTwoOperandOperation */
Local void EndOfSession(void) {
boolean OldPrintListing;
ZM_NewLine();
OldPrintListing = PrintListing;
PrintListing = PrinterEnabled();
PrintString(" *** End of session ***");
PrintListing = OldPrintListing;
ZM_NewLine();
longjmp(_JL999, 1);
} /* EndOfSession */
Local void ExecuteNoOperandOperation(void) {
ShortInteger ChkSum;
switch (cOp4(CmdCode)) {
case 0: /* RTT */
Return(1);
break;
case 1: /* RTF */
Return(0);
break;
case 2: /* WTX */
WTX(&IPC_PageNo, &IPC_PageIndex, true);
break;
case 3: /* WTR */
WTX(&IPC_PageNo, &IPC_PageIndex, true);
ZM_NewLine();
Return(1);
break;
case 4: /* NOP */
break;
case 5: /* SVE */
if (CodeVersion < '5') {
if (SavedState()) {
if (CodeVersion < '4')
HandleTrue();
else
DoPutWord(1);
} else if (CodeVersion < '4')
HandleFalse();
else
DoPutWord(0);
}
break;
case 6: /* RSE */
if (CodeVersion < '5') {
if (RestoredState()) {
if (CodeVersion < '4')
HandleTrue();
else
DoPutWord(2);
} else if (CodeVersion < '4')
HandleFalse();
else
DoPutWord(0);
}
break;
case 7: /* RST */
ReloadData();
ClearScreen();
ResetZMachine();
if (CodeVersion <= '3') {
ScrollTop = 2;
ZM_GotoXY(1, ScrollTop);
} else {
ScrollTop = 1;
}
LineNo = ScrollTop;
break;
case 8: /* RPL */
AccA = Pop();
Return(AccA);
break;
case 9: /* DSC/PMP */
if (CodeVersion < '5')
AccA = Pop();
else
DoPutWord(MSP);
break;
case 10: /* END */
EndOfSession();
break;
case 11: /* NWL */
ZM_NewLine();
break;
case 12: /* PSL */
PrintStatusLine();
break;
case 13: /* VFY */
if (CodeCorrect(&ChkSum)) {
if (CodeVersion < '4')
HandleTrue();
else
DoPutWord(1);
} else if (CodeVersion < '4')
HandleFalse();
else
DoPutWord(0);
break;
case 14: /* Extensions */
CmdCode = GetByteIPC();
GetMultipleOperands_(false);
if (CmdCode >= 224) { /* $E0 */
ExecuteMultipleOperandOperation(true);
} else if (CmdCode < 192)
ExecuteNewMultipleOperandOperation();
else
ExecuteTwoOperandOperation();
break;
case 15:
/* blank case */
break;
}/* CASE */
/* $C0 */
} /* ExecuteNoOperandOperation */
Static void ExecuteSingleInstruction(void) {
NewInstPageNo = IPC_PageNo;
NewInstPageIndex = IPC_PageIndex;
CmdCode = GetByteIPC();
if (Statistics)
++ExecCnt[CmdCode];
if (CmdCode == 0) {
ExecuteBPT();
} else if (CmdCode < 128) {
GetTwoOperands_();
ExecuteTwoOperandOperation();
} else if (CmdCode < 176) {
GetOneOperand_();
ExecuteOneOperandOperation();
} else if (CmdCode < 192) {
ExecuteNoOperandOperation();
} else {
GetMultipleOperands_(CmdCode == 236 || CmdCode == 250);
if (CmdCode < 224) /* $E0 */
ExecuteTwoOperandOperation();
else
ExecuteMultipleOperandOperation(false);
}
InstPageNo = NewInstPageNo;
InstPageIndex = NewInstPageIndex;
/* $80 */
/* $B0 */
/* $C0 */
} /* ExecuteSingleInstruction */
Static void ExecuteSubRoutine(int Address) {
int Org_PageNo;
int Org_PageIndex;
int OrgOpdCnt;
Operands OrgOpd;
int OrgCursorX;
int OrgCursorY;
OrgCursorX = CursorX;
OrgCursorY = CursorY;
OrgOpdCnt = OpdCnt;
OrgOpd = Opd;
Org_PageNo = IPC_PageNo;
Org_PageIndex = IPC_PageIndex;
IPC_PageNo = 0;
IPC_PageIndex = 0;
Call(Address, false, 0);
do {
ExecuteSingleInstruction();
} while (IPC_PageNo != 0 || IPC_PageIndex != 0);
IPC_PageNo = Org_PageNo;
IPC_PageIndex = Org_PageIndex;
Opd = OrgOpd;
OpdCnt = OrgOpdCnt;
CursorY = OrgCursorY;
CursorX = OrgCursorX;
PositionCursor();
} /* ExecuteSubRoutine */
Static void RunCommand(boolean ListState, char RunCmd) {
Char Key;
Cmd = RunCmd;
FirstInstPageNo = IPC_PageNo;
FirstInstPageIndex = IPC_PageIndex;
if (EndIPC_PageNo >= 0)
SetBPT(BPT_IdCnt, EndIPC_PageNo, EndIPC_PageIndex, RunBPT);
if (ListState)
PrintZState();
RestoreCursorState();
Running = true;
_L0:
/*
LOOP */
ExecuteSingleInstruction();
if (KeyPressed()) {
ReadKey(false, &Key, -1, CallNever, 0);
if (Key == BreakKey)
InternalError(KeyboardBreak);
KeyBuffer[WriteIndex] = Key;
++WriteIndex;
if (WriteIndex > 79)
WriteIndex = 0;
}
goto _L0;
/*
END */
} /* RunCommand */
Static void StepCommand(void) {
Char CmdKey;
int InstPageNo;
int InstPageIndex;
int LastBPT;
int OnePageNo;
int OnePageIndex;
LastBPT = -1;
Stepping = true;
Cmd = Step;
FirstInstPageNo = IPC_PageNo;
FirstInstPageIndex = IPC_PageIndex;
EndIPC_PageNo = -1;
EndIPC_PageIndex = -1;
do {
PrintZState();
DC_PageNo = IPC_PageNo;
DC_PageIndex = IPC_PageIndex;
InstPageNo = DC_PageNo;
InstPageIndex = DC_PageIndex;
Disassemble(1, true);
OnePageNo = DC_PageNo;
OnePageIndex = DC_PageIndex;
do {
ReadKey(false, &CmdKey, -1, CallNever, 0);
if (islower(CmdKey))
CmdKey = _toupper(CmdKey);
if (CmdKey == 'L') {
InstPageNo = DC_PageNo;
InstPageIndex = DC_PageIndex;
Disassemble(1, true);
} else if (CmdKey == 'G') {
EndIPC_PageNo = InstPageNo;
EndIPC_PageIndex = InstPageIndex;
RunCommand(false, Run);
} else if (CmdKey == 'O') {
EndIPC_PageNo = OnePageNo;
EndIPC_PageIndex = OnePageIndex;
RunCommand(false, Run);
} else if (CmdKey == 'T') {
Cmd = SwitchToTrace;
longjmp(_JL999, 1);
} else if (CmdKey == 'X') {
RunCommand(true, Run);
} else if (CmdKey == 'B') {
LastBPT = BPT_IdCnt;
SetBPT(BPT_IdCnt, InstPageNo, InstPageIndex, UserBPT);
PrintString("Break-point set at last instruction.");
ChkWait();
} else if (CmdKey == 'C') {
if (LastBPT < 0) {
RingBell();
} else {
ClearBPT(LastBPT);
LastBPT = -1;
PrintString("Last break-point cleared.");
ChkWait();
}
} else if (CmdKey != ExitKey && CmdKey != BreakKey && CmdKey != ' ') {
RingBell();
PrintString(
"sp=step, L=list, T=trace, X=run, G=go last, O=run one, B=set BPT, C=clr BPT");
ChkWait();
}
} while (CmdKey != ExitKey && CmdKey != BreakKey && CmdKey != ' ');
if (CmdKey == ' ') {
RestoreCursorState();
ExecuteSingleInstruction();
}
} while (CmdKey != ExitKey && CmdKey != BreakKey); /* StepCommand */
}
Static void TraceCommand(void) {
Char Key;
Cmd = Trace;
FirstInstPageNo = IPC_PageNo;
FirstInstPageIndex = IPC_PageIndex;
if (EndIPC_PageNo >= 0)
SetBPT(BPT_IdCnt, EndIPC_PageNo, EndIPC_PageIndex, TraceBPT);
PrintZState();
Tracing = true;
_L0:
/*
LOOP */
DC_PageNo = IPC_PageNo;
DC_PageIndex = IPC_PageIndex;
Disassemble(1, true);
RestoreCursorState();
ExecuteSingleInstruction();
PrintZState();
if (KeyPressed()) {
Key = ReadKeyWithNoEcho(-1);
if (islower(Key))
Key = _toupper(Key);
if (Key == BreakKey) {
ChkWait();
longjmp(_JL999, 1);
}
if (Key == 'S') {
Cmd = SwitchToStep;
longjmp(_JL999, 1);
} else {
KeyBuffer[WriteIndex] = Key;
++WriteIndex;
if (WriteIndex > 79)
WriteIndex = 0;
}
}
goto _L0;
/*
END; */
} /* TraceCommand */
Static void StartZMachine(char StartCmd) {
ClearScreen();
if (CodeVersion <= '3') {
ScrollTop = 2;
ZM_GotoXY(1, ScrollTop);
} else {
ScrollTop = 1;
ZM_GotoXY(1, ScreenHeight);
}
EndIPC_PageNo = -1;
EndIPC_PageIndex = -1;
RunCommand(false, StartCmd);
} /* StartZMachine */
Static void CallBacktrace(void) {
int NumLocalVariables;
int RegCnt;
int OldSP;
int WrkMSP;
int WrkNumCallParams;
int Discard;
Registers WrkRegs;
OldSP = SP;
WrkMSP = MSP;
while (WrkMSP != 0) {
SP = WrkMSP;
NumLocalVariables = Pop();
WrkNumCallParams = Pop();
for (RegCnt = NumLocalVariables - 1; RegCnt >= 0; --RegCnt)
WrkRegs.a[RegCnt] = Pop();
Discard = Pop();
Discard = Pop();
DC_PageIndex = Pop();
DC_PageNo = Pop();
WrkMSP = Pop();
Disassemble(1, true);
}
SP = OldSP;
} /* CallBacktrace */
Static void EnterSubroutine(void) {
int NumRegsToInit;
NumRegsToInit = GetByteDC();
DisRegList(NumRegsToInit);
Disassemble(ScreenHeight - 5, true);
} /* EnterSubroutine */
Static void DisplayTextData(void) {
int CodePageNo;
int CodeIndex;
CodePageNo = DC_PageNo;
CodeIndex = DC_PageIndex;
BackTxtPageNo = OldTextPageNo;
BackTxtIndex = OldTextPageIndex;
DC_PageNo = TextPageNo;
DC_PageIndex = TextPageIndex;
OldTextPageNo = TextPageNo;
OldTextPageIndex = TextPageIndex;
do {
WriteText('T', OntoScreen, FromDC, GlobalTextBuffer);
} while (DC_PageNo <= EndPageNo &&
(DC_PageNo != EndPageNo || DC_PageIndex <= EndPageIndex));
NewLine();
TextPageNo = DC_PageNo;
TextPageIndex = DC_PageIndex;
DC_PageNo = CodePageNo;
DC_PageIndex = CodeIndex;
} /* DisplayTextData */
Local void ListIt(void) {
int ChrCnt;
Char CodeName[256];
int PageIndex;
int PageNo;
PrintString("Code type :");
PrintCh(' ');
switch (CodeVersion) {
case '1':
case '2':
case '3':
strcpy(CodeName, "Standard");
break;
case '4':
strcpy(CodeName, "Plus");
break;
case '5':
strcpy(CodeName, "X");
break;
case '6':
strcpy(CodeName, "Y");
break;
default:
strcpy(CodeName, "Illegal");
break;
}
if (CodeVersion >= '1' && CodeVersion <= '6') {
PrintString(CodeName);
PrintString(" Development System (");
PrintCh(CodeVersion);
PrintCh(')');
} else {
PrintString("Unknown (");
PrintByte(MiscInfo.CodeType, 2);
PrintCh(')');
}
ChkWait();
PrintString("Release :");
PrintWord(ReleaseNo, 5);
ChkWait();
PrintString("Serialnumber :");
PrintCh(' ');
for (ChrCnt = 0; ChrCnt <= 5; ++ChrCnt)
PrintCh(MiscInfo.SerialNumber[ChrCnt]);
ChkWait();
PrintString("Start address :");
if (CodeVersion <= '5') {
PageIndex = MiscInfo.StartIndex;
PageNo = MiscInfo.StartPageNo;
} else {
CalcCallAddress(JoinBytes(MiscInfo.StartIndex, MiscInfo.StartPageNo),
&PageNo, &PageIndex);
}
PrintWord(PageNo, 5);
PrintByte(PageIndex, 2);
ChkWait();
PrintString("Vocabulary base :");
PrintWord(MiscInfo.VocabPageNo, 5);
PrintByte(MiscInfo.VocabPageIndex, 2);
ChkWait();
PrintString("Special base :");
PrintWord(MiscInfo.SpecialPageNo, 5);
PrintByte(MiscInfo.SpecialIndex, 2);
ChkWait();
PrintString("Data base :");
PrintWord(MiscInfo.DataPageNo, 5);
PrintByte(MiscInfo.DataPageIndex, 2);
ChkWait();
PrintString("Object base :");
PrintWord(MiscInfo.ObjPageNo, 5);
PrintByte(MiscInfo.ObjPageIndex, 2);
ChkWait();
PrintString("Code end :");
PrintWord(CodeEndPageNo, 5);
PrintByte(CodeEndPageIndex, 2);
ChkWait();
PrintString("Code checksum :");
PrintByte(MiscInfo.ChkSumHigh, 3);
PrintByte(MiscInfo.ChkSumLow, 2);
ChkWait();
PrintString("Data length :");
PrintByte(MiscInfo.NumReadWriteBytesHigh, 3);
PrintByte(MiscInfo.NumReadWriteBytesLow, 2);
ChkWait();
PrintString("Save length :");
PrintByte(MiscInfo.SaveStateSizeHigh, 3);
PrintByte(MiscInfo.SaveStateSizeHigh, 2);
ChkWait();
PrintString("Story file name :");
PrintCh(' ');
PrintString(StoryName);
ChkWait();
} /* ListIt */
Static void ListMiscInfo(void) {
int EndPageNo;
int EndPageIndex;
union {
tMiscInfo *M;
uchar *P;
} SwapPage;
SwapPage.P = PagePtrs[0];
MiscInfo = *SwapPage.M;
CodeVersion = MiscInfo.CodeType + '0';
ExpandAddress(MiscInfo.EndPageNo, MiscInfo.EndPageIndex, &EndPageNo,
&EndPageIndex);
CodeEndPageNo = EndPageNo;
CodeEndPageIndex = EndPageIndex;
if (CodeVersion >= '4') {
ObjRecSize = 14;
ObjOffset = 112;
WordNumChars = 9;
} else {
ObjRecSize = 9;
ObjOffset = 53;
WordNumChars = 6;
}
ListIt();
} /* ListMiscInfo */
Static void LoadStory(void) {
ChkWait();
BPT_IdCnt = 1;
BPT_No = 0;
while (BPT_List != NULL)
ClearBPT(BPT_List->BPT_No);
CodeEndPageNo = MaxPageNo;
ReadPages();
ReleaseNo = JoinBytes(MiscInfo.ReleaseLow, MiscInfo.ReleaseHigh);
ListMiscInfo();
ResetZMachine();
ChkWait();
EntryIndex = 0;
FirstObj = 0;
LastObj = 0;
FirstHigh = 0;
LastHigh = 0;
RegNo = 0;
DC_PageNo = IPC_PageNo;
DC_PageIndex = IPC_PageIndex;
OldPageNo = DC_PageNo;
OldIndex = DC_PageIndex;
BackPageNo = DC_PageNo;
BackIndex = DC_PageIndex;
OldIPC_PageNo = DC_PageNo;
OldIPC_PageIndex = DC_PageIndex;
BackIPC_PageNo = DC_PageNo;
BackIPC_PageIndex = DC_PageIndex;
} /* LoadStory */
Static void VerifyCommand(void) {
ShortInteger CodeChkSum;
if (CodeCorrect(&CodeChkSum)) {
PrintString("Code ok.");
} else {
PrintString("Checksum error:");
PrintWord(CodeChkSum, 5);
}
ChkWait();
} /* VerifyCommand */
Static void PreparePrinter(void) {
OpenPrinter();
if (PrinterOpen)
PrintListing = true;
} /* PreparePrinter */
#define Spacing 4
/* Local variables for DisplayVocabulary: */
struct DisplayVocabulary_LocalVariables {
boolean WithPointers;
int WordPageNo;
int WordIndex;
int ValuesOffset;
int NumWords;
int NumSpecial;
int EntryLength;
int Specs[16];
int Values[16];
} ;
Local void DisplayHeader(struct DisplayVocabulary_LocalVariables *DisplayVocabulary_Vars) {
int SpecialCnt;
int FORLIM;
PrintString("The vocabulary consists of");
PrintCh(' ');
PrintInteger(DisplayVocabulary_Vars->NumWords);
PrintString(" words and each word requires");
PrintCh(' ');
PrintInteger(DisplayVocabulary_Vars->EntryLength);
PrintString(" bytes.");
ChkWait();
ChkWait();
if (DisplayVocabulary_Vars->NumSpecial == 0) {
PrintString("The vocabulary contains no word separators.");
return;
}
PrintString("Word separators:");
FORLIM = DisplayVocabulary_Vars->NumSpecial;
for (SpecialCnt = 1; SpecialCnt <= FORLIM; ++SpecialCnt) {
PrintCh(' ');
PrintCh(DisplayVocabulary_Vars->Specs[SpecialCnt - 1]);
}
} /* DisplayHeader */
Local void DisplayWord(struct DisplayVocabulary_LocalVariables *DisplayVocabulary_Vars) {
int ValueCnt;
int SpaceCnt;
int FORLIM;
if (DisplayVocabulary_Vars->WithPointers) {
PrintByte(DisplayVocabulary_Vars->WordPageNo, 2);
PrintByte(DisplayVocabulary_Vars->WordIndex, 2);
PrintCh(':');
PrintCh(' ');
}
PrintString(GlobalTextBuffer);
FORLIM = WordNumChars - strlen(GlobalTextBuffer) + 1;
for (SpaceCnt = 1; SpaceCnt <= FORLIM; ++SpaceCnt)
PrintCh(' ');
if (!DisplayVocabulary_Vars->WithPointers) {
FORLIM = DisplayVocabulary_Vars->EntryLength - DisplayVocabulary_Vars->
ValuesOffset;
for (ValueCnt = 0; ValueCnt <= FORLIM; ++ValueCnt)
PrintByte(DisplayVocabulary_Vars->Values[ValueCnt], 3);
}
for (SpaceCnt = 1; SpaceCnt <= Spacing; ++SpaceCnt)
PrintCh(' ');
} /* DisplayWord */
Static void DisplayVocabulary(boolean WithPointers_) {
struct DisplayVocabulary_LocalVariables V;
boolean EmptyLine;
int OldDC_PageNo;
int OldDC_PageIndex;
int Cnt;
int ValueCnt;
int WordsPerLine;
int FORLIM;
int FORLIM1;
V.WithPointers = WithPointers_;
OldDC_PageNo = DC_PageNo;
OldDC_PageIndex = DC_PageIndex;
DC_PageNo = MiscInfo.VocabPageNo;
DC_PageIndex = MiscInfo.VocabPageIndex;
V.NumSpecial = GetByteDC();
if (V.NumSpecial > 16) {
PrintString("Error: too many word separators");
RingBell();
ChkWait();
goto _L777;
}
FORLIM = V.NumSpecial;
for (Cnt = 1; Cnt <= FORLIM; ++Cnt)
V.Specs[Cnt - 1] = GetByteDC();
V.EntryLength = GetByteDC();
V.NumWords = GetWordDC();
V.ValuesOffset = WordNumChars / 3 * 2 + 1;
WordsPerLine = ScreenWidth /
(WordNumChars + (V.EntryLength - V.ValuesOffset + 1) * 3 + Spacing + 1);
DisplayHeader(&V);
ChkWait();
ChkWait();
EmptyLine = true;
FORLIM = V.NumWords;
for (Cnt = 1; Cnt <= FORLIM; ++Cnt) {
V.WordPageNo = DC_PageNo;
V.WordIndex = DC_PageIndex;
WriteText('V', IntoBuffer, FromDC, GlobalTextBuffer);
FORLIM1 = V.EntryLength - V.ValuesOffset;
for (ValueCnt = 0; ValueCnt <= FORLIM1; ++ValueCnt)
V.Values[ValueCnt] = GetByteDC();
DisplayWord(&V);
EmptyLine = (Cnt % WordsPerLine == 0);
if (EmptyLine)
ChkWait();
}
if (!EmptyLine)
ChkWait();
ChkWait();
PrintString("Vocabulary ends at:");
PrintWord(DC_PageNo, 5);
PrintByte(DC_PageIndex, 2);
ChkWait();
DC_PageNo = OldDC_PageNo;
DC_PageIndex = OldDC_PageIndex;
_L777: ;
} /* DisplayVocabulary */
#undef Spacing
Static int FindObject(int LastObj, Char Name[256]) {
int NamePageNo;
int NamePageIndex;
int NameLength;
int ObjCnt;
boolean NotFound;
DC_PageNo = MiscInfo.ObjPageNo;
DC_PageIndex = MiscInfo.ObjPageIndex;
ObjCnt = 1;
NotFound = true;
while (NotFound && ObjCnt <= LastObj) {
if (CodeVersion < '4')
CalcObjAdrs(ObjCnt, &DC_PageNo, &DC_PageIndex, 7);
else
CalcObjAdrs(ObjCnt, &DC_PageNo, &DC_PageIndex, 12);
NamePageNo = GetByteDC();
NamePageIndex = GetByteDC();
DC_PageNo = NamePageNo;
DC_PageIndex = NamePageIndex;
NameLength = GetByteDC();
if (NameLength > 0 && NameLength < 80) {
*GlobalTextBuffer = '\0';
WriteText('N', IntoBuffer, FromDC, GlobalTextBuffer);
NotFound = (strpos2(GlobalTextBuffer, Name, 1) == 0);
}
++ObjCnt;
}
if (NotFound)
return 0;
else
return (ObjCnt - 1);
} /* FindObject */
Static void DispObject(int FirstObj, int LastObj, boolean WithData) {
int OldDC_PageNo;
int OldDC_PageIndex;
int ObjCnt;
int InsideObj;
int NextObj;
int ContainsObj;
int NamePageNo;
int NameIndex;
int FlagCnt;
int NameLength;
int DataNo;
int ByteCnt;
int DataValue;
int DataCnt;
int DataSize;
int Flags1Word;
int Flags2Word;
int Flags3Word;
int FORLIM1;
if (FirstObj == 0 || LastObj == 0) {
PrintString("No such object.");
ChkWait();
return;
}
OldDC_PageNo = DC_PageNo;
OldDC_PageIndex = DC_PageIndex;
for (ObjCnt = FirstObj; ObjCnt <= LastObj; ++ObjCnt) {
ChkWait();
CalcObjAdrs(ObjCnt, &DC_PageNo, &DC_PageIndex, 0);
PrintString("ObjNo:");
PrintWord(ObjCnt, 4);
PrintString(" RecAdrs:");
PrintByte(DC_PageNo, 2);
PrintByte(DC_PageIndex, 2);
Flags1Word = GetWordDC();
Flags2Word = GetWordDC();
if (CodeVersion < '4') {
Flags3Word = 0;
InsideObj = GetByteDC();
NextObj = GetByteDC();
ContainsObj = GetByteDC();
} else {
Flags3Word = GetWordDC();
InsideObj = GetWordDC();
NextObj = GetWordDC();
ContainsObj = GetWordDC();
}
NamePageNo = GetByteDC();
NameIndex = GetByteDC();
DC_PageNo = NamePageNo;
DC_PageIndex = NameIndex;
NameLength = GetByteDC();
PrintString(" PTO:");
PrintWord(InsideObj, 4);
PrintString(" NXO:");
PrintWord(NextObj, 4);
PrintString(" FSO:");
PrintWord(ContainsObj, 4);
PrintString(" NameLen:");
PrintByte(NameLength, 2);
PrintString(" DataPtr:");
PrintByte(NamePageNo, 2);
PrintByte(NameIndex, 2);
if (Flags1Word != 0 || Flags2Word != 0 || Flags3Word != 0) {
ChkWait();
PrintString("Flags set:");
FORLIM1 = (CodeVersion >= '4') * 16 + 31;
for (FlagCnt = 0; FlagCnt <= FORLIM1; ++FlagCnt) {
if (TestFlag(ObjCnt, FlagCnt))
PrintByte(FlagCnt, 3);
}
}
ChkWait();
if (NameLength > 0) {
WriteText('N', OntoScreen, FromDC, GlobalTextBuffer);
} else {
PrintString("<no name>");
ChkWait();
}
if (WithData) {
DataCnt = 0;
DataNo = GetPropertyNo(DC_PageNo, DC_PageIndex);
while (DataNo != 0) {
if (DataCnt % 6 == 0) {
if (DataCnt != 0)
ChkWait();
PrintCh('D');
PrintWord(DC_PageNo, 5);
PrintByte(DC_PageIndex, 2);
PrintCh(':');
}
PrintString(" #");
PrintByte(DataNo, 2);
DataSize = GetPropertySize(&DC_PageNo, &DC_PageIndex, true);
Inc(&DC_PageNo, &DC_PageIndex, 1);
if (DataSize == 1) {
DataValue = GetByteDC();
PrintByte(DataValue, 3);
} else if (DataSize == 2) {
DataValue = GetWordDC();
PrintWord(DataValue, 5);
} else {
ByteCnt = 0;
PrintCh(' ');
while (ByteCnt < DataSize) {
DataValue = GetByteDC();
PrintByte(DataValue, 2);
++ByteCnt;
}
}
++DataCnt;
DataNo = GetPropertyNo(DC_PageNo, DC_PageIndex);
}
ChkWait();
}
}
DC_PageNo = OldDC_PageNo;
DC_PageIndex = OldDC_PageIndex;
} /* DispObject */
Static void DumpData(boolean DoBytes) {
int CodePageNo;
int CodeIndex;
int ItemCnt;
int Value;
boolean OldWriteDump;
boolean FirstLine;
OldWriteDump = WriteDump;
WriteDump = false;
CodePageNo = DC_PageNo;
CodeIndex = DC_PageIndex;
BackTxtPageNo = OldTextPageNo;
BackTxtIndex = OldTextPageIndex;
DC_PageNo = TextPageNo;
DC_PageIndex = TextPageIndex;
OldTextPageNo = TextPageNo;
OldTextPageIndex = TextPageIndex;
ItemCnt = 0;
*Dump = '\0';
FirstLine = true;
do {
if ((ItemCnt & 15) == 0) {
if (!FirstLine) {
PrintString(Dump);
ChkWait();
}
strcpy(Dump, "D");
WriteCh(Dump, ' ');
FirstLine = false;
AddWord(Dump, DC_PageNo);
AddByte(Dump, DC_PageIndex);
WriteCh(Dump, ':');
}
if (DoBytes) {
Value = GetByteDC();
DumpByte(Dump, Value);
} else {
Value = GetWordDC();
WriteCh(Dump, ' ');
AddWord(Dump, Value);
}
ItemCnt += 2 - DoBytes;
} while (DC_PageNo <= EndPageNo &&
(DC_PageNo != EndPageNo || DC_PageIndex <= EndPageIndex));
PrintString(Dump);
ChkWait();
TextPageNo = DC_PageNo;
TextPageIndex = DC_PageIndex;
DC_PageNo = CodePageNo;
DC_PageIndex = CodeIndex;
WriteDump = OldWriteDump;
} /* DumpData */
Static void QuickSort(int StartIndex, int EndIndex) {
int Left;
int Right;
int Pivot;
int Swap;
int Shift;
Shift = IntToCardConst;
Left = StartIndex;
Right = EndIndex;
Pivot = EntryPoints[(Left + Right) / 2] + Shift;
do {
while (EntryPoints[Left] + Shift < Pivot)
++Left;
while (EntryPoints[Right] + Shift > Pivot)
--Right;
if (Left <= Right) {
if (Left < Right) {
Swap = EntryPoints[Left];
EntryPoints[Left] = EntryPoints[Right];
EntryPoints[Right] = Swap;
}
++Left;
--Right;
}
} while (Right > Left);
if (StartIndex < Right)
QuickSort(StartIndex, Right);
if (Left < EndIndex)
QuickSort(Left, EndIndex);
} /* QuickSort */
#define PointsPerLine 10
Static void DisplayEntryPoints(void) {
int EntryCnt;
int PageNo;
int PageIndex;
int NumOnLine;
if (EntryIndex > 1)
QuickSort(0, EntryIndex - 1);
PrintString("Number of entry points:");
PrintWord(EntryIndex, 5);
ChkWait();
EntryCnt = 0;
NumOnLine = 0;
while (EntryCnt < EntryIndex) {
PageNo = 0;
PageIndex = EntryPoints[EntryCnt];
CalcCallAddress(EntryPoints[EntryCnt], &PageNo, &PageIndex);
PrintWord(PageNo, 5);
PrintByte(PageIndex, 2);
++NumOnLine;
if (NumOnLine == PointsPerLine) {
ChkWait();
NumOnLine = 0;
}
++EntryCnt;
}
if (NumOnLine != 0)
ChkWait();
} /* DisplayEntryPoints */
#undef PointsPerLine
Static void ListCommands(void) {
ChkWait();
PrintString("NewCmd = N <StoryFileName>");
ChkWait();
PrintString("ExecutionCmd = ( S|X|A ) [P] <AddressRange>");
ChkWait();
PrintString("BPT_Cmd = B [P] [S|C] <Address> [<Number>]");
ChkWait();
PrintString("EntryPointCmd = E [C|D|N|Y]");
ChkWait();
PrintString("SimpleCmd = Q | ? | H | $ | I[P][M|S] | V[P|A] | C[P]");
ChkWait();
PrintString(" | Z [P] [S|I|R|X]");
ChkWait();
PrintString("OptionCmd = D ( (N|C|T|U) | ( (B|I|K|R|S|V) (Y|N|T|F) ) )");
ChkWait();
PrintString(
"ObjCmd = O [P] ( <AddressRange> | \"<string>\" [, <Address>] ) [#]");
ChkWait();
PrintString("ListCmd = ( L | G | T ) [P] <AddressRange>");
ChkWait();
PrintString(
"MemoryCmd = ( M | W ) ( W | B ) [P] <AddressRange> {, <Number>}");
ChkWait();
PrintString("AddressRange = [<Address> [. <Address>]]");
ChkWait();
PrintString("Address = [&] [*] <Number> [W|G] | ~ | ^ | @");
ChkWait();
PrintString("Number = <Hexdigit> {<Hexdigit>}");
ChkWait();
} /* ListCommands */
/* Local variables for LineInterpreter: */
struct LineInterpreter_LocalVariables {
Char *CmdLine;
Char WrkCh;
int Index;
int HexDigits[9];
} ;
Local void GetCh__(boolean Capitalize,
struct LineInterpreter_LocalVariables *LineInterpreter_Vars) {
if (LineInterpreter_Vars->Index >= strlen(LineInterpreter_Vars->CmdLine)) {
LineInterpreter_Vars->WrkCh = EOL();
return;
}
++LineInterpreter_Vars->Index;
LineInterpreter_Vars->WrkCh =
LineInterpreter_Vars->CmdLine[LineInterpreter_Vars->Index - 1];
while (LineInterpreter_Vars->WrkCh == ' ' && Capitalize)
GetCh__(true, LineInterpreter_Vars);
if (islower(LineInterpreter_Vars->WrkCh) && Capitalize)
LineInterpreter_Vars->WrkCh = _toupper(LineInterpreter_Vars->WrkCh);
} /* GetCh */
Local void GetAddress(int *PageNo, int *PageIndex, int OldPageNo,
int OldIndex, int BackPageNo, int BackIndex,
struct LineInterpreter_LocalVariables *LineInterpreter_Vars) {
int ChCnt;
boolean DataRelative;
boolean Indirect;
int Page2No;
int Page2Index;
anAddrString AddrString;
anAddrString AddrPart;
int SET[3];
int SET1[9];
if (LineInterpreter_Vars->WrkCh == '~' || LineInterpreter_Vars->WrkCh == '/') {
*PageNo = OldPageNo;
*PageIndex = OldIndex;
GetCh__(true, LineInterpreter_Vars);
} else if (LineInterpreter_Vars->WrkCh == '^' ||
LineInterpreter_Vars->WrkCh == '<') {
*PageNo = BackPageNo;
*PageIndex = BackIndex;
GetCh__(true, LineInterpreter_Vars);
} else if (LineInterpreter_Vars->WrkCh == '@') {
*PageNo = MiscInfo.StartPageNo;
*PageIndex = MiscInfo.StartIndex;
GetCh__(true, LineInterpreter_Vars);
} else {
P_addset(P_expset(SET, 0), '*');
if (P_inset(LineInterpreter_Vars->WrkCh,
P_setunion(SET1, LineInterpreter_Vars->HexDigits,
P_addset(SET, '&')))) {
Indirect = (LineInterpreter_Vars->WrkCh == '&');
if (Indirect)
GetCh__(true, LineInterpreter_Vars);
DataRelative = (LineInterpreter_Vars->WrkCh == '*');
if (DataRelative)
GetCh__(true, LineInterpreter_Vars);
*AddrString = '\0';
ChCnt = 0;
while (P_inset(LineInterpreter_Vars->WrkCh,
LineInterpreter_Vars->HexDigits)) {
++ChCnt;
AddrString[ChCnt - 1] = LineInterpreter_Vars->WrkCh;
GetCh__(true, LineInterpreter_Vars);
}
SetLength(AddrString, ChCnt);
while (strlen(AddrString) < 6)
strinsert("0", (void *)AddrString, 1);
sprintf(AddrPart, "%.4s", AddrString);
StringToNumber(PageNo, AddrPart);
strsub(AddrPart, AddrString, 5, 2);
StringToNumber(PageIndex, AddrPart);
if (DataRelative) {
*PageIndex += MiscInfo.DataPageIndex;
*PageNo += MiscInfo.DataPageNo;
ChkAddress(PageNo, PageIndex);
}
if (Indirect) {
Push(DC_PageNo);
Push(DC_PageIndex);
DC_PageNo = *PageNo;
DC_PageIndex = *PageIndex;
*PageNo = GetByteDC();
*PageIndex = GetByteDC();
DC_PageIndex = Pop();
DC_PageNo = Pop();
}
if (LineInterpreter_Vars->WrkCh == 'W') {
GetCh__(true, LineInterpreter_Vars);
*PageNo *= 2;
*PageIndex *= 2;
ChkAddress(PageNo, PageIndex);
} else if (LineInterpreter_Vars->WrkCh == 'Q') {
GetCh__(true, LineInterpreter_Vars);
*PageNo *= 4;
*PageIndex *= 4;
ChkAddress(PageNo, PageIndex);
} else if (LineInterpreter_Vars->WrkCh == 'G') {
GetCh__(true, LineInterpreter_Vars);
CalcCallAddress(JoinBytes(*PageIndex, *PageNo), PageNo, PageIndex);
}
} else {
*PageNo = OldPageNo;
*PageIndex = OldIndex;
}
}
if (LineInterpreter_Vars->WrkCh != '+')
return;
GetCh__(true, LineInterpreter_Vars);
GetAddress(&Page2No, &Page2Index, OldPageNo, OldIndex, BackPageNo,
BackIndex, LineInterpreter_Vars);
*PageNo += Page2No;
*PageIndex += Page2Index;
ChkAddress(PageNo, PageIndex);
} /* GetAddress */
Local void GetRange(int *StartPageNo, int *StartIndex, int *EndPageNo,
int *EndPageIndex, int OldPageNo, int OldIndex,
int BackPageNo, int BackIndex,
struct LineInterpreter_LocalVariables *LineInterpreter_Vars) {
int SET[5];
int SET1[9];
P_addset(P_expset(SET, 0), '*');
P_addset(SET, '&');
P_addset(SET, '@');
P_addset(SET, '~');
P_addset(SET, '^');
P_addset(SET, '/');
if (!P_inset(LineInterpreter_Vars->WrkCh,
P_setunion(SET1, LineInterpreter_Vars->HexDigits,
P_addset(SET, '<'))))
return;
GetAddress(StartPageNo, StartIndex, OldPageNo, OldIndex, BackPageNo,
BackIndex, LineInterpreter_Vars);
if (LineInterpreter_Vars->WrkCh != '.') {
*EndPageNo = -1;
*EndPageIndex = -1;
return;
}
GetCh__(true, LineInterpreter_Vars);
if (LineInterpreter_Vars->WrkCh == '.')
GetCh__(true, LineInterpreter_Vars);
GetAddress(EndPageNo, EndPageIndex, OldPageNo, OldIndex, BackPageNo,
BackIndex, LineInterpreter_Vars);
} /* GetRange */
Local void GetString(Char theString[256], boolean SpacesAllowed,
CharSet Terminators,
struct LineInterpreter_LocalVariables *LineInterpreter_Vars) {
int ChrCnt;
*theString = '\0';
ChrCnt = 0;
while (!P_inset(LineInterpreter_Vars->WrkCh, Terminators)) {
if (LineInterpreter_Vars->WrkCh != ' ' || SpacesAllowed) {
++ChrCnt;
SetLength(theString, ChrCnt);
theString[ChrCnt - 1] = LineInterpreter_Vars->WrkCh;
}
GetCh__(false, LineInterpreter_Vars);
}
GetCh__(true, LineInterpreter_Vars);
} /* GetString */
Local void SetDumpState(Char DumpChr,
struct LineInterpreter_LocalVariables *LineInterpreter_Vars) {
boolean ToValue;
if (DumpChr == 'O' || DumpChr == 'F' || DumpChr == 'V' || DumpChr == 'S' ||
DumpChr == 'R' || DumpChr == 'K' || DumpChr == 'I' || DumpChr == 'B') {
GetCh__(true, LineInterpreter_Vars);
if (LineInterpreter_Vars->WrkCh == 'T' ||
LineInterpreter_Vars->WrkCh == 'Y') {
ToValue = true;
} else if (LineInterpreter_Vars->WrkCh == 'F' ||
LineInterpreter_Vars->WrkCh == 'N')
ToValue = false;
else
HandleError(false, "Y, N, T or F expected after switch character.",
false);
}
switch (DumpChr) {
case 'B':
DisBPTs = ToValue;
break;
case 'C':
GlobalDumpState = CodeDump;
break;
case 'F':
FaultNotImplemented = ToValue;
break;
case 'I':
DisWithIds = ToValue;
break;
case 'K':
CrashInternal = ToValue;
break;
case 'N':
GlobalDumpState = NoDump;
break;
case 'O':
RestartOperations = ToValue;
break;
case 'R':
TryRegList = ToValue;
break;
case 'S':
if (!Statistics && ToValue)
InitExecCnt();
Statistics = ToValue;
break;
case 'T':
GlobalDumpState = TextDump;
break;
case 'U':
GlobalDumpState = UnpackedDump;
break;
case 'V':
DebugVocab = ToValue;
break;
default:
RingBell();
break;
}
WriteDump = (GlobalDumpState != NoDump);
} /* SetDumpState */
Local void ModifyData(boolean DoBytes, int ModPageNo, int ModPageIndex,
struct LineInterpreter_LocalVariables *LineInterpreter_Vars) {
int High;
int Low;
GetCh__(true, LineInterpreter_Vars);
High = 0;
Low = 0;
while (LineInterpreter_Vars->WrkCh == ',' ||
LineInterpreter_Vars->WrkCh == ' ' ||
LineInterpreter_Vars->WrkCh == '^' ||
LineInterpreter_Vars->WrkCh == '~' ||
LineInterpreter_Vars->WrkCh == '&' ||
LineInterpreter_Vars->WrkCh == '*' ||
isupper(LineInterpreter_Vars->WrkCh) ||
isdigit(LineInterpreter_Vars->WrkCh)) {
if (LineInterpreter_Vars->WrkCh == ',')
GetCh__(true, LineInterpreter_Vars);
GetAddress(&High, &Low, High, Low, High, Low, LineInterpreter_Vars);
if (!DoBytes) {
PrintWord(ModPageNo, 4);
PrintByte(ModPageIndex, 2);
PrintCh(':');
PrintByte(High, 3);
ChkWait();
PagePtrs[ModPageNo][ModPageIndex] = High;
Inc(&ModPageNo, &ModPageIndex, 1);
}
PrintWord(ModPageNo, 4);
PrintByte(ModPageIndex, 2);
PrintCh(':');
PrintByte(Low, 3);
ChkWait();
PagePtrs[ModPageNo][ModPageIndex] = Low;
Inc(&ModPageNo, &ModPageIndex, 1);
}
} /* ModifyData */
Local void HandleListObject(struct LineInterpreter_LocalVariables *LineInterpreter_Vars) {
int OldHigh;
int OldLow;
int BackHigh;
int BackLow;
Char ObjectName[256];
int SET[9];
do {
if (LineInterpreter_Vars->WrkCh == ',')
GetCh__(true, LineInterpreter_Vars);
OldHigh = FirstHigh;
OldLow = FirstObj;
BackHigh = FirstHigh;
BackLow = FirstObj;
if (BackHigh > 0 || BackLow > 0)
Inc(&BackHigh, &BackLow, -1);
Inc(&FirstHigh, &FirstObj, 1);
if (LineInterpreter_Vars->WrkCh == '"') {
GetCh__(false, LineInterpreter_Vars);
P_addset(P_expset(SET, 0), '"');
GetString(ObjectName, true, P_addset(SET, EOL()), LineInterpreter_Vars);
if (LineInterpreter_Vars->WrkCh == ',')
GetCh__(true, LineInterpreter_Vars);
GetAddress(&LastHigh, &LastObj, OldHigh, OldLow, BackHigh, BackLow,
LineInterpreter_Vars);
LastObj += LastHigh * 256;
FirstObj = FindObject(LastObj, ObjectName);
LastObj = FirstObj;
FirstHigh = 0;
LastHigh = 0;
} else {
GetRange(&FirstHigh, &FirstObj, &LastHigh, &LastObj, OldHigh, OldLow,
BackHigh, BackLow, LineInterpreter_Vars);
FirstObj += FirstHigh * 256;
LastObj += LastHigh * 256;
}
if (LastObj < 0)
LastObj = FirstObj;
if (LineInterpreter_Vars->WrkCh == '#') {
GetCh__(true, LineInterpreter_Vars);
DispObject(FirstObj, LastObj, true);
} else {
DispObject(FirstObj, LastObj, false);
}
} while (LineInterpreter_Vars->WrkCh == ','); /* HandleListObject */
}
Local void HandleListEntryPoints(struct LineInterpreter_LocalVariables *LineInterpreter_Vars) {
int EntryPageNo;
int EntryIdx;
if (LineInterpreter_Vars->WrkCh == 'C') {
EntryIndex = 0;
return;
}
if (LineInterpreter_Vars->WrkCh == 'D') {
do {
GetCh__(true, LineInterpreter_Vars);
GetAddress(&EntryPageNo, &EntryIdx, EntryPageNo, EntryIdx, EntryPageNo,
EntryIdx, LineInterpreter_Vars);
RemoveEntry(EntryPageNo, EntryIdx);
} while (LineInterpreter_Vars->WrkCh == ',');
return;
}
if (LineInterpreter_Vars->WrkCh == 'Y') {
SaveEntryPoints = true;
return;
}
if (LineInterpreter_Vars->WrkCh == 'N')
SaveEntryPoints = false;
else
DisplayEntryPoints();
} /* HandleListEntryPoints */
Local void HandleZState(struct LineInterpreter_LocalVariables *LineInterpreter_Vars) {
if (LineInterpreter_Vars->WrkCh == 'I') {
ResetZMachine();
PrintZState();
return;
}
if (LineInterpreter_Vars->WrkCh == 'R') {
ReloadData();
ResetZMachine();
PrintZState();
return;
}
if (LineInterpreter_Vars->WrkCh == 'X') {
ReloadData();
ResetZMachine();
StartZMachine(Run);
return;
}
if (LineInterpreter_Vars->WrkCh == 'S')
PrintZState();
else
RingBell();
} /* HandleZState */
/* Local variables for ListStatistics: */
struct ListStatistics_LocalVariables {
struct LineInterpreter_LocalVariables *LineInterpreter_Vars;
CountArray Cnts;
CountArray Cdes;
} ;
Local void QuickSort_(int StartIndex, int EndIndex,
struct ListStatistics_LocalVariables *ListStatistics_Vars) {
int Left;
int Right;
int Pivot;
int Swap;
Left = StartIndex;
Right = EndIndex;
Pivot = ListStatistics_Vars->Cnts[(Left + Right) / 2];
do {
while (ListStatistics_Vars->Cnts[Left] < Pivot)
++Left;
while (ListStatistics_Vars->Cnts[Right] > Pivot)
--Right;
if (Left <= Right) {
if (Left < Right) {
Swap = ListStatistics_Vars->Cnts[Left];
ListStatistics_Vars->Cnts[Left] = ListStatistics_Vars->Cnts[Right];
ListStatistics_Vars->Cnts[Right] = Swap;
Swap = ListStatistics_Vars->Cdes[Left];
ListStatistics_Vars->Cdes[Left] = ListStatistics_Vars->Cdes[Right];
ListStatistics_Vars->Cdes[Right] = Swap;
}
++Left;
--Right;
}
} while (Right > Left);
if (StartIndex < Right)
QuickSort_(StartIndex, Right, ListStatistics_Vars);
if (Left < EndIndex)
QuickSort_(Left, EndIndex, ListStatistics_Vars);
} /* QuickSort */
Local void ListStatistics(struct LineInterpreter_LocalVariables *LineInterpreter_Vars) {
struct ListStatistics_LocalVariables V;
int Index;
int SpaceCnt;
int StartX;
int FORLIM1;
V.LineInterpreter_Vars = LineInterpreter_Vars;
memcpy(V.Cnts, ExecCnt, signedsizeof(CountArray));
for (Index = 0; Index <= 255; ++Index)
V.Cdes[Index] = Index;
QuickSort_(0, 255, &V);
for (Index = 255; Index >= 0; --Index) {
if (V.Cnts[Index] > 0) {
StartX = CursorX;
PrintInteger(V.Cnts[Index]);
FORLIM1 = StartX - CursorX + 7;
for (SpaceCnt = 1; SpaceCnt <= FORLIM1; ++SpaceCnt)
PrintCh(' ');
CmdCode = V.Cdes[Index];
Disassemble(1, false);
}
}
} /* ListStatistics */
Static void LineInterpreter(char *Cmd, Char CmdLine_[256]) {
/*VAR Cmd:Commands; VAR CmdLine:aMaxString*/
struct LineInterpreter_LocalVariables V;
int UnusedHigh;
boolean NewAdvOk;
int SET[9];
V.CmdLine = CmdLine_;
P_addsetr(P_expset(V.HexDigits, 0), '0', '9');
P_addsetr(V.HexDigits, 'A', 'F');
V.Index = 0;
do {
*Cmd = Nothing;
EndPageNo = -1;
EndPageIndex = -1;
EndIPC_PageNo = -1;
EndIPC_PageIndex = -1;
GetCh__(true, &V);
if (V.WrkCh != EOL()) {
switch (V.WrkCh) {
case 'W':
GetCh__(true, &V);
if (V.WrkCh == 'W') {
*Cmd = DumpWords;
} else if (V.WrkCh == 'B')
*Cmd = cDumpBytes;
else
*Cmd = Nothing;
break;
case 'M':
GetCh__(true, &V);
if (V.WrkCh == 'W') {
*Cmd = ModifyWords;
} else if (V.WrkCh == 'B')
*Cmd = ModifyBytes;
break;
case 'B':
*Cmd = BPT_Cmd;
break;
case 'Q':
*Cmd = Quit;
break;
case 'E':
*Cmd = ListEntryPoints;
break;
case 'C':
*Cmd = ListCalls;
break;
case '?':
case 'H':
*Cmd = Help;
break;
case 'D':
*Cmd = DumpOption;
break;
case 'I':
*Cmd = Info;
break;
case 'N':
*Cmd = NewAdv;
break;
case 'L':
*Cmd = List;
break;
case 'T':
*Cmd = TextList;
break;
case 'A':
*Cmd = Trace;
break;
case 'G':
*Cmd = GoSub;
break;
case 'O':
*Cmd = ListObject;
break;
case 'V':
*Cmd = ListVocabulary;
break;
case 'S':
*Cmd = Step;
break;
case 'X':
*Cmd = Run;
break;
case '$':
*Cmd = VerifyCode;
break;
case 'Z':
*Cmd = ListZState;
break;
case 'R':
*Cmd = ListReg;
break;
default:
*Cmd = Nothing;
break;
}
GetCh__(*Cmd != NewAdv, &V);
PrintListing = false;
if (((1 << (*Cmd)) & ((1 << List) | (1 << TextList) | (1 << GoSub) |
(1 << ListEntryPoints) | (1 << ListObject) | (1 <<
ListVocabulary) | (1 << cDumpBytes) | (1 << DumpWords) |
(1 << Info) | (1 << ListZState) | (1 << ListReg) | (1 << Step) |
(1 << Trace) | (1 << Run) | (1 << BPT_Cmd) |
(1 << ModifyBytes) | (1 << ModifyWords) | (1 << Help) |
(1 << ListCalls))) != 0) {
if (V.WrkCh == 'P') {
PreparePrinter();
GetCh__(true, &V);
}
}
if (*Cmd == Nothing)
RingBell();
}
if (PageCnt == 0) {
if (((1 << (*Cmd)) & ((1 << NewAdv) | (1 << DumpOption) | (1 << Help) |
(1 << Quit))) == 0) {
PrintString("No story loaded.");
RingBell();
ChkWait();
goto _L666;
}
}
switch (*Cmd) {
case Quit:
/* blank case */
break;
case ListZState:
HandleZState(&V);
break;
case ListReg:
GetAddress(&UnusedHigh, &RegNo, UnusedHigh, RegNo, UnusedHigh,
RegNo - 1, &V);
PrintReg(RegNo);
ChkWait();
break;
case VerifyCode:
VerifyCommand();
break;
case NewAdv:
NewAdvOk = false;
GetString(StoryName, false, P_addset(P_expset(SET, 0), EOL()), &V);
if ((*StoryName == '\0') | IsDirectory(StoryName))
strcat(StoryName, "story.dat");
NewAdvOk = true;
LoadStory();
break;
case Info:
if (V.WrkCh == 'S')
ListStatistics(&V);
else
ListMiscInfo();
break;
case ListCalls:
CallBacktrace();
break;
case ListVocabulary:
DisplayVocabulary(V.WrkCh == 'A');
break;
case DumpOption:
do {
if (V.WrkCh == ',')
GetCh__(true, &V);
SetDumpState(V.WrkCh, &V);
GetCh__(true, &V);
} while (V.WrkCh == ',');
break;
case Help:
ListCommands();
break;
case cDumpBytes:
case DumpWords:
case ModifyWords:
case ModifyBytes:
do {
if (V.WrkCh == ',')
GetCh__(true, &V);
GetRange(&TextPageNo, &TextPageIndex, &EndPageNo, &EndPageIndex,
OldTextPageNo, OldTextPageIndex, BackTxtPageNo, BackTxtIndex,
&V);
if (((1 << (*Cmd)) & ((1 << ModifyWords) | (1 << ModifyBytes))) != 0)
ModifyData(*Cmd == ModifyBytes, TextPageNo, TextPageIndex, &V);
else
DumpData(*Cmd == cDumpBytes);
} while (V.WrkCh == ',');
break;
case List:
do {
if (V.WrkCh == ',')
GetCh__(true, &V);
GetRange(&DC_PageNo, &DC_PageIndex, &EndPageNo, &EndPageIndex,
OldPageNo, OldIndex, BackPageNo, BackIndex, &V);
Disassemble(ScreenHeight - 5, true);
} while (V.WrkCh == ',');
break;
case Step:
GetRange(&IPC_PageNo, &IPC_PageIndex, &EndIPC_PageNo, &EndIPC_PageIndex,
OldIPC_PageNo, OldIPC_PageIndex, BackIPC_PageNo,
BackIPC_PageIndex, &V);
StepCommand();
break;
case Trace:
GetRange(&IPC_PageNo, &IPC_PageIndex, &EndIPC_PageNo, &EndIPC_PageIndex,
OldIPC_PageNo, OldIPC_PageIndex, BackIPC_PageNo,
BackIPC_PageIndex, &V);
TraceCommand();
break;
case Run:
GetRange(&IPC_PageNo, &IPC_PageIndex, &EndIPC_PageNo, &EndIPC_PageIndex,
OldIPC_PageNo, OldIPC_PageIndex, BackIPC_PageNo,
BackIPC_PageIndex, &V);
RunCommand(true, Run);
break;
case BPT_Cmd:
if (V.WrkCh == 'S') {
GetCh__(true, &V);
BPT_PageNo = IPC_PageNo;
BPT_PageIndex = IPC_PageIndex;
GetAddress(&BPT_PageNo, &BPT_PageIndex, OldIPC_PageNo,
OldIPC_PageIndex, BackIPC_PageNo, BackIPC_PageIndex, &V);
BPT_No = BPT_IdCnt;
GetAddress(&UnusedHigh, &BPT_No, UnusedHigh, BPT_No, UnusedHigh,
BPT_No, &V);
SetBPT(BPT_No, BPT_PageNo, BPT_PageIndex, UserBPT);
} else if (V.WrkCh == 'C') {
GetCh__(true, &V);
GetAddress(&UnusedHigh, &BPT_No, UnusedHigh, BPT_No, UnusedHigh,
BPT_No - 1, &V);
ClearBPT(BPT_No);
} else {
PrintBPTs();
}
break;
case TextList:
do {
if (V.WrkCh == ',')
GetCh__(true, &V);
GetRange(&TextPageNo, &TextPageIndex, &EndPageNo, &EndPageIndex,
OldTextPageNo, OldTextPageIndex, BackTxtPageNo, BackTxtIndex,
&V);
DisplayTextData();
} while (V.WrkCh == ',');
break;
case GoSub:
do {
if (V.WrkCh == ',')
GetCh__(true, &V);
GetRange(&DC_PageNo, &DC_PageIndex, &EndPageNo, &EndPageIndex,
OldPageNo, OldIndex, BackPageNo, BackIndex, &V);
EnterSubroutine();
} while (V.WrkCh == ',');
break;
case ListEntryPoints:
HandleListEntryPoints(&V);
break;
case ListObject:
HandleListObject(&V);
break;
}
} while (V.WrkCh != EOL());
_L666: ;
} /* LineInterpreter */
Static void Initialize(void) {
int Cnt;
InitSystem();
for (Cnt = 0; Cnt <= MaxPageNo; ++Cnt) {
PagePtrs[Cnt] = NULL;
DataPagePtrs[Cnt] = NULL;
}
ExitKey = ESC();
BreakKey = '\002';
PrinterTried = false;
PrinterOpen = false;
PrintListing = false;
InitScreen();
InStory = false;
SetLength(Spaces, 255);
for (Cnt = 1; Cnt <= 255; ++Cnt)
Spaces[Cnt - 1] = ' ';
memcpy(HexChars, "0123456789ABCDEF", 16);
P_addset(P_expset(TerminatorSet, 0), '!');
P_addset(TerminatorSet, '?');
P_addset(TerminatorSet, ',');
P_addset(TerminatorSet, '.');
P_addset(TerminatorSet, ' ');
WordNumChars = 6;
memcpy(Char1Table, "0123456789.,!?_#'\"/\\|-:()", 25);
P_addsetr(P_expset(Char1Set, 0), '0', '9');
P_addset(Char1Set, '.');
P_addset(Char1Set, ',');
P_addset(Char1Set, '!');
P_addset(Char1Set, '?');
P_addset(Char1Set, '_');
P_addset(Char1Set, '#');
P_addset(Char1Set, '\'');
P_addset(Char1Set, '"');
P_addset(Char1Set, '/');
P_addset(Char1Set, '\\');
P_addset(Char1Set, '|');
P_addset(Char1Set, '-');
P_addset(Char1Set, ':');
P_addset(Char1Set, '(');
P_addset(Char1Set, ')');
memcpy(Char23Table, "0123456789.,!?_#'\"/\\-:()", 24);
P_addsetr(P_expset(Char23Set, 0), '0', '9');
P_addset(Char23Set, '.');
P_addset(Char23Set, ',');
P_addset(Char23Set, '!');
P_addset(Char23Set, '?');
P_addset(Char23Set, '_');
P_addset(Char23Set, '#');
P_addset(Char23Set, '\'');
P_addset(Char23Set, '"');
P_addset(Char23Set, '/');
P_addset(Char23Set, '\\');
P_addset(Char23Set, '-');
P_addset(Char23Set, ':');
P_addset(Char23Set, '(');
P_addset(Char23Set, ')');
CmpShift = 0; /* Pred(-MaxInt) */
Randomize();
WriteIndex = 0;
ReadIndex = WriteIndex;
PrintListing = false;
PrintString("Infocom Interactive Fiction Debugger Version [");
PrintCh(HexChars[InterpreterNumber / 10]);
PrintCh('.');
PrintCh(HexChars[InterpreterNumber % 10]);
PrintCh(InterpreterChar);
PrintCh(']');
PrintCh(' ');
PrintCh(' ');
PrintString(Date);
ChkWait();
ChkWait();
PrintString("Written by Frank Lancaster during 1984-1993, Bonn, Germany.");
ChkWait();
ChkWait();
PrintString("This programme is free. You may do anything with it.");
ChkWait();
ChkWait();
PageCnt = 0;
GlobalDumpState = NoDump;
WriteDump = false;
Statistics = false;
DisBPTs = false;
DisWithIds = false;
RestartOperations = true;
ChkLineChars = false;
Opd.U1.s0 = 0;
Opd.U1.s1 = 0;
Opd.U1.s2 = 0;
Opd.U1.s3 = 0;
Opd.U1.s4 = 0;
Opd.U1.s5 = 0;
Opd.U1.s6 = 0;
Opd.U1.s7 = 0;
R.U1.r0 = 0;
R.U1.r1 = 0;
R.U1.r2 = 0;
R.U1.r3 = 0;
R.U1.r4 = 0;
R.U1.r5 = 0;
R.U1.r6 = 0;
R.U1.r7 = 0;
R.U1.r8 = 0;
R.U1.r9 = 0;
R.U1.r10 = 0;
R.U1.r11 = 0;
R.U1.r12 = 0;
R.U1.r13 = 0;
R.U1.r14 = 0;
R.U1.r15 = 0;
TryRegList = true;
SaveEntryPoints = true;
CrashInternal = false;
FaultNotImplemented = false;
DebugVocab = false;
TextPageNo = -1;
TextPageIndex = -1;
OldTextPageNo = -1;
OldTextPageIndex = -1;
BackTxtPageNo = -1;
BackTxtIndex = -1;
EndPageNo = -1;
EndPageIndex = -1;
EntryIndex = 0;
BPT_List = NULL;
StoryCursorX = 0;
StoryCursorY = 0;
InitExecCnt();
} /* Initialize */
Static void HandleError(boolean WriteLastInst, Char Message[256],
boolean Crash) {
/*WriteLastInst:Boolean; Message:aMaxString;
Crash:Boolean*/
int *NilPtr;
SaveCursorState();
RingBell();
PrintString("Error:");
PrintCh(' ');
PrintString(Message);
ChkWait();
if (Crash)
NilPtr = NULL;
if (WriteLastInst) {
if (RestartOperations) {
IPC_PageNo = NewInstPageNo;
IPC_PageIndex = NewInstPageIndex;
}
PrintZState();
DC_PageNo = NewInstPageNo;
DC_PageIndex = NewInstPageIndex;
Disassemble(1, true);
}
Cmd = Break;
longjmp(_JL999, 1);
} /* HandleError */
Static void InternalError(char Error) {
/*Error:InternalErrors*/
Char Message[256];
strcpy(Message, "Unknown error #**");
Message[15] = HexChars[Error / 16 - 1];
Message[16] = HexChars[(Error & 15) - 1];
switch (Error) {
case IllMultiOpdOp:
strcpy(Message, "Illegal multiple operand operation");
break;
case IllNoOpdOp:
strcpy(Message, "Illegal no operand operation");
break;
case IllTwoOpdOp:
strcpy(Message, "Illegal two operand operation");
break;
case IllOneOpdOp:
strcpy(Message, "Illegal one operand operation");
break;
case StackUnderflow:
strcpy(Message, "Stack underflow");
break;
case StackOverflow:
strcpy(Message, "Stack overflow");
break;
case IllObjDataLoad:
strcpy(Message, "Illegal object data load");
break;
case DivideByZero:
strcpy(Message, "Divide by zero");
break;
case MissingOpd:
strcpy(Message, "Missing operand");
break;
case MissingObjData:
strcpy(Message, "Missing object data");
break;
case IllObjPropertyStore:
strcpy(Message, "Illegal object property store");
break;
case IllZCodeType:
strcpy(Message, "Illegal Z-code type");
break;
case NotImplemented:
strcpy(Message, "Not implemented");
break;
case KeyboardBreak:
strcpy(Message, "Keyboard break");
break;
case BreakPoint:
strcpy(Message, "Unexpected breakpoint");
break;
case OutputBufferUndefined:
strcpy(Message, "Output buffer is not defined");
break;
case PC_Overflow:
strcpy(Message, "PC overflow");
break;
case PC_Underflow:
strcpy(Message, "PC underflow");
break;
case TooManySeparators:
strcpy(Message, "Too many separators");
break;
case TooManyLocalVariables:
strcpy(Message, "Too many local variables");
break;
case TooManyParameters:
strcpy(Message, "Too many parameters");
break;
case IllNumOperands:
strcpy(Message, "Illegal number of operands");
break;
case IllOutputChar:
strcpy(Message, "Illegal output character");
break;
case IllScreenMode:
strcpy(Message, "Illegal screen mode");
break;
case NoPrinter:
strcpy(Message, "Unable to open printer");
break;
case IllOutputMode:
strcpy(Message, "Illegal output mode");
break;
default:
strcpy(Message, "Undefined Error");
break;
}
if (Error != NotImplemented || FaultNotImplemented)
HandleError(true, Message, CrashInternal);
} /* InternalError */
int main(int argc, Char *argv[]) {
PASCAL_MAIN(argc, argv);
if (setjmp(_JL999))
goto _L999;
Printer = NULL;
Initialize();
if (P_argc > 1) {
strcpy(StoryName, P_argv[1]);
LoadStory();
StartZMachine(Quit);
} else {
ListCommands();
*CmdLine = '\0';
do {
Tracing = false;
Running = false;
Stepping = false;
if (Cmd == SwitchToStep) {
StepCommand();
} else if (Cmd == SwitchToTrace) {
TraceCommand();
} else {
PrintListing = false;
ChkWait();
PrintCh(']');
SetLength(CmdLine, 0);
ReadLine(false, CmdLine, 79, -1, 0);
LineInterpreter(&Cmd, CmdLine);
}
_L999: ;
} while (Cmd != Quit);
}
ResetScreen();
CloseText(&Printer);
if (Printer != NULL)
fclose(Printer);
exit(EXIT_SUCCESS);
} /* InfocomInteractiveFictionDebugger */
/* End. */