Поскольку среда в любом случае фальшивая, т. Е. У вас нет действительного порта для игры, вы также можете эмулировать функциональность порта в вашей программе.
Вот как это сделать в Windows, используя Структурная обработка исключений (SEH):
// Filename: PortEmu.c
// Compiled with Open Watcom 1.9 as: wcl386 PortEmu.c
#include <windows.h>
#include <stdio.h>
#include <conio.h>
// Port state. Holds the last value written by OUT.
// IN reads from it.
volatile UINT32 PortState = 0;
UINT32 ReadPort(UINT16 PortNumber, UINT OperandSize)
{
UNREFERENCED_PARAMETER(PortNumber);
switch (OperandSize)
{
default:
case 8:
return PortState & 0xFF;
case 16:
return PortState & 0xFFFF;
case 32:
return PortState;
}
}
void WritePort(UINT16 PortNumber, UINT OperandSize, UINT32 Value)
{
UNREFERENCED_PARAMETER(PortNumber);
switch (OperandSize)
{
default:
case 8:
PortState = (PortState & ~0xFF) | (Value & 0xFF);
break;
case 16:
PortState = (PortState & ~0xFFFF) | (Value & 0xFFFF);
break;
case 32:
PortState = Value;
break;
}
}
// Exception filter to emulate x86 IN and OUT instructions
// in 32-bit Windows application.
int IoExceptionFilter(LPEXCEPTION_POINTERS ep)
{
CONTEXT* c = ep->ContextRecord;
UINT8* instr = (UINT8*)c->Eip;
int OperandSizeIs16Bit = 0;
switch (ep->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_PRIV_INSTRUCTION:
if (instr[0] == 0x66)
{
OperandSizeIs16Bit = 1;
instr++;
}
switch (instr[0])
{
case 0xE4: // IN AL, imm8
*(UINT8*)&c->Eax = ReadPort(instr[1], 8);
c->Eip += 2 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xE5: // IN (E)AX, imm8
if (OperandSizeIs16Bit)
*(UINT16*)&c->Eax = ReadPort(instr[1], 16);
else
c->Eax = ReadPort(instr[1], 32);
c->Eip += 2 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xEC: // IN AL, DX
*(UINT8*)&c->Eax = ReadPort((UINT16)c->Edx, 8);
c->Eip += 1 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xED: // IN (E)AX, DX
if (OperandSizeIs16Bit)
*(UINT16*)&c->Eax = ReadPort((UINT16)c->Edx, 16);
else
c->Eax = ReadPort((UINT16)c->Edx, 32);
c->Eip += 1 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xE6: // OUT imm8, AL
WritePort(instr[1], 8, (UINT8)c->Eax);
c->Eip += 2 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xE7: // OUT imm8, (E)AX
if (OperandSizeIs16Bit)
WritePort(instr[1], 16, (UINT16)c->Eax);
else
WritePort(instr[1], 32, c->Eax);
c->Eip += 2 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xEE: // OUT DX, AL
WritePort((UINT16)c->Edx, 8, (UINT8)c->Eax);
c->Eip += 1 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xEF: // OUT DX, (E)AX
if (OperandSizeIs16Bit)
WritePort((UINT16)c->Edx, 16, (UINT16)c->Eax);
else
WritePort((UINT16)c->Edx, 32, c->Eax);
c->Eip += 1 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
default:
return EXCEPTION_CONTINUE_SEARCH;
}
default:
return EXCEPTION_CONTINUE_SEARCH;
}
}
int main(void)
{
__try
{
outp(0x278, 0x00);
printf("portb=0x%X\n", inp(0));
outp(0x278, 0x55);
printf("portb=0x%X\n", inp(0));
outp(0x278, 0xFF);
printf("portb=0x%X\n", inp(0));
outpw(0x278, 0xAAAA);
printf("portw=0x%X\n", inpw(0));
outpd(0x278, 0x12345678);
printf("portd=0x%X\n", inpd(0));
outpw(0x278, 0xAAAA);
outp(0x278, 0x55);
printf("portd=0x%X\n", inpd(0));
}
__except(IoExceptionFilter(GetExceptionInformation()))
{
}
return 0;
}
Вывод:
C:\>PortEmu.exe
portb=0x0
portb=0x55
portb=0xFF
portw=0xAAAA
portd=0x12345678
portd=0x1234AA55
Просто измените реализацию ReadPort()
и WritePort()
сделать что-то более полезное или более подходящее для работы с портом принтера.