1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli
3 /***********************************************************************************************************
4
5
6 PC-Engine & Turbografx-16 cart emulation
7
8
9 ***********************************************************************************************************/
10
11
12 #include "emu.h"
13 #include "pce_rom.h"
14
15
16 //-------------------------------------------------
17 // pce_rom_device - constructor
18 //-------------------------------------------------
19
20 DEFINE_DEVICE_TYPE(PCE_ROM_STD, pce_rom_device, "pce_rom", "PCE/TG16 Carts")
21 DEFINE_DEVICE_TYPE(PCE_ROM_CDSYS3, pce_cdsys3_device, "pce_cdsys3", "PCE/TG16 CD-System Cart v3.00")
22 DEFINE_DEVICE_TYPE(PCE_ROM_POPULOUS, pce_populous_device, "pce_populous", "PCE Populous Cart")
23 DEFINE_DEVICE_TYPE(PCE_ROM_SF2, pce_sf2_device, "pce_sf2", "PCE Street Fighter 2 CE Cart")
24 DEFINE_DEVICE_TYPE(PCE_ROM_TENNOKOE, pce_tennokoe_device, "pce_tennokoe", "PCE Tennokoe Bank Cart")
25
26
pce_rom_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)27 pce_rom_device::pce_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
28 : device_t(mconfig, type, tag, owner, clock)
29 , device_pce_cart_interface( mconfig, *this )
30 {
31 }
32
pce_rom_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)33 pce_rom_device::pce_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
34 : pce_rom_device(mconfig, PCE_ROM_STD, tag, owner, clock)
35 {
36 }
37
pce_cdsys3_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)38 pce_cdsys3_device::pce_cdsys3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
39 : pce_rom_device(mconfig, PCE_ROM_CDSYS3, tag, owner, clock)
40 {
41 }
42
pce_populous_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)43 pce_populous_device::pce_populous_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
44 : pce_rom_device(mconfig, PCE_ROM_POPULOUS, tag, owner, clock)
45 {
46 }
47
pce_sf2_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)48 pce_sf2_device::pce_sf2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
49 : pce_rom_device(mconfig, PCE_ROM_SF2, tag, owner, clock), m_bank_base(0)
50 {
51 }
52
pce_tennokoe_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)53 pce_tennokoe_device::pce_tennokoe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
54 : pce_rom_device(mconfig, PCE_ROM_TENNOKOE, tag, owner, clock),
55 device_nvram_interface(mconfig, *this)
56 {
57 }
58
59
60 //-------------------------------------------------
61 // mapper specific start/reset
62 //-------------------------------------------------
63
64
device_start()65 void pce_sf2_device::device_start()
66 {
67 save_item(NAME(m_bank_base));
68 }
69
device_reset()70 void pce_sf2_device::device_reset()
71 {
72 m_bank_base = 0;
73 }
74
device_start()75 void pce_tennokoe_device::device_start()
76 {
77 save_item(NAME(m_bram));
78 save_item(NAME(m_bram_locked));
79 }
80
device_reset()81 void pce_tennokoe_device::device_reset()
82 {
83 m_bram_locked = 1;
84 }
85
86 // Tennokoe Bank is a special HuCard containing x4 Backup RAM banks,
87 // the software can transfer
nvram_default()88 void pce_tennokoe_device::nvram_default()
89 {
90 memset(m_bram, 0xff, m_bram_size);
91 // easter egg: load copy of a BRAM (debug leftover?) inside bank 4.
92 // Contains 14 save blocks, mostly at the end of the various games.
93 // Not entirely correct but not incorrect as well to just unlock these saves for public use,
94 // for testing reasons and for a slim chance of actually be supposed as default data in the bank(s)
95 // File list:
96 // 001 NEUTOPIA1
97 // 002 MOTURBO-1
98 // 003 MOMODE2-1
99 // 004 MOMOKATSU.
100 // 005 BOMBERMAN1
101 // 006 POPULOUS.
102 // 007 ADVENTURE1 (Starts in HuMan form at the village with 983040 gold, basically before the last dungeon);
103 // 008 TENGAI1
104 // 009 COBRA1
105 // 010 YS.DATA.01 (right before the switch between Ys 1 and 2, read book to move on);
106 // 011 YS.DATA.02
107 // 012 YS3.DAT.01 (right before the end, go to the right bridge for the ending);
108 // 013 URUSEI1
109 // 014 MITUBATI1
110 // TODO: document the other saves.
111 memcpy(m_bram + 0x1800, m_rom + 0x8800, 0x800);
112 }
113
nvram_read(emu_file & file)114 void pce_tennokoe_device::nvram_read(emu_file &file)
115 {
116 file.read(m_bram, m_bram_size);
117 }
118
nvram_write(emu_file & file)119 void pce_tennokoe_device::nvram_write(emu_file &file)
120 {
121 file.write(m_bram, m_bram_size);
122 }
123
124 /*-------------------------------------------------
125 mapper specific handlers
126 -------------------------------------------------*/
127
read_cart(offs_t offset)128 uint8_t pce_rom_device::read_cart(offs_t offset)
129 {
130 int bank = offset / 0x20000;
131 return m_rom[rom_bank_map[bank] * 0x20000 + (offset & 0x1ffff)];
132 }
133
134
read_cart(offs_t offset)135 uint8_t pce_cdsys3_device::read_cart(offs_t offset)
136 {
137 int bank = offset / 0x20000;
138 if (!m_ram.empty() && offset >= 0xd0000)
139 return m_ram[offset - 0xd0000];
140
141 return m_rom[rom_bank_map[bank] * 0x20000 + (offset & 0x1ffff)];
142 }
143
write_cart(offs_t offset,uint8_t data)144 void pce_cdsys3_device::write_cart(offs_t offset, uint8_t data)
145 {
146 if (!m_ram.empty() && offset >= 0xd0000)
147 m_ram[offset - 0xd0000] = data;
148 }
149
150
read_cart(offs_t offset)151 uint8_t pce_populous_device::read_cart(offs_t offset)
152 {
153 int bank = offset / 0x20000;
154 if (!m_ram.empty() && offset >= 0x80000 && offset < 0x88000)
155 return m_ram[offset & 0x7fff];
156
157 return m_rom[rom_bank_map[bank] * 0x20000 + (offset & 0x1ffff)];
158 }
159
write_cart(offs_t offset,uint8_t data)160 void pce_populous_device::write_cart(offs_t offset, uint8_t data)
161 {
162 if (!m_ram.empty() && offset >= 0x80000 && offset < 0x88000)
163 m_ram[offset & 0x7fff] = data;
164 }
165
166
read_cart(offs_t offset)167 uint8_t pce_sf2_device::read_cart(offs_t offset)
168 {
169 if (offset < 0x80000)
170 return m_rom[offset];
171 else
172 return m_rom[0x80000 + m_bank_base * 0x80000 + (offset & 0x7ffff)];
173 }
174
write_cart(offs_t offset,uint8_t data)175 void pce_sf2_device::write_cart(offs_t offset, uint8_t data)
176 {
177 if (offset >= 0x1ff0 && offset < 0x1ff4)
178 m_bank_base = offset & 3;
179 }
180
read_cart(offs_t offset)181 uint8_t pce_tennokoe_device::read_cart(offs_t offset)
182 {
183 switch((offset & 0xf0000) >> 16)
184 {
185 case 0:
186 case 1:
187 case 2:
188 case 3:
189 case 4:
190 case 5:
191 case 6:
192 case 7:
193 return m_rom[offset];
194 case 8:
195 if (m_bram_locked)
196 return 0xff;
197 else
198 return m_bram[offset & (m_bram_size-1)];
199 }
200
201 logerror("tennokoe: ROM reading at %06x\n",offset);
202 return 0xff;
203 }
204
write_cart(offs_t offset,uint8_t data)205 void pce_tennokoe_device::write_cart(offs_t offset, uint8_t data)
206 {
207 switch((offset & 0xf0000) >> 16)
208 {
209 case 8:
210 if(!m_bram_locked)
211 m_bram[offset & (m_bram_size-1)] = data;
212 break;
213 case 0xf:
214 // TODO: lock/unlock mechanism is a complete guess, needs real HW study
215 // (writes to ports $c0000, $d0000, $f0000)
216 m_bram_locked = (data == 0);
217 default:
218 logerror("tennokoe: ROM writing at %06x %02x\n",offset,data);
219 break;
220 }
221 }
222