static void *alloc_gpu_mem(uint32_t type, uint32_t size, uint32_t attribs, SceUID *uid) { int ret; void *mem = NULL; if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW) size = align_mem(size, 256 * 1024); else size = align_mem(size, 4 * 1024); *uid = sceKernelAllocMemBlock("gxm", type, size, NULL); printf("MemBlock uid: 0x%08X\n", *uid); ret = sceKernelGetMemBlockBase(*uid, &mem); printf("sceKernelGetMemBlockBase(): 0x%08X\n", ret); printf("MemBlockBase addr: %p\n", mem); if (ret != 0) { return NULL; } ret = sceGxmMapMemory(mem, size, attribs); printf("sceGxmMapMemory(): 0x%08X\n", ret); if (ret != 0) { return NULL; } return mem; }
void co_init() { int ret; void *base; block = sceKernelAllocMemBlockForVM("libco", MB_ALIGN(FOUR_KB_ALIGN(sizeof co_swap_function))); if (block < 0) return; /* get base address */ ret = sceKernelGetMemBlockBase(block, &base); if (ret < 0) return; /* set domain to be writable by user */ ret = sceKernelOpenVMDomain(); if (ret < 0) return; memcpy(base, co_swap_function, sizeof co_swap_function); /* set domain back to read-only */ ret = sceKernelCloseVMDomain(); if (ret < 0) return; /* flush icache */ ret = sceKernelSyncVMDomain(block, base, MB_ALIGN(FOUR_KB_ALIGN(sizeof co_swap_function))); if (ret < 0) return; co_swap = (void(*)(cothread_t, cothread_t))base; }
/********************************************//** * \brief Loads file to memory * * \returns Zero on success, otherwise error ***********************************************/ int uvl_load_file (const char *filename, ///< File to load void **data, ///< Output pointer to data PsvSSize *size) ///< Output pointer to data size { PsvUID fd; PsvUID memblock; char *base; PsvOff filesz; PsvOff nread; PsvSSize nbytes; fd = sceIoOpen (filename, PSP2_O_RDONLY, 0); if (fd < 0) { LOG ("Failed to open %s for reading.", filename); return -1; } filesz = sceIoLseek (fd, 0LL, PSP2_SEEK_END); if (filesz < 0) { LOG ("Failed to find file size: 0x%X", filesz); return -1; } sceIoLseek (fd, 0LL, PSP2_SEEK_SET); memblock = sceKernelAllocMemBlock ("UVLTemp", 0xC20D060, (filesz + 0xFFF) & ~0xFFF, NULL); if (memblock < 0) { LOG ("Failed allocate %u bytes of memory.", memblock); return -1; } if (sceKernelGetMemBlockBase (memblock, &base) < 0) { LOG ("Failed to locate base for block 0x%08X.", memblock); return -1; } base = (char *)(((u32_t)base + 0xFFF) & ~0xFFF); // align memory base nbytes = 0; while ((nread = sceIoRead (fd, base+nbytes, filesz)) < filesz-nbytes) { nbytes += nread; } if (nbytes < 0) { LOG ("Failed to read %s: 0x%08X", filename, nbytes); return -1; } IF_DEBUG LOG ("Read %u bytes from %s", nbytes, filename); if (sceIoClose (fd) < 0) { LOG ("Failed to close file."); return -1; } *data = base; *size = nbytes; return 0; }
void fragment_usse_free(SceUID uid) { void *mem = NULL; if (sceKernelGetMemBlockBase(uid, &mem) < 0) return; sceGxmUnmapFragmentUsseMemory(mem); sceKernelFreeMemBlock(uid); }
void vertex_usse_free(SceUID uid) { void *mem = NULL; if (sceKernelGetMemBlockBase(uid, &mem) < 0) return; sceGxmUnmapVertexUsseMemory(mem); sceKernelFreeMemBlock(uid); }
void gpu_free(SceUID uid) { void *mem = NULL; if (sceKernelGetMemBlockBase(uid, &mem) < 0) return; sceGxmUnmapMemory(mem); sceKernelFreeMemBlock(uid); }
code_pool::code_pool(uint32_t icount) : instruction_count(icount), instructions(0), next_instruction(0), flush_start(0) { printf("\n\ncode_pool icount: %i\n\n", icount); memset(labels, 0, sizeof(labels)); memset(branches, 0, sizeof(branches)); #ifdef USE_POSIX_MEMALIGN if (posix_memalign((void**)&instructions, 4096, instruction_count * 4)) { fprintf(stderr, "posix_memalign failed\n"); abort(); } #elif defined(_3DS) if(!_instructions){ _instructions = (uint32_t*)memalign(4096, instruction_count * 4); if (!_instructions) { fprintf(stderr, "memalign failed\n"); abort(); } ReprotectMemory((unsigned int*)_instructions, (instruction_count * 4) / 4096, 7); } instructions = _instructions; #elif defined(__vita__) block = sceKernelAllocMemBlockForVM("desmume_rwx_block", instruction_count * 4); if (block < 0) { fprintf(stderr, "sceKernelAllocMemBlockForVM failed\n"); abort(); } if (sceKernelGetMemBlockBase(block, (void **)&instructions) < 0) { fprintf(stderr, "sceKernelGetMemBlockBase failed\n"); abort(); } #else instructions = (uint32_t*)memalign(4096, instruction_count * 4); if (!instructions) { fprintf(stderr, "memalign failed\n"); abort(); } #endif #if !defined(_3DS) && !defined(__vita__) if (mprotect(instructions, instruction_count * 4, PROT_READ | PROT_WRITE | PROT_EXEC)) { fprintf(stderr, "mprotect failed\n"); abort(); } #endif }
void *fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset) { void *mem = NULL; size = ALIGN(size, 4096); *uid = sceKernelAllocMemBlock("fragment_usse", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL); if (sceKernelGetMemBlockBase(*uid, &mem) < 0) return NULL; if (sceGxmMapFragmentUsseMemory(mem, size, usse_offset) < 0) return NULL; return mem; }
void _init_vita_heap(void) { int _newlib_vm_size = 0; if (&_newlib_vm_size_user != NULL) { _newlib_vm_size = _newlib_vm_size_user; _newlib_vm_memblock = sceKernelAllocMemBlockForVM("code", _newlib_vm_size_user); if (_newlib_vm_memblock < 0){ //sceClibPrintf("sceKernelAllocMemBlockForVM failed\n"); goto failure; } }else{ _newlib_vm_memblock = 0; } // Create a mutex to use inside _sbrk_r if (sceKernelCreateLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex, "sbrk mutex", 0, 0, 0) < 0) { goto failure; } _newlib_heap_size = _newlib_heap_size_user; _newlib_heap_size -= _newlib_vm_size; _newlib_heap_memblock = sceKernelAllocMemBlock("Newlib heap", 0x0c20d060, _newlib_heap_size, 0); if (_newlib_heap_memblock < 0) { goto failure; } if (sceKernelGetMemBlockBase(_newlib_heap_memblock, (void**)&_newlib_heap_base) < 0) { goto failure; } _newlib_heap_end = _newlib_heap_base + _newlib_heap_size; _newlib_heap_cur = _newlib_heap_base; return; failure: _newlib_vm_memblock = 0; _newlib_heap_memblock = 0; _newlib_heap_base = 0; _newlib_heap_cur = 0; }
void *gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid) { void *mem; if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW) { size = ALIGN(size, 256*1024); } else { size = ALIGN(size, 4*1024); } *uid = sceKernelAllocMemBlock("gpu_mem", type, size, NULL); if (*uid < 0) return NULL; if (sceKernelGetMemBlockBase(*uid, &mem) < 0) return NULL; if (sceGxmMapMemory(mem, size, attribs) < 0) return NULL; return mem; }
int main(void){ void* base; SceUID memblock = sceKernelAllocMemBlock("camera", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, 256 * 1024 * 5, NULL); sceKernelGetMemBlockBase(memblock, &base); SceDisplayFrameBuf dbuf = { sizeof(SceDisplayFrameBuf), base, DISPLAY_WIDTH, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT}; int cur_res = 1;// 1-8 (maybe more) int cur_cam = 0;//front:0, back:1 int cur_fps = 6; int cur_fmt = 5; sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG); SceCtrlData ctrl_peek;SceCtrlData ctrl_press; do{ int cur_sat=0,cur_rev=0,cur_efx=0,cur_iso=0,cur_zom=10,cur_nim=0,cur_wbl=0; size_t res_table[][2] = {{0,0},{640,480},{320,240},{160,120},{352,288},{176,144},{480,272},{640,360},{640,360}}; size_t fps_table[] = {3,5,7,10,15,20,30}; sceCameraOpen(cur_cam, &(SceCameraInfo){ .size = sizeof(SceCameraInfo), .format = cur_fmt,//422_TO_ABGR .resolution = cur_res, .framerate = fps_table[cur_fps], .sizeIBase = 4*res_table[cur_res][0]*res_table[cur_res][1], .pitch = 4*(DISPLAY_WIDTH-res_table[cur_res][0]), .pIBase = base, }); sceCameraStart(cur_cam); do{ ctrl_press = ctrl_peek; sceCtrlPeekBufferPositive(0, &ctrl_peek, 1); ctrl_press.buttons = ctrl_peek.buttons & ~ctrl_press.buttons; sceCameraSetBrightness(cur_cam, ctrl_press.rx); sceCameraSetContrast(cur_cam, ctrl_press.ry-100); sceCameraSetEV(cur_cam, (ctrl_press.lx-128)/7);//-20...20 sceCameraSetGain(cur_cam, (ctrl_press.ly<100)?ctrl_press.ly/6:0);//0..16 //don't seem to work if(ctrl_press.buttons & SCE_CTRL_TRIANGLE) sceCameraSetSaturation(cur_cam, cur_sat=((cur_sat+5)%45)); if(ctrl_press.buttons & SCE_CTRL_CIRCLE) sceCameraSetReverse(cur_cam, cur_rev=((cur_rev+1)%4)); if(ctrl_press.buttons & SCE_CTRL_CROSS) sceCameraSetISO(cur_cam,(int[]){1,100,200,400}[cur_iso=((cur_iso+1)%4)]); if(ctrl_press.buttons & SCE_CTRL_SQUARE) sceCameraSetEffect(cur_cam, cur_efx=((cur_efx+1)%7)); if(ctrl_press.buttons & SCE_CTRL_LTRIGGER) sceCameraSetWhiteBalance(cur_cam, cur_wbl=((cur_wbl+1)%4)); if(ctrl_press.buttons & SCE_CTRL_RTRIGGER) sceCameraSetNightmode(cur_cam, cur_nim=((cur_nim+1)%4)); if(ctrl_press.buttons & SCE_CTRL_SELECT) sceCameraSetZoom(cur_cam, cur_zom=((cur_zom+1)%41)); /* TODO: find more button combo to trigg : sceCameraSetAntiFlicker(int cur_cam, int mode); sceCameraSetBacklight(int cur_cam, int mode); */ if(sceCameraIsActive(cur_cam)>0){ SceCameraRead read = {sizeof(SceCameraRead),0/*<Blocking*/}; sceCameraRead(cur_cam, &read); sceDisplaySetFrameBuf(&dbuf, SCE_DISPLAY_SETBUF_NEXTFRAME); } }while(!(ctrl_press.buttons & (SCE_CTRL_UP|SCE_CTRL_DOWN|SCE_CTRL_LEFT|SCE_CTRL_RIGHT|SCE_CTRL_START))); sceCameraStop(cur_cam); sceCameraClose(cur_cam); if(ctrl_press.buttons & SCE_CTRL_UP) cur_res=(cur_res+1)%ARRAYSIZE(res_table); if(ctrl_press.buttons & SCE_CTRL_DOWN) cur_cam=(cur_cam+1)%2; if(ctrl_press.buttons & SCE_CTRL_LEFT) cur_fps=(cur_fps+1)%ARRAYSIZE(fps_table); //may overflow the drawbuffer => TODO:reallocate drawbuff on format change //if(ctrl_press.buttons & SCE_CTRL_RIGHT) // cur_fmt=(cur_fmt+1)%9; }while(!(ctrl_press.buttons & SCE_CTRL_START));
/********************************************//** * \brief Loads an ELF file * * Performs both loading and resolving NIDs * \returns Zero on success, otherwise error ***********************************************/ int uvl_load_elf (void *data, ///< ELF data start void **entry, ///< Returned pointer to entry pointer uvl_loaded_t *loaded) ///< Pointer to loaded info { Elf32_Ehdr_t *elf_hdr; u32_t i; int addend; *entry = NULL; // get headers IF_VERBOSE LOG ("Reading headers."); elf_hdr = data; IF_DEBUG LOG ("Checking headers."); if (uvl_elf_check_header (elf_hdr) < 0) { LOG ("Check header failed."); return -1; } // get program headers Elf32_Phdr_t *prog_hdrs; IF_VERBOSE LOG ("Reading program headers."); prog_hdrs = (void*)((u32_t)data + elf_hdr->e_phoff); loaded->numsegs = elf_hdr->e_phnum; if (sizeof (PsvUID) * loaded->numsegs + sizeof (*loaded) > LOADED_INFO_SIZE) { LOG ("Too many segments: %d", elf_hdr->e_phnum); return -1; } // actually load the ELF PsvUID memblock; void *blockaddr; u32_t length; if (elf_hdr->e_phnum < 1) { LOG ("No program sections to load!"); return -1; } IF_DEBUG LOG ("Loading %u program segments.", elf_hdr->e_phnum); for (i = 0; i < elf_hdr->e_phnum; i++) { if (prog_hdrs[i].p_type == PT_LOAD) { length = prog_hdrs[i].p_memsz; length = (length + 0xFFFFF) & ~0xFFFFF; // Align to 1MB if (prog_hdrs[i].p_flags & PF_X == PF_X) // executable section { memblock = sceKernelAllocCodeMemBlock ("UVLHomebrew", length); } else // data section { memblock = sceKernelAllocMemBlock ("UVLHomebrew", 0xC20D060, length, NULL); } if (memblock < 0) { LOG ("Error allocating memory. 0x%08X", memblock); return -1; } if (sceKernelGetMemBlockBase (memblock, &blockaddr) < 0) { LOG ("Error getting memory block address."); } // remember where we're loaded loaded->segs[i] = memblock; prog_hdrs[i].p_vaddr = blockaddr; IF_DEBUG LOG ("Allocated memory at 0x%08X, attempting to load segment %u.", (u32_t)blockaddr, i); uvl_segment_write (&prog_hdrs[i], 0, (void*)((u32_t)data + prog_hdrs[i].p_offset), prog_hdrs[i].p_filesz); uvl_unlock_mem (); memset ((void*)((u32_t)blockaddr + prog_hdrs[i].p_filesz), 0, prog_hdrs[i].p_memsz - prog_hdrs[i].p_filesz); uvl_lock_mem (); } else if (prog_hdrs[i].p_type == PT_SCE_RELA) { uvl_relocate ((void*)((u32_t)data + prog_hdrs[i].p_offset), prog_hdrs[i].p_filesz, prog_hdrs); } else { IF_DEBUG LOG ("Segment %u is not loadable. Skipping.", i); continue; } } // get mod_info module_info_t *mod_info; int idx; IF_DEBUG LOG ("Getting module info."); if ((idx = uvl_elf_get_module_info (elf_hdr, prog_hdrs, &mod_info)) < 0) { LOG ("Cannot find module info section."); return -1; } IF_DEBUG LOG ("Module name: %s, export table offset: 0x%08X, import table offset: 0x%08X", mod_info->modname, mod_info->ent_top, mod_info->stub_top); // resolve NIDs uvl_unlock_mem (); g_import_start = (void*)(prog_hdrs[idx].p_vaddr + mod_info->stub_top); g_import_end = (void*)(prog_hdrs[idx].p_vaddr + mod_info->stub_end); uvl_lock_mem (); module_imports_t *import = g_import_start; void *end = g_import_end; for (; (void *)import < end; import = IMP_GET_NEXT (import)) { IF_DEBUG LOG ("Resolving imports for %s", IMP_GET_NAME (import)); if (uvl_resolve_imports (import) < 0) { LOG ("Failed to resolve imports for %s", IMP_GET_NAME (import)); return -1; } } // find the entry point *entry = (void*)(prog_hdrs[idx].p_vaddr + mod_info->mod_start); if (*entry == NULL) { LOG ("Invalid module entry function.\n"); return -1; } return 0; }
_start(UVL_Context *ctx) { void * const vhlStubTop = getVhlStubTop(); void * const vhlPrimaryStubTop = (void *)((uintptr_t)vhlStubTop + 16); void * const vhlPrimaryStubBtm = (void *)((uintptr_t)vhlPrimaryStubTop + vhlPrimaryStubSize); const SceModuleImports * cachedImports[CACHED_IMPORTED_MODULE_NUM]; nidTable_entry libkernelBase; SceModuleInfo *libkernelInfo; SceUID uid; void *p; int err; ctx->logline("Starting VHL..."); /* It may get wrong if you change the order of nid_table_resolveVhl* See stub.S to know what imports will be resolved with those functions. */ ctx->logline("Resolving VHL puts"); nid_table_resolveVhlPuts(vhlStubTop, ctx); ctx->psvFlushIcache(vhlStubTop, 16); DEBUG_LOG_("Searching for SceLibKernel"); if (nid_table_analyzeStub(ctx->libkernel_anchor, 0, &libkernelBase) != ANALYZE_STUB_OK) { DEBUG_LOG_("Failed to find the base of SceLibKernel"); return -1; } libkernelBase.value.i = B_UNSET(libkernelBase.value.i, 0); libkernelInfo = nid_table_findModuleInfo(libkernelBase.value.p, KERNEL_MODULE_SIZE, "SceLibKernel"); if (libkernelInfo == NULL) { DEBUG_LOG_("Failed to find the module information of SceLibKernel"); return -1; } DEBUG_LOG_("Searching for cached imports"); nidCacheFindCachedImports(libkernelInfo, cachedImports); DEBUG_LOG_("Resolving VHL primary imports"); nid_table_resolveVhlPrimaryImports(vhlPrimaryStubTop, vhlPrimaryStubSize, libkernelInfo, cachedImports, ctx); ctx->psvFlushIcache(vhlPrimaryStubTop, vhlPrimaryStubSize); DEBUG_LOG_("Allocating memory for VHL"); uid = sceKernelAllocMemBlock("vhlGlobals", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW, FOUR_KB_ALIGN(sizeof(globals_t)), NULL); if (uid < 0) { DEBUG_LOG("Failed to allocate memory block 0x%08X", uid); return uid; } err = sceKernelGetMemBlockBase(uid, &p); if (err < 0) { DEBUG_LOG("Failed to retrive memory block 0x%08X", err); return uid; } ctx->psvUnlockMem(); globals = p; ctx->psvLockMem(); DEBUG_LOG_("Initializing table"); nid_storage_initialize(); DEBUG_LOG_("Searching and Adding stubs to table..."); nid_table_addAllStubs(); DEBUG_LOG_("Resolving VHL secondary imports"); nid_table_resolveVhlSecondaryImports(vhlPrimaryStubBtm, vhlSecondaryStubSize, libkernelInfo, cachedImports, ctx); ctx->psvFlushIcache(vhlPrimaryStubBtm, vhlSecondaryStubSize); DEBUG_LOG_("Adding stubs to table with cache"); if (nid_table_addNIDCacheToTable(cachedImports) < 0) return -1; DEBUG_LOG_("Adding hooks to table"); nid_table_addAllHooks(); //TODO find a way to free unused memory block_manager_initialize(); //Initialize the elf block slots //TODO decide how to handle plugins config_initialize(); DEBUG_LOG_("Loading menu..."); if(elf_parser_load(globals->allocatedBlocks, "pss0:/top/Documents/homebrew.self", NULL) < 0) { internal_printf("Load failed!"); return -1; } puts("Load succeeded! Launching!"); elf_parser_start(globals->allocatedBlocks, 0); while(1) { //Delay thread and check for flags and things to update every once in a while, check for exit combination //calls.LogLine("Menu exited! Relaunching..."); sceKernelDelayThread(16000); //Update stuff once every 16 ms } return 0; }