ultimecia

A ps1 emulator in c
Log | Files | Refs

commit 13e7212f82ef681a5044fbb96b805811c713d7e0
parent fa1190dccb02895c82f3b65ea09e28b7a2f2d2d8
Author: edea <none@fithos.xyz>
Date:   Sun, 21 Jul 2024 16:43:10 +0300

Got a bit stuck. Because I need to figure out how to typecast my GP0-GP1 functions to a method variable and assign them to the GPU struct as methods. maybe i need to change the declarations of all functions to take only the gpu struct and not needing to take the value as a second parameter.

Diffstat:
Mbuild.sh | 2+-
Msrc/defs.h | 2+-
Msrc/gpu.c | 60+++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/gpu.h | 27+++++++++++++++++++++++----
Msrc/interconnect.c | 28+++++++++++++++-------------
Msrc/mem.c | 7-------
Msrc/mem.h | 4++--
Msrc/util.c | 15++++++++-------
8 files changed, 105 insertions(+), 40 deletions(-)

diff --git a/build.sh b/build.sh @@ -1 +1 @@ -cc -O3 -Wall -Wpedantic -static -Wall -pedantic -g src/*.c -o bin/ultimecia +cc -std=c89 -O3 -Wall -Wpedantic -static -Wall -pedantic -g src/*.c -o bin/ultimecia diff --git a/src/defs.h b/src/defs.h @@ -2,6 +2,6 @@ #define LOG_ERR(x) fprintf(stderr, (x)) -#define PANIC(...) do { fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); } while(0) +/* #define PANIC(...) do { fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); } while(0) */ #define DEBUG 1; diff --git a/src/gpu.c b/src/gpu.c @@ -90,8 +90,11 @@ GPU_gp1(GPU* gpu, u32 val) { case 0x00: GPU_gp1_reset(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; + case 0x07: GPU_gp1_display_vertical_range(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); + default: fprintf(stderr, "OP: %08X: Unhandled GP1 command %08X\n", opcode, val); exit(1); } } @@ -109,6 +112,27 @@ GPU_gp1_reset(GPU* gpu, u32 val) gpu->display_line_end = 0x100; } +void +GPU_gp1_display_horizontal_range(GPU* gpu, u32 val) +{ + gpu->display_horiz_start = (u16)(val & 0xfff); + gpu->display_horiz_end = (u16)((val >> 12) & 0xfff); +} + +void +GPU_gp1_display_vertical_range(GPU* gpu, u32 val) +{ + gpu->display_line_start = (u16)(val & 0x3ff); + gpu->display_line_end = (u16)((val >> 10) & 0x3ff); +} + +void +GPU_gp1_display_vram_start(GPU* gpu, u32 val) +{ + gpu->display_vram_x_start = (u16)(val & 0x3fe); + gpu->display_vram_y_start = (u16)((val >> 10) & 0x1ff); +} + void GPU_gp1_dma_direction(GPU* gpu, u32 val) { @@ -142,22 +166,25 @@ GPU_gp1_display_mode(GPU* gpu, u32 val) void GPU_gp0(GPU* gpu, u32 val) { - u32 opcode; - + u32 opcode, len; + void (*method)(GPU*); + opcode = (val >> 24) & 0xff; switch (opcode) { - case 0x00: break; + case 0x00: GPU_gp0_nop(gpu, val); 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); + default: fprintf(stderr, "OP: %08X: Unhandled GP0 command %08X\n", opcode, val); exit(1); } } +void GPU_gp0_nop(GPU* gpu, u32 val) {} + void GPU_gp0_draw_mode(GPU* gpu, u32 val) { @@ -226,3 +253,26 @@ GPU_gp0_mask_bit_setting(GPU* gpu, u32 val) gpu->force_set_mask_bit = val & 1; gpu->preserve_masked_pixels = val & 2; } + +GPU_CMD_BUFFER* +GPU_CMD_BUFFER_new(void) +{ + GPU_CMD_BUFFER* buffer; + + buffer = (GPU_CMD_BUFFER*)malloc(sizeof(GPU_CMD_BUFFER)); + memset(buffer, 0, sizeof(GPU_CMD_BUFFER)); + + return buffer; +} + +void GPU_CMD_BUFFER_clear(GPU_CMD_BUFFER* cmd_buffer) { cmd_buffer->len = 0; } + +void +GPU_CMD_BUFFER_push_word(GPU_CMD_BUFFER* cmd_buffer, u32 word) +{ + if (cmd_buffer->len > 12) + fprintf(stderr, "OUT OF BOUNDS GPU_CMD_BUFFER"), exit(EXIT_FAILURE); + + cmd_buffer->buffer[cmd_buffer->len] = word; + cmd_buffer->len++; +} diff --git a/src/gpu.h b/src/gpu.h @@ -5,12 +5,12 @@ typedef enum _TEXTURE_DEPTH { TD_T4BIT, TD_T8BIT, - TD_T15BIT, + TD_T15BIT } TEXTURE_DEPTH; typedef enum _FIELD { F_TOP, - F_BOTTOM, + F_BOTTOM } FIELD; typedef enum _DMA_DIRECTION { @@ -22,14 +22,19 @@ typedef enum _DMA_DIRECTION { typedef enum _VMODE { VMODE_NTSC, - VMODE_PAL, + VMODE_PAL } VMODE; typedef enum _DISPLAY_DEPTH { DISP_DEPTH_D15BITS, - DISP_DEPTH_D24BITS, + DISP_DEPTH_D24BITS } DISPLAY_DEPTH; +typedef struct _GPU_CMD_BUFFER { + u32 buffer[12]; + u32 len; +} GPU_CMD_BUFFER; + /* line 1045 in no$psx docs */ typedef struct _GPU { u8 page_base_x; @@ -71,15 +76,24 @@ typedef struct _GPU { u16 display_line_start; u16 display_line_end; + GPU_CMD_BUFFER* gp0_command; + u32 gp0_command_remaining; + void (*gp0_command_method) (struct _GPU*); + } GPU; +/* 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_gp1_display_vram_start(GPU*, u32); /* GP1(0x05): Display VRAM start */ +void GPU_gp1_display_horizontal_range(GPU*, u32); /* GP1(0x06): Display Horizontal Range */ +void GPU_gp1_display_vertical_range(GPU*, u32); /* GP1(0x07): Display Vertical Range */ void GPU_gp0(GPU*, u32); +void GPU_gp0_nop(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 */ @@ -88,3 +102,8 @@ 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*); + +/* GPU's Command Buffer: GPU_CMD_BUFFER */ +GPU_CMD_BUFFER* GPU_CMD_BUFFER_new(void); +void GPU_CMD_BUFFER_clear(GPU_CMD_BUFFER*); +void GPU_CMD_BUFFER_push_word(GPU_CMD_BUFFER*, u32); diff --git a/src/interconnect.c b/src/interconnect.c @@ -52,7 +52,8 @@ INTER_load8(Interconnect* inter, u32 addr) return 0; } - PANIC("Unhandled Load8 At Address %08X\n", addr); + fprintf(stderr, "Unhandled Load8 At Address %08X\n", addr); + exit(EXIT_FAILURE); } u16 @@ -95,7 +96,8 @@ INTER_load16(Interconnect* inter, u32 addr) return 0; } - PANIC("Unhandled Load16 At Address %08X\n", abs_addr); + fprintf(stderr, "Unhandled Load16 At Address %08X\n", abs_addr); + exit(EXIT_FAILURE); } u32 @@ -161,7 +163,8 @@ INTER_load32(Interconnect* inter, u32 addr) } } - PANIC("Unhandled Load32 At Address %08X\n", addr); + fprintf(stderr, "Unhandled Load32 At Address %08X\n", addr); + exit(EXIT_FAILURE); } void @@ -191,7 +194,8 @@ INTER_store8(Interconnect* inter, u32 addr, u8 val) return; } - PANIC("Unhandled store8 into abs_address: %08X\n", abs_addr); + fprintf(stderr, "Unhandled Store8 At Address %08X\n", abs_addr); + exit(EXIT_FAILURE); } void @@ -245,7 +249,8 @@ INTER_store16(Interconnect* inter, u32 addr, u16 val) return; } - PANIC("Unhandled store16 into abs_address: %08X\n", abs_addr); + fprintf(stderr, "Unhandled Store16 At Address %08X\n", abs_addr); + exit(EXIT_FAILURE); } void @@ -353,7 +358,8 @@ INTER_store32(Interconnect* inter, u32 addr, u32 val) return; } - PANIC("Unhandled store32 into abs_address: %08X\n", addr); + fprintf(stderr, "Unhandled Store32 At Address %08X\n", addr); + exit(EXIT_FAILURE); } u32 @@ -366,10 +372,6 @@ INTER_dma_reg(Interconnect* inter, u32 offset) 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) { @@ -424,7 +426,7 @@ INTER_set_dma_reg(Interconnect* inter, u32 offset, u32 val) 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); + 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); @@ -472,8 +474,8 @@ INTER_do_dma_block(Interconnect* inter, Port port) 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"); diff --git a/src/mem.c b/src/mem.c @@ -132,14 +132,7 @@ DMA_new(void) dma->channel_irq_flags = 0; dma->force_irq = 0; dma->irq_dummy = 0; - - //for (i = 0; i < 8; i++) - // dma->channels[i] = *CHANNEL_new(); - memset(dma->channels, 0, sizeof(Channel)*7); - - // printf("%d\n", (Port)dma->channels[1].step); - // exit(1); return dma; } diff --git a/src/mem.h b/src/mem.h @@ -10,7 +10,7 @@ typedef enum e_Direction { typedef enum e_Step { STEP_INCREMENT, - STEP_DECREMENT, + STEP_DECREMENT } Step; typedef enum e_Sync { @@ -27,7 +27,7 @@ typedef enum e_Port { PORT_SPU = 4, PORT_PIO = 5, PORT_OTC = 6, - PORT_INVALID = 7, + PORT_INVALID = 7 } Port; typedef struct RAM { diff --git a/src/util.c b/src/util.c @@ -3,13 +3,13 @@ #include <limits.h> const u32 REGION_MASK[8] = { - // KUSEG: 2048MB + /* KUSEG: 2048MB */ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - // KSEG0: 512MB // + /* KSEG0: 512MB */ 0x7fffffff, - // KSEG1: 512MB // + /* KSEG1: 512MB */ 0x1fffffff, - // KSEG2: 1024MB // + /* KSEG2: 1024MB */ 0xffffffff, 0xffffffff }; @@ -33,9 +33,10 @@ checked_addi32(i32 a, i32 b, i32* res) u8 checked_subi32(i32 a, i32 b, i32* res) { - if ((b > 0 && a > INT_MAX - b) || (b < 0 && a < INT_MIN - b) || (b == 0 && a == INT_MIN)) { - return 0; // Overflow occurred - } + if ((b > 0 && a > INT_MAX - b) || (b < 0 && a < INT_MIN - b) || (b == 0 && a == INT_MIN)) { + return 0; /* Overflow occurred */ + } + *res = a - b; return 1; }