Subversion Repositories SNES9x

Compare Revisions

Rev 1 → Rev 2

linux/snes9x/dsp1.h
87,44 → 87,44
Nintendo Co., Limited and its subsidiary companies.
*******************************************************************************/
 
#ifndef _DSP1_H_
#define _DSP1_H_
 
extern void (*SetDSP)(uint8, uint16);
extern uint8 (*GetDSP)(uint16);
 
void DSP1SetByte(uint8 byte, uint16 address);
uint8 DSP1GetByte(uint16 address);
 
void DSP2SetByte(uint8 byte, uint16 address);
uint8 DSP2GetByte(uint16 address);
 
void DSP3SetByte(uint8 byte, uint16 address);
uint8 DSP3GetByte(uint16 address);
void DSP3_Reset();
 
void DSP4SetByte(uint8 byte, uint16 address);
uint8 DSP4GetByte(uint16 address);
 
struct SDSP1 {
uint8 version;
bool8 waiting4command;
bool8 first_parameter;
uint8 command;
uint32 in_count;
uint32 in_index;
uint32 out_count;
uint32 out_index;
uint8 parameters [512];
uint8 output [512];
};
 
START_EXTERN_C
void S9xResetDSP1 ();
uint8 S9xGetDSP (uint16 Address);
void S9xSetDSP (uint8 Byte, uint16 Address);
END_EXTERN_C
 
extern struct SDSP1 DSP1;
 
#endif
#ifndef _DSP1_H_
#define _DSP1_H_
 
extern void (*SetDSP)(uint8, uint16);
extern uint8 (*GetDSP)(uint16);
 
void DSP1SetByte(uint8 byte, uint16 address);
uint8 DSP1GetByte(uint16 address);
 
void DSP2SetByte(uint8 byte, uint16 address);
uint8 DSP2GetByte(uint16 address);
 
void DSP3SetByte(uint8 byte, uint16 address);
uint8 DSP3GetByte(uint16 address);
void DSP3_Reset();
 
void DSP4SetByte(uint8 byte, uint16 address);
uint8 DSP4GetByte(uint16 address);
 
struct SDSP1 {
uint8 version;
bool8 waiting4command;
bool8 first_parameter;
uint8 command;
uint32 in_count;
uint32 in_index;
uint32 out_count;
uint32 out_index;
uint8 parameters [512];
uint8 output [512];
};
 
START_EXTERN_C
extern struct SDSP1 DSP1;
 
void S9xResetDSP1 ();
uint8 S9xGetDSP (uint16 Address);
void S9xSetDSP (uint8 Byte, uint16 Address);
END_EXTERN_C
 
#endif
linux/snes9x/dsp3emu.cpp
85,644 → 85,644
 
Super NES and Super Nintendo Entertainment System are trademarks of
Nintendo Co., Limited and its subsidiary companies.
*******************************************************************************/
 
uint16 DSP3_DataROM[1024] = {
0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100,
0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001,
0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100,
0x0000, 0x000f, 0x0400, 0x0200, 0x0140, 0x0400, 0x0200, 0x0040,
0x007d, 0x007e, 0x007e, 0x007b, 0x007c, 0x007d, 0x007b, 0x007c,
0x0002, 0x0020, 0x0030, 0x0000, 0x000d, 0x0019, 0x0026, 0x0032,
0x003e, 0x004a, 0x0056, 0x0062, 0x006d, 0x0079, 0x0084, 0x008e,
0x0098, 0x00a2, 0x00ac, 0x00b5, 0x00be, 0x00c6, 0x00ce, 0x00d5,
0x00dc, 0x00e2, 0x00e7, 0x00ec, 0x00f1, 0x00f5, 0x00f8, 0x00fb,
0x00fd, 0x00ff, 0x0100, 0x0100, 0x0100, 0x00ff, 0x00fd, 0x00fb,
0x00f8, 0x00f5, 0x00f1, 0x00ed, 0x00e7, 0x00e2, 0x00dc, 0x00d5,
0x00ce, 0x00c6, 0x00be, 0x00b5, 0x00ac, 0x00a2, 0x0099, 0x008e,
0x0084, 0x0079, 0x006e, 0x0062, 0x0056, 0x004a, 0x003e, 0x0032,
0x0026, 0x0019, 0x000d, 0x0000, 0xfff3, 0xffe7, 0xffdb, 0xffce,
0xffc2, 0xffb6, 0xffaa, 0xff9e, 0xff93, 0xff87, 0xff7d, 0xff72,
0xff68, 0xff5e, 0xff54, 0xff4b, 0xff42, 0xff3a, 0xff32, 0xff2b,
0xff25, 0xff1e, 0xff19, 0xff14, 0xff0f, 0xff0b, 0xff08, 0xff05,
0xff03, 0xff01, 0xff00, 0xff00, 0xff00, 0xff01, 0xff03, 0xff05,
0xff08, 0xff0b, 0xff0f, 0xff13, 0xff18, 0xff1e, 0xff24, 0xff2b,
0xff32, 0xff3a, 0xff42, 0xff4b, 0xff54, 0xff5d, 0xff67, 0xff72,
0xff7c, 0xff87, 0xff92, 0xff9e, 0xffa9, 0xffb5, 0xffc2, 0xffce,
0xffda, 0xffe7, 0xfff3, 0x002b, 0x007f, 0x0020, 0x00ff, 0xff00,
0xffbe, 0x0000, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0x0045,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffc5, 0x0003, 0x0004, 0x0005, 0x0047, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008,
0x0009, 0x004a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x004e, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011,
0x0012, 0x0013, 0x0014, 0x0053, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b,
0x0059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e,
0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0060, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a,
0x002b, 0x002c, 0x0068, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0071,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d,
0x003e, 0x003f, 0x0040, 0x0041, 0x007b, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002,
0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
0x000b, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012,
0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0050, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b,
0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023,
0x0024, 0x0025, 0x0026, 0x005d, 0x0000, 0x0000, 0x0000, 0x0000,
0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d,
0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
0x006b, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002,
0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0044, 0x0000, 0x0000,
0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016,
0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e,
0x001f, 0x0020, 0x0054, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023,
0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b,
0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0065,
0xffbe, 0x0000, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0xfead,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffc5, 0x0003, 0x0004, 0x0005, 0xfeaf, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008,
0x0009, 0xfeb2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0xfeb6, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011,
0x0012, 0x0013, 0x0014, 0xfebb, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b,
0xfec1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e,
0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0xfec8, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a,
0x002b, 0x002c, 0xfed0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0xfed9,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d,
0x003e, 0x003f, 0x0040, 0x0041, 0xfee3, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002,
0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
0x000b, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012,
0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0xfeb8, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b,
0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023,
0x0024, 0x0025, 0x0026, 0xfec5, 0x0000, 0x0000, 0x0000, 0x0000,
0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d,
0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
0xfed3, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002,
0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0xfeac, 0x0000, 0x0000,
0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016,
0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e,
0x001f, 0x0020, 0xfebc, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023,
0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b,
0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0xfecd,
0x0154, 0x0218, 0x0110, 0x00b0, 0x00cc, 0x00b0, 0x0088, 0x00b0,
0x0044, 0x00b0, 0x0000, 0x00b0, 0x00fe, 0xff07, 0x0002, 0x00ff,
0x00f8, 0x0007, 0x00fe, 0x00ee, 0x07ff, 0x0200, 0x00ef, 0xf800,
0x0700, 0x00ee, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0001,
0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
0xffff, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000,
0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0x0001, 0x0000, 0x0001,
0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000,
0xffff, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff,
0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0044, 0x0088, 0x00cc,
0x0110, 0x0154, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
};
 
#ifdef __WIN32__
void (__cdecl *SetDSP3)(void);
#else
void (*SetDSP3)(void);
#endif
 
uint16 DSP3_DR;
uint16 DSP3_SR;
uint16 DSP3_MemoryIndex;
 
void DSP3_MemorySize()
{
DSP3_DR = 0x0300;
SetDSP3 = &DSP3_Reset;
}
 
void DSP3_TestMemory()
{
DSP3_DR = 0x0000;
SetDSP3 = &DSP3_Reset;
}
 
void DSP3_DumpDataROM()
{
DSP3_DR = DSP3_DataROM[DSP3_MemoryIndex++];
if (DSP3_MemoryIndex == 1024)
SetDSP3 = &DSP3_Reset;
}
 
void DSP3_MemoryDump()
{
DSP3_MemoryIndex = 0;
SetDSP3 = &DSP3_DumpDataROM;
DSP3_DumpDataROM();
}
 
int16 DSP3_WinLo;
int16 DSP3_WinHi;
 
void DSP3_OP06()
{
DSP3_WinLo = (uint8)(DSP3_DR);
DSP3_WinHi = (uint8)(DSP3_DR >> 8);
DSP3_Reset();
}
 
void DSP3_OP03()
{
int16 Lo = (uint8)(DSP3_DR);
int16 Hi = (uint8)(DSP3_DR >> 8);
int16 Ofs = (DSP3_WinLo * Hi << 1) + (Lo << 1);
DSP3_DR = Ofs >> 1;
SetDSP3 = &DSP3_Reset;
}
 
int16 DSP3_AddLo;
int16 DSP3_AddHi;
 
void DSP3_OP07_B()
{
int16 Ofs = (DSP3_WinLo * DSP3_AddHi << 1) + (DSP3_AddLo << 1);
DSP3_DR = Ofs >> 1;
SetDSP3 = &DSP3_Reset;
}
 
void DSP3_OP07_A()
{
int16 Lo = (uint8)(DSP3_DR);
int16 Hi = (uint8)(DSP3_DR >> 8);
 
if (Lo & 1) Hi += (DSP3_AddLo & 1);
 
DSP3_AddLo += Lo;
DSP3_AddHi += Hi;
 
if (DSP3_AddLo < 0)
DSP3_AddLo += DSP3_WinLo;
else
if (DSP3_AddLo >= DSP3_WinLo)
DSP3_AddLo -= DSP3_WinLo;
 
if (DSP3_AddHi < 0)
DSP3_AddHi += DSP3_WinHi;
else
if (DSP3_AddHi >= DSP3_WinHi)
DSP3_AddHi -= DSP3_WinHi;
 
DSP3_DR = DSP3_AddLo | (DSP3_AddHi << 8) | ((DSP3_AddHi >> 8) & 0xff);
SetDSP3 = &DSP3_OP07_B;
}
 
void DSP3_OP07()
{
uint32 dataOfs = ((DSP3_DR << 1) + 0x03b2) & 0x03ff;
 
DSP3_AddHi = DSP3_DataROM[dataOfs];
DSP3_AddLo = DSP3_DataROM[dataOfs + 1];
 
SetDSP3 = &DSP3_OP07_A;
DSP3_SR = 0x0080;
}
 
uint16 DSP3_Codewords;
uint16 DSP3_Outwords;
uint16 DSP3_Symbol;
uint16 DSP3_BitCount;
uint16 DSP3_Index;
uint16 DSP3_Codes[512];
uint16 DSP3_BitsLeft;
uint16 DSP3_ReqBits;
uint16 DSP3_ReqData;
uint16 DSP3_BitCommand;
uint8 DSP3_BaseLength;
uint16 DSP3_BaseCodes;
uint16 DSP3_BaseCode;
uint8 DSP3_CodeLengths[8];
uint16 DSP3_CodeOffsets[8];
uint16 DSP3_LZCode;
uint8 DSP3_LZLength;
 
uint16 DSP3_X;
uint16 DSP3_Y;
 
void DSP3_Coordinate()
{
DSP3_Index++;
 
switch (DSP3_Index)
{
case 3:
{
if (DSP3_DR == 0xffff)
DSP3_Reset();
break;
}
case 4:
{
DSP3_X = DSP3_DR;
break;
}
case 5:
{
DSP3_Y = DSP3_DR;
DSP3_DR = 1;
break;
}
case 6:
{
DSP3_DR = DSP3_X;
break;
}
case 7:
{
DSP3_DR = DSP3_Y;
DSP3_Index = 0;
break;
}
}
}
 
uint8 DSP3_Bitmap[8];
uint8 DSP3_Bitplane[8];
uint16 DSP3_BMIndex;
uint16 DSP3_BPIndex;
uint16 DSP3_Count;
 
void DSP3_Convert_A()
{
if (DSP3_BMIndex < 8)
{
DSP3_Bitmap[DSP3_BMIndex++] = (uint8) (DSP3_DR);
DSP3_Bitmap[DSP3_BMIndex++] = (uint8) (DSP3_DR >> 8);
 
if (DSP3_BMIndex == 8)
{
for (short i=0; i < 8; i++)
for (short j=0; j < 8; j++)
{
DSP3_Bitplane[j] <<= 1;
DSP3_Bitplane[j] |= (DSP3_Bitmap[i] >> j) & 1;
}
 
DSP3_BPIndex = 0;
DSP3_Count--;
}
}
 
if (DSP3_BMIndex == 8)
{
if (DSP3_BPIndex == 8)
{
if (!DSP3_Count) DSP3_Reset();
DSP3_BMIndex = 0;
}
else
{
DSP3_DR = DSP3_Bitplane[DSP3_BPIndex++];
DSP3_DR |= DSP3_Bitplane[DSP3_BPIndex++] << 8;
}
}
}
 
void DSP3_Convert()
{
DSP3_Count = DSP3_DR;
DSP3_BMIndex = 0;
SetDSP3 = &DSP3_Convert_A;
}
 
bool DSP3_GetBits(uint8 Count)
{
if (!DSP3_BitsLeft)
{
DSP3_BitsLeft = Count;
DSP3_ReqBits = 0;
}
 
do {
if (!DSP3_BitCount)
{
DSP3_SR = 0xC0;
return false;
}
 
DSP3_ReqBits <<= 1;
if (DSP3_ReqData & 0x8000) DSP3_ReqBits++;
DSP3_ReqData <<= 1;
 
DSP3_BitCount--;
DSP3_BitsLeft--;
 
} while (DSP3_BitsLeft);
 
return true;
}
 
void DSP3_Decode_Data()
{
if (!DSP3_BitCount)
{
if (DSP3_SR & 0x40)
{
DSP3_ReqData = DSP3_DR;
DSP3_BitCount += 16;
}
else
{
DSP3_SR = 0xC0;
return;
}
}
 
if (DSP3_LZCode == 1)
{
if (!DSP3_GetBits(1))
return;
 
if (DSP3_ReqBits)
DSP3_LZLength = 12;
else
DSP3_LZLength = 8;
 
DSP3_LZCode++;
}
 
if (DSP3_LZCode == 2)
{
if (!DSP3_GetBits(DSP3_LZLength))
return;
 
DSP3_LZCode = 0;
DSP3_Outwords--;
if (!DSP3_Outwords) SetDSP3 = &DSP3_Reset;
 
DSP3_SR = 0x80;
DSP3_DR = DSP3_ReqBits;
return;
}
 
if (DSP3_BaseCode == 0xffff)
{
if (!DSP3_GetBits(DSP3_BaseLength))
return;
 
DSP3_BaseCode = DSP3_ReqBits;
}
 
if (!DSP3_GetBits(DSP3_CodeLengths[DSP3_BaseCode]))
return;
 
DSP3_Symbol = DSP3_Codes[DSP3_CodeOffsets[DSP3_BaseCode] + DSP3_ReqBits];
DSP3_BaseCode = 0xffff;
 
if (DSP3_Symbol & 0xff00)
{
DSP3_Symbol += 0x7f02;
DSP3_LZCode++;
}
else
{
DSP3_Outwords--;
if (!DSP3_Outwords)
SetDSP3 = &DSP3_Reset;
}
 
DSP3_SR = 0x80;
DSP3_DR = DSP3_Symbol;
}
 
void DSP3_Decode_Tree()
{
if (!DSP3_BitCount)
{
DSP3_ReqData = DSP3_DR;
DSP3_BitCount += 16;
}
 
if (!DSP3_BaseCodes)
{
DSP3_GetBits(1);
if (DSP3_ReqBits)
{
DSP3_BaseLength = 3;
DSP3_BaseCodes = 8;
}
else
{
DSP3_BaseLength = 2;
DSP3_BaseCodes = 4;
}
}
 
while (DSP3_BaseCodes)
{
if (!DSP3_GetBits(3))
return;
 
DSP3_ReqBits++;
 
DSP3_CodeLengths[DSP3_Index] = (uint8) DSP3_ReqBits;
DSP3_CodeOffsets[DSP3_Index] = DSP3_Symbol;
DSP3_Index++;
 
DSP3_Symbol += 1 << DSP3_ReqBits;
DSP3_BaseCodes--;
}
 
DSP3_BaseCode = 0xffff;
DSP3_LZCode = 0;
 
SetDSP3 = &DSP3_Decode_Data;
if (DSP3_BitCount) DSP3_Decode_Data();
}
 
void DSP3_Decode_Symbols()
{
DSP3_ReqData = DSP3_DR;
DSP3_BitCount += 16;
 
do {
 
if (DSP3_BitCommand == 0xffff)
{
if (!DSP3_GetBits(2)) return;
DSP3_BitCommand = DSP3_ReqBits;
}
 
switch (DSP3_BitCommand)
{
case 0:
{
if (!DSP3_GetBits(9)) return;
DSP3_Symbol = DSP3_ReqBits;
break;
}
case 1:
{
DSP3_Symbol++;
break;
}
case 2:
{
if (!DSP3_GetBits(1)) return;
DSP3_Symbol += 2 + DSP3_ReqBits;
break;
}
case 3:
{
if (!DSP3_GetBits(4)) return;
DSP3_Symbol += 4 + DSP3_ReqBits;
break;
}
}
 
DSP3_BitCommand = 0xffff;
 
DSP3_Codes[DSP3_Index++] = DSP3_Symbol;
DSP3_Codewords--;
 
} while (DSP3_Codewords);
 
DSP3_Index = 0;
DSP3_Symbol = 0;
DSP3_BaseCodes = 0;
 
SetDSP3 = &DSP3_Decode_Tree;
if (DSP3_BitCount) DSP3_Decode_Tree();
}
 
void DSP3_Decode_A()
{
DSP3_Outwords = DSP3_DR;
SetDSP3 = &DSP3_Decode_Symbols;
DSP3_BitCount = 0;
DSP3_BitsLeft = 0;
DSP3_Symbol = 0;
DSP3_Index = 0;
DSP3_BitCommand = 0xffff;
DSP3_SR = 0xC0;
}
 
void DSP3_Decode()
{
DSP3_Codewords = DSP3_DR;
SetDSP3 = &DSP3_Decode_A;
}
 
void DSP3_Command()
{
if (DSP3_DR < 0x40)
{
switch (DSP3_DR)
{
case 0x02: SetDSP3 = &DSP3_Coordinate; break;
case 0x03: SetDSP3 = &DSP3_OP03; break;
case 0x06: SetDSP3 = &DSP3_OP06; break;
case 0x07: SetDSP3 = &DSP3_OP07; return;
case 0x0f: SetDSP3 = &DSP3_TestMemory; break;
case 0x18: SetDSP3 = &DSP3_Convert; break;
case 0x1f: SetDSP3 = &DSP3_MemoryDump; break;
case 0x2f: SetDSP3 = &DSP3_MemorySize; break;
case 0x38: SetDSP3 = &DSP3_Decode; break;
}
DSP3_SR = 0x0080;
DSP3_Index = 0;
}
}
 
void DSP3_Reset()
{
DSP3_DR = 0x0080;
DSP3_SR = 0x0084;
SetDSP3 = &DSP3_Command;
}
 
void DSP3SetByte(uint8 byte, uint16 address)
{
if ((address & 0xC000) == 0x8000)
{
if (DSP3_SR & 0x04)
{
DSP3_DR = (DSP3_DR & 0xff00) + byte;
(*SetDSP3)();
}
else
{
DSP3_SR ^= 0x10;
 
if (DSP3_SR & 0x10)
DSP3_DR = (DSP3_DR & 0xff00) + byte;
else
{
DSP3_DR = (DSP3_DR & 0x00ff) + (byte << 8);
(*SetDSP3)();
}
}
}
}
 
uint8 DSP3GetByte(uint16 address)
{
if ((address & 0xC000) == 0x8000)
{
uint8 byte;
 
if (DSP3_SR & 0x04)
{
byte = (uint8) DSP3_DR;
(*SetDSP3)();
}
else
{
DSP3_SR ^= 0x10;
 
if (DSP3_SR & 0x10)
byte = (uint8) (DSP3_DR);
else
{
byte = (uint8) (DSP3_DR >> 8);
(*SetDSP3)();
}
}
 
return byte;
}
 
return (uint8) DSP3_SR;
*******************************************************************************/
 
uint16 DSP3_DataROM[1024] = {
0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100,
0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001,
0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100,
0x0000, 0x000f, 0x0400, 0x0200, 0x0140, 0x0400, 0x0200, 0x0040,
0x007d, 0x007e, 0x007e, 0x007b, 0x007c, 0x007d, 0x007b, 0x007c,
0x0002, 0x0020, 0x0030, 0x0000, 0x000d, 0x0019, 0x0026, 0x0032,
0x003e, 0x004a, 0x0056, 0x0062, 0x006d, 0x0079, 0x0084, 0x008e,
0x0098, 0x00a2, 0x00ac, 0x00b5, 0x00be, 0x00c6, 0x00ce, 0x00d5,
0x00dc, 0x00e2, 0x00e7, 0x00ec, 0x00f1, 0x00f5, 0x00f8, 0x00fb,
0x00fd, 0x00ff, 0x0100, 0x0100, 0x0100, 0x00ff, 0x00fd, 0x00fb,
0x00f8, 0x00f5, 0x00f1, 0x00ed, 0x00e7, 0x00e2, 0x00dc, 0x00d5,
0x00ce, 0x00c6, 0x00be, 0x00b5, 0x00ac, 0x00a2, 0x0099, 0x008e,
0x0084, 0x0079, 0x006e, 0x0062, 0x0056, 0x004a, 0x003e, 0x0032,
0x0026, 0x0019, 0x000d, 0x0000, 0xfff3, 0xffe7, 0xffdb, 0xffce,
0xffc2, 0xffb6, 0xffaa, 0xff9e, 0xff93, 0xff87, 0xff7d, 0xff72,
0xff68, 0xff5e, 0xff54, 0xff4b, 0xff42, 0xff3a, 0xff32, 0xff2b,
0xff25, 0xff1e, 0xff19, 0xff14, 0xff0f, 0xff0b, 0xff08, 0xff05,
0xff03, 0xff01, 0xff00, 0xff00, 0xff00, 0xff01, 0xff03, 0xff05,
0xff08, 0xff0b, 0xff0f, 0xff13, 0xff18, 0xff1e, 0xff24, 0xff2b,
0xff32, 0xff3a, 0xff42, 0xff4b, 0xff54, 0xff5d, 0xff67, 0xff72,
0xff7c, 0xff87, 0xff92, 0xff9e, 0xffa9, 0xffb5, 0xffc2, 0xffce,
0xffda, 0xffe7, 0xfff3, 0x002b, 0x007f, 0x0020, 0x00ff, 0xff00,
0xffbe, 0x0000, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0x0045,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffc5, 0x0003, 0x0004, 0x0005, 0x0047, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008,
0x0009, 0x004a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x004e, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011,
0x0012, 0x0013, 0x0014, 0x0053, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b,
0x0059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e,
0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0060, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a,
0x002b, 0x002c, 0x0068, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0071,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d,
0x003e, 0x003f, 0x0040, 0x0041, 0x007b, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002,
0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
0x000b, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012,
0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0050, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b,
0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023,
0x0024, 0x0025, 0x0026, 0x005d, 0x0000, 0x0000, 0x0000, 0x0000,
0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d,
0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
0x006b, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002,
0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0044, 0x0000, 0x0000,
0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016,
0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e,
0x001f, 0x0020, 0x0054, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023,
0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b,
0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0065,
0xffbe, 0x0000, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0xfead,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffc5, 0x0003, 0x0004, 0x0005, 0xfeaf, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008,
0x0009, 0xfeb2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0xfeb6, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011,
0x0012, 0x0013, 0x0014, 0xfebb, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b,
0xfec1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e,
0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0xfec8, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a,
0x002b, 0x002c, 0xfed0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0xfed9,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d,
0x003e, 0x003f, 0x0040, 0x0041, 0xfee3, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002,
0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
0x000b, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012,
0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0xfeb8, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b,
0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023,
0x0024, 0x0025, 0x0026, 0xfec5, 0x0000, 0x0000, 0x0000, 0x0000,
0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d,
0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
0xfed3, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002,
0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0xfeac, 0x0000, 0x0000,
0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016,
0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e,
0x001f, 0x0020, 0xfebc, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023,
0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b,
0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0xfecd,
0x0154, 0x0218, 0x0110, 0x00b0, 0x00cc, 0x00b0, 0x0088, 0x00b0,
0x0044, 0x00b0, 0x0000, 0x00b0, 0x00fe, 0xff07, 0x0002, 0x00ff,
0x00f8, 0x0007, 0x00fe, 0x00ee, 0x07ff, 0x0200, 0x00ef, 0xf800,
0x0700, 0x00ee, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0001,
0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
0xffff, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000,
0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0x0001, 0x0000, 0x0001,
0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000,
0xffff, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff,
0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0044, 0x0088, 0x00cc,
0x0110, 0x0154, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
};
 
#ifdef __WIN32__
void (__cdecl *SetDSP3)(void);
#else
void (*SetDSP3)(void);
#endif
 
uint16 DSP3_DR;
uint16 DSP3_SR;
uint16 DSP3_MemoryIndex;
 
void DSP3_MemorySize()
{
DSP3_DR = 0x0300;
SetDSP3 = &DSP3_Reset;
}
 
void DSP3_TestMemory()
{
DSP3_DR = 0x0000;
SetDSP3 = &DSP3_Reset;
}
 
void DSP3_DumpDataROM()
{
DSP3_DR = DSP3_DataROM[DSP3_MemoryIndex++];
if (DSP3_MemoryIndex == 1024)
SetDSP3 = &DSP3_Reset;
}
 
void DSP3_MemoryDump()
{
DSP3_MemoryIndex = 0;
SetDSP3 = &DSP3_DumpDataROM;
DSP3_DumpDataROM();
}
 
int16 DSP3_WinLo;
int16 DSP3_WinHi;
 
void DSP3_OP06()
{
DSP3_WinLo = (uint8)(DSP3_DR);
DSP3_WinHi = (uint8)(DSP3_DR >> 8);
DSP3_Reset();
}
 
void DSP3_OP03()
{
int16 Lo = (uint8)(DSP3_DR);
int16 Hi = (uint8)(DSP3_DR >> 8);
int16 Ofs = (DSP3_WinLo * Hi << 1) + (Lo << 1);
DSP3_DR = Ofs >> 1;
SetDSP3 = &DSP3_Reset;
}
 
int16 DSP3_AddLo;
int16 DSP3_AddHi;
 
void DSP3_OP07_B()
{
int16 Ofs = (DSP3_WinLo * DSP3_AddHi << 1) + (DSP3_AddLo << 1);
DSP3_DR = Ofs >> 1;
SetDSP3 = &DSP3_Reset;
}
 
void DSP3_OP07_A()
{
int16 Lo = (uint8)(DSP3_DR);
int16 Hi = (uint8)(DSP3_DR >> 8);
 
if (Lo & 1) Hi += (DSP3_AddLo & 1);
 
DSP3_AddLo += Lo;
DSP3_AddHi += Hi;
 
if (DSP3_AddLo < 0)
DSP3_AddLo += DSP3_WinLo;
else
if (DSP3_AddLo >= DSP3_WinLo)
DSP3_AddLo -= DSP3_WinLo;
 
if (DSP3_AddHi < 0)
DSP3_AddHi += DSP3_WinHi;
else
if (DSP3_AddHi >= DSP3_WinHi)
DSP3_AddHi -= DSP3_WinHi;
 
DSP3_DR = DSP3_AddLo | (DSP3_AddHi << 8) | ((DSP3_AddHi >> 8) & 0xff);
SetDSP3 = &DSP3_OP07_B;
}
 
void DSP3_OP07()
{
uint32 dataOfs = ((DSP3_DR << 1) + 0x03b2) & 0x03ff;
 
DSP3_AddHi = DSP3_DataROM[dataOfs];
DSP3_AddLo = DSP3_DataROM[dataOfs + 1];
 
SetDSP3 = &DSP3_OP07_A;
DSP3_SR = 0x0080;
}
 
uint16 DSP3_Codewords;
uint16 DSP3_Outwords;
uint16 DSP3_Symbol;
uint16 DSP3_BitCount;
uint16 DSP3_Index;
uint16 DSP3_Codes[512];
uint16 DSP3_BitsLeft;
uint16 DSP3_ReqBits;
uint16 DSP3_ReqData;
uint16 DSP3_BitCommand;
uint8 DSP3_BaseLength;
uint16 DSP3_BaseCodes;
uint16 DSP3_BaseCode;
uint8 DSP3_CodeLengths[8];
uint16 DSP3_CodeOffsets[8];
uint16 DSP3_LZCode;
uint8 DSP3_LZLength;
 
uint16 DSP3_X;
uint16 DSP3_Y;
 
void DSP3_Coordinate()
{
DSP3_Index++;
 
switch (DSP3_Index)
{
case 3:
{
if (DSP3_DR == 0xffff)
DSP3_Reset();
break;
}
case 4:
{
DSP3_X = DSP3_DR;
break;
}
case 5:
{
DSP3_Y = DSP3_DR;
DSP3_DR = 1;
break;
}
case 6:
{
DSP3_DR = DSP3_X;
break;
}
case 7:
{
DSP3_DR = DSP3_Y;
DSP3_Index = 0;
break;
}
}
}
 
uint8 DSP3_Bitmap[8];
uint8 DSP3_Bitplane[8];
uint16 DSP3_BMIndex;
uint16 DSP3_BPIndex;
uint16 DSP3_Count;
 
void DSP3_Convert_A()
{
if (DSP3_BMIndex < 8)
{
DSP3_Bitmap[DSP3_BMIndex++] = (uint8) (DSP3_DR);
DSP3_Bitmap[DSP3_BMIndex++] = (uint8) (DSP3_DR >> 8);
 
if (DSP3_BMIndex == 8)
{
for (short i=0; i < 8; i++)
for (short j=0; j < 8; j++)
{
DSP3_Bitplane[j] <<= 1;
DSP3_Bitplane[j] |= (DSP3_Bitmap[i] >> j) & 1;
}
 
DSP3_BPIndex = 0;
DSP3_Count--;
}
}
 
if (DSP3_BMIndex == 8)
{
if (DSP3_BPIndex == 8)
{
if (!DSP3_Count) DSP3_Reset();
DSP3_BMIndex = 0;
}
else
{
DSP3_DR = DSP3_Bitplane[DSP3_BPIndex++];
DSP3_DR |= DSP3_Bitplane[DSP3_BPIndex++] << 8;
}
}
}
 
void DSP3_Convert()
{
DSP3_Count = DSP3_DR;
DSP3_BMIndex = 0;
SetDSP3 = &DSP3_Convert_A;
}
 
bool DSP3_GetBits(uint8 Count)
{
if (!DSP3_BitsLeft)
{
DSP3_BitsLeft = Count;
DSP3_ReqBits = 0;
}
 
do {
if (!DSP3_BitCount)
{
DSP3_SR = 0xC0;
return false;
}
 
DSP3_ReqBits <<= 1;
if (DSP3_ReqData & 0x8000) DSP3_ReqBits++;
DSP3_ReqData <<= 1;
 
DSP3_BitCount--;
DSP3_BitsLeft--;
 
} while (DSP3_BitsLeft);
 
return true;
}
 
void DSP3_Decode_Data()
{
if (!DSP3_BitCount)
{
if (DSP3_SR & 0x40)
{
DSP3_ReqData = DSP3_DR;
DSP3_BitCount += 16;
}
else
{
DSP3_SR = 0xC0;
return;
}
}
 
if (DSP3_LZCode == 1)
{
if (!DSP3_GetBits(1))
return;
 
if (DSP3_ReqBits)
DSP3_LZLength = 12;
else
DSP3_LZLength = 8;
 
DSP3_LZCode++;
}
 
if (DSP3_LZCode == 2)
{
if (!DSP3_GetBits(DSP3_LZLength))
return;
 
DSP3_LZCode = 0;
DSP3_Outwords--;
if (!DSP3_Outwords) SetDSP3 = &DSP3_Reset;
 
DSP3_SR = 0x80;
DSP3_DR = DSP3_ReqBits;
return;
}
 
if (DSP3_BaseCode == 0xffff)
{
if (!DSP3_GetBits(DSP3_BaseLength))
return;
 
DSP3_BaseCode = DSP3_ReqBits;
}
 
if (!DSP3_GetBits(DSP3_CodeLengths[DSP3_BaseCode]))
return;
 
DSP3_Symbol = DSP3_Codes[DSP3_CodeOffsets[DSP3_BaseCode] + DSP3_ReqBits];
DSP3_BaseCode = 0xffff;
 
if (DSP3_Symbol & 0xff00)
{
DSP3_Symbol += 0x7f02;
DSP3_LZCode++;
}
else
{
DSP3_Outwords--;
if (!DSP3_Outwords)
SetDSP3 = &DSP3_Reset;
}
 
DSP3_SR = 0x80;
DSP3_DR = DSP3_Symbol;
}
 
void DSP3_Decode_Tree()
{
if (!DSP3_BitCount)
{
DSP3_ReqData = DSP3_DR;
DSP3_BitCount += 16;
}
 
if (!DSP3_BaseCodes)
{
DSP3_GetBits(1);
if (DSP3_ReqBits)
{
DSP3_BaseLength = 3;
DSP3_BaseCodes = 8;
}
else
{
DSP3_BaseLength = 2;
DSP3_BaseCodes = 4;
}
}
 
while (DSP3_BaseCodes)
{
if (!DSP3_GetBits(3))
return;
 
DSP3_ReqBits++;
 
DSP3_CodeLengths[DSP3_Index] = (uint8) DSP3_ReqBits;
DSP3_CodeOffsets[DSP3_Index] = DSP3_Symbol;
DSP3_Index++;
 
DSP3_Symbol += 1 << DSP3_ReqBits;
DSP3_BaseCodes--;
}
 
DSP3_BaseCode = 0xffff;
DSP3_LZCode = 0;
 
SetDSP3 = &DSP3_Decode_Data;
if (DSP3_BitCount) DSP3_Decode_Data();
}
 
void DSP3_Decode_Symbols()
{
DSP3_ReqData = DSP3_DR;
DSP3_BitCount += 16;
 
do {
 
if (DSP3_BitCommand == 0xffff)
{
if (!DSP3_GetBits(2)) return;
DSP3_BitCommand = DSP3_ReqBits;
}
 
switch (DSP3_BitCommand)
{
case 0:
{
if (!DSP3_GetBits(9)) return;
DSP3_Symbol = DSP3_ReqBits;
break;
}
case 1:
{
DSP3_Symbol++;
break;
}
case 2:
{
if (!DSP3_GetBits(1)) return;
DSP3_Symbol += 2 + DSP3_ReqBits;
break;
}
case 3:
{
if (!DSP3_GetBits(4)) return;
DSP3_Symbol += 4 + DSP3_ReqBits;
break;
}
}
 
DSP3_BitCommand = 0xffff;
 
DSP3_Codes[DSP3_Index++] = DSP3_Symbol;
DSP3_Codewords--;
 
} while (DSP3_Codewords);
 
DSP3_Index = 0;
DSP3_Symbol = 0;
DSP3_BaseCodes = 0;
 
SetDSP3 = &DSP3_Decode_Tree;
if (DSP3_BitCount) DSP3_Decode_Tree();
}
 
void DSP3_Decode_A()
{
DSP3_Outwords = DSP3_DR;
SetDSP3 = &DSP3_Decode_Symbols;
DSP3_BitCount = 0;
DSP3_BitsLeft = 0;
DSP3_Symbol = 0;
DSP3_Index = 0;
DSP3_BitCommand = 0xffff;
DSP3_SR = 0xC0;
}
 
void DSP3_Decode()
{
DSP3_Codewords = DSP3_DR;
SetDSP3 = &DSP3_Decode_A;
}
 
void DSP3_Command()
{
if (DSP3_DR < 0x40)
{
switch (DSP3_DR)
{
case 0x02: SetDSP3 = &DSP3_Coordinate; break;
case 0x03: SetDSP3 = &DSP3_OP03; break;
case 0x06: SetDSP3 = &DSP3_OP06; break;
case 0x07: SetDSP3 = &DSP3_OP07; return;
case 0x0f: SetDSP3 = &DSP3_TestMemory; break;
case 0x18: SetDSP3 = &DSP3_Convert; break;
case 0x1f: SetDSP3 = &DSP3_MemoryDump; break;
case 0x2f: SetDSP3 = &DSP3_MemorySize; break;
case 0x38: SetDSP3 = &DSP3_Decode; break;
}
DSP3_SR = 0x0080;
DSP3_Index = 0;
}
}
 
void DSP3_Reset()
{
DSP3_DR = 0x0080;
DSP3_SR = 0x0084;
SetDSP3 = &DSP3_Command;
}
 
void DSP3SetByte(uint8 byte, uint16 address)
{
if ((address & 0xC000) == 0x8000)
{
if (DSP3_SR & 0x04)
{
DSP3_DR = (DSP3_DR & 0xff00) + byte;
(*SetDSP3)();
}
else
{
DSP3_SR ^= 0x10;
 
if (DSP3_SR & 0x10)
DSP3_DR = (DSP3_DR & 0xff00) + byte;
else
{
DSP3_DR = (DSP3_DR & 0x00ff) + (byte << 8);
(*SetDSP3)();
}
}
}
}
 
uint8 DSP3GetByte(uint16 address)
{
if ((address & 0xC000) == 0x8000)
{
uint8 byte;
 
if (DSP3_SR & 0x04)
{
byte = (uint8) DSP3_DR;
(*SetDSP3)();
}
else
{
DSP3_SR ^= 0x10;
 
if (DSP3_SR & 0x10)
byte = (uint8) (DSP3_DR);
else
{
byte = (uint8) (DSP3_DR >> 8);
(*SetDSP3)();
}
}
 
return byte;
}
 
return (uint8) DSP3_SR;
}
\ No newline at end of file
linux/snes9x/dsp1.cpp
1023,147 → 1023,147
DSP4.in_index++;
}
 
