Compare commits

..

10 Commits

Author SHA1 Message Date
b05ce14a95 - [CHG] Per ara llevem la càrrega ràpida (que no va)
- [NEW] Afegit el Manic Miner pa provar
2024-04-23 06:38:11 +02:00
06734c3af4 - [ONGOING] Berserk Mode! 2024-04-22 14:56:27 +02:00
0bd7c841d9 - [NEW] IM2 teòricament funcionant 2024-04-22 14:46:47 +02:00
9831d3e8bc -[FIX] Arreglat el problema de les linies negres 2024-04-22 14:46:09 +02:00
43ee57221a -[FIX] El despaçament de les instruccions de les tables IX, IX_BIT, IY i IY_BIT no pillava el signe 2024-04-22 13:11:29 +02:00
9c2bf54c83 - [FIX] gestió incorrecta del carry en ADC8() 2024-04-22 10:02:28 +02:00
917531b60d - [FIX] Estava mirant mal el flag de BRIGHT 2024-04-22 10:01:49 +02:00
908beaf293 - [NEW] Cambiada la gestió del teclat per a facilitar certes combinacions amb teclats normals 2024-04-22 10:01:20 +02:00
9b603604e9 - [CHG] zx_screen pinta t_state a t_state, per a que es vegen les ralles al carregar
- [FIX] Ja carrega blocs capçalera i blocs programa. Falla el següent...
2024-04-21 21:53:34 +02:00
ddcb40b289 - Deixe el Abu Simbel ací per a anar fent proves de càrrega
- [NEW] Mòdul zx_tape, encara no carrega correctament les cintes.
- [CHG] Gestió completa del só pasada a la ULA, i de la pantalla a zxscreen
2024-04-20 09:32:57 +02:00
10 changed files with 550 additions and 128 deletions

BIN
abusimbel.tap Normal file

Binary file not shown.

View File

@@ -5,18 +5,11 @@
#include "z80debug.h"
#include "zx_ula.h"
#include "zx_screen.h"
#include "zx_tape.h"
#include <SDL2/SDL.h>
#include <string.h>
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("manic.tap");
bool should_exit = false;
SDL_Event e;
@@ -44,27 +39,24 @@ 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::redraw();
}
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);
zxscreen::redraw();
} 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);
zxscreen::redraw();
} 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 +70,13 @@ int main(int argc, char *argv[])
if (e.type == SDL_KEYDOWN) {
if (e.key.keysym.scancode==SDL_SCANCODE_F8) {
z80debug::stop();
zxscreen::refresh();
zxscreen::redraw();
}
if (e.key.keysym.scancode==SDL_SCANCODE_F12) {
zx_tape::play();
}
if (e.key.keysym.scancode==SDL_SCANCODE_F11) {
zx_tape::rewind();
}
}
}
@@ -86,30 +84,15 @@ int main(int argc, char *argv[])
if (!z80debug::debugging()) {
if (z80debug::isbreak(z80::getPC(), 9)) {
z80debug::stop();
zxscreen::refresh();
zxscreen::redraw();
} 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();
}
//if (z80::getPC()==0x05C8) zx_tape::go_berserk();
uint8_t dt = z80::step();
zx_tape::update(dt);
//if (!zx_tape::berserk()) {
zx_ula::sound_update(dt);
//}
zxscreen::refresh(dt);
}
}
}

BIN
manic.tap Normal file

Binary file not shown.

16
z80.cpp
View File

