Removed the save state loading from the 2SF player and updated the VBA-M code to the latest revision.
Removed the save state loading from the 2SF player and updated the VBA-M code to the latest revision.

--- a/src/in_2sf/XSFPlayer_2SF.cpp
+++ b/src/in_2sf/XSFPlayer_2SF.cpp
@@ -23,6 +23,12 @@
 
 class XSFPlayer_2SF : public XSFPlayer
 {
+	std::vector<uint8_t> rom;
+
+	void Map2SFSection(const std::vector<uint8_t> &section);
+	bool Map2SF(XSFFile *xSFToLoad);
+	bool RecursiveLoad2SF(XSFFile *xSFToLoad, int level);
+	bool Load2SF(XSFFile *xSFToLoad);
 public:
 	XSFPlayer_2SF(const std::string &filename);
 	XSFPlayer_2SF(const std::wstring &filename);
@@ -46,329 +52,6 @@
 }
 
 volatile bool execute = false;
-
-static struct
-{
-	std::vector<uint8_t> rom, state;
-	unsigned stateptr;
-} loaderwork;
-
-static inline uint16_t Get16BitsLE(const uint8_t *input)
-{
-	return input[0] | (input[1] << 8);
-}
-
-static void load_getstateinit(unsigned ptr)
-{
-	loaderwork.stateptr = ptr;
-}
-
-static void load_getsta(Status_Reg *ptr, unsigned l)
-{
-	unsigned s = l << 2;
-	if (loaderwork.stateptr > loaderwork.state.size() || loaderwork.stateptr + s > loaderwork.state.size())
-		return;
-	if (ptr)
-		for (unsigned i = 0; i < l; ++i)
-		{
-			uint32_t st = Get32BitsLE(&loaderwork.state[loaderwork.stateptr + (i << 2)]);
-			ptr[i].bits.N = (st >> 31) & 1;
-			ptr[i].bits.Z = (st >> 30) & 1;
-			ptr[i].bits.C = (st >> 29) & 1;
-			ptr[i].bits.V = (st >> 28) & 1;
-			ptr[i].bits.Q = (st >> 27) & 1;
-			ptr[i].bits.RAZ = (st >> 8) & ((1 << 19) - 1);
-			ptr[i].bits.I = (st >> 7) & 1;
-			ptr[i].bits.F = (st >> 6) & 1;
-			ptr[i].bits.T = (st >> 5) & 1;
-			ptr[i].bits.mode = (st >> 0) & 0x1f;
-		}
-	loaderwork.stateptr += s;
-}
-
-static void load_getbool(bool *ptr, unsigned l)
-{
-	unsigned s = l << 2;
-	if (loaderwork.stateptr > loaderwork.state.size() || loaderwork.stateptr + s > loaderwork.state.size())
-		return;
-	if (ptr)
-		for (unsigned i = 0; i < l; ++i)
-			ptr[i] = !!Get32BitsLE(&loaderwork.state[loaderwork.stateptr + (i << 2)]);
-	loaderwork.stateptr += s;
-}
-
-#ifdef SIGNED_IS_NOT_2S_COMPLEMENT
-/* 2's complement */
-static inline int32_t u32tos32(uint32_t v) { return static_cast<int32_t>((static_cast<int64_t>(v) ^ 0x8000) - 0x8000); }
-#else
-/* 2's complement */
-static inline int32_t u32tos32(uint32_t v) { return static_cast<int32_t>(v); }
-#endif
-
-static void load_gets32(int32_t *ptr, unsigned l)
-{
-	unsigned s = l << 2;
-	if (loaderwork.stateptr > loaderwork.state.size() || loaderwork.stateptr + s > loaderwork.state.size())
-		return;
-	if (ptr)
-		for (unsigned i = 0; i < l; ++i)
-			ptr[i] = u32tos32(Get32BitsLE(&loaderwork.state[loaderwork.stateptr + (i << 2)]));
-	loaderwork.stateptr += s;
-}
-
-static void load_getu32(uint32_t *ptr, unsigned l)
-{
-	unsigned s = l << 2;
-	if (loaderwork.stateptr > loaderwork.state.size() || loaderwork.stateptr + s > loaderwork.state.size())
-		return;
-	if (ptr)
-		for (unsigned i = 0; i < l; ++i)
-			ptr[i] = Get32BitsLE(&loaderwork.state[loaderwork.stateptr + (i << 2)]);
-	loaderwork.stateptr += s;
-}
-
-static void load_getu16(uint16_t *ptr, unsigned l)
-{
-	unsigned s = l << 1;
-	if (loaderwork.stateptr > loaderwork.state.size() || loaderwork.stateptr + s > loaderwork.state.size())
-		return;
-	if (ptr)
-		for (unsigned i = 0; i < l; ++i)
-			ptr[i] = Get16BitsLE(&loaderwork.state[loaderwork.stateptr + (i << 1)]);
-	loaderwork.stateptr += s;
-}
-
-static void load_getu8(uint8_t *ptr, unsigned l)
-{
-	unsigned s = l;
-	if (loaderwork.stateptr > loaderwork.state.size() || loaderwork.stateptr + s > loaderwork.state.size())
-		return;
-	if (ptr)
-		for (unsigned i = 0; i < l; ++i)
-			ptr[i] = loaderwork.state[loaderwork.stateptr + i];
-	loaderwork.stateptr += s;
-}
-
-/*static void gdb_stub_fix(armcpu_t *armcpu)
-{*/
-	/* armcpu->R[15] = armcpu->instruct_adr; */
-	/*armcpu->next_instruction = armcpu->instruct_adr;
-	if(armcpu->CPSR.bits.T == 0)
-	{
-		armcpu->instruction = MMU_read32(armcpu->proc_ID, armcpu->next_instruction);
-		armcpu->instruct_adr = armcpu->next_instruction;
-		armcpu->next_instruction += 4;
-		armcpu->R[15] = armcpu->next_instruction + 4;
-	}
-	else
-	{
-		armcpu->instruction = MMU_read16(armcpu->proc_ID, armcpu->next_instruction);
-		armcpu->instruct_adr = armcpu->next_instruction;
-		armcpu->next_instruction += 2;
-		armcpu->R[15] = armcpu->next_instruction + 2;
-	}
-}*/
-
-static void load_setstate()
-{
-	if (loaderwork.state.empty())
-		return;
-
-	//std::vector<uint8_t> savestate = std::vector<uint8_t>(&loaderwork.state[0], &loaderwork.state[loaderwork.state.size()]);
-	EMUFILE_MEMORY f(&loaderwork.state);
-	if (!savestate_load(&f))
-	{
-	//reset the emulator first to clean out the host's state
-
-		//while the series of resets below should work,
-		//we are testing the robustness of the savestate system with this full reset.
-		//the full reset wipes more things, so we can make sure that they are being restored correctly
-		//extern bool _HACK_DONT_STOPMOVIE;
-		//_HACK_DONT_STOPMOVIE = true;
-		NDS_Reset();
-		//_HACK_DONT_STOPMOVIE = false;
-
-		//reset some options to their old defaults which werent saved
-		//nds.debugConsole = false;
-
-		/* Skip over "Desmume Save File" crap */
-		load_getstateinit(0x17);
-
-		/* Read ARM7 cpu registers */
-		//load_getu32(&NDS_ARM7.proc_ID, 1);
-		load_getu32(nullptr, 1);
-		load_getu32(&NDS_ARM7.instruction, 1);
-		load_getu32(&NDS_ARM7.instruct_adr, 1);
-		load_getu32(&NDS_ARM7.next_instruction, 1);
-		load_getu32(NDS_ARM7.R, 16);
-		load_getsta(&NDS_ARM7.CPSR, 1);
-		load_getsta(&NDS_ARM7.SPSR, 1);
-		load_getu32(&NDS_ARM7.R13_usr, 1);
-		load_getu32(&NDS_ARM7.R14_usr, 1);
-		load_getu32(&NDS_ARM7.R13_svc, 1);
-		load_getu32(&NDS_ARM7.R14_svc, 1);
-		load_getu32(&NDS_ARM7.R13_abt, 1);
-		load_getu32(&NDS_ARM7.R14_abt, 1);
-		load_getu32(&NDS_ARM7.R13_und, 1);
-		load_getu32(&NDS_ARM7.R14_und, 1);
-		load_getu32(&NDS_ARM7.R13_irq, 1);
-		load_getu32(&NDS_ARM7.R14_irq, 1);
-		load_getu32(&NDS_ARM7.R8_fiq, 1);
-		load_getu32(&NDS_ARM7.R9_fiq, 1);
-		load_getu32(&NDS_ARM7.R10_fiq, 1);
-		load_getu32(&NDS_ARM7.R11_fiq, 1);
-		load_getu32(&NDS_ARM7.R12_fiq, 1);
-		load_getu32(&NDS_ARM7.R13_fiq, 1);
-		load_getu32(&NDS_ARM7.R14_fiq, 1);
-		load_getsta(&NDS_ARM7.SPSR_svc, 1);
-		load_getsta(&NDS_ARM7.SPSR_abt, 1);
-		load_getsta(&NDS_ARM7.SPSR_und, 1);
-		load_getsta(&NDS_ARM7.SPSR_irq, 1);
-		load_getsta(&NDS_ARM7.SPSR_fiq, 1);
-		load_getu32(&NDS_ARM7.intVector, 1);
-		load_getu8(&NDS_ARM7.LDTBit, 1);
-		load_getbool(&NDS_ARM7.waitIRQ, 1);
-		bool tmpbool;
-		//load_getbool(&NDS_ARM7.wIRQ, 1);
-		//loaderwork.stateptr += 4;
-		load_getbool(nullptr, 1);
-		//load_getbool(&NDS_ARM7.halt_IE_and_IF, 1);
-		//load_getbool(&NDS_ARM7.wirq, 1);
-		//loaderwork.stateptr += 4;
-		//load_getbool(nullptr, 1);
-		//load_getbool(&NDS_ARM7.intrWaitARM_state, 1);
-		load_getbool(&tmpbool, 1);
-		//NDS_ARM7.intrWaitARM_state = tmpbool;
-
-		/* Read ARM9 cpu registers */
-		//load_getu32(&NDS_ARM9.proc_ID, 1);
-		load_getu32(nullptr, 1);
-		load_getu32(&NDS_ARM9.instruction, 1);
-		load_getu32(&NDS_ARM9.instruct_adr, 1);
-		load_getu32(&NDS_ARM9.next_instruction, 1);
-		load_getu32(NDS_ARM9.R, 16);
-		load_getsta(&NDS_ARM9.CPSR, 1);
-		load_getsta(&NDS_ARM9.SPSR, 1);
-		load_getu32(&NDS_ARM9.R13_usr, 1);
-		load_getu32(&NDS_ARM9.R14_usr, 1);
-		load_getu32(&NDS_ARM9.R13_svc, 1);
-		load_getu32(&NDS_ARM9.R14_svc, 1);
-		load_getu32(&NDS_ARM9.R13_abt, 1);
-		load_getu32(&NDS_ARM9.R14_abt, 1);
-		load_getu32(&NDS_ARM9.R13_und, 1);
-		load_getu32(&NDS_ARM9.R14_und, 1);
-		load_getu32(&NDS_ARM9.R13_irq, 1);
-		load_getu32(&NDS_ARM9.R14_irq, 1);
-		load_getu32(&NDS_ARM9.R8_fiq, 1);
-		load_getu32(&NDS_ARM9.R9_fiq, 1);
-		load_getu32(&NDS_ARM9.R10_fiq, 1);
-		load_getu32(&NDS_ARM9.R11_fiq, 1);
-		load_getu32(&NDS_ARM9.R12_fiq, 1);
-		load_getu32(&NDS_ARM9.R13_fiq, 1);
-		load_getu32(&NDS_ARM9.R14_fiq, 1);
-		load_getsta(&NDS_ARM9.SPSR_svc, 1);
-		load_getsta(&NDS_ARM9.SPSR_abt, 1);
-		load_getsta(&NDS_ARM9.SPSR_und, 1);
-		load_getsta(&NDS_ARM9.SPSR_irq, 1);
-		load_getsta(&NDS_ARM9.SPSR_fiq, 1);
-		load_getu32(&NDS_ARM9.intVector, 1);
-		load_getu8(&NDS_ARM9.LDTBit, 1);
-		load_getbool(&NDS_ARM9.waitIRQ, 1);
-		//load_getbool(&NDS_ARM9.wIRQ, 1);
-		//loaderwork.stateptr += 4;
-		load_getbool(nullptr, 1);
-		//load_getbool(&NDS_ARM9.halt_IE_and_IF, 1);
-		//load_getbool(&NDS_ARM9.wirq, 1);
-		//loaderwork.stateptr += 4;
-		//load_getbool(nullptr, 1);
-		//load_getbool(&NDS_ARM9.intrWaitARM_state, 1);
-		load_getbool(&tmpbool, 1);
-		//NDS_ARM9.intrWaitARM_state = tmpbool;
-
-		/* Read in other internal variables that are important */
-		//int32_t tmps32;
-		//load_gets32(&nds.ARM9Cycle, 1);
-		load_gets32(nullptr, 1);
-		//load_gets32(&nds.ARM7Cycle, 1);
-		load_gets32(nullptr, 1);
-		load_gets32(&nds.cycles, 1);
-		int32_t tmps32_array[4];
-		//load_getu64(nds.timerCycle[0], 4);
-		load_gets32(tmps32_array, 4);
-		for (int i = 0; i < 4; ++i)
-			nds.timerCycle[0][i] = tmps32_array[i];
-		//load_getu64(nds.timerCycle[1], 4);
-		load_gets32(tmps32_array, 4);
-		for (int i = 0; i < 4; ++i)
-			nds.timerCycle[1][i] = tmps32_array[i];
-		//bool tmpbool_array[4];
-		//load_getbool(nds.timerOver[0], 4);
-		//loaderwork.stateptr += 16;
-		load_getbool(nullptr, 4);
-		//load_getbool(nds.timerOver[1], 4);
-		//loaderwork.stateptr += 16;
-		load_getbool(nullptr, 4);
-		//load_gets32(&nds.nextHBlank, 1);
-		//loaderwork.stateptr += 4;
-		load_gets32(nullptr, 1);
-		load_getu32(&nds.VCount, 1);
-		load_getu32(&nds.old, 1);
-		//load_gets32(&nds.diff, 1);
-		//loaderwork.stateptr += 4;
-		load_gets32(nullptr, 1);
-		//load_getbool(&nds.lignerendu, 1);
-		//loaderwork.stateptr += 4;
-		load_getbool(nullptr, 1);
-		load_getu16(nullptr, 1);
-		load_getu16(nullptr, 1);
-
-		/* Read in memory/registers specific to the ARM9 */
-		//load_getu8 (MMU.ARM9_ITCM, 0x8000);
-		load_getu8(nullptr, 0x8000);
-		load_getu8 (MMU.ARM9_DTCM, 0x4000);
-		//load_getu8 (MMU.MAIN_MEM, 0x1000000);
-		//load_getu8(MMU.MAIN_MEM, 0x800000);
-		//load_getu8(nullptr, 0x800000);
-		//load_getu8(nullptr, 0x1000000);
-		load_getu8(nullptr, 0xFF8000);
-		load_getu8(MMU.ARM9_ITCM, 0x8000);
-		load_getu8 (MMU.MAIN_MEM/*+0x400000*/, 0x400000);
-		load_getu8 (MMU.ARM9_REG, 0x10000);
-		load_getu8 (MMU.ARM9_VMEM, 0x800);
-		load_getu8 (MMU.ARM9_OAM, 0x800);
-		//uint8_t tmpu8_ABG[0x80000];
-		//load_getu8 (ARM9Mem.ARM9_ABG, 0x80000);
-		//loaderwork.stateptr += 0x80000;
-		load_getu8(nullptr, 0x80000);
-		//uint8_t tmpu8_BBG[0x20000];
-		//load_getu8 (ARM9Mem.ARM9_BBG, 0x20000);
-		//loaderwork.stateptr += 0x20000;
-		load_getu8(nullptr, 0x20000);
-		//uint8_t tmpu8_AOBJ[0x40000];
-		//load_getu8 (ARM9Mem.ARM9_AOBJ, 0x40000);
-		//loaderwork.stateptr += 0x40000;
-		load_getu8(nullptr, 0x40000);
-		//uint8_t tmpu8_BOBJ[0x20000];
-		//load_getu8 (ARM9Mem.ARM9_BOBJ, 0x20000);
-		//loaderwork.stateptr += 0x20000;
-		load_getu8(nullptr, 0x20000);
-		load_getu8 (MMU.ARM9_LCD, 0xA4000);
-		//loaderwork.stateptr += 12;
-
-		/* Read in memory/registers specific to the ARM7 */
-		load_getu8 (MMU.ARM7_ERAM, 0x10000);
-		load_getu8 (MMU.ARM7_REG, 0x10000);
-		load_getu8 (MMU.ARM7_WIRAM, 0x10000);
-
-		/* Read in shared memory */
-		load_getu8 (MMU.SWIRAM, 0x8000);
-
-		//gdb_stub_fix(&NDS_ARM9);
-		//gdb_stub_fix(&NDS_ARM7);
-
-		loadstate();
-	}
-}
 
 static struct
 {
@@ -432,71 +115,44 @@
 	nullptr
 };
 
