Skip to content

Commit 5f0c532

Browse files
committed
v1.05
fix: disable both accesibility and win keys while app in use (Windows) new: added bookmarks and compatibility flags to local file browser fix: ay envelope 15 fix (ay1 core) (thanks @leiradel!) fix: expand va() buffers new: zxdb mousewheel fix: restored glx window attribs to what v1.03 was using (Linux) fix: fixed embedding of zxdb in linux builds. fix #20 (Linux,MacOS)
1 parent 36e6f40 commit 5f0c532

File tree

8 files changed

+1158
-957
lines changed

8 files changed

+1158
-957
lines changed

MAKE.bat

+13-3
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@ if [ "$(uname)" != "Darwin" ]; then
2020
# compile -------------------------------------------------------------------- do not use -O3 below. zxdb cache will contain 0-byte files otherwise.
2121
gcc src/app.c -I src -o ./Spectral.linux -O2 -DNDEBUG=3 -D_GNU_SOURCE -Wno-unused-result -Wno-unused-value -Wno-format -Wno-multichar -Wno-pointer-sign -Wno-string-plus-int -Wno-empty-body -lm -lX11 -lGL -lasound -lpthread -ludev $* || exit
2222
upx -9 Spectral.linux
23+
24+
# embed zxdb -----------------------------------------------------------------
2325
#src/res/embed.linux Spectral.linux @SpectralEmBeDdEd
2426
#src/res/embed.linux Spectral.linux src/res/zxdb/Spectral.db.gz
2527
#src/res/embed.linux Spectral.linux @SpectralEmBeDdEd
26-
cat Spectral.linux src/res/embed src/res/zxdb/Spectral.db.gz src/res/embed > Spectral.linux
28+
#cat Spectral.linux src/res/embed src/res/zxdb/Spectral.db.gz src/res/embed > Spectral.linux
29+
dd if=src/res/embed >> Spectral.linux
30+
dd if=src/res/zxdb/Spectral.db.gz >> Spectral.linux
31+
dd if=src/res/embed >> Spectral.linux
2732

2833
fi
2934

@@ -32,10 +37,15 @@ if [ "$(uname)" = "Darwin" ]; then
3237
# compile --------------------------------------------------------------------
3338
export SDKROOT=$(xcrun --show-sdk-path)
3439
gcc -ObjC src/app.c -I src -o ./Spectral.osx -O3 -DNDEBUG=3 -Wno-unused-result -Wno-unused-value -Wno-format -Wno-multichar -Wno-pointer-sign -Wno-string-plus-int -Wno-empty-body -Wno-dangling-else -framework cocoa -framework iokit -framework CoreFoundation -framework CoreAudio -framework AudioToolbox -framework OpenGL -lm $* || exit
40+
41+
# embed zxdb
3542
#src/res/embed.osx Spectral.osx @SpectralEmBeDdEd
3643
#src/res/embed.osx Spectral.osx src/res/zxdb/Spectral.db.gz
3744
#src/res/embed.osx Spectral.osx @SpectralEmBeDdEd
38-
cat Spectral.osx src/res/embed src/res/zxdb/Spectral.db.gz src/res/embed > Spectral.osx
45+
#cat Spectral.osx src/res/embed src/res/zxdb/Spectral.db.gz src/res/embed > Spectral.osx
46+
dd if=src/res/embed >> Spectral.osx
47+
dd if=src/res/zxdb/Spectral.db.gz >> Spectral.osx
48+
dd if=src/res/embed >> Spectral.osx
3949

4050
# embed icon and make .app
4151
test -d Spectral.app && rm -rf Spectral.app
@@ -214,7 +224,7 @@ rem )
214224

