Skip to content

Commit ecc1557

Browse files
3do: keyboard terminal line + 66x64 logo proportions.
Keyboard renderer gains a second row -- a terminal-style typed-input line beneath the scancode summary. Starts with "> " prompt, displays the typed buffer (max 35 chars to fit the screen width at 8 px/char), shows a blinking underscore cursor at the insertion point, and pops the last char on backspace (PS/2 Set 2 scancode 0x66). Implementation: - PS2_TO_ASCII[128] table maps Set 2 scancodes to printable ASCII (lowercase + digits + common punctuation + space). Shift state isn't tracked yet so everything is unshifted. Bit 0x08 in the table is the special "do backspace" marker. - apply_event_record diffs the incoming ked_KeyMatrix against a per-process g_kb_prev_matrix snapshot on every keyboard event; bits that went 0->1 are fresh keypresses and get piped through kb_consume_press. Only the lower 128 bits (regular keys) are consumed; the upper 128 (E0-prefixed extended keys -- arrows, ctrl, etc.) are ignored for terminal use. - Keyboard row height bumped to 28 px (two text lines). The blink counter increments once per VBL so cursor toggle is ~1 Hz at 60 fps. Note this only renders meaningfully on real hardware with the upcoming USB23DO keyboard-mode firmware. Opera's libretro core doesn't enumerate a keyboard pod on the PBUS chain, so the keyboard row stays empty in the emu. Logo cel proportions: source PNG is now natively 66x64 (a real 3DO controller is slightly wider than tall, and the prior square 64x64 silhouette looked compressed). LOGO_W bumped to match, HDX stretch hack removed, bouncing bounds use the native dimensions directly.
1 parent 08ccf77 commit ecc1557

3 files changed

Lines changed: 89 additions & 16 deletions

File tree

3do/assets/logo_64.png

1.31 KB
Loading

3do/assets/logo_64_inv.png

46 Bytes
Loading

3do/src/main.cpp

Lines changed: 89 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
#define SCREEN_W 320
6868
#define SCREEN_H 240
6969
#define CYCLE_COUNT 7
70-
#define LOGO_W 64
70+
#define LOGO_W 66
7171
#define LOGO_H 64
7272

7373
// Toggle for the broker-pipeline diagnostic status line. Pads work
@@ -209,6 +209,53 @@ static int g_dbg_pod_queries = 0; // count of EB_DescribePods we sent
209209
static int32 g_dbg_pod_result = 1; // msg_Result of last reply (1=never)
210210
static uint32 g_dbg_pod_flavor = 0; // ebh_Flavor of last reply payload
211211

212+
// Keyboard "terminal" line: typed-text buffer + delta-detect state.
213+
// Shared across all keyboard pods on the chain (a single typing
214+
// stream, even if two keyboards were attached). Width is bounded by
215+
// what fits to the right of the prompt on a 320-pixel screen --
216+
// 8 px / char, "> " is 16 px starting at x=20, leaves 320-36 = 284 px
217+
// = 35 char cells.
218+
#define KB_TEXT_MAX 35
219+
static char g_kb_text[KB_TEXT_MAX + 1] = { 0 };
220+
static int g_kb_textlen = 0;
221+
static uint32 g_kb_prev_matrix[8] = { 0 };
222+
static uint32 g_kb_blink_frame = 0;
223+
224+
// PS/2 Set 2 scancode -> ASCII (unshifted). 0 = ignore key (modifier,
225+
// function key, unmapped). 0x08 = backspace (special-case: pop last
226+
// char from buffer). Source: 3DO host driverlet (KeyboardDriver.c)
227+
// decodes PS/2 Set 2 byte stream and stores press state in bit
228+
// `scancode` of ked_KeyMatrix (lower 128 bits = regular keys, upper
229+
// 128 = E0-prefixed extended keys which we ignore for terminal use).
230+
static const char PS2_TO_ASCII[128] = {
231+
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '`', 0,
232+
/* 0x10 */ 0, 0, 0, 0, 0, 'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2', 0,
233+
/* 0x20 */ 0, 'c', 'x', 'd', 'e', '4', '3', 0, 0, ' ', 'v', 'f', 't', 'r', '5', 0,
234+
/* 0x30 */ 0, 'n', 'b', 'h', 'g', 'y', '6', 0, 0, 0, 'm', 'j', 'u', '7', '8', 0,
235+
/* 0x40 */ 0, ',', 'k', 'i', 'o', '0', '9', 0, 0, '.', '/', 'l', ';', 'p', '-', 0,
236+
/* 0x50 */ 0, 0,'\'', 0, '[', '=', 0, 0, 0, 0, 0, ']', 0,'\\', 0, 0,
237+
/* 0x60 */ 0, 0, 0, 0, 0, 0,0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0,
238+
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
239+
};
240+
241+
static void
242+
kb_consume_press (uint8 scancode)
243+
{
244+
if (scancode >= 128) return; /* E0 keys -- not handled */
245+
char c = PS2_TO_ASCII[scancode];
246+
if (c == 0) return; /* unmapped key */
247+
if (c == 0x08) /* backspace */
248+
{
249+
if (g_kb_textlen > 0) g_kb_text[--g_kb_textlen] = 0;
250+
return;
251+
}
252+
if (g_kb_textlen < KB_TEXT_MAX)
253+
{
254+
g_kb_text[g_kb_textlen++] = c;
255+
g_kb_text[g_kb_textlen] = 0;
256+
}
257+
}
258+
212259

