Previous 199869 Revisions Next

r21871 Friday 15th March, 2013 at 09:13:49 UTC by Fabio Priuli
(MESS) snes.c: major overhaul of cart and add-on handling [Fabio Priuli]
 - updated carts to be slot devices
 - simplified loading and bankswitch mechanism
 - removed drivers snessfx and snespsfx: SuperFX/GSU games can now
   be loaded in snes and snespal
 - removed drivers snesdsp and snespdsp: NEC DSPx games can now
   be loaded in snes and snespal from softlist
 - removed drivers snesst10 and snesst11: Seta DSP games can now
   be loaded in snes and snespal from softlist
 - removed driver snesst: when you load Sufami Turbo, two more cart slots
   (-cart2 and -cart3) become available to load ST carts
 - added preliminary support for games with BS-X slots: when you load
   one of these, a -cart2 slot becomes available to load a 8MB memory pack
   (only a few of these work at the moment, e.g. Same Game)
 - added support for loading DSPx games with DSP dump appended at the
   end of the .sfc file
 - added two "legacy" drivers snes_add and snesp_add containing the
   DSP dumps in the bios, to allow loading of old .sfc dumps missing the DSP
   content (these drivers are of course marked as GAME_UNOFFICIAL)


out of whatsnew:
- I have removed the DSP1B dump from NSS, because I plan to update NSS
to use slot devices as well and that will cover everything needed by SMK, if we
ever find its NSS release and dump it
- Also, I will take care of fixing snes entries in messnew before u2, because
part of this set of changes supersede the log for 21546 (e.g. no more snesnew
or snespnew wip drivers)
[src/mame/drivers]nss.c
[src/mame/includes]snes.h
[src/mess]mess.lst mess.mak
[src/mess/drivers]snes.c
[src/mess/machine]snes7110.c snescart.c snescart.h snescx4.c snescx4.h snesobc1.c snesrtc.c snessdd1.c sns_slot.c sns_slot.h

