Merge branch 'master' of https://github.com/mamedev/mame.git
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 4.5 KiB |
6
makefile
@ -1436,9 +1436,9 @@ $(GENDIR)/includes/SDL2:
|
||||
-$(call MKDIR,$@)
|
||||
-$(call COPY,3rdparty/SDL2/include/,$(GENDIR)/includes/SDL2)
|
||||
|
||||
$(GENDIR)/%.lh: $(SRC)/%.lay scripts/build/file2str.py | $(GEN_FOLDERS)
|
||||
@echo Converting $<...
|
||||
$(SILENT)$(PYTHON) scripts/build/file2str.py $< $@ layout_$(basename $(notdir $<))
|
||||
$(GENDIR)/%.lh: $(SRC)/%.lay scripts/build/complay.py | $(GEN_FOLDERS)
|
||||
@echo Compressing $<...
|
||||
$(SILENT)$(PYTHON) scripts/build/complay.py $< $@ layout_$(basename $(notdir $<))
|
||||
|
||||
$(SRC)/devices/cpu/m68000/m68kops.cpp: $(SRC)/devices/cpu/m68000/m68k_in.cpp $(SRC)/devices/cpu/m68000/m68kmake.cpp
|
||||
ifeq ($(TARGETOS),asmjs)
|
||||
|
@ -170,12 +170,10 @@ function hiscore.startplugin()
|
||||
|
||||
local function check_scores ( posdata )
|
||||
local r = 0;
|
||||
-- commonly the first entry will be for the entire table
|
||||
-- so it will only trigger a write once a player enters
|
||||
-- his/her name in.
|
||||
local row = positions[1];
|
||||
for i=0,row["size"]-1 do
|
||||
for ri,row in ipairs(posdata) do
|
||||
for i=0,row["size"]-1 do
|
||||
r = r + row["mem"]:read_u8( row["addr"] + i );
|
||||
end
|
||||
end
|
||||
return r;
|
||||
end
|
||||
|
71
scripts/build/complay.py
Normal file
@ -0,0 +1,71 @@
|
||||
#!/usr/bin/python
|
||||
##
|
||||
## license:BSD-3-Clause
|
||||
## copyright-holders:Aaron Giles, Andrew Gardner
|
||||
|
||||
from __future__ import with_statement
|
||||
|
||||
import sys
|
||||
import os
|
||||
import zlib
|
||||
|
||||
if len(sys.argv) < 4:
|
||||
print('Usage:')
|
||||
print(' complay <source.lay> <output.h> <varname>')
|
||||
print('')
|
||||
sys.exit(0)
|
||||
|
||||
srcfile = sys.argv[1]
|
||||
dstfile = sys.argv[2]
|
||||
varname = sys.argv[3]
|
||||
type = 'UINT8'
|
||||
|
||||
try:
|
||||
myfile = open(srcfile, 'rb')
|
||||
except IOError:
|
||||
sys.stderr.write("Unable to open source file '%s'\n" % srcfile)
|
||||
sys.exit(-1)
|
||||
|
||||
byteCount = os.path.getsize(srcfile)
|
||||
compsize = 0
|
||||
compressiontype = 1
|
||||
|
||||
try:
|
||||
dst = open(dstfile,'w')
|
||||
dst.write('const %s %s_data[] =\n{\n\t' % ( type, varname))
|
||||
offs = 0
|
||||
with open(srcfile, "rb") as src:
|
||||
while True:
|
||||
chunk = src.read(byteCount)
|
||||
if chunk:
|
||||
compchunk = zlib.compress(chunk, 9)
|
||||
compsize = len(compchunk)
|
||||
for b in compchunk:
|
||||
# For Python 2.x compatibility.
|
||||
b = ord(b)
|
||||
dst.write('%d' % b)
|
||||
offs += 1
|
||||
if offs != compsize:
|
||||
dst.write(',')
|
||||
else:
|
||||
break
|
||||
dst.write('\n\t')
|
||||
|
||||
dst.write('\n};\n')
|
||||
|
||||
except IOError:
|
||||
sys.stderr.write("Unable to open output file '%s'\n" % dstfile)
|
||||
sys.exit(-1)
|
||||
|
||||
try:
|
||||
dst.write('extern const internal_layout %s;\n' % ( varname ))
|
||||
dst.write('const internal_layout %s = { \n\t' % ( varname ))
|
||||
dst.write('%d,%d,%d,%s_data\n' % ( byteCount, compsize, compressiontype, varname ))
|
||||
dst.write('\n};\n')
|
||||
|
||||
|
||||
dst.close()
|
||||
except IOError:
|
||||
sys.stderr.write("Unable to open output file '%s'\n" % dstfile)
|
||||
sys.exit(-1)
|
||||
|
@ -53,7 +53,7 @@ end
|
||||
|
||||
function layoutbuildtask(_folder, _name)
|
||||
return { MAME_DIR .. "src/".._folder.."/".. _name ..".lay" , GEN_DIR .. _folder .. "/".._name..".lh",
|
||||
{ MAME_DIR .. "scripts/build/file2str.py" }, {"@echo Converting src/".._folder.."/".._name..".lay...", PYTHON .. " $(1) $(<) $(@) layout_".._name }};
|
||||
{ MAME_DIR .. "scripts/build/complay.py" }, {"@echo Compressing src/".._folder.."/".._name..".lay...", PYTHON .. " $(1) $(<) $(@) layout_".._name }};
|
||||
end
|
||||
|
||||
function precompiledheaders()
|
||||
|
@ -68,7 +68,7 @@ project "netlist"
|
||||
MAME_DIR .. "src/lib/netlist/analog/nld_opamps.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_solver.cpp",
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_solver.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_matrix_solver.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_matrix_solver.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct1.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct2.h",
|
||||
@ -77,6 +77,7 @@ project "netlist"
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_ms_gmres.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/mat_cr.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_ms_sm.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_ms_w.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct_lu.h",
|
||||
MAME_DIR .. "src/lib/netlist/solver/vector_base.h",
|
||||
MAME_DIR .. "src/lib/netlist/devices/nld_4020.cpp",
|
||||
|
@ -573,6 +573,19 @@ void tms9901_device::device_stop(void)
|
||||
-------------------------------------------------*/
|
||||
|
||||
void tms9901_device::device_reset(void)
|
||||
{
|
||||
do_reset();
|
||||
}
|
||||
|
||||
/*
|
||||
RST1 input line (active low; using ASSERT/CLEAR).
|
||||
*/
|
||||
WRITE_LINE_MEMBER( tms9901_device::rst1_line )
|
||||
{
|
||||
if (state==ASSERT_LINE) do_reset();
|
||||
}
|
||||
|
||||
void tms9901_device::do_reset()
|
||||
{
|
||||
m_timer_int_pending = false;
|
||||
m_enabled_ints = 0;
|
||||
|
@ -60,6 +60,8 @@ public:
|
||||
|
||||
void set_single_int(int pin_number, int state);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( rst1_line );
|
||||
|
||||
DECLARE_READ8_MEMBER( read );
|
||||
DECLARE_WRITE8_MEMBER( write );
|
||||
|
||||
@ -95,6 +97,9 @@ private:
|
||||
void device_stop(void) override;
|
||||
void device_reset(void) override;
|
||||
|
||||
// Common method for device_reset and rst1_line
|
||||
void do_reset();
|
||||
|
||||
// State of the INT1-INT15 lines (must be inverted when queried)
|
||||
// Note that the levels must also be delivered when reading the pins, which
|
||||
// may require to latch the int levels.
|
||||
|
@ -46,7 +46,55 @@
|
||||
Note the standard naming for d* data bits with 7 as MSB and 0 as LSB is in lowercase.
|
||||
TI's naming has D7 as LSB and D0 as MSB and is in uppercase
|
||||
|
||||
TMS5100:
|
||||
|
||||
+-----------------+
|
||||
TST | 1 28 | CS
|
||||
PDC | 2 27 | CTL8
|
||||
ROM CK | 3 26 | ADD8
|
||||
CPU CK | 4 25 | CTL1
|
||||
VDD | 5 24 | ADD1
|
||||
CR OSC | 6 23 | CTL2
|
||||
RC OSC | 7 22 | ADD2
|
||||
T11 | 8 21 | ADD4
|
||||
NC | 9 20 | CTL4
|
||||
I/O | 10 19 | M1
|
||||
SPK1 | 11 18 | NC
|
||||
SPK2 | 12 17 | NC
|
||||
PROM OUT | 13 16 | NC
|
||||
VSS | 14 15 | M0
|
||||
+-----------------+
|
||||
|
||||
T11: Sync for serial data out
|
||||
|
||||
|
||||
M58817
|
||||
|
||||
The following connections could be derived from radar scope schematics.
|
||||
The M58817 is not 100% pin compatible to the 5100, but really close.
|
||||
|
||||
+-----------------+
|
||||
(NC) | 1 28 | CS
|
||||
PDC | 2 27 | CTL8
|
||||
ROM CK | 3 26 | ADD8 (to 58819)
|
||||
(NC) | 4 25 | CTL1
|
||||
(VDD,-5) | 5 24 | ADD1 (to 58819)
|
||||
(GND) | 6 23 | CTL2
|
||||
Xin | 7 22 | ADD2 (to 58819)
|
||||
Xout | 8 21 | ADD4 (to 58819)
|
||||
(NC) | 9 20 | CTL4
|
||||
(VDD,-5) | 10 19 | Status back to CPU
|
||||
(NC) | 11 18 | C1 (to 58819)
|
||||
SPKR | 12 17 | (NC)
|
||||
SPKR | 13 16 | C0 (to 58819)
|
||||
(NC) | 14 15 | (5V)
|
||||
+-----------------+
|
||||
|
||||
TODO:
|
||||
5110:
|
||||
* implement CS
|
||||
* TMS5110_CMD_TEST_TALK is only partially implemented
|
||||
5220:
|
||||
* Samples repeat over and over in the 'eprom' test mode. Needs investigation.
|
||||
* Implement a ready callback for pc interfaces
|
||||
- this will be quite a challenge since for it to be really accurate
|
||||
@ -272,7 +320,7 @@ static INT16 clip_analog(INT16 cliptemp);
|
||||
/* must be defined; if 0, output the waveform as if it was tapped on the speaker pin as usual, if 1, output the waveform as if it was tapped on the i/o pin (volume is much lower in the latter case) */
|
||||
#define FORCE_DIGITAL 0
|
||||
|
||||
/* must be defined; if 1, normal speech (one A cycle, one B cycle per interpolation step); if 0; speak as if SPKSLOW was used (two A cycles, one B cycle per interpolation step) */
|
||||
/* 5220 only; must be defined; if 1, normal speech (one A cycle, one B cycle per interpolation step); if 0; speak as if SPKSLOW was used (two A cycles, one B cycle per interpolation step) */
|
||||
#define FORCE_SUBC_RELOAD 1
|
||||
|
||||
|
||||
@ -280,9 +328,9 @@ static INT16 clip_analog(INT16 cliptemp);
|
||||
#undef VERBOSE
|
||||
// above is general, somewhat obsolete, catch all for debugs which don't fit elsewhere
|
||||
#undef DEBUG_DUMP_INPUT_DATA
|
||||
// above dumps the data input to the tms52xx to stdout, useful for making logged data dumps for real hardware tests
|
||||
// 5220 only; above dumps the data written to the tms52xx to stdout, useful for making logged data dumps for real hardware tests
|
||||
#undef DEBUG_FIFO
|
||||
// above debugs fifo stuff: writes, reads and flag updates
|
||||
// 5220 only; above debugs fifo stuff: writes, reads and flag updates
|
||||
#undef DEBUG_PARSE_FRAME_DUMP
|
||||
// above dumps each frame to stderr: be sure to select one of the options below if you define it!
|
||||
#undef DEBUG_PARSE_FRAME_DUMP_BIN
|
||||
@ -310,18 +358,39 @@ static INT16 clip_analog(INT16 cliptemp);
|
||||
|
||||
#define MAX_SAMPLE_CHUNK 512
|
||||
|
||||
/* Variants */
|
||||
/* 6+4 Variants, from tms5110r.inc */
|
||||
|
||||
#define TMS5220_IS_5220C (4)
|
||||
#define TMS5220_IS_5200 (5)
|
||||
#define TMS5220_IS_5220 (6)
|
||||
#define TMS5220_IS_CD2501ECD (7)
|
||||
#define TMS5220_IS_TMC0281 (1)
|
||||
#define TMS5220_IS_TMC0281D (2)
|
||||
#define TMS5220_IS_CD2801 (3)
|
||||
#define TMS5220_IS_CD2802 (4)
|
||||
#define TMS5220_IS_TMS5110A (5)
|
||||
#define TMS5220_IS_M58817 (6)
|
||||
#define TMS5220_IS_5220C (7)
|
||||
#define TMS5220_IS_5200 (8)
|
||||
#define TMS5220_IS_5220 (9)
|
||||
#define TMS5220_IS_CD2501ECD (10)
|
||||
|
||||
#define TMS5220_IS_CD2501E TMS5220_IS_5200
|
||||
|
||||
// 52xx: decide whether we have rate control or not
|
||||
#define TMS5220_HAS_RATE_CONTROL ((m_variant == TMS5220_IS_5220C) || (m_variant == TMS5220_IS_CD2501ECD))
|
||||
|
||||
// All: decide whether we are a 51xx or a 52xx
|
||||
#define TMS5220_IS_52xx ((m_variant == TMS5220_IS_5220C) || (m_variant == TMS5220_IS_5200) || (m_variant == TMS5220_IS_5220) || (m_variant == TMS5220_IS_CD2501ECD))
|
||||
|
||||
/* 51xx: States for CTL */
|
||||
// ctl bus is input to tms51xx
|
||||
#define CTL_STATE_INPUT (0)
|
||||
// ctl bus is outputting a test talk command on CTL1(bit 0)
|
||||
#define CTL_STATE_TTALK_OUTPUT (1)
|
||||
// ctl bus is switching direction, next will be above
|
||||
#define CTL_STATE_NEXT_TTALK_OUTPUT (2)
|
||||
// ctl bus is outputting a read nybble 'output' command on CTL1,2,4,8 (bits 0-3)
|
||||
#define CTL_STATE_OUTPUT (3)
|
||||
// ctl bus is switching direction, next will be above
|
||||
#define CTL_STATE_NEXT_OUTPUT (4)
|
||||
|
||||
static const UINT8 reload_table[4] = { 0, 2, 4, 6 }; //sample count reload for 5220c and cd2501ecd only; 5200 and 5220 always reload with 0; keep in mind this is loaded on IP=0 PC=12 subcycle=1 so it immediately will increment after one sample, effectively being 1,3,5,7 as in the comments above.
|
||||
|
||||
// Pull in the ROM tables
|
||||
@ -332,6 +401,24 @@ void tms5220_device::set_variant(int variant)
|
||||
{
|
||||
switch (variant)
|
||||
{
|
||||
case TMS5220_IS_TMC0281:
|
||||
m_coeff = &T0280B_0281A_coeff;
|
||||
break;
|
||||
case TMS5220_IS_TMC0281D:
|
||||
m_coeff = &T0280D_0281D_coeff;
|
||||
break;
|
||||
case TMS5220_IS_CD2801:
|
||||
m_coeff = &T0280F_2801A_coeff;
|
||||
break;
|
||||
case TMS5220_IS_M58817:
|
||||
m_coeff = &M58817_coeff;
|
||||
break;
|
||||
case TMS5220_IS_CD2802:
|
||||
m_coeff = &T0280F_2802_coeff;
|
||||
break;
|
||||
case TMS5220_IS_TMS5110A:
|
||||
m_coeff = &tms5110a_coeff;
|
||||
break;
|
||||
case TMS5220_IS_5200:
|
||||
case TMS5220_IS_CD2501ECD:
|
||||
m_coeff = &T0285_2501E_coeff;
|
||||
@ -458,7 +545,59 @@ static void printbits(long data, int num)
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
tms5220_data_write -- handle a write to the TMS5220
|
||||
tms5220_device::new_int_write -- wrap a write to the VSM
|
||||
|
||||
***********************************************************************************************/
|
||||
void tms5220_device::new_int_write(UINT8 rc, UINT8 m0, UINT8 m1, UINT8 addr)
|
||||
{
|
||||
if (!m_m0_cb.isnull())
|
||||
m_m0_cb(m0);
|
||||
if (!m_m1_cb.isnull())
|
||||
m_m1_cb(m1);
|
||||
if (!m_addr_cb.isnull())
|
||||
m_addr_cb((offs_t)0, addr);
|
||||
if (!m_romclk_cb.isnull())
|
||||
{
|
||||
//printf("rc %d\n", rc);
|
||||
m_romclk_cb(rc);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
tms5220_device::new_int_write_addr -- wrap a 'load address' set of writes to the VSM
|
||||
|
||||
***********************************************************************************************/
|
||||
void tms5220_device::new_int_write_addr(UINT8 addr)
|
||||
{
|
||||
new_int_write(1, 0, 1, addr); // romclk 1, m0 0, m1 1, addr bus nybble = xxxx
|
||||
new_int_write(0, 0, 1, addr); // romclk 0, m0 0, m1 1, addr bus nybble = xxxx
|
||||
new_int_write(1, 0, 0, addr); // romclk 1, m0 0, m1 0, addr bus nybble = xxxx
|
||||
new_int_write(0, 0, 0, addr); // romclk 0, m0 0, m1 0, addr bus nybble = xxxx
|
||||
}
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
tms5220_device::new_int_write_addr -- wrap a 'read bit' set of writes to the VSM
|
||||
|
||||
***********************************************************************************************/
|
||||
UINT8 tms5220_device::new_int_read()
|
||||
{
|
||||
new_int_write(1, 1, 0, 0); // romclk 1, m0 1, m1 0, addr bus nybble = 0/open bus
|
||||
new_int_write(0, 1, 0, 0); // romclk 0, m0 1, m1 0, addr bus nybble = 0/open bus
|
||||
new_int_write(1, 0, 0, 0); // romclk 1, m0 0, m1 0, addr bus nybble = 0/open bus
|
||||
new_int_write(0, 0, 0, 0); // romclk 0, m0 0, m1 0, addr bus nybble = 0/open bus
|
||||
if (!m_data_cb.isnull())
|
||||
return m_data_cb();
|
||||
#ifdef VERBOSE
|
||||
logerror("WARNING: CALLBACK MISSING, RETURNING 0!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
tms5220_device::data_write -- handle a write to the TMS5220
|
||||
|
||||
***********************************************************************************************/
|
||||
|
||||
@ -626,13 +765,39 @@ int tms5220_device::extract_bits(int count)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef USE_NEW_TMS6100_CODE
|
||||
/** TODO: get rid of this old code */
|
||||
// extract from VSM (speech ROM)
|
||||
if (m_speechrom)
|
||||
val = m_speechrom->read(count);
|
||||
#else
|
||||
while (count--)
|
||||
{
|
||||
val = (val << 1) | new_int_read();
|
||||
#ifdef VERBOSE
|
||||
logerror("bit read: %d\n", val&1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/** TODO: dummy reads should be auto-done for tms52xx for the first read after an address load, but not tms51xx where they need to be done manually, if needed */
|
||||
void tms5220_device::perform_dummy_read()
|
||||
{
|
||||
if (m_schedule_dummy_read)
|
||||
{
|
||||
#ifdef VERBOSE
|
||||
int data = new_int_read();
|
||||
logerror("TMS5110 performing dummy read; value read = %1i\n", data & 1);
|
||||
#else
|
||||
new_int_read();
|
||||
#endif
|
||||
m_schedule_dummy_read = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
tms5220_status_read -- read status or data from the TMS5220
|
||||
@ -1470,9 +1635,14 @@ void tms5220_device::device_start()
|
||||
set_variant(TMS5220_IS_5220);
|
||||
m_clock = clock();
|
||||
|
||||
/* resolve irq and readyq line */
|
||||
/* resolve callbacks */
|
||||
m_irq_handler.resolve();
|
||||
m_readyq_handler.resolve();
|
||||
m_m0_cb.resolve();
|
||||
m_m1_cb.resolve();
|
||||
m_romclk_cb.resolve();
|
||||
m_addr_cb.resolve();
|
||||
m_data_cb.resolve();
|
||||
|
||||
/* initialize a stream */
|
||||
m_stream = machine().sound().stream_alloc(*this, 0, 1, clock() / 80);
|
||||
@ -1917,7 +2087,12 @@ tms5220_device::tms5220_device(const machine_config &mconfig, const char *tag, d
|
||||
device_sound_interface(mconfig, *this),
|
||||
m_irq_handler(*this),
|
||||
m_readyq_handler(*this),
|
||||
m_speechrom_tag(nullptr)
|
||||
m_speechrom_tag(nullptr),
|
||||
m_m0_cb(*this),
|
||||
m_m1_cb(*this),
|
||||
m_addr_cb(*this),
|
||||
m_data_cb(*this),
|
||||
m_romclk_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1926,7 +2101,12 @@ tms5220_device::tms5220_device(const machine_config &mconfig, device_type type,
|
||||
device_sound_interface(mconfig, *this),
|
||||
m_irq_handler(*this),
|
||||
m_readyq_handler(*this),
|
||||
m_speechrom_tag(nullptr)
|
||||
m_speechrom_tag(nullptr),
|
||||
m_m0_cb(*this),
|
||||
m_m1_cb(*this),
|
||||
m_addr_cb(*this),
|
||||
m_data_cb(*this),
|
||||
m_romclk_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -25,9 +25,25 @@
|
||||
#define MCFG_TMS52XX_READYQ_HANDLER(_devcb) \
|
||||
devcb = &tms5220_device::set_readyq_handler(*device, DEVCB_##_devcb);
|
||||
|
||||
/* old VSM handler, remove me! */
|
||||
#define MCFG_TMS52XX_SPEECHROM(_tag) \
|
||||
tms5220_device::set_speechrom_tag(*device, _tag);
|
||||
|
||||
/* new VSM handler */
|
||||
#define MCFG_TMS52XX_M0_CB(_devcb) \
|
||||
devcb = &tms5220_device::set_m0_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_TMS52XX_M1_CB(_devcb) \
|
||||
devcb = &tms5220_device::set_m1_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_TMS52XX_ADDR_CB(_devcb) \
|
||||
devcb = &tms5220_device::set_addr_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_TMS52XX_DATA_CB(_devcb) \
|
||||
devcb = &tms5220_device::set_data_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_TMS52XX_ROMCLK_CB(_devcb) \
|
||||
devcb = &tms5220_device::set_romclk_callback(*device, DEVCB_##_devcb);
|
||||
class tms5220_device : public device_t,
|
||||
public device_sound_interface
|
||||
{
|
||||
@ -38,7 +54,14 @@ public:
|
||||
// static configuration helpers
|
||||
template<class _Object> static devcb_base &set_irq_handler(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_irq_handler.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_readyq_handler(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_readyq_handler.set_callback(object); }
|
||||
// old VSM support, remove me!
|
||||
static void set_speechrom_tag(device_t &device, const char *_tag) { downcast<tms5220_device &>(device).m_speechrom_tag = _tag; }
|
||||
// new VSM support
|
||||
template<class _Object> static devcb_base &set_m0_callback(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_m0_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_m1_callback(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_m1_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_addr_callback(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_addr_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_data_callback(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_data_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_romclk_callback(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_romclk_cb.set_callback(object); }
|
||||
|
||||
/* Control lines - once written to will switch interface into
|
||||
* "true" timing behaviour.
|
||||
@ -73,6 +96,12 @@ protected:
|
||||
void set_variant(int variant);
|
||||
|
||||
private:
|
||||
// 51xx and VSM related
|
||||
void new_int_write(UINT8 rc, UINT8 m0, UINT8 m1, UINT8 addr);
|
||||
void new_int_write_addr(UINT8 addr);
|
||||
UINT8 new_int_read();
|
||||
void perform_dummy_read();
|
||||
// 52xx or common
|
||||
void register_for_save_states();
|
||||
void data_write(int data);
|
||||
void update_fifo_status_and_ints();
|
||||
@ -96,6 +125,24 @@ private:
|
||||
/* coefficient tables */
|
||||
const struct tms5100_coeffs *m_coeff;
|
||||
|
||||
/* these contain global status bits */
|
||||
UINT8 m_PDC;
|
||||
UINT8 m_CTL_pins;
|
||||
UINT8 m_state;
|
||||
|
||||
/* New VSM interface */
|
||||
UINT32 m_address;
|
||||
UINT8 m_next_is_address;
|
||||
UINT8 m_schedule_dummy_read;
|
||||
UINT8 m_addr_bit;
|
||||
/* read byte */
|
||||
UINT8 m_CTL_buffer;
|
||||
|
||||
/* Old VSM interface; R Nabet : These have been added to emulate speech Roms */
|
||||
//UINT8 m_schedule_dummy_read; /* set after each load address, so that next read operation is preceded by a dummy read */
|
||||
UINT8 m_data_register; /* data register, used by read command */
|
||||
UINT8 m_RDB_flag; /* whether we should read data register or status register */
|
||||
|
||||
/* these contain data that describes the 128-bit data FIFO */
|
||||
UINT8 m_fifo[FIFO_SIZE];
|
||||
UINT8 m_fifo_head;
|
||||
@ -167,11 +214,6 @@ private:
|
||||
UINT16 m_RNG; /* the random noise generator configuration is: 1 + x + x^3 + x^4 + x^13 TODO: no it isn't */
|
||||
INT16 m_excitation_data;
|
||||
|
||||
/* R Nabet : These have been added to emulate speech Roms */
|
||||
UINT8 m_schedule_dummy_read; /* set after each load address, so that next read operation is preceded by a dummy read */
|
||||
UINT8 m_data_register; /* data register, used by read command */
|
||||
UINT8 m_RDB_flag; /* whether we should read data register or status register */
|
||||
|
||||
/* The TMS52xx has two different ways of providing output data: the
|
||||
analog speaker pin (which was usually used) and the Digital I/O pin.
|
||||
The internal DAC used to feed the analog pin is only 8 bits, and has the
|
||||
@ -201,8 +243,18 @@ private:
|
||||
/* callbacks */
|
||||
devcb_write_line m_irq_handler;
|
||||
devcb_write_line m_readyq_handler;
|
||||
// next 2 lines are old speechrom handler, remove me!
|
||||
const char *m_speechrom_tag;
|
||||
speechrom_device *m_speechrom;
|
||||
// next lines are new speechrom handler
|
||||
devcb_write_line m_m0_cb; // the M0 line
|
||||
devcb_write_line m_m1_cb; // the M1 line
|
||||
devcb_write8 m_addr_cb; // Write to ADD1,2,4,8 - 4 address bits
|
||||
devcb_read_line m_data_cb; // Read one bit from ADD8/Data - voice data
|
||||
// On a real chip rom_clk is running all the time
|
||||
// Here, we only use it to properly emulate the protocol.
|
||||
// Do not rely on it to be a timed signal.
|
||||
devcb_write_line m_romclk_cb; // rom clock - Only used to drive the data lines
|
||||
};
|
||||
|
||||
extern const device_type TMS5220;
|
||||
|
@ -59,6 +59,7 @@ tms9928a_device::tms9928a_device( const machine_config &mconfig, device_type typ
|
||||
device_memory_interface(mconfig, *this),
|
||||
device_video_interface(mconfig, *this),
|
||||
m_out_int_line_cb(*this),
|
||||
m_out_gromclk_cb(*this),
|
||||
m_space_config("vram",ENDIANNESS_BIG, 8, 14, 0, nullptr, *ADDRESS_MAP_NAME(memmap))
|
||||
{
|
||||
m_50hz = is_50hz;
|
||||
@ -74,6 +75,7 @@ tms9928a_device::tms9928a_device( const machine_config &mconfig, const char *tag
|
||||
device_video_interface(mconfig, *this),
|
||||
m_vram_size(0),
|
||||
m_out_int_line_cb(*this),
|
||||
m_out_gromclk_cb(*this),
|
||||
m_space_config("vram",ENDIANNESS_BIG, 8, 14, 0, nullptr, *ADDRESS_MAP_NAME(memmap))
|
||||
{
|
||||
m_50hz = false;
|
||||
@ -302,6 +304,15 @@ WRITE8_MEMBER( tms9928a_device::register_write )
|
||||
|
||||
void tms9928a_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
// Handle GROM clock if present
|
||||
if (id==GROMCLK)
|
||||
{
|
||||
// Pulse it
|
||||
m_out_gromclk_cb(ASSERT_LINE);
|
||||
m_out_gromclk_cb(CLEAR_LINE);
|
||||
return;
|
||||
}
|
||||
|
||||
int raw_vpos = m_screen->vpos();
|
||||
int vpos = raw_vpos * m_vertical_size / m_screen->height();
|
||||
UINT16 BackColour = m_Regs[7] & 15;
|
||||
@ -669,6 +680,7 @@ void tms9928a_device::device_start()
|
||||
m_vertical_size = m_50hz ? TMS9928A_TOTAL_VERT_PAL : TMS9928A_TOTAL_VERT_NTSC;
|
||||
|
||||
m_out_int_line_cb.resolve();
|
||||
m_out_gromclk_cb.resolve();
|
||||
|
||||
// Video RAM is allocated as an own address space
|
||||
m_vram_space = &space(AS_DATA);
|
||||
@ -677,6 +689,7 @@ void tms9928a_device::device_start()
|
||||
m_tmpbmp.allocate(TMS9928A_TOTAL_HORZ, TMS9928A_TOTAL_VERT_PAL);
|
||||
|
||||
m_line_timer = timer_alloc(TIMER_LINE);
|
||||
m_gromclk_timer = timer_alloc(GROMCLK);
|
||||
|
||||
set_palette();
|
||||
|
||||
@ -728,4 +741,7 @@ void tms9928a_device::device_reset()
|
||||
m_mode = 0;
|
||||
|
||||
m_line_timer->adjust( m_screen->time_until_pos( 0, TMS9928A_HORZ_DISPLAY_START ) );
|
||||
|
||||
// TODO: Check clock freq settings in all drivers
|
||||
if (!m_out_gromclk_cb.isnull() && m_99) m_gromclk_timer->adjust(attotime::zero, 0, attotime::from_hz(clock()/12));
|
||||
}
|
||||
|
@ -51,6 +51,9 @@
|
||||
|
||||
#define MCFG_TMS9928A_SET_SCREEN MCFG_VIDEO_SET_SCREEN
|
||||
|
||||
#define MCFG_TMS9928A_OUT_GROMCLK_CB(_devcb) \
|
||||
devcb = &tms9928a_device::set_out_gromclk_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
|
||||
#define MCFG_TMS9928A_SCREEN_ADD_NTSC(_screen_tag) \
|
||||
MCFG_VIDEO_SET_SCREEN(_screen_tag) \
|
||||
@ -87,6 +90,7 @@ public:
|
||||
|
||||
static void set_vram_size(device_t &device, int vram_size) { downcast<tms9928a_device &>(device).m_vram_size = vram_size; }
|
||||
template<class _Object> static devcb_base &set_out_int_line_callback(device_t &device, _Object object) { return downcast<tms9928a_device &>(device).m_out_int_line_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_out_gromclk_callback(device_t &device, _Object object) { return downcast<tms9928a_device &>(device).m_out_gromclk_cb.set_callback(object); }
|
||||
|
||||
DECLARE_READ8_MEMBER( vram_read );
|
||||
DECLARE_WRITE8_MEMBER( vram_write );
|
||||
@ -117,9 +121,11 @@ private:
|
||||
void set_palette();
|
||||
|
||||
static const device_timer_id TIMER_LINE = 0;
|
||||
static const device_timer_id GROMCLK = 1;
|
||||
|
||||
int m_vram_size; /* 4K, 8K, or 16K. This should be replaced by fetching data from an address space? */
|
||||
devcb_write_line m_out_int_line_cb; /* Callback is called whenever the state of the INT output changes */
|
||||
devcb_write_line m_out_gromclk_cb; // GROMCLK line is optional; if present, pulse it by XTAL/24 rate
|
||||
|
||||
/* TMS9928A internal settings */
|
||||
UINT8 m_ReadAhead;
|
||||
@ -147,6 +153,7 @@ private:
|
||||
|
||||
bitmap_rgb32 m_tmpbmp;
|
||||
emu_timer *m_line_timer;
|
||||
emu_timer *m_gromclk_timer;
|
||||
UINT8 m_mode;
|
||||
|
||||
/* emulation settings */
|
||||
|
@ -74,7 +74,7 @@ struct game_driver
|
||||
const rom_entry * rom; // pointer to list of ROMs for the game
|
||||
const char * compatible_with;
|
||||
UINT32 flags; // orientation and other flags; see defines below
|
||||
const char * default_layout; // default internally defined layout
|
||||
const internal_layout * default_layout; // default internally defined layout
|
||||
};
|
||||
|
||||
|
||||
@ -95,7 +95,22 @@ struct game_driver
|
||||
|
||||
// standard GAME() macro
|
||||
#define GAME(YEAR,NAME,PARENT,MACHINE,INPUT,CLASS,INIT,MONITOR,COMPANY,FULLNAME,FLAGS) \
|
||||
GAMEL(YEAR,NAME,PARENT,MACHINE,INPUT,CLASS,INIT,MONITOR,COMPANY,FULLNAME,FLAGS,((const char *)0))
|
||||
extern const game_driver GAME_NAME(NAME) = \
|
||||
{ \
|
||||
__FILE__, \
|
||||
#PARENT, \
|
||||
#NAME, \
|
||||
FULLNAME, \
|
||||
#YEAR, \
|
||||
COMPANY, \
|
||||
MACHINE_CONFIG_NAME(MACHINE), \
|
||||
INPUT_PORTS_NAME(INPUT), \
|
||||
&driver_device::driver_init_wrapper<CLASS, &CLASS::init_##INIT>, \
|
||||
ROM_NAME(NAME), \
|
||||
nullptr, \
|
||||
(MONITOR)|(FLAGS)|MACHINE_TYPE_ARCADE, \
|
||||
nullptr \
|
||||
};
|
||||
|
||||
// standard macro with additional layout
|
||||
#define GAMEL(YEAR,NAME,PARENT,MACHINE,INPUT,CLASS,INIT,MONITOR,COMPANY,FULLNAME,FLAGS,LAYOUT) \
|
||||
@ -111,9 +126,9 @@ extern const game_driver GAME_NAME(NAME) = \
|
||||
INPUT_PORTS_NAME(INPUT), \
|
||||
&driver_device::driver_init_wrapper<CLASS, &CLASS::init_##INIT>, \
|
||||
ROM_NAME(NAME), \
|
||||
NULL, \
|
||||
nullptr, \
|
||||
(MONITOR)|(FLAGS)|MACHINE_TYPE_ARCADE, \
|
||||
&LAYOUT[0] \
|
||||
&LAYOUT \
|
||||
};
|
||||
|
||||
// standard console definition macro
|
||||
@ -132,7 +147,7 @@ extern const game_driver GAME_NAME(NAME) = \
|
||||
ROM_NAME(NAME), \
|
||||
#COMPAT, \
|
||||
ROT0|(FLAGS)|MACHINE_TYPE_CONSOLE, \
|
||||
NULL \
|
||||
nullptr \
|
||||
};
|
||||
|
||||
// standard computer definition macro
|
||||
@ -151,7 +166,7 @@ extern const game_driver GAME_NAME(NAME) = \
|
||||
ROM_NAME(NAME), \
|
||||
#COMPAT, \
|
||||
ROT0|(FLAGS)|MACHINE_TYPE_COMPUTER, \
|
||||
NULL \
|
||||
nullptr \
|
||||
};
|
||||
|
||||
// standard system definition macro
|
||||
@ -170,7 +185,7 @@ extern const game_driver GAME_NAME(NAME) = \
|
||||
ROM_NAME(NAME), \
|
||||
#COMPAT, \
|
||||
ROT0|(FLAGS)|MACHINE_TYPE_OTHER, \
|
||||
NULL \
|
||||
nullptr \
|
||||
};
|
||||
|
||||
|
||||
|
@ -36,6 +36,15 @@ struct gfx_decode_entry;
|
||||
class driver_device;
|
||||
class screen_device;
|
||||
|
||||
struct internal_layout
|
||||
{
|
||||
size_t decompressed_size;
|
||||
size_t compressed_size;
|
||||
UINT8 compression_type;
|
||||
const UINT8* data;
|
||||
};
|
||||
|
||||
|
||||
// ======================> machine_config
|
||||
|
||||
// machine configuration definition
|
||||
@ -66,7 +75,7 @@ public:
|
||||
bool m_force_no_drc; // whether or not to force DRC off
|
||||
|
||||
// other parameters
|
||||
const char * m_default_layout; // default layout for this machine
|
||||
const internal_layout * m_default_layout; // default layout for this machine
|
||||
|
||||
// helpers during configuration; not for general use
|
||||
device_t *device_add(device_t *owner, const char *tag, device_type type, UINT32 clock);
|
||||
@ -201,7 +210,7 @@ References an external machine config.
|
||||
|
||||
// core video parameters
|
||||
#define MCFG_DEFAULT_LAYOUT(_layout) \
|
||||
config.m_default_layout = &(_layout)[0];
|
||||
config.m_default_layout = &(_layout);
|
||||
|
||||
// add/remove devices
|
||||
#define MCFG_DEVICE_ADD(_tag, _type, _clock) \
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "drivenum.h"
|
||||
#include "xmlfile.h"
|
||||
#include "ui/ui.h"
|
||||
#include <zlib.h>
|
||||
|
||||
|
||||
|
||||
@ -906,7 +907,7 @@ render_container::user_settings::user_settings()
|
||||
// render_target - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
render_target::render_target(render_manager &manager, const char *layoutfile, UINT32 flags)
|
||||
render_target::render_target(render_manager &manager, const internal_layout *layoutfile, UINT32 flags)
|
||||
: m_next(nullptr),
|
||||
m_manager(manager),
|
||||
m_curview(nullptr),
|
||||
@ -1548,7 +1549,7 @@ void render_target::update_layer_config()
|
||||
// given render target
|
||||
//-------------------------------------------------
|
||||
|
||||
void render_target::load_layout_files(const char *layoutfile, bool singlefile)
|
||||
void render_target::load_layout_files(const internal_layout *layoutfile, bool singlefile)
|
||||
{
|
||||
bool have_default = false;
|
||||
// if there's an explicit file, load that first
|
||||
@ -1587,34 +1588,34 @@ void render_target::load_layout_files(const char *layoutfile, bool singlefile)
|
||||
if (screens == 1)
|
||||
{
|
||||
if (system.flags & ORIENTATION_SWAP_XY)
|
||||
load_layout_file(nullptr, layout_vertical);
|
||||
load_layout_file(nullptr, &layout_vertical);
|
||||
else
|
||||
load_layout_file(nullptr, layout_horizont);
|
||||
load_layout_file(nullptr, &layout_horizont);
|
||||
assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
|
||||
}
|
||||
if (!have_default)
|
||||
{
|
||||
if (screens == 0)
|
||||
{
|
||||
load_layout_file(nullptr, layout_noscreens);
|
||||
load_layout_file(nullptr, &layout_noscreens);
|
||||
assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
|
||||
}
|
||||
else
|
||||
if (screens == 2)
|
||||
{
|
||||
load_layout_file(nullptr, layout_dualhsxs);
|
||||
load_layout_file(nullptr, &layout_dualhsxs);
|
||||
assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
|
||||
}
|
||||
else
|
||||
if (screens == 3)
|
||||
{
|
||||
load_layout_file(nullptr, layout_triphsxs);
|
||||
load_layout_file(nullptr, &layout_triphsxs);
|
||||
assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
|
||||
}
|
||||
else
|
||||
if (screens == 4)
|
||||
{
|
||||
load_layout_file(nullptr, layout_quadhsxs);
|
||||
load_layout_file(nullptr, &layout_quadhsxs);
|
||||
assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
|
||||
}
|
||||
}
|
||||
@ -1626,6 +1627,55 @@ void render_target::load_layout_files(const char *layoutfile, bool singlefile)
|
||||
// and append it to our list
|
||||
//-------------------------------------------------
|
||||
|
||||
|
||||
bool render_target::load_layout_file(const char *dirname, const internal_layout *layout_data)
|
||||
{
|
||||
// +1 to ensure data is terminated for XML parser
|
||||
auto tempout = make_unique_clear<UINT8[]>(layout_data->decompressed_size+1);
|
||||
|
||||
z_stream stream;
|
||||
int zerr;
|
||||
|
||||
/* initialize the stream */
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
stream.next_out = tempout.get();
|
||||
stream.avail_out = layout_data->decompressed_size;
|
||||
|
||||
|
||||
zerr = inflateInit(&stream);
|
||||
if (zerr != Z_OK)
|
||||
{
|
||||
fatalerror("could not inflateInit");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* decompress this chunk */
|
||||
stream.next_in = (unsigned char*)layout_data->data;
|
||||
stream.avail_in = layout_data->compressed_size;
|
||||
zerr = inflate(&stream, Z_NO_FLUSH);
|
||||
|
||||
/* stop at the end of the stream */
|
||||
if (zerr == Z_STREAM_END)
|
||||
{
|
||||
// OK
|
||||
}
|
||||
else if (zerr != Z_OK)
|
||||
{
|
||||
fatalerror("decompression error\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
zerr = inflateEnd(&stream);
|
||||
if (zerr != Z_OK)
|
||||
{
|
||||
fatalerror("inflateEnd error\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return load_layout_file(dirname, (const char*)tempout.get());
|
||||
}
|
||||
|
||||
bool render_target::load_layout_file(const char *dirname, const char *filename)
|
||||
{
|
||||
// if the first character of the "file" is an open brace, assume it is an XML string
|
||||
@ -2529,7 +2579,7 @@ float render_manager::max_update_rate() const
|
||||
// target_alloc - allocate a new target
|
||||
//-------------------------------------------------
|
||||
|
||||
render_target *render_manager::target_alloc(const char *layoutfile, UINT32 flags)
|
||||
render_target *render_manager::target_alloc(const internal_layout *layoutfile, UINT32 flags)
|
||||
{
|
||||
return &m_targetlist.append(*global_alloc(render_target(*this, layoutfile, flags)));
|
||||
}
|
||||
|
@ -888,7 +888,7 @@ class render_target
|
||||
friend class render_manager;
|
||||
|
||||
// construction/destruction
|
||||
render_target(render_manager &manager, const char *layoutfile = nullptr, UINT32 flags = 0);
|
||||
render_target(render_manager &manager, const internal_layout *layoutfile = nullptr, UINT32 flags = 0);
|
||||
~render_target();
|
||||
|
||||
public:
|
||||
@ -966,8 +966,9 @@ public:
|
||||
private:
|
||||
// internal helpers
|
||||
void update_layer_config();
|
||||
void load_layout_files(const char *layoutfile, bool singlefile);
|
||||
void load_layout_files(const internal_layout *layoutfile, bool singlefile);
|
||||
bool load_layout_file(const char *dirname, const char *filename);
|
||||
bool load_layout_file(const char *dirname, const internal_layout *layout_data);
|
||||
void add_container_primitives(render_primitive_list &list, const object_transform &xform, render_container &container, int blendmode);
|
||||
void add_element_primitives(render_primitive_list &list, const object_transform &xform, layout_element &element, int state, int blendmode);
|
||||
bool map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, ioport_port *&mapped_input_port, ioport_value &mapped_input_mask);
|
||||
@ -1044,7 +1045,7 @@ public:
|
||||
float max_update_rate() const;
|
||||
|
||||
// targets
|
||||
render_target *target_alloc(const char *layoutfile = nullptr, UINT32 flags = 0);
|
||||
render_target *target_alloc(const internal_layout *layoutfile = nullptr, UINT32 flags = 0);
|
||||
void target_free(render_target *target);
|
||||
render_target *first_target() const { return m_targetlist.first(); }
|
||||
render_target *target_by_index(int index) const;
|
||||
|
@ -16,26 +16,26 @@
|
||||
//**************************************************************************
|
||||
|
||||
// no screens layouts
|
||||
extern const char layout_noscreens[]; // for screenless systems
|
||||
extern const internal_layout layout_noscreens; // for screenless systems
|
||||
|
||||
// single screen layouts
|
||||
extern const char layout_horizont[]; // horizontal 4:3 screens
|
||||
extern const char layout_vertical[]; // vertical 4:3 screens
|
||||
extern const internal_layout layout_horizont; // horizontal 4:3 screens
|
||||
extern const internal_layout layout_vertical; // vertical 4:3 screens
|
||||
|
||||
// dual screen layouts
|
||||
extern const char layout_dualhsxs[]; // dual 4:3 screens side-by-side
|
||||
extern const char layout_dualhovu[]; // dual 4:3 screens above and below
|
||||
extern const char layout_dualhuov[]; // dual 4:3 screens below and above
|
||||
extern const internal_layout layout_dualhsxs; // dual 4:3 screens side-by-side
|
||||
extern const internal_layout layout_dualhovu; // dual 4:3 screens above and below
|
||||
extern const internal_layout layout_dualhuov; // dual 4:3 screens below and above
|
||||
|
||||
// triple screen layouts
|
||||
extern const char layout_triphsxs[]; // triple 4:3 screens side-by-side
|
||||
extern const internal_layout layout_triphsxs; // triple 4:3 screens side-by-side
|
||||
|
||||
// quad screen layouts
|
||||
extern const char layout_quadhsxs[]; // quad 4:3 screens side-by-side
|
||||
extern const internal_layout layout_quadhsxs; // quad 4:3 screens side-by-side
|
||||
|
||||
// LCD screen layouts
|
||||
extern const char layout_lcd[]; // generic 1:1 lcd screen layout
|
||||
extern const char layout_lcd_rot[]; // same, for use with ROT90 or ROT270
|
||||
extern const internal_layout layout_lcd; // generic 1:1 lcd screen layout
|
||||
extern const internal_layout layout_lcd_rot; // same, for use with ROT90 or ROT270
|
||||
|
||||
|
||||
#endif // __RENDLAY_H__
|
||||
|
@ -130,7 +130,7 @@ video_manager::video_manager(running_machine &machine)
|
||||
// the native target is hard-coded to our internal layout and has all options disabled
|
||||
if (m_snap_native)
|
||||
{
|
||||
m_snap_target = machine.render().target_alloc(layout_snap, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN);
|
||||
m_snap_target = machine.render().target_alloc(&layout_snap, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN);
|
||||
m_snap_target->set_backdrops_enabled(false);
|
||||
m_snap_target->set_overlays_enabled(false);
|
||||
m_snap_target->set_bezels_enabled(false);
|
||||
|
@ -596,7 +596,7 @@ int matrix_solver_w_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const bool
|
||||
}
|
||||
/* Back substitution */
|
||||
//inv(H) w = t w = H t
|
||||
nl_double *t=new nl_double[rowcount];
|
||||
nl_double *t = new nl_double[rowcount];
|
||||
for (int j = rowcount - 1; j >= 0; j--)
|
||||
{
|
||||
nl_double tmp = 0;
|
||||
@ -619,6 +619,7 @@ int matrix_solver_w_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const bool
|
||||
}
|
||||
new_V[i] -= tmp;
|
||||
}
|
||||
delete[] t;
|
||||
}
|
||||
}
|
||||
m_cnt++;
|
||||
|
@ -66,8 +66,9 @@ The following MCU images were tested on an original Arkanoid PCB using sets
|
||||
(2) MCU image with CRC 0x515d77b6 <- this is a blackbox-reverse engineered bootleg MCU written by pirates
|
||||
|
||||
An MCU found on a Tournament Arkanoid PCB was an unprotected type MC68705P3
|
||||
and when read the CRC matched (1). So we can assume the MCUs for Arkanoid and
|
||||
and when read the CRC matched (1). So we assumed the MCUs for Arkanoid and
|
||||
Tournament Arkanoid are the same.... or are at least interchangeable and work.
|
||||
This turns out not to be the case, in retrospect.
|
||||
|
||||
"Tetris (D.R. Korea)" in MAME is a hack on an original Arkanoid PCB.
|
||||
The hack can be undone and returned to Arkanoid simply by removing the mod
|
||||
|
@ -1251,16 +1251,6 @@ ADDRESS_MAP_END
|
||||
|
||||
|
||||
|
||||
/*************************** layout ********************************/
|
||||
|
||||
static const char layout_hp48gx[] = "hp48gx";
|
||||
static const char layout_hp48g [] = "hp48g";
|
||||
static const char layout_hp48gp[] = "hp48gp";
|
||||
static const char layout_hp48sx[] = "hp48sx";
|
||||
static const char layout_hp48s [] = "hp48s";
|
||||
static const char layout_hp49g [] = "hp49g";
|
||||
|
||||
|
||||
/*************************** driver ********************************/
|
||||
|
||||
|
||||
@ -1297,7 +1287,6 @@ MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( hp48gx, hp48_common )
|
||||
MCFG_MACHINE_START_OVERRIDE (hp48_state, hp48gx )
|
||||
MCFG_DEFAULT_LAYOUT ( layout_hp48gx )
|
||||
|
||||
/* expansion ports */
|
||||
MCFG_HP48_PORT_ADD ( "port1", 0, HP48_CE2, 128*1024 )
|
||||
@ -1310,7 +1299,6 @@ MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( hp48g, hp48_common )
|
||||
MCFG_MACHINE_START_OVERRIDE (hp48_state, hp48g )
|
||||
MCFG_DEFAULT_LAYOUT ( layout_hp48g )
|
||||
|
||||
/* serial I/O */
|
||||
//MCFG_XMODEM_ADD( "rs232_x", hp48_xmodem_rs232_conf )
|
||||
@ -1320,7 +1308,6 @@ MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( hp48gp, hp48_common )
|
||||
MCFG_MACHINE_START_OVERRIDE (hp48_state, hp48gp )
|
||||
MCFG_DEFAULT_LAYOUT ( layout_hp48gp )
|
||||
|
||||
/* serial I/O */
|
||||
//MCFG_XMODEM_ADD( "rs232_x", hp48_xmodem_rs232_conf )
|
||||
@ -1332,7 +1319,6 @@ static MACHINE_CONFIG_DERIVED( hp48sx, hp48_common )
|
||||
MCFG_CPU_MODIFY ( "maincpu" )
|
||||
MCFG_CPU_CLOCK ( 2000000 )
|
||||
MCFG_MACHINE_START_OVERRIDE (hp48_state, hp48sx )
|
||||
MCFG_DEFAULT_LAYOUT ( layout_hp48sx )
|
||||
|
||||
/* expansion ports */
|
||||
MCFG_HP48_PORT_ADD ( "port1", 0, HP48_CE1, 128*1024)
|
||||
@ -1346,7 +1332,6 @@ static MACHINE_CONFIG_DERIVED( hp48s, hp48_common )
|
||||
MCFG_CPU_MODIFY ( "maincpu" )
|
||||
MCFG_CPU_CLOCK ( 2000000 )
|
||||
MCFG_MACHINE_START_OVERRIDE (hp48_state, hp48s )
|
||||
MCFG_DEFAULT_LAYOUT ( layout_hp48s )
|
||||
|
||||
/* serial I/O */
|
||||
//MCFG_KERMIT_ADD( "rs232_k", hp48_kermit_rs232_conf )
|
||||
@ -1355,7 +1340,6 @@ MACHINE_CONFIG_END
|
||||
static MACHINE_CONFIG_DERIVED( hp49g, hp48_common )
|
||||
MCFG_CPU_MODIFY ( "maincpu" )
|
||||
MCFG_MACHINE_START_OVERRIDE (hp48_state, hp49g )
|
||||
MCFG_DEFAULT_LAYOUT ( layout_hp49g )
|
||||
|
||||
/* serial I/O */
|
||||
//MCFG_XMODEM_ADD( "rs232_x", hp48_xmodem_rs232_conf )
|
||||
|
@ -102,8 +102,8 @@
|
||||
2800 | D | R | Shield 1 Switch
|
||||
2800 | D | R | Fire 2 Switch
|
||||
2800 | D | R | Shield 2 Switch
|
||||
2800 | D | R | Not Used
|
||||
2800 | D | R | Speech Chip Ready
|
||||
2800 | D | R | N/C (floating, probably reads as 1)
|
||||
2800 | D | R | /TIRDY (Speech Chip Ready)
|
||||
2800 | D | R | Alpha Rcvd Flag
|
||||
2800 | D | R | Alpha Xmtd Flag
|
||||
| | |
|
||||
@ -119,7 +119,7 @@
|
||||
| | |
|
||||
5800 | D D D D D D D D | W | Speech Data Write / Write Strobe Clear
|
||||
5900 | | W | Speech Write Strobe Set
|
||||
| | |
|
||||
| | |
|
||||
6000-61FF | D D D D D D D D | R/W | EEROM
|
||||
8000-BFFF | D D D D D D D D | R | Program ROM (16K)
|
||||
-----------------------------------------------------------------------------
|
||||
|
@ -322,7 +322,7 @@ rumbling on a subwoofer in the cabinet.)
|
||||
#include "includes/taitoipt.h"
|
||||
#include "includes/ninjaw.h"
|
||||
|
||||
extern const char layout_darius[];
|
||||
extern const internal_layout layout_darius;
|
||||
|
||||
void ninjaw_state::parse_control( ) /* assumes Z80 sandwiched between 68Ks */
|
||||
{
|
||||
|
@ -31,7 +31,9 @@ class spyhuntertec_state : public driver_device
|
||||
public:
|
||||
spyhuntertec_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_audiocpu(*this, "audiocpu"),
|
||||
m_analog_timer(*this, "analog_timer"),
|
||||
m_videoram(*this, "videoram"),
|
||||
m_spriteram(*this, "spriteram"),
|
||||
m_spriteram2(*this, "spriteram2"),
|
||||
@ -43,12 +45,17 @@ public:
|
||||
{ }
|
||||
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<timer_device> m_analog_timer;
|
||||
required_shared_ptr<UINT8> m_videoram;
|
||||
required_shared_ptr<UINT8> m_spriteram;
|
||||
required_shared_ptr<UINT8> m_spriteram2;
|
||||
required_shared_ptr<UINT8> m_paletteram;
|
||||
required_shared_ptr<UINT8> m_spyhunt_alpharam;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
@ -57,9 +64,6 @@ public:
|
||||
UINT32 screen_update_spyhuntertec(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
|
||||
UINT8 m_spyhunt_sprite_color_mask;
|
||||
INT16 m_spyhunt_scroll_offset;
|
||||
@ -98,9 +102,12 @@ public:
|
||||
TILE_GET_INFO_MEMBER(spyhunt_get_alpha_tile_info);
|
||||
void mcr3_update_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int color_mask, int code_xor, int dx, int dy, int interlaced);
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(analog_shift_callback);
|
||||
void reset_analog_timer();
|
||||
|
||||
int m_analog_read_ready;
|
||||
int m_analog_latched_value;
|
||||
UINT8 m_analog_latched_value;
|
||||
UINT8 m_analog_select;
|
||||
int m_analog_read_count;
|
||||
};
|
||||
|
||||
@ -115,7 +122,17 @@ READ8_MEMBER(spyhuntertec_state::ay1_porta_r)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spyhuntertec_state::reset_analog_timer()
|
||||
{
|
||||
// 555 timer? complete guess
|
||||
m_analog_timer->adjust(attotime::from_nsec(7600));
|
||||
}
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(spyhuntertec_state::analog_shift_callback)
|
||||
{
|
||||
m_analog_read_count++;
|
||||
reset_analog_timer();
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(spyhuntertec_state::ay2_porta_w)
|
||||
{
|
||||
@ -124,25 +141,17 @@ WRITE8_MEMBER(spyhuntertec_state::ay2_porta_w)
|
||||
// or 81 / 01
|
||||
// depending on which sound command was used
|
||||
// assuming input select
|
||||
|
||||
if (data == 0x80)
|
||||
|
||||
// d7 falling edge
|
||||
if (~data & m_analog_select & 0x80)
|
||||
{
|
||||
m_analog_read_ready = 1;
|
||||
m_analog_read_count = 0;
|
||||
m_analog_latched_value = ioport("PEDAL")->read();
|
||||
}
|
||||
else if (data == 0x81)
|
||||
{
|
||||
m_analog_read_ready = 1;
|
||||
m_analog_read_count = 0;
|
||||
m_analog_latched_value = ioport("PADDLE")->read();
|
||||
|
||||
reset_analog_timer();
|
||||
m_analog_latched_value = ioport((data & 1) ? "PADDLE" : "PEDAL")->read();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
m_analog_select = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(spyhuntertec_state::ay2_porta_r)
|
||||
@ -410,6 +419,7 @@ READ8_MEMBER(spyhuntertec_state::spyhuntertec_in2_r)
|
||||
|
||||
|
||||
*/
|
||||
// printf("%04x spyhuntertec_in2_r\n", space.device().safe_pc());
|
||||
|
||||
UINT8 ret = ioport("IN2")->read()&~0x40;
|
||||
|
||||
@ -421,18 +431,12 @@ READ8_MEMBER(spyhuntertec_state::spyhuntertec_in2_r)
|
||||
m_analog_read_count = 0;
|
||||
m_analog_read_ready = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ret |= 0x40;
|
||||
m_analog_read_count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret |= 0x40;
|
||||
}
|
||||
|
||||
// printf("%04x spyhuntertec_in2_r\n", space.device().safe_pc());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -617,7 +621,7 @@ static INPUT_PORTS_START( spyhuntertec )
|
||||
PORT_START("PEDAL")
|
||||
PORT_BIT( 0xff, 0x02, IPT_PEDAL ) PORT_MINMAX(0x02,0xff) PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_REVERSE
|
||||
PORT_START("PADDLE")
|
||||
PORT_BIT( 0xff, 0x02, IPT_PADDLE ) PORT_MINMAX(0x02,0xff) PORT_SENSITIVITY(40) PORT_KEYDELTA(10) PORT_REVERSE
|
||||
PORT_BIT( 0x7f, 0x40, IPT_PADDLE ) PORT_MINMAX(0x30,0x50) PORT_SENSITIVITY(40) PORT_KEYDELTA(3) PORT_REVERSE
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -700,7 +704,8 @@ static MACHINE_CONFIG_START( spyhuntertec, spyhuntertec_state )
|
||||
MCFG_CPU_ADD("maincpu", Z80, MASTER_CLOCK/4)
|
||||
MCFG_CPU_PROGRAM_MAP(spyhuntertec_map)
|
||||
MCFG_CPU_IO_MAP(spyhuntertec_portmap)
|
||||
MCFG_CPU_VBLANK_INT_DRIVER("screen", spyhuntertec_state, irq0_line_hold)
|
||||
MCFG_CPU_VBLANK_INT_DRIVER("screen", spyhuntertec_state, irq0_line_hold)
|
||||
MCFG_TIMER_DRIVER_ADD("analog_timer", spyhuntertec_state, analog_shift_callback)
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
TODO:
|
||||
The entire lispcpu half (more like 3/4) of the machine
|
||||
Framebuffer 1152x864? (lives on the i/o card)
|
||||
Framebuffer 1152x864? 1150x900? (lives on the i/o card)
|
||||
I8274 MPSC (z80dart.cpp) x2
|
||||
1024x4bit SRAM AM2148-50 x6 @F22-F27
|
||||
2048x8bit SRAM @F7 and @G7
|
||||
@ -76,6 +76,13 @@ public:
|
||||
DECLARE_DRIVER_INIT(symbolics);
|
||||
DECLARE_READ16_MEMBER(buserror_r);
|
||||
DECLARE_READ16_MEMBER(fep_paddle_id_prom_r);
|
||||
//DECLARE_READ16_MEMBER(ram_parity_hack_r);
|
||||
//DECLARE_WRITE16_MEMBER(ram_parity_hack_w);
|
||||
//bool m_parity_error_has_occurred[0x20000];
|
||||
|
||||
// overrides
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
//protected:
|
||||
// virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
@ -95,7 +102,34 @@ READ16_MEMBER(symbolics_state::fep_paddle_id_prom_r) // bits 8 and 9 do somethin
|
||||
{
|
||||
return 0x0300;
|
||||
}
|
||||
/*
|
||||
READ16_MEMBER(symbolics_state::ram_parity_hack_r)
|
||||
{
|
||||
UINT16 *ram = (UINT16 *)(memregion("fepdram")->base());
|
||||
//m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
|
||||
m_maincpu->set_input_line_and_vector(M68K_IRQ_7, CLEAR_LINE, M68K_INT_ACK_AUTOVECTOR);
|
||||
if (!(m_parity_error_has_occurred[offset]))
|
||||
{
|
||||
//m_maincpu->set_input_line(M68K_IRQ_7, ASSERT_LINE);
|
||||
m_maincpu->set_input_line_and_vector(M68K_IRQ_7, ASSERT_LINE, M68K_INT_ACK_AUTOVECTOR);
|
||||
m_parity_error_has_occurred[offset] = true;
|
||||
}
|
||||
ram += offset;
|
||||
return *ram;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(symbolics_state::ram_parity_hack_w)
|
||||
{
|
||||
UINT16 *ram = (UINT16 *)(memregion("fepdram")->base());
|
||||
m_maincpu->set_input_line_and_vector(M68K_IRQ_7, CLEAR_LINE, M68K_INT_ACK_AUTOVECTOR);
|
||||
if (!(m_parity_error_has_occurred[offset]))
|
||||
{
|
||||
m_maincpu->set_input_line_and_vector(M68K_IRQ_7, ASSERT_LINE, M68K_INT_ACK_AUTOVECTOR);
|
||||
m_parity_error_has_occurred[offset] = true;
|
||||
}
|
||||
COMBINE_DATA(&ram[offset]);
|
||||
}
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
Address Maps
|
||||
@ -192,9 +226,12 @@ static ADDRESS_MAP_START(m68k_mem, AS_PROGRAM, 16, symbolics_state )
|
||||
ADDRESS_MAP_UNMAP_HIGH
|
||||
//AM_RANGE(0x000000, 0x01ffff) AM_ROM /* ROM lives here */
|
||||
AM_RANGE(0x000000, 0x00bfff) AM_ROM
|
||||
// 0x00c000-0x00ffff is open bus but decoded/auto-DTACKed, does not cause bus error
|
||||
AM_RANGE(0x010000, 0x01bfff) AM_ROM
|
||||
//AM_RANGE(0x020000, 0x03ffff) AM_RAM /* Local FEP ram seems to be here? there are 18 mcm4164s on the pcb which probably map here, plus 2 parity bits? */
|
||||
// 0x01c000-0x01ffff is open bus but decoded/auto-DTACKed, does not cause bus error
|
||||
AM_RANGE(0x020000, 0x03ffff) AM_RAM AM_REGION("fepdram", 0) /* Local FEP ram seems to be here? there are 18 mcm4164s on the pcb which probably map here, plus 2 parity bits? */
|
||||
//AM_RANGE(0x020000, 0x03ffff) AM_READWRITE(ram_parity_hack_r, ram_parity_hack_w)
|
||||
//AM_RANGE(0x020002, 0x03ffff) AM_RAM AM_REGION("fepdram", 0) /* Local FEP ram seems to be here? there are 18 mcm4164s on the pcb which probably map here, plus 2 parity bits? */
|
||||
// 2x AM9128-10PC 2048x8 SRAMs @F7 and @G7 map somewhere
|
||||
// 6x AM2148-50 1024x4bit SRAMs @F22-F27 map somewhere
|
||||
//AM_RANGE(0x040000, 0xffffff) AM_READ(buserror_r);
|
||||
@ -242,13 +279,27 @@ DRIVER_INIT_MEMBER(symbolics_state,symbolics)
|
||||
{
|
||||
}
|
||||
|
||||
/* start */
|
||||
void symbolics_state::machine_start()
|
||||
{
|
||||
//save_item(NAME(m_parity_error_has_occurred));
|
||||
}
|
||||
|
||||
/* reset */
|
||||
void symbolics_state::machine_reset()
|
||||
{
|
||||
/*for(int i=0; i < 0x20000; i++)
|
||||
m_parity_error_has_occurred[i] = false;
|
||||
*/
|
||||
}
|
||||
|
||||
static MACHINE_CONFIG_START( symbolics, symbolics_state )
|
||||
/* basic machine hardware */
|
||||
// per page 159 of http://bitsavers.trailing-edge.com/pdf/symbolics/3600_series/Lisp_Machine_Hardware_Memos.pdf:
|
||||
//XTALS: 16MHz @H11 (68k CPU clock)
|
||||
// 4.9152MHz @J5 (driving the two MPSCs serial clocks)
|
||||
// 66.67MHz @J10 (main lispcpu/system clock)
|
||||
MCFG_CPU_ADD("maincpu", M68000, XTAL_16MHz/2) /* MC68000L8 @A27; clock is derived from the 16Mhz xtal @ H11 */
|
||||
MCFG_CPU_ADD("maincpu", M68000, XTAL_16MHz/2) /* MC68000L8 @A27; clock is derived from the 16Mhz xtal @ H11, verified from patent */
|
||||
MCFG_CPU_PROGRAM_MAP(m68k_mem)
|
||||
MCFG_CPU_IO_MAP(m68k_io)
|
||||
|
||||
|
@ -100,7 +100,7 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
extern const char layout_dlair[];
|
||||
extern const internal_layout layout_dlair;
|
||||
|
||||
|
||||
|
||||
|
@ -85,9 +85,6 @@
|
||||
|
||||
/**************************** common *******************************/
|
||||
|
||||
/* layout */
|
||||
static const char layout_thomson[] = "thomson";
|
||||
|
||||
#define KEY(pos,name,key) \
|
||||
PORT_BIT ( 1<<(pos), IP_ACTIVE_LOW, IPT_KEYBOARD ) \
|
||||
PORT_NAME ( name ) \
|
||||
@ -630,7 +627,6 @@ static MACHINE_CONFIG_START( to7, thomson_state )
|
||||
MCFG_PALETTE_ADD ( "palette", 4097 ) /* 12-bit color + transparency */
|
||||
MCFG_PALETTE_INIT_OWNER(thomson_state, thom)
|
||||
MCFG_VIDEO_START_OVERRIDE( thomson_state, thom )
|
||||
MCFG_DEFAULT_LAYOUT( layout_thomson )
|
||||
|
||||
/* sound */
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
|
@ -1,6 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:hap, Jonathan Gevaryahu, Sean Riddle
|
||||
// thanks-to:David Viens
|
||||
// thanks-to:David Viens, Kevin Horton
|
||||
/***************************************************************************
|
||||
|
||||
** subclass of hh_tms1k_state (includes/hh_tms1k.h, drivers/hh_tms1k.cpp) **
|
||||
|
@ -242,7 +242,7 @@ public:
|
||||
|
||||
MACHINE_CONFIG_EXTERN( mw8080bw_root );
|
||||
MACHINE_CONFIG_EXTERN( invaders );
|
||||
extern const char layout_invaders[];
|
||||
extern const internal_layout layout_invaders;
|
||||
|
||||
/*----------- defined in audio/mw8080bw.c -----------*/
|
||||
|
||||
|