2424PROJECT_NAME = "DoomGeo-AES"
2525PACKAGE_ROM_ZIP = "doomgeo-aes.zip"
2626PACKAGE_ASM_ROM_ZIP = "doomgeo-aes-asm.zip"
27- FBNEO_COMPAT_ROM_ZIP = "puzzledp.zip"
27+ FBNEO_COMPAT_ROM_ZIP = "magdrop2.zip"
28+ FBNEO_DRIVER_NAME = "magdrop2"
2829ROM_ZIP = Path ("build" ) / "rom" / FBNEO_COMPAT_ROM_ZIP
2930ROM_ELF = Path ("build" ) / "rom.elf"
3031BIOS_ZIP = Path ("build" ) / "rom" / "neogeo.zip"
3132ASM_ROM_ZIP = Path ("build" ) / "asm-rom" / FBNEO_COMPAT_ROM_ZIP
3233ASM_ROM_ELF = Path ("build" ) / "asm" / "doomgeo_asm.elf"
3334ASM_BIOS_ZIP = Path ("build" ) / "asm-rom" / "neogeo.zip"
34- FBNEO_PUZZLEDP_CRC = {
35- "202-p1.p1" : 0x2B61415B ,
36- "202-s1.s1" : 0xCD19264F ,
37- "202-c1.c1" : 0xCC0095EF ,
38- "202-c2.c2" : 0x42371307 ,
39- "202-m1.m1" : 0x9C0291EA ,
40- "202-v1.v1" : 0xDEBEB8FB ,
41- }
42- FBNEO_PUZZLEDP_SIZE = {
43- "202-p1.p1" : 0x80000 ,
44- "202-s1.s1" : 0x20000 ,
45- "202-c1.c1" : 0x200000 ,
46- "202-c2.c2" : 0x200000 ,
47- "202-m1.m1" : 0x20000 ,
48- "202-v1.v1" : 0x80000 ,
35+ FBNEO_ROM_ENTRIES = {
36+ "221-p1.p1" : ("202-p1.p1" , 0x80000 , 0x7BE82353 ),
37+ "221-s1.s1" : ("202-s1.s1" , 0x20000 , 0x2A4063A3 ),
38+ "221-c1.c1" : ("202-c1.c1" , 0x400000 , 0x1F862A14 ),
39+ "221-c2.c2" : ("202-c2.c2" , 0x400000 , 0x14B90536 ),
40+ "221-m1.m1" : ("202-m1.m1" , 0x20000 , 0xBDDAE628 ),
41+ "221-v1.v1" : ("202-v1.v1" , 0x200000 , 0x7E5E53E4 ),
4942}
5043FBNEO_NEOGEO_CRC = {
5144 "sp-s3.sp1" : 0x91B64BE3 ,
@@ -364,11 +357,13 @@ def force_crc32(data: bytes, desired: int, patch_offset: int | None = None) -> b
364357 return bytes (patched )
365358
366359
367- def write_zip_entries (path : Path , entries : dict [str , bytes ]) -> None :
360+ def write_zip_entries (path : Path , entries : dict [str , bytes ], compression : int | None = None ) -> None :
368361 import zipfile
369362
370363 path .parent .mkdir (parents = True , exist_ok = True )
371- with zipfile .ZipFile (path , "w" , compression = zipfile .ZIP_DEFLATED ) as archive :
364+ if compression is None :
365+ compression = zipfile .ZIP_DEFLATED
366+ with zipfile .ZipFile (path , "w" , compression = compression ) as archive :
372367 for name , data in entries .items ():
373368 archive .writestr (name , data )
374369
@@ -381,35 +376,20 @@ def web_asset_version(paths: list[Path]) -> str:
381376 return digest .hexdigest ()[:12 ]
382377
383378
384- def build_fbneo_rom_zip (source_zip : Path , out_zip : Path ) -> None :
385- import zipfile
386-
387- if not source_zip .exists ():
388- raise BuildError (f"ROM not found: { source_zip } " )
389- entries : dict [str , bytes ] = {}
390- with zipfile .ZipFile (source_zip ) as archive :
391- for name , desired_crc in FBNEO_PUZZLEDP_CRC .items ():
392- try :
393- data = archive .read (name )
394- except KeyError as exc :
395- raise BuildError (f"ROM entry missing for FBNeo package: { name } " ) from exc
396- expected_size = FBNEO_PUZZLEDP_SIZE [name ]
397- if len (data ) != expected_size :
398- raise BuildError (
399- f"ROM entry { name } is { len (data )} bytes, but the FBNeo puzzledp "
400- f"web driver expects { expected_size } bytes; rebuild the Pages ROM "
401- "with DOOM_CROM_FILE_BYTES=2097152"
402- )
403- entries [name ] = force_crc32 (data , desired_crc )
404- write_zip_entries (out_zip , entries )
405- print_step (f"wrote FBNeo-compatible ROM package to { out_zip } " )
379+ def pad_rom_entry (data : bytes , expected_size : int , name : str ) -> bytes :
380+ if len (data ) > expected_size :
381+ raise BuildError (
382+ f"ROM entry { name } is { len (data )} bytes, but the FBNeo { FBNEO_DRIVER_NAME } "
383+ f"web driver expects { expected_size } bytes"
384+ )
385+ if len (data ) < expected_size :
386+ return data + (b"\xff " * (expected_size - len (data )))
387+ return data
406388
407389
408- def build_fbneo_bios_zip (source_zip : Path , out_zip : Path ) -> None :
390+ def fbneo_bios_entries (source_zip : Path ) -> dict [ str , bytes ] :
409391 import zipfile
410392
411- if not source_zip .exists ():
412- raise BuildError (f"BIOS not found: { source_zip } " )
413393 with zipfile .ZipFile (source_zip ) as archive :
414394 source_names = set (archive .namelist ())
415395
@@ -425,13 +405,41 @@ def read_first(*names: str) -> bytes:
425405 "sfix.sfix" : force_crc32 (read_first ("sfix.sfix" ), FBNEO_NEOGEO_CRC ["sfix.sfix" ]),
426406 "000-lo.lo" : force_crc32 (read_first ("000-lo.lo" ), FBNEO_NEOGEO_CRC ["000-lo.lo" ]),
427407 }
408+ return entries
409+
410+
411+ def build_fbneo_rom_zip (source_zip : Path , out_zip : Path , bios_zip : Path | None = None ) -> None :
412+ import zipfile
413+
414+ if not source_zip .exists ():
415+ raise BuildError (f"ROM not found: { source_zip } " )
416+ entries : dict [str , bytes ] = {}
417+ with zipfile .ZipFile (source_zip ) as archive :
418+ for target_name , (source_name , expected_size , desired_crc ) in FBNEO_ROM_ENTRIES .items ():
419+ try :
420+ data = archive .read (source_name )
421+ except KeyError as exc :
422+ raise BuildError (f"ROM entry missing for FBNeo package: { source_name } " ) from exc
423+ data = pad_rom_entry (data , expected_size , target_name )
424+ entries [target_name ] = force_crc32 (data , desired_crc )
425+ if bios_zip :
426+ entries .update (fbneo_bios_entries (bios_zip ))
427+ write_zip_entries (out_zip , entries , compression = zipfile .ZIP_STORED )
428+ print_step (f"wrote FBNeo-compatible ROM package to { out_zip } " )
429+
430+
431+ def build_fbneo_bios_zip (source_zip : Path , out_zip : Path ) -> None :
432+ if not source_zip .exists ():
433+ raise BuildError (f"BIOS not found: { source_zip } " )
434+ entries = fbneo_bios_entries (source_zip )
428435 write_zip_entries (out_zip , entries )
429436 print_step (f"wrote FBNeo-compatible BIOS package to { out_zip } " )
430437
431438
432439def html_page (
433440 game_name : str ,
434441 subtitle : str ,
442+ emulator_game_name : str ,
435443 game_url : str ,
436444 download_url : str ,
437445 bios_url : str ,
@@ -530,7 +538,7 @@ def html_page(
530538 <script>
531539 window.EJS_player = "#game";
532540 window.EJS_core = "fbneo";
533- window.EJS_gameName = "__GAME_NAME__ ";
541+ window.EJS_gameName = "__EMULATOR_GAME_NAME__ ";
534542 window.EJS_gameUrl = "__GAME_URL__";
535543 window.EJS_biosUrl = "__BIOS_URL__";
536544 window.EJS_pathtodata = "https://cdn.emulatorjs.org/stable/data/";
@@ -542,6 +550,7 @@ def html_page(
542550"""
543551 return (
544552 template .replace ("__GAME_NAME__" , game_name )
553+ .replace ("__EMULATOR_GAME_NAME__" , emulator_game_name )
545554 .replace ("__SUBTITLE__" , subtitle )
546555 .replace ("__GAME_URL__" , game_url )
547556 .replace ("__DOWNLOAD_URL__" , download_url )
@@ -570,16 +579,19 @@ def build_pages(
570579 rom_out = out_dir / "rom" / f"web-{ version } "
571580 rom_out .mkdir (parents = True , exist_ok = True )
572581 main_rom_url = f"rom/web-{ version } /{ PACKAGE_ROM_ZIP } "
582+ main_launch_rom_url = f"rom/web-{ version } /{ FBNEO_COMPAT_ROM_ZIP } "
573583 bios_url = f"rom/web-{ version } /neogeo.zip"
574- build_fbneo_rom_zip (rom , rom_out / PACKAGE_ROM_ZIP )
584+ build_fbneo_rom_zip (rom , rom_out / FBNEO_COMPAT_ROM_ZIP , bios )
585+ shutil .copy2 (rom_out / FBNEO_COMPAT_ROM_ZIP , rom_out / PACKAGE_ROM_ZIP )
575586 build_fbneo_bios_zip (bios , rom_out / "neogeo.zip" )
576587 # FBNeo still matches the internal Neo Geo chip filenames and CRCs against
577- # the Puzzle De Pon driver. The public zip name can be project-specific.
588+ # a known driver. The public page title and download copy stay project-specific.
578589 (out_dir / "index.html" ).write_text (
579590 html_page (
580591 PROJECT_NAME ,
581592 "Neo Geo AES Doom prototype running in a browser through the EmulatorJS FBNeo WebAssembly core." ,
582- main_rom_url ,
593+ FBNEO_DRIVER_NAME ,
594+ main_launch_rom_url ,
583595 main_rom_url ,
584596 bios_url ,
585597 "asm.html" if asm_rom_source else None ,
@@ -593,12 +605,15 @@ def build_pages(
593605 asm_out = out_dir / "rom" / "asm" / f"web-{ version } "
594606 asm_out .mkdir (parents = True , exist_ok = True )
595607 asm_rom_url = f"rom/asm/web-{ version } /{ PACKAGE_ASM_ROM_ZIP } "
596- build_fbneo_rom_zip (asm_rom , asm_out / PACKAGE_ASM_ROM_ZIP )
608+ asm_launch_rom_url = f"rom/asm/web-{ version } /{ FBNEO_COMPAT_ROM_ZIP } "
609+ build_fbneo_rom_zip (asm_rom , asm_out / FBNEO_COMPAT_ROM_ZIP , bios )
610+ shutil .copy2 (asm_out / FBNEO_COMPAT_ROM_ZIP , asm_out / PACKAGE_ASM_ROM_ZIP )
597611 (out_dir / "asm.html" ).write_text (
598612 html_page (
599613 f"{ PROJECT_NAME } ASM" ,
600614 "A separate 68000 assembly cartridge build with a controller-driven Neo Geo sprite scene." ,
601- asm_rom_url ,
615+ FBNEO_DRIVER_NAME ,
616+ asm_launch_rom_url ,
602617 asm_rom_url ,
603618 bios_url ,
604619 ),
0 commit comments