Skip to content

Commit a068f7f

Browse files
authored
netsio: add startup wait and gate netstream mode via Fuji enable + motor + POKEY config (atari800#265)
- add Netstream state machine/hooks in netsio/pokey/sio/pia - avoid activating raw stream mode on MOTOR alone - wait briefly for NetSIO connection during emulator startup
1 parent f79b4a5 commit a068f7f

6 files changed

Lines changed: 154 additions & 7 deletions

File tree

src/atari.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@
149149
#endif
150150
#ifdef NETSIO
151151
#include "netsio.h"
152+
153+
#define NETSIO_STARTUP_WAIT_TIMEOUT_MS 5000
154+
#define NETSIO_STARTUP_WAIT_POLL_MS 10
152155
#endif /* NETSIO */
153156

154157
int Atari800_machine_type = Atari800_MACHINE_XLXE;
@@ -626,7 +629,17 @@ int Atari800_Initialise(int *argc, char *argv[])
626629
if (netsio_init((uint16_t)port) < 0) {
627630
Log_print("netsio: init failed");
628631
} else {
632+
int waited_ms = 0;
629633
Log_print("netsio initialized with port %d", port);
634+
while (!netsio_enabled && waited_ms < NETSIO_STARTUP_WAIT_TIMEOUT_MS) {
635+
Util_sleep((double)NETSIO_STARTUP_WAIT_POLL_MS / 1000.0);
636+
waited_ms += NETSIO_STARTUP_WAIT_POLL_MS;
637+
}
638+
if (netsio_enabled)
639+
Log_print("netsio connected after %d ms", waited_ms);
640+
else
641+
Log_print("netsio not connected after %d ms, continuing startup",
642+
NETSIO_STARTUP_WAIT_TIMEOUT_MS);
630643
}
631644
}
632645
#endif /* NETSIO */

src/netsio.c

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ volatile int netsio_sync_wait = 0;
4242
int netsio_cmd_state = 0;
4343
/* data frame size for SIO write commands */
4444
volatile int netsio_next_write_size = 0;
45+
/* Netstream gate state */
46+
static volatile int netsio_netstream_pending_enable = 0;
47+
static volatile int netsio_netstream_fuji_enabled = 0;
48+
static volatile int netsio_netstream_motor_on = 0;
49+
static volatile int netsio_netstream_pokey_ok = 0;
50+
static volatile int netsio_netstream_is_active = 0;
4551

4652
/* PIA Pin buffered states for synchronous emulator polling */
4753
volatile int netsio_ca1_state = 1;
@@ -58,6 +64,26 @@ static socklen_t fujinet_addr_len = sizeof(fujinet_addr);
5864
/* Thread declaration */
5965
static void *fujinet_rx_thread(void *arg);
6066

