From fa05bd9f77bd6a5f8651b6799929ef1920733df4 Mon Sep 17 00:00:00 2001 From: Persune Date: Fri, 21 Jun 2024 18:05:27 +0800 Subject: [PATCH] Fix NES ROM export data alignment Fixes #278. --- Source/Compiler.cpp | 44 +++++++++++++++++++++------------- Source/Compiler.h | 2 +- Source/drivers/asm/nes.s | 51 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 Source/drivers/asm/nes.s diff --git a/Source/Compiler.cpp b/Source/Compiler.cpp index aa58e48e..54432455 100644 --- a/Source/Compiler.cpp +++ b/Source/Compiler.cpp @@ -725,7 +725,7 @@ void CCompiler::ExportNES(LPCTSTR lpszFileName, bool EnablePAL) } // Build the music data - if (!CompileData()) { + if (!CompileData(true)) { Cleanup(); return; } @@ -743,13 +743,15 @@ void CCompiler::ExportNES(LPCTSTR lpszFileName, bool EnablePAL) // Rewrite DPCM sample pointers UpdateSamplePointers(m_iSampleStart); - // Locate driver at $8000 - m_iLoadAddress = PAGE_START; - m_iDriverAddress = PAGE_START; - unsigned short MusicDataAddress = m_iLoadAddress + m_iDriverSize; + // Compressed mode means that driver and music is located just below the sample space, no space is lost even when samples are used + bool bCompressedMode; + unsigned short MusicDataAddress; - // Init is located first at the driver - m_iInitAddress = m_iDriverAddress; // // // + CalculateLoadAddresses(MusicDataAddress, bCompressedMode, true); + + // Load driver identifier + std::unique_ptr pNSFDRVPtr(LoadNSFDRV(m_pDriverData)); + char *pNSFDRV = pNSFDRVPtr.get(); // Load driver std::unique_ptr pDriverPtr(LoadDriver(m_pDriverData, m_iDriverAddress)); // // // @@ -758,6 +760,9 @@ void CCompiler::ExportNES(LPCTSTR lpszFileName, bool EnablePAL) // Patch driver binary PatchVibratoTable(pDriver); + // Copy the Namco table, if used + // // // nothing here, ft_channel_type is taken care in LoadDriver + // Write music data address SetDriverSongAddress(pDriver, MusicDataAddress); @@ -772,6 +777,7 @@ void CCompiler::ExportNES(LPCTSTR lpszFileName, bool EnablePAL) // Write NES data std::unique_ptr Render(new CChunkRenderNES(&OutputFile, m_iLoadAddress)); + Render->StoreNSFDRV(pNSFDRV, m_iNSFDRVSize); Render->StoreDriver(pDriver, m_iDriverSize); Render->StoreChunks(m_vChunks); Render->StoreSamples(m_vSamples); @@ -1027,7 +1033,7 @@ void CCompiler::ExportPRG(LPCTSTR lpszFileName, bool EnablePAL) } // Build the music data - if (!CompileData()) { + if (!CompileData(true)) { Cleanup(); return; } @@ -1045,13 +1051,15 @@ void CCompiler::ExportPRG(LPCTSTR lpszFileName, bool EnablePAL) // Rewrite DPCM sample pointers UpdateSamplePointers(m_iSampleStart); - // Locate driver at $8000 - m_iLoadAddress = PAGE_START; - m_iDriverAddress = PAGE_START; - unsigned short MusicDataAddress = m_iLoadAddress + m_iDriverSize; + // Compressed mode means that driver and music is located just below the sample space, no space is lost even when samples are used + bool bCompressedMode; + unsigned short MusicDataAddress; - // Init is located first at the driver - m_iInitAddress = m_iDriverAddress; // // // + CalculateLoadAddresses(MusicDataAddress, bCompressedMode, true); + + // Load driver identifier + std::unique_ptr pNSFDRVPtr(LoadNSFDRV(m_pDriverData)); + char *pNSFDRV = pNSFDRVPtr.get(); // Load driver std::unique_ptr pDriverPtr(LoadDriver(m_pDriverData, m_iDriverAddress)); // // // @@ -1060,6 +1068,9 @@ void CCompiler::ExportPRG(LPCTSTR lpszFileName, bool EnablePAL) // Patch driver binary PatchVibratoTable(pDriver); + // Copy the Namco table, if used + // // // nothing here, ft_channel_type is taken care in LoadDriver + // Write music data address SetDriverSongAddress(pDriver, MusicDataAddress); @@ -1071,6 +1082,7 @@ void CCompiler::ExportPRG(LPCTSTR lpszFileName, bool EnablePAL) // Write NES data std::unique_ptr Render(new CChunkRenderNES(&OutputFile, m_iLoadAddress)); + Render->StoreNSFDRV(pNSFDRV, m_iNSFDRVSize); Render->StoreDriver(pDriver, m_iDriverSize); Render->StoreChunks(m_vChunks); Render->StoreSamples(m_vSamples); @@ -2043,7 +2055,7 @@ void CCompiler::Cleanup() } } -void CCompiler::CalculateLoadAddresses(unsigned short &MusicDataAddress, bool &bCompressedMode) +void CCompiler::CalculateLoadAddresses(unsigned short &MusicDataAddress, bool &bCompressedMode, bool ForceDecompress) { // Find out load address @@ -2052,7 +2064,7 @@ void CCompiler::CalculateLoadAddresses(unsigned short &MusicDataAddress, bool &b bCompressedMode = !((PAGE_SAMPLES - m_iDriverSize - m_iMusicDataSize - m_iNSFDRVSize) < 0x8000 || m_bBankSwitched || m_iActualChip != m_pDocument->GetExpansionChip()); - if (bCompressedMode) { + if (bCompressedMode && !ForceDecompress) { // Locate driver at $C000 - (driver size) m_iLoadAddress = PAGE_SAMPLES - m_iDriverSize - m_iMusicDataSize - m_iNSFDRVSize; m_iDriverAddress = PAGE_SAMPLES - m_iDriverSize; diff --git a/Source/Compiler.h b/Source/Compiler.h index bd21fe32..c72676f5 100644 --- a/Source/Compiler.h +++ b/Source/Compiler.h @@ -145,7 +145,7 @@ class CCompiler void AssignLabels(CMap &labelMap); void AddBankswitching(); void Cleanup(); - void CalculateLoadAddresses(unsigned short &MusicDataAddress, bool &bCompressedMode); + void CalculateLoadAddresses(unsigned short &MusicDataAddress, bool &bCompressedMode, bool ForceDecompress = false); void SetNSFDRVHeaderSize(bool bUseNSFDRV); void ScanSong(); diff --git a/Source/drivers/asm/nes.s b/Source/drivers/asm/nes.s new file mode 100644 index 00000000..e4cffb9f --- /dev/null +++ b/Source/drivers/asm/nes.s @@ -0,0 +1,51 @@ +; decompilation of NSF_CALLER_BIN and NSF_CALLER_BIN_VRC6 in Driver.h +; decompilation by Persune 2024 + +.ifdef ::USE_VRC6 +INIT = $8000 +PLAY = $8003 +.else +INIT = $8008 +PLAY = $800B +.endif + +.org $FF80 +reset: sei + cld +: lda $2002 + bpl :- +: lda $2002 + bpl :- + ldx #0 + txa +: sta $0200,x + inx + bne :- +.ifdef ::USE_VRC6 + ; init banks + lda #$00 + sta $8000 + lda #$02 + sta $C000 +.endif + lda #$0F + sta $4015 + lda #$0A + sta $4010 + lda #$00 + ldx #$00 + ldy #$00 + jsr INIT + lda #$80 + sta $2000 + lda #$00 + sta $2001 + +: jmp :- + +nmi: jsr PLAY +irq: rti + + +.org $FFFA +vec: .addr nmi, reset, irq