commit fa1190dccb02895c82f3b65ea09e28b7a2f2d2d8
parent 734b221f69109ea06644f5430fd2284b497832f5
Author: root <root@fif>
Date: Sun, 21 Jul 2024 09:59:15 +0000
Progress on the gpu implementation.
Implemented some GP0 and GP1 opcodes
Diffstat:
5 files changed, 162 insertions(+), 10 deletions(-)
diff --git a/src/gpu.c b/src/gpu.c
@@ -21,6 +21,12 @@ GPU_new(void)
}
u32
+GPU_read(GPU* gpu)
+{
+ return 0;
+}
+
+u32
GPU_status(GPU* gpu)
{
u32 r;
@@ -73,7 +79,7 @@ GPU_status(GPU* gpu)
}
void
-GPU_gp0(GPU* gpu, u32 val)
+GPU_gp1(GPU* gpu, u32 val)
{
u32 opcode;
@@ -82,13 +88,76 @@ GPU_gp0(GPU* gpu, u32 val)
switch (opcode)
{
- case 0xe1: GPU_gp0_draw_mode(gpu, val); break;
- default: fprintf(stderr, "Unhandled GP0 command %08X\n", val); exit(1);
+ case 0x00: GPU_gp1_reset(gpu, val); break;
+ case 0x04: GPU_gp1_dma_direction(gpu, val); break;
+ case 0x08: GPU_gp1_display_mode(gpu, val); break;
+ default: fprintf(stderr, "OP: %08X: Unhandled GP1 command %08X\n", opcode, val); exit(1);
}
}
-/* TOBECONTINUED */
+void
+GPU_gp1_reset(GPU* gpu, u32 val)
+{
+ memset(gpu, 0, sizeof(GPU));
+ /* Fill out the rest of the fields with no$cash spec reset values*/
+ gpu->display_disabled = 1;
+ gpu->interlaced = 1;
+ gpu->display_horiz_start = 0x200;
+ gpu->display_horiz_end = 0xc00;
+ gpu->display_line_start = 0x10;
+ gpu->display_line_end = 0x100;
+}
+
+void
+GPU_gp1_dma_direction(GPU* gpu, u32 val)
+{
+ switch (val & 3) {
+ case 0: gpu->dma_direction = DMA_DIR_OFF; break;
+ case 1: gpu->dma_direction = DMA_DIR_FIFO; break;
+ case 2: gpu->dma_direction = DMA_DIR_CPUTOGP0; break;
+ case 3: gpu->dma_direction = DMA_DIR_VRAMTOCPU; break;
+ default: fprintf(stderr, "UNREACHABLE"); exit(EXIT_FAILURE);
+ }
+}
+
+void
+GPU_gp1_display_mode(GPU* gpu, u32 val)
+{
+ u8 hr1, hr2;
+
+ hr1 = (u8)(val & 3);
+ hr2 = (u8)((val >> 6) & 1);
+
+ gpu->hres = HOR_RES_from_fields(hr1, hr2);
+ gpu->vres = (val & 0x4);
+ gpu->vmode = (val & 0x8) ? VMODE_PAL : VMODE_NTSC;
+ gpu->display_depth = (val & 0x10) ? DISP_DEPTH_D24BITS : DISP_DEPTH_D15BITS;
+ gpu->interlaced = (val & 0x20);
+
+ if (val & 0x80)
+ fprintf(stderr, "Unsupported display mode %08X\n", val), exit(EXIT_FAILURE);
+}
+
+void
+GPU_gp0(GPU* gpu, u32 val)
+{
+ u32 opcode;
+
+ opcode = (val >> 24) & 0xff;
+
+ switch (opcode) {
+ case 0x00: break;
+ case 0xe1: GPU_gp0_draw_mode(gpu, val); break;
+ case 0xe2: GPU_gp0_texture_window(gpu, val); break;
+ case 0xe3: GPU_gp0_drawing_area_top_left(gpu, val); break;
+ case 0xe4: GPU_gp0_drawing_area_bottom_right(gpu, val); break;
+ case 0xe5: GPU_gp0_drawing_offset(gpu, val); break;
+ case 0xe6: GPU_gp0_mask_bit_setting(gpu, val); break;
+ default: fprintf(stderr, "OP: %08X: Unhandled GP0 command %08X\n", opcode, val); exit(1);
+ }
+}
+
void
GPU_gp0_draw_mode(GPU* gpu, u32 val)
{
@@ -107,5 +176,53 @@ GPU_gp0_draw_mode(GPU* gpu, u32 val)
default: fprintf(stderr, "Unhandled texture depth %d\n", (val >> 7) & 3); exit(1);
}
+ gpu->dithering = ((val >> 9) & 1);
+ gpu->draw_to_display = ((val >> 10) & 1);
+ gpu->texture_disable = ((val >> 11) & 1);
+ gpu->rectangle_texture_x_flip = ((val >> 12) & 1);
+ gpu->rectangle_texture_y_flip = ((val >> 13) & 1);
+}
+
+void
+GPU_gp0_drawing_area_top_left(GPU* gpu, u32 val)
+{
+ gpu->drawing_area_top = (u16)((val >> 10) & 0x3ff);
+ gpu->drawing_area_left = (u16)(val & 0x3ff);
+}
+
+void
+GPU_gp0_drawing_area_bottom_right(GPU* gpu, u32 val)
+{
+ gpu->drawing_area_bottom = (u16)((val >> 10) & 0x3ff);
+ gpu->drawing_area_right = (u16)(val & 0x3ff);
+}
+
+void
+GPU_gp0_drawing_offset(GPU* gpu, u32 val)
+{
+ u16 x, y;
+
+ x = (u16)(val & 0x7ff);
+ y = (u16)((val >> 11) & 0x7ff);
+
+ /* Values here are 11bit 2s complement signed values, we need to force sign extension */
+ gpu->drawing_x_offset = ((i16)(x << 5)) >> 5;
+ gpu->drawing_y_offset = ((i16)(y << 5)) >> 5;
+
}
+void
+GPU_gp0_texture_window(GPU* gpu, u32 val)
+{
+ gpu->texture_window_x_mask = (u8)(val & 0x1f);
+ gpu->texture_window_y_mask = (u8)((val >> 5) & 0x1f);
+ gpu->texture_window_x_offset = (u8)((val >> 10) & 0x1f);
+ gpu->texture_window_y_offset = (u8)((val >> 15) & 0x1f);
+}
+
+void
+GPU_gp0_mask_bit_setting(GPU* gpu, u32 val)
+{
+ gpu->force_set_mask_bit = val & 1;
+ gpu->preserve_masked_pixels = val & 2;
+}
diff --git a/src/gpu.h b/src/gpu.h
@@ -53,10 +53,38 @@ typedef struct _GPU {
u8 rectangle_texture_x_flip;
u8 rectangle_texture_y_flip;
+
+ u8 texture_window_x_mask;
+ u8 texture_window_y_mask;
+ u8 texture_window_x_offset;
+ u8 texture_window_y_offset;
+ u16 drawing_area_left;
+ u16 drawing_area_top;
+ u16 drawing_area_right;
+ u16 drawing_area_bottom;
+ i16 drawing_x_offset;
+ i16 drawing_y_offset;
+ u16 display_vram_x_start;
+ u16 display_vram_y_start;
+ u16 display_horiz_start;
+ u16 display_horiz_end;
+ u16 display_line_start;
+ u16 display_line_end;
+
} GPU;
u8 HOR_RES_from_fields(u8, u8);
u32 HOR_RES_into_status(u8);
+void GPU_gp1(GPU*, u32);
+void GPU_gp1_reset(GPU*, u32); /* GP1(0x00): Reset */
+void GPU_gp1_dma_direction(GPU*, u32); /* GP1(0x04): DMA Direction */
+void GPU_gp1_display_mode(GPU*, u32); /* GP1(0x08): Display Mode */
void GPU_gp0(GPU*, u32);
void GPU_gp0_draw_mode(GPU*, u32);
+void GPU_gp0_drawing_area_top_left(GPU*, u32); /* GP0(0xe3): Set Drawing Area top left */
+void GPU_gp0_drawing_area_bottom_right(GPU*, u32); /* GP0(0xe4): Set Drawing Area bottom right */
+void GPU_gp0_drawing_offset(GPU*, u32); /* GP0(0xe5): Set Drawing Offset */
+void GPU_gp0_texture_window(GPU*, u32); /* GP0(0xe2): Set Texture Window */
+void GPU_gp0_mask_bit_setting(GPU*, u32); /* GP0(0xe6): Set Mask Bit Setting */
GPU* GPU_new(void);
+u32 GPU_read(GPU*);
diff --git a/src/interconnect.c b/src/interconnect.c
@@ -7,6 +7,7 @@
#include "util.h"
#include "types.h"
#include "defs.h"
+#include "gpu.h"
Interconnect*
new_interconnect(void) {
@@ -14,6 +15,7 @@ new_interconnect(void) {
inter->bios = BIOS_new("roms/scph1001.bin");
inter->ram = RAM_new();
inter->dma = DMA_new();
+ inter->gpu = GPU_new();
return inter;
}
@@ -149,12 +151,11 @@ INTER_load32(Interconnect* inter, u32 addr)
contains = UTIL_contains(GPU_START, GPU_SIZE, abs_addr, &offset);
if (contains)
{
-#ifndef DEBUG
printf("GPU read %08X\n", abs_addr);
-#endif
switch(offset)
{
+ case 0: return GPU_read(inter->gpu); /* NOT COMPLETE */
case 4: return 0x1c000000;
default: return 0;
}
@@ -247,7 +248,7 @@ INTER_store16(Interconnect* inter, u32 addr, u16 val)
PANIC("Unhandled store16 into abs_address: %08X\n", abs_addr);
}
- void
+void
INTER_store32(Interconnect* inter, u32 addr, u32 val)
{
u32 offset;
@@ -317,9 +318,13 @@ INTER_store32(Interconnect* inter, u32 addr, u32 val)
contains = UTIL_contains(GPU_START, GPU_SIZE, abs_addr, &offset);
if (contains)
{
-#ifndef DEBUG
fprintf(stdout, "GPU write %08X to address %08X\n", val, offset);
-#endif
+ switch (offset) {
+ case 0: GPU_gp0(inter->gpu, val); break;
+ case 4: GPU_gp1(inter->gpu, val); break;
+ default: fprintf(stderr, "GPU write %08X: %08X", offset, val); exit(EXIT_FAILURE);
+ }
+
return;
}
@@ -543,6 +548,7 @@ INTER_do_dma_linked_list(Interconnect* inter, Port port)
while (remsz > 0) {
addr = (addr + 4) & 0x1ffffc;
command = RAM_load32(inter->ram, addr);
+ GPU_gp0(inter->gpu, command);
#ifndef DEBUG
printf("GPU command %08X\n", command);
#endif
diff --git a/src/interconnect.h b/src/interconnect.h
@@ -2,12 +2,14 @@
#include "bios.h"
#include "mem.h"
+#include "gpu.h"
#include "types.h"
struct Interconnect {
BIOS* bios;
RAM* ram;
DMA* dma;
+ GPU* gpu;
};
typedef struct Interconnect Interconnect;
diff --git a/src/main.c b/src/main.c
@@ -14,7 +14,6 @@ int
main(int argc, char **argv)
{
CPU* cpu;
- GPU* gpu;
Interconnect* inter;
inter = new_interconnect();