-static void Map2SFSection(const std::vector<uint8_t> &section, bool isSave)
-{
-	auto &data = isSave ? loaderwork.state : loaderwork.rom;
-
+void XSFPlayer_2SF::Map2SFSection(const std::vector<uint8_t> &section)
+{
 	uint32_t offset = Get32BitsLE(&section[0]), size = Get32BitsLE(&section[4]), finalSize = size + offset;
-	if (!isSave)
-		finalSize = NextHighestPowerOf2(finalSize);
-	if (data.empty())
-		data.resize(finalSize + 10, 0);
-	else if (data.size() < size + offset)
-		data.resize(offset + finalSize + 10);
-	memcpy(&data[offset], &section[8], size);
-}
-
-static bool Map2SF(XSFFile *xSF)
-{
-	if (!xSF->IsValidType(0x24))
+	finalSize = NextHighestPowerOf2(finalSize);
+	if (this->rom.empty())
+		this->rom.resize(finalSize + 10, 0);
+	else if (this->rom.size() < size + offset)
+		this->rom.resize(offset + finalSize + 10);
+	memcpy(&this->rom[offset], &section[8], size);
+}
+
+bool XSFPlayer_2SF::Map2SF(XSFFile *xSFToLoad)
+{
+	if (!xSFToLoad->IsValidType(0x24))
 		return false;
 
-	auto &reservedSection = xSF->GetReservedSection(), &programSection = xSF->GetProgramSection();
-
-	if (!reservedSection.empty())
-	{
-		size_t reservedPosition = 0, reservedSize = reservedSection.size();
-		while (reservedPosition + 12 < reservedSize)
-		{
-			uint32_t saveSize = Get32BitsLE(&reservedSection[reservedPosition + 4]);
-			if (Get32BitsLE(&reservedSection[reservedPosition]) == 0x45564153) // "SAVE"
-			{
-				if (reservedPosition + 12 + saveSize > reservedSize)
-					return false;
-
-				uint8_t tmpSaveUncompressed[8];
-				unsigned long saveUncompressedSize = 8;
-				uncompress(tmpSaveUncompressed, &saveUncompressedSize, &reservedSection[reservedPosition + 12], saveSize);
-				saveUncompressedSize = Get32BitsLE(&tmpSaveUncompressed[4]) + 8;
-				auto saveUncompressed = std::vector<uint8_t>(saveUncompressedSize);
-				uncompress(&saveUncompressed[0], &saveUncompressedSize, &reservedSection[reservedPosition + 12], saveSize);
-
-				Map2SFSection(saveUncompressed, true);
-			}
-			reservedPosition += saveSize + 12;
-		}
-	}
+	const auto &programSection = xSFToLoad->GetProgramSection();
 
 	if (!programSection.empty())
-		Map2SFSection(programSection, false);
+		this->Map2SFSection(programSection);
 
 	return true;
 }
 
-static bool RecursiveLoad2SF(XSFFile *xSF, int level)
-{
-	if (level <= 10 && xSF->GetTagExists("_lib"))
+bool XSFPlayer_2SF::RecursiveLoad2SF(XSFFile *xSFToLoad, int level)
+{
+	if (level <= 10 && xSFToLoad->GetTagExists("_lib"))
 	{
 #ifdef _WIN32
-		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetWStr()) + xSF->GetTagValue("_lib").GetWStr(), 4, 8));
+		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue("_lib").GetWStr(), 4, 8));
 #else
