@@ -42,6 +42,12 @@ volatile int netsio_sync_wait = 0;
4242int netsio_cmd_state = 0 ;
4343/* data frame size for SIO write commands */
4444volatile 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 */
4753volatile int netsio_ca1_state = 1 ;
@@ -58,6 +64,26 @@ static socklen_t fujinet_addr_len = sizeof(fujinet_addr);
5864/* Thread declaration */
5965static 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+
6187static 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 */
438521int 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 ));
0 commit comments