<commit_before>/* Copyright (c) 2013-2015 <NAME>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mgba/internal/gba/bios.h>

#include <mgba/internal/arm/isa-inlines.h>
#include <mgba/internal/arm/macros.h>
#include <mgba/internal/gba/gba.h>
#include <mgba/internal/gba/io.h>
#include <mgba/internal/gba/memory.h>
#include <mgba-util/math.h>

const uint32_t GBA_BIOS_CHECKSUM = 0xBAAE187F;
const uint32_t GBA_DS_BIOS_CHECKSUM = 0xBAAE1880;

mLOG_DEFINE_CATEGORY(GBA_BIOS, "GBA BIOS", "gba.bios");

static void _unLz77(struct GBA* gba, int width);
static void _unHuffman(struct GBA* gba);
static void _unRl(struct GBA* gba, int width);
static void _unFilter(struct GBA* gba, int inwidth, int outwidth);
static void _unBitPack(struct GBA* gba);

static int _mulWait(int32_t r) {
	if ((r & 0xFFFFFF00) == 0xFFFFFF00 || !(r & 0xFFFFFF00)) {
		return 1;
	} else if ((r & 0xFFFF0000) == 0xFFFF0000 || !(r & 0xFFFF0000)) {
		return 2;
	} else if ((r & 0xFF000000) == 0xFF000000 || !(r & 0xFF000000)) {
		return 3;
	} else {
		return 4;
	}
}

static void _SoftReset(struct GBA* gba) {
	struct ARMCore* cpu = gba->cpu;
	ARMSetPrivilegeMode(cpu, MODE_IRQ);
	cpu->spsr.packed = 0;
	cpu->gprs[ARM_LR] = 0;
	cpu->gprs[ARM_SP] = SP_BASE_IRQ;
	ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
	cpu->spsr.packed = 0;
	cpu->gprs[ARM_LR] = 0;
	cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR;
	ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
	cpu->gprs[ARM_LR] = 0;
	cpu->gprs[ARM_SP] = SP_BASE_SYSTEM;
	int8_t flag = ((int8_t*) gba->memory.iwram)[0x7FFA];
	memset(((int8_t*) gba->memory.iwram) + SIZE_WORKING_IRAM - 0x200, 0, 0x200);
	if (flag) {
		cpu->gprs[ARM_PC] = BASE_WORKING_RAM;
	} else {
		cpu->gprs[ARM_PC] = BASE_CART0;
	}
	_ARMSetMode(cpu, MODE_ARM);
	ARMWritePC(cpu);
}

static void _RegisterRamReset(struct GBA* gba) {
	uint32_t registers = gba->cpu->gprs[0];
	struct ARMCore* cpu = gba->cpu;
	cpu->memory.store16(cpu, BASE_IO | REG_DISPCNT, 0x0080, 0);
	if (registers & 0x01) {
		memset(gba->memory.wram, 0, SIZE_WORKING_RAM);
	}
	if (registers & 0x02) {
		memset(gba->memory.iwram, 0, SIZE_WORKING_IRAM - 0x200);
	}
	if (registers & 0x04) {
		memset(gba->video.palette, 0, SIZE_PALETTE_RAM);
	}
	if (registers & 0x08) {
		memset(gba->video.vram, 0, SIZE_VRAM);
	}
	if (registers & 0x10) {
		memset(gba->video.oam.raw, 0, SIZE_OAM);
	}
	if (registers & 0x20) {
		cpu->memory.store16(cpu, BASE_IO | REG_SIOCNT, 0x0000, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_RCNT, RCNT_INITIAL, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SIOMLT_SEND, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_JOYCNT, 0, 0);
		cpu->memory.store32(cpu, BASE_IO | REG_JOY_RECV_LO, 0, 0);
		cpu->memory.store32(cpu, BASE_IO | REG_JOY_TRANS_LO, 0, 0);
	}
	if (registers & 0x40) {
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_X, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND2CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND2CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_X, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND4CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND4CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_X, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUNDBIAS, 0x200, 0);
		memset(gba->audio.psg.ch3.wavedata32, 0, sizeof(gba->audio.psg.ch3.wavedata32));
	}
	if (registers & 0x80) {
		cpu->memory.store16(cpu, BASE_IO | 0x04, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x06, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x08, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x0A, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x0C, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x0E, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x10, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x12, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x14, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x16, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x18, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x1A, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x1C, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x1E, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2PA, 0x100, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2PB, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2PC, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2PD, 0x100, 0);
		cpu->memory.store32(cpu, BASE_IO | 0x28, 0, 0);
		cpu->memory.store32(cpu, BASE_IO | 0x2C, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3PA, 0x100, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3PB, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3PC, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3PD, 0x100, 0);
		cpu->memory.store32(cpu, BASE_IO | 0x38, 0, 0);
		cpu->memory.store32(cpu, BASE_IO | 0x3C, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x40, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x42, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x44, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x46, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x48, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x4A, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x4C, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x50, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x52, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x54, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xB0, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xB2, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xB4, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xB6, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xB8, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xBA, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xBC, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xBE, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xC0, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xC2, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xC4, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xC6, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xC8, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xCA, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xCC, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xCE, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xD0, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xD2, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xD4, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xD6, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xD8, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xDA, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xDC, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0xDE, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x100, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x102, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x104, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x106, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x108, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x10A, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x10C, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x10E, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x200, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x202, 0xFFFF, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x204, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | 0x208, 0, 0);
	}
	if (registers & 0x9C) {
		gba->video.renderer->reset(gba->video.renderer);
		gba->video.renderer->writeVideoRegister(gba->video.renderer, REG_DISPCNT, gba->memory.io[REG_DISPCNT >> 1]);
		int i;
		for (i = REG_BG0CNT; i < REG_SOUND1CNT_LO; i += 2) {
			gba->video.renderer->writeVideoRegister(gba->video.renderer, i, gba->memory.io[i >> 1]);
		}
	}
}

static void _BgAffineSet(struct GBA* gba) {
	struct ARMCore* cpu = gba->cpu;
	int i = cpu->gprs[2];
	float ox, oy;
	float cx, cy;
	float sx, sy;
	float theta;
	int offset = cpu->gprs[0];<commit_msg>GBA BIOS: De-magic constant RegisterRamReset<commit_after>/* Copyright (c) 2013-2015 <NAME>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mgba/internal/gba/bios.h>

#include <mgba/internal/arm/isa-inlines.h>
#include <mgba/internal/arm/macros.h>
#include <mgba/internal/gba/gba.h>
#include <mgba/internal/gba/io.h>
#include <mgba/internal/gba/memory.h>
#include <mgba-util/math.h>

const uint32_t GBA_BIOS_CHECKSUM = 0xBAAE187F;
const uint32_t GBA_DS_BIOS_CHECKSUM = 0xBAAE1880;

mLOG_DEFINE_CATEGORY(GBA_BIOS, "GBA BIOS", "gba.bios");

static void _unLz77(struct GBA* gba, int width);
static void _unHuffman(struct GBA* gba);
static void _unRl(struct GBA* gba, int width);
static void _unFilter(struct GBA* gba, int inwidth, int outwidth);
static void _unBitPack(struct GBA* gba);

static int _mulWait(int32_t r) {
	if ((r & 0xFFFFFF00) == 0xFFFFFF00 || !(r & 0xFFFFFF00)) {
		return 1;
	} else if ((r & 0xFFFF0000) == 0xFFFF0000 || !(r & 0xFFFF0000)) {
		return 2;
	} else if ((r & 0xFF000000) == 0xFF000000 || !(r & 0xFF000000)) {
		return 3;
	} else {
		return 4;
	}
}

static void _SoftReset(struct GBA* gba) {
	struct ARMCore* cpu = gba->cpu;
	ARMSetPrivilegeMode(cpu, MODE_IRQ);
	cpu->spsr.packed = 0;
	cpu->gprs[ARM_LR] = 0;
	cpu->gprs[ARM_SP] = SP_BASE_IRQ;
	ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
	cpu->spsr.packed = 0;
	cpu->gprs[ARM_LR] = 0;
	cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR;
	ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
	cpu->gprs[ARM_LR] = 0;
	cpu->gprs[ARM_SP] = SP_BASE_SYSTEM;
	int8_t flag = ((int8_t*) gba->memory.iwram)[0x7FFA];
	memset(((int8_t*) gba->memory.iwram) + SIZE_WORKING_IRAM - 0x200, 0, 0x200);
	if (flag) {
		cpu->gprs[ARM_PC] = BASE_WORKING_RAM;
	} else {
		cpu->gprs[ARM_PC] = BASE_CART0;
	}
	_ARMSetMode(cpu, MODE_ARM);
	ARMWritePC(cpu);
}

static void _RegisterRamReset(struct GBA* gba) {
	uint32_t registers = gba->cpu->gprs[0];
	struct ARMCore* cpu = gba->cpu;
	cpu->memory.store16(cpu, BASE_IO | REG_DISPCNT, 0x0080, 0);
	if (registers & 0x01) {
		memset(gba->memory.wram, 0, SIZE_WORKING_RAM);
	}
	if (registers & 0x02) {
		memset(gba->memory.iwram, 0, SIZE_WORKING_IRAM - 0x200);
	}
	if (registers & 0x04) {
		memset(gba->video.palette, 0, SIZE_PALETTE_RAM);
	}
	if (registers & 0x08) {
		memset(gba->video.vram, 0, SIZE_VRAM);
	}
	if (registers & 0x10) {
		memset(gba->video.oam.raw, 0, SIZE_OAM);
	}
	if (registers & 0x20) {
		cpu->memory.store16(cpu, BASE_IO | REG_SIOCNT, 0x0000, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_RCNT, RCNT_INITIAL, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SIOMLT_SEND, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_JOYCNT, 0, 0);
		cpu->memory.store32(cpu, BASE_IO | REG_JOY_RECV_LO, 0, 0);
		cpu->memory.store32(cpu, BASE_IO | REG_JOY_TRANS_LO, 0, 0);
	}
	if (registers & 0x40) {
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND1CNT_X, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND2CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND2CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND3CNT_X, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND4CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUND4CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUNDCNT_X, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_SOUNDBIAS, 0x200, 0);
		memset(gba->audio.psg.ch3.wavedata32, 0, sizeof(gba->audio.psg.ch3.wavedata32));
	}
	if (registers & 0x80) {
		cpu->memory.store16(cpu, BASE_IO | REG_DISPSTAT, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_VCOUNT, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG0CNT, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG1CNT, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2CNT, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3CNT, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG0HOFS, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG0VOFS, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG1HOFS, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG1VOFS, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2HOFS, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2VOFS, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3HOFS, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3VOFS, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2PA, 0x100, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2PB, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2PC, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG2PD, 0x100, 0);
		cpu->memory.store32(cpu, BASE_IO | REG_BG2X_LO, 0, 0);
		cpu->memory.store32(cpu, BASE_IO | REG_BG2Y_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3PA, 0x100, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3PB, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3PC, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BG3PD, 0x100, 0);
		cpu->memory.store32(cpu, BASE_IO | REG_BG3X_LO, 0, 0);
		cpu->memory.store32(cpu, BASE_IO | REG_BG3Y_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_WIN0H, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_WIN1H, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_WIN0V, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_WIN1V, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_WININ, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_WINOUT, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_MOSAIC, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BLDCNT, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BLDALPHA, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_BLDY, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA0SAD_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA0SAD_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA0DAD_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA0DAD_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA0CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA0CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA1SAD_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA1SAD_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA1DAD_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA1DAD_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA1CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA1CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA2SAD_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA2SAD_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA2DAD_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA2DAD_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA2CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA2CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA3SAD_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA3SAD_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA3DAD_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA3DAD_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA3CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_DMA3CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_TM0CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_TM0CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_TM1CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_TM1CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_TM2CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_TM2CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_TM3CNT_LO, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_TM3CNT_HI, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_IE, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_IF, 0xFFFF, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_WAITCNT, 0, 0);
		cpu->memory.store16(cpu, BASE_IO | REG_IME, 0, 0);
	}
	if (registers & 0x9C) {
		gba->video.renderer->reset(gba->video.renderer);
		gba->video.renderer->writeVideoRegister(gba->video.renderer, REG_DISPCNT, gba->memory.io[REG_DISPCNT >> 1]);
		int i;
		for (i = REG_BG0CNT; i < REG_SOUND1CNT_LO; i += 2) {
			gba->video.renderer->writeVideoRegister(gba->video.renderer, i, gba->memory.io[i >> 1]);
		}
	}
}

static void _BgAffineSet(struct GBA* gba) {
	struct ARMCore* cpu = gba->cpu;
	int i = cpu->gprs[2];
	float ox, oy;
	float cx, cy;
	float sx, sy;
	float theta;
	int offset = cpu->gprs[0];
{'fraction_non_alphanumeric': 0.1716712525421701, 'fraction_numerical': 0.07979423376001914, 'mean_word_length': 4.525115664243225, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 287, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '56066', 'n_tokens_mistral': 8955, 'n_tokens_neox': 7783, 'n_words': 1501}