/* * Project 64 - A Nintendo 64 emulator. * * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and * Jabo (jabo@emulation64.com). * * pj64 homepage: www.pj64.net * * Permission to use, copy, modify and distribute Project64 in both binary and * source form, for non-commercial purposes, is hereby granted without fee, * providing that this license information and copyright notice appear with * all copies and any derived work. * * This software is provided 'as-is', without any express or implied * warranty. In no event shall the authors be held liable for any damages * arising from the use of this software. * * Project64 is freeware for PERSONAL USE only. Commercial users should * seek permission of the copyright holders first. Commercial use includes * charging money for Project64 or software derived from Project64. * * The copyright holders request that bug fixes and improvements to the code * should be forwarded to them so if they want them. * */ #include #include #include #include "usf.h" #include "main.h" #include "cpu.h" #include "audio.h" #include "rsp.h" #include "usf_internal.h" uint8_t * PageROM(usf_state_t * state, uint32_t addr) { return (state->ROMPages[addr/0x10000])?state->ROMPages[addr/0x10000]+(addr%0x10000):&state->EmptySpace; } void * large_alloc(size_t); void large_free(void *, size_t); #ifdef _WIN32 #include void * large_alloc(size_t size) { return VirtualAlloc( NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); } void large_free(void * p, size_t size) { VirtualFree( p, size, MEM_RELEASE ); } #else #include #ifdef __APPLE__ #define MAP_ANONYMOUS MAP_ANON #endif void * large_alloc(size_t size) { return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); } void large_free(void * p, size_t size) { munmap( p, size ); } #endif int32_t Allocate_Memory ( void * state ) { //uint32_t i = 0; //RdramSize = 0x800000; // Allocate the N64MEM and TLB_Map so that they are in each others 4GB range // Also put the registers there :) // the mmap technique works craptacular when the regions don't overlay USF_STATE->MemChunk = (uint8_t *) large_alloc( 0x100000 * sizeof(uintptr_t) + 0x1D000 + USF_STATE->RdramSize ); USF_STATE->TLB_Map = (uintptr_t*)USF_STATE->MemChunk; if (USF_STATE->TLB_Map == NULL) { return 0; } memset(USF_STATE->TLB_Map, 0, 0x100000 * sizeof(uintptr_t) + 0x10000); USF_STATE->N64MEM = USF_STATE->MemChunk + 0x100000 * sizeof(uintptr_t) + 0x10000; if(USF_STATE->N64MEM == NULL) { DisplayError(USF_STATE, "Failed to allocate N64MEM"); return 0; } //memset(state->N64MEM, 0, USF_STATE->RdramSize); USF_STATE->NOMEM = USF_STATE->N64MEM + USF_STATE->RdramSize; //if(USF_STATE->RdramSize == 0x400000) //{ // munmap(N64MEM + 0x400000, 0x400000); //} USF_STATE->Registers = (N64_REGISTERS *)((uintptr_t)USF_STATE->MemChunk + 0x100000 * sizeof(uintptr_t)); //USF_STATE->TLBLoadAddress = (uint32_t *)((uintptr_t)USF_STATE->Registers + 0x500); //USF_STATE->Timers = (SYSTEM_TIMERS*)(USF_STATE->TLBLoadAddress + 4); USF_STATE->Timers = (SYSTEM_TIMERS*)((uintptr_t)USF_STATE->Registers + 0x500); USF_STATE->WaitMode = (uint32_t *)(USF_STATE->Timers + sizeof(SYSTEM_TIMERS)); USF_STATE->CPU_Action = (CPU_ACTION *)(USF_STATE->WaitMode + 4); //USF_STATE->RSP_GPR = (struct RSP_GPR_TYPE *)(USF_STATE->CPU_Action + sizeof(CPU_ACTION)); //USF_STATE->DMEM = (uint8_t *)(USF_STATE->RSP_GPR + (32 * 16)); USF_STATE->DMEM = (uint8_t *)(USF_STATE->CPU_Action + sizeof(CPU_ACTION)); //state->RSP_ACCUM = (struct RSP_ACCUM_TYPE *)(USF_STATE->DMEM + 0x2000); USF_STATE->RDRAM = (uint8_t *)(USF_STATE->N64MEM); USF_STATE->IMEM = USF_STATE->DMEM + 0x1000; USF_STATE->MemoryState = 1; return 1; } int PreAllocate_Memory(usf_state_t * state) { int i = 0; // Moved the savestate allocation here :) (for better management later) state->savestatespace = (uint8_t *) malloc(0x80275C); if(state->savestatespace == 0) return 0; memset(state->savestatespace, 0, 0x80275C); for (i = 0; i < 0x400; i++) { state->ROMPages[i] = 0; } return 1; } void Release_Memory ( usf_state_t * state ) { uint32_t i; for (i = 0; i < 0x400; i++) { if (state->ROMPages[i]) { free(state->ROMPages[i]); state->ROMPages[i] = 0; } } //printf("Freeing memory\n"); state->MemoryState = 0; if (state->MemChunk != 0) { large_free( state->MemChunk, 0x100000 * sizeof(uintptr_t) + 0x1D000 + state->RdramSize ); state->MemChunk=0; } if(state->cpu_hle_entries) free(state->cpu_hle_entries); state->cpu_hle_entries = NULL; if(state->savestatespace) free(state->savestatespace); state->savestatespace = NULL; } int32_t r4300i_LB_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t * Value, uint32_t SignExtend ) { if (PAddr >= 0x10000000 && PAddr < 0x16000000) { if (state->WrittenToRom) { return 0; } if ((PAddr & 2) == 0) { PAddr = (PAddr + 4) ^ 2; } if ((PAddr - 0x10000000) < state->RomFileSize) { if (SignExtend) { *Value = (char)*PageROM(state, (PAddr - 0x10000000)^3); } else { *Value = *PageROM(state, (PAddr - 0x10000000)^3); } return 1; } else { *Value = 0; return 0; } } switch (PAddr & 0xFFF00000) { default: * Value = 0; return 0; break; } return 1; } uint32_t r4300i_LB_VAddr ( usf_state_t * state, uint32_t VAddr, uint8_t * Value ) { uintptr_t address; address = state->TLB_Map[VAddr >> 12]; if (address == 0) { return 0; } *Value = *(uint8_t *)(address + (VAddr ^ 3)); return 1; } uint32_t r4300i_LD_VAddr ( usf_state_t * state, uint32_t VAddr, uint64_t * Value ) { uintptr_t address; address = state->TLB_Map[VAddr >> 12]; if (address == 0) { return 0; } if (address + VAddr + 7 - (uintptr_t)state->N64MEM >= state->RdramSize) { *((uint32_t *)(Value) + 1) = 0; *((uint32_t *)(Value)) = 0; return 1; } *((uint32_t *)(Value) + 1) = *(uint32_t *)(address + VAddr); *((uint32_t *)(Value)) = *(uint32_t *)(address + VAddr + 4); return 1; } int32_t r4300i_LH_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t * Value, int32_t SignExtend ) { (void)state; (void)SignExtend; switch (PAddr & 0xFFF00000) { default: * Value = 0; return 0; break; } return 1; } uint32_t r4300i_LH_VAddr ( usf_state_t * state, uint32_t VAddr, uint16_t * Value ) { uintptr_t address; address = state->TLB_Map[VAddr >> 12]; if (address == 0) return 0; if (address + (VAddr ^ 2) + 1 - (uintptr_t)state->N64MEM >= state->RdramSize) { *Value = 0; return 1; } *Value = *(uint16_t *)(address + (VAddr ^ 2)); return 1; } int32_t r4300i_LW_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t * Value ) { if (PAddr >= 0x10000000 && PAddr < 0x16000000) { if (state->WrittenToRom) { *Value = state->WroteToRom; //LogMessage("%X: Read crap from Rom %X from %X",PROGRAM_COUNTER,*Value,PAddr); state->WrittenToRom = 0; return 1; } if ((PAddr - 0x10000000) < state->RomFileSize) { *Value = *(uint32_t *)PageROM(state, (PAddr - 0x10000000)); return 1; } else { *Value = PAddr & 0xFFFF; *Value = (*Value << 16) | *Value; return 0; } } switch (PAddr & 0xFFF00000) { case 0x03F00000: switch (PAddr) { case 0x03F00000: * Value = RDRAM_CONFIG_REG; break; case 0x03F00004: * Value = RDRAM_DEVICE_ID_REG; break; case 0x03F00008: * Value = RDRAM_DELAY_REG; break; case 0x03F0000C: * Value = RDRAM_MODE_REG; break; case 0x03F00010: * Value = RDRAM_REF_INTERVAL_REG; break; case 0x03F00014: * Value = RDRAM_REF_ROW_REG; break; case 0x03F00018: * Value = RDRAM_RAS_INTERVAL_REG; break; case 0x03F0001C: * Value = RDRAM_MIN_INTERVAL_REG; break; case 0x03F00020: * Value = RDRAM_ADDR_SELECT_REG; break; case 0x03F00024: * Value = RDRAM_DEVICE_MANUF_REG; break; default: * Value = 0; return 0; } break; case 0x04000000: switch (PAddr) { case 0x04040010: *Value = SP_STATUS_REG; break; case 0x04040014: *Value = SP_DMA_FULL_REG; break; case 0x04040018: *Value = SP_DMA_BUSY_REG; break; case 0x04080000: *Value = SP_PC_REG; break; default: * Value = 0; return 0; } break; case 0x04100000: switch (PAddr) { case 0x0410000C: *Value = DPC_STATUS_REG; break; case 0x04100010: *Value = DPC_CLOCK_REG; break; case 0x04100014: *Value = DPC_BUFBUSY_REG; break; case 0x04100018: *Value = DPC_PIPEBUSY_REG; break; case 0x0410001C: *Value = DPC_TMEM_REG; break; default: * Value = 0; return 0; } break; case 0x04300000: switch (PAddr) { case 0x04300000: * Value = MI_MODE_REG; break; case 0x04300004: * Value = MI_VERSION_REG; break; case 0x04300008: * Value = MI_INTR_REG; break; case 0x0430000C: * Value = MI_INTR_MASK_REG; break; default: * Value = 0; return 0; } break; case 0x04400000: switch (PAddr) { case 0x04400000: *Value = VI_STATUS_REG; break; case 0x04400004: *Value = VI_ORIGIN_REG; break; case 0x04400008: *Value = VI_WIDTH_REG; break; case 0x0440000C: *Value = VI_INTR_REG; break; case 0x04400010: *Value = 0; break; case 0x04400014: *Value = VI_BURST_REG; break; case 0x04400018: *Value = VI_V_SYNC_REG; break; case 0x0440001C: *Value = VI_H_SYNC_REG; break; case 0x04400020: *Value = VI_LEAP_REG; break; case 0x04400024: *Value = VI_H_START_REG; break; case 0x04400028: *Value = VI_V_START_REG ; break; case 0x0440002C: *Value = VI_V_BURST_REG; break; case 0x04400030: *Value = VI_X_SCALE_REG; break; case 0x04400034: *Value = VI_Y_SCALE_REG; break; default: * Value = 0; return 0; } break; case 0x04500000: switch (PAddr) { case 0x04500004: *Value = AiReadLength(state); break; case 0x0450000C: *Value = AI_STATUS_REG; break; default: * Value = 0; return 0; } break; case 0x04600000: switch (PAddr) { case 0x04600010: *Value = PI_STATUS_REG; break; case 0x04600014: *Value = PI_DOMAIN1_REG; break; case 0x04600018: *Value = PI_BSD_DOM1_PWD_REG; break; case 0x0460001C: *Value = PI_BSD_DOM1_PGS_REG; break; case 0x04600020: *Value = PI_BSD_DOM1_RLS_REG; break; case 0x04600024: *Value = PI_DOMAIN2_REG; break; case 0x04600028: *Value = PI_BSD_DOM2_PWD_REG; break; case 0x0460002C: *Value = PI_BSD_DOM2_PGS_REG; break; case 0x04600030: *Value = PI_BSD_DOM2_RLS_REG; break; default: * Value = 0; return 0; } break; case 0x04700000: switch (PAddr) { case 0x04700000: * Value = RI_MODE_REG; break; case 0x04700004: * Value = RI_CONFIG_REG; break; case 0x04700008: * Value = RI_CURRENT_LOAD_REG; break; case 0x0470000C: * Value = RI_SELECT_REG; break; case 0x04700010: * Value = RI_REFRESH_REG; break; case 0x04700014: * Value = RI_LATENCY_REG; break; case 0x04700018: * Value = RI_RERROR_REG; break; case 0x0470001C: * Value = RI_WERROR_REG; break; default: * Value = 0; return 0; } break; case 0x04800000: switch (PAddr) { case 0x04800018: *Value = SI_STATUS_REG; break; default: *Value = 0; return 0; } break; case 0x05000000: *Value = PAddr & 0xFFFF; *Value = (*Value << 16) | *Value; return 0; case 0x08000000: *Value = 0; break; default: *Value = PAddr & 0xFFFF; *Value = (*Value << 16) | *Value; return 0; break; } return 1; } void r4300i_LW_PAddr ( usf_state_t * state, uint32_t PAddr, uint32_t * Value ) { *Value = *(uint32_t *)(state->N64MEM+PAddr); } uint32_t r4300i_LW_VAddr ( usf_state_t * state, uint32_t VAddr, uint32_t * Value ) { uintptr_t address = state->TLB_Map[VAddr >> 12]; if (address == 0) return 0; address += VAddr; if((address - (uintptr_t)state->RDRAM) > state->RdramSize) { address = address - (uintptr_t)state->RDRAM; return r4300i_LW_NonMemory(state, (uint32_t) address, Value); } *Value = *(uint32_t *)address; return 1; } int32_t r4300i_SB_NonMemory ( usf_state_t * state, uint32_t PAddr, uint8_t Value ) { switch (PAddr & 0xFFF00000) { case 0x00000000: case 0x00100000: case 0x00200000: case 0x00300000: case 0x00400000: case 0x00500000: case 0x00600000: case 0x00700000: if (PAddr < state->RdramSize) { *(uint8_t *)(state->N64MEM+PAddr) = Value; } break; default: return 0; break; } return 1; } uint32_t r4300i_SB_VAddr ( usf_state_t * state, uint32_t VAddr, uint8_t Value ) { uintptr_t address; address = state->TLB_Map[VAddr >> 12]; if (address == 0) { return 0; } if (address + (VAddr ^ 3) - (uintptr_t)state->N64MEM < state->RdramSize) *(uint8_t *)(address + (VAddr ^ 3)) = Value; return 1; } int32_t r4300i_SH_NonMemory ( usf_state_t * state, uint32_t PAddr, uint16_t Value ) { switch (PAddr & 0xFFF00000) { case 0x00000000: case 0x00100000: case 0x00200000: case 0x00300000: case 0x00400000: case 0x00500000: case 0x00600000: case 0x00700000: if (PAddr < state->RdramSize) { *(uint16_t *)(state->N64MEM+PAddr) = Value; } break; default: return 0; break; } return 1; } uint32_t r4300i_SD_VAddr ( usf_state_t * state, uint32_t VAddr, uint64_t Value ) { uintptr_t address; address = state->TLB_Map[VAddr >> 12]; if (address == 0) { return 0; } if (address + VAddr + 7 - (uintptr_t)state->N64MEM < state->RdramSize) { *(uint32_t *)(address + VAddr) = *((uint32_t *)(&Value) + 1); *(uint32_t *)(address + VAddr + 4) = *((uint32_t *)(&Value)); } return 1; } uint32_t r4300i_SH_VAddr ( usf_state_t * state, uint32_t VAddr, uint16_t Value ) { uintptr_t address; address = state->TLB_Map[VAddr >> 12]; if (address == 0) { return 0; } if (address + 1 + (VAddr ^ 2) - (uintptr_t)state->N64MEM < state->RdramSize) *(uint16_t *)(address + (VAddr ^ 2)) = Value; return 1; } int32_t r4300i_SW_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t Value ) { if (PAddr >= 0x10000000 && PAddr < 0x16000000) { if ((PAddr - 0x10000000) < state->RomFileSize) { state->WrittenToRom = 1; state->WroteToRom = Value; } else { return 0; } } switch (PAddr & 0xFFF00000) { case 0x00000000: case 0x00100000: case 0x00200000: case 0x00300000: case 0x00400000: case 0x00500000: case 0x00600000: case 0x00700000: if (PAddr < state->RdramSize) { *(uint32_t *)(state->N64MEM+PAddr) = Value; } break; case 0x03F00000: switch (PAddr) { case 0x03F00000: RDRAM_CONFIG_REG = Value; break; case 0x03F00004: RDRAM_DEVICE_ID_REG = Value; break; case 0x03F00008: RDRAM_DELAY_REG = Value; break; case 0x03F0000C: RDRAM_MODE_REG = Value; break; case 0x03F00010: RDRAM_REF_INTERVAL_REG = Value; break; case 0x03F00014: RDRAM_REF_ROW_REG = Value; break; case 0x03F00018: RDRAM_RAS_INTERVAL_REG = Value; break; case 0x03F0001C: RDRAM_MIN_INTERVAL_REG = Value; break; case 0x03F00020: RDRAM_ADDR_SELECT_REG = Value; break; case 0x03F00024: RDRAM_DEVICE_MANUF_REG = Value; break; case 0x03F04004: break; case 0x03F08004: break; case 0x03F80004: break; case 0x03F80008: break; case 0x03F8000C: break; case 0x03F80014: break; default: return 0; } break; case 0x04000000: if (PAddr < 0x04002000) { *(uint32_t *)(state->N64MEM+PAddr) = Value; return 1; } switch (PAddr) { case 0x04040000: SP_MEM_ADDR_REG = Value; break; case 0x04040004: SP_DRAM_ADDR_REG = Value; break; case 0x04040008: SP_RD_LEN_REG = Value; SP_DMA_READ(state); break; case 0x0404000C: SP_WR_LEN_REG = Value; SP_DMA_WRITE(state); break; case 0x04040010: if ( ( Value & SP_CLR_HALT ) != 0) { SP_STATUS_REG &= ~SP_STATUS_HALT; } if ( ( Value & SP_SET_HALT ) != 0) { SP_STATUS_REG |= SP_STATUS_HALT; } if ( ( Value & SP_CLR_BROKE ) != 0) { SP_STATUS_REG &= ~SP_STATUS_BROKE; } if ( ( Value & SP_CLR_INTR ) != 0) { MI_INTR_REG &= ~MI_INTR_SP; CheckInterrupts(state); } if ( ( Value & SP_CLR_SSTEP ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SSTEP; } if ( ( Value & SP_SET_SSTEP ) != 0) { SP_STATUS_REG |= SP_STATUS_SSTEP; } if ( ( Value & SP_CLR_INTR_BREAK ) != 0) { SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; } if ( ( Value & SP_SET_INTR_BREAK ) != 0) { SP_STATUS_REG |= SP_STATUS_INTR_BREAK; } if ( ( Value & SP_CLR_SIG0 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG0; } if ( ( Value & SP_SET_SIG0 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG0; } if ( ( Value & SP_CLR_SIG1 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG1; } if ( ( Value & SP_SET_SIG1 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG1; } if ( ( Value & SP_CLR_SIG2 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG2; } if ( ( Value & SP_SET_SIG2 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG2; } if ( ( Value & SP_CLR_SIG3 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG3; } if ( ( Value & SP_SET_SIG3 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG3; } if ( ( Value & SP_CLR_SIG4 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG4; } if ( ( Value & SP_SET_SIG4 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG4; } if ( ( Value & SP_CLR_SIG5 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG5; } if ( ( Value & SP_SET_SIG5 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG5; } if ( ( Value & SP_CLR_SIG6 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG6; } if ( ( Value & SP_SET_SIG6 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG6; } if ( ( Value & SP_CLR_SIG7 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG7; } if ( ( Value & SP_SET_SIG7 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG7; } RunRsp(state); break; case 0x0404001C: SP_SEMAPHORE_REG = 0; break; case 0x04080000: SP_PC_REG = Value & 0xFFC; break; default: return 0; } break; case 0x04100000: switch (PAddr) { case 0x04100000: DPC_START_REG = Value; DPC_CURRENT_REG = Value; break; case 0x04100004: DPC_END_REG = Value; break; case 0x04100008: DPC_CURRENT_REG = Value; break; case 0x0410000C: if ( ( Value & DPC_CLR_XBUS_DMEM_DMA ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_XBUS_DMEM_DMA; } if ( ( Value & DPC_SET_XBUS_DMEM_DMA ) != 0) { DPC_STATUS_REG |= DPC_STATUS_XBUS_DMEM_DMA; } if ( ( Value & DPC_CLR_FREEZE ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_FREEZE; } if ( ( Value & DPC_SET_FREEZE ) != 0) { DPC_STATUS_REG |= DPC_STATUS_FREEZE; } if ( ( Value & DPC_CLR_FLUSH ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_FLUSH; } if ( ( Value & DPC_SET_FLUSH ) != 0) { DPC_STATUS_REG |= DPC_STATUS_FLUSH; } if ( ( Value & DPC_CLR_FREEZE ) != 0) { if ( ( SP_STATUS_REG & SP_STATUS_HALT ) == 0) { if ( ( SP_STATUS_REG & SP_STATUS_BROKE ) == 0 ) { RunRsp(state); } } } break; default: return 0; } break; case 0x04300000: switch (PAddr) { case 0x04300000: MI_MODE_REG &= ~0x7F; MI_MODE_REG |= (Value & 0x7F); if ( ( Value & MI_CLR_INIT ) != 0 ) { MI_MODE_REG &= ~MI_MODE_INIT; } if ( ( Value & MI_SET_INIT ) != 0 ) { MI_MODE_REG |= MI_MODE_INIT; } if ( ( Value & MI_CLR_EBUS ) != 0 ) { MI_MODE_REG &= ~MI_MODE_EBUS; } if ( ( Value & MI_SET_EBUS ) != 0 ) { MI_MODE_REG |= MI_MODE_EBUS; } if ( ( Value & MI_CLR_DP_INTR ) != 0 ) { MI_INTR_REG &= ~MI_INTR_DP; CheckInterrupts(state); } if ( ( Value & MI_CLR_RDRAM ) != 0 ) { MI_MODE_REG &= ~MI_MODE_RDRAM; } if ( ( Value & MI_SET_RDRAM ) != 0 ) { MI_MODE_REG |= MI_MODE_RDRAM; } break; case 0x0430000C: if ( ( Value & MI_INTR_MASK_CLR_SP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SP; } if ( ( Value & MI_INTR_MASK_SET_SP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SP; } if ( ( Value & MI_INTR_MASK_CLR_SI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SI; } if ( ( Value & MI_INTR_MASK_SET_SI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SI; } if ( ( Value & MI_INTR_MASK_CLR_AI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_AI; } if ( ( Value & MI_INTR_MASK_SET_AI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_AI; } if ( ( Value & MI_INTR_MASK_CLR_VI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_VI; } if ( ( Value & MI_INTR_MASK_SET_VI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_VI; } if ( ( Value & MI_INTR_MASK_CLR_PI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_PI; } if ( ( Value & MI_INTR_MASK_SET_PI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_PI; } if ( ( Value & MI_INTR_MASK_CLR_DP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_DP; } if ( ( Value & MI_INTR_MASK_SET_DP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_DP; } break; default: return 0; } break; case 0x04400000: switch (PAddr) { case 0x04400000: //if (VI_STATUS_REG != Value) { VI_STATUS_REG = Value; // if (ViStatusChanged != NULL ) { ViStatusChanged(); } //} break; case 0x04400004: VI_ORIGIN_REG = (Value & 0xFFFFFF); //if (UpdateScreen != NULL ) { UpdateScreen(); } break; case 0x04400008: //if (VI_WIDTH_REG != Value) { VI_WIDTH_REG = Value; // if (ViWidthChanged != NULL ) { ViWidthChanged(); } //} break; case 0x0440000C: VI_INTR_REG = Value; break; case 0x04400010: MI_INTR_REG &= ~MI_INTR_VI; CheckInterrupts(state); break; case 0x04400014: VI_BURST_REG = Value; break; case 0x04400018: VI_V_SYNC_REG = Value; break; case 0x0440001C: VI_H_SYNC_REG = Value; break; case 0x04400020: VI_LEAP_REG = Value; break; case 0x04400024: VI_H_START_REG = Value; break; case 0x04400028: VI_V_START_REG = Value; break; case 0x0440002C: VI_V_BURST_REG = Value; break; case 0x04400030: VI_X_SCALE_REG = Value; break; case 0x04400034: VI_Y_SCALE_REG = Value; break; default: return 0; } break; case 0x04500000: switch (PAddr) { case 0x04500000: AI_DRAM_ADDR_REG = Value; break; case 0x04500004: AI_LEN_REG = Value; AiLenChanged(state); break; case 0x04500008: AI_CONTROL_REG = (Value & 0x1); break; case 0x0450000C: /* Clear Interrupt */; MI_INTR_REG &= ~MI_INTR_AI; state->AudioIntrReg &= ~MI_INTR_AI; CheckInterrupts(state); break; case 0x04500010: AiDacrateChanged(state, Value); break; case 0x04500014: AI_BITRATE_REG = Value; break; default: return 0; } break; case 0x04600000: switch (PAddr) { case 0x04600000: PI_DRAM_ADDR_REG = Value; break; case 0x04600004: PI_CART_ADDR_REG = Value; break; case 0x04600008: PI_RD_LEN_REG = Value; PI_DMA_READ(state); break; case 0x0460000C: PI_WR_LEN_REG = Value; PI_DMA_WRITE(state); break; case 0x04600010: //if ((Value & PI_SET_RESET) != 0 ) { DisplayError(state, "reset Controller"); } if ((Value & PI_CLR_INTR) != 0 ) { MI_INTR_REG &= ~MI_INTR_PI; CheckInterrupts(state); } break; case 0x04600014: PI_DOMAIN1_REG = (Value & 0xFF); break; case 0x04600018: PI_BSD_DOM1_PWD_REG = (Value & 0xFF); break; case 0x0460001C: PI_BSD_DOM1_PGS_REG = (Value & 0xFF); break; case 0x04600020: PI_BSD_DOM1_RLS_REG = (Value & 0xFF); break; default: return 0; } break; case 0x04700000: switch (PAddr) { case 0x04700000: RI_MODE_REG = Value; break; case 0x04700004: RI_CONFIG_REG = Value; break; case 0x04700008: RI_CURRENT_LOAD_REG = Value; break; case 0x0470000C: RI_SELECT_REG = Value; break; case 0x04700010: RI_REFRESH_REG = Value; break; case 0x04700014: RI_LATENCY_REG = Value; break; case 0x04700018: RI_RERROR_REG = Value; break; case 0x0470001C: RI_WERROR_REG = Value; break; default: return 0; } break; case 0x04800000: switch (PAddr) { case 0x04800000: SI_DRAM_ADDR_REG = Value; break; case 0x04800004: SI_PIF_ADDR_RD64B_REG = Value; SI_DMA_READ (state); break; case 0x04800010: SI_PIF_ADDR_WR64B_REG = Value; SI_DMA_WRITE(state); break; case 0x04800018: MI_INTR_REG &= ~MI_INTR_SI; SI_STATUS_REG &= ~SI_STATUS_INTERRUPT; CheckInterrupts(state); break; default: return 0; } break; case 0x08000000: if (PAddr != 0x08010000) { return 0; } break; case 0x1FC00000: if (PAddr < 0x1FC007C0) { return 0; } else if (PAddr < 0x1FC00800) { if (PAddr == 0x1FC007FC) { PifRamWrite(state); } return 1; } return 0; break; default: return 0; break; } return 1; } uint32_t r4300i_SW_VAddr ( usf_state_t * state, uint32_t VAddr, uint32_t Value ) { uintptr_t address; address = state->TLB_Map[VAddr >> 12]; if (address == 0) { return 0; } address = (address + VAddr); if((address - (uintptr_t)state->RDRAM) > state->RdramSize) { address = address - (uintptr_t)state->RDRAM; return r4300i_SW_NonMemory(state, (uint32_t) address, Value); } *(uint32_t *)address = Value; return 1; } void memcpyn642n64(usf_state_t * state, uint32_t dest, uint32_t src, uint32_t len) { uint32_t i; uint32_t temp; for (i = 0; i < len; i += 4) { uintptr_t dstAddr = state->TLB_Map[(dest + i) >> 12]; uintptr_t srcAddr = state->TLB_Map[(src + i) >> 12]; if (srcAddr) temp = *(uint32_t*)(srcAddr + src + i); else temp = 0; if (dstAddr) *(uint32_t*)(dstAddr + dest + i) = temp; } }