~groovestomp/gsnes

569e68eb6d8ef917668cc3fa9b0d46d9a9123526 — GrooveStomp 1 year, 6 months ago 775f165
Basic introspection in main()
5 files changed, 141 insertions(+), 26 deletions(-)

M .gitignore
M bus.c
M cpu.c
M cpu.h
A main.c
M .gitignore => .gitignore +1 -0
@@ 1,3 1,4 @@
release
#*
debug
core

M bus.c => bus.c +1 -2
@@ 4,7 4,7 @@

  File: bus.c
  Created: 2019-10-16
  Updated: 2019-10-16
  Updated: 2019-10-31
  Author: Aaron Oman
  Notice: GNU AGPLv3 License



@@ 26,7 26,6 @@ struct bus {

struct bus *BusInit(struct cpu *cpu) {
        struct bus *bus = (struct bus *)malloc(sizeof(struct bus));
        return bus;

        bus->ram = (uint8_t *)malloc(64 * 1024);
        for (int i = 0; i < 64 * 1024; i++) {

M cpu.c => cpu.c +16 -19
@@ 178,7 178,7 @@ void Clock(struct cpu *cpu) {
        cpu->cycles--;
}

void Reset(struct cpu *cpu) {
void CpuReset(struct cpu *cpu) {
        cpu->a = 0;
        cpu->x = 0;
        cpu->y = 0;


@@ 243,6 243,7 @@ void Nmi(struct cpu *cpu) {

//-- Addressing Modes ----------------------------------------------------------


//! \brief Add with Carry
//!
//! \param[in,out] cpu


@@ 1385,6 1386,7 @@ uint8_t XXX(struct cpu *cpu) {

//-- Helper Functions ----------------------------------------------------------


//! \brief convert number to hexadecimal string
//!
//! \param[in] n number to convert to hex


@@ 1399,12 1401,9 @@ void ToHexString(uint32_t n, uint8_t d, char *buf, uint8_t size) {
        for (int i = d - 1; i >= 0; i--, n >>= 4) {
                buf[i] = "0123456789ABCDEF"[n & 0xF];
        }
}

struct debug_instruction_map {
        struct debug_instruction **map;
        int count;
};
        buf[d] = '\0';
}

void DebugInstructionMapDeinit(struct debug_instruction_map *map) {
        if (NULL == map) {


@@ 1418,12 1417,6 @@ void DebugInstructionMapDeinit(struct debug_instruction_map *map) {
        free(map);
}

struct debug_instruction {
        uint16_t address;
        char *text;
        int text_length;
};

struct debug_instruction *DebugInstructionInit(uint16_t address, char *string, int length) {
        struct debug_instruction *self = (struct debug_instruction *)malloc(sizeof(struct debug_instruction));
        self->text = malloc(length);


@@ 1443,7 1436,7 @@ void DebugInstructionDeinit(struct debug_instruction *self) {
        free(self);
}

struct debug_instruction_map *Disassemble(struct cpu *cpu, uint16_t start, uint16_t stop) {
struct debug_instruction_map *CpuDisassemble(struct cpu *cpu, uint16_t start, uint16_t stop) {
        int addr = start;
        uint8_t value = 0x00;
        uint8_t lo = 0x00;


@@ 1454,8 1447,8 @@ struct debug_instruction_map *Disassemble(struct cpu *cpu, uint16_t start, uint1
        debug_map->count = stop - start;
        debug_map->map = (struct debug_instruction **)malloc(sizeof(struct debug_instruction *) * debug_map->count);

        char text[256];
        char text_cpy[256];
        char text[256] = { 0 };
        char text_cpy[256] = { 0 };
        uint8_t hex_buf_len = 5; // Space for terminating null.
        char hex_buf[hex_buf_len];
        uint16_t text_len = hex_buf_len; // Size adjusts as we construct string below.


@@ 1465,21 1458,22 @@ struct debug_instruction_map *Disassemble(struct cpu *cpu, uint16_t start, uint1

        int i = 0;
        while (addr <= stop) {
                text_len = hex_buf_len; // Size adjusts as we construct string below.
                line_addr = addr;
                struct instruction instruction;

                // Prefix instruction with address.
                ToHexString(addr, 4, hex_buf, hex_buf_len);
                text_len++;
                text_len += 3; // Adding $, <colon> and <space>
                snprintf(text, text_len, "$%s: ", hex_buf);
                strncpy(text_cpy, text, strnlen(text, text_len));
                strncpy(text_cpy, text, strnlen(text, text_len) + 1);

                // Get the readable name of the instruction.
                uint8_t opcode = BusRead(cpu->bus, addr);
                instruction = instruction_map[opcode];
                addr++;
                text_len += 4; // instruction.name is 3 chars, plus an extra space.
                snprintf(text, text_len, "%s%s ", text_cpy, instruction.name);
                snprintf(text, text_len, "%s%s ", text_cpy, instruction.name); //<--
                strncpy(text_cpy, text, strnlen(text, text_len));

                if (IMP == instruction.address) {


@@ 1551,7 1545,10 @@ struct debug_instruction_map *Disassemble(struct cpu *cpu, uint16_t start, uint1
                        value = BusRead(cpu->bus, addr);
                        addr++;
                        ToHexString(value, 2, hex_buf, hex_buf_len);
                        // TODO... sInst += "$" + hex(value, 2) + " [$" + hex(addr + value, hex_buf_len) + "] {REL}";

                        char hex_buf2[5];
                        ToHexString(addr + value, 4, hex_buf2, hex_buf_len);
                        snprintf(text, 256, "%s$%s [$%s] {REL}", text_cpy, hex_buf, hex_buf2);
                }

                debug_map->map[i] = DebugInstructionInit(line_addr, text, strnlen(text, 256));

M cpu.h => cpu.h +26 -5
@@ 4,7 4,7 @@

  File: cpu.h
  Created: 2019-10-16
  Updated: 2019-10-17
  Updated: 2019-10-31
  Author: Aaron Oman
  Notice: GNU AGPLv3 License



@@ 13,6 13,7 @@
  This is free software, and you are welcome to redistribute it under certain
  conditions; See LICENSE for details.
 ******************************************************************************/
#include <stdint.h>

//! \file cpu.h



@@ 31,9 32,29 @@ CpuDeinit(struct cpu *cpu);
void
CpuConnectBus(struct cpu *cpu, struct bus *bus);

void Clock();
void Reset();
void Irq();
void Nmi();
void
CpuReset(struct cpu *cpu);

//-- Debug ---------------------------------------------------------------------

struct debug_instruction {
        uint16_t address;
        char *text;
        int text_length;
};

struct debug_instruction_map {
        struct debug_instruction **map;
        int count;
};

void
DebugInstructionDeinit(struct debug_instruction *inst);

void
DebugInstructionMapDeinit(struct debug_instruction_map *map);

struct debug_instruction_map *
CpuDisassemble(struct cpu *cpu, uint16_t start, uint16_t stop);

#endif // CPU_VERSION

A main.c => main.c +97 -0
@@ 0,0 1,97 @@
/******************************************************************************
  GrooveStomp's NES Emulator
  Copyright (c) 2019 Aaron Oman (GrooveStomp)

  File: main.c
  Created: 2019-10-31
  Updated: 2019-10-31
  Author: Aaron Oman
  Notice: GNU AGPLv3 License

  Based off of: One Lone Coder NES Emulator Copyright (C) 2018 Javidx9
  This program comes with ABSOLUTELY NO WARRANTY.
  This is free software, and you are welcome to redistribute it under certain
  conditions; See LICENSE for details.
 ******************************************************************************/
#include <stdlib.h> // strtoul
#include <string.h> // strlen
#include <stdio.h> // printf

#include "cpu.h"
#include "bus.h"

//! \file main.c

// Load Program (assembled at https://www.masswerk.at/6502/assembler.html)
/*
 *=$8000
 LDX #10
 STX $0000
 LDX #3
 STX $0001
 LDY $0000
 LDA #0
 CLC
 loop
 ADC $0001
 DEY
 BNE loop
 STA $0002
 NOP
 NOP
 NOP
*/
static char *program = "A2 0A 8E 00 00 A2 03 8E 01 00 AC 00 00 A9 00 18 6D 01 00 88 D0 FA 8D 02 00 EA EA EA";

void LoadProgram(struct bus *bus, char *data) {
        uint16_t ram_offset = 0;
        char *last_byte = NULL;

        unsigned long i = strtoul(data, &last_byte, 16);
        while (data != last_byte) {
                BusWrite(bus, ram_offset++, (uint8_t)i);
                data = last_byte;
                i = strtoul(data, &last_byte, 16);
        }
}

int main(int argc, char **argv) {
        struct cpu *cpu = CpuInit();
        struct bus *bus = BusInit(cpu);
        CpuConnectBus(cpu, bus);

        LoadProgram(bus, program);

        // Set reset vector.
        BusWrite(bus, 0xFFFC, 0x00);
        BusWrite(bus, 0xFFFD, 0x80);

        // Disassemble
        struct debug_instruction_map *map = CpuDisassemble(cpu, 0x0000, 0x000F);

        for (int i = 0; i < map->count; i++) {
                printf("map{%p}", map);
                if (NULL != map) {
                        printf("->map{%p}", map->map);

                        if (NULL != map->map) {
                                printf("[i]{%p}", map->map[i]);

                                if (NULL != map->map[i]) {
                                        printf("->text{%s}", map->map[i]->text);
                                }
                        }
                }
                printf("\n");
        }

        DebugInstructionMapDeinit(map);

        // Reset
        CpuReset(cpu);

        BusDeinit(bus);
        CpuDeinit(cpu);

        return 0;
}