changed fourscore to exclude other control options. (this is still not as clean as it could be. more work should be done in both input.cpp files to make sure that only gamepads can be used with fourscore.

also properly implemented zapper logging. and now, finally, I can log anything if I add in a little bit of code.
This commit is contained in:
zeromus 2008-06-09 08:15:20 +00:00
parent 2683c041af
commit c438158a00
16 changed files with 1556 additions and 1417 deletions

View File

@ -67,7 +67,12 @@ void FCEUI_SetNTSCTH(int n, int tint, int hue);
void FCEUI_SetInput(int port, ESI type, void *ptr, int attrib);
void FCEUI_SetInputFC(ESIFC type, void *ptr, int attrib);
void FCEUI_DisableFourScore(bool disabled);
//tells the emulator whether a fourscore is attached
void FCEUI_SetInputFourscore(bool attachFourscore);
//tells whether a fourscore is attached
bool FCEUI_GetInputFourscore();
void FCEUI_UseInputPreset(int preset);
@ -143,6 +148,10 @@ void FCEUI_LoadState(char *fname);
void FCEUD_SaveStateAs(void);
void FCEUD_LoadStateFrom(void);
//at the minimum, you should call FCEUI_SetInput, FCEUI_SetInputFC, and FCEUI_SetInputFourscore
//you may also need to maintain your own internal state
void FCEUD_SetInput(bool fourscore, ESI port0, ESI port1, ESIFC fcexp);
//movie was recorded from poweron. the alternative is from a savestate (or from reset)
#define MOVIE_FLAG_FROM_POWERON (1<<3)
@ -179,7 +188,7 @@ void FCEUI_LoadMovie(char *fname, bool read_only, int _stopframe);
void FCEUI_MoviePlayFromBeginning(void);
void FCEUI_StopMovie(void);
//int FCEUI_IsMovieActive(void);
int FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* /* [in, out] */ info);
bool FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* /* [in, out] */ info);
char* FCEUI_MovieGetCurrentName(int addSlotNumber);
void FCEUI_MovieToggleReadOnly(void);
bool FCEUI_GetMovieToggleReadOnly();

View File

@ -59,7 +59,7 @@ extern int eoptions;
#define EO_HIGHPRIO 4096
#define EO_FORCEASPECT 8192
#define EO_FORCEISCALE 16384
#define EO_NOFOURSCORE 32768
#define EO_FOURSCORE 32768
bool directoryExists(const char* dirname);
#endif

View File