215225
where /q rcedit-x64 || curl -LO https://github.com/electron/rcedit/releases/download/v2.0.0/rcedit-x64.exe
216226
where /q rcedit-x64 && rcedit-x64 "Spectral.exe" --set-file-version "!year!.!month!.!today!.!today!!month!"
217-
where /q rcedit-x64 && rcedit-x64 "Spectral.exe" --set-product-version "1.041 Spectral"
227+
where /q rcedit-x64 && rcedit-x64 "Spectral.exe" --set-product-version "1.05-WIP Spectral"
218228
where /q rcedit-x64 && rcedit-x64 "Spectral.exe" --set-icon src\res\img\noto_1f47b.ico
219229
rem where /q rcedit-x64 && rcedit-x64 "Spectral.exe" --set-version-string "version" "value"
220230
rem where /q rcedit-x64 && rcedit-x64 "Spectral.exe" --set-resource-string "version" "value"

src/3rd.h

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "3rd_tigrmousecursor.h"
1414
#include "3rd_tigrdragndrop.h"
1515
#include "3rd_tigrtitle.h"
16+
#include "3rd_tigroskeys.h"
1617
#undef border
1718
#undef run
1819

src/3rd_tigr.h

+357-284
Large diffs are not rendered by default.

src/3rd_tigroskeys.h

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
void enable_os_keys( bool on );
2+
3+
#ifdef _WIN32
4+
5+
void enable_accessibility_keys( bool bAllowKeys ) {
6+
static STICKYKEYS g_StartupStickyKeys = {sizeof(STICKYKEYS), 0};
7+
static TOGGLEKEYS g_StartupToggleKeys = {sizeof(TOGGLEKEYS), 0};
8+
static FILTERKEYS g_StartupFilterKeys = {sizeof(FILTERKEYS), 0};
9+
static int once = 0;
10+
for(;!once;once=1) {
11+
// Save the current sticky/toggle/filter key settings so they can be restored them later
12+
SystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &g_StartupStickyKeys, 0);
13+
SystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(TOGGLEKEYS), &g_StartupToggleKeys, 0);
14+
SystemParametersInfo(SPI_GETFILTERKEYS, sizeof(FILTERKEYS), &g_StartupFilterKeys, 0);
15+
}
16+
17+
if( bAllowKeys ) {
18+
// Restore StickyKeys/etc to original state and enable Windows key
19+
STICKYKEYS sk = g_StartupStickyKeys;
20+
TOGGLEKEYS tk = g_StartupToggleKeys;
21+
FILTERKEYS fk = g_StartupFilterKeys;
22+
23+
SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &g_StartupStickyKeys, 0);
24+
SystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(TOGGLEKEYS), &g_StartupToggleKeys, 0);
25+
SystemParametersInfo(SPI_SETFILTERKEYS, sizeof(FILTERKEYS), &g_StartupFilterKeys, 0);
26+
}
27+
else {
28+
// Disable StickyKeys/etc shortcuts but if the accessibility feature is on,
29+
// then leave the settings alone as its probably being usefully used
30+
31+
STICKYKEYS skOff = g_StartupStickyKeys;
32+
if( (skOff.dwFlags & SKF_STICKYKEYSON) == 0 ) {
33+
// Disable the hotkey and the confirmation
34+
skOff.dwFlags &= ~SKF_HOTKEYACTIVE;
35+
skOff.dwFlags &= ~SKF_CONFIRMHOTKEY;
36+
SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &skOff, 0);
37+
}
38+
39+
TOGGLEKEYS tkOff = g_StartupToggleKeys;
40+
if( (tkOff.dwFlags & TKF_TOGGLEKEYSON) == 0 ) {
41+
// Disable the hotkey and the confirmation
42+
tkOff.dwFlags &= ~TKF_HOTKEYACTIVE;
43+
tkOff.dwFlags &= ~TKF_CONFIRMHOTKEY;
44+
SystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(TOGGLEKEYS), &tkOff, 0);
45+
}
46+
47+
FILTERKEYS fkOff = g_StartupFilterKeys;
48+
if( (fkOff.dwFlags & FKF_FILTERKEYSON) == 0 ) {
49+
// Disable the hotkey and the confirmation
50+
fkOff.dwFlags &= ~FKF_HOTKEYACTIVE;
51+
fkOff.dwFlags &= ~FKF_CONFIRMHOTKEY;
52+
SystemParametersInfo(SPI_SETFILTERKEYS, sizeof(FILTERKEYS), &fkOff, 0);
53+
}
54+
}
55+
}
56+
57+
static HHOOK keyhook = NULL;
58+
static
59+
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam ) {
60+
// Disable Win key. Note that this will not block the Xbox Game Bar hotkeys (Win+G, Win+Alt+R, etc.)
61+
if( nCode == HC_ACTION ) {
62+
if( wParam == WM_KEYDOWN || wParam == WM_KEYUP ) {
63+
KBDLLHOOKSTRUCT *p = (KBDLLHOOKSTRUCT*)(lParam);
64+
BOOL app_active = 1; // (GetActiveWindow() == hWnd);
65+
if( app_active ) {
66+
// check whether ALT/CTRL/SHIFT keys are pressed
67+
BOOL ALT_held = !!(p->flags & LLKHF_ALTDOWN); // !!(GetAsyncKeyState(VK_MENU) & 0x8000); //;
68+
BOOL CTRL_held = !!(GetAsyncKeyState(VK_CONTROL) & 0x8000);
69+
BOOL SHIFT_held = !!(GetAsyncKeyState(VK_LSHIFT) & 0x8000);
70+
int down = p->vkCode;
71+
72+
// Disable CTRL+ESC (which opens the Start Menu)
73+
if( CTRL_held && VK_ESCAPE == down )
74+
return 1;
75+
76+
// Disable WIN (which opens the Start Menu and, when combined with other keys, performs various system actions)
77+
if( VK_LWIN == down || VK_RWIN == down )
78+
return 1;
79+
80+
// @fixme: following entries do not work
81+
82+
// Disable ALT+ESC (which cycles through open windows in the order they were opened)
83+
if( ALT_held && VK_ESCAPE == down )
84+
return 1;
85+
86+
// Disable ALT+TAB (which opens the Task Switcher and allows cycling through open applications)
87+
if( ALT_held && VK_TAB == down )
88+
return 1;
89+
90+
// Disable CTRL+SHIFT (which switches the keyboard input language/layout)
91+
if( CTRL_held && VK_SHIFT == down )
92+
return 1;
93+
}
94+
}
95+
}
96+
return CallNextHookEx( keyhook, nCode, wParam, lParam );
97+
}
98+
99+
void enable_win_key( bool on ) {
100+
if(!on && !keyhook) keyhook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0 );
101+
if( on && keyhook) UnhookWindowsHookEx( keyhook ), keyhook = NULL;
102+
}
103+
104+
#endif
105+
106+
void enable_os_keys( bool on ) {
107+
#ifdef _WIN32
108+
enable_win_key(on);
109+
enable_accessibility_keys(on);
110+
#endif
111+
}

