Fix clang warnings and remove remaining baserom references

This commit is contained in:
octorock 2021-11-20 23:40:47 +01:00
parent 74e416b578
commit db763950bb
16 changed files with 436 additions and 706 deletions

View File

@ -272,49 +272,3 @@ demo_usa: ; @$(MAKE) GAME_VERSION=DEMO_USA
jp: ; @$(MAKE) GAME_VERSION=JP jp: ; @$(MAKE) GAME_VERSION=JP
demo_jp: ; @$(MAKE) GAME_VERSION=DEMO_JP demo_jp: ; @$(MAKE) GAME_VERSION=DEMO_JP
eu: ; @$(MAKE) GAME_VERSION=EU eu: ; @$(MAKE) GAME_VERSION=EU
ifeq ($(GAME_VERSION), USA)
baserom.gba:
$(error "You need to provide a USA ROM as baserom.gba")
.PHONY: baserom_demo.gba baserom_jp.gba baserom_eu.gba baserom_demo_jp.gba
baserom_demo.gba:
baserom_jp.gba:
baserom_eu.gba:
baserom_demo_jp.gba:
endif
ifeq ($(GAME_VERSION), DEMO_USA)
baserom_demo.gba:
$(error "You need to provide a DEMO ROM as baserom_demo.gba")
.PHONY: baserom_jp.gba baserom_eu.gba baserom.gba baserom_demo_jp.gba
baserom.gba:
baserom_jp.gba:
baserom_eu.gba:
baserom_demo_jp.gba:
endif
ifeq ($(GAME_VERSION), JP)
baserom_jp.gba:
$(error "You need to provide a JP ROM as baserom_jp.gba")
.PHONY: baserom_demo.gba baserom_eu.gba baserom.gba baserom_demo_jp.gba
baserom.gba:
baserom_demo.gba:
baserom_eu.gba:
baserom_demo_jp.gba:
endif
ifeq ($(GAME_VERSION), DEMO_JP)
baserom_demo_jp.gba:
$(error "You need to provide a DEMO JP ROM as baserom_demo_jp.gba")
.PHONY: baserom_jp.gba baserom_eu.gba baserom.gba baserom_demo.gba
baserom.gba:
baserom_jp.gba:
baserom_eu.gba:
baserom_demo.gba:
endif
ifeq ($(GAME_VERSION), EU)
baserom_eu.gba:
$(error "You need to provide a EU ROM as baserom_eu.gba")
.PHONY: baserom_demo.gba baserom.gba baserom_jp.gba baserom_demo_jp.gba
baserom.gba:
baserom_jp.gba:
baserom_demo.gba:
baserom_demo_jp.gba:
endif

View File

