/MAME/src/machine/tait8741.c

https://github.com/joolswills/mameox · C · 360 lines · 296 code · 28 blank · 36 comment · 35 complexity · 9c3464319654e779ca44c0fed671799a MD5 · raw file

  1. /*
  2. Taito 8741 emulation
  3. 1.comminucation main and sub cpu
  4. 2.dipswitch and key handling
  5. program types
  6. */
  7. #include "driver.h"
  8. #include "tait8741.h"
  9. #define __log__ 0
  10. #define CMD_IDLE 0
  11. #define CMD_08 1
  12. #define CMD_4a 2
  13. typedef struct TAITO8741_status{
  14. unsigned char toData; /* to host data */
  15. unsigned char fromData; /* from host data */
  16. unsigned char fromCmd; /* from host command */
  17. unsigned char status; /* b0 = rd ready,b1 = wd full,b2 = cmd ?? */
  18. unsigned char mode;
  19. unsigned char phase;
  20. unsigned char txd[8];
  21. unsigned char rxd[8];
  22. unsigned char parallelselect;
  23. unsigned char txpoint;
  24. int connect;
  25. unsigned char pending4a;
  26. int serial_out;
  27. int coins;
  28. read8_handler portHandler;
  29. }I8741;
  30. static const struct TAITO8741interface *intf;
  31. //static I8741 *taito8741;
  32. static I8741 taito8741[MAX_TAITO8741];
  33. /* for host data , write */
  34. static void taito8741_hostdata_w(I8741 *st,int data)
  35. {
  36. st->toData = data;
  37. st->status |= 0x01;
  38. }
  39. /* from host data , read */
  40. static int taito8741_hostdata_r(I8741 *st)
  41. {
  42. if( !(st->status & 0x02) ) return -1;
  43. st->status &= 0xfd;
  44. return st->fromData;
  45. }
  46. /* from host command , read */
  47. static int taito8741_hostcmd_r(I8741 *st)
  48. {
  49. if(!(st->status & 0x04)) return -1;
  50. st->status &= 0xfb;
  51. return st->fromCmd;
  52. }
  53. /* TAITO8741 I8741 emulation */
  54. void taito8741_serial_rx(I8741 *st,unsigned char *data)
  55. {
  56. memcpy(st->rxd,data,8);
  57. }
  58. /* timer callback of serial tx finish */
  59. void taito8741_serial_tx(int num)
  60. {
  61. I8741 *st = &taito8741[num];
  62. I8741 *sst;
  63. if( st->mode==TAITO8741_MASTER)
  64. st->serial_out = 1;
  65. st->txpoint = 1;
  66. if(st->connect >= 0 )
  67. {
  68. sst = &taito8741[st->connect];
  69. /* transfer data */
  70. taito8741_serial_rx(sst,st->txd);
  71. #if __log__
  72. logerror("8741-%d Serial data TX to %d\n",num,st->connect);
  73. #endif
  74. if( sst->mode==TAITO8741_SLAVE)
  75. sst->serial_out = 1;
  76. }
  77. }
  78. void TAITO8741_reset(int num)
  79. {
  80. I8741 *st = &taito8741[num];
  81. st->status = 0x00;
  82. st->phase = 0;
  83. st->parallelselect = 0;
  84. st->txpoint = 1;
  85. st->pending4a = 0;
  86. st->serial_out = 0;
  87. st->coins = 0;
  88. memset(st->rxd,0,8);
  89. memset(st->txd,0,8);
  90. }
  91. /* 8741 update */
  92. static void taito8741_update(int num)
  93. {
  94. I8741 *st,*sst;
  95. int next = num;
  96. int data;
  97. do{
  98. num = next;
  99. st = &taito8741[num];
  100. if( st->connect != -1 )
  101. sst = &taito8741[st->connect];
  102. else sst = 0;
  103. next = -1;
  104. /* check pending command */
  105. switch(st->phase)
  106. {
  107. case CMD_08: /* serial data latch */
  108. if( st->serial_out)
  109. {
  110. st->status &= 0xfb; /* patch for gsword */
  111. st->phase = CMD_IDLE;
  112. next = num; /* continue this chip */
  113. }
  114. break;
  115. case CMD_4a: /* wait for syncronus ? */
  116. if(!st->pending4a)
  117. {
  118. taito8741_hostdata_w(st,0);
  119. st->phase = CMD_IDLE;
  120. next = num; /* continue this chip */
  121. }
  122. break;
  123. case CMD_IDLE:
  124. /* ----- data in port check ----- */
  125. data = taito8741_hostdata_r(st);
  126. if( data != -1 )
  127. {
  128. switch(st->mode)
  129. {
  130. case TAITO8741_MASTER:
  131. case TAITO8741_SLAVE:
  132. /* buffering transmit data */
  133. if( st->txpoint < 8 )
  134. {
  135. //if (st->txpoint == 0 && num==1 && data&0x80) logerror("Coin Put\n");
  136. st->txd[st->txpoint++] = data;
  137. }
  138. break;
  139. case TAITO8741_PORT:
  140. if( data & 0xf8)
  141. { /* ?? */
  142. }
  143. else
  144. { /* port select */
  145. st->parallelselect = data & 0x07;
  146. taito8741_hostdata_w(st,st->portHandler ? st->portHandler(st->parallelselect) : 0);
  147. }
  148. }
  149. }
  150. /* ----- new command fetch ----- */
  151. data = taito8741_hostcmd_r(st);
  152. switch( data )
  153. {
  154. case -1: /* no command data */
  155. break;
  156. case 0x00: /* read from parallel port */
  157. taito8741_hostdata_w(st,st->portHandler ? st->portHandler(0) : 0 );
  158. break;
  159. case 0x01: /* read receive buffer 0 */
  160. case 0x02: /* read receive buffer 1 */
  161. case 0x03: /* read receive buffer 2 */
  162. case 0x04: /* read receive buffer 3 */
  163. case 0x05: /* read receive buffer 4 */
  164. case 0x06: /* read receive buffer 5 */
  165. case 0x07: /* read receive buffer 6 */
  166. //if (data == 2 && num==0 && st->rxd[data-1]&0x80) logerror("Coin Get\n");
  167. taito8741_hostdata_w(st,st->rxd[data-1]);
  168. break;
  169. case 0x08: /* latch received serial data */
  170. st->txd[0] = st->portHandler ? st->portHandler(0) : 0;
  171. if( sst )
  172. {
  173. timer_set (TIME_NOW,num,taito8741_serial_tx);
  174. st->serial_out = 0;
  175. st->status |= 0x04;
  176. st->phase = CMD_08;
  177. }
  178. break;
  179. case 0x0a: /* 8741-0 : set serial comminucation mode 'MASTER' */
  180. //st->mode = TAITO8741_MASTER;
  181. break;
  182. case 0x0b: /* 8741-1 : set serial comminucation mode 'SLAVE' */
  183. //st->mode = TAITO8741_SLAVE;
  184. break;
  185. case 0x1f: /* 8741-2,3 : ?? set parallelport mode ?? */
  186. case 0x3f: /* 8741-2,3 : ?? set parallelport mode ?? */
  187. case 0xe1: /* 8741-2,3 : ?? set parallelport mode ?? */
  188. st->mode = TAITO8741_PORT;
  189. st->parallelselect = 1; /* preset read number */
  190. break;
  191. case 0x62: /* 8741-3 : ? */
  192. break;
  193. case 0x4a: /* ?? syncronus with other cpu and return 00H */
  194. if( sst )
  195. {
  196. if(sst->pending4a)
  197. {
  198. sst->pending4a = 0; /* syncronus */
  199. taito8741_hostdata_w(st,0); /* return for host */
  200. next = st->connect;
  201. }
  202. else st->phase = CMD_4a;
  203. }
  204. break;
  205. case 0x80: /* 8741-3 : return check code */
  206. taito8741_hostdata_w(st,0x66);
  207. break;
  208. case 0x81: /* 8741-2 : return check code */
  209. taito8741_hostdata_w(st,0x48);
  210. break;
  211. case 0xf0: /* GSWORD 8741-1 : initialize ?? */
  212. break;
  213. case 0x82: /* GSWORD 8741-2 unknown */
  214. break;
  215. }
  216. break;
  217. }
  218. }while(next>=0);
  219. }
  220. int TAITO8741_start(const struct TAITO8741interface *taito8741intf)
  221. {
  222. int i;
  223. intf = taito8741intf;
  224. //taito8741 = (I8741 *)osd_malloc(intf->num*sizeof(I8741));
  225. //if( taito8741 == 0 ) return 1;
  226. for(i=0;i<intf->num;i++)
  227. {
  228. taito8741[i].connect = intf->serial_connect[i];
  229. taito8741[i].portHandler = intf->portHandler_r[i];
  230. taito8741[i].mode = intf->mode[i];
  231. TAITO8741_reset(i);
  232. }
  233. return 0;
  234. }
  235. /* read status port */
  236. static int I8741_status_r(int num)
  237. {
  238. I8741 *st = &taito8741[num];
  239. taito8741_update(num);
  240. #if __log__
  241. logerror("8741-%d ST Read %02x PC=%04x\n",num,st->status,activecpu_get_pc());
  242. #endif
  243. return st->status;
  244. }
  245. /* read data port */
  246. static int I8741_data_r(int num)
  247. {
  248. I8741 *st = &taito8741[num];
  249. int ret = st->toData;
  250. st->status &= 0xfe;
  251. #if __log__
  252. logerror("8741-%d DATA Read %02x PC=%04x\n",num,ret,activecpu_get_pc());
  253. #endif
  254. /* update chip */
  255. taito8741_update(num);
  256. switch( st->mode )
  257. {
  258. case TAITO8741_PORT: /* parallel data */
  259. taito8741_hostdata_w(st,st->portHandler ? st->portHandler(st->parallelselect) : 0);
  260. break;
  261. }
  262. return ret;
  263. }
  264. /* Write data port */
  265. static void I8741_data_w(int num, int data)
  266. {
  267. I8741 *st = &taito8741[num];
  268. #if __log__
  269. logerror("8741-%d DATA Write %02x PC=%04x\n",num,data,activecpu_get_pc());
  270. #endif
  271. st->fromData = data;
  272. st->status |= 0x02;
  273. /* update chip */
  274. taito8741_update(num);
  275. }
  276. /* Write command port */
  277. static void I8741_command_w(int num, int data)
  278. {
  279. I8741 *st = &taito8741[num];
  280. #if __log__
  281. logerror("8741-%d CMD Write %02x PC=%04x\n",num,data,activecpu_get_pc());
  282. #endif
  283. st->fromCmd = data;
  284. st->status |= 0x04;
  285. /* update chip */
  286. taito8741_update(num);
  287. }
  288. /* Write port handler */
  289. WRITE8_HANDLER( TAITO8741_0_w )
  290. {
  291. if(offset&1) I8741_command_w(0,data);
  292. else I8741_data_w(0,data);
  293. }
  294. WRITE8_HANDLER( TAITO8741_1_w )
  295. {
  296. if(offset&1) I8741_command_w(1,data);
  297. else I8741_data_w(1,data);
  298. }
  299. WRITE8_HANDLER( TAITO8741_2_w )
  300. {
  301. if(offset&1) I8741_command_w(2,data);
  302. else I8741_data_w(2,data);
  303. }
  304. WRITE8_HANDLER( TAITO8741_3_w )
  305. {
  306. if(offset&1) I8741_command_w(3,data);
  307. else I8741_data_w(3,data);
  308. }
  309. /* Read port handler */
  310. READ8_HANDLER( TAITO8741_0_r )
  311. {
  312. if(offset&1) return I8741_status_r(0);
  313. return I8741_data_r(0);
  314. }
  315. READ8_HANDLER( TAITO8741_1_r )
  316. {
  317. if(offset&1) return I8741_status_r(1);
  318. return I8741_data_r(1);
  319. }
  320. READ8_HANDLER( TAITO8741_2_r )
  321. {
  322. if(offset&1) return I8741_status_r(2);
  323. return I8741_data_r(2);
  324. }
  325. READ8_HANDLER( TAITO8741_3_r )
  326. {
  327. if(offset&1) return I8741_status_r(3);
  328. return I8741_data_r(3);
  329. }