diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/citra/default_ini.h | 2 | ||||
| -rw-r--r-- | src/citra_qt/bootmanager.cpp | 21 | ||||
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom.cpp | 11 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 115 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.h | 2 | ||||
| -rw-r--r-- | src/core/core.h | 12 | ||||
| -rw-r--r-- | src/core/hle/service/apt_u.cpp | 109 | ||||
| -rw-r--r-- | src/core/hle/service/frd_u.cpp | 35 | ||||
| -rw-r--r-- | src/core/hle/service/frd_u.h | 27 | ||||
| -rw-r--r-- | src/core/hle/service/service.cpp | 2 |
11 files changed, 238 insertions, 100 deletions
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index 7352c70c2..557da881b 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h | |||
| @@ -28,7 +28,7 @@ pad_sright = | |||
| 28 | 28 | ||
| 29 | [Core] | 29 | [Core] |
| 30 | cpu_core = ## 0: Interpreter (default), 1: FastInterpreter (experimental) | 30 | cpu_core = ## 0: Interpreter (default), 1: FastInterpreter (experimental) |
| 31 | gpu_refresh_rate = ## 60 (default), 1024 or 2048 may work better on the FastInterpreter | 31 | gpu_refresh_rate = ## 60 (default) |
| 32 | 32 | ||
| 33 | [Data Storage] | 33 | [Data Storage] |
| 34 | use_virtual_sd = | 34 | use_virtual_sd = |
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 8f3799351..20824692d 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp | |||
| @@ -33,19 +33,16 @@ void EmuThread::run() | |||
| 33 | stop_run = false; | 33 | stop_run = false; |
| 34 | while (!stop_run) | 34 | while (!stop_run) |
| 35 | { | 35 | { |
| 36 | for (int tight_loop = 0; tight_loop < 10000; ++tight_loop) | 36 | if (cpu_running) |
| 37 | { | 37 | { |
| 38 | if (cpu_running || exec_cpu_step) | 38 | Core::RunLoop(); |
| 39 | { | 39 | } |
| 40 | if (exec_cpu_step) | 40 | else if (exec_cpu_step) |
| 41 | exec_cpu_step = false; | 41 | { |
| 42 | 42 | exec_cpu_step = false; | |
| 43 | Core::SingleStep(); | 43 | Core::SingleStep(); |
| 44 | if (!cpu_running) { | 44 | emit CPUStepped(); |
| 45 | emit CPUStepped(); | 45 | yieldCurrentThread(); |
| 46 | yieldCurrentThread(); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | } | 46 | } |
| 50 | } | 47 | } |
| 51 | render_window->moveContext(); | 48 | render_window->moveContext(); |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f67481359..f41d52e80 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -36,6 +36,7 @@ set(SRCS | |||
| 36 | hle/service/dsp_dsp.cpp | 36 | hle/service/dsp_dsp.cpp |
| 37 | hle/service/err_f.cpp | 37 | hle/service/err_f.cpp |
| 38 | hle/service/fs_user.cpp | 38 | hle/service/fs_user.cpp |
| 39 | hle/service/frd_u.cpp | ||
| 39 | hle/service/gsp_gpu.cpp | 40 | hle/service/gsp_gpu.cpp |
| 40 | hle/service/hid_user.cpp | 41 | hle/service/hid_user.cpp |
| 41 | hle/service/mic_u.cpp | 42 | hle/service/mic_u.cpp |
| @@ -106,6 +107,7 @@ set(HEADERS | |||
| 106 | hle/service/dsp_dsp.h | 107 | hle/service/dsp_dsp.h |
| 107 | hle/service/err_f.h | 108 | hle/service/err_f.h |
| 108 | hle/service/fs_user.h | 109 | hle/service/fs_user.h |
| 110 | hle/service/frd_u.h | ||
| 109 | hle/service/gsp_gpu.h | 111 | hle/service/gsp_gpu.h |
| 110 | hle/service/hid_user.h | 112 | hle/service/hid_user.h |
| 111 | hle/service/mic_u.h | 113 | hle/service/mic_u.h |
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index 669b612fc..a3ed3e31e 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp | |||
| @@ -60,7 +60,7 @@ void ARM_DynCom::SetPC(u32 pc) { | |||
| 60 | * @return Returns current PC | 60 | * @return Returns current PC |
| 61 | */ | 61 | */ |
| 62 | u32 ARM_DynCom::GetPC() const { | 62 | u32 ARM_DynCom::GetPC() const { |
| 63 | return state->pc; | 63 | return state->Reg[15]; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | /** | 66 | /** |
| @@ -110,9 +110,12 @@ u64 ARM_DynCom::GetTicks() const { | |||
| 110 | * @param num_instructions Number of instructions to executes | 110 | * @param num_instructions Number of instructions to executes |
| 111 | */ | 111 | */ |
| 112 | void ARM_DynCom::ExecuteInstructions(int num_instructions) { | 112 | void ARM_DynCom::ExecuteInstructions(int num_instructions) { |
| 113 | ticks += num_instructions; | ||
| 114 | state->NumInstrsToExecute = num_instructions; | 113 | state->NumInstrsToExecute = num_instructions; |
| 115 | InterpreterMainLoop(state.get()); | 114 | |
| 115 | // Dyncom only breaks on instruction dispatch. This only happens on every instruction when | ||
| 116 | // executing one instruction at a time. Otherwise, if a block is being executed, more | ||
| 117 | // instructions may actually be executed than specified. | ||
| 118 | ticks += InterpreterMainLoop(state.get()); | ||
| 116 | } | 119 | } |
| 117 | 120 | ||
| 118 | /** | 121 | /** |
| @@ -126,7 +129,7 @@ void ARM_DynCom::SaveContext(ThreadContext& ctx) { | |||
| 126 | 129 | ||
| 127 | ctx.sp = state->Reg[13]; | 130 | ctx.sp = state->Reg[13]; |
| 128 | ctx.lr = state->Reg[14]; | 131 | ctx.lr = state->Reg[14]; |
| 129 | ctx.pc = state->pc; | 132 | ctx.pc = state->Reg[15]; |
| 130 | ctx.cpsr = state->Cpsr; | 133 | ctx.cpsr = state->Cpsr; |
| 131 | 134 | ||
| 132 | ctx.fpscr = state->VFP[1]; | 135 | ctx.fpscr = state->VFP[1]; |
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index fe1501b59..f899e2e8a 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -3718,7 +3718,7 @@ static bool InAPrivilegedMode(arm_core_t *core) | |||
| 3718 | } | 3718 | } |
| 3719 | 3719 | ||
| 3720 | /* r15 = r15 + 8 */ | 3720 | /* r15 = r15 + 8 */ |
| 3721 | void InterpreterMainLoop(ARMul_State* state) | 3721 | unsigned InterpreterMainLoop(ARMul_State* state) |
| 3722 | { | 3722 | { |
| 3723 | #define CRn inst_cream->crn | 3723 | #define CRn inst_cream->crn |
| 3724 | #define OPCODE_2 inst_cream->opcode_2 | 3724 | #define OPCODE_2 inst_cream->opcode_2 |
| @@ -3747,16 +3747,22 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 3747 | #endif | 3747 | #endif |
| 3748 | 3748 | ||
| 3749 | #define FETCH_INST if (inst_base->br != NON_BRANCH) \ | 3749 | #define FETCH_INST if (inst_base->br != NON_BRANCH) \ |
| 3750 | goto PROFILING; \ | 3750 | goto DISPATCH; \ |
| 3751 | inst_base = (arm_inst *)&inst_buf[ptr] | 3751 | inst_base = (arm_inst *)&inst_buf[ptr] |
| 3752 | #define INC_PC(l) ptr += sizeof(arm_inst) + l | 3752 | #define INC_PC(l) ptr += sizeof(arm_inst) + l |
| 3753 | 3753 | ||
| 3754 | // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a | 3754 | // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a |
| 3755 | // clunky switch statement. | 3755 | // clunky switch statement. |
| 3756 | #if defined __GNUC__ || defined __clang__ | 3756 | #if defined __GNUC__ || defined __clang__ |
| 3757 | #define GOTO_NEXT_INST goto *InstLabel[inst_base->idx] | 3757 | #define GOTO_NEXT_INST \ |
| 3758 | if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ | ||
| 3759 | num_instrs++; \ | ||
| 3760 | goto *InstLabel[inst_base->idx] | ||
| 3758 | #else | 3761 | #else |
| 3759 | #define GOTO_NEXT_INST switch(inst_base->idx) { \ | 3762 | #define GOTO_NEXT_INST \ |
| 3763 | if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ | ||
| 3764 | num_instrs++; \ | ||
| 3765 | switch(inst_base->idx) { \ | ||
| 3760 | case 0: goto VMLA_INST; \ | 3766 | case 0: goto VMLA_INST; \ |
| 3761 | case 1: goto VMLS_INST; \ | 3767 | case 1: goto VMLS_INST; \ |
| 3762 | case 2: goto VNMLA_INST; \ | 3768 | case 2: goto VNMLA_INST; \ |
| @@ -4028,20 +4034,15 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4028 | unsigned int addr; | 4034 | unsigned int addr; |
| 4029 | unsigned int phys_addr; | 4035 | unsigned int phys_addr; |
| 4030 | unsigned int last_pc = 0; | 4036 | unsigned int last_pc = 0; |
| 4037 | unsigned int num_instrs = 0; | ||
| 4031 | fault_t fault; | 4038 | fault_t fault; |
| 4032 | static unsigned int last_physical_base = 0, last_logical_base = 0; | 4039 | static unsigned int last_physical_base = 0, last_logical_base = 0; |
| 4033 | int ptr; | 4040 | int ptr; |
| 4041 | bool single_step = (cpu->NumInstrsToExecute == 1); | ||
| 4034 | 4042 | ||
| 4035 | LOAD_NZCVT; | 4043 | LOAD_NZCVT; |
| 4036 | DISPATCH: | 4044 | DISPATCH: |
| 4037 | { | 4045 | { |
| 4038 | if (cpu->NumInstrsToExecute == 0) | ||
| 4039 | return; | ||
| 4040 | |||
| 4041 | cpu->NumInstrsToExecute--; | ||
| 4042 | |||
| 4043 | //NOTICE_LOG(ARM11, "instr!"); | ||
| 4044 | |||
| 4045 | if (!cpu->NirqSig) { | 4046 | if (!cpu->NirqSig) { |
| 4046 | if (!(cpu->Cpsr & 0x80)) { | 4047 | if (!(cpu->Cpsr & 0x80)) { |
| 4047 | goto END; | 4048 | goto END; |
| @@ -4179,10 +4180,6 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4179 | inst_base = (arm_inst *)&inst_buf[ptr]; | 4180 | inst_base = (arm_inst *)&inst_buf[ptr]; |
| 4180 | GOTO_NEXT_INST; | 4181 | GOTO_NEXT_INST; |
| 4181 | } | 4182 | } |
| 4182 | PROFILING: | ||
| 4183 | { | ||
| 4184 | goto DISPATCH; | ||
| 4185 | } | ||
| 4186 | ADC_INST: | 4183 | ADC_INST: |
| 4187 | { | 4184 | { |
| 4188 | INC_ICOUNTER; | 4185 | INC_ICOUNTER; |
| @@ -4207,7 +4204,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4207 | } | 4204 | } |
| 4208 | if (inst_cream->Rd == 15) { | 4205 | if (inst_cream->Rd == 15) { |
| 4209 | INC_PC(sizeof(adc_inst)); | 4206 | INC_PC(sizeof(adc_inst)); |
| 4210 | goto PROFILING; | 4207 | goto DISPATCH; |
| 4211 | } | 4208 | } |
| 4212 | } | 4209 | } |
| 4213 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4210 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4241,7 +4238,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4241 | } | 4238 | } |
| 4242 | if (inst_cream->Rd == 15) { | 4239 | if (inst_cream->Rd == 15) { |
| 4243 | INC_PC(sizeof(add_inst)); | 4240 | INC_PC(sizeof(add_inst)); |
| 4244 | goto PROFILING; | 4241 | goto DISPATCH; |
| 4245 | } | 4242 | } |
| 4246 | } | 4243 | } |
| 4247 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4244 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4272,7 +4269,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4272 | } | 4269 | } |
| 4273 | if (inst_cream->Rd == 15) { | 4270 | if (inst_cream->Rd == 15) { |
| 4274 | INC_PC(sizeof(and_inst)); | 4271 | INC_PC(sizeof(and_inst)); |
| 4275 | goto PROFILING; | 4272 | goto DISPATCH; |
| 4276 | } | 4273 | } |
| 4277 | } | 4274 | } |
| 4278 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4275 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4290,11 +4287,11 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4290 | } | 4287 | } |
| 4291 | SET_PC; | 4288 | SET_PC; |
| 4292 | INC_PC(sizeof(bbl_inst)); | 4289 | INC_PC(sizeof(bbl_inst)); |
| 4293 | goto PROFILING; | 4290 | goto DISPATCH; |
| 4294 | } | 4291 | } |
| 4295 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4292 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 4296 | INC_PC(sizeof(bbl_inst)); | 4293 | INC_PC(sizeof(bbl_inst)); |
| 4297 | goto PROFILING; | 4294 | goto DISPATCH; |
| 4298 | } | 4295 | } |
| 4299 | BIC_INST: | 4296 | BIC_INST: |
| 4300 | { | 4297 | { |
| @@ -4322,7 +4319,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4322 | } | 4319 | } |
| 4323 | if (inst_cream->Rd == 15) { | 4320 | if (inst_cream->Rd == 15) { |
| 4324 | INC_PC(sizeof(bic_inst)); | 4321 | INC_PC(sizeof(bic_inst)); |
| 4325 | goto PROFILING; | 4322 | goto DISPATCH; |
| 4326 | } | 4323 | } |
| 4327 | } | 4324 | } |
| 4328 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4325 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4358,12 +4355,12 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4358 | //DEBUG_MSG; | 4355 | //DEBUG_MSG; |
| 4359 | } | 4356 | } |
| 4360 | INC_PC(sizeof(blx_inst)); | 4357 | INC_PC(sizeof(blx_inst)); |
| 4361 | goto PROFILING; | 4358 | goto DISPATCH; |
| 4362 | } | 4359 | } |
| 4363 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4360 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 4364 | // INC_PC(sizeof(bx_inst)); | 4361 | // INC_PC(sizeof(bx_inst)); |
| 4365 | INC_PC(sizeof(blx_inst)); | 4362 | INC_PC(sizeof(blx_inst)); |
| 4366 | goto PROFILING; | 4363 | goto DISPATCH; |
| 4367 | } | 4364 | } |
| 4368 | BX_INST: | 4365 | BX_INST: |
| 4369 | { | 4366 | { |
| @@ -4376,12 +4373,12 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4376 | cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe; | 4373 | cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe; |
| 4377 | // cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1; | 4374 | // cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1; |
| 4378 | INC_PC(sizeof(bx_inst)); | 4375 | INC_PC(sizeof(bx_inst)); |
| 4379 | goto PROFILING; | 4376 | goto DISPATCH; |
| 4380 | } | 4377 | } |
| 4381 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4378 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 4382 | // INC_PC(sizeof(bx_inst)); | 4379 | // INC_PC(sizeof(bx_inst)); |
| 4383 | INC_PC(sizeof(bx_inst)); | 4380 | INC_PC(sizeof(bx_inst)); |
| 4384 | goto PROFILING; | 4381 | goto DISPATCH; |
| 4385 | } | 4382 | } |
| 4386 | BXJ_INST: | 4383 | BXJ_INST: |
| 4387 | CDP_INST: | 4384 | CDP_INST: |
| @@ -4393,7 +4390,8 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4393 | #define CP_ACCESS_ALLOW 0 | 4390 | #define CP_ACCESS_ALLOW 0 |
| 4394 | if(CP_ACCESS_ALLOW){ | 4391 | if(CP_ACCESS_ALLOW){ |
| 4395 | /* undefined instruction here */ | 4392 | /* undefined instruction here */ |
| 4396 | return; | 4393 | cpu->NumInstrsToExecute = 0; |
| 4394 | return num_instrs; | ||
| 4397 | } | 4395 | } |
| 4398 | ERROR_LOG(ARM11, "CDP insn inst=0x%x, pc=0x%x\n", inst_cream->inst, cpu->Reg[15]); | 4396 | ERROR_LOG(ARM11, "CDP insn inst=0x%x, pc=0x%x\n", inst_cream->inst, cpu->Reg[15]); |
| 4399 | unsigned cpab = (cpu->CDP[inst_cream->cp_num]) (cpu, ARMul_FIRST, inst_cream->inst); | 4397 | unsigned cpab = (cpu->CDP[inst_cream->cp_num]) (cpu, ARMul_FIRST, inst_cream->inst); |
| @@ -4522,7 +4520,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4522 | // RD = RM; | 4520 | // RD = RM; |
| 4523 | if ((inst_cream->Rd == 15)) { | 4521 | if ((inst_cream->Rd == 15)) { |
| 4524 | INC_PC(sizeof(mov_inst)); | 4522 | INC_PC(sizeof(mov_inst)); |
| 4525 | goto PROFILING; | 4523 | goto DISPATCH; |
| 4526 | } | 4524 | } |
| 4527 | } | 4525 | } |
| 4528 | // DEBUG_LOG(ARM11, "cpy inst %x\n", cpu->Reg[15]); | 4526 | // DEBUG_LOG(ARM11, "cpy inst %x\n", cpu->Reg[15]); |
| @@ -4558,7 +4556,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4558 | } | 4556 | } |
| 4559 | if (inst_cream->Rd == 15) { | 4557 | if (inst_cream->Rd == 15) { |
| 4560 | INC_PC(sizeof(eor_inst)); | 4558 | INC_PC(sizeof(eor_inst)); |
| 4561 | goto PROFILING; | 4559 | goto DISPATCH; |
| 4562 | } | 4560 | } |
| 4563 | } | 4561 | } |
| 4564 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4562 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4717,7 +4715,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4717 | } | 4715 | } |
| 4718 | if (BIT(inst, 15)) { | 4716 | if (BIT(inst, 15)) { |
| 4719 | INC_PC(sizeof(ldst_inst)); | 4717 | INC_PC(sizeof(ldst_inst)); |
| 4720 | goto PROFILING; | 4718 | goto DISPATCH; |
| 4721 | } | 4719 | } |
| 4722 | } | 4720 | } |
| 4723 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4721 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4764,7 +4762,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4764 | cpu->TFlag = value & 0x1; | 4762 | cpu->TFlag = value & 0x1; |
| 4765 | cpu->Reg[15] &= 0xFFFFFFFE; | 4763 | cpu->Reg[15] &= 0xFFFFFFFE; |
| 4766 | INC_PC(sizeof(ldst_inst)); | 4764 | INC_PC(sizeof(ldst_inst)); |
| 4767 | goto PROFILING; | 4765 | goto DISPATCH; |
| 4768 | } | 4766 | } |
| 4769 | //} | 4767 | //} |
| 4770 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4768 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4794,7 +4792,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4794 | cpu->TFlag = value & 0x1; | 4792 | cpu->TFlag = value & 0x1; |
| 4795 | cpu->Reg[15] &= 0xFFFFFFFE; | 4793 | cpu->Reg[15] &= 0xFFFFFFFE; |
| 4796 | INC_PC(sizeof(ldst_inst)); | 4794 | INC_PC(sizeof(ldst_inst)); |
| 4797 | goto PROFILING; | 4795 | goto DISPATCH; |
| 4798 | } | 4796 | } |
| 4799 | } | 4797 | } |
| 4800 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4798 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4848,7 +4846,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4848 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 4846 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 4849 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 4847 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| 4850 | INC_PC(sizeof(ldst_inst)); | 4848 | INC_PC(sizeof(ldst_inst)); |
| 4851 | goto PROFILING; | 4849 | goto DISPATCH; |
| 4852 | } | 4850 | } |
| 4853 | } | 4851 | } |
| 4854 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4852 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4869,7 +4867,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4869 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 4867 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 4870 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 4868 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| 4871 | INC_PC(sizeof(ldst_inst)); | 4869 | INC_PC(sizeof(ldst_inst)); |
| 4872 | goto PROFILING; | 4870 | goto DISPATCH; |
| 4873 | } | 4871 | } |
| 4874 | } | 4872 | } |
| 4875 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4873 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4926,7 +4924,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4926 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 4924 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 4927 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 4925 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| 4928 | INC_PC(sizeof(ldst_inst)); | 4926 | INC_PC(sizeof(ldst_inst)); |
| 4929 | goto PROFILING; | 4927 | goto DISPATCH; |
| 4930 | } | 4928 | } |
| 4931 | } | 4929 | } |
| 4932 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4930 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4953,7 +4951,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4953 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 4951 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 4954 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 4952 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| 4955 | INC_PC(sizeof(ldst_inst)); | 4953 | INC_PC(sizeof(ldst_inst)); |
| 4956 | goto PROFILING; | 4954 | goto DISPATCH; |
| 4957 | } | 4955 | } |
| 4958 | } | 4956 | } |
| 4959 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4957 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -4980,7 +4978,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 4980 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 4978 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 4981 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 4979 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| 4982 | INC_PC(sizeof(ldst_inst)); | 4980 | INC_PC(sizeof(ldst_inst)); |
| 4983 | goto PROFILING; | 4981 | goto DISPATCH; |
| 4984 | } | 4982 | } |
| 4985 | } | 4983 | } |
| 4986 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4984 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -5006,7 +5004,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5006 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 5004 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 5007 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 5005 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| 5008 | INC_PC(sizeof(ldst_inst)); | 5006 | INC_PC(sizeof(ldst_inst)); |
| 5009 | goto PROFILING; | 5007 | goto DISPATCH; |
| 5010 | } | 5008 | } |
| 5011 | } | 5009 | } |
| 5012 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5010 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -5031,7 +5029,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5031 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 5029 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 5032 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 5030 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| 5033 | INC_PC(sizeof(ldst_inst)); | 5031 | INC_PC(sizeof(ldst_inst)); |
| 5034 | goto PROFILING; | 5032 | goto DISPATCH; |
| 5035 | } | 5033 | } |
| 5036 | } | 5034 | } |
| 5037 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5035 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -5058,7 +5056,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5058 | 5056 | ||
| 5059 | if (BITS(inst_cream->inst, 12, 15) == 15) { | 5057 | if (BITS(inst_cream->inst, 12, 15) == 15) { |
| 5060 | INC_PC(sizeof(ldst_inst)); | 5058 | INC_PC(sizeof(ldst_inst)); |
| 5061 | goto PROFILING; | 5059 | goto DISPATCH; |
| 5062 | } | 5060 | } |
| 5063 | } | 5061 | } |
| 5064 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5062 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -5228,7 +5226,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5228 | } | 5226 | } |
| 5229 | if (inst_cream->Rd == 15) { | 5227 | if (inst_cream->Rd == 15) { |
| 5230 | INC_PC(sizeof(mla_inst)); | 5228 | INC_PC(sizeof(mla_inst)); |
| 5231 | goto PROFILING; | 5229 | goto DISPATCH; |
| 5232 | } | 5230 | } |
| 5233 | } | 5231 | } |
| 5234 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5232 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -5260,7 +5258,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5260 | } | 5258 | } |
| 5261 | if (inst_cream->Rd == 15) { | 5259 | if (inst_cream->Rd == 15) { |
| 5262 | INC_PC(sizeof(mov_inst)); | 5260 | INC_PC(sizeof(mov_inst)); |
| 5263 | goto PROFILING; | 5261 | goto DISPATCH; |
| 5264 | } | 5262 | } |
| 5265 | // return; | 5263 | // return; |
| 5266 | } | 5264 | } |
| @@ -5422,7 +5420,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5422 | } | 5420 | } |
| 5423 | if (inst_cream->Rd == 15) { | 5421 | if (inst_cream->Rd == 15) { |
| 5424 | INC_PC(sizeof(mul_inst)); | 5422 | INC_PC(sizeof(mul_inst)); |
| 5425 | goto PROFILING; | 5423 | goto DISPATCH; |
| 5426 | } | 5424 | } |
| 5427 | } | 5425 | } |
| 5428 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5426 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -5451,7 +5449,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5451 | } | 5449 | } |
| 5452 | if (inst_cream->Rd == 15) { | 5450 | if (inst_cream->Rd == 15) { |
| 5453 | INC_PC(sizeof(mvn_inst)); | 5451 | INC_PC(sizeof(mvn_inst)); |
| 5454 | goto PROFILING; | 5452 | goto DISPATCH; |
| 5455 | } | 5453 | } |
| 5456 | } | 5454 | } |
| 5457 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5455 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -5483,7 +5481,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5483 | } | 5481 | } |
| 5484 | if (inst_cream->Rd == 15) { | 5482 | if (inst_cream->Rd == 15) { |
| 5485 | INC_PC(sizeof(orr_inst)); | 5483 | INC_PC(sizeof(orr_inst)); |
| 5486 | goto PROFILING; | 5484 | goto DISPATCH; |
| 5487 | } | 5485 | } |
| 5488 | } | 5486 | } |
| 5489 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5487 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -5575,7 +5573,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5575 | } | 5573 | } |
| 5576 | if (inst_cream->Rd == 15) { | 5574 | if (inst_cream->Rd == 15) { |
| 5577 | INC_PC(sizeof(rsb_inst)); | 5575 | INC_PC(sizeof(rsb_inst)); |
| 5578 | goto PROFILING; | 5576 | goto DISPATCH; |
| 5579 | } | 5577 | } |
| 5580 | } | 5578 | } |
| 5581 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5579 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -5612,7 +5610,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5612 | } | 5610 | } |
| 5613 | if (inst_cream->Rd == 15) { | 5611 | if (inst_cream->Rd == 15) { |
| 5614 | INC_PC(sizeof(rsc_inst)); | 5612 | INC_PC(sizeof(rsc_inst)); |
| 5615 | goto PROFILING; | 5613 | goto DISPATCH; |
| 5616 | } | 5614 | } |
| 5617 | } | 5615 | } |
| 5618 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5616 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -5653,7 +5651,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 5653 | } | 5651 | } |
| 5654 | if (inst_cream->Rd == 15) { | 5652 | if (inst_cream->Rd == 15) { |
| 5655 | INC_PC(sizeof(sbc_inst)); | 5653 | INC_PC(sizeof(sbc_inst)); |
| 5656 | goto PROFILING; | 5654 | goto DISPATCH; |
| 5657 | } | 5655 | } |
| 5658 | } | 5656 | } |
| 5659 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5657 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -6066,7 +6064,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 6066 | } | 6064 | } |
| 6067 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6065 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 6068 | //if (BITS(inst_cream->inst, 12, 15) == 15) | 6066 | //if (BITS(inst_cream->inst, 12, 15) == 15) |
| 6069 | // goto PROFILING; | 6067 | // goto DISPATCH; |
| 6070 | INC_PC(sizeof(ldst_inst)); | 6068 | INC_PC(sizeof(ldst_inst)); |
| 6071 | FETCH_INST; | 6069 | FETCH_INST; |
| 6072 | GOTO_NEXT_INST; | 6070 | GOTO_NEXT_INST; |
| @@ -6175,7 +6173,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 6175 | } | 6173 | } |
| 6176 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6174 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 6177 | //if (BITS(inst_cream->inst, 12, 15) == 15) | 6175 | //if (BITS(inst_cream->inst, 12, 15) == 15) |
| 6178 | // goto PROFILING; | 6176 | // goto DISPATCH; |
| 6179 | INC_PC(sizeof(ldst_inst)); | 6177 | INC_PC(sizeof(ldst_inst)); |
| 6180 | FETCH_INST; | 6178 | FETCH_INST; |
| 6181 | GOTO_NEXT_INST; | 6179 | GOTO_NEXT_INST; |
| @@ -6225,7 +6223,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 6225 | } | 6223 | } |
| 6226 | if (inst_cream->Rd == 15) { | 6224 | if (inst_cream->Rd == 15) { |
| 6227 | INC_PC(sizeof(sub_inst)); | 6225 | INC_PC(sizeof(sub_inst)); |
| 6228 | goto PROFILING; | 6226 | goto DISPATCH; |
| 6229 | } | 6227 | } |
| 6230 | } | 6228 | } |
| 6231 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 6229 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -6449,7 +6447,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 6449 | cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; | 6447 | cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; |
| 6450 | //DEBUG_LOG(ARM11, " BL_1_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); | 6448 | //DEBUG_LOG(ARM11, " BL_1_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); |
| 6451 | INC_PC(sizeof(b_2_thumb)); | 6449 | INC_PC(sizeof(b_2_thumb)); |
| 6452 | goto PROFILING; | 6450 | goto DISPATCH; |
| 6453 | } | 6451 | } |
| 6454 | B_COND_THUMB: | 6452 | B_COND_THUMB: |
| 6455 | { | 6453 | { |
| @@ -6461,7 +6459,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 6461 | cpu->Reg[15] += 2; | 6459 | cpu->Reg[15] += 2; |
| 6462 | //DEBUG_LOG(ARM11, " B_COND_THUMB: imm=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[15]); | 6460 | //DEBUG_LOG(ARM11, " B_COND_THUMB: imm=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[15]); |
| 6463 | INC_PC(sizeof(b_cond_thumb)); | 6461 | INC_PC(sizeof(b_cond_thumb)); |
| 6464 | goto PROFILING; | 6462 | goto DISPATCH; |
| 6465 | } | 6463 | } |
| 6466 | BL_1_THUMB: | 6464 | BL_1_THUMB: |
| 6467 | { | 6465 | { |
| @@ -6487,7 +6485,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 6487 | cpu->Reg[14] = tmp; | 6485 | cpu->Reg[14] = tmp; |
| 6488 | //DEBUG_LOG(ARM11, " BL_2_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); | 6486 | //DEBUG_LOG(ARM11, " BL_2_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); |
| 6489 | INC_PC(sizeof(bl_2_thumb)); | 6487 | INC_PC(sizeof(bl_2_thumb)); |
| 6490 | goto PROFILING; | 6488 | goto DISPATCH; |
| 6491 | } | 6489 | } |
| 6492 | BLX_1_THUMB: | 6490 | BLX_1_THUMB: |
| 6493 | { | 6491 | { |
| @@ -6503,7 +6501,7 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 6503 | cpu->TFlag = 0; | 6501 | cpu->TFlag = 0; |
| 6504 | //DEBUG_LOG(ARM11, "In BLX_1_THUMB, BLX(1),imm=0x%x,r14=0x%x, r15=0x%x, \n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); | 6502 | //DEBUG_LOG(ARM11, "In BLX_1_THUMB, BLX(1),imm=0x%x,r14=0x%x, r15=0x%x, \n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); |
| 6505 | INC_PC(sizeof(blx_1_thumb)); | 6503 | INC_PC(sizeof(blx_1_thumb)); |
| 6506 | goto PROFILING; | 6504 | goto DISPATCH; |
| 6507 | } | 6505 | } |
| 6508 | 6506 | ||
| 6509 | UQADD16_INST: | 6507 | UQADD16_INST: |
| @@ -6532,12 +6530,14 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 6532 | cpu->AbortAddr = addr; | 6530 | cpu->AbortAddr = addr; |
| 6533 | cpu->CP15[CP15(CP15_FAULT_STATUS)] = fault & 0xff; | 6531 | cpu->CP15[CP15(CP15_FAULT_STATUS)] = fault & 0xff; |
| 6534 | cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr; | 6532 | cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr; |
| 6535 | return; | 6533 | cpu->NumInstrsToExecute = 0; |
| 6534 | return num_instrs; | ||
| 6536 | } | 6535 | } |
| 6537 | END: | 6536 | END: |
| 6538 | { | 6537 | { |
| 6539 | SAVE_NZCVT; | 6538 | SAVE_NZCVT; |
| 6540 | return; | 6539 | cpu->NumInstrsToExecute = 0; |
| 6540 | return num_instrs; | ||
| 6541 | } | 6541 | } |
| 6542 | INIT_INST_LENGTH: | 6542 | INIT_INST_LENGTH: |
| 6543 | { | 6543 | { |
| @@ -6557,7 +6557,8 @@ void InterpreterMainLoop(ARMul_State* state) | |||
| 6557 | DEBUG_LOG(ARM11, "%llx\n", InstLabel[1]); | 6557 | DEBUG_LOG(ARM11, "%llx\n", InstLabel[1]); |
| 6558 | DEBUG_LOG(ARM11, "%lld\n", (char *)InstEndLabel[1] - (char *)InstLabel[1]); | 6558 | DEBUG_LOG(ARM11, "%lld\n", (char *)InstEndLabel[1] - (char *)InstLabel[1]); |
| 6559 | #endif | 6559 | #endif |
| 6560 | return; | 6560 | cpu->NumInstrsToExecute = 0; |
| 6561 | return num_instrs; | ||
| 6561 | } | 6562 | } |
| 6562 | } | 6563 | } |
| 6563 | 6564 | ||
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h index d73f8f65f..c65eb23f7 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.h +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h | |||
| @@ -4,4 +4,4 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | void InterpreterMainLoop(ARMul_State* state); | 7 | unsigned InterpreterMainLoop(ARMul_State* state); |
diff --git a/src/core/core.h b/src/core/core.h index 872dc0cd1..850bb0ab4 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -26,13 +26,13 @@ void Start(); | |||
| 26 | 26 | ||
| 27 | /** | 27 | /** |
| 28 | * Run the core CPU loop | 28 | * Run the core CPU loop |
| 29 | * This function loops for 100 instructions in the CPU before trying to update hardware. This is a | 29 | * This function runs the core for the specified number of CPU instructions before trying to update |
| 30 | * little bit faster than SingleStep, and should be pretty much equivalent. The number of | 30 | * hardware. This is much faster than SingleStep (and should be equivalent), as the CPU is not |
| 31 | * instructions chosen is fairly arbitrary, however a large number will more drastically affect the | 31 | * required to do a full dispatch with each instruction. NOTE: the number of instructions requested |
| 32 | * frequency of GSP interrupts and likely break things. The point of this is to just loop in the CPU | 32 | * is not guaranteed to run, as this will be interrupted preemptively if a hardware update is |
| 33 | * for more than 1 instruction to reduce overhead and make it a little bit faster... | 33 | * requested (e.g. on a thread switch). |
| 34 | */ | 34 | */ |
| 35 | void RunLoop(int tight_loop=100); | 35 | void RunLoop(int tight_loop=1000); |
| 36 | 36 | ||
| 37 | /// Step the CPU one instruction | 37 | /// Step the CPU one instruction |
| 38 | void SingleStep(); | 38 | void SingleStep(); |
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index 617b6add4..4f41ec5f4 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | 15 | ||
| 16 | namespace APT_U { | 16 | namespace APT_U { |
| 17 | 17 | ||
| 18 | static Handle lock_handle = 0; | ||
| 19 | |||
| 18 | /// Signals used by APT functions | 20 | /// Signals used by APT functions |
| 19 | enum class SignalType : u32 { | 21 | enum class SignalType : u32 { |
| 20 | None = 0x0, | 22 | None = 0x0, |
| @@ -32,15 +34,32 @@ void Initialize(Service::Interface* self) { | |||
| 32 | Kernel::SetEventLocked(cmd_buff[3], true); | 34 | Kernel::SetEventLocked(cmd_buff[3], true); |
| 33 | Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event | 35 | Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event |
| 34 | 36 | ||
| 37 | _assert_msg_(KERNEL, (0 != lock_handle), "Cannot initialize without lock"); | ||
| 38 | Kernel::ReleaseMutex(lock_handle); | ||
| 39 | |||
| 35 | cmd_buff[1] = 0; // No error | 40 | cmd_buff[1] = 0; // No error |
| 41 | |||
| 36 | DEBUG_LOG(KERNEL, "called"); | 42 | DEBUG_LOG(KERNEL, "called"); |
| 37 | } | 43 | } |
| 38 | 44 | ||
| 39 | void GetLockHandle(Service::Interface* self) { | 45 | void GetLockHandle(Service::Interface* self) { |
| 40 | u32* cmd_buff = Service::GetCommandBuffer(); | 46 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 41 | u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field | 47 | u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field |
| 48 | |||
| 49 | if (0 == lock_handle) { | ||
| 50 | // TODO(bunnei): Verify if this is created here or at application boot? | ||
| 51 | lock_handle = Kernel::CreateMutex(false, "APT_U:Lock"); | ||
| 52 | Kernel::ReleaseMutex(lock_handle); | ||
| 53 | } | ||
| 42 | cmd_buff[1] = 0; // No error | 54 | cmd_buff[1] = 0; // No error |
| 43 | cmd_buff[5] = Kernel::CreateMutex(false, "APT_U:Lock"); | 55 | |
| 56 | // Not sure what these parameters are used for, but retail apps check that they are 0 after | ||
| 57 | // GetLockHandle has been called. | ||
| 58 | cmd_buff[2] = 0; | ||
| 59 | cmd_buff[3] = 0; | ||
| 60 | cmd_buff[4] = 0; | ||
| 61 | |||
| 62 | cmd_buff[5] = lock_handle; | ||
| 44 | DEBUG_LOG(KERNEL, "called handle=0x%08X", cmd_buff[5]); | 63 | DEBUG_LOG(KERNEL, "called handle=0x%08X", cmd_buff[5]); |
| 45 | } | 64 | } |
| 46 | 65 | ||
| @@ -59,6 +78,25 @@ void InquireNotification(Service::Interface* self) { | |||
| 59 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X", app_id); | 78 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X", app_id); |
| 60 | } | 79 | } |
| 61 | 80 | ||
| 81 | /** | ||
| 82 | * APT_U::ReceiveParameter service function. This returns the current parameter data from NS state, | ||
| 83 | * from the source process which set the parameters. Once finished, NS will clear a flag in the NS | ||
| 84 | * state so that this command will return an error if this command is used again if parameters were | ||
| 85 | * not set again. This is called when the second Initialize event is triggered. It returns a signal | ||
| 86 | * type indicating why it was triggered. | ||
| 87 | * Inputs: | ||
| 88 | * 1 : AppID | ||
| 89 | * 2 : Parameter buffer size, max size is 0x1000 | ||
| 90 | * Outputs: | ||
| 91 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 92 | * 2 : Unknown, for now assume AppID of the process which sent these parameters | ||
| 93 | * 3 : Unknown, for now assume Signal type | ||
| 94 | * 4 : Actual parameter buffer size, this is <= to the the input size | ||
| 95 | * 5 : Value | ||
| 96 | * 6 : Handle from the source process which set the parameters, likely used for shared memory | ||
| 97 | * 7 : Size | ||
| 98 | * 8 : Output parameter buffer ptr | ||
| 99 | */ | ||
| 62 | void ReceiveParameter(Service::Interface* self) { | 100 | void ReceiveParameter(Service::Interface* self) { |
| 63 | u32* cmd_buff = Service::GetCommandBuffer(); | 101 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 64 | u32 app_id = cmd_buff[1]; | 102 | u32 app_id = cmd_buff[1]; |
| @@ -66,7 +104,7 @@ void ReceiveParameter(Service::Interface* self) { | |||
| 66 | cmd_buff[1] = 0; // No error | 104 | cmd_buff[1] = 0; // No error |
| 67 | cmd_buff[2] = 0; | 105 | cmd_buff[2] = 0; |
| 68 | cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type | 106 | cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type |
| 69 | cmd_buff[4] = 0x10; | 107 | cmd_buff[4] = 0x10; // Parameter buffer size (16) |
| 70 | cmd_buff[5] = 0; | 108 | cmd_buff[5] = 0; |
| 71 | cmd_buff[6] = 0; | 109 | cmd_buff[6] = 0; |
| 72 | cmd_buff[7] = 0; | 110 | cmd_buff[7] = 0; |
| @@ -74,35 +112,66 @@ void ReceiveParameter(Service::Interface* self) { | |||
| 74 | } | 112 | } |
| 75 | 113 | ||
| 76 | /** | 114 | /** |
| 77 | * APT_U::GlanceParameter service function | 115 | * APT_U::GlanceParameter service function. This is exactly the same as APT_U::ReceiveParameter |
| 78 | * Inputs: | 116 | * (except for the word value prior to the output handle), except this will not clear the flag |
| 79 | * 1 : AppID | 117 | * (except when responseword[3]==8 || responseword[3]==9) in NS state. |
| 80 | * 2 : Parameter buffer size, max size is 0x1000 | 118 | * Inputs: |
| 81 | * Outputs: | 119 | * 1 : AppID |
| 82 | * 1 : Result of function, 0 on success, otherwise error code | 120 | * 2 : Parameter buffer size, max size is 0x1000 |
| 83 | * 2 : Unknown, for now assume AppID of the process which sent these parameters | 121 | * Outputs: |
| 84 | * 3 : Unknown, for now assume Signal type | 122 | * 1 : Result of function, 0 on success, otherwise error code |
| 85 | * 4 : Actual parameter buffer size, this is <= to the the input size | 123 | * 2 : Unknown, for now assume AppID of the process which sent these parameters |
| 86 | * 5 : Value | 124 | * 3 : Unknown, for now assume Signal type |
| 87 | * 6 : Handle from the source process which set the parameters, likely used for shared memory | 125 | * 4 : Actual parameter buffer size, this is <= to the the input size |
| 88 | * 7 : Size | 126 | * 5 : Value |
| 89 | * 8 : Output parameter buffer ptr | 127 | * 6 : Handle from the source process which set the parameters, likely used for shared memory |
| 90 | */ | 128 | * 7 : Size |
| 129 | * 8 : Output parameter buffer ptr | ||
| 130 | */ | ||
| 91 | void GlanceParameter(Service::Interface* self) { | 131 | void GlanceParameter(Service::Interface* self) { |
| 92 | u32* cmd_buff = Service::GetCommandBuffer(); | 132 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 93 | u32 app_id = cmd_buff[1]; | 133 | u32 app_id = cmd_buff[1]; |
| 94 | u32 buffer_size = cmd_buff[2]; | 134 | u32 buffer_size = cmd_buff[2]; |
| 135 | |||
| 95 | cmd_buff[1] = 0; // No error | 136 | cmd_buff[1] = 0; // No error |
| 96 | cmd_buff[2] = 0; | 137 | cmd_buff[2] = 0; |
| 97 | cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type | 138 | cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type |
| 98 | cmd_buff[4] = 0; | 139 | cmd_buff[4] = 0x10; // Parameter buffer size (16) |
| 99 | cmd_buff[5] = 0; | 140 | cmd_buff[5] = 0; |
| 100 | cmd_buff[6] = 0; | 141 | cmd_buff[6] = 0; |
| 101 | cmd_buff[7] = 0; | 142 | cmd_buff[7] = 0; |
| 102 | cmd_buff[8] = 0; | 143 | |
| 103 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); | 144 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); |
| 104 | } | 145 | } |
| 105 | 146 | ||
| 147 | /** | ||
| 148 | * APT_U::AppletUtility service function | ||
| 149 | * Inputs: | ||
| 150 | * 1 : Unknown, but clearly used for something | ||
| 151 | * 2 : Buffer 1 size (purpose is unknown) | ||
| 152 | * 3 : Buffer 2 size (purpose is unknown) | ||
| 153 | * 5 : Buffer 1 address (purpose is unknown) | ||
| 154 | * 65 : Buffer 2 address (purpose is unknown) | ||
| 155 | * Outputs: | ||
| 156 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 157 | */ | ||
| 158 | void AppletUtility(Service::Interface* self) { | ||
| 159 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 160 | |||
| 161 | // These are from 3dbrew - I'm not really sure what they're used for. | ||
| 162 | u32 unk = cmd_buff[1]; | ||
| 163 | u32 buffer1_size = cmd_buff[2]; | ||
| 164 | u32 buffer2_size = cmd_buff[3]; | ||
| 165 | u32 buffer1_addr = cmd_buff[5]; | ||
| 166 | u32 buffer2_addr = cmd_buff[65]; | ||
| 167 | |||
| 168 | cmd_buff[1] = 0; // No error | ||
| 169 | |||
| 170 | WARN_LOG(KERNEL, "(STUBBED) called unk=0x%08X, buffer1_size=0x%08x, buffer2_size=0x%08x, " | ||
| 171 | "buffer1_addr=0x%08x, buffer2_addr=0x%08x", unk, buffer1_size, buffer2_size, | ||
| 172 | buffer1_addr, buffer2_addr); | ||
| 173 | } | ||
| 174 | |||
| 106 | const Interface::FunctionInfo FunctionTable[] = { | 175 | const Interface::FunctionInfo FunctionTable[] = { |
| 107 | {0x00010040, GetLockHandle, "GetLockHandle"}, | 176 | {0x00010040, GetLockHandle, "GetLockHandle"}, |
| 108 | {0x00020080, Initialize, "Initialize"}, | 177 | {0x00020080, Initialize, "Initialize"}, |
| @@ -178,7 +247,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 178 | {0x00480100, nullptr, "GetProgramInfo"}, | 247 | {0x00480100, nullptr, "GetProgramInfo"}, |
| 179 | {0x00490180, nullptr, "Reboot"}, | 248 | {0x00490180, nullptr, "Reboot"}, |
| 180 | {0x004A0040, nullptr, "GetCaptureInfo"}, | 249 | {0x004A0040, nullptr, "GetCaptureInfo"}, |
| 181 | {0x004B00C2, nullptr, "AppletUtility"}, | 250 | {0x004B00C2, AppletUtility, "AppletUtility"}, |
| 182 | {0x004C0000, nullptr, "SetFatalErrDispMode"}, | 251 | {0x004C0000, nullptr, "SetFatalErrDispMode"}, |
| 183 | {0x004D0080, nullptr, "GetAppletProgramInfo"}, | 252 | {0x004D0080, nullptr, "GetAppletProgramInfo"}, |
| 184 | {0x004E0000, nullptr, "HardwareResetAsync"}, | 253 | {0x004E0000, nullptr, "HardwareResetAsync"}, |
| @@ -191,6 +260,8 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 191 | 260 | ||
| 192 | Interface::Interface() { | 261 | Interface::Interface() { |
| 193 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | 262 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); |
| 263 | |||
| 264 | lock_handle = 0; | ||
| 194 | } | 265 | } |
| 195 | 266 | ||
| 196 | Interface::~Interface() { | 267 | Interface::~Interface() { |
diff --git a/src/core/hle/service/frd_u.cpp b/src/core/hle/service/frd_u.cpp new file mode 100644 index 000000000..58023e536 --- /dev/null +++ b/src/core/hle/service/frd_u.cpp | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/log.h" | ||
| 6 | #include "core/hle/hle.h" | ||
| 7 | #include "core/hle/service/frd_u.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace FRD_U | ||
| 11 | |||
| 12 | namespace FRD_U { | ||
| 13 | |||
| 14 | const Interface::FunctionInfo FunctionTable[] = { | ||
| 15 | {0x00050000, nullptr, "GetFriendKey"}, | ||
| 16 | {0x00080000, nullptr, "GetMyPresence"}, | ||
| 17 | {0x00100040, nullptr, "GetPassword"}, | ||
| 18 | {0x00190042, nullptr, "GetFriendFavoriteGame"}, | ||
| 19 | {0x001A00C4, nullptr, "GetFriendInfo"}, | ||
| 20 | {0x001B0080, nullptr, "IsOnFriendList"}, | ||
| 21 | {0x001C0042, nullptr, "DecodeLocalFriendCode"}, | ||
| 22 | {0x001D0002, nullptr, "SetCurrentlyPlayingText"}, | ||
| 23 | {0x00320042, nullptr, "SetClientSdkVersion"} | ||
| 24 | }; | ||
| 25 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 26 | // Interface class | ||
| 27 | |||
| 28 | Interface::Interface() { | ||
| 29 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | ||
| 30 | } | ||
| 31 | |||
| 32 | Interface::~Interface() { | ||
| 33 | } | ||
| 34 | |||
| 35 | } // namespace | ||
diff --git a/src/core/hle/service/frd_u.h b/src/core/hle/service/frd_u.h new file mode 100644 index 000000000..9df8a815a --- /dev/null +++ b/src/core/hle/service/frd_u.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 10 | // Namespace FRD_U | ||
| 11 | |||
| 12 | namespace FRD_U { | ||
| 13 | |||
| 14 | class Interface : public Service::Interface { | ||
| 15 | public: | ||
| 16 | Interface(); | ||
| 17 | ~Interface(); | ||
| 18 | /** | ||
| 19 | * Gets the string port name used by CTROS for the service | ||
| 20 | * @return Port name of service | ||
| 21 | */ | ||
| 22 | std::string GetPortName() const { | ||
| 23 | return "frd:u"; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace | ||
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index b144a77d4..bb0f80e98 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "core/hle/service/dsp_dsp.h" | 12 | #include "core/hle/service/dsp_dsp.h" |
| 13 | #include "core/hle/service/err_f.h" | 13 | #include "core/hle/service/err_f.h" |
| 14 | #include "core/hle/service/fs_user.h" | 14 | #include "core/hle/service/fs_user.h" |
| 15 | #include "core/hle/service/frd_u.h" | ||
| 15 | #include "core/hle/service/gsp_gpu.h" | 16 | #include "core/hle/service/gsp_gpu.h" |
| 16 | #include "core/hle/service/hid_user.h" | 17 | #include "core/hle/service/hid_user.h" |
| 17 | #include "core/hle/service/mic_u.h" | 18 | #include "core/hle/service/mic_u.h" |
| @@ -80,6 +81,7 @@ void Init() { | |||
| 80 | g_manager->AddService(new CFG_U::Interface); | 81 | g_manager->AddService(new CFG_U::Interface); |
| 81 | g_manager->AddService(new DSP_DSP::Interface); | 82 | g_manager->AddService(new DSP_DSP::Interface); |
| 82 | g_manager->AddService(new ERR_F::Interface); | 83 | g_manager->AddService(new ERR_F::Interface); |
| 84 | g_manager->AddService(new FRD_U::Interface); | ||
| 83 | g_manager->AddService(new FS_User::Interface); | 85 | g_manager->AddService(new FS_User::Interface); |
| 84 | g_manager->AddService(new GSP_GPU::Interface); | 86 | g_manager->AddService(new GSP_GPU::Interface); |
| 85 | g_manager->AddService(new HID_User::Interface); | 87 | g_manager->AddService(new HID_User::Interface); |