summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp48
-rw-r--r--src/core/arm/interpreter/armemu.cpp203
-rw-r--r--src/core/file_sys/archive_backend.h11
-rw-r--r--src/core/hle/kernel/kernel.h12
-rw-r--r--src/core/hle/kernel/semaphore.cpp8
-rw-r--r--src/core/hle/kernel/semaphore.h2
-rw-r--r--src/core/hle/kernel/thread.cpp56
-rw-r--r--src/core/hle/kernel/thread.h4
-rw-r--r--src/core/hle/svc.cpp3
-rw-r--r--src/core/loader/3dsx.cpp4
10 files changed, 275 insertions, 76 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 68012bffd..84b4a38f0 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -1266,6 +1266,13 @@ typedef struct _smla_inst {
1266 unsigned int Rn; 1266 unsigned int Rn;
1267} smla_inst; 1267} smla_inst;
1268 1268
1269typedef struct umaal_inst {
1270 unsigned int Rn;
1271 unsigned int Rm;
1272 unsigned int RdHi;
1273 unsigned int RdLo;
1274} umaal_inst;
1275
1269typedef struct _umlal_inst { 1276typedef struct _umlal_inst {
1270 unsigned int S; 1277 unsigned int S;
1271 unsigned int Rm; 1278 unsigned int Rm;
@@ -3010,7 +3017,26 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) { UN
3010ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB16"); } 3017ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB16"); }
3011ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB8"); } 3018ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB8"); }
3012ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUBADDX"); } 3019ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUBADDX"); }
3013ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UMAAL"); } 3020ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index)
3021{
3022 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst));
3023 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
3024
3025 inst_base->cond = BITS(inst, 28, 31);
3026 inst_base->idx = index;
3027 inst_base->br = NON_BRANCH;
3028 inst_base->load_r15 = 0;
3029
3030 inst_cream->Rm = BITS(inst, 8, 11);
3031 inst_cream->Rn = BITS(inst, 0, 3);
3032 inst_cream->RdLo = BITS(inst, 12, 15);
3033 inst_cream->RdHi = BITS(inst, 16, 19);
3034
3035 if (CHECK_RM || CHECK_RN)
3036 inst_base->load_r15 = 1;
3037
3038 return inst_base;
3039}
3014ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) 3040ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index)
3015{ 3041{
3016 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); 3042 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
@@ -6374,6 +6400,26 @@ unsigned InterpreterMainLoop(ARMul_State* state)
6374 UHSUB8_INST: 6400 UHSUB8_INST:
6375 UHSUBADDX_INST: 6401 UHSUBADDX_INST:
6376 UMAAL_INST: 6402 UMAAL_INST:
6403 {
6404 INC_ICOUNTER;
6405 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6406 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
6407
6408 const u32 rm = RM;
6409 const u32 rn = RN;
6410 const u32 rd_lo = RDLO;
6411 const u32 rd_hi = RDHI;
6412
6413 const u64 result = (rm * rn) + rd_lo + rd_hi;
6414
6415 RDLO = (result & 0xFFFFFFFF);
6416 RDHI = ((result >> 32) & 0xFFFFFFFF);
6417 }
6418 cpu->Reg[15] += GET_INST_SIZE(cpu);
6419 INC_PC(sizeof(umaal_inst));
6420 FETCH_INST;
6421 GOTO_NEXT_INST;
6422 }
6377 UMLAL_INST: 6423 UMLAL_INST:
6378 { 6424 {
6379 INC_ICOUNTER; 6425 INC_ICOUNTER;
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 63cfd03c6..610e04f10 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -5824,9 +5824,9 @@ L_stm_s_takeabort:
5824 case 0x3f: 5824 case 0x3f:
5825 printf ("Unhandled v6 insn: rbit\n"); 5825 printf ("Unhandled v6 insn: rbit\n");
5826 break; 5826 break;
5827 case 0x61: // SSUB16, SADD16, SSAX, and SASX 5827 case 0x61: // SADD16, SASX, SSAX, and SSUB16
5828 if ((instr & 0xFF0) == 0xf70 || (instr & 0xFF0) == 0xf10 || 5828 if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 ||
5829 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf30) 5829 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70)
5830 { 5830 {
5831 const u8 rd_idx = BITS(12, 15); 5831 const u8 rd_idx = BITS(12, 15);
5832 const u8 rm_idx = BITS(0, 3); 5832 const u8 rm_idx = BITS(0, 3);
@@ -5839,25 +5839,25 @@ L_stm_s_takeabort:
5839 s32 lo_result; 5839 s32 lo_result;
5840 s32 hi_result; 5840 s32 hi_result;
5841 5841
5842 // SSUB16
5843 if ((instr & 0xFF0) == 0xf70) {
5844 lo_result = (rn_lo - rm_lo);
5845 hi_result = (rn_hi - rm_hi);
5846 }
5847 // SADD16 5842 // SADD16
5848 else if ((instr & 0xFF0) == 0xf10) { 5843 if ((instr & 0xFF0) == 0xf10) {
5849 lo_result = (rn_lo + rm_lo); 5844 lo_result = (rn_lo + rm_lo);
5850 hi_result = (rn_hi + rm_hi); 5845 hi_result = (rn_hi + rm_hi);
5851 } 5846 }
5847 // SASX
5848 else if ((instr & 0xFF0) == 0xf30) {
5849 lo_result = (rn_lo - rm_hi);
5850 hi_result = (rn_hi + rm_lo);
5851 }
5852 // SSAX 5852 // SSAX
5853 else if ((instr & 0xFF0) == 0xf50) { 5853 else if ((instr & 0xFF0) == 0xf50) {
5854 lo_result = (rn_lo + rm_hi); 5854 lo_result = (rn_lo + rm_hi);
5855 hi_result = (rn_hi - rm_lo); 5855 hi_result = (rn_hi - rm_lo);
5856 } 5856 }
5857 // SASX 5857 // SSUB16
5858 else { 5858 else {
5859 lo_result = (rn_lo - rm_hi); 5859 lo_result = (rn_lo - rm_lo);
5860 hi_result = (rn_hi + rm_lo); 5860 hi_result = (rn_hi - rm_hi);
5861 } 5861 }
5862 5862
5863 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 5863 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
@@ -5878,12 +5878,87 @@ L_stm_s_takeabort:
5878 state->Cpsr &= ~(1 << 19); 5878 state->Cpsr &= ~(1 << 19);
5879 } 5879 }
5880 return 1; 5880 return 1;
5881 } else { 5881 }
5882 printf("Unhandled v6 insn: %08x", BITS(20, 27)); 5882 // SADD8/SSUB8
5883 else if ((instr & 0xFF0) == 0xf90 || (instr & 0xFF0) == 0xff0)
5884 {
5885 const u8 rd_idx = BITS(12, 15);
5886 const u8 rm_idx = BITS(0, 3);
5887 const u8 rn_idx = BITS(16, 19);
5888 const u32 rm_val = state->Reg[rm_idx];
5889 const u32 rn_val = state->Reg[rn_idx];
5890
5891 u8 lo_val1;
5892 u8 lo_val2;
5893 u8 hi_val1;
5894 u8 hi_val2;
5895
5896 // SADD8
5897 if ((instr & 0xFF0) == 0xf90) {
5898 lo_val1 = (u8)((rn_val & 0xFF) + (rm_val & 0xFF));
5899 lo_val2 = (u8)(((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF));
5900 hi_val1 = (u8)(((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF));
5901 hi_val2 = (u8)(((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF));
5902
5903 if (lo_val1 & 0x80)
5904 state->Cpsr |= (1 << 16);
5905 else
5906 state->Cpsr &= ~(1 << 16);
5907
5908 if (lo_val2 & 0x80)
5909 state->Cpsr |= (1 << 17);
5910 else
5911 state->Cpsr &= ~(1 << 17);
5912
5913 if (hi_val1 & 0x80)
5914 state->Cpsr |= (1 << 18);
5915 else
5916 state->Cpsr &= ~(1 << 18);
5917
5918 if (hi_val2 & 0x80)
5919 state->Cpsr |= (1 << 19);
5920 else
5921 state->Cpsr &= ~(1 << 19);
5922 }
5923 // SSUB8
5924 else {
5925 lo_val1 = (u8)((rn_val & 0xFF) - (rm_val & 0xFF));
5926 lo_val2 = (u8)(((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF));
5927 hi_val1 = (u8)(((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF));
5928 hi_val2 = (u8)(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF));
5929
5930 if (!(lo_val1 & 0x80))
5931 state->Cpsr |= (1 << 16);
5932 else
5933 state->Cpsr &= ~(1 << 16);
5934
5935 if (!(lo_val2 & 0x80))
5936 state->Cpsr |= (1 << 17);
5937 else
5938 state->Cpsr &= ~(1 << 17);
5939
5940 if (!(hi_val1 & 0x80))
5941 state->Cpsr |= (1 << 18);
5942 else
5943 state->Cpsr &= ~(1 << 18);
5944
5945 if (!(hi_val2 & 0x80))
5946 state->Cpsr |= (1 << 19);
5947 else
5948 state->Cpsr &= ~(1 << 19);
5949 }
5950
5951 state->Reg[rd_idx] = (lo_val1 | lo_val2 << 8 | hi_val1 << 16 | hi_val2 << 24);
5952 return 1;
5953 }
5954 else {
5955 printf("Unhandled v6 insn: %08x", instr);
5883 } 5956 }
5884 break; 5957 break;
5885 case 0x62: // QSUB16 and QADD16 5958 case 0x62: // QADD16, QASX, QSAX, and QSUB16
5886 if ((instr & 0xFF0) == 0xf70 || (instr & 0xFF0) == 0xf10) { 5959 if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 ||
5960 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70)
5961 {
5887 const u8 rd_idx = BITS(12, 15); 5962 const u8 rd_idx = BITS(12, 15);
5888 const u8 rn_idx = BITS(16, 19); 5963 const u8 rn_idx = BITS(16, 19);
5889 const u8 rm_idx = BITS(0, 3); 5964 const u8 rm_idx = BITS(0, 3);
@@ -5895,15 +5970,26 @@ L_stm_s_takeabort:
5895 s32 lo_result; 5970 s32 lo_result;
5896 s32 hi_result; 5971 s32 hi_result;
5897 5972
5973 // QADD16
5974 if ((instr & 0xFF0) == 0xf10) {
5975 lo_result = (rn_lo + rm_lo);
5976 hi_result = (rn_hi + rm_hi);
5977 }
5978 // QASX
5979 else if ((instr & 0xFF0) == 0xf30) {
5980 lo_result = (rn_lo - rm_hi);
5981 hi_result = (rn_hi + rm_lo);
5982 }
5983 // QSAX
5984 else if ((instr & 0xFF0) == 0xf50) {
5985 lo_result = (rn_lo + rm_hi);
5986 hi_result = (rn_hi - rm_lo);
5987 }
5898 // QSUB16 5988 // QSUB16
5899 if ((instr & 0xFF0) == 0xf70) { 5989 else {
5900 lo_result = (rn_lo - rm_lo); 5990 lo_result = (rn_lo - rm_lo);
5901 hi_result = (rn_hi - rm_hi); 5991 hi_result = (rn_hi - rm_hi);
5902 } 5992 }
5903 else { // QADD16
5904 lo_result = (rn_lo + rm_lo);
5905 hi_result = (rn_hi + rm_hi);
5906 }
5907 5993
5908 if (lo_result > 0x7FFF) 5994 if (lo_result > 0x7FFF)
5909 lo_result = 0x7FFF; 5995 lo_result = 0x7FFF;
@@ -6078,22 +6164,28 @@ L_stm_s_takeabort:
6078 //ichfly 6164 //ichfly
6079 //SSAT16 6165 //SSAT16
6080 { 6166 {
6081 u8 tar = BITS(12, 15); 6167 const u8 rd_idx = BITS(12, 15);
6082 u8 src = BITS(0, 3); 6168 const u8 rn_idx = BITS(0, 3);
6083 u8 val = BITS(16, 19) + 1; 6169 const u8 num_bits = BITS(16, 19) + 1;
6084 s16 a1 = (state->Reg[src]); 6170 const s16 min = -(0x8000 >> (16 - num_bits));
6085 s16 a2 = (state->Reg[src] >> 0x10); 6171 const s16 max = (0x7FFF >> (16 - num_bits));
6086 s16 min = (s16)(0x8000 >> (16 - val)); 6172 s16 rn_lo = (state->Reg[rn_idx]);
6087 s16 max = 0x7FFF >> (16 - val); 6173 s16 rn_hi = (state->Reg[rn_idx] >> 16);
6088 if (min > a1) a1 = min; 6174
6089 if (max < a1) a1 = max; 6175 if (rn_lo > max)
6090 if (min > a2) a2 = min; 6176 rn_lo = max;
6091 if (max < a2) a2 = max; 6177 else if (rn_lo < min)
6092 u32 temp2 = ((u32)(a2)) << 0x10; 6178 rn_lo = min;
6093 state->Reg[tar] = (a1 & 0xFFFF) | (temp2); 6179
6180 if (rn_hi > max)
6181 rn_hi = max;
6182 else if (rn_hi < min)
6183 rn_hi = min;
6184
6185 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);
6186 return 1;
6094 } 6187 }
6095 6188
6096 return 1;
6097 default: 6189 default:
6098 break; 6190 break;
6099 } 6191 }
@@ -6314,11 +6406,14 @@ L_stm_s_takeabort:
6314 } 6406 }
6315 case 0x70: 6407 case 0x70:
6316 // ichfly 6408 // ichfly
6317 // SMUAD, SMUSD, SMLAD 6409 // SMUAD, SMUSD, SMLAD, and SMLSD
6318 if ((instr & 0xf0d0) == 0xf010 || (instr & 0xf0d0) == 0xf050 || (instr & 0xd0) == 0x10) { 6410 if ((instr & 0xf0d0) == 0xf010 || (instr & 0xf0d0) == 0xf050 ||
6411 (instr & 0xd0) == 0x10 || (instr & 0xd0) == 0x50)
6412 {
6319 const u8 rd_idx = BITS(16, 19); 6413 const u8 rd_idx = BITS(16, 19);
6320 const u8 rn_idx = BITS(0, 3); 6414 const u8 rn_idx = BITS(0, 3);
6321 const u8 rm_idx = BITS(8, 11); 6415 const u8 rm_idx = BITS(8, 11);
6416 const u8 ra_idx = BITS(12, 15);
6322 const bool do_swap = (BIT(5) == 1); 6417 const bool do_swap = (BIT(5) == 1);
6323 6418
6324 u32 rm_val = state->Reg[rm_idx]; 6419 u32 rm_val = state->Reg[rm_idx];
@@ -6341,13 +6436,14 @@ L_stm_s_takeabort:
6341 state->Reg[rd_idx] = (rn_lo * rm_lo) - (rn_hi * rm_hi); 6436 state->Reg[rd_idx] = (rn_lo * rm_lo) - (rn_hi * rm_hi);
6342 } 6437 }
6343 // SMLAD 6438 // SMLAD
6344 else { 6439 else if ((instr & 0xd0) == 0x10) {
6345 const u8 ra_idx = BITS(12, 15);
6346 state->Reg[rd_idx] = (rn_lo * rm_lo) + (rn_hi * rm_hi) + (s32)state->Reg[ra_idx]; 6440 state->Reg[rd_idx] = (rn_lo * rm_lo) + (rn_hi * rm_hi) + (s32)state->Reg[ra_idx];
6347 } 6441 }
6442 // SMLSD
6443 else {
6444 state->Reg[rd_idx] = ((rn_lo * rm_lo) - (rn_hi * rm_hi)) + (s32)state->Reg[ra_idx];
6445 }
6348 return 1; 6446 return 1;
6349 } else {
6350 printf ("Unhandled v6 insn: smlsd\n");
6351 } 6447 }
6352 break; 6448 break;
6353 case 0x74: 6449 case 0x74:
@@ -6357,7 +6453,30 @@ L_stm_s_takeabort:
6357 printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); 6453 printf ("Unhandled v6 insn: smmla/smmls/smmul\n");
6358 break; 6454 break;
6359 case 0x78: 6455 case 0x78:
6360 printf ("Unhandled v6 insn: usad/usada8\n"); 6456 if (BITS(20, 24) == 0x18)
6457 {
6458 const u8 rm_idx = BITS(8, 11);
6459 const u8 rn_idx = BITS(0, 3);
6460 const u8 rd_idx = BITS(16, 19);
6461
6462 const u32 rm_val = state->Reg[rm_idx];
6463 const u32 rn_val = state->Reg[rn_idx];
6464
6465 const u8 diff1 = (u8)std::labs((rn_val & 0xFF) - (rm_val & 0xFF));
6466 const u8 diff2 = (u8)std::labs(((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF));
6467 const u8 diff3 = (u8)std::labs(((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF));
6468 const u8 diff4 = (u8)std::labs(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF));
6469
6470 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
6471
6472 // Op is USADA8 if true.
6473 const u8 ra_idx = BITS(12, 15);
6474 if (ra_idx != 15)
6475 finalDif += state->Reg[ra_idx];
6476
6477 state->Reg[rd_idx] = finalDif;
6478 return 1;
6479 }
6361 break; 6480 break;
6362 case 0x7a: 6481 case 0x7a:
6363 printf ("Unhandled v6 insn: usbfx\n"); 6482 printf ("Unhandled v6 insn: usbfx\n");
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
index 1b510b695..43583d206 100644
--- a/src/core/file_sys/archive_backend.h
+++ b/src/core/file_sys/archive_backend.h
@@ -143,7 +143,16 @@ public:
143 case Char: 143 case Char:
144 return std::vector<u8>(string.begin(), string.end()); 144 return std::vector<u8>(string.begin(), string.end());
145 case Wchar: 145 case Wchar:
146 return std::vector<u8>(u16str.begin(), u16str.end()); 146 {
147 // use two u8 for each character of u16str
148 std::vector<u8> to_return(u16str.size() * 2);
149 for (size_t i = 0; i < u16str.size(); ++i) {
150 u16 tmp_char = u16str.at(i);
151 to_return[i*2] = (tmp_char & 0xFF00) >> 8;
152 to_return[i*2 + 1] = (tmp_char & 0x00FF);
153 }
154 return to_return;
155 }
147 case Empty: 156 case Empty:
148 return {}; 157 return {};
149 default: 158 default:
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7123485be..683fffeee 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -14,6 +14,10 @@ typedef s32 Result;
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17// From kernel.h. Declarations duplicated here to avoid a circular header dependency.
18class Thread;
19Thread* GetCurrentThread();
20
17enum KernelHandle { 21enum KernelHandle {
18 CurrentThread = 0xFFFF8000, 22 CurrentThread = 0xFFFF8000,
19 CurrentProcess = 0xFFFF8001, 23 CurrentProcess = 0xFFFF8001,
@@ -81,6 +85,10 @@ public:
81 85
82 template <class T> 86 template <class T>
83 T* Get(Handle handle) { 87 T* Get(Handle handle) {
88 if (handle == CurrentThread) {
89 return reinterpret_cast<T*>(GetCurrentThread());
90 }
91
84 if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) { 92 if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) {
85 if (handle != 0) { 93 if (handle != 0) {
86 LOG_ERROR(Kernel, "Bad object handle %08x", handle); 94 LOG_ERROR(Kernel, "Bad object handle %08x", handle);
@@ -99,6 +107,10 @@ public:
99 // ONLY use this when you know the handle is valid. 107 // ONLY use this when you know the handle is valid.
100 template <class T> 108 template <class T>
101 T *GetFast(Handle handle) { 109 T *GetFast(Handle handle) {
110 if (handle == CurrentThread) {
111 return reinterpret_cast<T*>(GetCurrentThread());
112 }
113
102 const Handle realHandle = handle - HANDLE_OFFSET; 114 const Handle realHandle = handle - HANDLE_OFFSET;
103 _dbg_assert_(Kernel, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]); 115 _dbg_assert_(Kernel, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]);
104 return static_cast<T*>(pool[realHandle]); 116 return static_cast<T*>(pool[realHandle]);
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 6f56da8a9..f955d1957 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -20,8 +20,8 @@ public:
20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; } 20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; }
21 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; } 21 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; }
22 22
23 u32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 23 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
24 u32 available_count; ///< Number of free slots left in the semaphore 24 s32 available_count; ///< Number of free slots left in the semaphore
25 std::queue<Handle> waiting_threads; ///< Threads that are waiting for the semaphore 25 std::queue<Handle> waiting_threads; ///< Threads that are waiting for the semaphore
26 std::string name; ///< Name of semaphore (optional) 26 std::string name; ///< Name of semaphore (optional)
27 27
@@ -49,8 +49,8 @@ public:
49 49
50//////////////////////////////////////////////////////////////////////////////////////////////////// 50////////////////////////////////////////////////////////////////////////////////////////////////////
51 51
52ResultCode CreateSemaphore(Handle* handle, u32 initial_count, 52ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
53 u32 max_count, const std::string& name) { 53 s32 max_count, const std::string& name) {
54 54
55 if (initial_count > max_count) 55 if (initial_count > max_count)
56 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, 56 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index f0075fdb8..ad474b875 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -18,7 +18,7 @@ namespace Kernel {
18 * @param name Optional name of semaphore 18 * @param name Optional name of semaphore
19 * @return ResultCode of the error 19 * @return ResultCode of the error
20 */ 20 */
21ResultCode CreateSemaphore(Handle* handle, u32 initial_count, u32 max_count, const std::string& name = "Unknown"); 21ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown");
22 22
23/** 23/**
24 * Releases a certain number of slots from a semaphore. 24 * Releases a certain number of slots from a semaphore.
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 1c04701de..834308926 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -83,8 +83,7 @@ static Thread* current_thread;
83static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup 83static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
84static u32 next_thread_id; ///< The next available thread id 84static u32 next_thread_id; ///< The next available thread id
85 85
86/// Gets the current thread 86Thread* GetCurrentThread() {
87inline Thread* GetCurrentThread() {
88 return current_thread; 87 return current_thread;
89} 88}
90 89
@@ -148,16 +147,19 @@ void ChangeReadyState(Thread* t, bool ready) {
148 } 147 }
149} 148}
150 149
151/// Verify that a thread has not been released from waiting 150/// Check if a thread is blocking on a specified wait type
152static bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) { 151static bool CheckWaitType(const Thread* thread, WaitType type) {
153 _dbg_assert_(Kernel, thread != nullptr); 152 return (type == thread->wait_type) && (thread->IsWaiting());
154 return (type == thread->wait_type) && (wait_handle == thread->wait_handle) && (thread->IsWaiting());
155} 153}
156 154
157/// Verify that a thread has not been released from waiting (with wait address) 155/// Check if a thread is blocking on a specified wait type with a specified handle
158static bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle, VAddr wait_address) { 156static bool CheckWaitType(const Thread* thread, WaitType type, Handle wait_handle) {
159 _dbg_assert_(Kernel, thread != nullptr); 157 return CheckWaitType(thread, type) && (wait_handle == thread->wait_handle);
160 return VerifyWait(thread, type, wait_handle) && (wait_address == thread->wait_address); 158}
159
160/// Check if a thread is blocking on a specified wait type with a specified handle and address
161static bool CheckWaitType(const Thread* thread, WaitType type, Handle wait_handle, VAddr wait_address) {
162 return CheckWaitType(thread, type, wait_handle) && (wait_address == thread->wait_address);
161} 163}
162 164
163/// Stops the current thread 165/// Stops the current thread
@@ -172,9 +174,9 @@ ResultCode StopThread(Handle handle, const char* reason) {
172 thread->status = THREADSTATUS_DORMANT; 174 thread->status = THREADSTATUS_DORMANT;
173 for (Handle waiting_handle : thread->waiting_threads) { 175 for (Handle waiting_handle : thread->waiting_threads) {
174 Thread* waiting_thread = g_object_pool.Get<Thread>(waiting_handle); 176 Thread* waiting_thread = g_object_pool.Get<Thread>(waiting_handle);
175 if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) { 177
178 if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, handle))
176 ResumeThreadFromWait(waiting_handle); 179 ResumeThreadFromWait(waiting_handle);
177 }
178 } 180 }
179 thread->waiting_threads.clear(); 181 thread->waiting_threads.clear();
180 182
@@ -210,7 +212,7 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
210 for (Handle handle : thread_queue) { 212 for (Handle handle : thread_queue) {
211 Thread* thread = g_object_pool.Get<Thread>(handle); 213 Thread* thread = g_object_pool.Get<Thread>(handle);
212 214
213 if (!VerifyWait(thread, WAITTYPE_ARB, arbiter, address)) 215 if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address))
214 continue; 216 continue;
215 217
216 if (thread == nullptr) 218 if (thread == nullptr)
@@ -235,7 +237,7 @@ void ArbitrateAllThreads(u32 arbiter, u32 address) {
235 for (Handle handle : thread_queue) { 237 for (Handle handle : thread_queue) {
236 Thread* thread = g_object_pool.Get<Thread>(handle); 238 Thread* thread = g_object_pool.Get<Thread>(handle);
237 239
238 if (VerifyWait(thread, WAITTYPE_ARB, arbiter, address)) 240 if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address))
239 ResumeThreadFromWait(handle); 241 ResumeThreadFromWait(handle);
240 } 242 }
241} 243}
@@ -306,6 +308,8 @@ void ResumeThreadFromWait(Handle handle) {
306 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle); 308 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle);
307 if (thread) { 309 if (thread) {
308 thread->status &= ~THREADSTATUS_WAIT; 310 thread->status &= ~THREADSTATUS_WAIT;
311 thread->wait_handle = 0;
312 thread->wait_type = WAITTYPE_NONE;
309 if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { 313 if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
310 ChangeReadyState(thread, true); 314 ChangeReadyState(thread, true);
311 } 315 }
@@ -469,19 +473,27 @@ void Reschedule() {
469 Thread* prev = GetCurrentThread(); 473 Thread* prev = GetCurrentThread();
470 Thread* next = NextThread(); 474 Thread* next = NextThread();
471 HLE::g_reschedule = false; 475 HLE::g_reschedule = false;
472 if (next > 0) {
473 LOG_TRACE(Kernel, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle());
474 476
477 if (next != nullptr) {
478 LOG_TRACE(Kernel, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle());
475 SwitchContext(next); 479 SwitchContext(next);
480 } else {
481 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle());
476 482
477 // Hack - There is no mechanism yet to waken the primary thread if it has been put to sleep 483 for (Handle handle : thread_queue) {
478 // by a simulated VBLANK thread switch. So, we'll just immediately set it to "ready" again. 484 Thread* thread = g_object_pool.Get<Thread>(handle);
479 // This results in the current thread yielding on a VBLANK once, and then it will be 485 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X",
480 // immediately placed back in the queue for execution. 486 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, thread->wait_handle);
481 if (prev->wait_type == WAITTYPE_VBLANK) {
482 ResumeThreadFromWait(prev->GetHandle());
483 } 487 }
484 } 488 }
489
490 // TODO(bunnei): Hack - There is no timing mechanism yet to wake up a thread if it has been put
491 // to sleep. So, we'll just immediately set it to "ready" again after an attempted context
492 // switch has occurred. This results in the current thread yielding on a sleep once, and then it
493 // will immediately be placed back in the queue for execution.
494
495 if (CheckWaitType(prev, WAITTYPE_SLEEP))
496 ResumeThreadFromWait(prev->GetHandle());
485} 497}
486 498
487ResultCode GetThreadId(u32* thread_id, Handle handle) { 499ResultCode GetThreadId(u32* thread_id, Handle handle) {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index be7adface..65e8ef554 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -40,7 +40,6 @@ enum WaitType {
40 WAITTYPE_SEMA, 40 WAITTYPE_SEMA,
41 WAITTYPE_EVENT, 41 WAITTYPE_EVENT,
42 WAITTYPE_THREADEND, 42 WAITTYPE_THREADEND,
43 WAITTYPE_VBLANK,
44 WAITTYPE_MUTEX, 43 WAITTYPE_MUTEX,
45 WAITTYPE_SYNCH, 44 WAITTYPE_SYNCH,
46 WAITTYPE_ARB, 45 WAITTYPE_ARB,
@@ -78,6 +77,9 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address);
78/// Arbitrate all threads currently waiting... 77/// Arbitrate all threads currently waiting...
79void ArbitrateAllThreads(u32 arbiter, u32 address); 78void ArbitrateAllThreads(u32 arbiter, u32 address);
80 79
80/// Gets the current thread
81Thread* GetCurrentThread();
82
81/// Gets the current thread handle 83/// Gets the current thread handle
82Handle GetCurrentThreadHandle(); 84Handle GetCurrentThreadHandle();
83 85
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 47e9bf77e..70ef7839c 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -352,7 +352,8 @@ static Result ClearEvent(Handle evt) {
352static void SleepThread(s64 nanoseconds) { 352static void SleepThread(s64 nanoseconds) {
353 LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds); 353 LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds);
354 354
355 // Check for next thread to schedule 355 // Sleep current thread and check for next thread to schedule
356 Kernel::WaitCurrentThread(WAITTYPE_SLEEP);
356 HLE::Reschedule(__func__); 357 HLE::Reschedule(__func__);
357} 358}
358 359
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index 0437e5374..3d84fc5da 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -223,9 +223,7 @@ int THREEDSXReader::Load3DSXFile(const std::string& filename, u32 base_addr)
223 LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str()); 223 LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str());
224 FileUtil::IOFile file(filename, "rb"); 224 FileUtil::IOFile file(filename, "rb");
225 if (file.IsOpen()) { 225 if (file.IsOpen()) {
226 226 THREEDSXReader::Load3DSXFile(filename, 0x00100000);
227 THREEDSXReader reader;
228 reader.Load3DSXFile(filename, 0x00100000);
229 Kernel::LoadExec(0x00100000); 227 Kernel::LoadExec(0x00100000);
230 } else { 228 } else {
231 return ResultStatus::Error; 229 return ResultStatus::Error;