if (!DSP4.waiting4command && DSP4.in_count==DSP4.in_index)
{
//DSP4.parameters [DSP4.in_index] |= (byte << 8);
// Actually execute the command
DSP4.waiting4command = TRUE;
DSP4.out_index = 0;
DSP4.in_index=0;
switch (DSP4.command)
{
// 16-bit multiplication
case 0x0000:
{
int16 multiplier, multiplicand;
int product;
 
multiplier = DSP4_READ_WORD(0);
multiplicand = DSP4_READ_WORD(2);
 
DSP4_Multiply(multiplicand,multiplier,product);
 
DSP4.out_count = 4;
DSP4_WRITE_WORD(0,product);
DSP4_WRITE_WORD(2,product>>16);
}
break;
 
// unknown: horizontal mapping command
case 0x0011:
{
int16 a,b,c,d,m;
 
a = DSP4_READ_WORD(6);
b = DSP4_READ_WORD(4);
c = DSP4_READ_WORD(2);
d = DSP4_READ_WORD(0);
 
DSP4_UnknownOP11(a,b,c,d,m);
 
DSP4.out_count = 2;
DSP4_WRITE_WORD(0,m);
break;
}
 
// track projection
case 0x0001: DSP4_Op01(); break;
 
// track projection (pass 2)
case 0x0007: DSP4_Op07(); break;
 
// zone projections (fuel/repair/lap/teleport/...)
case 0x0008: DSP4_Op08(); break;
 
// sprite transformation
case 0x0009: DSP4_Op09(); break;
 
// fast track projection
case 0x000D: DSP4_Op0D(); break;
 
// single-player selection
case 0x0003: DSP4_Op03(); break;
 
// clear OAM
case 0x0005:
{
op06_index = 0;
op06_offset = 0;
for( int lcv=0; lcv<32; lcv++ )
op06_OAM[lcv] = 0;
break;
}
 
// multi-player selection
case 0x000E: DSP4_Op0E(); break;
 
#undef PRINT
 
// transfer OAM
case 0x0006:
{
DSP4.out_count = 32;
for( int lcv=0; lcv<32; lcv++ )
DSP4.output[lcv] = op06_OAM[lcv];
}
break;
 
// unknown
case 0x000A:
{
int16 in1a = DSP4_READ_WORD(0);
int16 in2a = DSP4_READ_WORD(2);
int16 in3a = DSP4_READ_WORD(4);
int16 out1a,out2a,out3a,out4a;
 
// NOTE: Snes9x only!
// For some odd reason, the input nybbles are reversed
 
DSP4_Op0A(in2a,out1a,out2a,out3a,out4a);
 
DSP4.out_count=8;
 
// Hack: Reverse the outputs for now to compensate
// Otherwise the AI gets really flaky
DSP4_WRITE_WORD(0,out2a);
DSP4_WRITE_WORD(2,out1a);
DSP4_WRITE_WORD(4,out4a);
DSP4_WRITE_WORD(6,out3a);
}
break;
 
// set OAM
case 0x000B:
{
int16 sp_x = DSP4_READ_WORD(0);
int16 sp_y = DSP4_READ_WORD(2);
int16 oam = DSP4_READ_WORD(4);
 
if ((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb))
{
short Row = (sp_y >> 3) & 0x1f;
 
if (RowCount[Row] < MaxTilesPerRow)
{
RowCount[Row]++;
 
// yield OAM output
DSP4.out_count = 6;
DSP4_WRITE_WORD(0,1);
 
// pack OAM data: x,y,name,attr
DSP4.output[2] = sp_x & 0xff;
DSP4.output[3] = sp_y & 0xff;
DSP4_WRITE_WORD(4,oam);
 
// OAM: size,msb data
DSP4_Op06(0,0);
}
}
}
break;
 
default: break;
if (!DSP4.waiting4command && DSP4.in_count==DSP4.in_index)
{
//DSP4.parameters [DSP4.in_index] |= (byte << 8);
// Actually execute the command
DSP4.waiting4command = TRUE;
DSP4.out_index = 0;
DSP4.in_index=0;
switch (DSP4.command)
{
// 16-bit multiplication
case 0x0000:
{
int16 multiplier, multiplicand;
int product;
 
multiplier = DSP4_READ_WORD(0);
multiplicand = DSP4_READ_WORD(2);
 
DSP4_Multiply(multiplicand,multiplier,product);
 
DSP4.out_count = 4;
DSP4_WRITE_WORD(0,product);
DSP4_WRITE_WORD(2,product>>16);
}
break;
 
// unknown: horizontal mapping command
case 0x0011:
{
int16 a,b,c,d,m;
 
a = DSP4_READ_WORD(6);
b = DSP4_READ_WORD(4);
c = DSP4_READ_WORD(2);
d = DSP4_READ_WORD(0);
 
DSP4_UnknownOP11(a,b,c,d,m);
 
DSP4.out_count = 2;
DSP4_WRITE_WORD(0,m);
break;
}
 
// track projection
case 0x0001: DSP4_Op01(); break;
 
// track projection (pass 2)
case 0x0007: DSP4_Op07(); break;
 
// zone projections (fuel/repair/lap/teleport/...)
case 0x0008: DSP4_Op08(); break;
 
// sprite transformation
case 0x0009: DSP4_Op09(); break;
 
// fast track projection
case 0x000D: DSP4_Op0D(); break;
 
// single-player selection
case 0x0003: DSP4_Op03(); break;
 
// clear OAM
case 0x0005:
{
op06_index = 0;
op06_offset = 0;
for( int lcv=0; lcv<32; lcv++ )
op06_OAM[lcv] = 0;
break;
}
 
// multi-player selection
case 0x000E: DSP4_Op0E(); break;
 
#undef PRINT
 
// transfer OAM
case 0x0006:
{
DSP4.out_count = 32;
for( int lcv=0; lcv<32; lcv++ )
DSP4.output[lcv] = op06_OAM[lcv];
}
break;
 
// unknown
case 0x000A:
{
int16 in1a = DSP4_READ_WORD(0);
int16 in2a = DSP4_READ_WORD(2);
int16 in3a = DSP4_READ_WORD(4);
int16 out1a,out2a,out3a,out4a;
 
// NOTE: Snes9x only!
// For some odd reason, the input nybbles are reversed
 
DSP4_Op0A(in2a,out1a,out2a,out3a,out4a);
 
DSP4.out_count=8;
 
// Hack: Reverse the outputs for now to compensate
// Otherwise the AI gets really flaky
DSP4_WRITE_WORD(0,out2a);
DSP4_WRITE_WORD(2,out1a);
DSP4_WRITE_WORD(4,out4a);
DSP4_WRITE_WORD(6,out3a);
}
break;
 
// set OAM
case 0x000B:
{
int16 sp_x = DSP4_READ_WORD(0);
int16 sp_y = DSP4_READ_WORD(2);
int16 oam = DSP4_READ_WORD(4);
 
if ((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb))
{
short Row = (sp_y >> 3) & 0x1f;
 
if (RowCount[Row] < MaxTilesPerRow)
{
RowCount[Row]++;
 
// yield OAM output
DSP4.out_count = 6;
DSP4_WRITE_WORD(0,1);
 
// pack OAM data: x,y,name,attr
DSP4.output[2] = sp_x & 0xff;
DSP4.output[3] = sp_y & 0xff;
DSP4_WRITE_WORD(4,oam);
 
// OAM: size,msb data
DSP4_Op06(0,0);
}
}
}
break;
 
default: break;
}
}
}
linux/snes9x/dsp4.h
1,83 → 1,83
// debug
int block; // current block number
extern int c;
 
// op control
int8 DSP4_Logic; // controls op flow
 
// projection format
const int16 PLANE_START = 0x7fff; // starting distance
 
int16 view_plane; // viewer location
int16 far_plane; // next milestone into screen
int16 segments; // # raster segments to draw
int16 raster; // current raster line
 
int16 project_x; // current x-position
int16 project_y; // current y-position
 
int16 project_centerx; // x-target of projection
int16 project_centery; // y-target of projection
 
int16 project_x1; // current x-distance
int16 project_x1low; // lower 16-bits
int16 project_y1; // current y-distance
int16 project_y1low; // lower 16-bits
 
int16 project_x2; // next projected x-distance
int16 project_y2; // next projected y-distance
 
int16 project_pitchx; // delta center
int16 project_pitchxlow; // lower 16-bits
int16 project_pitchy; // delta center
int16 project_pitchylow; // lower 16-bits
 
int16 project_focalx; // x-point of projection at viewer plane
int16 project_focaly; // y-point of projection at viewer plane
 
int16 project_ptr; // data structure pointer
 
// render window
int16 center_x; // x-center of viewport
int16 center_y; // y-center of viewport
int16 viewport_left; // x-left of viewport
int16 viewport_right; // x-right of viewport
int16 viewport_top; // y-top of viewport
int16 viewport_bottom; // y-bottom of viewport
 
// sprite structure
int16 sprite_x; // projected x-pos of sprite
int16 sprite_y; // projected y-pos of sprite
int16 sprite_offset; // data pointer offset
int8 sprite_type; // vehicle, terrain
bool8 sprite_size; // sprite size: 8x8 or 16x16
 
// path strips
int16 path_clipRight[4]; // value to clip to for x>b
int16 path_clipLeft[4]; // value to clip to for x<a
int16 path_pos[4]; // x-positions of lanes
int16 path_ptr[4]; // data structure pointers
int16 path_raster[4]; // current raster
int16 path_top[4]; // viewport_top
 
int16 path_y[2]; // current y-position
int16 path_x[2]; // current focals
int16 path_plane[2]; // previous plane
 
// op09 window sorting
int16 multi_index1; // index counter
int16 multi_index2; // index counter
bool8 op09_mode; // window mode
 
// multi-op storage
int16 multi_focaly[64]; // focal_y values
int16 multi_farplane[4]; // farthest drawn distance
int16 multi_raster[4]; // line where track stops
 
// OAM
int8 op06_OAM[32]; // OAM (size,MSB) data
int8 op06_index; // index into OAM table
int8 op06_offset; // offset into OAM table
 
short MaxTilesPerRow = 0;
short RowCount[32];
// debug
int block; // current block number
extern int c;
 
// op control
int8 DSP4_Logic; // controls op flow
 
// projection format
const int16 PLANE_START = 0x7fff; // starting distance
 
int16 view_plane; // viewer location
int16 far_plane; // next milestone into screen
int16 segments; // # raster segments to draw
int16 raster; // current raster line
 
int16 project_x; // current x-position
int16 project_y; // current y-position
 
int16 project_centerx; // x-target of projection
int16 project_centery; // y-target of projection
 
int16 project_x1; // current x-distance
int16 project_x1low; // lower 16-bits
int16 project_y1; // current y-distance
int16 project_y1low; // lower 16-bits
 
int16 project_x2; // next projected x-distance
int16 project_y2; // next projected y-distance
 
int16 project_pitchx; // delta center
int16 project_pitchxlow; // lower 16-bits
int16 project_pitchy; // delta center
int16 project_pitchylow; // lower 16-bits
 
int16 project_focalx; // x-point of projection at viewer plane
int16 project_focaly; // y-point of projection at viewer plane
 
int16 project_ptr; // data structure pointer
 
// render window
int16 center_x; // x-center of viewport
int16 center_y; // y-center of viewport
int16 viewport_left; // x-left of viewport
int16 viewport_right; // x-right of viewport
int16 viewport_top; // y-top of viewport
int16 viewport_bottom; // y-bottom of viewport
 
// sprite structure
int16 sprite_x; // projected x-pos of sprite
int16 sprite_y; // projected y-pos of sprite
int16 sprite_offset; // data pointer offset
int8 sprite_type; // vehicle, terrain
bool8 sprite_size; // sprite size: 8x8 or 16x16
 
// path strips
int16 path_clipRight[4]; // value to clip to for x>b
int16 path_clipLeft[4]; // value to clip to for x<a
int16 path_pos[4]; // x-positions of lanes
int16 path_ptr[4]; // data structure pointers
int16 path_raster[4]; // current raster
int16 path_top[4]; // viewport_top
 
int16 path_y[2]; // current y-position
int16 path_x[2]; // current focals
int16 path_plane[2]; // previous plane
 
// op09 window sorting
int16 multi_index1; // index counter
int16 multi_index2; // index counter
bool8 op09_mode; // window mode
 
// multi-op storage
int16 multi_focaly[64]; // focal_y values
int16 multi_farplane[4]; // farthest drawn distance
int16 multi_raster[4]; // line where track stops
 
// OAM
int8 op06_OAM[32]; // OAM (size,MSB) data
int8 op06_index; // index into OAM table
int8 op06_offset; // offset into OAM table
 
short MaxTilesPerRow = 0;
short RowCount[32];
linux/snes9x/offsets Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
linux/snes9x/win32.cpp
100,7 → 100,7
#include "soundux.h"
#include "netplay.h"
#include "movie.h"
#include "..\AVIOutput.h"
#include "..\AVIOutput.h"
#include "..\language.h"
 
#include <direct.h>
1442,13 → 1442,13
 
ClientToScreen (GUI.hWnd, &p);
GetClientRect (GUI.hWnd, &dstRect);
OffsetRect(&dstRect, p.x, p.y);
*/
p.x = p.y = 0;
ClientToScreen (GUI.hWnd, &p);
GetClientRect (GUI.hWnd, &dstRect);
dstRect.bottom = int(double(dstRect.bottom) * double(239.0 / 240.0));
OffsetRect(&dstRect, p.x, p.y);
*/
p.x = p.y = 0;
ClientToScreen (GUI.hWnd, &p);
GetClientRect (GUI.hWnd, &dstRect);
dstRect.bottom = int(double(dstRect.bottom) * double(239.0 / 240.0));
OffsetRect(&dstRect, p.x, p.y);
}
else
{
linux/snes9x/ppu.h
298,6 → 298,12
uint8 FirstLine;
};
 
typedef struct{
uint8 _5C77;
uint8 _5C78;
uint8 _5A22;
} SnesModel;
 
START_EXTERN_C
void S9xUpdateScreen ();
void S9xResetPPU ();
321,21 → 327,15
extern struct SPPU PPU;
extern struct SDMA DMA [8];
extern struct InternalPPU IPPU;
 
extern SnesModel* Model;
extern SnesModel M1SNES;
extern SnesModel M2SNES;
END_EXTERN_C
 
#include "gfx.h"
#include "memmap.h"
 
typedef struct{
uint8 _5C77;
uint8 _5C78;
uint8 _5A22;
} SnesModel;
 
extern SnesModel* Model;
extern SnesModel M1SNES;
extern SnesModel M2SNES;
 
#define MAX_5C77_VERSION 0x01
#define MAX_5C78_VERSION 0x03
#define MAX_5A22_VERSION 0x02
linux/snes9x/dsp4emu.cpp
85,1502 → 85,1502
 
Super NES and Super Nintendo Entertainment System are trademarks of
Nintendo Co., Limited and its subsidiary companies.
*******************************************************************************/
 
// Due recognition and credit are given on Overload's DSP website.
// Thank those contributors for their hard work on this chip.
 
#include "dsp4.h"
 
#define DSP4_READ_WORD(x) \
READ_WORD(DSP4.parameters+x)
 
#define DSP4_WRITE_WORD(x,d) \
WRITE_WORD(DSP4.output+x,d);
 
// used to wait for dsp i/o
#define DSP4_WAIT(x) \
DSP4_Logic = x; return;
 
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
 
void DSP4_Multiply(short Multiplicand, short Multiplier, int &Product)
{
Product = (Multiplicand * Multiplier << 1) >> 1;
}
 
void DSP4_UnknownOP11(short A, short B, short C, short D, short &M)
{
// 0x155 = 341 = Horizontal Width of the Screen
M = ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) |
((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f);
}
 
const unsigned short Op0A_Values[16] = {
0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150,
0xfe80, 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0
};
 
void DSP4_Op0A(short n2, short &o1, short &o2, short &o3, short &o4)
{
o4 = Op0A_Values[(n2 & 0x000f)];
o3 = Op0A_Values[(n2 & 0x00f0) >> 4];
o2 = Op0A_Values[(n2 & 0x0f00) >> 8];
o1 = Op0A_Values[(n2 & 0xf000) >> 12];
}
 
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
 
#if OP==0x0009
#define PRINT
#endif
 
void DSP4_Op03()
{
#ifdef PRINT
printf("Op03\n");
#endif
 
MaxTilesPerRow = 33;
 
for (int i=0; i < 32; i++)
RowCount[i] = 0;
 
// reset op09 data
op09_mode = 0;
}
 
void DSP4_Op0E()
{
#ifdef PRINT
printf("Op0E\n");
#endif
 
MaxTilesPerRow = 16;
 
for (int i=0; i < 32; i++)
RowCount[i] = 0;
 
// reset op09 data
op09_mode = 1;
}
 
#undef PRINT
 
void DSP4_Op06(bool8 size, bool8 msb)
{
// save post-oam table data for future retrieval
op06_OAM[op06_index] |= (msb<<(op06_offset+0));
op06_OAM[op06_index] |= (size<<(op06_offset+1));
op06_offset += 2;
 
if(op06_offset==8)
{
// move to next byte in buffer
op06_offset=0;
op06_index++;
}
}
 
#if OP==0x0001
#define PRINT
#endif
 
void DSP4_Op01()
{
uint16 command;
 
DSP4.waiting4command = FALSE;
 
// op flow control
switch(DSP4_Logic) {
case 1: goto resume1; break;
case 2: goto resume2; break;
}
 
////////////////////////////////////////////////////
// process initial inputs
 
// sort inputs
// 0x00 = DSP4_READ_WORD(0x00);
project_focaly = DSP4_READ_WORD(0x02);
raster = DSP4_READ_WORD(0x04);
viewport_top = DSP4_READ_WORD(0x06);
project_y = DSP4_READ_WORD(0x08);
viewport_bottom = DSP4_READ_WORD(0x0a);
project_x1low = DSP4_READ_WORD(0x0c);
project_focalx = DSP4_READ_WORD(0x0e);
project_centerx = DSP4_READ_WORD(0x10);
project_ptr = DSP4_READ_WORD(0x12);
// (envelope?) 0xc0 = DSP4_READ_WORD(0x14);
project_pitchylow = DSP4_READ_WORD(0x16);
project_pitchy = DSP4_READ_WORD(0x18);
project_pitchxlow = DSP4_READ_WORD(0x1a);
project_pitchx = DSP4_READ_WORD(0x1c);
far_plane = DSP4_READ_WORD(0x1e);
// ? = DSP4_READ_WORD(0x20);
project_y1low = DSP4_READ_WORD(0x22);
 
// pre-compute
view_plane = PLANE_START;
 
// find starting projection points
project_x1 = project_focalx;
project_y -= viewport_bottom;
 
// multi-op storage
multi_index1 = 0;
multi_index2 = 0;
 
// debug
block=0;
 
////////////////////////////////////////////////////
// command check
 
do {
// scan next command
DSP4.in_count = 2;
 
DSP4_WAIT(1) resume1:
 
// inspect input
command = DSP4_READ_WORD(0);
 
// check for termination
if(command == 0x8000) break;
 
// already have 2 bytes in queue
DSP4.in_index = 2;
DSP4.in_count = 8;
 
DSP4_WAIT(2) resume2:
 
////////////////////////////////////////////////////
// process one iteration of projection
 
// inspect inputs
int16 plane = DSP4_READ_WORD(0);
int16 index, lcv;
int16 py_dy=0, px_dx=0;
int16 y_out, x_out;
int16 envelope = DSP4_READ_WORD(6);
int16 project_x;
 
// ignore invalid data
if((uint16) plane == 0x8001) continue;
 
// one-time init
if(far_plane)
{
// setup final parameters
project_focalx += plane;
project_x1 = project_focalx;
project_y1 = project_focaly;
plane = far_plane;
far_plane = 0;
 
// track occlusion
multi_farplane[1] = plane;
multi_raster[1] = viewport_bottom;
}
 
// use proportional triangles to project new coords
project_x2 = project_focalx * plane / view_plane;
project_y2 = project_focaly * plane / view_plane;
 
// quadratic regression (rough)
if(project_focaly>=-0x0f)
py_dy = project_focaly * project_focaly * -0.20533553
- 1.08330005 * project_focaly - 69.61094639;
else
py_dy = project_focaly * project_focaly * -0.000657035759
- 1.07629051 * project_focaly - 65.69315963;
 
// approximate # of raster lines
segments = abs(project_y2-project_y1);
 
// prevent overdraw
if(project_y2>=raster) segments=0;
else raster=project_y2;
 
// don't draw outside the window
if(project_y2<viewport_top) segments=0;
 
// project new positions
if(segments>0)
{
// interpolate between projected points
px_dx = ((project_x2-project_x1)<<8)/segments;
}
 
// debug
++block;
#ifdef PRINT
printf("(line %d) Op01 check %02X, plane %04X, focal_y %04X, y2 %04X, y1 %04X\n",c,(uint16)segments,(uint16)(plane),(uint16)project_focaly,(uint16)project_y2,(uint16)project_y1);
#endif
 
// prepare output
DSP4.out_count=8+2+6*segments;
 
// pre-block data
DSP4_WRITE_WORD(0,project_focalx);
DSP4_WRITE_WORD(2,project_x2);
DSP4_WRITE_WORD(4,project_focaly);
DSP4_WRITE_WORD(6,project_y2);
DSP4_WRITE_WORD(8,segments);
 
#if 0
DSP4_WRITE_WORD(0,-1);
DSP4_WRITE_WORD(2,-1);
DSP4_WRITE_WORD(4,-1);
DSP4_WRITE_WORD(6,-1);
DSP4_WRITE_WORD(8,-1);
#endif
 
index=10;
 
project_x = project_centerx + project_x1;
 
// iterate through each point
for( lcv=0; lcv<segments; lcv++ )
{
// step through the projected line
y_out = project_y+((py_dy*lcv)>>8);
x_out = project_x+((px_dx*lcv)>>8);
 
// factor in dynamic track changes
y_out += envelope;
 
#if 0
project_ptr=-1;
y_out=-1;
//x_out=-1;
#endif
 
// data
DSP4_WRITE_WORD(index+0,project_ptr);
DSP4_WRITE_WORD(index+2,y_out);
DSP4_WRITE_WORD(index+4,x_out);
index += 6;
 
// post-update
project_ptr -= 4;
}
 
// post-update
project_y += ((py_dy*lcv)>>8);
 
// new positions
if(segments>0)
{
project_x1 = project_x2;
project_y1 = project_y2;
 
// storage of focals for op07
multi_focaly[multi_index2++] = project_focaly;
 
// track occlusion: can't see anything below it
multi_farplane[1] = plane;
multi_raster[1] -= segments;
}
 
// update projection points
project_pitchy += (int8)DSP4.parameters[3];
project_pitchx += (int8)DSP4.parameters[5];
 
project_focaly += project_pitchy;
project_focalx += project_pitchx;
} while (1);
 
// terminate op
DSP4.waiting4command = TRUE;
DSP4.out_count = 0;
}
 
#undef PRINT
 
#if OP==0x0007
#define PRINT
#endif
 
void DSP4_Op07()
{
uint16 command;
 
DSP4.waiting4command = FALSE;
 
// op flow control
switch(DSP4_Logic) {
case 1: goto resume1; break;
case 2: goto resume2; break;
}
 
////////////////////////////////////////////////////
// sort inputs
 
// 0x00 = DSP4_READ_WORD(0x00);
project_focaly = DSP4_READ_WORD(0x02);
raster = DSP4_READ_WORD(0x04);
viewport_top = DSP4_READ_WORD(0x06);
project_y = DSP4_READ_WORD(0x08);
viewport_bottom = DSP4_READ_WORD(0x0a);
project_x1low = DSP4_READ_WORD(0x0c);
project_x1 = DSP4_READ_WORD(0x0e);
project_centerx = DSP4_READ_WORD(0x10);
project_ptr = DSP4_READ_WORD(0x12);
// (envelope?) 0xc0 = DSP4_READ_WORD(0x14);
 
// pre-compute
view_plane = PLANE_START;
 
// find projection targets
project_y1 = project_focaly;
project_y -= viewport_bottom;
 
// multi-op storage
multi_index2 = 0;
 
// debug
block=0;
 
#ifdef PRINT
printf("(line %d) Op07 data %04X\n",c,(uint16)project_y1);
#endif
 
////////////////////////////////////////////////////
// command check
 
do {
// scan next command
DSP4.in_count = 2;
 
DSP4_WAIT(1) resume1:
 
// inspect input
command = DSP4_READ_WORD(0);
 
// check for opcode termination
if(command == 0x8000) break;
 
// already have 2 bytes in queue
DSP4.in_index = 2;
DSP4.in_count = 12;
 
DSP4_WAIT(2) resume2:
 
////////////////////////////////////////////////////
// process one loop of projection
 
int16 plane;
int16 index,lcv;
int16 y_out,x_out;
int16 py_dy=0,px_dx=0;
int16 project_x;
 
// debug
++block;
 
// inspect inputs
plane = DSP4_READ_WORD(0);
project_y2 = DSP4_READ_WORD(2);
// ? = DSP4_READ_WORD(4);
project_x2 = DSP4_READ_WORD(6);
int16 envelope = DSP4_READ_WORD(8);
 
// ignore invalid data
if((uint16) plane == 0x8001) continue;
 
// multi-op storage
project_focaly = multi_focaly[multi_index2];
 
// quadratic regression (rough)
if(project_focaly>=-0x0f)
py_dy = project_focaly * project_focaly * -0.20533553
- 1.08330005 * project_focaly - 69.61094639;
else
py_dy = project_focaly * project_focaly * -0.000657035759
- 1.07629051 * project_focaly - 65.69315963;
 
// approximate # of raster lines
segments = abs(project_y2-project_y1);
 
// prevent overdraw
if(project_y2>=raster) segments=0;
else raster=project_y2;
 
// don't draw outside the window
if(project_y2<viewport_top) segments=0;
 
// project new positions
if(segments>0)
{
// interpolate between projected points
px_dx = ((project_x2-project_x1)<<8)/segments;
}
 
#ifdef PRINT
printf("(line %d) Op07 block %d, loc %04X, out %02X, project_x2 %04X\n",c,block,plane,segments,(uint16)project_x2);
#endif
 
// prepare pre-output
DSP4.out_count=4+2+6*segments;
 
DSP4_WRITE_WORD(0,project_x2);
DSP4_WRITE_WORD(2,project_y2);
DSP4_WRITE_WORD(4,segments);
 
#if 0
DSP4_WRITE_WORD(0,-1);
DSP4_WRITE_WORD(2,-1);
DSP4_WRITE_WORD(4,-1);
#endif
 
index=6;
 
project_x = project_centerx + project_x1;
 
for( lcv=0; lcv<segments; lcv++ )
{
// pre-compute
y_out = project_y+((py_dy*lcv)>>8);
x_out = project_x+((px_dx*lcv)>>8);
 
// factor in dynamic track changes
y_out += envelope;
 
#if 0
project_ptr = -1;
//y_out = -1;
x_out = -1;
#endif
 
// data
DSP4_WRITE_WORD(index+0,project_ptr);
DSP4_WRITE_WORD(index+2,y_out);
DSP4_WRITE_WORD(index+4,x_out);
index += 6;
 
// post-update
project_ptr -= 4;
}
 
// update internal variables
project_y += ((py_dy*lcv)>>8);
 
// new positions
if(segments>0)
{
project_x1 = project_x2;
project_y1 = project_y2;
 
// multi-op storage
multi_index2++;
}
} while(1);
 
DSP4.waiting4command = TRUE;
DSP4.out_count = 0;
}
 
#undef PRINT
 
#if OP==0x0008
#define PRINT
#endif
 
