ja tenim el control de la finestra i de la imatge

treballant en les tecles de funcio
This commit is contained in:
2026-04-04 17:20:28 +02:00
parent baee62b375
commit abb23071b5
16 changed files with 249 additions and 318 deletions

View File

@@ -0,0 +1,37 @@
#include "core/global_inputs.hpp"
#include <SDL3/SDL.h>
#include "core/jinput.hpp"
#include "core/screen.hpp"
namespace GlobalInputs {
static bool f1_was_pressed = false;
static bool f2_was_pressed = false;
static bool f3_was_pressed = false;
void handle() {
// F1 — decrement zoom
bool f1 = JI_KeyPressed(SDL_SCANCODE_F1);
if (f1 && !f1_was_pressed) {
Screen::get()->decZoom();
}
f1_was_pressed = f1;
// F2 — increment zoom
bool f2 = JI_KeyPressed(SDL_SCANCODE_F2);
if (f2 && !f2_was_pressed) {
Screen::get()->incZoom();
}
f2_was_pressed = f2;
// F3 — toggle fullscreen
bool f3 = JI_KeyPressed(SDL_SCANCODE_F3);
if (f3 && !f3_was_pressed) {
Screen::get()->toggleFullscreen();
}
f3_was_pressed = f3;
}
} // namespace GlobalInputs

View File

@@ -0,0 +1,6 @@
#pragma once
namespace GlobalInputs {
// Comprovar una vegada per frame, després de JI_Update()
void handle();
} // namespace GlobalInputs

View File

