diff options
| author | KuroiIeWa5Da <tyuki@adu.me> | 2012-01-26 06:22:29 -0600 | 
|---|---|---|
| committer | KuroiIeWa5Da <tyuki@adu.me> | 2012-01-26 06:22:29 -0600 | 
| commit | bf1968297996fa8e2a5f004d60b83e516840a632 (patch) | |
| tree | 5ae653257dc979e098c4a7aaac3996cdb42138d3 | |
| parent | 25e09f50668a6a90620522bacd9bfaba2b6f6ee5 (diff) | |
Made several large upgrades to Music Disassembler
hg-commit-id: 0b180a6e2ec5
| -rw-r--r-- | music/pokeredmusicdisasm/AbstractData.h | 6 | ||||
| -rw-r--r-- | music/pokeredmusicdisasm/Parser.cpp | 186 | ||||
| -rw-r--r-- | music/pokeredmusicdisasm/Parser.h | 37 | ||||
| -rw-r--r-- | music/pokeredmusicdisasm/UnkCode.cpp | 67 | ||||
| -rw-r--r-- | music/pokeredmusicdisasm/UnkCode.h | 29 | ||||
| -rw-r--r-- | music/pokeredmusicdisasm/UnkEB.cpp | 69 | ||||
| -rw-r--r-- | music/pokeredmusicdisasm/UnkEB.h | 29 | 
7 files changed, 341 insertions, 82 deletions
| diff --git a/music/pokeredmusicdisasm/AbstractData.h b/music/pokeredmusicdisasm/AbstractData.h index 2a9fbbaf..0b49255d 100644 --- a/music/pokeredmusicdisasm/AbstractData.h +++ b/music/pokeredmusicdisasm/AbstractData.h @@ -10,11 +10,11 @@ public:      AbstractData();
      virtual std::string GenAsm(); // Generate Assembly Output
 -    virtual bool IsValid(unsigned char* byte); // Check for byte validity
      virtual bool Parse(unsigned char* byte); // Parse Given Data
 -    virtual unsigned int Arguments(); // Number of arguments taken
 +	virtual bool GetError(); // Get Error (No Write, Error is read only)
 -    virtual bool GetError(); // Get Error (No Write, Error is read only)
 +	virtual bool IsValid(unsigned char* byte); // Check for byte validity
 +    virtual unsigned int Arguments(); // Number of arguments taken
  protected:
      bool error; // Whether there's an error in parsing or not
 diff --git a/music/pokeredmusicdisasm/Parser.cpp b/music/pokeredmusicdisasm/Parser.cpp index 9fa0af7f..4878ee10 100644 --- a/music/pokeredmusicdisasm/Parser.cpp +++ b/music/pokeredmusicdisasm/Parser.cpp @@ -18,6 +18,7 @@ Parser::Parser(std::string filename)  	fileLength = 0;
  	filePos = 0;
  	stop = false;
 +	stopAddress = 0;
  	SetFilename(filename);
  }
 @@ -87,6 +88,8 @@ void Parser::Read()  	// Read filedata
  	tmpFile.read(rawBytes, fileLength);
  	tmpFile.close();
 +
 +	rawBytesFixed = (unsigned char*)rawBytes;
  }
  // Code Operations
 @@ -96,114 +99,165 @@ void Parser::Parse(unsigned int offset)  	ParseNext();
  }
 +template<class T>
 +bool Parser::ParseData(unsigned int& pos, bool reado)
 +{
 +	// Create the class to use if correct and a dummy class for validating
 +	T* tmpC = 0;
 +	T dummy;
 +
 +	// If the bytes are this data type then create and save it
 +	if(dummy.IsValid(&rawBytesFixed[pos]))
 +	{
 +		// Ensure this whole opperation isn't read-only (just peeking)
 +		if(!reado)
 +		{
 +			// Initialize the class
 +			tmpC = new T(&rawBytesFixed[pos]);
 +
 +			// Push it onto the stack and it's assembly generation onto the output class
 +			parsedBytes.push_back(tmpC);	// 
 +			parsedString.push_back(tmpC->GenAsm());
 +
 +			// If the class had any arguments, increment the counter that much forward
 +			pos += tmpC->Arguments();
 +		}
 +		return true;	// Let the code know this class was valid
 +	}
 +
 +	return false;	// Let the code know this class wasn't valid
 +}
 +
  void Parser::ParseNext() // Parses the block immidiately following
  {
  	stringstream tmpStr;
 -	unsigned char* rawBytesFixed = (unsigned char*)rawBytes;
  	stop = false;
  	// Smart generation
 -	bool indent = false;
 -	bool firstNonNote = false;	// First byte wasn't a note or octacve switch, add ";Setup" comment
 -	bool firstNote = false;	// First note or octave
 +	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;
  	stringstream pos;
  	pos << "; " << hex << uppercase << (unsigned int)filePos;
  	parsedString.push_back(pos.str());
 +	unsigned int count = 1;	// Counter for processed instructions
  	for(unsigned int i = filePos; (i <= fileLength) && (stop == false); i++)
  	{
 -		// There's a way to make this block shorter but for now it does it's job
 -
 -		// Check to see if it's the correct data type and if so then use it
 -		if(tmpCall.IsValid(&rawBytesFixed[i])) // Should have made IsValid static
 +		// First peek to see what kind of data it is, then perform any pre and post setup
 +		if(ParseData<Call>(i, true))
  		{
 -			// Call data type
 +			if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes
 -			// Create data type then move the increment pointer further up as needed
 -			parsedBytes.push_back(new Call(&rawBytesFixed[i]));
 -			parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
 -			i += tmpCall.Arguments(); // should have made Arguments static
 +			ParseData<Call>(i);
 +			lDataType = DATA_CALL;
 +		}
 +		else if(ParseData<Duty>(i, true))
 +		{
 +			if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes
 -			Call* _tmp = (Call*)parsedBytes[parsedBytes.size() - 1];
 +			ParseData<Duty>(i);
 +			lDataType = DATA_DUTY;
  		}
 -		else if(tmpDuty.IsValid(&rawBytesFixed[i]))
 +		else if(ParseData<Jump>(i, true))
  		{
 -			// Duty data type
 -			parsedBytes.push_back(new Duty(&rawBytesFixed[i]));
 -			parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
 -			i += tmpDuty.Arguments();
 +			if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes
 +
 +			ParseData<Jump>(i);
 +			lDataType = DATA_JUMP;
  		}
 -		else if(tmpJump.IsValid(&rawBytesFixed[i]))
 +		else if(ParseData<Modulation>(i, true))
  		{
 -			// Jump data type
 -			parsedBytes.push_back(new Jump(&rawBytesFixed[i]));
 -			parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
 -			i += tmpJump.Arguments();
 +			if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes
 -			Jump* _tmp = (Jump*)parsedBytes[parsedBytes.size() - 1];
 +			ParseData<Modulation>(i);
 +			lDataType = DATA_MODULATION;
  		}
 -		else if(tmpModulation.IsValid(&rawBytesFixed[i]))
 +		else if(ParseData<Note>(i, true))
  		{
 -			// Modulation data type
 -			parsedBytes.push_back(new Modulation(&rawBytesFixed[i]));
 -			parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
 -			i += tmpModulation.Arguments();
 +			 // Insert a newline after certain types
 +			if((lDataType == DATA_UNKCODE) ||
 +				(lDataType == DATA_UNKEB)) parsedString.push_back("\n");
 +
 +			// If the previous item was a rest note then insert a new line
 +			else if(lDataType == DATA_NOTE)
 +			{
 +				Note* _tmpNote = (Note*)parsedBytes[parsedBytes.size() - 1];
 +				if(_tmpNote->GetPitch() == _tmpNote->noteRst) parsedString.push_back("\n");
 +			}
 +
 +			ParseData<Note>(i);
 +
 +			// Further indent each note
 +			parsedString[parsedString.size() - 1] = "\t" + parsedString[parsedString.size() - 1];
 +			lDataType = DATA_NOTE;
  		}
 -		else if(tmpNote.IsValid(&rawBytesFixed[i]))
 +		else if(ParseData<Octave>(i, true))
  		{
 -			// Note data type
 -			parsedBytes.push_back(new Note(&rawBytesFixed[i]));
 -			parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
 -			i += tmpNote.Arguments();
 +			// Insert new-line if previous line isn't a newline
 +			if(parsedString[parsedString.size() - 1] != "\n") parsedString.push_back("\n");
 +
 +			ParseData<Octave>(i);
 +			lDataType = DATA_OCTAVE;
  		}
 -		else if(tmpOctave.IsValid(&rawBytesFixed[i]))
 +		else if(ParseData<Tempo>(i, true))
  		{
 -			// Octave data type
 -			parsedBytes.push_back(new Octave(&rawBytesFixed[i]));
 -			parsedString.push_back("\n" + parsedBytes[parsedBytes.size() - 1]->GenAsm());
 -			i += tmpOctave.Arguments();
 +			if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes
 +
 +			ParseData<Tempo>(i);
 +			lDataType = DATA_TEMPO;
  		}
 -		else if(tmpStop.IsValid(&rawBytesFixed[i]))
 +		else if(ParseData<Velocity>(i, true))
  		{
 -			// Stop data type
 -			parsedBytes.push_back(new Stop(&rawBytesFixed[i]));
 -			parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
 -			i += tmpStop.Arguments();
 +			if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes
 -			stop = true;	// Stop all further processing, we've reached the end of the song
 +			ParseData<Velocity>(i);
 +			lDataType = DATA_VELOCITY;
  		}
 -		else if(tmpTempo.IsValid(&rawBytesFixed[i]))
 +		else if(ParseData<Volume>(i, true))
  		{
 -			// Tempo data type
 -			parsedBytes.push_back(new Tempo(&rawBytesFixed[i]));
 -			parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
 -			i += tmpTempo.Arguments();
 +			if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes
 +
 +			ParseData<Volume>(i);
 +			lDataType = DATA_VOLUME;
  		}
 -		else if(tmpVelocity.IsValid(&rawBytesFixed[i]))
 +		else if(ParseData<UnkEB>(i, true))	// The opcode is 0xEB which is unknown and takes a 1-byte argument
  		{
 -			// Velocity data type
 -			parsedBytes.push_back(new Velocity(&rawBytesFixed[i]));
 -			parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
 -			i += tmpVelocity.Arguments();
 +			if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes
 +
 +			ParseData<UnkEB>(i);
 +			lDataType = DATA_UNKEB;
  		}
 -		else if(tmpVolume.IsValid(&rawBytesFixed[i]))
 +		else if(ParseData<Stop>(i, true))
  		{
 -			// Volume data type
 -			parsedBytes.push_back(new Volume(&rawBytesFixed[i]));
 -			parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
 -			i += tmpVolume.Arguments();
 +			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
 +			lDataType = DATA_STOP;
  		}
  		else
  		{
 -			// Unknown code
 -			stringstream unkCode;
 -			short tmpByte = (short)rawBytesFixed[i];
 -			unkCode << "db $" << hex << uppercase << (short)rawBytesFixed[i];
 -			parsedString.push_back(unkCode.str());
 +			if(lDataType == DATA_NOTE) parsedString.push_back("\n"); // Insert a newline after notes
 +
 +			ParseData<UnkCode>(i);	// The opcode is unknown - process the raw byte and move on
 +			lDataType = DATA_UNKCODE;
 +		}
 +
 +		// Put everything tabbed over at least 1 time to fix some weird RGBDS bug by pre-pending a tab character
 +		parsedString[parsedString.size() - 1] = "\t" + parsedString[parsedString.size() - 1];
 +
 +		// Append File Position in hexidecimal at end of line every 5 instructions
 +		if((count % 5) == 0)
 +		{
 +			stringstream _tmpCount;
 +			_tmpCount << hex << uppercase << i;
 +			parsedString[parsedString.size() - 1] = parsedString[parsedString.size() - 1] + "; " + _tmpCount.str();
  		}
  		filePos = i;
 +		count++;
  		// If the stop address parameter is set, break when we get there
  		if( (stopAddress != 0) && (i >= stopAddress) ) break;
 diff --git a/music/pokeredmusicdisasm/Parser.h b/music/pokeredmusicdisasm/Parser.h index 515d07ad..20af39a7 100644 --- a/music/pokeredmusicdisasm/Parser.h +++ b/music/pokeredmusicdisasm/Parser.h @@ -13,11 +13,12 @@  #include "Modulation.h"
  #include "Note.h"
  #include "Octave.h"
 -#include "Parser.h"
  #include "Stop.h"
  #include "Tempo.h"
  #include "Velocity.h"
  #include "Volume.h"
 +#include "UnkCode.h"
 +#include "UnkEB.h"
  // This is the final class, it takes all of the data types, abstract class, and helper functions and uses them
  // for parsing
 @@ -49,30 +50,40 @@ public:  	void Parse(unsigned int offset);
  	void ParseNext(); // Parses the block immidiately following
 +	// Templates
 +	template<class T>
 +	bool ParseData(unsigned int& pos, bool reado = false);
 +
 +	const enum dataType : unsigned char
 +	{
 +		DATA_NA,
 +		DATA_CALL,
 +		DATA_DUTY,
 +		DATA_JUMP,
 +		DATA_MODULATION,
 +		DATA_NOTE,
 +		DATA_OCTAVE,
 +		DATA_STOP,
 +		DATA_TEMPO,
 +		DATA_UNKCODE,
 +		DATA_UNKEB,
 +		DATA_VELOCITY,
 +		DATA_VOLUME
 +	};
 +
  private:
  	std::string filename;
  	std::vector<AbstractData*> parsedBytes;
  	std::vector<std::string> parsedString;
  	char* rawBytes;
 +	unsigned char* rawBytesFixed;
  	unsigned int fileLength;
  	unsigned int filePos;
  	bool stop;
  	// Optional Settings
  	unsigned int stopAddress;
 -
 -	// A lot of tmp classes
 -	Call tmpCall;
 -	Duty tmpDuty;
 -	Jump tmpJump;
 -	Modulation tmpModulation;
 -	Note tmpNote;
 -	Octave tmpOctave;
 -	Stop tmpStop;
 -	Tempo tmpTempo;
 -	Velocity tmpVelocity;
 -	Volume tmpVolume;
  };
  #endif
\ No newline at end of file diff --git a/music/pokeredmusicdisasm/UnkCode.cpp b/music/pokeredmusicdisasm/UnkCode.cpp new file mode 100644 index 00000000..93c74f66 --- /dev/null +++ b/music/pokeredmusicdisasm/UnkCode.cpp @@ -0,0 +1,67 @@ +#include <sstream>
 +
 +#include "Call.h"
 +#include "Duty.h"
 +#include "Jump.h"
 +#include "Modulation.h"
 +#include "Note.h"
 +#include "Octave.h"
 +#include "Stop.h"
 +#include "Tempo.h"
 +#include "Velocity.h"
 +#include "Volume.h"
 +
 +#include "UnkCode.h"
 +
 +using namespace std;
 +
 +UnkCode::UnkCode()
 +{
 +	code = 0;
 +}
 +
 +UnkCode::UnkCode(unsigned char* byte)
 +{
 +	code = 0;
 +	Parse(byte);
 +}
 +
 +UnkCode::UnkCode(unsigned char code, bool)
 +{
 +	SetCode(code);
 +}
 +
 +// Getters / Setters
 +unsigned char UnkCode::GetCode()
 +{
 +	return code;
 +}
 +
 +void UnkCode::SetCode(unsigned char value)
 +{
 +	code = value;
 +}
 +
 +// Re-implemented
 +string UnkCode::GenAsm()
 +{
 +	stringstream tmpAsmOut;
 +	tmpAsmOut << "db $" << hex << (short)code;
 +	return tmpAsmOut.str();
 +}
 +
 +bool UnkCode::Parse(unsigned char* byte)
 +{
 +	code = byte[0];
 +	return true;
 +}
 +
 +bool UnkCode::IsValid(unsigned char* byte)
 +{
 +	return true;
 +}
 +
 +unsigned int UnkCode::Arguments()
 +{
 +	return 0;
 +}
\ No newline at end of file diff --git a/music/pokeredmusicdisasm/UnkCode.h b/music/pokeredmusicdisasm/UnkCode.h new file mode 100644 index 00000000..28204448 --- /dev/null +++ b/music/pokeredmusicdisasm/UnkCode.h @@ -0,0 +1,29 @@ +#ifndef UNKCODE_H
 +#define UNKCODE_H
 +
 +#include "AbstractData.h"
 +
 +// Represents an unknown opcode
 +class UnkCode : public AbstractData
 +{
 +public:
 +	// Constructors
 +	UnkCode();
 +	UnkCode(unsigned char* byte); // Parse Immidiately
 +	UnkCode(unsigned char code, bool); // Set Value
 +
 +	// Getters / Setters
 +	unsigned char GetCode();
 +	void SetCode(unsigned char value);
 +
 +	// Re-implemented
 +	virtual std::string GenAsm();
 +	virtual bool Parse(unsigned char* byte);
 +	virtual bool IsValid(unsigned char* byte);
 +	virtual unsigned int Arguments();
 +
 +private:
 +	unsigned char code;
 +};
 +
 +#endif
\ No newline at end of file diff --git a/music/pokeredmusicdisasm/UnkEB.cpp b/music/pokeredmusicdisasm/UnkEB.cpp new file mode 100644 index 00000000..c8db595f --- /dev/null +++ b/music/pokeredmusicdisasm/UnkEB.cpp @@ -0,0 +1,69 @@ +#include <sstream>
 +
 +#include "Call.h"
 +#include "Duty.h"
 +#include "Jump.h"
 +#include "Modulation.h"
 +#include "Note.h"
 +#include "Octave.h"
 +#include "Stop.h"
 +#include "Tempo.h"
 +#include "Velocity.h"
 +#include "Volume.h"
 +
 +#include "UnkEB.h"
 +
 +using namespace std;
 +
 +UnkEB::UnkEB()
 +{
 +	param = 0;
 +}
 +
 +UnkEB::UnkEB(unsigned char* byte)
 +{
 +	param = 0;
 +	Parse(byte);
 +}
 +
 +UnkEB::UnkEB(unsigned char code, bool)
 +{
 +	SetParam(code);
 +}
 +
 +// Getters / Setters
 +unsigned char UnkEB::GetParam()
 +{
 +	return param;
 +}
 +
 +void UnkEB::SetParam(unsigned char value)
 +{
 +	param = value;
 +}
 +
 +// Re-implemented
 +string UnkEB::GenAsm()
 +{
 +	stringstream tmpAsmOut;
 +	tmpAsmOut << hex << "db $" << (short)0xEB << ", $" << (short)param;
 +	return tmpAsmOut.str();
 +}
 +
 +bool UnkEB::Parse(unsigned char* byte)
 +{
 +	param = byte[1];
 +	return true;
 +}
 +
 +bool UnkEB::IsValid(unsigned char* byte)
 +{
 +	if(byte[0] == 0xEB) return true;
 +	else return false;
 +}
 +
 +unsigned int UnkEB::Arguments()
 +{
 +	// 1 1-Byte param
 +	return 1;
 +}
\ No newline at end of file diff --git a/music/pokeredmusicdisasm/UnkEB.h b/music/pokeredmusicdisasm/UnkEB.h new file mode 100644 index 00000000..ab11a655 --- /dev/null +++ b/music/pokeredmusicdisasm/UnkEB.h @@ -0,0 +1,29 @@ +#ifndef UNKEB_H
 +#define UNKEB_H
 +
 +#include "AbstractData.h"
 +
 +// Represents an unknown opcode
 +class UnkEB : public AbstractData
 +{
 +public:
 +	// Constructors
 +	UnkEB();
 +	UnkEB(unsigned char* byte); // Parse Immidiately
 +	UnkEB(unsigned char code, bool); // Set Value
 +
 +	// Getters / Setters
 +	unsigned char GetParam();
 +	void SetParam(unsigned char value);
 +
 +	// Re-implemented
 +	virtual std::string GenAsm();
 +	virtual bool Parse(unsigned char* byte);
 +	virtual bool IsValid(unsigned char* byte);
 +	virtual unsigned int Arguments();
 +
 +private:
 +	unsigned char param;
 +};
 +
 +#endif
\ No newline at end of file | 
