Skip to content

Commit

Permalink
Fix NES ROM export data alignment
Browse files Browse the repository at this point in the history
Fixes #278.
  • Loading branch information
Gumball2415 committed Jun 21, 2024
1 parent b8425af commit fa05bd9
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 17 deletions.
44 changes: 28 additions & 16 deletions Source/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ void CCompiler::ExportNES(LPCTSTR lpszFileName, bool EnablePAL)
}

// Build the music data
if (!CompileData()) {
if (!CompileData(true)) {
Cleanup();
return;
}
Expand All @@ -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<char[]> pNSFDRVPtr(LoadNSFDRV(m_pDriverData));
char *pNSFDRV = pNSFDRVPtr.get();

// Load driver
std::unique_ptr<char[]> pDriverPtr(LoadDriver(m_pDriverData, m_iDriverAddress)); // // //
Expand All @@ -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);

Expand All @@ -772,6 +777,7 @@ void CCompiler::ExportNES(LPCTSTR lpszFileName, bool EnablePAL)

// Write NES data
std::unique_ptr<CChunkRenderNES> Render(new CChunkRenderNES(&OutputFile, m_iLoadAddress));
Render->StoreNSFDRV(pNSFDRV, m_iNSFDRVSize);
Render->StoreDriver(pDriver, m_iDriverSize);
Render->StoreChunks(m_vChunks);
Render->StoreSamples(m_vSamples);
Expand Down Expand Up @@ -1027,7 +1033,7 @@ void CCompiler::ExportPRG(LPCTSTR lpszFileName, bool EnablePAL)
}

// Build the music data
if (!CompileData()) {
if (!CompileData(true)) {
Cleanup();
return;
}
Expand All @@ -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<char[]> pNSFDRVPtr(LoadNSFDRV(m_pDriverData));
char *pNSFDRV = pNSFDRVPtr.get();

// Load driver
std::unique_ptr<char[]> pDriverPtr(LoadDriver(m_pDriverData, m_iDriverAddress)); // // //
Expand All @@ -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);

Expand All @@ -1071,6 +1082,7 @@ void CCompiler::ExportPRG(LPCTSTR lpszFileName, bool EnablePAL)

// Write NES data
std::unique_ptr<CChunkRenderNES> Render(new CChunkRenderNES(&OutputFile, m_iLoadAddress));
Render->StoreNSFDRV(pNSFDRV, m_iNSFDRVSize);
Render->StoreDriver(pDriver, m_iDriverSize);
Render->StoreChunks(m_vChunks);
Render->StoreSamples(m_vSamples);
Expand Down Expand Up @@ -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

Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion Source/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class CCompiler
void AssignLabels(CMap<CStringA, LPCSTR, int, int> &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();
Expand Down
51 changes: 51 additions & 0 deletions Source/drivers/asm/nes.s
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit fa05bd9

Please sign in to comment.