From 1db0c52e1ad9fb9dbcf98c4036ef033b7511982f Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Wed, 30 Jul 2025 13:01:01 +0200 Subject: [PATCH] =?UTF-8?q?-=20Enorme=20reestructuraci=C3=B3=20del=20codi?= =?UTF-8?q?=20per=20a=20que=20el=20fluxe=20comence=20a=20ser=20mes=20racio?= =?UTF-8?q?nal=20-=20[NEW]=20m=C3=B2dul=20zx=5Fsystem=20per=20a=20gestiona?= =?UTF-8?q?r=20la=20vida=20i=20canvi=20de=20systemes=20(48K,=20128K...)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ay-3-8912.cpp | 5 ++- main.cpp | 118 +++++++++++++++++++++++++------------------------ z80.cpp | 21 +++++---- z80.h | 2 + z80debug.cpp | 11 +++-- zx_mem.cpp | 6 +-- zx_mem.h | 6 +-- zx_screen.cpp | 16 ++++--- zx_screen.h | 2 +- zx_speaker.cpp | 42 +++++++++++++----- zx_speaker.h | 5 ++- zx_system.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++ zx_system.h | 19 ++++++++ zx_tape.cpp | 2 +- zx_tape.h | 2 +- 15 files changed, 257 insertions(+), 101 deletions(-) create mode 100644 zx_system.cpp create mode 100644 zx_system.h diff --git a/ay-3-8912.cpp b/ay-3-8912.cpp index 3f8c50c..93f7300 100644 --- a/ay-3-8912.cpp +++ b/ay-3-8912.cpp @@ -19,8 +19,7 @@ namespace audio { - #define SAMPLING_FREQ 44100 - #define AUDIO_BUFFER_SIZE 2048 + bool enabled = false; float cycles_per_sample; uint8_t volume_table[16] {0,2,3,4,6,8,11,16,23,32,45,64,90,128,180,255}; @@ -122,12 +121,14 @@ namespace audio void reset() { + enabled = true; selected_register = 0; for (int i=0; i<16;++i) registers[i]=0; } void update(uint32_t dt) { + if (!enabled) return; //dt = dt >> 1; // Oscillate (0-1) channel A tone level given its frequency diff --git a/main.cpp b/main.cpp index 2a9896e..d755dbb 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,6 @@ #include #include +#include "zx_system.h" #include "z80.h" #include "z80dis.h" #include "z80debug.h" @@ -14,8 +15,6 @@ #include "z80analyze.h" #include "ui_window.h" #include "zx_mem.h" -//#include "zx_48mem.h" -//#include "zx_128mem.h" #include "z80viewer.h" //#include "zx_128bankviewer.h" //#include "zx_128pageviewer.h" @@ -23,7 +22,6 @@ #include "ay_viewer.h" #include "file.h" -//uint8_t memory[65536]; uint32_t time = 0; uint32_t t_states = 0; @@ -77,43 +75,34 @@ namespace actions z80analyze::show(); return 0; } + + int mode48K(int value) + { + zx_system::reset(ZX_48K); + return 0; + } + + int mode128K(int value) + { + zx_system::reset(ZX_128K); + return 0; + } + + int reset(int value) + { + z80::reset(); + return 0; + } + + int exit(int value) + { + zx_system::shutdown(); + return 0; + } } -int main(int argc, char *argv[]) +void init_menu() { - //const uint32_t clock = 3500000; - const uint32_t clock = 3546900; - const uint32_t update_freq = clock / 10; - - file::setConfigFolder("z80"); - - //new zx_48mem(); - //new zx_128mem(); - mem::init(ZX_128K); - - z80dis::loadSymbols(); - z80::setClock(clock); - z80::reset(); - z80::connect_port(0xfe, 0x0001, zx_ula::port_in, zx_ula::port_out); - audio::init(); - - SDL_Init(SDL_INIT_EVERYTHING); - z80debug::init(); - //zxscreen::init(SCREEN_MODE_48K); - zxscreen::init(SCREEN_MODE_128K); - - //ay_viewer *v = new ay_viewer(); - //v->show(); - //z80viewer::registerViewer("AY", v); - - //z80viewer *v = new zx_128bankviewer(); - //v->show(); - //z80viewer::registerViewer("128BANK", v); - - //v = new zx_128pageviewer(); - //v->show(); - //z80viewer::registerViewer("128PAGE", v); - ui::menu::init(); ui::menu::setexitcallback(actions::exitMenu); @@ -123,6 +112,14 @@ int main(int argc, char *argv[]) ui::menu::addseparator(menu); ui::menu::addoption(menu, "LOAD STATE", nullptr); ui::menu::addoption(menu, "SAVE STATE", nullptr); + ui::menu::addseparator(menu); + ui::menu::addoption(menu, "EXIT", actions::exit); + + menu = ui::menu::addsubmenu("SYSTEM"); + ui::menu::addoption(menu, "ZX 48K", actions::mode48K); + ui::menu::addoption(menu, "ZX 128K/+2", actions::mode128K); + ui::menu::addseparator(menu); + ui::menu::addoption(menu, "RESET", actions::reset); menu = ui::menu::addsubmenu("TAPE"); ui::menu::addbooloption(menu, "FAST LOAD", zx_tape::getOption(ZXTAPE_OPTION_FAST_LOAD), actions::fastload); @@ -138,30 +135,36 @@ int main(int argc, char *argv[]) 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); +} - speaker::init(); - speaker::register_source(zx_ula::get_sample); - speaker::register_source(audio::get_sample); +int main(int argc, char *argv[]) +{ + file::setConfigFolder("z80"); + SDL_Init(SDL_INIT_EVERYTHING); + init_menu(); + z80debug::init(); + + //uint32_t update_freq = + zx_system::init(ZX_48K); zx_tape::load("ROBOCOP1.TAP"); - if (argc==3) { z80debug::loadngo(argv[1], argv[2]); } + //if (argc==3) { z80debug::loadngo(argv[1], argv[2]); } - z80debug::stop(); + //z80debug::stop(); - bool should_exit = false; SDL_Event e; time = SDL_GetTicks(); t_states = 0; - while (!should_exit) + while (!zx_system::shuttingDown()) { while (SDL_PollEvent(&e)) { bool result = true; - if (e.type == SDL_QUIT) { should_exit=true; break; } + if (e.type == SDL_QUIT) { zx_system::shutdown(); 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); @@ -224,10 +227,11 @@ int main(int argc, char *argv[]) if (e.type == SDL_MOUSEBUTTONUP && e.button.button==1) ui::setClicked(true); if (!result) - should_exit = true; break; + zx_system::shutdown(); break; } if (!z80debug::debugging() && !z80debug::paused()) { +/* //if (z80::getPC()==0x05C8) zx_tape::go_berserk(); bool fastload=false; if (zx_tape::getplaying() && zx_tape::getOption(ZXTAPE_OPTION_FAST_LOAD)) { fastload=true; time = SDL_GetTicks(); } @@ -245,7 +249,9 @@ int main(int argc, char *argv[]) //zxscreen::refresh(dt); } 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 (jo en veig 5) for (int i=0;i<5;++i) { if (z80debug::isbreak(z80::getPC(), 9)) { z80debug::stop(); @@ -254,23 +260,21 @@ int main(int argc, char *argv[]) } else { uint8_t dt = z80::step(); t_states += dt; - zx_tape::update(dt); - audio::update(dt); - speaker::update(dt); + zx_system::update(dt); + //zx_tape::update(dt); + //audio::update(dt); + //speaker::update(dt); zxscreen::refresh(dt); if (z80debug::debugging()) break; } } + uint32_t update_freq = z80::getClock()/10; if (t_states>=update_freq) { - //if (SDL_GetTicks()>=time+1000) - //printf("%i\n", SDL_GetTicks()-(time+1000)); - //else - // printf("%i\n", SDL_GetTicks()-(time+1000)); - //t_states = 0; - //printf("%i: %i\n", SDL_GetTicks()-(time+1000), t_states); + // Esperem a que es compleixca el temps corresponent als t states executats while (SDL_GetTicks() #include +#include "zx_system.h" #define MEMTAG_NONE 0x00 #define MEMTAG_DATA 0x01 @@ -16,11 +17,6 @@ #define MEMTAG_KNOWN 0x07 #define MEMTAG_TOUCHED 0x70 -#define ZX_48K 0x00 -#define ZX_128K 0x01 -#define ZX_2A_3 0x02 -#define ZX_NEXT 0x03 - namespace mem { void init(uint8_t mode); diff --git a/zx_screen.cpp b/zx_screen.cpp index b436408..7f456c4 100644 --- a/zx_screen.cpp +++ b/zx_screen.cpp @@ -26,6 +26,7 @@ namespace zxscreen uint32_t t_states_total = 69888; uint32_t t_states_per_scanline = 224; uint32_t vsync_lines = 16; + bool interrupt_enabled = true; uint8_t zoom = 2; bool fullscreen = false; @@ -39,8 +40,6 @@ namespace zxscreen uint8_t t_flash = 0; bool flash = false; - int pixels_draw = 0; - uint32_t pixel_base_addr = 0x4000; uint32_t color_base_addr = 0x5800; @@ -235,6 +234,9 @@ namespace zxscreen } create_tables(); + ptr_pixel = zx_pixels; + t_screen = t_flash = 0; + flash = false; reinit(); } @@ -247,7 +249,7 @@ namespace zxscreen } } - void refresh(const uint32_t dt, const bool full) + void refresh(const uint32_t dt) { const uint8_t* pixel_mem = mem::rawPtr(pixel_base_addr); const uint8_t* color_mem = mem::rawPtr(color_base_addr); @@ -272,17 +274,15 @@ namespace zxscreen mask>>=1; *(ptr_pixel++)=(block&mask) ? c1 : c2; } - pixels_draw+=2; } t_screen++; if (t_screen>=t_states_total) { - pixels_draw=0; t_flash++; if (t_flash==16) { t_flash=0; flash = !flash; } t_screen=0; ptr_pixel = zx_pixels; redraw(); - if (!full) z80::interrupt(); + if (interrupt_enabled) z80::interrupt(); } } } @@ -293,7 +293,9 @@ namespace zxscreen t_screen = 0; uint8_t * tmp_ptr = ptr_pixel; ptr_pixel = zx_pixels; - refresh(t_states_total, true); + interrupt_enabled = false; + refresh(t_states_total); + interrupt_enabled = true; ptr_pixel = tmp_ptr; t_screen = tmp; } diff --git a/zx_screen.h b/zx_screen.h index 57e6f4a..addca98 100644 --- a/zx_screen.h +++ b/zx_screen.h @@ -10,7 +10,7 @@ namespace zxscreen void setBaseAddresses(const uint32_t pixeladdr, const uint32_t coloraddr); void reinit(); void focus(); - void refresh(const uint32_t dt, const bool full=false); + void refresh(const uint32_t dt); void fullrefresh(); void debugrefresh(); void redraw(const bool present=true); diff --git a/zx_speaker.cpp b/zx_speaker.cpp index 3d71091..a42d4d5 100644 --- a/zx_speaker.cpp +++ b/zx_speaker.cpp @@ -5,24 +5,46 @@ namespace speaker { - #define SAMPLING_FREQ 44100 - #define AUDIO_BUFFER_SIZE 2048 - SDL_AudioDeviceID sdlAudioDevice; - uint8_t sound_buffer[AUDIO_BUFFER_SIZE]; + uint16_t sampling_freq = 44100; + uint16_t audio_buffer_size = 2048; + SDL_AudioDeviceID sdlAudioDevice = 0; + uint8_t *sound_buffer = nullptr; uint16_t sound_pos=0; uint16_t t_sound=0; std::vector sources; float cycles_per_sample; - void init() + void init(const uint16_t freq, const uint16_t buffer_size) { - SDL_AudioSpec audioSpec{SAMPLING_FREQ, AUDIO_U8, 1, 0, AUDIO_BUFFER_SIZE>>2, 0, 0, NULL, NULL}; + if (sound_buffer || sdlAudioDevice) quit(); + + sampling_freq = freq; + audio_buffer_size = buffer_size; + + SDL_AudioSpec audioSpec{sampling_freq, AUDIO_U8, 1, 0, (uint16_t)(audio_buffer_size>>2), 0, 0, NULL, NULL}; sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); - cycles_per_sample = z80::getClock() / SAMPLING_FREQ; + + cycles_per_sample = z80::getClock() / sampling_freq; + sound_buffer = (uint8_t*)malloc(audio_buffer_size); + enable(); } + void quit() + { + disable(); + sources.clear(); + if (sound_buffer) { + free(sound_buffer); + sound_buffer = nullptr; + } + if (sdlAudioDevice) { + SDL_CloseAudioDevice(sdlAudioDevice); + sdlAudioDevice = 0; + } + } + void enable() { SDL_PauseAudioDevice(sdlAudioDevice, 0); @@ -38,7 +60,7 @@ namespace speaker sources.push_back(callback); } - void update(const uint8_t dt) + void update(const uint32_t dt) { t_sound += dt; if (t_sound>=cycles_per_sample) { @@ -48,12 +70,12 @@ namespace speaker for (auto callback : sources) sample += callback(); sample /= sources.size(); - sound_buffer[(sound_pos++)&(AUDIO_BUFFER_SIZE-1)] = sample; + sound_buffer[(sound_pos++)&(audio_buffer_size-1)] = sample; } if (sound_pos>=1000) { SDL_QueueAudio(sdlAudioDevice, sound_buffer, sound_pos); sound_pos = 0; - while (SDL_GetQueuedAudioSize(sdlAudioDevice) > 4096 ) {} + while (SDL_GetQueuedAudioSize(sdlAudioDevice) > (audio_buffer_size<<1) ) {} } } diff --git a/zx_speaker.h b/zx_speaker.h index c1e3c01..caa71f6 100644 --- a/zx_speaker.h +++ b/zx_speaker.h @@ -3,9 +3,10 @@ namespace speaker { - void init(); + void init(const uint16_t freq = 44100, const uint16_t buffer_size = 2048); + void quit(); void enable(); void disable(); void register_source(uint8_t(*callback)()); - void update(const uint8_t dt); + void update(const uint32_t dt); } diff --git a/zx_system.cpp b/zx_system.cpp new file mode 100644 index 0000000..b880171 --- /dev/null +++ b/zx_system.cpp @@ -0,0 +1,101 @@ +#include "zx_system.h" +#include "z80.h" +#include "zx_mem.h" +#include "zx_ula.h" +#include "zx_screen.h" +#include "zx_tape.h" +#include "zx_speaker.h" +#include "ay-3-8912.h" +#include + +namespace zx_system +{ + bool resetting = true; + bool shutting_down = false; + uint8_t current_mode = ZX_48K; + uint8_t new_mode = ZX_48K; + std::vector updatables; + + int init(const uint8_t mode) + { + updatables.clear(); + z80::clearPorts(); + resetting = false; + switch(mode) + { + case ZX_NOCHANGE: + { + z80::reset(); + break; + + } + case ZX_48K: + { + const uint32_t clock = 3500000; + z80::init(clock); + z80::connect_port(0xfe, 0x0001, zx_ula::port_in, zx_ula::port_out); + mem::init(ZX_48K); + zxscreen::init(SCREEN_MODE_48K); + speaker::init(); + speaker::register_source(zx_ula::get_sample); + + registerUpdatable(zx_tape::update); + registerUpdatable(speaker::update); + //registerUpdatable(zxscreen::refresh); + + return clock / 10; + break; + } + case ZX_128K: + { + const uint32_t clock = 3546900; + z80::init(clock); + z80::connect_port(0xfe, 0x0001, zx_ula::port_in, zx_ula::port_out); + mem::init(ZX_128K); + zxscreen::init(SCREEN_MODE_128K); + audio::init(); + speaker::init(); + speaker::register_source(zx_ula::get_sample); + speaker::register_source(audio::get_sample); + + registerUpdatable(zx_tape::update); + registerUpdatable(audio::update); + registerUpdatable(speaker::update); + //registerUpdatable(zxscreen::refresh); + + return clock / 10; + break; + } + } + return 0; + } + + void reset(const uint8_t mode) + { + new_mode = mode; + resetting = true; + } + + void shutdown() + { + shutting_down = true; + } + + const bool shuttingDown() + { + if (resetting) init(new_mode); + return shutting_down; + } + + void registerUpdatable(void(*callback)(uint32_t)) + { + updatables.push_back(callback); + } + + void update(uint32_t dt) + { + for (auto& call : updatables) call(dt); + } + + +} diff --git a/zx_system.h b/zx_system.h new file mode 100644 index 0000000..18455e8 --- /dev/null +++ b/zx_system.h @@ -0,0 +1,19 @@ +#pragma once +#include + +#define ZX_NOCHANGE 0x00 +#define ZX_48K 0x01 +#define ZX_128K 0x02 +#define ZX_2A_3 0x03 +#define ZX_NEXT 0x04 + +namespace zx_system +{ + int init(const uint8_t mode); + void reset(const uint8_t mode); + void shutdown(); + const bool shuttingDown(); + + void registerUpdatable(void(*callback)(uint32_t)); + void update(uint32_t dt); +} diff --git a/zx_tape.cpp b/zx_tape.cpp index bf3d625..091456a 100644 --- a/zx_tape.cpp +++ b/zx_tape.cpp @@ -95,7 +95,7 @@ namespace zx_tape pulse_level = 1; } - void update(const uint8_t dt) + void update(const uint32_t dt) { if (!playing) return; diff --git a/zx_tape.h b/zx_tape.h index c48a407..d0debf2 100644 --- a/zx_tape.h +++ b/zx_tape.h @@ -11,7 +11,7 @@ namespace zx_tape void play(); void stop(); void rewind(); - void update(const uint8_t dt); + void update(const uint32_t dt); const bool getplaying(); void report(); uint16_t fastLoad(const uint8_t block_type, const uint16_t address, const uint16_t length);