- [NEW] Afegit modul debug

- [NEW] Afegit tagging de memòria
- [NEW] modul mbc_none funcional
- [NEW] Afegit modul main base del programa
- [NEW] Afegits Makefile i .gitignore
- Primera execució. No arriba a 0x0100
- [FIX] Corregida la representació del ensamblador cap enrere
This commit is contained in:
2025-01-15 15:42:14 +01:00
parent b06f26a4b7
commit ab77116dca
10 changed files with 1537 additions and 69 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
gb

8
Makefile Normal file
View File

@@ -0,0 +1,8 @@
compile:
g++ -g *.cpp -lSDL2 -o gb
run: compile
./gb
debug: compile
gdb -ex run gb

1165
debug.cpp Normal file

File diff suppressed because it is too large Load Diff

53
debug.h Normal file
View File

@@ -0,0 +1,53 @@
#pragma once
#include <stdint.h>
namespace debug
{
void init();
void show();
void focus();
void hide();
void pause();
void stop();
void cont();
const bool debugging();
const bool paused();
void setmemmodified(const uint16_t addr);
void refresh();
void sendToConsole(const char* text);
void sendToConsoleLog(const char *text);
void sendMoreToConsoleLog(const char *text);
void DeleteCharConsole();
void executeConsole();
const bool isbreak(const uint16_t address, const uint8_t type=1);
uint32_t next();
uint32_t stepout();
void savestate(const char *filename);
void loadstate(const char *filename);
void loadngo(const char* filename, const char* addr);
void setcursor(const uint16_t address);
void cursorfwd();
void cursorback();
void useOpcode(const uint8_t opcode, const uint8_t base);
void clearUsedOpcodes();
void markUsedOpcodes();
const int getNumOpcodesUsed();
void printOpcodesUsed();
void search(const char *seq=nullptr);
namespace history
{
void store();
void gototop();
void goforward();
void goback();
}
}

214
main.cpp
View File