trunk/src/mess/mess.lst
r21870r21871
6868gblight   // Nintendo Game Boy Light Handheld
6969gbcolor   // Nintendo Game Boy Color Handheld
7070gba       // Nintendo Game Boy Advance Handheld
71snesnew      // Nintendo Super Nintendo NTSC (test driver with slots)
72snespnew      // Nintendo Super Nintendo PAL (test driver with slots)
7371snes      // Nintendo Super Nintendo NTSC
7472snespal   // Nintendo Super Nintendo PAL
75snessfx   // Nintendo Super Nintendo NTSC w/SuperFX CPU
76snespsfx  // Nintendo Super Nintendo PAL w/SuperFX CPU
77snesdsp   // Nintendo Super Nintendo NTSC w/DSP-x CPU
78snespdsp  // Nintendo Super Nintendo PAL w/DSP-x CPU
79snesst10  // Nintendo Super Nintendo NTSC w/ST-010 CPU
80snesst11  // Nintendo Super Nintendo NTSC w/ST-011 CPU
81snesst    // Nintendo Super Nintendo NTSC w/Sufami Turbo base cart
73snes_add      // Nintendo Super Nintendo NTSC w/add-on CPUs as BIOS (legacy driver to run old dumps)
74snesp_add   // Nintendo Super Nintendo PAL w/add-on CPUs as BIOS (legacy driver to run old dumps)
8275n64       // Nintendo N64
8376n64dd     // Nintendo N64 (64DD Attachment)
8477pokemini  // Nintendo Pokemon Mini
trunk/src/mess/drivers/snes.c
r21870r21871
44
55  Driver file to handle emulation of the Nintendo Super NES.
66
7  R. Belmont
8  Anthony Kruize
9  Angelo Salese
10  Fabio Priuli
11  byuu
12  Based on the original MESS driver by Lee Hammerton (aka Savoury Snax)
7  Based on original MESS driver by Lee Hammerton (aka Savoury Snax),
8  later contributions by
9   R. Belmont
10   Anthony Kruize
11   Angelo Salese
12   Fabio Priuli
13   byuu (extensive RE of both SNES and add-on chips)
1314
14  Driver is preliminary right now.
1515
16  The memory map included below is setup in a way to make it easier to handle
17  Mode 20 and Mode 21 ROMs.
18
1916  Todo (in no particular order):
20    - Fix additional sound bugs
21    - Emulate extra chips - superfx, dsp2, sa-1 etc.
22    - Add horizontal mosaic, hi-res. interlaced etc to video emulation.
23    - Fix support for Mode 7. (In Progress)
24    - Handle interleaved roms (maybe even multi-part roms, but how?)
25    - Add support for running at 3.58 MHz at the appropriate time.
26    - I'm sure there's lots more ...
17    - Fix sync between 5A22, SPC700 and PPU
18    - Fix remaining sound and video bugs
19    - Fix vertical mosaic effects
20    - Add support for real CX4 and ST018 CPUs
21    - Add support for SA-1 and SuperGB add-ons
22    - Fix mouse & superscope support
23    - Add multitap support
24    - Add support for other controllers
2725
2826***************************************************************************/
2927
3028#include "emu.h"
3129#include "audio/snes_snd.h"
3230#include "cpu/spc700/spc700.h"
33#include "cpu/superfx/superfx.h"
34#include "cpu/g65816/g65816.h"
35#include "cpu/upd7725/upd7725.h"
3631#include "includes/snes.h"
37#include "machine/snescart.h"
32#include "machine/snescx4.h"
3833
3934#include "crsshair.h"
4035
36#include "machine/sns_slot.h"
37#include "machine/sns_rom.h"
38#include "machine/sns_rom21.h"
39#include "machine/sns_bsx.h"
40#include "machine/sns_sdd1.h"
41#include "machine/sns_sfx.h"
42#include "machine/sns_spc7110.h"
43#include "machine/sns_sufami.h"
44#include "machine/sns_upd.h"
45
46
4147class snes_console_state : public snes_state
4248{
4349public:
4450   snes_console_state(const machine_config &mconfig, device_type type, const char *tag)
45      : snes_state(mconfig, type, tag)
51         : snes_state(mconfig, type, tag)
52         , m_cartslot(*this, "snsslot")
4653   { }
4754
55   DECLARE_READ8_MEMBER( snes20_hi_r );
56   DECLARE_WRITE8_MEMBER( snes20_hi_w );
57   DECLARE_READ8_MEMBER( snes20_lo_r );
58   DECLARE_WRITE8_MEMBER( snes20_lo_w );
59   DECLARE_READ8_MEMBER( snes21_lo_r );
60   DECLARE_WRITE8_MEMBER( snes21_lo_w );
61   DECLARE_READ8_MEMBER( snes21_hi_r );
62   DECLARE_WRITE8_MEMBER( snes21_hi_w );
63   DECLARE_READ8_MEMBER( snessfx_hi_r );
64   DECLARE_READ8_MEMBER( snessfx_lo_r );
65   DECLARE_WRITE8_MEMBER( snessfx_hi_w );
66   DECLARE_WRITE8_MEMBER( snessfx_lo_w );
67   DECLARE_READ8_MEMBER( snes7110_hi_r );
68   DECLARE_READ8_MEMBER( snes7110_lo_r );
69   DECLARE_WRITE8_MEMBER( snes7110_hi_w );
70   DECLARE_WRITE8_MEMBER( snes7110_lo_w );
71   DECLARE_READ8_MEMBER( snessdd1_lo_r );
72   DECLARE_WRITE8_MEMBER( snessdd1_lo_w );
73   DECLARE_READ8_MEMBER( snessdd1_hi_r );
74   DECLARE_WRITE8_MEMBER( snessdd1_hi_w );
75   DECLARE_READ8_MEMBER( snesbsx_hi_r );
76   DECLARE_WRITE8_MEMBER( snesbsx_hi_w );
77   DECLARE_READ8_MEMBER( snesbsx_lo_r );
78   DECLARE_WRITE8_MEMBER( snesbsx_lo_w );
79
4880   DECLARE_READ8_MEMBER( spc_ram_100_r );
4981   DECLARE_WRITE8_MEMBER( spc_ram_100_w );
50   UINT8 st010_read_ram(UINT16 addr);
51   void st010_write_ram(UINT16 addr, UINT8 data);
52   DECLARE_READ8_MEMBER( snes_lo_r );
53   DECLARE_READ8_MEMBER( snes_hi_r );
54   DECLARE_WRITE8_MEMBER( snes_lo_w );
55   DECLARE_WRITE8_MEMBER( snes_hi_w );
56   DECLARE_READ8_MEMBER( sfx_r );
57   DECLARE_WRITE8_MEMBER( sfx_w );
58   DECLARE_READ8_MEMBER( superfx_r_bank1 );
59   DECLARE_READ8_MEMBER( superfx_r_bank2 );
60   DECLARE_READ8_MEMBER( superfx_r_bank3 );
61   DECLARE_WRITE8_MEMBER( superfx_w_bank3 );
62   DECLARE_READ8_MEMBER( sufami_r );
63   DECLARE_WRITE8_MEMBER( sufami_w );
6482   CUSTOM_INPUT_MEMBER( snes_mouse_speed_input );
6583   CUSTOM_INPUT_MEMBER( snes_superscope_offscreen_input );
6684   TIMER_CALLBACK_MEMBER( lightgun_tick );
r21870r21871
7290   DECLARE_READ8_MEMBER(snes_oldjoy1_read);
7391   DECLARE_READ8_MEMBER(snes_oldjoy2_read);
7492
75   UINT8 m_sfx_ram[0x200000];  // or 0x100000?
93   int m_type;
94   optional_device<sns_cart_slot_device> m_cartslot;
7695};
7796
97
7898/*************************************
7999 *
80100 *  Memory handlers
81101 *
82102 *************************************/
83103
104// SPC access
105
84106READ8_MEMBER(snes_console_state::spc_ram_100_r )
85107{
86108   return spc_ram_r(machine().device("spc700"), space, offset + 0x100);
r21870r21871
91113   spc_ram_w(machine().device("spc700"), space, offset + 0x100, data);
92114}
93115
94// DSP accessors
95#define dsp_get_sr() m_upd7725->snesdsp_read(false)
96#define dsp_get_dr() m_upd7725->snesdsp_read(true)
97#define dsp_set_sr(data) m_upd7725->snesdsp_write(false, data)
98#define dsp_set_dr(data) m_upd7725->snesdsp_write(true, data)
116// Memory access for the various types of carts
99117
100#define st010_get_sr() m_upd96050->snesdsp_read(false)
101#define st010_get_dr() m_upd96050->snesdsp_read(true)
102#define st010_set_sr(data) m_upd96050->snesdsp_write(false, data)
103#define st010_set_dr(data) m_upd96050->snesdsp_write(true, data)
118//---------------------------------------------------------------------------------
119// LoROM & LoROM + BSX slot & LoROM + some add-on chips
120//---------------------------------------------------------------------------------
104121
105// ST-010 and ST-011 RAM interface
106UINT8 snes_console_state::st010_read_ram(UINT16 addr)
122// In general LoROM games have perfect mirror between 0x00-0x7d and 0x80-0xff
123// But BSX+LoROM games use different read handlers (to access ROM beyond 2MB)
124// so we use two different set of handlers...
125
126// Also we have here LoROM + CX4, until the Hitachi CPU is emulated,
127// and the LoROM + Seta DSP, because their chip_read/chip_write need global offset
128
129READ8_MEMBER( snes_console_state::snes20_hi_r )
107130{
108   UINT16 temp = m_upd96050->dataram_r(addr/2);
109   UINT8 res;
131   UINT16 address = offset & 0xffff;
110132
111   if (addr & 1)
133   // take care of add-on IO
134   if ((m_cartslot->get_type() == SNES_ST010 || m_cartslot->get_type() == SNES_ST011)
135      && (offset >= 0x600000 && offset < 0x680000 && (offset & 0xffff) < 0x4000))
136      return m_cartslot->chip_read(space, offset);
137   else if ((m_cartslot->get_type() == SNES_ST010 || m_cartslot->get_type() == SNES_ST011)
138            && (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x8000))
139      return m_cartslot->chip_read(space, offset);
140   else if (m_cartslot->get_type() == SNES_CX4
141            && (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))    // hack until we emulate the real CPU
142      return CX4_read((offset & 0xffff) - 0x6000);
143
144   if (offset < 0x400000)
112145   {
113      res = temp>>8;
146      if (address < 0x2000)
147         return space.read_byte(0x7e0000 + address);
148      else if (address < 0x6000)
149         return snes_r_io(space, address);
150      else if (address < 0x8000)
151         return snes_open_bus_r(space, 0);
152      else
153         return m_cartslot->read_h(space, offset);
114154   }
115   else
155   else if (offset < 0x700000)
116156   {
117      res = temp & 0xff;
157      if (address < 0x8000)
158         return snes_open_bus_r(space, 0);
159      else
160         return m_cartslot->read_h(space, offset);
118161   }
162   else
163   {
164      if (m_type == SNES_SUFAMITURBO && address >= 0x8000 && offset < 0x740000)
165         return m_cartslot->read_h(space, offset);
119166
120   return res;
167      // here usually there is SRAM mirrored in the whole range, but if ROM is very large then arrives here too (see tokimeki and wizardg4)
168      if (m_cartslot->m_cart->get_rom_size() > 0x200000 && address >= 0x8000)
169         return m_cartslot->read_h(space, offset);
170      else
171      {
172         if (m_cartslot->m_cart->get_nvram_size() > 0x8000)
173         {
174            // In this case, SRAM is mapped in 0x8000 chunks at diff offsets: 0x700000-0x707fff, 0x710000-0x717fff, etc.
175            offset = ((offset - 0x700000) / 0x10000) * 0x8000 + (offset & 0x7fff);
176            return m_cartslot->read_ram(space, offset);
177         }
178         else if (m_cartslot->m_cart->get_nvram_size() > 0)
179            return m_cartslot->read_ram(space, offset);
180         else
181            return snes_open_bus_r(space, 0);
182      }
183   }
121184}
122185
123void snes_console_state::st010_write_ram(UINT16 addr, UINT8 data)
186WRITE8_MEMBER( snes_console_state::snes20_hi_w )
124187{
125   UINT16 temp = m_upd96050->dataram_r(addr/2);
188   UINT16 address = offset & 0xffff;
126189
127   if (addr & 1)
190   // take care of add-on IO
191   if ((m_cartslot->get_type() == SNES_ST010 || m_cartslot->get_type() == SNES_ST011)
192      && (offset >= 0x600000 && offset < 0x680000 && (offset & 0xffff) < 0x4000))
193   { m_cartslot->chip_write(space, offset, data); return; }
194   else if ((m_cartslot->get_type() == SNES_ST010 || m_cartslot->get_type() == SNES_ST011)
195            && (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x8000))
196   { m_cartslot->chip_write(space, offset, data); return; }
197   else if (m_cartslot->get_type() == SNES_CX4
198            && (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))    // hack until we emulate the real CPU
199   { CX4_write(space.machine(), (offset & 0xffff) - 0x6000, data); return; }
200   else if (m_type == SNES_SUFAMITURBO
201            && address >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
202   { m_cartslot->write_h(space, offset, data); return; }
203
204   if (offset < 0x400000)
128205   {
129      temp &= 0xff;
130      temp |= data<<8;
206      if (address < 0x2000)
207         space.write_byte(0x7e0000 + address, data);
208      else if (address < 0x6000)
209         snes_w_io(space, address, data);
131210   }
132   else
211   else if (offset >= 0x700000 && (m_cartslot->m_cart->get_rom_size() <= 0x200000 || address < 0x8000))    // NVRAM access
133212   {
134      temp &= 0xff00;
135      temp |= data;
213      if (m_cartslot->m_cart->get_nvram_size() > 0x8000)
214      {
215         // In this case, SRAM is mapped in 0x8000 chunks at diff offsets: 0x700000-0x707fff, 0x710000-0x717fff, etc.
216         offset = ((offset - 0x700000) / 0x10000) * 0x8000 + (offset & 0x7fff);
217         m_cartslot->write_ram(space, offset, data);
218      }
219      else if (m_cartslot->m_cart->get_nvram_size() > 0)
220         m_cartslot->write_ram(space, offset, data);
136221   }
137
138   m_upd96050->dataram_w(addr/2, temp);
139222}
140223
141READ8_MEMBER( snes_console_state::sfx_r )
224READ8_MEMBER( snes_console_state::snes20_lo_r )
142225{
143226   UINT16 address = offset & 0xffff;
227
228   // take care of add-on IO
229   if ((m_cartslot->get_type() == SNES_ST010 /*|| m_cartslot->get_type() == SNES_ST011*/) // why does this break moritash?
230      && (offset >= 0x600000 && offset < 0x680000 && (offset & 0xffff) < 0x4000))
231      return m_cartslot->chip_read(space, offset);
232   else if ((m_cartslot->get_type() == SNES_ST010 || m_cartslot->get_type() == SNES_ST011)
233            && (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x8000))
234      return m_cartslot->chip_read(space, offset);
235   else if (m_cartslot->get_type() == SNES_CX4
236            && (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))    // hack until we emulate the real CPU
237      return CX4_read((offset & 0xffff) - 0x6000);
238
144239   if (offset < 0x400000)
145240   {
146241      if (address < 0x2000)
147242         return space.read_byte(0x7e0000 + address);
148243      else if (address < 0x6000)
149      {
150         if (address >= 0x3000 && address < 0x3300)
151            return superfx_mmio_read(m_superfx, address);
152         else
153            return snes_r_io(space, address);
154      }
244         return snes_r_io(space, address);
155245      else if (address < 0x8000)
156         return superfx_access_ram(m_superfx) ? m_sfx_ram[offset & 0x1fff] : snes_open_bus_r(space, 0);
246         return snes_open_bus_r(space, 0);
157247      else
158         return m_cart[0].m_rom[m_cart[0].rom_bank_map[offset / 0x10000] * 0x8000 + (offset & 0x7fff)];
248         return m_cartslot->read_l(space, offset);
159249   }
160   else if (offset < 0x600000)
250   else if (offset < 0x700000)
161251   {
162      if (superfx_access_rom(m_superfx))
163         return m_cart[0].m_rom[m_cart[0].rom_bank_map[(offset - 0x400000) / 0x8000] * 0x8000 + (offset & 0x7fff)];
252      if (address < 0x8000)
253         return snes_open_bus_r(space, 0);
164254      else
255         return m_cartslot->read_l(space, offset);
256   }
257   else
258   {
259      if (m_type == SNES_SUFAMITURBO && address >= 0x8000 && offset < 0x740000)
260         return m_cartslot->read_l(space, offset);
261
262      // here usually there is SRAM mirrored in the whole range, but if ROM is very large then arrives here too (see tokimeki and wizardg4)
263      if (m_cartslot->m_cart->get_rom_size() > 0x200000 && address >= 0x8000)
264         return m_cartslot->read_l(space, offset);
265      else
165266      {
166         static const UINT8 sfx_data[16] = {
167            0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
168            0x00, 0x01, 0x08, 0x01, 0x00, 0x01, 0x0c, 0x01,
169         };
170         return sfx_data[offset & 0x0f];
267         if (m_cartslot->m_cart->get_nvram_size() > 0x8000)
268         {
269            // In this case, SRAM is mapped in 0x8000 chunks at diff offsets: 0x700000-0x707fff, 0x710000-0x717fff, etc.
270            offset = ((offset - 0x700000) / 0x10000) * 0x8000 + (offset & 0x7fff);
271            return m_cartslot->read_ram(space, offset);
272         }
273         else if (m_cartslot->m_cart->get_nvram_size() > 0)
274            return m_cartslot->read_ram(space, offset);
275         else
276            return snes_open_bus_r(space, 0);
171277      }
172278   }
173   else
174      return superfx_access_ram(m_superfx) ? m_sfx_ram[offset & 0xfffff] : snes_open_bus_r(space, 0);
175279}
176280
177WRITE8_MEMBER( snes_console_state::sfx_w )
281WRITE8_MEMBER( snes_console_state::snes20_lo_w )
178282{
283   if (m_type == SNES_SUFAMITURBO
284      && (offset & 0xffff) >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
285   { m_cartslot->write_l(space, offset, data); return; }
286
287   // other add-on writes matches the hi handler
288   snes20_hi_w(space, offset, data, 0xff);
289}
290
291
292//---------------------------------------------------------------------------------
293// HiROM & HiROM + BSX slot
294//---------------------------------------------------------------------------------
295
296READ8_MEMBER( snes_console_state::snes21_lo_r )
297{
179298   UINT16 address = offset & 0xffff;
180   if (offset < 0x400000)
299
300   if (offset < 0x400000 && address < 0x8000)
181301   {
182302      if (address < 0x2000)
183         space.write_byte(0x7e0000 + address, data);
303         return space.read_byte(0x7e0000 + address);
184304      else if (address < 0x6000)
305         return snes_r_io(space, address);
306      else
185307      {
186         if (address >= 0x3000 && address < 0x3300)
187            superfx_mmio_write(m_superfx, address, data);
308         if (m_type == SNES_BSXHI && m_cartslot->m_cart->get_nvram_size() && offset >= 0x200000)
309         {
310            int mask = (m_cartslot->m_cart->get_nvram_size() - 1) & 0x7fff;
311            return m_cartslot->read_ram(space, (offset - 0x6000) & mask);
312         }
313
314         if (m_cartslot->m_cart->get_nvram_size() && offset >= 0x300000)
315         {
316            /* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */
317            /* OTOH Secret of Mana does not work properly if sram is not mirrored on later banks */
318            int mask = (m_cartslot->m_cart->get_nvram_size() - 1) & 0x7fff; /* Limit SRAM size to what's actually present */
319            return m_cartslot->read_ram(space, (offset - 0x6000) & mask);
320         }
188321         else
189            snes_w_io(space, address, data);
322            return snes_open_bus_r(space, 0);
190323      }
191      else if (address < 0x8000)
192         m_sfx_ram[offset & 0x1fff] = data;
193324   }
194   else if (offset >= 0x600000)
195      m_sfx_ram[offset & 0xfffff] = data;
325
326   // ROM access
327   return m_cartslot->read_l(space, offset);
196328}
197329
198READ8_MEMBER( snes_console_state::snes_lo_r )
330WRITE8_MEMBER( snes_console_state::snes21_lo_w )
199331{
200332   UINT16 address = offset & 0xffff;
201
202   // take care of add-on chip access
203   if (m_has_addon_chip == HAS_OBC1
204      && (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
205      return obc1_read(space, offset, mem_mask);
206   if (m_has_addon_chip == HAS_CX4
207      && (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
208      return CX4_read(address - 0x6000);
209   if (m_has_addon_chip == HAS_RTC
210      && (offset < 0x400000 && (address == 0x2800 || address == 0x2801)))
211      return srtc_read(space, offset);
212   if (m_has_addon_chip == HAS_ST010 || m_has_addon_chip == HAS_ST011)
333   if (offset < 0x400000 && address < 0x8000)
213334   {
214      if (offset >= 0x680000 && offset < 0x700000 && address < 0x1000)
215         return st010_read_ram(address);
216      if ((offset == 0x600000 || offset == 0x600001) &&  m_has_addon_chip == HAS_ST010) // moritash freezes due to this...
217         return (offset & 1) ? st010_get_sr() : st010_get_dr();
335      if (address < 0x2000)
336         space.write_byte(0x7e0000 + address, data);
337      else if (address < 0x6000)
338         snes_w_io(space, address, data);
339      else
340      {
341         if (m_type == SNES_BSXHI && m_cartslot->m_cart->get_nvram_size() && offset >= 0x200000)
342         {
343            int mask = (m_cartslot->m_cart->get_nvram_size() - 1) & 0x7fff;
344            m_cartslot->write_ram(space, (offset - 0x6000) & mask, data);
345            return;
346         }
347         if (m_cartslot->m_cart->get_nvram_size() && offset >= 0x300000)
348         {
349            /* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */
350            /* OTOH Secret of Mana does not work properly if sram is not mirrored on later banks */
351            int mask = (m_cartslot->m_cart->get_nvram_size() - 1) & 0x7fff; /* Limit SRAM size to what's actually present */
352            m_cartslot->write_ram(space, (offset - 0x6000) & mask, data);
353         }
354      }
218355   }
219   if (m_cart[0].mode == SNES_MODE_21 && m_has_addon_chip == HAS_DSP1
220      && (offset < 0x200000 && address >= 0x6000 && address < 0x8000))
221      return (address < 0x7000) ? dsp_get_dr() : dsp_get_sr();
222   if (m_cart[0].mode == SNES_MODE_20 && m_has_addon_chip == HAS_DSP1)
223   {
224      if (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000)
225         return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
226      if (offset >= 0x600000 && offset < 0x700000 && (offset & 0x8000) == 0x0000)
227         return (address < 0x4000) ? dsp_get_dr() : dsp_get_sr();
228   }
229   if ((m_has_addon_chip == HAS_DSP2 || m_has_addon_chip == HAS_DSP3)
230      && (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
231      return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
232   if (m_has_addon_chip == HAS_DSP4
233      && (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
234      return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
235   if (m_has_addon_chip == HAS_SDD1
236      && (offset < 0x400000 && address >= 0x4800 && address < 0x4808))
237      return sdd1_mmio_read(space, (UINT32)address);
238   if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC)
239      && offset < 0x400000)
240   {
241      UINT16 limit = (m_has_addon_chip == HAS_SPC7110_RTC) ? 0x4842 : 0x483f;
242      if (address >= 0x4800 && address <= limit)
243         return spc7110_mmio_read(space, (UINT32)address);
244      if (offset < 0x10000 && address >= 0x6000 && address < 0x8000)
245         return spc7110_ram_read(address & 0x1fff);
246      if (offset >= 0x300000 && offset < 0x310000 && address >= 0x6000 && address < 0x8000)
247         return spc7110_ram_read(address & 0x1fff);
248   }
249   if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC)
250      && offset >= 0x500000 && offset < 0x510000)
251      return spc7110_mmio_read(space, 0x4800);
252   if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL)
253      return sfx_r(space, offset, 0xff);
254
255   // base cart access
256   return snes_r_bank1(space, offset, 0xff);
257356}
258357
259READ8_MEMBER( snes_console_state::snes_hi_r )
358READ8_MEMBER( snes_console_state::snes21_hi_r )
260359{
261360   UINT16 address = offset & 0xffff;
262361
263   // take care of add-on chip access
264   if (m_has_addon_chip == HAS_OBC1
265      && (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
266      return obc1_read(space, offset, mem_mask);
267   if (m_has_addon_chip == HAS_CX4
268      && (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
269      return CX4_read(address - 0x6000);
270   if (m_has_addon_chip == HAS_RTC
271      && (offset < 0x400000 && (address == 0x2800 || address == 0x2801)))
272      return srtc_read(space, offset);
273   if (m_has_addon_chip == HAS_ST010 || m_has_addon_chip == HAS_ST011)
362   if (offset < 0x400000 && address < 0x8000)
274363   {
275      if (offset >= 0x680000 && offset < 0x700000 && address < 0x1000)
276         return st010_read_ram(address);
277      if (offset == 0x600000 || offset == 0x600001)
278         return (offset & 1) ? st010_get_sr() : st010_get_dr();
364      if (address < 0x2000)
365         return space.read_byte(0x7e0000 + address);
366      else if (address < 0x6000)
367         return snes_r_io(space, address);
368      else
369      {
370         if (m_type == SNES_BSXHI && m_cartslot->m_cart->get_nvram_size() && offset >= 0x200000)
371         {
372            int mask = (m_cartslot->m_cart->get_nvram_size() - 1) & 0x7fff;
373            return m_cartslot->read_ram(space, (offset - 0x6000) & mask);
374         }
375
376         if (m_cartslot->m_cart->get_nvram_size() && offset >= 0x300000)
377         {
378            /* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */
379            /* OTOH Secret of Mana does not work properly if sram is not mirrored on later banks */
380            int mask = (m_cartslot->m_cart->get_nvram_size() - 1) & 0x7fff; /* Limit SRAM size to what's actually present */
381            return m_cartslot->read_ram(space, (offset - 0x6000) & mask);
382         }
383         else
384            return snes_open_bus_r(space, 0);
385      }
279386   }
280   if (m_cart[0].mode == SNES_MODE_21 && m_has_addon_chip == HAS_DSP1
281      && (offset < 0x200000 && address >= 0x6000 && address < 0x8000))
282      return (address < 0x7000) ? dsp_get_dr() : dsp_get_sr();
283   if (m_cart[0].mode == SNES_MODE_20 && m_has_addon_chip == HAS_DSP1)
284   {
285      if (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000)
286         return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
287      if (offset >= 0x600000 && offset < 0x700000 && (offset & 0x8000) == 0x0000)
288         return (address < 0x4000) ? dsp_get_dr() : dsp_get_sr();
289   }
290   if ((m_has_addon_chip == HAS_DSP2 || m_has_addon_chip == HAS_DSP3)
291      && (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
292      return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
293   if (m_has_addon_chip == HAS_DSP4
294      && (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
295      return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
296   if (m_has_addon_chip == HAS_SDD1
297      && (offset < 0x400000 && address >= 0x4800 && address < 0x4808))
298      return sdd1_mmio_read(space, (UINT32)address);
299   if (m_has_addon_chip == HAS_SDD1 && offset >= 0x400000)
300      return sdd1_read(space.machine(), offset - 0x400000);
301   if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC)
302      && offset < 0x400000)
303   {
304      UINT16 limit = (m_has_addon_chip == HAS_SPC7110_RTC) ? 0x4842 : 0x483f;
305      if (address >= 0x4800 && address <= limit)
306         return spc7110_mmio_read(space, (UINT32)address);
307      if (offset < 0x10000 && address >= 0x6000 && address < 0x8000)
308         return spc7110_ram_read(address & 0x1fff);
309      if (offset >= 0x300000 && offset < 0x310000 && address >= 0x6000 && address < 0x8000)
310         return spc7110_ram_read(address & 0x1fff);
311   }
312   if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC)
313      && offset >= 0x500000)
314      return spc7110_bank7_read(space, offset - 0x400000);
315   if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL)
316      return sfx_r(space, offset, 0xff);
317387
318   // base cart access
319   return snes_r_bank2(space, offset, 0xff);
388   // ROM access
389   return m_cartslot->read_h(space, offset);
320390}
321391
322WRITE8_MEMBER( snes_console_state::snes_lo_w )
392WRITE8_MEMBER( snes_console_state::snes21_hi_w )
323393{
324394   UINT16 address = offset & 0xffff;
325
326   // take care of add-on chip access
327   if (m_has_addon_chip == HAS_OBC1
328      && (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
329   {   obc1_write(space, offset, data, mem_mask);  return; }
330   if (m_has_addon_chip == HAS_CX4
331      && (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
332   {   CX4_write(space.machine(), address - 0x6000, data); return; }
333   if (m_has_addon_chip == HAS_RTC
334      && (offset < 0x400000 && (address == 0x2800 || address == 0x2801)))
335   {   srtc_write(space.machine(), offset, data);  return; }
336   if (m_has_addon_chip == HAS_ST010 || m_has_addon_chip == HAS_ST011)
395   if (offset < 0x400000 && address < 0x8000)
337396   {
338      if (offset >= 0x680000 && offset < 0x700000 && address < 0x1000)
339      {   st010_write_ram(address, data); return; }
340      if (offset == 0x600000)
341      {   st010_set_dr(data); return; }
342      if (offset == 0x600001)
343      {   st010_set_sr(data); return; }
344   }
345   if (m_cart[0].mode == SNES_MODE_21 && m_has_addon_chip == HAS_DSP1
346      && (offset < 0x200000 && address >= 0x6000 && address < 0x8000))
347   {   dsp_set_dr(data);   return; }
348   if (m_cart[0].mode == SNES_MODE_20 && m_has_addon_chip == HAS_DSP1)
349   {
350      if (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000)
351      {   dsp_set_dr(data);   return; }
352      if (offset >= 0x600000 && offset < 0x700000 && (offset & 0x8000) == 0x0000)
353      {   dsp_set_dr(data);   return; }
354   }
355   if ((m_has_addon_chip == HAS_DSP2 || m_has_addon_chip == HAS_DSP3)
356      && (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
357   {
358      if (address < 0xc000)
359      {   dsp_set_dr(data);   return; }
397      if (address < 0x2000)
398         space.write_byte(0x7e0000 + address, data);
399      else if (address < 0x6000)
400         snes_w_io(space, address, data);
360401      else
361      {   dsp_set_sr(data);   return; }
362   }
363   if (m_has_addon_chip == HAS_DSP4
364      && (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
365   {
366      if (address < 0xc000)
367      {   dsp_set_dr(data);   return; }
368      else
369      {   dsp_set_sr(data);   return; }
370   }
371   if (m_has_addon_chip == HAS_SDD1 && offset < 0x400000)
372   {
373      if ((address >= 0x4300 && address < 0x4380) || (address >= 0x4800 && address < 0x4808))
374402      {
375            sdd1_mmio_write(space, (UINT32)address, data);
376            // here we don't return, but we let the w_io happen...
403         if (m_type == SNES_BSXHI && m_cartslot->m_cart->get_nvram_size() && offset >= 0x200000)
404         {
405            int mask = (m_cartslot->m_cart->get_nvram_size() - 1) & 0x7fff;
406            m_cartslot->write_ram(space, (offset - 0x6000) & mask, data);
407            return;
408         }
409         if (m_cartslot->m_cart->get_nvram_size() && offset >= 0x300000)
410         {
411            /* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */
412            /* OTOH Secret of Mana does not work properly if sram is not mirrored on later banks */
413            int mask = (m_cartslot->m_cart->get_nvram_size() - 1) & 0x7fff; /* Limit SRAM size to what's actually present */
414            m_cartslot->write_ram(space, (offset - 0x6000) & mask, data);
415         }
377416      }
378417   }
379   if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC) && offset < 0x400000)
380   {
381      UINT16 limit = (m_has_addon_chip == HAS_SPC7110_RTC) ? 0x4842 : 0x483f;
382      if (address >= 0x4800 && address <= limit)
383      {   spc7110_mmio_write(space.machine(), (UINT32)address, data); return; }
384      if (offset < 0x10000 && address >= 0x6000 && address < 0x8000)
385      {   spc7110_ram_write(address & 0x1fff, data); return; }
386      if (offset >= 0x300000 && offset < 0x310000 && address >= 0x6000 && address < 0x8000)
387      {   spc7110_ram_write(address & 0x1fff, data); return; }
388   }
389   if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL)
390   {   sfx_w(space, offset, data, 0xff); return; }
391
392   // base cart access
393   snes_w_bank1(space, offset, data, 0xff);
394418}
395419
396WRITE8_MEMBER( snes_console_state::snes_hi_w )
420//---------------------------------------------------------------------------------
421// LoROM + SuperFX / GSU
422//---------------------------------------------------------------------------------
423
424READ8_MEMBER( snes_console_state::snessfx_hi_r )
397425{
398426   UINT16 address = offset & 0xffff;
399427
400   // take care of add-on chip access
401   if (m_has_addon_chip == HAS_OBC1
402      && (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
403   {   obc1_write(space, offset, data, mem_mask);  return; }
404   if (m_has_addon_chip == HAS_CX4
405      && (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
406   {   CX4_write(space.machine(), address - 0x6000, data); return; }
407   if (m_has_addon_chip == HAS_RTC
408      && (offset < 0x400000 && (address == 0x2800 || address == 0x2801)))
409   {   srtc_write(space.machine(), offset, data);  return; }
410   if (m_has_addon_chip == HAS_ST010 || m_has_addon_chip == HAS_ST011)
428   if (offset < 0x400000)
411429   {
412      if (offset >= 0x680000 && offset < 0x700000 && address < 0x1000)
413      {   st010_write_ram(address, data); return; }
414      if (offset == 0x600000)
415      {   st010_set_dr(data); return; }
416      if (offset == 0x600001)
417      {   st010_set_sr(data); return; }
418   }
419   if (m_cart[0].mode == SNES_MODE_21 && m_has_addon_chip == HAS_DSP1
420      && (offset < 0x200000 && address >= 0x6000 && address < 0x8000))
421   {   dsp_set_dr(data);   return; }
422   if (m_cart[0].mode == SNES_MODE_20 && m_has_addon_chip == HAS_DSP1)
423   {
424      if (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000)
425      {   dsp_set_dr(data);   return; }
426      if (offset >= 0x600000 && offset < 0x700000 && (offset & 0x8000) == 0x0000)
427      {   dsp_set_dr(data);   return; }
428   }
429   if ((m_has_addon_chip == HAS_DSP2 || m_has_addon_chip == HAS_DSP3)
430      && (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
431   {
432      if (address < 0xc000)
433      {   dsp_set_dr(data);   return; }
430      if (address < 0x2000)
431         return space.read_byte(0x7e0000 + address);
432      else if (address < 0x6000)
433      {
434         if (address >= 0x3000 && address < 0x3300)
435            return m_cartslot->chip_read(space, offset);
436         else
437            return snes_r_io(space, address);
438      }
439      else if (address < 0x8000)
440         return m_cartslot->read_ram(space, offset & 0x1fff);
434441      else
435      {   dsp_set_sr(data);   return; }
442         return m_cartslot->read_h(space, offset);
436443   }
437   if (m_has_addon_chip == HAS_DSP4
438      && (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
444   else if (offset < 0x600000)
445      return m_cartslot->read_h(space, offset);
446   else
447      return m_cartslot->read_ram(space, offset);
448}
449
450READ8_MEMBER( snes_console_state::snessfx_lo_r )
451{
452   UINT16 address = offset & 0xffff;
453
454   if (offset < 0x400000)
439455   {
440      if (address < 0xc000)
441      {   dsp_set_dr(data);   return; }
456      if (address < 0x2000)
457         return space.read_byte(0x7e0000 + address);
458      else if (address < 0x6000)
459      {
460         if (address >= 0x3000 && address < 0x3300)
461            return m_cartslot->chip_read(space, offset);
462         else
463            return snes_r_io(space, address);
464      }
465      else if (address < 0x8000)
466         return m_cartslot->read_ram(space, offset & 0x1fff);
442467      else
443      {   dsp_set_sr(data);   return; }
468         return m_cartslot->read_l(space, offset);
444469   }
445   if (m_has_addon_chip == HAS_SDD1 && offset < 0x400000)
470   else if (offset < 0x600000)
471      return m_cartslot->read_l(space, offset);
472   else
473      return m_cartslot->read_ram(space, offset);
474}
475
476WRITE8_MEMBER( snes_console_state::snessfx_hi_w )
477{
478   UINT16 address = offset & 0xffff;
479   if (offset < 0x400000)
446480   {
447      if ((address >= 0x4300 && address < 0x4380) || (address >= 0x4800 && address < 0x4808))
481      if (address < 0x2000)
482         space.write_byte(0x7e0000 + address, data);
483      else if (address < 0x6000)
448484      {
449         sdd1_mmio_write(space, (UINT32)address, data);
450         // here we don't return, but we let the w_io happen...
485         if (address >= 0x3000 && address < 0x3300)
486            m_cartslot->chip_write(space, offset, data);
487         else
488            snes_w_io(space, address, data);
451489      }
490      else if (address < 0x8000)
491         m_cartslot->write_ram(space, offset & 0x1fff, data);
452492   }
453   if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC) && offset < 0x400000)
454   {
455      UINT16 limit = (m_has_addon_chip == HAS_SPC7110_RTC) ? 0x4842 : 0x483f;
456      if (address >= 0x4800 && address <= limit)
457      {   spc7110_mmio_write(space.machine(), (UINT32)address, data); return; }
458      if (offset < 0x10000 && address >= 0x6000 && address < 0x8000)
459      {   spc7110_ram_write(address & 0x1fff, data); return; }
460      if (offset >= 0x300000 && offset < 0x310000 && address >= 0x6000 && address < 0x8000)
461      {   spc7110_ram_write(address & 0x1fff, data); return; }
462   }
463   if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL)
464   {   sfx_w(space, offset, data, 0xff); return; }
493   else if (offset >= 0x600000)
494      m_cartslot->write_ram(space, offset, data);
495}
465496
466   // base cart access
467   snes_w_bank2(space, offset, data, 0xff);
497WRITE8_MEMBER( snes_console_state::snessfx_lo_w )
498{
499   snessfx_hi_w(space, offset, data, 0xff);
468500}
469501
470READ8_MEMBER( snes_console_state::sufami_r )
502//---------------------------------------------------------------------------------
503// HiROM + SPC-7110
504//---------------------------------------------------------------------------------
505
506READ8_MEMBER( snes_console_state::snes7110_hi_r )
471507{
472508   UINT16 address = offset & 0xffff;
473   if (offset < 0x200000)
509
510   if (offset < 0x400000)
474511   {
475512      if (address < 0x2000)
476513         return space.read_byte(0x7e0000 + address);
477514      else if (address < 0x6000)
515      {
516         UINT16 limit = (m_cartslot->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
517         if (address >= 0x4800 && address < limit)
518            return m_cartslot->chip_read(space, address);
519
478520         return snes_r_io(space, address);
521      }
479522      else if (address < 0x8000)
480         return snes_open_bus_r(space, 0);
481      else
482523      {
483         UINT8 *ROM = memregion("sufami")->base();
484         int bank = (offset / 0x10000) & 7;
485         return ROM[bank * 0x8000 + (offset & 0x7fff)]; // SUFAMI ROM
524         if (offset < 0x10000)
525            return m_cartslot->read_ram(space, offset);
526         if (offset >= 0x300000 && offset < 0x310000)
527            return m_cartslot->read_ram(space, offset);
486528      }
529      else
530         return m_cartslot->read_h(space, offset);
487531   }
488   else if (offset < 0x400000)
532   return m_cartslot->read_h(space, offset);
533}
534
535READ8_MEMBER( snes_console_state::snes7110_lo_r )
536{
537   UINT16 address = offset & 0xffff;
538
539   if (offset < 0x400000)
489540   {
490541      if (address < 0x2000)
491542         return space.read_byte(0x7e0000 + address);
492543      else if (address < 0x6000)
544      {
545         UINT16 limit = (m_cartslot->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
546         if (address >= 0x4800 && address < limit)
547            return m_cartslot->chip_read(space, address);
548
493549         return snes_r_io(space, address);
550      }
494551      else if (address < 0x8000)
495         return snes_open_bus_r(space, 0);
496      else if (m_cart[0].slot_in_use)
497552      {
498         int bank = (offset - 0x200000) / 0x10000;
499         return m_cart[0].m_rom[m_cart[0].rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; // SUFAMI SLOT1
553         if (offset < 0x10000)
554            return m_cartslot->read_ram(space, offset);
555         if (offset >= 0x300000 && offset < 0x310000)
556            return m_cartslot->read_ram(space, offset);
500557      }
558      else
559         return m_cartslot->read_l(space, offset);
501560   }
502   else if (offset < 0x600000)
561   if (offset >= 0x500000 && offset < 0x510000)
562      return m_cartslot->chip_read(space, 0x4800);
563
564   return snes_open_bus_r(space, 0);
565}
566
567WRITE8_MEMBER( snes_console_state::snes7110_hi_w )
568{
569   snes7110_lo_w(space, offset, data, 0xff);
570}
571
572WRITE8_MEMBER( snes_console_state::snes7110_lo_w )
573{
574   UINT16 address = offset & 0xffff;
575   if (offset < 0x400000)
503576   {
504      if (address < 0x8000)
505         return snes_open_bus_r(space, 0);
506      else if (m_cart[1].slot_in_use)
577      if (address < 0x2000)
578         space.write_byte(0x7e0000 + address, data);
579      else if (address < 0x6000)
507580      {
508         int bank = (offset - 0x400000) / 0x10000;
509         return m_cart[1].m_rom[m_cart[1].rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; // SUFAMI SLOT2
581         UINT16 limit = (m_cartslot->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
582         if (address >= 0x4800 && address < limit)
583         {
584            m_cartslot->chip_write(space, address, data);
585            return;
586         }
587         snes_w_io(space, address, data);
510588      }
589      else if (address < 0x8000)
590      {
591         if (offset < 0x10000)
592            m_cartslot->write_ram(space, offset, data);
593         if (offset >= 0x300000 && offset < 0x310000)
594            m_cartslot->write_ram(space, offset, data);
595      }
511596   }
512   else if (address >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
597}
598
599
600//---------------------------------------------------------------------------------
601// LoROM + S-DD1
602//---------------------------------------------------------------------------------
603
604READ8_MEMBER( snes_console_state::snessdd1_lo_r )
605{
606   UINT16 address = offset & 0xffff;
607
608   if (offset < 0x400000)
513609   {
514      int slot_id = (offset & 0x100000) ? 1 : 0;
515      if (m_cart[slot_id].slot_in_use)
610      if (address < 0x2000)
611         return space.read_byte(0x7e0000 + address);
612      else if (address < 0x6000)
516613      {
517         int bank = (offset & 0x3ffff) / 0x10000;
518         return m_cart[slot_id].m_nvram[bank * 0x8000 + (offset & 0x7fff)];  // SLOT RAM
614         if (address >= 0x4800 && address < 0x4808)
615            return m_cartslot->chip_read(space, address);
616
617         return snes_r_io(space, address);
519618      }
619      else if (address < 0x8000)
620         return snes_open_bus_r(space, 0);
621      else
622         return m_cartslot->read_l(space, offset);
520623   }
521   return snes_open_bus_r(space, 0);
624   else if (offset >= 0x700000 && address < 0x8000 && m_cartslot->m_cart->get_nvram_size())    // NVRAM access
625      return m_cartslot->read_ram(space, offset);
626   else    // ROM access
627      return m_cartslot->read_l(space, offset);
522628}
523629
524WRITE8_MEMBER( snes_console_state::sufami_w )
630READ8_MEMBER( snes_console_state::snessdd1_hi_r )
525631{
632   if (offset >= 0x400000)
633      return m_cartslot->read_h(space, offset);
634   else
635      return snessdd1_lo_r(space, offset, 0xff);
636}
637
638WRITE8_MEMBER( snes_console_state::snessdd1_lo_w )
639{
640   snessdd1_hi_w(space, offset, data, 0xff);
641}
642
643WRITE8_MEMBER( snes_console_state::snessdd1_hi_w )
644{
526645   UINT16 address = offset & 0xffff;
527646   if (offset < 0x400000)
528647   {
529648      if (address < 0x2000)
530649         space.write_byte(0x7e0000 + address, data);
531650      else if (address < 0x6000)
651      {
652         if (address >= 0x4300 && address < 0x4380)
653         {
654            m_cartslot->chip_write(space, address, data);
655            // here we don't return, but we let the w_io happen...
656         }
657         if (address >= 0x4800 && address < 0x4808)
658         {
659            m_cartslot->chip_write(space, address, data);
660            return;
661         }
532662         snes_w_io(space, address, data);
663      }
533664   }
534   else if (address >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
665   if (offset >= 0x700000 && address < 0x8000 && m_cartslot->m_cart->get_nvram_size())
666      return m_cartslot->write_ram(space, offset, data);
667}
668
669
670//---------------------------------------------------------------------------------
671// LoROM + BS-X (Base unit)
672//---------------------------------------------------------------------------------
673
674READ8_MEMBER( snes_console_state::snesbsx_hi_r )
675{
676   UINT16 address = offset & 0xffff;
677
678   if (offset < 0x400000)
535679   {
536      int slot_id = (offset & 0x100000) ? 1 : 0;
537      if (m_cart[slot_id].slot_in_use)
680      if (address < 0x2000)
681         return space.read_byte(0x7e0000 + address);
682      else if (address < 0x6000)
538683      {
539         int bank = (offset & 0x3ffff) / 0x10000;
540         m_cart[slot_id].m_nvram[bank * 0x8000 + (offset & 0x7fff)] = data;  // SLOT RAM
684         if (address >= 0x2188 && address < 0x21a0)
685            return m_cartslot->chip_read(space, offset);
686         if (address >= 0x5000)
687            return m_cartslot->chip_read(space, offset);
688         return snes_r_io(space, address);
541689      }
690      else if (address < 0x8000)
691      {
692         if (offset >= 0x200000)
693            return m_cartslot->read_h(space, offset);
694         else
695            return snes_open_bus_r(space, 0);
696      }
697      else
698         return m_cartslot->read_h(space, offset);
542699   }
700   return m_cartslot->read_h(space, offset);
543701}
544702
545READ8_MEMBER( snes_console_state::superfx_r_bank1 )
703WRITE8_MEMBER( snes_console_state::snesbsx_hi_w )
546704{
547   return m_cart[0].m_rom[m_cart[0].rom_bank_map[offset / 0x10000] * 0x8000 + (offset & 0x7fff)];
705   UINT16 address = offset & 0xffff;
706   if (offset < 0x400000)
707   {
708      if (address < 0x2000)
709         space.write_byte(0x7e0000 + address, data);
710      else if (address < 0x6000)
711      {
712         if (address >= 0x2188 && address < 0x21a0)
713         {
714            m_cartslot->chip_write(space, offset, data);
715            return;
716         }
717         if (address >= 0x5000)
718         {
719            m_cartslot->chip_write(space, offset, data);
720            return;
721         }
722         snes_w_io(space, address, data);
723      }
724      else if (address < 0x8000)
725      {
726         if (offset >= 0x200000)
727            return m_cartslot->write_l(space, offset, data);
728      }
729      else
730         return m_cartslot->write_l(space, offset, data);
731   }
732   return m_cartslot->write_l(space, offset, data);
548733}
549734
550READ8_MEMBER( snes_console_state::superfx_r_bank2 )
735READ8_MEMBER( snes_console_state::snesbsx_lo_r )
551736{
552   return m_cart[0].m_rom[m_cart[0].rom_bank_map[offset / 0x8000] * 0x8000 + (offset & 0x7fff)];
553}
737   UINT16 address = offset & 0xffff;
554738
555READ8_MEMBER( snes_console_state::superfx_r_bank3 )
556{
557   /* IMPORTANT: SFX RAM sits in 0x600000-0x7fffff, and it's mirrored in 0xe00000-0xffffff. However, SNES
558    has only access to 0x600000-0x7dffff (because there is WRAM after that). */
559   //printf("superfx_r_bank3: %08x = %02x\n", offset, m_sfx_ram[offset & 0xfffff]);
560   return m_sfx_ram[offset & 0xfffff];
739   if (offset < 0x400000)
740   {
741      if (address < 0x2000)
742         return space.read_byte(0x7e0000 + address);
743      else if (address < 0x6000)
744      {
745         if (address >= 0x2188 && address < 0x21a0)
746            return m_cartslot->chip_read(space, offset);
747         if (address >= 0x5000)
748            return m_cartslot->chip_read(space, offset);
749         return snes_r_io(space, address);
750      }
751      else if (address < 0x8000)
752      {
753         if (offset >= 0x200000)
754            return m_cartslot->read_l(space, offset);
755         else
756            return snes_open_bus_r(space, 0);
757      }
758      else
759         return m_cartslot->read_l(space, offset);
760   }
761   return m_cartslot->read_l(space, offset);
561762}
562763
563WRITE8_MEMBER( snes_console_state::superfx_w_bank3 )
764WRITE8_MEMBER( snes_console_state::snesbsx_lo_w )
564765{
565   /* IMPORTANT: SFX RAM sits in 0x600000-0x7fffff, and it's mirrored in 0xe00000-0xffffff. However, SNES
566    has only access to 0x600000-0x7dffff (because there is WRAM after that). */
567   //printf("superfx_w_bank3: %08x = %02x\n", offset, data);
568   m_sfx_ram[offset & 0xfffff] = data;
766   snesbsx_hi_w(space, offset, data, 0xff);
569767}
570768
769
571770/*************************************
572771 *
573772 *  Address maps
r21870r21871
575774 *************************************/
576775
577776static ADDRESS_MAP_START( snes_map, AS_PROGRAM, 8, snes_console_state )
578   AM_RANGE(0x000000, 0x7dffff) AM_READWRITE(snes_lo_r, snes_lo_w)
579   AM_RANGE(0x7e0000, 0x7fffff) AM_RAM                 /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
580   AM_RANGE(0x800000, 0xffffff) AM_READWRITE(snes_hi_r, snes_hi_w)
777   AM_RANGE(0x000000, 0x7dffff) AM_READWRITE(snes20_lo_r, snes20_lo_w)
778   AM_RANGE(0x7e0000, 0x7fffff) AM_RAM                                     /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
779   AM_RANGE(0x800000, 0xffffff) AM_READWRITE(snes20_hi_r, snes20_hi_w)
581780ADDRESS_MAP_END
582781
583static ADDRESS_MAP_START( snesst_map, AS_PROGRAM, 8, snes_console_state )
584   AM_RANGE(0x000000, 0x7dffff) AM_READWRITE(sufami_r, sufami_w)
585   AM_RANGE(0x7e0000, 0x7fffff) AM_RAM                 /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
586   AM_RANGE(0x800000, 0xffffff) AM_READWRITE(sufami_r, sufami_w)
587ADDRESS_MAP_END
588
589static ADDRESS_MAP_START( superfx_map, AS_PROGRAM, 8, snes_console_state )
590   AM_RANGE(0x000000, 0x3fffff) AM_READ(superfx_r_bank1)
591   AM_RANGE(0x400000, 0x5fffff) AM_READ(superfx_r_bank2)
592   AM_RANGE(0x600000, 0x7dffff) AM_READWRITE(superfx_r_bank3, superfx_w_bank3)
593   AM_RANGE(0x800000, 0xbfffff) AM_READ(superfx_r_bank1)
594   AM_RANGE(0xc00000, 0xdfffff) AM_READ(superfx_r_bank2)
595   AM_RANGE(0xe00000, 0xffffff) AM_READWRITE(superfx_r_bank3, superfx_w_bank3)
596ADDRESS_MAP_END
597
598782static ADDRESS_MAP_START( spc_map, AS_PROGRAM, 8, snes_console_state )
599783   AM_RANGE(0x0000, 0x00ef) AM_DEVREADWRITE_LEGACY("spc700", spc_ram_r, spc_ram_w) /* lower 32k ram */
600784   AM_RANGE(0x00f0, 0x00ff) AM_DEVREADWRITE_LEGACY("spc700", spc_io_r, spc_io_w)   /* spc io */
601785   AM_RANGE(0x0100, 0xffff) AM_READWRITE(spc_ram_100_r, spc_ram_100_w)
602786ADDRESS_MAP_END
603787
604static ADDRESS_MAP_START( dsp_prg_map, AS_PROGRAM, 32, snes_console_state )
605   AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION("dspprg", 0)
606ADDRESS_MAP_END
607788
608static ADDRESS_MAP_START( dsp_data_map, AS_DATA, 16, snes_console_state )
609   AM_RANGE(0x0000, 0x03ff) AM_ROM AM_REGION("dspdata", 0)
610ADDRESS_MAP_END
611
612static ADDRESS_MAP_START( setadsp_prg_map, AS_PROGRAM, 32, snes_console_state )
613   AM_RANGE(0x0000, 0x3fff) AM_ROM AM_REGION("dspprg", 0)
614ADDRESS_MAP_END
615
616static ADDRESS_MAP_START( setadsp_data_map, AS_DATA, 16, snes_console_state )
617   AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION("dspdata", 0)
618ADDRESS_MAP_END
619
620789/*************************************
621790 *
622791 *  Input ports
r21870r21871
11941363 *
11951364 *************************************/
11961365
1197static MACHINE_START( snes_mess )
1198{
1199   snes_console_state *state = machine.driver_data<snes_console_state>();
12001366
1201   machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(snes_machine_stop),&machine));
1202   MACHINE_START_CALL(snes);
1203
1204   switch (state->m_has_addon_chip)
1205   {
1206      case HAS_SDD1:
1207         sdd1_init(machine);
1208         break;
1209      case HAS_SPC7110:
1210         spc7110_init(machine);
1211         break;
1212      case HAS_SPC7110_RTC:
1213         spc7110rtc_init(machine);
1214         break;
1215   }
1216}
1217
1218static MACHINE_START( snesst )
1219{
1220   machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(sufami_machine_stop),&machine));
1221   MACHINE_START_CALL(snes);
1222}
1223
1224static MACHINE_RESET( snes_mess )
1225{
1226   snes_console_state *state = machine.driver_data<snes_console_state>();
1227
1228   MACHINE_RESET_CALL(snes);
1229
1230   state->m_io_read = write8_delegate(FUNC(snes_console_state::snes_input_read),state);
1231   state->m_oldjoy1_read = read8_delegate(FUNC(snes_console_state::snes_oldjoy1_read),state);
1232   state->m_oldjoy2_read = read8_delegate(FUNC(snes_console_state::snes_oldjoy2_read),state);
1233
1234   // see if there's a uPD7725 DSP in the machine config
1235   state->m_upd7725 = machine.device<upd7725_device>("dsp");
1236
1237   // if we have a DSP, halt it for the moment
1238   if (state->m_upd7725)
1239      machine.device("dsp")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
1240
1241   // ditto for a uPD96050 (Seta ST-010 or ST-011)
1242   state->m_upd96050 = machine.device<upd96050_device>("setadsp");
1243   if (state->m_upd96050)
1244      machine.device("setadsp")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
1245
1246   switch (state->m_has_addon_chip)
1247   {
1248      case HAS_DSP1:
1249      case HAS_DSP2:
1250      case HAS_DSP3:
1251      case HAS_DSP4:
1252         // cartridge uses the DSP, let 'er rip
1253         if (state->m_upd7725)
1254            machine.device("dsp")->execute().set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
1255         else
1256         {
1257            logerror("SNES: Game uses a DSP, but the machine driver is missing the uPD7725!\n");
1258            state->m_has_addon_chip = HAS_NONE; // prevent crash trying to access NULL device
1259         }
1260         break;
1261
1262      case HAS_RTC:
1263         srtc_init(machine);
1264         break;
1265
1266      case HAS_OBC1:
1267         obc1_init(machine);
1268         break;
1269
1270      case HAS_ST010:
1271      case HAS_ST011:
1272         // cartridge uses the DSP, let 'er rip
1273         if (state->m_upd96050)
1274            machine.device("setadsp")->execute().set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
1275         else
1276         {
1277            logerror("SNES: Game uses a Seta DSP, but the machine driver is missing the uPD96050!\n");
1278            state->m_has_addon_chip = HAS_NONE; // prevent crash trying to access NULL device
1279         }
1280         break;
1281
1282      default:
1283         break;
1284   }
1285}
1286
1287static MACHINE_CONFIG_START( snes_base, snes_console_state )
1288
1289   /* basic machine hardware */
1290   MCFG_CPU_ADD("maincpu", _5A22, MCLK_NTSC)   /* 2.68 MHz, also 3.58 MHz */
1291   MCFG_CPU_PROGRAM_MAP(snes_map)
1292
1293   MCFG_CPU_ADD("soundcpu", SPC700, 1024000)   /* 1.024 MHz */
1294   MCFG_CPU_PROGRAM_MAP(spc_map)
1295
1296   //MCFG_QUANTUM_TIME(attotime::from_hz(48000))
1297   MCFG_QUANTUM_PERFECT_CPU("maincpu")
1298
1299   MCFG_MACHINE_START(snes_mess)
1300   MCFG_MACHINE_RESET(snes_mess)
1301
1302   /* video hardware */
1303   MCFG_SCREEN_ADD("screen", RASTER)
1304   MCFG_SCREEN_RAW_PARAMS(DOTCLK_NTSC * 2, SNES_HTOTAL * 2, 0, SNES_SCR_WIDTH * 2, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC)
1305   MCFG_SCREEN_UPDATE_DRIVER( snes_state, screen_update )
1306
1307   /* sound hardware */
1308   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
1309   MCFG_SOUND_ADD("spc700", SNES, 0)
1310   MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
1311   MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
1312MACHINE_CONFIG_END
1313
1314static MACHINE_CONFIG_DERIVED( snes, snes_base )
1315
1316   MCFG_FRAGMENT_ADD(snes_cartslot)
1317MACHINE_CONFIG_END
1318
1319
1320static SUPERFX_CONFIG( snes_superfx_config )
1321{
1322   DEVCB_DRIVER_LINE_MEMBER(snes_state,snes_extern_irq_w)  /* IRQ line from cart */
1323};
1324
1325static MACHINE_CONFIG_DERIVED( snessfx, snes )
1326
1327   MCFG_CPU_ADD("superfx", SUPERFX, 21480000)  /* 21.48MHz */
1328   MCFG_CPU_PROGRAM_MAP(superfx_map)
1329   MCFG_CPU_CONFIG(snes_superfx_config)
1330MACHINE_CONFIG_END
1331
1332static MACHINE_CONFIG_DERIVED( snesdsp, snes )
1333
1334   MCFG_CPU_ADD("dsp", UPD7725, 8000000)
1335   MCFG_CPU_PROGRAM_MAP(dsp_prg_map)
1336   MCFG_CPU_DATA_MAP(dsp_data_map)
1337MACHINE_CONFIG_END
1338
1339static MACHINE_CONFIG_DERIVED( snesst10, snes )
1340
1341   MCFG_CPU_ADD("setadsp", UPD96050, 10000000)
1342   MCFG_CPU_PROGRAM_MAP(setadsp_prg_map)
1343   MCFG_CPU_DATA_MAP(setadsp_data_map)
1344MACHINE_CONFIG_END
1345
1346static MACHINE_CONFIG_DERIVED( snesst11, snes )
1347
1348   MCFG_CPU_ADD("setadsp", UPD96050, 15000000)
1349   MCFG_CPU_PROGRAM_MAP(setadsp_prg_map)
1350   MCFG_CPU_DATA_MAP(setadsp_data_map)
1351MACHINE_CONFIG_END
1352
1353static MACHINE_CONFIG_DERIVED( snespal, snes_base )
1354   MCFG_CPU_MODIFY( "maincpu" )
1355   MCFG_CPU_CLOCK( MCLK_PAL )
1356
1357   MCFG_SCREEN_MODIFY("screen")
1358   MCFG_SCREEN_RAW_PARAMS(DOTCLK_PAL, SNES_HTOTAL, 0, SNES_SCR_WIDTH, SNES_VTOTAL_PAL, 0, SNES_SCR_HEIGHT_PAL)
1359
1360   MCFG_FRAGMENT_ADD(snesp_cartslot)
1361MACHINE_CONFIG_END
1362
1363static MACHINE_CONFIG_DERIVED( snespsfx, snespal )
1364
1365   MCFG_CPU_ADD("superfx", SUPERFX, 21480000)  /* 21.48MHz */
1366   MCFG_CPU_PROGRAM_MAP(superfx_map)
1367   MCFG_CPU_CONFIG(snes_superfx_config)
1368MACHINE_CONFIG_END
1369
1370static MACHINE_CONFIG_DERIVED( snespdsp, snespal )
1371
1372   MCFG_CPU_ADD("dsp", UPD7725, 8000000)
1373   MCFG_CPU_PROGRAM_MAP(dsp_prg_map)
1374   MCFG_CPU_DATA_MAP(dsp_data_map)
1375MACHINE_CONFIG_END
1376
1377static MACHINE_CONFIG_DERIVED( snesst, snes_base )
1378   MCFG_CPU_MODIFY( "maincpu" )
1379   MCFG_CPU_PROGRAM_MAP(snesst_map)
1380
1381   MCFG_MACHINE_START(snesst)
1382
1383   MCFG_FRAGMENT_ADD(sufami_cartslot)
1384MACHINE_CONFIG_END
1385
1386
1387/*************************************
1388 *
1389 *  ROM definition(s)
1390 *
1391 *************************************/
1392
1393ROM_START( snes )
1394   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1395
1396   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1397   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1398
1399   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
1400
1401   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
1402   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
1403ROM_END
1404
1405ROM_START( snesdsp )
1406   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1407
1408   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1409   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1410
1411   ROM_REGION( 0x10000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
1412   ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
1413   ROM_LOAD( "dsp1.bin",  SNES_DSP1_OFFSET,  0x002800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
1414   ROM_LOAD( "dsp2.bin",  SNES_DSP2_OFFSET,  0x002800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
1415   ROM_LOAD( "dsp3.bin",  SNES_DSP3_OFFSET,  0x002800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
1416   ROM_LOAD( "dsp4.bin",  SNES_DSP4_OFFSET,  0x002800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
1417
1418   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
1419   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
1420ROM_END
1421
1422ROM_START( snesst10 )
1423   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1424
1425   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1426   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1427
1428   ROM_REGION( 0x11000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
1429   ROM_LOAD( "st010.bin",    0x000000, 0x011000, CRC(aa11ee2d) SHA1(cc1984e989cb94e3dcbb5f99e085b5414e18a017) )
1430
1431   ROM_REGION( 0x10000, "dspprg", ROMREGION_ERASEFF)
1432   ROM_REGION( 0x1000, "dspdata", ROMREGION_ERASEFF)
1433ROM_END
1434
1435ROM_START( snesst11 )
1436   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1437
1438   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1439   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1440
1441   ROM_REGION( 0x11000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
1442   ROM_LOAD( "st011.bin",    0x000000, 0x011000, CRC(34d2952c) SHA1(1375b8c1efc8cae4962b57dfe22f6b78e1ddacc8) )
1443
1444   ROM_REGION( 0x10000, "dspprg", ROMREGION_ERASEFF)
1445   ROM_REGION( 0x1000, "dspdata", ROMREGION_ERASEFF)
1446ROM_END
1447
1448ROM_START( snessfx )
1449   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1450
1451   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1452   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1453
1454   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
1455
1456   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
1457   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
1458ROM_END
1459
1460ROM_START( snespal )
1461   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1462
1463   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1464   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1465
1466   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
1467
1468   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
1469   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
1470ROM_END
1471
1472ROM_START( snespdsp )
1473   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1474
1475   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1476   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1477
1478   ROM_REGION( 0x10000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
1479   ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
1480   ROM_LOAD( "dsp1.bin",  SNES_DSP1_OFFSET,  0x002800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
1481   ROM_LOAD( "dsp2.bin",  SNES_DSP2_OFFSET,  0x002800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
1482   ROM_LOAD( "dsp3.bin",  SNES_DSP3_OFFSET,  0x002800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
1483   ROM_LOAD( "dsp4.bin",  SNES_DSP4_OFFSET,  0x002800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
1484
1485   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
1486   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
1487ROM_END
1488
1489ROM_START( snespsfx )
1490   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1491
1492   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1493   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1494
1495   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
1496
1497   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
1498   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
1499ROM_END
1500
1501ROM_START( snesst )
1502   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1503
1504   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1505   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1506
1507   ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 )      /* add-on chip ROMs (DSP, SFX, etc) */
1508
1509   ROM_REGION( 0x40000, "sufami", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
1510   ROM_LOAD( "shvc-qh-0.bin", 0,   0x40000, CRC(9b4ca911) SHA1(ef86ea192eed03d5c413fdbbfd46043be1d7a127) )
1511
1512   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
1513   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
1514ROM_END
1515
1516
1517
1518/*************************************
1519 *
1520 *  Game driver(s)
1521 *
1522 *************************************/
1523
1524/*    YEAR  NAME      PARENT  COMPAT  MACHINE   INPUT  INIT          COMPANY     FULLNAME                                      FLAGS */
1525CONS( 1989, snes,     0,      0,      snes,     snes, snes_state,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1526CONS( 1991, snespal,  snes,   0,      snespal,  snes, snes_state,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1527
1528// FIXME: the "hacked" drivers below, currently needed due to limitations in the core device design, should eventually be removed
1529
1530// These would require CPU to be added/removed depending on the cart which is loaded
1531CONS( 1989, snesdsp,  snes,   0,      snesdsp,  snes, snes_state,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/DSP-x)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1532CONS( 1991, snespdsp, snes,   0,      snespdsp, snes, snes_state,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL, w/DSP-x)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1533CONS( 1989, snessfx,  snes,   0,      snessfx,  snes, snes_state,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/SuperFX)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1534CONS( 1991, snespsfx, snes,   0,      snespsfx, snes, snes_state,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL, w/SuperFX)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1535CONS( 1989, snesst10,  snes,   0,      snesst10,  snes, snes_state,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/ST-010)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1536CONS( 1989, snesst11,  snes,   0,      snesst11,  snes, snes_state,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/ST-011)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1537//CONS( 1989, snessa1,  snes,   0,      snessa1,  snes, XXX_CLASS,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/SA-1)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1538//CONS( 1991, snespsa1, snes,   0,      snespsa1, snes, XXX_CLASS,  snes_mess,    "Nintendo", "Super Nintendo Entertainment System (PAL, w/SA-1)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1539
1540// These would require cartslot to be added/removed depending on the cart which is loaded
1541CONS( 1989, snesst,   snes,   0,      snesst,  snes, snes_state,  snesst,       "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/Sufami Turbo)", GAME_NOT_WORKING )
1542
1543
1544
1545// WIP for slot-ified cart devices
1546
1547#include "machine/sns_slot.h"
1548#include "machine/sns_rom.h"
1549#include "machine/sns_rom21.h"
1550#include "machine/sns_bsx.h"
1551#include "machine/sns_sdd1.h"
1552#include "machine/sns_sfx.h"
1553#include "machine/sns_spc7110.h"
1554#include "machine/sns_sufami.h"
1555#include "machine/sns_upd.h"
1556
1557class snsnew_state : public snes_console_state
1558{
1559public:
1560   snsnew_state(const machine_config &mconfig, device_type type, const char *tag)
1561      : snes_console_state(mconfig, type, tag),
1562      m_slotcart(*this, "snsslot")
1563   { }
1564
1565   DECLARE_READ8_MEMBER( snes20_hi_r );
1566   DECLARE_WRITE8_MEMBER( snes20_hi_w );
1567   DECLARE_READ8_MEMBER( snes20_lo_r );
1568   DECLARE_WRITE8_MEMBER( snes20_lo_w );
1569   DECLARE_READ8_MEMBER( snes21_lo_r );
1570   DECLARE_WRITE8_MEMBER( snes21_lo_w );
1571   DECLARE_READ8_MEMBER( snes21_hi_r );
1572   DECLARE_WRITE8_MEMBER( snes21_hi_w );
1573   DECLARE_READ8_MEMBER( snessfx_hi_r );
1574   DECLARE_READ8_MEMBER( snessfx_lo_r );
1575   DECLARE_WRITE8_MEMBER( snessfx_hi_w );
1576   DECLARE_WRITE8_MEMBER( snessfx_lo_w );
1577   DECLARE_READ8_MEMBER( snes7110_hi_r );
1578   DECLARE_READ8_MEMBER( snes7110_lo_r );
1579   DECLARE_WRITE8_MEMBER( snes7110_hi_w );
1580   DECLARE_WRITE8_MEMBER( snes7110_lo_w );
1581   DECLARE_READ8_MEMBER( snessdd1_lo_r );
1582   DECLARE_WRITE8_MEMBER( snessdd1_lo_w );
1583   DECLARE_READ8_MEMBER( snessdd1_hi_r );
1584   DECLARE_WRITE8_MEMBER( snessdd1_hi_w );
1585   DECLARE_READ8_MEMBER( snesbsx_hi_r );
1586   DECLARE_WRITE8_MEMBER( snesbsx_hi_w );
1587   DECLARE_READ8_MEMBER( snesbsx_lo_r );
1588   DECLARE_WRITE8_MEMBER( snesbsx_lo_w );
1589
1590   optional_device<sns_cart_slot_device> m_slotcart;
1591   int m_type;
1592};
1593
1594//---------------------------------------------------------------------------------
1595// LoROM & LoROM + BSX slot & LoROM + some add-on chips
1596//---------------------------------------------------------------------------------
1597
1598// In general LoROM games have perfect mirror between 0x00-0x7d and 0x80-0xff
1599// But BSX+LoROM games use different read handlers (to access ROM beyond 2MB)
1600// so we use two different set of handlers...
1601
1602// Also we have here LoROM + CX4, until the Hitachi CPU is emulated,
1603// and the LoROM + Seta DSP, because their chip_read/chip_write need global offset
1604
1605READ8_MEMBER( snsnew_state::snes20_hi_r )
1606{
1607   UINT16 address = offset & 0xffff;
1608
1609   // take care of add-on IO
1610   if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
1611         && (offset >= 0x600000 && offset < 0x680000 && (offset & 0xffff) < 0x4000))
1612      return m_slotcart->chip_read(space, offset);
1613   else if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
1614         && (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x8000))
1615      return m_slotcart->chip_read(space, offset);
1616   else if (m_slotcart->get_type() == SNES_CX4
1617         && (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))    // hack until we emulate the real CPU
1618      return CX4_read((offset & 0xffff) - 0x6000);
1619
1620   if (offset < 0x400000)
1621   {
1622      if (address < 0x2000)
1623         return space.read_byte(0x7e0000 + address);
1624      else if (address < 0x6000)
1625         return snes_r_io(space, address);
1626      else if (address < 0x8000)
1627         return snes_open_bus_r(space, 0);
1628      else
1629         return m_slotcart->read_h(space, offset);
1630   }
1631   else if (offset < 0x700000)
1632   {
1633      if (address < 0x8000)
1634         return snes_open_bus_r(space, 0);
1635      else
1636         return m_slotcart->read_h(space, offset);
1637   }
1638   else
1639   {
1640      if (m_type == SNES_SUFAMITURBO && address >= 0x8000 && offset < 0x740000)
1641         return m_slotcart->read_h(space, offset);
1642
1643      // here usually there is SRAM mirrored in the whole range, but if ROM is very large then arrives here too (see tokimeki and wizardg4)
1644      if (m_slotcart->m_cart->get_rom_size() > 0x200000 && address >= 0x8000)
1645         return m_slotcart->read_h(space, offset);
1646      else
1647      {
1648         if (m_slotcart->m_cart->get_nvram_size() > 0x8000)
1649         {
1650            // In this case, SRAM is mapped in 0x8000 chunks at diff offsets: 0x700000-0x707fff, 0x710000-0x717fff, etc.
1651            offset = ((offset - 0x700000) / 0x10000) * 0x8000 + (offset & 0x7fff);
1652            return m_slotcart->read_ram(space, offset);
1653         }
1654         else if (m_slotcart->m_cart->get_nvram_size() > 0)
1655            return m_slotcart->read_ram(space, offset);
1656         else
1657            return snes_open_bus_r(space, 0);
1658      }
1659   }
1660}
1661
1662WRITE8_MEMBER( snsnew_state::snes20_hi_w )
1663{
1664   UINT16 address = offset & 0xffff;
1665
1666   // take care of add-on IO
1667   if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
1668         && (offset >= 0x600000 && offset < 0x680000 && (offset & 0xffff) < 0x4000))
1669   { m_slotcart->chip_write(space, offset, data); return; }
1670   else if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
1671         && (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x8000))
1672   { m_slotcart->chip_write(space, offset, data); return; }
1673   else if (m_slotcart->get_type() == SNES_CX4
1674         && (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))    // hack until we emulate the real CPU
1675   { CX4_write(space.machine(), (offset & 0xffff) - 0x6000, data); return; }
1676   else if (m_type == SNES_SUFAMITURBO
1677         && address >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
1678   { m_slotcart->write_h(space, offset, data); return; }
1679
1680   if (offset < 0x400000)
1681   {
1682      if (address < 0x2000)
1683         space.write_byte(0x7e0000 + address, data);
1684      else if (address < 0x6000)
1685         snes_w_io(space, address, data);
1686   }
1687   else if (offset >= 0x700000 && (m_slotcart->m_cart->get_rom_size() <= 0x200000 || address < 0x8000))    // NVRAM access
1688   {
1689      if (m_slotcart->m_cart->get_nvram_size() > 0x8000)
1690      {
1691         // In this case, SRAM is mapped in 0x8000 chunks at diff offsets: 0x700000-0x707fff, 0x710000-0x717fff, etc.
1692         offset = ((offset - 0x700000) / 0x10000) * 0x8000 + (offset & 0x7fff);
1693         m_slotcart->write_ram(space, offset, data);
1694      }
1695      else if (m_slotcart->m_cart->get_nvram_size() > 0)
1696         m_slotcart->write_ram(space, offset, data);
1697   }
1698}
1699
1700READ8_MEMBER( snsnew_state::snes20_lo_r )
1701{
1702   UINT16 address = offset & 0xffff;
1703
1704   // take care of add-on IO
1705   if ((m_slotcart->get_type() == SNES_ST010 /*|| m_slotcart->get_type() == SNES_ST011*/) // why does this break moritash?
1706         && (offset >= 0x600000 && offset < 0x680000 && (offset & 0xffff) < 0x4000))
1707      return m_slotcart->chip_read(space, offset);
1708   else if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
1709         && (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x8000))
1710      return m_slotcart->chip_read(space, offset);
1711   else if (m_slotcart->get_type() == SNES_CX4
1712         && (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))    // hack until we emulate the real CPU
1713      return CX4_read((offset & 0xffff) - 0x6000);
1714
1715   if (offset < 0x400000)
1716   {
1717      if (address < 0x2000)
1718         return space.read_byte(0x7e0000 + address);
1719      else if (address < 0x6000)
1720         return snes_r_io(space, address);
1721      else if (address < 0x8000)
1722         return snes_open_bus_r(space, 0);
1723      else
1724         return m_slotcart->read_l(space, offset);
1725   }
1726   else if (offset < 0x700000)
1727   {
1728      if (address < 0x8000)
1729         return snes_open_bus_r(space, 0);
1730      else
1731         return m_slotcart->read_l(space, offset);
1732   }
1733   else
1734   {
1735      if (m_type == SNES_SUFAMITURBO && address >= 0x8000 && offset < 0x740000)
1736         return m_slotcart->read_l(space, offset);
1737
1738      // here usually there is SRAM mirrored in the whole range, but if ROM is very large then arrives here too (see tokimeki and wizardg4)
1739      if (m_slotcart->m_cart->get_rom_size() > 0x200000 && address >= 0x8000)
1740         return m_slotcart->read_l(space, offset);
1741      else
1742      {
1743         if (m_slotcart->m_cart->get_nvram_size() > 0x8000)
1744         {
1745            // In this case, SRAM is mapped in 0x8000 chunks at diff offsets: 0x700000-0x707fff, 0x710000-0x717fff, etc.
1746            offset = ((offset - 0x700000) / 0x10000) * 0x8000 + (offset & 0x7fff);
1747            return m_slotcart->read_ram(space, offset);
1748         }
1749         else if (m_slotcart->m_cart->get_nvram_size() > 0)
1750            return m_slotcart->read_ram(space, offset);
1751         else
1752            return snes_open_bus_r(space, 0);
1753      }
1754   }
1755}
1756
1757WRITE8_MEMBER( snsnew_state::snes20_lo_w )
1758{
1759   if (m_type == SNES_SUFAMITURBO
1760            && (offset & 0xffff) >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
1761   { m_slotcart->write_l(space, offset, data); return; }
1762
1763   // other add-on writes matches the hi handler
1764   snes20_hi_w(space, offset, data, 0xff);
1765}
1766
1767
1768//---------------------------------------------------------------------------------
1769// HiROM & HiROM + BSX slot
1770//---------------------------------------------------------------------------------
1771
1772READ8_MEMBER( snsnew_state::snes21_lo_r )
1773{
1774   UINT16 address = offset & 0xffff;
1775
1776   if (offset < 0x400000 && address < 0x8000)
1777   {
1778      if (address < 0x2000)
1779         return space.read_byte(0x7e0000 + address);
1780      else if (address < 0x6000)
1781         return snes_r_io(space, address);
1782      else
1783      {
1784         if (m_type == SNES_BSXHI && m_slotcart->m_cart->get_nvram_size() && offset >= 0x200000)
1785         {
1786            int mask = (m_slotcart->m_cart->get_nvram_size() - 1) & 0x7fff;
1787            return m_slotcart->read_ram(space, (offset - 0x6000) & mask);
1788         }
1789
1790         if (m_slotcart->m_cart->get_nvram_size() && offset >= 0x300000)
1791         {
1792            /* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */
1793            /* OTOH Secret of Mana does not work properly if sram is not mirrored on later banks */
1794            int mask = (m_slotcart->m_cart->get_nvram_size() - 1) & 0x7fff; /* Limit SRAM size to what's actually present */
1795            return m_slotcart->read_ram(space, (offset - 0x6000) & mask);
1796         }
1797         else
1798            return snes_open_bus_r(space, 0);
1799      }
1800   }
1801
1802   // ROM access
1803   return m_slotcart->read_l(space, offset);
1804}
1805
1806WRITE8_MEMBER( snsnew_state::snes21_lo_w )
1807{
1808   UINT16 address = offset & 0xffff;
1809   if (offset < 0x400000 && address < 0x8000)
1810   {
1811      if (address < 0x2000)
1812         space.write_byte(0x7e0000 + address, data);
1813      else if (address < 0x6000)
1814         snes_w_io(space, address, data);
1815      else
1816      {
1817         if (m_type == SNES_BSXHI && m_slotcart->m_cart->get_nvram_size() && offset >= 0x200000)
1818         {
1819            int mask = (m_slotcart->m_cart->get_nvram_size() - 1) & 0x7fff;
1820            m_slotcart->write_ram(space, (offset - 0x6000) & mask, data);
1821            return;
1822         }
1823         if (m_slotcart->m_cart->get_nvram_size() && offset >= 0x300000)
1824         {
1825            /* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */
1826            /* OTOH Secret of Mana does not work properly if sram is not mirrored on later banks */
1827            int mask = (m_slotcart->m_cart->get_nvram_size() - 1) & 0x7fff; /* Limit SRAM size to what's actually present */
1828            m_slotcart->write_ram(space, (offset - 0x6000) & mask, data);
1829         }
1830      }
1831   }
1832}
1833
1834READ8_MEMBER( snsnew_state::snes21_hi_r )
1835{
1836   UINT16 address = offset & 0xffff;
1837
1838   if (offset < 0x400000 && address < 0x8000)
1839   {
1840      if (address < 0x2000)
1841         return space.read_byte(0x7e0000 + address);
1842      else if (address < 0x6000)
1843         return snes_r_io(space, address);
1844      else
1845      {
1846         if (m_type == SNES_BSXHI && m_slotcart->m_cart->get_nvram_size() && offset >= 0x200000)
1847         {
1848            int mask = (m_slotcart->m_cart->get_nvram_size() - 1) & 0x7fff;
1849            return m_slotcart->read_ram(space, (offset - 0x6000) & mask);
1850         }
1851
1852         if (m_slotcart->m_cart->get_nvram_size() && offset >= 0x300000)
1853         {
1854            /* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */
1855            /* OTOH Secret of Mana does not work properly if sram is not mirrored on later banks */
1856            int mask = (m_slotcart->m_cart->get_nvram_size() - 1) & 0x7fff; /* Limit SRAM size to what's actually present */
1857            return m_slotcart->read_ram(space, (offset - 0x6000) & mask);
1858         }
1859         else
1860            return snes_open_bus_r(space, 0);
1861      }
1862   }
1863
1864   // ROM access
1865   return m_slotcart->read_h(space, offset);
1866}
1867
1868WRITE8_MEMBER( snsnew_state::snes21_hi_w )
1869{
1870   UINT16 address = offset & 0xffff;
1871   if (offset < 0x400000 && address < 0x8000)
1872   {
1873      if (address < 0x2000)
1874         space.write_byte(0x7e0000 + address, data);
1875      else if (address < 0x6000)
1876         snes_w_io(space, address, data);
1877      else
1878      {
1879         if (m_type == SNES_BSXHI && m_slotcart->m_cart->get_nvram_size() && offset >= 0x200000)
1880         {
1881            int mask = (m_slotcart->m_cart->get_nvram_size() - 1) & 0x7fff;
1882            m_slotcart->write_ram(space, (offset - 0x6000) & mask, data);
1883            return;
1884         }
1885         if (m_slotcart->m_cart->get_nvram_size() && offset >= 0x300000)
1886         {
1887            /* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */
1888            /* OTOH Secret of Mana does not work properly if sram is not mirrored on later banks */
1889            int mask = (m_slotcart->m_cart->get_nvram_size() - 1) & 0x7fff; /* Limit SRAM size to what's actually present */
1890            m_slotcart->write_ram(space, (offset - 0x6000) & mask, data);
1891         }
1892      }
1893   }
1894}
1895
1896//---------------------------------------------------------------------------------
1897// LoROM + SuperFX / GSU
1898//---------------------------------------------------------------------------------
1899
1900READ8_MEMBER( snsnew_state::snessfx_hi_r )
1901{
1902   UINT16 address = offset & 0xffff;
1903
1904   if (offset < 0x400000)
1905   {
1906      if (address < 0x2000)
1907         return space.read_byte(0x7e0000 + address);
1908      else if (address < 0x6000)
1909      {
1910         if (address >= 0x3000 && address < 0x3300)
1911            return m_slotcart->chip_read(space, offset);
1912         else
1913            return snes_r_io(space, address);
1914      }
1915      else if (address < 0x8000)
1916         return m_slotcart->read_ram(space, offset & 0x1fff);
1917      else
1918         return m_slotcart->read_h(space, offset);
1919   }
1920   else if (offset < 0x600000)
1921      return m_slotcart->read_h(space, offset);
1922   else
1923      return m_slotcart->read_ram(space, offset);
1924}
1925
1926READ8_MEMBER( snsnew_state::snessfx_lo_r )
1927{
1928   UINT16 address = offset & 0xffff;
1929
1930   if (offset < 0x400000)
1931   {
1932      if (address < 0x2000)
1933         return space.read_byte(0x7e0000 + address);
1934      else if (address < 0x6000)
1935      {
1936         if (address >= 0x3000 && address < 0x3300)
1937            return m_slotcart->chip_read(space, offset);
1938         else
1939            return snes_r_io(space, address);
1940      }
1941      else if (address < 0x8000)
1942         return m_slotcart->read_ram(space, offset & 0x1fff);
1943      else
1944         return m_slotcart->read_l(space, offset);
1945   }
1946   else if (offset < 0x600000)
1947      return m_slotcart->read_l(space, offset);
1948   else
1949      return m_slotcart->read_ram(space, offset);
1950}
1951
1952WRITE8_MEMBER( snsnew_state::snessfx_hi_w )
1953{
1954   UINT16 address = offset & 0xffff;
1955   if (offset < 0x400000)
1956   {
1957      if (address < 0x2000)
1958         space.write_byte(0x7e0000 + address, data);
1959      else if (address < 0x6000)
1960      {
1961         if (address >= 0x3000 && address < 0x3300)
1962            m_slotcart->chip_write(space, offset, data);
1963         else
1964            snes_w_io(space, address, data);
1965      }
1966      else if (address < 0x8000)
1967         m_slotcart->write_ram(space, offset & 0x1fff, data);
1968   }
1969   else if (offset >= 0x600000)
1970      m_slotcart->write_ram(space, offset, data);
1971}
1972
1973WRITE8_MEMBER( snsnew_state::snessfx_lo_w )
1974{
1975   snessfx_hi_w(space, offset, data, 0xff);
1976}
1977
1978//---------------------------------------------------------------------------------
1979// HiROM + SPC-7110
1980//---------------------------------------------------------------------------------
1981
1982READ8_MEMBER( snsnew_state::snes7110_hi_r )
1983{
1984   UINT16 address = offset & 0xffff;
1985
1986   if (offset < 0x400000)
1987   {
1988      if (address < 0x2000)
1989         return space.read_byte(0x7e0000 + address);
1990      else if (address < 0x6000)
1991      {
1992         UINT16 limit = (m_slotcart->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
1993         if (address >= 0x4800 && address < limit)
1994            return m_slotcart->chip_read(space, address);
1995
1996         return snes_r_io(space, address);
1997      }
1998      else if (address < 0x8000)
1999      {
2000         if (offset < 0x10000)
2001            return m_slotcart->read_ram(space, offset);
2002         if (offset >= 0x300000 && offset < 0x310000)
2003            return m_slotcart->read_ram(space, offset);
2004      }
2005      else
2006         return m_slotcart->read_h(space, offset);
2007   }
2008   return m_slotcart->read_h(space, offset);
2009}
2010
2011READ8_MEMBER( snsnew_state::snes7110_lo_r )
2012{
2013   UINT16 address = offset & 0xffff;
2014
2015   if (offset < 0x400000)
2016   {
2017      if (address < 0x2000)
2018         return space.read_byte(0x7e0000 + address);
2019      else if (address < 0x6000)
2020      {
2021         UINT16 limit = (m_slotcart->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
2022         if (address >= 0x4800 && address < limit)
2023            return m_slotcart->chip_read(space, address);
2024
2025         return snes_r_io(space, address);
2026      }
2027      else if (address < 0x8000)
2028      {
2029         if (offset < 0x10000)
2030            return m_slotcart->read_ram(space, offset);
2031         if (offset >= 0x300000 && offset < 0x310000)
2032            return m_slotcart->read_ram(space, offset);
2033      }
2034      else
2035         return m_slotcart->read_l(space, offset);
2036   }
2037   if (offset >= 0x500000 && offset < 0x510000)
2038      return m_slotcart->chip_read(space, 0x4800);
2039
2040   return snes_open_bus_r(space, 0);
2041}
2042
2043WRITE8_MEMBER( snsnew_state::snes7110_hi_w )
2044{
2045   snes7110_lo_w(space, offset, data, 0xff);
2046}
2047
2048WRITE8_MEMBER( snsnew_state::snes7110_lo_w )
2049{
2050   UINT16 address = offset & 0xffff;
2051   if (offset < 0x400000)
2052   {
2053      if (address < 0x2000)
2054         space.write_byte(0x7e0000 + address, data);
2055      else if (address < 0x6000)
2056      {
2057         UINT16 limit = (m_slotcart->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
2058         if (address >= 0x4800 && address < limit)
2059         {
2060            m_slotcart->chip_write(space, address, data);
2061            return;
2062         }
2063         snes_w_io(space, address, data);
2064      }
2065      else if (address < 0x8000)
2066      {
2067         if (offset < 0x10000)
2068            m_slotcart->write_ram(space, offset, data);
2069         if (offset >= 0x300000 && offset < 0x310000)
2070            m_slotcart->write_ram(space, offset, data);
2071      }
2072   }
2073}
2074
2075
2076//---------------------------------------------------------------------------------
2077// LoROM + S-DD1
2078//---------------------------------------------------------------------------------
2079
2080READ8_MEMBER( snsnew_state::snessdd1_lo_r )
2081{
2082   UINT16 address = offset & 0xffff;
2083
2084   if (offset < 0x400000)
2085   {
2086      if (address < 0x2000)
2087         return space.read_byte(0x7e0000 + address);
2088      else if (address < 0x6000)
2089      {
2090         if (address >= 0x4800 && address < 0x4808)
2091            return m_slotcart->chip_read(space, address);
2092
2093         return snes_r_io(space, address);
2094      }
2095      else if (address < 0x8000)
2096         return snes_open_bus_r(space, 0);
2097      else
2098         return m_slotcart->read_l(space, offset);
2099   }
2100   else if (offset >= 0x700000 && address < 0x8000 && m_slotcart->m_cart->get_nvram_size())    // NVRAM access
2101      return m_slotcart->read_ram(space, offset);
2102   else    // ROM access
2103      return m_slotcart->read_l(space, offset);
2104}
2105
2106READ8_MEMBER( snsnew_state::snessdd1_hi_r )
2107{
2108   if (offset >= 0x400000)
2109      return m_slotcart->read_h(space, offset);
2110   else
2111      return snessdd1_lo_r(space, offset, 0xff);
2112}
2113
2114WRITE8_MEMBER( snsnew_state::snessdd1_lo_w )
2115{
2116   snessdd1_hi_w(space, offset, data, 0xff);
2117}
2118
2119WRITE8_MEMBER( snsnew_state::snessdd1_hi_w )
2120{
2121   UINT16 address = offset & 0xffff;
2122   if (offset < 0x400000)
2123   {
2124      if (address < 0x2000)
2125         space.write_byte(0x7e0000 + address, data);
2126      else if (address < 0x6000)
2127      {
2128         if (address >= 0x4300 && address < 0x4380)
2129         {
2130            m_slotcart->chip_write(space, address, data);
2131            // here we don't return, but we let the w_io happen...
2132         }
2133         if (address >= 0x4800 && address < 0x4808)
2134         {
2135            m_slotcart->chip_write(space, address, data);
2136            return;
2137         }
2138         snes_w_io(space, address, data);
2139      }
2140   }
2141   if (offset >= 0x700000 && address < 0x8000 && m_slotcart->m_cart->get_nvram_size())
2142      return m_slotcart->write_ram(space, offset, data);
2143}
2144
2145
2146//---------------------------------------------------------------------------------
2147// LoROM + BS-X (Base unit)
2148//---------------------------------------------------------------------------------
2149
2150READ8_MEMBER( snsnew_state::snesbsx_hi_r )
2151{
2152   UINT16 address = offset & 0xffff;
2153
2154   if (offset < 0x400000)
2155   {
2156      if (address < 0x2000)
2157         return space.read_byte(0x7e0000 + address);
2158      else if (address < 0x6000)
2159      {
2160         if (address >= 0x2188 && address < 0x21a0)
2161            return m_slotcart->chip_read(space, offset);
2162         if (address >= 0x5000)
2163            return m_slotcart->chip_read(space, offset);
2164         return snes_r_io(space, address);
2165      }
2166      else if (address < 0x8000)
2167      {
2168         if (offset >= 0x200000)
2169            return m_slotcart->read_h(space, offset);
2170         else
2171            return snes_open_bus_r(space, 0);
2172      }
2173      else
2174         return m_slotcart->read_h(space, offset);
2175   }
2176   return m_slotcart->read_h(space, offset);
2177}
2178
2179WRITE8_MEMBER( snsnew_state::snesbsx_hi_w )
2180{
2181   UINT16 address = offset & 0xffff;
2182   if (offset < 0x400000)
2183   {
2184      if (address < 0x2000)
2185         space.write_byte(0x7e0000 + address, data);
2186      else if (address < 0x6000)
2187      {
2188         if (address >= 0x2188 && address < 0x21a0)
2189         {
2190            m_slotcart->chip_write(space, offset, data);
2191            return;
2192         }
2193         if (address >= 0x5000)
2194         {
2195            m_slotcart->chip_write(space, offset, data);
2196            return;
2197         }
2198         snes_w_io(space, address, data);
2199      }
2200      else if (address < 0x8000)
2201      {
2202         if (offset >= 0x200000)
2203            return m_slotcart->write_l(space, offset, data);
2204      }
2205      else
2206         return m_slotcart->write_l(space, offset, data);
2207   }
2208   return m_slotcart->write_l(space, offset, data);
2209}
2210
2211READ8_MEMBER( snsnew_state::snesbsx_lo_r )
2212{
2213   UINT16 address = offset & 0xffff;
2214
2215   if (offset < 0x400000)
2216   {
2217      if (address < 0x2000)
2218         return space.read_byte(0x7e0000 + address);
2219      else if (address < 0x6000)
2220      {
2221         if (address >= 0x2188 && address < 0x21a0)
2222            return m_slotcart->chip_read(space, offset);
2223         if (address >= 0x5000)
2224            return m_slotcart->chip_read(space, offset);
2225         return snes_r_io(space, address);
2226      }
2227      else if (address < 0x8000)
2228      {
2229         if (offset >= 0x200000)
2230            return m_slotcart->read_l(space, offset);
2231         else
2232            return snes_open_bus_r(space, 0);
2233      }
2234      else
2235         return m_slotcart->read_l(space, offset);
2236   }
2237   return m_slotcart->read_l(space, offset);
2238}
2239
2240WRITE8_MEMBER( snsnew_state::snesbsx_lo_w )
2241{
2242   snesbsx_hi_w(space, offset, data, 0xff);
2243}
2244
2245
2246static ADDRESS_MAP_START( snesnew_map, AS_PROGRAM, 8, snsnew_state )
2247   AM_RANGE(0x000000, 0x7dffff) AM_READWRITE(snes20_lo_r, snes20_lo_w)
2248   AM_RANGE(0x7e0000, 0x7fffff) AM_RAM                 /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
2249   AM_RANGE(0x800000, 0xffffff) AM_READWRITE(snes20_hi_r, snes20_hi_w)
2250ADDRESS_MAP_END
2251
22521367static SLOT_INTERFACE_START(snes_cart)
22531368   SLOT_INTERFACE_INTERNAL("lorom",         SNS_LOROM)
22541369   SLOT_INTERFACE_INTERNAL("lorom_bsx",     SNS_LOROM_BSX) // LoROM + BS-X slot - unsupported
r21870r21871
22831398SLOT_INTERFACE_END
22841399
22851400
2286static MACHINE_START( snesnew )
1401
1402static MACHINE_START( snes_console )
22871403{
2288   snsnew_state *state = machine.driver_data<snsnew_state>();
1404   snes_console_state *state = machine.driver_data<snes_console_state>();
22891405
2290   state->m_type = state->m_slotcart->get_type();
1406   MACHINE_START_CALL(snes);
22911407
2292   MACHINE_START_CALL(snes_mess);
1408   state->m_type = state->m_cartslot->get_type();
22931409
2294   // in progress...
22951410   switch (state->m_type)
22961411   {
22971412      // LoROM & LoROM + addons
r21870r21871
23011416      case SNES_CX4:      // this still uses the old simulation instead of emulating the CPU
23021417      case SNES_ST010:    // this requires two diff kinds of chip access, so we handle it in snes20_lo/hi_r/w
23031418      case SNES_ST011:    // this requires two diff kinds of chip access, so we handle it in snes20_lo/hi_r/w
1419      case SNES_SA1:      // still unemulated
1420      case SNES_ST018:    // still unemulated
1421      case SNES_Z80GB:    // still unemulated
23041422         break;
23051423      case SNES_DSP:
2306         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x208000, 0x20ffff, 0, 0x9f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_slotcart));
2307         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x208000, 0x20ffff, 0, 0x9f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1424         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x208000, 0x20ffff, 0, 0x9f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_cartslot));
1425         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x208000, 0x20ffff, 0, 0x9f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23081426         break;
23091427      case SNES_DSP_2MB:
2310         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x600000, 0x607fff, 0, 0x8f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_slotcart));
2311         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x600000, 0x607fff, 0, 0x8f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1428         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x600000, 0x607fff, 0, 0x8f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_cartslot));
1429         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x600000, 0x607fff, 0, 0x8f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23121430         break;
23131431      case SNES_DSP4:
2314         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x308000, 0x30ffff, 0, 0x8f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_slotcart));
2315         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x308000, 0x30ffff, 0, 0x8f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1432         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x308000, 0x30ffff, 0, 0x8f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_cartslot));
1433         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x308000, 0x30ffff, 0, 0x8f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23161434         break;
23171435      case SNES_OBC1:
2318         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x006000, 0x007fff, 0, 0xbf0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_slotcart));
2319         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x006000, 0x007fff, 0, 0xbf0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1436         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x006000, 0x007fff, 0, 0xbf0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_cartslot));
1437         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x006000, 0x007fff, 0, 0xbf0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23201438         break;
23211439      case SNES_SFX:
2322         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snessfx_lo_r),state), write8_delegate(FUNC(snsnew_state::snessfx_lo_w),state));
2323         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snessfx_hi_r),state), write8_delegate(FUNC(snsnew_state::snessfx_hi_w),state));
1440         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snessfx_lo_r),state), write8_delegate(FUNC(snes_console_state::snessfx_lo_w),state));
1441         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snes_console_state::snessfx_hi_r),state), write8_delegate(FUNC(snes_console_state::snessfx_hi_w),state));
23241442         set_5a22_map(*state->m_maincpu);
23251443         break;
23261444      case SNES_SDD1:
2327         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snessdd1_lo_r),state), write8_delegate(FUNC(snsnew_state::snessdd1_lo_w),state));
2328         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snessdd1_hi_r),state), write8_delegate(FUNC(snsnew_state::snessdd1_hi_w),state));
1445         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snessdd1_lo_r),state), write8_delegate(FUNC(snes_console_state::snessdd1_lo_w),state));
1446         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snes_console_state::snessdd1_hi_r),state), write8_delegate(FUNC(snes_console_state::snessdd1_hi_w),state));
23291447         set_5a22_map(*state->m_maincpu);
23301448         break;
23311449      case SNES_BSX:
2332         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snesbsx_lo_r),state), write8_delegate(FUNC(snsnew_state::snesbsx_lo_w),state));
2333         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snesbsx_hi_r),state), write8_delegate(FUNC(snsnew_state::snesbsx_hi_w),state));
1450         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snesbsx_lo_r),state), write8_delegate(FUNC(snes_console_state::snesbsx_lo_w),state));
1451         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snes_console_state::snesbsx_hi_r),state), write8_delegate(FUNC(snes_console_state::snesbsx_hi_w),state));
23341452         set_5a22_map(*state->m_maincpu);
23351453         break;
23361454      // HiROM & HiROM + addons
23371455      case SNES_MODE21:
23381456      case SNES_BSXHI:
2339         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
2340         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
1457         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snes21_lo_r),state), write8_delegate(FUNC(snes_console_state::snes21_lo_w),state));
1458         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snes_console_state::snes21_hi_r),state), write8_delegate(FUNC(snes_console_state::snes21_hi_w),state));
23411459         set_5a22_map(*state->m_maincpu);
23421460         break;
23431461      case SNES_DSP_MODE21:
2344         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
2345         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
2346         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x006000, 0x007fff, 0, 0x9f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_slotcart));
2347         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x006000, 0x007fff, 0, 0x9f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1462         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snes21_lo_r),state), write8_delegate(FUNC(snes_console_state::snes21_lo_w),state));
1463         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snes_console_state::snes21_hi_r),state), write8_delegate(FUNC(snes_console_state::snes21_hi_w),state));
1464         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x006000, 0x007fff, 0, 0x9f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_cartslot));
1465         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x006000, 0x007fff, 0, 0x9f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23481466         set_5a22_map(*state->m_maincpu);
23491467         break;
23501468      case SNES_SRTC:
2351         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
2352         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
2353         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x002800, 0x002800, 0, 0xbf0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_slotcart));
2354         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x002801, 0x002801, 0, 0xbf0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1469         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snes21_lo_r),state), write8_delegate(FUNC(snes_console_state::snes21_lo_w),state));
1470         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snes_console_state::snes21_hi_r),state), write8_delegate(FUNC(snes_console_state::snes21_hi_w),state));
1471         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x002800, 0x002800, 0, 0xbf0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_cartslot));
1472         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x002801, 0x002801, 0, 0xbf0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23551473         set_5a22_map(*state->m_maincpu);
23561474         break;
23571475      case SNES_SPC7110:
23581476      case SNES_SPC7110_RTC:
2359         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes7110_lo_r),state), write8_delegate(FUNC(snsnew_state::snes7110_lo_w),state));
2360         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes7110_hi_r),state), write8_delegate(FUNC(snsnew_state::snes7110_hi_w),state));
1477         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snes7110_lo_r),state), write8_delegate(FUNC(snes_console_state::snes7110_lo_w),state));
1478         machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snes_console_state::snes7110_hi_r),state), write8_delegate(FUNC(snes_console_state::snes7110_hi_w),state));
23611479         set_5a22_map(*state->m_maincpu);
23621480         break;
23631481      // pirate 'mappers'
23641482      case SNES_POKEMON:
2365         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x800000, 0x80ffff, 0, 0x780000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_slotcart));
2366         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x800000, 0x80ffff, 0, 0x780000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1483         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x800000, 0x80ffff, 0, 0x780000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_cartslot));
1484         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x800000, 0x80ffff, 0, 0x780000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23671485         break;
23681486      case SNES_TEKKEN2:
2369         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x808000, 0x8087ff, 0, 0x3f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_slotcart));
2370         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x808000, 0x8087ff, 0, 0x3f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1487         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x808000, 0x8087ff, 0, 0x3f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_cartslot));
1488         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x808000, 0x8087ff, 0, 0x3f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23711489         break;
23721490      case SNES_MCPIR1:
23731491      case SNES_MCPIR2:
2374         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0xffff00, 0xffffff, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1492         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0xffff00, 0xffffff, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23751493         break;
23761494      case SNES_20COL:
2377         // why is this not working? investigate...
2378         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x008000, 0x008fff, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1495         machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x008000, 0x008fff, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23791496         break;
23801497      case SNES_SOULBLAD:
23811498         // reads from xxx0-xxx3in range [80-bf] return a fixed sequence of 4bits; reads in range [c0-ff] return open bus
2382         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x808000, 0x808003, 0, 0x3f7ff0, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_slotcart));
1499         machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x808000, 0x808003, 0, 0x3f7ff0, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_cartslot));
23831500         machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_read_handler(0xc00000, 0xffffff, FUNC(snes_open_bus_r));
23841501         break;
23851502      case SNES_BUGS:
23861503      case SNES_BANANA:
2387//          machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x808000, 0x80ffff, 0, 0x780000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_slotcart));
2388//          machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x808000, 0x80ffff, 0, 0x780000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_slotcart));
1504//          machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x808000, 0x80ffff, 0, 0x780000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)state->m_cartslot));
1505//          machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x808000, 0x80ffff, 0, 0x780000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)state->m_cartslot));
23891506//          set_5a22_map(*state->m_maincpu);
23901507         break;
23911508   }
23921509}
23931510
2394static MACHINE_CONFIG_START( snesnew, snsnew_state )
2395   MCFG_FRAGMENT_ADD( snes_base )
1511static MACHINE_RESET( snes_console )
1512{
1513   snes_console_state *state = machine.driver_data<snes_console_state>();
23961514
2397   MCFG_CPU_MODIFY("maincpu")
2398   MCFG_CPU_PROGRAM_MAP(snesnew_map)
1515   MACHINE_RESET_CALL(snes);
23991516
2400   MCFG_MACHINE_START(snesnew)
1517   state->m_io_read = write8_delegate(FUNC(snes_console_state::snes_input_read),state);
1518   state->m_oldjoy1_read = read8_delegate(FUNC(snes_console_state::snes_oldjoy1_read),state);
1519   state->m_oldjoy2_read = read8_delegate(FUNC(snes_console_state::snes_oldjoy2_read),state);
24011520
1521   // if trying to load a game requiring add-on CPU dump from fullpath,
1522   // warn the user, disable the CPU in slot & switch back to base type
1523   if (!state->m_cartslot->m_cart->get_addon_bios_size())
1524   {
1525      switch (state->m_type)
1526      {
1527         case SNES_DSP:
1528         case SNES_DSP_2MB:
1529         case SNES_DSP4:
1530         case SNES_ST010:
1531         case SNES_ST011:
1532            mame_printf_error("This type of cart requires the dump of on-cart CPU.\nPlease either load it from softlist or use snes_add driver.\n");
1533            state->m_cartslot->snes_stop_addon_cpu("dsp");
1534            state->m_type = SNES_MODE20;
1535            break;
1536         case SNES_DSP_MODE21:
1537            mame_printf_error("This type of cart requires the dump of on-cart CPU.\nPlease either load it from softlist or use snes_add driver.\n");
1538            state->m_cartslot->snes_stop_addon_cpu("dsp");
1539            state->m_type = SNES_MODE21;
1540            break;
1541         case SNES_ST018:
1542         case SNES_CX4:
1543            // we don't emulate the CPU for these yet...
1544            break;
1545      }
1546   }
1547}
1548
1549
1550static MACHINE_CONFIG_START( snes, snes_console_state )
1551
1552   /* basic machine hardware */
1553   MCFG_CPU_ADD("maincpu", _5A22, MCLK_NTSC)   /* 2.68 MHz, also 3.58 MHz */
1554   MCFG_CPU_PROGRAM_MAP(snes_map)
1555
1556   MCFG_CPU_ADD("soundcpu", SPC700, 1024000)   /* 1.024 MHz */
1557   MCFG_CPU_PROGRAM_MAP(spc_map)
1558
1559   //MCFG_QUANTUM_TIME(attotime::from_hz(48000))
1560   MCFG_QUANTUM_PERFECT_CPU("maincpu")
1561
1562   MCFG_MACHINE_START(snes_console)
1563   MCFG_MACHINE_RESET(snes_console)
1564
1565   /* video hardware */
1566   MCFG_SCREEN_ADD("screen", RASTER)
1567   MCFG_SCREEN_RAW_PARAMS(DOTCLK_NTSC * 2, SNES_HTOTAL * 2, 0, SNES_SCR_WIDTH * 2, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC)
1568   MCFG_SCREEN_UPDATE_DRIVER( snes_state, screen_update )
1569
1570   /* sound hardware */
1571   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
1572   MCFG_SOUND_ADD("spc700", SNES, 0)
1573   MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
1574   MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
1575
24021576   MCFG_SNS_CARTRIDGE_ADD("snsslot", snes_cart, NULL, NULL)
24031577   MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
24041578   MCFG_SOFTWARE_LIST_ADD("bsx_list","snes_bspack")
24051579   MCFG_SOFTWARE_LIST_ADD("st_list","snes_strom")
24061580MACHINE_CONFIG_END
24071581
2408static MACHINE_CONFIG_DERIVED( snespnew, snesnew )
1582static MACHINE_CONFIG_DERIVED( snespal, snes )
24091583   MCFG_CPU_MODIFY( "maincpu" )
24101584   MCFG_CPU_CLOCK( MCLK_PAL )
24111585
r21870r21871
24141588MACHINE_CONFIG_END
24151589
24161590
2417#define rom_snesnew rom_snes
2418#define rom_snespnew rom_snespal
1591static MACHINE_RESET( snes_addon )
1592{
1593   snes_console_state *state = machine.driver_data<snes_console_state>();
1594   UINT8 *ROM = state->memregion("addons")->base();
24191595
2420CONS( 1989, snesnew,   snes,   0,      snesnew,  snes, snes_state,  snes_mess,       "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, Test)", GAME_NOT_WORKING )
2421CONS( 1989, snespnew,  snes,   0,      snespnew, snes, snes_state,  snes_mess,       "Nintendo", "Super Nintendo Entertainment System (PAL, Test)", GAME_NOT_WORKING )
1596   MACHINE_RESET_CALL(snes);
1597
1598   state->m_io_read = write8_delegate(FUNC(snes_console_state::snes_input_read),state);
1599   state->m_oldjoy1_read = read8_delegate(FUNC(snes_console_state::snes_oldjoy1_read),state);
1600   state->m_oldjoy2_read = read8_delegate(FUNC(snes_console_state::snes_oldjoy2_read),state);
1601
1602   // if trying to load a game requiring add-on CPU dump from fullpath, load
1603   // such a dump from the BIOS (hacky workaround to support legacy sfc dumps)
1604   switch (state->m_cartslot->get_addon())
1605   {
1606      case ADDON_DSP1:
1607         state->m_cartslot->m_cart->addon_bios_alloc(machine, 0x2800);
1608         memcpy(state->m_cartslot->m_cart->get_addon_bios_base(), ROM + SNES_DSP1_OFFSET, 0x2800);
1609         break;
1610      case ADDON_DSP1B:
1611         state->m_cartslot->m_cart->addon_bios_alloc(machine, 0x2800);
1612         memcpy(state->m_cartslot->m_cart->get_addon_bios_base(), ROM + SNES_DSP1B_OFFSET, 0x2800);
1613         break;
1614      case ADDON_DSP2:
1615         state->m_cartslot->m_cart->addon_bios_alloc(machine, 0x2800);
1616         memcpy(state->m_cartslot->m_cart->get_addon_bios_base(), ROM + SNES_DSP2_OFFSET, 0x2800);
1617         break;
1618      case ADDON_DSP3:
1619         state->m_cartslot->m_cart->addon_bios_alloc(machine, 0x2800);
1620         memcpy(state->m_cartslot->m_cart->get_addon_bios_base(), ROM + SNES_DSP3_OFFSET, 0x2800);
1621         break;
1622      case ADDON_DSP4:
1623         state->m_cartslot->m_cart->addon_bios_alloc(machine, 0x2800);
1624         memcpy(state->m_cartslot->m_cart->get_addon_bios_base(), ROM + SNES_DSP4_OFFSET, 0x2800);
1625         break;
1626      case ADDON_ST010:
1627         state->m_cartslot->m_cart->addon_bios_alloc(machine, 0x11000);
1628         memcpy(state->m_cartslot->m_cart->get_addon_bios_base(), ROM + SNES_ST10_OFFSET, 0x11000);
1629         break;
1630      case ADDON_ST011:
1631         state->m_cartslot->m_cart->addon_bios_alloc(machine, 0x11000);
1632         memcpy(state->m_cartslot->m_cart->get_addon_bios_base(), ROM + SNES_ST11_OFFSET, 0x11000);
1633         break;
1634      case ADDON_CX4:
1635         state->m_cartslot->m_cart->addon_bios_alloc(machine, 0x00c00);
1636         memcpy(state->m_cartslot->m_cart->get_addon_bios_base(), ROM + SNES_CX4_OFFSET, 0x00c00);
1637         break;
1638      case ADDON_ST018:
1639         state->m_cartslot->m_cart->addon_bios_alloc(machine, 0x28000);
1640         memcpy(state->m_cartslot->m_cart->get_addon_bios_base(), ROM + SNES_ST18_OFFSET1, 0x20000);
1641         memcpy(state->m_cartslot->m_cart->get_addon_bios_base() + 0x20000, ROM + SNES_ST18_OFFSET2, 0x8000);
1642         break;
1643      default:
1644         break;
1645   }
1646}
1647
1648
1649static MACHINE_CONFIG_DERIVED( snes_add, snes )
1650   MCFG_MACHINE_RESET( snes_addon )
1651MACHINE_CONFIG_END
1652
1653static MACHINE_CONFIG_DERIVED( snesp_add, snespal )
1654   MCFG_MACHINE_RESET( snes_addon )
1655MACHINE_CONFIG_END
1656
1657
1658/*************************************
1659 *
1660 *  ROM definition(s)
1661 *
1662 *************************************/
1663
1664ROM_START( snes )
1665   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1666
1667   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1668   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1669ROM_END
1670
1671ROM_START( snes_add )
1672   ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
1673
1674   ROM_REGION( 0x100, "sound_ipl", 0 )     /* IPL ROM */
1675   ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
1676
1677   ROM_REGION( 0x60000, "addons", 0 )      /* add-on chip ROMs (DSP, SFX, etc) */
1678   ROM_LOAD( "dsp1.bin",       SNES_DSP1_OFFSET,  0x02800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
1679   ROM_LOAD( "dsp1b.bin",      SNES_DSP1B_OFFSET, 0x02800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
1680   ROM_LOAD( "dsp2.bin",       SNES_DSP2_OFFSET,  0x02800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
1681   ROM_LOAD( "dsp3.bin",       SNES_DSP3_OFFSET,  0x02800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
1682   ROM_LOAD( "dsp4.bin",       SNES_DSP4_OFFSET,  0x02800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
1683   ROM_LOAD( "st010.bin",      SNES_ST10_OFFSET,  0x11000, CRC(aa11ee2d) SHA1(cc1984e989cb94e3dcbb5f99e085b5414e18a017) )
1684   ROM_LOAD( "st011.bin",      SNES_ST11_OFFSET,  0x11000, CRC(34d2952c) SHA1(1375b8c1efc8cae4962b57dfe22f6b78e1ddacc8) )
1685   ROM_LOAD( "cx4.bin",        SNES_CX4_OFFSET,   0x00c00, CRC(b6e76a6a) SHA1(a002f4efba42775a31185d443f3ed1790b0e949a) )
1686   ROM_LOAD( "st018_0xf3.bin", SNES_ST18_OFFSET1, 0x20000, CRC(f73d5e10) SHA1(388e3721b94cd074d6ba0eca8616523d2118a6c3) )
1687   ROM_LOAD( "st018_0xf4.bin", SNES_ST18_OFFSET2, 0x08000, CRC(b5255459) SHA1(b19c0f8f207d62fdabf4bf71442826063bccc626) )
1688ROM_END
1689
1690#define rom_snespal rom_snes
1691#define rom_snesp_add rom_snes_add
1692
1693/*************************************
1694 *
1695 *  Game driver(s)
1696 *
1697 *************************************/
1698
1699/*    YEAR  NAME       PARENT  COMPAT MACHINE    INPUT                 INIT  COMPANY     FULLNAME                                      FLAGS */
1700CONS( 1989, snes,      0,      0,     snes,      snes, driver_device,  0,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1701CONS( 1991, snespal,   snes,   0,     snespal,   snes, driver_device,  0,    "Nintendo", "Super Nintendo Entertainment System (PAL)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
1702
1703// legacy drivers to allow loading old .sfc files of DSPx/CX4/ST0xx games without the add-on chip dump (add-on dumps directly in the BIOS)
1704CONS( 1989, snes_add,  snes,   0,     snes_add,  snes, driver_device,  0,    "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/add-on CPUs)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND | GAME_UNOFFICIAL)
1705CONS( 1991, snesp_add, snes,   0,     snesp_add, snes, driver_device,  0,    "Nintendo", "Super Nintendo Entertainment System (PAL, w/add-on CPUs)",  GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND | GAME_UNOFFICIAL)
trunk/src/mess/mess.mak
r21870r21871
14011401   $(MESS_VIDEO)/nes.o         \
14021402   $(MESS_MACHINE)/nes.o       \
14031403   $(MESS_DRIVERS)/nes.o       \
1404   $(MESS_MACHINE)/snescart.o  \
1404   $(MESS_MACHINE)/snescx4.o   \
14051405   $(MESS_MACHINE)/sns_slot.o  \
14061406   $(MESS_MACHINE)/sns_rom.o   \
14071407   $(MESS_MACHINE)/sns_rom21.o \
r21870r21871
21162116# miscellaneous dependencies
21172117#-------------------------------------------------
21182118
2119$(MESS_MACHINE)/snescart.o: $(MESSSRC)/machine/snesobc1.c \
2120            $(MESSSRC)/machine/snescx4.c \
2121            $(MESSSRC)/machine/cx4ops.c \
2119$(MESS_MACHINE)/snescx4.o: $(MESSSRC)/machine/cx4ops.c \
21222120            $(MESSSRC)/machine/cx4oam.c \
21232121            $(MESSSRC)/machine/cx4fn.c \
21242122            $(MESSSRC)/machine/cx4data.c \
2125            $(MESSSRC)/machine/snesrtc.c \
2126            $(MESSSRC)/machine/snessdd1.c \
2127            $(MESSSRC)/machine/snes7110.c \
21282123
21292124$(MESS_VIDEO)/gba.o:        $(MESSSRC)/video/gbamode0.c \
21302125            $(MESSSRC)/video/gbamode1.c \
trunk/src/mess/machine/snescart.c
r21870r21871
1/***************************************************************************
2
3  snescart.c
4
5  Machine file to handle cart loading in the Nintendo Super NES emulation.
6
7***************************************************************************/
8
9#include "emu.h"
10#include "includes/snes.h"
11#include "imagedev/cartslot.h"
12#include "snescart.h"
13
14#define SNES_CART_DEBUG 0
15
16/****** Strings for Cart Header Logging ******/
17
18#define UNK "Unknown"
19
20/* Some known type of cart */
21static const char *const types[] =
22{
23   "ROM",
24   "ROM, DSP-1",
25   "ROM, DSP-2",
26   "ROM, DSP-3",
27   "ROM, DSP-4",
28   "ROM, Super FX / FX2",
29   "ROM, SA-1",
30   "ROM, S-DD1",
31   "ROM, OBC-1",
32   "ROM, S-RTC",
33   "ROM, Z80GB (Super Game Boy)",
34   "ROM, C4",
35   "ROM, Seta ST-010",
36   "ROM, Seta ST-011",
37   "ROM, Seta ST-018",
38   "ROM, SPC7110",
39   "ROM, SPC7110, RTC",
40   UNK,                            // to add: Satellaview BS-X detection
41};
42
43/* Some known countries */
44static const char *const countries[] =
45{
46/* 0*/  "Japan (NTSC)", "USA & Canada (NTSC)", "Europe, Oceania & Asia (PAL)", "Sweden (PAL)",
47/* 4*/  "Finland (PAL)", "Denmark (PAL)", "France (PAL)", "Holland (PAL)",
48/* 8*/  "Spain (PAL)", "Germany, Austria & Switzerland (PAL)", "Italy (PAL)", "Hong Kong & China (PAL)",
49/* c*/  "Indonesia (PAL)", "South Korea (NTSC)", UNK, UNK,
50};
51
52/* Some known companies (integrations to the list from Snes9x) */
53static const char *const companies[] =
54{
55/* 0*/  "Invalid", "Nintendo", "Ajinomoto", "Imagineer-Zoom", "Chris Gray Enterprises Inc.", "Zamuse", "Falcom", UNK,
56/* 8*/  "Capcom", "HOT-B", "Jaleco", "Coconuts", "Rage Software", "Micronet", "Technos", "Mebio Software",
57/*10*/  "SHOUEi System", "Starfish", "Gremlin Graphics", "Electronic Arts", "NCS / Masaya", "COBRA Team", "Human/Field", "KOEI",
58/*18*/  "Hudson Soft", "Game Village", "Yanoman", UNK, "Tecmo", UNK, "Open System", "Virgin Games",
59/*20*/  "KSS", "Sunsoft", "POW", "Micro World", UNK, UNK, "Enix", "Loriciel/Electro Brain",
60/*28*/  "Kemco", "Seta Co.,Ltd.", "Culture Brain", "Irem Japan", "Pal Soft", "Visit Co.,Ltd.", "INTEC Inc.", "System Sacom Corp.",
61/*30*/  "Viacom New Media", "Carrozzeria", "Dynamic", "Nintendo", "Magifact", "Hect", UNK, UNK,
62/*38*/  "Capcom Europe", "Accolade Europe", UNK, "Arcade Zone", "Empire Software", "Loriciel", "Gremlin Graphics", UNK,
63/*40*/  "Seika Corp.", "UBI Soft", UNK, UNK, "LifeFitness Exertainment", UNK, "System 3", "Spectrum Holobyte",
64/*48*/  UNK, "Irem", UNK, "Raya Systems/Sculptured Software", "Renovation Products", "Malibu Games/Black Pearl", UNK, "U.S. Gold",
65/*50*/  "Absolute Entertainment", "Acclaim", "Activision", "American Sammy", "GameTek", "Hi Tech Expressions", "LJN Toys", UNK,
66/*58*/  UNK, UNK, "Mindscape", "Romstar, Inc.", UNK, "Tradewest", UNK, "American Softworks Corp.",
67/*60*/  "Titus", "Virgin Interactive Entertainment", "Maxis", "Origin/FCI/Pony Canyon", UNK, UNK, UNK, "Ocean",
68/*68*/  UNK, "Electronic Arts", UNK, "Laser Beam", UNK, UNK, "Elite", "Electro Brain",
69/*70*/  "Infogrames", "Interplay", "LucasArts", "Parker Brothers", "Konami", "STORM", UNK, UNK,
70/*78*/  "THQ Software", "Accolade Inc.", "Triffix Entertainment", UNK, "Microprose", UNK, UNK, "Kemco",
71/*80*/  "Misawa", "Teichio", "Namco Ltd.", "Lozc", "Koei", UNK, "Tokuma Shoten Intermedia", "Tsukuda Original",
72/*88*/  "DATAM-Polystar", UNK, UNK, "Bullet-Proof Software", "Vic Tokai", UNK, "Character Soft", "I\'\'Max",
73/*90*/  "Takara", "CHUN Soft", "Video System Co., Ltd.", "BEC", UNK, "Varie", "Yonezawa / S'Pal Corp.", "Kaneco",
74/*98*/  UNK, "Pack in Video", "Nichibutsu", "TECMO", "Imagineer Co.", UNK, UNK, UNK,
75/*a0*/  "Telenet", "Hori", UNK, UNK, "Konami", "K.Amusement Leasing Co.", UNK, "Takara",
76/*a8*/  UNK, "Technos Jap.", "JVC", UNK, "Toei Animation", "Toho", UNK, "Namco Ltd.",
77/*b0*/  "Media Rings Corp.", "ASCII Co. Activison", "Bandai", UNK, "Enix America", UNK, "Halken", UNK,
78/*b8*/  UNK, UNK, "Culture Brain", "Sunsoft", "Toshiba EMI", "Sony Imagesoft", UNK, "Sammy",
79/*c0*/  "Taito", UNK, "Kemco", "Square", "Tokuma Soft", "Data East", "Tonkin House", UNK,
80/*c8*/  "KOEI", UNK, "Konami USA", "NTVIC", UNK, "Meldac", "Pony Canyon", "Sotsu Agency/Sunrise",
81/*d0*/  "Disco/Taito", "Sofel", "Quest Corp.", "Sigma", "Ask Kodansha Co., Ltd.", UNK, "Naxat", UNK,
82/*d8*/  "Capcom Co., Ltd.", "Banpresto", "Tomy", "Acclaim", UNK, "NCS", "Human Entertainment", "Altron",
83/*e0*/  "Jaleco", UNK, "Yutaka", UNK, "T&ESoft", "EPOCH Co.,Ltd.", UNK, "Athena",
84/*e8*/  "Asmik", "Natsume", "King Records", "Atlus", "Sony Music Entertainment", UNK, "IGS", UNK,
85/*f0*/  UNK, "Motown Software", "Left Field Entertainment", "Beam Software", "Tec Magik", UNK, UNK, UNK,
86/*f8*/  UNK, "Cybersoft", UNK, "Psygnosis", UNK, UNK, "Davidson", UNK,
87};
88
89
90/* We use this to convert the company_id in the header to int value to be passed in companies[] */
91static int char_to_int_conv( char id )
92{
93   int value;
94
95   if (id == '1') value = 0x01;
96   else if (id == '2') value = 0x02;
97   else if (id == '3') value = 0x03;
98   else if (id == '4') value = 0x04;
99   else if (id == '5') value = 0x05;
100   else if (id == '6') value = 0x06;
101   else if (id == '7') value = 0x07;
102   else if (id == '8') value = 0x08;
103   else if (id == '9') value = 0x09;
104   else if (id == 'A') value = 0x0a;
105   else if (id == 'B') value = 0x0b;
106   else if (id == 'C') value = 0x0c;
107   else if (id == 'D') value = 0x0d;
108   else if (id == 'E') value = 0x0e;
109   else if (id == 'F') value = 0x0f;
110   else value = 0x00;
111
112   return value;
113}
114
115
116/***************************************************************************
117
118  SRAM handling
119
120***************************************************************************/
121
122/* Loads the battery backed RAM into the appropriate memory area */
123static void snes_load_sram(running_machine &machine)
124{
125   snes_state *state = machine.driver_data<snes_state>();
126   device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart"));
127   image->battery_load(state->m_cart[0].m_nvram, state->m_cart[0].m_nvram_size, 0xff);
128}
129
130/* Saves the battery backed RAM from the appropriate memory area */
131void snes_machine_stop(running_machine &machine)
132{
133   snes_state *state = machine.driver_data<snes_state>();
134
135   /* Save SRAM */
136   if (state->m_cart[0].m_nvram_size > 0)
137   {
138      device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart"));
139      image->battery_save(state->m_cart[0].m_nvram, state->m_cart[0].m_nvram_size);
140   }
141}
142
143
144static void sufami_load_sram(running_machine &machine, const char *cart_tag)
145{
146   snes_state *state = machine.driver_data<snes_state>();
147   int slot_id = 0;
148   device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device(cart_tag));
149
150   if (strcmp(cart_tag, ":slot_a") == 0)
151      slot_id = 0;
152
153   if (strcmp(cart_tag, ":slot_b") == 0)
154      slot_id = 1;
155
156   image->battery_load(state->m_cart[slot_id].m_nvram, state->m_cart[slot_id].m_nvram_size, 0xff);
157}
158
159void sufami_machine_stop(running_machine &machine)
160{
161   snes_state *state = machine.driver_data<snes_state>();
162
163   if (state->m_cart[0].slot_in_use && state->m_cart[0].m_nvram_size)
164   {
165      device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("slot_a"));
166      image->battery_save(state->m_cart[0].m_nvram, state->m_cart[0].m_nvram_size);
167   }
168
169   if (state->m_cart[1].slot_in_use && state->m_cart[1].m_nvram_size)
170   {
171      device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("slot_b"));
172      image->battery_save(state->m_cart[1].m_nvram, state->m_cart[1].m_nvram_size);
173   }
174}
175
176
177/***************************************************************************
178
179  Cart handling
180
181***************************************************************************/
182
183/* This function assign a 'score' to data immediately after 'offset' to measure how valid they are
184as information block (to decide if the image is HiRom, LoRom, ExLoRom or ExHiRom) */
185/* Code from bsnes, courtesy of byuu - http://byuu.org/ , based on previous code by Cowering */
186static int snes_validate_infoblock( UINT8 *infoblock, UINT32 offset )
187{
188   int score = 0;
189   UINT16 reset_vector = infoblock[offset + 0x3c] | (infoblock[offset + 0x3d] << 8);
190   UINT16 checksum     = infoblock[offset + 0x1e] | (infoblock[offset + 0x1f] << 8);
191   UINT16 ichecksum    = infoblock[offset + 0x1c] | (infoblock[offset + 0x1d] << 8);
192   UINT8 reset_opcode  = infoblock[(offset & ~0x7fff) | (reset_vector & 0x7fff)];  //first opcode executed upon reset
193   UINT8 mapper        = infoblock[offset + 0x15] & ~0x10;                         //mask off irrelevant FastROM-capable bit
194
195   /* $00:[000-7fff] contains uninitialized RAM and MMIO.
196   reset vector must point to ROM at $00:[8000-ffff] to be considered valid. */
197   if (reset_vector < 0x8000)
198      return 0;
199
200   /* some images duplicate the header in multiple locations, and others have completely
201   invalid header information that cannot be relied upon. The code below will analyze
202   the first opcode executed at the specified reset vector to determine the probability
203   that this is the correct header. Score is assigned accordingly. */
204
205   /* most likely opcodes */
206   if (reset_opcode == 0x78        //sei
207      || reset_opcode == 0x18     //clc (clc; xce)
208      || reset_opcode == 0x38     //sec (sec; xce)
209      || reset_opcode == 0x9c     //stz $nnnn (stz $4200)
210      || reset_opcode == 0x4c     //jmp $nnnn
211      || reset_opcode == 0x5c     //jml $nnnnnn
212   )
213      score += 8;
214
215   /* plausible opcodes */
216   if (reset_opcode == 0xc2        //rep #$nn
217      || reset_opcode == 0xe2     //sep #$nn
218      || reset_opcode == 0xad     //lda $nnnn
219      || reset_opcode == 0xae     //ldx $nnnn
220      || reset_opcode == 0xac     //ldy $nnnn
221      || reset_opcode == 0xaf     //lda $nnnnnn
222      || reset_opcode == 0xa9     //lda #$nn
223      || reset_opcode == 0xa2     //ldx #$nn
224      || reset_opcode == 0xa0     //ldy #$nn
225      || reset_opcode == 0x20     //jsr $nnnn
226      || reset_opcode == 0x22     //jsl $nnnnnn
227   )
228      score += 4;
229
230   /* implausible opcodes */
231   if (reset_opcode == 0x40        //rti
232      || reset_opcode == 0x60     //rts
233      || reset_opcode == 0x6b     //rtl
234      || reset_opcode == 0xcd     //cmp $nnnn
235      || reset_opcode == 0xec     //cpx $nnnn
236      || reset_opcode == 0xcc     //cpy $nnnn
237   )
238      score -= 4;
239
240   /* least likely opcodes */
241   if (reset_opcode == 0x00        //brk #$nn
242      || reset_opcode == 0x02     //cop #$nn
243      || reset_opcode == 0xdb     //stp
244      || reset_opcode == 0x42     //wdm
245      || reset_opcode == 0xff     //sbc $nnnnnn,x
246   )
247      score -= 8;
248
249   /* Sometimes, both the header and reset vector's first opcode will match ...
250   fallback and rely on info validity in these cases to determine more likely header. */
251
252   /* a valid checksum is the biggest indicator of a valid header. */
253   if ((checksum + ichecksum) == 0xffff && (checksum != 0) && (ichecksum != 0))
254      score += 4;
255
256   /* then there are the expected mapper values */
257   if (offset == 0x007fc0 && mapper == 0x20)   // 0x20 is usually LoROM
258      score += 2;
259
260   if (offset == 0x00ffc0 && mapper == 0x21)   // 0x21 is usually HiROM
261      score += 2;
262
263   if (offset == 0x007fc0 && mapper == 0x22)   // 0x22 is usually ExLoROM
264      score += 2;
265
266   if (offset == 0x40ffc0 && mapper == 0x25)   // 0x25 is usually ExHiROM
267      score += 2;
268
269   /* finally, there are valid values in the Company, Region etc. fields */
270   if (infoblock[offset + 0x1a] == 0x33)           // Company field: 0x33 indicates extended header
271      score += 2;
272
273   if (infoblock[offset + 0x16] < 0x08)            // ROM Type field
274      score++;
275
276   if (infoblock[offset + 0x17] < 0x10)            // ROM Size field
277      score++;
278
279   if (infoblock[offset + 0x18] < 0x08)            // SRAM Size field
280      score++;
281
282   if (infoblock[offset + 0x19] < 14)              // Region field
283      score++;
284
285   /* do we still have a positive score? */
286   if (score < 0)
287      score = 0;
288
289   return score;
290}
291
292/* Here we add a couple of cart utilities, to avoid duplicating the code in each DEVICE_IMAGE_LOAD */
293static UINT32 snes_skip_header( device_image_interface &image, UINT32 snes_rom_size )
294{
295   UINT8 header[512];
296   UINT32 offset = 512;
297
298   /* Check for a header (512 bytes) */
299   if (image.software_entry() == NULL)
300      image.fread(header, 512);
301   else
302      memcpy(header, image.get_software_region("rom"), 512);
303
304   if ((header[8] == 0xaa) && (header[9] == 0xbb) && (header[10] == 0x04))
305   {
306      /* Found an SWC identifier */
307      logerror("Found header (SWC) - Skipped\n");
308   }
309   else if ((header[0] | (header[1] << 8)) == (((snes_rom_size - 512) / 1024) / 8))
310   {
311      /* Some headers have the rom size at the start, if this matches with the actual rom size, we probably have a header */
312      logerror("Found header (size) - Skipped\n");
313   }
314   else if ((snes_rom_size % 0x8000) == 512)
315   {
316      /* As a last check we'll see if there's exactly 512 bytes extra to this image. */
317      logerror("Found header (extra) - Skipped\n");
318   }
319   else
320   {
321      /* No header found so go back to the start of the file */
322      logerror("No header found.\n");
323      offset = 0;
324   }
325
326   return offset;
327}
328
329
330/* This determines if a cart is in Mode 20, 21, 22 or 25; sets state->m_cart[0].mode and
331 state->m_cart[0].sram_max accordingly; and returns the offset of the internal header
332 (needed to detect BSX and ST carts) */
333static UINT32 snes_find_hilo_mode( running_machine &machine, UINT8 *buffer, UINT32 len, int cartid )
334{
335   snes_state *state = machine.driver_data<snes_state>();
336   UINT8 valid_mode20, valid_mode21, valid_mode25;
337   UINT32 retvalue;
338
339   /* Now to determine if this is a lo-ROM, a hi-ROM or an extended lo/hi-ROM */
340   valid_mode20 = snes_validate_infoblock(buffer, 0x007fc0);
341   valid_mode21 = snes_validate_infoblock(buffer, 0x00ffc0);
342   valid_mode25 = (len > 0x40ffc0) ? snes_validate_infoblock(buffer, 0x40ffc0) : 0;
343
344   /* Images larger than 32mbits are likely ExHiRom */
345   if (valid_mode25)
346      valid_mode25 += 4;
347
348   if ((valid_mode20 >= valid_mode21) && (valid_mode20 >= valid_mode25))
349   {
350      if (buffer[0x007fd5] == 0x32 || len > 0x401000)
351         state->m_cart[cartid].mode = SNES_MODE_22;  // ExLoRom
352      else
353         state->m_cart[cartid].mode = SNES_MODE_20;  // LoRom
354
355      retvalue = 0x007fc0;
356
357      /* a few games require 512k, however we store twice as much to be sure to cover the various mirrors */
358      state->m_cart[cartid].sram_max = 0x100000;
359   }
360   else if (valid_mode21 >= valid_mode25)
361   {
362      state->m_cart[cartid].mode = SNES_MODE_21;  // HiRom
363      retvalue = 0x00ffc0;
364      state->m_cart[cartid].sram_max = 0x20000;
365   }
366   else
367   {
368      state->m_cart[cartid].mode = SNES_MODE_25;  // ExHiRom
369      retvalue = 0x40ffc0;
370      state->m_cart[cartid].sram_max = 0x20000;
371   }
372
373   logerror( "\t HiROM/LoROM id: %s (LoROM: %d , HiROM: %d, ExHiROM: %d)\n",
374            (state->m_cart[cartid].mode == SNES_MODE_20) ? "LoROM" :
375            (state->m_cart[cartid].mode == SNES_MODE_21) ? "HiROM" :
376            (state->m_cart[cartid].mode == SNES_MODE_22) ? "ExLoROM" :
377            (state->m_cart[cartid].mode == SNES_MODE_25) ? "ExHiROM" : "Other (BSX or ST)",
378            valid_mode20, valid_mode21, valid_mode25);
379
380   return retvalue;
381}
382
383static int snes_find_addon_chip( running_machine &machine, UINT8 *buffer, UINT32 start_offs )
384{
385   snes_state *state = machine.driver_data<snes_state>();
386   int supported_type = 1;
387   int dsp_prg_offset = 0;
388
389   /* Info mostly taken from http://snesemu.black-ship.net/misc/-from%20nsrt.edgeemu.com-chipinfo.htm */
390   switch (buffer[start_offs + 0x16])
391   {
392      case 0x00:
393      case 0x01:
394      case 0x02:
395         state->m_has_addon_chip = HAS_NONE;
396         break;
397
398      case 0x03:
399         if (buffer[start_offs + 0x15] == 0x30)
400         {
401            state->m_has_addon_chip = HAS_DSP4;
402            dsp_prg_offset = SNES_DSP4_OFFSET;
403         }
404         else
405         {
406            state->m_has_addon_chip = HAS_DSP1;
407            dsp_prg_offset = SNES_DSP1B_OFFSET;
408         }
409         break;
410
411      case 0x04:
412         state->m_has_addon_chip = HAS_DSP1;
413         dsp_prg_offset = SNES_DSP1B_OFFSET;
414         break;
415
416      case 0x05:
417         if (buffer[start_offs + 0x15] == 0x20)
418         {
419            state->m_has_addon_chip = HAS_DSP2;
420            dsp_prg_offset = SNES_DSP2_OFFSET;
421         }
422         /* DSP-3 is hard to detect. We exploit the fact that the only game has been manufactured by Bandai */
423         else if ((buffer[start_offs + 0x15] == 0x30) && (buffer[start_offs + 0x1a] == 0xb2))
424         {
425            state->m_has_addon_chip = HAS_DSP3;
426            dsp_prg_offset = SNES_DSP3_OFFSET;
427         }
428         else
429         {
430            state->m_has_addon_chip = HAS_DSP1;
431            dsp_prg_offset = SNES_DSP1B_OFFSET;
432         }
433         break;
434
435      case 0x13:  // Mario Chip 1
436      case 0x14:  // GSU-x
437      case 0x15:  // GSU-x
438      case 0x1a:  // GSU-1 (21 MHz at start)
439         if (buffer[start_offs + 0x15] == 0x20)
440            state->m_has_addon_chip = HAS_SUPERFX;
441         break;
442
443      case 0x25:
444         state->m_has_addon_chip = HAS_OBC1;
445         break;
446
447      case 0x32:  // needed by a Sample game (according to ZSNES)
448      case 0x34:
449      case 0x35:
450         if (buffer[start_offs + 0x15] == 0x23)
451         {
452            state->m_has_addon_chip = HAS_SA1;
453            supported_type = 0;
454            mame_printf_error("This is a SA-1 type game, currently unsupported by the driver\n");
455         }
456         break;
457
458      case 0x43:
459      case 0x45:
460         if (buffer[start_offs + 0x15] == 0x32)
461         {
462            state->m_has_addon_chip = HAS_SDD1;
463         }
464         break;
465
466      case 0x55:
467         if (buffer[start_offs + 0x15] == 0x35)
468         {
469            state->m_has_addon_chip = HAS_RTC;
470         }
471         break;
472
473      case 0xe3:
474         state->m_has_addon_chip = HAS_Z80GB;
475         supported_type = 0;
476         break;
477
478      case 0xf3:
479         state->m_has_addon_chip = HAS_CX4;
480         break;
481
482      case 0xf5:
483         if (buffer[start_offs + 0x15] == 0x30)
484         {
485            state->m_has_addon_chip = HAS_ST018;
486            supported_type = 0;
487         }
488         else if (buffer[start_offs + 0x15] == 0x3a)
489         {
490            state->m_has_addon_chip = HAS_SPC7110;
491         }
492         break;
493
494      case 0xf6:
495         /* These Seta ST-01X chips have both 0x30 at 0x00ffd5,
496          they only differ for the 'size' at 0x00ffd7 */
497         if (buffer[start_offs + 0x17] < 0x0a)
498            state->m_has_addon_chip = HAS_ST011;
499         else
500            state->m_has_addon_chip = HAS_ST010;
501         break;
502
503      case 0xf9:
504         if (buffer[start_offs + 0x15] == 0x3a)
505         {
506            state->m_has_addon_chip = HAS_SPC7110_RTC;
507            supported_type = 0;
508         }
509         break;
510
511      default:
512         state->m_has_addon_chip = HAS_UNK;
513         supported_type = 0;
514         break;
515   }
516
517   if ((state->m_has_addon_chip >= HAS_DSP1) && (state->m_has_addon_chip <= HAS_DSP4))
518   {
519      UINT8 *dspsrc = (UINT8 *)(*machine.root_device().memregion("addons"));
520      UINT32 *dspprg = (UINT32 *)(*machine.root_device().memregion("dspprg"));
521      UINT16 *dspdata = (UINT16 *)(*machine.root_device().memregion("dspdata"));
522
523      // copy DSP program
524      for (int i = 0; i < 0x2000; i+= 4)
525      {
526         *dspprg = dspsrc[dsp_prg_offset+0+i]<<24 | dspsrc[dsp_prg_offset+1+i]<<16 | dspsrc[dsp_prg_offset+2+i]<<8;
527         dspprg++;
528      }
529
530      // copy DSP data
531      for (int i = 0; i < 0x800; i+= 2)
532      {
533         *dspdata++ = dspsrc[dsp_prg_offset+0x2000+i]<<8 | dspsrc[dsp_prg_offset+0x2001+i];
534      }
535   }
536
537   if ((state->m_has_addon_chip == HAS_ST010) || (state->m_has_addon_chip == HAS_ST011))
538   {
539      UINT8 *dspsrc = (UINT8 *)(*machine.root_device().memregion("addons"));
540      UINT32 *dspprg = (UINT32 *)(*machine.root_device().memregion("dspprg"));
541      UINT16 *dspdata = (UINT16 *)(*machine.root_device().memregion("dspdata"));
542
543      // copy DSP program
544      for (int i = 0; i < 0x10000; i+= 4)
545      {
546         *dspprg = dspsrc[0+i]<<24 | dspsrc[1+i]<<16 | dspsrc[2+i]<<8;
547         dspprg++;
548      }
549
550      // copy DSP data
551      for (int i = 0; i < 0x1000; i+= 2)
552      {
553         *dspdata++ = dspsrc[0x10000+i]<<8 | dspsrc[0x10001+i];
554      }
555   }
556
557   return supported_type;
558}
559
560static void snes_cart_log_info( running_machine &machine, UINT8* ROM, UINT32 len, int supported )
561{
562   snes_state *state = machine.driver_data<snes_state>();
563   char title[21], rom_id[4], company_id[2];
564   int i, company, has_ram = 0, has_sram = 0;
565   UINT32 hilo_mode = snes_find_hilo_mode(machine, ROM, len, 0);
566
567   /* Company */
568   for (i = 0; i < 2; i++)
569      company_id[i] = ROM[hilo_mode - 0x10 + i];
570   company = (char_to_int_conv(company_id[0]) << 4) + char_to_int_conv(company_id[1]);
571   if (company == 0)
572      company = ROM[hilo_mode + 0x1a];
573
574   /* ROM ID */
575   for (i = 0; i < 4; i++)
576      rom_id[i] = ROM[hilo_mode - 0x0e + i];
577
578   /* Title */
579   for (i = 0; i < 21; i++)
580      title[i] = ROM[hilo_mode + i];
581
582   /* RAM */
583   if (((ROM[hilo_mode + 0x16] & 0xf) == 1) ||
584      ((ROM[hilo_mode + 0x16] & 0xf) == 2) ||
585      ((ROM[hilo_mode + 0x16] & 0xf) == 4) ||
586      ((ROM[hilo_mode + 0x16] & 0xf) == 5))
587      has_ram = 1;
588
589   /* SRAM */
590   if (((ROM[hilo_mode + 0x16] & 0xf) == 2) ||
591      ((ROM[hilo_mode + 0x16] & 0xf) == 5) ||
592      ((ROM[hilo_mode + 0x16] & 0xf) == 6))
593      has_sram = 1;
594
595   int total_blocks = len / (state->m_cart[0].mode & 0xa5 ? 0x8000 : 0x10000);
596
597   logerror( "ROM DETAILS\n" );
598   logerror( "===========\n\n" );
599   logerror( "\tTotal blocks:  %d (%dmb)\n", total_blocks, total_blocks / (state->m_cart[0].mode & 5 ? 32 : 16) );
600   logerror( "\tROM bank size: %s \n",
601            (state->m_cart[0].mode == SNES_MODE_20) ? "LoROM" :
602            (state->m_cart[0].mode == SNES_MODE_21) ? "HiROM" :
603            (state->m_cart[0].mode == SNES_MODE_22) ? "ExLoROM" :
604            (state->m_cart[0].mode == SNES_MODE_25) ? "ExHiROM" : "Other (BSX or ST)" );
605   logerror( "\tCompany:       %s [%.2s]\n", companies[company], company_id );
606   logerror( "\tROM ID:        %.4s\n\n", rom_id );
607
608   logerror( "HEADER DETAILS\n" );
609   logerror( "==============\n\n" );
610   logerror( "\tName:          %.21s\n", title );
611   logerror( "\tSpeed:         %s [%d]\n", ((ROM[hilo_mode + 0x15] & 0xf0)) ? "FastROM" : "SlowROM", (ROM[hilo_mode + 0x15] & 0xf0) >> 4 );
612   logerror( "\tBank size:     %s [%d]\n", (ROM[hilo_mode + 0x15] & 0xf) ? "HiROM" : "LoROM", ROM[hilo_mode + 0x15] & 0xf );
613
614   logerror( "\tType:          %s", types[state->m_has_addon_chip]);
615   if (has_ram)
616      logerror( ", RAM");
617   if (has_sram)
618      logerror( ", SRAM");
619   logerror( " [%d]\n", ROM[hilo_mode + 0x16] );
620
621   logerror( "\tSize:          %d megabits [%d]\n", 1 << (ROM[hilo_mode + 0x17] - 7), ROM[hilo_mode + 0x17] );
622   logerror( "\tSRAM:          %d kilobits [%d]\n", state->m_cart[0].m_nvram_size * 8, ROM[hilo_mode + 0x18] );
623   logerror( "\tCountry:       %s [%d]\n", countries[ROM[hilo_mode + 0x19]], ROM[hilo_mode + 0x19] );
624   logerror( "\tLicense:       %s [%X]\n", companies[ROM[hilo_mode + 0x1a]], ROM[hilo_mode + 0x1a] );
625   logerror( "\tVersion:       1.%d\n", ROM[hilo_mode + 0x1b] );
626   logerror( "\tInv Checksum:  %X %X\n", ROM[hilo_mode + 0x1d], ROM[hilo_mode + 0x1c] );
627   logerror( "\tChecksum:      %X %X\n", ROM[hilo_mode + 0x1f], ROM[hilo_mode + 0x1e] );
628   logerror( "\tNMI Address:   %2X%2Xh\n", ROM[hilo_mode + 0x3b], ROM[hilo_mode + 0x3a] );
629   logerror( "\tStart Address: %2X%2Xh\n\n", ROM[hilo_mode + 0x3d], ROM[hilo_mode + 0x3c] );
630
631   logerror( "\tMode: %d\n", state->m_cart[0].mode);
632
633   if (!supported)
634      logerror("WARNING: This cart type \"%s\" is not supported yet!\n", types[state->m_has_addon_chip]);
635}
636
637DEVICE_IMAGE_LOAD_MEMBER( snes_state,snes_cart )
638{
639   int supported_type = 1;
640   int has_bsx_slot = 0, st_bios = 0;
641   UINT32 offset, int_header_offs;
642
643   if (image.software_entry() == NULL)
644      m_cart[0].m_rom_size = image.length();
645   else
646      m_cart[0].m_rom_size = image.get_software_region_length("rom");
647
648   // Check for a header (512 bytes), and skip it if found
649   offset = snes_skip_header(image, m_cart[0].m_rom_size);
650   m_cart[0].m_rom_size -= offset;
651
652   // Allocate rom pointer
653   m_cart[0].m_rom = auto_alloc_array_clear(machine(), UINT8, m_cart[0].m_rom_size);
654
655   if (image.software_entry() == NULL)
656   {
657      image.fseek(offset, SEEK_SET);
658      image.fread(m_cart[0].m_rom, m_cart[0].m_rom_size);
659   }
660   else
661      memcpy(m_cart[0].m_rom, image.get_software_region("rom") + offset, m_cart[0].m_rom_size);
662
663   if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", m_cart[0].m_rom_size);
664
665   // Setup the bank map to handle mirroring of ROM up to 8MB of accessible memory
666   rom_map_setup(m_cart[0].m_rom_size);
667
668   // Check if the cart is HiROM or LoROM (and set variables accordingly)
669   int_header_offs = snes_find_hilo_mode(machine(), m_cart[0].m_rom, m_cart[0].m_rom_size, 0);
670
671   // Detect BS-X carts:
672   // 1. Detect BS-X Flash Cart
673   if ((m_cart[0].m_rom[int_header_offs + 0x13] == 0x00 || m_cart[0].m_rom[int_header_offs + 0x13] == 0xff) &&
674         m_cart[0].m_rom[int_header_offs + 0x14] == 0x00)
675   {
676      UINT8 n15 = m_cart[0].m_rom[int_header_offs + 0x15];
677      if (n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc)
678      {
679         if (m_cart[0].m_rom[int_header_offs + 0x1a] == 0x33 || m_cart[0].m_rom[int_header_offs + 0x1a] == 0xff)
680         {
681            // BS-X Flash Cart
682            mame_printf_error("This is a game with BS-X slot: MESS does not support these yet, sorry.\n");
683            m_cart[0].mode = SNES_MODE_BSX;
684         }
685      }
686   }
687
688   // 2. Detect presence of BS-X flash cartridge connector
689   if ((m_cart[0].m_rom[int_header_offs - 14] == 'Z') && (m_cart[0].m_rom[int_header_offs - 11] == 'J'))
690   {
691      UINT8 n13 = m_cart[0].m_rom[int_header_offs - 13];
692      if ((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9'))
693      {
694         if (m_cart[0].m_rom[int_header_offs + 0x1a] == 0x33 ||
695            (m_cart[0].m_rom[int_header_offs - 10] == 0x00 && m_cart[0].m_rom[int_header_offs - 4] == 0x00))
696         {
697            has_bsx_slot = 1;
698         }
699      }
700   }
701
702   // If there is a BS-X connector, detect if it is the Base Cart or a compatible slotted cart
703   if (has_bsx_slot)
704   {
705      mame_printf_error("This is a game with BS-X slot: MESS does not support these yet, sorry.\n");
706      if (!memcmp(m_cart[0].m_rom + int_header_offs, "Satellaview BS-X     ", 21))
707      {
708         //BS-X Base Cart
709         m_cart[0].mode = SNES_MODE_20; //SNES_MODE_BSX;
710      }
711      else
712      {
713         m_cart[0].mode = (int_header_offs == 0x007fc0) ? SNES_MODE_20 : SNES_MODE_21; //SNES_MODE_BSLO : SNES_MODE_BSHI;
714      }
715   }
716
717   /* Then, detect Sufami Turbo carts */
718   if (!memcmp(m_cart[0].m_rom, "BANDAI SFC-ADX", 14))
719   {
720      m_cart[0].mode = SNES_MODE_ST;
721      if (!memcmp(m_cart[0].m_rom + 16, "SFC-ADX BACKUP", 14))
722         st_bios = 1;
723   }
724   if (st_bios)
725      mame_printf_error("This is the Sufami Turbo base cart. MESS does not fully support this game in snes/snespal yet, sorry.\nYou might want to try the snesst driver.\n");
726   else if (m_cart[0].mode == SNES_MODE_ST)
727   {
728      mame_printf_error("This is a Sufami Turbo data cart and cannot be loaded for snes/snespal in MESS.\n");
729      mame_printf_error("Please use snesst driver to load it, instead.\n");
730      return IMAGE_INIT_FAIL;
731   }
732
733   
734   if (SNES_CART_DEBUG) mame_printf_error("mode %d\n", m_cart[0].mode);
735
736   /* Detect special chips */
737   supported_type = snes_find_addon_chip(machine(), m_cart[0].m_rom, int_header_offs);
738
739   /* Find the amount of cart ram */
740   m_cart[0].m_nvram_size = 0;
741   if (image.software_entry() == NULL)
742   {
743      UINT32 nvram_size;
744      if ((m_has_addon_chip != HAS_SUPERFX))
745         nvram_size = m_cart[0].m_rom[int_header_offs + 0x18];
746      else
747         nvram_size = (m_cart[0].m_rom[0x007fbd] & 0x07);
748
749      if (nvram_size > 0)
750      {
751         nvram_size = (1024 << nvram_size);
752         if (nvram_size > m_cart[0].sram_max)
753            nvram_size = m_cart[0].sram_max;
754
755         m_cart[0].m_nvram_size = nvram_size;
756      }
757//      printf("size %x\n", m_cart[0].m_nvram_size);
758   }
759   else
760   {
761      // if we are loading from softlist, take memory length from the xml
762      m_cart[0].m_nvram_size = image.get_software_region("nvram") ? image.get_software_region_length("nvram") : 0;
763
764      if (m_cart[0].m_nvram_size > 0)
765      {
766         if (m_cart[0].m_nvram_size > m_cart[0].sram_max)
767            fatalerror("Found more memory than max allowed (found: %x, max: %x), check xml file!\n", m_cart[0].m_nvram_size, m_cart[0].sram_max);
768      }
769      // TODO: Eventually sram handlers should point to the allocated cart:sram region!
770      // For now, we only use the region as a placeholder to carry size info...
771//      printf("size %x\n", m_cart[0].m_nvram_size);
772   }
773
774   if (m_cart[0].m_nvram_size > 0)
775      m_cart[0].m_nvram = auto_alloc_array_clear(machine(), UINT8, m_cart[0].m_nvram_size);
776
777   /* Log snes_cart information */
778   snes_cart_log_info(machine(), m_cart[0].m_rom, m_cart[0].m_rom_size, supported_type);
779
780   /* Load SRAM */
781   if (m_cart[0].m_nvram_size > 0)
782      snes_load_sram(machine());
783
784   /* All done */
785   return IMAGE_INIT_PASS;
786}
787
788DEVICE_IMAGE_LOAD_MEMBER( snes_state,sufami_cart )
789{
790   int st_bios = 0, slot_id = 0;
791   UINT32 offset;
792
793   if (strcmp(image.device().tag(), ":slot_a") == 0)
794      slot_id = 0;
795
796   if (strcmp(image.device().tag(), ":slot_b") == 0)
797      slot_id = 1;
798
799   if (image.software_entry() == NULL)
800      m_cart[slot_id].m_rom_size = image.length();
801   else
802      m_cart[slot_id].m_rom_size = image.get_software_region_length("rom");
803
804   // Check for a header (512 bytes), and skip it if found
805   offset = snes_skip_header(image, m_cart[slot_id].m_rom_size);
806   m_cart[slot_id].m_rom_size -= offset;
807
808   // Allocate rom pointer
809   m_cart[slot_id].m_rom = auto_alloc_array_clear(machine(), UINT8, m_cart[slot_id].m_rom_size);
810
811   if (image.software_entry() == NULL)
812   {
813      image.fseek(offset, SEEK_SET);
814      image.fread(m_cart[slot_id].m_rom, m_cart[slot_id].m_rom_size);
815   }
816   else
817      memcpy(m_cart[slot_id].m_rom, image.get_software_region("rom") + offset, m_cart[slot_id].m_rom_size);
818
819   if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", m_cart[slot_id].m_rom_size);
820
821   // Setup the bank map to handle mirroring of ROM
822   rom_map_setup(m_cart[slot_id].m_rom_size);
823
824   // Detect Sufami Turbo carts
825   if (!memcmp(m_cart[slot_id].m_rom, "BANDAI SFC-ADX", 14))
826   {
827      m_cart[slot_id].mode = SNES_MODE_ST;
828      if (!memcmp(m_cart[slot_id].m_rom + 16, "SFC-ADX BACKUP", 14))
829         st_bios = 1;
830   }
831   else
832   {
833      mame_printf_error("This is not a Sufami Turbo data pack.\n");
834      mame_printf_error("This image cannot be loaded in snesst (Use snes or snespal drivers, instead).\n");
835      return IMAGE_INIT_FAIL;
836   }
837
838   if (st_bios == 1)
839   {
840      mame_printf_error("This is the Sufami Turbo BIOS and not a Sufami Turbo data pack.\n");
841      mame_printf_error("This image cannot be loaded in snesst.\n");
842      return IMAGE_INIT_FAIL;
843   }
844
845   m_cart[slot_id].m_nvram_size = 0x20000;
846   m_cart[slot_id].m_nvram = auto_alloc_array_clear(machine(), UINT8, m_cart[slot_id].m_nvram_size);
847
848   sufami_load_sram(machine(), image.device().tag());
849
850   m_cart[slot_id].slot_in_use = 1; // acknowledge the cart in this slot
851
852   return IMAGE_INIT_PASS;
853}
854
855MACHINE_CONFIG_FRAGMENT( snes_cartslot )
856   MCFG_CARTSLOT_ADD("cart")
857   MCFG_CARTSLOT_EXTENSION_LIST("sfc,smc,fig,swc,bin")
858   MCFG_CARTSLOT_NOT_MANDATORY
859   MCFG_CARTSLOT_INTERFACE("snes_cart")
860   MCFG_CARTSLOT_LOAD(snes_state,snes_cart)
861
862   MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
863   MCFG_SOFTWARE_LIST_FILTER("cart_list","NTSC")
864MACHINE_CONFIG_END
865
866MACHINE_CONFIG_FRAGMENT( snesp_cartslot )
867   MCFG_CARTSLOT_ADD("cart")
868   MCFG_CARTSLOT_EXTENSION_LIST("sfc,smc,fig,swc,bin")
869   MCFG_CARTSLOT_NOT_MANDATORY
870   MCFG_CARTSLOT_INTERFACE("snes_cart")
871   MCFG_CARTSLOT_LOAD(snes_state,snes_cart)
872
873   MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
874   MCFG_SOFTWARE_LIST_FILTER("cart_list","PAL")
875MACHINE_CONFIG_END
876
877// This (hackily) emulates a SNES unit with a Sufami Turbo Unit cart inserted:
878// hence, the user can mount two data cart in the two slots available on the ST Unit
879MACHINE_CONFIG_FRAGMENT( sufami_cartslot )
880   MCFG_CARTSLOT_ADD("slot_a")
881   MCFG_CARTSLOT_EXTENSION_LIST("st,sfc")
882   MCFG_CARTSLOT_NOT_MANDATORY
883   MCFG_CARTSLOT_INTERFACE("sufami_cart")
884   MCFG_CARTSLOT_LOAD(snes_state,sufami_cart)
885
886   MCFG_CARTSLOT_ADD("slot_b")
887   MCFG_CARTSLOT_EXTENSION_LIST("st,sfc")
888   MCFG_CARTSLOT_NOT_MANDATORY
889   MCFG_CARTSLOT_INTERFACE("sufami_cart")
890   MCFG_CARTSLOT_LOAD(snes_state,sufami_cart)
891
892//  MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
893MACHINE_CONFIG_END
894
895
896DRIVER_INIT_MEMBER(snes_state,snes_mess)
897{
898}
899
900DRIVER_INIT_MEMBER(snes_state,snesst)
901{
902   m_cart[0].slot_in_use = 0;
903   m_cart[1].slot_in_use = 0;
904
905   DRIVER_INIT_CALL(snes_mess);
906}
907
908// add-on chip emulators
909#include "machine/snesobc1.c"
910#include "machine/snescx4.c"
911#include "machine/snesrtc.c"
912#include "machine/snessdd1.c"
913#include "machine/snes7110.c"
trunk/src/mess/machine/snescart.h
r21870r21871
1/*
2    snescart.h
3
4*/
5
6#ifndef _SNESCART_H
7#define _SNESCART_H
8
9void snes_machine_stop(running_machine &machine);
10void sufami_machine_stop(running_machine &machine);
11
12MACHINE_CONFIG_EXTERN( snes_cartslot );
13MACHINE_CONFIG_EXTERN( snesp_cartslot );
14MACHINE_CONFIG_EXTERN( sufami_cartslot );
15
16
17// add-on chips IO
18void srtc_write(running_machine &machine, UINT16 addr, UINT8 data);
19UINT8 srtc_read(address_space &space, UINT16 addr);
20void srtc_init(running_machine &machine);
21extern DECLARE_READ8_HANDLER(obc1_read);
22extern DECLARE_WRITE8_HANDLER(obc1_write);
23void obc1_init(running_machine &machine);
24UINT8 CX4_read(UINT32 addr);
25void CX4_write(running_machine &machine, UINT32 addr, UINT8 data);
26UINT8 sdd1_mmio_read(address_space &space, UINT32 addr);
27void sdd1_mmio_write(address_space &space, UINT32 addr, UINT8 data);
28void sdd1_init(running_machine& machine);
29UINT8 sdd1_read(running_machine& machine, UINT32 addr);
30UINT8 spc7110_mmio_read(address_space &space, UINT32 addr);
31void spc7110_mmio_write(running_machine &machine, UINT32 addr, UINT8 data);
32UINT8 spc7110_bank7_read(address_space &space, UINT32 offset);
33void spc7110_init(running_machine& machine);
34void spc7110rtc_init(running_machine& machine);
35UINT8 spc7110_ram_read(UINT32 offset);
36void spc7110_ram_write(UINT32 offset, UINT8 data);
37
38
39#endif /* _SNESCART_H */
trunk/src/mess/machine/snesrtc.c
r21870r21871
1/***************************************************************************
2
3  snesrtc.c
4
5  File to handle emulation of the SNES "S-RTC" add-on chip.
6
7  Based on C++ implementation by Byuu in BSNES.
8
9  Byuu's code is released under GNU General Public License
10  version 2 as published by the Free Software Foundation.
11  The implementation below is released under the MAME license
12  for use in MAME, MESS and derivatives by permission of the
13  author
14
15***************************************************************************/
16
17enum
18{
19   RTCM_Ready,
20   RTCM_Command,
21   RTCM_Read,
22   RTCM_Write
23};
24
25struct snes_rtc_state
26{
27   UINT8  ram[13];
28   INT32  mode;
29   INT8   index;
30};
31
32static snes_rtc_state rtc_state;
33
34static const UINT8 srtc_months[12] =
35{
36   31, 28, 31,
37   30, 31, 30,
38   31, 31, 30,
39   31, 30, 31
40};
41
42static void srtc_update_time( running_machine &machine )
43{
44   system_time curtime, *systime = &curtime;
45   machine.current_datetime(curtime);
46   rtc_state.ram[0] = systime->local_time.second % 10;
47   rtc_state.ram[1] = systime->local_time.second / 10;
48   rtc_state.ram[2] = systime->local_time.minute % 10;
49   rtc_state.ram[3] = systime->local_time.minute / 10;
50   rtc_state.ram[4] = systime->local_time.hour % 10;
51   rtc_state.ram[5] = systime->local_time.hour / 10;
52   rtc_state.ram[6] = systime->local_time.mday % 10;
53   rtc_state.ram[7] = systime->local_time.mday / 10;
54   rtc_state.ram[8] = systime->local_time.month;
55   rtc_state.ram[9] = (systime->local_time.year - 1000) % 10;
56   rtc_state.ram[10] = ((systime->local_time.year - 1000) / 10) % 10;
57   rtc_state.ram[11] = (systime->local_time.year - 1000) / 100;
58   rtc_state.ram[12] = systime->local_time.weekday % 7;
59}
60
61// Returns day-of-week for specified date
62// e.g. 0 = Sunday, 1 = Monday, ... 6 = Saturday
63// Usage: weekday(2008, 1, 1) returns the weekday of January 1st, 2008
64static UINT8 srtc_weekday( UINT32 year, UINT32 month, UINT32 day )
65{
66   UINT32 y = 1900, m = 1; // Epoch is 1900-01-01
67   UINT32 sum = 0;         // Number of days passed since epoch
68
69   year = MAX(1900, year);
70   month = MAX(1, MIN(12, month));
71   day = MAX(1, MIN(31, day));
72
73   while (y < year)
74   {
75      UINT8 leapyear = 0;
76      if ((y % 4) == 0)
77      {
78         leapyear = 1;
79         if ((y % 100) == 0 && (y % 400) != 0)
80         {
81            leapyear = 0;
82         }
83      }
84      sum += leapyear ? 366 : 365;
85      y++;
86   }
87
88   while (m < month)
89   {
90      UINT32 days = srtc_months[m - 1];
91      if (days == 28)
92      {
93         UINT8 leapyear = 0;
94         if ((y % 4) == 0)
95         {
96            leapyear = 1;
97            if ((y % 100) == 0 && (y % 400) != 0)
98            {
99               leapyear = 0;
100            }
101         }
102         days += leapyear ? 1 : 0;
103      }
104      sum += days;
105      m++;
106   }
107
108   sum += day - 1;
109   return (sum + 1) % 7; // 1900-01-01 was a Monday
110}
111
112UINT8 srtc_read( address_space &space, UINT16 addr )
113{
114   addr &= 0xffff;
115
116   if (addr == 0x2800)
117   {
118      if (rtc_state.mode != RTCM_Read)
119      {
120         return 0x00;
121      }
122
123      if (rtc_state.index < 0)
124      {
125         srtc_update_time(space.machine());
126         rtc_state.index++;
127         return 0x0f;
128      }
129      else if (rtc_state.index > 12)
130      {
131         rtc_state.index = -1;
132         return 0x0f;
133      }
134      else
135      {
136         return rtc_state.ram[rtc_state.index++];
137      }
138   }
139
140   return snes_open_bus_r(space, 0);
141}
142
143void srtc_write( running_machine &machine, UINT16 addr, UINT8 data )
144{
145   addr &= 0xffff;
146
147   if (addr == 0x2801)
148   {
149      data &= 0x0f;   // Only the low four bits are used
150
151      if (data == 0x0d)
152      {
153         rtc_state.mode = RTCM_Read;
154         rtc_state.index = -1;
155         return;
156      }
157
158      if (data == 0x0e)
159      {
160         rtc_state.mode = RTCM_Command;
161         return;
162      }
163
164      if (data == 0x0f)
165      {
166         return; // Unknown behaviour
167      }
168
169      if (rtc_state.mode == RTCM_Write)
170      {
171         if (rtc_state.index >= 0 && rtc_state.index < 12)
172         {
173            rtc_state.ram[rtc_state.index++] = data;
174
175            if (rtc_state.index == 12)
176            {
177               // Day of week is automatically calculated and written
178               UINT32 day   = rtc_state.ram[6] + rtc_state.ram[7] * 10;
179               UINT32 month = rtc_state.ram[8];
180               UINT32 year  = rtc_state.ram[9] + rtc_state.ram[10] * 10 + rtc_state.ram[11] * 100;
181               year += 1000;
182
183               rtc_state.ram[rtc_state.index++] = srtc_weekday(year, month, day);
184            }
185         }
186      }
187      else if (rtc_state.mode == RTCM_Command)
188      {
189         if (data == 0)
190         {
191            rtc_state.mode = RTCM_Write;
192            rtc_state.index = 0;
193         }
194         else if (data == 4)
195         {
196            UINT8 i;
197            rtc_state.mode = RTCM_Ready;
198            rtc_state.index = -1;
199            for(i = 0; i < 13; i++)
200            {
201               rtc_state.ram[i] = 0;
202            }
203         }
204         else
205         {
206            // Unknown behaviour
207            rtc_state.mode = RTCM_Ready;
208         }
209      }
210   }
211}
212
213void srtc_init( running_machine &machine )
214{
215   rtc_state.mode = RTCM_Read;
216   rtc_state.index = -1;
217   srtc_update_time(machine);
218
219   state_save_register_global_array(machine, rtc_state.ram);
220   state_save_register_global(machine, rtc_state.mode);
221   state_save_register_global(machine, rtc_state.index);
222}
trunk/src/mess/machine/snessdd1.c
r21870r21871
1/***************************************************************************
2
3  snessdd1.c
4
5  File to handle emulation of the SNES "S-DD1" add-on chip.
6
7  Based on Andreas Naive Public Domain code.
8
9***************************************************************************/
10
11
12#define SSD1_ADD(addr)\
13mmc[(addr >> 20) & 3] + (addr & 0x0fffff)
14
15class SDD1_IM //Input Manager
16{
17public:
18   SDD1_IM() {}
19
20   UINT32 m_byte_ptr;
21   UINT8 m_bit_count;
22
23   void IM_prepareDecomp(UINT32 in_buf);
24   UINT8 IM_getCodeword(UINT8 *ROM, UINT32 *mmc, const UINT8 code_len);
25};
26
27void SDD1_IM::IM_prepareDecomp(UINT32 in_buf)
28{
29   m_byte_ptr = in_buf;
30   m_bit_count = 4;
31}
32
33UINT8 SDD1_IM::IM_getCodeword(UINT8 *ROM, UINT32 *mmc, const UINT8 code_len)
34{
35   UINT8 codeword = ROM[SSD1_ADD(m_byte_ptr)] << m_bit_count;
36
37   ++m_bit_count;
38
39   if (codeword & 0x80)
40   {
41      codeword |= ROM[SSD1_ADD((m_byte_ptr + 1))] >> (9 - m_bit_count);
42      m_bit_count += code_len;
43   }
44
45   if (m_bit_count & 0x08)
46   {
47      m_byte_ptr++;
48      m_bit_count &= 0x07;
49   }
50
51   return codeword;
52}
53
54class SDD1_GCD //Golomb-Code Decoder
55{
56public:
57   SDD1_GCD(SDD1_IM* associatedIM)
58      : m_IM(associatedIM) { }
59
60   SDD1_IM* m_IM;
61
62   void GCD_getRunCount(UINT8 *ROM, UINT32 *mmc, UINT8 code_num, UINT8* MPScount, UINT8* LPSind);
63};
64
65void SDD1_GCD::GCD_getRunCount(UINT8 *ROM, UINT32 *mmc, UINT8 code_num, UINT8* MPScount, UINT8* LPSind)
66{
67   const UINT8 run_count[] =
68   {
69      0x00, 0x00, 0x01, 0x00, 0x03, 0x01, 0x02, 0x00,
70      0x07, 0x03, 0x05, 0x01, 0x06, 0x02, 0x04, 0x00,
71      0x0f, 0x07, 0x0b, 0x03, 0x0d, 0x05, 0x09, 0x01,
72      0x0e, 0x06, 0x0a, 0x02, 0x0c, 0x04, 0x08, 0x00,
73      0x1f, 0x0f, 0x17, 0x07, 0x1b, 0x0b, 0x13, 0x03,
74      0x1d, 0x0d, 0x15, 0x05, 0x19, 0x09, 0x11, 0x01,
75      0x1e, 0x0e, 0x16, 0x06, 0x1a, 0x0a, 0x12, 0x02,
76      0x1c, 0x0c, 0x14, 0x04, 0x18, 0x08, 0x10, 0x00,
77      0x3f, 0x1f, 0x2f, 0x0f, 0x37, 0x17, 0x27, 0x07,
78      0x3b, 0x1b, 0x2b, 0x0b, 0x33, 0x13, 0x23, 0x03,
79      0x3d, 0x1d, 0x2d, 0x0d, 0x35, 0x15, 0x25, 0x05,
80      0x39, 0x19, 0x29, 0x09, 0x31, 0x11, 0x21, 0x01,
81      0x3e, 0x1e, 0x2e, 0x0e, 0x36, 0x16, 0x26, 0x06,
82      0x3a, 0x1a, 0x2a, 0x0a, 0x32, 0x12, 0x22, 0x02,
83      0x3c, 0x1c, 0x2c, 0x0c, 0x34, 0x14, 0x24, 0x04,
84      0x38, 0x18, 0x28, 0x08, 0x30, 0x10, 0x20, 0x00,
85      0x7f, 0x3f, 0x5f, 0x1f, 0x6f, 0x2f, 0x4f, 0x0f,
86      0x77, 0x37, 0x57, 0x17, 0x67, 0x27, 0x47, 0x07,
87      0x7b, 0x3b, 0x5b, 0x1b, 0x6b, 0x2b, 0x4b, 0x0b,
88      0x73, 0x33, 0x53, 0x13, 0x63, 0x23, 0x43, 0x03,
89      0x7d, 0x3d, 0x5d, 0x1d, 0x6d, 0x2d, 0x4d, 0x0d,
90      0x75, 0x35, 0x55, 0x15, 0x65, 0x25, 0x45, 0x05,
91      0x79, 0x39, 0x59, 0x19, 0x69, 0x29, 0x49, 0x09,
92      0x71, 0x31, 0x51, 0x11, 0x61, 0x21, 0x41, 0x01,
93      0x7e, 0x3e, 0x5e, 0x1e, 0x6e, 0x2e, 0x4e, 0x0e,
94      0x76, 0x36, 0x56, 0x16, 0x66, 0x26, 0x46, 0x06,
95      0x7a, 0x3a, 0x5a, 0x1a, 0x6a, 0x2a, 0x4a, 0x0a,
96      0x72, 0x32, 0x52, 0x12, 0x62, 0x22, 0x42, 0x02,
97      0x7c, 0x3c, 0x5c, 0x1c, 0x6c, 0x2c, 0x4c, 0x0c,
98      0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04,
99      0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
100      0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00,
101   };
102
103   UINT8 codeword = m_IM->IM_getCodeword(ROM, mmc, code_num);
104
105   if (codeword & 0x80)
106   {
107      *LPSind = 1;
108      *MPScount = run_count[codeword >> (code_num ^ 0x07)];
109   }
110   else
111   {
112      *MPScount = (1 << code_num);
113   }
114}
115
116class SDD1_BG // Bits Generator
117{
118public:
119   SDD1_BG(SDD1_GCD* associatedGCD, UINT8 code)
120      : m_code_num(code),
121         m_GCD(associatedGCD) { }
122
123   UINT8 m_code_num;
124   UINT8 m_MPScount;
125   UINT8 m_LPSind;
126   SDD1_GCD* m_GCD;
127
128   void BG_prepareDecomp();
129   UINT8 BG_getBit(UINT8 *ROM, UINT32 *mmc, UINT8* endOfRun);
130} ;
131
132void SDD1_BG::BG_prepareDecomp()
133{
134   m_MPScount = 0;
135   m_LPSind = 0;
136}
137
138UINT8 SDD1_BG::BG_getBit(UINT8 *ROM, UINT32 *mmc, UINT8* endOfRun)
139{
140   UINT8 bit;
141
142   if (!(m_MPScount || m_LPSind))
143   {
144      m_GCD->GCD_getRunCount(ROM, mmc, m_code_num, &(m_MPScount), &(m_LPSind));
145   }
146
147   if (m_MPScount)
148   {
149      bit = 0;
150      m_MPScount--;
151   }
152   else
153   {
154      bit = 1;
155      m_LPSind = 0;
156   }
157
158   if (m_MPScount || m_LPSind)
159   {
160      (*endOfRun) = 0;
161   }
162   else
163   {
164      (*endOfRun) = 1;
165   }
166
167   return bit;
168}
169
170
171struct SDD1_PEM_state
172{
173   UINT8 code_num;
174   UINT8 nextIfMPS;
175   UINT8 nextIfLPS;
176};
177
178static const SDD1_PEM_state PEM_evolution_table[33] =
179{
180   { 0,25,25},
181   { 0, 2, 1},
182   { 0, 3, 1},
183   { 0, 4, 2},
184   { 0, 5, 3},
185   { 1, 6, 4},
186   { 1, 7, 5},
187   { 1, 8, 6},
188   { 1, 9, 7},
189   { 2,10, 8},
190   { 2,11, 9},
191   { 2,12,10},
192   { 2,13,11},
193   { 3,14,12},
194   { 3,15,13},
195   { 3,16,14},
196   { 3,17,15},
197   { 4,18,16},
198   { 4,19,17},
199   { 5,20,18},
200   { 5,21,19},
201   { 6,22,20},
202   { 6,23,21},
203   { 7,24,22},
204   { 7,24,23},
205   { 0,26, 1},
206   { 1,27, 2},
207   { 2,28, 4},
208   { 3,29, 8},
209   { 4,30,12},
210   { 5,31,16},
211   { 6,32,18},
212   { 7,24,22}
213};
214
215struct SDD1_PEM_ContextInfo
216{
217   UINT8 status;
218   UINT8 MPS;
219};
220
221class SDD1_PEM //Probability Estimation Module
222{
223public:
224   SDD1_PEM(
225         SDD1_BG* associatedBG0, SDD1_BG* associatedBG1,
226         SDD1_BG* associatedBG2, SDD1_BG* associatedBG3,
227         SDD1_BG* associatedBG4, SDD1_BG* associatedBG5,
228         SDD1_BG* associatedBG6, SDD1_BG* associatedBG7)
229   {
230      m_BG[0] = associatedBG0;
231      m_BG[1] = associatedBG1;
232      m_BG[2] = associatedBG2;
233      m_BG[3] = associatedBG3;
234      m_BG[4] = associatedBG4;
235      m_BG[5] = associatedBG5;
236      m_BG[6] = associatedBG6;
237      m_BG[7] = associatedBG7;
238   }
239
240   SDD1_PEM_ContextInfo m_contextInfo[32];
241   SDD1_BG* m_BG[8];
242
243   void PEM_prepareDecomp();
244   UINT8 PEM_getBit(UINT8 *ROM, UINT32 *mmc, UINT8 context);
245} ;
246
247void SDD1_PEM::PEM_prepareDecomp()
248{
249   for (int i = 0; i < 32; i++)
250   {
251      m_contextInfo[i].status = 0;
252      m_contextInfo[i].MPS = 0;
253   }
254}
255
256UINT8 SDD1_PEM::PEM_getBit(UINT8 *ROM, UINT32 *mmc, UINT8 context)
257{
258   UINT8 endOfRun;
259   UINT8 bit;
260
261   SDD1_PEM_ContextInfo *pContInfo = &(m_contextInfo)[context];
262   UINT8 currStatus = pContInfo->status;
263   const SDD1_PEM_state* pState = &(PEM_evolution_table[currStatus]);
264   UINT8 currentMPS = pContInfo->MPS;
265
266   bit = m_BG[pState->code_num]->BG_getBit(ROM, mmc, &endOfRun);
267
268   if (endOfRun)
269   {
270      if (bit)
271      {
272         if (!(currStatus & 0xfe))
273         {
274            (pContInfo->MPS) ^= 0x01;
275         }
276         pContInfo->status = pState->nextIfLPS;
277      }
278      else
279      {
280         pContInfo->status = pState->nextIfMPS;
281      }
282   }
283
284   return bit ^ currentMPS;
285}
286
287class SDD1_CM
288{
289public:
290   SDD1_CM(SDD1_PEM* associatedPEM)
291      : m_PEM(associatedPEM) { }
292
293   UINT8 m_bitplanesInfo;
294   UINT8 m_contextBitsInfo;
295   UINT8 m_bit_number;
296   UINT8 m_currBitplane;
297   UINT16 m_prevBitplaneBits[8];
298   SDD1_PEM* m_PEM;
299
300   void CM_prepareDecomp(UINT8 *ROM, UINT32 *mmc, UINT32 first_byte);
301   UINT8 CM_getBit(UINT8 *ROM, UINT32 *mmc);
302} ;
303
304void SDD1_CM::CM_prepareDecomp(UINT8 *ROM, UINT32 *mmc, UINT32 first_byte)
305{
306   INT32 i = 0;
307   m_bitplanesInfo = ROM[SSD1_ADD(first_byte)] & 0xc0;
308   m_contextBitsInfo = ROM[SSD1_ADD(first_byte)] & 0x30;
309   m_bit_number = 0;
310   for (i = 0; i < 8; i++)
311   {
312      m_prevBitplaneBits[i] = 0;
313   }
314   switch (m_bitplanesInfo)
315   {
316      case 0x00:
317         m_currBitplane = 1;
318         break;
319      case 0x40:
320         m_currBitplane = 7;
321         break;
322      case 0x80:
323         m_currBitplane = 3;
324         break;
325   }
326}
327
328UINT8 SDD1_CM::CM_getBit(UINT8 *ROM, UINT32 *mmc)
329{
330   UINT8 currContext;
331   UINT16 *context_bits;
332   UINT8 bit = 0;
333
334   switch (m_bitplanesInfo)
335   {
336      case 0x00:
337         m_currBitplane ^= 0x01;
338         break;
339      case 0x40:
340         m_currBitplane ^= 0x01;
341         if (!(m_bit_number & 0x7f))
342            m_currBitplane = ((m_currBitplane + 2) & 0x07);
343         break;
344      case 0x80:
345         m_currBitplane ^= 0x01;
346         if (!(m_bit_number & 0x7f))
347            m_currBitplane ^= 0x02;
348         break;
349      case 0xc0:
350         m_currBitplane = m_bit_number & 0x07;
351         break;
352   }
353
354   context_bits = &(m_prevBitplaneBits)[m_currBitplane];
355
356   currContext = (m_currBitplane & 0x01) << 4;
357   switch (m_contextBitsInfo)
358   {
359      case 0x00:
360         currContext |= ((*context_bits & 0x01c0) >> 5) | (*context_bits & 0x0001);
361         break;
362      case 0x10:
363         currContext |= ((*context_bits & 0x0180) >> 5) | (*context_bits & 0x0001);
364         break;
365      case 0x20:
366         currContext |= ((*context_bits & 0x00c0) >> 5) | (*context_bits & 0x0001);
367         break;
368      case 0x30:
369         currContext |= ((*context_bits & 0x0180) >> 5) | (*context_bits & 0x0003);
370         break;
371   }
372
373   bit = m_PEM->PEM_getBit(ROM, mmc, currContext);
374
375   *context_bits <<= 1;
376   *context_bits |= bit;
377
378   m_bit_number++;
379
380   return bit;
381}
382
383class SDD1_OL
384{
385public:
386   SDD1_OL(SDD1_CM* associatedCM)
387      : m_CM(associatedCM) { }
388
389   UINT8 m_bitplanesInfo;
390   UINT16 m_length;
391   UINT8* m_buffer;
392   SDD1_CM* m_CM;
393
394   void OL_prepareDecomp(UINT8 *ROM, UINT32 *mmc, UINT32 first_byte, UINT16 out_len, UINT8 *out_buf);
395   void OL_launch(UINT8 *ROM, UINT32 *mmc);
396} ;
397
398void SDD1_OL::OL_prepareDecomp(UINT8 *ROM, UINT32 *mmc, UINT32 first_byte, UINT16 out_len, UINT8 *out_buf)
399{
400   m_bitplanesInfo = ROM[SSD1_ADD(first_byte)] & 0xc0;
401   m_length = out_len;
402   m_buffer = out_buf;
403}
404
405void SDD1_OL::OL_launch(UINT8 *ROM, UINT32 *mmc)
406{
407   UINT8 i;
408   UINT8 register1 = 0, register2 = 0;
409
410   switch (m_bitplanesInfo)
411   {
412      case 0x00:
413      case 0x40:
414      case 0x80:
415         i = 1;
416         do
417         {   // if length == 0, we output 2^16 bytes
418            if (!i)
419            {
420               *(m_buffer++) = register2;
421               i = ~i;
422            }
423            else
424            {
425               for (register1 = register2 = 0, i = 0x80; i; i >>= 1)
426               {
427                  if (m_CM->CM_getBit(ROM, mmc))
428                     register1 |= i;
429
430                  if (m_CM->CM_getBit(ROM, mmc))
431                     register2 |= i;
432               }
433               *(m_buffer++) = register1;
434            }
435         } while (--(m_length));
436         break;
437      case 0xc0:
438         do
439         {
440            for (register1 = 0, i = 0x01; i; i <<= 1)
441            {
442               if (m_CM->CM_getBit(ROM, mmc))
443               {
444                  register1 |= i;
445               }
446            }
447            *(m_buffer++) = register1;
448         } while (--(m_length));
449         break;
450   }
451}
452
453class SDD1emu
454{
455public:
456   SDD1emu(running_machine &machine);
457
458   running_machine &machine() const { return m_machine; }
459
460   SDD1_IM* m_IM;
461   SDD1_GCD* m_GCD;
462   SDD1_BG* m_BG0;   SDD1_BG* m_BG1;   SDD1_BG* m_BG2;   SDD1_BG* m_BG3;
463   SDD1_BG* m_BG4;   SDD1_BG* m_BG5;   SDD1_BG* m_BG6;   SDD1_BG* m_BG7;
464   SDD1_PEM* m_PEM;
465   SDD1_CM* m_CM;
466   SDD1_OL* m_OL;
467
468   void SDD1emu_decompress(UINT8 *ROM, UINT32 *mmc, UINT32 in_buf, UINT16 out_len, UINT8 *out_buf);
469
470private:
471   running_machine& m_machine;
472};
473
474SDD1emu::SDD1emu(running_machine &machine)
475   : m_machine(machine)
476{
477   m_IM = auto_alloc(machine, SDD1_IM());
478   m_GCD = auto_alloc(machine, SDD1_GCD(m_IM));
479   m_BG0 = auto_alloc(machine, SDD1_BG(m_GCD, 0));
480   m_BG1 = auto_alloc(machine, SDD1_BG(m_GCD, 1));
481   m_BG2 = auto_alloc(machine, SDD1_BG(m_GCD, 2));
482   m_BG3 = auto_alloc(machine, SDD1_BG(m_GCD, 3));
483   m_BG4 = auto_alloc(machine, SDD1_BG(m_GCD, 4));
484   m_BG5 = auto_alloc(machine, SDD1_BG(m_GCD, 5));
485   m_BG6 = auto_alloc(machine, SDD1_BG(m_GCD, 6));
486   m_BG7 = auto_alloc(machine, SDD1_BG(m_GCD, 7));
487   m_PEM = auto_alloc(machine, SDD1_PEM(m_BG0, m_BG1, m_BG2, m_BG3,
488                                 m_BG4, m_BG5, m_BG6, m_BG7));
489   m_CM = auto_alloc(machine, SDD1_CM(m_PEM));
490   m_OL = auto_alloc(machine, SDD1_OL(m_CM));
491}
492
493void SDD1emu::SDD1emu_decompress(UINT8 *ROM, UINT32 *mmc, UINT32 in_buf, UINT16 out_len, UINT8 *out_buf)
494{
495   m_IM->IM_prepareDecomp(in_buf);
496   m_BG0->BG_prepareDecomp();
497   m_BG1->BG_prepareDecomp();
498   m_BG2->BG_prepareDecomp();
499   m_BG3->BG_prepareDecomp();
500   m_BG4->BG_prepareDecomp();
501   m_BG5->BG_prepareDecomp();
502   m_BG6->BG_prepareDecomp();
503   m_BG7->BG_prepareDecomp();
504   m_PEM->PEM_prepareDecomp();
505   m_CM->CM_prepareDecomp(ROM, mmc, in_buf);
506   m_OL->OL_prepareDecomp(ROM, mmc, in_buf, out_len, out_buf);
507
508   m_OL->OL_launch(ROM, mmc);
509}
510
511struct snes_sdd1_t
512{
513   UINT8 sdd1_enable;  // channel bit-mask
514   UINT8 xfer_enable;  // channel bit-mask
515   UINT32 mmc[4];      // memory map controller ROM indices
516
517   struct
518   {
519      UINT32 addr;    // $43x2-$43x4 -- DMA transfer address
520      UINT16 size;    // $43x5-$43x6 -- DMA transfer size
521   } dma[8];
522
523   SDD1emu* sdd1emu;
524   struct
525   {
526      UINT8 *data;    // pointer to decompressed S-DD1 data (65536 bytes)
527      UINT16 offset;  // read index into S-DD1 decompression buffer
528      UINT32 size;    // length of data buffer; reads decrement counter, set ready to false at 0
529      UINT8 ready;    // 1 when data[] is valid; 0 to invoke sdd1emu.decompress()
530   } buffer;
531} ;
532
533static snes_sdd1_t snes_sdd1;
534
535void sdd1_init(running_machine& machine)
536{
537   snes_sdd1.sdd1_enable = 0x00;
538   snes_sdd1.xfer_enable = 0x00;
539
540   snes_sdd1.mmc[0] = 0 << 20;
541   snes_sdd1.mmc[1] = 1 << 20;
542   snes_sdd1.mmc[2] = 2 << 20;
543   snes_sdd1.mmc[3] = 3 << 20;
544
545   for (int i = 0; i < 8; i++)
546   {
547      snes_sdd1.dma[i].addr = 0;
548      snes_sdd1.dma[i].size = 0;
549   }
550
551   snes_sdd1.sdd1emu = auto_alloc(machine, SDD1emu(machine));
552
553   snes_sdd1.buffer.data = (UINT8*)auto_alloc_array(machine, UINT8, 0x10000);
554   snes_sdd1.buffer.ready = 0;
555}
556
557UINT8 sdd1_mmio_read(address_space &space, UINT32 addr)
558{
559   addr &= 0xffff;
560
561   switch(addr)
562   {
563      case 0x4804:
564         return (snes_sdd1.mmc[0] >> 20) & 7;
565      case 0x4805:
566         return (snes_sdd1.mmc[1] >> 20) & 7;
567      case 0x4806:
568         return (snes_sdd1.mmc[2] >> 20) & 7;
569      case 0x4807:
570         return (snes_sdd1.mmc[3] >> 20) & 7;
571   }
572
573   return snes_open_bus_r(space, 0);
574}
575
576void sdd1_mmio_write(address_space &space, UINT32 addr, UINT8 data)
577{
578   addr &= 0xffff;
579
580   if ((addr & 0x4380) == 0x4300)
581   {
582      UINT8 channel = (addr >> 4) & 7;
583      switch(addr & 15)
584      {
585         case 2:
586            snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0xffff00) + (data <<  0);
587            break;
588         case 3:
589            snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0xff00ff) + (data <<  8);
590            break;
591         case 4:
592            snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0x00ffff) + (data << 16);
593            break;
594
595         case 5:
596            snes_sdd1.dma[channel].size = (snes_sdd1.dma[channel].size &   0xff00) + (data <<  0);
597            break;
598         case 6:
599            snes_sdd1.dma[channel].size = (snes_sdd1.dma[channel].size &   0x00ff) + (data <<  8);
600            break;
601      }
602      return;
603   }
604
605   switch(addr)
606   {
607      case 0x4800:
608         snes_sdd1.sdd1_enable = data;
609         break;
610      case 0x4801:
611         snes_sdd1.xfer_enable = data;
612         break;
613
614      case 0x4804:
615         snes_sdd1.mmc[0] = (data & 7) << 20;
616         break;
617      case 0x4805:
618         snes_sdd1.mmc[1] = (data & 7) << 20;
619         break;
620      case 0x4806:
621         snes_sdd1.mmc[2] = (data & 7) << 20;
622         break;
623      case 0x4807:
624         snes_sdd1.mmc[3] = (data & 7) << 20;
625         break;
626   }
627}
628
629UINT8 sdd1_read(running_machine& machine, UINT32 addr)
630{
631   snes_state *state = machine.driver_data<snes_state>();
632   UINT8 *ROM = state->m_cart[0].m_rom;
633
634   if (snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable)
635   {
636      // at least one channel has S-DD1 decompression enabled...
637      for (int i = 0; i < 8; i++)
638      {
639         if (snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable & (1 << i))
640         {
641            // S-DD1 always uses fixed transfer mode, so address will not change during transfer
642            if ((addr + 0xc00000) == snes_sdd1.dma[i].addr)
643            {
644               UINT8 data;
645               if (!snes_sdd1.buffer.ready)
646               {
647                  UINT8 temp;
648                  // first byte read for channel performs full decompression.
649                  // this really should stream byte-by-byte, but it's not necessary since the size is known
650                  snes_sdd1.buffer.offset = 0;
651                  snes_sdd1.buffer.size = snes_sdd1.dma[i].size ? snes_sdd1.dma[i].size : 65536;
652
653                  // sdd1emu calls this function; it needs to access uncompressed data;
654                  // so temporarily disable decompression mode for decompress() call.
655                  temp = snes_sdd1.sdd1_enable;
656                  snes_sdd1.sdd1_enable = 0;
657                  snes_sdd1.sdd1emu->SDD1emu_decompress(ROM, snes_sdd1.mmc, addr, snes_sdd1.buffer.size, snes_sdd1.buffer.data);
658                  snes_sdd1.sdd1_enable = temp;
659
660                  snes_sdd1.buffer.ready = 1;
661               }
662
663               // fetch a decompressed byte; once buffer is depleted, disable channel and invalidate buffer
664               data = snes_sdd1.buffer.data[(UINT16)snes_sdd1.buffer.offset++];
665               if (snes_sdd1.buffer.offset >= snes_sdd1.buffer.size)
666               {
667                  snes_sdd1.buffer.ready = 0;
668                  snes_sdd1.xfer_enable &= ~(1 << i);
669               }
670
671               return data;
672            } // address matched
673         } // channel enabled
674      } // channel loop
675   } // S-DD1 decompressor enabled
676
677   return ROM[snes_sdd1.mmc[(addr >> 20) & 3] + (addr & 0x0fffff)];
678}
trunk/src/mess/machine/snesobc1.c
r21870r21871
1/***************************************************************************
2
3  snesobc1.c
4
5  File to handle emulation of the SNES "OBC-1" add-on chip.
6
7  Original C++ code by byuu.
8  Byuu's code is released under GNU General Public License
9  version 2 as published by the Free Software Foundation.
10  The implementation below is released under the MAME license
11  for use in MAME, MESS and derivatives by permission of the author.
12
13***************************************************************************/
14
15struct snes_obc1_state
16{
17   int address;
18   int offset;
19   int shift;
20   UINT8 ram[0x2000];
21};
22
23static snes_obc1_state obc1_state;
24
25
26READ8_HANDLER( obc1_read )
27{
28   UINT16 address = offset & 0x1fff;
29   UINT8 value;
30
31   switch (address)
32   {
33      case 0x1ff0:
34         value = obc1_state.ram[obc1_state.offset + (obc1_state.address << 2) + 0];
35         break;
36
37      case 0x1ff1:
38         value = obc1_state.ram[obc1_state.offset + (obc1_state.address << 2) + 1];
39         break;
40
41      case 0x1ff2:
42         value = obc1_state.ram[obc1_state.offset + (obc1_state.address << 2) + 2];
43         break;
44
45      case 0x1ff3:
46         value = obc1_state.ram[obc1_state.offset + (obc1_state.address << 2) + 3];
47         break;
48
49      case 0x1ff4:
50         value = obc1_state.ram[obc1_state.offset + (obc1_state.address >> 2) + 0x200];
51         break;
52
53      default:
54         value = obc1_state.ram[address];
55         break;
56   }
57
58   return value;
59}
60
61
62WRITE8_HANDLER( obc1_write )
63{
64   UINT16 address = offset & 0x1fff;
65   UINT8 temp;
66
67   switch(address)
68   {
69      case 0x1ff0:
70         obc1_state.ram[obc1_state.offset + (obc1_state.address << 2) + 0] = data;
71         break;
72
73      case 0x1ff1:
74         obc1_state.ram[obc1_state.offset + (obc1_state.address << 2) + 1] = data;
75         break;
76
77      case 0x1ff2:
78         obc1_state.ram[obc1_state.offset + (obc1_state.address << 2) + 2] = data;
79         break;
80
81      case 0x1ff3:
82         obc1_state.ram[obc1_state.offset + (obc1_state.address << 2) + 3] = data;
83         break;
84
85      case 0x1ff4:
86         temp = obc1_state.ram[obc1_state.offset + (obc1_state.address >> 2) + 0x200];
87         temp = (temp & ~(3 << obc1_state.shift)) | ((data & 0x03) << obc1_state.shift);
88         obc1_state.ram[obc1_state.offset + (obc1_state.address >> 2) + 0x200] = temp;
89         break;
90
91      case 0x1ff5:
92         obc1_state.offset = (data & 0x01) ? 0x1800 : 0x1c00;
93         obc1_state.ram[address & 0x1fff] = data;
94         break;
95
96      case 0x1ff6:
97         obc1_state.address = data & 0x7f;
98         obc1_state.shift = (data & 0x03) << 1;
99         obc1_state.ram[address & 0x1fff] = data;
100         break;
101
102      default:
103         obc1_state.ram[address & 0x1fff] = data;
104         break;
105   }
106}
107
108void obc1_init( running_machine &machine )
109{
110   memset(obc1_state.ram, 0x00, sizeof(obc1_state.ram));
111   obc1_state.offset  = (obc1_state.ram[0x1ff5] & 0x01) ? 0x1800 : 0x1c00;
112   obc1_state.address = (obc1_state.ram[0x1ff6] & 0x7f);
113   obc1_state.shift   = (obc1_state.ram[0x1ff6] & 0x03) << 1;
114
115   state_save_register_global(machine, obc1_state.offset);
116   state_save_register_global(machine, obc1_state.address);
117   state_save_register_global(machine, obc1_state.shift);
118   state_save_register_global_array(machine, obc1_state.ram);
119}
trunk/src/mess/machine/snes7110.c
r21870r21871
1/***************************************************************************
2
3  snes7110.c
4
5  File to handle emulation of the SNES "SPC7110" add-on chip.
6
7  Based on C++ implementation by Byuu in BSNES.
8
9  Byuu's code is released under GNU General Public License
10  version 2 as published by the Free Software Foundation.
11  The implementation below is released under the MAME license
12  for use in MAME, MESS and derivatives by permission of the
13  author
14
15***************************************************************************/
16
17
18#define SPC7110_DECOMP_BUFFER_SIZE 64
19
20static const UINT8 spc7110_evolution_table[53][4] =
21{
22   { 0x5a,  1,  1, 1 },
23   { 0x25,  6,  2, 0 },
24   { 0x11,  8,  3, 0 },
25   { 0x08, 10,  4, 0 },
26   { 0x03, 12,  5, 0 },
27   { 0x01, 15,  5, 0 },
28
29   { 0x5a,  7,  7, 1 },
30   { 0x3f, 19,  8, 0 },
31   { 0x2c, 21,  9, 0 },
32   { 0x20, 22, 10, 0 },
33   { 0x17, 23, 11, 0 },
34   { 0x11, 25, 12, 0 },
35   { 0x0c, 26, 13, 0 },
36   { 0x09, 28, 14, 0 },
37   { 0x07, 29, 15, 0 },
38   { 0x05, 31, 16, 0 },
39   { 0x04, 32, 17, 0 },
40   { 0x03, 34, 18, 0 },
41   { 0x02, 35,  5, 0 },
42
43   { 0x5a, 20, 20, 1 },
44   { 0x48, 39, 21, 0 },
45   { 0x3a, 40, 22, 0 },
46   { 0x2e, 42, 23, 0 },
47   { 0x26, 44, 24, 0 },
48   { 0x1f, 45, 25, 0 },
49   { 0x19, 46, 26, 0 },
50   { 0x15, 25, 27, 0 },
51   { 0x11, 26, 28, 0 },
52   { 0x0e, 26, 29, 0 },
53   { 0x0b, 27, 30, 0 },
54   { 0x09, 28, 31, 0 },
55   { 0x08, 29, 32, 0 },
56   { 0x07, 30, 33, 0 },
57   { 0x05, 31, 34, 0 },
58   { 0x04, 33, 35, 0 },
59   { 0x04, 33, 36, 0 },
60   { 0x03, 34, 37, 0 },
61   { 0x02, 35, 38, 0 },
62   { 0x02, 36,  5, 0 },
63
64   { 0x58, 39, 40, 1 },
65   { 0x4d, 47, 41, 0 },
66   { 0x43, 48, 42, 0 },
67   { 0x3b, 49, 43, 0 },
68   { 0x34, 50, 44, 0 },
69   { 0x2e, 51, 45, 0 },
70   { 0x29, 44, 46, 0 },
71   { 0x25, 45, 24, 0 },
72
73   { 0x56, 47, 48, 1 },
74   { 0x4f, 47, 49, 0 },
75   { 0x47, 48, 50, 0 },
76   { 0x41, 49, 51, 0 },
77   { 0x3c, 50, 52, 0 },
78   { 0x37, 51, 43, 0 },
79};
80
81static const UINT8 spc7110_mode2_context_table[32][2] =
82{
83   {  1,  2 },
84
85   {  3,  8 },
86   { 13, 14 },
87
88   { 15, 16 },
89   { 17, 18 },
90   { 19, 20 },
91   { 21, 22 },
92   { 23, 24 },
93   { 25, 26 },
94   { 25, 26 },
95   { 25, 26 },
96   { 25, 26 },
97   { 25, 26 },
98   { 27, 28 },
99   { 29, 30 },
100
101   { 31, 31 },
102   { 31, 31 },
103   { 31, 31 },
104   { 31, 31 },
105   { 31, 31 },
106   { 31, 31 },
107   { 31, 31 },
108   { 31, 31 },
109   { 31, 31 },
110   { 31, 31 },
111   { 31, 31 },
112   { 31, 31 },
113   { 31, 31 },
114   { 31, 31 },
115   { 31, 31 },
116   { 31, 31 },
117
118   { 31, 31 },
119};
120
121class SPC7110Decomp
122{
123public:
124   SPC7110Decomp(running_machine &machine, UINT32 size);
125
126   running_machine &machine() const { return m_machine; }
127
128   void init(running_machine &machine, UINT8 *ROM, UINT32 mode, UINT32 offset, UINT32 index);
129   void reset();
130
131   UINT8 read(UINT8 *ROM);
132   void write(UINT8 data);
133   void mode0(UINT8 init, UINT8 *ROM);
134   void mode1(UINT8 init, UINT8 *ROM);
135   void mode2(UINT8 init, UINT8 *ROM);
136
137   UINT8 dataread(UINT8 *ROM);
138   UINT8 probability(UINT32 n);
139   UINT8 next_lps(UINT32 n);
140   UINT8 next_mps(UINT32 n);
141   UINT8 toggle_invert(UINT32 n);
142   UINT32 morton_2x8(UINT32 data);
143   UINT32 morton_4x8(UINT32 data);
144
145   UINT32 m_decomp_mode;
146   UINT32 m_decomp_offset;
147
148   UINT8 *m_decomp_buffer;
149   UINT32 m_decomp_buffer_rdoffset;
150   UINT32 m_decomp_buffer_wroffset;
151   UINT32 m_decomp_buffer_length;
152
153   struct ContextState
154   {
155      UINT8 index;
156      UINT8 invert;
157   } m_context[32];
158
159   UINT32 m_morton16[2][256];
160   UINT32 m_morton32[4][256];
161
162
163private:
164   running_machine& m_machine;
165   UINT32 m_rom_size;
166};
167
168SPC7110Decomp::SPC7110Decomp(running_machine &machine, UINT32 size)
169      :  m_machine(machine),
170      m_rom_size(size)
171{
172   m_decomp_buffer = (UINT8*)auto_alloc_array(machine, UINT8, SPC7110_DECOMP_BUFFER_SIZE);
173   reset();
174
175   for (int i = 0; i < 256; i++)
176   {
177      #define map(x, y) (((i >> x) & 1) << y)
178      //2x8-bit
179      m_morton16[1][i] = map(7, 15) + map(6,  7) + map(5, 14) + map(4,  6)
180                     + map(3, 13) + map(2,  5) + map(1, 12) + map(0,  4);
181      m_morton16[0][i] = map(7, 11) + map(6,  3) + map(5, 10) + map(4,  2)
182                     + map(3,  9) + map(2,  1) + map(1,  8) + map(0,  0);
183      //4x8-bit
184      m_morton32[3][i] = map(7, 31) + map(6, 23) + map(5, 15) + map(4,  7)
185                     + map(3, 30) + map(2, 22) + map(1, 14) + map(0,  6);
186      m_morton32[2][i] = map(7, 29) + map(6, 21) + map(5, 13) + map(4,  5)
187                     + map(3, 28) + map(2, 20) + map(1, 12) + map(0,  4);
188      m_morton32[1][i] = map(7, 27) + map(6, 19) + map(5, 11) + map(4,  3)
189                     + map(3, 26) + map(2, 18) + map(1, 10) + map(0,  2);
190      m_morton32[0][i] = map(7, 25) + map(6, 17) + map(5,  9) + map(4,  1)
191                     + map(3, 24) + map(2, 16) + map(1,  8) + map(0,  0);
192      #undef map
193   }
194}
195
196void SPC7110Decomp::reset()
197{
198   //mode 3 is invalid; this is treated as a special case to always return 0x00
199   //set to mode 3 so that reading decomp port before starting first decomp will return 0x00
200   m_decomp_mode = 3;
201
202   m_decomp_buffer_rdoffset = 0;
203   m_decomp_buffer_wroffset = 0;
204   m_decomp_buffer_length   = 0;
205}
206
207void SPC7110Decomp::init(running_machine &machine, UINT8 *ROM, UINT32 mode, UINT32 offset, UINT32 index)
208{
209   m_decomp_mode = mode;
210   m_decomp_offset = offset;
211
212   m_decomp_buffer_rdoffset = 0;
213   m_decomp_buffer_wroffset = 0;
214   m_decomp_buffer_length   = 0;
215
216   //reset context states
217   for (int i = 0; i < 32; i++)
218   {
219      m_context[i].index  = 0;
220      m_context[i].invert = 0;
221   }
222
223   switch (m_decomp_mode)
224   {
225      case 0: mode0(1, ROM); break;
226      case 1: mode1(1, ROM); break;
227      case 2: mode2(1, ROM); break;
228   }
229
230   //decompress up to requested output data index
231   while (index--)
232   {
233      read(ROM);
234   }
235}
236
237UINT8 SPC7110Decomp::read(UINT8 *ROM)
238{
239   UINT8 data;
240
241   if (m_decomp_buffer_length == 0)
242   {
243      //decompress at least (SPC7110_DECOMP_BUFFER_SIZE / 2) bytes to the buffer
244      switch (m_decomp_mode)
245      {
246         case 0:
247            mode0(0, ROM);
248            break;
249
250         case 1:
251            mode1(0, ROM);
252            break;
253
254         case 2:
255            mode2(0, ROM);
256            break;
257
258         default:
259            return 0x00;
260      }
261   }
262
263   data = m_decomp_buffer[m_decomp_buffer_rdoffset++];
264   m_decomp_buffer_rdoffset &= SPC7110_DECOMP_BUFFER_SIZE - 1;
265   m_decomp_buffer_length--;
266   return data;
267}
268
269void SPC7110Decomp::write(UINT8 data)
270{
271   m_decomp_buffer[m_decomp_buffer_wroffset++] = data;
272   m_decomp_buffer_wroffset &= SPC7110_DECOMP_BUFFER_SIZE - 1;
273   m_decomp_buffer_length++;
274}
275
276UINT8 SPC7110Decomp::dataread(UINT8 *ROM)
277{
278   UINT32 size = m_rom_size - 0x100000;
279   while (m_decomp_offset >= size)
280   {
281      m_decomp_offset -= size;
282   }
283   return ROM[0x100000 + m_decomp_offset++];
284}
285
286void SPC7110Decomp::mode0(UINT8 init, UINT8 *ROM)
287{
288   static UINT8 val, in, span;
289   static INT32 out, inverts, lps, in_count;
290
291   if (init == 1)
292   {
293      out = inverts = lps = 0;
294      span = 0xff;
295      val = dataread(ROM);
296      in = dataread(ROM);
297      in_count = 8;
298      return;
299   }
300
301   while (m_decomp_buffer_length < (SPC7110_DECOMP_BUFFER_SIZE >> 1))
302   {
303      for (int bit = 0; bit < 8; bit++)
304      {
305         //get context
306         UINT8 mask = (1 << (bit & 3)) - 1;
307         UINT8 con = mask + ((inverts & mask) ^ (lps & mask));
308         UINT32 prob, mps, flag_lps;
309         UINT32 shift = 0;
310         if (bit > 3)
311         {
312            con += 15;
313         }
314
315         //get prob and mps
316         prob = probability(con);
317         mps = (((out >> 15) & 1) ^ m_context[con].invert);
318
319         //get bit
320         if (val <= span - prob) //mps
321         {
322            span = span - prob;
323            out = (out << 1) + mps;
324            flag_lps = 0;
325         }
326         else //lps
327         {
328            val = val - (span - (prob - 1));
329            span = prob - 1;
330            out = (out << 1) + 1 - mps;
331            flag_lps = 1;
332         }
333
334         //renormalize
335         while (span < 0x7f)
336         {
337            shift++;
338
339            span = (span << 1) + 1;
340            val = (val << 1) + (in >> 7);
341
342            in <<= 1;
343            if (--in_count == 0)
344            {
345               in = dataread(ROM);
346               in_count = 8;
347            }
348         }
349
350         //update processing info
351         lps = (lps << 1) + flag_lps;
352         inverts = (inverts << 1) + m_context[con].invert;
353
354         //update context state
355         if (flag_lps & toggle_invert(con))
356         {
357            m_context[con].invert ^= 1;
358         }
359         if (flag_lps)
360         {
361            m_context[con].index = next_lps(con);
362         }
363         else if (shift)
364         {
365            m_context[con].index = next_mps(con);
366         }
367      }
368
369      //save byte
370      write(out);
371   }
372}
373
374void SPC7110Decomp::mode1(UINT8 init, UINT8 *ROM)
375{
376   static INT32 pixelorder[4], realorder[4];
377   static UINT8 in, val, span;
378   static INT32 out, inverts, lps, in_count;
379
380   if (init == 1)
381   {
382      for (int i = 0; i < 4; i++)
383      {
384         pixelorder[i] = i;
385      }
386      out = inverts = lps = 0;
387      span = 0xff;
388      val = dataread(ROM);
389      in = dataread(ROM);
390      in_count = 8;
391      return;
392   }
393
394   while (m_decomp_buffer_length < (SPC7110_DECOMP_BUFFER_SIZE >> 1))
395   {
396      UINT16 data;
397      for (int pixel = 0; pixel < 8; pixel++)
398      {
399         //get first symbol context
400         UINT32 a = ((out >> (1 * 2)) & 3);
401         UINT32 b = ((out >> (7 * 2)) & 3);
402         UINT32 c = ((out >> (8 * 2)) & 3);
403         UINT32 con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
404
405         //update pixel order
406         UINT32 m, n;
407         for (m = 0; m < 4; m++)
408         {
409            if (pixelorder[m] == a)
410            {
411               break;
412            }
413         }
414         for (n = m; n > 0; n--)
415         {
416            pixelorder[n] = pixelorder[n - 1];
417         }
418         pixelorder[0] = a;
419
420         //calculate the real pixel order
421         for (m = 0; m < 4; m++)
422         {
423            realorder[m] = pixelorder[m];
424         }
425
426         //rotate reference pixel c value to top
427         for (m = 0; m < 4; m++)
428         {
429            if (realorder[m] == c)
430            {
431               break;
432            }
433         }
434         for (n = m; n > 0; n--)
435         {
436            realorder[n] = realorder[n - 1];
437         }
438         realorder[0] = c;
439
440         //rotate reference pixel b value to top
441         for (m = 0; m < 4; m++)
442         {
443            if (realorder[m] == b)
444            {
445               break;
446            }
447         }
448         for (n = m; n > 0; n--)
449         {
450            realorder[n] = realorder[n - 1];
451         }
452         realorder[0] = b;
453
454         //rotate reference pixel a value to top
455         for (m = 0; m < 4; m++)
456         {
457            if (realorder[m] == a)
458            {
459               break;
460            }
461         }
462         for (n = m; n > 0; n--)
463         {
464            realorder[n] = realorder[n - 1];
465         }
466         realorder[0] = a;
467
468         //get 2 symbols
469         for (int bit = 0; bit < 2; bit++)
470         {
471            //get prob
472            UINT32 prob = probability(con);
473            UINT32 shift = 0;
474
475            //get symbol
476            UINT32 flag_lps;
477            if (val <= span - prob) //mps
478            {
479               span = span - prob;
480               flag_lps = 0;
481            }
482            else //lps
483            {
484               val = val - (span - (prob - 1));
485               span = prob - 1;
486               flag_lps = 1;
487            }
488
489            //renormalize
490            while (span < 0x7f)
491            {
492               shift++;
493
494               span = (span << 1) + 1;
495               val = (val << 1) + (in >> 7);
496
497               in <<= 1;
498               if (--in_count == 0)
499               {
500                  in = dataread(ROM);
501                  in_count = 8;
502               }
503            }
504
505            //update processing info
506            lps = (lps << 1) + flag_lps;
507            inverts = (inverts << 1) + m_context[con].invert;
508
509            //update context state
510            if (flag_lps & toggle_invert(con))
511            {
512               m_context[con].invert ^= 1;
513            }
514            if (flag_lps)
515            {
516               m_context[con].index = next_lps(con);
517            }
518            else if (shift)
519            {
520               m_context[con].index = next_mps(con);
521            }
522
523            //get next context
524            con = 5 + (con << 1) + ((lps ^ inverts) & 1);
525         }
526
527         //get pixel
528         b = realorder[(lps ^ inverts) & 3];
529         out = (out << 2) + b;
530      }
531
532      //turn pixel data into bitplanes
533      data = morton_2x8(out);
534      write(data >> 8);
535      write(data >> 0);
536   }
537}
538
539void SPC7110Decomp::mode2(UINT8 init, UINT8 *ROM)
540{
541   static INT32 pixelorder[16], realorder[16];
542   static UINT8 bitplanebuffer[16], buffer_index;
543   static UINT8 in, val, span;
544   static INT32 out0, out1, inverts, lps, in_count;
545
546   if (init == 1)
547   {
548      for (int i = 0; i < 16; i++)
549      {
550         pixelorder[i] = i;
551      }
552      buffer_index = 0;
553      out0 = out1 = inverts = lps = 0;
554      span = 0xff;
555      val = dataread(ROM);
556      in = dataread(ROM);
557      in_count = 8;
558      return;
559   }
560
561   while (m_decomp_buffer_length < (SPC7110_DECOMP_BUFFER_SIZE >> 1))
562   {
563      UINT32 data;
564      for (int pixel = 0; pixel < 8; pixel++)
565      {
566         //get first symbol context
567         UINT32 a = ((out0 >> (0 * 4)) & 15);
568         UINT32 b = ((out0 >> (7 * 4)) & 15);
569         UINT32 c = ((out1 >> (0 * 4)) & 15);
570         UINT32 con = 0;
571         UINT32 refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
572
573         //update pixel order
574         UINT32 m, n;
575         for (m = 0; m < 16; m++)
576         {
577            if (pixelorder[m] == a)
578            {
579               break;
580            }
581         }
582         for (n = m; n >  0; n--)
583         {
584            pixelorder[n] = pixelorder[n - 1];
585         }
586         pixelorder[0] = a;
587
588         //calculate the real pixel order
589         for (m = 0; m < 16; m++)
590         {
591            realorder[m] = pixelorder[m];
592         }
593
594         //rotate reference pixel c value to top
595         for (m = 0; m < 16; m++)
596         {
597            if (realorder[m] == c)
598            {
599               break;
600            }
601         }
602         for (n = m; n >  0; n--)
603         {
604            realorder[n] = realorder[n - 1];
605         }
606         realorder[0] = c;
607
608         //rotate reference pixel b value to top
609         for (m = 0; m < 16; m++)
610         {
611            if (realorder[m] == b)
612            {
613               break;
614            }
615         }
616         for (n = m; n >  0; n--)
617         {
618            realorder[n] = realorder[n - 1];
619         }
620         realorder[0] = b;
621
622         //rotate reference pixel a value to top
623         for (m = 0; m < 16; m++)
624         {
625            if (realorder[m] == a)
626            {
627               break;
628            }
629         }
630         for (n = m; n >  0; n--)
631         {
632            realorder[n] = realorder[n - 1];
633         }
634         realorder[0] = a;
635
636         //get 4 symbols
637         for (int bit = 0; bit < 4; bit++)
638         {
639            UINT32 invertbit, shift;
640
641            //get prob
642            UINT32 prob = probability(con);
643
644            //get symbol
645            UINT32 flag_lps;
646            if (val <= span - prob) //mps
647            {
648               span = span - prob;
649               flag_lps = 0;
650            }
651            else //lps
652            {
653               val = val - (span - (prob - 1));
654               span = prob - 1;
655               flag_lps = 1;
656            }
657
658            //renormalize
659            shift = 0;
660            while (span < 0x7f)
661            {
662               shift++;
663
664               span = (span << 1) + 1;
665               val = (val << 1) + (in >> 7);
666
667               in <<= 1;
668               if (--in_count == 0)
669               {
670                  in = dataread(ROM);
671                  in_count = 8;
672               }
673            }
674
675            //update processing info
676            lps = (lps << 1) + flag_lps;
677            invertbit = m_context[con].invert;
678            inverts = (inverts << 1) + invertbit;
679
680            //update context state
681            if (flag_lps & toggle_invert(con))
682            {
683               m_context[con].invert ^= 1;
684            }
685            if (flag_lps)
686            {
687               m_context[con].index = next_lps(con);
688            }
689            else if (shift)
690            {
691               m_context[con].index = next_mps(con);
692            }
693
694            //get next context
695            con = spc7110_mode2_context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0);
696         }
697
698         //get pixel
699         b = realorder[(lps ^ inverts) & 0x0f];
700         out1 = (out1 << 4) + ((out0 >> 28) & 0x0f);
701         out0 = (out0 << 4) + b;
702      }
703
704      //convert pixel data into bitplanes
705      data = morton_4x8(out0);
706      write(data >> 24);
707      write(data >> 16);
708      bitplanebuffer[buffer_index++] = data >> 8;
709      bitplanebuffer[buffer_index++] = data >> 0;
710
711      if (buffer_index == 16)
712      {
713         for (int i = 0; i < 16; i++)
714         {
715            write(bitplanebuffer[i]);
716         }
717         buffer_index = 0;
718      }
719   }
720}
721
722UINT8 SPC7110Decomp::probability(UINT32 n)
723{
724   return spc7110_evolution_table[m_context[n].index][0];
725}
726
727UINT8 SPC7110Decomp::next_lps(UINT32 n)
728{
729   return spc7110_evolution_table[m_context[n].index][1];
730}
731
732UINT8 SPC7110Decomp::next_mps(UINT32 n)
733{
734   return spc7110_evolution_table[m_context[n].index][2];
735}
736
737UINT8 SPC7110Decomp::toggle_invert(UINT32 n)
738{
739   return spc7110_evolution_table[m_context[n].index][3];
740}
741
742UINT32 SPC7110Decomp::morton_2x8(UINT32 data)
743{
744   //reverse morton lookup: de-interleave two 8-bit values
745   //15, 13, 11,  9,  7,  5,  3,  1 -> 15- 8
746   //14, 12, 10,  8,  6,  4,  2,  0 ->  7- 0
747   return m_morton16[0][(data >>  0) & 255] + m_morton16[1][(data >>  8) & 255];
748}
749
750UINT32 SPC7110Decomp::morton_4x8(UINT32 data)
751{
752   //reverse morton lookup: de-interleave four 8-bit values
753   //31, 27, 23, 19, 15, 11,  7,  3 -> 31-24
754   //30, 26, 22, 18, 14, 10,  6,  2 -> 23-16
755   //29, 25, 21, 17, 13,  9,  5,  1 -> 15- 8
756   //28, 24, 20, 16, 12,  8,  4,  0 ->  7- 0
757   return m_morton32[0][(data >>  0) & 255] + m_morton32[1][(data >>  8) & 255]
758      + m_morton32[2][(data >> 16) & 255] + m_morton32[3][(data >> 24) & 255];
759}
760
761static void spc7110_update_time(running_machine &machine, UINT8 offset);
762
763enum RTC_State
764{
765   RTCS_Inactive,
766   RTCS_ModeSelect,
767   RTCS_IndexSelect,
768   RTCS_Write
769};
770
771enum RTC_Mode
772{
773   RTCM_Linear = 0x03,
774   RTCM_Indexed = 0x0c
775};
776
777static const UINT32 spc7110_months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
778
779struct snes_spc7110_t
780{
781   //==================
782   //decompression unit
783   //==================
784   UINT8 r4801;        // compression table low
785   UINT8 r4802;        // compression table high
786   UINT8 r4803;        // compression table bank
787   UINT8 r4804;        // compression table index
788   UINT8 r4805;        // decompression buffer index low
789   UINT8 r4806;        // decompression buffer index high
790   UINT8 r4807;        // ???
791   UINT8 r4808;        // ???
792   UINT8 r4809;        // compression length low
793   UINT8 r480a;        // compression length high
794   UINT8 r480b;        // decompression control register
795   UINT8 r480c;        // decompression status
796
797   SPC7110Decomp* decomp;
798
799   UINT8 r4811;        // data pointer low
800   UINT8 r4812;        // data pointer high
801   UINT8 r4813;        // data pointer bank
802   UINT8 r4814;        // data adjust low
803   UINT8 r4815;        // data adjust high
804   UINT8 r4816;        // data increment low
805   UINT8 r4817;        // data increment high
806   UINT8 r4818;        // data port control register
807
808   UINT8 r481x;
809
810   UINT8 r4814_latch;
811   UINT8 r4815_latch;
812
813   //=========
814   //math unit
815   //=========
816   UINT8 r4820;        // 16-bit multiplicand B0, 32-bit dividend B0
817   UINT8 r4821;        // 16-bit multiplicand B1, 32-bit dividend B1
818   UINT8 r4822;        // 32-bit dividend B2
819   UINT8 r4823;        // 32-bit dividend B3
820   UINT8 r4824;        // 16-bit multiplier B0
821   UINT8 r4825;        // 16-bit multiplier B1
822   UINT8 r4826;        // 16-bit divisor B0
823   UINT8 r4827;        // 16-bit divisor B1
824   UINT8 r4828;        // 32-bit product B0, 32-bit quotient B0
825   UINT8 r4829;        // 32-bit product B1, 32-bit quotient B1
826   UINT8 r482a;        // 32-bit product B2, 32-bit quotient B2
827   UINT8 r482b;        // 32-bit product B3, 32-bit quotient B3
828   UINT8 r482c;        // 16-bit remainder B0
829   UINT8 r482d;        // 16-bit remainder B1
830   UINT8 r482e;        // math control register
831   UINT8 r482f;        // math status
832
833   //===================
834   //memory mapping unit
835   //===================
836   UINT8 r4830;        // SRAM write enable
837   UINT8 r4831;        // $[d0-df]:[0000-ffff] mapping
838   UINT8 r4832;        // $[e0-ef]:[0000-ffff] mapping
839   UINT8 r4833;        // $[f0-ff]:[0000-ffff] mapping
840   UINT8 r4834;        // ???
841
842   UINT32 dx_offset;
843   UINT32 ex_offset;
844   UINT32 fx_offset;
845
846   //====================
847   //real-time clock unit
848   //====================
849   UINT8 r4840;        // RTC latch
850   UINT8 r4841;        // RTC index/data port
851   UINT8 r4842;        // RTC status
852
853   UINT32 rtc_state;
854   UINT32 rtc_mode;
855   UINT32 rtc_index;
856
857   UINT64 rtc_offset;
858
859   UINT8 rtc_ram[16];  // 0-12 secs, min, hrs, etc.; 13-14-15 control registers
860
861   UINT32 size;
862   UINT8 ram[0x2000];
863};
864
865static snes_spc7110_t snes_spc7110;
866
867void spc7110_init(running_machine& machine)
868{
869   snes_state *state = machine.driver_data<snes_state>();
870
871   snes_spc7110.r4801 = 0x00;
872   snes_spc7110.r4802 = 0x00;
873   snes_spc7110.r4803 = 0x00;
874   snes_spc7110.r4804 = 0x00;
875   snes_spc7110.r4805 = 0x00;
876   snes_spc7110.r4806 = 0x00;
877   snes_spc7110.r4807 = 0x00;
878   snes_spc7110.r4808 = 0x00;
879   snes_spc7110.r4809 = 0x00;
880   snes_spc7110.r480a = 0x00;
881   snes_spc7110.r480b = 0x00;
882   snes_spc7110.r480c = 0x00;
883
884   snes_spc7110.r4811 = 0x00;
885   snes_spc7110.r4812 = 0x00;
886   snes_spc7110.r4813 = 0x00;
887   snes_spc7110.r4814 = 0x00;
888   snes_spc7110.r4815 = 0x00;
889   snes_spc7110.r4816 = 0x00;
890   snes_spc7110.r4817 = 0x00;
891   snes_spc7110.r4818 = 0x00;
892
893   snes_spc7110.r481x = 0x00;
894   snes_spc7110.r4814_latch = 0;
895   snes_spc7110.r4815_latch = 0;
896
897   snes_spc7110.r4820 = 0x00;
898   snes_spc7110.r4821 = 0x00;
899   snes_spc7110.r4822 = 0x00;
900   snes_spc7110.r4823 = 0x00;
901   snes_spc7110.r4824 = 0x00;
902   snes_spc7110.r4825 = 0x00;
903   snes_spc7110.r4826 = 0x00;
904   snes_spc7110.r4827 = 0x00;
905   snes_spc7110.r4828 = 0x00;
906   snes_spc7110.r4829 = 0x00;
907   snes_spc7110.r482a = 0x00;
908   snes_spc7110.r482b = 0x00;
909   snes_spc7110.r482c = 0x00;
910   snes_spc7110.r482d = 0x00;
911   snes_spc7110.r482e = 0x00;
912   snes_spc7110.r482f = 0x00;
913
914   snes_spc7110.r4830 = 0x00;
915   spc7110_mmio_write(machine, 0x4831, 0);
916   spc7110_mmio_write(machine, 0x4832, 1);
917   spc7110_mmio_write(machine, 0x4833, 2);
918   snes_spc7110.r4834 = 0x00;
919
920   snes_spc7110.r4840 = 0x00;
921   snes_spc7110.r4841 = 0x00;
922   snes_spc7110.r4842 = 0x00;
923
924   snes_spc7110.size = state->m_cart[0].m_rom_size;
925
926   snes_spc7110.decomp = auto_alloc(machine, SPC7110Decomp(machine, snes_spc7110.size));
927}
928
929void spc7110rtc_init(running_machine& machine)
930{
931   spc7110_init(machine);
932
933   snes_spc7110.rtc_state = RTCS_Inactive;
934   snes_spc7110.rtc_mode  = RTCM_Linear;
935   snes_spc7110.rtc_index = 0;
936
937   snes_spc7110.rtc_offset = 0;
938
939   spc7110_update_time(machine, 0);
940}
941
942static UINT32 spc7110_datarom_addr(UINT32 addr)
943{
944   UINT32 size = snes_spc7110.size - 0x100000;
945   while (addr >= size)
946   {
947      addr -= size;
948   }
949   return addr + 0x100000;
950}
951
952static UINT32 spc7110_data_pointer(void)
953{
954   return snes_spc7110.r4811 + (snes_spc7110.r4812 << 8) + (snes_spc7110.r4813 << 16);
955}
956
957static UINT32 spc7110_data_adjust(void)
958{
959   return snes_spc7110.r4814 + (snes_spc7110.r4815 << 8);
960}
961
962static UINT32 spc7110_data_increment(void)
963{
964   return snes_spc7110.r4816 + (snes_spc7110.r4817 << 8);
965}
966
967static void spc7110_set_data_pointer(UINT32 addr)
968{
969   snes_spc7110.r4811 = addr;
970   snes_spc7110.r4812 = addr >> 8;
971   snes_spc7110.r4813 = addr >> 16;
972}
973
974static void spc7110_set_data_adjust(UINT32 addr)
975{
976   snes_spc7110.r4814 = addr;
977   snes_spc7110.r4815 = addr >> 8;
978}
979
980// FIXME: SPC7110 RTC is capable of rounding/adding/zero-ing seconds, so
981// we should probably keep track internally of the time rather than updating
982// to the system time at each call with a "offset" tracking as we do now...
983// (and indeed current code fails to pass Tengai Makyou Zero tests)
984static void spc7110_update_time(running_machine &machine, UINT8 offset)
985{
986   system_time curtime, *systime = &curtime;
987   machine.current_datetime(curtime);
988   int update = 1;
989
990   snes_spc7110.rtc_offset += offset;
991
992   // TEST: can we go beyond 24hrs of rounding?!? I doubt it will ever go beyond 3600, but I could be wrong...
993   assert(snes_spc7110.rtc_offset < 86400);
994
995   /* do not update if CR0 or CR2 timer disable flags are set */
996   if ((snes_spc7110.rtc_ram[13] & 0x01) || (snes_spc7110.rtc_ram[15] & 0x03))
997      update = 0;
998
999   if (update)
1000   {
1001      /* update time with offset, assuming offset < 3600s */
1002      UINT8 second = systime->local_time.second;
1003      UINT8 minute = systime->local_time.minute;
1004      UINT8 hour = systime->local_time.hour;
1005      UINT8 mday = systime->local_time.mday;
1006
1007      while (snes_spc7110.rtc_offset >= 3600)
1008      {
1009         snes_spc7110.rtc_offset -= 3600;
1010         hour++;
1011
1012         if (hour == 24)
1013         {
1014            mday++;
1015            hour = 0;
1016         }
1017      }
1018
1019      while (snes_spc7110.rtc_offset >= 60)
1020      {
1021         snes_spc7110.rtc_offset -= 60;
1022         minute++;
1023
1024         if (minute == 60)
1025         {
1026            hour++;
1027            minute = 0;
1028         }
1029      }
1030
1031      while (snes_spc7110.rtc_offset)
1032      {
1033         snes_spc7110.rtc_offset -= 1;
1034         second++;
1035
1036         if (second == 60)
1037         {
1038            minute++;
1039            second = 0;
1040         }
1041      }
1042
1043      snes_spc7110.rtc_ram[0] = second % 10;
1044      snes_spc7110.rtc_ram[1] = second / 10;
1045      snes_spc7110.rtc_ram[2] = minute % 10;
1046      snes_spc7110.rtc_ram[3] = minute / 10;
1047      snes_spc7110.rtc_ram[4] = hour % 10;
1048      snes_spc7110.rtc_ram[5] = hour / 10;
1049      snes_spc7110.rtc_ram[6] = mday % 10;
1050      snes_spc7110.rtc_ram[7] = mday / 10;
1051      snes_spc7110.rtc_ram[8] = systime->local_time.month % 10;
1052      snes_spc7110.rtc_ram[9] = systime->local_time.month / 10;
1053      snes_spc7110.rtc_ram[8] = systime->local_time.month;
1054      snes_spc7110.rtc_ram[10] = (systime->local_time.year - 1900) % 10;
1055      snes_spc7110.rtc_ram[11] = ((systime->local_time.year - 1900) / 10) % 10;
1056      snes_spc7110.rtc_ram[12] = systime->local_time.weekday % 7;
1057   }
1058}
1059
1060UINT8 spc7110_mmio_read(address_space &space, UINT32 addr)
1061{
1062   running_machine &machine = space.machine();
1063   snes_state *state = machine.driver_data<snes_state>();
1064   UINT8 *ROM = state->m_cart[0].m_rom;
1065
1066   addr &= 0xffff;
1067
1068   switch(addr)
1069   {
1070   //==================
1071   //decompression unit
1072   //==================
1073
1074   case 0x4800:
1075      {
1076         UINT16 counter = (snes_spc7110.r4809 + (snes_spc7110.r480a << 8));
1077         counter--;
1078         snes_spc7110.r4809 = counter;
1079         snes_spc7110.r480a = counter >> 8;
1080         return snes_spc7110.decomp->read(ROM);
1081      }
1082   case 0x4801: return snes_spc7110.r4801;
1083   case 0x4802: return snes_spc7110.r4802;
1084   case 0x4803: return snes_spc7110.r4803;
1085   case 0x4804: return snes_spc7110.r4804;
1086   case 0x4805: return snes_spc7110.r4805;
1087   case 0x4806: return snes_spc7110.r4806;
1088   case 0x4807: return snes_spc7110.r4807;
1089   case 0x4808: return snes_spc7110.r4808;
1090   case 0x4809: return snes_spc7110.r4809;
1091   case 0x480a: return snes_spc7110.r480a;
1092   case 0x480b: return snes_spc7110.r480b;
1093   case 0x480c:
1094      {
1095         UINT8 status = snes_spc7110.r480c;
1096         snes_spc7110.r480c &= 0x7f;
1097         return status;
1098      }
1099
1100   //==============
1101   //data port unit
1102   //==============
1103
1104   case 0x4810:
1105      {
1106         UINT8 data;
1107         UINT32 address, adjust, adjustaddr;
1108
1109         if (snes_spc7110.r481x != 0x07) return 0x00;
1110
1111         address = spc7110_data_pointer();
1112         adjust = spc7110_data_adjust();
1113         if (snes_spc7110.r4818 & 8)
1114         {
1115            adjust = (INT16)adjust;  //16-bit sign extend
1116         }
1117
1118         adjustaddr = address;
1119         if (snes_spc7110.r4818 & 2)
1120         {
1121            adjustaddr += adjust;
1122            spc7110_set_data_adjust(adjust + 1);
1123         }
1124
1125         data = ROM[spc7110_datarom_addr(adjustaddr)];
1126         if (!(snes_spc7110.r4818 & 2))
1127         {
1128            UINT32 increment = (snes_spc7110.r4818 & 1) ? spc7110_data_increment() : 1;
1129            if (snes_spc7110.r4818 & 4)
1130            {
1131               increment = (INT16)increment;  //16-bit sign extend
1132            }
1133
1134            if ((snes_spc7110.r4818 & 16) == 0)
1135            {
1136               spc7110_set_data_pointer(address + increment);
1137            }
1138            else
1139            {
1140               spc7110_set_data_adjust(adjust + increment);
1141            }
1142         }
1143
1144         return data;
1145      }
1146   case 0x4811: return snes_spc7110.r4811;
1147   case 0x4812: return snes_spc7110.r4812;
1148   case 0x4813: return snes_spc7110.r4813;
1149   case 0x4814: return snes_spc7110.r4814;
1150   case 0x4815: return snes_spc7110.r4815;
1151   case 0x4816: return snes_spc7110.r4816;
1152   case 0x4817: return snes_spc7110.r4817;
1153   case 0x4818: return snes_spc7110.r4818;
1154   case 0x481a:
1155      {
1156         UINT8 data;
1157         UINT32 address, adjust;
1158         if (snes_spc7110.r481x != 0x07)
1159         {
1160            return 0x00;
1161         }
1162
1163         address = spc7110_data_pointer();
1164         adjust = spc7110_data_adjust();
1165         if (snes_spc7110.r4818 & 8)
1166         {
1167            adjust = (INT16)adjust;  //16-bit sign extend
1168         }
1169
1170         data = ROM[spc7110_datarom_addr(address + adjust)];
1171         if ((snes_spc7110.r4818 & 0x60) == 0x60)
1172         {
1173            if ((snes_spc7110.r4818 & 16) == 0)
1174            {
1175               spc7110_set_data_pointer(address + adjust);
1176            }
1177            else
1178            {
1179               spc7110_set_data_adjust(adjust + adjust);
1180            }
1181         }
1182
1183         return data;
1184      }
1185
1186   //=========
1187   //math unit
1188   //=========
1189
1190   case 0x4820: return snes_spc7110.r4820;
1191   case 0x4821: return snes_spc7110.r4821;
1192   case 0x4822: return snes_spc7110.r4822;
1193   case 0x4823: return snes_spc7110.r4823;
1194   case 0x4824: return snes_spc7110.r4824;
1195   case 0x4825: return snes_spc7110.r4825;
1196   case 0x4826: return snes_spc7110.r4826;
1197   case 0x4827: return snes_spc7110.r4827;
1198   case 0x4828: return snes_spc7110.r4828;
1199   case 0x4829: return snes_spc7110.r4829;
1200   case 0x482a: return snes_spc7110.r482a;
1201   case 0x482b: return snes_spc7110.r482b;
1202   case 0x482c: return snes_spc7110.r482c;
1203   case 0x482d: return snes_spc7110.r482d;
1204   case 0x482e: return snes_spc7110.r482e;
1205   case 0x482f:
1206      {
1207         UINT8 status = snes_spc7110.r482f;
1208         snes_spc7110.r482f &= 0x7f;
1209         return status;
1210      }
1211
1212   //===================
1213   //memory mapping unit
1214   //===================
1215
1216   case 0x4830: return snes_spc7110.r4830;
1217   case 0x4831: return snes_spc7110.r4831;
1218   case 0x4832: return snes_spc7110.r4832;
1219   case 0x4833: return snes_spc7110.r4833;
1220   case 0x4834: return snes_spc7110.r4834;
1221
1222   //====================
1223   //real-time clock unit
1224   //====================
1225   case 0x4840: return snes_spc7110.r4840;
1226   case 0x4841:
1227      {
1228         UINT8 data = 0;
1229         if (snes_spc7110.rtc_state == RTCS_Inactive || snes_spc7110.rtc_state == RTCS_ModeSelect)
1230            return 0x00;
1231
1232         snes_spc7110.r4842 = 0x80;
1233         data = snes_spc7110.rtc_ram[snes_spc7110.rtc_index];
1234         snes_spc7110.rtc_index = (snes_spc7110.rtc_index + 1) & 15;
1235         return data;
1236      }
1237   case 0x4842:
1238      {
1239         UINT8 status = snes_spc7110.r4842;
1240         snes_spc7110.r4842 &= 0x7f;
1241         return status;
1242      }
1243   }
1244
1245   return snes_open_bus_r(space, 0);
1246}
1247
1248void spc7110_mmio_write(running_machine &machine, UINT32 addr, UINT8 data)
1249{
1250   snes_state *state = machine.driver_data<snes_state>();
1251   UINT8 *ROM = state->m_cart[0].m_rom;
1252
1253   addr &= 0xffff;
1254
1255   switch(addr)
1256   {
1257   //==================
1258   //decompression unit
1259   //==================
1260
1261   case 0x4801: snes_spc7110.r4801 = data; break;
1262   case 0x4802: snes_spc7110.r4802 = data; break;
1263   case 0x4803: snes_spc7110.r4803 = data; break;
1264   case 0x4804: snes_spc7110.r4804 = data; break;
1265   case 0x4805: snes_spc7110.r4805 = data; break;
1266   case 0x4806:
1267      {
1268         UINT32 table, index, address, mode, offset;
1269         snes_spc7110.r4806 = data;
1270
1271         table   = (snes_spc7110.r4801 + (snes_spc7110.r4802 << 8) + (snes_spc7110.r4803 << 16));
1272         index   = (snes_spc7110.r4804 << 2);
1273         //length  = (snes_spc7110.r4809 + (snes_spc7110.r480a << 8));
1274         address = spc7110_datarom_addr(table + index);
1275         mode    = (ROM[address + 0]);
1276         offset  = (ROM[address + 1] << 16)
1277               + (ROM[address + 2] <<  8)
1278               + (ROM[address + 3] <<  0);
1279
1280         snes_spc7110.decomp->init(machine, ROM, mode, offset, (snes_spc7110.r4805 + (snes_spc7110.r4806 << 8)) << mode);
1281         snes_spc7110.r480c = 0x80;
1282      }
1283      break;
1284
1285   case 0x4807: snes_spc7110.r4807 = data; break;
1286   case 0x4808: snes_spc7110.r4808 = data; break;
1287   case 0x4809: snes_spc7110.r4809 = data; break;
1288   case 0x480a: snes_spc7110.r480a = data; break;
1289   case 0x480b: snes_spc7110.r480b = data; break;
1290
1291   //==============
1292   //data port unit
1293   //==============
1294
1295   case 0x4811: snes_spc7110.r4811 = data; snes_spc7110.r481x |= 0x01; break;
1296   case 0x4812: snes_spc7110.r4812 = data; snes_spc7110.r481x |= 0x02; break;
1297   case 0x4813: snes_spc7110.r4813 = data; snes_spc7110.r481x |= 0x04; break;
1298   case 0x4814:
1299      {
1300         snes_spc7110.r4814 = data;
1301         snes_spc7110.r4814_latch = 1;
1302         if (!snes_spc7110.r4815_latch)
1303         {
1304            break;
1305         }
1306         if (!(snes_spc7110.r4818 & 2))
1307         {
1308            break;
1309         }
1310         if (snes_spc7110.r4818 & 0x10)
1311         {
1312            break;
1313         }
1314
1315         if ((snes_spc7110.r4818 & 0x60) == 0x20)
1316         {
1317            UINT32 increment = spc7110_data_adjust() & 0xff;
1318            if (snes_spc7110.r4818 & 8)
1319            {
1320               increment = (INT8)increment;  //8-bit sign extend
1321            }
1322            spc7110_set_data_pointer(spc7110_data_pointer() + increment);
1323         }
1324         else if ((snes_spc7110.r4818 & 0x60) == 0x40)
1325         {
1326            UINT32 increment = spc7110_data_adjust();
1327            if (snes_spc7110.r4818 & 8)
1328            {
1329               increment = (INT16)increment;  //16-bit sign extend
1330            }
1331            spc7110_set_data_pointer(spc7110_data_pointer() + increment);
1332         }
1333         break;
1334      }
1335
1336   case 0x4815:
1337      {
1338         snes_spc7110.r4815 = data;
1339         snes_spc7110.r4815_latch = 1;
1340         if (!snes_spc7110.r4814_latch)
1341         {
1342            break;
1343         }
1344         if (!(snes_spc7110.r4818 & 2))
1345         {
1346            break;
1347         }
1348         if (snes_spc7110.r4818 & 0x10)
1349         {
1350            break;
1351         }
1352
1353         if ((snes_spc7110.r4818 & 0x60) == 0x20)
1354         {
1355            UINT32 increment = spc7110_data_adjust() & 0xff;
1356            if (snes_spc7110.r4818 & 8)
1357            {
1358               increment = (INT8)increment;  //8-bit sign extend
1359            }
1360            spc7110_set_data_pointer(spc7110_data_pointer() + increment);
1361         }
1362         else if ((snes_spc7110.r4818 & 0x60) == 0x40)
1363         {
1364            UINT32 increment = spc7110_data_adjust();
1365            if (snes_spc7110.r4818 & 8)
1366            {
1367               increment = (INT16)increment;  //16-bit sign extend
1368            }
1369            spc7110_set_data_pointer(spc7110_data_pointer() + increment);
1370         }
1371         break;
1372      }
1373
1374   case 0x4816: snes_spc7110.r4816 = data; break;
1375   case 0x4817: snes_spc7110.r4817 = data; break;
1376   case 0x4818:
1377      {
1378            if (snes_spc7110.r481x != 0x07)
1379            break;
1380
1381            snes_spc7110.r4818 = data;
1382            snes_spc7110.r4814_latch = snes_spc7110.r4815_latch = 0;
1383            break;
1384         }
1385
1386   //=========
1387   //math unit
1388   //=========
1389
1390   case 0x4820: snes_spc7110.r4820 = data; break;
1391   case 0x4821: snes_spc7110.r4821 = data; break;
1392   case 0x4822: snes_spc7110.r4822 = data; break;
1393   case 0x4823: snes_spc7110.r4823 = data; break;
1394   case 0x4824: snes_spc7110.r4824 = data; break;
1395   case 0x4825:
1396      {
1397            snes_spc7110.r4825 = data;
1398
1399            if (snes_spc7110.r482e & 1)
1400         {
1401               //signed 16-bit x 16-bit multiplication
1402               INT16 r0 = (INT16)(snes_spc7110.r4824 + (snes_spc7110.r4825 << 8));
1403               INT16 r1 = (INT16)(snes_spc7110.r4820 + (snes_spc7110.r4821 << 8));
1404
1405               INT32 result = r0 * r1;
1406               snes_spc7110.r4828 = result;
1407               snes_spc7110.r4829 = result >> 8;
1408               snes_spc7110.r482a = result >> 16;
1409               snes_spc7110.r482b = result >> 24;
1410         }
1411         else
1412         {
1413               //unsigned 16-bit x 16-bit multiplication
1414               UINT16 r0 = (UINT16)(snes_spc7110.r4824 + (snes_spc7110.r4825 << 8));
1415               UINT16 r1 = (UINT16)(snes_spc7110.r4820 + (snes_spc7110.r4821 << 8));
1416
1417               UINT32 result = r0 * r1;
1418               snes_spc7110.r4828 = result;
1419               snes_spc7110.r4829 = result >> 8;
1420               snes_spc7110.r482a = result >> 16;
1421               snes_spc7110.r482b = result >> 24;
1422         }
1423
1424         snes_spc7110.r482f = 0x80;
1425         break;
1426      }
1427
1428   case 0x4826: snes_spc7110.r4826 = data; break;
1429   case 0x4827:
1430      {
1431         snes_spc7110.r4827 = data;
1432
1433         if (snes_spc7110.r482e & 1)
1434         {
1435            //signed 32-bit x 16-bit division
1436            INT32 dividend = (INT32)(snes_spc7110.r4820 + (snes_spc7110.r4821 << 8) + (snes_spc7110.r4822 << 16) + (snes_spc7110.r4823 << 24));
1437            INT16 divisor  = (INT16)(snes_spc7110.r4826 + (snes_spc7110.r4827 << 8));
1438
1439            INT32 quotient;
1440            INT16 remainder;
1441
1442            if (divisor)
1443            {
1444               quotient  = (INT32)(dividend / divisor);
1445               remainder = (INT32)(dividend % divisor);
1446            }
1447            else
1448            {
1449               //illegal division by zero
1450               quotient  = 0;
1451               remainder = dividend & 0xffff;
1452            }
1453
1454            snes_spc7110.r4828 = quotient;
1455            snes_spc7110.r4829 = quotient >> 8;
1456            snes_spc7110.r482a = quotient >> 16;
1457            snes_spc7110.r482b = quotient >> 24;
1458
1459            snes_spc7110.r482c = remainder;
1460            snes_spc7110.r482d = remainder >> 8;
1461         }
1462         else
1463         {
1464            //unsigned 32-bit x 16-bit division
1465            UINT32 dividend = (UINT32)(snes_spc7110.r4820 + (snes_spc7110.r4821 << 8) + (snes_spc7110.r4822 << 16) + (snes_spc7110.r4823 << 24));
1466            UINT16 divisor  = (UINT16)(snes_spc7110.r4826 + (snes_spc7110.r4827 << 8));
1467
1468            UINT32 quotient;
1469            UINT16 remainder;
1470
1471            if (divisor)
1472            {
1473               quotient  = (UINT32)(dividend / divisor);
1474               remainder = (UINT16)(dividend % divisor);
1475            }
1476            else
1477            {
1478               //illegal division by zero
1479               quotient  = 0;
1480               remainder = dividend & 0xffff;
1481            }
1482
1483            snes_spc7110.r4828 = quotient;
1484            snes_spc7110.r4829 = quotient >> 8;
1485            snes_spc7110.r482a = quotient >> 16;
1486            snes_spc7110.r482b = quotient >> 24;
1487
1488            snes_spc7110.r482c = remainder;
1489            snes_spc7110.r482d = remainder >> 8;
1490         }
1491
1492         snes_spc7110.r482f = 0x80;
1493         break;
1494      }
1495
1496   case 0x482e:
1497      {
1498         //reset math unit
1499         snes_spc7110.r4820 = snes_spc7110.r4821 = snes_spc7110.r4822 = snes_spc7110.r4823 = 0;
1500         snes_spc7110.r4824 = snes_spc7110.r4825 = snes_spc7110.r4826 = snes_spc7110.r4827 = 0;
1501         snes_spc7110.r4828 = snes_spc7110.r4829 = snes_spc7110.r482a = snes_spc7110.r482b = 0;
1502         snes_spc7110.r482c = snes_spc7110.r482d = 0;
1503
1504         snes_spc7110.r482e = data;
1505         break;
1506      }
1507
1508   //===================
1509   //memory mapping unit
1510   //===================
1511
1512   case 0x4830: snes_spc7110.r4830 = data; break;
1513
1514   case 0x4831:
1515      {
1516         snes_spc7110.r4831 = data;
1517         snes_spc7110.dx_offset = spc7110_datarom_addr(data * 0x100000);
1518         break;
1519      }
1520
1521   case 0x4832:
1522      {
1523         snes_spc7110.r4832 = data;
1524         snes_spc7110.ex_offset = spc7110_datarom_addr(data * 0x100000);
1525         break;
1526      }
1527
1528   case 0x4833:
1529      {
1530         snes_spc7110.r4833 = data;
1531         snes_spc7110.fx_offset = spc7110_datarom_addr(data * 0x100000);
1532         break;
1533      }
1534
1535   case 0x4834: snes_spc7110.r4834 = data; break;
1536
1537   //====================
1538   //real-time clock unit
1539   //====================
1540
1541   case 0x4840:
1542      {
1543         snes_spc7110.r4840 = data;
1544
1545         if (!(snes_spc7110.r4840 & 1))
1546         {
1547            //disable RTC
1548            snes_spc7110.rtc_state = RTCS_Inactive;
1549            spc7110_update_time(machine, 0);
1550         }
1551         else
1552         {
1553            //enable RTC
1554            snes_spc7110.r4842 = 0x80;
1555            snes_spc7110.rtc_state = RTCS_ModeSelect;
1556         }
1557      }
1558      break;
1559
1560   case 0x4841:
1561      {
1562         snes_spc7110.r4841 = data;
1563
1564         switch (snes_spc7110.rtc_state)
1565         {
1566         case RTCS_ModeSelect:
1567            if (data == RTCM_Linear || data == RTCM_Indexed)
1568            {
1569               snes_spc7110.r4842 = 0x80;
1570               snes_spc7110.rtc_state = RTCS_IndexSelect;
1571               snes_spc7110.rtc_mode = (RTC_Mode)data;
1572               snes_spc7110.rtc_index = 0;
1573            }
1574            break;
1575
1576         case RTCS_IndexSelect:
1577            snes_spc7110.r4842 = 0x80;
1578            snes_spc7110.rtc_index = data & 15;
1579            if (snes_spc7110.rtc_mode == RTCM_Linear)
1580               snes_spc7110.rtc_state = RTCS_Write;
1581            break;
1582
1583         case RTCS_Write:
1584            snes_spc7110.r4842 = 0x80;
1585
1586            //control register 0
1587            if (snes_spc7110.rtc_index == 13)
1588            {
1589               //increment second counter
1590               if (data & 2)
1591                  spc7110_update_time(machine, 1);
1592
1593               //round minute counter
1594               if (data & 8)
1595               {
1596                  spc7110_update_time(machine, 0);
1597
1598                  UINT8 second = snes_spc7110.rtc_ram[0] + snes_spc7110.rtc_ram[1] * 10;
1599                  //clear seconds
1600                  snes_spc7110.rtc_ram[0] = 0;
1601                  snes_spc7110.rtc_ram[1] = 0;
1602
1603                  if (second >= 30)
1604                     spc7110_update_time(machine, 60);
1605               }
1606            }
1607
1608            //control register 2
1609            if (snes_spc7110.rtc_index == 15)
1610            {
1611               //disable timer and clear second counter
1612               if ((data & 1) && !(snes_spc7110.rtc_ram[15]  & 1))
1613               {
1614                  spc7110_update_time(machine, 0);
1615
1616                  //clear seconds
1617                  snes_spc7110.rtc_ram[0] = 0;
1618                  snes_spc7110.rtc_ram[1] = 0;
1619               }
1620
1621               //disable timer
1622               if ((data & 2) && !(snes_spc7110.rtc_ram[15] & 2))
1623                  spc7110_update_time(machine, 0);
1624            }
1625
1626            snes_spc7110.rtc_ram[snes_spc7110.rtc_index] = data & 15;
1627            snes_spc7110.rtc_index = (snes_spc7110.rtc_index + 1) & 15;
1628            break;
1629         }
1630      }
1631      break;
1632   }
1633}
1634
1635UINT8 spc7110_bank7_read(address_space &space, UINT32 offset)
1636{
1637   snes_state *state = space.machine().driver_data<snes_state>();
1638   UINT8 *ROM = state->m_cart[0].m_rom;
1639   UINT32 addr = offset & 0x0fffff;
1640
1641   switch (offset & 0xf00000)
1642   {
1643   case 0x100000:
1644      return ROM[snes_spc7110.dx_offset + addr];
1645   case 0x200000:
1646      return ROM[snes_spc7110.ex_offset + addr];
1647   case 0x300000:
1648      return ROM[snes_spc7110.fx_offset + addr];
1649   default:
1650      break;
1651   }
1652   return snes_open_bus_r(space, 0);
1653}
1654
1655UINT8 spc7110_ram_read(UINT32 offset)
1656{
1657   return snes_spc7110.ram[offset & 0x1fff];
1658}
1659
1660void spc7110_ram_write(UINT32 offset, UINT8 data)
1661{
1662   snes_spc7110.ram[offset & 0x1fff] = data;
1663}
trunk/src/mess/machine/sns_slot.c
r21870r21871
2121    subslots (e.g. BS-X compatible ones), that need to write to subslot (NV)RAM independently
2222    to accesses to their own (NV)RAM.
2323
24    In order to support legacy dumps of games with add-on NEC & Seta DSPs, CX4 and Seta ST018,
25    we use not only m_type to identify the correct slot device to be used (for this DSP1B, DSP2 and
26    DSP3 are the same), but also a m_addon variable that snes_add driver uses to load CPU dump from
27    the system BIOS (for this DSP1B, DSP2 and DSP3 are not the same).
28
29
2430 ***********************************************************************************************************/
2531
2632
r21870r21871
169175                  device_t(mconfig, type, name, tag, owner, clock),
170176                  device_image_interface(mconfig, *this),
171177                  device_slot_interface(mconfig, *this),
178                  m_addon(ADDON_NONE),
172179                  m_type(SNES_MODE20)
173180{
174181}
r21870r21871
495502
496503      case 0x03:
497504         if (buffer[start_offs + 0x15] == 0x30)
498            return SNES_DSP4;
505            return ADDON_DSP4;
499506         else
500            return SNES_DSP;
507            return ADDON_DSP1;
501508
502509      case 0x04:
503         return SNES_DSP;
510         return ADDON_DSP1;
504511
505512      case 0x05:
506513         // DSP2 can be detected by (buffer[start_offs + 0x15] == 0x20)
507514         // DSP3 is harder to detect, and one has to rely on the manufacturer (Bandai)
508515         //      by checking (buffer[start_offs + 0x15] == 0x30) && (buffer[start_offs + 0x1a] == 0xb2)
509516         // in other cases is DSP1, but we do treat all these together...
510         return SNES_DSP;
517         if (buffer[start_offs + 0x15] == 0x20)
518            return ADDON_DSP2;
519         else if ((buffer[start_offs + 0x15] == 0x30) && (buffer[start_offs + 0x1a] == 0xb2))
520            return ADDON_DSP3;
521         else
522            return ADDON_DSP1;
511523
512524      case 0x13:  // Mario Chip 1
513525      case 0x14:  // GSU-x
514526      case 0x15:  // GSU-x
515527      case 0x1a:  // GSU-1 (21 MHz at start)
516528         if (buffer[start_offs + 0x15] == 0x20)
517            return SNES_SFX;
529            return ADDON_SFX;
518530         break;
519531
520532      case 0x25:
521         return SNES_OBC1;
533         return ADDON_OBC1;
522534
523535      case 0x32:  // needed by a Sample game (according to ZSNES)
524536      case 0x34:
525537      case 0x35:
526538         if (buffer[start_offs + 0x15] == 0x23)
527            return SNES_SA1;
539            return ADDON_SA1;
528540         break;
529541
530542      case 0x43:
531543      case 0x45:
532544         if (buffer[start_offs + 0x15] == 0x32)
533            return SNES_SDD1;
545            return ADDON_SDD1;
534546         break;
535547
536548      case 0x55:
537549         if (buffer[start_offs + 0x15] == 0x35)
538            return SNES_SRTC;
550            return ADDON_SRTC;
539551         break;
540552
541553      case 0xe3:
542         return SNES_Z80GB;
554         return ADDON_Z80GB;
543555
544556      case 0xf3:
545         return SNES_CX4;
557         return ADDON_CX4;
546558
547559      case 0xf5:
548560         if (buffer[start_offs + 0x15] == 0x30)
549            return SNES_ST018;
561            return ADDON_ST018;
550562         else if (buffer[start_offs + 0x15] == 0x3a)
551            return SNES_SPC7110;
563            return ADDON_SPC7110;
552564         break;
553565
554566      case 0xf6:
555567         /* These Seta ST-01X chips have both 0x30 at 0xffd5,
556568          they only differ for the 'size' at 0xffd7 */
557569         if (buffer[start_offs + 0x17] < 0x0a)
558            return SNES_ST011;
570            return ADDON_ST011;
559571         else
560            return SNES_ST010;
572            return ADDON_ST010;
561573
562574      case 0xf9:
563575         if (buffer[start_offs + 0x15] == 0x3a)
564            return SNES_SPC7110_RTC;
576            return ADDON_SPC7110_RTC;
565577         break;
566578
567579      default:
r21870r21871
618630
619631      // get pcb type
620632      if (software_entry() == NULL)
621         m_type = get_cart_type(ROM, len);
633         get_cart_type_addon(ROM, len, m_type, m_addon);
622634      else
623635      {
624636         if ((slot_name = get_feature("slot")) == NULL)
r21870r21871
630642               m_type = SNES_DSP_2MB;
631643      }
632644
633      setup_custom_mappers();
645      if (software_entry() == NULL)
646         setup_appended_addon();
634647
635648      setup_nvram();
636649
r21870r21871
648661            auto_free(machine(), temp_nvram);
649662      }
650663
651      printf("Type %d\n", m_type);
664      //printf("Type %d\n", m_type);
652665
653666      internal_header_logging(ROM, len);
654667
r21870r21871
684697}
685698
686699
687void base_sns_cart_slot_device::setup_custom_mappers()
700void base_sns_cart_slot_device::setup_appended_addon()
688701{
689   // we have to eventually support pirate mappers here
702   // if we already have an add-on bios or if no addon has been detected, we have nothing to do
703   if (m_cart->get_addon_bios_size() || m_addon == ADDON_NONE)
704      return;
705
706   // check if the add-on dump is appended to the file
707   // if this is the case, copy it in m_bios and refresh
708   // the rom_bank_map with correct game rom size
709   switch (m_addon)
710   {
711      case ADDON_DSP1:
712      case ADDON_DSP1B:
713      case ADDON_DSP2:
714      case ADDON_DSP3:
715      case ADDON_DSP4:
716         // check for add-on dump
717         if ((m_cart->get_rom_size() & 0x7fff) == 0x2800)
718         {
719            logerror("Found NEC DSP dump at the bottom of the ROM.\n");
720            m_cart->addon_bios_alloc(machine(), 0x2800);
721            memcpy(m_cart->get_addon_bios_base(), m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x2800), 0x2800);
722            m_cart->rom_map_setup(m_cart->get_rom_size() - 0x2800);
723         }
724         // check for byuu's compressed version (swapped order of bytes and stripped fixed 0x00 bytes)
725         if ((m_cart->get_rom_size() & 0x7fff) == 0x2000)
726         {
727            logerror("Found NEC DSP dump (byuu's version) at the bottom of the ROM.\n");
728            m_cart->addon_bios_alloc(machine(), 0x2800);
729            for (int i = 0; i < 0x800; i++)
730            {
731               memcpy(m_cart->get_addon_bios_base() + i * 4 + 2, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x2000) + i * 3 + 0, 1);
732               memcpy(m_cart->get_addon_bios_base() + i * 4 + 1, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x2000) + i * 3 + 1, 1);
733               memcpy(m_cart->get_addon_bios_base() + i * 4 + 0, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x2000) + i * 3 + 2, 1);
734               memset(m_cart->get_addon_bios_base() + i * 4 + 3, 0xff, 1);
735            }
736            memcpy(m_cart->get_addon_bios_base() + 0x2000, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x1800), 0x800);
737            m_cart->rom_map_setup(m_cart->get_rom_size() - 0x2000);
738         }
739         break;
740      case ADDON_ST010:
741      case ADDON_ST011:
742         // check for add-on dump
743         if ((m_cart->get_rom_size() & 0x3ffff) == 0x11000)
744         {
745            logerror("Found Seta DSP dump at the bottom of the ROM.\n");
746            m_cart->addon_bios_alloc(machine(), 0x11000);
747            memcpy(m_cart->get_addon_bios_base(), m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x11000), 0x11000);
748            m_cart->rom_map_setup(m_cart->get_rom_size() - 0x11000);
749         }
750         // check for byuu's compressed version (swapped order of bytes and stripped fixed 0x00 bytes)
751         if ((m_cart->get_rom_size() & 0xffff) == 0xd000)
752         {
753            logerror("Found Seta DSP dump (byuu's version) at the bottom of the ROM.\n");
754            m_cart->addon_bios_alloc(machine(), 0x11000);
755            for (int i = 0; i < 0x4000; i++)
756            {
757               memcpy(m_cart->get_addon_bios_base() + i * 4 + 2, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0xd000) + i * 3 + 0, 1);
758               memcpy(m_cart->get_addon_bios_base() + i * 4 + 1, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0xd000) + i * 3 + 1, 1);
759               memcpy(m_cart->get_addon_bios_base() + i * 4 + 0, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0xd000) + i * 3 + 2, 1);
760               memset(m_cart->get_addon_bios_base() + i * 4 + 3, 0xff, 1);
761            }
762            memcpy(m_cart->get_addon_bios_base() + 0x10000, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0xc000), 0x1000);
763            m_cart->rom_map_setup(m_cart->get_rom_size() - 0xd000);
764         }
765         break;
766      case ADDON_CX4:
767         if ((m_cart->get_rom_size() & 0x7fff) == 0x0c00)
768         {
769            logerror("Found CX4 dump at the bottom of the ROM.\n");
770            m_cart->addon_bios_alloc(machine(), 0x0c00);
771            memcpy(m_cart->get_addon_bios_base(), m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x0c00), 0x0c00);
772            m_cart->rom_map_setup(m_cart->get_rom_size() - 0x0c00);
773         }
774         break;
775      case ADDON_ST018:
776         if ((m_cart->get_rom_size() & 0x3ffff) == 0x28000)
777         {
778            logerror("Found ST018 dump at the bottom of the ROM.\n");
779            m_cart->addon_bios_alloc(machine(), 0x28000);
780            memcpy(m_cart->get_addon_bios_base(), m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x28000), 0x28000);
781            m_cart->rom_map_setup(m_cart->get_rom_size() - 0x28000);
782         }
783         break;
784   }
690785}
691786
692787void base_sns_cart_slot_device::setup_nvram()
r21870r21871
738833   return TRUE;
739834}
740835
741int base_sns_cart_slot_device::get_cart_type(UINT8 *ROM, UINT32 len)
836void base_sns_cart_slot_device::get_cart_type_addon(UINT8 *ROM, UINT32 len, int &type, int &addon)
742837{
743   int type = 0;
744
745838   // First, look if the cart is HiROM or LoROM (and set snes_cart accordingly)
746839   int hilo_mode = snes_find_hilo_mode(ROM, len);
747840
r21870r21871
784877   // check for add-on chips...
785878   if (len >= hilo_mode + 0x1a)
786879   {
787      int addon = snes_find_addon_chip(ROM, hilo_mode);
880      addon = snes_find_addon_chip(ROM, hilo_mode);
788881      if (addon != -1)
789882      {
790         if (type == SNES_MODE20 && addon == SNES_DSP)
883         // m_type handles DSP1,2,3 in the same way, but snes_add requires them to be separate...
884         switch (addon)
791885         {
792            if (len > 0x100000)
793               type = SNES_DSP_2MB;
794            else
795               type = SNES_DSP;
886            case ADDON_CX4:
887               type = SNES_CX4;
888               break;
889            case ADDON_DSP1:
890            case ADDON_DSP1B:
891            case ADDON_DSP2:
892            case ADDON_DSP3:
893               if (type == SNES_MODE20 && len > 0x100000)
894                  type = SNES_DSP_2MB;
895               else if (type == SNES_MODE21)
896                  type = SNES_DSP_MODE21;
897               else
898                  type = SNES_DSP;
899               break;
900            case ADDON_DSP4:
901               type = SNES_DSP4;
902               break;
903            case ADDON_OBC1:
904               type = SNES_OBC1;
905               break;
906            case ADDON_SA1:
907               type = SNES_SA1;
908               break;
909            case ADDON_SDD1:
910               type = SNES_SDD1;
911               break;
912            case ADDON_SFX:
913               type = SNES_SFX;
914               break;
915            case ADDON_SPC7110:
916               type = SNES_SPC7110;
917               break;
918            case ADDON_SPC7110_RTC:
919               type = SNES_SPC7110_RTC;
920               break;
921            case ADDON_ST010:
922               type = SNES_ST010;
923               break;
924            case ADDON_ST011:
925               type = SNES_ST011;
926               break;
927            case ADDON_ST018:
928               type = SNES_ST018;
929               break;
930            case ADDON_SRTC:
931               type = SNES_SRTC;
932               break;
933            case ADDON_Z80GB:
934               type = SNES_Z80GB;
935               break;
796936         }
797         else if (type == SNES_MODE21 && addon == SNES_DSP)
798            type = SNES_DSP_MODE21;
799         else
800            type = addon;
801937      }
802938   }
803   // ...and turn them off if we are loading from fullpath a game which requires an add-on bios
804   switch (type)
805   {
806      case SNES_DSP:
807      case SNES_DSP_2MB:
808      case SNES_DSP4:
809      case SNES_ST010:
810      case SNES_ST011:
811      case SNES_ST018:
812//      case SNES_CX4:
813         printf("This type of cart requires the dump of on-cart CPU. You need to load it from softlist!\n");
814         type = SNES_MODE20;
815         break;
816      case SNES_DSP_MODE21:
817         printf("This type of cart requires the dump of on-cart CPU. You need to load it from softlist!\n");
818         type = SNES_MODE21;
819         break;
820   }
939}
821940
822   return type;
823}
824941/*-------------------------------------------------
825942 get default card software
826943 -------------------------------------------------*/
827944
828945const char * base_sns_cart_slot_device::get_default_card_software(const machine_config &config, emu_options &options)
829946{
830   const char *slot_string = "lorom";
831947   bool fullpath = open_image_file(options);
832948
833949   if (fullpath)
834950   {
951      const char *slot_string = "lorom";
835952      UINT32 offset = 0;
836953      UINT32 len = core_fsize(m_file);
837954      UINT8 *ROM = global_alloc_array(UINT8, len);
838      int type;
955      int type = 0, addon = 0;
839956
840957      core_fread(m_file, ROM, len);
841958
842959      offset = snes_skip_header(ROM, len);
843     
844      type = get_cart_type(ROM + offset, len - offset);
960
961      get_cart_type_addon(ROM + offset, len - offset, type, addon);
845962      slot_string = sns_get_slot(type);
846963
847964      global_free(ROM);
r21870r21871
854971}
855972
856973
857
858974/*-------------------------------------------------
859975 read
860976 -------------------------------------------------*/
r21870r21871
9211037
9221038
9231039/*-------------------------------------------------
1040 snes_stop_addon_cpu
1041 -------------------------------------------------*/
1042
1043void base_sns_cart_slot_device::snes_stop_addon_cpu(const char *cputag)
1044{
1045   astring cpu(m_cart->device().tag(), ":", cputag);
1046   if (m_cart && machine().device(cpu))
1047      machine().device(cpu.cstr())->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
1048}
1049
1050/*-------------------------------------------------
9241051 Internal header logging
9251052 -------------------------------------------------*/
9261053
trunk/src/mess/machine/sns_slot.h
r21870r21871
55 TYPE DEFINITIONS
66 ***************************************************************************/
77
8// offset of add-on dumps inside snes_add/snesp_add bios, to support old dumps missing add-on data
9#define SNES_DSP1_OFFSET  (0x00000)
10#define SNES_DSP1B_OFFSET (0x03000)
11#define SNES_DSP2_OFFSET  (0x06000)
12#define SNES_DSP3_OFFSET  (0x09000)
13#define SNES_DSP4_OFFSET  (0x0c000)
14#define SNES_ST10_OFFSET  (0x0f000)
15#define SNES_ST11_OFFSET  (0x20000)
16#define SNES_CX4_OFFSET   (0x31000)
17#define SNES_ST18_OFFSET1 (0x32000)
18#define SNES_ST18_OFFSET2 (0x52000)
819
20
921/* PCB */
1022enum
1123{
r21870r21871
4658   SNES_BUGS   // wip
4759};
4860
61/* add-ons to handle legacy dumps in snes_add  */
62enum
63{
64   ADDON_NONE = 0,
65   ADDON_CX4,
66   ADDON_DSP1,
67   ADDON_DSP1B,
68   ADDON_DSP2,
69   ADDON_DSP3,
70   ADDON_DSP4,
71   ADDON_OBC1,
72   ADDON_SA1,
73   ADDON_SDD1,
74   ADDON_SFX,
75   ADDON_SPC7110,
76   ADDON_SPC7110_RTC,
77   ADDON_ST010,
78   ADDON_ST011,
79   ADDON_ST018,
80   ADDON_SRTC,
81   ADDON_Z80GB
82};
4983
5084// ======================> sns_cart_interface
5185
r21870r21871
123157   virtual void call_unload();
124158   virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry);
125159
126   int get_cart_type(UINT8 *ROM, UINT32 len);
160   void get_cart_type_addon(UINT8 *ROM, UINT32 len, int &type, int &addon);
127161   UINT32 snes_skip_header(UINT8 *ROM, UINT32 snes_rom_size);
128162   int get_type() { return m_type; }
163   int get_addon() { return m_addon; }
129164
130   void setup_custom_mappers();
131165   void setup_nvram();
132166   void internal_header_logging(UINT8 *ROM, UINT32 len);
133167
r21870r21871
152186   virtual DECLARE_READ8_MEMBER(chip_read);
153187   virtual DECLARE_WRITE8_MEMBER(chip_write);
154188
189   // in order to support legacy dumps, we enable add-on CPUs even when loading from fullpath
190   // and then we stop them at MACHINE_RESET to avoid crashes
191   void snes_stop_addon_cpu(const char *cputag);
192   // in order to support legacy dumps + add-on CPU dump appended at the end of the file, we
193   // check if the required data is present and update bank map accordingly
194   void setup_appended_addon();
195
196
155197// m_cart cannot be made private yet, because we need to check nvram_size from the driver...
156198// more work needed
157199//private:
158200
201   // this is used to support legacy DSPx/ST0xx/CX4 dumps not including the CPU data...
202   // i.e. it's only used for snes_add/snesp_add
203   int m_addon;
204
159205   int m_type;
160206   device_sns_cart_interface*      m_cart;
161207};
trunk/src/mess/machine/snescx4.c
r21870r21871
1111***************************************************************************/
1212
1313#include "emu.h"
14#include "snescx4.h"
14#include "machine/snescx4.h"
1515
1616static CX4 cx4;
1717
r21870r21871
2323
2424static void CX4_C4DrawLine(INT32 X1, INT32 Y1, INT16 Z1, INT32 X2, INT32 Y2, INT16 Z2, UINT8 Color);
2525
26#include "cx4data.c"
27#include "cx4fn.c"
26#include "machine/cx4data.c"
27#include "machine/cx4fn.c"
2828
2929static UINT32 CX4_ldr(UINT8 r)
3030{
r21870r21871
113113   }
114114}
115115
116#include "cx4oam.c"
117#include "cx4ops.c"
116#include "machine/cx4oam.c"
117#include "machine/cx4ops.c"
118118
119119void CX4_write(running_machine &machine, UINT32 addr, UINT8 data)
120120{
trunk/src/mess/machine/snescx4.h
r21870r21871
2222      double c4x, c4y, c4z;
2323      double c4x2, c4y2, c4z2;
2424};
25
26UINT8 CX4_read(UINT32 addr);
27void CX4_write(running_machine &machine, UINT32 addr, UINT8 data);
trunk/src/mame/includes/snes.h
r21870r21871
2929
3030#define SNES_LAYER_DEBUG  0
3131
32#define SNES_DSP1B_OFFSET (0x0000)
33#define SNES_DSP1_OFFSET  (0x3000)
34#define SNES_DSP2_OFFSET  (0x6000)
35#define SNES_DSP3_OFFSET  (0x9000)
36#define SNES_DSP4_OFFSET  (0xc000)
37
3832/* Debug definitions */
3933#ifdef MAME_DEBUG
4034/* #define SNES_DBG_GENERAL*/       /* Display general debug info */
trunk/src/mame/drivers/nss.c
r21870r21871
866866#define NSS_BIOS \
867867   ROM_REGION(0x100,           "sound_ipl", 0)     /* IPL ROM */ \
868868   ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) \
869   ROM_REGION(0x10000,           "addons", ROMREGION_ERASE00)      /* add-on chip ROMs (DSP1 will be needed if we dump the NSS version of Super Mario Kart)*/\
870   ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) ) \
871869   ROM_REGION(0x8000,         "bios",  0)      /* Bios CPU */ \
872870   ROM_SYSTEM_BIOS( 0, "single", "Nintendo Super System (Single Cart BIOS)" ) \
873871   ROMX_LOAD("nss-ic14.02", 0x00000, 0x8000, CRC(e06cb58f) SHA1(62f507e91a2797919a78d627af53f029c7d81477), ROM_BIOS(1) )   /* bios */ \
874872   ROM_SYSTEM_BIOS( 1, "multi", "Nintendo Super System (Multi Cart BIOS)" ) \
875   ROMX_LOAD("nss-c.dat"  , 0x00000, 0x8000, CRC(a8e202b3) SHA1(b7afcfe4f5cf15df53452dc04be81929ced1efb2), ROM_BIOS(2) )   /* bios */ \
876   ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF) \
877   ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
873   ROMX_LOAD("nss-c.dat"  , 0x00000, 0x8000, CRC(a8e202b3) SHA1(b7afcfe4f5cf15df53452dc04be81929ced1efb2), ROM_BIOS(2) )   /* bios */
878874
879875
880
881
882876ROM_START( nss )
883877   NSS_BIOS
884878   ROM_REGION( 0x100000, "user3", ROMREGION_ERASEFF )

Previous 199869 Revisions Next


© 1997-2024 The MAME Team