mirror of
https://github.com/JaCzekanski/Avocado.git
synced 2024-06-01 18:57:42 -04:00
gpu: started refactor
input: Changed digitalbutton threshold to lower value quiet warnings
This commit is contained in:
parent
0ec19f3bec
commit
883d912b32
|
@ -119,7 +119,6 @@ filter "action:gmake"
|
|||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wno-unused-parameter",
|
||||
"-Wno-macro-redefined",
|
||||
}
|
||||
|
||||
project "glad"
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include "config.h"
|
||||
#include "device/dma3Channel.h"
|
||||
#include "system.h"
|
||||
#include "utils/bcd.h"
|
||||
#include "utils/string.h"
|
||||
#include "device/dma3Channel.h"
|
||||
|
||||
// TODO: CDROM shouldn't know about DMA channels
|
||||
#define dma3 dynamic_cast<device::dma::dmaChannel::DMA3Channel*>(sys->dma->dma[3].get())
|
||||
|
@ -35,7 +35,7 @@ void CDROM::step() {
|
|||
if (mode.cddaReport && stat.play && reportcnt++ == 4000) {
|
||||
reportcnt = 0;
|
||||
// Report--> INT1(stat, track, index, mm / amm, ss + 80h / ass, sect / asect, peaklo, peakhi)
|
||||
auto pos = utils::Position(0,2,0);
|
||||
auto pos = utils::Position(0, 2, 0);
|
||||
|
||||
int track = 0;
|
||||
for (int i = 0; i < cue.getTrackCount(); i++) {
|
||||
|
@ -45,8 +45,6 @@ void CDROM::step() {
|
|||
}
|
||||
}
|
||||
|
||||
auto posInTrack = pos - cue.tracks[track].start;
|
||||
|
||||
CDROM_interrupt.push_back(1);
|
||||
writeResponse(stat._reg); // stat
|
||||
writeResponse(track); // track
|
||||
|
@ -342,7 +340,7 @@ void CDROM::cmdGetlocL() {
|
|||
}
|
||||
|
||||
void CDROM::cmdGetlocP() {
|
||||
auto pos = utils::Position(0,2,0);
|
||||
auto pos = utils::Position(0, 2, 0);
|
||||
|
||||
int track = 0;
|
||||
for (int i = 0; i < cue.getTrackCount(); i++) {
|
||||
|
|
|
@ -5,13 +5,13 @@ namespace device {
|
|||
namespace dma {
|
||||
namespace dmaChannel {
|
||||
class DMA2Channel : public DMAChannel {
|
||||
GPU *gpu = nullptr;
|
||||
gpu::GPU *gpu = nullptr;
|
||||
|
||||
uint32_t readDevice() override { return gpu->read(0); }
|
||||
void writeDevice(uint32_t data) override { gpu->write(0, data); }
|
||||
|
||||
public:
|
||||
DMA2Channel(int channel, System *sys, GPU *gpu) : DMAChannel(channel, sys), gpu(gpu) {}
|
||||
DMA2Channel(int channel, System *sys, gpu::GPU *gpu) : DMAChannel(channel, sys), gpu(gpu) {}
|
||||
};
|
||||
} // namespace dmaChannel
|
||||
} // namespace dma
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
#include "gpu.h"
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include "render.h"
|
||||
#include "render/render.h"
|
||||
#include "utils/logic.h"
|
||||
|
||||
namespace gpu {
|
||||
|
||||
const char* CommandStr[] = {"None", "FillRectangle", "Polygon", "Line", "Rectangle",
|
||||
"CopyCpuToVram1", "CopyCpuToVram2", "CopyVramToCpu", "CopyVramToVram", "Extra"};
|
||||
|
||||
GPU::GPU() { reset(); }
|
||||
|
||||
void GPU::reset() {
|
||||
irqRequest = false;
|
||||
displayDisable = true;
|
||||
|
@ -53,17 +57,17 @@ void GPU::drawPolygon(int16_t x[4], int16_t y[4], RGB c[4], TextureInfo t, bool
|
|||
for (int i : {0, 1, 2}) {
|
||||
v[i] = {{x[i], y[i]}, {c[i].r, c[i].g, c[i].b}, {t.uv[i].x, t.uv[i].y}, bitcount, {clutX, clutY}, {baseX, baseY}, flags};
|
||||
}
|
||||
drawTriangle(this, v);
|
||||
Render::drawTriangle(this, v);
|
||||
|
||||
if (isQuad) {
|
||||
for (int i : {1, 2, 3}) {
|
||||
v[i - 1] = {{x[i], y[i]}, {c[i].r, c[i].g, c[i].b}, {t.uv[i].x, t.uv[i].y}, bitcount, {clutX, clutY}, {baseX, baseY}, flags};
|
||||
}
|
||||
drawTriangle(this, v);
|
||||
Render::drawTriangle(this, v);
|
||||
}
|
||||
}
|
||||
|
||||
void GPU::cmdFillRectangle(uint8_t command, uint32_t arguments[]) {
|
||||
void GPU::cmdFillRectangle(uint8_t command) {
|
||||
// I'm sorry, but it appears that C++ doesn't have local functions.
|
||||
struct mask {
|
||||
constexpr static int startX(int x) { return x & 0x3f0; }
|
||||
|
@ -89,7 +93,7 @@ void GPU::cmdFillRectangle(uint8_t command, uint32_t arguments[]) {
|
|||
cmd = Command::None;
|
||||
}
|
||||
|
||||
void GPU::cmdPolygon(PolygonArgs arg, uint32_t arguments[]) {
|
||||
void GPU::cmdPolygon(PolygonArgs arg) {
|
||||
int ptr = 1;
|
||||
int16_t x[4], y[4];
|
||||
RGB c[4] = {};
|
||||
|
@ -119,7 +123,7 @@ void GPU::cmdPolygon(PolygonArgs arg, uint32_t arguments[]) {
|
|||
}
|
||||
|
||||
// fixme: handle multiline with > 15 lines (arguments array hold only 31 elements)
|
||||
void GPU::cmdLine(LineArgs arg, uint32_t arguments[]) {
|
||||
void GPU::cmdLine(LineArgs arg) {
|
||||
int ptr = 1;
|
||||
int16_t x[2] = {}, y[2] = {};
|
||||
RGB c[2] = {};
|
||||
|
@ -148,13 +152,13 @@ void GPU::cmdLine(LineArgs arg, uint32_t arguments[]) {
|
|||
|
||||
// No transparency support
|
||||
// No Gouroud Shading
|
||||
drawLine(this, x, y, c);
|
||||
Render::drawLine(this, x, y, c);
|
||||
}
|
||||
|
||||
cmd = Command::None;
|
||||
}
|
||||
|
||||
void GPU::cmdRectangle(RectangleArgs arg, uint32_t arguments[]) {
|
||||
void GPU::cmdRectangle(RectangleArgs arg) {
|
||||
int16_t w = arg.getSize();
|
||||
int16_t h = arg.getSize();
|
||||
|
||||
|
@ -223,7 +227,7 @@ struct MaskCopy {
|
|||
constexpr static int endY(int y) { return ((y - 1) & 0x1ff) + 1; }
|
||||
};
|
||||
|
||||
void GPU::cmdCpuToVram1(uint8_t command, uint32_t arguments[]) {
|
||||
void GPU::cmdCpuToVram1(uint8_t command) {
|
||||
if ((arguments[0] & 0x00ffffff) != 0) {
|
||||
printf("cmdCpuToVram1: Suspicious arg0: 0x%x\n", arguments[0]);
|
||||
}
|
||||
|
@ -238,7 +242,7 @@ void GPU::cmdCpuToVram1(uint8_t command, uint32_t arguments[]) {
|
|||
currentArgument = 0;
|
||||
}
|
||||
|
||||
void GPU::cmdCpuToVram2(uint8_t command, uint32_t arguments[]) {
|
||||
void GPU::cmdCpuToVram2(uint8_t command) {
|
||||
uint32_t byte = arguments[0];
|
||||
|
||||
// TODO: ugly code
|
||||
|
@ -257,7 +261,7 @@ void GPU::cmdCpuToVram2(uint8_t command, uint32_t arguments[]) {
|
|||
currentArgument = 0;
|
||||
}
|
||||
|
||||
void GPU::cmdVramToCpu(uint8_t command, uint32_t arguments[]) {
|
||||
void GPU::cmdVramToCpu(uint8_t command) {
|
||||
if ((arguments[0] & 0x00ffffff) != 0) {
|
||||
printf("cmdVramToCpu: Suspicious arg0: 0x%x\n", arguments[0]);
|
||||
}
|
||||
|
@ -270,7 +274,7 @@ void GPU::cmdVramToCpu(uint8_t command, uint32_t arguments[]) {
|
|||
cmd = Command::None;
|
||||
}
|
||||
|
||||
void GPU::cmdVramToVram(uint8_t command, uint32_t arguments[]) {
|
||||
void GPU::cmdVramToVram(uint8_t command) {
|
||||
if ((arguments[0] & 0x00ffffff) != 0) {
|
||||
printf("cpuVramToVram: Suspicious arg0: 0x%x, breaking!!!\n", arguments[0]);
|
||||
cmd = Command::None;
|
||||
|
@ -437,7 +441,7 @@ void GPU::writeGP0(uint32_t data) {
|
|||
}
|
||||
|
||||
if (gpuLogEnabled && cmd == Command::None) {
|
||||
GPU_LOG_ENTRY entry;
|
||||
LogEntry entry;
|
||||
entry.cmd = Command::Extra;
|
||||
entry.command = command;
|
||||
entry.args = std::vector<uint32_t>();
|
||||
|
@ -457,31 +461,31 @@ void GPU::writeGP0(uint32_t data) {
|
|||
}
|
||||
|
||||
if (gpuLogEnabled && cmd != Command::CopyCpuToVram2) {
|
||||
GPU_LOG_ENTRY entry;
|
||||
LogEntry entry;
|
||||
entry.cmd = cmd;
|
||||
entry.command = command;
|
||||
entry.args = std::vector<uint32_t>(arguments, arguments + argumentCount);
|
||||
entry.args = std::vector<uint32_t>(arguments.begin(), arguments.begin() + argumentCount);
|
||||
gpuLogList.push_back(entry);
|
||||
}
|
||||
|
||||
// printf("%s(0x%x)\n", CommandStr[(int)cmd], command);
|
||||
|
||||
if (cmd == Command::FillRectangle)
|
||||
cmdFillRectangle(command, arguments);
|
||||
cmdFillRectangle(command);
|
||||
else if (cmd == Command::Polygon)
|
||||
cmdPolygon(command, arguments);
|
||||
cmdPolygon(command);
|
||||
else if (cmd == Command::Line)
|
||||
cmdLine(command, arguments);
|
||||
cmdLine(command);
|
||||
else if (cmd == Command::Rectangle)
|
||||
cmdRectangle(command, arguments);
|
||||
cmdRectangle(command);
|
||||
else if (cmd == Command::CopyCpuToVram1)
|
||||
cmdCpuToVram1(command, arguments);
|
||||
cmdCpuToVram1(command);
|
||||
else if (cmd == Command::CopyCpuToVram2)
|
||||
cmdCpuToVram2(command, arguments);
|
||||
cmdCpuToVram2(command);
|
||||
else if (cmd == Command::CopyVramToCpu)
|
||||
cmdVramToCpu(command, arguments);
|
||||
cmdVramToCpu(command);
|
||||
else if (cmd == Command::CopyVramToVram)
|
||||
cmdVramToVram(command, arguments);
|
||||
cmdVramToVram(command);
|
||||
}
|
||||
|
||||
void GPU::writeGP1(uint32_t data) {
|
||||
|
@ -563,4 +567,19 @@ bool GPU::emulateGpuCycles(int cycles) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int GPU::minDrawingX(int x) const { return std::max((int)drawingArea.left, std::max(0, x)); }
|
||||
|
||||
int GPU::minDrawingY(int y) const { return std::max((int)drawingArea.top, std::max(0, y)); }
|
||||
|
||||
int GPU::maxDrawingX(int x) const { return std::min((int)drawingArea.right, std::min(VRAM_WIDTH, x)); }
|
||||
|
||||
int GPU::maxDrawingY(int y) const { return std::min((int)drawingArea.bottom, std::min(VRAM_HEIGHT, y)); }
|
||||
|
||||
bool GPU::insideDrawingArea(int x, int y) const {
|
||||
return (x >= drawingArea.left) && (x < drawingArea.right) && (x < VRAM_WIDTH) && (y >= drawingArea.top) && (y < drawingArea.bottom)
|
||||
&& (y < VRAM_HEIGHT);
|
||||
}
|
||||
|
||||
bool GPU::isNtsc() { return gp1_08.videoMode == GP1_08::VideoMode::ntsc; }
|
||||
|
||||
} // namespace gpu
|
|
@ -1,10 +1,17 @@
|
|||
#pragma once
|
||||
#include <array>
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
#include "psx_color.h"
|
||||
#include "registers.h"
|
||||
|
||||
const int MAX_ARGS = 32;
|
||||
#define VRAM ((uint16_t(*)[VRAM_WIDTH])vram.data())
|
||||
|
||||
struct System;
|
||||
class Render;
|
||||
class OpenGL;
|
||||
|
||||
namespace gpu {
|
||||
|
||||
extern const char* CommandStr[];
|
||||
|
||||
|
@ -14,147 +21,12 @@ const int VRAM_HEIGHT = 512;
|
|||
const int LINE_VBLANK_START_NTSC = 243;
|
||||
const int LINES_TOTAL_NTSC = 263;
|
||||
|
||||
#define VRAM ((uint16_t(*)[VRAM_WIDTH])vram.data())
|
||||
|
||||
union PolygonArgs {
|
||||
struct {
|
||||
uint8_t isRawTexture : 1;
|
||||
uint8_t semiTransparency : 1;
|
||||
uint8_t isTextureMapped : 1;
|
||||
uint8_t isQuad : 1;
|
||||
uint8_t gouroudShading : 1;
|
||||
uint8_t : 3;
|
||||
};
|
||||
uint8_t _;
|
||||
|
||||
PolygonArgs(uint8_t arg) : _(arg) {}
|
||||
|
||||
int getArgumentCount() const {
|
||||
int size = isQuad ? 4 : 3;
|
||||
if (isTextureMapped) size *= 2;
|
||||
if (gouroudShading) size += (isQuad ? 4 : 3) - 1;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int getVertexCount() const { return isQuad ? 4 : 3; }
|
||||
};
|
||||
|
||||
union LineArgs {
|
||||
struct {
|
||||
uint8_t : 1;
|
||||
uint8_t semiTransparency : 1;
|
||||
uint8_t : 1;
|
||||
uint8_t polyLine : 1;
|
||||
uint8_t gouroudShading : 1;
|
||||
uint8_t : 3;
|
||||
};
|
||||
uint8_t _;
|
||||
|
||||
LineArgs(uint8_t arg) : _(arg) {}
|
||||
|
||||
int getArgumentCount() const {
|
||||
if (polyLine) return MAX_ARGS - 1;
|
||||
|
||||
return 2 + (gouroudShading ? 1 : 0);
|
||||
}
|
||||
};
|
||||
|
||||
union RectangleArgs {
|
||||
struct {
|
||||
uint8_t isRawTexture : 1;
|
||||
uint8_t semiTransparency : 1;
|
||||
uint8_t isTextureMapped : 1;
|
||||
uint8_t size : 2;
|
||||
uint8_t : 3;
|
||||
};
|
||||
uint8_t _;
|
||||
|
||||
RectangleArgs(uint8_t arg) : _(arg) {}
|
||||
|
||||
int getArgumentCount() const { return (size == 0 ? 2 : 1) + (isTextureMapped ? 1 : 0); }
|
||||
|
||||
int getSize() const {
|
||||
if (size == 1) return 1;
|
||||
if (size == 2) return 8;
|
||||
if (size == 3) return 16;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
enum class Command : int {
|
||||
None,
|
||||
FillRectangle,
|
||||
Polygon,
|
||||
Line,
|
||||
Rectangle,
|
||||
CopyCpuToVram1,
|
||||
CopyCpuToVram2,
|
||||
CopyVramToCpu,
|
||||
CopyVramToVram,
|
||||
Extra
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
enum Flags { SemiTransparency = 1 << 0, RawTexture = 1 << 1, Dithering = 1 << 2, GouroudShading = 1 << 3 };
|
||||
int position[2];
|
||||
int color[3];
|
||||
int texcoord[2];
|
||||
int bitcount;
|
||||
int clut[2]; // clut position
|
||||
int texpage[2]; // texture page position
|
||||
int flags;
|
||||
/**
|
||||
* 0b76543210
|
||||
* ^
|
||||
* Transparency enabled (yes for tris, no for rect)
|
||||
*/
|
||||
};
|
||||
|
||||
struct TextureInfo {
|
||||
// t[0] ClutYyXx
|
||||
// t[1] PageYyXx
|
||||
// t[2] 0000YyXx
|
||||
// t[3] 0000YyXx
|
||||
|
||||
uint32_t palette;
|
||||
uint32_t texpage;
|
||||
glm::ivec2 uv[4];
|
||||
|
||||
int getClutX() const { return ((palette & 0x003f0000) >> 16) * 16; }
|
||||
|
||||
int getClutY() const { return ((palette & 0x7fc00000) >> 22); }
|
||||
|
||||
int getBaseX() const {
|
||||
return ((texpage & 0x0f0000) >> 16) * 64; // N * 64
|
||||
}
|
||||
|
||||
int getBaseY() const {
|
||||
return ((texpage & 0x100000) >> 20) * 256; // N * 256
|
||||
}
|
||||
|
||||
int getBitcount() const {
|
||||
int depth = (texpage & 0x1800000) >> 23;
|
||||
switch (depth) {
|
||||
case 0: return 4;
|
||||
case 1: return 8;
|
||||
case 2: return 16;
|
||||
case 3: return 16;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
GP0_E1::SemiTransparency semiTransparencyBlending() const { return (GP0_E1::SemiTransparency)((texpage & 0x600000) >> 21); }
|
||||
};
|
||||
|
||||
struct GPU {
|
||||
/* 0 - nothing
|
||||
1 - GP0(0xc0) - VRAM to CPU transfer
|
||||
2 - GP1(0x10) - Get GPU Info
|
||||
*/
|
||||
|
||||
int resolutionMultiplier = 1;
|
||||
class GPU {
|
||||
friend struct ::System;
|
||||
friend class ::Render;
|
||||
friend class ::OpenGL;
|
||||
|
||||
// TODO: Comment private fields
|
||||
int startX = 0;
|
||||
int startY = 0;
|
||||
int endX = 0;
|
||||
|
@ -167,15 +39,17 @@ struct GPU {
|
|||
|
||||
Command cmd = Command::None;
|
||||
uint8_t command = 0;
|
||||
uint32_t arguments[33];
|
||||
std::array<uint32_t, MAX_ARGS> arguments{}; // TODO: MAX_ARGS + 1 ?
|
||||
int currentArgument = 0;
|
||||
int argumentCount = 0;
|
||||
|
||||
int gpuLine = 0;
|
||||
int gpuDot = 0;
|
||||
|
||||
bool odd = false;
|
||||
int frames = 0;
|
||||
|
||||
GP0_E1 gp0_e1;
|
||||
GP0_E2 gp0_e2;
|
||||
|
||||
// GP0(0xe3)
|
||||
// GP0(0xe4)
|
||||
|
@ -209,57 +83,46 @@ struct GPU {
|
|||
int16_t displayRangeY1 = 0;
|
||||
int16_t displayRangeY2 = 0;
|
||||
|
||||
GP1_08 gp1_08;
|
||||
|
||||
// GP1(0x09)
|
||||
bool textureDisableAllowed = false;
|
||||
|
||||
void reset();
|
||||
void cmdFillRectangle(uint8_t command, uint32_t arguments[]);
|
||||
void cmdPolygon(PolygonArgs arg, uint32_t arguments[]);
|
||||
void cmdLine(LineArgs arg, uint32_t arguments[]);
|
||||
void cmdRectangle(RectangleArgs arg, uint32_t arguments[]);
|
||||
void cmdCpuToVram1(uint8_t command, uint32_t arguments[]);
|
||||
void cmdCpuToVram2(uint8_t command, uint32_t arguments[]);
|
||||
void cmdVramToCpu(uint8_t command, uint32_t arguments[]);
|
||||
void cmdVramToVram(uint8_t command, uint32_t arguments[]);
|
||||
void cmdFillRectangle(uint8_t command);
|
||||
void cmdPolygon(PolygonArgs arg);
|
||||
void cmdLine(LineArgs arg);
|
||||
void cmdRectangle(RectangleArgs arg);
|
||||
void cmdCpuToVram1(uint8_t command);
|
||||
void cmdCpuToVram2(uint8_t command);
|
||||
void cmdVramToCpu(uint8_t command);
|
||||
void cmdVramToVram(uint8_t command);
|
||||
|
||||
void drawPolygon(int16_t x[4], int16_t y[4], RGB c[4], TextureInfo t, bool isQuad = false, bool textured = false, int flags = 0);
|
||||
|
||||
void writeGP0(uint32_t data);
|
||||
void writeGP1(uint32_t data);
|
||||
|
||||
public:
|
||||
GP0_E2 gp0_e2;
|
||||
GP1_08 gp1_08;
|
||||
|
||||
std::array<uint16_t, VRAM_WIDTH * VRAM_HEIGHT> vram{};
|
||||
|
||||
GPU();
|
||||
void step();
|
||||
bool emulateGpuCycles(int cycles);
|
||||
uint32_t read(uint32_t address);
|
||||
void write(uint32_t address, uint32_t data);
|
||||
bool isNtsc();
|
||||
|
||||
int minDrawingX(int x) const;
|
||||
int minDrawingY(int y) const;
|
||||
int maxDrawingX(int x) const;
|
||||
int maxDrawingY(int y) const;
|
||||
bool insideDrawingArea(int x, int y) const;
|
||||
|
||||
bool odd = false;
|
||||
int frames = 0;
|
||||
|
||||
GPU() {
|
||||
vram.resize(VRAM_WIDTH * VRAM_HEIGHT * resolutionMultiplier);
|
||||
prevVram.resize(VRAM_WIDTH * VRAM_HEIGHT * resolutionMultiplier);
|
||||
}
|
||||
void step();
|
||||
uint32_t read(uint32_t address);
|
||||
void write(uint32_t address, uint32_t data);
|
||||
|
||||
bool emulateGpuCycles(int cycles);
|
||||
|
||||
bool isNtsc();
|
||||
|
||||
std::vector<uint16_t> vram;
|
||||
std::vector<uint16_t> prevVram;
|
||||
|
||||
struct GPU_LOG_ENTRY {
|
||||
uint8_t command;
|
||||
Command cmd;
|
||||
std::vector<uint32_t> args;
|
||||
};
|
||||
|
||||
bool gpuLogEnabled = true;
|
||||
std::vector<LogEntry> gpuLogList;
|
||||
std::array<uint16_t, VRAM_WIDTH * VRAM_HEIGHT> prevVram{};
|
||||
};
|
||||
|
||||
std::vector<GPU_LOG_ENTRY> gpuLogList;
|
||||
};
|
||||
} // namespace gpu
|
|
@ -1,15 +0,0 @@
|
|||
#include <algorithm>
|
||||
#include "gpu.h"
|
||||
|
||||
int GPU::minDrawingX(int x) const { return std::max((int)drawingArea.left, std::max(0, x)); }
|
||||
|
||||
int GPU::minDrawingY(int y) const { return std::max((int)drawingArea.top, std::max(0, y)); }
|
||||
|
||||
int GPU::maxDrawingX(int x) const { return std::min((int)drawingArea.right, std::min(VRAM_WIDTH, x)); }
|
||||
|
||||
int GPU::maxDrawingY(int y) const { return std::min((int)drawingArea.bottom, std::min(VRAM_HEIGHT, y)); }
|
||||
|
||||
bool GPU::insideDrawingArea(int x, int y) const {
|
||||
return (x >= drawingArea.left) && (x < drawingArea.right) && (x < VRAM_WIDTH) && (y >= drawingArea.top) && (y < drawingArea.bottom)
|
||||
&& (y < VRAM_HEIGHT);
|
||||
}
|
|
@ -1,6 +1,11 @@
|
|||
#pragma once
|
||||
#include "device/device.h"
|
||||
|
||||
namespace gpu {
|
||||
|
||||
// FIFO size
|
||||
const int MAX_ARGS = 32;
|
||||
|
||||
// Draw Mode setting
|
||||
union GP0_E1 {
|
||||
enum class SemiTransparency : uint32_t {
|
||||
|
@ -128,4 +133,140 @@ struct Rect {
|
|||
T top = 0;
|
||||
T right = 0;
|
||||
T bottom = 0;
|
||||
};
|
||||
};
|
||||
|
||||
union PolygonArgs {
|
||||
struct {
|
||||
uint8_t isRawTexture : 1;
|
||||
uint8_t semiTransparency : 1;
|
||||
uint8_t isTextureMapped : 1;
|
||||
uint8_t isQuad : 1;
|
||||
uint8_t gouroudShading : 1;
|
||||
uint8_t : 3;
|
||||
};
|
||||
uint8_t _;
|
||||
|
||||
PolygonArgs(uint8_t arg) : _(arg) {}
|
||||
|
||||
int getArgumentCount() const {
|
||||
int size = isQuad ? 4 : 3;
|
||||
if (isTextureMapped) size *= 2;
|
||||
if (gouroudShading) size += (isQuad ? 4 : 3) - 1;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int getVertexCount() const { return isQuad ? 4 : 3; }
|
||||
};
|
||||
|
||||
union LineArgs {
|
||||
struct {
|
||||
uint8_t : 1;
|
||||
uint8_t semiTransparency : 1;
|
||||
uint8_t : 1;
|
||||
uint8_t polyLine : 1;
|
||||
uint8_t gouroudShading : 1;
|
||||
uint8_t : 3;
|
||||
};
|
||||
uint8_t _;
|
||||
|
||||
LineArgs(uint8_t arg) : _(arg) {}
|
||||
|
||||
int getArgumentCount() const {
|
||||
if (polyLine) return MAX_ARGS - 1;
|
||||
|
||||
return 2 + (gouroudShading ? 1 : 0);
|
||||
}
|
||||
};
|
||||
|
||||
union RectangleArgs {
|
||||
struct {
|
||||
uint8_t isRawTexture : 1;
|
||||
uint8_t semiTransparency : 1;
|
||||
uint8_t isTextureMapped : 1;
|
||||
uint8_t size : 2;
|
||||
uint8_t : 3;
|
||||
};
|
||||
uint8_t _;
|
||||
|
||||
RectangleArgs(uint8_t arg) : _(arg) {}
|
||||
|
||||
int getArgumentCount() const { return (size == 0 ? 2 : 1) + (isTextureMapped ? 1 : 0); }
|
||||
|
||||
int getSize() const {
|
||||
if (size == 1) return 1;
|
||||
if (size == 2) return 8;
|
||||
if (size == 3) return 16;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
enum class Command : int {
|
||||
None,
|
||||
FillRectangle,
|
||||
Polygon,
|
||||
Line,
|
||||
Rectangle,
|
||||
CopyCpuToVram1,
|
||||
CopyCpuToVram2,
|
||||
CopyVramToCpu,
|
||||
CopyVramToVram,
|
||||
Extra
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
enum Flags { SemiTransparency = 1 << 0, RawTexture = 1 << 1, Dithering = 1 << 2, GouroudShading = 1 << 3 };
|
||||
int position[2];
|
||||
int color[3];
|
||||
int texcoord[2];
|
||||
int bitcount;
|
||||
int clut[2]; // clut position
|
||||
int texpage[2]; // texture page position
|
||||
int flags;
|
||||
/**
|
||||
* 0b76543210
|
||||
* ^
|
||||
* Transparency enabled (yes for tris, no for rect)
|
||||
*/
|
||||
};
|
||||
|
||||
struct TextureInfo {
|
||||
// t[0] ClutYyXx
|
||||
// t[1] PageYyXx
|
||||
// t[2] 0000YyXx
|
||||
// t[3] 0000YyXx
|
||||
|
||||
uint32_t palette;
|
||||
uint32_t texpage;
|
||||
glm::ivec2 uv[4];
|
||||
|
||||
int getClutX() const { return ((palette & 0x003f0000) >> 16) * 16; }
|
||||
int getClutY() const { return ((palette & 0x7fc00000) >> 22); }
|
||||
int getBaseX() const {
|
||||
return ((texpage & 0x0f0000) >> 16) * 64; // N * 64
|
||||
}
|
||||
int getBaseY() const {
|
||||
return ((texpage & 0x100000) >> 20) * 256; // N * 256
|
||||
}
|
||||
int getBitcount() const {
|
||||
int depth = (texpage & 0x1800000) >> 23;
|
||||
switch (depth) {
|
||||
case 0: return 4;
|
||||
case 1: return 8;
|
||||
case 2: return 16;
|
||||
case 3: return 16;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
GP0_E1::SemiTransparency semiTransparencyBlending() const { return (GP0_E1::SemiTransparency)((texpage & 0x600000) >> 21); }
|
||||
};
|
||||
|
||||
// Debug/rewind
|
||||
struct LogEntry {
|
||||
uint8_t command;
|
||||
Command cmd;
|
||||
std::vector<uint32_t> args;
|
||||
};
|
||||
|
||||
} // namespace gpu
|
|
@ -1,5 +0,0 @@
|
|||
#pragma once
|
||||
#include "gpu.h"
|
||||
|
||||
void drawLine(GPU* gpu, const int16_t x[2], const int16_t y[2], const RGB c[2]);
|
||||
void drawTriangle(GPU* gpu, Vertex v[3]);
|
10
src/device/gpu/render/render.h
Normal file
10
src/device/gpu/render/render.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
#include "device/gpu/gpu.h"
|
||||
|
||||
class Render {
|
||||
public:
|
||||
static void drawLine(gpu::GPU* gpu, const int16_t x[2], const int16_t y[2], const RGB c[2]);
|
||||
static void drawTriangle(gpu::GPU* gpu, gpu::Vertex v[3]);
|
||||
static void drawRectangle(gpu::GPU* gpu, const int16_t x[4], const int16_t y[4], const RGB color[4], const gpu::TextureInfo tex,
|
||||
bool textured, int flags);
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
#include <algorithm>
|
||||
#include "render.h"
|
||||
#include <algorithm>
|
||||
|
||||
#undef VRAM
|
||||
#define VRAM ((uint16_t(*)[VRAM_WIDTH])gpu->vram.data())
|
||||
#define VRAM ((uint16_t(*)[gpu::VRAM_WIDTH])gpu->vram.data())
|
||||
|
||||
void drawLine(GPU* gpu, const int16_t x[2], const int16_t y[2], const RGB c[2]) {
|
||||
void Render::drawLine(gpu::GPU* gpu, const int16_t x[2], const int16_t y[2], const RGB c[2]) {
|
||||
int x0 = x[0] + gpu->drawingOffsetX;
|
||||
int y0 = y[0] + gpu->drawingOffsetY;
|
||||
int x1 = x[1] + gpu->drawingOffsetX;
|
|
@ -1,12 +1,15 @@
|
|||
#include <algorithm>
|
||||
#include <glm/glm.hpp>
|
||||
#include "psx_color.h"
|
||||
#include "device/gpu/psx_color.h"
|
||||
#include "render.h"
|
||||
#include "texture_utils.h"
|
||||
#include "utils/macros.h"
|
||||
|
||||
using gpu::GPU;
|
||||
using gpu::Vertex;
|
||||
|
||||
#undef VRAM
|
||||
#define VRAM ((uint16_t(*)[VRAM_WIDTH])gpu->vram.data())
|
||||
#define VRAM ((uint16_t(*)[gpu::VRAM_WIDTH])gpu->vram.data())
|
||||
|
||||
// clang-format off
|
||||
int ditherTable[4][4] = {
|
||||
|
@ -102,10 +105,10 @@ INLINE void plotPixel(GPU* gpu, glm::ivec2 p, glm::vec3 s, glm::vec3* color, glm
|
|||
// TODO: Mask support
|
||||
|
||||
if ((flags & Vertex::SemiTransparency) && ((bits != ColorDepth::NONE && c.k) || (bits == ColorDepth::NONE))) {
|
||||
using Transparency = GP0_E1::SemiTransparency;
|
||||
using Transparency = gpu::GP0_E1::SemiTransparency;
|
||||
|
||||
PSXColor bg = VRAM[p.y][p.x];
|
||||
Transparency transparency = (Transparency)((flags & 0x60) >> 5);
|
||||
auto transparency = (Transparency)((flags & 0x60) >> 5);
|
||||
switch (transparency) {
|
||||
case Transparency::Bby2plusFby2: c = bg / 2.f + c / 2.f; break;
|
||||
case Transparency::BplusF: c = bg + c; break;
|
||||
|
@ -169,7 +172,7 @@ void triangle(GPU* gpu, glm::ivec2 pos[3], glm::vec3 color[3], glm::ivec2 tex[3]
|
|||
}
|
||||
|
||||
// TODO: Render in batches
|
||||
void drawTriangle(GPU* gpu, Vertex v[3]) {
|
||||
void Render::drawTriangle(GPU* gpu, Vertex v[3]) {
|
||||
glm::ivec2 pos[3];
|
||||
glm::vec3 color[3];
|
||||
glm::ivec2 texcoord[3];
|
4
src/device/gpu/render/render_rectangle.cpp
Normal file
4
src/device/gpu/render/render_rectangle.cpp
Normal file
|
@ -0,0 +1,4 @@
|
|||
#include "render.h"
|
||||
|
||||
void Render::drawRectangle(gpu::GPU* gpu, const int16_t x[4], const int16_t y[4], const RGB color[4], const gpu::TextureInfo tex,
|
||||
bool textured, int flags) {}
|
|
@ -1,24 +1,24 @@
|
|||
#pragma once
|
||||
#include "gpu.h"
|
||||
#include "device/gpu/gpu.h"
|
||||
#include "utils/macros.h"
|
||||
|
||||
#define gpuVRAM ((uint16_t(*)[VRAM_WIDTH])gpu->vram.data())
|
||||
#define gpuVRAM ((uint16_t(*)[gpu::VRAM_WIDTH])gpu->vram.data())
|
||||
|
||||
enum class ColorDepth { NONE, BIT_4, BIT_8, BIT_16 };
|
||||
|
||||
INLINE uint16_t tex4bit(GPU* gpu, glm::ivec2 tex, glm::ivec2 texPage, glm::ivec2 clut) {
|
||||
INLINE uint16_t tex4bit(gpu::GPU* gpu, glm::ivec2 tex, glm::ivec2 texPage, glm::ivec2 clut) {
|
||||
uint16_t index = gpuVRAM[texPage.y + tex.y][texPage.x + tex.x / 4];
|
||||
uint16_t entry = (index >> ((tex.x & 3) * 4)) & 0xf;
|
||||
return gpuVRAM[clut.y][clut.x + entry];
|
||||
}
|
||||
|
||||
INLINE uint16_t tex8bit(GPU* gpu, glm::ivec2 tex, glm::ivec2 texPage, glm::ivec2 clut) {
|
||||
INLINE uint16_t tex8bit(gpu::GPU* gpu, glm::ivec2 tex, glm::ivec2 texPage, glm::ivec2 clut) {
|
||||
uint16_t index = gpuVRAM[texPage.y + tex.y][texPage.x + tex.x / 2];
|
||||
uint16_t entry = (index >> ((tex.x & 1) * 8)) & 0xff;
|
||||
return gpuVRAM[clut.y][clut.x + entry];
|
||||
}
|
||||
|
||||
INLINE uint16_t tex16bit(GPU* gpu, glm::ivec2 tex, glm::ivec2 texPage) {
|
||||
INLINE uint16_t tex16bit(gpu::GPU* gpu, glm::ivec2 tex, glm::ivec2 texPage) {
|
||||
return gpuVRAM[texPage.y + tex.y][texPage.x + tex.x];
|
||||
// TODO: In PSOne BIOS colors are swapped (r == b, g == g, b == r, k == k)
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#include "render.h"
|
||||
|
||||
#undef VRAM
|
||||
#define VRAM ((uint16_t(*)[VRAM_WIDTH])gpu->vram.data())
|
||||
|
||||
void drawRectangle(GPU* gpu, const int16_t x[4], const int16_t y[4], const RGB color[4], const TextureInfo tex, bool textured, int flags) {}
|
|
@ -15,7 +15,7 @@ class InputManager {
|
|||
};
|
||||
|
||||
private:
|
||||
const int DIGITAL_THRESHOLD = UINT8_MAX / 2;
|
||||
const int DIGITAL_THRESHOLD = UINT8_MAX / 4;
|
||||
static InputManager* _instance;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -44,7 +44,9 @@ const char *mapIo(uint32_t address) {
|
|||
return "";
|
||||
}
|
||||
|
||||
void replayCommands(GPU *gpu, int to) {
|
||||
void replayCommands(gpu::GPU *gpu, int to) {
|
||||
using gpu::Command;
|
||||
|
||||
auto commands = gpu->gpuLogList;
|
||||
gpu->vram = gpu->prevVram;
|
||||
|
||||
|
@ -226,7 +228,7 @@ void gpuLogWindow(System *sys) {
|
|||
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||
auto &entry = sys->gpu.get()->gpuLogList[i];
|
||||
|
||||
bool nodeOpen = ImGui::TreeNode((void *)(intptr_t)i, "cmd: 0x%02x %s", entry.command, CommandStr[(int)entry.cmd]);
|
||||
bool nodeOpen = ImGui::TreeNode((void *)(intptr_t)i, "cmd: 0x%02x %s", entry.command, gpu::CommandStr[(int)entry.cmd]);
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
renderTo = i;
|
||||
|
@ -261,14 +263,14 @@ void gpuLogWindow(System *sys) {
|
|||
|
||||
for (size_t i = 0; i < gpuLog.size(); i++) {
|
||||
auto e = gpuLog[i];
|
||||
j.push_back({{"command", e.command}, {"cmd", (int)e.cmd}, {"name", CommandStr[(int)e.cmd]}, {"args", e.args}});
|
||||
j.push_back({{"command", e.command}, {"cmd", (int)e.cmd}, {"name", gpu::CommandStr[(int)e.cmd]}, {"args", e.args}});
|
||||
}
|
||||
|
||||
putFileContents(string_format("%s.json", filename), j.dump(2));
|
||||
|
||||
// Binary vram dump
|
||||
std::vector<uint8_t> vram;
|
||||
vram.assign(gpu->vram.data(), gpu->vram.data() + (VRAM_WIDTH * VRAM_HEIGHT));
|
||||
vram.assign(gpu->vram.begin(), gpu->vram.end());
|
||||
putFileContents(string_format("%s.bin", filename), vram);
|
||||
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
@ -356,7 +358,7 @@ void vramWindow() {
|
|||
ImGui::Begin("VRAM", &showVramWindow, defaultSize, -1, ImGuiWindowFlags_NoScrollbar);
|
||||
auto currentSize = ImGui::GetWindowSize();
|
||||
currentSize.y -= 32;
|
||||
ImGui::Image((ImTextureID)vramTextureId, currentSize);
|
||||
ImGui::Image((ImTextureID)(uintptr_t)vramTextureId, currentSize);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ void gpuWindow(System* sys) {
|
|||
int horRes = gpu->gp1_08.getHorizontalResoulution();
|
||||
int verRes = gpu->gp1_08.getVerticalResoulution();
|
||||
bool interlaced = gpu->gp1_08.interlace;
|
||||
int mode = gpu->gp1_08.videoMode == GP1_08::VideoMode::ntsc ? 60 : 50;
|
||||
int colorDepth = gpu->gp1_08.colorDepth == GP1_08::ColorDepth::bit24 ? 24 : 15;
|
||||
int mode = gpu->gp1_08.videoMode == gpu::GP1_08::VideoMode::ntsc ? 60 : 50;
|
||||
int colorDepth = gpu->gp1_08.colorDepth == gpu::GP1_08::ColorDepth::bit24 ? 24 : 15;
|
||||
|
||||
ImGui::Text("Resolution %dx%d%c @ %dHz", horRes, verRes, interlaced ? 'i' : 'p', mode);
|
||||
ImGui::Text("Color depth: %dbit", colorDepth);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "options.h"
|
||||
#include <imgui.h>s
|
||||
#include <imgui.h>
|
||||
#include "config.h"
|
||||
#include "gui.h"
|
||||
#include "images.h"
|
||||
|
@ -113,7 +113,7 @@ void drawImage(const optional<Image> image, float w = 0.f, float h = 0.f) {
|
|||
} else {
|
||||
size = ImVec2(img->w, img->h);
|
||||
}
|
||||
ImGui::Image((ImTextureID)img->id, size);
|
||||
ImGui::Image((ImTextureID)(uintptr_t)img->id, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ Key Key::controllerMove(SDL_ControllerAxisEvent axis) {
|
|||
Key key;
|
||||
key.type = Type::ControllerMove;
|
||||
key.controller.id = axis.which;
|
||||
key.controller.dir = axis.value > 0;
|
||||
key.controller.dir = axis.value >= 0;
|
||||
key.controller.axis = static_cast<SDL_GameControllerAxis>(axis.axis);
|
||||
key.controller.value = std::abs(axis.value);
|
||||
|
||||
|
|
|
@ -118,9 +118,9 @@ void loadFile(std::unique_ptr<System>& sys, std::string path) {
|
|||
auto& gpuLog = sys->gpu->gpuLogList;
|
||||
gpuLog.clear();
|
||||
for (size_t i = 0; i < j.size(); i++) {
|
||||
GPU::GPU_LOG_ENTRY e;
|
||||
gpu::LogEntry e;
|
||||
e.command = j[i]["command"];
|
||||
e.cmd = (Command)(int)j[i]["cmd"];
|
||||
e.cmd = (gpu::Command)(int)j[i]["cmd"];
|
||||
|
||||
for (uint32_t a : j[i]["args"]) {
|
||||
e.args.push_back(a);
|
||||
|
|
|
@ -104,7 +104,7 @@ void OpenGL::renderSecondStage() {
|
|||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
|
||||
void OpenGL::render(GPU *gpu) {
|
||||
void OpenGL::render(gpu::GPU *gpu) {
|
||||
// Viewport settings
|
||||
aspect = config["options"]["graphics"]["widescreen"] ? RATIO_16_9 : RATIO_4_3;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class OpenGL {
|
|||
|
||||
bool init();
|
||||
bool setup();
|
||||
void render(GPU* gpu);
|
||||
void render(gpu::GPU* gpu);
|
||||
|
||||
void setViewFullVram(bool v) { viewFullVram = v; }
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ void Attribute::enable() { glEnableVertexAttribArray(id); }
|
|||
|
||||
void Attribute::disable() { glDisableVertexAttribArray(id); }
|
||||
|
||||
void Attribute::pointer(GLint size, GLenum type, GLsizei stride, int pointer) {
|
||||
void Attribute::pointer(GLint size, GLenum type, GLsizei stride, uintptr_t pointer) {
|
||||
enable();
|
||||
if (type == GL_INT || type == GL_UNSIGNED_INT)
|
||||
glVertexAttribIPointer(id, size, type, stride, (const GLvoid*)pointer);
|
||||
|
|
|
@ -10,5 +10,5 @@ class Attribute {
|
|||
|
||||
void enable();
|
||||
void disable();
|
||||
void pointer(GLint size, GLenum type, GLsizei stride, int pointer);
|
||||
void pointer(GLint size, GLenum type, GLsizei stride, uintptr_t pointer);
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "system.h"
|
||||
#include <sound/sound.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sound/sound.h>
|
||||
#include "bios/functions.h"
|
||||
#include "config.h"
|
||||
#include "utils/file.h"
|
||||
|
@ -15,7 +15,7 @@ System::System() {
|
|||
memset(expansion, 0, EXPANSION_SIZE);
|
||||
|
||||
cpu = std::make_unique<mips::CPU>(this);
|
||||
gpu = std::make_unique<GPU>();
|
||||
gpu = std::make_unique<gpu::GPU>();
|
||||
spu = std::make_unique<spu::SPU>(this);
|
||||
|
||||
cdrom = std::make_unique<device::cdrom::CDROM>(this);
|
||||
|
@ -340,7 +340,7 @@ void System::emulateFrame() {
|
|||
return; // frame emulated
|
||||
}
|
||||
|
||||
if (gpu->gpuLine >= LINE_VBLANK_START_NTSC) {
|
||||
if (gpu->gpuLine >= gpu::LINE_VBLANK_START_NTSC) {
|
||||
if (timer1->mode.syncEnabled) {
|
||||
auto mode1 = static_cast<timer::CounterMode::SyncMode1>(timer1->mode.syncMode);
|
||||
using modes = timer::CounterMode::SyncMode1;
|
||||
|
|
|
@ -87,7 +87,7 @@ struct System {
|
|||
std::unique_ptr<device::controller::Controller> controller;
|
||||
std::unique_ptr<device::dma::DMA> dma;
|
||||
std::unique_ptr<Expansion2> expansion2;
|
||||
std::unique_ptr<GPU> gpu;
|
||||
std::unique_ptr<gpu::GPU> gpu;
|
||||
std::unique_ptr<Interrupt> interrupt;
|
||||
std::unique_ptr<MDEC> mdec;
|
||||
std::unique_ptr<MemoryControl> memoryControl;
|
||||
|
|
Loading…
Reference in a new issue