static void RestoreDisplayPointer( void )
{
    int addr;

    addr = DataAddr( Pmem[PC].offset );
    Dmem[ addr ] = Dmem[ DataAddr( FP ) ];
}
static void LoadDisplayPointer( void )
{
    int addr, temp;

    addr = DataAddr( Pmem[PC].offset );
    temp = Dmem[ addr ];
    Dmem[ DataAddr( FP ) ] = temp;
    Dmem[ addr ] = FP;
}
static void RemoveStackFrame( void )
{
    int addr;

    addr = DataAddr( FP );
    SP   = addr - 1;
    addr = DataAddr( FP + 1 );
    FP   = DataAddr( Dmem[ addr ] );
}
void  Interpret( void )
{
    INSTRUCTION current;
    int addr, nextaddr;

    current = Pmem[PC];
    nextaddr = PC+1;
    switch ( current.opcode )  {
        case  HALT:    WriteOut( "!! HALT encountered\n\n" );
                       Running = 0;                             break;
        case  ADD:     BinaryOp( ADD );                         break;
        case  SUB:     BinaryOp( SUB );                         break;
        case  MULT:    BinaryOp( MULT );                        break;
        case  DIV:     BinaryOp( DIV );                         break;
        case  NEG:     Dmem[SP] = -Dmem[SP];                    break;
        case  BR:      nextaddr = Branch( BR );                 break;
        case  BGZ:     nextaddr = Branch( BGZ );                break;
        case  BG:      nextaddr = Branch( BG );                 break;
        case  BLZ:     nextaddr = Branch( BLZ );                break;
        case  BL:      nextaddr = Branch( BL );                 break;
        case  BZ:      nextaddr = Branch( BZ );                 break;
        case  BNZ:     nextaddr = Branch( BNZ );                break;
        case  CALL:    Push( nextaddr );
                       nextaddr = CodeAddr( current.offset );   break;
        case  RET:     nextaddr = CodeAddr( Pop() );            break;
        case  BSF:     BuildStackFrame();                       break;
        case  RSF:     RemoveStackFrame();                      break;
        case  LDP:     LoadDisplayPointer();                    break;
        case  RDP:     RestoreDisplayPointer();                 break;
        case  INC:     SP = DataAddr( SP + current.offset );    break;
        case  DEC:     SP = Decrement( SP, current.offset );    break;    
        case  PUSHFP:  Push( FP );                              break;
        case  LOADI:   Push( current.offset );                  break;
        case  LOADA:   addr = DataAddr( current.offset );
                       Push( Dmem[addr] );                      break;
        case  LOADFP:  addr = DataAddr( FP + current.offset );
                       Push( Dmem[addr] );                      break;
        case  LOADSP:  addr = DataAddr( Dmem[SP] + current.offset );
                       Dmem[SP] = Dmem[addr];                   break;
        case  STOREA:  addr = DataAddr( current.offset );
                       Dmem[addr] = Pop();                      break;
        case  STOREFP: addr = DataAddr( FP + current.offset );
                       Dmem[addr] = Pop();                      break;
        case  STORESP: addr = DataAddr( Pop() );
                       addr = DataAddr( addr + current.offset );
                       Dmem[addr] = Pop();                      break;
        case  READ:    ReadInteger();                           break;
        case  WRITE:   WriteInteger();                          break;
        default:
            DisplayError( !FATAL, "Error, unknown opcode encountered\n" );
            DisplayError( FATAL,  "PC = %d, SP = %d, FP = %d, opcode = %d\n",
                          PC, SP, FP, current.opcode );
            break;
    }
    PC = nextaddr;
}
void PatchI23() {
    // product published?
    bmagic(0x00832f09, 0xc032cc33, 0x01b0cc33);

    // owns product?
    bmagic(0x0083408B, 0xff853a74, 0x5aeb01b0);

    // create character
    bmagic(0x0083DDD6, 0x0410ec81, 0xc8d545e8);
    bmagic(0x0083DDDA, 0x84a10000, 0x9220e8ff);
    bmagic(0x0083DDDE, 0x3300b1ba, 0x05c7ffee);
    bmagic(0x0083DDE2, 0x248489c4, 0x016789a4);
    bmagic(0x0083DDE6, 0x0000040c, editnpc);
    bmagic(0x0083DDEA, 0x88683d80, 0xc35dec89);

    // costume unlock BS
    bmagic(0x00458183, 0x950fc084, 0x950f91eb);
    bmagic(0x00458116, 0xcccccccc, 0x75433e81);
    bmagic(0x0045811a, 0xcccccccc, 0x6e757473);
    bmagic(0x0045811e, 0x5553cccc, 0x555368eb);

    // disable costume validation
    bmagic(0x004A97F0, 0xA108EC83, 0xA1C3C031);

    // don't show "hide store pieces" box
    bmagic(0x0071A095, 2, 1);

    if (editnpc) {
	// don't skip origin menu
	bmagic(0x00780A05, 0x3d833574, 0x3d8335eb);

	// don't skip playstyle menu
	bmagic(0x007814AD, 0x35891274, 0x358912eb);

	// don't skip archetype menu
	bmagic(0x0076F9F2, 0x3d833074, 0x3d8330eb);

	// don't skip power selection
	bmagic(0x00783DC0, 0x03da840f, 0x0003dbe9);
	bmagic(0x00783DC4, 0x8ca10000, 0x8ca19000);
    }

    // "Sandbox Mode" stuff below

    // NOP out comm check
    bmagic(0x00409332, 0x1FAC053B, 0x90909090);
    bmagic(0x00409336, 0xC01B0168, 0x90909090);

    // always return 1 for connected
    bmagic(0x0040D9CD, 3, 1);

    // ignore check for mapserver in main loop
    bmagic(0x0083ADF9, 0x3d392c77, 0x3d392ceb);

    // nocoll command
    bmagic(0x00BCEFBC, 1, 0);

    // Allow loading all override files
    bmagic(0x0088A500, 0xF0E4868B, 0xF0E42EEB);

    // turn on invert mouse
    bmagic(0x00B349F0, 0, 1);

    // Hook main command handler
    PutCall(0x0041655D, CodeAddr(CODE_CMD_HOOK));

    // Hook "enter game"
    PutCall(0x004CB80B, CodeAddr(CODE_ENTER_GAME));
    bmagic(0x004CB810, 0xC01BD8F7, 0x04A3C031);
    bmagic(0x004CB814, 0x83A6E083, 0xE9012DB5);
    bmagic(0x004CB818, 0x44895AC0, 0x0000038C);

    // Modify editor toolbar to affect entity position
    // Move it to the corner of the screen
    bmagic(0x00440C47, 0x1024448B, 0x0070B866);     // MOV AX, 70
    bmagic(0x00440C4F, 0xFD76B18D, 0xFE6BB18D);     // 28A -> 195
    bmagic(0x004408DE, 0xFD9E8E8D, 0xFE938E8D);     // 262 -> 16D
    bmagic(0x00440976, 0xFDDAC681, 0xFECFC681);     // 226 -> 131

    // Ignore editor crap
    bmagic(0x00440CA3, 0x448B1474, 0x448B14EB);     // JZ -> JMP
    PutCall(0x00440D03, CodeAddr(CODE_GET_TARGET));
    // adjust offsets for matrix position in entity
    bmagic(0x00440D1C, 0x4440D921, 0x5C40D921);     // 44 -> 5C
    bmagic(0x00440D20, 0xD920488D, 0xD938488D);     // 20 -> 38
    bmagic(0x00440D2C, 0x5CD94840, 0x5CD96040);     // 48 -> 60
    bmagic(0x00440D34, 0x245CD94C, 0x245CD964);     // 4C -> 64

    // Don't check editor selection stuff
    bmagic(0x00440DAF, 0x44D96175, 0x44D99090);     // NOP out the JNE

    // Hook 'user entered new coordinates' 
    PutCall(0x00440F00, CodeAddr(CODE_POS_UPDATE_CB));
    bmagic(0x00440F0C, 0xD0A13E74, 0xD0A137EB);     // Jump to end after hook

    // skip editor stuff here too
    bmagic(0x004405A9, 0x7D8B1174, 0x7D8B9090);
    bmagic(0x0044066F, 0x8DC1950F, 0x8D9001B1);
    bmagic(0x00440680, 0x7D834175, 0x7D8341EB);
    bmagic(0x00440795, 0x7D802174, 0x7D809090);
    bmagic(0x004407B6, 0x68A14975, 0x68A149EB);

    // Display editor toolbar in main loop
    bmagic(0x0083B96E, 0x0166CBD0, DataAddr(DATA_SHOW_TOOLBAR));
    bmagic(0x0083B974, 0x831005D9, 0x5404EC83);
    bmagic(0x0083B978, 0x1DD900A6, 0xC05283E8);
    bmagic(0x0083B97C, 0x01676D7C, 0x08C483FF);
    bmagic(0x0083B980, 0xFFFD5BE8, 0x909036EB);
    bmagic(0x0083B984, 0x24448DFF, 0x24448D90);
}
void PatchI24() {
    // product published?
    bmagic(0x00830259, 0xc032cc33, 0x01b0cc33);

    // owns product?
    bmagic(0x0083147B, 0xff853a74, 0x5aeb01b0);

    // create character
    bmagic(0x0083B246, 0x0410ec81, 0xc90ed5e8);
    if (random) {
        bmagic(0x0083B24a, 0x84a10000, 0xe980e8ff);
        bmagic(0x0083B24e, 0x3300b1ba, 0x1e6affc9);
        bmagic(0x0083B252, 0x248489c4, 0xd88b59e8);
        bmagic(0x0083B256, 0x0000040c, 0x04c483ff);
    } else {
        bmagic(0x0083B24a, 0x84a10000, 0xbb80e8ff);
        bmagic(0x0083B24e, 0x3300b1ba, 0x05c7ffee);
        bmagic(0x0083B252, 0x248489c4, 0x0167c800);
        bmagic(0x0083B256, 0x0000040c, editnpc);
    }
    bmagic(0x0083B25a, 0xc6c83d80, 0xc35dec89);

    // costume unlock BS
    bmagic(0x00458273, 0x950fc084, 0x950f91eb);
    bmagic(0x00458206, 0xcccccccc, 0x75433e81);
    bmagic(0x0045820a, 0xcccccccc, 0x6e757473);
    bmagic(0x0045820e, 0x5553cccc, 0x555368eb);

    // disable costume validation
    bmagic(0x004A9B60, 0xA108EC83, 0xA1C3C031);

    // don't show "hide store pieces" box
    bmagic(0x00719FE5, 2, 1);

    if (editnpc) {
		// don't skip origin menu
		bmagic(0x0077E255, 0x3d833574, 0x3d8335eb);

		// don't skip playstyle menu
		bmagic(0x0077ECFC, 0x35891274, 0x358912eb);

		// don't skip archetype menu
		bmagic(0x0076D222, 0x3d833074, 0x3d8330eb);

		// don't skip power selection
		bmagic(0x0078151F, 0x03da840f, 0x0003dbe9);
		bmagic(0x00781523, 0x74a10000, 0x74a19000);
    }

    // "Sandbox Mode" stuff below

    // NOP out comm check
    bmagic(0x00409332, 0x5E0C053B, 0x90909090);
    bmagic(0x00409336, 0xC01B0168, 0x90909090);

    // always return 1 for connected
    bmagic(0x0040DA1D, 3, 1);

    // ignore check for mapserver in main loop
    bmagic(0x00838249, 0x3d392c77, 0x3d392ceb);

    // nocoll command
    bmagic(0x00BD12A4, 1, 0);

    // Allow loading all override files
    bmagic(0x00887C70, 0x10C8868B, 0x10C82EEB);

    // turn on invert mouse
    bmagic(0x00B34E00, 0, 1);

    // Hook main command handler
    PutCall(0x004165BD, CodeAddr(CODE_CMD_HOOK));

    // Hook "enter game"
    PutCall(0x004CC60B, CodeAddr(CODE_ENTER_GAME));
    bmagic(0x004CC610, 0xC01BD8F7, 0xC4A3C031);
    bmagic(0x004CC614, 0x83A6E083, 0xE9012DF3);
    bmagic(0x004CC618, 0x44895AC0, 0x00000390);
//	WM_MOUSEMOVE
    // Modify editor toolbar to affect entity position
    // Move it to the corner of the screen
    bmagic(0x00440D27, 0x1024448B, 0x0070B866);     // MOV AX, 70
    bmagic(0x00440D2F, 0xFD76B18D, 0xFE6BB18D);     // 28A -> 195
    bmagic(0x004409BE, 0xFD9E8E8D, 0xFE938E8D);     // 262 -> 16D
    bmagic(0x00440A56, 0xFDDAC681, 0xFECFC681);     // 226 -> 131
    // Ignore editor crap
    bmagic(0x00440D83, 0x448B1474, 0x448B14EB);     // JZ -> JMP
    PutCall(0x00440DE3, CodeAddr(CODE_GET_TARGET));
    // adjust offsets for matrix position in entity
    bmagic(0x00440DFC, 0x4440D921, 0x5C40D921);     // 44 -> 5C
    bmagic(0x00440E00, 0xD920488D, 0xD938488D);     // 20 -> 38
    bmagic(0x00440E0C, 0x5CD94840, 0x5CD96040);     // 48 -> 60
    bmagic(0x00440E14, 0x245CD94C, 0x245CD964);     // 4C -> 64

    // Don't check editor selection stuff
    bmagic(0x00440E8F, 0x44D96175, 0x44D99090);     // NOP out the JNE

    // Hook 'user entered new coordinates' 
    PutCall(0x00440FE0, CodeAddr(CODE_POS_UPDATE_CB));
    bmagic(0x00440FEC, 0x30A13E74, 0x30A137EB);     // Jump to end after hook

    // skip editor stuff here too
    bmagic(0x004406C7, 0x7E8B1174, 0x7E8B9090);
    bmagic(0x0044078C, 0xC1950F01, 0x9001B101);
    bmagic(0x0044079C, 0x07750001, 0x07EB0001);
    bmagic(0x00440878, 0x7E801F74, 0x7E809090);
    bmagic(0x00440894, 0x75000161, 0xEB000161);

    // Display editor toolbar in main loop
    bmagic(0x00838DCA, 0x01670A30, DataAddr(DATA_SHOW_TOOLBAR));
    bmagic(0x00838DD0, 0x62B405D9, 0x5404EC83);
    bmagic(0x00838DD4, 0x1DD900A6, 0xC07F07E8);
    bmagic(0x00838DD8, 0x0167ABDC, 0x08C483FF);
    bmagic(0x00838DDC, 0xFFFD4FE8, 0x909036EB);
    bmagic(0x00838DE0, 0x24448DFF, 0x24448D90);
}