mirror of
https://github.com/ARMSX2/ARMSX1.git
synced 2026-08-24 16:53:35 -07:00
Implement more GP0 commands
Start implementing a framework for IRQs
This commit is contained in:
+13
-1
@@ -18,7 +18,7 @@ int main(int argc, const char* argv[]) {
|
||||
psxe_screen_set_scale(screen, 2);
|
||||
psxe_screen_reload(screen);
|
||||
|
||||
psx_gpu_set_dmode_event_callback(gpu, psxe_gpu_dmode_event_cb);
|
||||
psx_gpu_set_event_callback(gpu, GPU_EVENT_DMODE, psxe_gpu_dmode_event_cb);
|
||||
psx_gpu_set_udata(gpu, 0, screen);
|
||||
|
||||
if (argv[1]) {
|
||||
@@ -31,6 +31,18 @@ int main(int argc, const char* argv[]) {
|
||||
psxe_screen_update(screen);
|
||||
}
|
||||
|
||||
psx_cpu_t* cpu = psx_get_cpu(psx);
|
||||
|
||||
log_fatal("r0=%08x at=%08x v0=%08x v1=%08x", cpu->r[0] , cpu->r[1] , cpu->r[2] , cpu->r[3] );
|
||||
log_fatal("a0=%08x a1=%08x a2=%08x a3=%08x", cpu->r[4] , cpu->r[5] , cpu->r[6] , cpu->r[7] );
|
||||
log_fatal("t0=%08x t1=%08x t2=%08x t3=%08x", cpu->r[8] , cpu->r[9] , cpu->r[10], cpu->r[11]);
|
||||
log_fatal("t4=%08x t5=%08x t6=%08x t7=%08x", cpu->r[12], cpu->r[13], cpu->r[14], cpu->r[15]);
|
||||
log_fatal("s0=%08x s1=%08x s2=%08x s3=%08x", cpu->r[16], cpu->r[17], cpu->r[18], cpu->r[19]);
|
||||
log_fatal("s4=%08x s5=%08x s6=%08x s7=%08x", cpu->r[20], cpu->r[21], cpu->r[22], cpu->r[23]);
|
||||
log_fatal("t8=%08x t9=%08x k0=%08x k1=%08x", cpu->r[24], cpu->r[25], cpu->r[26], cpu->r[27]);
|
||||
log_fatal("gp=%08x sp=%08x fp=%08x ra=%08x", cpu->r[28], cpu->r[29], cpu->r[30], cpu->r[31]);
|
||||
log_fatal("pc=%08x hi=%08x lo=%08x", cpu->pc, cpu->hi, cpu->lo);
|
||||
|
||||
psx_destroy(psx);
|
||||
psxe_screen_destroy(screen);
|
||||
|
||||
|
||||
+16
-2
@@ -7,13 +7,19 @@ psxe_screen_t* psxe_screen_create() {
|
||||
void psxe_screen_init(psxe_screen_t* screen, psx_gpu_t* gpu) {
|
||||
memset(screen, 0, sizeof(psxe_screen_t));
|
||||
|
||||
#ifdef PSXE_SCREEN_DEBUG
|
||||
screen->width = PSX_GPU_FB_WIDTH;
|
||||
screen->height = PSX_GPU_FB_HEIGHT;
|
||||
#else
|
||||
screen->width = 320;
|
||||
screen->height = 240;
|
||||
#endif
|
||||
screen->scale = 1;
|
||||
screen->format = SDL_PIXELFORMAT_BGR555;
|
||||
screen->mode = 60;
|
||||
screen->buf = (uint32_t*)gpu->vram;
|
||||
screen->buf = gpu->vram;
|
||||
screen->open = 1;
|
||||
screen->gpu = gpu;
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||
}
|
||||
@@ -52,7 +58,9 @@ int psxe_screen_is_open(psxe_screen_t* screen) {
|
||||
}
|
||||
|
||||
void psxe_screen_update(psxe_screen_t* screen) {
|
||||
SDL_UpdateTexture(screen->texture, NULL, screen->buf, PSX_GPU_FB_WIDTH * sizeof(uint16_t));
|
||||
uint32_t disp_offset = screen->gpu->disp_x + (screen->gpu->disp_y * 1024);
|
||||
|
||||
SDL_UpdateTexture(screen->texture, NULL, screen->buf + disp_offset, PSX_GPU_FB_WIDTH * sizeof(uint16_t));
|
||||
SDL_RenderCopy(screen->renderer, screen->texture, NULL, NULL);
|
||||
SDL_RenderPresent(screen->renderer);
|
||||
|
||||
@@ -84,12 +92,18 @@ void psxe_screen_destroy(psxe_screen_t* screen) {
|
||||
void psxe_gpu_dmode_event_cb(psx_gpu_t* gpu) {
|
||||
psxe_screen_t* screen = gpu->udata[0];
|
||||
|
||||
#ifdef PSXE_SCREEN_DEBUG
|
||||
screen->width = PSX_GPU_FB_WIDTH; // dmode_hres_table[gpu->display_mode & 0x3];
|
||||
screen->height = PSX_GPU_FB_HEIGHT; // (gpu->display_mode & 0x4) ? 480 : 240;
|
||||
#else
|
||||
static int dmode_hres_table[] = {
|
||||
256, 320, 512, 640
|
||||
};
|
||||
|
||||
screen->width = dmode_hres_table[gpu->display_mode & 0x3];
|
||||
screen->height = (gpu->display_mode & 0x4) ? 480 : 240;
|
||||
#endif
|
||||
|
||||
screen->format = gpu->display_mode & 0x10 ? SDL_PIXELFORMAT_BGR888 : SDL_PIXELFORMAT_BGR555;
|
||||
screen->mode = gpu->display_mode & 0x8 ? 60 : 50;
|
||||
|
||||
|
||||
+3
-1
@@ -12,12 +12,14 @@ typedef struct {
|
||||
SDL_Renderer* renderer;
|
||||
SDL_Texture* texture;
|
||||
|
||||
psx_gpu_t* gpu;
|
||||
|
||||
unsigned int width, height, scale;
|
||||
unsigned int format;
|
||||
unsigned int mode;
|
||||
int open;
|
||||
|
||||
uint32_t* buf;
|
||||
uint16_t* buf;
|
||||
} psxe_screen_t;
|
||||
|
||||
psxe_screen_t* psxe_screen_create();
|
||||
|
||||
@@ -288,6 +288,7 @@ void psx_cpu_load_state(psx_cpu_t* cpu, FILE* file) {
|
||||
void psx_cpu_cycle(psx_cpu_t* cpu) {
|
||||
if ((cpu->pc & 0x3fffffff) == 0x000000a4)
|
||||
if (cpu->a_function_hook) cpu->a_function_hook(cpu);
|
||||
|
||||
if ((cpu->pc & 0x3fffffff) == 0x000000b4)
|
||||
if (cpu->a_function_hook) cpu->b_function_hook(cpu);
|
||||
|
||||
@@ -300,6 +301,11 @@ void psx_cpu_cycle(psx_cpu_t* cpu) {
|
||||
|
||||
g_psx_cpu_primary_table[OP](cpu);
|
||||
|
||||
// Interrupts not yet working
|
||||
// if ((cpu->cop0_sr & SR_IEC) && (cpu->cop0_cause & cpu->cop0_sr & SR_IM)) {
|
||||
// psx_cpu_exception(cpu, CAUSE_INT);
|
||||
// }
|
||||
|
||||
cpu->r[0] = 0;
|
||||
}
|
||||
|
||||
@@ -325,9 +331,12 @@ void psx_cpu_exception(psx_cpu_t* cpu, uint32_t cause) {
|
||||
cpu->pc = (cpu->cop0_sr & SR_BEV) ? 0xbfc00180 : 0x80000080;
|
||||
|
||||
// Simulate pipeline flush
|
||||
cpu->buf[0] = psx_bus_read32(cpu->bus, cpu->pc);
|
||||
psx_cpu_fetch(cpu);
|
||||
}
|
||||
|
||||
cpu->pc += 4;
|
||||
void psx_cpu_irq(psx_cpu_t* cpu, uint32_t irq) {
|
||||
// Set interrupt pending field
|
||||
cpu->cop0_cause |= irq << 10;
|
||||
}
|
||||
|
||||
void psx_cpu_i_invalid(psx_cpu_t* cpu) {
|
||||
|
||||
@@ -166,6 +166,7 @@ void psx_cpu_init(psx_cpu_t*, psx_bus_t*);
|
||||
void psx_cpu_destroy(psx_cpu_t*);
|
||||
void psx_cpu_cycle(psx_cpu_t*);
|
||||
void psx_cpu_exception(psx_cpu_t*, uint32_t);
|
||||
void psx_cpu_irq(psx_cpu_t*, uint32_t);
|
||||
void psx_cpu_load_state(psx_cpu_t*, FILE*);
|
||||
void psx_cpu_save_state(psx_cpu_t*, FILE*);
|
||||
void psx_cpu_fetch(psx_cpu_t*);
|
||||
|
||||
+259
-10
@@ -1,6 +1,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "gpu.h"
|
||||
#include "../log.h"
|
||||
@@ -15,7 +16,7 @@ psx_gpu_t* psx_gpu_create() {
|
||||
return (psx_gpu_t*)malloc(sizeof(psx_gpu_t));
|
||||
}
|
||||
|
||||
void psx_gpu_init(psx_gpu_t* gpu) {
|
||||
void psx_gpu_init(psx_gpu_t* gpu, psx_ic_t* ic) {
|
||||
memset(gpu, 0, sizeof(psx_gpu_t));
|
||||
|
||||
gpu->io_base = PSX_GPU_BEGIN;
|
||||
@@ -23,12 +24,14 @@ void psx_gpu_init(psx_gpu_t* gpu) {
|
||||
|
||||
gpu->vram = (uint16_t*)malloc(PSX_GPU_VRAM_SIZE);
|
||||
gpu->state = GPU_STATE_RECV_CMD;
|
||||
|
||||
gpu->ic = ic;
|
||||
}
|
||||
|
||||
uint32_t psx_gpu_read32(psx_gpu_t* gpu, uint32_t offset) {
|
||||
switch (offset) {
|
||||
case 0x00: return 0x00000000; // GPUREAD
|
||||
case 0x04: return 0x1c000000; // GPUSTAT
|
||||
case 0x00: return gpu->gpuread; // GPUREAD
|
||||
case 0x04: return gpu->gpustat; // GPUSTAT
|
||||
}
|
||||
|
||||
log_warn("Unhandled 32-bit GPU read at offset %08x", offset);
|
||||
@@ -58,7 +61,100 @@ uint8_t psx_gpu_read8(psx_gpu_t* gpu, uint32_t offset) {
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
int min(int x0, int x1) {
|
||||
return (x0 < x1) ? x0 : x1;
|
||||
}
|
||||
|
||||
int max(int x0, int x1) {
|
||||
return (x0 > x1) ? x0 : x1;
|
||||
}
|
||||
|
||||
#define EDGE(a, b, c) ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x))
|
||||
|
||||
void gpu_render_flat_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2, uint32_t color) {
|
||||
vertex_t a, b, c;
|
||||
|
||||
a = v0;
|
||||
|
||||
/* Ensure the winding order is correct */
|
||||
if (EDGE(v0, v1, v2) < 0) {
|
||||
b = v2;
|
||||
c = v1;
|
||||
} else {
|
||||
b = v1;
|
||||
c = v2;
|
||||
}
|
||||
|
||||
a.x += gpu->off_x;
|
||||
a.y += gpu->off_y;
|
||||
b.x += gpu->off_x;
|
||||
b.y += gpu->off_y;
|
||||
c.x += gpu->off_x;
|
||||
c.y += gpu->off_y;
|
||||
|
||||
int xmin = max(min(min(a.x, b.x), c.x), gpu->draw_x1);
|
||||
int ymin = max(min(min(a.y, b.y), c.y), gpu->draw_y1);
|
||||
int xmax = min(max(max(a.x, b.x), c.x), gpu->draw_x2);
|
||||
int ymax = min(max(max(a.y, b.y), c.y), gpu->draw_y2);
|
||||
|
||||
for (int y = ymin; y < ymax; y++) {
|
||||
for (int x = xmin; x < xmax; x++) {
|
||||
int z0 = ((b.x - a.x) * (y - a.y)) - ((b.y - a.y) * (x - a.x));
|
||||
int z1 = ((c.x - b.x) * (y - b.y)) - ((c.y - b.y) * (x - b.x));
|
||||
int z2 = ((a.x - c.x) * (y - c.y)) - ((a.y - c.y) * (x - c.x));
|
||||
|
||||
if ((z0 >= 0) && (z1 >= 0) && (z2 >= 0)) {
|
||||
gpu->vram[x + (y * 1024)] = gpu_to_bgr555(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gpu_render_shaded_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2) {
|
||||
vertex_t a, b, c;
|
||||
|
||||
a = v0;
|
||||
|
||||
/* Ensure the winding order is correct */
|
||||
if (EDGE(v0, v1, v2) < 0) {
|
||||
b = v2;
|
||||
c = v1;
|
||||
} else {
|
||||
b = v1;
|
||||
c = v2;
|
||||
}
|
||||
|
||||
a.x += gpu->off_x;
|
||||
a.y += gpu->off_y;
|
||||
b.x += gpu->off_x;
|
||||
b.y += gpu->off_y;
|
||||
c.x += gpu->off_x;
|
||||
c.y += gpu->off_y;
|
||||
|
||||
int xmin = max(min(min(a.x, b.x), c.x), gpu->draw_x1);
|
||||
int ymin = max(min(min(a.y, b.y), c.y), gpu->draw_y1);
|
||||
int xmax = min(max(max(a.x, b.x), c.x), gpu->draw_x2);
|
||||
int ymax = min(max(max(a.y, b.y), c.y), gpu->draw_y2);
|
||||
|
||||
int area = EDGE(a, b, c);
|
||||
|
||||
for (int y = ymin; y < ymax; y++) {
|
||||
for (int x = xmin; x < xmax; x++) {
|
||||
int z0 = ((b.x - a.x) * (y - a.y)) - ((b.y - a.y) * (x - a.x));
|
||||
int z1 = ((c.x - b.x) * (y - b.y)) - ((c.y - b.y) * (x - b.x));
|
||||
int z2 = ((a.x - c.x) * (y - c.y)) - ((a.y - c.y) * (x - c.x));
|
||||
|
||||
if ((z0 >= 0) && (z1 >= 0) && (z2 >= 0)) {
|
||||
uint32_t cr = (z0 * ((a.c >> 0) & 0xff) + z1 * ((b.c >> 0) & 0xff) + z2 * ((c.c >> 0) & 0xff)) / area;
|
||||
uint32_t cg = (z0 * ((a.c >> 8) & 0xff) + z1 * ((b.c >> 8) & 0xff) + z2 * ((c.c >> 8) & 0xff)) / area;
|
||||
uint32_t cb = (z0 * ((a.c >> 16) & 0xff) + z1 * ((b.c >> 16) & 0xff) + z2 * ((c.c >> 16) & 0xff)) / area;
|
||||
|
||||
uint32_t color = (cb << 16) | (cg << 8) | cr;
|
||||
|
||||
gpu->vram[x + (y * 1024)] = gpu_to_bgr555(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gpu_cmd_a0(psx_gpu_t* gpu) {
|
||||
@@ -132,9 +228,9 @@ void gpu_cmd_02(psx_gpu_t* gpu) {
|
||||
gpu->color
|
||||
);
|
||||
|
||||
for (int y = gpu->ypos; y < gpu->ysiz; y++) {
|
||||
for (int x = gpu->xpos; x < gpu->xsiz; x++) {
|
||||
((uint16_t*)gpu->vram)[x + (y * 512)] = 0x0000;
|
||||
for (int y = 0; y < gpu->ysiz; y++) {
|
||||
for (int x = 0; x < gpu->xsiz; x++) {
|
||||
gpu->vram[(x + gpu->xpos) + ((y + gpu->ypos) * 1024)] = gpu_to_bgr555(gpu->color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,10 +240,141 @@ void gpu_cmd_02(psx_gpu_t* gpu) {
|
||||
}
|
||||
}
|
||||
|
||||
// Monochrome Opaque Quadrilateral
|
||||
void gpu_cmd_28(psx_gpu_t* gpu) {
|
||||
switch (gpu->state) {
|
||||
case GPU_STATE_RECV_CMD: {
|
||||
gpu->state = GPU_STATE_RECV_ARGS;
|
||||
gpu->cmd_args_remaining = 4;
|
||||
} break;
|
||||
|
||||
case GPU_STATE_RECV_ARGS: {
|
||||
if (!gpu->cmd_args_remaining) {
|
||||
gpu->state = GPU_STATE_RECV_DATA;
|
||||
|
||||
gpu->v0.x = gpu->buf[1] & 0xffff;
|
||||
gpu->v0.y = gpu->buf[1] >> 16;
|
||||
gpu->v1.x = gpu->buf[2] & 0xffff;
|
||||
gpu->v1.y = gpu->buf[2] >> 16;
|
||||
gpu->v2.x = gpu->buf[3] & 0xffff;
|
||||
gpu->v2.y = gpu->buf[3] >> 16;
|
||||
gpu->v3.x = gpu->buf[4] & 0xffff;
|
||||
gpu->v3.y = gpu->buf[4] >> 16;
|
||||
gpu->color = gpu->buf[0] & 0xffffff;
|
||||
|
||||
gpu_render_flat_triangle(gpu, gpu->v0, gpu->v1, gpu->v2, gpu->color);
|
||||
gpu_render_flat_triangle(gpu, gpu->v1, gpu->v2, gpu->v3, gpu->color);
|
||||
|
||||
gpu->state = GPU_STATE_RECV_CMD;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
// Monochrome Opaque Quadrilateral
|
||||
void gpu_cmd_30(psx_gpu_t* gpu) {
|
||||
switch (gpu->state) {
|
||||
case GPU_STATE_RECV_CMD: {
|
||||
gpu->state = GPU_STATE_RECV_ARGS;
|
||||
gpu->cmd_args_remaining = 5;
|
||||
} break;
|
||||
|
||||
case GPU_STATE_RECV_ARGS: {
|
||||
if (!gpu->cmd_args_remaining) {
|
||||
gpu->state = GPU_STATE_RECV_DATA;
|
||||
|
||||
gpu->v0.c = gpu->buf[0] & 0xffffff;
|
||||
gpu->v0.x = gpu->buf[1] & 0xffff;
|
||||
gpu->v0.y = gpu->buf[1] >> 16;
|
||||
gpu->v1.c = gpu->buf[2] & 0xffffff;
|
||||
gpu->v1.x = gpu->buf[3] & 0xffff;
|
||||
gpu->v1.y = gpu->buf[3] >> 16;
|
||||
gpu->v2.c = gpu->buf[4] & 0xffffff;
|
||||
gpu->v2.x = gpu->buf[5] & 0xffff;
|
||||
gpu->v2.y = gpu->buf[5] >> 16;
|
||||
|
||||
gpu_render_flat_triangle(gpu, gpu->v0, gpu->v1, gpu->v2, gpu->color);
|
||||
|
||||
gpu->state = GPU_STATE_RECV_CMD;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
// Monochrome Opaque Quadrilateral
|
||||
void gpu_cmd_38(psx_gpu_t* gpu) {
|
||||
switch (gpu->state) {
|
||||
case GPU_STATE_RECV_CMD: {
|
||||
gpu->state = GPU_STATE_RECV_ARGS;
|
||||
gpu->cmd_args_remaining = 7;
|
||||
} break;
|
||||
|
||||
case GPU_STATE_RECV_ARGS: {
|
||||
if (!gpu->cmd_args_remaining) {
|
||||
gpu->state = GPU_STATE_RECV_DATA;
|
||||
|
||||
gpu->v0.c = gpu->buf[0] & 0xffffff;
|
||||
gpu->v0.x = gpu->buf[1] & 0xffff;
|
||||
gpu->v0.y = gpu->buf[1] >> 16;
|
||||
gpu->v1.c = gpu->buf[2] & 0xffffff;
|
||||
gpu->v1.x = gpu->buf[3] & 0xffff;
|
||||
gpu->v1.y = gpu->buf[3] >> 16;
|
||||
gpu->v2.c = gpu->buf[4] & 0xffffff;
|
||||
gpu->v2.x = gpu->buf[5] & 0xffff;
|
||||
gpu->v2.y = gpu->buf[5] >> 16;
|
||||
gpu->v3.c = gpu->buf[6] & 0xffffff;
|
||||
gpu->v3.x = gpu->buf[7] & 0xffff;
|
||||
gpu->v3.y = gpu->buf[7] >> 16;
|
||||
|
||||
log_fatal("v0=(%u, %u, %06x), v1=(%u, %u, %06x), v2=(%u, %u, %06x), v3=(%u, %u, %06x)",
|
||||
gpu->v0.x, gpu->v0.y, gpu->v0.c,
|
||||
gpu->v1.x, gpu->v1.y, gpu->v1.c,
|
||||
gpu->v2.x, gpu->v2.y, gpu->v2.c,
|
||||
gpu->v3.x, gpu->v3.y, gpu->v3.c
|
||||
);
|
||||
|
||||
gpu_render_shaded_triangle(gpu, gpu->v1, gpu->v0, gpu->v2);
|
||||
gpu_render_shaded_triangle(gpu, gpu->v3, gpu->v2, gpu->v1);
|
||||
|
||||
gpu->state = GPU_STATE_RECV_CMD;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void psx_gpu_update_cmd(psx_gpu_t* gpu) {
|
||||
switch (gpu->buf[0] >> 24) {
|
||||
case 0x00: /* nop */ break;
|
||||
case 0x02: gpu_cmd_02(gpu); break;
|
||||
case 0x28: gpu_cmd_28(gpu); break;
|
||||
case 0x30: gpu_cmd_30(gpu); break;
|
||||
case 0x38: gpu_cmd_38(gpu); break;
|
||||
case 0xa0: gpu_cmd_a0(gpu); break;
|
||||
case 0xe1: {
|
||||
gpu->gpustat = (gpu->buf[0] & 0x7ff) | 0x1c000000;
|
||||
} break;
|
||||
case 0xe2: {
|
||||
gpu->texw_mx = (gpu->buf[0] >> 0 ) & 0x1f;
|
||||
gpu->texw_my = (gpu->buf[0] >> 5 ) & 0x1f;
|
||||
gpu->texw_ox = (gpu->buf[0] >> 10) & 0x1f;
|
||||
gpu->texw_oy = (gpu->buf[0] >> 15) & 0x1f;
|
||||
} break;
|
||||
case 0xe3: {
|
||||
gpu->draw_x1 = (gpu->buf[0] >> 0 ) & 0x3ff;
|
||||
gpu->draw_y1 = (gpu->buf[0] >> 10) & 0x1ff;
|
||||
} break;
|
||||
case 0xe4: {
|
||||
gpu->draw_x2 = (gpu->buf[0] >> 0 ) & 0x3ff;
|
||||
gpu->draw_y2 = (gpu->buf[0] >> 10) & 0x1ff;
|
||||
} break;
|
||||
case 0xe5: {
|
||||
gpu->off_x = (gpu->buf[0] >> 0 ) & 0x7ff;
|
||||
gpu->off_y = (gpu->buf[0] >> 11) & 0x7ff;
|
||||
} break;
|
||||
case 0xe6: {
|
||||
/* To-do: Implement mask bit thing */
|
||||
} break;
|
||||
default: log_fatal("Unhandled GP0(%02Xh)", gpu->buf[0] >> 24); break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,9 +415,27 @@ void psx_gpu_write32(psx_gpu_t* gpu, uint32_t offset, uint32_t value) {
|
||||
case 0x08:
|
||||
gpu->display_mode = value & 0xffffff;
|
||||
|
||||
if (gpu->dmode_event_cb)
|
||||
gpu->dmode_event_cb(gpu);
|
||||
if (gpu->event_cb_table[GPU_EVENT_DMODE])
|
||||
gpu->event_cb_table[GPU_EVENT_DMODE](gpu);
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
switch (value & 7) {
|
||||
case 2:
|
||||
gpu->gpuread = ((gpu->texw_oy / 8) << 15) | ((gpu->texw_ox / 8) << 10) | ((gpu->texw_my / 8) << 5) | (gpu->texw_mx / 8);
|
||||
break;
|
||||
case 3:
|
||||
gpu->gpuread = (gpu->draw_y1 << 10) | gpu->draw_x1;
|
||||
break;
|
||||
case 4:
|
||||
gpu->gpuread = (gpu->draw_y2 << 10) | gpu->draw_x2;
|
||||
break;
|
||||
case 5: // Drawing Offset
|
||||
gpu->gpuread = (gpu->off_y << 10) | gpu->off_x;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
log_error("GP1(%02Xh) args=%06x", value >> 24, value & 0xffffff);
|
||||
@@ -210,14 +455,18 @@ void psx_gpu_write8(psx_gpu_t* gpu, uint32_t offset, uint8_t value) {
|
||||
log_warn("Unhandled 8-bit GPU write at offset %08x (%02x)", offset, value);
|
||||
}
|
||||
|
||||
void psx_gpu_set_dmode_event_callback(psx_gpu_t* gpu, psx_gpu_event_callback_t cb) {
|
||||
gpu->dmode_event_cb = cb;
|
||||
void psx_gpu_set_event_callback(psx_gpu_t* gpu, int event, psx_gpu_event_callback_t cb) {
|
||||
gpu->event_cb_table[event] = cb;
|
||||
}
|
||||
|
||||
void psx_gpu_set_udata(psx_gpu_t* gpu, int index, void* udata) {
|
||||
gpu->udata[index] = udata;
|
||||
}
|
||||
|
||||
void psx_gpu_update(psx_gpu_t* gpu) {
|
||||
// Do nothing for now
|
||||
}
|
||||
|
||||
void psx_gpu_destroy(psx_gpu_t* gpu) {
|
||||
free(gpu->vram);
|
||||
free(gpu);
|
||||
|
||||
+25
-8
@@ -5,6 +5,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ic.h"
|
||||
|
||||
#define PSX_GPU_BEGIN 0x1f801810
|
||||
#define PSX_GPU_SIZE 0x8
|
||||
#define PSX_GPU_END 0x1f801814
|
||||
@@ -14,6 +16,11 @@
|
||||
|
||||
#define PSX_GPU_VRAM_SIZE (0x100000)
|
||||
|
||||
enum {
|
||||
GPU_EVENT_DMODE,
|
||||
GPU_EVENT_VBLANK
|
||||
};
|
||||
|
||||
enum {
|
||||
GPU_STATE_RECV_CMD,
|
||||
GPU_STATE_RECV_ARGS,
|
||||
@@ -27,6 +34,11 @@ typedef struct psx_gpu_t psx_gpu_t;
|
||||
typedef void (*psx_gpu_cmd_t)(psx_gpu_t*);
|
||||
typedef void (*psx_gpu_event_callback_t)(psx_gpu_t*);
|
||||
|
||||
typedef struct {
|
||||
int32_t x, y;
|
||||
uint32_t c, t;
|
||||
} vertex_t;
|
||||
|
||||
struct psx_gpu_t {
|
||||
uint32_t io_base, io_size;
|
||||
|
||||
@@ -47,6 +59,7 @@ struct psx_gpu_t {
|
||||
uint32_t xsiz, ysiz;
|
||||
uint32_t addr;
|
||||
uint32_t xcnt, ycnt;
|
||||
vertex_t v0, v1, v2, v3;
|
||||
|
||||
// GPU state
|
||||
uint32_t state;
|
||||
@@ -66,18 +79,21 @@ struct psx_gpu_t {
|
||||
uint32_t texw_mx, texw_my;
|
||||
uint32_t texw_ox, texw_oy;
|
||||
|
||||
// CLUT offset
|
||||
uint32_t clut_x, clut_y;
|
||||
|
||||
psx_gpu_event_callback_t dmode_event_cb;
|
||||
// Display area
|
||||
uint32_t disp_x, disp_y;
|
||||
|
||||
uint32_t cycles;
|
||||
|
||||
psx_ic_t* ic;
|
||||
|
||||
psx_gpu_event_callback_t event_cb_table[8];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int32_t x, y;
|
||||
uint32_t c, t;
|
||||
} vertex_t;
|
||||
|
||||
psx_gpu_t* psx_gpu_create();
|
||||
void psx_gpu_init(psx_gpu_t*);
|
||||
void psx_gpu_init(psx_gpu_t*, psx_ic_t*);
|
||||
uint32_t psx_gpu_read32(psx_gpu_t*, uint32_t);
|
||||
uint16_t psx_gpu_read16(psx_gpu_t*, uint32_t);
|
||||
uint8_t psx_gpu_read8(psx_gpu_t*, uint32_t);
|
||||
@@ -86,6 +102,7 @@ void psx_gpu_write16(psx_gpu_t*, uint32_t, uint16_t);
|
||||
void psx_gpu_write8(psx_gpu_t*, uint32_t, uint8_t);
|
||||
void psx_gpu_destroy(psx_gpu_t*);
|
||||
void psx_gpu_set_udata(psx_gpu_t*, int, void*);
|
||||
void psx_gpu_set_dmode_event_callback(psx_gpu_t*, psx_gpu_event_callback_t);
|
||||
void psx_gpu_set_event_callback(psx_gpu_t*, int, psx_gpu_event_callback_t);
|
||||
void psx_gpu_update(psx_gpu_t*);
|
||||
|
||||
#endif
|
||||
+23
-11
@@ -3,26 +3,29 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "ic.h"
|
||||
|
||||
#include "../log.h"
|
||||
|
||||
psx_ic_t* psx_ic_create() {
|
||||
return (psx_ic_t*)malloc(sizeof(psx_ic_t));
|
||||
}
|
||||
|
||||
void psx_ic_init(psx_ic_t* ic) {
|
||||
void psx_ic_init(psx_ic_t* ic, psx_cpu_t* cpu) {
|
||||
memset(ic, 0, sizeof(psx_ic_t));
|
||||
|
||||
ic->io_base = PSX_IC_BEGIN;
|
||||
ic->io_size = PSX_IC_SIZE;
|
||||
|
||||
ic->i_stat = 0x00000000;
|
||||
ic->i_mask = 0x00000000;
|
||||
ic->stat = 0x00000000;
|
||||
ic->mask = 0x00000000;
|
||||
|
||||
ic->cpu = cpu;
|
||||
}
|
||||
|
||||
uint32_t psx_ic_read32(psx_ic_t* ic, uint32_t offset) {
|
||||
switch (offset) {
|
||||
case 0x00: return ic->i_stat;
|
||||
case 0x04: return ic->i_mask;
|
||||
case 0x00: return ic->stat;
|
||||
case 0x04: return ic->mask;
|
||||
}
|
||||
|
||||
log_warn("Unhandled 32-bit IC read at offset %08x", offset);
|
||||
@@ -32,8 +35,8 @@ uint32_t psx_ic_read32(psx_ic_t* ic, uint32_t offset) {
|
||||
|
||||
uint16_t psx_ic_read16(psx_ic_t* ic, uint32_t offset) {
|
||||
switch (offset) {
|
||||
case 0x00: return ic->i_stat;
|
||||
case 0x04: return ic->i_mask;
|
||||
case 0x00: return ic->stat;
|
||||
case 0x04: return ic->mask;
|
||||
}
|
||||
|
||||
log_warn("Unhandled 16-bit IC read at offset %08x", offset);
|
||||
@@ -49,8 +52,8 @@ uint8_t psx_ic_read8(psx_ic_t* ic, uint32_t offset) {
|
||||
|
||||
void psx_ic_write32(psx_ic_t* ic, uint32_t offset, uint32_t value) {
|
||||
switch (offset) {
|
||||
case 0x00: ic->i_stat = value; break;
|
||||
case 0x04: ic->i_mask = value; break;
|
||||
case 0x00: ic->stat = value; break;
|
||||
case 0x04: ic->mask = value; break;
|
||||
|
||||
default: {
|
||||
log_warn("Unhandled 32-bit IC write at offset %08x (%08x)", offset, value);
|
||||
@@ -60,8 +63,8 @@ void psx_ic_write32(psx_ic_t* ic, uint32_t offset, uint32_t value) {
|
||||
|
||||
void psx_ic_write16(psx_ic_t* ic, uint32_t offset, uint16_t value) {
|
||||
switch (offset) {
|
||||
case 0x00: ic->i_stat = value; break;
|
||||
case 0x04: ic->i_mask = value; break;
|
||||
case 0x00: ic->stat = value; break;
|
||||
case 0x04: ic->mask = value; break;
|
||||
|
||||
default: {
|
||||
log_warn("Unhandled 16-bit IC write at offset %08x (%08x)", offset, value);
|
||||
@@ -73,6 +76,15 @@ void psx_ic_write8(psx_ic_t* ic, uint32_t offset, uint8_t value) {
|
||||
log_warn("Unhandled 8-bit IC write at offset %08x (%02x)", offset, value);
|
||||
}
|
||||
|
||||
void psx_ic_irq(psx_ic_t* ic, int id) {
|
||||
if (!(ic->mask & id))
|
||||
return;
|
||||
|
||||
ic->stat = id;
|
||||
|
||||
psx_cpu_irq(ic->cpu, true);
|
||||
}
|
||||
|
||||
void psx_ic_destroy(psx_ic_t* ic) {
|
||||
free(ic);
|
||||
}
|
||||
+37
-3
@@ -3,10 +3,41 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../cpu.h"
|
||||
|
||||
#define PSX_IC_BEGIN 0x1f801070
|
||||
#define PSX_IC_SIZE 0x8
|
||||
#define PSX_IC_END 0x1F801077
|
||||
|
||||
/*
|
||||
0 IRQ0 VBLANK (PAL=50Hz, NTSC=60Hz)
|
||||
1 IRQ1 GPU Can be requested via GP0(1Fh) command (rarely used)
|
||||
2 IRQ2 CDROM
|
||||
3 IRQ3 DMA
|
||||
4 IRQ4 TMR0 Timer 0 aka Root Counter 0 (Sysclk or Dotclk)
|
||||
5 IRQ5 TMR1 Timer 1 aka Root Counter 1 (Sysclk or H-blank)
|
||||
6 IRQ6 TMR2 Timer 2 aka Root Counter 2 (Sysclk or Sysclk/8)
|
||||
7 IRQ7 Controller and Memory Card - Byte Received Interrupt
|
||||
8 IRQ8 SIO
|
||||
9 IRQ9 SPU
|
||||
10 IRQ10 Controller - Lightpen Interrupt (reportedly also PIO...?)
|
||||
11-15 Not used (always zero)
|
||||
16-31 Garbage
|
||||
*/
|
||||
enum {
|
||||
IC_VBLANK = 0x001,
|
||||
IC_GPU = 0x002,
|
||||
IC_CDROM = 0x004,
|
||||
IC_DM = 0x008,
|
||||
IC_TMR0 = 0x010,
|
||||
IC_TMR1 = 0x020,
|
||||
IC_TMR2 = 0x040,
|
||||
IC_CTRL = 0x080,
|
||||
IC_SIO = 0x100,
|
||||
IC_SPU = 0x200,
|
||||
IC_LP_PIO = 0x400
|
||||
};
|
||||
|
||||
/*
|
||||
1F801070h 2 I_STAT - Interrupt status register
|
||||
1F801074h 2 I_MASK - Interrupt mask register
|
||||
@@ -15,18 +46,21 @@
|
||||
typedef struct {
|
||||
uint32_t io_base, io_size;
|
||||
|
||||
uint16_t i_stat;
|
||||
uint16_t i_mask;
|
||||
uint16_t stat;
|
||||
uint16_t mask;
|
||||
|
||||
psx_cpu_t* cpu;
|
||||
} psx_ic_t;
|
||||
|
||||
psx_ic_t* psx_ic_create();
|
||||
void psx_ic_init(psx_ic_t*);
|
||||
void psx_ic_init(psx_ic_t*, psx_cpu_t*);
|
||||
uint32_t psx_ic_read32(psx_ic_t*, uint32_t);
|
||||
uint16_t psx_ic_read16(psx_ic_t*, uint32_t);
|
||||
uint8_t psx_ic_read8(psx_ic_t*, uint32_t);
|
||||
void psx_ic_write32(psx_ic_t*, uint32_t, uint32_t);
|
||||
void psx_ic_write16(psx_ic_t*, uint32_t, uint16_t);
|
||||
void psx_ic_write8(psx_ic_t*, uint32_t, uint8_t);
|
||||
void psx_ic_irq(psx_ic_t*, int);
|
||||
void psx_ic_destroy(psx_ic_t*);
|
||||
|
||||
#endif
|
||||
@@ -26,6 +26,7 @@ void psx_load_exe(psx_t* psx, const char* path) {
|
||||
|
||||
void psx_update(psx_t* psx) {
|
||||
psx_cpu_cycle(psx->cpu);
|
||||
psx_gpu_update(psx->gpu);
|
||||
}
|
||||
|
||||
void psx_run_frame(psx_t* psx) {
|
||||
@@ -35,7 +36,7 @@ void psx_run_frame(psx_t* psx) {
|
||||
unsigned int counter = (float)PSX_CPU_SPEED / framerate;
|
||||
|
||||
while (counter--) {
|
||||
psx_cpu_cycle(psx->cpu);
|
||||
psx_update(psx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,9 +79,9 @@ void psx_init(psx_t* psx, const char* bios_path) {
|
||||
psx_mc1_init(psx->mc1);
|
||||
psx_mc2_init(psx->mc2);
|
||||
psx_mc3_init(psx->mc3);
|
||||
psx_ic_init(psx->ic);
|
||||
psx_ic_init(psx->ic, psx->cpu);
|
||||
psx_scratchpad_init(psx->scratchpad);
|
||||
psx_gpu_init(psx->gpu);
|
||||
psx_gpu_init(psx->gpu, psx->ic);
|
||||
psx_spu_init(psx->spu);
|
||||
psx_cpu_init(psx->cpu, psx->bus);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user