@ -21023,6 +21023,21 @@
"start": 752492, "start": 752492,
"size": 8 "size": 8
}, },
{
"path": "data_080B7B74/gCollisionMtx.bin",
"start": 752500,
"size": 1210
},
{
"path": "data_080B7B74/gUnk_080B802E.bin",
"start": 753710,
"size": 8850
},
{
"path": "data_080B7B74/gUnk_080BA2C0.bin",
"start": 762560,
"size": 4064
},
{ {
"path": "data_080B7B74/gUnk_080B7B74_1_EU.bin", "path": "data_080B7B74/gUnk_080B7B74_1_EU.bin",
"variants": [ "variants": [
@ -42724,6 +42739,36 @@
"start": 1164390, "start": 1164390,
"size": 34 "size": 34
}, },
{
"path": "demo/save1.bin",
"starts": {
"DEMO_USA": 1171472
},
"size": 1280,
"variants": [
"DEMO_USA"
]
},
{
"path": "demo/save2.bin",
"starts": {
"DEMO_USA": 1172752
},
"size": 1280,
"variants": [
"DEMO_USA"
]
},
{
"path": "demo/save3.bin",
"starts": {
"DEMO_USA": 1174032
},
"size": 1280,
"variants": [
"DEMO_USA"
]
},
{ {
"offsets": { "offsets": {
"DEMO_USA": 2572, "DEMO_USA": 2572,
@ -48401,6 +48446,12 @@
"size": 60, "size": 60,
"type": "animation" "type": "animation"
}, },
{
"path": "animations/gSpriteAnimations_TorchTrapProjectile_0_0.bin",
"start": 1221600,
"size": 20,
"type": "animation"
},
{ {
"path": "animations/gSpriteAnimations_TorchTrapProjectile_1_0.bin", "path": "animations/gSpriteAnimations_TorchTrapProjectile_1_0.bin",
"start": 1221628, "start": 1221628,

View File

@ -5,7 +5,7 @@
.align 2 .align 2
gSpriteAnimations_TorchTrapProjectile_0_0:: @ 0812A3E0 gSpriteAnimations_TorchTrapProjectile_0_0:: @ 0812A3E0
.incbin "baserom.gba", 0x12A3E0, 0x0000014 .include "animations/gSpriteAnimations_TorchTrapProjectile_0_0.s"
gSpriteAnimations_TorchTrapProjectile_0:: @ 0812A3F4 gSpriteAnimations_TorchTrapProjectile_0:: @ 0812A3F4
.4byte gSpriteAnimations_TorchTrapProjectile_0_0 .4byte gSpriteAnimations_TorchTrapProjectile_0_0

View File

@ -5,13 +5,13 @@
.align 2 .align 2
gCollisionMtx:: @ 080B7B74 gCollisionMtx:: @ 080B7B74
.incbin "baserom.gba", 0x0B7B74, 0x00004BA .incbin "data_080B7B74/gCollisionMtx.bin"
gUnk_080B802E:: @ 080B802E gUnk_080B802E:: @ 080B802E
.incbin "baserom.gba", 0x0B802E, 0x0002292 .incbin "data_080B7B74/gUnk_080B802E.bin"
gUnk_080BA2C0:: @ 080BA2C0 gUnk_080BA2C0:: @ 080BA2C0
.incbin "baserom.gba", 0x0BA2C0, 0x0000FE0 .incbin "data_080B7B74/gUnk_080BA2C0.bin"
gUnk_080BB2A0:: @ 080BB2A0 gUnk_080BB2A0:: @ 080BB2A0
.ifdef EU .ifdef EU

View File

@ -59,9 +59,9 @@ static SaveResult (*const sSaveHandlers[])(u32) = { HandleSaveInit, HandleSaveIn
#if defined(DEMO_USA) || defined(DEMO_JP) #if defined(DEMO_USA) || defined(DEMO_JP)
#ifdef DEMO_USA #ifdef DEMO_USA
asm("demoPointer1: .incbin \"baserom_demo.gba\", 0x11e010, 0x500"); asm("demoPointer1: .incbin \"demo/save1.bin\"");
asm("demoPointer2: .incbin \"baserom_demo.gba\", 0x11e510, 0x500"); asm("demoPointer2: .incbin \"demo/save2.bin\"");
asm("demoPointer3: .incbin \"baserom_demo.gba\", 0x11ea10, 0x500"); asm("demoPointer3: .incbin \"demo/save3.bin\"");
extern const u8 demoPointer1[]; extern const u8 demoPointer1[];
extern const u8 demoPointer2[]; extern const u8 demoPointer2[];

View File

@ -44,20 +44,12 @@ void Seek(long offset);
std::vector<std::uint32_t> trackPointers; std::vector<std::uint32_t> trackPointers;
/*const int FILE_OFFSET = 0x10000;
// const int START_OFFSET = 0x1c;
const int START_OFFSET = 0x2DE4;
const int REDUCE_POINTERS = 0;*/
const int FILE_OFFSET = 0;
const int START_OFFSET = 0xDE38F0;
const unsigned int REDUCE_POINTERS = 0x8000000; const unsigned int REDUCE_POINTERS = 0x8000000;
extern int g_fileStartOffset; // TODO move to header extern int g_fileStartOffset; // TODO move to header
void ReadAgbSong() { void ReadAgbSong() {
Seek(g_fileStartOffset);
Seek(FILE_OFFSET + g_fileStartOffset);
int numTracks = ReadInt8(); int numTracks = ReadInt8();
int numBlocks = ReadInt8(); int numBlocks = ReadInt8();
@ -101,7 +93,6 @@ std::vector<std::vector<Event>> trackEvents;
std::vector<Event> metaEvents; std::vector<Event> metaEvents;
int convertTime(int time) { int convertTime(int time) {
// event.time = (24 * g_clocksPerBeat * event.time) / g_midiTimeDiv;
return ((float)time * g_midiTimeDiv) / (24 * g_clocksPerBeat); return ((float)time * g_midiTimeDiv) / (24 * g_clocksPerBeat);
} }
@ -112,19 +103,13 @@ std::uint32_t GetCurrentPtr() {
} }
std::uint32_t PtrToFileAddr(std::uint32_t ptr) { std::uint32_t PtrToFileAddr(std::uint32_t ptr) {
return ptr + FILE_OFFSET - REDUCE_POINTERS; return ptr - REDUCE_POINTERS;
} }
void insertAtCorrectTimeFromEnd(std::vector<Event>& events, const Event& event) { void insertAtCorrectTimeFromEnd(std::vector<Event>& events, const Event& event) {
// std::printf("time: %d\n", event.time);
for (auto it = events.rbegin(); it != events.rend(); it++) { for (auto it = events.rbegin(); it != events.rend(); it++) {
if ((*it).time <= event.time) { if ((*it).time <= event.time) {
events.insert(it.base(), event); events.insert(it.base(), event);
/* for (const auto& event : events) {
std::printf("e: %X t: %d\n", (int)event.type, event.time);
}
std::cin.ignore();*/
return; return;
} }
} }
@ -132,15 +117,9 @@ void insertAtCorrectTimeFromEnd(std::vector<Event>& events, const Event& event)
} }
void insertAtCorrectTimeFromStart(std::vector<Event>& events, const Event& event) { void insertAtCorrectTimeFromStart(std::vector<Event>& events, const Event& event) {
// std::printf("time: %d\n", event.time);
for (auto it = events.begin(); it != events.end(); it++) { for (auto it = events.begin(); it != events.end(); it++) {
if ((*it).time >= event.time) { if ((*it).time >= event.time) {
events.insert(it, event); events.insert(it, event);
/* for (const auto& event : events) {
std::printf("e: %X t: %d\n", (int)event.type, event.time);
}
std::cin.ignore();*/
return; return;
} }
} }
@ -149,9 +128,6 @@ void insertAtCorrectTimeFromStart(std::vector<Event>& events, const Event& event
void ReadAgbTracks() { void ReadAgbTracks() {
size_t count = 0; size_t count = 0;
int addedPadding = 8; int addedPadding = 8;
// TODO configurable??? // TODO configurable???
@ -168,11 +144,10 @@ void ReadAgbTracks() {
for (uint32_t trackPointer : trackPointers) { for (uint32_t trackPointer : trackPointers) {
std::vector<Event> events; std::vector<Event> events;
count ++; count++;
if (g_verbose) if (g_verbose)
std::printf("\n\ntrackPointer: %X -> %X %ld\n", trackPointer, trackPointer - REDUCE_POINTERS, count); std::printf("\n\ntrackPointer: %X -> %X %ld\n", trackPointer, trackPointer - REDUCE_POINTERS, count);
// Search for loop in this trac // Search for loop in this trac
bool hasLoop = false; bool hasLoop = false;
std::uint32_t loopAddress = 0; std::uint32_t loopAddress = 0;
@ -180,10 +155,12 @@ void ReadAgbTracks() {
int loopStartTime = 0; int loopStartTime = 0;
unsigned int trackEnd = unsigned int trackEnd =
(trackPointers.size() > count ? trackPointers[count] : (g_fileStartOffset + REDUCE_POINTERS)) ; // Use offset to header as end for last track (trackPointers.size() > count
? trackPointers[count]
: (g_fileStartOffset + REDUCE_POINTERS)); // Use offset to header as end for last track
if (g_verbose) if (g_verbose)
std::printf("End of track: %X\n", trackEnd); std::printf("End of track: %X\n", trackEnd);
Seek(FILE_OFFSET + trackEnd - REDUCE_POINTERS); Seek(trackEnd - REDUCE_POINTERS);
// search for a few bytes whether there is a loop end // search for a few bytes whether there is a loop end
for (int i = 5; i < 10 + addedPadding; i++) { for (int i = 5; i < 10 + addedPadding; i++) {
@ -191,11 +168,11 @@ void ReadAgbTracks() {
// Ignore GOTOs from the previous track. // Ignore GOTOs from the previous track.
continue; continue;
} }
Seek(FILE_OFFSET + trackEnd - REDUCE_POINTERS -i); Seek(trackEnd - REDUCE_POINTERS - i);
if (ReadInt8() == GOTO) { if (ReadInt8() == GOTO) {
if (g_verbose) if (g_verbose)
std::printf("Has loop: %d\n", i); std::printf("Has loop: %d\n", i);
loopAddress = lReadInt32() + FILE_OFFSET - REDUCE_POINTERS; loopAddress = lReadInt32() - REDUCE_POINTERS;
if (loopAddress > 0x1000000) { if (loopAddress > 0x1000000) {
// The 0xB1 was probably part of the pointer or something. // The 0xB1 was probably part of the pointer or something.
continue; continue;
@ -211,32 +188,17 @@ void ReadAgbTracks() {
if (g_verbose) if (g_verbose)
std::printf("Has loop: %d, %X\n", hasLoop, loopAddress); std::printf("Has loop: %d, %X\n", hasLoop, loopAddress);
// Read all track events // Read all track events
Seek(trackPointer - REDUCE_POINTERS);
Seek(FILE_OFFSET + trackPointer - REDUCE_POINTERS);
int type = ReadInt8(); int type = ReadInt8();
// std::printf("type: %X\n", type);
// VOL? // VOL?
if (type == VOL) { if (type == VOL) {
// TODO extract to function and reuse below
int val = ReadInt8(); int val = ReadInt8();
if (g_verbose) if (g_verbose)
std::printf("ignore vol: %X\n", val); std::printf("ignore vol: %X\n", val);
// TODO if this is a change to 127*mvl/mxv, there was no event in midi
/*std::printf("VOL: %X\n", val);
Event event;
event.type = EventType::Controller;
event.param1 = 0x7;
event.param2 = std::round((float)val * MXV / MVL); // TODO inverse "%u*%s_mvl/mxv", event.param2,
g_asmLabel.c_str()); events.push_back(event);*/
type = ReadInt8(); type = ReadInt8();
} }
@ -249,7 +211,6 @@ void ReadAgbTracks() {
if (g_verbose) if (g_verbose)
std::printf("KEYSH: %d\n", keyShift); std::printf("KEYSH: %d\n", keyShift);
// TODO initial shift is always 0? Or is this set as the whole key shift? // TODO initial shift is always 0? Or is this set as the whole key shift?
} else { } else {
std::printf("Error: initial type %X not implemented\n", type); std::printf("Error: initial type %X not implemented\n", type);
return; return;
@ -273,11 +234,10 @@ void ReadAgbTracks() {
int returnPtr = 0; int returnPtr = 0;
while (!endOfTrack) { while (!endOfTrack) {
// std::printf("type: %X\n", type); if (hasLoop && !foundLoop && GetCurrentPtr() - 1 == loopAddress) {
if (hasLoop && !foundLoop && GetCurrentPtr()-1 == loopAddress) {
if (g_verbose) if (g_verbose)
std::printf("<<<< inserted loop start\n"); std::printf("<<<< inserted loop start\n");
//foundLoop = true; // foundLoop = true;
loopStartTime = currentTime; loopStartTime = currentTime;
Event event; Event event;
event.time = loopStartTime; event.time = loopStartTime;
@ -291,8 +251,6 @@ void ReadAgbTracks() {
// Repeat last command // Repeat last command
Skip(-1); Skip(-1);
type = lastCommand; type = lastCommand;
// std::printf("%X ", type);
// std::printf("Repeat last command: %X\n", lastCommand);
if (g_verbose) if (g_verbose)
std::printf("(repeat cmd) "); std::printf("(repeat cmd) ");
} else { } else {
@ -310,7 +268,6 @@ void ReadAgbTracks() {
Event event; Event event;
event.time = currentTime; event.time = currentTime;
event.type = EventType::Tempo; event.type = EventType::Tempo;
// 60000000 / event.param2
event.param2 = 60000000 / (val * 2); event.param2 = 60000000 / (val * 2);
metaEvents.push_back(event); metaEvents.push_back(event);
@ -328,9 +285,7 @@ void ReadAgbTracks() {
break; break;
} }
case VOL: { case VOL: {
// const int MVL = 90; // TODO configurable per song?
const int MVL = 128; const int MVL = 128;
const int MXV = 0x7F; const int MXV = 0x7F;
int val = ReadInt8(); int val = ReadInt8();
@ -340,8 +295,7 @@ void ReadAgbTracks() {
event.time = currentTime; event.time = currentTime;
event.type = EventType::Controller; event.type = EventType::Controller;
event.param1 = 0x7; event.param1 = 0x7;
event.param2 = std::ceil((float)val * MXV / event.param2 = std::ceil((float)val * MXV / MVL);
MVL); // TODO inverse "%u*%s_mvl/mxv", event.param2, g_asmLabel.c_str());
events.push_back(event); events.push_back(event);
break; break;
} }
@ -414,7 +368,6 @@ void ReadAgbTracks() {
// Already handled // Already handled
loopEndTime = currentTime; loopEndTime = currentTime;
break; break;
} }
case EOT: { case EOT: {
@ -601,7 +554,6 @@ void ReadAgbTracks() {
} }
default: default:
if (type >= 0x80 && type <= 0x80 + 48) { if (type >= 0x80 && type <= 0x80 + 48) {
const int lenTbl[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, const int lenTbl[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 28, 30, 32, 36, 40, 42, 44, 48, 52, 17, 18, 19, 20, 21, 22, 23, 24, 28, 30, 32, 36, 40, 42, 44, 48, 52,
54, 56, 60, 64, 66, 68, 72, 76, 78, 80, 84, 88, 90, 92, 96 }; 54, 56, 60, 64, 66, 68, 72, 76, 78, 80, 84, 88, 90, 92, 96 };
@ -613,65 +565,31 @@ void ReadAgbTracks() {
patternDuration += wait; patternDuration += wait;
if (!currentlyPlayingNotes.empty()) { if (!currentlyPlayingNotes.empty()) {
// std::printf("Testing... %d\n", (int)currentlyPlayingNotes.size());
for (auto it = currentlyPlayingNotes.begin(); it != currentlyPlayingNotes.end();) { for (auto it = currentlyPlayingNotes.begin(); it != currentlyPlayingNotes.end();) {
Event& note = *it; // Modify the note in the list if we don't remove it now. Event& note = *it; // Modify the note in the list if we don't remove it now.
note.time -= wait; note.time -= wait;
if (note.time <= 0) { if (note.time <= 0) {
/*if (note.time < 0) {
std::printf("<0: %d\n", note.time);
std::cin.ignore();
}*/
// note.time += currentTime; // Set to the global time the note was finished.
// TODO negative=
note.time += currentTime + wait; note.time += currentTime + wait;
// std::printf("Note off at %d\n", note.time);
insertAtCorrectTimeFromEnd(events, note); insertAtCorrectTimeFromEnd(events, note);
it = currentlyPlayingNotes.erase(it); it = currentlyPlayingNotes.erase(it);
} else { } else {
++it; ++it;
} }
// // TODO handle multiple notes playing at the same time on the same track?
// if (wait >= currentlyPlayingNotes[0].time) {
// Event event = currentlyPlayingNotes[0];
// std::printf("Finished playing note\n");
// event.time = currentTime;
// events.push_back(event);
// currentlyPlayingNotes.pop_back();
// } else {
// currentlyPlayingNotes[0].time -= wait;
// }
} }
// std::printf("Done... %d\n", (int)currentlyPlayingNotes.size());
} }
currentTime += wait; currentTime += wait;
/* if (wait > 0) {
Event event;
event.type = EventType::Wait;
event.time = currentTime+convertTime(wait);
events.push_back(event);
}*/
} else if (type >= 0xD0 && type <= 0xD0 + 47) { } else if (type >= 0xD0 && type <= 0xD0 + 47) {
// Handle note with a fixed length // Handle note with a fixed length
int noteType = type; int noteType = type;
int note = ReadInt8(); int note = ReadInt8();
int velocity = 0; int velocity = 0;
int length = 0; int length = 0;
bool usedLastNote = false; bool usedLastNote = false;
bool usedLastVelocity = false; bool usedLastVelocity = false;
if (note < 0x80) { // a valid note if (note < 0x80) { // a valid note
lastNote = note; lastNote = note;
velocity = ReadInt8(); velocity = ReadInt8();
if (velocity < 0x80) { // a valid velocity if (velocity < 0x80) { // a valid velocity
// std::printf("Explicit velocity%d\n", velocity);
lastVelocity = velocity; lastVelocity = velocity;
length = ReadInt8(); length = ReadInt8();
if (length < 0x80) { // a valid length if (length < 0x80) { // a valid length
@ -681,7 +599,6 @@ void ReadAgbTracks() {
length = 0; length = 0;
} }
} else { } else {
// std::printf("Reusing last vel %d\n", lastVelocity);
type = velocity; type = velocity;
velocity = lastVelocity; velocity = lastVelocity;
usedLastVelocity = true; usedLastVelocity = true;
@ -732,56 +649,12 @@ void ReadAgbTracks() {
} }
std::printf("\n"); std::printf("\n");
} }
// std::printf("Wait before convert: %d\n", wait);
// std::printf("Wait after convert: %d\n", event.param2);
events.push_back(event); events.push_back(event);
event.type = EventType::NoteOff; event.type = EventType::NoteOff;
event.time = wait; event.time = wait;
// std::printf("Should be off at %d...\n", currentTime+wait);
// std::printf("Note length: %d\n", wait);
// std::cin.ignore();
currentlyPlayingNotes.push_back(event); currentlyPlayingNotes.push_back(event);
// event.param2 = wait;
/* int duration = wait; // event.param2;
if (!g_exactGateTime) { // && duration < 96)
// TODO inverse lut
std::printf("asdf\n");
for (size_t i = 0; i < 97; i++) {
if (g_noteDurationLUT[i] == duration) {
duration = i;
std::printf("test%d\n", (int)i);
break;
}
}
}
if (duration == 1)
duration = 0;
// event.param2 = (duration * g_midiTimeDiv) /(24 * g_clocksPerBeat);
event.param2 = g_noteDurationInverseLUT[duration];
std::printf("Wait after convert: %d\n", event.param2);*/
/*
event.param1 = g_noteVelocityLUT[event.param1];
std::uint32_t duration = (24 * g_clocksPerBeat * event.param2) / g_midiTimeDiv;
if (duration == 0)
duration = 1;
if (!g_exactGateTime && duration < 96)
duration = g_noteDurationLUT[duration];
event.param2 = duration;
*/
continue; // Next type was already read continue; // Next type was already read
} else { } else {
std::printf("ERROR: Unhandled type %X\n", type); std::printf("ERROR: Unhandled type %X\n", type);
return; return;
@ -789,8 +662,6 @@ void ReadAgbTracks() {
break; break;
} }
// TODO notes, waits, // TODO notes, waits,
type = ReadInt8(); type = ReadInt8();
} }
@ -816,30 +687,10 @@ void ReadAgbTracks() {
std::cin.ignore(); std::cin.ignore();
} }
/*if (foundLoop) {
// Place the loop begin event as the last event for that time on the meta events track.
// TODO this does not help as TEMPO events are not placed on the meta track?
Event event;
event.time = loopStartTime;
event.type = EventType::LoopBegin;
insertAtCorrectTimeFromEnd(events, event);
std::printf("--- Inserting loop at %d\n", loopStartTime);
}*/
if (hasLoop) { if (hasLoop) {
Event event; Event event;
event.type = EventType::LoopEnd; event.type = EventType::LoopEnd;
event.time = loopEndTime; event.time = loopEndTime;
// Place loop end at the end of the track that has the latest end.
/*for (const auto& events : trackEvents) {
int trackEnd = events.back().time;
if (trackEnd > event.time) {
event.time = trackEnd;
}
}*/
// std::printf("####### loop End %d\n", event.time);
//events.push_back(event);
insertAtCorrectTimeFromEnd(events, event); insertAtCorrectTimeFromEnd(events, event);
} }
@ -853,8 +704,6 @@ void ReadAgbTracks() {
trackEvents.push_back(events); trackEvents.push_back(events);
} }
// Insert manual time signature change event // Insert manual time signature change event
for (const auto& change : timeSignatureChanges) { for (const auto& change : timeSignatureChanges) {
bool inserted = false; bool inserted = false;
@ -866,17 +715,14 @@ void ReadAgbTracks() {
for (size_t i = 0; i < metaEvents.size() - 1; i++) { for (size_t i = 0; i < metaEvents.size() - 1; i++) {
int prevTime = metaEvents[i].time; int prevTime = metaEvents[i].time;
int nextTime = metaEvents[i + 1].time; int nextTime = metaEvents[i + 1].time;
//std::printf("%d < %d <= %d?\n", prevTime, event.time, nextTime);
if (event.time > prevTime && event.time <= nextTime) { if (event.time > prevTime && event.time <= nextTime) {
//std::printf("axd%d\n", (int)metaEvents.size());
metaEvents.insert(metaEvents.begin() + i + 1, event); metaEvents.insert(metaEvents.begin() + i + 1, event);
inserted = true; inserted = true;
break; break;
} }
} }
//std::printf("asd %d\n", (int)metaEvents.size());
if (!inserted) { if (!inserted) {
metaEvents.push_back(event); metaEvents.push_back(event);
} }
} }
} }

View File

@ -23,8 +23,7 @@
#include <cstdarg> #include <cstdarg>
// Reports an error diagnostic and terminates the program. // Reports an error diagnostic and terminates the program.
[[noreturn]] void RaiseError(const char* format, ...) [[noreturn]] void RaiseError(const char* format, ...) {
{
const int bufferSize = 1024; const int bufferSize = 1024;
char buffer[bufferSize]; char buffer[bufferSize];
std::va_list args; std::va_list args;

View File

@ -49,60 +49,49 @@ int g_denominatorExp = 2;
bool g_verbose = false; bool g_verbose = false;
std::vector<TimeSignatureChange> timeSignatureChanges; std::vector<TimeSignatureChange> timeSignatureChanges;
[[noreturn]] static void PrintUsage() {
std::printf("Usage: AGB2MID baserom start_offset input_file output_file [options]\n"
[[noreturn]] static void PrintUsage() "\n"
{ " baserom path to the baserom\n"
std::printf( " start_offset offset to the sound header\n"
"Usage: AGB2MID baserom start_offset input_file output_file [options]\n" " input_file filename(.s) for AGB file\n"
"\n" " output_file filename(.mid) of MIDI file (default:input_file)\n"
" baserom path to the baserom\n" "\n"
" start_offset offset to the sound header\n" "options -L??? label for assembler (default:output_file)\n"
" input_file filename(.s) for AGB file\n" " -V??? master volume (default:127)\n"
" output_file filename(.mid) of MIDI file (default:input_file)\n" " -G??? voice group number (default:0)\n"
"\n" " -P??? priority (default:0)\n"
"options -L??? label for assembler (default:output_file)\n" " -R??? reverb (default:off)\n"
" -V??? master volume (default:127)\n" " -X 48 clocks/beat (default:24 clocks/beat)\n"
" -G??? voice group number (default:0)\n" " -E exact gate-time\n"
" -P??? priority (default:0)\n" " -N no compression\n"
" -R??? reverb (default:off)\n" " -n??? midi time nominator\n"
" -X 48 clocks/beat (default:24 clocks/beat)\n" " -d??? midi time denominator\n"
" -E exact gate-time\n" " -t ? ? ? time signature change\n"
" -N no compression\n" " -v verbose\n");
" -n??? midi time nominator\n"
" -d??? midi time denominator\n"
" -t ? ? ? time signature change\n"
" -v verbose\n"
);
std::exit(1); std::exit(1);
} }
static std::string StripExtension(std::string s) static std::string StripExtension(std::string s) {
{
std::size_t pos = s.find_last_of('.'); std::size_t pos = s.find_last_of('.');
if (pos > 0 && pos != std::string::npos) if (pos > 0 && pos != std::string::npos) {
{
s = s.substr(0, pos); s = s.substr(0, pos);
} }
return s; return s;
} }
static std::string GetExtension(std::string s) static std::string GetExtension(std::string s) {
{
std::size_t pos = s.find_last_of('.'); std::size_t pos = s.find_last_of('.');
if (pos > 0 && pos != std::string::npos) if (pos > 0 && pos != std::string::npos) {
{
return s.substr(pos + 1); return s.substr(pos + 1);
} }
return ""; return "";
} }
static std::string BaseName(std::string s) static std::string BaseName(std::string s) {
{
std::size_t posAfterSlash = s.find_last_of("/\\"); std::size_t posAfterSlash = s.find_last_of("/\\");
if (posAfterSlash == std::string::npos) if (posAfterSlash == std::string::npos)
@ -117,11 +106,10 @@ static std::string BaseName(std::string s)
return s; return s;
} }
static const char *GetArgument(int argc, char **argv, int& index) static const char* GetArgument(int argc, char** argv, int& index) {
{
assert(index >= 0 && index < argc); assert(index >= 0 && index < argc);
const char *option = argv[index]; const char* option = argv[index];
assert(option != nullptr); assert(option != nullptr);
assert(option[0] == '-'); assert(option[0] == '-');
@ -131,144 +119,133 @@ static const char *GetArgument(int argc, char **argv, int& index)
return option + 2; return option + 2;
// Otherwise, try to get the next arg. // Otherwise, try to get the next arg.
if (index + 1 < argc) if (index + 1 < argc) {
{
index++; index++;
return argv[index]; return argv[index];
} } else {
else
{
return nullptr; return nullptr;
} }
} }
int main(int argc, char** argv) int main(int argc, char** argv) {
{
std::string baseromPath; std::string baseromPath;
std::string startOffset; std::string startOffset;
std::string inputFilename; std::string inputFilename;
std::string outputFilename; std::string outputFilename;
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++) {
{ const char* option = argv[i];
const char *option = argv[i];
if (option[0] == '-' && option[1] != '\0') if (option[0] == '-' && option[1] != '\0') {
{ const char* arg;
const char *arg;
switch (option[1]) switch (option[1]) {
{ case 'E':
case 'E': g_exactGateTime = true;
g_exactGateTime = true; break;
break; case 'G':
case 'G': arg = GetArgument(argc, argv, i);
arg = GetArgument(argc, argv, i); if (arg == nullptr)
if (arg == nullptr) PrintUsage();
PrintUsage(); g_voiceGroup = std::stoi(arg);
g_voiceGroup = std::stoi(arg); break;
break; case 'L':
case 'L': arg = GetArgument(argc, argv, i);
arg = GetArgument(argc, argv, i); if (arg == nullptr)
if (arg == nullptr) PrintUsage();
PrintUsage(); g_asmLabel = arg;
g_asmLabel = arg; break;
break; case 'N':
case 'N': g_compressionEnabled = false;
g_compressionEnabled = false; break;
break; case 'P':
case 'P': arg = GetArgument(argc, argv, i);
arg = GetArgument(argc, argv, i); if (arg == nullptr)
if (arg == nullptr) PrintUsage();
PrintUsage(); g_priority = std::stoi(arg);
g_priority = std::stoi(arg); break;
break; case 'R':
case 'R': arg = GetArgument(argc, argv, i);
arg = GetArgument(argc, argv, i); if (arg == nullptr)
if (arg == nullptr) PrintUsage();
PrintUsage(); g_reverb = std::stoi(arg);
g_reverb = std::stoi(arg); break;
break; case 'V':
case 'V': arg = GetArgument(argc, argv, i);
arg = GetArgument(argc, argv, i); if (arg == nullptr)
if (arg == nullptr) PrintUsage();
PrintUsage(); g_masterVolume = std::stoi(arg);
g_masterVolume = std::stoi(arg); break;
break; case 'X':
case 'X': g_clocksPerBeat = 2;
g_clocksPerBeat = 2; break;
break; case 'n':
case 'n': arg = GetArgument(argc, argv, i);
arg = GetArgument(argc, argv, i); if (arg == nullptr)
if (arg == nullptr) PrintUsage();
PrintUsage(); g_nominator = std::stoi(arg);
g_nominator = std::stoi(arg); break;
break; case 'd': {
case 'd': arg = GetArgument(argc, argv, i);
{ if (arg == nullptr)
arg = GetArgument(argc, argv, i); PrintUsage();
if (arg == nullptr) int denominator = std::stoi(arg);
PrintUsage(); if (denominator == 1) {
int denominator = std::stoi(arg); g_denominatorExp = 0;
if (denominator == 1) { } else if (denominator == 2) {
g_denominatorExp = 0; g_denominatorExp = 1;
} else if (denominator == 2) { } else if (denominator == 4) {
g_denominatorExp = 1; g_denominatorExp = 2;
} else if (denominator == 4) { } else if (denominator == 8) {
g_denominatorExp = 2; g_denominatorExp = 3;
} else if (denominator == 8) { } else if (denominator == 16) {
g_denominatorExp = 3; g_denominatorExp = 4;
} else if (denominator == 16) { } else if (denominator == 32) {
g_denominatorExp = 4; g_denominatorExp = 5;
} else if (denominator == 32) { } else {
g_denominatorExp = 5; std::printf("ERROR: denominator %d\n", denominator);
} else { exit(1);
std::printf("ERROR: denominator %d\n", denominator); }
exit(1); break;
} }
break; case 't': {
} int nominator = std::stoi(argv[i + 1]);
case 't': int denominator = std::stoi(argv[i + 2]);
{ if (denominator == 1) {
int nominator = std::stoi(argv[i+1]); denominator = 0;
int denominator = std::stoi(argv[i+2]); } else if (denominator == 2) {
if (denominator == 1) { denominator = 1;
denominator = 0; } else if (denominator == 4) {
} else if (denominator == 2) { denominator = 2;
denominator = 1; } else if (denominator == 8) {
} else if (denominator == 4) { denominator = 3;
denominator = 2; } else if (denominator == 16) {
} else if (denominator == 8) { denominator = 4;
denominator = 3; } else if (denominator == 32) {
} else if (denominator == 16) { denominator = 5;
denominator = 4; } else {
} else if (denominator == 32) { std::printf("ERROR: denominator %d\n", denominator);
denominator = 5; exit(1);
} else { }
std::printf("ERROR: denominator %d\n", denominator); int time = std::stoi(argv[i + 3]);
exit(1); i += 3;
} TimeSignatureChange change;
int time = std::stoi(argv[i+3]); change.nominator = nominator;
i += 3; change.denominator = denominator;
TimeSignatureChange change; change.time = time;
change.nominator = nominator;
change.denominator = denominator;
change.time = time;
// TODO sort by time? // TODO sort by time?
timeSignatureChanges.push_back(change); timeSignatureChanges.push_back(change);
break; break;
}
case 'v': {
g_verbose = true;
break;
}
default:
PrintUsage();
} }
case 'v': { } else {
g_verbose = true;
break;
}
default:
PrintUsage();
}
}
else
{
if (baseromPath.empty()) if (baseromPath.empty())
baseromPath = argv[i]; baseromPath = argv[i];
else if (startOffset.empty()) else if (startOffset.empty())
@ -285,16 +262,12 @@ int main(int argc, char** argv)
if (inputFilename.empty()) if (inputFilename.empty())
PrintUsage(); PrintUsage();
/*if (GetExtension(inputFilename) != "out") // TODO unify with baserom parameter?
RaiseError("input filename extension is not \"out\"");
*/
if (outputFilename.empty()) if (outputFilename.empty())
outputFilename = StripExtension(inputFilename) + ".mid"; outputFilename = StripExtension(inputFilename) + ".mid";
if (GetExtension(outputFilename) != "mid") if (GetExtension(outputFilename) != "mid")
RaiseError("output filename extension is not \"mid\""); RaiseError("output filename extension is not \"mid\"");
if (g_asmLabel.empty()) if (g_asmLabel.empty())
g_asmLabel = BaseName(outputFilename); g_asmLabel = BaseName(outputFilename);
@ -310,16 +283,10 @@ int main(int argc, char** argv)
g_fileStartOffset = std::stoul(startOffset, nullptr, 16); g_fileStartOffset = std::stoul(startOffset, nullptr, 16);
ReadAgbSong(); ReadAgbSong();
ReadAgbTracks(); ReadAgbTracks();
WriteMidiFile(); WriteMidiFile();
/*ReadMidiFileHeader();
PrintAgbHeader();
ReadMidiTracks();
PrintAgbFooter();*/
std::fclose(g_inputFile); std::fclose(g_inputFile);
std::fclose(g_outputFile); std::fclose(g_outputFile);

View File

@ -222,76 +222,71 @@ void WriteTrack(int channelId, const std::vector<Event>& events) {
bool DEBUG = g_verbose && false; bool DEBUG = g_verbose && false;
for (const auto& event : events) { for (const auto& event : events) {
if (DEBUG) {
if (DEBUG) { std::printf("TIME: %d\n", event.time); } std::printf("TIME: %d\n", event.time);
}
writeDeltaTime(data, event.time - currentTime);
/* if (event.type == EventType::Wait) { // Handle special wait event
waiting += event.time;
continue;
}*/
// TODO can remove type parameter if it is the same type as before?
// Delta time to previous event
// std::printf("delta Time: %d\n", event.time);
// TODO make sure currentTime <= event.time!!
writeDeltaTime(data, event.time - currentTime); // - previousTime);
currentTime = event.time; currentTime = event.time;
// previousTime = event.time;
switch (event.type) { switch (event.type) {
case EventType::InstrumentChange: case EventType::InstrumentChange:
if (DEBUG) { std::printf("InstrumentChange\n");} if (DEBUG) {
data.push_back(0xC0 + channelId); // type std::printf("InstrumentChange\n");
data.push_back(event.param1); // instrument }
data.push_back(0xC0 + channelId); // type
data.push_back(event.param1); // instrument
break; break;
case EventType::Controller: case EventType::Controller:
if (DEBUG) { std::printf("Controller\n");} if (DEBUG) {
/*if (event.param1 == 7 && !firstVol) { std::printf("Controller\n");
firstVol = true; // hack TODO }
} else {*/ data.push_back(0xB0 + channelId); // type
data.push_back(0xB0 + channelId); // type data.push_back(event.param1); // controller index
//} data.push_back(event.param2); // value
data.push_back(event.param1); // controller index
data.push_back(event.param2); // value
break; break;
case EventType::Note: case EventType::Note:
if (DEBUG) { std::printf("Note\n");} if (DEBUG) {
data.push_back(0x90 + channelId); // type std::printf("Note\n");
data.push_back(event.note); // note }
data.push_back(event.param1); // velocity data.push_back(0x90 + channelId); // type
data.push_back(event.note); // note
data.push_back(event.param1); // velocity
break; break;
case EventType::NoteOff: case EventType::NoteOff:
if (DEBUG) { std::printf("NoteOff\n");} if (DEBUG) {
std::printf("NoteOff\n");
}
// Wait and note_end // Wait and note_end
data.push_back(0x80 + channelId); // type data.push_back(0x80 + channelId); // type
data.push_back(event.note); // note data.push_back(event.note); // note
data.push_back(0); // Ignored velocity data.push_back(0); // Ignored velocity
break; break;
case EventType::TimeSignature: case EventType::TimeSignature: {
{ if (DEBUG) {
if (DEBUG) { std::printf("TimeSignature\n");} std::printf("TimeSignature\n");
}
// One time meta event at the beginning of the meta track. // One time meta event at the beginning of the meta track.
data.push_back(0xff); // meta data.push_back(0xff); // meta
data.push_back(88); // TIME_SIGNATURE data.push_back(88); // TIME_SIGNATURE
writeDeltaTime(data, 4); // m_length writeDeltaTime(data, 4); // m_length
data.push_back(event.param1); // numerator data.push_back(event.param1); // numerator
data.push_back(event.param2); // denominator data.push_back(event.param2); // denominator
data.push_back(24 * g_clocksPerBeat); // clocksPerClick data.push_back(24 * g_clocksPerBeat); // clocksPerClick
data.push_back(8); // 32ndPer4th data.push_back(8); // 32ndPer4th
break; break;
} }
case EventType::Tempo: case EventType::Tempo:
if (DEBUG) { std::printf("Tempo\n");} if (DEBUG) {
data.push_back(0xff); // meta std::printf("Tempo\n");
data.push_back(81); // META_TEMPO }
writeDeltaTime(data, 3); // only valid tempo size is 3 data.push_back(0xff); // meta
data.push_back(81); // META_TEMPO
writeDeltaTime(data, 3); // only valid tempo size is 3
writeInt24(data, event.param2); // usecPerQuarterNote writeInt24(data, event.param2); // usecPerQuarterNote
break; break;
case EventType::Extended: case EventType::Extended:
if (DEBUG) { std::printf("Extended\n");} if (DEBUG) {
std::printf("Extended\n");
}
if (event.note == 0x1d) { if (event.note == 0x1d) {
// for some reason the first one is in a meta change? // for some reason the first one is in a meta change?
data.push_back(0xb0); data.push_back(0xb0);
@ -300,41 +295,47 @@ void WriteTrack(int channelId, const std::vector<Event>& events) {
data.push_back(event.param1); data.push_back(event.param1);
writeDeltaTime(data, 0); // Next midi event writeDeltaTime(data, 0); // Next midi event
data.push_back(0x1d); // TODO why twice 0x1d? event.note); data.push_back(0x1d); // TODO why twice 0x1d? event.note);
data.push_back(event.param2); data.push_back(event.param2);
break; break;
case EventType::PitchBend: case EventType::PitchBend:
if (DEBUG) { std::printf("PitchBend\n");} if (DEBUG) {
std::printf("PitchBend\n");
}
data.push_back(0xe0 + channelId); // petch bend data.push_back(0xe0 + channelId); // petch bend
data.push_back(0); // lsb data.push_back(0); // lsb
data.push_back(event.param2); data.push_back(event.param2);
break; break;
case EventType::EndOfTrack: case EventType::EndOfTrack:
if (DEBUG) { std::printf("EndOfTrack\n");} if (DEBUG) {
std::printf("EndOfTrack\n");
}
// End of track // End of track
data.push_back(0xff); // meta data.push_back(0xff); // meta
data.push_back(47); // META_END_OF_TRACK data.push_back(47); // META_END_OF_TRACK
writeDeltaTime(data, 0); // length writeDeltaTime(data, 0); // length
break; break;
case EventType::LoopBegin: case EventType::LoopBegin:
if (DEBUG) { std::printf("LoopBegin\n");} if (DEBUG) {
data.push_back(0xff); // meta std::printf("LoopBegin\n");
data.push_back(0x6); // META_MARKER }
data.push_back(0x1); // length data.push_back(0xff); // meta
data.push_back(0x6); // META_MARKER
data.push_back(0x1); // length
data.push_back(0x5B); // [ data.push_back(0x5B); // [
break; break;
case EventType::LoopEnd: case EventType::LoopEnd:
if (DEBUG) { std::printf("LoopEnd\n");} if (DEBUG) {
data.push_back(0xff); // meta std::printf("LoopEnd\n");
data.push_back(0x6); // META_MARKER }
data.push_back(0x1); // length data.push_back(0xff); // meta
data.push_back(0x6); // META_MARKER
data.push_back(0x1); // length
data.push_back(0x5D); // ] data.push_back(0x5D); // ]
break; break;
} }
} }
// MidiTrack header // MidiTrack header
std::fprintf(g_outputFile, "MTrk"); std::fprintf(g_outputFile, "MTrk");
// length of track data // length of track data
@ -355,19 +356,11 @@ void WriteMidiFile() {
// u16 midiTimeDiv (24 in example) // u16 midiTimeDiv (24 in example)
WriteInt16(g_midiTimeDiv); WriteInt16(g_midiTimeDiv);
// Add end of track to meta events // Add end of track to meta events
Event event; Event event;
event.type = EventType::EndOfTrack; event.type = EventType::EndOfTrack;
/*event.time = 0; // EndOfTrack event needs to be at the last meta event (can be earlier than the end of other tracks) for
// Place loop end at the end of the track that has the latest end. // bgmVaatiMotif to work
for (const auto& events:trackEvents) {
int trackEnd = events.back().time;
if (trackEnd > event.time) {
event.time = trackEnd;
}
}*/
// EndOfTrack event needs to be at the last meta event (can be earlier than the end of other tracks) for bgmVaatiMotif to work
event.time = metaEvents.back().time; event.time = metaEvents.back().time;
metaEvents.push_back(event); metaEvents.push_back(event);

View File

@ -23,14 +23,9 @@
#include <cstdint> #include <cstdint>
enum class MidiFormat enum class MidiFormat { SingleTrack, MultiTrack };
{
SingleTrack,
MultiTrack
};
enum class EventType enum class EventType {
{
EndOfTie = 0x01, EndOfTie = 0x01,
Label = 0x11, Label = 0x11,
LoopEnd = 0x12, LoopEnd = 0x12,
@ -53,25 +48,19 @@ enum class EventType
NoteOff, NoteOff,
}; };
struct Event struct Event {
{
std::int32_t time = 0; std::int32_t time = 0;
EventType type; EventType type;
std::uint8_t note = 0; std::uint8_t note = 0;
std::uint8_t param1 = 0; std::uint8_t param1 = 0;
std::int32_t param2 = 0; std::int32_t param2 = 0;
bool operator==(const Event& other) bool operator==(const Event& other) {
{ return (time == other.time && type == other.type && note == other.note && param1 == other.param1 &&
return (time == other.time param2 == other.param2);
&& type == other.type
&& note == other.note
&& param1 == other.param1
&& param2 == other.param2);
} }
bool operator!=(const Event& other) bool operator!=(const Event& other) {
{
return !(*this == other); return !(*this == other);
} }
}; };
@ -81,8 +70,7 @@ void WriteMidiFile();
extern int g_midiChan; extern int g_midiChan;
extern std::int32_t g_initialWait; extern std::int32_t g_initialWait;
inline bool IsPatternBoundary(EventType type) inline bool IsPatternBoundary(EventType type) {
{
return type == EventType::EndOfTrack || (int)type <= 0x17; return type == EventType::EndOfTrack || (int)type <= 0x17;
} }
extern std::int16_t g_midiTimeDiv; extern std::int16_t g_midiTimeDiv;

View File

@ -20,18 +20,17 @@
#include "tables.h" #include "tables.h"
const int g_noteDurationLUT[] = const int g_noteDurationLUT[] = {
{ 0, // 0
0, // 0 1, // 1
1, // 1 2, // 2
2, // 2 3, // 3
3, // 3 4, // 4
4, // 4 5, // 5
5, // 5 6, // 6
6, // 6 7, // 7
7, // 7 8, // 8
8, // 8 9, // 9
9, // 9
10, // 10 10, // 10
11, // 11 11, // 11
12, // 12 12, // 12
@ -121,105 +120,104 @@ const int g_noteDurationLUT[] =
96, // 96 96, // 96
}; };
const int g_noteVelocityLUT[] = const int g_noteVelocityLUT[] = {
{ 0, // 0
0, // 0 4, // 1
4, // 1 4, // 2
4, // 2 4, // 3
4, // 3 4, // 4
4, // 4 8, // 5
8, // 5 8, // 6
8, // 6 8, // 7
8, // 7 8, // 8
8, // 8 12, // 9
12, // 9 12, // 10
12, // 10 12, // 11
12, // 11 12, // 12
12, // 12 16, // 13
16, // 13 16, // 14
16, // 14 16, // 15
16, // 15 16, // 16
16, // 16 20, // 17
20, // 17 20, // 18
20, // 18 20, // 19
20, // 19 20, // 20
20, // 20 24, // 21
24, // 21 24, // 22
24, // 22 24, // 23
24, // 23 24, // 24
24, // 24 28, // 25
28, // 25 28, // 26
28, // 26 28, // 27
28, // 27 28, // 28
28, // 28 32, // 29
32, // 29 32, // 30
32, // 30 32, // 31
32, // 31 32, // 32
32, // 32 36, // 33
36, // 33 36, // 34
36, // 34 36, // 35
36, // 35 36, // 36
36, // 36 40, // 37
40, // 37 40, // 38
40, // 38 40, // 39
40, // 39 40, // 40
40, // 40 44, // 41
44, // 41 44, // 42
44, // 42 44, // 43
44, // 43 44, // 44
44, // 44 48, // 45
48, // 45 48, // 46
48, // 46 48, // 47
48, // 47 48, // 48
48, // 48 52, // 49
52, // 49 52, // 50
52, // 50 52, // 51
52, // 51 52, // 52
52, // 52 56, // 53
56, // 53 56, // 54
56, // 54 56, // 55
56, // 55 56, // 56
56, // 56 60, // 57
60, // 57 60, // 58
60, // 58 60, // 59
60, // 59 60, // 60
60, // 60 64, // 61
64, // 61 64, // 62
64, // 62 64, // 63
64, // 63 64, // 64
64, // 64 68, // 65
68, // 65 68, // 66
68, // 66 68, // 67
68, // 67 68, // 68
68, // 68 72, // 69
72, // 69 72, // 70
72, // 70 72, // 71
72, // 71 72, // 72
72, // 72 76, // 73
76, // 73 76, // 74
76, // 74 76, // 75
76, // 75 76, // 76
76, // 76 80, // 77
80, // 77 80, // 78
80, // 78 80, // 79
80, // 79 80, // 80
80, // 80 84, // 81
84, // 81 84, // 82
84, // 82 84, // 83
84, // 83 84, // 84
84, // 84 88, // 85
88, // 85 88, // 86
88, // 86 88, // 87
88, // 87 88, // 88
88, // 88 92, // 89
92, // 89 92, // 90
92, // 90 92, // 91
92, // 91 92, // 92
92, // 92 96, // 93
96, // 93 96, // 94
96, // 94 96, // 95
96, // 95 96, // 96
96, // 96
100, // 97 100, // 97
100, // 98 100, // 98
100, // 99 100, // 99
@ -253,90 +251,17 @@ const int g_noteVelocityLUT[] =
127, // 127 127, // 127
}; };
const char* g_noteTable[] = const char* g_noteTable[] = {
{ "Cn%01u ", "Cs%01u ", "Dn%01u ", "Ds%01u ", "En%01u ", "Fn%01u ",
"Cn%01u ", "Fs%01u ", "Gn%01u ", "Gs%01u ", "An%01u ", "As%01u ", "Bn%01u ",
"Cs%01u ",
"Dn%01u ",
"Ds%01u ",
"En%01u ",
"Fn%01u ",
"Fs%01u ",
"Gn%01u ",
"Gs%01u ",
"An%01u ",
"As%01u ",
"Bn%01u ",
}; };
const char* g_minusNoteTable[] = const char* g_minusNoteTable[] = {
{ "CnM%01u", "CsM%01u", "DnM%01u", "DsM%01u", "EnM%01u", "FnM%01u",
"CnM%01u", "FsM%01u", "GnM%01u", "GsM%01u", "AnM%01u", "AsM%01u", "BnM%01u",
"CsM%01u",
"DnM%01u",
"DsM%01u",
"EnM%01u",
"FnM%01u",
"FsM%01u",
"GnM%01u",
"GsM%01u",
"AnM%01u",
"AsM%01u",
"BnM%01u",
};
const int g_noteIdLUT[] = {
0, //
}; };
const int g_noteDurationInverseLUT[] = { const int g_noteDurationInverseLUT[] = {
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1, 28, 30, 32, 36, 40, 42, 44, 48, 52, 54, 56, 60, 64, 66, 68, 72, 76, 78, 80, 84, 88, 90, 92, 96,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
28,
30,
32,
36,
40,
42,
44,
48,
52,
54,
56,
60,
64,
66,
68,
72,
76,
78,
80,
84,
88,
90,
92,
96,
}; };

View File

@ -1,9 +1,9 @@
CXX = g++ CXX = g++
CXXFLAGS = -O3 -Wall -Wextra -std=c++17 CXXFLAGS = -O3 -Wall -Wextra -Werror -std=c++17
#CXXFLAGS += -g # debug #CXXFLAGS += -g # debug
BUILD_FOLDER=build BUILD_FOLDER = build
SRCS = $(wildcard *.cpp) SRCS = $(wildcard *.cpp)
SRCS += $(wildcard assets/*.cpp) SRCS += $(wildcard assets/*.cpp)

View File

@ -13,6 +13,8 @@ class BaseAsset {
: path(path), start(start), size(size), asset(asset) { : path(path), start(start), size(size), asset(asset) {
} }
virtual ~BaseAsset() = default;
void setup() { void setup() {
// Cannot call virtual functions in constructor, so another function call is necessary // Cannot call virtual functions in constructor, so another function call is necessary
assetPath = this->generateAssetPath(); assetPath = this->generateAssetPath();

View File

@ -71,13 +71,13 @@ int main(int argc, char** argv) {
argCount--; argCount--;
args++; args++;
} else { } else {
std::cerr << "Unrecognized argument `" << args[0] << "`" << std::endl; std::cerr << "Error: Unrecognized argument `" << args[0] << "`" << std::endl;
std::exit(1); std::exit(1);
} }
} }
if (argCount != 3) { if (argCount != 3) {
std::cerr << "Not enough arguments. expected: 3, actual: " << argCount << std::endl; std::cerr << "Error: Not enough arguments. expected: 3, actual: " << argCount << std::endl;
usage(); usage();
} }
@ -88,18 +88,23 @@ int main(int argc, char** argv) {
} else if (strcmp(args[0], "build") == 0) { } else if (strcmp(args[0], "build") == 0) {
gMode = BUILD; gMode = BUILD;
} else { } else {
std::cerr << "Unsupported mode `" << args[0] << "`" << std::endl; std::cerr << "Error: Unsupported mode `" << args[0] << "`" << std::endl;
std::exit(1); std::exit(1);
} }
gVariant = args[1]; gVariant = args[1];
if (gVariant != "USA" && gVariant != "EU" && gVariant != "JP" && gVariant != "DEMO_USA" && gVariant != "DEMO_JP") { if (gVariant != "USA" && gVariant != "EU" && gVariant != "JP" && gVariant != "DEMO_USA" && gVariant != "DEMO_JP") {
std::cerr << "Unsupported variant `" << gVariant << "`" << std::endl; std::cerr << "Error: Unsupported variant `" << gVariant << "`" << std::endl;
std::exit(1); std::exit(1);
} }
gAssetsFolder = args[2]; gAssetsFolder = args[2];
gBaseromPath = baseroms[gVariant]; gBaseromPath = baseroms[gVariant];
if (!std::filesystem::exists(gBaseromPath)) {
std::cerr << "Error: You need to provide a " << gVariant << " ROM as " << gBaseromPath << std::endl;
std::exit(1);
}
// Read baserom. // Read baserom.
std::ifstream file(gBaseromPath, std::ios::binary | std::ios::ate); std::ifstream file(gBaseromPath, std::ios::binary | std::ios::ate);
std::streamsize size = file.tellg(); std::streamsize size = file.tellg();
@ -255,7 +260,7 @@ std::unique_ptr<BaseAsset> getAssetHandlerByType(const std::filesystem::path& pa
// Unknown binary asset // Unknown binary asset
assetHandler = std::make_unique<BaseAsset>(path, start, size, asset); assetHandler = std::make_unique<BaseAsset>(path, start, size, asset);
} else { } else {
std::cerr << "Unimplemented asset type `" << type << "`" << std::endl; std::cerr << "Error: Unimplemented asset type `" << type << "`" << std::endl;
std::exit(1); std::exit(1);
} }
assetHandler->setup(); assetHandler->setup();

View File

@ -99,7 +99,7 @@ int main(int argc, char **argv)
std::string path(includeDir + incbin); std::string path(includeDir + incbin);
if (CanOpenFile(path)) if (CanOpenFile(path))
{ {
dependencies.insert(path).second; dependencies.insert(path);
break; break;
} }
} }

View File

@ -28,11 +28,11 @@ namespace {
}; };
constexpr const char *const ColorStrings[] = { constexpr const char *const ColorStrings[] = {
[Color_White] = "White", "White",
[Color_Red] = "Red", "Red",
[Color_Green] = "Green", "Green",
[Color_Blue] = "Blue", "Blue",
[Color_Yellow] = "Yellow", "Yellow",
}; };
enum Input { enum Input {
@ -52,17 +52,17 @@ namespace {
}; };
constexpr const char *const InputStrings[] = { constexpr const char *const InputStrings[] = {
[Input_A] = "A", "A",
[Input_B] = "B", "B",
[Input_Left] = "Left", "Left",
[Input_Right] = "Right", "Right",
[Input_DUp] = "DUp", "DUp",
[Input_DDown] = "DDown", "DDown",
[Input_DLeft] = "DLeft", "DLeft",
[Input_DRight] = "DRight", "DRight",
[Input_Dpad] = "Dpad", "Dpad",
[Input_Select] = "Select", "Select",
[Input_Start] = "Start", "Start",
}; };
const std::map<u8, std::string> CharConvertArray = { const std::map<u8, std::string> CharConvertArray = {