void DSP4_Op08()
{
uint16 command;
 
DSP4.waiting4command = FALSE;
 
// op flow control
switch(DSP4_Logic) {
case 1: goto resume1; break;
case 2: goto resume2; break;
}
 
////////////////////////////////////////////////////
// process initial inputs
 
// clip values
path_clipRight[0] = DSP4_READ_WORD(0x00);
path_clipRight[1] = DSP4_READ_WORD(0x02);
path_clipRight[2] = DSP4_READ_WORD(0x04);
path_clipRight[3] = DSP4_READ_WORD(0x06);
 
path_clipLeft[0] = DSP4_READ_WORD(0x08);
path_clipLeft[1] = DSP4_READ_WORD(0x0a);
path_clipLeft[2] = DSP4_READ_WORD(0x0c);
path_clipLeft[3] = DSP4_READ_WORD(0x0e);
 
// unknown (constant)
// unknown (constant)
 
// path positions
path_pos[0] = DSP4_READ_WORD(0x20);
path_pos[1] = DSP4_READ_WORD(0x22);
path_pos[2] = DSP4_READ_WORD(0x24);
path_pos[3] = DSP4_READ_WORD(0x26);
 
// data locations
path_ptr[0] = DSP4_READ_WORD(0x28);
path_ptr[1] = DSP4_READ_WORD(0x2a);
path_ptr[2] = DSP4_READ_WORD(0x2c);
path_ptr[3] = DSP4_READ_WORD(0x2e);
 
// project_y1 lines
path_raster[0] = DSP4_READ_WORD(0x30);
path_raster[1] = DSP4_READ_WORD(0x32);
path_raster[2] = DSP4_READ_WORD(0x34);
path_raster[3] = DSP4_READ_WORD(0x36);
 
// viewport_top
path_top[0] = DSP4_READ_WORD(0x38);
path_top[1] = DSP4_READ_WORD(0x3a);
path_top[2] = DSP4_READ_WORD(0x3c);
path_top[3] = DSP4_READ_WORD(0x3e);
 
// unknown (constants)
 
view_plane = PLANE_START;
 
// debug
block=0;
 
////////////////////////////////////////////////////
// command check
 
do {
// scan next command
DSP4.in_count = 2;
 
DSP4_WAIT(1) resume1:
 
// inspect input
command = DSP4_READ_WORD(0);
 
// terminate op
if(command == 0x8000) break;
 
// already have 2 bytes in queue
DSP4.in_index = 2;
DSP4.in_count = 18;
 
DSP4_WAIT(2) resume2:
 
////////////////////////////////////////////////////
// projection begins
 
// debug
++block;
 
// used in envelope shaping
int16 x1_final;
int16 x2_final;
 
// look at guidelines
int16 plane = DSP4_READ_WORD(0x00);
int16 x_left = DSP4_READ_WORD(0x02);
int16 y_left = DSP4_READ_WORD(0x04);
int16 x_right = DSP4_READ_WORD(0x06);
int16 y_right = DSP4_READ_WORD(0x08);
 
// envelope guidelines (one frame only)
int16 envelope1 = DSP4_READ_WORD(0x0a);
int16 envelope2 = DSP4_READ_WORD(0x0c);
int16 envelope3 = DSP4_READ_WORD(0x0e);
int16 envelope4 = DSP4_READ_WORD(0x10);
 
// ignore invalid data
if((uint16) plane == 0x8001) continue;
 
// first init
if(plane == 0x7fff)
{
int pos1,pos2;
 
// initialize projection
path_x[0] = x_left;
path_x[1] = x_right;
 
path_y[0] = y_left;
path_y[1] = y_right;
 
// update coordinates
path_pos[0]-=x_left;
path_pos[1]-=x_left;
path_pos[2]-=x_right;
path_pos[3]-=x_right;
 
pos1 = path_pos[0]+envelope1;
pos2 = path_pos[1]+envelope2;
 
// clip offscreen data
if(pos1<path_clipLeft[0]) pos1 = path_clipLeft[0];
if(pos1>path_clipRight[0]) pos1 = path_clipRight[0];
if(pos2<path_clipLeft[1]) pos2 = path_clipLeft[1];
if(pos2>path_clipRight[1]) pos2 = path_clipRight[1];
 
#if 0
pos1=-1;
//pos2=-1;
#endif
 
path_plane[0] = plane;
path_plane[1] = plane;
 
// initial output
DSP4.out_count = 2;
DSP4.output[0]=pos1&0xFF;
DSP4.output[1]=pos2&0xFF;
 
#ifdef PRINT
printf("(line %d) Op08 x_left %04X\n",c,(uint16)x_left);
#endif
}
// proceed with projection
else
{
int16 index=0, lcv;
int16 left_inc=0,right_inc=0;
int16 dx1,dx2,dx3,dx4;
 
// # segments to traverse
segments = abs(y_left - path_y[0]);
 
// prevent overdraw
if(y_left>=path_raster[0]) segments=0;
else path_raster[0]=y_left;
 
// don't draw outside the window
if(path_raster[0]<path_top[0]) segments=0;
 
// proceed if visibility rules apply
if(segments>0)
{
// use previous data
dx1 = (envelope1 * path_plane[0] / view_plane);
dx2 = (envelope2 * path_plane[0] / view_plane);
 
// use temporary envelope pitch (this frame only)
dx3 = (envelope1 * plane / view_plane);
dx4 = (envelope2 * plane / view_plane);
 
// project new shapes (left side)
x1_final = x_left+dx1;
x2_final = path_x[0]+dx3;
 
// interpolate between projected points with shaping
left_inc = ((x2_final-x1_final)<<8)/segments;
 
// project new shapes (right side)
x1_final = x_left+dx2;
x2_final = path_x[0]+dx4;
 
// interpolate between projected points with shaping
right_inc = ((x2_final-x1_final)<<8)/segments;
 
path_plane[0] = plane;
}
 
#ifdef PRINT
printf("(line %d) Op08 block %d, out %02X, raster %02X\n",c,block,segments,(uint16)y_left);
#endif
 
// zone 1
DSP4.out_count = (2+4*segments);
DSP4_WRITE_WORD(index,segments); index+=2;
 
for( lcv=1; lcv<=segments; lcv++ )
{
int16 pos1,pos2;
 
// pre-compute
pos1 = path_pos[0]+((left_inc*lcv)>>8)+dx1;
pos2 = path_pos[1]+((right_inc*lcv)>>8)+dx2;
 
// clip offscreen data
if(pos1<path_clipLeft[0]) pos1 = path_clipLeft[0];
if(pos1>path_clipRight[0]) pos1 = path_clipRight[0];
if(pos2<path_clipLeft[1]) pos2 = path_clipLeft[1];
if(pos2>path_clipRight[1]) pos2 = path_clipRight[1];
 
#if 0
if(pos1==0x00ff) pos1=0;
if(pos2==0x00ff) pos2=0;
path_ptr[0] = -1;
pos1 = -1;
pos2 = -1;
#endif
 
// data
DSP4_WRITE_WORD(index,path_ptr[0]); index+=2;
DSP4.output[index++]=pos1&0xFF;
DSP4.output[index++]=pos2&0xFF;
 
// post-update
path_ptr[0] -= 4;
path_ptr[1] -= 4;
}
lcv--;
 
if(segments>0)
{
// project points w/out the envelopes
int16 inc = ((path_x[0]-x_left)<<8)/segments;
 
// post-store
path_pos[0] += ((inc*lcv)>>8);
path_pos[1] += ((inc*lcv)>>8);
 
path_x[0] = x_left;
path_y[0] = y_left;
}
 
//////////////////////////////////////////////
// zone 2
segments = abs(y_right - path_y[1]);
 
// prevent overdraw
if(y_right>=path_raster[2]) segments=0;
else path_raster[2]=y_right;
 
// don't draw outside the window
if(path_raster[2]<path_top[2]) segments=0;
 
// proceed if visibility rules apply
if(segments>0)
{
// use previous data
dx1 = (envelope1 * path_plane[1] / view_plane);
dx2 = (envelope2 * path_plane[1] / view_plane);
 
// use temporary envelope pitch (this frame only)
dx3 = (envelope1 * plane / view_plane);
dx4 = (envelope2 * plane / view_plane);
 
// project new shapes (left side)
x1_final = x_left+dx1;
x2_final = path_x[1]+dx3;
 
// interpolate between projected points with shaping
left_inc = ((x2_final-x1_final)<<8)/segments;
 
// project new shapes (right side)
x1_final = x_left+dx2;
x2_final = path_x[1]+dx4;
 
// interpolate between projected points with shaping
right_inc = ((x2_final-x1_final)<<8)/segments;
 
path_plane[1] = plane;
}
 
// write out results
DSP4.out_count += (2+4*segments);
DSP4_WRITE_WORD(index,segments); index+=2;
 
for( lcv=1; lcv<=segments; lcv++ )
{
int16 pos1,pos2;
 
// pre-compute
pos1 = path_pos[2]+((left_inc*lcv)>>8)+dx1;
pos2 = path_pos[3]+((right_inc*lcv)>>8)+dx2;
 
// clip offscreen data
if(pos1<path_clipLeft[2]) pos1 = path_clipLeft[2];
if(pos1>path_clipRight[2]) pos1 = path_clipRight[2];
if(pos2<path_clipLeft[3]) pos2 = path_clipLeft[3];
if(pos2>path_clipRight[3]) pos2 = path_clipRight[3];
 
#if 0
if(pos1==0x00ff) pos1=0;
if(pos2==0x00ff) pos2=0;
path_ptr[2] = -1;
//pos1 = -1;
pos2 = -1;
#endif
 
// data
DSP4_WRITE_WORD(index,path_ptr[2]); index+=2;
DSP4.output[index++]=pos1&0xFF;
DSP4.output[index++]=pos2&0xFF;
 
// post-update
path_ptr[2] -= 4;
path_ptr[3] -= 4;
}
lcv--;
 
if(segments>0)
{
// project points w/out the envelopes
int16 inc = ((path_x[1]-x_right)<<8)/segments;
 
// post-store
path_pos[2] += ((inc*lcv)>>8);
path_pos[3] += ((inc*lcv)>>8);
 
path_x[1] = x_right;
path_y[1] = y_right;
}
}
} while(1);
 
DSP4.waiting4command = TRUE;
DSP4.out_count = 2;
DSP4_WRITE_WORD(0,0);
}
 
#undef PRINT
 
#if OP==0x000D
#define PRINT
#endif
 
void DSP4_Op0D()
{
uint16 command;
 
DSP4.waiting4command = FALSE;
 
// op flow control
switch(DSP4_Logic) {
case 1: goto resume1; break;
case 2: goto resume2; break;
}
 
////////////////////////////////////////////////////
// process initial inputs
 
// sort inputs
// 0x00 = DSP4_READ_WORD(0x00);
project_focaly = DSP4_READ_WORD(0x02);
raster = DSP4_READ_WORD(0x04);
viewport_top = DSP4_READ_WORD(0x06);
project_y = DSP4_READ_WORD(0x08);
viewport_bottom = DSP4_READ_WORD(0x0a);
project_x1low = DSP4_READ_WORD(0x0c);
project_x1 = DSP4_READ_WORD(0x0e);
project_focalx = DSP4_READ_WORD(0x0e);
project_centerx = DSP4_READ_WORD(0x10);
project_ptr = DSP4_READ_WORD(0x12);
// 0xc0 = DSP4_READ_WORD(0x14);
project_pitchylow = DSP4_READ_WORD(0x16);
project_pitchy = DSP4_READ_WORD(0x18);
project_pitchxlow = DSP4_READ_WORD(0x1a);
project_pitchx = DSP4_READ_WORD(0x1c);
far_plane = DSP4_READ_WORD(0x1e);
// ? = DSP4_READ_WORD(0x20);
 
// multi-op storage
multi_index1++;
multi_index1%=4;
 
// remap 0D->09 window data ahead of time
// index starts at 1-3,0
//
// Op0D: BL,TL,BR,TR
// Op09: TL,TR,BL,BR (1,2,3,0)
switch(multi_index1)
{
case 1: multi_index2=3; break;
case 2: multi_index2=1; break;
case 3: multi_index2=0; break;
case 0: multi_index2=2; break;
}
 
// pre-compute
view_plane = PLANE_START;
 
// figure out projection data
project_y -= viewport_bottom;
 
// debug
block=0;
 
////////////////////////////////////////////////////
// command check
 
do {
// scan next command
DSP4.in_count = 2;
 
DSP4_WAIT(1) resume1:
 
// inspect input
command = DSP4_READ_WORD(0);
 
// terminate op
if(command == 0x8000) break;
 
// already have 2 bytes in queue
DSP4.in_index = 2;
DSP4.in_count = 8;
 
DSP4_WAIT(2) resume2:
 
////////////////////////////////////////////////////
// project section of the track
 
// inspect inputs
int16 plane = DSP4_READ_WORD(0);
int16 index, lcv;
int16 py_dy=0, px_dx=0;
int16 y_out, x_out;
int16 envelope = DSP4_READ_WORD(6);
int16 project_x;
 
// ignore invalid data
if((uint16) plane == 0x8001) continue;
 
// one-time init
if(far_plane)
{
// setup final data
// low16=plane
project_x1 = project_focalx;
project_y1 = project_focaly;
plane = far_plane;
far_plane = 0;
 
// track occlusion
multi_farplane[multi_index2] = plane;
multi_raster[multi_index2] = viewport_bottom;
}
 
// use proportional triangles to project new coords
project_x2 = project_focalx * plane / view_plane;
project_y2 = project_focaly * plane / view_plane;
 
// quadratic regression (rough)
if(project_focaly>=-0x0f)
py_dy = project_focaly * project_focaly * -0.20533553
- 1.08330005 * project_focaly - 69.61094639;
else
py_dy = project_focaly * project_focaly * -0.000657035759
- 1.07629051 * project_focaly - 65.69315963;
 
// approximate # of raster lines
segments = abs(project_y2-project_y1);
 
// prevent overdraw
if(project_y2>=raster) segments=0;
else raster=project_y2;
 
// don't draw outside the window
if(project_y2<viewport_top) segments=0;
 
// project new positions
if(segments>0)
{
// interpolate between projected points
px_dx = ((project_x2-project_x1)<<8)/segments;
}
 
// debug
++block;
 
#ifdef PRINT
printf("(line %d) Op0D check %02X, plane %04X\n",c,(uint16)segments,(uint16)(plane));
#endif
 
// prepare output
DSP4.out_count=8+2+6*segments;
 
DSP4_WRITE_WORD(0,project_focalx);
DSP4_WRITE_WORD(2,project_x2);
DSP4_WRITE_WORD(4,project_focaly);
DSP4_WRITE_WORD(6,project_y2);
DSP4_WRITE_WORD(8,segments);
#if 0
DSP4_WRITE_WORD(0,-1);
DSP4_WRITE_WORD(2,-1);
DSP4_WRITE_WORD(4,-1);
//DSP4_WRITE_WORD(6,-1);
DSP4_WRITE_WORD(8,-1);
#endif
 
index=10;
 
project_x = project_centerx + project_x1;
 
// iterate through each point
for( lcv=0; lcv<segments; lcv++ )
{
// step through the projected line
y_out = project_y+((py_dy*lcv)>>8);
x_out = project_x+((px_dx*lcv)>>8);
 
// factor in dynamic track changes
y_out += envelope;
 
#if 0
project_ptr=-1;
y_out=-1;
x_out=-1;
#endif
 
// data
DSP4_WRITE_WORD(index+0,project_ptr);
DSP4_WRITE_WORD(index+2,y_out);
DSP4_WRITE_WORD(index+4,x_out);
index += 6;
 
// post-update
project_ptr -= 4;
}
 
// post-update
project_y += ((py_dy*lcv)>>8);
 
if(segments > 0)
{
project_x1 = project_x2;
project_y1 = project_y2;
 
// track occlusion: can't see anything below it
multi_farplane[multi_index2] = plane;
multi_raster[multi_index2] -= segments;
}
 
// update focal projection points
project_pitchy += (int8)DSP4.parameters[3];
project_pitchx += (int8)DSP4.parameters[5];
 
project_focaly += project_pitchy;
project_focalx += project_pitchx;
} while(1);
 
DSP4.waiting4command = TRUE;
DSP4.out_count = 0;
}
 
#undef PRINT
 
#if OP==0x0009
#define PRINT
#endif
 
#if OP==0x0006
#define PRINT
#endif
 
void DSP4_Op09()
{
uint16 command;
 
DSP4.waiting4command = FALSE;
 
// op flow control
switch(DSP4_Logic) {
case 1: goto resume1; break;
case 2: goto resume2; break;
case 3: goto resume3; break;
case 4: goto resume4; break;
case 5: goto resume5; break;
case 6: goto resume6; break;
case 7: goto resume7; break;
}
 
////////////////////////////////////////////////////
// process initial inputs
 
// debug
block=0;
 
// grab screen information
view_plane = PLANE_START;
center_x = DSP4_READ_WORD(0x00);
center_y = DSP4_READ_WORD(0x02);
// 0x00 = DSP4_READ_WORD(0x04);
viewport_left = DSP4_READ_WORD(0x06);
viewport_right = DSP4_READ_WORD(0x08);
viewport_top = DSP4_READ_WORD(0x0a);
viewport_bottom = DSP4_READ_WORD(0x0c);
 
#ifdef PRINT2
printf("Window: (%04X,%04X) (%04X,%04X)\n",
viewport_left,viewport_right,viewport_top,viewport_bottom);
#endif
 
// cycle through viewport window data
multi_index1++;
multi_index1%=4;
 
goto no_sprite;
 
do {
////////////////////////////////////////////////////
// check for new sprites
 
do {
uint16 second;
 
DSP4.in_count = 4;
DSP4.in_index = 2;
 
DSP4_WAIT(1) resume1:
 
// try to classify sprite
second = DSP4_READ_WORD(2);
 
// op termination
if(second == 0x8000) goto terminate;
 
second >>= 8;
sprite_type = 0;
 
// vehicle sprite
if(second == 0x90)
{
sprite_type = 1;
break;
}
// terrain sprite
else if(second != 0)
{
sprite_type = 2;
break;
}
 
no_sprite:
// no sprite. try again
 
DSP4.in_count = 2;
 
DSP4_WAIT(2) resume2:
;
} while (1);
 
////////////////////////////////////////////////////
// process projection information
 
sprite_found:
// vehicle sprite
if(sprite_type == 1)
{
int16 plane;
int16 car_left, car_right, car_left_a;
int16 focal_back, focal_front;
uint8 distance, id;
 
// we already have 4 bytes we want
DSP4.in_count = 6+12;
DSP4.in_index = 4;
 
DSP4_WAIT(3) resume3:
 
// filter inputs
project_y1 = DSP4_READ_WORD(0x00);
// 0x9000 = DSP4_READ_WORD(0x02);
id = DSP4.parameters[0x04];
distance = DSP4.parameters[0x05];
focal_back = DSP4_READ_WORD(0x06);
focal_front = DSP4_READ_WORD(0x08);
car_left_a = DSP4_READ_WORD(0x0a);
car_left = DSP4_READ_WORD(0x0c);
plane = DSP4_READ_WORD(0x0e);
car_right = DSP4_READ_WORD(0x10);
 
// calculate car's x-center
project_focalx = car_right-car_left;
 
// determine how far into the screen to project
project_focaly = focal_back;
project_x = project_focalx * plane / view_plane;
segments = 0x33 - project_focaly * plane / view_plane;
far_plane = plane;
 
// prepare memory
sprite_x = center_x+project_x;
sprite_y = viewport_bottom-segments;
far_plane = plane;
 
// debug
++block;
#ifdef PRINT
printf("(line %d) Op09 vehicle block %d, Loop %04X\n",c,block,(uint16)project_y1);
//printf("%04X %04X %04X %04X / ",focal_back,focal_front,car_left_a,car_left);
//printf("%02X %02X ", distance, id);
#endif
 
// make the car's x-center available
DSP4.out_count = 2;
DSP4_WRITE_WORD(0,project_focalx);
 
#if 0
DSP4_WRITE_WORD(0,-1);
#endif
 
// grab a few remaining vehicle values
DSP4.in_count = 4;
 
DSP4_WAIT(4) resume4:
 
// store final values
int height = DSP4_READ_WORD(0);
sprite_offset = DSP4_READ_WORD(2);
 
// vertical lift factor
sprite_y += height;
 
#ifdef PRINT_09
printf("%04X\n",sprite_offset);
#endif
}
// terrain sprite
else if(sprite_type == 2)
{
int16 plane;
 
// we already have 4 bytes we want
DSP4.in_count = 6+6+2;
DSP4.in_index = 4;
 
DSP4_WAIT(5) resume5:
 
// sort loop inputs
project_y1 = DSP4_READ_WORD(0x00);
plane = DSP4_READ_WORD(0x02);
project_centerx = DSP4_READ_WORD(0x04);
//project_y1 = DSP4_READ_WORD(0x06);
project_focalx = DSP4_READ_WORD(0x08);
project_focaly = DSP4_READ_WORD(0x0a);
sprite_offset = DSP4_READ_WORD(0x0c);
 
// determine distances into virtual world
segments = 0x33 - project_y1;
project_x = project_focalx * plane / view_plane;
project_y = project_focaly * plane / view_plane;
 
// prepare memory
sprite_x = center_x+project_x-project_centerx;
sprite_y = viewport_bottom-segments+project_y;
far_plane = plane;
 
// debug
++block;
#ifdef PRINT
printf("(line %d) Op09 terrain block %d, Loop %04X\n",c,block,(uint16)project_y1);
#endif
}
 
// default sprite size: 16x16
sprite_size = 1;
 
////////////////////////////////////////////////////
// convert tile data to OAM
 
do {
DSP4.in_count = 2;
 
DSP4_WAIT(6) resume6:
 
command = DSP4_READ_WORD(0);
 
// opcode termination
if(command == 0x8000) goto terminate;
 
// toggle sprite size
if(command == 0x0000)
{
sprite_size = !sprite_size;
#ifdef PRINT
//printf("TOGGLE=%02X\n",(uint8)sprite_size);
#endif
continue;
}
 
// new sprite information
command >>= 8;
if(command != 0x20 && command != 0x40 &&
command != 0x60 && command != 0xa0 &&
command != 0xc0 && command != 0xe0)
break;
 
DSP4.in_count = 6;
DSP4.in_index = 2;
 
DSP4_WAIT(7) resume7:
 
/////////////////////////////////////
// process tile data
 
bool8 clip;
int16 sp_x, sp_y, sp_oam, sp_msb;
int16 sp_dx, sp_dy;
int16 expand = sprite_size ? 15:7;
 
// sprite deltas
sp_dy = DSP4_READ_WORD(2);
sp_dx = DSP4_READ_WORD(4);
 
// update coordinates
sp_y = sprite_y + sp_dy;
sp_x = sprite_x + sp_dx;
 
// reject points outside the clipping window
clip = FALSE;
 
// window clipping
if(sp_x < viewport_left-expand || sp_x > viewport_right) clip=TRUE;
if(sp_y < viewport_top || sp_y > viewport_bottom) clip=TRUE;
 
// track occlusion:
// clip any tiles that are below the road
if(far_plane <= multi_farplane[multi_index1] &&
(sp_y>>3) >= (multi_raster[multi_index1]>>3)) clip=TRUE;
 
// tile limitations
if ((sp_y >= -expand) && ((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb)) && !clip)
{
short Row = (sp_y >> 3) & 0x1f;
 
if(!sprite_size)
{
// 1x1 tile
if (RowCount[Row] < MaxTilesPerRow)
RowCount[Row]++;
else
clip=TRUE;
}
else
{
// 2x2 tile
if ((RowCount[Row+0]+1 < MaxTilesPerRow) &&
(RowCount[Row+1]+1 < MaxTilesPerRow))
{
RowCount[Row+0]+=2;
RowCount[Row+1]+=2;
}
else
clip=TRUE;
}
}
 
#ifdef PRINT
printf("(line %d) %04X, %04X, %04X / %04X %04X\n",line,
(uint16)sp_x,(uint16)sp_y,(uint16)far_plane,(uint16)multi_farplane[multi_index1],(uint16)multi_raster[multi_index1]);
#endif
 
// don't draw offscreen coordinates
DSP4.out_count = 0;
if(!clip)
{
int16 out_index = 0;
int16 offset = DSP4_READ_WORD(0);
 
// update sprite nametable/attribute information
sp_oam = sprite_offset + offset;
sp_msb = (sp_x<0 || sp_x>255);
 
#ifdef PRINT2
printf("(line %d) %04X, %04X, %04X, %04X, %04X\n",line,
(uint16)sp_oam,(uint16)sprite_offset,(uint16)offset,
(uint16)sp_x,(uint16)sp_y);
#endif
 
// emit transparency information
if(
(sprite_offset&0x08) &&
((sprite_type==1 && sp_y>=0xcc) ||
(sprite_type==2 && sp_y>=0xbb))
)
{
DSP4.out_count = 6;
 
// one block of OAM data
DSP4_WRITE_WORD(0,1);
 
// OAM: x,y,tile,no attr
DSP4.output[2] = sp_x&0xFF;
DSP4.output[3] = (sp_y+6)&0xFF;
DSP4_WRITE_WORD(4,0xEE);
 
out_index = 6;
 
// OAM: size,msb data
DSP4_Op06(sprite_size,sp_msb);
 
#if 0
//DSP4_WRITE_WORD(0,-1);
DSP4_WRITE_WORD(2,-1);
DSP4_WRITE_WORD(4,-1);
#endif
}
 
// normal data
DSP4.out_count += 8;
 
// one block of OAM data
DSP4_WRITE_WORD(out_index+0,1);
 
// OAM: x,y,tile,attr
DSP4.output[out_index+2] = sp_x&0xFF;
DSP4.output[out_index+3] = sp_y&0xFF;
DSP4_WRITE_WORD(out_index+4,sp_oam);
 
// no following OAM data
DSP4_WRITE_WORD(out_index+6,0);
 
// OAM: size,msb data
DSP4_Op06(sprite_size,sp_msb);
 
#if 0
//DSP4_WRITE_WORD(out_index+0,-1);
DSP4_WRITE_WORD(out_index+2,-1);
DSP4_WRITE_WORD(out_index+4,-1);
#endif
}
 
// no sprite information
if(DSP4.out_count == 0)
{
DSP4.out_count = 2;
DSP4_WRITE_WORD(0,0);
}
} while (1);
 
/////////////////////////////////////
// special cases: plane == 0x0000
 
// special vehicle case
if(command == 0x90)
{
sprite_type = 1;
 
// shift bytes
DSP4.parameters[2] = DSP4.parameters[0];
DSP4.parameters[3] = DSP4.parameters[1];
DSP4.parameters[0] = 0;
DSP4.parameters[1] = 0;
 
goto sprite_found;
}
// special terrain case
else if(command != 0x00 && command != 0xff)
{
sprite_type = 2;
 
// shift bytes
DSP4.parameters[2] = DSP4.parameters[0];
DSP4.parameters[3] = DSP4.parameters[1];
DSP4.parameters[0] = 0;
DSP4.parameters[1] = 0;
 
goto sprite_found;
}
} while (1);
 
terminate:
DSP4.waiting4command = TRUE;
DSP4.out_count=0;
}
 
#undef PRINT
*******************************************************************************/
 
// Due recognition and credit are given on Overload's DSP website.
// Thank those contributors for their hard work on this chip.
 
#include "dsp4.h"
 
#define DSP4_READ_WORD(x) \
READ_WORD(DSP4.parameters+x)
 
#define DSP4_WRITE_WORD(x,d) \
WRITE_WORD(DSP4.output+x,d);
 
// used to wait for dsp i/o
#define DSP4_WAIT(x) \
DSP4_Logic = x; return;
 
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
 
void DSP4_Multiply(short Multiplicand, short Multiplier, int &Product)
{
Product = (Multiplicand * Multiplier << 1) >> 1;
}
 
void DSP4_UnknownOP11(short A, short B, short C, short D, short &M)
{
// 0x155 = 341 = Horizontal Width of the Screen
M = ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) |
((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f);
}
 
const unsigned short Op0A_Values[16] = {
0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150,
0xfe80, 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0
};
 
void DSP4_Op0A(short n2, short &o1, short &o2, short &o3, short &o4)
{
o4 = Op0A_Values[(n2 & 0x000f)];
o3 = Op0A_Values[(n2 & 0x00f0) >> 4];
o2 = Op0A_Values[(n2 & 0x0f00) >> 8];
o1 = Op0A_Values[(n2 & 0xf000) >> 12];
}
 
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
 
#if OP==0x0009
#define PRINT
#endif
 
void DSP4_Op03()
{
#ifdef PRINT
printf("Op03\n");
#endif
 
MaxTilesPerRow = 33;
 
for (int i=0; i < 32; i++)
RowCount[i] = 0;
 
// reset op09 data
op09_mode = 0;
}
 
void DSP4_Op0E()
{
#ifdef PRINT
printf("Op0E\n");
#endif
 
MaxTilesPerRow = 16;
 
for (int i=0; i < 32; i++)
RowCount[i] = 0;
 
// reset op09 data
op09_mode = 1;
}
 
#undef PRINT
 
void DSP4_Op06(bool8 size, bool8 msb)
{
// save post-oam table data for future retrieval
op06_OAM[op06_index] |= (msb<<(op06_offset+0));
op06_OAM[op06_index] |= (size<<(op06_offset+1));
op06_offset += 2;
 
if(op06_offset==8)
{
// move to next byte in buffer
op06_offset=0;
op06_index++;
}
}
 
#if OP==0x0001
#define PRINT
#endif
 
void DSP4_Op01()
{
uint16 command;
 
DSP4.waiting4command = FALSE;
 
// op flow control
switch(DSP4_Logic) {
case 1: goto resume1; break;
case 2: goto resume2; break;
}
 
////////////////////////////////////////////////////
// process initial inputs
 
// sort inputs
// 0x00 = DSP4_READ_WORD(0x00);
project_focaly = DSP4_READ_WORD(0x02);
raster = DSP4_READ_WORD(0x04);
viewport_top = DSP4_READ_WORD(0x06);
project_y = DSP4_READ_WORD(0x08);
viewport_bottom = DSP4_READ_WORD(0x0a);
project_x1low = DSP4_READ_WORD(0x0c);
project_focalx = DSP4_READ_WORD(0x0e);
project_centerx = DSP4_READ_WORD(0x10);
project_ptr = DSP4_READ_WORD(0x12);
// (envelope?) 0xc0 = DSP4_READ_WORD(0x14);
project_pitchylow = DSP4_READ_WORD(0x16);
project_pitchy = DSP4_READ_WORD(0x18);
project_pitchxlow = DSP4_READ_WORD(0x1a);
project_pitchx = DSP4_READ_WORD(0x1c);
far_plane = DSP4_READ_WORD(0x1e);
// ? = DSP4_READ_WORD(0x20);
project_y1low = DSP4_READ_WORD(0x22);
 
// pre-compute
view_plane = PLANE_START;
 
// find starting projection points
project_x1 = project_focalx;
project_y -= viewport_bottom;
 
// multi-op storage
multi_index1 = 0;
multi_index2 = 0;
 
// debug
block=0;
 
////////////////////////////////////////////////////
// command check
 
do {
// scan next command
DSP4.in_count = 2;
 
DSP4_WAIT(1) resume1:
 
// inspect input
command = DSP4_READ_WORD(0);
 
// check for termination
if(command == 0x8000) break;
 
// already have 2 bytes in queue
DSP4.in_index = 2;
DSP4.in_count = 8;
 
DSP4_WAIT(2) resume2:
 
////////////////////////////////////////////////////
// process one iteration of projection
 
// inspect inputs
int16 plane = DSP4_READ_WORD(0);
int16 index, lcv;
int16 py_dy=0, px_dx=0;
int16 y_out, x_out;
int16 envelope = DSP4_READ_WORD(6);
int16 project_x;
 
// ignore invalid data
if((uint16) plane == 0x8001) continue;
 
// one-time init
if(far_plane)
{
// setup final parameters
project_focalx += plane;
project_x1 = project_focalx;
project_y1 = project_focaly;
plane = far_plane;
far_plane = 0;
 
// track occlusion
multi_farplane[1] = plane;
multi_raster[1] = viewport_bottom;
}
 
// use proportional triangles to project new coords
project_x2 = project_focalx * plane / view_plane;
project_y2 = project_focaly * plane / view_plane;
 
// quadratic regression (rough)
if(project_focaly>=-0x0f)
py_dy = project_focaly * project_focaly * -0.20533553
- 1.08330005 * project_focaly - 69.61094639;
else
py_dy = project_focaly * project_focaly * -0.000657035759
- 1.07629051 * project_focaly - 65.69315963;
 
// approximate # of raster lines
segments = abs(project_y2-project_y1);
 
// prevent overdraw
if(project_y2>=raster) segments=0;
else raster=project_y2;
 
// don't draw outside the window
if(project_y2<viewport_top) segments=0;
 
// project new positions
if(segments>0)
{
// interpolate between projected points
px_dx = ((project_x2-project_x1)<<8)/segments;
}
 
// debug
++block;
#ifdef PRINT
printf("(line %d) Op01 check %02X, plane %04X, focal_y %04X, y2 %04X, y1 %04X\n",c,(uint16)segments,(uint16)(plane),(uint16)project_focaly,(uint16)project_y2,(uint16)project_y1);
#endif
 
// prepare output
DSP4.out_count=8+2+6*segments;
 
// pre-block data
DSP4_WRITE_WORD(0,project_focalx);
DSP4_WRITE_WORD(2,project_x2);
DSP4_WRITE_WORD(4,project_focaly);
DSP4_WRITE_WORD(6,project_y2);
DSP4_WRITE_WORD(8,segments);
 
#if 0
DSP4_WRITE_WORD(0,-1);
DSP4_WRITE_WORD(2,-1);
DSP4_WRITE_WORD(4,-1);
DSP4_WRITE_WORD(6,-1);
DSP4_WRITE_WORD(8,-1);
#endif
 
index=10;
 
project_x = project_centerx + project_x1;
 
// iterate through each point
for( lcv=0; lcv<segments; lcv++ )
{
// step through the projected line
y_out = project_y+((py_dy*lcv)>>8);
x_out = project_x+((px_dx*lcv)>>8);
 
// factor in dynamic track changes
y_out += envelope;
 
#if 0
project_ptr=-1;
y_out=-1;
//x_out=-1;
#endif
 
// data
DSP4_WRITE_WORD(index+0,project_ptr);
DSP4_WRITE_WORD(index+2,y_out);
DSP4_WRITE_WORD(index+4,x_out);
index += 6;
 
// post-update
project_ptr -= 4;
}
 
// post-update
project_y += ((py_dy*lcv)>>8);
 
// new positions
if(segments>0)
{
project_x1 = project_x2;
project_y1 = project_y2;
 
// storage of focals for op07
multi_focaly[multi_index2++] = project_focaly;
 
// track occlusion: can't see anything below it
multi_farplane[1] = plane;
multi_raster[1] -= segments;
}
 
// update projection points
project_pitchy += (int8)DSP4.parameters[3];
project_pitchx += (int8)DSP4.parameters[5];
 
project_focaly += project_pitchy;
project_focalx += project_pitchx;
} while (1);
 
// terminate op
DSP4.waiting4command = TRUE;
DSP4.out_count = 0;
}
 
#undef PRINT
 
#if OP==0x0007
#define PRINT
#endif
 