src/app.c

+9-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// glue sequential tzx/taps in zips (side A) -> side 1 etc)
1616
// sequential tzx/taps/dsks do not reset model
1717

18-
#define SPECTRAL "v1.041"
18+
#define SPECTRAL "v1.05-WIP"
1919

2020
#if NDEBUG >= 2
2121
#define DEV 0
@@ -1195,6 +1195,11 @@ int main() {
11951195
// postfx
11961196
crt(ZX_CRT);
11971197

1198+
// disable win key
1199+
// disable nag window after holding shift for 8s (windows)
1200+
// ensure this is called after win32 handles are created
1201+
enable_os_keys(0);
1202+
11981203
// must be as close to frame() as possible
11991204
audio_init();
12001205

@@ -1718,6 +1723,9 @@ if( do_runahead == 0 ) {
17181723

17191724
} while( window_alive(app) );
17201725

1726+
// restore os keys
1727+
enable_os_keys(1);
1728+
17211729
// zxplayer does not save state
17221730
if(!ZX_PLAYER)
17231731

src/app_lib.h

+39-42
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// @fixme: excessive va()
2+
13
#include "res/scr/question_mark"
24

35
zxdb ZXDB2;
@@ -539,6 +541,8 @@ int game_browser_keyboard(const int ENTRIES, const int numgames) { // returns cl
539541
int home = window_pressed(app, TK_HOME) || (window_pressed(app, TK_UP) && tigrKeyHeld(app, TK_CONTROL));
540542
int end = window_pressed(app, TK_END) || (window_pressed(app, TK_DOWN) && tigrKeyHeld(app, TK_CONTROL));
541543

544+
scroll += tigrMouseWheel(app);
545+
542546
scroll = CLAMP(scroll, 0, numgames-1);
543547
selected = CLAMP(selected, 0, numgames-1);
544548

@@ -583,25 +587,34 @@ char* game_browser_v1() {
583587
return games[chosen];
584588
}
585589

590+
static char *buffer = 0; if(!buffer) { buffer = malloc(65536); /*rescan();*/ }
586591

587592
int clicked = 0;
588593

589-
static char *buffer = 0; if(!buffer) { buffer = malloc(65536); /*rescan();*/ }
590-
591594
int y = 0;
592595
for( int j = 0; j < ENTRIES; ++j ) {
593596
int i = scroll + j;
594597
if( i < 0 ) continue;
595598
if( i >= numgames ) continue;
596599

597600
const char *sep = strrchr(games[i], *DIR_SEP_);
598-
int is_dir = sep[1] == '\0';
601+
int is_dir = sep[1] == '\0', is_file = !is_dir;
599602
if( is_dir ) while(0[--sep] != '/');
600603

601-
int color =
602-
(dbgames[i] & 0x7F) == 0 ? '\x7' : // untested
603-
(dbgames[i] & 0x7F) == 1 ? '\x4' : // good
604-
(dbgames[i] & 0x7F) == 2 ? '\x2' : '\x6'; // fail:warn
604+
int flagged = 0;
605+
int starred = 0;
606+
if( i == selected ) {
607+
if( window_pressed(app, TK_SHIFT) && window_trigger(app, TK_SPACE) ) flagged = 1;
608+
if(!window_pressed(app, TK_SHIFT) && window_trigger(app, TK_SPACE) ) starred = 1;
609+
}
610+
611+
int stars = (dbgames[i] >> 8);
612+
int flags = (dbgames[i] & 0x7F);
613+
int color =
614+
flags == 0 ? '\x7' : // untested
615+
flags == 1 ? '\x2' : // fail
616+
flags == 2 ? '\x6' : // warn
617+
'\x4' ; // good
605618

606619
const char *title = sep+1;
607620

@@ -611,50 +624,34 @@ char* game_browser_v1() {
611624
if( strmatchi(title, wildcard) ) ui_alpha = 255;
612625
}
613626

614-
const char starred = dbgames[i] >> 8 ? (char)(dbgames[i] >> 8) : ' ';
615-
sprintf(buffer, "%c%c %3d.%s ",
616-
color, starred,
617-
i+1, i == selected ? ">":" ");
627+
ui_at(ui, 1*11 + 3, (2+y++) * 11 + 2 );
618628

619-
ui_at(ui, 1*11, (2+y++) * 11 );
629+
sprintf(buffer, "%3d.%s", i+1, i == selected ? ">":" ");
620630
ui_label(buffer);
621631

622-
sprintf(buffer, "%s%.*s\n",
623-
is_dir ? "\6" FOLDER_STR "\7\f" : "", (int)(strlen(title) - is_dir), title );
632+
if( is_file && ui_click("-Toggle bookmark-", va("%c\f", "\x10\x12"[!!stars])) )
633+
starred = 1;
634+
635+
if( is_file && ui_click("-Toggle compatibility flags-\n\2fail\7, \6warn\7, \4good", va("%c%s", color, flags == 0 || flags == 3 ? "✓":"╳")) ) // "":""
636+
flagged = 1;
637+
638+
sprintf(buffer, "%s%c%.*s\n",
639+
is_dir ? "\6" FOLDER_STR "\f" : " ", color, (int)(strlen(title) - is_dir), title );
624640

625641
if( ui_click(NULL, buffer) ) selected = i, clicked = 1;
642+
643+
if( is_file )
644+
if( starred || flagged ) {
645+
if( flagged ) flags = (flags+1) % 4;
646+
if( starred ) stars = stars != 'B' ? 'B' : 0;
647+
db_set(games[i], dbgames[i] = flags + (stars << 8));
648+
}
626649
}
627650

628651
// issue browser
629652
// if( window_trigger(app, TK_LEFT) ) { for(--up; (selected+up) >= 0 && (dbgames[selected+up]&0xFF) <= 1; --up ) ; }
630653
// if( window_trigger(app, TK_RIGHT) ) { for(++up; (selected+up) < numgames && (dbgames[selected+up]&0xFF) <= 1; ++up ) ; }
631654

632-
if( window_pressed(app, TK_CONTROL) || window_trigger(app, TK_SPACE) ) {
633-
int update = 0;
634-
int starred = dbgames[selected] >> 8;
635-
int color = dbgames[selected] & 0xFF;
636-
if( window_trigger(app, TK_SPACE) ) color = (color+1) % 4, update = 1;
637-
if( window_trigger(app, 'D') ) starred = starred != 'D' ? 'D' : 0, update = 1; // disk error
638-
if( window_trigger(app, 'T') ) starred = starred != 'T' ? 'T' : 0, update = 1; // tape error
639-
if( window_trigger(app, 'I') ) starred = starred != 'I' ? 'I' : 0, update = 1; // i/o ports error
640-
if( window_trigger(app, 'R') ) starred = starred != 'R' ? 'R' : 0, update = 1; // rom/bios error
641-
if( window_trigger(app, 'E') ) starred = starred != 'E' ? 'E' : 0, update = 1; // emulation error
642-
if( window_trigger(app, 'Z') ) starred = starred != 'Z' ? 'Z' : 0, update = 1; // zip error
643-
if( window_trigger(app, 'S') ) starred = starred != 'S' ? 'S' : 0, update = 1; // star
644-
if( window_trigger(app, '3') ) starred = starred != '3' ? '3' : 0, update = 1; // +3 only error
645-
if( window_trigger(app, '4') ) starred = starred != '4' ? '4' : 0, update = 1; // 48K only error
646-
if( window_trigger(app, '1') ) starred = starred != '1' ? '1' : 0, update = 1; // 128K only error
647-
if( window_trigger(app, '0') ) starred = starred != '0' ? '0' : 0, update = 1; // USR0 only error
648-
if( window_trigger(app, 'A') ) starred = starred != 'A' ? 'A' : 0, update = 1; // ay/audio error
649-
if( window_trigger(app, 'V') ) starred = starred != 'V' ? 'V' : 0, update = 1; // video/vram error
650-
if( window_trigger(app, 'H') ) starred = starred != 'H' ? 'H' : 0, update = 1; // hardware error
651-
if( window_trigger(app, 'M') ) starred = starred != 'M' ? 'M' : 0, update = 1; // mem/multiload error
652-
if(update) {
653-
dbgames[selected] = color + (starred << 8);
654-
db_set(games[selected], dbgames[selected]);
655-
}
656-
}
657-
658655
if( clicked ) {
659656
return games[selected];
660657
}
@@ -1106,8 +1103,8 @@ char* game_browser_v2() {
11061103

11071104
if( !num_options )
11081105
if( selected == i ) {
1109-
if( tigrKeyHeld(app, TK_CONTROL) && tigrKeyDown(app, 'B') ) starred = 1;
1110-
if( tigrKeyHeld(app, TK_CONTROL) && tigrKeyDown(app, TK_SPACE) ) flagged = 1;
1106+
if(!tigrKeyHeld(app, TK_SHIFT) && tigrKeyDown(app, TK_SPACE) ) starred = 1;
1107+
if( tigrKeyHeld(app, TK_SHIFT) && tigrKeyDown(app, TK_SPACE) ) flagged = 1;
11111108
}
11121109

11131110
if( flagged || starred ) {

0 commit comments

Comments
 (0)