You've already forked rdsspy-lua-host
mirror of
https://github.com/KubaPro010/rdsspy-lua-host.git
synced 2026-02-27 02:45:21 +01:00
Compare commits
9 Commits
ebfb628ab3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
67f0941dbd
|
|||
|
41d9bba1d1
|
|||
|
1d4cf16399
|
|||
|
|
38ae640f97 | ||
|
|
6245cdc66d | ||
|
|
b2130441cf | ||
|
7bd8970434
|
|||
|
71e2d4c863
|
|||
|
19a5483acb
|
13
Makefile
13
Makefile
@@ -2,20 +2,11 @@ liblua:
|
||||
gcc -c lua/*.c
|
||||
ar rcs liblua *.o
|
||||
rm *.o
|
||||
liblua-native:
|
||||
gcc -c lua/*.c -march=native
|
||||
ar rcs liblua.native *.o
|
||||
rm *.o
|
||||
|
||||
build: liblua
|
||||
gcc -O2 -shared -static -o luahost-x86.dll plugin.c liblua -lgdi32 -luser32 -lshell32 \
|
||||
gcc -O2 -shared -static -o luahost.dll src/*.c liblua -lgdi32 -luser32 -lshell32 -Ilua \
|
||||
-Wl,--add-stdcall-alias \
|
||||
-ffunction-sections -fdata-sections
|
||||
|
||||
build-native: liblua
|
||||
gcc -O2 -shared -static -o luahost.dll plugin.c liblua.native -lgdi32 -luser32 -lshell32 -march=native \
|
||||
-Wl,--add-stdcall-alias \
|
||||
-ffunction-sections -fdata-sections
|
||||
|
||||
install: build-native
|
||||
install: build
|
||||
cp luahost.dll "/c/Program Files (x86)/RDS Spy/plugins"
|
||||
21
README.md
21
README.md
@@ -1,19 +1,26 @@
|
||||
# Lua host
|
||||
This is an WIP lua host for rds spy, a plugin
|
||||
|
||||
Compile this under MINGW32, not 64, RDS Spy lives in the past where men who couldn't count to 4294967295 still walked the planet
|
||||
Compile this under MINGW32, not 64, RDS Spy lives in the past where men who couldn't count to 4294967296 in a CPU word still walked the planet
|
||||
|
||||
Project stared 1st of January, 2026 (or 7 haha)
|
||||
Project started 1st of January, 2026
|
||||
|
||||
Aside from all that, this it loads and executes the script at "%LOCALAPPDATA%\RDS Spy\script.lua", with the api in the `plugin.lua` meta-file
|
||||
Aside from all that, this loads and executes the script at "%LOCALAPPDATA%\RDS Spy\script.lua", with the api in the `plugin.lua` meta-file
|
||||
|
||||
## Why?
|
||||
|
||||
Ask Jan Kolar why his funny little rds decoder doesn't have Enchanced RT (excluding the 0x6552 to ERT mapping of course)
|
||||
Ask Jan Kolar why his funny little rds decoder doesn't have Enchanced RT (excluding the 0x6552 to ERT mapping of course). Yes, no eRT decoding is really why is this, because why decode RDS in C (or even delphi ughhh) when you can just do it in lua!
|
||||
|
||||
Also RDS Surveyor doesn't take line-in MPX input
|
||||
|
||||
# Scripts
|
||||
Inside of the examples folder you have `basic.lua` which mostly replaced the `basic.dll` plugin in RDS Spy
|
||||
|
||||
Note that you can double click on the buttons, if you try it
|
||||
Inside of the examples folder you have `basic.lua` which mostly replaces the `basic.dll` plugin in RDS Spy
|
||||
|
||||
Another note is that on menu 0 you have the PI and PS in a large font, why? democracy? or something like that ([forum post](https://pira.cz/forum/index.php?topic=1124.0))
|
||||
I have also included `large_pi.lua`, while `basic.lua` already shows the PS and PI on a large font, this does only the large PI and PS but in a even larger font. event 1 toggles stickyness
|
||||
|
||||
# Console
|
||||
|
||||
You have a console window generated by this plugin which has as of now 8 buttons where the first if you double-click the "Reload" button, I don't know what it does but maybe it reloads the script?
|
||||
|
||||
The other 7 send events to the Lua script, you can use this with the console mode:true to display diffrent "menus" on the console, double clicking also sends a unique event
|
||||
@@ -93,7 +93,7 @@ local pi_ecc_to_country = {
|
||||
e1 = {
|
||||
"Encoder fault", -- 0
|
||||
"Hellenic Republic (Greece)", -- 1
|
||||
"Libya", -- 2
|
||||
"Republic of Cyprus", -- 2
|
||||
"Republic of San Marino", -- 3
|
||||
"Swiss Confederation", -- 4
|
||||
"Hashemite Kingdom of Jordan", -- 5
|
||||
@@ -104,7 +104,7 @@ local pi_ecc_to_country = {
|
||||
"United Kingdom of Great Britain and Northern Ireland (Gibraltar)", -- 10 A
|
||||
"Republic of Iraq", -- 11 B
|
||||
"United Kingdom of Great Britain and Northern Ireland", -- 12 C
|
||||
"Unknown", -- 13 D
|
||||
"Libya", -- 13 D
|
||||
"Romania", -- 14 E
|
||||
"Republic of France", -- 15 F wish i could nuke this
|
||||
},
|
||||
@@ -180,6 +180,24 @@ local pi_ecc_to_country = {
|
||||
"Unknown", -- 14 E
|
||||
"Unknown", -- 15 F
|
||||
},
|
||||
e6 = {
|
||||
"Encoder fault", -- 0
|
||||
"Unknown", -- 1
|
||||
"Unknown", -- 2
|
||||
"Republic of West Poland", -- 3 coming soon
|
||||
"Unknown", -- 4
|
||||
"Unknown", -- 5
|
||||
"Unknown", -- 6
|
||||
"Unknown", -- 7
|
||||
"Unknown", -- 8
|
||||
"Unknown", -- 9
|
||||
"Unknown", -- 10 A
|
||||
"Unknown", -- 11 B
|
||||
"Unknown", -- 12 C
|
||||
"Unknown", -- 13 D
|
||||
"Unknown", -- 14 E
|
||||
"Unknown", -- 15 F
|
||||
},
|
||||
a0 = {
|
||||
"Encoder fault", -- 0
|
||||
"United States of America", -- 1
|
||||
@@ -215,7 +233,7 @@ local pi_ecc_to_country = {
|
||||
"Canada", -- 12 C
|
||||
"Canada", -- 13 D
|
||||
"Cananda", -- 14 E
|
||||
"Greenland", -- 15 F
|
||||
"Kingdom of Denmark (Greenland)", -- 15 F
|
||||
},
|
||||
a2 = {
|
||||
"Encoder fault", -- 0
|
||||
@@ -289,6 +307,24 @@ local pi_ecc_to_country = {
|
||||
"United Mexican States", -- 14 E
|
||||
"United Mexican States", -- 15 F
|
||||
},
|
||||
a6 = {
|
||||
"Encoder fault", -- 0
|
||||
"Unknown", -- 1
|
||||
"Unknown", -- 2
|
||||
"Unknown", -- 3
|
||||
"Unknown", -- 4
|
||||
"Unknown", -- 5
|
||||
"Unknown", -- 6
|
||||
"Unknown", -- 7
|
||||
"Unknown", -- 8
|
||||
"Unknown", -- 9
|
||||
"Unknown", -- 10 A
|
||||
"Unknown", -- 11 B
|
||||
"Unknown", -- 12 C
|
||||
"Unknown", -- 13 D
|
||||
"Unknown", -- 14 E
|
||||
"Republic of France (Saint Pierre and Miquelon)", -- 15 F
|
||||
},
|
||||
d0 = {
|
||||
"Encoder fault", -- 0
|
||||
"Republic of Cameroon", -- 1
|
||||
@@ -548,7 +584,7 @@ local function render_menu()
|
||||
out = out .. string.format("%s - %s\r\n\t", rtp_types[rtp_type2+1], current_rt:sub(rtp_start2+1, rtp_start2+rtp_len2+1))
|
||||
else out = out .. "-\r\n\t-\r\n\t" end
|
||||
out = out .. string.format("RAW %d,%d,%d,%d,%d,%d\r\n", rtp_type1, rtp_start1, rtp_len1, rtp_type2, rtp_start2, rtp_len2)
|
||||
elseif current_menu == 3 then
|
||||
elseif current_menu == 3 and not menu_extended then
|
||||
local pi_code = tonumber(db.read_value("PI") or "0000", 16)
|
||||
local country_id = (pi_code & 0xF000) >> 12
|
||||
local coverage_id = (pi_code & 0xF00) >> 8
|
||||
@@ -563,14 +599,14 @@ local function render_menu()
|
||||
out = out .. string.format("Coverage: %s\r\n", pi_coverage[coverage_id+1])
|
||||
out = out .. string.format("Country: %s (%X)\r\n\r\n", country_name, ecc)
|
||||
|
||||
out = out .. string.format("ERT: %s\r\n\r\n", ert_display)
|
||||
|
||||
local oda_string = ""
|
||||
for grp, data in pairs(odas) do
|
||||
local ver_char = (data.version == 0) and "A" or "B"
|
||||
oda_string = oda_string .. string.format("%d%s - %04X | ", grp, ver_char, data.aid)
|
||||
end
|
||||
out = out .. string.format("ODA: %s\r\n", oda_string:sub(1, #oda_string-2))
|
||||
elseif current_menu == 3 and menu_extended then
|
||||
out = out .. string.format("ERT: %s\r\n\r\n", ert_display)
|
||||
elseif current_menu == 4 then
|
||||
if time_display_offset > 2 then out = out .. string.format("RDS-System time offset: %d seconds\r\n", time_display_offset)
|
||||
else out = out .. string.format("RDS-System time offset: ~0\r\n") end
|
||||
@@ -596,6 +632,7 @@ function event(event)
|
||||
current_menu = event
|
||||
end
|
||||
render_menu()
|
||||
last_render_hash = 0
|
||||
end
|
||||
|
||||
local function ternary(cond, a, b)
|
||||
@@ -935,4 +972,4 @@ function group(stream, b_corr, a, b, c, d, time)
|
||||
end
|
||||
render_menu()
|
||||
end
|
||||
render_menu()
|
||||
render_menu()
|
||||
|
||||
20
examples/large_pi.lua
Normal file
20
examples/large_pi.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
set_console_mode(true)
|
||||
set_font_size(148)
|
||||
|
||||
local last_pi = "----"
|
||||
local last_ps = "--------"
|
||||
function group(...)
|
||||
local pi = db.read_value("PI") or "----"
|
||||
local ps = db.read_value("PS") or "--------"
|
||||
if last_pi ~= pi or last_ps ~= ps then
|
||||
set_console(string.format("%s\r\n%s", pi, ps))
|
||||
last_pi = pi
|
||||
last_ps = ps
|
||||
end
|
||||
end
|
||||
|
||||
function event(event)
|
||||
if event == 1 then
|
||||
set_window_stick(not get_window_stick())
|
||||
end
|
||||
end
|
||||
@@ -71,7 +71,7 @@ function db.read_record(index) end
|
||||
---@param value string
|
||||
function db.add_value(key, value) end
|
||||
|
||||
function db.reset_values(key, value) end
|
||||
function db.reset_values() end
|
||||
|
||||
---@return integer
|
||||
function db.count_records(key, value) end
|
||||
|
||||
227
src/api.c
Normal file
227
src/api.c
Normal file
@@ -0,0 +1,227 @@
|
||||
#include "api.h"
|
||||
|
||||
static const unsigned char EBU[127] = {
|
||||
0xE1, 'a', 0xE9, 'e', 0xED, 'i', 0xF3, 'o', 0xFA, 'u', 'N', 0xC7, 0xAA, 0xDF, 'I', 0x00,
|
||||
0xE2, 0xE4, 'e', 0xEB, 0xEE, 'i', 0xF4, 0xF6, 'u', 0xFC, 'n', 0xE7, 0xBA, 0x00, 'i', 0x00,
|
||||
0x00, 0x00, 0xA9, 0x89, 0x00, 0xEC, 0xF2, 0xF5, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xB1, 'I', 0xF1, 0xFB, 0xB5, '?', 0xF7, 0xB0, 0x00, 0x00, 0x00, 0xA7, 0x00,
|
||||
0xC1, 'A', 0xC9, 'E', 0xCD, 'I', 0xD3, 'O', 0xDA, 'U', 0xD8, 0xC8, 0x8A, 0x8E, 0xD0, 'L',
|
||||
0xC2, 0xC4, 'E', 0xCB, 0xCE, 'I', 0xD4, 0xD6, 'U', 0xDC, 0xF8, 0xE8, 0x9A, 0x9E, 0xF0, 'l',
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC6, 0x8C, 0x8F, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE6, 0x9C, 0x9F, 0x00
|
||||
};
|
||||
|
||||
unsigned char CharConv(unsigned char Ch) {
|
||||
if (Ch >= 128 && Ch < 255) {
|
||||
unsigned char conv = EBU[Ch - 128];
|
||||
if (conv != 0) return conv;
|
||||
}
|
||||
return Ch;
|
||||
}
|
||||
|
||||
int lua_log(lua_State* localL) {
|
||||
if(console_mode != 0) return luaL_error(localL, "Invalid log");
|
||||
AppendText(luaL_checkstring(localL, 1));
|
||||
AppendText("\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_console(lua_State* localL) {
|
||||
if(console_mode != 1) return luaL_error(localL, "Invalid log");
|
||||
if (hEditControl != NULL) SetWindowTextA(hEditControl, luaL_checkstring(localL, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_console_mode(lua_State* localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_typeerror(localL, 1, lua_typename(localL, LUA_TBOOLEAN));
|
||||
int mode = lua_toboolean(localL, 1);
|
||||
if (hEditControl != NULL) SetWindowTextA(hEditControl, "");
|
||||
console_mode = mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_window_stick(lua_State* localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_typeerror(localL, 1, lua_typename(localL, LUA_TBOOLEAN));
|
||||
sticky = lua_toboolean(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_get_window_stick(lua_State* localL) {
|
||||
lua_pushboolean(localL, sticky);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_set_font_size(lua_State* localL) {
|
||||
int size = luaL_checkinteger(localL, 1);
|
||||
|
||||
HFONT hNewFont = CreateFont(size, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, FONT_NAME);
|
||||
|
||||
if (hNewFont && hEditControl) {
|
||||
SendMessage(hEditControl, WM_SETFONT, (WPARAM)hNewFont, TRUE);
|
||||
|
||||
if (g_hCurrentFont != NULL) DeleteObject(g_hCurrentFont);
|
||||
|
||||
g_hCurrentFont = hNewFont;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_MessageBox(lua_State* localL) {
|
||||
MessageBoxA(NULL, luaL_checkstring(localL, 1), luaL_checkstring(localL, 2), MB_OK | MB_TOPMOST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_ReadValue(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) {
|
||||
lua_pushnil(localL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* key = luaL_checkstring(localL, 1);
|
||||
ShortString skey;
|
||||
skey.len = strlen(key);
|
||||
if (skey.len > 255) skey.len = 255;
|
||||
memcpy(skey.data, key, skey.len);
|
||||
|
||||
int count = g_DBPointer->Count;
|
||||
if (count > 255) count = 255;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (g_DBPointer->Records[i].Key.len == skey.len &&
|
||||
memcmp(g_DBPointer->Records[i].Key.data, skey.data, skey.len) == 0) {
|
||||
lua_pushlstring(localL, g_DBPointer->Records[i].Value.data, g_DBPointer->Records[i].Value.len);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
lua_pushnil(localL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_ReadRecord(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) {
|
||||
lua_pushnil(localL);
|
||||
lua_pushnil(localL);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int index = luaL_checkinteger(localL, 1);
|
||||
|
||||
if (index < 0 || index >= g_DBPointer->Count || index >= 255) {
|
||||
lua_pushnil(localL);
|
||||
lua_pushnil(localL);
|
||||
return 2;
|
||||
}
|
||||
|
||||
lua_pushlstring(localL, g_DBPointer->Records[index].Key.data, g_DBPointer->Records[index].Key.len);
|
||||
lua_pushlstring(localL, g_DBPointer->Records[index].Value.data, g_DBPointer->Records[index].Value.len);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int lua_AddValue(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) return 0;
|
||||
|
||||
const char* key = luaL_checkstring(localL, 1);
|
||||
const char* value = luaL_checkstring(localL, 2);
|
||||
|
||||
ShortString skey, svalue;
|
||||
skey.len = strlen(key);
|
||||
if (skey.len > 255) skey.len = 255;
|
||||
memcpy(skey.data, key, skey.len);
|
||||
|
||||
svalue.len = strlen(value);
|
||||
if (svalue.len > 252) {
|
||||
svalue.len = 252;
|
||||
memcpy(svalue.data, value, 252);
|
||||
memcpy(svalue.data + 252, "...", 3);
|
||||
svalue.len = 255;
|
||||
} else memcpy(svalue.data, value, svalue.len);
|
||||
|
||||
int count = g_DBPointer->Count;
|
||||
if (count > 255) count = 255;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (g_DBPointer->Records[i].Key.len == skey.len &&
|
||||
memcmp(g_DBPointer->Records[i].Key.data, skey.data, skey.len) == 0) {
|
||||
g_DBPointer->Records[i].Value = svalue;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (count < 254) {
|
||||
g_DBPointer->Records[count].Key = skey;
|
||||
g_DBPointer->Records[count].Value = svalue;
|
||||
g_DBPointer->Count = count + 1;
|
||||
} else if (_stricmp(key, "COMMAND") == 0) {
|
||||
g_DBPointer->Records[254].Key = skey;
|
||||
g_DBPointer->Records[254].Value = svalue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_ResetValues(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) return 0;
|
||||
g_DBPointer->Count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_CountRecords(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) {
|
||||
lua_pushinteger(localL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int count = g_DBPointer->Count;
|
||||
if (count > 255) count = 255;
|
||||
lua_pushinteger(localL, count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_CharConv(lua_State* localL) {
|
||||
int ch = luaL_checkinteger(localL, 1);
|
||||
lua_pushinteger(localL, CharConv((unsigned char)ch));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_SaveString(lua_State* localL) {
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
const char* value = luaL_checkstring(localL, 4);
|
||||
if (lua_isstring(localL, 1)) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
WritePrivateProfileStringA(section, key, value, fullPath);
|
||||
}
|
||||
} else if(lua_isnil(localL, 1)) WritePrivateProfileStringA(section, key, value, workspaceFile);
|
||||
else return luaL_typeerror(localL, 1, lua_typename(localL, LUA_TSTRING));
|
||||
}
|
||||
|
||||
int lua_LoadString(lua_State* localL) {
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
const char* defaultValue = luaL_optstring(localL, 4, "");
|
||||
|
||||
char buffer[1024];
|
||||
if (lua_isstring(localL, 1)) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
char path[MAX_PATH];
|
||||
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
GetPrivateProfileStringA(section, key, defaultValue, buffer, 1024, fullPath);
|
||||
lua_pushstring(localL, buffer);
|
||||
} else lua_pushstring(localL, defaultValue);
|
||||
return 1;
|
||||
} else if(lua_isnil(localL, 1)) {
|
||||
GetPrivateProfileStringA(section, key, defaultValue, buffer, 1024, workspaceFile);
|
||||
lua_pushstring(localL, buffer);
|
||||
return 1;
|
||||
} else return luaL_typeerror(localL, 1, lua_typename(localL, LUA_TSTRING));
|
||||
}
|
||||
35
src/api.h
Normal file
35
src/api.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include "types.h"
|
||||
|
||||
extern HFONT g_hCurrentFont;
|
||||
#define FONT_NAME "Segoe UI"
|
||||
|
||||
extern HWND hEditControl;
|
||||
extern uint8_t console_mode;
|
||||
extern uint8_t sticky;
|
||||
extern TDB* g_DBPointer;
|
||||
extern unsigned char workspaceFile[MAX_PATH];
|
||||
|
||||
int lua_log(lua_State* localL);
|
||||
int lua_set_console(lua_State* localL);
|
||||
int lua_set_console_mode(lua_State* localL);
|
||||
int lua_set_window_stick(lua_State* localL);
|
||||
int lua_get_window_stick(lua_State* localL);
|
||||
int lua_set_font_size(lua_State* localL);
|
||||
int lua_MessageBox(lua_State* localL);
|
||||
int lua_ReadValue(lua_State* localL);
|
||||
int lua_ReadRecord(lua_State* localL);
|
||||
int lua_AddValue(lua_State* localL);
|
||||
int lua_ResetValues(lua_State* localL);
|
||||
int lua_CountRecords(lua_State* localL);
|
||||
int lua_CharConv(lua_State* localL);
|
||||
int lua_SaveString(lua_State* localL);
|
||||
int lua_LoadString(lua_State* localL);
|
||||
|
||||
extern void AppendText(const char* text);
|
||||
@@ -1,42 +1,6 @@
|
||||
#include <windows.h>
|
||||
#include "api.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <shlobj.h>
|
||||
#include <stdint.h>
|
||||
#include "lua/lua.h"
|
||||
#include "lua/lualib.h"
|
||||
#include "lua/lauxlib.h"
|
||||
|
||||
typedef struct {
|
||||
uint16_t Year;
|
||||
uint8_t Month;
|
||||
uint8_t Day;
|
||||
uint8_t Hour;
|
||||
uint8_t Minute;
|
||||
uint8_t Second;
|
||||
uint8_t Centisecond;
|
||||
uint16_t RFU;
|
||||
int32_t Blk1;
|
||||
int32_t Blk2;
|
||||
int32_t Blk3;
|
||||
int32_t Blk4;
|
||||
} TRDSGroup;
|
||||
|
||||
typedef struct {
|
||||
// fuckass delphi
|
||||
uint8_t len;
|
||||
uint8_t data[255];
|
||||
} ShortString;
|
||||
|
||||
typedef struct {
|
||||
ShortString Key;
|
||||
ShortString Value;
|
||||
} TRecord;
|
||||
|
||||
typedef struct {
|
||||
int32_t Count;
|
||||
TRecord Records[255];
|
||||
} TDB;
|
||||
|
||||
static TRDSGroup Group;
|
||||
|
||||
@@ -45,11 +9,10 @@ static HINSTANCE hInst = NULL;
|
||||
|
||||
static lua_State* L = NULL;
|
||||
|
||||
static HWND hEditControl = NULL;
|
||||
static TDB* g_DBPointer = NULL;
|
||||
HWND hEditControl = NULL;
|
||||
TDB* g_DBPointer = NULL;
|
||||
|
||||
static HFONT g_hCurrentFont = NULL;
|
||||
#define FONT_NAME "Segoe UI"
|
||||
HFONT g_hCurrentFont = NULL;
|
||||
|
||||
#define IDC_MAIN_BUTTON 101
|
||||
|
||||
@@ -69,21 +32,10 @@ HWND hButton_event##I = CreateWindowEx( \
|
||||
(HMENU)(IDC_MAIN_BUTTON + I), hInst, NULL \
|
||||
);
|
||||
|
||||
static const unsigned char EBU[127] = {
|
||||
0xE1, 'a', 0xE9, 'e', 0xED, 'i', 0xF3, 'o', 0xFA, 'u', 'N', 0xC7, 0xAA, 0xDF, 'I', 0x00,
|
||||
0xE2, 0xE4, 'e', 0xEB, 0xEE, 'i', 0xF4, 0xF6, 'u', 0xFC, 'n', 0xE7, 0xBA, 0x00, 'i', 0x00,
|
||||
0x00, 0x00, 0xA9, 0x89, 0x00, 0xEC, 0xF2, 0xF5, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xB1, 'I', 0xF1, 0xFB, 0xB5, '?', 0xF7, 0xB0, 0x00, 0x00, 0x00, 0xA7, 0x00,
|
||||
0xC1, 'A', 0xC9, 'E', 0xCD, 'I', 0xD3, 'O', 0xDA, 'U', 0xD8, 0xC8, 0x8A, 0x8E, 0xD0, 'L',
|
||||
0xC2, 0xC4, 'E', 0xCB, 0xCE, 'I', 0xD4, 0xD6, 'U', 0xDC, 0xF8, 0xE8, 0x9A, 0x9E, 0xF0, 'l',
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC6, 0x8C, 0x8F, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE6, 0x9C, 0x9F, 0x00
|
||||
};
|
||||
|
||||
static unsigned short console_mode = 0;
|
||||
static unsigned short stop_execution = 0;
|
||||
static unsigned short sticky = 0;
|
||||
static unsigned char workspaceFile[MAX_PATH] = "";
|
||||
uint8_t console_mode = 0;
|
||||
uint8_t stop_execution = 0;
|
||||
uint8_t sticky = 0;
|
||||
unsigned char workspaceFile[MAX_PATH] = "";
|
||||
|
||||
const char* int_to_string(int value) {
|
||||
static char buffer[16];
|
||||
@@ -91,14 +43,6 @@ const char* int_to_string(int value) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
unsigned char CharConv(unsigned char Ch) {
|
||||
if (Ch >= 128 && Ch < 255) {
|
||||
unsigned char conv = EBU[Ch - 128];
|
||||
if (conv != 0) return conv;
|
||||
}
|
||||
return Ch;
|
||||
}
|
||||
|
||||
void InitLua();
|
||||
void lua_event(int event);
|
||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
@@ -202,223 +146,6 @@ void AppendText(const char* text) {
|
||||
}
|
||||
}
|
||||
|
||||
void SetText(const char* text) {
|
||||
if (hEditControl != NULL) SetWindowTextA(hEditControl, text);
|
||||
}
|
||||
|
||||
int lua_log(lua_State* localL) {
|
||||
if(console_mode != 0) return luaL_error(localL, "Invalid log");
|
||||
const char* data = luaL_checkstring(localL, 1);
|
||||
AppendText(data);
|
||||
AppendText("\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_console(lua_State* localL) {
|
||||
if(console_mode != 1) return luaL_error(localL, "Invalid log");
|
||||
const char* data = luaL_checkstring(localL, 1);
|
||||
SetText(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_console_mode(lua_State* localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
|
||||
int mode = lua_toboolean(localL, 1);
|
||||
SetText("");
|
||||
console_mode = mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_window_stick(lua_State* localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
|
||||
sticky = lua_toboolean(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_get_window_stick(lua_State* localL) {
|
||||
lua_pushboolean(localL, sticky);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_set_font_size(lua_State* localL) {
|
||||
int size = luaL_checkinteger(localL, 1);
|
||||
|
||||
HFONT hNewFont = CreateFont(size, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, FONT_NAME);
|
||||
|
||||
if (hNewFont && hEditControl) {
|
||||
SendMessage(hEditControl, WM_SETFONT, (WPARAM)hNewFont, TRUE);
|
||||
|
||||
if (g_hCurrentFont != NULL) DeleteObject(g_hCurrentFont);
|
||||
|
||||
g_hCurrentFont = hNewFont;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_MessageBox(lua_State* localL) {
|
||||
const char* data = luaL_checkstring(localL, 1);
|
||||
const char* title = luaL_checkstring(localL, 2);
|
||||
MessageBoxA(NULL, data, title, MB_OK | MB_TOPMOST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_ReadValue(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) {
|
||||
lua_pushnil(localL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* key = luaL_checkstring(localL, 1);
|
||||
ShortString skey;
|
||||
skey.len = strlen(key);
|
||||
if (skey.len > 255) skey.len = 255;
|
||||
memcpy(skey.data, key, skey.len);
|
||||
|
||||
int count = g_DBPointer->Count;
|
||||
if (count > 255) count = 255;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (g_DBPointer->Records[i].Key.len == skey.len &&
|
||||
memcmp(g_DBPointer->Records[i].Key.data, skey.data, skey.len) == 0) {
|
||||
lua_pushlstring(localL, g_DBPointer->Records[i].Value.data, g_DBPointer->Records[i].Value.len);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
lua_pushnil(localL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_ReadRecord(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) {
|
||||
lua_pushnil(localL);
|
||||
lua_pushnil(localL);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int index = luaL_checkinteger(localL, 1);
|
||||
|
||||
if (index < 0 || index >= g_DBPointer->Count || index >= 255) {
|
||||
lua_pushnil(localL);
|
||||
lua_pushnil(localL);
|
||||
return 2;
|
||||
}
|
||||
|
||||
lua_pushlstring(localL, g_DBPointer->Records[index].Key.data, g_DBPointer->Records[index].Key.len);
|
||||
lua_pushlstring(localL, g_DBPointer->Records[index].Value.data, g_DBPointer->Records[index].Value.len);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int lua_AddValue(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) return 0;
|
||||
|
||||
const char* key = luaL_checkstring(localL, 1);
|
||||
const char* value = luaL_checkstring(localL, 2);
|
||||
|
||||
ShortString skey, svalue;
|
||||
skey.len = strlen(key);
|
||||
if (skey.len > 255) skey.len = 255;
|
||||
memcpy(skey.data, key, skey.len);
|
||||
|
||||
svalue.len = strlen(value);
|
||||
if (svalue.len > 252) {
|
||||
svalue.len = 252;
|
||||
memcpy(svalue.data, value, 252);
|
||||
memcpy(svalue.data + 252, "...", 3);
|
||||
svalue.len = 255;
|
||||
} else memcpy(svalue.data, value, svalue.len);
|
||||
|
||||
int count = g_DBPointer->Count;
|
||||
if (count > 255) count = 255;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (g_DBPointer->Records[i].Key.len == skey.len &&
|
||||
memcmp(g_DBPointer->Records[i].Key.data, skey.data, skey.len) == 0) {
|
||||
g_DBPointer->Records[i].Value = svalue;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (count < 254) {
|
||||
g_DBPointer->Records[count].Key = skey;
|
||||
g_DBPointer->Records[count].Value = svalue;
|
||||
g_DBPointer->Count = count + 1;
|
||||
} else if (_stricmp(key, "COMMAND") == 0) {
|
||||
g_DBPointer->Records[254].Key = skey;
|
||||
g_DBPointer->Records[254].Value = svalue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_ResetValues(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) return 0;
|
||||
g_DBPointer->Count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_CountRecords(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) {
|
||||
lua_pushinteger(localL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int count = g_DBPointer->Count;
|
||||
if (count > 255) count = 255;
|
||||
lua_pushinteger(localL, count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_CharConv(lua_State* localL) {
|
||||
int ch = luaL_checkinteger(localL, 1);
|
||||
lua_pushinteger(localL, CharConv((unsigned char)ch));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_SaveString(lua_State* localL) {
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
const char* value = luaL_checkstring(localL, 4);
|
||||
if (lua_isstring(localL, 1)) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
WritePrivateProfileStringA(section, key, value, fullPath);
|
||||
}
|
||||
} else if(lua_isnil(localL, 1)) WritePrivateProfileStringA(section, key, value, workspaceFile);
|
||||
else luaL_typeerror(L, 1, lua_typename(L, LUA_TSTRING));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_LoadString(lua_State* localL) {
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
const char* defaultValue = luaL_optstring(localL, 4, "");
|
||||
|
||||
char buffer[1024];
|
||||
if (lua_isstring(localL, 1)) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
char path[MAX_PATH];
|
||||
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
GetPrivateProfileStringA(section, key, defaultValue, buffer, 1024, fullPath);
|
||||
lua_pushstring(localL, buffer);
|
||||
} else lua_pushstring(localL, defaultValue);
|
||||
return 1;
|
||||
} else if(lua_isnil(localL, 1)) {
|
||||
GetPrivateProfileStringA(section, key, defaultValue, buffer, 1024, workspaceFile);
|
||||
lua_pushstring(localL, buffer);
|
||||
return 1;
|
||||
} else luaL_typeerror(L, 1, lua_typename(L, LUA_TSTRING));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lua_call_command(const char* Cmd, const char* Param) {
|
||||
if(stop_execution != 0) return;
|
||||
lua_getglobal(L, "command");
|
||||
@@ -441,8 +168,8 @@ void lua_call_group() {
|
||||
lua_getglobal(L, "group");
|
||||
|
||||
if (lua_isfunction(L, -1)) {
|
||||
lua_pushinteger(L, Group.RFU & 3); // TODO: find out if fuckass pira.cz meant msb or lsb, i have no clue what does "Bits: 0-1" mean
|
||||
lua_pushboolean(L, (Group.RFU & 0x100) >> 8); // just do lsb for now i guess
|
||||
lua_pushinteger(L, Group.RFU & 3);
|
||||
lua_pushboolean(L, (Group.RFU & 0x100) >> 8);
|
||||
lua_pushinteger(L, Group.Blk1);
|
||||
lua_pushinteger(L, Group.Blk2);
|
||||
lua_pushinteger(L, Group.Blk3);
|
||||
@@ -492,7 +219,6 @@ void lua_event(int event) {
|
||||
|
||||
__declspec(dllexport) void WINAPI RDSGroup(TRDSGroup* PRDSGroup) {
|
||||
if (PRDSGroup == NULL) return;
|
||||
|
||||
Group = *PRDSGroup;
|
||||
lua_call_group();
|
||||
}
|
||||
@@ -500,21 +226,20 @@ __declspec(dllexport) void WINAPI RDSGroup(TRDSGroup* PRDSGroup) {
|
||||
__declspec(dllexport) void WINAPI Command(const char* Cmd, const char* Param) {
|
||||
if (Cmd == NULL) return;
|
||||
if (_stricmp(Cmd, "EXIT") == 0) {
|
||||
if (hWnd != NULL) {
|
||||
DestroyWindow(hWnd);
|
||||
hWnd = NULL;
|
||||
}
|
||||
if(L != NULL) {
|
||||
lua_close(L);
|
||||
L = NULL;
|
||||
}
|
||||
if (hWnd != NULL) {
|
||||
DestroyWindow(hWnd);
|
||||
hWnd = NULL;
|
||||
}
|
||||
} else if (_stricmp(Cmd, "CONFIGURE") == 0 || _stricmp(Cmd, "SHOW") == 0 || _stricmp(Cmd, "RESTORE") == 0) ShowWindow(hWnd, SW_SHOW);
|
||||
else if (_stricmp(Cmd, "MINIMIZE") == 0) ShowWindow(hWnd, SW_HIDE);
|
||||
else if (_stricmp(Cmd, "SHOWHIDE") == 0) {
|
||||
if(IsWindowVisible(hWnd)) ShowWindow(hWnd, SW_HIDE);
|
||||
else ShowWindow(hWnd, SW_SHOW);
|
||||
}
|
||||
else if (_stricmp(Cmd, "OPENWORKSPACE") == 0) {
|
||||
} else if (_stricmp(Cmd, "OPENWORKSPACE") == 0) {
|
||||
if(hWnd != NULL) {
|
||||
int value = GetPrivateProfileIntA("luahost", "Visible", 0, Param);
|
||||
if(value == 1) ShowWindow(hWnd, SW_SHOW);
|
||||
@@ -524,10 +249,10 @@ __declspec(dllexport) void WINAPI Command(const char* Cmd, const char* Param) {
|
||||
SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE);
|
||||
}
|
||||
sticky = GetPrivateProfileIntA("luahost", "Stick", 0, Param);
|
||||
lua_call_command(Cmd, Param); // still call
|
||||
lua_call_command(Cmd, Param);
|
||||
} else if (_stricmp(Cmd, "SAVEWORKSPACE") == 0) {
|
||||
if(hWnd != NULL) {
|
||||
RECT rect; // get rect
|
||||
RECT rect;
|
||||
if (GetWindowRect(hWnd, &rect)) {
|
||||
WritePrivateProfileStringA("luahost", "Left", int_to_string(rect.left), Param);
|
||||
WritePrivateProfileStringA("luahost", "Top", int_to_string(rect.top), Param);
|
||||
@@ -537,7 +262,7 @@ __declspec(dllexport) void WINAPI Command(const char* Cmd, const char* Param) {
|
||||
}
|
||||
memcpy(workspaceFile, Param, MAX_PATH);
|
||||
workspaceFile[MAX_PATH-1] = 0;
|
||||
lua_call_command(Cmd, Param); // still call
|
||||
lua_call_command(Cmd, Param);
|
||||
} else if (_stricmp(Cmd, "LUASCRIPT") == 0) { // custom
|
||||
char msg_buffer[255];
|
||||
if (luaL_loadfile(L, Param) != LUA_OK) {
|
||||
@@ -653,8 +378,7 @@ __declspec(dllexport) int WINAPI Initialize(HANDLE hHandle, TDB* DBPointer) {
|
||||
return (int)hWnd;
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
||||
if (fdwReason == DLL_PROCESS_ATTACH) hInst = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
33
src/types.h
Normal file
33
src/types.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t len;
|
||||
uint8_t data[255];
|
||||
} ShortString;
|
||||
|
||||
typedef struct {
|
||||
ShortString Key;
|
||||
ShortString Value;
|
||||
} TRecord;
|
||||
|
||||
typedef struct {
|
||||
int32_t Count;
|
||||
TRecord Records[255];
|
||||
} TDB;
|
||||
|
||||
typedef struct {
|
||||
uint16_t Year;
|
||||
uint8_t Month;
|
||||
uint8_t Day;
|
||||
uint8_t Hour;
|
||||
uint8_t Minute;
|
||||
uint8_t Second;
|
||||
uint8_t Centisecond;
|
||||
uint16_t RFU;
|
||||
int32_t Blk1;
|
||||
int32_t Blk2;
|
||||
int32_t Blk3;
|
||||
int32_t Blk4;
|
||||
} TRDSGroup;
|
||||
Reference in New Issue
Block a user