diff --git a/CMakeLists.txt b/CMakeLists.txt index 732cb623..6b6b7788 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ set(USE_SNDFILE_DEFAULT ON) set(SYSTEM_SDL2_DEFAULT OFF) include(CheckIncludeFile) +include(TestBigEndian) if (ANDROID) set(USE_RTMIDI_DEFAULT OFF) @@ -72,9 +73,15 @@ option(WITH_INSTRUMENTS "Install instruments" ON) set(DEPENDENCIES_INCLUDE_DIRS "") if (ANDROID AND NOT TERMUX) -set(DEPENDENCIES_DEFINES "IS_MOBILE") + set(DEPENDENCIES_DEFINES "IS_MOBILE") else() -set(DEPENDENCIES_DEFINES "") + set(DEPENDENCIES_DEFINES "") +endif() + +TEST_BIG_ENDIAN(IS_BIG_ENDIAN) + +if (IS_BIG_ENDIAN) + list(APPEND DEPENDENCIES_DEFINES "TA_BIG_ENDIAN") endif() set(DEPENDENCIES_COMPILE_OPTIONS "") diff --git a/TODO.md b/TODO.md index 13f31300..cba0b7c6 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,5 @@ # to-do for 0.6pre1.5-0.6pre2 - volume commands should work on Game Boy -- ability to customize `OFF`, `===` and `REL` - stereo separation control for AY +- "paste with instrument" \ No newline at end of file diff --git a/src/engine/safeReader.cpp b/src/engine/safeReader.cpp index 3cb1f4b1..a367bfb7 100644 --- a/src/engine/safeReader.cpp +++ b/src/engine/safeReader.cpp @@ -77,6 +77,85 @@ signed char SafeReader::readC() { return (signed char)buf[curSeek++]; } +#ifdef TA_BIG_ENDIAN +short SafeReader::readS_BE() { +#ifdef READ_DEBUG + logD("SR: reading short %x:",curSeek); +#endif + if (curSeek+2>len) throw EndOfFileException(this,len); + short ret; + memcpy(&ret,&buf[curSeek],2); +#ifdef READ_DEBUG + logD("SR: %.4x",ret); +#endif + curSeek+=2; + return ret; +} + +short SafeReader::readS() { + if (curSeek+2>len) throw EndOfFileException(this,len); + short ret; + memcpy(&ret,&buf[curSeek],2); + curSeek+=2; + return ((ret>>8)&0xff)|(ret<<8); +} + +int SafeReader::readI_BE() { +#ifdef READ_DEBUG + logD("SR: reading int %x:",curSeek); +#endif + if (curSeek+4>len) throw EndOfFileException(this,len); + int ret; + memcpy(&ret,&buf[curSeek],4); + curSeek+=4; +#ifdef READ_DEBUG + logD("SR: %.8x",ret); +#endif + return ret; +} + +int SafeReader::readI() { + if (curSeek+4>len) throw EndOfFileException(this,len); + unsigned int ret; + memcpy(&ret,&buf[curSeek],4); + curSeek+=4; + return (int)((ret>>24)|((ret&0xff0000)>>8)|((ret&0xff00)<<8)|((ret&0xff)<<24)); +} + +int64_t SafeReader::readL() { + if (curSeek+8>len) throw EndOfFileException(this,len); + unsigned char ret[8]; + memcpy(ret,&buf[curSeek],8); + curSeek+=8; + return (int64_t)(ret[0]|(ret[1]<<8)|(ret[2]<<16)|(ret[3]<<24)|(ret[4]<<32)|(ret[5]<<40)|(ret[6]<<48)|(ret[7]<<56)); +} + +float SafeReader::readF() { + if (curSeek+4>len) throw EndOfFileException(this,len); + unsigned int ret; + memcpy(&ret,&buf[curSeek],4); + curSeek+=4; + ret=((ret>>24)|((ret&0xff0000)>>8)|((ret&0xff00)<<8)|((ret&0xff)<<24)); + return *((float*)(&ret)); +} + +double SafeReader::readD() { + if (curSeek+8>len) throw EndOfFileException(this,len); + unsigned char ret[8]; + unsigned char retB[8]; + memcpy(ret,&buf[curSeek],8); + curSeek+=8; + retB[0]=ret[7]; + retB[1]=ret[6]; + retB[2]=ret[5]; + retB[3]=ret[4]; + retB[4]=ret[3]; + retB[5]=ret[2]; + retB[6]=ret[1]; + retB[7]=ret[0]; + return *((double*)retB); +} +#else short SafeReader::readS() { #ifdef READ_DEBUG logD("SR: reading short %x:",curSeek); @@ -144,6 +223,7 @@ double SafeReader::readD() { curSeek+=8; return ret; } +#endif String SafeReader::readString(size_t stlen) { String ret; diff --git a/src/engine/safeWriter.cpp b/src/engine/safeWriter.cpp index e6138093..a2a7315a 100644 --- a/src/engine/safeWriter.cpp +++ b/src/engine/safeWriter.cpp @@ -77,9 +77,64 @@ int SafeWriter::writeC(signed char val) { return write(&val,1); } +#ifdef TA_BIG_ENDIAN +int SafeWriter::writeS_BE(short val) { + return write(&val,2); +} + +int SafeWriter::writeS(short val) { + unsigned char bytes[2]{(unsigned char)((val>>8)&0xff), (unsigned char)(val&0xff)}; + return write(bytes,2); +} + +int SafeWriter::writeI(int val) { + unsigned char bytes[4]; + bytes[0]=((unsigned int)val)&0xff; + bytes[1]=(((unsigned int)val)>>8)&0xff; + bytes[2]=(((unsigned int)val)>>16)&0xff; + bytes[3]=(((unsigned int)val)>>24)&0xff; + return write(bytes,4); +} + +int SafeWriter::writeL(int64_t val) { + unsigned char bytes[8]; + bytes[0]=((uint64_t)val)&0xff; + bytes[1]=(((uint64_t)val)>>8)&0xff; + bytes[2]=(((uint64_t)val)>>16)&0xff; + bytes[3]=(((uint64_t)val)>>24)&0xff; + bytes[4]=(((uint64_t)val)>>32)&0xff; + bytes[5]=(((uint64_t)val)>>40)&0xff; + bytes[6]=(((uint64_t)val)>>48)&0xff; + bytes[7]=(((uint64_t)val)>>56)&0xff; + return write(bytes,8); +} + +int SafeWriter::writeF(float val) { + unsigned char bytes[4]; + bytes[0]=((unsigned char*)(&val))[3]; + bytes[1]=((unsigned char*)(&val))[2]; + bytes[2]=((unsigned char*)(&val))[1]; + bytes[3]=((unsigned char*)(&val))[0]; + return write(bytes,4); +} + +int SafeWriter::writeD(double val) { + unsigned char bytes[8]; + bytes[0]=((unsigned char*)(&val))[7]; + bytes[1]=((unsigned char*)(&val))[6]; + bytes[2]=((unsigned char*)(&val))[5]; + bytes[3]=((unsigned char*)(&val))[4]; + bytes[4]=((unsigned char*)(&val))[3]; + bytes[5]=((unsigned char*)(&val))[2]; + bytes[6]=((unsigned char*)(&val))[1]; + bytes[7]=((unsigned char*)(&val))[0]; + return write(bytes,8); +} +#else int SafeWriter::writeS(short val) { return write(&val,2); } + int SafeWriter::writeS_BE(short val) { unsigned char bytes[2]{(unsigned char)((val>>8)&0xff), (unsigned char)(val&0xff)}; return write(bytes,2); @@ -88,23 +143,20 @@ int SafeWriter::writeS_BE(short val) { int SafeWriter::writeI(int val) { return write(&val,4); } + int SafeWriter::writeL(int64_t val) { return write(&val,8); } + int SafeWriter::writeF(float val) { return write(&val,4); } + int SafeWriter::writeD(double val) { return write(&val,8); } -int SafeWriter::writeString(String val, bool pascal) { - if (pascal) { - writeC((unsigned char)val.size()); - return write(val.c_str(),val.size())+1; - } else { - return write(val.c_str(),val.size()+1); - } -} +#endif + int SafeWriter::writeWString(WString val, bool pascal) { if (pascal) { writeS((unsigned short)val.size()); @@ -120,10 +172,20 @@ int SafeWriter::writeWString(WString val, bool pascal) { return 2+val.size()*2; } } + int SafeWriter::writeText(String val) { return write(val.c_str(),val.size()); } +int SafeWriter::writeString(String val, bool pascal) { + if (pascal) { + writeC((unsigned char)val.size()); + return write(val.c_str(),val.size())+1; + } else { + return write(val.c_str(),val.size()+1); + } +} + void SafeWriter::init() { if (operative) return; buf=new unsigned char[WRITER_BUF_SIZE];