Compare commits
47 Commits
61b02fdeef
...
v1.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 536987f89b | |||
| 4084cb64f2 | |||
| 33bbf940ea | |||
| f12e46db1b | |||
| 681cbc2207 | |||
| 5db06a0645 | |||
| a17a1bb517 | |||
| fc962b4e18 | |||
| 9581ce67fd | |||
| 7c3b58c5f0 | |||
| 6e15fe7231 | |||
| eac20bbbe0 | |||
| 7fac42c9fe | |||
| 4858d94378 | |||
| 3e524fd32d | |||
| ace4a0f9f0 | |||
| 839c1e82eb | |||
| 33d7cc3b6d | |||
| a7cbdea4c5 | |||
| 3383b415cd | |||
| 02dc0a4953 | |||
| 091c2617a4 | |||
| c7559f0d29 | |||
| 327453b02c | |||
| 62ac5ae92d | |||
| 4172c6af3d | |||
| 7bff57c6fa | |||
| f154e1a36b | |||
| 0471bcbdda | |||
| 76e2925791 | |||
| 34a56fedcf | |||
| 9cd991cb44 | |||
| e1d5eb051c | |||
| 79781bbed1 | |||
| 0cb1296ad3 | |||
| 16be589a72 | |||
| 2a4195c839 | |||
| 5e24117266 | |||
| 88609465cb | |||
| 8f8009e8af | |||
| 150cb9f4ff | |||
| 4bda9cbd39 | |||
| adcc44ddab | |||
| 8e855fa2c1 | |||
| 8f98d52385 | |||
| b6e5dca277 | |||
| 3d14c33971 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ mini_debug
|
|||||||
.vscode/*
|
.vscode/*
|
||||||
info.plist
|
info.plist
|
||||||
*.dll
|
*.dll
|
||||||
|
build/*
|
||||||
14
Makefile
14
Makefile
@@ -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 -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++11 -ffunction-sections -fdata-sections -lSDL3 -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++11 -ffunction-sections -fdata-sections -lSDL3 -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++11 -framework SDL3 -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"
|
||||||
|
|||||||
@@ -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
38
data/gbc.glsl
Normal 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
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
9
data/ia/other.lua
Normal 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
3
data/ia/test.lua
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
function test2()
|
||||||
|
draw.text("THIS WORKS!",1,140,4)
|
||||||
|
end
|
||||||
41
data/lynx.glsl
Normal file
41
data/lynx.glsl
Normal 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
|
||||||
129
data/main.lua
129
data/main.lua
@@ -1,106 +1,45 @@
|
|||||||
other = require "other"
|
require "ia.other"
|
||||||
|
|
||||||
x=0
|
x=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;
|
print("=== PACKAGES LOADED ===")
|
||||||
s = surface.load("tiles01.gif")
|
for name, value in pairs(package.loaded) do
|
||||||
--surface.source(s)
|
print(name, value)
|
||||||
p = palette.load("tiles01.gif")
|
end
|
||||||
palette.set(p)
|
print("========================")
|
||||||
palette.setTransparent(255)
|
|
||||||
print(#p)
|
|
||||||
surface.save(s, "data/copy.gif")
|
|
||||||
s = surface.load("copy.gif")
|
|
||||||
--draw.source(s)
|
|
||||||
system.setBeat(4)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function mini.update()
|
function mini.update()
|
||||||
if keyboard.keyPressed(key.ESCAPE) then
|
surf.cls(0)
|
||||||
system.quit()
|
draw.surf(0, 0, 160, 144, 0, 0)
|
||||||
|
|
||||||
|
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)
|
|
||||||
--draw.text(#p,0,0,2)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
return {
|
|
||||||
peiv = function()
|
|
||||||
palette.setColor(1, 1, 1, 1)
|
|
||||||
return "HOLA OTHER UNIT"
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@@ -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
332
gifenc.h
@@ -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(gif);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
free(compressed);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
380
jail_audio.cpp
380
jail_audio.cpp
@@ -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(¤t_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
jail_audio.h
12
jail_audio.h
@@ -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);
|
||||||
|
|||||||
157
jfile.cpp
157
jfile.cpp
@@ -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>
|
||||||
@@ -130,10 +132,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 +173,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 +216,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 +273,107 @@ 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);
|
||||||
|
return mkdir(tmp, 0755)==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
10
jfile.h
@@ -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);
|
||||||
250
jshader.cpp
Normal file
250
jshader.cpp
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
#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;
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
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, ¶m);
|
||||||
|
//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
48
jshader.h
Normal 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
5
lagueirtofile
Normal 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
27
log.h
Normal 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
|
||||||
112
lua/loadlib.c
112
lua/loadlib.c
@@ -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] */
|
||||||
|
|||||||
526
mini.cpp
526
mini.cpp
@@ -2,12 +2,14 @@
|
|||||||
#include "jfile.h"
|
#include "jfile.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "gif.c"
|
#include "gif.h"
|
||||||
#include "gifenc.h"
|
#include "gifenc.h"
|
||||||
//#include "SDL2/SDL_mixer.h"
|
|
||||||
#include "jail_audio.h"
|
#include "jail_audio.h"
|
||||||
|
#include "jshader.h"
|
||||||
|
//#include <vector>
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define MAX_TEXTURES 10
|
#define MAX_SURFACES 100
|
||||||
|
|
||||||
#ifdef MACOS_BUNDLE
|
#ifdef MACOS_BUNDLE
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
@@ -18,12 +20,22 @@
|
|||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
struct surface_t {
|
struct surface_t {
|
||||||
uint8_t *p;
|
char *name {nullptr};
|
||||||
|
uint8_t *p {nullptr};
|
||||||
uint16_t w, h;
|
uint16_t w, h;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct font_t {
|
||||||
|
struct special_char_t { uint8_t character; SDL_Rect glyph; SDL_Point displacement; };
|
||||||
|
int8_t spacing;
|
||||||
|
SDL_Rect characters[96];
|
||||||
|
special_char_t specials[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
int fps=0;
|
||||||
|
int fps_counter=0;
|
||||||
|
uint32_t fps_timer=0;
|
||||||
char window_title[256];
|
char window_title[256];
|
||||||
char config_folder[256];
|
char config_folder[256];
|
||||||
uint16_t screen_width = 160;
|
uint16_t screen_width = 160;
|
||||||
@@ -35,7 +47,7 @@ bool screen_cursor = true;
|
|||||||
int desktop_width = 0;
|
int desktop_width = 0;
|
||||||
int desktop_height = 0;
|
int desktop_height = 0;
|
||||||
|
|
||||||
surface_t surfaces[MAX_TEXTURES];
|
surface_t surfaces[MAX_SURFACES];
|
||||||
surface_t *screen_surface = &surfaces[0];
|
surface_t *screen_surface = &surfaces[0];
|
||||||
surface_t *dest_surface = screen_surface;
|
surface_t *dest_surface = screen_surface;
|
||||||
surface_t *source_surface = NULL;
|
surface_t *source_surface = NULL;
|
||||||
@@ -66,6 +78,7 @@ namespace ds {
|
|||||||
uint16_t fill_pattern = 0b1111111111111111;
|
uint16_t fill_pattern = 0b1111111111111111;
|
||||||
bool fill_trans = false;
|
bool fill_trans = false;
|
||||||
uint8_t draw_palette[256];
|
uint8_t draw_palette[256];
|
||||||
|
uint8_t mode = DRAWMODE_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int update_mode = UPDATE_ALWAYS;
|
int update_mode = UPDATE_ALWAYS;
|
||||||
@@ -76,12 +89,13 @@ bool should_quit = false;
|
|||||||
SDL_Window *mini_win;
|
SDL_Window *mini_win;
|
||||||
SDL_Renderer *mini_ren;
|
SDL_Renderer *mini_ren;
|
||||||
SDL_Texture *mini_bak;
|
SDL_Texture *mini_bak;
|
||||||
|
SDL_Texture *mini_shadertex;
|
||||||
Uint32 windowID;
|
Uint32 windowID;
|
||||||
Uint32 *pixels;
|
Uint32 *pixels;
|
||||||
int pitch;
|
int pitch;
|
||||||
|
|
||||||
uint32_t palette[256] = { 0x001a1c2c, 0x005d275d, 0x00b13e53, 0x00ef7d57, 0x00ffcd75, 0x00a7f070, 0x0038b764, 0x00257179,
|
uint32_t palette[256] = { 0xFF1a1c2c, 0xFF5d275d, 0xFFb13e53, 0xFFef7d57, 0xFFffcd75, 0xFFa7f070, 0xFF38b764, 0xFF257179,
|
||||||
0x0029366f, 0x003b5dc9, 0x0041a6f6, 0x0073eff7, 0x00f4f4f4, 0x0094b0c2, 0x00566c86, 0x00333c57 };
|
0xFF29366f, 0xFF3b5dc9, 0xFF41a6f6, 0xFF73eff7, 0xFFf4f4f4, 0xFF94b0c2, 0xFF566c86, 0xFF333c57 };
|
||||||
|
|
||||||
const char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
const char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
@@ -93,15 +107,17 @@ char base64glyphs[193] = "/h/AqV/hhhh/GMYYMGz/t/eS33H477wsjjswY4IOPHEFFVVVAVAVAV
|
|||||||
"AMShAAAQsjAAAwsjAAAeSzAAAcU3AAAEqRAAABVaiAAMezhAAAAAMAADH4wAASb2SAAMAttAQYcefACGOe+AAAVVAAAAbbAA";
|
"AMShAAAQsjAAAwsjAAAeSzAAAcU3AAAEqRAAABVaiAAMezhAAAAAMAADH4wAASb2SAAMAttAQYcefACGOe+AAAVVAAAAbbAA";
|
||||||
|
|
||||||
//Uint8 keymapping[6] = { SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_Z, SDL_SCANCODE_X };
|
//Uint8 keymapping[6] = { SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_Z, SDL_SCANCODE_X };
|
||||||
const Uint8 *keys;
|
const bool *keys;
|
||||||
Uint8 key_just_pressed = 0;
|
Uint8 key_just_pressed = 0;
|
||||||
|
|
||||||
int mouse_x, mouse_y, mouse_wheel;
|
int mouse_x, mouse_y, mouse_wheel;
|
||||||
Uint32 mouse_buttons;
|
Uint32 mouse_buttons;
|
||||||
uint8_t mouse_just_pressed = 0;
|
uint8_t mouse_just_pressed = 0;
|
||||||
|
bool double_click = false;
|
||||||
|
bool mouse_discard = false;
|
||||||
|
|
||||||
SDL_GameController *gamepad = NULL;
|
SDL_Gamepad *gamepad = NULL;
|
||||||
int8_t pad_just_pressed = SDL_CONTROLLER_BUTTON_INVALID;
|
int8_t pad_just_pressed = SDL_GAMEPAD_BUTTON_INVALID;
|
||||||
|
|
||||||
#define MAX_SOUNDS 50
|
#define MAX_SOUNDS 50
|
||||||
JA_Music_t *music = NULL;
|
JA_Music_t *music = NULL;
|
||||||
@@ -109,6 +125,8 @@ JA_Sound_t *sounds[MAX_SOUNDS];
|
|||||||
|
|
||||||
int16_t beats, num_beats = 0;
|
int16_t beats, num_beats = 0;
|
||||||
|
|
||||||
|
void createNewProject();
|
||||||
|
|
||||||
char* get_value_from_line(char* line) {
|
char* get_value_from_line(char* line) {
|
||||||
char* equal_character = strchr(line, '=');
|
char* equal_character = strchr(line, '=');
|
||||||
if (equal_character == NULL) return NULL;
|
if (equal_character == NULL) return NULL;
|
||||||
@@ -118,21 +136,20 @@ char* get_value_from_line(char* line) {
|
|||||||
|
|
||||||
void read_ini() {
|
void read_ini() {
|
||||||
int size;
|
int size;
|
||||||
SDL_Log("Carregant 'game.ini'...");
|
|
||||||
FILE *f = file_getfilepointer("game.ini", size); // fopen("game.ini", "r");
|
FILE *f = file_getfilepointer("game.ini", size); // fopen("game.ini", "r");
|
||||||
char line[1024];
|
char line[1024];
|
||||||
if (f == NULL) { SDL_Log("FAIL!\n"); return; }
|
if (f == NULL) { log_msg(LOG_FAIL, "No s'ha pogut obrir 'game.ini'\n"); exit(-1); }
|
||||||
SDL_Log("OK!\n");
|
log_msg(LOG_OK, "'game.ini' carregat\n");
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
char *value = get_value_from_line(line);
|
char *value = get_value_from_line(line);
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
value[strlen(value)-1] = '\0';
|
value[strlen(value)-1] = '\0';
|
||||||
if (strcmp(line, "title") == 0) { strcpy(window_title, value); SDL_Log("-title=%s\n", window_title); }
|
if (strcmp(line, "title") == 0) { strcpy(window_title, value); log_msg(LOG_VERBOSE, "title = %s\n", window_title); }
|
||||||
else if (strcmp(line, "config") == 0) { strcpy(config_folder, value); SDL_Log("-config=%s\n", config_folder); }
|
else if (strcmp(line, "config") == 0) { strcpy(config_folder, value); log_msg(LOG_VERBOSE, "config = %s\n", config_folder); }
|
||||||
else if (strcmp(line, "width") == 0) { screen_width = atoi(value); SDL_Log("-screen width=%i\n", screen_width); }
|
else if (strcmp(line, "width") == 0) { screen_width = atoi(value); log_msg(LOG_VERBOSE, "screen width = %i\n", screen_width); }
|
||||||
else if (strcmp(line, "height") == 0) { screen_height = atoi(value); SDL_Log("-screen height=%i\n", screen_height); }
|
else if (strcmp(line, "height") == 0) { screen_height = atoi(value); log_msg(LOG_VERBOSE, "screen height = %i\n", screen_height); }
|
||||||
else if (strcmp(line, "zoom") == 0) { screen_zoom = atoi(value); SDL_Log("-screen zoom=%i\n", screen_zoom); }
|
else if (strcmp(line, "zoom") == 0) { screen_zoom = atoi(value); log_msg(LOG_VERBOSE, "screen zoom = %i\n", screen_zoom); }
|
||||||
else if (strcmp(line, "fullscreen") == 0) { screen_fullscreen = atoi(value); SDL_Log("-screen sullscreen=%i\n", screen_fullscreen); }
|
else if (strcmp(line, "fullscreen") == 0) { screen_fullscreen = atoi(value); log_msg(LOG_VERBOSE, "screen sullscreen = %i\n", screen_fullscreen); }
|
||||||
//else if (strcmp(line, "files") == 0) {
|
//else if (strcmp(line, "files") == 0) {
|
||||||
//lua_files = (char*)malloc(strlen(value));
|
//lua_files = (char*)malloc(strlen(value));
|
||||||
// strcpy(lua_files, value);
|
// strcpy(lua_files, value);
|
||||||
@@ -140,13 +157,32 @@ void read_ini() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
SDL_Log("'game.ini' carregat!\n");
|
//SDL_Log("'game.ini' carregat!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void pset_fast(int x, int y) {
|
void pset_fast(int x, int y) {
|
||||||
if (ds::trans != ds::pen_color) DEST(x, y) = ds::draw_palette[ds::pen_color];
|
if (ds::trans != ds::pen_color) DEST(x, y) = ds::draw_palette[ds::pen_color];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pset_bool(int x, int y) {
|
||||||
|
if (ds::trans != ds::pen_color) {
|
||||||
|
switch (ds::mode) {
|
||||||
|
case DRAWMODE_AND:
|
||||||
|
DEST(x, y) = DEST(x, y) & ds::draw_palette[ds::pen_color];
|
||||||
|
break;
|
||||||
|
case DRAWMODE_OR:
|
||||||
|
DEST(x, y) = DEST(x, y) | ds::draw_palette[ds::pen_color];
|
||||||
|
break;
|
||||||
|
case DRAWMODE_XOR:
|
||||||
|
DEST(x, y) = DEST(x, y) ^ ds::draw_palette[ds::pen_color];
|
||||||
|
break;
|
||||||
|
case DRAWMODE_NOT:
|
||||||
|
DEST(x, y) = ~DEST(x, y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pset_pattern(int x, int y) {
|
void pset_pattern(int x, int y) {
|
||||||
int pbx = x % 4, pby = y % 4;
|
int pbx = x % 4, pby = y % 4;
|
||||||
int pb = pbx+pby*4;
|
int pb = pbx+pby*4;
|
||||||
@@ -157,8 +193,29 @@ void pset_pattern(int x, int y) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_draw_mode(uint8_t mode) {
|
||||||
|
ds::mode = mode;
|
||||||
|
switch (mode) {
|
||||||
|
case DRAWMODE_NORMAL:
|
||||||
|
do_pset = pset_fast;
|
||||||
|
break;
|
||||||
|
case DRAWMODE_PATTERN:
|
||||||
|
do_pset = pset_pattern;
|
||||||
|
break;
|
||||||
|
case DRAWMODE_AND:
|
||||||
|
case DRAWMODE_OR:
|
||||||
|
case DRAWMODE_XOR:
|
||||||
|
case DRAWMODE_NOT:
|
||||||
|
do_pset = pset_bool;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
do_pset = pset_fast;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void reinit() {
|
void reinit() {
|
||||||
SDL_Log("REINIT\n");
|
log_msg(LOG_INFO, "STARTING A SYSTEM REINITIALIZATION\n");
|
||||||
do_pset = pset_fast;
|
do_pset = pset_fast;
|
||||||
ds::pen_color = 6;
|
ds::pen_color = 6;
|
||||||
ds::back_color = 0;
|
ds::back_color = 0;
|
||||||
@@ -168,17 +225,23 @@ void reinit() {
|
|||||||
ds::trans=0;
|
ds::trans=0;
|
||||||
ds::fill_pattern = 0b1111111111111111;
|
ds::fill_pattern = 0b1111111111111111;
|
||||||
ds::fill_trans = false;
|
ds::fill_trans = false;
|
||||||
for (int i=1; i<MAX_TEXTURES; ++i) {
|
for (unsigned int i=1; i<MAX_SURFACES; ++i) freesurf(i);
|
||||||
|
/*{
|
||||||
if (surfaces[i].p != NULL) free(surfaces[i].p);
|
if (surfaces[i].p != NULL) free(surfaces[i].p);
|
||||||
surfaces[i].p = NULL;
|
surfaces[i].p = NULL;
|
||||||
|
if (surfaces[i].name != NULL) free(surfaces[i].name);
|
||||||
|
surfaces[i].name = NULL;
|
||||||
}
|
}
|
||||||
|
surfaces.clear();*/
|
||||||
|
dest_surface = screen_surface;
|
||||||
|
|
||||||
for (int i=0;i<256;++i) ds::draw_palette[i]=i;
|
for (int i=0;i<256;++i) ds::draw_palette[i]=i;
|
||||||
if (file!=NULL) fclose(file);
|
if (file!=NULL) fclose(file);
|
||||||
file = NULL;
|
file = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initaudio() {
|
void initaudio() {
|
||||||
JA_Init(48000, AUDIO_S16, 1);
|
JA_Init(48000, SDL_AUDIO_S16, 1);
|
||||||
for (int i=0;i<MAX_SOUNDS;++i) sounds[i] = NULL;
|
for (int i=0;i<MAX_SOUNDS;++i) sounds[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,42 +260,69 @@ int scrh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t newsurf(int w, int h) {
|
uint8_t newsurf(int w, int h) {
|
||||||
int i = 0;
|
unsigned int i = 0;
|
||||||
while (i<MAX_TEXTURES && surfaces[i].p != NULL) ++i;
|
while (i<MAX_SURFACES && surfaces[i].p != NULL) ++i;
|
||||||
//[TODO] Gestionar el cas en que no queden surfaces lliures
|
if (i==MAX_SURFACES) return 255;
|
||||||
|
surfaces[i].name = nullptr;
|
||||||
surfaces[i].w = w;
|
surfaces[i].w = w;
|
||||||
surfaces[i].h = h;
|
surfaces[i].h = h;
|
||||||
surfaces[i].size = w*h;
|
surfaces[i].size = w*h;
|
||||||
surfaces[i].p = (uint8_t*)calloc(surfaces[i].size,1);
|
surfaces[i].p = (uint8_t*)calloc(surfaces[i].size,1);
|
||||||
|
log_msg(LOG_INFO, "Surface %i creada.\n", i);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t loadsurf(const char* filename) {
|
uint8_t loadsurf(const char* filename, const bool external) {
|
||||||
int i = 0;
|
// Si el gif ja s'ha carregat en una textura, tornem eixa textura
|
||||||
while (i<MAX_TEXTURES && surfaces[i].p != NULL) ++i;
|
for (unsigned int i=0; i<MAX_SURFACES; ++i)
|
||||||
//[TODO] Gestionar el cas en que no queden surfaces lliures
|
if (surfaces[i].name && strcmp(surfaces[i].name, filename)==0) {
|
||||||
|
log_msg(LOG_INFO, "Carrega de '%s' abortada: Reusant: %i.\n", filename, i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Agafar la pròxima textura lliure
|
||||||
|
unsigned int i = 0;
|
||||||
|
while (i<MAX_SURFACES && surfaces[i].p != NULL) ++i;
|
||||||
|
if (i==MAX_SURFACES) return 255;
|
||||||
|
|
||||||
|
// Carregar l'arxiu de disc
|
||||||
int size;
|
int size;
|
||||||
uint8_t *buffer = (uint8_t*)file_getfilebuffer(filename, size);
|
uint8_t *buffer;
|
||||||
|
if (external) {
|
||||||
|
buffer = (uint8_t*)file_getfilebufferex(filename, size);
|
||||||
|
} else {
|
||||||
|
buffer = (uint8_t*)file_getfilebuffer(filename, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si no s'ha pogut, petar
|
||||||
|
if (!buffer) {
|
||||||
|
log_msg(LOG_FAIL, "Error al intentar obrir l'arxiu '%s'\n", filename);
|
||||||
|
exit(-1);
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
|
||||||
surfaces[i].p = LoadGif(buffer, &surfaces[i].w, &surfaces[i].h);
|
surfaces[i].p = LoadGif(buffer, &surfaces[i].w, &surfaces[i].h);
|
||||||
surfaces[i].size = surfaces[i].w*surfaces[i].h;
|
surfaces[i].size = surfaces[i].w*surfaces[i].h;
|
||||||
|
surfaces[i].name = (char*)malloc(strlen(filename)+1);
|
||||||
|
strcpy(surfaces[i].name, filename);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
|
log_msg(LOG_INFO, "Arxiu '%s' carregat en surface: %i.\n", filename, i);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void savesurf(uint8_t surface, const char* filename, uint8_t *pal, uint8_t colors)
|
void savesurf(uint8_t surface, const char* filename, uint8_t *pal, uint8_t colors)
|
||||||
{
|
{
|
||||||
uint8_t depth=colors;
|
gif::write_gif(filename, surfaces[surface].p, surfaces[surface].w, surfaces[surface].h, pal, colors);
|
||||||
do { depth = depth >> 1; } while (depth!=0);
|
|
||||||
gif::gif_t *file = gif::create(filename, surfaces[surface].w, surfaces[surface].h, pal, (pal?depth:0), -1, -1);
|
|
||||||
memcpy(file->frame, surfaces[surface].p, surfaces[surface].w*surfaces[surface].h);
|
|
||||||
gif::addFrame(file, 0);
|
|
||||||
gif::close(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void freesurf(uint8_t surface) {
|
void freesurf(uint8_t surface) {
|
||||||
if (surfaces[surface].p != NULL) free(surfaces[surface].p);
|
if (surfaces[surface].name != NULL) free(surfaces[surface].name);
|
||||||
|
surfaces[surface].name = NULL;
|
||||||
|
if (surfaces[surface].p != NULL) {
|
||||||
|
free(surfaces[surface].p);
|
||||||
|
log_msg(LOG_INFO, "Surface %i alliberada.\n", surface);
|
||||||
|
}
|
||||||
surfaces[surface].p = NULL;
|
surfaces[surface].p = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +336,10 @@ int surfh(uint8_t surface) {
|
|||||||
|
|
||||||
void recalculate_clip()
|
void recalculate_clip()
|
||||||
{
|
{
|
||||||
ds::clip[0] = ds::clp[0]; ds::clip[1] = ds::clp[1]; ds::clip[2] = ds::clp[2]-ds::clp[0]-1; ds::clip[3] = ds::clp[3]-ds::clp[1]-1;
|
ds::clip[0] = ds::clp[0];
|
||||||
|
ds::clip[1] = ds::clp[1];
|
||||||
|
ds::clip[2] = ds::clp[2]+ds::clp[0]-1;
|
||||||
|
ds::clip[3] = ds::clp[3]+ds::clp[1]-1;
|
||||||
if (ds::clip[0]<0) ds::clip[0]=0;
|
if (ds::clip[0]<0) ds::clip[0]=0;
|
||||||
if (ds::clip[1]<0) ds::clip[1]=0;
|
if (ds::clip[1]<0) ds::clip[1]=0;
|
||||||
if (ds::clip[2]>=dest_surface->w) ds::clip[2]=dest_surface->w-1;
|
if (ds::clip[2]>=dest_surface->w) ds::clip[2]=dest_surface->w-1;
|
||||||
@@ -266,24 +359,64 @@ void setmap(uint8_t surface) {
|
|||||||
map_surface = &surfaces[surface];
|
map_surface = &surfaces[surface];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getmap()
|
uint8_t getdest()
|
||||||
{
|
{
|
||||||
for (int i=0; i<MAX_TEXTURES; ++i) if (map_surface == &surfaces[i]) return i;
|
for (unsigned int i=0; i<MAX_SURFACES; ++i) if (dest_surface == &surfaces[i]) return i;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t getsource()
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<MAX_SURFACES; ++i) if (source_surface == &surfaces[i]) return i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getmap()
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<MAX_SURFACES; ++i) if (map_surface == &surfaces[i]) return i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shader_init(const char* vshader, const char* fshader)
|
||||||
|
{
|
||||||
|
int filesize;
|
||||||
|
char *vshaderfile = file_getfilebuffer(vshader, filesize, true);
|
||||||
|
|
||||||
|
char *fshaderfile = nullptr;
|
||||||
|
if (fshader) { fshaderfile = file_getfilebuffer(fshader, filesize, true); }
|
||||||
|
shader::init(mini_win, mini_shadertex, vshaderfile, fshaderfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shader_enable() { shader::enable(); }
|
||||||
|
void shader_disable() { shader::disable(); }
|
||||||
|
|
||||||
void createDisplay() {
|
void createDisplay() {
|
||||||
if (screen_zoom <= 0) screen_zoom = 1;
|
if (screen_zoom <= 0) screen_zoom = 1;
|
||||||
while (screen_width*screen_zoom > desktop_width || screen_height*screen_zoom > desktop_height) screen_zoom--;
|
while (screen_width*screen_zoom > desktop_width || screen_height*screen_zoom > desktop_height) screen_zoom--;
|
||||||
|
|
||||||
mini_win = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width*screen_zoom, screen_height*screen_zoom, screen_fullscreen?SDL_WINDOW_FULLSCREEN_DESKTOP:SDL_WINDOW_RESIZABLE);
|
mini_win = SDL_CreateWindow(window_title, screen_width*screen_zoom, screen_height*screen_zoom, SDL_WINDOW_OPENGL|(screen_fullscreen?SDL_WINDOW_FULLSCREEN:0));
|
||||||
windowID = SDL_GetWindowID(mini_win);
|
windowID = SDL_GetWindowID(mini_win);
|
||||||
mini_ren = SDL_CreateRenderer(mini_win, -1, 0);
|
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
|
||||||
|
mini_ren = SDL_CreateRenderer(mini_win, NULL);
|
||||||
//SDL_CreateWindowAndRenderer(512,512,0,&mini_win,&mini_ren);
|
//SDL_CreateWindowAndRenderer(512,512,0,&mini_win,&mini_ren);
|
||||||
SDL_RenderSetLogicalSize(mini_ren, screen_width, screen_height);
|
//SDL_SetRenderLogicalPresentation(mini_ren, screen_width, screen_height);
|
||||||
SDL_ShowCursor(screen_cursor?SDL_ENABLE:SDL_DISABLE);
|
if (screen_cursor) SDL_ShowCursor(); else SDL_HideCursor();
|
||||||
mini_bak = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height);
|
mini_bak = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height);
|
||||||
|
SDL_SetTextureScaleMode(mini_bak, SDL_SCALEMODE_NEAREST);
|
||||||
|
SDL_PropertiesID props = SDL_GetTextureProperties(mini_bak);
|
||||||
|
int real_pixelformat = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_FORMAT_NUMBER, -1);
|
||||||
|
if (real_pixelformat != SDL_PIXELFORMAT_ARGB8888) {
|
||||||
|
log_msg(LOG_FAIL, "Pixelformat incorrecte: %i\n", real_pixelformat);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
mini_shadertex = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, screen_width*screen_zoom, screen_height*screen_zoom);
|
||||||
|
SDL_SetTextureScaleMode(mini_shadertex, SDL_SCALEMODE_NEAREST);
|
||||||
|
|
||||||
|
//int filesize;
|
||||||
|
//char *shaderfile = file_getfilebuffer("lynx.glsl", filesize);
|
||||||
|
shader::init(mini_win, mini_shadertex, nullptr);
|
||||||
//SDL_GetWindowPosition(mini_win, &windowpos_x, &windowpos_y);
|
//SDL_GetWindowPosition(mini_win, &windowpos_x, &windowpos_y);
|
||||||
|
log_msg(LOG_OK, "Graphics subsystem initialized\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroyDisplay() {
|
void destroyDisplay() {
|
||||||
@@ -293,13 +426,15 @@ void destroyDisplay() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void initGamePad() {
|
void initGamePad() {
|
||||||
const int num_joysticks = SDL_NumJoysticks();
|
int num_joysticks;
|
||||||
if (num_joysticks>=1) {
|
SDL_JoystickID *joysticks = SDL_GetJoysticks(&num_joysticks);
|
||||||
|
if (joysticks) {
|
||||||
for (int i=0; i<num_joysticks; ++i) {
|
for (int i=0; i<num_joysticks; ++i) {
|
||||||
if (SDL_IsGameController(i)) {
|
if (SDL_IsGamepad(joysticks[i])) {
|
||||||
gamepad = SDL_GameControllerOpen(i);
|
gamepad = SDL_OpenGamepad(joysticks[i]);
|
||||||
if (SDL_GameControllerGetAttached(gamepad) == SDL_TRUE) {
|
if (SDL_GamepadConnected(gamepad)) {
|
||||||
SDL_GameControllerEventState(SDL_ENABLE);
|
SDL_SetGamepadEventsEnabled(true);
|
||||||
|
log_msg(LOG_OK, "Gamepad found and initialized");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,12 +445,22 @@ void initGamePad() {
|
|||||||
int main(int argc,char*argv[]){
|
int main(int argc,char*argv[]){
|
||||||
|
|
||||||
#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
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
log_msg(LOG_UNSALTED, "MINI v%s\n",MINI_VERSION);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (argc>1)
|
if (argc>1)
|
||||||
{
|
{
|
||||||
if (strstr(argv[1], ".lua")!=nullptr) {
|
if (argv[1][0]=='-' && argv[1][1]=='-') {
|
||||||
|
const char *command = &argv[1][2];
|
||||||
|
if (strcmp(command, "new")==0) {
|
||||||
|
createNewProject();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
} else if (strstr(argv[1], ".lua")!=nullptr) {
|
||||||
file_setresourcefolder("./");
|
file_setresourcefolder("./");
|
||||||
file_setsource(SOURCE_FOLDER);
|
file_setsource(SOURCE_FOLDER);
|
||||||
strcpy(main_lua_file, argv[1]);
|
strcpy(main_lua_file, argv[1]);
|
||||||
@@ -328,6 +473,7 @@ int main(int argc,char*argv[]){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//screen_surface = &surfaces.emplace_back();
|
||||||
while (!should_quit) {
|
while (!should_quit) {
|
||||||
should_exit=false;
|
should_exit=false;
|
||||||
|
|
||||||
@@ -355,20 +501,19 @@ int main(int argc,char*argv[]){
|
|||||||
if (fullscreen) screen_fullscreen=strcmp(fullscreen, "true")==0?true:false;
|
if (fullscreen) screen_fullscreen=strcmp(fullscreen, "true")==0?true:false;
|
||||||
const char *cursor = file_getconfigvalue("cursor");
|
const char *cursor = file_getconfigvalue("cursor");
|
||||||
if (cursor) screen_cursor=strcmp(cursor, "true")?true:false;
|
if (cursor) screen_cursor=strcmp(cursor, "true")?true:false;
|
||||||
|
const char *music_enabled = file_getconfigvalue("music");
|
||||||
|
if (music_enabled) JA_EnableMusic(strcmp(music_enabled, "true")==0?true:false);
|
||||||
|
const char *sound_enabled = file_getconfigvalue("sound");
|
||||||
|
if (sound_enabled) JA_EnableSound(strcmp(sound_enabled, "true")==0?true:false);
|
||||||
}
|
}
|
||||||
|
|
||||||
setdest(newsurf(screen_width, screen_height));
|
setdest(newsurf(screen_width, screen_height));
|
||||||
|
|
||||||
SDL_Init(SDL_INIT_EVERYTHING);
|
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD);
|
||||||
|
|
||||||
SDL_DisplayMode dm;
|
const SDL_DisplayMode *dm = SDL_GetDesktopDisplayMode(SDL_GetPrimaryDisplay());
|
||||||
if (SDL_GetDesktopDisplayMode(0, &dm) != 0)
|
desktop_width = dm->w;
|
||||||
{
|
desktop_height = dm->h;
|
||||||
SDL_Log("SDL_GetDesktopDisplayMode failed: %s", SDL_GetError());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
desktop_width = dm.w;
|
|
||||||
desktop_height = dm.h;
|
|
||||||
|
|
||||||
createDisplay();
|
createDisplay();
|
||||||
|
|
||||||
@@ -380,23 +525,22 @@ int main(int argc,char*argv[]){
|
|||||||
|
|
||||||
reinit();
|
reinit();
|
||||||
initaudio();
|
initaudio();
|
||||||
#ifdef DEBUG
|
|
||||||
debug("MINI v%s\n",MINI_VERSION);
|
|
||||||
#endif
|
|
||||||
lua_init(main_lua_file);
|
lua_init(main_lua_file);
|
||||||
lua_call_init();
|
lua_call_init();
|
||||||
|
|
||||||
Uint32 dt=SDL_GetTicks();
|
Uint32 dt=SDL_GetTicks();
|
||||||
key_just_pressed = 0;
|
key_just_pressed = 0;
|
||||||
pad_just_pressed = SDL_CONTROLLER_BUTTON_INVALID;
|
pad_just_pressed = SDL_GAMEPAD_BUTTON_INVALID;
|
||||||
mouse_just_pressed = 0;
|
mouse_just_pressed = 0;
|
||||||
|
mouse_wheel = 0;
|
||||||
|
double_click = false;
|
||||||
while(!should_exit) {
|
while(!should_exit) {
|
||||||
mouse_wheel = 0;
|
|
||||||
if (update_mode==UPDATE_WAIT) SDL_WaitEvent(NULL);
|
if (update_mode==UPDATE_WAIT) SDL_WaitEvent(NULL);
|
||||||
else if (update_mode==UPDATE_TIMEOUT) SDL_WaitEventTimeout(NULL, timeout);
|
else if (update_mode==UPDATE_TIMEOUT) SDL_WaitEventTimeout(NULL, timeout);
|
||||||
while(SDL_PollEvent(&mini_eve)) {
|
while(SDL_PollEvent(&mini_eve)) {
|
||||||
if (mini_eve.type == SDL_QUIT) { should_exit=true; should_quit=true; break; }
|
if (mini_eve.type == SDL_EVENT_QUIT) { should_exit=true; should_quit=true; break; }
|
||||||
if (mini_eve.type == SDL_KEYDOWN) {
|
if (mini_eve.type == SDL_EVENT_KEY_DOWN) {
|
||||||
/*
|
/*
|
||||||
if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F2) {
|
if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F2) {
|
||||||
screen_zoom+=2; if (screen_zoom>=10) screen_zoom=2;
|
screen_zoom+=2; if (screen_zoom>=10) screen_zoom=2;
|
||||||
@@ -412,7 +556,7 @@ int main(int argc,char*argv[]){
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F12) {
|
if (mini_eve.key.scancode == SDL_SCANCODE_F12) {
|
||||||
if (lua_is_playing()) {
|
if (lua_is_playing()) {
|
||||||
lua_quit();
|
lua_quit();
|
||||||
quitaudio();
|
quitaudio();
|
||||||
@@ -420,23 +564,30 @@ int main(int argc,char*argv[]){
|
|||||||
} else {
|
} else {
|
||||||
should_exit=true;
|
should_exit=true;
|
||||||
}
|
}
|
||||||
} else if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F5) {
|
} else if (mini_eve.key.scancode == SDL_SCANCODE_F5) {
|
||||||
should_exit=true;
|
should_exit=true;
|
||||||
} else {
|
} else {
|
||||||
key_just_pressed = mini_eve.key.keysym.scancode;
|
key_just_pressed = mini_eve.key.scancode;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
key_just_pressed = mini_eve.key.keysym.scancode;
|
key_just_pressed = mini_eve.key.scancode;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (mini_eve.type == SDL_MOUSEBUTTONUP) {
|
if (mini_eve.type == SDL_EVENT_MOUSE_BUTTON_UP) {
|
||||||
mouse_just_pressed = mini_eve.button.button;
|
if (mouse_discard)
|
||||||
|
mouse_discard = false;
|
||||||
|
else
|
||||||
|
if (mini_eve.button.clicks==2 && mini_eve.button.button==SDL_BUTTON_LEFT) {
|
||||||
|
double_click = true;
|
||||||
|
} else {
|
||||||
|
mouse_just_pressed = mini_eve.button.button;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (mini_eve.type == SDL_MOUSEWHEEL) {
|
if (mini_eve.type == SDL_EVENT_MOUSE_WHEEL) {
|
||||||
mouse_wheel = mini_eve.wheel.y;
|
mouse_wheel = mini_eve.wheel.y;
|
||||||
}
|
}
|
||||||
if (mini_eve.type == SDL_CONTROLLERBUTTONDOWN) {
|
if (mini_eve.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
|
||||||
pad_just_pressed = mini_eve.cbutton.button;
|
pad_just_pressed = mini_eve.gbutton.button;
|
||||||
}
|
}
|
||||||
/*if ( (mini_eve.type == SDL_WINDOWEVENT) &&
|
/*if ( (mini_eve.type == SDL_WINDOWEVENT) &&
|
||||||
(mini_eve.window.windowID == windowID) &&
|
(mini_eve.window.windowID == windowID) &&
|
||||||
@@ -447,12 +598,12 @@ int main(int argc,char*argv[]){
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
keys = SDL_GetKeyboardState(NULL);
|
keys = SDL_GetKeyboardState(NULL);
|
||||||
int real_mouse_x, real_mouse_y;
|
float real_mouse_x, real_mouse_y;
|
||||||
mouse_buttons = SDL_GetMouseState(&real_mouse_x, &real_mouse_y);
|
mouse_buttons = SDL_GetMouseState(&real_mouse_x, &real_mouse_y);
|
||||||
float mx, my;
|
float mx, my;
|
||||||
SDL_RenderWindowToLogical(mini_ren, real_mouse_x, real_mouse_y, &mx, &my);
|
SDL_RenderCoordinatesFromWindow(mini_ren, real_mouse_x, real_mouse_y, &mx, &my);
|
||||||
mouse_x = int(mx);
|
mouse_x = int(mx/screen_zoom);
|
||||||
mouse_y = int(my);
|
mouse_y = int(my/screen_zoom);
|
||||||
//mouse_x /= screen_zoom; mouse_y /= screen_zoom;
|
//mouse_x /= screen_zoom; mouse_y /= screen_zoom;
|
||||||
|
|
||||||
if (SDL_GetTicks()-dt>13) {
|
if (SDL_GetTicks()-dt>13) {
|
||||||
@@ -466,22 +617,35 @@ int main(int argc,char*argv[]){
|
|||||||
if (beats>0)beats--;
|
if (beats>0)beats--;
|
||||||
key_just_pressed = 0;
|
key_just_pressed = 0;
|
||||||
mouse_just_pressed = 0;
|
mouse_just_pressed = 0;
|
||||||
pad_just_pressed = SDL_CONTROLLER_BUTTON_INVALID;
|
double_click = false;
|
||||||
|
mouse_wheel = 0;
|
||||||
|
pad_just_pressed = SDL_GAMEPAD_BUTTON_INVALID;
|
||||||
}
|
}
|
||||||
|
SDL_SetRenderTarget(mini_ren, mini_shadertex);
|
||||||
SDL_SetRenderDrawColor(mini_ren, 0, 0, 0, 255);
|
SDL_SetRenderDrawColor(mini_ren, 0, 0, 0, 255);
|
||||||
SDL_RenderClear(mini_ren);
|
SDL_RenderClear(mini_ren);
|
||||||
SDL_LockTexture(mini_bak, NULL, (void**)&pixels, &pitch);
|
SDL_LockTexture(mini_bak, NULL, (void**)&pixels, &pitch);
|
||||||
for (uint32_t i=0;i<screen_surface->size;++i) pixels[i] = palette[screen_surface->p[i]];
|
for (uint32_t i=0;i<screen_surface->size;++i) pixels[i] = palette[screen_surface->p[i]];
|
||||||
SDL_UnlockTexture(mini_bak);
|
SDL_UnlockTexture(mini_bak);
|
||||||
SDL_RenderCopy(mini_ren, mini_bak, NULL, NULL);
|
SDL_RenderTexture(mini_ren, mini_bak, NULL, NULL); //NEW
|
||||||
SDL_RenderPresent(mini_ren);
|
|
||||||
|
shader::render();
|
||||||
|
//SDL_RenderTexture(mini_ren, mini_bak, NULL, NULL);
|
||||||
|
//SDL_RenderPresent(mini_ren);
|
||||||
|
|
||||||
|
fps_counter++;
|
||||||
|
if (SDL_GetTicks()>=(fps_timer+1000)) {
|
||||||
|
fps = fps_counter;
|
||||||
|
fps_counter=0;
|
||||||
|
fps_timer = SDL_GetTicks();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lua_quit();
|
lua_quit();
|
||||||
quitaudio();
|
quitaudio();
|
||||||
|
|
||||||
//Mix_Quit();
|
//Mix_Quit();
|
||||||
|
|
||||||
for (int i=0;i<MAX_TEXTURES;++i) freesurf(i);
|
for (unsigned int i=0;i<MAX_SURFACES;++i) freesurf(i);
|
||||||
dest_surface = source_surface = map_surface = NULL;
|
dest_surface = source_surface = map_surface = NULL;
|
||||||
destroyDisplay();
|
destroyDisplay();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
@@ -491,7 +655,7 @@ int main(int argc,char*argv[]){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void simple_pset(int x, int y, uint8_t color) {
|
void simple_pset(int x, int y, uint8_t color) {
|
||||||
x -= ds::origin[0]; y -= ds::origin[1];
|
x += ds::origin[0]; y += ds::origin[1];
|
||||||
if (x < ds::clip[0] || x > ds::clip[2] || y < ds::clip[1] || y > ds::clip[3]) return;
|
if (x < ds::clip[0] || x > ds::clip[2] || y < ds::clip[1] || y > ds::clip[3]) return;
|
||||||
if (x < 0 || x >= dest_surface->w || y < 0 || y >= dest_surface->h) return;
|
if (x < 0 || x >= dest_surface->w || y < 0 || y >= dest_surface->h) return;
|
||||||
DEST(x, y) = color;
|
DEST(x, y) = color;
|
||||||
@@ -541,11 +705,12 @@ uint32_t *loadpal(const char* filename, uint16_t *palsize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setpal(uint32_t *pal) {
|
void setpal(uint32_t *pal) {
|
||||||
memcpy(palette, pal, 1024);
|
for (int i=0; i<256; ++i) palette[i] = pal[i] | 0xff000000;
|
||||||
|
//memcpy(palette, pal, 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setcolor(uint8_t index, uint32_t color) {
|
void setcolor(uint8_t index, uint32_t color) {
|
||||||
palette[index] = color;
|
palette[index] = color | 0xff000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getcolor(uint8_t index) {
|
uint32_t getcolor(uint8_t index) {
|
||||||
@@ -561,7 +726,7 @@ uint8_t gettrans() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void subpal(uint8_t index, uint8_t color) {
|
void subpal(uint8_t index, uint8_t color) {
|
||||||
ds::draw_palette[index] = color;
|
ds::draw_palette[SDL_clamp(index,0,255)] = SDL_clamp(color,0,255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_subpal() {
|
void reset_subpal() {
|
||||||
@@ -595,7 +760,7 @@ void palt(uint8_t col, bool t) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void pset(int x, int y) {
|
void pset(int x, int y) {
|
||||||
x -= ds::origin[0]; y -= ds::origin[1];
|
x += ds::origin[0]; y += ds::origin[1];
|
||||||
if (x < ds::clip[0] || x > ds::clip[2] || y < ds::clip[1] || y > ds::clip[3]) return;
|
if (x < ds::clip[0] || x > ds::clip[2] || y < ds::clip[1] || y > ds::clip[3]) return;
|
||||||
do_pset(x,y);
|
do_pset(x,y);
|
||||||
}
|
}
|
||||||
@@ -606,7 +771,7 @@ void pset(int x, int y, uint8_t color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t pget(int x, int y) {
|
uint8_t pget(int x, int y) {
|
||||||
x -= ds::origin[0]; y -= ds::origin[1];
|
x += ds::origin[0]; y += ds::origin[1];
|
||||||
//if (x < 0 || x > (dest_surface->w-1) || y < 0 || y > (dest_surface->h-1)) return 0;
|
//if (x < 0 || x > (dest_surface->w-1) || y < 0 || y > (dest_surface->h-1)) return 0;
|
||||||
if (x < ds::clip[0] || x > ds::clip[2] || y < ds::clip[1] || y > ds::clip[3]) return 0;
|
if (x < ds::clip[0] || x > ds::clip[2] || y < ds::clip[1] || y > ds::clip[3]) return 0;
|
||||||
return DEST(x, y);
|
return DEST(x, y);
|
||||||
@@ -704,7 +869,6 @@ void rectfill(int x, int y, int w, int h, uint8_t color) {
|
|||||||
void fillp(uint16_t pat, bool transparent) {
|
void fillp(uint16_t pat, bool transparent) {
|
||||||
ds::fill_trans = true; //transparent;
|
ds::fill_trans = true; //transparent;
|
||||||
ds::fill_pattern = pat;
|
ds::fill_pattern = pat;
|
||||||
do_pset=(pat==0xffff?pset_fast:pset_pattern);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_symbol(char sym, int x, int y) {
|
void print_symbol(char sym, int x, int y) {
|
||||||
@@ -833,6 +997,77 @@ void circfill(int x, int y, uint8_t r, uint8_t color) {
|
|||||||
circfill(x, y, r);
|
circfill(x, y, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void roundrect(int x, int y, int w, int h, uint8_t r) {
|
||||||
|
int xi=0, yi=r;
|
||||||
|
int d=3-2*r;
|
||||||
|
|
||||||
|
int xf = w+x-1;
|
||||||
|
int yf = h+y-1;
|
||||||
|
int x1 = x+r, y1 = y+r;
|
||||||
|
int x2 = xf-r, y2 = yf-r;
|
||||||
|
hline(x1, y, x2);
|
||||||
|
hline(x1, yf, x2);
|
||||||
|
vline(x, y1, y2);
|
||||||
|
vline(xf, y1, y2);
|
||||||
|
|
||||||
|
while (yi>=xi++) {
|
||||||
|
d += d>0 ? 4*(xi-yi--)+10 : 4*xi+6;
|
||||||
|
pset(x2+xi, y2+yi);
|
||||||
|
pset(x1-xi, y2+yi);
|
||||||
|
pset(x2+xi, y1-yi);
|
||||||
|
pset(x1-xi, y1-yi);
|
||||||
|
pset(x2+yi, y2+xi);
|
||||||
|
pset(x1-yi, y2+xi);
|
||||||
|
pset(x2+yi, y1-xi);
|
||||||
|
pset(x1-yi, y1-xi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void roundrect(int x, int y, int w, int h, uint8_t r, uint8_t color) {
|
||||||
|
ds::pen_color=color;
|
||||||
|
roundrect(x, y, w, h, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void roundrectfill(int x, int y, int w, int h, uint8_t r) {
|
||||||
|
int xi=0, yi=r;
|
||||||
|
int d=3-2*r;
|
||||||
|
|
||||||
|
int xf = w+x-1;
|
||||||
|
int yf = h+y-1;
|
||||||
|
int x1 = x+r, y1 = y+r;
|
||||||
|
int x2 = xf-r, y2 = yf-r;
|
||||||
|
for (int i=y1; i<=y2; ++i) hline(x, i, xf);
|
||||||
|
|
||||||
|
while (yi>=xi++) {
|
||||||
|
d += d>0 ? 4*(xi-yi--)+10 : 4*xi+6;
|
||||||
|
hline(x1-xi, y2+yi, x2+xi);
|
||||||
|
hline(x1-xi, y1-yi, x2+xi);
|
||||||
|
hline(x1-yi, y2+xi, x2+yi);
|
||||||
|
hline(x1-yi, y1-xi, x2+yi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void roundrectfill(int x, int y, int w, int h, uint8_t r, uint8_t color) {
|
||||||
|
ds::pen_color=color;
|
||||||
|
roundrectfill(x, y, w, h, r);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void roundrectfill(int x, int y, uint8_t r) {
|
||||||
|
int xi=0, yi=r;
|
||||||
|
int d=3-2*r;
|
||||||
|
(*fun_ptr)(x, y, xi, yi);
|
||||||
|
while (yi>=xi++) {
|
||||||
|
d += d>0 ? 4*(xi-yi--)+10 : 4*xi+6;
|
||||||
|
(*fun_ptr)(x, y, xi, yi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void roundrectfill(int x, int y, uint8_t r, uint8_t color) {
|
||||||
|
ds::pen_color=color;
|
||||||
|
roundrectfill(x, y, r);
|
||||||
|
}
|
||||||
|
*/
|
||||||
void _drawoval(int xc, int yc, int x, int y, float xf, float yf) {
|
void _drawoval(int xc, int yc, int x, int y, float xf, float yf) {
|
||||||
pset((xc+x)*xf, (yc+y)*yf);
|
pset((xc+x)*xf, (yc+y)*yf);
|
||||||
pset((xc-x)*xf, (yc+y)*yf);
|
pset((xc-x)*xf, (yc+y)*yf);
|
||||||
@@ -887,11 +1122,13 @@ void ovalfill(int x0, int y0, int x1, int y1, uint8_t color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t sget(int x, int y) {
|
uint8_t sget(int x, int y) {
|
||||||
|
if (!source_surface) return 0;
|
||||||
if (x < 0 || x > (source_surface->w-1) || y < 0 || y > (source_surface->h-1)) return 0;
|
if (x < 0 || x > (source_surface->w-1) || y < 0 || y > (source_surface->h-1)) return 0;
|
||||||
return SOURCE(x, y);
|
return SOURCE(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sset(int x, int y) {
|
void sset(int x, int y) {
|
||||||
|
if (!source_surface) return;
|
||||||
if (x < 0 || x > (source_surface->w-1) || y < 0 || y > (source_surface->h-1)) return;
|
if (x < 0 || x > (source_surface->w-1) || y < 0 || y > (source_surface->h-1)) return;
|
||||||
SOURCE(x, y) = ds::pen_color;
|
SOURCE(x, y) = ds::pen_color;
|
||||||
}
|
}
|
||||||
@@ -902,6 +1139,7 @@ void sset(int x, int y, uint8_t color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void spr(uint8_t n, int x, int y, float w, float h, bool flip_x, bool flip_y) {
|
void spr(uint8_t n, int x, int y, float w, float h, bool flip_x, bool flip_y) {
|
||||||
|
if (!source_surface) return;
|
||||||
int tx = (n%(source_surface->w >> 3))<<3;
|
int tx = (n%(source_surface->w >> 3))<<3;
|
||||||
int ty = (n/(source_surface->w >> 3))<<3;
|
int ty = (n/(source_surface->w >> 3))<<3;
|
||||||
int tw = w*8 - 1;
|
int tw = w*8 - 1;
|
||||||
@@ -1040,12 +1278,12 @@ void mset(int celx, int cely, uint8_t snum) {
|
|||||||
|
|
||||||
void map() { //int celx, int cely, int sx, int sy, uint8_t celw, uint8_t celh, uint8_t layer) {
|
void map() { //int celx, int cely, int sx, int sy, uint8_t celw, uint8_t celh, uint8_t layer) {
|
||||||
if (map_surface==NULL) return;
|
if (map_surface==NULL) return;
|
||||||
uint8_t celw = map_surface->w;// >> 3;
|
int celw = map_surface->w;// >> 3;
|
||||||
uint8_t celh = map_surface->h;// >> 3;
|
int celh = map_surface->h;// >> 3;
|
||||||
int celx = 0;
|
int celx = 0;
|
||||||
int cely = 0;
|
int cely = 0;
|
||||||
//if (celw <= 0 || celh <= 0 || celw >= TILES_WIDTH || celh >= TILES_HEIGHT) return;
|
//if (celw <= 0 || celh <= 0 || celw >= TILES_WIDTH || celh >= TILES_HEIGHT) return;
|
||||||
int sx = -ds::origin[0]; int sy = -ds::origin[1];
|
int sx = ds::origin[0]; int sy = ds::origin[1];
|
||||||
if (sx+celw*8 < ds::clip[0] || sx > ds::clip[2] || sy+celh*8 < ds::clip[1] || sy > ds::clip[3]) return;
|
if (sx+celw*8 < ds::clip[0] || sx > ds::clip[2] || sy+celh*8 < ds::clip[1] || sy > ds::clip[3]) return;
|
||||||
if (sx<0) {
|
if (sx<0) {
|
||||||
int diff = -sx/8;
|
int diff = -sx/8;
|
||||||
@@ -1059,10 +1297,15 @@ void map() { //int celx, int cely, int sx, int sy, uint8_t celw, uint8_t celh, u
|
|||||||
celh -= diff;
|
celh -= diff;
|
||||||
sy += diff*8;
|
sy += diff*8;
|
||||||
}
|
}
|
||||||
sx += ds::origin[0]; sy += ds::origin[1];
|
sx -= ds::origin[0]; sy -= ds::origin[1];
|
||||||
for (int y=0; y<celh; ++y) {
|
for (int y=0; y<celh; ++y) {
|
||||||
for (int x=0; x<celw; ++x) {
|
for (int x=0; x<celw; ++x) {
|
||||||
spr(mget(celx+x, cely+y), sx+x*8, sy+y*8);
|
const uint8_t tile = mget(celx+x, cely+y);
|
||||||
|
if (tile==0) continue;
|
||||||
|
const int fx = sx+(x*8)+ds::origin[0];
|
||||||
|
const int fy = sy+(y*8)+ds::origin[1];
|
||||||
|
if ( (fx+8<ds::clip[0]) || (fy+8<ds::clip[1]) || (fx>ds::clip[2]) || (fy>ds::clip[3]) ) continue;
|
||||||
|
spr(tile, sx+x*8, sy+y*8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1093,7 +1336,7 @@ bool anykey() {
|
|||||||
|
|
||||||
bool pad(int8_t i) {
|
bool pad(int8_t i) {
|
||||||
if (!gamepad) return false;
|
if (!gamepad) return false;
|
||||||
return SDL_GameControllerGetButton(gamepad, SDL_GameControllerButton(i)) == 1;
|
return SDL_GetGamepadButton(gamepad, SDL_GamepadButton(i)) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool padp(int8_t i) {
|
bool padp(int8_t i) {
|
||||||
@@ -1110,11 +1353,11 @@ int wpad() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mousex() {
|
int mousex() {
|
||||||
return mouse_x;
|
return mouse_x-ds::origin[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
int mousey() {
|
int mousey() {
|
||||||
return mouse_y;
|
return mouse_y-ds::origin[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int mwheel() {
|
int mwheel() {
|
||||||
@@ -1122,13 +1365,28 @@ int mwheel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool mbtn(uint8_t i) {
|
bool mbtn(uint8_t i) {
|
||||||
return mouse_buttons & SDL_BUTTON(i);
|
if (mouse_discard) return false;
|
||||||
|
return mouse_buttons & SDL_BUTTON_MASK(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mbtnp(uint8_t i) {
|
bool mbtnp(uint8_t i) {
|
||||||
return mouse_just_pressed == i;
|
return mouse_just_pressed == i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool doubleclick() {
|
||||||
|
return double_click;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mdiscard() {
|
||||||
|
mouse_discard = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool minside(int x, int y, int w, int h) {
|
||||||
|
const int mx = mouse_x-ds::origin[0];
|
||||||
|
const int my = mouse_y-ds::origin[1];
|
||||||
|
return (mx>=x) && (my>=y) && (mx<x+w) && (my<y+h);
|
||||||
|
}
|
||||||
|
|
||||||
float time() {
|
float time() {
|
||||||
return float(SDL_GetTicks())/1000.0f;
|
return float(SDL_GetTicks())/1000.0f;
|
||||||
}
|
}
|
||||||
@@ -1146,6 +1404,10 @@ int rnd(int x) {
|
|||||||
return rand()%x;
|
return rand()%x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getfps() {
|
||||||
|
return fps;
|
||||||
|
}
|
||||||
|
|
||||||
void playmusic(const char *filename, const int loop) {
|
void playmusic(const char *filename, const int loop) {
|
||||||
int size;
|
int size;
|
||||||
char *buffer = file_getfilebuffer(filename, size);
|
char *buffer = file_getfilebuffer(filename, size);
|
||||||
@@ -1176,6 +1438,18 @@ float musicpos()
|
|||||||
return JA_GetMusicPosition();
|
return JA_GetMusicPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void enablemusic(const bool value)
|
||||||
|
{
|
||||||
|
JA_EnableMusic(value);
|
||||||
|
file_setconfigvalue("music", value?"true":"false");
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool ismusicenabled()
|
||||||
|
{
|
||||||
|
return JA_IsMusicEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int loadsound(const char *filename) {
|
int loadsound(const char *filename) {
|
||||||
int size;
|
int size;
|
||||||
char *buffer = file_getfilebuffer(filename, size);
|
char *buffer = file_getfilebuffer(filename, size);
|
||||||
@@ -1203,6 +1477,17 @@ void stopsound(int soundchannel) {
|
|||||||
//Mix_HaltChannel(soundchannel);
|
//Mix_HaltChannel(soundchannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void enablesound(const bool value)
|
||||||
|
{
|
||||||
|
JA_EnableSound(value);
|
||||||
|
file_setconfigvalue("sound", value?"true":"false");
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool issoundenabled()
|
||||||
|
{
|
||||||
|
return JA_IsSoundEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
int getzoom() {
|
int getzoom() {
|
||||||
return screen_zoom;
|
return screen_zoom;
|
||||||
}
|
}
|
||||||
@@ -1239,7 +1524,7 @@ bool getcursor() {
|
|||||||
|
|
||||||
void setcursor(const bool value) {
|
void setcursor(const bool value) {
|
||||||
screen_cursor=value;
|
screen_cursor=value;
|
||||||
SDL_ShowCursor(screen_cursor?SDL_ENABLE:SDL_DISABLE);
|
if (screen_cursor) SDL_ShowCursor(); else SDL_HideCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* getconfig(const char* key) {
|
const char* getconfig(const char* key) {
|
||||||
@@ -1259,7 +1544,42 @@ void setupdatemode(const int value, const int t) {
|
|||||||
timeout = t;
|
timeout = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getupdatemode() {
|
||||||
|
return update_mode;
|
||||||
|
}
|
||||||
|
|
||||||
void exit() {
|
void exit() {
|
||||||
should_exit = true;
|
should_exit = true;
|
||||||
should_quit = true;
|
should_quit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createNewProject() {
|
||||||
|
if (file_createFolder("data")) {
|
||||||
|
log_msg(LOG_OK, "Directori 'data' creat\n");
|
||||||
|
} else {
|
||||||
|
log_msg(LOG_FAIL, "No s'ha pogut crear la carpeta 'data'\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *f = fopen("./data/game.ini", "w");
|
||||||
|
if (f) {
|
||||||
|
log_msg(LOG_OK, "Arxiu 'data/game.ini' creat\n");
|
||||||
|
} else {
|
||||||
|
log_msg(LOG_FAIL, "No s'ha pogut crear l'arxiu 'data/game.ini'\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
fprintf(f, "title=NEW MINI PROJECT\nconfig=newminiproject\nwidth=320\nheight=240\nzoom=2\n");
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
f = fopen("./data/main.lua", "w");
|
||||||
|
if (f) {
|
||||||
|
log_msg(LOG_OK, "Arxiu 'data/main.lua' creat\n");
|
||||||
|
} else {
|
||||||
|
log_msg(LOG_FAIL, "No s'ha pogut crear l'arxiu 'data/main.lua'\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
fprintf(f, "function mini.init()\n\nend\n\nfunction mini.update()\n surf.cls(0)\nend\n");
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
log_msg(LOG_OK, "Projecte nou creat. Ja està fet lo més dificil del jailgame!\n");
|
||||||
|
}
|
||||||
|
|||||||
35
mini.h
35
mini.h
@@ -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,14 @@ 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();
|
||||||
|
|
||||||
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);
|
||||||
@@ -142,6 +155,7 @@ uint8_t gettrans();
|
|||||||
void subpal(uint8_t index, uint8_t color);
|
void 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 +193,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);
|
||||||
|
|
||||||
@@ -215,13 +235,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 +251,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 +277,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();
|
||||||
|
|||||||
5
tools/fonted/data/game.ini
Normal file
5
tools/fonted/data/game.ini
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
title=FONTED
|
||||||
|
config=fonted
|
||||||
|
width=320
|
||||||
|
height=240
|
||||||
|
zoom=2
|
||||||
122
tools/fonted/data/main.lua
Normal file
122
tools/fonted/data/main.lua
Normal 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
|
||||||
BIN
tools/fonted/data/subatomic.gif
Normal file
BIN
tools/fonted/data/subatomic.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 540 B |
146
tools/fonted/data/ui.lua
Normal file
146
tools/fonted/data/ui.lua
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define MINI_VERSION "1.0 RC1"
|
#define MINI_VERSION "1.4.1"
|
||||||
|
|||||||
@@ -3,189 +3,184 @@
|
|||||||
---@class mini
|
---@class mini
|
||||||
mini = {}
|
mini = {}
|
||||||
|
|
||||||
---@class surface
|
---@class surf
|
||||||
surface = {}
|
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
|
---@class map
|
||||||
---@param h number
|
map = {}
|
||||||
---Create new map specifying width and height
|
|
||||||
function tilemap.new(w, h) end
|
|
||||||
|
|
||||||
---@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
|
---@class pal
|
||||||
palette = {}
|
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
|
||||||
|
|
||||||
---@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
|
||||||
|
---Reset the specified subpalette index to its default palette 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
|
---Set the specified subpalette index to the specified palette index
|
||||||
function subpalette.set(index, color) end
|
function pal.subpal(index, color) end
|
||||||
|
|
||||||
---@param index number
|
|
||||||
---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 +205,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 +233,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 +267,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 +287,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 +299,9 @@ 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
|
---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
|
---to the position (dx, dy) of the target surface, rotating it by a degrees
|
||||||
function draw.surfaceRotated(surface, sx, sy, sw, sh, x, y, a) end
|
function draw.surfrot(sx, sy, sw, sh, x, y, a) end
|
||||||
|
|
||||||
---@param text string
|
---@param text string
|
||||||
---@param x number
|
---@param x number
|
||||||
@@ -296,6 +310,46 @@ 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 text number
|
||||||
|
---@param x number
|
||||||
|
---@param y number
|
||||||
|
---@param color number
|
||||||
|
---Draw text to (x,y) using the specified color
|
||||||
|
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 +357,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 +371,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 +405,119 @@ 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
|
||||||
|
|
||||||
|
|
||||||
|
---@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 +526,151 @@ 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 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
|
||||||
|
|
||||||
|
|
||||||
---@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 +700,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 +780,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
|
||||||
@@ -703,52 +888,3 @@ key.RCTRL = 228
|
|||||||
key.RSHIFT = 229
|
key.RSHIFT = 229
|
||||||
key.RALT = 230
|
key.RALT = 230
|
||||||
key.RGUI = 231
|
key.RGUI = 231
|
||||||
|
|
||||||
|
|
||||||
---@class button
|
|
||||||
---@field button.INVALID number
|
|
||||||
---@field button.A number
|
|
||||||
---@field button.B number
|
|
||||||
---@field button.X number
|
|
||||||
---@field button.Y number
|
|
||||||
---@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
|
|
||||||
Reference in New Issue
Block a user