ultimecia

A ps1 emulator in c
Log | Files | Refs

commit fd282fe3e4bf4f32b895a3719da601f57c9c3d70
parent 2f2ac84b9e4f9fa88fcf03f24f79e6ab8986b4dc
Author: edea <none@fithos.xyz>
Date:   Fri, 26 Apr 2024 22:22:11 +0300

resume work. forgot to push unfinished changes to master

Diffstat:
Msrc/interconnect.c | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/interconnect.h | 6++++--
Msrc/mem.c | 21++++++++++++++++-----
Msrc/mem.h | 29+++++++++++++++--------------
Msrc/tags | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Dtest.c | 61-------------------------------------------------------------
Atest.cc | 45+++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 280 insertions(+), 108 deletions(-)

diff --git a/src/interconnect.c b/src/interconnect.c @@ -22,10 +22,10 @@ INTER_load8(Interconnect* inter, u32 addr) { u32 offset; u32 abs_addr; - u32 contains; + u32 contains; offset = 0; - contains = 0; + contains = 0; abs_addr = mask_region(addr); /* Assert abs_address Mappings */ @@ -126,7 +126,7 @@ INTER_load32(Interconnect* inter, u32 addr) contains = UTIL_contains(DMA_START, DMA_SIZE, abs_addr, &offset); if (contains) { - return INTER_dma_reg(inter->dma, offset); + return INTER_dma_reg(inter, offset); } contains = UTIL_contains(GPU_START, GPU_SIZE, abs_addr, &offset); @@ -148,11 +148,11 @@ void INTER_store8(Interconnect* inter, u32 addr, u8 val) { u32 offset; - u32 contains; + u32 contains; u32 abs_addr; - offset = 0; - contains = 0; + offset = 0; + contains = 0; abs_addr = mask_region(addr); contains = UTIL_contains(EXPANSION2_START, EXPANSION2_SIZE, abs_addr, &offset); @@ -176,11 +176,11 @@ void INTER_store16(Interconnect* inter, u32 addr, u16 val) { u32 offset; - u32 contains; + u32 contains; u32 abs_addr; - offset = 0; - contains = 0; + offset = 0; + contains = 0; abs_addr = mask_region(addr); if (addr % 2 != 0) @@ -265,7 +265,7 @@ INTER_store32(Interconnect* inter, u32 addr, u32 val) contains = UTIL_contains(DMA_START, DMA_SIZE, abs_addr, &offset); if (contains) { - INTER_set_dma_reg(inter->dma, offset, val); + INTER_set_dma_reg(inter, offset, val); return; } @@ -310,7 +310,7 @@ INTER_store32(Interconnect* inter, u32 addr, u32 val) } u32 -INTER_dma_reg(DMA* dma, u32 offset) +INTER_dma_reg(Interconnect* inter, u32 offset) { u32 major, minor, val; major = (offset & 0x70) >> 4; @@ -319,7 +319,7 @@ INTER_dma_reg(DMA* dma, u32 offset) switch (major) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: Channel* channel; - channel = &dma->channels[(Port)major]; + channel = &inter->dma->channels[(Port)major]; switch (minor) { case 0: val = CHANNEL_base(channel); break; case 4: val = CHANNEL_block_control(channel); break; @@ -329,8 +329,8 @@ INTER_dma_reg(DMA* dma, u32 offset) break; case 7: switch (minor) { - case 0: val = DMA_control(dma); break; - case 4: val = DMA_interrupt(dma); break; + case 0: val = DMA_control(inter->dma); break; + case 4: val = DMA_interrupt(inter->dma); break; default: fprintf(stderr, "unhandled DMA access %08X\n", offset); exit(EXIT_FAILURE); } break; @@ -341,32 +341,74 @@ INTER_dma_reg(DMA* dma, u32 offset) } void -INTER_set_dma_reg(DMA* dma, u32 offset, u32 val) +INTER_set_dma_reg(Interconnect* inter, u32 offset, u32 val) { - u32 major, minor; + u32 major, minor, active_port; major = (offset & 0x70) >> 4; minor = offset & 0xf; + active_port = (Port)0; switch (major) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: //printf("MAJOR: %d\n", major); //printf("MINOR: %d\n", minor); Channel* channel; - channel = &dma->channels[(Port)major]; + Port port; + + port = (Port)major; + channel = &inter->dma->channels[port]; switch (minor) { case 0: CHANNEL_set_base(channel, val); break; case 4: CHANNEL_set_block_control(channel, val); break; case 8: CHANNEL_set_control(channel, val); break; default: fprintf(stderr, "Unhandled DMA write at %08X\n", offset); exit(EXIT_FAILURE); } + if (CHANNEL_active(channel)) active_port = port; else active_port = -1; break; case 7: switch (minor) { - case 0: DMA_set_control(dma, val); break; - case 4: DMA_set_interrupt(dma, val); break; - default: fprintf(stderr, "unhandled DMA write %08X\n", offset); exit(EXIT_FAILURE); + case 0: DMA_set_control(inter->dma, val); break; + case 4: DMA_set_interrupt(inter->dma, val); break; + default: active_port = -1; 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); } + + if (active_port > -1) + INTER_do_dma(inter, (Port)active_port); +} + +void +INTER_do_dma(Interconnect* inter, Port port) +{ + Channel* ch; + if ((Port)port < 0) { + fprintf(stderr, "Invalid port doing dma\n"); + exit(EXIT_FAILURE); + } + + ch = &inter->dma->channels[(Port)port]; + + switch (ch->sync) { + case SYNC_LINKED_LIST: fprintf(stderr, "Linked list mode unsupported\n"); exit(EXIT_FAILURE); + default: INTER_do_dma_block(inter, port); break; + } +} + +void +INTER_do_dma_block(Interconnect* inter, Port port) +{ + Channel *ch; + u32 addr, transfer_size, increment; + + ch = &inter->dma->channels[port]; + + switch (ch->step) { + case STEP_INCREMENT: increment = 4; break; + case STEP_DECREMENT: increment = -4; break; + default: fprintf(stderr, "Unreachable!\n"); exit(EXIT_FAILURE); + } + + } diff --git a/src/interconnect.h b/src/interconnect.h @@ -20,5 +20,7 @@ void INTER_store32(Interconnect*, u32, u32); void INTER_store16(Interconnect*, u32, u16); void INTER_store8(Interconnect*, u32, u8); -u32 INTER_dma_reg(DMA*, u32); -void INTER_set_dma_reg(DMA*, u32, u32); +u32 INTER_dma_reg(Interconnect*, u32); +void INTER_set_dma_reg(Interconnect*, u32, u32); +void INTER_do_dma(Interconnect*, Port); +void INTER_do_dma_block(Interconnect*, Port); diff --git a/src/mem.c b/src/mem.c @@ -8,12 +8,11 @@ Channel* CHANNEL_new(void) { - Channel* ch = (Channel*)malloc(sizeof(Channel)); ch->enable = 0; - ch->direction = TO_RAM; - ch->step = INCREMENT; - ch->sync = MANUAL; + ch->direction = DIR_TO_RAM; + ch->step = STEP_INCREMENT; + ch->sync = SYNC_MANUAL; ch->base = 0; ch->trigger = 0; ch->chop = 0; @@ -88,6 +87,19 @@ CHANNEL_set_block_control(Channel* ch, u32 val) ch->block_count = (u16)(val >> 16); } +u8 +CHANNEL_active(Channel* ch) +{ + u8 trigger; + switch (ch->sync) + { + case SYNC_MANUAL: trigger = ch->trigger; break; + default: trigger = 1; break; + } + return ch->enable && trigger; + +} + DMA* DMA_new(void) { @@ -214,4 +226,3 @@ RAM_store32(RAM* r, u32 offset, u32 val) r->data[offset + 2] = b2; r->data[offset + 3] = b3; } - diff --git a/src/mem.h b/src/mem.h @@ -4,29 +4,29 @@ #include "types.h" typedef enum e_Direction { - TO_RAM, - FROM_RAM + DIR_TO_RAM, + DIR_FROM_RAM } Direction; typedef enum e_Step { - INCREMENT, - DECREMENT, + STEP_INCREMENT, + STEP_DECREMENT, } Step; typedef enum e_Sync { - MANUAL, - REQUEST, - LINKED_LIST + SYNC_MANUAL, + SYNC_REQUEST, + SYNC_LINKED_LIST } Sync; typedef enum e_Port { - MDEC_IN, - MDEC_OUT, - GPU, - CD_ROM, - SPU, - PIO, - OTC + PORT_MDEC_IN, + PORT_MDEC_OUT, + PORT_GPU, + PORT_CD_ROM, + PORT_SPU, + PORT_PIO, + PORT_OTC } Port; typedef struct RAM { @@ -74,6 +74,7 @@ u32 CHANNEL_base(Channel*); void CHANNEL_set_base(Channel*, u32); u32 CHANNEL_block_control(Channel*); void CHANNEL_set_block_control(Channel*, u32); +u8 CHANNEL_active(Channel*); RAM* RAM_new(void); u8 RAM_load8(RAM*, u32); diff --git a/src/tags b/src/tags @@ -1,17 +1,149 @@ +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 types.h /^typedef uint8_t Bool;$/ +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_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)$/ +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_/ +CPU_load32 cpu.c /^u32 CPU_load32(CPU* cpu, u32 addr) { return INTER_/ +CPU_load8 cpu.c /^u8 CPU_load8(CPU* cpu, u32 addr) { return INTER_lo/ CPU_run_next_instruction cpu.c /^CPU_run_next_instruction(CPU* cpu)$/ +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;$/ +DMA mem.h /^} DMA;$/ +DMA_control mem.c /^DMA_control(DMA* dma)$/ +DMA_interrupt mem.c /^DMA_interrupt(DMA* dma)$/ +DMA_irq mem.c /^DMA_irq(DMA* dma)$/ +DMA_new mem.c /^DMA_new(void)$/ +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;$/ +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_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)$/ +INTER_set_dma_reg interconnect.c /^INTER_set_dma_reg(Interconnect* inter, u32 offset,/ +INTER_store16 interconnect.c /^INTER_store16(Interconnect* inter, u32 addr, u16 v/ INTER_store32 interconnect.c /^INTER_store32(Interconnect* inter, u32 addr, u32 v/ +INTER_store8 interconnect.c /^INTER_store8(Interconnect* inter, u32 addr, u8 val/ +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)$/ RAM_load32 mem.c /^RAM_load32(RAM* r, u32 offset)$/ +RAM_load8 mem.c /^RAM_load8(RAM* r, u32 offset)$/ +RAM_new mem.c /^RAM_new(void) $/ +RAM_store16 mem.c /^RAM_store16(RAM* r, u32 offset, u16 val)$/ RAM_store32 mem.c /^RAM_store32(RAM* r, u32 offset, u32 val)$/ -UTIL_contains util.c /^UTIL_contains(u8 range, u32 addr)$/ -new_bios bios.c /^new_bios(char* path)$/ +RAM_store8 mem.c /^RAM_store8(RAM* r, u32 offset, u8 val)$/ +Step mem.h /^} Step;$/ +Sync mem.h /^} Sync;$/ +UTIL_contains util.c /^UTIL_contains(u32 start, u32 length, u32 addr, u32/ +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)$/ +exception cpu.c /^exception(CPU* cpu, EXCEPTION cause)$/ +i16 types.h /^typedef int16_t i16;$/ +i32 types.h /^typedef int32_t i32;$/ +i64 types.h /^typedef int64_t i64;$/ +i8 types.h /^typedef int8_t i8;$/ +instruction cpu.h /^} instruction;$/ +mask_region util.c /^u32 mask_region(u32 addr) { return addr & REGION_M/ new_cpu cpu.c /^new_cpu(Interconnect* inter) {$/ new_instr cpu.c /^new_instr(u32 i)$/ new_interconnect interconnect.c /^new_interconnect(void) {$/ -new_ram mem.c /^new_ram(void) $/ -print_instr cpu.c /^print_instr(instruction *ins)$/ -reg cpu.c /^reg(CPU* cpu, u32 reg) $/ -set_reg cpu.c /^set_reg(CPU* cpu, u32 reg, u32 val)$/ +op_add cpu.c /^op_add(CPU* cpu, instruction* i)$/ +op_addi cpu.c /^op_addi(CPU* cpu, instruction* i)$/ +op_addiu cpu.c /^op_addiu(CPU* cpu, instruction* i)$/ +op_addu cpu.c /^op_addu(CPU* cpu, instruction* i)$/ +op_and cpu.c /^op_and(CPU* cpu, instruction* i)$/ +op_andi cpu.c /^op_andi(CPU* cpu, instruction *i)$/ +op_beq cpu.c /^op_beq(CPU* cpu, instruction* i)$/ +op_bgtz cpu.c /^op_bgtz(CPU* cpu, instruction* i)$/ +op_blez cpu.c /^op_blez(CPU* cpu, instruction* i)$/ +op_bne cpu.c /^op_bne(CPU* cpu, instruction* i)$/ +op_break cpu.c /^op_break(CPU* cpu, instruction* i)$/ +op_bxx cpu.c /^op_bxx(CPU* cpu, instruction* i)$/ +op_cop0 cpu.c /^op_cop0(CPU* cpu, instruction* i)$/ +op_cop1 cpu.c /^op_cop1(CPU* cpu, instruction* i)$/ +op_cop2 cpu.c /^op_cop2(CPU* cpu, instruction* i)$/ +op_cop3 cpu.c /^op_cop3(CPU* cpu, instruction* i)$/ +op_div cpu.c /^op_div(CPU* cpu, instruction* i)$/ +op_divu cpu.c /^op_divu(CPU* cpu, instruction* i)$/ +op_illegal cpu.c /^op_illegal(CPU* cpu, instruction* i)$/ +op_j cpu.c /^op_j(CPU* cpu, instruction* i)$/ +op_jal cpu.c /^op_jal(CPU* cpu, instruction* i) $/ +op_jalr cpu.c /^void op_jalr(CPU* cpu, instruction* i) $/ +op_jr cpu.c /^op_jr(CPU* cpu, instruction* i) $/ +op_lb cpu.c /^op_lb(CPU* cpu, instruction* i)$/ +op_lbu cpu.c /^op_lbu(CPU* cpu, instruction* i)$/ +op_lh cpu.c /^op_lh(CPU* cpu, instruction* i)$/ +op_lhu cpu.c /^op_lhu(CPU* cpu, instruction* i)$/ +op_lui cpu.c /^op_lui(CPU* cpu, instruction* i)$/ +op_lw cpu.c /^op_lw(CPU* cpu, instruction* i)$/ +op_lwc0 cpu.c /^void op_lwc0(CPU* cpu, instruction* i) { exception/ +op_lwc1 cpu.c /^void op_lwc1(CPU* cpu, instruction* i) { exception/ +op_lwc2 cpu.c /^void op_lwc2(CPU* cpu, instruction* i) { fprintf(s/ +op_lwc3 cpu.c /^void op_lwc3(CPU* cpu, instruction* i) { exception/ +op_lwl cpu.c /^op_lwl(CPU* cpu, instruction* i)$/ +op_lwr cpu.c /^op_lwr(CPU* cpu, instruction* i)$/ +op_mfc0 cpu.c /^op_mfc0(CPU* cpu, instruction* i)$/ +op_mfhi cpu.c /^op_mfhi(CPU* cpu, instruction* i)$/ +op_mflo cpu.c /^op_mflo(CPU* cpu, instruction* i)$/ +op_mtc0 cpu.c /^op_mtc0(CPU* cpu, instruction* i)$/ +op_mthi cpu.c /^op_mthi(CPU* cpu, instruction* i)$/ +op_mtlo cpu.c /^op_mtlo(CPU* cpu, instruction* i)$/ +op_mult cpu.c /^op_mult(CPU* cpu, instruction* i)$/ +op_multu cpu.c /^op_multu(CPU* cpu, instruction* i)$/ +op_nor cpu.c /^op_nor(CPU* cpu, instruction* i)$/ +op_or cpu.c /^op_or(CPU* cpu, instruction* i)$/ +op_ori cpu.c /^op_ori(CPU* cpu, instruction* i)$/ +op_rfe cpu.c /^op_rfe(CPU* cpu, instruction* i)$/ +op_sb cpu.c /^op_sb(CPU* cpu, instruction* i)$/ +op_sh cpu.c /^op_sh(CPU* cpu, instruction* i)$/ +op_sll cpu.c /^op_sll(CPU* cpu, instruction* i)$/ +op_sllv cpu.c /^op_sllv(CPU* cpu, instruction* i)$/ +op_slt cpu.c /^op_slt(CPU* cpu, instruction* i)$/ +op_slti cpu.c /^op_slti(CPU* cpu, instruction* i)$/ +op_sltiu cpu.c /^op_sltiu(CPU* cpu, instruction* i)$/ +op_sltu cpu.c /^op_sltu(CPU* cpu, instruction* i)$/ +op_sra cpu.c /^op_sra(CPU* cpu, instruction* i)$/ +op_srav cpu.c /^op_srav(CPU* cpu, instruction* i)$/ +op_srl cpu.c /^op_srl(CPU* cpu, instruction* i)$/ +op_srlv cpu.c /^op_srlv(CPU* cpu, instruction* i)$/ +op_sub cpu.c /^op_sub(CPU* cpu, instruction* i)$/ +op_subu cpu.c /^op_subu(CPU* cpu, instruction* i)$/ +op_sw cpu.c /^op_sw(CPU* cpu, instruction* i)$/ +op_swc0 cpu.c /^void op_swc0(CPU* cpu, instruction* i) { exception/ +op_swc1 cpu.c /^void op_swc1(CPU* cpu, instruction* i) { exception/ +op_swc2 cpu.c /^void op_swc2(CPU* cpu, instruction* i) { fprintf(s/ +op_swc3 cpu.c /^void op_swc3(CPU* cpu, instruction* i) { exception/ +op_swl cpu.c /^op_swl(CPU* cpu, instruction* i)$/ +op_swr cpu.c /^op_swr(CPU* cpu, instruction* i)$/ +op_syscall cpu.c /^void op_syscall(CPU* cpu, instruction* i)$/ +op_xor cpu.c /^op_xor(CPU* cpu, instruction* i)$/ +op_xori cpu.c /^op_xori(CPU* cpu, instruction* i)$/ +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/ +u16 types.h /^typedef uint16_t u16;$/ +u32 types.h /^typedef uint32_t u32;$/ +u64 types.h /^typedef uint64_t u64;$/ +u8 types.h /^typedef uint8_t u8;$/ diff --git a/test.c b/test.c @@ -1,61 +0,0 @@ -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> - -struct foo { - int pc; - int ra; -}; - -void -bar(struct foo *foo1) -{ - //foo1->pc +=1; - //foo1->pc == 1; -} - -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; -} - -int -main() -{ - //fyk f = (fyk){100, NULL}; - //fyk f1 = (fyk){1, &f}; - //fyk* f2 = (fyk*)malloc(sizeof(fyk)); - - //f2 = {2, &f1}; - - //printf("Hello there F data %d\n", f2->foo->foo->val); - - //struct foo foo1 = { 1,1 }; - //printf("%d", foo1.pc); - //bar(&foo1); - //printf("%d", foo1.pc); - - //1 ? printf("hello there"), printf("what") : 0; - - uint8_t lst[] = {69,2,3,4,5,6}; - uint8_t a = 8; - - printf("%d\n", *(lst + 2)); - printf("%d\n", &lst); - - //find_second_bigger(lst); - - return 0; -} - diff --git a/test.cc b/test.cc @@ -0,0 +1,45 @@ +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +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]; +}; + +} + +int +main() +{ + + FOO::fyk a; + FOO::ho x = FOO::ONE; + + return 0; +} +