ultimecia

A ps1 emulator in c
Log | Files | Refs

commit f94ef545e4e4ef7002788d3bdab7e4c3c3f90cbe
parent 6c13b12f96500015a1c704d5cd1be23d8ca144d5
Author: noone <vazkats@gmail.com>
Date:   Sat,  5 Jul 2025 16:11:41 +0300

Not much. Just a sync with the repo. Still at cdrom implementation

Diffstat:
Mmakefile | 34++++++++++++++++++++++++++++------
Cmakefile -> makefile.old | 0
Msrc/cdrom.c | 77++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Msrc/cdrom.h | 41+++++++++++++++++++++++------------------
Msrc/interconnect.c | 12++++++++----
Asrc/irq.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/irq.h | 34++++++++++++++++++++++++++++++++++
Msrc/sr.c | 55++++---------------------------------------------------
Msrc/sr.h | 2+-
Msrc/util.c | 15+++++++++++++++
Msrc/util.h | 2++
Mtest.cc | 63+++++++++++++++------------------------------------------------
12 files changed, 266 insertions(+), 139 deletions(-)

diff --git a/makefile b/makefile @@ -1,6 +1,28 @@ -mac: - 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: - cc -O3 -g src/*.c -o bin/ultimecia -I/mingw64/include/SDL2 -L/mingw64/lib -lmingw32 -lSDL2main -lSDL2 +#Makefile for Ultimecia PSX Emulator + +CC := cc +CFLAGS := -Wall -Wpedantic -std=c99 -g -O3 -I/opt/homebrew/include/ -I/opt/homebrew/include/lua5.4 +LDFLAGS := -L/opt/homebrew/lib/ +LIBS := -lSDL2 -llua + +SRC := $(wildcard src/*.c) +OBJ := $(SRC:.c=.o) +BIN := bin/ultimecia +JOBS := 10 + +all: $(BIN) + +$(BIN): $(OBJ) + @mkdir -p bin + $(CC) $(OBJ) -o $@ $(LDFLAGS) $(LIBS) + +# Pattern rule for compiling .c to .o +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +# Clean +clean: + rm -f src/*.o + rm -f $(BIN) + +.PHONY: all clean diff --git a/makefile b/makefile.old diff --git a/src/cdrom.c b/src/cdrom.c @@ -1,12 +1,15 @@ /* CDRom Drive */ #include "cdrom.h" +#include "util.h" #include <stdlib.h> #include <string.h> +#include <stdio.h> cdrom* -cdrom_new() +cdrom_new(void) { - cdrom* cd = (cdrom*)malloc(sizeof(cdrom*)); + cdrom* cd = (cdrom*)malloc(sizeof(cdrom)); + memset(cd, 0, sizeof(cdrom)); return cd; } @@ -31,23 +34,75 @@ cdrom_store8(cdrom* cd, u32 off, u8 val) void cdrom_write(cdrom* cd, u32 offset, u8 val) { - u32 reg = ((cd->status & STATUS_INDEX_MASK) * 3) + (offset - 1); - switch (reg) { + //printf("**THE OFFSET IS %08X**\n", offset); + //printf("**THE VAL IS %d**\n", val); + u8 idx; + + + idx = cd->status & STATUS_INDEX_MASK; + + switch (offset) { case 0: - { - //DEBUG_LOG("cdrom command register <- 0x{:02X} ({})", value, s_command_info[value].name); - cdrom_command(cd, val); - return; - } + cd->status = (cd->status & (~3)) | (val & 3); + break; + case 1: + fprintf(stderr, "offset 1\n"); + break; + case 2: + fprintf(stderr, "offset 2\n"); + break; + case 3: + switch (idx) { + case 1: + //self.irq_ack(shared, val & 0x1f); + + //if val & 0x40 != 0 { + // self.host_params.clear(); + //} + + //if val & 0xa0 != 0 { + // panic!("Unhandled CDROM 3.1: {:02x}", val); + //} + break; + default: + fprintf(stderr, "cdrom_write: Unimplemented write on offset %08X and index %08X\n", offset, idx); + exit(EXIT_FAILURE); + } + break; default: - return; + break; } - return; + return; +} + +u8 +cdrom_load(cdrom* cd, u32 offset) +{ + printf("Offset %08X\n", offset); + + switch (offset) { + case 0: + return cd->status; + default: + break; + } + return 0; } void cdrom_command(cdrom* cd, u8 com) { + // u32 ret; + + switch ((cdrom_cmd)com) + { + case CDROM_CMD_GETSTAT: + cd->status = (cd->status & STATUS_INDEX_MASK); + break; + default: + break; + } + return; } diff --git a/src/cdrom.h b/src/cdrom.h @@ -3,21 +3,21 @@ #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, + 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 { @@ -29,6 +29,11 @@ typedef struct fifo { u8 read_idx; } fifo; +typedef enum { + CDROM_CMD_SYNC = 0X00, + CDROM_CMD_GETSTAT = 0X01, + CDROM_CMD_INIT = 0XA, +} cdrom_cmd; #define STATUS_INDEX_MASK 0x03 #define STATUS_ADPBUSY_MASK 0x04 @@ -52,13 +57,13 @@ typedef struct cdrom { u32 SB_in; } cdrom; -cdrom* cdrom_new(); +cdrom* cdrom_new(void); 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(); +u8 cdrom_load(cdrom*, u32); void cdrom_load8(cdrom*, u8); void cdrom_load16(cdrom*, u16); @@ -66,6 +71,6 @@ void cdrom_load32(cdrom*, u32); u8 cdrom_fifo_is_empty(fifo); u8 cdrom_fifo_is_full(fifo); -u8 cdrom_fifo_push(); +u8 cdrom_fifo_push(void); void cdrom_command(cdrom*, u8); diff --git a/src/interconnect.c b/src/interconnect.c @@ -54,6 +54,13 @@ INTER_load8(Interconnect* inter, u32 addr) return 0; } +// contains = UTIL_contains(CDROM_START, CDROM_SIZE, abs_addr, &offset); +// if (contains) +// { +// cdrom_load(inter->cdrom, offset); +// return 0; +// } + fprintf(stderr, "Unhandled Load8 At Address %08X\n", addr); exit(EXIT_FAILURE); } @@ -200,11 +207,8 @@ INTER_store8(Interconnect* inter, u32 addr, u8 val) 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; + return; } fprintf(stderr, "Unhandled Store8 At Address %08X\n", abs_addr); diff --git a/src/irq.c b/src/irq.c @@ -0,0 +1,70 @@ +/* IRQ Controller */ +#include "irq.h" +#include "types.h" + +irq +irq_new(void) +{ + irq i; + i.status = 0; + i.mask = 0; + return i; +} + +void +irq_write(irq* i, u32 a, u32 v) +{ + v <<= (a & 3) * 8; + + //printf("[IRQ] Write: 0x%08x 0x%08x --- PAD TEMP\n", A, V); + + if(a & 4) i->mask = v; else i->status &= v; + + return; +} + +u32 +irq_load(irq* i, u32 a) +{ + u32 ret = 0; + + if(a & 4) + ret = i->mask; + else + ret = i->status; + + ret |= 0x1F800000; + ret >>= (a & 3) * 8; + + //printf("[IRQ] Read: 0x%08x 0x%08x --- PAD TEMP\n", A, ret); + + return ret; + +} + +void +irq_set_register(irq* i, u32 which, u32 v) +{ + switch(which) + { + case IRQ_STATUS_REG: + i->status = v; + break; + case IRQ_MASK_REG: + i->mask = v; + break; + } +} + +u32 +irq_get_reg(irq* i, u32 which) +{ + switch(which) + { + case IRQ_STATUS_REG: + return i->status; + case IRQ_MASK_REG: + return i->mask; + } + return(0); +} diff --git a/src/irq.h b/src/irq.h @@ -0,0 +1,34 @@ +#pragma once + +#include <stdio.h> +#include "types.h" + +typedef struct irq { + u32 status; + u32 mask; +} irq; + +enum { + IRQ_VBLANK = 0, + IRQ_GPU = 1, + IRQ_CD = 2, + IRQ_DMA = 3, + IRQ_TIMER_0 = 4, + IRQ_TIMER_1 = 5, + IRQ_TIMER_2 = 6, + IRQ_SIO = 7, + IRQ_SPU = 9, + IRQ_PIO = 10, +}; + +enum +{ + IRQ_STATUS_REG = 0, + IRQ_MASK_REG = 1 +}; + +void irq_write(irq*, u32, u32); +u32 irq_load(irq*, u32); +void irq_set_reg(irq*, u32, u32); +u32 irq_get_reg(irq*, u32); +irq irq_new(void); diff --git a/src/sr.c b/src/sr.c @@ -39,7 +39,7 @@ FB_flip_vert(u32 *data) line = (u32 *)malloc(bytes_per_line * sizeof(u32)); half = H>>1; - for (i32 j=0; j<half; j++) { + for (j=0; j<half; j++) { u64 l1 = j*bytes_per_line; u64 l2 = (H-1-j)*bytes_per_line; memmove((void *)line, (void *)(data+l1), bytes_per_line* sizeof(u32)); @@ -49,53 +49,6 @@ FB_flip_vert(u32 *data) free(line); } -ivec2 -IVEC2_op(ivec2 a, ivec2 b, enum mop mop) -{ - ivec2 c; - switch(mop) { - case ADD: - c.x = a.x + b.x; - c.y = a.y + b.y; - break; - case SUB: - c.x = a.x - b.x; - c.y = a.y - b.y; - break; - case MUL: - c.x = a.x * b.x; - c.y = a.y * b.y; - break; - default: - break; - } - return c; -} - -ivec2 -IVEC2_ops(ivec2 a, i32 b, enum mop mop) -{ - ivec2 c; - switch(mop) { - case ADD: - c.x = a.x + b; - c.y = a.y + b; - break; - case SUB: - c.x = a.x - b; - c.y = a.y - b; - break; - case MUL: - c.x = a.x * b; - c.y = a.y * b; - break; - default: - break; - } - return c; -} - - C C_new(u32 b) { @@ -104,7 +57,7 @@ C_new(u32 b) c.g = (u8)((b >> 8) & 0xff); c.b = (u8)((b >> 16) & 0xff); return c; -}; +} void REN_FB_set(REN* ren, i32 x, i32 y, u8 r, u8 g, u8 b) { @@ -130,11 +83,11 @@ void REN_FB_set(REN* ren, i32 x, i32 y, u8 r, u8 g, u8 b) { //} REN* -REN_new() +REN_new(void) { REN* ren; ren = (REN*)malloc(sizeof(REN)); - ren->window = SDL_CreateWindow("Ultimecia", 400 , 300, WIN_W, WIN_H, SDL_WINDOW_SHOWN); + ren->window = SDL_CreateWindow("Ultimecia", 400 , 300, WIN_W, WIN_H, SDL_WINDOW_HIDDEN); ren->renderer = SDL_CreateRenderer(ren->window, -1, 0); ren->tex = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, W, H); ren->verts = (ivec2*)malloc(sizeof(ivec2) * 10000); // Single allocation with larger size diff --git a/src/sr.h b/src/sr.h @@ -36,7 +36,7 @@ ivec2 IVEC2_ops(ivec2, i32, enum mop); C C_new(u32); void REN_triangle(REN*, ivec2[3], C[3]); -REN* REN_new(); +REN* REN_new(void); ivec2 POSITION_from_gp0(u32 val); C COLOR_from_gp0(u32 val); void REN_push_triangle(REN*, ivec2[3], C[3]); diff --git a/src/util.c b/src/util.c @@ -1,6 +1,7 @@ #include "util.h" #include "types.h" #include <limits.h> +#include <stdint.h> const u32 REGION_MASK[8] = { /* KUSEG: 2048MB */ @@ -52,3 +53,17 @@ swap_color(C *a, C *b) { C temp = *a; *a = *b; *b = temp; } void swap_vec2(ivec2 *a, ivec2 *b) { ivec2 temp = *a; *a = *b; *b = temp; } +void +UTIL_bin32(u32 x) { + for (int i = 31; i >= 0; i--) { + putchar((x & (1U << i)) ? '1' : '0'); + if (i % 8 == 0 && i != 0) putchar(' '); + } +} + +void +UTIL_bin8(u8 x) { + for (int i = 7; i >= 0; i--) + putchar((x & (1 << i)) ? '1' : '0'); +} + diff --git a/src/util.h b/src/util.h @@ -52,3 +52,5 @@ void swap_int(int*, int*); void swap_color(C*, C*); void swap_vec2(ivec2*, ivec2*); +void UTIL_bin8(u8); +void UTIL_bin32(u32); diff --git a/test.cc b/test.cc @@ -1,58 +1,25 @@ -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> +#include <iostream> +#include <cstdint> +#include <cstdio> +#include <bitset> +#include <format> - -enum HEY { - DAFAQ = 0x1 -} - -namespace FOO -{ - -typedef struct fyk { - int val; - struct fyk** foo; -} fyk; - -int -find_second_bigger(int* lst) -{ - - int arr[] = {1,2,3,4,5,6}; - size_t length; - length = *(&arr + 1) - arr; - //printf("Length iS %ZU\n", length); - return 0; -} - -typedef enum ho { - ONE, - TWO, - THREE -} HO; - -struct ex { - HO a[7]; -}; - -} +using namespace std; 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; + uint8_t status_bits = 0; + uint8_t value = 1; + int wow = 3; - return 0; + cout << bitset<8>(status_bits) << endl; + cout << bitset<8>(0x1f) << endl; + cout << bitset<8>(~0x1f) << endl; + cout << bitset<8>(0x80) << endl; + cout << (status_bits & static_cast<uint8_t>(~3)) << endl; - HEY a = HEY.DAFUQ; + return 0; }