213260
// Two distinct outbound message items: one parks while the broker
214261
// holds it pending its Configure ack, the other handles DescribePods
@@ -618,7 +665,30 @@ apply_event_record (EventBrokerHeader *hdr, bool *needs_repodding)
618665
case EVENTNUM_KeyboardDataArrived:
619666
inferred = DEV_KEYBOARD;
620667
if (slot)
621-
slot->kb = *(KeyboardEventData *)frame->ef_EventData;
668+
{
669+
KeyboardEventData *kbed = (KeyboardEventData *)frame->ef_EventData;
670+
slot->kb = *kbed;
671+
/* Terminal feed: detect bits that went 0 -> 1 since the
672+
* last seen matrix and pipe each into the typed-text
673+
* buffer. Only the lower 128 bits (regular keys); the
674+
* upper 128 are E0-extended keys (arrows / ctrl / etc.)
675+
* which the terminal doesn't consume. */
676+
for (int w = 0; w < 4; w++)
677+
{
678+
uint32 cur = kbed->ked_KeyMatrix[w];
679+
uint32 down = cur & ~g_kb_prev_matrix[w];
680+
while (down)
681+
{
682+
int bit = 0;
683+
uint32 mask = down & (~down + 1); /* lowest set bit */
684+
uint32 tmp = mask;
685+
while (tmp >>= 1) bit++;
686+
kb_consume_press ((uint8)(w * 32 + bit));
687+
down ^= mask;
688+
}
689+
g_kb_prev_matrix[w] = cur;
690+
}
691+
}
622692
break;
623693

624694
case EVENTNUM_ControlPortChange:
@@ -883,6 +953,17 @@ draw_keyboard_row (BasicDisplay &display, device_t *dev, int y)
883953
display.draw_text8 (x, y, buf);
884954
x += 24;
885955
}
956+
957+
/* Row 2: terminal-style typed-input line. Starts with "> " prompt,
958+
* shows the typed buffer, and a blinking cursor (underscore) at
959+
* the insertion point. Blink rate ~1 Hz (toggle every 30 frames at
960+
* 60 fps). */
961+
int y2 = y + 14;
962+
display.draw_text8 (20, y2, "> ");
963+
if (g_kb_textlen > 0)
964+
display.draw_text8 (36, y2, g_kb_text);
965+
if (((g_kb_blink_frame / 30) & 1) == 0)
966+
display.draw_text8 (36 + g_kb_textlen * 8, y2, "_");
886967
}
887968

