776 lines
23 KiB
C
776 lines
23 KiB
C
//
|
|
// state.c
|
|
// vio2sf
|
|
//
|
|
// Created by Christopher Snowhill on 10/13/13.
|
|
// Copyright (c) 2013-2023 Christopher Snowhill. All rights reserved.
|
|
//
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "NDSSystem.h"
|
|
#include "MMU.h"
|
|
#include "GPU.h"
|
|
#include "armcpu.h"
|
|
#include "cp15.h"
|
|
#include "spu_exports.h"
|
|
#include "barray.h"
|
|
|
|
#include "state.h"
|
|
|
|
#define ROM_MASK 3
|
|
|
|
#define SNDCORE_DUMMY 0
|
|
#define SNDCORE_STATE 0
|
|
|
|
#ifdef GDB_STUB
|
|
static struct armcpu_ctrl_iface *arm9_ctrl_iface = 0;
|
|
static struct armcpu_ctrl_iface *arm7_ctrl_iface = 0;
|
|
#endif
|
|
|
|
int state_init(struct NDS_state *state)
|
|
{
|
|
int i;
|
|
|
|
memset(state, 0, sizeof(NDS_state));
|
|
|
|
state->nds = (NDSSystem *) calloc(1, sizeof(NDSSystem));
|
|
if (!state->nds)
|
|
return -1;
|
|
|
|
state->NDS_ARM7 = (armcpu_t *) calloc(1, sizeof(armcpu_t));
|
|
if (!state->NDS_ARM7)
|
|
return -1;
|
|
|
|
state->NDS_ARM9 = (armcpu_t *) calloc(1, sizeof(armcpu_t));
|
|
if (!state->NDS_ARM9)
|
|
return -1;
|
|
|
|
state->MMU = (MMU_struct *) calloc(1, sizeof(MMU_struct));
|
|
if (!state->MMU)
|
|
return -1;
|
|
|
|
state->ARM9Mem = (ARM9_struct *) calloc(1, sizeof(ARM9_struct));
|
|
if (!state->ARM9Mem)
|
|
return -1;
|
|
|
|
state->MainScreen = (NDS_Screen *) calloc(1, sizeof(NDS_Screen));
|
|
if (!state->MainScreen)
|
|
return -1;
|
|
|
|
state->SubScreen = (NDS_Screen *) calloc(1, sizeof(NDS_Screen));
|
|
if (!state->SubScreen)
|
|
return -1;
|
|
|
|
for (i = 0; i < 0x10; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_ITCM;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x00007FFF;
|
|
}
|
|
|
|
for (; i < 0x20; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_WRAM;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x00FFFFFF;
|
|
}
|
|
|
|
for (; i < 0x30; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->MAIN_MEM;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x003FFFFF;
|
|
}
|
|
|
|
for (; i < 0x40; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->MMU->SWIRAM;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x00007FFF;
|
|
}
|
|
|
|
for (; i < 0x50; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_REG;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x00FFFFFF;
|
|
}
|
|
|
|
for (; i < 0x60; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_VMEM;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x000007FF;
|
|
}
|
|
|
|
for (; i < 0x62; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_ABG;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x0007FFFF;
|
|
}
|
|
|
|
for (; i < 0x64; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_BBG;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x0001FFFF;
|
|
}
|
|
|
|
for (; i < 0x66; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_AOBJ;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x0003FFFF;
|
|
}
|
|
|
|
for (; i < 0x68; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_BOBJ;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x0001FFFF;
|
|
}
|
|
|
|
for (; i < 0x70; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_LCD;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x000FFFFF;
|
|
}
|
|
|
|
for (; i < 0x80; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_OAM;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x000007FF;
|
|
}
|
|
|
|
for (; i < 0xA0; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = NULL;
|
|
state->MMU_ARM9_MEM_MASK[i] = ROM_MASK;
|
|
}
|
|
|
|
for (; i < 0xB0; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->MMU->CART_RAM;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x0000FFFF;
|
|
}
|
|
|
|
for (; i < 0xF0; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->MMU->UNUSED_RAM;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x00000003;
|
|
}
|
|
|
|
for (; i < 0x100; ++i)
|
|
{
|
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_BIOS;
|
|
state->MMU_ARM9_MEM_MASK[i] = 0x00007FFF;
|
|
}
|
|
|
|
for (i = 0; i < 0x10; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->ARM7_BIOS;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x00003FFF;
|
|
}
|
|
|
|
for (; i < 0x20; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->UNUSED_RAM;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x00000003;
|
|
}
|
|
|
|
for (; i < 0x30; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->ARM9Mem->MAIN_MEM;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x003FFFFF;
|
|
}
|
|
|
|
for (; i < 0x38; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->SWIRAM;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x00007FFF;
|
|
}
|
|
|
|
for (; i < 0x40; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->ARM7_ERAM;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x0000FFFF;
|
|
}
|
|
|
|
for (; i < 0x48; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->ARM7_REG;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x00FFFFFF;
|
|
}
|
|
|
|
for (; i < 0x50; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->ARM7_WIRAM;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x0000FFFF;
|
|
}
|
|
|
|
for (; i < 0x60; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->UNUSED_RAM;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x00000003;
|
|
}
|
|
|
|
for (; i < 0x70; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->ARM9Mem->ARM9_ABG;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x0003FFFF;
|
|
}
|
|
|
|
for (; i < 0x80; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->UNUSED_RAM;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x00000003;
|
|
}
|
|
|
|
for (; i < 0xA0; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = NULL;
|
|
state->MMU_ARM7_MEM_MASK[i] = ROM_MASK;
|
|
}
|
|
|
|
for (; i < 0xB0; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->CART_RAM;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x0000FFFF;
|
|
}
|
|
|
|
for (; i < 0x100; ++i)
|
|
{
|
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->UNUSED_RAM;
|
|
state->MMU_ARM7_MEM_MASK[i] = 0x00000003;
|
|
}
|
|
|
|
state->partie = 1;
|
|
|
|
state->SPU_currentCoreNum = SNDCORE_DUMMY;
|
|
|
|
#ifdef GDB_STUB
|
|
if (NDS_Init(state, &arm9_base_memory_iface, &arm9_ctrl_iface, &arm7_base_memory_iface, &arm7_ctrl_iface))
|
|
#else
|
|
if (NDS_Init(state))
|
|
#endif
|
|
return -1;
|
|
|
|
SPU_ChangeSoundCore(state, 0, 44100);
|
|
|
|
state->execute = FALSE;
|
|
|
|
MMU_unsetRom(state);
|
|
|
|
state->cycles = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void state_deinit(struct NDS_state *state)
|
|
{
|
|
if (state->MMU)
|
|
MMU_unsetRom(state);
|
|
if (state->nds && state->MMU && state->NDS_ARM7 && state->NDS_ARM9 && state->MainScreen && state->SubScreen)
|
|
NDS_DeInit(state);
|
|
if (state->nds) free(state->nds);
|
|
state->nds = NULL;
|
|
if (state->NDS_ARM7) free(state->NDS_ARM7);
|
|
state->NDS_ARM7 = NULL;
|
|
if (state->NDS_ARM9) free(state->NDS_ARM9);
|
|
state->NDS_ARM9 = NULL;
|
|
if (state->MMU) free(state->MMU);
|
|
state->MMU = NULL;
|
|
if (state->ARM9Mem) free(state->ARM9Mem);
|
|
state->ARM9Mem = NULL;
|
|
if (state->MainScreen) free(state->MainScreen);
|
|
state->MainScreen = NULL;
|
|
if (state->SubScreen) free(state->SubScreen);
|
|
state->SubScreen = NULL;
|
|
if (state->array_rom_coverage) bit_array_destroy(state->array_rom_coverage);
|
|
state->array_rom_coverage = NULL;
|
|
}
|
|
|
|
void state_setrom(struct NDS_state *state, u8 * rom, u32 rom_size, unsigned int enable_coverage_checking)
|
|
{
|
|
assert(!(rom_size & (rom_size - 1)));
|
|
NDS_SetROM(state, rom, rom_size - 1);
|
|
if (enable_coverage_checking)
|
|
state->array_rom_coverage = bit_array_create(rom_size / 4);
|
|
NDS_Reset(state);
|
|
state->execute = TRUE;
|
|
}
|
|
|
|
static void load_setstate(struct NDS_state *state, const u8 *ss, u32 ss_size);
|
|
|
|
void state_loadstate(struct NDS_state *state, const u8 *ss, u32 ss_size)
|
|
{
|
|
if (ss && ss_size)
|
|
{
|
|
armcp15_t *c9 = (armcp15_t *)state->NDS_ARM9->coproc[15];
|
|
int proc;
|
|
if (state->initial_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(state, 0, REG_TM0CNTL, 0x0000);
|
|
MMU_write16(state, 0, REG_TM0CNTH, 0x00C1);
|
|
MMU_write16(state, 1, REG_TM0CNTL, 0x0000);
|
|
MMU_write16(state, 1, REG_TM0CNTH, 0x00C1);
|
|
MMU_write16(state, 1, REG_TM1CNTL, 0xf7e7);
|
|
MMU_write16(state, 1, REG_TM1CNTH, 0x00C1);
|
|
|
|
/* set initial interrupt state */
|
|
|
|
state->MMU->reg_IME[0] = 0x00000001;
|
|
state->MMU->reg_IE[0] = 0x00042001;
|
|
state->MMU->reg_IME[1] = 0x00000001;
|
|
state->MMU->reg_IE[1] = 0x0104009d;
|
|
}
|
|
else if (state->initial_frames > 0)
|
|
{
|
|
/* execute boot code */
|
|
int i;
|
|
for (i=0; i<state->initial_frames; i++)
|
|
NDS_exec_frame(state, 0, 0);
|
|
i = 0;
|
|
}
|
|
|
|
/* load state */
|
|
|
|
load_setstate(state, ss, ss_size);
|
|
|
|
if (state->initial_frames == -1)
|
|
{
|
|
armcp15_moveARM2CP(c9, (state->NDS_ARM9->R13_irq & 0x0fff0000) | 0x0a, 0x09, 0x01, 0, 0);
|
|
}
|
|
|
|
/* restore timer state */
|
|
|
|
for (proc = 0; proc < 2; proc++)
|
|
{
|
|
MMU_write16(state, proc, REG_TM0CNTH, T1ReadWord(state->MMU->MMU_MEM[proc][0x40], REG_TM0CNTH & 0xFFF));
|
|
MMU_write16(state, proc, REG_TM1CNTH, T1ReadWord(state->MMU->MMU_MEM[proc][0x40], REG_TM1CNTH & 0xFFF));
|
|
MMU_write16(state, proc, REG_TM2CNTH, T1ReadWord(state->MMU->MMU_MEM[proc][0x40], REG_TM2CNTH & 0xFFF));
|
|
MMU_write16(state, proc, REG_TM3CNTH, T1ReadWord(state->MMU->MMU_MEM[proc][0x40], REG_TM3CNTH & 0xFFF));
|
|
}
|
|
}
|
|
else if (state->initial_frames > 0)
|
|
{
|
|
/* skip 1 sec */
|
|
int i;
|
|
for (i=0; i<state->initial_frames; i++)
|
|
NDS_exec_frame(state, 0, 0);
|
|
}
|
|
|
|
state->execute = TRUE;
|
|
}
|
|
|
|
void state_render(struct NDS_state *state, s16 * buffer, unsigned int sample_count)
|
|
{
|
|
s16 * ptr = buffer;
|
|
|
|
while (sample_count)
|
|
{
|
|
unsigned long remain_samples = state->sample_pointer;
|
|
if (remain_samples > 0)
|
|
{
|
|
if (remain_samples > sample_count)
|
|
{
|
|
memcpy(ptr, state->sample_buffer, sample_count * sizeof(s16) * 2);
|
|
memmove(state->sample_buffer, state->sample_buffer + sample_count * 2, ( remain_samples - sample_count ) * sizeof(s16) * 2 );
|
|
state->sample_pointer -= sample_count;
|
|
ptr += sample_count * 2;
|
|
remain_samples -= sample_count; /**/
|
|
sample_count = 0; /**/
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
memcpy(ptr, state->sample_buffer, remain_samples * sizeof(s16) * 2);
|
|
state->sample_pointer = 0;
|
|
ptr += remain_samples * 2;
|
|
sample_count -= remain_samples;
|
|
remain_samples = 0;
|
|
}
|
|
}
|
|
while (remain_samples == 0 && state->sample_pointer < 1024)
|
|
{
|
|
|
|
/*
|
|
#define HBASE_CYCLES (16756000*2)
|
|
#define HBASE_CYCLES (33512000*1)
|
|
#define HBASE_CYCLES (33509300.322234)
|
|
*/
|
|
#define HBASE_CYCLES (33509300.322234)
|
|
#define HLINE_CYCLES (6 * (99 + 256))
|
|
#define HSAMPLES ((u32)((44100.0 * HLINE_CYCLES) / HBASE_CYCLES))
|
|
#define VDIVISION 100
|
|
#define VLINES 263
|
|
#define VBASE_CYCLES (((double)HBASE_CYCLES) / VDIVISION)
|
|
#define VSAMPLES ((u32)((44100.0 * HLINE_CYCLES * VLINES) / HBASE_CYCLES))
|
|
|
|
int numsamples;
|
|
if (state->sync_type == 1)
|
|
{
|
|
/* vsync */
|
|
state->cycles += ((44100 / VDIVISION) * HLINE_CYCLES * VLINES);
|
|
if (state->cycles >= (u32)(VBASE_CYCLES * (VSAMPLES + 1)))
|
|
{
|
|
numsamples = (VSAMPLES + 1);
|
|
state->cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 1));
|
|
}
|
|
else
|
|
{
|
|
numsamples = (VSAMPLES + 0);
|
|
state->cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 0));
|
|
}
|
|
NDS_exec_frame(state, state->arm9_clockdown_level, state->arm7_clockdown_level);
|
|
}
|
|
else
|
|
{
|
|
/* hsync */
|
|
state->cycles += (44100 * HLINE_CYCLES);
|
|
if (state->cycles >= (u32)(HBASE_CYCLES * (HSAMPLES + 1)))
|
|
{
|
|
numsamples = (HSAMPLES + 1);
|
|
state->cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 1));
|
|
}
|
|
else
|
|
{
|
|
numsamples = (HSAMPLES + 0);
|
|
state->cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 0));
|
|
}
|
|
NDS_exec_hframe(state, state->arm9_clockdown_level, state->arm7_clockdown_level);
|
|
}
|
|
SPU_EmulateSamples(state, numsamples);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int SNDStateInit(NDS_state *state, int buffersize)
|
|
{
|
|
state->sample_buffer = (s16 *) malloc(buffersize * sizeof(s16) * 2);
|
|
state->sample_pointer = 0;
|
|
state->sample_size = buffersize;
|
|
|
|
return state->sample_buffer == NULL ? -1 : 0;
|
|
}
|
|
|
|
static void SNDStateDeInit(NDS_state *state)
|
|
{
|
|
if ( state->sample_buffer ) free( state->sample_buffer );
|
|
state->sample_buffer = NULL;
|
|
}
|
|
|
|
static void SNDStateUpdateAudio(NDS_state *state, s16 *buffer, u32 num_samples)
|
|
{
|
|
memcpy( state->sample_buffer + state->sample_pointer * 2, buffer, num_samples * sizeof(s16) * 2);
|
|
state->sample_pointer += num_samples;
|
|
}
|
|
|
|
static u32 SNDStateGetAudioSpace(NDS_state *state)
|
|
{
|
|
return (u32)(state->sample_size - state->sample_pointer);
|
|
}
|
|
|
|
static void SNDStateMuteAudio(NDS_state *state)
|
|
{
|
|
(void)state;
|
|
}
|
|
|
|
static void SNDStateUnMuteAudio(NDS_state *state)
|
|
{
|
|
(void)state;
|
|
}
|
|
|
|
static void SNDStateSetVolume(NDS_state *state, int volume)
|
|
{
|
|
(void)state;
|
|
(void)volume;
|
|
}
|
|
|
|
SoundInterface_struct SNDState = {
|
|
SNDCORE_STATE,
|
|
"State Sound Interface",
|
|
SNDStateInit,
|
|
SNDStateDeInit,
|
|
SNDStateUpdateAudio,
|
|
SNDStateGetAudioSpace,
|
|
SNDStateMuteAudio,
|
|
SNDStateUnMuteAudio,
|
|
SNDStateSetVolume
|
|
};
|
|
|
|
SoundInterface_struct *SNDCoreList[2] = {
|
|
&SNDState,
|
|
NULL
|
|
};
|
|
|
|
static u16 getwordle(const unsigned char *pData)
|
|
{
|
|
return pData[0] | (((u16)pData[1]) << 8);
|
|
}
|
|
|
|
static u32 getdwordle(const unsigned char *pData)
|
|
{
|
|
return pData[0] | (((u32)pData[1]) << 8) | (((u32)pData[2]) << 16) | (((u32)pData[3]) << 24);
|
|
}
|
|
|
|
static void load_getsta(Status_Reg *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
|
{
|
|
unsigned s = l << 2;
|
|
unsigned i;
|
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
|
return;
|
|
for (i = 0; i < l; i++)
|
|
{
|
|
u32 st = getdwordle(*ss + (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;
|
|
}
|
|
*ss += s;
|
|
}
|
|
|
|
static void load_getbool(BOOL *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
|
{
|
|
unsigned s = l << 2;
|
|
unsigned i;
|
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
|
return;
|
|
for (i = 0; i < l; i++)
|
|
ptr[i] = (BOOL)getdwordle(*ss + (i << 2));
|
|
*ss += s;
|
|
}
|
|
|
|
#if defined(SIGNED_IS_NOT_2S_COMPLEMENT)
|
|
/* 2's complement */
|
|
#define u32tos32(v) ((s32)((((s64)(v)) ^ 0x80000000) - 0x80000000))
|
|
#else
|
|
/* 2's complement */
|
|
#define u32tos32(v) ((s32)v)
|
|
#endif
|
|
|
|
static void load_gets32(s32 *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
|
{
|
|
unsigned s = l << 2;
|
|
unsigned i;
|
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
|
return;
|
|
for (i = 0; i < l; i++)
|
|
ptr[i] = u32tos32(getdwordle(*ss + (i << 2)));
|
|
*ss += s;
|
|
}
|
|
|
|
static void load_getu32(u32 *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
|
{
|
|
unsigned s = l << 2;
|
|
unsigned i;
|
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
|
return;
|
|
for (i = 0; i < l; i++)
|
|
ptr[i] = getdwordle(*ss + (i << 2));
|
|
*ss += s;
|
|
}
|
|
|
|
static void load_getu16(u16 *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
|
{
|
|
unsigned s = l << 1;
|
|
unsigned i;
|
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
|
return;
|
|
for (i = 0; i < l; i++)
|
|
ptr[i] = getwordle(*ss + (i << 1));
|
|
*ss += s;
|
|
}
|
|
|
|
static void load_getu8(u8 *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
|
{
|
|
unsigned s = l;
|
|
unsigned i;
|
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
|
return;
|
|
for (i = 0; i < l; i++)
|
|
ptr[i] = (*ss)[i];
|
|
*ss += s;
|
|
}
|
|
|
|
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_acl(armcpu->state, armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
|
|
armcpu->instruct_adr = armcpu->next_instruction;
|
|
armcpu->next_instruction += 4;
|
|
armcpu->R[15] = armcpu->next_instruction + 4;
|
|
}
|
|
else
|
|
{
|
|
armcpu->instruction = MMU_read16_acl(armcpu->state, armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
|
|
armcpu->instruct_adr = armcpu->next_instruction;
|
|
armcpu->next_instruction += 2;
|
|
armcpu->R[15] = armcpu->next_instruction + 2;
|
|
}
|
|
}
|
|
|
|
static void load_setstate(struct NDS_state *state, const u8 *ss, u32 ss_size)
|
|
{
|
|
const u8 *sse = ss + ss_size;
|
|
|
|
if (!ss || !ss_size)
|
|
return;
|
|
|
|
/* Skip over "Desmume Save File" crap */
|
|
ss += 0x17;
|
|
|
|
/* Read ARM7 cpu registers */
|
|
load_getu32(&state->NDS_ARM7->proc_ID, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->instruction, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->instruct_adr, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->next_instruction, 1, &ss, sse);
|
|
load_getu32(state->NDS_ARM7->R, 16, &ss, sse);
|
|
load_getsta(&state->NDS_ARM7->CPSR, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM7->SPSR, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R13_usr, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R14_usr, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R13_svc, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R14_svc, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R13_abt, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R14_abt, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R13_und, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R14_und, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R13_irq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R14_irq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R8_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R9_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R10_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R11_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R12_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R13_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->R14_fiq, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM7->SPSR_svc, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM7->SPSR_abt, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM7->SPSR_und, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM7->SPSR_irq, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM7->SPSR_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM7->intVector, 1, &ss, sse);
|
|
load_getu8(&state->NDS_ARM7->LDTBit, 1, &ss, sse);
|
|
load_getbool(&state->NDS_ARM7->waitIRQ, 1, &ss, sse);
|
|
load_getbool(&state->NDS_ARM7->wIRQ, 1, &ss, sse);
|
|
load_getbool(&state->NDS_ARM7->wirq, 1, &ss, sse);
|
|
|
|
/* Read ARM9 cpu registers */
|
|
load_getu32(&state->NDS_ARM9->proc_ID, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->instruction, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->instruct_adr, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->next_instruction, 1, &ss, sse);
|
|
load_getu32(state->NDS_ARM9->R, 16, &ss, sse);
|
|
load_getsta(&state->NDS_ARM9->CPSR, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM9->SPSR, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R13_usr, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R14_usr, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R13_svc, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R14_svc, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R13_abt, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R14_abt, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R13_und, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R14_und, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R13_irq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R14_irq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R8_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R9_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R10_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R11_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R12_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R13_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->R14_fiq, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM9->SPSR_svc, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM9->SPSR_abt, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM9->SPSR_und, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM9->SPSR_irq, 1, &ss, sse);
|
|
load_getsta(&state->NDS_ARM9->SPSR_fiq, 1, &ss, sse);
|
|
load_getu32(&state->NDS_ARM9->intVector, 1, &ss, sse);
|
|
load_getu8(&state->NDS_ARM9->LDTBit, 1, &ss, sse);
|
|
load_getbool(&state->NDS_ARM9->waitIRQ, 1, &ss, sse);
|
|
load_getbool(&state->NDS_ARM9->wIRQ, 1, &ss, sse);
|
|
load_getbool(&state->NDS_ARM9->wirq, 1, &ss, sse);
|
|
|
|
/* Read in other internal variables that are important */
|
|
load_gets32(&state->nds->ARM9Cycle, 1, &ss, sse);
|
|
load_gets32(&state->nds->ARM7Cycle, 1, &ss, sse);
|
|
load_gets32(&state->nds->cycles, 1, &ss, sse);
|
|
load_gets32(state->nds->timerCycle[0], 4, &ss, sse);
|
|
load_gets32(state->nds->timerCycle[1], 4, &ss, sse);
|
|
load_getbool(state->nds->timerOver[0], 4, &ss, sse);
|
|
load_getbool(state->nds->timerOver[1], 4, &ss, sse);
|
|
load_gets32(&state->nds->nextHBlank, 1, &ss, sse);
|
|
load_getu32(&state->nds->VCount, 1, &ss, sse);
|
|
load_getu32(&state->nds->old, 1, &ss, sse);
|
|
load_gets32(&state->nds->diff, 1, &ss, sse);
|
|
load_getbool(&state->nds->lignerendu, 1, &ss, sse);
|
|
load_getu16(&state->nds->touchX, 1, &ss, sse);
|
|
load_getu16(&state->nds->touchY, 1, &ss, sse);
|
|
|
|
/* Read in memory/registers specific to the ARM9 */
|
|
load_getu8 (state->ARM9Mem->ARM9_ITCM, 0x8000, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->ARM9_DTCM, 0x4000, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->ARM9_WRAM, 0x1000000, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->MAIN_MEM, 0x400000, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->ARM9_REG, 0x10000, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->ARM9_VMEM, 0x800, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->ARM9_OAM, 0x800, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->ARM9_ABG, 0x80000, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->ARM9_BBG, 0x20000, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->ARM9_AOBJ, 0x40000, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->ARM9_BOBJ, 0x20000, &ss, sse);
|
|
load_getu8 (state->ARM9Mem->ARM9_LCD, 0xA4000, &ss, sse);
|
|
|
|
/* Read in memory/registers specific to the ARM7 */
|
|
load_getu8 (state->MMU->ARM7_ERAM, 0x10000, &ss, sse);
|
|
load_getu8 (state->MMU->ARM7_REG, 0x10000, &ss, sse);
|
|
load_getu8 (state->MMU->ARM7_WIRAM, 0x10000, &ss, sse);
|
|
|
|
/* Read in shared memory */
|
|
load_getu8 (state->MMU->SWIRAM, 0x8000, &ss, sse);
|
|
|
|
#ifdef GDB_STUB
|
|
#else
|
|
gdb_stub_fix(state->NDS_ARM9);
|
|
gdb_stub_fix(state->NDS_ARM7);
|
|
#endif
|
|
}
|