[GPU & other] Variable size rectangles & diff tool for the cpu

This commit is contained in:
liuk7071 2023-12-29 20:25:33 +01:00
parent c9e13e0b33
commit 76f8db38a1
11 changed files with 116 additions and 10 deletions

View file

@ -4,6 +4,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
project(ChonkyStation)
add_subdirectory(external)
add_subdirectory(test)
add_subdirectory(src)
include_directories(src/common)
@ -14,14 +15,17 @@ include_directories(src/gpu)
include_directories(src/cdrom)
include_directories(src/scheduler)
include_directories(test)
include_directories(external/Dolphin)
include_directories(external/Panda3DS)
source_group("Header Files/Test" FILES ${TEST_HEADER_FILES})
source_group("Header Files/External/Dolphin" FILES ${DOLPHIN_HEADER_FILES})
source_group("Header Files/External/Panda3DS" FILES ${PANDA3DS_HEADER_FILES})
add_compile_definitions(SDL_MAIN_HANDLED)
add_executable(ChonkyStation ${SOURCE_FILES} ${HEADER_FILES} ${DOLPHIN_HEADER_FILES} ${PANDA3DS_HEADER_FILES})
add_executable(ChonkyStation ${SOURCE_FILES} ${HEADER_FILES} ${TEST_SOURCE_FILES} ${TEST_HEADER_FILES} ${DOLPHIN_HEADER_FILES} ${PANDA3DS_HEADER_FILES})
target_include_directories(ChonkyStation PRIVATE ${SDL2_INCLUDE_DIR})
target_link_libraries(ChonkyStation PRIVATE fmt SDL2-static)

View file

