// // Created by bruno on 2.2.2025. // #include "memory.h" #define SFR_OFFSET (0xDF00) uint8_t write_mem(CPU *cpu, uint32_t addr, uint8_t value) { if (addr >= MEM_SIZE) { return 1; } switch (addr) { case SFR_OFFSET + 0x00: pcm_buffer_push(&audioData.pcmVoice, value << 8 | cpu->memory[SFR_OFFSET + 0x01]); case SFR_OFFSET + 0x02: audioData.synthVoices[0].volume = value; case SFR_OFFSET + 0x03: audioData.synthVoices[0].waveform = value; case SFR_OFFSET + 0x04: audioData.synthVoices[0].phase = value; case SFR_OFFSET + 0x05: audioData.synthVoices[0].frequency = value << 8 | cpu->memory[SFR_OFFSET + 0x06]; case SFR_OFFSET + 0x07: audioData.synthVoices[1].volume = value; case SFR_OFFSET + 0x08: audioData.synthVoices[1].waveform = value; case SFR_OFFSET + 0x09: audioData.synthVoices[1].phase = value; case SFR_OFFSET + 0x0A: audioData.synthVoices[1].frequency = value << 8 | cpu->memory[SFR_OFFSET + 0x0B]; case SFR_OFFSET + 0x0C: audioData.synthVoices[2].volume = value; case SFR_OFFSET + 0x0D: audioData.synthVoices[2].waveform = value; case SFR_OFFSET + 0x0E: audioData.synthVoices[2].phase = value; case SFR_OFFSET + 0x0F: audioData.synthVoices[2].frequency = value << 8 | cpu->memory[SFR_OFFSET + 0x10]; default: break; } cpu->memory[addr] = value; return 0; } uint8_t read_mem(CPU *cpu, uint32_t addr) { if (addr >= MEM_SIZE) { return 0; } switch (addr) { default: return cpu->memory[addr]; } } uint16_t read_mem16(CPU *cpu, uint32_t addr) { return read_mem(cpu, addr) | (read_mem(cpu, addr + 1) << 8); } uint32_t read_mem32(CPU *cpu, uint32_t addr) { return read_mem16(cpu, addr) | (read_mem16(cpu, addr + 2) << 16); } uint32_t read_mem24(CPU *cpu, uint32_t addr) { return read_mem16(cpu, addr) | (read_mem(cpu, addr + 2) << 16); } uint32_t read_address_argument(CPU *cpu) { uint32_t out = read_mem24(cpu, cpu->pc); cpu->pc += 3; if (out >= MEM_SIZE) { out = MEM_SIZE - 1; } return out; } uint8_t read_register_argument(CPU *cpu) { uint8_t out = read_mem(cpu, cpu->pc); cpu->pc += 1; if (out >= REG_COUNT) { out = REG_COUNT - 1; } return out; } // Push a 32-bit program counter (PC) onto the stack void write_stack(CPU *cpu) { if (cpu->pc >= MEM_SIZE) { return; // Invalid memory address } if (cpu->stack_ptr >= STACK_SIZE - 1) { return; // Stack overflow protection } cpu->stack[++cpu->stack_ptr] = cpu->pc; for (uint32_t reg = 0; reg < REG_COUNT; reg += 4) { uint32_t packed = cpu->regs[reg] | ((reg + 1 < REG_COUNT) ? (cpu->regs[reg + 1] << 8) : 0) | ((reg + 2 < REG_COUNT) ? (cpu->regs[reg + 2] << 16) : 0); cpu->stack[++cpu->stack_ptr] = packed; } cpu->stack[++cpu->stack_ptr] = cpu->flags; } // Pop a 32-bit program counter (PC) and registers from the stack void read_stack(CPU *cpu) { if (cpu->stack_ptr == 0) { return; // Stack underflow protection } // Restore flags cpu->flags = cpu->stack[cpu->stack_ptr--]; // Restore registers for (int32_t reg = REG_COUNT - 1; reg >= 0; reg -= 4) { if (cpu->stack_ptr == 0) { return; // Stack underflow protection } uint32_t packed = cpu->stack[cpu->stack_ptr--]; cpu->regs[reg] = (packed & 0xFF); if (reg - 1 >= 0) cpu->regs[reg - 1] = ((packed >> 8) & 0xFF); if (reg - 2 >= 0) cpu->regs[reg - 2] = ((packed >> 16) & 0xFF); } // Restore PC if (cpu->stack_ptr == 0) { return; // Stack underflow protection } cpu->pc = cpu->stack[cpu->stack_ptr--]; } uint8_t read_reg_number(CPU *cpu) { uint8_t out = read_mem(cpu, cpu->pc++); if (out >= REG_COUNT) { return 0; } return out; } uint8_t read_reg(CPU *cpu, uint8_t number) { if (number >= REG_COUNT) { return 0; } return cpu->regs[number]; } uint8_t write_reg(CPU *cpu, uint8_t number, uint8_t value) { if (number >= REG_COUNT) { return 1; } cpu->regs[number] = value; return 0; } uint8_t write_mem16(CPU *cpu, uint32_t addr, uint16_t value) { uint8_t status = write_mem(cpu, addr, value & 0xFF); if (status) { return status; } status = write_mem(cpu, addr + 1, (value >> 8) & 0xFF); if (status) { return status; } return 0; } uint8_t write_mem32(CPU *cpu, uint32_t addr, uint32_t value) { uint8_t status = write_mem16(cpu, addr, value & 0xFFFF); if (status) { return status; } status = write_mem16(cpu, addr + 2, (value >> 16) & 0xFFFF); if (status) { return status; } return 0; }