@@ -338,7 +338,7 @@ namespace z80
rF=0;
FLAGS_SZXY(res);
if ( (res & 0x0f) <= (rA & 0x0f) ) SET_FLAGS(fH);
if ( res <= rA ) SET_FLAGS(fC);
if ( res > 255 ) SET_FLAGS(fC);
if ( (b^rA^0x80) & (b^res) & 0x80 ) SET_FLAGS(fV);
rA = (uint8_t)res;
}
@@ -643,7 +643,11 @@ namespace z80
if (!iff1) return;
exit_from_halt = true;
PUSH(rPC);
rPC = 0x38;
if (im==1) {
rPC = 0x38;
} else if (im==2) {
rPC = (rI<<8) | 0xFF;
}
}
void RST(uint8_t vec)
@@ -1601,7 +1605,7 @@ namespace z80
void IX_INSTRUCTIONS()
{
const uint8_t opcode = READ_M1();
uint8_t d;
int8_t d;
switch (opcode)
{
@@ -1821,7 +1825,7 @@ namespace z80
void IX_BIT_INSTRUCTIONS()
{
const uint8_t d = READ_MEM_8();
const int8_t d = READ_MEM_8();
const uint8_t opcode = READ_MEM_8();
t+=3;
switch (opcode)
@@ -2181,7 +2185,7 @@ namespace z80
void IY_INSTRUCTIONS()
{
const uint8_t opcode = READ_M1();
uint8_t d;
int8_t d;
switch (opcode)
{
@@ -2401,7 +2405,7 @@ namespace z80
void IY_BIT_INSTRUCTIONS()
{
const uint8_t d = READ_MEM_8();
const int8_t d = READ_MEM_8();
const uint8_t opcode = READ_MEM_8();
t+=3;
switch (opcode)

View File

@@ -13,61 +13,140 @@ namespace zxscreen
SDL_Renderer *ren = nullptr;
SDL_Texture *tex = nullptr;
bool _flash = false;
uint32_t time=0;
void flash() { _flash = not _flash; }
uint32_t t_screen = 0;
uint8_t t_flash = 0;
bool flash = false;
void show()
int pixels_draw = 0;
uint16_t pixel_addr[69888];
uint16_t color_addr[69888];
uint8_t zx_pixels[352*296];
uint8_t *ptr_pixel = zx_pixels;
void create_tables()
{
if (win) return;
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();
}
uint32_t count = 0;
void refresh()
{
const uint8_t* memory = z80::getMem();
const uint8_t border_color = zx_ula::get_border_color();
//memory+=0x4000;
uint16_t *ptr_pixel = pixel_addr;
uint16_t *ptr_color = color_addr;
Uint32* pixels;
int pitch;
SDL_LockTexture(tex, NULL, (void**)&pixels, &pitch);
// vsync
for (int i=0; i<224*16;++i) { *(ptr_pixel++) = 0; *(ptr_color++) = 0; }
// Upper border
for (int i=0; i<352*48;++i) *(pixels++) = palette[border_color];
for (int i=0; i<48;++i) {
// hsync
for (int j=0;j<48;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 0; }
//border
for (int j=0;j<176;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 1; count+=2; }
}
// scanlines
for (uint8_t y=0; y<192; ++y)
{
// hsync
for (int j=0;j<48;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 0; }
// Left border
for (int j=0;j<48;++j) *(pixels++) = palette[border_color];
for (int j=0;j<24;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 1; count+=2; }
// Actual screen
for (uint8_t x=0;x<32;++x)
{
uint8_t color = memory[0x5800 + x + (y>>3)*32];
uint16_t color = 0x5800 + x + (y>>3)*32;
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; }
for (int i=0;i<8;++i)
for (int i=7;i>0;i-=2)
{
*(pixels++)=(block&0x80) ? palette[c1] : palette[c2];
block = block<<1;
*(ptr_pixel++) = (address & 0x1FFF) | (i << 13);
*(ptr_color++) = color;
count+=2;
}
}
// Right border
for (int j=0;j<48;++j) *(pixels++) = palette[border_color];
for (int j=0;j<24;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 1; count+=2; }
}
// Lower border
for (int i=0; i<352*48;++i) *(pixels++)=palette[border_color];
for (int i=0; i<56;++i) {
// hsync
for (int j=0;j<48;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 0; }
//border
for (int j=0;j<176;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = 1; count+=2; }
}
printf("COUNT: %i\n", count);
}
void show()
{
if (win) return;
win = SDL_CreateWindow("ZX Spectrum Screen", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 352, 296, SDL_WINDOW_SHOWN);
ren = SDL_CreateRenderer(win, -1, 0);
tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 352, 296);
create_tables();
redraw();
}
void refresh(const uint8_t dt)
{
const uint8_t* memory = z80::getMem();
const uint8_t border_color = zx_ula::get_border_color();
for (int i=0;i<dt;++i)
{
if (color_addr[t_screen] != 0)
{
if (color_addr[t_screen] == 1)
{
*(ptr_pixel++) = border_color;
*(ptr_pixel++) = border_color;
//pixels_draw+=2;
}
else
{
uint8_t color = memory[color_addr[t_screen]];
uint8_t c1 = color&0x7, c2 = (color>>3)&0x7;
if ((color&0x80) && flash) { c1=c2; c2=color&0x7; }
if ((color&0x40)) { c1 |= 0x8; c2 |= 0x8; }
uint16_t address = (0x4000) | (pixel_addr[t_screen]&0x1FFF);
uint8_t mask = 1 << (pixel_addr[t_screen]>>13);
uint8_t block = memory[address];
*(ptr_pixel++)=(block&mask) ? c1 : c2;
mask>>=1;
*(ptr_pixel++)=(block&mask) ? c1 : c2;
}
pixels_draw+=2;
}
t_screen++;
/*if (pixels_draw>352*296)
{
printf("PIXELS OVERFLOW: %i\n", pixels_draw);
}*/
if (t_screen>=69888) {
//printf("PIXELS DRAWN: %i\n", pixels_draw);
pixels_draw=0;
t_flash++;
if (t_flash==16) { t_flash=0; flash = !flash; }
t_screen=0;
ptr_pixel = zx_pixels;
redraw();
//while (SDL_GetTicks()-time < 20) {}
//time = SDL_GetTicks();
z80::interrupt();
}
}
}
void redraw()
{
Uint32* pixels;
int pitch;
SDL_LockTexture(tex, NULL, (void**)&pixels, &pitch);
for (int i=0; i<352*296;++i) *(pixels++) = palette[zx_pixels[i]];
SDL_UnlockTexture(tex);
SDL_RenderCopy(ren, tex, NULL, NULL);
SDL_RenderPresent(ren);

View File

@@ -1,8 +1,9 @@
#pragma once
#include <stdint.h>
namespace zxscreen
{
void show();
void refresh();
void flash();
void refresh(const uint8_t dt);
void redraw();
}

224
zx_tape.cpp Normal file
View File

@@ -0,0 +1,224 @@
#include "zx_tape.h"
#include "zx_ula.h"
#include <vector>
#include <stdio.h>
#include <stdlib.h>
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 *data;
};
bool playing = false;
bool loaded = false;
bool berserk_mode = false;
std::vector<block_t> 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 = !playing; //true;
}
void stop()
{
playing = false;
berserk_mode = 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].data[0]<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 && pulse_level==0)
{
pulse_level = 0;
}
else 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;
}
}
static int level[2] = {0, 0};
if (current_section == PULSE_DATA)
{
level[pulse_level]+=dt;
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 =0;//-= pulse_len;
pulse_level--;
if (pulse_level>=2)
{
pulse_level = 1;
//printf("%i\n",current_bit);
level[0]=level[1]=0;
current_bit++;
if (current_bit>=8)
{
current_bit = 0;
block_pos++;
if (block_pos>=blocks[current_block].length)
{
block_pos = 0;
current_section = PULSE_SYNC3;
}
}
}
}
}
/*if (current_section == PULSE_CHECKSUM)
{
const uint8_t datum = 1;//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)
{
pulse_pos = 0;
current_section = PULSE_PILOT;
pulse_level = 1;
current_block++;
if (current_block>=blocks.size())
{
stop();
rewind();
}
}
}
zx_ula::set_ear(pulse_level);
}
void go_berserk() { berserk_mode = true; }
const bool berserk() { return berserk_mode; }
}

13
zx_tape.h Normal file
View File

@@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
namespace zx_tape
{
void load(const char* filename);
void play();
void stop();
void rewind();
void update(const uint8_t dt);
void go_berserk();
const bool berserk();
}

View File

@@ -3,86 +3,196 @@
namespace zx_ula
{
#define KEY_SHIFT 0
#define KEY_Z 1
#define KEY_X 2
#define KEY_C 3
#define KEY_V 4
#define KEY_A 5
#define KEY_S 6
#define KEY_D 7
#define KEY_F 8
#define KEY_G 9
#define KEY_Q 10
#define KEY_W 11
#define KEY_E 12
#define KEY_R 13
#define KEY_T 14
#define KEY_1 15
#define KEY_2 16
#define KEY_3 17
#define KEY_4 18
#define KEY_5 19
#define KEY_0 20
#define KEY_9 21
#define KEY_8 22
#define KEY_7 23
#define KEY_6 24
#define KEY_P 25
#define KEY_O 26
#define KEY_I 27
#define KEY_U 28
#define KEY_Y 29
#define KEY_RETURN 30
#define KEY_L 31
#define KEY_K 32
#define KEY_J 33
#define KEY_H 34
#define KEY_SPACE 35
#define KEY_SYMBOL 36
#define KEY_M 37
#define KEY_N 38
#define KEY_B 39
uint8_t zx_keyboard[40];
static uint8_t border_color = 0;
static uint8_t ear = 0;
static uint8_t mic = 0;
int port_in(int port)
void update_zx_keyboard()
{
const uint8_t *keys = SDL_GetKeyboardState(NULL);
// Normal keypresses
zx_keyboard[KEY_SHIFT] = keys[SDL_SCANCODE_LSHIFT] | keys[SDL_SCANCODE_RSHIFT];
zx_keyboard[KEY_Z] = keys[SDL_SCANCODE_Z];
zx_keyboard[KEY_X] = keys[SDL_SCANCODE_X];
zx_keyboard[KEY_C] = keys[SDL_SCANCODE_C];
zx_keyboard[KEY_V] = keys[SDL_SCANCODE_V];
zx_keyboard[KEY_A] = keys[SDL_SCANCODE_A];
zx_keyboard[KEY_S] = keys[SDL_SCANCODE_S];
zx_keyboard[KEY_D] = keys[SDL_SCANCODE_D];
zx_keyboard[KEY_F] = keys[SDL_SCANCODE_F];
zx_keyboard[KEY_G] = keys[SDL_SCANCODE_G];
zx_keyboard[KEY_Q] = keys[SDL_SCANCODE_Q];
zx_keyboard[KEY_W] = keys[SDL_SCANCODE_W];
zx_keyboard[KEY_E] = keys[SDL_SCANCODE_E];
zx_keyboard[KEY_R] = keys[SDL_SCANCODE_R];
zx_keyboard[KEY_T] = keys[SDL_SCANCODE_T];
zx_keyboard[KEY_1] = keys[SDL_SCANCODE_1] | keys[SDL_SCANCODE_KP_1];
zx_keyboard[KEY_2] = keys[SDL_SCANCODE_2] | keys[SDL_SCANCODE_KP_2];
zx_keyboard[KEY_3] = keys[SDL_SCANCODE_3] | keys[SDL_SCANCODE_KP_3];
zx_keyboard[KEY_4] = keys[SDL_SCANCODE_4] | keys[SDL_SCANCODE_KP_4];
zx_keyboard[KEY_5] = keys[SDL_SCANCODE_5] | keys[SDL_SCANCODE_KP_5];
zx_keyboard[KEY_0] = keys[SDL_SCANCODE_0] | keys[SDL_SCANCODE_KP_0];
zx_keyboard[KEY_9] = keys[SDL_SCANCODE_9] | keys[SDL_SCANCODE_KP_9];
zx_keyboard[KEY_8] = keys[SDL_SCANCODE_8] | keys[SDL_SCANCODE_KP_8];
zx_keyboard[KEY_7] = keys[SDL_SCANCODE_7] | keys[SDL_SCANCODE_KP_7];
zx_keyboard[KEY_6] = keys[SDL_SCANCODE_6] | keys[SDL_SCANCODE_KP_6];
zx_keyboard[KEY_P] = keys[SDL_SCANCODE_P];
zx_keyboard[KEY_O] = keys[SDL_SCANCODE_O];
zx_keyboard[KEY_I] = keys[SDL_SCANCODE_I];
zx_keyboard[KEY_U] = keys[SDL_SCANCODE_U];
zx_keyboard[KEY_Y] = keys[SDL_SCANCODE_Y];
zx_keyboard[KEY_RETURN] = keys[SDL_SCANCODE_KP_ENTER] | keys[SDL_SCANCODE_RETURN];
zx_keyboard[KEY_L] = keys[SDL_SCANCODE_L];
zx_keyboard[KEY_K] = keys[SDL_SCANCODE_K];
zx_keyboard[KEY_J] = keys[SDL_SCANCODE_J];
zx_keyboard[KEY_H] = keys[SDL_SCANCODE_H];
zx_keyboard[KEY_SPACE] = keys[SDL_SCANCODE_SPACE];
zx_keyboard[KEY_SYMBOL] = keys[SDL_SCANCODE_LCTRL] | keys[SDL_SCANCODE_RCTRL];
zx_keyboard[KEY_M] = keys[SDL_SCANCODE_M];
zx_keyboard[KEY_N] = keys[SDL_SCANCODE_N];
zx_keyboard[KEY_B] = keys[SDL_SCANCODE_B];
// Keys in a normal keyboard that ara combinations in the zx one
if (keys[SDL_SCANCODE_BACKSPACE]) zx_keyboard[KEY_SHIFT] = zx_keyboard[KEY_0] = 1;
if (keys[SDL_SCANCODE_PERIOD]) zx_keyboard[KEY_SYMBOL] = zx_keyboard[KEY_M] = 1;
}
int port_in(int port)
{
const uint8_t h_addr = (port>>8);
uint8_t result = 0xff;
uint8_t result = ear ? 0xbf : 0xff;
update_zx_keyboard();
if (!(h_addr & ~0xfe))
{
result &= ~(
keys[SDL_SCANCODE_LSHIFT]*0x01 +
keys[SDL_SCANCODE_Z]*0x02 +
keys[SDL_SCANCODE_X]*0x04 +
keys[SDL_SCANCODE_C]*0x08 +
keys[SDL_SCANCODE_V]*0x10 );
zx_keyboard[KEY_SHIFT]*0x01 +
zx_keyboard[KEY_Z]*0x02 +
zx_keyboard[KEY_X]*0x04 +
zx_keyboard[KEY_C]*0x08 +
zx_keyboard[KEY_V]*0x10 );
}
if (!(h_addr & ~0xfd))
{
result &= ~(
keys[SDL_SCANCODE_A]*0x01 +
keys[SDL_SCANCODE_S]*0x02 +
keys[SDL_SCANCODE_D]*0x04 +
keys[SDL_SCANCODE_F]*0x08 +
keys[SDL_SCANCODE_G]*0x10 );
zx_keyboard[KEY_A]*0x01 +
zx_keyboard[KEY_S]*0x02 +
zx_keyboard[KEY_D]*0x04 +
zx_keyboard[KEY_F]*0x08 +
zx_keyboard[KEY_G]*0x10 );
}
if (!(h_addr & ~0xfb))
{
result &= ~(
keys[SDL_SCANCODE_Q]*0x01 +
keys[SDL_SCANCODE_W]*0x02 +
keys[SDL_SCANCODE_E]*0x04 +
keys[SDL_SCANCODE_R]*0x08 +
keys[SDL_SCANCODE_T]*0x10 );
zx_keyboard[KEY_Q]*0x01 +
zx_keyboard[KEY_W]*0x02 +
zx_keyboard[KEY_E]*0x04 +
zx_keyboard[KEY_R]*0x08 +
zx_keyboard[KEY_T]*0x10 );
}
if (!(h_addr & ~0xf7))
{
result &= ~(
keys[SDL_SCANCODE_1]*0x01 +
keys[SDL_SCANCODE_2]*0x02 +
keys[SDL_SCANCODE_3]*0x04 +
keys[SDL_SCANCODE_4]*0x08 +
keys[SDL_SCANCODE_5]*0x10 );
zx_keyboard[KEY_1]*0x01 +
zx_keyboard[KEY_2]*0x02 +
zx_keyboard[KEY_3]*0x04 +
zx_keyboard[KEY_4]*0x08 +
zx_keyboard[KEY_5]*0x10 );
}
if (!(h_addr & ~0xef))
{
result &= ~(
keys[SDL_SCANCODE_0]*0x01 +
keys[SDL_SCANCODE_9]*0x02 +
keys[SDL_SCANCODE_8]*0x04 +
keys[SDL_SCANCODE_7]*0x08 +
keys[SDL_SCANCODE_6]*0x10 );
zx_keyboard[KEY_0]*0x01 +
zx_keyboard[KEY_9]*0x02 +
zx_keyboard[KEY_8]*0x04 +
zx_keyboard[KEY_7]*0x08 +
zx_keyboard[KEY_6]*0x10 );
}
if (!(h_addr & ~0xdf))
{
result &= ~(
keys[SDL_SCANCODE_P]*0x01 +
keys[SDL_SCANCODE_O]*0x02 +
keys[SDL_SCANCODE_I]*0x04 +
keys[SDL_SCANCODE_U]*0x08 +
keys[SDL_SCANCODE_Y]*0x10 );
zx_keyboard[KEY_P]*0x01 +
zx_keyboard[KEY_O]*0x02 +
zx_keyboard[KEY_I]*0x04 +
zx_keyboard[KEY_U]*0x08 +
zx_keyboard[KEY_Y]*0x10 );
}
if (!(h_addr & ~0xbf))
{
result &= ~(
keys[SDL_SCANCODE_RETURN]*0x01 +
keys[SDL_SCANCODE_L]*0x02 +
keys[SDL_SCANCODE_K]*0x04 +
keys[SDL_SCANCODE_J]*0x08 +
keys[SDL_SCANCODE_H]*0x10 );
zx_keyboard[KEY_RETURN]*0x01 +
zx_keyboard[KEY_L]*0x02 +
zx_keyboard[KEY_K]*0x04 +
zx_keyboard[KEY_J]*0x08 +
zx_keyboard[KEY_H]*0x10 );
}
if (!(h_addr & ~0x7f))
{
result &= ~(
keys[SDL_SCANCODE_SPACE]*0x01 +
keys[SDL_SCANCODE_RSHIFT]*0x02 +
keys[SDL_SCANCODE_M]*0x04 +
keys[SDL_SCANCODE_N]*0x08 +
keys[SDL_SCANCODE_B]*0x10 );
zx_keyboard[KEY_SPACE]*0x01 +
zx_keyboard[KEY_SYMBOL]*0x02 +
zx_keyboard[KEY_M]*0x04 +
zx_keyboard[KEY_N]*0x08 +
zx_keyboard[KEY_B]*0x10 );
}
return result;
}
@@ -90,13 +200,14 @@ namespace zx_ula
void port_out(int port, int val)
{
border_color = val & 0x7;
mic = (val>>3)&0x1;
ear = (val>>4)&0x1;
mic = (val&0x08)==0;
ear = val&0x10;
//printf("EAR:%i MIC:%i\n", ear, mic);
}
uint8_t get_border_color() { return border_color; }
uint8_t get_ear() { return ear; }
void set_ear(const uint8_t val) { ear = val; }
@@ -104,11 +215,13 @@ 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)
{
const uint16_t top = sound_pos < len ? sound_pos : len;
memcpy(stream, sound_buffer, top);
if (top<len) memchr(&stream[top], sound_buffer[top-1], len-top);
sound_pos=0;
}
@@ -128,8 +241,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>=317) {
t_sound-=317;
sound_buffer[sound_pos++] = ear*128;
}
}
}

View File

@@ -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);
}