@ -1,8 +1,8 @@
#include "interpreter.hpp"
//#define DONT_CRASH_ON_BAD_READWRITE
//#define DONT_CRASH_ON_BAD_JUMP
#define DONT_CRASH_ON_BAD_READWRITE
#define DONT_CRASH_ON_BAD_JUMP
void Interpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler) {
// Handle interrupts

View file

@ -68,6 +68,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
if (delay) { // branch delay slot
core->pc = jump - 4;
delay = false;
core->isDelaySlot = false;
}
// Quick and dirty hack. TODO: Replace this with a bitfield
@ -125,6 +126,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
jump = addr;
debug_log("jr %s\n", reg[rs].c_str());
delay = true;
core->isDelaySlot = true;
break;
}
case 0x09: {
@ -137,6 +139,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
jump = addr;
debug_log("jalr %s\n", reg[rs].c_str());
delay = true;
core->isDelaySlot = true;
break;
}
case 0x0C: {
@ -304,6 +307,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
if (signed_rs < 0) {
jump = (core->pc + 4) + (sign_extended_imm << 2);
delay = true;
core->isDelaySlot = true;
debug_log(" branched\n");
}
else { debug_log("\n"); }
@ -315,6 +319,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
if (signed_rs >= 0) {
jump = (core->pc + 4) + (sign_extended_imm << 2);
delay = true;
core->isDelaySlot = true;
debug_log(" branched\n");
}
else { debug_log("\n"); }
@ -326,6 +331,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
jump = (core->pc & 0xf0000000) | (jump_imm << 2);
debug_log("j 0x%.8x\n", jump_imm);
delay = true;
core->isDelaySlot = true;
break;
}
case 0x03: {
@ -333,6 +339,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
debug_log("jal 0x%.8x\n", jump_imm);
regs[0x1f] = core->pc + 8;
delay = true;
core->isDelaySlot = true;
break;
}
case 0x04: {
@ -340,6 +347,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
if (regs[rs] == regs[rt]) {
jump = (core->pc + 4) + (sign_extended_imm << 2);
delay = true;
core->isDelaySlot = true;
debug_log(" branched\n");
}
else { debug_log("\n"); }
@ -350,6 +358,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
if (regs[rs] != regs[rt]) {
jump = (core->pc + 4) + (sign_extended_imm << 2);
delay = true;
core->isDelaySlot = true;
debug_log(" branched\n");
}
else { debug_log("\n"); }
@ -360,6 +369,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
if (signed_rs <= 0) {
jump = (core->pc + 4) + (sign_extended_imm << 2);
delay = true;
core->isDelaySlot = true;
debug_log(" branched\n");
}
else { debug_log("\n"); }
@ -370,6 +380,7 @@ void OldInterpreter::step(CpuCore* core, Memory* mem, Disassembler* disassembler
if (signed_rs > 0) {
jump = (core->pc + 4) + (sign_extended_imm << 2);
delay = true;
core->isDelaySlot = true;
debug_log(" branched\n");
}
else { debug_log("\n"); }

View file

@ -54,6 +54,11 @@ void GPU::writeGp0(u32 data) {
if (paramsLeft == 0) {
if (!uploadingTexture) {
switch (fifo[0] >> 24) {
case (u32)GP0Command::FillVRAM: {
// TODO
hasCommand = false;
break;
}
case (u32)GP0Command::UploadTexture: {
uploadingTexture = true;
// Calculate size
@ -145,17 +150,23 @@ void GPU::writeGp0(u32 data) {
vert.u = fifo[idx] & 0xff;
vert.v = (fifo[idx++] >> 8) & 0xff;
}
// TODO: variable size
Helpers::debugAssert(rect.size != 0, "[FATAL] Unimplemented variable size rectangle\n");
// TODO: textured
Helpers::debugAssert(!rect.textured, "[FATAL] Unimplemented textured rectangle\n");
u16 width = 0;
u16 height = 0;
switch (rect.size) {
case 1: width = 1; height = 1; break;
case 2: width = 8; height = 8; break;
case 3: width = 16; height = 16; break;
if (rect.size == 0) {
width = fifo[idx] & 0xffff;
height = (fifo[idx++] >> 8) & 0xffff;
}
else {
switch (rect.size) {
case 1: width = 1; height = 1; break;
case 2: width = 8; height = 8; break;
case 3: width = 16; height = 16; break;
}
}
backend->drawRectUntextured(vert, width, height);
@ -248,6 +259,12 @@ void GPU::startCommand(u32 rawCommand) {
// Stubbed
break;
}
case (u32)GP0Command::FillVRAM: {
log("FillVRAM\n");
paramsLeft = 2;
hasCommand = true;
break;
}
case (u32)GP0Command::UploadTexture: {
log("UploadTexture\n");
paramsLeft = 2;

View file

@ -42,6 +42,7 @@ public:
enum class GP0Command {
NOP = 0x00,
ClearCache = 0x01,
FillVRAM = 0x02,
UploadTexture = 0xA0,
ReadVRAM = 0xC0,
DrawModeSetting = 0xE1,

View file

@ -2,6 +2,8 @@
#include <SDL.h>
#include "playstation.hpp"
#include <diff/diff.hpp>
int main(int argc, char** argv) {
if (argc < 2) Helpers::panic("Usage: ChonkyStation [bios path]\n");
@ -14,6 +16,10 @@ int main(int argc, char** argv) {
playstation.sideloadExecutable(argv[2]);
}
// Testing
//Test::Diff diffTest = Test::Diff(argv[1]);
//diffTest.doTest();
// SDL Window
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("ChonkyStation", 100, 100, 1024, 512, 0);

View file

@ -157,6 +157,9 @@ u32 Memory::read(u32 vaddr) {
else if (paddr == 0x1f8010f4) return dma->dicr;
// Timers
else if (Helpers::inRangeSized<u32>(paddr, (u32)MemoryBase::Timer, (u32)MemorySize::Timer)) return 0;
else if (paddr == 0x1f80101C) return 0x00070777; // Expansion 2 Delay/Size (usually 00070777h) (128 bytes, 8bit bus)
else
Helpers::dump("ramdump.bin", ram, 2_MB);
Helpers::panic("[ FATAL ] Unhandled read32 0x%08x (virtual 0x%08x) @ pc 0x%08x\n", paddr, vaddr, core->pc);

View file

@ -16,7 +16,7 @@ public:
mem.core = &cpu.core;
mem.loadBios(biosPath);
cpu.switchBackend(Cpu::Backend::Interpreter);
cpu.switchBackend(Cpu::Backend::OldInterpreter);
// Setup GPU scheduler events
scheduler.push(&gpu.scanlineEvent, scheduler.time + GPUConstants::cyclesPerScanline, &gpu);
@ -47,6 +47,7 @@ public:
u32 getPC() { return cpu.core.pc; }
u8* getRAM() { return mem.ram; }
u8* getVRAM() { return gpu.getVRAM(); }
u32* getGPRS() { return cpu.core.gprs; }
bool getVBLANKAndClear() {
bool temp = gpu.vblank;
gpu.vblank = false;
@ -55,6 +56,8 @@ public:
void VBLANK() { interrupt.raiseInterrupt(Interrupt::InterruptType::VBLANK); }
bool isInBIOS() { return Helpers::inRangeSized<u32>(cpu.core.pc, (u32)Memory::MemoryBase::BIOS, (u32)Memory::MemorySize::BIOS); }
void switchCpuBackend(Cpu::Backend backend) { cpu.switchBackend(backend); }
void loadExecutable(const fs::path path) {
auto binary = Helpers::readBinary(path);

7
test/CMakeLists.txt Normal file
View file

@ -0,0 +1,7 @@
set(TEST_SOURCE_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/diff/diff.cpp"
PARENT_SCOPE)
set(TEST_HEADER_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/diff/diff.hpp"
PARENT_SCOPE)

38
test/diff/diff.cpp Normal file
View file

@ -0,0 +1,38 @@
#include "diff.hpp"
using namespace Test;
Diff::Diff(const fs::path& biosPath) : p1(biosPath), p2(biosPath) {
p1.switchCpuBackend(Cpu::Backend::Interpreter);
p2.switchCpuBackend(Cpu::Backend::OldInterpreter);
}
void Diff::doTest() {
u32* gprs1 = p1.getGPRS();
u32* gprs2 = p2.getGPRS();
while (true) {
while (!p1.getVBLANKAndClear()) {
p1.step();
p2.step();
for (int i = 0; i < 32; i++) {
if (gprs1[i] != gprs2[i]) {
printf("r%d | 0x%08x != 0x%08x\n", i, gprs1[i], gprs2[i]);
exit(0);
}
}
if (p1.getPC() != p2.getPC()) {
printf("pc | 0x%08x != 0x%08x\n", p1.getPC(), p2.getPC());
Helpers::dump("ramp1.bin", p1.getRAM(), 2_MB);
Helpers::dump("ramp2.bin", p2.getRAM(), 2_MB);
exit(0);
}
}
p1.VBLANK();
p2.VBLANK();
}
}

16
test/diff/diff.hpp Normal file
View file

@ -0,0 +1,16 @@
#pragma once
#include <helpers.hpp>
#include "../../src/playstation.hpp"
namespace Test {
class Diff {
public:
Diff(const fs::path& biosPath);
void doTest();
private:
PlayStation p1;
PlayStation p2;
};
} // End namespace test