68 Commits

Author SHA1 Message Date
0547378331 - [FIX] El nom dels .zip estaba mal 2026-03-25 10:35:28 +01:00
92b4e4472f - [FIX] Ficar dlls on fan falta
- [FIX] Llevades les dlls que ja no fan falta
2026-03-25 10:23:09 +01:00
d362eef8bf - [NEW] Ajustada la compilació en Windows
- [FIX] Ficades les dll en l'arrel del zip
2026-03-25 10:14:22 +01:00
57852bd3ae VERSIÓ 1.4.10:
- [NEW] surface_t.flags
- [NEW] F12 per a recàrrega de surfaces en calent
2026-03-24 08:23:11 +01:00
6fb31a3ae5 - [FIX] Fallaba al carregar fonts amb format de final de linea de Windows 2026-03-22 17:39:21 +01:00
89496fb8fb - [FIX] El nom dels arxius a pujar a gitea estaba mal 2026-03-21 11:53:41 +01:00
4774a1a806 - [FIX] Scripts de publicació 2026-03-21 11:46:47 +01:00
74cb8cb0f8 VERSIÓ 1.4.8:
- [NEW] draw.surfrot
2026-03-21 10:15:23 +01:00
d573c159fa - [FIX] Arreglat el make de macos
- [NEW] Publicació automàtica de releases
2026-03-20 11:46:11 +01:00
446f588cfe - [WIP] Treballant en que publique a gitea amb la API 2026-03-20 09:17:21 +01:00
8c9c1f2b47 - [WIP] Afegides DLLs de windows per a quan empaquete 2026-03-20 08:37:01 +01:00
6cccd44743 - [FIX] Eliminat un warning en macOS en jfile
- [WIP] Sistema de release automatic
2026-03-20 08:35:28 +01:00
4a3450e116 VERSIÓ 1.4.7
- [NEW] map.cell() per a establir o llegir el tamany dels tiles del mapa
2026-03-19 11:29:08 +01:00
779ef7acb6 VERSIÓ 1.4.6
-[NEW] font.load()
-[NEW] font.current()
-[NEW] font.spacing()
-[NEW] font.DEFAULT
-[NEW] surf.SCREEN
2026-03-18 20:36:14 +01:00
bf34c92e09 VERSIÓ 1.4.5
- [NEW] Afegida funció "sub" al modul estandar "utf8"
2026-03-18 10:33:02 +01:00
9c895a518e VERSIÓ 1.4.4
- [NEW] Nou sistema de fonts funcionant ja internament
2026-03-18 08:58:42 +01:00
e89d596ea4 (Canvi d'ordenador)
- [WIP] Treballant en les fonts
2026-03-17 18:25:17 +01:00
560d67ca3d VERSIÓ 1.4.3
- [NEW] key.text()
- [NEW] key.utf8char()
- [NEW] pal.trans() ara torna el color transparent
- [NEW] pal.subpal(index) i pal.subpal(index,color) ara tornen el color al que estaba abans asignat el index
2026-03-17 13:47:25 +01:00
6f5d90ee49 - [FIX] typo en un #ifdef 2026-03-16 16:27:04 +01:00
d92a903c61 VERSIÓ 1.4.2
- [NEW] excutar "mini --version" torna la versió
- [NEW] executar "mini dura/a/un/data.jf2" usará eixe arxiu jf2
- [NEW] sys.version()
2026-03-16 14:25:47 +01:00
afa022d838 - [FIX] Arerglat mkdir() en Windows
- [FIX] Arreglat glActiveTexture en Windows
2026-03-15 13:10:00 +01:00
536987f89b VERSIÓ 1.4.1
- [NEW] Ara require soporta rutes relatives (he tingut que fer un parxe al codi de Lua)
2026-03-12 16:23:48 +01:00
4084cb64f2 VERSIÓ 1.4
- [NEW] jfile_listdir()
- [NEW] ara els moduls es deuen carregar amb 'require "directori.modul" '
- [NEW] Ara es poden carregar directoris sencers amb 'require "directori.*" '
2026-03-12 14:58:39 +01:00
33bbf940ea - [FIX] JA_StopChannel() petava al parar tots els sons. 2026-03-04 10:19:16 +01:00
f12e46db1b - [NEW] sys.debug() returns true if we are on a debug version of mini. false otherwise. 2026-03-04 10:12:53 +01:00
681cbc2207 - [FIX] Updatat el makefile per a incloure opengl (per lo dels shaders, un dia he de tirar-los a la basura) 2026-03-03 13:40:59 +01:00
5db06a0645 - [FIX] sys.subpal() now clamps values for safety 2026-02-25 11:53:15 +01:00
a17a1bb517 - [CHG] surf.target() i surf.source() sense paràmetres ara el que fan es tornar les surfaces actuals de target i de source 2026-02-24 22:18:54 +01:00
fc962b4e18 - [NEW] draw.mode(), amb modes NORMAL, PATTERN, AND, OR, XOR i NOT
- [NEW] Ara per a pintar en pattern hi ha que dir-ho en draw.mode(), no es automatic al ficar un pattern.
- [NEW] Nous modes de pintat booleans. AND, OR i XOR fan l'operació pixel_actual = pixel_actual OP color_especificat. NOT no usa el color especificat, nomes fa un NOT del pixel actual.
2026-02-24 18:53:53 +01:00
9581ce67fd - [NEW] sys.chrono() 2026-02-18 10:53:31 +01:00
7c3b58c5f0 - [WIP] Font Editor 2025-12-10 14:03:11 +01:00
6e15fe7231 - [NEW] mouse.inside(x,y,w,h)
- [WIP] fonted tool
2025-12-09 14:05:12 +01:00
eac20bbbe0 VERSIÓ 1.3.15
- [NEW] mouse.dblclick()
- [FIX] de vegades no pillava be la rodeta del ratolí
- [NEW] sys.dir() torna el contingut del directori primer les carpetes, i tot ordenat alfabèticament
- [WIP] Treballant en ferramentes
2025-12-04 17:46:22 +01:00
7fac42c9fe - [NEW] sys.dir() ara torna un array de entrades amb nom i si es directori 2025-12-04 14:47:25 +01:00
4858d94378 VERSIÓ 1.3.14
- [NEW] draw.pattern() sense paràmetres restableix el patró de relleno
- [FIX] Llevat el std::vector que estava donant pel cul. No, si ja sabia jo...
- [NEW] Gestió del cas en que es supere el nombre màxim de textures (en compte d'explotar, tira un error bonico)
2025-12-04 11:35:34 +01:00
3e524fd32d VERSIÓ 1.3.13
- [NEW]  Executant la versió de debug amb el paràmeter "--new" crea un projecte nou en eixe directori.
- [NEW] Nou sistema de log
- [FIX] Amb el tema de usar std::vector no s'estava inicialitzant la surface de pantalla correctament.
- [FIX] Proteccions per a que no pete quan s'intenta usar funcions que els fa falta una surface de oritge, pero no hi ha ninguna seleccionada.
- [NEW] file_createFolder() (ATENCIÓ: No funcionarà en Windows encara)
2025-12-03 14:05:52 +01:00
ace4a0f9f0 - [NEW] Ara les textures usen un std::vector i ja no hi ha limit. Espere no arrepentir-me
- [WIP] Treballant en les custom fonts
2025-11-27 22:18:46 +01:00
839c1e82eb VERSIÓ 1.3.12
- [FIX] La paleta per defecte era tota transparent
- [NEW] draw.rrect() i draw.rrectf()
2025-11-27 17:18:07 +01:00
33d7cc3b6d VERSIÓ 1.3.11
- [NEW] surf.loadex()
2025-11-27 11:22:52 +01:00
a7cbdea4c5 - [FIX] uncompress() cleanup 2025-11-24 14:30:11 +01:00
3383b415cd - [FIX] Arreglat el guardat de GIFs 2025-11-14 17:31:09 +01:00
02dc0a4953 - Treballant en que els GIFs no donen pel cul 2025-11-13 17:45:30 +01:00
091c2617a4 VERSIÓ 1.3.10
- [NEW] sys.delta()
2025-11-10 09:06:13 +01:00
c7559f0d29 VERSIÓ 1.3.9
- [FIX] el mapa sempre pintava TOTS els tiles, es veren o no. Ara te en compte el oritge i la regió de clipping.
2025-11-05 13:08:56 +01:00
327453b02c VERSIÓ 1.3.8
- [FIX] Al pintar el mapa usava uint8_t i per tant els mapes de mes de 255 tiles en alguna dimensió no funcionaven be
2025-11-05 09:55:38 +01:00
62ac5ae92d VERSIÓ 1.3.7
- [NEW] music.enable() i sound.enable()
2025-10-30 16:27:40 +01:00
4172c6af3d - Ajustat el nombre de versió
- Retocades dos funcions de la llibreria de vscode
2025-10-30 12:35:13 +01:00
7bff57c6fa - [NEW] mouse.discard() 2025-06-20 13:49:59 +02:00
f154e1a36b - [NEW] Ara mouse.pos() torna les coordenades relatives al origen, no a la finestra. 2025-06-20 12:07:30 +02:00
0471bcbdda - [FIX] No guardava be els GIFs sense paleta 2025-06-19 17:48:56 +02:00
76e2925791 - [ONGOING] A meitat de arreglar el bug del guardat de GIFs 2025-06-19 13:56:44 +02:00
34a56fedcf - [FIX] mouse.pos() donava coordenades reals de finestra, en compte de tindre en compte el zoom. 2025-06-19 12:44:51 +02:00
9cd991cb44 - [FIX] draw.text() també soporta que li pases un numero pa escriure-lo 2025-06-18 19:52:24 +02:00
e1d5eb051c VERSIÓ 1.3
- [NEW] shader.init(), shader.enable i shader.disable
- [NEW] Deixe els shaders de Lynx i GBC de exemple.
- [NEW] file_getfilebuffer() ara soporta un tercer paràmetre opcional, per a 'zeroterminar' el buffer per si es un arxiu de text.
2025-06-18 19:29:17 +02:00
79781bbed1 VERSIÓ 1.2.5
- [NEW] Soport bàsic per a shaders.
2025-06-18 13:49:35 +02:00
0cb1296ad3 VERSIÓ 1.2
- [NEW] Convertit a SDL3
2025-06-18 12:47:24 +02:00
16be589a72 - VERSIÓ 1.1
- [NEW] map.surf() per a obtindre i fixar la surface que usa el tilemap
- [NEW] Llevats map.new, map.load i map.save. Es fa des de les surfaces.
2025-06-17 13:53:45 +02:00
2a4195c839 VERSIÓ 1.0.1
- [FIX] view.clip() calculaba mal el ample i el alt de la zona clipada.
- [FIX] view.origin() funcionava al reves.
2025-06-17 11:34:38 +02:00
5e24117266 - [CHG] Renombrat "stb_vorbis.c" a "stb_vorbis.h"
- [NEW] Afegit lagueirtofile
2025-06-16 13:45:54 +02:00
88609465cb - [CHG] Renombrat "gif.c" a "gif.h"
- [FIX] El codi de exemple petava
2025-06-16 13:39:50 +02:00
8f8009e8af - [FIX] Updated 'library.lua' with sys.fps() and sys.clipboard(). 2025-06-04 13:14:59 +02:00
150cb9f4ff VERSIÓ 1.0 RC4
- [NEW] sys.clipboard() per a llegir i escriure al portapapers.
2025-06-04 11:56:51 +02:00
4bda9cbd39 VERSIÓ 1.0 RC3
- [FIX] Funció "view.local()" canviada a "view.tolocal()", per a evitar problemes.
- [FIX] Si una surface no s'ha creat, no hi ha res que alliberar.
- [NEW] Afegit log de creació i destrucció de surfaces.
2025-06-03 13:26:11 +02:00
adcc44ddab - [NEW] Augmentat el màxim de textures a 100.
- [NEW] Camp "name" per a les textures.
- [NEW] Si s'intenta carregar un gif que ja està en memòria, se torna el que està en memòria.
2025-06-02 12:30:58 +02:00
8e855fa2c1 - [FIX] No permetia carregar GIFs de mes de 256 pixels de ample o alt
- [FIX] No tornava be la ruta al arxiu de configuració
- [NEW] Ara guarda en "~/.config/jailgames/loquesiga/"
- [FIX] El mapa de tiles ha de pillar els tiles de la surface source
- [NEW] Actualitzada la llibreria de autocompletar per a vscode
2025-05-31 14:28:20 +02:00
8f98d52385 VERSIÓ 1.0 RC2
- Nova i, espere, definitiva API
2025-05-30 20:16:02 +02:00
b6e5dca277 - [NEW] system.fps() 2025-05-30 17:45:12 +02:00
3d14c33971 - [NEW] Proposta de API inclosa al repositori 2025-05-30 13:53:30 +02:00
42 changed files with 4001 additions and 1165 deletions

4
.gitignore vendored
View File

@@ -4,4 +4,6 @@ mini_debug.exe
mini_debug mini_debug
.vscode/* .vscode/*
info.plist info.plist
*.dll build/*
*.zip
*.tar.gz

View File

@@ -3,25 +3,25 @@ source = *.cpp ./lua/*.c
windows: windows:
@echo off @echo off
g++ $(source) icon.res -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -lmingw32 -lSDL2main -lSDL2 -mwindows -o "$(executable).exe" g++ $(source) icon.res -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -lmingw32 -lSDL3 -lopengl32 -static-libstdc++ -static-libgcc -lpthread -mwindows -o "$(executable).exe"
strip -s -R .comment -R .gnu.version --strip-unneeded "$(executable).exe" strip -s -R .comment -R .gnu.version --strip-unneeded "$(executable).exe"
windows_debug: windows_debug:
@echo off @echo off
g++ $(source) -D DEBUG -g -Wall -Os -lmingw32 -lSDL2main -lSDL2 -o "$(executable)_debug.exe" g++ $(source) -D DEBUG -g -Wall -Os -lmingw32 -lSDL3 -lopengl32 -o "$(executable)_debug.exe"
macos: macos:
clang++ $(source) -Wall -Os -std=c++11 -ffunction-sections -fdata-sections -lSDL2 -o "$(executable)" clang++ $(source) -Wall -Os -std=c++17 -Wno-deprecated -ffunction-sections -fdata-sections -lSDL3 -framework OpenGL -o "$(executable)"
macos_debug: macos_debug:
clang++ $(source) -D DEBUG -g -Wall -Os -std=c++11 -ffunction-sections -fdata-sections -lSDL2 -o "$(executable)_debug" clang++ $(source) -D DEBUG -g -Wall -Os -std=c++17 -Wno-deprecated -ffunction-sections -fdata-sections -lSDL3 -framework OpenGL -o "$(executable)_debug"
macos_bundle: macos_bundle:
clang++ $(source) -D MACOS_BUNDLE -Wall -Os -std=c++11 -framework SDL2 -F /Library/Frameworks -ffunction-sections -fdata-sections -o mini_bundle -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12 clang++ $(source) -D MACOS_BUNDLE -Wall -Os -std=c++17 -Wno-deprecated -framework SDL3 -framework OpenGL -F /Library/Frameworks -ffunction-sections -fdata-sections -o mini_bundle -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12
linux: linux:
g++ $(source) -D LUA_USE_LINUX -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -lSDL2 -o "$(executable)" g++ $(source) -D LUA_USE_LINUX -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -lSDL3 -lGL -o "$(executable)"
strip -s -R .comment -R .gnu.version --strip-unneeded "$(executable)" strip -s -R .comment -R .gnu.version --strip-unneeded "$(executable)"
linux_debug: linux_debug:
g++ $(source) -D LUA_USE_LINUX -D DEBUG -g -Wall -lSDL2 -o "$(executable)_debug" g++ $(source) -D LUA_USE_LINUX -D DEBUG -g -Wall -lSDL3 -lGL -o "$(executable)_debug"

BIN
bin/SDL3.dll Normal file

Binary file not shown.

BIN
bin/libwinpthread-1.dll Normal file

Binary file not shown.

9
data/font.fnt Normal file
View File

@@ -0,0 +1,9 @@
bitmap=font.gif
48: 0 0 7 7 0 # 0
49: 8 0 4 7 0 # 1
50: 16 0 7 7 0 # 2
51: 24 0 7 7 0 # 3
52: 32 0 7 7 0 # 4
53: 40 0 7 7 0 # 5
54: 48 0 7 7 0 # 6
55: 56 0 7 7 0 # 7

BIN
data/font.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

View File

@@ -1,5 +1,5 @@
title=HOLA MINI title=TESTS
config=minitest config=minitests
width=160 width=400
height=120 height=300
zoom=3 zoom=2

38
data/gbc.glsl Normal file
View File

@@ -0,0 +1,38 @@
varying vec2 tex_coord;
varying vec2 pix_coord;
#if defined(VERTEX)
void main()
{
pix_coord = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
tex_coord = vec2((gl_Vertex.x+1.0)*0.5, (-gl_Vertex.y+1.0)*0.5);
vec4 pos = vec4(gl_Vertex.x * 2.0, gl_Vertex.y * 2.0, gl_Vertex.z, gl_Vertex.w);
gl_Position = gl_Vertex; //(gl_Vertex*2)-vec3(1.0, 1.0, 1.0);//gl_ModelViewProjectionMatrix * gl_Vertex;
}
#elif defined(FRAGMENT)
uniform sampler2D Texture;
void main()
{
float x = sign(pix_coord.x)*floor(abs(pix_coord.x)+0.5);
float y = sign(pix_coord.y)*floor(abs(pix_coord.y)+0.5);
float column = mod(x,4.0);
float row = mod(y,4.0);
vec4 color = texture2D(Texture, tex_coord);
vec4 newcolor;
if ((column == 0.0) || (row == 0.0) ) {
newcolor = color * vec4(0.4, 0.4, 0.4, 1.0);
} else if ((column == 1.0) || (row == 1.0) ) {
newcolor = color * vec4(0.6, 0.7, 0.8, 1.0);
} else if ((column == 3.0) || (row == 3.0) ) {
newcolor = color * vec4(0.8, 0.7, 0.6, 1.0);
} else {
newcolor = color;
}
gl_FragColor = newcolor;
}
#endif

BIN
data/gfx/logo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

9
data/ia/other.lua Normal file
View File

@@ -0,0 +1,9 @@
require "ia.test"
other = {
peiv = function()
pal.color(1, 1, 1, 1)
test2()
return "HOLA OTHER UNIT"
end
}

3
data/ia/test.lua Normal file
View File

@@ -0,0 +1,3 @@
function test2()
draw.text("THIS WORKS!",1,140,4)
end

41
data/lynx.glsl Normal file
View File

@@ -0,0 +1,41 @@
varying vec2 tex_coord;
varying vec2 pix_coord;
#if defined(VERTEX)
void main()
{
pix_coord = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
tex_coord = vec2((gl_Vertex.x+1.0)*0.5, (-gl_Vertex.y+1.0)*0.5);
vec4 pos = vec4(gl_Vertex.x * 2.0, gl_Vertex.y * 2.0, gl_Vertex.z, gl_Vertex.w);
gl_Position = gl_Vertex; //(gl_Vertex*2)-vec3(1.0, 1.0, 1.0);//gl_ModelViewProjectionMatrix * gl_Vertex;
}
#elif defined(FRAGMENT)
uniform sampler2D Texture;
void main()
{
float x = sign(pix_coord.x)*floor(abs(pix_coord.x)+0.5);
float column = mod(x,4.0);
vec4 color = texture2D(Texture, tex_coord);
float xfade = abs((tex_coord.s * 2.0) - 1.0);
xfade = xfade * xfade * xfade * xfade * xfade;
float yfade = abs((tex_coord.t * 2.0) - 1.0);
yfade = yfade * yfade * yfade * yfade * yfade;
color = color + vec4(0.7, 0.7, 0.7, 0.0) * (1.0-tex_coord.t) * (1.0-xfade) * (1.0-yfade);
vec4 newcolor;
if (column == 0.0) {
newcolor = color * vec4(1.0, 0.4, 0.6, 1.0);
} else if (column == 1.0) {
newcolor = color * vec4(0.4, 1.0, 0.4, 1.0);
} else if (column == 2.0) {
newcolor = color * vec4(0.6, 0.4, 1.0, 1.0);
} else {
newcolor = color * vec4(0.2, 0.2, 0.2, 1.0);
}
gl_FragColor = newcolor;
}
#endif

View File

@@ -1,106 +1,53 @@
other = require "other" --require "ia.other"
x=0 x=0
rot=0
function mini.init() function mini.init()
text=other.peiv() s = surf.load("gfx/logo.gif")
keyRight = tonumber(config.getKey("keyright")) or key.RIGHT surf.source(s)
keyLeft = tonumber(config.getKey("keyleft")) or key.LEFT p = pal.load("gfx/logo.gif")
mini.update=normal_update pal.set(p)
--turbo(false) pal.trans(255)
local perico = "péricòñ" --surf.save(s, "prova.gif", p)
print(utf8.len(perico))
ants = 0xc936;
s = surface.load("tiles01.gif")
--surface.source(s)
p = palette.load("tiles01.gif")
palette.set(p)
palette.setTransparent(255)
print(#p)
surface.save(s, "data/copy.gif")
s = surface.load("copy.gif")
--draw.source(s)
system.setBeat(4)
print("=== PACKAGES LOADED ===")
for name, value in pairs(package.loaded) do
print(name, value)
end
print("========================")
f = font.load("font.fnt")
end end
function mini.update() function mini.update()
if keyboard.keyPressed(key.ESCAPE) then surf.cls(0)
system.quit() draw.surfrot(0, 0, 160, 144, 120, 78, rot)
draw.text("PRESS START", 60, 110, 28)
if key.press(key.ESCAPE) then sys.quit() end
draw.text(sys.fps(), 1, 1, 28)
if key.press(key.N1) then
shader.init("lynx.glsl")
shader.enable()
end
if key.press(key.N2) then
shader.init("gbc.glsl")
shader.enable()
end
if key.press(key.N3) then
shader.disable()
end end
if system.isBeat() then local mx, my = mouse.pos()
ants = (ants >> 12) | ((ants<<4)&0xffff) draw.rectf(mx, my, 4, 4, 8)
end draw.text(mx .. " " .. my, 1, 8, 8)
surface.cls(5) --draw.text(other.peiv(),1,100,4)
draw.surface(s, 0, 0, 64, 64, 10, 10)
draw.rect(10, 10, 73, 73, 8)
draw.setPattern(ants)
draw.rect(10, 10, 73, 73, 0)
draw.setPattern(0xffff) font.current(f)
--draw.text(#p,0,0,2) font.spacing(0)
draw.text("0146",100,50,28)
font.current(font.DEFAULT)
rot=rot+1
end end
function normal_update()
if keyboard.keyPressed(key.RIGHT) then x=x+1 end
if keyboard.keyPressed(key.LEFT) then x=x-1 end
if keyboard.keyPressed(key.SPACE) then
redefinekeys.init()
end
if keyboard.keyPressed(key.ESCAPE) then
system.quit()
end
if keyboard.keyPressed(key.F2) or mouse.buttonPressed(1) then
local val = window.getZoom() + 2
if val >= 10 then val = 2 end
window.setZoom(val)
elseif keyboard.keyPressed(key.F3) then
window.setFullscreen(not window.getFullscreen())
end
if x>160 then x=-utf8.len(text)*4 end
viewport.resetClipping()
viewport.setOrigin(0,0)
surface.cls(20)
viewport.setClipping(10,10,140,100)
surface.cls(3)
draw.text("HOLA",0,0,5)
viewport.setOrigin(-70,-50)
draw.text("ORÍGIN",0,0,5)
draw.text(text,x,10,5)
draw.circFill(20,20,10,15);
draw.setPattern(0x5a5a);
draw.circFill(20,20,10,10);
draw.setPattern(0xffff);
end
redefinekeys = {
state = 0,
init = function ()
redefinekeys.state=0
_update=redefinekeys.update
end,
update = function()
surface.cls(20)
if redefinekeys.state == 0 then
draw.text("PULSA TECLA PER A DRETA...",0,0,10)
local key = keyboard.keyPressed();
if key ~= 0 then
redefinekeys.state = 1
keyRight=key
config.setKey("keyright", keyRight)
end
elseif redefinekeys.state == 1 then
draw.text("PULSA TECLA PER A ESQUERRA...",0,0,10)
local key = keyboard.keyPressed();
if key ~= 0 then
keyLeft=key
config.setKey("keyleft", keyLeft)
_update=normal_update
end
end
end
}

View File

@@ -1,6 +0,0 @@
return {
peiv = function()
palette.setColor(1, 1, 1, 1)
return "HOLA OTHER UNIT"
end
}

130
default_font.fnt Normal file
View File

@@ -0,0 +1,130 @@
bitmap=default_font
32: 0 0 3 5 0 #
33: 4 0 3 5 0 # !
34: 8 0 3 5 0 # "
35: 12 0 3 5 0 # #
36: 16 0 3 5 0 # $
37: 20 0 3 5 0 # %
38: 24 0 3 5 0 # &
39: 28 0 3 5 0 # '
40: 32 0 3 5 0 # (
41: 36 0 3 5 0 # )
42: 40 0 3 5 0 # *
43: 44 0 3 5 0 # +
44: 48 0 3 5 0 # ,
45: 52 0 3 5 0 # -
46: 56 0 3 5 0 # .
47: 60 0 3 5 0 # /
48: 0 6 3 5 0 # 0
49: 4 6 3 5 0 # 1
50: 8 6 3 5 0 # 2
51: 12 6 3 5 0 # 3
52: 16 6 3 5 0 # 4
53: 20 6 3 5 0 # 5
54: 24 6 3 5 0 # 6
55: 28 6 3 5 0 # 7
56: 32 6 3 5 0 # 8
57: 36 6 3 5 0 # 9
58: 40 6 3 5 0 # :
59: 44 6 3 5 0 # ;
60: 48 6 3 5 0 # <
61: 52 6 3 5 0 # =
62: 56 6 3 5 0 # >
63: 60 6 3 5 0 # ?
64: 0 12 3 5 0 # @
65: 4 12 3 5 0 # A
66: 8 12 3 5 0 # B
67: 12 12 3 5 0 # C
68: 16 12 3 5 0 # D
69: 20 12 3 5 0 # E
70: 24 12 3 5 0 # F
71: 28 12 3 5 0 # G
72: 32 12 3 5 0 # H
73: 36 12 3 5 0 # I
74: 40 12 3 5 0 # J
75: 44 12 3 5 0 # K
76: 48 12 3 5 0 # L
77: 52 12 3 5 0 # M
78: 56 12 3 5 0 # N
79: 60 12 3 5 0 # O
80: 0 18 3 5 0 # P
81: 4 18 3 5 0 # Q
82: 8 18 3 5 0 # R
83: 12 18 3 5 0 # S
84: 16 18 3 5 0 # T
85: 20 18 3 5 0 # U
86: 24 18 3 5 0 # V
87: 28 18 3 5 0 # W
88: 32 18 3 5 0 # X
89: 36 18 3 5 0 # Y
90: 40 18 3 5 0 # Z
91: 44 18 3 5 0 # [
92: 48 18 3 5 0 # \
93: 52 18 3 5 0 # ]
94: 56 18 3 5 0 # ^
95: 60 18 3 5 0 # _
96: 0 24 3 5 0 # `
97: 4 24 3 5 0 # a
98: 8 24 3 5 0 # b
99: 12 24 3 5 0 # c
100: 16 24 3 5 0 # d
101: 20 24 3 5 0 # e
102: 24 24 3 5 0 # f
103: 28 24 3 5 0 # g
104: 32 24 3 5 0 # h
105: 36 24 3 5 0 # i
106: 40 24 3 5 0 # j
107: 44 24 3 5 0 # k
108: 48 24 3 5 0 # l
109: 52 24 3 5 0 # m
110: 56 24 3 5 0 # n
111: 60 24 3 5 0 # o
112: 0 30 3 5 0 # p
113: 4 30 3 5 0 # q
114: 8 30 3 5 0 # r
115: 12 30 3 5 0 # s
116: 16 30 3 5 0 # t
117: 20 30 3 5 0 # u
118: 24 30 3 5 0 # v
119: 28 30 3 5 0 # w
120: 32 30 3 5 0 # x
121: 36 30 3 5 0 # y
122: 40 30 3 5 0 # z
123: 44 30 3 5 0 # {
124: 48 30 3 5 0 # |
125: 52 30 3 5 0 # }
126: 56 30 3 5 0 # ~
127: 60 30 3 5 0 # ⌂ (DEL placeholder)
# Extended characters
161: 0 36 3 5 0 # ¡
191: 4 36 3 5 0 # ¿
192: 8 36 3 8 3 # À
193: 12 36 3 8 3 # Á
200: 16 36 3 8 3 # È
201: 20 36 3 8 3 # É
204: 24 36 3 8 3 # Ì
205: 28 36 3 8 3 # Í
210: 32 36 3 8 3 # Ò
211: 36 36 3 8 3 # Ó
217: 40 36 3 8 3 # Ù
218: 44 36 3 8 3 # Ú
209: 48 36 3 7 2 # Ñ
241: 52 36 3 6 1 # ñ
199: 56 36 3 5 0 # Ç
231: 60 36 3 5 0 # ç
224: 0 45 3 7 2 # à
225: 4 45 3 7 2 # á
232: 8 45 3 7 2 # è
233: 12 45 3 7 2 # é
236: 16 45 3 7 2 # ì
237: 20 45 3 7 2 # í
242: 24 45 3 7 2 # ò
243: 28 45 3 7 2 # ó
249: 32 45 3 7 2 # ù
250: 36 45 3 7 2 # ú

BIN
default_font.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

223
default_font_fnt.h Normal file
View File

@@ -0,0 +1,223 @@
unsigned char default_font_fnt[] = {
0x62, 0x69, 0x74, 0x6d, 0x61, 0x70, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75,
0x6c, 0x74, 0x5f, 0x66, 0x6f, 0x6e, 0x74, 0x0a, 0x33, 0x32, 0x3a, 0x20,
0x30, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x20,
0x23, 0x20, 0x20, 0x0a, 0x33, 0x33, 0x3a, 0x20, 0x34, 0x20, 0x30, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x20, 0x23, 0x20, 0x21, 0x0a,
0x33, 0x34, 0x3a, 0x20, 0x38, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20,
0x30, 0x20, 0x20, 0x20, 0x23, 0x20, 0x22, 0x0a, 0x33, 0x35, 0x3a, 0x20,
0x31, 0x32, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20,
0x23, 0x20, 0x23, 0x0a, 0x33, 0x36, 0x3a, 0x20, 0x31, 0x36, 0x20, 0x30,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x24, 0x0a,
0x33, 0x37, 0x3a, 0x20, 0x32, 0x30, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x25, 0x0a, 0x33, 0x38, 0x3a, 0x20,
0x32, 0x34, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20,
0x23, 0x20, 0x26, 0x0a, 0x33, 0x39, 0x3a, 0x20, 0x32, 0x38, 0x20, 0x30,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x27, 0x0a,
0x34, 0x30, 0x3a, 0x20, 0x33, 0x32, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x28, 0x0a, 0x34, 0x31, 0x3a, 0x20,
0x33, 0x36, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20,
0x23, 0x20, 0x29, 0x0a, 0x34, 0x32, 0x3a, 0x20, 0x34, 0x30, 0x20, 0x30,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x2a, 0x0a,
0x34, 0x33, 0x3a, 0x20, 0x34, 0x34, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x2b, 0x0a, 0x34, 0x34, 0x3a, 0x20,
0x34, 0x38, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20,
0x23, 0x20, 0x2c, 0x0a, 0x34, 0x35, 0x3a, 0x20, 0x35, 0x32, 0x20, 0x30,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x2d, 0x0a,
0x34, 0x36, 0x3a, 0x20, 0x35, 0x36, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x2e, 0x0a, 0x34, 0x37, 0x3a, 0x20,
0x36, 0x30, 0x20, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20,
0x23, 0x20, 0x2f, 0x0a, 0x0a, 0x34, 0x38, 0x3a, 0x20, 0x30, 0x20, 0x36,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x20, 0x23, 0x20, 0x30,
0x0a, 0x34, 0x39, 0x3a, 0x20, 0x34, 0x20, 0x36, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x20, 0x20, 0x23, 0x20, 0x31, 0x0a, 0x35, 0x30, 0x3a,
0x20, 0x38, 0x20, 0x36, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20,
0x20, 0x23, 0x20, 0x32, 0x0a, 0x35, 0x31, 0x3a, 0x20, 0x31, 0x32, 0x20,
0x36, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x33,
0x0a, 0x35, 0x32, 0x3a, 0x20, 0x31, 0x36, 0x20, 0x36, 0x20, 0x33, 0x20,
0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x34, 0x0a, 0x35, 0x33, 0x3a,
0x20, 0x32, 0x30, 0x20, 0x36, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20,
0x20, 0x23, 0x20, 0x35, 0x0a, 0x35, 0x34, 0x3a, 0x20, 0x32, 0x34, 0x20,
0x36, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x36,
0x0a, 0x35, 0x35, 0x3a, 0x20, 0x32, 0x38, 0x20, 0x36, 0x20, 0x33, 0x20,
0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x37, 0x0a, 0x35, 0x36, 0x3a,
0x20, 0x33, 0x32, 0x20, 0x36, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20,
0x20, 0x23, 0x20, 0x38, 0x0a, 0x35, 0x37, 0x3a, 0x20, 0x33, 0x36, 0x20,
0x36, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x39,
0x0a, 0x35, 0x38, 0x3a, 0x20, 0x34, 0x30, 0x20, 0x36, 0x20, 0x33, 0x20,
0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x3a, 0x0a, 0x35, 0x39, 0x3a,
0x20, 0x34, 0x34, 0x20, 0x36, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20,
0x20, 0x23, 0x20, 0x3b, 0x0a, 0x36, 0x30, 0x3a, 0x20, 0x34, 0x38, 0x20,
0x36, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x3c,
0x0a, 0x36, 0x31, 0x3a, 0x20, 0x35, 0x32, 0x20, 0x36, 0x20, 0x33, 0x20,
0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x3d, 0x0a, 0x36, 0x32, 0x3a,
0x20, 0x35, 0x36, 0x20, 0x36, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20,
0x20, 0x23, 0x20, 0x3e, 0x0a, 0x36, 0x33, 0x3a, 0x20, 0x36, 0x30, 0x20,
0x36, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x3f,
0x0a, 0x0a, 0x36, 0x34, 0x3a, 0x20, 0x30, 0x20, 0x31, 0x32, 0x20, 0x33,
0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x40, 0x0a, 0x36, 0x35,
0x3a, 0x20, 0x34, 0x20, 0x31, 0x32, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30,
0x20, 0x20, 0x23, 0x20, 0x41, 0x0a, 0x36, 0x36, 0x3a, 0x20, 0x38, 0x20,
0x31, 0x32, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20,
0x42, 0x0a, 0x36, 0x37, 0x3a, 0x20, 0x31, 0x32, 0x20, 0x31, 0x32, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x43, 0x0a, 0x36, 0x38,
0x3a, 0x20, 0x31, 0x36, 0x20, 0x31, 0x32, 0x20, 0x33, 0x20, 0x35, 0x20,
0x30, 0x20, 0x23, 0x20, 0x44, 0x0a, 0x36, 0x39, 0x3a, 0x20, 0x32, 0x30,
0x20, 0x31, 0x32, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20,
0x45, 0x0a, 0x37, 0x30, 0x3a, 0x20, 0x32, 0x34, 0x20, 0x31, 0x32, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x46, 0x0a, 0x37, 0x31,
0x3a, 0x20, 0x32, 0x38, 0x20, 0x31, 0x32, 0x20, 0x33, 0x20, 0x35, 0x20,
0x30, 0x20, 0x23, 0x20, 0x47, 0x0a, 0x37, 0x32, 0x3a, 0x20, 0x33, 0x32,
0x20, 0x31, 0x32, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20,
0x48, 0x0a, 0x37, 0x33, 0x3a, 0x20, 0x33, 0x36, 0x20, 0x31, 0x32, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x49, 0x0a, 0x37, 0x34,
0x3a, 0x20, 0x34, 0x30, 0x20, 0x31, 0x32, 0x20, 0x33, 0x20, 0x35, 0x20,
0x30, 0x20, 0x23, 0x20, 0x4a, 0x0a, 0x37, 0x35, 0x3a, 0x20, 0x34, 0x34,
0x20, 0x31, 0x32, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20,
0x4b, 0x0a, 0x37, 0x36, 0x3a, 0x20, 0x34, 0x38, 0x20, 0x31, 0x32, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x4c, 0x0a, 0x37, 0x37,
0x3a, 0x20, 0x35, 0x32, 0x20, 0x31, 0x32, 0x20, 0x33, 0x20, 0x35, 0x20,
0x30, 0x20, 0x23, 0x20, 0x4d, 0x0a, 0x37, 0x38, 0x3a, 0x20, 0x35, 0x36,
0x20, 0x31, 0x32, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20,
0x4e, 0x0a, 0x37, 0x39, 0x3a, 0x20, 0x36, 0x30, 0x20, 0x31, 0x32, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x4f, 0x0a, 0x0a, 0x38,
0x30, 0x3a, 0x20, 0x30, 0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35, 0x20,
0x30, 0x20, 0x20, 0x23, 0x20, 0x50, 0x0a, 0x38, 0x31, 0x3a, 0x20, 0x34,
0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23,
0x20, 0x51, 0x0a, 0x38, 0x32, 0x3a, 0x20, 0x38, 0x20, 0x31, 0x38, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x52, 0x0a, 0x38,
0x33, 0x3a, 0x20, 0x31, 0x32, 0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x23, 0x20, 0x53, 0x0a, 0x38, 0x34, 0x3a, 0x20, 0x31,
0x36, 0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23,
0x20, 0x54, 0x0a, 0x38, 0x35, 0x3a, 0x20, 0x32, 0x30, 0x20, 0x31, 0x38,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x55, 0x0a, 0x38,
0x36, 0x3a, 0x20, 0x32, 0x34, 0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x23, 0x20, 0x56, 0x0a, 0x38, 0x37, 0x3a, 0x20, 0x32,
0x38, 0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23,
0x20, 0x57, 0x0a, 0x38, 0x38, 0x3a, 0x20, 0x33, 0x32, 0x20, 0x31, 0x38,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x58, 0x0a, 0x38,
0x39, 0x3a, 0x20, 0x33, 0x36, 0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x23, 0x20, 0x59, 0x0a, 0x39, 0x30, 0x3a, 0x20, 0x34,
0x30, 0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23,
0x20, 0x5a, 0x0a, 0x39, 0x31, 0x3a, 0x20, 0x34, 0x34, 0x20, 0x31, 0x38,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x5b, 0x0a, 0x39,
0x32, 0x3a, 0x20, 0x34, 0x38, 0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x23, 0x20, 0x5c, 0x0a, 0x39, 0x33, 0x3a, 0x20, 0x35,
0x32, 0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23,
0x20, 0x5d, 0x0a, 0x39, 0x34, 0x3a, 0x20, 0x35, 0x36, 0x20, 0x31, 0x38,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x5e, 0x0a, 0x39,
0x35, 0x3a, 0x20, 0x36, 0x30, 0x20, 0x31, 0x38, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x23, 0x20, 0x5f, 0x0a, 0x0a, 0x39, 0x36, 0x3a, 0x20,
0x30, 0x20, 0x32, 0x34, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20,
0x23, 0x20, 0x60, 0x0a, 0x39, 0x37, 0x3a, 0x20, 0x34, 0x20, 0x32, 0x34,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x61, 0x0a,
0x39, 0x38, 0x3a, 0x20, 0x38, 0x20, 0x32, 0x34, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x62, 0x0a, 0x39, 0x39, 0x3a, 0x20,
0x31, 0x32, 0x20, 0x32, 0x34, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20,
0x23, 0x20, 0x63, 0x0a, 0x31, 0x30, 0x30, 0x3a, 0x20, 0x31, 0x36, 0x20,
0x32, 0x34, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x64,
0x0a, 0x31, 0x30, 0x31, 0x3a, 0x20, 0x32, 0x30, 0x20, 0x32, 0x34, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x65, 0x0a, 0x31, 0x30,
0x32, 0x3a, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x23, 0x20, 0x66, 0x0a, 0x31, 0x30, 0x33, 0x3a, 0x20,
0x32, 0x38, 0x20, 0x32, 0x34, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20,
0x23, 0x20, 0x67, 0x0a, 0x31, 0x30, 0x34, 0x3a, 0x20, 0x33, 0x32, 0x20,
0x32, 0x34, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x68,
0x0a, 0x31, 0x30, 0x35, 0x3a, 0x20, 0x33, 0x36, 0x20, 0x32, 0x34, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x69, 0x0a, 0x31, 0x30,
0x36, 0x3a, 0x20, 0x34, 0x30, 0x20, 0x32, 0x34, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x23, 0x20, 0x6a, 0x0a, 0x31, 0x30, 0x37, 0x3a, 0x20,
0x34, 0x34, 0x20, 0x32, 0x34, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20,
0x23, 0x20, 0x6b, 0x0a, 0x31, 0x30, 0x38, 0x3a, 0x20, 0x34, 0x38, 0x20,
0x32, 0x34, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x6c,
0x0a, 0x31, 0x30, 0x39, 0x3a, 0x20, 0x35, 0x32, 0x20, 0x32, 0x34, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x6d, 0x0a, 0x31, 0x31,
0x30, 0x3a, 0x20, 0x35, 0x36, 0x20, 0x32, 0x34, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x23, 0x20, 0x6e, 0x0a, 0x31, 0x31, 0x31, 0x3a, 0x20,
0x36, 0x30, 0x20, 0x32, 0x34, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20,
0x23, 0x20, 0x6f, 0x0a, 0x0a, 0x31, 0x31, 0x32, 0x3a, 0x20, 0x30, 0x20,
0x33, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20,
0x70, 0x0a, 0x31, 0x31, 0x33, 0x3a, 0x20, 0x34, 0x20, 0x33, 0x30, 0x20,
0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x71, 0x0a, 0x31,
0x31, 0x34, 0x3a, 0x20, 0x38, 0x20, 0x33, 0x30, 0x20, 0x33, 0x20, 0x35,
0x20, 0x30, 0x20, 0x20, 0x23, 0x20, 0x72, 0x0a, 0x31, 0x31, 0x35, 0x3a,
0x20, 0x31, 0x32, 0x20, 0x33, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30,
0x20, 0x23, 0x20, 0x73, 0x0a, 0x31, 0x31, 0x36, 0x3a, 0x20, 0x31, 0x36,
0x20, 0x33, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20,
0x74, 0x0a, 0x31, 0x31, 0x37, 0x3a, 0x20, 0x32, 0x30, 0x20, 0x33, 0x30,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x75, 0x0a, 0x31,
0x31, 0x38, 0x3a, 0x20, 0x32, 0x34, 0x20, 0x33, 0x30, 0x20, 0x33, 0x20,
0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x76, 0x0a, 0x31, 0x31, 0x39, 0x3a,
0x20, 0x32, 0x38, 0x20, 0x33, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30,
0x20, 0x23, 0x20, 0x77, 0x0a, 0x31, 0x32, 0x30, 0x3a, 0x20, 0x33, 0x32,
0x20, 0x33, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20,
0x78, 0x0a, 0x31, 0x32, 0x31, 0x3a, 0x20, 0x33, 0x36, 0x20, 0x33, 0x30,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x79, 0x0a, 0x31,
0x32, 0x32, 0x3a, 0x20, 0x34, 0x30, 0x20, 0x33, 0x30, 0x20, 0x33, 0x20,
0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x7a, 0x0a, 0x31, 0x32, 0x33, 0x3a,
0x20, 0x34, 0x34, 0x20, 0x33, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30,
0x20, 0x23, 0x20, 0x7b, 0x0a, 0x31, 0x32, 0x34, 0x3a, 0x20, 0x34, 0x38,
0x20, 0x33, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20,
0x7c, 0x0a, 0x31, 0x32, 0x35, 0x3a, 0x20, 0x35, 0x32, 0x20, 0x33, 0x30,
0x20, 0x33, 0x20, 0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x7d, 0x0a, 0x31,
0x32, 0x36, 0x3a, 0x20, 0x35, 0x36, 0x20, 0x33, 0x30, 0x20, 0x33, 0x20,
0x35, 0x20, 0x30, 0x20, 0x23, 0x20, 0x7e, 0x0a, 0x31, 0x32, 0x37, 0x3a,
0x20, 0x36, 0x30, 0x20, 0x33, 0x30, 0x20, 0x33, 0x20, 0x35, 0x20, 0x30,
0x20, 0x23, 0x20, 0xe2, 0x8c, 0x82, 0x20, 0x28, 0x44, 0x45, 0x4c, 0x20,
0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x29,
0x0a, 0x0a, 0x23, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64,
0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x0a,
0x31, 0x36, 0x31, 0x3a, 0x20, 0x30, 0x20, 0x33, 0x36, 0x20, 0x33, 0x20,
0x35, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc2, 0xa1, 0x0a,
0x31, 0x39, 0x31, 0x3a, 0x20, 0x34, 0x20, 0x33, 0x36, 0x20, 0x33, 0x20,
0x35, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc2, 0xbf, 0x0a,
0x31, 0x39, 0x32, 0x3a, 0x20, 0x38, 0x20, 0x33, 0x36, 0x20, 0x33, 0x20,
0x38, 0x20, 0x33, 0x20, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x80, 0x0a,
0x31, 0x39, 0x33, 0x3a, 0x20, 0x31, 0x32, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x38, 0x20, 0x33, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x81, 0x0a,
0x32, 0x30, 0x30, 0x3a, 0x20, 0x31, 0x36, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x38, 0x20, 0x33, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x88, 0x0a,
0x32, 0x30, 0x31, 0x3a, 0x20, 0x32, 0x30, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x38, 0x20, 0x33, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x89, 0x0a,
0x32, 0x30, 0x34, 0x3a, 0x20, 0x32, 0x34, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x38, 0x20, 0x33, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x8c, 0x0a,
0x32, 0x30, 0x35, 0x3a, 0x20, 0x32, 0x38, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x38, 0x20, 0x33, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x8d, 0x0a,
0x32, 0x31, 0x30, 0x3a, 0x20, 0x33, 0x32, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x38, 0x20, 0x33, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x92, 0x0a,
0x32, 0x31, 0x31, 0x3a, 0x20, 0x33, 0x36, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x38, 0x20, 0x33, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x93, 0x0a,
0x32, 0x31, 0x37, 0x3a, 0x20, 0x34, 0x30, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x38, 0x20, 0x33, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x99, 0x0a,
0x32, 0x31, 0x38, 0x3a, 0x20, 0x34, 0x34, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x38, 0x20, 0x33, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x9a, 0x0a,
0x32, 0x30, 0x39, 0x3a, 0x20, 0x34, 0x38, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x37, 0x20, 0x32, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x91, 0x0a,
0x32, 0x34, 0x31, 0x3a, 0x20, 0x35, 0x32, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x36, 0x20, 0x31, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xb1, 0x0a,
0x31, 0x39, 0x39, 0x3a, 0x20, 0x35, 0x36, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0x87, 0x0a,
0x32, 0x33, 0x31, 0x3a, 0x20, 0x36, 0x30, 0x20, 0x33, 0x36, 0x20, 0x33,
0x20, 0x35, 0x20, 0x30, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xa7, 0x0a,
0x32, 0x32, 0x34, 0x3a, 0x20, 0x30, 0x20, 0x34, 0x35, 0x20, 0x33, 0x20,
0x37, 0x20, 0x32, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xa0, 0x0a, 0x32,
0x32, 0x35, 0x3a, 0x20, 0x34, 0x20, 0x34, 0x35, 0x20, 0x33, 0x20, 0x37,
0x20, 0x32, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xa1, 0x0a, 0x32, 0x33,
0x32, 0x3a, 0x20, 0x38, 0x20, 0x34, 0x35, 0x20, 0x33, 0x20, 0x37, 0x20,
0x32, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xa8, 0x0a, 0x32, 0x33, 0x33,
0x3a, 0x20, 0x31, 0x32, 0x20, 0x34, 0x35, 0x20, 0x33, 0x20, 0x37, 0x20,
0x32, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xa9, 0x0a, 0x32, 0x33, 0x36,
0x3a, 0x20, 0x31, 0x36, 0x20, 0x34, 0x35, 0x20, 0x33, 0x20, 0x37, 0x20,
0x32, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xac, 0x0a, 0x32, 0x33, 0x37,
0x3a, 0x20, 0x32, 0x30, 0x20, 0x34, 0x35, 0x20, 0x33, 0x20, 0x37, 0x20,
0x32, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xad, 0x0a, 0x32, 0x34, 0x32,
0x3a, 0x20, 0x32, 0x34, 0x20, 0x34, 0x35, 0x20, 0x33, 0x20, 0x37, 0x20,
0x32, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xb2, 0x0a, 0x32, 0x34, 0x33,
0x3a, 0x20, 0x32, 0x38, 0x20, 0x34, 0x35, 0x20, 0x33, 0x20, 0x37, 0x20,
0x32, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xb3, 0x0a, 0x32, 0x34, 0x39,
0x3a, 0x20, 0x33, 0x32, 0x20, 0x34, 0x35, 0x20, 0x33, 0x20, 0x37, 0x20,
0x32, 0x20, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xb9, 0x0a, 0x32, 0x35, 0x30,
0x3a, 0x20, 0x33, 0x36, 0x20, 0x34, 0x35, 0x20, 0x33, 0x20, 0x37, 0x20,
0x32, 0x20, 0x20, 0x23, 0x20, 0xc3, 0xba, 0x0a, 0x00
};
unsigned int default_font_fnt_len = 2637;

42
default_font_gif.h Normal file
View File

@@ -0,0 +1,42 @@
unsigned char default_font_gif[] = {
0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x40, 0x00, 0x36, 0x00, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x21, 0xf9, 0x04, 0x08, 0x01,
0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x36, 0x00,
0x00, 0x02, 0xff, 0x84, 0x1d, 0x08, 0xc9, 0x1b, 0xcd, 0x92, 0x9a, 0x4b,
0xc9, 0x83, 0x73, 0xbe, 0x47, 0xc2, 0xe7, 0x60, 0x11, 0xc5, 0x55, 0xe6,
0xa9, 0x69, 0x25, 0xd5, 0x99, 0xa0, 0xbb, 0x96, 0xd1, 0xbc, 0xbd, 0x62,
0x9a, 0x3e, 0xf4, 0xd5, 0xdc, 0x3e, 0xdf, 0xc2, 0xb1, 0x82, 0x37, 0x8f,
0xc5, 0x11, 0x0b, 0xf6, 0x88, 0x9b, 0xa1, 0xf0, 0x09, 0x8d, 0x4a, 0x73,
0xa0, 0x97, 0x0e, 0x59, 0xd9, 0x75, 0xaa, 0xdc, 0x55, 0xd3, 0x87, 0xed,
0x71, 0x80, 0x10, 0x66, 0xf6, 0x6c, 0x24, 0x21, 0xac, 0x45, 0xd7, 0xda,
0xb3, 0xeb, 0xb6, 0xae, 0x57, 0x9c, 0x77, 0x52, 0x75, 0xa3, 0x4e, 0x64,
0xfe, 0x19, 0x4f, 0x04, 0x97, 0x26, 0x22, 0x47, 0x67, 0x13, 0x47, 0x76,
0xf8, 0x65, 0x36, 0x36, 0xe5, 0xf8, 0x08, 0xf9, 0x65, 0x08, 0x17, 0x12,
0x66, 0x55, 0x36, 0x89, 0xb6, 0x35, 0xb2, 0xa6, 0x89, 0x39, 0xe7, 0xa7,
0x36, 0x68, 0xb4, 0x44, 0xe7, 0x99, 0xc5, 0x25, 0x5a, 0xc9, 0xf6, 0xa6,
0xb6, 0x0a, 0xfa, 0xd9, 0x57, 0x76, 0x04, 0x44, 0xab, 0xe7, 0x56, 0x7a,
0x4a, 0xf9, 0xb1, 0x5b, 0xb8, 0x89, 0x96, 0x0a, 0x1c, 0x5b, 0x19, 0x59,
0x6c, 0x4c, 0x95, 0x56, 0xe7, 0x3b, 0x1c, 0x1b, 0x3c, 0x36, 0x08, 0x7b,
0xaa, 0xa4, 0x2b, 0xfd, 0xc7, 0x32, 0xfb, 0xfb, 0xd1, 0x8a, 0x2b, 0x2d,
0x08, 0xc8, 0x74, 0xc7, 0x47, 0x3a, 0x2d, 0x1c, 0xe6, 0x57, 0x7b, 0x2d,
0xf4, 0x0c, 0x1c, 0x98, 0x9c, 0x87, 0x48, 0x0c, 0x53, 0x13, 0x7e, 0x5c,
0x3f, 0x45, 0x6f, 0x9f, 0x9f, 0x63, 0xd9, 0x7a, 0x09, 0xcf, 0x6b, 0xae,
0x54, 0xb0, 0x78, 0xec, 0xce, 0xad, 0x1a, 0x75, 0x8b, 0x92, 0xb8, 0x61,
0x84, 0x3e, 0xd9, 0x52, 0xa5, 0x6c, 0x5a, 0x2e, 0x86, 0xb0, 0x0a, 0x79,
0xe3, 0xf1, 0x8e, 0x5f, 0xb9, 0x66, 0xa0, 0xfa, 0x3a, 0x7a, 0xfc, 0x58,
0x03, 0x0f, 0xbd, 0x88, 0x58, 0x42, 0x98, 0x62, 0xe6, 0x89, 0x55, 0xa8,
0x6f, 0x28, 0x1b, 0x51, 0x73, 0x97, 0xa8, 0x5d, 0x40, 0x8d, 0x36, 0xf4,
0x00, 0x3c, 0x09, 0x2a, 0x10, 0x39, 0x4d, 0x5b, 0x0a, 0x8a, 0x13, 0x89,
0x49, 0xce, 0x2b, 0x82, 0x25, 0x41, 0x1a, 0x5d, 0x04, 0xcd, 0xda, 0x91,
0x36, 0x4c, 0xe7, 0x08, 0xad, 0xf9, 0x04, 0x9d, 0x54, 0x9d, 0xae, 0xf6,
0x20, 0x65, 0x05, 0xf5, 0xa8, 0x0a, 0x85, 0xe8, 0x12, 0x5a, 0xfc, 0x77,
0xa9, 0x53, 0x4b, 0x6b, 0x2e, 0x71, 0x62, 0x73, 0xc9, 0x6d, 0xec, 0x2c,
0xa1, 0xc8, 0x68, 0x4e, 0x7d, 0x09, 0x77, 0xe5, 0x3e, 0x87, 0x28, 0x6a,
0xa9, 0x55, 0x0a, 0xa9, 0x19, 0x58, 0x4e, 0x87, 0x14, 0x6a, 0xfd, 0x7b,
0xaf, 0x89, 0x8c, 0x3d, 0x4b, 0x96, 0x9a, 0x39, 0xf6, 0x76, 0x65, 0xe2,
0xae, 0x80, 0x1b, 0xe7, 0xfd, 0x6a, 0x89, 0xc6, 0xc1, 0x6a, 0xf5, 0x38,
0x12, 0xb3, 0x0b, 0x17, 0xdf, 0x3d, 0x5f, 0xe9, 0x00, 0x8d, 0xcd, 0xa7,
0x37, 0xb2, 0xdb, 0x9e, 0x44, 0x1d, 0x9b, 0x3e, 0xed, 0xb8, 0x00, 0x00,
0x3b
};
unsigned int default_font_gif_len = 457;

33
do_release.bat Normal file
View File

@@ -0,0 +1,33 @@
@echo off
REM Comprobar parámetro
IF "%1"=="" (
echo Uso: build_windows.bat ^<PARAMETRO^>
exit /b 1
)
set PARAM=%1
echo Compilando windows...
make windows || exit /b 1
echo Compilando windows_debug...
make windows_debug || exit /b 1
echo Creando paquetes...
copy bin\SDL3.dll .
copy bin\libwinpthread-1.dll .
REM Crear ZIP release con mini.exe + DLLs
tar -a -c -f mini_%PARAM%_win32-x64_release.zip mini.exe *.dll || exit /b 1
REM Crear ZIP debug solo con mini_debug.exe
tar -a -c -f mini_%PARAM%_win32-x64_debug.zip mini_debug.exe *.dll || exit /b 1
del SDL3.dll
del libwinpthread-1.dll
echo Paquetes generados:
echo mini_%PARAM%_win32-x64_release.zip
echo mini_%PARAM%_win32-x64_debug.zip

41
do_release.sh Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/bash
set -e
#if [ -z "$1" ]; then
# echo "Uso: $0 <PARAMETRO>"
# exit 1
#fi
# Leer versión desde version.h
VERSION=$(grep '#define MINI_VERSION' version.h | sed 's/.*"\(.*\)".*/\1/')
echo "Versión detectada: $VERSION"
#PARAM=$1
# Datos Windows
WIN_USER="raimon"
WIN_HOST="tonlab19"
WIN_PATH_SSH="C:\Users\raimon\dev\mini"
WIN_PATH_SCP="C:/Users/Raimon/dev/mini"
echo "=== Compilando Linux ==="
make linux
make linux_debug
echo "=== Empaquetando Linux ==="
tar -czf mini_v${VERSION}_linux_release.tar.gz mini
tar -czf mini_v${VERSION}_linux_debug.tar.gz mini_debug
echo "=== Ejecutando build remoto Windows ==="
ssh ${WIN_USER}@${WIN_HOST} "cd ${WIN_PATH_SSH} && do_release.bat v${VERSION}"
echo "=== Copiando ZIPs desde Windows ==="
scp ${WIN_USER}@${WIN_HOST}:"${WIN_PATH_SCP}/mini_v${VERSION}_win32-x64_release.zip" .
scp ${WIN_USER}@${WIN_HOST}:"${WIN_PATH_SCP}/mini_v${VERSION}_win32-x64_debug.zip" .
echo "=== Build completado correctamente ==="
echo "Generados:"
echo " mini_v${VERSION}_linux_release.tar.gz"
echo " mini_v${VERSION}_linux_debug.tar.gz"
echo " mini_v${VERSION}_win32-x64_release.zip"
echo " mini_v${VERSION}_win32-x64_debug.zip"

View File

@@ -22,19 +22,12 @@ struct dictionary_entry_t
void uncompress( int code_length, const uint8_t *input, int input_length, uint8_t *out ) void uncompress( int code_length, const uint8_t *input, int input_length, uint8_t *out )
{ {
int i, bit;
int code, prev = -1;
dictionary_entry_t *dictionary; dictionary_entry_t *dictionary;
int dictionary_ind; int dictionary_ind;
uint32_t 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 ); const int clear_code = 1 << ( code_length );
stop_code = clear_code + 1; const int stop_code = clear_code + 1;
reset_code_length = code_length; const int reset_code_length = code_length;
dictionary = ( dictionary_entry_t * ) dictionary = ( dictionary_entry_t * )
malloc( sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) ); malloc( sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
@@ -47,12 +40,15 @@ void uncompress( int code_length, const uint8_t *input, int input_length, uint8_
} }
dictionary_ind+=2; dictionary_ind+=2;
int prev = -1;
uint32_t mask = 0x01;
while ( input_length ) while ( input_length )
{ {
code = 0x0; int code = 0x0;
for (i=0; i<(code_length + 1); i++)
for (int i=0; i<(code_length + 1); i++)
{ {
bit = ( *input & mask ) ? 1 : 0; const int bit = ( *input & mask ) ? 1 : 0;
mask <<= 1; mask <<= 1;
if ( mask == 0x100 ) if ( mask == 0x100 )
@@ -90,18 +86,9 @@ void uncompress( int code_length, const uint8_t *input, int input_length, uint8_
exit( 0 ); exit( 0 );
} }
if ( code == dictionary_ind ) int ptr = (code == dictionary_ind) ? prev : code;
{ while ( dictionary[ ptr ].prev != -1 ) ptr = dictionary[ ptr ].prev;
int ptr = prev; dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
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 ].prev = prev;
dictionary[ dictionary_ind ].len = dictionary[ prev ].len + 1; dictionary[ dictionary_ind ].len = dictionary[ prev ].len + 1;
@@ -116,7 +103,7 @@ void uncompress( int code_length, const uint8_t *input, int input_length, uint8_
prev = code; prev = code;
match_len = dictionary[ code ].len; const int match_len = dictionary[ code ].len;
while ( code != -1 ) while ( code != -1 )
{ {
out[ dictionary[ code ].len - 1 ] = dictionary[ code ].byte; out[ dictionary[ code ].len - 1 ] = dictionary[ code ].byte;
@@ -197,8 +184,8 @@ static uint8_t* LoadGif(uint8_t *buffer, uint16_t* w, uint16_t* h)
rgb *global_color_table = NULL; rgb *global_color_table = NULL;
buffer += 6; // Ignore header buffer += 6; // Ignore header
*w = (uint16_t)*buffer; buffer+=2; *w = *((uint16_t*)buffer); buffer+=2;
*h = (uint16_t)*buffer; buffer+=2; *h = *((uint16_t*)buffer); buffer+=2;
const uint8_t fields = *buffer; buffer+=3; const uint8_t fields = *buffer; buffer+=3;
const int color_resolution_bits = ( ( fields & 0x70 ) >> 4 ) + 1; const int color_resolution_bits = ( ( fields & 0x70 ) >> 4 ) + 1;

332
gifenc.h
View File

@@ -3,226 +3,172 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#define MAX_DICT_SIZE 4096
namespace gif namespace gif
{ {
struct gif_t { typedef struct {
uint16_t w, h; int prefix;
int depth; uint8_t character;
int bgindex; } DictEntry;
FILE *fd;
int offset;
int nframes;
uint8_t *frame, *back;
uint32_t partial;
uint8_t buffer[0xFF];
};
struct node_t { typedef struct {
uint16_t key; uint8_t *data;
node_t *children[]; size_t size;
}; size_t capacity;
int bit_pos;
uint32_t bit_buffer;
} BitStream;
static node_t *new_node(uint16_t key, int degree) void bitstream_init(BitStream *bs) {
{ bs->capacity = 256;
node_t *node = (node_t*)calloc(1, sizeof(*node) + degree * sizeof(node_t *)); bs->size = 0;
if (node) node->key = key; bs->data = (uint8_t*)malloc(bs->capacity);
return node; bs->bit_pos = 0;
bs->bit_buffer = 0;
} }
static node_t *new_trie(int degree, int *nkeys) void bitstream_write(BitStream *bs, uint16_t code, int code_size) {
{ bs->bit_buffer |= ((uint32_t)code) << bs->bit_pos;
node_t *root = new_node(0, degree); bs->bit_pos += code_size;
/* Create nodes for single pixels. */
for (*nkeys = 0; *nkeys < degree; (*nkeys)++) root->children[*nkeys] = new_node(*nkeys, degree);
*nkeys += 2; /* skip clear code and stop code */
return root;
}
static void del_trie(node_t *root, int degree) while (bs->bit_pos >= 8) {
{ if (bs->size >= bs->capacity) {
if (!root) return; bs->capacity *= 2;
for (int i = 0; i < degree; i++) del_trie(root->children[i], degree); bs->data = (uint8_t*)realloc(bs->data, bs->capacity);
free(root);
}
static void put_loop(gif_t *gif, uint16_t loop);
gif_t *create(const char *fname, uint16_t width, uint16_t height, uint8_t *palette, uint8_t depth, int16_t bgindex, int loop)
{
gif_t *gif = (gif_t*)calloc(1, sizeof(*gif) + (bgindex < 0 ? 2 : 1)*width*height);
gif->w = width; gif->h = height;
gif->bgindex = bgindex;
gif->frame = (uint8_t *) &gif[1];
gif->back = &gif->frame[width*height];
gif->fd = fopen(fname, "wb");
if (!gif->fd) { free(gif); return NULL; }
fwrite("GIF89a", 6, 1, gif->fd);
fwrite(&width, 2, 1, gif->fd);
fwrite(&height, 2, 1, gif->fd);
gif->depth = depth;
fputc((!palette?0x70:0xF0|(depth-1)), gif->fd);
fputc(bgindex, gif->fd); fputc(0, gif->fd);
if (palette) fwrite(palette, 3 << depth, 1, gif->fd);
if (loop >= 0 && loop <= 0xFFFF) put_loop(gif, (uint16_t)loop);
return gif;
}
static void put_loop(gif_t *gif, uint16_t loop)
{
fputc('!', gif->fd); fputc(0xFF, gif->fd); fputc(0x0B, gif->fd);
fwrite("NETSCAPE2.0", 11, 1, gif->fd);
fputc(0x03, gif->fd); fputc(0x01, gif->fd);
fwrite(&loop, 2, 1, gif->fd);
fputc(0, gif->fd);
}
/* Add packed key to buffer, updating offset and partial.
* gif->offset holds position to put next *bit*
* gif->partial holds bits to include in next byte */
static void put_key(gif_t *gif, uint16_t key, int key_size)
{
int byte_offset, bit_offset, bits_to_write;
byte_offset = gif->offset / 8;
bit_offset = gif->offset % 8;
gif->partial |= ((uint32_t) key) << bit_offset;
bits_to_write = bit_offset + key_size;
while (bits_to_write >= 8) {
gif->buffer[byte_offset++] = gif->partial & 0xFF;
if (byte_offset == 0xFF) {
fputc(0xFF, gif->fd);
fwrite(gif->buffer, 0xFF, 1, gif->fd);
byte_offset = 0;
} }
gif->partial >>= 8; bs->data[bs->size++] = bs->bit_buffer & 0xFF;
bits_to_write -= 8; bs->bit_buffer >>= 8;
bs->bit_pos -= 8;
} }
gif->offset = (gif->offset + key_size) % (0xFF * 8);
} }
static void end_key(gif_t *gif) void bitstream_flush(BitStream *bs) {
{ if (bs->bit_pos > 0) {
uint8_t byte_offset; if (bs->size >= bs->capacity) {
byte_offset = gif->offset >> 3; bs->capacity *= 2;
if (gif->offset & 0x07) gif->buffer[byte_offset++] = gif->partial & 0xFF; bs->data = (uint8_t*)realloc(bs->data, bs->capacity);
if (byte_offset) }
{ bs->data[bs->size++] = bs->bit_buffer & 0xFF;
fputc(byte_offset, gif->fd);
fwrite(gif->buffer, byte_offset, 1, gif->fd);
} }
fputc(0, gif->fd);
gif->offset = gif->partial = 0;
} }
static void put_image(gif_t *gif, uint16_t w, uint16_t h, uint16_t x, uint16_t y) uint8_t *lzw_compress(uint8_t *input, int width, int height, int min_code_size, size_t *out_size) {
{ int clear_code = 1 << min_code_size;
int nkeys, key_size, i, j; int end_code = clear_code + 1;
node_t *node, *child, *root; int next_code = end_code + 1;
int degree = 1 << gif->depth; int code_size = min_code_size + 1;
fputc(',', gif->fd); DictEntry dict[MAX_DICT_SIZE];
fwrite(&x, 2, 1, gif->fd); int dict_len = next_code;
fwrite(&y, 2, 1, gif->fd);
fwrite(&w, 2, 1, gif->fd); BitStream bs;
fwrite(&h, 2, 1, gif->fd); bitstream_init(&bs);
fputc(0, gif->fd); fputc(gif->depth, gif->fd); bitstream_write(&bs, clear_code, code_size);
root = node = new_trie(degree, &nkeys);
key_size = gif->depth + 1; int prefix = input[0];
put_key(gif, degree, key_size); /* clear code */ for (int i = 1; i < width * height; i++) {
for (i = y; i < y+h; i++) { uint8_t c = input[i];
for (j = x; j < x+w; j++) {
uint8_t pixel = gif->frame[i*gif->w+j] & (degree - 1); // Search for prefix + c in dictionary
child = node->children[pixel]; int found = -1;
if (child) { for (int j = end_code + 1; j < dict_len; j++) {
node = child; if (dict[j].prefix == prefix && dict[j].character == c) {
found = j;
break;
}
}
if (found != -1) {
prefix = found; // Extend prefix
} else {
bitstream_write(&bs, prefix, code_size); // Emit current prefix
if (dict_len < MAX_DICT_SIZE) {
if (dict_len == (1 << code_size) && code_size < 12) code_size++;
dict[dict_len].prefix = prefix;
dict[dict_len].character = c;
dict_len++;
} else { } else {
put_key(gif, node->key, key_size); bitstream_write(&bs, clear_code, code_size);
if (nkeys < 0x1000) { dict_len = end_code + 1;
if (nkeys == (1 << key_size)) code_size = min_code_size + 1;
key_size++;
node->children[pixel] = new_node(nkeys++, degree);
} else {
put_key(gif, degree, key_size); /* clear code */
del_trie(root, degree);
root = node = new_trie(degree, &nkeys);
key_size = gif->depth + 1;
}
node = root->children[pixel];
} }
prefix = c; // Start new prefix
} }
} }
put_key(gif, node->key, key_size);
put_key(gif, degree + 1, key_size); /* stop code */ // Emit final prefix and end code
end_key(gif); bitstream_write(&bs, prefix, code_size);
del_trie(root, degree); bitstream_write(&bs, end_code, code_size);
bitstream_flush(&bs);
*out_size = bs.size;
return bs.data;
} }
static int get_bbox(gif_t *gif, uint16_t *w, uint16_t *h, uint16_t *x, uint16_t *y) void write_gif(const char *filename, uint8_t *pixels, int width, int height, uint8_t *palette, int palette_size) {
{ FILE *f = fopen(filename, "wb");
int i, j, k; if (!f) {
int left, right, top, bottom; perror("Failed to open file");
uint8_t back; return;
left = gif->w; right = 0;
top = gif->h; bottom = 0;
k = 0;
for (i = 0; i < gif->h; i++) {
for (j = 0; j < gif->w; j++, k++) {
back = gif->bgindex >= 0 ? gif->bgindex : gif->back[k];
if (gif->frame[k] != back) {
if (j < left) left = j;
if (j > right) right = j;
if (i < top) top = i;
if (i > bottom) bottom = i;
}
}
} }
if (left != gif->w && top != gif->h) {
*x = left; *y = top; // Header
*w = right - left + 1; fwrite("GIF89a", 1, 6, f);
*h = bottom - top + 1;
return 1; // Determine min_code_size from palette_size
} else { int palette_depth = 0;
return 0; while ((1 << palette_depth) < palette_size) palette_depth++;
const int min_code_size = palette_depth < 2 ? 2 : palette_depth; // GIF spec requires at least 2
printf("min_code_size: %i\n", palette_depth);
// Logical Screen Descriptor
uint8_t packed_field = palette ? (0x80 | ((palette_depth - 1) << 4) | (palette_depth - 1)) : 0x00;
uint8_t screen_desc[] = {
uint8_t(width & 0xFF), uint8_t((width >> 8) & 0xFF),
uint8_t(height & 0xFF), uint8_t((height >> 8) & 0xFF),
packed_field, // GCT flag + color resolution + size
0x00, // Background color index
0x00 // Pixel aspect ratio
};
fwrite(screen_desc, 1, sizeof(screen_desc), f);
// Global Color Table (if provided)
if (palette) {
int gct_size = 1 << palette_depth;
fwrite(palette, 1, gct_size * 3, f);
} }
}
static void add_graphics_control_extension(gif_t *gif, uint16_t d) // Image Descriptor
{ uint8_t image_desc[] = {
uint8_t flags = ((gif->bgindex >= 0 ? 2 : 1) << 2) + 1; 0x2C, 0, 0, 0, 0,
fputc('!', gif->fd); fputc(0xF9, gif->fd); fputc(0x04, gif->fd); fputc(flags, gif->fd); uint8_t(width & 0xFF), uint8_t((width >> 8) & 0xFF),
fwrite(&d, 2, 1, gif->fd); uint8_t(height & 0xFF), uint8_t((height >> 8) & 0xFF),
fputc(gif->bgindex, gif->fd); fputc(0, gif->fd); 0x00 // No local color table
} };
fwrite(image_desc, 1, sizeof(image_desc), f);
void addFrame(gif_t *gif, uint16_t delay) // LZW-compressed image data
{ fwrite(&min_code_size, 1, 1, f);
uint16_t w, h, x, y;
uint8_t *tmp;
if (delay || (gif->bgindex >= 0)) size_t compressed_size;
add_graphics_control_extension(gif, delay); uint8_t *compressed = lzw_compress(pixels, width, height, min_code_size, &compressed_size);
if (gif->nframes == 0) {
w = gif->w; // Write as sub-blocks
h = gif->h; size_t offset = 0;
x = y = 0; while (offset < compressed_size) {
} else if (!get_bbox(gif, &w, &h, &x, &y)) { uint8_t block_size = (compressed_size - offset > 255) ? 255 : (uint8_t)(compressed_size - offset);
/* image's not changed; save one pixel just to add delay */ fwrite(&block_size, 1, 1, f);
w = h = 1; fwrite(compressed + offset, 1, block_size, f);
x = y = 0; offset += block_size;
} }
put_image(gif, w, h, x, y); fputc(0x00, f); // Block terminator
gif->nframes++;
if (gif->bgindex < 0) {
tmp = gif->back;
gif->back = gif->frame;
gif->frame = tmp;
}
}
void close(gif_t* gif) // Trailer
{ fputc(0x3B, f);
fputc(';', gif->fd);
fclose(gif->fd); free(compressed);
free(gif); fclose(f);
} }
} }

View File

@@ -1,47 +1,61 @@
#ifndef JA_USESDLMIXER #ifndef JA_USESDLMIXER
#include "jail_audio.h" #include "jail_audio.h"
#include "stb_vorbis.c" #include "stb_vorbis.h"
#include <SDL2/SDL.h> #include <SDL3/SDL.h>
#include <stdio.h> #include <stdio.h>
#include "log.h"
#define JA_MAX_SIMULTANEOUS_CHANNELS 5 #define JA_MAX_SIMULTANEOUS_CHANNELS 5
struct JA_Sound_t { struct JA_Sound_t
Uint32 length {0}; {
Uint8* buffer {NULL}; SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
Uint32 length { 0 };
Uint8 *buffer { NULL };
}; };
struct JA_Channel_t { struct JA_Channel_t
JA_Sound_t *sound; {
int pos {0}; JA_Sound_t *sound { nullptr };
int times {0}; int pos { 0 };
JA_Channel_state state { JA_CHANNEL_FREE }; int times { 0 };
SDL_AudioStream *stream { nullptr };
JA_Channel_state state { JA_CHANNEL_FREE };
}; };
struct JA_Music_t { struct JA_Music_t
int samples {0}; {
int pos {0}; SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
int times {0}; Uint32 length { 0 };
short* output {NULL}; Uint8 *buffer { nullptr };
JA_Music_state state {JA_MUSIC_INVALID};
int pos { 0 };
int times { 0 };
SDL_AudioStream *stream { nullptr };
JA_Music_state state { JA_MUSIC_INVALID };
}; };
JA_Music_t *current_music{NULL}; JA_Music_t *current_music { nullptr };
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS]; JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
int JA_freq {48000}; SDL_AudioSpec JA_audioSpec { SDL_AUDIO_S16, 2, 48000 };
SDL_AudioFormat JA_format {AUDIO_S16}; float JA_musicVolume { 1.0f };
Uint8 JA_channels {2}; float JA_soundVolume { 0.5f };
int JA_musicVolume = 128; bool JA_musicEnabled { true };
int JA_soundVolume = 64; bool JA_soundEnabled { true };
bool JA_musicEnabled = true; SDL_AudioDeviceID sdlAudioDevice { 0 };
bool JA_soundEnabled = true; SDL_TimerID JA_timerID { 0 };
SDL_AudioDeviceID sdlAudioDevice = 0;
bool fading = false;
int fade_start_time;
int fade_duration;
int fade_initial_volume;
/*
void audioCallback(void * userdata, uint8_t * stream, int len) { void audioCallback(void * userdata, uint8_t * stream, int len) {
SDL_memset(stream, 0, len); SDL_memset(stream, 0, len);
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING) { if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING) {
const int size = SDL_min(len, (current_music->samples-current_music->pos)*2); const int size = SDL_min(len, current_music->samples*2-current_music->pos);
SDL_MixAudioFormat(stream, (Uint8*)(current_music->output+current_music->pos), AUDIO_S16, size, JA_musicVolume); SDL_MixAudioFormat(stream, (Uint8*)(current_music->output+current_music->pos), AUDIO_S16, size, JA_musicVolume);
current_music->pos += size/2; current_music->pos += size/2;
if (size < len) { if (size < len) {
@@ -73,56 +87,100 @@ void audioCallback(void * userdata, uint8_t * stream, int len) {
} }
} }
} }
*/
Uint32 JA_UpdateCallback(void *userdata, SDL_TimerID timerID, Uint32 interval)
{
if (JA_musicEnabled && current_music && current_music->state == JA_MUSIC_PLAYING)
{
if (fading) {
int time = SDL_GetTicks();
if (time > (fade_start_time+fade_duration)) {
fading = false;
JA_StopMusic();
return 30;
} else {
const int time_passed = time - fade_start_time;
const float percent = (float)time_passed / (float)fade_duration;
SDL_SetAudioStreamGain(current_music->stream, 1.0 - percent);
}
}
if (current_music->times != 0)
{
if (SDL_GetAudioStreamAvailable(current_music->stream) < int(current_music->length/2)) {
SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length);
}
if (current_music->times>0) current_music->times--;
}
else
{
if (SDL_GetAudioStreamAvailable(current_music->stream) == 0) JA_StopMusic();
}
}
if (JA_soundEnabled)
{
for (int i=0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i)
if (channels[i].state == JA_CHANNEL_PLAYING)
{
if (channels[i].times != 0)
{
if (SDL_GetAudioStreamAvailable(channels[i].stream) < int(channels[i].sound->length/2))
SDL_PutAudioStreamData(channels[i].stream, channels[i].sound->buffer, channels[i].sound->length);
if (channels[i].times>0) channels[i].times--;
}
}
else
{
if (SDL_GetAudioStreamAvailable(channels[i].stream) == 0) JA_StopChannel(i);
}
}
return 30;
}
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) void JA_Init(const int freq, const SDL_AudioFormat format, const int channels)
{ {
#ifdef DEBUG #ifdef DEBUG
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG); SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
#endif #endif
SDL_Log("Iniciant JailAudio..."); JA_audioSpec = {format, channels, freq };
JA_freq = freq; if (!sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
JA_format = format; sdlAudioDevice = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &JA_audioSpec);
JA_channels = channels; if (!sdlAudioDevice) {
SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL}; log_msg(LOG_FAIL, "Failed to initialize SDL audio: %s\n", SDL_GetError());
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice);
sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
if (sdlAudioDevice==0)
{
SDL_Log("FAILED!\n");
SDL_Log("Failed to initialize SDL audio!\n");
} else { } else {
SDL_Log("OK!\n"); log_msg(LOG_OK, "Audio subsytem initialized\n");
} }
SDL_PauseAudioDevice(sdlAudioDevice, 0); //SDL_PauseAudioDevice(sdlAudioDevice);
JA_timerID = SDL_AddTimer(30, JA_UpdateCallback, nullptr);
} }
void JA_Quit() { void JA_Quit()
SDL_PauseAudioDevice(sdlAudioDevice, 1); {
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice); if (JA_timerID) SDL_RemoveTimer(JA_timerID);
if (!sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
sdlAudioDevice = 0; sdlAudioDevice = 0;
} }
JA_Music_t *JA_LoadMusic(Uint8* buffer, Uint32 length) JA_Music_t *JA_LoadMusic(Uint8* buffer, Uint32 length)
{ {
int chan, samplerate;
JA_Music_t *music = new JA_Music_t(); JA_Music_t *music = new JA_Music_t();
music->samples = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &music->output); int chan, samplerate;
// [RZC 28/08/22] Abans el descomprimiem mentre el teniem obert short *output;
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output); music->length = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &output) * chan * 2;
SDL_AudioCVT cvt; music->spec.channels = chan;
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq); music->spec.freq = samplerate;
SDL_Log("Music length: %f\n", float(music->samples)/float(JA_freq)); music->spec.format = SDL_AUDIO_S16;
if (cvt.needed) { music->buffer = (Uint8*)SDL_malloc(music->length);
cvt.len = music->samples * chan * 2; SDL_memcpy(music->buffer, output, music->length);
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult); free(output);
SDL_memcpy(cvt.buf, music->output, cvt.len);
SDL_ConvertAudio(&cvt);
free(music->output);
music->output = (short*)cvt.buf;
}
music->pos = 0; music->pos = 0;
music->state = JA_MUSIC_STOPPED; music->state = JA_MUSIC_STOPPED;
@@ -151,122 +209,133 @@ void JA_PlayMusic(JA_Music_t *music, const int loop)
{ {
if (!JA_musicEnabled) return; if (!JA_musicEnabled) return;
if (current_music != NULL) { JA_StopMusic();
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
current_music = music; current_music = music;
current_music->pos = 0; current_music->pos = 0;
current_music->state = JA_MUSIC_PLAYING; current_music->state = JA_MUSIC_PLAYING;
current_music->times = loop; current_music->times = loop;
current_music->stream = SDL_CreateAudioStream(&current_music->spec, &JA_audioSpec);
if (!SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length)) log_msg(LOG_FAIL, "SDL_PutAudioStreamData failed!\n");
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
if (!SDL_BindAudioStream(sdlAudioDevice, current_music->stream)) log_msg(LOG_FAIL, "SDL_BindAudioStream failed!\n");
//SDL_ResumeAudioStreamDevice(current_music->stream);
} }
void JA_PauseMusic() void JA_PauseMusic()
{ {
if (!JA_musicEnabled) return; if (!JA_musicEnabled) return;
if (!current_music || current_music->state == JA_MUSIC_INVALID) return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->state = JA_MUSIC_PAUSED; current_music->state = JA_MUSIC_PAUSED;
//SDL_PauseAudioStreamDevice(current_music->stream);
SDL_UnbindAudioStream(current_music->stream);
} }
void JA_ResumeMusic() void JA_ResumeMusic()
{ {
if (!JA_musicEnabled) return; if (!JA_musicEnabled) return;
if (!current_music || current_music->state == JA_MUSIC_INVALID) return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->state = JA_MUSIC_PLAYING; current_music->state = JA_MUSIC_PLAYING;
//SDL_ResumeAudioStreamDevice(current_music->stream);
SDL_BindAudioStream(sdlAudioDevice, current_music->stream);
} }
void JA_StopMusic() void JA_StopMusic()
{ {
if (!JA_musicEnabled) return; if (!JA_musicEnabled) return;
if (!current_music || current_music->state == JA_MUSIC_INVALID) return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->pos = 0; current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED; current_music->state = JA_MUSIC_STOPPED;
//SDL_PauseAudioStreamDevice(current_music->stream);
SDL_DestroyAudioStream(current_music->stream);
current_music->stream = nullptr;
} }
JA_Music_state JA_GetMusicState() { void JA_FadeOutMusic(const int milliseconds)
if (!JA_musicEnabled) return JA_MUSIC_DISABLED; {
if (!JA_musicEnabled) return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
fading = true;
fade_start_time = SDL_GetTicks();
fade_duration = milliseconds;
fade_initial_volume = JA_musicVolume;
}
JA_Music_state JA_GetMusicState()
{
if (!JA_musicEnabled) return JA_MUSIC_DISABLED;
if (!current_music) return JA_MUSIC_INVALID;
if (current_music == NULL) return JA_MUSIC_INVALID;
return current_music->state; return current_music->state;
} }
void JA_DeleteMusic(JA_Music_t *music) { void JA_DeleteMusic(JA_Music_t *music)
if (current_music == music) current_music = NULL; {
free(music->output); if (current_music == music) current_music = nullptr;
SDL_free(music->buffer);
if (music->stream) SDL_DestroyAudioStream(music->stream);
delete music; delete music;
} }
int JA_SetMusicVolume(int volume) float JA_SetMusicVolume(float volume)
{ {
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume; JA_musicVolume = SDL_clamp( volume, 0.0f, 1.0f );
if (current_music) SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
return JA_musicVolume; return JA_musicVolume;
} }
void JA_SetMusicPosition(float value) void JA_SetMusicPosition(float value)
{ {
if (!current_music) return; if (!current_music) return;
current_music->pos = value * JA_freq; current_music->pos = value * current_music->spec.freq;
} }
float JA_GetMusicPosition() float JA_GetMusicPosition()
{ {
if (!current_music) return 0; if (!current_music) return 0;
return float(current_music->pos)/float(JA_freq); return float(current_music->pos)/float(current_music->spec.freq);
} }
void JA_EnableMusic(const bool value) void JA_EnableMusic(const bool value)
{ {
if (!value && current_music != NULL && current_music->state==JA_MUSIC_PLAYING) JA_StopMusic(); if ( !value && current_music && (current_music->state==JA_MUSIC_PLAYING) ) JA_StopMusic();
JA_musicEnabled = value; JA_musicEnabled = value;
} }
const bool JA_IsMusicEnabled()
{
return JA_musicEnabled;
}
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length)
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length) { {
JA_Sound_t *sound = new JA_Sound_t(); JA_Sound_t *sound = new JA_Sound_t();
sound->buffer = buffer; sound->buffer = buffer;
sound->length = length; sound->length = length;
return sound; return sound;
} }
JA_Sound_t *JA_LoadSound(uint8_t* buffer, uint32_t size) { JA_Sound_t *JA_LoadSound(uint8_t* buffer, uint32_t size)
{
JA_Sound_t *sound = new JA_Sound_t(); JA_Sound_t *sound = new JA_Sound_t();
SDL_AudioSpec wavSpec; SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size),1, &sound->spec, &sound->buffer, &sound->length);
SDL_LoadWAV_RW(SDL_RWFromMem(buffer, size),1, &wavSpec, &sound->buffer, &sound->length);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
cvt.len = sound->length;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, sound->buffer, sound->length);
SDL_ConvertAudio(&cvt);
SDL_FreeWAV(sound->buffer);
sound->buffer = cvt.buf;
sound->length = cvt.len_cvt;
return sound; return sound;
} }
JA_Sound_t *JA_LoadSound(const char* filename) { JA_Sound_t *JA_LoadSound(const char* filename)
{
JA_Sound_t *sound = new JA_Sound_t(); JA_Sound_t *sound = new JA_Sound_t();
SDL_AudioSpec wavSpec; SDL_LoadWAV(filename, &sound->spec, &sound->buffer, &sound->length);
SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
cvt.len = sound->length;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, sound->buffer, sound->length);
SDL_ConvertAudio(&cvt);
SDL_FreeWAV(sound->buffer);
sound->buffer = cvt.buf;
sound->length = cvt.len_cvt;
return sound; return sound;
} }
@@ -278,11 +347,36 @@ int JA_PlaySound(JA_Sound_t *sound, const int loop)
int channel = 0; int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; } while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0; if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0;
JA_StopChannel(channel);
channels[channel].sound = sound; channels[channel].sound = sound;
channels[channel].times = loop; channels[channel].times = loop;
channels[channel].pos = 0; channels[channel].pos = 0;
channels[channel].state = JA_CHANNEL_PLAYING; channels[channel].state = JA_CHANNEL_PLAYING;
channels[channel].stream = SDL_CreateAudioStream(&channels[channel].sound->spec, &JA_audioSpec);
SDL_PutAudioStreamData(channels[channel].stream, channels[channel].sound->buffer, channels[channel].sound->length);
SDL_SetAudioStreamGain(channels[channel].stream, JA_soundVolume);
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
return channel;
}
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop)
{
if (!JA_soundEnabled) return -1;
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return -1;
JA_StopChannel(channel);
channels[channel].sound = sound;
channels[channel].times = loop;
channels[channel].pos = 0;
channels[channel].state = JA_CHANNEL_PLAYING;
channels[channel].stream = SDL_CreateAudioStream(&channels[channel].sound->spec, &JA_audioSpec);
SDL_PutAudioStreamData(channels[channel].stream, channels[channel].sound->buffer, channels[channel].sound->length);
SDL_SetAudioStreamGain(channels[channel].stream, JA_soundVolume);
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
return channel; return channel;
} }
@@ -299,12 +393,24 @@ void JA_PauseChannel(const int channel)
{ {
if (!JA_soundEnabled) return; if (!JA_soundEnabled) return;
if (channel == -1) { if (channel == -1)
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { {
if (channels[i].state == JA_CHANNEL_PLAYING) channels[i].state = JA_CHANNEL_PAUSED; for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
if (channels[i].state == JA_CHANNEL_PLAYING)
{
channels[i].state = JA_CHANNEL_PAUSED;
//SDL_PauseAudioStreamDevice(channels[i].stream);
SDL_UnbindAudioStream(channels[i].stream);
}
}
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
if (channels[channel].state == JA_CHANNEL_PLAYING)
{
channels[channel].state = JA_CHANNEL_PAUSED;
//SDL_PauseAudioStreamDevice(channels[channel].stream);
SDL_UnbindAudioStream(channels[channel].stream);
} }
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PLAYING) channels[channel].state = JA_CHANNEL_PAUSED;
} }
} }
@@ -312,12 +418,24 @@ void JA_ResumeChannel(const int channel)
{ {
if (!JA_soundEnabled) return; if (!JA_soundEnabled) return;
if (channel == -1) { if (channel == -1)
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { {
if (channels[i].state == JA_CHANNEL_PAUSED) channels[i].state = JA_CHANNEL_PLAYING; for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
if (channels[i].state == JA_CHANNEL_PAUSED)
{
channels[i].state = JA_CHANNEL_PLAYING;
//SDL_ResumeAudioStreamDevice(channels[i].stream);
SDL_BindAudioStream(sdlAudioDevice, channels[i].stream);
}
}
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
if (channels[channel].state == JA_CHANNEL_PAUSED)
{
channels[channel].state = JA_CHANNEL_PLAYING;
//SDL_ResumeAudioStreamDevice(channels[channel].stream);
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
} }
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PAUSED) channels[channel].state = JA_CHANNEL_PLAYING;
} }
} }
@@ -325,13 +443,20 @@ void JA_StopChannel(const int channel)
{ {
if (!JA_soundEnabled) return; if (!JA_soundEnabled) return;
if (channel == -1) { if (channel == -1)
{
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state != JA_CHANNEL_FREE) SDL_DestroyAudioStream(channels[i].stream);
channels[i].stream = nullptr;
channels[i].state = JA_CHANNEL_FREE; channels[i].state = JA_CHANNEL_FREE;
channels[i].pos = 0; channels[i].pos = 0;
channels[i].sound = NULL; channels[i].sound = NULL;
} }
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { }
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
if (channels[channel].state != JA_CHANNEL_FREE) SDL_DestroyAudioStream(channels[channel].stream);
channels[channel].stream = nullptr;
channels[channel].state = JA_CHANNEL_FREE; channels[channel].state = JA_CHANNEL_FREE;
channels[channel].pos = 0; channels[channel].pos = 0;
channels[channel].sound = NULL; channels[channel].sound = NULL;
@@ -343,12 +468,18 @@ JA_Channel_state JA_GetChannelState(const int channel)
if (!JA_soundEnabled) return JA_SOUND_DISABLED; if (!JA_soundEnabled) return JA_SOUND_DISABLED;
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID; if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
return channels[channel].state; return channels[channel].state;
} }
int JA_SetSoundVolume(int volume) float JA_SetSoundVolume(float volume)
{ {
JA_soundVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume; JA_soundVolume = SDL_clamp( volume, 0.0f, 1.0f );
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
if ( (channels[i].state == JA_CHANNEL_PLAYING) || (channels[i].state == JA_CHANNEL_PAUSED) )
SDL_SetAudioStreamGain(channels[i].stream, JA_soundVolume);
return JA_soundVolume; return JA_soundVolume;
} }
@@ -361,10 +492,15 @@ void JA_EnableSound(const bool value)
JA_soundEnabled = value; JA_soundEnabled = value;
} }
int JA_SetVolume(int volume) const bool JA_IsSoundEnabled()
{ {
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume; return JA_soundEnabled;
JA_soundVolume = JA_musicVolume/2; }
float JA_SetVolume(float volume)
{
JA_SetSoundVolume(JA_SetMusicVolume(volume) / 2.0f);
return JA_musicVolume; return JA_musicVolume;
} }

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include <SDL2/SDL.h> #include <SDL3/SDL.h>
enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED, JA_SOUND_DISABLED }; enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED, JA_SOUND_DISABLED };
enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED, JA_MUSIC_DISABLED }; enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED, JA_MUSIC_DISABLED };
@@ -16,23 +16,27 @@ void JA_PlayMusic(JA_Music_t *music, const int loop = -1);
void JA_PauseMusic(); void JA_PauseMusic();
void JA_ResumeMusic(); void JA_ResumeMusic();
void JA_StopMusic(); void JA_StopMusic();
void JA_FadeOutMusic(const int milliseconds);
JA_Music_state JA_GetMusicState(); JA_Music_state JA_GetMusicState();
void JA_DeleteMusic(JA_Music_t *music); void JA_DeleteMusic(JA_Music_t *music);
int JA_SetMusicVolume(int volume); float JA_SetMusicVolume(float volume);
void JA_SetMusicPosition(float value); void JA_SetMusicPosition(float value);
float JA_GetMusicPosition(); float JA_GetMusicPosition();
void JA_EnableMusic(const bool value); void JA_EnableMusic(const bool value);
const bool JA_IsMusicEnabled();
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length); JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length);
JA_Sound_t *JA_LoadSound(Uint8* buffer, Uint32 length); JA_Sound_t *JA_LoadSound(Uint8* buffer, Uint32 length);
JA_Sound_t *JA_LoadSound(const char* filename); JA_Sound_t *JA_LoadSound(const char* filename);
int JA_PlaySound(JA_Sound_t *sound, const int loop = 0); int JA_PlaySound(JA_Sound_t *sound, const int loop = 0);
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop = 0);
void JA_PauseChannel(const int channel); void JA_PauseChannel(const int channel);
void JA_ResumeChannel(const int channel); void JA_ResumeChannel(const int channel);
void JA_StopChannel(const int channel); void JA_StopChannel(const int channel);
JA_Channel_state JA_GetChannelState(const int channel); JA_Channel_state JA_GetChannelState(const int channel);
void JA_DeleteSound(JA_Sound_t *sound); void JA_DeleteSound(JA_Sound_t *sound);
int JA_SetSoundVolume(int volume); float JA_SetSoundVolume(float volume);
void JA_EnableSound(const bool value); void JA_EnableSound(const bool value);
const bool JA_IsSoundEnabled();
int JA_SetVolume(int volume); float JA_SetVolume(float volume);

