(MESS)-gamete: added noise and envelope emulation [Peter Trauner]
This commit is contained in:
parent
1c4cfb6f18
commit
31f677b73a
@ -1,17 +1,22 @@
|
||||
/***************************************************************************
|
||||
gamate sound hardware
|
||||
|
||||
PeT mess@utanet.at
|
||||
PeT mess@utanet.at 2015
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/gamate.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
|
||||
enum { ClockDelay=32 };
|
||||
|
||||
// device type definition
|
||||
const device_type GAMATE_SND = &device_creator<gamate_sound_device>;
|
||||
|
||||
|
||||
const int gamate_sound_device::DAConverter[]={ 0, 3, 7, 13, 23, 41, 75, 137, 249, 453, 825, 1499, 2726, 4956, 9011, 16383 }; // (*.55) on the real below index 8 bareless measureable
|
||||
const UINT8 Mask[]={ 0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0x1f, 0x3f, 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0xf };
|
||||
const int EnvelopeVolumes[]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
@ -27,7 +32,6 @@ gamate_sound_device::gamate_sound_device(const machine_config &mconfig, const ch
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
@ -35,7 +39,7 @@ gamate_sound_device::gamate_sound_device(const machine_config &mconfig, const ch
|
||||
void gamate_sound_device::device_start()
|
||||
{
|
||||
// bind callbacks
|
||||
// m_irq_cb.bind_relative_to(*owner());
|
||||
// m_irq_cb.bind_relative_to(*owner());
|
||||
|
||||
memset(m_channels, 0, sizeof(m_channels));
|
||||
memset(reg, 0, sizeof(reg));
|
||||
@ -52,31 +56,94 @@ void gamate_sound_device::sound_stream_update(sound_stream &stream, stream_sampl
|
||||
{
|
||||
stream_sample_t *left=outputs[0], *right=outputs[1];
|
||||
int i, j;
|
||||
GAMATE_CHANNEL *channel;
|
||||
|
||||
Tone *channel;
|
||||
|
||||
for (i = 0; i < samples; i++, left++, right++)
|
||||
{
|
||||
noise.pos += noise.step;
|
||||
while (noise.pos >= 1.0) {
|
||||
// guess (white noise register taken from supervision)
|
||||
noise.level = noise.state & 0x40 ? 1 : 0;
|
||||
bool b1 = (noise.state & 0x40) != 0, b2 = (noise.state & 0x20) != 0;
|
||||
noise.state=(noise.state<<1)+(b1!=b2?1:0);
|
||||
noise.pos -= 1;
|
||||
}
|
||||
|
||||
envelope.pos += envelope.step;
|
||||
while (envelope.pos >= 1.0) {
|
||||
envelope.pos -= 1;
|
||||
envelope.index++;
|
||||
switch (envelope.control) {
|
||||
case 0: case 1: case 2: case 3:
|
||||
case 4: case 5: case 6: case 7:
|
||||
case 8: case 9: case 0xb:
|
||||
case 0xd: case 0xf:
|
||||
if (envelope.index>=ARRAY_LENGTH(EnvelopeVolumes)/2) {
|
||||
envelope.index=0;
|
||||
envelope.first=false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (envelope.index>=ARRAY_LENGTH(EnvelopeVolumes)) {
|
||||
envelope.index=0;
|
||||
envelope.first=false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*left = 0;
|
||||
*right = 0;
|
||||
for (channel=m_channels, j=0; j<ARRAY_LENGTH(m_channels); j++, channel++)
|
||||
{
|
||||
if (channel->size != 0)
|
||||
{
|
||||
if (channel->on)//||channel->count)
|
||||
{
|
||||
int on = FALSE;
|
||||
on = channel->pos <= channel->size / 2;
|
||||
{
|
||||
INT16 s = on ? channel->volume << 8 : 0;
|
||||
if (j == 0)
|
||||
*right += s;
|
||||
else if (j==1)
|
||||
*left += s;
|
||||
else {
|
||||
*right += s;
|
||||
*left += s;
|
||||
}
|
||||
}
|
||||
channel->level= channel->pos <= channel->size / 2;
|
||||
bool l= channel->full_cycle? true: channel->level;
|
||||
if (!channel->tone) l= l && noise.level;
|
||||
int volume=0;
|
||||
if (l) {
|
||||
if (channel->envelope_on) {
|
||||
switch (envelope.control) {
|
||||
case 0: case 1: case 2: case 3:
|
||||
case 0x9: // one time falling, low
|
||||
if (envelope.first && channel->level) volume=0xf-EnvelopeVolumes[envelope.index];
|
||||
break;
|
||||
case 4: case 5: case 6: case 7:
|
||||
case 0xf: // one time rising, low
|
||||
if (envelope.first && channel->level) volume=EnvelopeVolumes[envelope.index];
|
||||
break;
|
||||
case 8: // falling
|
||||
if (channel->level) volume=0xf-EnvelopeVolumes[envelope.index];
|
||||
break;
|
||||
case 0xa: // rising, falling
|
||||
if (channel->level) volume=EnvelopeVolumes[envelope.index];
|
||||
break;
|
||||
case 0xb: // one time falling, high
|
||||
if (channel->level) volume=envelope.first? 0xf-EnvelopeVolumes[envelope.index]: 0xf;
|
||||
break;
|
||||
case 0xc: // rising, low
|
||||
if (channel->level) volume=envelope.index<ARRAY_LENGTH(EnvelopeVolumes)/2? EnvelopeVolumes[envelope.index]: 0;
|
||||
break;
|
||||
case 0xd: // one time rising, high
|
||||
if (channel->level) volume=envelope.first? EnvelopeVolumes[envelope.index]: 0xf;
|
||||
break;
|
||||
case 0xe: // falling, rising
|
||||
if (channel->level) volume=0xf-EnvelopeVolumes[envelope.index];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
volume=channel->volume;
|
||||
}
|
||||
}
|
||||
if (j == Right)
|
||||
*right += Value2Volume(volume);
|
||||
else if (j==Left)
|
||||
*left += Value2Volume(volume);
|
||||
else {
|
||||
*right += Value2Volume(volume);
|
||||
*left += Value2Volume(volume);
|
||||
}
|
||||
channel->pos++;
|
||||
if (channel->pos >= channel->size)
|
||||
@ -94,7 +161,7 @@ WRITE8_MEMBER( gamate_sound_device::device_w )
|
||||
reg[offset] = data;
|
||||
int chan=-1;
|
||||
|
||||
switch (offset)
|
||||
switch (offset&0xf)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
@ -102,11 +169,11 @@ WRITE8_MEMBER( gamate_sound_device::device_w )
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
chan=offset/2;
|
||||
chan=offset/2;
|
||||
size = reg[chan*2] | ((reg[chan*2+1] & 0xf) << 8);
|
||||
if (size)
|
||||
{
|
||||
m_channels[chan].size= (int) (machine().sample_rate() * (size << 5) / machine().device("maincpu")->unscaled_clock());
|
||||
m_channels[chan].size= (int) (machine().sample_rate() * size*ClockDelay / machine().device("maincpu")->unscaled_clock());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -115,13 +182,49 @@ WRITE8_MEMBER( gamate_sound_device::device_w )
|
||||
m_channels[chan].pos = 0;
|
||||
break;
|
||||
case 6:
|
||||
size=data&0x1f;
|
||||
if (size==0) size=1;
|
||||
noise.step= machine().device("maincpu")->unscaled_clock() / (1.0*ClockDelay*machine().sample_rate()*size);
|
||||
break;
|
||||
case 7:
|
||||
m_channels[Right].full_cycle=data&1;
|
||||
m_channels[Right].tone=data&8;
|
||||
m_channels[Left].full_cycle=data&2;
|
||||
m_channels[Left].tone=data&0x10;
|
||||
m_channels[Both].full_cycle=data&4;
|
||||
m_channels[Both].tone=data&0x20;
|
||||
noise.state=1;
|
||||
noise.pos=0.0;
|
||||
noise.level=false;
|
||||
break;
|
||||
case 8:
|
||||
chan=offset-6;
|
||||
// m_channels[chan]->on = data & 0x40;
|
||||
// channel->waveform = (data & 0x30) >> 4;
|
||||
case 9:
|
||||
case 0xa:
|
||||
chan=offset-8;
|
||||
m_channels[chan].envelope_on = data & 0x10; // buggy aussetzer cube up
|
||||
m_channels[chan].volume = data & 0xf;
|
||||
break;
|
||||
case 0xb: case 0xc:
|
||||
size = reg[0xb] | ((reg[0xc]) << 8);
|
||||
if (size==0) size=1;
|
||||
envelope.step= machine().device("maincpu")->unscaled_clock() / (1.0*ClockDelay*machine().sample_rate()*size);
|
||||
break;
|
||||
case 0xd:
|
||||
envelope.control=data&0xf;
|
||||
envelope.pos=0;
|
||||
envelope.index=0;
|
||||
envelope.first=true;
|
||||
break;
|
||||
|
||||
}
|
||||
if (chan!=-1) m_channels[chan].on=m_channels[chan].volume!=0 && m_channels[chan].size>3/* avoid speed loss for unhearable >=23khz*/;
|
||||
envelope.pos=0; // guess
|
||||
envelope.index=0;
|
||||
envelope.first=true;
|
||||
}
|
||||
|
||||
READ8_MEMBER( gamate_sound_device::device_r )
|
||||
{
|
||||
UINT8 data=0;
|
||||
if ((offset&0xf)<ARRAY_LENGTH(Mask)) data=reg[offset&0xf]&Mask[offset&0xf]; // unused bits set to last write value? in this area
|
||||
return data;
|
||||
}
|
||||
|
@ -3,7 +3,11 @@
|
||||
Peter Wilhelmsen peter.wilhelmsen@gmail.com
|
||||
Morten Shearman Kirkegaard morten+gamate@afdelingp.dk
|
||||
Juan F??lix Mateos vectrex@hackermesh.org
|
||||
******************************************************************************/
|
||||
|
||||
nmi unknown
|
||||
cube up audio sometimes missing
|
||||
bomb blast top status line missing
|
||||
******************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/m6502/m6502.h"
|
||||
@ -36,6 +40,7 @@ public:
|
||||
DECLARE_WRITE8_MEMBER(cart_bankswitch_w);
|
||||
DECLARE_READ8_MEMBER(gamate_video_r);
|
||||
DECLARE_READ8_MEMBER(gamate_pad_r);
|
||||
DECLARE_READ8_MEMBER(gamate_nmi_r);
|
||||
DECLARE_WRITE8_MEMBER(gamate_video_w);
|
||||
DECLARE_READ8_MEMBER(gamate_audio_r);
|
||||
DECLARE_WRITE8_MEMBER(gamate_audio_w);
|
||||
@ -51,25 +56,24 @@ private:
|
||||
|
||||
struct
|
||||
{
|
||||
UINT8 reg[8];
|
||||
struct {
|
||||
bool write;
|
||||
bool page2; // else page1
|
||||
UINT8 reg[8];
|
||||
struct {
|
||||
bool page2; // else page1
|
||||
UINT8 ypos, xpos/*tennis*/;
|
||||
UINT8 data[2][0x100][0x20];
|
||||
} bitmap;
|
||||
UINT8 x, y;
|
||||
UINT8 data[2][0x100][0x20];
|
||||
} bitmap;
|
||||
UINT8 x, y;
|
||||
bool y_increment;
|
||||
} video;
|
||||
|
||||
struct {
|
||||
bool set;
|
||||
bool set;
|
||||
int bit_shifter;
|
||||
UINT8 cartridge_byte;
|
||||
UINT16 address; // in reality something more like short local cartridge address offset
|
||||
bool unprotected;
|
||||
bool failed;
|
||||
|
||||
|
||||
} card_protection;
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
@ -80,13 +84,13 @@ private:
|
||||
required_shared_ptr<UINT8> m_bios;
|
||||
emu_timer *timer1;
|
||||
emu_timer *timer2;
|
||||
UINT8 bank_multi;
|
||||
UINT8 bank_multi;
|
||||
};
|
||||
|
||||
WRITE8_MEMBER( gamate_state::gamate_cart_protection_w )
|
||||
{
|
||||
logerror("%.6f protection write %x %x address:%x data:%x shift:%d\n",machine().time().as_double(), offset, data, card_protection.address, card_protection.cartridge_byte, card_protection.bit_shifter);
|
||||
|
||||
logerror("%.6f protection write %x %x address:%x data:%x shift:%d\n",machine().time().as_double(), offset, data, card_protection.address, card_protection.cartridge_byte, card_protection.bit_shifter);
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
card_protection.failed= card_protection.failed || ((card_protection.cartridge_byte&0x80)!=0) != ((data&4)!=0);
|
||||
@ -100,10 +104,11 @@ WRITE8_MEMBER( gamate_state::gamate_cart_protection_w )
|
||||
}
|
||||
READ8_MEMBER( gamate_state::gamate_cart_protection_r )
|
||||
{
|
||||
UINT8 ret=1;
|
||||
if (card_protection.bit_shifter==7 && card_protection.unprotected) {
|
||||
ret=m_cart->get_rom_base()[bank_multi*0x4000];
|
||||
} else {
|
||||
|
||||
UINT8 ret=1;
|
||||
if (card_protection.bit_shifter==7 && card_protection.unprotected) {
|
||||
ret=m_cart->get_rom_base()[bank_multi*0x4000];
|
||||
} else {
|
||||
card_protection.bit_shifter++;
|
||||
if (card_protection.bit_shifter==8) {
|
||||
card_protection.bit_shifter=0;
|
||||
@ -112,66 +117,59 @@ READ8_MEMBER( gamate_state::gamate_cart_protection_r )
|
||||
}
|
||||
ret=(card_protection.cartridge_byte&0x80)?2:0;
|
||||
if (card_protection.bit_shifter==7 && !card_protection.failed) { // now protection chip on cartridge activates cartridge chip select on cpu accesses
|
||||
// m_maincpu->space(AS_PROGRAM).install_read_handler(0x6000, 0x6000, READ8_DELEGATE(gamate_state, gamate_cart_protection_r)); // next time I will try to get this working
|
||||
// m_maincpu->space(AS_PROGRAM).install_read_handler(0x6000, 0x6000, READ8_DELEGATE(gamate_state, gamate_cart_protection_r)); // next time I will try to get this working
|
||||
}
|
||||
card_protection.cartridge_byte<<=1;
|
||||
}
|
||||
logerror("%.6f protection read %x %x address:%x data:%x shift:%d\n",machine().time().as_double(), offset, ret, card_protection.address, card_protection.cartridge_byte, card_protection.bit_shifter);
|
||||
return ret;
|
||||
}
|
||||
logerror("%.6f protection read %x %x address:%x data:%x shift:%d\n",machine().time().as_double(), offset, ret, card_protection.address, card_protection.cartridge_byte, card_protection.bit_shifter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
READ8_MEMBER( gamate_state::protection_r ) { return card_protection.set? 3: 1; } // bits 0 and 1 checked
|
||||
|
||||
WRITE8_MEMBER( gamate_state::protection_reset )
|
||||
{
|
||||
// writes 0x20
|
||||
card_protection.address=0x6005-0x6001;
|
||||
card_protection.bit_shifter=0;
|
||||
card_protection.cartridge_byte=m_cart->get_rom_base()[card_protection.address++];//m_cart_rom[card_protection.address++];
|
||||
card_protection.failed=false;
|
||||
card_protection.unprotected=false;
|
||||
// writes 0x20
|
||||
card_protection.address=0x6005-0x6001;
|
||||
card_protection.bit_shifter=0;
|
||||
card_protection.cartridge_byte=m_cart->get_rom_base()[card_protection.address++];//m_cart_rom[card_protection.address++];
|
||||
card_protection.failed=false;
|
||||
card_protection.unprotected=false;
|
||||
}
|
||||
|
||||
READ8_MEMBER( gamate_state::newer_protection_set )
|
||||
{
|
||||
card_protection.set=true;
|
||||
return 0;
|
||||
card_protection.set=true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER( gamate_state::gamate_video_w )
|
||||
{
|
||||
video.reg[offset]=data;
|
||||
switch (offset) {
|
||||
case 1:
|
||||
if (data&0xf) printf("lcd mode %x\n", data);
|
||||
video.bitmap.write=data&0xc0; // more addressing mode
|
||||
video.y_increment=data&0x40;
|
||||
break;
|
||||
case 2: video.bitmap.xpos=data;break;
|
||||
case 3:
|
||||
if (data>=200) printf("lcd ypos: %x\n", data);
|
||||
video.bitmap.ypos=data;
|
||||
break;
|
||||
case 4: video.bitmap.page2=data&0x80;video.x=data&0x7f;break;
|
||||
case 5: video.y=data;break;
|
||||
case 7:
|
||||
if (video.y>=200)
|
||||
machine().ui().popup_time(2, "bitmap write to x:%x y:%x mode:%x data:%x\n", video.x, video.y, video.reg[1], data);
|
||||
if (video.bitmap.write) {
|
||||
video.bitmap.data[video.bitmap.page2][video.y][video.x]=data;
|
||||
} else {
|
||||
video.bitmap.data[0][video.y][video.x&(ARRAY_LENGTH(video.bitmap.data[0][0])-1)]=data;
|
||||
}
|
||||
if (video.y_increment) video.y++;
|
||||
else video.x++;
|
||||
}
|
||||
video.reg[offset]=data;
|
||||
switch (offset) {
|
||||
case 1:
|
||||
if (data&0xf) printf("lcd mode %x\n", data);
|
||||
video.y_increment=data&0x40;
|
||||
break;
|
||||
case 2: video.bitmap.xpos=data;break;
|
||||
case 3:
|
||||
if (data>=200) printf("lcd ypos: %x\n", data);
|
||||
video.bitmap.ypos=data;
|
||||
break;
|
||||
case 4: video.bitmap.page2=data&0x80;video.x=data&0x1f;break;
|
||||
case 5: video.y=data;break;
|
||||
case 7:
|
||||
video.bitmap.data[video.bitmap.page2][video.y][video.x&(ARRAY_LENGTH(video.bitmap.data[0][0])-1)]=data;
|
||||
if (video.y_increment) video.y++;
|
||||
else video.x++; // overruns
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( gamate_state::cart_bankswitchmulti_w )
|
||||
{
|
||||
bank_multi=data;
|
||||
membank("bankmulti")->set_base(m_cart->get_rom_base()+0x4000*data+1);
|
||||
bank_multi=data;
|
||||
membank("bankmulti")->set_base(m_cart->get_rom_base()+0x4000*data+1);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( gamate_state::cart_bankswitch_w )
|
||||
@ -181,55 +179,61 @@ WRITE8_MEMBER( gamate_state::cart_bankswitch_w )
|
||||
|
||||
READ8_MEMBER( gamate_state::gamate_video_r )
|
||||
{
|
||||
if (offset!=6) return 0;
|
||||
UINT8 data=0;
|
||||
if (video.bitmap.write) {
|
||||
data=video.bitmap.data[video.bitmap.page2][video.y][video.x];
|
||||
} else {
|
||||
data=video.bitmap.data[0][video.y][video.x&(ARRAY_LENGTH(video.bitmap.data[0][0])-1)];
|
||||
}
|
||||
if (offset!=6) return 0;
|
||||
UINT8 data=0;
|
||||
data=video.bitmap.data[video.bitmap.page2][video.y][video.x&(ARRAY_LENGTH(video.bitmap.data[0][0])-1)];
|
||||
// if (m_maincpu->pc()<0xf000)
|
||||
// machine().ui().popup_time(2, "lcd read x:%x y:%x mode:%x data:%x\n", video.x, video.y, video.reg[1], data);
|
||||
return data;
|
||||
if (video.y_increment) video.y++;
|
||||
else video.x++; // overruns?
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( gamate_state::gamate_audio_w )
|
||||
{
|
||||
// printf("audio write %x:%x\n", offset, data);//logerror("%.6f %04x audio write %04x %02x\n",machine().time().as_double(),m_maincpu->pc(),offset,data);
|
||||
m_sound->device_w(space, offset, data);
|
||||
m_sound->device_w(space, offset, data);
|
||||
}
|
||||
|
||||
READ8_MEMBER( gamate_state::gamate_audio_r )
|
||||
{
|
||||
// legend of dragon knight
|
||||
// machine().ui().popup_time(2, "%.6f %04x audio read %04x \n",machine().time().as_double(),m_maincpu->pc(),offset);
|
||||
return 0;
|
||||
UINT8 data=m_sound->device_r(space, offset);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER( gamate_state::gamate_pad_r )
|
||||
{
|
||||
UINT8 data=m_io_joy->read();
|
||||
return data;
|
||||
UINT8 data=m_io_joy->read();
|
||||
return data;
|
||||
}
|
||||
|
||||
READ8_MEMBER( gamate_state::gamate_nmi_r )
|
||||
{
|
||||
UINT8 data=0;
|
||||
machine().ui().popup_time(2, "nmi/4800 read\n");
|
||||
return data;
|
||||
}
|
||||
|
||||
static ADDRESS_MAP_START( gamate_mem, AS_PROGRAM, 8, gamate_state )
|
||||
AM_RANGE(0x0000, 0x03ff) AM_RAM
|
||||
AM_RANGE(0x4000, 0x400d) AM_READWRITE(gamate_audio_r, gamate_audio_w)
|
||||
AM_RANGE(0x4400, 0x4400) AM_READ(gamate_pad_r)
|
||||
AM_RANGE(0x5000, 0x5007) AM_READWRITE(gamate_video_r, gamate_video_w)
|
||||
AM_RANGE(0x5800, 0x5800) AM_READ(newer_protection_set)
|
||||
AM_RANGE(0x5900, 0x5900) AM_WRITE(protection_reset)
|
||||
AM_RANGE(0x5a00, 0x5a00) AM_READ(protection_r)
|
||||
AM_RANGE(0x0000, 0x03ff) AM_RAM
|
||||
AM_RANGE(0x4000, 0x400d) AM_READWRITE(gamate_audio_r, gamate_audio_w)
|
||||
AM_RANGE(0x4400, 0x4400) AM_READ(gamate_pad_r)
|
||||
AM_RANGE(0x4800, 0x4800) AM_READ(gamate_nmi_r)
|
||||
AM_RANGE(0x5000, 0x5007) AM_READWRITE(gamate_video_r, gamate_video_w)
|
||||
AM_RANGE(0x5800, 0x5800) AM_READ(newer_protection_set)
|
||||
AM_RANGE(0x5900, 0x5900) AM_WRITE(protection_reset)
|
||||
AM_RANGE(0x5a00, 0x5a00) AM_READ(protection_r)
|
||||
|
||||
AM_RANGE(0x6001, 0x9fff) AM_READ_BANK("bankmulti")
|
||||
AM_RANGE(0xa000, 0xdfff) AM_READ_BANK("bank")
|
||||
AM_RANGE(0x6001, 0x9fff) AM_READ_BANK("bankmulti")
|
||||
AM_RANGE(0xa000, 0xdfff) AM_READ_BANK("bank")
|
||||
|
||||
AM_RANGE(0x6000, 0x6000) AM_READWRITE(gamate_cart_protection_r, gamate_cart_protection_w)
|
||||
AM_RANGE(0x8000, 0x8000) AM_WRITE(cart_bankswitchmulti_w)
|
||||
AM_RANGE(0xc000, 0xc000) AM_WRITE(cart_bankswitch_w)
|
||||
|
||||
AM_RANGE(0xf000, 0xffff) AM_ROM AM_SHARE("bios")
|
||||
AM_RANGE(0xf000, 0xffff) AM_ROM AM_SHARE("bios")
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
@ -245,7 +249,7 @@ static INPUT_PORTS_START( gamate )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("Select")
|
||||
INPUT_PORTS_END
|
||||
|
||||
ATTR_UNUSED static const unsigned short gamate_palette[4] =
|
||||
static const unsigned short gamate_palette[4] =
|
||||
{
|
||||
0,1,2,3
|
||||
};
|
||||
@ -254,10 +258,10 @@ ATTR_UNUSED static const unsigned short gamate_palette[4] =
|
||||
/* palette in red, green, blue tribles */
|
||||
static const unsigned char gamate_colors[4][3] =
|
||||
{
|
||||
{ 255,255,255 },
|
||||
{ 0xa0, 0xa0, 0xa0 },
|
||||
{ 0x60, 0x60, 0x60 },
|
||||
{ 0, 0, 0 }
|
||||
{ 255,255,255 },
|
||||
{ 0xa0, 0xa0, 0xa0 },
|
||||
{ 0x60, 0x60, 0x60 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
PALETTE_INIT_MEMBER(gamate_state, gamate)
|
||||
@ -280,27 +284,27 @@ static void BlitPlane(UINT16* line, UINT8 plane1, UINT8 plane2)
|
||||
|
||||
UINT32 gamate_state::screen_update_gamate(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int x, y, j;
|
||||
for (y=0;y<152;y++) {
|
||||
for (x=-(video.bitmap.xpos&7), j=0;x<160;x+=8, j++) {
|
||||
UINT8 d1, d2;
|
||||
if (video.bitmap.ypos<200) {
|
||||
int x, y, j;
|
||||
for (y=0;y<152;y++) {
|
||||
for (x=-(video.bitmap.xpos&7), j=0;x<160;x+=8, j++) {
|
||||
UINT8 d1, d2;
|
||||
if (video.bitmap.ypos<200) {
|
||||
d1=video.bitmap.data[0][(y+video.bitmap.ypos)%200][(j+video.bitmap.xpos/8)&0x1f];
|
||||
d2=video.bitmap.data[1][(y+video.bitmap.ypos)%200][(j+video.bitmap.xpos/8)&0x1f];
|
||||
} else if ((video.bitmap.ypos&0xf)<8) { // lcdtest, of course still some registers not known, my gamate doesn't display bottom lines
|
||||
} else if ((video.bitmap.ypos&0xf)<8) { // lcdtest, of course still some registers not known, my gamate doesn't display bottom lines; most likely problematic 200 warp around hardware! no real usage
|
||||
int yi=(y+(video.bitmap.ypos&0xf)-8);
|
||||
if (yi<0) yi=video.bitmap.ypos+y; // in this case only 2nd plane used!?, source of first plane?
|
||||
d1=video.bitmap.data[0][yi][(j+video.bitmap.xpos/8)&0x1f]; // value of lines bevor 0 chaos
|
||||
d2=video.bitmap.data[1][yi][(j+video.bitmap.xpos/8)&0x1f];
|
||||
} else {
|
||||
} else {
|
||||
d1=video.bitmap.data[0][y][(j+video.bitmap.xpos/8)&0x1f];
|
||||
d2=video.bitmap.data[1][y][(j+video.bitmap.xpos/8)&0x1f];
|
||||
}
|
||||
BlitPlane(&bitmap.pix16(y, x+4), d1, d2);
|
||||
BlitPlane(&bitmap.pix16(y, x), d1>>4, d2>>4);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
d2=video.bitmap.data[1][y][(j+video.bitmap.xpos/8)&0x1f];
|
||||
}
|
||||
BlitPlane(&bitmap.pix16(y, x+4), d1, d2);
|
||||
BlitPlane(&bitmap.pix16(y, x), d1>>4, d2>>4);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(gamate_state,gamate)
|
||||
@ -314,11 +318,11 @@ DRIVER_INIT_MEMBER(gamate_state,gamate)
|
||||
void gamate_state::machine_start()
|
||||
{
|
||||
if (m_cart->exists()) {
|
||||
// m_maincpu->space(AS_PROGRAM).install_read_handler(0x6000, 0x6000, READ8_DELEGATE(gamate_state, gamate_cart_protection_r));
|
||||
// m_maincpu->space(AS_PROGRAM).install_read_handler(0x6000, 0x6000, READ8_DELEGATE(gamate_state, gamate_cart_protection_r));
|
||||
membank("bankmulti")->set_base(m_cart->get_rom_base()+1);
|
||||
membank("bank")->set_base(m_cart->get_rom_base()+0x4000); // bankswitched games in reality no offset
|
||||
}
|
||||
// m_bios[0xdf1]=0xea; m_bios[0xdf2]=0xea; // default bios: $47 protection readback
|
||||
// m_bios[0xdf1]=0xea; m_bios[0xdf2]=0xea; // default bios: $47 protection readback
|
||||
card_protection.set=false;
|
||||
bank_multi=0;
|
||||
card_protection.unprotected=false;
|
||||
@ -378,7 +382,7 @@ static MACHINE_CONFIG_START( gamate, gamate_state )
|
||||
MCFG_SOUND_ADD("custom", GAMATE_SND, 0)
|
||||
MCFG_SOUND_ROUTE(0, "lspeaker", 0.50)
|
||||
MCFG_SOUND_ROUTE(1, "rspeaker", 0.50)
|
||||
|
||||
|
||||
MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_linear_slot, "gamate_cart")
|
||||
MCFG_GENERIC_MANDATORY
|
||||
|
||||
@ -396,4 +400,6 @@ ROM_END
|
||||
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */
|
||||
CONS( 19??, gamate, 0, 0, gamate, gamate, gamate_state, gamate, "Bit Corp", "Gamate", GAME_IMPERFECT_SOUND)
|
||||
CONS( 19??, gamate, 0, 0, gamate, gamate, gamate_state, gamate, "Bit Corp", "Gamate", 0)
|
||||
|
||||
|
||||
|
@ -11,25 +11,6 @@
|
||||
#include "bus/generic/slot.h"
|
||||
#include "bus/generic/carts.h"
|
||||
|
||||
struct GAMATE_CHANNEL
|
||||
{
|
||||
GAMATE_CHANNEL() :
|
||||
// on(0),
|
||||
// waveform(0),
|
||||
volume(0),
|
||||
pos(0),
|
||||
size(0)
|
||||
// count(0)
|
||||
{
|
||||
}
|
||||
|
||||
int on;
|
||||
int /*waveform,*/ volume;
|
||||
int pos;
|
||||
int size;
|
||||
// int count;
|
||||
};
|
||||
|
||||
|
||||
// ======================> gamate_sound_device
|
||||
|
||||
@ -49,11 +30,46 @@ protected:
|
||||
|
||||
public:
|
||||
DECLARE_WRITE8_MEMBER( device_w );
|
||||
DECLARE_READ8_MEMBER( device_r );
|
||||
|
||||
private:
|
||||
|
||||
static const int DAConverter[];
|
||||
static int Value2Volume(int volume) { return DAConverter[volume]*1; }
|
||||
|
||||
sound_stream *m_mixer_channel;
|
||||
GAMATE_CHANNEL m_channels[3];
|
||||
struct Tone
|
||||
{
|
||||
Tone() :
|
||||
envelope_on(false),
|
||||
level(false),
|
||||
tone(false), full_cycle(false),
|
||||
volume(0),
|
||||
pos(0),
|
||||
size(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool envelope_on, level;
|
||||
bool tone/*else noise*/, full_cycle/* else square signal/pulse */;
|
||||
int volume;
|
||||
int pos, size;
|
||||
};
|
||||
enum { Right, Left, Both };
|
||||
Tone m_channels[3];
|
||||
struct Noise {
|
||||
Noise(): state(1), level(false), step(0.0), pos(0.0) {}
|
||||
int state;
|
||||
bool level;
|
||||
double step, pos;
|
||||
} noise;
|
||||
struct Envelope {
|
||||
Envelope():control(0), index(0), first(false) {}
|
||||
int control;
|
||||
int index;
|
||||
bool first;
|
||||
double step, pos;
|
||||
} envelope;
|
||||
UINT8 reg[14];
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user