- [CHG] mode berserk passa a per Fast Tape. sistema de Opcions.

- [NEW] Opció per a parar execució al acabar de carregar una cinta.
- [NEW] Opció per a parar l'execució al trobar una instrucció del Z80 no vàlida
- [NEW] Savestate del Fernando Martin, per a provar més ràpid.
- [NEW] Treballant en el sistema d'anàlisi visual del codi
This commit is contained in:
2024-12-08 22:57:03 +01:00
parent edf8728b04
commit 8fd2eecb85
9 changed files with 129 additions and 17 deletions

BIN
fer.sav Normal file

Binary file not shown.

View File

@@ -10,6 +10,7 @@
#include <string.h> #include <string.h>
#include "ui.h" #include "ui.h"
#include "ui_menu.h" #include "ui_menu.h"
#include "z80analyze.h"
uint8_t memory[65536]; uint8_t memory[65536];
uint32_t time = 0; uint32_t time = 0;
@@ -24,10 +25,16 @@ namespace actions
zxscreen::refresh(dt); zxscreen::refresh(dt);
} }
int berserk(int value) int fastload(int value)
{ {
zx_tape::setberserk(!zx_tape::getberserk()); zx_tape::toggleOption(ZXTAPE_OPTION_FAST_LOAD);
return zx_tape::getberserk(); return zx_tape::getOption(ZXTAPE_OPTION_FAST_LOAD);
}
int stopatend(int value)
{
zx_tape::toggleOption(ZXTAPE_OPTION_STOP_AT_END);
return zx_tape::getOption(ZXTAPE_OPTION_STOP_AT_END);
} }
int decZoom(int value) int decZoom(int value)
@@ -47,6 +54,12 @@ namespace actions
zxscreen::toggleFullscreen(); zxscreen::toggleFullscreen();
return zxscreen::getFullscreen(); return zxscreen::getFullscreen();
} }
int showAnalyzer(int value)
{
z80analyze::show();
return 0;
}
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@@ -73,13 +86,18 @@ int main(int argc, char *argv[])
ui::menu::addoption(menu, "SAVE STATE", nullptr); ui::menu::addoption(menu, "SAVE STATE", nullptr);
menu = ui::menu::addsubmenu("TAPE"); menu = ui::menu::addsubmenu("TAPE");
ui::menu::addbooloption(menu, "BERSERK MODE", zx_tape::getberserk(), actions::berserk); ui::menu::addbooloption(menu, "BERSERK MODE", zx_tape::getOption(ZXTAPE_OPTION_FAST_LOAD), actions::fastload);
ui::menu::addbooloption(menu, "STOP AT END", zx_tape::getOption(ZXTAPE_OPTION_STOP_AT_END), actions::stopatend);
menu = ui::menu::addsubmenu("SCREEN"); menu = ui::menu::addsubmenu("SCREEN");
ui::menu::addoption(menu, "DEC ZOOM", actions::decZoom); ui::menu::addoption(menu, "DEC ZOOM", actions::decZoom);
ui::menu::addoption(menu, "INC ZOOM", actions::incZoom); ui::menu::addoption(menu, "INC ZOOM", actions::incZoom);
ui::menu::addbooloption(menu, "FULLSCREEN", zxscreen::getFullscreen(), actions::fullscreen); ui::menu::addbooloption(menu, "FULLSCREEN", zxscreen::getFullscreen(), actions::fullscreen);
menu = ui::menu::addsubmenu("EMULATION");
ui::menu::addbooloption(menu, "STOP ON INVALID OP", z80::getOption(Z80_OPTION_STOP_ON_INVALID), actions::decZoom);
ui::menu::addoption(menu, "SHOW ANALYZER", actions::showAnalyzer);
zx_ula::sound_init(); zx_ula::sound_init();
zx_tape::load("fernandomartin.tap"); zx_tape::load("fernandomartin.tap");
@@ -206,9 +224,9 @@ int main(int argc, char *argv[])
zxscreen::redraw(); zxscreen::redraw();
} else { } else {
//if (z80::getPC()==0x05C8) zx_tape::go_berserk(); //if (z80::getPC()==0x05C8) zx_tape::go_berserk();
bool berserk=false; bool fastload=false;
if (zx_tape::getplaying() && zx_tape::getberserk()) { berserk=true; time = SDL_GetTicks(); } if (zx_tape::getplaying() && zx_tape::getOption(ZXTAPE_OPTION_FAST_LOAD)) { fastload=true; time = SDL_GetTicks(); }
while (zx_tape::getplaying() && zx_tape::getberserk()) while (zx_tape::getplaying() && zx_tape::getOption(ZXTAPE_OPTION_FAST_LOAD))
{ {
// zx_tape::update(z80::step()); // zx_tape::update(z80::step());
uint8_t dt = z80::step(); uint8_t dt = z80::step();
@@ -221,7 +239,7 @@ int main(int argc, char *argv[])
//zx_ula::sound_update(dt); //zx_ula::sound_update(dt);
//zxscreen::refresh(dt); //zxscreen::refresh(dt);
} }
if (berserk) { printf("%i\n", SDL_GetTicks()-time); t_states=0; } if (fastload) { printf("%i\n", SDL_GetTicks()-time); t_states=0; }
// En cada bucle fem 10 pasos de la CPU, sino s'ofega // En cada bucle fem 10 pasos de la CPU, sino s'ofega
for (int i=0;i<5;++i) { for (int i=0;i<5;++i) {
uint8_t dt = z80::step(); uint8_t dt = z80::step();

19
z80.cpp
View File

@@ -9,6 +9,7 @@ namespace z80
static uint8_t memtag[65536]; static uint8_t memtag[65536];
static uint32_t t = 0; static uint32_t t = 0;
static uint16_t current_opcode_address = 0; static uint16_t current_opcode_address = 0;
bool options[Z80_NUM_OPTIONS] = { true };
int (*in_ports[256])(int); int (*in_ports[256])(int);
void (*out_ports[256])(int, int); void (*out_ports[256])(int, int);
@@ -1032,9 +1033,8 @@ namespace z80
void INVALID(uint8_t opcode) void INVALID(uint8_t opcode)
{ {
// [TODO]
printf("INVALID OPCODE AT: %04x\n", current_opcode_address); printf("INVALID OPCODE AT: %04x\n", current_opcode_address);
z80debug::stop(); if (options[Z80_OPTION_STOP_ON_INVALID]) z80debug::stop();
} }
void reset(uint8_t* mem) void reset(uint8_t* mem)
@@ -2738,4 +2738,19 @@ namespace z80
uint8_t getMemTag(const uint16_t addr) { return memtag[addr]; }; uint8_t getMemTag(const uint16_t addr) { return memtag[addr]; };
const bool getOption(const int option)
{
return options[option];
}
void setOption(const int option, const bool value)
{
options[option] = value;
}
void toggleOption(const int option)
{
options[option] = !options[option];
}
} }

7
z80.h
View File

@@ -9,6 +9,9 @@ namespace z80
#define MEMTAG_CODE 2 #define MEMTAG_CODE 2
#define MEMTAG_DATA 3 #define MEMTAG_DATA 3
#define Z80_OPTION_STOP_ON_INVALID 0
#define Z80_NUM_OPTIONS 1
void reset(uint8_t* mem); void reset(uint8_t* mem);
void connect_port(int num, int (*in_ptr)(int), void (*out_ptr)(int,int)); void connect_port(int num, int (*in_ptr)(int), void (*out_ptr)(int,int));
void interrupt(); void interrupt();
@@ -34,4 +37,8 @@ namespace z80
void setPC(const uint16_t addr); void setPC(const uint16_t addr);
uint8_t getMemTag(const uint16_t addr); uint8_t getMemTag(const uint16_t addr);
const bool getOption(const int option);
void setOption(const int option, const bool value);
void toggleOption(const int option);
} }

