summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/mw8080bw.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/mw8080bw.c')
-rw-r--r--src/mame/machine/mw8080bw.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/mame/machine/mw8080bw.c b/src/mame/machine/mw8080bw.c
new file mode 100644
index 00000000000..24c32966bee
--- /dev/null
+++ b/src/mame/machine/mw8080bw.c
@@ -0,0 +1,125 @@
+/***************************************************************************
+
+ Midway 8080-based black and white hardware
+
+****************************************************************************/
+
+#include "driver.h"
+#include "mw8080bw.h"
+#include "machine/mb14241.h"
+
+
+/*************************************
+ *
+ * Interrupt generation
+ *
+ *************************************/
+
+static emu_timer *interrupt_timer;
+
+
+static UINT8 vpos_to_vysnc_chain_counter(int vpos)
+{
+ /* convert from a vertical position to the actual values on the vertical sync counters */
+ UINT8 counter;
+ int vblank = (vpos >= MW8080BW_VBSTART);
+
+ if (vblank)
+ {
+ counter = vpos - MW8080BW_VBSTART + MW8080BW_VCOUNTER_START_VBLANK;
+ }
+ else
+ {
+ counter = vpos + MW8080BW_VCOUNTER_START_NO_VBLANK;
+ }
+
+
+ return counter;
+}
+
+
+static int vysnc_chain_counter_to_vpos(UINT8 counter, int vblank)
+{
+ /* convert from the vertical sync counters to an actual vertical position */
+ int vpos;
+
+ if (vblank)
+ {
+ vpos = counter - MW8080BW_VCOUNTER_START_VBLANK + MW8080BW_VBSTART;
+ }
+ else
+ {
+ vpos = counter - MW8080BW_VCOUNTER_START_NO_VBLANK;
+ }
+
+ return vpos;
+}
+
+
+static TIMER_CALLBACK( mw8080bw_interrupt_callback )
+{
+ UINT8 next_counter;
+ int next_vpos;
+ int next_vblank;
+
+ /* compute vector and set the interrupt line */
+ int vpos = video_screen_get_vpos(0);
+ UINT8 counter = vpos_to_vysnc_chain_counter(vpos);
+ UINT8 vector = 0xc7 | ((counter & 0x40) >> 2) | ((~counter & 0x40) >> 3);
+ cpunum_set_input_line_and_vector(0, 0, HOLD_LINE, vector);
+
+ /* set up for next interrupt */
+ if (counter == MW8080BW_INT_TRIGGER_COUNT_1)
+ {
+ next_counter = MW8080BW_INT_TRIGGER_COUNT_2;
+ next_vblank = MW8080BW_INT_TRIGGER_VBLANK_2;
+ }
+ else
+ {
+ next_counter = MW8080BW_INT_TRIGGER_COUNT_1;
+ next_vblank = MW8080BW_INT_TRIGGER_VBLANK_1;
+ }
+
+ next_vpos = vysnc_chain_counter_to_vpos(next_counter, next_vblank);
+ timer_adjust(interrupt_timer, video_screen_get_time_until_pos(0, next_vpos, 0), 0, attotime_zero);
+}
+
+
+static void mw8080bw_create_interrupt_timer(void)
+{
+ interrupt_timer = timer_alloc(mw8080bw_interrupt_callback);
+}
+
+
+static void mw8080bw_start_interrupt_timer(void)
+{
+ int vpos = vysnc_chain_counter_to_vpos(MW8080BW_INT_TRIGGER_COUNT_1, MW8080BW_INT_TRIGGER_VBLANK_1);
+ timer_adjust(interrupt_timer, video_screen_get_time_until_pos(0, vpos, 0), 0, attotime_zero);
+}
+
+
+
+/*************************************
+ *
+ * Machine setup
+ *
+ *************************************/
+
+MACHINE_START( mw8080bw )
+{
+ mw8080bw_create_interrupt_timer();
+ mb14241_init(0);
+}
+
+
+
+/*************************************
+ *
+ * Machine reset
+ *
+ *************************************/
+
+MACHINE_RESET( mw8080bw )
+{
+ mw8080bw_start_interrupt_timer();
+}