commit 734b221f69109ea06644f5430fd2284b497832f5
parent dd25e590a2a1f91dd5a6ea1023d96546cb0aef74
Author: edea <none@fithos.xyz>
Date: Sun, 14 Jul 2024 11:26:06 +0300
continuing with GPUSTAT register
Diffstat:
| M | build.sh | | | 2 | +- |
| M | src/gpu.c | | | 110 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | src/gpu.h | | | 51 | ++++++++++++++++++++++++++++++++++++++++----------- |
| M | src/interconnect.c | | | 310 | ++++++++++++++++++++++++++++++++++++++++---------------------------------------- |
| M | src/main.c | | | 2 | ++ |
| M | test.cc | | | 6 | ++++++ |
6 files changed, 314 insertions(+), 167 deletions(-)
diff --git a/build.sh b/build.sh
@@ -1 +1 @@
-c++ -O3 -Wall -Wpedantic -static -Wall -pedantic -g src/*.c -o bin/ultimecia
+cc -O3 -Wall -Wpedantic -static -Wall -pedantic -g src/*.c -o bin/ultimecia
diff --git a/src/gpu.c b/src/gpu.c
@@ -1 +1,111 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "gpu.h"
+#include "types.h"
+#include "defs.h"
+
+u8 HOR_RES_from_fields(u8 hr1, u8 hr2) { return (hr2 & 1) | ((hr1 & 3) << 1); }
+u32 HOR_RES_into_status(u8 hr) {return ((u32)hr) << 16; }
+
+GPU*
+GPU_new(void)
+{
+ GPU* gpu;
+
+ gpu = (GPU*)malloc(sizeof(GPU));
+ memset(gpu, 0, sizeof(GPU));
+ gpu->display_disabled = 1;
+
+ return gpu;
+}
+
+u32
+GPU_status(GPU* gpu)
+{
+ u32 r;
+ u32 dma_req;
+
+ dma_req = 0;
+ r = 0;
+
+ r |= ((u32)gpu->page_base_x) << 0;
+ r |= ((u32)gpu->page_base_y) << 4;
+ r |= ((u32)gpu->semi_transparency) << 5;
+ r |= ((u32)gpu->texture_depth) << 7;
+ r |= ((u32)gpu->dithering) << 9;
+ r |= ((u32)gpu->draw_to_display) << 10;
+ r |= ((u32)gpu->force_set_mask_bit) << 11;
+ r |= ((u32)gpu->preserve_masked_pixels) << 12;
+ r |= ((u32)gpu->field) << 13;
+ /* Bit 14 not supported */
+ r |= ((u32)gpu->texture_disable) << 15;
+ r |= HOR_RES_into_status(gpu->hres);
+ r |= ((u32)gpu->vres) << 19;
+ r |= ((u32)gpu->vmode) << 20;
+ r |= ((u32)gpu->display_depth) << 21;
+ r |= ((u32)gpu->interlaced) << 22;
+ r |= ((u32)gpu->display_disabled) << 23;
+ r |= ((u32)gpu->interrupt) << 24;
+
+ /* Always GPU is ready */
+ r |= 1 << 26;
+ r |= 1 << 27;
+ r |= 1 << 28;
+
+ r |= ((u32) gpu->dma_direction) << 29;
+
+ /* Ignore odd lines for now */
+ r |= 0 << 31;
+
+ switch(gpu->dma_direction)
+ {
+ case DMA_DIR_OFF: dma_req = 0; break;
+ case DMA_DIR_FIFO: dma_req = 1; break;
+ case DMA_DIR_CPUTOGP0: dma_req = (r >> 28) & 1; break;
+ case DMA_DIR_VRAMTOCPU: dma_req = (r >> 27) & 1; break;
+ default: fprintf(stderr, "UNREACHABLE"); exit(1);
+ }
+
+ r |= dma_req << 25;
+
+ return r;
+}
+
+void
+GPU_gp0(GPU* gpu, u32 val)
+{
+
+ u32 opcode;
+
+ opcode = (val >> 24) & 0xff;
+
+ switch (opcode)
+ {
+ case 0xe1: GPU_gp0_draw_mode(gpu, val); break;
+ default: fprintf(stderr, "Unhandled GP0 command %08X\n", val); exit(1);
+ }
+
+}
+
+/* TOBECONTINUED */
+void
+GPU_gp0_draw_mode(GPU* gpu, u32 val)
+{
+ gpu->page_base_x = (u8)(val & 0xf);
+ gpu->page_base_y = (u8)((val >> 4) & 1);
+ gpu->semi_transparency = (u8)((val >> 5) & 3);
+
+ /* Thought i would try ternary but I am not sure if this actually works
+ gpu->texture_depth = (val >> 7 & 3) ? 0 ? TD_T4BIT ? 1 ? TD_T8BIT ? 2 ? TD_T15BIT : 0 : 0 : 0 : 0 : 0 : 0;*/
+
+ switch ((val >> 7) & 3)
+ {
+ case 0: gpu->texture_depth = TD_T4BIT; break;
+ case 1: gpu->texture_depth = TD_T8BIT; break;
+ case 2: gpu->texture_depth = TD_T15BIT; break;
+ default: fprintf(stderr, "Unhandled texture depth %d\n", (val >> 7) & 3); exit(1);
+ }
+
+}
diff --git a/src/gpu.h b/src/gpu.h
@@ -1,5 +1,36 @@
#pragma once
+#include "types.h"
+
+typedef enum _TEXTURE_DEPTH {
+ TD_T4BIT,
+ TD_T8BIT,
+ TD_T15BIT,
+} TEXTURE_DEPTH;
+
+typedef enum _FIELD {
+ F_TOP,
+ F_BOTTOM,
+} FIELD;
+
+typedef enum _DMA_DIRECTION {
+ DMA_DIR_OFF,
+ DMA_DIR_FIFO,
+ DMA_DIR_CPUTOGP0,
+ DMA_DIR_VRAMTOCPU
+} DMA_DIRECTION;
+
+typedef enum _VMODE {
+ VMODE_NTSC,
+ VMODE_PAL,
+} VMODE;
+
+typedef enum _DISPLAY_DEPTH {
+ DISP_DEPTH_D15BITS,
+ DISP_DEPTH_D24BITS,
+} DISPLAY_DEPTH;
+
+/* line 1045 in no$psx docs */
typedef struct _GPU {
u8 page_base_x;
u8 page_base_y;
@@ -14,20 +45,18 @@ typedef struct _GPU {
u8 hres;
u8 vres;
VMODE vmode;
- DISPLAY_DEPTH diplay_depth;
+ DISPLAY_DEPTH display_depth;
u8 interlaced;
u8 display_disabled;
u8 interrupt;
DMA_DIRECTION dma_direction;
-} GPU;
-typdef enum _TEXTURE_DEPTH {
- TD_T4BIT,
- TD_T8BIT,
- TD_T15BIT,
-} TEXTURE_DEPTH;
+ u8 rectangle_texture_x_flip;
+ u8 rectangle_texture_y_flip;
+} GPU;
-typedef enum _FIELD {
- F_TOP,
- F_BOTTOM,
-} FIELD;
+u8 HOR_RES_from_fields(u8, u8);
+u32 HOR_RES_into_status(u8);
+void GPU_gp0(GPU*, u32);
+void GPU_gp0_draw_mode(GPU*, u32);
+GPU* GPU_new(void);
diff --git a/src/interconnect.c b/src/interconnect.c
@@ -58,10 +58,10 @@ INTER_load16(Interconnect* inter, u32 addr)
{
u32 offset;
u32 abs_addr;
- u32 contains;
+ u32 contains;
offset = 0;
- contains = 0;
+ contains = 0;
abs_addr = mask_region(addr);
if (addr % 2 != 0)
@@ -73,12 +73,12 @@ INTER_load16(Interconnect* inter, u32 addr)
/* Assert abs_address Mappings */
contains = UTIL_contains(SPU_START, SPU_SIZE, abs_addr, &offset);
if (contains)
- {
+ {
#ifndef DEBUG
- fprintf(stderr, "Unhandled read from SPU register: %08X\n", offset);
+ fprintf(stderr, "Unhandled read from SPU register: %08X\n", offset);
#endif
- return 0;
- }
+ return 0;
+ }
contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
if (contains)
@@ -96,15 +96,15 @@ INTER_load16(Interconnect* inter, u32 addr)
PANIC("Unhandled Load16 At Address %08X\n", abs_addr);
}
-u32
+ u32
INTER_load32(Interconnect* inter, u32 addr)
{
u32 offset;
u32 abs_addr;
- u32 contains;
+ u32 contains;
offset = 0;
- contains = 0;
+ contains = 0;
abs_addr = mask_region(addr);
if (addr % 4 != 0)
@@ -143,7 +143,7 @@ INTER_load32(Interconnect* inter, u32 addr)
contains = UTIL_contains(DMA_START, DMA_SIZE, abs_addr, &offset);
if (contains)
{
- return INTER_dma_reg(inter, offset);
+ return INTER_dma_reg(inter, offset);
}
contains = UTIL_contains(GPU_START, GPU_SIZE, abs_addr, &offset);
@@ -153,17 +153,17 @@ INTER_load32(Interconnect* inter, u32 addr)
printf("GPU read %08X\n", abs_addr);
#endif
- switch(offset)
- {
- case 4: return 0x1c000000;
- default: return 0;
- }
+ switch(offset)
+ {
+ case 4: return 0x1c000000;
+ default: return 0;
+ }
}
PANIC("Unhandled Load32 At Address %08X\n", addr);
}
-void
+ void
INTER_store8(Interconnect* inter, u32 addr, u8 val)
{
u32 offset;
@@ -193,7 +193,7 @@ INTER_store8(Interconnect* inter, u32 addr, u8 val)
PANIC("Unhandled store8 into abs_address: %08X\n", abs_addr);
}
-void
+ void
INTER_store16(Interconnect* inter, u32 addr, u16 val)
{
u32 offset;
@@ -231,7 +231,7 @@ INTER_store16(Interconnect* inter, u32 addr, u16 val)
contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
if (contains)
{
- RAM_store16(inter->ram, offset, val);
+ RAM_store16(inter->ram, offset, val);
return;
}
@@ -239,7 +239,7 @@ INTER_store16(Interconnect* inter, u32 addr, u16 val)
if (contains)
{
#ifndef DEBUG
- printf("IRQ control write %08X at address %08X\n", val, offset);
+ printf("IRQ control write %08X at address %08X\n", val, offset);
#endif
return;
}
@@ -247,22 +247,22 @@ 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;
- u32 contains;
+ u32 contains;
u32 abs_addr;
- offset = 0;
- contains = 0;
+ offset = 0;
+ contains = 0;
abs_addr = mask_region(addr);
if (addr % 4 != 0) {
#ifndef DEBUG
fprintf(stderr, "Unaligned_store32_address: %08X", addr);
#endif
- }
+ }
contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
if (contains)
@@ -351,90 +351,90 @@ INTER_store32(Interconnect* inter, u32 addr, u32 val)
PANIC("Unhandled store32 into abs_address: %08X\n", addr);
}
-u32
+ u32
INTER_dma_reg(Interconnect* inter, u32 offset)
{
u32 major, minor, val;
- Channel* channel;
+ Channel* channel;
major = (offset & 0x70) >> 4;
minor = offset & 0xf;
switch (major) {
- case 0: case 1: case 2: case 3: case 4: case 5: case 6:
- //if ((Port)major < 0) {
- // fprintf(stderr, "WHATTTTTTTTT");
- // exit(1);
- //}
-
- channel = &inter->dma->channels[(Port)major];
- switch (minor) {
- case 0: val = CHANNEL_base(channel); break;
- case 4: val = CHANNEL_block_control(channel); break;
- case 8: val = CHANNEL_control(channel); break;
- default: fprintf(stderr, "Unhandled DMA read at %08X\n", offset); exit(EXIT_FAILURE);
- }
- break;
- case 7:
- switch (minor) {
- case 0: val = DMA_control(inter->dma); break;
- case 4: val = DMA_interrupt(inter->dma); break;
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6:
+ //if ((Port)major < 0) {
+ // fprintf(stderr, "WHATTTTTTTTT");
+ // exit(1);
+ //}
+
+ channel = &inter->dma->channels[(Port)major];
+ switch (minor) {
+ case 0: val = CHANNEL_base(channel); break;
+ case 4: val = CHANNEL_block_control(channel); break;
+ case 8: val = CHANNEL_control(channel); break;
+ default: fprintf(stderr, "Unhandled DMA read at %08X\n", offset); exit(EXIT_FAILURE);
+ }
+ break;
+ case 7:
+ switch (minor) {
+ case 0: val = DMA_control(inter->dma); break;
+ case 4: val = DMA_interrupt(inter->dma); break;
+ default: fprintf(stderr, "unhandled DMA access %08X\n", offset); exit(EXIT_FAILURE);
+ }
+ break;
default: fprintf(stderr, "unhandled DMA access %08X\n", offset); exit(EXIT_FAILURE);
- }
- break;
- default: fprintf(stderr, "unhandled DMA access %08X\n", offset); exit(EXIT_FAILURE);
}
return val;
}
-void
+ void
INTER_set_dma_reg(Interconnect* inter, u32 offset, u32 val)
{
u32 major, minor;
- Channel* channel;
- Port port, active_port;
+ Channel* channel;
+ Port port, active_port;
major = (offset & 0x70) >> 4;
minor = offset & 0xf;
active_port = PORT_INVALID;
switch (major) {
- case 0: case 1: case 2: case 3: case 4: case 5: case 6:
-
- port = (Port)major;
- channel = &inter->dma->channels[port];
-
- switch (minor) {
- case 0: CHANNEL_set_base(channel, val); break;
- case 4: CHANNEL_set_block_control(channel, val); break;
- case 8: CHANNEL_set_control(channel, val); break;
- default: fprintf(stderr, "Unhandled DMA write at %08X\n", offset); exit(EXIT_FAILURE);
- }
- if (CHANNEL_active(channel)) {
- active_port = port;
- } else {
- active_port = PORT_INVALID;
- }
- break;
- case 7:
- switch (minor) {
- case 0: DMA_set_control(inter->dma, val); break;
- case 4: DMA_set_interrupt(inter->dma, val); break;
- default: active_port = PORT_INVALID; break;// fprintf(stderr, "unhandled DMA write %08X\n", offset); exit(EXIT_FAILURE);
- }
- break;
- default: fprintf(stderr, "unhandled DMA write %08X\n", offset); exit(EXIT_FAILURE);
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6:
+
+ port = (Port)major;
+ channel = &inter->dma->channels[port];
+
+ switch (minor) {
+ case 0: CHANNEL_set_base(channel, val); break;
+ case 4: CHANNEL_set_block_control(channel, val); break;
+ case 8: CHANNEL_set_control(channel, val); break;
+ default: fprintf(stderr, "Unhandled DMA write at %08X\n", offset); exit(EXIT_FAILURE);
+ }
+ if (CHANNEL_active(channel)) {
+ active_port = port;
+ } else {
+ active_port = PORT_INVALID;
+ }
+ break;
+ case 7:
+ switch (minor) {
+ case 0: DMA_set_control(inter->dma, val); break;
+ case 4: DMA_set_interrupt(inter->dma, val); break;
+ default: active_port = PORT_INVALID; break;// fprintf(stderr, "unhandled DMA write %08X\n", offset); exit(EXIT_FAILURE);
+ }
+ break;
+ default: fprintf(stderr, "unhandled DMA write %08X\n", offset); exit(EXIT_FAILURE);
}
- if (active_port != PORT_INVALID)
- INTER_do_dma(inter, (Port)active_port);
+ if (active_port != PORT_INVALID)
+ INTER_do_dma(inter, (Port)active_port);
}
-void
+ void
INTER_do_dma(Interconnect* inter, Port port)
{
Channel* ch;
if (port == PORT_INVALID) {
- printf("%d\n", port);
+ printf("%d\n", port);
fprintf(stderr, "Invalid port doing dma\n");
exit(EXIT_FAILURE);
}
@@ -442,8 +442,8 @@ INTER_do_dma(Interconnect* inter, Port port)
ch = &inter->dma->channels[(Port)port];
switch (ch->sync) {
- case SYNC_LINKED_LIST: INTER_do_dma_linked_list(inter, port); break;
- default: INTER_do_dma_block(inter, port); break;
+ case SYNC_LINKED_LIST: INTER_do_dma_linked_list(inter, port); break;
+ default: INTER_do_dma_block(inter, port); break;
}
}
@@ -452,69 +452,69 @@ INTER_do_dma_block(Interconnect* inter, Port port)
{
Channel *ch;
u32 addr;
- u32 increment;
- u32 src_word;
- u32 remsz;
+ u32 increment;
+ u32 src_word;
+ u32 remsz;
ch = &inter->dma->channels[port];
- remsz = 0;
+ remsz = 0;
switch (ch->step) {
- case STEP_INCREMENT: increment = 4; break;
- case STEP_DECREMENT: increment = -4; break;
- default: fprintf(stderr, "Unreachable!\n"); exit(EXIT_FAILURE);
+ case STEP_INCREMENT: increment = 4; break;
+ case STEP_DECREMENT: increment = -4; break;
+ default: fprintf(stderr, "Unreachable!\n"); exit(EXIT_FAILURE);
}
- addr = ch->base;
+ addr = ch->base;
- // printf("%d\n", port);
- // printf("%08X %08X %d\n", ch->block_size, ch->block_count, (Port)ch->step);
+ // printf("%d\n", port);
+ // printf("%08X %08X %d\n", ch->block_size, ch->block_count, (Port)ch->step);
- if (!CHANNEL_transfer_size(ch, &remsz)) {
- fprintf(stderr, "Couldn't figure out DMA block transfer size\n");
- exit(EXIT_FAILURE);
- }
+ if (!CHANNEL_transfer_size(ch, &remsz)) {
+ fprintf(stderr, "Couldn't figure out DMA block transfer size\n");
+ exit(EXIT_FAILURE);
+ }
- while (remsz > 0) {
- u32 cur_addr;
- cur_addr = addr & 0x1ffffc;
+ while (remsz > 0) {
+ u32 cur_addr;
+ cur_addr = addr & 0x1ffffc;
- switch (ch->direction) {
- case DIR_FROM_RAM:
- src_word = RAM_load32(inter->ram, cur_addr);
- switch(port) {
- case PORT_GPU:
+ switch (ch->direction) {
+ case DIR_FROM_RAM:
+ src_word = RAM_load32(inter->ram, cur_addr);
+ switch(port) {
+ case PORT_GPU:
#ifndef DEBUG
- printf("GPU data %08X\n", src_word);
+ printf("GPU data %08X\n", src_word);
#endif
- break;
- default:
- fprintf(stderr, "Unhandled DMA destination port: %d", (u8)port);
- exit(EXIT_FAILURE);
- }
- break;
- case DIR_TO_RAM:
- switch(port) {
- case PORT_OTC:
- if (remsz == 1) {
- src_word = 0xffffff;
- } else {
- src_word = (addr - 4) & 0x1fffff;
- }
- break;
- default:
- fprintf(stderr, "Unhandled DMA source port: %d", (u8)port);
- exit(EXIT_FAILURE);
- }
- RAM_store32(inter->ram, cur_addr, src_word);
- break;
- default: break;
- }
-
- addr += increment;
- remsz--;
- }
- CHANNEL_done(ch);
+ break;
+ default:
+ fprintf(stderr, "Unhandled DMA destination port: %d", (u8)port);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case DIR_TO_RAM:
+ switch(port) {
+ case PORT_OTC:
+ if (remsz == 1) {
+ src_word = 0xffffff;
+ } else {
+ src_word = (addr - 4) & 0x1fffff;
+ }
+ break;
+ default:
+ fprintf(stderr, "Unhandled DMA source port: %d", (u8)port);
+ exit(EXIT_FAILURE);
+ }
+ RAM_store32(inter->ram, cur_addr, src_word);
+ break;
+ default: break;
+ }
+
+ addr += increment;
+ remsz--;
+ }
+ CHANNEL_done(ch);
}
void
@@ -524,36 +524,36 @@ INTER_do_dma_linked_list(Interconnect* inter, Port port)
u32 addr, header, remsz, command;
ch = &inter->dma->channels[port];
- addr = ch->base & 0x1ffffc;
+ addr = ch->base & 0x1ffffc;
- if (ch->direction == DIR_TO_RAM) {
- fprintf(stderr, "Invalid DMA direction for linked list mode\n");
- exit(EXIT_FAILURE);
- }
+ if (ch->direction == DIR_TO_RAM) {
+ fprintf(stderr, "Invalid DMA direction for linked list mode\n");
+ exit(EXIT_FAILURE);
+ }
- if (port != PORT_GPU) {
- fprintf(stderr, "Attempted linked list DMA on port %d\n", (u8)port);
- exit(EXIT_FAILURE);
- }
+ if (port != PORT_GPU) {
+ fprintf(stderr, "Attempted linked list DMA on port %d\n", (u8)port);
+ exit(EXIT_FAILURE);
+ }
- while (1) {
- header = RAM_load32(inter->ram, addr);
- remsz = header >> 24;
+ while (1) {
+ header = RAM_load32(inter->ram, addr);
+ remsz = header >> 24;
- while (remsz > 0) {
- addr = (addr + 4) & 0x1ffffc;
- command = RAM_load32(inter->ram, addr);
+ while (remsz > 0) {
+ addr = (addr + 4) & 0x1ffffc;
+ command = RAM_load32(inter->ram, addr);
#ifndef DEBUG
- printf("GPU command %08X\n", command);
+ printf("GPU command %08X\n", command);
#endif
- remsz--;
- }
+ remsz--;
+ }
- if ((header & 0x800000) != 0)
- break;
+ if ((header & 0x800000) != 0)
+ break;
- addr = header & 0x1ffffc;
+ addr = header & 0x1ffffc;
- }
- CHANNEL_done(ch);
+ }
+ CHANNEL_done(ch);
}
diff --git a/src/main.c b/src/main.c
@@ -8,11 +8,13 @@
#include "bios.h"
#include "mem.h"
#include "defs.h"
+#include "gpu.h"
int
main(int argc, char **argv)
{
CPU* cpu;
+ GPU* gpu;
Interconnect* inter;
inter = new_interconnect();
diff --git a/test.cc b/test.cc
@@ -37,6 +37,12 @@ int
main()
{
+ /* Thought i would try ternary but I am not sure if this actually works */
+ int val = 800;
+ int test = (val >> 7 & 3) ? 0 ? 100 ? 1 ? 200 ? 2 ? 300 : 0 : 0 : 0 : 0 : 0 : 0;
+
+ printf("\n%d\n", test);
+
FOO::fyk a;
FOO::ho x = FOO::ONE;