summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/mathbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/mathbox.c')
-rw-r--r--src/mame/machine/mathbox.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/src/mame/machine/mathbox.c b/src/mame/machine/mathbox.c
new file mode 100644
index 00000000000..ada570c25ea
--- /dev/null
+++ b/src/mame/machine/mathbox.c
@@ -0,0 +1,285 @@
+/*
+ * mathbox.c: math box simulation (Battlezone/Red Baron/Tempest)
+ *
+ * Copyright 1991, 1992, 1993, 1996 Eric Smith
+ *
+ */
+
+#include "driver.h"
+#include "mathbox.h"
+
+typedef short s16;
+typedef int s32;
+
+/* math box scratch registers */
+static s16 mb_reg [16];
+
+/* math box result */
+static s16 mb_result = 0;
+
+#define REG0 mb_reg [0x00]
+#define REG1 mb_reg [0x01]
+#define REG2 mb_reg [0x02]
+#define REG3 mb_reg [0x03]
+#define REG4 mb_reg [0x04]
+#define REG5 mb_reg [0x05]
+#define REG6 mb_reg [0x06]
+#define REG7 mb_reg [0x07]
+#define REG8 mb_reg [0x08]
+#define REG9 mb_reg [0x09]
+#define REGa mb_reg [0x0a]
+#define REGb mb_reg [0x0b]
+#define REGc mb_reg [0x0c]
+#define REGd mb_reg [0x0d]
+#define REGe mb_reg [0x0e]
+#define REGf mb_reg [0x0f]
+
+
+/*define MB_TEST*/
+
+WRITE8_HANDLER( mb_go_w )
+{
+ s32 mb_temp; /* temp 32-bit multiply results */
+ s16 mb_q; /* temp used in division */
+ int msb;
+
+#ifdef MB_TEST
+ logerror("math box command %02x data %02x ", offset, data);
+#endif
+
+ switch (offset)
+ {
+ case 0x00: mb_result = REG0 = (REG0 & 0xff00) | data; break;
+ case 0x01: mb_result = REG0 = (REG0 & 0x00ff) | (data << 8); break;
+ case 0x02: mb_result = REG1 = (REG1 & 0xff00) | data; break;
+ case 0x03: mb_result = REG1 = (REG1 & 0x00ff) | (data << 8); break;
+ case 0x04: mb_result = REG2 = (REG2 & 0xff00) | data; break;
+ case 0x05: mb_result = REG2 = (REG2 & 0x00ff) | (data << 8); break;
+ case 0x06: mb_result = REG3 = (REG3 & 0xff00) | data; break;
+ case 0x07: mb_result = REG3 = (REG3 & 0x00ff) | (data << 8); break;
+ case 0x08: mb_result = REG4 = (REG4 & 0xff00) | data; break;
+ case 0x09: mb_result = REG4 = (REG4 & 0x00ff) | (data << 8); break;
+
+ case 0x0a: mb_result = REG5 = (REG5 & 0xff00) | data; break;
+ /* note: no function loads low part of REG5 without performing a computation */
+
+ case 0x0c: mb_result = REG6 = data; break;
+ /* note: no function loads high part of REG6 */
+
+ case 0x15: mb_result = REG7 = (REG7 & 0xff00) | data; break;
+ case 0x16: mb_result = REG7 = (REG7 & 0x00ff) | (data << 8); break;
+
+ case 0x1a: mb_result = REG8 = (REG8 & 0xff00) | data; break;
+ case 0x1b: mb_result = REG8 = (REG8 & 0x00ff) | (data << 8); break;
+
+ case 0x0d: mb_result = REGa = (REGa & 0xff00) | data; break;
+ case 0x0e: mb_result = REGa = (REGa & 0x00ff) | (data << 8); break;
+ case 0x0f: mb_result = REGb = (REGb & 0xff00) | data; break;
+ case 0x10: mb_result = REGb = (REGb & 0x00ff) | (data << 8); break;
+
+ case 0x17: mb_result = REG7; break;
+ case 0x19: mb_result = REG8; break;
+ case 0x18: mb_result = REG9; break;
+
+ case 0x0b:
+
+ REG5 = (REG5 & 0x00ff) | (data << 8);
+
+ REGf = (s16)0xffff;
+ REG4 -= REG2;
+ REG5 -= REG3;
+
+ step_048:
+
+ mb_temp = ((s32) REG0) * ((s32) REG4);
+ REGc = mb_temp >> 16;
+ REGe = mb_temp & 0xffff;
+
+ mb_temp = ((s32) -REG1) * ((s32) REG5);
+ REG7 = mb_temp >> 16;
+ mb_q = mb_temp & 0xffff;
+
+ REG7 += REGc;
+
+ /* rounding */
+ REGe = (REGe >> 1) & 0x7fff;
+ REGc = (mb_q >> 1) & 0x7fff;
+ mb_q = REGc + REGe;
+ if (mb_q < 0)
+ REG7++;
+
+ mb_result = REG7;
+
+ if (REGf < 0)
+ break;
+
+ REG7 += REG2;
+
+ /* fall into command 12 */
+
+ case 0x12:
+
+ mb_temp = ((s32) REG1) * ((s32) REG4);
+ REGc = mb_temp >> 16;
+ REG9 = mb_temp & 0xffff;
+
+ mb_temp = ((s32) REG0) * ((s32) REG5);
+ REG8 = mb_temp >> 16;
+ mb_q = mb_temp & 0xffff;
+
+ REG8 += REGc;
+
+ /* rounding */
+ REG9 = (REG9 >> 1) & 0x7fff;
+ REGc = (mb_q >> 1) & 0x7fff;
+ REG9 += REGc;
+ if (REG9 < 0)
+ REG8++;
+ REG9 <<= 1; /* why? only to get the desired load address? */
+
+ mb_result = REG8;
+
+ if (REGf < 0)
+ break;
+
+ REG8 += REG3;
+
+ REG9 &= 0xff00;
+
+ /* fall into command 13 */
+
+ case 0x13:
+#ifdef MB_TEST
+ logerror("\nR7: %04x R8: %04x R9: %04x\n", REG7, REG8, REG9);
+#endif
+
+ REGc = REG9;
+ mb_q = REG8;
+ goto step_0bf;
+
+ case 0x14:
+ REGc = REGa;
+ mb_q = REGb;
+
+ step_0bf:
+ REGe = REG7 ^ mb_q; /* save sign of result */
+ REGd = mb_q;
+ if (mb_q >= 0)
+ mb_q = REGc;
+ else
+ {
+ REGd = - mb_q - 1;
+ mb_q = - REGc - 1;
+ if ((mb_q < 0) && ((mb_q + 1) < 0))
+ REGd++;
+ mb_q++;
+ }
+
+ /* step 0c9: */
+ /* REGc = abs (REG7) */
+ if (REG7 >= 0)
+ REGc = REG7;
+ else
+ REGc = -REG7;
+
+ REGf = REG6; /* step counter */
+
+ do
+ {
+ REGd -= REGc;
+ msb = ((mb_q & 0x8000) != 0);
+ mb_q <<= 1;
+ if (REGd >= 0)
+ mb_q++;
+ else
+ REGd += REGc;
+ REGd <<= 1;
+ REGd += msb;
+ }
+ while (--REGf >= 0);
+
+ if (REGe >= 0)
+ mb_result = mb_q;
+ else
+ mb_result = - mb_q;
+ break;
+
+ case 0x11:
+ REG5 = (REG5 & 0x00ff) | (data << 8);
+ REGf = 0x0000; /* do everything in one step */
+ goto step_048;
+ break;
+
+ case 0x1c:
+ /* window test? */
+ REG5 = (REG5 & 0x00ff) | (data << 8);
+ do
+ {
+ REGe = (REG4 + REG7) >> 1;
+ REGf = (REG5 + REG8) >> 1;
+ if ((REGb < REGe) && (REGf < REGe) && ((REGe + REGf) >= 0))
+ { REG7 = REGe; REG8 = REGf; }
+ else
+ { REG4 = REGe; REG5 = REGf; }
+ }
+ while (--REG6 >= 0);
+
+ mb_result = REG8;
+ break;
+
+ case 0x1d:
+ REG3 = (REG3 & 0x00ff) | (data << 8);
+
+ REG2 -= REG0;
+ if (REG2 < 0)
+ REG2 = -REG2;
+
+ REG3 -= REG1;
+ if (REG3 < 0)
+ REG3 = -REG3;
+
+ /* fall into command 1e */
+
+ case 0x1e:
+ /* result = max (REG2, REG3) + 3/8 * min (REG2, REG3) */
+ if (REG3 >= REG2)
+ { REGc = REG2; REGd = REG3; }
+ else
+ { REGd = REG2; REGc = REG3; }
+ REGc >>= 2;
+ REGd += REGc;
+ REGc >>= 1;
+ mb_result = REGd = (REGc + REGd);
+ break;
+
+ case 0x1f:
+ logerror("math box function 0x1f\n");
+ /* $$$ do some computation here (selftest? signature analysis? */
+ break;
+ }
+
+#ifdef MB_TEST
+ logerror(" result %04x\n", mb_result & 0xffff);
+#endif
+}
+
+READ8_HANDLER( mb_status_r )
+{
+ return 0x00; /* always done! */
+}
+
+READ8_HANDLER( mb_lo_r )
+{
+ return mb_result & 0xff;
+}
+
+READ8_HANDLER( mb_hi_r )
+{
+ return (mb_result >> 8) & 0xff;
+}
+
+void mb_register_states(void)
+{
+ state_save_register_global(mb_result);
+ state_save_register_global_array(mb_reg);
+}