not yet correct (nw)

This commit is contained in:
David Haywood 2013-07-18 02:29:52 +00:00
parent bd1f4df87c
commit 96bbc15ff8
4 changed files with 375 additions and 36 deletions

View File

@ -151,7 +151,43 @@ WRITE16_MEMBER(sshangha_state::paletteram16_xbgr_word_be_tilehigh_w)
sshangha_set_color_888((offset/2)+0x300, 0, 8, 16, m_tile_paletteram2[(offset) | 1] | (m_tile_paletteram2[(offset) & ~1] << 16) );
}
READ16_MEMBER( sshangha_state::sshangha_protection_region_d_146_r )
{
int real_address = 0x3f4000 + (offset *2);
int deco146_addr = BITSWAP32(real_address, /* NC */31,30,29,28,27,26,25,24,23,22,21,20,19,18, 13,12,11,/**/ 17,16,15,14, 10,9,8, 7,6,5,4, 3,2,1,0) & 0x7fff;
UINT8 cs = 0;
UINT16 data = m_deco146->read_data( deco146_addr, mem_mask, cs );
return data;
}
WRITE16_MEMBER( sshangha_state::sshangha_protection_region_d_146_w )
{
int real_address = 0x3f4000 + (offset *2);
int deco146_addr = BITSWAP32(real_address, /* NC */31,30,29,28,27,26,25,24,23,22,21,20,19,18, 13,12,11,/**/ 17,16,15,14, 10,9,8, 7,6,5,4, 3,2,1,0) & 0x7fff;
UINT8 cs = 0;
m_deco146->write_data( deco146_addr, data, mem_mask, cs );
}
READ16_MEMBER( sshangha_state::sshangha_protection_region_8_146_r )
{
int real_address = 0x3e0000 + (offset *2);
int deco146_addr = BITSWAP32(real_address, /* NC */31,30,29,28,27,26,25,24,23,22,21,20,19,18, 13,12,11,/**/ 17,16,15,14, 10,9,8, 7,6,5,4, 3,2,1,0) & 0x7fff;
UINT8 cs = 0;
UINT16 data = m_deco146->read_data( deco146_addr, mem_mask, cs );
return data;
}
WRITE16_MEMBER( sshangha_state::sshangha_protection_region_8_146_w )
{
int real_address = 0x3e0000 + (offset *2);
int deco146_addr = BITSWAP32(real_address, /* NC */31,30,29,28,27,26,25,24,23,22,21,20,19,18, 13,12,11,/**/ 17,16,15,14, 10,9,8, 7,6,5,4, 3,2,1,0) & 0x7fff;
UINT8 cs = 0;
m_deco146->write_data( deco146_addr, data, mem_mask, cs );
}
static ADDRESS_MAP_START( sshangha_map, AS_PROGRAM, 16, sshangha_state )
ADDRESS_MAP_GLOBAL_MASK(0x3fffff)
AM_RANGE(0x000000, 0x03ffff) AM_ROM
AM_RANGE(0x100000, 0x10000f) AM_RAM AM_SHARE("sound_shared")
@ -177,9 +213,9 @@ static ADDRESS_MAP_START( sshangha_map, AS_PROGRAM, 16, sshangha_state )
AM_RANGE(0x380800, 0x380bff) AM_RAM_WRITE(paletteram16_xbgr_word_be_sprites2_w) AM_SHARE("sprite_palram2")
AM_RANGE(0x380c00, 0x380fff) AM_RAM_WRITE(paletteram16_xbgr_word_be_tilelow_w) AM_SHARE("tile_palram1")
AM_RANGE(0x381000, 0x383fff) AM_RAM // unused palette area
AM_RANGE(0xfec000, 0xff3fff) AM_RAM
AM_RANGE(0xff4000, 0xff47ff) AM_READWRITE(sshangha_protection16_r,sshangha_protection16_w) AM_SHARE("prot_data")
AM_RANGE(0x3e0000, 0x3e3fff) AM_READWRITE(sshangha_protection_region_8_146_r,sshangha_protection_region_8_146_w)
AM_RANGE(0x3ec000, 0x3f3fff) AM_RAM
AM_RANGE(0x3f4000, 0x3f7fff) AM_READWRITE(sshangha_protection_region_d_146_r,sshangha_protection_region_d_146_w) AM_SHARE("prot_data")
ADDRESS_MAP_END
static ADDRESS_MAP_START( sshanghb_map, AS_PROGRAM, 16, sshangha_state )