@ -351,8 +351,19 @@ void FCEUD_UpdateInput()
}
}
void FCEUD_SetInput(bool fourscore, ESI port0, ESI port1, ESIFC fcexp)
{
eoptions &= ~EO_FOURSCORE;
if(fourscore) eoptions |= EO_FOURSCORE;
InputType[0]=port0;
InputType[1]=port1;
InputType[2]=fcexp;
InitInputPorts();
}
//Initializes the emulator with the current input port configuration
void InitInputPorts(void)
void InitInputPorts()
{
void *InputDPtr;
@ -396,7 +407,7 @@ void InitInputPorts(void)
}
FCEUI_SetInputFC((ESIFC)InputType[2],InputDPtr,attrib);
FCEUI_DisableFourScore((eoptions&EO_NOFOURSCORE)!=0);
FCEUI_SetInputFourscore((eoptions&EO_FOURSCORE)!=0);
}
ButtConfig fkbmap[0x48]=
@ -725,13 +736,13 @@ static BOOL CALLBACK DWBCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
bc->DeviceNum[wc]=0;
bc->ButtonNum[wc]=lParam&255;
/* Stop config if the user pushes the same button twice in a row. */
//Stop config if the user pushes the same button twice in a row.
if(wc && bc->ButtType[wc]==bc->ButtType[wc-1] && bc->DeviceNum[wc]==bc->DeviceNum[wc-1] &&
bc->ButtonNum[wc]==bc->ButtonNum[wc-1])
goto gornk;
bc->NumC++;
/* Stop config if we reached our maximum button limit. */
//Stop config if we reached our maximum button limit.
if(bc->NumC >= MAXBUTTCONFIG)
goto gornk;
@ -743,12 +754,15 @@ static BOOL CALLBACK DWBCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
case WM_INITDIALOG:
SetWindowText(hwndDlg, (char*)DWBText); //mbg merge 7/17/06 added cast
BeginJoyWait(hwndDlg);
SetTimer(hwndDlg,666,25,0); /* Every 25ms.*/
SetTimer(hwndDlg,666,25,0); //Every 25ms.
{
char *nstr = MakeButtString(DWBButtons);
SetDlgItemText(hwndDlg, LBL_DWBDIALOG_TEXT, nstr);
free(nstr);
}
break;
case WM_CLOSE:
case WM_QUIT: goto gornk;
@ -883,8 +897,6 @@ static BOOL CALLBACK DoTBCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
sprintf(buf,"Virtual Gamepad %d",DoTBPort+3);
SetDlgItemText(hwndDlg, GRP_GAMEPAD2, buf);
CheckDlgButton(hwndDlg,CHECK_DISABLE_FOURSCORE,(eoptions & EO_NOFOURSCORE)?BST_CHECKED:BST_UNCHECKED);
}
SetWindowText(hwndDlg, DoTBTitle);
break;
@ -907,19 +919,12 @@ static BOOL CALLBACK DoTBCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
case BTN_CLOSE:
gornk:
if(DoTBType == SI_GAMEPAD)
{
eoptions &= ~EO_NOFOURSCORE;
if(IsDlgButtonChecked(hwndDlg,CHECK_DISABLE_FOURSCORE)==BST_CHECKED)
eoptions|=EO_NOFOURSCORE;
}
EndDialog(hwndDlg,0);
break;
}
}
}
return 0;
}
static void DoTBConfig(HWND hParent, const char *text, char *_template, ButtConfig *buttons, int max)
@ -930,391 +935,402 @@ static void DoTBConfig(HWND hParent, const char *text, char *_template, ButtConf
DialogBox(fceu_hInstance,_template,hParent,DoTBCallB);
}
/**
* Callback function of the input configuration dialog.
**/
const unsigned int NUMBER_OF_PORTS = 2;
const unsigned int NUMBER_OF_NES_DEVICES = SI_COUNT;
const static unsigned int NUMBER_OF_FAMICOM_DEVICES = SIFC_COUNT;
//these are unfortunate lists. they match the ESI and ESIFC enums
static const int configurable_nes[6]= { 0, 1, 0, 1, 1, 0 };
static const int configurable_fam[14]= { 0,0,0,0, 1,1,0,1, 1,1,1,0, 0,0 };
const unsigned int FAMICOM_POSITION = 2;
static void UpdateComboPad(HWND hwndDlg, WORD id)
{
unsigned int sel_input = id - COMBO_PAD1;
// Update the user input type
InputType[sel_input] =
SendDlgItemMessage(
hwndDlg,
id,
CB_GETCURSEL,
0,
(LPARAM)(LPSTR)0
);
// Enable or disable the configuration button
EnableWindow(
GetDlgItem(hwndDlg, id + 2),
configurable_nes[InputType[sel_input]]
);
// Update the text field
SetDlgItemText(
hwndDlg,
TXT_PAD1 + sel_input,
(LPTSTR)ESI_Name((ESI)InputType[sel_input])
);
}
static void UpdateComboFam(HWND hwndDlg)
{
// Update the user input type of the famicom
InputType[FAMICOM_POSITION] =
SendDlgItemMessage(
hwndDlg,
COMBO_FAM,
CB_GETCURSEL,
0,
(LPARAM)(LPSTR)0
);
// Enable or disable the configuration button
EnableWindow(
GetDlgItem(hwndDlg, BTN_FAM),
configurable_fam[InputType[FAMICOM_POSITION]]
);
// Update the text field
SetDlgItemText(
hwndDlg,
TXT_FAM,
(LPTSTR)ESIFC_Name((ESIFC)InputType[FAMICOM_POSITION])
);
}
static void UpdateFourscoreState(HWND dlg)
{
//(inverse logic:)
BOOL enable = (eoptions & EO_FOURSCORE)?FALSE:TRUE;
EnableWindow(GetDlgItem(dlg,BTN_PORT1),enable);
EnableWindow(GetDlgItem(dlg,BTN_PORT2),enable);
EnableWindow(GetDlgItem(dlg,COMBO_PAD1),enable);
EnableWindow(GetDlgItem(dlg,COMBO_PAD2),enable);
EnableWindow(GetDlgItem(dlg,TXT_PAD1),enable);
EnableWindow(GetDlgItem(dlg,TXT_PAD2),enable);
//change the inputs to gamepad
if(!enable)
{
SendMessage(GetDlgItem(dlg,COMBO_PAD1),CB_SETCURSEL,SI_GAMEPAD,0);
SendMessage(GetDlgItem(dlg,COMBO_PAD2),CB_SETCURSEL,SI_GAMEPAD,0);
UpdateComboPad(dlg,COMBO_PAD1);
UpdateComboPad(dlg,COMBO_PAD2);
SetDlgItemText(dlg,TXT_PAD1,ESI_Name(SI_GAMEPAD));
SetDlgItemText(dlg,TXT_PAD2,ESI_Name(SI_GAMEPAD));
}
}
//Callback function of the input configuration dialog.
BOOL CALLBACK InputConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
const unsigned int NUMBER_OF_PORTS = 2;
const char * const nes_description[6] = {
"<none>",
"Gamepad",
"Zapper",
"Power Pad A",
"Power Pad B",
"Arkanoid Paddle"
};
const unsigned int NUMBER_OF_NES_DEVICES = sizeof(nes_description) / sizeof(*nes_description);
const char * const famicom_description[14] =
switch(uMsg)
{
"<none>",
"Arkanoid Paddle",
"Hyper Shot gun",
"4-Player Adapter",
"Family Keyboard",
"Subor Keyboard",
"HyperShot Pads",
"Mahjong",
"Quiz King Buzzers",
"Family Trainer A",
"Family Trainer B",
"Oeka Kids Tablet",
"Barcode World",
"Top Rider"};
case WM_INITDIALOG:
// Update the disable UDLR checkbox based on the current value
CheckDlgButton(hwndDlg,BTN_ALLOW_LRUD,allowUDLR?BST_CHECKED:BST_UNCHECKED);
const static unsigned int NUMBER_OF_FAMICOM_DEVICES = sizeof(famicom_description) / sizeof(*famicom_description);
//update the fourscore checkbox
CheckDlgButton(hwndDlg,CHECK_ENABLE_FOURSCORE,(eoptions & EO_FOURSCORE)?BST_CHECKED:BST_UNCHECKED);
static const int configurable_nes[6]= { 0, 1, 0, 1, 1, 0 };
static const int configurable_fam[14]= { 0,0,0,0, 1,1,0,1, 1,1,1,0, 0,0 };
const unsigned int FAMICOM_POSITION = 2;
switch(uMsg)
// Initialize the controls for the input ports
for(unsigned int port = 0; port < NUMBER_OF_PORTS; port++)
{
case WM_INITDIALOG:
// Update the disable UDLR checkbox based on the current value
CheckDlgButton(hwndDlg,BTN_ALLOW_LRUD,allowUDLR?BST_CHECKED:BST_UNCHECKED);
// Initialize the controls for the input ports
for(unsigned int port = 0; port < NUMBER_OF_PORTS; port++)
// Initialize the combobox
for(unsigned int current_device = 0; current_device < NUMBER_OF_NES_DEVICES; current_device++)
{
// Initialize the combobox
for(unsigned int current_device = 0; current_device < NUMBER_OF_NES_DEVICES; current_device++)
{
SendDlgItemMessage(hwndDlg,
COMBO_PAD1 + port,
CB_ADDSTRING, 0,
(LPARAM)(LPSTR)nes_description[current_device]
);
}
// Update the combobox selection according to the
// currently selected input mode.
SendDlgItemMessage(hwndDlg,
COMBO_PAD1 + port,
CB_SETCURSEL,
InputType[port],
(LPARAM)(LPSTR)0
);
// Enable the configuration button if necessary.
EnableWindow(
GetDlgItem(hwndDlg, BTN_PORT1 + port),
configurable_nes[InputType[port]]
);
// Update the label that displays the input device.
SetDlgItemText(
hwndDlg,
TXT_PAD1 + port,
(LPTSTR)nes_description[InputType[port]]
);
}
// Initialize the Famicom combobox
for(unsigned current_device = 0; current_device < NUMBER_OF_FAMICOM_DEVICES; current_device++)
{
SendDlgItemMessage(
hwndDlg,
COMBO_FAM,
CB_ADDSTRING,
0,
(LPARAM)(LPSTR)famicom_description[current_device]
CB_ADDSTRING, 0,
(LPARAM)(LPSTR)ESI_Name((ESI)current_device)
);
}
// Update the combobox selection according to the
// currently selected input mode.
SendDlgItemMessage(
hwndDlg,
COMBO_FAM,
SendDlgItemMessage(hwndDlg,
COMBO_PAD1 + port,
CB_SETCURSEL,
InputType[FAMICOM_POSITION],
InputType[port],
(LPARAM)(LPSTR)0
);
// Enable the configuration button if necessary.
EnableWindow(
GetDlgItem(hwndDlg, BTN_FAM),
configurable_fam[InputType[FAMICOM_POSITION]]
GetDlgItem(hwndDlg, BTN_PORT1 + port),
configurable_nes[InputType[port]]
);
// Update the label that displays the input device.
SetDlgItemText(
hwndDlg,
TXT_FAM,
(LPTSTR)famicom_description[InputType[FAMICOM_POSITION]]
TXT_PAD1 + port,
(LPTSTR)ESI_Name((ESI)InputType[port])
);
// Initialize the auto key controls
extern int autoHoldKey, autoHoldClearKey;
char btext[128];
if(autoHoldKey)
{
if(!GetKeyNameText(autoHoldKey << 16, btext, 128))
{
sprintf(btext, "KB: %d", autoHoldKey);
}
}
else
{
sprintf(btext, "not assigned");
}
SetDlgItemText(hwndDlg, LBL_AUTO_HOLD, btext);
if(autoHoldClearKey)
{
if(!GetKeyNameText(autoHoldClearKey << 16, btext, 128))
{
sprintf(btext, "KB: %d", autoHoldClearKey);
}
}
else
{
sprintf(btext, "not assigned");
}
SetDlgItemText(hwndDlg, LBL_CLEAR_AH, btext);
CenterWindowOnScreen(hwndDlg);
break;
case WM_CLOSE:
case WM_QUIT:
EndDialog(hwndDlg, 0);
case WM_COMMAND:
// Handle disable UD/LR option
if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == BTN_ALLOW_LRUD)
{
FCEU_printf("Allow UDLR toggled.\n");
allowUDLR = !allowUDLR;
}
if(HIWORD(wParam) == CBN_SELENDOK)
{
switch(LOWORD(wParam))
{
case COMBO_PAD1:
case COMBO_PAD2:
{
unsigned int sel_input = LOWORD(wParam) - COMBO_PAD1;
// Update the user input type
InputType[sel_input] =
SendDlgItemMessage(
hwndDlg,
LOWORD(wParam),
CB_GETCURSEL,
0,
(LPARAM)(LPSTR)0
);
// Enable or disable the configuration button
EnableWindow(
GetDlgItem(hwndDlg, LOWORD(wParam) + 2),
configurable_nes[InputType[sel_input]]
);
// Update the text field
SetDlgItemText(
hwndDlg,
TXT_PAD1 + sel_input,
(LPTSTR)nes_description[InputType[sel_input]]
);
}
break;
case COMBO_FAM:
// Update the user input type of the famicom
InputType[FAMICOM_POSITION] =
SendDlgItemMessage(
hwndDlg,
COMBO_FAM,
CB_GETCURSEL,
0,
(LPARAM)(LPSTR)0
);
// Enable or disable the configuration button
EnableWindow(
GetDlgItem(hwndDlg, BTN_FAM),
configurable_fam[InputType[FAMICOM_POSITION]]
);
// Update the text field
SetDlgItemText(
hwndDlg,
TXT_FAM,
(LPTSTR)famicom_description[InputType[FAMICOM_POSITION]]
);
break;
}
}
if( !(wParam >> 16) )
{
switch(wParam & 0xFFFF)
{
case BTN_FAM:
{
const char *text = famicom_description[InputType[FAMICOM_POSITION]];
DoTBType = DoTBPort = 0;
switch(InputType[FAMICOM_POSITION])
{
case SIFC_FTRAINERA:
case SIFC_FTRAINERB:
DoTBConfig(hwndDlg, text, "POWERPADDIALOG", FTrainerButtons, 12);
break;
case SIFC_FKB:
DoTBConfig(hwndDlg, text, "FKBDIALOG", fkbmap, 0x48);
break;
case SIFC_SUBORKB:
DoTBConfig(hwndDlg, text, "SUBORKBDIALOG", suborkbmap, 0x60);
break;
case SIFC_MAHJONG:
DoTBConfig(hwndDlg, text, "MAHJONGDIALOG", MahjongButtons, 21);
break;
case SIFC_QUIZKING:
DoTBConfig(hwndDlg, text, "QUIZKINGDIALOG", QuizKingButtons, 6);
break;
}
}
break;
case BTN_PORT2:
case BTN_PORT1:
{
int which = (wParam & 0xFFFF) - BTN_PORT1;
const char *text = nes_description[InputType[which]];
DoTBType = DoTBPort = 0;
switch(InputType[which])
{
case SI_GAMEPAD:
{
ButtConfig tmp[10 + 10];
memcpy(tmp, GamePadConfig[which], 10 * sizeof(ButtConfig));
memcpy(&tmp[10], GamePadConfig[which + 2], 10 * sizeof(ButtConfig));
DoTBType = SI_GAMEPAD;
DoTBPort = which;
DoTBConfig(hwndDlg, text, "GAMEPADDIALOG", tmp, 10 + 10);
memcpy(GamePadConfig[which], tmp, 10 * sizeof(ButtConfig));
memcpy(GamePadConfig[which + 2], &tmp[10], 10 * sizeof(ButtConfig));
}
break;
case SI_POWERPADA:
case SI_POWERPADB:
DoTBConfig(hwndDlg, text, "POWERPADDIALOG", powerpadsc[which], 12);
break;
}
}
break;
case BTN_PRESET_SET1:
MessageBox(0, "Current input configuration has been set as Preset 1.", "FCE Ultra Message", MB_ICONINFORMATION | MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
memcpy(GamePadPreset1, GamePadConfig, sizeof(GamePadConfig));
break;
case BTN_PRESET_SET2:
MessageBox(0, "Current input configuration has been set as Preset 2.", "FCE Ultra Message", MB_ICONINFORMATION | MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
memcpy(GamePadPreset2, GamePadConfig, sizeof(GamePadConfig));
break;
case BTN_PRESET_SET3:
MessageBox(0, "Current input configuration has been set as Preset 3.", "FCE Ultra Message", MB_ICONINFORMATION | MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
memcpy(GamePadPreset3, GamePadConfig, sizeof(GamePadConfig));
break;
case BTN_PRESET_EXPORT1: PresetExport(1); break;
case BTN_PRESET_EXPORT2: PresetExport(2); break;
case BTN_PRESET_EXPORT3: PresetExport(3); break;
case BTN_PRESET_IMPORT1: PresetImport(1); break;
case BTN_PRESET_IMPORT2: PresetImport(2); break;
case BTN_PRESET_IMPORT3: PresetImport(3); break;
case BTN_AUTO_HOLD: // auto-hold button
{
char btext[128] = { 0 };
GetDlgItemText(hwndDlg, BTN_AUTO_HOLD, btext, sizeof(btext) );
int button = DWaitSimpleButton(hwndDlg, (uint8*)btext); //mbg merge 7/17/06
if(button)
{
if(!GetKeyNameText(button << 16, btext, 128))
{
sprintf(btext, "KB: %d", button);
}
}
else
{
sprintf(btext, "not assigned");
}
extern int autoHoldKey;
autoHoldKey = button;
SetDlgItemText(hwndDlg, LBL_AUTO_HOLD, btext);
}
break;
case BTN_CLEAR_AH: // auto-hold clear button
{
char btext[128] = { 0 };
GetDlgItemText(hwndDlg, BTN_CLEAR_AH, btext, 128);
int button = DWaitSimpleButton(hwndDlg, (uint8*)btext); //mbg merge 7/17/06 added cast
if(button)
{
if( !GetKeyNameText(button << 16, btext, sizeof(btext)))
{
sprintf(btext, "KB: %d", button);
}
}
else
{
sprintf(btext, "not assigned");
}
extern int autoHoldClearKey;
autoHoldClearKey = button;
SetDlgItemText(hwndDlg, LBL_CLEAR_AH, btext);
}
break;
case BTN_CLOSE:
EndDialog(hwndDlg, 0);
break;
}
}
}
return 0;
// Initialize the Famicom combobox
for(unsigned current_device = 0; current_device < NUMBER_OF_FAMICOM_DEVICES; current_device++)
{
SendDlgItemMessage(
hwndDlg,
COMBO_FAM,
CB_ADDSTRING,
0,
(LPARAM)(LPSTR)ESIFC_Name((ESIFC)current_device)
);
}
// Update the combobox selection according to the
// currently selected input mode.
SendDlgItemMessage(
hwndDlg,
COMBO_FAM,
CB_SETCURSEL,
InputType[FAMICOM_POSITION],
(LPARAM)(LPSTR)0
);
// Enable the configuration button if necessary.
EnableWindow(
GetDlgItem(hwndDlg, BTN_FAM),
configurable_fam[InputType[FAMICOM_POSITION]]
);
// Update the label that displays the input device.
SetDlgItemText(
hwndDlg,
TXT_FAM,
(LPTSTR)ESIFC_Name((ESIFC)InputType[FAMICOM_POSITION])
);
// Initialize the auto key controls
extern int autoHoldKey, autoHoldClearKey;
char btext[128];
if(autoHoldKey)
{
if(!GetKeyNameText(autoHoldKey << 16, btext, 128))
{
sprintf(btext, "KB: %d", autoHoldKey);
}
}
else
{
sprintf(btext, "not assigned");
}
SetDlgItemText(hwndDlg, LBL_AUTO_HOLD, btext);
if(autoHoldClearKey)
{
if(!GetKeyNameText(autoHoldClearKey << 16, btext, 128))
{
sprintf(btext, "KB: %d", autoHoldClearKey);
}
}
else
{
sprintf(btext, "not assigned");
}
SetDlgItemText(hwndDlg, LBL_CLEAR_AH, btext);
CenterWindowOnScreen(hwndDlg);
UpdateFourscoreState(hwndDlg);
break;
case WM_CLOSE:
case WM_QUIT:
EndDialog(hwndDlg, 0);
case WM_COMMAND:
// Handle disable UD/LR option
if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == BTN_ALLOW_LRUD)
{
FCEU_printf("Allow UDLR toggled.\n");
allowUDLR = !allowUDLR;
}
//Handle the fourscore button
if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == CHECK_ENABLE_FOURSCORE)
{
eoptions ^= EO_FOURSCORE;
FCEU_printf("Fourscore toggled to \n",(eoptions & EO_FOURSCORE)?"ON":"OFF");
UpdateFourscoreState(hwndDlg);
}
if(HIWORD(wParam) == CBN_SELENDOK)
{
switch(LOWORD(wParam))
{
case COMBO_PAD1:
case COMBO_PAD2:
UpdateComboPad(hwndDlg, LOWORD(wParam));
break;
case COMBO_FAM:
UpdateComboFam(hwndDlg);
break;
}
}
if( !(wParam >> 16) )
{
switch(wParam & 0xFFFF)
{
case BTN_FAM:
{
const char *text = ESI_Name((ESI)InputType[FAMICOM_POSITION]);
DoTBType = DoTBPort = 0;
switch(InputType[FAMICOM_POSITION])
{
case SIFC_FTRAINERA:
case SIFC_FTRAINERB:
DoTBConfig(hwndDlg, text, "POWERPADDIALOG", FTrainerButtons, 12);
break;
case SIFC_FKB:
DoTBConfig(hwndDlg, text, "FKBDIALOG", fkbmap, 0x48);
break;
case SIFC_SUBORKB:
DoTBConfig(hwndDlg, text, "SUBORKBDIALOG", suborkbmap, 0x60);
break;
case SIFC_MAHJONG:
DoTBConfig(hwndDlg, text, "MAHJONGDIALOG", MahjongButtons, 21);
break;
case SIFC_QUIZKING:
DoTBConfig(hwndDlg, text, "QUIZKINGDIALOG", QuizKingButtons, 6);
break;
}
}
break;
case BTN_PORT2:
case BTN_PORT1:
{
int which = (wParam & 0xFFFF) - BTN_PORT1;
const char *text = ESI_Name((ESI)InputType[which]);
DoTBType = DoTBPort = 0;
switch(InputType[which])
{
case SI_GAMEPAD:
{
ButtConfig tmp[10 + 10];
memcpy(tmp, GamePadConfig[which], 10 * sizeof(ButtConfig));
memcpy(&tmp[10], GamePadConfig[which + 2], 10 * sizeof(ButtConfig));
DoTBType = SI_GAMEPAD;
DoTBPort = which;
DoTBConfig(hwndDlg, text, "GAMEPADDIALOG", tmp, 10 + 10);
memcpy(GamePadConfig[which], tmp, 10 * sizeof(ButtConfig));
memcpy(GamePadConfig[which + 2], &tmp[10], 10 * sizeof(ButtConfig));
}
break;
case SI_POWERPADA:
case SI_POWERPADB:
DoTBConfig(hwndDlg, text, "POWERPADDIALOG", powerpadsc[which], 12);
break;
}
}
break;
case BTN_PRESET_SET1:
MessageBox(0, "Current input configuration has been set as Preset 1.", "FCE Ultra Message", MB_ICONINFORMATION | MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
memcpy(GamePadPreset1, GamePadConfig, sizeof(GamePadConfig));
break;
case BTN_PRESET_SET2:
MessageBox(0, "Current input configuration has been set as Preset 2.", "FCE Ultra Message", MB_ICONINFORMATION | MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
memcpy(GamePadPreset2, GamePadConfig, sizeof(GamePadConfig));
break;
case BTN_PRESET_SET3:
MessageBox(0, "Current input configuration has been set as Preset 3.", "FCE Ultra Message", MB_ICONINFORMATION | MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
memcpy(GamePadPreset3, GamePadConfig, sizeof(GamePadConfig));
break;
case BTN_PRESET_EXPORT1: PresetExport(1); break;
case BTN_PRESET_EXPORT2: PresetExport(2); break;
case BTN_PRESET_EXPORT3: PresetExport(3); break;
case BTN_PRESET_IMPORT1: PresetImport(1); break;
case BTN_PRESET_IMPORT2: PresetImport(2); break;
case BTN_PRESET_IMPORT3: PresetImport(3); break;
case BTN_AUTO_HOLD: // auto-hold button
{
char btext[128] = { 0 };
GetDlgItemText(hwndDlg, BTN_AUTO_HOLD, btext, sizeof(btext) );
int button = DWaitSimpleButton(hwndDlg, (uint8*)btext); //mbg merge 7/17/06
if(button)
{
if(!GetKeyNameText(button << 16, btext, 128))
{
sprintf(btext, "KB: %d", button);
}
}
else
{
sprintf(btext, "not assigned");
}
extern int autoHoldKey;
autoHoldKey = button;
SetDlgItemText(hwndDlg, LBL_AUTO_HOLD, btext);
}
break;
case BTN_CLEAR_AH: // auto-hold clear button
{
char btext[128] = { 0 };
GetDlgItemText(hwndDlg, BTN_CLEAR_AH, btext, 128);
int button = DWaitSimpleButton(hwndDlg, (uint8*)btext); //mbg merge 7/17/06 added cast
if(button)
{
if( !GetKeyNameText(button << 16, btext, sizeof(btext)))
{
sprintf(btext, "KB: %d", button);
}
}
else
{
sprintf(btext, "not assigned");
}
extern int autoHoldClearKey;
autoHoldClearKey = button;
SetDlgItemText(hwndDlg, LBL_CLEAR_AH, btext);
}
break;
case BTN_CLOSE:
EndDialog(hwndDlg, 0);
break;
}
}
}
return 0;
}
//Shows the input configuration dialog.
@ -1431,9 +1447,9 @@ void FCEUI_UseInputPreset(int preset)
{
switch(preset)
{
case 0: memcpy(GamePadConfig, GamePadPreset1, sizeof(GamePadPreset1)); break;
case 1: memcpy(GamePadConfig, GamePadPreset2, sizeof(GamePadPreset2)); break;
case 2: memcpy(GamePadConfig, GamePadPreset3, sizeof(GamePadPreset3)); break;
case 0: memcpy(GamePadConfig, GamePadPreset1, sizeof(GamePadPreset1)); break;
case 1: memcpy(GamePadConfig, GamePadPreset2, sizeof(GamePadPreset2)); break;
case 2: memcpy(GamePadConfig, GamePadPreset3, sizeof(GamePadPreset3)); break;
}
FCEU_DispMessage("Using input preset %d.",preset+1);
}

View File

@ -58,7 +58,7 @@ void ParseGIInput(FCEUGI *GameInfo);
#define FCFGD_HYPERSHOT 3
#define FCFGD_QUIZKING 4
void InitInputPorts(void);
void InitInputPorts();
void SetEmulationSpeed(int type);
int FCEUD_TestCommandState(int c);
void FCEUD_UpdateInput();

View File

@ -7,8 +7,7 @@
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
@ -325,8 +324,6 @@ BEGIN
PUSHBUTTON "A",310,195,138,16,12
PUSHBUTTON "Turbo B",319,154,122,32,12
PUSHBUTTON "Turbo A",318,195,122,32,12
CONTROL "Disable four-score emulation.",CHECK_DISABLE_FOURSCORE,
"Button",BS_AUTOCHECKBOX,9,193,106,12
END
GUICONFIG DIALOGEX 16, 123, 184, 90
@ -344,48 +341,50 @@ BEGIN
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,53,164,12
END
INPUTCONFIG DIALOGEX 122, 105, 349, 187
INPUTCONFIG DIALOGEX 122, 105, 349, 199
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Input Configuration"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
GROUPBOX "Port 1:",102,20,19,152,50
COMBOBOX COMBO_PAD1,27,47,71,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "Configure",BTN_PORT1,109,33,56,14
GROUPBOX "Port 2:",103,176,19,152,50
COMBOBOX COMBO_PAD2,183,47,71,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "Configure",BTN_PORT2,265,33,56,14
GROUPBOX "NES-style Input Ports",108,10,8,328,71
GROUPBOX "Famicom Expansion Port:",109,176,82,162,50
COMBOBOX COMBO_FAM,183,111,84,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "Configure",BTN_FAM,275,98,56,14
CONTROL "",65487,"Static",SS_BLACKFRAME,27,31,71,12
CONTROL "",65486,"Static",SS_BLACKFRAME,183,31,71,12
CONTROL "",65485,"Static",SS_BLACKFRAME,183,95,84,12
CTEXT "",TXT_PAD1,30,32,65,10
CTEXT "",TXT_PAD2,186,32,65,10
CTEXT "",TXT_FAM,186,96,78,10
PUSHBUTTON "Set",BTN_AUTO_HOLD,19,146,45,13
LTEXT "not assigned",LBL_AUTO_HOLD,71,148,87,8
PUSHBUTTON "Clear",BTN_CLEAR_AH,19,161,45,13
LTEXT "not assigned",LBL_CLEAR_AH,71,163,87,8
DEFPUSHBUTTON "Close",BTN_CLOSE,282,166,56,14
GROUPBOX "Input Presets",113,10,82,162,50
CONTROL "Allow Left+Right / Up+Down",BTN_ALLOW_LRUD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,146,107,10
PUSHBUTTON "Set",BTN_PRESET_SET1,34,92,37,11
PUSHBUTTON "Set",BTN_PRESET_SET2,34,104,37,11
PUSHBUTTON "Set",BTN_PRESET_SET3,34,116,37,11
PUSHBUTTON "Import",BTN_PRESET_IMPORT1,84,92,37,11
PUSHBUTTON "Import",BTN_PRESET_IMPORT2,84,104,37,11
PUSHBUTTON "Import",BTN_PRESET_IMPORT3,84,116,37,11
PUSHBUTTON "Export",BTN_PRESET_EXPORT1,123,92,37,11
PUSHBUTTON "Export",BTN_PRESET_EXPORT2,123,104,37,11
PUSHBUTTON "Export",BTN_PRESET_EXPORT3,123,116,37,11
GROUPBOX "Auto-Hold",118,10,135,162,44
GROUPBOX "Emulation",119,176,135,162,25
CTEXT "1",IDC_STATIC,18,94,8,8
CTEXT "2",IDC_STATIC,18,105,8,8
CTEXT "3",IDC_STATIC,18,117,8,8
GROUPBOX "Port 1:",102,20,31,152,50
COMBOBOX COMBO_PAD1,27,57,71,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "Configure",BTN_PORT1,109,43,56,14
GROUPBOX "Port 2:",103,176,31,152,50
COMBOBOX COMBO_PAD2,183,57,71,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "Configure",BTN_PORT2,265,41,56,14
GROUPBOX "NES-style Input Ports",108,10,8,328,83
GROUPBOX "Famicom Expansion Port:",109,176,93,162,50
COMBOBOX COMBO_FAM,183,122,84,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "Configure",BTN_FAM,275,105,56,14
CONTROL "",65487,"Static",SS_BLACKFRAME,27,41,71,12
CONTROL "",65486,"Static",SS_BLACKFRAME,183,41,71,12
CONTROL "",65485,"Static",SS_BLACKFRAME,183,106,84,12
CTEXT "",TXT_PAD1,30,42,65,10
CTEXT "",TXT_PAD2,186,42,65,10
CTEXT "",TXT_FAM,186,107,78,10
PUSHBUTTON "Set",BTN_AUTO_HOLD,19,157,45,13
LTEXT "not assigned",LBL_AUTO_HOLD,71,159,87,8
PUSHBUTTON "Clear",BTN_CLEAR_AH,19,172,45,13
LTEXT "not assigned",LBL_CLEAR_AH,71,174,87,8
DEFPUSHBUTTON "Close",BTN_CLOSE,282,177,56,14
GROUPBOX "Input Presets",113,10,93,162,50
CONTROL "Allow Left+Right / Up+Down",BTN_ALLOW_LRUD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,157,107,10
PUSHBUTTON "Set",BTN_PRESET_SET1,34,103,37,11
PUSHBUTTON "Set",BTN_PRESET_SET2,34,115,37,11
PUSHBUTTON "Set",BTN_PRESET_SET3,34,127,37,11
PUSHBUTTON "Import",BTN_PRESET_IMPORT1,84,103,37,11
PUSHBUTTON "Import",BTN_PRESET_IMPORT2,84,115,37,11
PUSHBUTTON "Import",BTN_PRESET_IMPORT3,84,127,37,11
PUSHBUTTON "Export",BTN_PRESET_EXPORT1,123,103,37,11
PUSHBUTTON "Export",BTN_PRESET_EXPORT2,123,115,37,11
PUSHBUTTON "Export",BTN_PRESET_EXPORT3,123,127,37,11
GROUPBOX "Auto-Hold",118,10,146,162,44
GROUPBOX "Emulation",119,176,146,162,25
CTEXT "1",IDC_STATIC,18,105,8,8
CTEXT "2",IDC_STATIC,18,116,8,8
CTEXT "3",IDC_STATIC,18,128,8,8
CONTROL "Attach four-score (implies four gamepads)",CHECK_ENABLE_FOURSCORE,
"Button",BS_AUTOCHECKBOX,18,18,142,12
END
MAHJONGDIALOG DIALOG 65510, 106, 340, 110
@ -1261,7 +1260,7 @@ BEGIN
LEFTMARGIN, 10
RIGHTMARGIN, 338
TOPMARGIN, 8
BOTTOMMARGIN, 179
BOTTOMMARGIN, 191
END
"NETMOO", DIALOG
@ -1603,8 +1602,7 @@ IDB_TE_ARROW BITMAP "res/te_arrow.bmp"
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -252,6 +252,7 @@
#define IDC_WINSIZE_MUL_X 400
#define IDC_CHEAT_CHECK_NE_BY 401
#define IDC_WINSIZE_MUL_Y 401
#define CHECK_ENABLE_FOURSCORE 401
#define IDC_CHEAT_CHECK_GT_BY 402
#define IDC_FORCE_INT_VIDEO_SCALARS 402
#define IDC_CHEAT_CHECK_LT_BY 403

File diff suppressed because it is too large Load Diff

View File

@ -594,12 +594,12 @@ void RestartMovieOrReset(unsigned int do_power_off)
void ResetNES(void)
{
FCEUMOV_AddCommand(FCEUNPCMD_RESET);
if(!GameInfo) return;
GameInterface(GI_RESETM2);
FCEUSND_Reset();
FCEUPPU_Reset();
X6502_Reset();
FCEUMOV_AddCommand(FCEUNPCMD_RESET);
if(!GameInfo) return;
GameInterface(GI_RESETM2);
FCEUSND_Reset();
FCEUPPU_Reset();
X6502_Reset();
// clear back baffer
extern uint8 *XBackBuf;

View File

@ -35,9 +35,29 @@ enum ESI
SI_POWERPADA = 3,
SI_POWERPADB = 4,
SI_ARKANOID = 5,
SI_MOUSE = 6 //mbg merge 7/17/06 added
SI_MOUSE = 6,
SI_COUNT = SI_MOUSE
};
inline const char* ESI_Name(ESI esi)
{
static const char * const names[] =
{
"<none>",
"Gamepad",
"Zapper",
"Power Pad A",
"Power Pad B",
"Arkanoid Paddle"
};
if(esi >= SI_NONE && esi < SI_COUNT)
return names[esi];
else return "<invalid ESI>";
}
//input device types for the expansion port
enum ESIFC
{
@ -56,11 +76,41 @@ enum ESIFC
SIFC_OEKAKIDS = 11,
SIFC_BWORLD = 12,
SIFC_TOPRIDER = 13,
SIFC_COUNT = SIFC_TOPRIDER
};
inline const char* ESIFC_Name(ESIFC esifc)
{
static const char * const names[] =
{
"<none>",
"Arkanoid Paddle",
"Hyper Shot gun",
"4-Player Adapter",
"Family Keyboard",
"Subor Keyboard",
"HyperShot Pads",
"Mahjong",
"Quiz King Buzzers",
"Family Trainer A",
"Family Trainer B",
"Oeka Kids Tablet",
"Barcode World",
"Top Rider"
};
if(esifc >= SIFC_NONE && esifc < SIFC_COUNT)
return names[esifc];
else return "<invalid ESIFC>";
}
#include "utils/md5.h"
typedef struct {
typedef struct
{
uint8 *name; //Game name, UTF8 encoding
EGIT type;

View File

@ -82,7 +82,8 @@ uint8 FCEU_GetJoyJoy(void)
extern uint8 coinon;
static bool FSDisable=false; // Set to true if NES-style four-player adapter is disabled.
//set to true if the fourscore is attached
static bool FSAttached = false;
JOYPORT joyports[2] = { JOYPORT(0), JOYPORT(1) };
FCPORT portFC;
@ -93,6 +94,11 @@ static DECLFR(JPRead)
ret|=joyports[A&1].driver->Read(A&1);
if(!(A&1) && ret)
{
int zzz=9;
}
if(portFC.driver)
ret = portFC.driver->Read(A&1,ret);
@ -120,7 +126,7 @@ static DECLFW(B4016)
//mbg 6/7/08 - I guess he means that the input drivers could track the strobing themselves
//I dont see why it is unreasonable here.
for(int i=0;i<2;i++)
joyports[i].driver->Strobe(0);
joyports[i].driver->Strobe(i);
if(portFC.driver)
portFC.driver->Strobe();
}
@ -225,7 +231,7 @@ static uint8 ReadGP(int w)
else
ret = ((joy[w]>>(joy_readbit[w]))&1);
if(joy_readbit[w]>=16) ret=0;
if(FSDisable)
if(!FSAttached)
{
if(joy_readbit[w]>=8) ret|=1;
}
@ -486,10 +492,13 @@ void InitializeInput(void)
}
void FCEUI_DisableFourScore(bool disabled)
bool FCEUI_GetInputFourscore()
{
FSDisable = disabled;
return FSAttached;
}
void FCEUI_SetInputFourscore(bool attachFourscore)
{
FSAttached = attachFourscore;
}
SFORMAT FCEUCTRL_STATEINFO[]={

View File

@ -25,7 +25,7 @@
#include "zapper.h"
#include "../movie.h"
extern ZAPPER ZD[2];
static ZAPPER ZD[2];
static void ZapperFrapper(int w, uint8 *bg, uint8 *spr, uint32 linets, int final)
{

View File

@ -10,6 +10,4 @@ struct ZAPPER
uint64 zaphit;
};
static ZAPPER ZD[2];
#endif

View File

@ -93,41 +93,105 @@ void MovieData::TryDumpIncremental()
}
const char MovieRecord::mnemonics[8] = {'A','B','S','T','U','D','L','R'};
void MovieRecord::dump(std::ostream* os, int index)
void MovieRecord::dumpJoy(std::ostream* os, uint8 joystate)
{
//these are mnemonics for each joystick bit.
//since we usually use the regular joypad, these will be more helpful.
//but any character other than ' ' should count as a set bit
//maybe other input types will need to be encoded another way..
for(int bit=7;bit>=0;bit--)
{
int bitmask = (1<<bit);
char mnemonic = mnemonics[bit];
//if the bit is set write the mnemonic
if(joystate & bitmask)
os->put(mnemonic);
else //otherwise write a space
os->put(' ');
}
}
void MovieRecord::parseJoy(std::istream* is, uint8& joystate)
{
joystate = 0;
for(int bit=7;bit>=0;bit--)
{
int c = is->get();
if(c == -1)
return;
if(c != ' ')
joystate |= (1<<bit);
}
}
void MovieRecord::parse(MovieData* md, std::istream* is)
{
//by the time we get in here, the initial pipe has already been extracted
//a special case: if fourscore is enabled, parse four gamepads
if(md->fourscore)
{
parseJoy(is,joysticks[0]); is->get(); //eat the pipe
parseJoy(is,joysticks[1]); is->get(); //eat the pipe
parseJoy(is,joysticks[2]); is->get(); //eat the pipe
parseJoy(is,joysticks[3]); is->get(); //eat the pipe
}
else
{
for(int port=0;port<2;port++)
{
if(md->ports[port] == SI_GAMEPAD)
parseJoy(is, joysticks[port]);
else if(md->ports[port] == SI_ZAPPER)
{
int x,y,b;
*is >> x >> y >> b;
zappers[port].x = x;
zappers[port].y = y;
zappers[port].b = b;
}
is->get(); //eat the pipe
}
}
//(no fcexp data is logged right now)
is->get(); //eat the pipe
//should be left at a newline
}
void MovieRecord::dump(MovieData* md, std::ostream* os, int index)
{
//todo: if we want frame numbers in the output (which we dont since we couldnt cut and paste in movies)
//but someone would need to change the parser to ignore it
//fputc('|',fp);
//fprintf(fp,"%08d",index);
os->put('|');
//for each joystick
for(int i=0;i<4;i++)
//a special case: if fourscore is enabled, dump four gamepads
if(md->fourscore)
{
//these are mnemonics for each joystick bit.
//since we usually use the regular joypad, these will be more helpful.
//but any character other than ' ' should count as a set bit
//maybe other input types will need to be encoded another way..
for(int bit=7;bit>=0;bit--)
os->put('|');
dumpJoy(os,joysticks[0]); os->put('|');
dumpJoy(os,joysticks[1]); os->put('|');
dumpJoy(os,joysticks[2]); os->put('|');
dumpJoy(os,joysticks[3]); os->put('|');
}
else
{
for(int port=0;port<2;port++)
{
uint8 &joystate = joysticks[i];
int bitmask = (1<<bit);
char mnemonic = mnemonics[bit];
//if the bit is set write the mnemonic
if(joystate & bitmask)
os->put(mnemonic);
else //otherwise write a space
os->put(' ');
os->put('|');
if(md->ports[port] == SI_GAMEPAD)
dumpJoy(os, joysticks[port]);
else if(md->ports[port] == SI_ZAPPER)
*os << setw(3) << setfill('0') << (int)zappers[port].x << ' ' << setw(3) << setfill('0') << (int)zappers[port].y << setw(1) << ' ' << (int)zappers[port].b;
}
//separate the joysticks
os->put('|');
}
//write the zapper state
*os << setw(3) << setfill('0') << (int)zappers[0].x << ' ' << setw(3) << setfill('0') << (int)zappers[0].y << setw(1) << ' ' << (int)zappers[0].b << '|';
*os << setw(3) << setfill('0') << (int)zappers[1].x << ' ' << setw(3) << setfill('0') << (int)zappers[1].y << setw(1) << ' ' << (int)zappers[1].b;
//(no fcexp data is logged right now)
os->put('|');
//each frame is on a new line
os->put('\n');
@ -150,27 +214,42 @@ void MovieData::truncateAt(int frame)
records.resize(frame);
}
void MovieData::installDictionary(TDictionary& dictionary)
void MovieData::installValue(std::string& key, std::string& val)
{
dictionary.tryInstallInt("version",version);
dictionary.tryInstallInt("emuVersion",emuVersion);
dictionary.tryInstallInt("recordCount",recordCount);
dictionary.tryInstallBool("palFlag",palFlag);
dictionary.tryInstallBool("poweronFlag",poweronFlag);
dictionary.tryInstallBool("resetFlag",resetFlag);
dictionary.tryInstallString("romFilename",romFilename);
if(dictionary.containsKey("romChecksum"))
StringToBytes(dictionary["romChecksum"],&romChecksum,MD5DATA::size);
if(dictionary.containsKey("guid"))
guid = FCEU_Guid::fromString(dictionary["guid"]);
if(dictionary.containsKey("savestate"))
//todo - use another config system, or drive this from a little data structure. because this is gross
if(key == "version")
installInt(val,version);
else if(key == "emuVersion")
installInt(val,emuVersion);
else if(key == "recordCount")
installInt(val,recordCount);
else if(key == "palFlag")
installBool(val,palFlag);
else if(key == "poweronFlag")
installBool(val,poweronFlag);
else if(key == "resetFlag")
installBool(val,resetFlag);
else if(key == "romFilename")
romFilename = val;
else if(key == "romChecksum")
StringToBytes(val,&romChecksum,MD5DATA::size);
else if(key == "guid")
guid = FCEU_Guid::fromString(val);
else if(key == "fourscore")
installBool(val,fourscore);
else if(key == "port0")
installInt(val,ports[0]);
else if(key == "port1")
installInt(val,ports[1]);
else if(key == "port2")
installInt(val,ports[2]);
else if(key == "savestate")
{
std::string& str = dictionary["savestate"];
int len = HexStringToBytesLength(str);
int len = HexStringToBytesLength(val);
if(len >= 1)
{
savestate.resize(len);
StringToBytes(str,&savestate[0],len);
StringToBytes(val,&savestate[0],len);
}
}
}
@ -186,11 +265,15 @@ void MovieData::dump(std::ostream *os)
*os << "romFilename " << romFilename << endl;
*os << "romChecksum " << BytesToString(romChecksum.data,MD5DATA::size) << endl;
*os << "guid " << guid.toString() << endl;
*os << "fourscore " << (fourscore?1:0) << endl;
*os << "port0 " << ports[0] << endl;
*os << "port1 " << ports[1] << endl;
*os << "port2 " << ports[2] << endl;
if(savestate.size() != 0)
*os << "savestate " << BytesToString(&savestate[0],savestate.size()) << endl;
for(int i=0;i<(int)records.size();i++)
records[i].dump(os,i);
records[i].dump(this,os,i);
}
int MovieData::dumpLen()
@ -235,10 +318,8 @@ bool FCEUMOV_Mode(int modemask)
}
//yuck... another custom text parser.
void LoadFM2(MovieData& movieData, FILE *fp)
void LoadFM2(MovieData& movieData, std::istream* fp)
{
MovieData::TDictionary dictionary;
std::string key,value;
enum {
NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT
@ -247,7 +328,7 @@ void LoadFM2(MovieData& movieData, FILE *fp)
for(;;)
{
bool iswhitespace, isrecchar, isnewline;
int c = fgetc(fp);
int c = fp->get();
if(c == -1)
goto bail;
iswhitespace = (c==' '||c=='\t');
@ -269,33 +350,7 @@ void LoadFM2(MovieData& movieData, FILE *fp)
{
dorecord:
MovieRecord record;
//for each joystick
for(int i=0;i<4;i++)
{
uint8& joystate = record.joysticks[i];
joystate = 0;
for(int bit=7;bit>=0;bit--)
{
int c = fgetc(fp);
if(c == -1)
goto bail;
if(c != ' ')
joystate |= (1<<bit);
}
//eat the separator (a pipe or a newline)
fgetc(fp);
}
//crappy parser
char tmp[4] = {0,0,0,0};
fread(tmp,1,3,fp); record.zappers[0].x = atoi(tmp); fgetc(fp);
fread(tmp,1,3,fp); record.zappers[0].y = atoi(tmp); fgetc(fp);
tmp[1] = 0;
fread(tmp,1,1,fp); record.zappers[0].b = atoi(tmp); fgetc(fp);
fread(tmp,1,3,fp); record.zappers[1].x = atoi(tmp); fgetc(fp);
fread(tmp,1,3,fp); record.zappers[1].y = atoi(tmp); fgetc(fp);
tmp[1] = 0;
fread(tmp,1,1,fp); record.zappers[1].b = atoi(tmp); fgetc(fp);
record.parse(&movieData, fp);
movieData.records.push_back(record);
state = NEWLINE;
break;
@ -326,13 +381,11 @@ void LoadFM2(MovieData& movieData, FILE *fp)
bail = true;
if(state == VALUE) goto commit;
commit:
dictionary[key] = value;
movieData.installValue(key,value);
state = NEWLINE;
if(bail) break;
done: ;
}
movieData.installDictionary(dictionary);
}
@ -368,28 +421,6 @@ void FCEUI_StopMovie()
curMovieFilename[0] = 0;
}
void ParseGIInput(FCEUGI *GI); //mbg merge 7/17/06 - had to add. gross.
void InitOtherInput(void); //mbg merge 7/17/06 - had to add. gross.
//TODO - i dont think some of this like gametype and cspec are necessary
static void ResetInputTypes()
{
//#ifdef WIN32
// extern int UsrInputType[3];
// UsrInputType[0] = SI_GAMEPAD;
// UsrInputType[1] = SI_GAMEPAD;
// UsrInputType[2] = SIFC_NONE;
//
// ParseGIInput(NULL/*GameInfo*/);
// extern int cspec, gametype;
// cspec=GameInfo->cspecial;
// gametype=GameInfo->type;
//
// InitOtherInput();
//#endif
}
static void poweron(bool shouldDisableBatteryLoading)
{
// make a for-movie-recording power-on clear the game's save data, too
@ -435,7 +466,7 @@ void FCEUMOV_EnterTasEdit()
poweron(false);
//todo - think about this
ResetInputTypes();
//ResetInputTypes();
//pause the emulator
FCEUI_SetEmulationPaused(1);
@ -485,10 +516,11 @@ void FCEUI_LoadMovie(char *fname, bool _read_only, int _pauseframe)
currMovieData = MovieData();
strcpy(curMovieFilename, fname);
FILE* fp = FCEUD_UTF8fopen(fname, "rb");
std::fstream* fp = FCEUD_UTF8_fstream(fname, "rb");
if (!fp) return;
LoadFM2(currMovieData, fp);
fclose(fp);
fp->close();
delete fp;
// fully reload the game to reinitialize everything before playing any movie
// to try fixing nondeterministic playback of some games
@ -514,8 +546,8 @@ void FCEUI_LoadMovie(char *fname, bool _read_only, int _pauseframe)
else
FCEUI_SetVidSystem(0);
//we really need to research this...
ResetInputTypes();
//force the input configuration stored in the movie to apply
FCEUD_SetInput(currMovieData.fourscore,(ESI)currMovieData.ports[0],(ESI)currMovieData.ports[1],(ESIFC)currMovieData.ports[2]);
//stuff that should only happen when we're ready to positively commit to the replay
currFrameCounter = 0;
@ -577,6 +609,10 @@ void FCEUI_SaveMovie(char *fname, uint8 flags)
currMovieData.resetFlag = (flags & MOVIE_FLAG_FROM_RESET)!=0;
currMovieData.romChecksum = GameInfo->MD5;
currMovieData.romFilename = FileBase;
currMovieData.fourscore = FCEUI_GetInputFourscore();
currMovieData.ports[0] = joyports[0].type;
currMovieData.ports[1] = joyports[1].type;
currMovieData.ports[2] = portFC.type;
if(currMovieData.poweronFlag)
{
@ -591,7 +627,7 @@ void FCEUI_SaveMovie(char *fname, uint8 flags)
currMovieData.dump(osRecordingMovie);
//todo - think about this
ResetInputTypes();
//ResetInputTypes();
//todo - think about this
// trigger a reset
@ -653,7 +689,7 @@ void FCEUMOV_AddInputState()
joyports[0].log(&mr);
joyports[1].log(&mr);
mr.dump(osRecordingMovie,currMovieData.records.size());
mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size());
currMovieData.records.push_back(mr);
}
@ -715,20 +751,17 @@ bool FCEUMOV_ReadState(FILE* st, uint32 size)
load_successful = false;
//write the state to disk so we can reload
std::vector<uint8> buf(size);
std::vector<char> buf(size);
fread(&buf[0],1,size,st);
FILE* tmp = tmpfile();
fwrite(&buf[0],1,size,tmp);
//---------
//(debug)
//FILE* wtf = fopen("d:\\wtf.txt","wb");
//fwrite(&buf[0],1,size,wtf);
//fclose(wtf);
//---------
fseek(tmp,0,SEEK_SET);
memorystream mstemp(&buf);
MovieData tempMovieData = MovieData();
LoadFM2(tempMovieData, tmp);
fclose(tmp);
LoadFM2(tempMovieData, &mstemp);
//complex TAS logic for when a savestate is loaded:
//----------------
@ -867,15 +900,17 @@ void FCEUI_MoviePlayFromBeginning(void)
}
int FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* info)
bool FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* info)
{
memset(info,0,sizeof(MOVIE_INFO));
MovieData md;
FILE* fp = FCEUD_UTF8fopen(fname, "rb");
if(!fp) return 0;
std::fstream* fp = FCEUD_UTF8_fstream(fname, "rb");
if(!fp) return false;
LoadFM2(md, fp);
fclose(fp);
fp->close();
delete fp;
info->movie_version = md.version;
info->poweron = md.poweronFlag;
@ -889,7 +924,7 @@ int FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* info)
info->name_of_rom_used = md.romFilename;
info->rerecord_count = md.recordCount;
return 1;
return true;
}

