-[NEW] reorganització de códi

-[NEW] mòdul display operatiu
-[NEW] mòdul tia pràcticament acabat (falta el reset)
-[NEW] glue code para poder compilar. Primera compilació
-[NEW] Afegides classes de UI
-[NEW] Afegides classes de debug desensamblador del z80, a convertir a 6502
This commit is contained in:
raimon@prometeo
2026-09-17 10:43:59 +02:00
parent c819ab5f16
commit fb5097733d
29 changed files with 2286 additions and 65 deletions
+3 -1
View File
@@ -1 +1,3 @@
nes
atari2600
atari2600_debug
build/*
+4 -2
View File
@@ -4,13 +4,15 @@ libs = -Wl,--gc-sections -lSDL3
executable = atari2600
sourcepath = source+
buildpath = build
exclude = z80*
[linux_debug] default
cppflags = -D DEBUG -g -Wall -std=c++20 -Isource
libs = -lSDL3 -lGL
cppflags = -D DEBUG -g -std=c++20 -Isource
libs = -lSDL3
executable = atari2600_debug
sourcepath = source+
buildpath = build
exclude = z80*
[windows]
cppflags = -Wall -Os -ffunction-sections -fdata-sections -std=c++20 -Isource
View File
View File
+3 -3
View File
@@ -40,8 +40,8 @@ namespace atari2600
void step()
{
uint8_t t_states;
uint16_t pc = m6502::getPC();
//uint8_t t_states;
//uint16_t pc = m6502::getPC();
// if (z80debugger::isbreak(pc, 9)) {
// msx::pause();
@@ -59,7 +59,7 @@ namespace atari2600
tia::tick();
tia::tick();
pia::tick();
t_states++;
//t_states++;
}
//speaker::update(t_states);
// }
View File
+251
View File
@@ -0,0 +1,251 @@
#include "display.h"
#include <SDL3/SDL.h>
#include "tia.h"
#include "atari2600.h"
#include "ui_window.h"
//#include "z80debugger.h"
#include "ui.h"
namespace display
{
constexpr int screen_width = 160;
constexpr int screen_height = 192;
// Standard Stella NTSC Palette (ARGB format: 0xFFRRGGBB)
// Indexed by: (COLUx >> 1) & 0x7F
const uint32_t palette[128] = {
// Hue $0 (Grayscale / Monochromatic)
0xFF000000, 0xFF282828, 0xFF444444, 0xFF5C5C5C, 0xFF707070, 0xFF848484, 0xFF989898, 0xFFACACAC,
// Hue $1 (Gold / Yellow-Orange)
0xFF4C2C00, 0xFF684400, 0xFF845C00, 0xFF9C7400, 0xFFB48C00, 0xFFCCA414, 0xFFE4BC34, 0xFFFCD454,
// Hue $2 (Orange / Red-Orange)
0xFF541800, 0xFF742C00, 0xFF904400, 0xFFA85C00, 0xFFC07400, 0xFFD88C00, 0xFFF0A420, 0xFFFFBC40,
// Hue $3 (Red-Orange)
0xFF580C00, 0xFF781C00, 0xFF943000, 0xFFB04800, 0xFFC86000, 0xFFE07808, 0xFFF89028, 0xFFFFA848,
// Hue $4 (Magenta / Red-Violet)
0xFF540420, 0xFF74103C, 0xFF902058, 0xFFAC3474, 0xFFC4488C, 0xFFDC5CA8, 0xFFF474C0, 0xFFFF8CD8,
// Hue $5 (Purple / Violet)
0xFF440454, 0xFF601074, 0xFF7C2090, 0xFF9434AC, 0xFFAC48C4, 0xFFC45CDC, 0xFFDC74F4, 0xFFF48CFF,
// Hue $6 (Blue-Violet / Indigo)
0xFF2C0874, 0xFF441494, 0xFF5C24B0, 0xFF7438CC, 0xFF8C4CE4, 0xFFA460FC, 0xFFBC78FF, 0xFFD490FF,
// Hue $7 (Blue)
0xFF101480, 0xFF2424A0, 0xFF3C38BC, 0xFF504CD4, 0xFF6860EC, 0xFF8078FF, 0xFF9890FF, 0xFFB0A8FF,
// Hue $8 (Blue-Cyan)
0xFF002074, 0xFF003494, 0xFF0C48B0, 0xFF2060CC, 0xFF3474E4, 0xFF4C8CFC, 0xFF64A4FF, 0xFF7CBCFF,
// Hue $9 (Cyan / Blue-Green)
0xFF002854, 0xFF004074, 0xFF005490, 0xFF006CAC, 0xFF1880C4, 0xFF3098DC, 0xFF48B0F4, 0xFF60C8FF,
// Hue $A (Teal / Green-Cyan)
0xFF00302C, 0xFF004844, 0xFF00605C, 0xFF007874, 0xFF00908C, 0xFF1CA8A4, 0xFF38C0BC, 0xFF54D8D4,
// Hue $B (Green)
0xFF003408, 0xFF004C18, 0xFF00642C, 0xFF007C40, 0xFF009454, 0xFF14AC6C, 0xFF30C484, 0xFF4CDC9C,
// Hue $C (Yellow-Green)
0xFF0C3400, 0xFF204C00, 0xFF346400, 0xFF487C00, 0xFF5C9400, 0xFF74AC10, 0xFF8CC428, 0xFFA4DC44,
// Hue $D (Olive Green)
0xFF243000, 0xFF3C4800, 0xFF546000, 0xFF6C7800, 0xFF849000, 0xFF9CA800, 0xFFB4C018, 0xFFCCC434,
// Hue $E (Brown / Olive-Yellow)
0xFF3C2C00, 0xFF584000, 0xFF745800, 0xFF8C6C00, 0xFFA48400, 0xFFBC9C00, 0xFFD4B420, 0xFFECC83C,
// Hue $F (Orange-Brown)
0xFF482400, 0xFF643800, 0xFF805000, 0xFF986400, 0xFFB07C00, 0xFFC89400, 0xFFE0AC28, 0xFFF8C444
};
SDL_Window *win = nullptr;
SDL_Renderer *ren = nullptr;
SDL_Texture *tex = nullptr;
SDL_Texture *uitex = nullptr;
uint8_t zoom = 1;
bool fullscreen = false;
int fullscreen_scale = 1;
SDL_FRect dest_rect;
bool eventHandler(SDL_Event *e)
{
if (e->type==SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
return false;
} else if ((e->type==SDL_EVENT_WINDOW_SHOWN) || (e->type==SDL_EVENT_WINDOW_EXPOSED)) {
redraw();
}
if (e->type == SDL_EVENT_KEY_DOWN) {
const SDL_Scancode &key = e->key.scancode;
switch (key) {
case SDL_SCANCODE_F8: atari2600::pause(); /*z80debugger::show();*/ break;
case SDL_SCANCODE_F12: if (atari2600::is_paused()) atari2600::resume(); else atari2600::pause(); break;
case SDL_SCANCODE_Q: if (e->key.mod & SDL_KMOD_CTRL) { return false; break; }
default: break;
}
if (atari2600::is_paused()) {
switch (key) {
case SDL_SCANCODE_F2: display::decZoom(); break;
case SDL_SCANCODE_F3: display::incZoom(); break;
case SDL_SCANCODE_F4: display::toggleFullscreen(); break;
default: break;
}
}
}
if (e->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
if (atari2600::is_paused())
atari2600::resume();
else
atari2600::pause();
}
if (e->type == SDL_EVENT_MOUSE_MOTION) {
SDL_ShowCursor();
}
return true;
}
void init()
{
if (win) ui::window::unregisterWindow(SDL_GetWindowID(win));
if (tex) SDL_DestroyTexture(tex);
if (uitex) SDL_DestroyTexture(uitex);
if (ren) SDL_DestroyRenderer(ren);
if (win) SDL_DestroyWindow(win);
const int z = fullscreen ? 1 : zoom;
win = SDL_CreateWindow("Atari 2600 Screen", screen_width*2*z, screen_height*z, 0);
SDL_SetWindowFullscreen(win, fullscreen);
ren = SDL_CreateRenderer(win, NULL);
tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height);
SDL_SetTextureScaleMode(tex, SDL_SCALEMODE_NEAREST);
uitex = ui::createtexture(ren);
ui::window::registerWindow(SDL_GetWindowID(win), eventHandler);
if (fullscreen)
{
int w, h;
SDL_GetWindowSize(win, &w, &h);
fullscreen_scale = h/screen_height;
dest_rect.w = screen_width*2 * fullscreen_scale;
dest_rect.h = screen_height * fullscreen_scale;
dest_rect.x = (w - dest_rect.w)/2;
dest_rect.y = (h - dest_rect.h)/2;
}
else
{
dest_rect.x = dest_rect.y = 0;
dest_rect.w = screen_width*2 * zoom;
dest_rect.h = screen_height * zoom;
}
focus();
}
void focus()
{
if (win)
{
SDL_RaiseWindow(win);
redraw();
}
}
void redraw(const bool present)
{
//if (zx_tape::getplaying() && zx_tape::getOption(ZXTAPE_OPTION_FAST_LOAD)) return;
//ui::setrenderer(ren, uitex);
const uint8_t *framebuffer = tia::get_framebuffer();
//framebuffer += screen_width*26;
Uint32* pixels;
int pitch;
SDL_LockTexture(tex, NULL, (void**)&pixels, &pitch);
for (int i=0; i<screen_width*screen_height;++i) *(pixels++) = palette[framebuffer[i]];
SDL_UnlockTexture(tex);
if (fullscreen)
{
SDL_SetRenderDrawColor(ren, 0, 0, 0, 255);
SDL_RenderClear(ren);
}
// Pintem la textura a pantalla
SDL_RenderTexture(ren, tex, NULL, &dest_rect);
// Pintem les ralles dels pixels
//if (zoom>2 || fullscreen) {
// SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND);
// SDL_SetRenderDrawColor(ren, 160, 170, 5, 96);
// const float scale = fullscreen ? fullscreen_scale : zoom;
// for (int i=0;i<144;++i) SDL_RenderDrawLine(ren, dest_rect.x, dest_rect.y+i*scale, dest_rect.x+159*scale, dest_rect.y+i*scale);
// for (int i=0;i<160;++i) SDL_RenderDrawLine(ren, dest_rect.x+i*scale, dest_rect.y, dest_rect.x+i*scale, dest_rect.y+143*scale);
//}
//if (present)
// SDL_RenderPresent(ren);
//else
//{
// SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND);
// SDL_SetRenderDrawColor(ren, 0, 0, 0, 128);
// int w = screen_width*zoom;
// int h = screen_height*zoom;
// if (fullscreen) SDL_GetWindowSize(win, &w, &h);
// SDL_FRect rect {0,0,float(w),float(h)};
// SDL_RenderFillRect(ren, &rect);
//}
if (atari2600::is_paused()) {
SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(ren, 0, 0, 0, 128);
int w = screen_width*2*zoom;
int h = screen_height*zoom;
if (fullscreen) SDL_GetWindowSize(win, &w, &h);
SDL_FRect rect {0,0,float(w),float(h)};
SDL_RenderFillRect(ren, &rect);
}
SDL_RenderPresent(ren);
}
void present()
{
SDL_RenderPresent(ren);
}
void setTitle(const char* title)
{
char tmp[256];
strcpy(tmp, "MSX Screen");
strcat(tmp, title);
SDL_SetWindowTitle(win, tmp);
}
void setZoom(const int value)
{
if (fullscreen) return;
if (value < 1) return;
const SDL_DisplayMode *dm = SDL_GetCurrentDisplayMode(SDL_GetDisplayForWindow(win));
if (screen_width*2*value > dm->w) return;
if (screen_height*value > dm->h) return;
zoom = value;
init();
}
void incZoom()
{
if (fullscreen) return;
setZoom(zoom+1);
}
void decZoom()
{
if (fullscreen) return;
setZoom(zoom-1);
}
void toggleFullscreen()
{
fullscreen = !fullscreen;
init();
}
const bool getFullscreen()
{
return fullscreen;
}
}
View File
+48
View File
@@ -0,0 +1,48 @@
#include <SDL3/SDL.h>
#include "atari2600.h"
#include "rom.h"
#include "ui.h"
#include "ui_window.h"
//#include "z80debugger.h"
int main(int argc, char *argv[]) {
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
atari2600::init();
if (argc > 1) {
rom::load(argv[1]);
} else {
rom::load("combat.bin");
}
int wait = 16;
SDL_Event e;
while (!atari2600::is_quitting()) {
wait--;
if (wait==0) {
wait = 16;
if (atari2600::is_paused()) SDL_WaitEventTimeout(NULL, 1000);
while (SDL_PollEvent(&e)) {
bool result = true;
if (e.type == SDL_EVENT_QUIT) { atari2600::quit(); break; }
if (e.type == SDL_EVENT_KEY_DOWN) {
if (atari2600::is_paused()) {
switch (e.key.scancode) {
case SDL_SCANCODE_F10: atari2600::step(); /*z80debugger::refresh();*/ break;
}
}
}
SDL_Window* window = SDL_GetWindowFromEvent(&e);
if (!ui::window::sendEvent(SDL_GetWindowID(window), &e)) { atari2600::quit(); break; }
}
}
if (!atari2600::is_paused()) atari2600::step();
ui::setClicked(false);
}
SDL_Quit();
return 0;
}
View File
View File
+14
View File
@@ -32,9 +32,15 @@ namespace pia
// I/O Ports
switch( address & 0x03) {
case 0x00: // [TODO] SWCHA
return 0x00;
case 0x01: // [TODO] DDRA
return 0x00;
case 0x02: // [TODO] SWCHB
return 0x00;
case 0x03: // [TODO] DDRB
return 0x00;
default:
return 0x00;
}
}
} else {
@@ -50,9 +56,13 @@ namespace pia
// Timer functions
switch( address & 0x03) {
case 0x00: // [TODO] TIM1T
break;
case 0x01: // [TODO] TIM8T
break;
case 0x02: // [TODO] TIM64T
break;
case 0x03: // [TODO] TIM1024T
break;
}
} else {
// Funcionalitat relacionada amb les interrupcions. Ignorar per a la Atari 2600
@@ -61,9 +71,13 @@ namespace pia
// I/O Ports
switch( address & 0x03) {
case 0x00: // [TODO] SWCHA
break;
case 0x01: // [TODO] DDRA
break;
case 0x02: // [TODO] SWCHB
break;
case 0x03: // [TODO] DDRB
break;
}
}
} else {
View File
View File
View File
View File
View File
View File
+153 -59
View File
@@ -1,46 +1,24 @@
#include "tia.h"
#include "tia-audio.h"
#include "display.h"
namespace tia
{
// Standard Stella NTSC Palette (ARGB format: 0xFFRRGGBB)
// Indexed by: (COLUx >> 1) & 0x7F
const uint32_t NTSC_PALETTE[128] = {
// Hue $0 (Grayscale / Monochromatic)
0xFF000000, 0xFF282828, 0xFF444444, 0xFF5C5C5C, 0xFF707070, 0xFF848484, 0xFF989898, 0xFFACACAC,
// Hue $1 (Gold / Yellow-Orange)
0xFF4C2C00, 0xFF684400, 0xFF845C00, 0xFF9C7400, 0xFFB48C00, 0xFFCCA414, 0xFFE4BC34, 0xFFFCD454,
// Hue $2 (Orange / Red-Orange)
0xFF541800, 0xFF742C00, 0xFF904400, 0xFFA85C00, 0xFFC07400, 0xFFD88C00, 0xFFF0A420, 0xFFFFBC40,
// Hue $3 (Red-Orange)
0xFF580C00, 0xFF781C00, 0xFF943000, 0xFFB04800, 0xFFC86000, 0xFFE07808, 0xFFF89028, 0xFFFFA848,
// Hue $4 (Magenta / Red-Violet)
0xFF540420, 0xFF74103C, 0xFF902058, 0xFFAC3474, 0xFFC4488C, 0xFFDC5CA8, 0xFFF474C0, 0xFFFF8CD8,
// Hue $5 (Purple / Violet)
0xFF440454, 0xFF601074, 0xFF7C2090, 0xFF9434AC, 0xFFAC48C4, 0xFFC45CDC, 0xFFDC74F4, 0xFFF48CFF,
// Hue $6 (Blue-Violet / Indigo)
0xFF2C0874, 0xFF441494, 0xFF5C24B0, 0xFF7438CC, 0xFF8C4CE4, 0xFFA460FC, 0xFFBC78FF, 0xFFD490FF,
// Hue $7 (Blue)
0xFF101480, 0xFF2424A0, 0xFF3C38BC, 0xFF504CD4, 0xFF6860EC, 0xFF8078FF, 0xFF9890FF, 0xFFB0A8FF,
// Hue $8 (Blue-Cyan)
0xFF002074, 0xFF003494, 0xFF0C48B0, 0xFF2060CC, 0xFF3474E4, 0xFF4C8CFC, 0xFF64A4FF, 0xFF7CBCFF,
// Hue $9 (Cyan / Blue-Green)
0xFF002854, 0xFF004074, 0xFF005490, 0xFF006CAC, 0xFF1880C4, 0xFF3098DC, 0xFF48B0F4, 0xFF60C8FF,
// Hue $A (Teal / Green-Cyan)
0xFF00302C, 0xFF004844, 0xFF00605C, 0xFF007874, 0xFF00908C, 0xFF1CA8A4, 0xFF38C0BC, 0xFF54D8D4,
// Hue $B (Green)
0xFF003408, 0xFF004C18, 0xFF00642C, 0xFF007C40, 0xFF009454, 0xFF14AC6C, 0xFF30C484, 0xFF4CDC9C,
// Hue $C (Yellow-Green)
0xFF0C3400, 0xFF204C00, 0xFF346400, 0xFF487C00, 0xFF5C9400, 0xFF74AC10, 0xFF8CC428, 0xFFA4DC44,
// Hue $D (Olive Green)
0xFF243000, 0xFF3C4800, 0xFF546000, 0xFF6C7800, 0xFF849000, 0xFF9CA800, 0xFFB4C018, 0xFFCCC434,
// Hue $E (Brown / Olive-Yellow)
0xFF3C2C00, 0xFF584000, 0xFF745800, 0xFF8C6C00, 0xFFA48400, 0xFFBC9C00, 0xFFD4B420, 0xFFECC83C,
// Hue $F (Orange-Brown)
0xFF482400, 0xFF643800, 0xFF805000, 0xFF986400, 0xFFB07C00, 0xFFC89400, 0xFFE0AC28, 0xFFF8C444
};
uint8_t collisions[8] { 0, 0, 0, 0, 0, 0, 0, 0 };
bool collision_missile0_player1 = false;
bool collision_missile0_player0 = false;
bool collision_missile1_player0 = false;
bool collision_missile1_player1 = false;
bool collision_player0_playfield = false;
bool collision_player0_ball = false;
bool collision_player1_playfield = false;
bool collision_player1_ball = false;
bool collision_missile0_playfield = false;
bool collision_missile0_ball = false;
bool collision_missile1_playfield = false;
bool collision_missile1_ball = false;
bool collision_ball_playfield = false;
bool collision_player0_player1 = false;
bool collision_missile0_missile1 = false;
float paddle_pos[4] { 0.5f, 0.5f, 0.5f, 0.5f };
uint32_t paddle_charge_cycles[4] { 0, 0, 0, 0 };
@@ -51,7 +29,7 @@ namespace tia
uint8_t player0_size = 1;
uint8_t player0_num_copies = 1;
uint8_t player0_copies_distance = 0;
uint32_t player0_color = 0x00000000;
uint8_t player0_color = 0;
bool player0_reflect = false;
uint8_t player0_pos = 0;
uint8_t player0_bits = 0;
@@ -63,7 +41,7 @@ namespace tia
uint8_t player1_size = 1;
uint8_t player1_num_copies = 1;
uint8_t player1_copies_distance = 0;
uint32_t player1_color = 0x00000000;
uint8_t player1_color = 0;
bool player1_reflect = false;
uint8_t player1_pos = 0;
uint8_t player1_bits = 0;
@@ -94,7 +72,7 @@ namespace tia
bool ball_vert_delay = false;
uint8_t ball_pixel_counter = 0;
uint32_t playfield_color = 0x00000000;
uint8_t playfield_color = 0;
bool playfield_reflected = false;
bool playfield_score = false;
bool playfield_priority = false;
@@ -106,7 +84,7 @@ namespace tia
{16,17,18,19, 15,14,13,12,11,10,9,8, 0,1,2,3,4,5,6,7, 7,6,5,4,3,2,1,0, 8,9,10,11,12,13,14,15, 19,18,17,16}
};
uint32_t background_color = 0x00000000;
uint8_t background_color = 0;
uint32_t current_frame_cycles = 0;
@@ -121,11 +99,18 @@ namespace tia
uint16_t current_scanline = 0;
bool rdy_low = false;
uint8_t framebuffer[160][192];
void reset()
{
}
const uint8_t *get_framebuffer()
{
return (const uint8_t*)framebuffer;
}
void tick()
{
if (!vblank_dump) current_frame_cycles++;
@@ -164,6 +149,96 @@ namespace tia
ball_pixel_counter = ball_size;
}
bool player0_visible = false;
bool player1_visible = false;
bool missile0_visible = false;
bool missile1_visible = false;
bool ball_visible = false;
bool playfield_visible = false;
if (player0_pixel_counter>0) {
if ((player0_bits>>player0_pixel_position)&0x01) player0_visible = true;
player0_pixel_counter--;
if ( (player0_pixel_counter==0) && (player0_pixel_position>0) ) {
player0_pixel_counter = player0_size;
player0_pixel_position--;
}
}
if (player1_pixel_counter>0) {
if ((player1_bits>>player1_pixel_position)&0x01) player1_visible = true;
player1_pixel_counter--;
if ( (player1_pixel_counter==0) && (player1_pixel_position>0) ) {
player1_pixel_counter = player1_size;
player1_pixel_position--;
}
}
if (missile0_pixel_counter>0) {
missile0_visible = true;
missile0_pixel_counter--;
}
if (missile1_pixel_counter>0) {
missile1_visible = true;
missile1_pixel_counter--;
}
if (ball_pixel_counter>0) {
ball_visible = true;
ball_pixel_counter--;
}
const uint8_t playfield_clock = pixel_clock >> 2;
const uint8_t playfield_shift = playfield_shifts[playfield_reflected?1:0][playfield_clock];
if ( (playfield_bits >> playfield_shift) & 0x01) {
playfield_visible = true;
}
if (missile0_visible && player1_visible) collision_missile0_player1 = true;
if (missile0_visible && player0_visible) collision_missile0_player0 = true;
if (missile1_visible && player0_visible) collision_missile1_player0 = true;
if (missile1_visible && player1_visible) collision_missile1_player1 = true;
if (player0_visible && playfield_visible) collision_player0_playfield = true;
if (player0_visible && ball_visible) collision_player0_ball = true;
if (player1_visible && playfield_visible) collision_player1_playfield = true;
if (player1_visible && ball_visible) collision_player1_ball = true;
if (missile0_visible && playfield_visible) collision_missile0_playfield = true;
if (missile0_visible && ball_visible) collision_missile0_ball = true;
if (missile1_visible && playfield_visible) collision_missile1_playfield = true;
if (missile1_visible && ball_visible) collision_missile1_ball = true;
if (ball_visible && playfield_visible) collision_ball_playfield = true;
if (player0_visible && player1_visible) collision_player0_player1 = true;
if (missile0_visible && missile1_visible) collision_missile0_missile1 = true;
const uint8_t x = pixel_clock;
const uint8_t y = current_scanline-37;
if (playfield_priority) {
if (ball_visible) {
framebuffer[y][x] = playfield_color;
} else if (playfield_visible) {
framebuffer[y][x] = playfield_score ? (x<80 ? player0_color : player1_color) : playfield_color;
} else if (player0_visible || missile0_visible) {
framebuffer[y][x] = player0_color;
} else if (player1_visible || missile1_visible) {
framebuffer[y][x] = player1_color;
} else {
framebuffer[y][x] = background_color;
}
} else {
if (player0_visible || missile0_visible) {
framebuffer[y][x] = player0_color;
} else if (player1_visible || missile1_visible) {
framebuffer[y][x] = player1_color;
} else if (ball_visible) {
framebuffer[y][x] = playfield_color;
} else if (playfield_visible) {
framebuffer[y][x] = playfield_score ? (x<80 ? player0_color : player1_color) : playfield_color;
} else {
framebuffer[y][x] = background_color;
}
}
}
}
@@ -178,14 +253,14 @@ namespace tia
uint8_t read(uint16_t address)
{
switch (address & 0x0f) {
case 0x00: return collisions[0];
case 0x01: return collisions[1];
case 0x02: return collisions[2];
case 0x03: return collisions[3];
case 0x04: return collisions[4];
case 0x05: return collisions[5];
case 0x06: return collisions[6];
case 0x07: return collisions[7];
case 0x00: return (collision_missile0_player1?0x80:0x00) | (collision_missile0_player0?0x40:0x00);
case 0x01: return (collision_missile1_player0?0x80:0x00) | (collision_missile1_player1?0x40:0x00);
case 0x02: return (collision_player0_playfield?0x80:0x00) | (collision_player0_ball?0x40:0x00);
case 0x03: return (collision_player1_playfield?0x80:0x00) | (collision_player1_ball?0x40:0x00);
case 0x04: return (collision_missile0_playfield?0x80:0x00) | (collision_missile0_ball?0x40:0x00);
case 0x05: return (collision_missile1_playfield?0x80:0x00) | (collision_missile1_ball?0x40:0x00);
case 0x06: return (collision_ball_playfield?0x80:0x00);
case 0x07: return (collision_player0_player1?0x80:0x00) | (collision_missile0_missile1?0x40:0x00);
case 0x08: return get_paddle_state(0);
case 0x09: return get_paddle_state(1);
@@ -194,6 +269,7 @@ namespace tia
case 0x0C: return joy0_button_pressed ? 0x00 : 0x80;
case 0x0D: return joy1_button_pressed ? 0x00 : 0x80;
default: return 0x00;
}
}
@@ -205,14 +281,17 @@ namespace tia
// [TODO] Procesar segons l'adreça resultant
switch (address) {
case 0x00: // VSYNC
{
const bool old_vsync = vsync_set;
vsync_set = value & 0x20;
if (old_vsync && !vsync_set) { // Resetejem el frame
current_scanline = 0;
display::redraw();
}
break;
}
case 0x01: // VBLANK
{
bool prev_dump = vblank_dump;
vblank_set = value & 0x20;
vblank_latch = value & 0x40;
@@ -220,9 +299,10 @@ namespace tia
if (prev_dump && !vblank_dump) {
current_frame_cycles = 0;
for (int i = 0; i < 4; ++i) paddle_charge_cycles[i] = static_cast<uint32_t>(paddle_pos[i] * 2400.0f);
}
break;
}
case 0x02: // WSYNC
rdy_low = true;
break;
@@ -232,7 +312,7 @@ namespace tia
rdy_low = false;
break;
case 0x004: // NUSIZ0
case 0x04: // NUSIZ0
missile0_size = 1 << ((value >> 4) & 0x03);
switch (value & 0x07) {
case 0: player0_num_copies = 1; player0_copies_distance = 0; player0_size = 1; break;
@@ -246,7 +326,7 @@ namespace tia
}
break;
case 0x005: // NUSIZ1
case 0x05: // NUSIZ1
missile1_size = 1 << ((value >> 4) & 0x03);
switch (value & 0x07) {
case 0: player1_num_copies = 1; player1_copies_distance = 0; player1_size = 1; break;
@@ -261,13 +341,13 @@ namespace tia
break;
case 0x06: // COLUP0
player0_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break;
player0_color = (value >> 1) & 0x7F; break;
case 0x07: // COLUP1
player1_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break;
player1_color = (value >> 1) & 0x7F; break;
case 0x08: // COLUPF
playfield_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break;
playfield_color = (value >> 1) & 0x7F; break;
case 0x09: // COLUBK
background_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break;
background_color = (value >> 1) & 0x7F; break;
case 0x0A: // CTRLPF
playfield_reflected = value & 0x01;
@@ -357,7 +437,21 @@ namespace tia
player0_hmotion = player1_hmotion = missile0_hmotion = missile1_hmotion = ball_hmotion = 0;
break;
case 0x2C: // CXCLR
for (int i=0;i<8;++i) collisions[i] = 0;
collision_missile0_player1 = false;
collision_missile0_player0 = false;
collision_missile1_player0 = false;
collision_missile1_player1 = false;
collision_player0_playfield = false;
collision_player0_ball = false;
collision_player1_playfield = false;
collision_player1_ball = false;
collision_missile0_playfield = false;
collision_missile0_ball = false;
collision_missile1_playfield = false;
collision_missile1_ball = false;
collision_ball_playfield = false;
collision_player0_player1 = false;
collision_missile0_missile1 = false;
break;
}
}
+2
View File
@@ -10,6 +10,8 @@ namespace tia
bool is_rdy_low();
const uint8_t *get_framebuffer();
namespace audio
{
uint8_t get_sample0();
+172
View File
@@ -0,0 +1,172 @@
#include "ui.h"
namespace ui
{
uint8_t colors[16][3] = {
{0,0,0},
{0,0,128},
{0,128,0},
{0,128,128},
{128,0,0},
{128,0,128},
{255,128,0},
{128,128,128},
{30,30,30},
{0,0,255},
{0,255,0},
{0,255,255},
{255,0,0},
{255,0,255},
{255,255,0},
{255,255,255},
};
SDL_Renderer *ren = nullptr;
SDL_Texture *tex = nullptr;
uint8_t offset_x = 0;
uint8_t offset_y = 0;
bool clicked = false;
void (*dialog)(void) = nullptr;
SDL_Texture * createtexture(SDL_Renderer *renderer)
{
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, SDL_LoadBMP("font.bmp"));
SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
return texture;
}
void setrenderer(SDL_Renderer *renderer, SDL_Texture *texture)
{
ren = renderer;
tex = texture;
offset_x = offset_y = 0;
}
void setoffset(uint8_t x, uint8_t y)
{
offset_x = x;
offset_y = y;
}
void incoffset(uint8_t x, uint8_t y)
{
offset_x += x;
offset_y += y;
}
uint8_t getOffsetX()
{
return offset_x;
}
uint8_t getOffsetY()
{
return offset_y;
}
bool mouseInside(int x, int y, int w, int h)
{
float mxf, myf;
SDL_GetMouseState(&mxf, &myf);
int mx = int(mxf)/CHR_W;
int my = int(myf)/CHR_H;
mx -= offset_x;
my -= offset_y;
return (mx >= x) && (mx < x+w) && (my >= y) && (my < y+h);
}
void panel(int x, int y, int w, int h, const char *title)
{
ui::setoffset(x, y);
ui::box(0,0,w,h,COLOR_WHITE);
ui::printrect(2,0, strlen(title)+2,1, COLOR_DARK);
ui::printtxt(3,0, title, COLOR_WHITE);
ui::incoffset(1, 1);
}
void box(int x, int y, int w, int h, uint8_t color)
{
SDL_FRect rect {float((offset_x+x)*CHR_W)+3, float((offset_y+y)*CHR_H)+6, float(w*CHR_W-6), float(h*CHR_H-13)};
SDL_SetRenderDrawColor(ren, colors[color][0], colors[color][1], colors[color][2], 255);
SDL_RenderRect(ren, &rect);
}
void printrect(int x, int y, int w, int h, uint8_t color)
{
SDL_FRect rect {float(offset_x+x)*CHR_W, float(offset_y+y)*CHR_H, float(w*CHR_W), float(h*CHR_H)};
SDL_SetRenderDrawColor(ren, colors[color][0], colors[color][1], colors[color][2], 255);
SDL_RenderFillRect(ren, &rect);
}
void printvoidrect(int x, int y, int w, int h, uint8_t color)
{
SDL_FRect rect {float(offset_x+x)*CHR_W, float(offset_y+y)*CHR_H, float(w*CHR_W), float(h*CHR_H)};
SDL_SetRenderDrawColor(ren, colors[color][0], colors[color][1], colors[color][2], 255);
SDL_RenderRect(ren, &rect);
}
void printchar(int x, int y, char chr, uint8_t color)
{
if (color != 255) SDL_SetRenderDrawColor(ren, colors[color][0], colors[color][1], colors[color][2], 255);
if (chr==32) return;
if (chr<32 || chr>127) chr = '.';
SDL_FRect src {float((chr-32)&0xf)*CHR_W, float((chr-32)>>4)*CHR_H, float(CHR_W), float(CHR_H)};
SDL_FRect dst {float(offset_x+x)*CHR_W, float(offset_y+y)*CHR_H, float(CHR_W), float(CHR_H)};
SDL_RenderTexture(ren, tex, &src, &dst);
}
void printtxt(int x, int y, const char *text, uint8_t color)
{
SDL_SetTextureColorMod(tex, colors[color][0], colors[color][1], colors[color][2]);
for (int i=0; i<strlen(text);++i) if (text[i]!=32) printchar(x+i, y, text[i]);
}
void placechar(int x, int y, char chr, uint8_t color)
{
if (color != 255) SDL_SetRenderDrawColor(ren, colors[color][0], colors[color][1], colors[color][2], 255);
if (chr==32) return;
if (chr<32 || chr>127) chr = '.';
SDL_FRect src {float((chr-32)&0xf)*CHR_W, float((chr-32)>>4)*CHR_H, float(CHR_W), float(CHR_H)};
SDL_FRect dst {float(x), float(y), float(CHR_W*2), float(CHR_H*2)};
SDL_RenderTexture(ren, tex, &src, &dst);
}
void placetxt(int x, int y, const char *text, uint8_t color)
{
SDL_SetTextureColorMod(tex, colors[color][0], colors[color][1], colors[color][2]);
for (int i=0; i<strlen(text);++i) if (text[i]!=32) placechar(x+i*CHR_W*2, y, text[i]);
}
void setClicked(const bool value)
{
clicked = value;
}
const bool getClicked()
{
return clicked;
}
void setDialog(void(*new_dialog)(void))
{
ui:dialog = new_dialog;
}
bool hasDialog()
{
return dialog != nullptr;
}
void callDialog()
{
if (dialog) dialog();
}
}
+50
View File
@@ -0,0 +1,50 @@
#pragma once
#include <SDL3/SDL.h>
namespace ui
{
#define CHR_W 6
#define CHR_H 13
#define COLOR_BLACK 0
#define COLOR_DARK_BLUE 1
#define COLOR_GREEN 2
#define COLOR_TEAL 3
#define COLOR_BROWN 4
#define COLOR_PURPLE 5
#define COLOR_ORANGE 6
#define COLOR_GRAY 7
#define COLOR_DARK 8
#define COLOR_BLUE 9
#define COLOR_LIME 10
#define COLOR_CYAN 11
#define COLOR_RED 12
#define COLOR_MAGENTA 13
#define COLOR_YELLOW 14
#define COLOR_WHITE 15
SDL_Texture * createtexture(SDL_Renderer *renderer);
void setrenderer(SDL_Renderer *renderer, SDL_Texture *texture);
void setoffset(uint8_t x, uint8_t y);
void incoffset(uint8_t x, uint8_t y);
uint8_t getOffsetX();
uint8_t getOffsetY();
bool mouseInside(int x, int y, int w, int h);
void panel(int x, int y, int w, int h, const char *title);
void box(int x, int y, int w, int h, uint8_t color);
void printrect(int x, int y, int w, int h, uint8_t color);
void printvoidrect(int x, int y, int w, int h, uint8_t color);
void printchar(int x, int y, char chr, uint8_t color=255);
void printtxt(int x, int y, const char *text, uint8_t color);
void placechar(int x, int y, char chr, uint8_t color=255);
void placetxt(int x, int y, const char *text, uint8_t color);
void setClicked(const bool value);
const bool getClicked();
void setDialog(void(*new_dialog)(void));
bool hasDialog();
void callDialog();
}
+33
View File
@@ -0,0 +1,33 @@
#include "ui_window.h"
#include <vector>
namespace ui
{
namespace window
{
struct window_t
{
Uint32 window;
bool (*callback)(SDL_Event*);
};
std::vector<window_t> windows;
void registerWindow(Uint32 window, bool(*callback)(SDL_Event*))
{
for (auto win : windows) if (win.window == window) return;
windows.push_back((window_t){window, callback});
}
void unregisterWindow(Uint32 window)
{
for (auto win = windows.begin(); win != windows.end(); win++) if ((*win).window == window) { windows.erase(win); return; }
}
bool sendEvent(Uint32 window, SDL_Event *e)
{
for (auto win : windows) if (win.window == window) return win.callback(e);
return true;
}
}
}
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include <SDL3/SDL.h>
namespace ui
{
namespace window
{
void registerWindow(Uint32 window, bool(*callback)(SDL_Event *e));
void unregisterWindow(Uint32 window);
bool sendEvent(Uint32 window, SDL_Event *e);
}
}
+1212
View File
File diff suppressed because it is too large Load Diff
+71
View File
@@ -0,0 +1,71 @@
#pragma once
#include <stdint.h>
namespace z80debugger
{
#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 show();
void focus();
void hide();
void pause();
void stop();
void cont();
void setmemmodified(const uint16_t addr);
void refresh();
void sendToConsole(const char* text);
void sendToConsoleLog(const char *text);
void sendMoreToConsoleLog(const char *text);
void DeleteCharConsole();
void executeConsole();
const bool isbreak(const uint16_t address, const uint8_t type=1);
uint32_t next();
uint32_t stepout();
void savestate(const char *filename);
void loadstate(const char *filename);
void loadngo(const char* filename, const char* addr);
void setcursor(const uint16_t address);
void cursorfwd();
void cursorback();
void useOpcode(const uint8_t opcode, const uint8_t base);
void clearUsedOpcodes();
void markUsedOpcodes();
const int getNumOpcodesUsed();
void printOpcodesUsed();
void search(const char *seq=nullptr);
namespace history
{
void reset();
void store();
void gototop();
void goforward();
void goback();
}
}
+241
View File
File diff suppressed because one or more lines are too long
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <stdint.h>
namespace z80dis
{
void loadSymbols();
void saveSymbols();
const char *getAsm(const uint16_t pos);
const char *getOpcode(const uint16_t pos);
const int getOpcodeSize(const uint16_t pos);
const char *getSymbol(const uint16_t pos);
void setSymbol(const uint16_t pos, const char *sym);
const int getNumSymbols();
const uint16_t getSymbolAddress(const int pos);
}