diff options
Diffstat (limited to 'src/core')
29 files changed, 369 insertions, 133 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index addcb953c..b67226d8d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -66,6 +66,7 @@ set(SRCS hle/service/soc_u.cpp hle/service/srv.cpp hle/service/ssl_c.cpp + hle/service/y2r_u.cpp hle/config_mem.cpp hle/hle.cpp hle/svc.cpp @@ -157,6 +158,7 @@ set(HEADERS hle/service/soc_u.h hle/service/srv.h hle/service/ssl_c.h + hle/service/y2r_u.h hle/config_mem.h hle/result.h hle/function_wrappers.h diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index ba23ef383..9b291862c 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -1083,7 +1083,7 @@ typedef struct _cdp_inst { unsigned int cp_num; unsigned int opcode_2; unsigned int CRm; - uint32 inst; + unsigned int inst; }cdp_inst; typedef struct _uxtb_inst { @@ -1423,15 +1423,19 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst)); bx_inst *inst_cream = (bx_inst *)inst_base->component; - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = INDIRECT_BRANCH; + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = INDIRECT_BRANCH; - inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rm = BITS(inst, 0, 3); return inst_base; } -ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("BXJ"); } +ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(bx)(inst, index); +} + ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index){ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst)); cdp_inst *inst_cream = (cdp_inst *)inst_base->component; @@ -2057,7 +2061,37 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) return inst_base; } -ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD"); } + +ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->op1 = BITS(inst, 21, 22); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd)(inst, index); +} +ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd)(inst, index); +} +ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd)(inst, index); +} + ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) { arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); @@ -2084,9 +2118,6 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) { return INTERPRETER_TRANSLATE(qadd8)(inst, index); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDADD"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDSUB"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB"); } ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) { return INTERPRETER_TRANSLATE(qadd8)(inst, index); @@ -2373,7 +2404,25 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) } ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALXY"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLAW"); } + +ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); + smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->Ra = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 8, 11); + inst_cream->Rn = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 16, 19); + inst_cream->m = BIT(inst, 6); + + return inst_base; +} ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) { @@ -3444,7 +3493,7 @@ static tdstate decode_thumb_instr(arm_processor *cpu, uint32_t inst, addr_t addr tdstate ret = thumb_translate (addr, inst, arm_inst, inst_size); if(ret == t_branch){ // TODO: FIXME, endian should be judged - uint32 tinstr; + u32 tinstr; if((addr & 0x3) != 0) tinstr = inst >> 16; else @@ -3457,7 +3506,7 @@ static tdstate decode_thumb_instr(arm_processor *cpu, uint32_t inst, addr_t addr case 26: case 27: if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ - uint32 cond = (tinstr & 0x0F00) >> 8; + u32 cond = (tinstr & 0x0F00) >> 8; inst_index = table_length - 4; *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); } else { @@ -4088,22 +4137,35 @@ unsigned InterpreterMainLoop(ARMul_State* state) { INC_PC(sizeof(blx_inst)); goto DISPATCH; } + BX_INST: + BXJ_INST: { - bx_inst *inst_cream = (bx_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + // Note that only the 'fail' case of BXJ is emulated. This is because + // the facilities for Jazelle emulation are not implemented. + // + // According to the ARM documentation on BXJ, if setting the J bit in the APSR + // fails, then BXJ functions identically like a regular BX instruction. + // + // This is sufficient for citra, as the CPU for the 3DS does not implement Jazelle. + + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + bx_inst* const inst_cream = (bx_inst*)inst_base->component; + if (inst_cream->Rm == 15) LOG_WARNING(Core_ARM11, "BX at pc %x: use of Rm = R15 is discouraged", cpu->Reg[15]); + cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1; cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe; INC_PC(sizeof(bx_inst)); goto DISPATCH; } + cpu->Reg[15] += GET_INST_SIZE(cpu); INC_PC(sizeof(bx_inst)); goto DISPATCH; } - BXJ_INST: + CDP_INST: { cdp_inst *inst_cream = (cdp_inst *)inst_base->component; @@ -5027,6 +5089,78 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } QADD_INST: + QDADD_INST: + QDSUB_INST: + QSUB_INST: + { + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + const u8 op1 = inst_cream->op1; + const u32 rm_val = RM; + const u32 rn_val = RN; + + u32 result = 0; + + // QADD + if (op1 == 0x00) { + result = rm_val + rn_val; + + if (AddOverflow(rm_val, rn_val, result)) { + result = POS(result) ? 0x80000000 : 0x7FFFFFFF; + cpu->Cpsr |= (1 << 27); + } + } + // QSUB + else if (op1 == 0x01) { + result = rm_val - rn_val; + + if (SubOverflow(rm_val, rn_val, result)) { + result = POS(result) ? 0x80000000 : 0x7FFFFFFF; + cpu->Cpsr |= (1 << 27); + } + } + // QDADD + else if (op1 == 0x02) { + u32 mul = (rn_val * 2); + + if (AddOverflow(rn_val, rn_val, rn_val * 2)) { + mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; + cpu->Cpsr |= (1 << 27); + } + + result = mul + rm_val; + + if (AddOverflow(rm_val, mul, result)) { + result = POS(result) ? 0x80000000 : 0x7FFFFFFF; + cpu->Cpsr |= (1 << 27); + } + } + // QDSUB + else if (op1 == 0x03) { + u32 mul = (rn_val * 2); + + if (AddOverflow(rn_val, rn_val, mul)) { + mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; + cpu->Cpsr |= (1 << 27); + } + + result = rm_val - mul; + + if (SubOverflow(rm_val, mul, result)) { + result = POS(result) ? 0x80000000 : 0x7FFFFFFF; + cpu->Cpsr |= (1 << 27); + } + } + + RD = result; + } + + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(generic_arm_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + QADD8_INST: QADD16_INST: QADDSUBX_INST: @@ -5089,10 +5223,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) { GOTO_NEXT_INST; } - QDADD_INST: - QDSUB_INST: - QSUB_INST: - REV_INST: REV16_INST: REVSH_INST: @@ -5461,7 +5591,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); RD = operand1 * operand2 + RN; - // TODO: FIXME: UPDATE Q FLAGS + if (AddOverflow(operand1 * operand2, RN, RD)) + cpu->Cpsr |= (1 << 27); } cpu->Reg[15] += GET_INST_SIZE(cpu); INC_PC(sizeof(smla_inst)); @@ -5555,7 +5686,31 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } SMLALXY_INST: + SMLAW_INST: + { + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; + + const u32 rm_val = RM; + const u32 rn_val = RN; + const u32 ra_val = cpu->Reg[inst_cream->Ra]; + const bool high = (inst_cream->m == 1); + + const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF); + const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16); + + RD = (result & (0xFFFFFFFFFFFFFFFFLL >> 15)) >> 16; + + if ((result >> 16) != (s32)RD) + cpu->Cpsr |= (1 << 27); + } + + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(smlad_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } SMLALD_INST: SMLSLD_INST: @@ -6585,7 +6740,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { BLX_1_THUMB: { // BLX 1 for armv5t and above - uint32 tmp = cpu->Reg[15]; + u32 tmp = cpu->Reg[15]; blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component; cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC; cpu->Reg[14] = ((tmp + 2) | 1); diff --git a/src/core/arm/dyncom/arm_dyncom_run.h b/src/core/arm/dyncom/arm_dyncom_run.h index aeabeac16..c70522274 100644 --- a/src/core/arm/dyncom/arm_dyncom_run.h +++ b/src/core/arm/dyncom/arm_dyncom_run.h @@ -24,8 +24,8 @@ void switch_mode(arm_core_t *core, uint32_t mode); /* FIXME, we temporarily think thumb instruction is always 16 bit */ -static inline uint32 GET_INST_SIZE(arm_core_t* core){ - return core->TFlag? 2 : 4; +static inline u32 GET_INST_SIZE(arm_core_t* core) { + return core->TFlag? 2 : 4; } /** @@ -36,8 +36,8 @@ static inline uint32 GET_INST_SIZE(arm_core_t* core){ * * @return */ -static inline addr_t CHECK_READ_REG15_WA(arm_core_t* core, int Rn){ - return (Rn == 15)? ((core->Reg[15] & ~0x3) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; +static inline addr_t CHECK_READ_REG15_WA(arm_core_t* core, int Rn) { + return (Rn == 15)? ((core->Reg[15] & ~0x3) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; } /** @@ -48,8 +48,8 @@ static inline addr_t CHECK_READ_REG15_WA(arm_core_t* core, int Rn){ * * @return */ -static inline uint32 CHECK_READ_REG15(arm_core_t* core, int Rn){ - return (Rn == 15)? ((core->Reg[15] & ~0x1) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; +static inline u32 CHECK_READ_REG15(arm_core_t* core, int Rn) { + return (Rn == 15)? ((core->Reg[15] & ~0x1) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; } #endif diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h index 5541de9d1..bf69b2fd4 100644 --- a/src/core/arm/dyncom/arm_dyncom_thumb.h +++ b/src/core/arm/dyncom/arm_dyncom_thumb.h @@ -37,10 +37,10 @@ enum tdstate { t_uninitialized, }; -tdstate -thumb_translate(addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size); -static inline uint32 get_thumb_instr(uint32 instr, addr_t pc){ - uint32 tinstr; +tdstate thumb_translate(addr_t addr, u32 instr, u32* ainstr, u32* inst_size); + +static inline u32 get_thumb_instr(u32 instr, addr_t pc) { + u32 tinstr; if ((pc & 0x3) != 0) tinstr = instr >> 16; else diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index eec34143e..68ac2a0ce 100644 --- a/src/core/arm/interpreter/armsupp.cpp +++ b/src/core/arm/interpreter/armsupp.cpp @@ -418,22 +418,18 @@ ARMul_NegZero (ARMul_State * state, ARMword result) } } -/* Compute whether an addition of A and B, giving RESULT, overflowed. */ - -int -AddOverflow (ARMword a, ARMword b, ARMword result) +// Compute whether an addition of A and B, giving RESULT, overflowed. +bool AddOverflow(ARMword a, ARMword b, ARMword result) { - return ((NEG (a) && NEG (b) && POS (result)) - || (POS (a) && POS (b) && NEG (result))); + return ((NEG(a) && NEG(b) && POS(result)) || + (POS(a) && POS(b) && NEG(result))); } -/* Compute whether a subtraction of A and B, giving RESULT, overflowed. */ - -int -SubOverflow (ARMword a, ARMword b, ARMword result) +// Compute whether a subtraction of A and B, giving RESULT, overflowed. +bool SubOverflow(ARMword a, ARMword b, ARMword result) { - return ((NEG (a) && POS (b) && POS (result)) - || (POS (a) && NEG (b) && NEG (result))); + return ((NEG(a) && POS(b) && POS(result)) || + (POS(a) && NEG(b) && NEG(result))); } /* Assigns the C flag after an addition of a and b to give result. */ diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index 4592c5808..1b2cef451 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h @@ -70,6 +70,9 @@ #define DATACACHE 1 #define INSTCACHE 2 +#define POS(i) ( (~(i)) >> 31 ) +#define NEG(i) ( (i) >> 31 ) + #ifndef __STDC__ typedef char *VoidStar; #endif @@ -783,6 +786,8 @@ RUn %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",\ //#define PXA250 0x69052903 // 0x69052903; //PXA250 B1 from intel 278522-001.pdf +extern bool AddOverflow(ARMword, ARMword, ARMword); +extern bool SubOverflow(ARMword, ARMword, ARMword); extern void ARMul_UndefInstr(ARMul_State*, ARMword); extern void ARMul_FixCPSR(ARMul_State*, ARMword, ARMword); diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h index e1b286f0f..1dfcc635a 100644 --- a/src/core/arm/skyeye_common/armemu.h +++ b/src/core/arm/skyeye_common/armemu.h @@ -42,9 +42,6 @@ #define R15FBIT (1L << 26) #define R15IFBITS (3L << 26) -#define POS(i) ( (~(i)) >> 31 ) -#define NEG(i) ( (i) >> 31 ) - #ifdef MODET /* Thumb support. */ /* ??? This bit is actually in the low order bit of the PC in the hardware. It isn't clear if the simulator needs to model that or not. */ @@ -561,8 +558,7 @@ tdstate; /* Prototypes for exported functions. */ extern unsigned ARMul_NthReg (ARMword, unsigned); -extern int AddOverflow (ARMword, ARMword, ARMword); -extern int SubOverflow (ARMword, ARMword, ARMword); + /* Prototypes for exported functions. */ #ifdef __cplusplus extern "C" { diff --git a/src/core/arm/skyeye_common/skyeye_types.h b/src/core/arm/skyeye_common/skyeye_types.h index e7f022f19..fc7d8d922 100644 --- a/src/core/arm/skyeye_common/skyeye_types.h +++ b/src/core/arm/skyeye_common/skyeye_types.h @@ -22,34 +22,10 @@ * 12/16/2006 Michael.Kang <blackfin.kang@gmail.com> */ -#ifndef __SKYEYE_TYPES_H -#define __SKYEYE_TYPES_H +#pragma once -#include <stdint.h> - -/*default machine word length */ - -#ifndef __BEOS__ -/* To avoid the type conflict with the qemu */ -#ifndef QEMU -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint64_t uint64; - -typedef int8_t sint8; -typedef int16_t sint16; -typedef int32_t sint32; -typedef int64_t sint64; -#endif +#include <cstdint> typedef uint32_t address_t; -typedef uint32_t uinteger_t; -typedef int32_t integer_t; - typedef uint32_t physical_address_t; -typedef uint32_t generic_address_t; - -#endif - -#endif +typedef uint32_t generic_address_t; diff --git a/src/core/core.cpp b/src/core/core.cpp index 22213d647..8ac4481cc 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -53,10 +53,10 @@ int Init() { g_sys_core = new ARM_Interpreter(); switch (Settings::values.cpu_core) { - case CPU_FastInterpreter: + case CPU_Interpreter: g_app_core = new ARM_DynCom(); break; - case CPU_Interpreter: + case CPU_OldInterpreter: default: g_app_core = new ARM_Interpreter(); break; diff --git a/src/core/core.h b/src/core/core.h index 05dbe0ae5..ecd58a73a 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -13,7 +13,7 @@ namespace Core { enum CPUCore { CPU_Interpreter, - CPU_FastInterpreter + CPU_OldInterpreter, }; extern ARM_Interface* g_app_core; ///< ARM11 application core diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp index 0197f727d..c6e033fcd 100644 --- a/src/core/file_sys/disk_archive.cpp +++ b/src/core/file_sys/disk_archive.cpp @@ -6,6 +6,7 @@ #include "common/common_types.h" #include "common/file_util.h" +#include "common/make_unique.h" #include "core/file_sys/disk_archive.h" #include "core/settings.h" @@ -17,10 +18,10 @@ namespace FileSys { std::unique_ptr<FileBackend> DiskArchive::OpenFile(const Path& path, const Mode mode) const { LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex); - DiskFile* file = new DiskFile(this, path, mode); + auto file = Common::make_unique<DiskFile>(this, path, mode); if (!file->Open()) return nullptr; - return std::unique_ptr<FileBackend>(file); + return std::move(file); } bool DiskArchive::DeleteFile(const Path& path) const { @@ -66,10 +67,10 @@ bool DiskArchive::RenameDirectory(const Path& src_path, const Path& dest_path) c std::unique_ptr<DirectoryBackend> DiskArchive::OpenDirectory(const Path& path) const { LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str()); - DiskDirectory* directory = new DiskDirectory(this, path); + auto directory = Common::make_unique<DiskDirectory>(this, path); if (!directory->Open()) return nullptr; - return std::unique_ptr<DirectoryBackend>(directory); + return std::move(directory); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -100,7 +101,7 @@ bool DiskFile::Open() { // Open the file in binary mode, to avoid problems with CR/LF on Windows systems mode_string += "b"; - file = new FileUtil::IOFile(path, mode_string.c_str()); + file = Common::make_unique<FileUtil::IOFile>(path, mode_string.c_str()); return true; } diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h index f18d96f5a..3472f6874 100644 --- a/src/core/file_sys/disk_archive.h +++ b/src/core/file_sys/disk_archive.h @@ -56,10 +56,6 @@ public: DiskFile(); DiskFile(const DiskArchive* archive, const Path& path, const Mode mode); - ~DiskFile() override { - Close(); - } - bool Open() override; size_t Read(const u64 offset, const u32 length, u8* buffer) const override; size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; @@ -75,7 +71,7 @@ protected: const DiskArchive* archive; std::string path; Mode mode; - FileUtil::IOFile* file; + std::unique_ptr<FileUtil::IOFile> file; }; class DiskDirectory : public DirectoryBackend { diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 38705e3cd..736bbc36a 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -51,6 +51,17 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3 HLE::Reschedule(__func__); } break; + + case ArbitrationType::DecrementAndWaitIfLessThan: + { + s32 memory_value = Memory::Read32(address) - 1; + Memory::Write32(address, memory_value); + if (memory_value <= value) { + Kernel::WaitCurrentThread(WAITTYPE_ARB, handle, address); + HLE::Reschedule(__func__); + } + break; + } default: LOG_ERROR(Kernel, "unknown type=%d", type); diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 558068c79..3dfeffc9b 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -168,9 +168,9 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { ResultVal<bool> Mutex::WaitSynchronization() { bool wait = locked; if (locked) { + waiting_threads.push_back(GetCurrentThreadHandle()); Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle()); - } - else { + } else { // Lock the mutex when the first thread accesses it locked = true; MutexAcquireLock(this); diff --git a/src/core/hle/service/apt_a.cpp b/src/core/hle/service/apt_a.cpp index 4b0f761d9..37be4b027 100644 --- a/src/core/hle/service/apt_a.cpp +++ b/src/core/hle/service/apt_a.cpp @@ -25,12 +25,12 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00040040, nullptr, "Finalize?"}, {0x00050040, nullptr, "GetAppletManInfo?"}, {0x00060040, nullptr, "GetAppletInfo?"}, + {0x000D0080, APT_U::ReceiveParameter, "ReceiveParameter?"}, + {0x000E0080, APT_U::GlanceParameter, "GlanceParameter?"}, {0x003B0040, nullptr, "CancelLibraryApplet?"}, {0x00430040, nullptr, "NotifyToWait?"}, {0x004B00C2, nullptr, "AppletUtility?"}, {0x00550040, nullptr, "WriteInputToNsState?"}, - {0x000D0080, APT_U::ReceiveParameter, "ReceiveParameter" }, - {0x000E0080, APT_U::GlanceParameter, "GlanceParameter" }, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp index 03c01cf90..835620909 100644 --- a/src/core/hle/service/cfg/cfg_u.cpp +++ b/src/core/hle/service/cfg/cfg_u.cpp @@ -172,12 +172,12 @@ static void GetModelNintendo2DS(Service::Interface* self) { const Interface::FunctionInfo FunctionTable[] = { {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, {0x00020000, nullptr, "SecureInfoGetRegion"}, - {0x00030000, nullptr, "GenHashConsoleUnique"}, + {0x00030040, nullptr, "GenHashConsoleUnique"}, {0x00040000, nullptr, "GetRegionCanadaUSA"}, {0x00050000, GetSystemModel, "GetSystemModel"}, {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, - {0x00070040, nullptr, "unknown"}, - {0x00080080, nullptr, "unknown"}, + {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, + {0x00080080, nullptr, "GoThroughTable"}, {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, }; diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp index aef8cfbca..3a557efe1 100644 --- a/src/core/hle/service/csnd_snd.cpp +++ b/src/core/hle/service/csnd_snd.cpp @@ -14,16 +14,15 @@ namespace CSND_SND { const Interface::FunctionInfo FunctionTable[] = { {0x00010140, nullptr, "Initialize"}, {0x00020000, nullptr, "Shutdown"}, - {0x00030040, nullptr, "Unknown"}, - {0x00040080, nullptr, "Unknown"}, - {0x00050000, nullptr, "Unknown"}, - {0x00060000, nullptr, "Unknown"}, - {0x00070000, nullptr, "Unknown"}, - {0x00080040, nullptr, "Unknown"}, + {0x00030040, nullptr, "ExecuteType0Commands"}, + {0x00040080, nullptr, "ExecuteType1Commands"}, + {0x00050000, nullptr, "AcquireSoundChannels"}, + {0x00060000, nullptr, "ReleaseSoundChannels"}, + {0x00070000, nullptr, "AcquireCaptureDevice"}, + {0x00080040, nullptr, "ReleaseCaptureDevice"}, {0x00090082, nullptr, "FlushDCache"}, {0x000A0082, nullptr, "StoreDCache"}, {0x000B0082, nullptr, "InvalidateDCache"}, - {0x000C0000, nullptr, "Unknown"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 2cf4d118f..d4affdfbf 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -12,9 +12,23 @@ namespace DSP_DSP { -static u32 read_pipe_count; -static Handle semaphore_event; -static Handle interrupt_event; +static u32 read_pipe_count = 0; +static Handle semaphore_event = 0; +static Handle interrupt_event = 0; + +void SignalInterrupt() { + // TODO(bunnei): This is just a stub, it does not do anything other than signal to the emulated + // application that a DSP interrupt occurred, without specifying which one. Since we do not + // emulate the DSP yet (and how it works is largely unknown), this is a work around to get games + // that check the DSP interrupt signal event to run. We should figure out the different types of + // DSP interrupts, and trigger them at the appropriate times. + + if (interrupt_event == 0) { + LOG_WARNING(Service_DSP, "cannot signal interrupt until DSP event has been created!"); + return; + } + Kernel::SignalEvent(interrupt_event); +} /** * DSP_DSP::ConvertProcessAddressFromDspDram service function @@ -102,7 +116,7 @@ void RegisterInterruptEvents(Service::Interface* self) { void WriteReg0x10(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - Kernel::SignalEvent(interrupt_event); + SignalInterrupt(); cmd_buff[1] = 0; // No error diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h index 0b8b64600..fa13bfb7c 100644 --- a/src/core/hle/service/dsp_dsp.h +++ b/src/core/hle/service/dsp_dsp.h @@ -20,4 +20,7 @@ public: } }; +/// Signals that a DSP interrupt has occurred to userland code +void SignalInterrupt(); + } // namespace diff --git a/src/core/hle/service/ir_rst.cpp b/src/core/hle/service/ir_rst.cpp index b388afb15..d49bd5335 100644 --- a/src/core/hle/service/ir_rst.cpp +++ b/src/core/hle/service/ir_rst.cpp @@ -15,12 +15,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00010000, nullptr, "GetHandles"}, {0x00020080, nullptr, "Initialize"}, {0x00030000, nullptr, "Shutdown"}, - {0x00040000, nullptr, "Unknown"}, - {0x00050000, nullptr, "Unknown"}, - {0x00060000, nullptr, "Unknown"}, - {0x00070080, nullptr, "Unknown"}, - {0x00080000, nullptr, "Unknown"}, - {0x00090000, nullptr, "Unknown"}, + {0x00090000, nullptr, "WriteToTwoFields"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp index 9c9e90a40..7d6e2e8e8 100644 --- a/src/core/hle/service/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro.cpp @@ -13,10 +13,14 @@ namespace LDR_RO { const Interface::FunctionInfo FunctionTable[] = { {0x000100C2, nullptr, "Initialize"}, - {0x00020082, nullptr, "CRR_Load"}, - {0x00030042, nullptr, "CRR_Unload"}, - {0x000402C2, nullptr, "CRO_LoadAndFix"}, - {0x000500C2, nullptr, "CRO_ApplyRelocationPatchesAndLink"} + {0x00020082, nullptr, "LoadCRR"}, + {0x00030042, nullptr, "UnloadCCR"}, + {0x000402C2, nullptr, "LoadExeCRO"}, + {0x000500C2, nullptr, "LoadCROSymbols"}, + {0x00060042, nullptr, "CRO_Load?"}, + {0x00070042, nullptr, "LoadCROSymbols"}, + {0x00080042, nullptr, "Shutdown"}, + {0x000902C2, nullptr, "LoadExeCRO_New?"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/ndm_u.cpp b/src/core/hle/service/ndm_u.cpp index 233b14f6d..0f03de6ae 100644 --- a/src/core/hle/service/ndm_u.cpp +++ b/src/core/hle/service/ndm_u.cpp @@ -11,10 +11,13 @@ namespace NDM_U { const Interface::FunctionInfo FunctionTable[] = { - {0x00060040, nullptr, "SuspendDaemons"}, - {0x00080040, nullptr, "DisableWifiUsage"}, - {0x00090000, nullptr, "EnableWifiUsage"}, - {0x00140040, nullptr, "OverrideDefaultDaemons"}, + {0x00010042, nullptr, "EnterExclusiveState"}, + {0x00020002, nullptr, "LeaveExclusiveState"}, + {0x00030000, nullptr, "QueryExclusiveMode"}, + {0x00060040, nullptr, "SuspendDaemons"}, + {0x00080040, nullptr, "DisableWifiUsage"}, + {0x00090000, nullptr, "EnableWifiUsage"}, + {0x00140040, nullptr, "OverrideDefaultDaemons"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 0f3cc2aa8..c5233e687 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -37,6 +37,7 @@ #include "core/hle/service/soc_u.h" #include "core/hle/service/srv.h" #include "core/hle/service/ssl_c.h" +#include "core/hle/service/y2r_u.h" namespace Service { @@ -122,6 +123,7 @@ void Init() { g_manager->AddService(new PTM_U::Interface); g_manager->AddService(new SOC_U::Interface); g_manager->AddService(new SSL_C::Interface); + g_manager->AddService(new Y2R_U::Interface); LOG_DEBUG(Service, "initialized OK"); } diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index 8e7abcf9c..f502c6afe 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp @@ -308,11 +308,11 @@ static void Socket(Service::Interface* self) { u32 socket_handle = static_cast<u32>(::socket(domain, type, protocol)); - if (socket_handle != SOCKET_ERROR_VALUE) + if ((s32)socket_handle != SOCKET_ERROR_VALUE) open_sockets[socket_handle] = { socket_handle, true }; int result = 0; - if (socket_handle == SOCKET_ERROR_VALUE) + if ((s32)socket_handle == SOCKET_ERROR_VALUE) result = TranslateError(GET_ERRNO); cmd_buffer[1] = result; @@ -436,11 +436,11 @@ static void Accept(Service::Interface* self) { socklen_t addr_len = sizeof(addr); u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len)); - if (ret != SOCKET_ERROR_VALUE) + if ((s32)ret != SOCKET_ERROR_VALUE) open_sockets[ret] = { ret, true }; int result = 0; - if (ret == SOCKET_ERROR_VALUE) { + if ((s32)ret == SOCKET_ERROR_VALUE) { result = TranslateError(GET_ERRNO); } else { CTRSockAddr ctr_addr = CTRSockAddr::FromPlatform(addr); diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 25fab1a4f..912b52adf 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -52,13 +52,15 @@ static void GetServiceHandle(Service::Interface* self) { } const Interface::FunctionInfo FunctionTable[] = { - {0x00010002, Initialize, "Initialize"}, - {0x00020000, GetProcSemaphore, "GetProcSemaphore"}, - {0x00030100, nullptr, "RegisterService"}, - {0x000400C0, nullptr, "UnregisterService"}, - {0x00050100, GetServiceHandle, "GetServiceHandle"}, - {0x000B0000, nullptr, "ReceiveNotification"}, - {0x000C0080, nullptr, "PublishToSubscriber"} + {0x00010002, Initialize, "Initialize"}, + {0x00020000, GetProcSemaphore, "GetProcSemaphore"}, + {0x00030100, nullptr, "RegisterService"}, + {0x000400C0, nullptr, "UnregisterService"}, + {0x00050100, GetServiceHandle, "GetServiceHandle"}, + {0x000600C2, nullptr, "RegisterHandle"}, + {0x00090040, nullptr, "Subscribe"}, + {0x000B0000, nullptr, "ReceiveNotification"}, + {0x000C0080, nullptr, "PublishToSubscriber"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp new file mode 100644 index 000000000..f9e3619dd --- /dev/null +++ b/src/core/hle/service/y2r_u.cpp @@ -0,0 +1,45 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/log.h" +#include "core/hle/hle.h" +#include "core/hle/kernel/event.h" +#include "core/hle/service/y2r_u.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Namespace Y2R_U + +namespace Y2R_U { + +const Interface::FunctionInfo FunctionTable[] = { + {0x00010040, nullptr, "SetInputFormat"}, + {0x00030040, nullptr, "SetOutputFormat"}, + {0x00050040, nullptr, "SetRotation"}, + {0x00070040, nullptr, "SetBlockAlignment"}, + {0x000D0040, nullptr, "SetTransferEndInterrupt"}, + {0x000F0000, nullptr, "GetTransferEndEvent"}, + {0x00100102, nullptr, "SetSendingY"}, + {0x00110102, nullptr, "SetSendingU"}, + {0x00120102, nullptr, "SetSendingV"}, + {0x00180102, nullptr, "SetReceiving"}, + {0x001A0040, nullptr, "SetInputLineWidth"}, + {0x001C0040, nullptr, "SetInputLines"}, + {0x00200040, nullptr, "SetStandardCoefficient"}, + {0x00220040, nullptr, "SetAlpha"}, + {0x00260000, nullptr, "StartConversion"}, + {0x00270000, nullptr, "StopConversion"}, + {0x00280000, nullptr, "IsBusyConversion"}, + {0x002A0000, nullptr, "PingProcess"}, + {0x002B0000, nullptr, "DriverInitialize"}, + {0x002C0000, nullptr, "DriverFinalize"} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Interface class + +Interface::Interface() { + Register(FunctionTable, ARRAY_SIZE(FunctionTable)); +} + +} // namespace diff --git a/src/core/hle/service/y2r_u.h b/src/core/hle/service/y2r_u.h new file mode 100644 index 000000000..171aecfd1 --- /dev/null +++ b/src/core/hle/service/y2r_u.h @@ -0,0 +1,23 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Namespace Y2R_U + +namespace Y2R_U { + +class Interface : public Service::Interface { +public: + Interface(); + + std::string GetPortName() const override { + return "y2r:u"; + } +}; + +} // namespace diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 0ff6c6cde..e346e0ad6 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -10,6 +10,7 @@ #include "core/hle/hle.h" #include "core/hle/service/gsp_gpu.h" +#include "core/hle/service/dsp_dsp.h" #include "core/hw/gpu.h" @@ -214,13 +215,18 @@ void Update() { // - If frameskip == 0 (disabled), always swap buffers // - If frameskip == 1, swap buffers every other frame (starting from the first frame) // - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame) - if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && last_skip_frame != g_skip_frame) || Settings::values.frame_skip == 0) { VideoCore::g_renderer->SwapBuffers(); } + // Signal to GSP that GPU interrupt has occurred GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); + + // TODO(bunnei): Fake a DSP interrupt on each frame. This does not belong here, but + // until we can emulate DSP interrupts, this is probably the only reasonable place to do + // this. Certain games expect this to be periodically signaled. + DSP_DSP::SignalInterrupt(); } } } diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 87580cb2a..45cf425df 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -45,6 +45,8 @@ FileType IdentifyFile(const std::string &filename) { return FileType::CCI; } else if (extension == ".bin") { return FileType::BIN; + } else if (extension == ".3ds") { + return FileType::CCI; } else if (extension == ".3dsx") { return FileType::THREEDSX; } |