pokered/music/pokeredmusicdisasm/Parser.cpp

218 lines
5.6 KiB
C++
Raw Normal View History

#include <sstream>
#include "Parser.h"
using namespace std;
// Constructors
Parser::Parser()
{
rawBytes = 0;
fileLength = 0;
filePos = 0;
stop = false;
stopAddress = 0;
}
Parser::Parser(std::string filename)
{
rawBytes = 0;
fileLength = 0;
filePos = 0;
stop = false;
SetFilename(filename);
}
// Deconstructors
Parser::~Parser()
{
// Clear out temporary buffer
delete[] rawBytes;
// Clear out parsed buffer
for(unsigned int i = 0; i < parsedBytes.size(); i++)
{
delete parsedBytes[i];
}
}
// Getters / Setters
string Parser::GetFilename()
{
return filename;
}
void Parser::SetFilename(std::string value)
{
filename = value;
Read();
}
unsigned int Parser::GetStopAddress()
{
return stopAddress;
}
void Parser::SetStopAddress(unsigned int value)
{
stopAddress = value;
}
string Parser::GetParsedAsm()
{
string tmpStr;
for(unsigned int i = 0; i < parsedString.size(); i++)
{
tmpStr += parsedString[i] + "\n";
}
return tmpStr;
}
// File Operations
// Absolutely no error checking at all - likely needs to be done at somepoint
void Parser::Read()
{
// open File
fstream tmpFile(filename, ios_base::in | ios_base::binary);
// Get Length
tmpFile.seekg(0, ios::end);
fileLength = tmpFile.tellg();
tmpFile.seekg(0, ios::beg);
// Allocate proper memory
rawBytes = new char[fileLength];
// Read filedata
tmpFile.read(rawBytes, fileLength);
tmpFile.close();
}
// Code Operations
void Parser::Parse(unsigned int offset)
{
filePos = offset;
ParseNext();
}
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
stringstream pos;
pos << "; " << hex << uppercase << (unsigned int)filePos;
parsedString.push_back(pos.str());
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
{
// Call data type
// 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
Call* _tmp = (Call*)parsedBytes[parsedBytes.size() - 1];
}
else if(tmpDuty.IsValid(&rawBytesFixed[i]))
{
// Duty data type
parsedBytes.push_back(new Duty(&rawBytesFixed[i]));
parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
i += tmpDuty.Arguments();
}
else if(tmpJump.IsValid(&rawBytesFixed[i]))
{
// Jump data type
parsedBytes.push_back(new Jump(&rawBytesFixed[i]));
parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
i += tmpJump.Arguments();
Jump* _tmp = (Jump*)parsedBytes[parsedBytes.size() - 1];
}
else if(tmpModulation.IsValid(&rawBytesFixed[i]))
{
// Modulation data type
parsedBytes.push_back(new Modulation(&rawBytesFixed[i]));
parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
i += tmpModulation.Arguments();
}
else if(tmpNote.IsValid(&rawBytesFixed[i]))
{
// Note data type
parsedBytes.push_back(new Note(&rawBytesFixed[i]));
parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
i += tmpNote.Arguments();
}
else if(tmpOctave.IsValid(&rawBytesFixed[i]))
{
// Octave data type
parsedBytes.push_back(new Octave(&rawBytesFixed[i]));
parsedString.push_back("\n" + parsedBytes[parsedBytes.size() - 1]->GenAsm());
i += tmpOctave.Arguments();
}
else if(tmpStop.IsValid(&rawBytesFixed[i]))
{
// Stop data type
parsedBytes.push_back(new Stop(&rawBytesFixed[i]));
parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
i += tmpStop.Arguments();
stop = true; // Stop all further processing, we've reached the end of the song
}
else if(tmpTempo.IsValid(&rawBytesFixed[i]))
{
// Tempo data type
parsedBytes.push_back(new Tempo(&rawBytesFixed[i]));
parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
i += tmpTempo.Arguments();
}
else if(tmpVelocity.IsValid(&rawBytesFixed[i]))
{
// Velocity data type
parsedBytes.push_back(new Velocity(&rawBytesFixed[i]));
parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
i += tmpVelocity.Arguments();
}
else if(tmpVolume.IsValid(&rawBytesFixed[i]))
{
// Volume data type
parsedBytes.push_back(new Volume(&rawBytesFixed[i]));
parsedString.push_back(parsedBytes[parsedBytes.size() - 1]->GenAsm());
i += tmpVolume.Arguments();
}
else
{
// Unknown code
stringstream unkCode;
short tmpByte = (short)rawBytesFixed[i];
unkCode << "db $" << hex << uppercase << (short)rawBytesFixed[i];
parsedString.push_back(unkCode.str());
}
filePos = i;
// If the stop address parameter is set, break when we get there
if( (stopAddress != 0) && (i >= stopAddress) ) break;
}
// Now record the postion we left off
pos.str("");
pos << "; " << hex << uppercase << (unsigned int)filePos;
parsedString.push_back(pos.str());
filePos += 1; // increment 1 for the start of the next possible song
}