-[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:
+3
-1
@@ -1 +1,3 @@
|
|||||||
nes
|
atari2600
|
||||||
|
atari2600_debug
|
||||||
|
build/*
|
||||||
|
|||||||
+4
-2
@@ -4,13 +4,15 @@ libs = -Wl,--gc-sections -lSDL3
|
|||||||
executable = atari2600
|
executable = atari2600
|
||||||
sourcepath = source+
|
sourcepath = source+
|
||||||
buildpath = build
|
buildpath = build
|
||||||
|
exclude = z80*
|
||||||
|
|
||||||
[linux_debug] default
|
[linux_debug] default
|
||||||
cppflags = -D DEBUG -g -Wall -std=c++20 -Isource
|
cppflags = -D DEBUG -g -std=c++20 -Isource
|
||||||
libs = -lSDL3 -lGL
|
libs = -lSDL3
|
||||||
executable = atari2600_debug
|
executable = atari2600_debug
|
||||||
sourcepath = source+
|
sourcepath = source+
|
||||||
buildpath = build
|
buildpath = build
|
||||||
|
exclude = z80*
|
||||||
|
|
||||||
[windows]
|
[windows]
|
||||||
cppflags = -Wall -Os -ffunction-sections -fdata-sections -std=c++20 -Isource
|
cppflags = -Wall -Os -ffunction-sections -fdata-sections -std=c++20 -Isource
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ namespace atari2600
|
|||||||
|
|
||||||
void step()
|
void step()
|
||||||
{
|
{
|
||||||
uint8_t t_states;
|
//uint8_t t_states;
|
||||||
uint16_t pc = m6502::getPC();
|
//uint16_t pc = m6502::getPC();
|
||||||
|
|
||||||
// if (z80debugger::isbreak(pc, 9)) {
|
// if (z80debugger::isbreak(pc, 9)) {
|
||||||
// msx::pause();
|
// msx::pause();
|
||||||
@@ -59,7 +59,7 @@ namespace atari2600
|
|||||||
tia::tick();
|
tia::tick();
|
||||||
tia::tick();
|
tia::tick();
|
||||||
pia::tick();
|
pia::tick();
|
||||||
t_states++;
|
//t_states++;
|
||||||
}
|
}
|
||||||
//speaker::update(t_states);
|
//speaker::update(t_states);
|
||||||
// }
|
// }
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -32,9 +32,15 @@ namespace pia
|
|||||||
// I/O Ports
|
// I/O Ports
|
||||||
switch( address & 0x03) {
|
switch( address & 0x03) {
|
||||||
case 0x00: // [TODO] SWCHA
|
case 0x00: // [TODO] SWCHA
|
||||||
|
return 0x00;
|
||||||
case 0x01: // [TODO] DDRA
|
case 0x01: // [TODO] DDRA
|
||||||
|
return 0x00;
|
||||||
case 0x02: // [TODO] SWCHB
|
case 0x02: // [TODO] SWCHB
|
||||||
|
return 0x00;
|
||||||
case 0x03: // [TODO] DDRB
|
case 0x03: // [TODO] DDRB
|
||||||
|
return 0x00;
|
||||||
|
default:
|
||||||
|
return 0x00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -50,9 +56,13 @@ namespace pia
|
|||||||
// Timer functions
|
// Timer functions
|
||||||
switch( address & 0x03) {
|
switch( address & 0x03) {
|
||||||
case 0x00: // [TODO] TIM1T
|
case 0x00: // [TODO] TIM1T
|
||||||
|
break;
|
||||||
case 0x01: // [TODO] TIM8T
|
case 0x01: // [TODO] TIM8T
|
||||||
|
break;
|
||||||
case 0x02: // [TODO] TIM64T
|
case 0x02: // [TODO] TIM64T
|
||||||
|
break;
|
||||||
case 0x03: // [TODO] TIM1024T
|
case 0x03: // [TODO] TIM1024T
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Funcionalitat relacionada amb les interrupcions. Ignorar per a la Atari 2600
|
// Funcionalitat relacionada amb les interrupcions. Ignorar per a la Atari 2600
|
||||||
@@ -61,9 +71,13 @@ namespace pia
|
|||||||
// I/O Ports
|
// I/O Ports
|
||||||
switch( address & 0x03) {
|
switch( address & 0x03) {
|
||||||
case 0x00: // [TODO] SWCHA
|
case 0x00: // [TODO] SWCHA
|
||||||
|
break;
|
||||||
case 0x01: // [TODO] DDRA
|
case 0x01: // [TODO] DDRA
|
||||||
|
break;
|
||||||
case 0x02: // [TODO] SWCHB
|
case 0x02: // [TODO] SWCHB
|
||||||
|
break;
|
||||||
case 0x03: // [TODO] DDRB
|
case 0x03: // [TODO] DDRB
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
+153
-59
@@ -1,46 +1,24 @@
|
|||||||
#include "tia.h"
|
#include "tia.h"
|
||||||
#include "tia-audio.h"
|
#include "tia-audio.h"
|
||||||
|
#include "display.h"
|
||||||
|
|
||||||
namespace tia
|
namespace tia
|
||||||
{
|
{
|
||||||
// Standard Stella NTSC Palette (ARGB format: 0xFFRRGGBB)
|
bool collision_missile0_player1 = false;
|
||||||
// Indexed by: (COLUx >> 1) & 0x7F
|
bool collision_missile0_player0 = false;
|
||||||
const uint32_t NTSC_PALETTE[128] = {
|
bool collision_missile1_player0 = false;
|
||||||
// Hue $0 (Grayscale / Monochromatic)
|
bool collision_missile1_player1 = false;
|
||||||
0xFF000000, 0xFF282828, 0xFF444444, 0xFF5C5C5C, 0xFF707070, 0xFF848484, 0xFF989898, 0xFFACACAC,
|
bool collision_player0_playfield = false;
|
||||||
// Hue $1 (Gold / Yellow-Orange)
|
bool collision_player0_ball = false;
|
||||||
0xFF4C2C00, 0xFF684400, 0xFF845C00, 0xFF9C7400, 0xFFB48C00, 0xFFCCA414, 0xFFE4BC34, 0xFFFCD454,
|
bool collision_player1_playfield = false;
|
||||||
// Hue $2 (Orange / Red-Orange)
|
bool collision_player1_ball = false;
|
||||||
0xFF541800, 0xFF742C00, 0xFF904400, 0xFFA85C00, 0xFFC07400, 0xFFD88C00, 0xFFF0A420, 0xFFFFBC40,
|
bool collision_missile0_playfield = false;
|
||||||
// Hue $3 (Red-Orange)
|
bool collision_missile0_ball = false;
|
||||||
0xFF580C00, 0xFF781C00, 0xFF943000, 0xFFB04800, 0xFFC86000, 0xFFE07808, 0xFFF89028, 0xFFFFA848,
|
bool collision_missile1_playfield = false;
|
||||||
// Hue $4 (Magenta / Red-Violet)
|
bool collision_missile1_ball = false;
|
||||||
0xFF540420, 0xFF74103C, 0xFF902058, 0xFFAC3474, 0xFFC4488C, 0xFFDC5CA8, 0xFFF474C0, 0xFFFF8CD8,
|
bool collision_ball_playfield = false;
|
||||||
// Hue $5 (Purple / Violet)
|
bool collision_player0_player1 = false;
|
||||||
0xFF440454, 0xFF601074, 0xFF7C2090, 0xFF9434AC, 0xFFAC48C4, 0xFFC45CDC, 0xFFDC74F4, 0xFFF48CFF,
|
bool collision_missile0_missile1 = false;
|
||||||
// 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 };
|
|
||||||
|
|
||||||
float paddle_pos[4] { 0.5f, 0.5f, 0.5f, 0.5f };
|
float paddle_pos[4] { 0.5f, 0.5f, 0.5f, 0.5f };
|
||||||
uint32_t paddle_charge_cycles[4] { 0, 0, 0, 0 };
|
uint32_t paddle_charge_cycles[4] { 0, 0, 0, 0 };
|
||||||
@@ -51,7 +29,7 @@ namespace tia
|
|||||||
uint8_t player0_size = 1;
|
uint8_t player0_size = 1;
|
||||||
uint8_t player0_num_copies = 1;
|
uint8_t player0_num_copies = 1;
|
||||||
uint8_t player0_copies_distance = 0;
|
uint8_t player0_copies_distance = 0;
|
||||||
uint32_t player0_color = 0x00000000;
|
uint8_t player0_color = 0;
|
||||||
bool player0_reflect = false;
|
bool player0_reflect = false;
|
||||||
uint8_t player0_pos = 0;
|
uint8_t player0_pos = 0;
|
||||||
uint8_t player0_bits = 0;
|
uint8_t player0_bits = 0;
|
||||||
@@ -63,7 +41,7 @@ namespace tia
|
|||||||
uint8_t player1_size = 1;
|
uint8_t player1_size = 1;
|
||||||
uint8_t player1_num_copies = 1;
|
uint8_t player1_num_copies = 1;
|
||||||
uint8_t player1_copies_distance = 0;
|
uint8_t player1_copies_distance = 0;
|
||||||
uint32_t player1_color = 0x00000000;
|
uint8_t player1_color = 0;
|
||||||
bool player1_reflect = false;
|
bool player1_reflect = false;
|
||||||
uint8_t player1_pos = 0;
|
uint8_t player1_pos = 0;
|
||||||
uint8_t player1_bits = 0;
|
uint8_t player1_bits = 0;
|
||||||
@@ -94,7 +72,7 @@ namespace tia
|
|||||||
bool ball_vert_delay = false;
|
bool ball_vert_delay = false;
|
||||||
uint8_t ball_pixel_counter = 0;
|
uint8_t ball_pixel_counter = 0;
|
||||||
|
|
||||||
uint32_t playfield_color = 0x00000000;
|
uint8_t playfield_color = 0;
|
||||||
bool playfield_reflected = false;
|
bool playfield_reflected = false;
|
||||||
bool playfield_score = false;
|
bool playfield_score = false;
|
||||||
bool playfield_priority = 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}
|
{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;
|
uint32_t current_frame_cycles = 0;
|
||||||
|
|
||||||
@@ -121,11 +99,18 @@ namespace tia
|
|||||||
uint16_t current_scanline = 0;
|
uint16_t current_scanline = 0;
|
||||||
bool rdy_low = false;
|
bool rdy_low = false;
|
||||||
|
|
||||||
|
uint8_t framebuffer[160][192];
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t *get_framebuffer()
|
||||||
|
{
|
||||||
|
return (const uint8_t*)framebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
void tick()
|
void tick()
|
||||||
{
|
{
|
||||||
if (!vblank_dump) current_frame_cycles++;
|
if (!vblank_dump) current_frame_cycles++;
|
||||||
@@ -164,6 +149,96 @@ namespace tia
|
|||||||
ball_pixel_counter = ball_size;
|
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)
|
uint8_t read(uint16_t address)
|
||||||
{
|
{
|
||||||
switch (address & 0x0f) {
|
switch (address & 0x0f) {
|
||||||
case 0x00: return collisions[0];
|
case 0x00: return (collision_missile0_player1?0x80:0x00) | (collision_missile0_player0?0x40:0x00);
|
||||||
case 0x01: return collisions[1];
|
case 0x01: return (collision_missile1_player0?0x80:0x00) | (collision_missile1_player1?0x40:0x00);
|
||||||
case 0x02: return collisions[2];
|
case 0x02: return (collision_player0_playfield?0x80:0x00) | (collision_player0_ball?0x40:0x00);
|
||||||
case 0x03: return collisions[3];
|
case 0x03: return (collision_player1_playfield?0x80:0x00) | (collision_player1_ball?0x40:0x00);
|
||||||
case 0x04: return collisions[4];
|
case 0x04: return (collision_missile0_playfield?0x80:0x00) | (collision_missile0_ball?0x40:0x00);
|
||||||
case 0x05: return collisions[5];
|
case 0x05: return (collision_missile1_playfield?0x80:0x00) | (collision_missile1_ball?0x40:0x00);
|
||||||
case 0x06: return collisions[6];
|
case 0x06: return (collision_ball_playfield?0x80:0x00);
|
||||||
case 0x07: return collisions[7];
|
case 0x07: return (collision_player0_player1?0x80:0x00) | (collision_missile0_missile1?0x40:0x00);
|
||||||
|
|
||||||
case 0x08: return get_paddle_state(0);
|
case 0x08: return get_paddle_state(0);
|
||||||
case 0x09: return get_paddle_state(1);
|
case 0x09: return get_paddle_state(1);
|
||||||
@@ -194,6 +269,7 @@ namespace tia
|
|||||||
|
|
||||||
case 0x0C: return joy0_button_pressed ? 0x00 : 0x80;
|
case 0x0C: return joy0_button_pressed ? 0x00 : 0x80;
|
||||||
case 0x0D: return joy1_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
|
// [TODO] Procesar segons l'adreça resultant
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case 0x00: // VSYNC
|
case 0x00: // VSYNC
|
||||||
|
{
|
||||||
const bool old_vsync = vsync_set;
|
const bool old_vsync = vsync_set;
|
||||||
vsync_set = value & 0x20;
|
vsync_set = value & 0x20;
|
||||||
if (old_vsync && !vsync_set) { // Resetejem el frame
|
if (old_vsync && !vsync_set) { // Resetejem el frame
|
||||||
current_scanline = 0;
|
current_scanline = 0;
|
||||||
|
display::redraw();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 0x01: // VBLANK
|
case 0x01: // VBLANK
|
||||||
|
{
|
||||||
bool prev_dump = vblank_dump;
|
bool prev_dump = vblank_dump;
|
||||||
vblank_set = value & 0x20;
|
vblank_set = value & 0x20;
|
||||||
vblank_latch = value & 0x40;
|
vblank_latch = value & 0x40;
|
||||||
@@ -220,9 +299,10 @@ namespace tia
|
|||||||
if (prev_dump && !vblank_dump) {
|
if (prev_dump && !vblank_dump) {
|
||||||
current_frame_cycles = 0;
|
current_frame_cycles = 0;
|
||||||
for (int i = 0; i < 4; ++i) paddle_charge_cycles[i] = static_cast<uint32_t>(paddle_pos[i] * 2400.0f);
|
for (int i = 0; i < 4; ++i) paddle_charge_cycles[i] = static_cast<uint32_t>(paddle_pos[i] * 2400.0f);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 0x02: // WSYNC
|
case 0x02: // WSYNC
|
||||||
rdy_low = true;
|
rdy_low = true;
|
||||||
break;
|
break;
|
||||||
@@ -232,7 +312,7 @@ namespace tia
|
|||||||
rdy_low = false;
|
rdy_low = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x004: // NUSIZ0
|
case 0x04: // NUSIZ0
|
||||||
missile0_size = 1 << ((value >> 4) & 0x03);
|
missile0_size = 1 << ((value >> 4) & 0x03);
|
||||||
switch (value & 0x07) {
|
switch (value & 0x07) {
|
||||||
case 0: player0_num_copies = 1; player0_copies_distance = 0; player0_size = 1; break;
|
case 0: player0_num_copies = 1; player0_copies_distance = 0; player0_size = 1; break;
|
||||||
@@ -246,7 +326,7 @@ namespace tia
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x005: // NUSIZ1
|
case 0x05: // NUSIZ1
|
||||||
missile1_size = 1 << ((value >> 4) & 0x03);
|
missile1_size = 1 << ((value >> 4) & 0x03);
|
||||||
switch (value & 0x07) {
|
switch (value & 0x07) {
|
||||||
case 0: player1_num_copies = 1; player1_copies_distance = 0; player1_size = 1; break;
|
case 0: player1_num_copies = 1; player1_copies_distance = 0; player1_size = 1; break;
|
||||||
@@ -261,13 +341,13 @@ namespace tia
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x06: // COLUP0
|
case 0x06: // COLUP0
|
||||||
player0_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break;
|
player0_color = (value >> 1) & 0x7F; break;
|
||||||
case 0x07: // COLUP1
|
case 0x07: // COLUP1
|
||||||
player1_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break;
|
player1_color = (value >> 1) & 0x7F; break;
|
||||||
case 0x08: // COLUPF
|
case 0x08: // COLUPF
|
||||||
playfield_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break;
|
playfield_color = (value >> 1) & 0x7F; break;
|
||||||
case 0x09: // COLUBK
|
case 0x09: // COLUBK
|
||||||
background_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break;
|
background_color = (value >> 1) & 0x7F; break;
|
||||||
|
|
||||||
case 0x0A: // CTRLPF
|
case 0x0A: // CTRLPF
|
||||||
playfield_reflected = value & 0x01;
|
playfield_reflected = value & 0x01;
|
||||||
@@ -357,7 +437,21 @@ namespace tia
|
|||||||
player0_hmotion = player1_hmotion = missile0_hmotion = missile1_hmotion = ball_hmotion = 0;
|
player0_hmotion = player1_hmotion = missile0_hmotion = missile1_hmotion = ball_hmotion = 0;
|
||||||
break;
|
break;
|
||||||
case 0x2C: // CXCLR
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,8 @@ namespace tia
|
|||||||
|
|
||||||
bool is_rdy_low();
|
bool is_rdy_low();
|
||||||
|
|
||||||
|
const uint8_t *get_framebuffer();
|
||||||
|
|
||||||
namespace audio
|
namespace audio
|
||||||
{
|
{
|
||||||
uint8_t get_sample0();
|
uint8_t get_sample0();
|
||||||
+172
@@ -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
@@ -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();
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
File diff suppressed because one or more lines are too long
@@ -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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user