commit e3ec2d2175f83466b3ab7734c34cd015d8443605
parent 993827f756cfff97e9351a379498e4747986724b
Author: root <root@fif>
Date: Fri, 26 Jul 2024 19:51:53 +0000
According to the guide we finished the implementation of the gpu..
Until the point that we are able to display the boot logo!!
Diffstat:
5 files changed, 139 insertions(+), 20 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,3 +1,4 @@
+*.vscode
bin/
a.out
test.c
diff --git a/build.sh b/build.sh
@@ -1 +1 @@
-cc -std=c89 -Wall -Wpedantic -static -Wall -pedantic -g src/*.c -o bin/ultimecia
+cc -Wall -Wpedantic -static -Wall -pedantic -g src/*.c -o bin/ultimecia
diff --git a/src/gpu.c b/src/gpu.c
@@ -47,7 +47,7 @@ GPU_status(GPU* gpu)
/* 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->vres) << 19;
r |= ((u32)gpu->vmode) << 20;
r |= ((u32)gpu->display_depth) << 21;
r |= ((u32)gpu->interlaced) << 22;
@@ -82,13 +82,16 @@ void
GPU_gp1(GPU* gpu, u32 val)
{
- u32 opcode, len;
+ u32 opcode;
opcode = (val >> 24) & 0xff;
switch (opcode)
{
case 0x00: GPU_gp1_reset(gpu, val); break;
+ case 0x01: GPU_gp1_reset_command_buffer(gpu, val); break;
+ case 0x02: GPU_gp1_acknowledge_irq(gpu, val); break;
+ case 0x03: GPU_gp1_display_enable(gpu, val); break;
case 0x04: GPU_gp1_dma_direction(gpu, val); break;
case 0x05: GPU_gp1_display_vram_start(gpu, val); break;
case 0x06: GPU_gp1_display_horizontal_range(gpu, val); break;
@@ -102,7 +105,7 @@ GPU_gp1(GPU* gpu, u32 val)
void
GPU_gp1_reset(GPU* gpu, u32 val)
{
- memset(gpu, 0, sizeof(GPU));
+ 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;
@@ -113,6 +116,28 @@ GPU_gp1_reset(GPU* gpu, u32 val)
}
void
+GPU_gp1_display_enable(GPU* gpu, u32 val)
+{
+ gpu->display_disabled = (val & 1) != 0;
+}
+
+void
+GPU_gp1_acknowledge_irq(GPU* gpu, u32 val)
+{
+ gpu->interrupt = 0;
+}
+
+void
+GPU_gp1_reset_command_buffer(GPU* gpu, u32 val)
+{
+ GPU_CMD_BUFFER_clear(&gpu->gp0_command);
+ gpu->gp0_words_remaining = 0;
+ gpu->gp0_mode = GP0_MODE_COMMAND;
+
+ // XXX Should also clear the command FIFO when we implement it
+}
+
+void
GPU_gp1_display_horizontal_range(GPU* gpu, u32 val)
{
gpu->display_horiz_start = (u16)(val & 0xfff);
@@ -154,10 +179,10 @@ GPU_gp1_display_mode(GPU* gpu, u32 val)
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);
+ gpu->vres = (val & 0x4) != 0;
+ gpu->vmode = (val & 0x8) != 0 ? VMODE_NTSC : VMODE_PAL;
+ gpu->display_depth = (val & 0x10) != 0 ? DISP_DEPTH_D24BITS : DISP_DEPTH_D15BITS;
+ gpu->interlaced = (val & 0x20) != 0;
if (val & 0x80)
fprintf(stderr, "Unsupported display mode %08X\n", val), exit(EXIT_FAILURE);
@@ -166,7 +191,7 @@ GPU_gp1_display_mode(GPU* gpu, u32 val)
void
GPU_gp0(GPU* gpu, u32 val)
{
- if (gpu->gp0_command_remaining == 0) {
+ if (gpu->gp0_words_remaining == 0) {
u32 opcode, len;
void (*method)(GPU*);
@@ -174,28 +199,60 @@ GPU_gp0(GPU* gpu, u32 val)
switch (opcode) {
case 0x00: len = 1; method = GPU_gp0_nop; break;
+ case 0x01: len = 1; method = GPU_gp0_clear_cache; break;
+ case 0xa0: len = 3; method = GPU_gp0_image_load; break;
case 0xe1: len = 1; method = GPU_gp0_draw_mode; break;
case 0xe2: len = 1; method = GPU_gp0_texture_window; break;
case 0xe3: len = 1; method = GPU_gp0_drawing_area_top_left; break;
case 0xe4: len = 1; method = GPU_gp0_drawing_area_bottom_right; break;
case 0xe5: len = 1; method = GPU_gp0_drawing_offset; break;
case 0xe6: len = 1; method = GPU_gp0_mask_bit_setting; break;
+ case 0x28: len = 5; method = GPU_gp0_quad_mono_opaque; break;
+ case 0x2c: len = 9; method = GPU_gp0_quad_texture_blend_opaque; break;
+ case 0x30: len = 6; method = GPU_gp0_triangle_shaded_opaque; break;
+ case 0x38: len = 8; method = GPU_gp0_quad_shaded_opaque; break;
+ case 0xc0: len = 3; method = GPU_gp0_image_store; break;
default: fprintf(stderr, "OP: %08X: Unhandled GP0 command %08X\n", opcode, val); exit(1);
}
- gpu->gp0_command_remaining = len;
+ gpu->gp0_words_remaining = len;
gpu->gp0_command_method = method;
GPU_CMD_BUFFER_clear(&gpu->gp0_command);
}
- GPU_CMD_BUFFER_push_word(&gpu->gp0_command, val);
- gpu->gp0_command_remaining -= 1;
- if (gpu->gp0_command_remaining == 0)
- gpu->gp0_command_method(gpu);
+ gpu->gp0_words_remaining -= 1;
+
+ switch (gpu->gp0_mode) {
+ case GP0_MODE_COMMAND:
+ GPU_CMD_BUFFER_push_word(&gpu->gp0_command, val);
+ if (gpu->gp0_words_remaining == 0)
+ gpu->gp0_command_method(gpu);
+ break;
+ case GP0_MODE_IMAGE_LOAD:
+ if (gpu->gp0_words_remaining == 0)
+ gpu->gp0_mode = GP0_MODE_COMMAND;
+ break;
+ }
}
void GPU_gp0_nop(GPU* gpu) {}
+void GPU_gp0_clear_cache(GPU* gpu) { /* Not implemented */}
+
+void
+GPU_gp0_image_load(GPU* gpu)
+{
+ u32 res, width, height, imgsize;
+
+ res = gpu->gp0_command.buffer[2];
+ width = res & 0xffff;
+ height = res >> 16;
+ imgsize = width * height;
+ imgsize = (imgsize + 1) & ~1;
+ gpu->gp0_words_remaining = imgsize / 2;
+ gpu->gp0_mode = GP0_MODE_IMAGE_LOAD;
+}
+
void
GPU_gp0_draw_mode(GPU* gpu)
{
@@ -277,8 +334,44 @@ GPU_gp0_mask_bit_setting(GPU* gpu)
u32 val;
val = gpu->gp0_command.buffer[0];
- gpu->force_set_mask_bit = val & 1;
- gpu->preserve_masked_pixels = val & 2;
+ gpu->force_set_mask_bit = (val & 1) != 0;
+ gpu->preserve_masked_pixels = (val & 2) != 0;
+}
+
+void
+GPU_gp0_quad_mono_opaque(GPU* gpu)
+{
+ fprintf(stdout, "Draw quad pls\n");
+}
+
+void
+GPU_gp0_triangle_shaded_opaque(GPU* gpu)
+{
+ fprintf(stdout, "Draw triangle shaded\n");
+}
+
+void
+GPU_gp0_quad_texture_blend_opaque(GPU* gpu)
+{
+ fprintf(stdout, "Draw quad texture blending\n");
+}
+
+void
+GPU_gp0_quad_shaded_opaque(GPU* gpu)
+{
+ fprintf(stdout, "Draw quad shaded\n");
+}
+
+void
+GPU_gp0_image_store(GPU* gpu)
+{
+ u32 res, width, height;
+
+ res = gpu->gp0_command.buffer[2];
+ width = res & 0xffff;
+ height = res >> 16;
+
+ fprintf(stdout, "Unhandled image store: %dx%d\n", width, height);
}
GPU_CMD_BUFFER*
@@ -292,7 +385,12 @@ GPU_CMD_BUFFER_new(void)
return buffer;
}
-void GPU_CMD_BUFFER_clear(GPU_CMD_BUFFER* cmd_buffer) { if (cmd_buffer == NULL) return; cmd_buffer->len = 0; }
+void
+GPU_CMD_BUFFER_clear(GPU_CMD_BUFFER* cmd_buffer)
+{
+ cmd_buffer->len = 0;
+ /*memset(cmd_buffer->buffer, 413, 12 * sizeof(u32));*/
+}
void
GPU_CMD_BUFFER_push_word(GPU_CMD_BUFFER* cmd_buffer, u32 word)
@@ -302,4 +400,4 @@ GPU_CMD_BUFFER_push_word(GPU_CMD_BUFFER* cmd_buffer, u32 word)
cmd_buffer->buffer[cmd_buffer->len] = word;
cmd_buffer->len++;
-}
+}
+\ No newline at end of file
diff --git a/src/gpu.h b/src/gpu.h
@@ -2,6 +2,11 @@
#include "types.h"
+typedef enum _GP0_MODE {
+ GP0_MODE_COMMAND,
+ GP0_MODE_IMAGE_LOAD
+} GP0_MODE;
+
typedef enum _TEXTURE_DEPTH {
TD_T4BIT,
TD_T8BIT,
@@ -76,8 +81,10 @@ typedef struct _GPU {
u16 display_line_start;
u16 display_line_end;
+ GP0_MODE gp0_mode;
+
GPU_CMD_BUFFER gp0_command;
- u32 gp0_command_remaining;
+ u32 gp0_words_remaining;
void (*gp0_command_method) (struct _GPU*);
} GPU;
@@ -87,6 +94,9 @@ 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_reset_command_buffer(GPU*, u32); /* GP1(0x01): Reset Command Buffer */
+void GPU_gp1_acknowledge_irq(GPU*, u32); /* GP1(0x02): Acknoweledge Interrupt */
+void GPU_gp1_display_enable(GPU*, u32); /* GP1(0x03): Display Enable */
void GPU_gp1_dma_direction(GPU*, u32); /* GP1(0x04): DMA Direction */
void GPU_gp1_display_mode(GPU*, u32); /* GP1(0x08): Display Mode */
void GPU_gp1_display_vram_start(GPU*, u32); /* GP1(0x05): Display VRAM start */
@@ -96,13 +106,21 @@ void GPU_gp1_display_vertical_range(GPU*, u32); /* GP1(0x07): Display Vertical R
/* GP0 */
void GPU_gp0(GPU*, u32);
void GPU_gp0_nop(GPU*);
+void GPU_gp0_clear_cache(GPU*); /* GP0(0x01): Clear Cache */
+void GPU_gp0_image_load(GPU*); /* GP0(0xa0): Image Load */
void GPU_gp0_draw_mode(GPU*);
void GPU_gp0_drawing_area_top_left(GPU*); /* GP0(0xe3): Set Drawing Area top left */
void GPU_gp0_drawing_area_bottom_right(GPU*); /* GP0(0xe4): Set Drawing Area bottom right */
void GPU_gp0_drawing_offset(GPU*); /* GP0(0xe5): Set Drawing Offset */
void GPU_gp0_texture_window(GPU*); /* GP0(0xe2): Set Texture Window */
void GPU_gp0_mask_bit_setting(GPU*); /* GP0(0xe6): Set Mask Bit Setting */
+void GPU_gp0_quad_mono_opaque(GPU*); /* GP0(0x28): Monochrome Opaque Quadrilateral */
+void GPU_gp0_triangle_shaded_opaque(GPU*); /* GP0(0x30): Shaded Opaque Triangle */
+void GPU_gp0_quad_shaded_opaque(GPU*); /* GP0(0x38): Shaded Opaque Quadrilateral */
+void GPU_gp0_quad_texture_blend_opaque(GPU*); /* GP0(0x2c): Textured Opaque Quadrilateral */
+void GPU_gp0_image_store(GPU*); /* GP0(0xc0): Image store */
GPU* GPU_new(void);
+u32 GPU_status(GPU*);
u32 GPU_read(GPU*);
/* GPU's Command Buffer: GPU_CMD_BUFFER */
diff --git a/src/interconnect.c b/src/interconnect.c
@@ -158,7 +158,7 @@ INTER_load32(Interconnect* inter, u32 addr)
switch(offset)
{
case 0: return GPU_read(inter->gpu); /* NOT COMPLETE */
- case 4: return 0x1c000000;
+ case 4: return GPU_status(inter->gpu);
default: return 0;
}
}
@@ -491,6 +491,7 @@ INTER_do_dma_block(Interconnect* inter, Port port)
src_word = RAM_load32(inter->ram, cur_addr);
switch(port) {
case PORT_GPU:
+ GPU_gp0(inter->gpu, src_word);
#ifndef DEBUG
printf("GPU data %08X\n", src_word);
#endif