summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp19
-rw-r--r--src/core/hle/service/err_f.cpp165
-rw-r--r--src/core/hw/gpu.cpp66
-rw-r--r--src/core/mem_map_funcs.cpp18
4 files changed, 216 insertions, 52 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index b691ffbc3..3b508f617 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -4422,12 +4422,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
unsigned int value = Memory::Read32(addr);
- if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
- else {
- value = ROTATE_RIGHT_32(value,(8*(addr&0x3)));
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
- }
+ cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
if (BITS(inst_cream->inst, 12, 15) == 15) {
// For armv5t, should enter thumb when bits[0] is non-zero.
@@ -4450,12 +4445,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
unsigned int value = Memory::Read32(addr);
- if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
- else {
- value = ROTATE_RIGHT_32(value,(8*(addr&0x3)));
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
- }
+ cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
if (BITS(inst_cream->inst, 12, 15) == 15) {
// For armv5t, should enter thumb when bits[0] is non-zero.
@@ -4699,11 +4689,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
unsigned int value = Memory::Read32(addr);
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
- if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
- else
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ROTATE_RIGHT_32(value,(8*(addr&0x3))) ;
-
if (BITS(inst_cream->inst, 12, 15) == 15) {
INC_PC(sizeof(ldst_inst));
goto DISPATCH;
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 8d765acb5..58c5acd1e 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -10,8 +10,171 @@
namespace ERR_F {
+enum {
+ ErrSpecifier0 = 0,
+ ErrSpecifier1 = 1,
+ ErrSpecifier3 = 3,
+ ErrSpecifier4 = 4,
+};
+
+// This is used instead of ResultCode from result.h
+// because we can't have non-trivial data members in unions.
+union RSL {
+ u32 raw;
+
+ BitField<0, 10, u32> description;
+ BitField<10, 8, u32> module;
+ BitField<21, 6, u32> summary;
+ BitField<27, 5, u32> level;
+};
+
+union ErrInfo {
+ u8 specifier;
+
+ struct {
+ u8 specifier; // 0x0
+ u8 rev_high; // 0x1
+ u16 rev_low; // 0x2
+ RSL result_code; // 0x4
+ u32 address; // 0x8
+ INSERT_PADDING_BYTES(4); // 0xC
+ u32 pid_low; // 0x10
+ u32 pid_high; // 0x14
+ u32 aid_low; // 0x18
+ u32 aid_high; // 0x1C
+ } errtype1;
+
+ struct {
+ u8 specifier; // 0x0
+ u8 rev_high; // 0x1
+ u16 rev_low; // 0x2
+ INSERT_PADDING_BYTES(0xC); // 0x4
+ u32 pid_low; // 0x10
+ u32 pid_high; // 0x14
+ u32 aid_low; // 0x18
+ u32 aid_high; // 0x1C
+ u8 error_type; // 0x20
+ INSERT_PADDING_BYTES(3); // 0x21
+ u32 fault_status_reg; // 0x24
+ u32 fault_addr; // 0x28
+ u32 fpexc; // 0x2C
+ u32 finst; // 0x30
+ u32 finst2; // 0x34
+ INSERT_PADDING_BYTES(0x34); // 0x38
+ u32 sp; // 0x6C
+ u32 pc; // 0x70
+ u32 lr; // 0x74
+ u32 cpsr; // 0x78
+ } errtype3;
+
+ struct {
+ u8 specifier; // 0x0
+ u8 rev_high; // 0x1
+ u16 rev_low; // 0x2
+ RSL result_code; // 0x4
+ INSERT_PADDING_BYTES(8); // 0x8
+ u32 pid_low; // 0x10
+ u32 pid_high; // 0x14
+ u32 aid_low; // 0x18
+ u32 aid_high; // 0x1C
+ char debug_string1[0x2E]; // 0x20
+ char debug_string2[0x2E]; // 0x4E
+ } errtype4;
+};
+
+enum {
+ PrefetchAbort = 0,
+ DataAbort = 1,
+ UndefInstr = 2,
+ VectorFP = 3
+};
+
+static std::string GetErrInfo3Type(u8 type_code) {
+ switch (type_code) {
+ case PrefetchAbort: return "Prefetch Abort";
+ case DataAbort: return "Data Abort";
+ case UndefInstr: return "Undefined Instruction";
+ case VectorFP: return "Vector Floating Point";
+ default: return "unknown";
+ }
+}
+
+static void ThrowFatalError(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ LOG_CRITICAL(Service_ERR, "Fatal error!");
+ const ErrInfo* errinfo = reinterpret_cast<ErrInfo*>(&cmd_buff[1]);
+
+ switch (errinfo->specifier) {
+ case ErrSpecifier0:
+ case ErrSpecifier1:
+ {
+ const auto& errtype = errinfo->errtype1;
+ LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
+ LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
+ LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
+ LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address);
+
+ LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
+ LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
+ LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
+ LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
+ LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
+ break;
+ }
+
+ case ErrSpecifier3:
+ {
+ const auto& errtype = errinfo->errtype3;
+ LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
+ LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
+ LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
+ LOG_CRITICAL(Service_ERR, "TYPE: %s", GetErrInfo3Type(errtype.error_type).c_str());
+
+ LOG_CRITICAL(Service_ERR, "PC: 0x%08X", errtype.pc);
+ LOG_CRITICAL(Service_ERR, "LR: 0x%08X", errtype.lr);
+ LOG_CRITICAL(Service_ERR, "SP: 0x%08X", errtype.sp);
+ LOG_CRITICAL(Service_ERR, "CPSR: 0x%08X", errtype.cpsr);
+
+ switch (errtype.error_type) {
+ case PrefetchAbort:
+ case DataAbort:
+ LOG_CRITICAL(Service_ERR, "Fault Address: 0x%08X", errtype.fault_addr);
+ LOG_CRITICAL(Service_ERR, "Fault Status Register: 0x%08X", errtype.fault_status_reg);
+ break;
+ case VectorFP:
+ LOG_CRITICAL(Service_ERR, "FPEXC: 0x%08X", errtype.fpexc);
+ LOG_CRITICAL(Service_ERR, "FINST: 0x%08X", errtype.finst);
+ LOG_CRITICAL(Service_ERR, "FINST2: 0x%08X", errtype.finst2);
+ break;
+ }
+ break;
+ }
+
+ case ErrSpecifier4:
+ {
+ const auto& errtype = errinfo->errtype4;
+ LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
+ LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
+ LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
+
+ LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
+ LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
+ LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
+ LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
+ LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
+
+ LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1);
+ LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2);
+ break;
+ }
+ }
+
+ cmd_buff[1] = 0; // No error
+}
+
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010800, nullptr, "ThrowFatalError"}
+ {0x00010800, ThrowFatalError, "ThrowFatalError"}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index bd7d92cd1..e6022d69f 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -19,6 +19,7 @@
#include "video_core/command_processor.h"
#include "video_core/video_core.h"
+#include <video_core/color.h>
namespace GPU {
@@ -132,12 +133,31 @@ inline void Write(u32 addr, const T data) {
switch (config.input_format) {
case Regs::PixelFormat::RGBA8:
{
- // TODO: Most likely got the component order messed up.
u8* srcptr = source_pointer + (x * pixel_skip + y * config.input_width) * 4;
- source_color.r = srcptr[0]; // blue
- source_color.g = srcptr[1]; // green
- source_color.b = srcptr[2]; // red
- source_color.a = srcptr[3]; // alpha
+ source_color.r = srcptr[3]; // red
+ source_color.g = srcptr[2]; // green
+ source_color.b = srcptr[1]; // blue
+ source_color.a = srcptr[0]; // alpha
+ break;
+ }
+
+ case Regs::PixelFormat::RGB5A1:
+ {
+ u16 srcval = *(u16*)(source_pointer + x * 4 * pixel_skip + y * config.input_width * 4 * pixel_skip);
+ source_color.r = Color::Convert5To8((srcval >> 11) & 0x1F); // red
+ source_color.g = Color::Convert5To8((srcval >> 6) & 0x1F); // green
+ source_color.b = Color::Convert5To8((srcval >> 1) & 0x1F); // blue
+ source_color.a = Color::Convert1To8(srcval & 0x1); // alpha
+ break;
+ }
+
+ case Regs::PixelFormat::RGBA4:
+ {
+ u16 srcval = *(u16*)(source_pointer + x * 4 * pixel_skip + y * config.input_width * 4 * pixel_skip);
+ source_color.r = Color::Convert4To8((srcval >> 12) & 0xF); // red
+ source_color.g = Color::Convert4To8((srcval >> 8) & 0xF); // green
+ source_color.b = Color::Convert4To8((srcval >> 4) & 0xF); // blue
+ source_color.a = Color::Convert4To8( srcval & 0xF); // alpha
break;
}
@@ -147,24 +167,38 @@ inline void Write(u32 addr, const T data) {
}
switch (config.output_format) {
- /*case Regs::PixelFormat::RGBA8:
+ case Regs::PixelFormat::RGBA8:
{
- // TODO: Untested
- u8* dstptr = (u32*)(dest_pointer + x * 4 + y * config.output_width * 4);
- dstptr[0] = source_color.r;
- dstptr[1] = source_color.g;
- dstptr[2] = source_color.b;
- dstptr[3] = source_color.a;
+ u8* dstptr = dest_pointer + (x * pixel_skip + y * config.output_width) * 4;
+ dstptr[3] = source_color.r;
+ dstptr[2] = source_color.g;
+ dstptr[1] = source_color.b;
+ dstptr[0] = source_color.a;
break;
- }*/
+ }
case Regs::PixelFormat::RGB8:
{
- // TODO: Most likely got the component order messed up.
u8* dstptr = dest_pointer + (x + y * output_width) * 3;
- dstptr[0] = source_color.r; // blue
+ dstptr[2] = source_color.r; // red
dstptr[1] = source_color.g; // green
- dstptr[2] = source_color.b; // red
+ dstptr[0] = source_color.b; // blue
+ break;
+ }
+
+ case Regs::PixelFormat::RGB5A1:
+ {
+ u16* dstptr = (u16*)(dest_pointer + x * 2 + y * config.output_width * 2);
+ *dstptr = ((source_color.r >> 3) << 11) | ((source_color.g >> 3) << 6)
+ | ((source_color.b >> 3) << 1) | ( source_color.a >> 7);
+ break;
+ }
+
+ case Regs::PixelFormat::RGBA4:
+ {
+ u16* dstptr = (u16*)(dest_pointer + x * 2 + y * config.output_width * 2);
+ *dstptr = ((source_color.r >> 4) << 12) | ((source_color.g >> 4) << 8)
+ | ((source_color.b >> 4) << 4) | ( source_color.a >> 4);
break;
}
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index 4f93c0e64..48f61db4e 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -236,30 +236,12 @@ u8 Read8(const VAddr addr) {
u16 Read16(const VAddr addr) {
u16_le data = 0;
Read<u16_le>(data, addr);
-
- // Check for 16-bit unaligned memory reads...
- if (addr & 1) {
- // TODO(bunnei): Implement 16-bit unaligned memory reads
- LOG_ERROR(HW_Memory, "16-bit unaligned memory reads are not implemented!");
- }
-
return (u16)data;
}
u32 Read32(const VAddr addr) {
u32_le data = 0;
Read<u32_le>(data, addr);
-
- // Check for 32-bit unaligned memory reads...
- if (addr & 3) {
- // ARM allows for unaligned memory reads, however older ARM architectures read out memory
- // from unaligned addresses in a shifted way. Our ARM CPU core (SkyEye) corrects for this,
- // so therefore expects the memory to be read out in this manner.
- // TODO(bunnei): Determine if this is necessary - perhaps it is OK to remove this from both
- // SkyEye and here?
- int shift = (addr & 3) * 8;
- data = (data << shift) | (data >> (32 - shift));
- }
return (u32)data;
}