164
jfile.cpp
View File

@@ -9,7 +9,9 @@
#include <fstream> #include <fstream>
#include <filesystem> #include <filesystem>
#include <string> #include <string>
#include <vector>
#include <algorithm>
#include <dirent.h> // Para opendir/readdir en SOURCE_FOLDER
#ifndef _WIN32 #ifndef _WIN32
#include <pwd.h> #include <pwd.h>
@@ -76,10 +78,11 @@ bool file_getdictionary() {
fi.read( (char*)&file_size, 4 ); fi.read( (char*)&file_size, 4 );
uint8_t path_size; uint8_t path_size;
fi.read( (char*)&path_size, 1 ); fi.read( (char*)&path_size, 1 );
char file_name[path_size+1]; char *file_name = (char*)malloc(path_size+1);
fi.read( file_name, path_size ); fi.read( file_name, path_size );
file_name[path_size] = 0; file_name[path_size] = 0;
std::string filename = file_name; std::string filename = file_name;
free(file_name);
toc.push_back({filename, file_size, file_offset}); toc.push_back({filename, file_size, file_offset});
} }
fi.close(); fi.close();
@@ -130,10 +133,30 @@ FILE *file_getfilepointer(const char *resourcename, int& filesize, const bool bi
return f; return f;
} }
char *file_getfilebuffer(const char *resourcename, int& filesize) { char *file_getfilebuffer(const char *resourcename, int& filesize, const bool zero_terminate) {
FILE *f = file_getfilepointer(resourcename, filesize, true); FILE *f = file_getfilepointer(resourcename, filesize, true);
char* buffer = (char*)malloc(filesize); char* buffer = (char*)malloc(zero_terminate?filesize:filesize+1);
fread(buffer, filesize, 1, f); fread(buffer, filesize, 1, f);
if (zero_terminate) buffer[filesize]=0;
fclose(f);
return buffer;
}
FILE *file_getfilepointerex(const char *filename, int& filesize, const bool binary) {
FILE *f;
f = fopen(filename, binary?"rb":"r");
fseek(f, 0, SEEK_END);
filesize = ftell(f);
fseek(f, 0, SEEK_SET);
return f;
}
char *file_getfilebufferex(const char *filename, int& filesize, const bool zero_terminate) {
FILE *f = file_getfilepointerex(filename, filesize, true);
char* buffer = (char*)malloc(zero_terminate?filesize:filesize+1);
fread(buffer, filesize, 1, f);
if (zero_terminate) buffer[filesize]=0;
fclose(f); fclose(f);
return buffer; return buffer;
} }
@@ -151,6 +174,29 @@ void file_setconfigfolder(const char *foldername)
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir; const char *homedir = pw->pw_dir;
config_folder = std::string(homedir) + "/." + foldername; config_folder = std::string(homedir) + "/." + foldername;
config_folder = std::string(homedir) + "/.config/jailgames/" + foldername;
{
// Intenta crear ".config", per si no existeix
std::string config_base_folder = std::string(homedir) + "/.config";
int ret = mkdir(config_base_folder.c_str(), S_IRWXU);
if (ret == -1 && errno != EEXIST)
{
printf("ERROR CREATING CONFIG BASE FOLDER.");
exit(EXIT_FAILURE);
}
}
{
// Intenta crear ".config/jailgames", per si no existeix
std::string config_base_folder = std::string(homedir) + "/.config/jailgames";
int ret = mkdir(config_base_folder.c_str(), S_IRWXU);
if (ret == -1 && errno != EEXIST)
{
printf("ERROR CREATING CONFIG BASE FOLDER.");
exit(EXIT_FAILURE);
}
}
#endif #endif
struct stat st = {0}; struct stat st = {0};
@@ -171,7 +217,7 @@ void file_setconfigfolder(const char *foldername)
} }
const char *file_getconfigfolder() { const char *file_getconfigfolder() {
std::string folder = config_folder + "/"; static std::string folder = config_folder + "/";
return folder.c_str(); return folder.c_str();
} }
@@ -228,3 +274,111 @@ void file_setconfigvalue(const char* key, const char* value) {
file_saveconfigvalues(); file_saveconfigvalues();
return; return;
} }
bool file_createFolder(const char* name) {
char tmp[256];
strcpy(tmp, "./");
strcat(tmp, name);
#ifdef _WIN32
return mkdir(tmp)==0;
#else
return mkdir(tmp, 0755)==0;
#endif
}
static bool has_extension(const std::string &name, const char *ext)
{
if (!ext) return true; // sin filtro
std::string e = ext;
std::string suffix = "." + e;
if (name.size() < suffix.size())
return false;
return (name.compare(name.size() - suffix.size(), suffix.size(), suffix) == 0);
}
std::vector<std::string> file_listdir(const char *folder, const char *extension)
{
std::vector<std::string> result;
std::string base(folder);
// Normalizar: quitar "/" final si existe
if (!base.empty() && base.back() == '/')
base.pop_back();
// -------------------------------
// 1. MODO: ARCHIVOS SUELTOS
// -------------------------------
if (file_source == SOURCE_FOLDER)
{
std::string fullpath = std::string(resource_folder) + base;
DIR *dir = opendir(fullpath.c_str());
if (!dir)
return result;
struct dirent *entry;
while ((entry = readdir(dir)) != nullptr)
{
std::string name = entry->d_name;
// Ignorar "." y ".."
if (name == "." || name == "..")
continue;
// Ignorar subdirectorios
std::string full = fullpath + "/" + name;
DIR *test = opendir(full.c_str());
if (test)
{
closedir(test);
continue; // es un directorio
}
// Filtrar por extensión
if (!has_extension(name, extension))
continue;
result.push_back(name);
}
closedir(dir);
return result;
}
// -------------------------------
// 2. MODO: ARCHIVO CONTENEDOR
// -------------------------------
if (file_source == SOURCE_FILE)
{
std::string prefix = base + "/";
for (auto &f : toc)
{
const std::string &path = f.path;
// Debe empezar por "folder/"
if (path.compare(0, prefix.size(), prefix) != 0)
continue;
// Extraer la parte después de "folder/"
std::string rest = path.substr(prefix.size());
// Ignorar subdirectorios
if (rest.find('/') != std::string::npos)
continue;
// Filtrar por extensión
if (!has_extension(rest, extension))
continue;
result.push_back(rest);
}
return result;
}
return result;
}