void DSP4_Op07()
{
uint16 command;
 
DSP4.waiting4command = FALSE;
 
// op flow control
switch(DSP4_Logic) {
case 1: goto resume1; break;
case 2: goto resume2; break;
}
 
////////////////////////////////////////////////////
// sort inputs
 
// 0x00 = DSP4_READ_WORD(0x00);
project_focaly = DSP4_READ_WORD(0x02);
raster = DSP4_READ_WORD(0x04);
viewport_top = DSP4_READ_WORD(0x06);
project_y = DSP4_READ_WORD(0x08);
viewport_bottom = DSP4_READ_WORD(0x0a);
project_x1low = DSP4_READ_WORD(0x0c);
project_x1 = DSP4_READ_WORD(0x0e);
project_centerx = DSP4_READ_WORD(0x10);
project_ptr = DSP4_READ_WORD(0x12);
// (envelope?) 0xc0 = DSP4_READ_WORD(0x14);
 
// pre-compute
view_plane = PLANE_START;
 
// find projection targets
project_y1 = project_focaly;
project_y -= viewport_bottom;
 
// multi-op storage
multi_index2 = 0;
 
// debug
block=0;
 
#ifdef PRINT
printf("(line %d) Op07 data %04X\n",c,(uint16)project_y1);
#endif
 
////////////////////////////////////////////////////
// command check
 
do {
// scan next command
DSP4.in_count = 2;
 
DSP4_WAIT(1) resume1:
 
// inspect input
command = DSP4_READ_WORD(0);
 
// check for opcode termination
if(command == 0x8000) break;
 
// already have 2 bytes in queue
DSP4.in_index = 2;
DSP4.in_count = 12;
 
DSP4_WAIT(2) resume2:
 
////////////////////////////////////////////////////
// process one loop of projection
 
int16 plane;
int16 index,lcv;
int16 y_out,x_out;
int16 py_dy=0,px_dx=0;
int16 project_x;
 
// debug
++block;
 
// inspect inputs
plane = DSP4_READ_WORD(0);
project_y2 = DSP4_READ_WORD(2);
// ? = DSP4_READ_WORD(4);
project_x2 = DSP4_READ_WORD(6);
int16 envelope = DSP4_READ_WORD(8);
 
// ignore invalid data
if((uint16) plane == 0x8001) continue;
 
// multi-op storage
project_focaly = multi_focaly[multi_index2];
 
// quadratic regression (rough)
if(project_focaly>=-0x0f)
py_dy = project_focaly * project_focaly * -0.20533553
- 1.08330005 * project_focaly - 69.61094639;
else
py_dy = project_focaly * project_focaly * -0.000657035759
- 1.07629051 * project_focaly - 65.69315963;
 
// approximate # of raster lines
segments = abs(project_y2-project_y1);
 
// prevent overdraw
if(project_y2>=raster) segments=0;
else raster=project_y2;
 
// don't draw outside the window
if(project_y2<viewport_top) segments=0;
 
// project new positions
if(segments>0)
{
// interpolate between projected points
px_dx = ((project_x2-project_x1)<<8)/segments;
}
 
#ifdef PRINT
printf("(line %d) Op07 block %d, loc %04X, out %02X, project_x2 %04X\n",c,block,plane,segments,(uint16)project_x2);
#endif
 
// prepare pre-output
DSP4.out_count=4+2+6*segments;
 
DSP4_WRITE_WORD(0,project_x2);
DSP4_WRITE_WORD(2,project_y2);
DSP4_WRITE_WORD(4,segments);
 
#if 0
DSP4_WRITE_WORD(0,-1);
DSP4_WRITE_WORD(2,-1);
DSP4_WRITE_WORD(4,-1);
#endif
 
index=6;
 
project_x = project_centerx + project_x1;
 
for( lcv=0; lcv<segments; lcv++ )
{
// pre-compute
y_out = project_y+((py_dy*lcv)>>8);
x_out = project_x+((px_dx*lcv)>>8);
 
// factor in dynamic track changes
y_out += envelope;
 
#if 0
project_ptr = -1;
//y_out = -1;
x_out = -1;
#endif
 
// data
DSP4_WRITE_WORD(index+0,project_ptr);
DSP4_WRITE_WORD(index+2,y_out);
DSP4_WRITE_WORD(index+4,x_out);
index += 6;
 
// post-update
project_ptr -= 4;
}
 
// update internal variables
project_y += ((py_dy*lcv)>>8);
 
// new positions
if(segments>0)
{
project_x1 = project_x2;
project_y1 = project_y2;
 
// multi-op storage
multi_index2++;
}
} while(1);
 
DSP4.waiting4command = TRUE;
DSP4.out_count = 0;
}
 
#undef PRINT
 
#if OP==0x0008
#define PRINT
#endif
 
void DSP4_Op08()
{
uint16 command;
 
DSP4.waiting4command = FALSE;
 
// op flow control
switch(DSP4_Logic) {
case 1: goto resume1; break;
case 2: goto resume2; break;
}
 
////////////////////////////////////////////////////
// process initial inputs
 
// clip values
path_clipRight[0] = DSP4_READ_WORD(0x00);
path_clipRight[1] = DSP4_READ_WORD(0x02);
path_clipRight[2] = DSP4_READ_WORD(0x04);
path_clipRight[3] = DSP4_READ_WORD(0x06);
 
path_clipLeft[0] = DSP4_READ_WORD(0x08);
path_clipLeft[1] = DSP4_READ_WORD(0x0a);
path_clipLeft[2] = DSP4_READ_WORD(0x0c);
path_clipLeft[3] = DSP4_READ_WORD(0x0e);
 
// unknown (constant)
// unknown (constant)
 
// path positions
path_pos[0] = DSP4_READ_WORD(0x20);
path_pos[1] = DSP4_READ_WORD(0x22);
path_pos[2] = DSP4_READ_WORD(0x24);
path_pos[3] = DSP4_READ_WORD(0x26);
 
// data locations
path_ptr[0] = DSP4_READ_WORD(0x28);
path_ptr[1] = DSP4_READ_WORD(0x2a);
path_ptr[2] = DSP4_READ_WORD(0x2c);
path_ptr[3] = DSP4_READ_WORD(0x2e);
 
// project_y1 lines
path_raster[0] = DSP4_READ_WORD(0x30);
path_raster[1] = DSP4_READ_WORD(0x32);
path_raster[2] = DSP4_READ_WORD(0x34);
path_raster[3] = DSP4_READ_WORD(0x36);
 
// viewport_top
path_top[0] = DSP4_READ_WORD(0x38);
path_top[1] = DSP4_READ_WORD(0x3a);
path_top[2] = DSP4_READ_WORD(0x3c);
path_top[3] = DSP4_READ_WORD(0x3e);
 
// unknown (constants)
 
view_plane = PLANE_START;
 
// debug
block=0;
 
////////////////////////////////////////////////////
// command check
 
do {
// scan next command
DSP4.in_count = 2;
 
DSP4_WAIT(1) resume1:
 
// inspect input
command = DSP4_READ_WORD(0);
 
// terminate op
if(command == 0x8000) break;
 
// already have 2 bytes in queue
DSP4.in_index = 2;
DSP4.in_count = 18;
 
DSP4_WAIT(2) resume2:
 
////////////////////////////////////////////////////
// projection begins
 
// debug
++block;
 
// used in envelope shaping
int16 x1_final;
int16 x2_final;
 
// look at guidelines
int16 plane = DSP4_READ_WORD(0x00);
int16 x_left = DSP4_READ_WORD(0x02);
int16 y_left = DSP4_READ_WORD(0x04);
int16 x_right = DSP4_READ_WORD(0x06);
int16 y_right = DSP4_READ_WORD(0x08);
 
// envelope guidelines (one frame only)
int16 envelope1 = DSP4_READ_WORD(0x0a);
int16 envelope2 = DSP4_READ_WORD(0x0c);
int16 envelope3 = DSP4_READ_WORD(0x0e);
int16 envelope4 = DSP4_READ_WORD(0x10);
 
// ignore invalid data
if((uint16) plane == 0x8001) continue;
 
// first init
if(plane == 0x7fff)
{
int pos1,pos2;
 
// initialize projection
path_x[0] = x_left;
path_x[1] = x_right;
 
path_y[0] = y_left;
path_y[1] = y_right;
 
// update coordinates
path_pos[0]-=x_left;
path_pos[1]-=x_left;
path_pos[2]-=x_right;
path_pos[3]-=x_right;
 
pos1 = path_pos[0]+envelope1;
pos2 = path_pos[1]+envelope2;
 
// clip offscreen data
if(pos1<path_clipLeft[0]) pos1 = path_clipLeft[0];
if(pos1>path_clipRight[0]) pos1 = path_clipRight[0];
if(pos2<path_clipLeft[1]) pos2 = path_clipLeft[1];
if(pos2>path_clipRight[1]) pos2 = path_clipRight[1];
 
#if 0
pos1=-1;
//pos2=-1;
#endif
 
path_plane[0] = plane;
path_plane[1] = plane;
 
// initial output
DSP4.out_count = 2;
DSP4.output[0]=pos1&0xFF;
DSP4.output[1]=pos2&0xFF;
 
#ifdef PRINT
printf("(line %d) Op08 x_left %04X\n",c,(uint16)x_left);
#endif
}
// proceed with projection
else
{
int16 index=0, lcv;
int16 left_inc=0,right_inc=0;
int16 dx1,dx2,dx3,dx4;
 
// # segments to traverse
segments = abs(y_left - path_y[0]);
 
// prevent overdraw
if(y_left>=path_raster[0]) segments=0;
else path_raster[0]=y_left;
 
// don't draw outside the window
if(path_raster[0]<path_top[0]) segments=0;
 
// proceed if visibility rules apply
if(segments>0)
{
// use previous data
dx1 = (envelope1 * path_plane[0] / view_plane);
dx2 = (envelope2 * path_plane[0] / view_plane);
 
// use temporary envelope pitch (this frame only)
dx3 = (envelope1 * plane / view_plane);
dx4 = (envelope2 * plane / view_plane);
 
// project new shapes (left side)
x1_final = x_left+dx1;
x2_final = path_x[0]+dx3;
 
// interpolate between projected points with shaping
left_inc = ((x2_final-x1_final)<<8)/segments;
 
// project new shapes (right side)
x1_final = x_left+dx2;
x2_final = path_x[0]+dx4;
 
// interpolate between projected points with shaping
right_inc = ((x2_final-x1_final)<<8)/segments;
 
path_plane[0] = plane;
}
 
#ifdef PRINT
printf("(line %d) Op08 block %d, out %02X, raster %02X\n",c,block,segments,(uint16)y_left);
#endif
 
// zone 1
DSP4.out_count = (2+4*segments);
DSP4_WRITE_WORD(index,segments); index+=2;
 
for( lcv=1; lcv<=segments; lcv++ )
{
int16 pos1,pos2;
 
// pre-compute
pos1 = path_pos[0]+((left_inc*lcv)>>8)+dx1;
pos2 = path_pos[1]+((right_inc*lcv)>>8)+dx2;
 
// clip offscreen data
if(pos1<path_clipLeft[0]) pos1 = path_clipLeft[0];
if(pos1>path_clipRight[0]) pos1 = path_clipRight[0];
if(pos2<path_clipLeft[1]) pos2 = path_clipLeft[1];
if(pos2>path_clipRight[1]) pos2 = path_clipRight[1];
 
#if 0
if(pos1==0x00ff) pos1=0;
if(pos2==0x00ff) pos2=0;
path_ptr[0] = -1;
pos1 = -1;
pos2 = -1;
#endif
 
// data
DSP4_WRITE_WORD(index,path_ptr[0]); index+=2;
DSP4.output[index++]=pos1&0xFF;
DSP4.output[index++]=pos2&0xFF;
 
// post-update
path_ptr[0] -= 4;
path_ptr[1] -= 4;
}
lcv--;
 
if(segments>0)
{
// project points w/out the envelopes
int16 inc = ((path_x[0]-x_left)<<8)/segments;
 
// post-store
path_pos[0] += ((inc*lcv)>>8);
path_pos[1] += ((inc*lcv)>>8);
 
path_x[0] = x_left;
path_y[0] = y_left;
}
 
//////////////////////////////////////////////
// zone 2
segments = abs(y_right - path_y[1]);
 
// prevent overdraw
if(y_right>=path_raster[2]) segments=0;
else path_raster[2]=y_right;
 
// don't draw outside the window
if(path_raster[2]<path_top[2]) segments=0;
 
// proceed if visibility rules apply
if(segments>0)
{
// use previous data
dx1 = (envelope1 * path_plane[1] / view_plane);
dx2 = (envelope2 * path_plane[1] / view_plane);
 
// use temporary envelope pitch (this frame only)
dx3 = (envelope1 * plane / view_plane);
dx4 = (envelope2 * plane / view_plane);
 
// project new shapes (left side)
x1_final = x_left+dx1;
x2_final = path_x[1]+dx3;
 
// interpolate between projected points with shaping
left_inc = ((x2_final-x1_final)<<8)/segments;
 
// project new shapes (right side)
x1_final = x_left+dx2;
x2_final = path_x[1]+dx4;
 
// interpolate between projected points with shaping
right_inc = ((x2_final-x1_final)<<8)/segments;
 
path_plane[1] = plane;
}
 
// write out results
DSP4.out_count += (2+4*segments);
DSP4_WRITE_WORD(index,segments); index+=2;
 
for( lcv=1; lcv<=segments; lcv++ )
{
int16 pos1,pos2;
 
// pre-compute
pos1 = path_pos[2]+((left_inc*lcv)>>8)+dx1;
pos2 = path_pos[3]+((right_inc*lcv)>>8)+dx2;
 
// clip offscreen data
if(pos1<path_clipLeft[2]) pos1 = path_clipLeft[2];
if(pos1>path_clipRight[2]) pos1 = path_clipRight[2];
if(pos2<path_clipLeft[3]) pos2 = path_clipLeft[3];
if(pos2>path_clipRight[3]) pos2 = path_clipRight[3];
 
#if 0
if(pos1==0x00ff) pos1=0;
if(pos2==0x00ff) pos2=0;
path_ptr[2] = -1;
//pos1 = -1;
pos2 = -1;
#endif
 
// data
DSP4_WRITE_WORD(index,path_ptr[2]); index+=2;
DSP4.output[index++]=pos1&0xFF;
DSP4.output[index++]=pos2&0xFF;
 
// post-update
path_ptr[2] -= 4;
path_ptr[3] -= 4;
}
lcv--;
 
if(segments>0)
{
// project points w/out the envelopes
int16 inc = ((path_x[1]-x_right)<<8)/segments;
 
// post-store
path_pos[2] += ((inc*lcv)>>8);
path_pos[3] += ((inc*lcv)>>8);
 
path_x[1] = x_right;
path_y[1] = y_right;
}
}
} while(1);
 
DSP4.waiting4command = TRUE;
DSP4.out_count = 2;
DSP4_WRITE_WORD(0,0);
}
 
#undef PRINT
 
#if OP==0x000D
#define PRINT
#endif
 
void DSP4_Op0D()
{
uint16 command;
 
DSP4.waiting4command = FALSE;
 
// op flow control
switch(DSP4_Logic) {
case 1: goto resume1; break;
case 2: goto resume2; break;
}
 
////////////////////////////////////////////////////
// process initial inputs
 
// sort inputs
// 0x00 = DSP4_READ_WORD(0x00);
project_focaly = DSP4_READ_WORD(0x02);
raster = DSP4_READ_WORD(0x04);
viewport_top = DSP4_READ_WORD(0x06);
project_y = DSP4_READ_WORD(0x08);
viewport_bottom = DSP4_READ_WORD(0x0a);
project_x1low = DSP4_READ_WORD(0x0c);
project_x1 = DSP4_READ_WORD(0x0e);
project_focalx = DSP4_READ_WORD(0x0e);
project_centerx = DSP4_READ_WORD(0x10);
project_ptr = DSP4_READ_WORD(0x12);
// 0xc0 = DSP4_READ_WORD(0x14);
project_pitchylow = DSP4_READ_WORD(0x16);
project_pitchy = DSP4_READ_WORD(0x18);
project_pitchxlow = DSP4_READ_WORD(0x1a);
project_pitchx = DSP4_READ_WORD(0x1c);
far_plane = DSP4_READ_WORD(0x1e);
// ? = DSP4_READ_WORD(0x20);
 
// multi-op storage
multi_index1++;
multi_index1%=4;
 
// remap 0D->09 window data ahead of time
// index starts at 1-3,0
//
// Op0D: BL,TL,BR,TR
// Op09: TL,TR,BL,BR (1,2,3,0)
switch(multi_index1)
{
case 1: multi_index2=3; break;
case 2: multi_index2=1; break;
case 3: multi_index2=0; break;
case 0: multi_index2=2; break;
}
 
// pre-compute
view_plane = PLANE_START;
 
// figure out projection data
project_y -= viewport_bottom;
 
// debug
block=0;
 
////////////////////////////////////////////////////
// command check
 
do {
// scan next command
DSP4.in_count = 2;
 
DSP4_WAIT(1) resume1:
 
// inspect input
command = DSP4_READ_WORD(0);
 
// terminate op
if(command == 0x8000) break;
 
// already have 2 bytes in queue
DSP4.in_index = 2;
DSP4.in_count = 8;
 
DSP4_WAIT(2) resume2:
 
////////////////////////////////////////////////////
// project section of the track
 
// inspect inputs
int16 plane = DSP4_READ_WORD(0);
int16 index, lcv;
int16 py_dy=0, px_dx=0;
int16 y_out, x_out;
int16 envelope = DSP4_READ_WORD(6);
int16 project_x;
 
// ignore invalid data
if((uint16) plane == 0x8001) continue;
 
// one-time init
if(far_plane)
{
// setup final data
// low16=plane
project_x1 = project_focalx;
project_y1 = project_focaly;
plane = far_plane;
far_plane = 0;
 
// track occlusion
multi_farplane[multi_index2] = plane;
multi_raster[multi_index2] = viewport_bottom;
}
 
// use proportional triangles to project new coords
project_x2 = project_focalx * plane / view_plane;
project_y2 = project_focaly * plane / view_plane;
 
// quadratic regression (rough)
if(project_focaly>=-0x0f)
py_dy = project_focaly * project_focaly * -0.20533553
- 1.08330005 * project_focaly - 69.61094639;
else
py_dy = project_focaly * project_focaly * -0.000657035759
- 1.07629051 * project_focaly - 65.69315963;
 
// approximate # of raster lines
segments = abs(project_y2-project_y1);
 
// prevent overdraw
if(project_y2>=raster) segments=0;
else raster=project_y2;
 
// don't draw outside the window
if(project_y2<viewport_top) segments=0;
 
// project new positions
if(segments>0)
{
// interpolate between projected points
px_dx = ((project_x2-project_x1)<<8)/segments;
}
 
// debug
++block;
 
#ifdef PRINT
printf("(line %d) Op0D check %02X, plane %04X\n",c,(uint16)segments,(uint16)(plane));
#endif
 
// prepare output
DSP4.out_count=8+2+6*segments;
 
DSP4_WRITE_WORD(0,project_focalx);
DSP4_WRITE_WORD(2,project_x2);
DSP4_WRITE_WORD(4,project_focaly);
DSP4_WRITE_WORD(6,project_y2);
DSP4_WRITE_WORD(8,segments);
#if 0
DSP4_WRITE_WORD(0,-1);
DSP4_WRITE_WORD(2,-1);
DSP4_WRITE_WORD(4,-1);
//DSP4_WRITE_WORD(6,-1);
DSP4_WRITE_WORD(8,-1);
#endif
 
index=10;
 
project_x = project_centerx + project_x1;
 
// iterate through each point
for( lcv=0; lcv<segments; lcv++ )
{
// step through the projected line
y_out = project_y+((py_dy*lcv)>>8);
x_out = project_x+((px_dx*lcv)>>8);
 
// factor in dynamic track changes
y_out += envelope;
 
#if 0
project_ptr=-1;
y_out=-1;
x_out=-1;
#endif
 
// data
DSP4_WRITE_WORD(index+0,project_ptr);
DSP4_WRITE_WORD(index+2,y_out);
DSP4_WRITE_WORD(index+4,x_out);
index += 6;
 
// post-update
project_ptr -= 4;
}
 
// post-update
project_y += ((py_dy*lcv)>>8);
 
if(segments > 0)
{
project_x1 = project_x2;
project_y1 = project_y2;
 
// track occlusion: can't see anything below it
multi_farplane[multi_index2] = plane;
multi_raster[multi_index2] -= segments;
}
 
// update focal projection points
project_pitchy += (int8)DSP4.parameters[3];
project_pitchx += (int8)DSP4.parameters[5];
 
project_focaly += project_pitchy;
project_focalx += project_pitchx;
} while(1);
 
DSP4.waiting4command = TRUE;
DSP4.out_count = 0;
}
 
#undef PRINT
 
#if OP==0x0009
#define PRINT
#endif
 
#if OP==0x0006
#define PRINT
#endif
 
void DSP4_Op09()
{
uint16 command;
 
DSP4.waiting4command = FALSE;
 
// op flow control
switch(DSP4_Logic) {
case 1: goto resume1; break;
case 2: goto resume2; break;
case 3: goto resume3; break;
case 4: goto resume4; break;
case 5: goto resume5; break;
case 6: goto resume6; break;
case 7: goto resume7; break;
}
 
////////////////////////////////////////////////////
// process initial inputs
 
// debug
block=0;
 
// grab screen information
view_plane = PLANE_START;
center_x = DSP4_READ_WORD(0x00);
center_y = DSP4_READ_WORD(0x02);
// 0x00 = DSP4_READ_WORD(0x04);
viewport_left = DSP4_READ_WORD(0x06);
viewport_right = DSP4_READ_WORD(0x08);
viewport_top = DSP4_READ_WORD(0x0a);
viewport_bottom = DSP4_READ_WORD(0x0c);
 
#ifdef PRINT2
printf("Window: (%04X,%04X) (%04X,%04X)\n",
viewport_left,viewport_right,viewport_top,viewport_bottom);
#endif
 
// cycle through viewport window data
multi_index1++;
multi_index1%=4;
 
goto no_sprite;
 
do {
////////////////////////////////////////////////////
// check for new sprites
 
do {
uint16 second;
 
DSP4.in_count = 4;
DSP4.in_index = 2;
 
DSP4_WAIT(1) resume1:
 
// try to classify sprite
second = DSP4_READ_WORD(2);
 
// op termination
if(second == 0x8000) goto terminate;
 
second >>= 8;
sprite_type = 0;
 
// vehicle sprite
if(second == 0x90)
{
sprite_type = 1;
break;
}
// terrain sprite
else if(second != 0)
{
sprite_type = 2;
break;
}
 
no_sprite:
// no sprite. try again
 
DSP4.in_count = 2;
 
DSP4_WAIT(2) resume2:
;
} while (1);
 
////////////////////////////////////////////////////
// process projection information
 
sprite_found:
// vehicle sprite
if(sprite_type == 1)
{
int16 plane;
int16 car_left, car_right, car_left_a;
int16 focal_back, focal_front;
uint8 distance, id;
 
// we already have 4 bytes we want
DSP4.in_count = 6+12;
DSP4.in_index = 4;
 
DSP4_WAIT(3) resume3:
 
// filter inputs
project_y1 = DSP4_READ_WORD(0x00);
// 0x9000 = DSP4_READ_WORD(0x02);
id = DSP4.parameters[0x04];
distance = DSP4.parameters[0x05];
focal_back = DSP4_READ_WORD(0x06);
focal_front = DSP4_READ_WORD(0x08);
car_left_a = DSP4_READ_WORD(0x0a);
car_left = DSP4_READ_WORD(0x0c);
plane = DSP4_READ_WORD(0x0e);
car_right = DSP4_READ_WORD(0x10);
 
// calculate car's x-center
project_focalx = car_right-car_left;
 
// determine how far into the screen to project
project_focaly = focal_back;
project_x = project_focalx * plane / view_plane;
segments = 0x33 - project_focaly * plane / view_plane;
far_plane = plane;
 
// prepare memory
sprite_x = center_x+project_x;
sprite_y = viewport_bottom-segments;
far_plane = plane;
 
// debug
++block;
#ifdef PRINT
printf("(line %d) Op09 vehicle block %d, Loop %04X\n",c,block,(uint16)project_y1);
//printf("%04X %04X %04X %04X / ",focal_back,focal_front,car_left_a,car_left);
//printf("%02X %02X ", distance, id);
#endif
 
// make the car's x-center available
DSP4.out_count = 2;
DSP4_WRITE_WORD(0,project_focalx);
 
#if 0
DSP4_WRITE_WORD(0,-1);
#endif
 
// grab a few remaining vehicle values
DSP4.in_count = 4;
 
DSP4_WAIT(4) resume4:
 
// store final values
int height = DSP4_READ_WORD(0);
sprite_offset = DSP4_READ_WORD(2);
 
// vertical lift factor
sprite_y += height;
 
#ifdef PRINT_09
printf("%04X\n",sprite_offset);
#endif
}
// terrain sprite
else if(sprite_type == 2)
{
int16 plane;
 
// we already have 4 bytes we want
DSP4.in_count = 6+6+2;
DSP4.in_index = 4;
 
DSP4_WAIT(5) resume5:
 
// sort loop inputs
project_y1 = DSP4_READ_WORD(0x00);
plane = DSP4_READ_WORD(0x02);
project_centerx = DSP4_READ_WORD(0x04);
//project_y1 = DSP4_READ_WORD(0x06);
project_focalx = DSP4_READ_WORD(0x08);
project_focaly = DSP4_READ_WORD(0x0a);
sprite_offset = DSP4_READ_WORD(0x0c);
 
// determine distances into virtual world
segments = 0x33 - project_y1;
project_x = project_focalx * plane / view_plane;
project_y = project_focaly * plane / view_plane;
 
// prepare memory
sprite_x = center_x+project_x-project_centerx;
sprite_y = viewport_bottom-segments+project_y;
far_plane = plane;
 
// debug
++block;
#ifdef PRINT
printf("(line %d) Op09 terrain block %d, Loop %04X\n",c,block,(uint16)project_y1);
#endif
}
 
// default sprite size: 16x16
sprite_size = 1;
 
////////////////////////////////////////////////////
// convert tile data to OAM
 
do {
DSP4.in_count = 2;
 
DSP4_WAIT(6) resume6:
 
command = DSP4_READ_WORD(0);
 
// opcode termination
if(command == 0x8000) goto terminate;
 
// toggle sprite size
if(command == 0x0000)
{
sprite_size = !sprite_size;
#ifdef PRINT
//printf("TOGGLE=%02X\n",(uint8)sprite_size);
#endif
continue;
}
 
// new sprite information
command >>= 8;
if(command != 0x20 && command != 0x40 &&
command != 0x60 && command != 0xa0 &&
command != 0xc0 && command != 0xe0)
break;
 
DSP4.in_count = 6;
DSP4.in_index = 2;
 
DSP4_WAIT(7) resume7:
 
/////////////////////////////////////
// process tile data
 
bool8 clip;
int16 sp_x, sp_y, sp_oam, sp_msb;
int16 sp_dx, sp_dy;
int16 expand = sprite_size ? 15:7;
 
// sprite deltas
sp_dy = DSP4_READ_WORD(2);
sp_dx = DSP4_READ_WORD(4);
 
// update coordinates
sp_y = sprite_y + sp_dy;
sp_x = sprite_x + sp_dx;
 
// reject points outside the clipping window
clip = FALSE;
 
// window clipping
if(sp_x < viewport_left-expand || sp_x > viewport_right) clip=TRUE;
if(sp_y < viewport_top || sp_y > viewport_bottom) clip=TRUE;
 
// track occlusion:
// clip any tiles that are below the road
if(far_plane <= multi_farplane[multi_index1] &&
(sp_y>>3) >= (multi_raster[multi_index1]>>3)) clip=TRUE;
 
// tile limitations
if ((sp_y >= -expand) && ((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb)) && !clip)
{
short Row = (sp_y >> 3) & 0x1f;
 
if(!sprite_size)
{
// 1x1 tile
if (RowCount[Row] < MaxTilesPerRow)
RowCount[Row]++;
else
clip=TRUE;
}
else
{
// 2x2 tile
if ((RowCount[Row+0]+1 < MaxTilesPerRow) &&
(RowCount[Row+1]+1 < MaxTilesPerRow))
{
RowCount[Row+0]+=2;
RowCount[Row+1]+=2;
}
else
clip=TRUE;
}
}
 
#ifdef PRINT
printf("(line %d) %04X, %04X, %04X / %04X %04X\n",line,
(uint16)sp_x,(uint16)sp_y,(uint16)far_plane,(uint16)multi_farplane[multi_index1],(uint16)multi_raster[multi_index1]);
#endif
 
// don't draw offscreen coordinates
DSP4.out_count = 0;
if(!clip)
{
int16 out_index = 0;
int16 offset = DSP4_READ_WORD(0);
 
// update sprite nametable/attribute information
sp_oam = sprite_offset + offset;
sp_msb = (sp_x<0 || sp_x>255);
 
#ifdef PRINT2
printf("(line %d) %04X, %04X, %04X, %04X, %04X\n",line,
(uint16)sp_oam,(uint16)sprite_offset,(uint16)offset,
(uint16)sp_x,(uint16)sp_y);
#endif
 
// emit transparency information
if(
(sprite_offset&0x08) &&
((sprite_type==1 && sp_y>=0xcc) ||
(sprite_type==2 && sp_y>=0xbb))
)
{
DSP4.out_count = 6;
 
// one block of OAM data
DSP4_WRITE_WORD(0,1);
 
// OAM: x,y,tile,no attr
DSP4.output[2] = sp_x&0xFF;
DSP4.output[3] = (sp_y+6)&0xFF;
DSP4_WRITE_WORD(4,0xEE);
 
out_index = 6;
 
// OAM: size,msb data
DSP4_Op06(sprite_size,sp_msb);
 
#if 0
//DSP4_WRITE_WORD(0,-1);
DSP4_WRITE_WORD(2,-1);
DSP4_WRITE_WORD(4,-1);
#endif
}
 
// normal data
DSP4.out_count += 8;
 
// one block of OAM data
DSP4_WRITE_WORD(out_index+0,1);
 
// OAM: x,y,tile,attr
DSP4.output[out_index+2] = sp_x&0xFF;
DSP4.output[out_index+3] = sp_y&0xFF;
DSP4_WRITE_WORD(out_index+4,sp_oam);
 
// no following OAM data
DSP4_WRITE_WORD(out_index+6,0);
 
// OAM: size,msb data
DSP4_Op06(sprite_size,sp_msb);
 
#if 0
//DSP4_WRITE_WORD(out_index+0,-1);
DSP4_WRITE_WORD(out_index+2,-1);
DSP4_WRITE_WORD(out_index+4,-1);
#endif
}
 
// no sprite information
if(DSP4.out_count == 0)
{
DSP4.out_count = 2;
DSP4_WRITE_WORD(0,0);
}
} while (1);
 
/////////////////////////////////////
// special cases: plane == 0x0000
 
// special vehicle case
if(command == 0x90)
{
sprite_type = 1;
 
// shift bytes
DSP4.parameters[2] = DSP4.parameters[0];
DSP4.parameters[3] = DSP4.parameters[1];
DSP4.parameters[0] = 0;
DSP4.parameters[1] = 0;
 
goto sprite_found;
}
// special terrain case
else if(command != 0x00 && command != 0xff)
{
sprite_type = 2;
 
// shift bytes
DSP4.parameters[2] = DSP4.parameters[0];
DSP4.parameters[3] = DSP4.parameters[1];
DSP4.parameters[0] = 0;
DSP4.parameters[1] = 0;
 
goto sprite_found;
}
} while (1);
 
terminate:
DSP4.waiting4command = TRUE;
DSP4.out_count=0;
}
 
#undef PRINT
linux/wsnes9x.h
191,7 → 191,7
char SPL4Pack[MAX_PATH];
char MDHPack[MAX_PATH];
COLORREF InfoColor;
bool HideMenu;
bool HideMenu;
bool VideoMemory;
 
// avi writing
302,8 → 302,8
 
/*****************************************************************************/
 
void S9xSetWinPixelFormat ();
//int CheckKey( WORD Key, int OldJoypad);
void S9xSetWinPixelFormat ();
//int CheckKey( WORD Key, int OldJoypad);
//void TranslateKey(WORD keyz,char *out);
#ifdef USE_GLIDE
#define VOODOO_MODE (GUI.Scale == 7)
linux/language.h
1,328 → 1,328
/*******************************************************************************
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
 
(c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and
Jerremy Koot (jkoot@snes9x.com)
 
(c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net)
 
(c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net),
funkyass (funkyass@spam.shaw.ca),
Joel Yliluoma (http://iki.fi/bisqwit/)
Kris Bleakley (codeviolation@hotmail.com),
Matthew Kendora,
Nach (n-a-c-h@users.sourceforge.net),
Peter Bortas (peter@bortas.org) and
zones (kasumitokoduck@yahoo.com)
 
C4 x86 assembler and some C emulation code
(c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com),
_Demo_ (_demo_@zsnes.com), and Nach
 
C4 C++ code
(c) Copyright 2003 Brad Jorsch
 
DSP-1 emulator code
(c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson,
John Weidman, neviksti (neviksti@hotmail.com),
Kris Bleakley, Andreas Naive
 
DSP-2 emulator code
(c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and
Lord Nightmare (lord_nightmare@users.sourceforge.net
 
OBC1 emulator code
(c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and
Kris Bleakley
Ported from x86 assembler to C by sanmaiwashi
 
SPC7110 and RTC C++ emulator code
(c) Copyright 2002 Matthew Kendora with research by
zsKnight, John Weidman, and Dark Force
 
S-DD1 C emulator code
(c) Copyright 2003 Brad Jorsch with research by
Andreas Naive and John Weidman
 
S-RTC C emulator code
(c) Copyright 2001 John Weidman
 
ST010 C++ emulator code
(c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora
 
Super FX x86 assembler emulator code
(c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault
 
Super FX C emulator code
(c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman
 
 
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
 
 
Specific ports contains the works of other authors. See headers in
individual files.
 
Snes9x homepage: http://www.snes9x.com
 
Permission to use, copy, modify and distribute Snes9x in both binary and
source form, for non-commercial purposes, is hereby granted without fee,
providing that this license information and copyright notice appear with
all copies and any derived work.
 
This software is provided 'as-is', without any express or implied
warranty. In no event shall the authors be held liable for any damages
arising from the use of this software.
 
Snes9x is freeware for PERSONAL USE only. Commercial users should
seek permission of the copyright holders first. Commercial use includes
charging money for Snes9x or software derived from Snes9x.
 
The copyright holders request that bug fixes and improvements to the code
should be forwarded to them so everyone can benefit from the modifications
in future versions.
 
Super NES and Super Nintendo Entertainment System are trademarks of
Nintendo Co., Limited and its subsidiary companies.
*******************************************************************************/
 
/* This is where all the GUI text strings will eventually end up */
 
#define WINDOW_TITLE "Snes9X v%s for Windows"
 
#define MY_REG_KEY "Software\\Emulators\\Snes9X"
 
#define REG_KEY_VER "1.31"
 
#define DISCLAIMER_TEXT "Snes9X v%s for Windows.\r\n" \
"(c) Copyright 1996 - 2002 Gary Henderson and Jerremy Koot.\r\n" \
"(c) Copyright 2001- 2004 John Weidman.\r\n" \
"(c) Copyright 2002 - 2004 blip, Brad Jorsch, funkyass, Joel Yliluoma, Kris Bleakley, Matthew Kendora, Nach, Peter Bortas, zones.\r\n\r\n" \
"Snes9X is a Super Nintendo Entertainment System\r\n" \
"emulator that allows you to play most games designed\r\n" \
"for the SNES on your PC.\r\n\r\n" \
"Please visit http://www.snes9x.com for\r\n" \
"up-to-the-minute information and help on Snes9X.\r\n\r\n" \
"Nintendo is a trade mark."
 
 
#define APP_NAME "Snes9x"
/* possible global strings */
#define SNES9X_INFO "Snes9x: Information"
#define SNES9X_WARN "Snes9x: WARNING!"
#define SNES9X_DXS "Snes9X: DirectSound"
#define SNES9X_SNDQ "Snes9X: Sound CPU Question"
#define SNES9X_NP_ERROR "Snes9X: NetPlay Error"
#define BUTTON_OK "&OK"
#define BUTTON_CANCEL "&Cancel"
 
