ultimecia

A ps1 emulator in c
Log | Files | Refs

commit 993827f756cfff97e9351a379498e4747986724b
parent 13e7212f82ef681a5044fbb96b805811c713d7e0
Author: edea <none@fithos.xyz>
Date:   Mon, 22 Jul 2024 00:48:26 +0300

progress..

Diffstat:
AMISFORTUNES | 10++++++++++
Mbuild.sh | 2+-
Msrc/gpu.c | 131++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/gpu.h | 18++++++++++--------
Msrc/interconnect.c | 2+-
Msrc/tags | 34+++++++++++++++++++++++++++++++++-
6 files changed, 134 insertions(+), 63 deletions(-)

diff --git a/MISFORTUNES b/MISFORTUNES @@ -0,0 +1,10 @@ +-- GPU -- +22072024 + +STUCK +so my gp0_command somewhere in code gets invalidated and it doesn't contain +a struct anymore so it has no len nor buffer fields and i get segmentation +fault... the question is why + +UNSTUCK +So the solution was (for now) to change CMD_BUFFER to non pointer. Sometime i need to see this kind of problem because this is not the first time I encounter pointer invalidation without any free. diff --git a/build.sh b/build.sh @@ -1 +1 @@ -cc -std=c89 -O3 -Wall -Wpedantic -static -Wall -pedantic -g src/*.c -o bin/ultimecia +cc -std=c89 -Wall -Wpedantic -static -Wall -pedantic -g src/*.c -o bin/ultimecia diff --git a/src/gpu.c b/src/gpu.c @@ -82,7 +82,7 @@ void GPU_gp1(GPU* gpu, u32 val) { - u32 opcode; + u32 opcode, len; opcode = (val >> 24) & 0xff; @@ -102,7 +102,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; @@ -148,46 +148,60 @@ GPU_gp1_dma_direction(GPU* gpu, u32 val) 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); + 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, len; - void (*method)(GPU*); - - opcode = (val >> 24) & 0xff; - - switch (opcode) { - 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); + if (gpu->gp0_command_remaining == 0) { + u32 opcode, len; + void (*method)(GPU*); + + opcode = (val >> 24) & 0xff; + + switch (opcode) { + case 0x00: len = 1; method = GPU_gp0_nop; 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; + default: fprintf(stderr, "OP: %08X: Unhandled GP0 command %08X\n", opcode, val); exit(1); + } + + gpu->gp0_command_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); } -void GPU_gp0_nop(GPU* gpu, u32 val) {} +void GPU_gp0_nop(GPU* gpu) {} void -GPU_gp0_draw_mode(GPU* gpu, u32 val) +GPU_gp0_draw_mode(GPU* gpu) { + u32 val; + val = gpu->gp0_command.buffer[0]; + gpu->page_base_x = (u8)(val & 0xf); gpu->page_base_y = (u8)((val >> 4) & 1); gpu->semi_transparency = (u8)((val >> 5) & 3); @@ -203,32 +217,39 @@ 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); + 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_gp0_drawing_area_top_left(GPU* gpu) { - gpu->drawing_area_top = (u16)((val >> 10) & 0x3ff); - gpu->drawing_area_left = (u16)(val & 0x3ff); + u32 val; + val = gpu->gp0_command.buffer[0]; + 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_gp0_drawing_area_bottom_right(GPU* gpu) { - gpu->drawing_area_bottom = (u16)((val >> 10) & 0x3ff); - gpu->drawing_area_right = (u16)(val & 0x3ff); + u32 val; + val = gpu->gp0_command.buffer[0]; + + gpu->drawing_area_bottom = (u16)((val >> 10) & 0x3ff); + gpu->drawing_area_right = (u16)(val & 0x3ff); } void -GPU_gp0_drawing_offset(GPU* gpu, u32 val) +GPU_gp0_drawing_offset(GPU* gpu) { u16 x, y; + u32 val; + val = gpu->gp0_command.buffer[0]; x = (u16)(val & 0x7ff); y = (u16)((val >> 11) & 0x7ff); @@ -239,19 +260,25 @@ GPU_gp0_drawing_offset(GPU* gpu, u32 val) } void -GPU_gp0_texture_window(GPU* gpu, u32 val) +GPU_gp0_texture_window(GPU* gpu) { - 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); + u32 val; + val = gpu->gp0_command.buffer[0]; + + 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_gp0_mask_bit_setting(GPU* gpu) { - gpu->force_set_mask_bit = val & 1; - gpu->preserve_masked_pixels = val & 2; + u32 val; + val = gpu->gp0_command.buffer[0]; + + gpu->force_set_mask_bit = val & 1; + gpu->preserve_masked_pixels = val & 2; } GPU_CMD_BUFFER* @@ -265,7 +292,7 @@ GPU_CMD_BUFFER_new(void) return buffer; } -void GPU_CMD_BUFFER_clear(GPU_CMD_BUFFER* cmd_buffer) { cmd_buffer->len = 0; } +void GPU_CMD_BUFFER_clear(GPU_CMD_BUFFER* cmd_buffer) { if (cmd_buffer == NULL) return; cmd_buffer->len = 0; } void GPU_CMD_BUFFER_push_word(GPU_CMD_BUFFER* cmd_buffer, u32 word) diff --git a/src/gpu.h b/src/gpu.h @@ -76,7 +76,7 @@ typedef struct _GPU { u16 display_line_start; u16 display_line_end; - GPU_CMD_BUFFER* gp0_command; + GPU_CMD_BUFFER gp0_command; u32 gp0_command_remaining; void (*gp0_command_method) (struct _GPU*); @@ -92,14 +92,16 @@ 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 */ + +/* GP0 */ 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 */ -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 */ +void GPU_gp0_nop(GPU*); +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 */ GPU* GPU_new(void); u32 GPU_read(GPU*); diff --git a/src/interconnect.c b/src/interconnect.c @@ -15,7 +15,7 @@ new_interconnect(void) { inter->bios = BIOS_new("roms/scph1001.bin"); inter->ram = RAM_new(); inter->dma = DMA_new(); - inter->gpu = GPU_new(); + inter->gpu = GPU_new(); return inter; } diff --git a/src/tags b/src/tags @@ -7,10 +7,12 @@ CHANNEL_active mem.c /^CHANNEL_active(Channel* ch)$/ CHANNEL_base mem.c /^CHANNEL_base(Channel* ch)$/ CHANNEL_block_control mem.c /^CHANNEL_block_control(Channel* ch)$/ CHANNEL_control mem.c /^CHANNEL_control(Channel* ch)$/ +CHANNEL_done mem.c /^CHANNEL_done(Channel* ch)$/ CHANNEL_new mem.c /^CHANNEL_new(void)$/ CHANNEL_set_base mem.c /^CHANNEL_set_base(Channel* ch, u32 val)$/ CHANNEL_set_block_control mem.c /^CHANNEL_set_block_control(Channel* ch, u32 val)$/ CHANNEL_set_control mem.c /^CHANNEL_set_control(Channel* ch, u32 val)$/ +CHANNEL_transfer_size mem.c /^CHANNEL_transfer_size(Channel* ch, u32 *res)$/ CPU cpu.h /^} CPU;$/ CPU_decode_and_execute cpu.c /^CPU_decode_and_execute(CPU* cpu, instruction* i)$/ CPU_load16 cpu.c /^u16 CPU_load16(CPU* cpu, u32 addr) { return INTER_/ @@ -21,7 +23,9 @@ CPU_store16 cpu.c /^void CPU_store16(CPU* cpu, u32 addr, u16 val) { IN/ CPU_store32 cpu.c /^void CPU_store32(CPU* cpu, u32 addr, u32 val) { IN/ CPU_store8 cpu.c /^void CPU_store8(CPU* cpu, u32 addr, u8 val) { IN/ Channel mem.h /^} Channel;$/ +DISPLAY_DEPTH gpu.h /^} DISPLAY_DEPTH;$/ DMA mem.h /^} DMA;$/ +DMA_DIRECTION gpu.h /^} DMA_DIRECTION;$/ DMA_control mem.c /^DMA_control(DMA* dma)$/ DMA_interrupt mem.c /^DMA_interrupt(DMA* dma)$/ DMA_irq mem.c /^DMA_irq(DMA* dma)$/ @@ -30,9 +34,36 @@ DMA_set_control mem.c /^DMA_set_control(DMA* dma, u32 val)$/ DMA_set_interrupt mem.c /^DMA_set_interrupt(DMA* dma, u32 val)$/ Direction mem.h /^} Direction;$/ EXCEPTION cpu.h /^} EXCEPTION;$/ +FIELD gpu.h /^} FIELD;$/ +GPU gpu.h /^} GPU;$/ +GPU_CMD_BUFFER gpu.h /^} GPU_CMD_BUFFER;$/ +GPU_CMD_BUFFER_clear gpu.c /^void GPU_CMD_BUFFER_clear(GPU_CMD_BUFFER* cmd_buff/ +GPU_CMD_BUFFER_new gpu.c /^GPU_CMD_BUFFER_new(void)$/ +GPU_CMD_BUFFER_push_word gpu.c /^GPU_CMD_BUFFER_push_word(GPU_CMD_BUFFER* cmd_buffe/ +GPU_gp0 gpu.c /^GPU_gp0(GPU* gpu, u32 val)$/ +GPU_gp0_draw_mode gpu.c /^GPU_gp0_draw_mode(GPU* gpu)$/ +GPU_gp0_drawing_area_bottom_right gpu.c /^GPU_gp0_drawing_area_bottom_right(GPU* gpu)$/ +GPU_gp0_drawing_area_top_left gpu.c /^GPU_gp0_drawing_area_top_left(GPU* gpu)$/ +GPU_gp0_drawing_offset gpu.c /^GPU_gp0_drawing_offset(GPU* gpu)$/ +GPU_gp0_mask_bit_setting gpu.c /^GPU_gp0_mask_bit_setting(GPU* gpu)$/ +GPU_gp0_nop gpu.c /^void GPU_gp0_nop(GPU* gpu) {}$/ +GPU_gp0_texture_window gpu.c /^GPU_gp0_texture_window(GPU* gpu)$/ +GPU_gp1 gpu.c /^GPU_gp1(GPU* gpu, u32 val)$/ +GPU_gp1_display_horizontal_range gpu.c /^GPU_gp1_display_horizontal_range(GPU* gpu, u32 val/ +GPU_gp1_display_mode gpu.c /^GPU_gp1_display_mode(GPU* gpu, u32 val)$/ +GPU_gp1_display_vertical_range gpu.c /^GPU_gp1_display_vertical_range(GPU* gpu, u32 val)$/ +GPU_gp1_display_vram_start gpu.c /^GPU_gp1_display_vram_start(GPU* gpu, u32 val)$/ +GPU_gp1_dma_direction gpu.c /^GPU_gp1_dma_direction(GPU* gpu, u32 val)$/ +GPU_gp1_reset gpu.c /^GPU_gp1_reset(GPU* gpu, u32 val)$/ +GPU_new gpu.c /^GPU_new(void)$/ +GPU_read gpu.c /^GPU_read(GPU* gpu)$/ +GPU_status gpu.c /^GPU_status(GPU* gpu)$/ +HOR_RES_from_fields gpu.c /^u8 HOR_RES_from_fields(u8 hr1, u8 hr2) { return (/ +HOR_RES_into_status gpu.c /^u32 HOR_RES_into_status(u8 hr) {return ((u32)hr) </ INTER_dma_reg interconnect.c /^INTER_dma_reg(Interconnect* inter, u32 offset)$/ INTER_do_dma interconnect.c /^INTER_do_dma(Interconnect* inter, Port port)$/ INTER_do_dma_block interconnect.c /^INTER_do_dma_block(Interconnect* inter, Port port)/ +INTER_do_dma_linked_list interconnect.c /^INTER_do_dma_linked_list(Interconnect* inter, Port/ INTER_load16 interconnect.c /^INTER_load16(Interconnect* inter, u32 addr)$/ INTER_load32 interconnect.c /^INTER_load32(Interconnect* inter, u32 addr)$/ INTER_load8 interconnect.c /^INTER_load8(Interconnect* inter, u32 addr)$/ @@ -44,7 +75,6 @@ Interconnect interconnect.h /^struct Interconnect {$/ LOG_ERR defs.h /^#define LOG_ERR(x) fprintf(stderr, (x))$/ Load cpu.h /^} Load;$/ Mmain main.c /^main(int argc, char **argv)$/ -PANIC defs.h /^#define PANIC(...) do { fprintf(stderr, __VA_ARGS_/ Port mem.h /^} Port;$/ RAM mem.h /^} RAM;$/ RAM_load16 mem.c /^RAM_load16(RAM* r, u32 offset)$/ @@ -56,7 +86,9 @@ RAM_store32 mem.c /^RAM_store32(RAM* r, u32 offset, u32 val)$/ RAM_store8 mem.c /^RAM_store8(RAM* r, u32 offset, u8 val)$/ Step mem.h /^} Step;$/ Sync mem.h /^} Sync;$/ +TEXTURE_DEPTH gpu.h /^} TEXTURE_DEPTH;$/ UTIL_contains util.c /^UTIL_contains(u32 start, u32 length, u32 addr, u32/ +VMODE gpu.h /^} VMODE;$/ branch cpu.c /^branch(CPU* cpu, u32 offset)$/ checked_addi32 util.c /^checked_addi32(i32 a, i32 b, i32* res)$/ checked_subi32 util.c /^checked_subi32(i32 a, i32 b, i32* res)$/