From ddcb40b289557f974e83a2bb5716fe7c276c4b1c Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Sat, 20 Apr 2024 09:32:57 +0200 Subject: [PATCH] =?UTF-8?q?-=20Deixe=20el=20Abu=20Simbel=20ac=C3=AD=20per?= =?UTF-8?q?=20a=20anar=20fent=20proves=20de=20c=C3=A0rrega=20-=20[NEW]=20M?= =?UTF-8?q?=C3=B2dul=20zx=5Ftape,=20encara=20no=20carrega=20correctament?= =?UTF-8?q?=20les=20cintes.=20-=20[CHG]=20Gesti=C3=B3=20completa=20del=20s?= =?UTF-8?q?=C3=B3=20pasada=20a=20la=20ULA,=20i=20de=20la=20pantalla=20a=20?= =?UTF-8?q?zxscreen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- abusimbel.tap | Bin 0 -> 46362 bytes main.cpp | 63 +++++---------- zx_screen.cpp | 21 +++-- zx_screen.h | 4 +- zx_tape.cpp | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++ zx_tape.h | 11 +++ zx_ula.cpp | 12 ++- zx_ula.h | 3 +- 8 files changed, 270 insertions(+), 56 deletions(-) create mode 100644 abusimbel.tap create mode 100644 zx_tape.cpp create mode 100644 zx_tape.h diff --git a/abusimbel.tap b/abusimbel.tap new file mode 100644 index 0000000000000000000000000000000000000000..652cac95442603ac720ef1210afe86a602d35c7c GIT binary patch literal 46362 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

