?login_element?

Subversion Repositories NedoOS

Rev

Rev 401 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5.  
  6. #include "net.h"
  7. #include "psg.h"
  8. #include "play.h"
  9. #include "global.h"
  10. #include "rnd.h"
  11. #include "ififo.h"
  12.  
  13.  
  14. // init net_context
  15. void init_ctx(struct net_context * ctx, int sock)
  16. {
  17.         if( ctx )
  18.         {
  19.                 ctx->sock = sock;
  20.                 ctx->in_ptr = ctx->out_ptr = 0;
  21.         }
  22.         else
  23.         {
  24.                 fprintf(stderr,"%s: ctx pointer is NULL!\n",__PRETTY_FUNCTION__);
  25.                 exit(1);
  26.         }
  27. }
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34. int get_in_free_size(struct net_context * ctx)
  35. {
  36.         return (int)( ((ctx->out_ptr - ctx->in_ptr - 1)&(NET_BUF_SIZE-1)) );
  37. }
  38.  
  39.  
  40. int get_in_cont_size(struct net_context * ctx)
  41. {
  42.         int free_size = get_in_free_size(ctx);
  43.  
  44.         int up_to_end = NET_BUF_SIZE-ctx->in_ptr;
  45.  
  46.         if( up_to_end > free_size ) up_to_end = free_size;
  47.  
  48.         return up_to_end;
  49. }
  50.  
  51.  
  52. uint8_t * get_in_ptr(struct net_context * ctx)
  53. {
  54.         return &ctx->buf[ctx->in_ptr];
  55. }
  56.  
  57.  
  58. void set_write_size(struct net_context * ctx, int len)
  59. {
  60.         ctx->in_ptr += len;
  61.         ctx->in_ptr &= (NET_BUF_SIZE-1);
  62. }
  63.  
  64.  
  65.  
  66. int get_out_used_size(struct net_context * ctx)
  67. {
  68.         return (int)((ctx->in_ptr - ctx->out_ptr)&(NET_BUF_SIZE-1));
  69. }
  70.  
  71.  
  72. int get_out_cont_size(struct net_context * ctx)
  73. {
  74.         int used_size = get_out_used_size(ctx);
  75.  
  76.         int up_to_end = NET_BUF_SIZE-ctx->out_ptr;
  77.  
  78.         if( up_to_end > used_size ) up_to_end = used_size;
  79.  
  80.         return up_to_end;
  81. }
  82.  
  83.  
  84. uint8_t * get_out_ptr(struct net_context * ctx)
  85. {
  86.         return &ctx->buf[ctx->out_ptr];
  87. }
  88.  
  89.  
  90. void set_read_size(struct net_context * ctx, int len)
  91. {
  92.         ctx->out_ptr += len;
  93.         ctx->out_ptr &= (NET_BUF_SIZE-1);
  94. }
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105. struct packet * rcv_packet(struct net_context * ctx)
  106. {
  107.         static uint8_t buf[NET_BUF_SIZE];
  108.  
  109.         uint8_t type;
  110.         uint8_t hello_size;
  111.  
  112.  
  113.         // receive packet type
  114.         if( !net_recv_bytes(ctx->sock, &buf[0], 1) )
  115.         {
  116.                 return NULL; // if connection is closed
  117.         }
  118.  
  119.         switch( type=buf[0] )
  120.         {
  121.                 case FROMZX_HELLO:
  122.                         if( !net_recv_bytes(ctx->sock, &buf[1], 1) ) return NULL;
  123.  
  124.                         if( (hello_size=buf[1])>0 )
  125.                         {
  126.                                 if( !net_recv_bytes(ctx->sock, &buf[2], hello_size) ) return NULL;
  127.                         }
  128.                 break;
  129.  
  130.                 case FROMZX_FRAMESYNC:
  131.                 case FROMZX_SYNCRPLY:
  132.                         if( !net_recv_bytes(ctx->sock, &buf[1], 4) ) return NULL;
  133.                 break;
  134.  
  135.                 default:
  136.                         fprintf(stderr,"%s: invalid packet type (0x%02x) received!\n",__PRETTY_FUNCTION__,type);
  137.                         net_disconnect(ctx->sock);
  138.                         exit(1);
  139.                 break;
  140.         }
  141.  
  142.         return (struct packet *)buf;
  143. }
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151. void play_tune(int sock, struct frame_list * frames)
  152. {
  153.         struct net_context from_zx;
  154.         struct net_context to_zx;
  155.  
  156.         struct packet * rcvd;
  157.  
  158.         int was_hello;
  159.         int was_syncrply;
  160.         int was_framesync;
  161.  
  162.         struct frame_list * curr_frame = frames;
  163.  
  164.         // buffer for dump packet and (if needed) syncreq packet.
  165.         uint8_t txbuf[sizeof(struct tx_packet_syncreq)+sizeof(struct tx_packet_dump)];
  166.  
  167.         struct tx_packet_dump    * const dump    = (struct tx_packet_dump    *) ( txbuf+sizeof(struct tx_packet_syncreq) );
  168.         struct tx_packet_syncreq * const syncreq = (struct tx_packet_syncreq *) txbuf;
  169.  
  170.         struct packet * pkt;
  171.  
  172.  
  173.         const size_t size_dump    = sizeof(struct tx_packet_dump);
  174.         const size_t size_syncreq = sizeof(struct tx_packet_syncreq);
  175.         const size_t size_both    = size_dump + size_syncreq;
  176.  
  177.         size_t actual_size;
  178.  
  179.  
  180.         int frames_in_flight = 0;
  181.  
  182.         uint32_t framesync_val, framesync_old, framesync_init;
  183.  
  184.  
  185.         // inits
  186.  
  187.         dump->base.type    = TOZX_DUMP;
  188.         syncreq->base.type = TOZX_SYNCREQ;
  189.  
  190.         init_ctx(&from_zx,sock);
  191.         init_ctx(&to_zx,sock);
  192.  
  193.         was_hello = 0;
  194.         was_syncrply = 0;
  195.         was_framesync = 0;
  196.  
  197.  
  198.  
  199.  
  200.         actual_size = g.syncchk ? size_both : size_dump;
  201.         pkt = g.syncchk ? (struct packet *)syncreq : (struct packet *)dump;
  202.  
  203.  
  204.         // play loop
  205.         for(;;)
  206.         {
  207.                 // wait for frame sync
  208.                 do
  209.                 {
  210.                 if( !(rcvd=rcv_packet(&from_zx)) ) return;
  211.  
  212.                         if( rcvd->type==FROMZX_HELLO )
  213.                         {
  214.                                 if( was_hello )
  215.                                 {
  216.                                         fprintf(stderr,"%s: protocol error: received multiple ZX>> HELLO!\n",__PRETTY_FUNCTION__);
  217.                                         net_disconnect(sock);
  218.                                         exit(1);
  219.                                 }
  220.  
  221.                                 was_hello=1;
  222.  
  223.                                 struct rx_packet_hello * hello = (struct rx_packet_hello *)rcvd;
  224.  
  225.                                 char hell_str[256];
  226.                                 memset(hell_str,0,sizeof(hell_str));
  227.                                 if( hello->len > 0 )
  228.                                 {
  229.                                         strncpy(hell_str, hello->text, hello->len);
  230.                                 }
  231.                                 printf("Hello from ZX: %s\n",hell_str);
  232.                         }
  233.                         else if( rcvd->type==FROMZX_SYNCRPLY )
  234.                         {
  235.                                 if( !g.syncchk )
  236.                                 {
  237.                                         fprintf(stderr,"%s: protocol error: received ZX>> SYNCRPLY while it was not requested!\n",__PRETTY_FUNCTION__);
  238.                                         exit(1);
  239.                                 }
  240.                                 else if( was_syncrply ) // TODO: more checks for whether syncrply was requested and whether it carries correct data
  241.                                 {
  242.                                         fprintf(stderr,"%s: protocol error: received multiple ZX>> SYNCRPLY!\n",__PRETTY_FUNCTION__);
  243.                                         exit(1);
  244.                                 }
  245.  
  246.                                 was_syncrply=1;
  247.  
  248.                                 uint32_t from_ififo = ififo_get();
  249.                                
  250.                                 struct rx_packet_syncrply * syncrply = (struct rx_packet_syncrply *)rcvd;
  251.  
  252.                                 if( syncrply->value != from_ififo )
  253.                                 {
  254.                                         fprintf(stderr,"%s: protocol error: wrong data in ZX>> SYNCRPLY!\n",__PRETTY_FUNCTION__);
  255.                                         exit(1);
  256.                                 }
  257.                         }
  258.                 } while( rcvd->type!=FROMZX_FRAMESYNC );
  259. #ifdef DEBUG
  260. printf("%s: FRAMESYNC received: %08x!\n",__PRETTY_FUNCTION__,((struct rx_packet_framesync *)rcvd)->value);
  261. #endif
  262.                 // FRAMESYNC was finally received
  263.  
  264.                 if( !was_framesync )
  265.                 { // first framesync
  266.                         was_framesync = 1;
  267.  
  268.                         framesync_init = framesync_val = ((struct rx_packet_framesync *)rcvd)->value;
  269.  
  270.                         if( g.framechk )
  271.                         {
  272.                                 printf("FRAMECHK: initial framesync received, value = %d\n",framesync_init);
  273.                         }
  274.                 }
  275.                 else
  276.                 { // normal sequential framesyncs
  277.                         framesync_old = framesync_val;
  278.  
  279.                         framesync_val = ((struct rx_packet_framesync *)rcvd)->value;
  280.  
  281.                         if( g.framechk & (framesync_val-framesync_old)!=1 )
  282.                         {
  283.                                 printf("FRAMECHK: framesync skipped %d counts, total counts from initial: %d\n", framesync_val-framesync_old, framesync_val-framesync_init);
  284.                         }
  285.                 }
  286.  
  287.  
  288.  
  289.                 was_syncrply=0;
  290.  
  291.                 // assume we have (framesync_val-framesync_old) frames less
  292.                 if( frames_in_flight >= (framesync_val-framesync_old) ) frames_in_flight -= (framesync_val - framesync_old);
  293.  
  294.  
  295.  
  296.                 if( g.prebuf >= 0 )
  297.                 {
  298.                         // put many (or required number of) ZX<< DUMP (and, if needed, ZX<< SYNCREQ) packets in tx fifo
  299.                         while( get_in_free_size(&to_zx) >= actual_size )
  300.                         {
  301.                                 // make ZX<< SYNCREQ packet, if needed
  302.                                 if( g.syncchk )
  303.                                 {
  304.                                         uint32_t rnd_val = get_rnd();
  305.                                         memcpy(&syncreq->value, &rnd_val, sizeof(uint32_t));
  306.                                         ififo_put(rnd_val);
  307.                                 }
  308.  
  309.                                 // make ZX<< DUMP packet
  310.                                 memcpy(dump->data, ((struct frame_ay *)curr_frame->frame)->regs, 14);
  311.        
  312.                                 int remaining_size = actual_size;
  313.                                 int max_size;
  314.        
  315.                                 while( remaining_size )
  316.                                 {
  317.                                         max_size = get_in_cont_size(&to_zx);
  318.        
  319.                                         if( max_size > remaining_size ) max_size = remaining_size;
  320.        
  321.                                         memcpy(get_in_ptr(&to_zx), ((uint8_t *)pkt)+(actual_size-remaining_size), max_size);
  322.                                         set_write_size(&to_zx,max_size);
  323.                                         remaining_size -= max_size;
  324.                                 }
  325.  
  326.                                 // next frame
  327.                                 curr_frame = curr_frame->next;
  328.                                 if( !curr_frame ) curr_frame = frames;
  329.  
  330.                                 frames_in_flight++;
  331.  
  332.                                 // control how many frames must be pre-buffered
  333.                                 if( g.prebuf > 0 && frames_in_flight >= g.prebuf ) break;
  334.                         }
  335.                 }
  336.                 else
  337.                 {
  338.                         fprintf(stderr,"%s: g.buf_num < 0!\n",__PRETTY_FUNCTION__);
  339.                         exit(1);
  340.                 }
  341.  
  342.                
  343.                 // try to send the whole fifo. stop if actual len<requested or EAGAIN/EWOULDBLOCK
  344.                 int send_size;
  345.                 while( (send_size=get_out_cont_size(&to_zx))>0 )
  346.                 {
  347.                         ssize_t sent = send(to_zx.sock, get_out_ptr(&to_zx), send_size, MSG_DONTWAIT|MSG_NOSIGNAL);
  348.                         if( sent<0 )
  349.                         {
  350. #ifdef _WIN32
  351.                                 switch (errno=WSAGetLastError()){
  352. #else
  353.                                 switch (errno){
  354.                                         case EPIPE:
  355.                                         printf("Connection dropped!\n");
  356.                                         return;
  357. #if EAGAIN != EWOULDBLOCK
  358.                                         case EAGAIN:
  359.                                         break;
  360. #endif
  361. #endif
  362.                                         case EWOULDBLOCK:
  363.                                         break;
  364.                                         case ECONNRESET:
  365.                                         printf("Connection dropped!\n");
  366.                                         return;
  367.                                         default:
  368.                                         fprintf(stderr,"%s: send() returned (-1), strerror() gave: %s!\n",__PRETTY_FUNCTION__,strerror(errno));
  369.                                         exit(1);
  370.                                         break;
  371.                                 }
  372.                         }
  373.                         else if( sent>0 )
  374.                         {
  375.                                 set_read_size(&to_zx, sent);
  376.                         }
  377.  
  378.                         if( sent < send_size )
  379.                                 break;
  380.                 }
  381.         }
  382. }
  383.  
  384.