mym2serial_win32.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*******************************************************************
  2. * MYM Player to Serial port
  3. * (c) 2014 Manoel "Godzil" Trapier
  4. *
  5. * This file is base on the mym2ym by
  6. * Marq/Lieves!Tuore & Fit (marq@iki.fi)
  7. *
  8. * The YM writing part have been removed and replaced by code to
  9. * send register dump to the serial port.
  10. **************************** Licence ******************************
  11. * This file is licenced under the licence:
  12. * WTFPL v2 Postal Card Edition:
  13. *
  14. * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
  15. * Version 2, December 2004
  16. *
  17. * Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
  18. *
  19. * Everyone is permitted to copy and distribute verbatim or modified
  20. * copies of this license document, and changing it is allowed as long
  21. * as the name is changed.
  22. *
  23. * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
  24. * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  25. *
  26. * 0. You just DO WHAT THE FUCK YOU WANT TO.
  27. * 1. If you like this software you can send me a (virtual) postals
  28. * card. Details bellow:
  29. *
  30. * < godzil-nospambot at godzil dot net >
  31. *
  32. * If you want to send a real postal card, send me an email, I'll
  33. * give you my address. Of course remove the -nospambot from my
  34. * e-mail address.
  35. *
  36. ******************************************************************/
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. // #include <unistd.h> (replaced w/ void usleep(__int64 usec) )
  41. #include <fcntl.h>
  42. /*
  43. this is the i/o tool popular with linux, porting to windows is very hard
  44. #include <termios.h> //does not exist on windows
  45. */
  46. #include <windows.h>
  47. #include <errno.h>
  48. #define REGS 14
  49. #define FRAG 128 /* Nuber of rows to compress at a time */
  50. #define OFFNUM 14 /* Bits needed to store off+num of FRAG */
  51. unsigned readbits(int bits,FILE *f);
  52. void usleep(__int64 usec);
  53. int set_interface_attribs (int fd, int speed, int parity);
  54. void set_blocking (int fd, int should_block);
  55. int main(int argc,char *argv[])
  56. {
  57. unsigned char *data[REGS], /* The unpacked YM data */
  58. c;
  59. int serial_fd;
  60. unsigned current[REGS];
  61. FILE *f;
  62. long n,i,row,index,compoff,compnum,
  63. bytes=0,
  64. regbits[REGS]={8,4,8,4, 8,4,5,8, 5,5,5,8, 8,8}; /* Bits per PSG reg */
  65. unsigned long rows;
  66. HANDLE hComPort;
  67. int Status;
  68. DWORD dNoOfBytesWritten = 0;
  69. char tmp[80];
  70. strcpy(tmp, "\\\\.\\");
  71. strcat(tmp, argv[2]);
  72. printf("%s \n", tmp);
  73. hComPort = CreateFile(tmp, //port name
  74. GENERIC_READ | GENERIC_WRITE, //Read/Write
  75. 0, // No Sharing
  76. NULL, // No Security
  77. OPEN_EXISTING, // Open existing port only
  78. 0, // Non Overlapped I/O
  79. NULL); // Null for Comm Devices
  80. if (hComPort == INVALID_HANDLE_VALUE)
  81. {
  82. printf("Error in opening serial port");
  83. CloseHandle(hComPort);
  84. return -1;
  85. }
  86. else
  87. {
  88. printf("opening serial port successful");
  89. }
  90. // set up com port windows style
  91. DCB dcbSerialParams = { 0 }; // Initializing DCB structure
  92. dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
  93. // read state
  94. Status = GetCommState(hComPort, &dcbSerialParams);
  95. // set state
  96. dcbSerialParams.BaudRate = CBR_115200;// Setting BaudRate = 115200
  97. dcbSerialParams.ByteSize = 8; // Setting ByteSize = 8
  98. dcbSerialParams.StopBits = ONESTOPBIT;// Setting StopBits = 1
  99. dcbSerialParams.Parity = NOPARITY; // Setting Parity = None
  100. // write state
  101. SetCommState(hComPort, &dcbSerialParams);
  102. if(argc!=3)
  103. {
  104. printf("Usage: mym2serial source.mym /dev/serial\n");
  105. return(EXIT_FAILURE);
  106. }
  107. if((f=fopen(argv[1],"rb"))==NULL)
  108. {
  109. printf("File open error.\n");
  110. return(EXIT_FAILURE);
  111. }
  112. rows=fgetc(f); /* Read the number of rows */
  113. rows+=fgetc(f)<<8u;
  114. for(n=0;n<REGS;n++) /* Allocate memory for rows */
  115. {
  116. if((data[n]=(unsigned char *)malloc(rows+FRAG))==NULL)
  117. {
  118. printf("Out of memory.\n");
  119. exit(EXIT_FAILURE);
  120. }
  121. }
  122. for(n=0;n<rows;n+=FRAG) /* Go through rows... */
  123. {
  124. for(i=0;i<REGS;i++) /* ... and registers */
  125. {
  126. index=0;
  127. if(!readbits(1,f)) /* Totally unchanged fragment */
  128. {
  129. for(row=0;row<FRAG;row++)
  130. data[i][n+row]=current[i];
  131. continue;
  132. }
  133. while(index<FRAG) /* Packed fragment */
  134. {
  135. if(!readbits(1,f)) /* Unchanged register */
  136. {
  137. data[i][n+index]=current[i];
  138. index++;
  139. }
  140. else
  141. {
  142. if(readbits(1,f)) /* Raw data */
  143. {
  144. c=readbits(regbits[i],f);
  145. current[i]=data[i][n+index]=c;
  146. index++;
  147. }
  148. else /* Reference to previous data */
  149. {
  150. compoff=readbits(OFFNUM/2,f)+index;
  151. compnum=readbits(OFFNUM/2,f)+1;
  152. for(row=0;row<compnum;row++)
  153. {
  154. c=data[i][n-FRAG+compoff+row];
  155. data[i][n+index]=current[i]=c;
  156. index++;
  157. }
  158. }
  159. }
  160. }
  161. }
  162. }
  163. fclose(f);
  164. //serial_fd = open (argv[2], O_RDWR | O_NOCTTY | O_SYNC);
  165. if (/*serial_fd > 0*/ 1 )
  166. {
  167. char buffer[14];
  168. printf("Serial opened...\n");
  169. // set_interface_attribs (serial_fd, B115200, 0); // 115200 8n1
  170. // set_blocking (serial_fd, 0);
  171. /* Wait a little bit to be sure that the other end is ready... */
  172. usleep(2000); //sleep(2);
  173. printf("Playing now!\n");
  174. for(n=0;n<rows;n++)
  175. {
  176. for(i=0;i<REGS;i++)
  177. {
  178. buffer[i] = data[i][n];
  179. }
  180. //write(serial_fd, buffer, 14);
  181. Status = WriteFile(hComPort, // Handle to the Serial port
  182. buffer, // Data to be written to the port
  183. 14, //No of bytes to write
  184. &dNoOfBytesWritten, //Bytes written
  185. NULL);
  186. // 50Hz so wait a little bit...
  187. printf("\rVBL%ld ", n);
  188. fflush(stdout);
  189. usleep(1000*20); /* 50Hz */
  190. }
  191. printf("\n");
  192. }
  193. else
  194. {
  195. printf("Opening error...\n");
  196. }
  197. CloseHandle(hComPort);
  198. return(EXIT_SUCCESS);
  199. }
  200. /* Reads bits from a while */
  201. unsigned readbits(int bits,FILE *f)
  202. {
  203. static unsigned char byte;
  204. static int off=7;
  205. unsigned n,data=0;
  206. /* Go through the bits and read a whole byte if needed */
  207. for(n=0;n<bits;n++)
  208. {
  209. data<<=1;
  210. if(++off==8)
  211. {
  212. byte=fgetc(f);
  213. off=0;
  214. }
  215. if(byte&(0x80>>off))
  216. data++;
  217. }
  218. return(data);
  219. }
  220. void usleep(__int64 usec)
  221. {
  222. HANDLE timer;
  223. LARGE_INTEGER ft;
  224. ft.QuadPart = -(10*usec); // Convert to 100 nanosecond interval, negative value indicates relative time
  225. timer = CreateWaitableTimer(NULL, TRUE, NULL);
  226. SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
  227. WaitForSingleObject(timer, INFINITE);
  228. CloseHandle(timer);
  229. }
  230. /*
  231. int set_interface_attribs (int fd, int speed, int parity)
  232. {
  233. struct termios tty;
  234. memset (&tty, 0, sizeof tty);
  235. if (tcgetattr (fd, &tty) != 0)
  236. {
  237. printf("error %d from tcgetattr", errno);
  238. return -1;
  239. }
  240. cfsetospeed (&tty, speed);
  241. cfsetispeed (&tty, speed);
  242. tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
  243. // disable IGNBRK for mismatched speed tests; otherwise receive break
  244. // as \000 chars
  245. tty.c_iflag &= ~IGNBRK; // disable break processing
  246. tty.c_lflag = 0; // no signaling chars, no echo,
  247. // no canonical processing
  248. tty.c_oflag = 0; // no remapping, no delays
  249. tty.c_cc[VMIN] = 0; // read doesn't block
  250. tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
  251. tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
  252. tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
  253. // enable reading
  254. tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
  255. tty.c_cflag |= parity;
  256. tty.c_cflag &= ~CSTOPB;
  257. tty.c_cflag &= ~CRTSCTS;
  258. if (tcsetattr (fd, TCSANOW, &tty) != 0)
  259. {
  260. printf ("error %d from tcsetattr", errno);
  261. return -1;
  262. }
  263. return 0;
  264. }
  265. */
  266. /*
  267. void set_blocking (int fd, int should_block)
  268. {
  269. struct termios tty;
  270. memset (&tty, 0, sizeof tty);
  271. if (tcgetattr (fd, &tty) != 0)
  272. {
  273. printf ("error %d from tggetattr", errno);
  274. return;
  275. }
  276. tty.c_cc[VMIN] = should_block ? 1 : 0;
  277. tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
  278. if (tcsetattr (fd, TCSANOW, &tty) != 0)
  279. printf ("error %d setting term attributes", errno);
  280. }
  281. */