/* Gamepad Dialog Strings */
#define INPUTCONFIG_TITLE "Input Configuration"
#define INPUTCONFIG_JPTOGGLE "Enable"
#define INPUTCONFIG_DIAGTOGGLE "Toggle Diagonals"
/* #define INPUTCONFIG_OK "&OK" */
/* #define INPUTCONFIG_CANCEL "&Cancel" */
#define INPUTCONFIG_JPCOMBO "Joypad #%d"
#define INPUTCONFIG_LABEL_UP "Up"
#define INPUTCONFIG_LABEL_DOWN "Down"
#define INPUTCONFIG_LABEL_LEFT "Left"
#define INPUTCONFIG_LABEL_RIGHT "Right"
#define INPUTCONFIG_LABEL_A "A"
#define INPUTCONFIG_LABEL_B "B"
#define INPUTCONFIG_LABEL_X "X"
#define INPUTCONFIG_LABEL_Y "Y"
#define INPUTCONFIG_LABEL_L "L"
#define INPUTCONFIG_LABEL_R "R"
#define INPUTCONFIG_LABEL_START "Start"
#define INPUTCONFIG_LABEL_SELECT "Select"
#define INPUTCONFIG_LABEL_UPLEFT "Up Left"
#define INPUTCONFIG_LABEL_UPRIGHT "Up Right"
#define INPUTCONFIG_LABEL_DOWNRIGHT "Down Right"
#define INPUTCONFIG_LABEL_DOWNLEFT "Down Left"
#define INPUTCONFIG_LABEL_BLUE "Blue means the current key/button is already mapped; Red means it's a Snes9x/Windows reserved key."
 
/* gaming buttons and axises */
#define GAMEDEVICE_JOYNUMPREFIX "(J%d)"
#define GAMEDEVICE_JOYBUTPREFIX "#[%d]"
#define GAMEDEVICE_XNEG "Left"
#define GAMEDEVICE_XPOS "Right"
#define GAMEDEVICE_YPOS "Up"
#define GAMEDEVICE_YNEG "Down"
#define GAMEDEVICE_POVLEFT "POV Left"
#define GAMEDEVICE_POVRIGHT "POV Right"
#define GAMEDEVICE_POVUP "POV Up"
#define GAMEDEVICE_POVDOWN "POV Down"
#define GAMEDEVICE_POVDNLEFT "POV Dn Left"
#define GAMEDEVICE_POVDNRIGHT "POV Dn Right"
#define GAMEDEVICE_POVUPLEFT "POV Up Left"
#define GAMEDEVICE_POVUPRIGHT "POV Up Right"
#define GAMEDEVICE_ZPOS "Z Up"
#define GAMEDEVICE_ZNEG "Z Down"
#define GAMEDEVICE_RPOS "R Up"
#define GAMEDEVICE_RNEG "R Down"
#define GAMEDEVICE_UPOS "U Up"
#define GAMEDEVICE_UNEG "U Down"
#define GAMEDEVICE_VPOS "V Up"
#define GAMEDEVICE_VNEG "V Down"
#define GAMEDEVICE_BUTTON "Button %d"
 
/* gaming general */
#define GAMEDEVICE_DISABLED "Disabled"
 
/* gaming keys */
#define GAMEDEVICE_KEY "#%d"
#define GAMEDEVICE_NUMPADPREFIX "Numpad-%c"
#define GAMEDEVICE_VK_TAB "Tab"
#define GAMEDEVICE_VK_BACK "Backspace"
#define GAMEDEVICE_VK_CLEAR "Delete"
#define GAMEDEVICE_VK_RETURN "Enter"
#define GAMEDEVICE_VK_LSHIFT "LShift"
#define GAMEDEVICE_VK_RSHIFT "RShift"
#define GAMEDEVICE_VK_LCONTROL "LCTRL"
#define GAMEDEVICE_VK_RCONTROL "RCTRL"
#define GAMEDEVICE_VK_LMENU "LAlt"
#define GAMEDEVICE_VK_RMENU "RAlt"
#define GAMEDEVICE_VK_PAUSE "Pause"
#define GAMEDEVICE_VK_CAPITAL "Capslock"
#define GAMEDEVICE_VK_ESCAPE "Disabled"
#define GAMEDEVICE_VK_SPACE "Space"
#define GAMEDEVICE_VK_PRIOR "PgUp"
#define GAMEDEVICE_VK_NEXT "PgDn"
#define GAMEDEVICE_VK_HOME "Home"
#define GAMEDEVICE_VK_END "End"
#define GAMEDEVICE_VK_LEFT "Left"
#define GAMEDEVICE_VK_RIGHT "Right"
#define GAMEDEVICE_VK_UP "Up"
#define GAMEDEVICE_VK_DOWN "Down"
#define GAMEDEVICE_VK_SELECT "Select"
#define GAMEDEVICE_VK_PRINT "Print"
#define GAMEDEVICE_VK_EXECUTE "Execute"
#define GAMEDEVICE_VK_SNAPSHOT "SnapShot"
#define GAMEDEVICE_VK_INSERT "Insert"
#define GAMEDEVICE_VK_DELETE "Delete"
#define GAMEDEVICE_VK_HELP "Help"
#define GAMEDEVICE_VK_LWIN "LWinKey"
#define GAMEDEVICE_VK_RWIN "RWinKey"
#define GAMEDEVICE_VK_APPS "AppKey"
#define GAMEDEVICE_VK_MULTIPLY "Numpad *"
#define GAMEDEVICE_VK_ADD "Numpad +"
#define GAMEDEVICE_VK_SEPARATOR "\\"
#define GAMEDEVICE_VK_OEM_1 "Semi-Colon"
#define GAMEDEVICE_VK_OEM_7 "Apostrophe"
#define GAMEDEVICE_VK_OEM_COMMA "Comma"
#define GAMEDEVICE_VK_OEM_PERIOD "Period"
#define GAMEDEVICE_VK_SUBTRACT "Numpad -"
#define GAMEDEVICE_VK_DECIMAL "Numpad ."
#define GAMEDEVICE_VK_DIVIDE "Numpad /"
#define GAMEDEVICE_VK_NUMLOCK "Num-lock"
#define GAMEDEVICE_VK_SCROLL "Scroll-lock"
 
/* evil things I found in WinProc */
 
#define WINPROC_TURBOMODE_ON "Turbo Mode Activated"
#define WINPROC_TURBOMODE_OFF "Turbo Mode Deactivated"
#define WINPROC_TURBOMODE_TEXT "Turbo Mode"
#define WINPROC_HDMA_TEXT "HDMA emulation"
#define WINPROC_BG1 "BG#1" /* Background Layers */
#define WINPROC_BG2 "BG#2"
#define WINPROC_BG3 "BG#3"
#define WINPROC_BG4 "BG#4"
#define WINPROC_SPRITES "Sprites"
#define WINPROC_PADSWAP "Joypad swapping"
#define WINPROC_CONTROLERS0 "Multiplayer 5 on #0"
#define WINPROC_CONTROLERS1 "Joypad on #0"
#define WINPROC_CONTROLERS2 "Mouse on #1"
#define WINPROC_CONTROLERS3 "Mouse on #0"
#define WINPROC_CONTROLERS4 "Superscope on #1"
#define WINPROC_CONTROLERS5 "Justifier 1 on #1"
#define WINPROC_CONTROLERS6 "Justifier 2 on #1"
#define WINPROC_BGHACK "Background layering hack"
#define WINPROC_MODE7INTER "Mode 7 Interpolation"
#define WINPROC_TRANSPARENCY "Transparency effects"
#define WINPROC_CLIPWIN "Graphic clip windows"
#define WINPROC_PAUSE "Pause"
#define WINPROC_EMUFRAMETIME "Emulated frame time: %dms"
#define WINPROC_AUTOSKIP "Auto Frame Skip"
#define WINPROC_FRAMESKIP "Frame skip: %d"
#define WINPROC_TURBO_R_ON "Turbo R Activated"
#define WINPROC_TURBO_R_OFF "Turbo R Deactivated"
#define WINPROC_TURBO_L_ON "Turbo L Activated"
#define WINPROC_TURBO_L_OFF "Turbo L Deactivated"
#define WINPROC_TURBO_X_ON "Turbo X Activated"
#define WINPROC_TURBO_X_OFF "Turbo X Deactivated"
#define WINPROC_TURBO_Y_ON "Turbo Y Activated"
#define WINPROC_TURBO_Y_OFF "Turbo Y Deactivated"
#define WINPROC_TURBO_A_ON "Turbo A Activated"
#define WINPROC_TURBO_A_OFF "Turbo A Deactivated"
#define WINPROC_TURBO_B_ON "Turbo B Activated"
#define WINPROC_TURBO_B_OFF "Turbo B Deactivated"
#define WINPROC_TURBO_SEL_ON "Turbo Select Activated"
#define WINPROC_TURBO_SEL_OFF "Turbo Select Deactivated"
#define WINPROC_TURBO_START_ON "Turbo Start Activated"
#define WINPROC_TURBO_START_OFF "Turbo Start Deactivated"
#define WINPROC_FILTER_RESTART "You will need to restart Snes9x before the output image\nprocessing option change will take effect."
#define WINPROC_DISCONNECT "Disconnect from the NetPlay server first."
#define WINPROC_NET_RESTART "Your game will be reset after the ROM has been sent due to\nyour 'Sync Using Reset Game' setting.\n\n"
#define WINPROC_INTERPOLATED_SND "Interpolated sound"
#define WINPROC_SYNC_SND "Sync sound"
#define WINPROC_SND_OFF "Disabling the sound CPU emulation will help to improve\nemulation speed but you will not hear any sound effects\nor music. If you later want to re-enable the sound CPU\nemulation you will need to reset your game before it will\ntake effect.\n\nAre you sure this is what you want?"
#define WINPROC_SND_RESTART "You will need to reset your game or load another one\nbefore enabling the sound CPU will take effect."
 
/* Emulator Settings */
 
#define EMUSET_TITLE "Emulation Settings"
#define EMUSET_LABEL_FREEZE "Freeze Folder Directory"
#define EMUSET_BROWSE "&Browse..."
#define EMUSET_LABEL_ASRAM "Auto-Save S-RAM"
#define EMUSET_LABEL_ASRAM_TEXT "seconds after last change (0 disables auto-save)"
#define EMUSET_LABEL_SMAX "Skip at most"
#define EMUSET_LABEL_SMAX_TEXT "frames in auto-frame rate mode"
#define EMUSET_LABEL_STURBO "Skip Rendering"
#define EMUSET_LABEL_STURBO_TEXT "frames in Turbo mode"
#define EMUSET_TOGGLE_TURBO "Tab Toggles Turbo"
 
/* Netplay Options */
 
#define NPOPT_TITLE "Netplay Options"
#define NPOPT_LABEL_PORTNUM "Socket Port Number"
#define NPOPT_LABEL_PAUSEINTERVAL "Ask Server to Pause when"
#define NPOPT_LABEL_PAUSEINTERVAL_TEXT "frames behind"
#define NPOPT_LABEL_MAXSKIP "Maximum Frame Rate Skip"
#define NPOPT_SYNCBYRESET "Sync By Reset"
#define NPOPT_SENDROM "Send ROM Image to Client on Connect"
#define NPOPT_ACTASSERVER "Act As Server"
#define NPOPT_PORTNUMBLOCK "Port Settings"
#define NPOPT_CLIENTSETTINGSBLOCK "Client Settings"
#define NPOPT_SERVERSETTINGSBLOCK "Server Settings"
 
/* Netplay Connect */
 
 
#define NPCON_TITLE "Connect to Server"
#define NPCON_LABEL_SERVERADDY "Server Address"
#define NPCON_LABEL_PORTNUM "Port Number"
#define NPCON_CLEARHISTORY "Clear History"
 
 
/* Movie Messages */
 
#define MOVIE_INFO_REPLAY "Movie replay"
#define MOVIE_INFO_RECORD "Movie record"
#define MOVIE_INFO_RERECORD "Movie re-record"
#define MOVIE_INFO_REWIND "Movie rewind"
#define MOVIE_INFO_STOP "Movie stop"
#define MOVIE_INFO_END "Movie end"
#define MOVIE_INFO_RECORDING_ENABLED "Recording enabled"
#define MOVIE_INFO_RECORDING_DISABLED "Recording disabled"
#define MOVIE_ERR_SNAPSHOT_WRONG_MOVIE "Snapshot not from this movie"
#define MOVIE_ERR_SNAPSHOT_NOT_MOVIE "Not a movie snapshot"
#define MOVIE_ERR_COULD_NOT_OPEN "Could not open movie file."
#define MOVIE_ERR_NOT_FOUND "File not found."
#define MOVIE_ERR_WRONG_FORMAT "File is wrong format."
#define MOVIE_ERR_WRONG_VERSION "File is wrong version."
 
 
/* AVI Messages */
 
#define AVI_CONFIGURATION_CHANGED "AVI recording stopped (configuration settings changed)."
/*******************************************************************************
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
 
(c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and
Jerremy Koot (jkoot@snes9x.com)
 
(c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net)
 
(c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net),
funkyass (funkyass@spam.shaw.ca),
Joel Yliluoma (http://iki.fi/bisqwit/)
Kris Bleakley (codeviolation@hotmail.com),
Matthew Kendora,
Nach (n-a-c-h@users.sourceforge.net),
Peter Bortas (peter@bortas.org) and
zones (kasumitokoduck@yahoo.com)
 
C4 x86 assembler and some C emulation code
(c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com),
_Demo_ (_demo_@zsnes.com), and Nach
 
C4 C++ code
(c) Copyright 2003 Brad Jorsch
 
DSP-1 emulator code
(c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson,
John Weidman, neviksti (neviksti@hotmail.com),
Kris Bleakley, Andreas Naive
 
DSP-2 emulator code
(c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and
Lord Nightmare (lord_nightmare@users.sourceforge.net
 
OBC1 emulator code
(c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and
Kris Bleakley
Ported from x86 assembler to C by sanmaiwashi
 
SPC7110 and RTC C++ emulator code
(c) Copyright 2002 Matthew Kendora with research by
zsKnight, John Weidman, and Dark Force
 
S-DD1 C emulator code
(c) Copyright 2003 Brad Jorsch with research by
Andreas Naive and John Weidman
 
S-RTC C emulator code
(c) Copyright 2001 John Weidman
 
ST010 C++ emulator code
(c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora
 
Super FX x86 assembler emulator code
(c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault
 
Super FX C emulator code
(c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman
 
 
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
 
 
Specific ports contains the works of other authors. See headers in
individual files.
 
Snes9x homepage: http://www.snes9x.com
 
Permission to use, copy, modify and distribute Snes9x in both binary and
source form, for non-commercial purposes, is hereby granted without fee,
providing that this license information and copyright notice appear with
all copies and any derived work.
 
This software is provided 'as-is', without any express or implied
warranty. In no event shall the authors be held liable for any damages
arising from the use of this software.
 
Snes9x is freeware for PERSONAL USE only. Commercial users should
seek permission of the copyright holders first. Commercial use includes
charging money for Snes9x or software derived from Snes9x.
 
The copyright holders request that bug fixes and improvements to the code
should be forwarded to them so everyone can benefit from the modifications
in future versions.
 
Super NES and Super Nintendo Entertainment System are trademarks of
Nintendo Co., Limited and its subsidiary companies.
*******************************************************************************/
 
/* This is where all the GUI text strings will eventually end up */
 
#define WINDOW_TITLE "Snes9X v%s for Windows"
 
#define MY_REG_KEY "Software\\Emulators\\Snes9X"
 
#define REG_KEY_VER "1.31"
 
#define DISCLAIMER_TEXT "Snes9X v%s for Windows.\r\n" \
"(c) Copyright 1996 - 2002 Gary Henderson and Jerremy Koot.\r\n" \
"(c) Copyright 2001- 2004 John Weidman.\r\n" \
"(c) Copyright 2002 - 2004 blip, Brad Jorsch, funkyass, Joel Yliluoma, Kris Bleakley, Matthew Kendora, Nach, Peter Bortas, zones.\r\n\r\n" \
"Snes9X is a Super Nintendo Entertainment System\r\n" \
"emulator that allows you to play most games designed\r\n" \
"for the SNES on your PC.\r\n\r\n" \
"Please visit http://www.snes9x.com for\r\n" \
"up-to-the-minute information and help on Snes9X.\r\n\r\n" \
"Nintendo is a trade mark."
 
 
#define APP_NAME "Snes9x"
/* possible global strings */
#define SNES9X_INFO "Snes9x: Information"
#define SNES9X_WARN "Snes9x: WARNING!"
#define SNES9X_DXS "Snes9X: DirectSound"
#define SNES9X_SNDQ "Snes9X: Sound CPU Question"
#define SNES9X_NP_ERROR "Snes9X: NetPlay Error"
#define BUTTON_OK "&OK"
#define BUTTON_CANCEL "&Cancel"
 
/* Gamepad Dialog Strings */
#define INPUTCONFIG_TITLE "Input Configuration"
#define INPUTCONFIG_JPTOGGLE "Enable"
#define INPUTCONFIG_DIAGTOGGLE "Toggle Diagonals"
/* #define INPUTCONFIG_OK "&OK" */
/* #define INPUTCONFIG_CANCEL "&Cancel" */
#define INPUTCONFIG_JPCOMBO "Joypad #%d"
#define INPUTCONFIG_LABEL_UP "Up"
#define INPUTCONFIG_LABEL_DOWN "Down"
#define INPUTCONFIG_LABEL_LEFT "Left"
#define INPUTCONFIG_LABEL_RIGHT "Right"
#define INPUTCONFIG_LABEL_A "A"
#define INPUTCONFIG_LABEL_B "B"
#define INPUTCONFIG_LABEL_X "X"
#define INPUTCONFIG_LABEL_Y "Y"
#define INPUTCONFIG_LABEL_L "L"
#define INPUTCONFIG_LABEL_R "R"
#define INPUTCONFIG_LABEL_START "Start"
#define INPUTCONFIG_LABEL_SELECT "Select"
#define INPUTCONFIG_LABEL_UPLEFT "Up Left"
#define INPUTCONFIG_LABEL_UPRIGHT "Up Right"
#define INPUTCONFIG_LABEL_DOWNRIGHT "Down Right"
#define INPUTCONFIG_LABEL_DOWNLEFT "Down Left"
#define INPUTCONFIG_LABEL_BLUE "Blue means the current key/button is already mapped; Red means it's a Snes9x/Windows reserved key."
 
/* gaming buttons and axises */
#define GAMEDEVICE_JOYNUMPREFIX "(J%d)"
#define GAMEDEVICE_JOYBUTPREFIX "#[%d]"
#define GAMEDEVICE_XNEG "Left"
#define GAMEDEVICE_XPOS "Right"
#define GAMEDEVICE_YPOS "Up"
#define GAMEDEVICE_YNEG "Down"
#define GAMEDEVICE_POVLEFT "POV Left"
#define GAMEDEVICE_POVRIGHT "POV Right"
#define GAMEDEVICE_POVUP "POV Up"
#define GAMEDEVICE_POVDOWN "POV Down"
#define GAMEDEVICE_POVDNLEFT "POV Dn Left"
#define GAMEDEVICE_POVDNRIGHT "POV Dn Right"
#define GAMEDEVICE_POVUPLEFT "POV Up Left"
#define GAMEDEVICE_POVUPRIGHT "POV Up Right"
#define GAMEDEVICE_ZPOS "Z Up"
#define GAMEDEVICE_ZNEG "Z Down"
#define GAMEDEVICE_RPOS "R Up"
#define GAMEDEVICE_RNEG "R Down"
#define GAMEDEVICE_UPOS "U Up"
#define GAMEDEVICE_UNEG "U Down"
#define GAMEDEVICE_VPOS "V Up"
#define GAMEDEVICE_VNEG "V Down"
#define GAMEDEVICE_BUTTON "Button %d"
 
/* gaming general */
#define GAMEDEVICE_DISABLED "Disabled"
 
/* gaming keys */
#define GAMEDEVICE_KEY "#%d"
#define GAMEDEVICE_NUMPADPREFIX "Numpad-%c"
#define GAMEDEVICE_VK_TAB "Tab"
#define GAMEDEVICE_VK_BACK "Backspace"
#define GAMEDEVICE_VK_CLEAR "Delete"
#define GAMEDEVICE_VK_RETURN "Enter"
#define GAMEDEVICE_VK_LSHIFT "LShift"
#define GAMEDEVICE_VK_RSHIFT "RShift"
#define GAMEDEVICE_VK_LCONTROL "LCTRL"
#define GAMEDEVICE_VK_RCONTROL "RCTRL"
#define GAMEDEVICE_VK_LMENU "LAlt"
#define GAMEDEVICE_VK_RMENU "RAlt"
#define GAMEDEVICE_VK_PAUSE "Pause"
#define GAMEDEVICE_VK_CAPITAL "Capslock"
#define GAMEDEVICE_VK_ESCAPE "Disabled"
#define GAMEDEVICE_VK_SPACE "Space"
#define GAMEDEVICE_VK_PRIOR "PgUp"
#define GAMEDEVICE_VK_NEXT "PgDn"
#define GAMEDEVICE_VK_HOME "Home"
#define GAMEDEVICE_VK_END "End"
#define GAMEDEVICE_VK_LEFT "Left"
#define GAMEDEVICE_VK_RIGHT "Right"
#define GAMEDEVICE_VK_UP "Up"
#define GAMEDEVICE_VK_DOWN "Down"
#define GAMEDEVICE_VK_SELECT "Select"
#define GAMEDEVICE_VK_PRINT "Print"
#define GAMEDEVICE_VK_EXECUTE "Execute"
#define GAMEDEVICE_VK_SNAPSHOT "SnapShot"
#define GAMEDEVICE_VK_INSERT "Insert"
#define GAMEDEVICE_VK_DELETE "Delete"
#define GAMEDEVICE_VK_HELP "Help"
#define GAMEDEVICE_VK_LWIN "LWinKey"
#define GAMEDEVICE_VK_RWIN "RWinKey"
#define GAMEDEVICE_VK_APPS "AppKey"
#define GAMEDEVICE_VK_MULTIPLY "Numpad *"
#define GAMEDEVICE_VK_ADD "Numpad +"
#define GAMEDEVICE_VK_SEPARATOR "\\"
#define GAMEDEVICE_VK_OEM_1 "Semi-Colon"
#define GAMEDEVICE_VK_OEM_7 "Apostrophe"
#define GAMEDEVICE_VK_OEM_COMMA "Comma"
#define GAMEDEVICE_VK_OEM_PERIOD "Period"
#define GAMEDEVICE_VK_SUBTRACT "Numpad -"
#define GAMEDEVICE_VK_DECIMAL "Numpad ."
#define GAMEDEVICE_VK_DIVIDE "Numpad /"
#define GAMEDEVICE_VK_NUMLOCK "Num-lock"
#define GAMEDEVICE_VK_SCROLL "Scroll-lock"
 
/* evil things I found in WinProc */
 
#define WINPROC_TURBOMODE_ON "Turbo Mode Activated"
#define WINPROC_TURBOMODE_OFF "Turbo Mode Deactivated"
#define WINPROC_TURBOMODE_TEXT "Turbo Mode"
#define WINPROC_HDMA_TEXT "HDMA emulation"
#define WINPROC_BG1 "BG#1" /* Background Layers */
#define WINPROC_BG2 "BG#2"
#define WINPROC_BG3 "BG#3"
#define WINPROC_BG4 "BG#4"
#define WINPROC_SPRITES "Sprites"
#define WINPROC_PADSWAP "Joypad swapping"
#define WINPROC_CONTROLERS0 "Multiplayer 5 on #0"
#define WINPROC_CONTROLERS1 "Joypad on #0"
#define WINPROC_CONTROLERS2 "Mouse on #1"
#define WINPROC_CONTROLERS3 "Mouse on #0"
#define WINPROC_CONTROLERS4 "Superscope on #1"
#define WINPROC_CONTROLERS5 "Justifier 1 on #1"
#define WINPROC_CONTROLERS6 "Justifier 2 on #1"
#define WINPROC_BGHACK "Background layering hack"
#define WINPROC_MODE7INTER "Mode 7 Interpolation"
#define WINPROC_TRANSPARENCY "Transparency effects"
#define WINPROC_CLIPWIN "Graphic clip windows"
#define WINPROC_PAUSE "Pause"
#define WINPROC_EMUFRAMETIME "Emulated frame time: %dms"
#define WINPROC_AUTOSKIP "Auto Frame Skip"
#define WINPROC_FRAMESKIP "Frame skip: %d"
#define WINPROC_TURBO_R_ON "Turbo R Activated"
#define WINPROC_TURBO_R_OFF "Turbo R Deactivated"
#define WINPROC_TURBO_L_ON "Turbo L Activated"
#define WINPROC_TURBO_L_OFF "Turbo L Deactivated"
#define WINPROC_TURBO_X_ON "Turbo X Activated"
#define WINPROC_TURBO_X_OFF "Turbo X Deactivated"
#define WINPROC_TURBO_Y_ON "Turbo Y Activated"
#define WINPROC_TURBO_Y_OFF "Turbo Y Deactivated"
#define WINPROC_TURBO_A_ON "Turbo A Activated"
#define WINPROC_TURBO_A_OFF "Turbo A Deactivated"
#define WINPROC_TURBO_B_ON "Turbo B Activated"
#define WINPROC_TURBO_B_OFF "Turbo B Deactivated"
#define WINPROC_TURBO_SEL_ON "Turbo Select Activated"
#define WINPROC_TURBO_SEL_OFF "Turbo Select Deactivated"
#define WINPROC_TURBO_START_ON "Turbo Start Activated"
#define WINPROC_TURBO_START_OFF "Turbo Start Deactivated"
#define WINPROC_FILTER_RESTART "You will need to restart Snes9x before the output image\nprocessing option change will take effect."
#define WINPROC_DISCONNECT "Disconnect from the NetPlay server first."
#define WINPROC_NET_RESTART "Your game will be reset after the ROM has been sent due to\nyour 'Sync Using Reset Game' setting.\n\n"
#define WINPROC_INTERPOLATED_SND "Interpolated sound"
#define WINPROC_SYNC_SND "Sync sound"
#define WINPROC_SND_OFF "Disabling the sound CPU emulation will help to improve\nemulation speed but you will not hear any sound effects\nor music. If you later want to re-enable the sound CPU\nemulation you will need to reset your game before it will\ntake effect.\n\nAre you sure this is what you want?"
#define WINPROC_SND_RESTART "You will need to reset your game or load another one\nbefore enabling the sound CPU will take effect."
 
/* Emulator Settings */
 
#define EMUSET_TITLE "Emulation Settings"
#define EMUSET_LABEL_FREEZE "Freeze Folder Directory"
#define EMUSET_BROWSE "&Browse..."
#define EMUSET_LABEL_ASRAM "Auto-Save S-RAM"
#define EMUSET_LABEL_ASRAM_TEXT "seconds after last change (0 disables auto-save)"
#define EMUSET_LABEL_SMAX "Skip at most"
#define EMUSET_LABEL_SMAX_TEXT "frames in auto-frame rate mode"
#define EMUSET_LABEL_STURBO "Skip Rendering"
#define EMUSET_LABEL_STURBO_TEXT "frames in Turbo mode"
#define EMUSET_TOGGLE_TURBO "Tab Toggles Turbo"
 
/* Netplay Options */
 
#define NPOPT_TITLE "Netplay Options"
#define NPOPT_LABEL_PORTNUM "Socket Port Number"
#define NPOPT_LABEL_PAUSEINTERVAL "Ask Server to Pause when"
#define NPOPT_LABEL_PAUSEINTERVAL_TEXT "frames behind"
#define NPOPT_LABEL_MAXSKIP "Maximum Frame Rate Skip"
#define NPOPT_SYNCBYRESET "Sync By Reset"
#define NPOPT_SENDROM "Send ROM Image to Client on Connect"
#define NPOPT_ACTASSERVER "Act As Server"
#define NPOPT_PORTNUMBLOCK "Port Settings"
#define NPOPT_CLIENTSETTINGSBLOCK "Client Settings"
#define NPOPT_SERVERSETTINGSBLOCK "Server Settings"
 
/* Netplay Connect */
 
 
#define NPCON_TITLE "Connect to Server"
#define NPCON_LABEL_SERVERADDY "Server Address"
#define NPCON_LABEL_PORTNUM "Port Number"
#define NPCON_CLEARHISTORY "Clear History"
 
 
/* Movie Messages */
 
#define MOVIE_INFO_REPLAY "Movie replay"
#define MOVIE_INFO_RECORD "Movie record"
#define MOVIE_INFO_RERECORD "Movie re-record"
#define MOVIE_INFO_REWIND "Movie rewind"
#define MOVIE_INFO_STOP "Movie stop"
#define MOVIE_INFO_END "Movie end"
#define MOVIE_INFO_RECORDING_ENABLED "Recording enabled"
#define MOVIE_INFO_RECORDING_DISABLED "Recording disabled"
#define MOVIE_ERR_SNAPSHOT_WRONG_MOVIE "Snapshot not from this movie"
#define MOVIE_ERR_SNAPSHOT_NOT_MOVIE "Not a movie snapshot"
#define MOVIE_ERR_COULD_NOT_OPEN "Could not open movie file."
#define MOVIE_ERR_NOT_FOUND "File not found."
#define MOVIE_ERR_WRONG_FORMAT "File is wrong format."
#define MOVIE_ERR_WRONG_VERSION "File is wrong version."
 
 
/* AVI Messages */
 