-		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetAnsi()) + xSF->GetTagValue("_lib").GetAnsi(), 4, 8));
+		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue("_lib").GetAnsi(), 4, 8));
 #endif
-		if (!RecursiveLoad2SF(libxSF.get(), level + 1))
+		if (!this->RecursiveLoad2SF(libxSF.get(), level + 1))
 			return false;
 	}
 
-	if (!Map2SF(xSF))
+	if (!this->Map2SF(xSFToLoad))
 		return false;
 
 	unsigned n = 2;
@@ -505,15 +161,15 @@
 	{
 		found = false;
 		std::string libTag = "_lib" + stringify(n++);
-		if (xSF->GetTagExists(libTag))
+		if (xSFToLoad->GetTagExists(libTag))
 		{
 			found = true;
 #ifdef _WIN32
-			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetWStr()) + xSF->GetTagValue(libTag).GetWStr(), 4, 8));
+			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue(libTag).GetWStr(), 4, 8));
 #else
-			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetAnsi()) + xSF->GetTagValue(libTag).GetAnsi(), 4, 8));
+			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue(libTag).GetAnsi(), 4, 8));
 #endif
-			if (!RecursiveLoad2SF(libxSF.get(), level + 1))
+			if (!this->RecursiveLoad2SF(libxSF.get(), level + 1))
 				return false;
 		}
 	} while (found);
