- Jo que se, moltes coses

This commit is contained in:
2024-01-29 06:59:46 +01:00
parent a690619865
commit 3832fdf5e4
13 changed files with 1068 additions and 399 deletions

20
crt.cpp
View File

@@ -1,5 +1,25 @@
#include "crt.h"
#include <time.h>
#include "jinput.h"
void update()
{
SDL_Event e;
while(SDL_PollEvent(&e))
{
if (e.type==SDL_QUIT) { exit(0); }
if (e.type==SDL_KEYDOWN)
{
if (input::getKey() == SDL_SCANCODE_UNKNOWN)
input::updateKey(e.key.keysym.scancode);
}
if (e.type==SDL_KEYUP)
{
if (input::getKey() == e.key.keysym.scancode)
input::updateKey(SDL_SCANCODE_UNKNOWN);
}
}
}
uint8_t get_hours()
{

4
crt.h
View File

@@ -1,5 +1,9 @@
#pragma once
#include <stdint.h>
#include <stdio.h>
#include <SDL2/SDL.h>
void update();
uint8_t get_hours();

35
datos/convert.cpp Normal file
View File

@@ -0,0 +1,35 @@
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *f = fopen("graf.mif", "rb");
fseek(f, 0, SEEK_END);
int size = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buffer = (unsigned char*)malloc(size);
fread(buffer, size, 1, f);
fclose(f);
unsigned char *p = buffer;
int num_img = *p++;
p += num_img*8;
for (int i=0; i<num_img; ++i)
{
p += 64000;
for (int j=0; j<768; ++j)
{
unsigned char color = *p;
*p = color << 2;
p++;
}
}
f = fopen("graf.mif", "wb");
fwrite(buffer, size, 1, f);
fclose(f);
free(buffer);
return 0;
}

File diff suppressed because one or more lines are too long

BIN
datos/sprites.dat Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

4
dos.h
View File

@@ -1,4 +0,0 @@
#pragma once
#include <stdint.h>
#include <stdio.h>

479
gif.c Normal file
View File