67+
static void netsio_netstream_recalc(void)
68+
{
69+
int active = 0;
70+
if (netsio_enabled
71+
&& netsio_netstream_fuji_enabled
72+
&& netsio_netstream_motor_on
73+
&& netsio_netstream_pokey_ok)
74+
active = 1;
75+
if (active != netsio_netstream_is_active) {
76+
netsio_netstream_is_active = active;
77+
#ifdef DEBUG
78+
Log_print("netsio: netstream %s (fuji=%d motor=%d pokey=%d)",
79+
active ? "enter" : "exit",
80+
netsio_netstream_fuji_enabled,
81+
netsio_netstream_motor_on,
82+
netsio_netstream_pokey_ok);
83+
#endif
84+
}
85+
}
86+
6187
static void millisleep(unsigned int ms)
6288
{
6389
struct timespec req, rem;
@@ -214,6 +240,7 @@ int netsio_init(uint16_t port) {
214240
struct sockaddr_in addr;
215241
pthread_t rx_thread;
216242
int broadcast = 1;
243+
int reuse = 1;
217244

218245
/* Skip re-initialization if already initialized (during emulator restarts) */
219246
if (netsio_initialized) {
@@ -270,7 +297,6 @@ int netsio_init(uint16_t port) {
270297
}
271298

272299
/* Enable SO_REUSEADDR to allow binding even if the port is in TIME_WAIT state */
273-
int reuse = 1;
274300
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
275301
{
276302
#ifdef DEBUG
@@ -434,6 +460,63 @@ int netsio_motor_off(void)
434460
return 0;
435461
}
436462

463+
void netsio_netstream_set_motor(int motor_on)
464+
{
465+
netsio_netstream_motor_on = motor_on ? 1 : 0;
466+
if (netsio_enabled) {
467+
if (motor_on)
468+
netsio_motor_on();
469+
else
470+
netsio_motor_off();
471+
}
472+
netsio_netstream_recalc();
473+
}
474+
475+
void netsio_netstream_note_command_frame(const uint8_t *cmd, size_t len)
476+
{
477+
if (len >= 2 && cmd != NULL && cmd[0] == 0x70 && cmd[1] == 0xF0) {
478+
netsio_netstream_pending_enable = 1;
479+
#ifdef DEBUG
480+
Log_print("netsio: netstream pending enable (cf 70/F0)");
481+
#endif
482+
}
483+
}
484+
485+
void netsio_netstream_note_status_byte(uint8_t status)
486+
{
487+
if (!netsio_netstream_pending_enable)
488+
return;
489+
netsio_netstream_pending_enable = 0;
490+
netsio_netstream_fuji_enabled = (status == 'A') ? 1 : 0;
491+
#ifdef DEBUG
492+
Log_print("netsio: netstream enable %s (status=%02X)",
493+
netsio_netstream_fuji_enabled ? "accepted" : "rejected",
494+
status);
495+
#endif
496+
netsio_netstream_recalc();
497+
}
498+
499+
void netsio_netstream_clear_pending(void)
500+
{
501+
netsio_netstream_pending_enable = 0;
502+
}
503+
504+
void netsio_netstream_update_pokey(uint8_t skctl, uint8_t audctl, uint8_t audf3, uint8_t audf4)
505+
{
506+
uint8_t mode = skctl & 0x70;
507+
(void)audf3;
508+
(void)audf4;
509+
netsio_netstream_pokey_ok =
510+
((audctl & 0x28) == 0x28)
511+
&& (mode == 0x00 || mode == 0x10 || mode == 0x30 || mode == 0x40);
512+
netsio_netstream_recalc();
513+
}
514+
515+
int netsio_netstream_active(void)
516+
{
517+
return netsio_netstream_is_active;
518+
}
519+
437520
/* The emulator calls this to send a data byte out to FujiNet */
438521
int netsio_send_byte(uint8_t b) {
439522
uint8_t pkt[2];
@@ -496,6 +579,9 @@ int netsio_cold_reset(void) {
496579
#ifdef DEBUG
497580
Log_print("netsio: cold reset");
498581
#endif
582+
netsio_netstream_pending_enable = 0;
583+
netsio_netstream_fuji_enabled = 0;
584+
netsio_netstream_recalc();
499585
send_to_fujinet(&pkt, 1);
500586
return 0;
501587
}
@@ -506,6 +592,9 @@ int netsio_warm_reset(void) {
506592
#ifdef DEBUG
507593
Log_print("netsio: warm reset");
508594
#endif
595+
netsio_netstream_pending_enable = 0;
596+
netsio_netstream_fuji_enabled = 0;
597+
netsio_netstream_recalc();
509598
send_to_fujinet(&pkt, 1);
510599
return 0;
511600
}
@@ -595,6 +684,7 @@ static void *fujinet_rx_thread(void *arg) {
595684
Log_print("netsio: recv: device connected");
596685
#endif
597686
netsio_enabled = 1;
687+
netsio_netstream_recalc();
598688
break;
599689
}
600690

@@ -604,6 +694,9 @@ static void *fujinet_rx_thread(void *arg) {
604694
Log_print("netsio: recv: device disconnected");
605695
#endif
606696
netsio_enabled = 0;
697+
netsio_netstream_pending_enable = 0;
698+
netsio_netstream_fuji_enabled = 0;
699+
netsio_netstream_is_active = 0;
607700
break;
608701
}
609702

@@ -826,6 +919,11 @@ void netsio_shutdown(void) {
826919
netsio_sync_wait = 0;
827920
netsio_cmd_state = 0;
828921
netsio_next_write_size = 0;
922+
netsio_netstream_pending_enable = 0;
923+
netsio_netstream_fuji_enabled = 0;
924+
netsio_netstream_motor_on = 0;
925+
netsio_netstream_pokey_ok = 0;
926+
netsio_netstream_is_active = 0;
829927

830928
/* Clear address info */
831929
memset(&fujinet_addr, 0, sizeof(fujinet_addr));

src/netsio.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,12 @@ int netsio_warm_reset(void);
9191

9292
void netsio_test_cmd(void);
9393

94+
/* Netstream state gates (Fuji $70/$F0 + MOTOR + POKEY config). */
95+
void netsio_netstream_set_motor(int motor_on);
96+
void netsio_netstream_note_command_frame(const uint8_t *cmd, size_t len);
97+
void netsio_netstream_note_status_byte(uint8_t status);
98+
void netsio_netstream_clear_pending(void);
99+
void netsio_netstream_update_pokey(uint8_t skctl, uint8_t audctl, uint8_t audf3, uint8_t audf4);
100+
int netsio_netstream_active(void);
101+
94102
#endif /* NETSIO_H */

src/pia.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,7 @@ static void set_CA2(int value)
101101
/* The motor status has changed */
102102
CASSETTE_TapeMotor(!value);
103103
#ifdef NETSIO
104-
if (netsio_enabled) {
105-
if (value == 0)
106-
netsio_motor_on();
107-
else
108-
netsio_motor_off();
109-
}
104+
netsio_netstream_set_motor(value == 0);
110105
#endif
111106
}
112107
PIA_CA2 = value;

src/pokey.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ void POKEY_PutByte(UWORD addr, UBYTE byte)
217217

218218
Update_Counter((1 << POKEY_CHAN1) | (1 << POKEY_CHAN2) | (1 << POKEY_CHAN3) | (1 << POKEY_CHAN4));
219219
POKEYSND_Update(POKEY_OFFSET_AUDCTL, byte, 0, SOUND_GAIN);
220+
#ifdef NETSIO
221+
netsio_netstream_update_pokey(POKEY_SKCTL, POKEY_AUDCTL[0], POKEY_AUDF[POKEY_CHAN3], POKEY_AUDF[POKEY_CHAN4]);
222+
#endif
220223
break;
221224
case POKEY_OFFSET_AUDF1:
222225
POKEY_AUDF[POKEY_CHAN1] = byte;
@@ -232,11 +235,17 @@ void POKEY_PutByte(UWORD addr, UBYTE byte)
232235
POKEY_AUDF[POKEY_CHAN3] = byte;
233236
Update_Counter((POKEY_AUDCTL[0] & POKEY_CH3_CH4) ? ((1 << POKEY_CHAN4) | (1 << POKEY_CHAN3)) : (1 << POKEY_CHAN3));
234237
POKEYSND_Update(POKEY_OFFSET_AUDF3, byte, 0, SOUND_GAIN);
238+
#ifdef NETSIO
239+
netsio_netstream_update_pokey(POKEY_SKCTL, POKEY_AUDCTL[0], POKEY_AUDF[POKEY_CHAN3], POKEY_AUDF[POKEY_CHAN4]);
240+
#endif
235241
break;
236242
case POKEY_OFFSET_AUDF4:
237243
POKEY_AUDF[POKEY_CHAN4] = byte;
238244
Update_Counter(1 << POKEY_CHAN4);
239245
POKEYSND_Update(POKEY_OFFSET_AUDF4, byte, 0, SOUND_GAIN);
246+
#ifdef NETSIO
247+
netsio_netstream_update_pokey(POKEY_SKCTL, POKEY_AUDCTL[0], POKEY_AUDF[POKEY_CHAN3], POKEY_AUDF[POKEY_CHAN4]);
248+
#endif
240249
break;
241250
case POKEY_OFFSET_IRQEN:
242251
POKEY_IRQEN = byte;
@@ -259,6 +268,12 @@ void POKEY_PutByte(UWORD addr, UBYTE byte)
259268
case POKEY_OFFSET_SEROUT:
260269
#ifdef VOICEBOX
261270
VOICEBOX_SEROUTPutByte(byte);
271+
#endif
272+
/* Netstream raw serial path: only active after Fuji enable + MOTOR + matching POKEY setup. */
273+
#ifdef NETSIO
274+
if (netsio_enabled && netsio_netstream_active())
275+
NetSIO_PutByte(byte);
276+
else
262277
#endif
263278
if ((POKEY_SKCTL & 0x70) == 0x20 && POKEY_siocheck())
264279
SIO_PutByte(byte);
@@ -311,6 +326,9 @@ void POKEY_PutByte(UWORD addr, UBYTE byte)
311326
#endif
312327
POKEY_SKCTL = byte;
313328
POKEYSND_Update(POKEY_OFFSET_SKCTL, byte, 0, SOUND_GAIN);
329+
#ifdef NETSIO
330+
netsio_netstream_update_pokey(POKEY_SKCTL, POKEY_AUDCTL[0], POKEY_AUDF[POKEY_CHAN3], POKEY_AUDF[POKEY_CHAN4]);
331+
#endif
314332
if (byte & 4)
315333
pot_scanline = 228; /* fast pot mode - return results immediately */
316334
if ((byte & 0x03) == 0) {
@@ -392,6 +410,9 @@ int POKEY_Initialise(int *argc, char *argv[])
392410
POKEY_IRQEN = 0x00;
393411
POKEY_SKSTAT = 0xef;
394412
POKEY_SKCTL = 0x00;
413+
#ifdef NETSIO
414+
netsio_netstream_update_pokey(POKEY_SKCTL, 0, 0, 0);
415+
#endif
395416

396417
for (i = 0; i < (POKEY_MAXPOKEYS * 4); i++) {
397418
POKEY_AUDC[i] = 0;

src/sio.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,6 +1528,15 @@ static UBYTE Command_Frame(void)
15281528
/* Enable/disable the command frame */
15291529
void SIO_SwitchCommandFrame(int onoff)
15301530
{
1531+
#ifdef NETSIO
1532+
if (netsio_enabled && netsio_netstream_active()) {
1533+
CommandIndex = 0;
1534+
DataIndex = 0;
1535+
ExpectedBytes = 0;
1536+
TransferStatus = SIO_NoFrame;
1537+
return;
1538+
}
1539+
#endif /* NETSIO */
15311540
if (onoff)
15321541
{ /* Enabled */
15331542
#ifdef NETSIO
@@ -1555,6 +1564,7 @@ void SIO_SwitchCommandFrame(int onoff)
15551564
#ifdef DEBUG
15561565
Log_print("Short command frame: %d bytes", CommandIndex);
15571566
#endif
1567+
netsio_netstream_clear_pending();
15581568
/* a) Send short CF ...
15591569
if (CommandIndex > 0)
15601570
netsio_send_block(CommandFrame, CommandIndex);
@@ -1618,6 +1628,7 @@ void NetSIO_PutByte(int byte)
16181628
CommandFrame[CommandIndex++] = byte; /* Collect CF bytes into buffer */
16191629
if (CommandIndex == ExpectedBytes)
16201630
{
1631+
netsio_netstream_note_command_frame(CommandFrame, ExpectedBytes);
16211632
netsio_send_block(CommandFrame, ExpectedBytes); /* Send CF buffer */
16221633
}
16231634
}
@@ -1757,6 +1768,7 @@ int NetSIO_GetByte(void)
17571768

17581769
switch (TransferStatus) {
17591770
case SIO_StatusRead:
1771+
netsio_netstream_note_status_byte((uint8_t)b);
17601772
if (b == 'A')
17611773
{ /* ACK received */
17621774
if (netsio_next_write_size > 0)

0 commit comments

Comments
 (0)