@@ -521,13 +177,11 @@
 	return true;
 }
 
-static bool Load2SF(XSFFile *xSF)
-{
-	loaderwork.rom.clear();
-	loaderwork.state.clear();
-	loaderwork.stateptr = 0;
-
-	return RecursiveLoad2SF(xSF, 1);
+bool XSFPlayer_2SF::Load2SF(XSFFile *xSFToLoad)
+{
+	this->rom.clear();
+
+	return this->RecursiveLoad2SF(xSFToLoad, 1);
 }
 
 XSFPlayer_2SF::XSFPlayer_2SF(const std::string &filename) : XSFPlayer()
@@ -542,11 +196,11 @@
 
 bool XSFPlayer_2SF::Load()
 {
-	int frames = xSF->GetTagValue("_frames", -1);
-	sndifwork.sync_type = xSF->GetTagValue("_2sf_sync_type", 0);
+	int frames = this->xSF->GetTagValue("_frames", -1);
+	sndifwork.sync_type = this->xSF->GetTagValue("_2sf_sync_type", 0);
 
 	sndifwork.xfs_load = false;
-	if (!Load2SF(this->xSF))
+	if (!this->Load2SF(this->xSF))
 		return false;
 
 	if (NDS_Init())
@@ -557,103 +211,23 @@
 	execute = false;
 
 	MMU_unsetRom();
-	if (!loaderwork.rom.empty())
-	{
-		NDS_SetROM(&loaderwork.rom[0], loaderwork.rom.size() - 1);
-		gameInfo.loadData(reinterpret_cast<char *>(&loaderwork.rom[0]), loaderwork.rom.size() - 1);
+	if (!this->rom.empty())
+	{
+		NDS_SetROM(&this->rom[0], this->rom.size() - 1);
+		gameInfo.loadData(reinterpret_cast<char *>(&this->rom[0]), this->rom.size() - 1);
 	}
 
 	NDS_Reset();
 
 	execute = true;
 
-	if (!loaderwork.state.empty())
-	{
-		armcp15_t *c9 = reinterpret_cast<armcp15_t *>(NDS_ARM9.coproc[15]);
-		//int proc;
-		if (frames == -1)
-		{
-			/* set initial ARM9 coprocessor state */
-
-			armcp15_moveARM2CP(c9, 0x00000000, 0x01, 0x00, 0, 0);
-			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x05, 0, 0);
-			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x06, 0, 0);
-			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4);
-			armcp15_moveARM2CP(c9, 0x04000033, 0x06, 0x00, 0, 4);
-			armcp15_moveARM2CP(c9, 0x0200002d, 0x06, 0x01, 0, 0);
-			armcp15_moveARM2CP(c9, 0x027e0021, 0x06, 0x02, 0, 0);
-			armcp15_moveARM2CP(c9, 0x08000035, 0x06, 0x03, 0, 0);
-			armcp15_moveARM2CP(c9, 0x027e001b, 0x06, 0x04, 0, 0);
-			armcp15_moveARM2CP(c9, 0x0100002f, 0x06, 0x05, 0, 0);
-			armcp15_moveARM2CP(c9, 0xffff001d, 0x06, 0x06, 0, 0);
-			armcp15_moveARM2CP(c9, 0x027ff017, 0x06, 0x07, 0, 0);
-			armcp15_moveARM2CP(c9, 0x00000020, 0x09, 0x01, 0, 1);
-
-			armcp15_moveARM2CP(c9, 0x027e000a, 0x09, 0x01, 0, 0);
-
-			armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 1);
-			armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 0);
-			armcp15_moveARM2CP(c9, 0x00000002, 0x03, 0x00, 0, 0);
-			armcp15_moveARM2CP(c9, 0x05100011, 0x05, 0x00, 0, 3);
-			armcp15_moveARM2CP(c9, 0x15111011, 0x05, 0x00, 0, 2);
-			armcp15_moveARM2CP(c9, 0x07dd1e10, 0x01, 0x00, 0, 0);
-			armcp15_moveARM2CP(c9, 0x0005707d, 0x01, 0x00, 0, 0);
-
-			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4);
-			armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x05, 0, 1);
-			armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x0e, 0, 1);
-
-			/* set initial timer state */
-
-			/*MMU_write16(0, REG_TM0CNTL, 0x0000);
-			MMU_write16(0, REG_TM0CNTH, 0x00C1);
-			MMU_write16(1, REG_TM0CNTL, 0x0000);
-			MMU_write16(1, REG_TM0CNTH, 0x00C1);
-			MMU_write16(1, REG_TM1CNTL, 0xf7e7);
-			MMU_write16(1, REG_TM1CNTH, 0x00C1);*/
-
-			/* set initial interrupt state */
-
-			MMU.reg_IME[0] = 0x00000001;
-			MMU.reg_IE[0]  = 0x00042001;
-			MMU.reg_IME[1] = 0x00000001;
-			MMU.reg_IE[1]  = 0x0104009d;
-		}
-		else if (frames > 0)
-		{
-			/* execute boot code */
-			for (int i = 0; i < frames; ++i)
-				NDS_exec<true>();
-		}
-
-		/* load state */
-
-		execute = false;
-		SPU_Reset();
-
-		load_setstate();
-		loaderwork.state.clear();
-
-		if (frames == -1)
-			armcp15_moveARM2CP(c9, (NDS_ARM9.R13_irq & 0x0fff0000) | 0x0a, 0x09, 0x01, 0, 0);
-
-		/* restore timer state */
-
-		/*for (proc = 0; proc < 2; proc++)
-		{
-			MMU_write16(proc, REG_TM0CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM0CNTH & 0xFFF));
-			MMU_write16(proc, REG_TM1CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM1CNTH & 0xFFF));
-			MMU_write16(proc, REG_TM2CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM2CNTH & 0xFFF));
-			MMU_write16(proc, REG_TM3CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM3CNTH & 0xFFF));
-		}*/
-	}
-	else if (frames > 0)
+	if (frames > 0)
 	{
 		/* skip 1 sec */
 		for (int i = 0; i < frames; ++i)
 			NDS_exec<false>();
 	}
