hg-commit-id: fd141a80fa99
This commit is contained in:
YamaArashi 2012-01-28 09:58:44 -08:00
commit 182682a5c4
11 changed files with 8887 additions and 637 deletions

1108
main.asm

File diff suppressed because it is too large Load diff

8028
music.asm

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,7 @@ void Console::ErrorLn(const char* value)
} }
// Higher // Higher
void Console::Ask(const char* question, char* answer) /*void Console::Ask(const char* question, char* answer)
{ {
Print(question); Print(question);
Get(answer); Get(answer);
@ -42,13 +42,4 @@ void Console::Ask(const char* question, string& answer)
{ {
Print(question); Print(question);
Get(answer); Get(answer);
} }*/
// Better Error Handling
int Console::atoi_ex(const char* input, bool supress)
{
int convInp = atoi(input);
if((supress == false) && (convInp == 0))
PrintLn("Warning: the converted integer input is 0, this may not be what you intended");
return convInp;
}

View file

@ -3,6 +3,7 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <sstream>
// Just a Console Utility Library // Just a Console Utility Library
class Console class Console
@ -19,11 +20,22 @@ public:
static void ErrorLn(const char* value); static void ErrorLn(const char* value);
// Higher // Higher
static void Ask(const char* question, char* answer); //static void Ask(const char* question, char* answer);
static void Ask(const char* question, std::string& answer); //static void Ask(const char* question, std::string& answer);
// Better Error Handling template<class T>
static int atoi_ex(const char* input, bool supress = false); static void Ask(const char* question, T& answer, std::ios_base::fmtflags flags = std::ios_base::dec)
{
std::stringstream _tmpstr;
std::string _tmp;
Print(question);
Get(_tmp);
_tmpstr << _tmp;
_tmpstr.flags(flags);
_tmpstr >> answer;
}
}; };
#endif // CONSOLE_H #endif // CONSOLE_H

View file

@ -1,7 +1,7 @@
OBJECTS = main.o Jump.o Modulation.o Note.o Octave.o Parser.o Stop.o \ OBJECTS = main.o Jump.o Modulation.o Note.o Octave.o Parser.o Stop.o \
Tempo.o UnkCode.o UnkEB.o Velocity.o Volume.o Console.o AbstractData.o Call.o \ Tempo.o UnkCode.o UnkEB.o Velocity.o Volume.o Console.o AbstractData.o Call.o \
Duty.o Duty.o args.o
CC = g++ CC = g++
CFLAGS = -std=c++0x CFLAGS = -std=c++0x
@ -27,8 +27,8 @@ AbstractData.o: AbstractData.h
Call.o: Call.h Call.cpp AbstractData.h Call.o: Call.h Call.cpp AbstractData.h
$(CC) $(CFLAGS) -c Call.cpp AbstractData.cpp $(CC) $(CFLAGS) -c Call.cpp AbstractData.cpp
main.o: main.cpp Console.h Parser.h main.o: main.cpp Console.h Parser.h args.h
$(CC) $(CFLAGS) -c main.cpp Console.cpp Parser.cpp $(CC) $(CFLAGS) -c main.cpp Console.cpp Parser.cpp args.cpp
Jump.o: Jump.h AbstractData.h Jump.o: Jump.h AbstractData.h
$(CC) $(CFLAGS) -c Jump.cpp AbstractData.cpp $(CC) $(CFLAGS) -c Jump.cpp AbstractData.cpp
@ -60,6 +60,9 @@ Velocity.o: Velocity.h AbstractData.h
Volume.o: Volume.h AbstractData.h Volume.o: Volume.h AbstractData.h
$(CC) $(CFLAGS) -c Volume.cpp AbstractData.cpp $(CC) $(CFLAGS) -c Volume.cpp AbstractData.cpp
args.o: args.h
$(CC) $(CFLAGS) -c args.cpp
clean: clean:
rm *.o rm *.o
rm ../../extras/pokeredmusicdisasm.exe rm ../../extras/pokeredmusicdisasm.exe

View file

