diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ARM.cpp | 22 | ||||
-rw-r--r-- | src/DSi.cpp | 37 | ||||
-rw-r--r-- | src/DSi_Camera.cpp | 220 | ||||
-rw-r--r-- | src/DSi_Camera.h | 32 | ||||
-rw-r--r-- | src/DSi_I2C.cpp | 12 | ||||
-rw-r--r-- | src/DSi_NDMA.cpp | 2 | ||||
-rw-r--r-- | src/NDS.cpp | 4 | ||||
-rw-r--r-- | src/NDS.h | 3 |
8 files changed, 303 insertions, 29 deletions
diff --git a/src/ARM.cpp b/src/ARM.cpp index 7eeacb7..7fe3497 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -256,6 +256,18 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr) // aging cart debug crap //if (addr == 0x0201764C) printf("capture test %d: R1=%08X\n", R[6], R[1]); //if (addr == 0x020175D8) printf("capture test %d: res=%08X\n", R[6], R[0]); + if(addr==0x0219BA2D) printf("CAM RESET FROM %08X\n", R[15]); + if(addr==0x0219BB69) printf("CAM SHITO FROM %08X\n", R[15]); + if(addr==0x0200BA45) printf("CAM SHITO2 FROM %08X\n", R[15]); + if(addr==0x0200B9ED) printf("CAM SHITO3 FROM %08X\n", R[15]); + if(addr==0x0200B9BD) printf("CAM SETUP START FROM %08X\n", R[15]); + if(R[15]==0x0200B9E6) printf("CAM SETUP END FROM %08X\n", addr); + if(addr==0x0219AA5B) printf("CAM LOOP BACK FROM %08X\n", R[15]); + if(addr==0x0200BD0D) printf("GUILLOTINE FIVE MILLION %08X\n", R[15]); + if(addr==0x0200512D) printf("GUILLOTINE SIX MILLION %08X\n", R[15]); + if(addr==0x0219A585) printf("GUILLOTINE SEVEN MILLION %08X\n", R[15]); + if(addr==0x0219BAF1) printf("CAM GET DRQ BIT %08X\n", R[15]); + if(addr==0x0219BA91) printf("CAM STOP TRANSFER %08X\n", R[15]); u32 oldregion = R[15] >> 24; u32 newregion = addr >> 24; @@ -570,6 +582,8 @@ void ARMv5::Execute() // actually execute u32 icode = (CurInstr >> 6) & 0x3FF; ARMInterpreter::THUMBInstrTable[icode](this); + + if (R[15]==0x0219A6B0) printf("CAM THREAD MSG: %02X %08X -> %08X\n", R[1], R[0], 0x0219A6B6+R[0]); } else { @@ -592,7 +606,7 @@ void ARMv5::Execute() else AddCycles_C(); } - + // TODO optimize this shit!!! if (Halted) { @@ -651,7 +665,7 @@ void ARMv5::ExecuteJIT() return; } - ARMJIT::JitBlockEntry block = ARMJIT::LookUpBlock(0, FastBlockLookup, + ARMJIT::JitBlockEntry block = ARMJIT::LookUpBlock(0, FastBlockLookup, instrAddr - FastBlockLookupStart, instrAddr); if (block) ARM_Dispatch(this, block); @@ -802,7 +816,7 @@ void ARMv4::ExecuteJIT() return; } - ARMJIT::JitBlockEntry block = ARMJIT::LookUpBlock(1, FastBlockLookup, + ARMJIT::JitBlockEntry block = ARMJIT::LookUpBlock(1, FastBlockLookup, instrAddr - FastBlockLookupStart, instrAddr); if (block) ARM_Dispatch(this, block); @@ -879,4 +893,4 @@ void ARMv4::FillPipeline() NextInstr[0] = CodeRead32(R[15] - 4); NextInstr[1] = CodeRead32(R[15]); } -}
\ No newline at end of file +} diff --git a/src/DSi.cpp b/src/DSi.cpp index a96322b..259a447 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -35,6 +35,7 @@ #include "DSi_I2C.h" #include "DSi_SD.h" #include "DSi_AES.h" +#include "DSi_Camera.h" #include "tiny-AES-c/aes.hpp" @@ -1406,6 +1407,12 @@ u8 ARM9IORead8(u32 addr) CASE_READ8_32BIT(0x04004060, MBK[0][8]) } + if ((addr & 0xFFFFFF00) == 0x04004200) + { + if (!(SCFG_EXT[0] & (1<<17))) return 0; + return DSi_Camera::Read8(addr); + } + return NDS::ARM9IORead8(addr); } @@ -1428,6 +1435,12 @@ u16 ARM9IORead16(u32 addr) CASE_READ16_32BIT(0x04004060, MBK[0][8]) } + if ((addr & 0xFFFFFF00) == 0x04004200) + { + if (!(SCFG_EXT[0] & (1<<17))) return 0; + return DSi_Camera::Read16(addr); + } + return NDS::ARM9IORead16(addr); } @@ -1480,6 +1493,12 @@ u32 ARM9IORead32(u32 addr) case 0x04004170: return NDMAs[3]->Cnt; } + if ((addr & 0xFFFFFF00) == 0x04004200) + { + if (!(SCFG_EXT[0] & (1<<17))) return 0; + return DSi_Camera::Read32(addr); + } + return NDS::ARM9IORead32(addr); } @@ -1519,6 +1538,12 @@ void ARM9IOWrite8(u32 addr, u8 val) case 0x04004053: MapNWRAM_C(7, val); return; } + if ((addr & 0xFFFFFF00) == 0x04004200) + { + if (!(SCFG_EXT[0] & (1<<17))) return; + return DSi_Camera::Write8(addr, val); + } + return NDS::ARM9IOWrite8(addr, val); } @@ -1572,6 +1597,12 @@ void ARM9IOWrite16(u32 addr, u16 val) return; } + if ((addr & 0xFFFFFF00) == 0x04004200) + { + if (!(SCFG_EXT[0] & (1<<17))) return; + return DSi_Camera::Write16(addr, val); + } + return NDS::ARM9IOWrite16(addr, val); } @@ -1678,6 +1709,12 @@ void ARM9IOWrite32(u32 addr, u32 val) case 0x04004170: NDMAs[3]->WriteCnt(val); return; } + if ((addr & 0xFFFFFF00) == 0x04004200) + { + if (!(SCFG_EXT[0] & (1<<17))) return; + return DSi_Camera::Write32(addr, val); + } + return NDS::ARM9IOWrite32(addr, val); } diff --git a/src/DSi_Camera.cpp b/src/DSi_Camera.cpp index 56cba1c..dd8dea7 100644 --- a/src/DSi_Camera.cpp +++ b/src/DSi_Camera.cpp @@ -18,12 +18,22 @@ #include <stdio.h> #include <string.h> +#include "DSi.h" #include "DSi_Camera.h" DSi_Camera* DSi_Camera0; // 78 / facing outside DSi_Camera* DSi_Camera1; // 7A / selfie cam +u16 DSi_Camera::ModuleCnt; +u16 DSi_Camera::Cnt; + +u8 DSi_Camera::FrameBuffer[640*480*4]; +u32 DSi_Camera::FrameLength; +u32 DSi_Camera::TransferPos; + +const u32 kCameraInterval = 1024*16; // interval between camera data blocks + bool DSi_Camera::Init() { @@ -43,6 +53,63 @@ void DSi_Camera::Reset() { DSi_Camera0->ResetCam(); DSi_Camera1->ResetCam(); + + ModuleCnt = 0; // CHECKME + Cnt = 0; + + memset(FrameBuffer, 0, 640*480*4); + TransferPos = 0; + FrameLength = 256*192*2; // TODO: make it check frame size, data type, etc + + NDS::ScheduleEvent(NDS::Event_DSi_Camera, true, kCameraInterval, Process, 0); +} + + +void DSi_Camera::Process(u32 param) +{ + DSi_Camera* activecam = nullptr; + + // TODO: check which camera has priority if both are activated + if (DSi_Camera0->IsActivated()) activecam = DSi_Camera0; + else if (DSi_Camera1->IsActivated()) activecam = DSi_Camera1; + + if (activecam) + { + if (TransferPos == 0) + RequestFrame(activecam->Num); + + Cnt |= (1<<4); + if (Cnt & (1<<11)) NDS::SetIRQ(0, NDS::IRQ_DSi_Camera); + } + else + { + TransferPos = 0; + } + + // TODO: check the interval for this? + // on hardware the delay is likely determined by how long the camera takes to process raw data + NDS::ScheduleEvent(NDS::Event_DSi_Camera, true, kCameraInterval, Process, 0); +} + +void DSi_Camera::RequestFrame(u32 cam) +{ + if (!(Cnt & (1<<13))) printf("CAMERA: !! REQUESTING YUV FRAME\n"); + + // TODO: picture size, data type, cropping, etc + // generate test pattern + // TODO: get picture from platform (actual camera, video file, whatever source) + for (u32 y = 0; y < 192; y++) + { + for (u32 x = 0; x < 256; x++) + { + u16* px = (u16*)&FrameBuffer[((y*256) + x) * 2]; + + if ((x & 0x8) ^ (y & 0x8)) + *px = 0x8000; + else + *px = 0xFC00 | ((y >> 3) << 5); + } + } } @@ -63,15 +130,25 @@ void DSi_Camera::ResetCam() RegData = 0; PLLCnt = 0; + ClocksCnt = 0; StandbyCnt = 0x4029; // checkme + MiscCnt = 0; +} + +bool DSi_Camera::IsActivated() +{ + if (StandbyCnt & (1<<14)) return false; // standby + if (!(MiscCnt & (1<<9))) return false; // data transfer not enabled + + return true; } -void DSi_Camera::Start() +void DSi_Camera::I2C_Start() { } -u8 DSi_Camera::Read(bool last) +u8 DSi_Camera::I2C_Read(bool last) { u8 ret; @@ -89,7 +166,7 @@ u8 DSi_Camera::Read(bool last) } else { - RegData = ReadReg(RegAddr); + RegData = I2C_ReadReg(RegAddr); ret = RegData >> 8; } } @@ -100,7 +177,7 @@ u8 DSi_Camera::Read(bool last) return ret; } -void DSi_Camera::Write(u8 val, bool last) +void DSi_Camera::I2C_Write(u8 val, bool last) { if (DataPos < 2) { @@ -116,7 +193,7 @@ void DSi_Camera::Write(u8 val, bool last) if (DataPos & 0x1) { RegData |= val; - WriteReg(RegAddr, RegData); + I2C_WriteReg(RegAddr, RegData); RegAddr += 2; // checkme } else @@ -129,22 +206,24 @@ void DSi_Camera::Write(u8 val, bool last) else DataPos++; } -u16 DSi_Camera::ReadReg(u16 addr) +u16 DSi_Camera::I2C_ReadReg(u16 addr) { switch (addr) { case 0x0000: return 0x2280; // chip ID case 0x0014: return PLLCnt; + case 0x0016: return ClocksCnt; case 0x0018: return StandbyCnt; + case 0x001A: return MiscCnt; case 0x301A: return ((~StandbyCnt) & 0x4000) >> 12; } - //printf("DSi_Camera%d: unknown read %04X\n", Num, addr); + if(Num==1)printf("DSi_Camera%d: unknown read %04X\n", Num, addr); return 0; } -void DSi_Camera::WriteReg(u16 addr, u16 val) +void DSi_Camera::I2C_WriteReg(u16 addr, u16 val) { switch (addr) { @@ -154,13 +233,136 @@ void DSi_Camera::WriteReg(u16 addr, u16 val) val |= ((val & 0x0002) << 14); PLLCnt = val; return; + case 0x0016: + ClocksCnt = val; + printf("ClocksCnt=%04X\n", val); + return; case 0x0018: // TODO: this shouldn't be instant, but uh val &= 0x003F; val |= ((val & 0x0001) << 14); StandbyCnt = val; + printf("CAM%d STBCNT=%04X (%04X)\n", Num, StandbyCnt, val); + return; + case 0x001A: + MiscCnt = val & 0x0B7B; + printf("CAM%d MISCCNT=%04X (%04X)\n", Num, MiscCnt, val); + return; + } + + if(Num==1)printf("DSi_Camera%d: unknown write %04X %04X\n", Num, addr, val); +} + + +u8 DSi_Camera::Read8(u32 addr) +{ + // + + printf("unknown DSi cam read8 %08X\n", addr); + return 0; +} + +u16 DSi_Camera::Read16(u32 addr) +{printf("CAM READ %08X %08X\n", addr, NDS::GetPC(0)); + switch (addr) + { + case 0x04004200: return ModuleCnt; + case 0x04004202: return Cnt; + } + + printf("unknown DSi cam read16 %08X\n", addr); + return 0; +} +u32 dorp = 0; +u32 DSi_Camera::Read32(u32 addr) +{ + switch (addr) + { + case 0x04004204: + { + if (!(Cnt & (1<<15))) return 0; // CHECKME + u32 ret = *(u32*)&FrameBuffer[TransferPos]; + TransferPos += 4; + if (TransferPos >= FrameLength) TransferPos = 0; + dorp += 4; + //if (dorp >= (256*4*2)) + if (TransferPos == 0) + { + dorp = 0; + Cnt &= ~(1<<4); + } + return ret; + } + } + + printf("unknown DSi cam read32 %08X\n", addr); + return 0; +} + +void DSi_Camera::Write8(u32 addr, u8 val) +{ + // + + printf("unknown DSi cam write8 %08X %02X\n", addr, val); +} + +void DSi_Camera::Write16(u32 addr, u16 val) +{printf("CAM WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(0)); + switch (addr) + { + case 0x04004200: + { + u16 oldcnt = ModuleCnt; + ModuleCnt = val; + + if ((ModuleCnt & (1<<1)) && !(oldcnt & (1<<1))) + { + // reset shit to zero + // CHECKME + + Cnt = 0; + } + + if ((ModuleCnt & (1<<5)) && !(oldcnt & (1<<5))) + { + // TODO: reset I2C?? + } + } + return; + + case 0x04004202: + { + // checkme + u16 oldmask; + if (Cnt & 0x8000) + { + val &= 0x8F00; + oldmask = 0x601F; + } + else + { + val &= 0xEF0F; + oldmask = 0x0010; + } + + Cnt = (Cnt & oldmask) | val; + if (val & (1<<5)) Cnt &= ~(1<<4); + + if ((val & (1<<15)) && !(Cnt & (1<<15))) + { + // start transfer + DSi::CheckNDMAs(0, 0x0B); + } + } return; } - //printf("DSi_Camera%d: unknown write %04X %04X\n", Num, addr, val); + printf("unknown DSi cam write16 %08X %04X\n", addr, val); +} + +void DSi_Camera::Write32(u32 addr, u32 val) +{ + // + + printf("unknown DSi cam write32 %08X %08X\n", addr, val); } diff --git a/src/DSi_Camera.h b/src/DSi_Camera.h index 844a4d2..8e44db1 100644 --- a/src/DSi_Camera.h +++ b/src/DSi_Camera.h @@ -28,27 +28,47 @@ public: static void DeInit(); static void Reset(); + static void Process(u32 param); + static void RequestFrame(u32 cam); + DSi_Camera(u32 num); ~DSi_Camera(); void ResetCam(); + bool IsActivated(); - void Start(); - u8 Read(bool last); - void Write(u8 val, bool last); + void I2C_Start(); + u8 I2C_Read(bool last); + void I2C_Write(u8 val, bool last); + + static u8 Read8(u32 addr); + static u16 Read16(u32 addr); + static u32 Read32(u32 addr); + static void Write8(u32 addr, u8 val); + static void Write16(u32 addr, u16 val); + static void Write32(u32 addr, u32 val); -private: u32 Num; +private: u32 DataPos; u32 RegAddr; u16 RegData; - u16 ReadReg(u16 addr); - void WriteReg(u16 addr, u16 val); + u16 I2C_ReadReg(u16 addr); + void I2C_WriteReg(u16 addr, u16 val); u16 PLLCnt; + u16 ClocksCnt; u16 StandbyCnt; + u16 MiscCnt; + + static u16 ModuleCnt; + static u16 Cnt; + + static u8 FrameBuffer[640*480*4]; + static u32 TransferPos; + static u32 FrameLength; }; diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp index d58a38c..faa3d16 100644 --- a/src/DSi_I2C.cpp +++ b/src/DSi_I2C.cpp @@ -187,8 +187,8 @@ void WriteCnt(u8 val) switch (Device) { case 0x4A: Data = DSi_BPTWL::Read(islast); break; - case 0x78: Data = DSi_Camera0->Read(islast); break; - case 0x7A: Data = DSi_Camera1->Read(islast); break; + case 0x78: Data = DSi_Camera0->I2C_Read(islast); break; + case 0x7A: Data = DSi_Camera1->I2C_Read(islast); break; default: printf("I2C: read on unknown device %02X, cnt=%02X, data=%02X, last=%d\n", Device, val, 0, islast); Data = 0xFF; @@ -211,8 +211,8 @@ void WriteCnt(u8 val) switch (Device) { case 0x4A: DSi_BPTWL::Start(); break; - case 0x78: DSi_Camera0->Start(); break; - case 0x7A: DSi_Camera1->Start(); break; + case 0x78: DSi_Camera0->I2C_Start(); break; + case 0x7A: DSi_Camera1->I2C_Start(); break; default: printf("I2C: %s start on unknown device %02X\n", (Data&0x01)?"read":"write", Device); ack = false; @@ -226,8 +226,8 @@ void WriteCnt(u8 val) switch (Device) { case 0x4A: DSi_BPTWL::Write(Data, islast); break; - case 0x78: DSi_Camera0->Write(Data, islast); break; - case 0x7A: DSi_Camera1->Write(Data, islast); break; + case 0x78: DSi_Camera0->I2C_Write(Data, islast); break; + case 0x7A: DSi_Camera1->I2C_Write(Data, islast); break; default: printf("I2C: write on unknown device %02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast); ack = false; diff --git a/src/DSi_NDMA.cpp b/src/DSi_NDMA.cpp index 707c777..d6d289d 100644 --- a/src/DSi_NDMA.cpp +++ b/src/DSi_NDMA.cpp @@ -101,7 +101,7 @@ void DSi_NDMA::WriteCnt(u32 val) Start(); if (StartMode != 0x10 && StartMode != 0x30 && - StartMode != 0x04 && StartMode != 0x06 && StartMode != 0x07 && StartMode != 0x08 && StartMode != 0x09 && + StartMode != 0x04 && StartMode != 0x06 && StartMode != 0x07 && StartMode != 0x08 && StartMode != 0x09 && StartMode != 0x0B && StartMode != 0x24 && StartMode != 0x26 && StartMode != 0x28 && StartMode != 0x29 && StartMode != 0x2A && StartMode != 0x2B) printf("UNIMPLEMENTED ARM%d NDMA%d START MODE %02X, %08X->%08X LEN=%d BLK=%d CNT=%08X\n", CPU?7:9, Num, StartMode, SrcAddr, DstAddr, TotalLength, BlockLength, Cnt); diff --git a/src/NDS.cpp b/src/NDS.cpp index f926399..90eaac5 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1819,14 +1819,14 @@ void debug(u32 param) fclose(shit);*/ FILE* - shit = fopen("debug/picto9.bin", "wb"); + shit = fopen("debug/cam9.bin", "wb"); for (u32 i = 0x02000000; i < 0x04000000; i+=4) { u32 val = DSi::ARM9Read32(i); fwrite(&val, 4, 1, shit); } fclose(shit); - shit = fopen("debug/picto7.bin", "wb"); + shit = fopen("debug/cam7.bin", "wb"); for (u32 i = 0x02000000; i < 0x04000000; i+=4) { u32 val = DSi::ARM7Read32(i); @@ -46,6 +46,7 @@ enum Event_DSi_SDMMCTransfer, Event_DSi_SDIOTransfer, Event_DSi_NWifi, + Event_DSi_Camera, Event_DSi_RAMSizeChange, @@ -82,7 +83,7 @@ enum IRQ_IPCSendDone, IRQ_IPCRecv, IRQ_CartSendDone, // TODO: less misleading name - IRQ_CartIREQMC, // IRQ triggered by game cart (example: Pok�mon Typing Adventure, BT controller) + IRQ_CartIREQMC, // IRQ triggered by game cart (example: Pokémon Typing Adventure, BT controller) IRQ_GXFIFO, IRQ_LidOpen, IRQ_SPI, |