10
jfile.h
View File

@@ -1,5 +1,7 @@
#pragma once #pragma once
#include <stdio.h> #include <stdio.h>
#include <vector>
#include <string>
#define SOURCE_FILE 0 #define SOURCE_FILE 0
#define SOURCE_FOLDER 1 #define SOURCE_FOLDER 1
@@ -12,7 +14,13 @@ void file_setresourcefolder(const char *str);
void file_setsource(const int src); void file_setsource(const int src);
FILE *file_getfilepointer(const char *resourcename, int& filesize, const bool binary=false); FILE *file_getfilepointer(const char *resourcename, int& filesize, const bool binary=false);
char *file_getfilebuffer(const char *resourcename, int& filesize); char *file_getfilebuffer(const char *resourcename, int& filesize, const bool zero_terminate=false);
FILE *file_getfilepointerex(const char *filename, int& filesize, const bool binary=false);
char *file_getfilebufferex(const char *filename, int& filesize, const bool zero_terminate=false);
const char* file_getconfigvalue(const char *key); const char* file_getconfigvalue(const char *key);
void file_setconfigvalue(const char* key, const char* value); void file_setconfigvalue(const char* key, const char* value);
bool file_createFolder(const char* name);
std::vector<std::string> file_listdir(const char *folder, const char *extension=NULL);