43
z80analyze.cpp Normal file
View File

@@ -0,0 +1,43 @@
#include "z80analyze.h"
#include "z80.h"
#include <SDL2/SDL.h>
namespace z80analyze
{
SDL_Window *win = nullptr;
SDL_Renderer *ren = nullptr;
SDL_Texture *tex = nullptr;
void show()
{
if (!win)
{
win = SDL_CreateWindow("Z80 Analyzer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 256, 256, SDL_WINDOW_SHOWN);
ren = SDL_CreateRenderer(win, -1, 0);
tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 256, 256);
}
refresh();
}
void refresh()
{
Uint32 *pixels;
int pitch;
SDL_LockTexture(tex, NULL, (void**)&pixels, &pitch);
for (int i=0; i<65536; ++i)
{
uint8_t tag = z80::getMemTag(i);
pixels[i] = tag==MEMTAG_NONE ? 0x808080 : tag==MEMTAG_DATA ? 0x0000FF : 0x00FF00;
}
SDL_UnlockTexture(tex);
SDL_RenderCopy(ren, tex, NULL, NULL);
SDL_RenderPresent(ren);
}
void hide()
{
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
}
}

8
z80analyze.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
namespace z80analyze
{
void show();
void refresh();
void hide();
}

View File

@@ -181,7 +181,7 @@ namespace zxscreen
void redraw(const bool present) void redraw(const bool present)
{ {
if (zx_tape::getplaying() && zx_tape::getberserk()) return; if (zx_tape::getplaying() && zx_tape::getOption(ZXTAPE_OPTION_FAST_LOAD)) return;
Uint32* pixels; Uint32* pixels;
int pitch; int pitch;

View File

@@ -1,6 +1,7 @@
#include "zx_tape.h" #include "zx_tape.h"
#include "zx_ula.h" #include "zx_ula.h"
#include "zx_screen.h" #include "zx_screen.h"
#include "z80debug.h"
#include <vector> #include <vector>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -34,7 +35,7 @@ namespace zx_tape
bool playing = false; bool playing = false;
bool loaded = false; bool loaded = false;
bool berserk_mode = true; bool options[ZXTAPE_NUM_OPTIONS] = { true, true };
std::vector<block_t> blocks; std::vector<block_t> blocks;
uint8_t current_block = 0; uint8_t current_block = 0;
@@ -80,7 +81,7 @@ namespace zx_tape
void stop() void stop()
{ {
playing = false; playing = false;
berserk_mode = false; //berserk_mode = false;
} }
void rewind() void rewind()
@@ -220,6 +221,7 @@ namespace zx_tape
printf("end\n"); printf("end\n");
stop(); stop();
rewind(); rewind();
if (options[ZXTAPE_OPTION_STOP_AT_END]) z80debug::stop();
} }
else else
{ {
@@ -232,8 +234,6 @@ namespace zx_tape
zx_ula::set_ear(pulse_level); zx_ula::set_ear(pulse_level);
} }
void setberserk(const bool value) { berserk_mode = value; }
const bool getberserk() { return berserk_mode; }
const bool getplaying() { return playing; } const bool getplaying() { return playing; }
void report() void report()
@@ -242,4 +242,19 @@ namespace zx_tape
const int percent = (float(block_pos)/float(blocks[current_block].length))*100; const int percent = (float(block_pos)/float(blocks[current_block].length))*100;
printf("tape loading: %i%\n", percent); printf("tape loading: %i%\n", percent);
} }
const bool getOption(const int option)
{
return options[option];
}
void setOption(const int option, const bool value)
{
options[option] = value;
}
void toggleOption(const int option)
{
options[option] = !options[option];
}
} }

View File

@@ -3,13 +3,19 @@
namespace zx_tape namespace zx_tape
{ {
#define ZXTAPE_OPTION_FAST_LOAD 0
#define ZXTAPE_OPTION_STOP_AT_END 1
#define ZXTAPE_NUM_OPTIONS 2
void load(const char* filename); void load(const char* filename);
void play(); void play();
void stop(); void stop();
void rewind(); void rewind();
void update(const uint8_t dt); void update(const uint8_t dt);
void setberserk(const bool value);
const bool getberserk();
const bool getplaying(); const bool getplaying();
void report(); void report();
const bool getOption(const int option);
void setOption(const int option, const bool value);
void toggleOption(const int option);
} }