@@ -3,54 +3,23 @@
#include <fstream>
#include "core/jfile.hpp"
#include "core/jshader.hpp"
#include "core/screen.hpp"
#include "external/gif.h"
#define SCREEN_WIDTH 960
#define SCREEN_HEIGHT 720
JD8_Surface screen = NULL;
JD8_Palette main_palette = NULL;
Uint32 *pixel_data = NULL;
int screenWidth = 320;
int screenHeight = 200;
Uint32 contadorFPS = 0;
Uint32 tempsFPS = SDL_GetTicks();
char *fps = (char *)malloc(10);
SDL_Window *sdlWindow = NULL;
SDL_Renderer *sdlRenderer = NULL;
SDL_Texture *sdlTexture = NULL;
SDL_Texture *backBuffer = NULL;
void JD8_Init(const char *title) {
void JD8_Init() {
screen = (JD8_Surface)calloc(1, 64000);
main_palette = (JD8_Palette)calloc(1, 768);
pixel_data = (Uint32 *)calloc(1, 320 * 200 * 4); // 1048576 );
sdlWindow = SDL_CreateWindow(title, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL);
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
// SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
sdlRenderer = SDL_CreateRenderer(sdlWindow, NULL);
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, 320, 200);
backBuffer = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 320, 200);
int filesize = 0;
char *buffer = file_getfilebuffer("crtpi.glsl", filesize, true);
shader::init(sdlWindow, backBuffer, buffer);
free(buffer);
pixel_data = (Uint32 *)calloc(1, 320 * 200 * 4);
}
void JD8_Quit() {
if (screen != NULL) free(screen);
if (main_palette != NULL) free(main_palette);
if (pixel_data != NULL) free(pixel_data);
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow(sdlWindow);
}
void JD8_ClearScreen(Uint8 color) {
@@ -177,8 +146,6 @@ void JD8_BlitCKToSurface(int x, int y, JD8_Surface surface, int sx, int sy, int
}
}
SDL_Rect rect{0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
void JD8_Flip() {
for (int x = 0; x < 320; x++) {
for (int y = 0; y < 200; y++) {
@@ -186,11 +153,7 @@ void JD8_Flip() {
pixel_data[x + (y * 320)] = color;
}
}
SDL_UpdateTexture(sdlTexture, NULL, pixel_data, 320 * sizeof(Uint32));
SDL_SetRenderTarget(sdlRenderer, backBuffer);
SDL_RenderTexture(sdlRenderer, sdlTexture, NULL, NULL);
shader::render();
// SDL_RenderPresent(sdlRenderer);
Screen::get()->present(pixel_data);
}
void JD8_FreeSurface(JD8_Surface surface) {

View File

@@ -10,7 +10,7 @@ struct Color {
typedef Uint8 *JD8_Surface;
typedef Color *JD8_Palette;
void JD8_Init(const char *title);
void JD8_Init();
void JD8_Quit();

View File

@@ -2,6 +2,7 @@
#include <string>
#include "core/global_inputs.hpp"
#include "core/jgame.hpp"
const bool* keystates; // = SDL_GetKeyboardState( NULL );
@@ -35,6 +36,8 @@ void JI_Update() {
JI_moveCheats(event.key.scancode);
}
}
GlobalInputs::handle();
}
bool JI_KeyPressed(int key) {

View File

@@ -1,225 +0,0 @@
#include "core/jshader.hpp"
#include <iostream>
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include "CoreFoundation/CoreFoundation.h"
#if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#include <OpenGL/gl3.h>
#else
#include <OpenGL/gl.h>
#endif //! ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#else
#include <SDL3/SDL_opengl.h>
#include <SDL3/SDL_opengl_glext.h>
#endif
namespace shader {
SDL_Window* win = nullptr;
SDL_Renderer* renderer = nullptr;
GLuint programId = 0;
SDL_Texture* backBuffer = nullptr;
SDL_Point win_size = {640, 480};
SDL_FPoint tex_size = {320, 240};
bool usingOpenGL;
GLuint texture_number;
GLuint nose;
#ifndef __APPLE__
// I'm avoiding the use of GLEW or some extensions handler, but that
// doesn't mean you should...
PFNGLCREATESHADERPROC glCreateShader;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLGETSHADERIVPROC glGetShaderiv;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
PFNGLDELETESHADERPROC glDeleteShader;
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLVALIDATEPROGRAMPROC glValidateProgram;
PFNGLGETPROGRAMIVPROC glGetProgramiv;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLUSEPROGRAMPROC glUseProgram;
bool initGLExtensions() {
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
glGetShaderiv = (PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog");
glDeleteShader = (PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader");
glAttachShader = (PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader");
glCreateProgram = (PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram");
glLinkProgram = (PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram");
glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)SDL_GL_GetProcAddress("glValidateProgram");
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv");
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)SDL_GL_GetProcAddress("glGetProgramInfoLog");
glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram");
return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv &&
glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram &&
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
glUseProgram;
}
#endif
GLuint compileShader(const char* source, GLuint shaderType) {
// Create ID for shader
GLuint result = glCreateShader(shaderType);
// Add define depending on shader type
const char* sources[2] = {shaderType == GL_VERTEX_SHADER ? "#define VERTEX\n" : "#define FRAGMENT\n", source};
// Define shader text
glShaderSource(result, 2, sources, NULL);
// Compile shader
glCompileShader(result);
// Check vertex shader for errors
GLint shaderCompiled = GL_FALSE;
glGetShaderiv(result, GL_COMPILE_STATUS, &shaderCompiled);
if (shaderCompiled != GL_TRUE) {
std::cout << "Error en la compilación: " << result << "!" << std::endl;
GLint logLength;
glGetShaderiv(result, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar* log = (GLchar*)malloc(logLength);
glGetShaderInfoLog(result, logLength, &logLength, log);
std::cout << "Shader compile log:" << log << std::endl;
free(log);
}
glDeleteShader(result);
result = 0;
}
return result;
}
GLuint compileProgram(const char* vertexShaderSource, const char* fragmentShaderSource) {
GLuint programId = 0;
GLuint vtxShaderId, fragShaderId;
programId = glCreateProgram();
vtxShaderId = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
fragShaderId = compileShader(fragmentShaderSource ? fragmentShaderSource : vertexShaderSource, GL_FRAGMENT_SHADER);
if (vtxShaderId && fragShaderId) {
// Associate shader with program
glAttachShader(programId, vtxShaderId);
glAttachShader(programId, fragShaderId);
glLinkProgram(programId);
glValidateProgram(programId);
// Check the status of the compile/link
GLint logLen;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);
if (logLen > 0) {
char* log = (char*)malloc(logLen * sizeof(char));
// Show any errors as appropriate
glGetProgramInfoLog(programId, logLen, &logLen, log);
std::cout << "Prog Info Log: " << std::endl
<< log << std::endl;
free(log);
}
}
if (vtxShaderId) glDeleteShader(vtxShaderId);
if (fragShaderId) glDeleteShader(fragShaderId);
return programId;
}
const bool init(SDL_Window* win, SDL_Texture* backBuffer, const char* vertexShader, const char* fragmentShader) {
shader::win = win;
shader::renderer = SDL_GetRenderer(win);
shader::backBuffer = backBuffer;
SDL_GetWindowSize(win, &win_size.x, &win_size.y);
SDL_GetTextureSize(backBuffer, &tex_size.x, &tex_size.y);
printf("tex size: %fx%f\n", tex_size.x, tex_size.y);
SDL_PropertiesID props = SDL_GetTextureProperties(backBuffer);
texture_number = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_NUMBER, -1);
printf("texture number: %i\n", texture_number);
int access = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_ACCESS_NUMBER, -1);
nose = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_TARGET_NUMBER, -1);
printf("texture target number: %i\n", nose);
if (access != SDL_TEXTUREACCESS_TARGET) {
std::cout << "ERROR FATAL: La textura per al render ha de tindre SDL_TEXTUREACCESS_TARGET definit." << std::endl;
exit(1);
}
const char* renderer_name = SDL_GetRendererName(renderer);
printf("rendererInfo.name: %s\n", renderer_name);
if (!strncmp(renderer_name, "opengl", 6)) {
#ifndef __APPLE__
if (!initGLExtensions()) {
std::cout << "WARNING: No s'han pogut inicialitzar les extensions d'OpenGL!" << std::endl;
usingOpenGL = false;
return false;
}
#endif
// Compilar el shader y dejarlo listo para usar.
programId = compileProgram(vertexShader, fragmentShader);
} else {
std::cout << "WARNING: El driver del renderer no es OpenGL." << std::endl;
usingOpenGL = false;
return false;
}
usingOpenGL = true;
return true;
}
unsigned char pixels[512 * 240 * 4];
void render() {
SDL_FlushRenderer(renderer);
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_FlushRenderer(renderer);
if (usingOpenGL) {
GLint oldProgramId;
if (programId != 0) {
glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgramId);
glUseProgram(programId);
}
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 1);
// glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
// if (glGetError()) { printf("GLGETERROR!\n"); exit(1);}
// GLint param;
// glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &param);
// printf("tex width: %i\n", param);
glViewport(0, 0, win_size.x, win_size.y);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(tex_size.x, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(0.0f, tex_size.y);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(tex_size.x, tex_size.y);
glEnd();
SDL_GL_SwapWindow(win);
if (programId != 0) glUseProgram(oldProgramId);
} else {
SDL_RenderTexture(renderer, backBuffer, NULL, NULL);
SDL_RenderPresent(renderer);
}
if (glGetError()) {
printf("GLERROR!\n");
exit(1);
}
}
} // namespace shader

View File

@@ -1,42 +0,0 @@
#pragma once
#include <SDL3/SDL.h>
// TIPS:
// =======================================================================
// Abans de crear el renderer, cridar a la següent funció:
//
// SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
//
// Aixó li diu que volem un renderer que use especificament opengl. A més,
// al crear el renderer li tenim que dir que el volem que use acceeració
// per hardware, i que soporte render a textura. Per exemple:
//
// SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED |
// SDL_RENDERER_TARGETTEXTURE);
//
// Per altra part, al crear la textura tenim que definir que puga ser target
// de renderitzat (SDL_TEXTUREACCESS_TARGET), per exemple:
//
// SDL_Texture *tex = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
// SDL_TEXTUREACCESS_TARGET, 320, 240);
//
// Els shaders li'ls passem com una cadena, som nosaltres els que s'encarreguem
// de carregarlos de disc, amb fopen, ifstream, jfile o el que vullgues.
// Si els tens en un std::string, passa-li-la com "cadena.c_str()".
//
// Poden ser els dos el mateix arxiu, com fa libRetro, jo desde dins ja fique
// els defines necessaris. Si es el mateix arxiu, pots no ficar el quart paràmetre.
//
// Els shaders de libRetro no funcionen directament, hi ha que fer algunes modificacions.
//
// El pintat final de la teua escena l'has de fer com si "backBuffer" fora la pantalla.
//
// Ah! una cosa mes: al compilar, en Linux afegir "-lGL", en Windows afegir "-lopengl32".
// En Mac ni idea
namespace shader {
const bool init(SDL_Window* win, SDL_Texture* backBuffer, const char* vertexShader, const char* fragmentShader = nullptr);
void render();
} // namespace shader

106
source/core/screen.cpp Normal file
View File

@@ -0,0 +1,106 @@
#include "core/screen.hpp"
#include <iostream>
#include "game/defines.hpp"
#include "game/options.hpp"
Screen* Screen::instance_ = nullptr;
void Screen::init() {
instance_ = new Screen();
}
void Screen::destroy() {
delete instance_;
instance_ = nullptr;
}
auto Screen::get() -> Screen* {
return instance_;
}
Screen::Screen() {
// Carrega opcions guardades
zoom_ = Options::window.zoom;
fullscreen_ = Options::window.fullscreen;
calculateMaxZoom();
if (zoom_ < 1) zoom_ = 1;
if (zoom_ > max_zoom_) zoom_ = max_zoom_;
int w = GAME_WIDTH * zoom_;
int h = GAME_HEIGHT * zoom_;
window_ = SDL_CreateWindow(Texts::WINDOW_TITLE, w, h, fullscreen_ ? SDL_WINDOW_FULLSCREEN : 0);
renderer_ = SDL_CreateRenderer(window_, nullptr);
SDL_SetRenderLogicalPresentation(renderer_, GAME_WIDTH, GAME_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, GAME_WIDTH, GAME_HEIGHT);
SDL_SetTextureScaleMode(texture_, SDL_SCALEMODE_NEAREST);
std::cout << "Screen initialized: " << w << "x" << h << " (zoom " << zoom_ << ", max " << max_zoom_ << ")\n";
}
Screen::~Screen() {
// Guarda opcions abans de destruir
Options::window.zoom = zoom_;
Options::window.fullscreen = fullscreen_;
if (texture_) SDL_DestroyTexture(texture_);
if (renderer_) SDL_DestroyRenderer(renderer_);
if (window_) SDL_DestroyWindow(window_);
}
void Screen::present(const Uint32* pixel_data) {
SDL_UpdateTexture(texture_, nullptr, pixel_data, GAME_WIDTH * sizeof(Uint32));
SDL_RenderClear(renderer_);
SDL_RenderTexture(renderer_, texture_, nullptr, nullptr);
SDL_RenderPresent(renderer_);
}
void Screen::toggleFullscreen() {
fullscreen_ = !fullscreen_;
SDL_SetWindowFullscreen(window_, fullscreen_);
if (!fullscreen_) {
adjustWindowSize();
}
std::cout << (fullscreen_ ? "Fullscreen ON\n" : "Fullscreen OFF\n");
}
void Screen::incZoom() {
if (fullscreen_ || zoom_ >= max_zoom_) return;
zoom_++;
adjustWindowSize();
}
void Screen::decZoom() {
if (fullscreen_ || zoom_ <= 1) return;
zoom_--;
adjustWindowSize();
}
void Screen::setZoom(int zoom) {
if (zoom < 1 || zoom > max_zoom_ || fullscreen_) return;
zoom_ = zoom;
adjustWindowSize();
}
void Screen::adjustWindowSize() {
int w = GAME_WIDTH * zoom_;
int h = GAME_HEIGHT * zoom_;
SDL_SetWindowSize(window_, w, h);
SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
}
void Screen::calculateMaxZoom() {
SDL_DisplayID display = SDL_GetPrimaryDisplay();
const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(display);
if (mode) {
int max_w = mode->w / GAME_WIDTH;
int max_h = mode->h / GAME_HEIGHT;
max_zoom_ = (max_w < max_h) ? max_w : max_h;
if (max_zoom_ < 1) max_zoom_ = 1;
}
}

47
source/core/screen.hpp Normal file
View File

@@ -0,0 +1,47 @@
#pragma once
#include <SDL3/SDL.h>
#include <cstdint>
class Screen {
public:
static void init();
static void destroy();
static auto get() -> Screen*;
// Presentació — rep el buffer ARGB de 320x200 de JD8
void present(const Uint32* pixel_data);
// Gestió de finestra
void toggleFullscreen();
void incZoom();
void decZoom();
void setZoom(int zoom);
// Getters
[[nodiscard]] auto isFullscreen() const -> bool { return fullscreen_; }
[[nodiscard]] auto getZoom() const -> int { return zoom_; }
[[nodiscard]] auto getWindow() -> SDL_Window* { return window_; }
[[nodiscard]] auto getRenderer() -> SDL_Renderer* { return renderer_; }
private:
Screen();
~Screen();
void adjustWindowSize();
void calculateMaxZoom();
static Screen* instance_;
SDL_Window* window_{nullptr};
SDL_Renderer* renderer_{nullptr};
SDL_Texture* texture_{nullptr}; // 320x200 streaming, ARGB8888
int zoom_{3};
int max_zoom_{6};
bool fullscreen_{false};
static constexpr int GAME_WIDTH = 320;
static constexpr int GAME_HEIGHT = 200;
};