View File

@ -27,7 +27,6 @@ bool FCEUMOV_Mode(int modemask);
bool FCEUMOV_ShouldPause(void);
int FCEUMOV_GetFrame(void);
//int FCEUMOV_WriteState(FILE* st);
int FCEUMOV_WriteState(std::ostream* os);
bool FCEUMOV_ReadState(FILE* st, uint32 size);
void FCEUMOV_PreLoad();
@ -36,9 +35,10 @@ bool FCEUMOV_PostLoad();
void FCEUMOV_EnterTasEdit();
void FCEUMOV_ExitTasEdit();
class MovieData;
class MovieRecord
{
public:
ValueArray<uint8,4> joysticks;
@ -79,8 +79,11 @@ public:
//a waste of memory in lots of cases.. maybe make it a pointer later?
std::vector<char> savestate;
void dump(std::ostream* os, int index);
void parse(MovieData* md, std::istream* is);
void dump(MovieData* md, std::ostream* os, int index);
void parseJoy(std::istream* is, uint8& joystate);
void dumpJoy(std::ostream* os, uint8 joystate);
static const char mnemonics[8];
private:
@ -106,6 +109,11 @@ public:
//this is the RERECORD COUNT. please rename variable.
int recordCount;
FCEU_Guid guid;
//which ports are defined for the movie
int ports[3];
//whether fourscore is enabled
bool fourscore;
//----TasEdit stuff---
int greenZoneCount;
@ -142,7 +150,7 @@ public:
};
void truncateAt(int frame);
void installDictionary(TDictionary& dictionary);
void installValue(std::string& key, std::string& val);
void dump(std::ostream* os);
int dumpLen();
void clearRecordRange(int start, int len);
@ -150,6 +158,17 @@ public:
static bool loadSavestateFrom(std::vector<char>* buf);
static void dumpSavestateTo(std::vector<char>* buf, int compressionLevel);
void TryDumpIncremental();
private:
void installInt(std::string& val, int& var)
{
var = atoi(val.c_str());
}
void installBool(std::string& val, bool& var)
{
var = atoi(val.c_str())!=0;
}
};
extern MovieData currMovieData;

