diff --git a/Makefile b/Makefile index c01cb03..9a0918c 100644 --- a/Makefile +++ b/Makefile @@ -225,9 +225,10 @@ else ifeq ($(core), vb) core = vb NEED_BPP = 32 NEED_BLIP = 1 + WANT_NEW_API = 1 NEED_STEREO_SOUND = 1 CORE_DEFINE := -DWANT_VB_EMU - CORE_DIR := $(MEDNAFEN_DIR)/vb-0926 + CORE_DIR := $(MEDNAFEN_DIR)/vb-09333 CORE_SOURCES := $(CORE_DIR)/input.cpp \ $(CORE_DIR)/timer.cpp \ diff --git a/libretro.cpp b/libretro.cpp index 7654c7b..8d804f3 100644 --- a/libretro.cpp +++ b/libretro.cpp @@ -162,7 +162,7 @@ static bool is_pal = false; #elif defined(WANT_VB_EMU) #define MEDNAFEN_CORE_NAME_MODULE "vb" #define MEDNAFEN_CORE_NAME "Mednafen VB" -#define MEDNAFEN_CORE_VERSION "v0.9.26" +#define MEDNAFEN_CORE_VERSION "v0.9.33.3" #define MEDNAFEN_CORE_EXTENSIONS "vb|vboy|bin" #define MEDNAFEN_CORE_TIMING_FPS 50.27 #define MEDNAFEN_CORE_GEOMETRY_BASE_W (game->nominal_width) diff --git a/mednafen/hw_cpu/v810/fpu-new/.deps/softfloat.Po b/mednafen/hw_cpu/v810/fpu-new/.deps/softfloat.Po new file mode 100644 index 0000000..9ce06a8 --- /dev/null +++ b/mednafen/hw_cpu/v810/fpu-new/.deps/softfloat.Po @@ -0,0 +1 @@ +# dummy diff --git a/mednafen/hw_cpu/v810/fpu-new/mednafen-gcc.h b/mednafen/hw_cpu/v810/fpu-new/mednafen-gcc.h index f0d0367..477c903 100644 --- a/mednafen/hw_cpu/v810/fpu-new/mednafen-gcc.h +++ b/mednafen/hw_cpu/v810/fpu-new/mednafen-gcc.h @@ -2,7 +2,7 @@ #include #endif -#include +#include /*---------------------------------------------------------------------------- | One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. diff --git a/mednafen/hw_cpu/v810/fpu-new/softfloat-macros b/mednafen/hw_cpu/v810/fpu-new/softfloat-macros index 58f2974..b4f7448 100644 --- a/mednafen/hw_cpu/v810/fpu-new/softfloat-macros +++ b/mednafen/hw_cpu/v810/fpu-new/softfloat-macros @@ -39,11 +39,6 @@ these four paragraphs for those parts of this code that are retained. | The result is stored in the location pointed to by `zPtr'. *----------------------------------------------------------------------------*/ -#ifdef _WIN32 -#undef INLINE -#define INLINE -#endif - INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) { bits32 z; diff --git a/mednafen/hw_cpu/v810/fpu-new/softfloat.c b/mednafen/hw_cpu/v810/fpu-new/softfloat.c index f2e560c..ce4a72f 100644 --- a/mednafen/hw_cpu/v810/fpu-new/softfloat.c +++ b/mednafen/hw_cpu/v810/fpu-new/softfloat.c @@ -2009,7 +2009,7 @@ float64 float64_rem( float64 a, float64 b ) sub64( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); } while ( 0 <= (sbits32) aSig0 ); add64( - aSig0, aSig1, alternateASig0, alternateASig1, (bits32*)&sigMean0, &sigMean1 ); + aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 ); if ( ( sigMean0 < 0 ) || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { aSig0 = alternateASig0; diff --git a/mednafen/hw_cpu/v810/v810_cpu.cpp b/mednafen/hw_cpu/v810/v810_cpu.cpp index 604b4be..097c012 100644 --- a/mednafen/hw_cpu/v810/v810_cpu.cpp +++ b/mednafen/hw_cpu/v810/v810_cpu.cpp @@ -83,6 +83,9 @@ V810::V810() memset(MemReadBus32, 0, sizeof(MemReadBus32)); memset(MemWriteBus32, 0, sizeof(MemWriteBus32)); + + v810_timestamp = 0; + next_event_ts = 0x7FFFFFFF; } V810::~V810() @@ -286,9 +289,6 @@ void V810::Reset() if(ADDBT) ADDBT(GetPC(), 0xFFFFFFF0, 0xFFF0); #endif - v810_timestamp = 0; - next_event_ts = 0x7FFFFFFF; // fixme - memset(&Cache, 0, sizeof(Cache)); memset(P_REG, 0, sizeof(P_REG)); @@ -449,7 +449,7 @@ INLINE void V810::SetSZ(uint32 value) } #ifdef WANT_DEBUGGER -void V810::CheckBreakpoints(void (*callback)(int type, uint32 address, unsigned int len), uint16 MDFN_FASTCALL (*peek16)(const v810_timestamp_t, uint32), uint32 MDFN_FASTCALL (*peek32)(const v810_timestamp_t, uint32)) +void V810::CheckBreakpoints(void (*callback)(int type, uint32 address, uint32 value, unsigned int len), uint16 MDFN_FASTCALL (*peek16)(const v810_timestamp_t, uint32), uint32 MDFN_FASTCALL (*peek32)(const v810_timestamp_t, uint32)) { unsigned int opcode; uint16 tmpop; @@ -472,21 +472,21 @@ void V810::CheckBreakpoints(void (*callback)(int type, uint32 address, unsigned default: break; - case LD_B: callback(BPOINT_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFF, 1); break; - case LD_H: callback(BPOINT_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFE, 2); break; - case LD_W: callback(BPOINT_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFC, 4); break; + case LD_B: callback(BPOINT_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFF, 0, 1); break; + case LD_H: callback(BPOINT_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFE, 0, 2); break; + case LD_W: callback(BPOINT_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFC, 0, 4); break; - case ST_B: callback(BPOINT_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFF, 1); break; - case ST_H: callback(BPOINT_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFE, 2); break; - case ST_W: callback(BPOINT_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFC, 4); break; + case ST_B: callback(BPOINT_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFF, P_REG[(tmpop >> 5) & 0x1F] & 0x00FF, 1); break; + case ST_H: callback(BPOINT_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFE, P_REG[(tmpop >> 5) & 0x1F] & 0xFFFF, 2); break; + case ST_W: callback(BPOINT_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFC, P_REG[(tmpop >> 5) & 0x1F], 4); break; - case IN_B: callback(BPOINT_IO_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFF, 1); break; - case IN_H: callback(BPOINT_IO_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFE, 2); break; - case IN_W: callback(BPOINT_IO_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFC, 4); break; + case IN_B: callback(BPOINT_IO_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFF, 0, 1); break; + case IN_H: callback(BPOINT_IO_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFE, 0, 2); break; + case IN_W: callback(BPOINT_IO_READ, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFC, 0, 4); break; - case OUT_B: callback(BPOINT_IO_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFF, 1); break; - case OUT_H: callback(BPOINT_IO_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFE, 2); break; - case OUT_W: callback(BPOINT_IO_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFC, 4); break; + case OUT_B: callback(BPOINT_IO_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFF, P_REG[(tmpop >> 5) & 0x1F] & 0xFF, 1); break; + case OUT_H: callback(BPOINT_IO_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFE, P_REG[(tmpop >> 5) & 0x1F] & 0xFFFF, 2); break; + case OUT_W: callback(BPOINT_IO_WRITE, (sign_16(tmpop_high)+P_REG[tmpop & 0x1F])&0xFFFFFFFC, P_REG[(tmpop >> 5) & 0x1F], 4); break; } } @@ -600,8 +600,7 @@ INLINE uint32 V810::GetSREG(unsigned int which) // Define accurate mode defines #define RB_GETPC() PC -#define RB_RDOP2(PC_offset, b) RDOP(timestamp, PC + PC_offset, b) -#define RB_RDOP(PC_offset) RDOP(timestamp, PC + PC_offset) +#define RB_RDOP(PC_offset, ...) RDOP(timestamp, PC + PC_offset, ## __VA_ARGS__) void V810::Run_Accurate(int32 MDFN_FASTCALL (*event_handler)(const v810_timestamp_t timestamp)) @@ -618,12 +617,21 @@ void V810::Run_Accurate(int32 MDFN_FASTCALL (*event_handler)(const v810_timestam } #ifdef WANT_DEBUGGER + +/* Make sure class member variable v810_timestamp is synchronized to our local copy, since we'll read it externally if a system + reset/power occurs when in step mode or similar. +*/ +#define RB_CPUHOOK_DBG(n) { if(CPUHook) { v810_timestamp = timestamp_rl; CPUHook(timestamp_rl, n); } } + void V810::Run_Accurate_Debug(int32 MDFN_FASTCALL (*event_handler)(const v810_timestamp_t timestamp)) { const bool RB_AccurateMode = true; - #define RB_ADDBT(n,o,p) ADDBT(n,o,p) - #define RB_CPUHOOK(n) {if(CPUHook) CPUHook(n); } + #define RB_ADDBT(n,o,p) { if(ADDBT) ADDBT(n,o,p); } + /* Make sure class member variable v810_timestamp is synchronized to our local copy, since we'll read it externally if a system + reset/power occurs when in step mode or similar. + */ + #define RB_CPUHOOK(n) RB_CPUHOOK_DBG(n) #define RB_DEBUGMODE #include "v810_oploop.inc" @@ -639,7 +647,6 @@ void V810::Run_Accurate_Debug(int32 MDFN_FASTCALL (*event_handler)(const v810_ti // #undef RB_GETPC #undef RB_RDOP -#undef RB_RDOP2 @@ -647,8 +654,8 @@ void V810::Run_Accurate_Debug(int32 MDFN_FASTCALL (*event_handler)(const v810_ti // Define fast mode defines // #define RB_GETPC() ((uint32)(PC_ptr - PC_base)) -#define RB_RDOP(PC_offset) LoadU16_LE((uint16 *)&PC_ptr[PC_offset]) -#define RB_RDOP2(PC_offset, b) LoadU16_LE((uint16 *)&PC_ptr[PC_offset]) + +#define RB_RDOP(PC_offset, ...) LoadU16_LE((uint16 *)&PC_ptr[PC_offset]) void V810::Run_Fast(int32 MDFN_FASTCALL (*event_handler)(const v810_timestamp_t timestamp)) { @@ -668,8 +675,8 @@ void V810::Run_Fast_Debug(int32 MDFN_FASTCALL (*event_handler)(const v810_timest { const bool RB_AccurateMode = false; - #define RB_ADDBT(n,o,p) ADDBT(n,o,p) - #define RB_CPUHOOK(n) { if(CPUHook) CPUHook(n); } + #define RB_ADDBT(n,o,p) { if(ADDBT) ADDBT(n,o,p); } + #define RB_CPUHOOK(n) RB_CPUHOOK_DBG(n) #define RB_DEBUGMODE #include "v810_oploop.inc" @@ -685,14 +692,13 @@ void V810::Run_Fast_Debug(int32 MDFN_FASTCALL (*event_handler)(const v810_timest // #undef RB_GETPC #undef RB_RDOP -#undef RB_RDOP2 v810_timestamp_t V810::Run(int32 MDFN_FASTCALL (*event_handler)(const v810_timestamp_t timestamp)) { Running = true; #ifdef WANT_DEBUGGER - if(CPUHook) + if(CPUHook || ADDBT) { if(EmuMode == V810_EMU_MODE_FAST) Run_Fast_Debug(event_handler); @@ -716,7 +722,7 @@ void V810::Exit(void) } #ifdef WANT_DEBUGGER -void V810::SetCPUHook(void (*newhook)(uint32 PC), void (*new_ADDBT)(uint32 old_PC, uint32 new_PC, uint32)) +void V810::SetCPUHook(void (*newhook)(const v810_timestamp_t timestamp, uint32 PC), void (*new_ADDBT)(uint32 old_PC, uint32 new_PC, uint32)) { CPUHook = newhook; ADDBT = new_ADDBT; @@ -953,6 +959,104 @@ bool V810::bstr_subop(v810_timestamp_t ×tamp, int sub_op, int arg1) uint32 dst = (P_REG[29] & 0xFFFFFFFC); uint32 src = (P_REG[30] & 0xFFFFFFFC); +#if 0 + // Be careful not to cause 32-bit integer overflow, and careful about not shifting by 32. + // TODO: + + // Read src[0], src[4] into shifter. + // Read dest[0]. + DO_BSTR_PROLOGUE(); // if(len) { blah blah blah masking blah } + src_cache = BSTR_RWORD(timestamp, src); + + if((uint64)(srcoff + len) > 0x20) + src_cache |= (uint64)BSTR_RWORD(timestamp, src + 4) << 32; + + dst_cache = BSTR_RWORD(timestamp, dst); + + if(len) + { + uint32 dst_preserve_mask; + uint32 dst_change_mask; + + dst_preserve_mask = (1U << dstoff) - 1; + + if((uint64)(dstoff + len) < 0x20) + dst_preserve_mask |= ((1U << ((0x20 - (dstoff + len)) & 0x1F)) - 1) << (dstoff + len); + + dst_change_mask = ~dst_preserve_mask; + + src_cache = BSTR_RWORD(timestamp, src); + src_cache |= (uint64)BSTR_RWORD(timestamp, src + 4) << 32; + dst_cache = BSTR_RWORD(timestamp, dst); + + dst_cache = (dst_cache & dst_preserve_mask) | ((dst_cache OP_THINGY_HERE (src_cache >> srcoff)) & dst_change_mask); + BSTR_WWORD(timestamp, dst, dst_cache); + + if((uint64)(dstoff + len) < 0x20) + { + srcoff += len; + dstoff += len; + len = 0; + } + else + { + srcoff += (0x20 - dstoff); + dstoff = 0; + len -= (0x20 - dstoff); + dst += 4; + } + + if(srcoff >= 0x20) + { + srcoff &= 0x1F; + src += 4; + + if(len) + { + src_cache >>= 32; + src_cache |= (uint64)BSTR_RWORD(timestamp, src + 4) << 32; + } + } + } + + DO_BSTR_PRIMARY(); // while(len >= 32) (do allow interruption; interrupt and emulator-return - + // they must be handled differently!) + while(len >= 32) + { + dst_cache = BSTR_RWORD(timestamp, dst); + dst_cache = OP_THINGY_HERE(dst_cache, src_cache >> srcoff); + BSTR_WWORD(timestamp, dst, dst_cache); + len -= 32; + dst += 4; + src += 4; + src_cache >>= 32; + src_cache |= (uint64)BSTR_RWORD(timestamp, src + 4) << 32; + } + + DO_BSTR_EPILOGUE(); // if(len) { blah blah blah masking blah } + if(len) + { + uint32 dst_preserve_mask; + uint32 dst_change_mask; + + dst_preserve_mask = (1U << ((0x20 - len) & 0x1F) << len; + dst_change_mask = ~dst_preserve_mask; + + dst_cache = BSTR_RWORD(timestamp, dst); + dst_cache = OP_THINGY_HERE(dst_cache, src_cache >> srcoff); + BSTR_WWORD(timestamp, dst, dst_cache); + dstoff += len; + srcoff += len; + + if(srcoff >= 0x20) + { + srcoff &= 0x1F; + src += 4; + } + len = 0; + } +#endif + switch(sub_op) { case ORBSU: DO_BSTR(BSTR_OP_OR); break; @@ -1431,6 +1535,8 @@ int V810::StateAction(StateMem *sm, int load, int data_only) } } + int32 next_event_ts_delta = next_event_ts - v810_timestamp; + SFORMAT StateRegs[] = { SFARRAY32(P_REG, 32), @@ -1444,11 +1550,8 @@ int V810::StateAction(StateMem *sm, int load, int data_only) SFARRAY32(cache_data_temp, 128 * 2), SFARRAYB(cache_data_valid_temp, 128 * 2), - SFVAR(ilevel), // Perhaps remove in future? - SFVAR(next_event_ts), // This too - - //SFVAR(tmp_timestamp), - SFVAR(v810_timestamp), + SFVAR(ilevel), // Perhaps remove in future? + SFVAR(next_event_ts_delta), // Bitstring stuff: SFVAR(src_cache), @@ -1465,7 +1568,12 @@ int V810::StateAction(StateMem *sm, int load, int data_only) if(load) { - //clamp(&PCFX_V810.v810_timestamp, 0, 30 * 1000 * 1000); + // std::max is sanity check for a corrupted save state to not crash emulation, + // std::min(0x7FF... is a sanity check and for the case where next_event_ts is set to an extremely large value to + // denote that it's not happening anytime soon, which could cause an overflow if our current timestamp is larger + // than what it was when the state was saved. + next_event_ts = std::max(v810_timestamp, std::min(0x7FFFFFFF, (int64)v810_timestamp + next_event_ts_delta)); + RecalcIPendingCache(); SetPC(PC_tmp); diff --git a/mednafen/hw_cpu/v810/v810_cpu.h b/mednafen/hw_cpu/v810/v810_cpu.h index a819b9c..49c2c8e 100644 --- a/mednafen/hw_cpu/v810/v810_cpu.h +++ b/mednafen/hw_cpu/v810/v810_cpu.h @@ -168,12 +168,12 @@ class V810 // Length specifies the number of bytes to map in, at each location specified by addresses[] (for mirroring) uint8 *SetFastMap(uint32 addresses[], uint32 length, unsigned int num_addresses, const char *name); - INLINE void ResetTS(void) + INLINE void ResetTS(v810_timestamp_t new_base_timestamp) { assert(next_event_ts > v810_timestamp); - next_event_ts -= v810_timestamp; - v810_timestamp = 0; + next_event_ts -= (v810_timestamp - new_base_timestamp); + v810_timestamp = new_base_timestamp; } INLINE void SetEventNT(const v810_timestamp_t timestamp) @@ -194,8 +194,8 @@ class V810 int StateAction(StateMem *sm, int load, int data_only); #ifdef WANT_DEBUGGER - void CheckBreakpoints(void (*callback)(int type, uint32 address, unsigned int len), uint16 MDFN_FASTCALL (*peek16)(const v810_timestamp_t, uint32), uint32 MDFN_FASTCALL (*peek32)(const v810_timestamp_t, uint32)); - void SetCPUHook(void (*newhook)(uint32 PC), void (*new_ADDBT)(uint32, uint32, uint32)); + void CheckBreakpoints(void (*callback)(int type, uint32 address, uint32 value, unsigned int len), uint16 MDFN_FASTCALL (*peek16)(const v810_timestamp_t, uint32), uint32 MDFN_FASTCALL (*peek32)(const v810_timestamp_t, uint32)); + void SetCPUHook(void (*newhook)(const v810_timestamp_t timestamp, uint32 PC), void (*new_ADDBT)(uint32, uint32, uint32)); #endif uint32 GetPC(void); void SetPC(uint32); @@ -313,7 +313,7 @@ class V810 #ifdef WANT_DEBUGGER - void (*CPUHook)(uint32 PC); + void (*CPUHook)(const v810_timestamp_t timestamp, uint32 PC); void (*ADDBT)(uint32 old_PC, uint32 new_PC, uint32); #endif diff --git a/mednafen/hw_cpu/v810/v810_cpuD.cpp b/mednafen/hw_cpu/v810/v810_cpuD.cpp index d880821..f074e28 100644 --- a/mednafen/hw_cpu/v810/v810_cpuD.cpp +++ b/mednafen/hw_cpu/v810/v810_cpuD.cpp @@ -73,7 +73,7 @@ static const operation optable[80] = { { AM_II, "cmp " }, // 0x13 { AM_II, "shl " }, // 0x14 { AM_II, "shr " }, // 0x15 - { AM_UDEF, "??? " }, // 0x16 // Unknown + {0x8000|AM_IX,"ei " }, // 0x16 // EI(VB only) { AM_II, "sar " }, // 0x17 { AM_II, "trap " }, // 0x18 @@ -83,7 +83,7 @@ static const operation optable[80] = { {AM_UDEF, "??? " }, // 0x1B // Unknown { AM_II, "ldsr " }, // 0x1C { AM_II, "stsr " }, // 0x1D - { AM_UDEF, "??? " }, // 0x1E // Unknown + {0x8000|AM_IX,"di " }, // 0x1E // DI(VB only) {AM_BSTR, "BSTR " }, // 0x1F // Special Bit String Instructions {AM_UDEF, "??? " }, // 0x20 // Unknown // This is a fudg on our part @@ -177,6 +177,26 @@ static const suboperation fpsuboptable[16] = { { "subf.s " }, // 0x05 { "mulf.s " }, // 0x06 { "divf.s " }, // 0x07 + + { "FError8" }, // 0x08 // Invalid + { "FError9" }, // 0x09 // Invalid + { "FErrorA" }, // 0x0A // Invalid + { "FErrorB" }, // 0x0B // Invalid + { "FErrorC" }, // 0x0C // Invalid + { "FErrorD" }, // 0x0D // Invalid + { "FErrorE" }, // 0x0E // Invalid + { "FErrorF" } // 0x0F // Invalid +}; + +static const suboperation fpsuboptable_vb[16] = { + { "cmpf.s " }, // 0x00 + { "FError1" }, // 0x01 // Unknown + { "cvt.ws " }, // 0x02 + { "cvt.sw " }, // 0x03 + { "addf.s " }, // 0x04 + { "subf.s " }, // 0x05 + { "mulf.s " }, // 0x06 + { "divf.s " }, // 0x07 { "XB" }, // 0x08 // undocumented { "XH" }, // 0x09 // undocumented //VFishing??? { "REV" }, // 0x0A // undocumented @@ -205,7 +225,7 @@ static const char *pretty_sreg_names[32] = "sr31(invalid)" }; -void v810_dis(uint32 &tPC, int num, char *buf, uint16 (*rhword)(uint32)) +void v810_dis(uint32 &tPC, int num, char *buf, uint16 (*rhword)(uint32), bool vbmode) { int lowB, highB, lowB2, highB2; // up to 4 bytes for instruction (either 16 or 32 bits) int opcode, arg1, arg2, arg3; @@ -215,31 +235,33 @@ void v810_dis(uint32 &tPC, int num, char *buf, uint16 (*rhword)(uint32)) for(i = 0; i< num; i++) { - uint16 tmp; + const uint16 hw0 = rhword(tPC); + const uint16 hw1 = rhword(tPC + 2); - tmp = rhword(tPC); - // lowB = mem_rbyte(tPC); - // highB = mem_rbyte(tPC+1); - lowB = tmp & 0xFF; - highB = tmp >> 8; + lowB = hw0 & 0xFF; + highB = hw0 >> 8; - tmp = rhword(tPC + 2); - // lowB2 = mem_rbyte(tPC+2); - // highB2 = mem_rbyte(tPC+3); - lowB2 = tmp & 0xFF; - highB2 = tmp >> 8; + lowB2 = hw1 & 0xFF; + highB2 = hw1 >> 8; opcode = highB >> 2; - if((highB & 0xE0) == 0x80) // Special opcode format for + if((highB & 0xE0) == 0x80) // Special opcode format for opcode = (highB >> 1); // type III instructions. - + if((opcode > 0x4F) | (opcode < 0)) { //Error Invalid opcode! - sprintf(&buf[strlen(buf)],"0x%2x 0x%2x ;Invalid Opcode", lowB, highB); - tPC += 2; + sprintf(&buf[strlen(buf)], "0x%04x", hw0); + tPC += 2; } - - switch(optable[opcode].addr_mode) { + + int am = optable[opcode].addr_mode; + + if((am & 0x8000) && !vbmode) + am = AM_UDEF; + + am &= ~0x8000; + + switch(am) { case AM_I: // Do the same Ither way =) arg1 = (lowB >> 5) + ((highB & 0x3) << 3); arg2 = (lowB & 0x1F); @@ -350,14 +372,14 @@ void v810_dis(uint32 &tPC, int num, char *buf, uint16 (*rhword)(uint32)) if(arg3 > 15) { sprintf(&buf[strlen(buf)],"(Invalid FPU: 0x%02x)", arg3); } else { - sprintf(&buf[strlen(buf)],"%s %s, %s", fpsuboptable[arg3].opname, pretty_preg_names[arg2], pretty_preg_names[arg1]); + sprintf(&buf[strlen(buf)],"%s %s, %s", (vbmode ? fpsuboptable_vb[arg3].opname : fpsuboptable[arg3].opname), pretty_preg_names[arg2], pretty_preg_names[arg1]); } tPC += 4; // 32 bit instruction break; case AM_UDEF: // Invalid opcode. default: // Invalid opcode. - sprintf(&buf[strlen(buf)],"0x%2x 0x%2x ;Invalid Opcode", lowB, highB); - tPC += 2; + sprintf(&buf[strlen(buf)],"0x%04x", hw0); + tPC += 2; } } } diff --git a/mednafen/hw_cpu/v810/v810_cpuD.h b/mednafen/hw_cpu/v810/v810_cpuD.h index db5ebad..6169f41 100644 --- a/mednafen/hw_cpu/v810/v810_cpuD.h +++ b/mednafen/hw_cpu/v810/v810_cpuD.h @@ -9,7 +9,7 @@ #include "v810_opt.h" // Dissasemble num lines of code starting at tPC (If tPC == -1 start at PC) -void v810_dis(uint32 &PC, int num, char *, uint16 (*rhword)(uint32)); +void v810_dis(uint32 &PC, int num, char *, uint16 (*rhword)(uint32), bool vbmode = false); #endif diff --git a/mednafen/hw_cpu/v810/v810_oploop.inc b/mednafen/hw_cpu/v810/v810_oploop.inc index a71981f..035e20a 100644 --- a/mednafen/hw_cpu/v810/v810_oploop.inc +++ b/mednafen/hw_cpu/v810/v810_oploop.inc @@ -67,16 +67,14 @@ P_REG[0] = 0; //Zero the Zero Reg!!! - //v810_timestamp = timestamp_rl; RB_CPUHOOK(RB_GETPC()); - //timestamp_rl = v810_timestamp; { //printf("%08x\n", RB_GETPC()); { v810_timestamp_t timestamp = timestamp_rl; - tmpop = RB_RDOP2(0, 0); + tmpop = RB_RDOP(0, 0); timestamp_rl = timestamp; } @@ -85,16 +83,12 @@ //printf("%02x\n", opcode >> 1); - #ifdef _MSC_VER - #include "v810_op_table_msvc.inc" - #else static const void *const op_goto_table[256] = { #include "v810_op_table.inc" }; goto *op_goto_table[opcode]; - #endif // Bit string subopcodes #define DO_AM_BSTR() \ @@ -292,12 +286,8 @@ BEGIN_OP(SETF); ADDCLOCK(1); - //SETF may contain bugs P_REG[arg2] = 0; - //if(arg1 != 0xe) - //printf("SETF: %02x\n", arg1); - //snortus(); switch (arg1 & 0x0F) { case COND_V: @@ -841,7 +831,7 @@ SetPREG(30, (uint32)(temp >> 32)); SetPREG(arg2, temp); SetSZ(P_REG[arg2]); - SetFlag(PSW_OV, temp != (uint32)temp); + SetFlag(PSW_OV, temp != (uint64)(int64)(int32)(uint32)temp); lastop = -1; END_OP_SKIPLO(); @@ -1053,7 +1043,7 @@ if(!RB_AccurateMode) { RB_SETPC(RB_GETPC()); - if((uint32)(RB_RDOP2(0, 0) >> 9) != opcode) + if((uint32)(RB_RDOP(0, 0) >> 9) != opcode) { //printf("Trampoline: %08x %02x\n", RB_GETPC(), opcode >> 1); } diff --git a/mednafen/vb-09333/.deps/debug.Po b/mednafen/vb-09333/.deps/debug.Po new file mode 100644 index 0000000..9ce06a8 --- /dev/null +++ b/mednafen/vb-09333/.deps/debug.Po @@ -0,0 +1 @@ +# dummy diff --git a/mednafen/vb-09333/.deps/input.Po b/mednafen/vb-09333/.deps/input.Po new file mode 100644 index 0000000..9ce06a8 --- /dev/null +++ b/mednafen/vb-09333/.deps/input.Po @@ -0,0 +1 @@ +# dummy diff --git a/mednafen/vb-09333/.deps/timer.Po b/mednafen/vb-09333/.deps/timer.Po new file mode 100644 index 0000000..9ce06a8 --- /dev/null +++ b/mednafen/vb-09333/.deps/timer.Po @@ -0,0 +1 @@ +# dummy diff --git a/mednafen/vb-09333/.deps/vb.Po b/mednafen/vb-09333/.deps/vb.Po new file mode 100644 index 0000000..9ce06a8 --- /dev/null +++ b/mednafen/vb-09333/.deps/vb.Po @@ -0,0 +1 @@ +# dummy diff --git a/mednafen/vb-09333/.deps/vip.Po b/mednafen/vb-09333/.deps/vip.Po new file mode 100644 index 0000000..9ce06a8 --- /dev/null +++ b/mednafen/vb-09333/.deps/vip.Po @@ -0,0 +1 @@ +# dummy diff --git a/mednafen/vb-09333/.deps/vsu.Po b/mednafen/vb-09333/.deps/vsu.Po new file mode 100644 index 0000000..9ce06a8 --- /dev/null +++ b/mednafen/vb-09333/.deps/vsu.Po @@ -0,0 +1 @@ +# dummy diff --git a/mednafen/vb-09333/Makefile b/mednafen/vb-09333/Makefile new file mode 100644 index 0000000..3f1f208 --- /dev/null +++ b/mednafen/vb-09333/Makefile @@ -0,0 +1,633 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# src/vb/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/mednafen +pkgincludedir = $(includedir)/mednafen +pkglibdir = $(libdir)/mednafen +pkglibexecdir = $(libexecdir)/mednafen +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = x86_64-unknown-linux-gnu +host_triplet = x86_64-unknown-linux-gnu +target_triplet = x86_64-unknown-linux-gnu +am__append_1 = debug.cpp +subdir = src/vb +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/fcntl-o.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ + $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ + $(top_srcdir)/m4/inttypes-pri.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/uintmax_t.m4 \ + $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ + $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +AM_V_AR = $(am__v_AR_$(V)) +am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY)) +am__v_AR_0 = @echo " AR " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +libvb_a_AR = $(AR) $(ARFLAGS) +libvb_a_LIBADD = +am__libvb_a_SOURCES_DIST = vb.cpp timer.cpp input.cpp vip.cpp vsu.cpp \ + debug.cpp +am__objects_1 = debug.$(OBJEXT) +am_libvb_a_OBJECTS = vb.$(OBJEXT) timer.$(OBJEXT) input.$(OBJEXT) \ + vip.$(OBJEXT) vsu.$(OBJEXT) $(am__objects_1) +libvb_a_OBJECTS = $(am_libvb_a_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_$(V)) +am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY)) +am__v_CXX_0 = @echo " CXX " $@; +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_$(V)) +am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CXXLD_0 = @echo " CXXLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libvb_a_SOURCES) +DIST_SOURCES = $(am__libvb_a_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = ${SHELL} /home/squarepusher/Downloads/mednafen/missing --run aclocal-1.11 +ALLOCA = +ALSA_CFLAGS = +ALSA_LIBS = -lasound -lm -ldl -lpthread +AMTAR = $${TAR-tar} +AM_CFLAGS = -fsigned-char -Wall -Winline -Wshadow -Wempty-body -Wignored-qualifiers -fno-fast-math -fno-unsafe-math-optimizations -fno-aggressive-loop-optimizations -fomit-frame-pointer -finline-limit=6000 --param large-function-growth=800 --param inline-unit-growth=175 --param max-inline-insns-single=10000 -fno-strict-overflow +AM_CXXFLAGS = -fsigned-char -Wall -Winline -Wshadow -Wempty-body -Wignored-qualifiers -fno-fast-math -fno-unsafe-math-optimizations -fno-aggressive-loop-optimizations -fomit-frame-pointer -finline-limit=6000 --param large-function-growth=800 --param inline-unit-growth=175 --param max-inline-insns-single=10000 -fno-strict-overflow +AM_DEFAULT_VERBOSITY = 1 +AR = ar +AUTOCONF = ${SHELL} /home/squarepusher/Downloads/mednafen/missing --run autoconf +AUTOHEADER = ${SHELL} /home/squarepusher/Downloads/mednafen/missing --run autoheader +AUTOMAKE = ${SHELL} /home/squarepusher/Downloads/mednafen/missing --run automake-1.11 +AWK = gawk +BUILD_INCLUDED_LIBINTL = no +CATOBJEXT = .gmo +CC = gcc +CCAS = gcc +CCASDEPMODE = depmode=gcc3 +CCASFLAGS = -g -O2 +CCDEPMODE = depmode=gcc3 +CFLAGS = -g -O2 +CFLAG_VISIBILITY = -fvisibility=hidden +CPP = gcc -E +CPPFLAGS = +CXX = g++ +CXXCPP = g++ -E +CXXDEPMODE = depmode=gcc3 +CXXFLAGS = -g -O2 +CYGPATH_W = echo +DATADIRNAME = share +DEFS = -DLOCALEDIR=\"$(datadir)/locale\" -DHAVE_CONFIG_H -fno-strict-aliasing +DEPDIR = .deps +DLLTOOL = false +DSYMUTIL = +DUMPBIN = +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /usr/bin/grep -E +EXEEXT = +FGREP = /usr/bin/grep -F +GBA_EXTRA_FLAGS = -fno-unit-at-a-time +GENCAT = gencat +GETTEXT_MACRO_VERSION = 0.18 +GLIBC2 = yes +GLIBC21 = yes +GMSGFMT = /usr/bin/msgfmt +GMSGFMT_015 = /usr/bin/msgfmt +GREP = /usr/bin/grep +HAVE_ASPRINTF = 1 +HAVE_NEWLOCALE = 1 +HAVE_POSIX_PRINTF = 1 +HAVE_SNPRINTF = 1 +HAVE_VISIBILITY = 1 +HAVE_WPRINTF = 0 +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +INSTOBJEXT = .mo +INTLBISON = bison +INTLLIBS = +INTLOBJS = +INTL_DEFAULT_VERBOSITY = 1 +INTL_LIBTOOL_SUFFIX_PREFIX = +INTL_MACOSX_LIBS = +JACK_CFLAGS = +JACK_LIBS = -ljack -lpthread +LD = /usr/bin/ld -m elf_x86_64 +LDFLAGS = +LIBCDIO_CFLAGS = +LIBCDIO_LIBS = -lcdio -lm +LIBICONV = +LIBINTL = +LIBMULTITHREAD = -lpthread +LIBOBJS = +LIBPTH = +LIBPTH_PREFIX = +LIBS = -lsndfile -lcdio -lm -lz -lz -lasound -lm -ldl -lpthread -ljack -lpthread +LIBTHREAD = +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIPO = +LN_S = ln -s +LTLIBC = -lc +LTLIBICONV = +LTLIBINTL = +LTLIBMULTITHREAD = -lpthread +LTLIBOBJS = +LTLIBPTH = +LTLIBTHREAD = +MAKEINFO = ${SHELL} /home/squarepusher/Downloads/mednafen/missing --run makeinfo +MANIFEST_TOOL = : +MKDIR_P = /usr/bin/mkdir -p +MMX_CFLAGS = -mmmx +MSGFMT = /usr/bin/msgfmt +MSGFMT_015 = /usr/bin/msgfmt +MSGMERGE = /usr/bin/msgmerge +NM = /usr/bin/nm -B +NMEDIT = +OBJDUMP = objdump +OBJEXT = o +OTOOL = +OTOOL64 = +PACKAGE = mednafen +PACKAGE_BUGREPORT = +PACKAGE_NAME = +PACKAGE_STRING = +PACKAGE_TARNAME = +PACKAGE_URL = +PACKAGE_VERSION = +PATH_SEPARATOR = : +PKG_CONFIG = /usr/bin/pkg-config +PKG_CONFIG_LIBDIR = +PKG_CONFIG_PATH = +POSUB = po +PRI_MACROS_BROKEN = 0 +RANLIB = ranlib +SDL_CFLAGS = -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT +SDL_CONFIG = /usr/bin/sdl-config +SDL_LIBS = -L/usr/lib -lSDL -lpthread +SED = /usr/bin/sed +SET_MAKE = +SHELL = /bin/sh +SNDFILE_CFLAGS = +SNDFILE_LIBS = -lsndfile +SNES_EXTRA_CXXFLAGS = +SNES_EXTRA_FLAGS = -Wno-unused -Wno-inline -Wno-shadow -Wno-sign-compare -Wno-ignored-qualifiers -Wno-uninitialized -Wno-parentheses -Wno-switch +SNES_PERF_EXTRA_CXXFLAGS = -funswitch-loops -fpredictive-commoning -fgcse-after-reload -ftree-vectorize -fipa-cp-clone -fno-stack-protector +SNES_PERF_EXTRA_FLAGS = -Wno-unused -Wno-inline -Wno-shadow -Wno-sign-compare -Wno-ignored-qualifiers -Wno-uninitialized -Wno-parentheses -Wno-switch +SSE2_CFLAGS = -msse2 +SSE3_CFLAGS = -msse3 +SSE_CFLAGS = -msse +STRIP = strip +TRIO_CFLAGS = +USE_INCLUDED_LIBINTL = no +USE_NLS = yes +VERSION = 0.9.33.3 +WARNING_FLAGS = -Wall -Winline -Wshadow -Wempty-body -Wignored-qualifiers +WINDRES = +WOE32 = no +WOE32DLL = no +XGETTEXT = /usr/bin/xgettext +XGETTEXT_015 = /usr/bin/xgettext +XGETTEXT_EXTRA_OPTIONS = +abs_builddir = /home/squarepusher/Downloads/mednafen/src/vb +abs_srcdir = /home/squarepusher/Downloads/mednafen/src/vb +abs_top_builddir = /home/squarepusher/Downloads/mednafen +abs_top_srcdir = /home/squarepusher/Downloads/mednafen +ac_ct_AR = ar +ac_ct_CC = gcc +ac_ct_CXX = g++ +ac_ct_DUMPBIN = +am__include = include +am__leading_dot = . +am__quote = +am__tar = $${TAR-tar} chof - "$$tardir" +am__untar = $${TAR-tar} xf - +bindir = ${exec_prefix}/bin +build = x86_64-unknown-linux-gnu +build_alias = +build_cpu = x86_64 +build_os = linux-gnu +build_vendor = unknown +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE} +dvidir = ${docdir} +exec_prefix = ${prefix} +host = x86_64-unknown-linux-gnu +host_alias = +host_cpu = x86_64 +host_os = linux-gnu +host_vendor = unknown +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /home/squarepusher/Downloads/mednafen/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = /usr/bin/mkdir -p +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = /usr/local +program_transform_name = s,x,x, +psdir = ${docdir} +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target = x86_64-unknown-linux-gnu +target_alias = +target_cpu = x86_64 +target_os = linux-gnu +target_vendor = unknown +top_build_prefix = ../../ +top_builddir = ../.. +top_srcdir = ../.. +AUTOMAKE_OPTIONS = subdir-objects +DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir) +noinst_LIBRARIES = libvb.a +libvb_a_SOURCES = vb.cpp timer.cpp input.cpp vip.cpp vsu.cpp \ + $(am__append_1) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/vb/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/vb/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libvb.a: $(libvb_a_OBJECTS) $(libvb_a_DEPENDENCIES) $(EXTRA_libvb_a_DEPENDENCIES) + $(AM_V_at)-rm -f libvb.a + $(AM_V_AR)$(libvb_a_AR) libvb.a $(libvb_a_OBJECTS) $(libvb_a_LIBADD) + $(AM_V_at)$(RANLIB) libvb.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/debug.Po +include ./$(DEPDIR)/input.Po +include ./$(DEPDIR)/timer.Po +include ./$(DEPDIR)/vb.Po +include ./$(DEPDIR)/vip.Po +include ./$(DEPDIR)/vsu.Po + +.cpp.o: + $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ + $(am__mv) $$depbase.Tpo $$depbase.Po +# $(AM_V_CXX)source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ + $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ + $(am__mv) $$depbase.Tpo $$depbase.Po +# $(AM_V_CXX)source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: + $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ + $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ + $(am__mv) $$depbase.Tpo $$depbase.Plo +# $(AM_V_CXX)source='$<' object='$@' libtool=yes \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/mednafen/vb-09333/Makefile.am b/mednafen/vb-09333/Makefile.am new file mode 100644 index 0000000..378645a --- /dev/null +++ b/mednafen/vb-09333/Makefile.am @@ -0,0 +1,10 @@ +AUTOMAKE_OPTIONS = subdir-objects +DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ -fno-strict-aliasing +DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir) + +noinst_LIBRARIES = libvb.a +libvb_a_SOURCES = vb.cpp timer.cpp input.cpp vip.cpp vsu.cpp + +if WANT_DEBUGGER +libvb_a_SOURCES += debug.cpp +endif diff --git a/mednafen/vb-09333/Makefile.in b/mednafen/vb-09333/Makefile.in new file mode 100644 index 0000000..2ace7a7 --- /dev/null +++ b/mednafen/vb-09333/Makefile.in @@ -0,0 +1,633 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@WANT_DEBUGGER_TRUE@am__append_1 = debug.cpp +subdir = src/vb +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/fcntl-o.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ + $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ + $(top_srcdir)/m4/inttypes-pri.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/uintmax_t.m4 \ + $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ + $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +libvb_a_AR = $(AR) $(ARFLAGS) +libvb_a_LIBADD = +am__libvb_a_SOURCES_DIST = vb.cpp timer.cpp input.cpp vip.cpp vsu.cpp \ + debug.cpp +@WANT_DEBUGGER_TRUE@am__objects_1 = debug.$(OBJEXT) +am_libvb_a_OBJECTS = vb.$(OBJEXT) timer.$(OBJEXT) input.$(OBJEXT) \ + vip.$(OBJEXT) vsu.$(OBJEXT) $(am__objects_1) +libvb_a_OBJECTS = $(am_libvb_a_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libvb_a_SOURCES) +DIST_SOURCES = $(am__libvb_a_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AM_CFLAGS = @AM_CFLAGS@ +AM_CXXFLAGS = @AM_CXXFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ -fno-strict-aliasing +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GBA_EXTRA_FLAGS = @GBA_EXTRA_FLAGS@ +GENCAT = @GENCAT@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIBC2 = @GLIBC2@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +HAVE_ASPRINTF = @HAVE_ASPRINTF@ +HAVE_NEWLOCALE = @HAVE_NEWLOCALE@ +HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@ +HAVE_SNPRINTF = @HAVE_SNPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WPRINTF = @HAVE_WPRINTF@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_DEFAULT_VERBOSITY = @INTL_DEFAULT_VERBOSITY@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +JACK_CFLAGS = @JACK_CFLAGS@ +JACK_LIBS = @JACK_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCDIO_CFLAGS = @LIBCDIO_CFLAGS@ +LIBCDIO_LIBS = @LIBCDIO_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBPTH_PREFIX = @LIBPTH_PREFIX@ +LIBS = @LIBS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBC = @LTLIBC@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMX_CFLAGS = @MMX_CFLAGS@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ +SNDFILE_LIBS = @SNDFILE_LIBS@ +SNES_EXTRA_CXXFLAGS = @SNES_EXTRA_CXXFLAGS@ +SNES_EXTRA_FLAGS = @SNES_EXTRA_FLAGS@ +SNES_PERF_EXTRA_CXXFLAGS = @SNES_PERF_EXTRA_CXXFLAGS@ +SNES_PERF_EXTRA_FLAGS = @SNES_PERF_EXTRA_FLAGS@ +SSE2_CFLAGS = @SSE2_CFLAGS@ +SSE3_CFLAGS = @SSE3_CFLAGS@ +SSE_CFLAGS = @SSE_CFLAGS@ +STRIP = @STRIP@ +TRIO_CFLAGS = @TRIO_CFLAGS@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WARNING_FLAGS = @WARNING_FLAGS@ +WINDRES = @WINDRES@ +WOE32 = @WOE32@ +WOE32DLL = @WOE32DLL@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = subdir-objects +DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir) +noinst_LIBRARIES = libvb.a +libvb_a_SOURCES = vb.cpp timer.cpp input.cpp vip.cpp vsu.cpp \ + $(am__append_1) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/vb/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/vb/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libvb.a: $(libvb_a_OBJECTS) $(libvb_a_DEPENDENCIES) $(EXTRA_libvb_a_DEPENDENCIES) + $(AM_V_at)-rm -f libvb.a + $(AM_V_AR)$(libvb_a_AR) libvb.a $(libvb_a_OBJECTS) $(libvb_a_LIBADD) + $(AM_V_at)$(RANLIB) libvb.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vsu.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/mednafen/vb-09333/debug.cpp b/mednafen/vb-09333/debug.cpp new file mode 100644 index 0000000..cc919d1 --- /dev/null +++ b/mednafen/vb-09333/debug.cpp @@ -0,0 +1,681 @@ +/* Mednafen - Multi-system Emulator + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "vb.h" +#include +#include +#include +#include +#include + +#include "debug.h" +#include "timer.h" +//#include "input.h" +#include "vip.h" +#include "vsu.h" +#include "timer.h" + +namespace MDFN_IEN_VB +{ + +extern V810 *VB_V810; +extern VSU *VB_VSU; + +static void RedoCPUHook(void); +static void (*CPUHook)(uint32, bool bpoint) = NULL; +static bool CPUHookContinuous = false; +static void (*LogFunc)(const char *, const char *); +bool VB_LoggingOn = FALSE; + +typedef struct __VB_BPOINT { + uint32 A[2]; + int type; + bool logical; +} VB_BPOINT; + +static std::vector BreakPointsPC, BreakPointsRead, BreakPointsWrite; +static bool FoundBPoint = 0; + +struct BTEntry +{ + uint32 from; + uint32 to; + uint32 branch_count; + uint32 ecode; + bool valid; +}; + +#define NUMBT 24 +static BTEntry BTEntries[NUMBT]; +static int BTIndex; +static bool BTEnabled; + +static void AddBranchTrace(uint32 from, uint32 to, uint32 ecode) +{ + BTEntry *prevbt = &BTEntries[(BTIndex + NUMBT - 1) % NUMBT]; + + //if(BTEntries[(BTIndex - 1) & 0xF] == PC) return; + + if(prevbt->from == from && prevbt->to == to && prevbt->ecode == ecode && prevbt->branch_count < 0xFFFFFFFF && prevbt->valid) + prevbt->branch_count++; + else + { + BTEntries[BTIndex].from = from; + BTEntries[BTIndex].to = to; + BTEntries[BTIndex].ecode = ecode; + BTEntries[BTIndex].branch_count = 1; + BTEntries[BTIndex].valid = true; + + BTIndex = (BTIndex + 1) % NUMBT; + } +} + +void VBDBG_EnableBranchTrace(bool enable) +{ + BTEnabled = enable; + if(!enable) + { + BTIndex = 0; + memset(BTEntries, 0, sizeof(BTEntries)); + } + + RedoCPUHook(); +} + +std::vector VBDBG_GetBranchTrace(void) +{ + BranchTraceResult tmp; + std::vector ret; + + for(int x = 0; x < NUMBT; x++) + { + const BTEntry *bt = &BTEntries[(x + BTIndex) % NUMBT]; + + if(!bt->valid) + continue; + + tmp.count = bt->branch_count; + trio_snprintf(tmp.from, sizeof(tmp.from), "%08x", bt->from); + trio_snprintf(tmp.to, sizeof(tmp.to), "%08x", bt->to); + + tmp.code[0] = 0; + + switch(bt->ecode) + { + case 0: break; + default: trio_snprintf(tmp.code, sizeof(tmp.code), "e"); + break; + + case 0xFFF0: // Reset + trio_snprintf(tmp.code, sizeof(tmp.code), "R"); + break; + + case 0xFFD0: // NMI + trio_snprintf(tmp.code, sizeof(tmp.code), "NMI"); + break; + + case 0xFFC0: // Address trap + trio_snprintf(tmp.code, sizeof(tmp.code), "ADTR"); + break; + + case 0xFFA0 ... 0xFFBF: // TRAP + trio_snprintf(tmp.code, sizeof(tmp.code), "TRAP"); + break; + + case 0xFF90: // Illegal/invalid instruction code + trio_snprintf(tmp.code, sizeof(tmp.code), "ILL"); + break; + + case 0xFF80: // Zero division + trio_snprintf(tmp.code, sizeof(tmp.code), "ZD"); + break; + + case 0xFF70: + trio_snprintf(tmp.code, sizeof(tmp.code), "FIV"); // FIV + break; + + case 0xFF68: + trio_snprintf(tmp.code, sizeof(tmp.code), "FZD"); // FZD + break; + + case 0xFF64: + trio_snprintf(tmp.code, sizeof(tmp.code), "FOV"); // FOV + break; + + case 0xFF62: + trio_snprintf(tmp.code, sizeof(tmp.code), "FUD"); // FUD + break; + + case 0xFF61: + trio_snprintf(tmp.code, sizeof(tmp.code), "FPR"); // FPR + break; + + case 0xFF60: + trio_snprintf(tmp.code, sizeof(tmp.code), "FRO"); // FRO + break; + + case 0xFE00 ... 0xFEFF: + trio_snprintf(tmp.code, sizeof(tmp.code), "INT%d", (bt->ecode >> 4) & 0xF); + break; + } + + ret.push_back(tmp); + } + return(ret); +} + + +void VBDBG_CheckBP(int type, uint32 address, uint32 value, unsigned int len) +{ + std::vector::iterator bpit, bpit_end; + + if(type == BPOINT_READ || type == BPOINT_IO_READ) + { + bpit = BreakPointsRead.begin(); + bpit_end = BreakPointsRead.end(); + } + else if(type == BPOINT_WRITE || type == BPOINT_IO_WRITE) + { + bpit = BreakPointsWrite.begin(); + bpit_end = BreakPointsWrite.end(); + } + else + return; + + for(; bpit != bpit_end; bpit++) + { + uint32 tmp_address = address; + uint32 tmp_len = len; + + while(tmp_len--) + { + if(tmp_address >= bpit->A[0] && tmp_address <= bpit->A[1]) + { + FoundBPoint = TRUE; + break; + } + tmp_address++; + } + } +} + +static uint16 MDFN_FASTCALL MemPeek8(v810_timestamp_t timestamp, uint32 A) +{ + uint8 ret; + + // TODO: VB_InDebugPeek(implement elsewhere) + VB_InDebugPeek++; + ret = MemRead8(timestamp, A); + VB_InDebugPeek--; + + return(ret); +} + +static uint16 MDFN_FASTCALL MemPeek16(v810_timestamp_t timestamp, uint32 A) +{ + uint16 ret; + + // TODO: VB_InDebugPeek(implement elsewhere) + VB_InDebugPeek++; + ret = MemRead16(timestamp, A); + VB_InDebugPeek--; + + return(ret); +} + +static void CPUHandler(const v810_timestamp_t timestamp, uint32 PC) +{ + std::vector::iterator bpit; + + for(bpit = BreakPointsPC.begin(); bpit != BreakPointsPC.end(); bpit++) + { + if(PC >= bpit->A[0] && PC <= bpit->A[1]) + { + FoundBPoint = TRUE; + break; + } + } + VB_V810->CheckBreakpoints(VBDBG_CheckBP, MemPeek16, NULL); + + CPUHookContinuous |= FoundBPoint; + + if(CPUHook && CPUHookContinuous) + { + ForceEventUpdates(timestamp); + CPUHook(PC, FoundBPoint); + } + + FoundBPoint = false; +} + +static void RedoCPUHook(void) +{ + VB_V810->SetCPUHook((CPUHook || VB_LoggingOn || BreakPointsPC.size() || BreakPointsRead.size() || BreakPointsWrite.size()) ? CPUHandler : NULL, + BTEnabled ? AddBranchTrace : NULL); +} + +void VBDBG_FlushBreakPoints(int type) +{ + std::vector::iterator bpit; + + if(type == BPOINT_READ) + BreakPointsRead.clear(); + else if(type == BPOINT_WRITE) + BreakPointsWrite.clear(); + else if(type == BPOINT_PC) + BreakPointsPC.clear(); + + RedoCPUHook(); +} + +void VBDBG_AddBreakPoint(int type, unsigned int A1, unsigned int A2, bool logical) +{ + VB_BPOINT tmp; + + tmp.A[0] = A1; + tmp.A[1] = A2; + tmp.type = type; + + if(type == BPOINT_READ) + BreakPointsRead.push_back(tmp); + else if(type == BPOINT_WRITE) + BreakPointsWrite.push_back(tmp); + else if(type == BPOINT_PC) + BreakPointsPC.push_back(tmp); + + RedoCPUHook(); +} + +static uint16 dis_readhw(uint32 A) +{ + int32 timestamp = 0; + return(MemPeek16(timestamp, A)); +} + +void VBDBG_Disassemble(uint32 &a, uint32 SpecialA, char *TextBuf) +{ + return(v810_dis(a, 1, TextBuf, dis_readhw, true)); +} + +uint32 VBDBG_MemPeek(uint32 A, unsigned int bsize, bool hl, bool logical) +{ + uint32 ret = 0; + int32 ws = 0; + + for(unsigned int i = 0; i < bsize; i++) + { + A &= 0xFFFFFFFF; + //ret |= mem_peekbyte(A, ws) << (i * 8); + ret |= MemRead8(ws, A) << (i * 8); + A++; + } + + return(ret); +} + +static void GetAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint8 *Buffer) +{ + if(!strcmp(name, "cpu")) + { + while(Length--) + { + *Buffer = MemPeek8(0, Address); + + Address++; + Buffer++; + } + } + else if(!strncmp(name, "vsuwd", 5)) + { + const unsigned int which = name[5] - '0'; + + while(Length--) + { + *Buffer = VB_VSU->PeekWave(which, Address); + + Address++; + Buffer++; + } + } +} + +static void PutAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint32 Granularity, bool hl, const uint8 *Buffer) +{ + if(!strcmp(name, "cpu")) + { + while(Length--) + { + int32 dummy_ts = 0; + + MemWrite8(dummy_ts, Address, *Buffer); + + Address++; + Buffer++; + } + } + else if(!strncmp(name, "vsuwd", 5)) + { + const unsigned int which = name[5] - '0'; + + while(Length--) + { + VB_VSU->PokeWave(which, Address, *Buffer); + + Address++; + Buffer++; + } + } +} + +uint32 VBDBG_GetRegister(const std::string &name, std::string *special) +{ + if(name == "PC") + { + return(VB_V810->GetPC()); + } + const char *thestring = name.c_str(); + + if(!strncmp(thestring, "PR", 2)) + { + return(VB_V810->GetPR(atoi(thestring + 2))); + } + else if(!strcmp(thestring, "HSP")) + return(VB_V810->GetPR(2)); + else if(!strcmp(thestring, "SP")) + return(VB_V810->GetPR(3)); + else if(!strcmp(thestring, "GP")) + return(VB_V810->GetPR(4)); + else if(!strcmp(thestring, "TP")) + return(VB_V810->GetPR(5)); + else if(!strcmp(thestring, "LP")) + return(VB_V810->GetPR(31)); + else if(!strcmp(thestring, "TStamp")) + return(VB_V810->v810_timestamp); + else if(!strncmp(thestring, "SR", 2)) + { + int which_one = atoi(thestring + 2); + uint32 val = VB_V810->GetSR(which_one); + + if(special && which_one == PSW) + { + char buf[256]; + trio_snprintf(buf, 256, "Z: %d, S: %d, OV: %d, CY: %d, ID: %d, AE: %d, EP: %d, NP: %d, IA: %2d", + (int)(bool)(val & PSW_Z), (int)(bool)(val & PSW_S), (int)(bool)(val & PSW_OV), (int)(bool)(val & PSW_CY), + (int)(bool)(val & PSW_ID), (int)(bool)(val & PSW_AE), (int)(bool)(val & PSW_EP), (int)(bool)(val & PSW_NP), + (val & PSW_IA) >> 16); + *special = std::string(buf); + } + return(val); + } + uint32 val = 0; + + return(val); +} + +void VBDBG_SetRegister(const std::string &name, uint32 value) +{ + if(name == "PC") + { + VB_V810->SetPC(value & ~1); + return; + } + + const char *thestring = name.c_str(); + + if(!strncmp(thestring, "PR", 2)) + { + VB_V810->SetPR(atoi(thestring + 2), value); + } + else if(!strcmp(thestring, "HSP")) + VB_V810->SetPR(2, value); + else if(!strcmp(thestring, "SP")) + VB_V810->SetPR(3, value); + else if(!strcmp(thestring, "GP")) + VB_V810->SetPR(4, value); + else if(!strcmp(thestring, "TP")) + VB_V810->SetPR(5, value); + else if(!strcmp(thestring, "LP")) + VB_V810->SetPR(31, value); + else if(!strncmp(thestring, "SR", 2)) + { + VB_V810->SetSR(atoi(thestring + 2), value); + } +} + +void VBDBG_SetCPUCallback(void (*callb)(uint32 PC, bool bpoint), bool continuous) +{ + CPUHook = callb; + CPUHookContinuous = continuous; + RedoCPUHook(); +} + +void VBDBG_DoLog(const char *type, const char *format, ...) +{ + if(LogFunc) + { + char *temp; + + va_list ap; + va_start(ap, format); + + temp = trio_vaprintf(format, ap); + LogFunc(type, temp); + free(temp); + + va_end(ap); + } +} + +void VBDBG_SetLogFunc(void (*func)(const char *, const char *)) +{ + LogFunc = func; + + VB_LoggingOn = func ? TRUE : FALSE; + + if(VB_LoggingOn) + { + + } + else + { + + } + RedoCPUHook(); +} + +static RegType V810Regs[] = +{ + { 0, "PC", "Program Counter", 4 }, + { 0, "PR1", "Program Register 1", 4 }, + { 0, "HSP", "Program Register 2(Handler Stack Pointer)", 4 }, + { 0, "SP", "Program Register 3(Stack Pointer)", 4 }, + { 0, "GP", "Program Register 4(Global Pointer)", 4 }, + { 0, "TP", "Program Register 5(Text Pointer)", 4 }, + { 0, "PR6", "Program Register 6", 4 }, + { 0, "PR7", "Program Register 7", 4 }, + { 0, "PR8", "Program Register 8", 4 }, + { 0, "PR9", "Program Register 9", 4 }, + { 0, "PR10", "Program Register 10", 4 }, + { 0, "PR11", "Program Register 11", 4 }, + { 0, "PR12", "Program Register 12", 4 }, + { 0, "PR13", "Program Register 13", 4 }, + { 0, "PR14", "Program Register 14", 4 }, + { 0, "PR15", "Program Register 15", 4 }, + { 0, "PR16", "Program Register 16", 4 }, + { 0, "PR17", "Program Register 17", 4 }, + { 0, "PR18", "Program Register 18", 4 }, + { 0, "PR19", "Program Register 19", 4 }, + { 0, "PR20", "Program Register 20", 4 }, + { 0, "PR21", "Program Register 21", 4 }, + { 0, "PR22", "Program Register 22", 4 }, + { 0, "PR23", "Program Register 23", 4 }, + { 0, "PR24", "Program Register 24", 4 }, + { 0, "PR25", "Program Register 25", 4 }, + { 0, "PR26", "Program Register 26(String Dest Bit Offset)", 4 }, + { 0, "PR27", "Program Register 27(String Source Bit Offset)", 4 }, + { 0, "PR28", "Program Register 28(String Length)", 4 }, + { 0, "PR29", "Program Register 29(String Dest)", 4 }, + { 0, "PR30", "Program Register 30(String Source)", 4 }, + { 0, "LP", "Program Register 31(Link Pointer)", 4 }, + { 0, "SR0", "Exception/Interrupt PC", 4 }, + { 0, "SR1", "Exception/Interrupt PSW", 4 }, + { 0, "SR2", "Fatal Error PC", 4 }, + { 0, "SR3", "Fatal Error PSW", 4 }, + { 0, "SR4", "Exception Cause Register", 4 }, + { 0, "SR5", "Program Status Word", 4 }, + { 0, "SR6", "Processor ID Register", 4 }, + { 0, "SR7", "Task Control Word", 4 }, + { 0, "SR24", "Cache Control Word", 4 }, + { 0, "SR25", "Address Trap Register", 4 }, + + //{ 0, "IPEND", "Interrupts Pending", 2 }, + //{ 0, "IMASK", "Interrupt Mask", 2 }, + //{ 0, "TCTRL", "Timer Control", 2 }, + //{ 0, "TPRD", "Timer Period", 2 }, + //{ 0, "TCNTR", "Timer Counter", 3 }, + + { 0, "TStamp", "Timestamp", 3 }, + { 0, "", "", 0 }, +}; + + +static RegGroupType V810RegsGroup = +{ + NULL, + V810Regs, + NULL, + NULL, + VBDBG_GetRegister, + VBDBG_SetRegister, +}; + +static uint32 MISC_GetRegister(const unsigned int id, char *special, const uint32 special_len) +{ + return(TIMER_GetRegister(id, special, special_len)); +} + +static void MISC_SetRegister(const unsigned int id, const uint32 value) +{ + TIMER_SetRegister(id, value); +} + + +static RegType Regs_Misc[] = +{ + { TIMER_GSREG_TCR, "TCR", "Timer Control Register", 1 }, + { TIMER_GSREG_DIVCOUNTER, "DivCounter", "Timer Clock Divider Counter", 2 }, + { TIMER_GSREG_RELOAD_VALUE, "ReloadValue", "Timer Reload Value", 2 }, + { TIMER_GSREG_COUNTER, "Counter", "Timer Counter Value", 2 }, + { 0, "", "", 0 }, +}; + +static RegGroupType RegsGroup_Misc = +{ + "Misc", + Regs_Misc, + MISC_GetRegister, + MISC_SetRegister +}; + + +static RegType Regs_VIP[] = +{ + { VIP_GSREG_IPENDING, "IPending", "Interrupts Pending", 2 }, + { VIP_GSREG_IENABLE, "IEnable", "Interrupts Enabled", 2 }, + + { VIP_GSREG_DPCTRL, "DPCTRL", "DPCTRL", 2 }, + + { VIP_GSREG_BRTA, "BRTA", "BRTA", 1 }, + { VIP_GSREG_BRTB, "BRTB", "BRTB", 1 }, + { VIP_GSREG_BRTC, "BRTC", "BRTC", 1 }, + { VIP_GSREG_REST, "REST", "REST", 1 }, + { VIP_GSREG_FRMCYC, "FRMCYC", "FRMCYC", 1 }, + { VIP_GSREG_XPCTRL, "XPCTRL", "XPCTRL", 2 }, + + { VIP_GSREG_SPT0, "SPT0", "SPT0", 2 }, + { VIP_GSREG_SPT1, "SPT1", "SPT1", 2 }, + { VIP_GSREG_SPT2, "SPT2", "SPT2", 2 }, + { VIP_GSREG_SPT3, "SPT3", "SPT3", 2 }, + + { VIP_GSREG_GPLT0, "GPLT0", "GPLT0", 1 }, + { VIP_GSREG_GPLT1, "GPLT1", "GPLT1", 1 }, + { VIP_GSREG_GPLT2, "GPLT2", "GPLT2", 1 }, + { VIP_GSREG_GPLT3, "GPLT3", "GPLT3", 1 }, + + { VIP_GSREG_JPLT0, "JPLT0", "JPLT0", 1 }, + { VIP_GSREG_JPLT1, "JPLT1", "JPLT1", 1 }, + { VIP_GSREG_JPLT2, "JPLT2", "JPLT2", 1 }, + { VIP_GSREG_JPLT3, "JPLT3", "JPLT3", 1 }, + + { VIP_GSREG_BKCOL, "BKCOL", "BKCOL", 1 }, + + { 0, "", "", 0 }, +}; + +static RegGroupType RegsGroup_VIP = +{ + "VIP", + Regs_VIP, + VIP_GetRegister, + VIP_SetRegister +}; + + +bool VBDBG_Init(void) +{ + BTEnabled = false; + BTIndex = 0; + memset(BTEntries, 0, sizeof(BTEntries)); + + MDFNDBG_AddRegGroup(&V810RegsGroup); + MDFNDBG_AddRegGroup(&RegsGroup_Misc); + MDFNDBG_AddRegGroup(&RegsGroup_VIP); + + ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "cpu", "CPU Physical", 32); +// ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ram", "RAM", 21); + + + for(int x = 0; x < 5; x++) + { + AddressSpaceType newt; + char tmpname[128], tmpinfo[128]; + + trio_snprintf(tmpname, 128, "vsuwd%d", x); + trio_snprintf(tmpinfo, 128, "VSU Wave Data %d", x); + + memset(&newt, 0, sizeof(AddressSpaceType)); + + newt.GetAddressSpaceBytes = GetAddressSpaceBytes; + newt.PutAddressSpaceBytes = PutAddressSpaceBytes; + + newt.name = strdup(tmpname); + newt.long_name = strdup(tmpinfo); + newt.TotalBits = 5; + newt.NP2Size = 0; + + newt.IsWave = TRUE; + newt.WaveFormat = ASPACE_WFMT_UNSIGNED; + newt.WaveBits = 6; + ASpace_Add(newt); //PSG_GetAddressSpaceBytes, PSG_PutAddressSpaceBytes, tmpname, tmpinfo, 5); + } + + + + return(true); +} + +} diff --git a/mednafen/vb-09333/debug.h b/mednafen/vb-09333/debug.h new file mode 100644 index 0000000..f4f1ccc --- /dev/null +++ b/mednafen/vb-09333/debug.h @@ -0,0 +1,33 @@ +#ifndef __VB_DEBUG_H +#define __VB_DEBUG_H + +namespace MDFN_IEN_VB +{ + +void VBDBG_FlushBreakPoints(int type); +void VBDBG_AddBreakPoint(int type, unsigned int A1, unsigned int A2, bool logical); +void VBDBG_Disassemble(uint32 &a, uint32 SpecialA, char *); + +uint32 VBDBG_MemPeek(uint32 A, unsigned int bsize, bool hl, bool logical); +uint32 VBDBG_GetRegister(const std::string &name, std::string *special); +void VBDBG_SetRegister(const std::string &name, uint32 value); + +void VBDBG_SetCPUCallback(void (*callb)(uint32 PC, bool bpoint), bool continuous); + +void VBDBG_EnableBranchTrace(bool enable); +std::vector VBDBG_GetBranchTrace(void); + +void VBDBG_CheckBP(int type, uint32 address, uint32 value, unsigned int len); + +void VBDBG_SetLogFunc(void (*func)(const char *, const char *)); + +void VBDBG_DoLog(const char *type, const char *format, ...); + + +extern bool VB_LoggingOn; + +bool VBDBG_Init(void); + +}; + +#endif diff --git a/mednafen/vb-09333/input.cpp b/mednafen/vb-09333/input.cpp new file mode 100644 index 0000000..3fe1a85 --- /dev/null +++ b/mednafen/vb-09333/input.cpp @@ -0,0 +1,228 @@ +/* Mednafen - Multi-system Emulator + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "vb.h" +#include "input.h" + +namespace MDFN_IEN_VB +{ +static bool InstantReadHack; + +static bool IntPending; + +static uint8 *data_ptr; + +static uint16 PadData; +static uint16 PadLatched; + +static uint8 SCR; +static uint16 SDR; + +#define SCR_S_ABT_DIS 0x01 +#define SCR_SI_STAT 0x02 +#define SCR_HW_SI 0x04 +#define SCR_SOFT_CLK 0x10 + +#define SCR_PARA_SI 0x20 +#define SCR_K_INT_INH 0x80 + +static uint32 ReadBitPos; +static int32 ReadCounter; + +static v810_timestamp_t last_ts; + +void VBINPUT_Init(void) +{ + InstantReadHack = true; +} + +void VBINPUT_SetInstantReadHack(bool enabled) +{ + InstantReadHack = enabled; +} + + +void VBINPUT_SetInput(int port, const char *type, void *ptr) +{ + data_ptr = (uint8 *)ptr; +} + +uint8 VBINPUT_Read(v810_timestamp_t ×tamp, uint32 A) +{ + uint8 ret = 0; + + + VBINPUT_Update(timestamp); + + //if(((A & 0xFF) == 0x10 || (A & 0xFF) == 0x14)) + // printf("Read %d\n", timestamp); + + //if(((A & 0xFF) == 0x10 || (A & 0xFF) == 0x14) && ReadCounter > 0) + //{ + // printf("Input port read during hardware transfer: %08x %d\n", A, timestamp); + //} + + switch(A & 0xFF) + { + case 0x10: if(InstantReadHack) + ret = PadData; + else + ret = SDR & 0xFF; + break; + + case 0x14: if(InstantReadHack) + ret = PadData >> 8; + else + ret = SDR >> 8; + break; + + case 0x28: ret = SCR | (0x40 | 0x08 | SCR_HW_SI); + if(ReadCounter > 0) + ret |= SCR_SI_STAT; + break; + } + +// printf("Input Read: %08x %02x\n", A, ret); + VB_SetEvent(VB_EVENT_INPUT, (ReadCounter > 0) ? (timestamp + ReadCounter) : VB_EVENT_NONONO); + + return(ret); +} + +void VBINPUT_Write(v810_timestamp_t ×tamp, uint32 A, uint8 V) +{ + VBINPUT_Update(timestamp); + + //printf("Input write: %d, %08x %02x\n", timestamp, A, V); + switch(A & 0xFF) + { + case 0x28: + if((V & SCR_HW_SI) && !(SCR & SCR_S_ABT_DIS) && ReadCounter <= 0) + { + //printf("Start Read: %d\n", timestamp); + PadLatched = PadData; + ReadBitPos = 0; + ReadCounter = 640; + } + + if(V & SCR_S_ABT_DIS) + { + ReadCounter = 0; + ReadBitPos = 0; + } + + if(V & SCR_K_INT_INH) + { + IntPending = false; + VBIRQ_Assert(VBIRQ_SOURCE_INPUT, IntPending); + } + + SCR = V & (0x80 | 0x20 | 0x10 | 1); + break; + } + + VB_SetEvent(VB_EVENT_INPUT, (ReadCounter > 0) ? (timestamp + ReadCounter) : VB_EVENT_NONONO); +} + +void VBINPUT_Frame(void) +{ + PadData = (MDFN_de16lsb(data_ptr) << 2) | 0x2; +} + +v810_timestamp_t VBINPUT_Update(const v810_timestamp_t timestamp) +{ + int32 clocks = timestamp - last_ts; + + if(ReadCounter > 0) + { + ReadCounter -= clocks; + + while(ReadCounter <= 0) + { + SDR &= ~(1 << ReadBitPos); + SDR |= PadLatched & (1 << ReadBitPos); + + ReadBitPos++; + if(ReadBitPos < 16) + ReadCounter += 640; + else + { + //printf("Read End: %d\n", timestamp); + if(!(SCR & SCR_K_INT_INH)) + { + //printf("Input IRQ: %d\n", timestamp); + IntPending = true; + VBIRQ_Assert(VBIRQ_SOURCE_INPUT, IntPending); + } + break; + } + } + + } + + + last_ts = timestamp; + + return((ReadCounter > 0) ? (timestamp + ReadCounter) : VB_EVENT_NONONO); +} + +void VBINPUT_ResetTS(void) +{ + last_ts = 0; +} + +void VBINPUT_Power(void) +{ + last_ts = 0; + PadData = 0; + PadLatched = 0; + SDR = 0; + SCR = 0; + ReadBitPos = 0; + ReadCounter = 0; + IntPending = false; + + VBIRQ_Assert(VBIRQ_SOURCE_INPUT, 0); +} + + + +int VBINPUT_StateAction(StateMem *sm, int load, int data_only) +{ + SFORMAT StateRegs[] = + { + SFVAR(PadData), + SFVAR(PadLatched), + SFVAR(SCR), + SFVAR(SDR), + SFVAR(ReadBitPos), + SFVAR(ReadCounter), + SFVAR(IntPending), + SFEND + }; + + int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "INPUT"); + + if(load) + { + + } + + return(ret); +} + + +} diff --git a/mednafen/vb-09333/input.h b/mednafen/vb-09333/input.h new file mode 100644 index 0000000..2ff4c46 --- /dev/null +++ b/mednafen/vb-09333/input.h @@ -0,0 +1,29 @@ +#ifndef __VB_INPUT_H +#define __VB_INPUT_H + +namespace MDFN_IEN_VB +{ + +void VBINPUT_Init(void); +void VBINPUT_SetInstantReadHack(bool); + +void VBINPUT_SetInput(int port, const char *type, void *ptr); + +uint8 VBINPUT_Read(v810_timestamp_t ×tamp, uint32 A); + +void VBINPUT_Write(v810_timestamp_t ×tamp, uint32 A, uint8 V); + +void VBINPUT_Frame(void); +int VBINPUT_StateAction(StateMem *sm, int load, int data_only); + +int32 VBINPUT_Update(const int32 timestamp); +void VBINPUT_ResetTS(void); + + +void VBINPUT_Power(void); + + +int VBINPUT_StateAction(StateMem *sm, int load, int data_only); + +} +#endif diff --git a/mednafen/vb-09333/timer.cpp b/mednafen/vb-09333/timer.cpp new file mode 100644 index 0000000..cc239ef --- /dev/null +++ b/mednafen/vb-09333/timer.cpp @@ -0,0 +1,254 @@ +/* Mednafen - Multi-system Emulator + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "vb.h" +#include "timer.h" + +namespace MDFN_IEN_VB +{ + +#define TC_TENABLE 0x01 +#define TC_ZSTAT 0x02 +#define TC_ZSTATCLR 0x04 +#define TC_TIMZINT 0x08 +#define TC_TCLKSEL 0x10 + +static uint8 TimerControl; +static uint16 TimerReloadValue; +static uint16 TimerCounter; +static int32 TimerDivider; +static v810_timestamp_t TimerLastTS; +static bool TimerStatus, TimerStatusShadow; +static bool ReloadPending; + +v810_timestamp_t TIMER_Update(v810_timestamp_t timestamp) +{ + int32 run_time = timestamp - TimerLastTS; + + if(TimerControl & TC_TENABLE) + { + TimerDivider -= run_time; + while(TimerDivider <= 0) + { + if(!TimerCounter || ReloadPending) + { + TimerCounter = TimerReloadValue; + ReloadPending = false; + } + + if(TimerCounter) + TimerCounter--; + + if(!TimerCounter || TimerStatus) + { + TimerStatusShadow = TimerStatus = true; + } + + VBIRQ_Assert(VBIRQ_SOURCE_TIMER, TimerStatusShadow && (TimerControl & TC_TIMZINT)); + TimerDivider += (TimerControl & TC_TCLKSEL) ? 500 : 2000; + } + } + + TimerLastTS = timestamp; + + return((TimerControl & TC_TENABLE) ? (timestamp + TimerDivider) : VB_EVENT_NONONO); +} + +void TIMER_ResetTS(void) +{ + TimerLastTS = 0; +} + +uint8 TIMER_Read(const v810_timestamp_t ×tamp, uint32 A) +{ + uint8 ret = 0; + + //if(A <= 0x1C) + //printf("Read: %d, %08x\n", timestamp, A); + TIMER_Update(timestamp); + + switch(A & 0xFF) + { + case 0x18: ret = TimerCounter; + break; + + case 0x1C: ret = TimerCounter >> 8; + break; + + case 0x20: ret = TimerControl | (0xE0 | TC_ZSTATCLR) | (TimerStatus ? TC_ZSTAT : 0); + break; + + } + + return(ret); +} + +void TIMER_Write(const v810_timestamp_t ×tamp, uint32 A, uint8 V) +{ + if(A & 0x3) + { + puts("HWCtrl Bogus Write?"); + return; + } + + TIMER_Update(timestamp); + + //if((A & 0xFF) <= 0x1C) + //printf("Write: %d, %08x %02x\n", timestamp, A, V); + + switch(A & 0xFF) + { + case 0x18: TimerReloadValue &= 0xFF00; + TimerReloadValue |= V; + ReloadPending = true; + break; + + case 0x1C: TimerReloadValue &= 0x00FF; + TimerReloadValue |= V << 8; + ReloadPending = true; + break; + + case 0x20: if(V & TC_ZSTATCLR) + { + if((TimerControl & TC_TENABLE) && TimerCounter == 0) + { + //puts("Faulty Z-Stat-Clr"); + } + else + { + TimerStatus = false; + } + TimerStatusShadow = false; + } + if((V & TC_TENABLE) && !(TimerControl & TC_TENABLE)) + { + //TimerCounter = TimerReloadValue; + TimerDivider = (V & TC_TCLKSEL) ? 500 : 2000; + } + TimerControl = V & (0x10 | 0x08 | 0x01); + + if(!(TimerControl & TC_TIMZINT)) + TimerStatus = TimerStatusShadow = false; + + VBIRQ_Assert(VBIRQ_SOURCE_TIMER, TimerStatusShadow && (TimerControl & TC_TIMZINT)); + + if(TimerControl & TC_TENABLE) + VB_SetEvent(VB_EVENT_TIMER, timestamp + TimerDivider); + break; + } +} + +void TIMER_Power(void) +{ + TimerLastTS = 0; + + TimerCounter = 0xFFFF; + TimerReloadValue = 0xFFFF; + TimerDivider = 2000; //2150; //2000; + + TimerStatus = false; + TimerStatusShadow = false; + TimerControl = 0; + + ReloadPending = false; + + VBIRQ_Assert(VBIRQ_SOURCE_TIMER, false); +} + +int TIMER_StateAction(StateMem *sm, int load, int data_only) +{ + SFORMAT StateRegs[] = + { + SFVAR(TimerCounter), + SFVAR(TimerReloadValue), + SFVAR(TimerDivider), + SFVAR(TimerStatus), + SFVAR(TimerStatusShadow), + SFVAR(TimerControl), + SFVAR(ReloadPending), + SFEND + }; + + int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "TIMER"); + + if(load) + { + + } + + return(ret); +} + +uint32 TIMER_GetRegister(const unsigned int id, char *special, const uint32 special_len) +{ + uint32 ret = 0xDEADBEEF; + + switch(id) + { + case TIMER_GSREG_TCR: + ret = TimerControl; + if(special) + trio_snprintf(special, special_len, "TEnable: %d, TimZInt: %d, TClkSel: %d(%.3f KHz)", + (int)(bool)(ret & TC_TENABLE), + (int)(bool)(ret & TC_TIMZINT), + (int)(bool)(ret & TC_TCLKSEL), + (double)VB_MASTER_CLOCK / ((ret & TC_TCLKSEL) ? 500 : 2000) / 1000 ); + break; + + case TIMER_GSREG_DIVCOUNTER: + ret = TimerDivider; + break; + + case TIMER_GSREG_RELOAD_VALUE: + ret = TimerReloadValue; + break; + + case TIMER_GSREG_COUNTER: + ret = TimerCounter; + break; + + } + return(ret); +} + +void TIMER_SetRegister(const unsigned int id, const uint32 value) +{ + switch(id) + { + case TIMER_GSREG_TCR: + TimerControl = value & (TC_TENABLE | TC_TIMZINT | TC_TCLKSEL); + break; + + case TIMER_GSREG_DIVCOUNTER: + TimerDivider = value % ((TimerControl & TC_TCLKSEL) ? 500 : 2000); + break; + + case TIMER_GSREG_RELOAD_VALUE: + TimerReloadValue = value; + break; + + case TIMER_GSREG_COUNTER: + TimerCounter = value; + break; + + } + + +} + + +} diff --git a/mednafen/vb-09333/timer.h b/mednafen/vb-09333/timer.h new file mode 100644 index 0000000..8950c6c --- /dev/null +++ b/mednafen/vb-09333/timer.h @@ -0,0 +1,30 @@ +#ifndef __MDFN_VB_TIMER_H +#define __MDFN_VB_TIMER_H + +namespace MDFN_IEN_VB +{ + +v810_timestamp_t TIMER_Update(v810_timestamp_t timestamp); +void TIMER_ResetTS(void); +uint8 TIMER_Read(const v810_timestamp_t ×tamp, uint32 A); +void TIMER_Write(const v810_timestamp_t ×tamp, uint32 A, uint8 V); + +void TIMER_Power(void) MDFN_COLD; + +int TIMER_StateAction(StateMem *sm, int load, int data_only); + + +enum +{ + TIMER_GSREG_TCR, + TIMER_GSREG_DIVCOUNTER, + TIMER_GSREG_RELOAD_VALUE, + TIMER_GSREG_COUNTER, +}; + +uint32 TIMER_GetRegister(const unsigned int id, char *special, const uint32 special_len); +void TIMER_SetRegister(const unsigned int id, const uint32 value); + +} + +#endif diff --git a/mednafen/vb-09333/vb.cpp b/mednafen/vb-09333/vb.cpp new file mode 100644 index 0000000..ca745a7 --- /dev/null +++ b/mednafen/vb-09333/vb.cpp @@ -0,0 +1,1068 @@ +/* Mednafen - Multi-system Emulator + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "vb.h" +#include "timer.h" +#include "vsu.h" +#include "vip.h" +#ifdef WANT_DEBUGGER +#include "debug.h" +#endif +#include "input.h" +#include "../general.h" +#include "../md5.h" +#include "../mempatcher.h" +#if 0 +#include +#endif + +namespace MDFN_IEN_VB +{ + +enum +{ + ANAGLYPH_PRESET_DISABLED = 0, + ANAGLYPH_PRESET_RED_BLUE, + ANAGLYPH_PRESET_RED_CYAN, + ANAGLYPH_PRESET_RED_ELECTRICCYAN, + ANAGLYPH_PRESET_RED_GREEN, + ANAGLYPH_PRESET_GREEN_MAGENTA, + ANAGLYPH_PRESET_YELLOW_BLUE, +}; + +static const uint32 AnaglyphPreset_Colors[][2] = +{ + { 0, 0 }, + { 0xFF0000, 0x0000FF }, + { 0xFF0000, 0x00B7EB }, + { 0xFF0000, 0x00FFFF }, + { 0xFF0000, 0x00FF00 }, + { 0x00FF00, 0xFF00FF }, + { 0xFFFF00, 0x0000FF }, +}; + + +int32 VB_InDebugPeek; + +static uint32 VB3DMode; + +static Blip_Buffer sbuf[2]; + +static uint8 *WRAM = NULL; + +static uint8 *GPRAM = NULL; +static uint32 GPRAM_Mask; + +static uint8 *GPROM = NULL; +static uint32 GPROM_Mask; + +V810 *VB_V810 = NULL; + +VSU *VB_VSU = NULL; +static uint32 VSU_CycleFix; + +static uint8 WCR; + +static int32 next_vip_ts, next_timer_ts, next_input_ts; + + +static uint32 IRQ_Asserted; + +static INLINE void RecalcIntLevel(void) +{ + int ilevel = -1; + + for(int i = 4; i >= 0; i--) + { + if(IRQ_Asserted & (1 << i)) + { + ilevel = i; + break; + } + } + + VB_V810->SetInt(ilevel); +} + +void VBIRQ_Assert(int source, bool assert) +{ + assert(source >= 0 && source <= 4); + + IRQ_Asserted &= ~(1 << source); + + if(assert) + IRQ_Asserted |= 1 << source; + + RecalcIntLevel(); +} + + + +static uint8 HWCTRL_Read(v810_timestamp_t ×tamp, uint32 A) +{ + uint8 ret = 0; + + if(A & 0x3) + { + puts("HWCtrl Bogus Read?"); + return(ret); + } + + switch(A & 0xFF) + { + default: printf("Unknown HWCTRL Read: %08x\n", A); + break; + + case 0x18: + case 0x1C: + case 0x20: ret = TIMER_Read(timestamp, A); + break; + + case 0x24: ret = WCR | 0xFC; + break; + + case 0x10: + case 0x14: + case 0x28: ret = VBINPUT_Read(timestamp, A); + break; + + } + + return(ret); +} + +static void HWCTRL_Write(v810_timestamp_t ×tamp, uint32 A, uint8 V) +{ + if(A & 0x3) + { + puts("HWCtrl Bogus Write?"); + return; + } + + switch(A & 0xFF) + { + default: printf("Unknown HWCTRL Write: %08x %02x\n", A, V); + break; + + case 0x18: + case 0x1C: + case 0x20: TIMER_Write(timestamp, A, V); + break; + + case 0x24: WCR = V & 0x3; + break; + + case 0x10: + case 0x14: + case 0x28: VBINPUT_Write(timestamp, A, V); + break; + } +} + +uint8 MDFN_FASTCALL MemRead8(v810_timestamp_t ×tamp, uint32 A) +{ + uint8 ret = 0; + A &= (1 << 27) - 1; + + //if((A >> 24) <= 2) + // printf("Read8: %d %08x\n", timestamp, A); + + switch(A >> 24) + { + case 0: ret = VIP_Read8(timestamp, A); + break; + + case 1: break; + + case 2: ret = HWCTRL_Read(timestamp, A); + break; + + case 3: break; + case 4: break; + + case 5: ret = WRAM[A & 0xFFFF]; + break; + + case 6: if(GPRAM) + ret = GPRAM[A & GPRAM_Mask]; + else + printf("GPRAM(Unmapped) Read: %08x\n", A); + break; + + case 7: ret = GPROM[A & GPROM_Mask]; + break; + } + return(ret); +} + +uint16 MDFN_FASTCALL MemRead16(v810_timestamp_t ×tamp, uint32 A) +{ + uint16 ret = 0; + + A &= (1 << 27) - 1; + + //if((A >> 24) <= 2) + // printf("Read16: %d %08x\n", timestamp, A); + + + switch(A >> 24) + { + case 0: ret = VIP_Read16(timestamp, A); + break; + + case 1: break; + + case 2: ret = HWCTRL_Read(timestamp, A); + break; + + case 3: break; + + case 4: break; + + case 5: ret = LoadU16_LE((uint16 *)&WRAM[A & 0xFFFF]); + break; + + case 6: if(GPRAM) + ret = LoadU16_LE((uint16 *)&GPRAM[A & GPRAM_Mask]); + else printf("GPRAM(Unmapped) Read: %08x\n", A); + break; + + case 7: ret = LoadU16_LE((uint16 *)&GPROM[A & GPROM_Mask]); + break; + } + return(ret); +} + +void MDFN_FASTCALL MemWrite8(v810_timestamp_t ×tamp, uint32 A, uint8 V) +{ + A &= (1 << 27) - 1; + + //if((A >> 24) <= 2) + // printf("Write8: %d %08x %02x\n", timestamp, A, V); + + switch(A >> 24) + { + case 0: VIP_Write8(timestamp, A, V); + break; + + case 1: VB_VSU->Write((timestamp + VSU_CycleFix) >> 2, A, V); + break; + + case 2: HWCTRL_Write(timestamp, A, V); + break; + + case 3: break; + + case 4: break; + + case 5: WRAM[A & 0xFFFF] = V; + break; + + case 6: if(GPRAM) + GPRAM[A & GPRAM_Mask] = V; + break; + + case 7: // ROM, no writing allowed! + break; + } +} + +void MDFN_FASTCALL MemWrite16(v810_timestamp_t ×tamp, uint32 A, uint16 V) +{ + A &= (1 << 27) - 1; + + //if((A >> 24) <= 2) + // printf("Write16: %d %08x %04x\n", timestamp, A, V); + + switch(A >> 24) + { + case 0: VIP_Write16(timestamp, A, V); + break; + + case 1: VB_VSU->Write((timestamp + VSU_CycleFix) >> 2, A, V); + break; + + case 2: HWCTRL_Write(timestamp, A, V); + break; + + case 3: break; + + case 4: break; + + case 5: StoreU16_LE((uint16 *)&WRAM[A & 0xFFFF], V); + break; + + case 6: if(GPRAM) + StoreU16_LE((uint16 *)&GPRAM[A & GPRAM_Mask], V); + break; + + case 7: // ROM, no writing allowed! + break; + } +} + +static void FixNonEvents(void) +{ + if(next_vip_ts & 0x40000000) + next_vip_ts = VB_EVENT_NONONO; + + if(next_timer_ts & 0x40000000) + next_timer_ts = VB_EVENT_NONONO; + + if(next_input_ts & 0x40000000) + next_input_ts = VB_EVENT_NONONO; +} + +static void EventReset(void) +{ + next_vip_ts = VB_EVENT_NONONO; + next_timer_ts = VB_EVENT_NONONO; + next_input_ts = VB_EVENT_NONONO; +} + +static INLINE int32 CalcNextTS(void) +{ + int32 next_timestamp = next_vip_ts; + + if(next_timestamp > next_timer_ts) + next_timestamp = next_timer_ts; + + if(next_timestamp > next_input_ts) + next_timestamp = next_input_ts; + + return(next_timestamp); +} + +static void RebaseTS(const v810_timestamp_t timestamp) +{ + //printf("Rebase: %08x %08x %08x\n", timestamp, next_vip_ts, next_timer_ts); + + assert(next_vip_ts > timestamp); + assert(next_timer_ts > timestamp); + assert(next_input_ts > timestamp); + + next_vip_ts -= timestamp; + next_timer_ts -= timestamp; + next_input_ts -= timestamp; +} + +void VB_SetEvent(const int type, const v810_timestamp_t next_timestamp) +{ + //assert(next_timestamp > VB_V810->v810_timestamp); + + if(type == VB_EVENT_VIP) + next_vip_ts = next_timestamp; + else if(type == VB_EVENT_TIMER) + next_timer_ts = next_timestamp; + else if(type == VB_EVENT_INPUT) + next_input_ts = next_timestamp; + + if(next_timestamp < VB_V810->GetEventNT()) + VB_V810->SetEventNT(next_timestamp); +} + + +static int32 MDFN_FASTCALL EventHandler(const v810_timestamp_t timestamp) +{ + if(timestamp >= next_vip_ts) + next_vip_ts = VIP_Update(timestamp); + + if(timestamp >= next_timer_ts) + next_timer_ts = TIMER_Update(timestamp); + + if(timestamp >= next_input_ts) + next_input_ts = VBINPUT_Update(timestamp); + + return(CalcNextTS()); +} + +// Called externally from debug.cpp in some cases. +void ForceEventUpdates(const v810_timestamp_t timestamp) +{ + next_vip_ts = VIP_Update(timestamp); + next_timer_ts = TIMER_Update(timestamp); + next_input_ts = VBINPUT_Update(timestamp); + + VB_V810->SetEventNT(CalcNextTS()); + //printf("FEU: %d %d %d\n", next_vip_ts, next_timer_ts, next_input_ts); +} + +static void VB_Power(void) +{ + memset(WRAM, 0, 65536); + + VIP_Power(); + VB_VSU->Power(); + TIMER_Power(); + VBINPUT_Power(); + + EventReset(); + IRQ_Asserted = 0; + RecalcIntLevel(); + VB_V810->Reset(); + + VSU_CycleFix = 0; + WCR = 0; + + + ForceEventUpdates(0); //VB_V810->v810_timestamp); +} + +static void SettingChanged(const char *name) +{ + if(!strcasecmp(name, "vb.3dmode")) + { + // FIXME, TODO (complicated) + //VB3DMode = MDFN_GetSettingUI("vb.3dmode"); + //VIP_Set3DMode(VB3DMode); + } + else if(!strcasecmp(name, "vb.disable_parallax")) + { + VIP_SetParallaxDisable(MDFN_GetSettingB("vb.disable_parallax")); + } + else if(!strcasecmp(name, "vb.anaglyph.lcolor") || !strcasecmp(name, "vb.anaglyph.rcolor") || + !strcasecmp(name, "vb.anaglyph.preset") || !strcasecmp(name, "vb.default_color")) + + { + uint32 lcolor = MDFN_GetSettingUI("vb.anaglyph.lcolor"), rcolor = MDFN_GetSettingUI("vb.anaglyph.rcolor"); + int preset = MDFN_GetSettingI("vb.anaglyph.preset"); + + if(preset != ANAGLYPH_PRESET_DISABLED) + { + lcolor = AnaglyphPreset_Colors[preset][0]; + rcolor = AnaglyphPreset_Colors[preset][1]; + } + VIP_SetAnaglyphColors(lcolor, rcolor); + VIP_SetDefaultColor(MDFN_GetSettingUI("vb.default_color")); + } + else if(!strcasecmp(name, "vb.input.instant_read_hack")) + { + VBINPUT_SetInstantReadHack(MDFN_GetSettingB("vb.input.instant_read_hack")); + } + else if(!strcasecmp(name, "vb.instant_display_hack")) + VIP_SetInstantDisplayHack(MDFN_GetSettingB("vb.instant_display_hack")); + else if(!strcasecmp(name, "vb.allow_draw_skip")) + VIP_SetAllowDrawSkip(MDFN_GetSettingB("vb.allow_draw_skip")); + else + abort(); + + +} + +struct VB_HeaderInfo +{ + char game_title[256]; + uint32 game_code; + uint16 manf_code; + uint8 version; +}; + +static void ReadHeader(MDFNFILE *fp, VB_HeaderInfo *hi) +{ +#if 0 + iconv_t sjis_ict = iconv_open("UTF-8", "shift_jis"); + + if(sjis_ict != (iconv_t)-1) + { + char *in_ptr, *out_ptr; + size_t ibl, obl; + + ibl = 20; + obl = sizeof(hi->game_title) - 1; + + in_ptr = (char*)GET_FDATA_PTR(fp) + (0xFFFFFDE0 & (GET_FSIZE_PTR(fp) - 1)); + out_ptr = hi->game_title; + + iconv(sjis_ict, (ICONV_CONST char **)&in_ptr, &ibl, &out_ptr, &obl); + iconv_close(sjis_ict); + + *out_ptr = 0; + + MDFN_RemoveControlChars(hi->game_title); + MDFN_trim(hi->game_title); + } + else + hi->game_title[0] = 0; + + hi->game_code = MDFN_de32lsb(fp->data + (0xFFFFFDFB & (fp->size - 1))); + hi->manf_code = MDFN_de16lsb(fp->data + (0xFFFFFDF9 & (fp->size - 1))); + hi->version = fp->data[0xFFFFFDFF & (fp->size - 1)]; +#endif +} + +static bool TestMagic(const char *name, MDFNFILE *fp) +{ + if(!strcasecmp(GET_FEXTS_PTR(fp), "vb") || !strcasecmp(GET_FEXTS_PTR(fp), "vboy")) + return(true); + + return(false); +} + +static int Load(const char *name, MDFNFILE *fp) +{ + V810_Emu_Mode cpu_mode; + md5_context md5; + + + VB_InDebugPeek = 0; + + cpu_mode = (V810_Emu_Mode)MDFN_GetSettingI("vb.cpu_emulation"); + + if(GET_FSIZE_PTR(fp) != round_up_pow2(GET_FSIZE_PTR(fp))) + { + puts("VB ROM image size is not a power of 2???"); + return(0); + } + + if(GET_FSIZE_PTR(fp) < 256) + { + puts("VB ROM image size is too small??"); + return(0); + } + + if(GET_FSIZE_PTR(fp) > (1 << 24)) + { + puts("VB ROM image size is too large??"); + return(0); + } + + md5.starts(); + md5.update(GET_FDATA_PTR(fp), GET_FSIZE_PTR(fp)); + md5.finish(MDFNGameInfo->MD5); + + VB_HeaderInfo hinfo; + + ReadHeader(fp, &hinfo); + + MDFN_printf(_("Title: %s\n"), hinfo.game_title); + MDFN_printf(_("Game ID Code: %u\n"), hinfo.game_code); + MDFN_printf(_("Manufacturer Code: %d\n"), hinfo.manf_code); + MDFN_printf(_("Version: %u\n"), hinfo.version); + + MDFN_printf(_("ROM: %dKiB\n"), (int)(GET_FSIZE_PTR(fp) / 1024)); + MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str()); + + MDFN_printf("\n"); + + MDFN_printf(_("V810 Emulation Mode: %s\n"), (cpu_mode == V810_EMU_MODE_ACCURATE) ? _("Accurate") : _("Fast")); + + VB_V810 = new V810(); + VB_V810->Init(cpu_mode, true); + + VB_V810->SetMemReadHandlers(MemRead8, MemRead16, NULL); + VB_V810->SetMemWriteHandlers(MemWrite8, MemWrite16, NULL); + + VB_V810->SetIOReadHandlers(MemRead8, MemRead16, NULL); + VB_V810->SetIOWriteHandlers(MemWrite8, MemWrite16, NULL); + + for(int i = 0; i < 256; i++) + { + VB_V810->SetMemReadBus32(i, false); + VB_V810->SetMemWriteBus32(i, false); + } + + std::vector Map_Addresses; + + for(uint64 A = 0; A < 1ULL << 32; A += (1 << 27)) + { + for(uint64 sub_A = 5 << 24; sub_A < (6 << 24); sub_A += 65536) + { + Map_Addresses.push_back(A + sub_A); + } + } + + WRAM = VB_V810->SetFastMap(&Map_Addresses[0], 65536, Map_Addresses.size(), "WRAM"); + Map_Addresses.clear(); + + + // Round up the ROM size to 65536(we mirror it a little later) + GPROM_Mask = (GET_FSIZE_PTR(fp) < 65536) ? (65536 - 1) : (GET_FSIZE_PTR(fp) - 1); + + for(uint64 A = 0; A < 1ULL << 32; A += (1 << 27)) + { + for(uint64 sub_A = 7 << 24; sub_A < (8 << 24); sub_A += GPROM_Mask + 1) + { + Map_Addresses.push_back(A + sub_A); + //printf("%08x\n", (uint32)(A + sub_A)); + } + } + + + GPROM = VB_V810->SetFastMap(&Map_Addresses[0], GPROM_Mask + 1, Map_Addresses.size(), "Cart ROM"); + Map_Addresses.clear(); + + // Mirror ROM images < 64KiB to 64KiB + for(uint64 i = 0; i < 65536; i += GET_FSIZE_PTR(fp)) + { + memcpy(GPROM + i, GET_FDATA_PTR(fp), GET_FSIZE_PTR(fp)); + } + + GPRAM_Mask = 0xFFFF; + + for(uint64 A = 0; A < 1ULL << 32; A += (1 << 27)) + { + for(uint64 sub_A = 6 << 24; sub_A < (7 << 24); sub_A += GPRAM_Mask + 1) + { + //printf("GPRAM: %08x\n", A + sub_A); + Map_Addresses.push_back(A + sub_A); + } + } + + + GPRAM = VB_V810->SetFastMap(&Map_Addresses[0], GPRAM_Mask + 1, Map_Addresses.size(), "Cart RAM"); + Map_Addresses.clear(); + + memset(GPRAM, 0, GPRAM_Mask + 1); + + { + FILE *gp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb"); + + if(gp) + { + if(gzread(gp, GPRAM, 65536) != 65536) + puts("Error reading GPRAM"); + gzclose(gp); + } + } + + VIP_Init(); + VB_VSU = new VSU(&sbuf[0], &sbuf[1]); + VBINPUT_Init(); + + VB3DMode = MDFN_GetSettingUI("vb.3dmode"); + uint32 prescale = MDFN_GetSettingUI("vb.liprescale"); + uint32 sbs_separation = MDFN_GetSettingUI("vb.sidebyside.separation"); + + VIP_Set3DMode(VB3DMode, MDFN_GetSettingUI("vb.3dreverse"), prescale, sbs_separation); + + + //SettingChanged("vb.3dmode"); + SettingChanged("vb.disable_parallax"); + SettingChanged("vb.anaglyph.lcolor"); + SettingChanged("vb.anaglyph.rcolor"); + SettingChanged("vb.anaglyph.preset"); + SettingChanged("vb.default_color"); + + SettingChanged("vb.instant_display_hack"); + SettingChanged("vb.allow_draw_skip"); + + SettingChanged("vb.input.instant_read_hack"); + + MDFNGameInfo->fps = (int64)20000000 * 65536 * 256 / (259 * 384 * 4); + + + VB_Power(); + + + #ifdef WANT_DEBUGGER + VBDBG_Init(); + #endif + + + MDFNGameInfo->nominal_width = 384; + MDFNGameInfo->nominal_height = 224; + MDFNGameInfo->fb_width = 384; + MDFNGameInfo->fb_height = 224; + + switch(VB3DMode) + { + default: break; + + case VB3DMODE_VLI: + MDFNGameInfo->nominal_width = 768 * prescale; + MDFNGameInfo->nominal_height = 224; + MDFNGameInfo->fb_width = 768 * prescale; + MDFNGameInfo->fb_height = 224; + break; + + case VB3DMODE_HLI: + MDFNGameInfo->nominal_width = 384; + MDFNGameInfo->nominal_height = 448 * prescale; + MDFNGameInfo->fb_width = 384; + MDFNGameInfo->fb_height = 448 * prescale; + break; + + case VB3DMODE_CSCOPE: + MDFNGameInfo->nominal_width = 512; + MDFNGameInfo->nominal_height = 384; + MDFNGameInfo->fb_width = 512; + MDFNGameInfo->fb_height = 384; + break; + + case VB3DMODE_SIDEBYSIDE: + MDFNGameInfo->nominal_width = 384 * 2 + sbs_separation; + MDFNGameInfo->nominal_height = 224; + MDFNGameInfo->fb_width = 384 * 2 + sbs_separation; + MDFNGameInfo->fb_height = 224; + break; + } + MDFNGameInfo->lcm_width = MDFNGameInfo->fb_width; + MDFNGameInfo->lcm_height = MDFNGameInfo->fb_height; + + + MDFNMP_Init(32768, ((uint64)1 << 27) / 32768); + MDFNMP_AddRAM(65536, 5 << 24, WRAM); + if((GPRAM_Mask + 1) >= 32768) + MDFNMP_AddRAM(GPRAM_Mask + 1, 6 << 24, GPRAM); + return(1); +} + +static void CloseGame(void) +{ + // Only save cart RAM if it has been modified. + for(unsigned int i = 0; i < GPRAM_Mask + 1; i++) + { + if(GPRAM[i]) + { + if(!MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, GPRAM, 65536)) + { + + } + break; + } + } + //VIP_Kill(); + + if(VB_VSU) + { + delete VB_VSU; + VB_VSU = NULL; + } + + /* + if(GPRAM) + { + MDFN_free(GPRAM); + GPRAM = NULL; + } + + if(GPROM) + { + MDFN_free(GPROM); + GPROM = NULL; + } + */ + + if(VB_V810) + { + VB_V810->Kill(); + delete VB_V810; + VB_V810 = NULL; + } +} + +void VB_ExitLoop(void) +{ + VB_V810->Exit(); +} + +static void Emulate(EmulateSpecStruct *espec) +{ + v810_timestamp_t v810_timestamp; + + MDFNMP_ApplyPeriodicCheats(); + + VBINPUT_Frame(); + + if(espec->SoundFormatChanged) + { + for(int y = 0; y < 2; y++) + { + sbuf[y].set_sample_rate(espec->SoundRate ? espec->SoundRate : 44100, 50); + sbuf[y].clock_rate((long)(VB_MASTER_CLOCK / 4)); + sbuf[y].bass_freq(20); + } + } + + VIP_StartFrame(espec); + + v810_timestamp = VB_V810->Run(EventHandler); + + FixNonEvents(); + ForceEventUpdates(v810_timestamp); + + VB_VSU->EndFrame((v810_timestamp + VSU_CycleFix) >> 2); + + if(espec->SoundBuf) + { + for(int y = 0; y < 2; y++) + { + sbuf[y].end_frame((v810_timestamp + VSU_CycleFix) >> 2); + espec->SoundBufSize = sbuf[y].read_samples(espec->SoundBuf + y, espec->SoundBufMaxSize, 1); + } + } + + VSU_CycleFix = (v810_timestamp + VSU_CycleFix) & 3; + + espec->MasterCycles = v810_timestamp; + + TIMER_ResetTS(); + VBINPUT_ResetTS(); + VIP_ResetTS(); + + RebaseTS(v810_timestamp); + + VB_V810->ResetTS(0); + + +#if 0 + if(espec->SoundRate) + { + unsigned long long crf = (unsigned long long)sbuf[0].clock_rate_factor(sbuf[0].clock_rate()); + double real_rate = (double)crf * sbuf[0].clock_rate() / (1ULL << BLIP_BUFFER_ACCURACY); + + printf("%f\n", real_rate); + } +#endif +} + +} + +using namespace MDFN_IEN_VB; + +#ifdef WANT_DEBUGGER +static DebuggerInfoStruct DBGInfo = +{ + "shift_jis", + 4, + 2, // Instruction alignment(bytes) + 32, + 32, + 0x00000000, + ~0U, + + VBDBG_MemPeek, + VBDBG_Disassemble, + NULL, + NULL, //ForceIRQ, + NULL, + VBDBG_FlushBreakPoints, + VBDBG_AddBreakPoint, + VBDBG_SetCPUCallback, + VBDBG_EnableBranchTrace, + VBDBG_GetBranchTrace, + NULL, //KING_SetGraphicsDecode, + VBDBG_SetLogFunc, +}; +#endif + + +static int StateAction(StateMem *sm, int load, int data_only) +{ + const v810_timestamp_t timestamp = VB_V810->v810_timestamp; + int ret = 1; + + SFORMAT StateRegs[] = + { + SFARRAY(WRAM, 65536), + SFARRAY(GPRAM, GPRAM_Mask ? (GPRAM_Mask + 1) : 0), + SFVAR(WCR), + SFVAR(IRQ_Asserted), + SFVAR(VSU_CycleFix), + SFEND + }; + + ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, "MAIN"); + + ret &= VB_V810->StateAction(sm, load, data_only); + + ret &= VB_VSU->StateAction(sm, load, data_only); + ret &= TIMER_StateAction(sm, load, data_only); + ret &= VBINPUT_StateAction(sm, load, data_only); + ret &= VIP_StateAction(sm, load, data_only); + + if(load) + { + // Needed to recalculate next_*_ts since we don't bother storing their deltas in save states. + ForceEventUpdates(timestamp); + } + return(ret); +} + +static void SetLayerEnableMask(uint64 mask) +{ + +} + +static void DoSimpleCommand(int cmd) +{ + switch(cmd) + { + case MDFN_MSC_POWER: + case MDFN_MSC_RESET: VB_Power(); break; + } +} + +static const MDFNSetting_EnumList V810Mode_List[] = +{ + { "fast", (int)V810_EMU_MODE_FAST, gettext_noop("Fast Mode"), gettext_noop("Fast mode trades timing accuracy, cache emulation, and executing from hardware registers and RAM not intended for code use for performance.")}, + { "accurate", (int)V810_EMU_MODE_ACCURATE, gettext_noop("Accurate Mode"), gettext_noop("Increased timing accuracy, though not perfect, along with cache emulation, at the cost of decreased performance. Additionally, even the pipeline isn't correctly and fully emulated in this mode.") }, + { NULL, 0 }, +}; + +static const MDFNSetting_EnumList VB3DMode_List[] = +{ + { "anaglyph", VB3DMODE_ANAGLYPH, gettext_noop("Anaglyph"), gettext_noop("Used in conjunction with classic dual-lens-color glasses.") }, + { "cscope", VB3DMODE_CSCOPE, gettext_noop("CyberScope"), gettext_noop("Intended for use with the CyberScope 3D device.") }, + { "sidebyside", VB3DMODE_SIDEBYSIDE, gettext_noop("Side-by-Side"), gettext_noop("The left-eye image is displayed on the left, and the right-eye image is displayed on the right.") }, +// { "overunder", VB3DMODE_OVERUNDER }, + { "vli", VB3DMODE_VLI, gettext_noop("Vertical Line Interlaced"), gettext_noop("Vertical lines alternate between left view and right view.") }, + { "hli", VB3DMODE_HLI, gettext_noop("Horizontal Line Interlaced"), gettext_noop("Horizontal lines alternate between left view and right view.") }, + { NULL, 0 }, +}; + +static const MDFNSetting_EnumList AnaglyphPreset_List[] = +{ + { "disabled", ANAGLYPH_PRESET_DISABLED, gettext_noop("Disabled"), gettext_noop("Forces usage of custom anaglyph colors.") }, + { "0", ANAGLYPH_PRESET_DISABLED }, + + { "red_blue", ANAGLYPH_PRESET_RED_BLUE, gettext_noop("Red/Blue"), gettext_noop("Classic red/blue anaglyph.") }, + { "red_cyan", ANAGLYPH_PRESET_RED_CYAN, gettext_noop("Red/Cyan"), gettext_noop("Improved quality red/cyan anaglyph.") }, + { "red_electriccyan", ANAGLYPH_PRESET_RED_ELECTRICCYAN, gettext_noop("Red/Electric Cyan"), gettext_noop("Alternate version of red/cyan") }, + { "red_green", ANAGLYPH_PRESET_RED_GREEN, gettext_noop("Red/Green") }, + { "green_magenta", ANAGLYPH_PRESET_GREEN_MAGENTA, gettext_noop("Green/Magenta") }, + { "yellow_blue", ANAGLYPH_PRESET_YELLOW_BLUE, gettext_noop("Yellow/Blue") }, + + { NULL, 0 }, +}; + +static MDFNSetting VBSettings[] = +{ + { "vb.cpu_emulation", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("CPU emulation mode."), NULL, MDFNST_ENUM, "fast", NULL, NULL, NULL, NULL, V810Mode_List }, + { "vb.input.instant_read_hack", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Input latency reduction hack."), gettext_noop("Reduces latency in some games by 20ms by returning the current pad state, rather than latched state, on serial port data reads. This hack may cause some homebrew software to malfunction, but it should be relatively safe for commercial official games."), MDFNST_BOOL, "1", NULL, NULL, NULL, SettingChanged }, + + { "vb.instant_display_hack", MDFNSF_NOFLAGS, gettext_noop("Display latency reduction hack."), gettext_noop("Reduces latency in games by displaying the framebuffer 20ms earlier. This hack has some potential of causing graphical glitches, so it is disabled by default."), MDFNST_BOOL, "0", NULL, NULL, NULL, SettingChanged }, + { "vb.allow_draw_skip", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Allow draw skipping."), gettext_noop("If vb.instant_display_hack is set to \"1\", and this setting is set to \"1\", then frame-skipping the drawing to the emulated framebuffer will be allowed. THIS WILL CAUSE GRAPHICAL GLITCHES, AND THEORETICALLY(but unlikely) GAME CRASHES, ESPECIALLY WITH DIRECT FRAMEBUFFER DRAWING GAMES."), MDFNST_BOOL, "0", NULL, NULL, NULL, SettingChanged }, + + // FIXME: We're going to have to set up some kind of video mode change notification for changing vb.3dmode while the game is running to work properly. + { "vb.3dmode", MDFNSF_NOFLAGS, gettext_noop("3D mode."), NULL, MDFNST_ENUM, "anaglyph", NULL, NULL, NULL, /*SettingChanged*/NULL, VB3DMode_List }, + { "vb.liprescale", MDFNSF_NOFLAGS, gettext_noop("Line Interlaced prescale."), NULL, MDFNST_UINT, "2", "1", "10", NULL, NULL }, + + { "vb.disable_parallax", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Disable parallax for BG and OBJ rendering."), NULL, MDFNST_BOOL, "0", NULL, NULL, NULL, SettingChanged }, + { "vb.default_color", MDFNSF_NOFLAGS, gettext_noop("Default maximum-brightness color to use in non-anaglyph 3D modes."), NULL, MDFNST_UINT, "0xF0F0F0", "0x000000", "0xFFFFFF", NULL, SettingChanged }, + + { "vb.anaglyph.preset", MDFNSF_NOFLAGS, gettext_noop("Anaglyph preset colors."), NULL, MDFNST_ENUM, "red_blue", NULL, NULL, NULL, SettingChanged, AnaglyphPreset_List }, + { "vb.anaglyph.lcolor", MDFNSF_NOFLAGS, gettext_noop("Anaglyph maximum-brightness color for left view."), NULL, MDFNST_UINT, "0xffba00", "0x000000", "0xFFFFFF", NULL, SettingChanged }, + { "vb.anaglyph.rcolor", MDFNSF_NOFLAGS, gettext_noop("Anaglyph maximum-brightness color for right view."), NULL, MDFNST_UINT, "0x00baff", "0x000000", "0xFFFFFF", NULL, SettingChanged }, + + { "vb.sidebyside.separation", MDFNSF_NOFLAGS, gettext_noop("Number of pixels to separate L/R views by."), gettext_noop("This setting refers to pixels before vb.xscale(fs) scaling is taken into consideration. For example, a value of \"100\" here will result in a separation of 300 screen pixels if vb.xscale(fs) is set to \"3\"."), MDFNST_UINT, /*"96"*/"0", "0", "1024", NULL, NULL }, + + { "vb.3dreverse", MDFNSF_NOFLAGS, gettext_noop("Reverse left/right 3D views."), NULL, MDFNST_BOOL, "0", NULL, NULL, NULL, SettingChanged }, + { NULL } +}; + + +static const InputDeviceInputInfoStruct IDII[] = +{ + { "a", "A", 7, IDIT_BUTTON_CAN_RAPID, NULL }, + { "b", "B", 6, IDIT_BUTTON_CAN_RAPID, NULL }, + { "rt", "Right-Back", 13, IDIT_BUTTON, NULL }, + { "lt", "Left-Back", 12, IDIT_BUTTON, NULL }, + + { "up-r", "UP ↑ (Right D-Pad)", 8, IDIT_BUTTON, "down-r" }, + { "right-r", "RIGHT → (Right D-Pad)", 11, IDIT_BUTTON, "left-r" }, + + { "right-l", "RIGHT → (Left D-Pad)", 3, IDIT_BUTTON, "left-l" }, + { "left-l", "LEFT ← (Left D-Pad)", 2, IDIT_BUTTON, "right-l" }, + { "down-l", "DOWN ↓ (Left D-Pad)", 1, IDIT_BUTTON, "up-l" }, + { "up-l", "UP ↑ (Left D-Pad)", 0, IDIT_BUTTON, "down-l" }, + + { "start", "Start", 5, IDIT_BUTTON, NULL }, + { "select", "Select", 4, IDIT_BUTTON, NULL }, + + { "left-r", "LEFT ← (Right D-Pad)", 10, IDIT_BUTTON, "right-r" }, + { "down-r", "DOWN ↓ (Right D-Pad)", 9, IDIT_BUTTON, "up-r" }, +}; + +static InputDeviceInfoStruct InputDeviceInfo[] = +{ + { + "gamepad", + "Gamepad", + NULL, + NULL, + sizeof(IDII) / sizeof(InputDeviceInputInfoStruct), + IDII, + } +}; + +static const InputPortInfoStruct PortInfo[] = +{ + { "builtin", "Built-In", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" } +}; + +static InputInfoStruct InputInfo = +{ + sizeof(PortInfo) / sizeof(InputPortInfoStruct), + PortInfo +}; + + +static const FileExtensionSpecStruct KnownExtensions[] = +{ + { ".vb", gettext_noop("Nintendo Virtual Boy") }, + { ".vboy", gettext_noop("Nintendo Virtual Boy") }, + { NULL, NULL } +}; + +MDFNGI EmulatedVB = +{ + "vb", + "Virtual Boy", + KnownExtensions, + MODPRIO_INTERNAL_HIGH, + #ifdef WANT_DEBUGGER + &DBGInfo, + #else + NULL, // Debug info + #endif + &InputInfo, // + Load, + TestMagic, + NULL, + NULL, + CloseGame, + SetLayerEnableMask, + NULL, // Layer names, null-delimited + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + false, + StateAction, + Emulate, + VBINPUT_SetInput, + DoSimpleCommand, + VBSettings, + MDFN_MASTERCLOCK_FIXED(VB_MASTER_CLOCK), + 0, + false, // Multires possible? + + 0, // lcm_width + 0, // lcm_height + NULL, // Dummy + + 384, // Nominal width + 224, // Nominal height + + 384, // Framebuffer width + 256, // Framebuffer height + + 2, // Number of output sound channels +}; diff --git a/mednafen/vb-09333/vb.h b/mednafen/vb-09333/vb.h new file mode 100644 index 0000000..7bc13ac --- /dev/null +++ b/mednafen/vb-09333/vb.h @@ -0,0 +1,63 @@ +#ifndef __VB_VB_H +#define __VB_VB_H + +#include +#include +#include +#include + +namespace MDFN_IEN_VB +{ + +enum +{ + VB3DMODE_ANAGLYPH = 0, + VB3DMODE_CSCOPE = 1, + VB3DMODE_SIDEBYSIDE = 2, + VB3DMODE_OVERUNDER = 3, + VB3DMODE_VLI, + VB3DMODE_HLI +}; + +#define VB_MASTER_CLOCK 20000000.0 + + + +enum +{ + VB_EVENT_VIP = 0, + VB_EVENT_TIMER, + VB_EVENT_INPUT, +// VB_EVENT_COMM +}; + +#define VB_EVENT_NONONO 0x7fffffff + +void VB_SetEvent(const int type, const v810_timestamp_t next_timestamp); + + +#define VBIRQ_SOURCE_INPUT 0 +#define VBIRQ_SOURCE_TIMER 1 +#define VBIRQ_SOURCE_EXPANSION 2 +#define VBIRQ_SOURCE_COMM 3 +#define VBIRQ_SOURCE_VIP 4 + +void VBIRQ_Assert(int source, bool assert); + +void VB_ExitLoop(void); + +void ForceEventUpdates(const v810_timestamp_t timestamp); + + +uint8 MDFN_FASTCALL MemRead8(v810_timestamp_t ×tamp, uint32 A); +uint16 MDFN_FASTCALL MemRead16(v810_timestamp_t ×tamp, uint32 A); + +void MDFN_FASTCALL MemWrite8(v810_timestamp_t ×tamp, uint32 A, uint8 V); +void MDFN_FASTCALL MemWrite16(v810_timestamp_t ×tamp, uint32 A, uint16 V); + + + +extern int32 VB_InDebugPeek; +} + +#endif diff --git a/mednafen/vb-09333/vip.cpp b/mednafen/vb-09333/vip.cpp new file mode 100644 index 0000000..6b7ae08 --- /dev/null +++ b/mednafen/vb-09333/vip.cpp @@ -0,0 +1,1686 @@ +/* Mednafen - Multi-system Emulator + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "vb.h" +#include "vip.h" +#include + +#define VIP_DBGMSG(format, ...) { } +//#define VIP_DBGMSG(format, ...) printf(format "\n", ## __VA_ARGS__) + +namespace MDFN_IEN_VB +{ + +static uint8 FB[2][2][0x6000]; +static uint16 CHR_RAM[0x8000 / sizeof(uint16)]; +static uint16 DRAM[0x20000 / sizeof(uint16)]; + +// Helper functions for the V810 VIP RAM read/write handlers. +// "Memory Array 16 (Write/Read) (16/8)" +#define VIP__GETP16(array, address) ( (uint16 *)&((uint8 *)(array))[(address)] ) + +#ifdef MSB_FIRST +#define VIP__GETP8(array, address) ( &((uint8 *)(array))[(address) ^ 1] ) +#else +#define VIP__GETP8(array, address) ( &((uint8 *)(array))[(address)] ) +#endif + +static INLINE void VIP_MA16W16(uint16 *array, const uint32 v810_address, const uint16 value) +{ + *(VIP__GETP16(array, v810_address)) = value; +} + +static INLINE uint16 VIP_MA16R16(uint16 *array, const uint32 v810_address) +{ + return *(VIP__GETP16(array, v810_address)); +} + +static INLINE void VIP_MA16W8(uint16 *array, const uint32 v810_address, const uint8 value) +{ + *(VIP__GETP8(array, v810_address)) = value; +} + +static INLINE uint8 VIP_MA16R8(uint16 *array, const uint32 v810_address) +{ + return *(VIP__GETP8(array, v810_address)); +} + + +#define INT_SCAN_ERR 0x0001 +#define INT_LFB_END 0x0002 +#define INT_RFB_END 0x0004 +#define INT_GAME_START 0x0008 +#define INT_FRAME_START 0x0010 + +#define INT_SB_HIT 0x2000 +#define INT_XP_END 0x4000 +#define INT_TIME_ERR 0x8000 + +static uint16 InterruptPending; +static uint16 InterruptEnable; + +static uint8 BRTA, BRTB, BRTC, REST; +static uint8 Repeat; + +static void CopyFBColumnToTarget_Anaglyph(void) NO_INLINE; +static void CopyFBColumnToTarget_AnaglyphSlow(void) NO_INLINE; +static void CopyFBColumnToTarget_CScope(void) NO_INLINE; +static void CopyFBColumnToTarget_SideBySide(void) NO_INLINE; +static void CopyFBColumnToTarget_VLI(void) NO_INLINE; +static void CopyFBColumnToTarget_HLI(void) NO_INLINE; +static void (*CopyFBColumnToTarget)(void) = NULL; +static uint32 VB3DMode; +static uint32 VB3DReverse; +static uint32 VBPrescale; +static uint32 VBSBS_Separation; +static uint32 HLILUT[256]; +static uint32 ColorLUT[2][256]; +static int32 BrightnessCache[4]; +static uint32 BrightCLUT[2][4]; + +static double ColorLUTNoGC[2][256][3]; +static uint32 AnaSlowColorLUT[256][256]; + +// A few settings: +static bool InstantDisplayHack; +static bool AllowDrawSkip; + +static bool VidSettingsDirty; +static bool ParallaxDisabled; +static uint32 Anaglyph_Colors[2]; +static uint32 Default_Color; + +static void MakeColorLUT(const MDFN_PixelFormat &format) +{ + for(int lr = 0; lr < 2; lr++) + { + for(int i = 0; i < 256; i++) + { + double r, g, b; + double r_prime, g_prime, b_prime; + + r = g = b = (double)i / 255; + + // TODO: Use correct gamma curve, instead of approximation. + r_prime = pow(r, 1.0 / 2.2); + g_prime = pow(g, 1.0 / 2.2); + b_prime = pow(b, 1.0 / 2.2); + + switch(VB3DMode) + { + case VB3DMODE_ANAGLYPH: + r_prime = r_prime * ((Anaglyph_Colors[lr ^ VB3DReverse] >> 16) & 0xFF) / 255; + g_prime = g_prime * ((Anaglyph_Colors[lr ^ VB3DReverse] >> 8) & 0xFF) / 255; + b_prime = b_prime * ((Anaglyph_Colors[lr ^ VB3DReverse] >> 0) & 0xFF) / 255; + break; + default: + r_prime = r_prime * ((Default_Color >> 16) & 0xFF) / 255; + g_prime = g_prime * ((Default_Color >> 8) & 0xFF) / 255; + b_prime = b_prime * ((Default_Color >> 0) & 0xFF) / 255; + break; + } + ColorLUTNoGC[lr][i][0] = pow(r_prime, 2.2 / 1.0); + ColorLUTNoGC[lr][i][1] = pow(g_prime, 2.2 / 1.0); + ColorLUTNoGC[lr][i][2] = pow(b_prime, 2.2 / 1.0); + + ColorLUT[lr][i] = format.MakeColor((int)(r_prime * 255), (int)(g_prime * 255), (int)(b_prime * 255), 0); + } + } + + // Anaglyph slow-mode LUT calculation + for(int l_b = 0; l_b < 256; l_b++) + { + for(int r_b = 0; r_b < 256; r_b++) + { + double r, g, b; + double r_prime, g_prime, b_prime; + + r = ColorLUTNoGC[0][l_b][0] + ColorLUTNoGC[1][r_b][0]; + g = ColorLUTNoGC[0][l_b][1] + ColorLUTNoGC[1][r_b][1]; + b = ColorLUTNoGC[0][l_b][2] + ColorLUTNoGC[1][r_b][2]; + + if(r > 1.0) + r = 1.0; + if(g > 1.0) + g = 1.0; + if(b > 1.0) + b = 1.0; + + r_prime = pow(r, 1.0 / 2.2); + g_prime = pow(g, 1.0 / 2.2); + b_prime = pow(b, 1.0 / 2.2); + + AnaSlowColorLUT[l_b][r_b] = format.MakeColor((int)(r_prime * 255), (int)(g_prime * 255), (int)(b_prime * 255), 0); + } + } +} + +static void RecalcBrightnessCache(void) +{ + //printf("BRTA: %d, BRTB: %d, BRTC: %d, Rest: %d\n", BRTA, BRTB, BRTC, REST); + int32 CumulativeTime = (BRTA + 1 + BRTB + 1 + BRTC + 1 + REST + 1) + 1; + int32 MaxTime = 128; + + BrightnessCache[0] = 0; + BrightnessCache[1] = 0; + BrightnessCache[2] = 0; + BrightnessCache[3] = 0; + + for(int i = 0; i < Repeat + 1; i++) + { + int32 btemp[4]; + + if((i * CumulativeTime) >= MaxTime) + break; + + btemp[1] = (i * CumulativeTime) + BRTA; + if(btemp[1] > MaxTime) + btemp[1] = MaxTime; + btemp[1] -= (i * CumulativeTime); + if(btemp[1] < 0) + btemp[1] = 0; + + + btemp[2] = (i * CumulativeTime) + BRTA + 1 + BRTB; + if(btemp[2] > MaxTime) + btemp[2] = MaxTime; + btemp[2] -= (i * CumulativeTime) + BRTA + 1; + if(btemp[2] < 0) + btemp[2] = 0; + + //btemp[3] = (i * CumulativeTime) + BRTA + 1 + BRTB + 1 + BRTC; + //if(btemp[3] > MaxTime) + // btemp[3] = MaxTime; + //btemp[3] -= (i * CumulativeTime); + //if(btemp[3] < 0) + // btemp[3] = 0; + + btemp[3] = (i * CumulativeTime) + BRTA + BRTB + BRTC + 1; + if(btemp[3] > MaxTime) + btemp[3] = MaxTime; + btemp[3] -= (i * CumulativeTime) + 1; + if(btemp[3] < 0) + btemp[3] = 0; + + BrightnessCache[1] += btemp[1]; + BrightnessCache[2] += btemp[2]; + BrightnessCache[3] += btemp[3]; + } + + //printf("BC: %d %d %d %d\n", BrightnessCache[0], BrightnessCache[1], BrightnessCache[2], BrightnessCache[3]); + + for(int i = 0; i < 4; i++) + BrightnessCache[i] = 255 * BrightnessCache[i] / MaxTime; + + for(int lr = 0; lr < 2; lr++) + for(int i = 0; i < 4; i++) + { + BrightCLUT[lr][i] = ColorLUT[lr][BrightnessCache[i]]; + } +} + +static void Recalc3DModeStuff(bool non_rgb_output = false) +{ + switch(VB3DMode) + { + default: + if(((Anaglyph_Colors[0] & 0xFF) && (Anaglyph_Colors[1] & 0xFF)) || + ((Anaglyph_Colors[0] & 0xFF00) && (Anaglyph_Colors[1] & 0xFF00)) || + ((Anaglyph_Colors[0] & 0xFF0000) && (Anaglyph_Colors[1] & 0xFF0000)) || + non_rgb_output) + { + CopyFBColumnToTarget = CopyFBColumnToTarget_AnaglyphSlow; + } + else + CopyFBColumnToTarget = CopyFBColumnToTarget_Anaglyph; + break; + + case VB3DMODE_CSCOPE: + CopyFBColumnToTarget = CopyFBColumnToTarget_CScope; + break; + + case VB3DMODE_SIDEBYSIDE: + CopyFBColumnToTarget = CopyFBColumnToTarget_SideBySide; + break; + + case VB3DMODE_VLI: + CopyFBColumnToTarget = CopyFBColumnToTarget_VLI; + break; + + case VB3DMODE_HLI: + CopyFBColumnToTarget = CopyFBColumnToTarget_HLI; + break; + } + RecalcBrightnessCache(); +} + +void VIP_Set3DMode(uint32 mode, bool reverse, uint32 prescale, uint32 sbs_separation) +{ + VB3DMode = mode; + VB3DReverse = reverse ? 1 : 0; + VBPrescale = prescale; + VBSBS_Separation = sbs_separation; + + VidSettingsDirty = true; + + for(uint32 p = 0; p < 256; p++) + { + uint32 v; + uint8 s[4]; + + s[0] = (p >> 0) & 0x3; + s[1] = (p >> 2) & 0x3; + s[2] = (p >> 4) & 0x3; + s[3] = (p >> 6) & 0x3; + + v = 0; + for(unsigned int i = 0, shifty = 0; i < 4; i++) + { + for(unsigned int ps = 0; ps < prescale; ps++) + { + v |= s[i] << shifty; + shifty += 2; + } + } + + HLILUT[p] = v; + } +} + +void VIP_SetParallaxDisable(bool disabled) +{ + ParallaxDisabled = disabled; +} + +void VIP_SetDefaultColor(uint32 default_color) +{ + Default_Color = default_color; + + VidSettingsDirty = true; +} + + +void VIP_SetAnaglyphColors(uint32 lcolor, uint32 rcolor) +{ + Anaglyph_Colors[0] = lcolor; + Anaglyph_Colors[1] = rcolor; + + VidSettingsDirty = true; +} + +void VIP_SetInstantDisplayHack(bool val) +{ + InstantDisplayHack = val; +} + +void VIP_SetAllowDrawSkip(bool val) +{ + AllowDrawSkip = val; +} + + +static uint16 FRMCYC; + +static uint16 DPCTRL; +static bool DisplayActive; + +#define XPCTRL_XP_RST 0x0001 +#define XPCTRL_XP_EN 0x0002 +static uint16 XPCTRL; +static uint16 SBCMP; // Derived from XPCTRL + +static uint16 SPT[4]; // SPT0~SPT3, 5f848~5f84e +static uint16 GPLT[4]; +static uint8 GPLT_Cache[4][4]; + +static INLINE void Recalc_GPLT_Cache(int which) +{ + for(int i = 0; i < 4; i++) + GPLT_Cache[which][i] = (GPLT[which] >> (i * 2)) & 3; +} + +static uint16 JPLT[4]; +static uint8 JPLT_Cache[4][4]; + +static INLINE void Recalc_JPLT_Cache(int which) +{ + for(int i = 0; i < 4; i++) + JPLT_Cache[which][i] = (JPLT[which] >> (i * 2)) & 3; +} + + +static uint16 BKCOL; + +// +// +// +static int32 CalcNextEvent(void); + +static int32 last_ts; + +static int32 Column; +static int32 ColumnCounter; + +static int32 DisplayRegion; +static bool DisplayFB; + +static int32 GameFrameCounter; + +static int32 DrawingCounter; +static bool DrawingActive; +static bool DrawingFB; +static uint32 DrawingBlock; +static int32 SB_Latch; +static int32 SBOUT_InactiveTime; + +//static uint8 CTA_L, CTA_R; + +static void CheckIRQ(void) +{ + VBIRQ_Assert(VBIRQ_SOURCE_VIP, (bool)(InterruptEnable & InterruptPending)); + + #if 0 + printf("%08x\n", InterruptEnable & InterruptPending); + if((bool)(InterruptEnable & InterruptPending)) + puts("IRQ asserted"); + else + puts("IRQ not asserted"); + #endif +} + + +bool VIP_Init(void) +{ + InstantDisplayHack = false; + AllowDrawSkip = false; + ParallaxDisabled = false; + Anaglyph_Colors[0] = 0xFF0000; + Anaglyph_Colors[1] = 0x0000FF; + VB3DMode = VB3DMODE_ANAGLYPH; + Default_Color = 0xFFFFFF; + VB3DReverse = 0; + VBPrescale = 1; + VBSBS_Separation = 0; + + VidSettingsDirty = true; + + return(true); +} + +void VIP_Power(void) +{ + Repeat = 0; + SB_Latch = 0; + SBOUT_InactiveTime = -1; + last_ts = 0; + + Column = 0; + ColumnCounter = 259; + + DisplayRegion = 0; + DisplayFB = 0; + + GameFrameCounter = 0; + + DrawingCounter = 0; + DrawingActive = false; + DrawingFB = 0; + DrawingBlock = 0; + + DPCTRL = 2; + DisplayActive = false; + + + + memset(FB, 0, 0x6000 * 2 * 2); + memset(CHR_RAM, 0, 0x8000); + memset(DRAM, 0, 0x20000); + + InterruptPending = 0; + InterruptEnable = 0; + + BRTA = 0; + BRTB = 0; + BRTC = 0; + REST = 0; + + FRMCYC = 0; + + XPCTRL = 0; + SBCMP = 0; + + for(int i = 0; i < 4; i++) + { + SPT[i] = 0; + GPLT[i] = 0; + JPLT[i] = 0; + + Recalc_GPLT_Cache(i); + Recalc_JPLT_Cache(i); + } + + BKCOL = 0; +} + +static INLINE uint16 ReadRegister(int32 ×tamp, uint32 A) +{ + uint16 ret = 0; //0xFFFF; + + if(A & 1) + VIP_DBGMSG("Misaligned VIP Read: %08x", A); + + switch(A & 0xFE) + { + default: VIP_DBGMSG("Unknown VIP register read: %08x", A); + break; + + case 0x00: ret = InterruptPending; + break; + + case 0x02: ret = InterruptEnable; + break; + + case 0x20: //printf("Read DPSTTS at %d\n", timestamp); + ret = DPCTRL & 0x702; + if((DisplayRegion & 1) && DisplayActive) + { + unsigned int DPBSY = 1 << ((DisplayRegion >> 1) & 1); + + if(DisplayFB) + DPBSY <<= 2; + + ret |= DPBSY << 2; + } + //if(!(DisplayRegion & 1)) // FIXME? (Had to do it this way for Galactic Pinball...) + ret |= 1 << 6; + break; + + // Note: Upper bits of BRTA, BRTB, BRTC, and REST(?) are 0 when read(on real hardware) + case 0x24: ret = BRTA; + break; + + case 0x26: ret = BRTB; + break; + + case 0x28: ret = BRTC; + break; + + case 0x2A: ret = REST; + break; + + case 0x30: ret = 0xFFFF; + break; + + case 0x40: ret = XPCTRL & 0x2; + if(DrawingActive) + { + ret |= (1 + DrawingFB) << 2; + } + if(timestamp < SBOUT_InactiveTime) + { + ret |= 0x8000; + ret |= /*DrawingBlock*/SB_Latch << 8; + } + break; // XPSTTS, read-only + + case 0x44: ret = 2; // VIP version. 2 is a known valid version, while the validity of other numbers is unknown, so we'll just go with 2. + break; + + case 0x48: + case 0x4a: + case 0x4c: + case 0x4e: ret = SPT[(A >> 1) & 3]; + break; + + case 0x60: + case 0x62: + case 0x64: + case 0x66: ret = GPLT[(A >> 1) & 3]; + break; + + case 0x68: + case 0x6a: + case 0x6c: + case 0x6e: ret = JPLT[(A >> 1) & 3]; + break; + + case 0x70: ret = BKCOL; + break; + } + + return(ret); +} + +static INLINE void WriteRegister(int32 ×tamp, uint32 A, uint16 V) +{ + if(A & 1) + VIP_DBGMSG("Misaligned VIP Write: %08x %04x", A, V); + + switch(A & 0xFE) + { + default: VIP_DBGMSG("Unknown VIP register write: %08x %04x", A, V); + break; + + case 0x00: break; // Interrupt pending, read-only + + case 0x02: { + InterruptEnable = V & 0xE01F; + + VIP_DBGMSG("Interrupt Enable: %04x", V); + + if(V & 0x2000) + VIP_DBGMSG("Warning: VIP SB Hit Interrupt enable: %04x\n", V); + CheckIRQ(); + } + break; + + case 0x04: InterruptPending &= ~V; + CheckIRQ(); + break; + + case 0x20: break; // Display control, read-only. + + case 0x22: DPCTRL = V & (0x703); // Display-control, write-only + if(V & 1) + { + DisplayActive = false; + InterruptPending &= ~(INT_TIME_ERR | INT_FRAME_START | INT_GAME_START | INT_RFB_END | INT_LFB_END | INT_SCAN_ERR); + CheckIRQ(); + } + break; + + case 0x24: BRTA = V & 0xFF; // BRTA + RecalcBrightnessCache(); + break; + + case 0x26: BRTB = V & 0xFF; // BRTB + RecalcBrightnessCache(); + break; + + case 0x28: BRTC = V & 0xFF; // BRTC + RecalcBrightnessCache(); + break; + + case 0x2A: REST = V & 0xFF; // REST + RecalcBrightnessCache(); + break; + + case 0x2E: FRMCYC = V & 0xF; // FRMCYC, write-only? + break; + + case 0x30: break; // CTA, read-only( + + case 0x40: break; // XPSTTS, read-only + + case 0x42: XPCTRL = V & 0x0002; // XPCTRL, write-only + SBCMP = (V >> 8) & 0x1F; + + if(V & 1) + { + VIP_DBGMSG("XPRST"); + DrawingActive = 0; + DrawingCounter = 0; + InterruptPending &= ~(INT_SB_HIT | INT_XP_END | INT_TIME_ERR); + CheckIRQ(); + } + break; + + case 0x44: break; // Version Control, read-only? + + case 0x48: + case 0x4a: + case 0x4c: + case 0x4e: SPT[(A >> 1) & 3] = V & 0x3FF; + break; + + case 0x60: + case 0x62: + case 0x64: + case 0x66: GPLT[(A >> 1) & 3] = V & 0xFC; + Recalc_GPLT_Cache((A >> 1) & 3); + break; + + case 0x68: + case 0x6a: + case 0x6c: + case 0x6e: JPLT[(A >> 1) & 3] = V & 0xFC; + Recalc_JPLT_Cache((A >> 1) & 3); + break; + + case 0x70: BKCOL = V & 0x3; + break; + + } +} + +// +// Don't update the VIP state on reads/writes, the event system will update it with enough precision as far as VB software cares. +// + +uint8 VIP_Read8(int32 ×tamp, uint32 A) +{ + uint8 ret = 0; //0xFF; + + //VIP_Update(timestamp); + + switch(A >> 16) + { + case 0x0: + case 0x1: + if((A & 0x7FFF) >= 0x6000) + { + ret = VIP_MA16R8(CHR_RAM, (A & 0x1FFF) | ((A >> 2) & 0x6000)); + } + else + { + ret = FB[(A >> 15) & 1][(A >> 16) & 1][A & 0x7FFF]; + } + break; + + case 0x2: + case 0x3: ret = VIP_MA16R8(DRAM, A & 0x1FFFF); + break; + + case 0x4: + case 0x5: if(A >= 0x5E000) + ret = ReadRegister(timestamp, A); + else + VIP_DBGMSG("Unknown VIP Read: %08x", A); + break; + + case 0x6: break; + + case 0x7: if(A >= 0x8000) + { + ret = VIP_MA16R8(CHR_RAM, A & 0x7FFF); + } + else + VIP_DBGMSG("Unknown VIP Read: %08x", A); + break; + + default: VIP_DBGMSG("Unknown VIP Read: %08x", A); + break; + } + + + //VB_SetEvent(VB_EVENT_VIP, timestamp + CalcNextEvent()); + + return(ret); +} + +uint16 VIP_Read16(int32 ×tamp, uint32 A) +{ + uint16 ret = 0; //0xFFFF; + + //VIP_Update(timestamp); + + switch(A >> 16) + { + case 0x0: + case 0x1: + if((A & 0x7FFF) >= 0x6000) + { + ret = VIP_MA16R16(CHR_RAM, (A & 0x1FFF) | ((A >> 2) & 0x6000)); + } + else + { + ret = LoadU16_LE((uint16 *)&FB[(A >> 15) & 1][(A >> 16) & 1][A & 0x7FFF]); + } + break; + + case 0x2: + case 0x3: ret = VIP_MA16R16(DRAM, A & 0x1FFFF); + break; + + case 0x4: + case 0x5: + if(A >= 0x5E000) + ret = ReadRegister(timestamp, A); + else + VIP_DBGMSG("Unknown VIP Read: %08x", A); + break; + + case 0x6: break; + + case 0x7: if(A >= 0x8000) + { + ret = VIP_MA16R16(CHR_RAM, A & 0x7FFF); + } + else + VIP_DBGMSG("Unknown VIP Read: %08x", A); + break; + + default: VIP_DBGMSG("Unknown VIP Read: %08x", A); + break; + } + + + //VB_SetEvent(VB_EVENT_VIP, timestamp + CalcNextEvent()); + return(ret); +} + +void VIP_Write8(int32 ×tamp, uint32 A, uint8 V) +{ + //VIP_Update(timestamp); + + //if(A >= 0x3DC00 && A < 0x3E000) + // printf("%08x %02x\n", A, V); + + switch(A >> 16) + { + case 0x0: + case 0x1: + if((A & 0x7FFF) >= 0x6000) + VIP_MA16W8(CHR_RAM, (A & 0x1FFF) | ((A >> 2) & 0x6000), V); + else + FB[(A >> 15) & 1][(A >> 16) & 1][A & 0x7FFF] = V; + break; + + case 0x2: + case 0x3: VIP_MA16W8(DRAM, A & 0x1FFFF, V); + break; + + case 0x4: + case 0x5: if(A >= 0x5E000) + WriteRegister(timestamp, A, V); + else + VIP_DBGMSG("Unknown VIP Write: %08x %02x", A, V); + break; + + case 0x6: VIP_DBGMSG("Unknown VIP Write: %08x %02x", A, V); + break; + + case 0x7: if(A >= 0x8000) + VIP_MA16W8(CHR_RAM, A & 0x7FFF, V); + else + VIP_DBGMSG("Unknown VIP Write: %08x %02x", A, V); + break; + + default: VIP_DBGMSG("Unknown VIP Write: %08x %02x", A, V); + break; + } + + //VB_SetEvent(VB_EVENT_VIP, timestamp + CalcNextEvent()); +} + +void VIP_Write16(int32 ×tamp, uint32 A, uint16 V) +{ + //VIP_Update(timestamp); + + //if(A >= 0x3DC00 && A < 0x3E000) + // printf("%08x %04x\n", A, V); + + switch(A >> 16) + { + case 0x0: + case 0x1: + if((A & 0x7FFF) >= 0x6000) + VIP_MA16W16(CHR_RAM, (A & 0x1FFF) | ((A >> 2) & 0x6000), V); + else + StoreU16_LE((uint16 *)&FB[(A >> 15) & 1][(A >> 16) & 1][A & 0x7FFF], V); + break; + + case 0x2: + case 0x3: VIP_MA16W16(DRAM, A & 0x1FFFF, V); + break; + + case 0x4: + case 0x5: if(A >= 0x5E000) + WriteRegister(timestamp, A, V); + else + VIP_DBGMSG("Unknown VIP Write: %08x %04x", A, V); + break; + + case 0x6: VIP_DBGMSG("Unknown VIP Write: %08x %04x", A, V); + break; + + case 0x7: if(A >= 0x8000) + VIP_MA16W16(CHR_RAM, A & 0x7FFF, V); + else + VIP_DBGMSG("Unknown VIP Write: %08x %04x", A, V); + break; + + default: VIP_DBGMSG("Unknown VIP Write: %08x %04x", A, V); + break; + } + + + //VB_SetEvent(VB_EVENT_VIP, timestamp + CalcNextEvent()); +} + +static MDFN_Surface *surface; +static bool skip; + +void VIP_StartFrame(EmulateSpecStruct *espec) +{ +// puts("Start frame"); + + if(espec->VideoFormatChanged || VidSettingsDirty) + { + MakeColorLUT(espec->surface->format); + Recalc3DModeStuff(espec->surface->format.colorspace != MDFN_COLORSPACE_RGB); + + VidSettingsDirty = false; + } + + espec->DisplayRect.x = 0; + espec->DisplayRect.y = 0; + + switch(VB3DMode) + { + default: + espec->DisplayRect.w = 384; + espec->DisplayRect.h = 224; + break; + + case VB3DMODE_VLI: + espec->DisplayRect.w = 768 * VBPrescale; + espec->DisplayRect.h = 224; + break; + + case VB3DMODE_HLI: + espec->DisplayRect.w = 384; + espec->DisplayRect.h = 448 * VBPrescale; + break; + + case VB3DMODE_CSCOPE: + espec->DisplayRect.w = 512; + espec->DisplayRect.h = 384; + break; + + case VB3DMODE_SIDEBYSIDE: + espec->DisplayRect.w = 768 + VBSBS_Separation; + espec->DisplayRect.h = 224; + break; + } + + surface = espec->surface; + skip = espec->skip; +} + +void VIP_ResetTS(void) +{ + if(SBOUT_InactiveTime >= 0) + SBOUT_InactiveTime -= last_ts; + last_ts = 0; +} + +static int32 CalcNextEvent(void) +{ + return(ColumnCounter); +} + +#include "vip_draw.inc" + +static INLINE void CopyFBColumnToTarget_Anaglyph_BASE(const bool DisplayActive_arg, const int lr) +{ + const int fb = DisplayFB; + uint32 *target = surface->pixels + Column; + const int32 pitch32 = surface->pitch32; + const uint8 *fb_source = &FB[fb][lr][64 * Column]; + + for(int y = 56; y; y--) + { + uint32 source_bits = *fb_source; + + for(int y_sub = 4; y_sub; y_sub--) + { + uint32 pixel = BrightCLUT[lr][source_bits & 3]; + + if(!DisplayActive_arg) + pixel = 0; + + if(lr) + *target |= pixel; + else + *target = pixel; + + source_bits >>= 2; + target += pitch32; + } + fb_source++; + } +} + +static void CopyFBColumnToTarget_Anaglyph(void) +{ + const int lr = (DisplayRegion & 2) >> 1; + + if(!DisplayActive) + { + if(!lr) + CopyFBColumnToTarget_Anaglyph_BASE(0, 0); + else + CopyFBColumnToTarget_Anaglyph_BASE(0, 1); + } + else + { + if(!lr) + CopyFBColumnToTarget_Anaglyph_BASE(1, 0); + else + CopyFBColumnToTarget_Anaglyph_BASE(1, 1); + } +} + +static uint32 AnaSlowBuf[384][224]; + +static INLINE void CopyFBColumnToTarget_AnaglyphSlow_BASE(const bool DisplayActive_arg, const int lr) +{ + const int fb = DisplayFB; + const uint8 *fb_source = &FB[fb][lr][64 * Column]; + + if(!lr) + { + uint32 *target = AnaSlowBuf[Column]; + + for(int y = 56; y; y--) + { + uint32 source_bits = *fb_source; + + for(int y_sub = 4; y_sub; y_sub--) + { + uint32 pixel = BrightnessCache[source_bits & 3]; + + if(!DisplayActive_arg) + pixel = 0; + + *target = pixel; + source_bits >>= 2; + target++; + } + fb_source++; + } + + } + else + { + uint32 *target = surface->pixels + Column; + const uint32 *left_src = AnaSlowBuf[Column]; + const int32 pitch32 = surface->pitch32; + + for(int y = 56; y; y--) + { + uint32 source_bits = *fb_source; + + for(int y_sub = 4; y_sub; y_sub--) + { + uint32 pixel = AnaSlowColorLUT[*left_src][DisplayActive_arg ? BrightnessCache[source_bits & 3] : 0]; + + *target = pixel; + + source_bits >>= 2; + target += pitch32; + left_src++; + } + fb_source++; + } + } +} + +static void CopyFBColumnToTarget_AnaglyphSlow(void) +{ + const int lr = (DisplayRegion & 2) >> 1; + + if(!DisplayActive) + { + if(!lr) + CopyFBColumnToTarget_AnaglyphSlow_BASE(0, 0); + else + CopyFBColumnToTarget_AnaglyphSlow_BASE(0, 1); + } + else + { + if(!lr) + CopyFBColumnToTarget_AnaglyphSlow_BASE(1, 0); + else + CopyFBColumnToTarget_AnaglyphSlow_BASE(1, 1); + } +} + + +static void CopyFBColumnToTarget_CScope_BASE(const bool DisplayActive_arg, const int lr, const int dest_lr) +{ + const int fb = DisplayFB; + uint32 *target = surface->pixels + (dest_lr ? 512 - 16 - 1 : 16) + (dest_lr ? Column : 383 - Column) * surface->pitch32; + const uint8 *fb_source = &FB[fb][lr][64 * Column]; + + for(int y = 56; y; y--) + { + uint32 source_bits = *fb_source; + + for(int y_sub = 4; y_sub; y_sub--) + { + if(DisplayActive_arg) + *target = BrightCLUT[lr][source_bits & 3]; + else + *target = 0; + + source_bits >>= 2; + if(dest_lr) + target--; + else + target++; + } + fb_source++; + } +} + +static void CopyFBColumnToTarget_CScope(void) +{ + const int lr = (DisplayRegion & 2) >> 1; + + if(!DisplayActive) + { + if(!lr) + CopyFBColumnToTarget_CScope_BASE(0, 0, 0 ^ VB3DReverse); + else + CopyFBColumnToTarget_CScope_BASE(0, 1, 1 ^ VB3DReverse); + } + else + { + if(!lr) + CopyFBColumnToTarget_CScope_BASE(1, 0, 0 ^ VB3DReverse); + else + CopyFBColumnToTarget_CScope_BASE(1, 1, 1 ^ VB3DReverse); + } +} + +static void CopyFBColumnToTarget_SideBySide_BASE(const bool DisplayActive_arg, const int lr, const int dest_lr) +{ + const int fb = DisplayFB; + uint32 *target = surface->pixels + Column + (dest_lr ? (384 + VBSBS_Separation) : 0); + const int32 pitch32 = surface->pitch32; + const uint8 *fb_source = &FB[fb][lr][64 * Column]; + + for(int y = 56; y; y--) + { + uint32 source_bits = *fb_source; + + for(int y_sub = 4; y_sub; y_sub--) + { + if(DisplayActive_arg) + *target = BrightCLUT[lr][source_bits & 3]; + else + *target = 0; + source_bits >>= 2; + target += pitch32; + } + fb_source++; + } +} + +static void CopyFBColumnToTarget_SideBySide(void) +{ + const int lr = (DisplayRegion & 2) >> 1; + + if(!DisplayActive) + { + if(!lr) + CopyFBColumnToTarget_SideBySide_BASE(0, 0, 0 ^ VB3DReverse); + else + CopyFBColumnToTarget_SideBySide_BASE(0, 1, 1 ^ VB3DReverse); + } + else + { + if(!lr) + CopyFBColumnToTarget_SideBySide_BASE(1, 0, 0 ^ VB3DReverse); + else + CopyFBColumnToTarget_SideBySide_BASE(1, 1, 1 ^ VB3DReverse); + } +} + +static INLINE void CopyFBColumnToTarget_VLI_BASE(const bool DisplayActive_arg, const int lr, const int dest_lr) +{ + const int fb = DisplayFB; + uint32 *target = surface->pixels + Column * 2 * VBPrescale + dest_lr; + const int32 pitch32 = surface->pitch32; + const uint8 *fb_source = &FB[fb][lr][64 * Column]; + + for(int y = 56; y; y--) + { + uint32 source_bits = *fb_source; + + for(int y_sub = 4; y_sub; y_sub--) + { + uint32 tv; + + if(DisplayActive_arg) + tv = BrightCLUT[0][source_bits & 3]; + else + tv = 0; + + for(uint32 ps = 0; ps < VBPrescale; ps++) + target[ps * 2] = tv; + + source_bits >>= 2; + target += pitch32; + } + fb_source++; + } +} + +static void CopyFBColumnToTarget_VLI(void) +{ + const int lr = (DisplayRegion & 2) >> 1; + + if(!DisplayActive) + { + if(!lr) + CopyFBColumnToTarget_VLI_BASE(0, 0, 0 ^ VB3DReverse); + else + CopyFBColumnToTarget_VLI_BASE(0, 1, 1 ^ VB3DReverse); + } + else + { + if(!lr) + CopyFBColumnToTarget_VLI_BASE(1, 0, 0 ^ VB3DReverse); + else + CopyFBColumnToTarget_VLI_BASE(1, 1, 1 ^ VB3DReverse); + } +} + +static INLINE void CopyFBColumnToTarget_HLI_BASE(const bool DisplayActive_arg, const int lr, const int dest_lr) +{ + const int fb = DisplayFB; + const int32 pitch32 = surface->pitch32; + uint32 *target = surface->pixels + Column + dest_lr * pitch32; + const uint8 *fb_source = &FB[fb][lr][64 * Column]; + +if(VBPrescale <= 4) + for(int y = 56; y; y--) + { + uint32 source_bits = HLILUT[*fb_source]; + + for(int y_sub = 4 * VBPrescale; y_sub; y_sub--) + { + if(DisplayActive_arg) + *target = BrightCLUT[0][source_bits & 3]; + else + *target = 0; + + target += pitch32 * 2; + source_bits >>= 2; + } + fb_source++; + } +else + for(int y = 56; y; y--) + { + uint32 source_bits = *fb_source; + + for(int y_sub = 4; y_sub; y_sub--) + { + for(uint32 ps = 0; ps < VBPrescale; ps++) + { + if(DisplayActive_arg) + *target = BrightCLUT[0][source_bits & 3]; + else + *target = 0; + + target += pitch32 * 2; + } + + source_bits >>= 2; + } + fb_source++; + } +} + +static void CopyFBColumnToTarget_HLI(void) +{ + const int lr = (DisplayRegion & 2) >> 1; + + if(!DisplayActive) + { + if(!lr) + CopyFBColumnToTarget_HLI_BASE(0, 0, 0 ^ VB3DReverse); + else + CopyFBColumnToTarget_HLI_BASE(0, 1, 1 ^ VB3DReverse); + } + else + { + if(!lr) + CopyFBColumnToTarget_HLI_BASE(1, 0, 0 ^ VB3DReverse); + else + CopyFBColumnToTarget_HLI_BASE(1, 1, 1 ^ VB3DReverse); + } +} + + +v810_timestamp_t MDFN_FASTCALL VIP_Update(const v810_timestamp_t timestamp) +{ + int32 clocks = timestamp - last_ts; + int32 running_timestamp = timestamp; + + while(clocks > 0) + { + int32 chunk_clocks = clocks; + + if(DrawingCounter > 0 && chunk_clocks > DrawingCounter) + chunk_clocks = DrawingCounter; + if(chunk_clocks > ColumnCounter) + chunk_clocks = ColumnCounter; + + running_timestamp += chunk_clocks; + + if(DrawingCounter > 0) + { + DrawingCounter -= chunk_clocks; + if(DrawingCounter <= 0) + { + MDFN_ALIGN(8) uint8 DrawingBuffers[2][512 * 8]; // Don't decrease this from 512 unless you adjust vip_draw.inc(including areas that draw off-visible >= 384 and >= -7 for speed reasons) + + if(skip && InstantDisplayHack && AllowDrawSkip) + { +#if 0 + for(int lr = 0; lr < 2; lr++) + { + uint8 *FB_Target = FB[DrawingFB][lr] + DrawingBlock * 2; + for(int x = 0; x < 384; x++) + { + FB_Target[64 * x + 0] = BKCOL; + FB_Target[64 * x + 1] = BKCOL; + } + } +#endif + } + else + { + VIP_DrawBlock(DrawingBlock, DrawingBuffers[0] + 8, DrawingBuffers[1] + 8); + + for(int lr = 0; lr < 2; lr++) + { + uint8 *FB_Target = FB[DrawingFB][lr] + DrawingBlock * 2; + + for(int x = 0; x < 384; x++) + { + FB_Target[64 * x + 0] = (DrawingBuffers[lr][8 + x + 512 * 0] << 0) + | (DrawingBuffers[lr][8 + x + 512 * 1] << 2) + | (DrawingBuffers[lr][8 + x + 512 * 2] << 4) + | (DrawingBuffers[lr][8 + x + 512 * 3] << 6); + + FB_Target[64 * x + 1] = (DrawingBuffers[lr][8 + x + 512 * 4] << 0) + | (DrawingBuffers[lr][8 + x + 512 * 5] << 2) + | (DrawingBuffers[lr][8 + x + 512 * 6] << 4) + | (DrawingBuffers[lr][8 + x + 512 * 7] << 6); + + } + } + } + + SBOUT_InactiveTime = running_timestamp + 1120; + SB_Latch = DrawingBlock; // Not exactly correct, but probably doesn't matter. + + DrawingBlock++; + if(DrawingBlock == 28) + { + DrawingActive = false; + + InterruptPending |= INT_XP_END; + CheckIRQ(); + } + else + DrawingCounter += 1120 * 4; + } + } + + ColumnCounter -= chunk_clocks; + if(ColumnCounter == 0) + { + if(DisplayRegion & 1) + { + if(!(Column & 3)) + { + const int lr = (DisplayRegion & 2) >> 1; + uint16 ctdata = VIP_MA16R16(DRAM, 0x1DFFE - ((Column >> 2) * 2) - (lr ? 0 : 0x200)); + + if((ctdata >> 8) != Repeat) + { + Repeat = ctdata >> 8; + RecalcBrightnessCache(); + } + } + if(!skip && !InstantDisplayHack) + CopyFBColumnToTarget(); + } + + ColumnCounter = 259; + Column++; + if(Column == 384) + { + Column = 0; + + if(DisplayActive) + { + if(DisplayRegion & 1) // Did we just finish displaying an active region? + { + if(DisplayRegion & 2) // finished displaying right eye + InterruptPending |= INT_RFB_END; + else // Otherwise, left eye + InterruptPending |= INT_LFB_END; + + CheckIRQ(); + } + } + + DisplayRegion = (DisplayRegion + 1) & 3; + + if(DisplayRegion == 0) // New frame start + { + DisplayActive = DPCTRL & 0x2; + + if(DisplayActive) + { + InterruptPending |= INT_FRAME_START; + CheckIRQ(); + } + GameFrameCounter++; + if(GameFrameCounter > FRMCYC) // New game frame start? + { + InterruptPending |= INT_GAME_START; + CheckIRQ(); + + if(XPCTRL & XPCTRL_XP_EN) + { + DisplayFB ^= 1; + + DrawingBlock = 0; + DrawingActive = true; + DrawingCounter = 1120 * 4; + DrawingFB = DisplayFB ^ 1; + } + + GameFrameCounter = 0; + } + + if(!skip && InstantDisplayHack) + { + // Ugly kludge, fix in the future. + int32 save_DisplayRegion = DisplayRegion; + int32 save_Column = Column; + uint8 save_Repeat = Repeat; + + for(int lr = 0; lr < 2; lr++) + { + DisplayRegion = lr << 1; + for(Column = 0; Column < 384; Column++) + { + if(!(Column & 3)) + { + uint16 ctdata = VIP_MA16R16(DRAM, 0x1DFFE - ((Column >> 2) * 2) - (lr ? 0 : 0x200)); + + if((ctdata >> 8) != Repeat) + { + Repeat = ctdata >> 8; + RecalcBrightnessCache(); + } + } + + CopyFBColumnToTarget(); + } + } + DisplayRegion = save_DisplayRegion; + Column = save_Column; + Repeat = save_Repeat; + RecalcBrightnessCache(); + } + + VB_ExitLoop(); + } + } + } + + clocks -= chunk_clocks; + } + + last_ts = timestamp; + + return(timestamp + CalcNextEvent()); +} + + +int VIP_StateAction(StateMem *sm, int load, int data_only) +{ + SFORMAT StateRegs[] = + { + SFARRAY(FB[0][0], 0x6000 * 2 * 2), + SFARRAY16(CHR_RAM, 0x8000 / sizeof(uint16)), + SFARRAY16(DRAM, 0x20000 / sizeof(uint16)), + + SFVAR(InterruptPending), + SFVAR(InterruptEnable), + + SFVAR(BRTA), + SFVAR(BRTB), + SFVAR(BRTC), + SFVAR(REST), + + SFVAR(FRMCYC), + SFVAR(DPCTRL), + + SFVAR(DisplayActive), + + SFVAR(XPCTRL), + SFVAR(SBCMP), + SFARRAY16(SPT, 4), + SFARRAY16(GPLT, 4), // FIXME + SFARRAY16(JPLT, 4), + + SFVAR(BKCOL), + + SFVAR(Column), + SFVAR(ColumnCounter), + + SFVAR(DisplayRegion), + SFVAR(DisplayFB), + + SFVAR(GameFrameCounter), + + SFVAR(DrawingCounter), + + SFVAR(DrawingActive), + SFVAR(DrawingFB), + SFVAR(DrawingBlock), + + SFVAR(SB_Latch), + SFVAR(SBOUT_InactiveTime), + + SFVAR(Repeat), + SFEND + }; + + int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "VIP"); + + if(load) + { + RecalcBrightnessCache(); + for(int i = 0; i < 4; i++) + { + Recalc_GPLT_Cache(i); + Recalc_JPLT_Cache(i); + } + } + + return(ret); +} + +uint32 VIP_GetRegister(const unsigned int id, char *special, const uint32 special_len) +{ + uint32 ret = 0xDEADBEEF; + + switch(id) + { + case VIP_GSREG_IPENDING: + ret = InterruptPending; + break; + + case VIP_GSREG_IENABLE: + ret = InterruptEnable; + break; + + case VIP_GSREG_DPCTRL: + ret = DPCTRL; + break; + + case VIP_GSREG_BRTA: + ret = BRTA; + break; + + case VIP_GSREG_BRTB: + ret = BRTB; + break; + + case VIP_GSREG_BRTC: + ret = BRTC; + break; + + case VIP_GSREG_REST: + ret = REST; + break; + + case VIP_GSREG_FRMCYC: + ret = FRMCYC; + break; + + case VIP_GSREG_XPCTRL: + ret = XPCTRL | (SBCMP << 8); + break; + + case VIP_GSREG_SPT0: + case VIP_GSREG_SPT1: + case VIP_GSREG_SPT2: + case VIP_GSREG_SPT3: + ret = SPT[id - VIP_GSREG_SPT0]; + break; + + case VIP_GSREG_GPLT0: + case VIP_GSREG_GPLT1: + case VIP_GSREG_GPLT2: + case VIP_GSREG_GPLT3: + ret = GPLT[id - VIP_GSREG_GPLT0]; + break; + + case VIP_GSREG_JPLT0: + case VIP_GSREG_JPLT1: + case VIP_GSREG_JPLT2: + case VIP_GSREG_JPLT3: + ret = JPLT[id - VIP_GSREG_JPLT0]; + break; + + case VIP_GSREG_BKCOL: + ret = BKCOL; + break; + + } + + if(id == VIP_GSREG_IPENDING || id == VIP_GSREG_IENABLE) + { + if(special) + trio_snprintf(special, special_len, "%s: %s%s%s%s%s%s%s%s", + (id == VIP_GSREG_IPENDING) ? "Interrupts Pending" : "Interrupts Enabled", + (ret & INT_SCAN_ERR) ? "SCAN_ERR " : "", + (ret & INT_LFB_END) ? "LFB_END " : "", + (ret & INT_RFB_END) ? "RFB_END " : "", + (ret & INT_GAME_START) ? "GAME_START " : "", + (ret & INT_FRAME_START) ? "FRAME_START " : "", + (ret & INT_SB_HIT) ? "SB_HIT " : "", + (ret & INT_XP_END) ? "XP_END " : "", + (ret & INT_TIME_ERR) ? "TIME_ERR " : ""); + + } + + return(ret); +} + +void VIP_SetRegister(const unsigned int id, const uint32 value) +{ + switch(id) + { + case VIP_GSREG_IPENDING: + InterruptPending = value & 0xE01F; + CheckIRQ(); + break; + + case VIP_GSREG_IENABLE: + InterruptEnable = value & 0xE01F; + CheckIRQ(); + break; + + case VIP_GSREG_DPCTRL: + DPCTRL = value & 0x703; // FIXME(Lower bit?) + break; + + case VIP_GSREG_BRTA: + BRTA = value & 0xFF; + RecalcBrightnessCache(); + break; + + case VIP_GSREG_BRTB: + BRTB = value & 0xFF; + RecalcBrightnessCache(); + break; + + case VIP_GSREG_BRTC: + BRTC = value & 0xFF; + RecalcBrightnessCache(); + break; + + case VIP_GSREG_REST: + REST = value & 0xFF; + RecalcBrightnessCache(); + break; + + case VIP_GSREG_FRMCYC: + FRMCYC = value & 0xF; + break; + + case VIP_GSREG_XPCTRL: + XPCTRL = value & 0x2; + SBCMP = (value >> 8) & 0x1f; + break; + + case VIP_GSREG_SPT0: + case VIP_GSREG_SPT1: + case VIP_GSREG_SPT2: + case VIP_GSREG_SPT3: + SPT[id - VIP_GSREG_SPT0] = value & 0x3FF; + break; + + case VIP_GSREG_GPLT0: + case VIP_GSREG_GPLT1: + case VIP_GSREG_GPLT2: + case VIP_GSREG_GPLT3: + GPLT[id - VIP_GSREG_GPLT0] = value & 0xFC; + Recalc_GPLT_Cache(id - VIP_GSREG_GPLT0); + break; + + case VIP_GSREG_JPLT0: + case VIP_GSREG_JPLT1: + case VIP_GSREG_JPLT2: + case VIP_GSREG_JPLT3: + JPLT[id - VIP_GSREG_JPLT0] = value & 0xFC; + Recalc_JPLT_Cache(id - VIP_GSREG_JPLT0); + break; + + case VIP_GSREG_BKCOL: + BKCOL = value & 0x03; + break; + } +} + + +} diff --git a/mednafen/vb-09333/vip.h b/mednafen/vb-09333/vip.h new file mode 100644 index 0000000..0bbe653 --- /dev/null +++ b/mednafen/vb-09333/vip.h @@ -0,0 +1,71 @@ +#ifndef __VB_VIP_H +#define __VB_VIP_H + +namespace MDFN_IEN_VB +{ + +bool VIP_Init(void) MDFN_COLD; +void VIP_Power(void) MDFN_COLD; + +void VIP_SetInstantDisplayHack(bool); +void VIP_SetAllowDrawSkip(bool); +void VIP_Set3DMode(uint32 mode, bool reverse, uint32 prescale, uint32 sbs_separation); +void VIP_SetParallaxDisable(bool disabled); +void VIP_SetDefaultColor(uint32 default_color); +void VIP_SetAnaglyphColors(uint32 lcolor, uint32 rcolor); // R << 16, G << 8, B << 0 + +v810_timestamp_t MDFN_FASTCALL VIP_Update(const v810_timestamp_t timestamp); +void VIP_ResetTS(void); + +void VIP_StartFrame(EmulateSpecStruct *espec); + +uint8 VIP_Read8(v810_timestamp_t ×tamp, uint32 A); +uint16 VIP_Read16(v810_timestamp_t ×tamp, uint32 A); + + +void VIP_Write8(v810_timestamp_t ×tamp, uint32 A, uint8 V); +void VIP_Write16(v810_timestamp_t ×tamp, uint32 A, uint16 V); + + + +int VIP_StateAction(StateMem *sm, int load, int data_only); + + +enum +{ + VIP_GSREG_IPENDING = 0, // Current pending interrupt(bits) + VIP_GSREG_IENABLE, + + VIP_GSREG_DPCTRL, + + VIP_GSREG_BRTA, + VIP_GSREG_BRTB, + VIP_GSREG_BRTC, + VIP_GSREG_REST, + VIP_GSREG_FRMCYC, + VIP_GSREG_XPCTRL, + + VIP_GSREG_SPT0, + VIP_GSREG_SPT1, + VIP_GSREG_SPT2, + VIP_GSREG_SPT3, + + VIP_GSREG_GPLT0, + VIP_GSREG_GPLT1, + VIP_GSREG_GPLT2, + VIP_GSREG_GPLT3, + + VIP_GSREG_JPLT0, + VIP_GSREG_JPLT1, + VIP_GSREG_JPLT2, + VIP_GSREG_JPLT3, + + VIP_GSREG_BKCOL, +}; + +uint32 VIP_GetRegister(const unsigned int id, char *special, const uint32 special_len); +void VIP_SetRegister(const unsigned int id, const uint32 value); + + +} +#endif diff --git a/mednafen/vb-09333/vip_draw.inc b/mednafen/vb-09333/vip_draw.inc new file mode 100644 index 0000000..775f0de --- /dev/null +++ b/mednafen/vb-09333/vip_draw.inc @@ -0,0 +1,474 @@ +#include "vb.h" + +#define BGM_AFFINE 0x2 +#define BGM_OBJ 0x3 + + +static void DrawBG(uint8 *target, uint16 RealY, bool lr, uint8 bgmap_base_raw, bool overplane, uint16 overplane_char, uint32 SourceX, uint32 SourceY, uint32 scx, uint32 scy, uint16 DestX, uint16 DestY, uint16 DestWidth, uint16 DestHeight) +{ + const uint16 *CHR16 = CHR_RAM; + const uint16 *BGMap = DRAM; + uint32 BGMap_Base = bgmap_base_raw << 12; + int32 start_x, final_x; + const uint32 bgsc_overplane = DRAM[overplane_char]; + const uint32 BGMap_XCount = 1 << scx; + const uint32 BGMap_YCount = 1 << scy; + const uint32 SourceX_Size = 512 * BGMap_XCount; + const uint32 SourceY_Size = 512 * BGMap_YCount; + const uint32 SourceX_Mask = overplane ? 0x1FFF : (SourceX_Size - 1); + const uint32 SourceY_Mask = overplane ? 0x1FFF : (SourceY_Size - 1); + + if((uint16)(RealY - DestY) > DestHeight) + return; + + //printf("%d, %d, %d, %d\n", overplane, srcXSize, srcYSize, bgmap_base_raw); + + DestX = sign_10_to_s16(DestX); + + if(DestX & 0x8000) + SourceX -= DestX; + + start_x = (int16)DestX; + final_x = (int16)DestX + DestWidth; + + if(start_x < 0) + start_x = 0; + + if(final_x > 383) + final_x = 383; + + if(start_x > final_x) + return; + + // Optimization: + SourceY &= SourceY_Mask; + BGMap_Base |= (((SourceY >> 3) & 0x3F) * 0x40) | (((SourceY << 3) & ~0xFFF) << scx); + + for(int x = start_x; x <= final_x; x++) + { + uint32 bgsc; + uint32 char_no; + uint32 palette_selector; + uint32 hflip_xor; + uint32 vflip_xor; + + SourceX &= SourceX_Mask; + + bgsc = bgsc_overplane; + + if(SourceX < SourceX_Size && SourceY < SourceY_Size) + bgsc = BGMap[(BGMap_Base | ((SourceX << 3) & ~0xFFF) | ((SourceX >> 3) & 0x3F)) & 0xFFFF]; + + char_no = bgsc & 0x7FF; + palette_selector = bgsc >> 14; + hflip_xor = (bgsc & 0x2000) ? 7 : 0; //(((int32)bgsc << 18) >> 31) & 0x7; + vflip_xor = (bgsc & 0x1000) ? 7 : 0; //(((int32)bgsc << 19) >> 31) & 0x7; + + unsigned int char_sub_y = vflip_xor ^ (SourceY & 0x7); + + if(!(SourceX & 7) && (x + 7) <= final_x) + { + uint32 pixels = CHR16[char_no * 8 + char_sub_y]; + + #if 0 + unsigned int char_sub_x; + uint8 *sub_target = target + x + 8; + + for(int sub_x = -8; sub_x < 0; sub_x++) + { + if(pixels & 3) sub_target[sub_x] = GPLT_Cache[palette_selector][pixels & 3]; + pixels >>= 2; + } + #endif + + if(bgsc & 0x2000) + { + if((pixels >> 14) & 3) target[0 + x] = GPLT_Cache[palette_selector][(pixels >> 14) & 3]; + if((pixels >> 12) & 3) target[1 + x] = GPLT_Cache[palette_selector][(pixels >> 12) & 3]; + if((pixels >> 10) & 3) target[2 + x] = GPLT_Cache[palette_selector][(pixels >> 10) & 3]; + if((pixels >> 8) & 3) target[3 + x] = GPLT_Cache[palette_selector][(pixels >> 8) & 3]; + if((pixels >> 6) & 3) target[4 + x] = GPLT_Cache[palette_selector][(pixels >> 6) & 3]; + if((pixels >> 4) & 3) target[5 + x] = GPLT_Cache[palette_selector][(pixels >> 4) & 3]; + if((pixels >> 2) & 3) target[6 + x] = GPLT_Cache[palette_selector][(pixels >> 2) & 3]; + if((pixels >> 0) & 3) target[7 + x] = GPLT_Cache[palette_selector][(pixels >> 0) & 3]; + } + else + { + if((pixels >> 0) & 3) target[0 + x] = GPLT_Cache[palette_selector][(pixels >> 0) & 3]; + if((pixels >> 2) & 3) target[1 + x] = GPLT_Cache[palette_selector][(pixels >> 2) & 3]; + if((pixels >> 4) & 3) target[2 + x] = GPLT_Cache[palette_selector][(pixels >> 4) & 3]; + if((pixels >> 6) & 3) target[3 + x] = GPLT_Cache[palette_selector][(pixels >> 6) & 3]; + if((pixels >> 8) & 3) target[4 + x] = GPLT_Cache[palette_selector][(pixels >> 8) & 3]; + if((pixels >> 10) & 3) target[5 + x] = GPLT_Cache[palette_selector][(pixels >> 10) & 3]; + if((pixels >> 12) & 3) target[6 + x] = GPLT_Cache[palette_selector][(pixels >> 12) & 3]; + if((pixels >> 14) & 3) target[7 + x] = GPLT_Cache[palette_selector][(pixels >> 14) & 3]; + } + + x += 7; + SourceX += 8; + } + else + { + unsigned int char_sub_x; + + char_sub_x = hflip_xor ^ (SourceX & 0x7); + + uint8 pixel = (CHR16[char_no * 8 + char_sub_y] >> (char_sub_x * 2)) & 0x3; + + if(pixel) + target[x] = GPLT_Cache[palette_selector][pixel]; //target[x] = (GPLT[palette_selector] >> (pixel * 2)) & 0x3; + SourceX++; + } + } +} + +static void DrawAffine(uint8 *target, uint16 RealY, bool lr, uint32 ParamBase, uint32 BGMap_Base, bool OverplaneMode, uint16 OverplaneChar, uint32 scx, uint32 scy, + uint16 DestX, uint16 DestY, uint16 DestWidth, uint16 DestHeight) +{ + const uint16 *CHR16 = CHR_RAM; + const uint16 *BGMap = DRAM; + + const uint32 BGMap_XCount = 1 << scx; + const uint32 BGMap_YCount = 1 << scy; + const uint32 SourceX_Size = 512 * BGMap_XCount; + const uint32 SourceY_Size = 512 * BGMap_YCount; + + const uint16 *param_ptr = &DRAM[(ParamBase + 8 * (RealY - DestY)) & 0xFFFF]; + int16 mx = param_ptr[0], mp = (ParallaxDisabled ? 0 : param_ptr[1]), my = param_ptr[2], dx = param_ptr[3], dy = param_ptr[4]; + + uint32 SourceX, SourceY; + uint32 SourceX_Mask, SourceY_Mask; + + int32 start_x, final_x; + const uint32 bgsc_overplane = DRAM[OverplaneChar]; + + + DestX = sign_10_to_s16(DestX); + + if((uint16)(RealY - DestY) > DestHeight) + return; + + SourceX = (int32)mx << 6; + SourceY = (int32)my << 6; + + if(DestX & 0x8000) + { + SourceX += dx * (65536 - DestX); + SourceY += dy * (65536 - DestX); + } + + if(mp >= 0 && lr) + { + SourceX += dx * mp; + SourceY += dy * mp; + } + else if(mp < 0 && !lr) + { + SourceX += dx * -mp; + SourceY += dy * -mp; + } + + if(OverplaneMode) + { + SourceX_Mask = 0x3FFFFFF; //(((uint32)SourceX_Size << 9) * 2) - 1; + SourceY_Mask = 0x3FFFFFF; //(((uint32)SourceY_Size << 9) * 2) - 1; + } + else + { + SourceX_Mask = ((uint32)SourceX_Size << 9) - 1; + SourceY_Mask = ((uint32)SourceY_Size << 9) - 1; + } + + start_x = (int16)DestX; + final_x = (int16)DestX + DestWidth; + + if(start_x < 0) + start_x = 0; + + if(final_x > 383) + final_x = 383; + +if(dy == 0) // Optimization for no rotation. +{ + SourceY &= SourceY_Mask; + + if(SourceY >= (SourceY_Size << 9)) + return; + + BGMap_Base |= (((SourceY >> 6) & ~0xFFF) << scx) | (((SourceY >> 12) & 0x3F) * 0x40); + for(int x = start_x; x <= final_x; x++) + { + uint32 bgsc; + uint32 hflip_xor; + uint32 vflip_xor; + uint32 pixel = 0; + + SourceX &= SourceX_Mask; + + bgsc = bgsc_overplane; + + if(SourceX < (SourceX_Size << 9)) + bgsc = BGMap[(BGMap_Base | ((SourceX >> 6) & ~0xFFF) | ((SourceX >> 12) & 0x3F)) & 0xFFFF]; + + //hflip_xor = bgsc & 0x2000 ? 0xE : 0; + //vflip_xor = bgsc & 0x1000 ? 0x7 : 0; + hflip_xor = ((int32)(bgsc << 18) >> 30) & 0xE; + vflip_xor = ((int32)(bgsc << 19) >> 31) & 0x7; + + unsigned int char_sub_y = vflip_xor ^ ((SourceY >> 9) & 0x7); + unsigned int char_sub_x = hflip_xor ^ ((SourceX >> 8) & 0xE); + + pixel = (CHR16[((bgsc & 0x7FF) * 8) | char_sub_y] >> char_sub_x) & 0x3; + + if(pixel) + target[x] = GPLT_Cache[bgsc >> 14][pixel]; + + SourceX += dx; + } +} +else + for(int x = start_x; x <= final_x; x++) + { + uint32 bgsc; + uint32 char_no; + uint32 palette_selector; + uint32 hflip_xor; + uint32 vflip_xor; + uint8 pixel = 0; + + SourceX &= SourceX_Mask; + SourceY &= SourceY_Mask; + + bgsc = bgsc_overplane; + + if(SourceX < (SourceX_Size << 9) && SourceY < (SourceY_Size << 9)) + { + uint32 m_index = ((SourceX >> 6) & ~0xFFF) + (((SourceY >> 6) & ~0xFFF) << scx); + uint32 sub_index = ((SourceX >> 12) & 0x3F) + (((SourceY >> 12) & 0x3F) * 0x40); + + bgsc = BGMap[(BGMap_Base | m_index | sub_index) & 0xFFFF]; + + //bgsc = BGMap[(BGMapBase + (SourceX >> 12) + (SourceY >> 12) * (SourceX_Size >> 3)) & 0xFFFF ]; + } + char_no = bgsc & 0x7FF; + palette_selector = bgsc >> 14; + hflip_xor = bgsc & 0x2000 ? 7 : 0; //(((int32)bgsc << 18) >> 31) & 0x7; + vflip_xor = bgsc & 0x1000 ? 7 : 0; //(((int32)bgsc << 19) >> 31) & 0x7; + + unsigned int char_sub_y = vflip_xor ^ ((SourceY >> 9) & 0x7); + unsigned int char_sub_x = hflip_xor ^ ((SourceX >> 9) & 0x7); + + pixel = (CHR16[char_no * 8 + char_sub_y] >> (char_sub_x * 2)) & 0x3; + + if(pixel) + target[x] = GPLT_Cache[palette_selector][pixel]; + + SourceX += dx; + SourceY += dy; + } +} + +static int obj_search_which; + +static void DrawOBJ(uint8 *fb[2], uint16 Y, bool lron[2]) +{ + const uint16 *CHR16 = CHR_RAM; + + int32 start_oam; + int32 end_oam; + + start_oam = SPT[obj_search_which]; + + end_oam = 1023; + if(obj_search_which) + end_oam = SPT[obj_search_which - 1]; + + int32 oam = start_oam; + do + { + const uint16 *oam_ptr = &DRAM[(0x1E000 + (oam * 8)) >> 1]; + const uint32 jy = oam_ptr[2]; + const uint32 tile_y = (Y - jy) & 0xFF; // I think this mask is right. See: http://www.planetvb.com/modules/newbb/viewtopic.php?topic_id=3797&forum=2 + + if(tile_y >= 8) + continue; + + uint32 jx = oam_ptr[0]; + uint32 jp = ParallaxDisabled ? 0 : (oam_ptr[1] & 0x3FFF); + uint32 palette_selector = oam_ptr[3] >> 14; + uint32 vflip_xor = (oam_ptr[3] & 0x1000) ? 7 : 0; + uint32 char_sub_y = vflip_xor ^ tile_y; + bool jlron[2] = { (bool)(oam_ptr[1] & 0x8000), (bool)(oam_ptr[1] & 0x4000) }; + uint32 char_no = oam_ptr[3] & 0x7FF; + const uint32 pixels_save = CHR16[char_no * 8 + char_sub_y]; + + for(int lr = 0; lr < 2; lr++) + { + if(!(jlron[lr] & lron[lr])) + continue; + + uint32 pixels = pixels_save; + int32 x = sign_x_to_s32(10, (jx + (lr ? jp : -jp))); // It may actually be 9, TODO? + + if(x >= -7 && x < 384) // Make sure we always keep the pitch of our 384x8 buffer large enough(with padding before and after the visible space) + { + uint8 *target = &fb[lr][x]; + + if(oam_ptr[3] & 0x2000) + { + target += 7; + + for(int meow = 8; meow; meow--) + { + if(pixels & 3) + *target = JPLT_Cache[palette_selector][pixels & 3]; + target--; + pixels >>= 2; + } + } + else + { + for(int meow = 8; meow; meow--) + { + if(pixels & 3) + *target = JPLT_Cache[palette_selector][pixels & 3]; + target++; + pixels >>= 2; + } + } + #if 0 + if(oam_ptr[3] & 0x2000) + { + if((pixels >> 14) & 3) fb[lr][0 + x] = JPLT_Cache[palette_selector][(pixels >> 14) & 3]; + if((pixels >> 12) & 3) fb[lr][1 + x] = JPLT_Cache[palette_selector][(pixels >> 12) & 3]; + if((pixels >> 10) & 3) fb[lr][2 + x] = JPLT_Cache[palette_selector][(pixels >> 10) & 3]; + if((pixels >> 8) & 3) fb[lr][3 + x] = JPLT_Cache[palette_selector][(pixels >> 8) & 3]; + if((pixels >> 6) & 3) fb[lr][4 + x] = JPLT_Cache[palette_selector][(pixels >> 6) & 3]; + if((pixels >> 4) & 3) fb[lr][5 + x] = JPLT_Cache[palette_selector][(pixels >> 4) & 3]; + if((pixels >> 2) & 3) fb[lr][6 + x] = JPLT_Cache[palette_selector][(pixels >> 2) & 3]; + if((pixels >> 0) & 3) fb[lr][7 + x] = JPLT_Cache[palette_selector][(pixels >> 0) & 3]; + } + else + { + if((pixels >> 0) & 3) fb[lr][0 + x] = JPLT_Cache[palette_selector][(pixels >> 0) & 3]; + if((pixels >> 2) & 3) fb[lr][1 + x] = JPLT_Cache[palette_selector][(pixels >> 2) & 3]; + if((pixels >> 4) & 3) fb[lr][2 + x] = JPLT_Cache[palette_selector][(pixels >> 4) & 3]; + if((pixels >> 6) & 3) fb[lr][3 + x] = JPLT_Cache[palette_selector][(pixels >> 6) & 3]; + if((pixels >> 8) & 3) fb[lr][4 + x] = JPLT_Cache[palette_selector][(pixels >> 8) & 3]; + if((pixels >> 10) & 3) fb[lr][5 + x] = JPLT_Cache[palette_selector][(pixels >> 10) & 3]; + if((pixels >> 12) & 3) fb[lr][6 + x] = JPLT_Cache[palette_selector][(pixels >> 12) & 3]; + if((pixels >> 14) & 3) fb[lr][7 + x] = JPLT_Cache[palette_selector][(pixels >> 14) & 3]; + } +#endif + + } + + } + } while( (oam = (oam - 1) & 1023) != end_oam); + +} + + +void VIP_DrawBlock(uint8 block_no, uint8 *fb_l, uint8 *fb_r) +{ + for(int y = 0; y < 8; y++) + { + memset(fb_l + y * 512, BKCOL, 384); + memset(fb_r + y * 512, BKCOL, 384); + } + + obj_search_which = 3; + + for(int world = 31; world >= 0; world--) + { + const uint16 *world_ptr = &DRAM[(0x1D800 + world * 0x20) >> 1]; + + uint32 bgmap_base = world_ptr[0] & 0xF; + bool end = world_ptr[0] & 0x40; + bool over = world_ptr[0] & 0x80; + uint32 scy = (world_ptr[0] >> 8) & 3; + uint32 scx = (world_ptr[0] >> 10) & 3; + uint32 bgm = (world_ptr[0] >> 12) & 3; + bool lron[2] = { (bool)(world_ptr[0] & 0x8000), (bool)(world_ptr[0] & 0x4000) }; + + uint16 gx = sign_11_to_s16(world_ptr[1]); + uint16 gp = ParallaxDisabled ? 0 : sign_9_to_s16(world_ptr[2]); + uint16 gy = sign_11_to_s16(world_ptr[3]); + uint16 mx = world_ptr[4]; + uint16 mp = ParallaxDisabled ? 0 : sign_9_to_s16(world_ptr[5]); + uint16 my = world_ptr[6]; + uint16 window_width = sign_11_to_s16(world_ptr[7]); + uint16 window_height = (world_ptr[8] & 0x3FF); + uint32 param_base = (world_ptr[9] & 0xFFF0); + uint16 overplane_char = world_ptr[10]; + + if(end) + break; + + if(((512 << scx) + (512 << scy)) > 4096) + { + printf("BG Size too large for world: %d(scx=%d, scy=%d)\n", world, scx, scy); + } + +// if(world != 2) +// continue; + + // if(block_no == 8) + // printf("World: %d; gx: %d, gp: %d, gy: %d, mx: %d, mp: %d, my: %d, window_width: %d, window_height: %d\n", world, gx, gp, gy, mx, mp, my, window_width, window_height); + + for(int y = 0; y < 8; y++) + { + uint8 *fb[2] = { &fb_l[y * 512], &fb_r[y * 512] }; + + if(bgm == BGM_OBJ) + { + if(!lron[0] || !lron[1]) + printf("Bad OBJ World? %d(%d/%d) %d~%d\n", world, lron[0], lron[1], SPT[obj_search_which], obj_search_which ? (SPT[obj_search_which - 1] + 1) : 0); + + DrawOBJ(fb, (block_no * 8) + y, lron); + } + else if(bgm == BGM_AFFINE) + { + //if(((block_no * 8) + y) == 128) + // printf("Draw affine: %d %d\n", gx, gp); + for(int lr = 0; lr < 2; lr++) + { + if(lron[lr]) + { + DrawAffine(fb[lr], (block_no * 8) + y, lr, param_base, bgmap_base * 4096, over, overplane_char, scx, scy, + gx + (lr ? gp : -gp), gy, window_width, window_height); + } + } + } + else + for(int lr = 0; lr < 2; lr++) + { + uint16 srcX, srcY; + uint16 RealY = (block_no * 8) + y; + uint16 DestX; + uint16 DestY; + + srcX = mx + (lr ? mp : -mp); + srcY = my + (RealY - gy); + + DestX = gx + (lr ? gp : -gp); + DestY = gy; + + if(lron[lr]) + { + if(bgm == 1) // HBias + srcX += (int16)DRAM[(param_base + (((RealY - DestY) * 2) | lr)) & 0xFFFF]; + + DrawBG(fb[lr], RealY, lr, bgmap_base, over, overplane_char, (int32)(int16)srcX, (int32)(int16)srcY, scx, scy, DestX, DestY, window_width, window_height); + } + } + } + + if(bgm == BGM_OBJ) + if(obj_search_which) + obj_search_which--; + + } + + +} diff --git a/mednafen/vb-09333/vsu.cpp b/mednafen/vb-09333/vsu.cpp new file mode 100644 index 0000000..2dd47fd --- /dev/null +++ b/mednafen/vb-09333/vsu.cpp @@ -0,0 +1,524 @@ +/* Mednafen - Multi-system Emulator + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "vb.h" +#include "vsu.h" + +static const unsigned int Tap_LUT[8] = { 15 - 1, 11 - 1, 14 - 1, 5 - 1, 9 - 1, 7 - 1, 10 - 1, 12 - 1 }; + +VSU::VSU(Blip_Buffer *bb_l, Blip_Buffer *bb_r) +{ + sbuf[0] = bb_l; + sbuf[1] = bb_r; + + Synth.volume(1.0 / 6 / 2); + + for(int ch = 0; ch < 6; ch++) + { + for(int lr = 0; lr < 2; lr++) + last_output[ch][lr] = 0; + } +} + +VSU::~VSU() +{ + +} + +void VSU::Power(void) +{ + SweepControl = 0; + SweepModCounter = 0; + SweepModClockDivider = 1; + + for(int ch = 0; ch < 6; ch++) + { + IntlControl[ch] = 0; + LeftLevel[ch] = 0; + RightLevel[ch] = 0; + Frequency[ch] = 0; + EnvControl[ch] = 0; + RAMAddress[ch] = 0; + + EffFreq[ch] = 0; + Envelope[ch] = 0; + WavePos[ch] = 0; + FreqCounter[ch] = 0; + IntervalCounter[ch] = 0; + EnvelopeCounter[ch] = 0; + + EffectsClockDivider[ch] = 4800; + IntervalClockDivider[ch] = 4; + EnvelopeClockDivider[ch] = 4; + + LatcherClockDivider[ch] = 120; + } + + + NoiseLatcherClockDivider = 120; + NoiseLatcher = 0; + + memset(WaveData, 0, sizeof(WaveData)); + memset(ModData, 0, sizeof(ModData)); + + last_ts = 0; +} + +void VSU::Write(int32 timestamp, uint32 A, uint8 V) +{ + A &= 0x7FF; + + Update(timestamp); + + //printf("VSU Write: %d, %08x %02x\n", timestamp, A, V); + + if(A < 0x280) + WaveData[A >> 7][(A >> 2) & 0x1F] = V & 0x3F; + else if(A < 0x400) + { + //if(A >= 0x300) + // printf("Modulation mirror write? %08x %02x\n", A, V); + ModData[(A >> 2) & 0x1F] = V; + } + else if(A < 0x600) + { + int ch = (A >> 6) & 0xF; + + //if(ch < 6) + //printf("Ch: %d, Reg: %d, Value: %02x\n", ch, (A >> 2) & 0xF, V); + + if(ch > 5) + { + if(A == 0x580 && (V & 1)) + { + //puts("STOP, HAMMER TIME"); + for(int i = 0; i < 6; i++) + IntlControl[i] &= ~0x80; + } + } + else + switch((A >> 2) & 0xF) + { + case 0x0: IntlControl[ch] = V & ~0x40; + + if(V & 0x80) + { + EffFreq[ch] = Frequency[ch]; + if(ch == 5) + FreqCounter[ch] = 10 * (2048 - EffFreq[ch]); + else + FreqCounter[ch] = 2048 - EffFreq[ch]; + IntervalCounter[ch] = (V & 0x1F) + 1; + EnvelopeCounter[ch] = (EnvControl[ch] & 0x7) + 1; + + if(ch == 4) + { + SweepModCounter = (SweepControl >> 4) & 7; + SweepModClockDivider = (SweepControl & 0x80) ? 8 : 1; + ModWavePos = 0; + } + + WavePos[ch] = 0; + + if(ch == 5) // Not sure if this is correct. + lfsr = 1; + + //if(!(IntlControl[ch] & 0x80)) + // Envelope[ch] = (EnvControl[ch] >> 4) & 0xF; + + EffectsClockDivider[ch] = 4800; + IntervalClockDivider[ch] = 4; + EnvelopeClockDivider[ch] = 4; + } + break; + + case 0x1: LeftLevel[ch] = (V >> 4) & 0xF; + RightLevel[ch] = (V >> 0) & 0xF; + break; + + case 0x2: Frequency[ch] &= 0xFF00; + Frequency[ch] |= V << 0; + EffFreq[ch] &= 0xFF00; + EffFreq[ch] |= V << 0; + break; + + case 0x3: Frequency[ch] &= 0x00FF; + Frequency[ch] |= (V & 0x7) << 8; + EffFreq[ch] &= 0x00FF; + EffFreq[ch] |= (V & 0x7) << 8; + break; + + case 0x4: EnvControl[ch] &= 0xFF00; + EnvControl[ch] |= V << 0; + + Envelope[ch] = (V >> 4) & 0xF; + break; + + case 0x5: EnvControl[ch] &= 0x00FF; + if(ch == 4) + EnvControl[ch] |= (V & 0x73) << 8; + else if(ch == 5) + { + EnvControl[ch] |= (V & 0x73) << 8; + lfsr = 1; + } + else + EnvControl[ch] |= (V & 0x03) << 8; + break; + + case 0x6: RAMAddress[ch] = V & 0xF; + break; + + case 0x7: if(ch == 4) + { + SweepControl = V; + } + break; + } + } +} + +INLINE void VSU::CalcCurrentOutput(int ch, int &left, int &right) +{ + if(!(IntlControl[ch] & 0x80)) + { + left = right = 0; + return; + } + + int WD; + int l_ol, r_ol; + + if(ch == 5) + WD = NoiseLatcher; //(NoiseLatcher << 6) - NoiseLatcher; + else + { + if(RAMAddress[ch] > 4) + WD = 0; + else + WD = WaveData[RAMAddress[ch]][WavePos[ch]]; // - 0x20; + } + l_ol = Envelope[ch] * LeftLevel[ch]; + if(l_ol) + { + l_ol >>= 3; + l_ol += 1; + } + + r_ol = Envelope[ch] * RightLevel[ch]; + if(r_ol) + { + r_ol >>= 3; + r_ol += 1; + } + + left = WD * l_ol; + right = WD * r_ol; +} + +void VSU::Update(int32 timestamp) +{ + //puts("VSU Start"); + int left, right; + + for(int ch = 0; ch < 6; ch++) + { + int32 clocks = timestamp - last_ts; + int32 running_timestamp = last_ts; + + // Output sound here + CalcCurrentOutput(ch, left, right); + Synth.offset_inline(running_timestamp, left - last_output[ch][0], sbuf[0]); + Synth.offset_inline(running_timestamp, right - last_output[ch][1], sbuf[1]); + last_output[ch][0] = left; + last_output[ch][1] = right; + + if(!(IntlControl[ch] & 0x80)) + continue; + + while(clocks > 0) + { + int32 chunk_clocks = clocks; + + if(chunk_clocks > EffectsClockDivider[ch]) + chunk_clocks = EffectsClockDivider[ch]; + + if(ch == 5) + { + if(chunk_clocks > NoiseLatcherClockDivider) + chunk_clocks = NoiseLatcherClockDivider; + } + else + { + if(EffFreq[ch] >= 2040) + { + if(chunk_clocks > LatcherClockDivider[ch]) + chunk_clocks = LatcherClockDivider[ch]; + } + else + { + if(chunk_clocks > FreqCounter[ch]) + chunk_clocks = FreqCounter[ch]; + } + } + + if(ch == 5 && chunk_clocks > NoiseLatcherClockDivider) + chunk_clocks = NoiseLatcherClockDivider; + + FreqCounter[ch] -= chunk_clocks; + while(FreqCounter[ch] <= 0) + { + if(ch == 5) + { + int feedback = ((lfsr >> 7) & 1) ^ ((lfsr >> Tap_LUT[(EnvControl[5] >> 12) & 0x7]) & 1) ^ 1; + lfsr = ((lfsr << 1) & 0x7FFF) | feedback; + + FreqCounter[ch] += 10 * (2048 - EffFreq[ch]); + } + else + { + FreqCounter[ch] += 2048 - EffFreq[ch]; + WavePos[ch] = (WavePos[ch] + 1) & 0x1F; + } + } + + LatcherClockDivider[ch] -= chunk_clocks; + while(LatcherClockDivider[ch] <= 0) + LatcherClockDivider[ch] += 120; + + if(ch == 5) + { + NoiseLatcherClockDivider -= chunk_clocks; + if(!NoiseLatcherClockDivider) + { + NoiseLatcherClockDivider = 120; + NoiseLatcher = ((lfsr & 1) << 6) - (lfsr & 1); + } + } + + EffectsClockDivider[ch] -= chunk_clocks; + while(EffectsClockDivider[ch] <= 0) + { + EffectsClockDivider[ch] += 4800; + + IntervalClockDivider[ch]--; + while(IntervalClockDivider[ch] <= 0) + { + IntervalClockDivider[ch] += 4; + + if(IntlControl[ch] & 0x20) + { + IntervalCounter[ch]--; + if(!IntervalCounter[ch]) + { + IntlControl[ch] &= ~0x80; + } + } + + EnvelopeClockDivider[ch]--; + while(EnvelopeClockDivider[ch] <= 0) + { + EnvelopeClockDivider[ch] += 4; + + if(EnvControl[ch] & 0x0100) // Enveloping enabled? + { + EnvelopeCounter[ch]--; + if(!EnvelopeCounter[ch]) + { + EnvelopeCounter[ch] = (EnvControl[ch] & 0x7) + 1; + + if(EnvControl[ch] & 0x0008) // Grow + { + if(Envelope[ch] < 0xF || (EnvControl[ch] & 0x200)) + Envelope[ch] = (Envelope[ch] + 1) & 0xF; + } + else // Decay + { + if(Envelope[ch] > 0 || (EnvControl[ch] & 0x200)) + Envelope[ch] = (Envelope[ch] - 1) & 0xF; + } + } + } + + } // end while(EnvelopeClockDivider[ch] <= 0) + } // end while(IntervalClockDivider[ch] <= 0) + + if(ch == 4) + { + SweepModClockDivider--; + while(SweepModClockDivider <= 0) + { + SweepModClockDivider += (SweepControl & 0x80) ? 8 : 1; + + if(((SweepControl >> 4) & 0x7) && (EnvControl[ch] & 0x4000)) + { + if(SweepModCounter) + SweepModCounter--; + + if(!SweepModCounter) + { + SweepModCounter = (SweepControl >> 4) & 0x7; + + if(EnvControl[ch] & 0x1000) // Modulation + { + if(ModWavePos < 32 || (EnvControl[ch] & 0x2000)) + { + ModWavePos &= 0x1F; + + EffFreq[ch] = (EffFreq[ch] + (int8)ModData[ModWavePos]); + if(EffFreq[ch] < 0) + { + //puts("Underflow"); + EffFreq[ch] = 0; + } + else if(EffFreq[ch] > 0x7FF) + { + //puts("Overflow"); + EffFreq[ch] = 0x7FF; + } + ModWavePos++; + } + //puts("Mod"); + } + else // Sweep + { + int32 delta = EffFreq[ch] >> (SweepControl & 0x7); + int32 NewFreq = EffFreq[ch] + ((SweepControl & 0x8) ? delta : -delta); + + //printf("Sweep(%d): Old: %d, New: %d\n", ch, EffFreq[ch], NewFreq); + + if(NewFreq < 0) + EffFreq[ch] = 0; + else if(NewFreq > 0x7FF) + { + //EffFreq[ch] = 0x7FF; + IntlControl[ch] &= ~0x80; + } + else + EffFreq[ch] = NewFreq; + } + } + } + } // end while(SweepModClockDivider <= 0) + } // end if(ch == 4) + } // end while(EffectsClockDivider[ch] <= 0) + clocks -= chunk_clocks; + running_timestamp += chunk_clocks; + + // Output sound here too. + CalcCurrentOutput(ch, left, right); + Synth.offset_inline(running_timestamp, left - last_output[ch][0], sbuf[0]); + Synth.offset_inline(running_timestamp, right - last_output[ch][1], sbuf[1]); + last_output[ch][0] = left; + last_output[ch][1] = right; + } + } + last_ts = timestamp; + //puts("VSU End"); +} + +void VSU::EndFrame(int32 timestamp) +{ + Update(timestamp); + last_ts = 0; +} + +int VSU::StateAction(StateMem *sm, int load, int data_only) +{ + SFORMAT StateRegs[] = + { + SFARRAY(IntlControl, 6), + SFARRAY(LeftLevel, 6), + SFARRAY(RightLevel, 6), + + SFARRAY16(Frequency, 6), + SFARRAY16(EnvControl, 6), + SFARRAY(RAMAddress, 6), + SFVAR(SweepControl), + + SFARRAY(&WaveData[0][0], 5 * 0x20), + SFARRAY(ModData, 0x20), + + SFARRAY32(EffFreq, 6), + SFARRAY32(Envelope, 6), + + SFARRAY32(WavePos, 6), + + SFVAR(ModWavePos), + + SFARRAY32(LatcherClockDivider, 6), + SFARRAY32(FreqCounter, 6), + SFARRAY32(IntervalCounter, 6), + SFARRAY32(EnvelopeCounter, 6), + + SFVAR(SweepModCounter), + + SFARRAY32(EffectsClockDivider, 6), + SFARRAY32(IntervalClockDivider, 6), + SFARRAY32(EnvelopeClockDivider, 6), + + SFVAR(SweepModClockDivider), + + SFVAR(NoiseLatcherClockDivider), + SFVAR(NoiseLatcher), + SFVAR(lfsr), + SFEND + }; + + int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "VSU"); + + + if(load) + { + + } + + return(ret); +} + + + +uint8 VSU::PeekWave(const unsigned int which, uint32 Address) +{ + assert(which <= 4); + + Address &= 0x1F; + + return(WaveData[which][Address]); +} + +void VSU::PokeWave(const unsigned int which, uint32 Address, uint8 value) +{ + assert(which <= 4); + + Address &= 0x1F; + + WaveData[which][Address] = value & 0x3F; +} + +uint8 VSU::PeekModWave(uint32 Address) +{ + Address &= 0x1F; + return(ModData[Address]); +} + +void VSU::PokeModWave(uint32 Address, uint8 value) +{ + Address &= 0x1F; + + ModData[Address] = value & 0xFF; +} diff --git a/mednafen/vb-09333/vsu.h b/mednafen/vb-09333/vsu.h new file mode 100644 index 0000000..4a3d7ff --- /dev/null +++ b/mednafen/vb-09333/vsu.h @@ -0,0 +1,81 @@ +#ifndef __VB_VSU_H +#define __VB_VSU_H + +#include + +class VSU +{ + public: + + VSU(Blip_Buffer *bb_l, Blip_Buffer *bb_r) MDFN_COLD; + ~VSU() MDFN_COLD; + + void Power(void) MDFN_COLD; + + void Write(int32 timestamp, uint32 A, uint8 V); + + void EndFrame(int32 timestamp); + + int StateAction(StateMem *sm, int load, int data_only); + + uint8 PeekWave(const unsigned int which, uint32 Address); + void PokeWave(const unsigned int which, uint32 Address, uint8 value); + + uint8 PeekModWave(uint32 Address); + void PokeModWave(uint32 Address, uint8 value); + + private: + + void CalcCurrentOutput(int ch, int &left, int &right); + + void Update(int32 timestamp); + + uint8 IntlControl[6]; + uint8 LeftLevel[6]; + uint8 RightLevel[6]; + uint16 Frequency[6]; + uint16 EnvControl[6]; // Channel 5/6 extra functionality tacked on too. + + uint8 RAMAddress[6]; + + uint8 SweepControl; + + uint8 WaveData[5][0x20]; + + uint8 ModData[0x20]; + + // + // + // + int32 EffFreq[6]; + int32 Envelope[6]; + + int32 WavePos[6]; + int32 ModWavePos; + + int32 LatcherClockDivider[6]; + + int32 FreqCounter[6]; + int32 IntervalCounter[6]; + int32 EnvelopeCounter[6]; + int32 SweepModCounter; + + int32 EffectsClockDivider[6]; + int32 IntervalClockDivider[6]; + int32 EnvelopeClockDivider[6]; + int32 SweepModClockDivider; + + int32 NoiseLatcherClockDivider; + uint32 NoiseLatcher; + + uint32 lfsr; + + int32 last_output[6][2]; + int32 last_ts; + + Blip_Buffer *sbuf[2]; + Blip_Synth Synth; + Blip_Synth NoiseSynth; +}; + +#endif