- [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:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
gb
|
||||
8
Makefile
Normal file
8
Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
compile:
|
||||
g++ -g *.cpp -lSDL2 -o gb
|
||||
|
||||
run: compile
|
||||
./gb
|
||||
|
||||
debug: compile
|
||||
gdb -ex run gb
|
||||
53
debug.h
Normal file
53
debug.h
Normal 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
214
main.cpp
@@ -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;
|
||||
}
|
||||
44
mbc_none.cpp
44
mbc_none.cpp
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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
30
mem.cpp
@@ -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
24
mem.h
@@ -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*);
|
||||
}
|
||||
|
||||
60
sm83.cpp
60
sm83.cpp
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user