253
jshader.cpp Normal file
View File

@@ -0,0 +1,253 @@
#include "jshader.h"
#include <iostream>
#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
#include <OpenGL/OpenGL.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 can_use_opengl = false;
bool using_opengl = false;
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;
PFNGLDELETEPROGRAMPROC glDeleteProgram;
PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLVALIDATEPROGRAMPROC glValidateProgram;
PFNGLGETPROGRAMIVPROC glGetProgramiv;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLUSEPROGRAMPROC glUseProgram;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
PFNGLACTIVETEXTUREPROC glActiveTexture;
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");
glDeleteProgram = (PFNGLDELETEPROGRAMPROC)SDL_GL_GetProcAddress("glDeleteProgram");
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");
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)SDL_GL_GetProcAddress("glGetUniformLocation");
glActiveTexture = (PFNGLACTIVETEXTUREPROC)SDL_GL_GetProcAddress("glActiveTexture");
return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv &&
glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram &&
glDeleteProgram && glLinkProgram && glValidateProgram && glGetProgramiv &&
glGetProgramInfoLog && glUseProgram && glGetUniformLocation;
}
#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;
//std::cout << source << std::endl;
free(log);
}
glDeleteShader(result);
result = 0;
}
return result;
}
GLuint compileProgram(const char* vertexShaderSource, const char* fragmentShaderSource)
{
GLuint programId = 0;
GLuint vtxShaderId, fragShaderId;
if (programId != 0) glDeleteProgram(programId);
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__
static bool gl_extensions_initialized = false;
if (!gl_extensions_initialized) {
if (!initGLExtensions()) {
std::cout << "WARNING: No s'han pogut inicialitzar les extensions d'OpenGL!" << std::endl;
can_use_opengl = false;
return false;
}
gl_extensions_initialized = true;
}
#endif
// Compilar el shader y dejarlo listo para usar.
if (!vertexShader) {
can_use_opengl = false;
return false;
}
programId = compileProgram(vertexShader, fragmentShader);
} else {
std::cout << "WARNING: El driver del renderer no es OpenGL." << std::endl;
can_use_opengl = false;
return false;
}
can_use_opengl = true;
return true;
}
unsigned char pixels[512*240*4];
void enable() { if (can_use_opengl) using_opengl = true; }
void disable() { using_opengl = false; }
void render()
{
SDL_FlushRenderer(renderer);
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_FlushRenderer(renderer);
if (using_opengl)
{
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(-1.0f, -1.0f);
glTexCoord2f(tex_size.x, 0.0f);
glVertex2f(1.0f, -1.0f);
glTexCoord2f(0.0f, tex_size.y);
glVertex2f(-1.0f, 1.0f);
glTexCoord2f(tex_size.x, tex_size.y);
glVertex2f(1.0f, 1.0f);
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); }
}
}

