Compare commits
4 Commits
88a02d49f7
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 35afea447b | |||
| 8ba37d215a | |||
| ed2c014c7e | |||
| 2fe0ce6152 |
@@ -1,5 +1,5 @@
|
|||||||
compile:
|
compile:
|
||||||
g++ -g *.cpp -lSDL2 -o gb
|
g++ -g source/*.cpp -lSDL2 -o gb
|
||||||
|
|
||||||
run: compile
|
run: compile
|
||||||
./gb tetris.gb
|
./gb tetris.gb
|
||||||
@@ -11,7 +11,7 @@ debug1: compile
|
|||||||
gdb -ex run gb
|
gdb -ex run gb
|
||||||
|
|
||||||
release:
|
release:
|
||||||
g++ -O3 *.cpp -lSDL2 -o gb
|
g++ -O3 source/*.cpp -lSDL2 -o gb
|
||||||
|
|
||||||
profile:
|
profile:
|
||||||
g++ -g *.cpp -lSDL2 -o gb -pg
|
g++ -g source/*.cpp -lSDL2 -o gb -pg
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define INTERRUPT_VBLANK 0x01
|
|
||||||
#define INTERRUPT_LCD 0x02
|
|
||||||
#define INTERRUPT_TIMER 0x04
|
|
||||||
#define INTERRUPT_SERIAL 0x08
|
|
||||||
#define INTERRUPT_JOYPAD 0x10
|
|
||||||
+1
-1
@@ -2,5 +2,5 @@
|
|||||||
cppflags = -g
|
cppflags = -g
|
||||||
libs = -lSDL2
|
libs = -lSDL2
|
||||||
executable = gb
|
executable = gb
|
||||||
sourcepath = .
|
sourcepath = source
|
||||||
buildpath = build
|
buildpath = build
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "apu.h"
|
#include "apu.h"
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
//#include "audio_viewer.h"
|
|
||||||
namespace apu
|
namespace apu
|
||||||
{
|
{
|
||||||
#define SAMPLING_FREQ 44100
|
#define SAMPLING_FREQ 44100
|
||||||
@@ -10,9 +10,7 @@ namespace apu
|
|||||||
SDL_AudioDeviceID sdlAudioDevice;
|
SDL_AudioDeviceID sdlAudioDevice;
|
||||||
uint8_t sound_buffer[AUDIO_BUFFER_SIZE];
|
uint8_t sound_buffer[AUDIO_BUFFER_SIZE];
|
||||||
uint16_t sound_pos=0;
|
uint16_t sound_pos=0;
|
||||||
uint16_t sound_start=0;
|
|
||||||
float t_sound = 0.0f;
|
float t_sound = 0.0f;
|
||||||
uint32_t samples_generated=0;
|
|
||||||
|
|
||||||
#define CH1 channels[0]
|
#define CH1 channels[0]
|
||||||
#define CH2 channels[1]
|
#define CH2 channels[1]
|
||||||
@@ -87,9 +85,11 @@ namespace apu
|
|||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
|
for (int i=0; i<AUDIO_BUFFER_SIZE; ++i) sound_buffer[i] = 128;
|
||||||
SDL_AudioSpec audioSpec{SAMPLING_FREQ, AUDIO_U8, 1, 0, AUDIO_BUFFER_SIZE, 0, 0, NULL, NULL};
|
SDL_AudioSpec audioSpec{SAMPLING_FREQ, AUDIO_U8, 1, 0, AUDIO_BUFFER_SIZE, 0, 0, NULL, NULL};
|
||||||
sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
|
sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
|
||||||
resume();
|
resume();
|
||||||
|
SDL_QueueAudio(sdlAudioDevice, sound_buffer, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
@@ -428,7 +428,8 @@ namespace apu
|
|||||||
if (sound_pos>=1000) {
|
if (sound_pos>=1000) {
|
||||||
SDL_QueueAudio(sdlAudioDevice, sound_buffer, sound_pos);
|
SDL_QueueAudio(sdlAudioDevice, sound_buffer, sound_pos);
|
||||||
sound_pos = 0;
|
sound_pos = 0;
|
||||||
while (SDL_GetQueuedAudioSize(sdlAudioDevice) > 4096 ) {}
|
while (SDL_GetQueuedAudioSize(sdlAudioDevice) > 4096 ) { SDL_Delay(1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,8 @@ namespace debug
|
|||||||
int con_h = 6;
|
int con_h = 6;
|
||||||
int sym_h = 14;
|
int sym_h = 14;
|
||||||
|
|
||||||
|
uint8_t tags[65536];
|
||||||
|
|
||||||
int resizing_type = RESIZING_MEMORY;
|
int resizing_type = RESIZING_MEMORY;
|
||||||
bool resizing = false;
|
bool resizing = false;
|
||||||
|
|
||||||
@@ -108,10 +110,9 @@ namespace debug
|
|||||||
con_y = win_h - con_h;
|
con_y = win_h - con_h;
|
||||||
sym_h = win_h - sym_y;
|
sym_h = win_h - sym_y;
|
||||||
debug::refresh();
|
debug::refresh();
|
||||||
display::redraw();
|
|
||||||
} else if (e->window.event == SDL_WINDOWEVENT_CLOSE) {
|
} else if (e->window.event == SDL_WINDOWEVENT_CLOSE) {
|
||||||
hide();
|
hide();
|
||||||
display::focus();
|
//display::focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e->type == SDL_MOUSEWHEEL) {
|
if (e->type == SDL_MOUSEWHEEL) {
|
||||||
@@ -305,10 +306,63 @@ namespace debug
|
|||||||
|
|
||||||
void processCommand();
|
void processCommand();
|
||||||
|
|
||||||
|
uint8_t getTag(uint16_t address)
|
||||||
|
{
|
||||||
|
return tags[address];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTag(uint16_t address, uint8_t value)
|
||||||
|
{
|
||||||
|
tags[address] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onInstructionExecute(uint16_t address)
|
||||||
|
{
|
||||||
|
uint8_t &tag = tags[address];
|
||||||
|
if ( !(tag & MEMTAG_IGNORE) ) tag |= MEMTAG_INST;
|
||||||
|
tag |= (!(tag&MEMTAG_TOUCHED) ? MEMTAG_TREPEAT : MEMTAG_TINST);
|
||||||
|
|
||||||
|
setcursor(sm83::getPC());
|
||||||
|
history::store();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onMemRead(uint16_t address, bool code)
|
||||||
|
{
|
||||||
|
if (isbreak(address, 2)) stop();
|
||||||
|
|
||||||
|
uint8_t &tag = tags[address];
|
||||||
|
if ( tag & MEMTAG_IGNORE) return;
|
||||||
|
|
||||||
|
if ( code ) {
|
||||||
|
tag |= MEMTAG_CODE;
|
||||||
|
} else if ( !(tag & MEMTAG_INST) ) {
|
||||||
|
tag |= MEMTAG_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onMemWrite(uint16_t address)
|
||||||
|
{
|
||||||
|
if (isbreak(address, 4)) stop();
|
||||||
|
|
||||||
|
mem_modified[address] = true;
|
||||||
|
|
||||||
|
uint8_t &tag = tags[address];
|
||||||
|
if ( tag & MEMTAG_IGNORE ) return;
|
||||||
|
|
||||||
|
if ( !(tag & MEMTAG_INST) ) {
|
||||||
|
tag |= ( MEMTAG_DATA | MEMTAG_TDATA );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
is_debugging = is_paused = false;
|
is_debugging = is_paused = false;
|
||||||
for (int i=0; i<65536; ++i) breakpoints[i]=0;
|
for (int i=0; i<65536; ++i) {
|
||||||
|
breakpoints[i]=0;
|
||||||
|
tags[i] = MEMTAG_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cur_df) cur_df = SDL_GetCursor();
|
if (!cur_df) cur_df = SDL_GetCursor();
|
||||||
if (!cur_ns) cur_ns = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
|
if (!cur_ns) cur_ns = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
|
||||||
if (!cur_we) cur_we = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
|
if (!cur_we) cur_we = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
|
||||||
@@ -381,10 +435,9 @@ namespace debug
|
|||||||
uint16_t find_previous_opcode(uint16_t pc)
|
uint16_t find_previous_opcode(uint16_t pc)
|
||||||
{
|
{
|
||||||
pc--;
|
pc--;
|
||||||
uint8_t tag = mem::getTag(pc);
|
if ( !(tags[pc] & (MEMTAG_CODE | MEMTAG_INST) ) ) return pc;
|
||||||
if ( !(tag & (MEMTAG_CODE | MEMTAG_INST) ) ) return pc;
|
|
||||||
|
|
||||||
while ( !(mem::getTag(pc) & MEMTAG_INST) ) pc--;
|
while ( !(tags[pc] & MEMTAG_INST) ) pc--;
|
||||||
|
|
||||||
return pc;
|
return pc;
|
||||||
|
|
||||||
@@ -410,7 +463,7 @@ namespace debug
|
|||||||
void printDissasemblerLine(const uint16_t address, const int line, const bool heuristics=false)
|
void printDissasemblerLine(const uint16_t address, const int line, const bool heuristics=false)
|
||||||
{
|
{
|
||||||
uint8_t colors[4] = { COLOR_RED, COLOR_CYAN, COLOR_WHITE, COLOR_WHITE};
|
uint8_t colors[4] = { COLOR_RED, COLOR_CYAN, COLOR_WHITE, COLOR_WHITE};
|
||||||
const uint8_t tag = mem::getTag(address);
|
const uint8_t &tag = tags[address];
|
||||||
if ( !(tag & (MEMTAG_TINST | MEMTAG_TREPEAT)) ) colors[3]=COLOR_GRAY;
|
if ( !(tag & (MEMTAG_TINST | MEMTAG_TREPEAT)) ) colors[3]=COLOR_GRAY;
|
||||||
if ( !(tag & MEMTAG_TOUCHED) ) colors[1]=COLOR_GRAY;
|
if ( !(tag & MEMTAG_TOUCHED) ) colors[1]=COLOR_GRAY;
|
||||||
|
|
||||||
@@ -428,7 +481,7 @@ namespace debug
|
|||||||
|
|
||||||
const int opcodesize = sm83dis::getOpcodeSize(address);
|
const int opcodesize = sm83dis::getOpcodeSize(address);
|
||||||
for (int i=0; i<opcodesize; ++i) {
|
for (int i=0; i<opcodesize; ++i) {
|
||||||
const uint8_t tag = mem::getTag(address+i);
|
const uint8_t &tag = tags[address+i];
|
||||||
const uint32_t color = !(tag & MEMTAG_KNOWN) ? COLOR_GRAY : (tag & MEMTAG_DATA) ? ( (tag & (MEMTAG_CODE|MEMTAG_INST)) ? COLOR_MAGENTA : COLOR_BLUE ) : COLOR_GREEN;
|
const uint32_t color = !(tag & MEMTAG_KNOWN) ? COLOR_GRAY : (tag & MEMTAG_DATA) ? ( (tag & (MEMTAG_CODE|MEMTAG_INST)) ? COLOR_MAGENTA : COLOR_BLUE ) : COLOR_GREEN;
|
||||||
ui::printrect(19+i*3,line,2,1,color);
|
ui::printrect(19+i*3,line,2,1,color);
|
||||||
}
|
}
|
||||||
@@ -608,7 +661,7 @@ namespace debug
|
|||||||
ui::printtxt(1,i, tohex(mem_viewer_cursor, 4), COLOR_CYAN);
|
ui::printtxt(1,i, tohex(mem_viewer_cursor, 4), COLOR_CYAN);
|
||||||
for (int j=0; j<16; ++j) {
|
for (int j=0; j<16; ++j) {
|
||||||
|
|
||||||
const uint8_t tag = mem::getTag(mem_viewer_cursor);
|
const uint8_t &tag = tags[mem_viewer_cursor];
|
||||||
const uint32_t color = !(tag & MEMTAG_KNOWN) ? COLOR_GRAY : (tag & MEMTAG_DATA) ? ( (tag & (MEMTAG_CODE|MEMTAG_INST)) ? COLOR_MAGENTA : COLOR_BLUE ) : COLOR_GREEN;
|
const uint32_t color = !(tag & MEMTAG_KNOWN) ? COLOR_GRAY : (tag & MEMTAG_DATA) ? ( (tag & (MEMTAG_CODE|MEMTAG_INST)) ? COLOR_MAGENTA : COLOR_BLUE ) : COLOR_GREEN;
|
||||||
ui::printrect(6+j*3,i,2,1,color);
|
ui::printrect(6+j*3,i,2,1,color);
|
||||||
ui::printrect(54+j,i,1,1,color);
|
ui::printrect(54+j,i,1,1,color);
|
||||||
@@ -886,7 +939,7 @@ namespace debug
|
|||||||
getcmd();
|
getcmd();
|
||||||
int address = getnum(cmd);
|
int address = getnum(cmd);
|
||||||
if (address<0 || address>=65536) { sendToConsoleLog("Illegal address"); return; }
|
if (address<0 || address>=65536) { sendToConsoleLog("Illegal address"); return; }
|
||||||
if ( !(mem::getTag(address) & MEMTAG_INST) ) address = find_previous_opcode(address);
|
if ( !(tags[address] & MEMTAG_INST) ) address = find_previous_opcode(address);
|
||||||
debug::setcursor(address);
|
debug::setcursor(address);
|
||||||
} else if (strcmp(cmd, "sym")==0 || strcmp(cmd, "symbol")==0) {
|
} else if (strcmp(cmd, "sym")==0 || strcmp(cmd, "symbol")==0) {
|
||||||
getcmd();
|
getcmd();
|
||||||
@@ -938,7 +991,7 @@ namespace debug
|
|||||||
} else if (strcmp(cmd, "ignore")==0) {
|
} else if (strcmp(cmd, "ignore")==0) {
|
||||||
getcmd();
|
getcmd();
|
||||||
const int address = getnum(cmd);
|
const int address = getnum(cmd);
|
||||||
mem::setTag(address, mem::getTag(address) | MEMTAG_IGNORE);
|
tags[address] |= MEMTAG_IGNORE;
|
||||||
} else if (strcmp(cmd, "search")==0) {
|
} else if (strcmp(cmd, "search")==0) {
|
||||||
getcmd();
|
getcmd();
|
||||||
if (strcmp(cmd, "next")==0) {
|
if (strcmp(cmd, "next")==0) {
|
||||||
@@ -979,30 +1032,6 @@ namespace debug
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setmemmodified(const uint16_t addr)
|
|
||||||
{
|
|
||||||
mem_modified[addr] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loadngo(const char* filename, const char* addr)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
int address = getnum(addr);
|
|
||||||
if (address<0 || address>65536) { sendToConsoleLog("Illegal offset"); return; }
|
|
||||||
|
|
||||||
FILE *f = fopen(filename, "rb");
|
|
||||||
fseek(f, 0, SEEK_END);
|
|
||||||
int size = ftell(f);
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
uint32_t memsize;
|
|
||||||
uint8_t *memory = mem::getRawPointer(&memsize);
|
|
||||||
fread(memory+address, size, 1, f);
|
|
||||||
fclose(f);
|
|
||||||
sm83::setPC(address);
|
|
||||||
is_debugging = is_paused = false;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void savestate(const char *filename)
|
void savestate(const char *filename)
|
||||||
{
|
{
|
||||||
uint8_t *regs = sm83::getRegs();
|
uint8_t *regs = sm83::getRegs();
|
||||||
@@ -1026,7 +1055,7 @@ namespace debug
|
|||||||
void setcursor(const uint16_t address)
|
void setcursor(const uint16_t address)
|
||||||
{
|
{
|
||||||
//if (!debugging()) return;
|
//if (!debugging()) return;
|
||||||
if ( !(mem::getTag(address) & MEMTAG_INST) )
|
if ( !(tags[address] & MEMTAG_INST) )
|
||||||
cursor = find_previous_opcode(address);
|
cursor = find_previous_opcode(address);
|
||||||
else
|
else
|
||||||
cursor = address;
|
cursor = address;
|
||||||
@@ -3,6 +3,26 @@
|
|||||||
|
|
||||||
namespace debug
|
namespace debug
|
||||||
{
|
{
|
||||||
|
#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
|
||||||
|
|
||||||
|
uint8_t getTag(uint16_t address);
|
||||||
|
void setTag(uint16_t address, uint8_t value);
|
||||||
|
|
||||||
|
void onInstructionExecute(uint16_t address);
|
||||||
|
void onMemRead(uint16_t address, bool code=false);
|
||||||
|
void onMemWrite(uint16_t address);
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void show();
|
void show();
|
||||||
void focus();
|
void focus();
|
||||||
@@ -13,7 +33,6 @@ namespace debug
|
|||||||
void cont();
|
void cont();
|
||||||
const bool debugging();
|
const bool debugging();
|
||||||
const bool paused();
|
const bool paused();
|
||||||
void setmemmodified(const uint16_t addr);
|
|
||||||
|
|
||||||
void refresh();
|
void refresh();
|
||||||
void sendToConsole(const char* text);
|
void sendToConsole(const char* text);
|
||||||
@@ -29,8 +48,6 @@ namespace debug
|
|||||||
void savestate(const char *filename);
|
void savestate(const char *filename);
|
||||||
void loadstate(const char *filename);
|
void loadstate(const char *filename);
|
||||||
|
|
||||||
void loadngo(const char* filename, const char* addr);
|
|
||||||
|
|
||||||
void setcursor(const uint16_t address);
|
void setcursor(const uint16_t address);
|
||||||
void cursorfwd();
|
void cursorfwd();
|
||||||
void cursorback();
|
void cursorback();
|
||||||
@@ -53,10 +53,6 @@ namespace display
|
|||||||
display::incZoom();
|
display::incZoom();
|
||||||
} else if (e->key.keysym.scancode==SDL_SCANCODE_F3) {
|
} else if (e->key.keysym.scancode==SDL_SCANCODE_F3) {
|
||||||
display::toggleFullscreen();
|
display::toggleFullscreen();
|
||||||
} else if (e->key.keysym.scancode==SDL_SCANCODE_F6) {
|
|
||||||
//zx_tape::play();
|
|
||||||
} else if (e->key.keysym.scancode==SDL_SCANCODE_F7) {
|
|
||||||
//zx_tape::rewind();
|
|
||||||
} else if (e->key.keysym.scancode==SDL_SCANCODE_Q && e->key.keysym.mod & KMOD_CTRL) {
|
} else if (e->key.keysym.scancode==SDL_SCANCODE_Q && e->key.keysym.mod & KMOD_CTRL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -69,7 +65,7 @@ namespace display
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reinit()
|
void init()
|
||||||
{
|
{
|
||||||
if (win) ui::window::unregisterWindow(SDL_GetWindowID(win));
|
if (win) ui::window::unregisterWindow(SDL_GetWindowID(win));
|
||||||
|
|
||||||
@@ -106,11 +102,6 @@ namespace display
|
|||||||
focus();
|
focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void init()
|
|
||||||
{
|
|
||||||
reinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void focus()
|
void focus()
|
||||||
{
|
{
|
||||||
if (win)
|
if (win)
|
||||||
@@ -188,7 +179,7 @@ namespace display
|
|||||||
if (144*value > dm.h) return;
|
if (144*value > dm.h) return;
|
||||||
|
|
||||||
zoom = value;
|
zoom = value;
|
||||||
reinit();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void incZoom()
|
void incZoom()
|
||||||
@@ -206,7 +197,7 @@ namespace display
|
|||||||
void toggleFullscreen()
|
void toggleFullscreen()
|
||||||
{
|
{
|
||||||
fullscreen = !fullscreen;
|
fullscreen = !fullscreen;
|
||||||
reinit();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool getFullscreen()
|
const bool getFullscreen()
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
namespace display
|
namespace display
|
||||||
{
|
{
|
||||||
void init();
|
void init();
|
||||||
void reinit();
|
|
||||||
void focus();
|
void focus();
|
||||||
void redraw(const bool present=true);
|
void redraw(const bool present=true);
|
||||||
void present();
|
void present();
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#include "gameboy.h"
|
||||||
|
|
||||||
|
gameboy::gameboy(const std::string &rom_file)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gameboy::~gameboy()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void gameboy::step()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class gameboy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
gameboy(const std::string &rom_file);
|
||||||
|
~gameboy();
|
||||||
|
|
||||||
|
void step();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace gb
|
||||||
|
{
|
||||||
|
namespace interrupts
|
||||||
|
{
|
||||||
|
constexpr uint8_t VBLANK = 0x01;
|
||||||
|
constexpr uint8_t LCD = 0x02;
|
||||||
|
constexpr uint8_t TIMER = 0x04;
|
||||||
|
constexpr uint8_t SERIAL = 0x08;
|
||||||
|
constexpr uint8_t JOYPAD = 0x10;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define io_interrupts_address 0xff0f
|
||||||
+30
-19
@@ -52,13 +52,17 @@ namespace actions
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
// Control de paràmetres
|
||||||
if (argc < 2) { printf("ABORTING: No rom specified.\n"); exit(1); }
|
if (argc < 2) { printf("ABORTING: No rom specified.\n"); exit(1); }
|
||||||
|
|
||||||
|
// Velocitat de rellotge
|
||||||
const uint32_t clock = 4194304;
|
const uint32_t clock = 4194304;
|
||||||
const uint32_t update_freq = clock >> 3;
|
const uint32_t update_freq = clock >> 3;
|
||||||
|
|
||||||
|
// Inicia SDL
|
||||||
SDL_Init(SDL_INIT_EVERYTHING);
|
SDL_Init(SDL_INIT_EVERYTHING);
|
||||||
|
|
||||||
|
// Carrega la rom
|
||||||
FILE *f = fopen(argv[1], "rb");
|
FILE *f = fopen(argv[1], "rb");
|
||||||
if (!f) { printf("ABORTING: Rom not found.\n"); exit(1); }
|
if (!f) { printf("ABORTING: Rom not found.\n"); exit(1); }
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
@@ -68,8 +72,10 @@ int main(int argc, char *argv[])
|
|||||||
fread(buffer, filesize, 1, f);
|
fread(buffer, filesize, 1, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
// i mem inicialitza el mbc
|
||||||
mem::init(buffer, filesize);
|
mem::init(buffer, filesize);
|
||||||
|
|
||||||
|
// Iniciem tots els sistemes
|
||||||
sm83dis::loadSymbols();
|
sm83dis::loadSymbols();
|
||||||
sm83::reset();
|
sm83::reset();
|
||||||
|
|
||||||
@@ -77,6 +83,7 @@ int main(int argc, char *argv[])
|
|||||||
display::init();
|
display::init();
|
||||||
debug::init();
|
debug::init();
|
||||||
|
|
||||||
|
// Iniciem el menú princpal (ací? perqué? No es de display.h?)
|
||||||
ui::menu::init();
|
ui::menu::init();
|
||||||
ui::menu::setexitcallback(actions::exitMenu);
|
ui::menu::setexitcallback(actions::exitMenu);
|
||||||
|
|
||||||
@@ -96,18 +103,15 @@ int main(int argc, char *argv[])
|
|||||||
ui::menu::addbooloption(menu, "STOP ON INVALID OP", sm83::getOption(SM83_OPTION_STOP_ON_INVALID), actions::decZoom);
|
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);
|
ui::menu::addoption(menu, "SHOW ANALYZER", actions::showAnalyzer);
|
||||||
|
|
||||||
//zx_ula::sound_init();
|
|
||||||
|
|
||||||
//debug::stop();
|
|
||||||
|
|
||||||
bool should_exit = false;
|
bool should_exit = false;
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
|
|
||||||
time = SDL_GetTicks();
|
time = SDL_GetTicks();
|
||||||
t_states = 0;
|
t_states = 0;
|
||||||
|
uint8_t wait = 125;
|
||||||
while (!should_exit)
|
while (!should_exit)
|
||||||
{
|
{
|
||||||
|
if (wait==0) {
|
||||||
while (SDL_PollEvent(&e))
|
while (SDL_PollEvent(&e))
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
@@ -172,12 +176,11 @@ int main(int argc, char *argv[])
|
|||||||
if (!result)
|
if (!result)
|
||||||
should_exit = true; break;
|
should_exit = true; break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!debug::debugging() && !debug::paused()) {
|
if (!debug::debugging() && !debug::paused()) {
|
||||||
bool fastload=false;
|
// En cada pas de bucle fem 10 pasos de la CPU, sino s'ofega
|
||||||
|
//for (int i=0;i<20;++i) {
|
||||||
// En cada bucle fem 10 pasos de la CPU, sino s'ofega
|
|
||||||
for (int i=0;i<20;++i) {
|
|
||||||
if (debug::isbreak(sm83::getPC(), 9)) {
|
if (debug::isbreak(sm83::getPC(), 9)) {
|
||||||
debug::stop();
|
debug::stop();
|
||||||
display::redraw();
|
display::redraw();
|
||||||
@@ -185,20 +188,23 @@ int main(int argc, char *argv[])
|
|||||||
} else {
|
} else {
|
||||||
uint8_t dt = sm83::step();
|
uint8_t dt = sm83::step();
|
||||||
t_states += dt;
|
t_states += dt;
|
||||||
//zx_ula::sound_update(dt);
|
|
||||||
ppu::refresh(dt);
|
ppu::refresh(dt);
|
||||||
if (debug::debugging()) break;
|
if (debug::debugging()) break;
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (t_states>=update_freq)
|
// Sincronització:
|
||||||
{
|
// la frequència del rellotge diu quants t_states pot executar per segon.
|
||||||
while (SDL_GetTicks()<(time+125)) {}
|
// update_freq es la freq del rellotge / 8. Per tant, el nombre de t_states que
|
||||||
t_states -= update_freq;
|
// pot executar cada 125 ms. Ací comprobem si ja havem executat eixe nombre
|
||||||
time = SDL_GetTicks();
|
// de t_states i, si ho havem fet, esperem fins que passen 125ms des de l'ultima
|
||||||
//z80analyze::refresh();
|
// vegada que ho comprobarem.
|
||||||
}
|
//if (t_states>=update_freq)
|
||||||
//z80analyze::refresh(true);
|
//{
|
||||||
|
// while (SDL_GetTicks()<(time+125)) {}
|
||||||
|
// t_states -= update_freq;
|
||||||
|
// time = SDL_GetTicks();
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
} else if (!debug::debugging() && debug::paused()) {
|
} else if (!debug::debugging() && debug::paused()) {
|
||||||
@@ -206,7 +212,12 @@ int main(int argc, char *argv[])
|
|||||||
ui::menu::show();
|
ui::menu::show();
|
||||||
display::present();
|
display::present();
|
||||||
}
|
}
|
||||||
|
if (wait == 0) {
|
||||||
ui::setClicked(false);
|
ui::setClicked(false);
|
||||||
|
wait = 125;
|
||||||
|
} else {
|
||||||
|
wait--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include "apu.h"
|
#include "apu.h"
|
||||||
|
#include "io_constants.h"
|
||||||
#include "mbc_none.h"
|
#include "mbc_none.h"
|
||||||
#include "mbc1.h"
|
#include "mbc1.h"
|
||||||
#include "mbc3.h"
|
#include "mbc3.h"
|
||||||
@@ -28,8 +28,6 @@ namespace mem
|
|||||||
uint8_t wram[8192];
|
uint8_t wram[8192];
|
||||||
uint8_t hram[512];
|
uint8_t hram[512];
|
||||||
|
|
||||||
uint8_t tags[65536];
|
|
||||||
|
|
||||||
char *title = nullptr;
|
char *title = nullptr;
|
||||||
uint8_t mapper_type = 0;
|
uint8_t mapper_type = 0;
|
||||||
uint32_t rom_size = 0;
|
uint32_t rom_size = 0;
|
||||||
@@ -102,7 +100,6 @@ namespace mem
|
|||||||
for (int i=0; i<8192; ++i) { vram[i] = 0; }
|
for (int i=0; i<8192; ++i) { vram[i] = 0; }
|
||||||
for (int i=0; i<8192; ++i) { wram[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<512; ++i) { hram[i] = 0; }
|
||||||
for (int i=0; i<65536; ++i) { tags[i] = MEMTAG_NONE; }
|
|
||||||
|
|
||||||
resetMbc();
|
resetMbc();
|
||||||
apu::reset();
|
apu::reset();
|
||||||
@@ -183,14 +180,9 @@ namespace mem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getTag(uint16_t address)
|
void requestInterrupt(uint8_t type)
|
||||||
{
|
{
|
||||||
return tags[address];
|
mem::writeMem(io_interrupts_address, mem::readMem(io_interrupts_address) | type);
|
||||||
}
|
|
||||||
|
|
||||||
void setTag(uint16_t address, uint8_t value)
|
|
||||||
{
|
|
||||||
tags[address] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveState(FILE* f)
|
void saveState(FILE* f)
|
||||||
@@ -248,7 +240,7 @@ namespace mem
|
|||||||
TIMA++;
|
TIMA++;
|
||||||
else {
|
else {
|
||||||
TIMA = TMA;
|
TIMA = TMA;
|
||||||
sm83::interrupt(INTERRUPT_TIMER);
|
mem::requestInterrupt(gb::interrupts::TIMER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+1
-16
@@ -3,19 +3,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
namespace mem
|
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 MBC_NONE 0
|
||||||
#define MBC1 1
|
#define MBC1 1
|
||||||
#define MBC2 2
|
#define MBC2 2
|
||||||
@@ -29,9 +16,7 @@ namespace mem
|
|||||||
|
|
||||||
uint8_t readMem(uint16_t address);
|
uint8_t readMem(uint16_t address);
|
||||||
void writeMem(uint16_t address, uint8_t value);
|
void writeMem(uint16_t address, uint8_t value);
|
||||||
|
void requestInterrupt(uint8_t type);
|
||||||
uint8_t getTag(uint16_t address);
|
|
||||||
void setTag(uint16_t address, uint8_t value);
|
|
||||||
|
|
||||||
void saveState(FILE* f);
|
void saveState(FILE* f);
|
||||||
void loadState(FILE* f);
|
void loadState(FILE* f);
|
||||||
@@ -45,7 +45,6 @@ namespace ppu
|
|||||||
#define WY (*_WY)
|
#define WY (*_WY)
|
||||||
#define WX (*_WX)
|
#define WX (*_WX)
|
||||||
|
|
||||||
#define IF 0xff0f
|
|
||||||
bool last_interrupt_lcd_state = false;
|
bool last_interrupt_lcd_state = false;
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
@@ -212,7 +211,6 @@ namespace ppu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// gestió de en quin dot i linea estem, i tot el que ha de passar
|
// gestió de en quin dot i linea estem, i tot el que ha de passar
|
||||||
//uint8_t interrupts = 0x00;
|
|
||||||
bool current_interrupt_lcd_state = false;
|
bool current_interrupt_lcd_state = false;
|
||||||
dots_in_scanline++;
|
dots_in_scanline++;
|
||||||
if ( (dots_in_scanline==80) && (LY<144) )
|
if ( (dots_in_scanline==80) && (LY<144) )
|
||||||
@@ -222,7 +220,7 @@ namespace ppu
|
|||||||
else if ( (dots_in_scanline==252) && (LY<144) )
|
else if ( (dots_in_scanline==252) && (LY<144) )
|
||||||
{
|
{
|
||||||
STAT = (STAT & 0xFC); // Set mode 0
|
STAT = (STAT & 0xFC); // Set mode 0
|
||||||
if (STAT&0x08) current_interrupt_lcd_state = true; // interrupts |= INTERRUPT_LCD;
|
if (STAT&0x08) current_interrupt_lcd_state = true;
|
||||||
}
|
}
|
||||||
else if (dots_in_scanline==456)
|
else if (dots_in_scanline==456)
|
||||||
{
|
{
|
||||||
@@ -232,17 +230,16 @@ namespace ppu
|
|||||||
if (LY==144)
|
if (LY==144)
|
||||||
{
|
{
|
||||||
// Set vblank interrupt
|
// Set vblank interrupt
|
||||||
mem::writeMem(IF, mem::readMem(IF) | INTERRUPT_VBLANK);
|
mem::requestInterrupt(gb::interrupts::VBLANK);
|
||||||
STAT = (STAT & 0xFC) | 0x01; // Set mode 1
|
STAT = (STAT & 0xFC) | 0x01; // Set mode 1
|
||||||
//interrupts |= INTERRUPT_VBLANK;
|
if (STAT&0x10) current_interrupt_lcd_state = true;
|
||||||
if (STAT&0x10) current_interrupt_lcd_state = true; //interrupts |= INTERRUPT_LCD;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (LY<144)
|
if (LY<144)
|
||||||
{
|
{
|
||||||
STAT = (STAT & 0xFC) | 0x02; // Set mode 2
|
STAT = (STAT & 0xFC) | 0x02; // Set mode 2
|
||||||
if (STAT&0x20) current_interrupt_lcd_state = true; // interrupts |= INTERRUPT_LCD;
|
if (STAT&0x20) current_interrupt_lcd_state = true;
|
||||||
fill_line_buffer_bkg();
|
fill_line_buffer_bkg();
|
||||||
fill_line_buffer_win();
|
fill_line_buffer_win();
|
||||||
fill_line_buffer_obj();
|
fill_line_buffer_obj();
|
||||||
@@ -251,7 +248,7 @@ namespace ppu
|
|||||||
if (LY==LYC)
|
if (LY==LYC)
|
||||||
{
|
{
|
||||||
STAT = (STAT & 0xFB) | 0x04;
|
STAT = (STAT & 0xFB) | 0x04;
|
||||||
if (STAT&0x40) current_interrupt_lcd_state = true; // interrupts |= INTERRUPT_LCD;
|
if (STAT&0x40) current_interrupt_lcd_state = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -261,8 +258,7 @@ namespace ppu
|
|||||||
|
|
||||||
if (!last_interrupt_lcd_state && current_interrupt_lcd_state)
|
if (!last_interrupt_lcd_state && current_interrupt_lcd_state)
|
||||||
{
|
{
|
||||||
mem::writeMem(IF, mem::readMem(IF) | INTERRUPT_LCD);
|
mem::requestInterrupt(gb::interrupts::LCD);
|
||||||
//sm83::interrupt(interrupts);
|
|
||||||
}
|
}
|
||||||
last_interrupt_lcd_state = current_interrupt_lcd_state;
|
last_interrupt_lcd_state = current_interrupt_lcd_state;
|
||||||
|
|
||||||
+17
-108
@@ -46,10 +46,6 @@ namespace sm83
|
|||||||
|
|
||||||
uint8_t *_rIME = ®s[12];
|
uint8_t *_rIME = ®s[12];
|
||||||
|
|
||||||
bool halted = false;
|
|
||||||
bool exit_from_halt = false;
|
|
||||||
int pending_ei = 0;
|
|
||||||
|
|
||||||
#define rA (*_rA)
|
#define rA (*_rA)
|
||||||
#define rF (*_rF)
|
#define rF (*_rF)
|
||||||
#define rB (*_rB)
|
#define rB (*_rB)
|
||||||
@@ -71,41 +67,26 @@ namespace sm83
|
|||||||
|
|
||||||
#define EX(a,b) {auto temp=a;a=b;b=temp;}
|
#define EX(a,b) {auto temp=a;a=b;b=temp;}
|
||||||
|
|
||||||
bool reading_m1 = false;
|
bool halted = false;
|
||||||
|
bool exit_from_halt = false;
|
||||||
|
int pending_ei = 0;
|
||||||
|
|
||||||
uint8_t READ_MEM_8(const uint16_t addr, const bool code=false)
|
uint8_t READ_MEM_8(const uint16_t addr, const bool code=false)
|
||||||
{
|
{
|
||||||
if (debug::isbreak(addr, 2)) debug::stop();
|
|
||||||
t+=4;
|
t+=4;
|
||||||
|
debug::onMemRead(addr, code);
|
||||||
const uint8_t tag = mem::getTag(addr);
|
|
||||||
if ( !(tag&MEMTAG_IGNORE) ) {
|
|
||||||
if (!code) {
|
|
||||||
if ( tag & MEMTAG_INST ) {
|
|
||||||
} else {
|
|
||||||
mem::setTag(addr, tag | MEMTAG_DATA);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ( (reading_m1) && ( tag & MEMTAG_DATA ) ) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reading_m1 = false;
|
|
||||||
return mem::readMem(addr);
|
return mem::readMem(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t READ_MEM_8()
|
uint8_t READ_MEM_8()
|
||||||
{
|
{
|
||||||
const uint8_t data = READ_MEM_8(rPC, true);
|
const uint8_t data = READ_MEM_8(rPC, true);
|
||||||
const uint8_t tag = mem::getTag(rPC);
|
|
||||||
if ( !(tag & MEMTAG_IGNORE) ) mem::setTag(rPC, tag | MEMTAG_CODE);
|
|
||||||
rPC++;
|
rPC++;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t READ_M1()
|
uint8_t READ_M1()
|
||||||
{
|
{
|
||||||
reading_m1 = true;
|
|
||||||
return READ_MEM_8();
|
return READ_MEM_8();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,19 +106,7 @@ namespace sm83
|
|||||||
{
|
{
|
||||||
t+=4;
|
t+=4;
|
||||||
mem::writeMem(addr, value);
|
mem::writeMem(addr, value);
|
||||||
|
debug::onMemWrite(addr);
|
||||||
if (debug::isbreak(addr, 4)) debug::stop();
|
|
||||||
debug::setmemmodified(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 {
|
|
||||||
mem::setTag(addr, tag | MEMTAG_DATA | MEMTAG_TDATA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,19 +471,6 @@ namespace sm83
|
|||||||
{
|
{
|
||||||
POP(_rPC);
|
POP(_rPC);
|
||||||
if (cond != cUnconditional) t += 4;
|
if (cond != cUnconditional) t += 4;
|
||||||
|
|
||||||
/*if (options[Z80_OPTION_BREAK_ON_RET]) {
|
|
||||||
if (calls_stacked>0) {
|
|
||||||
calls_stacked--;
|
|
||||||
printf("RET: calls still stacked: %i\n", calls_stacked);
|
|
||||||
} else {
|
|
||||||
printf("RET: BREAK\n");
|
|
||||||
options[Z80_OPTION_BREAK_ON_RET] = false;
|
|
||||||
z80debug::setcursor(rPC);
|
|
||||||
z80debug::history::store();
|
|
||||||
z80debug::stop();
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,28 +490,22 @@ namespace sm83
|
|||||||
DI();
|
DI();
|
||||||
PUSH(rPC);
|
PUSH(rPC);
|
||||||
//t+=20;
|
//t+=20;
|
||||||
if (*IF & INTERRUPT_VBLANK) {
|
if (*IF & gb::interrupts::VBLANK) {
|
||||||
rPC = 0x40;
|
rPC = 0x40;
|
||||||
*IF = *IF & ~INTERRUPT_VBLANK;
|
*IF = *IF & ~gb::interrupts::VBLANK;
|
||||||
} else if (*IF & INTERRUPT_LCD) {
|
} else if (*IF & gb::interrupts::LCD) {
|
||||||
rPC = 0x48;
|
rPC = 0x48;
|
||||||
*IF = *IF & ~INTERRUPT_LCD;
|
*IF = *IF & ~gb::interrupts::LCD;
|
||||||
} else if (*IF & INTERRUPT_TIMER) {
|
} else if (*IF & gb::interrupts::TIMER) {
|
||||||
rPC = 0x50;
|
rPC = 0x50;
|
||||||
*IF = *IF & ~INTERRUPT_TIMER;
|
*IF = *IF & ~gb::interrupts::TIMER;
|
||||||
} else if (*IF & INTERRUPT_SERIAL) {
|
} else if (*IF & gb::interrupts::SERIAL) {
|
||||||
rPC = 0x58;
|
rPC = 0x58;
|
||||||
*IF = *IF & ~INTERRUPT_SERIAL;
|
*IF = *IF & ~gb::interrupts::SERIAL;
|
||||||
} else if (*IF & INTERRUPT_JOYPAD) {
|
} else if (*IF & gb::interrupts::JOYPAD) {
|
||||||
rPC = 0x60;
|
rPC = 0x60;
|
||||||
*IF = *IF & ~INTERRUPT_JOYPAD;
|
*IF = *IF & ~gb::interrupts::JOYPAD;
|
||||||
}
|
}
|
||||||
/*if (options[Z80_OPTION_BREAK_ON_INTERRUPT]) {
|
|
||||||
printf("Break on interrupt! 0x%2x, PC: 0x%2x\n", address, rPC);
|
|
||||||
z80debug::setcursor(rPC);
|
|
||||||
z80debug::history::store();
|
|
||||||
z80debug::stop();
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RETI()
|
void RETI()
|
||||||
@@ -602,13 +552,7 @@ namespace sm83
|
|||||||
halted = true;
|
halted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*if (exit_from_halt) {
|
|
||||||
exit_from_halt = false;
|
|
||||||
halted = false;
|
|
||||||
} else {*/
|
|
||||||
//printf("HALT\n");
|
|
||||||
rPC--;
|
rPC--;
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void STOP()
|
void STOP()
|
||||||
@@ -616,15 +560,6 @@ namespace sm83
|
|||||||
HALT();
|
HALT();
|
||||||
}
|
}
|
||||||
|
|
||||||
void interrupt(uint8_t type)
|
|
||||||
{
|
|
||||||
const uint8_t IE = mem::readMem(0xffff);
|
|
||||||
//if (IE & type) exit_from_halt = true;
|
|
||||||
const uint8_t IF = mem::readMem(0xff0f);
|
|
||||||
mem::writeMem(0xff0f, IF | type);
|
|
||||||
//processInterrupts();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline const uint8_t RLC(const uint8_t v)
|
static inline const uint8_t RLC(const uint8_t v)
|
||||||
{
|
{
|
||||||
const uint8_t res = (v>>7) | (v<<1);
|
const uint8_t res = (v>>7) | (v<<1);
|
||||||
@@ -739,21 +674,9 @@ namespace sm83
|
|||||||
rHL--;
|
rHL--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void INVALID(uint8_t opcode)
|
|
||||||
{
|
|
||||||
printf("INVALID OPCODE AT: %04x\n", current_opcode_address);
|
|
||||||
//if (options[Z80_OPTION_STOP_ON_INVALID]) z80debug::stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool opcode_ignored = false;
|
|
||||||
void IgnoreOpcode()
|
void IgnoreOpcode()
|
||||||
{
|
{
|
||||||
debug::setcursor(rPC);
|
|
||||||
debug::history::store();
|
|
||||||
debug::stop();
|
debug::stop();
|
||||||
/*t-=3;
|
|
||||||
rPC--;
|
|
||||||
opcode_ignored=true;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
@@ -779,21 +702,11 @@ namespace sm83
|
|||||||
|
|
||||||
uint32_t step()
|
uint32_t step()
|
||||||
{
|
{
|
||||||
do {
|
|
||||||
opcode_ignored = false;
|
|
||||||
current_opcode_address = rPC;
|
current_opcode_address = rPC;
|
||||||
t = 0;
|
t = 0;
|
||||||
const uint8_t opcode = READ_M1();
|
const uint8_t opcode = READ_M1();
|
||||||
|
|
||||||
uint8_t tag = mem::getTag(current_opcode_address);
|
|
||||||
if ( !(tag & MEMTAG_IGNORE) )
|
|
||||||
tag = tag | MEMTAG_INST;
|
|
||||||
mem::setTag(current_opcode_address, tag | (!(tag&MEMTAG_TOUCHED) ? MEMTAG_TREPEAT : MEMTAG_TINST) );
|
|
||||||
|
|
||||||
uint16_t tmp;
|
uint16_t tmp;
|
||||||
|
|
||||||
//if (opcode!=0xED && opcode!=0xCB && opcode!=0xDD && opcode!=0xFD ) z80debug::useOpcode(opcode, 0);
|
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case 0x00: /* NOP */ break;
|
case 0x00: /* NOP */ break;
|
||||||
@@ -1069,14 +982,12 @@ namespace sm83
|
|||||||
case 0xFF: RST(0x38); break;
|
case 0xFF: RST(0x38); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (opcode_ignored);
|
|
||||||
|
|
||||||
if (pending_ei==2) { pending_ei=0; actualEI(); }
|
if (pending_ei==2) { pending_ei=0; actualEI(); }
|
||||||
if (pending_ei==1) pending_ei=2;
|
if (pending_ei==1) pending_ei=2;
|
||||||
|
|
||||||
debug::setcursor(rPC);
|
debug::onInstructionExecute(current_opcode_address);
|
||||||
debug::history::store();
|
|
||||||
mem::update_mapped(t);
|
mem::update_mapped(t);
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1084,8 +995,6 @@ namespace sm83
|
|||||||
{
|
{
|
||||||
const uint8_t opcode = READ_M1();
|
const uint8_t opcode = READ_M1();
|
||||||
|
|
||||||
//z80debug::useOpcode(opcode, 2);
|
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case 0x00: rB = RLC(rB); break;
|
case 0x00: rB = RLC(rB); break;
|
||||||
@@ -16,7 +16,6 @@ namespace sm83
|
|||||||
uint32_t getClock();
|
uint32_t getClock();
|
||||||
|
|
||||||
void processInterrupts();
|
void processInterrupts();
|
||||||
void interrupt(uint8_t type);
|
|
||||||
|
|
||||||
uint32_t step();
|
uint32_t step();
|
||||||
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "sm83dis.h"
|
#include "sm83dis.h"
|
||||||
#include "sm83.h"
|
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
Reference in New Issue
Block a user