-	execute = true;
+
 	sndifwork.xfs_load = true;
 	//CommonSettings.spu_advanced = true;
 	//CommonSettings.advanced_timing = false;
@@ -728,8 +302,6 @@
 	MMU_unsetRom();
 	NDS_DeInit();
 
-	loaderwork.rom.clear();
-	loaderwork.state.clear();
-	loaderwork.stateptr = 0;
-}
-
+	this->rom.clear();
+}
+

--- a/src/in_gsf/vbam/gba/GBA-arm.cpp
+++ b/src/in_gsf/vbam/gba/GBA-arm.cpp
@@ -356,7 +356,11 @@
         EMIT2(and, KONST(0x1F), ecx)
 #define VALUE_LOAD_REG \
         EMIT2(and, KONST(0x0F), eax)            \
+                EMIT2(cmp, KONST(0x0F), eax)                    \
         EMIT2(mov, REGREF2(eax,4), eax)         \
+                EMIT1(jne, LABELREF(3,f))                               \
+                EMIT2(add, KONST(4), eax)                               \
+                LABEL(3)                                                                \
         EMIT2(movzx, ch, ecx)                   \
         EMIT2(and, KONST(0x0F), ecx)            \
         EMIT2(mov, REGREF2(ecx,4), ecx)
@@ -753,13 +757,17 @@
 // OP Rd,Rb,Rm LSL Rs
 #ifndef VALUE_LSL_REG_C
  #define VALUE_LSL_REG_C \
-    unsigned int shift = reg[(opcode >> 8)&15].B.B0;    \
+    u32 shift = reg[(opcode >> 8)&15].B.B0;                  \
+    u32 rm = reg[opcode & 0x0F].I;                           \
+    if((opcode & 0x0F) == 15) {                              \
+        rm += 4;                                             \
+    }                                                        \
     if (LIKELY(shift)) {                                \
         if (shift == 32) {                              \
             value = 0;                                  \
-            C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false);\
+            C_OUT = (rm & 1 ? true : false);                 \
         } else if (LIKELY(shift < 32)) {                \
-            u32 v = reg[opcode & 0x0F].I;               \
+            u32 v = rm;                                      \
             C_OUT = (v >> (32 - shift)) & 1 ? true : false;\
             value = v << shift;                         \
         } else {                                        \
@@ -767,13 +775,13 @@
             C_OUT = false;                              \
         }                                               \
     } else {                                            \
-        value = reg[opcode & 0x0F].I;                   \
+        value = rm;                                          \
     }
 #endif
 // OP Rd,Rb,Rm LSR #
 #ifndef VALUE_LSR_IMM_C
  #define VALUE_LSR_IMM_C \
-    unsigned int shift = (opcode >> 7) & 0x1F;          \
+    u32 shift = (opcode >> 7) & 0x1F;                   \
     if (LIKELY(shift)) {                                \
         u32 v = reg[opcode & 0x0F].I;                   \
         C_OUT = (v >> (shift - 1)) & 1 ? true : false;  \
@@ -787,12 +795,16 @@
 #ifndef VALUE_LSR_REG_C
  #define VALUE_LSR_REG_C \
     unsigned int shift = reg[(opcode >> 8)&15].B.B0;    \
+    u32 rm = reg[opcode & 0x0F].I;                      \
+    if((opcode & 0x0F) == 15) {                         \
+        rm += 4;                                            \
+    }                                                   \
     if (LIKELY(shift)) {                                \
         if (shift == 32) {                              \
             value = 0;                                  \
-            C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false);\
+            C_OUT = (rm & 0x80000000 ? true : false);\
         } else if (LIKELY(shift < 32)) {                \
-            u32 v = reg[opcode & 0x0F].I;               \
+            u32 v = rm;               \
             C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
             value = v >> shift;                         \
         } else {                                        \
@@ -800,7 +812,7 @@
             C_OUT = false;                              \
         }                                               \
     } else {                                            \
-        value = reg[opcode & 0x0F].I;                   \
+        value = rm;                   \
     }
 #endif
 // OP Rd,Rb,Rm ASR #
@@ -826,13 +838,17 @@
 #ifndef VALUE_ASR_REG_C
  #define VALUE_ASR_REG_C \
     unsigned int shift = reg[(opcode >> 8)&15].B.B0;    \
