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