io.c
  1  /*
  2      io.c
  3      I/O controller chip emulation
  4  */
  5  
  6  #include "shared.h"
  7  
  8  port_t port[3];
  9  uint8 io_reg[0x10];
 10  
 11  
 12  void io_reset(void)
 13  {
 14      /* I/O register default settings */
 15      uint8 io_def[0x10] =
 16      {
 17          0xA0,
 18          0x7F, 0x7F, 0x7F,
 19          0x00, 0x00, 0x00, 
 20          0xFF, 0x00, 0x00,
 21          0xFF, 0x00, 0x00,  
 22          0xFB, 0x00, 0x00,  
 23      };
 24  
 25      /* Initialize I/O registers */
 26      memcpy(io_reg, io_def, 0x10);
 27  
 28      /*
 29          Port A : 3B pad
 30          Port B : Unused
 31          Port C : Unused
 32      */
 33      port[0].data_w = device_3b_w;   
 34      port[0].data_r = device_3b_r;
 35      port[1].data_w = NULL;
 36      port[1].data_r = NULL;
 37      port[2].data_w = NULL;
 38      port[2].data_r = NULL;
 39  }
 40  
 41  /*--------------------------------------------------------------------------*/
 42  /* I/O chip functions                                                       */
 43  /*--------------------------------------------------------------------------*/
 44  
 45  void gen_io_w(int offset, int value)
 46  {
 47      switch(offset)
 48      {
 49          case 0x01: /* Port A Data */
 50              value = ((value & 0x80) | (value & io_reg[offset+3]));
 51              io_reg[offset] = value;
 52              if(port[0].data_w) port[0].data_w(value);
 53              return;
 54  
 55          case 0x02: /* Port B Data */
 56              value = ((value & 0x80) | (value & io_reg[offset+3]));
 57              io_reg[offset] = value;
 58              if(port[1].data_w) port[1].data_w(value);
 59              return;
 60  
 61          case 0x03: /* Port C Data */
 62              value = ((value & 0x80) | (value & io_reg[offset+3]));
 63              io_reg[offset] = value;
 64              if(port[2].data_w) port[2].data_w(value);
 65              return;  
 66  
 67          case 0x04: /* Port A Ctrl */
 68          case 0x05: /* Port B Ctrl */
 69          case 0x06: /* Port C Ctrl */
 70              io_reg[offset] = value & 0xFF;
 71              break;
 72  
 73          case 0x07: /* Port A TxData */
 74          case 0x0A: /* Port B TxData */
 75          case 0x0D: /* Port C TxData */
 76              io_reg[offset] = value;
 77              break;
 78  
 79          case 0x09: /* Port A S-Ctrl */
 80          case 0x0C: /* Port B S-Ctrl */
 81          case 0x0F: /* Port C S-Ctrl */
 82              io_reg[offset] = (value & 0xF8);
 83              break;
 84      }
 85  }
 86  
 87  int gen_io_r(int offset)
 88  {
 89      uint8 temp;
 90      uint8 has_scd = 0x20; /* No Sega CD unit attached */
 91      uint8 gen_ver = 0x00; /* Version 0 hardware */
 92  
 93      switch(offset)
 94      {
 95          case 0x00: /* Version */
 96              switch(rom_version())
 97              {
 98                  case 'J':
 99                      temp = 0x00;
100                      break;
101                  case 'U':
102                      temp = 0x80;
103                      break;
104                  case 'E':
105                      temp = 0xC0;
106                      break;
107                  case 'A':
108                      temp = 0xC0;
109                      break;
110                  case 'B':
111                      temp = 0xC0;
112                      break;
113                  case '4':
114                      temp = 0x80;
115                      break;
116                  default:
117                      temp = 0x80;
118                      break;
119              }
120              return (temp | has_scd | gen_ver);
121              break;
122  
123          case 0x01: /* Port A Data */
124              if(port[0].data_r) return ((io_reg[offset] & 0x80) | port[0].data_r());
125              return (io_reg[offset] | ((~io_reg[offset+3]) & 0x7F));
126  
127          case 0x02: /* Port B Data */
128              if(port[1].data_r) return ((io_reg[offset] & 0x80) | port[1].data_r());
129              return (io_reg[offset] | ((~io_reg[offset+3]) & 0x7F));
130  
131          case 0x03: /* Port C Data */
132              if(port[2].data_r) return ((io_reg[offset] & 0x80) | port[2].data_r());
133              return (io_reg[offset] | ((~io_reg[offset+3]) & 0x7F));
134      }
135  
136      return (io_reg[offset]);
137  }
138  
139  /*--------------------------------------------------------------------------*/
140  /* Input callbacks                                                          */
141  /*--------------------------------------------------------------------------*/
142  
143  uint8 pad_2b_r(void)
144  {
145      uint8 temp = 0x3F;
146      if(input.pad[0] & INPUT_UP)    temp &= ~0x01;
147      if(input.pad[0] & INPUT_DOWN)  temp &= ~0x02;
148      if(input.pad[0] & INPUT_LEFT)  temp &= ~0x04;
149      if(input.pad[0] & INPUT_RIGHT) temp &= ~0x08;
150      if(input.pad[0] & INPUT_B)     temp &= ~0x10;
151      if(input.pad[0] & INPUT_C)     temp &= ~0x20;
152      return (temp);
153  }
154  
155  static int th = 0;
156  
157  uint8 device_3b_r(void)
158  {
159      uint8 temp = 0x3F;
160  
161      if(th)
162      {
163          temp = 0x3f;
164          if(input.pad[0] & INPUT_UP)    temp &= ~0x01;
165          if(input.pad[0] & INPUT_DOWN)  temp &= ~0x02;
166          if(input.pad[0] & INPUT_LEFT)  temp &= ~0x04;
167          if(input.pad[0] & INPUT_RIGHT) temp &= ~0x08;
168          if(input.pad[0] & INPUT_B)     temp &= ~0x10;
169          if(input.pad[0] & INPUT_C)     temp &= ~0x20;
170          return (temp | 0x40);
171      }
172      else
173      {
174          temp = 0x33;
175          if(input.pad[0] & INPUT_UP)    temp &= ~0x01;
176          if(input.pad[0] & INPUT_DOWN)  temp &= ~0x02;
177          if(input.pad[0] & INPUT_A)     temp &= ~0x10;
178          if(input.pad[0] & INPUT_START) temp &= ~0x20;
179          return (temp);
180      }
181  }
182  
183  void device_3b_w(uint8 data)
184  {
185      th = (data & 0x40);
186  }