+    u32 rm = reg[opcode & 0x0F].I;                      \
+    if((opcode & 0x0F) == 15) {                         \
+        rm += 4;                                            \
+    }                                                   \
     if (LIKELY(shift < 32)) {                           \
         if (LIKELY(shift)) {                            \
-            s32 v = reg[opcode & 0x0F].I;               \
+            s32 v = rm;               \
             C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\
             value = v >> (int)shift;                    \
         } else {                                        \
-            value = reg[opcode & 0x0F].I;               \
+            value = rm;               \
         }                                               \
     } else {                                            \
         if (reg[opcode & 0x0F].I & 0x80000000) {        \
@@ -864,13 +880,17 @@
 #ifndef VALUE_ROR_REG_C
  #define VALUE_ROR_REG_C \
     unsigned int shift = reg[(opcode >> 8)&15].B.B0;    \
+    u32 rm = reg[opcode & 0x0F].I;                      \
+    if((opcode & 0x0F) == 15) {                         \
+        rm += 4;                                            \
+    }                                                   \
     if (LIKELY(shift & 0x1F)) {                         \
-        u32 v = reg[opcode & 0x0F].I;                   \
+        u32 v = rm;                   \
         C_OUT = (v >> (shift - 1)) & 1 ? true : false;  \
         value = ((v << (32 - shift)) |                  \
                  (v >> shift));                         \
     } else {                                            \
-        value = reg[opcode & 0x0F].I;                   \
+        value = rm;                   \
         if (shift)                                      \
             C_OUT = (value & 0x80000000 ? true : false);\
     }
@@ -951,9 +971,9 @@
 #endif
 #ifndef OP_RSB
  #define OP_RSB \
-    u32 lhs = reg[(opcode>>16)&15].I;                   \
-    u32 rhs = value;                                    \
-    u32 res = rhs - lhs;                                \
+    u32 lhs = value;                                    \
+    u32 rhs = reg[(opcode>>16)&15].I;                   \
+    u32 res = lhs - rhs;                                \
     reg[dest].I = res;
 #endif
 #ifndef OP_RSBS
@@ -991,9 +1011,9 @@
 #endif
 #ifndef OP_RSC
  #define OP_RSC \
-    u32 lhs = reg[(opcode>>16)&15].I;                   \
-    u32 rhs = value;                                    \
-    u32 res = rhs - lhs - !((u32)C_FLAG);               \
+    u32 lhs = value;                                    \
+    u32 rhs = reg[(opcode>>16)&15].I;                   \
+    u32 res = lhs - rhs - !((u32)C_FLAG);               \
     reg[dest].I = res;
 #endif
 #ifndef OP_RSCS
@@ -1517,7 +1537,7 @@
 #define OP_LDR    reg[dest].I = CPUReadMemory(address)
 #define OP_LDRH   reg[dest].I = CPUReadHalfWord(address)
 #define OP_LDRB   reg[dest].I = CPUReadByte(address)
-#define OP_LDRSH  reg[dest].I = (s16)CPUReadHalfWordSigned(address)
+#define OP_LDRSH  reg[dest].I = (u32)CPUReadHalfWordSigned(address)
 #define OP_LDRSB  reg[dest].I = (s8)CPUReadByte(address)
 
 #define WRITEBACK_NONE     /*nothing*/
@@ -2592,8 +2612,7 @@
     reg[15].I += 4;
     ARM_PREFETCH;
     clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
-    clockTicks += 2 + codeTicksAccess32(armNextPC)
-                    + codeTicksAccessSeq32(armNextPC);
+    clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
     busPrefetchCount = 0;
 }
 
@@ -2629,8 +2648,7 @@
 static INSN_REGPARM void armF00(u32 opcode)
 {
     clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
-    clockTicks += 2 + codeTicksAccess32(armNextPC)
-                    + codeTicksAccessSeq32(armNextPC);
+        clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
     busPrefetchCount = 0;
     CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
 }
@@ -2682,9 +2700,9 @@
     arm0D0,arm0D1,arm0D2,arm0D3,arm0D4,arm0D5,arm0D6,arm0D7,  // 0D0
     arm0D0,arm0D9,arm0D2,arm0DB,arm0D4,arm0DD,arm0D6,arm0DF,  // 0D8
     arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7,  // 0E0
-    arm0E0,arm0E9,arm0E2,arm_UI,arm0E4,arm_UI,arm0E6,arm_UI,  // 0E8
+    arm0E0,arm0E9,arm0E2,arm0CB,arm0E4,arm_UI,arm0E6,arm_UI,  // 0E8
     arm0F0,arm0F1,arm0F2,arm0F3,arm0F4,arm0F5,arm0F6,arm0F7,  // 0F0
-    arm0F0,arm0F9,arm0F2,arm_UI,arm0F4,arm0DD,arm0F6,arm0DF,  // 0F8
+    arm0F0,arm0F9,arm0F2,arm0DB,arm0F4,arm0DD,arm0F6,arm0DF,  // 0F8
 
     arm100,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,  // 100
     arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI,  // 108

--- a/src/in_gsf/vbam/gba/GBA-thumb.cpp
+++ b/src/in_gsf/vbam/gba/GBA-thumb.cpp
@@ -1417,10 +1417,18 @@
   CMP_RD_RS;
 }
 
+// MOV Rd, Rs
+static INSN_REGPARM void thumb46_0(u32 opcode)
+{
+        reg[opcode&7].I = reg[((opcode>>3)&7)].I;
+        clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+}
+
 // MOV Rd, Hs
 static INSN_REGPARM void thumb46_1(u32 opcode)
 {
   reg[opcode&7].I = reg[((opcode>>3)&7)+8].I;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
 }
 
 // MOV Hd, Rs
@@ -1467,16 +1475,14 @@
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC)
-        + codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3;
+    clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3;
   } else {
     armState = true;
     reg[15].I &= 0xFFFFFFFC;
     armNextPC = reg[15].I;
     reg[15].I += 4;
     ARM_PREFETCH;
-    clockTicks = codeTicksAccessSeq32(armNextPC)
-        + codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3;
+    clockTicks = codeTicksAccessSeq32(armNextPC)*2 + codeTicksAccess32(armNextPC) + 3;
   }
 }
 
@@ -1570,7 +1576,7 @@
   if (busPrefetchCount == 0)
     busPrefetch = busPrefetchEnable;
   u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
-  reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address);
+  reg[opcode&7].I = (u32)CPUReadHalfWordSigned(address);
   clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
 }
 
@@ -1663,6 +1669,7 @@
 {
   u8 regist = (opcode >> 8) & 7;
   reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
+  clockTicks = 1 + codeTicksAccess16(armNextPC);
 }
 
 // ADD R0~R7, SP, Imm
@@ -1670,6 +1677,7 @@
 {
   u8 regist = (opcode >> 8) & 7;
   reg[regist].I = reg[13].I + ((opcode&255)<<2);
+  clockTicks = 1 + codeTicksAccess16(armNextPC);
 }
 
 // ADD SP, Imm
@@ -1679,6 +1687,7 @@
   if(opcode & 0x80)
     offset = -offset;
   reg[13].I += offset;
+  clockTicks = 1 + codeTicksAccess16(armNextPC);
 }
 
 // Push and pop ///////////////////////////////////////////////////////////
