Fixed header editor bug, mappers>255 support were totally broken

This commit is contained in:
Alexey 'Cluster' Avdyukhin 2020-11-03 15:18:45 +03:00
parent 9471ff5e7b
commit 7e38d08bdb
1 changed files with 169 additions and 166 deletions

View File

@ -159,11 +159,11 @@ bool LoadHeader(HWND parent, iNES_HEADER* header)
error = errors::UNIF_HEADER; error = errors::UNIF_HEADER;
else if (!memcmp(header, "NESM", 4)) else if (!memcmp(header, "NESM", 4))
error = errors::NSF_HEADER; error = errors::NSF_HEADER;
/* else if (!memcmp(header, "NSFE", 4)) /* else if (!memcmp(header, "NSFE", 4))
error = errors::NSFE_HEADER; error = errors::NSFE_HEADER;
else if (!memcmp(header, "NESM\2", 4)) else if (!memcmp(header, "NESM\2", 4))
error = errors::NSF2_HEADER; error = errors::NSF2_HEADER;
*/ else */ else
error = errors::INVALID_HEADER; error = errors::INVALID_HEADER;
FCEU_fclose(fp); FCEU_fclose(fp);
} }
@ -174,27 +174,27 @@ bool LoadHeader(HWND parent, iNES_HEADER* header)
{ {
switch (error) switch (error)
{ {
case errors::OPEN_FAILED: case errors::OPEN_FAILED:
{ {
char buf[1024]; char buf[1024];
sprintf(buf, "Error opening %s!", LoadedRomFName); sprintf(buf, "Error opening %s!", LoadedRomFName);
MessageBox(parent, buf, "iNES Header Editor", MB_OK | MB_ICONERROR); MessageBox(parent, buf, "iNES Header Editor", MB_OK | MB_ICONERROR);
break; break;
} }
case errors::INVALID_HEADER: case errors::INVALID_HEADER:
MessageBox(parent, "Invalid iNES header.", "iNES Header Editor", MB_OK | MB_ICONERROR); MessageBox(parent, "Invalid iNES header.", "iNES Header Editor", MB_OK | MB_ICONERROR);
break; break;
case errors::FDS_HEADER: case errors::FDS_HEADER:
MessageBox(parent, "Editing header of an FDS file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR); MessageBox(parent, "Editing header of an FDS file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR);
break; break;
case errors::UNIF_HEADER: case errors::UNIF_HEADER:
MessageBox(parent, "Editing header of a UNIF file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR); MessageBox(parent, "Editing header of a UNIF file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR);
break; break;
case errors::NSF_HEADER: case errors::NSF_HEADER:
// case errors::NSF2_HEADER: // case errors::NSF2_HEADER:
// case errors::NSFE_HEADER: // case errors::NSFE_HEADER:
MessageBox(parent, "Editing header of an NSF file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR); MessageBox(parent, "Editing header of an NSF file is not supported.", "iNES Header Editor", MB_OK | MB_ICONERROR);
break; break;
} }
return false; return false;
} }
@ -502,85 +502,85 @@ INT_PTR CALLBACK HeaderEditorProc(HWND hDlg, UINT uMsg, WPARAM wP, LPARAM lP)
static iNES_HEADER* header; static iNES_HEADER* header;
switch (uMsg) { switch (uMsg) {
case WM_INITDIALOG: case WM_INITDIALOG:
{
header = (iNES_HEADER*)lP;
if (!header)
goto wm_close;
else
InitHeaderEditDialog(hDlg, header);
// Put the window aside the main window when in game.
if (GameInfo)
CalcSubWindowPos(hDlg, NULL);
}
break;
case WM_COMMAND:
switch (HIWORD(wP))
{ {
header = (iNES_HEADER*)lP; case BN_CLICKED:
if (!header) {
goto wm_close; int id = LOWORD(wP);
else switch (id)
InitHeaderEditDialog(hDlg, header);
// Put the window aside the main window when in game.
if (GameInfo)
CalcSubWindowPos(hDlg, NULL);
}
break;
case WM_COMMAND:
switch (HIWORD(wP))
{ {
case BN_CLICKED: case IDC_RADIO_VERSION_STANDARD:
ToggleINES20(hDlg, false);
break;
case IDC_RADIO_VERSION_INES20:
ToggleINES20(hDlg, true);
break;
case IDC_RADIO_SYSTEM_NORMAL:
case IDC_RADIO_SYSTEM_PLAYCHOICE10:
case IDC_RADIO_SYSTEM_EXTEND:
ToggleExtendSystemList(hDlg, IsDlgButtonChecked(hDlg, IDC_RADIO_SYSTEM_EXTEND) == BST_CHECKED);
case IDC_RADIO_SYSTEM_VS:
// Both ines 1.0 and 2.0 can trigger VS System, but only 2.0 enables the extra detailed properties
ToggleVSSystemGroup(hDlg, IsDlgButtonChecked(hDlg, IDC_RADIO_VERSION_INES20) == BST_CHECKED && IsDlgButtonChecked(hDlg, IDC_RADIO_SYSTEM_VS) == BST_CHECKED);
break;
case IDC_CHECK_UNOFFICIAL:
ToggleUnofficialPropertiesEnabled(hDlg, false, IsDlgButtonChecked(hDlg, IDC_CHECK_UNOFFICIAL) == BST_CHECKED);
break;
case IDC_CHECK_UNOFFICIAL_PRGRAM:
ToggleUnofficialPrgRamPresent(hDlg, false, true, IsDlgButtonChecked(hDlg, IDC_CHECK_UNOFFICIAL_PRGRAM) == BST_CHECKED);
break;
case IDC_CHECK_UNOFFICIAL_EXTRA_REGION:
ToggleUnofficialExtraRegionCode(hDlg, false, true, IsDlgButtonChecked(hDlg, IDC_CHECK_UNOFFICIAL_EXTRA_REGION) == BST_CHECKED);
break;
case IDC_RESTORE_BUTTON:
SetHeaderData(hDlg, header);
break;
case IDSAVE:
{
iNES_HEADER newHeader;
if (WriteHeaderData(hDlg, &newHeader))
{ {
int id = LOWORD(wP); char path[4096] = { 0 };
switch (id) if (ShowINESFileBox(hDlg, path, true))
{ SaveINESFile(hDlg, path, &newHeader);
case IDC_RADIO_VERSION_STANDARD:
ToggleINES20(hDlg, false);
break;
case IDC_RADIO_VERSION_INES20:
ToggleINES20(hDlg, true);
break;
case IDC_RADIO_SYSTEM_NORMAL:
case IDC_RADIO_SYSTEM_PLAYCHOICE10:
case IDC_RADIO_SYSTEM_EXTEND:
ToggleExtendSystemList(hDlg, IsDlgButtonChecked(hDlg, IDC_RADIO_SYSTEM_EXTEND) == BST_CHECKED);
case IDC_RADIO_SYSTEM_VS:
// Both ines 1.0 and 2.0 can trigger VS System, but only 2.0 enables the extra detailed properties
ToggleVSSystemGroup(hDlg, IsDlgButtonChecked(hDlg, IDC_RADIO_VERSION_INES20) == BST_CHECKED && IsDlgButtonChecked(hDlg, IDC_RADIO_SYSTEM_VS) == BST_CHECKED);
break;
case IDC_CHECK_UNOFFICIAL:
ToggleUnofficialPropertiesEnabled(hDlg, false, IsDlgButtonChecked(hDlg, IDC_CHECK_UNOFFICIAL) == BST_CHECKED);
break;
case IDC_CHECK_UNOFFICIAL_PRGRAM:
ToggleUnofficialPrgRamPresent(hDlg, false, true, IsDlgButtonChecked(hDlg, IDC_CHECK_UNOFFICIAL_PRGRAM) == BST_CHECKED);
break;
case IDC_CHECK_UNOFFICIAL_EXTRA_REGION:
ToggleUnofficialExtraRegionCode(hDlg, false, true, IsDlgButtonChecked(hDlg, IDC_CHECK_UNOFFICIAL_EXTRA_REGION) == BST_CHECKED);
break;
case IDC_RESTORE_BUTTON:
SetHeaderData(hDlg, header);
break;
case IDSAVE:
{
iNES_HEADER newHeader;
if (WriteHeaderData(hDlg, &newHeader))
{
char path[4096] = { 0 };
if (ShowINESFileBox(hDlg, path, true))
SaveINESFile(hDlg, path, &newHeader);
}
}
break;
case IDCLOSE:
goto wm_close;
}
} }
} }
break;
case WM_CLOSE:
case WM_QUIT:
wm_close:
if (GameInfo)
DestroyWindow(hDlg);
else
{
EndDialog(hDlg, 0);
LoadedRomFName[0] = 0;
}
break; break;
case WM_DESTROY: case IDCLOSE:
hHeadEditor = NULL; goto wm_close;
free(header); }
}
}
break;
case WM_CLOSE:
case WM_QUIT:
wm_close:
if (GameInfo)
DestroyWindow(hDlg);
else
{
EndDialog(hDlg, 0);
LoadedRomFName[0] = 0;
}
break;
case WM_DESTROY:
hHeadEditor = NULL;
free(header);
break; break;
} }
return false; return false;
@ -628,7 +628,7 @@ void SetHeaderData(HWND hwnd, iNES_HEADER* header) {
// Mapper# // Mapper#
int mapper = header->ROM_type >> 4 | header->ROM_type2 & 0xF0; int mapper = header->ROM_type >> 4 | header->ROM_type2 & 0xF0;
if (ines20) if (ines20)
mapper |= (header->ROM_type3 & 0xF0) << 4; mapper |= (header->ROM_type3 & 0x0F) << 8;
sprintf(buf, "%d ", mapper); sprintf(buf, "%d ", mapper);
if (SendDlgItemMessage(hwnd, IDC_MAPPER_COMBO, CB_SELECTSTRING, 0, (LPARAM)buf) == CB_ERR) if (SendDlgItemMessage(hwnd, IDC_MAPPER_COMBO, CB_SELECTSTRING, 0, (LPARAM)buf) == CB_ERR)
SetDlgItemText(hwnd, IDC_MAPPER_COMBO, buf); SetDlgItemText(hwnd, IDC_MAPPER_COMBO, buf);
@ -672,7 +672,8 @@ void SetHeaderData(HWND hwnd, iNES_HEADER* header) {
else sprintf(buf, "%dB", prg_ram); else sprintf(buf, "%dB", prg_ram);
} }
} else }
else
{ {
if (!(header->RAM_size & 0x10) && header->ROM_type3) if (!(header->RAM_size & 0x10) && header->ROM_type3)
sprintf(buf, "%dKB", header->ROM_type3 ? 1 : header->ROM_type3 * 8); sprintf(buf, "%dKB", header->ROM_type3 ? 1 : header->ROM_type3 * 8);
@ -692,7 +693,8 @@ void SetHeaderData(HWND hwnd, iNES_HEADER* header) {
sprintf(buf, "%dKB", prg_nvram / 1024); sprintf(buf, "%dKB", prg_nvram / 1024);
else sprintf(buf, "%dB", prg_nvram); else sprintf(buf, "%dB", prg_nvram);
} }
} else }
else
CheckDlgButton(hwnd, IDC_CHECK_BATTERYNVRAM, header->ROM_type & 0x2 ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwnd, IDC_CHECK_BATTERYNVRAM, header->ROM_type & 0x2 ? BST_CHECKED : BST_UNCHECKED);
if (SendDlgItemMessage(hwnd, IDC_PRGNVRAM_COMBO, CB_SELECTSTRING, 0, (LPARAM)buf) == CB_ERR) if (SendDlgItemMessage(hwnd, IDC_PRGNVRAM_COMBO, CB_SELECTSTRING, 0, (LPARAM)buf) == CB_ERR)
@ -763,21 +765,21 @@ void SetHeaderData(HWND hwnd, iNES_HEADER* header) {
{ {
int region = header->TV_system & 3; int region = header->TV_system & 3;
switch (region) { switch (region) {
case 0: case 0:
// NTSC // NTSC
CheckRadioButton(hwnd, IDC_RADIO_REGION_NTSC, IDC_RADIO_REGION_DENDY, IDC_RADIO_REGION_NTSC); CheckRadioButton(hwnd, IDC_RADIO_REGION_NTSC, IDC_RADIO_REGION_DENDY, IDC_RADIO_REGION_NTSC);
break; break;
case 1: case 1:
// PAL // PAL
CheckRadioButton(hwnd, IDC_RADIO_REGION_NTSC, IDC_RADIO_REGION_DENDY, IDC_RADIO_REGION_PAL); CheckRadioButton(hwnd, IDC_RADIO_REGION_NTSC, IDC_RADIO_REGION_DENDY, IDC_RADIO_REGION_PAL);
break; break;
case 2: case 2:
// Dual // Dual
CheckRadioButton(hwnd, IDC_RADIO_REGION_NTSC, IDC_RADIO_REGION_DENDY, IDC_RADIO_REGION_DUAL); CheckRadioButton(hwnd, IDC_RADIO_REGION_NTSC, IDC_RADIO_REGION_DENDY, IDC_RADIO_REGION_DUAL);
break; break;
case 3: case 3:
// Dendy // Dendy
CheckRadioButton(hwnd, IDC_RADIO_REGION_NTSC, IDC_RADIO_REGION_DENDY, IDC_RADIO_REGION_DENDY); CheckRadioButton(hwnd, IDC_RADIO_REGION_NTSC, IDC_RADIO_REGION_DENDY, IDC_RADIO_REGION_DENDY);
} }
} }
else { else {
@ -798,25 +800,25 @@ void SetHeaderData(HWND hwnd, iNES_HEADER* header) {
int system = header->ROM_type2 & 3; int system = header->ROM_type2 & 3;
switch (system) switch (system)
{ {
default: default:
// Normal // Normal
case 0: case 0:
CheckRadioButton(hwnd, IDC_RADIO_SYSTEM_NORMAL, IDC_RADIO_SYSTEM_EXTEND, IDC_RADIO_SYSTEM_NORMAL); CheckRadioButton(hwnd, IDC_RADIO_SYSTEM_NORMAL, IDC_RADIO_SYSTEM_EXTEND, IDC_RADIO_SYSTEM_NORMAL);
break; break;
// VS. System // VS. System
case 1: case 1:
CheckRadioButton(hwnd, IDC_RADIO_SYSTEM_NORMAL, IDC_RADIO_SYSTEM_EXTEND, IDC_RADIO_SYSTEM_VS); CheckRadioButton(hwnd, IDC_RADIO_SYSTEM_NORMAL, IDC_RADIO_SYSTEM_EXTEND, IDC_RADIO_SYSTEM_VS);
break; break;
// PlayChoice-10 // PlayChoice-10
case 2: case 2:
CheckRadioButton(hwnd, IDC_RADIO_SYSTEM_NORMAL, IDC_RADIO_SYSTEM_EXTEND, IDC_RADIO_SYSTEM_PLAYCHOICE10); CheckRadioButton(hwnd, IDC_RADIO_SYSTEM_NORMAL, IDC_RADIO_SYSTEM_EXTEND, IDC_RADIO_SYSTEM_PLAYCHOICE10);
// PlayChoice-10 is an unofficial setting for ines 1.0 // PlayChoice-10 is an unofficial setting for ines 1.0
unofficial = !ines20; unofficial = !ines20;
break; break;
// Extend // Extend
case 3: case 3:
// The 7th byte is different between ines 1.0 and 2.0, so we need to check it // The 7th byte is different between ines 1.0 and 2.0, so we need to check it
if (ines20) CheckRadioButton(hwnd, IDC_RADIO_SYSTEM_NORMAL, IDC_RADIO_SYSTEM_EXTEND, IDC_RADIO_SYSTEM_EXTEND); if (ines20) CheckRadioButton(hwnd, IDC_RADIO_SYSTEM_NORMAL, IDC_RADIO_SYSTEM_EXTEND, IDC_RADIO_SYSTEM_EXTEND);
} }
// it's quite ambiguous to put them here, but it's better to have a default selection than leave the dropdown blank, because user might switch to ines 2.0 anytime // it's quite ambiguous to put them here, but it's better to have a default selection than leave the dropdown blank, because user might switch to ines 2.0 anytime
@ -891,11 +893,9 @@ bool WriteHeaderData(HWND hwnd, iNES_HEADER* header)
if (mapper < 4096) if (mapper < 4096)
{ {
if (mapper < 256) _header.ROM_type |= (mapper & 0xF) << 4;
{ _header.ROM_type2 |= (mapper & 0xF0);
_header.ROM_type |= (mapper & 0xF) << 4; if (mapper >= 256)
_header.ROM_type2 |= (mapper & 0xF0);
} else
{ {
if (ines20) if (ines20)
_header.ROM_type3 |= mapper >> 8; _header.ROM_type3 |= mapper >> 8;
@ -929,7 +929,8 @@ bool WriteHeaderData(HWND hwnd, iNES_HEADER* header)
SetFocus(GetDlgItem(hwnd, IDC_SUBMAPPER_EDIT)); SetFocus(GetDlgItem(hwnd, IDC_SUBMAPPER_EDIT));
return false; return false;
} }
} else }
else
{ {
MessageBox(hwnd, "The sub mapper# you have entered is invalid. Please enter a decimal number.", "Error", MB_OK | MB_ICONERROR); MessageBox(hwnd, "The sub mapper# you have entered is invalid. Please enter a decimal number.", "Error", MB_OK | MB_ICONERROR);
SetFocus(GetDlgItem(hwnd, IDC_SUBMAPPER_EDIT)); SetFocus(GetDlgItem(hwnd, IDC_SUBMAPPER_EDIT));
@ -1021,7 +1022,8 @@ bool WriteHeaderData(HWND hwnd, iNES_HEADER* header)
SetFocus(GetDlgItem(hwnd, IDC_PRGROM_COMBO)); SetFocus(GetDlgItem(hwnd, IDC_PRGROM_COMBO));
return false; return false;
} }
} else }
else
return false; return false;
// PRG RAM // PRG RAM
@ -1424,7 +1426,7 @@ bool WriteHeaderData(HWND hwnd, iNES_HEADER* header)
printf("%02X\n", _header.reserved[1]); printf("%02X\n", _header.reserved[1]);
#endif #endif
return true; return true;
} }
int GetComboBoxByteSize(HWND hwnd, UINT id, int* value) int GetComboBoxByteSize(HWND hwnd, UINT id, int* value)
@ -1512,32 +1514,33 @@ bool GetComboBoxListItemData(HWND hwnd, UINT id, int* value, char* buf, bool exa
{ {
switch (id) switch (id)
{ {
default: default:
success = false; success = false;
break; break;
case IDC_MAPPER_COMBO: case IDC_MAPPER_COMBO:
if (!(success = sscanf(buf, "%d", value) > 0)) if (!(success = sscanf(buf, "%d", value) > 0))
success = SearchByString(hwnd, id, value, buf); success = SearchByString(hwnd, id, value, buf);
else else
SetDlgItemText(hwnd, id, buf); SetDlgItemText(hwnd, id, buf);
break; break;
case IDC_VS_SYSTEM_COMBO: case IDC_VS_SYSTEM_COMBO:
case IDC_VS_PPU_COMBO: case IDC_VS_PPU_COMBO:
case IDC_SYSTEM_EXTEND_COMBO: case IDC_SYSTEM_EXTEND_COMBO:
if (!(success = sscanf(buf, "$%X", (unsigned int *)value) > 0)) if (!(success = sscanf(buf, "$%X", (unsigned int *)value) > 0))
success = SearchByString(hwnd, id, value, buf); success = SearchByString(hwnd, id, value, buf);
else else
SetDlgItemText(hwnd, id, buf);
break;
case IDC_INPUT_DEVICE_COMBO:
if (success = sscanf(buf, "$%X", (unsigned int *)value) > 0)
{
char buf2[8];
sprintf(buf2, "$%02X", *value);
if (SendDlgItemMessage(hwnd, id, CB_SELECTSTRING, 0, (LPARAM)buf2) == CB_ERR)
SetDlgItemText(hwnd, id, buf); SetDlgItemText(hwnd, id, buf);
break; }
case IDC_INPUT_DEVICE_COMBO: else
if (success = sscanf(buf, "$%X", (unsigned int *)value) > 0) success = SearchByString(hwnd, id, value, buf);
{
char buf2[8];
sprintf(buf2, "$%02X", *value);
if (SendDlgItemMessage(hwnd, id, CB_SELECTSTRING, 0, (LPARAM)buf2) == CB_ERR)
SetDlgItemText(hwnd, id, buf);
} else
success = SearchByString(hwnd, id, value, buf);
break; break;
} }