u32 svcCreateThread() { u32 prio = arm11_R(0); u32 ent_pc = arm11_R(1); u32 ent_r0 = arm11_R(2); u32 ent_sp = arm11_R(3); u32 cpu = arm11_R(4); DEBUG("entrypoint=%08x, r0=%08x, sp=%08x, prio=%x, cpu=%x\n", ent_pc, ent_r0, ent_sp, prio, cpu); u32 hand = handle_New(HANDLE_TYPE_THREAD, 0); u32 numthread = threads_New(hand); threads[numthread].priority = prio; threads[numthread].r[0] = ent_r0; threads[numthread].sp = ent_sp; threads[numthread].r15 = ent_pc &~0x1; if (ent_pc & 0x1) { threads[numthread].cpsr = 0x3F; //usermode } else { threads[numthread].cpsr = 0x1F; //usermode } threads[numthread].mode = RESUME; arm11_SetR(1, hand); // r1 = handle_out return 0; }
u32 svcAcceptSession() { u32 session = arm11_R(0); u32 old_port = arm11_R(1); handleinfo* newhi = handle_Get(old_port); if (newhi == NULL) { ERROR("getting handle.\n"); return 0x0; } u32 newhand = handle_New(HANDLE_TYPE_SERVICE_SERVER, SERVICE_DIRECT); handleinfo* newhi2 = handle_Get(newhand); if (newhi2 == NULL) { ERROR("getting handle.\n"); return 0x0; } newhi2->misc[0] = newhi->misc[1]; //unlock handleinfo* anewhi = handle_Get(newhi->misc[1]); if (anewhi == NULL) { ERROR("getting handle.\n"); return 0x0; } anewhi->misc[0] |= HANDLE_SERV_STAT_OPENING; DEBUG("AcceptSession %08x %08x\n", session, newhi->misc[1]); arm11_SetR(1, newhand); return 0; }
u32 svcAcceptSession() { s32 session = arm11_R(0); u32 port = arm11_R(1); arm11_SetR(1, handle_New(HANDLE_TYPE_SESSION, port)); DEBUG("AcceptSession %08x %08x\n", session, port); return 0; }
void srv_InitGlobal() { // Create handles for all services. u32 i; for(i=0; i<ARRAY_SIZE(services); i++) { services[i].handle = handle_New(HANDLE_TYPE_SERVICE, services[i].subtype); } }
void mcu_GPU_init() { mcumutex = handle_New(HANDLE_TYPE_MUTEX, 0); handleinfo* h = handle_Get(mcumutex); if (h == NULL) { DEBUG("failed to get newly created semaphore\n"); PAUSE(); return; } h->locked = false; }
static u32 sharedextd_OpenFile(archive* self, file_path path, u32 flags, u32 attr) { char p[256], tmp[256]; // Generate path on host file system snprintf(p, 256, "sys/shared/%s/%s", self->type_specific.sharedextd.path, fs_PathToString(path.type, path.ptr, path.size, tmp, 256)); if(!fs_IsSafePath(p)) { ERROR("Got unsafe path.\n"); return 0; } if(flags != OPEN_READ) { ERROR("Trying to write/create in SharedExtData\n"); return 0; } FILE* fd = fopen(p, "rb"); if(fd == NULL) { ERROR("Failed to open SharedExtData, path=%s\n", p); return 0; } fseek(fd, 0, SEEK_END); u32 sz = 0; if((sz=ftell(fd)) == -1) { ERROR("ftell() failed.\n"); fclose(fd); return 0; } // Create file object file_type* file = calloc(sizeof(file_type), 1); if(file == NULL) { ERROR("calloc() failed.\n"); fclose(fd); return 0; } file->type_specific.sharedextd.fd = fd; file->type_specific.sharedextd.sz = (u64) sz; // Setup function pointers. file->fnRead = &sharedextdfile_Read; file->fnGetSize = &sharedextdfile_GetSize; file->fnClose = &sharedextdfile_Close; return handle_New(HANDLE_TYPE_FILE, (uintptr_t) file); }
u32 srv_InitHandle() { // Create a handle for srv: port. arm11_SetR(1, handle_New(HANDLE_TYPE_PORT, PORT_TYPE_SRV)); eventhandle = handle_New(HANDLE_TYPE_SEMAPHORE, 0); handleinfo* h = handle_Get(eventhandle); if (h == NULL) { DEBUG("failed to get newly created semaphore\n"); PAUSE(); return -1; } h->locked = true; h->misc[0] = 0x10; //there are 0x10 events we know 2 non of them are used here h->misc[1] = 0x10; return 0; }
u32 romfs_OpenFile(archive* self, file_path path, u32 flags, u32 attr) { DEBUG("romfs_OpenFile\n"); // RomFS has support for raw reads. if (path.type == PATH_BINARY) { rawromfs_file.handle = handle_New(HANDLE_TYPE_FILE, (uintptr_t)&rawromfs_file); return rawromfs_file.handle; } // XXX: Return actual file handle here return 0; }
u32 svcCreateMemoryBlock() // TODO { u32 memblock = arm11_R(0); u32 addr = arm11_R(1); u32 size = arm11_R(2); ERROR("CreateMemoryBlock addr=%08x size=%08x\n",addr,size); u32 handle = handle_New(HANDLE_TYPE_SHAREDMEM, MEM_TYPE_ALLOC); handleinfo* h = handle_Get(handle); if (h == NULL) { DEBUG("failed to get handle\n"); PAUSE(); return -1; } h->misc[0] = addr; h->misc[1] = size; h->misc_ptr[0] = malloc(size); arm11_SetR(1, handle); return 0; }
int main(int argc, char* argv[]) { atexit(AtExit); if (argc < 2) { printf("Usage:\n"); #ifdef MODULE_SUPPORT printf("%s <in.ncch> [-d|-noscreen|-codepatch <code>|-modules <num> <in.ncch>|-overdrivlist <num> <services>|-sdmc <path>|-sysdata <path>|-sdwrite|-slotone|-configsave|-gdbport <port>]\n", argv[0]); #else printf("%s <in.ncch> [-d|-noscreen|-codepatch <code>|-sdmc <path>|-sysdata <path>|-sdwrite|-slotone|-configsave|-gdbport <port>]\n", argv[0]); #endif return 1; } //disasm = (argc > 2) && (strcmp(argv[2], "-d") == 0); //noscreen = (argc > 2) && (strcmp(argv[2], "-noscreen") == 0); for (int i = 2; i < argc; i++) { if ((strcmp(argv[i], "-d") == 0))disasm = true; else if ((strcmp(argv[i], "-noscreen") == 0))noscreen = true; else if ((strcmp(argv[i], "-codepatch") == 0)) { i++; codepath = malloc(strlen(argv[i])); strcpy(codepath, argv[i]); } else if ((strcmp(argv[i], "-sdmc") == 0)) { i++; strcpy(config_sdmc_path, argv[i]); config_has_sdmc = true; } else if ((strcmp(argv[i], "-sysdata") == 0)) { i++; strcpy(config_sysdataoutpath, argv[i]); config_usesys = true; } else if ((strcmp(argv[i], "-sdwrite") == 0))config_slotone = true; else if ((strcmp(argv[i], "-slotone") == 0))config_sdmcwriteable = true; else if ((strcmp(argv[i], "-configsave") == 0))config_nand_cfg_save = true; #ifdef GDB_STUB if ((strcmp(argv[i], "-gdbport") == 0)) { i++; global_gdb_port = atoi(argv[i]); if (global_gdb_port < 1 || global_gdb_port > 65535) { DEBUG("ARM9 GDB stub port must be in the range 1 to 65535\n"); exit(-1); } gdb_ctrl_iface.stall = stall_cpu; gdb_ctrl_iface.unstall = unstall_cpu; gdb_ctrl_iface.read_reg = read_cpu_reg; gdb_ctrl_iface.set_reg = set_cpu_reg; gdb_ctrl_iface.install_post_ex_fn = install_post_exec_fn; gdb_ctrl_iface.remove_post_ex_fn = remove_post_exec_fn; gdb_base_memory_iface.prefetch16 = gdb_prefetch16; gdb_base_memory_iface.prefetch32 = gdb_prefetch32; gdb_base_memory_iface.read32 = gdb_read32; gdb_base_memory_iface.write32 = gdb_write32; gdb_base_memory_iface.read16 = gdb_read16; gdb_base_memory_iface.write16 = gdb_write16; gdb_base_memory_iface.read8 = gdb_read8; gdb_base_memory_iface.write8 = gdb_write8; } #endif if (i >= argc)break; #ifdef MODULE_SUPPORT if ((strcmp(argv[i], "-modules") == 0)) { i++; modulenum = atoi(argv[i]); modulenames = malloc(sizeof(char*)*modulenum); i++; for (int j = 0; j < modulenum; j++) { *(modulenames + j) = malloc(strlen(argv[i])); strcpy(*(modulenames + j), argv[i]); i++; } } if (i >= argc)break; if ((strcmp(argv[i], "-overdrivlist") == 0)) { i++; overdrivnum = atoi(argv[i]); overdrivnames = malloc(sizeof(char*)*modulenum); i++; for (int j = 0; j < modulenum; j++) { *(overdrivnames + j) = malloc(strlen(argv[i])); strcpy(*(overdrivnames + j), argv[i]); i++; } } if (i >= argc)break; #endif } #ifdef MODULE_SUPPORT curprocesshandlelist = malloc(sizeof(u32)*(modulenum + 1)); ModuleSupport_MemInit(modulenum); #endif signal(SIGINT, AtSig); if (!noscreen) screen_Init(); hid_spvr_init(); hid_user_init(); initDSP(); mcu_GPU_init(); initGPU(); srv_InitGlobal(); arm11_Init(); #ifdef MODULE_SUPPORT int i; for (i = 0; i<modulenum; i++) { u32 handzwei = handle_New(HANDLE_TYPE_PROCESS, 0); curprocesshandle = handzwei; *(curprocesshandlelist + i) = handzwei; ModuleSupport_SwapProcessMem(i); u32 hand = handle_New(HANDLE_TYPE_THREAD, 0); threads_New(hand); // Load file. FILE* fd = fopen(*(modulenames + i), "rb"); if (fd == NULL) { perror("Error opening file"); return 1; } if (loader_LoadFile(fd) != 0) { fclose(fd); return 1; } } u32 handzwei = handle_New(HANDLE_TYPE_PROCESS, 0); *(curprocesshandlelist + modulenum) = handzwei; ModuleSupport_SwapProcessMem(modulenum); #else u32 handzwei = handle_New(HANDLE_TYPE_PROCESS, 0); curprocesshandle = handzwei; #endif FILE* fd = fopen(argv[1], "rb"); if (fd == NULL) { perror("Error opening file"); return 1; } u32 hand = handle_New(HANDLE_TYPE_THREAD, 0); threads_New(hand); // Load file. if (loader_LoadFile(fd) != 0) { fclose(fd); return 1; } #ifdef GDB_STUB if (global_gdb_port) { gdb_stub = createStub_gdb(global_gdb_port, &gdb_memio, &gdb_base_memory_iface); if (gdb_stub == NULL) { DEBUG("Failed to create ARM9 gdbstub on port %d\n", global_gdb_port); exit(-1); } activateStub_gdb(gdb_stub, &gdb_ctrl_iface); } #endif // Execute. while (running) { if (!noscreen) screen_HandleEvent(); #ifdef MODULE_SUPPORT int k; for (k = 0; k <= modulenum; k++) { ModuleSupport_SwapProcess(k); DEBUG("Process %X\n",k); } #else threads_Execute(); #endif if (!noscreen) screen_RenderGPU(); FPS_Lock(); //mem_Dbugdump(); } fclose(fd); return 0; }
u32 srv_SyncRequest() { u32 cid = mem_Read32(arm11_ServiceBufferAddress() + 0x80); // Read command-id. switch(cid) { case 0x10002: DEBUG("srv_Initialize\n"); // XXX: check +4, flags? mem_Write32(arm11_ServiceBufferAddress() + 0x84, 0); //no error PAUSE(); return 0; case 0x20000: DEBUG("srv_GetProcSemaphore"); mem_Write32(arm11_ServiceBufferAddress() + 0x84, 0); //no error mem_Write32(arm11_ServiceBufferAddress() + 0x88, 0); //done in sm 4.4 mem_Write32(arm11_ServiceBufferAddress() + 0x8C, eventhandle); return 0; char names[9]; case 0x000400C0: DEBUG("srv_UnRegisterService --todo--\n"); // Read rest of command header mem_Read((u8*)&req, arm11_ServiceBufferAddress() + 0x84, sizeof(req)); memcpy(names, req.name, 8); names[8] = '\0'; DEBUG("name=%s, namelen=%u\n", names, req.name_len); return 0; case 0x00030100: DEBUG("srv_registerService\n"); // Read rest of command header mem_Read((u8*)&req, arm11_ServiceBufferAddress() + 0x84, sizeof(req)); memcpy(names, req.name, 8); names[8] = '\0'; DEBUG("name=%s, namelen=%u, unk=0x%x\n", names, req.name_len, req.unk2); ownservice[ownservice_num].name = malloc(9); memcpy(ownservice[ownservice_num].name, req.name, 9); ownservice[ownservice_num].handle = handle_New(HANDLE_TYPE_SERVICE, SERVICE_DIRECT); handleinfo* hi = handle_Get(ownservice[ownservice_num].handle); if (hi == NULL) { ERROR("getting handle.\n"); return 0x0; } hi->misc[0] = HANDLE_SERV_STAT_TAKEN; //init hi->misc_ptr[0] = malloc(0x200); mem_Write32(arm11_ServiceBufferAddress() + 0x84, 0); //no error mem_Write32(arm11_ServiceBufferAddress() + 0x8C, ownservice[ownservice_num].handle); //return handle ownservice_num++; return 0; case 0x50100: DEBUG("srv_GetServiceHandle\n"); // Read rest of command header mem_Read((u8*)&req, arm11_ServiceBufferAddress() + 0x84, sizeof(req)); memcpy(names, req.name, 8); names[8] = '\0'; DEBUG("name=%s, namelen=%u, unk=0x%x\n", names, req.name_len, req.unk2); PAUSE(); u32 i; bool overdr = false; for (u32 i = 0; i < overdrivnum; i++) { if (memcmp(req.name, *(overdrivnames + i), strnlen(*(overdrivnames + i), 8)) == 0)overdr = true; } if (!overdr) { for (u32 i = 0; i < ownservice_num; i++) { if (memcmp(req.name, ownservice[i].name, strnlen(ownservice[i].name, 8)) == 0) { // Write result. mem_Write32(arm11_ServiceBufferAddress() + 0x84, 0); // Write handle_out. mem_Write32(arm11_ServiceBufferAddress() + 0x8C, ownservice[i].handle); return 0; } } } for(i=0; i<ARRAY_SIZE(services); i++) { // Find service in list. if(memcmp(req.name, services[i].name, strnlen(services[i].name, 8)) == 0) { // Write result. mem_Write32(arm11_ServiceBufferAddress() + 0x84, 0); // Write handle_out. mem_Write32(arm11_ServiceBufferAddress() + 0x8C, services[i].handle); return 0; } } ERROR("Unimplemented service: %s\n", req.name); arm11_Dump(); exit(1); case 0x90040: // EnableNotificationType DEBUG("srv_EnableNotificationType\n"); u32 type = mem_Read32(arm11_ServiceBufferAddress() + 0x84); DEBUG("STUBBED, type=%x\n", type); mem_Write32(arm11_ServiceBufferAddress() + 0x84, 0); return 0; case 0xa0040: // DisableNotificationType DEBUG("srv_DisableNotificationType\n"); type = mem_Read32(arm11_ServiceBufferAddress() + 0x84); DEBUG("STUBBED, type=%x\n", type); mem_Write32(arm11_ServiceBufferAddress() + 0x84, 0); //no error return 0; case 0xB0000: // GetNotificationType DEBUG("srv_GetNotificationType\n"); //mem_Dbugdump(); mem_Write32(arm11_ServiceBufferAddress() + 0x84, 0); //worked mem_Write32(arm11_ServiceBufferAddress() + 0x88, 0); //type return 0; default: ERROR("Unimplemented command %08x in \"srv:\"\n", cid); arm11_Dump(); mem_Write32(arm11_ServiceBufferAddress() + 0x84, 0xFFFFFFFF); //worked return 0; //exit(1); } return 0; }