@@ -1876,13 +1885,13 @@
 static INSN_REGPARM void thumbD0(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(Z_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -1891,13 +1900,13 @@
 static INSN_REGPARM void thumbD1(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(!Z_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -1906,13 +1915,13 @@
 static INSN_REGPARM void thumbD2(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(C_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -1921,13 +1930,13 @@
 static INSN_REGPARM void thumbD3(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(!C_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -1936,13 +1945,13 @@
 static INSN_REGPARM void thumbD4(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(N_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -1951,13 +1960,13 @@
 static INSN_REGPARM void thumbD5(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(!N_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -1966,13 +1975,13 @@
 static INSN_REGPARM void thumbD6(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(V_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -1981,13 +1990,13 @@
 static INSN_REGPARM void thumbD7(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(!V_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -1996,13 +2005,13 @@
 static INSN_REGPARM void thumbD8(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(C_FLAG && !Z_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -2011,13 +2020,13 @@
 static INSN_REGPARM void thumbD9(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(!C_FLAG || Z_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -2026,13 +2035,13 @@
 static INSN_REGPARM void thumbDA(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(N_FLAG == V_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -2041,13 +2050,13 @@
 static INSN_REGPARM void thumbDB(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(N_FLAG != V_FLAG) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -2056,13 +2065,13 @@
 static INSN_REGPARM void thumbDC(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
   if(!Z_FLAG && (N_FLAG == V_FLAG)) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -2071,13 +2080,13 @@
 static INSN_REGPARM void thumbDD(u32 opcode)
 {
   UPDATE_OLDREG;
+  clockTicks = codeTicksAccessSeq16(armNextPC);
   if(Z_FLAG || (N_FLAG != V_FLAG)) {
     reg[15].I += ((s8)(opcode & 0xFF)) << 1;
     armNextPC = reg[15].I;
     reg[15].I += 2;
     THUMB_PREFETCH;
-    clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-        codeTicksAccess16(armNextPC)+3;
+    clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
     busPrefetchCount=0;
   }
 }
@@ -2088,8 +2097,8 @@
 static INSN_REGPARM void thumbDF(u32 opcode)
 {
   u32 address = 0;
-  clockTicks = codeTicksAccessSeq16(address) + codeTicksAccessSeq16(address) +
-      codeTicksAccess16(address)+3;
+  //clockTicks = codeTicksAccessSeq16(address)*2 + codeTicksAccess16(address)+3;
+  clockTicks = 3;
   busPrefetchCount=0;
   CPUSoftwareInterrupt(opcode & 0xFF);
 }
@@ -2104,8 +2113,7 @@
   armNextPC = reg[15].I;
   reg[15].I += 2;
   THUMB_PREFETCH;
-  clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
-      codeTicksAccess16(armNextPC) + 3;
+  clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC)+3;
   busPrefetchCount=0;
 }
 
@@ -2135,8 +2143,7 @@
   reg[15].I += 2;
   reg[14].I = temp|1;
   THUMB_PREFETCH;
-  clockTicks = codeTicksAccessSeq16(armNextPC) +
-      codeTicksAccess16(armNextPC) + codeTicksAccessSeq16(armNextPC) + 3;
+  clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3;
   busPrefetchCount = 0;
 }
 
@@ -2185,7 +2192,7 @@
   thumb40_0,thumb40_1,thumb40_2,thumb40_3,thumb41_0,thumb41_1,thumb41_2,thumb41_3,  // 40
   thumb42_0,thumb42_1,thumb42_2,thumb42_3,thumb43_0,thumb43_1,thumb43_2,thumb43_3,
   thumbUI,thumb44_1,thumb44_2,thumb44_3,thumbUI,thumb45_1,thumb45_2,thumb45_3,
-  thumbUI,thumb46_1,thumb46_2,thumb46_3,thumb47,thumb47,thumbUI,thumbUI,
+  thumb46_0,thumb46_1,thumb46_2,thumb46_3,thumb47,thumb47,thumbUI,thumbUI,
   thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,  // 48
   thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
   thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,

--- a/src/in_gsf/vbam/gba/GBA.cpp
+++ b/src/in_gsf/vbam/gba/GBA.cpp
@@ -44,7 +44,6 @@
 u32 busPrefetchCount = 0;
 int cpuDmaTicksToUpdate = 0;
 int cpuDmaCount = 0;
-bool cpuDmaHack = false;
 u32 cpuDmaLast = 0;
 int dummyAddress = 0;
 
@@ -936,7 +935,7 @@
   fseek(file, 0x0, SEEK_SET);
   fread(&i, 1, 4, file);
   fseek(file, i, SEEK_CUR); // Skip SharkPortSave
-  fseek(file, 4, SEEK_CUR); // skip some sort of flag
+//  fseek(file, 4, SEEK_CUR); // skip some sort of flag
   fread(&i, 1, 4, file); // name length
   fseek(file, i, SEEK_CUR); // skip name
   fread(&i, 1, 4, file); // desc length
@@ -1812,8 +1811,8 @@
   case 0x02:
 #ifdef GBA_LOGGING
     if(systemVerbose & VERBOSE_SWI) {
-      log("Halt: (VCOUNT = %2d)\n",
-          VCOUNT);
+      /*log("Halt: (VCOUNT = %2d)\n",
+          VCOUNT);*/
     }
 #endif
     holdState = true;
@@ -1823,8 +1822,8 @@
   case 0x03:
 #ifdef GBA_LOGGING
     if(systemVerbose & VERBOSE_SWI) {
-      log("Stop: (VCOUNT = %2d)\n",
-          VCOUNT);
+      /*log("Stop: (VCOUNT = %2d)\n",
+          VCOUNT);*/
     }
 #endif
     holdState = true;
@@ -2190,7 +2189,6 @@
       doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement,
             DM0CNT_L ? DM0CNT_L : 0x4000,
             DM0CNT_H & 0x0400);
-      cpuDmaHack = true;
 
       if(DM0CNT_H & 0x4000) {
         IF |= 0x0100;
@@ -2259,7 +2257,6 @@
               DM1CNT_L ? DM1CNT_L : 0x4000,
               DM1CNT_H & 0x0400);
       }
-      cpuDmaHack = true;
 
       if(DM1CNT_H & 0x4000) {
         IF |= 0x0200;
@@ -2329,7 +2326,6 @@
               DM2CNT_L ? DM2CNT_L : 0x4000,
               DM2CNT_H & 0x0400);
       }
-      cpuDmaHack = true;
 
       if(DM2CNT_H & 0x4000) {
         IF |= 0x0400;
@@ -3412,8 +3408,6 @@
 
   //systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
 
-  cpuDmaHack = false;
-
   lastTime = /*systemGetClock()*/0;
 
   SWITicks = 0;
@@ -3512,7 +3506,6 @@
 
       clockTicks = cpuNextEvent;
       cpuTotalTicks = 0;
-      cpuDmaHack = false;
 
     updateLoop:
 
@@ -3914,7 +3907,6 @@
         cpuDmaTicksToUpdate -= clockTicks;
         if(cpuDmaTicksToUpdate < 0)
           cpuDmaTicksToUpdate = 0;
-        cpuDmaHack = true;
         goto updateLoop;
       }
 

--- a/src/in_gsf/vbam/gba/GBAinline.h
+++ b/src/in_gsf/vbam/gba/GBAinline.h
@@ -19,7 +19,6 @@
 extern bool cpuFlashEnabled;
 extern bool cpuEEPROMEnabled;
 extern bool cpuEEPROMSensorEnabled;
-extern bool cpuDmaHack;
 extern u32 cpuDmaLast;
 extern bool timer0On;
 extern int timer0Ticks;
@@ -46,23 +45,20 @@
 
 static inline u32 CPUReadMemory(u32 address)
 {
-#ifdef GBA_LOGGING
+  u32 value;
+  u32 oldAddress = address;
+
   if(address & 3) {
-    if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
-      log("Unaligned word read: %08x at %08x\n", address, armMode ?
-        armNextPC - 4 : armNextPC - 2);
-    }
-  }
-#endif
-
-  u32 value;
+           address &= ~0x03;
+  }
+
   switch(address >> 24) {
   case 0:
     if(reg[15].I >> 24) {
       if(address < 0x4000) {
 #ifdef GBA_LOGGING
         if(systemVerbose & VERBOSE_ILLEGAL_READ) {
-          log("Illegal word read: %08x at %08x\n", address, armMode ?
+          log("Illegal word read from bios: %08x at %08x\n", address, armMode ?
             armNextPC - 4 : armNextPC - 2);
         }
 #endif
@@ -135,21 +131,17 @@
     }
 #endif
 
-    if(cpuDmaHack) {
-      value = cpuDmaLast;
-    } else {
       if(armState) {
-        value = CPUReadMemoryQuick(reg[15].I);
+                return CPUReadMemoryQuick(reg[15].I);
       } else {
-        value = CPUReadHalfWordQuick(reg[15].I) |
+                return CPUReadHalfWordQuick(reg[15].I) |
           CPUReadHalfWordQuick(reg[15].I) << 16;
       }
     }
-  }
-
-  if(address & 3) {
+
+  if(oldAddress & 3) {
 #ifdef C_CORE
-    int shift = (address & 3) << 3;
+        int shift = (oldAddress & 3) << 3;
     value = (value >> shift) | (value << (32 - shift));
 #else
 #ifdef __GNUC__
@@ -157,10 +149,10 @@
       "shl $3 ,%%ecx;"
       "ror %%cl, %0"
       : "=r" (value)
-      : "r" (value), "c" (address));
+      : "r" (value), "c" (oldAddress));
 #else
     __asm {
-      mov ecx, address;
+      mov ecx, oldAddress;
       and ecx, 3;
       shl ecx, 3;
       ror [dword ptr value], cl;
@@ -168,6 +160,15 @@
 #endif
 #endif
   }
+
+#ifdef GBA_LOGGING
+  if(oldAddress & 3) {
+          if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
+                  log("Unaligned word read from: %08x at %08x (%08x)\n", oldAddress, armMode ?
+                          armNextPC - 4 : armNextPC - 2, value);
+          }
+  }
+#endif
   return value;
 }
 
@@ -175,16 +176,12 @@
 
 static inline u32 CPUReadHalfWord(u32 address)
 {
-#ifdef GBA_LOGGING
+  u32 value;
+  u32 oldAddress = address;
+
   if(address & 1) {
-    if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
-      log("Unaligned halfword read: %08x at %08x\n", address, armMode ?
-        armNextPC - 4 : armNextPC - 2);
-    }
-  }
-#endif
-
-  u32 value;
+          address &= ~0x01;
+  }
 
   switch(address >> 24) {
   case 0:
@@ -192,7 +189,7 @@
       if(address < 0x4000) {
 #ifdef GBA_LOGGING
         if(systemVerbose & VERBOSE_ILLEGAL_READ) {
-          log("Illegal halfword read: %08x at %08x\n", address, armMode ?
+          log("Illegal halfword read from bios: %08x at %08x\n", oldAddress, armMode ?
             armNextPC - 4 : armNextPC - 2);
         }
 #endif
@@ -269,34 +266,48 @@
 unreadable:
 #ifdef GBA_LOGGING
     if(systemVerbose & VERBOSE_ILLEGAL_READ) {
-      log("Illegal halfword read: %08x at %08x\n", address, armMode ?
+      log("Illegal halfword read: %08x at %08x\n", oldAddress, armMode ?
         armNextPC - 4 : armNextPC - 2);
     }
 #endif
-    if(cpuDmaHack) {
-      value = cpuDmaLast & 0xFFFF;
-    } else {
       if(armState) {
-        value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
+                return CPUReadMemoryQuick(reg[15].I);
       } else {
-        value = CPUReadHalfWordQuick(reg[15].I);
+                return CPUReadHalfWordQuick(reg[15].I) |
+                                CPUReadHalfWordQuick(reg[15].I) << 16;
       }
     }
-    break;
-  }
-
-  if(address & 1) {
+
+  if(oldAddress & 1) {
     value = (value >> 8) | (value << 24);
+#ifdef GBA_LOGGING
+          if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
+                  log("Unaligned halfword read from: %08x at %08x (%08x)\n", oldAddress, armMode ?
+                          armNextPC - 4 : armNextPC - 2, value);
+          }
+#endif
   }
 
   return value;
 }
 
-static inline u16 CPUReadHalfWordSigned(u32 address)
+static inline s16 CPUReadHalfWordSigned(u32 address)
 {
-  u16 value = CPUReadHalfWord(address);
-  if((address & 1))
+  u32 oldAddress = address;
+  if(address & 1) {
+    address &= ~0x01;
+  }
+  s16 value = (s16)CPUReadHalfWord(address);
+  if((oldAddress & 1))
+  {
     value = (s8)value;
+#ifdef GBA_LOGGING
+        if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
+                log("Unaligned signed halfword read from: %08x at %08x (%08x)\n", oldAddress, armMode ?
+                        armNextPC - 4 : armNextPC - 2, value);
+        }
+#endif
+  }
   return value;
 }
 
@@ -308,7 +319,7 @@
       if(address < 0x4000) {
 #ifdef GBA_LOGGING
         if(systemVerbose & VERBOSE_ILLEGAL_READ) {
-          log("Illegal byte read: %08x at %08x\n", address, armMode ?
+          log("Illegal byte read from bios: %08x at %08x\n", address, armMode ?
             armNextPC - 4 : armNextPC - 2);
         }
 #endif
@@ -369,17 +380,13 @@
         armNextPC - 4 : armNextPC - 2);
     }
 #endif
-    if(cpuDmaHack) {
-      return cpuDmaLast & 0xFF;
-    } else {
       if(armState) {
-        return CPUReadByteQuick(reg[15].I+(address & 3));
+                         return CPUReadMemoryQuick(reg[15].I);
       } else {
-        return CPUReadByteQuick(reg[15].I+(address & 1));
+                         return CPUReadHalfWordQuick(reg[15].I) |
+                                 CPUReadHalfWordQuick(reg[15].I) << 16;
       }
     }
-    break;
-  }
 }
 
 static inline void CPUWriteMemory(u32 address, u32 value)
@@ -396,6 +403,8 @@
   }
 #endif
 
+  address &= 0xFFFFFFFC;
+
   switch(address >> 24) {
   case 0x02:
 #ifdef BKPT_SUPPORT
@@ -492,6 +501,8 @@
     }
   }
 #endif
+
+  address &= 0xFFFFFFFE;
 
   switch(address >> 24) {
   case 2:

--- a/src/in_gsf/vbam/gba/Sound.cpp
+++ b/src/in_gsf/vbam/gba/Sound.cpp
@@ -42,7 +42,7 @@
 
 int const SOUND_CLOCK_TICKS_ = 167772; // 1/100 second
 
-static u16   soundFinalWave [1600];
+static u16   soundFinalWave [6400];
 long  soundSampleRate    = 44100;
 bool  soundInterpolation = true;
 bool  soundPaused        = true;
@@ -452,6 +452,13 @@
 	pcm [0].pcm.init();
 	pcm [1].pcm.init();
 
+	// APU
+	if ( !gb_apu )
+	{
+		gb_apu = new Gb_Apu; // TODO: handle out of memory
+		reset_apu();
+	}
+
 	// Stereo_Buffer
 	delete stereo_buffer;
 	stereo_buffer = 0;
@@ -465,13 +472,7 @@
 	pcm [1].which = 1;
 	apply_filtering();
 
-	// APU
-	if ( !gb_apu )
-	{
-		gb_apu = new Gb_Apu; // TODO: handle out of memory
-		reset_apu();
-	}
-
+	// Volume Level
 	apply_muting();
 	apply_volume();
 }

--- a/src/in_gsf/vbam/revision.txt
+++ b/src/in_gsf/vbam/revision.txt
@@ -1,1 +1,1 @@
-1102
+1195