diff options
| -rw-r--r-- | appveyor.yml | 2 | ||||
| -rw-r--r-- | src/common/common_types.h | 26 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/arm_regformat.h | 2 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfp.cpp | 20 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfp.h | 4 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpinstr.cpp | 75 | ||||
| -rw-r--r-- | src/core/hle/service/soc_u.cpp | 18 | ||||
| -rw-r--r-- | src/core/hw/gpu.cpp | 79 | ||||
| -rw-r--r-- | src/core/loader/ncch.cpp | 1 |
9 files changed, 115 insertions, 112 deletions
diff --git a/appveyor.yml b/appveyor.yml index 7e9155e6d..5dc147639 100644 --- a/appveyor.yml +++ b/appveyor.yml | |||
| @@ -13,7 +13,7 @@ configuration: | |||
| 13 | - Release | 13 | - Release |
| 14 | 14 | ||
| 15 | install: | 15 | install: |
| 16 | - git submodule update --init --recursive --depth 20 | 16 | - git submodule update --init --recursive |
| 17 | 17 | ||
| 18 | before_build: | 18 | before_build: |
| 19 | - mkdir build | 19 | - mkdir build |
diff --git a/src/common/common_types.h b/src/common/common_types.h index ebfd7824a..fa3e0b8d6 100644 --- a/src/common/common_types.h +++ b/src/common/common_types.h | |||
| @@ -50,32 +50,6 @@ typedef double f64; ///< 64-bit floating point | |||
| 50 | typedef u32 VAddr; ///< Represents a pointer in the userspace virtual address space. | 50 | typedef u32 VAddr; ///< Represents a pointer in the userspace virtual address space. |
| 51 | typedef u32 PAddr; ///< Represents a pointer in the ARM11 physical address space. | 51 | typedef u32 PAddr; ///< Represents a pointer in the ARM11 physical address space. |
| 52 | 52 | ||
| 53 | /// Union for fast 16-bit type casting | ||
| 54 | union t16 { | ||
| 55 | u8 _u8[2]; ///< 8-bit unsigned char(s) | ||
| 56 | u16 _u16; ///< 16-bit unsigned shorts(s) | ||
| 57 | }; | ||
| 58 | |||
| 59 | /// Union for fast 32-bit type casting | ||
| 60 | union t32 { | ||
| 61 | f32 _f32; ///< 32-bit floating point(s) | ||
| 62 | u32 _u32; ///< 32-bit unsigned int(s) | ||
| 63 | s32 _s32; ///< 32-bit signed int(s) | ||
| 64 | u16 _u16[2]; ///< 16-bit unsigned shorts(s) | ||
| 65 | u8 _u8[4]; ///< 8-bit unsigned char(s) | ||
| 66 | }; | ||
| 67 | |||
| 68 | /// Union for fast 64-bit type casting | ||
| 69 | union t64 { | ||
| 70 | f64 _f64; ///< 64-bit floating point | ||
| 71 | u64 _u64; ///< 64-bit unsigned long | ||
| 72 | f32 _f32[2]; ///< 32-bit floating point(s) | ||
| 73 | u32 _u32[2]; ///< 32-bit unsigned int(s) | ||
| 74 | s32 _s32[2]; ///< 32-bit signed int(s) | ||
| 75 | u16 _u16[4]; ///< 16-bit unsigned shorts(s) | ||
| 76 | u8 _u8[8]; ///< 8-bit unsigned char(s) | ||
| 77 | }; | ||
| 78 | |||
| 79 | // An inheritable class to disallow the copy constructor and operator= functions | 53 | // An inheritable class to disallow the copy constructor and operator= functions |
| 80 | class NonCopyable { | 54 | class NonCopyable { |
| 81 | protected: | 55 | protected: |
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h index a92effbb4..d1c721809 100644 --- a/src/core/arm/skyeye_common/arm_regformat.h +++ b/src/core/arm/skyeye_common/arm_regformat.h | |||
| @@ -59,6 +59,8 @@ enum { | |||
| 59 | VFP_FPSID, | 59 | VFP_FPSID, |
| 60 | VFP_FPSCR, | 60 | VFP_FPSCR, |
| 61 | VFP_FPEXC, | 61 | VFP_FPEXC, |
| 62 | VFP_FPINST, | ||
| 63 | VFP_FPINST2, | ||
| 62 | VFP_MVFR0, | 64 | VFP_MVFR0, |
| 63 | VFP_MVFR1, | 65 | VFP_MVFR1, |
| 64 | 66 | ||
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp index bbe11f690..1ffc1f9af 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.cpp +++ b/src/core/arm/skyeye_common/vfp/vfp.cpp | |||
| @@ -27,30 +27,20 @@ | |||
| 27 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" | 27 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" |
| 28 | #include "core/arm/skyeye_common/vfp/vfp.h" | 28 | #include "core/arm/skyeye_common/vfp/vfp.h" |
| 29 | 29 | ||
| 30 | unsigned VFPInit(ARMul_State* state) | 30 | void VFPInit(ARMul_State* state) |
| 31 | { | 31 | { |
| 32 | state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 | | 32 | state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 | |
| 33 | VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION; | 33 | VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION; |
| 34 | state->VFP[VFP_FPEXC] = 0; | 34 | state->VFP[VFP_FPEXC] = 0; |
| 35 | state->VFP[VFP_FPSCR] = 0; | 35 | state->VFP[VFP_FPSCR] = 0; |
| 36 | 36 | ||
| 37 | // ARM11 MPCore instruction register reset values. | ||
| 38 | state->VFP[VFP_FPINST] = 0xEE000A00; | ||
| 39 | state->VFP[VFP_FPINST2] = 0; | ||
| 40 | |||
| 37 | // ARM11 MPCore feature register values. | 41 | // ARM11 MPCore feature register values. |
| 38 | state->VFP[VFP_MVFR0] = 0x11111111; | 42 | state->VFP[VFP_MVFR0] = 0x11111111; |
| 39 | state->VFP[VFP_MVFR1] = 0; | 43 | state->VFP[VFP_MVFR1] = 0; |
| 40 | |||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | void VMSR(ARMul_State* state, ARMword reg, ARMword Rt) | ||
| 45 | { | ||
| 46 | if (reg == 1) | ||
| 47 | { | ||
| 48 | state->VFP[VFP_FPSCR] = state->Reg[Rt]; | ||
| 49 | } | ||
| 50 | else if (reg == 8) | ||
| 51 | { | ||
| 52 | state->VFP[VFP_FPEXC] = state->Reg[Rt]; | ||
| 53 | } | ||
| 54 | } | 44 | } |
| 55 | 45 | ||
| 56 | void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value) | 46 | void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value) |
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h index acefae9bb..80ca93ccd 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.h +++ b/src/core/arm/skyeye_common/vfp/vfp.h | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | #define CHECK_VFP_ENABLED | 26 | #define CHECK_VFP_ENABLED |
| 27 | #define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]); | 27 | #define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]); |
| 28 | 28 | ||
| 29 | unsigned VFPInit(ARMul_State* state); | 29 | void VFPInit(ARMul_State* state); |
| 30 | 30 | ||
| 31 | s32 vfp_get_float(ARMul_State* state, u32 reg); | 31 | s32 vfp_get_float(ARMul_State* state, u32 reg); |
| 32 | void vfp_put_float(ARMul_State* state, s32 val, u32 reg); | 32 | void vfp_put_float(ARMul_State* state, s32 val, u32 reg); |
| @@ -36,10 +36,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc | |||
| 36 | u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); | 36 | u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); |
| 37 | u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); | 37 | u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); |
| 38 | 38 | ||
| 39 | void VMSR(ARMul_State* state, ARMword reg, ARMword Rt); | ||
| 40 | void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value); | 39 | void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value); |
| 41 | void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); | 40 | void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); |
| 42 | void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); | 41 | void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); |
| 43 | void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm); | 42 | void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm); |
| 44 | void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm); | 43 | void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm); |
| 45 | |||
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp index 67fe63aa4..8efcbab1c 100644 --- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp | |||
| @@ -995,7 +995,7 @@ VMOVBRS_INST: | |||
| 995 | #ifdef VFP_INTERPRETER_STRUCT | 995 | #ifdef VFP_INTERPRETER_STRUCT |
| 996 | struct vmsr_inst { | 996 | struct vmsr_inst { |
| 997 | unsigned int reg; | 997 | unsigned int reg; |
| 998 | unsigned int Rd; | 998 | unsigned int Rt; |
| 999 | }; | 999 | }; |
| 1000 | #endif | 1000 | #endif |
| 1001 | #ifdef VFP_INTERPRETER_TRANS | 1001 | #ifdef VFP_INTERPRETER_TRANS |
| @@ -1009,7 +1009,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index) | |||
| 1009 | inst_base->br = NON_BRANCH; | 1009 | inst_base->br = NON_BRANCH; |
| 1010 | 1010 | ||
| 1011 | inst_cream->reg = BITS(inst, 16, 19); | 1011 | inst_cream->reg = BITS(inst, 16, 19); |
| 1012 | inst_cream->Rd = BITS(inst, 12, 15); | 1012 | inst_cream->Rt = BITS(inst, 12, 15); |
| 1013 | 1013 | ||
| 1014 | return inst_base; | 1014 | return inst_base; |
| 1015 | } | 1015 | } |
| @@ -1017,15 +1017,30 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index) | |||
| 1017 | #ifdef VFP_INTERPRETER_IMPL | 1017 | #ifdef VFP_INTERPRETER_IMPL |
| 1018 | VMSR_INST: | 1018 | VMSR_INST: |
| 1019 | { | 1019 | { |
| 1020 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 1020 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 1021 | /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled , | 1021 | /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled , |
| 1022 | and in privileged mode */ | 1022 | and in privileged mode */ |
| 1023 | /* Exceptions must be checked, according to v7 ref manual */ | 1023 | /* Exceptions must be checked, according to v7 ref manual */ |
| 1024 | CHECK_VFP_ENABLED; | 1024 | CHECK_VFP_ENABLED; |
| 1025 | 1025 | ||
| 1026 | vmsr_inst *inst_cream = (vmsr_inst *)inst_base->component; | 1026 | vmsr_inst* const inst_cream = (vmsr_inst*)inst_base->component; |
| 1027 | |||
| 1028 | unsigned int reg = inst_cream->reg; | ||
| 1029 | unsigned int rt = inst_cream->Rt; | ||
| 1027 | 1030 | ||
| 1028 | VMSR(cpu, inst_cream->reg, inst_cream->Rd); | 1031 | if (reg == 1) |
| 1032 | { | ||
| 1033 | cpu->VFP[VFP_FPSCR] = cpu->Reg[rt]; | ||
| 1034 | } | ||
| 1035 | else if (InAPrivilegedMode(cpu)) | ||
| 1036 | { | ||
| 1037 | if (reg == 8) | ||
| 1038 | cpu->VFP[VFP_FPEXC] = cpu->Reg[rt]; | ||
| 1039 | else if (reg == 9) | ||
| 1040 | cpu->VFP[VFP_FPINST] = cpu->Reg[rt]; | ||
| 1041 | else if (reg == 10) | ||
| 1042 | cpu->VFP[VFP_FPINST2] = cpu->Reg[rt]; | ||
| 1043 | } | ||
| 1029 | } | 1044 | } |
| 1030 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1045 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 1031 | INC_PC(sizeof(vmsr_inst)); | 1046 | INC_PC(sizeof(vmsr_inst)); |
| @@ -1111,19 +1126,22 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index) | |||
| 1111 | #ifdef VFP_INTERPRETER_IMPL | 1126 | #ifdef VFP_INTERPRETER_IMPL |
| 1112 | VMRS_INST: | 1127 | VMRS_INST: |
| 1113 | { | 1128 | { |
| 1114 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 1129 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 1115 | /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled, | 1130 | /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled, |
| 1116 | and in privileged mode */ | 1131 | and in privileged mode */ |
| 1117 | /* Exceptions must be checked, according to v7 ref manual */ | 1132 | /* Exceptions must be checked, according to v7 ref manual */ |
| 1118 | CHECK_VFP_ENABLED; | 1133 | CHECK_VFP_ENABLED; |
| 1119 | 1134 | ||
| 1120 | vmrs_inst *inst_cream = (vmrs_inst *)inst_base->component; | 1135 | vmrs_inst* const inst_cream = (vmrs_inst*)inst_base->component; |
| 1121 | 1136 | ||
| 1122 | if (inst_cream->reg == 1) /* FPSCR */ | 1137 | unsigned int reg = inst_cream->reg; |
| 1138 | unsigned int rt = inst_cream->Rt; | ||
| 1139 | |||
| 1140 | if (reg == 1) // FPSCR | ||
| 1123 | { | 1141 | { |
| 1124 | if (inst_cream->Rt != 15) | 1142 | if (rt != 15) |
| 1125 | { | 1143 | { |
| 1126 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPSCR]; | 1144 | cpu->Reg[rt] = cpu->VFP[VFP_FPSCR]; |
| 1127 | } | 1145 | } |
| 1128 | else | 1146 | else |
| 1129 | { | 1147 | { |
| @@ -1133,25 +1151,26 @@ VMRS_INST: | |||
| 1133 | cpu->VFlag = (cpu->VFP[VFP_FPSCR] >> 28) & 1; | 1151 | cpu->VFlag = (cpu->VFP[VFP_FPSCR] >> 28) & 1; |
| 1134 | } | 1152 | } |
| 1135 | } | 1153 | } |
| 1136 | else | 1154 | else if (reg == 0) |
| 1137 | { | 1155 | { |
| 1138 | switch (inst_cream->reg) | 1156 | cpu->Reg[rt] = cpu->VFP[VFP_FPSID]; |
| 1139 | { | 1157 | } |
| 1140 | case 0: | 1158 | else if (reg == 6) |
| 1141 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPSID]; | 1159 | { |
| 1142 | break; | 1160 | cpu->Reg[rt] = cpu->VFP[VFP_MVFR1]; |
| 1143 | case 6: | 1161 | } |
| 1144 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_MVFR1]; | 1162 | else if (reg == 7) |
| 1145 | break; | 1163 | { |
| 1146 | case 7: | 1164 | cpu->Reg[rt] = cpu->VFP[VFP_MVFR0]; |
| 1147 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_MVFR0]; | 1165 | } |
| 1148 | break; | 1166 | else if (InAPrivilegedMode(cpu)) |
| 1149 | case 8: | 1167 | { |
| 1150 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPEXC]; | 1168 | if (reg == 8) |
| 1151 | break; | 1169 | cpu->Reg[rt] = cpu->VFP[VFP_FPEXC]; |
| 1152 | default: | 1170 | else if (reg == 9) |
| 1153 | break; | 1171 | cpu->Reg[rt] = cpu->VFP[VFP_FPINST]; |
| 1154 | } | 1172 | else if (reg == 10) |
| 1173 | cpu->Reg[rt] = cpu->VFP[VFP_FPINST2]; | ||
| 1155 | } | 1174 | } |
| 1156 | } | 1175 | } |
| 1157 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1176 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index 5b2a643d8..d0e166fdf 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp | |||
| @@ -335,6 +335,7 @@ static void Socket(Service::Interface* self) { | |||
| 335 | if ((s32)socket_handle == SOCKET_ERROR_VALUE) | 335 | if ((s32)socket_handle == SOCKET_ERROR_VALUE) |
| 336 | result = TranslateError(GET_ERRNO); | 336 | result = TranslateError(GET_ERRNO); |
| 337 | 337 | ||
| 338 | cmd_buffer[0] = IPC::MakeHeader(2, 2, 0); | ||
| 338 | cmd_buffer[1] = result; | 339 | cmd_buffer[1] = result; |
| 339 | cmd_buffer[2] = socket_handle; | 340 | cmd_buffer[2] = socket_handle; |
| 340 | } | 341 | } |
| @@ -358,8 +359,9 @@ static void Bind(Service::Interface* self) { | |||
| 358 | if (res != 0) | 359 | if (res != 0) |
| 359 | result = TranslateError(GET_ERRNO); | 360 | result = TranslateError(GET_ERRNO); |
| 360 | 361 | ||
| 361 | cmd_buffer[2] = res; | 362 | cmd_buffer[0] = IPC::MakeHeader(5, 2, 0); |
| 362 | cmd_buffer[1] = result; | 363 | cmd_buffer[1] = result; |
| 364 | cmd_buffer[2] = res; | ||
| 363 | } | 365 | } |
| 364 | 366 | ||
| 365 | static void Fcntl(Service::Interface* self) { | 367 | static void Fcntl(Service::Interface* self) { |
| @@ -441,8 +443,9 @@ static void Listen(Service::Interface* self) { | |||
| 441 | if (ret != 0) | 443 | if (ret != 0) |
| 442 | result = TranslateError(GET_ERRNO); | 444 | result = TranslateError(GET_ERRNO); |
| 443 | 445 | ||
| 444 | cmd_buffer[2] = ret; | 446 | cmd_buffer[0] = IPC::MakeHeader(3, 2, 0); |
| 445 | cmd_buffer[1] = result; | 447 | cmd_buffer[1] = result; |
| 448 | cmd_buffer[2] = ret; | ||
| 446 | } | 449 | } |
| 447 | 450 | ||
| 448 | static void Accept(Service::Interface* self) { | 451 | static void Accept(Service::Interface* self) { |
| @@ -467,8 +470,10 @@ static void Accept(Service::Interface* self) { | |||
| 467 | Memory::WriteBlock(cmd_buffer[0x104 >> 2], (const u8*)&ctr_addr, max_addr_len); | 470 | Memory::WriteBlock(cmd_buffer[0x104 >> 2], (const u8*)&ctr_addr, max_addr_len); |
| 468 | } | 471 | } |
| 469 | 472 | ||
| 470 | cmd_buffer[2] = ret; | 473 | cmd_buffer[0] = IPC::MakeHeader(4, 2, 2); |
| 471 | cmd_buffer[1] = result; | 474 | cmd_buffer[1] = result; |
| 475 | cmd_buffer[2] = ret; | ||
| 476 | cmd_buffer[3] = IPC::StaticBufferDesc(static_cast<u32>(max_addr_len), 0); | ||
| 472 | } | 477 | } |
| 473 | 478 | ||
| 474 | static void GetHostId(Service::Interface* self) { | 479 | static void GetHostId(Service::Interface* self) { |
| @@ -676,8 +681,10 @@ static void Connect(Service::Interface* self) { | |||
| 676 | int result = 0; | 681 | int result = 0; |
| 677 | if (ret != 0) | 682 | if (ret != 0) |
| 678 | result = TranslateError(GET_ERRNO); | 683 | result = TranslateError(GET_ERRNO); |
| 679 | cmd_buffer[2] = ret; | 684 | |
| 685 | cmd_buffer[0] = IPC::MakeHeader(6, 2, 0); | ||
| 680 | cmd_buffer[1] = result; | 686 | cmd_buffer[1] = result; |
| 687 | cmd_buffer[2] = ret; | ||
| 681 | } | 688 | } |
| 682 | 689 | ||
| 683 | static void InitializeSockets(Service::Interface* self) { | 690 | static void InitializeSockets(Service::Interface* self) { |
| @@ -688,7 +695,8 @@ static void InitializeSockets(Service::Interface* self) { | |||
| 688 | #endif | 695 | #endif |
| 689 | 696 | ||
| 690 | u32* cmd_buffer = Kernel::GetCommandBuffer(); | 697 | u32* cmd_buffer = Kernel::GetCommandBuffer(); |
| 691 | cmd_buffer[1] = 0; | 698 | cmd_buffer[0] = IPC::MakeHeader(1, 1, 0); |
| 699 | cmd_buffer[1] = RESULT_SUCCESS.raw; | ||
| 692 | } | 700 | } |
| 693 | 701 | ||
| 694 | static void ShutdownSockets(Service::Interface* self) { | 702 | static void ShutdownSockets(Service::Interface* self) { |
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 901519a8b..a1789f9c7 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -56,6 +56,29 @@ inline void Read(T &var, const u32 raw_addr) { | |||
| 56 | var = g_regs[addr / 4]; | 56 | var = g_regs[addr / 4]; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static Math::Vec4<u8> DecodePixel(Regs::PixelFormat input_format, const u8* src_pixel) { | ||
| 60 | switch (input_format) { | ||
| 61 | case Regs::PixelFormat::RGBA8: | ||
| 62 | return Color::DecodeRGBA8(src_pixel); | ||
| 63 | |||
| 64 | case Regs::PixelFormat::RGB8: | ||
| 65 | return Color::DecodeRGB8(src_pixel); | ||
| 66 | |||
| 67 | case Regs::PixelFormat::RGB565: | ||
| 68 | return Color::DecodeRGB565(src_pixel); | ||
| 69 | |||
| 70 | case Regs::PixelFormat::RGB5A1: | ||
| 71 | return Color::DecodeRGB5A1(src_pixel); | ||
| 72 | |||
| 73 | case Regs::PixelFormat::RGBA4: | ||
| 74 | return Color::DecodeRGBA4(src_pixel); | ||
| 75 | |||
| 76 | default: | ||
| 77 | LOG_ERROR(HW_GPU, "Unknown source framebuffer format %x", input_format); | ||
| 78 | return {0, 0, 0, 0}; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 59 | template <typename T> | 82 | template <typename T> |
| 60 | inline void Write(u32 addr, const T data) { | 83 | inline void Write(u32 addr, const T data) { |
| 61 | addr -= HW::VADDR_GPU; | 84 | addr -= HW::VADDR_GPU; |
| @@ -128,11 +151,18 @@ inline void Write(u32 addr, const T data) { | |||
| 128 | break; | 151 | break; |
| 129 | } | 152 | } |
| 130 | 153 | ||
| 131 | unsigned horizontal_scale = (config.scaling != config.NoScale) ? 2 : 1; | 154 | if (config.output_tiled && |
| 132 | unsigned vertical_scale = (config.scaling == config.ScaleXY) ? 2 : 1; | 155 | (config.scaling == config.ScaleXY || config.scaling == config.ScaleX)) { |
| 156 | LOG_CRITICAL(HW_GPU, "Scaling is only implemented on tiled input"); | ||
| 157 | UNIMPLEMENTED(); | ||
| 158 | break; | ||
| 159 | } | ||
| 133 | 160 | ||
| 134 | u32 output_width = config.output_width / horizontal_scale; | 161 | bool horizontal_scale = config.scaling != config.NoScale; |
| 135 | u32 output_height = config.output_height / vertical_scale; | 162 | bool vertical_scale = config.scaling == config.ScaleXY; |
| 163 | |||
| 164 | u32 output_width = config.output_width >> horizontal_scale; | ||
| 165 | u32 output_height = config.output_height >> vertical_scale; | ||
| 136 | 166 | ||
| 137 | u32 input_size = config.input_width * config.input_height * GPU::Regs::BytesPerPixel(config.input_format); | 167 | u32 input_size = config.input_width * config.input_height * GPU::Regs::BytesPerPixel(config.input_format); |
| 138 | u32 output_size = output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format); | 168 | u32 output_size = output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format); |
| @@ -156,16 +186,14 @@ inline void Write(u32 addr, const T data) { | |||
| 156 | break; | 186 | break; |
| 157 | } | 187 | } |
| 158 | 188 | ||
| 159 | // TODO(Subv): Implement the box filter when scaling is enabled | ||
| 160 | // right now we're just skipping the extra pixels. | ||
| 161 | for (u32 y = 0; y < output_height; ++y) { | 189 | for (u32 y = 0; y < output_height; ++y) { |
| 162 | for (u32 x = 0; x < output_width; ++x) { | 190 | for (u32 x = 0; x < output_width; ++x) { |
| 163 | Math::Vec4<u8> src_color = { 0, 0, 0, 0 }; | 191 | Math::Vec4<u8> src_color; |
| 164 | 192 | ||
| 165 | // Calculate the [x,y] position of the input image | 193 | // Calculate the [x,y] position of the input image |
| 166 | // based on the current output position and the scale | 194 | // based on the current output position and the scale |
| 167 | u32 input_x = x * horizontal_scale; | 195 | u32 input_x = x << horizontal_scale; |
| 168 | u32 input_y = y * vertical_scale; | 196 | u32 input_y = y << vertical_scale; |
| 169 | 197 | ||
| 170 | if (config.flip_vertically) { | 198 | if (config.flip_vertically) { |
| 171 | // Flip the y value of the output data, | 199 | // Flip the y value of the output data, |
| @@ -196,30 +224,15 @@ inline void Write(u32 addr, const T data) { | |||
| 196 | } | 224 | } |
| 197 | 225 | ||
| 198 | const u8* src_pixel = src_pointer + src_offset; | 226 | const u8* src_pixel = src_pointer + src_offset; |
| 199 | switch (config.input_format) { | 227 | src_color = DecodePixel(config.input_format, src_pixel); |
| 200 | case Regs::PixelFormat::RGBA8: | 228 | if (config.scaling == config.ScaleX) { |
| 201 | src_color = Color::DecodeRGBA8(src_pixel); | 229 | Math::Vec4<u8> pixel = DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel); |
| 202 | break; | 230 | src_color = ((src_color + pixel) / 2).Cast<u8>(); |
| 203 | 231 | } else if (config.scaling == config.ScaleXY) { | |
| 204 | case Regs::PixelFormat::RGB8: | 232 | Math::Vec4<u8> pixel1 = DecodePixel(config.input_format, src_pixel + 1 * src_bytes_per_pixel); |
| 205 | src_color = Color::DecodeRGB8(src_pixel); | 233 | Math::Vec4<u8> pixel2 = DecodePixel(config.input_format, src_pixel + 2 * src_bytes_per_pixel); |
| 206 | break; | 234 | Math::Vec4<u8> pixel3 = DecodePixel(config.input_format, src_pixel + 3 * src_bytes_per_pixel); |
| 207 | 235 | src_color = (((src_color + pixel1) + (pixel2 + pixel3)) / 4).Cast<u8>(); | |
| 208 | case Regs::PixelFormat::RGB565: | ||
| 209 | src_color = Color::DecodeRGB565(src_pixel); | ||
| 210 | break; | ||
| 211 | |||
| 212 | case Regs::PixelFormat::RGB5A1: | ||
| 213 | src_color = Color::DecodeRGB5A1(src_pixel); | ||
| 214 | break; | ||
| 215 | |||
| 216 | case Regs::PixelFormat::RGBA4: | ||
| 217 | src_color = Color::DecodeRGBA4(src_pixel); | ||
| 218 | break; | ||
| 219 | |||
| 220 | default: | ||
| 221 | LOG_ERROR(HW_GPU, "Unknown source framebuffer format %x", config.input_format.Value()); | ||
| 222 | break; | ||
| 223 | } | 236 | } |
| 224 | 237 | ||
| 225 | u8* dst_pixel = dst_pointer + dst_offset; | 238 | u8* dst_pixel = dst_pointer + dst_offset; |
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index a8f8f78b7..2b26b31cf 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp | |||
| @@ -240,7 +240,6 @@ ResultStatus AppLoader_NCCH::Load() { | |||
| 240 | LOG_DEBUG(Loader, "Bss size: 0x%08X", bss_size); | 240 | LOG_DEBUG(Loader, "Bss size: 0x%08X", bss_size); |
| 241 | LOG_DEBUG(Loader, "Core version: %d" , core_version); | 241 | LOG_DEBUG(Loader, "Core version: %d" , core_version); |
| 242 | LOG_DEBUG(Loader, "Thread priority: 0x%X" , priority); | 242 | LOG_DEBUG(Loader, "Thread priority: 0x%X" , priority); |
| 243 | LOG_DEBUG(Loader, "Resource limit descriptor: 0x%08X", exheader_header.arm11_system_local_caps.resource_limit_descriptor); | ||
| 244 | LOG_DEBUG(Loader, "Resource limit category: %d" , resource_limit_category); | 243 | LOG_DEBUG(Loader, "Resource limit category: %d" , resource_limit_category); |
| 245 | 244 | ||
| 246 | // Read ExeFS... | 245 | // Read ExeFS... |