@@ -0,0 +1,479 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdint.h>
#define EXTENSION_INTRODUCER 0x21
#define IMAGE_DESCRIPTOR 0x2C
#define TRAILER 0x3B
#define GRAPHIC_CONTROL 0xF9
#define APPLICATION_EXTENSION 0xFF
#define COMMENT_EXTENSION 0xFE
#define PLAINTEXT_EXTENSION 0x01
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
typedef struct
{
unsigned short width;
unsigned short height;
unsigned char fields;
unsigned char background_color_index;
unsigned char pixel_aspect_ratio;
}
screen_descriptor_t;
typedef struct
{
unsigned char r;
unsigned char g;
unsigned char b;
}
rgb;
typedef struct
{
unsigned short image_left_position;
unsigned short image_top_position;
unsigned short image_width;
unsigned short image_height;
unsigned char fields;
}
image_descriptor_t;
typedef struct
{
unsigned char byte;
int prev;
int len;
}
dictionary_entry_t;
typedef struct
{
unsigned char extension_code;
unsigned char block_size;
}
extension_t;
typedef struct
{
unsigned char fields;
unsigned short delay_time;
unsigned char transparent_color_index;
}
graphic_control_extension_t;
typedef struct
{
unsigned char application_id[ 8 ];
unsigned char version[ 3 ];
}
application_extension_t;
typedef struct
{
unsigned short left;
unsigned short top;
unsigned short width;
unsigned short height;
unsigned char cell_width;
unsigned char cell_height;
unsigned char foreground_color;
unsigned char background_color;
}
plaintext_extension_t;
//static unsigned short width = 0;
//static unsigned short height = 0;
//static unsigned char* uncompressed_data = NULL;
void uncompress( int code_length,
const unsigned char *input,
int input_length,
unsigned char *out )
{
//int maxbits;
int i, bit;
int code, prev = -1;
dictionary_entry_t *dictionary;
int dictionary_ind;
unsigned int mask = 0x01;
int reset_code_length;
int clear_code; // This varies depending on code_length
int stop_code; // one more than clear code
int match_len;
clear_code = 1 << ( code_length );
stop_code = clear_code + 1;
// To handle clear codes
reset_code_length = code_length;
// Create a dictionary large enough to hold "code_length" entries.
// Once the dictionary overflows, code_length increases
dictionary = ( dictionary_entry_t * )
malloc( sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
// Initialize the first 2^code_len entries of the dictionary with their
// indices. The rest of the entries will be built up dynamically.
// Technically, it shouldn't be necessary to initialize the
// dictionary. The spec says that the encoder "should output a
// clear code as the first code in the image data stream". It doesn't
// say must, though...
for ( dictionary_ind = 0;
dictionary_ind < ( 1 << code_length );
dictionary_ind++ )
{
dictionary[ dictionary_ind ].byte = dictionary_ind;
// XXX this only works because prev is a 32-bit int (> 12 bits)
dictionary[ dictionary_ind ].prev = -1;
dictionary[ dictionary_ind ].len = 1;
}
// 2^code_len + 1 is the special "end" code; don't give it an entry here
dictionary_ind++;
dictionary_ind++;
// TODO verify that the very last byte is clear_code + 1
while ( input_length )
{
code = 0x0;
// Always read one more bit than the code length
for ( i = 0; i < ( code_length + 1 ); i++ )
{
// This is different than in the file read example; that
// was a call to "next_bit"
bit = ( *input & mask ) ? 1 : 0;
mask <<= 1;
if ( mask == 0x100 )
{
mask = 0x01;
input++;
input_length--;
}
code = code | ( bit << i );
}
if ( code == clear_code )
{
code_length = reset_code_length;
dictionary = ( dictionary_entry_t * ) realloc( dictionary,
sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
for ( dictionary_ind = 0;
dictionary_ind < ( 1 << code_length );
dictionary_ind++ )
{
dictionary[ dictionary_ind ].byte = dictionary_ind;
// XXX this only works because prev is a 32-bit int (> 12 bits)
dictionary[ dictionary_ind ].prev = -1;
dictionary[ dictionary_ind ].len = 1;
}
dictionary_ind++;
dictionary_ind++;
prev = -1;
continue;
}
else if ( code == stop_code )
{
/*if ( input_length > 1 )
{
fprintf( stderr, "Malformed GIF (early stop code)\n" );
exit( 0 );
}*/
break;
}
// Update the dictionary with this character plus the _entry_
// (character or string) that came before it
if ( ( prev > -1 ) && ( code_length < 12 ) )
{
if ( code > dictionary_ind )
{
fprintf( stderr, "code = %.02x, but dictionary_ind = %.02x\n",
code, dictionary_ind );
exit( 0 );
}
// Special handling for KwKwK
if ( code == dictionary_ind )
{
int ptr = prev;
while ( dictionary[ ptr ].prev != -1 )
{
ptr = dictionary[ ptr ].prev;
}
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
}
else
{
int ptr = code;
while ( dictionary[ ptr ].prev != -1 )
{
ptr = dictionary[ ptr ].prev;
}
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
}
dictionary[ dictionary_ind ].prev = prev;
dictionary[ dictionary_ind ].len = dictionary[ prev ].len + 1;
dictionary_ind++;
// GIF89a mandates that this stops at 12 bits
if ( ( dictionary_ind == ( 1 << ( code_length + 1 ) ) ) &&
( code_length < 11 ) )
{
code_length++;
dictionary = ( dictionary_entry_t * ) realloc( dictionary,
sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
}
}
prev = code;
// Now copy the dictionary entry backwards into "out"
match_len = dictionary[ code ].len;
while ( code != -1 )
{
out[ dictionary[ code ].len - 1 ] = dictionary[ code ].byte;
if ( dictionary[ code ].prev == code )
{
fprintf( stderr, "Internal error; self-reference." );
exit( 0 );
}
code = dictionary[ code ].prev;
}
out += match_len;
}
}
static int read_sub_blocks( unsigned char* buffer, unsigned char **data )
{
int data_length;
int index;
unsigned char block_size;
// Everything following are data sub-blocks, until a 0-sized block is
// encountered.
data_length = 0;
*data = NULL;
index = 0;
while ( 1 )
{
READ(&block_size, 1);
if ( block_size == 0 ) // end of sub-blocks
{
break;
}
data_length += block_size;
*data = (unsigned char*)realloc( *data, data_length );
// TODO this could be split across block size boundaries
READ(*data + index, block_size);
index += block_size;
}
return data_length;
}
unsigned char* process_image_descriptor( unsigned char* buffer,
rgb *gct,
int gct_size,
int resolution_bits )
{
image_descriptor_t image_descriptor;
int compressed_data_length;
unsigned char *compressed_data = NULL;
unsigned char lzw_code_size;
int uncompressed_data_length = 0;
unsigned char *uncompressed_data = NULL;
// TODO there could actually be lots of these
READ(&image_descriptor, 9);
// TODO if LCT = true, read the LCT
READ(&lzw_code_size, 1);
compressed_data_length = read_sub_blocks( buffer, &compressed_data );
// width = image_descriptor.image_width;
// height = image_descriptor.image_height;
uncompressed_data_length = image_descriptor.image_width *
image_descriptor.image_height;
uncompressed_data = (unsigned char*)malloc( uncompressed_data_length );
uncompress( lzw_code_size, compressed_data, compressed_data_length,
uncompressed_data );
if ( compressed_data ) free( compressed_data );
//if ( uncompressed_data )
// free( uncompressed_data );
return uncompressed_data;
}
/**
* @param gif_file the file descriptor of a file containing a
* GIF-encoded file. This should point to the first byte in
* the file when invoked.
*/
#define rb (*(buffer++))
uint32_t* LoadPalette(unsigned char *buffer) {
unsigned char header[7];
screen_descriptor_t screen_descriptor;
//int color_resolution_bits;
int global_color_table_size = 0; // number of entries in global_color_table
uint32_t *global_color_table = NULL;
READ(header, 6);
READ(&screen_descriptor, 7);
//color_resolution_bits = ((screen_descriptor.fields & 0x70) >> 4) + 1;
global_color_table = (uint32_t *)calloc(1, 1024);
if (screen_descriptor.fields & 0x80) {
global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
//global_color_table = (rgb *)malloc(3 * global_color_table_size);
//READ(global_color_table, 3 * global_color_table_size);
for (int i=0; i<global_color_table_size;++i) {
global_color_table[i] = (buffer[0]<<16) + (buffer[1]<<8) + buffer[2];
buffer+=3;
}
}
return global_color_table;
}
static unsigned char* process_gif_stream(unsigned char *buffer, unsigned short* w, unsigned short* h)
{
unsigned char header[ 7 ];
screen_descriptor_t screen_descriptor;
int color_resolution_bits;
int global_color_table_size =0; // number of entries in global_color_table
rgb *global_color_table = NULL;
unsigned char block_type = 0x0;
// A GIF file starts with a Header (section 17)
READ(header, 6);
header[ 6 ] = 0x0;
// XXX there's another format, GIF87a, that you may still find
// floating around.
/*if ( strcmp( "GIF89a", (char*)header ) )
{
fprintf( stderr,
"Invalid GIF file (header is '%s', should be 'GIF89a')\n",
header );
return NULL;
}*/
// Followed by a logical screen descriptor
// Note that this works because GIFs specify little-endian order; on a
// big-endian machine, the height & width would need to be reversed.
// Can't use sizeof here since GCC does byte alignment;
// sizeof( screen_descriptor_t ) = 8!
READ(&screen_descriptor, 7);
*w = screen_descriptor.width;
*h = screen_descriptor.height;
color_resolution_bits = ( ( screen_descriptor.fields & 0x70 ) >> 4 ) + 1;
if ( screen_descriptor.fields & 0x80 )
{
//int i;
// If bit 7 is set, the next block is a global color table; read it
global_color_table_size = 1 <<
( ( ( screen_descriptor.fields & 0x07 ) + 1 ) );
global_color_table = ( rgb * ) malloc( 3 * global_color_table_size );
// XXX this could conceivably return a short count...
READ(global_color_table, 3 * global_color_table_size);
}
while ( block_type != TRAILER )
{
READ(&block_type, 1);
unsigned char size;
switch ( block_type )
{
case IMAGE_DESCRIPTOR:
return process_image_descriptor(buffer,
global_color_table,
global_color_table_size,
color_resolution_bits);
break;
case EXTENSION_INTRODUCER:
buffer++;
size = *(buffer++);
buffer += size;
do {
size = *(buffer++);
buffer += size;
} while (size != 0);
/*if ( !process_extension( buffer ) )
{
return NULL;
}*/
break;
case TRAILER:
break;
default:
fprintf( stderr, "Bailing on unrecognized block type %.02x\n",
block_type );
return NULL;
}
}
return NULL;
}
unsigned char* LoadGif(unsigned char *buffer, unsigned short* w, unsigned short* h) {
return process_gif_stream(buffer, w, h);
}
/*int main( int argc, char *argv[] )
{
FILE* gif_file;
if ( argc < 2 )
{
fprintf( stderr, "Usage: %s <path-to-gif-file>\n", argv[ 0 ] );
exit( 0 );
}
gif_file = fopen( argv[ 1 ], "rb" );
if ( gif_file == NULL )
{
fprintf( stderr, "Unable to open file '%s'", argv[ 1 ] );
perror( ": " );
}
process_gif_stream( gif_file );
fclose( gif_file );
}*/

316
grafix.cpp Normal file
View File

@@ -0,0 +1,316 @@
#include "grafix.h"
#include <SDL2/SDL.h>
#include "gif.c"
#include "crt.h"
namespace draw
{
SDL_Window *sdl_window = nullptr; // La finestra de SDL
SDL_Renderer *sdl_renderer = nullptr; // El renderer de SDL
SDL_Texture *sdl_texture = nullptr; // La textura de SDL a la que pintarem la nostra superficie "screen" i que despres volcarem a pantalla
surface *screen = nullptr; // La superficie screen, que representa la pantalla. Se crea i destrueix internament
uint32_t palette[256]; // La paleta de colors
void init(const char* titol, const uint16_t width, const uint16_t height, const uint8_t zoom)
{
// Inicialització de les estructures de SDL
sdl_window = SDL_CreateWindow(titol, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width * zoom, height * zoom, SDL_WINDOW_SHOWN);
sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
// Establim el tamany "logic", indepndent del tamany de finestra
SDL_RenderSetLogicalSize(sdl_renderer, width, height);
// Creem la superficie "screen" i la establim com a superficie destinació
screen = createSurface(width, height);
}
// Finalització del sistema
void quit()
{
// Si la superficie "screen" existia, alliberem la seua memòria
if (screen != nullptr)
{
freeSurface(screen);
}
// Destruim tot el relacionat amb SDL
SDL_DestroyTexture(sdl_texture);
SDL_DestroyRenderer(sdl_renderer);
SDL_DestroyWindow(sdl_window);
// Fiquem tots els punters a nullptr, per si de cas no estem eixint del programa
// i anem a tornar a inicialitzar el sistema
sdl_window = nullptr;
sdl_renderer = nullptr;
sdl_texture = nullptr;
screen = nullptr;
}
surface *createSurface(const int width, const int height)
{
// Primer reservem memòria per a la estructura "surface"
surface *surf = (surface *)malloc(sizeof(surface));
// Després reservem memòria per als pixels
surf->pixels = (uint8_t *)malloc(width * height);
// I apuntem el ample i alt de la superficie
surf->w = width;
surf->h = height;
// ...i tornem la superficie creada, clar
return surf;
}
surface *loadSurface(const char *filename)
{
// Agafem un buffer de bytes de l'arxiu especificat
FILE *f = fopen(filename, "r");
if (f==nullptr) return nullptr;
fseek(f, 0, SEEK_END);
const int size = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t *buffer = (uint8_t*)malloc(size);
fread(buffer, size, 1, f);
fclose(f);
// Primer reservem memòria per a la estructura "surface"
surface *surf = (surface *)malloc(sizeof(surface));
// Després li passem el buffer de bytes a la funció de carregar un GIF.
// El resultat es un array de bytes, els pixels en sí. Ja havem reservat
// la memòria necessaria en "LoadGif", així que no tenim que fer-ho ara,
// però, ojo, sí que tindrem que alliberar-la.
surf->pixels = LoadGif(buffer, &surf->w, &surf->h);
// Com ja no ens fa falta, alliberem la memòria del buffer del arxiu
free(buffer);
// I finalment tornem la superficie
return surf;
}
void freeSurface(surface *surface)
{
// Si la superficie existeix...
if (surface != nullptr)
{
// Si el array de pixels existeix, l'alliberem
if (surface->pixels != nullptr)
{
free(surface->pixels);
}
// ... alliberem la superficie
free(surface);
}
}
void draw(surface *src, surface *dst, uint16_t src_offset, uint16_t w, uint16_t h, uint16_t dst_x, uint16_t dst_y)
{
if (!src) src = screen;
if (!dst) dst = screen;
const int src_x = src_offset % src->w;
const int src_y = src_offset / src->w;
for (int y=0; y<h; ++y)
for (int x=0; x<w; ++x)
{
uint8_t color = getPixel(src_x+x, src_y+y, src);
if (color != 0) putPixel(dst_x+x, dst_y+y, color , dst);
}
if (dst==screen) render();
}
void draw(surface *src, surface *dst)
{
if (!src) src = screen;
if (!dst) dst = screen;
const int w = src->w<dst->w ? src->w : dst->w;
const int h = src->h<dst->h ? src->h : dst->h;
for (int y=0;y<h;++y)
for (int x=0;x<w;++x)
dst->pixels[x+y*dst->w] = src->pixels[x+y*src->w];
if (dst==screen) render();
}
void cls(const uint8_t color, surface *dst)
{
if (!dst) dst = screen;
// El tamany es width x height bytes
const int size = dst->w * dst->h;
// Omplim la memòria dels pixels de la superficie de destinació amb "color"
memset(dst->pixels, color, size);
if (dst==screen) render();
}
// Estableix la paleta del sistema carregant-la d'un GIF
void loadPalette(const char *filename)
{
// Agafem un buffer de bytes de l'arxiu especificat
FILE *f = fopen(filename, "r");
if (f==nullptr) return;
fseek(f, 0, SEEK_END);
const int size = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t *buffer = (uint8_t*)malloc(size);
fread(buffer, size, 1, f);
fclose(f);
// Li passem el array del arxiu a LoadPalette. Ell ens torna un array de uint32_t amb la paleta
// Van a ser 256 entrades de 32 bits, cada entrada es un color, amb el format 0xAARRGGBB
uint32_t *pal = LoadPalette(buffer);
// Copiem eixe array al nostre array de la paleta de sistema. Ara ja tenim la paleta carregada.
memcpy(palette, pal, 1024); // 32 bits per entrada == 4 bytes x 256 entrades == 1024
// Alliberem el array que ens habia tornat LoadPalette()
free(pal);
// I també el buffer del arxiu
free(buffer);
}
void setPalette(uint8_t *paleta)
{
uint8_t *p = paleta;
for (int i=0; i<256; ++i)
{
uint32_t color = (*p++)<<16;
color += (*p++)<<8;
color += (*p++);
palette[i] = color;
}
}
uint8_t *getPalette()
{
uint8_t *paleta = (uint8_t*)malloc(768);
uint8_t *p = paleta;
for (int i=0; i<256; ++i)
{
const uint32_t color = palette[i];
*p = (color >> 16) & 0xff; p++;
*p = (color >> 8) & 0xff; p++;
*p = color & 0xff; p++;
}
return paleta;
}
void setColor(const uint8_t index, const uint8_t r, const uint8_t g, const uint8_t b)
{
palette[index] = (uint32_t(r)<<16) + (uint32_t(g)<<8) + (uint32_t(b));
}
void getColor(const uint8_t index, uint8_t *r, uint8_t *g, uint8_t *b)
{
const uint32_t color = palette[index];
*r = (color >> 16) & 0xff;
*g = (color >> 8) & 0xff;
*b = color & 0xff;
}
void blackout()
{
for (int i=0; i<256; ++i) palette[i] = 0;
}
void fadeDown(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t espera) // espera son el nombre de waitVsync a executar en cada iteració del bucle
{
for (int i=0; i<256; ++i)
{
bool done = true;
for (int j=0; j<espera; ++j) waitVsync();
uint8_t rr, gg, bb;
for (int j=0; j<256; ++j)
{
getColor(j, &rr, &gg, &bb);
if (rr>r) { rr--; done = false; }
if (gg>g) { gg--; done = false; }
if (bb>b) { bb--; done = false; }
setColor(j, rr, gg, bb);
}
render();
if (done) return;
}
}
void fadeUp(const uint8_t *paleta, const uint8_t espera)
{
for (int i=0; i<256; ++i)
{
bool done = true;
for (int j=0; j<espera; ++j) waitVsync();
uint8_t r, g, b;
for (int j=0; j<256; ++j)
{
getColor(j, &r, &g, &b);
if (paleta[j*3]>r) { r++; done = false; }
if (paleta[j*3+1]>g) { g++; done = false; }
if (paleta[j*3+2]>b) { b++; done = false; }
setColor(j, r, g, b);
}
render();
if (done) return;
}
}
void putPixel(const int x, const int y, const uint8_t color, surface *dst)
{
if (!dst) dst = screen;
if (x<0 || y<0 || x>=dst->w || y>=dst->h) return;
dst->pixels[x+y*dst->w] = color;
}
uint8_t getPixel(const int x, const int y, surface *src)
{
if (!src) src = screen;
if (x<0 || y<0 || x>=src->w || y>=src->h) return 0;
return src->pixels[x+y*src->w];
}
void vline(const int x, const int y1, const int y2, const uint8_t color, surface *dst)
{
if (!dst) dst = screen;
for (int y=y1; y<=y2; ++y) dst->pixels[x+(y*dst->w)] = color;
}
void waitVsync()
{
const uint32_t next_vsync = SDL_GetTicks() + (17 - SDL_GetTicks()%17);
while (SDL_GetTicks() < next_vsync)
{
update();
}
}
void render()
{
Uint32 *sdl_pixels; // Punter al array de pixels que enstornarà SDL_LockTexture
int sdl_pitch; // Ací estarà guardat el pitch de la textura, com es de 32 bits, no m'afecta
const uint32_t size = screen->w * screen->h; // tamany de la superficie
// Bloquejem la textura SDL i agafem els seus pixels (son enters de 32 bits amb format 0xAARRGGBB)
SDL_LockTexture(sdl_texture, NULL, (void **)&sdl_pixels, &sdl_pitch);
// Cada pixel de la superficie "screen" es un enter de 8 bits que representa un index en la paleta de colors
// Per tant, per a pintar en la textura SDL, pillem el color de la paleta que correspon al index en "screen"
// i el enviem a la textura SDL
for (uint32_t i = 0; i < size; ++i)
{
sdl_pixels[i] = palette[screen->pixels[i]];
}
// Desbloquejem la textura
SDL_UnlockTexture(sdl_texture);
// Pintem la textura a pantalla
SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
// I ho presentem
SDL_RenderPresent(sdl_renderer);
}
}

View File

@@ -4,16 +4,29 @@
namespace draw
{
void init();
// Estructura per a mantindre una superficie de pintat, la "pantalla virtual" de tota la vida
struct surface
{
uint16_t w; // Ample de la superficie
uint16_t h; // Alt de la superficie
uint8_t *pixels; // pixels de la superficie
};
uint8_t *newSurface(const int width, const int height);
uint8_t *loadSurface(const char *filename);
void deleteSurface(const uint8_t *surface);
void init(const char* titol, const uint16_t width, const uint16_t height, const uint8_t zoom);
void quit();
surface *createSurface(const int width, const int height);
surface *loadSurface(const char *filename);
void freeSurface(surface *surface);
void draw(uint8_t *src, uint8_t *dst, uint16_t src_offset, uint16_t w, uint16_t h, uint16_t dst_x, uint16_t dst_y);
void draw(uint8_t *src, uint8_t *dst);
void draw(surface *src, surface *dst, uint16_t src_offset, uint16_t w, uint16_t h, uint16_t dst_x, uint16_t dst_y);
void draw(surface *src, surface *dst);
void cls(const uint8_t color, uint8_t *dst);
void cls(const uint8_t color, surface *dst);
/// @brief Estableix la paleta del sistema carregant-la d'un GIF
/// @param filename nom de l'arxiu GIF d'on carregar la paleta
void loadPalette(const char *filename);
void setPalette(uint8_t *paleta);
uint8_t *getPalette();
@@ -24,9 +37,11 @@ namespace draw
void fadeDown(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t espera); // espera son el nombre de waitVsync a executar en cada iteració del bucle
void fadeUp(const uint8_t *paleta, const uint8_t espera);
void putPixel(const int x, const int y, const uint8_t color, uint8_t *dst);
void line(const int x1, const int y1, const int x2, const int y2, const uint8_t color, uint8_t *dst);
void putPixel(const int x, const int y, const uint8_t color, surface *dst);
uint8_t getPixel(const int x, const int y, surface *src);
void vline(const int x, const int y1, const int y2, const uint8_t color, surface *dst);
void waitVsync();
void blit();
void render();
}

36
jinput.cpp Normal file
View File

@@ -0,0 +1,36 @@
#include "jinput.h"
#include <SDL2/SDL.h>
#include "crt.h"
namespace input
{
static const uint8_t *keys = nullptr;
static uint8_t keypressed = 0;
void init()
{
keys = SDL_GetKeyboardState(NULL);
}
bool anyKey()
{
update();
return keypressed != 0;
}
bool keyPressed(uint8_t tecla)
{
update();
return keys[tecla];
}
uint8_t getKey()
{
return keypressed;
}
void updateKey(uint8_t key)
{
keypressed = key;
}
}

View File

@@ -1,5 +1,7 @@
#pragma once
#include <stdint.h>
namespace input
{
void init();
@@ -7,4 +9,6 @@ namespace input
bool anyKey();
bool keyPressed(uint8_t tecla);
uint8_t getKey();
}
void updateKey(uint8_t key);
}

24
midiplay.cpp Normal file
View File

@@ -0,0 +1,24 @@
#include "midiplay.h"
namespace audio
{
void playMusic()
{
}
bool musicPlaying()
{
return false;
}
void stopMusic()
{
}
void unloadMusic()
{
}
}

View File

@@ -8,13 +8,10 @@
Port a C/Windows per Raimon Zamora Chanzà (Gener 2024)
──────────────────────────────────────────────────────────────────────────*/
#include "grafix.h"
#include "crt.h"
#include "jinput.h"
#include "dos.h"
#include "pepe_vell.h"
//#include "pepe_vell.h"
#include "midiplay.h"
// const
@@ -271,9 +268,9 @@
//VirScrSP : Ptr_pantalla;
uint8_t *vaddr; // : word;
uint8_t *vaddr2; // : word;
uint8_t *vaddrSP; // : word;
draw::surface *vaddr; // : word;
draw::surface *vaddr2; // : word;
draw::surface *vaddrSP; // : word;
uint16_t blocs_per_pintar;// : word;
uint16_t total_blocs_per_pintar;// : word;
@@ -367,7 +364,7 @@ malo_t malo[max_malos];
/*──────────────────────────────────────────────────────────────────────────*/
void power_off(uint8_t *where)
void power_off(draw::surface *where)
{
uint16_t i;
uint8_t j;
@@ -394,7 +391,7 @@ void power_off(uint8_t *where)
}
/*──────────────────────────────────────────────────────────────────────────*/
void load_mif(int num, uint8_t *where)
void load_mif(int num, draw::surface *where)
{
draw::waitVsync();
draw::cls(0, VGA);
@@ -404,7 +401,7 @@ void load_mif(int num, uint8_t *where)
// fread(&num_dibuixos, 1, 1, fich); // Read(fich,num_dibuixos);
int pos = 1 + (8 * num_dibuixos) + ((num - 1) * 64768);
fseek(fich, pos, SEEK_SET);
fread(where, 64000, 1, fich);
fread(where->pixels, 64000, 1, fich);
uint8_t paleta[768];
fread(paleta, 768, 1, fich);
draw::setPalette(paleta);
@@ -597,72 +594,72 @@ var aux : boolean; intents : word;
}
/*──────────────────────────────────────────────────────────────────────────*/
void pinta(uint16_t offset, uint8_t color, uint16_t x, uint16_t y, uint8_t *where) // offset es on comença el dibuixet en el "bitmap" de sprites, where la surface
void pinta(uint16_t offset, uint8_t color, uint16_t x, uint16_t y, draw::surface *where) // offset es on comença el dibuixet en el "bitmap" de sprites, where la surface
{
// [RZC 24/01/0224] [NOTA] No entenc perqué s'incrementa 1 a les coordenades on anem a pintar. Per ara ho lleve
// inc(x); inc(y);
for (int i = 0; i < 6; ++i)
for (int j = 0; j < 6; ++j)
if (color != 255)
where[(x + i) + ((y + j) * 320)] = color;
else if (vaddrSP[offset + i + (j * 320)] != 255)
where[(x + i) + ((y + j) * 320)] = vaddrSP[offset + i + (j * 320)];
// [RZC 24/01/0224] [NOTA] No entenc perqué s'incrementa 1 a les coordenades on anem a pintar. Per ara ho lleve
// inc(x); inc(y);
for (int i = 0; i < 6; ++i)
for (int j = 0; j < 6; ++j)
if (color != 255)
draw::putPixel(x+i, y+j, color, where);
else if (vaddrSP->pixels[offset + i + (j * 320)] != 255)
draw::putPixel(x+i, y+j, vaddrSP->pixels[offset + i + (j * 320)], where);
}
/*──────────────────────────────────────────────────────────────────────────*/
// [RZC 24/01/0224] [NOTA] Esta funció i l'anterior son exactament iguals!
void pinta_zoom(uint8_t zoom, uint16_t offset, uint8_t color, uint16_t x, uint16_t y, uint8_t *where)
void pinta_zoom(uint8_t zoom, uint16_t offset, uint8_t color, uint16_t x, uint16_t y, draw::surface *where)
{
// [RZC 24/01/0224] [NOTA] No entenc perqué s'incrementa 1 a les coordenades on anem a pintar. Per ara ho lleve
// inc(x); inc(y);
for (int i = 0; i < 6; ++i)
for (int j = 0; j < 6; ++j)
if (color != 255)
where[(x + i) + ((y + j) * 320)] = color;
else if (vaddrSP[offset + i + (j * 320)] != 255)
where[(x + i) + ((y + j) * 320)] = vaddrSP[offset + i + (j * 320)];
// [RZC 24/01/0224] [NOTA] No entenc perqué s'incrementa 1 a les coordenades on anem a pintar. Per ara ho lleve
// inc(x); inc(y);
for (int i = 0; i < 6; ++i)
for (int j = 0; j < 6; ++j)
if (color != 255)
draw::putPixel(x+i, y+j, color, where);
else if (vaddrSP->pixels[offset + i + (j * 320)] != 255)
draw::putPixel(x+i, y+j, vaddrSP->pixels[offset + i + (j * 320)], where);
}
/*──────────────────────────────────────────────────────────────────────────*/
// [RZC 24/01/0224] [NOTA] Esta es igual pero els bucles van de 0 a 8 en compte de de 0 a 5
void pinta_number(uint16_t offset, uint8_t color, uint16_t x, uint16_t y, uint8_t *where)
{
// [RZC 24/01/0224] [NOTA] No entenc perqué s'incrementa 1 a les coordenades on anem a pintar. Per ara ho lleve
// inc(x); inc(y);
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
if (color != 255)
where[(x + i) + ((y + j) * 320)] = color;
else if (vaddrSP[offset + i + (j * 320)] != 255)
where[(x + i) + ((y + j) * 320)] = vaddrSP[offset + i + (j * 320)];
}
/*──────────────────────────────────────────────────────────────────────────*/
void pinta_number2(uint16_t offset, uint8_t color, uint8_t color_determinat, uint16_t x, uint16_t y, uint8_t *where)
void pinta_number(uint16_t offset, uint8_t color, uint16_t x, uint16_t y, draw::surface *where)
{
// [RZC 24/01/0224] [NOTA] No entenc perqué s'incrementa 1 a les coordenades on anem a pintar. Per ara ho lleve
// inc(x); inc(y);
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
if (color != 255)
where[(x + i) + ((y + j) * 320)] = color;
else if ((vaddrSP[offset + i + (j * 320)] != 255) && (vaddrSP[offset + i + (j * 320)] != 254))
where[(x + i) + ((y + j) * 320)] = vaddrSP[offset + i + (j * 320)];
else if (vaddrSP[offset + i + (j * 320)] == 254)
where[(x + i) + ((y + j) * 320)] = color_determinat;
draw::putPixel(x+i, y+j, color, where);
else if (vaddrSP->pixels[offset + i + (j * 320)] != 255)
draw::putPixel(x+i, y+j, vaddrSP->pixels[offset + i + (j * 320)], where);
}
/*──────────────────────────────────────────────────────────────────────────*/
void pinta_number_zoom(uint8_t zoom, uint16_t offset, uint8_t color, uint16_t x, uint16_t y, uint8_t *where)
void pinta_number2(uint16_t offset, uint8_t color, uint8_t color_determinat, uint16_t x, uint16_t y, draw::surface *where)
{
// [RZC 24/01/0224] [NOTA] No entenc perqué s'incrementa 1 a les coordenades on anem a pintar. Per ara ho lleve
// inc(x); inc(y);
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
if (color != 255)
draw::putPixel(x+i, y+j, color, where);
else if ((vaddrSP->pixels[offset + i + (j * 320)] != 255) && (vaddrSP->pixels[offset + i + (j * 320)] != 254))
draw::putPixel(x+i, y+j, vaddrSP->pixels[offset + i + (j * 320)], where);
else if (vaddrSP->pixels[offset + i + (j * 320)] == 254)
draw::putPixel(x+i, y+j, color_determinat, where);
}
/*──────────────────────────────────────────────────────────────────────────*/
void pinta_number_zoom(uint8_t zoom, uint16_t offset, uint8_t color, uint16_t x, uint16_t y, draw::surface *where)
{
// [RZC 24/01/0224] [NOTA] No entenc perqué s'incrementa 1 a les coordenades on anem a pintar. Per ara ho lleve
// inc(x); inc(y);
for (int i = 0; i < 9 * zoom; ++i)
for (int j = 0; j < 9 * zoom; ++j)
if (color != 255)
where[(x + i) + ((y + j) * 320)] = color;
else if (vaddrSP[offset + (i / zoom) + ((j / zoom) * 320)] != 255)
where[(x + i) + ((y + j) * 320)] = vaddrSP[offset + (i / zoom) + ((j / zoom) * 320)];
draw::putPixel(x+i, y+j, color, where);
else if (vaddrSP->pixels[offset + (i / zoom) + ((j / zoom) * 320)] != 255)
draw::putPixel(x+i, y+j, vaddrSP->pixels[offset + (i / zoom) + ((j / zoom) * 320)], where);
}
/*──────────────────────────────────────────────────────────────────────────*/
@@ -675,7 +672,7 @@ void retard(int centesimes)
}
/*──────────────────────────────────────────────────────────────────────────*/
void escriu_frase(char *nom, uint8_t color_determinat, uint16_t x,uint16_t y, uint8_t *where, uint16_t velocitat, uint8_t mode, uint8_t mode2)
void escriu_frase(const char *nom, uint8_t color_determinat, uint16_t x,uint16_t y, draw::surface *where, uint16_t velocitat, uint8_t mode, uint8_t mode2)
{
for (int i=0; i<strlen(nom); ++i)
{
@@ -726,7 +723,7 @@ void escriu_frase(char *nom, uint8_t color_determinat, uint16_t x,uint16_t y, ui
case ':' : quina_lletra = lletra_dos_punts; break;
case '(' : quina_lletra = lletra_parentesis_o; break;
case ')' : quina_lletra = lletra_parentesis_t; break;
case '¡' : quina_lletra = lletra_exclamacio_o; break;
//case '¡' : quina_lletra = lletra_exclamacio_o; break;
case '!' : quina_lletra = lletra_exclamacio_t; break;
case '*' : quina_lletra = lletra_apostrof; break;
case '.' : quina_lletra = lletra_punt; break;
@@ -745,7 +742,7 @@ void escriu_frase(char *nom, uint8_t color_determinat, uint16_t x,uint16_t y, ui
}
/*──────────────────────────────────────────────────────────────────────────*/
void borrar_frase(int temps, uint8_t *zona_mem1, uint8_t *zona_mem2)
void borrar_frase(int temps, draw::surface *zona_mem1, draw::surface *zona_mem2)
{
retard(temps);
draw::draw(zona_mem1, zona_mem2);
@@ -754,7 +751,7 @@ void borrar_frase(int temps, uint8_t *zona_mem1, uint8_t *zona_mem2)
}
/*──────────────────────────────────────────────────────────────────────────*/
void borrat_de_pantalla(uint8_t *where)
void borrat_de_pantalla(draw::surface *where)
{
for (int i = 0; i < 32; ++i)
{
@@ -1084,7 +1081,7 @@ void pepe_text()
/*──────────────────────────────────────────────────────────────────────────*/
void final_fals()
{
uint8_t *vaddr3 = draw::newSurface(320, 240);
draw::surface *vaddr3 = draw::createSurface(320, 240);
draw::cls(0, vaddr);
load_mif(FINALF1, vaddr2);
load_mif(FINALF2, vaddr3);
@@ -1183,7 +1180,7 @@ void final_fals()
draw::fadeDown(0,0,0,0);
if (midi) { audio::stopMusic(); audio::unloadMusic(); midi = false; }
draw::deleteSurface(vaddr3);
draw::freeSurface(vaddr3);
}
/*──────────────────────────────────────────────────────────────────────────*/
@@ -1428,7 +1425,7 @@ void credits()
}
}
uint32_t t = SDL_GetTicks()+10000;
t = SDL_GetTicks()+10000;
do {} while (!input::anyKey() && SDL_GetTicks()<t);
draw::fadeDown(0,0,0,3);
@@ -1442,18 +1439,18 @@ void credits()
}
/*──────────────────────────────────────────────────────────────────────────*/
void reixa(uint16_t posx, uint8_t longitud, uint8_t *where)
void reixa(uint16_t posx, uint8_t longitud, draw::surface *where)
{
draw::line(posx, 30, posx, 197-longitud, 0, where);
draw::line(posx+1, 30, posx+1, 197-longitud, 0, where);
draw::line(posx+2, 30, posx+2, 198-longitud, 0, where);
draw::line(posx+3, 30, posx+3, 198-longitud, 0, where);
draw::line(posx+4, 30, posx+4, 199-longitud, 0, where);
draw::line(posx+5, 30, posx+5, 199-longitud, 0, where);
draw::line(posx+6, 30, posx+6, 198-longitud, 0, where);
draw::line(posx+7, 30, posx+7, 198-longitud, 0, where);
draw::line(posx+8, 30, posx+8, 197-longitud, 0, where);
draw::line(posx+9, 30, posx+9, 197-longitud, 0, where);
draw::vline(posx, 30, 197-longitud, 0, where);
draw::vline(posx+1, 30, 197-longitud, 0, where);
draw::vline(posx+2, 30, 198-longitud, 0, where);
draw::vline(posx+3, 30, 198-longitud, 0, where);
draw::vline(posx+4, 30, 199-longitud, 0, where);
draw::vline(posx+5, 30, 199-longitud, 0, where);
draw::vline(posx+6, 30, 198-longitud, 0, where);
draw::vline(posx+7, 30, 198-longitud, 0, where);
draw::vline(posx+8, 30, 197-longitud, 0, where);
draw::vline(posx+9, 30, 197-longitud, 0, where);
}
/*──────────────────────────────────────────────────────────────────────────*/
@@ -1482,11 +1479,12 @@ void historia_final()
}
if (mode_nocturne) retard(200); else retard(600);
draw::fadeDown(0,0,0,0);
free(paleta);
// dibuix 2
if (mode_nocturne) load_mif(FINALN02, vaddr); else load_mif(FINAL02, vaddr);
draw::setColor(1,32,0,0);
uint8_t *paleta = draw::getPalette();
paleta = draw::getPalette();
draw::blackout();
draw::waitVsync();
draw::draw(vaddr, VGA);
@@ -1500,13 +1498,14 @@ void historia_final()
}
if (!mode_nocturne) retard(600);
draw::fadeDown(0,0,0,0);
free(paleta);
// dibuix 3
if (mode_nocturne) load_mif(FINALN03, vaddr); else load_mif(FINAL03, vaddr);
draw::setColor(253,39, 0,48);
draw::setColor(254, 0,63, 6);
draw::setColor(255, 0, 3,63);
uint8_t *paleta = draw::getPalette();
paleta = draw::getPalette();
draw::blackout();
draw::waitVsync();
draw::draw(vaddr, VGA);
@@ -1533,6 +1532,7 @@ void historia_final()
} while (!input::anyKey() && SDL_GetTicks()<t);
draw::fadeDown(0,0,0,0);
free(paleta);
// dibuix 4
if (mode_nocturne)
@@ -1546,7 +1546,7 @@ void historia_final()
retard(600);
draw::fadeDown(0,0,0,0);
}
free(paleta);
credits();
}
@@ -1557,7 +1557,7 @@ void pilla_temps()
}
/*──────────────────────────────────────────────────────────────────────────*/
void posa_el_temps(uint8_t *where)
void posa_el_temps(draw::surface *where)
{
//gettime(h1,m1,s1,c1);
temps = (SDL_GetTicks() / 1000) - hora;
@@ -1921,7 +1921,7 @@ var i,j : word;
vaddrFase : Word;
*/
{
uint8_t *vaddrFase = (uint8_t*)malloc(6400); // 6400???
draw::surface *vaddrFase = draw::createSurface(320, 20); //(uint8_t*)malloc(6400); // 6400???
load_mif(FASES,vaddr);
draw::cls(0, vaddrFase);
@@ -3115,7 +3115,7 @@ uint8_t percentatge;
}
}
void fondo_estreles(uint8_t *from, uint8_t *where)
void fondo_estreles(draw::surface *from, draw::surface *where)
{
for (int i=0; i<10; ++i)
{
@@ -3132,7 +3132,7 @@ uint8_t percentatge;
}
void actualitza_options(uint8_t *from, uint8_t *where)
void actualitza_options(draw::surface *from, draw::surface *where)
{
draw::cls(0, vaddr2);
@@ -3863,7 +3863,7 @@ void menu_joc()
draw::draw(vaddr2, VGA);
} while (input::anyKey());
bool tecla_incorrecta = true;
//bool tecla_incorrecta = true;
if (aux >= SDL_SCANCODE_A && aux <= SDL_SCANCODE_Z) tecla_incorrecta = false;
if (aux >= SDL_SCANCODE_RIGHT && aux <= SDL_SCANCODE_UP) tecla_incorrecta = false;
@@ -3945,6 +3945,8 @@ void menu_joc()
/*──────────────────────────────────────────────────────────────────────────*/
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
comprobar_comp_i_sprites();
srand(SDL_GetTicks());
@@ -3952,12 +3954,13 @@ int main(int argc, char *argv[])
input::init();
//setmode(0x13);
draw::init();
draw::init("Pepe el Pintor", 320, 200, 3);
vaddr = draw::newSurface(320, 240);
vaddr2 = draw::newSurface(320, 240);
vaddr = draw::createSurface(320, 200);
vaddr2 = draw::createSurface(320, 200);
vaddrSP = draw::loadSurface("datos/sprites.dat"); //(320, 24);// (uint8_t *)malloc(7680);
//loadPCX('datos/sprites.dat', vaddrSP);
draw::loadPalette("datos/sprites.dat");
load_setup_i_versio();
@@ -3978,9 +3981,9 @@ int main(int argc, char *argv[])
} while (!eixir_del_joc);
draw::deleteSurface(vaddr);
draw::deleteSurface(vaddr2);
draw::deleteSurface(vaddrSP);
draw::freeSurface(vaddr);
draw::freeSurface(vaddr2);
draw::freeSurface(vaddrSP);
/* if amb_so then arxius_wav(FALSE);
if amb_so then EndWAV;*/
@@ -3988,6 +3991,8 @@ int main(int argc, char *argv[])
//DesinstalarKB();
//setmode(0x3);
draw::quit();
SDL_Quit();
}
/*