diff --git a/UI/BackgroundAudio.cpp b/UI/BackgroundAudio.cpp index 261f4af5d2..c87237c0ac 100644 --- a/UI/BackgroundAudio.cpp +++ b/UI/BackgroundAudio.cpp @@ -31,10 +31,10 @@ public: u8 at3_extradata[16]; int num_channels, sample_rate, numFrames, samplesPerSec, avgBytesPerSec, Nothing; - if (file_.descend('RIFF')) { - file_.readInt(); //get past 'WAVE' - if (file_.descend('fmt ')) { //enter the format chunk - int temp = file_.readInt(); + if (file_.Descend('RIFF')) { + file_.ReadInt(); //get past 'WAVE' + if (file_.Descend('fmt ')) { //enter the format chunk + int temp = file_.ReadInt(); int format = temp & 0xFFFF; switch (format) { case 0xFFFE: @@ -50,10 +50,10 @@ public: num_channels = temp >> 16; - samplesPerSec = file_.readInt(); - avgBytesPerSec = file_.readInt(); + samplesPerSec = file_.ReadInt(); + avgBytesPerSec = file_.ReadInt(); - temp = file_.readInt(); + temp = file_.ReadInt(); raw_bytes_per_frame_ = temp & 0xFFFF; Nothing = temp >> 16; @@ -64,41 +64,41 @@ public: if (codec == PSP_CODEC_AT3) { // The first two bytes are actually not a useful part of the extradata. // We already read 16 bytes, so make sure there's enough left. - if (file_.getCurrentChunkSize() >= 32) { - file_.readData(at3_extradata, 16); + if (file_.GetCurrentChunkSize() >= 32) { + file_.ReadData(at3_extradata, 16); } else { memset(at3_extradata, 0, sizeof(at3_extradata)); } } - file_.ascend(); + file_.Ascend(); // ILOG("got fmt data: %i", samplesPerSec); } else { ELOG("Error - no format chunk in wav"); - file_.ascend(); + file_.Ascend(); return; } - if (file_.descend('data')) { //enter the data chunk - int numBytes = file_.getCurrentChunkSize(); + if (file_.Descend('data')) { //enter the data chunk + int numBytes = file_.GetCurrentChunkSize(); numFrames = numBytes / raw_bytes_per_frame_; // numFrames raw_data_ = (uint8_t *)malloc(numBytes); raw_data_size_ = numBytes; if (/*raw_bytes_per_frame_ == 280 && */ num_channels == 1 || num_channels == 2) { - file_.readData(raw_data_, numBytes); + file_.ReadData(raw_data_, numBytes); } else { ELOG("Error - bad blockalign or channels"); free(raw_data_); raw_data_ = 0; return; } - file_.ascend(); + file_.Ascend(); } else { ELOG("Error - no data chunk in wav"); - file_.ascend(); + file_.Ascend(); return; } - file_.ascend(); + file_.Ascend(); } else { ELOG("Could not descend into RIFF file. Data size=%d", (int32_t)data.size()); return; @@ -153,7 +153,7 @@ public: } private: - ChunkFile file_; + RIFFReader file_; uint8_t *raw_data_; int raw_data_size_; int raw_offset_; diff --git a/ext/native/file/chunk_file.cpp b/ext/native/file/chunk_file.cpp index 0544417a33..4cd4e5157c 100644 --- a/ext/native/file/chunk_file.cpp +++ b/ext/native/file/chunk_file.cpp @@ -3,287 +3,109 @@ #include "file/zip_read.h" #include "file/file_util.h" -//#define CHUNKDEBUG +#include "Common/Log.h" -ChunkFile::ChunkFile(const char *filename, bool _read) { - data=0; - fn = filename; - numLevels=0; - read=_read; - pos=0; - didFail=false; - - fastMode = read ? true : false; - - if (fastMode) { - size_t size; - data = (uint8_t *)VFSReadFile(filename, &size); - if (!data) { - ELOG("Chunkfile fail: %s", filename); - didFail = true; - return; - } - eof = (int)size; - return; - } - - file = openCFile(filename, "wb"); - if (file) { - didFail = false; - eof = 0; - } else { - didFail = true; - } +inline uint32_t flipID(uint32_t id) { + return ((id >> 24) & 0xFF) | ((id >> 8) & 0xFF00) | ((id << 8) & 0xFF0000) | ((id << 24) & 0xFF000000); } -ChunkFile::ChunkFile(const uint8_t *read_data, int data_size) { - data = new uint8_t[data_size]; - memcpy(data, read_data, data_size); - fastMode = true; - numLevels = 0; - read = true; - pos = 0; - didFail = false; - eof = data_size; +RIFFReader::RIFFReader(const uint8_t *data, int dataSize) { + data_ = new uint8_t[dataSize]; + memcpy(data_, data, dataSize); + depth_ = 0; + pos_ = 0; + eof_ = dataSize; + fileSize_ = dataSize; } -ChunkFile::~ChunkFile() { - if (fastMode) { - delete[] data; - } else { - fclose(file); - } +RIFFReader::~RIFFReader() { + delete[] data_; } -int ChunkFile::readInt() { - if (data && pos 30) +// let's get into the business +bool RIFFReader::Descend(uint32_t intoId) { + if (depth_ > 30) return false; - id = flipID(id); - if (read) { - bool found = false; + intoId = flipID(intoId); + bool found = false; - //save information to restore after the next Ascend - stack[numLevels].parentStartLocation = pos; - stack[numLevels].parentEOF = eof; + // save information to restore after the next Ascend + stack[depth_].parentStartLocation = pos_; + stack[depth_].parentEOF = eof_; - ChunkInfo temp = stack[numLevels]; + // let's search through children.. + while (pos_ < eof_) { + int id = ReadInt(); + int length = ReadInt(); + int startLocation = pos_; - int firstID = 0; - //let's search through children.. - while(pos>8, id>>16, id>>24); -#endif - stack[numLevels]=temp; - seekTo(stack[numLevels].parentStartLocation); + if (pos_ + length > fileSize_) { + ERROR_LOG(SYSTEM, "Block extends outside of RIFF file - failing descend"); + pos_ = stack[depth_].parentStartLocation; return false; } - //descend into it - //pos was set inside the loop above - eof = stack[numLevels].startLocation + stack[numLevels].length; - numLevels++; -#ifdef CHUNKDEBUG - ILOG("Descended into %c%c%c%c", id, id>>8, id>>16, id>>24); -#endif - return true; - } else { -#ifndef DEMO_VERSION //if this is missing.. heheh - //write a chunk id, and prepare for filling in length later - writeInt(id); - writeInt(0); //will be filled in by Ascend - stack[numLevels].startLocation=pos; - numLevels++; - return true; -#else - return true; -#endif - } -} - -void ChunkFile::seekTo(int _pos) { - if (!fastMode) { - fseek(file, 0, SEEK_SET); - } - pos = _pos; -} - -//let's ascend out -void ChunkFile::ascend() { - if (read) { - //ascend, and restore information - numLevels--; - seekTo(stack[numLevels].parentStartLocation); - eof = stack[numLevels].parentEOF; -#ifdef CHUNKDEBUG - int id = stack[numLevels].ID; - ILOG("Ascended out of %c%c%c%c", id, id>>8, id>>16, id>>24); -#endif + if (id == intoId) { + stack[depth_].ID = intoId; + stack[depth_].length = length; + stack[depth_].startLocation = startLocation; + found = true; + break; } else { - numLevels--; - //now fill in the written length automatically - int posNow = pos; - seekTo(stack[numLevels].startLocation - 4); - writeInt(posNow-stack[numLevels].startLocation); - seekTo(posNow); - } -} - -//read a block -void ChunkFile::readData(void *what, int count) { - if (fastMode) { - memcpy(what, data + pos, count); - } else { - if (fread(what, 1, count, file) != (size_t)count) { - ELOG("Failed to read complete %d bytes", count); - } - } - - pos+=count; - count &= 3; - if (count) { - count=4-count; - if (!fastMode) { - if (fseek(file, count, SEEK_CUR) != 0) { - ELOG("Missing padding"); + if (length > 0) { + pos_ += length; // try next block + } else { + ERROR_LOG(SYSTEM, "Bad data in RIFF file : block length %d. Not descending.", length); + pos_ = stack[depth_].parentStartLocation; + return false; } } - pos+=count; + } + + // if we found nothing, return false so the caller can skip this + if (!found) { + pos_ = stack[depth_].parentStartLocation; + return false; + } + + // descend into it + // pos was set inside the loop above + eof_ = stack[depth_].startLocation + stack[depth_].length; + depth_++; + return true; +} + +// let's ascend out +void RIFFReader::Ascend() { + // ascend, and restore information + depth_--; + pos_ = stack[depth_].parentStartLocation; + eof_ = stack[depth_].parentEOF; +} + +// read a block +void RIFFReader::ReadData(void *what, int count) { + memcpy(what, data_ + pos_, count); + pos_ += count; + count &= 3; + if (count) { + count = 4 - count; + pos_ += count; } } -//write a block -void ChunkFile::writeData(const void *what, int count) { - fwrite(what, 1, count, file); - pos+=count; - char temp[5]={0,0,0,0,0}; - count &= 3; - if (count) - { - count=4-count; - fwrite(temp, 1, count, file); - pos+=count; - } -} - -/* -void ChunkFile::writeWString(String str) { - wchar_t *text; - int len=str.length(); -#ifdef UNICODE -#error - text = str.getPointer(); -#else - text = new wchar_t[len+1]; - str.toUnicode(text); -#endif - writeInt(len); - writeData((char *)text, len * sizeof(wchar_t)); -#ifndef UNICODE - delete [] text; -#endif -} -*/ - -// Takes utf-8 -void ChunkFile::writeWString(const std::string &str) { - unsigned short *text; - int len = (int)str.length(); - text = new unsigned short[len+1]; - for (int i = 0; i < len; i++) - text[i] = str[i]; - text[len]=0; - writeInt(len); - writeData((char *)text, len * sizeof(unsigned short)); - delete [] text; -} - -static void toUnicode(const std::string &str, uint16_t *t) { - for (size_t i = 0; i < str.size(); i++) { - *t++ = str[i]; - } - *t++ = '\0'; -} - -static std::string fromUnicode(const uint16_t *src, int len) { - std::string str; - str.resize(len); - for (int i = 0; i < len; i++) { - str[i] = src[i] > 255 ? ' ' : src[i]; - } - return str; -} - -std::string ChunkFile::readWString() { - int len=readInt(); - uint16_t *text = new uint16_t[len+1]; - readData((char *)text, len*sizeof(uint16_t)); - text[len] = 0; - std::string temp = fromUnicode(text, len); - delete [] text; - return temp; -} - -void ChunkFile::writeString(const std::string &str) { - uint16_t *text; - int len = (int)str.size(); - text=new uint16_t[len+1]; - toUnicode(str, text); - writeInt(len); - writeData((char *)text,len*sizeof(uint16_t)); - delete [] text; -} - -std::string ChunkFile::readString() { - int len=readInt(); - uint16_t *text = new uint16_t[len+1]; - readData((char *)text,len*sizeof(uint16_t)); - text[len]=0; - std::string temp = fromUnicode(text, len); - delete [] text; - return temp; -} -int ChunkFile::getCurrentChunkSize() { - if (numLevels) - return stack[numLevels-1].length; +int RIFFReader::GetCurrentChunkSize() { + if (depth_) + return stack[depth_ - 1].length; else return 0; } diff --git a/ext/native/file/chunk_file.h b/ext/native/file/chunk_file.h index f1e9d8f3ee..18d8a80e8b 100644 --- a/ext/native/file/chunk_file.h +++ b/ext/native/file/chunk_file.h @@ -10,62 +10,34 @@ // otherwise the scheme breaks. #include -#include +#include +#include -#include "base/basictypes.h" - -inline uint32_t flipID(uint32_t id) { - return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000); -} - -class ChunkFile { +class RIFFReader { public: - ChunkFile(const char *filename, bool _read); - ChunkFile(const uint8_t *read_data, int data_size); + RIFFReader(const uint8_t *data, int dataSize); + ~RIFFReader(); - ~ChunkFile(); + bool Descend(uint32_t id); + void Ascend(); - bool descend(uint32_t id); - void ascend(); + int ReadInt(); + void ReadData(void *data, int count); - int readInt(); - void readInt(int &i) {i = readInt();} - void readData(void *data, int count); - // String readWString(); - std::string readWString(); - - void writeString(const std::string &str); - std::string readString(); - - void writeInt(int i); - //void writeWString(String str); - void writeWString(const std::string &str); - void writeData(const void *data, int count); - - int getCurrentChunkSize(); - bool failed() const { return didFail; } - std::string filename() const { return fn; } + int GetCurrentChunkSize(); private: - std::string fn; - FILE *file; struct ChunkInfo { int startLocation; int parentStartLocation; int parentEOF; - unsigned int ID; + uint32_t ID; int length; }; ChunkInfo stack[32]; - int numLevels; - - uint8_t *data; - int pos; - int eof; - bool fastMode; - bool read; - bool didFail; - - void seekTo(int _pos); - int getPos() const {return pos;} + uint8_t *data_; + int pos_ = 0; + int eof_ = 0; // really end of current block + int depth_ = 0; + int fileSize_ = 0; };