diff --git a/.gitignore b/.gitignore index a93ed3a..15ad946 100644 --- a/.gitignore +++ b/.gitignore @@ -55,4 +55,4 @@ build/ *.pyc __pycache__/ .vscode/ -.command_prefix.lua \ No newline at end of file +.script.lua \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f3766ba..9d42a20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) -project(rds95 VERSION 1.6) +project(rds95 VERSION 1.7) add_compile_options(-Wall -Werror -Wextra -pedantic -O2 -std=c18 -march=native -DVERSION=\"${PROJECT_VERSION}\") @@ -21,7 +21,7 @@ install(TARGETS rds95 DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(CODE " # Define the paths for the source and destination files - set(PREFIX_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/.script_prefix.lua\") + set(PREFIX_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/.script.lua\") set(SCRIPTS_DIR \"${CMAKE_CURRENT_SOURCE_DIR}/scripts\") set(DEST_FILE \"/etc/rds95.lua\") diff --git a/scripts/0-oda.lua b/scripts/0-oda.lua index 925ca70..81700bd 100644 --- a/scripts/0-oda.lua +++ b/scripts/0-oda.lua @@ -29,7 +29,7 @@ end ---@param oda_id integer ---@param data integer function set_oda_id_data(oda_id, data) - if oda_id > #_RDS_ODAs then return end + if oda_id < 1 or oda_id > #_RDS_ODAs then error("Invalid ODA ID: " .. tostring(oda_id), 2) end _RDS_ODAs[oda_id].data = data end @@ -41,8 +41,8 @@ end ---@param oda_id integer The ID returned by register_oda ---@param fun ODAHandler function set_oda_handler(oda_id, fun) - if oda_id > #_RDS_ODAs then return end - if _RDS_ODAs.group == 3 then error("3A ODAs cannot have handlers.") end + if oda_id < 1 or oda_id > #_RDS_ODAs then error("Invalid ODA ID: " .. tostring(oda_id), 2) end + if _RDS_ODAs[oda_id].group == 3 then error("3A ODAs cannot have handlers.", 2) end _RDS_ODAs[oda_id].handler = fun end diff --git a/scripts/0-rds2_oda.lua b/scripts/0-rds2_oda.lua index 6a23cc6..f57869a 100644 --- a/scripts/0-rds2_oda.lua +++ b/scripts/0-rds2_oda.lua @@ -25,7 +25,7 @@ end ---@param oda_id integer ---@param data integer function set_oda_id_data_rds2(oda_id, data) - if oda_id > #_RDS2_ODAs then return end + if oda_id < 1 or oda_id > #_RDS2_ODAs then error("Invalid ODA ID: " .. tostring(oda_id), 2) end _RDS2_ODAs[oda_id].data = data end @@ -33,7 +33,7 @@ end ---@param oda_id integer ---@param func RDS2_ODAHandler function set_oda_handler_rds2(oda_id, func) - if oda_id > #_RDS2_ODAs then return end + if oda_id < 1 or oda_id > #_RDS2_ODAs then error("Invalid ODA ID: " .. tostring(oda_id), 2) end _RDS2_ODAs[oda_id].handler = func end diff --git a/scripts/1-af.lua b/scripts/1-af.lua index f615e8c..4d2eef2 100644 --- a/scripts/1-af.lua +++ b/scripts/1-af.lua @@ -3,7 +3,7 @@ _Af_Oda_state = 0 _Af_Oda_len = 0 _Af_Oda_afs = {} -local USERDATA_OFFSET = 270 +local USERDATA_ODA_OFFSET = 274 ---@param freq number ---@return table @@ -19,7 +19,7 @@ local function encode_af(freq) elseif freq >= 531 and freq <= 1602 then table.insert(out, 250) -- LFMF incoming table.insert(out, math.tointeger((freq - 531) / 9 + 16)) - end + else error(string.format("Invalid AF frequency: %.1f", freq), 2) end return out end @@ -69,7 +69,7 @@ local function save_af_to_userdata(afs) local payload = string.pack("B", count) for i = 1, count do payload = payload .. string.pack("f", afs[i]) end - set_userdata_offset(USERDATA_OFFSET, #payload, payload) + set_userdata_offset(USERDATA_ODA_OFFSET, #payload, payload) end local function _process_af_list(afs) @@ -86,13 +86,13 @@ local function _process_af_list(afs) end local function load_af_from_userdata() - local header = get_userdata_offset(USERDATA_OFFSET, 1) + local header = get_userdata_offset(USERDATA_ODA_OFFSET, 1) if header == "" or header == nil then return end local count = string.unpack("B", header) if count == 0 or count > 25 then return end - local data = get_userdata_offset(USERDATA_OFFSET + 1, count * 4) + local data = get_userdata_offset(USERDATA_ODA_OFFSET + 1, count * 4) if #data < (count * 4) then return end local afs = {} diff --git a/scripts/1-ert.lua b/scripts/1-ert.lua index f462394..b008d03 100644 --- a/scripts/1-ert.lua +++ b/scripts/1-ert.lua @@ -1,27 +1,30 @@ _Ert_state = 0 _Ert_oda_id = nil +--- Size: 259 bytes +local USERDATA_ERT_OFFSET = 0 + local function init_ert() if _Ert_oda_id == nil then _Ert_oda_id = register_oda(13, false, 0x6552, 1) set_oda_handler(_Ert_oda_id, function () - if string.byte(get_userdata_offset(258, 1)) == 1 then - local new_data = get_userdata_offset(0, 128) - local new_segments = string.byte(get_userdata_offset(128, 1)) - set_userdata_offset(129, 128, new_data) - set_userdata_offset(257, 1, string.char(new_segments)) - set_userdata_offset(258, 1, string.char(0)) + if string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+258, 1)) == 1 then + local new_data = get_userdata_offset(USERDATA_ERT_OFFSET, 128) + local new_segments = string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+128, 1)) + set_userdata_offset(USERDATA_ERT_OFFSET+129, 128, new_data) + set_userdata_offset(USERDATA_ERT_OFFSET+257, 1, string.char(new_segments)) + set_userdata_offset(USERDATA_ERT_OFFSET+258, 1, string.char(0)) _Ert_state = 0 end - local segments = string.byte(get_userdata_offset(257, 1)) + local segments = string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+257, 1)) if segments == 0 then return false, 0, 0, 0 end if _Ert_state >= segments then _Ert_state = 0 end local b = _Ert_state & 31 - local chunk = get_userdata_offset(129 + _Ert_state * 4, 4) + local chunk = get_userdata_offset(USERDATA_ERT_OFFSET + 129 + _Ert_state * 4, 4) local c = (string.byte(chunk, 1) << 8) | string.byte(chunk, 2) local d = (string.byte(chunk, 3) << 8) | string.byte(chunk, 4) @@ -33,9 +36,9 @@ end function set_rds_ert(ert) if #ert == 0 then - set_userdata_offset(0, 128, "") - set_userdata_offset(128, 1, string.char(0)) - set_userdata_offset(258, 1, string.char(1)) + set_userdata_offset(USERDATA_ERT_OFFSET, 128, "") + set_userdata_offset(USERDATA_ERT_OFFSET+128, 1, string.char(0)) + set_userdata_offset(USERDATA_ERT_OFFSET+258, 1, string.char(1)) return end @@ -45,31 +48,31 @@ function set_rds_ert(ert) local padding = (4 - (#data % 4)) % 4 data = data .. string.rep("\0", padding) - set_userdata_offset(0, 128, data) + set_userdata_offset(USERDATA_ERT_OFFSET, 128, data) local segments = #data // 4 if segments > 32 then segments = 32 end - set_userdata_offset(128, 1, string.char(segments)) + set_userdata_offset(USERDATA_ERT_OFFSET+128, 1, string.char(segments)) - if string.byte(get_userdata_offset(257, 1)) == 0 then + if string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+257, 1)) == 0 then init_ert() - set_userdata_offset(129, 128, data) - set_userdata_offset(257, 1, string.char(segments)) + set_userdata_offset(USERDATA_ERT_OFFSET+129, 128, data) + set_userdata_offset(USERDATA_ERT_OFFSET+257, 1, string.char(segments)) _Ert_state = 0 - else set_userdata_offset(258, 1, string.char(1)) end + else set_userdata_offset(USERDATA_ERT_OFFSET+258, 1, string.char(1)) end end function get_rds_ert() - local segments = string.byte(get_userdata_offset(128, 1)) + local segments = string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+128, 1)) if segments == 0 then return "" end - local data = get_userdata_offset(0, 128) + local data = get_userdata_offset(USERDATA_ERT_OFFSET, 128) return data:match("^(.-)[\r%z]*") or "" end local _old_on_state_ert = on_state function on_state() - if string.byte(get_userdata_offset(257, 1)) ~= 0 then init_ert() end + if string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+257, 1)) ~= 0 then init_ert() end if type(_old_on_state_ert) == "function" then _old_on_state_ert() end end \ No newline at end of file diff --git a/scripts/1-rft.lua b/scripts/1-rft.lua index b003d91..7377a6d 100644 --- a/scripts/1-rft.lua +++ b/scripts/1-rft.lua @@ -37,15 +37,16 @@ end ---@param path string ---@param id integer function load_station_logo(path, id) + local file = io.open(path, "rb") + if not file then error("Could not open file") end + _Rft_file = file:read("*a") + file:close() + if id == _Rft_last_id then _Rft_toggle = not _Rft_toggle _Rft_version = _Rft_version + 1 if _Rft_version > 7 then _Rft_version = 0 end end - local file = io.open(path, "rb") - if not file then error("Could not open file") end - _Rft_file = file:read("*a") - file:close() if #_Rft_file > 262143 then error("The file is too large", 2) end if _Rft_oda_id == nil then start_rft() end diff --git a/scripts/1-rtp.lua b/scripts/1-rtp.lua index b9887bd..a8995b2 100644 --- a/scripts/1-rtp.lua +++ b/scripts/1-rtp.lua @@ -3,13 +3,16 @@ _Ertp_oda_id = nil _Rtp_toggle = false _Ertp_toggle = false +--- Size: 15 bytes +local USERDATA_RTP_OFFSET = 259 + local function init_rtp() if _Rtp_oda_id == nil then _Rtp_oda_id = register_oda(11, false, 0x4BD7, 0) set_oda_handler(_Rtp_oda_id, function () - local b = (_Rtp_toggle and 1 or 0) << 4 | string.byte(get_userdata_offset(259, 1)) << 3 - local data_0 = get_userdata_offset(260, 3) - local data_1 = get_userdata_offset(263, 3) + local b = (_Rtp_toggle and 1 or 0) << 4 | string.byte(get_userdata_offset(USERDATA_RTP_OFFSET, 1)) << 3 + local data_0 = get_userdata_offset(USERDATA_RTP_OFFSET+1, 3) + local data_1 = get_userdata_offset(USERDATA_RTP_OFFSET+4, 3) b = b | (string.byte(data_0, 1) & 0xf8) >> 3 local c = (string.byte(data_0, 1) & 0x7) << 13 @@ -30,9 +33,9 @@ local function init_ertp() if _Ertp_oda_id == nil then _Ertp_oda_id = register_oda(12, false, 0x4BD8, 0) set_oda_handler(_Ertp_oda_id, function () - local b = (_Ertp_toggle and 1 or 0) << 4 | string.byte(get_userdata_offset(266, 1)) << 3 - local data_0 = get_userdata_offset(267, 3) - local data_1 = get_userdata_offset(270, 3) + local b = (_Ertp_toggle and 1 or 0) << 4 | string.byte(get_userdata_offset(USERDATA_RTP_OFFSET+7, 1)) << 3 + local data_0 = get_userdata_offset(USERDATA_RTP_OFFSET+8, 3) + local data_1 = get_userdata_offset(USERDATA_RTP_OFFSET+11, 3) b = b | (string.byte(data_0, 1) & 0xf8) >> 3 local c = (string.byte(data_0, 1) & 0x7) << 13 @@ -52,14 +55,14 @@ end function set_rds_rtp_meta(ertp, running) if ertp then if running and _Ertp_oda_id == nil then init_ertp() end - set_userdata_offset(266, 1, string.char(running and 1 or 0)) + set_userdata_offset(USERDATA_RTP_OFFSET+7, 1, string.char(running and 1 or 0)) else if running and _Rtp_oda_id == nil then init_rtp() end - set_userdata_offset(259, 1, string.char(running and 1 or 0)) + set_userdata_offset(USERDATA_RTP_OFFSET, 1, string.char(running and 1 or 0)) end end function get_rds_rtp_meta(ertp) - local offset = ertp and 266 or 259 + local offset = ertp and (USERDATA_RTP_OFFSET+7) or USERDATA_RTP_OFFSET return string.byte(get_userdata_offset(offset, 1)) ~= 0 end function toggle_rds_rtp(ertp) @@ -70,10 +73,10 @@ end function set_rds_rtplus_tags(ertp, t1, s1, l1, t2, s2, l2) set_rds_rtp_meta(ertp, true) toggle_rds_rtp(ertp) - set_userdata_offset(ertp and 267 or 260, 6, string.char(t1, s1, l1, t2, s2, l2)) + set_userdata_offset(ertp and (USERDATA_RTP_OFFSET+8) or (USERDATA_RTP_OFFSET+1), 6, string.char(t1, s1, l1, t2, s2, l2)) end function get_rds_rtplus_tags(ertp) - return string.byte(get_userdata_offset(ertp and 267 or 260, 6), 1, 6) + return string.byte(get_userdata_offset(ertp and (USERDATA_RTP_OFFSET+8) or (USERDATA_RTP_OFFSET+1), 6), 1, 6) end local _old_on_state_rtp = on_state