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 }