mirror of
https://github.com/liuk7071/ChonkyStation.git
synced 2024-05-09 16:14:09 -04:00
[GPU & other] Variable size rectangles & diff tool for the cpu
This commit is contained in:
parent
c9e13e0b33
commit
76f8db38a1
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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"); }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
enum class GP0Command {
|
||||
NOP = 0x00,
|
||||
ClearCache = 0x01,
|
||||
FillVRAM = 0x02,
|
||||
UploadTexture = 0xA0,
|
||||
ReadVRAM = 0xC0,
|
||||
DrawModeSetting = 0xE1,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
7
test/CMakeLists.txt
Normal 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
38
test/diff/diff.cpp
Normal 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
16
test/diff/diff.hpp
Normal 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
|
Loading…
Reference in a new issue