@@ -1,9 +1,221 @@
#include <stdint.h>
#include <stdio.h>
#include "sm83.h"
#include "mem.h"
#include "sm83dis.h"
#include "debug.h"
//#include "zx_ula.h"
//#include "zx_screen.h"
//#include "zx_tape.h"
#include <SDL2/SDL.h>
#include <string.h>
#include "ui.h"
#include "ui_menu.h"
//#include "z80analyze.h"
#include "ui_window.h"
uint32_t time = 0;
uint32_t t_states = 0;
namespace actions
{
void exitMenu()
{
const uint8_t dt = sm83::step();
debug::cont();
//zxscreen::refresh(dt);
}
int decZoom(int value)
{
//zxscreen::decZoom();
return 0;
}
int incZoom(int value)
{
//zxscreen::incZoom();
return 0;
}
int fullscreen(int value)
{
//zxscreen::toggleFullscreen();
return 0; //zxscreen::getFullscreen();
}
int fullrefresh(int value)
{
//zxscreen::toggleFullRefresh();
return 0; //zxscreen::getFullRefresh();
}
int showAnalyzer(int value)
{
//z80analyze::show();
return 0;
}
}
int main(int argc, char *argv[])
{
mem::init(nullptr, 0);
if (argc < 2) { printf("ABORTING: No rom specified.\n"); exit(1); }
const uint32_t clock = 4194304;
const uint32_t update_freq = clock / 10;
FILE *f = fopen(argv[1], "rb");
if (!f) { printf("ABORTING: Rom not found.\n"); exit(1); }
fseek(f, 0, SEEK_END);
const int filesize = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t *buffer = (uint8_t*)malloc(filesize);
fread(buffer, filesize, 1, f);
fclose(f);
mem::init(buffer, filesize);
sm83dis::loadSymbols();
sm83::reset();
SDL_Init(SDL_INIT_EVERYTHING);
debug::init();
//zxscreen::init(SCREEN_MODE_48K);
ui::menu::init();
ui::menu::setexitcallback(actions::exitMenu);
int menu = ui::menu::addsubmenu("FILE");
ui::menu::addoption(menu, "LOAD ROM", nullptr);
ui::menu::addoption(menu, "SAVE ROM", nullptr);
ui::menu::addseparator(menu);
ui::menu::addoption(menu, "LOAD STATE", nullptr);
ui::menu::addoption(menu, "SAVE STATE", nullptr);
menu = ui::menu::addsubmenu("SCREEN");
ui::menu::addoption(menu, "DEC ZOOM", actions::decZoom);
ui::menu::addoption(menu, "INC ZOOM", actions::incZoom);
ui::menu::addbooloption(menu, "FULLSCREEN", false /*zxscreen::getFullscreen()*/, actions::fullscreen);
ui::menu::addseparator(menu);
ui::menu::addbooloption(menu, "FULL REFRESH", false /*zxscreen::getFullRefresh()*/, actions::fullrefresh);
menu = ui::menu::addsubmenu("EMULATION");
ui::menu::addbooloption(menu, "STOP ON INVALID OP", sm83::getOption(SM83_OPTION_STOP_ON_INVALID), actions::decZoom);
ui::menu::addoption(menu, "SHOW ANALYZER", actions::showAnalyzer);
//zx_ula::sound_init();
debug::stop();
bool should_exit = false;
SDL_Event e;
time = SDL_GetTicks();
t_states = 0;
while (!should_exit)
{
while (SDL_PollEvent(&e))
{
bool result = true;
if (e.type == SDL_QUIT) { should_exit=true; break; }
if (e.type == SDL_MOUSEBUTTONDOWN) result = ui::window::sendEvent(e.button.windowID, &e);
if (e.type == SDL_MOUSEBUTTONUP) result = ui::window::sendEvent(e.button.windowID, &e);
if (e.type == SDL_MOUSEMOTION) result = ui::window::sendEvent(e.motion.windowID, &e);
if (e.type == SDL_WINDOWEVENT) result = ui::window::sendEvent(e.window.windowID, &e);
if (e.type == SDL_MOUSEWHEEL) result = ui::window::sendEvent(e.wheel.windowID, &e);
if (e.type == SDL_TEXTINPUT) result = ui::window::sendEvent(e.text.windowID, &e);
if (e.type == SDL_KEYDOWN) {
if (e.key.keysym.scancode==SDL_SCANCODE_F5) {
if (debug::debugging()) {
debug::history::gototop();
const uint8_t dt = sm83::step();
debug::cont();
//zxscreen::refresh(dt);
}
} else if (e.key.keysym.scancode==SDL_SCANCODE_F8) {
if (!debug::debugging()) {
debug::stop();
//zxscreen::redraw();
} else {
debug::show();
}
} else if (e.key.keysym.scancode==SDL_SCANCODE_F10) {
if (debug::debugging()) {
debug::show();
debug::history::gototop();
const uint8_t dt = sm83::step();
debug::refresh();
//zxscreen::fullrefresh();
//zxscreen::redraw();
//z80analyze::refresh();
}
} else if (e.key.keysym.scancode==SDL_SCANCODE_F11) {
if (debug::debugging()) {
debug::show();
debug::history::gototop();
const uint8_t dt = debug::next();
debug::refresh();
//zxscreen::refresh(dt);
//zxscreen::redraw();
//z80analyze::refresh();
}
} else if (e.key.keysym.scancode==SDL_SCANCODE_F12) {
if (debug::debugging()) {
debug::show();
debug::history::gototop();
const uint8_t dt = debug::stepout();
debug::refresh();
//zxscreen::refresh(dt);
//zxscreen::redraw();
//z80analyze::refresh();
}
}
result = ui::window::sendEvent(e.key.windowID, &e);
}
if (e.type == SDL_MOUSEBUTTONUP && e.button.button==1) ui::setClicked(true);
if (!result)
should_exit = true; break;
}
if (!debug::debugging() && !debug::paused()) {
bool fastload=false;
// En cada bucle fem 10 pasos de la CPU, sino s'ofega
for (int i=0;i<5;++i) {
if (debug::isbreak(sm83::getPC(), 9)) {
debug::stop();
//zxscreen::redraw();
break;
} else {
uint8_t dt = sm83::step();
t_states += dt;
//zx_ula::sound_update(dt);
//zxscreen::refresh(dt);
if (debug::debugging()) break;
}
}
if (t_states>=update_freq)
{
while (SDL_GetTicks()<time+100) {}
t_states -= update_freq;
time = SDL_GetTicks();
//z80analyze::refresh();
}
//z80analyze::refresh(true);
} else if (!debug::debugging() && debug::paused()) {
//zxscreen::redraw(false);
ui::menu::show();
//zxscreen::present();
}
ui::setClicked(false);
}
return 0;
}

View File

