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
void Console::Ask(const char* question, char* answer)
/*void Console::Ask(const char* question, char* answer)
{
Print(question);
Get(answer);
@ -42,13 +42,4 @@ void Console::Ask(const char* question, string& answer)
{
Print(question);
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 <string>
#include <sstream>
// Just a Console Utility Library
class Console
@ -19,11 +20,22 @@ public:
static void ErrorLn(const char* value);
// Higher
static void Ask(const char* question, char* answer);
static void Ask(const char* question, std::string& answer);
//static void Ask(const char* question, char* answer);
//static void Ask(const char* question, std::string& answer);
// Better Error Handling
static int atoi_ex(const char* input, bool supress = false);
template<class T>
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

View file

@ -1,7 +1,7 @@
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 \
Duty.o
Duty.o args.o
CC = g++
CFLAGS = -std=c++0x
@ -27,8 +27,8 @@ AbstractData.o: AbstractData.h
Call.o: Call.h Call.cpp AbstractData.h
$(CC) $(CFLAGS) -c Call.cpp AbstractData.cpp
main.o: main.cpp Console.h Parser.h
$(CC) $(CFLAGS) -c main.cpp Console.cpp Parser.cpp
main.o: main.cpp Console.h Parser.h args.h
$(CC) $(CFLAGS) -c main.cpp Console.cpp Parser.cpp args.cpp
Jump.o: Jump.h AbstractData.h
$(CC) $(CFLAGS) -c Jump.cpp AbstractData.cpp
@ -60,6 +60,9 @@ Velocity.o: Velocity.h AbstractData.h
Volume.o: Volume.h AbstractData.h
$(CC) $(CFLAGS) -c Volume.cpp AbstractData.cpp
args.o: args.h
$(CC) $(CFLAGS) -c args.cpp
clean:
rm *.o
rm ../../extras/pokeredmusicdisasm.exe

View file

@ -10,6 +10,7 @@ Parser::Parser()
filePos = 0;
stop = false;
stopAddress = 0;
force = false;
}
Parser::Parser(std::string filename)
@ -19,6 +20,7 @@ Parser::Parser(std::string filename)
filePos = 0;
stop = false;
stopAddress = 0;
force = false;
SetFilename(filename);
}
@ -58,6 +60,16 @@ void Parser::SetStopAddress(unsigned int value)
stopAddress = value;
}
bool Parser::GetForce()
{
return force;
}
void Parser::SetForce(bool value)
{
force = value;
}
string Parser::GetParsedAsm()
{
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 firstNote = false; // (unused so far) First note or octave
unsigned char lDataType = DATA_NA;
bool newBranch = false; // Create a new branch
stringstream pos;
pos << "; " << hex << uppercase << (unsigned int)filePos;
parsedString.push_back(pos.str());
unsigned int count = 1; // Counter for processed instructions
newBranch = true;
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
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
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;
}
else

View file

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

View file

@ -1,22 +1,26 @@
to compile you must have g++ installed
type: make
and it will install to the extras folder
if you want to unmake
type: make clean
and it will remove make objects and the executable
the program usage is: pokeredmusicdisasm [<offset> [<file> | --] [--stop]
offset is the rom offset in hexidecimal (FFFF or 0xFFFF)
file is the rom file, you can use -- for "../baserom.gbc"
--stop is the hexidecimal stop number
to make things quick and easy you can just enter the hexidecimal offset
pokeredmusicdisasm <offset>
to use the stop parameter you must use it as the 3rd argument as below
pokeredmusicdisasm <offset> -- --stop=FFFF
pokeredmusicdisasm <offset> <file> --stop=FFFF
you may enter limited interactive mode by not supplying any arguments
pokeredmusicdisasm
Usage: [<offset> [<file> | --]]
Usage: [--offset=<offset> | -o <offset>] [--file=[<file> | --] | -f [<file> | --]] [--stop=<offset> | -s <offset>]
Usage: [-h | --help]
Used without parameters will start in limited interactive mode where the program will ask you the file and offset
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'
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=
* <offset> <file>
If parameter options are used the ordering does not matter, ensure the <offset> parameter option or parameter is present
You may mix and match parameters and parameter options, keep in mind that bare parameters must be in a certain order
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
Parameter types
* <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
* -xxx xxx - Short parameter option, it can be in any order but is case sensitive, must contain 1 space and is read literally
----
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
<file> - A bare parameter, it must be the second parameter and tells the parser which rom file to parse
-- - 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 "Parser.h"
#include "args.h"
#include <sstream>
#include <string>
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)
{
Args a(argc, argv);
const unsigned char parameters = 2;
const unsigned char self = 1;
const unsigned char _max_argc = parameters + self;
const string defFileLoc = "../baserom.gbc";
string arg1; // Offset
string arg2; // File or "--" (if "--" then the file is assumed)
string filePath = "";
unsigned int offset = 0;
unsigned int stop = 0;
bool force = false;
string paramStopAddr;
if(argc >= _max_argc)
// 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)
// 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];
arg2 = argv[2];
}
else if(argc == (_max_argc - 1))
{
arg1 = argv[1];
arg2 = defFileLoc;
PrintUsage();
return 0;
}
// Process any parameters
if(argc > _max_argc)
// Does a -f or --file key exist
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++)
{
string tmpArgv = argv[i];
if(tmpArgv.substr(0, 7) == "--stop=") paramStopAddr = tmpArgv.substr(7);
}
Console::PrintLn("Filename can't be blank");
return 1;
}
if(arg1 == "") Console::Ask("What offset in the file in hex (0x----): ", arg1);
if(arg2 == "") Console::Ask("What file: ", arg2);
if(arg2 == "--") arg2 = defFileLoc; // You can also put "--" for the default file location
// Get the offset, this can be set with -o <offset>, --offset=<offset>, or as arg #1
if(a.SearchKeys("o") != -1) a.GetValueC<unsigned int>(a.SearchKeys("o"), offset, ios_base::hex | ios_base::uppercase, true);
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
Parser p(arg2);
// Does arg #1 exist
else if(a.GetArgs() >= 1 + 1) a.GetValueC<unsigned int>(1, offset, ios_base::hex | ios_base::uppercase);
stringstream arg1Conv;
unsigned int arg1ConvNum;
arg1Conv << arg1;
arg1Conv << hex;
arg1Conv >> arg1ConvNum;
// Ask the user
else Console::Ask<unsigned int>("Offset: ", offset, ios_base::hex | ios_base::uppercase);
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;
unsigned int paramStopAddrNum = 0;
paramStopAddrConv.str("");
paramStopAddrConv << paramStopAddr;
paramStopAddrConv << hex;
paramStopAddrConv >> paramStopAddrNum;
p.SetStopAddress(paramStopAddrNum);
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.");
return 1;
}
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());
return 0;
return 0;
}