#define AVI_CONFIGURATION_CHANGED "AVI recording stopped (configuration settings changed)."
linux/resource.h
1,393 → 1,393
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by 0snes9X.rc
//
#define IDR_MENU_US 101
#define IDC_CURSOR_SCOPE 101
#define IDD_SPC7110_CACHE 101
#define IDI_ICON1 101
#define IDR_MENU_NL 102
#define IDC_CURSOR_BLANK 102
#define IDD_SOUND_OPTS 102
#define IDR_SNES9X_ACCELERATORS 103
#define IDD_7110_RTC 103
#define IDD_ROM_INFO 104
#define IDD_ABOUT 105
#define IDD_EMU_SETTINGS 106
#define IDD_OPEN_ROM 107
#define IDD_GFX_PACK 108
#define IDD_NETCONNECT 109
#define IDD_NPOPTIONS 110
#define IDB_OPENFOLDER 111
#define IDD_CHEATER 111
#define IDB_CLOSEDFOLDER 112
#define IDB_CDDRIVE 113
#define IDB_NETDRIVE 114
#define IDB_HARDDRIVE 115
#define IDD_NEWDISPLAY 123
#define IDD_NETPLAYPROGRESS 124
#define IDD_INPUTCONFIG 125
#define IDB_JOYPAD 127
#define IDD_CHEAT_SEARCH 129
#define IDD_DIALOG1 130
#define IDD_CHEAT_FROM_SEARCH 131
#define IDB_PAD 133
#define IDD_OPENMOVIE 134
#define IDD_CREATEMOVIE 135
#define IDC_DRIVER 1001
#define IDC_BUFLEN 1002
#define IDC_RATE 1003
#define IDC_MIX 1004
#define IDC_16BIT 1005
#define IDC_STEREO 1006
#define IDC_REV_STEREO 1007
#define IDC_LINEAR_INTER 1008
#define IDC_SYNC_TO_SOUND_CPU 1009
#define IDC_ENVX 1010
#define IDC_ECHO 1011
#define IDC_CACHING 1012
#define IDC_MASTER_VOL 1013
#define IDC_SPC700ON 1014
#define IDC_ANTIRES 1015
#define IDC_MUTE 1016
#define IDC_SKIP_TYPE 1017
#define IDC_SCROLLBAR1 1018
#define IDC_VRAM_DISPLAY 1019
#define IDC_ADDRESS 1020
#define IDC_SPC7110_ALL 1021
#define IDC_SPC7110_SOME 1022
#define IDC_SPC7110_FILE 1023
#define IDC_RTC_D8 1024
#define IDC_RTC_D4 1025
#define IDC_RTC_D2 1026
#define IDC_RTC_D1 1027
#define IDC_RTC_E8 1028
#define IDC_RTC_E4 1029
#define IDC_RTC_E2 1030
#define IDC_RTC_E1 1031
#define IDC_RTC_F8 1032
#define IDC_RTC_F4 1033
#define IDC_RTC_F2 1034
#define IDC_RTC_F1 1035
#define IDC_DAY 1036
#define IDC_YEAR 1037
#define IDC_MONTH 1038
#define IDC_HOUR 1039
#define IDC_MINUTE 1040
#define IDC_SECOND 1041
#define IDC_LBLMONTH 1042
#define IDC_LBLYEAR 1043
#define IDC_LBLDAY 1044
#define IDC_LBLHOUR 1045
#define IDC_LBLMINUTE 1046
#define IDC_LBLSECOND 1047
#define IDC_CACHE_MB 1048
#define IDC_SPIN_CACHE 1049
#define IDC_ROM_DATA 1051
#define IDC_WARNINGS 1052
#define IDC_DISCLAIMER 1053
#define IDC_FREEZE_FOLDER 1054
#define IDC_BROWSE 1055
#define IDC_CANCEL 1056
#define IDC_AUTO_SAVE_DELAY 1057
#define IDC_MAX_SKIP 1058
#define IDC_TURBO_SKIP 1059
#define IDC_TOGGLE_TURBO 1060
#define IDC_SRAM_SPIN 1061
#define IDC_SPIN_MAX_SKIP 1062
#define IDC_SPIN_TURBO_SKIP 1063
#define IDC_ROM_DIR 1064
#define IDC_INTERLEAVE 1065
#define IDC_VIDEO_MODE 1066
#define IDC_HEADER 1067
#define IDC_ROMLIST 1068
#define IDC_MEM_TYPE 1069
#define IDC_STAR_OCEAN 1070
#define IDC_SO_BROWSE 1071
#define IDC_FEOEZ 1072
#define IDC_FEOEZ_BROWSE 1073
#define IDC_MDH 1074
#define IDC_MDH_BROWSE 1075
#define IDC_SPL4 1076
#define IDC_SPL4_BROWSE 1077
#define IDC_SJNS 1078
#define IDC_FEOEZ_SJNS_BROWSE 1079
#define IDC_SFA2 1080
#define IDC_SFA2_BROWSE 1081
#define IDC_SFA2E 1082
#define IDC_SFA2E_BROWSE 1083
#define IDC_SFZ2 1084
#define IDC_SFZ2_BROWSE 1085
#define IDC_HOSTNAME 1086
#define IDC_PORTNUMBER 1087
#define IDC_CLEARHISTORY 1088
#define IDC_STATIC2 1089
#define IDC_EDIT1 1090
#define IDC_UP 1090
#define IDC_VALUE_ENTER 1090
#define IDC_MOVIE_METADATA 1090
#define IDC_PAUSEINTERVAL 1091
#define IDC_UPRIGHT 1091
#define IDC_MAXSKIP 1092
#define IDC_PAUSESPIN 1093
#define IDC_DWNRIGHT 1093
#define IDC_SYNCBYRESET 1094
#define IDC_DOWN 1094
#define IDC_SENDROM 1095
#define IDC_DWNLEFT 1095
#define IDC_ACTASSERVER 1096
#define IDC_LEFT 1096
#define IDC_MAXSPIN 1097
#define IDC_UPLEFT 1097
#define IDC_SELECT 1098
#define IDC_PORTNUMBERA 1099
#define IDC_START 1099
#define IDC_TESTMODE 1100
#define IDC_L 1100
#define IDC_VIDEOLIST 1101
#define IDC_R 1101
#define IDC_SELECT2 1101
#define IDC_VIDMODELIST 1102
#define IDC_Y 1102
#define IDC_SETDMODE 1103
#define IDC_B 1103
#define IDC_A 1104
#define IDC_X 1105
#define IDC_RIGHT 1106
#define IDC_SHOWFPS 1108
#define IDC_STRETCH 1109
#define IDC_FULLSCREEN 1110
#define IDC_BILINEARMD7 1111
#define IDC_RENDER16BIT 1112
#define IDC_TRANS 1113
#define IDC_HIRES 1114
#define IDC_CHEAT_CODE 1115
#define IDC_FILTERBOX 1116
#define IDC_AUTOFRAME 1117
#define IDC_LIMITFRAMES 1118
#define IDC_FRAMERATESKIPSLIDER 1120
#define IDC_TOGGLE 1121
#define IDC_DBLBUFFER 1122
#define IDC_CURRMODE 1123
#define IDC_DELETE_CHEAT 1124
#define IDC_NPPROGRESS 1124
#define IDC_VIDEOCARD 1124
#define IDC_UPDATE_CHEAT 1125
#define IDC_JPCOMBO 1125
#define IDC_CLEAR_CHEATS 1126
#define IDC_JPTOGGLE 1126
#define IDC_CHEAT_DESCRIPTION 1127
#define IDC_KEYBOARD 1127
#define IDC_CHEAT_ADDRESS 1128
#define IDC_CHEAT_BYTE 1129
#define IDC_ADD_CHEAT 1130
#define IDC_CHEAT_LIST 1131
#define IDC_PICTURE 1132
#define IDC_ADDYS 1133
#define IDC_OK 1134
#define IDC_C_SEARCH 1134
#define IDC_RED 1135
#define IDC_C_ADD 1135
#define IDC_BLUE 1136
#define IDC_C_RESET 1136
#define IDC_LABEL_BLUE 1136
#define IDC_1_BYTE 1137
#define IDC_2_BYTE 1138
#define IDC_3_BYTE 1139
#define IDC_4_BYTE 1140
#define IDC_LESS_THAN 1141
#define IDC_GREATER_THAN 1142
#define IDC_LESS_THAN_EQUAL 1143
#define IDC_GREATER_THAN_EQUAL 1144
#define IDC_EQUAL 1145
#define IDC_NOT_EQUAL 1146
#define IDC_PREV 1147
#define IDC_ENTERED 1148
#define IDC_UNSIGNED 1149
#define IDC_SIGNED 1150
#define IDC_HEX 1151
#define IDC_ENTER_LABEL 1152
#define IDC_DIAGTOGGLE 1153
#define IDC_UNDO 1154
#define IDC_COMBO1 1155
#define IDC_NC_ADDRESS 1156
#define IDC_NC_CURRVAL 1157
#define IDC_NC_PREVVAL 1158
#define IDC_NC_NEWVAL 1159
#define IDC_NC_DESC 1160
#define IDC_LABEL_UP 1161
#define IDC_LABEL_LEFT 1162
#define IDC_LABEL_DOWN 1163
#define IDC_LABEL_RIGHT 1164
#define IDC_LABEL_B 1165
#define IDC_LABEL_A 1166
#define IDC_LABEL_Y 1167
#define IDC_LABEL_X 1168
#define IDC_LABEL_START 1169
#define IDC_LABEL_SELECT 1170
#define IDC_LABEL_L 1171
#define IDC_LABEL_R 1172
#define IDC_LABEL_UPLEFT 1173
#define IDC_LABEL_UPRIGHT 1174
#define IDC_LABEL_DOWNRIGHT 1175
#define IDC_LABEL_DOWNLEFT 1176
#define IDC_LABEL_FREEZE 1177
#define IDC_LABEL_ASRAM 1178
#define IDC_LABEL_SMAX 1179
#define IDC_LABEL_STURBO 1180
#define IDC_LABEL_ASRAM_TEXT 1181
#define IDC_LABEL_SMAX_TEXT 1182
#define IDC_LABEL_STURBO_TEXT 1183
#define IDC_PORTNUMBLOCK 1184
#define IDC_CLIENTSETTINGSBLOCK 1185
#define IDC_SERVERSETTINGSBLOCK 1186
#define IDC_LABEL_PORTNUM 1187
#define IDC_LABEL_PAUSEINTERVAL 1188
#define IDC_LABEL_PAUSEINTERVAL_TEXT 1189
#define IDC_LABEL_MAXSKIP 1190
#define IDC_LABEL_CHEAT_CODE 1191
#define IDC_LABEL_CHEAT_DESCRIPTION 1192
#define IDC_LABEL_CHEAT_ADDRESS 1193
#define IDC_LABEL_CHEAT_BYTE 1194
#define IDC_LABEL_SERVERADDY 1195
#define IDC_RECORD_NOW 1201
#define IDC_RECORD_RESET 1202
#define IDC_JOY1 1203
#define IDC_JOY2 1204
#define IDC_JOY3 1205
#define IDC_JOY4 1206
#define IDC_JOY5 1207
#define IDC_MOVIE_PATH 1208
#define IDC_BROWSE_MOVIE 1209
#define IDC_MOVIE_DATE 1210
#define IDC_MOVIE_LENGTH 1211
#define IDC_MOVIE_FRAMES 1212
#define IDC_MOVIE_RERECORD 1213
#define IDC_READONLY 1218
#define ID_FILE_EXIT 40001
#define ID_LANGUAGE_ENGLISH 40002
#define ID_LANGUAGE_NEDERLANDS 40003
#define ID_WINDOW_HIDEMENUBAR 40004
#define ID_SOUND_8BIT8000HZMONO 40005
#define ID_SOUND_8BIT11025HZMONO 40006
#define ID_SOUND_8BIT22050HZMONO 40007
#define ID_SOUND_8BIT44100HZMONO 40008
#define ID_SOUND_16BIT8000HZMONO 40009
#define ID_SOUND_16BIT11025HZMONO 40010
#define ID_SOUND_16BIT22050HZMONO 40011
#define ID_SOUND_16BIT44100HZMONO 40012
#define ID_SOUND_8BIT8000HZSTEREO 40013
#define ID_SOUND_8BIT11025HZSTEREO 40014
#define ID_SOUND_8BIT22050HZSTEREO 40015
#define ID_SOUND_8BIT44100HZSTEREO 40016
#define ID_SOUND_16BIT8000HZSTEREO 40017
#define ID_SOUND_16BIT11025HZSTEREO 40018
#define ID_SOUND_16BIT22050HZSTEREO 40019
#define ID_SOUND_16BIT44100HZSTEREO 40020
#define ID_SOUND_NOSOUND 40021
#define ID_OPTIONS_JOYPAD 40022
#define ID_WINDOW_SHOWFPS 40023
#define ID_OPTIONS_DISPLAY 40024
#define ID_FILE_RESET 40025
#define ID_FILE_PAUSE 40026
#define ID_SOUND_INTERPOLATED 40027
#define ID_SOUND_SYNC 40028
#define ID_WINDOW_FULLSCREEN 40029
#define ID_SOUND_16BIT 40030
#define ID_SOUND_STEREO 40031
#define ID_WINDOW_STRETCH 40032
#define ID_SOUND_8000HZ 40033
#define ID_SOUND_11025HZ 40034
#define ID_SOUND_22050HZ 40035
#define ID_SOUND_44100HZ 40036
#define ID_SOUND_30000HZ 40037
#define ID_SOUND_50MS 40038
#define ID_SOUND_100MS 40039
#define ID_SOUND_200MS 40040
#define ID_SOUND_500MS 40041
#define ID_SOUND_1S 40042
#define ID_SOUND_25MS 40043
#define ID_SOUND_2S 40044
#define ID_FILE_SAVE1 40045
#define ID_FILE_SAVE2 40046
#define ID_FILE_SAVE3 40047
#define ID_FILE_SAVE4 40048
#define ID_FILE_SAVE5 40049
#define ID_FILE_SAVE6 40050
#define ID_FILE_SAVE7 40051
#define ID_FILE_SAVE8 40052
#define ID_FILE_SAVE9 40053
#define ID_FILE_LOAD1 40054
#define ID_FILE_LOAD2 40055
#define ID_FILE_LOAD3 40056
#define ID_FILE_LOAD4 40057
#define ID_FILE_LOAD5 40058
#define ID_FILE_LOAD6 40059
#define ID_FILE_LOAD7 40060
#define ID_FILE_LOAD8 40061
#define ID_FILE_LOAD9 40062
#define ID_CHEAT_ENTER 40063
#define ID_CHEAT_SEARCH 40064
#define ID_CHEAT_APPLY 40065
#define ID_FILE_SAVE_SPC_DATA 40066
#define ID_HELP_ABOUT 40067
#define ID_SOUND_OPTIONS 40068
#define ID_OPTIONS_EMULATION 40069
#define ID_OPTIONS_SETTINGS 40070
#define ID_DEBUG_TRACE 40071
#define ID_DEBUG_TRACE_SPC 40072
#define ID_DEBUG_TRACE_SA1 40073
#define ID_DEBUG_TRACE_DSP1 40074
#define ID_DEBUG_FRAME_ADVANCE 40075
#define ID_DEBUG_SNES_STATUS 40076
#define ID_NETPLAY_SERVER 40077
#define ID_NETPLAY_CONNECT 40078
#define ID_NETPLAY_DISCONNECT 40079
#define ID_NETPLAY_OPTIONS 40080
#define ID_NETPLAY_ROM 40081
#define ID_NETPLAY_SYNC 40082
#define ID_NETPLAY_SEND_ROM_ON_CONNECT 40083
#define ID_NETPLAY_SYNC_BY_RESET 40084
#define ID_SOUND_48000HZ 40085
#define ID_SOUND_16000HZ 40086
#define ID_SOUND_35000HZ 40087
#define ID_SOUND_REVERSE_STEREO 40088
#define ID_FILE_SAVE_SRAM_DATA 40089
#define ID_RECENT_DUMMY 40090
#define IDM_LOG_7110 40091
#define IDM_7110_RTC 40092
#define IDM_7110_CACHE 40093
#define IDM_ROM_INFO 40094
#define ID_SOUND_32000HZ 40095
#define ID_TURBO_START 40096
#define ID_TURBO_SELECT 40097
#define ID_TURBO_L 40098
#define ID_TURBO_R 40099
#define ID_TURBO_Y 40100
#define ID_TURBO_X 40101
#define ID_TURBO_B 40102
#define ID_TURBO_A 40103
#define IDM_ENABLE_MULTITAP 40104
#define IDM_MOUSE_TOGGLE 40105
#define IDM_SCOPE_TOGGLE 40106
#define IDM_CATCH_UP_SOUND 40107
#define IDM_GFX_PACKS 40108
#define IDM_JUSTIFIER 40109
#define ID_SCREENSHOT 40110
#define ID_FILE_MOVIE_PLAY 40113
#define ID_FILE_MOVIE_STOP 40114
#define ID_FILE_MOVIE_RECORD 40115
#define ID_FILE_MOVIE_ENABLERECORDING 40116
#define ID_FILE_WRITE_AVI 40116
#define ID_FILE_STOP_AVI 40117
 
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 135
#define _APS_NEXT_COMMAND_VALUE 40118
#define _APS_NEXT_CONTROL_VALUE 1198
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by 0snes9X.rc
//
#define IDR_MENU_US 101
#define IDC_CURSOR_SCOPE 101
#define IDD_SPC7110_CACHE 101
#define IDI_ICON1 101
#define IDR_MENU_NL 102
#define IDC_CURSOR_BLANK 102
#define IDD_SOUND_OPTS 102
#define IDR_SNES9X_ACCELERATORS 103
#define IDD_7110_RTC 103
#define IDD_ROM_INFO 104
#define IDD_ABOUT 105
#define IDD_EMU_SETTINGS 106
#define IDD_OPEN_ROM 107
#define IDD_GFX_PACK 108
#define IDD_NETCONNECT 109
#define IDD_NPOPTIONS 110
#define IDB_OPENFOLDER 111
#define IDD_CHEATER 111
#define IDB_CLOSEDFOLDER 112
#define IDB_CDDRIVE 113
#define IDB_NETDRIVE 114
#define IDB_HARDDRIVE 115
#define IDD_NEWDISPLAY 123
#define IDD_NETPLAYPROGRESS 124
#define IDD_INPUTCONFIG 125
#define IDB_JOYPAD 127
#define IDD_CHEAT_SEARCH 129
#define IDD_DIALOG1 130
#define IDD_CHEAT_FROM_SEARCH 131
#define IDB_PAD 133
#define IDD_OPENMOVIE 134
#define IDD_CREATEMOVIE 135
#define IDC_DRIVER 1001
#define IDC_BUFLEN 1002
#define IDC_RATE 1003
#define IDC_MIX 1004
#define IDC_16BIT 1005
#define IDC_STEREO 1006
#define IDC_REV_STEREO 1007
#define IDC_LINEAR_INTER 1008
#define IDC_SYNC_TO_SOUND_CPU 1009
#define IDC_ENVX 1010
#define IDC_ECHO 1011
#define IDC_CACHING 1012
#define IDC_MASTER_VOL 1013
#define IDC_SPC700ON 1014
#define IDC_ANTIRES 1015
#define IDC_MUTE 1016
#define IDC_SKIP_TYPE 1017
#define IDC_SCROLLBAR1 1018
#define IDC_VRAM_DISPLAY 1019
#define IDC_ADDRESS 1020
#define IDC_SPC7110_ALL 1021
#define IDC_SPC7110_SOME 1022
#define IDC_SPC7110_FILE 1023
#define IDC_RTC_D8 1024
#define IDC_RTC_D4 1025
#define IDC_RTC_D2 1026
#define IDC_RTC_D1 1027
#define IDC_RTC_E8 1028
#define IDC_RTC_E4 1029
#define IDC_RTC_E2 1030
#define IDC_RTC_E1 1031
#define IDC_RTC_F8 1032
#define IDC_RTC_F4 1033
#define IDC_RTC_F2 1034
#define IDC_RTC_F1 1035
#define IDC_DAY 1036
#define IDC_YEAR 1037
#define IDC_MONTH 1038
#define IDC_HOUR 1039
#define IDC_MINUTE 1040
#define IDC_SECOND 1041
#define IDC_LBLMONTH 1042
#define IDC_LBLYEAR 1043
#define IDC_LBLDAY 1044
#define IDC_LBLHOUR 1045
#define IDC_LBLMINUTE 1046
#define IDC_LBLSECOND 1047
#define IDC_CACHE_MB 1048
#define IDC_SPIN_CACHE 1049
#define IDC_ROM_DATA 1051
#define IDC_WARNINGS 1052
#define IDC_DISCLAIMER 1053
#define IDC_FREEZE_FOLDER 1054
#define IDC_BROWSE 1055
#define IDC_CANCEL 1056
#define IDC_AUTO_SAVE_DELAY 1057
#define IDC_MAX_SKIP 1058
#define IDC_TURBO_SKIP 1059
#define IDC_TOGGLE_TURBO 1060
#define IDC_SRAM_SPIN 1061
#define IDC_SPIN_MAX_SKIP 1062
#define IDC_SPIN_TURBO_SKIP 1063
#define IDC_ROM_DIR 1064
#define IDC_INTERLEAVE 1065
#define IDC_VIDEO_MODE 1066
#define IDC_HEADER 1067
#define IDC_ROMLIST 1068
#define IDC_MEM_TYPE 1069
#define IDC_STAR_OCEAN 1070
#define IDC_SO_BROWSE 1071
#define IDC_FEOEZ 1072
#define IDC_FEOEZ_BROWSE 1073
#define IDC_MDH 1074
#define IDC_MDH_BROWSE 1075
#define IDC_SPL4 1076
#define IDC_SPL4_BROWSE 1077
#define IDC_SJNS 1078
#define IDC_FEOEZ_SJNS_BROWSE 1079
#define IDC_SFA2 1080
#define IDC_SFA2_BROWSE 1081
#define IDC_SFA2E 1082
#define IDC_SFA2E_BROWSE 1083
#define IDC_SFZ2 1084
#define IDC_SFZ2_BROWSE 1085
#define IDC_HOSTNAME 1086
#define IDC_PORTNUMBER 1087
#define IDC_CLEARHISTORY 1088
#define IDC_STATIC2 1089
#define IDC_EDIT1 1090
#define IDC_UP 1090
#define IDC_VALUE_ENTER 1090
#define IDC_MOVIE_METADATA 1090
#define IDC_PAUSEINTERVAL 1091
#define IDC_UPRIGHT 1091
#define IDC_MAXSKIP 1092
#define IDC_PAUSESPIN 1093
#define IDC_DWNRIGHT 1093
#define IDC_SYNCBYRESET 1094
#define IDC_DOWN 1094
#define IDC_SENDROM 1095
#define IDC_DWNLEFT 1095
#define IDC_ACTASSERVER 1096
#define IDC_LEFT 1096
#define IDC_MAXSPIN 1097
#define IDC_UPLEFT 1097
#define IDC_SELECT 1098
#define IDC_PORTNUMBERA 1099
#define IDC_START 1099
#define IDC_TESTMODE 1100
#define IDC_L 1100
#define IDC_VIDEOLIST 1101
#define IDC_R 1101
#define IDC_SELECT2 1101
#define IDC_VIDMODELIST 1102
#define IDC_Y 1102
#define IDC_SETDMODE 1103
#define IDC_B 1103
#define IDC_A 1104
#define IDC_X 1105
#define IDC_RIGHT 1106
#define IDC_SHOWFPS 1108
#define IDC_STRETCH 1109
#define IDC_FULLSCREEN 1110
#define IDC_BILINEARMD7 1111
#define IDC_RENDER16BIT 1112
#define IDC_TRANS 1113
#define IDC_HIRES 1114
#define IDC_CHEAT_CODE 1115
#define IDC_FILTERBOX 1116
#define IDC_AUTOFRAME 1117
#define IDC_LIMITFRAMES 1118
#define IDC_FRAMERATESKIPSLIDER 1120
#define IDC_TOGGLE 1121
#define IDC_DBLBUFFER 1122
#define IDC_CURRMODE 1123
#define IDC_DELETE_CHEAT 1124
#define IDC_NPPROGRESS 1124
#define IDC_VIDEOCARD 1124
#define IDC_UPDATE_CHEAT 1125
#define IDC_JPCOMBO 1125
#define IDC_CLEAR_CHEATS 1126
#define IDC_JPTOGGLE 1126
#define IDC_CHEAT_DESCRIPTION 1127
#define IDC_KEYBOARD 1127
#define IDC_CHEAT_ADDRESS 1128
#define IDC_CHEAT_BYTE 1129
#define IDC_ADD_CHEAT 1130
#define IDC_CHEAT_LIST 1131
#define IDC_PICTURE 1132
#define IDC_ADDYS 1133
#define IDC_OK 1134
#define IDC_C_SEARCH 1134
#define IDC_RED 1135
#define IDC_C_ADD 1135
#define IDC_BLUE 1136
#define IDC_C_RESET 1136
#define IDC_LABEL_BLUE 1136
#define IDC_1_BYTE 1137
#define IDC_2_BYTE 1138
#define IDC_3_BYTE 1139
#define IDC_4_BYTE 1140
#define IDC_LESS_THAN 1141
#define IDC_GREATER_THAN 1142
#define IDC_LESS_THAN_EQUAL 1143
#define IDC_GREATER_THAN_EQUAL 1144
#define IDC_EQUAL 1145
#define IDC_NOT_EQUAL 1146
#define IDC_PREV 1147
#define IDC_ENTERED 1148
#define IDC_UNSIGNED 1149
#define IDC_SIGNED 1150
#define IDC_HEX 1151
#define IDC_ENTER_LABEL 1152
#define IDC_DIAGTOGGLE 1153
#define IDC_UNDO 1154
#define IDC_COMBO1 1155
#define IDC_NC_ADDRESS 1156
#define IDC_NC_CURRVAL 1157
#define IDC_NC_PREVVAL 1158
#define IDC_NC_NEWVAL 1159
#define IDC_NC_DESC 1160
#define IDC_LABEL_UP 1161
#define IDC_LABEL_LEFT 1162
#define IDC_LABEL_DOWN 1163
#define IDC_LABEL_RIGHT 1164
#define IDC_LABEL_B 1165
#define IDC_LABEL_A 1166
#define IDC_LABEL_Y 1167
#define IDC_LABEL_X 1168
#define IDC_LABEL_START 1169
#define IDC_LABEL_SELECT 1170
#define IDC_LABEL_L 1171
#define IDC_LABEL_R 1172
#define IDC_LABEL_UPLEFT 1173
#define IDC_LABEL_UPRIGHT 1174
#define IDC_LABEL_DOWNRIGHT 1175
#define IDC_LABEL_DOWNLEFT 1176
#define IDC_LABEL_FREEZE 1177
#define IDC_LABEL_ASRAM 1178
#define IDC_LABEL_SMAX 1179
#define IDC_LABEL_STURBO 1180
#define IDC_LABEL_ASRAM_TEXT 1181
#define IDC_LABEL_SMAX_TEXT 1182
#define IDC_LABEL_STURBO_TEXT 1183
#define IDC_PORTNUMBLOCK 1184
#define IDC_CLIENTSETTINGSBLOCK 1185
#define IDC_SERVERSETTINGSBLOCK 1186
#define IDC_LABEL_PORTNUM 1187
#define IDC_LABEL_PAUSEINTERVAL 1188
#define IDC_LABEL_PAUSEINTERVAL_TEXT 1189
#define IDC_LABEL_MAXSKIP 1190
#define IDC_LABEL_CHEAT_CODE 1191
#define IDC_LABEL_CHEAT_DESCRIPTION 1192
#define IDC_LABEL_CHEAT_ADDRESS 1193
#define IDC_LABEL_CHEAT_BYTE 1194
#define IDC_LABEL_SERVERADDY 1195
#define IDC_RECORD_NOW 1201
#define IDC_RECORD_RESET 1202
#define IDC_JOY1 1203
#define IDC_JOY2 1204
#define IDC_JOY3 1205
#define IDC_JOY4 1206
#define IDC_JOY5 1207
#define IDC_MOVIE_PATH 1208
#define IDC_BROWSE_MOVIE 1209
#define IDC_MOVIE_DATE 1210
#define IDC_MOVIE_LENGTH 1211
#define IDC_MOVIE_FRAMES 1212
#define IDC_MOVIE_RERECORD 1213
#define IDC_READONLY 1218
#define ID_FILE_EXIT 40001
#define ID_LANGUAGE_ENGLISH 40002
#define ID_LANGUAGE_NEDERLANDS 40003
#define ID_WINDOW_HIDEMENUBAR 40004
#define ID_SOUND_8BIT8000HZMONO 40005
#define ID_SOUND_8BIT11025HZMONO 40006
#define ID_SOUND_8BIT22050HZMONO 40007
#define ID_SOUND_8BIT44100HZMONO 40008
#define ID_SOUND_16BIT8000HZMONO 40009
#define ID_SOUND_16BIT11025HZMONO 40010
#define ID_SOUND_16BIT22050HZMONO 40011
#define ID_SOUND_16BIT44100HZMONO 40012
#define ID_SOUND_8BIT8000HZSTEREO 40013
#define ID_SOUND_8BIT11025HZSTEREO 40014
#define ID_SOUND_8BIT22050HZSTEREO 40015
#define ID_SOUND_8BIT44100HZSTEREO 40016
#define ID_SOUND_16BIT8000HZSTEREO 40017
#define ID_SOUND_16BIT11025HZSTEREO 40018
#define ID_SOUND_16BIT22050HZSTEREO 40019
#define ID_SOUND_16BIT44100HZSTEREO 40020
#define ID_SOUND_NOSOUND 40021
#define ID_OPTIONS_JOYPAD 40022
#define ID_WINDOW_SHOWFPS 40023
#define ID_OPTIONS_DISPLAY 40024
#define ID_FILE_RESET 40025
#define ID_FILE_PAUSE 40026
#define ID_SOUND_INTERPOLATED 40027
#define ID_SOUND_SYNC 40028
#define ID_WINDOW_FULLSCREEN 40029
#define ID_SOUND_16BIT 40030
#define ID_SOUND_STEREO 40031
#define ID_WINDOW_STRETCH 40032
#define ID_SOUND_8000HZ 40033
#define ID_SOUND_11025HZ 40034
#define ID_SOUND_22050HZ 40035
#define ID_SOUND_44100HZ 40036
#define ID_SOUND_30000HZ 40037
#define ID_SOUND_50MS 40038
#define ID_SOUND_100MS 40039
#define ID_SOUND_200MS 40040
#define ID_SOUND_500MS 40041
#define ID_SOUND_1S 40042
#define ID_SOUND_25MS 40043
#define ID_SOUND_2S 40044
#define ID_FILE_SAVE1 40045
#define ID_FILE_SAVE2 40046
#define ID_FILE_SAVE3 40047
#define ID_FILE_SAVE4 40048
#define ID_FILE_SAVE5 40049
#define ID_FILE_SAVE6 40050
#define ID_FILE_SAVE7 40051
#define ID_FILE_SAVE8 40052
#define ID_FILE_SAVE9 40053
#define ID_FILE_LOAD1 40054
#define ID_FILE_LOAD2 40055
#define ID_FILE_LOAD3 40056
#define ID_FILE_LOAD4 40057
#define ID_FILE_LOAD5 40058
#define ID_FILE_LOAD6 40059
#define ID_FILE_LOAD7 40060
#define ID_FILE_LOAD8 40061
#define ID_FILE_LOAD9 40062
#define ID_CHEAT_ENTER 40063
#define ID_CHEAT_SEARCH 40064
#define ID_CHEAT_APPLY 40065
#define ID_FILE_SAVE_SPC_DATA 40066
#define ID_HELP_ABOUT 40067
#define ID_SOUND_OPTIONS 40068
#define ID_OPTIONS_EMULATION 40069
#define ID_OPTIONS_SETTINGS 40070
#define ID_DEBUG_TRACE 40071
#define ID_DEBUG_TRACE_SPC 40072
#define ID_DEBUG_TRACE_SA1 40073
#define ID_DEBUG_TRACE_DSP1 40074
#define ID_DEBUG_FRAME_ADVANCE 40075
#define ID_DEBUG_SNES_STATUS 40076
#define ID_NETPLAY_SERVER 40077
#define ID_NETPLAY_CONNECT 40078
#define ID_NETPLAY_DISCONNECT 40079
#define ID_NETPLAY_OPTIONS 40080
#define ID_NETPLAY_ROM 40081
#define ID_NETPLAY_SYNC 40082
#define ID_NETPLAY_SEND_ROM_ON_CONNECT 40083
#define ID_NETPLAY_SYNC_BY_RESET 40084
#define ID_SOUND_48000HZ 40085
#define ID_SOUND_16000HZ 40086
#define ID_SOUND_35000HZ 40087
#define ID_SOUND_REVERSE_STEREO 40088
#define ID_FILE_SAVE_SRAM_DATA 40089
#define ID_RECENT_DUMMY 40090
#define IDM_LOG_7110 40091
#define IDM_7110_RTC 40092
#define IDM_7110_CACHE 40093
#define IDM_ROM_INFO 40094
#define ID_SOUND_32000HZ 40095
#define ID_TURBO_START 40096
#define ID_TURBO_SELECT 40097
#define ID_TURBO_L 40098
#define ID_TURBO_R 40099
#define ID_TURBO_Y 40100
#define ID_TURBO_X 40101
#define ID_TURBO_B 40102
#define ID_TURBO_A 40103
#define IDM_ENABLE_MULTITAP 40104
#define IDM_MOUSE_TOGGLE 40105
#define IDM_SCOPE_TOGGLE 40106
#define IDM_CATCH_UP_SOUND 40107
#define IDM_GFX_PACKS 40108
#define IDM_JUSTIFIER 40109
#define ID_SCREENSHOT 40110
#define ID_FILE_MOVIE_PLAY 40113
#define ID_FILE_MOVIE_STOP 40114
#define ID_FILE_MOVIE_RECORD 40115
#define ID_FILE_MOVIE_ENABLERECORDING 40116
#define ID_FILE_WRITE_AVI 40116
#define ID_FILE_STOP_AVI 40117
 
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 135
#define _APS_NEXT_COMMAND_VALUE 40118
#define _APS_NEXT_CONTROL_VALUE 1198
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
linux/InputCustom.h
1,15 → 1,15
#ifndef CUSTCTRL_INCLUDED
#define CUSTCTRL_INCLUDED
 
#ifdef __cplusplus
extern "C" {
#endif
 
void InitInputCustomControl(void);
HWND CreateInputCustom(HWND hwndParent);
 
#ifdef __cplusplus
}
#endif
 
#ifndef CUSTCTRL_INCLUDED
#define CUSTCTRL_INCLUDED
 
#ifdef __cplusplus
extern "C" {
#endif
 
void InitInputCustomControl(void);
HWND CreateInputCustom(HWND hwndParent);
 
#ifdef __cplusplus
}
#endif
 
#endif
\ No newline at end of file
linux/directx.cpp
370,15 → 370,15
 
ZeroMemory (&ddsd, sizeof (ddsd));
ddsd.dwSize = sizeof (ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
if(GUI.VideoMemory)
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
if(GUI.VideoMemory)
{
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
}
else
{
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
}
else
{
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
}
ddsd.dwWidth = SNES_WIDTH * 2;
ddsd.dwHeight = SNES_HEIGHT_EXTENDED * 2;
 
linux/wsnes9x.cpp
106,8 → 106,8
#include "snes9x/netplay.h"
#include "snes9x/apu.h"
#include "snes9x/movie.h"
#include "AVIOutput.h"
#include "InputCustom.h"
#include "AVIOutput.h"
#include "InputCustom.h"
#include <vector>
 
#include <TCHAR.H>
320,14 → 320,14
uint8 Opts;
wchar_t Metadata[MOVIE_MAX_METADATA];
};
struct dMode
{
long height;
long width;
long depth;
int status;
};
 
struct dMode
{
long height;
long width;
long depth;
int status;
};
 