@@ -1,5 +1,6 @@
#include "mbc_none.h"
#include "mem.h"
#include <stdlib.h>
namespace mbc_none
{
@@ -10,6 +11,8 @@ namespace mbc_none
uint8_t wram[8192];
uint8_t hram[512];
uint8_t tags[65536];
uint8_t readMem(uint16_t address)
{
if (address < 0x8000) {
@@ -47,10 +50,49 @@ namespace mbc_none
}
}
void init(uint8_t *rom)
uint8_t getTag(uint16_t address)
{
return tags[address];
}
void setTag(uint16_t address, uint8_t value)
{
tags[address] = value;
}
void saveState(FILE* f)
{
}
void loadState(FILE *f)
{
}
void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size)
{
mem::readMem = mbc_none::readMem;
mem::writeMem = mbc_none::writeMem;
mem::getTag = mbc_none::getTag;
mem::setTag = mbc_none::setTag;
mem::saveState = mbc_none::saveState;
mem::loadState = mbc_none::loadState;
mbc_none::rom = rom;
FILE *f = fopen("dmg_boot.bin", "rb");
if (!f) { printf("ABORTING: 'dmg_boot.bin' not found!\n"); exit(1); }
fseek(f, 0, SEEK_END);
const int size = ftell(f);
fseek(f, 0, SEEK_SET);
fread(bootrom, size, 1, f);
fclose(f);
for (int i=0; i<8192; ++i) { vram[i] = 0; }
for (int i=0; i<8192; ++i) { exram[i] = 0; }
for (int i=0; i<8192; ++i) { wram[i] = 0; }
for (int i=0; i<512; ++i) { hram[i] = 0; }
for (int i=0; i<65536; ++i) { tags[i] = MEMTAG_NONE; }
}
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
namespace mbc_none
{
void init();
void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size);
}

30
mem.cpp
View File

