BOOL GX2RCreateSurfaceUserMemory(virt_ptr<GX2Surface> surface, virt_ptr<uint8_t> image, virt_ptr<uint8_t> mipmap, GX2RResourceFlags flags) { GX2CalcSurfaceSizeAndAlignment(surface); surface->resourceFlags = flags; surface->resourceFlags &= ~GX2RResourceFlags::Locked; surface->resourceFlags &= ~GX2RResourceFlags::Gx2rAllocated; surface->image = image; surface->mipmaps = mipmap; if ((surface->resourceFlags & GX2RResourceFlags::UsageGpuWrite) || (surface->resourceFlags & GX2RResourceFlags::UsageDmaWrite)) { DCInvalidateRange(virt_cast<virt_addr>(surface->image), surface->imageSize); if (surface->mipmaps) { DCInvalidateRange(virt_cast<virt_addr>(surface->mipmaps), surface->mipmapSize); } } return true; }
/** * ARAMFetch * * This function will move data from ARAM to MAIN memory */ void ARAMFetch (char *dst, char *src, int len) { DCInvalidateRange(dst, len); AR_StartDMA( ARAM_READ, (u32) dst, (u32) src, len); while (AR_GetDMAStatus()); }
virt_ptr<void> GX2RLockSurfaceEx(virt_ptr<GX2Surface> surface, int32_t level, GX2RResourceFlags flags) { decaf_check(surface); decaf_check(surface->resourceFlags & ~GX2RResourceFlags::Locked); flags = surface->resourceFlags | internal::getOptionFlags(flags); // Set Locked flag surface->resourceFlags |= GX2RResourceFlags::Locked; surface->resourceFlags |= flags & GX2RResourceFlags::LockedReadOnly; // Check if we need to invalidate the surface. if ((flags & GX2RResourceFlags::UsageGpuWrite) || (flags & GX2RResourceFlags::UsageDmaWrite)) { if (!(flags & GX2RResourceFlags::DisableCpuInvalidate)) { auto ptr = virt_ptr<void> { nullptr }; auto size = uint32_t { 0 }; internal::getSurfaceData(surface, level, &ptr, &size); DCInvalidateRange(virt_cast<virt_addr>(ptr), size); } } return surface->image; }
s32 IOS_GetRevision() { u32 vercode; u16 rev; DCInvalidateRange((void*)0x80003140,8); vercode = *((u32*)0x80003140); rev = vercode & 0xFFFF; if(vercode == 0 || rev == 0) return IOS_EBADVERSION; return rev; }
s32 IOS_GetVersion() { u32 vercode; u16 version; DCInvalidateRange((void*)0x80003140,8); vercode = *((u32*)0x80003140); version = vercode >> 16; if(version == 0) return IOS_EBADVERSION; if(version > 0xff) return IOS_EBADVERSION; return version; }
static void build_disp_list(void) { DCInvalidateRange(display_list, sizeof(display_list)); GX_BeginDispList(display_list, sizeof(display_list)); GX_Begin(GX_QUADS, GX_VTXFMT0, 4); for (unsigned i = 0; i < 4; i++) { GX_Position1x8(i); GX_TexCoord1x8(i); } GX_End(); display_list_size = GX_EndDispList(); }
int main(int argc, char **argv) { // Exit after 10 seconds if there is an error __exception_setreload(10); CheckForGecko(); DCInvalidateRange(loader_stub, 0x1800); memcpy(loader_stub, (void*)0x80001800, 0x1800); DCFlushRange(loader_stub, 0x1800); if( !IsWiiU() ) { gprintf("Nintendont Loader\r\n"); gprintf("Built : %s %s\r\n", __DATE__, __TIME__ ); gprintf("Version : %d.%d\r\n", NIN_VERSION>>16, NIN_VERSION&0xFFFF ); }
/**************************************************************************** * dvd_read * * The only DVD function we need - you gotta luv gc-linux self-boots! * returns: 1 - ok ; 0 - error ***************************************************************************/ int dvd_read (void *dst, unsigned int len, u64 offset) { unsigned char *buffer = (unsigned char *) (unsigned int) DVDreadbuffer; if (len > 2048) return 0; /*** We only allow 2k reads **/ DCInvalidateRange ((void *) buffer, len); // don't read past the end of the DVD (1.5 GB for GC DVD, 4.7 GB for DVD) if(offset < 0x57057C00 || (isWii && offset < 0x118244F00LL)) { #ifdef HW_DOL dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xA8000000; dvd[3] = (u32)(offset >> 2); dvd[4] = len; dvd[5] = (u32) buffer; dvd[6] = len; dvd[7] = 3; /*** Enable reading with DMA ***/ while (dvd[7] & 1); memcpy (dst, buffer, len); if (dvd[0] & 0x4) /* Ensure it has completed */ return 0; return 1; #elif WII_DVD int ret = 1; ret = DI_ReadDVD(dst, len >> 11, (u32)(offset >> 11)); if (ret==0) return 1; else return 0; #endif }
/* DVD_LowRead64(void* dst, unsigned int len, uint64_t offset) Read Raw, needs to be on sector boundaries Has 8,796,093,020,160 byte limit (8 TeraBytes) Synchronous function. return -1 if offset is out of range */ int DVD_LowRead64(void* dst, unsigned int len, uint64_t offset) { if(offset>>2 > 0xFFFFFFFF) return -1; if ((((int)dst) & 0xC0000000) == 0x80000000) // cached? dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = read_cmd; dvd[3] = read_cmd == DVDR ? offset>>11 : offset >> 2; dvd[4] = read_cmd == DVDR ? len>>11 : len; dvd[5] = (unsigned long)dst; dvd[6] = len; dvd[7] = 3; // enable reading! DCInvalidateRange(dst, len); while (dvd[7] & 1); if (dvd[0] & 0x4) return 1; return 0; }
model_t* MODEL_setup(const u8* model_bmb) { binheader_t* header = (binheader_t*) model_bmb; const u32 posOffset = sizeof(binheader_t); const u32 nrmOffset = posOffset + (sizeof(f32)* header->vcount * 3); const u32 texOffset = nrmOffset + (sizeof(f32)* header->vcount * 3); const u32 indOffset = texOffset + (sizeof(f32)* header->vcount * 2); f32* positions = (f32*) (model_bmb + posOffset); f32* normals = (f32*) (model_bmb + nrmOffset); f32* texcoords = (f32*) (model_bmb + texOffset); u16* indices = (u16*) (model_bmb + indOffset); /* Calculate cost */ const u32 indicesCount = header->fcount * 3; const u32 indicesSize = indicesCount * 3 * sizeof(u16); /* 3 indices per vertex index (p,n,t) that are u16 in size */ const u32 callSize = 89; /* Size of setup var */ /* Round up to nearest 32 multiplication */ const u32 dispSize = (((indicesSize + callSize + 63) >> 5) + 1) << 5; /* Build display list */ /* Allocate and clear */ u32 i; void* modelList = memalign(32, dispSize); memset(modelList, 0, dispSize); /* Set buffer data */ DCInvalidateRange(modelList, dispSize); GX_BeginDispList(modelList, dispSize); //GX_InvVtxCache(); GX_ClearVtxDesc(); GX_SetVtxDesc(GX_VA_POS, GX_INDEX16); GX_SetVtxDesc(GX_VA_NRM, GX_INDEX16); GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX16); GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GX_SetArray(GX_VA_POS, (void*) positions, 3 * sizeof(f32)); GX_SetArray(GX_VA_NRM, (void*) normals, 3 * sizeof(f32)); GX_SetArray(GX_VA_TEX0, (void*) texcoords, 2 * sizeof(f32)); /* Fill the list with indices */ GX_Begin(GX_TRIANGLES, GX_VTXFMT0, indicesCount); for (i = 0; i < indicesCount; i++) { GX_Position1x16(indices[i]); GX_Normal1x16(indices[i]); GX_TexCoord1x16(indices[i]); } GX_End(); /* Close display list */ u32 modelListSize = GX_EndDispList(); if (modelListSize == 0) { printf("Error: Display list not big enough [%u]\n", dispSize); return NULL; } /* Return model info */ model_t* model = malloc(sizeof(model_t)); model->modelList = modelList; model->modelListSize = modelListSize; model->modelFaceCount = header->fcount; model->modelPositions = positions; model->modelNormals = normals; model->modelTexcoords = texcoords; model->modelIndices = indices; return model; }
s32 Swi_Handler(u32 arg0, u32 arg1, u32 arg2, u32 arg3) { u8 cmd; /* Check alignment */ SwiAddr -= (SwiAddr[-4] == 0xDF) ? 3 : 1; /* Get command */ cmd = SwiAddr[0]; /* Check command */ if(SwiAddr[0] != 0xcc) { if (SwiTable[cmd]) return SwiTable[cmd](arg0, arg1, arg2, arg3); else return arg0; } /* Check argument */ switch (arg0) { /** Add SWI handler **/ case 0: { SwiTable[arg1]= (void *)arg2; break; } /** Memcpy (cached to cached) **/ case 2: { void *src = (void *)arg2; void *dst = (void *)arg1; u32 len = arg3; u32 perms; /* Apply permissions */ perms = Perms_Read(); Perms_Write(0xFFFFFFFF); /* Copy data */ memcpy(dst, src, len); DCFlushRange(dst, len); /* Restore permissions */ Perms_Write(perms); break; } /** Get register **/ case 3: return *(vu32 *)arg1; /** Set register **/ case 4: *(vu32 *)arg1 = arg2; break; /** Set register **/ case 5: *(vu32 *)arg1 |= arg2; break; /** Clear register **/ case 6: *(vu32 *)arg1 &= ~arg2; break; /** Memcpy (uncached to cached) **/ case 9: { void *src = (void *)arg2; void *dst = (void *)arg1; u32 len = arg3; u32 perms; /* Apply permissions */ perms = Perms_Read(); Perms_Write(0xFFFFFFFF); /* Copy data */ DCInvalidateRange(src, len); memcpy(dst, src, len); DCFlushRange(dst, len); /* Restore permissions */ Perms_Write(perms); break; } /** Call function **/ case 16: { s32 (*Function)(void *in, void *out); /* Set function */ Function = (void *)arg1; /* Call function */ return Function((void *)arg2, (void *)arg3); } /** Get syscall base */ case 17: return ios.syscall; /** Get IOS info **/ case 18: { iosInfo *buffer = (iosInfo *)arg1; /* Copy IOS info */ memcpy(buffer, &ios, sizeof(ios)); DCFlushRange(buffer, sizeof(ios)); break; } /** Get MLOAD version **/ case 19: return (MLOAD_VER << 4) | MLOAD_SUBVER; /** Led on **/ case 128: *(vu32 *)0x0d8000c0 |= 0x20; break; /** Led off **/ case 129: *(vu32 *)0x0d8000c0 &=~ 0x20; break; /** Led blink **/ case 130: *(vu32 *)0x0d8000c0 ^= 0x20; break; default: break; } return 0; }
s32 LoadKernel() { u32 TMDSize; u32 i,u; s32 r = ES_GetStoredTMDSize( 0x000000010000003aLL, &TMDSize ); if( r < 0 ) { gprintf("ES_GetStoredTMDSize():%d\r\n", r ); return r; } gprintf("TMDSize:%u\r\n", TMDSize ); TitleMetaData *TMD = (TitleMetaData*)memalign( 32, TMDSize ); if( TMD == (TitleMetaData*)NULL ) { gprintf("Failed to alloc:%u\r\n", TMDSize ); return r; //todo errors are < 0 r still has >= 0 from previous call } r = ES_GetStoredTMD( 0x000000010000003aLL, (signed_blob *)TMD, TMDSize ); if( r < 0 ) { gprintf("ES_GetStoredTMD():%d\r\n", r ); free(TMD); return r; } //Look for boot index for( i=0; i < TMD->ContentCount; ++i ) { if( TMD->BootIndex == TMD->Contents[i].Index ) break; } gprintf("BootIndex:%u\r\n", i ); s32 cfd = IOS_Open( "/shared1/content.map", 1 ); if( cfd < 0 ) { gprintf("IOS_Open():%d\r\n", cfd ); free(TMD); return cfd; } for( u=0;; u+=0x1C ) { if( IOS_Read( cfd, Entry, 0x1C ) != 0x1C ) { gprintf("Hash not found in content.map\r\n"); free(TMD); return -2; } if( memcmp( (char*)(Entry+8), TMD->Contents[i].SHA1, 0x14 ) == 0 ) break; } FoundVersion = ((TMD->TitleID & 0xFFFF) << 16) | (TMD->TitleVersion); free(TMD); IOS_Close( cfd ); u32 *IOSVersion = (u32*)0x93003000; DCInvalidateRange(IOSVersion, 0x20); *IOSVersion = FoundVersion; gprintf("IOS Version: 0x%08X\n", FoundVersion); DCFlushRange(IOSVersion, 0x20); //char Path[32]; char *Path = (char*)0x93003020; DCInvalidateRange(Path, 1024); memset(Path, 0, 1024); sprintf( Path, "/shared1/%.8s.app", Entry ); gprintf("Kernel:\"%s\"\r\n", Path ); DCFlushRange(Path, 1024); s32 kfd = IOS_Open( Path, 1 ); if( kfd < 0 ) { gprintf("IOS_Open():%d\r\n", kfd ); return kfd; } KernelSize = IOS_Seek( kfd, 0, SEEK_END ); IOS_Seek( kfd, 0, 0); gprintf("KernelSize:%u\r\n", KernelSize ); if( IOS_Read( kfd, Kernel, KernelSize ) != KernelSize ) { gprintf("IOS_Read() failed\r\n"); IOS_Close(kfd); return -1; } IOS_Close(kfd); return 0; }
static void __ARCheckSize() { u32 i,arsize,arszflag; static u32 test_data[8] ATTRIBUTE_ALIGN(32); static u32 dummy_data[8] ATTRIBUTE_ALIGN(32); static u32 buffer[8] ATTRIBUTE_ALIGN(32); #ifdef _AR_DEBUG printf("__ARCheckSize()\n"); #endif while(!(_dspReg[11]&0x0001)); __ARSize = __ARInternalSize = arsize = 0x1000000; _dspReg[9] = (_dspReg[9]&~0x3f)|0x23; for(i=0;i<8;i++) { test_data[i] = 0xBAD1BAD0; dummy_data[i] = 0xDEADBEEF; } DCFlushRange(test_data,32); DCFlushRange(dummy_data,32); __ARExpansionSize = 0; __ARWriteDMA((u32)test_data,0x1000000,32); __ARWriteDMA((u32)test_data,0x1200000,32); __ARWriteDMA((u32)test_data,0x2000000,32); __ARWriteDMA((u32)test_data,0x1000200,32); __ARWriteDMA((u32)test_data,0x1400000,32); memset(buffer,0,32); DCFlushRange(buffer,32); __ARWriteDMA((u32)dummy_data,0x1000000,32); DCInvalidateRange(buffer,32); __ARReadDMA((u32)buffer,0x1000000,32); _nop(); arszflag = 0x03; if(buffer[0]==dummy_data[0]) { memset(buffer,0,32); DCFlushRange(buffer,32); __ARReadDMA((u32)buffer,0x1200000,32); _nop(); if(buffer[0]==dummy_data[0]) { __ARExpansionSize = 0x200000; arsize += 0x200000; goto end_check; //not nice but fast } memset(buffer,0,32); DCFlushRange(buffer,32); __ARReadDMA((u32)buffer,0x2000000,32); _nop(); if(buffer[0]==dummy_data[0]) { __ARExpansionSize = 0x400000; arsize += 0x400000; arszflag |= 0x08; goto end_check; //not nice but fast } memset(buffer,0,32); DCFlushRange(buffer,32); __ARReadDMA((u32)buffer,0x1400000,32); _nop(); if(buffer[0]==dummy_data[0]) { __ARExpansionSize = 0x1000000; arsize += 0x1000000; arszflag |= 0x18; } else { __ARExpansionSize = 0x2000000; arsize += 0x2000000; arszflag |= 0x20; } end_check: _dspReg[9] = (_dspReg[9]&~0x3f)|arszflag; } #ifdef _AR_DEBUG printf("__ARCheckSize(%d)\n",arsize); #endif *(u32*)0x800000d0 = arsize; __ARSize = arsize; }
void _start() { /* Load a good stack */ asm( "lis %r1, 0x1ab5 ;" "ori %r1, %r1, 0xd138 ;" ); /* Get a handle to coreinit.rpl, dmae.rpl, and nsysnet.rpl */ unsigned int coreinit_handle, dmae_handle, nsysnet_handle; OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); OSDynLoad_Acquire("dmae.rpl", &dmae_handle); OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle); /* Cache, DMA, and socket functions */ void (*DCFlushRange)(void *addr, unsigned int length); void (*DCInvalidateRange)(void *addr, unsigned int length); unsigned long long (*DMAECopyMem)(void *dst, void *src, unsigned int nwords, int endian); int (*DMAEWaitDone)(unsigned long long ret); int (*socket)(int family, int type, int proto); int (*connect)(int fd, struct sockaddr *addr, int addrlen); int (*send)(int fd, const void *buffer, int len, int flags); /* Read the addresses of the functions */ OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange); OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange); OSDynLoad_FindExport(dmae_handle, 0, "DMAECopyMem", &DMAECopyMem); OSDynLoad_FindExport(dmae_handle, 0, "DMAEWaitDone", &DMAEWaitDone); OSDynLoad_FindExport(nsysnet_handle, 0, "socket", &socket); OSDynLoad_FindExport(nsysnet_handle, 0, "connect", &connect); OSDynLoad_FindExport(nsysnet_handle, 0, "send", &send); /* Set up our socket address structure */ struct sockaddr sin; sin.sin_family = AF_INET; sin.sin_port = 12345; sin.sin_addr.s_addr = PC_IP; int i; for (i = 0; i < 8; i++) { sin.sin_zero[i] = 0; } /* Connect to the PC */ int pc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); int status = connect(pc, &sin, 0x10); if (status) OSFatal("Error connecting to PC server"); /* Cache stuff */ DCFlushRange(0x01000000, 0x20); DCInvalidateRange(0x1dd7b820, 0x20); /* Do the copy */ int success = DMAEWaitDone(DMAECopyMem(0x1dd7b820, 0x01000000, 2, 0)); if (success) { send(pc, "Success", 8, 0); } else { send(pc, "Fail", 5, 0); } while(1); }
//addr == addr of 4kb block of PowerPC_block ptrs to pull out from ARAM void ARAM_ReadBlock(u32 addr, int block_num) { ARQ_PostRequest(&ARQ_request_blocks, 0x2EAD, AR_ARAMTOMRAM, ARQ_PRIO_LO, (int)(BLOCKS_CACHE_ADDR + addr), (int)&cached_block[block_num][0], CACHED_BLOCK_SIZE); DCInvalidateRange((void*)&cached_block[block_num][0], CACHED_BLOCK_SIZE); }
int BuildLists(GXTexObj texture) { // Make the new display list // For display lists, each command has an associated "cost" in bytes. // Add all these up to calculate the size of your display list before rounding up. // eke-eke says GX_Begin() costs 3 bytes (u8 + u16) // According to my research: // GX_Position3f32() is 12 bytes (f32*3) // GX_Normal3f32() is 12 bytes (f32*3) // GX_Color3f32() is actually 3 bytes ((f32 -> u8) * 3) // GX_TexCoord2f32() is 8 bytes (f32*2) // GX_End() seems to cost zero (there's no actual code in it) // Size -must- be multiple of 32, so (12*24) + (12*24) + (3*24) + (8*24) + 3 = 843 // Rounded up to the nearest 32 is 864. // NOTE: Actual size may be up to 63 bytes -larger- than you calculate it to be due to padding and cache alignment. for (int i=0; i<5;i++) { boxList[i] = memalign(32,896); memset(boxList[i],0,896); DCInvalidateRange(boxList[i],896); GX_BeginDispList(boxList[i],896); GX_Begin(GX_QUADS,GX_VTXFMT0,24); // Start drawing // Bottom face GX_Position3f32(-1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top right GX_Position3f32( 1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Top left GX_Position3f32( 1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom left GX_Position3f32(-1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Bottom right // Front face GX_Position3f32(-1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom left GX_Position3f32( 1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Bottom right GX_Position3f32( 1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top right GX_Position3f32(-1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Top left // Back face GX_Position3f32(-1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Bottom right GX_Position3f32(-1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top right GX_Position3f32( 1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Top left GX_Position3f32( 1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom left // Right face GX_Position3f32( 1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Bottom right GX_Position3f32( 1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top right GX_Position3f32( 1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Top left GX_Position3f32( 1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom left // Left face GX_Position3f32(-1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom right GX_Position3f32(-1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Top right GX_Position3f32(-1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top left GX_Position3f32(-1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Bottom left // Top face GX_Position3f32(-1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(TopColors[i][0],TopColors[i][1],TopColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Top left GX_Position3f32(-1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(TopColors[i][0],TopColors[i][1],TopColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom left GX_Position3f32( 1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(TopColors[i][0],TopColors[i][1],TopColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Bottom rught GX_Position3f32( 1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1); GX_Color3f32(TopColors[i][0],TopColors[i][1],TopColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top right GX_End(); // Done drawing quads // GX_EndDispList() returns the size of the display list, so store that value and use it with GX_CallDispList(). boxSize[i] = GX_EndDispList(); // Done building the box list if (boxSize[i] == 0) return 1; } // setup texture coordinate generation // args: texcoord slot 0-7, matrix type, source to generate texture coordinates from, matrix to use GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); // Set up TEV to paint the textures properly. GX_SetTevOp(GX_TEVSTAGE0,GX_MODULATE); GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); // Load up the textures (just one this time). GX_LoadTexObj(&texture, GX_TEXMAP0); return 0; }
/* Install an exception handler */ int _start(int argc, char **argv) { /* Get a handle to coreinit.rpl and nsysnet.rpl */ unsigned int coreinit_handle, nsysnet_handle; OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle); /* Memory and cache functions */ unsigned int (*OSEffectiveToPhysical)(void *ptr); void (*DCFlushRange)(void *addr, unsigned int len); void (*DCInvalidateRange)(void *addr, unsigned int len); OSDynLoad_FindExport(coreinit_handle, 0, "OSEffectiveToPhysical", &OSEffectiveToPhysical); OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange); OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange); /* Kernel is mapped */ if (OSEffectiveToPhysical((void*)0xA0000000) == 0xC0000000) { /* Patches installed */ if (*((unsigned int*)(0xA0000000 + (0xFFF00B40 - 0xC0000000))) == 1) { /* Socket functions */ int (*socket_lib_init)(); int (*get_socket_rm_fd)(); int (*socket)(int family, int type, int proto); int (*connect)(int fd, struct sockaddr *addr, int addrlen); OSDynLoad_FindExport(nsysnet_handle, 0, "socket_lib_init", &socket_lib_init); OSDynLoad_FindExport(nsysnet_handle, 0, "get_socket_rm_fd", &get_socket_rm_fd); OSDynLoad_FindExport(nsysnet_handle, 0, "socket", &socket); OSDynLoad_FindExport(nsysnet_handle, 0, "connect", &connect); /* Init the sockets library */ socket_lib_init(); /* Set up our socket address structure */ struct sockaddr sin; sin.sin_family = AF_INET; sin.sin_port = 12345; sin.sin_addr.s_addr = PC_IP; int i; for (i = 0; i < 8; i++) { sin.sin_zero[i] = 0; } /* Connect to the PC */ int pc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); int status = connect(pc, &sin, 0x10); if (status) OSFatal("Error connecting to PC"); /* Store the socket info in a place the kernel can access */ unsigned int sock_info[4] = {1, (unsigned int)get_socket_rm_fd(), (unsigned int)pc, 0}; memcpy((void*)(0xA0000000 + (0xFFF00B40 - 0xC0000000)), sock_info, 0x10); DCFlushRange((void*)(0xA0000000 + (0xFFF00B40 - 0xC0000000)), 0x20); DCInvalidateRange((void*)(0xA0000000 + (0xFFF00B40 - 0xC0000000)), 0x20); } /* Patches not yet installed, but they will be next time */ else { /* Signify patches installed, socket data still invalid, spinlock 0 */ *((unsigned int*)(0xA0000000 + (0xFFF00B40 - 0xC0000000))) = 1; *((unsigned int*)(0xA0000000 + (0xFFF00B44 - 0xC0000000))) = -1; *((unsigned int*)(0xA0000000 + (0xFFF00B48 - 0xC0000000))) = -1; *((unsigned int*)(0xA0000000 + (0xFFF00B4C - 0xC0000000))) = 0; DCFlushRange((void*)(0xA0000000 + (0xFFF00B40 - 0xC0000000)), 0x20); DCInvalidateRange((void*)(0xA0000000 + (0xFFF00B40 - 0xC0000000)), 0x20); } } /* Return to main() */ #if VER == 532 int (*main)(int argc, char **argv) = (int (*)(int,char**)) (*((unsigned int*)0x1005D180)); #elif VER == 550 int (*main)(int argc, char **argv) = (int (*)(int,char**)) (*((unsigned int*)0x1005E040)); #else int (*main)(int argc, char **argv) = (int (*)(int,char**)) (*((unsigned int*)0x0)); #endif return main(argc, argv); }
void InitVideo () { VIDEO_Init(); vmode = VIDEO_GetPreferredMode(NULL); // get default video mode bool pal = false; if (vmode == &TVPal528IntDf) pal = true; if (CONF_GetAspectRatio() == CONF_ASPECT_16_9) { vmode->fbWidth = 640; vmode->efbHeight = 456; vmode->viWidth = 686; if (pal) { vmode->xfbHeight = 542; vmode->viHeight = 542; } else { vmode->xfbHeight = 456; vmode->viHeight = 456; } } else { if (pal) vmode = &TVPal574IntDfScale; vmode->viWidth = 672; } if (pal) { vmode->viXOrigin = (VI_MAX_WIDTH_PAL - vmode->viWidth) / 2; vmode->viYOrigin = (VI_MAX_HEIGHT_PAL - vmode->viHeight) / 2; } else { vmode->viXOrigin = (VI_MAX_WIDTH_NTSC - vmode->viWidth) / 2; vmode->viYOrigin = (VI_MAX_HEIGHT_NTSC - vmode->viHeight) / 2; } VIDEO_Configure (vmode); // Allocate the video buffers xfb[0] = (u32 *) SYS_AllocateFramebuffer (vmode); xfb[1] = (u32 *) SYS_AllocateFramebuffer (vmode); DCInvalidateRange(xfb[0], VIDEO_GetFrameBufferSize(vmode)); DCInvalidateRange(xfb[1], VIDEO_GetFrameBufferSize(vmode)); xfb[0] = (u32 *) MEM_K0_TO_K1 (xfb[0]); xfb[1] = (u32 *) MEM_K0_TO_K1 (xfb[1]); // Clear framebuffers etc. VIDEO_ClearFrameBuffer (vmode, xfb[0], COLOR_BLACK); VIDEO_ClearFrameBuffer (vmode, xfb[1], COLOR_BLACK); VIDEO_SetNextFramebuffer (xfb[0]); VIDEO_SetBlack (FALSE); VIDEO_Flush (); VIDEO_WaitVSync (); if (vmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync (); StartGX(); ResetVideo_Menu(); // Finally, the video is up and ready for use :) }
int main(int argc, char **argv) { // Exit after 10 seconds if there is an error __exception_setreload(10); // u64 timeout = 0; CheckForGecko(); DCInvalidateRange(loader_stub, 0x1800); memcpy(loader_stub, (void*)0x80001800, 0x1800); RAMInit(); //Meh, doesnt do anything anymore anyways //STM_RegisterEventHandler(HandleSTMEvent); Initialise(); // Checking for storage devices... ShowMessageScreen("Checking storage devices..."); u32 u; //Disables MEMPROT for patches write16(MEM_PROT, 0); //Patches FS access for( u = 0x93A00000; u < 0x94000000; u+=2 ) { if( memcmp( (void*)(u), FSAccessPattern, sizeof(FSAccessPattern) ) == 0 ) { // gprintf("FSAccessPatch:%08X\r\n", u ); memcpy( (void*)u, FSAccessPatch, sizeof(FSAccessPatch) ); DCFlushRange((void*)u, sizeof(FSAccessPatch)); break; } } //for BT.c CONF_GetPadDevices((conf_pads*)0x932C0000); DCFlushRange((void*)0x932C0000, sizeof(conf_pads)); *(vu32*)0x932C0490 = CONF_GetIRSensitivity(); *(vu32*)0x932C0494 = CONF_GetSensorBarPosition(); DCFlushRange((void*)0x932C0490, 8); if(LoadKernel() < 0) { ClearScreen(); gprintf("Failed to load kernel from NAND!\r\n"); ShowMessageScreenAndExit("Failed to load kernel from NAND!", 1); } InsertModule((char*)kernel_bin, kernel_bin_size); memset( (void*)0x92f00000, 0, 0x100000 ); DCFlushRange( (void*)0x92f00000, 0x100000 ); DCInvalidateRange( (void*)0x939F02F0, 0x20 ); memcpy( (void*)0x939F02F0, Boot2Patch, sizeof(Boot2Patch) ); DCFlushRange( (void*)0x939F02F0, 0x20 ); //libogc still has that, lets close it __ES_Close(); s32 fd = IOS_Open( "/dev/es", 0 ); memset( STATUS, 0xFFFFFFFF, 0x20 ); DCFlushRange( STATUS, 0x20 ); memset( (void*)0x91000000, 0xFFFFFFFF, 0x20 ); DCFlushRange( (void*)0x91000000, 0x20 ); *(vu32*)0xD3003420 = 0; //make sure kernel doesnt reload raw_irq_handler_t irq_handler = BeforeIOSReload(); IOS_IoctlvAsync( fd, 0x1F, 0, 0, &IOCTL_Buf, NULL, NULL ); AfterIOSReload( irq_handler, FoundVersion ); while(1) { DCInvalidateRange( STATUS, 0x20 ); if((STATUS_LOADING > 0 || abs(STATUS_LOADING) > 1) && STATUS_LOADING < 20) { gprintf("Kernel sent signal\n"); break; } } /* For slow USB HDDs */ time_t timeout = time(NULL); while(time(NULL) - timeout < 10) { if(__io_custom_usbstorage.startup() && __io_custom_usbstorage.isInserted()) break; usleep(50000); } fatInitDefault(); gprintf("Nintendont at your service!\r\n%s\r\n", NIN_BUILD_STRING); KernelLoaded = 1; char* first_slash = strrchr(argv[0], '/'); if (first_slash != NULL) strncpy(launch_dir, argv[0], first_slash-argv[0]+1); gprintf("launch_dir = %s\r\n", launch_dir); FPAD_Init(); FPAD_Update(); /* Read IPL Font before doing any patches */ void *fontbuffer = memalign(32, 0x50000); __SYS_ReadROM((void*)fontbuffer,0x50000,0x1AFF00); memcpy((void*)0xD3100000, fontbuffer, 0x50000); DCInvalidateRange( (void*)0x93100000, 0x50000 ); free(fontbuffer); //gprintf("Font: 0x1AFF00 starts with %.4s, 0x1FCF00 with %.4s\n", (char*)0x93100000, (char*)0x93100000 + 0x4D000); // Simple code to autoupdate the meta.xml in Nintendont's folder FILE *meta = fopen("meta.xml", "w"); if(meta != NULL) { fprintf(meta, "%s\r\n<app version=\"1\">\r\n\t<name>%s</name>\r\n", META_XML, META_NAME); fprintf(meta, "\t<coder>%s</coder>\r\n\t<version>%d.%d</version>\r\n", META_AUTHOR, NIN_VERSION>>16, NIN_VERSION&0xFFFF); fprintf(meta, "\t<release_date>20150531000000</release_date>\r\n"); fprintf(meta, "\t<short_description>%s</short_description>\r\n", META_SHORT); fprintf(meta, "\t<long_description>%s\r\n\r\n%s</long_description>\r\n", META_LONG1, META_LONG2); fprintf(meta, "\t<ahb_access/>\r\n</app>"); fclose(meta); }
void _start() { /* Get a handle to coreinit.rpl */ unsigned int coreinit_handle; OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle); //OS memory functions void* (*memcpy)(void *dest, void *src, uint32_t length); void* (*memset)(void * dest, uint32_t value, uint32_t bytes); void* (*OSAllocFromSystem)(uint32_t size, int align); void (*OSFreeToSystem)(void *ptr); OSDynLoad_FindExport(coreinit_handle, 0, "memcpy", &memcpy); OSDynLoad_FindExport(coreinit_handle, 0, "memset", &memset); OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem); OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem); void (*OSCoherencyBarrier)(); OSDynLoad_FindExport(coreinit_handle, 0, "OSCoherencyBarrier", &OSCoherencyBarrier); void (*_Exit)(); OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit); //DC memory functions void (*DCFlushRangeNoSync)(void *buffer, uint32_t length); void (*DCInvalidateRange)(void *buffer, uint32_t length); OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRangeNoSync", &DCFlushRangeNoSync); OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange); //LC memory functions void* (*LCAlloc)( uint32_t bytes ); void (*LCDealloc)(); uint32_t (*LCHardwareIsAvailable)(); uint32_t (*LCIsDMAEnabled)(); void (*LCEnableDMA)(); void (*LCDisableDMA)(); void (*LCLoadDMABlocks)(void* lc_addr, void* src_addr, uint32_t blocks); void (*LCStoreDMABlocks)(void* dest_addr, void* lc_addr, uint32_t blocks); void (*LCWaitDMAQueue)( uint32_t length ); OSDynLoad_FindExport(coreinit_handle, 0, "LCAlloc", &LCAlloc); OSDynLoad_FindExport(coreinit_handle, 0, "LCDealloc", &LCDealloc); OSDynLoad_FindExport(coreinit_handle, 0, "LCHardwareIsAvailable", &LCHardwareIsAvailable); OSDynLoad_FindExport(coreinit_handle, 0, "LCIsDMAEnabled", &LCIsDMAEnabled); OSDynLoad_FindExport(coreinit_handle, 0, "LCEnableDMA", &LCEnableDMA); OSDynLoad_FindExport(coreinit_handle, 0, "LCDisableDMA", &LCDisableDMA); OSDynLoad_FindExport(coreinit_handle, 0, "LCLoadDMABlocks", &LCLoadDMABlocks); OSDynLoad_FindExport(coreinit_handle, 0, "LCStoreDMABlocks", &LCStoreDMABlocks); OSDynLoad_FindExport(coreinit_handle, 0, "LCWaitDMAQueue", &LCWaitDMAQueue); //Used for keeping track of vairables to print to screen char output[1000]; //Alloc 64 byte alligned space void* src_addr=OSAllocFromSystem(512,64); void* dest_addr=OSAllocFromSystem(512,64); //Store some debug values __os_snprintf(output, 1000, "src_addr:%02x,",(uint32_t)src_addr); __os_snprintf(output+strlen(output), 255, "dest_addr: %02x,", (uint32_t)dest_addr); //Number of 32bit blocks to copy. Must be multiple of 2 between [0,127] uint32_t blocks=2; //2 32bit blocks //Do something to the source memset(src_addr,1,64); //Grab values for debug uint32_t * src_val=src_addr; uint32_t * dest_val=dest_addr; __os_snprintf(output+strlen(output), 255, "Old src_val: %02x\n",src_val[0]); __os_snprintf(output+strlen(output), 255, "Old dest_val: %02x,",dest_val[0]); //Get some locked cache address space void *lc_addr=LCAlloc(512); //512 Minmum. Must be multiple of 512. //Calculate size from blocks to flush/invalidate range properly uint32_t size; //If blocks is set to 0, the transaction will default to 128 blocks if(blocks==0) { size=32*128; } else { size=32*blocks; } //Flush the range at the source to ensure cache gets written back to memory. DCFlushRangeNoSync(src_addr,size); //Invalidate the range at the destination DCInvalidateRange(dest_addr,size); //Sync OSCoherencyBarrier(); //Check to see of DMA hardware is avaliable if(LCHardwareIsAvailable()!=1) { OSFatal("Hardware is not avaliable."); } //Gets the current state of DMA, so we can restore it after our copy uint32_t dmaState=LCIsDMAEnabled(); //Checks to see if DMA is enabled, if not it will try to enable it. if(dmaState!=1) { LCEnableDMA(); dmaState=LCIsDMAEnabled(); if(dmaState!=1) { OSFatal("Can't enable DMA"); } } //Load memory to locked cache LCLoadDMABlocks(lc_addr,src_addr,blocks); LCWaitDMAQueue(0); //Store memory from locked cache LCStoreDMABlocks(dest_addr,lc_addr,blocks); LCWaitDMAQueue(0); //If DMA was not previously enabled, then disable it to restore state. if(dmaState!=1) { LCDisableDMA(); dmaState=LCIsDMAEnabled(); //If DMA failed to disable, return error code if(dmaState!=1) { OSFatal("Couldn't Disable DMA"); } } __os_snprintf(output+strlen(output), 255, "New src_val: %02x,",src_val[0]); __os_snprintf(output+strlen(output), 255, "New dest_val: %02x,",dest_val[0]); //Cleanup LCDealloc(lc_addr); OSFreeToSystem(dest_addr); OSFreeToSystem(src_addr); OSFatal(output); }