std::vector<dMode> dm;
/*****************************************************************************/
/* WinProc */
549,9 → 549,9
{
int i;
//bool showFPS;
static char InfoString [100];
static char InfoString [100];
#ifdef NETPLAY_SUPPORT
char hostname [100];
char hostname [100];
#endif
switch (uMsg)
{
2137,7 → 2137,7
SetKey( "NetPlay Max Frame Skip", NetPlay.MaxFrameSkip);
SetKey( "NetPlay Max Behind Frame Count", NetPlay.MaxBehindFrameCount);
#endif
SetKey( "Bi-Linear Filter Mode7", Settings.Mode7Interpolate);
SetKey( "Bi-Linear Filter Mode7", Settings.Mode7Interpolate);
SetKey( "Use Hardware Video Memory",GUI.VideoMemory);
 
RegSetValueEx (hKey, TEXT("StarOcean"), 0, REG_SZ,
2192,29 → 2192,29
}
}
 
static void WinSetDefaultValues ()
static void WinSetDefaultValues ()
 
{
HKEY hKey;
char temp[4];
strcpy(temp,"C:\\");
if (RegCreateKeyEx (HKEY_CURRENT_USER,
S9X_REG_KEY_BASE TEXT("\\") S9X_REG_KEY_VERSION, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
NULL) == ERROR_SUCCESS)
RegCloseKey(hKey);
if(RegOpenKeyEx(HKEY_CURRENT_USER, MY_REG_KEY, 0, KEY_ALL_ACCESS, &hKey)==ERROR_SUCCESS)
{
if(RegQueryValueEx(hKey,TEXT("Last Directory"),NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
{
RegSetValueEx(hKey,TEXT("Last Directory"),NULL,REG_SZ,(uint8*)temp,strlen(temp)+1);
}
RegCloseKey(hKey);
}
else
 
 
{
HKEY hKey;
char temp[4];
strcpy(temp,"C:\\");
if (RegCreateKeyEx (HKEY_CURRENT_USER,
S9X_REG_KEY_BASE TEXT("\\") S9X_REG_KEY_VERSION, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
NULL) == ERROR_SUCCESS)
RegCloseKey(hKey);
if(RegOpenKeyEx(HKEY_CURRENT_USER, MY_REG_KEY, 0, KEY_ALL_ACCESS, &hKey)==ERROR_SUCCESS)
{
if(RegQueryValueEx(hKey,TEXT("Last Directory"),NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
{
RegSetValueEx(hKey,TEXT("Last Directory"),NULL,REG_SZ,(uint8*)temp,strlen(temp)+1);
}
RegCloseKey(hKey);
}
else
 
 
 
GUI.IgnoreNextMouseMove = false;
GUI.window_size.left = 0;
GUI.window_size.right = 264 + SNES_WIDTH;
2230,7 → 2230,7
GUI.Stretch = false;
GUI.PausedFramesBeforeMutingSound = 20;
GUI.FlipCounter = 0;
GUI.NumFlipFrames = 1;
GUI.NumFlipFrames = 1;
GUI.VideoMemory = false;
WinDeleteRecentGamesList ();
 
2354,7 → 2354,7
if (RegOpenKeyEx (HKEY_CURRENT_USER,
S9X_REG_KEY_BASE TEXT("\\") S9X_REG_KEY_VERSION,
0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
{
 
GetKey( "Language", GUI.Language);
GetKey( "Stereo Sound", Settings.Stereo);
2411,7 → 2411,7
GetKeyDef( "NetPlay Send ROM On Connect", NPServer.SendROMImageOnConnect, false);
GetKeyDef( "NetPlay Max Frame Skip", NetPlay.MaxFrameSkip, 10);
GetKeyDef( "NetPlay Max Behind Frame Count", NetPlay.MaxBehindFrameCount, 10);
#endif
#endif
GetKeyDef( "Use Hardware Video Memory",GUI.VideoMemory, false);
cbData = _MAX_PATH + 1;
RegQueryValueEx (hKey, TEXT("Freeze File Directory"), 0, NULL,
6773,7 → 6773,7
#endif
HRESULT CALLBACK EnumModesCallback( LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
{
char depmode[80];
char depmode[80];
char s[80];
dMode curmode;
HWND hDlg = (HWND)lpContext;
6799,35 → 6799,35
 
 
 
curmode.width=lpDDSurfaceDesc->dwWidth;
curmode.height=lpDDSurfaceDesc->dwHeight;
curmode.depth=lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount;
if(RegQueryValueEx(hKey,depmode,0,&type,val,&nuv)==ERROR_SUCCESS)
{
//sprintf(s,"%d %d %d %d",val[0],val[1],val[2],val[3]);
//MessageBox(hDlg,s,temp,MB_OK);
switch(val[0])
{
case 1:
strcpy(s,"Failed");
curmode.status=1;
break;
case 3:
strcpy(s,"Works");
curmode.status=3;
break;
default:
strcpy(s,"Untested");
curmode.status=0;
}
}
else
{
strcpy(s,"Untested");
curmode.status=0;
//MessageBox(hDlg,s,temp,MB_OK);
}
dm.push_back(curmode);
curmode.width=lpDDSurfaceDesc->dwWidth;
curmode.height=lpDDSurfaceDesc->dwHeight;
curmode.depth=lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount;
if(RegQueryValueEx(hKey,depmode,0,&type,val,&nuv)==ERROR_SUCCESS)
{
//sprintf(s,"%d %d %d %d",val[0],val[1],val[2],val[3]);
//MessageBox(hDlg,s,temp,MB_OK);
switch(val[0])
{
case 1:
strcpy(s,"Failed");
curmode.status=1;
break;
case 3:
strcpy(s,"Works");
curmode.status=3;
break;
default:
strcpy(s,"Untested");
curmode.status=0;
}
}
else
{
strcpy(s,"Untested");
curmode.status=0;
//MessageBox(hDlg,s,temp,MB_OK);
}
dm.push_back(curmode);
LVITEM lvi;
ZeroMemory(&lvi, sizeof(LVITEM));
lvi.iItem=dm.size();
6944,11 → 6944,11
if(GUI.FullScreen)
{
SendDlgItemMessage(hDlg, IDC_FULLSCREEN, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
}
if(GUI.VideoMemory)
{
SendDlgItemMessage(hDlg,IDC_VIDEOCARD, BM_SETCHECK, (WPARAM)BST_CHECKED,0);
}
if(GUI.VideoMemory)
{
SendDlgItemMessage(hDlg,IDC_VIDEOCARD, BM_SETCHECK, (WPARAM)BST_CHECKED,0);
}
if(Settings.DisplayFrameRate)
{
SendDlgItemMessage(hDlg, IDC_SHOWFPS, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
7012,11 → 7012,11
{
EnableWindow(GetDlgItem(hDlg,IDC_FILTERBOX),false);
EnableWindow(GetDlgItem(hDlg,IDC_HIRES),false);
}
 
}
 
 
 
 
 
 
 
LVCOLUMN col;
7130,7 → 7130,7
 
case IDOK:
Settings.SixteenBit = IsDlgButtonChecked(hDlg, IDC_RENDER16BIT);
Settings.Transparency = IsDlgButtonChecked(hDlg, IDC_TRANS);
Settings.Transparency = IsDlgButtonChecked(hDlg, IDC_TRANS);
GUI.VideoMemory = (bool)(IsDlgButtonChecked(hDlg,IDC_VIDEOCARD)==BST_CHECKED);
if(GUI.Width >= 512 && GUI.Height >= 478)
{
7378,299 → 7378,299
 
return false;
}
#endif
int CALLBACK DlgInputConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HBITMAP hBmp;
char temp[256];
short C;
int i, which;
static int index=0;
 
 
static SJoypad pads[5];
 
 
//HBRUSH g_hbrBackground;
 
InitInputCustomControl();
switch(msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint (hDlg, &ps);
if(hBmp)
{
BITMAP bmp;
ZeroMemory(&bmp, sizeof(BITMAP));
RECT r;
GetClientRect(hDlg, &r);
HDC hdc=GetDC(hDlg);
HDC hDCbmp=CreateCompatibleDC(hdc);
GetObject(hBmp, sizeof(BITMAP), &bmp);
HBITMAP hOldBmp=(HBITMAP)SelectObject(hDCbmp, hBmp);
StretchBlt(hdc, 0,0,r.right,r.bottom,hDCbmp,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
SelectObject(hDCbmp, hOldBmp);
DeleteDC(hDCbmp);
ReleaseDC(hDlg, hdc);
}
 
EndPaint (hDlg, &ps);
}
return true;
case WM_INITDIALOG:
SetWindowText(hDlg,INPUTCONFIG_TITLE);
SetDlgItemText(hDlg,IDC_JPTOGGLE,INPUTCONFIG_JPTOGGLE);
SetDlgItemText(hDlg,IDC_OK,BUTTON_OK);
SetDlgItemText(hDlg,IDC_CANCEL,BUTTON_CANCEL);
SetDlgItemText(hDlg,IDC_DIAGTOGGLE,INPUTCONFIG_DIAGTOGGLE);
SetDlgItemText(hDlg,IDC_LABEL_UP,INPUTCONFIG_LABEL_UP);
SetDlgItemText(hDlg,IDC_LABEL_DOWN,INPUTCONFIG_LABEL_DOWN);
SetDlgItemText(hDlg,IDC_LABEL_LEFT,INPUTCONFIG_LABEL_LEFT);
SetDlgItemText(hDlg,IDC_LABEL_RIGHT,INPUTCONFIG_LABEL_RIGHT);
SetDlgItemText(hDlg,IDC_LABEL_A,INPUTCONFIG_LABEL_A);
SetDlgItemText(hDlg,IDC_LABEL_B,INPUTCONFIG_LABEL_B);
SetDlgItemText(hDlg,IDC_LABEL_X,INPUTCONFIG_LABEL_X);
SetDlgItemText(hDlg,IDC_LABEL_Y,INPUTCONFIG_LABEL_Y);
SetDlgItemText(hDlg,IDC_LABEL_L,INPUTCONFIG_LABEL_L);
SetDlgItemText(hDlg,IDC_LABEL_R,INPUTCONFIG_LABEL_R);
SetDlgItemText(hDlg,IDC_LABEL_START,INPUTCONFIG_LABEL_START);
SetDlgItemText(hDlg,IDC_LABEL_SELECT,INPUTCONFIG_LABEL_SELECT);
SetDlgItemText(hDlg,IDC_LABEL_UPRIGHT,INPUTCONFIG_LABEL_UPRIGHT);
SetDlgItemText(hDlg,IDC_LABEL_UPLEFT,INPUTCONFIG_LABEL_UPLEFT);
SetDlgItemText(hDlg,IDC_LABEL_DOWNRIGHT,INPUTCONFIG_LABEL_DOWNRIGHT);
SetDlgItemText(hDlg,IDC_LABEL_DOWNRIGHT,INPUTCONFIG_LABEL_DOWNRIGHT);
SetDlgItemText(hDlg,IDC_LABEL_BLUE,INPUTCONFIG_LABEL_BLUE);
 
hBmp=(HBITMAP)LoadImage(NULL, TEXT("PBortas.bmp"), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
memcpy(pads, Joypad, 5*sizeof(SJoypad));
for( i=0;i<256;i++)
{
GetAsyncKeyState(i);
}
for( C = 0; C != 16; C ++)
JoystickF[C].Attached = joyGetDevCaps( JOYSTICKID1+C, &JoystickF[C].Caps, sizeof( JOYCAPS)) == JOYERR_NOERROR;
for (i=1;i<6;i++)
{
 
sprintf(temp,INPUTCONFIG_JPCOMBO,i);
SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)temp);
}
 
SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_SETCURSEL,(WPARAM)0,0);
if(Joypad[index].Enabled)
{
SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK,(WPARAM)BST_CHECKED,0);
}
else
{
SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK,(WPARAM)BST_UNCHECKED,0);
}
SendDlgItemMessage(hDlg,IDC_UP,WM_USER+44,Joypad[index].Up,0);
SendDlgItemMessage(hDlg,IDC_LEFT,WM_USER+44,Joypad[index].Left,0);
SendDlgItemMessage(hDlg,IDC_DOWN,WM_USER+44,Joypad[index].Down,0);
SendDlgItemMessage(hDlg,IDC_RIGHT,WM_USER+44,Joypad[index].Right,0);
SendDlgItemMessage(hDlg,IDC_A,WM_USER+44,Joypad[index].A,0);
SendDlgItemMessage(hDlg,IDC_B,WM_USER+44,Joypad[index].B,0);
SendDlgItemMessage(hDlg,IDC_X,WM_USER+44,Joypad[index].X,0);
SendDlgItemMessage(hDlg,IDC_Y,WM_USER+44,Joypad[index].Y,0);
SendDlgItemMessage(hDlg,IDC_L,WM_USER+44,Joypad[index].L,0);
SendDlgItemMessage(hDlg,IDC_R,WM_USER+44,Joypad[index].R,0);
SendDlgItemMessage(hDlg,IDC_START,WM_USER+44,Joypad[index].Start,0);
SendDlgItemMessage(hDlg,IDC_SELECT,WM_USER+44,Joypad[index].Select,0);
SendDlgItemMessage(hDlg,IDC_UPLEFT,WM_USER+44,Joypad[index].Left_Up,0);
SendDlgItemMessage(hDlg,IDC_UPRIGHT,WM_USER+44,Joypad[index].Right_Up,0);
SendDlgItemMessage(hDlg,IDC_DWNLEFT,WM_USER+44,Joypad[index].Left_Down,0);
SendDlgItemMessage(hDlg,IDC_DWNRIGHT,WM_USER+44,Joypad[index].Right_Down,0);
 
 
SetFocus(GetDlgItem(hDlg,IDC_JPCOMBO));
 
 
return true;
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
return TRUE;
case WM_USER+43:
//MessageBox(hDlg,"USER+43 CAUGHT","moo",MB_OK);
which = GetDlgCtrlID((HWND)lParam);
switch(which)
{
case IDC_UP:
Joypad[index].Up = wParam;
 
break;
case IDC_DOWN:
Joypad[index].Down = wParam;
 
break;
case IDC_LEFT:
Joypad[index].Left = wParam;
 
break;
case IDC_RIGHT:
Joypad[index].Right = wParam;
 
break;
case IDC_A:
Joypad[index].A = wParam;
 
break;
case IDC_B:
Joypad[index].B = wParam;
 
break;
case IDC_X:
Joypad[index].X = wParam;
 
break;
case IDC_Y:
Joypad[index].Y = wParam;
 
break;
case IDC_L:
Joypad[index].L = wParam;
break;
 
case IDC_R:
Joypad[index].R = wParam;
 
break;
case IDC_SELECT:
Joypad[index].Select = wParam;
 
break;
case IDC_START:
Joypad[index].Start = wParam;
 
break;
case IDC_UPLEFT:
Joypad[index].Left_Up = wParam;
 
break;
case IDC_UPRIGHT:
Joypad[index].Right_Up = wParam;
 
break;
case IDC_DWNLEFT:
Joypad[index].Left_Down = wParam;
 
case IDC_DWNRIGHT:
Joypad[index].Right_Down = wParam;
 
break;
 
}
SendDlgItemMessage(hDlg,IDC_UP,WM_USER+44,Joypad[index].Up,0);
SendDlgItemMessage(hDlg,IDC_LEFT,WM_USER+44,Joypad[index].Left,0);
SendDlgItemMessage(hDlg,IDC_DOWN,WM_USER+44,Joypad[index].Down,0);
SendDlgItemMessage(hDlg,IDC_RIGHT,WM_USER+44,Joypad[index].Right,0);
SendDlgItemMessage(hDlg,IDC_A,WM_USER+44,Joypad[index].A,0);
SendDlgItemMessage(hDlg,IDC_B,WM_USER+44,Joypad[index].B,0);
SendDlgItemMessage(hDlg,IDC_X,WM_USER+44,Joypad[index].X,0);
SendDlgItemMessage(hDlg,IDC_Y,WM_USER+44,Joypad[index].Y,0);
SendDlgItemMessage(hDlg,IDC_L,WM_USER+44,Joypad[index].L,0);
SendDlgItemMessage(hDlg,IDC_R,WM_USER+44,Joypad[index].R,0);
SendDlgItemMessage(hDlg,IDC_START,WM_USER+44,Joypad[index].Start,0);
SendDlgItemMessage(hDlg,IDC_SELECT,WM_USER+44,Joypad[index].Select,0);
SendDlgItemMessage(hDlg,IDC_UPLEFT,WM_USER+44,Joypad[index].Left_Up,0);
SendDlgItemMessage(hDlg,IDC_UPRIGHT,WM_USER+44,Joypad[index].Right_Up,0);
SendDlgItemMessage(hDlg,IDC_DWNLEFT,WM_USER+44,Joypad[index].Left_Down,0);
SendDlgItemMessage(hDlg,IDC_DWNRIGHT,WM_USER+44,Joypad[index].Right_Down,0);
PostMessage(hDlg,WM_NEXTDLGCTL,0,0);
return true;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDCANCEL:
memcpy(Joypad, pads, 5*sizeof(SJoypad));
EndDialog(hDlg,0);
if(hBmp)
{
DeleteObject(hBmp);
hBmp=NULL;
}
break;
case IDOK:
EndDialog(hDlg,0);
if(hBmp)
{
DeleteObject(hBmp);
hBmp=NULL;
}
break;
case IDC_JPTOGGLE:
index = SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_GETCURSEL,0,0);
Joypad[index].Enabled=IsDlgButtonChecked(hDlg,IDC_JPTOGGLE);
break;
case IDC_DIAGTOGGLE:
if(IsWindowEnabled(GetDlgItem(hDlg,IDC_UPLEFT))==0)
{
 
EnableWindow(GetDlgItem(hDlg,IDC_UPLEFT),TRUE);
 
EnableWindow(GetDlgItem(hDlg,IDC_UPRIGHT),TRUE);
 
EnableWindow(GetDlgItem(hDlg,IDC_DWNLEFT),TRUE);
 
EnableWindow(GetDlgItem(hDlg,IDC_DWNRIGHT),TRUE);
 
}
else
{
 
EnableWindow(GetDlgItem(hDlg,IDC_UPLEFT),FALSE);
 
EnableWindow(GetDlgItem(hDlg,IDC_UPRIGHT),FALSE);
 
EnableWindow(GetDlgItem(hDlg,IDC_DWNLEFT),FALSE);
 
EnableWindow(GetDlgItem(hDlg,IDC_DWNRIGHT),FALSE);
}
break;
}
switch(HIWORD(wParam))
{
case CBN_SELCHANGE:
index = SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_GETCURSEL,0,0);
SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_SETCURSEL,(WPARAM)index,0);
if(Joypad[index].Enabled)
{
SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK,(WPARAM)BST_CHECKED,0);
}
else
{
SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK,(WPARAM)BST_UNCHECKED,0);
}
SendDlgItemMessage(hDlg,IDC_UP,WM_USER+44,Joypad[index].Up,0);
SendDlgItemMessage(hDlg,IDC_LEFT,WM_USER+44,Joypad[index].Left,0);
SendDlgItemMessage(hDlg,IDC_DOWN,WM_USER+44,Joypad[index].Down,0);
SendDlgItemMessage(hDlg,IDC_RIGHT,WM_USER+44,Joypad[index].Right,0);
SendDlgItemMessage(hDlg,IDC_A,WM_USER+44,Joypad[index].A,0);
SendDlgItemMessage(hDlg,IDC_B,WM_USER+44,Joypad[index].B,0);
SendDlgItemMessage(hDlg,IDC_X,WM_USER+44,Joypad[index].X,0);
SendDlgItemMessage(hDlg,IDC_Y,WM_USER+44,Joypad[index].Y,0);
SendDlgItemMessage(hDlg,IDC_L,WM_USER+44,Joypad[index].L,0);
SendDlgItemMessage(hDlg,IDC_R,WM_USER+44,Joypad[index].R,0);
SendDlgItemMessage(hDlg,IDC_START,WM_USER+44,Joypad[index].Start,0);
SendDlgItemMessage(hDlg,IDC_SELECT,WM_USER+44,Joypad[index].Select,0);
SendDlgItemMessage(hDlg,IDC_UPLEFT,WM_USER+44,Joypad[index].Left_Up,0);
SendDlgItemMessage(hDlg,IDC_UPRIGHT,WM_USER+44,Joypad[index].Right_Up,0);
SendDlgItemMessage(hDlg,IDC_DWNLEFT,WM_USER+44,Joypad[index].Left_Down,0);
SendDlgItemMessage(hDlg,IDC_DWNRIGHT,WM_USER+44,Joypad[index].Right_Down,0);
break;
}
return FALSE;
 
}
 
return FALSE;
}
 
 
#endif
int CALLBACK DlgInputConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HBITMAP hBmp;
char temp[256];
short C;
int i, which;
static int index=0;
 
 
static SJoypad pads[5];
 
 
//HBRUSH g_hbrBackground;
 
InitInputCustomControl();
switch(msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint (hDlg, &ps);
if(hBmp)
{
BITMAP bmp;
ZeroMemory(&bmp, sizeof(BITMAP));
RECT r;
GetClientRect(hDlg, &r);
HDC hdc=GetDC(hDlg);
HDC hDCbmp=CreateCompatibleDC(hdc);
GetObject(hBmp, sizeof(BITMAP), &bmp);
HBITMAP hOldBmp=(HBITMAP)SelectObject(hDCbmp, hBmp);
StretchBlt(hdc, 0,0,r.right,r.bottom,hDCbmp,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
SelectObject(hDCbmp, hOldBmp);
DeleteDC(hDCbmp);
ReleaseDC(hDlg, hdc);
}
 
EndPaint (hDlg, &ps);
}
return true;
case WM_INITDIALOG:
SetWindowText(hDlg,INPUTCONFIG_TITLE);
SetDlgItemText(hDlg,IDC_JPTOGGLE,INPUTCONFIG_JPTOGGLE);
SetDlgItemText(hDlg,IDC_OK,BUTTON_OK);
SetDlgItemText(hDlg,IDC_CANCEL,BUTTON_CANCEL);
SetDlgItemText(hDlg,IDC_DIAGTOGGLE,INPUTCONFIG_DIAGTOGGLE);
SetDlgItemText(hDlg,IDC_LABEL_UP,INPUTCONFIG_LABEL_UP);
SetDlgItemText(hDlg,IDC_LABEL_DOWN,INPUTCONFIG_LABEL_DOWN);
SetDlgItemText(hDlg,IDC_LABEL_LEFT,INPUTCONFIG_LABEL_LEFT);
SetDlgItemText(hDlg,IDC_LABEL_RIGHT,INPUTCONFIG_LABEL_RIGHT);
SetDlgItemText(hDlg,IDC_LABEL_A,INPUTCONFIG_LABEL_A);
SetDlgItemText(hDlg,IDC_LABEL_B,INPUTCONFIG_LABEL_B);
SetDlgItemText(hDlg,IDC_LABEL_X,INPUTCONFIG_LABEL_X);
SetDlgItemText(hDlg,IDC_LABEL_Y,INPUTCONFIG_LABEL_Y);
SetDlgItemText(hDlg,IDC_LABEL_L,INPUTCONFIG_LABEL_L);
SetDlgItemText(hDlg,IDC_LABEL_R,INPUTCONFIG_LABEL_R);
SetDlgItemText(hDlg,IDC_LABEL_START,INPUTCONFIG_LABEL_START);
SetDlgItemText(hDlg,IDC_LABEL_SELECT,INPUTCONFIG_LABEL_SELECT);
SetDlgItemText(hDlg,IDC_LABEL_UPRIGHT,INPUTCONFIG_LABEL_UPRIGHT);
SetDlgItemText(hDlg,IDC_LABEL_UPLEFT,INPUTCONFIG_LABEL_UPLEFT);
SetDlgItemText(hDlg,IDC_LABEL_DOWNRIGHT,INPUTCONFIG_LABEL_DOWNRIGHT);
SetDlgItemText(hDlg,IDC_LABEL_DOWNRIGHT,INPUTCONFIG_LABEL_DOWNRIGHT);
SetDlgItemText(hDlg,IDC_LABEL_BLUE,INPUTCONFIG_LABEL_BLUE);
 
hBmp=(HBITMAP)LoadImage(NULL, TEXT("PBortas.bmp"), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
memcpy(pads, Joypad, 5*sizeof(SJoypad));
for( i=0;i<256;i++)
{
GetAsyncKeyState(i);
}
for( C = 0; C != 16; C ++)
JoystickF[C].Attached = joyGetDevCaps( JOYSTICKID1+C, &JoystickF[C].Caps, sizeof( JOYCAPS)) == JOYERR_NOERROR;
for (i=1;i<6;i++)
{
 
sprintf(temp,INPUTCONFIG_JPCOMBO,i);
SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)temp);
}
 
SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_SETCURSEL,(WPARAM)0,0);
if(Joypad[index].Enabled)
{
SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK,(WPARAM)BST_CHECKED,0);
}
else
{
SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK,(WPARAM)BST_UNCHECKED,0);
}
SendDlgItemMessage(hDlg,IDC_UP,WM_USER+44,Joypad[index].Up,0);
SendDlgItemMessage(hDlg,IDC_LEFT,WM_USER+44,Joypad[index].Left,0);
SendDlgItemMessage(hDlg,IDC_DOWN,WM_USER+44,Joypad[index].Down,0);
SendDlgItemMessage(hDlg,IDC_RIGHT,WM_USER+44,Joypad[index].Right,0);
SendDlgItemMessage(hDlg,IDC_A,WM_USER+44,Joypad[index].A,0);
SendDlgItemMessage(hDlg,IDC_B,WM_USER+44,Joypad[index].B,0);
SendDlgItemMessage(hDlg,IDC_X,WM_USER+44,Joypad[index].X,0);
SendDlgItemMessage(hDlg,IDC_Y,WM_USER+44,Joypad[index].Y,0);
SendDlgItemMessage(hDlg,IDC_L,WM_USER+44,Joypad[index].L,0);
SendDlgItemMessage(hDlg,IDC_R,WM_USER+44,Joypad[index].R,0);
SendDlgItemMessage(hDlg,IDC_START,WM_USER+44,Joypad[index].Start,0);
SendDlgItemMessage(hDlg,IDC_SELECT,WM_USER+44,Joypad[index].Select,0);
SendDlgItemMessage(hDlg,IDC_UPLEFT,WM_USER+44,Joypad[index].Left_Up,0);
SendDlgItemMessage(hDlg,IDC_UPRIGHT,WM_USER+44,Joypad[index].Right_Up,0);
SendDlgItemMessage(hDlg,IDC_DWNLEFT,WM_USER+44,Joypad[index].Left_Down,0);
SendDlgItemMessage(hDlg,IDC_DWNRIGHT,WM_USER+44,Joypad[index].Right_Down,0);
 
 
SetFocus(GetDlgItem(hDlg,IDC_JPCOMBO));
 
 
return true;
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
return TRUE;
case WM_USER+43:
//MessageBox(hDlg,"USER+43 CAUGHT","moo",MB_OK);
which = GetDlgCtrlID((HWND)lParam);
switch(which)
{
case IDC_UP:
Joypad[index].Up = wParam;
 
break;
case IDC_DOWN:
Joypad[index].Down = wParam;
 
break;
case IDC_LEFT:
Joypad[index].Left = wParam;
 
break;
case IDC_RIGHT:
Joypad[index].Right = wParam;
 
break;
case IDC_A:
Joypad[index].A = wParam;
 
break;
case IDC_B:
Joypad[index].B = wParam;
 
break;
case IDC_X:
Joypad[index].X = wParam;
 
break;
case IDC_Y:
Joypad[index].Y = wParam;
 
break;
case IDC_L:
Joypad[index].L = wParam;
break;
 
case IDC_R:
Joypad[index].R = wParam;
 
break;
case IDC_SELECT:
Joypad[index].Select = wParam;
 
break;
case IDC_START:
Joypad[index].Start = wParam;
 
break;
case IDC_UPLEFT:
Joypad[index].Left_Up = wParam;
 
break;
case IDC_UPRIGHT:
Joypad[index].Right_Up = wParam;
 
break;
case IDC_DWNLEFT:
Joypad[index].Left_Down = wParam;
 
case IDC_DWNRIGHT:
Joypad[index].Right_Down = wParam;
 
break;
 
}
SendDlgItemMessage(hDlg,IDC_UP,WM_USER+44,Joypad[index].Up,0);
SendDlgItemMessage(hDlg,IDC_LEFT,WM_USER+44,Joypad[index].Left,0);
SendDlgItemMessage(hDlg,IDC_DOWN,WM_USER+44,Joypad[index].Down,0);
SendDlgItemMessage(hDlg,IDC_RIGHT,WM_USER+44,Joypad[index].Right,0);
SendDlgItemMessage(hDlg,IDC_A,WM_USER+44,Joypad[index].A,0);
SendDlgItemMessage(hDlg,IDC_B,WM_USER+44,Joypad[index].B,0);
SendDlgItemMessage(hDlg,IDC_X,WM_USER+44,Joypad[index].X,0);
SendDlgItemMessage(hDlg,IDC_Y,WM_USER+44,Joypad[index].Y,0);
SendDlgItemMessage(hDlg,IDC_L,WM_USER+44,Joypad[index].L,0);
SendDlgItemMessage(hDlg,IDC_R,WM_USER+44,Joypad[index].R,0);
SendDlgItemMessage(hDlg,IDC_START,WM_USER+44,Joypad[index].Start,0);
SendDlgItemMessage(hDlg,IDC_SELECT,WM_USER+44,Joypad[index].Select,0);
SendDlgItemMessage(hDlg,IDC_UPLEFT,WM_USER+44,Joypad[index].Left_Up,0);
SendDlgItemMessage(hDlg,IDC_UPRIGHT,WM_USER+44,Joypad[index].Right_Up,0);
SendDlgItemMessage(hDlg,IDC_DWNLEFT,WM_USER+44,Joypad[index].Left_Down,0);
SendDlgItemMessage(hDlg,IDC_DWNRIGHT,WM_USER+44,Joypad[index].Right_Down,0);
PostMessage(hDlg,WM_NEXTDLGCTL,0,0);
return true;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDCANCEL:
memcpy(Joypad, pads, 5*sizeof(SJoypad));
EndDialog(hDlg,0);
if(hBmp)
{
DeleteObject(hBmp);
hBmp=NULL;
}
break;
case IDOK:
EndDialog(hDlg,0);
if(hBmp)
{
DeleteObject(hBmp);
hBmp=NULL;
}
break;
case IDC_JPTOGGLE:
index = SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_GETCURSEL,0,0);
Joypad[index].Enabled=IsDlgButtonChecked(hDlg,IDC_JPTOGGLE);
break;
case IDC_DIAGTOGGLE:
if(IsWindowEnabled(GetDlgItem(hDlg,IDC_UPLEFT))==0)
{
 
EnableWindow(GetDlgItem(hDlg,IDC_UPLEFT),TRUE);
 
EnableWindow(GetDlgItem(hDlg,IDC_UPRIGHT),TRUE);
 
EnableWindow(GetDlgItem(hDlg,IDC_DWNLEFT),TRUE);
 
EnableWindow(GetDlgItem(hDlg,IDC_DWNRIGHT),TRUE);
 
}
else
{
 
EnableWindow(GetDlgItem(hDlg,IDC_UPLEFT),FALSE);
 
EnableWindow(GetDlgItem(hDlg,IDC_UPRIGHT),FALSE);
 
EnableWindow(GetDlgItem(hDlg,IDC_DWNLEFT),FALSE);
 
EnableWindow(GetDlgItem(hDlg,IDC_DWNRIGHT),FALSE);
}
break;
}
switch(HIWORD(wParam))
{
case CBN_SELCHANGE:
index = SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_GETCURSEL,0,0);
SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_SETCURSEL,(WPARAM)index,0);
if(Joypad[index].Enabled)
{
SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK,(WPARAM)BST_CHECKED,0);
}
else
{
SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK,(WPARAM)BST_UNCHECKED,0);
}
SendDlgItemMessage(hDlg,IDC_UP,WM_USER+44,Joypad[index].Up,0);
SendDlgItemMessage(hDlg,IDC_LEFT,WM_USER+44,Joypad[index].Left,0);
SendDlgItemMessage(hDlg,IDC_DOWN,WM_USER+44,Joypad[index].Down,0);
SendDlgItemMessage(hDlg,IDC_RIGHT,WM_USER+44,Joypad[index].Right,0);
SendDlgItemMessage(hDlg,IDC_A,WM_USER+44,Joypad[index].A,0);
SendDlgItemMessage(hDlg,IDC_B,WM_USER+44,Joypad[index].B,0);
SendDlgItemMessage(hDlg,IDC_X,WM_USER+44,Joypad[index].X,0);
SendDlgItemMessage(hDlg,IDC_Y,WM_USER+44,Joypad[index].Y,0);
SendDlgItemMessage(hDlg,IDC_L,WM_USER+44,Joypad[index].L,0);
SendDlgItemMessage(hDlg,IDC_R,WM_USER+44,Joypad[index].R,0);
SendDlgItemMessage(hDlg,IDC_START,WM_USER+44,Joypad[index].Start,0);
SendDlgItemMessage(hDlg,IDC_SELECT,WM_USER+44,Joypad[index].Select,0);
SendDlgItemMessage(hDlg,IDC_UPLEFT,WM_USER+44,Joypad[index].Left_Up,0);
SendDlgItemMessage(hDlg,IDC_UPRIGHT,WM_USER+44,Joypad[index].Right_Up,0);
SendDlgItemMessage(hDlg,IDC_DWNLEFT,WM_USER+44,Joypad[index].Left_Down,0);
SendDlgItemMessage(hDlg,IDC_DWNRIGHT,WM_USER+44,Joypad[index].Right_Down,0);
break;
}
return FALSE;
 
}
 
return FALSE;
}
 
 
 
enum CheatStatus{
Untouched,
Deleted,
9316,8 → 9316,8
}
GetDlgItemText(hDlg, IDC_NC_DESC, new_cheat->name, 23);
 
new_cheat->enabled=TRUE;
S9xAddCheat(new_cheat->enabled,new_cheat->saved_val,new_cheat->address,new_cheat->new_val);
new_cheat->enabled=TRUE;
S9xAddCheat(new_cheat->enabled,new_cheat->saved_val,new_cheat->address,new_cheat->new_val);
strcpy(Cheat.c[Cheat.num_cheats-1].name,new_cheat->name);
ret=0;
}
linux/InputCustom.cpp
1,691 → 1,691
#define STRICT
#include <windows.h>
#include <tchar.h>
#include <io.h>
#include <fstream.h>
#include "InputCustom.h"
#include "wsnes9x.h"
#include "language.h"
 
static TCHAR szClassName[] = _T("InputCustom");
 
LRESULT CALLBACK InputCustomWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
typedef struct
{
COLORREF crForeGnd; // Foreground text colour
COLORREF crBackGnd; // Background text colour
HFONT hFont; // The font
HWND hwnd; // The control's window handle
} InputCust;
 
 
extern SJoyState JoystickF [16];
 
HWND funky;
WPARAM tid;
 
 
void JoystickChanged( short ID, short Movement)
{
WORD JoyKey;
 
JoyKey = 0x8000;
JoyKey |= (WORD)(ID << 8);
JoyKey |= Movement;
SendMessage(funky,WM_USER+45,JoyKey,0);
KillTimer(funky,tid);
 
 
}
 
int FunkyNormalize(int cur, int min, int max)
{
int Result = 0;
 
if ((max - min) == 0)
 
return (Result);
 
Result = cur - min;
Result = (Result * 200) / (max - min);
Result -= 100;
 
return Result;
}
 
 
void CheckAxis (short joy, short control, int val,
int min, int max,
bool &first, bool &second)
{
 
 
 
if (FunkyNormalize (val, min, max) < -S9X_JOY_NEUTRAL)
 
{
second = false;
if (!first)
{
JoystickChanged (joy, control);
first = true;
 
}
}
else
first = false;
 
if (FunkyNormalize (val, min, max) > S9X_JOY_NEUTRAL)
{
first = false;
if (!second)
{
JoystickChanged (joy, (short) (control + 1));
second = true;
}
}
else
second = false;
}
 