888969
// SillyPad / Arcade buttons. Our SillyPadDriver decodes byte 1 of
@@ -1071,7 +1152,7 @@ draw_devices (BasicDisplay &display)
10711152
case DEV_STICK: draw_stick_row (display, dev, y); rh = 28; break;
10721153
case DEV_LIGHTGUN: draw_lightgun_row (display, dev, y); break;
10731154
case DEV_ARCADE: draw_arcade_row (display, dev, y); break;
1074-
case DEV_KEYBOARD: draw_keyboard_row (display, dev, y); break;
1155+
case DEV_KEYBOARD: draw_keyboard_row (display, dev, y); rh = 28; break;
10751156
default: draw_generic_row (display, dev, y); break;
10761157
}
10771158
y += rh;
@@ -1183,15 +1264,6 @@ main (int argc_, char *argv_)
11831264
* being recolored even though only the background actually is. */
11841265
CCB *logo_ccb = LoadCel ("LogoCel.cel", MEMTYPE_CEL);
11851266
if (logo_ccb == NULL) abort_err (-1);
1186-
/* The source PNG is 64x64 (square), but a real 3DO joypad is
1187-
* wider than tall, so the silhouette looks squeezed at 1:1.
1188-
* Stretch horizontally by 1.5x at render time via the CCB's
1189-
* HDX (horizontal X delta, 12.20 fixed-point). 1.0 = 1<<20;
1190-
* 1.5x = 3<<19. Vertical scale stays 1.0. */
1191-
logo_ccb->ccb_HDX = 3 << 19;
1192-
/* Effective rendered width after the HDX scale -- bouncing
1193-
* uses this so the cel doesn't clip off the right edge. */
1194-
const int LOGO_W_RENDERED = (LOGO_W * 3) / 2;
11951267

11961268
uint32 prev_sig = 0;
11971269
int idle_count = 0;
@@ -1284,10 +1356,10 @@ main (int argc_, char *argv_)
12841356
* matching and we keep overwriting them in place. */
12851357
ss_x += ss_dx;
12861358
ss_y += ss_dy;
1287-
if (ss_x <= 0) { ss_x = 0; ss_dx = -ss_dx; ss_color = (ss_color + 1) % CYCLE_COUNT; }
1288-
if (ss_x >= SCREEN_W - LOGO_W_RENDERED) { ss_x = SCREEN_W - LOGO_W_RENDERED; ss_dx = -ss_dx; ss_color = (ss_color + 1) % CYCLE_COUNT; }
1289-
if (ss_y <= 0) { ss_y = 0; ss_dy = -ss_dy; ss_color = (ss_color + 1) % CYCLE_COUNT; }
1290-
if (ss_y >= SCREEN_H - LOGO_H) { ss_y = SCREEN_H - LOGO_H; ss_dy = -ss_dy; ss_color = (ss_color + 1) % CYCLE_COUNT; }
1359+
if (ss_x <= 0) { ss_x = 0; ss_dx = -ss_dx; ss_color = (ss_color + 1) % CYCLE_COUNT; }
1360+
if (ss_x >= SCREEN_W - LOGO_W) { ss_x = SCREEN_W - LOGO_W; ss_dx = -ss_dx; ss_color = (ss_color + 1) % CYCLE_COUNT; }
1361+
if (ss_y <= 0) { ss_y = 0; ss_dy = -ss_dy; ss_color = (ss_color + 1) % CYCLE_COUNT; }
1362+
if (ss_y >= SCREEN_H - LOGO_H) { ss_y = SCREEN_H - LOGO_H; ss_dy = -ss_dy; ss_color = (ss_color + 1) % CYCLE_COUNT; }
12911363

12921364
uint16 sprite_color = 0x8000u | (uint16)CYCLE_RGB[ss_color];
12931365
uint16 *src = (uint16 *)logo_ccb->ccb_SourcePtr;
@@ -1312,6 +1384,7 @@ main (int argc_, char *argv_)
13121384

13131385
display.display_and_swap ();
13141386
display.waitvbl ();
1387+
g_kb_blink_frame++; /* drives the terminal-cursor blink */
13151388
}
13161389

13171390
// Unreachable in practice; cleanup is left to the OS on reset.

0 commit comments

Comments
 (0)