wge@XO3;*LYEmsCh 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 literal 0 HcmV?d00001 diff --git a/main.cpp b/main.cpp index d823d23..9e4544e 100644 --- a/main.cpp +++ b/main.cpp @@ -5,18 +5,11 @@ #include "z80debug.h" #include "zx_ula.h" #include "zx_screen.h" +#include "zx_tape.h" #include #include uint8_t memory[65536]; -uint32_t t = 0; -uint16_t ts = 0; -uint8_t ft = 0; -uint32_t fps=0; -uint32_t fps_time=0; - - -uint8_t test = 0; int main(int argc, char *argv[]) { @@ -33,6 +26,8 @@ int main(int argc, char *argv[]) zx_ula::sound_init(); + zx_tape::load("abusimbel.tap"); + bool should_exit = false; SDL_Event e; @@ -44,27 +39,22 @@ int main(int argc, char *argv[]) if (z80debug::debugging()) { if ((e.type==SDL_WINDOWEVENT) && ((e.window.event==SDL_WINDOWEVENT_SHOWN) || (e.window.event==SDL_WINDOWEVENT_EXPOSED))) { z80debug::refresh(); - zxscreen::refresh(); + zxscreen::refresh(0, true); } if (e.type == SDL_KEYDOWN) { if (e.key.keysym.scancode==SDL_SCANCODE_ESCAPE) { should_exit=true; break; } else if (e.key.keysym.scancode==SDL_SCANCODE_F10) { - t += z80::step(); - if (t>=69888) { t=0; z80::interrupt(); } + const uint8_t dt = z80::step(); z80debug::refresh(); - zxscreen::refresh(); + zxscreen::refresh(dt, true); } else if (e.key.keysym.scancode==SDL_SCANCODE_F11) { - t += z80debug::next(); - fps=0; - fps_time = SDL_GetTicks(); - zxscreen::refresh(); + const uint8_t dt = z80debug::next(); + zxscreen::refresh(dt, true); } else if (e.key.keysym.scancode==SDL_SCANCODE_F5) { - t += z80::step(); + const uint8_t dt = z80::step(); z80debug::cont(); - fps=0; - fps_time = SDL_GetTicks(); - zxscreen::refresh(); + zxscreen::refresh(dt); } else if (e.key.keysym.scancode==SDL_SCANCODE_RETURN) { z80debug::executeConsole(); } else if (e.key.keysym.scancode==SDL_SCANCODE_BACKSPACE) { @@ -78,7 +68,10 @@ int main(int argc, char *argv[]) if (e.type == SDL_KEYDOWN) { if (e.key.keysym.scancode==SDL_SCANCODE_F8) { z80debug::stop(); - zxscreen::refresh(); + zxscreen::refresh(0, true); + } + if (e.key.keysym.scancode==SDL_SCANCODE_F12) { + zx_tape::play(); } } } @@ -86,30 +79,12 @@ int main(int argc, char *argv[]) if (!z80debug::debugging()) { if (z80debug::isbreak(z80::getPC(), 9)) { z80debug::stop(); - zxscreen::refresh(); + zxscreen::refresh(0, true); } else { - uint8_t t_states = z80::step(); - t += t_states; - ts += t_states; - if (ts>=400) { - ts-=400; - zx_ula::sound_update(); - } - if (t>=69888) { - ft++; - if (ft==16) { ft=0; zxscreen::flash(); } -/* - fps++; - if (SDL_GetTicks() - fps_time >= 1000) { - printf("FPS: %i\n", fps); - fps = 0; - fps_time = SDL_GetTicks(); - } -*/ - t=0; - zxscreen::refresh(); - z80::interrupt(); - } + uint8_t dt = z80::step(); + zx_tape::update(dt); + zx_ula::sound_update(dt); + zxscreen::refresh(dt); } } } diff --git a/zx_screen.cpp b/zx_screen.cpp index e998a2c..66b223e 100644 --- a/zx_screen.cpp +++ b/zx_screen.cpp @@ -13,9 +13,9 @@ namespace zxscreen SDL_Renderer *ren = nullptr; SDL_Texture *tex = nullptr; - bool _flash = false; - - void flash() { _flash = not _flash; } + uint32_t t_screen = 0; + uint8_t t_flash = 0; + bool flash = false; void show() { @@ -23,11 +23,18 @@ namespace zxscreen win = SDL_CreateWindow("ZX Spectrum Screen", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 352, 288, SDL_WINDOW_RESIZABLE); ren = SDL_CreateRenderer(win, -1, 0); tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 352, 288); - refresh(); + refresh(0); } - void refresh() + void refresh(const uint8_t dt, const bool force_refresh) { + t_screen += dt; + if (t_screen>=69888) { + t_flash++; + if (t_flash==16) { t_flash=0; flash = !flash; } + t_screen=0; + } else if (!force_refresh) return; + const uint8_t* memory = z80::getMem(); const uint8_t border_color = zx_ula::get_border_color(); //memory+=0x4000; @@ -53,7 +60,7 @@ namespace zxscreen uint16_t address = 0x4000 | (x&0x1f) | ((y&0x7)<<8) | ((y&0x38)<<2) | ((y&0xc0)<<5); uint8_t block = memory[address]; uint8_t c1 = color&0x7, c2 = (color>>3)&0x7; - if ((color&0x80) && _flash) { c1=c2; c2=color&0x7; } + if ((color&0x80) && flash) { c1=c2; c2=color&0x7; } for (int i=0;i<8;++i) { *(pixels++)=(block&0x80) ? palette[c1] : palette[c2]; @@ -71,5 +78,7 @@ namespace zxscreen SDL_UnlockTexture(tex); SDL_RenderCopy(ren, tex, NULL, NULL); SDL_RenderPresent(ren); + + if (t_screen==0) z80::interrupt(); } } diff --git a/zx_screen.h b/zx_screen.h index 276bf7b..16eca18 100644 --- a/zx_screen.h +++ b/zx_screen.h @@ -1,8 +1,8 @@ #pragma once +#include namespace zxscreen { void show(); - void refresh(); - void flash(); + void refresh(const uint8_t dt, const bool force_refresh=false); } diff --git a/zx_tape.cpp b/zx_tape.cpp new file mode 100644 index 0000000..714276b --- /dev/null +++ b/zx_tape.cpp @@ -0,0 +1,212 @@ +#include "zx_tape.h" +#include "zx_ula.h" +#include +#include +#include + +namespace zx_tape +{ + #define PULSE_PILOT 0 + #define PULSE_SYNC1 1 + #define PULSE_SYNC2 2 + #define PULSE_DATA 3 + #define PULSE_CHECKSUM 4 + #define PULSE_SYNC3 5 + #define PULSE_WAIT 6 + + #define PULSE_LEN_ZERO 855 + #define PULSE_LEN_ONE 1710 + + #define PULSE_LEN_PILOT 2168 + #define PULSE_LEN_SYNC1 667 + #define PULSE_LEN_SYNC2 735 + #define PULSE_LEN_SYNC3 954 + + #define PULSE_COUNT_PILOT_HEADER 8063 + #define PULSE_COUNT_PILOT_DATA 3223 + + struct block_t + { + uint16_t length; + uint8_t flag; + uint8_t *data; + uint8_t checksum; + }; + + bool playing = false; + bool loaded = false; + + std::vector blocks; + uint8_t current_block = 0; + uint16_t block_pos=0; + uint8_t current_bit=0; + + uint8_t current_section = PULSE_PILOT; + uint16_t current_pulse = 0; + uint32_t pulse_pos = 0; + uint8_t pulse_level = 0; + + void load(const char* filename) + { + //[TODO] Free memory that might be taken by previous tape + + FILE *f = fopen(filename, "rb"); + if (!f) return; + while (!feof(f)) + { + block_t block; + fread(&block.length, 2, 1, f); + fread(&block.flag, 1, 1, f); + block.length -= 2; // substract flag and checksum + block.data = (uint8_t *)malloc(block.length); + fread(block.data, block.length, 1, f); + fread(&block.checksum, 1, 1, f); + blocks.push_back(block); + } + fclose(f); + + loaded = true; + playing = false; + rewind(); + } + + void play() + { + if (!loaded) return; + playing = true; + } + + void stop() + { + playing = false; + } + + void rewind() + { + if (!loaded) return; + current_block = block_pos = current_bit = 0; + current_section = PULSE_PILOT; + current_pulse = pulse_pos = 0; + pulse_level = 1; + } + + void update(const uint8_t dt) + { + if (!playing) return; + + pulse_pos += dt; + + if (current_section == PULSE_PILOT) + { + const uint16_t pulse_count = blocks[current_block].flag<128 ? PULSE_COUNT_PILOT_HEADER : PULSE_COUNT_PILOT_DATA; + if (pulse_pos >= PULSE_LEN_PILOT ) + { + pulse_pos -= PULSE_LEN_PILOT; + current_pulse++; + pulse_level = pulse_level?0:1; + if (current_pulse >= pulse_count) + { + current_pulse = 0; + pulse_level = 1; + current_section = PULSE_SYNC1; + } + } + } + + if (current_section == PULSE_SYNC1) + { + if (pulse_pos >= PULSE_LEN_SYNC1) + { + pulse_pos -= PULSE_LEN_SYNC1; + pulse_level = 0; + current_section = PULSE_SYNC2; + } + } + + if (current_section == PULSE_SYNC2) + { + if (pulse_pos >= PULSE_LEN_SYNC2) + { + pulse_pos -= PULSE_LEN_SYNC2; + pulse_level = 1; + current_section = PULSE_DATA; + } + } + + if (current_section == PULSE_DATA) + { + const uint8_t datum = blocks[current_block].data[block_pos]; + const uint16_t pulse_len = (datum & (0x80>>current_bit)) == 0 ? PULSE_LEN_ZERO : PULSE_LEN_ONE; + if (pulse_pos >= pulse_len) + { + pulse_pos -= pulse_len; + pulse_level--; + if (pulse_level>=2) + { + pulse_level = 1; + current_bit++; + if (current_bit>=8) + { + current_bit = 0; + block_pos++; + if (block_pos>=blocks[current_block].length) + { + block_pos = 0; + current_section = PULSE_CHECKSUM; + } + } + } + } + } + + if (current_section == PULSE_CHECKSUM) + { + const uint8_t datum = blocks[current_block].checksum; + const uint16_t pulse_len = (datum & (0x80>>current_bit)) == 0 ? PULSE_LEN_ZERO : PULSE_LEN_ONE; + if (pulse_pos >= pulse_len) + { + pulse_pos -= pulse_len; + pulse_level--; + if (pulse_level>=2) + { + pulse_level = 1; + current_bit++; + if (current_bit>=8) + { + current_bit = 0; + current_section = PULSE_SYNC3; + } + } + } + } + + if (current_section == PULSE_SYNC3) + { + if (pulse_pos >= PULSE_LEN_SYNC3) + { + pulse_pos -= PULSE_LEN_SYNC3; + pulse_level = 0; + current_section = PULSE_WAIT; + } + + } + + if (current_section == PULSE_WAIT) + { + pulse_level = 0; + if (pulse_pos >= 3500000) + { + current_section = PULSE_PILOT; + pulse_level = 1; + current_block++; + if (current_block>=blocks.size()) + { + stop(); + rewind(); + } + } + } + + zx_ula::set_ear(pulse_level); + } +} diff --git a/zx_tape.h b/zx_tape.h new file mode 100644 index 0000000..a929b9c --- /dev/null +++ b/zx_tape.h @@ -0,0 +1,11 @@ +#pragma once +#include + +namespace zx_tape +{ + void load(const char* filename); + void play(); + void stop(); + void rewind(); + void update(const uint8_t dt); +} diff --git a/zx_ula.cpp b/zx_ula.cpp index bd5241a..cebd42b 100644 --- a/zx_ula.cpp +++ b/zx_ula.cpp @@ -11,7 +11,7 @@ namespace zx_ula { const uint8_t *keys = SDL_GetKeyboardState(NULL); const uint8_t h_addr = (port>>8); - uint8_t result = 0xff; + uint8_t result = ear ? 0xbf : 0xff; if (!(h_addr & ~0xfe)) { result &= ~( @@ -97,6 +97,7 @@ namespace zx_ula uint8_t get_border_color() { return border_color; } uint8_t get_ear() { return ear; } + void set_ear(const uint8_t val) { ear = val; } @@ -104,6 +105,7 @@ namespace zx_ula SDL_AudioDeviceID sdlAudioDevice; uint8_t sound_buffer[1024]; uint16_t sound_pos; + uint16_t t_sound=0; void audioCallback(void * userdata, uint8_t * stream, int len) { @@ -128,8 +130,12 @@ namespace zx_ula SDL_PauseAudioDevice(sdlAudioDevice, 1); } - void sound_update() + void sound_update(const uint8_t dt) { - sound_buffer[sound_pos++] = ear*128; + t_sound += dt; + if (t_sound>=400) { + t_sound-=400; + sound_buffer[sound_pos++] = ear*128; + } } } \ No newline at end of file diff --git a/zx_ula.h b/zx_ula.h index 3a9e7ac..3b6991e 100644 --- a/zx_ula.h +++ b/zx_ula.h @@ -9,9 +9,10 @@ namespace zx_ula uint8_t get_border_color(); uint8_t get_ear(); + void set_ear(const uint8_t val); void sound_init(); void sound_enable(); void sound_disable(); - void sound_update(); + void sound_update(const uint8_t dt); }