Compare commits
55 Commits
5306e82897
...
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 | |||
| 61b02fdeef | |||
| 7abc8648a1 | |||
| 2f0817d20c | |||
| ecb493f9c8 | |||
| 9c3baebc1e | |||
| 173654e0bd | |||
| ba1daf810d | |||
| 45d31579d2 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ mini_debug
|
||||
.vscode/*
|
||||
info.plist
|
||||
*.dll
|
||||
build/*
|
||||
14
Makefile
14
Makefile
@@ -3,25 +3,25 @@ source = *.cpp ./lua/*.c
|
||||
|
||||
windows:
|
||||
@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"
|
||||
|
||||
windows_debug:
|
||||
@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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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)"
|
||||
|
||||
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
|
||||
config=minitest
|
||||
width=160
|
||||
height=120
|
||||
zoom=3
|
||||
title=TESTS
|
||||
config=minitests
|
||||
width=400
|
||||
height=300
|
||||
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
|
||||
|
||||
function mini.init()
|
||||
text=other.peiv()
|
||||
keyRight = tonumber(config.getKey("keyright")) or key.RIGHT
|
||||
keyLeft = tonumber(config.getKey("keyleft")) or key.LEFT
|
||||
mini.update=normal_update
|
||||
--turbo(false)
|
||||
local perico = "péricòñ"
|
||||
print(utf8.len(perico))
|
||||
ants = 0xc936;
|
||||
s = surface.load("tiles01.gif")
|
||||
--surface.source(s)
|
||||
p = palette.load("tiles01.gif")
|
||||
palette.set(p)
|
||||
palette.setTransparent(255)
|
||||
print(#p)
|
||||
surface.save(s, "data/copy.gif")
|
||||
s = surface.load("copy.gif")
|
||||
--draw.source(s)
|
||||
system.setBeat(4)
|
||||
s = surf.load("gfx/logo.gif")
|
||||
surf.source(s)
|
||||
p = pal.load("gfx/logo.gif")
|
||||
pal.set(p)
|
||||
pal.trans(255)
|
||||
--surf.save(s, "prova.gif", p)
|
||||
|
||||
print("=== PACKAGES LOADED ===")
|
||||
for name, value in pairs(package.loaded) do
|
||||
print(name, value)
|
||||
end
|
||||
print("========================")
|
||||
|
||||
end
|
||||
|
||||
function mini.update()
|
||||
if keyboard.keyPressed(key.ESCAPE) then
|
||||
system.quit()
|
||||
surf.cls(0)
|
||||
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
|
||||
|
||||
if system.isBeat() then
|
||||
ants = (ants >> 12) | ((ants<<4)&0xffff)
|
||||
end
|
||||
surface.cls(5)
|
||||
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)
|
||||
local mx, my = mouse.pos()
|
||||
draw.rectf(mx, my, 4, 4, 8)
|
||||
draw.text(mx .. " " .. my, 1, 8, 8)
|
||||
draw.text(other.peiv(),1,100,4)
|
||||
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 )
|
||||
{
|
||||
int i, bit;
|
||||
int code, prev = -1;
|
||||
dictionary_entry_t *dictionary;
|
||||
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 );
|
||||
stop_code = clear_code + 1;
|
||||
reset_code_length = code_length;
|
||||
const int clear_code = 1 << ( code_length );
|
||||
const int stop_code = clear_code + 1;
|
||||
const int reset_code_length = code_length;
|
||||
|
||||
dictionary = ( dictionary_entry_t * )
|
||||
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;
|
||||
|
||||
int prev = -1;
|
||||
uint32_t mask = 0x01;
|
||||
while ( input_length )
|
||||
{
|
||||
code = 0x0;
|
||||
for (i=0; i<(code_length + 1); i++)
|
||||
int code = 0x0;
|
||||
|
||||
for (int i=0; i<(code_length + 1); i++)
|
||||
{
|
||||
bit = ( *input & mask ) ? 1 : 0;
|
||||
const int bit = ( *input & mask ) ? 1 : 0;
|
||||
mask <<= 1;
|
||||
|
||||
if ( mask == 0x100 )
|
||||
@@ -90,18 +86,9 @@ void uncompress( int code_length, const uint8_t *input, int input_length, uint8_
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( code == dictionary_ind )
|
||||
{
|
||||
int ptr = prev;
|
||||
while ( dictionary[ ptr ].prev != -1 ) ptr = dictionary[ ptr ].prev;
|
||||
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
int ptr = code;
|
||||
while ( dictionary[ ptr ].prev != -1 ) ptr = dictionary[ ptr ].prev;
|
||||
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
|
||||
}
|
||||
int ptr = (code == dictionary_ind) ? prev : code;
|
||||
while ( dictionary[ ptr ].prev != -1 ) ptr = dictionary[ ptr ].prev;
|
||||
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
|
||||
|
||||
dictionary[ dictionary_ind ].prev = prev;
|
||||
dictionary[ dictionary_ind ].len = dictionary[ prev ].len + 1;
|
||||
@@ -116,7 +103,7 @@ void uncompress( int code_length, const uint8_t *input, int input_length, uint8_
|
||||
|
||||
prev = code;
|
||||
|
||||
match_len = dictionary[ code ].len;
|
||||
const int match_len = dictionary[ code ].len;
|
||||
while ( code != -1 )
|
||||
{
|
||||
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;
|
||||
|
||||
buffer += 6; // Ignore header
|
||||
*w = (uint16_t)*buffer; buffer+=2;
|
||||
*h = (uint16_t)*buffer; buffer+=2;
|
||||
*w = *((uint16_t*)buffer); buffer+=2;
|
||||
*h = *((uint16_t*)buffer); buffer+=2;
|
||||
const uint8_t fields = *buffer; buffer+=3;
|
||||
|
||||
const int color_resolution_bits = ( ( fields & 0x70 ) >> 4 ) + 1;
|
||||
332
gifenc.h
332
gifenc.h
@@ -3,226 +3,172 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_DICT_SIZE 4096
|
||||
|
||||
namespace gif
|
||||
{
|
||||
struct gif_t {
|
||||
uint16_t w, h;
|
||||
int depth;
|
||||
int bgindex;
|
||||
FILE *fd;
|
||||
int offset;
|
||||
int nframes;
|
||||
uint8_t *frame, *back;
|
||||
uint32_t partial;
|
||||
uint8_t buffer[0xFF];
|
||||
};
|
||||
typedef struct {
|
||||
int prefix;
|
||||
uint8_t character;
|
||||
} DictEntry;
|
||||
|
||||
struct node_t {
|
||||
uint16_t key;
|
||||
node_t *children[];
|
||||
};
|
||||
typedef struct {
|
||||
uint8_t *data;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
int bit_pos;
|
||||
uint32_t bit_buffer;
|
||||
} BitStream;
|
||||
|
||||
static node_t *new_node(uint16_t key, int degree)
|
||||
{
|
||||
node_t *node = (node_t*)calloc(1, sizeof(*node) + degree * sizeof(node_t *));
|
||||
if (node) node->key = key;
|
||||
return node;
|
||||
void bitstream_init(BitStream *bs) {
|
||||
bs->capacity = 256;
|
||||
bs->size = 0;
|
||||
bs->data = (uint8_t*)malloc(bs->capacity);
|
||||
bs->bit_pos = 0;
|
||||
bs->bit_buffer = 0;
|
||||
}
|
||||
|
||||
static node_t *new_trie(int degree, int *nkeys)
|
||||
{
|
||||
node_t *root = new_node(0, degree);
|
||||
/* 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;
|
||||
}
|
||||
void bitstream_write(BitStream *bs, uint16_t code, int code_size) {
|
||||
bs->bit_buffer |= ((uint32_t)code) << bs->bit_pos;
|
||||
bs->bit_pos += code_size;
|
||||
|
||||
static void del_trie(node_t *root, int degree)
|
||||
{
|
||||
if (!root) return;
|
||||
for (int i = 0; i < degree; i++) del_trie(root->children[i], degree);
|
||||
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;
|
||||
while (bs->bit_pos >= 8) {
|
||||
if (bs->size >= bs->capacity) {
|
||||
bs->capacity *= 2;
|
||||
bs->data = (uint8_t*)realloc(bs->data, bs->capacity);
|
||||
}
|
||||
gif->partial >>= 8;
|
||||
bits_to_write -= 8;
|
||||
bs->data[bs->size++] = bs->bit_buffer & 0xFF;
|
||||
bs->bit_buffer >>= 8;
|
||||
bs->bit_pos -= 8;
|
||||
}
|
||||
gif->offset = (gif->offset + key_size) % (0xFF * 8);
|
||||
}
|
||||
|
||||
static void end_key(gif_t *gif)
|
||||
{
|
||||
uint8_t byte_offset;
|
||||
byte_offset = gif->offset >> 3;
|
||||
if (gif->offset & 0x07) gif->buffer[byte_offset++] = gif->partial & 0xFF;
|
||||
if (byte_offset)
|
||||
{
|
||||
fputc(byte_offset, gif->fd);
|
||||
fwrite(gif->buffer, byte_offset, 1, gif->fd);
|
||||
void bitstream_flush(BitStream *bs) {
|
||||
if (bs->bit_pos > 0) {
|
||||
if (bs->size >= bs->capacity) {
|
||||
bs->capacity *= 2;
|
||||
bs->data = (uint8_t*)realloc(bs->data, bs->capacity);
|
||||
}
|
||||
bs->data[bs->size++] = bs->bit_buffer & 0xFF;
|
||||
}
|
||||
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)
|
||||
{
|
||||
int nkeys, key_size, i, j;
|
||||
node_t *node, *child, *root;
|
||||
int degree = 1 << gif->depth;
|
||||
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 end_code = clear_code + 1;
|
||||
int next_code = end_code + 1;
|
||||
int code_size = min_code_size + 1;
|
||||
|
||||
fputc(',', gif->fd);
|
||||
fwrite(&x, 2, 1, gif->fd);
|
||||
fwrite(&y, 2, 1, gif->fd);
|
||||
fwrite(&w, 2, 1, gif->fd);
|
||||
fwrite(&h, 2, 1, gif->fd);
|
||||
fputc(0, gif->fd); fputc(gif->depth, gif->fd);
|
||||
root = node = new_trie(degree, &nkeys);
|
||||
key_size = gif->depth + 1;
|
||||
put_key(gif, degree, key_size); /* clear code */
|
||||
for (i = y; i < y+h; i++) {
|
||||
for (j = x; j < x+w; j++) {
|
||||
uint8_t pixel = gif->frame[i*gif->w+j] & (degree - 1);
|
||||
child = node->children[pixel];
|
||||
if (child) {
|
||||
node = child;
|
||||
DictEntry dict[MAX_DICT_SIZE];
|
||||
int dict_len = next_code;
|
||||
|
||||
BitStream bs;
|
||||
bitstream_init(&bs);
|
||||
bitstream_write(&bs, clear_code, code_size);
|
||||
|
||||
int prefix = input[0];
|
||||
for (int i = 1; i < width * height; i++) {
|
||||
uint8_t c = input[i];
|
||||
|
||||
// Search for prefix + c in dictionary
|
||||
int found = -1;
|
||||
for (int j = end_code + 1; j < dict_len; j++) {
|
||||
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 {
|
||||
put_key(gif, node->key, key_size);
|
||||
if (nkeys < 0x1000) {
|
||||
if (nkeys == (1 << key_size))
|
||||
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];
|
||||
bitstream_write(&bs, clear_code, code_size);
|
||||
dict_len = end_code + 1;
|
||||
code_size = min_code_size + 1;
|
||||
}
|
||||
prefix = c; // Start new prefix
|
||||
}
|
||||
}
|
||||
put_key(gif, node->key, key_size);
|
||||
put_key(gif, degree + 1, key_size); /* stop code */
|
||||
end_key(gif);
|
||||
del_trie(root, degree);
|
||||
|
||||
// Emit final prefix and end code
|
||||
bitstream_write(&bs, prefix, code_size);
|
||||
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)
|
||||
{
|
||||
int i, j, k;
|
||||
int left, right, top, bottom;
|
||||
uint8_t back;
|
||||
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;
|
||||
}
|
||||
}
|
||||
void write_gif(const char *filename, uint8_t *pixels, int width, int height, uint8_t *palette, int palette_size) {
|
||||
FILE *f = fopen(filename, "wb");
|
||||
if (!f) {
|
||||
perror("Failed to open file");
|
||||
return;
|
||||
}
|
||||
if (left != gif->w && top != gif->h) {
|
||||
*x = left; *y = top;
|
||||
*w = right - left + 1;
|
||||
*h = bottom - top + 1;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
|
||||
// Header
|
||||
fwrite("GIF89a", 1, 6, f);
|
||||
|
||||
// Determine min_code_size from palette_size
|
||||
int palette_depth = 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)
|
||||
{
|
||||
uint8_t flags = ((gif->bgindex >= 0 ? 2 : 1) << 2) + 1;
|
||||
fputc('!', gif->fd); fputc(0xF9, gif->fd); fputc(0x04, gif->fd); fputc(flags, gif->fd);
|
||||
fwrite(&d, 2, 1, gif->fd);
|
||||
fputc(gif->bgindex, gif->fd); fputc(0, gif->fd);
|
||||
}
|
||||
// Image Descriptor
|
||||
uint8_t image_desc[] = {
|
||||
0x2C, 0, 0, 0, 0,
|
||||
uint8_t(width & 0xFF), uint8_t((width >> 8) & 0xFF),
|
||||
uint8_t(height & 0xFF), uint8_t((height >> 8) & 0xFF),
|
||||
0x00 // No local color table
|
||||
};
|
||||
fwrite(image_desc, 1, sizeof(image_desc), f);
|
||||
|
||||
void addFrame(gif_t *gif, uint16_t delay)
|
||||
{
|
||||
uint16_t w, h, x, y;
|
||||
uint8_t *tmp;
|
||||
// LZW-compressed image data
|
||||
fwrite(&min_code_size, 1, 1, f);
|
||||
|
||||
if (delay || (gif->bgindex >= 0))
|
||||
add_graphics_control_extension(gif, delay);
|
||||
if (gif->nframes == 0) {
|
||||
w = gif->w;
|
||||
h = gif->h;
|
||||
x = y = 0;
|
||||
} else if (!get_bbox(gif, &w, &h, &x, &y)) {
|
||||
/* image's not changed; save one pixel just to add delay */
|
||||
w = h = 1;
|
||||
x = y = 0;
|
||||
size_t compressed_size;
|
||||
uint8_t *compressed = lzw_compress(pixels, width, height, min_code_size, &compressed_size);
|
||||
|
||||
// Write as sub-blocks
|
||||
size_t offset = 0;
|
||||
while (offset < compressed_size) {
|
||||
uint8_t block_size = (compressed_size - offset > 255) ? 255 : (uint8_t)(compressed_size - offset);
|
||||
fwrite(&block_size, 1, 1, f);
|
||||
fwrite(compressed + offset, 1, block_size, f);
|
||||
offset += block_size;
|
||||
}
|
||||
put_image(gif, w, h, x, y);
|
||||
gif->nframes++;
|
||||
if (gif->bgindex < 0) {
|
||||
tmp = gif->back;
|
||||
gif->back = gif->frame;
|
||||
gif->frame = tmp;
|
||||
}
|
||||
}
|
||||
fputc(0x00, f); // Block terminator
|
||||
|
||||
void close(gif_t* gif)
|
||||
{
|
||||
fputc(';', gif->fd);
|
||||
fclose(gif->fd);
|
||||
free(gif);
|
||||
}
|
||||
// Trailer
|
||||
fputc(0x3B, f);
|
||||
|
||||
free(compressed);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
380
jail_audio.cpp
380
jail_audio.cpp
@@ -1,47 +1,61 @@
|
||||
#ifndef JA_USESDLMIXER
|
||||
#include "jail_audio.h"
|
||||
#include "stb_vorbis.c"
|
||||
#include <SDL2/SDL.h>
|
||||
#include "stb_vorbis.h"
|
||||
#include <SDL3/SDL.h>
|
||||
#include <stdio.h>
|
||||
#include "log.h"
|
||||
|
||||
#define JA_MAX_SIMULTANEOUS_CHANNELS 5
|
||||
|
||||
struct JA_Sound_t {
|
||||
Uint32 length {0};
|
||||
Uint8* buffer {NULL};
|
||||
struct JA_Sound_t
|
||||
{
|
||||
SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
|
||||
Uint32 length { 0 };
|
||||
Uint8 *buffer { NULL };
|
||||
};
|
||||
|
||||
struct JA_Channel_t {
|
||||
JA_Sound_t *sound;
|
||||
int pos {0};
|
||||
int times {0};
|
||||
JA_Channel_state state { JA_CHANNEL_FREE };
|
||||
struct JA_Channel_t
|
||||
{
|
||||
JA_Sound_t *sound { nullptr };
|
||||
int pos { 0 };
|
||||
int times { 0 };
|
||||
SDL_AudioStream *stream { nullptr };
|
||||
JA_Channel_state state { JA_CHANNEL_FREE };
|
||||
};
|
||||
|
||||
struct JA_Music_t {
|
||||
int samples {0};
|
||||
int pos {0};
|
||||
int times {0};
|
||||
short* output {NULL};
|
||||
JA_Music_state state {JA_MUSIC_INVALID};
|
||||
struct JA_Music_t
|
||||
{
|
||||
SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
|
||||
Uint32 length { 0 };
|
||||
Uint8 *buffer { nullptr };
|
||||
|
||||
int pos { 0 };
|
||||
int times { 0 };
|
||||
SDL_AudioStream *stream { nullptr };
|
||||
JA_Music_state state { JA_MUSIC_INVALID };
|
||||
};
|
||||
|
||||
JA_Music_t *current_music{NULL};
|
||||
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
|
||||
JA_Music_t *current_music { nullptr };
|
||||
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
|
||||
|
||||
int JA_freq {48000};
|
||||
SDL_AudioFormat JA_format {AUDIO_S16};
|
||||
Uint8 JA_channels {2};
|
||||
int JA_musicVolume = 128;
|
||||
int JA_soundVolume = 64;
|
||||
bool JA_musicEnabled = true;
|
||||
bool JA_soundEnabled = true;
|
||||
SDL_AudioDeviceID sdlAudioDevice = 0;
|
||||
SDL_AudioSpec JA_audioSpec { SDL_AUDIO_S16, 2, 48000 };
|
||||
float JA_musicVolume { 1.0f };
|
||||
float JA_soundVolume { 0.5f };
|
||||
bool JA_musicEnabled { true };
|
||||
bool JA_soundEnabled { true };
|
||||
SDL_AudioDeviceID sdlAudioDevice { 0 };
|
||||
SDL_TimerID JA_timerID { 0 };
|
||||
|
||||
bool fading = false;
|
||||
int fade_start_time;
|
||||
int fade_duration;
|
||||
int fade_initial_volume;
|
||||
|
||||
/*
|
||||
void audioCallback(void * userdata, uint8_t * stream, int len) {
|
||||
SDL_memset(stream, 0, len);
|
||||
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);
|
||||
current_music->pos += size/2;
|
||||
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)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
||||
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
||||
#endif
|
||||
|
||||
SDL_Log("Iniciant JailAudio...");
|
||||
JA_freq = freq;
|
||||
JA_format = format;
|
||||
JA_channels = channels;
|
||||
SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL};
|
||||
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");
|
||||
JA_audioSpec = {format, channels, freq };
|
||||
if (!sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
|
||||
sdlAudioDevice = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &JA_audioSpec);
|
||||
if (!sdlAudioDevice) {
|
||||
log_msg(LOG_FAIL, "Failed to initialize SDL audio: %s\n", SDL_GetError());
|
||||
} 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() {
|
||||
SDL_PauseAudioDevice(sdlAudioDevice, 1);
|
||||
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice);
|
||||
void JA_Quit()
|
||||
{
|
||||
if (JA_timerID) SDL_RemoveTimer(JA_timerID);
|
||||
|
||||
if (!sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
|
||||
sdlAudioDevice = 0;
|
||||
}
|
||||
|
||||
JA_Music_t *JA_LoadMusic(Uint8* buffer, Uint32 length)
|
||||
{
|
||||
int chan, samplerate;
|
||||
JA_Music_t *music = new JA_Music_t();
|
||||
|
||||
music->samples = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &music->output);
|
||||
// [RZC 28/08/22] Abans el descomprimiem mentre el teniem obert
|
||||
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
|
||||
int chan, samplerate;
|
||||
short *output;
|
||||
music->length = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &output) * chan * 2;
|
||||
|
||||
SDL_AudioCVT cvt;
|
||||
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
|
||||
SDL_Log("Music length: %f\n", float(music->samples)/float(JA_freq));
|
||||
if (cvt.needed) {
|
||||
cvt.len = music->samples * chan * 2;
|
||||
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
|
||||
SDL_memcpy(cvt.buf, music->output, cvt.len);
|
||||
SDL_ConvertAudio(&cvt);
|
||||
free(music->output);
|
||||
music->output = (short*)cvt.buf;
|
||||
}
|
||||
music->spec.channels = chan;
|
||||
music->spec.freq = samplerate;
|
||||
music->spec.format = SDL_AUDIO_S16;
|
||||
music->buffer = (Uint8*)SDL_malloc(music->length);
|
||||
SDL_memcpy(music->buffer, output, music->length);
|
||||
free(output);
|
||||
music->pos = 0;
|
||||
music->state = JA_MUSIC_STOPPED;
|
||||
|
||||
@@ -151,122 +209,133 @@ void JA_PlayMusic(JA_Music_t *music, const int loop)
|
||||
{
|
||||
if (!JA_musicEnabled) return;
|
||||
|
||||
if (current_music != NULL) {
|
||||
current_music->pos = 0;
|
||||
current_music->state = JA_MUSIC_STOPPED;
|
||||
}
|
||||
JA_StopMusic();
|
||||
|
||||
current_music = music;
|
||||
current_music->pos = 0;
|
||||
current_music->state = JA_MUSIC_PLAYING;
|
||||
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()
|
||||
{
|
||||
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;
|
||||
//SDL_PauseAudioStreamDevice(current_music->stream);
|
||||
SDL_UnbindAudioStream(current_music->stream);
|
||||
}
|
||||
|
||||
void JA_ResumeMusic()
|
||||
{
|
||||
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;
|
||||
//SDL_ResumeAudioStreamDevice(current_music->stream);
|
||||
SDL_BindAudioStream(sdlAudioDevice, current_music->stream);
|
||||
}
|
||||
|
||||
void JA_StopMusic()
|
||||
{
|
||||
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->state = JA_MUSIC_STOPPED;
|
||||
//SDL_PauseAudioStreamDevice(current_music->stream);
|
||||
SDL_DestroyAudioStream(current_music->stream);
|
||||
current_music->stream = nullptr;
|
||||
}
|
||||
|
||||
JA_Music_state JA_GetMusicState() {
|
||||
if (!JA_musicEnabled) return JA_MUSIC_DISABLED;
|
||||
void JA_FadeOutMusic(const int milliseconds)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void JA_DeleteMusic(JA_Music_t *music) {
|
||||
if (current_music == music) current_music = NULL;
|
||||
free(music->output);
|
||||
void JA_DeleteMusic(JA_Music_t *music)
|
||||
{
|
||||
if (current_music == music) current_music = nullptr;
|
||||
SDL_free(music->buffer);
|
||||
if (music->stream) SDL_DestroyAudioStream(music->stream);
|
||||
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;
|
||||
}
|
||||
|
||||
void JA_SetMusicPosition(float value)
|
||||
{
|
||||
if (!current_music) return;
|
||||
current_music->pos = value * JA_freq;
|
||||
current_music->pos = value * current_music->spec.freq;
|
||||
}
|
||||
|
||||
float JA_GetMusicPosition()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
sound->buffer = buffer;
|
||||
sound->length = length;
|
||||
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();
|
||||
SDL_AudioSpec wavSpec;
|
||||
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;
|
||||
SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size),1, &sound->spec, &sound->buffer, &sound->length);
|
||||
|
||||
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();
|
||||
SDL_AudioSpec wavSpec;
|
||||
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;
|
||||
SDL_LoadWAV(filename, &sound->spec, &sound->buffer, &sound->length);
|
||||
|
||||
return sound;
|
||||
}
|
||||
@@ -278,11 +347,36 @@ int JA_PlaySound(JA_Sound_t *sound, const int loop)
|
||||
int channel = 0;
|
||||
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
|
||||
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -299,12 +393,24 @@ void JA_PauseChannel(const int channel)
|
||||
{
|
||||
if (!JA_soundEnabled) return;
|
||||
|
||||
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;
|
||||
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;
|
||||
//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 (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;
|
||||
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;
|
||||
//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 (channel == -1) {
|
||||
if (channel == -1)
|
||||
{
|
||||
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].pos = 0;
|
||||
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].pos = 0;
|
||||
channels[channel].sound = NULL;
|
||||
@@ -343,12 +468,18 @@ JA_Channel_state JA_GetChannelState(const int channel)
|
||||
if (!JA_soundEnabled) return JA_SOUND_DISABLED;
|
||||
|
||||
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -361,10 +492,15 @@ void JA_EnableSound(const bool value)
|
||||
JA_soundEnabled = value;
|
||||
}
|
||||
|
||||
int JA_SetVolume(int volume)
|
||||
const bool JA_IsSoundEnabled()
|
||||
{
|
||||
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume;
|
||||
JA_soundVolume = JA_musicVolume/2;
|
||||
return JA_soundEnabled;
|
||||
}
|
||||
|
||||
float JA_SetVolume(float volume)
|
||||
{
|
||||
JA_SetSoundVolume(JA_SetMusicVolume(volume) / 2.0f);
|
||||
|
||||
return JA_musicVolume;
|
||||
}
|
||||
|
||||
|
||||
12
jail_audio.h
12
jail_audio.h
@@ -1,5 +1,5 @@
|
||||
#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_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_ResumeMusic();
|
||||
void JA_StopMusic();
|
||||
void JA_FadeOutMusic(const int milliseconds);
|
||||
JA_Music_state JA_GetMusicState();
|
||||
void JA_DeleteMusic(JA_Music_t *music);
|
||||
int JA_SetMusicVolume(int volume);
|
||||
float JA_SetMusicVolume(float volume);
|
||||
void JA_SetMusicPosition(float value);
|
||||
float JA_GetMusicPosition();
|
||||
void JA_EnableMusic(const bool value);
|
||||
const bool JA_IsMusicEnabled();
|
||||
|
||||
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length);
|
||||
JA_Sound_t *JA_LoadSound(Uint8* buffer, Uint32 length);
|
||||
JA_Sound_t *JA_LoadSound(const char* filename);
|
||||
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_ResumeChannel(const int channel);
|
||||
void JA_StopChannel(const int channel);
|
||||
JA_Channel_state JA_GetChannelState(const int channel);
|
||||
void JA_DeleteSound(JA_Sound_t *sound);
|
||||
int JA_SetSoundVolume(int volume);
|
||||
float JA_SetSoundVolume(float volume);
|
||||
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 <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <algorithm>
|
||||
#include <dirent.h> // Para opendir/readdir en SOURCE_FOLDER
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <pwd.h>
|
||||
@@ -130,10 +132,30 @@ FILE *file_getfilepointer(const char *resourcename, int& filesize, const bool bi
|
||||
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);
|
||||
char* buffer = (char*)malloc(filesize);
|
||||
char* buffer = (char*)malloc(zero_terminate?filesize:filesize+1);
|
||||
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);
|
||||
return buffer;
|
||||
}
|
||||
@@ -151,6 +173,29 @@ void file_setconfigfolder(const char *foldername)
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
const char *homedir = pw->pw_dir;
|
||||
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
|
||||
|
||||
struct stat st = {0};
|
||||
@@ -171,7 +216,7 @@ void file_setconfigfolder(const char *foldername)
|
||||
}
|
||||
|
||||
const char *file_getconfigfolder() {
|
||||
std::string folder = config_folder + "/";
|
||||
static std::string folder = config_folder + "/";
|
||||
return folder.c_str();
|
||||
}
|
||||
|
||||
@@ -228,3 +273,107 @@ void file_setconfigvalue(const char* key, const char* value) {
|
||||
file_saveconfigvalues();
|
||||
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
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#define SOURCE_FILE 0
|
||||
#define SOURCE_FOLDER 1
|
||||
@@ -12,7 +14,13 @@ void file_setresourcefolder(const char *str);
|
||||
void file_setsource(const int src);
|
||||
|
||||
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);
|
||||
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) {
|
||||
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_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
|
||||
lua_getfield(L, 2, name); /* LOADED[name] */
|
||||
|
||||
563
mini.cpp
563
mini.cpp
@@ -2,12 +2,14 @@
|
||||
#include "jfile.h"
|
||||
#include <string.h>
|
||||
#include "lua.h"
|
||||
#include "gif.c"
|
||||
#include "gif.h"
|
||||
#include "gifenc.h"
|
||||
//#include "SDL2/SDL_mixer.h"
|
||||
#include "jail_audio.h"
|
||||
#include "jshader.h"
|
||||
//#include <vector>
|
||||
#include "log.h"
|
||||
|
||||
#define MAX_TEXTURES 10
|
||||
#define MAX_SURFACES 100
|
||||
|
||||
#ifdef MACOS_BUNDLE
|
||||
#include <libgen.h>
|
||||
@@ -18,12 +20,22 @@
|
||||
#pragma pack(1)
|
||||
|
||||
struct surface_t {
|
||||
uint8_t *p;
|
||||
char *name {nullptr};
|
||||
uint8_t *p {nullptr};
|
||||
uint16_t w, h;
|
||||
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 config_folder[256];
|
||||
uint16_t screen_width = 160;
|
||||
@@ -35,7 +47,7 @@ bool screen_cursor = true;
|
||||
int desktop_width = 0;
|
||||
int desktop_height = 0;
|
||||
|
||||
surface_t surfaces[MAX_TEXTURES];
|
||||
surface_t surfaces[MAX_SURFACES];
|
||||
surface_t *screen_surface = &surfaces[0];
|
||||
surface_t *dest_surface = screen_surface;
|
||||
surface_t *source_surface = NULL;
|
||||
@@ -66,6 +78,7 @@ namespace ds {
|
||||
uint16_t fill_pattern = 0b1111111111111111;
|
||||
bool fill_trans = false;
|
||||
uint8_t draw_palette[256];
|
||||
uint8_t mode = DRAWMODE_NORMAL;
|
||||
}
|
||||
|
||||
int update_mode = UPDATE_ALWAYS;
|
||||
@@ -76,12 +89,13 @@ bool should_quit = false;
|
||||
SDL_Window *mini_win;
|
||||
SDL_Renderer *mini_ren;
|
||||
SDL_Texture *mini_bak;
|
||||
SDL_Texture *mini_shadertex;
|
||||
Uint32 windowID;
|
||||
Uint32 *pixels;
|
||||
int pitch;
|
||||
|
||||
uint32_t palette[256] = { 0x001a1c2c, 0x005d275d, 0x00b13e53, 0x00ef7d57, 0x00ffcd75, 0x00a7f070, 0x0038b764, 0x00257179,
|
||||
0x0029366f, 0x003b5dc9, 0x0041a6f6, 0x0073eff7, 0x00f4f4f4, 0x0094b0c2, 0x00566c86, 0x00333c57 };
|
||||
uint32_t palette[256] = { 0xFF1a1c2c, 0xFF5d275d, 0xFFb13e53, 0xFFef7d57, 0xFFffcd75, 0xFFa7f070, 0xFF38b764, 0xFF257179,
|
||||
0xFF29366f, 0xFF3b5dc9, 0xFF41a6f6, 0xFF73eff7, 0xFFf4f4f4, 0xFF94b0c2, 0xFF566c86, 0xFF333c57 };
|
||||
|
||||
const char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
@@ -93,15 +107,17 @@ char base64glyphs[193] = "/h/AqV/hhhh/GMYYMGz/t/eS33H477wsjjswY4IOPHEFFVVVAVAVAV
|
||||
"AMShAAAQsjAAAwsjAAAeSzAAAcU3AAAEqRAAABVaiAAMezhAAAAAMAADH4wAASb2SAAMAttAQYcefACGOe+AAAVVAAAAbbAA";
|
||||
|
||||
//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;
|
||||
|
||||
int mouse_x, mouse_y, mouse_wheel;
|
||||
Uint32 mouse_buttons;
|
||||
uint8_t mouse_just_pressed = 0;
|
||||
bool double_click = false;
|
||||
bool mouse_discard = false;
|
||||
|
||||
SDL_GameController *gamepad = NULL;
|
||||
int8_t pad_just_pressed = SDL_CONTROLLER_BUTTON_INVALID;
|
||||
SDL_Gamepad *gamepad = NULL;
|
||||
int8_t pad_just_pressed = SDL_GAMEPAD_BUTTON_INVALID;
|
||||
|
||||
#define MAX_SOUNDS 50
|
||||
JA_Music_t *music = NULL;
|
||||
@@ -109,6 +125,8 @@ JA_Sound_t *sounds[MAX_SOUNDS];
|
||||
|
||||
int16_t beats, num_beats = 0;
|
||||
|
||||
void createNewProject();
|
||||
|
||||
char* get_value_from_line(char* line) {
|
||||
char* equal_character = strchr(line, '=');
|
||||
if (equal_character == NULL) return NULL;
|
||||
@@ -118,21 +136,20 @@ char* get_value_from_line(char* line) {
|
||||
|
||||
void read_ini() {
|
||||
int size;
|
||||
SDL_Log("Carregant 'game.ini'...");
|
||||
FILE *f = file_getfilepointer("game.ini", size); // fopen("game.ini", "r");
|
||||
char line[1024];
|
||||
if (f == NULL) { SDL_Log("FAIL!\n"); return; }
|
||||
SDL_Log("OK!\n");
|
||||
if (f == NULL) { log_msg(LOG_FAIL, "No s'ha pogut obrir 'game.ini'\n"); exit(-1); }
|
||||
log_msg(LOG_OK, "'game.ini' carregat\n");
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
char *value = get_value_from_line(line);
|
||||
if (value != NULL) {
|
||||
value[strlen(value)-1] = '\0';
|
||||
if (strcmp(line, "title") == 0) { strcpy(window_title, value); SDL_Log("-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, "width") == 0) { screen_width = atoi(value); SDL_Log("-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, "zoom") == 0) { screen_zoom = atoi(value); SDL_Log("-screen zoom=%i\n", screen_zoom); }
|
||||
else if (strcmp(line, "fullscreen") == 0) { screen_fullscreen = atoi(value); SDL_Log("-screen sullscreen=%i\n", screen_fullscreen); }
|
||||
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); log_msg(LOG_VERBOSE, "config = %s\n", config_folder); }
|
||||
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); log_msg(LOG_VERBOSE, "screen height = %i\n", screen_height); }
|
||||
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); log_msg(LOG_VERBOSE, "screen sullscreen = %i\n", screen_fullscreen); }
|
||||
//else if (strcmp(line, "files") == 0) {
|
||||
//lua_files = (char*)malloc(strlen(value));
|
||||
// strcpy(lua_files, value);
|
||||
@@ -140,13 +157,32 @@ void read_ini() {
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
SDL_Log("'game.ini' carregat!\n");
|
||||
//SDL_Log("'game.ini' carregat!\n");
|
||||
}
|
||||
|
||||
void pset_fast(int x, int y) {
|
||||
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) {
|
||||
int pbx = x % 4, pby = y % 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() {
|
||||
SDL_Log("REINIT\n");
|
||||
log_msg(LOG_INFO, "STARTING A SYSTEM REINITIALIZATION\n");
|
||||
do_pset = pset_fast;
|
||||
ds::pen_color = 6;
|
||||
ds::back_color = 0;
|
||||
@@ -168,17 +225,23 @@ void reinit() {
|
||||
ds::trans=0;
|
||||
ds::fill_pattern = 0b1111111111111111;
|
||||
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);
|
||||
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;
|
||||
if (file!=NULL) fclose(file);
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -197,42 +260,69 @@ int scrh() {
|
||||
}
|
||||
|
||||
uint8_t newsurf(int w, int h) {
|
||||
int i = 0;
|
||||
while (i<MAX_TEXTURES && surfaces[i].p != NULL) ++i;
|
||||
//[TODO] Gestionar el cas en que no queden surfaces lliures
|
||||
unsigned int i = 0;
|
||||
while (i<MAX_SURFACES && surfaces[i].p != NULL) ++i;
|
||||
if (i==MAX_SURFACES) return 255;
|
||||
surfaces[i].name = nullptr;
|
||||
surfaces[i].w = w;
|
||||
surfaces[i].h = h;
|
||||
surfaces[i].size = w*h;
|
||||
surfaces[i].p = (uint8_t*)malloc(surfaces[i].size);
|
||||
surfaces[i].p = (uint8_t*)calloc(surfaces[i].size,1);
|
||||
log_msg(LOG_INFO, "Surface %i creada.\n", i);
|
||||
return i;
|
||||
}
|
||||
|
||||
uint8_t loadsurf(const char* filename) {
|
||||
int i = 0;
|
||||
while (i<MAX_TEXTURES && surfaces[i].p != NULL) ++i;
|
||||
//[TODO] Gestionar el cas en que no queden surfaces lliures
|
||||
uint8_t loadsurf(const char* filename, const bool external) {
|
||||
// Si el gif ja s'ha carregat en una textura, tornem eixa textura
|
||||
for (unsigned int i=0; i<MAX_SURFACES; ++i)
|
||||
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;
|
||||
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].size = surfaces[i].w*surfaces[i].h;
|
||||
surfaces[i].name = (char*)malloc(strlen(filename)+1);
|
||||
strcpy(surfaces[i].name, filename);
|
||||
free(buffer);
|
||||
|
||||
log_msg(LOG_INFO, "Arxiu '%s' carregat en surface: %i.\n", filename, i);
|
||||
return i;
|
||||
}
|
||||
|
||||
void savesurf(uint8_t surface, const char* filename, uint8_t *pal, uint8_t colors)
|
||||
{
|
||||
uint8_t depth=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);
|
||||
gif::write_gif(filename, surfaces[surface].p, surfaces[surface].w, surfaces[surface].h, pal, colors);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -246,7 +336,10 @@ int surfh(uint8_t surface) {
|
||||
|
||||
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[1]<0) ds::clip[1]=0;
|
||||
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];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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() {
|
||||
if (screen_zoom <= 0) screen_zoom = 1;
|
||||
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);
|
||||
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_RenderSetLogicalSize(mini_ren, screen_width, screen_height);
|
||||
SDL_ShowCursor(screen_cursor?SDL_ENABLE:SDL_DISABLE);
|
||||
//SDL_SetRenderLogicalPresentation(mini_ren, screen_width, screen_height);
|
||||
if (screen_cursor) SDL_ShowCursor(); else SDL_HideCursor();
|
||||
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);
|
||||
log_msg(LOG_OK, "Graphics subsystem initialized\n");
|
||||
}
|
||||
|
||||
void destroyDisplay() {
|
||||
@@ -293,13 +426,15 @@ void destroyDisplay() {
|
||||
}
|
||||
|
||||
void initGamePad() {
|
||||
const int num_joysticks = SDL_NumJoysticks();
|
||||
if (num_joysticks>=1) {
|
||||
int num_joysticks;
|
||||
SDL_JoystickID *joysticks = SDL_GetJoysticks(&num_joysticks);
|
||||
if (joysticks) {
|
||||
for (int i=0; i<num_joysticks; ++i) {
|
||||
if (SDL_IsGameController(i)) {
|
||||
gamepad = SDL_GameControllerOpen(i);
|
||||
if (SDL_GameControllerGetAttached(gamepad) == SDL_TRUE) {
|
||||
SDL_GameControllerEventState(SDL_ENABLE);
|
||||
if (SDL_IsGamepad(joysticks[i])) {
|
||||
gamepad = SDL_OpenGamepad(joysticks[i]);
|
||||
if (SDL_GamepadConnected(gamepad)) {
|
||||
SDL_SetGamepadEventsEnabled(true);
|
||||
log_msg(LOG_OK, "Gamepad found and initialized");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -310,12 +445,22 @@ void initGamePad() {
|
||||
int main(int argc,char*argv[]){
|
||||
|
||||
#ifdef DEBUG
|
||||
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
||||
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
log_msg(LOG_UNSALTED, "MINI v%s\n",MINI_VERSION);
|
||||
#endif
|
||||
|
||||
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_setsource(SOURCE_FOLDER);
|
||||
strcpy(main_lua_file, argv[1]);
|
||||
@@ -328,6 +473,7 @@ int main(int argc,char*argv[]){
|
||||
}
|
||||
}
|
||||
|
||||
//screen_surface = &surfaces.emplace_back();
|
||||
while (!should_quit) {
|
||||
should_exit=false;
|
||||
|
||||
@@ -355,20 +501,19 @@ int main(int argc,char*argv[]){
|
||||
if (fullscreen) screen_fullscreen=strcmp(fullscreen, "true")==0?true:false;
|
||||
const char *cursor = file_getconfigvalue("cursor");
|
||||
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));
|
||||
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD);
|
||||
|
||||
SDL_DisplayMode dm;
|
||||
if (SDL_GetDesktopDisplayMode(0, &dm) != 0)
|
||||
{
|
||||
SDL_Log("SDL_GetDesktopDisplayMode failed: %s", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
desktop_width = dm.w;
|
||||
desktop_height = dm.h;
|
||||
const SDL_DisplayMode *dm = SDL_GetDesktopDisplayMode(SDL_GetPrimaryDisplay());
|
||||
desktop_width = dm->w;
|
||||
desktop_height = dm->h;
|
||||
|
||||
createDisplay();
|
||||
|
||||
@@ -380,23 +525,22 @@ int main(int argc,char*argv[]){
|
||||
|
||||
reinit();
|
||||
initaudio();
|
||||
#ifdef DEBUG
|
||||
debug("MINI v%s\n",MINI_VERSION);
|
||||
#endif
|
||||
|
||||
lua_init(main_lua_file);
|
||||
lua_call_init();
|
||||
|
||||
Uint32 dt=SDL_GetTicks();
|
||||
key_just_pressed = 0;
|
||||
pad_just_pressed = SDL_CONTROLLER_BUTTON_INVALID;
|
||||
pad_just_pressed = SDL_GAMEPAD_BUTTON_INVALID;
|
||||
mouse_just_pressed = 0;
|
||||
mouse_wheel = 0;
|
||||
double_click = false;
|
||||
while(!should_exit) {
|
||||
mouse_wheel = 0;
|
||||
if (update_mode==UPDATE_WAIT) SDL_WaitEvent(NULL);
|
||||
else if (update_mode==UPDATE_TIMEOUT) SDL_WaitEventTimeout(NULL, timeout);
|
||||
while(SDL_PollEvent(&mini_eve)) {
|
||||
if (mini_eve.type == SDL_QUIT) { should_exit=true; should_quit=true; break; }
|
||||
if (mini_eve.type == SDL_KEYDOWN) {
|
||||
if (mini_eve.type == SDL_EVENT_QUIT) { should_exit=true; should_quit=true; break; }
|
||||
if (mini_eve.type == SDL_EVENT_KEY_DOWN) {
|
||||
/*
|
||||
if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F2) {
|
||||
screen_zoom+=2; if (screen_zoom>=10) screen_zoom=2;
|
||||
@@ -412,7 +556,7 @@ int main(int argc,char*argv[]){
|
||||
}
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F12) {
|
||||
if (mini_eve.key.scancode == SDL_SCANCODE_F12) {
|
||||
if (lua_is_playing()) {
|
||||
lua_quit();
|
||||
quitaudio();
|
||||
@@ -420,23 +564,30 @@ int main(int argc,char*argv[]){
|
||||
} else {
|
||||
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;
|
||||
} else {
|
||||
key_just_pressed = mini_eve.key.keysym.scancode;
|
||||
key_just_pressed = mini_eve.key.scancode;
|
||||
}
|
||||
#else
|
||||
key_just_pressed = mini_eve.key.keysym.scancode;
|
||||
key_just_pressed = mini_eve.key.scancode;
|
||||
#endif
|
||||
}
|
||||
if (mini_eve.type == SDL_MOUSEBUTTONUP) {
|
||||
mouse_just_pressed = mini_eve.button.button;
|
||||
if (mini_eve.type == SDL_EVENT_MOUSE_BUTTON_UP) {
|
||||
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;
|
||||
}
|
||||
if (mini_eve.type == SDL_CONTROLLERBUTTONDOWN) {
|
||||
pad_just_pressed = mini_eve.cbutton.button;
|
||||
if (mini_eve.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
|
||||
pad_just_pressed = mini_eve.gbutton.button;
|
||||
}
|
||||
/*if ( (mini_eve.type == SDL_WINDOWEVENT) &&
|
||||
(mini_eve.window.windowID == windowID) &&
|
||||
@@ -447,12 +598,12 @@ int main(int argc,char*argv[]){
|
||||
}*/
|
||||
}
|
||||
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);
|
||||
float mx, my;
|
||||
SDL_RenderWindowToLogical(mini_ren, real_mouse_x, real_mouse_y, &mx, &my);
|
||||
mouse_x = int(mx);
|
||||
mouse_y = int(my);
|
||||
SDL_RenderCoordinatesFromWindow(mini_ren, real_mouse_x, real_mouse_y, &mx, &my);
|
||||
mouse_x = int(mx/screen_zoom);
|
||||
mouse_y = int(my/screen_zoom);
|
||||
//mouse_x /= screen_zoom; mouse_y /= screen_zoom;
|
||||
|
||||
if (SDL_GetTicks()-dt>13) {
|
||||
@@ -466,22 +617,35 @@ int main(int argc,char*argv[]){
|
||||
if (beats>0)beats--;
|
||||
key_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_RenderClear(mini_ren);
|
||||
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]];
|
||||
SDL_UnlockTexture(mini_bak);
|
||||
SDL_RenderCopy(mini_ren, mini_bak, NULL, NULL);
|
||||
SDL_RenderPresent(mini_ren);
|
||||
SDL_RenderTexture(mini_ren, mini_bak, NULL, NULL); //NEW
|
||||
|
||||
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();
|
||||
quitaudio();
|
||||
|
||||
//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;
|
||||
destroyDisplay();
|
||||
SDL_Quit();
|
||||
@@ -491,7 +655,7 @@ int main(int argc,char*argv[]){
|
||||
}
|
||||
|
||||
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 < 0 || x >= dest_surface->w || y < 0 || y >= dest_surface->h) return;
|
||||
DEST(x, y) = color;
|
||||
@@ -499,12 +663,13 @@ void simple_pset(int x, int y, uint8_t color) {
|
||||
|
||||
void cls(uint8_t color) {
|
||||
const uint8_t col = ds::draw_palette[color];
|
||||
for (int y=ds::clip[1]; y<=ds::clip[3];++y) {
|
||||
/*for (int y=ds::clip[1]; y<=ds::clip[3];++y) {
|
||||
for (int x=ds::clip[0]; x<=ds::clip[2];++x) {
|
||||
simple_pset(x,y,col);
|
||||
}
|
||||
}
|
||||
//SDL_memset(dest_surface->p, color, dest_surface->size);
|
||||
}*/
|
||||
|
||||
SDL_memset(dest_surface->p, col, dest_surface->size);
|
||||
}
|
||||
|
||||
void color(uint8_t color) {
|
||||
@@ -540,11 +705,12 @@ uint32_t *loadpal(const char* filename, uint16_t *palsize) {
|
||||
}
|
||||
|
||||
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) {
|
||||
palette[index] = color;
|
||||
palette[index] = color | 0xff000000;
|
||||
}
|
||||
|
||||
uint32_t getcolor(uint8_t index) {
|
||||
@@ -560,7 +726,7 @@ uint8_t gettrans() {
|
||||
}
|
||||
|
||||
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() {
|
||||
@@ -594,7 +760,7 @@ void palt(uint8_t col, bool t) {
|
||||
*/
|
||||
|
||||
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;
|
||||
do_pset(x,y);
|
||||
}
|
||||
@@ -605,7 +771,7 @@ void pset(int x, int y, uint8_t color) {
|
||||
}
|
||||
|
||||
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 < ds::clip[0] || x > ds::clip[2] || y < ds::clip[1] || y > ds::clip[3]) return 0;
|
||||
return DEST(x, y);
|
||||
@@ -675,31 +841,34 @@ void vline(int x, int y0, int y1, uint8_t color) {
|
||||
vline(x, y0, y1);
|
||||
}
|
||||
|
||||
void rect(int x0, int y0, int x1, int y1) {
|
||||
hline(x0, y0, x1);
|
||||
hline(x0, y1, x1);
|
||||
vline(x0, y0, y1);
|
||||
vline(x1, y0, y1);
|
||||
void rect(int x, int y, int w, int h) {
|
||||
int x1 = w+x-1;
|
||||
int y1 = h+y-1;
|
||||
hline(x, y, x1);
|
||||
hline(x, y1, x1);
|
||||
vline(x, y, y1);
|
||||
vline(x1, y, y1);
|
||||
}
|
||||
|
||||
void rect(int x0, int y0, int x1, int y1, uint8_t color) {
|
||||
void rect(int x, int y, int w, int h, uint8_t color) {
|
||||
ds::pen_color = color;
|
||||
rect(x0, y0, x1, y1);
|
||||
rect(x, y, w, h);
|
||||
}
|
||||
|
||||
void rectfill(int x0, int y0, int x1, int y1) {
|
||||
for (int y=y0; y<=y1; ++y) hline(x0, y, x1);
|
||||
void rectfill(int x, int y, int w, int h) {
|
||||
int x1 = w+x-1;
|
||||
int y1 = h+y-1;
|
||||
for (int i=y; i<=y1; ++i) hline(x, i, x1);
|
||||
}
|
||||
|
||||
void rectfill(int x0, int y0, int x1, int y1, uint8_t color) {
|
||||
void rectfill(int x, int y, int w, int h, uint8_t color) {
|
||||
ds::pen_color = color;
|
||||
rectfill(x0, y0, x1, y1);
|
||||
rectfill(x, y, w, h);
|
||||
}
|
||||
|
||||
void fillp(uint16_t pat, bool transparent) {
|
||||
ds::fill_trans = true; //transparent;
|
||||
ds::fill_pattern = pat;
|
||||
do_pset=(pat==0xffff?pset_fast:pset_pattern);
|
||||
}
|
||||
|
||||
void print_symbol(char sym, int x, int y) {
|
||||
@@ -828,6 +997,77 @@ void circfill(int x, int y, uint8_t r, uint8_t color) {
|
||||
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) {
|
||||
pset((xc+x)*xf, (yc+y)*yf);
|
||||
pset((xc-x)*xf, (yc+y)*yf);
|
||||
@@ -882,11 +1122,13 @@ void ovalfill(int x0, int y0, int x1, int y1, uint8_t color) {
|
||||
}
|
||||
|
||||
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;
|
||||
return SOURCE(x, 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;
|
||||
SOURCE(x, y) = ds::pen_color;
|
||||
}
|
||||
@@ -897,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) {
|
||||
if (!source_surface) return;
|
||||
int tx = (n%(source_surface->w >> 3))<<3;
|
||||
int ty = (n/(source_surface->w >> 3))<<3;
|
||||
int tw = w*8 - 1;
|
||||
@@ -1022,23 +1265,25 @@ void tvline(int x, int y0, int y1, float mx, float my, float mdx, float mdy) {
|
||||
}
|
||||
|
||||
uint8_t mget(int celx, int cely) {
|
||||
if (!map_surface) return 0;
|
||||
if (celx < 0 || celx > (map_surface->w-1) || cely < 0 || cely > (map_surface->h-1)) return 0;
|
||||
return TILES(celx, cely);
|
||||
}
|
||||
|
||||
void mset(int celx, int cely, uint8_t snum) {
|
||||
if (!map_surface) return;
|
||||
if (celx < 0 || celx > (map_surface->w-1) || cely < 0 || cely > (map_surface->h-1)) return;
|
||||
TILES(celx, cely) = snum;
|
||||
}
|
||||
|
||||
void map() { //int celx, int cely, int sx, int sy, uint8_t celw, uint8_t celh, uint8_t layer) {
|
||||
if (map_surface==NULL) return;
|
||||
uint8_t celw = map_surface->w >> 3;
|
||||
uint8_t celh = map_surface->h >> 3;
|
||||
int celw = map_surface->w;// >> 3;
|
||||
int celh = map_surface->h;// >> 3;
|
||||
int celx = 0;
|
||||
int cely = 0;
|
||||
//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<0) {
|
||||
int diff = -sx/8;
|
||||
@@ -1052,10 +1297,15 @@ void map() { //int celx, int cely, int sx, int sy, uint8_t celw, uint8_t celh, u
|
||||
celh -= diff;
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1086,7 +1336,7 @@ bool anykey() {
|
||||
|
||||
bool pad(int8_t i) {
|
||||
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) {
|
||||
@@ -1103,11 +1353,11 @@ int wpad() {
|
||||
}
|
||||
|
||||
int mousex() {
|
||||
return mouse_x;
|
||||
return mouse_x-ds::origin[0];
|
||||
}
|
||||
|
||||
int mousey() {
|
||||
return mouse_y;
|
||||
return mouse_y-ds::origin[1];
|
||||
}
|
||||
|
||||
int mwheel() {
|
||||
@@ -1115,13 +1365,28 @@ int mwheel() {
|
||||
}
|
||||
|
||||
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) {
|
||||
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() {
|
||||
return float(SDL_GetTicks())/1000.0f;
|
||||
}
|
||||
@@ -1139,6 +1404,10 @@ int rnd(int x) {
|
||||
return rand()%x;
|
||||
}
|
||||
|
||||
int getfps() {
|
||||
return fps;
|
||||
}
|
||||
|
||||
void playmusic(const char *filename, const int loop) {
|
||||
int size;
|
||||
char *buffer = file_getfilebuffer(filename, size);
|
||||
@@ -1169,6 +1438,18 @@ float musicpos()
|
||||
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 size;
|
||||
char *buffer = file_getfilebuffer(filename, size);
|
||||
@@ -1196,6 +1477,17 @@ void stopsound(int 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() {
|
||||
return screen_zoom;
|
||||
}
|
||||
@@ -1232,7 +1524,7 @@ bool getcursor() {
|
||||
|
||||
void setcursor(const bool 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) {
|
||||
@@ -1252,7 +1544,42 @@ void setupdatemode(const int value, const int t) {
|
||||
timeout = t;
|
||||
}
|
||||
|
||||
int getupdatemode() {
|
||||
return update_mode;
|
||||
}
|
||||
|
||||
void exit() {
|
||||
should_exit = 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");
|
||||
}
|
||||
|
||||
43
mini.h
43
mini.h
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "version.h"
|
||||
|
||||
@@ -112,13 +112,20 @@
|
||||
#define KEY_RALT 230
|
||||
#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();
|
||||
|
||||
int scrw();
|
||||
int scrh();
|
||||
|
||||
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 freesurf(uint8_t surface);
|
||||
int surfw(uint8_t surface);
|
||||
@@ -127,8 +134,14 @@ int surfh(uint8_t surface);
|
||||
void setdest(uint8_t surface);
|
||||
void setsource(uint8_t surface);
|
||||
void setmap(uint8_t surface);
|
||||
uint8_t getdest();
|
||||
uint8_t getsource();
|
||||
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 color(uint8_t color=6);
|
||||
void bcolor(uint8_t color=0);
|
||||
@@ -142,6 +155,7 @@ uint8_t gettrans();
|
||||
void subpal(uint8_t index, uint8_t color);
|
||||
void reset_subpal();
|
||||
|
||||
void set_draw_mode(uint8_t mode);
|
||||
void pset(int x, int y);
|
||||
void pset(int x, int y, uint8_t color);
|
||||
|
||||
@@ -156,11 +170,11 @@ void hline(int x0, int y, int x1, uint8_t color);
|
||||
void vline(int x, int y0, int y1);
|
||||
void vline(int x, int y0, int y1, uint8_t color);
|
||||
|
||||
void rect(int x0, int y0, int x1, int y1);
|
||||
void rect(int x0, int y0, int x1, int y1, uint8_t color);
|
||||
void rect(int x, int y, int w, int h);
|
||||
void rect(int x, int y, int w, int h, uint8_t color);
|
||||
|
||||
void rectfill(int x0, int y0, int x1, int y1);
|
||||
void rectfill(int x0, int y0, int x1, int y1, uint8_t color);
|
||||
void rectfill(int x, int y, int w, int h);
|
||||
void rectfill(int x, int y, int w, int h, uint8_t color);
|
||||
|
||||
void fillp(uint16_t pat, bool transparent = false);
|
||||
|
||||
@@ -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, 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, uint8_t color);
|
||||
|
||||
@@ -215,13 +235,15 @@ int mousey();
|
||||
int mwheel();
|
||||
bool mbtn(uint8_t i);
|
||||
bool mbtnp(uint8_t i);
|
||||
bool doubleclick();
|
||||
void mdiscard();
|
||||
bool minside(int x, int y, int w, int h);
|
||||
|
||||
float time();
|
||||
bool beat(int16_t i);
|
||||
|
||||
int rnd(int x);
|
||||
|
||||
#define debug printf
|
||||
int getfps();
|
||||
|
||||
void playmusic(const char *filename, const int loop=-1);
|
||||
void pausemusic();
|
||||
@@ -229,11 +251,15 @@ void resumemusic();
|
||||
void stopmusic(const int t=1000);
|
||||
void musicpos(float value);
|
||||
float musicpos();
|
||||
void enablemusic(const bool value);
|
||||
const bool ismusicenabled();
|
||||
|
||||
int loadsound(const char *filename);
|
||||
void freesound(int soundfile);
|
||||
int playsound(int soundfile, const int volume=-1);
|
||||
void stopsound(int soundchannel);
|
||||
void enablesound(const bool value);
|
||||
const bool issoundenabled();
|
||||
|
||||
int getzoom();
|
||||
void setzoom(const int value);
|
||||
@@ -251,5 +277,6 @@ const char *configfolder();
|
||||
#define UPDATE_WAIT 1
|
||||
#define UPDATE_TIMEOUT 2
|
||||
void setupdatemode(const int value, const int t=0);
|
||||
int getupdatemode();
|
||||
|
||||
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
|
||||
|
||||
#define MINI_VERSION "1.0 RC1"
|
||||
#define MINI_VERSION "1.4.1"
|
||||
|
||||
@@ -3,183 +3,184 @@
|
||||
---@class mini
|
||||
mini = {}
|
||||
|
||||
---@class surface
|
||||
surface = {}
|
||||
---@class surf
|
||||
surf = {}
|
||||
|
||||
---@param w number
|
||||
---@param h number
|
||||
---@return number surface
|
||||
---Create new surface specifying width and height
|
||||
function surface.new(w, h) end
|
||||
function surf.new(w, h) end
|
||||
|
||||
---@param filename string
|
||||
---@return number 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 filename string
|
||||
---@optional palette table
|
||||
---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
|
||||
---Free the specified surface
|
||||
function surface.free(surface) end
|
||||
function surf.free(surface) end
|
||||
|
||||
---@param surface number
|
||||
---@return number w, number h
|
||||
---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
|
||||
---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
|
||||
---Erase the current target surface with 'color'
|
||||
function surface.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
|
||||
function surf.cls(color) end
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@return number color
|
||||
---Get color of pixel (x,y) in the current target
|
||||
function surface.getPixel(x, y) end
|
||||
---Get color of pixel (x,y) on the source surface.
|
||||
function surf.pixel(x, y) end
|
||||
|
||||
---@class tilemap
|
||||
tilemap = {}
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param color number
|
||||
---Set the color for pixel (x,y) on the target surface.
|
||||
function surf.pixel(x, y, color) end
|
||||
|
||||
---@class map
|
||||
map = {}
|
||||
|
||||
---@param filename string
|
||||
---@return number surface
|
||||
---Load a tilemap from a file and set it as current tilemap
|
||||
function tilemap.load(filename) end
|
||||
|
||||
---@param filename string
|
||||
---Save the current tilemap in a file
|
||||
function tilemap.save(filename) end
|
||||
---Get tilemaps current surface
|
||||
function map.surf() end
|
||||
|
||||
---@param surface number
|
||||
---Set surface as the current tilemap
|
||||
function tilemap.set(surface) end
|
||||
function map.surf(surface) end
|
||||
|
||||
---Draw the tilemap
|
||||
function tilemap.draw() end
|
||||
---Draw the tilemap, using the source surface as tile graphics source
|
||||
function map.draw() end
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@return number color
|
||||
---@return number tile
|
||||
---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 y number
|
||||
---@param tile number
|
||||
---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
|
||||
palette = {}
|
||||
---@class pal
|
||||
pal = {}
|
||||
|
||||
---@param filename string
|
||||
---@return table pal
|
||||
---Load a palette from a GIF file and return it
|
||||
function palette.load(filename) end
|
||||
function pal.load(filename) end
|
||||
|
||||
---@param pal table
|
||||
---Set a specified palette as the current palette
|
||||
function palette.set(pal) end
|
||||
function pal.set(pal) end
|
||||
|
||||
---@param index number
|
||||
---@return number r, number g, number b
|
||||
---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 r number
|
||||
---@param g number
|
||||
---@param b number
|
||||
---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
|
||||
---Set the index specified as transparent color
|
||||
function palette.setTransparent(index) end
|
||||
|
||||
---@class subpalette
|
||||
subpalette = {}
|
||||
function pal.trans(index) end
|
||||
|
||||
---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 color number
|
||||
---Set the specified subpalette index to the specified palette index
|
||||
function subpalette.set(index, color) end
|
||||
|
||||
---@param index number
|
||||
---Reset the specified subpalette index to its default palette index
|
||||
function subpalette.reset(index) end
|
||||
function pal.subpal(index, color) end
|
||||
|
||||
---@param index1 number
|
||||
---@param index2 number
|
||||
---@param color number
|
||||
---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
|
||||
---@param index2 number
|
||||
---Reset the specified subpalette range to its default palette index
|
||||
function subpalette.resetRange(index1, index2) end
|
||||
---@class view
|
||||
view = {}
|
||||
|
||||
---@class viewport
|
||||
viewport = {}
|
||||
---reset the current clipping region to the entire window
|
||||
function view.clip() end
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w number
|
||||
---@param h number
|
||||
---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
|
||||
function viewport.resetClipping() end
|
||||
---@return number x, number y
|
||||
---Get the current origin position
|
||||
function view.origin() end
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---Set the current origin position
|
||||
function viewport.setOrigin(x, y) end
|
||||
|
||||
---@return number x, number y
|
||||
---Get the current origin position
|
||||
function viewport.getOrigin() end
|
||||
function view.origin(x, y) end
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@return number x, number y
|
||||
---Convert screen position to viewport position
|
||||
function viewport.toLocal(x, y) end
|
||||
function view.tolocal(x, y) end
|
||||
|
||||
|
||||
---@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 = {}
|
||||
|
||||
---@param x1 number
|
||||
@@ -204,21 +205,21 @@ function draw.hline(x1, y, x2, color) end
|
||||
---Draw a vertical line from (x,y1) to (x,y2) with the givencolor
|
||||
function draw.vline(x, y1, y2, color) end
|
||||
|
||||
---@param x1 number
|
||||
---@param y1 number
|
||||
---@param x2 number
|
||||
---@param y2 number
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w number
|
||||
---@param h number
|
||||
---@param color number
|
||||
---Draw the ouline of a rectangle from (x1,y1) to (x2,y2) with the given color
|
||||
function draw.rect(x1, y1, x2, y2, color) end
|
||||
---Draw the ouline of a rectangle at (x,y) of size (w,h) with the given color
|
||||
function draw.rect(x, y, w, h, color) end
|
||||
|
||||
---@param x1 number
|
||||
---@param y1 number
|
||||
---@param x2 number
|
||||
---@param y2 number
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w number
|
||||
---@param h number
|
||||
---@param color number
|
||||
---Draw a filled rectangle from (x1,y1) to (x2,y2) with the given color
|
||||
function draw.rectFill(x1, y1, x2, y2, color) end
|
||||
---Draw a filled rectangle at (x,y) of size (w,h) with the given color
|
||||
function draw.rectf(x, y, w, h, color) end
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
@@ -232,7 +233,25 @@ function draw.circ(x, y, r, color) end
|
||||
---@param r number
|
||||
---@param color number
|
||||
---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 y1 number
|
||||
@@ -248,13 +267,15 @@ function draw.oval(x1, y1, x2, y2, color) end
|
||||
---@param y2 number
|
||||
---@param color number
|
||||
---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
|
||||
---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 sy number
|
||||
---@param sw number
|
||||
@@ -266,12 +287,11 @@ function draw.setPattern(pattern) end
|
||||
---@optional boolean flip_x
|
||||
---@optional boolean flip_y
|
||||
---@optional boolean invert
|
||||
---Blit the region starting at (sx,sy) and size (sw, sh) from the 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,
|
||||
---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 sy number
|
||||
---@param sw number
|
||||
@@ -279,9 +299,9 @@ function draw.surface(surface, sx, sy, sw, sh, dx, dy, dw, dh, flip_x, flip_y, i
|
||||
---@param x number
|
||||
---@param y 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
|
||||
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 x number
|
||||
@@ -290,6 +310,46 @@ function draw.surfaceRotated(surface, sx, sy, sw, sh, x, y, a) end
|
||||
---Draw text to (x,y) using the specified color
|
||||
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
|
||||
music = {}
|
||||
|
||||
@@ -297,6 +357,11 @@ music = {}
|
||||
---Load and play the song in the specified OGG file
|
||||
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
|
||||
function music.pause() end
|
||||
|
||||
@@ -306,13 +371,22 @@ function music.resume() end
|
||||
---Stop the currently playing song
|
||||
function music.stop() end
|
||||
|
||||
---@param pos number
|
||||
---Set the playing position of the currently loaded song
|
||||
function music.setPosition(pos) end
|
||||
|
||||
---@return number pos
|
||||
---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
|
||||
sound = {}
|
||||
@@ -331,155 +405,272 @@ function sound.free(snd) end
|
||||
---Play the sound specified, returns the channel in which it's playing
|
||||
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
|
||||
---Stop the channel specified
|
||||
function sound.stop(chl) end
|
||||
|
||||
---@class system
|
||||
system = {}
|
||||
---@return boolean value
|
||||
---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)
|
||||
function system.getTime() end
|
||||
function sys.time() end
|
||||
|
||||
---@param bts number
|
||||
---Set number of frames between beats
|
||||
function system.setBeat(bts) end
|
||||
---@param offset number
|
||||
---Reset chrono time (with offset in seconds) (with decimals)
|
||||
function sys.chrono(offset) end
|
||||
|
||||
---@return number
|
||||
---@---Get chrono time since last chrono reset in seconds (with decimals)
|
||||
function sys.chrono() end
|
||||
|
||||
---@return boolean
|
||||
---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
|
||||
function system.updateAtFullSpeed() end
|
||||
|
||||
---The game will call mini.update only when a keyboard, mouse or pad event fires
|
||||
function system.updateOnlyOnEvents() end
|
||||
---@param bts number
|
||||
---Set number of frames between beats
|
||||
function sys.beat(bts) end
|
||||
|
||||
---@param mode number
|
||||
---@param ms number
|
||||
---The game will call mini.update on events or after the milliseconds specified passed
|
||||
function system.updateOnEventsAndTimeout(ms) end
|
||||
---Sets the update mode.
|
||||
---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
|
||||
---Gets a table with the name of each file in the data directory
|
||||
function system.getFilesInDataDirectory() end
|
||||
---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 '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
|
||||
function system.quit() end
|
||||
function sys.quit() end
|
||||
|
||||
---@class window
|
||||
window = {}
|
||||
---@return number
|
||||
---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
|
||||
---Set the window zoom
|
||||
function window.setZoom(value) end
|
||||
function win.zoom(value) end
|
||||
|
||||
---@return number value
|
||||
---Get the window zoom
|
||||
function window.getZoom() end
|
||||
function win.zoom() end
|
||||
|
||||
---@param value boolean
|
||||
---Specifies if the window must display at fullscreen or not
|
||||
function window.setFullscreen(value) end
|
||||
function win.fullscreen(value) end
|
||||
|
||||
---@return boolean value
|
||||
---Returns if the window is at fullscreen or not
|
||||
function window.getFullscreen() end
|
||||
function win.fullscreen() end
|
||||
|
||||
---@param value boolean
|
||||
---Specifies if the cursor must be visible or not
|
||||
function window.showCursor(value) end
|
||||
function win.cursor(value) end
|
||||
|
||||
---@return number w, number h
|
||||
---Returns the current window size
|
||||
function window.getResolution() end
|
||||
function win.res() end
|
||||
|
||||
---@param w number
|
||||
---@param h number
|
||||
---Sets the window size
|
||||
function window.setResolution(w, h) end
|
||||
function win.res(w, h) end
|
||||
|
||||
|
||||
---@class config
|
||||
config = {}
|
||||
|
||||
---@param key string
|
||||
---@param value string
|
||||
---@param value any
|
||||
---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
|
||||
---@return string value
|
||||
---Gets the value of a key in the configuration file
|
||||
function config.getKey(key) end
|
||||
function config.key(key) end
|
||||
|
||||
---@return string value
|
||||
---Returns the folder in which the configuration file resides
|
||||
function config.getConfigFolder() end
|
||||
function config.folder() end
|
||||
|
||||
|
||||
---@class mouse
|
||||
---@field mouse.LEFT number
|
||||
---@field mouse.MIDDLE number
|
||||
---@field mouse.RIGHT number
|
||||
|
||||
mouse = {}
|
||||
|
||||
---@return number x, number y
|
||||
---Returns the current position of the mouse
|
||||
function mouse.getPos() end
|
||||
function mouse.pos() end
|
||||
|
||||
---@return number value
|
||||
---Returns the value of the mouse wheel
|
||||
function mouse.getWheel() end
|
||||
function mouse.wheel() end
|
||||
|
||||
---@param btn number
|
||||
---@return boolean
|
||||
---Returns whether the specified mouse button is down
|
||||
function mouse.buttonDown(btn) end
|
||||
function mouse.down(btn) end
|
||||
|
||||
---@param btn number
|
||||
---@return boolean
|
||||
---Returns whether the specified mouse button has just been pressed
|
||||
function mouse.buttonPressed(btn) end
|
||||
function mouse.press(btn) end
|
||||
|
||||
---@class keyboard
|
||||
keyboard = {}
|
||||
---@return boolean
|
||||
---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
|
||||
---@return boolean
|
||||
---Returns whether the specified keyboard key is down
|
||||
function keyboard.keyDown(key) end
|
||||
function key.down(key) end
|
||||
|
||||
---@return number
|
||||
---Returns which keyboard key has just been pressed
|
||||
function keyboard.keyPressed() end
|
||||
function key.press() end
|
||||
|
||||
---@param key number
|
||||
---@return boolean
|
||||
---Returns whether the specified keyboard key has just been pressed
|
||||
function keyboard.keyPressed(key) end
|
||||
function key.press(key) end
|
||||
|
||||
---@return boolean
|
||||
---Returns whether any keyboard key has just been pressed
|
||||
function keyboard.anyKeyPressed() end
|
||||
function key.any() end
|
||||
|
||||
|
||||
---@class gamepad
|
||||
gamepad = {}
|
||||
---@class pad
|
||||
---@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
|
||||
---@return boolean
|
||||
---Returns whether the specified gamepad button is down
|
||||
function gamepad.buttonDown(btn) end
|
||||
function pad.down(btn) end
|
||||
|
||||
---@return number
|
||||
---Returns which gamepad button has just been pressed
|
||||
function gamepad.buttonPressed() end
|
||||
function pad.press() end
|
||||
|
||||
---@param btn number
|
||||
---@return boolean
|
||||
---Returns whether the specified gamepad button has just been pressed
|
||||
function gamepad.buttonPressed(btn) end
|
||||
function pad.press(btn) end
|
||||
|
||||
---@return boolean
|
||||
---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
|
||||
---@field key.UNKNOWN number
|
||||
@@ -509,16 +700,16 @@ function gamepad.anybuttonPressed() end
|
||||
---@field key.X number
|
||||
---@field key.Y number
|
||||
---@field key.Z number
|
||||
---@field key.1 number
|
||||
---@field key.2 number
|
||||
---@field key.3 number
|
||||
---@field key.4 number
|
||||
---@field key.5 number
|
||||
---@field key.6 number
|
||||
---@field key.7 number
|
||||
---@field key.8 number
|
||||
---@field key.9 number
|
||||
---@field key.0 number
|
||||
---@field key.N1 number
|
||||
---@field key.N2 number
|
||||
---@field key.N3 number
|
||||
---@field key.N4 number
|
||||
---@field key.N5 number
|
||||
---@field key.N6 number
|
||||
---@field key.N7 number
|
||||
---@field key.N8 number
|
||||
---@field key.N9 number
|
||||
---@field key.N0 number
|
||||
---@field key.RETURN number
|
||||
---@field key.ESCAPE number
|
||||
---@field key.BACKSPACE number
|
||||
@@ -589,7 +780,7 @@ function gamepad.anybuttonPressed() end
|
||||
---@field key.RSHIFT number
|
||||
---@field key.RALT number
|
||||
---@field key.RGUI number
|
||||
key = {}
|
||||
|
||||
key.UNKNOWN = 0
|
||||
key.A = 4
|
||||
key.B = 5
|
||||
@@ -697,52 +888,3 @@ key.RCTRL = 228
|
||||
key.RSHIFT = 229
|
||||
key.RALT = 230
|
||||
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