ultimecia

A ps1 emulator in c
Log | Files | Refs

commit 6c13b12f96500015a1c704d5cd1be23d8ca144d5
parent 56986bc1d6f9bb29f08ff7d27f0a3e93d994ff18
Author: noone <vazkats@gmail.com>
Date:   Tue, 27 May 2025 20:53:43 +0300

Skeleton of cdrom (completely incomplete)
I won't mess around with the software renderer anymore
I think it's ok for now

Diffstat:
Mmakefile | 2+-
Asrc/cdrom.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cdrom.h | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/interconnect.c | 16++++++++++++++--
Msrc/interconnect.h | 10++++++----
Msrc/main.c | 10+++++++++-
Msrc/sr.c | 38++++++++++++++++++++------------------
Msrc/sr.h | 4++--
Msrc/tags | 23++++++++++++++++++-----
Msrc/util.h | 3+++
Mtest.cc | 13++++++++++---
11 files changed, 207 insertions(+), 36 deletions(-)

diff --git a/makefile b/makefile @@ -1,5 +1,5 @@ mac: - cc -g src/*.c -o bin/ultimecia -I/opt/homebrew/include/ -L/opt/homebrew/lib/ -lSDL2 + cc -g src/*.c -o bin/ultimecia -I/opt/homebrew/include/ -I/opt/homebrew/include/lua5.4 -L/opt/homebrew/lib/ -lSDL2 -llua bsd: cc -O0 -g src/*.c -o bin/ultimecia -I/usr/local/include -L/usr/local/lib -lSDL2 win: diff --git a/src/cdrom.c b/src/cdrom.c @@ -0,0 +1,53 @@ +/* CDRom Drive */ +#include "cdrom.h" +#include <stdlib.h> +#include <string.h> + +cdrom* +cdrom_new() +{ + cdrom* cd = (cdrom*)malloc(sizeof(cdrom*)); + return cd; +} + +u8 +cdrom_fifo_is_empty(fifo fifo) +{ + return fifo.write_idx == fifo.read_idx; +} + +u8 +cdrom_fifo_is_full(fifo fifo) +{ + return fifo.write_idx == (fifo.read_idx ^ 0x10); +} + +void +cdrom_store8(cdrom* cd, u32 off, u8 val) +{ + off &= 0x3; +} + +void +cdrom_write(cdrom* cd, u32 offset, u8 val) +{ + u32 reg = ((cd->status & STATUS_INDEX_MASK) * 3) + (offset - 1); + switch (reg) { + case 0: + { + //DEBUG_LOG("cdrom command register <- 0x{:02X} ({})", value, s_command_info[value].name); + cdrom_command(cd, val); + return; + } + default: + return; + } + + return; +} + +void +cdrom_command(cdrom* cd, u8 com) +{ + +} diff --git a/src/cdrom.h b/src/cdrom.h @@ -0,0 +1,71 @@ +#pragma once + +#include "types.h" + +enum { + cdrom_raw_sector_size = 2352, + cdrom_data_sector_size = 2048, + cdrom_sector_sync_size = 12, + cdrom_sector_header_size = 4, + cdrom_mode1_header_size = 4, + cdrom_mode2_header_size = 12, + cdrom_mode2_data_sector_size = 2336, // header + edc + cdrom_frames_per_second = 75, // "sectors", or "timecode frames" (not "channel frames") + cdrom_seconds_per_minute = 60, + cdrom_frames_per_minute = cdrom_frames_per_second * cdrom_seconds_per_minute, + cdrom_subchannel_bytes_per_frame = 12, + cdrom_lead_out_sector_count = 6750, + cdrom_all_subcode_size = 96, + cdrom_audio_sample_rate = 44100, + cdrom_audio_channels = 2, +}; + +typedef struct fifo { + // Data buffer + u8 buffer[16]; + // Write pointer (4bits + carry) + u8 write_idx; + // Read pointer (4bits + carry) + u8 read_idx; +} fifo; + + +#define STATUS_INDEX_MASK 0x03 +#define STATUS_ADPBUSY_MASK 0x04 +#define STATUS_PRMEMPT_MASK 0x08 +#define STATUS_PRMWRDY_MASK 0x10 +#define STATUS_RSLRRDY_MASK 0x20 +#define STATUS_DRQSTS_MASK 0x40 +#define STATUS_BUSYSTS_MASK 0x80 + +typedef struct cdrom { + u8 status; /* Status Register */ + /// Command parameter FIFO + fifo host_params; + fifo host_response; + + u8 command; + u8 irq_flags; + u8 irq_mask; + + u8 sb[2340]; + u32 SB_in; +} cdrom; + +cdrom* cdrom_new(); + +void cdrom_store8(cdrom*, u32, u8); +void cdrom_store16(cdrom*, u32, u16); +void cdrom_store32(cdrom*, u32, u32); +void cdrom_write(cdrom*, u32, u8); +void cdrom_load(); + +void cdrom_load8(cdrom*, u8); +void cdrom_load16(cdrom*, u16); +void cdrom_load32(cdrom*, u32); + +u8 cdrom_fifo_is_empty(fifo); +u8 cdrom_fifo_is_full(fifo); +u8 cdrom_fifo_push(); + +void cdrom_command(cdrom*, u8); diff --git a/src/interconnect.c b/src/interconnect.c @@ -8,6 +8,7 @@ #include "types.h" #include "defs.h" #include "gpu.h" +#include "cdrom.h" Interconnect* new_interconnect(void) { @@ -16,6 +17,7 @@ new_interconnect(void) { inter->ram = RAM_new(); inter->dma = DMA_new(); inter->gpu = GPU_new(); + inter->cdrom = cdrom_new(); return inter; } @@ -168,7 +170,7 @@ INTER_load32(Interconnect* inter, u32 addr) exit(EXIT_FAILURE); } - void +void INTER_store8(Interconnect* inter, u32 addr, u8 val) { u32 offset; @@ -195,6 +197,16 @@ INTER_store8(Interconnect* inter, u32 addr, u8 val) return; } + contains = UTIL_contains(CDROM_START, CDROM_SIZE, abs_addr, &offset); + if (contains) + { + fprintf(stderr, "GODDAMN! We reached the CDROM register at %08X\n", abs_addr); + fprintf(stderr, "And the value is %08X\n", val); + cdrom_write(inter->cdrom, offset, val); + exit(EXIT_FAILURE); + //return; + } + fprintf(stderr, "Unhandled Store8 At Address %08X\n", abs_addr); exit(EXIT_FAILURE); } @@ -363,7 +375,7 @@ INTER_store32(Interconnect* inter, u32 addr, u32 val) exit(EXIT_FAILURE); } - u32 +u32 INTER_dma_reg(Interconnect* inter, u32 offset) { u32 major, minor, val; diff --git a/src/interconnect.h b/src/interconnect.h @@ -4,12 +4,14 @@ #include "mem.h" #include "gpu.h" #include "types.h" +#include "cdrom.h" struct Interconnect { - BIOS* bios; - RAM* ram; - DMA* dma; - GPU* gpu; + BIOS* bios; + RAM* ram; + DMA* dma; + GPU* gpu; + cdrom* cdrom; }; typedef struct Interconnect Interconnect; diff --git a/src/main.c b/src/main.c @@ -1,5 +1,8 @@ #include <stdlib.h> #include <SDL2/SDL.h> +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> #include "cpu.h" #include "interconnect.h" @@ -17,6 +20,8 @@ main(int argc, char **argv) REN *ren; CPU *cpu; Interconnect *inter; + //lua_State *L = luaL_newstate(); + //luaL_openlibs(L); SDL_Init(SDL_INIT_VIDEO); inter = new_interconnect(); @@ -40,7 +45,7 @@ main(int argc, char **argv) SDL_Quit(); exit(1); } else if (ev.key.keysym.sym == SDLK_a) { - SDL_Log("A pressed"); + fprintf(stderr, "The data %d\n;", inter->cdrom->host_params.buffer[0]); break; } } @@ -53,9 +58,12 @@ main(int argc, char **argv) free(inter->ram); free(inter->dma); free(inter->gpu); + free(inter->cdrom); free(inter); free(cpu); + //lua_close(L); + SDL_Quit(); return 0; diff --git a/src/sr.c b/src/sr.c @@ -106,20 +106,20 @@ C_new(u32 b) return c; }; -void REN_FB_set(REN* ren, i32 x, i32 y, C c) { +void REN_FB_set(REN* ren, i32 x, i32 y, u8 r, u8 g, u8 b) { u32 *fb; if (!ren->fb || x < 0 || y < 0 || x >= W || y >= H) return; - + // Clamp color values - c.r = c.r > 255 ? 255 : c.r; - c.g = c.g > 255 ? 255 : c.g; - c.b = c.b > 255 ? 255 : c.b; - + r = r > 255 ? 255 : r; + g = g > 255 ? 255 : g; + b = b > 255 ? 255 : b; + // Direct write instead of memcpy fb = ren->fb + (x + y * W); - *fb = (c.r) | (c.g << 8) | (c.b << 16); + *fb = r | (g << 8) | (b << 16); } //C* @@ -146,7 +146,7 @@ REN_new() } // Draw a scanline with color interpolation -void +void draw_scanline(REN* ren, int y, int x1, C c1, int x2, C c2) { if (x1 > x2) { @@ -163,13 +163,13 @@ draw_scanline(REN* ren, int y, int x1, C c1, int x2, C c2) float r = c1.r, g = c1.g, b = c1.b; for (int x = x1; x <= x2; x++) { - REN_FB_set(ren, x, y, (C){r,g,b}); + REN_FB_set(ren, x, y, (u8)r,(u8)g,(u8)b); r += dr; g += dg; b += db; } } // Rasterize triangle with color interpolation -void +void REN_triangle(REN* ren, ivec2 verts[3], C colors[3]) { // Check for degenerate triangles @@ -201,12 +201,14 @@ REN_triangle(REN* ren, ivec2 verts[3], C colors[3]) i32 db12 = ((colors[2].b - colors[1].b) << 16) / (verts[2].y - verts[1].y + 1); // Rasterize top part - i32 xL = verts[0].x << 16, rL = colors[0].r << 16, gL = colors[0].g << 16, bL = colors[0].b << 16; - i32 xR = verts[0].x << 16, rR = colors[0].r << 16, gR = colors[0].g << 16, bR = colors[0].b << 16; + i32 xL = verts[0].x << 16; + u32 rL = colors[0].r << 16, gL = colors[0].g << 16, bL = colors[0].b << 16; + i32 xR = verts[0].x << 16; + u32 rR = colors[0].r << 16, gR = colors[0].g << 16, bR = colors[0].b << 16; for (i32 y = verts[0].y; y < verts[1].y; y++) { - draw_scanline(ren, y, xL >> 16, (C){rL >> 16, gL >> 16, bL >> 16}, - xR >> 16, (C){rR >> 16, gR >> 16, bR >> 16}); + draw_scanline(ren, y, xL >> 16, (C){(u8)(rL >> 16), (u8)(gL >> 16), (u8)(bL >> 16)}, + xR >> 16, (C){(u8)(rR >> 16), (u8)(gR >> 16), (u8)(bR >> 16)}); xL += dx01; rL += dr01; gL += dg01; bL += db01; xR += dx02; rR += dr02; gR += dg02; bR += db02; } @@ -214,8 +216,8 @@ REN_triangle(REN* ren, ivec2 verts[3], C colors[3]) // Rasterize bottom part xL = verts[1].x << 16, rL = colors[1].r << 16, gL = colors[1].g << 16, bL = colors[1].b << 16; for (i32 y = verts[1].y; y < verts[2].y; y++) { - draw_scanline(ren, y, xL >> 16, (C){rL >> 16, gL >> 16, bL >> 16}, - xR >> 16, (C){rR >> 16, gR >> 16, bR >> 16}); + draw_scanline(ren, y, xL >> 16, (C){(u8)(rL >> 16), (u8)(gL >> 16), (u8)(bL >> 16)}, + xR >> 16, (C){(u8)(rR >> 16), (u8)(gR >> 16), (u8)(bR >> 16)}); xL += dx12; rL += dr12; gL += dg12; bL += db12; xR += dx02; rR += dr02; gR += dg02; bR += db02; } @@ -255,7 +257,7 @@ REN_push_quad(REN* ren, ivec2 verts[4], C colors[4]) } } -void +void REN_flush(REN* ren) { u32 i; for (i = 0; i < ren->nvertices; i += 3) @@ -277,7 +279,7 @@ REN_display(REN* ren) if (ren->nvertices > 0) { REN_flush(ren); } - + REN_draw(ren); SDL_RenderPresent(ren->renderer); } diff --git a/src/sr.h b/src/sr.h @@ -6,8 +6,8 @@ #define W 640 #define H 480 -#define WIN_W 1280 -#define WIN_H 960 +#define WIN_W 640 +#define WIN_H 480 #define VERTEX_BUFFER_LEN 64*1024 #define VEC2I_SWAP(x, y) { ivec2 temp = x; x = y; y = temp; } diff --git a/src/tags b/src/tags @@ -2,8 +2,15 @@ BIOS bios.h /^struct BIOS {$/ BIOS_load32 bios.c /^BIOS_load32(BIOS* b, u32 offset)$/ BIOS_load8 bios.c /^u8 BIOS_load8(BIOS* b, u32 offset) { return b->dat/ BIOS_new bios.c /^BIOS_new(const char* path)$/ -Bool tags /^Bool types.h \/^typedef uint8_t Bool;$\/$/ +Bool tags /^Bool tags \/^Bool types.h \\\/^typedef uint8_t Bo/ C sr.h /^typedef struct {u8 b;u8 g;u8 r;} C;$/ +CDROM cdrom.h /^}CDROM;$/ +CDROM_Fifo cdrom.h /^} CDROM_Fifo;$/ +CDROM_Fifo_is_empty cdrom.c /^CDROM_Fifo_is_empty(CDROM_Fifo fifo)$/ +CDROM_Fifo_is_full cdrom.c /^CDROM_Fifo_is_full(CDROM_Fifo fifo)$/ +CDROM_new cdrom.c /^CDROM_new()$/ +CDROM_store8 cdrom.c /^CDROM_store8(CDROM* cd, u32 off, u8 val)$/ +CDROM_write cdrom.c /^void CDROM_write(u32 offset, u8 val)$/ 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)$/ @@ -43,16 +50,17 @@ FIELD gpu.h /^} FIELD;$/ GP0_MODE gpu.h /^} GP0_MODE;$/ GPU gpu.h /^} GPU;$/ GPU_CMD_BUFFER gpu.h /^} GPU_CMD_BUFFER;$/ -GPU_CMD_BUFFER_clear gpu.c /^GPU_CMD_BUFFER_clear(GPU_CMD_BUFFER* cmd_buffer) $/ +GPU_CMD_BUFFER_clear gpu.c /^GPU_CMD_BUFFER_clear(GPU_CMD_BUFFER* cmd_buffer)$/ 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_LOG defs.h /^#define GPU_LOG(fmt, ...) \\$/ GPU_gp0 gpu.c /^GPU_gp0(GPU* gpu, u32 val)$/ GPU_gp0_clear_cache gpu.c /^void GPU_gp0_clear_cache(GPU* gpu) { \/* Not imple/ 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_image_load gpu.c /^GPU_gp0_image_load(GPU* gpu) $/ +GPU_gp0_image_load gpu.c /^GPU_gp0_image_load(GPU* gpu)$/ GPU_gp0_image_store gpu.c /^GPU_gp0_image_store(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) {}$/ @@ -106,13 +114,14 @@ RAM_store16 mem.c /^RAM_store16(RAM* r, u32 offset, u16 val)$/ RAM_store32 mem.c /^RAM_store32(RAM* r, u32 offset, u32 val)$/ RAM_store8 mem.c /^RAM_store8(RAM* r, u32 offset, u8 val)$/ REN sr.h /^} REN;$/ -REN_FB_set sr.c /^void REN_FB_set(REN* ren, i32 x, i32 y, C c) { (!r/ +REN_FB_set sr.c /^void REN_FB_set(REN* ren, i32 x, i32 y, u8 r, u8 g/ REN_display sr.c /^REN_display(REN* ren)$/ REN_draw sr.c /^REN_draw(REN* ren)$/ +REN_flush sr.c /^REN_flush(REN* ren) {$/ REN_new sr.c /^REN_new()$/ REN_push_quad sr.c /^REN_push_quad(REN* ren, ivec2 verts[4], C colors[4/ REN_push_triangle sr.c /^REN_push_triangle(REN* ren, ivec2 verts[3], C colo/ -REN_triangle sr.c /^void REN_triangle(REN* ren, ivec2 verts[3], C colo/ +REN_triangle sr.c /^REN_triangle(REN* ren, ivec2 verts[3], C colors[3]/ SHADERS_gradient_shader shaders.c /^SHADERS_gradient_shader(float alpha, float beta, f/ Step mem.h /^} Step;$/ Sync mem.h /^} Sync;$/ @@ -123,6 +132,7 @@ 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)$/ +draw_scanline sr.c /^draw_scanline(REN* ren, int y, int x1, C c1, int x/ exception cpu.c /^exception(CPU* cpu, EXCEPTION cause)$/ i16 types.h /^typedef int16_t i16;$/ i32 types.h /^typedef int32_t i32;$/ @@ -209,6 +219,9 @@ op_xori cpu.c /^op_xori(CPU* cpu, instruction* i)$/ point sr.h /^typedef struct { double x, y, z; } point;$/ reg cpu.c /^u32 reg(CPU* cpu, u32 reg) { return cpu->out_regs[/ set_reg cpu.c /^void set_reg(CPU* cpu, u32 reg, u32 val) { cpu->ou/ +swap_color util.c /^swap_color(C *a, C *b) { C temp = *a; *a = *b; *b / +swap_int util.c /^swap_int(int *a, int *b) { int temp = *a; *a = *b;/ +swap_vec2 util.c /^swap_vec2(ivec2 *a, ivec2 *b) { ivec2 temp = *a; */ u16 types.h /^typedef uint16_t u16;$/ u32 types.h /^typedef uint32_t u32;$/ u64 types.h /^typedef uint64_t u64;$/ diff --git a/src/util.h b/src/util.h @@ -39,6 +39,9 @@ #define GPU_START 0x1F801810 #define GPU_SIZE 8 +#define CDROM_START 0x1F801800 +#define CDROM_SIZE 12 + u32 UTIL_contains(u32, u32, u32, u32*); u8 checked_addi32(i32, i32, i32*); u8 checked_subi32(i32, i32, i32*); diff --git a/test.cc b/test.cc @@ -2,7 +2,12 @@ #include <stdint.h> #include <stdlib.h> -namespace FOO + +enum HEY { + DAFAQ = 0x1 +} + +namespace FOO { typedef struct fyk { @@ -39,7 +44,7 @@ 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; + int test = (val >> 7 & 3) ? 0 ? 100 ? 1 ? 200 ? 2 ? 300 : 0 : 0 : 0 : 0 : 0 : 0; printf("\n%d\n", test); @@ -47,5 +52,7 @@ main() FOO::ho x = FOO::ONE; return 0; -} + + HEY a = HEY.DAFUQ; +}