1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria
3 /***************************************************************************
4 
5   machine.c
6 
7   Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
8   I/O ports)
9 
10 ***************************************************************************/
11 
12 #include "emu.h"
13 #include "cpu/m6805/m6805.h"
14 #include "includes/taitosj.h"
15 
16 
17 #define VERBOSE 1
18 #define LOG(x) do { if (VERBOSE) logerror x; } while (0)
19 
20 
machine_start()21 void taitosj_state::machine_start()
22 {
23 	membank("bank1")->configure_entry(0, memregion("maincpu")->base() + 0x6000);
24 	membank("bank1")->configure_entry(1, memregion("maincpu")->base() + 0x10000);
25 
26 	save_item(NAME(m_spacecr_prot_value));
27 	save_item(NAME(m_protection_value));
28 }
29 
machine_reset()30 void taitosj_state::machine_reset()
31 {
32 	/* set the default ROM bank (many games only have one bank and */
33 	/* never write to the bank selector register) */
34 	taitosj_bankswitch_w(0);
35 
36 	m_spacecr_prot_value = 0;
37 }
38 
39 
taitosj_bankswitch_w(uint8_t data)40 void taitosj_state::taitosj_bankswitch_w(uint8_t data)
41 {
42 	machine().bookkeeping().coin_lockout_global_w(~data & 1);
43 
44 	/* this is a bit of a hack, but works.
45 	    Eventually the mixing of the ay1 outs and
46 	    amplitude-overdrive-mute stuff done by
47 	    bit 1 here should be done on a netlist.
48 	*/
49 	m_ay1->set_output_gain(0, (data & 0x2) ? 1.0 : 0.0); // 3 outputs for Ay1 since it doesn't use tied together outs
50 	m_ay1->set_output_gain(1, (data & 0x2) ? 1.0 : 0.0);
51 	m_ay1->set_output_gain(2, (data & 0x2) ? 1.0 : 0.0);
52 	m_ay2->set_output_gain(0, (data & 0x2) ? 1.0 : 0.0);
53 	m_ay3->set_output_gain(0, (data & 0x2) ? 1.0 : 0.0);
54 	m_ay4->set_output_gain(0, (data & 0x2) ? 1.0 : 0.0);
55 	m_dac->set_output_gain(0, (data & 0x2) ? 1.0 : 0.0);
56 
57 	if(data & 0x80) membank("bank1")->set_entry(1);
58 	else membank("bank1")->set_entry(0);
59 }
60 
61 
62 
63 /***************************************************************************
64 
65                            PROTECTION HANDLING
66 
67  Some of the games running on this hardware are protected with a 68705 mcu.
68  It can either be on a daughter board containing Z80+68705+one ROM, which
69  replaces the Z80 on an unprotected main board; or it can be built-in on the
70  main board. The two are functionally equivalent.
71 
72  The 68705 can read commands from the Z80, send back result codes, and has
73  direct access to the Z80 memory space. It can also trigger IRQs on the Z80.
74 
75 ***************************************************************************/
taitosj_fake_data_r()76 uint8_t taitosj_state::taitosj_fake_data_r()
77 {
78 	LOG(("%04x: protection read\n",m_maincpu->pc()));
79 	return 0;
80 }
81 
taitosj_fake_data_w(uint8_t data)82 void taitosj_state::taitosj_fake_data_w(uint8_t data)
83 {
84 	LOG(("%04x: protection write %02x\n",m_maincpu->pc(),data));
85 }
86 
taitosj_fake_status_r()87 uint8_t taitosj_state::taitosj_fake_status_r()
88 {
89 	LOG(("%04x: protection status read\n",m_maincpu->pc()));
90 	return 0xff;
91 }
92 
93 
mcu_mem_r(offs_t offset)94 uint8_t taitosj_state::mcu_mem_r(offs_t offset)
95 {
96 	return m_maincpu->space(AS_PROGRAM).read_byte(offset);
97 }
98 
mcu_mem_w(offs_t offset,uint8_t data)99 void taitosj_state::mcu_mem_w(offs_t offset, uint8_t data)
100 {
101 	m_maincpu->space(AS_PROGRAM).write_byte(offset, data);
102 }
103 
WRITE_LINE_MEMBER(taitosj_state::mcu_intrq_w)104 WRITE_LINE_MEMBER(taitosj_state::mcu_intrq_w)
105 {
106 	// FIXME: there's a logic network here that makes this edge sensitive or something and mixes it with other interrupt sources
107 	if (CLEAR_LINE != state)
108 		LOG(("68705  68INTRQ **NOT SUPPORTED**!\n"));
109 }
110 
WRITE_LINE_MEMBER(taitosj_state::mcu_busrq_w)111 WRITE_LINE_MEMBER(taitosj_state::mcu_busrq_w)
112 {
113 	// this actually goes to the Z80 BUSRQ (aka WAIT) pin, and the MCU waits for the bus to become available
114 	// we're pretending this happens immediately to make life easier
115 	m_mcu->busak_w(state);
116 }
117 
118 
119 /* Space Cruiser protection (otherwise the game resets on the asteroids level) */
120 
spacecr_prot_r()121 uint8_t taitosj_state::spacecr_prot_r()
122 {
123 	int pc = m_maincpu->pc();
124 
125 	if( pc != 0x368A && pc != 0x36A6 )
126 		logerror("Read protection from an unknown location: %04X\n",pc);
127 
128 	m_spacecr_prot_value ^= 0xff;
129 
130 	return m_spacecr_prot_value;
131 }
132 
133 
134 /* Alpine Ski protection crack routines */
135 
alpine_protection_w(uint8_t data)136 void taitosj_state::alpine_protection_w(uint8_t data)
137 {
138 	switch (data)
139 	{
140 	case 0x05:
141 		m_protection_value = 0x18;
142 		break;
143 	case 0x07:
144 	case 0x0c:
145 	case 0x0f:
146 		m_protection_value = 0x00;      /* not used as far as I can tell */
147 		break;
148 	case 0x16:
149 		m_protection_value = 0x08;
150 		break;
151 	case 0x1d:
152 		m_protection_value = 0x18;
153 		break;
154 	default:
155 		m_protection_value = data;      /* not used as far as I can tell */
156 		break;
157 	}
158 }
159 
alpinea_bankswitch_w(uint8_t data)160 void taitosj_state::alpinea_bankswitch_w(uint8_t data)
161 {
162 	taitosj_bankswitch_w(data);
163 	m_protection_value = data >> 2;
164 }
165 
alpine_port_2_r()166 uint8_t taitosj_state::alpine_port_2_r()
167 {
168 	return ioport("IN2")->read() | m_protection_value;
169 }
170