View File

@ -1,11 +1,13 @@
#include "video/deco16ic.h"
#include "video/decospr.h"
#include "machine/deco146.h"
class sshangha_state : public driver_device
{
public:
sshangha_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
: driver_device(mconfig, type, tag),
m_deco146(*this, "ioprot"),
m_deco_tilegen1(*this, "tilegen1"),
m_spriteram(*this, "spriteram"),
m_spriteram2(*this, "spriteram2"),
@ -22,6 +24,7 @@ public:
m_maincpu(*this, "maincpu"),
m_audiocpu(*this, "audiocpu") { }
optional_device<deco146_device> m_deco146;
required_device<deco16ic_device> m_deco_tilegen1;
required_shared_ptr<UINT16> m_spriteram;
optional_shared_ptr<UINT16> m_spriteram2;
@ -42,6 +45,10 @@ public:
int m_video_control;
DECLARE_READ16_MEMBER( sshangha_protection_region_8_146_r );
DECLARE_WRITE16_MEMBER( sshangha_protection_region_8_146_w );
DECLARE_READ16_MEMBER( sshangha_protection_region_d_146_r );
DECLARE_WRITE16_MEMBER( sshangha_protection_region_d_146_w );
DECLARE_WRITE16_MEMBER(sshangha_protection16_w);

View File

@ -1,4 +1,4 @@
/* Data East 146 protection chip & I/O interface */
/* Data East 146 protection chip / memory-mapper & I/O interface */
#include "emu.h"
#include "deco146.h"
@ -25,7 +25,7 @@ struct nibselect
struct deco146port
{
UINT16 read_offset;
UINT16 write_offset;
int write_offset;
// char bit_mapping[16];
UINT16 nibble_rotate;
// UINT16 blank_mask;
@ -1082,33 +1082,280 @@ struct deco146port
{ 0x7FE, 0x4C/*, "FEDC3210BA987654"*/, 0/*, 0xFFFF*/, { 3,0,2,1 }, 2}, // .N.
};
static ADDRESS_MAP_START( deco146_map, AS_0, 16, deco146_device )
AM_RANGE(0x0000, 0x07ff) AM_RAM
AM_RANGE(0x0800, 0x0fff) AM_RAM
AM_RANGE(0x1000, 0x17ff) AM_RAM
AM_RANGE(0x1800, 0x1fff) AM_RAM
AM_RANGE(0x2000, 0x27ff) AM_RAM
AM_RANGE(0x2800, 0x2fff) AM_RAM
AM_RANGE(0x3000, 0x37ff) AM_RAM
AM_RANGE(0x3800, 0x3fff) AM_RAM
AM_RANGE(0x4000, 0x47ff) AM_RAM
AM_RANGE(0x4800, 0x4fff) AM_RAM
AM_RANGE(0x5000, 0x57ff) AM_RAM
AM_RANGE(0x5800, 0x5fff) AM_RAM
AM_RANGE(0x6000, 0x67ff) AM_RAM
AM_RANGE(0x6800, 0x6fff) AM_RAM
AM_RANGE(0x7000, 0x77ff) AM_RAM
AM_RANGE(0x7800, 0x7fff) AM_RAM
ADDRESS_MAP_END
/* there are probably less dumb ways of doing the CS logic, it could be hooked up
more like the system16 mapper chips */
void deco146_device::write_data(UINT16 address, UINT16 data, UINT16 mem_mask, UINT8 &csflags)
{
csflags = 0;
int upper_addr_bits = (address & 0x7800) >> 11;
if (upper_addr_bits == 0x8) // configuration registers are hardcoded to this area
{
int real_address = address & 0xf;
printf("write to config regs %04x %04x %04x\n", real_address, data, mem_mask);
if ((real_address>=0x2) && (real_address<=0x0c))
{
region_selects[(real_address-2)/2] = data &0xf;
return;
}
else
{
// unknown
}
return; // or fall through?
}
for (int i=0;i<6;i++)
{
int cs = region_selects[i];
if (cs==upper_addr_bits)
{
int real_address = address & 0x7ff;
csflags |= (1 << i);
if (i==0) // the first cs is our internal protection area
{
printf("write matches cs table (protection) %01x %04x %04x %04x\n", i, real_address, data, mem_mask);
write_protport(real_address, data, mem_mask);
}
else
{
printf("write matches cs table (external connection) %01x %04x %04x %04x\n", i, real_address, data, mem_mask);
}
}
}
if (csflags==0)
{
printf("write not in cs table\n");
}
}
UINT16 deco146_device::read_input_a_callback(void)
{
return ioport(":INPUTS")->read();
}
UINT16 deco146_device::read_input_b_callback(void)
{
return ioport(":SYSTEM")->read();
}
UINT16 deco146_device::read_input_c_callback(void)
{
return ioport(":DSW")->read();
}
UINT16 deco146_device::read_protport(UINT16 address, UINT16 mem_mask)
{
UINT16 retdata = 0;
// if we read the last written address immediately after then ignore all other logic and just return what was written unmodified
if ((address==m_latchaddr) && (m_latchflag==1))
{
printf("returning latched data %04x\n", m_latchdata);
m_latchflag = 0;
return m_latchdata;
}
m_latchflag = 0;
// otherwise process the data..
int location = port_info[address>>1].write_offset;
if (location==INPUT_PORT_A)
{
retdata = read_input_a_callback();
}
else if (location==INPUT_PORT_B)
{
retdata = read_input_b_callback();
}
else if (location==INPUT_PORT_C)
{
retdata = read_input_c_callback();
}
else
{
retdata = m_current_rambank[location>>1];
}
int flags = (port_info[address>>1].flags);
if (location>=0)
{
printf("read_protport (real ram addres %02x) | %04x %04x | ", location, address, mem_mask);
printf("nibble order %d %d %d %d | ", (port_info[address>>1].nibbles.nib0), (port_info[address>>1].nibbles.nib1),(port_info[address>>1].nibbles.nib2),(port_info[address>>1].nibbles.nib3) );
printf("lowest nibble rotate %d | ",(port_info[address>>1].nibble_rotate) );
if (flags&1) printf("read is affected by XOR | ");
if (flags&2) printf("read is affected by NAND | ");
//if (flags&4) printf("read has nibbles blanked out\n");
printf("would return %04x | ", retdata);
}
int nib;
UINT16 realret = 0;
nib = port_info[address>>1].nibbles.nib0;
if (nib==0) realret |= ((retdata & 0x000f)<<12);
if (nib==1) realret |= ((retdata & 0x00f0)<<8);
if (nib==2) realret |= ((retdata & 0x0f00)<<4);
if (nib==3) realret |= ((retdata & 0xf000)<<0);
nib = port_info[address>>1].nibbles.nib1;
if (nib==0) realret |= ((retdata & 0x000f)<<8);
if (nib==1) realret |= ((retdata & 0x00f0)<<4);
if (nib==2) realret |= ((retdata & 0x0f00)<<0);
if (nib==3) realret |= ((retdata & 0xf000)>>4);
nib = port_info[address>>1].nibbles.nib2;
if (nib==0) realret |= ((retdata & 0x000f)<<4);
if (nib==1) realret |= ((retdata & 0x00f0)<<0);
if (nib==2) realret |= ((retdata & 0x0f00)>>4);
if (nib==3) realret |= ((retdata & 0xf000)>>8);
nib = port_info[address>>1].nibbles.nib3;
UINT16 lownib = 0;
if (nib==0) lownib = ((retdata & 0x000f)<<0);
if (nib==1) lownib = ((retdata & 0x00f0)>>4);
if (nib==2) lownib = ((retdata & 0x0f00)>>8);
if (nib==3) lownib = ((retdata & 0xf000)>>12);
int rotate = (port_info[address>>1].nibble_rotate);
if (rotate==0)
{
}
else if (rotate==1)
{
lownib = ((lownib&0x7) << 1) | ((lownib&0x8) >> 3);
}
else if (rotate==2)
{
lownib = ((lownib&0x3) << 2) | ((lownib&0xc) >> 2);
}
else if (rotate==3)
{
lownib = ((lownib&0x1) << 3) | ((lownib&0xe) >> 1);
}
realret |= lownib;
if (flags&1) realret ^= m_xor;
if (flags&2) realret = (realret & m_nand)^0xffff;
if (location>=0)
{
printf("actual return %04x \n", realret);
}
if (location == 0x78) // this has a special meaning
{
printf("(bankswitch) %04x %04x\n", address, mem_mask);
if (m_current_rambank==m_rambank0)
m_current_rambank = m_rambank1;
else
m_current_rambank = m_rambank0;
}
return realret;
}
void deco146_device::write_protport(UINT16 address, UINT16 data, UINT16 mem_mask)
{
m_latchaddr = address;
m_latchdata = data;
m_latchflag = 1;
if ((address&0xff) == 0x2c)
{
printf("LOAD XOR REGISTER %04x %04x\n", data, mem_mask);
COMBINE_DATA(&m_xor);
}
else if ((address&0xff) == 0x36)
{
printf("LOAD NAND REGISTER %04x %04x\n", data, mem_mask);
COMBINE_DATA(&m_nand);
}
else if ((address&0xff) == 0x64)
{
printf("LOAD SOUND LATCH %04x %04x\n", data, mem_mask);
COMBINE_DATA(&m_soundlatch);
}
// always store
COMBINE_DATA(&m_current_rambank[address>>1]);
}
UINT16 deco146_device::read_data(UINT16 address, UINT16 mem_mask, UINT8 &csflags)
{
UINT16 retdata = 0;
csflags = 0;
int upper_addr_bits = (address & 0x7800) >> 11;
if (upper_addr_bits == 0x8) // configuration registers are hardcoded to this area
{
int real_address = address & 0xf;
printf("read config regs? %04x %04x\n", real_address, mem_mask);
return 0x0000;
}
// what gets priority?
for (int i=0;i<6;i++)
{
int cs = region_selects[i];
if (cs==upper_addr_bits)
{
int real_address = address & 0x7ff;
csflags |= (1 << i);
if (i==0) // the first cs is our internal protection area
{
//printf("read matches cs table (protection) %01x %04x %04x\n", i, real_address, mem_mask);
retdata = read_protport( real_address, mem_mask);
}
else
{
printf("read matches cs table (external connection) %01x %04x %04x\n", i, real_address, mem_mask);
}
}
}
if (csflags==0)
{
printf("read not in cs table\n");
}
return retdata;
}
const device_type DECO146PROT = &device_creator<deco146_device>;
deco146_device::deco146_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, DECO146PROT, "DECO146PROT", tag, owner, clock, "deco146", __FILE__),
device_memory_interface(mconfig, *this),
m_space_config("deco146_space", ENDIANNESS_BIG, 16,15, 0, NULL, *ADDRESS_MAP_NAME(deco146_map))
: device_t(mconfig, DECO146PROT, "DECO146PROT", tag, owner, clock, "deco146", __FILE__)
{
}
@ -1127,13 +1374,32 @@ void deco146_device::device_start()
if (read_address != i*2)
printf("%04x %02x\n", port_info[i].read_offset, port_info[i].write_offset);
}
}
void deco146_device::device_reset()
{
region_selects[0] = 0;
region_selects[1] = 0;
region_selects[2] = 0;
region_selects[3] = 0;
region_selects[4] = 0;
region_selects[5] = 0;
for (int i=0;i<0x80;i++)
{
m_rambank0[i] = 0x0000;
m_rambank1[i] = 0xffff;
}
m_current_rambank = m_rambank0;
m_nand = 0x0000;
m_xor = 0x0000;
m_soundlatch = 0x0000;
m_latchaddr = 0xffff;
m_latchdata = 0x0000;
m_latchflag = 0;
}
const address_space_config *deco146_device::memory_space_config(address_spacenum spacenum) const
{
return (spacenum == 0) ? &m_space_config : NULL;
}