void FunkyJoyStickTimer()
{
JOYINFOEX jie;
 
for (short C = 0; C != 16; C ++)
{
 
jie.dwSize = sizeof( jie);
jie.dwFlags = JOY_RETURNALL;
 
if (joyGetPosEx (JOYSTICKID1 + C, &jie) != JOYERR_NOERROR)
continue;
 
CheckAxis (C, 0, jie.dwXpos,
JoystickF[C].Caps.wXmin, JoystickF[C].Caps.wXmax,
JoystickF[C].Left, JoystickF[C].Right);
CheckAxis (C, 2, jie.dwYpos,
JoystickF[C].Caps.wYmin, JoystickF[C].Caps.wYmax,
JoystickF[C].Up, JoystickF[C].Down);
if(JoystickF[C].Caps.wCaps & JOYCAPS_HASZ)
{
CheckAxis (C, 41, jie.dwZpos,
JoystickF[C].Caps.wZmin, JoystickF[C].Caps.wZmax,
JoystickF[C].ZUp, JoystickF[C].ZDown);
}
if(JoystickF[C].Caps.wCaps & JOYCAPS_HASR)
{
CheckAxis (C, 43, jie.dwRpos,
JoystickF[C].Caps.wRmin, JoystickF[C].Caps.wRmax,
JoystickF[C].RUp, JoystickF[C].RDown);
}
if(JoystickF[C].Caps.wCaps & JOYCAPS_HASU)
{
CheckAxis (C, 45, jie.dwUpos,
JoystickF[C].Caps.wUmin, JoystickF[C].Caps.wUmax,
JoystickF[C].UUp, JoystickF[C].UDown);
}
if(JoystickF[C].Caps.wCaps & JOYCAPS_HASV)
{
CheckAxis (C, 47, jie.dwVpos,
JoystickF[C].Caps.wVmin, JoystickF[C].Caps.wVmax,
JoystickF[C].VUp, JoystickF[C].VDown);
}
 
switch (jie.dwPOV)
{
case JOY_POVBACKWARD:
if( !JoystickF[C].PovDown)
{ JoystickChanged( C, 7); }
 
JoystickF[C].PovDown = true;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
case 4500:
if( !JoystickF[C].PovUpRight)
{ JoystickChanged( C, 52); }
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = true;
break;
case 13500:
if( !JoystickF[C].PovDnRight)
{ JoystickChanged( C, 50); }
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = true;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
case 22500:
if( !JoystickF[C].PovDnLeft)
{ JoystickChanged( C, 49); }
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = true;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
case 31500:
if( !JoystickF[C].PovUpLeft)
{ JoystickChanged( C, 51); }
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = true;
JoystickF[C].PovUpRight = false;
break;
 
case JOY_POVFORWARD:
if( !JoystickF[C].PovUp)
{ JoystickChanged( C, 6); }
 
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = true;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
 
case JOY_POVLEFT:
if( !JoystickF[C].PovLeft)
{ JoystickChanged( C, 4); }
 
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = true;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
 
case JOY_POVRIGHT:
if( !JoystickF[C].PovRight)
{ JoystickChanged( C, 5); }
 
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = true;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
 
default:
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
}
 
for( short B = 0; B != 32; B ++, jie.dwButtons >>= 1)
if( (jie.dwButtons&1))
{
if( !JoystickF[C].Button[B])
{
JoystickChanged( C, (short)(8+B));
JoystickF[C].Button[B] = true;
}
}
else
{ JoystickF[C].Button[B] = false; }
 
}
 
 
 
 
 
}
void TranslateKey(WORD keyz,char *out)
{
char temp[100];
if(keyz&0x8000)
{
sprintf(out,GAMEDEVICE_JOYNUMPREFIX,((keyz>>8)&0xF));
switch(keyz&0xFF)
{
case 0: strncat(out,GAMEDEVICE_XNEG,4); break;
case 1: strncat(out,GAMEDEVICE_XPOS,5); break;
case 2: strncat(out,GAMEDEVICE_YPOS,2); break;
case 3: strncat(out,GAMEDEVICE_YNEG,4); break;
case 4: strncat(out,GAMEDEVICE_POVLEFT,8); break;
case 5: strncat(out,GAMEDEVICE_POVRIGHT,9); break;
case 6: strncat(out,GAMEDEVICE_POVUP,6); break;
case 7: strncat(out,GAMEDEVICE_POVDOWN,8); break;
case 49: strncat(out,GAMEDEVICE_POVDNLEFT,11); break;
case 50: strncat(out,GAMEDEVICE_POVDNRIGHT,12); break;
case 51: strncat(out,GAMEDEVICE_POVUPLEFT,11); break;
case 52: strncat(out,GAMEDEVICE_POVUPRIGHT,12); break;
case 41: strncat(out,GAMEDEVICE_ZPOS,4); break;
case 42: strncat(out,GAMEDEVICE_ZNEG,6); break;
case 43: strncat(out,GAMEDEVICE_RPOS,4); break;
case 44: strncat(out,GAMEDEVICE_RNEG,6); break;
case 45: strncat(out,GAMEDEVICE_UPOS,4); break;
case 46: strncat(out,GAMEDEVICE_UNEG,6); break;
case 47: strncat(out,GAMEDEVICE_VPOS,4); break;
case 48: strncat(out,GAMEDEVICE_VNEG,6); break;
default:
if ((keyz & 0xff) > 40)
{
sprintf(temp,GAMEDEVICE_JOYBUTPREFIX,keyz&0xFF);
strncat(out,temp,strlen(temp));
break;
}
 
sprintf(temp,GAMEDEVICE_BUTTON,(keyz&0xFF)-8);
strncat(out,temp,strlen(temp));
break;
 
}
return;
}
sprintf(out,GAMEDEVICE_KEY,keyz);
if((keyz>='0' && keyz<='9')||(keyz>='A' &&keyz<='Z'))
{
sprintf(out,"%c",keyz);
return;
}
if( keyz >= VK_NUMPAD0 && keyz <= VK_NUMPAD9)
{
 
sprintf(out,GAMEDEVICE_NUMPADPREFIX,'0'+(keyz-VK_NUMPAD0));
 
return ;
}
switch(keyz)
{
case 0: sprintf(out,GAMEDEVICE_DISABLED); break;
case VK_TAB: sprintf(out,GAMEDEVICE_VK_TAB); break;
case VK_BACK: sprintf(out,GAMEDEVICE_VK_BACK); break;
case VK_CLEAR: sprintf(out,GAMEDEVICE_VK_CLEAR); break;
case VK_RETURN: sprintf(out,GAMEDEVICE_VK_RETURN); break;
case VK_LSHIFT: sprintf(out,GAMEDEVICE_VK_LSHIFT); break;
case VK_RSHIFT: sprintf(out,GAMEDEVICE_VK_RSHIFT); break;
case VK_LCONTROL: sprintf(out,GAMEDEVICE_VK_LCONTROL); break;
case VK_RCONTROL: sprintf(out,GAMEDEVICE_VK_RCONTROL); break;
case VK_LMENU: sprintf(out,GAMEDEVICE_VK_LMENU); break;
case VK_RMENU: sprintf(out,GAMEDEVICE_VK_RMENU); break;
case VK_PAUSE: sprintf(out,GAMEDEVICE_VK_PAUSE); break;
case VK_CAPITAL: sprintf(out,GAMEDEVICE_VK_CAPITAL); break;
case VK_ESCAPE: sprintf(out,GAMEDEVICE_VK_ESCAPE); break;
case VK_SPACE: sprintf(out,GAMEDEVICE_VK_SPACE); break;
case VK_PRIOR: sprintf(out,GAMEDEVICE_VK_PRIOR); break;
case VK_NEXT: sprintf(out,GAMEDEVICE_VK_NEXT); break;
case VK_HOME: sprintf(out,GAMEDEVICE_VK_HOME); break;
case VK_END: sprintf(out,GAMEDEVICE_VK_END); break;
case VK_LEFT: sprintf(out,GAMEDEVICE_VK_LEFT ); break;
case VK_RIGHT: sprintf(out,GAMEDEVICE_VK_RIGHT); break;
case VK_UP: sprintf(out,GAMEDEVICE_VK_UP); break;
case VK_DOWN: sprintf(out,GAMEDEVICE_VK_DOWN); break;
case VK_SELECT: sprintf(out,GAMEDEVICE_VK_SELECT); break;
case VK_PRINT: sprintf(out,GAMEDEVICE_VK_PRINT); break;
case VK_EXECUTE: sprintf(out,GAMEDEVICE_VK_EXECUTE); break;
case VK_SNAPSHOT: sprintf(out,GAMEDEVICE_VK_SNAPSHOT); break;
case VK_INSERT: sprintf(out,GAMEDEVICE_VK_INSERT); break;
case VK_DELETE: sprintf(out,GAMEDEVICE_VK_DELETE); break;
case VK_HELP: sprintf(out,GAMEDEVICE_VK_HELP); break;
case VK_LWIN: sprintf(out,GAMEDEVICE_VK_LWIN); break;
case VK_RWIN: sprintf(out,GAMEDEVICE_VK_RWIN); break;
case VK_APPS: sprintf(out,GAMEDEVICE_VK_APPS); break;
case VK_MULTIPLY: sprintf(out,GAMEDEVICE_VK_MULTIPLY); break;
case VK_ADD: sprintf(out,GAMEDEVICE_VK_ADD); break;
case VK_SEPARATOR: sprintf(out,GAMEDEVICE_VK_SEPARATOR); break;
case VK_OEM_1: sprintf(out,GAMEDEVICE_VK_OEM_1); break;
case VK_OEM_7: sprintf(out,GAMEDEVICE_VK_OEM_7); break;
case VK_OEM_COMMA: sprintf(out,GAMEDEVICE_VK_OEM_COMMA );break;
case VK_OEM_PERIOD: sprintf(out,GAMEDEVICE_VK_OEM_PERIOD);break;
case VK_SUBTRACT: sprintf(out,GAMEDEVICE_VK_SUBTRACT); break;
case VK_DECIMAL: sprintf(out,GAMEDEVICE_VK_DECIMAL); break;
case VK_DIVIDE: sprintf(out,GAMEDEVICE_VK_DIVIDE); break;
case VK_NUMLOCK: sprintf(out,GAMEDEVICE_VK_NUMLOCK); break;
case VK_SCROLL: sprintf(out,GAMEDEVICE_VK_SCROLL); break;
 
 
 
}
 
return ;
 
 
 
}
COLORREF CheckKey( WORD Key)
{
COLORREF red,blue,white;
red =RGB(255,0,0);
blue = RGB(0,0,255);
white = RGB(255,255,255);
// Check for windows keys
if( Key == VK_MENU || Key == VK_CAPITAL || Key == VK_LWIN ||
Key == VK_RWIN || Key == VK_APPS)
{
//return 1;
return red;
}
 
// Check for Snes9X keys
if ((Key >= VK_F1 && Key <= VK_F9) || Key == VK_F12 || Key == VK_TAB ||
Key == VK_OEM_MINUS || Key == VK_OEM_PLUS || Key == VK_OEM_3 || (Key >= 0x30 && Key <= 0x39))
{
return red;
}
 
// Check for duplicate keys
int Found = 0;
for( int J = 0; J != 5; J++)
{
 
 
 
//if( J == OldJoypad)
//{ continue; }
 
if( Key == Joypad[J].Left)
{ Found ++; }
if( Key == Joypad[J].Left_Up)
{ Found ++; }
if( Key == Joypad[J].Left_Down)
{ Found ++; }
if( Key == Joypad[J].Right)
{ Found ++; }
if( Key == Joypad[J].Right_Up)
{ Found ++; }
if( Key == Joypad[J].Right_Down)
{ Found ++; }
if( Key == Joypad[J].Up)
{ Found ++; }
if( Key == Joypad[J].Down)
{ Found ++; }
if( Key == Joypad[J].Start)
{ Found ++; }
if( Key == Joypad[J].Select)
{ Found ++; }
if( Key == Joypad[J].A)
{ Found ++; }
if( Key == Joypad[J].B)
{ Found ++; }
if( Key == Joypad[J].X)
{ Found ++; }
if( Key == Joypad[J].Y)
{ Found ++; }
if( Key == Joypad[J].L)
{ Found ++; }
if( Key == Joypad[J].R)
{ Found ++; }
}
 
 
 
 
if( Found > 1)
{
return blue;
}
 
return white;
}
void InitInputCustomControl()
{
 
WNDCLASSEX wc;
 
wc.cbSize = sizeof(wc);
wc.lpszClassName = szClassName;
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = InputCustomWndProc;
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hIcon = 0;
wc.lpszMenuName = 0;
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_BTNFACE);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(InputCust *);
wc.hIconSm = 0;
 
 
RegisterClassEx(&wc);
 
}
HWND CreateInputCustom(HWND hwndParent)
{
HWND hwndCtrl;
 
hwndCtrl = CreateWindowEx(
WS_EX_CLIENTEDGE, // give it a standard border
szClassName,
_T("A custom control"),
WS_VISIBLE | WS_CHILD,
0, 0, 100, 100,
hwndParent,
NULL, GetModuleHandle(0), NULL
);
 
return hwndCtrl;
}
static InputCust * GetInputCustom(HWND hwnd)
{
return (InputCust *)GetWindowLong(hwnd, 0);
}
 
void SetInputCustom(HWND hwnd, InputCust *icp)
{
SetWindowLong(hwnd, 0, (LONG)icp);
}
 
LRESULT InputCustom_OnPaint(InputCust *ccp, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HANDLE hOldFont;
TCHAR szText[200];
RECT rect;
SIZE sz;
int x,y;
 
// Get a device context for this window
hdc = BeginPaint(ccp->hwnd, &ps);
 
// Set the font we are going to use
hOldFont = SelectObject(hdc, ccp->hFont);
 
// Set the text colours
SetTextColor(hdc, ccp->crForeGnd);
SetBkColor (hdc, ccp->crBackGnd);
 
// Find the text to draw
GetWindowText(ccp->hwnd, szText, sizeof(szText));
 
// Work out where to draw
GetClientRect(ccp->hwnd, &rect);
 
 
// Find out how big the text will be
GetTextExtentPoint32(hdc, szText, lstrlen(szText), &sz);
 
// Center the text
x = (rect.right - sz.cx) / 2;
y = (rect.bottom - sz.cy) / 2;
 
// Draw the text
ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0);
 
// Restore the old font when we have finished
SelectObject(hdc, hOldFont);
 
// Release the device context
EndPaint(ccp->hwnd, &ps);
 
return 0;
}
 
static LRESULT CALLBACK InputCustomWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// retrieve the custom structure POINTER for THIS window
InputCust *icp = GetInputCustom(hwnd);
HWND pappy = (HWND__ *)GetWindowLongPtr(hwnd,GWL_HWNDPARENT);
funky= hwnd;
 
char temp[100];
COLORREF col;
switch(msg)
{
case WM_GETDLGCODE:
return DLGC_WANTARROWS|DLGC_WANTALLKEYS|DLGC_WANTCHARS;
break;
 
 
case WM_NCCREATE:
 
// Allocate a new CustCtrl structure for this window.
icp = (InputCust *) malloc( sizeof(InputCust) );
 
// Failed to allocate, stop window creation.
if(icp == NULL) return FALSE;
 
// Initialize the CustCtrl structure.
icp->hwnd = hwnd;
icp->crForeGnd = GetSysColor(COLOR_WINDOWTEXT);
icp->crBackGnd = GetSysColor(COLOR_WINDOW);
icp->hFont = (HFONT__ *) GetStockObject(DEFAULT_GUI_FONT);
 
// Assign the window text specified in the call to CreateWindow.
SetWindowText(hwnd, ((CREATESTRUCT *)lParam)->lpszName);
 
// Attach custom structure to this window.
SetInputCustom(hwnd, icp);
 
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);
return true;
 
// Continue with window creation.
return TRUE;
 
// Clean up when the window is destroyed.
case WM_NCDESTROY:
free(icp);
break;
case WM_PAINT:
return InputCustom_OnPaint(icp,wParam,lParam);
break;
case WM_ERASEBKGND:
return 1;
case WM_USER+45:
case WM_KEYDOWN:
TranslateKey(wParam,temp);
col = CheckKey(wParam);
 
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
SetWindowText(hwnd,temp);
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);
SendMessage(pappy,WM_USER+43,wParam,(LPARAM)hwnd);
 
break;
case WM_USER+44:
 
TranslateKey(wParam,temp);
if(IsWindowEnabled(hwnd))
{
col = CheckKey(wParam);
}
else
{
col = RGB( 192,192,192);
}
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
SetWindowText(hwnd,temp);
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);
 
break;
 
case WM_SETFOCUS:
{
col = RGB( 0,255,0);
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);
tid = wParam;
 
 
SetTimer(hwnd,tid,125,NULL);
 
 
break;
}
case WM_KILLFOCUS:
{
/*col = RGB( 255,255,255);
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);*/
break;
}
 
case WM_TIMER:
FunkyJoyStickTimer();
break;
case WM_LBUTTONDOWN:
SetFocus(hwnd);
break;
case WM_ENABLE:
COLORREF col;
if(wParam)
{
col = RGB( 255,255,255);
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
}
else
{
col = RGB( 192,192,192);
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
}
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);
return true;
default:
break;
}
 
return DefWindowProc(hwnd, msg, wParam, lParam);
#define STRICT
#include <windows.h>
#include <tchar.h>
#include <io.h>
#include <fstream.h>
#include "InputCustom.h"
#include "wsnes9x.h"
#include "language.h"
 
static TCHAR szClassName[] = _T("InputCustom");
 
LRESULT CALLBACK InputCustomWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
typedef struct
{
COLORREF crForeGnd; // Foreground text colour
COLORREF crBackGnd; // Background text colour
HFONT hFont; // The font
HWND hwnd; // The control's window handle
} InputCust;
 
 
extern SJoyState JoystickF [16];
 
HWND funky;
WPARAM tid;
 
 
void JoystickChanged( short ID, short Movement)
{
WORD JoyKey;
 
JoyKey = 0x8000;
JoyKey |= (WORD)(ID << 8);
JoyKey |= Movement;
SendMessage(funky,WM_USER+45,JoyKey,0);
KillTimer(funky,tid);
 
 
}
 
int FunkyNormalize(int cur, int min, int max)
{
int Result = 0;
 
if ((max - min) == 0)
 
return (Result);
 
Result = cur - min;
Result = (Result * 200) / (max - min);
Result -= 100;
 
return Result;
}
 
 
void CheckAxis (short joy, short control, int val,
int min, int max,
bool &first, bool &second)
{
 
 
 
if (FunkyNormalize (val, min, max) < -S9X_JOY_NEUTRAL)
 
{
second = false;
if (!first)
{
JoystickChanged (joy, control);
first = true;
 
}
}
else
first = false;
 
if (FunkyNormalize (val, min, max) > S9X_JOY_NEUTRAL)
{
first = false;
if (!second)
{
JoystickChanged (joy, (short) (control + 1));
second = true;
}
}
else
second = false;
}
 
void FunkyJoyStickTimer()
{
JOYINFOEX jie;
 
for (short C = 0; C != 16; C ++)
{
 
jie.dwSize = sizeof( jie);
jie.dwFlags = JOY_RETURNALL;
 
if (joyGetPosEx (JOYSTICKID1 + C, &jie) != JOYERR_NOERROR)
continue;
 
CheckAxis (C, 0, jie.dwXpos,
JoystickF[C].Caps.wXmin, JoystickF[C].Caps.wXmax,
JoystickF[C].Left, JoystickF[C].Right);
CheckAxis (C, 2, jie.dwYpos,
JoystickF[C].Caps.wYmin, JoystickF[C].Caps.wYmax,
JoystickF[C].Up, JoystickF[C].Down);
if(JoystickF[C].Caps.wCaps & JOYCAPS_HASZ)
{
CheckAxis (C, 41, jie.dwZpos,
JoystickF[C].Caps.wZmin, JoystickF[C].Caps.wZmax,
JoystickF[C].ZUp, JoystickF[C].ZDown);
}
if(JoystickF[C].Caps.wCaps & JOYCAPS_HASR)
{
CheckAxis (C, 43, jie.dwRpos,
JoystickF[C].Caps.wRmin, JoystickF[C].Caps.wRmax,
JoystickF[C].RUp, JoystickF[C].RDown);
}
if(JoystickF[C].Caps.wCaps & JOYCAPS_HASU)
{
CheckAxis (C, 45, jie.dwUpos,
JoystickF[C].Caps.wUmin, JoystickF[C].Caps.wUmax,
JoystickF[C].UUp, JoystickF[C].UDown);
}
if(JoystickF[C].Caps.wCaps & JOYCAPS_HASV)
{
CheckAxis (C, 47, jie.dwVpos,
JoystickF[C].Caps.wVmin, JoystickF[C].Caps.wVmax,
JoystickF[C].VUp, JoystickF[C].VDown);
}
 
switch (jie.dwPOV)
{
case JOY_POVBACKWARD:
if( !JoystickF[C].PovDown)
{ JoystickChanged( C, 7); }
 
JoystickF[C].PovDown = true;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
case 4500:
if( !JoystickF[C].PovUpRight)
{ JoystickChanged( C, 52); }
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = true;
break;
case 13500:
if( !JoystickF[C].PovDnRight)
{ JoystickChanged( C, 50); }
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = true;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
case 22500:
if( !JoystickF[C].PovDnLeft)
{ JoystickChanged( C, 49); }
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = true;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
case 31500:
if( !JoystickF[C].PovUpLeft)
{ JoystickChanged( C, 51); }
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = true;
JoystickF[C].PovUpRight = false;
break;
 
case JOY_POVFORWARD:
if( !JoystickF[C].PovUp)
{ JoystickChanged( C, 6); }
 
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = true;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
 
case JOY_POVLEFT:
if( !JoystickF[C].PovLeft)
{ JoystickChanged( C, 4); }
 
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = true;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
 
case JOY_POVRIGHT:
if( !JoystickF[C].PovRight)
{ JoystickChanged( C, 5); }
 
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = true;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
 
default:
JoystickF[C].PovDown = false;
JoystickF[C].PovUp = false;
JoystickF[C].PovLeft = false;
JoystickF[C].PovRight = false;
JoystickF[C].PovDnLeft = false;
JoystickF[C].PovDnRight = false;
JoystickF[C].PovUpLeft = false;
JoystickF[C].PovUpRight = false;
break;
}
 
for( short B = 0; B != 32; B ++, jie.dwButtons >>= 1)
if( (jie.dwButtons&1))
{
if( !JoystickF[C].Button[B])
{
JoystickChanged( C, (short)(8+B));
JoystickF[C].Button[B] = true;
}
}
else
{ JoystickF[C].Button[B] = false; }
 
}
 
 
 
 
 
}
void TranslateKey(WORD keyz,char *out)
{
char temp[100];
if(keyz&0x8000)
{
sprintf(out,GAMEDEVICE_JOYNUMPREFIX,((keyz>>8)&0xF));
switch(keyz&0xFF)
{
case 0: strncat(out,GAMEDEVICE_XNEG,4); break;
case 1: strncat(out,GAMEDEVICE_XPOS,5); break;
case 2: strncat(out,GAMEDEVICE_YPOS,2); break;
case 3: strncat(out,GAMEDEVICE_YNEG,4); break;
case 4: strncat(out,GAMEDEVICE_POVLEFT,8); break;
case 5: strncat(out,GAMEDEVICE_POVRIGHT,9); break;
case 6: strncat(out,GAMEDEVICE_POVUP,6); break;
case 7: strncat(out,GAMEDEVICE_POVDOWN,8); break;
case 49: strncat(out,GAMEDEVICE_POVDNLEFT,11); break;
case 50: strncat(out,GAMEDEVICE_POVDNRIGHT,12); break;
case 51: strncat(out,GAMEDEVICE_POVUPLEFT,11); break;
case 52: strncat(out,GAMEDEVICE_POVUPRIGHT,12); break;
case 41: strncat(out,GAMEDEVICE_ZPOS,4); break;
case 42: strncat(out,GAMEDEVICE_ZNEG,6); break;
case 43: strncat(out,GAMEDEVICE_RPOS,4); break;
case 44: strncat(out,GAMEDEVICE_RNEG,6); break;
case 45: strncat(out,GAMEDEVICE_UPOS,4); break;
case 46: strncat(out,GAMEDEVICE_UNEG,6); break;
case 47: strncat(out,GAMEDEVICE_VPOS,4); break;
case 48: strncat(out,GAMEDEVICE_VNEG,6); break;
default:
if ((keyz & 0xff) > 40)
{
sprintf(temp,GAMEDEVICE_JOYBUTPREFIX,keyz&0xFF);
strncat(out,temp,strlen(temp));
break;
}
 
sprintf(temp,GAMEDEVICE_BUTTON,(keyz&0xFF)-8);
strncat(out,temp,strlen(temp));
break;
 
}
return;
}
sprintf(out,GAMEDEVICE_KEY,keyz);
if((keyz>='0' && keyz<='9')||(keyz>='A' &&keyz<='Z'))
{
sprintf(out,"%c",keyz);
return;
}
if( keyz >= VK_NUMPAD0 && keyz <= VK_NUMPAD9)
{
 
sprintf(out,GAMEDEVICE_NUMPADPREFIX,'0'+(keyz-VK_NUMPAD0));
 
return ;
}
switch(keyz)
{
case 0: sprintf(out,GAMEDEVICE_DISABLED); break;
case VK_TAB: sprintf(out,GAMEDEVICE_VK_TAB); break;
case VK_BACK: sprintf(out,GAMEDEVICE_VK_BACK); break;
case VK_CLEAR: sprintf(out,GAMEDEVICE_VK_CLEAR); break;
case VK_RETURN: sprintf(out,GAMEDEVICE_VK_RETURN); break;
case VK_LSHIFT: sprintf(out,GAMEDEVICE_VK_LSHIFT); break;
case VK_RSHIFT: sprintf(out,GAMEDEVICE_VK_RSHIFT); break;
case VK_LCONTROL: sprintf(out,GAMEDEVICE_VK_LCONTROL); break;
case VK_RCONTROL: sprintf(out,GAMEDEVICE_VK_RCONTROL); break;
case VK_LMENU: sprintf(out,GAMEDEVICE_VK_LMENU); break;
case VK_RMENU: sprintf(out,GAMEDEVICE_VK_RMENU); break;
case VK_PAUSE: sprintf(out,GAMEDEVICE_VK_PAUSE); break;
case VK_CAPITAL: sprintf(out,GAMEDEVICE_VK_CAPITAL); break;
case VK_ESCAPE: sprintf(out,GAMEDEVICE_VK_ESCAPE); break;
case VK_SPACE: sprintf(out,GAMEDEVICE_VK_SPACE); break;
case VK_PRIOR: sprintf(out,GAMEDEVICE_VK_PRIOR); break;
case VK_NEXT: sprintf(out,GAMEDEVICE_VK_NEXT); break;
case VK_HOME: sprintf(out,GAMEDEVICE_VK_HOME); break;
case VK_END: sprintf(out,GAMEDEVICE_VK_END); break;
case VK_LEFT: sprintf(out,GAMEDEVICE_VK_LEFT ); break;
case VK_RIGHT: sprintf(out,GAMEDEVICE_VK_RIGHT); break;
case VK_UP: sprintf(out,GAMEDEVICE_VK_UP); break;
case VK_DOWN: sprintf(out,GAMEDEVICE_VK_DOWN); break;
case VK_SELECT: sprintf(out,GAMEDEVICE_VK_SELECT); break;
case VK_PRINT: sprintf(out,GAMEDEVICE_VK_PRINT); break;
case VK_EXECUTE: sprintf(out,GAMEDEVICE_VK_EXECUTE); break;
case VK_SNAPSHOT: sprintf(out,GAMEDEVICE_VK_SNAPSHOT); break;
case VK_INSERT: sprintf(out,GAMEDEVICE_VK_INSERT); break;
case VK_DELETE: sprintf(out,GAMEDEVICE_VK_DELETE); break;
case VK_HELP: sprintf(out,GAMEDEVICE_VK_HELP); break;
case VK_LWIN: sprintf(out,GAMEDEVICE_VK_LWIN); break;
case VK_RWIN: sprintf(out,GAMEDEVICE_VK_RWIN); break;
case VK_APPS: sprintf(out,GAMEDEVICE_VK_APPS); break;
case VK_MULTIPLY: sprintf(out,GAMEDEVICE_VK_MULTIPLY); break;
case VK_ADD: sprintf(out,GAMEDEVICE_VK_ADD); break;
case VK_SEPARATOR: sprintf(out,GAMEDEVICE_VK_SEPARATOR); break;
case VK_OEM_1: sprintf(out,GAMEDEVICE_VK_OEM_1); break;
case VK_OEM_7: sprintf(out,GAMEDEVICE_VK_OEM_7); break;
case VK_OEM_COMMA: sprintf(out,GAMEDEVICE_VK_OEM_COMMA );break;
case VK_OEM_PERIOD: sprintf(out,GAMEDEVICE_VK_OEM_PERIOD);break;
case VK_SUBTRACT: sprintf(out,GAMEDEVICE_VK_SUBTRACT); break;
case VK_DECIMAL: sprintf(out,GAMEDEVICE_VK_DECIMAL); break;
case VK_DIVIDE: sprintf(out,GAMEDEVICE_VK_DIVIDE); break;
case VK_NUMLOCK: sprintf(out,GAMEDEVICE_VK_NUMLOCK); break;
case VK_SCROLL: sprintf(out,GAMEDEVICE_VK_SCROLL); break;
 
 
 
}
 
return ;
 
 
 
}
COLORREF CheckKey( WORD Key)
{
COLORREF red,blue,white;
red =RGB(255,0,0);
blue = RGB(0,0,255);
white = RGB(255,255,255);
// Check for windows keys
if( Key == VK_MENU || Key == VK_CAPITAL || Key == VK_LWIN ||
Key == VK_RWIN || Key == VK_APPS)
{
//return 1;
return red;
}
 
// Check for Snes9X keys
if ((Key >= VK_F1 && Key <= VK_F9) || Key == VK_F12 || Key == VK_TAB ||
Key == VK_OEM_MINUS || Key == VK_OEM_PLUS || Key == VK_OEM_3 || (Key >= 0x30 && Key <= 0x39))
{
return red;
}
 
// Check for duplicate keys
int Found = 0;
for( int J = 0; J != 5; J++)
{
 
 
 
//if( J == OldJoypad)
//{ continue; }
 
if( Key == Joypad[J].Left)
{ Found ++; }
if( Key == Joypad[J].Left_Up)
{ Found ++; }
if( Key == Joypad[J].Left_Down)
{ Found ++; }
if( Key == Joypad[J].Right)
{ Found ++; }
if( Key == Joypad[J].Right_Up)
{ Found ++; }
if( Key == Joypad[J].Right_Down)
{ Found ++; }
if( Key == Joypad[J].Up)
{ Found ++; }
if( Key == Joypad[J].Down)
{ Found ++; }
if( Key == Joypad[J].Start)
{ Found ++; }
if( Key == Joypad[J].Select)
{ Found ++; }
if( Key == Joypad[J].A)
{ Found ++; }
if( Key == Joypad[J].B)
{ Found ++; }
if( Key == Joypad[J].X)
{ Found ++; }
if( Key == Joypad[J].Y)
{ Found ++; }
if( Key == Joypad[J].L)
{ Found ++; }
if( Key == Joypad[J].R)
{ Found ++; }
}
 
 
 
 
if( Found > 1)
{
return blue;
}
 
return white;
}
void InitInputCustomControl()
{
 
WNDCLASSEX wc;
 
wc.cbSize = sizeof(wc);
wc.lpszClassName = szClassName;
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = InputCustomWndProc;
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hIcon = 0;
wc.lpszMenuName = 0;
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_BTNFACE);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(InputCust *);
wc.hIconSm = 0;
 
 
RegisterClassEx(&wc);
 
}
HWND CreateInputCustom(HWND hwndParent)
{
HWND hwndCtrl;
 
hwndCtrl = CreateWindowEx(
WS_EX_CLIENTEDGE, // give it a standard border
szClassName,
_T("A custom control"),
WS_VISIBLE | WS_CHILD,
0, 0, 100, 100,
hwndParent,
NULL, GetModuleHandle(0), NULL
);
 
return hwndCtrl;
}
static InputCust * GetInputCustom(HWND hwnd)
{
return (InputCust *)GetWindowLong(hwnd, 0);
}
 
void SetInputCustom(HWND hwnd, InputCust *icp)
{
SetWindowLong(hwnd, 0, (LONG)icp);
}
 
LRESULT InputCustom_OnPaint(InputCust *ccp, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HANDLE hOldFont;
TCHAR szText[200];
RECT rect;
SIZE sz;
int x,y;
 
// Get a device context for this window
hdc = BeginPaint(ccp->hwnd, &ps);
 
// Set the font we are going to use
hOldFont = SelectObject(hdc, ccp->hFont);
 
// Set the text colours
SetTextColor(hdc, ccp->crForeGnd);
SetBkColor (hdc, ccp->crBackGnd);
 
// Find the text to draw
GetWindowText(ccp->hwnd, szText, sizeof(szText));
 
// Work out where to draw
GetClientRect(ccp->hwnd, &rect);
 
 
// Find out how big the text will be
GetTextExtentPoint32(hdc, szText, lstrlen(szText), &sz);
 
// Center the text
x = (rect.right - sz.cx) / 2;
y = (rect.bottom - sz.cy) / 2;
 
// Draw the text
ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0);
 
// Restore the old font when we have finished
SelectObject(hdc, hOldFont);
 
// Release the device context
EndPaint(ccp->hwnd, &ps);
 
return 0;
}
 
static LRESULT CALLBACK InputCustomWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// retrieve the custom structure POINTER for THIS window
InputCust *icp = GetInputCustom(hwnd);
HWND pappy = (HWND__ *)GetWindowLongPtr(hwnd,GWL_HWNDPARENT);
funky= hwnd;
 
char temp[100];
COLORREF col;
switch(msg)
{
case WM_GETDLGCODE:
return DLGC_WANTARROWS|DLGC_WANTALLKEYS|DLGC_WANTCHARS;
break;
 
 
case WM_NCCREATE:
 
// Allocate a new CustCtrl structure for this window.
icp = (InputCust *) malloc( sizeof(InputCust) );
 
// Failed to allocate, stop window creation.
if(icp == NULL) return FALSE;
 
// Initialize the CustCtrl structure.
icp->hwnd = hwnd;
icp->crForeGnd = GetSysColor(COLOR_WINDOWTEXT);
icp->crBackGnd = GetSysColor(COLOR_WINDOW);
icp->hFont = (HFONT__ *) GetStockObject(DEFAULT_GUI_FONT);
 
// Assign the window text specified in the call to CreateWindow.
SetWindowText(hwnd, ((CREATESTRUCT *)lParam)->lpszName);
 
// Attach custom structure to this window.
SetInputCustom(hwnd, icp);
 
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);
return true;
 
// Continue with window creation.
return TRUE;
 
// Clean up when the window is destroyed.
case WM_NCDESTROY:
free(icp);
break;
case WM_PAINT:
return InputCustom_OnPaint(icp,wParam,lParam);
break;
case WM_ERASEBKGND:
return 1;
case WM_USER+45:
case WM_KEYDOWN:
TranslateKey(wParam,temp);
col = CheckKey(wParam);
 
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
SetWindowText(hwnd,temp);
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);
SendMessage(pappy,WM_USER+43,wParam,(LPARAM)hwnd);
 
break;
case WM_USER+44:
 
TranslateKey(wParam,temp);
if(IsWindowEnabled(hwnd))
{
col = CheckKey(wParam);
}
else
{
col = RGB( 192,192,192);
}
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
SetWindowText(hwnd,temp);
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);
 
break;
 
case WM_SETFOCUS:
{
col = RGB( 0,255,0);
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);
tid = wParam;
 
 
SetTimer(hwnd,tid,125,NULL);
 
 
break;
}
case WM_KILLFOCUS:
{
/*col = RGB( 255,255,255);
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);*/
break;
}
 
case WM_TIMER:
FunkyJoyStickTimer();
break;
case WM_LBUTTONDOWN:
SetFocus(hwnd);
break;
case WM_ENABLE:
COLORREF col;
if(wParam)
{
col = RGB( 255,255,255);
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
}
else
{
col = RGB( 192,192,192);
icp->crForeGnd = ((~col) & 0x00ffffff);
icp->crBackGnd = col;
}
InvalidateRect(icp->hwnd, NULL, FALSE);
UpdateWindow(icp->hwnd);
return true;
default:
break;
}
 
return DefWindowProc(hwnd, msg, wParam, lParam);
}
\ No newline at end of file