mirror of
https://github.com/libretro/beetle-pcfx-libretro.git
synced 2024-11-27 10:20:21 +00:00
Update to 0.9.24.
This commit is contained in:
parent
03fcaf14d4
commit
44d7a687ef
2
Makefile
2
Makefile
@ -154,7 +154,7 @@ WARNINGS := -Wall \
|
||||
-Wno-overflow
|
||||
|
||||
FLAGS += $(ENDIANNESS_DEFINES) -DSIZEOF_DOUBLE=8 $(WARNINGS) \
|
||||
-DMEDNAFEN_VERSION=\"0.9.22\" -DMEDNAFEN_VERSION_NUMERIC=922 -DPSS_STYLE=1 -DMPC_FIXED_POINT -DARCH_X86 \
|
||||
-DMEDNAFEN_VERSION=\"0.9.24\" -DPACKAGE=\"mednafen\" -DMEDNAFEN_VERSION_NUMERIC=924 -DPSS_STYLE=1 -DMPC_FIXED_POINT -DARCH_X86 \
|
||||
-DWANT_PSX_EMU -DSTDC_HEADERS
|
||||
|
||||
CXXFLAGS += $(FLAGS)
|
||||
|
@ -54,7 +54,6 @@ static int16 CDDABuffer[588 * 2];
|
||||
static int16 ResampBuffer[588 * 2][2]; // Resampler input buffer, * 2 for resampler leftovers
|
||||
static uint32 ResampBufferPos;
|
||||
static uint32 PrevRate;
|
||||
static unsigned int CurrentDisc;
|
||||
|
||||
static std::vector<CDIF *> *cdifs;
|
||||
|
||||
@ -541,6 +540,7 @@ MDFNGI EmulatedCDPlay =
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
NULL, //StateAction,
|
||||
Emulate,
|
||||
SetInput,
|
||||
|
@ -36,6 +36,15 @@ MDFN_Error::MDFN_Error(int errno_code_new, const char *format, ...) throw()
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
MDFN_Error::MDFN_Error(const ErrnoHolder &enh)
|
||||
{
|
||||
errno_code = enh.Errno();
|
||||
|
||||
error_message = trio_aprintf("%s", enh.StrError());
|
||||
}
|
||||
|
||||
|
||||
MDFN_Error::~MDFN_Error() throw()
|
||||
{
|
||||
if(error_message)
|
||||
@ -78,7 +87,7 @@ const char * MDFN_Error::what(void) const throw()
|
||||
return(error_message);
|
||||
}
|
||||
|
||||
int MDFN_Error::GetErrno(void) throw()
|
||||
int MDFN_Error::GetErrno(void) const throw()
|
||||
{
|
||||
return(errno_code);
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <exception>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
class ErrnoHolder;
|
||||
class MDFN_Error : public std::exception
|
||||
{
|
||||
public:
|
||||
@ -13,6 +15,7 @@ class MDFN_Error : public std::exception
|
||||
MDFN_Error() throw();
|
||||
|
||||
MDFN_Error(int errno_code_new, const char *format, ...) throw();
|
||||
MDFN_Error(const ErrnoHolder &enh);
|
||||
|
||||
~MDFN_Error() throw();
|
||||
|
||||
@ -20,7 +23,7 @@ class MDFN_Error : public std::exception
|
||||
MDFN_Error & operator=(const MDFN_Error &ze_error) throw();
|
||||
|
||||
virtual const char *what(void) const throw();
|
||||
int GetErrno(void) throw();
|
||||
int GetErrno(void) const throw();
|
||||
|
||||
private:
|
||||
|
||||
@ -44,12 +47,12 @@ class ErrnoHolder
|
||||
SetErrno(the_errno);
|
||||
}
|
||||
|
||||
inline int Errno(void)
|
||||
inline int Errno(void) const
|
||||
{
|
||||
return(local_errno);
|
||||
}
|
||||
|
||||
const char *StrError(void)
|
||||
const char *StrError(void) const
|
||||
{
|
||||
return(local_strerror);
|
||||
}
|
||||
|
@ -312,6 +312,7 @@ typedef struct
|
||||
void (*RemoveReadPatches)(void);
|
||||
uint8 (*MemRead)(uint32 addr);
|
||||
|
||||
bool SaveStateAltersState; // true for bsnes and some libco-style emulators, false otherwise.
|
||||
// Main save state routine, called by the save state code in state.cpp.
|
||||
// When saving, load is set to 0. When loading, load is set to the version field of the save state being loaded.
|
||||
// data_only is true when the save state data is temporary, such as being saved into memory for state rewinding.
|
||||
|
@ -102,10 +102,10 @@ static INLINE void StoreU32_LE(uint32 *a, const uint32 v)
|
||||
//
|
||||
// pre_padding and post_padding are specified in units of sizeof(max_unit_type).
|
||||
//
|
||||
template<unsigned size, typename max_unit_type, bool big_endian, unsigned pre_padding_count, unsigned post_padding_count>
|
||||
template<unsigned size, typename max_unit_type, bool big_endian> //, unsigned pre_padding_count, unsigned post_padding_count>
|
||||
struct MultiAccessSizeMem
|
||||
{
|
||||
max_unit_type pre_padding[pre_padding_count];
|
||||
//max_unit_type pre_padding[pre_padding_count ? pre_padding_count : 1];
|
||||
|
||||
union
|
||||
{
|
||||
@ -114,7 +114,7 @@ struct MultiAccessSizeMem
|
||||
uint32 data32[size / sizeof(uint32)];
|
||||
};
|
||||
|
||||
max_unit_type post_padding[post_padding_count];
|
||||
//max_unit_type post_padding[post_padding_count ? post_padding_count : 1];
|
||||
|
||||
INLINE uint8 ReadU8(uint32 address)
|
||||
{
|
||||
|
@ -1,7 +1,23 @@
|
||||
#ifndef __MDFN_MATH_OPS_H
|
||||
#define __MDFN_MATH_OPS_H
|
||||
|
||||
uint32 round_up_pow2(uint32 v);
|
||||
// Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
|
||||
// Rounds up to the nearest power of 2.
|
||||
static INLINE uint64 round_up_pow2(uint64 v)
|
||||
{
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v |= v >> 32;
|
||||
v++;
|
||||
|
||||
v += (v == 0);
|
||||
|
||||
return(v);
|
||||
}
|
||||
|
||||
static INLINE uint32 uilog2(uint32 v)
|
||||
{
|
||||
@ -38,7 +54,4 @@ static INLINE uint32 uilog2(uint32 v)
|
||||
// convert those faster with typecasts...
|
||||
#define sign_x_to_s32(_bits, _value) (((int32)((uint32)(_value) << (32 - _bits))) >> (32 - _bits))
|
||||
|
||||
|
||||
#define INT16_TO_BCD(A) ((((((A) % 100) / 10) * 16 + ((A) % 10))) | (((((((A) / 100) % 100) / 10) * 16 + (((A) / 100) % 10))) << 8)) // convert INT16 --> BCD
|
||||
|
||||
#endif
|
||||
|
@ -77,7 +77,7 @@ int MDFNI_Initialize(const char *basedir, const std::vector<MDFNSetting> &Driver
|
||||
void MDFNI_SetBaseDirectory(const char *dir);
|
||||
|
||||
/* Call only when a game is loaded. */
|
||||
int MDFNI_NetplayStart(uint32 local_players, uint32 netmerge, const std::string &nickname, const std::string &game_key, const std::string &connect_password);
|
||||
int MDFNI_NetplayStart(uint32 local_players, const std::string &nickname, const std::string &game_key, const std::string &connect_password);
|
||||
|
||||
/* Emulates a frame. */
|
||||
void MDFNI_Emulate(EmulateSpecStruct *espec);
|
||||
|
@ -138,7 +138,6 @@ static MDFNSetting RenamedSettings[] =
|
||||
{ "netlocalplayers", MDFNSF_NOFLAGS, NULL, NULL, MDFNST_ALIAS , "netplay.localplayers" },
|
||||
{ "netnick", MDFNSF_NOFLAGS, NULL, NULL, MDFNST_ALIAS , "netplay.nick" },
|
||||
{ "netgamekey", MDFNSF_NOFLAGS, NULL, NULL, MDFNST_ALIAS , "netplay.gamekey" },
|
||||
{ "netmerge", MDFNSF_NOFLAGS, NULL, NULL, MDFNST_ALIAS , "netplay.merge" },
|
||||
{ "netsmallfont", MDFNSF_NOFLAGS, NULL, NULL, MDFNST_ALIAS , "netplay.smallfont" },
|
||||
|
||||
{ "frameskip", MDFNSF_NOFLAGS, NULL, NULL, MDFNST_ALIAS , "video.frameskip" },
|
||||
@ -295,9 +294,9 @@ void MDFNI_CloseGame(void)
|
||||
memset(PortDeviceCache, 0, sizeof(PortDeviceCache));
|
||||
}
|
||||
|
||||
int MDFNI_NetplayStart(uint32 local_players, uint32 netmerge, const std::string &nickname, const std::string &game_key, const std::string &connect_password)
|
||||
int MDFNI_NetplayStart(uint32 local_players, const std::string &nickname, const std::string &game_key, const std::string &connect_password)
|
||||
{
|
||||
return(NetplayStart((const char**)PortDeviceCache, PortDataLenCache, local_players, netmerge, nickname, game_key, connect_password));
|
||||
return(NetplayStart((const char**)PortDeviceCache, PortDataLenCache, local_players, nickname, game_key, connect_password));
|
||||
}
|
||||
|
||||
|
||||
@ -1054,7 +1053,6 @@ int MDFNI_Initialize(const char *basedir, const std::vector<MDFNSetting> &Driver
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
memset(PortDataCache, 0, sizeof(PortDataCache));
|
||||
memset(PortDataLenCache, 0, sizeof(PortDataLenCache));
|
||||
memset(PortDeviceCache, 0, sizeof(PortDeviceCache));
|
||||
@ -1070,9 +1068,9 @@ int MDFNI_Initialize(const char *basedir, const std::vector<MDFNSetting> &Driver
|
||||
{
|
||||
MDFNSetting setting;
|
||||
const char *sysname;
|
||||
|
||||
|
||||
sysname = (const char *)MDFNSystems[i]->shortname;
|
||||
|
||||
|
||||
if(!MDFNSystems[i]->soundchan)
|
||||
printf("0 sound channels for %s????\n", sysname);
|
||||
|
||||
@ -1095,14 +1093,13 @@ int MDFNI_Initialize(const char *basedir, const std::vector<MDFNSetting> &Driver
|
||||
dynamic_settings.push_back(setting);
|
||||
}
|
||||
|
||||
if(DriverSettings.size())
|
||||
MDFN_MergeSettings(DriverSettings);
|
||||
|
||||
// First merge all settable settings, then load the settings from the SETTINGS FILE OF DOOOOM
|
||||
MDFN_MergeSettings(MednafenSettings);
|
||||
MDFN_MergeSettings(dynamic_settings);
|
||||
MDFN_MergeSettings(MDFNMP_Settings);
|
||||
|
||||
if(DriverSettings.size())
|
||||
MDFN_MergeSettings(DriverSettings);
|
||||
|
||||
for(unsigned int x = 0; x < MDFNSystems.size(); x++)
|
||||
{
|
||||
@ -1306,6 +1303,12 @@ void MDFNI_Emulate(EmulateSpecStruct *espec)
|
||||
multiplier_save = 1;
|
||||
volume_save = 1;
|
||||
|
||||
// Initialize some espec member data to zero, to catch some types of bugs.
|
||||
espec->DisplayRect.x = 0;
|
||||
espec->DisplayRect.w = 0;
|
||||
espec->DisplayRect.y = 0;
|
||||
espec->DisplayRect.h = 0;
|
||||
|
||||
assert((bool)(espec->SoundBuf != NULL) == (bool)espec->SoundRate && (bool)espec->SoundRate == (bool)espec->SoundBufMaxSize);
|
||||
|
||||
espec->SoundBufSize = 0;
|
||||
@ -1359,12 +1362,12 @@ void MDFNI_Emulate(EmulateSpecStruct *espec)
|
||||
if(MDFNMOV_IsPlaying())
|
||||
{
|
||||
espec->NeedRewind = 0;
|
||||
MDFN_DispMessage(_("Can't rewind during movie playback(yet!)."));
|
||||
MDFN_DispMessage(_("Can't rewind during movie playback."));
|
||||
}
|
||||
else if(MDFNnetplay)
|
||||
{
|
||||
espec->NeedRewind = 0;
|
||||
MDFN_DispMessage(_("Silly-billy, can't rewind during netplay."));
|
||||
MDFN_DispMessage(_("Can't rewind during netplay."));
|
||||
}
|
||||
else if(MDFNGameInfo->GameType == GMT_PLAYER)
|
||||
{
|
||||
@ -1373,10 +1376,30 @@ void MDFNI_Emulate(EmulateSpecStruct *espec)
|
||||
}
|
||||
}
|
||||
|
||||
espec->NeedSoundReverse = MDFN_StateEvil(espec->NeedRewind);
|
||||
// Don't even save states with state rewinding if netplay is enabled, it will degrade netplay performance, and can cause
|
||||
// desynchs with some emulation(IE SNES based on bsnes).
|
||||
|
||||
if(MDFNnetplay)
|
||||
espec->NeedSoundReverse = false;
|
||||
else
|
||||
espec->NeedSoundReverse = MDFN_StateEvil(espec->NeedRewind);
|
||||
|
||||
MDFNGameInfo->Emulate(espec);
|
||||
|
||||
//
|
||||
// Sanity checks
|
||||
//
|
||||
if(!espec->skip)
|
||||
{
|
||||
if(espec->DisplayRect.h == 0)
|
||||
{
|
||||
fprintf(stderr, "espec->DisplayRect.h == 0\n");
|
||||
}
|
||||
}
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
if(espec->InterlaceOn)
|
||||
{
|
||||
if(!PrevInterlaced)
|
||||
@ -1556,7 +1579,7 @@ void MDFN_DoSimpleCommand(int cmd)
|
||||
void MDFN_QSimpleCommand(int cmd)
|
||||
{
|
||||
if(MDFNnetplay)
|
||||
MDFNNET_SendCommand(cmd, 0);
|
||||
NetplaySendCommand(cmd, 0);
|
||||
else
|
||||
{
|
||||
if(!MDFNMOV_IsPlaying())
|
||||
|
@ -37,7 +37,7 @@ static inline void MDFN_FastU32MemsetM8(uint32_t *array, uint32_t value_32, unsi
|
||||
|
||||
#else
|
||||
|
||||
for(uint32_t *ai = array; ai < array + u32len; ai += 2)
|
||||
for(uint32 *ai = array; ai < array + u32len; ai += 2)
|
||||
{
|
||||
ai[0] = value_32;
|
||||
ai[1] = value_32;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <trio/trio.h>
|
||||
|
||||
#include "driver.h"
|
||||
#include "state.h"
|
||||
@ -75,6 +76,17 @@ void MDFNI_SaveMovie(char *fname, const MDFN_Surface *surface, const MDFN_Rect *
|
||||
{
|
||||
gzFile fp;
|
||||
|
||||
if(!MDFNGameInfo->StateAction)
|
||||
return;
|
||||
|
||||
if(MDFNnetplay && (MDFNGameInfo->SaveStateAltersState == true))
|
||||
{
|
||||
char sb[256];
|
||||
trio_snprintf(sb, sizeof(sb), _("Module %s is not compatible with manual movie save starting/stopping during netplay."), MDFNGameInfo->shortname);
|
||||
MDFND_NetplayText((const uint8*)sb, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if(current < 0) /* Can't interrupt playback.*/
|
||||
return;
|
||||
|
||||
|
@ -9,9 +9,8 @@ void MDFNI_NetplayStop(void);
|
||||
MDFND_RecvData().
|
||||
*/
|
||||
|
||||
/* Return 0 on failure, 1 on success. */
|
||||
int MDFND_SendData(const void *data, uint32 len);
|
||||
int MDFND_RecvData(void *data, uint32 len);
|
||||
void MDFND_SendData(const void *data, uint32 len); // thrown std::exception will be handled
|
||||
void MDFND_RecvData(void *data, uint32 len); // thrown std::exception will be handled
|
||||
|
||||
/* Display text received over the network. */
|
||||
/* NetEcho will be set to TRUE if the displayed text is a network
|
||||
@ -23,6 +22,14 @@ void MDFND_NetplayText(const uint8 *text, bool NetEcho);
|
||||
void MDFNI_NetplayText(const uint8 *text);
|
||||
|
||||
|
||||
void MDFNI_NetplayQuit(const char *quit_message);
|
||||
void MDFNI_NetplaySwap(uint8 a, uint8 b);
|
||||
void MDFNI_NetplayTake(uint32 mask);
|
||||
void MDFNI_NetplayDrop(uint32 mask);
|
||||
void MDFNI_NetplayDupe(uint32 mask);
|
||||
|
||||
void MDFNI_NetplayList(void);
|
||||
|
||||
/* Starts a process to determine the integrity(synchronization) of all players
|
||||
in the current game session on the server. Outputs result via MDFND_NetplayText()
|
||||
when they are received from the server(not in this function).
|
||||
|
@ -18,6 +18,7 @@
|
||||
// Protocol versions:
|
||||
// 1 - I forgot!
|
||||
// 2 - Added support for more versatile input configurations...somewhat
|
||||
// 3 -
|
||||
|
||||
#include "mednafen.h"
|
||||
|
||||
@ -46,10 +47,6 @@ static uint32 LocalPlayersMask = 0;
|
||||
static uint32 TotalInputStateSize = 0;
|
||||
static uint32 LocalInputStateSize = 0;
|
||||
|
||||
/* NetError should only be called after a MDFND_*Data function returned 0, in the function
|
||||
that called MDFND_*Data, to prevent it from being called twice.
|
||||
*/
|
||||
|
||||
static void NetError(const char *format, ...)
|
||||
{
|
||||
char *temp = NULL;
|
||||
@ -68,6 +65,7 @@ void MDFNI_NetplayStop(void)
|
||||
{
|
||||
if(MDFNnetplay)
|
||||
{
|
||||
Joined = false;
|
||||
MDFNnetplay = 0;
|
||||
MDFN_FlushGameCheats(1); /* Don't save netplay cheats. */
|
||||
MDFN_LoadGameCheats(0); /* Reload our original cheats. */
|
||||
@ -80,72 +78,74 @@ void MDFNI_NetplayStop(void)
|
||||
else puts("Check your code!");
|
||||
}
|
||||
|
||||
int NetplayStart(const char *PortDeviceCache[16], const uint32 PortDataLenCache[16], uint32 local_players, uint32 netmerge, const std::string &nickname, const std::string &game_key, const std::string &connect_password)
|
||||
int NetplayStart(const char *PortDeviceCache[16], const uint32 PortDataLenCache[16], uint32 local_players, const std::string &nickname, const std::string &game_key, const std::string &connect_password)
|
||||
{
|
||||
uint8 *sendbuf;
|
||||
uint32 sblen;
|
||||
std::string controller_types;
|
||||
const char *emu_id = PACKAGE " " MEDNAFEN_VERSION;
|
||||
|
||||
// Concatenate!
|
||||
for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++)
|
||||
controller_types += std::string(PortDeviceCache[x]) + "\n";
|
||||
|
||||
sblen = 4 + 16 + 16 + 64 + 1 + nickname.size() + controller_types.size();
|
||||
sendbuf = (uint8 *)malloc(sblen);
|
||||
memset(sendbuf, 0, sblen);
|
||||
|
||||
MDFN_en32lsb(sendbuf, sblen - 4);
|
||||
if(game_key != "")
|
||||
try
|
||||
{
|
||||
md5_context md5;
|
||||
uint8 md5out[16];
|
||||
sblen = 4 + 16 + 16 + 64 + 1 + nickname.size() + strlen(emu_id);
|
||||
sendbuf = (uint8 *)malloc(sblen);
|
||||
memset(sendbuf, 0, sblen);
|
||||
|
||||
md5.starts();
|
||||
md5.update(MDFNGameInfo->MD5, 16);
|
||||
md5.update((uint8 *)game_key.c_str(), game_key.size());
|
||||
md5.finish(md5out);
|
||||
memcpy(sendbuf + 4, md5out, 16);
|
||||
MDFN_en32lsb(sendbuf, sblen - 4);
|
||||
if(game_key != "")
|
||||
{
|
||||
md5_context md5;
|
||||
uint8 md5out[16];
|
||||
|
||||
md5.starts();
|
||||
md5.update(MDFNGameInfo->MD5, 16);
|
||||
md5.update((uint8 *)game_key.c_str(), game_key.size());
|
||||
md5.finish(md5out);
|
||||
memcpy(sendbuf + 4, md5out, 16);
|
||||
}
|
||||
else
|
||||
memcpy(sendbuf + 4, MDFNGameInfo->MD5, 16);
|
||||
|
||||
if(connect_password != "")
|
||||
{
|
||||
md5_context md5;
|
||||
uint8 md5out[16];
|
||||
|
||||
md5.starts();
|
||||
md5.update((uint8*)connect_password.c_str(), connect_password.size());
|
||||
md5.finish(md5out);
|
||||
memcpy(sendbuf + 4 + 16, md5out, 16);
|
||||
}
|
||||
|
||||
uint8 *extra = sendbuf + 4 + 16 + 16;
|
||||
|
||||
extra[0] = 3; // Protocol version
|
||||
|
||||
// Set input device number thingies here.
|
||||
extra[1] = MDFNGameInfo->InputInfo->InputPorts; // Total number of ports
|
||||
|
||||
// The size of the giganto string with the controller types
|
||||
MDFN_en32lsb(&extra[4], strlen(emu_id));
|
||||
|
||||
// 16-32, controller data sizes
|
||||
for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++)
|
||||
extra[16 + x] = PortDataLenCache[x];
|
||||
|
||||
|
||||
sendbuf[4 + 16 + 16 + 64] = local_players;
|
||||
|
||||
if(nickname != "")
|
||||
memcpy(sendbuf + 4 + 16 + 16 + 64 + 1, nickname.c_str(), nickname.size());
|
||||
|
||||
memcpy(sendbuf + 4 + 16 + 16 + 64 + 1 + nickname.size(), emu_id, strlen(emu_id));
|
||||
|
||||
MDFND_SendData(sendbuf, sblen);
|
||||
}
|
||||
else
|
||||
memcpy(sendbuf + 4, MDFNGameInfo->MD5, 16);
|
||||
|
||||
if(connect_password != "")
|
||||
catch(std::exception &e)
|
||||
{
|
||||
md5_context md5;
|
||||
uint8 md5out[16];
|
||||
|
||||
md5.starts();
|
||||
md5.update((uint8*)connect_password.c_str(), connect_password.size());
|
||||
md5.finish(md5out);
|
||||
memcpy(sendbuf + 4 + 16, md5out, 16);
|
||||
NetError("%s", e.what());
|
||||
return(false);
|
||||
}
|
||||
|
||||
uint8 *extra = sendbuf + 4 + 16 + 16;
|
||||
|
||||
extra[0] = 2; // Protocol version
|
||||
|
||||
// Set input device number thingies here.
|
||||
extra[1] = MDFNGameInfo->InputInfo->InputPorts; // Total number of ports
|
||||
|
||||
// The size of the giganto string with the controller types
|
||||
MDFN_en32lsb(&extra[4], controller_types.size());
|
||||
|
||||
// 16-32, controller data sizes
|
||||
for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++)
|
||||
extra[16 + x] = PortDataLenCache[x];
|
||||
|
||||
|
||||
sendbuf[4 + 16 + 16 + 32] = netmerge;
|
||||
|
||||
sendbuf[4 + 16 + 16 + 64] = local_players;
|
||||
|
||||
if(nickname != "")
|
||||
memcpy(sendbuf + 4 + 16 + 16 + 64 + 1, nickname.c_str(), nickname.size());
|
||||
|
||||
memcpy(sendbuf + 4 + 16 + 16 + 64 + 1 + nickname.size(), controller_types.c_str(), controller_types.size());
|
||||
|
||||
MDFND_SendData(sendbuf, sblen);
|
||||
|
||||
TotalInputStateSize = 0;
|
||||
for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++)
|
||||
TotalInputStateSize += PortDataLenCache[x];
|
||||
@ -169,7 +169,7 @@ int NetplayStart(const char *PortDeviceCache[16], const uint32 PortDataLenCache[
|
||||
return(1);
|
||||
}
|
||||
|
||||
int MDFNNET_SendCommand(uint8 cmd, uint32 len)
|
||||
static void SendCommand(uint8 cmd, uint32 len)
|
||||
{
|
||||
uint8 buf[1 + LocalInputStateSize + 4]; // Command, unused, command length
|
||||
|
||||
@ -177,63 +177,171 @@ int MDFNNET_SendCommand(uint8 cmd, uint32 len)
|
||||
|
||||
buf[0] = cmd;
|
||||
MDFN_en32lsb(&buf[1 + LocalInputStateSize], len);
|
||||
if(!MDFND_SendData(buf,LocalInputStateSize + 1 + 4))
|
||||
{
|
||||
NetError("Could not send command.");
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
MDFND_SendData(buf,LocalInputStateSize + 1 + 4);
|
||||
}
|
||||
|
||||
bool NetplaySendCommand(uint8 cmd, uint32 len)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendCommand(cmd, len);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
return(false);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
void MDFNI_NetplaySwap(uint8 a, uint8 b)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendCommand(MDFNNPCMD_CTRLR_SWAP, (a << 0) | (b << 8));
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MDFNI_NetplayTake(uint32 mask)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendCommand(MDFNNPCMD_CTRLR_TAKE, mask);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MDFNI_NetplayDrop(uint32 mask)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendCommand(MDFNNPCMD_CTRLR_DROP, mask);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MDFNI_NetplayDupe(uint32 mask)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendCommand(MDFNNPCMD_CTRLR_DUPE, mask);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MDFNI_NetplayList(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendCommand(MDFNNPCMD_REQUEST_LIST, 0);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MDFNI_NetplayPing(void)
|
||||
{
|
||||
uint64 now_time;
|
||||
try
|
||||
{
|
||||
uint64 now_time;
|
||||
|
||||
now_time = MDFND_GetTime();
|
||||
now_time = MDFND_GetTime();
|
||||
|
||||
if(!MDFNNET_SendCommand(MDFNNPCMD_ECHO, sizeof(now_time)))
|
||||
return;
|
||||
SendCommand(MDFNNPCMD_ECHO, sizeof(now_time));
|
||||
|
||||
// Endianness doesn't matter, since it will be echoed back only to us.
|
||||
if(!MDFND_SendData(&now_time, sizeof(now_time)))
|
||||
NetError("Could not send echo data.");
|
||||
// Endianness doesn't matter, since it will be echoed back only to us.
|
||||
MDFND_SendData(&now_time, sizeof(now_time));
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MDFNI_NetplayIntegrity(void)
|
||||
{
|
||||
if(!MDFNNET_SendCommand(MDFNNPCMD_INTEGRITY, 0))
|
||||
return;
|
||||
try
|
||||
{
|
||||
SendCommand(MDFNNPCMD_INTEGRITY, 0);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MDFNI_NetplayText(const uint8 *text)
|
||||
{
|
||||
uint32 len;
|
||||
try
|
||||
{
|
||||
uint32 len;
|
||||
|
||||
if(!Joined) return;
|
||||
if(!Joined) return;
|
||||
|
||||
len = strlen((char *)text);
|
||||
len = strlen((char *)text);
|
||||
|
||||
if(!MDFNNET_SendCommand(MDFNNPCMD_TEXT,len)) return;
|
||||
SendCommand(MDFNNPCMD_TEXT, len);
|
||||
|
||||
if(!MDFND_SendData(text,len))
|
||||
NetError("Could not send text data.");
|
||||
MDFND_SendData(text,len);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MDFNI_NetplayChangeNick(UTF8 *newnick)
|
||||
{
|
||||
uint32 len;
|
||||
try
|
||||
{
|
||||
uint32 len;
|
||||
|
||||
if(!Joined) return;
|
||||
if(!Joined) return;
|
||||
|
||||
len = strlen((char *)newnick);
|
||||
len = strlen((char *)newnick);
|
||||
|
||||
if(!MDFNNET_SendCommand(MDFNNPCMD_SETNICK,len)) return;
|
||||
SendCommand(MDFNNPCMD_SETNICK, len);
|
||||
|
||||
if(!MDFND_SendData(newnick, len))
|
||||
NetError("Could not send new nick data.");
|
||||
MDFND_SendData(newnick, len);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
int MDFNNET_SendIntegrity(void)
|
||||
void MDFNI_NetplayQuit(const char *quit_message)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendCommand(MDFNNPCMD_QUIT, strlen(quit_message));
|
||||
MDFND_SendData(quit_message, strlen(quit_message));
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Integrity checking is experimental, and needs work to function properly(in the emulator cores).
|
||||
static int SendIntegrity(void)
|
||||
{
|
||||
StateMem sm;
|
||||
md5_context md5;
|
||||
@ -241,8 +349,11 @@ int MDFNNET_SendIntegrity(void)
|
||||
|
||||
memset(&sm, 0, sizeof(StateMem));
|
||||
|
||||
if(!MDFNSS_SaveSM(&sm, 0, 0))
|
||||
return(0);
|
||||
// Do not do a raw/data-only state for speed, due to lack of endian and bool conversion.
|
||||
if(!MDFNSS_SaveSM(&sm, 0, false))
|
||||
{
|
||||
throw MDFN_Error(0, _("Error during save state generation."));
|
||||
}
|
||||
|
||||
md5.starts();
|
||||
md5.update(sm.data, sm.len);
|
||||
@ -254,122 +365,134 @@ int MDFNNET_SendIntegrity(void)
|
||||
// printf("%02x", digest[i]);
|
||||
//puts("");
|
||||
|
||||
if(!MDFNNET_SendCommand(MDFNNPCMD_INTEGRITY_RES, 16))
|
||||
{
|
||||
NetError(_("Could not send the integrity result to the netplay server."));
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(!MDFND_SendData(digest, 16))
|
||||
{
|
||||
NetError(_("Could not send the integrity result to the netplay server."));
|
||||
return(0);
|
||||
}
|
||||
SendCommand(MDFNNPCMD_INTEGRITY_RES, 16);
|
||||
MDFND_SendData(digest, 16);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int MDFNNET_SendState(void)
|
||||
static void SendState(void)
|
||||
{
|
||||
StateMem sm;
|
||||
uLongf clen;
|
||||
uint8 *cbuf;
|
||||
std::vector<uint8> cbuf;
|
||||
|
||||
memset(&sm, 0, sizeof(StateMem));
|
||||
|
||||
if(!MDFNSS_SaveSM(&sm, 0, 0))
|
||||
return(0);
|
||||
{
|
||||
throw MDFN_Error(0, _("Error during save state generation."));
|
||||
}
|
||||
|
||||
clen = sm.len + sm.len / 1000 + 12;
|
||||
cbuf = (uint8 *)malloc(4 + clen);
|
||||
MDFN_en32lsb(cbuf, sm.len);
|
||||
compress2((Bytef *)cbuf + 4, &clen, (Bytef *)sm.data, sm.len, 7);
|
||||
|
||||
if(!MDFNNET_SendCommand(MDFNNPCMD_LOADSTATE,clen + 4))
|
||||
{
|
||||
free(cbuf);
|
||||
NetError(_("Could not send the save state command to the netplay server."));
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(!MDFND_SendData(cbuf, clen + 4))
|
||||
{
|
||||
NetError(_("Could not send the save state data to the netplay server."));
|
||||
free(cbuf);
|
||||
return(0);
|
||||
}
|
||||
|
||||
cbuf.resize(4 + clen);
|
||||
MDFN_en32lsb(&cbuf[0], sm.len);
|
||||
compress2((Bytef *)&cbuf[0] + 4, &clen, (Bytef *)sm.data, sm.len, 7);
|
||||
free(sm.data);
|
||||
free(cbuf);
|
||||
|
||||
return(1);
|
||||
SendCommand(MDFNNPCMD_LOADSTATE, clen + 4);
|
||||
MDFND_SendData(&cbuf[0], clen + 4);
|
||||
}
|
||||
|
||||
int MDFNNET_RecvState(uint32 clen)
|
||||
static void RecvState(const uint32 clen)
|
||||
{
|
||||
StateMem sm;
|
||||
uint8 *cbuf;
|
||||
std::vector<uint8> cbuf;
|
||||
std::vector<uint8> buf;
|
||||
|
||||
memset(&sm, 0, sizeof(StateMem));
|
||||
|
||||
if(clen > 4000000) // Sanity check
|
||||
if(clen < 4)
|
||||
{
|
||||
NetError("Compressed save state data is too large: %d", clen);
|
||||
return(0);
|
||||
throw MDFN_Error(0, _("Compressed save state data is too small: %u"), clen);
|
||||
}
|
||||
cbuf = (uint8*)malloc(clen);
|
||||
if(!MDFND_RecvData(cbuf, clen))
|
||||
{
|
||||
NetError("Could not receive compressed save state data.");
|
||||
free(cbuf);
|
||||
return(0);
|
||||
}
|
||||
uLongf len = MDFN_de32lsb((uint8 *)cbuf);
|
||||
if(len > 4000000)
|
||||
{
|
||||
NetError("Decompressed save state data is too large: %d", clen);
|
||||
free(cbuf);
|
||||
return(0);
|
||||
}
|
||||
uint8 *buf = (uint8 *)malloc(len);
|
||||
uncompress((Bytef *)buf, &len, (Bytef *)cbuf + 4, clen - 4);
|
||||
|
||||
sm.data = buf;
|
||||
if(clen > 8 * 1024 * 1024) // Compressed length sanity check - 8 MiB max.
|
||||
{
|
||||
throw MDFN_Error(0, _("Compressed save state data is too large: %u"), clen);
|
||||
}
|
||||
|
||||
cbuf.resize(clen);
|
||||
|
||||
MDFND_RecvData(&cbuf[0], clen);
|
||||
|
||||
uLongf len = MDFN_de32lsb(&cbuf[0]);
|
||||
if(len > 12 * 1024 * 1024) // Uncompressed length sanity check - 12 MiB max.
|
||||
{
|
||||
throw MDFN_Error(0, _("Uncompressed save state data is too large: %u"), len);
|
||||
}
|
||||
|
||||
buf.resize(len);
|
||||
|
||||
uncompress((Bytef *)&buf[0], &len, (Bytef *)&cbuf[0] + 4, clen - 4);
|
||||
|
||||
sm.data = &buf[0];
|
||||
sm.len = len;
|
||||
|
||||
if(!MDFNSS_LoadSM(&sm, 0, 0))
|
||||
{
|
||||
NetError("Error during save state loading.");
|
||||
return(0);
|
||||
throw MDFN_Error(0, _("Error during save state loading."));
|
||||
}
|
||||
|
||||
if(MDFNMOV_IsRecording())
|
||||
MDFNMOV_RecordState();
|
||||
return(1);
|
||||
}
|
||||
|
||||
std::string GenerateMPSString(uint8 mps)
|
||||
static std::string GenerateMPSString(uint32 mps, bool ctlr_string = false)
|
||||
{
|
||||
char tmpbuf[256];
|
||||
|
||||
tmpbuf[0] = 0;
|
||||
|
||||
if(!mps)
|
||||
trio_snprintf(tmpbuf, 256, _("a lurker"));
|
||||
{
|
||||
if(!ctlr_string)
|
||||
trio_snprintf(tmpbuf, sizeof(tmpbuf), _("a lurker"));
|
||||
}
|
||||
else
|
||||
trio_snprintf(tmpbuf, 256, _("player(s)%s%s%s%s%s%s%s%s"),
|
||||
(mps & 0x01) ? " 1" : "",
|
||||
(mps & 0x02) ? " 2" : "",
|
||||
(mps & 0x04) ? " 3" : "",
|
||||
(mps & 0x08) ? " 4" : "",
|
||||
(mps & 0x10) ? " 5" : "",
|
||||
(mps & 0x20) ? " 6" : "",
|
||||
(mps & 0x40) ? " 7" : "",
|
||||
(mps & 0x80) ? " 8" : "");
|
||||
trio_snprintf(tmpbuf, sizeof(tmpbuf), ("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"), ctlr_string ? ((mps == round_up_pow2(mps)) ? _("controller") : _("controllers")) : ((mps == round_up_pow2(mps)) ? _("player") : _("players")),
|
||||
(mps & 0x0001) ? " 1" : "",
|
||||
(mps & 0x0002) ? " 2" : "",
|
||||
(mps & 0x0004) ? " 3" : "",
|
||||
(mps & 0x0008) ? " 4" : "",
|
||||
(mps & 0x0010) ? " 5" : "",
|
||||
(mps & 0x0020) ? " 6" : "",
|
||||
(mps & 0x0040) ? " 7" : "",
|
||||
(mps & 0x0080) ? " 8" : "",
|
||||
(mps & 0x0100) ? " 9" : "",
|
||||
(mps & 0x0200) ? " 10" : "",
|
||||
(mps & 0x0400) ? " 11" : "",
|
||||
(mps & 0x0800) ? " 12" : "",
|
||||
(mps & 0x1000) ? " 13" : "",
|
||||
(mps & 0x2000) ? " 14" : "",
|
||||
(mps & 0x4000) ? " 15" : "",
|
||||
(mps & 0x8000) ? " 16" : "");
|
||||
|
||||
|
||||
return(std::string(tmpbuf));
|
||||
}
|
||||
|
||||
void NetplaySendState(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendState();
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[], int NumPorts)
|
||||
{
|
||||
uint8 buf[TotalInputStateSize + 1];
|
||||
|
||||
//
|
||||
//
|
||||
try
|
||||
{
|
||||
if(Joined)
|
||||
{
|
||||
uint8 outgoing_buffer[1 + LocalInputStateSize];
|
||||
@ -381,7 +504,7 @@ void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[],
|
||||
|
||||
int wpos = 1;
|
||||
|
||||
for(int x = 0; x < NumPorts; x++)
|
||||
for(int x = 0; x < NumPorts; x++)
|
||||
{
|
||||
if(LocalPlayersMask & (1 << x))
|
||||
{
|
||||
@ -399,20 +522,12 @@ void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[],
|
||||
|
||||
}
|
||||
}
|
||||
if(!MDFND_SendData(outgoing_buffer, 1 + LocalInputStateSize))
|
||||
{
|
||||
NetError("Sending joystick update data failed.");
|
||||
return;
|
||||
}
|
||||
MDFND_SendData(outgoing_buffer, 1 + LocalInputStateSize);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if(!MDFND_RecvData(buf, TotalInputStateSize + 1))
|
||||
{
|
||||
NetError("Could not receive joystick update data.");
|
||||
return;
|
||||
}
|
||||
MDFND_RecvData(buf, TotalInputStateSize + 1);
|
||||
|
||||
switch(buf[TotalInputStateSize])
|
||||
{
|
||||
@ -421,41 +536,32 @@ void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[],
|
||||
default: MDFN_DoSimpleCommand(buf[TotalInputStateSize]);break;
|
||||
|
||||
case MDFNNPCMD_INTEGRITY:
|
||||
if(!MDFNNET_SendIntegrity())
|
||||
return;
|
||||
|
||||
SendIntegrity();
|
||||
break;
|
||||
|
||||
case MDFNNPCMD_SAVESTATE:
|
||||
if(!MDFNNET_SendState())
|
||||
{
|
||||
return;
|
||||
}
|
||||
case MDFNNPCMD_REQUEST_STATE:
|
||||
SendState();
|
||||
break;
|
||||
|
||||
case MDFNNPCMD_LOADSTATE:
|
||||
if(!MDFNNET_RecvState(MDFN_de32lsb(buf)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
case MDFNNPCMD_LOADSTATE:
|
||||
RecvState(MDFN_de32lsb(buf));
|
||||
MDFN_DispMessage(_("Remote state loaded."));
|
||||
break;
|
||||
|
||||
case MDFNNPCMD_SERVERTEXT:
|
||||
{
|
||||
uint32 totallen = MDFN_de32lsb(buf);
|
||||
if(totallen > 2000) // Sanity check
|
||||
static const uint32 MaxLength = 2000;
|
||||
uint8 neobuf[MaxLength + 1];
|
||||
char *textbuf = NULL;
|
||||
const uint32 totallen = MDFN_de32lsb(buf);
|
||||
|
||||
if(totallen > MaxLength) // Sanity check
|
||||
{
|
||||
NetError("Text length is too long: %d", totallen);
|
||||
return;
|
||||
}
|
||||
uint8 neobuf[totallen + 1];
|
||||
char *textbuf = NULL;
|
||||
if(!MDFND_RecvData(neobuf, totallen))
|
||||
{
|
||||
NetError("Could not receive text data.");
|
||||
return;
|
||||
throw MDFN_Error(0, _("Text length is too long: %u"), totallen);
|
||||
}
|
||||
|
||||
MDFND_RecvData(neobuf, totallen);
|
||||
|
||||
neobuf[totallen] = 0;
|
||||
trio_asprintf(&textbuf, "** %s", neobuf);
|
||||
MDFND_NetplayText((UTF8*)textbuf, FALSE);
|
||||
@ -471,14 +577,11 @@ void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[],
|
||||
|
||||
if(totallen != sizeof(then_time))
|
||||
{
|
||||
NetError("Echo response length is incorrect size: %d", totallen);
|
||||
return;
|
||||
throw MDFN_Error(0, _("Echo response length is incorrect size: %u"), totallen);
|
||||
}
|
||||
if(!MDFND_RecvData(&then_time, sizeof(then_time)))
|
||||
{
|
||||
NetError("Could not receive echo response data.");
|
||||
return;
|
||||
}
|
||||
|
||||
MDFND_RecvData(&then_time, sizeof(then_time));
|
||||
|
||||
now_time = MDFND_GetTime();
|
||||
|
||||
char *textbuf = NULL;
|
||||
@ -490,28 +593,32 @@ void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[],
|
||||
|
||||
case MDFNNPCMD_TEXT:
|
||||
{
|
||||
uint32 totallen = MDFN_de32lsb(buf);
|
||||
if(totallen > 2000) // Sanity check
|
||||
static const uint32 MaxLength = 2000;
|
||||
uint8 neobuf[MaxLength + 1];
|
||||
const uint32 totallen = MDFN_de32lsb(buf);
|
||||
uint32 nicklen;
|
||||
bool NetEcho = false;
|
||||
char *textbuf = NULL;
|
||||
|
||||
if(totallen < 4)
|
||||
{
|
||||
NetError("Text length is too long: %d", totallen);
|
||||
return;
|
||||
}
|
||||
uint32 nicklen;
|
||||
uint8 neobuf[totallen + 1];
|
||||
char *textbuf = NULL;
|
||||
if(!MDFND_RecvData(neobuf, totallen))
|
||||
throw MDFN_Error(0, _("Text command length is too short: %u"), totallen);
|
||||
}
|
||||
|
||||
if(totallen > MaxLength) // Sanity check
|
||||
{
|
||||
NetError("Could not receive text data.");
|
||||
return;
|
||||
throw MDFN_Error(0, _("Text command length is too long: %u"), totallen);
|
||||
}
|
||||
|
||||
MDFND_RecvData(neobuf, totallen);
|
||||
|
||||
nicklen = MDFN_de32lsb(neobuf);
|
||||
if(nicklen > totallen) // Sanity check
|
||||
if(nicklen > (totallen - 4)) // Sanity check
|
||||
{
|
||||
NetError("Received nickname length is too long: %d", nicklen);
|
||||
return;
|
||||
throw MDFN_Error(0, _("Received nickname length is too long: %u"), nicklen);
|
||||
}
|
||||
|
||||
neobuf[totallen] = 0;
|
||||
bool NetEcho = 0;
|
||||
|
||||
if(nicklen)
|
||||
{
|
||||
@ -521,7 +628,7 @@ void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[],
|
||||
if(OurNick && !strcasecmp(OurNick, (char *)nickbuf))
|
||||
{
|
||||
trio_asprintf(&textbuf, "> %s", &neobuf[4 + nicklen]);
|
||||
NetEcho = TRUE;
|
||||
NetEcho = true;
|
||||
}
|
||||
else
|
||||
trio_asprintf(&textbuf, "<%s> %s", nickbuf, &neobuf[4 + nicklen]);
|
||||
@ -531,29 +638,24 @@ void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[],
|
||||
trio_asprintf(&textbuf, "* %s", &neobuf[4]);
|
||||
}
|
||||
MDFND_NetplayText((UTF8*)textbuf, NetEcho);
|
||||
free(textbuf);
|
||||
free(textbuf);
|
||||
}
|
||||
break;
|
||||
|
||||
case MDFNNPCMD_NICKCHANGED:
|
||||
{
|
||||
uint32 len = MDFN_de32lsb(buf);
|
||||
static const uint32 MaxLength = 2000;
|
||||
uint8 neobuf[MaxLength + 1];
|
||||
uint8 *newnick;
|
||||
char *textbuf = NULL;
|
||||
const uint32 len = MDFN_de32lsb(buf);
|
||||
|
||||
if(len > 2000) // Sanity check
|
||||
if(len > MaxLength) // Sanity check
|
||||
{
|
||||
NetError("Nickname change length is too long: %u", len);
|
||||
return;
|
||||
throw MDFN_Error(0, _("Nickname change length is too long: %u"), len);
|
||||
}
|
||||
|
||||
uint8 neobuf[len + 1];
|
||||
uint8 *newnick;
|
||||
char *textbuf = NULL;
|
||||
|
||||
if(!MDFND_RecvData(neobuf, len))
|
||||
{
|
||||
NetError("Unable to receive data for nickname change.");
|
||||
return;
|
||||
}
|
||||
MDFND_RecvData(neobuf, len);
|
||||
|
||||
neobuf[len] = 0;
|
||||
|
||||
@ -582,39 +684,104 @@ void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[],
|
||||
}
|
||||
break;
|
||||
|
||||
case MDFNNPCMD_CTRL_CHANGE:
|
||||
{
|
||||
const uint32 len = MDFN_de32lsb(buf);
|
||||
|
||||
//
|
||||
// Joined = true;
|
||||
SendCommand(MDFNNPCMD_CTRL_CHANGE_ACK, len);
|
||||
//
|
||||
//
|
||||
LocalInputStateSize = 0;
|
||||
LocalPlayersMask = len;
|
||||
|
||||
for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++)
|
||||
{
|
||||
if(LocalPlayersMask & (1 << x))
|
||||
LocalInputStateSize += PortLen[x];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MDFNNPCMD_CTRLR_SWAP_NOTIF:
|
||||
{
|
||||
const uint32 cm = MDFN_de32lsb(buf);
|
||||
char textbuf[512];
|
||||
|
||||
trio_snprintf(textbuf, sizeof(textbuf), _("* All instances of controllers %u and %u have been swapped."), ((cm & 0xFF) + 1), ((cm >> 8) & 0xFF) + 1);
|
||||
MDFND_NetplayText((UTF8*)textbuf, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case MDFNNPCMD_CTRLR_TAKE_NOTIF:
|
||||
case MDFNNPCMD_CTRLR_DROP_NOTIF:
|
||||
case MDFNNPCMD_CTRLR_DUPE_NOTIF:
|
||||
{
|
||||
static const uint32 MaxNicknameLength = 1000;
|
||||
static const uint32 MaxLength = 12 + MaxNicknameLength;
|
||||
const char *fstr = NULL;
|
||||
const uint32 len = MDFN_de32lsb(buf);
|
||||
uint8 ntf_buf[MaxLength + 1];
|
||||
char *textbuf = NULL;
|
||||
|
||||
if(len < 12)
|
||||
throw MDFN_Error(0, _("Take/drop/dupe notification is too short: %u"), len);
|
||||
|
||||
if(len > MaxLength)
|
||||
throw MDFN_Error(0, _("Take/drop/dupe notification is too long: %u"), len);
|
||||
|
||||
MDFND_RecvData(ntf_buf, len);
|
||||
ntf_buf[len] = 0;
|
||||
|
||||
switch(buf[TotalInputStateSize])
|
||||
{
|
||||
case MDFNNPCMD_CTRLR_TAKE_NOTIF:
|
||||
fstr = _("* <%s> took all instances of %s, and is now %s.");
|
||||
break;
|
||||
|
||||
case MDFNNPCMD_CTRLR_DUPE_NOTIF:
|
||||
fstr = _("* <%s> took copies of %s, and is now %s.");
|
||||
break;
|
||||
|
||||
case MDFNNPCMD_CTRLR_DROP_NOTIF:
|
||||
fstr = _("* <%s> dropped %s, and is now %s.");
|
||||
break;
|
||||
}
|
||||
trio_asprintf(&textbuf, fstr, ntf_buf + 12, GenerateMPSString(MDFN_de32lsb(&ntf_buf[0]), true).c_str(), GenerateMPSString(MDFN_de32lsb(&ntf_buf[4]), false).c_str());
|
||||
MDFND_NetplayText((UTF8*)textbuf, false);
|
||||
free(textbuf);
|
||||
}
|
||||
break;
|
||||
|
||||
case MDFNNPCMD_YOUJOINED:
|
||||
case MDFNNPCMD_YOULEFT:
|
||||
case MDFNNPCMD_PLAYERLEFT:
|
||||
case MDFNNPCMD_PLAYERJOINED:
|
||||
{
|
||||
uint32 len = MDFN_de32lsb(buf);
|
||||
static const uint32 MaxLength = 2000;
|
||||
uint8 neobuf[MaxLength + 1];
|
||||
char *textbuf = NULL;
|
||||
uint32 mps;
|
||||
std::string mps_string;
|
||||
const uint32 len = MDFN_de32lsb(buf);
|
||||
|
||||
if(len > 2000) // Sanity check
|
||||
if(len < 8)
|
||||
{
|
||||
throw MDFN_Error(0, _("Join/Left length is too short: %u"), len);
|
||||
}
|
||||
|
||||
if(len > MaxLength) // Sanity check
|
||||
{
|
||||
NetError("Join/Left length is too long: %u", len);
|
||||
return;
|
||||
throw MDFN_Error(0, _("Join/Left length is too long: %u"), len);
|
||||
}
|
||||
|
||||
uint8 neobuf[len + 1];
|
||||
char *textbuf = NULL;
|
||||
char mergedstr[] = " merged into: ";
|
||||
std::string mps_string;
|
||||
|
||||
if(!MDFND_RecvData(neobuf, len))
|
||||
{
|
||||
NetError("Unable to receive data for join/part message");
|
||||
return;
|
||||
}
|
||||
MDFND_RecvData(neobuf, len);
|
||||
neobuf[len] = 0; // NULL-terminate the string
|
||||
|
||||
if(neobuf[1]) // Player is merged?
|
||||
{
|
||||
mergedstr[strlen(mergedstr) - 1] = '1' + (int)rint(log(neobuf[1]) / log(2));
|
||||
}
|
||||
else
|
||||
mergedstr[0] = 0;
|
||||
mps = MDFN_de32lsb(&neobuf[0]);
|
||||
|
||||
mps_string = GenerateMPSString(neobuf[0]);
|
||||
mps_string = GenerateMPSString(mps);
|
||||
|
||||
if(buf[TotalInputStateSize] == MDFNNPCMD_YOULEFT)
|
||||
{
|
||||
@ -630,27 +797,28 @@ void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[],
|
||||
free(OurNick);
|
||||
OurNick = NULL;
|
||||
}
|
||||
OurNick = strdup((char*)neobuf + 2);
|
||||
OurNick = strdup((char*)neobuf + 8);
|
||||
|
||||
trio_asprintf(&textbuf, _("* You, %s, have connected as: %s%s"), neobuf + 2, mps_string.c_str(), mergedstr);
|
||||
trio_asprintf(&textbuf, _("* You, %s, have connected as: %s"), neobuf + 8, mps_string.c_str());
|
||||
|
||||
LocalInputStateSize = 0;
|
||||
LocalPlayersMask = neobuf[0];
|
||||
LocalPlayersMask = mps;
|
||||
|
||||
for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++)
|
||||
{
|
||||
if(LocalPlayersMask & (1 << x))
|
||||
LocalInputStateSize += PortLen[x];
|
||||
}
|
||||
Joined = TRUE;
|
||||
MDFNNET_SendCommand(MDFNNPCMD_SETFPS, MDFNGameInfo->fps);
|
||||
SendCommand(MDFNNPCMD_SETFPS, MDFNGameInfo->fps);
|
||||
}
|
||||
else if(buf[TotalInputStateSize] == MDFNNPCMD_PLAYERLEFT)
|
||||
{
|
||||
trio_asprintf(&textbuf, _("* %s has left(%s%s)"), neobuf + 2, mps_string.c_str(), mergedstr);
|
||||
trio_asprintf(&textbuf, _("* %s(%s) has left"), neobuf + 8, mps_string.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
trio_asprintf(&textbuf, _("* %s has connected as: %s%s"), neobuf + 2, mps_string.c_str(), mergedstr);
|
||||
trio_asprintf(&textbuf, _("* %s has connected as: %s"), neobuf + 8, mps_string.c_str());
|
||||
}
|
||||
MDFND_NetplayText((UTF8*)textbuf, FALSE);
|
||||
free(textbuf);
|
||||
@ -661,11 +829,18 @@ void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[],
|
||||
|
||||
int rpos = 0;
|
||||
for(int x = 0; x < NumPorts; x++)
|
||||
{
|
||||
{
|
||||
//printf("%d %d\n", x, PortLen[x]);
|
||||
//memset(PortData[x], 0, PortLen[x]);
|
||||
memcpy(PortData[x], buf + rpos, PortLen[x]);
|
||||
rpos += PortLen[x];
|
||||
}
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
NetError("%s", e.what());
|
||||
}
|
||||
//
|
||||
//
|
||||
|
||||
}
|
||||
|
@ -4,8 +4,9 @@
|
||||
int InitNetplay(void);
|
||||
|
||||
void NetplayUpdate(const char **, void *PortData[], uint32 PortLen[], int NumPorts);
|
||||
|
||||
int NetplayStart(const char *PortDeviceCache[16], const uint32 PortDataLenCache[16], uint32 local_players, uint32 netmerge, const std::string &nickname, const std::string &game_key, const std::string &connect_password);
|
||||
int NetplayStart(const char *PortDeviceCache[16], const uint32 PortDataLenCache[16], uint32 local_players, const std::string &nickname, const std::string &game_key, const std::string &connect_password);
|
||||
void NetplaySendState(void);
|
||||
bool NetplaySendCommand(uint8, uint32);
|
||||
|
||||
extern int MDFNnetplay;
|
||||
|
||||
@ -19,17 +20,33 @@ extern int MDFNnetplay;
|
||||
#define MDFNNPCMD_FDSEJECT MDFN_MSC_EJECT_DISK
|
||||
#define MDFNNPCMD_FDSSELECT MDFN_MSC_SELECT_DISK
|
||||
|
||||
#define MDFNNPCMD_SETFPS 0x40 /* Sent from client to server ONLY(it should be ignored server-side if it's not from the first
|
||||
active player for the game). */
|
||||
#define MDFNNPCMD_SETFPS 0x40 // Client->server. It should be ignored server-side if it's not from the first
|
||||
// active player for the game).
|
||||
|
||||
#define MDFNNPCMD_LOADSTATE 0x80
|
||||
#define MDFNNPCMD_NOP 0x41 // Client->server.
|
||||
|
||||
#define MDFNNPCMD_SAVESTATE 0x81 /* Sent from server to client. */
|
||||
//
|
||||
#define MDFNNPCMD_CTRL_CHANGE 0x43 // Server->client.
|
||||
#define MDFNNPCMD_CTRL_CHANGE_ACK 0x44 // Client->server. Acknowledge controller change. Sent using old local data length, everything after
|
||||
// this should be new data size.
|
||||
//
|
||||
|
||||
#define MDFNNPCMD_CTRLR_SWAP_NOTIF 0x68 // Server->Client
|
||||
|
||||
#define MDFNNPCMD_CTRLR_TAKE 0x70 // Client->server. Take the specified controllers(from other clients)
|
||||
#define MDFNNPCMD_CTRLR_DROP 0x71 // Client->server. Drop(relinquish) the specified controllers.
|
||||
#define MDFNNPCMD_CTRLR_DUPE 0x72 // Client->server. Take the specified controllers(but let other clients still keep their control).
|
||||
|
||||
|
||||
#define MDFNNPCMD_CTRLR_SWAP 0x78 // Client->server.
|
||||
|
||||
#define MDFNNPCMD_REQUEST_LIST 0x7F // client->server
|
||||
|
||||
#define MDFNNPCMD_LOADSTATE 0x80 // Client->server, and server->client
|
||||
#define MDFNNPCMD_REQUEST_STATE 0x81 // Server->client
|
||||
|
||||
#define MDFNNPCMD_TEXT 0x90
|
||||
|
||||
#define MDFNNPCMD_SETSETTING 0x91 /* TODO: WIP */
|
||||
|
||||
#define MDFNNPCMD_SERVERTEXT 0x93 // Server text message(informational), server->client
|
||||
#define MDFNNPCMD_ECHO 0x94 // Echos the string(no larger than 256 bytes) back to the client(used for pinging).
|
||||
|
||||
@ -48,6 +65,14 @@ extern int MDFNnetplay;
|
||||
|
||||
#define MDFNNPCMD_NICKCHANGED 0xB8
|
||||
|
||||
#define MDFNNPCMD_LIST 0xC0 // Server->client
|
||||
|
||||
#define MDFNNPCMD_CTRLR_TAKE_NOTIF 0xF0 // Server->client
|
||||
#define MDFNNPCMD_CTRLR_DROP_NOTIF 0xF1 // Server->client
|
||||
#define MDFNNPCMD_CTRLR_DUPE_NOTIF 0xF2 // Server->client
|
||||
|
||||
|
||||
#define MDFNNPCMD_QUIT 0xFF // Client->server
|
||||
|
||||
int MDFNNET_SendCommand(uint8, uint32);
|
||||
int MDFNNET_SendState(void);
|
||||
#endif
|
||||
|
Binary file not shown.
@ -80,7 +80,7 @@ cpu.o: cpu.cpp psx.h ../../mednafen/mednafen.h ../../mednafen/types.h \
|
||||
../../mednafen/state-common.h ../../mednafen/settings-common.h \
|
||||
../../mednafen/debug.h ../../mednafen/git-virtb.h \
|
||||
../../mednafen/settings.h ../../mednafen/mednafen-driver.h \
|
||||
../../mednafen/endian.h ../../mednafen/memory.h \
|
||||
../../mednafen/endian.h ../../mednafen/memory.h ../../mednafen/masmem.h \
|
||||
../../include/trio/trio.h ../../include/trio/triop.h \
|
||||
../../include/trio/triodef.h ../cdrom/cdromif.h ../cdrom/CDUtility.h \
|
||||
/usr/include/c++/4.4/queue /usr/include/c++/4.4/deque \
|
||||
@ -368,6 +368,8 @@ psx.h:
|
||||
|
||||
../../mednafen/memory.h:
|
||||
|
||||
../../mednafen/masmem.h:
|
||||
|
||||
../../include/trio/trio.h:
|
||||
|
||||
../../include/trio/triop.h:
|
||||
|
@ -124,6 +124,8 @@ 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@
|
||||
@ -242,6 +244,8 @@ 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@
|
||||
SSE2_CFLAGS = @SSE2_CFLAGS@
|
||||
SSE3_CFLAGS = @SSE3_CFLAGS@
|
||||
SSE_CFLAGS = @SSE_CFLAGS@
|
||||
@ -250,6 +254,7 @@ 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@
|
||||
|
@ -1,6 +1,8 @@
|
||||
Soul Reaver - Legacy of Kain has CD load time pauses where it probably shouldn't.
|
||||
|
||||
Dead or Alive, Battle Arena Toshinden, Final Fantasy 7 have some kind of GPU timing issues.
|
||||
Battle Arena Toshinden, Final Fantasy 7 have some kind of GPU timing issues.
|
||||
|
||||
Zero Divide runs too fast(related to CPU emulation speed?).
|
||||
|
||||
Chrono Cross has several-second freezes during some large special attack/magic sequences.
|
||||
|
||||
@ -12,6 +14,10 @@ Rayman (Europe) has somewhat broken FMV.
|
||||
|
||||
Crusaders of Might and Magic - The CD-XA buffering increase for ToD II is apparently exacerbating the early voice cutoff problem in this game.
|
||||
|
||||
Misadventures of Trone Bonne - Voice problems, lockup, possibly due to excessively long seek delays?
|
||||
|
||||
Test time delta between GPU LL DMA end and GPU non-busy status for various primitive types in sequence on a PS1.
|
||||
|
||||
Test IRQ and COP0 latencies; PSX IRQ controller latency, software IRQ bit latency, latency of both relevant COP0 IRQ enable bits.
|
||||
|
||||
Test IRQ with LWC2.
|
||||
|
@ -305,6 +305,9 @@ int PS_CDC::StateAction(StateMem *sm, int load, int data_only)
|
||||
SFVAR(CommandLoc_Dirty),
|
||||
SFARRAY16(&xa_previous[0][0], sizeof(xa_previous) / sizeof(xa_previous[0][0])),
|
||||
|
||||
SFVAR(xa_cur_set),
|
||||
SFVAR(xa_cur_file),
|
||||
SFVAR(xa_cur_chan),
|
||||
SFEND
|
||||
};
|
||||
|
||||
@ -357,10 +360,8 @@ void PS_CDC::WriteResult(uint8 V)
|
||||
ResultsWP = (ResultsWP + 1) & 0xF;
|
||||
ResultsIn = (ResultsIn + 1) & 0x1F;
|
||||
|
||||
#ifdef DEBUG
|
||||
if(!ResultsIn)
|
||||
PSX_WARNING("[CDC] Results buffer overflow!");
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8 PS_CDC::ReadResult(void)
|
||||
@ -468,6 +469,10 @@ struct XA_SoundGroup
|
||||
#define XA_CODING_189 0x04
|
||||
#define XA_CODING_STEREO 0x01
|
||||
|
||||
// Special regression prevention test cases:
|
||||
// Um Jammer Lammy (start doing poorly)
|
||||
// Yarudora Series Vol.1 - Double Cast (non-FMV speech)
|
||||
|
||||
bool PS_CDC::XA_Test(const uint8 *sdata)
|
||||
{
|
||||
const XA_Subheader *sh = (const XA_Subheader *)&sdata[12 + 4];
|
||||
@ -478,9 +483,28 @@ bool PS_CDC::XA_Test(const uint8 *sdata)
|
||||
if(!(sh->submode & XA_SUBMODE_AUDIO))
|
||||
return false;
|
||||
|
||||
//printf("Test File: 0x%02x 0x%02x - Channel: 0x%02x 0x%02x - Submode: 0x%02x 0x%02x - Coding: 0x%02x 0x%02x - \n", sh->file, sh->file_dup, sh->channel, sh->channel_dup, sh->submode, sh->submode_dup, sh->coding, sh->coding_dup);
|
||||
|
||||
if((Mode & MODE_SF) && (sh->file != FilterFile || sh->channel != FilterChan))
|
||||
return false;
|
||||
|
||||
if(!xa_cur_set || (Mode & MODE_SF))
|
||||
{
|
||||
xa_cur_set = true;
|
||||
xa_cur_file = sh->file;
|
||||
xa_cur_chan = sh->channel;
|
||||
}
|
||||
else if(sh->file != xa_cur_file || sh->channel != xa_cur_chan)
|
||||
return false;
|
||||
|
||||
if(sh->submode & XA_SUBMODE_EOF)
|
||||
{
|
||||
//puts("YAY");
|
||||
xa_cur_set = false;
|
||||
xa_cur_file = 0;
|
||||
xa_cur_chan = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -489,6 +513,10 @@ void PS_CDC::ClearAudioBuffers(void)
|
||||
memset(AudioBuffer, 0, sizeof(AudioBuffer));
|
||||
memset(xa_previous, 0, sizeof(xa_previous));
|
||||
|
||||
xa_cur_set = false;
|
||||
xa_cur_file = 0;
|
||||
xa_cur_chan = 0;
|
||||
|
||||
AudioBuffer_ReadPos = 0;
|
||||
AudioBuffer_WritePos = 0;
|
||||
AudioBuffer_UsedCount = 0;
|
||||
@ -501,6 +529,8 @@ void PS_CDC::XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab)
|
||||
const XA_Subheader *sh = (const XA_Subheader *)&sdata[12 + 4];
|
||||
const unsigned unit_index_shift = (sh->coding & XA_CODING_8BIT) ? 0 : 1;
|
||||
|
||||
//printf("File: 0x%02x 0x%02x - Channel: 0x%02x 0x%02x - Submode: 0x%02x 0x%02x - Coding: 0x%02x 0x%02x - \n", sh->file, sh->file_dup, sh->channel, sh->channel_dup, sh->submode, sh->submode_dup, sh->coding, sh->coding_dup);
|
||||
|
||||
ab->Size = 18 * (4 << unit_index_shift) * 28;
|
||||
|
||||
if(sh->coding & XA_CODING_STEREO)
|
||||
@ -521,10 +551,8 @@ void PS_CDC::XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab)
|
||||
uint8 ibuffer[28];
|
||||
int16 obuffer[2 + 28];
|
||||
|
||||
#ifdef DEBUG
|
||||
if(param != param_copy)
|
||||
printf("%d %02x %02x\n", unit, param, param_copy);
|
||||
#endif
|
||||
|
||||
for(unsigned i = 0; i < 28; i++)
|
||||
{
|
||||
@ -594,12 +622,10 @@ void PS_CDC::CheckAIP(void)
|
||||
|
||||
void PS_CDC::SetAIP(unsigned irq, unsigned result_count, uint8 *r)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if(AsyncIRQPending)
|
||||
{
|
||||
PSX_WARNING("***WARNING*** Previous notification skipped: CurSector=%d, old_notification=0x%02x", CurSector, AsyncIRQPending);
|
||||
}
|
||||
#endif
|
||||
ClearAIP();
|
||||
|
||||
AsyncResultsPendingCount = result_count;
|
||||
@ -723,9 +749,7 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
{
|
||||
if(CurSector >= (int32)toc.tracks[100].lba)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Beyond end!");
|
||||
#endif
|
||||
DriveStatus = DS_STOPPED;
|
||||
|
||||
SetAIP(CDCIRQ_DISC_ERROR, MakeStatus() | 0x04, 0x04);
|
||||
@ -736,9 +760,7 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
}
|
||||
else
|
||||
{
|
||||
bool need_ap = false;
|
||||
|
||||
//PSX_WARNING("Read sector: %d", CurSector);
|
||||
//PSX_WARNING("Read sector: %d", CurSector);
|
||||
|
||||
Cur_CDIF->ReadRawSector(buf, CurSector); // FIXME: error out on error.
|
||||
DecodeSubQ(buf + 2352);
|
||||
@ -749,28 +771,19 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
{
|
||||
if(XA_Test(buf))
|
||||
{
|
||||
if((Mode & MODE_AUTOPAUSE) && (buf[12 + 6] & 0x80))
|
||||
{
|
||||
//need_ap = true;
|
||||
}
|
||||
//else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if(AudioBuffer_ReadPos & 0xFFF)
|
||||
printf("readpos=%04x(rabl=%04x) writepos=%04x\n", AudioBuffer_ReadPos, AudioBuffer[AudioBuffer_ReadPos >> 12].Size, AudioBuffer_WritePos);
|
||||
#endif
|
||||
if(AudioBuffer_ReadPos & 0xFFF)
|
||||
printf("readpos=%04x(rabl=%04x) writepos=%04x\n", AudioBuffer_ReadPos, AudioBuffer[AudioBuffer_ReadPos >> 12].Size, AudioBuffer_WritePos);
|
||||
|
||||
//if(AudioBuffer_UsedCount == 0)
|
||||
// AudioBuffer_InPrebuffer = true;
|
||||
//if(AudioBuffer_UsedCount == 0)
|
||||
// AudioBuffer_InPrebuffer = true;
|
||||
|
||||
XA_ProcessSector(buf, &AudioBuffer[AudioBuffer_WritePos >> 12]);
|
||||
AudioBuffer_UsedCount++;
|
||||
XA_ProcessSector(buf, &AudioBuffer[AudioBuffer_WritePos >> 12]);
|
||||
AudioBuffer_UsedCount++;
|
||||
|
||||
if(AudioBuffer_UsedCount == AudioBuffer_PreBufferCount)
|
||||
AudioBuffer_InPrebuffer = false;
|
||||
if(AudioBuffer_UsedCount == AudioBuffer_PreBufferCount)
|
||||
AudioBuffer_InPrebuffer = false;
|
||||
|
||||
AudioBuffer_WritePos = (AudioBuffer_WritePos & 0xFFF) | ((((AudioBuffer_WritePos >> 12) + 1) % AudioBuffer_Count) << 12);
|
||||
}
|
||||
AudioBuffer_WritePos = (AudioBuffer_WritePos & 0xFFF) | ((((AudioBuffer_WritePos >> 12) + 1) % AudioBuffer_Count) << 12);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -784,10 +797,8 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if(!(Mode & 0x30) && (buf[12 + 6] & 0x20))
|
||||
PSX_WARNING("BORK: %d", CurSector);
|
||||
#endif
|
||||
|
||||
{
|
||||
int32 offs = (Mode & 0x20) ? 0 : 12;
|
||||
@ -806,19 +817,8 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
SetAIP(CDCIRQ_DATA_READY, MakeStatus());
|
||||
}
|
||||
|
||||
if(need_ap)
|
||||
{
|
||||
MDFN_DispMessage("Autopause XA");
|
||||
DriveStatus = DS_PAUSED;
|
||||
PSRCounter = 0;
|
||||
|
||||
SetAIP(CDCIRQ_DATA_END, MakeStatus());
|
||||
}
|
||||
else
|
||||
{
|
||||
PSRCounter += 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1));
|
||||
CurSector++;
|
||||
}
|
||||
PSRCounter += 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1));
|
||||
CurSector++;
|
||||
}
|
||||
}
|
||||
else if(DriveStatus == DS_PLAYING)
|
||||
@ -924,10 +924,8 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
else
|
||||
CurSector++;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
PSX_WARNING("[CDC] BUG CDDA buffer full");
|
||||
#endif
|
||||
|
||||
}
|
||||
} // end if playing
|
||||
@ -960,9 +958,7 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
}
|
||||
else if(PendingCommand >= 0x20 || !Commands[PendingCommand].func)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Unknown command: 0x%02x", PendingCommand);
|
||||
#endif
|
||||
|
||||
WriteResult(MakeStatus(true));
|
||||
WriteResult(ERRCODE_BAD_COMMAND);
|
||||
@ -972,9 +968,7 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
}
|
||||
else if(ArgsIn < Commands[PendingCommand].args_min || ArgsIn > Commands[PendingCommand].args_max)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Bad number(%d) of args(first check) for command 0x%02x", ArgsIn, PendingCommand);
|
||||
#endif
|
||||
|
||||
WriteResult(MakeStatus(true));
|
||||
WriteResult(ERRCODE_BAD_NUMARGS);
|
||||
@ -987,7 +981,7 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
const CDC_CTEntry *command = &Commands[PendingCommand];
|
||||
//PSX_WARNING("[CDC] Command: %s --- %d", command->name, Results.CanRead());
|
||||
|
||||
#ifdef DEBUG
|
||||
#if 1
|
||||
printf("[CDC] Command: %s --- ", command->name);
|
||||
for(unsigned int i = 0; i < ArgsIn; i++)
|
||||
printf(" 0x%02x", ArgsBuf[i]);
|
||||
@ -1035,13 +1029,10 @@ void PS_CDC::Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V)
|
||||
switch(reg_index)
|
||||
{
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Unknown write to register 0x%02x: 0x%02x\n", reg_index, V);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x00:
|
||||
#ifdef DEBUG
|
||||
if(PendingCommandCounter > 0)
|
||||
{
|
||||
PSX_WARNING("[CDC] WARNING: Interrupting command 0x%02x, phase=%d, timeleft=%d with command=0x%02x", PendingCommand, PendingCommandPhase,
|
||||
@ -1057,7 +1048,6 @@ void PS_CDC::Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V)
|
||||
{
|
||||
PSX_WARNING("[CDC] Attempting to start command(0x%02x) while command results(count=%d) still in buffer.", V, ResultsIn);
|
||||
}
|
||||
#endif
|
||||
|
||||
PendingCommandCounter = 8192; //1024; //128; //256; //16; //1024;
|
||||
PendingCommand = V;
|
||||
@ -1068,12 +1058,10 @@ void PS_CDC::Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V)
|
||||
ArgsBuf[ArgsIn & 0xF] = V;
|
||||
ArgsIn = (ArgsIn + 1) & 0x1F;
|
||||
|
||||
#ifdef DEBUG
|
||||
if(!(ArgsIn & 0x0F))
|
||||
{
|
||||
PSX_WARNING("[CDC] Argument buffer overflow");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
@ -1083,9 +1071,7 @@ void PS_CDC::Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V)
|
||||
{
|
||||
if(!SB_In)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Data read begin when no data to read!");
|
||||
#endif
|
||||
|
||||
DMABuffer.Write(SB, 2340);
|
||||
|
||||
@ -1115,9 +1101,7 @@ void PS_CDC::Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V)
|
||||
|
||||
if(V & 0x20)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Mystery IRQ trigger bit set.");
|
||||
#endif
|
||||
IRQBuffer |= 0x10;
|
||||
}
|
||||
break;
|
||||
@ -1133,9 +1117,7 @@ void PS_CDC::Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V)
|
||||
|
||||
if(V & 0x80) // Forced CD hardware reset of some kind(interface, controller, and drive?) Seems to take a while(relatively speaking) to complete.
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Soft Reset");
|
||||
#endif
|
||||
SoftReset();
|
||||
}
|
||||
|
||||
@ -1166,7 +1148,6 @@ void PS_CDC::Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V)
|
||||
{
|
||||
memcpy(DecodeVolume, Pending_DecodeVolume, sizeof(DecodeVolume));
|
||||
|
||||
#ifdef DEBUG
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
for(int o = 0; o < 2; o++)
|
||||
@ -1174,7 +1155,6 @@ void PS_CDC::Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V)
|
||||
//fprintf(stderr, "Input Channel %d, Output Channel %d -- Volume=%d\n", i, o, DecodeVolume[i][o]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1216,12 +1196,10 @@ uint8 PS_CDC::Read(const pscpu_timestamp_t timestamp, uint32 A)
|
||||
case 0x02:
|
||||
if(DMABuffer.CanRead())
|
||||
ret = DMABuffer.ReadByte();
|
||||
#ifdef DEBUG
|
||||
else
|
||||
{
|
||||
PSX_WARNING("[CDC] CD data transfer port read, but no data present!");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
@ -1280,9 +1258,7 @@ bool PS_CDC::CommandCheckDiscPresent(void)
|
||||
|
||||
int32 PS_CDC::Command_Sync(const int arg_count, const uint8 *args)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Unimplemented command: 0x%02x", PendingCommand);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -1328,9 +1304,7 @@ static int32 CalcSeekTime(int32 initial, int32 target, bool motor_on, bool pause
|
||||
else if(paused)
|
||||
ret += (int64)33868800 * 150 / 1000;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("%d\n", ret);
|
||||
#endif
|
||||
|
||||
return(ret);
|
||||
}
|
||||
@ -1381,16 +1355,12 @@ int32 PS_CDC::Command_Play(const int arg_count, const uint8 *args)
|
||||
|
||||
if(track < toc.first_track)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Attempt to play track before first track.");
|
||||
#endif
|
||||
track = toc.first_track;
|
||||
}
|
||||
else if(track > toc.last_track)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Attempt to play track before first track.");
|
||||
#endif
|
||||
track = toc.last_track;
|
||||
}
|
||||
|
||||
@ -1398,9 +1368,7 @@ int32 PS_CDC::Command_Play(const int arg_count, const uint8 *args)
|
||||
|
||||
PlayTrackMatch = track;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[CDC] Play track: %d\n", track);
|
||||
#endif
|
||||
SeekTarget = toc.tracks[track].lba;
|
||||
PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
|
||||
PreSeekHack(SeekTarget);
|
||||
@ -1533,11 +1501,18 @@ int32 PS_CDC::Command_Stop(const int arg_count, const uint8 *args)
|
||||
WriteResult(MakeStatus());
|
||||
WriteIRQ(CDCIRQ_ACKNOWLEDGE);
|
||||
|
||||
ClearAudioBuffers();
|
||||
ClearAIP();
|
||||
DriveStatus = DS_STOPPED;
|
||||
if(DriveStatus == DS_STOPPED)
|
||||
{
|
||||
return(5000);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearAudioBuffers();
|
||||
ClearAIP();
|
||||
DriveStatus = DS_STOPPED;
|
||||
|
||||
return(33868);
|
||||
return(33868); // FIXME, should be much higher.
|
||||
}
|
||||
}
|
||||
|
||||
int32 PS_CDC::Command_Stop_Part2(void)
|
||||
@ -1551,6 +1526,7 @@ int32 PS_CDC::Command_Stop_Part2(void)
|
||||
}
|
||||
|
||||
|
||||
// TODO: Pause speed depends on speed(1x/2x) and current position. Also check restart(for ReadN/ReadS and Play) 'delay'.
|
||||
int32 PS_CDC::Command_Pause(const int arg_count, const uint8 *args)
|
||||
{
|
||||
if(!CommandCheckDiscPresent())
|
||||
@ -1559,12 +1535,19 @@ int32 PS_CDC::Command_Pause(const int arg_count, const uint8 *args)
|
||||
WriteResult(MakeStatus());
|
||||
WriteIRQ(CDCIRQ_ACKNOWLEDGE);
|
||||
|
||||
// "Viewpoint" flips out and crashes if reading isn't stopped (almost?) immediately.
|
||||
ClearAudioBuffers();
|
||||
ClearAIP();
|
||||
DriveStatus = DS_PAUSED;
|
||||
if(DriveStatus == DS_PAUSED || DriveStatus == DS_STOPPED)
|
||||
{
|
||||
return(5000);
|
||||
}
|
||||
else
|
||||
{
|
||||
// "Viewpoint" flips out and crashes if reading isn't stopped (almost?) immediately.
|
||||
ClearAudioBuffers();
|
||||
ClearAIP();
|
||||
DriveStatus = DS_PAUSED;
|
||||
|
||||
return((int64)33868800 * 100 / 1000);
|
||||
return((int64)33868800 * 100 / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
int32 PS_CDC::Command_Pause_Part2(void)
|
||||
@ -1817,9 +1800,7 @@ int32 PS_CDC::Command_Test(const int arg_count, const uint8 *args)
|
||||
switch(args[0])
|
||||
{
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]);
|
||||
#endif
|
||||
WriteResult(MakeStatus(true));
|
||||
WriteResult(0x10);
|
||||
WriteIRQ(CDCIRQ_DISC_ERROR);
|
||||
@ -1840,9 +1821,7 @@ int32 PS_CDC::Command_Test(const int arg_count, const uint8 *args)
|
||||
case 0x18:
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]);
|
||||
#endif
|
||||
WriteResult(MakeStatus());
|
||||
WriteIRQ(CDCIRQ_ACKNOWLEDGE);
|
||||
break;
|
||||
@ -1857,18 +1836,14 @@ int32 PS_CDC::Command_Test(const int arg_count, const uint8 *args)
|
||||
#endif
|
||||
|
||||
case 0x51: // *Need to retest this test command
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]);
|
||||
#endif
|
||||
WriteResult(0x01);
|
||||
WriteResult(0x00);
|
||||
WriteResult(0x00);
|
||||
break;
|
||||
|
||||
case 0x75: // *Need to retest this test command
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]);
|
||||
#endif
|
||||
WriteResult(0x00);
|
||||
WriteResult(0xC0);
|
||||
WriteResult(0x00);
|
||||
|
@ -238,6 +238,9 @@ class PS_CDC
|
||||
bool XA_Test(const uint8 *sdata);
|
||||
void XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab);
|
||||
int16 xa_previous[2][2];
|
||||
bool xa_cur_set;
|
||||
uint8 xa_cur_file;
|
||||
uint8 xa_cur_chan;
|
||||
|
||||
struct CDC_CTEntry
|
||||
{
|
||||
|
@ -209,7 +209,6 @@ uint32 PS_CPU::Exception(uint32 code, uint32 PC, const uint32 NPM)
|
||||
const bool InBDSlot = !(NPM & 0x3);
|
||||
uint32 handler = 0x80000080;
|
||||
|
||||
#ifdef DEBUG
|
||||
assert(code < 16);
|
||||
|
||||
if(code != EXCEPTION_INT && code != EXCEPTION_BP && code != EXCEPTION_SYSCALL)
|
||||
@ -218,7 +217,6 @@ uint32 PS_CPU::Exception(uint32 code, uint32 PC, const uint32 NPM)
|
||||
IRQ_GetRegister(IRQ_GSREG_STATUS, NULL, 0), IRQ_GetRegister(IRQ_GSREG_MASK, NULL, 0));
|
||||
//assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(CP0.SR & (1 << 22)) // BEV
|
||||
handler = 0xBFC00180;
|
||||
@ -413,9 +411,7 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
||||
|
||||
{
|
||||
BEGIN_OPF(ILL, 0, 0);
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CPU] Unknown instruction @%08x = %08x, op=%02x, funct=%02x", PC, instr, instr >> 26, (instr & 0x3F));
|
||||
#endif
|
||||
DO_LDS();
|
||||
new_PC = Exception(EXCEPTION_RI, PC, new_PC_mask);
|
||||
new_PC_mask = 0;
|
||||
@ -602,9 +598,7 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
||||
// BREAK - Breakpoint
|
||||
//
|
||||
BEGIN_OPF(BREAK, 0, 0x0D);
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[CPU] BREAK BREAK BREAK BREAK DAAANCE -- PC=0x%08x", PC);
|
||||
#endif
|
||||
|
||||
DO_LDS();
|
||||
new_PC = Exception(EXCEPTION_BP, PC, new_PC_mask);
|
||||
@ -646,12 +640,10 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
||||
uint32 rd = (instr >> 11) & 0x1F;
|
||||
uint32 val = GPR[rt];
|
||||
|
||||
#ifdef DEBUG
|
||||
if(rd != CP0REG_CAUSE && rd != CP0REG_SR && val)
|
||||
{
|
||||
PSX_WARNING("[CPU] Unimplemented MTC0: rt=%d(%08x) -> rd=%d", rt, GPR[rt], rd);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(rd)
|
||||
{
|
||||
@ -689,10 +681,8 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
||||
CP0.SR = val & ~( (0x3 << 26) | (0x3 << 23) | (0x3 << 6));
|
||||
RecalcIPCache();
|
||||
|
||||
#ifdef DEBUG
|
||||
if(CP0.SR & 0x10000)
|
||||
PSX_WARNING("[CPU] IsC set");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -461,11 +461,8 @@ void DMA_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V)
|
||||
RecalcIRQOut();
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[DMA] Unknown write: %08x %08x", A, V);
|
||||
default: PSX_WARNING("[DMA] Unknown write: %08x %08x", A, V);
|
||||
assert(0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return;
|
||||
@ -499,10 +496,8 @@ PSX_WARNING("[DMA] Unknown write: %08x %08x", A, V);
|
||||
GPU->Write(timestamp, 0x04, 0x01 << 24);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[DMA] Forced stop for channel %d -- scanline=%d", ch, GPU->GetScanlineNum());
|
||||
MDFN_DispMessage("[DMA] Forced stop for channel %d", ch);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(ch == 6)
|
||||
@ -549,11 +544,8 @@ uint32 DMA_Read(const pscpu_timestamp_t timestamp, uint32 A)
|
||||
{
|
||||
switch(A & 0xC)
|
||||
{
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[DMA] Unknown read: %08x", A);
|
||||
assert(0);
|
||||
#endif
|
||||
default: PSX_WARNING("[DMA] Unknown read: %08x", A);
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
case 0x0: ret = DMAControl;
|
||||
|
@ -156,18 +156,18 @@ FrontIO::FrontIO(bool emulate_memcards_[8], bool emulate_multitap_[2])
|
||||
memcpy(emulate_memcards, emulate_memcards_, sizeof(emulate_memcards));
|
||||
memcpy(emulate_multitap, emulate_multitap_, sizeof(emulate_multitap));
|
||||
|
||||
DummyDevice = new InputDevice;
|
||||
DummyDevice = new InputDevice();
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
DeviceData[i] = NULL;
|
||||
Devices[i] = new InputDevice;
|
||||
Devices[i] = new InputDevice();
|
||||
DevicesMC[i] = Device_Memcard_Create();
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < 2; i++)
|
||||
{
|
||||
DevicesTap[i] = new InputDevice_Multitap;
|
||||
DevicesTap[i] = new InputDevice_Multitap();
|
||||
}
|
||||
|
||||
MapDevicesToPorts();
|
||||
@ -197,6 +197,12 @@ FrontIO::~FrontIO()
|
||||
DevicesTap[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(DummyDevice)
|
||||
{
|
||||
delete DummyDevice;
|
||||
DummyDevice = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int32 FrontIO::CalcNextEvent(int32 next_event)
|
||||
@ -598,7 +604,7 @@ void FrontIO::SetInput(unsigned int port, const char *type, void *ptr)
|
||||
else if(!strcmp(type, "mouse"))
|
||||
Devices[port] = Device_Mouse_Create();
|
||||
else
|
||||
Devices[port] = new InputDevice;
|
||||
Devices[port] = new InputDevice();
|
||||
|
||||
DeviceData[port] = ptr;
|
||||
|
||||
|
@ -406,13 +406,14 @@ void PS_GPU::Command_FBFill(const uint32 *cb)
|
||||
|
||||
for(int32 y = 0; y < height; y++)
|
||||
{
|
||||
if(LineSkipTest(y))
|
||||
const int32 d_y = (y + destY) & 511;
|
||||
|
||||
if(LineSkipTest(d_y))
|
||||
continue;
|
||||
|
||||
for(int32 x = 0; x < width; x++)
|
||||
{
|
||||
int32 d_y = (y + destY) & 511;
|
||||
int32 d_x = (x + destX) & 1023;
|
||||
const int32 d_x = (x + destX) & 1023;
|
||||
|
||||
GPURAM[d_y][d_x] = fill_value;
|
||||
}
|
||||
@ -509,45 +510,23 @@ void PS_GPU::Command_FBRead(const uint32 *cb)
|
||||
|
||||
void PS_GPU::RecalcTexWindowLUT(void)
|
||||
{
|
||||
const unsigned TexWindowX_AND = ~(tww << 3);
|
||||
const unsigned TexWindowX_OR = (twx & tww) << 3;
|
||||
|
||||
const unsigned TexWindowY_AND = ~(twh << 3);
|
||||
const unsigned TexWindowY_OR = (twy & twh) << 3;
|
||||
|
||||
// printf("TWX: 0x%02x, TWW: 0x%02x\n", twx, tww);
|
||||
// printf("TWY: 0x%02x, TWH: 0x%02x\n", twy, twh);
|
||||
|
||||
for(unsigned x = 0; x < 256; x++)
|
||||
{
|
||||
uint8 targ_x = 0;
|
||||
uint8 targ_wc = 0;
|
||||
uint8 x = twx * 8;
|
||||
|
||||
do
|
||||
{
|
||||
if(!targ_wc)
|
||||
{
|
||||
targ_x = twx * 8;
|
||||
targ_wc = tww * 8;
|
||||
}
|
||||
TexWindowXLUT[x] = targ_x;
|
||||
|
||||
x++;
|
||||
targ_x++;
|
||||
targ_wc++;
|
||||
} while(x != (twx * 8));
|
||||
TexWindowXLUT[x] = (x & TexWindowX_AND) | TexWindowX_OR;
|
||||
}
|
||||
|
||||
for(unsigned y = 0; y < 256; y++)
|
||||
{
|
||||
uint8 targ_y = 0;
|
||||
uint8 targ_hc = 0;
|
||||
uint8 y = twy * 8;
|
||||
|
||||
do
|
||||
{
|
||||
if(!targ_hc)
|
||||
{
|
||||
targ_y = twy * 8;
|
||||
targ_hc = twh * 8;
|
||||
}
|
||||
//printf("Texture window y: %d %d\n", y, targ_y);
|
||||
TexWindowYLUT[y] = targ_y;
|
||||
|
||||
y++;
|
||||
targ_y++;
|
||||
targ_hc++;
|
||||
} while(y != (twy * 8));
|
||||
TexWindowYLUT[y] = (y & TexWindowY_AND) | TexWindowY_OR;
|
||||
}
|
||||
|
||||
memset(TexWindowXLUT_Pre, TexWindowXLUT[0], sizeof(TexWindowXLUT_Pre));
|
||||
@ -569,7 +548,7 @@ void PS_GPU::Command_DrawMode(const uint32 *cb)
|
||||
|
||||
dtd = (*cb >> 9) & 1;
|
||||
dfe = (*cb >> 10) & 1;
|
||||
//printf("DFE: %d -- scanline=%d\n", dfe, scanline);
|
||||
//printf("*******************DFE: %d -- scanline=%d\n", dfe, scanline);
|
||||
}
|
||||
|
||||
void PS_GPU::Command_TexWindow(const uint32 *cb)
|
||||
|
@ -113,13 +113,13 @@ void PS_GPU::DrawLine(line_point *points)
|
||||
|
||||
if(i_dx >= 1024)
|
||||
{
|
||||
PSX_WARNING("[GPU] Line too long: i_dx=%d", i_dx);
|
||||
//PSX_WARNING("[GPU] Line too long: i_dx=%d", i_dx);
|
||||
return;
|
||||
}
|
||||
|
||||
if(i_dy >= 512)
|
||||
{
|
||||
PSX_WARNING("[GPU] Line too long: i_dy=%d", i_dy);
|
||||
//PSX_WARNING("[GPU] Line too long: i_dy=%d", i_dy);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -146,8 +146,9 @@ void PS_GPU::DrawLine(line_point *points)
|
||||
//
|
||||
for(int32 i = 0; i <= k; i++) // <= is not a typo.
|
||||
{
|
||||
const int32 x = cur_point.x >> Line_XY_FractBits;
|
||||
const int32 y = cur_point.y >> Line_XY_FractBits;
|
||||
// Sign extension is not necessary here for x and y, due to the maximum values that ClipX1 and ClipY1 can contain.
|
||||
const int32 x = (cur_point.x >> Line_XY_FractBits) & 2047;
|
||||
const int32 y = (cur_point.y >> Line_XY_FractBits) & 2047;
|
||||
uint16 pix = 0x8000;
|
||||
|
||||
if(!LineSkipTest(y))
|
||||
@ -209,8 +210,8 @@ void PS_GPU::Command_DrawLine(const uint32 *cb)
|
||||
points[0].b = (*cb >> 16) & 0xFF;
|
||||
cb++;
|
||||
|
||||
points[0].x = sign_x_to_s32(11, ((*cb >> 0) & 0xFFFF) + OffsX);
|
||||
points[0].y = sign_x_to_s32(11, ((*cb >> 16) & 0xFFFF) + OffsY);
|
||||
points[0].x = sign_x_to_s32(11, ((*cb >> 0) & 0xFFFF)) + OffsX;
|
||||
points[0].y = sign_x_to_s32(11, ((*cb >> 16) & 0xFFFF)) + OffsY;
|
||||
cb++;
|
||||
}
|
||||
|
||||
@ -228,8 +229,8 @@ void PS_GPU::Command_DrawLine(const uint32 *cb)
|
||||
points[1].b = points[0].b;
|
||||
}
|
||||
|
||||
points[1].x = sign_x_to_s32(11, ((*cb >> 0) & 0xFFFF) + OffsX);
|
||||
points[1].y = sign_x_to_s32(11, ((*cb >> 16) & 0xFFFF) + OffsY);
|
||||
points[1].x = sign_x_to_s32(11, ((*cb >> 0) & 0xFFFF)) + OffsX;
|
||||
points[1].y = sign_x_to_s32(11, ((*cb >> 16) & 0xFFFF)) + OffsY;
|
||||
cb++;
|
||||
|
||||
if(polyline)
|
||||
|
@ -64,8 +64,35 @@ void PS_GPU::DrawSprite(int32 x_arg, int32 y_arg, int32 w, int32 h, uint8 u_arg,
|
||||
|
||||
if(y_bound > y_start && x_bound > x_start)
|
||||
{
|
||||
//
|
||||
// Note(TODO): From tests on a PS1, even a 0-width sprite takes up time to "draw" proportional to its height.
|
||||
//
|
||||
int32 suck_time = (x_bound - x_start) * (y_bound - y_start);
|
||||
|
||||
// Disabled until we can get it to take into account texture windowing, which can cause large sprites to be drawn entirely from cache(and not suffer from a texturing
|
||||
// penalty); and disabled until we find a game that needs more accurate sprite draw timing. :b
|
||||
#if 0
|
||||
if(textured)
|
||||
{
|
||||
// Empirically-observed approximations of time(66MHz cycles) taken to draw large textured sprites in the various texture depths, when the texture data and CLUT data
|
||||
// was zero(non-zero takes longer to draw, TODO test that more):
|
||||
// 4bpp - area * 2
|
||||
// 8bpp - area * 3
|
||||
// 15/16bpp - area * 5
|
||||
// (other factors come into more importance for smaller sprites)
|
||||
static const int cw[4] = { 64, 32, 32, 32 };
|
||||
static const int ch[4] = { 64, 64, 32, 32 };
|
||||
static const int mm[4] = { 2 - 1, 3 - 1, 5 - 1, 5 - 1 };
|
||||
|
||||
// Parts of the first few(up to texture cache height) horizontal lines can be in cache, so assume they are.
|
||||
suck_time += mm[TexMode_TA] * std::max<int>(0, (x_bound - x_start) - cw[TexMode_TA]) * std::min<int>(ch[TexMode_TA], y_bound - y_start);
|
||||
|
||||
// The rest of the horizontal lines should not possibly have parts in the cache now.
|
||||
suck_time += mm[TexMode_TA] * (x_bound - x_start) * std::max<int>(0, (y_bound - y_start) - ch[TexMode_TA]);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if((BlendMode >= 0) || MaskEval_TA)
|
||||
{
|
||||
suck_time += ((((x_bound + 1) & ~1) - (x_start & ~1)) * (y_bound - y_start)) >> 1;
|
||||
@ -144,8 +171,8 @@ void PS_GPU::Command_DrawSprite(const uint32 *cb)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
w = *cb & 0xFFFF;
|
||||
h = *cb >> 16;
|
||||
w = (*cb & 0x3FF);
|
||||
h = (*cb >> 16) & 0x1FF;
|
||||
cb++;
|
||||
break;
|
||||
|
||||
|
@ -416,12 +416,10 @@ void MDEC_DMAWrite(uint32 V)
|
||||
InCounter--;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
{
|
||||
printf("MYSTERY1: %08x\n", V);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32 MDEC_DMARead(void)
|
||||
@ -446,9 +444,7 @@ bool MDEC_DMACanRead(void)
|
||||
|
||||
void MDEC_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[MDEC] Write: 0x%08x 0x%08x, %d", A, V, timestamp);
|
||||
#endif
|
||||
if(A & 4)
|
||||
{
|
||||
if(V & 0x80000000) // Reset?
|
||||
|
@ -72,15 +72,15 @@ PS_GPU *GPU = NULL;
|
||||
PS_CDC *CDC = NULL;
|
||||
FrontIO *FIO = NULL;
|
||||
|
||||
static MultiAccessSizeMem<512 * 1024, uint32, false, 0, 0> *BIOSROM = NULL;
|
||||
static MultiAccessSizeMem<65536, uint32, false, 0, 0> *PIOMem = NULL;
|
||||
static MultiAccessSizeMem<512 * 1024, uint32, false> *BIOSROM = NULL;
|
||||
static MultiAccessSizeMem<65536, uint32, false> *PIOMem = NULL;
|
||||
|
||||
MultiAccessSizeMem<2048 * 1024, uint32, false, 0, 0> MainRAM;
|
||||
MultiAccessSizeMem<2048 * 1024, uint32, false> MainRAM;
|
||||
|
||||
static uint32 TextMem_Start;
|
||||
static std::vector<uint8> TextMem;
|
||||
|
||||
static MultiAccessSizeMem<1024, uint32, false, 0, 0> ScratchRAM;
|
||||
static MultiAccessSizeMem<1024, uint32, false> ScratchRAM;
|
||||
|
||||
static const uint32 SysControl_Mask[9] = { 0x00ffffff, 0x00ffffff, 0xffffffff, 0x2f1fffff,
|
||||
0xffffffff, 0x2f1fffff, 0x2f1fffff, 0xffffffff,
|
||||
@ -499,16 +499,12 @@ template<typename T, bool IsWrite, bool Access24, bool Peek> static INLINE void
|
||||
{
|
||||
if(IsWrite)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[MEM] Unknown write%d to %08x at time %d, =%08x(%d)", (int)(sizeof(T) * 8), A, timestamp, V, V);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
V = 0;
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[MEM] Unknown read%d from %08x at time %d", (int)(sizeof(T) * 8), A, timestamp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -930,8 +926,8 @@ static bool InitCommon(std::vector<CDIF *> *CDInterfaces, const bool EmulateMemc
|
||||
(CD_SelectedDisc >= 0 && !CD_TrayOpen) ? cdifs_scex_ids[CD_SelectedDisc] : NULL);
|
||||
|
||||
|
||||
BIOSROM = new MultiAccessSizeMem<512 * 1024, uint32, false, 0, 0>();
|
||||
PIOMem = new MultiAccessSizeMem<65536, uint32, false, 0, 0>();
|
||||
BIOSROM = new MultiAccessSizeMem<512 * 1024, uint32, false>();
|
||||
PIOMem = new MultiAccessSizeMem<65536, uint32, false>();
|
||||
|
||||
for(uint32 ma = 0x00000000; ma < 0x00800000; ma += 2048 * 1024)
|
||||
{
|
||||
@ -1179,7 +1175,8 @@ static int Load(const char *name, MDFNFILE *fp)
|
||||
#if 0
|
||||
static std::vector<CDIF *> CDInterfaces;
|
||||
|
||||
CDInterfaces.push_back(new CDIF("/extra/games/PSX/Tony Hawk's Pro Skater 2 (USA)/Tony Hawk's Pro Skater 2 (USA).cue"));
|
||||
CDInterfaces.push_back(new CDIF("/extra/games/PSX/Jumping Flash! (USA)/Jumping Flash! (USA).cue"));
|
||||
//CDInterfaces.push_back(new CDIF("/extra/games/PSX/Tony Hawk's Pro Skater 2 (USA)/Tony Hawk's Pro Skater 2 (USA).cue"));
|
||||
|
||||
if(!InitCommon(&CDInterfaces, !IsPSF))
|
||||
return(0);
|
||||
@ -1319,7 +1316,6 @@ static void SetInput(int port, const char *type, void *ptr)
|
||||
static int StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
return(0);
|
||||
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(CD_TrayOpen),
|
||||
@ -1347,6 +1343,9 @@ static int StateAction(StateMem *sm, int load, int data_only)
|
||||
ret &= TIMER_StateAction(sm, load, data_only);
|
||||
ret &= CDC->StateAction(sm, load, data_only);
|
||||
ret &= MDEC_StateAction(sm, load, data_only);
|
||||
ret &= SPU->StateAction(sm, load, data_only);
|
||||
//ret &= FIO->StateAction(sm, load, data_only);
|
||||
//ret &= GPU->StateAction(sm, load, data_only);
|
||||
ret &= IRQ_StateAction(sm, load, data_only);
|
||||
|
||||
if(load)
|
||||
@ -1496,6 +1495,7 @@ MDFNGI EmulatedPSX =
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
StateAction,
|
||||
Emulate,
|
||||
SetInput,
|
||||
|
@ -74,7 +74,7 @@ namespace MDFN_IEN_PSX
|
||||
extern PS_GPU *GPU;
|
||||
extern PS_CDC *CDC;
|
||||
extern PS_SPU *SPU;
|
||||
extern MultiAccessSizeMem<2048 * 1024, uint32, false, 0, 0> MainRAM;
|
||||
extern MultiAccessSizeMem<2048 * 1024, uint32, false> MainRAM;
|
||||
};
|
||||
|
||||
|
||||
|
@ -45,9 +45,7 @@ uint32 SIO_Read(pscpu_timestamp_t timestamp, uint32 A)
|
||||
switch(A & 0xE)
|
||||
{
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[SIO] Unknown read: 0x%08x -- %d\n", A, timestamp);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x0:
|
||||
@ -82,9 +80,7 @@ void SIO_Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V)
|
||||
switch(A & 0xE)
|
||||
{
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
PSX_WARNING("[SIO] Unknown write: 0x%08x 0x%08x -- %d\n", A, V, timestamp);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x0:
|
||||
|
@ -169,14 +169,11 @@ void PS_SPU::Power(void)
|
||||
|
||||
BlockEnd = 0;
|
||||
|
||||
CDAudioCWA = 0;
|
||||
CWA = 0;
|
||||
|
||||
memset(CDXA_ResampBuffer, 0, sizeof(CDXA_ResampBuffer));
|
||||
CDXA_CurPhase = 0;
|
||||
|
||||
VoiceCWP[0] = 0;
|
||||
VoiceCWP[1] = 0;
|
||||
|
||||
memset(Regs, 0, sizeof(Regs));
|
||||
|
||||
memset(RDSB, 0, sizeof(RDSB));
|
||||
@ -488,10 +485,7 @@ void PS_SPU::RunEnvelope(SPU_Voice *voice)
|
||||
//static INLINE void CalcVCDelta(const uint8 zs, uint8 speed, bool log_mode, bool decrement, int16 Current, int &increment, int &divinco)
|
||||
switch(ADSR->Phase)
|
||||
{
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
assert(0);
|
||||
#endif
|
||||
default: assert(0);
|
||||
break;
|
||||
|
||||
case ADSR_ATTACK:
|
||||
@ -729,8 +723,7 @@ int32 PS_SPU::UpdateFromCDC(int32 clocks)
|
||||
{
|
||||
int index = voice_num >> 1;
|
||||
|
||||
WriteSPURAM(0x400 | (index * 0x200) | VoiceCWP[index], voice_pvs);
|
||||
VoiceCWP[index] = (VoiceCWP[index] + 1) & 0x1FF;
|
||||
WriteSPURAM(0x400 | (index * 0x200) | CWA, voice_pvs);
|
||||
}
|
||||
|
||||
|
||||
@ -765,9 +758,7 @@ int32 PS_SPU::UpdateFromCDC(int32 clocks)
|
||||
phase_inc = voice->Pitch + (((int16)voice->Pitch * ((voice - 1)->PreLRSample)) >> 15);
|
||||
if(phase_inc < 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("phase_inc < 0 (THIS SHOULD NOT HAPPEN)\n");
|
||||
#endif
|
||||
phase_inc = 0;
|
||||
}
|
||||
}
|
||||
@ -806,9 +797,6 @@ int32 PS_SPU::UpdateFromCDC(int32 clocks)
|
||||
voice->CurPhase_SD = 28 << 12; // Trigger initial sample decode
|
||||
|
||||
voice->CurAddr = voice->StartAddr & ~0x7;
|
||||
|
||||
if(voice_num == 1 || voice_num == 3)
|
||||
VoiceCWP[voice_num >> 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -848,12 +836,11 @@ int32 PS_SPU::UpdateFromCDC(int32 clocks)
|
||||
}
|
||||
}
|
||||
}
|
||||
WriteSPURAM(CDAudioCWA | 0x000, cda_raw[0]);
|
||||
WriteSPURAM(CDAudioCWA | 0x200, cda_raw[1]);
|
||||
|
||||
CDAudioCWA = (CDAudioCWA + 1) & 0x1FF;
|
||||
WriteSPURAM(CWA | 0x000, cda_raw[0]);
|
||||
WriteSPURAM(CWA | 0x200, cda_raw[1]);
|
||||
}
|
||||
|
||||
CWA = (CWA + 1) & 0x1FF;
|
||||
|
||||
NoiseCounter += NoiseFreqTable[(SPUControl >> 8) & 0x3F];
|
||||
if(NoiseCounter >= 0x8000)
|
||||
@ -888,9 +875,7 @@ int32 PS_SPU::UpdateFromCDC(int32 clocks)
|
||||
clamp(&output_l, -32768, 32767);
|
||||
clamp(&output_r, -32768, 32767);
|
||||
|
||||
#ifdef DEBUG
|
||||
assert(IntermediateBufferPos < 4096);
|
||||
#endif
|
||||
IntermediateBuffer[IntermediateBufferPos][0] = output_l;
|
||||
IntermediateBuffer[IntermediateBufferPos][1] = output_r;
|
||||
IntermediateBufferPos++;
|
||||
@ -1238,9 +1223,7 @@ int32 PS_SPU::EndFrame(int16 *SoundBuf)
|
||||
|
||||
speex_resampler_process_interleaved_int(resampler, (const spx_int16_t *)IntermediateBuffer, &in_len, (spx_int16_t *)SoundBuf, &out_len);
|
||||
|
||||
#ifdef DEBUG
|
||||
assert(in_len <= IntermediateBufferPos);
|
||||
#endif
|
||||
|
||||
if((IntermediateBufferPos - in_len) > 0)
|
||||
memmove(IntermediateBuffer, IntermediateBuffer + in_len, (IntermediateBufferPos - in_len) * sizeof(int16) * 2);
|
||||
@ -1256,6 +1239,135 @@ int32 PS_SPU::EndFrame(int16 *SoundBuf)
|
||||
}
|
||||
}
|
||||
|
||||
int PS_SPU::StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
#define SFSWEEP(r) SFVAR((r).Control), \
|
||||
SFVAR((r).Current), \
|
||||
SFVAR((r).Divider)
|
||||
|
||||
#define SFVOICE(n) SFARRAY32(&Voices[n].DecodeBuffer[0], sizeof(Voices[n].DecodeBuffer) / sizeof(Voices[n].DecodeBuffer[0])), \
|
||||
SFVAR(Voices[n].DecodeWritePos), \
|
||||
SFVAR(Voices[n].DecodeFlags), \
|
||||
\
|
||||
SFSWEEP(Voices[n].Sweep[0]), \
|
||||
SFSWEEP(Voices[n].Sweep[1]), \
|
||||
\
|
||||
SFVAR(Voices[n].Pitch), \
|
||||
SFVAR(Voices[n].CurPhase), \
|
||||
SFVAR(Voices[n].CurPhase_SD), \
|
||||
\
|
||||
SFVAR(Voices[n].StartAddr), \
|
||||
SFVAR(Voices[n].CurAddr), \
|
||||
SFVAR(Voices[n].ADSRControl), \
|
||||
SFVAR(Voices[n].LoopAddr), \
|
||||
SFVAR(Voices[n].PreLRSample), \
|
||||
\
|
||||
SFVAR(Voices[n].ADSR.EnvLevel), \
|
||||
SFVAR(Voices[n].ADSR.Divider), \
|
||||
SFVAR(Voices[n].ADSR.Phase), \
|
||||
\
|
||||
SFVAR(Voices[n].ADSR.AttackExp), \
|
||||
SFVAR(Voices[n].ADSR.SustainExp), \
|
||||
SFVAR(Voices[n].ADSR.SustainDec), \
|
||||
SFVAR(Voices[n].ADSR.ReleaseExp), \
|
||||
\
|
||||
SFVAR(Voices[n].ADSR.AttackRate), \
|
||||
SFVAR(Voices[n].ADSR.DecayRate), \
|
||||
SFVAR(Voices[n].ADSR.SustainRate), \
|
||||
SFVAR(Voices[n].ADSR.ReleaseRate), \
|
||||
\
|
||||
SFVAR(Voices[n].ADSR.SustainLevel)
|
||||
|
||||
SFVOICE(0),
|
||||
SFVOICE(1),
|
||||
SFVOICE(2),
|
||||
SFVOICE(3),
|
||||
SFVOICE(4),
|
||||
SFVOICE(5),
|
||||
SFVOICE(6),
|
||||
SFVOICE(7),
|
||||
SFVOICE(8),
|
||||
SFVOICE(9),
|
||||
SFVOICE(10),
|
||||
SFVOICE(11),
|
||||
SFVOICE(12),
|
||||
SFVOICE(13),
|
||||
SFVOICE(14),
|
||||
SFVOICE(15),
|
||||
SFVOICE(16),
|
||||
SFVOICE(17),
|
||||
SFVOICE(18),
|
||||
SFVOICE(19),
|
||||
SFVOICE(20),
|
||||
SFVOICE(21),
|
||||
SFVOICE(22),
|
||||
SFVOICE(23),
|
||||
#undef SFVOICE
|
||||
|
||||
SFVAR(NoiseCounter),
|
||||
SFVAR(LFSR),
|
||||
|
||||
SFVAR(FM_Mode),
|
||||
SFVAR(Noise_Mode),
|
||||
SFVAR(Reverb_Mode),
|
||||
|
||||
SFVAR(ReverbWA),
|
||||
|
||||
SFSWEEP(GlobalSweep[0]),
|
||||
SFSWEEP(GlobalSweep[1]),
|
||||
|
||||
SFARRAY32(ReverbVol, sizeof(ReverbVol) / sizeof(ReverbVol[0])),
|
||||
|
||||
SFARRAY32(CDVol, sizeof(CDVol) / sizeof(CDVol[0])),
|
||||
SFARRAY32(ExternVol, sizeof(ExternVol) / sizeof(ExternVol[0])),
|
||||
|
||||
SFVAR(IRQAddr),
|
||||
|
||||
SFVAR(RWAddr),
|
||||
|
||||
SFVAR(SPUControl),
|
||||
|
||||
SFVAR(VoiceOn),
|
||||
SFVAR(VoiceOff),
|
||||
|
||||
SFVAR(BlockEnd),
|
||||
|
||||
SFVAR(CWA),
|
||||
|
||||
SFARRAY32(&CDXA_ResampBuffer[0][0], sizeof(CDXA_ResampBuffer) / sizeof(CDXA_ResampBuffer[0][0])),
|
||||
SFVAR(CDXA_CurPhase),
|
||||
|
||||
SFARRAY16(Regs, sizeof(Regs) / sizeof(Regs[0])),
|
||||
SFARRAY16(AuxRegs, sizeof(AuxRegs) / sizeof(AuxRegs[0])),
|
||||
|
||||
SFARRAY16(&RDSB[0][0], sizeof(RDSB) / sizeof(RDSB[0][0])),
|
||||
SFVAR(RDSB_WP),
|
||||
|
||||
SFARRAY16(&RUSB[0][0], sizeof(RUSB) / sizeof(RUSB[0][0])),
|
||||
SFVAR(RUSB_WP),
|
||||
|
||||
SFVAR(ReverbCur),
|
||||
SFVAR(IRQAsserted),
|
||||
|
||||
SFVAR(clock_divider),
|
||||
|
||||
SFARRAY16(SPURAM, 524288 / sizeof(uint16)),
|
||||
SFEND
|
||||
};
|
||||
#undef SFSWEEP
|
||||
int ret = 1;
|
||||
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, "SPU");
|
||||
|
||||
if(load)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
uint16 PS_SPU::PeekSPURAM(uint32 address)
|
||||
{
|
||||
|
@ -34,8 +34,11 @@ struct SPU_ADSR
|
||||
int32 SustainLevel; // (Sl + 1) << 11
|
||||
};
|
||||
|
||||
class PS_SPU;
|
||||
class SPU_Sweep
|
||||
{
|
||||
friend class PS_SPU; // For save states - FIXME(remove in future?)
|
||||
|
||||
public:
|
||||
SPU_Sweep() { }
|
||||
~SPU_Sweep() { }
|
||||
@ -88,6 +91,8 @@ class PS_SPU
|
||||
PS_SPU();
|
||||
~PS_SPU();
|
||||
|
||||
int StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
void Power(void);
|
||||
void Write(pscpu_timestamp_t timestamp, uint32 A, uint16 V);
|
||||
uint16 Read(pscpu_timestamp_t timestamp, uint32 A);
|
||||
@ -144,20 +149,17 @@ class PS_SPU
|
||||
uint32 RWAddr;
|
||||
|
||||
uint16 SPUControl;
|
||||
uint16 AddressMult; // Just a guess!
|
||||
|
||||
uint32 VoiceOn;
|
||||
uint32 VoiceOff;
|
||||
|
||||
uint32 BlockEnd;
|
||||
|
||||
uint32 CDAudioCWA;
|
||||
uint32 CWA;
|
||||
|
||||
int32 CDXA_ResampBuffer[2][4];
|
||||
int32 CDXA_CurPhase;
|
||||
|
||||
uint32 VoiceCWP[2];
|
||||
|
||||
union
|
||||
{
|
||||
uint16 Regs[0x100];
|
||||
@ -233,14 +235,13 @@ class PS_SPU
|
||||
|
||||
bool IRQAsserted;
|
||||
|
||||
int last_rate;
|
||||
uint32 last_quality;
|
||||
|
||||
//pscpu_timestamp_t lastts;
|
||||
int32 clock_divider;
|
||||
|
||||
uint16 SPURAM[524288 / sizeof(uint16)];
|
||||
|
||||
int last_rate;
|
||||
uint32 last_quality;
|
||||
SpeexResamplerState *resampler;
|
||||
|
||||
// Buffers 44.1KHz samples, should have enough for one video frame(~735 frames NTSC, ~882 PAL) plus jitter plus enough for the resampler leftovers.
|
||||
|
@ -116,9 +116,7 @@ static int32 CalcNextEvent(int32 next_event)
|
||||
count_delta = target - Timers[i].Counter;
|
||||
if(count_delta <= 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "timer %d count_delta <= 0!!! %d %d\n", i, target, Timers[i].Counter);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -130,17 +128,13 @@ static int32 CalcNextEvent(int32 next_event)
|
||||
|
||||
if((i == 0x2) && (Timers[i].Mode & 0x200))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
assert(Timers[i].Div8Counter >= 0 && Timers[i].Div8Counter < 8);
|
||||
#endif
|
||||
tmp_clocks = ((count_delta - 1) * 8) + (8 - Timers[i].Div8Counter);
|
||||
}
|
||||
else
|
||||
tmp_clocks = count_delta;
|
||||
|
||||
#ifdef DEBUG
|
||||
assert(tmp_clocks > 0);
|
||||
#endif
|
||||
|
||||
if(next_event > tmp_clocks)
|
||||
next_event = tmp_clocks;
|
||||
@ -184,7 +178,7 @@ static void ClockTimer(int i, uint32 clocks)
|
||||
|
||||
if((before < target && Timers[i].Counter >= target) || zero_tm || Timers[i].Counter > 0xFFFF)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#if 1
|
||||
if(Timers[i].Mode & 0x10)
|
||||
{
|
||||
if((Timers[i].Counter - target) > 3)
|
||||
@ -261,11 +255,9 @@ void TIMER_Write(const pscpu_timestamp_t timestamp, uint32 A, uint16 V)
|
||||
|
||||
int which = (A >> 4) & 0x3;
|
||||
|
||||
#ifdef DEBUG
|
||||
assert(!(A & 3));
|
||||
|
||||
PSX_DBGINFO("[TIMER] Write: %08x %04x", A, V);
|
||||
#endif
|
||||
|
||||
if(which >= 3)
|
||||
return;
|
||||
@ -322,12 +314,10 @@ uint16 TIMER_Read(const pscpu_timestamp_t timestamp, uint32 A)
|
||||
uint16 ret = 0;
|
||||
int which = (A >> 4) & 0x3;
|
||||
|
||||
#ifdef DEBUG
|
||||
assert(!(A & 3));
|
||||
|
||||
if(which >= 3)
|
||||
assert(0);
|
||||
#endif
|
||||
|
||||
TIMER_Update(timestamp);
|
||||
|
||||
|
@ -254,6 +254,12 @@ void QTRecord::WriteFrame(const MDFN_Surface *surface, const MDFN_Rect &DisplayR
|
||||
|
||||
memset(&qts, 0, sizeof(qts));
|
||||
|
||||
if(DisplayRect.h <= 0)
|
||||
{
|
||||
fprintf(stderr, "[BUG] qtrecord.cpp: DisplayRect.h <= 0\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
qts.video_foffset = qtfile.tell();
|
||||
|
||||
@ -304,6 +310,17 @@ void QTRecord::WriteFrame(const MDFN_Surface *surface, const MDFN_Rect &DisplayR
|
||||
dest_line++;
|
||||
}
|
||||
|
||||
#if 0
|
||||
while(dest_x < ((QTVideoWidth - (xscale_factor * width)) / 2))
|
||||
{
|
||||
dest_line[dest_x * 3 + 0] = 0;
|
||||
dest_line[dest_x * 3 + 1] = 0;
|
||||
dest_line[dest_x * 3 + 2] = 0;
|
||||
|
||||
dest_x++;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(int x = x_start; x < x_start + width; x++)
|
||||
{
|
||||
for(int sub_x = 0; sub_x < xscale_factor; sub_x++)
|
||||
|
@ -7,7 +7,7 @@
|
||||
void MDFNI_SelectState(int);
|
||||
|
||||
/* "fname" overrides the default save state filename code if non-NULL. */
|
||||
/* If suffix is set, just override the default suffix(nc0-nc9) */
|
||||
/* If suffix is set, just override the default suffix(mc0-mc9) */
|
||||
void MDFNI_SaveState(const char *fname, const char *suffix, const MDFN_Surface *surface, const MDFN_Rect *DisplayRect, const MDFN_Rect *LineWidths);
|
||||
void MDFNI_LoadState(const char *fname, const char *suffix);
|
||||
void MDFNI_EnableStateRewind(int enable);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <trio/trio.h>
|
||||
#include "driver.h"
|
||||
@ -547,12 +548,15 @@ int MDFNSS_StateAction(StateMem *st, int load, int data_only, SFORMAT *sf, const
|
||||
return(MDFNSS_StateAction(st, load, data_only, love));
|
||||
}
|
||||
|
||||
int MDFNSS_SaveSM(StateMem *st, int wantpreview, int data_only, const MDFN_Surface *surface, const MDFN_Rect *DisplayRect, const MDFN_Rect *LineWidths)
|
||||
int MDFNSS_SaveSM(StateMem *st, int wantpreview_and_ts, int data_only, const MDFN_Surface *surface, const MDFN_Rect *DisplayRect, const MDFN_Rect *LineWidths)
|
||||
{
|
||||
static uint8 header[32]="MEDNAFENSVESTATE";
|
||||
static const char *header_magic = "MDFNSVST";
|
||||
uint8 header[32];
|
||||
int neowidth = 0, neoheight = 0;
|
||||
|
||||
if(wantpreview)
|
||||
memset(header, 0, sizeof(header));
|
||||
|
||||
if(wantpreview_and_ts)
|
||||
{
|
||||
bool is_multires = FALSE;
|
||||
|
||||
@ -585,14 +589,18 @@ int MDFNSS_SaveSM(StateMem *st, int wantpreview, int data_only, const MDFN_Surfa
|
||||
|
||||
if(!data_only)
|
||||
{
|
||||
memset(header+16,0,16);
|
||||
memcpy(header, header_magic, 8);
|
||||
|
||||
if(wantpreview_and_ts)
|
||||
MDFN_en64lsb(header + 8, time(NULL));
|
||||
|
||||
MDFN_en32lsb(header + 16, MEDNAFEN_VERSION_NUMERIC);
|
||||
MDFN_en32lsb(header + 24, neowidth);
|
||||
MDFN_en32lsb(header + 28, neoheight);
|
||||
smem_write(st, header, 32);
|
||||
}
|
||||
|
||||
if(wantpreview)
|
||||
if(wantpreview_and_ts)
|
||||
{
|
||||
uint8 *previewbuffer = (uint8 *)malloc(4 * neowidth * neoheight);
|
||||
MDFN_Surface *dest_surface = new MDFN_Surface((uint32 *)previewbuffer, neowidth, neoheight, neowidth, surface->format);
|
||||
@ -730,16 +738,11 @@ int MDFNSS_LoadSM(StateMem *st, int haspreview, int data_only)
|
||||
else
|
||||
{
|
||||
smem_read(st, header, 32);
|
||||
if(memcmp(header,"MEDNAFENSVESTATE",16))
|
||||
|
||||
if(memcmp(header, "MEDNAFENSVESTATE", 16) && memcmp(header, "MDFNSVST", 8))
|
||||
return(0);
|
||||
|
||||
stateversion = MDFN_de32lsb(header + 16);
|
||||
|
||||
if(stateversion < 0x0600)
|
||||
{
|
||||
printf("State too old: %08x\n", stateversion);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
if(haspreview)
|
||||
@ -959,6 +962,14 @@ void MDFNI_SaveState(const char *fname, const char *suffix, const MDFN_Surface *
|
||||
if(!MDFNGameInfo->StateAction)
|
||||
return;
|
||||
|
||||
if(MDFNnetplay && (MDFNGameInfo->SaveStateAltersState == true))
|
||||
{
|
||||
char sb[256];
|
||||
trio_snprintf(sb, sizeof(sb), _("Module %s is not compatible with manual state saving during netplay."), MDFNGameInfo->shortname);
|
||||
MDFND_NetplayText((const uint8*)sb, false);
|
||||
return;
|
||||
}
|
||||
|
||||
MDFND_SetStateStatus(NULL);
|
||||
MDFNSS_Save(fname, suffix, surface, DisplayRect, LineWidths);
|
||||
}
|
||||
@ -978,7 +989,9 @@ void MDFNI_LoadState(const char *fname, const char *suffix)
|
||||
if(MDFNSS_Load(fname, suffix))
|
||||
{
|
||||
if(MDFNnetplay)
|
||||
MDFNNET_SendState();
|
||||
{
|
||||
NetplaySendState();
|
||||
}
|
||||
|
||||
if(MDFNMOV_IsRecording())
|
||||
MDFNMOV_RecordState();
|
||||
|
@ -34,7 +34,7 @@ int32 smem_seek(StateMem *st, uint32 offset, int whence);
|
||||
int smem_write32le(StateMem *st, uint32 b);
|
||||
int smem_read32le(StateMem *st, uint32 *b);
|
||||
|
||||
int MDFNSS_SaveSM(StateMem *st, int wantpreview, int data_only, const MDFN_Surface *surface = (MDFN_Surface *)NULL, const MDFN_Rect *DisplayRect = (MDFN_Rect*)NULL, const MDFN_Rect *LineWidths = (MDFN_Rect *)NULL);
|
||||
int MDFNSS_SaveSM(StateMem *st, int wantpreview_and_ts, int data_only, const MDFN_Surface *surface = (MDFN_Surface *)NULL, const MDFN_Rect *DisplayRect = (MDFN_Rect*)NULL, const MDFN_Rect *LineWidths = (MDFN_Rect *)NULL);
|
||||
int MDFNSS_LoadSM(StateMem *st, int haspreview, int data_only);
|
||||
|
||||
void MDFNSS_CheckStates(void);
|
||||
|
@ -89,8 +89,8 @@ int MDFND_UnlockMutex(MDFN_Mutex *lock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MDFND_SendData(const void*, uint32) { return 0; }
|
||||
int MDFND_RecvData(void *, uint32) { return 0; }
|
||||
void MDFND_SendData(const void*, uint32) {}
|
||||
void MDFND_RecvData(void *, uint32) {}
|
||||
void MDFND_NetplayText(const uint8*, bool) {}
|
||||
void MDFND_NetworkClose() {}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user