fix an issue of lost inputs in direct control mode
[teensytas.git] / host / main.c
index 2f13059..73b8a9f 100644 (file)
@@ -1,3 +1,28 @@
+/*
+ * TeensyTAS, TAS input player for MegaDrive
+ * Copyright (c) 2014 notaz
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -587,13 +612,22 @@ out:
   return 2;
 }
 
-static int tas_data_to_teensy(uint8_t b, uint8_t *data)
+static int tas_data_to_teensy(uint8_t b, uint8_t *data, FILE *logf)
 {
+  uint8_t t;
+
   /* SCBA RLDU */
   /*     v     */
   /* ?0SA 00DU, ?1CB RLDU */
   data[0] = (b & 0x13) | ((b >> 2) & 0x20);
   data[1] = (b & 0x0f) | ((b >> 1) & 0x30);
+
+  if (logf != NULL) {
+    fwrite(&data[0], 1, 1, logf);
+    t = data[1] | 0x40; // expected TH
+    fwrite(&t, 1, 1, logf);
+  }
+
   return 2;
 }
 
@@ -627,7 +661,7 @@ int main(int argc, char *argv[])
   struct teensy_dev dev;
   struct usbdevfs_urb urb[URB_CNT];
   struct usbdevfs_urb *reaped_urb;
-  int fixed_input_changed;
+  int fixed_input_changed = 0;
   int evdev_fds[16];
   int evdev_fd_cnt = 0;
   int evdev_support;
@@ -636,8 +670,10 @@ int main(int argc, char *argv[])
   fd_set rfds, wfds;
   const char *tasfn = NULL;
   const char *outfn = NULL;
+  const char *logfn = NULL;
   uint8_t *tas_data = NULL;
   int use_vsync = 0; // frame increment on vsync
+  int no_start_seq = 0;
   int tas_skip = 0;
   int enable_sent = 0;
   int abort_sent = 0;
@@ -649,6 +685,7 @@ int main(int argc, char *argv[])
   struct timeval *timeout = NULL;
   struct timeval tout;
   FILE *outf = NULL;
+  FILE *logf = NULL;
   int i, ret = -1;
   int fd;
 
@@ -667,6 +704,12 @@ int main(int argc, char *argv[])
           missing_arg(i);
         outfn = argv[i];
         continue;
+      case 'l':
+        i++;
+        if (argv[i] == NULL)
+          missing_arg(i);
+        logfn = argv[i];
+        continue;
       case 's':
         i++;
         if (argv[i] == NULL)
@@ -676,6 +719,9 @@ int main(int argc, char *argv[])
       case 'v':
         use_vsync = 1;
         continue;
+      case 'n':
+        no_start_seq = 1;
+        continue;
       default:
         fprintf(stderr, "bad arg: %s\n", argv[i]);
         return 1;
@@ -775,7 +821,16 @@ int main(int argc, char *argv[])
   if (outfn != NULL) {
     outf = fopen(outfn, "w");
     if (outf == NULL) {
-      fprintf(stderr, "fopen %s: ", tasfn);
+      fprintf(stderr, "fopen %s: ", outfn);
+      perror("");
+      return 1;
+    }
+  }
+
+  if (logfn != NULL) {
+    logf = fopen(logfn, "wb");
+    if (logf == NULL) {
+      fprintf(stderr, "fopen %s: ", logfn);
       perror("");
       return 1;
     }
@@ -863,12 +918,13 @@ int main(int argc, char *argv[])
       switch (c) {
       case 'r':
         enable_sent = 0;
+        if (logf != NULL)
+          rewind(logf);
         break;
       }
     }
 
     /* something from input devices? */
-    fixed_input_changed = 0;
     for (i = 0; i < evdev_fd_cnt; i++) {
       if (FD_ISSET(evdev_fds[i], &rfds)) {
         fixed_input_changed |=
@@ -921,7 +977,7 @@ int main(int argc, char *argv[])
 
             for (i = 0; i < sizeof(pkt_out.data); ) {
               i += tas_data_to_teensy(tas_data[frames_sent],
-                     pkt_out.data + i);
+                     pkt_out.data + i, logf);
 
               frames_sent++;
               if (frames_sent >= frame_count)
@@ -929,8 +985,11 @@ int main(int argc, char *argv[])
             }
             pkt_out.size = i;
           }
-          else
+          else {
             pkt_out.type = PKT_STREAM_END;
+            if (logf != NULL)
+              fflush(logf);
+          }
 
           ret = submit_urb(dev.fd, &urb[URB_DATA_OUT],
                   dev.ifaces[0].ep_out, &pkt_out, sizeof(pkt_out));
@@ -963,6 +1022,12 @@ int main(int argc, char *argv[])
         /* debug text */
         buf_dbg[reaped_urb->actual_length] = 0;
         printf("%s", buf_dbg);
+
+        // continue receiving debug before sending out stuff
+        tout.tv_sec = 0;
+        tout.tv_usec = 1000;
+        timeout = &tout;
+        continue;
       }
       else {
         fprintf(stderr, "reaped unknown urb? %p #%zu\n",
@@ -981,6 +1046,7 @@ int main(int argc, char *argv[])
       pkt_out.enable.stream_to = (tas_data != NULL);
       pkt_out.enable.stream_from = (outf != NULL);
       pkt_out.enable.use_readinc = !use_vsync;
+      pkt_out.enable.no_start_seq = no_start_seq;
 
       ret = submit_urb(dev.fd, &urb[URB_DATA_OUT], dev.ifaces[0].ep_out,
                        &pkt_out, sizeof(pkt_out));
@@ -1004,6 +1070,7 @@ int main(int argc, char *argv[])
         perror("USBDEVFS_SUBMITURB PKT_FIXED_STATE");
         break;
       }
+      fixed_input_changed = 0;
       pending_urbs |= 1 << URB_DATA_OUT;
       continue;
     }
@@ -1033,6 +1100,8 @@ dev_close:
 
   if (outf != NULL)
     fclose(outf);
+  if (logf != NULL)
+    fclose(logf);
 
   if (dev.fd != -1) {
     /* deal with pending URBs */