View File

@ -1,16 +1,46 @@
#pragma once
#ifndef __DECO146_H__
#define __DECO146_H__
/* Data East 146 protection chip */
class deco146_device : public device_t,
public device_memory_interface
class deco146_device : public device_t
{
public:
deco146_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
void write_data(UINT16 address, UINT16 data, UINT16 mem_mask, UINT8 &csflags);
UINT16 read_data(UINT16 address, UINT16 mem_mask, UINT8 &csflags);
protected:
virtual void device_config_complete();
virtual void device_start();
virtual void device_reset();
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
address_space_config m_space_config;
UINT16 read_protport(UINT16 address, UINT16 mem_mask);
void write_protport(UINT16 address, UINT16 data, UINT16 mem_mask);
UINT16 m_rambank0[0x80];
UINT16 m_rambank1[0x80];
UINT16* m_current_rambank;
UINT16 read_input_a_callback(void);
UINT16 read_input_b_callback(void);
UINT16 read_input_c_callback(void);
UINT16 m_nand;
UINT16 m_xor;
UINT16 m_soundlatch;
UINT16 m_latchaddr;
UINT16 m_latchdata;
int m_latchflag;
private:
UINT8 region_selects[6];
};
@ -22,4 +52,4 @@ extern const device_type DECO146PROT;
#endif