48
jshader.h Normal file
View File

@@ -0,0 +1,48 @@
#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 enable();
void disable();
void render();
}

5
lagueirtofile Normal file
View File

@@ -0,0 +1,5 @@
libs = -lSDL3 -lGL
cppflags = -D LUA_USE_LINUX -D DEBUG -g -Wall
executable = mini_debug
sourcepath = . lua
buildpath = build

27
log.h Normal file
View File

@@ -0,0 +1,27 @@
#pragma once
#include <stdio.h>
#include <stdarg.h>
#ifdef DEBUG
enum LogLevel { LOG_OK, LOG_FAIL, LOG_WARN, LOG_INFO, LOG_LUART, LOG_LUALD, LOG_VERBOSE, LOG_UNSALTED };
static inline void log_msg(enum LogLevel level, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
switch (level) {
case LOG_OK: printf("[\033[1;32m OK \033[0m] "); break;
case LOG_FAIL: printf("[\033[1;31mFAIL\033[0m] "); break;
case LOG_WARN: printf("[\033[1;33mWARN\033[0m] "); break;
case LOG_INFO: printf("[\033[1;34mINFO\033[0m] "); break;
case LOG_LUART: printf("[\033[1;35mLUA RUNTIME ERROR\033[0m] "); break;
case LOG_LUALD: printf("[\033[1;35mLUA LOADING ERROR\033[0m] "); break;
case LOG_VERBOSE: printf(" - "); break;
case LOG_UNSALTED: break;
}
vprintf(fmt, args);
va_end(args);
}
#else
#define log_msg(...) ((void)0)
#endif

