Minor nitpicks and smaller perf improvements (barely noticeable)

This commit is contained in:
SimoneN64
2024-10-14 23:25:09 +02:00
parent d2c37d373e
commit 57fd6a9af8
59 changed files with 1547 additions and 1528 deletions

View File

@@ -23,7 +23,7 @@ void Core::LoadROM(const std::string &rom_) {
std::string archive_types[] = {".zip", ".7z", ".rar", ".tar"};
auto extension = fs::path(rom).extension().string();
bool isArchive = std::any_of(std::begin(archive_types), std::end(archive_types),
const bool isArchive = std::ranges::any_of(archive_types,
[&extension](const auto &e) { return e == extension; });
cpu->GetMem().LoadROM(isArchive, rom);

View File

@@ -3,29 +3,29 @@
namespace n64 {
void GameDB::match(Mem &mem) {
ROM &rom = mem.rom;
for (const auto &i : gamedb) {
bool matches_code = i.code == rom.code;
const ROM &rom = mem.rom;
for (const auto &[code, regions, saveType, name] : gamedb) {
const bool matches_code = code == rom.code;
bool matches_region = false;
for (int j = 0; j < i.regions.size() && !matches_region; j++) {
if (i.regions[j] == rom.header.countryCode[0]) {
for (int j = 0; j < regions.size() && !matches_region; j++) {
if (regions[j] == rom.header.countryCode[0]) {
matches_region = true;
}
}
if (matches_code) {
if (matches_region) {
mem.saveType = i.saveType;
mem.rom.gameNameDB = i.name;
mem.saveType = saveType;
mem.rom.gameNameDB = name;
return;
}
Util::warn(
"Matched code for {}, but not region! Game supposedly exists in regions [{}] but this image has region {}",
i.name, i.regions, rom.header.countryCode[0]);
mem.saveType = i.saveType;
mem.rom.gameNameDB = i.name;
name, regions, rom.header.countryCode[0]);
mem.saveType = saveType;
mem.rom.gameNameDB = name;
return;
}
}

View File

@@ -2,16 +2,16 @@
#include <core/Mem.hpp>
#include <core/registers/Registers.hpp>
void Scheduler::EnqueueRelative(u64 t, const EventType type) { EnqueueAbsolute(t + ticks, type); }
void Scheduler::EnqueueRelative(const u64 t, const EventType type) { EnqueueAbsolute(t + ticks, type); }
void Scheduler::EnqueueAbsolute(u64 t, const EventType type) { events.push({t, type}); }
void Scheduler::EnqueueAbsolute(const u64 t, const EventType type) { events.push({t, type}); }
u64 Scheduler::Remove(EventType type) {
for (auto &e : events) {
if (e.type == type) {
u64 ret = e.time - ticks;
e.type = NONE;
e.time = ticks;
u64 Scheduler::Remove(const EventType eventType) const {
for (auto &[time, type] : events) {
if (type == eventType) {
const u64 ret = time - ticks;
type = NONE;
time = ticks;
return ret;
}
}
@@ -19,14 +19,14 @@ u64 Scheduler::Remove(EventType type) {
return 0;
}
void Scheduler::Tick(u64 t, n64::Mem &mem) {
void Scheduler::Tick(const u64 t, n64::Mem &mem) {
ticks += t;
n64::MI &mi = mem.mmio.mi;
n64::SI &si = mem.mmio.si;
n64::PI &pi = mem.mmio.pi;
while (ticks >= events.top().time) {
switch (auto type = events.top().type) {
switch (const auto type = events.top().type) {
case SI_DMA:
si.DMA();
break;

View File

@@ -1,5 +1,4 @@
#pragma once
#include <array>
#include <functional>
#include <log.hpp>
#include <queue>
@@ -25,13 +24,12 @@ struct Event {
struct IterableEvents {
std::priority_queue<Event, std::vector<Event>, std::greater<>> events;
public:
explicit IterableEvents() = default;
[[nodiscard]] auto top() const { return events.top(); }
auto pop() { events.pop(); }
[[nodiscard]] auto begin() const { return (Event *)(&events.top()); }
[[nodiscard]] auto begin() const { return const_cast<Event *>(&events.top()); }
[[nodiscard]] auto end() const { return begin() + events.size(); }
auto push(Event e) { events.push(e); }
auto push(const Event e) { events.push(e); }
};
struct Scheduler {
@@ -39,10 +37,10 @@ struct Scheduler {
void EnqueueRelative(u64, EventType);
void EnqueueAbsolute(u64, EventType);
u64 Remove(EventType);
[[nodiscard]] u64 Remove(EventType) const;
void Tick(u64 t, n64::Mem &);
IterableEvents events;
IterableEvents events{};
u64 ticks = 0;
u8 index = 0;
};

View File

@@ -8,12 +8,12 @@ struct BaseCPU {
virtual ~BaseCPU() = default;
virtual int Step() = 0;
virtual void Reset() = 0;
virtual bool ShouldServiceInterrupt() = 0;
[[nodiscard]] virtual bool ShouldServiceInterrupt() const = 0;
virtual void CheckCompareInterrupt() = 0;
virtual std::vector<u8> Serialize() = 0;
virtual void Deserialize(const std::vector<u8> &) = 0;
virtual Mem &GetMem() = 0;
virtual Registers &GetRegs() = 0;
virtual Disassembler::DisassemblyResult Disassemble(u32, u32) const = 0;
[[nodiscard]] virtual Disassembler::DisassemblyResult Disassemble(u32, u32) const = 0;
};
} // namespace n64

View File

@@ -1,9 +1,9 @@
#include <Disassembler.hpp>
Disassembler::DisassemblyResult Disassembler::DisassembleSimple(u32 address, u32 instruction) {
Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 address, const u32 instruction) const {
cs_insn *insn;
auto bytes = Util::IntegralToBuffer(instruction);
auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
const auto bytes = Util::IntegralToBuffer(instruction);
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
if (count <= 0)
return {};
@@ -15,10 +15,10 @@ Disassembler::DisassemblyResult Disassembler::DisassembleSimple(u32 address, u32
return result;
}
Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(u32 address, u32 instruction) {
Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(const u32 address, const u32 instruction) const {
cs_insn *insn;
auto bytes = Util::IntegralToBuffer(instruction);
auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
const auto bytes = Util::IntegralToBuffer(instruction);
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
if (count <= 0)
return {};
@@ -27,10 +27,10 @@ Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(u32 address, u
result.address = insn[0].address;
result.mnemonic = insn[0].mnemonic;
result.full += result.address + ":\t";
result.full += fmt::format("0x{:016X}", result.address) + ":\t";
result.full += result.mnemonic + "\t";
cs_detail *details = insn[0].detail;
const cs_detail *details = insn[0].detail;
auto formatOperand = [&](const cs_mips_op &operand) {
switch (operand.type) {
case MIPS_OP_IMM:
@@ -39,6 +39,8 @@ Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(u32 address, u
return fmt::format("{}(0x{:X})", cs_reg_name(handle, operand.mem.base), operand.mem.disp);
case MIPS_OP_REG:
return fmt::format("{}", cs_reg_name(handle, operand.reg));
default:
return std::string{""};
}
};

View File

@@ -25,8 +25,8 @@ struct Disassembler {
~Disassembler() { cs_close(&handle); }
private:
DisassemblyResult DisassembleDetailed(u32 address, u32 instruction);
DisassemblyResult DisassembleSimple(u32 address, u32 instruction);
DisassemblyResult DisassembleDetailed(u32 address, u32 instruction) const;
DisassemblyResult DisassembleSimple(u32 address, u32 instruction) const;
explicit Disassembler(const bool rsp) : rsp(rsp) {
if (cs_open(CS_ARCH_MIPS, static_cast<cs_mode>((rsp ? CS_MODE_32 : CS_MODE_64) | CS_MODE_BIG_ENDIAN), &handle) !=

View File

@@ -3,11 +3,11 @@
namespace n64 {
Interpreter::Interpreter(ParallelRDP &parallel) : mem(regs, parallel) {}
bool Interpreter::ShouldServiceInterrupt() {
bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
bool interrupts_enabled = regs.cop0.status.ie == 1;
bool currently_handling_exception = regs.cop0.status.exl == 1;
bool currently_handling_error = regs.cop0.status.erl == 1;
bool Interpreter::ShouldServiceInterrupt() const {
const bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
const bool interrupts_enabled = regs.cop0.status.ie == 1;
const bool currently_handling_exception = regs.cop0.status.exl == 1;
const bool currently_handling_error = regs.cop0.status.erl == 1;
return interrupts_pending && interrupts_enabled && !currently_handling_exception && !currently_handling_error;
}
@@ -15,13 +15,13 @@ bool Interpreter::ShouldServiceInterrupt() {
void Interpreter::CheckCompareInterrupt() {
regs.cop0.count++;
regs.cop0.count &= 0x1FFFFFFFF;
if (regs.cop0.count == (u64)regs.cop0.compare << 1) {
if (regs.cop0.count == static_cast<u64>(regs.cop0.compare) << 1) {
regs.cop0.cause.ip7 = 1;
mem.mmio.mi.UpdateInterrupt();
}
}
Disassembler::DisassemblyResult Interpreter::Disassemble(u32 address, u32 instruction) const {
Disassembler::DisassemblyResult Interpreter::Disassemble(const u32 address, const u32 instruction) const {
return Disassembler::instance().Disassemble(address, instruction);
}
@@ -40,11 +40,11 @@ int Interpreter::Step() {
u32 paddr = 0;
if (!regs.cop0.MapVAddr(Cop0::LOAD, regs.pc, paddr)) {
regs.cop0.HandleTLBException(regs.pc);
regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.pc);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.pc);
return 1;
}
u32 instruction = mem.Read<u32>(regs, paddr);
const u32 instruction = mem.Read<u32>(regs, paddr);
if (ShouldServiceInterrupt()) {
regs.cop0.FireException(ExceptionCode::Interrupt, 0, regs.pc);

View File

@@ -20,7 +20,7 @@ struct Interpreter : BaseCPU {
Mem &GetMem() override { return mem; }
Registers &GetRegs() override { return regs; }
Disassembler::DisassemblyResult Disassemble(u32, u32) const override;
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32, u32) const override;
private:
Registers regs;
@@ -29,7 +29,7 @@ private:
friend struct Cop1;
#define check_address_error(mask, vaddr) \
(((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
bool ShouldServiceInterrupt() override;
bool ShouldServiceInterrupt() const override;
void CheckCompareInterrupt() override;
std::vector<u8> Serialize() override;
void Deserialize(const std::vector<u8> &) override;
@@ -118,7 +118,7 @@ private:
void srav(u32);
void srl(u32);
void srlv(u32);
void trap(bool);
void trap(bool) const;
void or_(u32);
void ori(u32);
void xor_(u32);

View File

@@ -4,11 +4,11 @@
namespace n64 {
JIT::JIT(ParallelRDP &parallel) : mem(regs, parallel) {}
bool JIT::ShouldServiceInterrupt() {
bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
bool interrupts_enabled = regs.cop0.status.ie == 1;
bool currently_handling_exception = regs.cop0.status.exl == 1;
bool currently_handling_error = regs.cop0.status.erl == 1;
bool JIT::ShouldServiceInterrupt() const {
const bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
const bool interrupts_enabled = regs.cop0.status.ie == 1;
const bool currently_handling_exception = regs.cop0.status.exl == 1;
const bool currently_handling_error = regs.cop0.status.erl == 1;
return interrupts_pending && interrupts_enabled && !currently_handling_exception && !currently_handling_error;
}
@@ -16,7 +16,7 @@ bool JIT::ShouldServiceInterrupt() {
void JIT::CheckCompareInterrupt() {
regs.cop0.count++;
regs.cop0.count &= 0x1FFFFFFFF;
if (regs.cop0.count == (u64)regs.cop0.compare << 1) {
if (regs.cop0.count == static_cast<u64>(regs.cop0.compare) << 1) {
regs.cop0.cause.ip7 = 1;
mem.mmio.mi.UpdateInterrupt();
}
@@ -41,10 +41,10 @@ int JIT::Step() {
u32 paddr = 0;
if (!regs.cop0.MapVAddr(Cop0::LOAD, pc, paddr)) {
/*regs.cop0.HandleTLBException(pc);
regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, pc);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, pc);
return 1;*/
Util::panic("[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address!",
static_cast<int>(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)));
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)));
}
instruction = mem.Read<u32>(regs, paddr);

View File

@@ -20,7 +20,7 @@ struct JIT : BaseCPU {
Registers &GetRegs() override { return regs; }
Disassembler::DisassemblyResult Disassemble(u32, u32) const override { return {}; }
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32, u32) const override { return {}; }
private:
Registers regs;
@@ -29,7 +29,7 @@ private:
friend struct Cop1;
#define check_address_error(mask, vaddr) \
(((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
bool ShouldServiceInterrupt() override;
bool ShouldServiceInterrupt() const override;
void CheckCompareInterrupt() override;
std::vector<u8> Serialize() override;
void Deserialize(const std::vector<u8> &) override;

View File

@@ -36,7 +36,7 @@ u32 MMIO::Read(u32 addr) {
}
}
void MMIO::Write(u32 addr, u32 val) {
void MMIO::Write(const u32 addr, const u32 val) {
switch (addr) {
case RSP_REGION:
rsp.Write(addr, val);
@@ -82,14 +82,30 @@ std::vector<u8> MMIO::Serialize() {
index += sizeof(DPC);
memcpy(res.data() + index, rdp.cmd_buf, 0xFFFFF);
index += 0xFFFFF;
std::copy(rdp.rdram.begin(), rdp.rdram.end(), res.begin() + index);
std::ranges::copy(rdp.rdram, res.begin() + index);
index += RDRAM_SIZE;
memcpy(res.data() + index, &mi, sizeof(MI));
index += sizeof(MI);
memcpy(res.data() + index, &vi, sizeof(VI));
index += sizeof(VI);
memcpy(res.data() + index, &ai, sizeof(AI));
index += sizeof(AI);
memcpy(res.data() + index, &ai.dmaEnable, sizeof(ai.dmaEnable));
index += sizeof(ai.dmaEnable);
memcpy(res.data() + index, &ai.dacRate, sizeof(ai.dacRate));
index += sizeof(ai.dacRate);
memcpy(res.data() + index, &ai.bitrate, sizeof(ai.bitrate));
index += sizeof(ai.bitrate);
memcpy(res.data() + index, &ai.dmaCount, sizeof(ai.dmaCount));
index += sizeof(ai.dmaCount);
memcpy(res.data() + index, &ai.dmaLen, sizeof(ai.dmaLen));
index += sizeof(ai.dmaLen);
memcpy(res.data() + index, &ai.dmaAddr, sizeof(ai.dmaAddr));
index += sizeof(ai.dmaAddr);
memcpy(res.data() + index, &ai.dmaAddrCarry, sizeof(ai.dmaAddrCarry));
index += sizeof(ai.dmaAddrCarry);
memcpy(res.data() + index, &ai.cycles, sizeof(ai.cycles));
index += sizeof(ai.cycles);
memcpy(res.data() + index, &ai.dac, sizeof(ai.dac));
index += sizeof(ai.dac);
memcpy(res.data() + index, &pi, sizeof(PI));
index += sizeof(PI);
memcpy(res.data() + index, &ri, sizeof(RI));
@@ -113,14 +129,30 @@ void MMIO::Deserialize(const std::vector<u8> &data) {
index += sizeof(DPC);
memcpy(rdp.cmd_buf, data.data() + index, 0xFFFFF);
index += 0xFFFFF;
std::copy(data.begin() + index, data.begin() + index + RDRAM_SIZE, rdp.rdram.begin());
std::copy_n(data.begin() + index, RDRAM_SIZE, rdp.rdram.begin());
index += RDRAM_SIZE;
memcpy(&mi, data.data() + index, sizeof(MI));
index += sizeof(MI);
memcpy(&vi, data.data() + index, sizeof(VI));
index += sizeof(VI);
memcpy(&ai, data.data() + index, sizeof(AI));
index += sizeof(AI);
memcpy(&ai.dmaEnable, data.data() + index, sizeof(ai.dmaEnable));
index += sizeof(ai.dmaEnable);
memcpy(&ai.dacRate, data.data() + index, sizeof(ai.dacRate));
index += sizeof(ai.dacRate);
memcpy(&ai.bitrate, data.data() + index, sizeof(ai.bitrate));
index += sizeof(ai.bitrate);
memcpy(&ai.dmaCount, data.data() + index, sizeof(ai.dmaCount));
index += sizeof(ai.dmaCount);
memcpy(&ai.dmaLen, data.data() + index, sizeof(ai.dmaLen));
index += sizeof(ai.dmaLen);
memcpy(&ai.dmaAddr, data.data() + index, sizeof(ai.dmaAddr));
index += sizeof(ai.dmaAddr);
memcpy(&ai.dmaAddrCarry, data.data() + index, sizeof(ai.dmaAddrCarry));
index += sizeof(ai.dmaAddrCarry);
memcpy(&ai.cycles, data.data() + index, sizeof(ai.cycles));
index += sizeof(ai.cycles);
memcpy(&ai.dac, data.data() + index, sizeof(ai.dac));
index += sizeof(ai.dac);
memcpy(&pi, data.data() + index, sizeof(PI));
index += sizeof(PI);
memcpy(&ri, data.data() + index, sizeof(RI));

View File

@@ -8,13 +8,13 @@
#include <unarr.h>
namespace n64 {
Mem::Mem(Registers &regs, ParallelRDP &parallel) : flash(saveData), mmio(*this, regs, parallel) {
Mem::Mem(Registers &regs, ParallelRDP &parallel) : mmio(*this, regs, parallel), flash(saveData) {
rom.cart.resize(CART_SIZE);
std::fill(rom.cart.begin(), rom.cart.end(), 0);
std::ranges::fill(rom.cart, 0);
}
void Mem::Reset() {
std::fill(rom.cart.begin(), rom.cart.end(), 0);
std::ranges::fill(rom.cart, 0);
flash.Reset();
if (saveData.is_mapped()) {
std::error_code error;
@@ -87,7 +87,7 @@ FORCE_INLINE void SetROMCIC(u32 checksum, ROM &rom) {
}
std::vector<u8> Mem::OpenArchive(const std::string &path, size_t &sizeAdjusted) {
auto stream = ar_open_file(fs::path(path).string().c_str());
const auto stream = ar_open_file(fs::path(path).string().c_str());
if (!stream) {
Util::panic("Could not open archive! Are you sure it's an archive?");
@@ -115,17 +115,17 @@ std::vector<u8> Mem::OpenArchive(const std::string &path, size_t &sizeAdjusted)
auto filename = ar_entry_get_name(archive);
auto extension = fs::path(filename).extension();
if (std::any_of(rom_exts.begin(), rom_exts.end(), [&](auto x) { return extension == x; })) {
auto size = ar_entry_get_size(archive);
if (std::ranges::any_of(rom_exts, [&](const auto& x) { return extension == x; })) {
const auto size = ar_entry_get_size(archive);
sizeAdjusted = Util::NextPow2(size);
buf.resize(sizeAdjusted);
ar_entry_uncompress(archive, buf.data(), size);
break;
} else {
ar_close_archive(archive);
ar_close(stream);
Util::panic("Could not find any rom image in the archive!");
}
ar_close_archive(archive);
ar_close(stream);
Util::panic("Could not find any rom image in the archive!");
}
ar_close_archive(archive);
@@ -139,10 +139,10 @@ std::vector<u8> Mem::OpenROM(const std::string &filename, size_t &sizeAdjusted)
return buf;
}
void Mem::LoadROM(bool isArchive, const std::string &filename) {
size_t sizeAdjusted;
void Mem::LoadROM(const bool isArchive, const std::string &filename) {
u32 endianness;
{
size_t sizeAdjusted;
std::vector<u8> buf{};
if (isArchive) {
buf = OpenArchive(filename, sizeAdjusted);
@@ -153,7 +153,7 @@ void Mem::LoadROM(bool isArchive, const std::string &filename) {
endianness = bswap(*reinterpret_cast<u32 *>(buf.data()));
Util::SwapN64Rom<true>(buf, endianness);
std::copy(buf.begin(), buf.end(), rom.cart.begin());
std::ranges::copy(buf, rom.cart.begin());
rom.mask = sizeAdjusted - 1;
memcpy(&rom.header, buf.data(), sizeof(ROMHeader));
}
@@ -178,7 +178,7 @@ void Mem::LoadROM(bool isArchive, const std::string &filename) {
rom.gameNameCart[i] = '\0';
}
u32 checksum = Util::crc32(0, &rom.cart[0x40], 0x9c0);
const u32 checksum = Util::crc32(0, &rom.cart[0x40], 0x9c0);
SetROMCIC(checksum, rom);
endianness = bswap(*reinterpret_cast<u32 *>(rom.cart.data()));
Util::SwapN64Rom(rom.cart, endianness);
@@ -186,15 +186,15 @@ void Mem::LoadROM(bool isArchive, const std::string &filename) {
}
template <>
u8 Mem::Read(n64::Registers &regs, u32 paddr) {
SI &si = mmio.si;
u8 Mem::Read(Registers &regs, const u32 paddr) {
const SI &si = mmio.si;
switch (paddr) {
case RDRAM_REGION:
return mmio.rdp.ReadRDRAM<u8>(paddr);
case RSP_MEM_REGION:
{
auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return src[BYTE_ADDRESS(paddr & 0xfff)];
}
case REGION_CART:
@@ -206,9 +206,9 @@ u8 Mem::Read(n64::Registers &regs, u32 paddr) {
Util::panic("MMIO Read<u8>!\n");
case AI_REGION:
{
u32 w = mmio.ai.Read(paddr & ~3);
int offs = 3 - (paddr & 3);
return (w >> (offs * 8)) & 0xff;
const u32 w = mmio.ai.Read(paddr & ~3);
const int offs = 3 - (paddr & 3);
return w >> offs * 8 & 0xff;
}
case PIF_ROM_REGION:
return si.pif.bootrom[BYTE_ADDRESS(paddr) - PIF_ROM_REGION_START];
@@ -221,19 +221,20 @@ u8 Mem::Read(n64::Registers &regs, u32 paddr) {
return 0;
default:
Util::panic("Unimplemented 8-bit read at address {:08X} (PC = {:016X})", paddr, (u64)regs.pc);
return 0;
}
}
template <>
u16 Mem::Read(n64::Registers &regs, u32 paddr) {
SI &si = mmio.si;
u16 Mem::Read(Registers &regs, const u32 paddr) {
const SI &si = mmio.si;
switch (paddr) {
case RDRAM_REGION:
return mmio.rdp.ReadRDRAM<u16>(paddr);
case RSP_MEM_REGION:
{
auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return Util::ReadAccess<u16>(src, HALF_ADDRESS(paddr & 0xfff));
}
case MMIO_REGION:
@@ -251,19 +252,20 @@ u16 Mem::Read(n64::Registers &regs, u32 paddr) {
return 0;
default:
Util::panic("Unimplemented 16-bit read at address {:08X} (PC = {:016X})", paddr, (u64)regs.pc);
return 0;
}
}
template <>
u32 Mem::Read(n64::Registers &regs, u32 paddr) {
SI &si = mmio.si;
u32 Mem::Read(Registers &regs, const u32 paddr) {
const SI &si = mmio.si;
switch (paddr) {
case RDRAM_REGION:
return mmio.rdp.ReadRDRAM<u32>(paddr);
case RSP_MEM_REGION:
{
auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return Util::ReadAccess<u32>(src, paddr & 0xfff);
}
case MMIO_REGION:
@@ -285,15 +287,15 @@ u32 Mem::Read(n64::Registers &regs, u32 paddr) {
}
template <>
u64 Mem::Read(n64::Registers &regs, u32 paddr) {
SI &si = mmio.si;
u64 Mem::Read(Registers &regs, const u32 paddr) {
const SI &si = mmio.si;
switch (paddr) {
case RDRAM_REGION:
return mmio.rdp.ReadRDRAM<u64>(paddr);
case RSP_MEM_REGION:
{
auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return Util::ReadAccess<u64>(src, paddr & 0xfff);
}
case MMIO_REGION:
@@ -397,7 +399,7 @@ void Mem::Write<u16>(Registers &regs, u32 paddr, u32 val) {
}
template <>
void Mem::Write<u32>(Registers &regs, u32 paddr, u32 val) {
void Mem::Write<u32>(Registers &regs, const u32 paddr, const u32 val) {
SI &si = mmio.si;
switch (paddr) {
@@ -434,7 +436,7 @@ void Mem::Write<u32>(Registers &regs, u32 paddr, u32 val) {
}
}
void Mem::Write(Registers &regs, u32 paddr, u64 val) {
void Mem::Write(const Registers &regs, const u32 paddr, u64 val) {
SI &si = mmio.si;
switch (paddr) {
@@ -472,7 +474,7 @@ void Mem::Write(Registers &regs, u32 paddr, u64 val) {
}
template <>
u32 Mem::BackupRead<u32>(u32 addr) {
u32 Mem::BackupRead<u32>(const u32 addr) {
switch (saveType) {
case SAVE_NONE:
return 0;
@@ -490,7 +492,7 @@ u32 Mem::BackupRead<u32>(u32 addr) {
}
template <>
u8 Mem::BackupRead<u8>(u32 addr) {
u8 Mem::BackupRead<u8>(const u32 addr) {
switch (saveType) {
case SAVE_NONE:
return 0;
@@ -513,7 +515,7 @@ u8 Mem::BackupRead<u8>(u32 addr) {
}
template <>
void Mem::BackupWrite<u32>(u32 addr, u32 val) {
void Mem::BackupWrite<u32>(const u32 addr, const u32 val) {
switch (saveType) {
case SAVE_NONE:
Util::warn("Accessing cartridge with save type SAVE_NONE in write word");
@@ -532,7 +534,7 @@ void Mem::BackupWrite<u32>(u32 addr, u32 val) {
}
template <>
void Mem::BackupWrite<u8>(u32 addr, u8 val) {
void Mem::BackupWrite<u8>(const u32 addr, const u8 val) {
switch (saveType) {
case SAVE_NONE:
Util::warn("Accessing cartridge with save type SAVE_NONE in write word");
@@ -572,8 +574,8 @@ std::vector<u8> Mem::Serialize() {
}
void Mem::Deserialize(const std::vector<u8> &data) {
mmio.Deserialize(std::vector<u8>(data.begin(), data.begin() + mmioSize));
flash.Deserialize(std::vector<u8>(data.begin() + mmioSize, data.begin() + mmioSize + flashSize));
mmio.Deserialize(std::vector(data.begin(), data.begin() + mmioSize));
flash.Deserialize(std::vector(data.begin() + mmioSize, data.begin() + mmioSize + flashSize));
memcpy(saveData.data(), data.data() + mmioSize + flashSize, saveData.size());
}
} // namespace n64

View File

@@ -62,7 +62,7 @@ struct Flash {
FLASH_COMMAND_READ = 0xF0,
};
void CommandExecute();
void CommandExecute() const;
void CommandStatus();
void CommandSetEraseOffs(u32);
void CommandErase();
@@ -96,7 +96,7 @@ struct Mem {
T Read(Registers &, u32);
template <typename T>
void Write(Registers &, u32, u32);
void Write(Registers &, u32, u64);
void Write(const Registers &, u32, u64);
template <typename T>
T BackupRead(u32);
@@ -108,21 +108,21 @@ struct Mem {
FORCE_INLINE void DumpRDRAM() const {
std::vector<u8> temp{};
temp.resize(RDRAM_SIZE);
std::copy(mmio.rdp.rdram.begin(), mmio.rdp.rdram.end(), temp.begin());
std::ranges::copy(mmio.rdp.rdram, temp.begin());
Util::SwapBuffer<u32>(temp);
Util::WriteFileBinary(temp, "rdram.bin");
}
FORCE_INLINE void DumpIMEM() const {
std::array<u8, IMEM_SIZE> temp{};
std::copy(mmio.rsp.imem.begin(), mmio.rsp.imem.end(), temp.begin());
std::ranges::copy(mmio.rsp.imem, temp.begin());
Util::SwapBuffer<u32>(temp);
Util::WriteFileBinary(temp, "imem.bin");
}
FORCE_INLINE void DumpDMEM() const {
std::array<u8, DMEM_SIZE> temp{};
std::copy(mmio.rsp.dmem.begin(), mmio.rsp.dmem.end(), temp.begin());
std::ranges::copy(mmio.rsp.dmem, temp.begin());
Util::SwapBuffer<u32>(temp);
Util::WriteFileBinary(temp, "dmem.bin");
}
@@ -141,9 +141,9 @@ private:
mio::mmap_sink saveData{};
int mmioSize{}, flashSize{};
FORCE_INLINE bool IsROMPAL() {
static const char pal_codes[] = {'D', 'F', 'I', 'P', 'S', 'U', 'X', 'Y'};
return std::any_of(std::begin(pal_codes), std::end(pal_codes), [this](char a) { return rom.cart[0x3d] == a; });
[[nodiscard]] FORCE_INLINE bool IsROMPAL() const {
static constexpr char pal_codes[] = {'D', 'F', 'I', 'P', 'S', 'U', 'X', 'Y'};
return std::ranges::any_of(pal_codes, [this](char a) { return rom.cart[0x3d] == a; });
}
};
} // namespace n64

View File

@@ -7,7 +7,7 @@
namespace n64 {
RDP::RDP(Mem &mem, ParallelRDP &parallel) : mem(mem), parallel(parallel) {
rdram.resize(RDRAM_SIZE);
std::fill(rdram.begin(), rdram.end(), 0);
std::ranges::fill(rdram, 0);
memset(cmd_buf, 0, 0x100000);
dpc.status.raw = 0x80;
}
@@ -15,75 +15,75 @@ RDP::RDP(Mem &mem, ParallelRDP &parallel) : mem(mem), parallel(parallel) {
void RDP::Reset() {
dpc = {};
dpc.status.raw = 0x80;
std::fill(rdram.begin(), rdram.end(), 0);
std::ranges::fill(rdram, 0);
memset(cmd_buf, 0, 0x100000);
}
template <>
void RDP::WriteRDRAM<u8>(size_t idx, u8 v) {
size_t real = BYTE_ADDRESS(idx);
if (real < RDRAM_SIZE) {
void RDP::WriteRDRAM<u8>(const size_t idx, const u8 v) {
if (const size_t real = BYTE_ADDRESS(idx); real < RDRAM_SIZE) [[likely]] {
rdram[real] = v;
}
}
template <>
void RDP::WriteRDRAM<u16>(size_t idx, u16 v) {
size_t real = HALF_ADDRESS(idx);
if (real < RDRAM_SIZE) {
void RDP::WriteRDRAM<u16>(const size_t idx, const u16 v) {
if (const size_t real = HALF_ADDRESS(idx); real < RDRAM_SIZE) [[likely]] {
Util::WriteAccess<u16>(rdram, real, v);
}
}
template <>
void RDP::WriteRDRAM<u32>(size_t idx, u32 v) {
if (idx < RDRAM_SIZE) {
void RDP::WriteRDRAM<u32>(const size_t idx, const u32 v) {
if (idx < RDRAM_SIZE) [[likely]] {
Util::WriteAccess<u32>(rdram, idx, v);
}
}
template <>
void RDP::WriteRDRAM<u64>(size_t idx, u64 v) {
if (idx < RDRAM_SIZE) {
void RDP::WriteRDRAM<u64>(const size_t idx, const u64 v) {
if (idx < RDRAM_SIZE) [[likely]] {
Util::WriteAccess<u64>(rdram, idx, v);
}
}
template <>
u8 RDP::ReadRDRAM<u8>(size_t idx) {
size_t real = BYTE_ADDRESS(idx);
if (real >= RDRAM_SIZE)
return 0;
return rdram[real];
u8 RDP::ReadRDRAM<u8>(const size_t idx) {
if (const size_t real = BYTE_ADDRESS(idx); real < RDRAM_SIZE) [[likely]]
return rdram[real];
return 0;
}
template <>
u16 RDP::ReadRDRAM<u16>(size_t idx) {
size_t real = HALF_ADDRESS(idx);
if (real >= RDRAM_SIZE)
return 0;
return Util::ReadAccess<u16>(rdram, real);
u16 RDP::ReadRDRAM<u16>(const size_t idx) {
if (const size_t real = HALF_ADDRESS(idx); real < RDRAM_SIZE) [[likely]]
return Util::ReadAccess<u16>(rdram, real);
return 0;
}
template <>
u32 RDP::ReadRDRAM<u32>(size_t idx) {
if (idx >= RDRAM_SIZE)
return 0;
return Util::ReadAccess<u32>(rdram, idx);
u32 RDP::ReadRDRAM<u32>(const size_t idx) {
if (idx < RDRAM_SIZE) [[likely]]
return Util::ReadAccess<u32>(rdram, idx);
return 0;
}
template <>
u64 RDP::ReadRDRAM<u64>(size_t idx) {
if (idx >= RDRAM_SIZE)
return 0;
return Util::ReadAccess<u64>(rdram, idx);
u64 RDP::ReadRDRAM<u64>(const size_t idx) {
if (idx < RDRAM_SIZE) [[likely]]
return Util::ReadAccess<u64>(rdram, idx);
return 0;
}
static const int cmd_lens[64] = {2, 2, 2, 2, 2, 2, 2, 2, 8, 12, 24, 28, 24, 28, 40, 44, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
auto RDP::Read(u32 addr) const -> u32 {
auto RDP::Read(const u32 addr) const -> u32 {
switch (addr) {
case 0x04100000:
return dpc.start;
@@ -104,9 +104,11 @@ auto RDP::Read(u32 addr) const -> u32 {
default:
Util::panic("Unhandled DP Command Registers read (addr: {:08X})", addr);
}
return 0;
}
void RDP::Write(u32 addr, u32 val) {
void RDP::Write(const u32 addr, const u32 val) {
switch (addr) {
case 0x04100000:
WriteStart(val);
@@ -122,7 +124,7 @@ void RDP::Write(u32 addr, u32 val) {
}
}
void RDP::WriteStatus(u32 val) {
void RDP::WriteStatus(const u32 val) {
DPCStatusWrite temp{};
temp.raw = val;
@@ -201,39 +203,40 @@ void RDP::RunCommand() {
const u32 current = dpc.current & 0xFFFFF8;
const u32 end = dpc.end & 0xFFFFF8;
int len = end - current;
const auto len = static_cast<s32>(end) - static_cast<s32>(current);
if (len <= 0)
return;
if (len + (remaining_cmds * 4) > 0xFFFFF) {
if (len + remaining_cmds * 4 > 0xFFFFF) {
Util::panic("Too many RDP commands");
return;
}
if (dpc.status.xbusDmemDma) {
for (int i = 0; i < len; i += 4) {
u32 cmd = Util::ReadAccess<u32>(mem.mmio.rsp.dmem, (current + i) & 0xFFF);
const u32 cmd = Util::ReadAccess<u32>(mem.mmio.rsp.dmem, (current + i) & 0xFFF);
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
}
} else {
if (end > 0x7FFFFFF || current > 0x7FFFFFF) { // if (end > RDRAM_DSIZE || current > RDRAM_DSIZE)
return;
}
for (int i = 0; i < len; i += 4) {
u32 cmd = Util::ReadAccess<u32>(rdram, current + i);
const u32 cmd = Util::ReadAccess<u32>(rdram, current + i);
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
}
}
int word_len = (len >> 2) + remaining_cmds;
const int word_len = (len >> 2) + remaining_cmds;
int buf_index = 0;
bool processed_all = true;
while (buf_index < word_len) {
u8 cmd = (cmd_buf[buf_index] >> 24) & 0x3F;
const u8 cmd = (cmd_buf[buf_index] >> 24) & 0x3F;
int cmd_len = cmd_lens[cmd];
const int cmd_len = cmd_lens[cmd];
if ((buf_index + cmd_len) * 4 > len + (remaining_cmds * 4)) {
remaining_cmds = word_len - buf_index;

View File

@@ -4,7 +4,7 @@
#include <log.hpp>
namespace n64 {
RSP::RSP(Mem &mem, Registers &regs) : mem(mem), regs(regs) { Reset(); }
RSP::RSP(Mem &mem, Registers &regs) : regs(regs), mem(mem) { Reset(); }
void RSP::Reset() {
lastSuccessfulSPAddr.raw = 0;
@@ -65,7 +65,7 @@ FORCE_INLINE void logRSP(const RSP& rsp, const u32 instr) {
}
*/
auto RSP::Read(u32 addr) -> u32 {
auto RSP::Read(const u32 addr) -> u32 {
switch (addr) {
case 0x04040000:
return lastSuccessfulSPAddr.raw & 0x1FF8;
@@ -89,9 +89,9 @@ auto RSP::Read(u32 addr) -> u32 {
}
}
void RSP::WriteStatus(u32 value) {
void RSP::WriteStatus(const u32 value) {
MI &mi = mem.mmio.mi;
auto write = SPStatusWrite{.raw = value};
const auto write = SPStatusWrite{.raw = value};
if (write.clearHalt && !write.setHalt) {
spStatus.halt = false;
}
@@ -123,7 +123,7 @@ void RSP::DMA<true>() {
length = (length + 0x7) & ~0x7;
std::array<u8, DMEM_SIZE> &src = spDMASPAddr.bank ? imem : dmem;
const auto &src = spDMASPAddr.bank ? imem : dmem;
u32 mem_address = spDMASPAddr.address & 0xFF8;
u32 dram_address = spDMADRAMAddr.address & 0xFFFFF8;
@@ -134,7 +134,7 @@ void RSP::DMA<true>() {
mem.mmio.rdp.WriteRDRAM<u8>(BYTE_ADDRESS(dram_address + j), src[(mem_address + j) & DMEM_DSIZE]);
}
int skip = i == spDMALen.count ? 0 : spDMALen.skip;
const int skip = i == spDMALen.count ? 0 : spDMALen.skip;
dram_address += (length + skip);
dram_address &= 0xFFFFF8;
@@ -155,7 +155,7 @@ void RSP::DMA<false>() {
length = (length + 0x7) & ~0x7;
std::array<u8, DMEM_SIZE> &dst = spDMASPAddr.bank ? imem : dmem;
auto &dst = spDMASPAddr.bank ? imem : dmem;
u32 mem_address = spDMASPAddr.address & 0xFF8;
u32 dram_address = spDMADRAMAddr.address & 0xFFFFF8;
@@ -166,7 +166,7 @@ void RSP::DMA<false>() {
dst[(mem_address + j) & DMEM_DSIZE] = mem.mmio.rdp.ReadRDRAM<u8>(BYTE_ADDRESS(dram_address + j));
}
int skip = i == spDMALen.count ? 0 : spDMALen.skip;
const int skip = i == spDMALen.count ? 0 : spDMALen.skip;
dram_address += (length + skip);
dram_address &= 0xFFFFF8;
@@ -181,7 +181,7 @@ void RSP::DMA<false>() {
spDMALen.raw = 0xFF8 | (spDMALen.skip << 20);
}
void RSP::Write(u32 addr, u32 val) {
void RSP::Write(const u32 addr, const u32 val) {
switch (addr) {
case 0x04040000:
spDMASPAddr.raw = val & 0x1FF8;

View File

@@ -118,9 +118,9 @@ struct Registers;
#define DE(x) (((x) >> 11) & 0x1F)
#define CLEAR_SET(val, clear, set) \
do { \
if (clear && !set) \
if ((clear) && !(set)) \
(val) = 0; \
if (set && !clear) \
if ((set) && !(clear)) \
(val) = 1; \
} \
while (0)
@@ -131,13 +131,15 @@ struct RSP {
FORCE_INLINE void Step() {
gpr[0] = 0;
u32 instr = Util::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
const u32 instr = Util::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
oldPC = pc & 0xFFC;
pc = nextPC & 0xFFC;
nextPC += 4;
Exec(instr);
}
void SetVTE(const VPR &vt, u8 e);
auto Read(u32 addr) -> u32;
void Write(u32 addr, u32 val);
void Exec(u32 instr);
@@ -151,6 +153,7 @@ struct RSP {
std::array<u8, DMEM_SIZE> dmem{};
std::array<u8, IMEM_SIZE> imem{};
VPR vpr[32]{};
VPR vte{};
s32 gpr[32]{};
VPR vce{};
s16 divIn{}, divOut{};
@@ -167,13 +170,13 @@ struct RSP {
bool semaphore = false;
FORCE_INLINE void SetPC(u16 val) {
FORCE_INLINE void SetPC(const u16 val) {
oldPC = pc & 0xFFC;
pc = val & 0xFFC;
nextPC = pc + 4;
}
FORCE_INLINE s64 GetACC(int e) const {
[[nodiscard]] FORCE_INLINE s64 GetACC(const int e) const {
s64 val = u64(acc.h.element[e]) << 32;
val |= u64(acc.m.element[e]) << 16;
val |= u64(acc.l.element[e]) << 00;
@@ -183,69 +186,69 @@ struct RSP {
return val;
}
FORCE_INLINE void SetACC(int e, s64 val) {
FORCE_INLINE void SetACC(const int e, const s64 val) {
acc.h.element[e] = val >> 32;
acc.m.element[e] = val >> 16;
acc.l.element[e] = val;
}
FORCE_INLINE u16 GetVCO() const {
[[nodiscard]] FORCE_INLINE u16 GetVCO() const {
u16 value = 0;
for (int i = 0; i < 8; i++) {
bool h = vco.h.element[7 - i] != 0;
bool l = vco.l.element[7 - i] != 0;
u32 mask = (l << i) | (h << (i + 8));
const bool h = vco.h.element[7 - i] != 0;
const bool l = vco.l.element[7 - i] != 0;
const u32 mask = (l << i) | (h << (i + 8));
value |= mask;
}
return value;
}
FORCE_INLINE u16 GetVCC() const {
[[nodiscard]] FORCE_INLINE u16 GetVCC() const {
u16 value = 0;
for (int i = 0; i < 8; i++) {
bool h = vcc.h.element[7 - i] != 0;
bool l = vcc.l.element[7 - i] != 0;
u32 mask = (l << i) | (h << (i + 8));
const bool h = vcc.h.element[7 - i] != 0;
const bool l = vcc.l.element[7 - i] != 0;
const u32 mask = (l << i) | (h << (i + 8));
value |= mask;
}
return value;
}
FORCE_INLINE u8 GetVCE() const {
[[nodiscard]] FORCE_INLINE u8 GetVCE() const {
u8 value = 0;
for (int i = 0; i < 8; i++) {
bool l = vce.element[ELEMENT_INDEX(i)] != 0;
const bool l = vce.element[ELEMENT_INDEX(i)] != 0;
value |= (l << i);
}
return value;
}
FORCE_INLINE u32 ReadWord(u32 addr) {
[[nodiscard]] FORCE_INLINE u32 ReadWord(u32 addr) const {
addr &= 0xfff;
return GET_RSP_WORD(addr);
}
FORCE_INLINE void WriteWord(u32 addr, u32 val) {
FORCE_INLINE void WriteWord(u32 addr, const u32 val) {
addr &= 0xfff;
SET_RSP_WORD(addr, val);
}
FORCE_INLINE u16 ReadHalf(u32 addr) {
[[nodiscard]] FORCE_INLINE u16 ReadHalf(u32 addr) const {
addr &= 0xfff;
return GET_RSP_HALF(addr);
}
FORCE_INLINE void WriteHalf(u32 addr, u16 val) {
FORCE_INLINE void WriteHalf(u32 addr, const u16 val) {
addr &= 0xfff;
SET_RSP_HALF(addr, val);
}
FORCE_INLINE u8 ReadByte(u32 addr) {
[[nodiscard]] FORCE_INLINE u8 ReadByte(u32 addr) const {
addr &= 0xfff;
return RSP_BYTE(addr);
}
FORCE_INLINE void WriteByte(u32 addr, u8 val) {
FORCE_INLINE void WriteByte(u32 addr, const u8 val) {
addr &= 0xfff;
RSP_BYTE(addr) = val;
}
@@ -364,8 +367,8 @@ struct RSP {
void vor(u32 instr);
void vnor(u32 instr);
void vzero(u32 instr);
void mfc0(RDP &rdp, u32 instr);
void mtc0(u32 instr);
void mfc0(const RDP &rdp, u32 instr);
void mtc0(u32 instr) const;
void mfc2(u32 instr);
void mtc2(u32 instr);
@@ -376,13 +379,13 @@ struct RSP {
private:
Registers &regs;
Mem &mem;
FORCE_INLINE void branch(u16 address, bool cond) {
FORCE_INLINE void branch(const u16 address, const bool cond) {
if (cond) {
nextPC = address & 0xFFC;
}
}
FORCE_INLINE void branch_likely(u16 address, bool cond) {
FORCE_INLINE void branch_likely(const u16 address, const bool cond) {
if (cond) {
nextPC = address & 0xFFC;
} else {

View File

@@ -3,10 +3,9 @@
#include <log.hpp>
namespace n64 {
void Interpreter::special(u32 instr) {
u8 mask = (instr & 0x3F);
void Interpreter::special(const u32 instr) {
// 00rr_rccc
switch (mask) { // TODO: named constants for clearer code
switch (const u8 mask = instr & 0x3F) {
case SLL:
if (instr != 0) {
sll(instr);
@@ -166,14 +165,13 @@ void Interpreter::special(u32 instr) {
break;
default:
Util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 7, mask & 7, instr,
(u64)regs.oldPC);
static_cast<u64>(regs.oldPC));
}
}
void Interpreter::regimm(u32 instr) {
u8 mask = ((instr >> 16) & 0x1F);
void Interpreter::regimm(const u32 instr) {
// 000r_rccc
switch (mask) { // TODO: named constants for clearer code
switch (const u8 mask = instr >> 16 & 0x1F) {
case BLTZ:
b(instr, regs.Read<s64>(RS(instr)) < 0);
break;
@@ -187,22 +185,22 @@ void Interpreter::regimm(u32 instr) {
bl(instr, regs.Read<s64>(RS(instr)) >= 0);
break;
case TGEI:
trap(regs.Read<s64>(RS(instr)) >= s64(s16(instr)));
trap(regs.Read<s64>(RS(instr)) >= static_cast<s64>(static_cast<s16>(instr)));
break;
case TGEIU:
trap(regs.Read<u64>(RS(instr)) >= u64(s64(s16(instr))));
trap(regs.Read<u64>(RS(instr)) >= static_cast<u64>(static_cast<s64>(static_cast<s16>(instr))));
break;
case TLTI:
trap(regs.Read<s64>(RS(instr)) < s64(s16(instr)));
trap(regs.Read<s64>(RS(instr)) < static_cast<s64>(static_cast<s16>(instr)));
break;
case TLTIU:
trap(regs.Read<u64>(RS(instr)) < u64(s64(s16(instr))));
trap(regs.Read<u64>(RS(instr)) < static_cast<u64>(static_cast<s64>(static_cast<s16>(instr))));
break;
case TEQI:
trap(regs.Read<s64>(RS(instr)) == s64(s16(instr)));
trap(regs.Read<s64>(RS(instr)) == static_cast<s64>(static_cast<s16>(instr)));
break;
case TNEI:
trap(regs.Read<s64>(RS(instr)) != s64(s16(instr)));
trap(regs.Read<s64>(RS(instr)) != static_cast<s64>(static_cast<s16>(instr)));
break;
case BLTZAL:
blink(instr, regs.Read<s64>(RS(instr)) < 0);
@@ -217,11 +215,12 @@ void Interpreter::regimm(u32 instr) {
bllink(instr, regs.Read<s64>(RS(instr)) >= 0);
break;
default:
Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC);
Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 3, mask & 7, instr,
static_cast<u64>(regs.oldPC));
}
}
void Interpreter::cop2Decode(u32 instr) {
void Interpreter::cop2Decode(const u32 instr) {
if (!regs.cop0.status.cu2) {
regs.cop0.FireException(ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
return;
@@ -250,10 +249,9 @@ void Interpreter::cop2Decode(u32 instr) {
}
}
void Interpreter::Exec(u32 instr) {
u8 mask = (instr >> 26) & 0x3f;
void Interpreter::Exec(const u32 instr) {
// 00rr_rccc
switch (mask) { // TODO: named constants for clearer code
switch (const u8 mask = instr >> 26 & 0x3f) {
case SPECIAL:
special(instr);
break;
@@ -416,7 +414,7 @@ void Interpreter::Exec(u32 instr) {
sd(instr);
break;
default:
Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", mask, instr, (u64)regs.oldPC);
Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", mask, instr, static_cast<u64>(regs.oldPC));
}
}
} // namespace n64

File diff suppressed because it is too large Load Diff

View File

@@ -50,7 +50,7 @@ void Flash::Load(SaveType saveType, const std::string &path) {
}
}
void Flash::CommandExecute() {
void Flash::CommandExecute() const {
Util::trace("Flash::CommandExecute");
switch (state) {
case FlashState::Idle:
@@ -119,7 +119,7 @@ std::vector<u8> Flash::Serialize() {
index += sizeof(eraseOffs);
memcpy(res.data() + index, &writeOffs, sizeof(writeOffs));
index += sizeof(writeOffs);
std::copy(writeBuf.begin(), writeBuf.end(), res.begin() + index);
std::ranges::copy(writeBuf, res.begin() + index);
return res;
}
@@ -192,31 +192,31 @@ void Flash::Write<u8>(u32 index, u8 val) {
}
template <>
u8 Flash::Read<u8>(u32 index) const {
u8 Flash::Read<u8>(const u32 index) const {
switch (state) {
case FlashState::Idle:
Util::panic("Flash read byte while in state FLASH_STATE_IDLE");
case FlashState::Write:
Util::panic("Flash read byte while in state FLASH_STATE_WRITE");
case FlashState::Read:
{
if (saveData.is_mapped()) {
u8 value = saveData[index];
Util::trace("Flash read byte in state read: index {:08X} = {:02X}", index, value);
return value;
} else {
Util::panic("Accessing flash when not mapped!");
}
if (saveData.is_mapped()) {
const u8 value = saveData[index];
Util::trace("Flash read byte in state read: index {:08X} = {:02X}", index, value);
return value;
}
Util::panic("Accessing flash when not mapped!");
case FlashState::Status:
{
u32 offset = (7 - (index % 8)) * 8;
u8 value = (status >> offset) & 0xFF;
const u32 offset = (7 - (index % 8)) * 8;
const u8 value = (status >> offset) & 0xFF;
Util::trace("Flash read byte in state status: index {:08X} = {:02X}", index, value);
return value;
}
default:
Util::panic("Flash read byte while in unknown state");
return 0;
}
}

View File

@@ -21,7 +21,7 @@ void AI::Reset() {
// https://github.com/ares-emulator/ares/blob/master/ares/n64/ai/io.cpp
// https://github.com/ares-emulator/ares/blob/master/LICENSE
auto AI::Read(u32 addr) const -> u32 {
auto AI::Read(const u32 addr) const -> u32 {
if (addr == 0x0450000C) {
u32 val = 0;
val |= (dmaCount > 1);
@@ -36,7 +36,7 @@ auto AI::Read(u32 addr) const -> u32 {
return dmaLen[0];
}
void AI::Write(u32 addr, u32 val) {
void AI::Write(const u32 addr, const u32 val) {
switch (addr) {
case 0x04500000:
if (dmaCount < 2) {
@@ -45,7 +45,7 @@ void AI::Write(u32 addr, u32 val) {
break;
case 0x04500004:
{
u32 len = (val & 0x3FFFF) & ~7;
const u32 len = (val & 0x3FFFF) & ~7;
if (dmaCount < 2) {
if (dmaCount == 0)
mem.mmio.mi.InterruptRaise(MI::Interrupt::AI);
@@ -62,7 +62,7 @@ void AI::Write(u32 addr, u32 val) {
break;
case 0x04500010:
{
u32 oldDacFreq = dac.freq;
const u32 oldDacFreq = dac.freq;
dacRate = val & 0x3FFF;
dac.freq = std::max(1.f, (float)GetVideoFrequency(mem.IsROMPAL()) / (dacRate + 1)) * 1.037;
dac.period = N64_CPU_FREQ / dac.freq;
@@ -80,7 +80,7 @@ void AI::Write(u32 addr, u32 val) {
}
}
void AI::Step(u32 cpuCycles, float volumeL, float volumeR) {
void AI::Step(const u32 cpuCycles, const float volumeL, const float volumeR) {
cycles += cpuCycles;
while (cycles > dac.period) {
if (dmaCount == 0) {
@@ -88,18 +88,18 @@ void AI::Step(u32 cpuCycles, float volumeL, float volumeR) {
}
if (dmaLen[0] && dmaEnable) {
u32 addrHi = ((dmaAddr[0] >> 13) + dmaAddrCarry) & 0x7FF;
dmaAddr[0] = (addrHi << 13) | (dmaAddr[0] & 0x1FFF);
u32 data = mem.mmio.rdp.ReadRDRAM<u32>(dmaAddr[0]);
s16 l = s16(data >> 16);
s16 r = s16(data);
const u32 addrHi = (dmaAddr[0] >> 13) + dmaAddrCarry & 0x7FF;
dmaAddr[0] = addrHi << 13 | dmaAddr[0] & 0x1FFF;
const u32 data = mem.mmio.rdp.ReadRDRAM<u32>(dmaAddr[0]);
const s16 l = s16(data >> 16);
const s16 r = s16(data);
if (volumeR > 0 && volumeL > 0) {
device.PushSample((float)l / INT16_MAX, volumeL, (float)r / INT16_MAX, volumeR);
}
u32 addrLo = (dmaAddr[0] + 4) & 0x1FFF;
dmaAddr[0] = (dmaAddr[0] & ~0x1FFF) | addrLo;
const u32 addrLo = dmaAddr[0] + 4 & 0x1FFF;
dmaAddr[0] = dmaAddr[0] & ~0x1FFF | addrLo;
dmaAddrCarry = addrLo == 0;
dmaLen[0] -= 4;
}

View File

@@ -31,13 +31,13 @@ AudioDevice::AudioDevice() {
}
}
void AudioDevice::PushSample(float left, float volumeL, float right, float volumeR) {
float adjustedL = left * volumeL;
float adjustedR = right * volumeR;
float samples[]{adjustedL, adjustedR};
void AudioDevice::PushSample(const float left, const float volumeL, const float right, const float volumeR) {
const float adjustedL = left * volumeL;
const float adjustedR = right * volumeR;
const float samples[]{adjustedL, adjustedR};
auto availableBytes = (float)SDL_GetAudioStreamAvailable(audioStream);
if (availableBytes <= BYTES_PER_HALF_SECOND) {
if (const auto availableBytes = static_cast<float>(SDL_GetAudioStreamAvailable(audioStream));
availableBytes <= BYTES_PER_HALF_SECOND) {
SDL_PutAudioStreamData(audioStream, samples, 2 * sizeof(float));
}
@@ -47,7 +47,7 @@ void AudioDevice::PushSample(float left, float volumeL, float right, float volum
}
}
void AudioDevice::AdjustSampleRate(int sampleRate) {
void AudioDevice::AdjustSampleRate(const int sampleRate) {
LockMutex();
SDL_DestroyAudioStream(audioStream);

View File

@@ -11,16 +11,16 @@ struct AudioDevice {
void PushSample(float, float, float, float);
void AdjustSampleRate(int);
void LockMutex() {
void LockMutex() const {
if (audioStreamMutex)
SDL_LockMutex(audioStreamMutex);
}
void UnlockMutex() {
void UnlockMutex() const {
if (audioStreamMutex)
SDL_UnlockMutex(audioStreamMutex);
}
SDL_AudioStream *GetStream() { return audioStream; }
SDL_AudioStream *GetStream() const { return audioStream; }
private:
SDL_AudioStream *audioStream;

View File

@@ -2,7 +2,7 @@
#include <core/registers/Registers.hpp>
namespace n64 {
void MI::InterruptRaise(Interrupt intr) {
void MI::InterruptRaise(const Interrupt intr) {
switch (intr) {
case Interrupt::VI:
miIntr.vi = true;
@@ -27,7 +27,7 @@ void MI::InterruptRaise(Interrupt intr) {
UpdateInterrupt();
}
void MI::InterruptLower(Interrupt intr) {
void MI::InterruptLower(const Interrupt intr) {
switch (intr) {
case Interrupt::VI:
miIntr.vi = false;
@@ -52,8 +52,8 @@ void MI::InterruptLower(Interrupt intr) {
UpdateInterrupt();
}
void MI::UpdateInterrupt() {
bool interrupt = miIntr.raw & miIntrMask.raw;
void MI::UpdateInterrupt() const {
const bool interrupt = miIntr.raw & miIntrMask.raw;
regs.cop0.cause.ip2 = interrupt;
}
} // namespace n64

View File

@@ -66,8 +66,8 @@ void MI::Write(u32 paddr, u32 val) {
break;
case 0xC:
for (int bit = 0; bit < 6; bit++) {
int clearbit = bit << 1;
int setbit = (bit << 1) + 1;
const int clearbit = bit << 1;
const int setbit = (bit << 1) + 1;
if (val & (1 << clearbit)) {
miIntrMask.raw &= ~(1 << bit);

View File

@@ -21,13 +21,13 @@ struct Registers;
struct MI {
enum class Interrupt : u8 { VI, SI, PI, AI, DP, SP };
MI(Registers &);
explicit MI(Registers &);
void Reset();
[[nodiscard]] auto Read(u32) const -> u32;
void Write(u32, u32);
void InterruptRaise(Interrupt intr);
void InterruptLower(Interrupt intr);
void UpdateInterrupt();
void UpdateInterrupt() const;
u32 miMode{};
MIIntr miIntr{}, miIntrMask{};

View File

@@ -65,7 +65,7 @@ auto PI::BusRead<u8, true>(u32 addr) -> u8 {
case REGION_PI_ROM:
{
// round to nearest 4 byte boundary, keeping old LSB
u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM;
const u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM;
if (index >= mem.rom.cart.size()) {
Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr,
index, index, mem.rom.cart.size(), mem.rom.cart.size());
@@ -104,7 +104,7 @@ auto PI::BusRead<u8, false>(u32 addr) -> u8 {
{
addr = (addr + 2) & ~2;
// round to nearest 4 byte boundary, keeping old LSB
u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM;
const u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM;
if (index >= mem.rom.cart.size()) {
Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr,
index, index, mem.rom.cart.size(), mem.rom.cart.size());
@@ -178,7 +178,7 @@ auto PI::BusRead<u16, false>(u32 addr) -> u16 {
case REGION_PI_ROM:
{
addr = (addr + 2) & ~3;
u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM;
const u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM;
if (index > mem.rom.cart.size() - 1) {
Util::panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index);
}
@@ -312,7 +312,7 @@ void PI::BusWrite<u32, false>(u32 addr, u32 val) {
{
if (val < CART_ISVIEWER_SIZE) {
std::string message(val + 1, 0);
std::copy(mem.isviewer.begin(), mem.isviewer.begin() + val, message.begin());
std::copy_n(mem.isviewer.begin(), val, message.begin());
Util::print<Util::Always>("{}", message);
} else {
Util::panic("ISViewer buffer size is emulated at {} bytes, but received a flush command for {} bytes!",
@@ -355,7 +355,7 @@ auto PI::BusRead<u64, false>(u32 addr) -> u64 {
Util::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr);
case REGION_PI_ROM:
{
u32 index = addr - SREGION_PI_ROM;
const u32 index = addr - SREGION_PI_ROM;
if (index > mem.rom.cart.size() - 7) { // -7 because we're reading an entire dword
Util::panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index);
}
@@ -439,7 +439,7 @@ auto PI::Read(u32 addr) const -> u32 {
}
}
u8 PI::GetDomain(u32 address) {
u8 PI::GetDomain(const u32 address) {
switch (address) {
case REGION_PI_UNKNOWN:
case REGION_PI_64DD_ROM:
@@ -453,13 +453,12 @@ u8 PI::GetDomain(u32 address) {
}
}
u32 PI::AccessTiming(u8 domain, u32 length) const {
u32 PI::AccessTiming(const u8 domain, const u32 length) const {
uint32_t cycles = 0;
uint32_t latency = 0;
uint32_t pulse_width = 0;
uint32_t release = 0;
uint32_t page_size = 0;
uint32_t pages;
switch (domain) {
case 1:
@@ -478,7 +477,7 @@ u32 PI::AccessTiming(u8 domain, u32 length) const {
Util::panic("Unknown PI domain: {}\n", domain);
}
pages = ceil((double)length / page_size);
const uint32_t pages = ceil((double)length / page_size);
cycles += (14 + latency) * pages;
cycles += (pulse_width + release) * (length / 2);
@@ -489,7 +488,7 @@ u32 PI::AccessTiming(u8 domain, u32 length) const {
// rdram -> cart
template <>
void PI::DMA<false>() {
s32 len = rdLen + 1;
const s32 len = rdLen + 1;
Util::trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
if (mem.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < 0x08010000) {
@@ -512,7 +511,7 @@ void PI::DMA<false>() {
// cart -> rdram
template <>
void PI::DMA<true>() {
s32 len = wrLen + 1;
const s32 len = wrLen + 1;
Util::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
if (mem.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < 0x08010000) {

View File

@@ -9,7 +9,7 @@ struct Registers;
struct PI {
PI(Mem &, Registers &);
void Reset();
auto Read(u32) const -> u32;
[[nodiscard]] auto Read(u32) const -> u32;
void Write(u32, u32);
template <typename T, bool isDma>

View File

@@ -85,7 +85,7 @@ FORCE_INLINE size_t GetSaveSize(SaveType saveType) {
}
}
void PIF::LoadEeprom(SaveType saveType, const std::string &path) {
void PIF::LoadEeprom(const SaveType saveType, const std::string &path) {
if (saveType == SAVE_EEPROM_16k || saveType == SAVE_EEPROM_4k) {
fs::path eepromPath_ = path;
if (!savePath.empty()) {
@@ -134,7 +134,7 @@ void PIF::CICChallenge() {
challenge[i * 2 + 1] = (ram[0x30 + i] >> 0) & 0x0F;
}
n64_cic_nus_6105((char *)challenge, (char *)response, CHL_LEN - 2);
n64_cic_nus_6105(reinterpret_cast<char *>(challenge), reinterpret_cast<char *>(response), CHL_LEN - 2);
for (int i = 0; i < 15; i++) {
ram[0x30 + i] = (response[i * 2] << 4) + response[i * 2 + 1];
@@ -145,7 +145,7 @@ FORCE_INLINE u8 DataCRC(const u8 *data) {
u8 crc = 0;
for (int i = 0; i <= 32; i++) {
for (int j = 7; j >= 0; j--) {
u8 xorVal = ((crc & 0x80) != 0) ? 0x85 : 0x00;
const u8 xorVal = ((crc & 0x80) != 0) ? 0x85 : 0x00;
crc <<= 1;
if (i < 32) {
@@ -164,27 +164,25 @@ FORCE_INLINE u8 DataCRC(const u8 *data) {
#define BCD_ENCODE(x) (((x) / 10) << 4 | ((x) % 10))
#define BCD_DECODE(x) (((x) >> 4) * 10 + ((x) & 15))
void PIF::ProcessCommands(Mem &mem) {
u8 control = ram[63];
void PIF::ProcessCommands(const Mem &mem) {
const u8 control = ram[63];
if (control & 1) {
channel = 0;
int i = 0;
while (i < 63) {
u8 *cmd = &ram[i++];
u8 cmdlen = cmd[CMD_LEN] & 0x3F;
if (cmdlen == 0 || cmdlen == 0x3D) {
if (const u8 cmdlen = cmd[CMD_LEN] & 0x3F; cmdlen == 0 || cmdlen == 0x3D) {
channel++;
} else if (cmdlen == 0x3E) {
break;
} else if (cmdlen == 0x3F) {
continue;
} else {
u8 r = ram[i++];
const u8 r = ram[i++];
if (r == 0xFE) {
break;
}
u8 reslen = r & 0x3F;
const u8 reslen = r & 0x3F;
u8 *res = &ram[i + cmdlen];
switch (cmd[CMD_IDX]) {
@@ -225,7 +223,7 @@ void PIF::ProcessCommands(Mem &mem) {
case 2:
{
auto now = std::time(nullptr);
auto *gmtm = gmtime(&now);
const auto *gmtm = gmtime(&now);
res[0] = BCD_ENCODE(gmtm->tm_sec);
res[1] = BCD_ENCODE(gmtm->tm_min);
res[2] = BCD_ENCODE(gmtm->tm_hour) + 0x80;
@@ -321,7 +319,7 @@ void PIF::MempakWrite(u8 *cmd, u8 *res) {
void PIF::EepromRead(const u8 *cmd, u8 *res, const Mem &mem) const {
assert(mem.saveType == SAVE_EEPROM_4k || mem.saveType == SAVE_EEPROM_16k);
if (channel == 4) {
u8 offset = cmd[3];
const u8 offset = cmd[3];
if ((offset * 8) >= GetSaveSize(mem.saveType)) {
Util::panic("Out of range EEPROM read! offset: {:02X}", offset);
}
@@ -335,7 +333,7 @@ void PIF::EepromRead(const u8 *cmd, u8 *res, const Mem &mem) const {
void PIF::EepromWrite(const u8 *cmd, u8 *res, const Mem &mem) {
assert(mem.saveType == SAVE_EEPROM_4k || mem.saveType == SAVE_EEPROM_16k);
if (channel == 4) {
u8 offset = cmd[3];
const u8 offset = cmd[3];
if ((offset * 8) >= GetSaveSize(mem.saveType)) {
Util::panic("Out of range EEPROM write! offset: {:02X}", offset);
}
@@ -348,7 +346,7 @@ void PIF::EepromWrite(const u8 *cmd, u8 *res, const Mem &mem) {
}
}
void PIF::HLE(bool pal, CICType cicType) {
void PIF::HLE(const bool pal, const CICType cicType) const {
mem.Write<u32>(regs, PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);
switch (cicType) {
@@ -609,13 +607,13 @@ void PIF::HLE(bool pal, CICType cicType) {
regs.Write(22, (cicSeeds[cicType] >> 8) & 0xFF);
regs.cop0.Reset();
mem.Write<u32>(regs, 0x04300004, 0x01010101);
std::copy(mem.rom.cart.begin(), mem.rom.cart.begin() + 0x1000, mem.mmio.rsp.dmem.begin());
regs.SetPC32(s32(0xA4000040));
std::copy_n(mem.rom.cart.begin(), 0x1000, mem.mmio.rsp.dmem.begin());
regs.SetPC32(static_cast<s32>(0xA4000040));
}
void PIF::Execute() {
CICType cicType = mem.rom.cicType;
bool pal = mem.rom.pal;
void PIF::Execute() const {
const CICType cicType = mem.rom.cicType;
const bool pal = mem.rom.pal;
mem.Write<u32>(regs, PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);
switch (cicType) {
case UNKNOWN_CIC_TYPE:

View File

@@ -184,11 +184,11 @@ struct PIF {
void Reset();
void MaybeLoadMempak();
void LoadEeprom(SaveType, const std::string &);
void ProcessCommands(Mem &);
void ProcessCommands(const Mem &);
void InitDevices(SaveType);
void CICChallenge();
void Execute();
void HLE(bool pal, CICType cicType);
void Execute() const;
void HLE(bool pal, CICType cicType) const;
bool ReadButtons(u8 *);
void ControllerID(u8 *) const;
void MempakRead(const u8 *, u8 *);
@@ -214,26 +214,26 @@ struct PIF {
Mem &mem;
Registers &regs;
FORCE_INLINE u8 Read(u32 addr) {
[[nodiscard]] FORCE_INLINE u8 Read(u32 addr) const {
addr &= 0x7FF;
if (addr < 0x7c0)
return bootrom[addr];
return ram[addr & PIF_RAM_DSIZE];
}
FORCE_INLINE void Write(u32 addr, u8 val) {
FORCE_INLINE void Write(u32 addr, const u8 val) {
addr &= 0x7FF;
if (addr < 0x7c0)
return;
ram[addr & PIF_RAM_DSIZE] = val;
}
FORCE_INLINE AccessoryType GetAccessoryType() const {
[[nodiscard]] FORCE_INLINE AccessoryType GetAccessoryType() const {
if (channel >= 4 || joybusDevices[channel].type != JOYBUS_CONTROLLER) {
return ACCESSORY_NONE;
} else {
return joybusDevices[channel].accessoryType;
}
return joybusDevices[channel].accessoryType;
}
};
} // namespace n64

View File

@@ -96,7 +96,7 @@ bool PIF::ReadButtons(u8 *res) {
case JOYBUS_16KB_EEPROM:
case JOYBUS_CONTROLLER:
if (movie.IsLoaded()) {
Controller controller = movie.NextInputs();
const Controller controller = movie.NextInputs();
res[0] = controller.byte1;
res[1] = controller.byte2;
res[2] = controller.joyX;

View File

@@ -47,7 +47,7 @@ static_assert(sizeof(TASMovieHeader) == 1024);
struct MupenMovie {
MupenMovie() = default;
MupenMovie(const fs::path &);
explicit MupenMovie(const fs::path &);
bool Load(const fs::path &);
void Reset();
n64::Controller NextInputs();

View File

@@ -3,7 +3,7 @@
#include <core/mmio/SI.hpp>
namespace n64 {
SI::SI(Mem &mem, Registers &regs) : mem(mem), regs(regs), pif(mem, regs) { Reset(); }
SI::SI(Mem &mem, Registers &regs) : pif(mem, regs), mem(mem), regs(regs) { Reset(); }
void SI::Reset() {
status.raw = 0;

View File

@@ -27,7 +27,7 @@ struct SI {
u32 pifAddr{};
bool toDram = false;
auto Read(u32) const -> u32;
[[nodiscard]] auto Read(u32) const -> u32;
void Write(u32, u32);
template <bool toDram>
void DMA();

View File

@@ -24,7 +24,7 @@ void VI::Reset() {
swaps = {};
}
u32 VI::Read(u32 paddr) const {
u32 VI::Read(const u32 paddr) const {
switch (paddr) {
case 0x04400000:
return status.raw;
@@ -59,7 +59,7 @@ u32 VI::Read(u32 paddr) const {
}
}
void VI::Write(u32 paddr, u32 val) {
void VI::Write(const u32 paddr, const u32 val) {
switch (paddr) {
case 0x04400000:
status.raw = val;
@@ -67,7 +67,7 @@ void VI::Write(u32 paddr, u32 val) {
break;
case 0x04400004:
{
u32 masked = val & 0xFFFFFF;
const u32 masked = val & 0xFFFFFF;
if (origin != masked) {
swaps++;
}

View File

@@ -43,7 +43,7 @@ void Cop0::Reset() {
openbus = {};
}
u32 Cop0::GetReg32(u8 addr) {
u32 Cop0::GetReg32(const u8 addr) {
switch (addr) {
case COP0_REG_INDEX:
return index.raw & INDEX_MASK;
@@ -108,7 +108,7 @@ u32 Cop0::GetReg32(u8 addr) {
}
}
u64 Cop0::GetReg64(u8 addr) const {
u64 Cop0::GetReg64(const u8 addr) const {
switch (addr) {
case COP0_REG_ENTRYLO0:
return entryLo0.raw;
@@ -145,7 +145,7 @@ u64 Cop0::GetReg64(u8 addr) const {
}
}
void Cop0::SetReg32(u8 addr, u32 value) {
void Cop0::SetReg32(const u8 addr, const u32 value) {
openbus = value & 0xFFFFFFFF;
switch (addr) {
case COP0_REG_INDEX:
@@ -241,7 +241,7 @@ void Cop0::SetReg32(u8 addr, u32 value) {
}
}
void Cop0::SetReg64(u8 addr, u64 value) {
void Cop0::SetReg64(const u8 addr, const u64 value) {
openbus = value;
switch (addr) {
case COP0_REG_ENTRYLO0:
@@ -286,24 +286,23 @@ void Cop0::SetReg64(u8 addr, u64 value) {
}
}
static FORCE_INLINE u64 getVPN(u64 addr, u64 pageMask) {
u64 mask = pageMask | 0x1fff;
u64 vpn = (addr & 0xFFFFFFFFFF) | ((addr >> 22) & 0x30000000000);
static FORCE_INLINE u64 getVPN(const u64 addr, const u64 pageMask) {
const u64 mask = pageMask | 0x1fff;
const u64 vpn = addr & 0xFFFFFFFFFF | addr >> 22 & 0x30000000000;
return vpn & ~mask;
}
TLBEntry *Cop0::TLBTryMatch(u64 vaddr, int *match) {
TLBEntry *Cop0::TLBTryMatch(const u64 vaddr, int *match) const {
for (int i = 0; i < 32; i++) {
TLBEntry *entry = &regs.cop0.tlb[i];
if (entry->initialized) {
u64 entry_vpn = getVPN(entry->entryHi.raw, entry->pageMask.raw);
u64 vaddr_vpn = getVPN(vaddr, entry->pageMask.raw);
if (TLBEntry *entry = &regs.cop0.tlb[i]; entry->initialized) {
const u64 entry_vpn = getVPN(entry->entryHi.raw, entry->pageMask.raw);
const u64 vaddr_vpn = getVPN(vaddr, entry->pageMask.raw);
bool vpn_match = entry_vpn == vaddr_vpn;
bool asid_match = entry->global || (regs.cop0.entryHi.asid == entry->entryHi.asid);
const bool vpn_match = entry_vpn == vaddr_vpn;
if (vpn_match && asid_match) {
if (const bool asid_match = entry->global || regs.cop0.entryHi.asid == entry->entryHi.asid;
vpn_match && asid_match) {
if (match) {
*match = i;
}
@@ -315,15 +314,15 @@ TLBEntry *Cop0::TLBTryMatch(u64 vaddr, int *match) {
return nullptr;
}
bool Cop0::ProbeTLB(TLBAccessType access_type, u64 vaddr, u32 &paddr, int *match) {
TLBEntry *entry = TLBTryMatch(vaddr, match);
bool Cop0::ProbeTLB(const TLBAccessType accessType, const u64 vaddr, u32 &paddr, int *match) const {
const TLBEntry *entry = TLBTryMatch(vaddr, match);
if (!entry) {
regs.cop0.tlbError = MISS;
return false;
}
u32 mask = (entry->pageMask.mask << 12) | 0xFFF;
u32 odd = vaddr & (mask + 1);
const u32 mask = entry->pageMask.mask << 12 | 0xFFF;
const u32 odd = vaddr & (mask + 1);
u32 pfn;
if (!odd) {
@@ -332,7 +331,7 @@ bool Cop0::ProbeTLB(TLBAccessType access_type, u64 vaddr, u32 &paddr, int *match
return false;
}
if (access_type == STORE && !entry->entryLo0.d) {
if (accessType == STORE && !entry->entryLo0.d) {
regs.cop0.tlbError = MODIFICATION;
return false;
}
@@ -344,7 +343,7 @@ bool Cop0::ProbeTLB(TLBAccessType access_type, u64 vaddr, u32 &paddr, int *match
return false;
}
if (access_type == STORE && !entry->entryLo1.d) {
if (accessType == STORE && !entry->entryLo1.d) {
regs.cop0.tlbError = MODIFICATION;
return false;
}
@@ -352,14 +351,13 @@ bool Cop0::ProbeTLB(TLBAccessType access_type, u64 vaddr, u32 &paddr, int *match
pfn = entry->entryLo1.pfn;
}
paddr = (pfn << 12) | (vaddr & mask);
paddr = pfn << 12 | vaddr & mask;
return true;
}
FORCE_INLINE bool Is64BitAddressing(Cop0 &cp0, u64 addr) {
u8 region = (addr >> 62) & 3;
switch (region) {
FORCE_INLINE bool Is64BitAddressing(const Cop0 &cp0, const u64 addr) {
switch (addr >> 62 & 3) {
case 0b00:
return cp0.status.ux;
case 0b01:
@@ -371,8 +369,8 @@ FORCE_INLINE bool Is64BitAddressing(Cop0 &cp0, u64 addr) {
}
}
void Cop0::FireException(ExceptionCode code, int cop, s64 pc) {
bool old_exl = regs.cop0.status.exl;
void Cop0::FireException(const ExceptionCode code, const int cop, s64 pc) const {
const bool old_exl = regs.cop0.status.exl;
if (!regs.cop0.status.exl) {
if ((regs.cop0.cause.branchDelay = regs.prevDelaySlot)) {
@@ -424,18 +422,18 @@ void Cop0::FireException(ExceptionCode code, int cop, s64 pc) {
regs.cop0.Update();
}
void Cop0::HandleTLBException(u64 vaddr) {
u64 vpn2 = (vaddr >> 13) & 0x7FFFF;
u64 xvpn2 = (vaddr >> 13) & 0x7FFFFFF;
void Cop0::HandleTLBException(const u64 vaddr) const {
const u64 vpn2 = vaddr >> 13 & 0x7FFFF;
const u64 xvpn2 = vaddr >> 13 & 0x7FFFFFF;
regs.cop0.badVaddr = vaddr;
regs.cop0.context.badvpn2 = vpn2;
regs.cop0.xcontext.badvpn2 = xvpn2;
regs.cop0.xcontext.r = (vaddr >> 62) & 3;
regs.cop0.xcontext.r = vaddr >> 62 & 3;
regs.cop0.entryHi.vpn2 = xvpn2;
regs.cop0.entryHi.r = (vaddr >> 62) & 3;
regs.cop0.entryHi.r = vaddr >> 62 & 3;
}
ExceptionCode Cop0::GetTLBExceptionCode(TLBError error, TLBAccessType accessType) {
ExceptionCode Cop0::GetTLBExceptionCode(const TLBError error, const TLBAccessType accessType) {
switch (error) {
case NONE:
Util::panic("Getting TLB exception with error NONE");
@@ -448,6 +446,7 @@ ExceptionCode Cop0::GetTLBExceptionCode(TLBError error, TLBAccessType accessType
return accessType == LOAD ? ExceptionCode::AddressErrorLoad : ExceptionCode::AddressErrorStore;
default:
Util::panic("Getting TLB exception for unknown error code! ({})", static_cast<u8>(error));
return {};
}
}
@@ -467,9 +466,9 @@ template void Cop0::decode<JIT>(JIT &, u32);
void Cop0::decodeJIT(JIT &cpu, u32 instr) {}
void Cop0::decodeInterp(u32 instr) {
u8 mask_cop = (instr >> 21) & 0x1F;
u8 mask_cop2 = instr & 0x3F;
void Cop0::decodeInterp(const u32 instr) {
const u8 mask_cop = instr >> 21 & 0x1F;
const u8 mask_cop2 = instr & 0x3F;
switch (mask_cop) {
case 0x00:
mfc0(instr);
@@ -510,13 +509,17 @@ void Cop0::decodeInterp(u32 instr) {
}
}
bool Cop0::MapVAddr(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
bool Cop0::MapVAddr(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) {
if (regs.cop0.is64BitAddressing) [[unlikely]] {
if (regs.cop0.kernelMode) [[likely]] {
return MapVAddr64(accessType, vaddr, paddr);
} else if (regs.cop0.userMode) {
}
if (regs.cop0.userMode) {
return UserMapVAddr64(accessType, vaddr, paddr);
} else if (regs.cop0.supervisorMode) {
}
if (regs.cop0.supervisorMode) {
Util::panic("Supervisor mode memory access, 64 bit mode");
} else {
Util::panic("Unknown mode! This should never happen!");
@@ -524,9 +527,13 @@ bool Cop0::MapVAddr(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
} else {
if (regs.cop0.kernelMode) [[likely]] {
return MapVAddr32(accessType, vaddr, paddr);
} else if (regs.cop0.userMode) {
}
if (regs.cop0.userMode) {
return UserMapVAddr32(accessType, vaddr, paddr);
} else if (regs.cop0.supervisorMode) {
}
if (regs.cop0.supervisorMode) {
Util::panic("Supervisor mode memory access, 32 bit mode");
} else {
Util::panic("Unknown mode! This should never happen!");
@@ -534,7 +541,7 @@ bool Cop0::MapVAddr(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
}
}
bool Cop0::UserMapVAddr32(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
bool Cop0::UserMapVAddr32(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) const {
switch (vaddr) {
case VREGION_KUSEG:
return ProbeTLB(accessType, s64(s32(vaddr)), paddr, nullptr);
@@ -544,8 +551,8 @@ bool Cop0::UserMapVAddr32(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
}
}
bool Cop0::MapVAddr32(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
switch ((u32(vaddr) >> 29) & 7) {
bool Cop0::MapVAddr32(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) const {
switch (u32(vaddr) >> 29 & 7) {
case 0 ... 3:
case 7:
return ProbeTLB(accessType, s64(s32(vaddr)), paddr, nullptr);
@@ -561,7 +568,7 @@ bool Cop0::MapVAddr32(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
return false;
}
bool Cop0::UserMapVAddr64(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
bool Cop0::UserMapVAddr64(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) const {
switch (vaddr) {
case VREGION_XKUSEG:
return ProbeTLB(accessType, vaddr, paddr, nullptr);
@@ -571,7 +578,7 @@ bool Cop0::UserMapVAddr64(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
}
}
bool Cop0::MapVAddr64(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
bool Cop0::MapVAddr64(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) const {
switch (vaddr) {
case VREGION_XKUSEG:
case VREGION_XKSSEG:
@@ -581,15 +588,13 @@ bool Cop0::MapVAddr64(TLBAccessType accessType, u64 vaddr, u32 &paddr) {
if (!regs.cop0.kernelMode) {
Util::panic("Access to XKPHYS address 0x{:016X} when outside kernel mode!", vaddr);
}
u8 high_two_bits = (vaddr >> 62) & 0b11;
if (high_two_bits != 0b10) {
if (const u8 high_two_bits = (vaddr >> 62) & 0b11; high_two_bits != 0b10) {
Util::panic("Access to XKPHYS address 0x{:016X} with high two bits != 0b10!", vaddr);
}
u8 subsegment = (vaddr >> 59) & 0b11;
const u8 subsegment = (vaddr >> 59) & 0b11;
bool cached = subsegment != 2; // do something with this eventually
// If any bits in the range of 58:32 are set, the address is invalid.
bool valid = (vaddr & 0x07FFFFFF00000000) == 0;
if (!valid) {
if (const bool valid = (vaddr & 0x07FFFFFF00000000) == 0; !valid) {
regs.cop0.tlbError = DISALLOWED_ADDRESS;
return false;
}

View File

@@ -240,9 +240,9 @@ struct Cop0 {
s64 openbus{};
template <class T>
void decode(T &, u32);
FORCE_INLINE u32 GetRandom() {
[[nodiscard]] FORCE_INLINE u32 GetRandom() const {
u32 val = rand();
auto wired_ = GetWired();
const auto wired_ = GetWired();
u32 lower, upper;
if (wired_ > 31) {
lower = 0;
@@ -257,7 +257,7 @@ struct Cop0 {
}
FORCE_INLINE void Update() {
bool exception = status.exl || status.erl;
const bool exception = status.exl || status.erl;
kernelMode = exception || status.ksu == 0;
supervisorMode = !exception && status.ksu == 1;
@@ -267,17 +267,17 @@ struct Cop0 {
enum TLBAccessType { LOAD, STORE };
bool ProbeTLB(TLBAccessType access_type, u64 vaddr, u32 &paddr, int *match);
void FireException(ExceptionCode code, int cop, s64 pc);
bool ProbeTLB(TLBAccessType accessType, u64 vaddr, u32 &paddr, int *match) const;
void FireException(ExceptionCode code, int cop, s64 pc) const;
bool MapVAddr(TLBAccessType accessType, u64 vaddr, u32 &paddr);
bool UserMapVAddr32(TLBAccessType accessType, u64 vaddr, u32 &paddr);
bool MapVAddr32(TLBAccessType accessType, u64 vaddr, u32 &paddr);
bool UserMapVAddr64(TLBAccessType accessType, u64 vaddr, u32 &paddr);
bool MapVAddr64(TLBAccessType accessType, u64 vaddr, u32 &paddr);
bool UserMapVAddr32(TLBAccessType accessType, u64 vaddr, u32 &paddr) const;
bool MapVAddr32(TLBAccessType accessType, u64 vaddr, u32 &paddr) const;
bool UserMapVAddr64(TLBAccessType accessType, u64 vaddr, u32 &paddr) const;
bool MapVAddr64(TLBAccessType accessType, u64 vaddr, u32 &paddr) const;
TLBEntry *TLBTryMatch(u64 vaddr, int *match);
void HandleTLBException(u64 vaddr);
ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType access_type);
TLBEntry *TLBTryMatch(u64 vaddr, int *match) const;
void HandleTLBException(u64 vaddr) const;
static ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType accessType);
private:
Registers &regs;

View File

@@ -26,9 +26,9 @@ template void Cop1::decode<JIT>(JIT &, u32);
void Cop1::decodeInterp(Interpreter &cpu, u32 instr) {
u8 mask_sub = (instr >> 21) & 0x1F;
u8 mask_fun = instr & 0x3F;
u8 mask_branch = (instr >> 16) & 0x1F;
const u8 mask_sub = (instr >> 21) & 0x1F;
const u8 mask_fun = instr & 0x3F;
const u8 mask_branch = (instr >> 16) & 0x1F;
switch (mask_sub) {
// 000r_rccc
case 0x00:

View File

@@ -131,9 +131,9 @@ struct Cop1 {
template <typename T>
bool CheckResult(T &);
template <typename T>
bool CheckArg(T &);
bool CheckArg(T);
template <typename T>
bool CheckArgs(T &, T &);
bool CheckArgs(T, T);
template <typename T>
bool isqnan(T);
@@ -141,9 +141,9 @@ struct Cop1 {
bool XORDERED(T fs, T ft);
template <typename T>
bool CheckCVTArg(float &f);
bool CheckCVTArg(float f);
template <typename T>
bool CheckCVTArg(double &f);
bool CheckCVTArg(double f);
template <bool cvt = false>
bool TestExceptions();
@@ -156,11 +156,11 @@ struct Cop1 {
private:
template <typename T>
auto FGR_T(Cop0Status &, u32) -> T &;
auto FGR_T(const Cop0Status &, u32) -> T &;
template <typename T>
auto FGR_S(Cop0Status &, u32) -> T &;
auto FGR_S(const Cop0Status &, u32) -> T &;
template <typename T>
auto FGR_D(Cop0Status &, u32) -> T &;
auto FGR_D(const Cop0Status &, u32) -> T &;
void decodeInterp(Interpreter &, u32);
void decodeJIT(JIT &, u32);
void absd(u32 instr);

View File

@@ -3,13 +3,13 @@
#include <log.hpp>
namespace n64 {
void Cop0::mtc0(u32 instr) { SetReg32(RD(instr), regs.Read<u32>(RT(instr))); }
void Cop0::mtc0(const u32 instr) { SetReg32(RD(instr), regs.Read<u32>(RT(instr))); }
void Cop0::dmtc0(u32 instr) { SetReg64(RD(instr), regs.Read<u64>(RT(instr))); }
void Cop0::dmtc0(const u32 instr) { SetReg64(RD(instr), regs.Read<u64>(RT(instr))); }
void Cop0::mfc0(u32 instr) { regs.Write(RT(instr), s32(GetReg32(RD(instr)))); }
void Cop0::mfc0(const u32 instr) { regs.Write(RT(instr), s32(GetReg32(RD(instr)))); }
void Cop0::dmfc0(u32 instr) const { regs.Write(RT(instr), s64(GetReg64(RD(instr)))); }
void Cop0::dmfc0(const u32 instr) const { regs.Write(RT(instr), s64(GetReg64(RD(instr)))); }
void Cop0::eret() {
if (status.erl) {
@@ -29,7 +29,7 @@ void Cop0::tlbr() {
Util::panic("TLBR with TLB index {}", index.i);
}
TLBEntry entry = tlb[index.i];
const TLBEntry entry = tlb[index.i];
entryHi.raw = entry.entryHi.raw;
entryLo0.raw = entry.entryLo0.raw & 0x3FFFFFFF;
@@ -40,10 +40,10 @@ void Cop0::tlbr() {
pageMask.raw = entry.pageMask.raw;
}
void Cop0::tlbw(int index_) {
void Cop0::tlbw(const int index_) {
PageMask page_mask{};
page_mask = pageMask;
u32 top = page_mask.mask & 0xAAA;
const u32 top = page_mask.mask & 0xAAA;
page_mask.mask = top | (top >> 1);
if (index_ >= 32) {
@@ -63,8 +63,7 @@ void Cop0::tlbw(int index_) {
void Cop0::tlbp() {
int match = -1;
TLBEntry *entry = TLBTryMatch(entryHi.raw, &match);
if (entry && match >= 0) {
if (const TLBEntry *entry = TLBTryMatch(entryHi.raw, &match); entry && match >= 0) {
index.raw = match;
} else {
index.raw = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,8 @@
#include <log.hpp>
namespace n64 {
FORCE_INLINE void special(MI &mi, Registers &regs, RSP &rsp, u32 instr) {
u8 mask = instr & 0x3f;
// Util::print("rsp special {:02X}", mask);
switch (mask) {
FORCE_INLINE void special(MI &mi, RSP &rsp, const u32 instr) {
switch (const u8 mask = instr & 0x3f) {
case 0x00:
if (instr != 0) {
rsp.sll(instr);
@@ -73,31 +71,27 @@ FORCE_INLINE void special(MI &mi, Registers &regs, RSP &rsp, u32 instr) {
}
}
FORCE_INLINE void regimm(RSP &rsp, u32 instr) {
u8 mask = ((instr >> 16) & 0x1F);
// Util::print("rsp regimm {:02X}", mask);
switch (mask) {
FORCE_INLINE void regimm(RSP &rsp, const u32 instr) {
switch (const u8 mask = instr >> 16 & 0x1F) {
case 0x00:
rsp.b(instr, (s32)rsp.gpr[RS(instr)] < 0);
rsp.b(instr, rsp.gpr[RS(instr)] < 0);
break;
case 0x01:
rsp.b(instr, (s32)rsp.gpr[RS(instr)] >= 0);
rsp.b(instr, rsp.gpr[RS(instr)] >= 0);
break;
case 0x10:
rsp.blink(instr, (s32)rsp.gpr[RS(instr)] < 0);
rsp.blink(instr, rsp.gpr[RS(instr)] < 0);
break;
case 0x11:
rsp.blink(instr, (s32)rsp.gpr[RS(instr)] >= 0);
rsp.blink(instr, rsp.gpr[RS(instr)] >= 0);
break;
default:
Util::panic("Unhandled RSP regimm instruction ({:05b})", mask);
}
}
FORCE_INLINE void lwc2(RSP &rsp, u32 instr) {
u8 mask = (instr >> 11) & 0x1F;
// Util::print("lwc2 {:02X}", mask);
switch (mask) {
FORCE_INLINE void lwc2(RSP &rsp, const u32 instr) {
switch (const u8 mask = instr >> 11 & 0x1F) {
case 0x00:
rsp.lbv(instr);
break;
@@ -138,10 +132,8 @@ FORCE_INLINE void lwc2(RSP &rsp, u32 instr) {
}
}
FORCE_INLINE void swc2(RSP &rsp, u32 instr) {
u8 mask = (instr >> 11) & 0x1F;
// Util::print("swc2 {:02X}", mask);
switch (mask) {
FORCE_INLINE void swc2(RSP &rsp, const u32 instr) {
switch (const u8 mask = instr >> 11 & 0x1F) {
case 0x00:
rsp.sbv(instr);
break;
@@ -183,13 +175,11 @@ FORCE_INLINE void swc2(RSP &rsp, u32 instr) {
}
}
FORCE_INLINE void cop2(RSP &rsp, u32 instr) {
u8 mask = instr & 0x3F;
u8 mask_sub = (instr >> 21) & 0x1F;
// Util::print("Cop2 {:02X}", mask);
switch (mask) {
FORCE_INLINE void cop2(RSP &rsp, const u32 instr) {
const u8 mask_sub = instr >> 21 & 0x1F;
switch (const u8 mask = instr & 0x3F) {
case 0x00:
if ((instr >> 25) & 1) {
if (instr >> 25 & 1) {
rsp.vmulf(instr);
} else {
switch (mask_sub) {
@@ -355,14 +345,13 @@ FORCE_INLINE void cop2(RSP &rsp, u32 instr) {
}
}
FORCE_INLINE void cop0(Registers &regs, Mem &mem, u32 instr) {
u8 mask = (instr >> 21) & 0x1F;
FORCE_INLINE void cop0(Mem &mem, const u32 instr) {
MMIO &mmio = mem.mmio;
RSP &rsp = mmio.rsp;
RDP &rdp = mmio.rdp;
// Util::print("Cop0 {:02X}", mask);
if ((instr & 0x7FF) == 0) {
switch (mask) {
switch (const u8 mask = instr >> 21 & 0x1F) {
case 0x00:
rsp.mfc0(rdp, instr);
break;
@@ -377,14 +366,12 @@ FORCE_INLINE void cop0(Registers &regs, Mem &mem, u32 instr) {
}
}
void RSP::Exec(u32 instr) {
u8 mask = (instr >> 26) & 0x3F;
void RSP::Exec(const u32 instr) {
MMIO &mmio = mem.mmio;
MI &mi = mmio.mi;
// Util::print("RSP {:02X}", mask);
switch (mask) {
switch (const u8 mask = instr >> 26 & 0x3F) {
case 0x00:
special(mi, regs, *this, instr);
special(mi, *this, instr);
break;
case 0x01:
regimm(*this, instr);
@@ -396,16 +383,16 @@ void RSP::Exec(u32 instr) {
jal(instr);
break;
case 0x04:
b(instr, (s32)gpr[RT(instr)] == (s32)gpr[RS(instr)]);
b(instr, gpr[RT(instr)] == gpr[RS(instr)]);
break;
case 0x05:
b(instr, (s32)gpr[RT(instr)] != (s32)gpr[RS(instr)]);
b(instr, gpr[RT(instr)] != gpr[RS(instr)]);
break;
case 0x06:
b(instr, (s32)gpr[RS(instr)] <= 0);
b(instr, gpr[RS(instr)] <= 0);
break;
case 0x07:
b(instr, (s32)gpr[RS(instr)] > 0);
b(instr, gpr[RS(instr)] > 0);
break;
case 0x08:
case 0x09:
@@ -430,7 +417,7 @@ void RSP::Exec(u32 instr) {
lui(instr);
break;
case 0x10:
cop0(regs, mem, instr);
cop0(mem, instr);
break;
case 0x12:
cop2(*this, instr);

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
#include <AudioSettings.hpp>
AudioSettings::AudioSettings(nlohmann::json &settings) : settings(settings), QWidget(nullptr) {
AudioSettings::AudioSettings(nlohmann::json &settings) : QWidget(nullptr), settings(settings) {
lockChannels->setChecked(JSONGetField<bool>(settings, "audio", "lock"));
volumeL->setValue(JSONGetField<float>(settings, "audio", "volumeL") * 100);
volumeR->setValue(JSONGetField<float>(settings, "audio", "volumeR") * 100);

View File

@@ -6,7 +6,7 @@
#include <QLabel>
#include <QVBoxLayout>
class AudioSettings : public QWidget {
class AudioSettings final : public QWidget {
std::unique_ptr<QCheckBox> lockChannels = std::make_unique<QCheckBox>();
std::unique_ptr<QLabel> labelLock = std::make_unique<QLabel>("Lock channels:");
std::unique_ptr<QLabel> labelL = std::make_unique<QLabel>("Volume L");
@@ -17,7 +17,7 @@ class AudioSettings : public QWidget {
public:
std::unique_ptr<QSlider> volumeL = std::make_unique<QSlider>(Qt::Horizontal),
volumeR = std::make_unique<QSlider>(Qt::Horizontal);
AudioSettings(nlohmann::json &);
explicit AudioSettings(nlohmann::json &);
nlohmann::json &settings;
Q_SIGNALS:
void modified();

View File

@@ -2,7 +2,7 @@
#include <JSONUtils.hpp>
#include <log.hpp>
CPUSettings::CPUSettings(nlohmann::json &settings) : settings(settings), QWidget(nullptr) {
CPUSettings::CPUSettings(nlohmann::json &settings) : QWidget(nullptr), settings(settings) {
cpuTypes->addItems({
"Interpreter" //, "Dynamic Recompiler"
});

View File

@@ -5,13 +5,13 @@
#include <QLabel>
#include <QVBoxLayout>
class CPUSettings : public QWidget {
class CPUSettings final : public QWidget {
std::unique_ptr<QComboBox> cpuTypes = std::make_unique<QComboBox>();
std::unique_ptr<QLabel> label = std::make_unique<QLabel>("CPU type:");
std::unique_ptr<QVBoxLayout> mainLayout = std::make_unique<QVBoxLayout>();
Q_OBJECT
public:
CPUSettings(nlohmann::json &);
explicit CPUSettings(nlohmann::json &);
nlohmann::json &settings;
Q_SIGNALS:
void modified();

View File

@@ -4,9 +4,9 @@
class CodeModel final : public QAbstractTableModel {
Q_OBJECT
public:
~CodeModel() override {}
~CodeModel() override = default;
explicit CodeModel(QObject *parent = nullptr) {}
int rowCount(const QModelIndex &parent = QModelIndex()) const override { return 1; }
int columnCount(const QModelIndex &parent = QModelIndex()) const override { return 2; }
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { return {}; }
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override { return 1; }
[[nodiscard]] int columnCount(const QModelIndex &parent = QModelIndex()) const override { return 2; }
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { return {}; }
};

View File

@@ -6,7 +6,7 @@
#include <QVBoxLayout>
#include <CodeModel.hpp>
class Debugger : public QWidget {
class Debugger final : public QWidget {
std::unique_ptr<QDockWidget> disassembly = std::make_unique<QDockWidget>(),
cpuState = std::make_unique<QDockWidget>();
std::unique_ptr<QTreeView> codeView = std::make_unique<QTreeView>(disassembly.get()),

View File

@@ -9,7 +9,7 @@ namespace n64 {
struct Core;
}
class EmuThread : public QThread {
class EmuThread final : public QThread {
Q_OBJECT
RenderWidget &renderWidget;

View File

@@ -8,7 +8,7 @@
#include <QComboBox>
#include <QTimer>
class InputSettings : public QWidget {
class InputSettings final : public QWidget {
bool grabbing = false;
int whichGrabbing = -1;

View File

@@ -75,15 +75,15 @@ void KaizenQt::Quit() const noexcept {
QApplication::quit();
}
void KaizenQt::LoadTAS(const QString &fileName) const noexcept {
if (emuThread->core->LoadTAS(fs::path(fileName.toStdString()))) {
auto gameNameDB = emuThread->core->cpu->GetMem().rom.gameNameDB;
auto movieName = fs::path(fileName.toStdString()).stem().string();
void KaizenQt::LoadTAS(const QString &path) const noexcept {
if (emuThread->core->LoadTAS(fs::path(path.toStdString()))) {
const auto gameNameDB = emuThread->core->cpu->GetMem().rom.gameNameDB;
const auto movieName = fs::path(path.toStdString()).stem().string();
Util::RPC::GetInstance().Update(Util::RPC::MovieReplay, gameNameDB, movieName);
return;
}
Util::panic("Could not load TAS movie {}!", fileName.toStdString());
Util::panic("Could not load TAS movie {}!", path.toStdString());
}
void KaizenQt::keyPressEvent(QKeyEvent *e) {

View File

@@ -103,7 +103,7 @@ void MainWindow::Retranslate() {
void MainWindow::ConnectSignalsToSlots() noexcept {
connect(actionOpen.get(), &QAction::triggered, this, [this]() {
QString file_name = QFileDialog::getOpenFileName(
const QString file_name = QFileDialog::getOpenFileName(
this, "Nintendo 64 executable", QString(),
"All supported types (*.zip *.ZIP *.7z *.7Z *.rar *.RAR *.tar *.TAR *.n64 *.N64 *.v64 *.V64 *.z64 *.Z64)");

View File

@@ -12,11 +12,11 @@
#include <RenderWidget.hpp>
#include <Debugger.hpp>
class MainWindow : public QMainWindow {
class MainWindow final : public QMainWindow {
Q_OBJECT
public:
MainWindow(const std::shared_ptr<n64::Core> &) noexcept;
explicit MainWindow(const std::shared_ptr<n64::Core> &) noexcept;
std::unique_ptr<QAction> actionOpenDebuggerWindow{};
std::unique_ptr<QAction> actionAbout{};

View File

@@ -10,7 +10,7 @@ namespace n64 {
struct Core;
}
struct QtInstanceFactory : Vulkan::InstanceFactory {
struct QtInstanceFactory final : Vulkan::InstanceFactory {
VkInstance create_instance(const VkInstanceCreateInfo *info) override {
handle.setApiVersion({1, 3, 0});
QByteArrayList exts;
@@ -36,7 +36,7 @@ struct QtInstanceFactory : Vulkan::InstanceFactory {
QVulkanInstance handle;
};
class QtParallelRdpWindowInfo : public ParallelRDP::WindowInfo {
class QtParallelRdpWindowInfo final : public ParallelRDP::WindowInfo {
public:
explicit QtParallelRdpWindowInfo(QWindow *window) : window(window) {}
CoordinatePair get_window_size() override {
@@ -56,8 +56,8 @@ public:
const auto &extensions = window->vulkanInstance()->supportedExtensions();
vec.reserve(extensions.size());
for (const auto &ext : extensions) {
vec.emplace_back(ext.name);
for (const auto &[name, _] : extensions) {
vec.emplace_back(name);
}
return vec;
@@ -96,7 +96,7 @@ private:
bool canPollEvents = true;
};
class RenderWidget : public QWidget {
class RenderWidget final : public QWidget {
public:
[[nodiscard]] VkInstance instance() const { return qtVkInstanceFactory->handle.vkInstance(); }
explicit RenderWidget(const std::shared_ptr<n64::Core> &);

View File

@@ -1,7 +1,7 @@
#include <SettingsWindow.hpp>
#include <fmt/core.h>
std::string savePath = "";
std::string savePath;
SettingsWindow::SettingsWindow() : QWidget(nullptr) {
settings = JSONOpenOrCreate("resources/settings.json");

View File

@@ -11,7 +11,7 @@
#include <QGroupBox>
#include <QVBoxLayout>
class SettingsWindow : public QWidget {
class SettingsWindow final : public QWidget {
std::unique_ptr<QPushButton> cancel = std::make_unique<QPushButton>("Cancel");
std::unique_ptr<QPushButton> apply = std::make_unique<QPushButton>("Apply");
std::unique_ptr<QFileIconProvider> iconProv = std::make_unique<QFileIconProvider>();
@@ -28,8 +28,8 @@ public:
SettingsWindow();
void hideEvent(QHideEvent *event) override { emit gotClosed(); }
void showEvent(QShowEvent *event) override { emit gotOpened(); }
float getVolumeL() { return float(audioSettings->volumeL->value()) / 100.f; }
float getVolumeR() { return float(audioSettings->volumeR->value()) / 100.f; }
[[nodiscard]] float getVolumeL() const { return static_cast<float>(audioSettings->volumeL->value()) / 100.f; }
[[nodiscard]] float getVolumeR() const { return static_cast<float>(audioSettings->volumeR->value()) / 100.f; }
std::array<Qt::Key, 18> keyMap{};
nlohmann::json settings;

View File

@@ -3,8 +3,8 @@
#include <QCommandLineParser>
int main(int argc, char **argv) {
QApplication app(argc, argv);
app.setStyle("fusion");
const QApplication app(argc, argv);
QApplication::setStyle("fusion");
QCoreApplication::setOrganizationName("kaizen");
QCoreApplication::setApplicationName("Kaizen");
QCommandLineParser parser;
@@ -13,7 +13,7 @@ int main(int argc, char **argv) {
parser.addOptions({{"rom", "Rom to launch from command-line", "path"}, {"movie", "Mupen Movie to replay", "path"}});
parser.process(app);
KaizenQt kaizenQt;
const KaizenQt kaizenQt;
if (parser.isSet("rom")) {
kaizenQt.LoadROM(parser.value("rom"));
if (parser.isSet("movie")) {
@@ -21,5 +21,5 @@ int main(int argc, char **argv) {
}
}
return app.exec();
return QApplication::exec();
}

View File

@@ -2,7 +2,6 @@
#include <common.hpp>
#include <cstring>
#include <functional>
#include <log.hpp>
#include <byteswap.hpp>
namespace Util {
@@ -17,7 +16,7 @@ static FORCE_INLINE std::vector<u8> IntegralToBuffer(const T &val) {
}
template <typename T>
static FORCE_INLINE T ReadAccess(const u8 *data, const u32 index) {
static constexpr FORCE_INLINE T ReadAccess(const u8 *data, const u32 index) {
if constexpr (sizeof(T) == 8) {
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
@@ -29,7 +28,7 @@ static FORCE_INLINE T ReadAccess(const u8 *data, const u32 index) {
}
template <typename T>
static FORCE_INLINE T ReadAccess(const std::vector<u8> &data, const u32 index) {
static constexpr FORCE_INLINE T ReadAccess(const std::vector<u8> &data, const u32 index) {
if constexpr (sizeof(T) == 8) {
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
@@ -41,7 +40,7 @@ static FORCE_INLINE T ReadAccess(const std::vector<u8> &data, const u32 index) {
}
template <typename T, size_t Size>
static FORCE_INLINE T ReadAccess(const std::array<u8, Size> &data, const u32 index) {
static constexpr FORCE_INLINE T ReadAccess(const std::array<u8, Size> &data, const u32 index) {
if constexpr (sizeof(T) == 8) {
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
@@ -53,7 +52,7 @@ static FORCE_INLINE T ReadAccess(const std::array<u8, Size> &data, const u32 ind
}
template <typename T, size_t Size>
static FORCE_INLINE void WriteAccess(std::array<u8, Size> &data, const u32 index, const T val) {
static constexpr FORCE_INLINE void WriteAccess(std::array<u8, Size> &data, const u32 index, const T val) {
if constexpr (sizeof(T) == 8) {
const u32 hi = val >> 32;
const u32 lo = val;
@@ -66,7 +65,7 @@ static FORCE_INLINE void WriteAccess(std::array<u8, Size> &data, const u32 index
}
template <typename T>
static FORCE_INLINE void WriteAccess(std::vector<u8> &data, const u32 index, const T val) {
static constexpr FORCE_INLINE void WriteAccess(std::vector<u8> &data, const u32 index, const T val) {
if constexpr (sizeof(T) == 8) {
const u32 hi = val >> 32;
const u32 lo = val;
@@ -79,7 +78,7 @@ static FORCE_INLINE void WriteAccess(std::vector<u8> &data, const u32 index, con
}
template <typename T>
static FORCE_INLINE void WriteAccess(u8 *data, const u32 index, const T val) {
static constexpr FORCE_INLINE void WriteAccess(u8 *data, const u32 index, const T val) {
if constexpr (sizeof(T) == 8) {
const u32 hi = val >> 32;
const u32 lo = val;
@@ -92,7 +91,7 @@ static FORCE_INLINE void WriteAccess(u8 *data, const u32 index, const T val) {
}
template <typename T>
static FORCE_INLINE void SwapBuffer(std::vector<u8> &data) {
static constexpr FORCE_INLINE void SwapBuffer(std::vector<u8> &data) {
for (size_t i = 0; i < data.size(); i += sizeof(T)) {
const T original = *reinterpret_cast<T *>(&data[i]);
*reinterpret_cast<T *>(&data[i]) = bswap(original);
@@ -100,7 +99,7 @@ static FORCE_INLINE void SwapBuffer(std::vector<u8> &data) {
}
template <typename T, size_t Size>
static FORCE_INLINE void SwapBuffer(std::array<u8, Size> &data) {
static constexpr FORCE_INLINE void SwapBuffer(std::array<u8, Size> &data) {
for (size_t i = 0; i < data.size(); i += sizeof(T)) {
const T original = *reinterpret_cast<T *>(&data[i]);
*reinterpret_cast<T *>(&data[i]) = bswap(original);