Files
Accessibility ModandClaude Opus 5 e57350ded3 Phase 0: accessibility mod bootstrap and TTS
Establishes the mod skeleton and gets speech working end to end.

Game-file footprint: one line in main.lua.

- accessibility/init.lua: sole entry point. Patch registry, hooks states.switch
  (announces screen changes) and states.update (per-frame speech flush, avoiding
  an edit to love.update). Startup self-test prints what resolved -- the canary
  for when a future game version moves something we hook.
- accessibility/speech.lua: TTS wrapper. pcall-guarded so a missing DLL degrades
  to silence instead of crashing. Queues utterances within a frame and joins them,
  since one game turn emits several console.print calls and speaking each with
  interrupt would leave only the last audible.
- accessibility/stateNames.lua: spoken names for the 28 states.
- accessibility/vendor/love2talk: vendored TTS library, see VENDORED.md.
  Loads Tolk.dll by absolute path via love.filesystem.getSource() and adds that
  directory via SetDllDirectory, so the DLLs live in the project instead of
  needing an elevated copy into Program Files.

Verified with lovec against NVDA: TTS available, speech channel yes,
'Main menu' spoken on startup.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 20:28:30 +02:00

41 lines
1.2 KiB
Lua

local ffi = require "ffi"
local kernel32 = ffi.load("kernel32")
ffi.cdef[[
int Beep(int x, int y);
typedef unsigned int UINT;
typedef unsigned int DWORD;
typedef const char * LPCSTR;
typedef char * LPSTR;
typedef wchar_t * LPWSTR;
typedef const wchar_t *LPCWSTR;
typedef int *LPBOOL;
int WideCharToMultiByte(UINT CodePage,
DWORD dwFlags,
LPCWSTR lpWideCharStr, int cchWideChar,
LPSTR lpMultiByteStr, int cbMultiByte,
LPCSTR lpDefaultChar,
LPBOOL lpUsedDefaultChar
);
int MultiByteToWideChar(UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr, int cbMultiByte,
LPWSTR lpWideCharStr, int cchWideChar);
]]
local CP_UTF8 = 65001
local function to_utf16(s)
local needed = kernel32.MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0)
local buf = ffi.new("wchar_t[?]", needed)
local written = kernel32.MultiByteToWideChar(CP_UTF8, 0, s, -1, buf, needed)
return ffi.string(buf, written*2)
end
local function to_utf8(s)
local needed = kernel32.WideCharToMultiByte(CP_UTF8, 0, s, -1, nil, 0, nil, nil)
local buf = ffi.new("char[?]", needed)
local written = kernel32.WideCharToMultiByte(CP_UTF8, 0, s, -1, buf, needed, nil, nil)
return ffi.string(buf, written - 1)
end
return {to_utf8=to_utf8, to_utf16=to_utf16}