@@ -1,28 +1,20 @@
#include "mem.h"
#include <stdlib.h>
#include <stdio.h>
#include "mbc_none.h"
namespace mem
{
uint8_t(*readMem)(uint16_t);
void (*writeMem)(uint16_t, uint8_t);
uint8_t(*getTag)(uint16_t);
void (*setTag)(uint16_t, uint8_t);
void (*saveState)(FILE*);
void (*loadState)(FILE*);
char *title = nullptr;
/*uint8_t *memory = nullptr;
uint8_t *mapper_type = nullptr;
uint8_t *rom_size = nullptr;
uint8_t *ram_size = nullptr;*/
uint8_t r(uint16_t address)
{
return 0;
}
void w(uint16_t address, uint8_t value)
{
}
void init(const uint8_t* rom, const int size)
void init(uint8_t* rom, const int size)
{
//if (memory) free(memory);
//memory = (uint8_t*)malloc(size);
@@ -32,8 +24,12 @@ namespace mem
int sizes[] = { 0, 0, 8, 32, 128, 64};
uint32_t ram_size = sizes[rom[0x149]] * 1024;
readMem = r;
writeMem = w;
switch (mapper_type)
{
case 0x00:
mbc_none::init(rom, rom_size, ram_size);
break;
};
}
void reset()

24
mem.h
View File

@@ -1,8 +1,21 @@
#pragma once
#include <stdint.h>
#include <stdio.h>
namespace mem
{
#define MEMTAG_NONE 0x00
#define MEMTAG_DATA 0x01
#define MEMTAG_INST 0x02
#define MEMTAG_CODE 0x04
#define MEMTAG_IGNORE 0x08
#define MEMTAG_TDATA 0x10
#define MEMTAG_TINST 0x20
#define MEMTAG_TREPEAT 0x40
#define MEMTAG_MODIFIED 0x80
#define MEMTAG_KNOWN 0x07
#define MEMTAG_TOUCHED 0x70
#define MBC_NONE 0
#define MBC1 1
#define MBC2 2
@@ -11,8 +24,15 @@ namespace mem
#define MBC6 6
#define MBC7 7
void init(const uint8_t* rom, const int size);
void init(uint8_t* rom, const int size);
void reset();
extern uint8_t(*readMem)(uint16_t);
extern void (*writeMem)(uint16_t, uint8_t);
extern uint8_t(*getTag)(uint16_t);
extern void (*setTag)(uint16_t, uint8_t);
extern void (*saveState)(FILE*);
extern void (*loadState)(FILE*);
}

View File

@@ -1,7 +1,6 @@
#include "sm83.h"
#include "mem.h"
//#include "z80debug.h"
//#include "z80mem.h"
#include "debug.h"
#include <stdio.h>
namespace sm83
@@ -75,22 +74,21 @@ namespace sm83
uint8_t READ_MEM_8(const uint16_t addr, const bool code=false)
{
//if (z80debug::isbreak(addr, 2)) z80debug::stop();
if (debug::isbreak(addr, 2)) debug::stop();
t+=4;
/*
const uint8_t tag = z80mem::get()->getTag(addr);
const uint8_t tag = mem::getTag(addr);
if ( !(tag&MEMTAG_IGNORE) ) {
if (!code) {
if ( tag & MEMTAG_INST ) {
} else {
z80mem::get()->setTag(addr, tag | MEMTAG_DATA);
mem::setTag(addr, tag | MEMTAG_DATA);
}
} else {
if ( (reading_m1) && ( tag & MEMTAG_DATA ) ) {
}
}
}
*/
reading_m1 = false;
return mem::readMem(addr);
}
@@ -98,8 +96,8 @@ namespace sm83
uint8_t READ_MEM_8()
{
const uint8_t data = READ_MEM_8(rPC, true);
//const uint8_t tag = z80mem::get()->getTag(rPC);
//if ( !(tag & MEMTAG_IGNORE) ) z80mem::get()->setTag(rPC, tag | MEMTAG_CODE);
const uint8_t tag = mem::getTag(rPC);
if ( !(tag & MEMTAG_IGNORE) ) mem::setTag(rPC, tag | MEMTAG_CODE);
rPC++;
return data;
}
@@ -127,20 +125,18 @@ namespace sm83
t+=4;
mem::writeMem(addr, value);
/*
if (z80debug::isbreak(addr, 4)) z80debug::stop();
z80debug::setmemmodified(addr);
if (debug::isbreak(addr, 4)) debug::stop();
debug::setmemmodified(addr);
const uint8_t tag = z80mem::get()->getTag(addr);
const uint8_t tag = mem::getTag(addr);
if ( !(tag & MEMTAG_IGNORE) ) {
if ( tag & MEMTAG_INST ) {
//printf("WARNING! WRITING DATA OVER CODE!!! $%4X\n", addr);
//z80debug::stop();
} else {
z80mem::get()->setTag(addr, tag | MEMTAG_DATA | MEMTAG_TDATA);
mem::setTag(addr, tag | MEMTAG_DATA | MEMTAG_TDATA);
}
}
*/
return value;
}
@@ -718,10 +714,10 @@ namespace sm83
t = 0;
const uint8_t opcode = READ_M1();
/*uint8_t tag = z80mem::get()->getTag(current_opcode_address);
uint8_t tag = mem::getTag(current_opcode_address);
if ( !(tag & MEMTAG_IGNORE) )
tag = tag | MEMTAG_INST;
z80mem::get()->setTag(current_opcode_address, tag | (!(tag&MEMTAG_TOUCHED) ? MEMTAG_TREPEAT : MEMTAG_TINST) );*/
mem::setTag(current_opcode_address, tag | (!(tag&MEMTAG_TOUCHED) ? MEMTAG_TREPEAT : MEMTAG_TINST) );
uint16_t tmp;
@@ -1007,8 +1003,8 @@ namespace sm83
if (pending_ei==2) { pending_ei=0; actualEI(); }
if (pending_ei==1) pending_ei=2;
/*z80debug::setcursor(rPC);
z80debug::history::store();*/
debug::setcursor(rPC);
debug::history::store();
return t;
}
@@ -1308,32 +1304,6 @@ namespace sm83
void setPC(const uint16_t addr) { rPC = addr; }
/*
uint8_t getMemTag(const uint16_t addr) { return memtag[addr]; }
void setMemTag(const uint16_t addr, const uint8_t value) { memtag[addr] = value; }
void clearMemTag()
{
for (int i=0; i<65536; ++i) memtag[i] = MEMTAG_NONE;
}
uint8_t getMemTouched(const uint16_t addr) { return memtouched[addr]; }
void clearMemTouched()
{
for (int i=0; i<65536; ++i) memtouched[i] = MEMTAG_NONE;
}
void fixMemTouched()
{
for (int i=0; i<65536; ++i)
if ( (memtouched[i]==MEMTAG_INST) || (memtouched[i]==MEMTAG_REPEAT) )
memtouched[i] = MEMTAG_DATA;
//else if (memtouched[i]==MEMTAG_DATA)
// memtouched[i] = MEMTAG_REPEAT;
}
*/
const bool getOption(const int option)
{