View File

@ -31,9 +31,9 @@ private:
public:
memory_streambuf()
: buf(new T[capacity = 128])
: buf(new T[capacity = 128])
, myBuf(true)
, length(0)
, length(0)
, ww(0)
, usevec(0)
{
@ -42,8 +42,8 @@ public:
//constructs a non-expandable streambuf around the provided buffer
memory_streambuf(T* usebuf, int buflength)
: buf(usebuf)
, myBuf(false)
: buf(usebuf)
, myBuf(false)
, length(buflength)
, ww(0)
, usevec(0)
@ -53,10 +53,10 @@ public:
//constructs an expandable streambuf around the provided buffer
memory_streambuf(std::vector<T>* _usevec)
: capacity(_usevec->size())
, myBuf(false)
, length(_usevec->size())
, ww(0)
: capacity(_usevec->size())
, myBuf(false)
, length(_usevec->size())
, ww(0)
, usevec(_usevec)
{
if(length>0)

View File

@ -44,7 +44,7 @@
#include "nsf.h"
#include "input.h"
#include "vsuni.h"
#include "drawing.h"
#include "drawing.h"
#include "driver.h"
uint8 *XBuf=NULL;
@ -60,7 +60,7 @@ extern uint32 cur_input_display;
#ifdef _USE_SHARED_MEMORY_
HANDLE mapXBuf;
#endif
void FCEU_KillVirtualVideo(void)
{
//mbg merge TODO 7/17/06 temporarily removed