cog/Frameworks/vio2sf/vio2sf/src/vio2sf/desmume/MMU.c

3507 lines
104 KiB
C
Executable File

/* Copyright (C) 2006 yopyop
yopyop156@ifrance.com
yopyop156.ifrance.com
Copyright (C) 2007 shash
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//#define RENDER3D
#include <stdlib.h>
#include <math.h>
#include <string.h>
//#include "gl_vertex.h"
#include "spu_exports.h"
#include "state.h"
#include "MMU.h"
#include "debug.h"
#include "NDSSystem.h"
//#include "cflash.h"
#define cflash_read(s,a) 0
#define cflash_write(s,a,d)
#include "cp15.h"
//#include "wifi.h"
#include "registers.h"
#include "isqrt.h"
#include "barray.h"
#if VIO2SF_GPU_ENABLE
#include "render3D.h"
#else
#define GPU_setVideoProp(p1, p2)
#define GPU_setBGProp(p1, p2, p3)
#define GPU_setBLDCNT(p1, p2)
#define GPU_setBLDALPHA(p1, p2)
#define GPU_setBLDY(p1, p2)
#define GPU_setMOSAIC(p1, p2)
#define GPU_remove(p1,p2)
#define GPU_addBack(p1,p2)
#define GPU_ChangeGraphicsCore(p1) 0
#define GPU_set_DISPCAPCNT(p1, p2)
#define GPU_ligne(p1, p2)
#define GPU_setMasterBrightness(p1, p2)
#define GPU_setWIN0_H(p1, p2)
#define GPU_setWIN0_H0(p1, p2)
#define GPU_setWIN0_H1(p1, p2)
#define GPU_setWIN0_V(p1, p2)
#define GPU_setWIN0_V0(p1, p2)
#define GPU_setWIN0_V1(p1, p2)
#define GPU_setWIN1_H(p1, p2)
#define GPU_setWIN1_H0(p1, p2)
#define GPU_setWIN1_H1(p1, p2)
#define GPU_setWIN1_V(p1, p2)
#define GPU_setWIN1_V0(p1, p2)
#define GPU_setWIN1_V1(p1, p2)
#define GPU_setWININ(p1, p2)
#define GPU_setWININ0(p1, p2)
#define GPU_setWININ1(p1, p2)
#define GPU_setWINOUT16(p1, p2)
#define GPU_setWINOUT(p1, p2)
#define GPU_setWINOBJ(p1, p2)
#define GPU_setBLDCNT_LOW(p1, p2)
#define GPU_setBLDCNT_HIGH(p1, p2)
#define GPU_setBLDCNT(p1, p2)
#define GPU_setBLDALPHA(p1, p2)
#define GPU_setBLDALPHA_EVA(p1, p2)
#define GPU_setBLDALPHA_EVB(p1, p2)
#define GPU_setBLDY_EVY(p1, p2)
#endif
#define ROM_MASK 3
/*
*
*/
//#define PROFILE_MEMORY_ACCESS 1
#define EARLY_MEMORY_ACCESS 1
#define INTERNAL_DTCM_READ 1
#define INTERNAL_DTCM_WRITE 1
//#define LOG_CARD
//#define LOG_GPU
//#define LOG_DMA
//#define LOG_DMA2
//#define LOG_DIV
#define DUP2(x) x, x
#define DUP4(x) x, x, x, x
#define DUP8(x) x, x, x, x, x, x, x, x
#define DUP16(x) x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x
#if 0
#endif
const u32 MMU_ARM9_WAIT16[16]={
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1,
};
const u32 MMU_ARM9_WAIT32[16]={
1, 1, 1, 1, 1, 2, 2, 1, 8, 8, 5, 1, 1, 1, 1, 1,
};
const u32 MMU_ARM7_WAIT16[16]={
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1,
};
const u32 MMU_ARM7_WAIT32[16]={
1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 5, 1, 1, 1, 1, 1,
};
void MMU_Init(NDS_state *state) {
int i;
LOG("MMU init\n");
memset(state->MMU, 0, sizeof(MMU_struct));
state->MMU->CART_ROM = state->MMU->UNUSED_RAM;
for(i = 0x80; i<0xA0; ++i)
{
state->MMU_ARM9_MEM_MAP[i] = state->MMU->CART_ROM;
state->MMU_ARM7_MEM_MAP[i] = state->MMU->CART_ROM;
}
state->MMU->MMU_MEM[0] = state->MMU_ARM9_MEM_MAP;
state->MMU->MMU_MEM[1] = state->MMU_ARM7_MEM_MAP;
state->MMU->MMU_MASK[0]= state->MMU_ARM9_MEM_MASK;
state->MMU->MMU_MASK[1] = state->MMU_ARM7_MEM_MASK;
state->MMU->ITCMRegion = 0x00800000;
state->MMU->MMU_WAIT16[0] = MMU_ARM9_WAIT16;
state->MMU->MMU_WAIT16[1] = MMU_ARM7_WAIT16;
state->MMU->MMU_WAIT32[0] = MMU_ARM9_WAIT32;
state->MMU->MMU_WAIT32[1] = MMU_ARM7_WAIT32;
for(i = 0;i < 16;i++)
FIFOInit(state->MMU->fifos + i);
mc_init(&state->MMU->fw, MC_TYPE_FLASH); /* init fw device */
mc_alloc(&state->MMU->fw, NDS_FW_SIZE_V1);
state->MMU->fw.fp = NULL;
// Init Backup Memory device, this should really be done when the rom is loaded
mc_init(&state->MMU->bupmem, MC_TYPE_AUTODETECT);
mc_alloc(&state->MMU->bupmem, 1);
state->MMU->bupmem.fp = NULL;
}
void MMU_DeInit(NDS_state *state) {
LOG("MMU deinit\n");
// if (MMU->fw.fp)
// fclose(MMU->fw.fp);
mc_free(&state->MMU->fw);
// if (MMU->bupmem.fp)
// fclose(MMU->bupmem.fp);
mc_free(&state->MMU->bupmem);
}
//Card rom & ram
void MMU_clearMem(NDS_state *state)
{
int i;
memset(state->ARM9Mem->ARM9_ABG, 0, 0x080000);
memset(state->ARM9Mem->ARM9_AOBJ, 0, 0x040000);
memset(state->ARM9Mem->ARM9_BBG, 0, 0x020000);
memset(state->ARM9Mem->ARM9_BOBJ, 0, 0x020000);
memset(state->ARM9Mem->ARM9_DTCM, 0, 0x4000);
memset(state->ARM9Mem->ARM9_ITCM, 0, 0x8000);
memset(state->ARM9Mem->ARM9_LCD, 0, 0x0A4000);
memset(state->ARM9Mem->ARM9_OAM, 0, 0x0800);
memset(state->ARM9Mem->ARM9_REG, 0, 0x01000000);
memset(state->ARM9Mem->ARM9_VMEM, 0, 0x0800);
memset(state->ARM9Mem->ARM9_WRAM, 0, 0x01000000);
memset(state->ARM9Mem->MAIN_MEM, 0, 0x400000);
memset(state->ARM9Mem->blank_memory, 0, 0x020000);
memset(state->MMU->ARM7_ERAM, 0, 0x010000);
memset(state->MMU->ARM7_REG, 0, 0x010000);
for(i = 0;i < 16;i++)
FIFOInit(state->MMU->fifos + i);
state->MMU->DTCMRegion = 0;
state->MMU->ITCMRegion = 0x00800000;
memset(state->MMU->timer, 0, sizeof(u16) * 2 * 4);
memset(state->MMU->timerMODE, 0, sizeof(s32) * 2 * 4);
memset(state->MMU->timerON, 0, sizeof(u32) * 2 * 4);
memset(state->MMU->timerRUN, 0, sizeof(u32) * 2 * 4);
memset(state->MMU->timerReload, 0, sizeof(u16) * 2 * 4);
memset(state->MMU->reg_IME, 0, sizeof(u32) * 2);
memset(state->MMU->reg_IE, 0, sizeof(u32) * 2);
memset(state->MMU->reg_IF, 0, sizeof(u32) * 2);
memset(state->MMU->DMAStartTime, 0, sizeof(u32) * 2 * 4);
memset(state->MMU->DMACycle, 0, sizeof(s32) * 2 * 4);
memset(state->MMU->DMACrt, 0, sizeof(u32) * 2 * 4);
memset(state->MMU->DMAing, 0, sizeof(BOOL) * 2 * 4);
memset(state->MMU->dscard, 0, sizeof(nds_dscard) * 2);
state->MainScreen->offset = 192;
state->SubScreen->offset = 0;
/* setup the texture slot pointers */
#if 0
state->ARM9Mem->textureSlotAddr[0] = state->ARM9Mem->blank_memory;
state->ARM9Mem->textureSlotAddr[1] = state->ARM9Mem->blank_memory;
state->ARM9Mem->textureSlotAddr[2] = state->ARM9Mem->blank_memory;
state->ARM9Mem->textureSlotAddr[3] = state->ARM9Mem->blank_memory;
#else
state->ARM9Mem->textureSlotAddr[0] = &state->ARM9Mem->ARM9_LCD[0x20000 * 0];
state->ARM9Mem->textureSlotAddr[1] = &state->ARM9Mem->ARM9_LCD[0x20000 * 1];
state->ARM9Mem->textureSlotAddr[2] = &state->ARM9Mem->ARM9_LCD[0x20000 * 2];
state->ARM9Mem->textureSlotAddr[3] = &state->ARM9Mem->ARM9_LCD[0x20000 * 3];
#endif
}
/* the VRAM blocks keep their content even when not blended in */
/* to ensure that we write the content back to the LCD ram */
/* FIXME: VRAM Bank E,F,G,H,I missing */
void MMU_VRAMWriteBackToLCD(NDS_state *state, u8 block)
{
#if 0
u8 *destination;
u8 *source;
u32 size ;
u8 VRAMBankCnt;
#endif
#if 1
return ;
#endif
#if 0
destination = 0 ;
source = 0;
VRAMBankCnt = MMU_read8(state, ARMCPU_ARM9,REG_VRAMCNTA+block) ;
switch (block)
{
case 0: // Bank A
destination = state->ARM9Mem->ARM9_LCD ;
size = 0x20000 ;
break ;
case 1: // Bank B
destination = state->ARM9Mem->ARM9_LCD + 0x20000 ;
size = 0x20000 ;
break ;
case 2: // Bank C
destination = state->ARM9Mem->ARM9_LCD + 0x40000 ;
size = 0x20000 ;
break ;
case 3: // Bank D
destination = state->ARM9Mem->ARM9_LCD + 0x60000 ;
size = 0x20000 ;
break ;
case 4: // Bank E
destination = state->ARM9Mem->ARM9_LCD + 0x80000 ;
size = 0x10000 ;
break ;
case 5: // Bank F
destination = state->ARM9Mem->ARM9_LCD + 0x90000 ;
size = 0x4000 ;
break ;
case 6: // Bank G
destination = state->ARM9Mem->ARM9_LCD + 0x94000 ;
size = 0x4000 ;
break ;
case 8: // Bank H
destination = state->ARM9Mem->ARM9_LCD + 0x98000 ;
size = 0x8000 ;
break ;
case 9: // Bank I
destination = state->ARM9Mem->ARM9_LCD + 0xA0000 ;
size = 0x4000 ;
break ;
default:
return ;
}
switch (VRAMBankCnt & 7) {
case 0:
/* vram is allready stored at LCD, we dont need to write it back */
state->MMU->vScreen = 1;
break ;
case 1:
switch(block){
case 0:
case 1:
case 2:
case 3:
/* banks are in use for BG at ABG + ofs * 0x20000 */
source = state->ARM9Mem->ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ;
break ;
case 4:
/* bank E is in use at ABG */
source = state->ARM9Mem->ARM9_ABG ;
break;
case 5:
case 6:
/* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/
source = state->ARM9Mem->ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ;
break;
case 8:
/* bank H is in use at BBG */
source = state->ARM9Mem->ARM9_BBG ;
break ;
case 9:
/* bank I is in use at BBG */
source = state->ARM9Mem->ARM9_BBG + 0x8000 ;
break;
default: return ;
}
break ;
case 2:
if (block < 2)
{
/* banks A,B are in use for OBJ at AOBJ + ofs * 0x20000 */
source = state->ARM9Mem->ARM9_AOBJ + ((VRAMBankCnt >> 3) & 1) * 0x20000 ;
} else return ;
break ;
case 4:
switch(block){
case 2:
/* bank C is in use at BBG */
source = state->ARM9Mem->ARM9_BBG ;
break ;
case 3:
/* bank D is in use at BOBJ */
source = state->ARM9Mem->ARM9_BOBJ ;
break ;
default: return ;
}
break ;
default:
return ;
}
if (!destination) return ;
if (!source) return ;
memcpy(destination,source,size) ;
#endif
}
void MMU_VRAMReloadFromLCD(NDS_state *state, u8 block,u8 VRAMBankCnt)
{
#if 0
u8 *destination;
u8 *source;
u32 size;
#endif
#if 1
return ;
#endif
#if 0
destination = 0;
source = 0;
size = 0;
switch (block)
{
case 0: // Bank A
source = state->ARM9Mem->ARM9_LCD ;
size = 0x20000 ;
break ;
case 1: // Bank B
source = state->ARM9Mem->ARM9_LCD + 0x20000 ;
size = 0x20000 ;
break ;
case 2: // Bank C
source = state->ARM9Mem->ARM9_LCD + 0x40000 ;
size = 0x20000 ;
break ;
case 3: // Bank D
source = state->ARM9Mem->ARM9_LCD + 0x60000 ;
size = 0x20000 ;
break ;
case 4: // Bank E
source = state->ARM9Mem->ARM9_LCD + 0x80000 ;
size = 0x10000 ;
break ;
case 5: // Bank F
source = state->ARM9Mem->ARM9_LCD + 0x90000 ;
size = 0x4000 ;
break ;
case 6: // Bank G
source = state->ARM9Mem->ARM9_LCD + 0x94000 ;
size = 0x4000 ;
break ;
case 8: // Bank H
source = state->ARM9Mem->ARM9_LCD + 0x98000 ;
size = 0x8000 ;
break ;
case 9: // Bank I
source = state->ARM9Mem->ARM9_LCD + 0xA0000 ;
size = 0x4000 ;
break ;
default:
return ;
}
switch (VRAMBankCnt & 7) {
case 0:
/* vram is allready stored at LCD, we dont need to write it back */
state->MMU->vScreen = 1;
break ;
case 1:
if (block < 4)
{
/* banks are in use for BG at ABG + ofs * 0x20000 */
destination = state->ARM9Mem->ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ;
} else return ;
break ;
case 2:
switch(block){
case 0:
case 1:
case 2:
case 3:
/* banks are in use for BG at ABG + ofs * 0x20000 */
destination = state->ARM9Mem->ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ;
break ;
case 4:
/* bank E is in use at ABG */
destination = state->ARM9Mem->ARM9_ABG ;
break;
case 5:
case 6:
/* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/
destination = state->ARM9Mem->ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ;
break;
case 8:
/* bank H is in use at BBG */
destination = state->ARM9Mem->ARM9_BBG ;
break ;
case 9:
/* bank I is in use at BBG */
destination = state->ARM9Mem->ARM9_BBG + 0x8000 ;
break;
default: return ;
}
break ;
case 4:
switch(block){
case 2:
/* bank C is in use at BBG */
destination = state->ARM9Mem->ARM9_BBG ;
break ;
case 3:
/* bank D is in use at BOBJ */
destination = state->ARM9Mem->ARM9_BOBJ ;
break ;
default: return ;
}
break ;
default:
return ;
}
if (!destination) return ;
if (!source) return ;
memcpy(destination,source,size) ;
#endif
}
void MMU_setRom(NDS_state *state, u8 * rom, u32 mask)
{
unsigned int i;
state->MMU->CART_ROM = rom;
for(i = 0x80; i<0xA0; ++i)
{
state->MMU_ARM9_MEM_MAP[i] = rom;
state->MMU_ARM7_MEM_MAP[i] = rom;
state->MMU_ARM9_MEM_MASK[i] = mask;
state->MMU_ARM7_MEM_MASK[i] = mask;
}
state->rom_mask = mask;
}
void MMU_unsetRom(NDS_state *state)
{
unsigned int i;
state->MMU->CART_ROM=state->MMU->UNUSED_RAM;
for(i = 0x80; i<0xA0; ++i)
{
state->MMU_ARM9_MEM_MAP[i] = state->MMU->UNUSED_RAM;
state->MMU_ARM7_MEM_MAP[i] = state->MMU->UNUSED_RAM;
state->MMU_ARM9_MEM_MASK[i] = ROM_MASK;
state->MMU_ARM7_MEM_MASK[i] = ROM_MASK;
}
state->rom_mask = ROM_MASK;
}
u8 FASTCALL MMU_read8(NDS_state *state, u32 proc, u32 adr)
{
#ifdef INTERNAL_DTCM_READ
if((proc==ARMCPU_ARM9)&((adr&(~0x3FFF))==state->MMU->DTCMRegion))
{
return state->ARM9Mem->ARM9_DTCM[adr&0x3FFF];
}
#endif
// CFlash reading, Mic
if ((adr>=0x9000000)&&(adr<0x9900000))
return (unsigned char)cflash_read(state, adr);
#ifdef EXPERIMENTAL_WIFI
/* wifi mac access */
if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
{
if (adr & 1)
return (WIFI_read16(&state->wifiMac,adr) >> 8) & 0xFF;
else
return WIFI_read16(&state->wifiMac,adr) & 0xFF;
}
#endif
if (state->array_rom_coverage)
{
if (state->MMU->MMU_MEM[proc][(adr>>20)&0xFF] == state->MMU->CART_ROM)
{
bit_array_set(state->array_rom_coverage, (adr & state->MMU->MMU_MASK[proc][(adr>>20)&0xFF]) / 4);
}
}
return state->MMU->MMU_MEM[proc][(adr>>20)&0xFF][adr&state->MMU->MMU_MASK[proc][(adr>>20)&0xFF]];
}
u16 FASTCALL MMU_read16(NDS_state *state, u32 proc, u32 adr)
{
#ifdef INTERNAL_DTCM_READ
if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == state->MMU->DTCMRegion))
{
/* Returns data from DTCM (ARM9 only) */
return T1ReadWord(state->ARM9Mem->ARM9_DTCM, adr & 0x3FFF);
}
#endif
// CFlash reading, Mic
if ((adr>=0x08800000)&&(adr<0x09900000))
return (unsigned short)cflash_read(state, adr);
#ifdef EXPERIMENTAL_WIFI
/* wifi mac access */
if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
return WIFI_read16(&state->wifiMac,adr) ;
#endif
adr &= 0x0FFFFFFF;
if(adr&0x04000000)
{
/* Adress is an IO register */
switch(adr)
{
#if VIO2SF_GPU_ENABLE
case 0x04000604:
return (state->gpu3D->NDS_3D_GetNumPolys(state->gpu3D)&2047);
case 0x04000606:
return (state->gpu3D->NDS_3D_GetNumVertex(state->gpu3D)&8191);
#endif
case REG_IPCFIFORECV : /* TODO (clear): ??? */
state->execute = FALSE;
return 1;
case REG_IME :
return (u16)state->MMU->reg_IME[proc];
case REG_IE :
return (u16)state->MMU->reg_IE[proc];
case REG_IE + 2 :
return (u16)(state->MMU->reg_IE[proc]>>16);
case REG_IF :
return (u16)state->MMU->reg_IF[proc];
case REG_IF + 2 :
return (u16)(state->MMU->reg_IF[proc]>>16);
case REG_TM0CNTL :
case REG_TM1CNTL :
case REG_TM2CNTL :
case REG_TM3CNTL :
return state->MMU->timer[proc][(adr&0xF)>>2];
case 0x04000630 :
LOG("vect res\r\n"); /* TODO (clear): ??? */
//execute = FALSE;
return 0;
case REG_POSTFLG :
return 1;
default :
break;
}
}
if (state->array_rom_coverage)
{
if (state->MMU->MMU_MEM[proc][(adr>>20)&0xFF] == state->MMU->CART_ROM)
{
bit_array_set(state->array_rom_coverage, (adr & state->MMU->MMU_MASK[proc][(adr>>20)&0xFF]) / 4);
}
}
/* Returns data from memory */
return T1ReadWord(state->MMU->MMU_MEM[proc][(adr >> 20) & 0xFF], adr & state->MMU->MMU_MASK[proc][(adr >> 20) & 0xFF]);
}
u32 FASTCALL MMU_read32(NDS_state *state, u32 proc, u32 adr)
{
#ifdef INTERNAL_DTCM_READ
if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == state->MMU->DTCMRegion))
{
/* Returns data from DTCM (ARM9 only) */
return T1ReadLong(state->ARM9Mem->ARM9_DTCM, adr & 0x3FFF);
}
#endif
// CFlash reading, Mic
if ((adr>=0x9000000)&&(adr<0x9900000))
return (unsigned long)cflash_read(state, adr);
adr &= 0x0FFFFFFF;
if((adr >> 24) == 4)
{
/* Adress is an IO register */
switch(adr)
{
// This is hacked due to the only current 3D core
case 0x04000600:
{
u32 fifonum = IPCFIFO+proc;
u32 gxstat = (state->MMU->fifos[fifonum].empty<<26) |
(1<<25) |
(state->MMU->fifos[fifonum].full<<24) |
/*((NDS_nbpush[0]&1)<<13) | ((NDS_nbpush[2]&0x1F)<<8) |*/
2;
LOG ("GXSTAT: 0x%X", gxstat);
return gxstat;
}
case 0x04000640:
case 0x04000644:
case 0x04000648:
case 0x0400064C:
case 0x04000650:
case 0x04000654:
case 0x04000658:
case 0x0400065C:
case 0x04000660:
case 0x04000664:
case 0x04000668:
case 0x0400066C:
case 0x04000670:
case 0x04000674:
case 0x04000678:
case 0x0400067C:
{
//LOG("4000640h..67Fh - CLIPMTX_RESULT - Read Current Clip Coordinates Matrix (R)");
#if VIO2SF_GPU_ENABLE
return state->gpu3D->NDS_3D_GetClipMatrix (state->gpu3D, (adr-0x04000640)/4);
#else
return 0;
#endif
}
case 0x04000680:
case 0x04000684:
case 0x04000688:
case 0x0400068C:
case 0x04000690:
case 0x04000694:
case 0x04000698:
case 0x0400069C:
case 0x040006A0:
{
#if VIO2SF_GPU_ENABLE
//LOG("4000680h..6A3h - VECMTX_RESULT - Read Current Directional Vector Matrix (R)");
return state->gpu3D->NDS_3D_GetDirectionalMatrix (state->gpu3D, (adr-0x04000680)/4);
#else
return 0;
#endif
}
case 0x4000604:
{
#if VIO2SF_GPU_ENABLE
return (state->gpu3D->NDS_3D_GetNumPolys(state->gpu3D)&2047) & ((state->gpu3D->NDS_3D_GetNumVertex(state->gpu3D)&8191) << 16);
//LOG ("read32 - RAM_COUNT -> 0x%X", ((u32 *)(MMU->MMU_MEM[proc][(adr>>20)&0xFF]))[(adr&MMU->MMU_MASK[proc][(adr>>20)&0xFF])>>2]);
#else
return 0;
#endif
}
case REG_IME :
return state->MMU->reg_IME[proc];
case REG_IE :
return state->MMU->reg_IE[proc];
case REG_IF :
return state->MMU->reg_IF[proc];
case REG_IPCFIFORECV :
{
u16 IPCFIFO_CNT = T1ReadWord(state->MMU->MMU_MEM[proc][0x40], 0x184);
if(IPCFIFO_CNT&0x8000)
{
//execute = FALSE;
u32 fifonum = IPCFIFO+proc;
u32 val = FIFOValue(state->MMU->fifos + fifonum);
u32 remote = (proc+1) & 1;
u16 IPCFIFO_CNT_remote = T1ReadWord(state->MMU->MMU_MEM[remote][0x40], 0x184);
IPCFIFO_CNT |= (state->MMU->fifos[fifonum].empty<<8) | (state->MMU->fifos[fifonum].full<<9) | (state->MMU->fifos[fifonum].error<<14);
IPCFIFO_CNT_remote |= (state->MMU->fifos[fifonum].empty) | (state->MMU->fifos[fifonum].full<<1);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT);
T1WriteWord(state->MMU->MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote);
if ((state->MMU->fifos[fifonum].empty) && (IPCFIFO_CNT & BIT(2)))
NDS_makeInt(state, remote,17) ; /* remote: SEND FIFO EMPTY */
return val;
}
}
return 0;
case REG_TM0CNTL :
case REG_TM1CNTL :
case REG_TM2CNTL :
case REG_TM3CNTL :
{
u32 val = T1ReadWord(state->MMU->MMU_MEM[proc][0x40], (adr + 2) & 0xFFF);
return state->MMU->timer[proc][(adr&0xF)>>2] | (val<<16);
}
/*
case 0x04000640 : // TODO (clear): again, ???
LOG("read proj\r\n");
return 0;
case 0x04000680 :
LOG("read roat\r\n");
return 0;
case 0x04000620 :
LOG("point res\r\n");
return 0;
*/
case REG_GCDATAIN:
{
u32 val;
if(!state->MMU->dscard[proc].adress) return 0;
if (state->array_rom_coverage)
bit_array_set(state->array_rom_coverage, state->MMU->dscard[proc].adress / 4);
val = T1ReadLong(state->MMU->CART_ROM, state->MMU->dscard[proc].adress);
state->MMU->dscard[proc].adress += 4; /* increment adress */
state->MMU->dscard[proc].transfer_count--; /* update transfer counter */
if(state->MMU->dscard[proc].transfer_count) /* if transfer is not ended */
{
return val; /* return data */
}
else /* transfer is done */
{
T1WriteLong(state->MMU->MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, T1ReadLong(state->MMU->MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff) & ~(0x00800000 | 0x80000000));
/* = 0x7f7fffff */
/* if needed, throw irq for the end of transfer */
if(T1ReadWord(state->MMU->MMU_MEM[proc][(REG_AUXSPICNT >> 20) & 0xff], REG_AUXSPICNT & 0xfff) & 0x4000)
{
if(proc == ARMCPU_ARM7) NDS_makeARM7Int(state, 19);
else NDS_makeARM9Int(state, 19);
}
return val;
}
}
default :
break;
}
}
if (state->array_rom_coverage)
{
if (state->MMU->MMU_MEM[proc][(adr>>20)&0xFF] == state->MMU->CART_ROM)
{
bit_array_set(state->array_rom_coverage, (adr & state->MMU->MMU_MASK[proc][(adr>>20)&0xFF]) / 4);
}
}
/* Returns data from memory */
return T1ReadLong(state->MMU->MMU_MEM[proc][(adr >> 20) & 0xFF], adr & state->MMU->MMU_MASK[proc][(adr >> 20) & 0xFF]);
}
void FASTCALL MMU_write8(NDS_state *state, u32 proc, u32 adr, u8 val)
{
#ifdef INTERNAL_DTCM_WRITE
if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == state->MMU->DTCMRegion))
{
/* Writes data in DTCM (ARM9 only) */
state->ARM9Mem->ARM9_DTCM[adr&0x3FFF] = val;
return ;
}
#endif
// CFlash writing, Mic
if ((adr>=0x9000000)&&(adr<0x9900000)) {
cflash_write(state,adr,val);
return;
}
adr &= 0x0FFFFFFF;
// This is bad, remove it
if(proc == ARMCPU_ARM7)
{
if ((adr>=0x04000400)&&(adr<0x0400051D))
{
SPU_WriteByte(state, adr, val);
return;
}
}
if ((adr & 0xFF800000) == 0x04800000)
{
/* is wifi hardware, dont intermix with regular hardware registers */
/* FIXME handle 8 bit writes */
return ;
}
switch(adr)
{
case REG_DISPA_WIN0H:
if(proc == ARMCPU_ARM9) GPU_setWIN0_H1 (state->MainScreen->gpu, val);
break ;
case REG_DISPA_WIN0H+1:
if(proc == ARMCPU_ARM9) GPU_setWIN0_H0 (state->MainScreen->gpu, val);
break ;
case REG_DISPA_WIN1H:
if(proc == ARMCPU_ARM9) GPU_setWIN1_H1 (state->MainScreen->gpu,val);
break ;
case REG_DISPA_WIN1H+1:
if(proc == ARMCPU_ARM9) GPU_setWIN1_H0 (state->MainScreen->gpu,val);
break ;
case REG_DISPB_WIN0H:
if(proc == ARMCPU_ARM9) GPU_setWIN0_H1(state->SubScreen->gpu,val);
break ;
case REG_DISPB_WIN0H+1:
if(proc == ARMCPU_ARM9) GPU_setWIN0_H0(state->SubScreen->gpu,val);
break ;
case REG_DISPB_WIN1H:
if(proc == ARMCPU_ARM9) GPU_setWIN1_H1(state->SubScreen->gpu,val);
break ;
case REG_DISPB_WIN1H+1:
if(proc == ARMCPU_ARM9) GPU_setWIN1_H0(state->SubScreen->gpu,val);
break ;
case REG_DISPA_WIN0V:
if(proc == ARMCPU_ARM9) GPU_setWIN0_V1(state->MainScreen->gpu,val) ;
break ;
case REG_DISPA_WIN0V+1:
if(proc == ARMCPU_ARM9) GPU_setWIN0_V0(state->MainScreen->gpu,val) ;
break ;
case REG_DISPA_WIN1V:
if(proc == ARMCPU_ARM9) GPU_setWIN1_V1(state->MainScreen->gpu,val) ;
break ;
case REG_DISPA_WIN1V+1:
if(proc == ARMCPU_ARM9) GPU_setWIN1_V0(state->MainScreen->gpu,val) ;
break ;
case REG_DISPB_WIN0V:
if(proc == ARMCPU_ARM9) GPU_setWIN0_V1(state->SubScreen->gpu,val) ;
break ;
case REG_DISPB_WIN0V+1:
if(proc == ARMCPU_ARM9) GPU_setWIN0_V0(state->SubScreen->gpu,val) ;
break ;
case REG_DISPB_WIN1V:
if(proc == ARMCPU_ARM9) GPU_setWIN1_V1(state->SubScreen->gpu,val) ;
break ;
case REG_DISPB_WIN1V+1:
if(proc == ARMCPU_ARM9) GPU_setWIN1_V0(state->SubScreen->gpu,val) ;
break ;
case REG_DISPA_WININ:
if(proc == ARMCPU_ARM9) GPU_setWININ0(state->MainScreen->gpu,val) ;
break ;
case REG_DISPA_WININ+1:
if(proc == ARMCPU_ARM9) GPU_setWININ1(state->MainScreen->gpu,val) ;
break ;
case REG_DISPA_WINOUT:
if(proc == ARMCPU_ARM9) GPU_setWINOUT(state->MainScreen->gpu,val) ;
break ;
case REG_DISPA_WINOUT+1:
if(proc == ARMCPU_ARM9) GPU_setWINOBJ(state->MainScreen->gpu,val);
break ;
case REG_DISPB_WININ:
if(proc == ARMCPU_ARM9) GPU_setWININ0(state->SubScreen->gpu,val) ;
break ;
case REG_DISPB_WININ+1:
if(proc == ARMCPU_ARM9) GPU_setWININ1(state->SubScreen->gpu,val) ;
break ;
case REG_DISPB_WINOUT:
if(proc == ARMCPU_ARM9) GPU_setWINOUT(state->SubScreen->gpu,val) ;
break ;
case REG_DISPB_WINOUT+1:
if(proc == ARMCPU_ARM9) GPU_setWINOBJ(state->SubScreen->gpu,val) ;
break ;
case REG_DISPA_BLDCNT:
if(proc == ARMCPU_ARM9) GPU_setBLDCNT_HIGH(state->MainScreen->gpu,val);
break;
case REG_DISPA_BLDCNT+1:
if(proc == ARMCPU_ARM9) GPU_setBLDCNT_LOW (state->MainScreen->gpu,val);
break;
case REG_DISPB_BLDCNT:
if(proc == ARMCPU_ARM9) GPU_setBLDCNT_HIGH (state->SubScreen->gpu,val);
break;
case REG_DISPB_BLDCNT+1:
if(proc == ARMCPU_ARM9) GPU_setBLDCNT_LOW (state->SubScreen->gpu,val);
break;
case REG_DISPA_BLDALPHA:
if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVB(state->MainScreen->gpu,val) ;
break;
case REG_DISPA_BLDALPHA+1:
if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVA(state->MainScreen->gpu,val) ;
break;
case REG_DISPB_BLDALPHA:
if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVB(state->SubScreen->gpu,val) ;
break;
case REG_DISPB_BLDALPHA+1:
if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVA(state->SubScreen->gpu,val);
break;
case REG_DISPA_BLDY:
if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(state->MainScreen->gpu,val) ;
break ;
case REG_DISPB_BLDY:
if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(state->SubScreen->gpu,val) ;
break;
/* TODO: EEEK ! Controls for VRAMs A, B, C, D are missing ! */
/* TODO: Not all mappings of VRAMs are handled... (especially BG and OBJ modes) */
case REG_VRAMCNTA:
case REG_VRAMCNTB:
case REG_VRAMCNTC:
case REG_VRAMCNTD:
if(proc == ARMCPU_ARM9)
{
MMU_VRAMWriteBackToLCD(state, 0) ;
MMU_VRAMWriteBackToLCD(state, 1) ;
MMU_VRAMWriteBackToLCD(state, 2) ;
MMU_VRAMWriteBackToLCD(state, 3) ;
switch(val & 0x1F)
{
case 1 :
state->MMU->vram_mode[adr-REG_VRAMCNTA] = 0; // BG-VRAM
//MMU->vram_offset[0] = ARM9Mem->ARM9_ABG+(0x20000*0); // BG-VRAM
break;
case 1 | (1 << 3) :
state->MMU->vram_mode[adr-REG_VRAMCNTA] = 1; // BG-VRAM
//MMU->vram_offset[0] = ARM9Mem->ARM9_ABG+(0x20000*1); // BG-VRAM
break;
case 1 | (2 << 3) :
state->MMU->vram_mode[adr-REG_VRAMCNTA] = 2; // BG-VRAM
//MMU->vram_offset[0] = ARM9Mem->ARM9_ABG+(0x20000*2); // BG-VRAM
break;
case 1 | (3 << 3) :
state->MMU->vram_mode[adr-REG_VRAMCNTA] = 3; // BG-VRAM
//MMU->vram_offset[0] = ARM9Mem->ARM9_ABG+(0x20000*3); // BG-VRAM
break;
case 0: /* mapped to lcd */
state->MMU->vram_mode[adr-REG_VRAMCNTA] = 4 | (adr-REG_VRAMCNTA) ;
break ;
}
/*
* FIXME: simply texture slot handling
* This is a first stab and is not correct. It does
* not handle a VRAM texture slot becoming
* unconfigured.
* Revisit all of VRAM control handling for future
* release?
*/
if ( val & 0x80) {
if ( (val & 0x7) == 3) {
int slot_index = (val >> 3) & 0x3;
state->ARM9Mem->textureSlotAddr[slot_index] =
&state->ARM9Mem->ARM9_LCD[0x20000 * (adr - REG_VRAMCNTA)];
}
}
MMU_VRAMReloadFromLCD(state, adr-REG_VRAMCNTA,val) ;
}
break;
case REG_VRAMCNTE :
if(proc == ARMCPU_ARM9)
{
MMU_VRAMWriteBackToLCD(state, (u8)REG_VRAMCNTE) ;
if((val & 7) == 5)
{
state->ARM9Mem->ExtPal[0][0] = state->ARM9Mem->ARM9_LCD + 0x80000;
state->ARM9Mem->ExtPal[0][1] = state->ARM9Mem->ARM9_LCD + 0x82000;
state->ARM9Mem->ExtPal[0][2] = state->ARM9Mem->ARM9_LCD + 0x84000;
state->ARM9Mem->ExtPal[0][3] = state->ARM9Mem->ARM9_LCD + 0x86000;
}
else if((val & 7) == 3)
{
state->ARM9Mem->texPalSlot[0] = state->ARM9Mem->ARM9_LCD + 0x80000;
state->ARM9Mem->texPalSlot[1] = state->ARM9Mem->ARM9_LCD + 0x82000;
state->ARM9Mem->texPalSlot[2] = state->ARM9Mem->ARM9_LCD + 0x84000;
state->ARM9Mem->texPalSlot[3] = state->ARM9Mem->ARM9_LCD + 0x86000;
}
else if((val & 7) == 4)
{
state->ARM9Mem->ExtPal[0][0] = state->ARM9Mem->ARM9_LCD + 0x80000;
state->ARM9Mem->ExtPal[0][1] = state->ARM9Mem->ARM9_LCD + 0x82000;
state->ARM9Mem->ExtPal[0][2] = state->ARM9Mem->ARM9_LCD + 0x84000;
state->ARM9Mem->ExtPal[0][3] = state->ARM9Mem->ARM9_LCD + 0x86000;
}
MMU_VRAMReloadFromLCD(state,adr-REG_VRAMCNTE,val) ;
}
break;
case REG_VRAMCNTF :
if(proc == ARMCPU_ARM9)
{
switch(val & 0x1F)
{
case 4 :
state->ARM9Mem->ExtPal[0][0] = state->ARM9Mem->ARM9_LCD + 0x90000;
state->ARM9Mem->ExtPal[0][1] = state->ARM9Mem->ARM9_LCD + 0x92000;
break;
case 4 | (1 << 3) :
state->ARM9Mem->ExtPal[0][2] = state->ARM9Mem->ARM9_LCD + 0x90000;
state->ARM9Mem->ExtPal[0][3] = state->ARM9Mem->ARM9_LCD + 0x92000;
break;
case 3 :
state->ARM9Mem->texPalSlot[0] = state->ARM9Mem->ARM9_LCD + 0x90000;
break;
case 3 | (1 << 3) :
state->ARM9Mem->texPalSlot[1] = state->ARM9Mem->ARM9_LCD + 0x90000;
break;
case 3 | (2 << 3) :
state->ARM9Mem->texPalSlot[2] = state->ARM9Mem->ARM9_LCD + 0x90000;
break;
case 3 | (3 << 3) :
state->ARM9Mem->texPalSlot[3] = state->ARM9Mem->ARM9_LCD + 0x90000;
break;
case 5 :
case 5 | (1 << 3) :
case 5 | (2 << 3) :
case 5 | (3 << 3) :
state->ARM9Mem->ObjExtPal[0][0] = state->ARM9Mem->ARM9_LCD + 0x90000;
state->ARM9Mem->ObjExtPal[0][1] = state->ARM9Mem->ARM9_LCD + 0x92000;
break;
}
}
break;
case REG_VRAMCNTG :
if(proc == ARMCPU_ARM9)
{
switch(val & 0x1F)
{
case 4 :
state->ARM9Mem->ExtPal[0][0] = state->ARM9Mem->ARM9_LCD + 0x94000;
state->ARM9Mem->ExtPal[0][1] = state->ARM9Mem->ARM9_LCD + 0x96000;
break;
case 4 | (1 << 3) :
state->ARM9Mem->ExtPal[0][2] = state->ARM9Mem->ARM9_LCD + 0x94000;
state->ARM9Mem->ExtPal[0][3] = state->ARM9Mem->ARM9_LCD + 0x96000;
break;
case 3 :
state->ARM9Mem->texPalSlot[0] = state->ARM9Mem->ARM9_LCD + 0x94000;
break;
case 3 | (1 << 3) :
state->ARM9Mem->texPalSlot[1] = state->ARM9Mem->ARM9_LCD + 0x94000;
break;
case 3 | (2 << 3) :
state->ARM9Mem->texPalSlot[2] = state->ARM9Mem->ARM9_LCD + 0x94000;
break;
case 3 | (3 << 3) :
state->ARM9Mem->texPalSlot[3] = state->ARM9Mem->ARM9_LCD + 0x94000;
break;
case 5 :
case 5 | (1 << 3) :
case 5 | (2 << 3) :
case 5 | (3 << 3) :
state->ARM9Mem->ObjExtPal[0][0] = state->ARM9Mem->ARM9_LCD + 0x94000;
state->ARM9Mem->ObjExtPal[0][1] = state->ARM9Mem->ARM9_LCD + 0x96000;
break;
}
}
break;
case REG_VRAMCNTH :
if(proc == ARMCPU_ARM9)
{
MMU_VRAMWriteBackToLCD(state, (u8)REG_VRAMCNTH) ;
if((val & 7) == 2)
{
state->ARM9Mem->ExtPal[1][0] = state->ARM9Mem->ARM9_LCD + 0x98000;
state->ARM9Mem->ExtPal[1][1] = state->ARM9Mem->ARM9_LCD + 0x9A000;
state->ARM9Mem->ExtPal[1][2] = state->ARM9Mem->ARM9_LCD + 0x9C000;
state->ARM9Mem->ExtPal[1][3] = state->ARM9Mem->ARM9_LCD + 0x9E000;
}
MMU_VRAMReloadFromLCD(state,adr-REG_VRAMCNTH,val) ;
}
break;
case REG_VRAMCNTI :
if(proc == ARMCPU_ARM9)
{
MMU_VRAMWriteBackToLCD(state,(u8)REG_VRAMCNTI) ;
if((val & 7) == 3)
{
state->ARM9Mem->ObjExtPal[1][0] = state->ARM9Mem->ARM9_LCD + 0xA0000;
state->ARM9Mem->ObjExtPal[1][1] = state->ARM9Mem->ARM9_LCD + 0xA2000;
}
MMU_VRAMReloadFromLCD(state,adr-REG_VRAMCNTI,val) ;
}
break;
#ifdef LOG_CARD
case 0x040001A0 : /* TODO (clear): ??? */
case 0x040001A1 :
case 0x040001A2 :
case 0x040001A8 :
case 0x040001A9 :
case 0x040001AA :
case 0x040001AB :
case 0x040001AC :
case 0x040001AD :
case 0x040001AE :
case 0x040001AF :
LOG("%08X : %02X\r\n", adr, val);
#endif
default :
break;
}
state->MMU->MMU_MEM[proc][(adr>>20)&0xFF][adr&state->MMU->MMU_MASK[proc][(adr>>20)&0xFF]]=val;
}
void FASTCALL MMU_write16(NDS_state *state, u32 proc, u32 adr, u16 val)
{
#ifdef INTERNAL_DTCM_WRITE
if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == state->MMU->DTCMRegion))
{
/* Writes in DTCM (ARM9 only) */
T1WriteWord(state->ARM9Mem->ARM9_DTCM, adr & 0x3FFF, val);
return;
}
#endif
// CFlash writing, Mic
if ((adr>=0x08800000)&&(adr<0x09900000))
{
cflash_write(state,adr,val);
return;
}
#ifdef EXPERIMENTAL_WIFI
/* wifi mac access */
if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
{
WIFI_write16(&state->wifiMac,adr,val) ;
return ;
}
#else
if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
return ;
#endif
adr &= 0x0FFFFFFF;
// This is bad, remove it
if(proc == ARMCPU_ARM7)
{
if ((adr>=0x04000400)&&(adr<0x0400051D))
{
SPU_WriteWord(state, adr, val);
return;
}
}
if((adr >> 24) == 4)
{
/* Adress is an IO register */
switch(adr)
{
#if VIO2SF_GPU_ENABLE
case 0x0400035C:
{
((u16 *)(state->MMU->MMU_MEM[proc][0x40]))[0x35C>>1] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_FogOffset (state->gpu3D, val);
}
return;
}
case 0x04000340:
{
((u16 *)(state->MMU->MMU_MEM[proc][0x40]))[0x340>>1] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_AlphaFunc(state->gpu3D, val);
}
return;
}
case 0x04000060:
{
((u16 *)(state->MMU->MMU_MEM[proc][0x40]))[0x060>>1] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Control(state->gpu3D, val);
}
return;
}
case 0x04000354:
{
((u16 *)(state->MMU->MMU_MEM[proc][0x40]))[0x354>>1] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_ClearDepth(state->gpu3D, val);
}
return;
}
#endif
case REG_DISPA_BLDCNT:
if(proc == ARMCPU_ARM9) GPU_setBLDCNT(state->MainScreen->gpu,val) ;
break ;
case REG_DISPB_BLDCNT:
if(proc == ARMCPU_ARM9) GPU_setBLDCNT(state->SubScreen->gpu,val) ;
break ;
case REG_DISPA_BLDALPHA:
if(proc == ARMCPU_ARM9) GPU_setBLDALPHA(state->MainScreen->gpu,val) ;
break ;
case REG_DISPB_BLDALPHA:
if(proc == ARMCPU_ARM9) GPU_setBLDALPHA(state->SubScreen->gpu,val) ;
break ;
case REG_DISPA_BLDY:
if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(state->MainScreen->gpu,val) ;
break ;
case REG_DISPB_BLDY:
if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(state->SubScreen->gpu,val) ;
break;
case REG_DISPA_MASTERBRIGHT:
GPU_setMasterBrightness (state->MainScreen->gpu, val);
break;
/*
case REG_DISPA_MOSAIC:
if(proc == ARMCPU_ARM9) GPU_setMOSAIC(state->MainScreen->gpu,val) ;
break ;
case REG_DISPB_MOSAIC:
if(proc == ARMCPU_ARM9) GPU_setMOSAIC(state->SubScreen->gpu,val) ;
break ;
*/
case REG_DISPA_WIN0H:
if(proc == ARMCPU_ARM9) GPU_setWIN0_H (state->MainScreen->gpu,val) ;
break ;
case REG_DISPA_WIN1H:
if(proc == ARMCPU_ARM9) GPU_setWIN1_H(state->MainScreen->gpu,val) ;
break ;
case REG_DISPB_WIN0H:
if(proc == ARMCPU_ARM9) GPU_setWIN0_H(state->SubScreen->gpu,val) ;
break ;
case REG_DISPB_WIN1H:
if(proc == ARMCPU_ARM9) GPU_setWIN1_H(state->SubScreen->gpu,val) ;
break ;
case REG_DISPA_WIN0V:
if(proc == ARMCPU_ARM9) GPU_setWIN0_V(state->MainScreen->gpu,val) ;
break ;
case REG_DISPA_WIN1V:
if(proc == ARMCPU_ARM9) GPU_setWIN1_V(state->MainScreen->gpu,val) ;
break ;
case REG_DISPB_WIN0V:
if(proc == ARMCPU_ARM9) GPU_setWIN0_V(state->SubScreen->gpu,val) ;
break ;
case REG_DISPB_WIN1V:
if(proc == ARMCPU_ARM9) GPU_setWIN1_V(state->SubScreen->gpu,val) ;
break ;
case REG_DISPA_WININ:
if(proc == ARMCPU_ARM9) GPU_setWININ(state->MainScreen->gpu, val) ;
break ;
case REG_DISPA_WINOUT:
if(proc == ARMCPU_ARM9) GPU_setWINOUT16(state->MainScreen->gpu, val) ;
break ;
case REG_DISPB_WININ:
if(proc == ARMCPU_ARM9) GPU_setWININ(state->SubScreen->gpu, val) ;
break ;
case REG_DISPB_WINOUT:
if(proc == ARMCPU_ARM9) GPU_setWINOUT16(state->SubScreen->gpu, val) ;
break ;
case REG_DISPB_MASTERBRIGHT:
GPU_setMasterBrightness (state->SubScreen->gpu, val);
break;
case REG_POWCNT1 :
if(proc == ARMCPU_ARM9)
{
if(val & (1<<15))
{
LOG("Main core on top\n");
state->MainScreen->offset = 0;
state->SubScreen->offset = 192;
//nds->swapScreen();
}
else
{
LOG("Main core on bottom (%04X)\n", val);
state->MainScreen->offset = 192;
state->SubScreen->offset = 0;
}
}
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x304, val);
return;
case REG_AUXSPICNT:
T1WriteWord(state->MMU->MMU_MEM[proc][(REG_AUXSPICNT >> 20) & 0xff], REG_AUXSPICNT & 0xfff, val);
state->AUX_SPI_CNT = val;
if (val == 0)
mc_reset_com(&state->MMU->bupmem); /* reset backup memory device communication */
return;
case REG_AUXSPIDATA:
if(val!=0)
{
state->AUX_SPI_CMD = val & 0xFF;
}
T1WriteWord(state->MMU->MMU_MEM[proc][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&state->MMU->bupmem, (u8)val));
return;
case REG_SPICNT :
if(proc == ARMCPU_ARM7)
{
int reset_firmware = 1;
if ( ((state->SPI_CNT >> 8) & 0x3) == 1) {
if ( ((val >> 8) & 0x3) == 1) {
if ( BIT11(state->SPI_CNT)) {
/* select held */
reset_firmware = 0;
}
}
}
//MMU->fw.com == 0; /* reset fw device communication */
if ( reset_firmware) {
/* reset fw device communication */
mc_reset_com(&state->MMU->fw);
}
state->SPI_CNT = val;
}
T1WriteWord(state->MMU->MMU_MEM[proc][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff, val);
return;
case REG_SPIDATA :
if(proc==ARMCPU_ARM7)
{
u16 spicnt;
if(val!=0)
{
state->SPI_CMD = val;
}
spicnt = T1ReadWord(state->MMU->MMU_MEM[proc][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff);
switch((spicnt >> 8) & 0x3)
{
case 0 :
break;
case 1 : /* firmware memory device */
if((spicnt & 0x3) != 0) /* check SPI baudrate (must be 4mhz) */
{
T1WriteWord(state->MMU->MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, 0);
break;
}
T1WriteWord(state->MMU->MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, fw_transfer(&state->MMU->fw, (u8)val));
return;
case 2 :
switch(state->SPI_CMD & 0x70)
{
case 0x00 :
val = 0;
break;
case 0x10 :
//execute = FALSE;
if(state->SPI_CNT&(1<<11))
{
if(state->partie)
{
val = ((state->nds->touchY<<3)&0x7FF);
state->partie = 0;
//execute = FALSE;
break;
}
val = (state->nds->touchY>>5);
state->partie = 1;
break;
}
val = ((state->nds->touchY<<3)&0x7FF);
state->partie = 1;
break;
case 0x20 :
val = 0;
break;
case 0x30 :
val = 0;
break;
case 0x40 :
val = 0;
break;
case 0x50 :
if(spicnt & 0x800)
{
if(state->partie)
{
val = ((state->nds->touchX<<3)&0x7FF);
state->partie = 0;
break;
}
val = (state->nds->touchX>>5);
state->partie = 1;
break;
}
val = ((state->nds->touchX<<3)&0x7FF);
state->partie = 1;
break;
case 0x60 :
val = 0;
break;
case 0x70 :
val = 0;
break;
}
break;
case 3 :
/* NOTICE: Device 3 of SPI is reserved (unused and unusable) */
break;
}
}
T1WriteWord(state->MMU->MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, val);
return;
/* NOTICE: Perhaps we have to use gbatek-like reg names instead of libnds-like ones ...*/
case REG_DISPA_BG0CNT :
//GPULOG("MAIN BG0 SETPROP 16B %08X\r\n", val);
if(proc == ARMCPU_ARM9) GPU_setBGProp(state->MainScreen->gpu, 0, val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x8, val);
return;
case REG_DISPA_BG1CNT :
//GPULOG("MAIN BG1 SETPROP 16B %08X\r\n", val);
if(proc == ARMCPU_ARM9) GPU_setBGProp(state->MainScreen->gpu, 1, val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0xA, val);
return;
case REG_DISPA_BG2CNT :
//GPULOG("MAIN BG2 SETPROP 16B %08X\r\n", val);
if(proc == ARMCPU_ARM9) GPU_setBGProp(state->MainScreen->gpu, 2, val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0xC, val);
return;
case REG_DISPA_BG3CNT :
//GPULOG("MAIN BG3 SETPROP 16B %08X\r\n", val);
if(proc == ARMCPU_ARM9) GPU_setBGProp(state->MainScreen->gpu, 3, val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0xE, val);
return;
case REG_DISPB_BG0CNT :
//GPULOG("SUB BG0 SETPROP 16B %08X\r\n", val);
if(proc == ARMCPU_ARM9) GPU_setBGProp(state->SubScreen->gpu, 0, val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x1008, val);
return;
case REG_DISPB_BG1CNT :
//GPULOG("SUB BG1 SETPROP 16B %08X\r\n", val);
if(proc == ARMCPU_ARM9) GPU_setBGProp(state->SubScreen->gpu, 1, val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x100A, val);
return;
case REG_DISPB_BG2CNT :
//GPULOG("SUB BG2 SETPROP 16B %08X\r\n", val);
if(proc == ARMCPU_ARM9) GPU_setBGProp(state->SubScreen->gpu, 2, val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x100C, val);
return;
case REG_DISPB_BG3CNT :
//GPULOG("SUB BG3 SETPROP 16B %08X\r\n", val);
if(proc == ARMCPU_ARM9) GPU_setBGProp(state->SubScreen->gpu, 3, val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x100E, val);
return;
case REG_IME : {
u32 old_val = state->MMU->reg_IME[proc];
u32 new_val = val & 1;
state->MMU->reg_IME[proc] = new_val;
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x208, val);
if ( new_val && old_val != new_val) {
/* raise an interrupt request to the CPU if needed */
if ( state->MMU->reg_IE[proc] & state->MMU->reg_IF[proc]) {
state->NDS_ARM7->wIRQ = TRUE;
state->NDS_ARM7->waitIRQ = FALSE;
}
}
return;
}
case REG_VRAMCNTA:
MMU_write8(state,proc,adr,val & 0xFF) ;
MMU_write8(state,proc,adr+1,val >> 8) ;
return ;
case REG_VRAMCNTC:
MMU_write8(state,proc,adr,val & 0xFF) ;
MMU_write8(state,proc,adr+1,val >> 8) ;
return ;
case REG_VRAMCNTE:
MMU_write8(state,proc,adr,val & 0xFF) ;
MMU_write8(state,proc,adr+1,val >> 8) ;
return ;
case REG_VRAMCNTG:
MMU_write8(state,proc,adr,val & 0xFF) ;
MMU_write8(state,proc,adr+1,val >> 8) ;
return ;
case REG_VRAMCNTI:
MMU_write8(state,proc,adr,val & 0xFF) ;
return ;
case REG_IE :
state->MMU->reg_IE[proc] = (state->MMU->reg_IE[proc]&0xFFFF0000) | val;
if ( state->MMU->reg_IME[proc]) {
/* raise an interrupt request to the CPU if needed */
if ( state->MMU->reg_IE[proc] & state->MMU->reg_IF[proc]) {
state->NDS_ARM7->wIRQ = TRUE;
state->NDS_ARM7->waitIRQ = FALSE;
}
}
return;
case REG_IE + 2 :
state->execute = FALSE;
state->MMU->reg_IE[proc] = (state->MMU->reg_IE[proc]&0xFFFF) | (((u32)val)<<16);
return;
case REG_IF :
state->execute = FALSE;
state->MMU->reg_IF[proc] &= (~((u32)val));
return;
case REG_IF + 2 :
state->execute = FALSE;
state->MMU->reg_IF[proc] &= (~(((u32)val)<<16));
return;
case REG_IPCSYNC :
{
u32 remote = (proc+1)&1;
u16 IPCSYNC_remote = T1ReadWord(state->MMU->MMU_MEM[remote][0x40], 0x180);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF));
T1WriteWord(state->MMU->MMU_MEM[remote][0x40], 0x180, (IPCSYNC_remote&0xFFF0)|((val>>8)&0xF));
state->MMU->reg_IF[remote] |= ((IPCSYNC_remote & (1<<14))<<2) & ((val & (1<<13))<<3);// & (MMU->reg_IME[remote] << 16);// & (MMU->reg_IE[remote] & (1<<16));//
//execute = FALSE;
}
return;
case REG_IPCFIFOCNT :
{
u32 cnt_l = T1ReadWord(state->MMU->MMU_MEM[proc][0x40], 0x184) ;
u32 cnt_r = T1ReadWord(state->MMU->MMU_MEM[(proc+1) & 1][0x40], 0x184) ;
if ((val & 0x8000) && !(cnt_l & 0x8000))
{
/* this is the first init, the other side didnt init yet */
/* so do a complete init */
FIFOInit(state->MMU->fifos + (IPCFIFO+proc));
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x184,0x8101) ;
/* and then handle it as usual */
}
if(val & 0x4008)
{
FIFOInit(state->MMU->fifos + (IPCFIFO+((proc+1)&1)));
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1);
T1WriteWord(state->MMU->MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100);
state->MMU->reg_IF[proc] |= ((val & 4)<<15);// & (MMU->reg_IME[proc]<<17);// & (MMU->reg_IE[proc]&0x20000);//
return;
}
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x184, T1ReadWord(state->MMU->MMU_MEM[proc][0x40], 0x184) | (val & 0xBFF4));
}
return;
case REG_TM0CNTL :
case REG_TM1CNTL :
case REG_TM2CNTL :
case REG_TM3CNTL :
state->MMU->timerReload[proc][(adr>>2)&3] = val;
return;
case REG_TM0CNTH :
case REG_TM1CNTH :
case REG_TM2CNTH :
case REG_TM3CNTH :
if(val&0x80)
{
state->MMU->timer[proc][((adr-2)>>2)&0x3] = state->MMU->timerReload[proc][((adr-2)>>2)&0x3];
}
state->MMU->timerON[proc][((adr-2)>>2)&0x3] = val & 0x80;
switch(val&7)
{
case 0 :
state->MMU->timerMODE[proc][((adr-2)>>2)&0x3] = 0+1;//proc;
break;
case 1 :
state->MMU->timerMODE[proc][((adr-2)>>2)&0x3] = 6+1;//proc;
break;
case 2 :
state->MMU->timerMODE[proc][((adr-2)>>2)&0x3] = 8+1;//proc;
break;
case 3 :
state->MMU->timerMODE[proc][((adr-2)>>2)&0x3] = 10+1;//proc;
break;
default :
state->MMU->timerMODE[proc][((adr-2)>>2)&0x3] = 0xFFFF;
break;
}
if(!(val & 0x80))
state->MMU->timerRUN[proc][((adr-2)>>2)&0x3] = FALSE;
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], adr & 0xFFF, val);
return;
case REG_DISPA_DISPCNT+2 :
{
//execute = FALSE;
u32 v = (T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0) & 0xFFFF) | ((u32) val << 16);
GPU_setVideoProp(state->MainScreen->gpu, v);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0, v);
}
return;
case REG_DISPA_DISPCNT :
if(proc == ARMCPU_ARM9)
{
u32 v = (T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0) & 0xFFFF0000) | val;
GPU_setVideoProp(state->MainScreen->gpu, v);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0, v);
}
return;
case REG_DISPA_DISPCAPCNT :
if(proc == ARMCPU_ARM9)
{
GPU_set_DISPCAPCNT(state->MainScreen->gpu,val);
}
return;
case REG_DISPB_DISPCNT+2 :
if(proc == ARMCPU_ARM9)
{
//execute = FALSE;
u32 v = (T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0x1000) & 0xFFFF) | ((u32) val << 16);
GPU_setVideoProp(state->SubScreen->gpu, v);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x1000, v);
}
return;
case REG_DISPB_DISPCNT :
{
u32 v = (T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0x1000) & 0xFFFF0000) | val;
GPU_setVideoProp(state->SubScreen->gpu, v);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x1000, v);
}
return;
//case 0x020D8460 :
/*case 0x0235A904 :
LOG("ECRIRE %d %04X\r\n", proc, val);
execute = FALSE;*/
case REG_DMA0CNTH :
{
u32 v;
//if(val&0x8000) execute = FALSE;
//LOG("16 bit dma0 %04X\r\n", val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0xBA, val);
state->DMASrc[proc][0] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xB0);
state->DMADst[proc][0] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xB4);
v = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xB8);
state->MMU->DMAStartTime[proc][0] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
state->MMU->DMACrt[proc][0] = v;
if(state->MMU->DMAStartTime[proc][0] == 0)
MMU_doDMA(state, proc, 0);
#ifdef LOG_DMA2
//else
{
LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 0, state->DMASrc[proc][0], state->DMADst[proc][0], (val&(1<<25))?"ON":"OFF");
}
#endif
}
return;
case REG_DMA1CNTH :
{
u32 v;
//if(val&0x8000) execute = FALSE;
//LOG("16 bit dma1 %04X\r\n", val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0xC6, val);
state->DMASrc[proc][1] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xBC);
state->DMADst[proc][1] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xC0);
v = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xC4);
state->MMU->DMAStartTime[proc][1] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
state->MMU->DMACrt[proc][1] = v;
if(state->MMU->DMAStartTime[proc][1] == 0)
MMU_doDMA(state, proc, 1);
#ifdef LOG_DMA2
//else
{
LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 1, state->DMASrc[proc][1], state->DMADst[proc][1], (val&(1<<25))?"ON":"OFF");
}
#endif
}
return;
case REG_DMA2CNTH :
{
u32 v;
//if(val&0x8000) execute = FALSE;
//LOG("16 bit dma2 %04X\r\n", val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0xD2, val);
state->DMASrc[proc][2] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xC8);
state->DMADst[proc][2] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xCC);
v = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xD0);
state->MMU->DMAStartTime[proc][2] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
state->MMU->DMACrt[proc][2] = v;
if(state->MMU->DMAStartTime[proc][2] == 0)
MMU_doDMA(state, proc, 2);
#ifdef LOG_DMA2
//else
{
LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 2, state->DMASrc[proc][2], state->DMADst[proc][2], (val&(1<<25))?"ON":"OFF");
}
#endif
}
return;
case REG_DMA3CNTH :
{
u32 v;
//if(val&0x8000) execute = FALSE;
//LOG("16 bit dma3 %04X\r\n", val);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0xDE, val);
state->DMASrc[proc][3] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xD4);
state->DMADst[proc][3] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xD8);
v = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xDC);
state->MMU->DMAStartTime[proc][3] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
state->MMU->DMACrt[proc][3] = v;
if(state->MMU->DMAStartTime[proc][3] == 0)
MMU_doDMA(state, proc, 3);
#ifdef LOG_DMA2
//else
{
LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 3, state->DMASrc[proc][3], state->DMADst[proc][3], (val&(1<<25))?"ON":"OFF");
}
#endif
}
return;
//case REG_AUXSPICNT : execute = FALSE;
default :
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], adr&state->MMU->MMU_MASK[proc][(adr>>20)&0xFF], val);
return;
}
}
T1WriteWord(state->MMU->MMU_MEM[proc][(adr>>20)&0xFF], adr&state->MMU->MMU_MASK[proc][(adr>>20)&0xFF], val);
}
void FASTCALL MMU_write32(NDS_state *state, u32 proc, u32 adr, u32 val)
{
#ifdef INTERNAL_DTCM_WRITE
if((proc==ARMCPU_ARM9)&((adr&(~0x3FFF))==state->MMU->DTCMRegion))
{
T1WriteLong(state->ARM9Mem->ARM9_DTCM, adr & 0x3FFF, val);
return ;
}
#endif
// CFlash writing, Mic
if ((adr>=0x9000000)&&(adr<0x9900000)) {
cflash_write(state,adr,val);
return;
}
adr &= 0x0FFFFFFF;
// This is bad, remove it
if(proc == ARMCPU_ARM7)
{
if ((adr>=0x04000400)&&(adr<0x0400051D))
{
SPU_WriteLong(state, adr, val);
return;
}
}
if ((adr & 0xFF800000) == 0x04800000) {
/* access to non regular hw registers */
/* return to not overwrite valid data */
return ;
} ;
if((adr>>24)==4)
{
if (adr >= 0x04000400 && adr < 0x04000440)
{
// Geometry commands (aka Dislay Lists) - Parameters:X
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x400>>2] = val;
#if VIO2SF_GPU_ENABLE
if(proc==ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_CallList(state->gpu3D, val);
}
#endif
}
else
switch(adr)
{
#if VIO2SF_GPU_ENABLE
// Alpha test reference value - Parameters:1
case 0x04000340:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x340>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_AlphaFunc(state->gpu3D, val);
}
return;
}
// Clear background color setup - Parameters:2
case 0x04000350:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x350>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_ClearColor(state->gpu3D, val);
}
return;
}
// Clear background depth setup - Parameters:2
case 0x04000354:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x354>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_ClearDepth(state->gpu3D, val);
}
return;
}
// Fog Color - Parameters:4b
case 0x04000358:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x358>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_FogColor(state->gpu3D, val);
}
return;
}
case 0x0400035C:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x35C>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_FogOffset(state->gpu3D, val);
}
return;
}
// Matrix mode - Parameters:1
case 0x04000440:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x440>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_MatrixMode(state->gpu3D, val);
}
return;
}
// Push matrix - Parameters:0
case 0x04000444:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x444>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_PushMatrix(state->gpu3D);
}
return;
}
// Pop matrix/es - Parameters:1
case 0x04000448:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x448>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_PopMatrix(state->gpu3D, val);
}
return;
}
// Store matrix in the stack - Parameters:1
case 0x0400044C:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x44C>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_StoreMatrix(state->gpu3D, val);
}
return;
}
// Restore matrix from the stack - Parameters:1
case 0x04000450:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x450>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_RestoreMatrix(state->gpu3D, val);
}
return;
}
// Load Identity matrix - Parameters:0
case 0x04000454:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x454>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_LoadIdentity(state->gpu3D);
}
return;
}
// Load 4x4 matrix - Parameters:16
case 0x04000458:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x458>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_LoadMatrix4x4(state->gpu3D, val);
}
return;
}
// Load 4x3 matrix - Parameters:12
case 0x0400045C:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x45C>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_LoadMatrix4x3(state->gpu3D, val);
}
return;
}
// Multiply 4x4 matrix - Parameters:16
case 0x04000460:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x460>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_MultMatrix4x4(state->gpu3D, val);
}
return;
}
// Multiply 4x4 matrix - Parameters:12
case 0x04000464:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x464>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_MultMatrix4x3(state->gpu3D, val);
}
return;
}
// Multiply 3x3 matrix - Parameters:9
case 0x04000468 :
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x468>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_MultMatrix3x3(state->gpu3D, val);
}
return;
}
// Multiply current matrix by scaling matrix - Parameters:3
case 0x0400046C:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x46C>>2] = val;
if(proc==ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Scale(state->gpu3D, val);
}
return;
}
// Multiply current matrix by translation matrix - Parameters:3
case 0x04000470:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x470>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Translate(state->gpu3D, val);
}
return;
}
// Set vertex color - Parameters:1
case 0x04000480:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x480>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Color3b(state->gpu3D, val);
}
return;
}
// Set vertex normal - Parameters:1
case 0x04000484:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x484>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Normal(state->gpu3D, val);
}
return;
}
// Set vertex texture coordinate - Parameters:1
case 0x04000488:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x488>>2] = val;
if(proc==ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_TexCoord(state->gpu3D, val);
}
return;
}
// Set vertex position 16b/coordinate - Parameters:2
case 0x0400048C:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x48C>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Vertex16b(state->gpu3D, val);
}
return;
}
// Set vertex position 10b/coordinate - Parameters:1
case 0x04000490:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x490>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Vertex10b(state->gpu3D, val);
}
return;
}
// Set vertex XY position - Parameters:1
case 0x04000494:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x494>>2] = val;
if(proc==ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Vertex3_cord(state->gpu3D,0,1,val);
}
return;
}
// Set vertex XZ position - Parameters:1
case 0x04000498:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x498>>2] = val;
if(proc==ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Vertex3_cord(state->gpu3D,0,2,val);
}
return;
}
// Set vertex YZ position - Parameters:1
case 0x0400049C:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x49C>>2] = val;
if(proc==ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Vertex3_cord(state->gpu3D,1,2,val);
}
return;
}
// Set vertex difference position (offset from the last vertex) - Parameters:1
case 0x040004A0:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x4A0>>2] = val;
if(proc==ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Vertex_rel (state->gpu3D,val);
}
return;
}
// Set polygon attributes - Parameters:1
case 0x040004A4:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x4A4>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_PolygonAttrib(state->gpu3D,val);
}
return;
}
// Set texture parameteres - Parameters:1
case 0x040004A8:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x4A8>>2] = val;
if(proc==ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_TexImage(state->gpu3D,val);
}
return;
}
// Set palette base address - Parameters:1
case 0x040004AC:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x4AC>>2] = val&0x1FFF;
if(proc==ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_TexPalette(state->gpu3D, val&0x1FFFF);
}
return;
}
// Set material diffuse/ambient parameters - Parameters:1
case 0x040004C0:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x4C0>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Material0 (state->gpu3D, val);
}
return;
}
// Set material reflection/emission parameters - Parameters:1
case 0x040004C4:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x4C4>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Material1 (state->gpu3D, val);
}
return;
}
// Light direction vector - Parameters:1
case 0x040004C8:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x4C8>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_LightDirection (state->gpu3D, val);
}
return;
}
// Light color - Parameters:1
case 0x040004CC:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x4CC>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_LightColor(state->gpu3D, val);
}
return;
}
// Material Shininess - Parameters:32
case 0x040004D0:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x4D0>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Shininess(state->gpu3D, val);
}
return;
}
// Begin vertex list - Parameters:1
case 0x04000500:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x500>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Begin(state->gpu3D, val);
}
return;
}
// End vertex list - Parameters:0
case 0x04000504:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x504>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_End(state->gpu3D);
}
return;
}
// Swap rendering engine buffers - Parameters:1
case 0x04000540:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x540>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_Flush(state->gpu3D, val);
}
return;
}
// Set viewport coordinates - Parameters:1
case 0x04000580:
{
((u32 *)(state->MMU->MMU_MEM[proc][0x40]))[0x580>>2] = val;
if(proc == ARMCPU_ARM9)
{
state->gpu3D->NDS_3D_ViewPort(state->gpu3D, val);
}
return;
}
#endif
case REG_DISPA_WININ:
{
if(proc == ARMCPU_ARM9)
{
GPU_setWININ (state->MainScreen->gpu, val & 0xFFFF) ;
GPU_setWINOUT16 (state->MainScreen->gpu, (val >> 16) & 0xFFFF) ;
}
break;
}
case REG_DISPB_WININ:
{
if(proc == ARMCPU_ARM9)
{
GPU_setWININ (state->SubScreen->gpu, val & 0xFFFF) ;
GPU_setWINOUT16 (state->SubScreen->gpu, (val >> 16) & 0xFFFF) ;
}
break;
}
case REG_DISPA_BLDCNT:
{
if (proc == ARMCPU_ARM9)
{
GPU_setBLDCNT (state->MainScreen->gpu,val&0xffff);
GPU_setBLDALPHA (state->MainScreen->gpu,val>>16);
}
break;
}
case REG_DISPB_BLDCNT:
{
if (proc == ARMCPU_ARM9)
{
GPU_setBLDCNT (state->SubScreen->gpu,val&0xffff);
GPU_setBLDALPHA (state->SubScreen->gpu,val>>16);
}
break;
}
/*
// Commented out, as this doesn't use the plug-in system, neither works
case cmd_3D_MTX_MODE // 0x04000440 :
if (proc == ARMCPU_ARM9) gl_MTX_MODE(val);
return;
case cmd_3D_MTX_PUSH // 0x04000444 :
case cmd_3D_MTX_POP // 0x04000448 :
case cmd_3D_MTX_STORE // 0x0400044C :
case cmd_3D_MTX_RESTORE // 0x04000450 :
if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
return;
case cmd_3D_MTX_IDENTITY // 0x04000454 :
if (proc == ARMCPU_ARM9) gl_MTX_IDENTITY();
return;
case cmd_3D_MTX_LOAD_4x4 // 0x04000458 :
if (proc == ARMCPU_ARM9) gl_MTX_LOAD_4x4(val);
return;
case cmd_3D_MTX_LOAD_4x3 // 0x0400045C :
if (proc == ARMCPU_ARM9) gl_MTX_LOAD_4x3(val);
return;
case cmd_3D_MTX_MULT_4x4 // 0x04000460 :
if (proc == ARMCPU_ARM9) gl_MTX_MULT_4x4(val);
return;
case cmd_3D_MTX_MULT_4x3 // 0x04000464 :
if (proc == ARMCPU_ARM9) gl_MTX_MULT_4x3(val);
return;
case cmd_3D_MTX_MULT_3x3 // 0x04000468 :
if (proc == ARMCPU_ARM9) gl_MTX_MULT_3x3(val);
return;
case cmd_3D_MTX_SCALE // 0x0400046C :
case cmd_3D_MTX_TRANS // 0x04000470 :
case cmd_3D_COLOR // 0x04000480 :
case cmd_3D_NORMA // 0x04000484 :
if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
return;
case cmd_3D_TEXCOORD // 0x04000488 :
if (proc == ARMCPU_ARM9) gl_TEXCOORD(val);
return;
case cmd_3D_VTX_16 // 0x0400048C :
if (proc == ARMCPU_ARM9) gl_VTX_16(val);
return;
case cmd_3D_VTX_10 // 0x04000490 :
if (proc == ARMCPU_ARM9) gl_VTX_10(val);
return;
case cmd_3D_VTX_XY // 0x04000494 :
if (proc == ARMCPU_ARM9) gl_VTX_XY(val);
return;
case cmd_3D_VTX_XZ // 0x04000498 :
if (proc == ARMCPU_ARM9) gl_VTX_XZ(val);
return;
case cmd_3D_VTX_YZ // 0x0400049C :
if (proc == ARMCPU_ARM9) gl_VTX_YZ(val);
return;
case cmd_3D_VTX_DIFF // 0x040004A0 :
if (proc == ARMCPU_ARM9) gl_VTX_DIFF(val);
return;
case cmd_3D_POLYGON_ATTR // 0x040004A4 :
case cmd_3D_TEXIMAGE_PARAM // 0x040004A8 :
case cmd_3D_PLTT_BASE // 0x040004AC :
case cmd_3D_DIF_AMB // 0x040004C0 :
case cmd_3D_SPE_EMI // 0x040004C4 :
case cmd_3D_LIGHT_VECTOR // 0x040004C8 :
case cmd_3D_LIGHT_COLOR // 0x040004CC :
case cmd_3D_SHININESS // 0x040004D0 :
if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
return;
case cmd_3D_BEGIN_VTXS // 0x04000500 :
if (proc == ARMCPU_ARM9) gl_VTX_begin(val);
return;
case cmd_3D_END_VTXS // 0x04000504 :
if (proc == ARMCPU_ARM9) gl_VTX_end();
return;
case cmd_3D_SWAP_BUFFERS // 0x04000540 :
case cmd_3D_VIEWPORT // 0x04000580 :
case cmd_3D_BOX_TEST // 0x040005C0 :
case cmd_3D_POS_TEST // 0x040005C4 :
case cmd_3D_VEC_TEST // 0x040005C8 :
if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
return;
*/
case REG_DISPA_DISPCNT :
if(proc == ARMCPU_ARM9) GPU_setVideoProp(state->MainScreen->gpu, val);
//GPULOG("MAIN INIT 32B %08X\r\n", val);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0, val);
return;
case REG_DISPB_DISPCNT :
if (proc == ARMCPU_ARM9) GPU_setVideoProp(state->SubScreen->gpu, val);
//GPULOG("SUB INIT 32B %08X\r\n", val);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x1000, val);
return;
case REG_VRAMCNTA:
case REG_VRAMCNTE:
MMU_write8(state,proc,adr,val & 0xFF) ;
MMU_write8(state,proc,adr+1,val >> 8) ;
MMU_write8(state,proc,adr+2,val >> 16) ;
MMU_write8(state,proc,adr+3,val >> 24) ;
return ;
case REG_VRAMCNTI:
MMU_write8(state,proc,adr,val & 0xFF) ;
return ;
case REG_IME : {
u32 old_val = state->MMU->reg_IME[proc];
u32 new_val = val & 1;
state->MMU->reg_IME[proc] = new_val;
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x208, val);
if ( new_val && old_val != new_val) {
/* raise an interrupt request to the CPU if needed */
if ( state->MMU->reg_IE[proc] & state->MMU->reg_IF[proc]) {
state->NDS_ARM7->wIRQ = TRUE;
state->NDS_ARM7->waitIRQ = FALSE;
}
}
return;
}
case REG_IE :
state->MMU->reg_IE[proc] = val;
if ( state->MMU->reg_IME[proc]) {
/* raise an interrupt request to the CPU if needed */
if ( state->MMU->reg_IE[proc] & state->MMU->reg_IF[proc]) {
state->NDS_ARM7->wIRQ = TRUE;
state->NDS_ARM7->waitIRQ = FALSE;
}
}
return;
case REG_IF :
state->MMU->reg_IF[proc] &= (~val);
return;
case REG_TM0CNTL :
case REG_TM1CNTL :
case REG_TM2CNTL :
case REG_TM3CNTL :
state->MMU->timerReload[proc][(adr>>2)&0x3] = (u16)val;
if(val&0x800000)
{
state->MMU->timer[proc][(adr>>2)&0x3] = state->MMU->timerReload[proc][(adr>>2)&0x3];
}
state->MMU->timerON[proc][(adr>>2)&0x3] = val & 0x800000;
switch((val>>16)&7)
{
case 0 :
state->MMU->timerMODE[proc][(adr>>2)&0x3] = 0+1;//proc;
break;
case 1 :
state->MMU->timerMODE[proc][(adr>>2)&0x3] = 6+1;//proc;
break;
case 2 :
state->MMU->timerMODE[proc][(adr>>2)&0x3] = 8+1;//proc;
break;
case 3 :
state->MMU->timerMODE[proc][(adr>>2)&0x3] = 10+1;//proc;
break;
default :
state->MMU->timerMODE[proc][(adr>>2)&0x3] = 0xFFFF;
break;
}
if(!(val & 0x800000))
{
state->MMU->timerRUN[proc][(adr>>2)&0x3] = FALSE;
}
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], adr & 0xFFF, val);
return;
case REG_DIVDENOM :
{
u16 cnt;
s64 num = 0;
s64 den = 1;
s64 res;
s64 mod;
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x298, val);
cnt = T1ReadWord(state->MMU->MMU_MEM[proc][0x40], 0x280);
switch(cnt&3)
{
case 0:
{
num = (s64) (s32) T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0x290);
den = (s64) (s32) T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0x298);
}
break;
case 1:
{
num = (s64) T1ReadQuad(state->MMU->MMU_MEM[proc][0x40], 0x290);
den = (s64) (s32) T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0x298);
}
break;
case 2:
{
return;
}
break;
default:
break;
}
if(den==0)
{
res = 0;
mod = 0;
cnt |= 0x4000;
cnt &= 0x7FFF;
}
else
{
res = num / den;
mod = num % den;
cnt &= 0x3FFF;
}
DIVLOG("BOUT1 %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num,
(u32)(den>>32), (u32)den,
(u32)(res>>32), (u32)res);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2A0, (u32) res);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2A4, (u32) (res >> 32));
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2A8, (u32) mod);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2AC, (u32) (mod >> 32));
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x280, cnt);
}
return;
case REG_DIVDENOM+4 :
{
u16 cnt;
s64 num = 0;
s64 den = 1;
s64 res;
s64 mod;
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x29C, val);
cnt = T1ReadWord(state->MMU->MMU_MEM[proc][0x40], 0x280);
switch(cnt&3)
{
case 0:
{
return;
}
break;
case 1:
{
return;
}
break;
case 2:
{
num = (s64) T1ReadQuad(state->MMU->MMU_MEM[proc][0x40], 0x290);
den = (s64) T1ReadQuad(state->MMU->MMU_MEM[proc][0x40], 0x298);
}
break;
default:
break;
}
if(den==0)
{
res = 0;
mod = 0;
cnt |= 0x4000;
cnt &= 0x7FFF;
}
else
{
res = num / den;
mod = num % den;
cnt &= 0x3FFF;
}
DIVLOG("BOUT2 %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num,
(u32)(den>>32), (u32)den,
(u32)(res>>32), (u32)res);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2A0, (u32) res);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2A4, (u32) (res >> 32));
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2A8, (u32) mod);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2AC, (u32) (mod >> 32));
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x280, cnt);
}
return;
case REG_SQRTPARAM :
{
u16 cnt;
u64 v = 1;
//execute = FALSE;
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2B8, val);
cnt = T1ReadWord(state->MMU->MMU_MEM[proc][0x40], 0x2B0);
switch(cnt&1)
{
case 0:
v = (u64) T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0x2B8);
break;
case 1:
return;
}
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2B4, (u32) isqrt64(v));
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2B0, cnt & 0x7FFF);
SQRTLOG("BOUT1 sqrt(%08X%08X) = %08X\r\n", (u32)(v>>32), (u32)v,
T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0x2B4));
}
return;
case REG_SQRTPARAM+4 :
{
u16 cnt;
u64 v = 1;
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2BC, val);
cnt = T1ReadWord(state->MMU->MMU_MEM[proc][0x40], 0x2B0);
switch(cnt&1)
{
case 0:
return;
//break;
case 1:
v = T1ReadQuad(state->MMU->MMU_MEM[proc][0x40], 0x2B8);
break;
}
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2B4, (u32) isqrt64(v));
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x2B0, cnt & 0x7FFF);
SQRTLOG("BOUT2 sqrt(%08X%08X) = %08X\r\n", (u32)(v>>32), (u32)v,
T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0x2B4));
}
return;
case REG_IPCSYNC :
{
//execute=FALSE;
u32 remote = (proc+1)&1;
u32 IPCSYNC_remote = T1ReadLong(state->MMU->MMU_MEM[remote][0x40], 0x180);
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF));
T1WriteLong(state->MMU->MMU_MEM[remote][0x40], 0x180, (IPCSYNC_remote&0xFFF0)|((val>>8)&0xF));
state->MMU->reg_IF[remote] |= ((IPCSYNC_remote & (1<<14))<<2) & ((val & (1<<13))<<3);// & (MMU->reg_IME[remote] << 16);// & (MMU->reg_IE[remote] & (1<<16));//
}
return;
case REG_IPCFIFOCNT :
{
u32 cnt_l = T1ReadWord(state->MMU->MMU_MEM[proc][0x40], 0x184) ;
u32 cnt_r = T1ReadWord(state->MMU->MMU_MEM[(proc+1) & 1][0x40], 0x184) ;
if ((val & 0x8000) && !(cnt_l & 0x8000))
{
/* this is the first init, the other side didnt init yet */
/* so do a complete init */
FIFOInit(state->MMU->fifos + (IPCFIFO+proc));
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x184,0x8101) ;
/* and then handle it as usual */
}
if(val & 0x4008)
{
FIFOInit(state->MMU->fifos + (IPCFIFO+((proc+1)&1)));
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1);
T1WriteWord(state->MMU->MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100);
state->MMU->reg_IF[proc] |= ((val & 4)<<15);// & (MMU->reg_IME[proc]<<17);// & (MMU->reg_IE[proc]&0x20000);//
return;
}
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x184, val & 0xBFF4);
//execute = FALSE;
return;
}
case REG_IPCFIFOSEND :
{
u16 IPCFIFO_CNT = T1ReadWord(state->MMU->MMU_MEM[proc][0x40], 0x184);
if(IPCFIFO_CNT&0x8000)
{
//if(val==43) execute = FALSE;
u32 remote = (proc+1)&1;
u32 fifonum = IPCFIFO+remote;
u16 IPCFIFO_CNT_remote;
FIFOAdd(state->MMU->fifos + fifonum, val);
IPCFIFO_CNT = (IPCFIFO_CNT & 0xFFFC) | (state->MMU->fifos[fifonum].full<<1);
IPCFIFO_CNT_remote = T1ReadWord(state->MMU->MMU_MEM[remote][0x40], 0x184);
IPCFIFO_CNT_remote = (IPCFIFO_CNT_remote & 0xFCFF) | (state->MMU->fifos[fifonum].full<<10);
T1WriteWord(state->MMU->MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT);
T1WriteWord(state->MMU->MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote);
state->MMU->reg_IF[remote] |= ((IPCFIFO_CNT_remote & (1<<10))<<8);// & (MMU->reg_IME[remote] << 18);// & (MMU->reg_IE[remote] & 0x40000);//
//execute = FALSE;
}
}
return;
case REG_DMA0CNTL :
//LOG("32 bit dma0 %04X\r\n", val);
state->DMASrc[proc][0] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xB0);
state->DMADst[proc][0] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xB4);
state->MMU->DMAStartTime[proc][0] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
state->MMU->DMACrt[proc][0] = val;
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0xB8, val);
if( state->MMU->DMAStartTime[proc][0] == 0 ||
state->MMU->DMAStartTime[proc][0] == 7) // Start Immediately
MMU_doDMA(state, proc, 0);
#ifdef LOG_DMA2
else
{
LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 0, state->DMASrc[proc][0], state->DMADst[proc][0], 0, ((state->MMU->DMACrt[proc][0]>>27)&7));
}
#endif
//execute = FALSE;
return;
case REG_DMA1CNTL:
//LOG("32 bit dma1 %04X\r\n", val);
state->DMASrc[proc][1] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xBC);
state->DMADst[proc][1] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xC0);
state->MMU->DMAStartTime[proc][1] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
state->MMU->DMACrt[proc][1] = val;
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0xC4, val);
if(state->MMU->DMAStartTime[proc][1] == 0 ||
state->MMU->DMAStartTime[proc][1] == 7) // Start Immediately
MMU_doDMA(state, proc, 1);
#ifdef LOG_DMA2
else
{
LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 1, state->DMASrc[proc][1], state->DMADst[proc][1], 0, ((state->MMU->DMACrt[proc][1]>>27)&7));
}
#endif
return;
case REG_DMA2CNTL :
//LOG("32 bit dma2 %04X\r\n", val);
state->DMASrc[proc][2] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xC8);
state->DMADst[proc][2] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xCC);
state->MMU->DMAStartTime[proc][2] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
state->MMU->DMACrt[proc][2] = val;
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0xD0, val);
if(state->MMU->DMAStartTime[proc][2] == 0 ||
state->MMU->DMAStartTime[proc][2] == 7) // Start Immediately
MMU_doDMA(state, proc, 2);
#ifdef LOG_DMA2
else
{
LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 2, state->DMASrc[proc][2], state->DMADst[proc][2], 0, ((state->MMU->DMACrt[proc][2]>>27)&7));
}
#endif
return;
case 0x040000DC :
//LOG("32 bit dma3 %04X\r\n", val);
state->DMASrc[proc][3] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xD4);
state->DMADst[proc][3] = T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xD8);
state->MMU->DMAStartTime[proc][3] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
state->MMU->DMACrt[proc][3] = val;
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0xDC, val);
if( state->MMU->DMAStartTime[proc][3] == 0 ||
state->MMU->DMAStartTime[proc][3] == 7) // Start Immediately
MMU_doDMA(state, proc, 3);
#ifdef LOG_DMA2
else
{
LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 3, state->DMASrc[proc][3], state->DMADst[proc][3], 0, ((state->MMU->DMACrt[proc][3]>>27)&7));
}
#endif
return;
case REG_GCROMCTRL :
{
int i;
if(MEM_8(state->MMU->MMU_MEM[proc], REG_GCCMDOUT) == 0xB7)
{
state->MMU->dscard[proc].adress = (MEM_8(state->MMU->MMU_MEM[proc], REG_GCCMDOUT+1) << 24) | (MEM_8(state->MMU->MMU_MEM[proc], REG_GCCMDOUT+2) << 16) | (MEM_8(state->MMU->MMU_MEM[proc], REG_GCCMDOUT+3) << 8) | (MEM_8(state->MMU->MMU_MEM[proc], REG_GCCMDOUT+4));
state->MMU->dscard[proc].transfer_count = 0x80;// * ((val>>24)&7));
}
else if (MEM_8(state->MMU->MMU_MEM[proc], REG_GCCMDOUT) == 0xB8)
{
// Get ROM chip ID
val |= 0x800000; // Data-Word Status
T1WriteLong(state->MMU->MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);
state->MMU->dscard[proc].adress = 0;
}
else
{
LOG("CARD command: %02X\n", MEM_8(state->MMU->MMU_MEM[proc], REG_GCCMDOUT));
}
//CARDLOG("%08X : %08X %08X\r\n", adr, val, adresse[proc]);
val |= 0x00800000;
if(state->MMU->dscard[proc].adress == 0)
{
val &= ~0x80000000;
T1WriteLong(state->MMU->MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);
return;
}
T1WriteLong(state->MMU->MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);
/* launch DMA if start flag was set to "DS Cart" */
if(proc == ARMCPU_ARM7) i = 2;
else i = 5;
if(proc == ARMCPU_ARM9 && state->MMU->DMAStartTime[proc][0] == i) /* dma0/1 on arm7 can't start on ds cart event */
{
MMU_doDMA(state, proc, 0);
return;
}
else if(proc == ARMCPU_ARM9 && state->MMU->DMAStartTime[proc][1] == i)
{
MMU_doDMA(state, proc, 1);
return;
}
else if(state->MMU->DMAStartTime[proc][2] == i)
{
MMU_doDMA(state, proc, 2);
return;
}
else if(state->MMU->DMAStartTime[proc][3] == i)
{
MMU_doDMA(state, proc, 3);
return;
}
return;
}
return;
case REG_DISPA_DISPCAPCNT :
if(proc == ARMCPU_ARM9)
{
GPU_set_DISPCAPCNT(state->MainScreen->gpu,val);
T1WriteLong(state->ARM9Mem->ARM9_REG, 0x64, val);
}
return;
case REG_DISPA_BG0CNT :
if (proc == ARMCPU_ARM9)
{
GPU_setBGProp(state->MainScreen->gpu, 0, (val&0xFFFF));
GPU_setBGProp(state->MainScreen->gpu, 1, (val>>16));
}
//if((val>>16)==0x400) execute = FALSE;
T1WriteLong(state->ARM9Mem->ARM9_REG, 8, val);
return;
case REG_DISPA_BG2CNT :
if (proc == ARMCPU_ARM9)
{
GPU_setBGProp(state->MainScreen->gpu, 2, (val&0xFFFF));
GPU_setBGProp(state->MainScreen->gpu, 3, (val>>16));
}
T1WriteLong(state->ARM9Mem->ARM9_REG, 0xC, val);
return;
case REG_DISPB_BG0CNT :
if (proc == ARMCPU_ARM9)
{
GPU_setBGProp(state->SubScreen->gpu, 0, (val&0xFFFF));
GPU_setBGProp(state->SubScreen->gpu, 1, (val>>16));
}
T1WriteLong(state->ARM9Mem->ARM9_REG, 0x1008, val);
return;
case REG_DISPB_BG2CNT :
if (proc == ARMCPU_ARM9)
{
GPU_setBGProp(state->SubScreen->gpu, 2, (val&0xFFFF));
GPU_setBGProp(state->SubScreen->gpu, 3, (val>>16));
}
T1WriteLong(state->ARM9Mem->ARM9_REG, 0x100C, val);
return;
case REG_DISPA_DISPMMEMFIFO:
{
// NOTE: right now, the capture unit is not taken into account,
// I don't know is it should be handled here or
FIFOAdd(state->MMU->fifos + MAIN_MEMORY_DISP_FIFO, val);
break;
}
//case 0x21FDFF0 : if(val==0) execute = FALSE;
//case 0x21FDFB0 : if(val==0) execute = FALSE;
default :
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], adr & state->MMU->MMU_MASK[proc][(adr>>20)&0xFF], val);
return;
}
}
T1WriteLong(state->MMU->MMU_MEM[proc][(adr>>20)&0xFF], adr&state->MMU->MMU_MASK[proc][(adr>>20)&0xFF], val);
}
void FASTCALL MMU_doDMA(NDS_state *state, u32 proc, u32 num)
{
u32 src = state->DMASrc[proc][num];
u32 dst = state->DMADst[proc][num];
u32 taille;
if(src==dst)
{
T1WriteLong(state->MMU->MMU_MEM[proc][0x40], 0xB8 + (0xC*num), T1ReadLong(state->MMU->MMU_MEM[proc][0x40], 0xB8 + (0xC*num)) & 0x7FFFFFFF);
return;
}
if((!(state->MMU->DMACrt[proc][num]&(1<<31)))&&(!(state->MMU->DMACrt[proc][num]&(1<<25))))
{ /* not enabled and not to be repeated */
state->MMU->DMAStartTime[proc][num] = 0;
state->MMU->DMACycle[proc][num] = 0;
//MMU->DMAing[proc][num] = FALSE;
return;
}
/* word count */
taille = (state->MMU->DMACrt[proc][num]&0xFFFF);
// If we are in "Main memory display" mode just copy an entire
// screen (256x192 pixels).
// Reference: http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode
// (under DISP_MMEM_FIFO)
if ((state->MMU->DMAStartTime[proc][num]==4) && // Must be in main memory display mode
(taille==4) && // Word must be 4
(((state->MMU->DMACrt[proc][num]>>26)&1) == 1)) // Transfer mode must be 32bit wide
taille = 256*192/2;
if(state->MMU->DMAStartTime[proc][num] == 5)
taille *= 0x80;
state->MMU->DMACycle[proc][num] = taille + state->nds->cycles;
state->MMU->DMAing[proc][num] = TRUE;
DMALOG("proc %d, dma %d src %08X dst %08X start %d taille %d repeat %s %08X\r\n",
proc, num, src, dst, state->MMU->DMAStartTime[proc][num], taille,
(state->MMU->DMACrt[proc][num]&(1<<25))?"on":"off",state->MMU->DMACrt[proc][num]);
if(!(state->MMU->DMACrt[proc][num]&(1<<25)))
state->MMU->DMAStartTime[proc][num] = 0;
// transfer
{
u32 i=0;
// 32 bit or 16 bit transfer ?
int sz = ((state->MMU->DMACrt[proc][num]>>26)&1)? 4 : 2;
int dstinc,srcinc;
int u=(state->MMU->DMACrt[proc][num]>>21);
switch(u & 0x3) {
case 0 : dstinc = sz; break;
case 1 : dstinc = -sz; break;
case 2 : dstinc = 0; break;
case 3 : dstinc = sz; break; //reload
}
switch((u >> 2)&0x3) {
case 0 : srcinc = sz; break;
case 1 : srcinc = -sz; break;
case 2 : srcinc = 0; break;
case 3 : // reserved
return;
}
if ((state->MMU->DMACrt[proc][num]>>26)&1)
for(; i < taille; ++i)
{
MMU_write32(state, proc, dst, MMU_read32(state, proc, src));
dst += dstinc;
src += srcinc;
}
else
for(; i < taille; ++i)
{
MMU_write16(state, proc, dst, MMU_read16(state, proc, src));
dst += dstinc;
src += srcinc;
}
}
}
#ifdef MMU_ENABLE_ACL
INLINE void check_access(NDS_state *state, u32 adr, u32 access) {
/* every other mode: sys */
access |= 1;
if ((state->NDS_ARM9->CPSR.val & 0x1F) == 0x10) {
/* is user mode access */
access ^= 1 ;
}
if (armcp15_isAccessAllowed((armcp15_t *)state->NDS_ARM9->coproc[15],adr,access)==FALSE) {
state->execute = FALSE ;
}
}
INLINE void check_access_write(NDS_State *state, u32 adr) {
u32 access = CP15_ACCESS_WRITE;
check_access(state, adr, access)
}
u8 FASTCALL MMU_read8_acl(NDS_state *state, u32 proc, u32 adr, u32 access)
{
/* on arm9 we need to check the MPU regions */
if (proc == ARMCPU_ARM9)
check_access(state, adr, access);
return MMU_read8(state,proc,adr);
}
u16 FASTCALL MMU_read16_acl(NDS_state *state, u32 proc, u32 adr, u32 access)
{
/* on arm9 we need to check the MPU regions */
if (proc == ARMCPU_ARM9)
check_access(state, adr, access);
return MMU_read16(state,proc,adr);
}
u32 FASTCALL MMU_read32_acl(NDS_state *state, u32 proc, u32 adr, u32 access)
{
/* on arm9 we need to check the MPU regions */
if (proc == ARMCPU_ARM9)
check_access(state, adr, access);
return MMU_read32(state,proc,adr);
}
void FASTCALL MMU_write8_acl(NDS_state *state, u32 proc, u32 adr, u8 val)
{
/* check MPU region on ARM9 */
if (proc == ARMCPU_ARM9)
check_access_write(state,adr);
MMU_write8(state,proc,adr,val);
}
void FASTCALL MMU_write16_acl(NDS_state *state, u32 proc, u32 adr, u16 val)
{
/* check MPU region on ARM9 */
if (proc == ARMCPU_ARM9)
check_access_write(state,adr);
MMU_write16(state,proc,adr,val) ;
}
void FASTCALL MMU_write32_acl(NDS_state *state, u32 proc, u32 adr, u32 val)
{
/* check MPU region on ARM9 */
if (proc == ARMCPU_ARM9)
check_access_write(state,adr);
MMU_write32(state,proc,adr,val) ;
}
#endif
#ifdef PROFILE_MEMORY_ACCESS
#define PROFILE_PREFETCH 0
#define PROFILE_READ 1
#define PROFILE_WRITE 2
struct mem_access_profile {
u64 num_accesses;
u32 address_mask;
u32 masked_value;
};
#define PROFILE_NUM_MEM_ACCESS_PROFILES 4
static u64 profile_num_accesses[2][3];
static u64 profile_unknown_addresses[2][3];
static struct mem_access_profile
profile_memory_accesses[2][3][PROFILE_NUM_MEM_ACCESS_PROFILES];
static void
setup_profiling( void) {
int i;
for ( i = 0; i < 2; i++) {
int access_type;
for ( access_type = 0; access_type < 3; access_type++) {
profile_num_accesses[i][access_type] = 0;
profile_unknown_addresses[i][access_type] = 0;
/*
* Setup the access testing structures
*/
profile_memory_accesses[i][access_type][0].address_mask = 0x0e000000;
profile_memory_accesses[i][access_type][0].masked_value = 0x00000000;
profile_memory_accesses[i][access_type][0].num_accesses = 0;
/* main memory */
profile_memory_accesses[i][access_type][1].address_mask = 0x0f000000;
profile_memory_accesses[i][access_type][1].masked_value = 0x02000000;
profile_memory_accesses[i][access_type][1].num_accesses = 0;
/* shared memory */
profile_memory_accesses[i][access_type][2].address_mask = 0x0f800000;
profile_memory_accesses[i][access_type][2].masked_value = 0x03000000;
profile_memory_accesses[i][access_type][2].num_accesses = 0;
/* arm7 memory */
profile_memory_accesses[i][access_type][3].address_mask = 0x0f800000;
profile_memory_accesses[i][access_type][3].masked_value = 0x03800000;
profile_memory_accesses[i][access_type][3].num_accesses = 0;
}
}
}
static void
profile_memory_access( int arm9, u32 adr, int access_type) {
static int first = 1;
int mem_profile;
int address_found = 0;
if ( first) {
setup_profiling();
first = 0;
}
profile_num_accesses[arm9][access_type] += 1;
for ( mem_profile = 0;
mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES &&
!address_found;
mem_profile++) {
if ( (adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask) ==
profile_memory_accesses[arm9][access_type][mem_profile].masked_value) {
/*printf( "adr %08x mask %08x res %08x expected %08x\n",
adr,
profile_memory_accesses[arm9][access_type][mem_profile].address_mask,
adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask,
profile_memory_accesses[arm9][access_type][mem_profile].masked_value);*/
address_found = 1;
profile_memory_accesses[arm9][access_type][mem_profile].num_accesses += 1;
}
}
if ( !address_found) {
profile_unknown_addresses[arm9][access_type] += 1;
}
}
static const char *access_type_strings[] = {
"prefetch",
"read ",
"write "
};
void
print_memory_profiling( void) {
int arm;
printf("------ Memory access profile ------\n");
for ( arm = 0; arm < 2; arm++) {
int access_type;
for ( access_type = 0; access_type < 3; access_type++) {
int mem_profile;
printf("ARM%c: num of %s %lld\n",
arm ? '9' : '7',
access_type_strings[access_type],
profile_num_accesses[arm][access_type]);
for ( mem_profile = 0;
mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES;
mem_profile++) {
printf( "address %08x: %lld\n",
profile_memory_accesses[arm][access_type][mem_profile].masked_value,
profile_memory_accesses[arm][access_type][mem_profile].num_accesses);
}
printf( "unknown addresses %lld\n",
profile_unknown_addresses[arm][access_type]);
printf( "\n");
}
}
printf("------ End of Memory access profile ------\n\n");
}
#else
void
print_memory_profiling( void) {
}
#endif /* End of PROFILE_MEMORY_ACCESS area */
#ifdef GDB_STUB
static u16 FASTCALL
arm9_prefetch16( NDS_state *state, void *data, u32 adr) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 1, adr, PROFILE_PREFETCH);
#endif
#ifdef EARLY_MEMORY_ACCESS
if((adr & ~0x3FFF) == state->MMU->DTCMRegion)
{
/* Returns data from DTCM (ARM9 only) */
return T1ReadWord(state->ARM9Mem->ARM9_DTCM, adr & 0x3FFF);
}
/* access to main memory */
if ( (adr & 0x0f000000) == 0x02000000) {
return T1ReadWord( state->MMU->MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
adr & state->MMU->MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
}
#endif
return MMU_read16( state, ARMCPU_ARM9, adr);
}
static u32 FASTCALL
arm9_prefetch32( NDS_state *state, void *data, u32 adr) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 1, adr, PROFILE_PREFETCH);
#endif
#ifdef EARLY_MEMORY_ACCESS
if((adr & ~0x3FFF) == state->MMU->DTCMRegion)
{
/* Returns data from DTCM (ARM9 only) */
return T1ReadLong(state->ARM9Mem->ARM9_DTCM, adr & 0x3FFF);
}
/* access to main memory */
if ( (adr & 0x0f000000) == 0x02000000) {
return T1ReadLong( state->MMU->MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
adr & state->MMU->MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
}
#endif
return MMU_read32( state, ARMCPU_ARM9, adr);
}
static u8 FASTCALL
arm9_read8( NDS_state *state, void *data, u32 adr) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 1, adr, PROFILE_READ);
#endif
#ifdef EARLY_MEMORY_ACCESS
if( (adr&(~0x3FFF)) == state->MMU->DTCMRegion)
{
return state->ARM9Mem->ARM9_DTCM[adr&0x3FFF];
}
/* access to main memory */
if ( (adr & 0x0f000000) == 0x02000000) {
return state->MMU->MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF]
[adr & state->MMU->MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]];
}
#endif
return MMU_read8( state, ARMCPU_ARM9, adr);
}
static u16 FASTCALL
arm9_read16( NDS_state *state, void *data, u32 adr) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 1, adr, PROFILE_READ);
#endif
#ifdef EARLY_MEMORY_ACCESS
if((adr & ~0x3FFF) == state->MMU->DTCMRegion)
{
/* Returns data from DTCM (ARM9 only) */
return T1ReadWord(state->ARM9Mem->ARM9_DTCM, adr & 0x3FFF);
}
/* access to main memory */
if ( (adr & 0x0f000000) == 0x02000000) {
return T1ReadWord( state->MMU->MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
adr & state->MMU->MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
}
#endif
return MMU_read16( state, ARMCPU_ARM9, adr);
}
static u32 FASTCALL
arm9_read32( NDS_state *state, void *data, u32 adr) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 1, adr, PROFILE_READ);
#endif
#ifdef EARLY_MEMORY_ACCESS
if((adr & ~0x3FFF) == state->MMU->DTCMRegion)
{
/* Returns data from DTCM (ARM9 only) */
return T1ReadLong(state->ARM9Mem->ARM9_DTCM, adr & 0x3FFF);
}
/* access to main memory */
if ( (adr & 0x0f000000) == 0x02000000) {
return T1ReadLong( state->MMU->MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
adr & state->MMU->MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
}
#endif
return MMU_read32( state, ARMCPU_ARM9, adr);
}
static void FASTCALL
arm9_write8(NDS_state *state, void *data, u32 adr, u8 val) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 1, adr, PROFILE_WRITE);
#endif
#ifdef EARLY_MEMORY_ACCESS
if( (adr & ~0x3FFF) == state->MMU->DTCMRegion)
{
/* Writes data in DTCM (ARM9 only) */
state->ARM9Mem->ARM9_DTCM[adr&0x3FFF] = val;
return ;
}
/* main memory */
if ( (adr & 0x0f000000) == 0x02000000) {
state->MMU->MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF]
[adr&state->MMU->MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF]] = val;
return;
}
#endif
MMU_write8( state, ARMCPU_ARM9, adr, val);
}
static void FASTCALL
arm9_write16(NDS_state *state, void *data, u32 adr, u16 val) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 1, adr, PROFILE_WRITE);
#endif
#ifdef EARLY_MEMORY_ACCESS
if((adr & ~0x3FFF) == state->MMU->DTCMRegion)
{
/* Writes in DTCM (ARM9 only) */
T1WriteWord(state->ARM9Mem->ARM9_DTCM, adr & 0x3FFF, val);
return;
}
/* main memory */
if ( (adr & 0x0f000000) == 0x02000000) {
T1WriteWord( state->MMU->MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF],
adr&state->MMU->MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF], val);
return;
}
#endif
MMU_write16( state, ARMCPU_ARM9, adr, val);
}
static void FASTCALL
arm9_write32(NDS_state *state, void *data, u32 adr, u32 val) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 1, adr, PROFILE_WRITE);
#endif
#ifdef EARLY_MEMORY_ACCESS
if((adr & ~0x3FFF) == state->MMU->DTCMRegion)
{
/* Writes in DTCM (ARM9 only) */
T1WriteLong(state->ARM9Mem->ARM9_DTCM, adr & 0x3FFF, val);
return;
}
/* main memory */
if ( (adr & 0x0f000000) == 0x02000000) {
T1WriteLong( state->MMU->MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF],
adr&state->MMU->MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF], val);
return;
}
#endif
MMU_write32( state, ARMCPU_ARM9, adr, val);
}
static u16 FASTCALL
arm7_prefetch16( NDS_state *state, void *data, u32 adr) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 0, adr, PROFILE_PREFETCH);
#endif
#ifdef EARLY_MEMORY_ACCESS
/* ARM7 private memory */
if ( (adr & 0x0f800000) == 0x03800000) {
T1ReadWord(state->MMU->MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF],
adr & state->MMU->MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]);
}
#endif
return MMU_read16( state, ARMCPU_ARM7, adr);
}
static u32 FASTCALL
arm7_prefetch32( NDS_state *state, void *data, u32 adr) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 0, adr, PROFILE_PREFETCH);
#endif
#ifdef EARLY_MEMORY_ACCESS
/* ARM7 private memory */
if ( (adr & 0x0f800000) == 0x03800000) {
T1ReadLong(state->MMU->MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF],
adr & state->MMU->MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]);
}
#endif
return MMU_read32( state, ARMCPU_ARM7, adr);
}
static u8 FASTCALL
arm7_read8( NDS_state *state, void *data, u32 adr) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 0, adr, PROFILE_READ);
#endif
return MMU_read8( state, ARMCPU_ARM7, adr);
}
static u16 FASTCALL
arm7_read16( NDS_state *state, void *data, u32 adr) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 0, adr, PROFILE_READ);
#endif
return MMU_read16( state, ARMCPU_ARM7, adr);
}
static u32 FASTCALL
arm7_read32( NDS_state *state, void *data, u32 adr) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 0, adr, PROFILE_READ);
#endif
return MMU_read32( state, ARMCPU_ARM7, adr);
}
static void FASTCALL
arm7_write8(NDS_state *state, void *data, u32 adr, u8 val) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 0, adr, PROFILE_WRITE);
#endif
MMU_write8( state, ARMCPU_ARM7, adr, val);
}
static void FASTCALL
arm7_write16(NDS_state *state, void *data, u32 adr, u16 val) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 0, adr, PROFILE_WRITE);
#endif
MMU_write16( state, ARMCPU_ARM7, adr, val);
}
static void FASTCALL
arm7_write32(NDS_state *state, void *data, u32 adr, u32 val) {
#ifdef PROFILE_MEMORY_ACCESS
profile_memory_access( 0, adr, PROFILE_WRITE);
#endif
MMU_write32( state, ARMCPU_ARM7, adr, val);
}
/*
* the base memory interfaces
*/
struct armcpu_memory_iface arm9_base_memory_iface = {
#ifdef __GNUC__
.prefetch32 = arm9_prefetch32,
.prefetch16 = arm9_prefetch16,
.read8 = arm9_read8,
.read16 = arm9_read16,
.read32 = arm9_read32,
.write8 = arm9_write8,
.write16 = arm9_write16,
.write32 = arm9_write32
#else
arm9_prefetch32,
arm9_prefetch16,
arm9_read8,
arm9_read16,
arm9_read32,
arm9_write8,
arm9_write16,
arm9_write32
#endif
};
struct armcpu_memory_iface arm7_base_memory_iface = {
#ifdef __GNUC__
.prefetch32 = arm7_prefetch32,
.prefetch16 = arm7_prefetch16,
.read8 = arm7_read8,
.read16 = arm7_read16,
.read32 = arm7_read32,
.write8 = arm7_write8,
.write16 = arm7_write16,
.write32 = arm7_write32
#else
arm7_prefetch32,
arm7_prefetch16,
arm7_read8,
arm7_read16,
arm7_read32,
arm7_write8,
arm7_write16,
arm7_write32
#endif
};
/*
* The direct memory interface for the ARM9.
* This avoids the ARM9 protection unit when accessing
* memory.
*/
struct armcpu_memory_iface arm9_direct_memory_iface = {
#ifdef __GNUC__
/* the prefetch is not used */
.prefetch32 = NULL,
.prefetch16 = NULL,
.read8 = arm9_read8,
.read16 = arm9_read16,
.read32 = arm9_read32,
.write8 = arm9_write8,
.write16 = arm9_write16,
.write32 = arm9_write32
#else
NULL,
NULL,
arm9_read8,
arm9_read16,
arm9_read32,
arm9_write8,
arm9_write16,
arm9_write32
#endif
};
#endif