1067
lua.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -653,9 +653,119 @@ static void findloader (lua_State *L, const char *name) {
} }
} }
// [RZC 12/03/2026] ==================================
// Soport per a rutes relatives i absolutes
//
static void resolve_module_name(lua_State *L, char *out, size_t outsz) {
const char *req = luaL_checkstring(L, 1);
// 1. RUTA ABSOLUTA: empieza por ':'
if (req[0] == ':') {
strncpy(out, req + 1, outsz - 1);
out[outsz - 1] = '\0';
return;
}
// 2. Obtener módulo llamador
lua_Debug ar;
if (!lua_getstack(L, 1, &ar)) {
// No hay llamador → usar nombre tal cual
strncpy(out, req, outsz - 1);
out[outsz - 1] = '\0';
return;
}
lua_getinfo(L, "S", &ar);
// ar.source contiene algo como "@ia.test" o "@main"
const char *src = ar.source;
if (!src) {
// No viene de archivo → usar nombre tal cual
strncpy(out, req, outsz - 1);
out[outsz - 1] = '\0';
return;
}
// Quitar '@'
//src++;
// 3. Extraer directorio del módulo llamador
// Ej: "ia.tools.other" → "ia.tools"
char caller[256];
strncpy(caller, src, sizeof(caller) - 1);
caller[sizeof(caller) - 1] = '\0';
char *lastdot = strrchr(caller, '.');
if (lastdot)
*lastdot = '\0'; // dejar solo el directorio
else
caller[0] = '\0'; // está en la raíz
// 4. RUTA RELATIVA HACIA ARRIBA: empieza por ".."
if (req[0] == '.' && req[1] == '.') {
// Contar cuántos '.' consecutivos hay
int up = 0;
while (req[up] == '.')
up++;
// up = número de puntos → niveles a subir
// Ej: "..test" → up=2 → subir 1 nivel
// "...main" → up=3 → subir 2 niveles
int levels = up - 1;
// Copiar caller a buffer temporal
char temp[256];
strncpy(temp, caller, sizeof(temp) - 1);
temp[sizeof(temp) - 1] = '\0';
// Subir niveles
for (int i = 0; i < levels; i++) {
char *p = strrchr(temp, '.');
if (p)
*p = '\0';
else {
temp[0] = '\0';
break;
}
}
// Concatenar lo que queda después de los puntos
const char *rest = req + up;
if (temp[0] == '\0') {
// Hemos llegado a la raíz
strncpy(out, rest, outsz - 1);
} else {
snprintf(out, outsz, "%s.%s", temp, rest);
}
out[outsz - 1] = '\0';
return;
}
// 5. RUTA RELATIVA NORMAL (no empieza por ':' ni por '..')
if (caller[0] == '\0') {
// Estamos en la raíz
strncpy(out, req, outsz - 1);
} else {
snprintf(out, outsz, "%s.%s", caller, req);
}
out[outsz - 1] = '\0';
}
// ===================================================
static int ll_require (lua_State *L) { static int ll_require (lua_State *L) {
const char *name = luaL_checkstring(L, 1); // [RZC 12/03/2026] ==================================
// Soport per a rutes relatives i absolutes
//
//const char *name = luaL_checkstring(L, 1);
char resolved[256];
resolve_module_name(L, resolved, sizeof(resolved));
const char *name = resolved;
// ===================================================
lua_settop(L, 1); /* LOADED table will be at index 2 */ lua_settop(L, 1); /* LOADED table will be at index 2 */
lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
lua_getfield(L, 2, name); /* LOADED[name] */ lua_getfield(L, 2, name); /* LOADED[name] */

958
mini.cpp

File diff suppressed because it is too large Load Diff

51
mini.h
View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <SDL2/SDL.h> #include <SDL3/SDL.h>
#include "version.h" #include "version.h"
@@ -112,13 +112,20 @@
#define KEY_RALT 230 #define KEY_RALT 230
#define KEY_RGUI 231 #define KEY_RGUI 231
#define DRAWMODE_NORMAL 0
#define DRAWMODE_PATTERN 1
#define DRAWMODE_AND 2
#define DRAWMODE_OR 3
#define DRAWMODE_XOR 4
#define DRAWMODE_NOT 5
void loop(); void loop();
int scrw(); int scrw();
int scrh(); int scrh();
uint8_t newsurf(int w, int h); uint8_t newsurf(int w, int h);
uint8_t loadsurf(const char* filename); uint8_t loadsurf(const char* filename, const bool external = false);
void savesurf(uint8_t surface, const char* filename, uint8_t *pal, uint8_t colors=0); void savesurf(uint8_t surface, const char* filename, uint8_t *pal, uint8_t colors=0);
void freesurf(uint8_t surface); void freesurf(uint8_t surface);
int surfw(uint8_t surface); int surfw(uint8_t surface);
@@ -127,8 +134,20 @@ int surfh(uint8_t surface);
void setdest(uint8_t surface); void setdest(uint8_t surface);
void setsource(uint8_t surface); void setsource(uint8_t surface);
void setmap(uint8_t surface); void setmap(uint8_t surface);
uint8_t getdest();
uint8_t getsource();
uint8_t getmap(); uint8_t getmap();
void shader_init(const char* vshader, const char* fshader);
void shader_enable();
void shader_disable();
uint8_t loadfont(const char *filename);
uint8_t getfont();
void setfont(uint8_t font);
uint8_t getfontspacing();
void setfontspacing(uint8_t spacing);
void cls(uint8_t color=0); void cls(uint8_t color=0);
void color(uint8_t color=6); void color(uint8_t color=6);
void bcolor(uint8_t color=0); void bcolor(uint8_t color=0);
@@ -139,9 +158,10 @@ void setcolor(uint8_t index, uint32_t color);
uint32_t getcolor(uint8_t index); uint32_t getcolor(uint8_t index);
void settrans(uint8_t index); void settrans(uint8_t index);
uint8_t gettrans(); uint8_t gettrans();
void subpal(uint8_t index, uint8_t color); uint8_t subpal(uint8_t index, uint8_t color);
void reset_subpal(); void reset_subpal();
void set_draw_mode(uint8_t mode);
void pset(int x, int y); void pset(int x, int y);
void pset(int x, int y, uint8_t color); void pset(int x, int y, uint8_t color);
@@ -179,6 +199,12 @@ void circ(int x, int y, uint8_t r, uint8_t color);
void circfill(int x, int y, uint8_t r = 4); void circfill(int x, int y, uint8_t r = 4);
void circfill(int x, int y, uint8_t r, uint8_t color); void circfill(int x, int y, uint8_t r, uint8_t color);
void roundrect(int x, int y, int w, int h, uint8_t r);
void roundrect(int x, int y, int w, int h, uint8_t r, uint8_t color);
void roundrectfill(int x, int y, int w, int h, uint8_t r);
void roundrectfill(int x, int y, int w, int h, uint8_t r, uint8_t color);
void oval(int x0, int y0, int x1, int y1); void oval(int x0, int y0, int x1, int y1);
void oval(int x0, int y0, int x1, int y1, uint8_t color); void oval(int x0, int y0, int x1, int y1, uint8_t color);
@@ -191,7 +217,8 @@ void sset(int x, int y, uint8_t color);
void spr(uint8_t n, int x, int y, float w = 1.0f, float h = 1.0f, bool flip_x = false, bool flip_y = false); void spr(uint8_t n, int x, int y, float w = 1.0f, float h = 1.0f, bool flip_x = false, bool flip_y = false);
void blit(int sx, int sy, int sw, int sh, int dx, int dy, int dw=0, int dh=0, bool flip_x = false, bool flip_y = false, bool invert = false); void blit(int sx, int sy, int sw, int sh, int dx, int dy, int dw=0, int dh=0, bool flip_x = false, bool flip_y = false, bool invert = false);
void blit_r(int sx, int sy, int sw, int sh, int x, int y, float a); //void blit_r(int sx, int sy, int sw, int sh, int x, int y, float a);
void blit_r(int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, bool flip_x, bool flip_y, float angle_deg);
void tline(int x0, int y0, int x1, int y1, float mx, float my, float mdx=0.125f, float mdy=0.0f); void tline(int x0, int y0, int x1, int y1, float mx, float my, float mdx=0.125f, float mdy=0.0f);
void thline(int x0, int y, int x1, float mx, float my, float mdx=0.125f, float mdy=0.0f); void thline(int x0, int y, int x1, float mx, float my, float mdx=0.125f, float mdy=0.0f);
@@ -199,12 +226,17 @@ void tvline(int x, int y0, int y1, float mx, float my, float mdx=0.0f, float mdy
uint8_t mget(int celx, int cely); uint8_t mget(int celx, int cely);
void mset(int celx, int cely, uint8_t snum); void mset(int celx, int cely, uint8_t snum);
uint8_t gettilew();
uint8_t gettileh();
void settilesize(int w, int h);
void map(); //int celx, int cely, int sx, int sy, uint8_t celw, uint8_t celh, uint8_t layer=0); void map(); //int celx, int cely, int sx, int sy, uint8_t celw, uint8_t celh, uint8_t layer=0);
bool btn(uint8_t i); bool btn(uint8_t i);
int wbtnp(); int wbtnp();
bool btnp(uint8_t i); bool btnp(uint8_t i);
bool anykey(); bool anykey();
void textenable(const bool enable);
const char *textinput();
bool pad(int8_t i); bool pad(int8_t i);
bool padp(int8_t i); bool padp(int8_t i);
@@ -215,13 +247,15 @@ int mousey();
int mwheel(); int mwheel();
bool mbtn(uint8_t i); bool mbtn(uint8_t i);
bool mbtnp(uint8_t i); bool mbtnp(uint8_t i);
bool doubleclick();
void mdiscard();
bool minside(int x, int y, int w, int h);
float time(); float time();
bool beat(int16_t i); bool beat(int16_t i);
int rnd(int x); int rnd(int x);
int getfps();
#define debug printf
void playmusic(const char *filename, const int loop=-1); void playmusic(const char *filename, const int loop=-1);
void pausemusic(); void pausemusic();
@@ -229,11 +263,15 @@ void resumemusic();
void stopmusic(const int t=1000); void stopmusic(const int t=1000);
void musicpos(float value); void musicpos(float value);
float musicpos(); float musicpos();
void enablemusic(const bool value);
const bool ismusicenabled();
int loadsound(const char *filename); int loadsound(const char *filename);
void freesound(int soundfile); void freesound(int soundfile);
int playsound(int soundfile, const int volume=-1); int playsound(int soundfile, const int volume=-1);
void stopsound(int soundchannel); void stopsound(int soundchannel);
void enablesound(const bool value);
const bool issoundenabled();
int getzoom(); int getzoom();
void setzoom(const int value); void setzoom(const int value);
@@ -251,5 +289,6 @@ const char *configfolder();
#define UPDATE_WAIT 1 #define UPDATE_WAIT 1
#define UPDATE_TIMEOUT 2 #define UPDATE_TIMEOUT 2
void setupdatemode(const int value, const int t=0); void setupdatemode(const int value, const int t=0);
int getupdatemode();
void exit(); void exit();

57
publish_gitea.sh Executable file
View File

@@ -0,0 +1,57 @@
#!/bin/bash
set -e
#if [ -z "$1" ]; then
# echo "Uso: $0 <PARAMETRO>"
# exit 1
#fi
#GITEA_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
if [ -z "$GITEA_TOKEN" ]; then
echo "ERROR: Debes exportar GITEA_TOKEN"
exit 1
fi
# Leer versión desde version.h
VERSION=$(grep '#define MINI_VERSION' version.h | sed 's/.*"\(.*\)".*/\1/')
echo "Versión detectada: $VERSION"
#PARAM=$1
API="https://gitea.sustancia.synology.me/api/v1"
REPO="JailDoctor/mini"
echo "=== Creando release ${VERSION} en Gitea ==="
RELEASE_ID=$(curl -s -X POST "${API}/repos/${REPO}/releases" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"tag_name\": \"${VERSION}\",
\"name\": \"Release ${VERSION}\",
\"draft\": false,
\"prerelease\": false
}" | jq -r '.id')
if [ "$RELEASE_ID" = "null" ]; then
echo "ERROR: No se pudo crear el release"
exit 1
fi
echo "Release creado con ID: $RELEASE_ID"
echo "=== Subiendo artefactos ==="
for f in mini_v${VERSION}_linux_release.tar.gz \
mini_v${VERSION}_linux_debug.tar.gz \
mini_v${VERSION}_win32-x64_release.zip \
mini_v${VERSION}_win32-x64_debug.zip
do
echo "Subiendo $f..."
curl -s -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-F "attachment=@${f}" \
"${API}/repos/${REPO}/releases/${RELEASE_ID}/assets" > /dev/null
done
echo "=== Publicación completada ==="

View File

@@ -0,0 +1,5 @@
title=FONTED
config=fonted
width=320
height=240
zoom=2

122
tools/fonted/data/main.lua Normal file
View File

@@ -0,0 +1,122 @@
require "ui"
update = nil
protofont_surface = nil
protofont_name = nil
function mini.init()
pal.trans(255)
surf.cls(0)
update = any_update
--ui.filedialog.show(select_file)
end
function select_file(filename)
if protofont_surface then surf.free(protofont_surface) end
protofont_name = filename:match("([^/]+)$")
protofont_surface = surf.loadex(filename)
end
function mini.update()
view.origin(0,0)
for i=0,15 do
draw.rectf(i*8, 0, 8, 8, i)
end
update()
end
seltab = 1
function draw_big_char(x,y,w,h)
if protofont_surface then
surf.source(protofont_surface)
for yy=0,h-1 do
for xx=0,w-1 do
if surf.pixel(x+xx, y+yy)~=0 then
draw.rectf(xx*8, yy*8, 7, 7, 0)
else
draw.rectf(xx*8, yy*8, 7, 7, 12)
end
end
end
end
end
function any_update()
surf.cls(0)
view.origin(4,4)
draw.rrectf(0,0,140,232,3,15)
ui.button("NEW",4,4,30,11, {7,6,5})
ui.button("LOAD",36,4,30,11, {9,10,11})
ui.button("SAVE",68,4,30,11, {2,3,4})
view.origin(8,24)
local w,h = 128,20
if protofont_surface then w,h = surf.size(protofont_surface) end
draw.rrectf(0,0,132,h+35,2,14)
draw.text("SURFACE:",4,4,12)
if protofont_surface then
draw.text(protofont_name,36,4,12)
--local w,h = surf.size(protofont_surface)
local x,y = 6,15
surf.source(protofont_surface)
pal.subpal(1,12)
draw.surf(0,0,w,h,x,y,w,h)
pal.subpal(1)
draw.rect(x-1,y-1,w+2,h+2,0)
draw.rrect(x-2,y-2,w+4,h+4,2,12)
draw.text(tostring(w)..","..tostring(h), 10, 100, 3)
else
draw.text("<none>",36,4,12)
end
if ui.button("LOAD",98,20+h,30,11, {9,10,11}) then
ui.filedialog.show(select_file)
end
--view.origin(4,140)
--draw.rrectf(0,0,140,68,3,15)
view.origin(148,4)
draw.rrectf(0,0,21,12,3,14)
draw.text("BASE",3,2,12)
draw.rrectf(22,0,45,12,3,15)
draw.text("DIACRITICS",25,2,0)
-- acute(Á), grave(À); diaeresis(Ä), circumflex(Â); cedilla(Ç), tilde(Ñ)
draw.rrectf(68,0,49,12,3,15)
draw.text("PRECOMPOSED",71,2,0)
draw.rrectf(0,8,140,140,3,14)
view.origin(152,18)
draw.text("CARÀCTER ACTUAL:65(A)",0,0,0)
view.origin(152,25)
draw_big_char(7,7,7,7)
ui.button("<",70,2,9,9, {9,10,11})
--draw.rrectf(80,2,16,10,2,15)
draw.rrectf(80,2,15,9,2,13)
draw.text("240",82,4,15)
ui.button(">",96,2,9,9, {9,10,11})
view.origin(152,144)
local x,y=0,0
for c=32,127 do
draw.rectf(x,y,7,9,12)
draw.rect(x,y,7,9,0)
draw.text(string.char(c),x+2,y+2,0)
x=x+8
if x>=128 then
x=0
y=y+10
end
end
draw.text("ÁÄÉÍÓÚáéíóúÀÈÌÒÙàèìòùñÑçÇ", x, y+8, 12)
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

146
tools/fonted/data/ui.lua Normal file
View File

@@ -0,0 +1,146 @@
ui = {
button = function(text, x, y, w, h, color)
local text_x = (w-(#text*4))/2
draw.rrectf(x,y+1,w,h,2,color[1])
if mouse.inside(x,y,w,h) then
if mouse.down(mouse.LEFT) then y=y+1 end
draw.rrectf(x,y,w,h,2,color[3])
if mouse.press(mouse.LEFT) then return true end
else
draw.rrectf(x,y,w,h,2,color[2])
end
local text_y = (h-5)/2
draw.text(text,x+text_x+1,y+text_y,color[1])
return false
end,
filedialog = {
folder = nil,
files = nil,
dir = ".",
selected = 0,
offset = 0,
lift_height = -1,
lift_top = 0,
old_update = nil,
callback = nil,
show = function(callback)
if not ui.filedialog.folder then
ui.filedialog.folder=surf.new(5,4)
surf.target(ui.filedialog.folder)
for i=0,4 do for j=0,3 do surf.pixel(i,j,0) end end
for i=2,4 do surf.pixel(i,0,255) end
surf.target(0)
end
ui.filedialog.loadDir(".")
ui.filedialog.callback = callback
ui.filedialog.old_update = update
update = ui.filedialog.update
end,
loadDir = function(path)
ui.filedialog.files = sys.dir(path)
if #ui.filedialog.files > 0 then
ui.filedialog.dir = ui.filedialog.files[1].name:match("(.+)/[^/]+$")
else
ui.filedialog.dir = path
end
table.insert(ui.filedialog.files, 1, { dir=true, name=".." })
ui.filedialog.selected = 0
ui.filedialog.offset = 0
ui.filedialog.lift_height=-1
ui.filedialog.lift_top=0
if #ui.filedialog.files>23 then
ui.filedialog.lift_height=23*161/#ui.filedialog.files
end
end,
goBack = function()
ui.filedialog.dir = ui.filedialog.dir:match("(.+)/[^/]+$")
ui.filedialog.loadDir(ui.filedialog.dir)
end,
select = function()
if ui.filedialog.files[ui.filedialog.selected].dir then
local filename = ui.filedialog.files[ui.filedialog.selected].name:match("([^/]+)$")
ui.filedialog.loadDir(ui.filedialog.dir.."/"..filename)
else
update = ui.filedialog.old_update
ui.filedialog.callback(ui.filedialog.files[ui.filedialog.selected].name)
end
end,
update = function()
pal.trans(255)
view.origin(20, 20)
draw.rrectf(0,0,280,200,3,15)
draw.rrectf(4,4,272,9,2,12)
draw.rrectf(4,17,272,163,2,12)
if ui.filedialog.lift_height>0 then draw.rrectf(271,18+ui.filedialog.lift_top,4,ui.filedialog.lift_height,2,14) end
if ui.button("OK",192,184,40,11,{9,10,11}) then ui.filedialog.select() end
if ui.button("CANCEL",236,184,40,11,{1,2,3}) then update = ui.filedialog.old_update end
local y = 19
draw.text(ui.filedialog.dir, 6, 6, 0)
surf.source(ui.filedialog.folder)
local count = 0
for k,file in ipairs(ui.filedialog.files) do
local filename = file.name:match("([^/]+)$")
if count < ui.filedialog.offset then goto continue end
--if not ui.filedialog.filter or filename:match("%."..ui.filedialog.filter.."$") then
if mouse.inside(4,y-1,272,7) then
--if mx>4 and mx<268 and my>=y-1 and my<y+6 then
draw.rectf(4,y-1,272,7,13)
if mouse.dblclick() then
ui.filedialog.select()
elseif mouse.press(mouse.LEFT) then
ui.filedialog.selected = k
end
end
if ui.filedialog.selected == k then
draw.rectf(4,y-1,272,7,10)
end
if file.dir then
draw.surf(0,0,5,4,7,y+1,5,4)
pal.subpal(0,3)
draw.surf(0,0,5,4,6,y,5,4)
pal.subpal(0)
draw.text(filename, 13, y, 0)
else
draw.text(filename, 6, y, 0)
end
y=y+7
::continue::
count=count+1
if count-ui.filedialog.offset>=23 then break end
end
if key.press(key.RETURN) and ui.filedialog.selected~=-1 then
ui.filedialog.select()
elseif key.press(key.DOWN) and ui.filedialog.selected<#ui.filedialog.files then
ui.filedialog.selected=ui.filedialog.selected+1
elseif key.press(key.UP) then
if ui.filedialog.selected>1 then
ui.filedialog.selected=ui.filedialog.selected-1
else
ui.filedialog.selected = 1
end
end
local scroll = -mouse.wheel()
if scroll~=0 then
ui.filedialog.offset=ui.filedialog.offset+scroll
if ui.filedialog.offset<0 then ui.filedialog.offset=0 end
if ui.filedialog.offset+23 > #ui.filedialog.files then ui.filedialog.offset = #ui.filedialog.files-23 end
ui.filedialog.lift_top=ui.filedialog.offset*161/#ui.filedialog.files
end
end
}
}

View File

@@ -1,3 +1,3 @@
#pragma once #pragma once
#define MINI_VERSION "1.0 RC1" #define MINI_VERSION "1.4.10"

View File

@@ -3,189 +3,205 @@
---@class mini ---@class mini
mini = {} mini = {}
---@class surface ---@class surf
surface = {} ---@field surf.SCREEN number
surf = {}
---@param w number ---@param w number
---@param h number ---@param h number
---@return number surface ---@return number surface
---Create new surface specifying width and height ---Create new surface specifying width and height
function surface.new(w, h) end function surf.new(w, h) end
---@param filename string ---@param filename string
---@return number surface ---@return number surface
---Load GIF file and return surface ---Load GIF file and return surface
function surface.load(filename) end function surf.load(filename) end
---@param filename string
---@return number surface
---Load GIF from external file and return surface
function surf.loadex(filename) end
---@param surface number ---@param surface number
---@param filename string ---@param filename string
---@optional palette table ---@optional palette table
---Save surface as GIF file, with optional palette ---Save surface as GIF file, with optional palette
function surface.save(surface, filename, palette) end function surf.save(surface, filename, palette) end
---@param surface number ---@param surface number
---Free the specified surface ---Free the specified surface
function surface.free(surface) end function surf.free(surface) end
---@param surface number ---@param surface number
---@return number w, number h ---@return number w, number h
---Retrieve width and height of surface ---Retrieve width and height of surface
function surface.getSize(surface) end function surf.size(surface) end
---@return number surface
---Get current target surface
function surf.target() end
---@param surface number ---@param surface number
---Set surface as target ---Set surface as target
function surface.setTarget(surface) end function surf.target(surface) end
---@return number surface
---Get current source surface
function surf.source() end
---@param surface number
---Set surface as source
function surf.source(surface) end
---Erase the current target surface with color 0.
function surf.cls() end
---@param color number ---@param color number
---Erase the current target surface with 'color' ---Erase the current target surface with 'color'
function surface.cls(color) end function surf.cls(color) end
---@param surface number
---@param x number
---@param y number
---@param color number
---Set the color for pixel (x,y) in the specified surface.
function surface.setPixel(surface, x, y, color) end
---@param surface number
---@param x number
---@param y number
---@return number color
---Get color of pixel (x,y) in the specified surface.
function surface.getPixel(surface, x, y) end
---@param x number
---@param y number
---@param color number
---Set the color for pixel (x,y) in the current target surface.
function surface.setPixel(x, y, color) end
---@param x number ---@param x number
---@param y number ---@param y number
---@return number color ---@return number color
---Get color of pixel (x,y) in the current target ---Get color of pixel (x,y) on the source surface.
function surface.getPixel(x, y) end function surf.pixel(x, y) end
---@class tilemap ---@param x number
tilemap = {} ---@param y number
---@param color number
---Set the color for pixel (x,y) on the target surface.
function surf.pixel(x, y, color) end
---@param w number surf.SCREEN = 0
---@param h number
---Create new map specifying width and height
function tilemap.new(w, h) end ---@class map
map = {}
---@param filename string
---@return number surface ---@return number surface
---Load a tilemap from a file and set it as current tilemap ---Get tilemaps current surface
function tilemap.load(filename) end function map.surf() end
---@param filename string
---Save the current tilemap in a file
function tilemap.save(filename) end
---@param surface number ---@param surface number
---Set surface as the current tilemap ---Set surface as the current tilemap
function tilemap.set(surface) end function map.surf(surface) end
---@param surface number ---Draw the tilemap, using the source surface as tile graphics source
---Draw the tilemap, using the provided surface as tile graphics source function map.draw() end
function tilemap.draw(surface) end
---@param x number ---@param x number
---@param y number ---@param y number
---@return number color ---@return number tile
---Get tile at the position (x,y) in the current tilemap ---Get tile at the position (x,y) in the current tilemap
function tilemap.getTile(x, y) end function map.tile(x, y) end
---@param x number ---@param x number
---@param y number ---@param y number
---@param tile number ---@param tile number
---Set the tile at the position (x,y) in the current tilemap ---Set the tile at the position (x,y) in the current tilemap
function tilemap.setTile(x, y, tile) end function map.tile(x, y, tile) end
---@class palette ---@param w number
palette = {} ---@param h number
---Set current tile size
function map.cell(w, h) end
---@return number w, number h
---Set current tile size
function map.cell() end
---@class pal
pal = {}
---@param filename string ---@param filename string
---@return table pal ---@return table pal
---Load a palette from a GIF file and return it ---Load a palette from a GIF file and return it
function palette.load(filename) end function pal.load(filename) end
---@param pal table ---@param pal table
---Set a specified palette as the current palette ---Set a specified palette as the current palette
function palette.set(pal) end function pal.set(pal) end
---@param index number ---@param index number
---@return number r, number g, number b ---@return number r, number g, number b
---Retrieve (r,g,b) color for the index specified in the current palette ---Retrieve (r,g,b) color for the index specified in the current palette
function palette.getColor(index) end function pal.color(index) end
---@param index number ---@param index number
---@param r number ---@param r number
---@param g number ---@param g number
---@param b number ---@param b number
---Set (r,g,b) color for the specified index in the current palette ---Set (r,g,b) color for the specified index in the current palette
function palette.setColor(index, r, g, b) end function pal.color(index, r, g, b) end
---@return number index
---Get the index specified as transparent color
function pal.trans() end
---@param index number ---@param index number
---Set the index specified as transparent color ---Set the index specified as transparent color
function palette.setTransparent(index) end function pal.trans(index) end
---@class subpalette
subpalette = {}
---Reset all the subpalette indices to their default palette index ---Reset all the subpalette indices to their default palette index
function subpalette.resetAll() end function pal.subpal() end
---@param index number
---@return number index
---Reset the specified subpalette index to its default palette index,
---returns the previously mapped index
function pal.subpal(index) end
---@param index number ---@param index number
---@param color number ---@param color number
---Set the specified subpalette index to the specified palette index ---@return number index
function subpalette.set(index, color) end ---Set the specified subpalette index to the specified palette index,
---returns the previously mapped index
---@param index number function pal.subpal(index, color) end
---Reset the specified subpalette index to its default palette index
function subpalette.reset(index) end
---@param index1 number ---@param index1 number
---@param index2 number ---@param index2 number
---@param color number ---@param color number
---Set the specified subpalette range to the specified palette index ---Set the specified subpalette range to the specified palette index
function subpalette.setRange(index1, index2, color) end function pal.subpal(index1, index2, color) end
---@param index1 number ---@class view
---@param index2 number view = {}
---Reset the specified subpalette range to its default palette index
function subpalette.resetRange(index1, index2) end
---@class viewport ---reset the current clipping region to the entire window
viewport = {} function view.clip() end
---@param x number ---@param x number
---@param y number ---@param y number
---@param w number ---@param w number
---@param h number ---@param h number
---Set the current clipping region ---Set the current clipping region
function viewport.setClipping(x, y, w, h) end function view.clip(x, y, w, h) end
---reset the current clipping region to the entire window ---@return number x, number y
function viewport.resetClipping() end ---Get the current origin position
function view.origin() end
---@param x number ---@param x number
---@param y number ---@param y number
---Set the current origin position ---Set the current origin position
function viewport.setOrigin(x, y) end function view.origin(x, y) end
---@return number x, number y
---Get the current origin position
function viewport.getOrigin() end
---@param x number ---@param x number
---@param y number ---@param y number
---@return number x, number y ---@return number x, number y
---Convert screen position to viewport position ---Convert screen position to viewport position
function viewport.toLocal(x, y) end function view.tolocal(x, y) end
---@class draw ---@class draw
---@field draw.NORMAL number
---@field draw.PATTERN number
---@field draw.AND number
---@field draw.OR number
---@field draw.XOR number
---@field draw.NOT number
draw = {} draw = {}
---@param x1 number ---@param x1 number
@@ -210,21 +226,21 @@ function draw.hline(x1, y, x2, color) end
---Draw a vertical line from (x,y1) to (x,y2) with the givencolor ---Draw a vertical line from (x,y1) to (x,y2) with the givencolor
function draw.vline(x, y1, y2, color) end function draw.vline(x, y1, y2, color) end
---@param x1 number ---@param x number
---@param y1 number ---@param y number
---@param x2 number ---@param w number
---@param y2 number ---@param h number
---@param color number ---@param color number
---Draw the ouline of a rectangle from (x1,y1) to (x2,y2) with the given color ---Draw the ouline of a rectangle at (x,y) of size (w,h) with the given color
function draw.rect(x1, y1, x2, y2, color) end function draw.rect(x, y, w, h, color) end
---@param x1 number ---@param x number
---@param y1 number ---@param y number
---@param x2 number ---@param w number
---@param y2 number ---@param h number
---@param color number ---@param color number
---Draw a filled rectangle from (x1,y1) to (x2,y2) with the given color ---Draw a filled rectangle at (x,y) of size (w,h) with the given color
function draw.rectFill(x1, y1, x2, y2, color) end function draw.rectf(x, y, w, h, color) end
---@param x number ---@param x number
---@param y number ---@param y number
@@ -238,7 +254,25 @@ function draw.circ(x, y, r, color) end
---@param r number ---@param r number
---@param color number ---@param color number
---Draw a filled cicle at position(x,y) with radius r and the given color ---Draw a filled cicle at position(x,y) with radius r and the given color
function draw.circFill(x, y, r, color) end function draw.circf(x, y, r, color) end
---@param x number
---@param y number
---@param w number
---@param h number
---@param r number
---@param color number
---Draw the outline of a round rectangle at (x,y) of size (w,h) with border radius r and the given color
function draw.rrect(x, y, w, h, r, color) end
---@param x number
---@param y number
---@param w number
---@param h number
---@param r number
---@param color number
---Draw a filled round rectangle at (x,y) of size (w,h) with border radius r and the given color
function draw.rrectf(x, y, w, h, r, color) end
---@param x1 number ---@param x1 number
---@param y1 number ---@param y1 number
@@ -254,13 +288,15 @@ function draw.oval(x1, y1, x2, y2, color) end
---@param y2 number ---@param y2 number
---@param color number ---@param color number
---Draw a filled oval enclosed in (x1,y1)-(x2,y2) and the given color ---Draw a filled oval enclosed in (x1,y1)-(x2,y2) and the given color
function draw.ovalFill(x1, y1, x2, y2, color) end function draw.ovalf(x1, y1, x2, y2, color) end
---@param pattern number ---@param pattern number
---Specify a pattern for the drawing functions ---Specify a pattern for the drawing functions
function draw.setPattern(pattern) end function draw.pattern(pattern) end
---Reset to no pattern for drawing functions
function draw.pattern() end
---@param surface number
---@param sx number ---@param sx number
---@param sy number ---@param sy number
---@param sw number ---@param sw number
@@ -272,12 +308,11 @@ function draw.setPattern(pattern) end
---@optional boolean flip_x ---@optional boolean flip_x
---@optional boolean flip_y ---@optional boolean flip_y
---@optional boolean invert ---@optional boolean invert
---Blit the region starting at (sx,sy) and size (sw, sh) from the specified surface ---Blit the region starting at (sx,sy) and size (sw, sh) from the source surface
---to the position (dx, dy) (and optionally of size (dw, dh)) to the target surface, ---to the position (dx, dy) (and optionally of size (dw, dh)) to the target surface,
---optionally flipping it horizontally or vertically, or inverting x and y axes ---optionally flipping it horizontally or vertically, or inverting x and y axes
function draw.surface(surface, sx, sy, sw, sh, dx, dy, dw, dh, flip_x, flip_y, invert) end function draw.surf(sx, sy, sw, sh, dx, dy, dw, dh, flip_x, flip_y, invert) end
---@param surface number
---@param sx number ---@param sx number
---@param sy number ---@param sy number
---@param sw number ---@param sw number
@@ -285,9 +320,15 @@ function draw.surface(surface, sx, sy, sw, sh, dx, dy, dw, dh, flip_x, flip_y, i
---@param x number ---@param x number
---@param y number ---@param y number
---@param a number ---@param a number
---Blit the region starting at (sx,sy) and size (sw, sh) from the specified surface ---@optional dw number
---to the position (dx, dy) of the target surface, rotating it by a degrees ---@optional dh number
function draw.surfaceRotated(surface, sx, sy, sw, sh, x, y, a) end ---@optional boolean flip_x
---@optional boolean flip_y
---@optional boolean invert
---Blit the region starting at (sx,sy) and size (sw, sh) from the source surface
---to the position (dx, dy) of the target surface, rotating it by a degrees,
---(and optionally of size (dw, dh)) optionally flipping it horizontally or vertically
function draw.surfrot(sx, sy, sw, sh, x, y, a, dw, dh, flip_x, flip_y) end
---@param text string ---@param text string
---@param x number ---@param x number
@@ -296,6 +337,39 @@ function draw.surfaceRotated(surface, sx, sy, sw, sh, x, y, a) end
---Draw text to (x,y) using the specified color ---Draw text to (x,y) using the specified color
function draw.text(text, x, y, color) end function draw.text(text, x, y, color) end
---@param mode number
---Specify the mode for the drawing functions
function draw.mode(mode) end
draw.NORMAL = 0
draw.PATTERN = 1
draw.AND = 2
draw.OR = 3
draw.XOR = 4
draw.NOT = 5
---@class shader
shader = {}
---Initialize shaders subsystem, still non functional without shaders
function shader.init() end
---@param shader string
---Initialize shaders subsystem, specifying a file that contains both vertex and fragment shader
function shader.init(shader) end
---@param vshader string
---@param fshader string
---Initialize shaders subsystem, specifying both a vertex shader file and a fragment shader file
function shader.init(vshader, fshader) end
---Enable previously loaded shader
function shader.enable() end
---Disable shaders
function shader.disable() end
---@class music ---@class music
music = {} music = {}
@@ -303,6 +377,11 @@ music = {}
---Load and play the song in the specified OGG file ---Load and play the song in the specified OGG file
function music.play(filename) end function music.play(filename) end
---@param filename string
---@param loop integer
---Load and play the song in the specified OGG file, loop number of times
function music.play(filename, loop) end
---Pause the currently playing song ---Pause the currently playing song
function music.pause() end function music.pause() end
@@ -312,13 +391,22 @@ function music.resume() end
---Stop the currently playing song ---Stop the currently playing song
function music.stop() end function music.stop() end
---@param pos number
---Set the playing position of the currently loaded song
function music.setPosition(pos) end
---@return number pos ---@return number pos
---Get the playing position of the currently loaded song ---Get the playing position of the currently loaded song
function music.getPosition() end function music.pos() end
---@param pos number
---Set the playing position of the currently loaded song
function music.pos(pos) end
---@return boolean value
---Get if music is enabled
function music.enabled() end
---@param value boolean
---Set if music is enabled or not
function music.enabled(value) end
---@class sound ---@class sound
sound = {} sound = {}
@@ -337,72 +425,123 @@ function sound.free(snd) end
---Play the sound specified, returns the channel in which it's playing ---Play the sound specified, returns the channel in which it's playing
function sound.play(snd) end function sound.play(snd) end
---@param snd number
---@param loop integer
---@return number chl
---Play the sound specified loop number of times, returns the channel in which it's playing
function sound.play(snd, loop) end
---@param chl number ---@param chl number
---Stop the channel specified ---Stop the channel specified
function sound.stop(chl) end function sound.stop(chl) end
---@class system ---@return boolean value
system = {} ---Get if sound is enabled
function sound.enabled() end
---@param value boolean
---Set if sound is enabled or not
function sound.enabled(value) end
---@class sys
sys = {}
---Get delta time from last update in seconds (with decimals)
function sys.delta() end
---Get current system timer in seconds (with decimals) ---Get current system timer in seconds (with decimals)
function system.getTime() end function sys.time() end
---@param bts number ---@param offset number
---Set number of frames between beats ---Reset chrono time (with offset in seconds) (with decimals)
function system.setBeat(bts) end function sys.chrono(offset) end
---@return number
---@---Get chrono time since last chrono reset in seconds (with decimals)
function sys.chrono() end
---@return boolean ---@return boolean
---Query if a beat has already passed ---Query if a beat has already passed
function system.isBeat() end function sys.beat() end
---The game will call mini.update as fast as possible ---@param bts number
function system.updateAtFullSpeed() end ---Set number of frames between beats
function sys.beat(bts) end
---The game will call mini.update only when a keyboard, mouse or pad event fires
function system.updateOnlyOnEvents() end
---@param mode number
---@param ms number ---@param ms number
---The game will call mini.update on events or after the milliseconds specified passed ---Sets the update mode.
function system.updateOnEventsAndTimeout(ms) end ---UPDATE_ALWAYS: The game will call mini.update as fast as possible
---UPDATE_EVENTS: The game will call mini.update only when a keyboard, mouse or pad event fires
---UPDATE_TIMEOUT: The game will call mini.update on events or after the milliseconds specified passed
function sys.update(mode, ms) end
---@return table ---@return table
---Gets a table with the name of each file in the data directory ---Gets a table in which each entry has a field "name" with the name and a field "dir" with a
function system.getFilesInDataDirectory() end ---boolean specifying if it's a directory, for each file in the 'data' directory
function sys.dir() end
---@param path string
---@return table
---Gets a table in which each entry has a field "name" with the name and a field "dir" with a
---boolean specifying if it's a directory, for each file in the specified path
function sys.dir(path) end
---Exit the game ---Exit the game
function system.quit() end function sys.quit() end
---@class window ---@return number
window = {} ---Gets the frames per second
function sys.fps() end
---@return string
---Gets the content of the clipboard
function sys.clipboard() end
---@param value string
---Sets the content of the clipboard
function sys.clipboard(value) end
---@return boolean
---Returns true if running on debug version of mini. False otherwise.
function sys.debug() end
---@return string
---Returns the current mini version as a string.
function sys.version() end
---@class win
win = {}
---@param value number ---@param value number
---Set the window zoom ---Set the window zoom
function window.setZoom(value) end function win.zoom(value) end
---@return number value ---@return number value
---Get the window zoom ---Get the window zoom
function window.getZoom() end function win.zoom() end
---@param value boolean ---@param value boolean
---Specifies if the window must display at fullscreen or not ---Specifies if the window must display at fullscreen or not
function window.setFullscreen(value) end function win.fullscreen(value) end
---@return boolean value ---@return boolean value
---Returns if the window is at fullscreen or not ---Returns if the window is at fullscreen or not
function window.getFullscreen() end function win.fullscreen() end
---@param value boolean ---@param value boolean
---Specifies if the cursor must be visible or not ---Specifies if the cursor must be visible or not
function window.showCursor(value) end function win.cursor(value) end
---@return number w, number h ---@return number w, number h
---Returns the current window size ---Returns the current window size
function window.getResolution() end function win.res() end
---@param w number ---@param w number
---@param h number ---@param h number
---Sets the window size ---Sets the window size
function window.setResolution(w, h) end function win.res(w, h) end
---@class config ---@class config
@@ -411,81 +550,187 @@ config = {}
---@param key string ---@param key string
---@param value any ---@param value any
---Sets the value of a key in the configuration file ---Sets the value of a key in the configuration file
function config.setKey(key, value) end function config.key(key, value) end
---@param key string ---@param key string
---@return string value ---@return string value
---Gets the value of a key in the configuration file ---Gets the value of a key in the configuration file
function config.getKey(key) end function config.key(key) end
---@return string value ---@return string value
---Returns the folder in which the configuration file resides ---Returns the folder in which the configuration file resides
function config.getConfigFolder() end function config.folder() end
---@class font
---@field font.DEFAULT number
font = {}
---@param filename string
---@return number fnt
---Loads a font from a file
function font.load(filename) end
---@return number fnt
---Gets the currently selected font
function font.current() end
---@param fnt number
---Sets the specified font as selected
function font.current(fnt) end
---@return number value
---Gets the currently selected font's spacing
function font.spacing() end
---@param value number
---Sets the currently selected font's spacing
function font.spacing(value) end
font.DEFAULT = 0
---@class mouse ---@class mouse
---@field mouse.LEFT number
---@field mouse.MIDDLE number
---@field mouse.RIGHT number
mouse = {} mouse = {}
---@return number x, number y ---@return number x, number y
---Returns the current position of the mouse ---Returns the current position of the mouse
function mouse.getPos() end function mouse.pos() end
---@return number value ---@return number value
---Returns the value of the mouse wheel ---Returns the value of the mouse wheel
function mouse.getWheel() end function mouse.wheel() end
---@param btn number ---@param btn number
---@return boolean ---@return boolean
---Returns whether the specified mouse button is down ---Returns whether the specified mouse button is down
function mouse.buttonDown(btn) end function mouse.down(btn) end
---@param btn number ---@param btn number
---@return boolean ---@return boolean
---Returns whether the specified mouse button has just been pressed ---Returns whether the specified mouse button has just been pressed
function mouse.buttonPressed(btn) end function mouse.press(btn) end
---@class keyboard ---@return boolean
keyboard = {} ---Returns whether the user performed a double click
function mouse.dblclick() end
---Ignores current down button, effectively not raising the next "press" event
function mouse.discard() end
---@param x number
---@param y number
---@param w number
---@param h number
---@return boolean
---Returns whether the mouse is inside the rectangle specified
function mouse.inside(x,y,w,h) end
mouse.LEFT = 1
mouse.MIDDLE = 2
mouse.RIGHT = 3
---@class key
key = {}
---@param key number ---@param key number
---@return boolean ---@return boolean
---Returns whether the specified keyboard key is down ---Returns whether the specified keyboard key is down
function keyboard.keyDown(key) end function key.down(key) end
---@return number ---@return number
---Returns which keyboard key has just been pressed ---Returns which keyboard key has just been pressed
function keyboard.keyPressed() end function key.press() end
---@param key number ---@param key number
---@return boolean ---@return boolean
---Returns whether the specified keyboard key has just been pressed ---Returns whether the specified keyboard key has just been pressed
function keyboard.keyPressed(key) end function key.press(key) end
---@return boolean ---@return boolean
---Returns whether any keyboard key has just been pressed ---Returns whether any keyboard key has just been pressed
function keyboard.anyKeyPressed() end function key.any() end
---@param enable boolean
---Enable or disable utf8 text input
function key.text(enable) end
---@return string
---Returns a string with the utf-8 character sequence pressed. Only when utf8 is enabled
function key.utf8char() end
---@class gamepad ---@class pad
gamepad = {} ---@field pad.INVALID number
---@field pad.A number
---@field pad.B number
---@field pad.X number
---@field pad.Y number
---@field pad.BACK number
---@field pad.GUIDE number
---@field pad.START number
---@field pad.LEFTSTICK number
---@field pad.RIGHTSTICK number
---@field pad.LEFTSHOULDER number
---@field pad.RIGHTSHOULDER number
---@field pad.UP number
---@field pad.DOWN number
---@field pad.LEFT number
---@field pad.RIGHT number
---@field pad.MISC1 number
---@field pad.PADDLE1 number
---@field pad.PADDLE2 number
---@field pad.PADDLE3 number
---@field pad.PADDLE4 number
---@field pad.TOUCHPAD number
pad = {}
---@param btn number ---@param btn number
---@return boolean ---@return boolean
---Returns whether the specified gamepad button is down ---Returns whether the specified gamepad button is down
function gamepad.buttonDown(btn) end function pad.down(btn) end
---@return number ---@return number
---Returns which gamepad button has just been pressed ---Returns which gamepad button has just been pressed
function gamepad.buttonPressed() end function pad.press() end
---@param btn number ---@param btn number
---@return boolean ---@return boolean
---Returns whether the specified gamepad button has just been pressed ---Returns whether the specified gamepad button has just been pressed
function gamepad.buttonPressed(btn) end function pad.press(btn) end
---@return boolean ---@return boolean
---Returns whether any gamepad button has just been pressed ---Returns whether any gamepad button has just been pressed
function gamepad.anybuttonPressed() end function pad.any() end
pad.INVALID = -1
pad.A = 0
pad.B = 1
pad.X = 2
pad.Y = 3
pad.BACK = 4
pad.GUIDE = 5
pad.START = 6
pad.LEFTSTICK = 7
pad.RIGHTSTICK = 8
pad.LEFTSHOULDER = 9
pad.RIGHTSHOULDER = 10
pad.UP = 11
pad.DOWN = 12
pad.LEFT = 13
pad.RIGHT = 14
pad.MISC1 = 15
pad.PADDLE1 = 16
pad.PADDLE2 = 17
pad.PADDLE3 = 18
pad.PADDLE4 = 19
pad.TOUCHPAD = 20
---@class key ---@class key
---@field key.UNKNOWN number ---@field key.UNKNOWN number
@@ -515,16 +760,16 @@ function gamepad.anybuttonPressed() end
---@field key.X number ---@field key.X number
---@field key.Y number ---@field key.Y number
---@field key.Z number ---@field key.Z number
---@field key.1 number ---@field key.N1 number
---@field key.2 number ---@field key.N2 number
---@field key.3 number ---@field key.N3 number
---@field key.4 number ---@field key.N4 number
---@field key.5 number ---@field key.N5 number
---@field key.6 number ---@field key.N6 number
---@field key.7 number ---@field key.N7 number
---@field key.8 number ---@field key.N8 number
---@field key.9 number ---@field key.N9 number
---@field key.0 number ---@field key.N0 number
---@field key.RETURN number ---@field key.RETURN number
---@field key.ESCAPE number ---@field key.ESCAPE number
---@field key.BACKSPACE number ---@field key.BACKSPACE number
@@ -595,7 +840,7 @@ function gamepad.anybuttonPressed() end
---@field key.RSHIFT number ---@field key.RSHIFT number
---@field key.RALT number ---@field key.RALT number
---@field key.RGUI number ---@field key.RGUI number
key = {}
key.UNKNOWN = 0 key.UNKNOWN = 0
key.A = 4 key.A = 4
key.B = 5 key.B = 5
@@ -704,51 +949,12 @@ key.RSHIFT = 229
key.RALT = 230 key.RALT = 230
key.RGUI = 231 key.RGUI = 231
---@class utf8
utf8 = {}
---@class button ---@param str string
---@field button.INVALID number ---@param startchr number
---@field button.A number ---@param endchr number
---@field button.B number ---@return string
---@field button.X number ---Returns whether the specified keyboard key is down
---@field button.Y number function utf8.sub(str, startchr, endchr) end
---@field button.BACK number
---@field button.GUIDE number
---@field button.START number
---@field button.LEFTSTICK number
---@field button.RIGHTSTICK number
---@field button.LEFTSHOULDER number
---@field button.RIGHTSHOULDER number
---@field button.UP number
---@field button.DOWN number
---@field button.LEFT number
---@field button.RIGHT number
---@field button.MISC1 number
---@field button.PADDLE1 number
---@field button.PADDLE2 number
---@field button.PADDLE3 number
---@field button.PADDLE4 number
---@field button.TOUCHPAD number
button = {}
button.INVALID = -1
button.A = 0
button.B = 1
button.X = 2
button.Y = 3
button.BACK = 4
button.GUIDE = 5
button.START = 6
button.LEFTSTICK = 7
button.RIGHTSTICK = 8
button.LEFTSHOULDER = 9
button.RIGHTSHOULDER = 10
button.UP = 11
button.DOWN = 12
button.LEFT = 13
button.RIGHT = 14
button.MISC1 = 15
button.PADDLE1 = 16
button.PADDLE2 = 17
button.PADDLE3 = 18
button.PADDLE4 = 19
button.TOUCHPAD = 20