@ -10,6 +10,7 @@ Parser::Parser()
filePos = 0; filePos = 0;
stop = false; stop = false;
stopAddress = 0; stopAddress = 0;
force = false;
} }
Parser::Parser(std::string filename) Parser::Parser(std::string filename)
@ -19,6 +20,7 @@ Parser::Parser(std::string filename)
filePos = 0; filePos = 0;
stop = false; stop = false;
stopAddress = 0; stopAddress = 0;
force = false;
SetFilename(filename); SetFilename(filename);
} }
@ -58,6 +60,16 @@ void Parser::SetStopAddress(unsigned int value)
stopAddress = value; stopAddress = value;
} }
bool Parser::GetForce()
{
return force;
}
void Parser::SetForce(bool value)
{
force = value;
}
string Parser::GetParsedAsm() string Parser::GetParsedAsm()
{ {
string tmpStr; string tmpStr;
@ -139,14 +151,27 @@ void Parser::ParseNext() // Parses the block immidiately following
bool firstNonNote = false; // (unused so far)First byte wasn't a note or octacve switch, add ";Setup" comment bool firstNonNote = false; // (unused so far)First byte wasn't a note or octacve switch, add ";Setup" comment
bool firstNote = false; // (unused so far) First note or octave bool firstNote = false; // (unused so far) First note or octave
unsigned char lDataType = DATA_NA; unsigned char lDataType = DATA_NA;
bool newBranch = false; // Create a new branch
stringstream pos; stringstream pos;
pos << "; " << hex << uppercase << (unsigned int)filePos; pos << "; " << hex << uppercase << (unsigned int)filePos;
parsedString.push_back(pos.str()); parsedString.push_back(pos.str());
unsigned int count = 1; // Counter for processed instructions unsigned int count = 1; // Counter for processed instructions
newBranch = true;
for(unsigned int i = filePos; (i <= fileLength) && (stop == false); i++) for(unsigned int i = filePos; (i <= fileLength) && (stop == false); i++)
{ {
if(newBranch)
{
stringstream _tmpBr;
_tmpBr << "\n";
_tmpBr << "UnknSong_md_" << hex << i << ":";
parsedString.push_back(_tmpBr.str());
_tmpBr.str("");
newBranch = false;
}
// First peek to see what kind of data it is, then perform any pre and post setup // First peek to see what kind of data it is, then perform any pre and post setup
if(ParseData<Call>(i, true)) if(ParseData<Call>(i, true))
{ {
@ -236,7 +261,8 @@ void Parser::ParseNext() // Parses the block immidiately following
if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes
ParseData<Stop>(i); ParseData<Stop>(i);
stop = true; // Raise the stop flag informing the parser to stop if(!force) stop = true; // Raise the stop flag informing the parser to stop
newBranch = true;
lDataType = DATA_STOP; lDataType = DATA_STOP;
} }
else else

View file

@ -41,6 +41,9 @@ public:
unsigned int GetStopAddress(); unsigned int GetStopAddress();
void SetStopAddress(unsigned int value); void SetStopAddress(unsigned int value);
bool GetForce();
void SetForce(bool value);
std::string GetParsedAsm(); std::string GetParsedAsm();
// File Operations // File Operations
@ -81,6 +84,7 @@ private:
unsigned int fileLength; unsigned int fileLength;
unsigned int filePos; unsigned int filePos;
bool stop; bool stop;
bool force;
// Optional Settings // Optional Settings
unsigned int stopAddress; unsigned int stopAddress;

View file

@ -1,22 +1,26 @@
to compile you must have g++ installed Usage: [<offset> [<file> | --]]
type: make Usage: [--offset=<offset> | -o <offset>] [--file=[<file> | --] | -f [<file> | --]] [--stop=<offset> | -s <offset>]
and it will install to the extras folder Usage: [-h | --help]
if you want to unmake Used without parameters will start in limited interactive mode where the program will ask you the file and offset
type: make clean An offset is a requirement but the file may be blank or explicitly set, whenever the file is set you may use '--' to substitute for the default file '../baserom.gbc'
and it will remove make objects and the executable If parameter options are not used the ordering is important:
There is an intentional glitch in the program, since long paramaters must be specified with --xxx= with or without a value, you may use the short option instead -xxx even though it's suppose to be -xxx=
the program usage is: pokeredmusicdisasm [<offset> [<file> | --] [--stop] * <offset> <file>
offset is the rom offset in hexidecimal (FFFF or 0xFFFF) If parameter options are used the ordering does not matter, ensure the <offset> parameter option or parameter is present
file is the rom file, you can use -- for "../baserom.gbc" You may mix and match parameters and parameter options, keep in mind that bare parameters must be in a certain order
--stop is the hexidecimal stop number If the offset parameter is missing in any way the program will prompt you for it
The program will stop parsing when it encounters mus_end regardlessly
to make things quick and easy you can just enter the hexidecimal offset Parameter types
pokeredmusicdisasm <offset> * <xxx> - Bare parameter, they must be in a certain order
* -xxx=xxx - Long parameter option, it can be in any order but is case sensitive, can contain no spaces, must contain the equal sign, and is read literally
to use the stop parameter you must use it as the 3rd argument as below * -xxx xxx - Short parameter option, it can be in any order but is case sensitive, must contain 1 space and is read literally
pokeredmusicdisasm <offset> -- --stop=FFFF ----
pokeredmusicdisasm <offset> <file> --stop=FFFF Breakdown of parameters:
<offset> - A bare parameter, it must be in hexidecimal eith alone or prefixed with 0x and be the first parameter. It tells the parser where to start parsing
you may enter limited interactive mode by not supplying any arguments <file> - A bare parameter, it must be the second parameter and tells the parser which rom file to parse
pokeredmusicdisasm -- - A special file path value meaning use the default file '../baserom.gbc'
--offset, -o - the parameterized offset in hexidecimal, It tells the parser where to start parsing
--file, -f - the parameterized file path, It tells the parser which rom file to parse
--stop, -s - tells the parser to stop at that hexidecimal address or until it reaches mus_end.
help, --help, -h - prints this info and exits, if the bare parameter is used it must be the first parameter

View file

@ -0,0 +1,93 @@
#include <sstream>
#include "args.h"
using namespace std;
Args::Args(int _argc, char**& _argv)
{
argc = _argc;
for(int i = 0; i < _argc; i++)
{
argv.push_back(string(_argv[i]));
}
}
//template<class T>
/*export void Args::GetArg(unsigned int ind, T& var, ios_base::fmtflags flags)
{
string stream _tmpstr;
_tmpstr << flags;
_tmpstr << GetArgv(ind);
_tmpstr >> var;
}*/
int Args::GetArgs()
{
return argv.size();
}
string Args::GetArgv(int ind)
{
return argv[ind];
}
bool Args::IsLongOption(int ind) // Is that argument a --long-key=value
{
if(GetArgv(ind).substr(0, 2) == "--") return true;
else return false;
}
bool Args::IsShortOption(int ind, bool param2) // Is that argument a --long-key=value
{
if(param2)
{
if(GetArgv(ind).substr(0, 1) == "-" && // The argument must start with -
GetArgv(ind).substr(0, 2) != "--" && // The argument can't start with "--"
ind + 1 < GetArgs()) return true; // The second argument must exist
}
else
{
if(GetArgv(ind).substr(0, 1) == "-" && // The argument must start with -
GetArgv(ind).substr(0, 2) != "--") return true; // The argument can't start with "--"
}
return false;
}
string Args::GetKey(int ind) // Get the key, if not a key/value then returns the arg
{
if(IsLongOption(ind) && GetArgv(ind).find("=") != string::npos) return GetArgv(ind).substr(2, GetArgv(ind).find("=") - 2);
else if(IsShortOption(ind)) return GetArgv(ind).substr(1);
else return GetArgv(ind);
}
string Args::GetValue(int ind, bool param2) // Get the value , if not a key/value then returns the arg
{
if(IsLongOption(ind) && GetArgv(ind).find("=") != string::npos) return GetArgv(ind).substr(GetArgv(ind).find("=") + 1);
else if(IsShortOption(ind, param2))
{
if(param2) return GetArgv(ind + 1);
else return GetArgv(ind);
}
return GetArgv(ind);
}
int Args::SearchKeys(const char* str)
{
string needle = str;
string scr = "";
unsigned int pos = -1;
for(int i = 0; i < GetArgs(); i++)
{
scr = GetKey(i);
if(scr == needle)
{
pos = i;
break;
}
}
return pos;
}

View file

@ -0,0 +1,38 @@
#ifndef ARGS_H
#define ARGS_H
#include <string>
#include <vector>
#include <sstream>
class Args
{
public:
Args(int _argc, char**& _argv);
template<class T> // Get the argument automatically in any format that stringstream can output to
void GetValueC(int ind, T& var, std::ios_base::fmtflags flags = std::ios_base::dec, bool param2 = false)
{
std::stringstream _tmpstr;
_tmpstr << GetValue(ind, param2);
_tmpstr.flags(flags);
_tmpstr >> var;
}
int GetArgs(); // Get number of args
std::string GetArgv(int ind); // Get the arg based on true index
bool IsLongOption(int ind); // Is that argument a --long-key=value
bool IsShortOption(int ind, bool param2 = false); // Is that argument a --long-key=value
std::string GetKey(int ind); // Get the key, if not a key/value then returns the arg
std::string GetValue(int ind, bool param2 = false); // Get the value, if not a key/value then returns the arg
int SearchKeys(const char* str); // Return the index number of found key or -1 if not found
private:
int argc;
std::vector<std::string> argv;
};
#endif

View file

@ -1,69 +1,122 @@
#include "Console.h" #include "Console.h"
#include "Parser.h" #include "Parser.h"
#include "args.h"
#include <sstream> #include <sstream>
#include <string> #include <string>
using namespace std; using namespace std;
void PrintUsage()
{
Console::PrintLn("Usage: [<offset> [<file> | --]]");
Console::PrintLn("Usage: [--offset=<offset> | -o <offset>] [--file=[<file> | --] | -f [<file> | --]] [--stop=<offset> | -s <offset>]");
Console::PrintLn("Usage: [-h | --help]");
Console::PrintLn("");
Console::PrintLn("Used without parameters will start in limited interactive mode where the program will ask you the file and offset");
Console::PrintLn("An offset is a requirement but the file may be blank or explicitly set, whenever the file is set you may use '--' to substitute for the default file '../baserom.gbc'");
Console::PrintLn("If parameter options are not used the ordering is important:");
Console::PrintLn("There is an intentional glitch in the program, since long paramaters must be specified with --xxx= with or without a value, you may use the short option instead -xxx even though it's suppose to be -xxx=");
Console::PrintLn("\t* <offset> <file>");
Console::PrintLn("If parameter options are used the ordering does not matter, ensure the <offset> parameter option or parameter is present");
Console::PrintLn("You may mix and match parameters and parameter options, keep in mind that bare parameters must be in a certain order");
Console::PrintLn("If the offset parameter is missing in any way the program will prompt you for it");
Console::PrintLn("The program will stop parsing when it encounters mus_end regardlessly");
Console::PrintLn("Parameter types");
Console::PrintLn("\t* <xxx> - Bare parameter, they must be in a certain order");
Console::PrintLn("\t* -xxx=xxx - Long parameter option, it can be in any order but is case sensitive, can contain no spaces, must contain the equal sign, and is read literally");
Console::PrintLn("\t* -xxx xxx - Short parameter option, it can be in any order but is case sensitive, must contain 1 space and is read literally");
Console::PrintLn("----");
Console::PrintLn("Breakdown of parameters:");
Console::PrintLn("<offset> - A bare parameter, it must be in hexidecimal eith alone or prefixed with 0x and be the first parameter. It tells the parser where to start parsing");
Console::PrintLn("<file> - A bare parameter, it must be the second parameter and tells the parser which rom file to parse");
Console::PrintLn("-- - A special file path value meaning use the default file '../baserom.gbc'");
Console::PrintLn("--offset, -o - the parameterized offset in hexidecimal, It tells the parser where to start parsing");
Console::PrintLn("--file, -f - the parameterized file path, It tells the parser which rom file to parse");
Console::PrintLn("--stop, -s - tells the parser to stop at that hexidecimal address or until it reaches mus_end.");
Console::PrintLn("-fo - must be used with --stop, forces the program to proceed on despite discovering any mus_end");
Console::PrintLn("help, --help, -h - prints this info and exits, if the bare parameter is used it must be the first parameter");
}
/*
Usage:
pokeredmusicdisasm [<offset> [<file> | --]]
pokeredmusicdisasm [--offset=<offset> | -o <offset>] [--file=[<file> | --] | -f [<file> | --]] [--stop=<offset> | -s <offset>]
*/
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
Args a(argc, argv);
const unsigned char parameters = 2; const unsigned char parameters = 2;
const unsigned char self = 1;
const unsigned char _max_argc = parameters + self;
const string defFileLoc = "../baserom.gbc"; const string defFileLoc = "../baserom.gbc";
string arg1; // Offset string filePath = "";
string arg2; // File or "--" (if "--" then the file is assumed) unsigned int offset = 0;
unsigned int stop = 0;
bool force = false;
string paramStopAddr; // Get the file path, this can be set with -f filename, --file=filename, arg #2, or missing (missing means default)
// the filepath can contain the actual filename or -- to use the built-in path, if the path is not missing then it must be set (can't be blank)
if(argc >= _max_argc)
// Is the user asking for help with -h, --help=, or help
if((a.SearchKeys("h") != -1) || (a.SearchKeys("help") != -1) || (a.GetArgv(1) == "help"))
{ {
arg1 = argv[1]; PrintUsage();
arg2 = argv[2]; return 0;
}
else if(argc == (_max_argc - 1))
{
arg1 = argv[1];
arg2 = defFileLoc;
} }
// Process any parameters // Does a -f or --file key exist
if(argc > _max_argc) if(a.SearchKeys("f") != -1) filePath = a.GetValue(a.SearchKeys("f"), true);
else if(a.SearchKeys("file") != -1) filePath = a.GetValue(a.SearchKeys("file"));
// BUG FIX: a short parameter can be either 1 or 2 parts so this causes the if statement below to load incorrect info if
// -f or --file isn't specified and the first argument is a short parameter "-x x"
else if((a.GetArgs() == (2 + 1)) && (a.IsShortOption(1, true))) filePath = defFileLoc;
// Does arg #2 exist
else if(a.GetArgs() >= 2 + 1) a.GetValueC<string>(2, filePath);
// Is there at least 1 arg (In that case it's missing and the default can be assumed)
else if(a.GetArgs() >= 1 + 1) filePath = defFileLoc;
// Ask the user
else Console::Ask("Filepath: ", filePath);
if(filePath == "--") filePath = defFileLoc;
else if(filePath == "")
{ {
for(int i = _max_argc; i < argc; i++) Console::PrintLn("Filename can't be blank");
{ return 1;
string tmpArgv = argv[i];
if(tmpArgv.substr(0, 7) == "--stop=") paramStopAddr = tmpArgv.substr(7);
}
} }
if(arg1 == "") Console::Ask("What offset in the file in hex (0x----): ", arg1); // Get the offset, this can be set with -o <offset>, --offset=<offset>, or as arg #1
if(arg2 == "") Console::Ask("What file: ", arg2); if(a.SearchKeys("o") != -1) a.GetValueC<unsigned int>(a.SearchKeys("o"), offset, ios_base::hex | ios_base::uppercase, true);
if(arg2 == "--") arg2 = defFileLoc; // You can also put "--" for the default file location else if(a.SearchKeys("offset") != -1) a.GetValueC(a.SearchKeys("offset"), offset, ios_base::hex | ios_base::uppercase);
// Weird way of converting arg1 to an unsigned integer // Does arg #1 exist
Parser p(arg2); else if(a.GetArgs() >= 1 + 1) a.GetValueC<unsigned int>(1, offset, ios_base::hex | ios_base::uppercase);
stringstream arg1Conv; // Ask the user
unsigned int arg1ConvNum; else Console::Ask<unsigned int>("Offset: ", offset, ios_base::hex | ios_base::uppercase);
arg1Conv << arg1;
arg1Conv << hex;
arg1Conv >> arg1ConvNum;
if(paramStopAddr != "") // Get the stop parameter, this can be set with -s <offset>, --stop=<offset> (it must be set via args)
if(a.SearchKeys("s") != -1) a.GetValueC<unsigned int>(a.SearchKeys("s"), stop, ios_base::hex | ios_base::uppercase, true);
else if(a.SearchKeys("stop") != -1) filePath = a.GetValue(a.SearchKeys("stop"));
// Get the force parameter, this can be set with -f (it must be set via args)
if(a.SearchKeys("fo") != -1) force = true;
if((stop == 0) && (force == true))
{ {
stringstream paramStopAddrConv; Console::ErrorLn("Error! You set the force command but did not set the stop command, this means it will parse every line until the end of the rom.");
unsigned int paramStopAddrNum = 0; return 1;
paramStopAddrConv.str("");
paramStopAddrConv << paramStopAddr;
paramStopAddrConv << hex;
paramStopAddrConv >> paramStopAddrNum;
p.SetStopAddress(paramStopAddrNum);
} }
p.Parse(arg1ConvNum); Parser p(filePath);
if(stop != 0) p.SetStopAddress(stop);
if(force) p.SetForce(true);
p.Parse(offset);
Console::PrintLn(p.GetParsedAsm().c_str()); Console::PrintLn(p.GetParsedAsm().c_str());
return 0; return 0;
} }