Open barbudreadmon opened 5 years ago
Barbudreadmon, yes, of course. This topic is a great idea! Let's go:
On patching the rom, let's take for example these: ROM_FILL(0x701af4,1,0x4e) ROM_FILL(0x701af5,1,0x71) ROM_FILL(0x701b18,1,0x60) ROM_FILL(0x701ca2,1,0x60) ROM_FILL(a,b,c) is basically memset(rom+a,c,b);
But, let's do it in a bit differently - to learn some other methods:
UINT16 ROM = (UINT16)Neo68KROMActive; ROM[0x701af4 / 2] = 0x4e71; // word-write nop Neo68KROMActive[0x701b18] = 0x60; // byte-write 0x60 Neo68KROMActive[0x701ca2] = 0x60; // byte-write 0x60
Let's explain a few things: 0: Neo68KROMActive is a byte-array, but can be word(UINT16)-accessed using a simple cast. 1: notice the first 2 ROM_FILL's are contiguous? 0x701af4, 0x701af5, that's why we are able to write both bytes at once using a UINT16 cast for ROM[]. 0x4e71 is commonly known as NOP on 68k cpu's 2: notice the /2 when writing a word using ROM[]? When indexing using UINT16 (word), each word address is 2 bytes, that's why the address is divided by 2. For example: WORD0 BYTE0,BYTE1 WORD1 BYTE2,BYTE3 WORD2 BYTE4,BYTE5 .. and so on :) Take for example BYTE4, divide that by 2 and you get WORD2.
Maybe you just want to do it exactly the same way as HBMAME? Neo68KROMActive[0x701af4] = 0x4e; Neo68KROMActive[0x701af5] = 0x71; Neo68KROMActive[0x701b18] = 0x60; // byte-write 0x60 Neo68KROMActive[0x701ca2] = 0x60; // byte-write 0x60
or even with memset():
memset(Neo68KROMActive + 0x701af4, 0x4e, 1); memset(Neo68KROMActive + 0x701af5, 0x71, 1); memset(Neo68KROMActive + 0x701b18, 0x60, 1); memset(Neo68KROMActive + 0x701ca2, 0x60, 1); ... and so on...
hope this clears some things up :)
best regards,
Updated the first post with latest version of the code. It's currently crashing with the following trace :
#0 0x7f9f3e4488af in inflate_fast src/dep/libs/zlib/inffast.c:120
#1 0x7f9f3e454e20 in inflate src/dep/libs/zlib/inflate.c:1047
#2 0x7f9f3e227277 in unzReadCurrentFile src/burner/unzip.c:1854
#3 0x7f9f3e4a62c1 in ZipLoadFile(unsigned char*, int, int*, int) src/burner/zipfn.cpp:229
#4 0x7f9f3fd04ef6 in archive_load_rom src/burner/libretro/libretro.cpp:584
#5 0x7f9f3e522f5b in BurnLoadRomExt(unsigned char*, int, int, int) src/burn/load.cpp:80
#6 0x7f9f3e523aa5 in BurnLoadRom(unsigned char*, int, int) src/burn/load.cpp:100
#7 0x7f9f3edc6a52 in kof98pfeCallback src/burn/drv/neogeo/d_neogeo.cpp:17454
#8 0x7f9f3ed810f4 in LoadRoms src/burn/drv/neogeo/neo_run.cpp:759
#9 0x7f9f3ed8feda in NeoInit() src/burn/drv/neogeo/neo_run.cpp:4143
#10 0x7f9f3edd6c15 in kof98pfeInit src/burn/drv/neogeo/d_neogeo.cpp:17465
#11 0x7f9f3e51c796 in BurnDrvInit src/burn/burn.cpp:647
#12 0x7f9f3fd0d63f in retro_load_game_common src/burner/libretro/libretro.cpp:1281
#13 0x7f9f3fd0f609 in retro_load_game src/burner/libretro/libretro.cpp:1353
#14 0x56433e6e18f8 (/usr/bin/retroarch+0x468f8)
#15 0x56433e6fb689 (/usr/bin/retroarch+0x60689)
#16 0x56433e6ec063 (/usr/bin/retroarch+0x51063)
#17 0x56433e6e4e78 (/usr/bin/retroarch+0x49e78)
#18 0x56433e6f9164 (/usr/bin/retroarch+0x5e164)
#19 0x56433e6f953b (/usr/bin/retroarch+0x5e53b)
#20 0x56433e6f9db4 (/usr/bin/retroarch+0x5edb4)
#21 0x56433e6e08f8 (/usr/bin/retroarch+0x458f8)
#22 0x7f9f5956bae6 in __libc_start_main (/lib64/libc.so.6+0x21ae6)
#23 0x56433e6dd859 (/usr/bin/retroarch+0x42859)
Seems like it's failing on BurnLoadRom(Neo68KROMActive + 0x700000, 2, 1);
, any idea ?
Looks like we'll need a kludge in neo_run for this set to have it allocate the required memory for the main roms. try this: edit neo_run.cpp, search for burnmalloc(ncodesize add this line above it: if (!strcmp("kof98pfe", BurnDrvGetTextA(DRV_NAME))) nCodeSize[nNeoActiveSlot] = 0x720000;
in the driver d_neogeo, remove the extrarom stuff & change a things a bit: if (nRet == 0) { rom = (UINT16*)Neo68KROMActive;
for (INT32 i = 0; i < 0x100000/2; i++) {
if (rom[i] == 0x4e7d) rom[i] = 0x4e71;
if (rom[i] == 0x4e7c) rom[i] = 0x4e75;
}
for (INT32 i = 0x700000/2; i < 0x720000/2; i++) {
if (rom[i] == 0x4e7d) rom[i] = 0x4e71;
if (rom[i] == 0x4e7c) rom[i] = 0x4e75;
}
}
.. and should be good :)
@dinkc64 got the game working with "official" kof98pfe from hbmame (see commit above), some details :
if (!strcmp("kof98pfe", BurnDrvGetTextA(DRV_NAME))) nCodeSize[nNeoActiveSlot] = 0x720000;
I think i understand this part, we need an allocation of 0x700000+0x020000 which is last 68k code rom offset+size, and it was previously failing because fba compute it only from file size by default (which makes me realize that maybe we are over-allocating 68k code memory for the kof2k2omg romset, it's computed 0x3bd4c1+0x400000 while we only need 0x100000+0x400000, but maybe that's not an issue ?).
I got a similar issue with the sound data roms and fixed it like this : https://github.com/libretro/fbalpha/blob/f9f067906613181615aca662baafd281d169300e/src/burn/drv/neogeo/neo_run.cpp#L675 There are 4 roms of 0x400000 each for sound data, which is 0x1000000. However i don't understand why there was no crash with previous version of the implementation (size is the same)
I didn't understand the changes in kof98pfeInit, and actually the game will stop working (black screen after the neogeo logo) if i apply those changes (edit : actually i understand what you are trying to do now, however it's still not working for some reason). Here is the code i tried :
static struct BurnRomInfo kof98pfeRomDesc[] = {
{ "242pfe.p1", 0x100000, 0x23876d95, 1 | BRF_ESS | BRF_PRG }, // 1 68K code
{ "242pfe.p2", 0x400000, 0xadbaa852, 1 | BRF_ESS | BRF_PRG }, // 1 68K code, 2MB zero bytes are added to the end of file so the file size expands to 6MB.
{ "242pfe.p3", 0x020000, 0x930ea34e, 1 | BRF_ESS | BRF_PRG }, // 1 68K code, protections are patched out.
{ "242pfe.s1", 0x020000, 0x7f4dbf23, 2 | BRF_GRA }, // 2 Text layer tiles / TC531000
{ "242hx73.c1", 0x800000, 0x379654a5, 3 | BRF_GRA }, // 3 Sprite data
{ "242hx73.c2", 0x800000, 0x9c71fa3d, 3 | BRF_GRA }, // 4
{ "242.c3", 0x800000, 0x22127b4f, 3 | BRF_GRA }, // 5
{ "242.c4", 0x800000, 0x0b4fa044, 3 | BRF_GRA }, // 6
{ "242.c5", 0x800000, 0x9d10bed3, 3 | BRF_GRA }, // 7
{ "242.c6", 0x800000, 0xda07b6a2, 3 | BRF_GRA }, // 8
{ "242pfe.c7", 0x800000, 0x02f09b2e, 3 | BRF_GRA }, // 9
{ "242pfe.c8", 0x800000, 0xd43ab3e6, 3 | BRF_GRA }, // 10
{ "242-mg1.m1", 0x040000, 0x4e7a6b1b, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code
{ "242.v1", 0x400000, 0xb9ea8051, 5 | BRF_SND }, // 12 Sound data
{ "242.v2", 0x400000, 0xcc11106e, 5 | BRF_SND }, // 13
{ "242.v3", 0x400000, 0x044ea4e1, 5 | BRF_SND }, // 14
{ "242.v4", 0x400000, 0x7985ea30, 5 | BRF_SND }, // 15
};
STDROMPICKEXT(kof98pfe, kof98pfe, neogeo)
STD_ROM_FN(kof98pfe)
static void kof98pfeCallback()
{
BurnLoadRom(Neo68KROMActive + 0x000000, 0, 1);
BurnLoadRom(Neo68KROMActive + 0x100000, 1, 1);
BurnLoadRom(Neo68KROMActive + 0x700000, 2, 1);
Neo68KROMActive[0x701af4] = 0x4e;
Neo68KROMActive[0x701af5] = 0x71;
Neo68KROMActive[0x701b18] = 0x60; // byte-write 0x60
Neo68KROMActive[0x701ca2] = 0x60; // byte-write 0x60
}
static INT32 kof98pfeInit()
{
NeoCallbackActive->pInitialise = kof98pfeCallback;
INT32 nRet = NeoInit();
if (nRet == 0) {
UINT16 *rom = (UINT16*)Neo68KROMActive;
for (INT32 i = 0; i < 0x100000/2; i++) {
if (rom[i] == 0x4e7d) rom[i] = 0x4e71;
if (rom[i] == 0x4e7c) rom[i] = 0x4e75;
}
for (INT32 i = 0x700000/2; i < 0x720000/2; i++) {
if (rom[i] == 0x4e7d) rom[i] = 0x4e71;
if (rom[i] == 0x4e7c) rom[i] = 0x4e75;
}
}
return nRet;
}
struct BurnDriver BurnDrvkof98pfe = {
"kof98pfe", "kof98", "neogeo", NULL, "2017",
"KOF'98 (Plus Final Edition)(2017-07-23)\0", NULL, "hack", "Neo Geo MVS",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF,
NULL, kof98pfeRomInfo, kof98pfeRomName, NULL, NULL, NULL, NULL, neogeoInputInfo, neogeoDIPInfo,
kof98pfeInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette,
0x1000, 320, 224, 4, 3
};
Nice job figuring it out :) So basically, the rom search & replace code is not needed then, right?
@dinkc64 it's needed, but i'm just not too sure why
static INT32 kof98pfeInit()
{
NeoCallbackActive->pInitialise = kof98pfeCallback; // Use this callback when loading the romset
INT32 nRet = NeoInit();
if (nRet == 0) {
kof98pfeExtraROM = (UINT8*)BurnMalloc(0x20000);
if (BurnLoadRom(kof98pfeExtraROM, 2, 1)) return 1;
UINT16 *rom = (UINT16*)kof98pfeExtraROM;
for (INT32 i = 0; i < 0x20000/2; i++) {
if (rom[i] == 0x4e7d) rom[i] = 0x4e71;
if (rom[i] == 0x4e7c) rom[i] = 0x4e75;
}
rom = (UINT16*)Neo68KROMActive;
for (INT32 i = 0; i < 0x100000/2; i++) {
if (rom[i] == 0x4e7d) rom[i] = 0x4e71;
if (rom[i] == 0x4e7c) rom[i] = 0x4e75;
}
SekOpen(0);
SekMapMemory(kof98pfeExtraROM, 0x900000, 0x91ffff, MAP_ROM);
SekClose();
}
return nRet;
}
works and
static INT32 kof98pfeInit()
{
NeoCallbackActive->pInitialise = kof98pfeCallback;
INT32 nRet = NeoInit();
if (nRet == 0) {
UINT16 *rom = (UINT16*)Neo68KROMActive;
for (INT32 i = 0; i < 0x100000/2; i++) {
if (rom[i] == 0x4e7d) rom[i] = 0x4e71;
if (rom[i] == 0x4e7c) rom[i] = 0x4e75;
}
for (INT32 i = 0x700000/2; i < 0x720000/2; i++) {
if (rom[i] == 0x4e7d) rom[i] = 0x4e71;
if (rom[i] == 0x4e7c) rom[i] = 0x4e75;
}
}
return nRet;
}
don't.
With the third c68k code rom already loaded, patching directly on Neo68KROMActive makes more sense to me.
if (BurnLoadRom(kof98pfeExtraROM, 2, 1)) return 1;
is definitely needed (black screen without it), while it's returning false (because BurnLoadRom(Neo68KROMActive + 0x700000, 2, 1);
was called in the callback i guess), so i'm not too sure what is happening behind the scene. If you have any explanation i would be curious.
Oh, ok, I must have looked at the wrong code in hbmame then when I came up with that alternate init. oops :) BurnLoadRom shouldn't return bad if you load a rom a second (or third) time - that's odd :/ Try ignoring the load status?
BurnLoadRom shouldn't return bad if you load a rom a second (or third) time
My bad, it seems the good return value for BurnLoadRom
is actually 0, so having the return value equivalent to false is actually a good thing.
I think the code you looked at in hbmame is the right one. You can see the same kind of differences for lastbladsp between hbmame and fba : https://github.com/Robbbert/hbmame/blob/fce87309c706c6e9626bdc735ed82eddef342811/src/hbmame/drivers/nglastblade.cpp#L8-L28 and https://github.com/libretro/fbalpha/blob/89aaee4338869b3f8f10df97023353805846c4bf/src/burn/drv/neogeo/d_neogeo.cpp#L15733-L15770
I don't understand why, in both cases, direct access to Neo68KROMActive doesn't work for this 3rd rom, but you can backport the kof98pfe romset to standalone anyway.
So i wanted to sync kof98pfe with the hbmame version (having a hack of a hack just to get it working is no good, i won't keep it in the core if it's not fixed), and i thought it would be a good idea to open an issue that might become a reference for @SumavisionQ5 or whoever who want to add support for more hacks in the future.
First, here is the original romset from hbmame :
I think there are 2 difficulties in this romset, which weren't handled correctly in the present implementation from @SumavisionQ5 (hence the modified
242pfe.p2
and242pfe.p3
files). The first one is that the 2 files aren't contiguous in memory (hence the 2M padding), iirc the correct way to do this would be more like this (updated with latest version + some comments) :@dinkc64 correct me if i'm wrong, but the callback + burnloadrom thing allows to load a rom at a specific offset ? (that's what i used for the kof2k2omg hacks)
The second issue would be the
ROM_FILL
thing from hbmame, i think it's something like replacing data at a specific offset ? How should i deal with this in fba ?