1 // license:BSD-3-Clause 2 // copyright-holders:Eric Smith 3 /* 4 * mathbox.c: math box simulation (Battlezone/Red Baron/Tempest) 5 * 6 * Copyright Eric Smith 7 * 8 */ 9 10 #include "burnint.h" 11 #include "mathbox.h" 12 13 14 /* math box scratch registers */ 15 static INT16 m_reg[16]; 16 17 /* math box result */ 18 static INT16 m_result; 19 20 21 #define REG0 m_reg [0x00] 22 #define REG1 m_reg [0x01] 23 #define REG2 m_reg [0x02] 24 #define REG3 m_reg [0x03] 25 #define REG4 m_reg [0x04] 26 #define REG5 m_reg [0x05] 27 #define REG6 m_reg [0x06] 28 #define REG7 m_reg [0x07] 29 #define REG8 m_reg [0x08] 30 #define REG9 m_reg [0x09] 31 #define REGa m_reg [0x0a] 32 #define REGb m_reg [0x0b] 33 #define REGc m_reg [0x0c] 34 #define REGd m_reg [0x0d] 35 #define REGe m_reg [0x0e] 36 #define REGf m_reg [0x0f] 37 mathbox_reset()38void mathbox_reset() 39 { 40 m_result = 0; 41 memset(m_reg, 0, sizeof(m_reg)); 42 } 43 mathbox_scan(INT32 nAction,INT32 *)44void mathbox_scan(INT32 nAction, INT32 *) 45 { 46 SCAN_VAR(m_reg); 47 SCAN_VAR(m_result); 48 } 49 50 mathbox_go_write(UINT8 offset,UINT8 data)51void mathbox_go_write(UINT8 offset, UINT8 data) 52 { 53 INT32 mb_temp = 0; /* temp 32-bit multiply results */ 54 INT16 mb_q = 0; /* temp used in division */ 55 INT32 msb = 0; 56 57 switch (offset) 58 { 59 case 0x00: m_result = REG0 = (REG0 & 0xff00) | data; break; 60 case 0x01: m_result = REG0 = (REG0 & 0x00ff) | (data << 8); break; 61 case 0x02: m_result = REG1 = (REG1 & 0xff00) | data; break; 62 case 0x03: m_result = REG1 = (REG1 & 0x00ff) | (data << 8); break; 63 case 0x04: m_result = REG2 = (REG2 & 0xff00) | data; break; 64 case 0x05: m_result = REG2 = (REG2 & 0x00ff) | (data << 8); break; 65 case 0x06: m_result = REG3 = (REG3 & 0xff00) | data; break; 66 case 0x07: m_result = REG3 = (REG3 & 0x00ff) | (data << 8); break; 67 case 0x08: m_result = REG4 = (REG4 & 0xff00) | data; break; 68 case 0x09: m_result = REG4 = (REG4 & 0x00ff) | (data << 8); break; 69 70 case 0x0a: m_result = REG5 = (REG5 & 0xff00) | data; break; 71 /* note: no function loads low part of REG5 without performing a computation */ 72 73 case 0x0c: m_result = REG6 = data; break; 74 /* note: no function loads high part of REG6 */ 75 76 case 0x15: m_result = REG7 = (REG7 & 0xff00) | data; break; 77 case 0x16: m_result = REG7 = (REG7 & 0x00ff) | (data << 8); break; 78 79 case 0x1a: m_result = REG8 = (REG8 & 0xff00) | data; break; 80 case 0x1b: m_result = REG8 = (REG8 & 0x00ff) | (data << 8); break; 81 82 case 0x0d: m_result = REGa = (REGa & 0xff00) | data; break; 83 case 0x0e: m_result = REGa = (REGa & 0x00ff) | (data << 8); break; 84 case 0x0f: m_result = REGb = (REGb & 0xff00) | data; break; 85 case 0x10: m_result = REGb = (REGb & 0x00ff) | (data << 8); break; 86 87 case 0x17: m_result = REG7; break; 88 case 0x19: m_result = REG8; break; 89 case 0x18: m_result = REG9; break; 90 91 case 0x0b: 92 93 REG5 = (REG5 & 0x00ff) | (data << 8); 94 95 REGf = (INT16)0xffff; 96 REG4 -= REG2; 97 REG5 -= REG3; 98 99 step_048: 100 101 mb_temp = ((INT32) REG0) * ((INT32) REG4); 102 REGc = mb_temp >> 16; 103 REGe = mb_temp & 0xffff; 104 105 mb_temp = ((INT32) -REG1) * ((INT32) REG5); 106 REG7 = mb_temp >> 16; 107 mb_q = mb_temp & 0xffff; 108 109 REG7 += REGc; 110 111 /* rounding */ 112 REGe = (REGe >> 1) & 0x7fff; 113 REGc = (mb_q >> 1) & 0x7fff; 114 mb_q = REGc + REGe; 115 if (mb_q < 0) 116 REG7++; 117 118 m_result = REG7; 119 120 if (REGf < 0) 121 break; 122 123 REG7 += REG2; 124 125 /* fall into command 12 */ 126 127 case 0x12: 128 mb_temp = ((INT32) REG1) * ((INT32) REG4); 129 REGc = mb_temp >> 16; 130 REG9 = mb_temp & 0xffff; 131 132 mb_temp = ((INT32) REG0) * ((INT32) REG5); 133 REG8 = mb_temp >> 16; 134 mb_q = mb_temp & 0xffff; 135 136 REG8 += REGc; 137 138 /* rounding */ 139 REG9 = (REG9 >> 1) & 0x7fff; 140 REGc = (mb_q >> 1) & 0x7fff; 141 REG9 += REGc; 142 if (REG9 < 0) 143 REG8++; 144 REG9 <<= 1; /* why? only to get the desired load address? */ 145 146 m_result = REG8; 147 148 if (REGf < 0) 149 break; 150 151 REG8 += REG3; 152 153 REG9 &= 0xff00; 154 155 /* fall into command 13 */ 156 157 case 0x13: 158 REGc = REG9; 159 mb_q = REG8; 160 goto step_0bf; 161 162 case 0x14: 163 REGc = REGa; 164 mb_q = REGb; 165 166 step_0bf: 167 REGe = REG7 ^ mb_q; /* save sign of result */ 168 REGd = mb_q; 169 if (mb_q >= 0) 170 mb_q = REGc; 171 else 172 { 173 REGd = - mb_q - 1; 174 mb_q = - REGc - 1; 175 if ((mb_q < 0) && ((mb_q + 1) < 0)) 176 REGd++; 177 mb_q++; 178 } 179 180 /* step 0c9: */ 181 /* REGc = abs (REG7) */ 182 if (REG7 >= 0) 183 REGc = REG7; 184 else 185 REGc = -REG7; 186 187 REGf = REG6; /* step counter */ 188 189 do 190 { 191 REGd -= REGc; 192 msb = ((mb_q & 0x8000) != 0); 193 mb_q <<= 1; 194 if (REGd >= 0) 195 mb_q++; 196 else 197 REGd += REGc; 198 REGd <<= 1; 199 REGd += msb; 200 } 201 while (--REGf >= 0); 202 203 if (REGe >= 0) 204 m_result = mb_q; 205 else 206 m_result = - mb_q; 207 break; 208 209 case 0x11: 210 REG5 = (REG5 & 0x00ff) | (data << 8); 211 REGf = 0x0000; /* do everything in one step */ 212 goto step_048; 213 //break; // never reached 214 215 case 0x1c: 216 /* window test? */ 217 REG5 = (REG5 & 0x00ff) | (data << 8); 218 do 219 { 220 REGe = (REG4 + REG7) >> 1; 221 REGf = (REG5 + REG8) >> 1; 222 if ((REGb < REGe) && (REGf < REGe) && ((REGe + REGf) >= 0)) 223 { REG7 = REGe; REG8 = REGf; } 224 else 225 { REG4 = REGe; REG5 = REGf; } 226 } 227 while (--REG6 >= 0); 228 229 m_result = REG8; 230 break; 231 232 case 0x1d: 233 REG3 = (REG3 & 0x00ff) | (data << 8); 234 235 REG2 -= REG0; 236 if (REG2 < 0) 237 REG2 = -REG2; 238 239 REG3 -= REG1; 240 if (REG3 < 0) 241 REG3 = -REG3; 242 243 /* fall into command 1e */ 244 245 case 0x1e: 246 /* result = max (REG2, REG3) + 3/8 * min (REG2, REG3) */ 247 if (REG3 >= REG2) 248 { REGc = REG2; REGd = REG3; } 249 else 250 { REGd = REG2; REGc = REG3; } 251 REGc >>= 2; 252 REGd += REGc; 253 REGc >>= 1; 254 m_result = REGd = (REGc + REGd); 255 break; 256 257 case 0x1f: 258 /* $$$ do some computation here (selftest? signature analysis? */ 259 break; 260 } 261 } 262 mathbox_status_read()263UINT8 mathbox_status_read() 264 { 265 return 0x00; /* always done! */ 266 } 267 mathbox_lo_read()268UINT8 mathbox_lo_read() 269 { 270 return m_result & 0xff; 271 } 272 mathbox_hi_read()273UINT8 mathbox_hi_read() 274 { 275 return (m_result >> 8) & 0xff; 276 } 277