summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/amis2000/amis2000.h34
-rw-r--r--src/devices/cpu/e0c6200/e0c6200.h8
-rw-r--r--src/devices/cpu/e0c6200/e0c6s46.cpp2
-rw-r--r--src/devices/cpu/hmcs40/hmcs40.h10
-rw-r--r--src/devices/cpu/i386/i386ops.hxx5
-rw-r--r--src/devices/cpu/m6805/m6805.cpp156
-rw-r--r--src/devices/cpu/m6805/m6805.h72
-rw-r--r--src/devices/cpu/melps4/melps4.h62
-rw-r--r--src/devices/cpu/tms1000/tms0270.h2
-rw-r--r--src/devices/cpu/tms1000/tms0970.cpp2
-rw-r--r--src/devices/cpu/tms1000/tms0980.cpp2
-rw-r--r--src/devices/cpu/tms1000/tms1000.cpp2
-rw-r--r--src/devices/cpu/tms1000/tms1k_base.h6
-rw-r--r--src/devices/cpu/tms1000/tp0320.cpp2
-rw-r--r--src/devices/cpu/ucom4/ucom4.h8
-rw-r--r--src/devices/machine/gen_latch.cpp43
-rw-r--r--src/devices/machine/gen_latch.h7
-rw-r--r--src/devices/machine/tms6100.h6
-rw-r--r--src/emu/emuopts.cpp6
-rw-r--r--src/emu/emuopts.h9
-rw-r--r--src/emu/ioport.cpp27
-rw-r--r--src/emu/ioport.h2
-rw-r--r--src/emu/machine.cpp32
-rw-r--r--src/emu/machine.h1
-rw-r--r--src/emu/main.cpp208
-rw-r--r--src/emu/main.h22
-rw-r--r--src/frontend/mame/clifront.cpp6
-rw-r--r--src/frontend/mame/info.cpp2
-rw-r--r--src/frontend/mame/ui/info.cpp3
-rw-r--r--src/frontend/mame/ui/info.h2
-rw-r--r--src/frontend/mame/ui/ui.cpp10
-rw-r--r--src/lib/netlist/analog/nld_bjt.h2
-rw-r--r--src/lib/netlist/analog/nld_fourterm.h2
-rw-r--r--src/lib/netlist/analog/nld_twoterm.cpp63
-rw-r--r--src/lib/netlist/analog/nld_twoterm.h63
-rw-r--r--src/lib/netlist/build/makefile1
-rw-r--r--src/lib/netlist/devices/net_lib.cpp197
-rw-r--r--src/lib/netlist/devices/net_lib.h2
-rw-r--r--src/lib/netlist/devices/nld_7448.cpp2
-rw-r--r--src/lib/netlist/devices/nld_7493.cpp12
-rw-r--r--src/lib/netlist/devices/nld_mm5837.cpp31
-rw-r--r--src/lib/netlist/devices/nld_truthtable.h4
-rw-r--r--src/lib/netlist/devices/nlid_system.h39
-rw-r--r--src/lib/netlist/macro/nlm_cd4xxx.cpp4
-rw-r--r--src/lib/netlist/macro/nlm_opamp.cpp2
-rw-r--r--src/lib/netlist/macro/nlm_ttl74xx.cpp28
-rw-r--r--src/lib/netlist/nl_base.h105
-rw-r--r--src/lib/netlist/nl_config.h8
-rw-r--r--src/lib/netlist/nl_factory.cpp44
-rw-r--r--src/lib/netlist/nl_factory.h80
-rw-r--r--src/lib/netlist/nl_parser.cpp59
-rw-r--r--src/lib/netlist/nl_setup.cpp31
-rw-r--r--src/lib/netlist/nl_setup.h13
-rw-r--r--src/lib/netlist/plib/palloc.cpp38
-rw-r--r--src/lib/netlist/plib/palloc.h54
-rw-r--r--src/lib/netlist/plib/pexception.cpp109
-rw-r--r--src/lib/netlist/plib/pexception.h112
-rw-r--r--src/lib/netlist/plib/pstream.h1
-rw-r--r--src/lib/netlist/plib/putil.h5
-rw-r--r--src/lib/netlist/prg/nltool.cpp32
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h2
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp6
-rw-r--r--src/lib/util/base64.hpp167
-rw-r--r--src/lib/util/client_http.hpp438
-rw-r--r--src/lib/util/client_https.hpp152
-rw-r--r--src/lib/util/client_ws.hpp517
-rw-r--r--src/lib/util/client_wss.hpp82
-rw-r--r--src/lib/util/crypto.hpp18
-rw-r--r--src/lib/util/path_to_regex.cpp217
-rw-r--r--src/lib/util/path_to_regex.hpp110
-rw-r--r--src/lib/util/server_http.hpp497
-rw-r--r--src/lib/util/server_https.hpp99
-rw-r--r--src/lib/util/server_ws.hpp714
-rw-r--r--src/lib/util/server_wss.hpp82
-rw-r--r--src/lib/util/sha1.hpp181
-rw-r--r--src/mame/arcade.flt1
-rw-r--r--src/mame/drivers/aa310.cpp24
-rw-r--r--src/mame/drivers/alpha68k.cpp4
-rw-r--r--src/mame/drivers/ashnojoe.cpp23
-rw-r--r--src/mame/drivers/crospang.cpp10
-rw-r--r--src/mame/drivers/crshrace.cpp14
-rw-r--r--src/mame/drivers/dcheese.cpp29
-rw-r--r--src/mame/drivers/ddenlovr.cpp376
-rw-r--r--src/mame/drivers/esd16.cpp3
-rw-r--r--src/mame/drivers/hapyfish.cpp85
-rw-r--r--src/mame/drivers/harddriv.cpp7
-rw-r--r--src/mame/drivers/hh_cop400.cpp12
-rw-r--r--src/mame/drivers/hh_hmcs40.cpp6
-rw-r--r--src/mame/drivers/hh_melps4.cpp6
-rw-r--r--src/mame/drivers/hh_pic16.cpp6
-rw-r--r--src/mame/drivers/hh_sm510.cpp2
-rw-r--r--src/mame/drivers/hh_tms1k.cpp3
-rw-r--r--src/mame/drivers/novag6502.cpp6
-rw-r--r--src/mame/drivers/pc.cpp414
-rw-r--r--src/mame/drivers/rm380z.cpp23
-rw-r--r--src/mame/drivers/rohga.cpp4
-rw-r--r--src/mame/drivers/stv.cpp34
-rw-r--r--src/mame/drivers/vd.cpp143
-rw-r--r--src/mame/drivers/x1.cpp88
-rw-r--r--src/mame/includes/ashnojoe.h3
-rw-r--r--src/mame/includes/crospang.h1
-rw-r--r--src/mame/includes/crshrace.h2
-rw-r--r--src/mame/includes/dcheese.h3
-rw-r--r--src/mame/includes/fidelz80.h6
-rw-r--r--src/mame/includes/harddriv.h3
-rw-r--r--src/mame/includes/hh_tms1k.h6
-rw-r--r--src/mame/includes/hh_ucom4.h6
-rw-r--r--src/mame/includes/namcos2.h6
-rw-r--r--src/mame/includes/rm380z.h5
-rw-r--r--src/mame/machine/alpha8201.h6
-rw-r--r--src/mame/mame.lst9
-rw-r--r--src/mame/video/rm380z.cpp37
-rw-r--r--src/osd/modules/render/bgfx/chainentry.cpp2
-rw-r--r--src/osd/modules/render/bgfx/chainmanager.cpp5
-rw-r--r--src/osd/modules/render/bgfx/effectmanager.cpp6
-rw-r--r--src/osd/modules/render/bgfx/shadermanager.cpp8
-rw-r--r--src/osd/modules/render/drawbgfx.cpp11
117 files changed, 5327 insertions, 1305 deletions
diff --git a/src/devices/cpu/amis2000/amis2000.h b/src/devices/cpu/amis2000/amis2000.h
index 68fd87ee0ae..76190cb3090 100644
--- a/src/devices/cpu/amis2000/amis2000.h
+++ b/src/devices/cpu/amis2000/amis2000.h
@@ -100,28 +100,28 @@ protected:
uint8_t m_bu_bits;
uint16_t m_bu_mask;
- uint8_t m_callstack_bits; // number of program counter bits held in callstack
+ uint8_t m_callstack_bits; // number of program counter bits held in callstack
uint16_t m_callstack_mask;
- uint8_t m_callstack_depth; // callstack levels: 3 on 2000/2150, 5 on 2200/2400
- uint16_t m_callstack[5]; // max 5
+ uint8_t m_callstack_depth; // callstack levels: 3 on 2000/2150, 5 on 2200/2400
+ uint16_t m_callstack[5]; // max 5
int m_icount;
- uint16_t m_pc; // 13-bit program counter
- uint8_t m_ppr; // prepared page register (PP 1)
- uint8_t m_pbr; // prepared bank register (PP 2)
+ uint16_t m_pc; // 13-bit program counter
+ uint8_t m_ppr; // prepared page register (PP 1)
+ uint8_t m_pbr; // prepared bank register (PP 2)
bool m_skip; // skip next opcode, including PP prefixes
uint8_t m_op;
- uint8_t m_prev_op; // previous opcode, needed for PP, LAI, LB*
- uint8_t m_f; // generic flags: 2 on 2000/2150, 6 on 2200/2400
- uint8_t m_carry; // carry flag
- uint8_t m_bl; // 4-bit ram index x
- uint8_t m_bu; // 2/3-bit ram index y
- uint8_t m_acc; // 4-bit accumulator
- uint8_t m_e; // 4-bit generic register
- uint8_t m_ki_mask; // 4-bit k/i-pins select latch
- uint8_t m_d; // 8-bit d-pins latch
+ uint8_t m_prev_op; // previous opcode, needed for PP, LAI, LB*
+ uint8_t m_f; // generic flags: 2 on 2000/2150, 6 on 2200/2400
+ uint8_t m_carry; // carry flag
+ uint8_t m_bl; // 4-bit ram index x
+ uint8_t m_bu; // 2/3-bit ram index y
+ uint8_t m_acc; // 4-bit accumulator
+ uint8_t m_e; // 4-bit generic register
+ uint8_t m_ki_mask; // 4-bit k/i-pins select latch
+ uint8_t m_d; // 8-bit d-pins latch
bool m_d_active; // d-pins available for direct i/o(floating), or outputting d-latch
- uint8_t m_d_polarity; // invert d-latch output
- uint16_t m_a; // 13-bit a-pins latch (master strobe latch)
+ uint8_t m_d_polarity; // invert d-latch output
+ uint16_t m_a; // 13-bit a-pins latch (master strobe latch)
// i/o handlers
const uint8_t *m_7seg_table;
diff --git a/src/devices/cpu/e0c6200/e0c6200.h b/src/devices/cpu/e0c6200/e0c6200.h
index e1b95d0381c..bf43c80ad2b 100644
--- a/src/devices/cpu/e0c6200/e0c6200.h
+++ b/src/devices/cpu/e0c6200/e0c6200.h
@@ -54,10 +54,10 @@ protected:
uint16_t m_op;
uint16_t m_prev_op;
uint8_t m_irq_vector; // low 4 bits for new programcounter after interrupt
- int m_irq_id; // for standard_irq_callback(id)
- bool m_possible_irq; // indicates interrupts need to be re-checked
- bool m_halt; // cpu halt state
- bool m_sleep; // cpu sleep state
+ int m_irq_id; // for standard_irq_callback(id)
+ bool m_possible_irq; // indicates interrupts need to be re-checked
+ bool m_halt; // cpu halt state
+ bool m_sleep; // cpu sleep state
int m_icount;
uint16_t m_pc; // 13-bit programcounter: 1-bit bank, 4-bit page, 8-bit 'step'
diff --git a/src/devices/cpu/e0c6200/e0c6s46.cpp b/src/devices/cpu/e0c6200/e0c6s46.cpp
index 7563f4bc4a3..4feed3f4e32 100644
--- a/src/devices/cpu/e0c6200/e0c6s46.cpp
+++ b/src/devices/cpu/e0c6200/e0c6s46.cpp
@@ -49,7 +49,7 @@ e0c6s46_device::e0c6s46_device(const machine_config &mconfig, const char *tag, d
: e0c6200_cpu_device(mconfig, E0C6S46, "E0C6S46", tag, owner, clock, ADDRESS_MAP_NAME(e0c6s46_program), ADDRESS_MAP_NAME(e0c6s46_data), "e0c6s46", __FILE__)
, m_vram1(*this, "vram1")
, m_vram2(*this, "vram2"), m_osc(0), m_svd(0), m_lcd_control(0), m_lcd_contrast(0)
- , m_pixel_update_handler(nullptr)
+ , m_pixel_update_handler(nullptr)
, m_write_r0(*this), m_write_r1(*this), m_write_r2(*this), m_write_r3(*this), m_write_r4(*this)
, m_read_p0(*this), m_read_p1(*this), m_read_p2(*this), m_read_p3(*this)
, m_write_p0(*this), m_write_p1(*this), m_write_p2(*this), m_write_p3(*this), m_r_dir(0), m_p_dir(0), m_p_pullup(0), m_dfk0(0), m_256_src_pulse(0), m_core_256_handle(nullptr),
diff --git a/src/devices/cpu/hmcs40/hmcs40.h b/src/devices/cpu/hmcs40/hmcs40.h
index 73ae6308940..38a6d20169d 100644
--- a/src/devices/cpu/hmcs40/hmcs40.h
+++ b/src/devices/cpu/hmcs40/hmcs40.h
@@ -182,22 +182,22 @@ protected:
address_space *m_program;
address_space *m_data;
- int m_pcwidth; // Program Counter bit-width
+ int m_pcwidth; // Program Counter bit-width
int m_prgwidth;
int m_datawidth;
int m_pcmask;
int m_prgmask;
int m_datamask;
- int m_family; // MCU family (42-47)
+ int m_family; // MCU family (42-47)
uint16_t m_polarity; // i/o polarity (pmos vs cmos)
- int m_stack_levels; // number of callstack levels
+ int m_stack_levels; // number of callstack levels
uint16_t m_stack[4]; // max 4
uint16_t m_op; // current opcode
uint16_t m_prev_op;
uint8_t m_i; // 4-bit immediate opcode param
- int m_eint_line; // which input_line caused an interrupt
+ int m_eint_line; // which input_line caused an interrupt
emu_timer *m_timer;
- int m_halt; // internal HLT state
+ int m_halt; // internal HLT state
attotime m_timer_halted_remain;
int m_icount;
diff --git a/src/devices/cpu/i386/i386ops.hxx b/src/devices/cpu/i386/i386ops.hxx
index e27bb4a13bc..1d00ac21566 100644
--- a/src/devices/cpu/i386/i386ops.hxx
+++ b/src/devices/cpu/i386/i386ops.hxx
@@ -1224,8 +1224,9 @@ void i386_device::i386_repeat(int invert_flag)
return;
default:
- fatalerror("i386: Invalid REP/opcode %02X combination\n",opcode);
- break;
+ logerror("i386: Invalid REP/opcode %02X combination at %08x\n",opcode, m_pc - 2);
+ m_pc--;
+ return;
}
if( m_address_size ) {
diff --git a/src/devices/cpu/m6805/m6805.cpp b/src/devices/cpu/m6805/m6805.cpp
index 278505b8c1e..6c2f3de6622 100644
--- a/src/devices/cpu/m6805/m6805.cpp
+++ b/src/devices/cpu/m6805/m6805.cpp
@@ -415,7 +415,7 @@ m6805_base_device::m6805_base_device(const machine_config &mconfig, const char *
{
}
-m6805_base_device::m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_constructor internal_map, const char *shortname, const char *source)
+m6805_base_device::m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_delegate internal_map, const char *shortname, const char *source)
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source),
m_program_config("program", ENDIANNESS_BIG, 8, addr_width, 0, internal_map)
{
@@ -965,63 +965,146 @@ void m68705_device::execute_set_input(int inputnum, int state)
/* ddr - direction registers */
-WRITE8_MEMBER(m68705_new_device::mc68705_ddrA_w)
+WRITE8_MEMBER(m68705_new_device::internal_ddrA_w)
{
+ const u8 ddr_old = m_ddrA;
m_ddrA = data;
+
+ // update outputs if lines switched to output
+ if ((m_ddrA & ~ddr_old) != 0)
+ update_portA_state();
}
-WRITE8_MEMBER(m68705_new_device::mc68705_ddrB_w)
+WRITE8_MEMBER(m68705_new_device::internal_ddrB_w)
{
+ const u8 ddr_old = m_ddrB;
m_ddrB = data;
+
+ // update outputs if lines switched to output
+ if ((m_ddrB & ~ddr_old) != 0)
+ update_portB_state();
}
-WRITE8_MEMBER(m68705_new_device::mc68705_ddrC_w)
+WRITE8_MEMBER(m68705_new_device::internal_ddrC_w)
{
+ const u8 ddr_old = m_ddrC;
m_ddrC = data;
+
+ // update outputs if lines switched to output
+ if ((m_ddrC & ~ddr_old) != 0)
+ update_portC_state();
}
/* read ports */
-READ8_MEMBER(m68705_new_device::mc68705_portA_r)
+READ8_MEMBER(m68705_new_device::internal_portA_r)
{
- m_portA_in = m_portA_cb_r(0, ~m_ddrA); // pass the direction register as mem_mask so that externally we know which lines were actually pulled
- uint8_t res = (m_portA_out & m_ddrA) | (m_portA_in & ~m_ddrA);
+ if (!m_portA_cb_r.isnull())
+ m_portA_in = m_portA_cb_r(space, 0, ~m_ddrA); // pass the direction register as mem_mask so that externally we know which lines were actually pulled
+ u8 res = (m_portA_out & m_ddrA) | (m_portA_in & ~m_ddrA);
return res;
-
}
-READ8_MEMBER(m68705_new_device::mc68705_portB_r)
+READ8_MEMBER(m68705_new_device::internal_portB_r)
{
- m_portB_in = m_portB_cb_r(0, ~m_ddrB);
- uint8_t res = (m_portB_out & m_ddrB) | (m_portB_in & ~m_ddrB);
+ if (!m_portB_cb_r.isnull())
+ m_portB_in = m_portB_cb_r(space, 0, ~m_ddrB);
+ u8 res = (m_portB_out & m_ddrB) | (m_portB_in & ~m_ddrB);
return res;
}
-READ8_MEMBER(m68705_new_device::mc68705_portC_r)
+READ8_MEMBER(m68705_new_device::internal_portC_r)
{
- m_portC_in = m_portC_cb_r(0, ~m_ddrC);
- uint8_t res = (m_portC_out & m_ddrC) | (m_portC_in & ~m_ddrC);
+ if (!m_portC_cb_r.isnull())
+ m_portC_in = m_portC_cb_r(space, 0, ~m_ddrC);
+ u8 res = (m_portC_out & m_ddrC) | (m_portC_in & ~m_ddrC);
return res;
}
/* write ports */
-WRITE8_MEMBER(m68705_new_device::mc68705_portA_w)
+WRITE8_MEMBER(m68705_new_device::internal_portA_w)
{
- m_portA_cb_w(0, data, m_ddrA); // pass the direction register as mem_mask so that externally we know which lines were actually pushed
+ // load the output latch
m_portA_out = data;
+
+ // update the output lines
+ update_portA_state();
}
-WRITE8_MEMBER(m68705_new_device::mc68705_portB_w)
+void m68705_new_device::update_portA_state()
{
- m_portB_cb_w(0, data, m_ddrB);
+ // pass bits through DDR output mask
+ m_portA_in = (m_portA_out & m_ddrA) | (m_portA_in & ~m_ddrA);
+
+ // pass the direction register as mem_mask as mem_mask so that externally we know which lines were actually pushed
+ m_portA_cb_w(space(AS_PROGRAM), 0, m_portA_in, m_ddrA);
+}
+
+WRITE8_MEMBER(m68705_new_device::internal_portB_w)
+{
+ // load the output latch
m_portB_out = data;
+
+ // update the output lines
+ update_portB_state();
}
-WRITE8_MEMBER(m68705_new_device::mc68705_portC_w)
+void m68705_new_device::update_portB_state()
{
- m_portC_cb_w(0, data, m_ddrC);
+ // pass bits through DDR output mask
+ m_portB_in = (m_portB_out & m_ddrB) | (m_portB_in & ~m_ddrB);
+
+ // pass the direction register as mem_mask as mem_mask so that externally we know which lines were actually pushed
+ m_portB_cb_w(space(AS_PROGRAM), 0, m_portB_in, m_ddrB);
+}
+
+WRITE8_MEMBER(m68705_new_device::internal_portC_w)
+{
+ // load the output latch
m_portC_out = data;
+
+ // update the output lines
+ update_portC_state();
+}
+
+void m68705_new_device::update_portC_state()
+{
+ // pass bits through DDR output mask
+ m_portC_in = (m_portC_out & m_ddrC) | (m_portC_in & ~m_ddrC);
+
+ // pass the direction register as mem_mask as mem_mask so that externally we know which lines were actually pushed
+ m_portC_cb_w(space(AS_PROGRAM), 0, m_portC_in, m_ddrC);
+}
+
+READ8_MEMBER(m68705_new_device::pa_r)
+{
+ return m_portA_in;
+}
+
+READ8_MEMBER(m68705_new_device::pb_r)
+{
+ return m_portB_in;
+}
+
+READ8_MEMBER(m68705_new_device::pc_r)
+{
+ return m_portC_in;
+}
+
+WRITE8_MEMBER(m68705_new_device::pa_w)
+{
+ COMBINE_DATA(&m_portA_in);
+}
+
+WRITE8_MEMBER(m68705_new_device::pb_w)
+{
+ COMBINE_DATA(&m_portB_in);
+}
+
+WRITE8_MEMBER(m68705_new_device::pc_w)
+{
+ COMBINE_DATA(&m_portC_in);
}
/*
@@ -1079,13 +1162,13 @@ selftest rom at similar area; selftest roms differ between the U2 and U3 version
*/
-ADDRESS_MAP_START( m68705_internal_map, AS_PROGRAM, 8, m68705_new_device )
- AM_RANGE(0x000, 0x000) AM_READWRITE(mc68705_portA_r, mc68705_portA_w)
- AM_RANGE(0x001, 0x001) AM_READWRITE(mc68705_portB_r, mc68705_portB_w)
- AM_RANGE(0x002, 0x002) AM_READWRITE(mc68705_portC_r, mc68705_portC_w)
- AM_RANGE(0x004, 0x004) AM_WRITE(mc68705_ddrA_w)
- AM_RANGE(0x005, 0x005) AM_WRITE(mc68705_ddrB_w)
- AM_RANGE(0x006, 0x006) AM_WRITE(mc68705_ddrC_w)
+DEVICE_ADDRESS_MAP_START( internal_map, 8, m68705_new_device )
+ AM_RANGE(0x000, 0x000) AM_READWRITE(internal_portA_r, internal_portA_w)
+ AM_RANGE(0x001, 0x001) AM_READWRITE(internal_portB_r, internal_portB_w)
+ AM_RANGE(0x002, 0x002) AM_READWRITE(internal_portC_r, internal_portC_w)
+ AM_RANGE(0x004, 0x004) AM_WRITE(internal_ddrA_w)
+ AM_RANGE(0x005, 0x005) AM_WRITE(internal_ddrB_w)
+ AM_RANGE(0x006, 0x006) AM_WRITE(internal_ddrC_w)
AM_RANGE(0x010, 0x07f) AM_RAM
AM_RANGE(0x080, 0x7ff) AM_ROM
@@ -1111,10 +1194,23 @@ void m68705_new_device::device_start()
m_portB_cb_w.resolve_safe();
m_portC_cb_w.resolve_safe();
- m_portA_cb_r.resolve_safe(0xff);
- m_portB_cb_r.resolve_safe(0xff);
- m_portC_cb_r.resolve_safe(0xff);
+ m_portA_cb_r.resolve();
+ m_portB_cb_r.resolve();
+ m_portC_cb_r.resolve();
+
+ m_portA_in = 0xff;
+ m_portB_in = 0xff;
+ m_portC_in = 0xff;
+}
+
+void m68705_new_device::device_reset()
+{
+ m68705_device::device_reset();
+ // all bits of ports A, B and C revert to inputs on reset
+ m_ddrA = 0;
+ m_ddrB = 0;
+ m_ddrC = 0;
}
/****************************************************************************
diff --git a/src/devices/cpu/m6805/m6805.h b/src/devices/cpu/m6805/m6805.h
index 24b75f57158..f0d6e5200a7 100644
--- a/src/devices/cpu/m6805/m6805.h
+++ b/src/devices/cpu/m6805/m6805.h
@@ -28,7 +28,7 @@ class m6805_base_device : public cpu_device
public:
// construction/destruction
m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, const char *shortname, const char *source);
- m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_constructor internal_map, const char *shortname, const char *source);
+ m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_delegate internal_map, const char *shortname, const char *source);
protected:
// device-level overrides
@@ -330,7 +330,7 @@ public:
m68705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: m6805_base_device(mconfig, tag, owner, clock, M68705, "M68705", 12, "m68705", __FILE__) { }
- m68705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_constructor internal_map, const char *shortname, const char *source)
+ m68705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_delegate internal_map, const char *shortname, const char *source)
: m6805_base_device(mconfig, tag, owner, clock, type, name, addr_width, internal_map, shortname, source) { }
@@ -345,26 +345,24 @@ protected:
// ======================> m68705_new_device
-ADDRESS_MAP_EXTERN(m68705_internal_map, 8);
-
#define MCFG_M68705_PORTA_W_CB(_devcb) \
- m68705_new_device::set_portA_cb_w(*device, DEVCB_##_devcb);
+ devcb = &m68705_new_device::set_portA_cb_w(*device, DEVCB_##_devcb);
#define MCFG_M68705_PORTB_W_CB(_devcb) \
- m68705_new_device::set_portB_cb_w(*device, DEVCB_##_devcb);
+ devcb = &m68705_new_device::set_portB_cb_w(*device, DEVCB_##_devcb);
#define MCFG_M68705_PORTC_W_CB(_devcb) \
- m68705_new_device::set_portC_cb_w(*device, DEVCB_##_devcb);
+ devcb = &m68705_new_device::set_portC_cb_w(*device, DEVCB_##_devcb);
#define MCFG_M68705_PORTA_R_CB(_devcb) \
- m68705_new_device::set_portA_cb_r(*device, DEVCB_##_devcb);
+ devcb = &m68705_new_device::set_portA_cb_r(*device, DEVCB_##_devcb);
#define MCFG_M68705_PORTB_R_CB(_devcb) \
- m68705_new_device::set_portB_cb_r(*device, DEVCB_##_devcb);
+ devcb = &m68705_new_device::set_portB_cb_r(*device, DEVCB_##_devcb);
#define MCFG_M68705_PORTC_R_CB(_devcb) \
- m68705_new_device::set_portC_cb_r(*device, DEVCB_##_devcb);
+ devcb = &m68705_new_device::set_portC_cb_r(*device, DEVCB_##_devcb);
class m68705_new_device : public m68705_device
@@ -372,7 +370,7 @@ class m68705_new_device : public m68705_device
public:
// construction/destruction
m68705_new_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : m68705_device(mconfig, tag, owner, clock, M68705_NEW, "M68705 (NEW)", 11, ADDRESS_MAP_NAME( m68705_internal_map ), "m68705_new", __FILE__),
+ : m68705_device(mconfig, tag, owner, clock, M68705_NEW, "M68705 (NEW)", 11, address_map_delegate(FUNC(m68705_new_device::internal_map), this), "m68705_new", __FILE__),
m_portA_in(0),
m_portB_in(0),
m_portC_in(0),
@@ -399,31 +397,44 @@ public:
template<class _Object> static devcb_base &set_portB_cb_r(device_t &device, _Object object) { return downcast<m68705_new_device &>(device).m_portB_cb_r.set_callback(object); }
template<class _Object> static devcb_base &set_portC_cb_r(device_t &device, _Object object) { return downcast<m68705_new_device &>(device).m_portC_cb_r.set_callback(object); }
- DECLARE_READ8_MEMBER(mc68705_portA_r);
- DECLARE_READ8_MEMBER(mc68705_portB_r);
- DECLARE_READ8_MEMBER(mc68705_portC_r);
-
- DECLARE_WRITE8_MEMBER(mc68705_portA_w);
- DECLARE_WRITE8_MEMBER(mc68705_portB_w);
- DECLARE_WRITE8_MEMBER(mc68705_portC_w);
+ DECLARE_READ8_MEMBER(pa_r);
+ DECLARE_READ8_MEMBER(pb_r);
+ DECLARE_READ8_MEMBER(pc_r);
- DECLARE_WRITE8_MEMBER(mc68705_ddrA_w);
- DECLARE_WRITE8_MEMBER(mc68705_ddrB_w);
- DECLARE_WRITE8_MEMBER(mc68705_ddrC_w);
+ DECLARE_WRITE8_MEMBER(pa_w);
+ DECLARE_WRITE8_MEMBER(pb_w);
+ DECLARE_WRITE8_MEMBER(pc_w);
protected:
+ DECLARE_ADDRESS_MAP(internal_map, 8);
+
+ DECLARE_READ8_MEMBER(internal_portA_r);
+ DECLARE_READ8_MEMBER(internal_portB_r);
+ DECLARE_READ8_MEMBER(internal_portC_r);
+
+ DECLARE_WRITE8_MEMBER(internal_portA_w);
+ DECLARE_WRITE8_MEMBER(internal_portB_w);
+ DECLARE_WRITE8_MEMBER(internal_portC_w);
- uint8_t m_portA_in;
- uint8_t m_portB_in;
- uint8_t m_portC_in;
+ DECLARE_WRITE8_MEMBER(internal_ddrA_w);
+ DECLARE_WRITE8_MEMBER(internal_ddrB_w);
+ DECLARE_WRITE8_MEMBER(internal_ddrC_w);
- uint8_t m_portA_out;
- uint8_t m_portB_out;
- uint8_t m_portC_out;
+ void update_portA_state();
+ void update_portB_state();
+ void update_portC_state();
- uint8_t m_ddrA;
- uint8_t m_ddrB;
- uint8_t m_ddrC;
+ u8 m_portA_in;
+ u8 m_portB_in;
+ u8 m_portC_in;
+
+ u8 m_portA_out;
+ u8 m_portB_out;
+ u8 m_portC_out;
+
+ u8 m_ddrA;
+ u8 m_ddrB;
+ u8 m_ddrC;
/* Callbacks */
devcb_write8 m_portA_cb_w;
@@ -437,6 +448,7 @@ protected:
// device-level overrides
virtual void device_start() override;
+ virtual void device_reset() override;
// virtual void execute_set_input(int inputnum, int state) override;
diff --git a/src/devices/cpu/melps4/melps4.h b/src/devices/cpu/melps4/melps4.h
index d7668d35fb6..d3b84a01aa5 100644
--- a/src/devices/cpu/melps4/melps4.h
+++ b/src/devices/cpu/melps4/melps4.h
@@ -177,32 +177,32 @@ protected:
int m_d_pins; // number of D port pins and bitmask: 11 on '40,'41,'42,'44, 8 on '43, 12 on '45,'46, 16 on '47
int m_d_mask; // "
- uint8_t m_sm_page; // subroutine default page: 14 on '40 to '44, 2 on '45,'46, 0 on '47
- uint8_t m_int_page; // interrupt routine page: 12 on '40 to '44, 1 on '45,'46, 2 on '47
- uint8_t m_xami_mask; // mask option for XAMI opcode on '40,'41,'45 (0xf for others)
- uint16_t m_sp_mask; // SP opcode location(middle 4 bits): 7 on '40 to '46, 3 on '47
- uint16_t m_ba_op; // BA opcode location: 1 on '40 to '46, N/A on '47
- uint8_t m_stack_levels; // 3 levels on MELPS 4, 12 levels on MELPS 41/42
+ uint8_t m_sm_page; // subroutine default page: 14 on '40 to '44, 2 on '45,'46, 0 on '47
+ uint8_t m_int_page; // interrupt routine page: 12 on '40 to '44, 1 on '45,'46, 2 on '47
+ uint8_t m_xami_mask; // mask option for XAMI opcode on '40,'41,'45 (0xf for others)
+ uint16_t m_sp_mask; // SP opcode location(middle 4 bits): 7 on '40 to '46, 3 on '47
+ uint16_t m_ba_op; // BA opcode location: 1 on '40 to '46, N/A on '47
+ uint8_t m_stack_levels; // 3 levels on MELPS 4, 12 levels on MELPS 41/42
// internal state, misc regs
- uint16_t m_pc; // program counter (11 or 10-bit)
+ uint16_t m_pc; // program counter (11 or 10-bit)
uint16_t m_prev_pc;
- uint16_t m_stack[12]; // callstack (SK0-SKx, same size as PC)
+ uint16_t m_stack[12]; // callstack (SK0-SKx, same size as PC)
uint16_t m_op;
uint16_t m_prev_op;
- uint8_t m_bitmask; // opcode bit argument
+ uint8_t m_bitmask; // opcode bit argument
- uint16_t m_port_d; // last written port data
- uint8_t m_port_s; // "
- uint8_t m_port_f; // "
- uint8_t m_port_t; // "
+ uint16_t m_port_d; // last written port data
+ uint8_t m_port_s; // "
+ uint8_t m_port_f; // "
+ uint8_t m_port_t; // "
bool m_sm, m_sms; // subroutine mode flag + irq stack
bool m_ba_flag; // temp flag indicates BA opcode was executed
- uint8_t m_sp_param; // temp register holding SP opcode parameter
- uint8_t m_cps; // DP,CY or DP',CY' selected
+ uint8_t m_sp_param; // temp register holding SP opcode parameter
+ uint8_t m_cps; // DP,CY or DP',CY' selected
bool m_skip; // skip next opcode
- uint8_t m_inte; // interrupt enable flag
+ uint8_t m_inte; // interrupt enable flag
int m_intp; // external interrupt polarity ('40 to '44)
bool m_irqflag[3]; // irq flags: exf, 1f, 2f (external, timer 1, timer 2)
int m_int_state; // INT pin state
@@ -210,24 +210,24 @@ protected:
bool m_prohibit_irq; // interrupt is prohibited during certain opcodes
bool m_possible_irq; // indicate that irq needs to be rechecked
- uint8_t m_tmr_count[2]; // timer active count
- uint8_t m_tmr_reload; // timer(2) auto reload
+ uint8_t m_tmr_count[2]; // timer active count
+ uint8_t m_tmr_reload; // timer(2) auto reload
bool m_tmr_irq_enabled[2];
// work registers (unless specified, each is 4-bit)
- uint8_t m_a; // accumulator
- uint8_t m_b; // generic
- uint8_t m_e; // 8-bit register, hold data for S output
- uint8_t m_y, m_y2; // RAM index Y, Y' (Z.XX.YYYY is DP aka Data Pointer)
- uint8_t m_x, m_x2; // RAM index X, X', 2-bit
- uint8_t m_z, m_z2; // RAM index Z, Z', 1-bit, optional
- uint8_t m_cy, m_cy2; // carry flag(s)
-
- uint8_t m_h; // A/D converter H or generic
- uint8_t m_l; // A/D converter L or generic
- uint8_t m_c; // A/D converter counter
- uint8_t m_v; // timer control V
- uint8_t m_w; // timer control W
+ uint8_t m_a; // accumulator
+ uint8_t m_b; // generic
+ uint8_t m_e; // 8-bit register, hold data for S output
+ uint8_t m_y, m_y2; // RAM index Y, Y' (Z.XX.YYYY is DP aka Data Pointer)
+ uint8_t m_x, m_x2; // RAM index X, X', 2-bit
+ uint8_t m_z, m_z2; // RAM index Z, Z', 1-bit, optional
+ uint8_t m_cy, m_cy2; // carry flag(s)
+
+ uint8_t m_h; // A/D converter H or generic
+ uint8_t m_l; // A/D converter L or generic
+ uint8_t m_c; // A/D converter counter
+ uint8_t m_v; // timer control V
+ uint8_t m_w; // timer control W
// i/o handlers
devcb_read16 m_read_k;
diff --git a/src/devices/cpu/tms1000/tms0270.h b/src/devices/cpu/tms1000/tms0270.h
index 76bbd2f859b..77f596cda84 100644
--- a/src/devices/cpu/tms1000/tms0270.h
+++ b/src/devices/cpu/tms1000/tms0270.h
@@ -54,7 +54,7 @@ private:
uint8_t m_chipsel;
uint8_t m_ctl_out;
uint8_t m_ctl_dir;
- int m_pdc;
+ int m_pdc;
uint8_t m_o_latch_low;
uint8_t m_o_latch;
diff --git a/src/devices/cpu/tms1000/tms0970.cpp b/src/devices/cpu/tms1000/tms0970.cpp
index 96c60fe5183..b24f1ba6774 100644
--- a/src/devices/cpu/tms1000/tms0970.cpp
+++ b/src/devices/cpu/tms1000/tms0970.cpp
@@ -119,7 +119,7 @@ void tms0970_cpu_device::device_reset()
uint32_t mmask = m_mpla->read(msel);
mmask ^= 0x09fe; // invert active-negative
- // _____ _____ _____ _____ ______ _____ ______ _____ _____
+ // _____ _____ _____ _____ ______ _____ ______ _____ _____
const uint32_t md[15] = { M_CKM, M_CKP, M_YTP, M_MTP, M_ATN, M_NATN, M_MTN, M_15TN, M_CKN, M_NE, M_C8, M_CIN, M_AUTA, M_AUTY, M_STO };
for (int bit = 0; bit < 15; bit++)
diff --git a/src/devices/cpu/tms1000/tms0980.cpp b/src/devices/cpu/tms1000/tms0980.cpp
index b3678165d4a..5e9ea00d178 100644
--- a/src/devices/cpu/tms1000/tms0980.cpp
+++ b/src/devices/cpu/tms1000/tms0980.cpp
@@ -122,7 +122,7 @@ uint32_t tms0980_cpu_device::decode_micro(uint8_t sel)
// M_RSTR is specific to TMS02x0/TMS1980, it redirects to F_RSTR
// M_UNK1 is specific to TMS0270, unknown/unused yet and apparently not connected on every TMS0270
- // _______ ______ _____ _____ _____ _____ ______ _____ ______ _____ _____
+ // _______ ______ _____ _____ _____ _____ ______ _____ ______ _____ _____
const uint32_t md[22] = { M_NDMTP, M_DMTP, M_AUTY, M_AUTA, M_CKM, M_SSE, M_CKP, M_YTP, M_MTP, M_ATN, M_NATN, M_MTN, M_15TN, M_CKN, M_NE, M_C8, M_SSS, M_CME, M_CIN, M_STO, M_RSTR, M_UNK1 };
for (int bit = 0; bit < 22 && bit < m_mpla->outputs(); bit++)
diff --git a/src/devices/cpu/tms1000/tms1000.cpp b/src/devices/cpu/tms1000/tms1000.cpp
index 40add17105c..05ff12e03c6 100644
--- a/src/devices/cpu/tms1000/tms1000.cpp
+++ b/src/devices/cpu/tms1000/tms1000.cpp
@@ -114,7 +114,7 @@ void tms1000_cpu_device::device_reset()
for (int op = 0; op < 0x100; op++)
{
- // _____ _____ ______ _____ ______ _____ _____ _____ _____
+ // _____ _____ ______ _____ ______ _____ _____ _____ _____
const uint32_t md[16] = { M_STSL, M_AUTY, M_AUTA, M_CIN, M_C8, M_NE, M_CKN, M_15TN, M_MTN, M_NATN, M_ATN, M_MTP, M_YTP, M_CKP, M_CKM, M_STO };
uint16_t mask = m_mpla->read(op);
mask ^= 0x3fc8; // invert active-negative
diff --git a/src/devices/cpu/tms1000/tms1k_base.h b/src/devices/cpu/tms1000/tms1k_base.h
index c4fdb99f933..39ccbf31ea1 100644
--- a/src/devices/cpu/tms1000/tms1k_base.h
+++ b/src/devices/cpu/tms1000/tms1k_base.h
@@ -261,14 +261,14 @@ protected:
uint8_t m_ram_in;
uint8_t m_dam_in;
- int m_ram_out; // signed!
+ int m_ram_out; // signed!
uint8_t m_ram_address;
uint16_t m_rom_address;
uint16_t m_opcode;
uint32_t m_fixed;
uint32_t m_micro;
- int m_subcycle;
- int m_icount;
+ int m_subcycle;
+ int m_icount;
uint8_t m_o_index;
uint8_t m_o_pins; // how many O pins
diff --git a/src/devices/cpu/tms1000/tp0320.cpp b/src/devices/cpu/tms1000/tp0320.cpp
index 243ef3bb8e3..cf427cda589 100644
--- a/src/devices/cpu/tms1000/tp0320.cpp
+++ b/src/devices/cpu/tms1000/tp0320.cpp
@@ -74,7 +74,7 @@ uint32_t tp0320_cpu_device::decode_micro(uint8_t sel)
uint32_t mask = m_mpla->read(sel);
mask ^= 0x0bff0; // invert active-negative
- // _____ _______ ______ _____ _____ ______ _____ _____ ______ _____ _____
+ // _____ _______ ______ _____ _____ ______ _____ _____ ______ _____ _____
const uint32_t md[22] = { M_AUTA, M_AUTY, M_SSS, M_STO, M_YTP, M_NDMTP, M_DMTP, M_MTP, M_CKP, M_15TN, M_CKN, M_MTN, M_NATN, M_ATN, M_CME, M_CIN, M_SSE, M_CKM, M_NE, M_C8, M_SETR, M_RSTR };
for (int bit = 0; bit < 22 && bit < m_mpla->outputs(); bit++)
diff --git a/src/devices/cpu/ucom4/ucom4.h b/src/devices/cpu/ucom4/ucom4.h
index be7905f5065..ca0701734fb 100644
--- a/src/devices/cpu/ucom4/ucom4.h
+++ b/src/devices/cpu/ucom4/ucom4.h
@@ -169,15 +169,15 @@ protected:
int m_datawidth;
int m_prgmask;
int m_datamask;
- int m_family; // MCU family (43/44/45)
- int m_stack_levels; // number of callstack levels
+ int m_family; // MCU family (43/44/45)
+ int m_stack_levels; // number of callstack levels
uint16_t m_stack[3]; // max 3
uint8_t m_port_out[0x10]; // last value written to output port
uint8_t m_op;
uint8_t m_prev_op; // previous opcode
uint8_t m_arg; // opcode argument for 2-byte opcodes
uint8_t m_bitmask; // opcode bit argument
- bool m_skip; // skip next opcode
+ bool m_skip; // skip next opcode
int m_icount;
emu_timer *m_timer;
@@ -192,7 +192,7 @@ protected:
uint8_t m_timer_f; // timer out flag
uint8_t m_int_f; // interrupt flag
uint8_t m_inte_f; // interrupt enable flag
- int m_int_line; // interrupt pin state
+ int m_int_line; // interrupt pin state
// i/o handlers
devcb_read8 m_read_a;
diff --git a/src/devices/machine/gen_latch.cpp b/src/devices/machine/gen_latch.cpp
index 7be65c67943..f41f6df5fca 100644
--- a/src/devices/machine/gen_latch.cpp
+++ b/src/devices/machine/gen_latch.cpp
@@ -26,7 +26,7 @@ const device_type GENERIC_LATCH_16 = &device_creator<generic_latch_16_device>;
generic_latch_base_device::generic_latch_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source) :
device_t(mconfig, type, name, tag, owner, clock, shortname, source),
- m_latch_read(false),
+ m_latch_written(false),
m_data_pending_cb(*this)
{
}
@@ -38,7 +38,16 @@ generic_latch_base_device::generic_latch_base_device(const machine_config &mconf
void generic_latch_base_device::device_start()
{
m_data_pending_cb.resolve_safe();
- save_item(NAME(m_latch_read));
+ save_item(NAME(m_latch_written));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void generic_latch_base_device::device_reset()
+{
+ m_latch_written = false;
}
//-------------------------------------------------
@@ -48,20 +57,20 @@ void generic_latch_base_device::device_start()
READ_LINE_MEMBER(generic_latch_base_device::pending_r)
{
- return !m_latch_read;
+ return m_latch_written ? 1 : 0;
}
//-------------------------------------------------
-// set_latch_read - helper to signal that latch
-// has been read or is waiting to be read
+// set_latch_written - helper to signal that latch
+// has been written or has been read
//-------------------------------------------------
-void generic_latch_base_device::set_latch_read(bool latch_read)
+void generic_latch_base_device::set_latch_written(bool latch_written)
{
- if (m_latch_read != latch_read)
+ if (m_latch_written != latch_written)
{
- m_latch_read = latch_read;
- m_data_pending_cb(!latch_read);
+ m_latch_written = latch_written;
+ m_data_pending_cb(latch_written ? 1 : 0);
}
}
@@ -77,7 +86,7 @@ generic_latch_8_device::generic_latch_8_device(const machine_config &mconfig, co
READ8_MEMBER( generic_latch_8_device::read )
{
- set_latch_read(true);
+ set_latch_written(false);
return m_latched_value;
}
@@ -115,13 +124,13 @@ void generic_latch_8_device::sync_callback(void *ptr, s32 param)
{
u8 value = param;
- // if the latch hasn't been read and the value is changed, log a warning
- if (!is_latch_read() && m_latched_value != value)
+ // if the latch has been written and the value is changed, log a warning
+ if (is_latch_written() && m_latched_value != value)
logerror("Warning: latch written before being read. Previous: %02x, new: %02x\n", m_latched_value, value);
// store the new value and mark it not read
m_latched_value = value;
- set_latch_read(false);
+ set_latch_written(true);
}
//-------------------------------------------------
@@ -147,7 +156,7 @@ generic_latch_16_device::generic_latch_16_device(const machine_config &mconfig,
READ16_MEMBER( generic_latch_16_device::read )
{
- set_latch_read(true);
+ set_latch_written(false);
return m_latched_value;
}
@@ -185,13 +194,13 @@ void generic_latch_16_device::sync_callback(void *ptr, s32 param)
{
u16 value = param;
- // if the latch hasn't been read and the value is changed, log a warning
- if (!is_latch_read() && m_latched_value != value)
+ // if the latch has been written and the value is changed, log a warning
+ if (is_latch_written() && m_latched_value != value)
logerror("Warning: latch written before being read. Previous: %02x, new: %02x\n", m_latched_value, value);
// store the new value and mark it not read
m_latched_value = value;
- set_latch_read(false);
+ set_latch_written(true);
}
//-------------------------------------------------
diff --git a/src/devices/machine/gen_latch.h b/src/devices/machine/gen_latch.h
index 4cfa73a1c4c..2c000d2fce7 100644
--- a/src/devices/machine/gen_latch.h
+++ b/src/devices/machine/gen_latch.h
@@ -46,12 +46,13 @@ public:
protected:
virtual void device_start() override;
+ virtual void device_reset() override;
- bool is_latch_read() const { return m_latch_read; }
- void set_latch_read(bool latch_read);
+ bool is_latch_written() const { return m_latch_written; }
+ void set_latch_written(bool latch_written);
private:
- bool m_latch_read;
+ bool m_latch_written;
devcb_write_line m_data_pending_cb;
};
diff --git a/src/devices/machine/tms6100.h b/src/devices/machine/tms6100.h
index 0749424b0d7..93a4f06826f 100644
--- a/src/devices/machine/tms6100.h
+++ b/src/devices/machine/tms6100.h
@@ -131,9 +131,9 @@ protected:
uint8_t m_data; // ADD/DATA pins output
int m_m0;
int m_m1;
- int m_cs; // chipselect pin
- int m_clk; // CLK pin
- int m_rck; // RCK pin (mask/gate to CLK?)
+ int m_cs; // chipselect pin
+ int m_clk; // CLK pin
+ int m_rck; // RCK pin (mask/gate to CLK?)
};
diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp
index 0e5305f33d1..b6463a99f9d 100644
--- a/src/emu/emuopts.cpp
+++ b/src/emu/emuopts.cpp
@@ -203,6 +203,12 @@ const options_entry emu_options::s_option_entries[] =
{ OPTION_PLUGIN, nullptr, OPTION_STRING, "list of plugins to enable" },
{ OPTION_NO_PLUGIN, nullptr, OPTION_STRING, "list of plugins to disable" },
{ OPTION_LANGUAGE ";lang", "English", OPTION_STRING, "display language" },
+
+ { nullptr, nullptr, OPTION_HEADER, "HTTP SERVER OPTIONS" },
+ { OPTION_HTTP, "0", OPTION_BOOLEAN, "HTTP server enable" },
+ { OPTION_HTTP_PORT, "8080", OPTION_INTEGER, "HTTP server port" },
+ { OPTION_HTTP_ROOT, "web", OPTION_STRING, "HTTP server document root" },
+
{ nullptr }
};
diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h
index d8983101a3a..99b5463f540 100644
--- a/src/emu/emuopts.h
+++ b/src/emu/emuopts.h
@@ -190,6 +190,10 @@
#define OPTION_LANGUAGE "language"
+#define OPTION_HTTP "http"
+#define OPTION_HTTP_PORT "http_port"
+#define OPTION_HTTP_ROOT "http_root"
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -381,6 +385,11 @@ public:
const char *language() const { return value(OPTION_LANGUAGE); }
+ // Web server specific optopns
+ bool http() const { return bool_value(OPTION_HTTP); }
+ short http_port() const { return int_value(OPTION_HTTP_PORT); }
+ const char *http_root() const { return value(OPTION_HTTP_ROOT); }
+
// cache frequently used options in members
void update_cached_options();
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp
index 6f751a28dad..4d106912d7b 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -634,6 +634,8 @@ ioport_field::ioport_field(ioport_port &port, ioport_type type, ioport_value def
if (device().subtag(def->tag) == fulltag && def->mask == m_mask)
m_defvalue = def->defvalue & m_mask;
}
+
+ m_flags |= FIELD_FLAG_TOGGLE;
}
}
@@ -707,6 +709,24 @@ const input_seq &ioport_field::defseq(input_seq_type seqtype) const
//-------------------------------------------------
+// set_defseq - dynamically alter the default
+// input sequence for the given input field
+//-------------------------------------------------
+
+void ioport_field::set_defseq(input_seq_type seqtype, const input_seq &newseq)
+{
+ const bool was_changed = seq(seqtype) != defseq(seqtype);
+
+ // set the new sequence
+ m_seq[seqtype] = newseq;
+
+ // also update live state unless previously customized
+ if (m_live != nullptr && !was_changed)
+ m_live->seq[seqtype] = newseq;
+}
+
+
+//-------------------------------------------------
// type_class - return the type class for this
// field
//-------------------------------------------------
@@ -3112,13 +3132,6 @@ ioport_configurer& ioport_configurer::onoff_alloc(const char *name, ioport_value
// allocate a field normally
field_alloc(IPT_DIPSWITCH, defval, mask, name);
- // special case service mode
- if (name == DEF_STR(Service_Mode))
- {
- field_set_toggle();
- m_curfield->m_seq[SEQ_TYPE_STANDARD].set(KEYCODE_F2);
- }
-
// expand the diplocation
if (diplocation != nullptr)
field_set_diplocation(diplocation);
diff --git a/src/emu/ioport.h b/src/emu/ioport.h
index a9a4d49b0c4..a5169e08c21 100644
--- a/src/emu/ioport.h
+++ b/src/emu/ioport.h
@@ -1058,6 +1058,8 @@ public:
const input_seq &seq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const;
const input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const;
const input_seq &defseq_unresolved(input_seq_type seqtype = SEQ_TYPE_STANDARD) const { return m_seq[seqtype]; }
+ void set_defseq(const input_seq &newseq) { set_defseq(SEQ_TYPE_STANDARD, newseq); }
+ void set_defseq(input_seq_type seqtype, const input_seq &newseq);
bool has_dynamic_read() const { return !m_read.isnull(); }
bool has_dynamic_write() const { return !m_write.isnull(); }
diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp
index 91999a8307e..d528d9afd40 100644
--- a/src/emu/machine.cpp
+++ b/src/emu/machine.cpp
@@ -84,6 +84,9 @@
#include "network.h"
#include "ui/uimain.h"
#include <time.h>
+#include "server_http.hpp"
+#include "rapidjson/include/rapidjson/writer.h"
+#include "rapidjson/include/rapidjson/stringbuffer.h"
#if defined(EMSCRIPTEN)
#include <emscripten.h>
@@ -332,6 +335,8 @@ int running_machine::run(bool quiet)
if (m_saveload_schedule != SLS_NONE)
handle_saveload();
+ export_http_api();
+
// run the CPUs until a reset or exit
m_hard_reset_pending = false;
while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != SLS_NONE)
@@ -1176,7 +1181,32 @@ running_machine::logerror_callback_item::logerror_callback_item(logerror_callbac
{
}
-
+void running_machine::export_http_api()
+{
+ if (!options().http()) return;
+
+ m_manager.http_server()->on_get("/api/machine", [this](auto response, auto request)
+ {
+ rapidjson::StringBuffer s;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(s);
+ writer.StartObject();
+ writer.Key("name");
+ writer.String(m_basename.c_str());
+
+ writer.Key("devices");
+ writer.StartArray();
+
+ device_iterator iter(this->root_device());
+ for (device_t &device : iter)
+ writer.String(device.tag());
+
+ writer.EndArray();
+ writer.EndObject();
+
+ response->type("application/json");
+ response->status(200).send(s.GetString());
+ });
+}
//**************************************************************************
// SYSTEM TIME
diff --git a/src/emu/machine.h b/src/emu/machine.h
index cac9a3f38b6..2b14edfcd64 100644
--- a/src/emu/machine.h
+++ b/src/emu/machine.h
@@ -239,6 +239,7 @@ public:
void add_logerror_callback(logerror_callback callback);
void set_ui_active(bool active) { m_ui_active = active; }
void debug_break();
+ void export_http_api();
// TODO: Do saves and loads still require scheduling?
void immediate_save(const char *filename);
diff --git a/src/emu/main.cpp b/src/emu/main.cpp
new file mode 100644
index 00000000000..e8e07ea52b1
--- /dev/null
+++ b/src/emu/main.cpp
@@ -0,0 +1,208 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles
+/***************************************************************************
+
+main.cpp
+
+Controls execution of the core MAME system.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "main.h"
+#include "server_ws.hpp"
+#include "server_http.hpp"
+#include <fstream>
+
+const static struct mapping
+{
+ const char* extension;
+ const char* mime_type;
+} mappings[] =
+{
+ { "aac", "audio/aac" },
+ { "aat", "application/font-sfnt" },
+ { "aif", "audio/x-aif" },
+ { "arj", "application/x-arj-compressed" },
+ { "asf", "video/x-ms-asf" },
+ { "avi", "video/x-msvideo" },
+ { "bmp", "image/bmp" },
+ { "cff", "application/font-sfnt" },
+ { "css", "text/css" },
+ { "csv", "text/csv" },
+ { "doc", "application/msword" },
+ { "eps", "application/postscript" },
+ { "exe", "application/octet-stream" },
+ { "gif", "image/gif" },
+ { "gz", "application/x-gunzip" },
+ { "htm", "text/html" },
+ { "html", "text/html" },
+ { "ico", "image/x-icon" },
+ { "ief", "image/ief" },
+ { "jpeg", "image/jpeg" },
+ { "jpg", "image/jpeg" },
+ { "jpm", "image/jpm" },
+ { "jpx", "image/jpx" },
+ { "js", "application/javascript" },
+ { "json", "application/json" },
+ { "m3u", "audio/x-mpegurl" },
+ { "m4v", "video/x-m4v" },
+ { "mid", "audio/x-midi" },
+ { "mov", "video/quicktime" },
+ { "mp3", "audio/mpeg" },
+ { "mp4", "video/mp4" },
+ { "mpeg", "video/mpeg" },
+ { "mpg", "video/mpeg" },
+ { "oga", "audio/ogg" },
+ { "ogg", "audio/ogg" },
+ { "ogv", "video/ogg" },
+ { "otf", "application/font-sfnt" },
+ { "pct", "image/x-pct" },
+ { "pdf", "application/pdf" },
+ { "pfr", "application/font-tdpfr" },
+ { "pict", "image/pict" },
+ { "png", "image/png" },
+ { "ppt", "application/x-mspowerpoint" },
+ { "ps", "application/postscript" },
+ { "qt", "video/quicktime" },
+ { "ra", "audio/x-pn-realaudio" },
+ { "ram", "audio/x-pn-realaudio" },
+ { "rar", "application/x-arj-compressed" },
+ { "rgb", "image/x-rgb" },
+ { "rtf", "application/rtf" },
+ { "sgm", "text/sgml" },
+ { "shtm", "text/html" },
+ { "shtml", "text/html" },
+ { "sil", "application/font-sfnt" },
+ { "svg", "image/svg+xml" },
+ { "swf", "application/x-shockwave-flash" },
+ { "tar", "application/x-tar" },
+ { "tgz", "application/x-tar-gz" },
+ { "tif", "image/tiff" },
+ { "tiff", "image/tiff" },
+ { "torrent", "application/x-bittorrent" },
+ { "ttf", "application/font-sfnt" },
+ { "txt", "text/plain" },
+ { "wav", "audio/x-wav" },
+ { "webm", "video/webm" },
+ { "woff", "application/font-woff" },
+ { "wrl", "model/vrml" },
+ { "xhtml", "application/xhtml+xml" },
+ { "xls", "application/x-msexcel" },
+ { "xml", "text/xml" },
+ { "xsl", "application/xml" },
+ { "xslt", "application/xml" },
+ { "zip", "application/x-zip-compressed" }
+};
+
+static std::string extension_to_type(const std::string& extension)
+{
+ for (mapping m : mappings)
+ {
+ if (m.extension == extension)
+ {
+ return m.mime_type;
+ }
+ }
+
+ return "text/plain";
+}
+
+machine_manager::machine_manager(emu_options& options, osd_interface& osd)
+ : m_osd(osd),
+ m_options(options),
+ m_machine(nullptr),
+ m_io_context(std::make_shared<asio::io_context>())
+{
+}
+
+machine_manager::~machine_manager()
+{
+ if (options().http())
+ {
+ m_server->stop();
+ }
+ m_server_thread.join();
+}
+
+void machine_manager::start_http_server()
+{
+ if (options().http())
+ {
+ m_server = std::make_unique<webpp::http_server>();
+ m_server->m_config.port = options().http_port();
+ m_server->set_io_context(m_io_context);
+ m_wsserver = std::make_unique<webpp::ws_server>();
+
+ auto& endpoint = m_wsserver->endpoint["/"];
+
+ m_server->on_get([this](auto response, auto request) {
+ std::string doc_root = this->options().http_root();
+
+ std::string path = request->path;
+ // If path ends in slash (i.e. is a directory) then add "index.html".
+ if (path[path.size() - 1] == '/')
+ {
+ path += "index.html";
+ }
+
+ std::size_t last_qmark_pos = path.find_last_of("?");
+ if (last_qmark_pos != std::string::npos)
+ path = path.substr(0, last_qmark_pos - 1);
+
+ // Determine the file extension.
+ std::size_t last_slash_pos = path.find_last_of("/");
+ std::size_t last_dot_pos = path.find_last_of(".");
+ std::string extension;
+ if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos)
+ {
+ extension = path.substr(last_dot_pos + 1);
+ }
+
+ // Open the file to send back.
+ std::string full_path = doc_root + path;
+ std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary);
+ if (!is)
+ {
+ response->status(400).send("Error");
+ }
+
+ // Fill out the reply to be sent to the client.
+ std::string content;
+ char buf[512];
+ while (is.read(buf, sizeof(buf)).gcount() > 0)
+ content.append(buf, size_t(is.gcount()));
+
+ response->type(extension_to_type(extension));
+ response->status(200).send(content);
+
+ });
+
+ endpoint.on_open = [&](auto connection) {
+ auto send_stream = std::make_shared<webpp::ws_server::SendStream>();
+ *send_stream << "update_machine";
+ m_wsserver->send(connection, send_stream, [](const std::error_code& ec) { });
+ };
+
+ m_server->on_upgrade = [this](auto socket, auto request) {
+ auto connection = std::make_shared<webpp::ws_server::Connection>(socket);
+ connection->method = std::move(request->method);
+ connection->path = std::move(request->path);
+ connection->http_version = std::move(request->http_version);
+ connection->header = std::move(request->header);
+ connection->remote_endpoint_address = std::move(request->remote_endpoint_address);
+ connection->remote_endpoint_port = request->remote_endpoint_port;
+ m_wsserver->upgrade(connection);
+ };
+ m_server->start();
+ }
+}
+
+void machine_manager::start_context()
+{
+ m_server_thread = std::thread([this]() {
+ m_io_context->run();
+ });
+}
+
diff --git a/src/emu/main.h b/src/emu/main.h
index 12f0f1a9462..3a5f5a5c689 100644
--- a/src/emu/main.h
+++ b/src/emu/main.h
@@ -16,6 +16,7 @@
#ifndef MAME_EMU_MAIN_H
#define MAME_EMU_MAIN_H
+#include <thread>
#include <time.h>
//**************************************************************************
@@ -65,15 +66,24 @@ public:
// ======================> machine_manager
class ui_manager;
+namespace asio
+{
+ class io_context;
+}
+namespace webpp
+{
+ class http_server;
+ class ws_server;
+}
class machine_manager
{
DISABLE_COPYING(machine_manager);
protected:
// construction/destruction
- machine_manager(emu_options &options, osd_interface &osd) : m_osd(osd), m_options(options), m_machine(nullptr) { }
+ machine_manager(emu_options& options, osd_interface& osd);
public:
- virtual ~machine_manager() { }
+ virtual ~machine_manager();
osd_interface &osd() const { return m_osd; }
emu_options &options() const { return m_options; }
@@ -87,10 +97,18 @@ public:
virtual void ui_initialize(running_machine& machine) { }
virtual void update_machine() { }
+
+ void start_http_server();
+ void start_context();
+ webpp::http_server* http_server() const { return m_server.get(); }
protected:
osd_interface & m_osd; // reference to OSD system
emu_options & m_options; // reference to options
running_machine * m_machine;
+ std::shared_ptr<asio::io_context> m_io_context;
+ std::unique_ptr<webpp::http_server> m_server;
+ std::unique_ptr<webpp::ws_server> m_wsserver;
+ std::thread m_server_thread;
};
diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp
index ff7e371c438..fd785ef8139 100644
--- a/src/frontend/mame/clifront.cpp
+++ b/src/frontend/mame/clifront.cpp
@@ -309,9 +309,13 @@ int cli_frontend::execute(int argc, char **argv)
load_translation(m_options);
+ manager->start_http_server();
+
manager->start_luaengine();
- start_execution(manager, argc, argv, option_errors);
+ manager->start_context();
+
+ start_execution(manager, argc, argv, option_errors);
}
// handle exceptions of various types
catch (emu_fatalerror &fatal)
diff --git a/src/frontend/mame/info.cpp b/src/frontend/mame/info.cpp
index 0889dd7bd39..1479978ceb9 100644
--- a/src/frontend/mame/info.cpp
+++ b/src/frontend/mame/info.cpp
@@ -603,7 +603,7 @@ void info_xml_creator::output_rom(device_t &device)
if (bios_name[0] != 0)
util::stream_format(output, " bios=\"%s\"", util::xml::normalize_string(bios_name));
if (!is_disk)
- util::stream_format(output, " size=\"%d\"", rom_file_size(rom));
+ util::stream_format(output, " size=\"%u\"", rom_file_size(rom));
// dump checksum information only if there is a known dump
if (!hashes.flag(util::hash_collection::FLAG_NO_DUMP))
diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp
index 9de81cef6ec..18a2039e5d4 100644
--- a/src/frontend/mame/ui/info.cpp
+++ b/src/frontend/mame/ui/info.cpp
@@ -30,6 +30,7 @@ machine_info::machine_info(running_machine &machine)
m_has_dips = false;
m_has_bioses = false;
m_has_keyboard = false;
+ m_has_test_switch = false;
// scan the input port array to see what options we need to enable
for (auto &port : machine.ioport().ports())
@@ -43,6 +44,8 @@ machine_info::machine_info(running_machine &machine)
m_has_analog = true;
if (field.type() == IPT_KEYBOARD)
m_has_keyboard = true;
+ if (field.type() == IPT_SERVICE)
+ m_has_test_switch = true;
}
for (device_t &device : device_iterator(machine.root_device()))
diff --git a/src/frontend/mame/ui/info.h b/src/frontend/mame/ui/info.h
index 21d920e4131..b718c2acf64 100644
--- a/src/frontend/mame/ui/info.h
+++ b/src/frontend/mame/ui/info.h
@@ -29,6 +29,7 @@ public:
bool has_dips() const { return m_has_dips; }
bool has_bioses() const { return m_has_bioses; }
bool has_keyboard() const { return m_has_keyboard; }
+ bool has_test_switch() const { return m_has_test_switch; }
// text generators
std::string warnings_string();
@@ -46,6 +47,7 @@ private:
bool m_has_dips;
bool m_has_bioses;
bool m_has_keyboard;
+ bool m_has_test_switch;
};
class menu_game_info : public menu
diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp
index d7bf97a6562..bda9bdcf3be 100644
--- a/src/frontend/mame/ui/ui.cpp
+++ b/src/frontend/mame/ui/ui.cpp
@@ -256,6 +256,16 @@ void mame_ui_manager::initialize(running_machine &machine)
{
slider_current = nullptr;
}
+
+ // if no test switch found, assign its input sequence to a service mode DIP
+ if (!m_machine_info->has_test_switch() && m_machine_info->has_dips())
+ {
+ const char *const service_mode_dipname = ioport_configurer::string_from_token(DEF_STR(Service_Mode));
+ for (auto &port : machine.ioport().ports())
+ for (ioport_field &field : port.second->fields())
+ if (field.type() == IPT_DIPSWITCH && strcmp(field.name(), service_mode_dipname) == 0)
+ field.set_defseq(machine.ioport().type_seq(IPT_SERVICE));
+ }
}
diff --git a/src/lib/netlist/analog/nld_bjt.h b/src/lib/netlist/analog/nld_bjt.h
index e2da1bd529f..0c91d58bdb6 100644
--- a/src/lib/netlist/analog/nld_bjt.h
+++ b/src/lib/netlist/analog/nld_bjt.h
@@ -48,7 +48,7 @@ public:
{
}
- NETLIB_DYNAMIC()
+ NETLIB_IS_DYNAMIC()
//NETLIB_RESETI();
NETLIB_UPDATEI();
diff --git a/src/lib/netlist/analog/nld_fourterm.h b/src/lib/netlist/analog/nld_fourterm.h
index 7792607cf7a..723eccf77f5 100644
--- a/src/lib/netlist/analog/nld_fourterm.h
+++ b/src/lib/netlist/analog/nld_fourterm.h
@@ -115,7 +115,7 @@ public:
{
}
- NETLIB_DYNAMIC()
+ NETLIB_IS_DYNAMIC()
param_double_t m_cur_limit; /* current limit */
diff --git a/src/lib/netlist/analog/nld_twoterm.cpp b/src/lib/netlist/analog/nld_twoterm.cpp
index 089b11f8607..9818ea9f86f 100644
--- a/src/lib/netlist/analog/nld_twoterm.cpp
+++ b/src/lib/netlist/analog/nld_twoterm.cpp
@@ -45,6 +45,44 @@ void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double g
m_VtInv = 1.0 / m_Vt;
}
+void generic_diode::update_diode(const nl_double nVd)
+{
+#if 1
+ if (nVd < NL_FCONST(-5.0) * m_Vt)
+ {
+ m_Vd = nVd;
+ m_G = m_gmin;
+ m_Id = - m_Is;
+ }
+ else if (nVd < m_Vcrit)
+ {
+ m_Vd = nVd;
+ //m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
+ const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
+ m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
+ m_G = m_Is * m_VtInv * eVDVt + m_gmin;
+ }
+ else
+ {
+#if 1
+ const nl_double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99));
+ m_Vd = m_Vd + std::log1p(a) * m_Vt;
+#else
+ m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
+#endif
+ const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
+ m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
+
+ m_G = m_Is * m_VtInv * eVDVt + m_gmin;
+ }
+#else
+ m_Vd = m_Vd + 20.0 * m_Vt * std::tanh((nVd - m_Vd) / 20.0 / m_Vt);
+ const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
+ m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
+ m_G = m_Is * m_VtInv * eVDVt + m_gmin;
+#endif
+}
+
// ----------------------------------------------------------------------------------------
// nld_twoterm
// ----------------------------------------------------------------------------------------
@@ -101,14 +139,14 @@ NETLIB_UPDATE_PARAM(POT2)
NETLIB_RESET(C)
{
+ // FIXME: Startup conditions
set(netlist().gmin(), 0.0, -5.0 / netlist().gmin());
- //set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN);
+ //set(netlist().gmin(), 0.0, 0.0);
}
NETLIB_UPDATE_PARAM(C)
{
- //step_time(1.0/48000.0);
- m_GParallel = netlist().gmin() * m_C();
+ m_GParallel = netlist().gmin();
}
NETLIB_UPDATE(C)
@@ -116,6 +154,14 @@ NETLIB_UPDATE(C)
NETLIB_NAME(twoterm)::update();
}
+NETLIB_TIMESTEP(C)
+{
+ /* Gpar should support convergence */
+ const nl_double G = m_C() / step + m_GParallel;
+ const nl_double I = -G * deltaV();
+ set(G, 0.0, I);
+}
+
// ----------------------------------------------------------------------------------------
// nld_L
// ----------------------------------------------------------------------------------------
@@ -128,8 +174,7 @@ NETLIB_RESET(L)
NETLIB_UPDATE_PARAM(L)
{
- //step_time(1.0/48000.0);
- //m_GParallel = netlist().gmin() / m_L();
+ m_GParallel = netlist().gmin();
}
NETLIB_UPDATE(L)
@@ -137,6 +182,14 @@ NETLIB_UPDATE(L)
NETLIB_NAME(twoterm)::update();
}
+NETLIB_TIMESTEP(L)
+{
+ /* Gpar should support convergence */
+ m_I += m_I + m_G * deltaV();
+ m_G = step / m_L() + m_GParallel;
+ set(m_G, 0.0, m_I);
+}
+
// ----------------------------------------------------------------------------------------
// nld_D
// ----------------------------------------------------------------------------------------
diff --git a/src/lib/netlist/analog/nld_twoterm.h b/src/lib/netlist/analog/nld_twoterm.h
index f59b9e62594..2ff6db1e2c3 100644
--- a/src/lib/netlist/analog/nld_twoterm.h
+++ b/src/lib/netlist/analog/nld_twoterm.h
@@ -137,7 +137,9 @@ public:
return m_P.net().Q_Analog() - m_N.net().Q_Analog();
}
- void set_mat(nl_double a11, nl_double a12, nl_double a21, nl_double a22, nl_double r1, nl_double r2)
+ void set_mat(const nl_double a11, const nl_double a12,
+ const nl_double a21, const nl_double a22,
+ const nl_double r1, const nl_double r2)
{
/* GO, GT, I */
m_P.set(-a12, a11, -r1);
@@ -286,14 +288,8 @@ public:
//register_term("2", m_N);
}
- NETLIB_TIMESTEP()
- {
- /* Gpar should support convergence */
- const nl_double G = m_C() / step + m_GParallel;
- const nl_double I = -G * deltaV();
- set(G, 0.0, I);
- }
-
+ NETLIB_IS_TIMESTEP()
+ NETLIB_TIMESTEPI();
param_double_t m_C;
@@ -324,13 +320,8 @@ public:
//register_term("2", m_N);
}
- NETLIB_TIMESTEP()
- {
- /* Gpar should support convergence */
- m_I = m_I + m_G * deltaV();
- m_G = step / m_L() + m_GParallel;
- set(m_G, 0.0, m_I);
- }
+ NETLIB_IS_TIMESTEP()
+ NETLIB_TIMESTEPI();
param_double_t m_L;
@@ -354,43 +345,7 @@ class generic_diode
public:
generic_diode(device_t &dev, pstring name);
- inline void update_diode(const nl_double nVd)
- {
-#if 1
- if (nVd < NL_FCONST(-5.0) * m_Vt)
- {
- m_Vd = nVd;
- m_G = m_gmin;
- m_Id = - m_Is;
- }
- else if (nVd < m_Vcrit)
- {
- m_Vd = nVd;
- //m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
- }
- else
- {
-#if 1
- const nl_double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(0.5) - NL_FCONST(1.0));
- m_Vd = m_Vd + std::log1p(a) * m_Vt;
-#else
- m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
-#endif
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
-
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
- }
-#else
- m_Vd = m_Vd + 20.0 * m_Vt * std::tanh((nVd - m_Vd) / 20.0 / m_Vt);
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
-#endif
- }
+ void update_diode(const nl_double nVd);
void set_param(const nl_double Is, const nl_double n, nl_double gmin);
@@ -430,7 +385,7 @@ public:
register_subalias("K", m_N);
}
- NETLIB_DYNAMIC()
+ NETLIB_IS_DYNAMIC()
NETLIB_UPDATE_TERMINALSI();
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index 171ba4cf5bb..cddb4751146 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -49,6 +49,7 @@ POBJS := \
$(POBJ)/palloc.o \
$(POBJ)/pchrono.o \
$(POBJ)/pdynlib.o \
+ $(POBJ)/pexception.o \
$(POBJ)/pfmtlog.o \
$(POBJ)/poptions.o \
$(POBJ)/pparser.o \
diff --git a/src/lib/netlist/devices/net_lib.cpp b/src/lib/netlist/devices/net_lib.cpp
index bc391e98728..9f23283ac6b 100644
--- a/src/lib/netlist/devices/net_lib.cpp
+++ b/src/lib/netlist/devices/net_lib.cpp
@@ -63,7 +63,7 @@ NETLIST_END()
#define ENTRY1(nic, name, defparam) factory.register_device<nic>( # name, xstr(nic), defparam );
#define ENTRY(nic, name, defparam) ENTRY1(NETLIB_NAME(nic), name, defparam)
-#define NETLIB_DEVICE_DECL(chip) extern factory_creator_ptr_t decl_ ## chip;
+#define NETLIB_DEVICE_DECL(chip) extern factory::constructor_ptr_t decl_ ## chip;
#define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (# name, xstr(nic), defparam) );
#define ENTRYX(nic, name, defparam) { NETLIB_DEVICE_DECL(nic) ENTRYX1(NETLIB_NAME(nic), name, defparam, decl_ ## nic) }
@@ -72,7 +72,7 @@ namespace netlist
{
namespace devices
{
-static void initialize_factory(factory_list_t &factory)
+static void initialize_factory(factory::list_t &factory)
{
ENTRY(R, RES, "R")
ENTRY(POT, POT, "R")
@@ -80,15 +80,15 @@ static void initialize_factory(factory_list_t &factory)
ENTRY(C, CAP, "C")
ENTRY(L, IND, "L")
ENTRY(D, DIODE, "MODEL")
- ENTRY(VCVS, VCVS, "-")
- ENTRY(VCCS, VCCS, "-")
- ENTRY(CCCS, CCCS, "-")
- ENTRY(LVCCS, LVCCS, "-")
+ ENTRY(VCVS, VCVS, "")
+ ENTRY(VCCS, VCCS, "")
+ ENTRY(CCCS, CCCS, "")
+ ENTRY(LVCCS, LVCCS, "")
ENTRY(VS, VS, "V")
ENTRY(CS, CS, "I")
ENTRY(OPAMP, OPAMP, "MODEL")
- ENTRYX(dummy_input, DUMMY_INPUT, "-")
- ENTRYX(frontier, FRONTIER_DEV, "+I,G,Q") // not intended to be used directly
+ ENTRYX(dummy_input, DUMMY_INPUT, "")
+ ENTRYX(frontier, FRONTIER_DEV, "+I,+G,+Q") // not intended to be used directly
ENTRYX(function, AFUNC, "N,FUNC") // only for macro devices - NO FEEDBACK loops
ENTRY(QBJT_EB, QBJT_EB, "MODEL")
ENTRY(QBJT_switch, QBJT_SW, "MODEL")
@@ -96,106 +96,107 @@ static void initialize_factory(factory_list_t &factory)
ENTRYX(logic_input, LOGIC_INPUT, "IN,FAMILY")
ENTRYX(analog_input, ANALOG_INPUT, "IN")
ENTRYX(log, LOG, "+I")
- ENTRYX(logD, LOGD, "+I,I2")
+ ENTRYX(logD, LOGD, "+I,+I2")
ENTRYX(clock, CLOCK, "FREQ")
ENTRYX(extclock, EXTCLOCK, "FREQ")
ENTRYX(mainclock, MAINCLOCK, "FREQ")
- ENTRYX(gnd, GND, "-")
- ENTRYX(netlistparams, PARAMETER, "-")
+ ENTRYX(gnd, GND, "")
+ ENTRYX(netlistparams, PARAMETER, "")
ENTRY(solver, SOLVER, "FREQ")
- ENTRYX(res_sw, RES_SWITCH, "+IN,P1,P2")
- ENTRY(switch1, SWITCH, "-")
- ENTRY(switch2, SWITCH2, "-")
- ENTRYX(nicRSFF, NETDEV_RSFF, "+S,R")
- ENTRYX(nicDelay, NETDEV_DELAY, "-")
- ENTRYX(2716, EPROM_2716, "+GQ,EPQ,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10")
- ENTRYX(2102A, RAM_2102A, "+CEQ,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,RWQ,DI")
- ENTRYX(7450, TTL_7450_ANDORINVERT, "+A,B,C,D")
- ENTRYX(7448, TTL_7448, "+A,B,C,D,LTQ,BIQ,RBIQ")
- ENTRYX(7473, TTL_7473, "+CLK,J,K,CLRQ")
- ENTRYX(7473A, TTL_7473A, "+CLK,J,K,CLRQ")
- ENTRYX(7474, TTL_7474, "+CLK,D,CLRQ,PREQ")
- ENTRYX(7475, TTL_7475, "-")
- ENTRYX(7477, TTL_7477, "-")
- ENTRYX(7483, TTL_7483, "+A1,A2,A3,A4,B1,B2,B3,B4,C0")
- ENTRYX(7485, TTL_7485, "+A0,A1,A2,A3,B0,B1,B2,B3,LTIN,EQIN,GTIN")
- ENTRYX(7490, TTL_7490, "+A,B,R1,R2,R91,R92")
- ENTRYX(7493, TTL_7493, "+CLKA,CLKB,R1,R2")
- ENTRYX(74107, TTL_74107, "+CLK,J,K,CLRQ")
- ENTRYX(74107A, TTL_74107A, "+CLK,J,K,CLRQ")
- ENTRYX(74123, TTL_74123, "-")
- ENTRYX(74153, TTL_74153, "+C0,C1,C2,C3,A,B,G")
- ENTRYX(74161, TTL_74161, "+A,B,C,D,CLRQ,LOADQ,CLK,ENABLEP,ENABLET")
- ENTRYX(74165, TTL_74165, "+CLK,CLKINH,SH_LDQ,SER,A,B,C,D,E,F,G,H")
- ENTRYX(74166, TTL_74166, "+CLK,CLKINH,SH_LDQ,SER,A,B,C,D,E,F,G,H,CLRQ")
- ENTRYX(74174, TTL_74174, "+CLK,D1,D2,D3,D4,D5,D6,CLRQ")
- ENTRYX(74175, TTL_74175, "+CLK,D1,D2,D3,D4,CLRQ")
- ENTRYX(74192, TTL_74192, "+A,B,C,D,CLEAR,LOADQ,CU,CD")
- ENTRYX(74193, TTL_74193, "+A,B,C,D,CLEAR,LOADQ,CU,CD")
- ENTRYX(74194, TTL_74194, "+CLK,S0,S1,SRIN,A,B,C,D,SLIN,CLRQ")
- ENTRYX(74365, TTL_74365, "+G1Q,G2Q,A1,A2,A3,A4,A5,A6")
- //ENTRY(74279, TTL_74279, "-") // only dip available
+ ENTRYX(res_sw, RES_SWITCH, "+IN,+P1,+P2")
+ ENTRY(switch1, SWITCH, "")
+ ENTRY(switch2, SWITCH2, "")
+ ENTRYX(nicRSFF, NETDEV_RSFF, "+S,+R")
+ ENTRYX(nicDelay, NETDEV_DELAY, "")
+ ENTRYX(2716, EPROM_2716, "+GQ,+EPQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10")
+ ENTRYX(2102A, RAM_2102A, "+CEQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+RWQ,+DI")
+ ENTRYX(7450, TTL_7450_ANDORINVERT, "+A,+B,+C,+D")
+ ENTRYX(7448, TTL_7448, "+A,+B,+C,+D,+LTQ,+BIQ,+RBIQ")
+ ENTRYX(7473, TTL_7473, "+CLK,+J,+K,+CLRQ")
+ ENTRYX(7473A, TTL_7473A, "+CLK,+J,+K,+CLRQ")
+ ENTRYX(7474, TTL_7474, "+CLK,+D,+CLRQ,+PREQ")
+ ENTRYX(7475, TTL_7475, "")
+ ENTRYX(7477, TTL_7477, "")
+ ENTRYX(7483, TTL_7483, "+A1,+A2,+A3,+A4,+B1,+B2,+B3,+B4,+C0")
+ ENTRYX(7485, TTL_7485, "+A0,+A1,+A2,+A3,+B0,+B1,+B2,+B3,+LTIN,+EQIN,+GTIN")
+ ENTRYX(7490, TTL_7490, "+A,+B,+R1,+R2,+R91,+R92")
+ ENTRYX(7493, TTL_7493, "+CLKA,+CLKB,+R1,+R2")
+ ENTRYX(74107, TTL_74107, "+CLK,+J,+K,+CLRQ")
+ ENTRYX(74107A, TTL_74107A, "+CLK,+J,+K,+CLRQ")
+ ENTRYX(74123, TTL_74123, "")
+ ENTRYX(74153, TTL_74153, "+C0,+C1,+C2,+C3,+A,+B,+G")
+ ENTRYX(74161, TTL_74161, "+A,+B,+C,+D,+CLRQ,+LOADQ,+CLK,+ENABLEP,+ENABLET")
+ ENTRYX(74165, TTL_74165, "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H")
+ ENTRYX(74166, TTL_74166, "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H,+CLRQ")
+ ENTRYX(74174, TTL_74174, "+CLK,+D1,+D2,+D3,+D4,+D5,+D6,+CLRQ")
+ ENTRYX(74175, TTL_74175, "+CLK,+D1,+D2,+D3,+D4,+CLRQ")
+ ENTRYX(74192, TTL_74192, "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD")
+ ENTRYX(74193, TTL_74193, "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD")
+ ENTRYX(74194, TTL_74194, "+CLK,+S0,+S1,+SRIN,+A,+B,+C,+D,+SLIN,+CLRQ")
+ ENTRYX(74365, TTL_74365, "+G1Q,+G2Q,+A1,+A2,+A3,+A4,+A5,+A6")
+ //ENTRY(74279, TTL_74279, "") // only dip available
ENTRYX(SN74LS629, SN74LS629, "CAP")
- ENTRYX(82S16, TTL_82S16, "-")
- ENTRYX(82S115, PROM_82S115, "+CE1Q,CE2,A0,A1,A2,A3,A4,A5,A6,A7,A8,STROBE")
- ENTRYX(82S123, PROM_82S123, "+CEQ,A0,A1,A2,A3,A4")
- ENTRYX(82S126, PROM_82S126, "+CE1Q,CE2Q,A0,A1,A2,A3,A4,A5,A6,A7")
- ENTRYX(9310, TTL_9310, "-")
- ENTRYX(9312, TTL_9312, "+A,B,C,D0,D1,D2,D3,D4,D5,D6,D7,G")
- ENTRYX(9316, TTL_9316, "+CLK,ENP,ENT,CLRQ,LOADQ,A,B,C,D")
- ENTRYX(9322, TTL_9322, "+SELECT,A1,B1,A2,B2,A3,B3,A4,B4,STROBE")
- ENTRYX(9334, TTL_9334, "+CQ,EQ,D,A0,A1,A2")
- ENTRYX(AM2847, TTL_AM2847, "+CP,INA,INB,INC,IND,RCA,RCB,RCC,RCD")
+ ENTRYX(82S16, TTL_82S16, "")
+ ENTRYX(82S115, PROM_82S115, "+CE1Q,+CE2,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+STROBE")
+ ENTRYX(82S123, PROM_82S123, "+CEQ,+A0,+A1,+A2,+A3,+A4")
+ ENTRYX(82S126, PROM_82S126, "+CE1Q,+CE2Q,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7")
+ ENTRYX(9310, TTL_9310, "")
+ ENTRYX(9312, TTL_9312, "+A,+B,+C,+D0,+D1,+D2,+D3,+D4,+D5,+D6,+D7,+G")
+ ENTRYX(9316, TTL_9316, "+CLK,+ENP,+ENT,+CLRQ,+LOADQ,+A,+B,+C,+D")
+ ENTRYX(9322, TTL_9322, "+SELECT,+A1,+B1,+A2,+B2,+A3,+B3,+A4,+B4,+STROBE")
+ ENTRYX(9334, TTL_9334, "+CQ,+EQ,+D,+A0,+A1,+A2")
+ ENTRYX(AM2847, TTL_AM2847, "+CP,+INA,+INB,+INC,+IND,+RCA,+RCB,+RCC,+RCD")
ENTRYX(CD4020, CD4020, "")
ENTRYX(CD4066_GATE, CD4066_GATE, "")
+ ENTRYX(CD4316_GATE, CD4316_GATE, "")
/* entries with suffix WI are legacy only */
- ENTRYX(CD4020, CD4020_WI, "+IP,RESET,VDD,VSS")
+ ENTRYX(CD4020, CD4020_WI, "+IP,+RESET,+VDD,+VSS")
//ENTRY(4066, CD_4066, "+A,B")
- ENTRYX(NE555, NE555, "-")
+ ENTRYX(NE555, NE555, "")
ENTRYX(r2r_dac, R2R_DAC, "VIN,R,N")
- ENTRYX(tristate, TTL_TRISTATE, "+CEQ1,D1,CEQ2,D2")
- ENTRYX(tristate3, TTL_TRISTATE3, "-")
- ENTRYX(2102A_dip, RAM_2102A_DIP, "-")
- ENTRYX(2716_dip, EPROM_2716_DIP, "-")
- ENTRYX(4538_dip, CD4538_DIP, "-")
- ENTRYX(7448_dip, TTL_7448_DIP, "-")
- ENTRYX(7450_dip, TTL_7450_DIP, "-")
- ENTRYX(7473_dip, TTL_7473_DIP, "-")
- ENTRYX(7473A_dip, TTL_7473A_DIP, "-")
- ENTRYX(7474_dip, TTL_7474_DIP, "-")
- ENTRYX(7475_dip, TTL_7475_DIP, "-")
- ENTRYX(7477_dip, TTL_7477_DIP, "-")
- ENTRYX(7483_dip, TTL_7483_DIP, "-")
- ENTRYX(7485_dip, TTL_7485_DIP, "-")
- ENTRYX(7490_dip, TTL_7490_DIP, "-")
- ENTRYX(7493_dip, TTL_7493_DIP, "-")
- ENTRYX(74107_dip, TTL_74107_DIP, "-")
- ENTRYX(74123_dip, TTL_74123_DIP, "-")
- ENTRYX(74153_dip, TTL_74153_DIP, "-")
- ENTRYX(74161_dip, TTL_74161_DIP, "-")
- ENTRYX(74165_dip, TTL_74165_DIP, "-")
- ENTRYX(74166_dip, TTL_74166_DIP, "-")
- ENTRYX(74174_dip, TTL_74174_DIP, "-")
- ENTRYX(74175_dip, TTL_74175_DIP, "-")
- ENTRYX(74192_dip, TTL_74192_DIP, "-")
- ENTRYX(74193_dip, TTL_74193_DIP, "-")
- ENTRYX(74194_dip, TTL_74194_DIP, "-")
- ENTRYX(74279_dip, TTL_74279_DIP, "-")
- ENTRYX(74365_dip, TTL_74365_DIP, "-")
- ENTRYX(82S16_dip, TTL_82S16_DIP, "-")
- ENTRYX(82S115_dip, PROM_82S115_DIP, "-")
- ENTRYX(82S123_dip, PROM_82S123_DIP, "-")
- ENTRYX(82S126_dip, PROM_82S126_DIP, "-")
- ENTRYX(9602_dip, TTL_9602_DIP, "-")
- ENTRYX(9310_dip, TTL_9310_DIP, "-")
- ENTRYX(9312_dip, TTL_9312_DIP, "-")
- ENTRYX(9316_dip, TTL_9316_DIP, "-")
- ENTRYX(9322_dip, TTL_9322_DIP, "-")
- ENTRYX(9334_dip, TTL_9334_DIP, "-")
- ENTRYX(AM2847_dip, TTL_AM2847_DIP, "-")
+ ENTRYX(tristate, TTL_TRISTATE, "+CEQ1,+D1,+CEQ2,+D2")
+ ENTRYX(tristate3, TTL_TRISTATE3, "")
+ ENTRYX(2102A_dip, RAM_2102A_DIP, "")
+ ENTRYX(2716_dip, EPROM_2716_DIP, "")
+ ENTRYX(4538_dip, CD4538_DIP, "")
+ ENTRYX(7448_dip, TTL_7448_DIP, "")
+ ENTRYX(7450_dip, TTL_7450_DIP, "")
+ ENTRYX(7473_dip, TTL_7473_DIP, "")
+ ENTRYX(7473A_dip, TTL_7473A_DIP, "")
+ ENTRYX(7474_dip, TTL_7474_DIP, "")
+ ENTRYX(7475_dip, TTL_7475_DIP, "")
+ ENTRYX(7477_dip, TTL_7477_DIP, "")
+ ENTRYX(7483_dip, TTL_7483_DIP, "")
+ ENTRYX(7485_dip, TTL_7485_DIP, "")
+ ENTRYX(7490_dip, TTL_7490_DIP, "")
+ ENTRYX(7493_dip, TTL_7493_DIP, "")
+ ENTRYX(74107_dip, TTL_74107_DIP, "")
+ ENTRYX(74123_dip, TTL_74123_DIP, "")
+ ENTRYX(74153_dip, TTL_74153_DIP, "")
+ ENTRYX(74161_dip, TTL_74161_DIP, "")
+ ENTRYX(74165_dip, TTL_74165_DIP, "")
+ ENTRYX(74166_dip, TTL_74166_DIP, "")
+ ENTRYX(74174_dip, TTL_74174_DIP, "")
+ ENTRYX(74175_dip, TTL_74175_DIP, "")
+ ENTRYX(74192_dip, TTL_74192_DIP, "")
+ ENTRYX(74193_dip, TTL_74193_DIP, "")
+ ENTRYX(74194_dip, TTL_74194_DIP, "")
+ ENTRYX(74279_dip, TTL_74279_DIP, "")
+ ENTRYX(74365_dip, TTL_74365_DIP, "")
+ ENTRYX(82S16_dip, TTL_82S16_DIP, "")
+ ENTRYX(82S115_dip, PROM_82S115_DIP, "")
+ ENTRYX(82S123_dip, PROM_82S123_DIP, "")
+ ENTRYX(82S126_dip, PROM_82S126_DIP, "")
+ ENTRYX(9602_dip, TTL_9602_DIP, "")
+ ENTRYX(9310_dip, TTL_9310_DIP, "")
+ ENTRYX(9312_dip, TTL_9312_DIP, "")
+ ENTRYX(9316_dip, TTL_9316_DIP, "")
+ ENTRYX(9322_dip, TTL_9322_DIP, "")
+ ENTRYX(9334_dip, TTL_9334_DIP, "")
+ ENTRYX(AM2847_dip, TTL_AM2847_DIP, "")
ENTRYX(SN74LS629_dip, SN74LS629_DIP, "1.CAP1,2.CAP2")
- ENTRYX(NE555_dip, NE555_DIP, "-")
- ENTRYX(MM5837_dip, MM5837_DIP, "-")
+ ENTRYX(NE555_dip, NE555_DIP, "")
+ ENTRYX(MM5837_dip, MM5837_DIP, "")
}
} //namespace devices
@@ -203,7 +204,7 @@ static void initialize_factory(factory_list_t &factory)
namespace netlist
{
- void initialize_factory(factory_list_t &factory)
+ void initialize_factory(factory::list_t &factory)
{
devices::initialize_factory(factory);
}
diff --git a/src/lib/netlist/devices/net_lib.h b/src/lib/netlist/devices/net_lib.h
index c9c0b6b3917..585df6aa369 100644
--- a/src/lib/netlist/devices/net_lib.h
+++ b/src/lib/netlist/devices/net_lib.h
@@ -81,7 +81,7 @@ NETLIST_EXTERNAL(bjt_models)
NETLIST_EXTERNAL(family_models)
namespace netlist {
- void initialize_factory(netlist::factory_list_t &factory);
+ void initialize_factory(factory::list_t &factory);
}
#endif
diff --git a/src/lib/netlist/devices/nld_7448.cpp b/src/lib/netlist/devices/nld_7448.cpp
index 56b322dbc2f..8b4d11c374b 100644
--- a/src/lib/netlist/devices/nld_7448.cpp
+++ b/src/lib/netlist/devices/nld_7448.cpp
@@ -62,7 +62,7 @@ namespace netlist
register_subalias("2", m_C);
register_subalias("3", m_LTQ);
register_subalias("4", m_BIQ);
- register_subalias("5",m_RBIQ);
+ register_subalias("5", m_RBIQ);
register_subalias("6", m_D);
register_subalias("7", m_A);
diff --git a/src/lib/netlist/devices/nld_7493.cpp b/src/lib/netlist/devices/nld_7493.cpp
index 6e96facabae..a87aada2cd6 100644
--- a/src/lib/netlist/devices/nld_7493.cpp
+++ b/src/lib/netlist/devices/nld_7493.cpp
@@ -71,7 +71,7 @@ namespace netlist
{
NETLIB_CONSTRUCTOR_DERIVED(7493_dip, 7493)
{
- register_subalias("1", B.m_I);
+ register_subalias("1", "CLKB");
register_subalias("2", m_R1);
register_subalias("3", m_R2);
@@ -80,13 +80,13 @@ namespace netlist
// register_subalias("6", ); --> NC
// register_subalias("7", ); --> NC
- register_subalias("8", C.m_Q);
- register_subalias("9", B.m_Q);
+ register_subalias("8", "QC");
+ register_subalias("9", "QB");
// register_subalias("10", ); -. GND
- register_subalias("11", D.m_Q);
- register_subalias("12", A.m_Q);
+ register_subalias("11", "QD");
+ register_subalias("12", "QA");
// register_subalias("13", ); -. NC
- register_subalias("14", A.m_I);
+ register_subalias("14", "CLKA");
}
};
diff --git a/src/lib/netlist/devices/nld_mm5837.cpp b/src/lib/netlist/devices/nld_mm5837.cpp
index 41d2fea9e34..6f705e8ccf0 100644
--- a/src/lib/netlist/devices/nld_mm5837.cpp
+++ b/src/lib/netlist/devices/nld_mm5837.cpp
@@ -19,15 +19,15 @@ namespace netlist
NETLIB_OBJECT(MM5837_dip)
{
NETLIB_CONSTRUCTOR(MM5837_dip)
- , m_RV(*this, "RV")
+ , m_RV(*this, "_RV")
, m_VDD(*this, "1")
, m_VGG(*this, "2")
, m_VSS(*this, "4")
- , m_V0(*this, "_Q")
+ , m_FREQ(*this, "FREQ", 24000)
/* clock */
- , m_feedback(*this, "FB")
- , m_Q(*this, "Q")
- , m_inc(netlist_time::from_hz(56000))
+ , m_feedback(*this, "_FB")
+ , m_Q(*this, "_Q")
+ , m_inc(netlist_time::from_hz(24000))
, m_shift(*this, "m_shift", 0)
, m_is_timestep(false)
{
@@ -36,7 +36,7 @@ namespace netlist
/* output */
//register_term("_RV1", m_RV.m_P);
//register_term("_RV2", m_RV.m_N);
- connect_late(m_RV.m_N, m_V0);
+ connect_late(m_RV.m_N, m_VDD);
/* device */
register_subalias("3", m_RV.m_P);
@@ -44,20 +44,19 @@ namespace netlist
NETLIB_RESETI();
NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI();
protected:
NETLIB_SUB(twoterm) m_RV;
analog_input_t m_VDD;
analog_input_t m_VGG;
analog_input_t m_VSS;
-
- /* output stage */
- analog_output_t m_V0; /* could be gnd as well */
+ param_double_t m_FREQ;
/* clock stage */
logic_input_t m_feedback;
logic_output_t m_Q;
- const netlist_time m_inc;
+ netlist_time m_inc;
/* state */
state_var_u32 m_shift;
@@ -71,14 +70,24 @@ namespace netlist
//m_V0.initial(0.0);
//m_RV.do_reset();
m_RV.set(NL_FCONST(1.0) / R_LOW, 0.0, 0.0);
+ m_inc = netlist_time::from_hz(m_FREQ());
+ if (m_FREQ() < 24000 || m_FREQ() > 56000)
+ netlist().log().warning("MM5837: Frequency outside of specs.", m_FREQ());
m_shift = 0x1ffff;
m_is_timestep = m_RV.m_P.net().solver()->is_timestep();
}
+ NETLIB_UPDATE_PARAM(MM5837_dip)
+ {
+ m_inc = netlist_time::from_hz(m_FREQ());
+ if (m_FREQ() < 24000 || m_FREQ() > 56000)
+ netlist().log().warning("MM5837: Frequency outside of specs.", m_FREQ());
+ }
+
NETLIB_UPDATE(MM5837_dip)
{
- m_Q.push(!m_Q.net().new_Q(), m_inc);
+ m_Q.push(!m_feedback.Q(), m_inc);
/* shift register
*
diff --git a/src/lib/netlist/devices/nld_truthtable.h b/src/lib/netlist/devices/nld_truthtable.h
index 2be1e978367..564699cd89b 100644
--- a/src/lib/netlist/devices/nld_truthtable.h
+++ b/src/lib/netlist/devices/nld_truthtable.h
@@ -366,13 +366,13 @@ namespace netlist
plib::pstring_vector_t m_desc;
};
- class netlist_base_factory_truthtable_t : public base_factory_t
+ class netlist_base_factory_truthtable_t : public factory::element_t
{
P_PREVENT_COPYING(netlist_base_factory_truthtable_t)
public:
netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname,
const pstring &def_param)
- : base_factory_t(name, classname, def_param), m_family(family_TTL())
+ : factory::element_t(name, classname, def_param), m_family(family_TTL())
{}
virtual ~netlist_base_factory_truthtable_t()
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h
index ff08177cfdb..89251264fa7 100644
--- a/src/lib/netlist/devices/nlid_system.h
+++ b/src/lib/netlist/devices/nlid_system.h
@@ -413,45 +413,6 @@ namespace netlist
state_var<netlist_sig_t> m_last_state;
};
- // -----------------------------------------------------------------------------
- // factory class to wrap macro based chips/elements
- // -----------------------------------------------------------------------------
-
- class factory_lib_entry_t : public base_factory_t
- {
- P_PREVENT_COPYING(factory_lib_entry_t)
- public:
-
- factory_lib_entry_t(setup_t &setup, const pstring &name, const pstring &classname,
- const pstring &def_param)
- : base_factory_t(name, classname, def_param), m_setup(setup) { }
-
- class wrapper : public device_t
- {
- public:
- wrapper(const pstring &devname, netlist_t &anetlist, const pstring &name)
- : device_t(anetlist, name), m_devname(devname)
- {
- anetlist.setup().namespace_push(name);
- anetlist.setup().include(m_devname);
- anetlist.setup().namespace_pop();
- }
- protected:
- NETLIB_RESETI() { }
- NETLIB_UPDATEI() { }
-
- pstring m_devname;
- };
-
- plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
- {
- return plib::owned_ptr<device_t>::Create<wrapper>(this->name(), anetlist, name);
- }
-
- private:
- setup_t &m_setup;
- };
-
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/macro/nlm_cd4xxx.cpp b/src/lib/netlist/macro/nlm_cd4xxx.cpp
index d169e2790f5..469ff13b954 100644
--- a/src/lib/netlist/macro/nlm_cd4xxx.cpp
+++ b/src/lib/netlist/macro/nlm_cd4xxx.cpp
@@ -33,13 +33,13 @@ static NETLIST_START(CD4001_DIP)
DUMMY_INPUT(VDD)
DIPPINS( /* +--------------+ */
- s1.A, /* A1 |1 ++ 14| VCC */ VSS.I,
+ s1.A, /* A1 |1 ++ 14| VCC */ VDD.I,
s1.B, /* B1 |2 13| A6 */ s4.B,
s1.Q, /* A2 |3 12| Y6 */ s4.A,
s2.Q, /* Y2 |4 4001 11| A5 */ s4.Q,
s2.A, /* A3 |5 10| Y5 */ s3.Q,
s2.B, /* Y3 |6 9| A4 */ s3.B,
- VDD.I, /* GND |7 8| Y4 */ s3.A
+ VSS.I, /* GND |7 8| Y4 */ s3.A
/* +--------------+ */
)
diff --git a/src/lib/netlist/macro/nlm_opamp.cpp b/src/lib/netlist/macro/nlm_opamp.cpp
index 5c68cfc86a3..146f95b72b4 100644
--- a/src/lib/netlist/macro/nlm_opamp.cpp
+++ b/src/lib/netlist/macro/nlm_opamp.cpp
@@ -52,7 +52,7 @@ static NETLIST_START(opamp_layout_2_13_9_4)
A.GND, /* |4 11| */ NC,
B.N1, /* |5 10| */ B.OUT,
B.PLUS, /* |6 9| */ B.VCC,
- B.MINUS /* |7 8| */ B.N2
+ B.MINUS, /* |7 8| */ B.N2
/* +--------------+ */
)
NET_C(A.GND, B.GND)
diff --git a/src/lib/netlist/macro/nlm_ttl74xx.cpp b/src/lib/netlist/macro/nlm_ttl74xx.cpp
index 2120d88eb3f..c66314366d2 100644
--- a/src/lib/netlist/macro/nlm_ttl74xx.cpp
+++ b/src/lib/netlist/macro/nlm_ttl74xx.cpp
@@ -588,7 +588,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7400_NAND, 2, 1, "A,B")
+ TRUTHTABLE_START(TTL_7400_NAND, 2, 1, "+A,+B")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|1|22")
TT_LINE("X,0|1|22")
@@ -604,7 +604,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7402_NOR, 2, 1, "A,B")
+ TRUTHTABLE_START(TTL_7402_NOR, 2, 1, "+A,+B")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|1|22")
TT_LINE("X,1|0|15")
@@ -619,7 +619,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7404_INVERT, 1, 1, "A")
+ TRUTHTABLE_START(TTL_7404_INVERT, 1, 1, "+A")
TT_HEAD(" A | Q ")
TT_LINE(" 0 | 1 |22")
TT_LINE(" 1 | 0 |15")
@@ -634,7 +634,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7408_AND, 2, 1, "A,B")
+ TRUTHTABLE_START(TTL_7408_AND, 2, 1, "+A,+B")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|0|15")
TT_LINE("X,0|0|15")
@@ -642,7 +642,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7410_NAND, 3, 1, "A,B,C")
+ TRUTHTABLE_START(TTL_7410_NAND, 3, 1, "+A,+B,+C")
TT_HEAD("A,B,C|Q ")
TT_LINE("0,X,X|1|22")
TT_LINE("X,0,X|1|22")
@@ -660,7 +660,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7411_AND, 3, 1, "A,B,C")
+ TRUTHTABLE_START(TTL_7411_AND, 3, 1, "+A,+B,+C")
TT_HEAD("A,B,C|Q ")
TT_LINE("0,X,X|0|15")
TT_LINE("X,0,X|0|15")
@@ -696,7 +696,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7420_NAND, 4, 1, "A,B,C,D")
+ TRUTHTABLE_START(TTL_7420_NAND, 4, 1, "+A,+B,+C,+D")
TT_HEAD("A,B,C,D|Q ")
TT_LINE("0,X,X,X|1|22")
TT_LINE("X,0,X,X|1|22")
@@ -716,7 +716,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7425_NOR, 4, 1, "A,B,C,D")
+ TRUTHTABLE_START(TTL_7425_NOR, 4, 1, "+A,+B,+C,+D")
TT_HEAD("A,B,C,D|Q ")
TT_LINE("1,X,X,X|0|15")
TT_LINE("X,1,X,X|0|15")
@@ -735,7 +735,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7427_NOR, 3, 1, "A,B,C")
+ TRUTHTABLE_START(TTL_7427_NOR, 3, 1, "+A,+B,+C")
TT_HEAD("A,B,C|Q ")
TT_LINE("1,X,X|0|15")
TT_LINE("X,1,X|0|15")
@@ -758,7 +758,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7430_NAND, 8, 1, "A,B,C,D,E,F,G,H")
+ TRUTHTABLE_START(TTL_7430_NAND, 8, 1, "+A,+B,+C,+D,+E,+F,+G,+H")
TT_HEAD("A,B,C,D,E,F,G,H|Q ")
TT_LINE("0,X,X,X,X,X,X,X|1|22")
TT_LINE("X,0,X,X,X,X,X,X|1|22")
@@ -780,7 +780,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7432_OR, 2, 1, "A,B")
+ TRUTHTABLE_START(TTL_7432_OR, 2, 1, "+A,+B")
TT_HEAD("A,B|Q ")
TT_LINE("1,X|1|22")
TT_LINE("X,1|1|22")
@@ -800,7 +800,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7437_NAND, 2, 1, "A,B")
+ TRUTHTABLE_START(TTL_7437_NAND, 2, 1, "+A,+B")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|1|22")
TT_LINE("X,0|1|22")
@@ -817,7 +817,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7486_XOR, 2, 1, "A,B")
+ TRUTHTABLE_START(TTL_7486_XOR, 2, 1, "+A,+B")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|0|15")
TT_LINE("0,1|1|22")
@@ -837,7 +837,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_74260_NOR, 5, 1, "A,B,C,D,E")
+ TRUTHTABLE_START(TTL_74260_NOR, 5, 1, "+A,+B,+C,+D,+E")
TT_HEAD("A,B,C,D,E|Q ")
TT_LINE("0,0,0,0,0|1|10")
TT_LINE("X,X,X,X,1|0|12")
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 6b515a20c1c..cfefc32bc41 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -22,6 +22,7 @@
#include "plib/pstate.h"
#include "plib/pfmtlog.h"
#include "plib/pstream.h"
+#include "plib/pexception.h"
// ----------------------------------------------------------------------------------------
// Type definitions
@@ -88,29 +89,35 @@ class NETLIB_NAME(name) : public device_t
* dynamic device, i.e. #NETLIB_UPDATE_TERMINALSI is called on a each step
* of the Newton-Raphson step of solving the linear equations.
*/
-#define NETLIB_DYNAMIC() \
+#define NETLIB_IS_DYNAMIC() \
public: virtual bool is_dynamic() const override { return true; }
- /*! Add this to a device definition to mark the device as a time-stepping device
- * and add code.
- * If this is added to device definition the device is treated as an analog
- * time-stepping device. Currently, only the capacitor device uses this. An other
- * example would be an inductor device.
- *
- * Example:
- *
- * NETLIB_TIMESTEP()
- * {
- * // Gpar should support convergence
- * const nl_double G = m_C.Value() / step + m_GParallel;
- * const nl_double I = -G * deltaV();
- * set(G, 0.0, I);
- * }
- *
- */
-#define NETLIB_TIMESTEP() \
- public: virtual bool is_timestep() const override { return true; } \
- public: virtual void step_time(const nl_double step) override
+ /*! Add this to a device definition to mark the device as a time-stepping device.
+ *
+ * You have to implement NETLIB_TIMESTEP in this case as well. Currently, only
+ * the capacitor and inductor devices uses this.
+ *
+ * Example:
+ *
+ * NETLIB_TIMESTEP_IS_TIMESTEP()
+ * NETLIB_TIMESTEPI()
+ * {
+ * // Gpar should support convergence
+ * const nl_double G = m_C.Value() / step + m_GParallel;
+ * const nl_double I = -G * deltaV();
+ * set(G, 0.0, I);
+ * }
+ *
+ */
+#define NETLIB_IS_TIMESTEP() \
+ public: virtual bool is_timestep() const override { return true; }
+
+ /*! Used to implement the time stepping code.
+ *
+ * Please see NETLIB_IS_TIMESTEP for an example.
+ */
+#define NETLIB_TIMESTEPI() \
+ public: virtual void timestep(const nl_double step) override
#define NETLIB_UPDATE_AFTER_PARAM_CHANGE() \
public: virtual bool needs_update_after_param_change() const override { return true; }
@@ -122,6 +129,8 @@ class NETLIB_NAME(name) : public device_t
#define NETLIB_UPDATE_PARAMI() public: virtual void update_param() override
#define NETLIB_RESETI() protected: virtual void reset() override
+#define NETLIB_TIMESTEP(chip) void NETLIB_NAME(chip) :: timestep(const nl_double step)
+
#define NETLIB_SUB(chip) nld_ ## chip
#define NETLIB_SUBXX(chip) std::unique_ptr< nld_ ## chip >
@@ -960,28 +969,6 @@ namespace netlist
virtual void changed() override { }
};
- template <typename ST, std::size_t AW, std::size_t DW>
- class param_rom_t final: public param_data_t
- {
- public:
-
- param_rom_t(device_t &device, const pstring name)
- : param_data_t(device, name)
- {
- stream()->read(&m_data[0],1<<AW);
- }
-
- const ST & operator[] (std::size_t n) { return m_data[n]; }
-
- protected:
- virtual void changed() override
- {
- stream()->read(&m_data[0],1<<AW);
- }
- private:
- ST m_data[1 << AW];
- };
-
// -----------------------------------------------------------------------------
// core_device_t
// -----------------------------------------------------------------------------
@@ -1050,7 +1037,7 @@ namespace netlist
virtual void reset() { }
public:
- virtual void step_time(ATTR_UNUSED const nl_double st) { }
+ virtual void timestep(ATTR_UNUSED const nl_double st) { }
virtual void update_terminals() { }
virtual void update_param() {}
@@ -1299,6 +1286,36 @@ namespace netlist
};
// -----------------------------------------------------------------------------
+ // rom parameter
+ // -----------------------------------------------------------------------------
+
+ template <typename ST, std::size_t AW, std::size_t DW>
+ class param_rom_t final: public param_data_t
+ {
+ public:
+
+ param_rom_t(device_t &device, const pstring name)
+ : param_data_t(device, name)
+ {
+ auto f = stream();
+ if (f != nullptr)
+ f->read(&m_data[0],1<<AW);
+ else
+ device.netlist().log().warning("Rom {1} not found", Value());
+ }
+
+ const ST & operator[] (std::size_t n) { return m_data[n]; }
+
+ protected:
+ virtual void changed() override
+ {
+ stream()->read(&m_data[0],1<<AW);
+ }
+ private:
+ ST m_data[1 << AW];
+ };
+
+ // -----------------------------------------------------------------------------
// inline implementations
// -----------------------------------------------------------------------------
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index e85a1c191fc..3181e486dde 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -51,7 +51,7 @@
*/
// This will be autodetected
-//#define NL_PMF_TYPE 0
+// #define NL_PMF_TYPE 0
#define NL_PMF_TYPE_VIRTUAL 0
#define NL_PMF_TYPE_GNUC_PMF 1
@@ -82,6 +82,7 @@
* linear memory pool. This is based of the assumption that
* due to enhanced locality there will be less cache misses.
* Your mileage may vary.
+ * This will cause crashes on OSX and thus is ignored on OSX.
*
*/
#define USE_MEMPOOL (0)
@@ -91,7 +92,6 @@
// Solver defines
//============================================================
-#define USE_MATRIX_GS (0)
#define USE_GABS (1)
// savings are eaten up by effort
// FIXME: Convert into solver parameter
@@ -165,5 +165,9 @@ using nl_double = double;
#endif
#endif
+#ifdef __APPLE__
+#undef USE_MEMPOOL
+#define USE_MEMPOOL (0)
+#endif
#endif /* NLCONFIG_H_ */
diff --git a/src/lib/netlist/nl_factory.cpp b/src/lib/netlist/nl_factory.cpp
index f1d3281aa81..1e5a8e11b44 100644
--- a/src/lib/netlist/nl_factory.cpp
+++ b/src/lib/netlist/nl_factory.cpp
@@ -12,45 +12,28 @@
#include "nl_setup.h"
#include "plib/putil.h"
-namespace netlist
+namespace netlist { namespace factory
{
// ----------------------------------------------------------------------------------------
// net_device_t_base_factory
// ----------------------------------------------------------------------------------------
-const plib::pstring_vector_t base_factory_t::term_param_list()
-{
- if (m_def_param.startsWith("+"))
- return plib::pstring_vector_t(m_def_param.substr(1), ",");
- else
- return plib::pstring_vector_t();
-}
-
-const plib::pstring_vector_t base_factory_t::def_params()
-{
- if (m_def_param.startsWith("+") || m_def_param.equals("-"))
- return plib::pstring_vector_t();
- else
- return plib::pstring_vector_t(m_def_param, ",");
-}
-
-
-factory_list_t::factory_list_t( setup_t &setup)
+list_t::list_t( setup_t &setup)
: m_setup(setup)
{
}
-factory_list_t::~factory_list_t()
+list_t::~list_t()
{
clear();
}
-void factory_list_t::error(const pstring &s)
+void list_t::error(const pstring &s)
{
m_setup.log().fatal("{1}", s);
}
-base_factory_t * factory_list_t::factory_by_name(const pstring &devname)
+factory::element_t * list_t::factory_by_name(const pstring &devname)
{
for (auto & e : *this)
{
@@ -62,4 +45,21 @@ base_factory_t * factory_list_t::factory_by_name(const pstring &devname)
return nullptr; // appease code analysis
}
+// -----------------------------------------------------------------------------
+// factory_lib_entry_t: factory class to wrap macro based chips/elements
+// -----------------------------------------------------------------------------
+
+plib::owned_ptr<device_t> library_element_t::Create(netlist_t &anetlist, const pstring &name)
+{
+ return plib::owned_ptr<device_t>::Create<wrapper>(anetlist, name);
}
+
+void library_element_t::macro_actions(netlist_t &anetlist, const pstring &name)
+{
+ anetlist.setup().namespace_push(name);
+ anetlist.setup().include(this->name());
+ anetlist.setup().namespace_pop();
+}
+
+
+} }
diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h
index 6a53797d0d8..b7750751e06 100644
--- a/src/lib/netlist/nl_factory.h
+++ b/src/lib/netlist/nl_factory.h
@@ -17,32 +17,31 @@
#include "plib/putil.h"
#include "nl_base.h"
-#define NETLIB_DEVICE_IMPL(chip) factory_creator_ptr_t decl_ ## chip = factory_creator_t< NETLIB_NAME(chip) >;
+#define NETLIB_DEVICE_IMPL(chip) factory::constructor_ptr_t decl_ ## chip = factory::constructor_t< NETLIB_NAME(chip) >;
-namespace netlist
+namespace netlist { namespace factory
{
// -----------------------------------------------------------------------------
// net_dev class factory
// -----------------------------------------------------------------------------
- class base_factory_t
+ class element_t
{
- P_PREVENT_COPYING(base_factory_t)
+ P_PREVENT_COPYING(element_t)
public:
- base_factory_t(const pstring &name, const pstring &classname,
+ element_t(const pstring &name, const pstring &classname,
const pstring &def_param)
: m_name(name), m_classname(classname), m_def_param(def_param)
{}
- virtual ~base_factory_t() {}
+ virtual ~element_t() {}
virtual plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) = 0;
+ virtual void macro_actions(netlist_t &anetlist, const pstring &name) {};
const pstring &name() const { return m_name; }
const pstring &classname() const { return m_classname; }
const pstring &param_desc() const { return m_def_param; }
- const plib::pstring_vector_t term_param_list();
- const plib::pstring_vector_t def_params();
protected:
pstring m_name; /* device name */
@@ -51,13 +50,13 @@ namespace netlist
};
template <class C>
- class factory_t : public base_factory_t
+ class device_element_t : public element_t
{
- P_PREVENT_COPYING(factory_t)
+ P_PREVENT_COPYING(device_element_t)
public:
- factory_t(const pstring &name, const pstring &classname,
+ device_element_t(const pstring &name, const pstring &classname,
const pstring &def_param)
- : base_factory_t(name, classname, def_param) { }
+ : element_t(name, classname, def_param) { }
plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
{
@@ -65,20 +64,20 @@ namespace netlist
}
};
- class factory_list_t : public std::vector<std::unique_ptr<base_factory_t>>
+ class list_t : public std::vector<std::unique_ptr<element_t>>
{
public:
- factory_list_t(setup_t &m_setup);
- ~factory_list_t();
+ list_t(setup_t &m_setup);
+ ~list_t();
template<class device_class>
void register_device(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- register_device(std::unique_ptr<base_factory_t>(new factory_t<device_class>(name, classname, def_param)));
+ register_device(std::unique_ptr<element_t>(new device_element_t<device_class>(name, classname, def_param)));
}
- void register_device(std::unique_ptr<base_factory_t> factory)
+ void register_device(std::unique_ptr<element_t> factory)
{
for (auto & e : *this)
if (e->name() == factory->name())
@@ -86,12 +85,12 @@ namespace netlist
push_back(std::move(factory));
}
- base_factory_t * factory_by_name(const pstring &devname);
+ element_t * factory_by_name(const pstring &devname);
template <class C>
- bool is_class(base_factory_t *f)
+ bool is_class(element_t *f)
{
- return dynamic_cast<factory_t<C> *>(f) != nullptr;
+ return dynamic_cast<device_element_t<C> *>(f) != nullptr;
}
private:
@@ -104,16 +103,49 @@ namespace netlist
// factory_creator_ptr_t
// -----------------------------------------------------------------------------
- using factory_creator_ptr_t = std::unique_ptr<base_factory_t> (*)(const pstring &name, const pstring &classname,
+ using constructor_ptr_t = std::unique_ptr<element_t> (*)(const pstring &name, const pstring &classname,
const pstring &def_param);
template <typename T>
- std::unique_ptr<base_factory_t> factory_creator_t(const pstring &name, const pstring &classname,
+ std::unique_ptr<element_t> constructor_t(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- return std::unique_ptr<base_factory_t>(new factory_t<T>(name, classname, def_param));
+ return std::unique_ptr<element_t>(new device_element_t<T>(name, classname, def_param));
}
-}
+ // -----------------------------------------------------------------------------
+ // factory_lib_entry_t: factory class to wrap macro based chips/elements
+ // -----------------------------------------------------------------------------
+
+ class library_element_t : public element_t
+ {
+ P_PREVENT_COPYING(library_element_t)
+ public:
+
+ library_element_t(setup_t &setup, const pstring &name, const pstring &classname,
+ const pstring &def_param)
+ : element_t(name, classname, def_param), m_setup(setup) { }
+
+ class wrapper : public device_t
+ {
+ public:
+ wrapper(netlist_t &anetlist, const pstring &name)
+ : device_t(anetlist, name)
+ {
+ }
+ protected:
+ NETLIB_RESETI() { }
+ NETLIB_UPDATEI() { }
+ };
+
+ plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override;
+
+ void macro_actions(netlist_t &anetlist, const pstring &name) override;
+
+ private:
+ setup_t &m_setup;
+ };
+
+} }
#endif /* NLFACTORY_H_ */
diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp
index 6760873a4af..6dee211ce56 100644
--- a/src/lib/netlist/nl_parser.cpp
+++ b/src/lib/netlist/nl_parser.cpp
@@ -316,7 +316,7 @@ void parser_t::dippins()
error(plib::pfmt("expected a comma, found <{1}>")(n.str()) );
}
if ((pins.size() % 2) == 1)
- error("You must pass an equal number of pins to DIPPINS");
+ error(plib::pfmt("You must pass an equal number of pins to DIPPINS, first pin is {}")(pins[0]));
std::size_t n = pins.size();
for (std::size_t i = 0; i < n / 2; i++)
{
@@ -356,35 +356,29 @@ void parser_t::netdev_hint()
void parser_t::device(const pstring &dev_type)
{
- if (m_setup.is_library_item(dev_type))
- {
- pstring devname = get_identifier();
- m_setup.namespace_push(devname);
- m_setup.include(dev_type);
- m_setup.namespace_pop();
- require_token(m_tok_param_right);
- }
- else
- {
- base_factory_t *f = m_setup.factory().factory_by_name(dev_type);
- plib::pstring_vector_t termlist = f->term_param_list();
- plib::pstring_vector_t def_params = f->def_params();
+ factory::element_t *f = m_setup.factory().factory_by_name(dev_type);
+ auto paramlist = plib::pstring_vector_t(f->param_desc(), ",");
- std::size_t cnt;
+ pstring devname = get_identifier();
- pstring devname = get_identifier();
+ m_setup.register_dev(dev_type, devname);
+ m_setup.log().debug("Parser: IC: {1}\n", devname);
- m_setup.register_dev(dev_type, m_setup.build_fqn(devname));
-
- m_setup.log().debug("Parser: IC: {1}\n", devname);
+ for (pstring tp : paramlist)
+ {
+ require_token(m_tok_comma);
+ if (tp.startsWith("+"))
+ {
+ pstring output_name = get_identifier();
+ m_setup.log().debug("Link: {1} {2}\n", tp, output_name);
- cnt = 0;
- while (cnt < def_params.size())
+ m_setup.register_link(devname + "." + tp.substr(1), output_name);
+ }
+ else
{
- pstring paramfq = devname + "." + def_params[cnt];
+ pstring paramfq = devname + "." + tp;
m_setup.log().debug("Defparam: {1}\n", paramfq);
- require_token(m_tok_comma);
token_t tok = get_token();
if (tok.is_type(STRING))
{
@@ -395,24 +389,11 @@ void parser_t::device(const pstring &dev_type)
nl_double val = eval_param(tok);
m_setup.register_param(paramfq, val);
}
- cnt++;
}
-
- token_t tok = get_token();
- cnt = 0;
- while (tok.is(m_tok_comma) && cnt < termlist.size())
- {
- pstring output_name = get_identifier();
-
- m_setup.register_link(devname + "." + termlist[cnt], output_name);
-
- cnt++;
- tok = get_token();
- }
- if (cnt != termlist.size())
- error(plib::pfmt("Input count mismatch for {1} - expected {2} found {3}")(devname)(termlist.size())(cnt));
- require_token(tok, m_tok_param_right);
}
+
+ // error(plib::pfmt("Input count mismatch for {1} - expected {2} found {3}")(devname)(termlist.size())(cnt));
+ require_token(m_tok_param_right);
}
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 8ece4c616ec..038fd7ed978 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -103,27 +103,17 @@ void setup_t::namespace_pop()
void setup_t::register_lib_entry(const pstring &name)
{
- if (plib::container::contains(m_lib, name))
- log().warning("Lib entry collection already contains {1}. IGNORED", name);
- else
- m_lib.push_back(name);
+ factory().register_device(plib::make_unique_base<factory::element_t, factory::library_element_t>(*this, name, name, ""));
}
void setup_t::register_dev(const pstring &classname, const pstring &name)
{
- if (plib::container::contains(m_lib, classname))
- {
- namespace_push(name);
- include(classname);
- namespace_pop();
- }
- else
- {
- auto f = factory().factory_by_name(classname);
- if (f == nullptr)
- log().fatal("Class {1} not found!\n", classname);
- m_device_factory.push_back(std::pair<pstring, base_factory_t *>(build_fqn(name), f));
- }
+ auto f = factory().factory_by_name(classname);
+ if (f == nullptr)
+ log().fatal("Class {1} not found!\n", classname);
+ /* make sure we parse macro library entries */
+ f->macro_actions(netlist(), name);
+ m_device_factory.push_back(std::pair<pstring, factory::element_t *>(build_fqn(name), f));
}
bool setup_t::device_exists(const pstring name) const
@@ -165,7 +155,7 @@ void setup_t::register_dippins_arr(const pstring &terms)
{
plib::pstring_vector_t list(terms,", ");
if (list.size() == 0 || (list.size() % 2) == 1)
- log().fatal("You must pass an equal number of pins to DIPPINS");
+ log().fatal("You must pass an equal number of pins to DIPPINS {1}" , build_fqn(""));
std::size_t n = list.size();
for (std::size_t i = 0; i < n / 2; i++)
{
@@ -349,7 +339,7 @@ const pstring setup_t::resolve_alias(const pstring &name) const
ret = temp;
auto p = m_alias.find(ret);
temp = (p != m_alias.end() ? p->second : "");
- } while (temp != "");
+ } while (temp != "" && temp != ret);
log().debug("{1}==>{2}\n", name, ret);
return ret;
@@ -1040,7 +1030,8 @@ std::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring name)
return strm;
}
}
- log().fatal("unable to find data named {1} in source collection", name);
+ //log().fatal("unable to find data named {1} in source collection", name);
+ log().warning("unable to find data named {1} in source collection", name);
return std::unique_ptr<plib::pistream>(nullptr);
}
diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h
index 399c44e3dbe..1edc3b50781 100644
--- a/src/lib/netlist/nl_setup.h
+++ b/src/lib/netlist/nl_setup.h
@@ -92,7 +92,7 @@ void NETLIST_NAME(name)(netlist::setup_t &setup) \
desc.classname = #cname ; \
desc.ni = in; \
desc.no = out; \
- desc.def_param = pstring("+") + def_params; \
+ desc.def_param = def_params; \
desc.family = "";
#define TT_HEAD(x) \
@@ -252,10 +252,8 @@ namespace netlist
void register_define(pstring def, pstring val) { m_defines.push_back(plib::ppreprocessor::define_t(def, val)); }
void register_define(pstring defstr);
- factory_list_t &factory() { return m_factory; }
- const factory_list_t &factory() const { return m_factory; }
-
- bool is_library_item(const pstring &name) const { return plib::container::contains(m_lib, name); }
+ factory::list_t &factory() { return m_factory; }
+ const factory::list_t &factory() const { return m_factory; }
/* model / family related */
@@ -275,7 +273,7 @@ namespace netlist
plib::plog_base<NL_DEBUG> &log();
const plib::plog_base<NL_DEBUG> &log() const;
- std::vector<std::pair<pstring, base_factory_t *>> m_device_factory;
+ std::vector<std::pair<pstring, factory::element_t *>> m_device_factory;
std::unordered_map<pstring, pstring> m_alias;
std::unordered_map<pstring, pstring> m_param_values;
@@ -305,13 +303,12 @@ namespace netlist
netlist_t &m_netlist;
std::unordered_map<pstring, param_ref_t> m_params;
std::vector<link_t> m_links;
- factory_list_t m_factory;
+ factory::list_t m_factory;
std::unordered_map<pstring, pstring> m_models;
std::stack<pstring> m_namespace_stack;
source_t::list_t m_sources;
std::vector<plib::ppreprocessor::define_t> m_defines;
- std::vector<pstring> m_lib;
unsigned m_proxy_cnt;
unsigned m_frontier_cnt;
diff --git a/src/lib/netlist/plib/palloc.cpp b/src/lib/netlist/plib/palloc.cpp
index b90960f953e..2f1131601da 100644
--- a/src/lib/netlist/plib/palloc.cpp
+++ b/src/lib/netlist/plib/palloc.cpp
@@ -12,44 +12,6 @@
#include "pfmtlog.h"
namespace plib {
-//============================================================
-// Exceptions
-//============================================================
-
-pexception::pexception(const pstring text)
-{
- m_text = text;
-}
-
-file_e::file_e(const pstring fmt, const pstring &filename)
- : pexception(pfmt(fmt)(filename))
-{
-}
-
-file_open_e::file_open_e(const pstring &filename)
- : file_e("File open failed: {}", filename)
-{
-}
-
-file_read_e::file_read_e(const pstring &filename)
- : file_e("File read failed: {}", filename)
-{
-}
-
-file_write_e::file_write_e(const pstring &filename)
- : file_e("File write failed: {}", filename)
-{
-}
-
-null_argument_e::null_argument_e(const pstring &argument)
- : pexception(pfmt("Null argument passed: {}")(argument))
-{
-}
-
-out_of_mem_e::out_of_mem_e(const pstring &location)
- : pexception(pfmt("Out of memory: {}")(location))
-{
-}
//============================================================
// Memory pool
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h
index a12595e0027..1f4a5b083d9 100644
--- a/src/lib/netlist/plib/palloc.h
+++ b/src/lib/netlist/plib/palloc.h
@@ -8,7 +8,6 @@
#ifndef PALLOC_H_
#define PALLOC_H_
-#include <exception>
#include <vector>
#include <memory>
#include <utility>
@@ -17,59 +16,6 @@
#include "pstring.h"
namespace plib {
-//============================================================
-// exception base
-//============================================================
-
-class pexception : public std::exception
-{
-public:
- pexception(const pstring text);
- pexception(const pexception &e) : std::exception(e) { m_text = e.m_text; }
-
- virtual ~pexception() noexcept {}
-
- const pstring &text() { return m_text; }
-
-private:
- pstring m_text;
-};
-
-class file_e : public plib::pexception
-{
-public:
- explicit file_e(const pstring fmt, const pstring &filename);
-};
-
-class file_open_e : public file_e
-{
-public:
- explicit file_open_e(const pstring &filename);
-};
-
-class file_read_e : public file_e
-{
-public:
- explicit file_read_e(const pstring &filename);
-};
-
-class file_write_e : public file_e
-{
-public:
- explicit file_write_e(const pstring &filename);
-};
-
-class null_argument_e : public plib::pexception
-{
-public:
- explicit null_argument_e(const pstring &argument);
-};
-
-class out_of_mem_e : public plib::pexception
-{
-public:
- explicit out_of_mem_e(const pstring &location);
-};
//============================================================
// Memory allocation
diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp
new file mode 100644
index 00000000000..a49fa699ce5
--- /dev/null
+++ b/src/lib/netlist/plib/pexception.cpp
@@ -0,0 +1,109 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * palloc.c
+ *
+ */
+
+#include <cfenv>
+
+#include "pexception.h"
+#include "pfmtlog.h"
+
+#if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__)
+#define HAS_FEENABLE_EXCEPT (1)
+#else
+#define HAS_FEENABLE_EXCEPT (0)
+#endif
+
+namespace plib {
+//============================================================
+// Exceptions
+//============================================================
+
+pexception::pexception(const pstring text)
+{
+ m_text = text;
+}
+
+file_e::file_e(const pstring fmt, const pstring &filename)
+ : pexception(pfmt(fmt)(filename))
+{
+}
+
+file_open_e::file_open_e(const pstring &filename)
+ : file_e("File open failed: {}", filename)
+{
+}
+
+file_read_e::file_read_e(const pstring &filename)
+ : file_e("File read failed: {}", filename)
+{
+}
+
+file_write_e::file_write_e(const pstring &filename)
+ : file_e("File write failed: {}", filename)
+{
+}
+
+null_argument_e::null_argument_e(const pstring &argument)
+ : pexception(pfmt("Null argument passed: {}")(argument))
+{
+}
+
+out_of_mem_e::out_of_mem_e(const pstring &location)
+ : pexception(pfmt("Out of memory: {}")(location))
+{
+}
+
+fpexception::fpexception(const pstring &text)
+ : pexception(pfmt("Out of memory: {}")(text))
+{
+}
+
+bool fpsignalenabler::m_enable = false;
+
+fpsignalenabler::fpsignalenabler(unsigned fpexceptions)
+{
+#if HAS_FEENABLE_EXCEPT
+ if (m_enable)
+ {
+ unsigned b = 0;
+ if (fpexceptions & plib::FP_INEXACT) b = b | FE_INEXACT;
+ if (fpexceptions & plib::FP_DIVBYZERO) b = b | FE_DIVBYZERO;
+ if (fpexceptions & plib::FP_UNDERFLOW) b = b | FE_UNDERFLOW;
+ if (fpexceptions & plib::FP_OVERFLOW) b = b | FE_OVERFLOW;
+ if (fpexceptions & plib::FP_INVALID) b = b | FE_INVALID;
+ m_last_enabled = feenableexcept(b);
+ }
+#else
+ m_last_enabled = 0;
+#endif
+}
+
+
+fpsignalenabler::~fpsignalenabler()
+{
+#if HAS_FEENABLE_EXCEPT
+ if (m_enable)
+ {
+ fedisableexcept(FE_ALL_EXCEPT); // Enable all floating point exceptions but FE_INEXACT
+ feenableexcept(m_last_enabled); // Enable all floating point exceptions but FE_INEXACT
+ }
+#endif
+}
+
+bool fpsignalenabler::supported()
+{
+ return true;
+}
+
+bool fpsignalenabler::global_enable(bool enable)
+{
+ bool old = m_enable;
+ m_enable = enable;
+ return old;
+}
+
+
+}
diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h
new file mode 100644
index 00000000000..7e3c59441c2
--- /dev/null
+++ b/src/lib/netlist/plib/pexception.h
@@ -0,0 +1,112 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * palloc.h
+ *
+ */
+
+#ifndef PEXCEPTION_H_
+#define PEXCEPTION_H_
+
+#include <exception>
+
+#include "pconfig.h"
+#include "pstring.h"
+
+namespace plib {
+//============================================================
+// exception base
+//============================================================
+
+class pexception : public std::exception
+{
+public:
+ pexception(const pstring text);
+ pexception(const pexception &e) : std::exception(e) { m_text = e.m_text; }
+
+ virtual ~pexception() noexcept {}
+
+ const pstring &text() { return m_text; }
+
+private:
+ pstring m_text;
+};
+
+class file_e : public plib::pexception
+{
+public:
+ explicit file_e(const pstring fmt, const pstring &filename);
+};
+
+class file_open_e : public file_e
+{
+public:
+ explicit file_open_e(const pstring &filename);
+};
+
+class file_read_e : public file_e
+{
+public:
+ explicit file_read_e(const pstring &filename);
+};
+
+class file_write_e : public file_e
+{
+public:
+ explicit file_write_e(const pstring &filename);
+};
+
+class null_argument_e : public plib::pexception
+{
+public:
+ explicit null_argument_e(const pstring &argument);
+};
+
+class out_of_mem_e : public plib::pexception
+{
+public:
+ explicit out_of_mem_e(const pstring &location);
+};
+
+/* FIXME: currently only a stub for later use. More use could be added by
+ * using “-fnon-call-exceptions" and sigaction to enable c++ exception supported.
+ */
+
+class fpexception : public pexception
+{
+public:
+ fpexception(const pstring &text);
+};
+
+static const unsigned FP_INEXACT = 0x0001;
+static const unsigned FP_DIVBYZERO = 0x0002;
+static const unsigned FP_UNDERFLOW = 0x0004;
+static const unsigned FP_OVERFLOW = 0x0008;
+static const unsigned FP_INVALID = 0x00010;
+static const unsigned FP_ALL = 0x0001f;
+
+/*
+ * Catch SIGFPE on linux for debugging purposes.
+ */
+
+class fpsignalenabler
+{
+public:
+ fpsignalenabler(unsigned fpexceptions);
+ ~fpsignalenabler();
+
+ /* is the functionality supported ? */
+ static bool supported();
+ /* returns last global enable state */
+ static bool global_enable(bool enable);
+
+private:
+ unsigned m_last_enabled;
+
+ static bool m_enable;
+};
+
+
+}
+
+#endif /* PEXCEPTION_H_ */
diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h
index e400837c3ac..11bf0fb12cf 100644
--- a/src/lib/netlist/plib/pstream.h
+++ b/src/lib/netlist/plib/pstream.h
@@ -13,6 +13,7 @@
#include "pconfig.h"
#include "pstring.h"
#include "pfmtlog.h"
+#include "pexception.h"
namespace plib {
// -----------------------------------------------------------------------------
diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h
index cc388cd3393..9e79e958927 100644
--- a/src/lib/netlist/plib/putil.h
+++ b/src/lib/netlist/plib/putil.h
@@ -45,6 +45,11 @@ namespace plib
con.insert(con.begin() + static_cast<std::ptrdiff_t>(index), elem);
}
+ template <class C>
+ void remove(C &con, const typename C::value_type &elem)
+ {
+ con.erase(std::remove(con.begin(), con.end(), elem), con.end());
+ }
}
template <class C>
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index 0f3d29d00d8..60189bfb0cc 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -15,12 +15,15 @@
#include "plib/pstring.h"
#include "plib/plists.h"
#include "plib/ptypes.h"
+#include "plib/pexception.h"
#include "nl_setup.h"
#include "nl_factory.h"
#include "nl_parser.h"
#include "devices/net_lib.h"
#include "tools/nl_convert.h"
+#include <cfenv>
+
class tool_options_t : public plib::options
{
public:
@@ -346,7 +349,7 @@ static void listdevices(tool_options_t &opts)
if (opts.opt_quiet())
nt.log().warning.set_enabled(false);
- netlist::factory_list_t &list = nt.setup().factory();
+ netlist::factory::list_t &list = nt.setup().factory();
nt.setup().register_source(plib::make_unique_base<netlist::source_t,
netlist::source_proc_t>(nt.setup(), "dummy", &netlist_dummy));
@@ -363,6 +366,7 @@ static void listdevices(tool_options_t &opts)
pstring out = plib::pfmt("{1} {2}(<id>")(f->classname(),"-20")(f->name());
std::vector<pstring> terms;
+ f->macro_actions(nt.setup().netlist(), f->name() + "_lc");
auto d = f->Create(nt.setup().netlist(), f->name() + "_lc");
// get the list of terminals ...
@@ -381,10 +385,12 @@ static void listdevices(tool_options_t &opts)
if (t.first.startsWith(d->name()))
{
pstring tn(t.first.substr(d->name().len()+1));
+ //printf("\t%s %s %s\n", t.first.c_str(), t.second.c_str(), tn.c_str());
if (tn.find(".") == tn.end())
{
terms.push_back(tn);
pstring resolved = nt.setup().resolve_alias(t.first);
+ //printf("\t%s %s %s\n", t.first.c_str(), t.second.c_str(), resolved.c_str());
if (resolved != t.first)
{
auto found = std::find(terms.begin(), terms.end(), resolved.substr(d->name().len()+1));
@@ -395,18 +401,13 @@ static void listdevices(tool_options_t &opts)
}
}
- if (f->param_desc().startsWith("+"))
- {
- out += "," + f->param_desc().substr(1);
- terms.clear();
- }
- else if (f->param_desc() == "-")
+ out += "," + f->param_desc();
+ for (auto p : plib::pstring_vector_t(f->param_desc(),",") )
{
- /* no params at all */
- }
- else
- {
- out += "," + f->param_desc();
+ if (p.startsWith("+"))
+ {
+ plib::container::remove(terms, p.substr(1));
+ }
}
out += ")";
printf("%s\n", out.c_str());
@@ -415,7 +416,7 @@ static void listdevices(tool_options_t &opts)
pstring t = "";
for (auto & j : terms)
t += "," + j;
- printf("Terminals: %s\n", t.substr(1).c_str());
+ printf("\tTerminals: %s\n", t.substr(1).c_str());
}
devs.push_back(std::move(d));
}
@@ -442,8 +443,13 @@ int main(int argc, char *argv[])
tool_options_t opts;
int ret;
+ /* make SIGFPE actually deliver signals on supoorted platforms */
+ plib::fpsignalenabler::global_enable(true);
+ plib::fpsignalenabler sigen(plib::FP_ALL & ~plib::FP_INEXACT & ~plib::FP_UNDERFLOW);
+
//perr("{}", "WARNING: This is Work In Progress! - It may fail anytime\n");
//perr("Update dispatching using method {}\n", pmf_verbose[NL_PMF_TYPE]);
+ //printf("test2 %f\n", std::exp(-14362.38064713));
if ((ret = opts.parse(argc, argv)) != argc)
{
perr("Error parsing {}\n", argv[ret]);
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index 36e39462c17..f1473ce5931 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -45,7 +45,7 @@ public:
: m_railstart(0)
, m_last_V(0.0)
, m_DD_n_m_1(0.0)
- , m_h_n_m_1(1e-6)
+ , m_h_n_m_1(1e-9)
{}
void clear()
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index 3f4deb0340f..b0c70ebbde4 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -408,7 +408,7 @@ void matrix_solver_t::step(const netlist_time &delta)
{
const nl_double dd = delta.as_double();
for (std::size_t k=0; k < m_step_devices.size(); k++)
- m_step_devices[k]->step_time(dd);
+ m_step_devices[k]->timestep(dd);
}
void matrix_solver_t::solve_base()
@@ -510,6 +510,7 @@ netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts)
const nl_double DD_n = (n->Q_Analog() - t->m_last_V);
const nl_double hn = cur_ts;
+ //printf("%f %f %f %f\n", DD_n, t->m_DD_n_m_1, hn, t->m_h_n_m_1);
nl_double DD2 = (DD_n / hn - t->m_DD_n_m_1 / t->m_h_n_m_1) / (hn + t->m_h_n_m_1);
nl_double new_net_timestep;
@@ -526,7 +527,10 @@ netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts)
t->m_last_V = n->Q_Analog();
}
if (new_solver_timestep < m_params.m_min_timestep)
+ {
+ //log().warning("Dynamic timestep below min timestep. Consider decreasing MIN_TIMESTEP: {1} us", new_solver_timestep*1.0e6);
new_solver_timestep = m_params.m_min_timestep;
+ }
}
//if (new_solver_timestep > 10.0 * hn)
// new_solver_timestep = 10.0 * hn;
diff --git a/src/lib/util/base64.hpp b/src/lib/util/base64.hpp
new file mode 100644
index 00000000000..dc8f69335dc
--- /dev/null
+++ b/src/lib/util/base64.hpp
@@ -0,0 +1,167 @@
+// license:BSD-3-Clause
+// copyright-holders:René Nyffenegger
+/*
+ base64.cpp and base64.h
+
+ Copyright (C) 2004-2008 René Nyffenegger
+
+ This source code is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented; you must not
+ claim that you wrote the original source code. If you use this source code
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original source code.
+
+ 3. This notice may not be removed or altered from any source distribution.
+
+ René Nyffenegger rene.nyffenegger@adp-gmbh.ch
+
+*/
+
+#ifndef _BASE64_HPP_
+#define _BASE64_HPP_
+
+#include <string>
+
+static std::string const base64_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+/// Test whether a character is a valid base64 character
+/**
+ * @param c The character to test
+ * @return true if c is a valid base64 character
+ */
+static inline bool is_base64(unsigned char c) {
+ return (c == 43 || // +
+ (c >= 47 && c <= 57) || // /-9
+ (c >= 65 && c <= 90) || // A-Z
+ (c >= 97 && c <= 122)); // a-z
+}
+
+/// Encode a char buffer into a base64 string
+/**
+ * @param input The input data
+ * @param len The length of input in bytes
+ * @return A base64 encoded string representing input
+ */
+inline std::string base64_encode(unsigned char const * input, size_t len) {
+ std::string ret;
+ int i = 0;
+ int j;
+ unsigned char char_array_3[3];
+ unsigned char char_array_4[4];
+
+ while (len--) {
+ char_array_3[i++] = *(input++);
+ if (i == 3) {
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) +
+ ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) +
+ ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for(i = 0; (i <4) ; i++) {
+ ret += base64_chars[char_array_4[i]];
+ }
+ i = 0;
+ }
+ }
+
+ if (i) {
+ for(j = i; j < 3; j++) {
+ char_array_3[j] = '\0';
+ }
+
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) +
+ ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) +
+ ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for (j = 0; (j < i + 1); j++) {
+ ret += base64_chars[char_array_4[j]];
+ }
+
+ while((i++ < 3)) {
+ ret += '=';
+ }
+ }
+
+ return ret;
+}
+
+/// Encode a string into a base64 string
+/**
+ * @param input The input data
+ * @return A base64 encoded string representing input
+ */
+inline std::string base64_encode(std::string const & input) {
+ return base64_encode(
+ reinterpret_cast<const unsigned char *>(input.data()),
+ input.size()
+ );
+}
+
+/// Decode a base64 encoded string into a string of raw bytes
+/**
+ * @param input The base64 encoded input data
+ * @return A string representing the decoded raw bytes
+ */
+inline std::string base64_decode(std::string const & input) {
+ size_t in_len = input.size();
+ int i = 0;
+ int j;
+ int in_ = 0;
+ unsigned char char_array_4[4], char_array_3[3];
+ std::string ret;
+
+ while (in_len-- && ( input[in_] != '=') && is_base64(input[in_])) {
+ char_array_4[i++] = input[in_]; in_++;
+ if (i ==4) {
+ for (i = 0; i <4; i++) {
+ char_array_4[i] = static_cast<unsigned char>(base64_chars.find(char_array_4[i]));
+ }
+
+ char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+ char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+ char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+ for (i = 0; (i < 3); i++) {
+ ret += char_array_3[i];
+ }
+ i = 0;
+ }
+ }
+
+ if (i) {
+ for (j = i; j <4; j++)
+ char_array_4[j] = 0;
+
+ for (j = 0; j <4; j++)
+ char_array_4[j] = static_cast<unsigned char>(base64_chars.find(char_array_4[j]));
+
+ char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+ char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+ char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+ for (j = 0; (j < i - 1); j++) {
+ ret += static_cast<std::string::value_type>(char_array_3[j]);
+ }
+ }
+
+ return ret;
+}
+#endif // _BASE64_HPP_
diff --git a/src/lib/util/client_http.hpp b/src/lib/util/client_http.hpp
new file mode 100644
index 00000000000..df188090f87
--- /dev/null
+++ b/src/lib/util/client_http.hpp
@@ -0,0 +1,438 @@
+// license:MIT
+// copyright-holders:Ole Christian Eidheim, Miodrag Milanovic
+#ifndef CLIENT_HTTP_HPP
+#define CLIENT_HTTP_HPP
+
+#if defined(_MSC_VER)
+#pragma warning(disable:4503)
+#endif
+
+#include "asio.h"
+
+#include <unordered_map>
+#include <map>
+#include <random>
+#include <mutex>
+
+#ifndef CASE_INSENSITIVE_EQUALS_AND_HASH
+#define CASE_INSENSITIVE_EQUALS_AND_HASH
+class case_insensitive_equals {
+public:
+ bool operator()(const std::string &key1, const std::string &key2) const {
+ return key1.size() == key2.size()
+ && equal(key1.cbegin(), key1.cend(), key2.cbegin(),
+ [](std::string::value_type key1v, std::string::value_type key2v)
+ { return tolower(key1v) == tolower(key2v); });
+ }
+};
+class case_insensitive_hash {
+public:
+ size_t operator()(const std::string &key) const {
+ size_t seed = 0;
+ for (auto &c : key) {
+ std::hash<char> hasher;
+ seed ^= hasher(std::tolower(c)) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ }
+ return seed;
+ }
+};
+#endif
+
+namespace webpp {
+ template <class socket_type>
+ class Client;
+
+ template <class socket_type>
+ class ClientBase {
+ public:
+ virtual ~ClientBase() {}
+
+ class Response {
+ friend class ClientBase<socket_type>;
+ friend class Client<socket_type>;
+ public:
+ std::string http_version, status_code;
+
+ std::istream content;
+
+ std::unordered_multimap<std::string, std::string, case_insensitive_hash, case_insensitive_equals> header;
+
+ private:
+ asio::streambuf content_buffer;
+
+ Response(): content(&content_buffer) {}
+ };
+
+ class Config {
+ friend class ClientBase<socket_type>;
+ private:
+ Config() {}
+ public:
+ /// Set timeout on requests in seconds. Default value: 0 (no timeout).
+ size_t timeout = 0;
+ /// Set proxy server (server:port)
+ std::string proxy_server;
+ };
+
+ /// Set before calling request
+ Config config;
+
+ std::shared_ptr<Response> request(const std::string& request_type, const std::string& path="/", const std::string content="",
+ const std::map<std::string, std::string>& header=std::map<std::string, std::string>()) {
+ auto corrected_path=path;
+ if(corrected_path=="")
+ corrected_path="/";
+ if (!config.proxy_server.empty() && std::is_same<socket_type, asio::ip::tcp::socket>::value)
+ corrected_path = "http://" + host + ':' + std::to_string(port) + corrected_path;
+
+ asio::streambuf write_buffer;
+ std::ostream write_stream(&write_buffer);
+ write_stream << request_type << " " << corrected_path << " HTTP/1.1\r\n";
+ write_stream << "Host: " << host << "\r\n";
+ for(auto& h: header) {
+ write_stream << h.first << ": " << h.second << "\r\n";
+ }
+ if(content.size()>0)
+ write_stream << "Content-Length: " << content.size() << "\r\n";
+ write_stream << "\r\n";
+
+ connect();
+
+ auto timer = get_timeout_timer();
+ asio::async_write(*socket, write_buffer,
+ [this, &content, timer](const std::error_code &ec, size_t /*bytes_transferred*/) {
+ if (timer)
+ timer->cancel();
+ if (!ec) {
+ if (!content.empty()) {
+ auto timer2 = get_timeout_timer();
+ asio::async_write(*socket, asio::buffer(content.data(), content.size()),
+ [this,timer2](const std::error_code &ec, size_t /*bytes_transferred*/) {
+ if (timer2)
+ timer2->cancel();
+ if (ec) {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ }
+ }
+ else {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ io_context.reset();
+ io_context.run();
+ return request_read();
+ }
+
+ std::shared_ptr<Response> request(const std::string& request_type, const std::string& path, std::iostream& content,
+ const std::map<std::string, std::string>& header=std::map<std::string, std::string>()) {
+ auto corrected_path=path;
+ if(corrected_path=="")
+ corrected_path="/";
+ if (!config.proxy_server.empty() && std::is_same<socket_type, asio::ip::tcp::socket>::value)
+ corrected_path = "http://" + host + ':' + std::to_string(port) + corrected_path;
+
+ content.seekp(0, std::ios::end);
+ auto content_length=content.tellp();
+ content.seekp(0, std::ios::beg);
+
+ asio::streambuf write_buffer;
+ std::ostream write_stream(&write_buffer);
+ write_stream << request_type << " " << corrected_path << " HTTP/1.1\r\n";
+ write_stream << "Host: " << host << "\r\n";
+ for(auto& h: header) {
+ write_stream << h.first << ": " << h.second << "\r\n";
+ }
+ if(content_length>0)
+ write_stream << "Content-Length: " << content_length << "\r\n";
+ write_stream << "\r\n";
+ if(content_length>0)
+ write_stream << content.rdbuf();
+
+ connect();
+
+ auto timer = get_timeout_timer();
+ asio::async_write(*socket, write_buffer,
+ [this,timer](const std::error_code &ec, size_t /*bytes_transferred*/) {
+ if (timer)
+ timer->cancel();
+ if (ec) {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ io_context.reset();
+ io_context.run();
+
+ return request_read();
+ }
+ void close() {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ if (socket) {
+ std::error_code ec;
+ socket->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, ec);
+ socket->lowest_layer().close();
+ }
+ }
+ protected:
+ asio::io_context io_context;
+ asio::ip::tcp::resolver resolver;
+
+ std::unique_ptr<socket_type> socket;
+ std::mutex socket_mutex;
+
+ std::string host;
+ unsigned short port;
+
+ ClientBase(const std::string& host_port, unsigned short default_port) : resolver(io_context) {
+ auto parsed_host_port = parse_host_port(host_port, default_port);
+ host = parsed_host_port.first;
+ port = parsed_host_port.second;
+ }
+
+ std::pair<std::string, unsigned short> parse_host_port(const std::string &host_port, unsigned short default_port) const
+ {
+ std::pair<std::string, unsigned short> parsed_host_port;
+ size_t host_end=host_port.find(':');
+ if(host_end==std::string::npos) {
+ parsed_host_port.first =host_port;
+ parsed_host_port.second =default_port;
+ }
+ else {
+ parsed_host_port.first =host_port.substr(0, host_end);
+ parsed_host_port.second =static_cast<unsigned short>(stoul(host_port.substr(host_end+1)));
+ }
+ return parsed_host_port;
+ }
+
+ virtual void connect()=0;
+
+ std::shared_ptr<asio::system_timer> get_timeout_timer() {
+ if (config.timeout == 0)
+ return nullptr;
+
+ auto timer = std::make_shared<asio::system_timer>(io_context);
+ timer->expires_from_now(std::chrono::seconds(config.timeout));
+ timer->async_wait([this](const std::error_code& ec) {
+ if (!ec) {
+ close();
+ }
+ });
+ return timer;
+ }
+
+ void parse_response_header(const std::shared_ptr<Response> &response) const {
+ std::string line;
+ getline(response->content, line);
+ size_t version_end=line.find(' ');
+ if(version_end!=std::string::npos) {
+ if(5<line.size())
+ response->http_version=line.substr(5, version_end-5);
+ if((version_end+1)<line.size())
+ response->status_code=line.substr(version_end+1, line.size()-(version_end+1)-1);
+
+ getline(response->content, line);
+ size_t param_end;
+ while((param_end=line.find(':'))!=std::string::npos) {
+ size_t value_start=param_end+1;
+ if((value_start)<line.size()) {
+ if(line[value_start]==' ')
+ value_start++;
+ if(value_start<line.size())
+ response->header.insert(std::make_pair(line.substr(0, param_end), line.substr(value_start, line.size()-value_start-1)));
+ }
+
+ getline(response->content, line);
+ }
+ }
+ }
+
+ std::shared_ptr<Response> request_read() {
+ std::shared_ptr<Response> response(new Response());
+
+ asio::streambuf chunked_streambuf;
+
+ auto timer = get_timeout_timer();
+ asio::async_read_until(*socket, response->content_buffer, "\r\n\r\n",
+ [this, &response, &chunked_streambuf,timer](const std::error_code& ec, size_t bytes_transferred) {
+ if (timer)
+ timer->cancel();
+ if (!ec) {
+ size_t num_additional_bytes = response->content_buffer.size() - bytes_transferred;
+
+ parse_response_header(response);
+
+ auto header_it = response->header.find("Content-Length");
+ if (header_it != response->header.end()) {
+ auto content_length = stoull(header_it->second);
+ if (content_length>num_additional_bytes) {
+ auto timer2 = get_timeout_timer();
+ asio::async_read(*socket, response->content_buffer,
+ asio::transfer_exactly(size_t(content_length) - num_additional_bytes),
+ [this,timer2](const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if (timer2)
+ timer2->cancel();
+ if (ec) {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ }
+ }
+ else if ((header_it = response->header.find("Transfer-Encoding")) != response->header.end() && header_it->second == "chunked") {
+ request_read_chunked(response, chunked_streambuf);
+ }
+ }
+ else {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ io_context.reset();
+ io_context.run();
+
+ return response;
+ }
+
+ void request_read_chunked(const std::shared_ptr<Response> &response, asio::streambuf &streambuf) {
+ auto timer = get_timeout_timer();
+ asio::async_read_until(*socket, response->content_buffer, "\r\n",
+ [this, &response, &streambuf,timer](const std::error_code& ec, size_t bytes_transferred) {
+ if (timer)
+ timer->cancel();
+ if (!ec) {
+ std::string line;
+ getline(response->content, line);
+ bytes_transferred -= line.size() + 1;
+ line.pop_back();
+ std::streamsize length = stol(line, nullptr, 16);
+
+ auto num_additional_bytes = static_cast<std::streamsize>(response->content_buffer.size() - bytes_transferred);
+
+ auto post_process = [this, &response, &streambuf, length] {
+ std::ostream stream(&streambuf);
+ if (length > 0) {
+ std::vector<char> buffer(static_cast<size_t>(length));
+ response->content.read(&buffer[0], length);
+ stream.write(&buffer[0], length);
+ }
+
+ //Remove "\r\n"
+ response->content.get();
+ response->content.get();
+
+ if (length>0)
+ request_read_chunked(response, streambuf);
+ else {
+ std::ostream response_stream(&response->content_buffer);
+ response_stream << stream.rdbuf();
+ }
+ };
+
+ if ((2 + length)>num_additional_bytes) {
+ auto timer2 = get_timeout_timer();
+ asio::async_read(*socket, response->content_buffer,
+ asio::transfer_exactly(size_t(2 + length) - size_t(num_additional_bytes)),
+ [this, post_process, timer2](const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if (timer2)
+ timer2->cancel();
+ if (!ec) {
+ post_process();
+ }
+ else {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ }
+ else
+ post_process();
+ }
+ else {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ }
+ };
+
+ template<class socket_type>
+ class Client : public ClientBase<socket_type> {
+ public:
+ Client(const std::string& host_port, unsigned short default_port)
+ : ClientBase<socket_type>(host_port, default_port)
+ {
+ }
+ };
+
+ using HTTP = asio::ip::tcp::socket;
+
+ template<>
+ class Client<HTTP> : public ClientBase<HTTP> {
+ public:
+ explicit Client(const std::string& server_port_path) : ClientBase(server_port_path, 80) { }
+
+ protected:
+ void connect() override {
+ if(!socket || !socket->is_open()) {
+ std::unique_ptr<asio::ip::tcp::resolver::query> query;
+ if (config.proxy_server.empty())
+ query = std::make_unique<asio::ip::tcp::resolver::query>(host, std::to_string(port));
+ else {
+ auto proxy_host_port = parse_host_port(config.proxy_server, 8080);
+ query = std::make_unique<asio::ip::tcp::resolver::query>(proxy_host_port.first, std::to_string(proxy_host_port.second));
+
+ }
+ resolver.async_resolve(*query, [this](const std::error_code &ec,
+ asio::ip::tcp::resolver::iterator it){
+ if(!ec) {
+ {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = std::make_unique<HTTP>(io_context);
+ }
+
+ auto timer = get_timeout_timer();
+ asio::async_connect(*socket, it, [this,timer]
+ (const std::error_code &ec, asio::ip::tcp::resolver::iterator /*it*/){
+ if (timer)
+ timer->cancel();
+ if(!ec) {
+ asio::ip::tcp::no_delay option(true);
+ socket->set_option(option);
+ }
+ else {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket=nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ }
+ else {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket=nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ io_context.reset();
+ io_context.run();
+ }
+ }
+ };
+
+ class http_client : public Client<HTTP> {
+ public:
+ explicit http_client(const std::string& server_port_path) : Client<HTTP>::Client(server_port_path) {}
+ };
+}
+
+#endif /* CLIENT_HTTP_HPP */
diff --git a/src/lib/util/client_https.hpp b/src/lib/util/client_https.hpp
new file mode 100644
index 00000000000..fc1f12bb075
--- /dev/null
+++ b/src/lib/util/client_https.hpp
@@ -0,0 +1,152 @@
+// license:MIT
+// copyright-holders:Ole Christian Eidheim, Miodrag Milanovic
+#ifndef CLIENT_HTTPS_HPP
+#define CLIENT_HTTPS_HPP
+
+#include "client_http.hpp"
+#include "asio/ssl.hpp"
+
+namespace webpp {
+ using HTTPS = asio::ssl::stream<asio::ip::tcp::socket>;
+
+ template<>
+ class Client<HTTPS> : public ClientBase<HTTPS> {
+ public:
+ explicit Client(const std::string& server_port_path, bool verify_certificate=true,
+ const std::string& cert_file=std::string(), const std::string& private_key_file=std::string(),
+ const std::string& verify_file=std::string()) :
+ ClientBase(server_port_path, 443), m_context(asio::ssl::context::tlsv12) {
+ if(cert_file.size()>0 && private_key_file.size()>0) {
+ m_context.use_certificate_chain_file(cert_file);
+ m_context.use_private_key_file(private_key_file, asio::ssl::context::pem);
+ }
+
+ if(verify_certificate)
+ m_context.set_verify_callback(asio::ssl::rfc2818_verification(host));
+
+ if(verify_file.size()>0)
+ m_context.load_verify_file(verify_file);
+ else
+ m_context.set_default_verify_paths();
+
+ if(verify_file.size()>0 || verify_certificate)
+ m_context.set_verify_mode(asio::ssl::verify_peer);
+ else
+ m_context.set_verify_mode(asio::ssl::verify_none);
+ }
+
+ protected:
+ asio::ssl::context m_context;
+
+ void connect() override {
+ if(!socket || !socket->lowest_layer().is_open()) {
+ std::unique_ptr<asio::ip::tcp::resolver::query> query;
+ if (config.proxy_server.empty()) {
+ query = std::make_unique<asio::ip::tcp::resolver::query>(host, std::to_string(port));
+ }
+ else {
+ auto proxy_host_port = parse_host_port(config.proxy_server, 8080);
+ query = std::make_unique<asio::ip::tcp::resolver::query>(proxy_host_port.first, std::to_string(proxy_host_port.second));
+ }
+ resolver.async_resolve(*query, [this]
+ (const std::error_code &ec, asio::ip::tcp::resolver::iterator it) {
+ if (!ec) {
+ {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = std::make_unique<HTTPS>(io_context, m_context);
+ }
+
+ auto timer = get_timeout_timer();
+ asio::async_connect(socket->lowest_layer(), it, [this, timer]
+ (const std::error_code &ec, asio::ip::tcp::resolver::iterator /*it*/) {
+ if (timer)
+ timer->cancel();
+ if (!ec) {
+ asio::ip::tcp::no_delay option(true);
+ socket->lowest_layer().set_option(option);
+ }
+ else {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ }
+ else {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ io_context.reset();
+ io_context.run();
+
+ if (!config.proxy_server.empty()) {
+ asio::streambuf write_buffer;
+ std::ostream write_stream(&write_buffer);
+ auto host_port = host + ':' + std::to_string(port);
+ write_stream << "CONNECT " + host_port + " HTTP/1.1\r\n" << "Host: " << host_port << "\r\n\r\n";
+ auto timer = get_timeout_timer();
+ asio::async_write(socket->next_layer(), write_buffer,
+ [this, timer](const std::error_code &ec, size_t /*bytes_transferred*/) {
+ if (timer)
+ timer->cancel();
+ if (ec) {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ io_context.reset();
+ io_context.run();
+
+ std::shared_ptr<Response> response(new Response());
+ timer=get_timeout_timer();
+ asio::async_read_until(socket->next_layer(), response->content_buffer, "\r\n\r\n",
+ [this, timer](const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(timer)
+ timer->cancel();
+ if(ec) {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket=nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ io_context.reset();
+ io_context.run();
+ parse_response_header(response);
+
+ if (response->status_code.size()>0 && response->status_code.compare(0, 3, "200") != 0) {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(std::error_code(int(std::errc::permission_denied), std::generic_category()));
+ }
+ }
+
+ auto timer = get_timeout_timer();
+ this->socket->async_handshake(asio::ssl::stream_base::client,
+ [this, timer](const std::error_code& ec) {
+ if (timer)
+ timer->cancel();
+ if (ec) {
+ std::lock_guard<std::mutex> lock(socket_mutex);
+ socket = nullptr;
+ throw std::system_error(ec);
+ }
+ });
+ io_context.reset();
+ io_context.run();
+ }
+ }
+ };
+
+ class https_client : public Client<HTTPS> {
+ public:
+ explicit https_client(const std::string& server_port_path, bool verify_certificate = true,
+ const std::string& cert_file = std::string(), const std::string& private_key_file = std::string(),
+ const std::string& verify_file = std::string()) : Client<HTTPS>::Client(server_port_path, verify_certificate, cert_file, private_key_file, verify_file) {}
+ };
+
+}
+
+#endif /* CLIENT_HTTPS_HPP */
diff --git a/src/lib/util/client_ws.hpp b/src/lib/util/client_ws.hpp
new file mode 100644
index 00000000000..f3c4ded6bb2
--- /dev/null
+++ b/src/lib/util/client_ws.hpp
@@ -0,0 +1,517 @@
+// license:MIT
+// copyright-holders:Ole Christian Eidheim, Miodrag Milanovic
+#ifndef CLIENT_WS_HPP
+#define CLIENT_WS_HPP
+
+#include "asio.h"
+
+#include <unordered_map>
+#include <iostream>
+#include <random>
+#include <atomic>
+#include <list>
+#include "crypto.hpp"
+
+#ifndef CASE_INSENSITIVE_EQUALS_AND_HASH
+#define CASE_INSENSITIVE_EQUALS_AND_HASH
+class case_insensitive_equals {
+public:
+ bool operator()(const std::string &key1, const std::string &key2) const {
+ return key1.size() == key2.size()
+ && equal(key1.cbegin(), key1.cend(), key2.cbegin(),
+ [](std::string::value_type key1v, std::string::value_type key2v)
+ { return tolower(key1v) == tolower(key2v); });
+ }
+};
+class case_insensitive_hash {
+public:
+ size_t operator()(const std::string &key) const {
+ size_t seed = 0;
+ for (auto &c : key) {
+ std::hash<char> hasher;
+ seed ^= hasher(std::tolower(c)) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ }
+ return seed;
+ }
+};
+#endif
+
+namespace webpp {
+ template <class socket_type>
+ class SocketClient;
+
+ template <class socket_type>
+ class SocketClientBase {
+ public:
+ virtual ~SocketClientBase() { connection.reset(); }
+
+ class SendStream : public std::iostream {
+ friend class SocketClientBase<socket_type>;
+ asio::streambuf streambuf;
+ public:
+ SendStream(): std::iostream(&streambuf) {}
+ size_t size() const {
+ return streambuf.size();
+ }
+ };
+
+ class Connection {
+ friend class SocketClientBase<socket_type>;
+ friend class SocketClient<socket_type>;
+
+ public:
+ std::unordered_multimap<std::string, std::string, case_insensitive_hash, case_insensitive_equals> header;
+ std::string remote_endpoint_address;
+ unsigned short remote_endpoint_port;
+
+ private:
+ explicit Connection(socket_type* socket): remote_endpoint_port(0), socket(socket), strand(socket->get_io_context()), closed(false) { }
+
+ class SendData {
+ public:
+ SendData(const std::shared_ptr<SendStream> &send_stream, const std::function<void(const std::error_code)> &callback) :
+ send_stream(send_stream), callback(callback) {}
+ std::shared_ptr<SendStream> send_stream;
+ std::function<void(const std::error_code)> callback;
+ };
+
+ std::unique_ptr<socket_type> socket;
+
+ asio::io_context::strand strand;
+
+ std::list<SendData> send_queue;
+
+ void send_from_queue() {
+ strand.post([this]() {
+ asio::async_write(*socket, send_queue.begin()->send_stream->streambuf,
+ strand.wrap([this](const std::error_code& ec, size_t /*bytes_transferred*/) {
+ auto send_queued=send_queue.begin();
+ if(send_queued->callback)
+ send_queued->callback(ec);
+ if(!ec) {
+ send_queue.erase(send_queued);
+ if(send_queue.size()>0)
+ send_from_queue();
+ }
+ else
+ send_queue.clear();
+ }));
+ });
+ }
+
+ std::atomic<bool> closed;
+
+ void read_remote_endpoint_data() {
+ try {
+ remote_endpoint_address=socket->lowest_layer().remote_endpoint().address().to_string();
+ remote_endpoint_port=socket->lowest_layer().remote_endpoint().port();
+ }
+ catch(const std::exception& e) {
+ std::cerr << e.what() << std::endl;
+ }
+ }
+ };
+
+ std::shared_ptr<Connection> connection;
+
+ class Message : public std::istream {
+ friend class SocketClientBase<socket_type>;
+
+ public:
+ unsigned char fin_rsv_opcode;
+ size_t size() const {
+ return length;
+ }
+ std::string string() const {
+ std::stringstream ss;
+ ss << rdbuf();
+ return ss.str();
+ }
+ private:
+ Message(): std::istream(&streambuf), fin_rsv_opcode(0), length(0) { }
+
+ size_t length;
+ asio::streambuf streambuf;
+ };
+
+ std::function<void()> on_open;
+ std::function<void(std::shared_ptr<Message>)> on_message;
+ std::function<void(int, const std::string&)> on_close;
+ std::function<void(const std::error_code&)> on_error;
+
+ void start() {
+ if(!io_context) {
+ io_context=std::make_shared<asio::io_context>();
+ internal_io_context=true;
+ }
+
+ if(io_context->stopped())
+ io_context->reset();
+
+ if(!resolver)
+ resolver= std::make_unique<asio::ip::tcp::resolver>(*io_context);
+
+ connect();
+
+ if(internal_io_context)
+ io_context->run();
+ }
+
+ void stop() const {
+ resolver->cancel();
+ if(internal_io_context)
+ io_context->stop();
+ }
+
+ ///fin_rsv_opcode: 129=one fragment, text, 130=one fragment, binary, 136=close connection.
+ ///See http://tools.ietf.org/html/rfc6455#section-5.2 for more information
+ void send(const std::shared_ptr<SendStream> &message_stream, const std::function<void(const std::error_code&)>& callback=nullptr,
+ unsigned char fin_rsv_opcode=129) {
+ //Create mask
+ std::vector<unsigned char> mask;
+ mask.resize(4);
+ std::uniform_int_distribution<unsigned short> dist(0,255);
+ std::random_device rd;
+ for(int c=0;c<4;c++) {
+ mask[c]=static_cast<unsigned char>(dist(rd));
+ }
+
+ auto send_stream = std::make_shared<SendStream>();
+
+ size_t length=message_stream->size();
+
+ send_stream->put(fin_rsv_opcode);
+ //masked (first length byte>=128)
+ if(length>=126) {
+ int num_bytes;
+ if(length>0xffff) {
+ num_bytes=8;
+ send_stream->put(static_cast<unsigned char>(127+128));
+ }
+ else {
+ num_bytes=2;
+ send_stream->put(static_cast<unsigned char>(126+128));
+ }
+
+ for(int c=num_bytes-1;c>=0;c--) {
+ send_stream->put((static_cast<unsigned long long>(length) >> (8 * c)) % 256);
+ }
+ }
+ else
+ send_stream->put(static_cast<unsigned char>(length+128));
+
+ for(int c=0;c<4;c++) {
+ send_stream->put(mask[c]);
+ }
+
+ for(size_t c=0;c<length;c++) {
+ send_stream->put(message_stream->get()^mask[c%4]);
+ }
+
+ connection->strand.post([this, send_stream, callback]() {
+ connection->send_queue.emplace_back(send_stream, callback);
+ if(connection->send_queue.size()==1)
+ connection->send_from_queue();
+ });
+ }
+
+ void send_close(int status, const std::string& reason="", const std::function<void(const std::error_code&)>& callback=nullptr) {
+ //Send close only once (in case close is initiated by client)
+ if(connection->closed)
+ return;
+ connection->closed=true;
+
+ auto send_stream=std::make_shared<SendStream>();
+
+ send_stream->put(status>>8);
+ send_stream->put(status%256);
+
+ *send_stream << reason;
+
+ //fin_rsv_opcode=136: message close
+ send(send_stream, callback, 136);
+ }
+
+ /// If you have your own asio::io_context, store its pointer here before running start().
+ std::shared_ptr<asio::io_context> io_context;
+ protected:
+ const std::string ws_magic_string="258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
+ bool internal_io_context=false;
+ std::unique_ptr<asio::ip::tcp::resolver> resolver;
+
+ std::string host;
+ unsigned short port;
+ std::string path;
+
+ SocketClientBase(const std::string& host_port_path, unsigned short default_port) {
+ size_t host_end=host_port_path.find(':');
+ size_t host_port_end=host_port_path.find('/');
+ if(host_end==std::string::npos) {
+ host_end=host_port_end;
+ port=default_port;
+ }
+ else {
+ if(host_port_end==std::string::npos)
+ port=static_cast<unsigned short>(stoul(host_port_path.substr(host_end + 1)));
+ else
+ port=static_cast<unsigned short>(stoul(host_port_path.substr(host_end + 1, host_port_end - (host_end + 1))));
+ }
+ if(host_port_end==std::string::npos)
+ path="/";
+ else
+ path=host_port_path.substr(host_port_end);
+ if(host_end==std::string::npos)
+ host=host_port_path;
+ else
+ host=host_port_path.substr(0, host_end);
+ }
+
+ virtual void connect()=0;
+
+ void handshake() {
+ connection->read_remote_endpoint_data();
+
+ auto write_buffer = std::make_shared<asio::streambuf>();
+
+ std::ostream request(write_buffer.get());
+
+ request << "GET " << path << " HTTP/1.1" << "\r\n";
+ request << "Host: " << host << "\r\n";
+ request << "Upgrade: websocket\r\n";
+ request << "Connection: Upgrade\r\n";
+
+ //Make random 16-byte nonce
+ std::string nonce;
+ nonce.resize(16);
+ std::uniform_int_distribution<unsigned short> dist(0,255);
+ std::random_device rd;
+ for(int c=0;c<16;c++)
+ nonce[c]=static_cast<unsigned char>(dist(rd));
+
+ auto nonce_base64 = std::make_shared<std::string>(base64_encode(nonce));
+ request << "Sec-WebSocket-Key: " << *nonce_base64 << "\r\n";
+ request << "Sec-WebSocket-Version: 13\r\n";
+ request << "\r\n";
+
+ asio::async_write(*connection->socket, *write_buffer,
+ [this, write_buffer, nonce_base64]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(!ec) {
+ std::shared_ptr<Message> message(new Message());
+
+ asio::async_read_until(*connection->socket, message->streambuf, "\r\n\r\n",
+ [this, message, nonce_base64]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(!ec) {
+ parse_handshake(*message);
+ auto header_it = connection->header.find("Sec-WebSocket-Accept");
+ if (header_it != connection->header.end() &&
+ base64_decode(header_it->second) == sha1_encode(*nonce_base64 + ws_magic_string)) {
+ if(on_open)
+ on_open();
+ read_message(message);
+ }
+ else if(on_error)
+ on_error(std::error_code(int(std::errc::protocol_error), std::generic_category()));
+ }
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+
+ void parse_handshake(std::istream& stream) const {
+ std::string line;
+ getline(stream, line);
+ //Not parsing the first line
+
+ getline(stream, line);
+ size_t param_end;
+ while((param_end=line.find(':'))!=std::string::npos) {
+ size_t value_start=param_end+1;
+ if((value_start)<line.size()) {
+ if(line[value_start]==' ')
+ value_start++;
+ if(value_start<line.size())
+ connection->header.emplace(line.substr(0, param_end), line.substr(value_start, line.size()-value_start-1));
+ }
+
+ getline(stream, line);
+ }
+ }
+
+ void read_message(const std::shared_ptr<Message> &message) {
+ asio::async_read(*connection->socket, message->streambuf, asio::transfer_exactly(2),
+ [this, message](const std::error_code& ec, size_t bytes_transferred) {
+ if(!ec) {
+ if(bytes_transferred==0) { //TODO: This might happen on server at least, might also happen here
+ read_message(message);
+ return;
+ }
+ std::vector<unsigned char> first_bytes;
+ first_bytes.resize(2);
+ message->read(reinterpret_cast<char*>(&first_bytes[0]), 2);
+
+ message->fin_rsv_opcode=first_bytes[0];
+
+ //Close connection if masked message from server (protocol error)
+ if(first_bytes[1]>=128) {
+ const std::string reason("message from server masked");
+ auto kept_connection=connection;
+ send_close(1002, reason, [this, kept_connection](const std::error_code& /*ec*/) {});
+ if(on_close)
+ on_close(1002, reason);
+ return;
+ }
+
+ size_t length=(first_bytes[1]&127);
+
+ if(length==126) {
+ //2 next bytes is the size of content
+ asio::async_read(*connection->socket, message->streambuf, asio::transfer_exactly(2),
+ [this, message]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(!ec) {
+ std::vector<unsigned char> length_bytes;
+ length_bytes.resize(2);
+ message->read(reinterpret_cast<char*>(&length_bytes[0]), 2);
+
+ size_t length=0;
+ int num_bytes=2;
+ for(int c=0;c<num_bytes;c++)
+ length+=length_bytes[c]<<(8*(num_bytes-1-c));
+
+ message->length=length;
+ read_message_content(message);
+ }
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+ else if(length==127) {
+ //8 next bytes is the size of content
+ asio::async_read(*connection->socket, message->streambuf, asio::transfer_exactly(8),
+ [this, message]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(!ec) {
+ std::vector<unsigned char> length_bytes;
+ length_bytes.resize(8);
+ message->read(reinterpret_cast<char*>(&length_bytes[0]), 8);
+
+ size_t length=0;
+ int num_bytes=8;
+ for(int c=0;c<num_bytes;c++)
+ length+=length_bytes[c]<<(8*(num_bytes-1-c));
+
+ message->length=length;
+ read_message_content(message);
+ }
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+ else {
+ message->length=length;
+ read_message_content(message);
+ }
+ }
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+
+ void read_message_content(const std::shared_ptr<Message> &message) {
+ asio::async_read(*connection->socket, message->streambuf, asio::transfer_exactly(message->length),
+ [this, message]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(!ec) {
+ //If connection close
+ if((message->fin_rsv_opcode&0x0f)==8) {
+ int status=0;
+ if(message->length>=2) {
+ unsigned char byte1=message->get();
+ unsigned char byte2=message->get();
+ status=(byte1<<8)+byte2;
+ }
+
+ auto reason=message->string();
+ auto kept_connection=connection;
+ send_close(status, reason, [this, kept_connection](const std::error_code& /*ec*/) {});
+ if(on_close)
+ on_close(status, reason);
+ return;
+ }
+ //If ping
+ else if((message->fin_rsv_opcode&0x0f)==9) {
+ //send pong
+ auto empty_send_stream=std::make_shared<SendStream>();
+ send(empty_send_stream, nullptr, message->fin_rsv_opcode+1);
+ }
+ else if(on_message) {
+ on_message(message);
+ }
+
+ //Next message
+ std::shared_ptr<Message> next_message(new Message());
+ read_message(next_message);
+ }
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+ };
+
+ template<class socket_type>
+ class SocketClient : public SocketClientBase<socket_type> {
+ public:
+ SocketClient(const std::string& host_port_path, unsigned short default_port)
+ : SocketClientBase<socket_type>(host_port_path, default_port)
+ {
+ }
+ };
+
+ using WS = asio::ip::tcp::socket;
+
+ template<>
+ class SocketClient<WS> : public SocketClientBase<WS> {
+ public:
+ explicit SocketClient(const std::string& server_port_path) : SocketClientBase(server_port_path, 80) {};
+
+ protected:
+ void connect() override {
+ asio::ip::tcp::resolver::query query(host, std::to_string(port));
+
+ resolver->async_resolve(query, [this]
+ (const std::error_code &ec, asio::ip::tcp::resolver::iterator it){
+ if(!ec) {
+ connection=std::shared_ptr<Connection>(new Connection(new WS(*io_context)));
+
+ asio::async_connect(*connection->socket, it, [this]
+ (const std::error_code &ec, asio::ip::tcp::resolver::iterator /*it*/){
+ if(!ec) {
+ asio::ip::tcp::no_delay option(true);
+ connection->socket->set_option(option);
+
+ handshake();
+ }
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+ };
+
+ class ws_client : public SocketClient<WS> {
+ public:
+ explicit ws_client(const std::string& server_port_path) : SocketClient<WS>::SocketClient(server_port_path) {}
+ };
+}
+
+#endif /* CLIENT_WS_HPP */
diff --git a/src/lib/util/client_wss.hpp b/src/lib/util/client_wss.hpp
new file mode 100644
index 00000000000..ef30b459607
--- /dev/null
+++ b/src/lib/util/client_wss.hpp
@@ -0,0 +1,82 @@
+// license:MIT
+// copyright-holders:Ole Christian Eidheim, Miodrag Milanovic
+#ifndef CLIENT_WSS_HPP
+#define CLIENT_WSS_HPP
+
+#include "client_ws.hpp"
+#include "asio/ssl.hpp"
+
+namespace webpp {
+ using WSS = asio::ssl::stream<asio::ip::tcp::socket>;
+
+ template<>
+ class SocketClient<WSS> : public SocketClientBase<WSS> {
+ public:
+ explicit SocketClient(const std::string& server_port_path, bool verify_certificate=true,
+ const std::string& cert_file=std::string(), const std::string& private_key_file=std::string(),
+ const std::string& verify_file=std::string()) :
+ SocketClientBase(server_port_path, 443),
+ context(asio::ssl::context::tlsv12) {
+ if(cert_file.size()>0 && private_key_file.size()>0) {
+ context.use_certificate_chain_file(cert_file);
+ context.use_private_key_file(private_key_file, asio::ssl::context::pem);
+ }
+
+ if (verify_certificate)
+ context.set_verify_callback(asio::ssl::rfc2818_verification(host));
+
+ if (verify_file.size() > 0)
+ context.load_verify_file(verify_file);
+ else
+ context.set_default_verify_paths();
+
+ if (verify_file.size()>0 || verify_certificate)
+ context.set_verify_mode(asio::ssl::verify_peer);
+ else
+ context.set_verify_mode(asio::ssl::verify_none);
+ };
+
+ protected:
+ asio::ssl::context context;
+
+ void connect() override {
+ asio::ip::tcp::resolver::query query(host, std::to_string(port));
+
+ resolver->async_resolve(query, [this]
+ (const std::error_code &ec, asio::ip::tcp::resolver::iterator it){
+ if(!ec) {
+ connection=std::shared_ptr<Connection>(new Connection(new WSS(*io_context, context)));
+
+ asio::async_connect(connection->socket->lowest_layer(), it, [this]
+ (const std::error_code &ec, asio::ip::tcp::resolver::iterator /*it*/){
+ if(!ec) {
+ asio::ip::tcp::no_delay option(true);
+ connection->socket->lowest_layer().set_option(option);
+
+ connection->socket->async_handshake(asio::ssl::stream_base::client,
+ [this](const std::error_code& ec) {
+ if(!ec)
+ handshake();
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+ else if(on_error)
+ on_error(ec);
+ });
+ }
+ };
+
+ class wss_client : public SocketClient<WSS> {
+ public:
+ explicit wss_client(const std::string& server_port_path, bool verify_certificate = true,
+ const std::string& cert_file = std::string(), const std::string& private_key_file = std::string(),
+ const std::string& verify_file = std::string()) : SocketClient<WSS>::SocketClient(server_port_path, verify_certificate, cert_file, private_key_file, verify_file) {}
+ };
+}
+
+#endif /* CLIENT_WSS_HPP */
diff --git a/src/lib/util/crypto.hpp b/src/lib/util/crypto.hpp
new file mode 100644
index 00000000000..705aad6a375
--- /dev/null
+++ b/src/lib/util/crypto.hpp
@@ -0,0 +1,18 @@
+// license:MIT
+// copyright-holders:Miodrag Milanovic
+#ifndef CRYPTO_HPP
+#define CRYPTO_HPP
+
+#include "base64.hpp"
+#include "sha1.hpp"
+
+inline std::string sha1_encode(const std::string& input)
+{
+ char message_digest[20];
+ sha1::calc(input.c_str(),input.length(),reinterpret_cast<unsigned char*>(message_digest));
+
+ return std::string(message_digest, sizeof(message_digest));
+
+}
+#endif /* CRYPTO_HPP */
+
diff --git a/src/lib/util/path_to_regex.cpp b/src/lib/util/path_to_regex.cpp
new file mode 100644
index 00000000000..927ababbb8a
--- /dev/null
+++ b/src/lib/util/path_to_regex.cpp
@@ -0,0 +1,217 @@
+// license:MIT
+// copyright-holders:Alfred Bratterud
+// NOTE: Author allowed MAME project to distribute this file under MIT
+// license. Other projects need to do it under Apache 2 license
+//
+// This file is a part of the IncludeOS unikernel - www.includeos.org
+//
+// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
+// and Alfred Bratterud
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// https://github.com/pillarjs/path-to-regexp/blob/master/index.js
+
+#include "path_to_regex.hpp"
+
+namespace path2regex {
+
+const std::regex PATH_REGEXP =
+ std::regex{"((\\\\.)|(([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))))"};
+
+std::regex path_to_regex(const std::string& path, Keys& keys, const Options& options) {
+ Tokens all_tokens = parse(path);
+ tokens_to_keys(all_tokens, keys); // fill keys with relevant tokens
+ return tokens_to_regex(all_tokens, options);
+}
+
+std::regex path_to_regex(const std::string& path, const Options& options) {
+ return tokens_to_regex(parse(path), options);
+}
+
+// Parse a string for the raw tokens
+std::vector<Token> parse(const std::string& str) {
+ if (str.empty())
+ return {};
+
+ Tokens tokens;
+ int key = 0;
+ int index = 0;
+ std::string path = "";
+ std::smatch res;
+
+ for (std::sregex_iterator i = std::sregex_iterator{str.begin(), str.end(), PATH_REGEXP};
+ i != std::sregex_iterator{}; ++i) {
+
+ res = *i;
+
+ std::string m = res[0]; // the parameter, f.ex. /:test
+ std::string escaped = res[2];
+ int offset = res.position();
+
+ // JS: path += str.slice(index, offset); from and included index to and included offset-1
+ path += str.substr(index, (offset - index)); // from index, number of chars: offset - index
+
+ index = offset + m.size();
+
+ if (!escaped.empty()) {
+ path += escaped[1]; // if escaped == \a, escaped[1] == a (if str is "/\\a" f.ex.)
+ continue;
+ }
+
+ std::string next = (size_t(index) < str.size()) ? std::string{str.at(index)} : "";
+
+ std::string prefix = res[4]; // f.ex. /
+ std::string name = res[5]; // f.ex. test
+ std::string capture = res[6]; // f.ex. \d+
+ std::string group = res[7]; // f.ex. (users|admins)
+ std::string modifier = res[8]; // f.ex. ?
+ std::string asterisk = res[9]; // * if path is /*
+
+ // Push the current path onto the tokens
+ if (!path.empty()) {
+ Token stringToken;
+ stringToken.set_string_token(path);
+ tokens.push_back(stringToken);
+ path = "";
+ }
+
+ bool partial = (!prefix.empty()) && (!next.empty()) && (next != prefix);
+ bool repeat = (modifier == "+") || (modifier == "*");
+ bool optional = (modifier == "?") || (modifier == "*");
+ std::string delimiter = (!prefix.empty()) ? prefix : "/";
+ std::string pattern;
+
+ if (!capture.empty())
+ pattern = capture;
+ else if (!group.empty())
+ pattern = group;
+ else
+ pattern = (!asterisk.empty()) ? ".*" : ("[^" + delimiter + "]+?");
+
+ Token t;
+ t.name = (!name.empty()) ? name : std::to_string(key++);
+ t.prefix = prefix;
+ t.delimiter = delimiter;
+ t.optional = optional;
+ t.repeat = repeat;
+ t.partial = partial;
+ t.asterisk = (asterisk == "*");
+ t.pattern = pattern;
+ t.is_string = false;
+ tokens.push_back(t);
+ }
+
+ // Match any characters still remaining
+ if (size_t(index) < str.size())
+ path += str.substr(index);
+
+ // If the path exists, push it onto the end
+ if (!path.empty()) {
+ Token stringToken;
+ stringToken.set_string_token(path);
+ tokens.push_back(stringToken);
+ }
+
+ return tokens;
+}
+
+// Creates a regex based on the given tokens and options (optional)
+std::regex tokens_to_regex(const Tokens& tokens, const Options& options) {
+ if (tokens.empty())
+ return std::regex{""};
+
+ // Set default values for options:
+ bool strict = false;
+ bool sensitive = false;
+ bool end = true;
+
+ if (!options.empty()) {
+ auto it = options.find("strict");
+ strict = (it != options.end()) ? options.find("strict")->second : false;
+
+ it = options.find("sensitive");
+ sensitive = (it != options.end()) ? options.find("sensitive")->second : false;
+
+ it = options.find("end");
+ end = (it != options.end()) ? options.find("end")->second : true;
+ }
+
+ std::string route = "";
+ Token lastToken = tokens[tokens.size() - 1];
+ std::regex re{"(.*\\/$)"};
+ bool endsWithSlash = lastToken.is_string && std::regex_match(lastToken.name, re);
+ // endsWithSlash if the last char in lastToken's name is a slash
+
+ // Iterate over the tokens and create our regexp string
+ for (size_t i = 0; i < tokens.size(); i++) {
+ Token token = tokens[i];
+
+ if (token.is_string) {
+ route += token.name;
+ } else {
+ std::string prefix = token.prefix;
+ std::string capture = "(?:" + token.pattern + ")";
+
+ if (token.repeat)
+ capture += "(?:" + prefix + capture + ")*";
+
+ if (token.optional) {
+
+ if (!token.partial)
+ capture = "(?:" + prefix + "(" + capture + "))?";
+ else
+ capture = prefix + "(" + capture + ")?";
+
+ } else {
+ capture = prefix + "(" + capture + ")";
+ }
+
+ route += capture;
+ }
+ }
+
+ // In non-strict mode we allow a slash at the end of match. If the path to
+ // match already ends with a slash, we remove it for consistency. The slash
+ // is valid at the end of a path match, not in the middle. This is important
+ // in non-ending mode, where "/test/" shouldn't match "/test//route".
+
+ if (!strict) {
+ if (endsWithSlash)
+ route = route.substr(0, (route.size() - 1));
+
+ route += "(?:\\/(?=$))?";
+ }
+
+ if (end) {
+ route += "$";
+ } else {
+ // In non-ending mode, we need the capturing groups to match as much as
+ // possible by using a positive lookahead to the end or next path segment
+ if (!(strict && endsWithSlash))
+ route += "(?=\\/|$)";
+ }
+
+ if (sensitive)
+ return std::regex{"^" + route};
+
+ return std::regex{"^" + route, std::regex_constants::ECMAScript | std::regex_constants::icase};
+}
+
+void tokens_to_keys(const Tokens& tokens, Keys& keys) {
+ for (const auto& token : tokens)
+ if (!token.is_string)
+ keys.push_back(token);
+}
+
+} //< namespace route
diff --git a/src/lib/util/path_to_regex.hpp b/src/lib/util/path_to_regex.hpp
new file mode 100644
index 00000000000..7608d77bb5d
--- /dev/null
+++ b/src/lib/util/path_to_regex.hpp
@@ -0,0 +1,110 @@
+// license:MIT
+// copyright-holders:Alfred Bratterud
+// NOTE: Author allowed MAME project to distribute this file under MIT
+// license. Other projects need to do it under Apache 2 license
+//
+// This file is a part of the IncludeOS unikernel - www.includeos.org
+//
+// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
+// and Alfred Bratterud
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// https://github.com/pillarjs/path-to-regexp/blob/master/index.js
+
+#ifndef PATH_TO_REGEX_HPP
+#define PATH_TO_REGEX_HPP
+
+#include <map>
+#include <regex>
+#include <vector>
+
+namespace path2regex {
+
+struct Token {
+ std::string name {}; // can be a string or an int (index)
+ std::string prefix {};
+ std::string delimiter {};
+ std::string pattern {};
+ bool optional {false};
+ bool repeat {false};
+ bool partial {false};
+ bool asterisk {false};
+ bool is_string {false}; // If it is a string we only put/have a string in the name-attribute (path in parse-method)
+ // So if this is true, we can ignore all attributes except name
+
+ void set_string_token(const std::string& name_) {
+ name = name_;
+ is_string = true;
+ }
+}; //< struct Token
+
+using Keys = std::vector<Token>;
+using Tokens = std::vector<Token>;
+using Options = std::map<std::string, bool>;
+
+ /**
+ * Creates a path-regex from string input (path)
+ * Updates keys-vector (empty input parameter)
+ *
+ * Calls parse-method and then tokens_to_regex-method based on the tokens returned from parse-method
+ * Puts the tokens that are keys (not string-tokens) into keys-vector
+ *
+ * std::vector<Token> keys (empty)
+ * Is created outside the class and sent in as parameter
+ * One Token-object in the keys-vector per parameter found in the path
+ *
+ * std::map<std::string, bool> options (optional)
+ * Can contain bool-values for the keys "sensitive", "strict" and/or "end"
+ * Default:
+ * strict = false
+ * sensitive = false
+ * end = true
+ */
+ std::regex path_to_regex(const std::string& path, Keys& keys, const Options& options = Options{});
+
+ /**
+ * Creates a path-regex from string input (path)
+ *
+ * Calls parse-method and then tokens_to_regex-method based on the tokens returned from parse-method
+ *
+ * std::map<std::string, bool> options (optional)
+ * Can contain bool-values for the keys "sensitive", "strict" and/or "end"
+ * Default:
+ * strict = false
+ * sensitive = false
+ * end = true
+ */
+ std::regex path_to_regex(const std::string& path, const Options& options = Options{});
+
+ /**
+ * Creates vector of tokens based on the given string (this vector of tokens can be sent as
+ * input to tokens_to_regex-method and includes tokens that are strings, not only tokens
+ * that are parameters in str)
+ */
+ Tokens parse(const std::string& str);
+
+ /**
+ * Creates a regex based on the tokens and options (optional) given
+ */
+ std::regex tokens_to_regex(const Tokens& tokens, const Options& options = Options{});
+
+ /**
+ * Goes through the tokens-vector and push all tokens that are not string-tokens
+ * onto keys-vector
+ */
+ void tokens_to_keys(const Tokens& tokens, Keys& keys);
+
+} //< namespace path2regex
+
+#endif //< PATH_TO_REGEX_HPP
diff --git a/src/lib/util/server_http.hpp b/src/lib/util/server_http.hpp
new file mode 100644
index 00000000000..57fd57e6993
--- /dev/null
+++ b/src/lib/util/server_http.hpp
@@ -0,0 +1,497 @@
+// license:MIT
+// copyright-holders:Ole Christian Eidheim, Miodrag Milanovic
+#ifndef SERVER_HTTP_HPP
+#define SERVER_HTTP_HPP
+
+#if defined(_MSC_VER)
+#pragma warning(disable:4503)
+#endif
+
+#include "asio.h"
+#include "asio/system_timer.hpp"
+#include "path_to_regex.hpp"
+
+#include <map>
+#include <unordered_map>
+#include <thread>
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <regex>
+
+#ifndef CASE_INSENSITIVE_EQUALS_AND_HASH
+#define CASE_INSENSITIVE_EQUALS_AND_HASH
+class case_insensitive_equals {
+public:
+ bool operator()(const std::string &key1, const std::string &key2) const {
+ return key1.size() == key2.size()
+ && equal(key1.cbegin(), key1.cend(), key2.cbegin(),
+ [](std::string::value_type key1v, std::string::value_type key2v)
+ { return tolower(key1v) == tolower(key2v); });
+ }
+};
+class case_insensitive_hash {
+public:
+ size_t operator()(const std::string &key) const {
+ size_t seed = 0;
+ for (auto &c : key) {
+ std::hash<char> hasher;
+ seed ^= hasher(std::tolower(c)) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ }
+ return seed;
+ }
+};
+#endif
+namespace webpp {
+ template <class socket_type>
+ class Server;
+
+ template <class socket_type>
+ class ServerBase {
+ public:
+ virtual ~ServerBase() {}
+
+ class Response {
+ friend class ServerBase<socket_type>;
+
+ asio::streambuf m_streambuf;
+
+ std::shared_ptr<socket_type> m_socket;
+ std::ostream m_ostream;
+ std::stringstream m_header;
+ explicit Response(const std::shared_ptr<socket_type> &socket) : m_socket(socket), m_ostream(&m_streambuf) {}
+
+ static std::string statusToString(int status)
+ {
+ switch (status) {
+ default:
+ case 200: return "HTTP/1.0 200 OK\r\n";
+ case 201: return "HTTP/1.0 201 Created\r\n";
+ case 202: return "HTTP/1.0 202 Accepted\r\n";
+ case 204: return "HTTP/1.0 204 No Content\r\n";
+ case 300: return "HTTP/1.0 300 Multiple Choices\r\n";
+ case 301: return "HTTP/1.0 301 Moved Permanently\r\n";
+ case 302: return "HTTP/1.0 302 Moved Temporarily\r\n";
+ case 304: return "HTTP/1.0 304 Not Modified\r\n";
+ case 400: return "HTTP/1.0 400 Bad Request\r\n";
+ case 401: return "HTTP/1.0 401 Unauthorized\r\n";
+ case 403: return "HTTP/1.0 403 Forbidden\r\n";
+ case 404: return "HTTP/1.0 404 Not Found\r\n";
+ case 500: return "HTTP/1.0 500 Internal Server Error\r\n";
+ case 501: return "HTTP/1.0 501 Not Implemented\r\n";
+ case 502: return "HTTP/1.0 502 Bad Gateway\r\n";
+ case 504: return "HTTP/1.0 503 Service Unavailable\r\n";
+ }
+ }
+ public:
+ Response& status(int number) { m_ostream << statusToString(number); return *this; }
+ void type(std::string str) { m_header << "Content-Type: "<< str << "\r\n"; }
+ void send(std::string str) { m_ostream << m_header.str() << "Content-Length: " << str.length() << "\r\n\r\n" << str; }
+ size_t size() const { return m_streambuf.size(); }
+ std::shared_ptr<socket_type> socket() { return m_socket; }
+ };
+
+ class Content : public std::istream {
+ friend class ServerBase<socket_type>;
+ public:
+ size_t size() const {
+ return streambuf.size();
+ }
+ std::string string() const {
+ std::stringstream ss;
+ ss << rdbuf();
+ return ss.str();
+ }
+ private:
+ asio::streambuf &streambuf;
+ explicit Content(asio::streambuf &streambuf): std::istream(&streambuf), streambuf(streambuf) {}
+ };
+
+ class Request {
+ friend class ServerBase<socket_type>;
+ friend class Server<socket_type>;
+ public:
+ std::string method, path, http_version;
+
+ Content content;
+
+ std::unordered_multimap<std::string, std::string, case_insensitive_hash, case_insensitive_equals> header;
+
+ path2regex::Keys keys;
+ std::map<std::string, std::string> params;
+
+ std::string remote_endpoint_address;
+ unsigned short remote_endpoint_port;
+
+ private:
+ Request(const socket_type &socket): content(streambuf) {
+ try {
+ remote_endpoint_address=socket.lowest_layer().remote_endpoint().address().to_string();
+ remote_endpoint_port=socket.lowest_layer().remote_endpoint().port();
+ }
+ catch(...) {}
+ }
+ asio::streambuf streambuf;
+ };
+
+ class Config {
+ friend class ServerBase<socket_type>;
+
+ Config(unsigned short port) : port(port) {}
+ public:
+ /// Port number to use. Defaults to 80 for HTTP and 443 for HTTPS.
+ unsigned short port;
+ /// Number of threads that the server will use when start() is called. Defaults to 1 thread.
+ size_t thread_pool_size=1;
+ /// Timeout on request handling. Defaults to 5 seconds.
+ size_t timeout_request=5;
+ /// Timeout on content handling. Defaults to 300 seconds.
+ size_t timeout_content=300;
+ /// IPv4 address in dotted decimal form or IPv6 address in hexadecimal notation.
+ /// If empty, the address will be any address.
+ std::string address;
+ /// Set to false to avoid binding the socket to an address that is already in use. Defaults to true.
+ bool reuse_address=true;
+ };
+ ///Set before calling start().
+ Config m_config;
+ private:
+ class regex_orderable : public std::regex {
+ std::string str;
+ public:
+ regex_orderable(std::regex reg, const std::string &regex_str) : std::regex(reg), str(regex_str) {}
+ bool operator<(const regex_orderable &rhs) const {
+ return str<rhs.str;
+ }
+ std::string getstr() const { return str; }
+ };
+ using http_handler = std::function<void(std::shared_ptr<Response>, std::shared_ptr<Request>)>;
+
+ public:
+ template<class T> void on_get(std::string regex, T&& func) { std::lock_guard<std::mutex> lock(m_resource_mutex); path2regex::Keys keys; auto reg = path2regex::path_to_regex(regex, keys); m_resource[regex_orderable(reg,regex)]["GET"] = std::make_tuple(std::move(keys), func); }
+ template<class T> void on_get(T&& func) { std::lock_guard<std::mutex> lock(m_resource_mutex); m_default_resource["GET"] = func; }
+ template<class T> void on_post(std::string regex, T&& func) { std::lock_guard<std::mutex> lock(m_resource_mutex); path2regex::Keys keys; auto reg = path2regex::path_to_regex(regex, keys); m_resource[regex_orderable(reg, regex)]["POST"] = std::make_tuple(std::move(keys), func); }
+ template<class T> void on_post(T&& func) { std::lock_guard<std::mutex> lock(m_resource_mutex); m_default_resource["POST"] = func; }
+ template<class T> void on_put(std::string regex, T&& func) { std::lock_guard<std::mutex> lock(m_resource_mutex); path2regex::Keys keys; auto reg = path2regex::path_to_regex(regex, keys); m_resource[regex_orderable(reg, regex)]["PUT"] = std::make_tuple(std::move(keys), func); }
+ template<class T> void on_put(T&& func) { std::lock_guard<std::mutex> lock(m_resource_mutex); m_default_resource["PUT"] = func; }
+ template<class T> void on_patch(std::string regex, T&& func) { std::lock_guard<std::mutex> lock(m_resource_mutex); path2regex::Keys keys; auto reg = path2regex::path_to_regex(regex, keys); m_resource[regex_orderable(reg, regex)]["PATCH"] = std::make_tuple(std::move(keys), func); }
+ template<class T> void on_patch(T&& func) { std::lock_guard<std::mutex> lock(m_resource_mutex); m_default_resource["PATCH"] = func; }
+ template<class T> void on_delete(std::string regex, T&& func) { std::lock_guard<std::mutex> lock(m_resource_mutex); path2regex::Keys keys; auto reg = path2regex::path_to_regex(regex, keys); m_resource[regex_orderable(reg, regex)]["DELETE"] = std::make_tuple(std::move(keys), func); }
+ template<class T> void on_delete(T&& func) { std::lock_guard<std::mutex> lock(m_resource_mutex); m_default_resource["DELETE"] = func; }
+
+ void remove_handler(std::string regex)
+ {
+ std::lock_guard<std::mutex> lock(m_resource_mutex);
+ for (auto &it = m_resource.begin(); it != m_resource.end(); ++it)
+ {
+ if (it->first.getstr() == regex)
+ {
+ m_resource.erase(it);
+ break;
+ }
+ }
+ }
+
+ std::function<void(std::shared_ptr<typename ServerBase<socket_type>::Request>, const std::error_code&)> on_error;
+
+ std::function<void(std::shared_ptr<socket_type> socket, std::shared_ptr<typename ServerBase<socket_type>::Request>)> on_upgrade;
+ private:
+ /// Warning: do not add or remove resources after start() is called
+ std::map<regex_orderable, std::map<std::string, std::tuple<path2regex::Keys, http_handler>>> m_resource;
+
+ std::map<std::string, http_handler> m_default_resource;
+
+ std::mutex m_resource_mutex;
+ public:
+ virtual void start() {
+ if(!m_io_context)
+ m_io_context=std::make_shared<asio::io_context>();
+
+ if(m_io_context->stopped())
+ m_io_context.reset();
+
+ asio::ip::tcp::endpoint endpoint;
+ if(m_config.address.size()>0)
+ endpoint=asio::ip::tcp::endpoint(asio::ip::make_address(m_config.address), m_config.port);
+ else
+ endpoint=asio::ip::tcp::endpoint(asio::ip::tcp::v4(), m_config.port);
+
+ if(!acceptor)
+ acceptor= std::make_unique<asio::ip::tcp::acceptor>(*m_io_context);
+ acceptor->open(endpoint.protocol());
+ acceptor->set_option(asio::socket_base::reuse_address(m_config.reuse_address));
+ acceptor->bind(endpoint);
+ acceptor->listen();
+
+ accept();
+
+ if (!m_external_context)
+ m_io_context->run();
+ }
+
+ void stop() const
+ {
+ acceptor->close();
+ if (!m_external_context)
+ m_io_context->stop();
+ }
+
+ ///Use this function if you need to recursively send parts of a longer message
+ void send(const std::shared_ptr<Response> &response, const std::function<void(const std::error_code&)>& callback=nullptr) const {
+ asio::async_write(*response->socket(), response->m_streambuf, [this, response, callback](const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(callback)
+ callback(ec);
+ });
+ }
+
+ void set_io_context(std::shared_ptr<asio::io_context> new_io_context)
+ {
+ m_io_context = new_io_context;
+ m_external_context = true;
+ }
+ protected:
+ std::shared_ptr<asio::io_context> m_io_context;
+ bool m_external_context;
+ std::unique_ptr<asio::ip::tcp::acceptor> acceptor;
+ std::vector<std::thread> threads;
+
+ ServerBase(unsigned short port) : m_config(port), m_external_context(false) {}
+
+ virtual void accept()=0;
+
+ std::shared_ptr<asio::system_timer> get_timeout_timer(const std::shared_ptr<socket_type> &socket, long seconds) {
+ if(seconds==0)
+ return nullptr;
+ auto timer = std::make_shared<asio::system_timer>(*m_io_context);
+ timer->expires_at(std::chrono::system_clock::now() + std::chrono::seconds(seconds));
+ timer->async_wait([socket](const std::error_code& ec){
+ if(!ec) {
+ std::error_code newec = ec;
+ socket->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, newec);
+ socket->lowest_layer().close();
+ }
+ });
+ return timer;
+ }
+
+ void read_request_and_content(const std::shared_ptr<socket_type> &socket) {
+ //Create new streambuf (Request::streambuf) for async_read_until()
+ //shared_ptr is used to pass temporary objects to the asynchronous functions
+ std::shared_ptr<Request> request(new Request(*socket));
+
+ //Set timeout on the following asio::async-read or write function
+ auto timer = get_timeout_timer(socket, m_config.timeout_request);
+
+ asio::async_read_until(*socket, request->streambuf, "\r\n\r\n",
+ [this, socket, request, timer](const std::error_code& ec, size_t bytes_transferred) {
+ if(timer)
+ timer->cancel();
+ if(!ec) {
+ //request->streambuf.size() is not necessarily the same as bytes_transferred, from Boost-docs:
+ //"After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter"
+ //The chosen solution is to extract lines from the stream directly when parsing the header. What is left of the
+ //streambuf (maybe some bytes of the content) is appended to in the async_read-function below (for retrieving content).
+ size_t num_additional_bytes=request->streambuf.size()-bytes_transferred;
+
+ if (!parse_request(request))
+ return;
+
+ //If content, read that as well
+ auto it = request->header.find("Content-Length");
+ if (it != request->header.end()) {
+ unsigned long long content_length;
+ try {
+ content_length = stoull(it->second);
+ }
+ catch (const std::exception &) {
+ if (on_error)
+ on_error(request, std::error_code(EPROTO, std::generic_category()));
+ return;
+ }
+ if (content_length > num_additional_bytes) {
+ //Set timeout on the following asio::async-read or write function
+ auto timer2 = get_timeout_timer(socket, m_config.timeout_content);
+ asio::async_read(*socket, request->streambuf,
+ asio::transfer_exactly(size_t(content_length) - num_additional_bytes),
+ [this, socket, request, timer2]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if (timer2)
+ timer2->cancel();
+ if (!ec)
+ find_resource(socket, request);
+ else if (on_error)
+ on_error(request, ec);
+ });
+ }
+ else {
+ find_resource(socket, request);
+ }
+ }
+ else {
+ find_resource(socket, request);
+ }
+ }
+ else if (on_error)
+ on_error(request, ec);
+ });
+ }
+
+ bool parse_request(const std::shared_ptr<Request> &request) const {
+ std::string line;
+ getline(request->content, line);
+ size_t method_end;
+ if((method_end=line.find(' '))!=std::string::npos) {
+ size_t path_end;
+ if((path_end=line.find(' ', method_end+1))!=std::string::npos) {
+ request->method=line.substr(0, method_end);
+ request->path=line.substr(method_end+1, path_end-method_end-1);
+
+ size_t protocol_end;
+ if((protocol_end=line.find('/', path_end+1))!=std::string::npos) {
+ if(line.compare(path_end+1, protocol_end-path_end-1, "HTTP")!=0)
+ return false;
+ request->http_version=line.substr(protocol_end+1, line.size()-protocol_end-2);
+ }
+ else
+ return false;
+
+ getline(request->content, line);
+ size_t param_end;
+ while((param_end=line.find(':'))!=std::string::npos) {
+ size_t value_start=param_end+1;
+ if((value_start)<line.size()) {
+ if(line[value_start]==' ')
+ value_start++;
+ if(value_start<line.size())
+ request->header.emplace(line.substr(0, param_end), line.substr(value_start, line.size() - value_start - 1));
+ }
+
+ getline(request->content, line);
+ }
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+ return true;
+ }
+
+ void find_resource(const std::shared_ptr<socket_type> &socket, const std::shared_ptr<Request> &request) {
+ std::lock_guard<std::mutex> lock(m_resource_mutex);
+ //Upgrade connection
+ if(on_upgrade) {
+ auto it=request->header.find("Upgrade");
+ if(it!=request->header.end()) {
+ on_upgrade(socket, request);
+ return;
+ }
+ }
+ //Find path- and method-match, and call write_response
+ for(auto& regex_method : m_resource) {
+ auto it = regex_method.second.find(request->method);
+ if (it != regex_method.second.end()) {
+ std::smatch sm_res;
+ if (std::regex_match(request->path, sm_res, regex_method.first)) {
+ request->keys = std::get<0>(it->second);
+ for (size_t i = 0; i < request->keys.size(); i++) {
+ request->params.insert(std::pair<std::string, std::string>(request->keys[i].name, sm_res[i + 1]));
+ }
+ write_response(socket, request, std::get<1>(it->second));
+ return;
+ }
+ }
+ }
+ auto it=m_default_resource.find(request->method);
+ if(it!=m_default_resource.end()) {
+ write_response(socket, request, it->second);
+ }
+ }
+
+ void write_response(const std::shared_ptr<socket_type> &socket, const std::shared_ptr<Request> &request, http_handler& resource_function) {
+ //Set timeout on the following asio::async-read or write function
+ auto timer = get_timeout_timer(socket, m_config.timeout_content);
+
+ auto response=std::shared_ptr<Response>(new Response(socket), [this, request, timer](Response *response_ptr) {
+ auto response=std::shared_ptr<Response>(response_ptr);
+ send(response, [this, response, request, timer](const std::error_code& ec) {
+ if (timer)
+ timer->cancel();
+ if (!ec) {
+ float http_version;
+ try {
+ http_version = stof(request->http_version);
+ }
+ catch (const std::exception &) {
+ if (on_error)
+ on_error(request, std::error_code(EPROTO, std::generic_category()));
+ return;
+ }
+
+ auto range = request->header.equal_range("Connection");
+ case_insensitive_equals check;
+ for (auto it = range.first; it != range.second; ++it) {
+ if (check(it->second, "close"))
+ return;
+ }
+ if (http_version > 1.05)
+ read_request_and_content(response->socket());
+ }
+ else if (on_error)
+ on_error(request, ec);
+ });
+ });
+
+ try {
+ resource_function(response, request);
+ }
+ catch(const std::exception &) {
+ if (on_error)
+ on_error(request, std::error_code(EPROTO, std::generic_category()));
+ }
+ }
+ };
+
+ template<class socket_type>
+ class Server : public ServerBase<socket_type> {
+ public:
+ Server(unsigned short port, size_t num_threads, long timeout_request, long timeout_send_or_receive)
+ : ServerBase<socket_type>(port, num_threads, timeout_request, timeout_send_or_receive)
+ {
+ }
+ };
+
+ using HTTP = asio::ip::tcp::socket;
+
+ template<>
+ class Server<HTTP> : public ServerBase<HTTP> {
+ public:
+ Server() : ServerBase<HTTP>::ServerBase(80) {}
+ protected:
+ void accept() override {
+ //Create new socket for this connection
+ //Shared_ptr is used to pass temporary objects to the asynchronous functions
+ auto socket = std::make_shared<HTTP>(*m_io_context);
+
+ acceptor->async_accept(*socket, [this, socket](const std::error_code& ec){
+ //Immediately start accepting a new connection (if io_context hasn't been stopped)
+ if (ec != asio::error::operation_aborted)
+ accept();
+
+ if(!ec) {
+ asio::ip::tcp::no_delay option(true);
+ socket->set_option(option);
+
+ read_request_and_content(socket);
+ } else if (on_error)
+ on_error(std::shared_ptr<Request>(new Request(*socket)), ec);
+ });
+ }
+ };
+
+ class http_server : public Server<HTTP> {
+ public:
+ http_server() : Server<HTTP>::Server() {}
+ };
+}
+#endif /* SERVER_HTTP_HPP */
diff --git a/src/lib/util/server_https.hpp b/src/lib/util/server_https.hpp
new file mode 100644
index 00000000000..e721cbb3e25
--- /dev/null
+++ b/src/lib/util/server_https.hpp
@@ -0,0 +1,99 @@
+// license:MIT
+// copyright-holders:Ole Christian Eidheim, Miodrag Milanovic
+#ifndef SERVER_HTTPS_HPP
+#define SERVER_HTTPS_HPP
+
+#include "server_http.hpp"
+#include "asio/ssl.hpp"
+#include <openssl/ssl.h>
+#include <algorithm>
+
+namespace webpp {
+ using HTTPS = asio::ssl::stream<asio::ip::tcp::socket>;
+
+ template<>
+ class Server<HTTPS> : public ServerBase<HTTPS> {
+ std::string session_id_context;
+ bool set_session_id_context = false;
+ public:
+ Server(unsigned short port, size_t thread_pool_size, const std::string& cert_file, const std::string& private_key_file,
+ long timeout_request = 5, long timeout_content = 300,
+ const std::string& verify_file = std::string()) :
+ Server(cert_file, private_key_file, verify_file) {
+ m_config.port=port;
+ m_config.thread_pool_size= thread_pool_size;
+ m_config.timeout_request=timeout_request;
+ m_config.timeout_content=timeout_content;
+ }
+
+ Server(const std::string& cert_file, const std::string& private_key_file, const std::string& verify_file = std::string()) :
+ ServerBase<HTTPS>::ServerBase(443), context(asio::ssl::context::tlsv12) {
+
+ context.use_certificate_chain_file(cert_file);
+ context.use_private_key_file(private_key_file, asio::ssl::context::pem);
+
+ if (verify_file.size() > 0) {
+ context.load_verify_file(verify_file);
+ context.set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert |
+ asio::ssl::verify_client_once);
+ set_session_id_context = true;
+ }
+ }
+ void start() override {
+ if (set_session_id_context) {
+ // Creating session_id_context from address:port but reversed due to small SSL_MAX_SSL_SESSION_ID_LENGTH
+ session_id_context = std::to_string(m_config.port) + ':';
+ session_id_context.append(m_config.address.rbegin(), m_config.address.rend());
+ SSL_CTX_set_session_id_context(context.native_handle(), reinterpret_cast<const unsigned char*>(session_id_context.data()),
+ std::min<size_t>(session_id_context.size(), SSL_MAX_SSL_SESSION_ID_LENGTH));
+
+ }
+ ServerBase::start();
+ }
+
+ protected:
+ asio::ssl::context context;
+
+ void accept() override {
+ //Create new socket for this connection
+ //Shared_ptr is used to pass temporary objects to the asynchronous functions
+ auto socket = std::make_shared<HTTPS>(*m_io_context, context);
+
+ acceptor->async_accept((*socket).lowest_layer(), [this, socket](const std::error_code& ec) {
+ //Immediately start accepting a new connection (if io_context hasn't been stopped)
+ if (ec != asio::error::operation_aborted)
+ accept();
+
+
+ if(!ec) {
+ asio::ip::tcp::no_delay option(true);
+ socket->lowest_layer().set_option(option);
+
+ //Set timeout on the following asio::ssl::stream::async_handshake
+ auto timer = get_timeout_timer(socket, m_config.timeout_request);
+ socket->async_handshake(asio::ssl::stream_base::server, [this, socket, timer]
+ (const std::error_code& ec) {
+ if(timer)
+ timer->cancel();
+ if(!ec)
+ read_request_and_content(socket);
+ else if(on_error)
+ on_error(std::shared_ptr<Request>(new Request(*socket)), ec);
+ });
+ }
+ else if(on_error)
+ on_error(std::shared_ptr<Request>(new Request(*socket)), ec);
+ });
+ }
+ };
+
+ class https_server : public Server<HTTPS> {
+ public:
+ explicit https_server(const std::string& cert_file, const std::string& private_key_file, const std::string& verify_file = std::string()) : Server<HTTPS>::Server(cert_file, private_key_file, verify_file) {}
+ };
+
+}
+
+
+#endif /* SERVER_HTTPS_HPP */
+
diff --git a/src/lib/util/server_ws.hpp b/src/lib/util/server_ws.hpp
new file mode 100644
index 00000000000..170dc31ae63
--- /dev/null
+++ b/src/lib/util/server_ws.hpp
@@ -0,0 +1,714 @@
+// license:MIT
+// copyright-holders:Ole Christian Eidheim, Miodrag Milanovic
+#ifndef SERVER_WS_HPP
+#define SERVER_WS_HPP
+#include "path_to_regex.hpp"
+#include "crypto.hpp"
+
+#include "asio.h"
+#include "asio/system_timer.hpp"
+
+#include <unordered_map>
+#include <thread>
+#include <mutex>
+#include <unordered_set>
+#include <list>
+#include <memory>
+#include <atomic>
+#include <iostream>
+#include <map>
+#include <chrono>
+#include <regex>
+
+#ifndef CASE_INSENSITIVE_EQUALS_AND_HASH
+#define CASE_INSENSITIVE_EQUALS_AND_HASH
+class case_insensitive_equals {
+public:
+ bool operator()(const std::string &key1, const std::string &key2) const {
+ return key1.size() == key2.size()
+ && equal(key1.cbegin(), key1.cend(), key2.cbegin(),
+ [](std::string::value_type key1v, std::string::value_type key2v)
+ { return tolower(key1v) == tolower(key2v); });
+ }
+};
+class case_insensitive_hash {
+public:
+ size_t operator()(const std::string &key) const {
+ size_t seed = 0;
+ for (auto &c : key) {
+ std::hash<char> hasher;
+ seed ^= hasher(std::tolower(c)) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ }
+ return seed;
+ }
+};
+#endif
+
+namespace webpp {
+ template <class socket_type>
+ class SocketServer;
+
+ template <class socket_type>
+ class SocketServerBase {
+ public:
+ virtual ~SocketServerBase() {}
+
+ class SendStream : public std::ostream {
+ friend class SocketServerBase<socket_type>;
+
+ asio::streambuf streambuf;
+ public:
+ SendStream(): std::ostream(&streambuf) {}
+ size_t size() const {
+ return streambuf.size();
+ }
+ };
+
+
+ class Connection {
+ friend class SocketServerBase<socket_type>;
+ friend class SocketServer<socket_type>;
+
+ public:
+ explicit Connection(const std::shared_ptr<socket_type> &socket) : remote_endpoint_port(0), socket(socket), strand(socket->get_io_service()), closed(false) { }
+
+ std::string method, path, http_version;
+
+ std::unordered_multimap<std::string, std::string, case_insensitive_hash, case_insensitive_equals> header;
+
+ std::smatch path_match;
+
+ std::string remote_endpoint_address;
+ unsigned short remote_endpoint_port;
+
+ private:
+ explicit Connection(socket_type *socket): remote_endpoint_port(0), socket(socket), strand(socket->get_io_service()), closed(false) { }
+
+ class SendData {
+ public:
+ SendData(const std::shared_ptr<SendStream> &header_stream, const std::shared_ptr<SendStream> &message_stream,
+ const std::function<void(const std::error_code)> &callback) :
+ header_stream(header_stream), message_stream(message_stream), callback(callback) {}
+ std::shared_ptr<SendStream> header_stream;
+ std::shared_ptr<SendStream> message_stream;
+ std::function<void(const std::error_code)> callback;
+ };
+
+ std::shared_ptr<socket_type> socket;
+
+ asio::io_context::strand strand;
+
+ std::list<SendData> send_queue;
+
+ void send_from_queue(const std::shared_ptr<Connection> &connection) {
+ strand.post([this, connection]() {
+ asio::async_write(*socket, send_queue.begin()->header_stream->streambuf,
+ strand.wrap([this, connection](const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(!ec) {
+ asio::async_write(*socket, send_queue.begin()->message_stream->streambuf,
+ strand.wrap([this, connection]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ auto send_queued=send_queue.begin();
+ if(send_queued->callback)
+ send_queued->callback(ec);
+ if(!ec) {
+ send_queue.erase(send_queued);
+ if(send_queue.size()>0)
+ send_from_queue(connection);
+ }
+ else
+ send_queue.clear();
+ }));
+ }
+ else {
+ auto send_queued=send_queue.begin();
+ if(send_queued->callback)
+ send_queued->callback(ec);
+ send_queue.clear();
+ }
+ }));
+ });
+ }
+
+ std::atomic<bool> closed;
+
+ std::unique_ptr<asio::system_timer> timer_idle;
+
+ void read_remote_endpoint_data() {
+ try {
+ remote_endpoint_address=socket->lowest_layer().remote_endpoint().address().to_string();
+ remote_endpoint_port=socket->lowest_layer().remote_endpoint().port();
+ }
+ catch (...) {}
+ }
+ };
+
+ class Message : public std::istream {
+ friend class SocketServerBase<socket_type>;
+
+ public:
+ unsigned char fin_rsv_opcode;
+ size_t size() const {
+ return length;
+ }
+ std::string string() const {
+ std::stringstream ss;
+ ss << rdbuf();
+ return ss.str();
+ }
+ private:
+ Message(): std::istream(&streambuf), fin_rsv_opcode(0), length(0) {}
+
+ size_t length;
+ asio::streambuf streambuf;
+ };
+
+ class Endpoint {
+ friend class SocketServerBase<socket_type>;
+ std::unordered_set<std::shared_ptr<Connection> > connections;
+ std::mutex connections_mutex;
+
+ public:
+ std::function<void(std::shared_ptr<Connection>)> on_open;
+ std::function<void(std::shared_ptr<Connection>, std::shared_ptr<Message>)> on_message;
+ std::function<void(std::shared_ptr<Connection>, int, const std::string&)> on_close;
+ std::function<void(std::shared_ptr<Connection>, const std::error_code&)> on_error;
+
+ std::unordered_set<std::shared_ptr<Connection> > get_connections() {
+ std::lock_guard<std::mutex> lock(connections_mutex);
+ auto copy=connections;
+ return copy;
+ }
+ };
+
+ class Config {
+ friend class SocketServerBase<socket_type>;
+
+ Config(unsigned short port) : port(port) {}
+ public:
+ /// Port number to use. Defaults to 80 for HTTP and 443 for HTTPS.
+ unsigned short port;
+ /// Number of threads that the server will use when start() is called. Defaults to 1 thread.
+ size_t thread_pool_size=1;
+ /// Timeout on request handling. Defaults to 5 seconds.
+ size_t timeout_request=5;
+ /// Idle timeout. Defaults to no timeout.
+ size_t timeout_idle=0;
+ /// IPv4 address in dotted decimal form or IPv6 address in hexadecimal notation.
+ /// If empty, the address will be any address.
+ std::string address;
+ /// Set to false to avoid binding the socket to an address that is already in use. Defaults to true.
+ bool reuse_address=true;
+ };
+ ///Set before calling start().
+ Config config;
+
+ private:
+ class regex_orderable : public std::regex {
+ std::string str;
+ path2regex::Keys keys;
+ public:
+ regex_orderable(const char *regex_cstr) : std::regex(path2regex::path_to_regex(regex_cstr, keys)), str(regex_cstr) {}
+ regex_orderable(const std::string &regex_cstr) : std::regex(path2regex::path_to_regex(regex_cstr, keys)), str(regex_cstr) {}
+ bool operator<(const regex_orderable &rhs) const {
+ return str<rhs.str;
+ }
+ };
+ public:
+ /// Warning: do not add or remove endpoints after start() is called
+ std::map<regex_orderable, Endpoint> endpoint;
+
+ virtual void start() {
+ if(!io_context)
+ io_context=std::make_shared<asio::io_context>();
+
+ if(io_context->stopped())
+ io_context->reset();
+
+ asio::ip::tcp::endpoint endpoint;
+ if(config.address.size()>0)
+ endpoint=asio::ip::tcp::endpoint(asio::ip::address::from_string(config.address), config.port);
+ else
+ endpoint=asio::ip::tcp::endpoint(asio::ip::tcp::v4(), config.port);
+
+ if(!acceptor)
+ acceptor= std::make_unique<asio::ip::tcp::acceptor>(*io_context);
+ acceptor->open(endpoint.protocol());
+ acceptor->set_option(asio::socket_base::reuse_address(config.reuse_address));
+ acceptor->bind(endpoint);
+ acceptor->listen();
+
+ accept();
+
+ io_context->run();
+ }
+
+ void stop() {
+ acceptor->close();
+ io_context->stop();
+
+ for(auto& p: endpoint)
+ p.second.connections.clear();
+ }
+
+ ///fin_rsv_opcode: 129=one fragment, text, 130=one fragment, binary, 136=close connection.
+ ///See http://tools.ietf.org/html/rfc6455#section-5.2 for more information
+ void send(const std::shared_ptr<Connection> &connection, const std::shared_ptr<SendStream> &message_stream,
+ const std::function<void(const std::error_code&)>& callback=nullptr,
+ unsigned char fin_rsv_opcode=129) const {
+ if(fin_rsv_opcode!=136)
+ timer_idle_reset(connection);
+
+ auto header_stream = std::make_shared<SendStream>();
+
+ size_t length=message_stream->size();
+
+ header_stream->put(fin_rsv_opcode);
+ //unmasked (first length byte<128)
+ if(length>=126) {
+ int num_bytes;
+ if(length>0xffff) {
+ num_bytes=8;
+ header_stream->put(127);
+ }
+ else {
+ num_bytes=2;
+ header_stream->put(126);
+ }
+
+ for(int c=num_bytes-1;c>=0;c--) {
+ header_stream->put((static_cast<unsigned long long>(length) >> (8 * c)) % 256);
+ }
+ }
+ else
+ header_stream->put(static_cast<unsigned char>(length));
+
+ connection->strand.post([this, connection, header_stream, message_stream, callback]() {
+ connection->send_queue.emplace_back(header_stream, message_stream, callback);
+ if(connection->send_queue.size()==1)
+ connection->send_from_queue(connection);
+ });
+ }
+
+ void send_close(const std::shared_ptr<Connection> &connection, int status, const std::string& reason="",
+ const std::function<void(const std::error_code&)>& callback=nullptr) const {
+ //Send close only once (in case close is initiated by server)
+ if(connection->closed)
+ return;
+ connection->closed=true;
+
+ auto send_stream=std::make_shared<SendStream>();
+
+ send_stream->put(status>>8);
+ send_stream->put(status%256);
+
+ *send_stream << reason;
+
+ //fin_rsv_opcode=136: message close
+ send(connection, send_stream, callback, 136);
+ }
+
+ std::unordered_set<std::shared_ptr<Connection> > get_connections() {
+ std::unordered_set<std::shared_ptr<Connection> > all_connections;
+ for(auto& e: endpoint) {
+ std::lock_guard<std::mutex> lock(e.second.connections_mutex);
+ all_connections.insert(e.second.connections.begin(), e.second.connections.end());
+ }
+ return all_connections;
+ }
+
+ /**
+ * Upgrades a request, from for instance Simple-Web-Server, to a WebSocket connection.
+ * The parameters are moved to the Connection object.
+ * See also Server::on_upgrade in the Simple-Web-Server project.
+ * The socket's io_service is used, thus running start() is not needed.
+ *
+ * Example use:
+ * server.on_upgrade=[&socket_server] (auto socket, auto request) {
+ * auto connection=std::make_shared<SimpleWeb::SocketServer<SimpleWeb::WS>::Connection>(socket);
+ * connection->method=std::move(request->method);
+ * connection->path=std::move(request->path);
+ * connection->http_version=std::move(request->http_version);
+ * connection->header=std::move(request->header);
+ * connection->remote_endpoint_address=std::move(request->remote_endpoint_address);
+ * connection->remote_endpoint_port=request->remote_endpoint_port;
+ * socket_server.upgrade(connection);
+ * }
+ */
+ void upgrade(const std::shared_ptr<Connection> &connection) {
+ auto read_buffer=std::make_shared<asio::streambuf>();
+ write_handshake(connection, read_buffer);
+ }
+
+ /// If you have your own asio::io_context, store its pointer here before running start().
+ /// You might also want to set config.num_threads to 0.
+ std::shared_ptr<asio::io_context> io_context;
+ protected:
+ const std::string ws_magic_string="258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
+ std::unique_ptr<asio::ip::tcp::acceptor> acceptor;
+
+ std::vector<std::thread> threads;
+
+ SocketServerBase(unsigned short port) :
+ config(port) {}
+
+ virtual void accept()=0;
+
+ std::shared_ptr<asio::system_timer> get_timeout_timer(const std::shared_ptr<Connection> &connection, size_t seconds) {
+ if (seconds == 0)
+ return nullptr;
+ auto timer = std::make_shared<asio::system_timer>(connection->socket->get_io_service());
+ timer->expires_at(std::chrono::system_clock::now() + std::chrono::seconds(static_cast<long>(seconds)));
+ timer->async_wait([connection](const std::error_code& ec){
+ if(!ec) {
+ connection->socket->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both);
+ connection->socket->lowest_layer().close();
+ }
+ });
+ return timer;
+ }
+
+ void read_handshake(const std::shared_ptr<Connection> &connection) {
+ connection->read_remote_endpoint_data();
+
+ //Create new read_buffer for async_read_until()
+ //Shared_ptr is used to pass temporary objects to the asynchronous functions
+ auto read_buffer = std::make_shared<asio::streambuf>();
+
+ //Set timeout on the following asio::async-read or write function
+ auto timer = get_timeout_timer(connection, config.timeout_request);
+
+ asio::async_read_until(*connection->socket, *read_buffer, "\r\n\r\n",
+ [this, connection, read_buffer, timer]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(timer)
+ timer->cancel();
+ if(!ec) {
+ //Convert to istream to extract string-lines
+ std::istream stream(read_buffer.get());
+
+ parse_handshake(connection, stream);
+
+ write_handshake(connection, read_buffer);
+ }
+ });
+ }
+
+ void parse_handshake(const std::shared_ptr<Connection> &connection, std::istream& stream) const {
+ std::string line;
+ getline(stream, line);
+ size_t method_end;
+ if((method_end=line.find(' '))!=std::string::npos) {
+ size_t path_end;
+ if((path_end=line.find(' ', method_end+1))!=std::string::npos) {
+ connection->method=line.substr(0, method_end);
+ connection->path=line.substr(method_end+1, path_end-method_end-1);
+ if((path_end+6)<line.size())
+ connection->http_version=line.substr(path_end+6, line.size()-(path_end+6)-1);
+ else
+ connection->http_version="1.1";
+
+ getline(stream, line);
+ size_t param_end;
+ while((param_end=line.find(':'))!=std::string::npos) {
+ size_t value_start=param_end+1;
+ if((value_start)<line.size()) {
+ if(line[value_start]==' ')
+ value_start++;
+ if(value_start<line.size())
+ connection->header.emplace(line.substr(0, param_end), line.substr(value_start, line.size()-value_start-1));
+ }
+
+ getline(stream, line);
+ }
+ }
+ }
+ }
+
+ void write_handshake(const std::shared_ptr<Connection> &connection, const std::shared_ptr<asio::streambuf> &read_buffer) {
+ //Find path- and method-match, and generate response
+ for (auto &regex_endpoint : endpoint) {
+ std::smatch path_match;
+ if(std::regex_match(connection->path, path_match, regex_endpoint.first)) {
+ auto write_buffer = std::make_shared<asio::streambuf>();
+ std::ostream handshake(write_buffer.get());
+
+ if(generate_handshake(connection, handshake)) {
+ connection->path_match=std::move(path_match);
+ //Capture write_buffer in lambda so it is not destroyed before async_write is finished
+ asio::async_write(*connection->socket, *write_buffer,
+ [this, connection, write_buffer, read_buffer, &regex_endpoint]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(!ec) {
+ connection_open(connection, regex_endpoint.second);
+ read_message(connection, read_buffer, regex_endpoint.second);
+ }
+ else
+ connection_error(connection, regex_endpoint.second, ec);
+ });
+ }
+ return;
+ }
+ }
+ }
+
+ bool generate_handshake(const std::shared_ptr<Connection> &connection, std::ostream& handshake) const {
+ auto header_it = connection->header.find("Sec-WebSocket-Key");
+ if (header_it == connection->header.end())
+ return false;
+
+ auto sha1=sha1_encode(header_it->second + ws_magic_string);
+
+ handshake << "HTTP/1.1 101 Web Socket Protocol Handshake\r\n";
+ handshake << "Upgrade: websocket\r\n";
+ handshake << "Connection: Upgrade\r\n";
+ handshake << "Sec-WebSocket-Accept: " << base64_encode(sha1) << "\r\n";
+ handshake << "\r\n";
+
+ return true;
+ }
+
+ void read_message(const std::shared_ptr<Connection> &connection,
+ const std::shared_ptr<asio::streambuf> &read_buffer, Endpoint& endpoint) const {
+ asio::async_read(*connection->socket, *read_buffer, asio::transfer_exactly(2),
+ [this, connection, read_buffer, &endpoint]
+ (const std::error_code& ec, size_t bytes_transferred) {
+ if(!ec) {
+ if(bytes_transferred==0) { //TODO: why does this happen sometimes?
+ read_message(connection, read_buffer, endpoint);
+ return;
+ }
+ std::istream stream(read_buffer.get());
+
+ std::vector<unsigned char> first_bytes;
+ first_bytes.resize(2);
+ stream.read(reinterpret_cast<char*>(&first_bytes[0]), 2);
+
+ unsigned char fin_rsv_opcode=first_bytes[0];
+
+ //Close connection if unmasked message from client (protocol error)
+ if(first_bytes[1]<128) {
+ const std::string reason("message from client not masked");
+ send_close(connection, 1002, reason, [this, connection](const std::error_code& /*ec*/) {});
+ connection_close(connection, endpoint, 1002, reason);
+ return;
+ }
+
+ size_t length=(first_bytes[1]&127);
+
+ if(length==126) {
+ //2 next bytes is the size of content
+ asio::async_read(*connection->socket, *read_buffer, asio::transfer_exactly(2),
+ [this, connection, read_buffer, &endpoint, fin_rsv_opcode]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(!ec) {
+ std::istream stream(read_buffer.get());
+
+ std::vector<unsigned char> length_bytes;
+ length_bytes.resize(2);
+ stream.read(reinterpret_cast<char*>(&length_bytes[0]), 2);
+
+ size_t length=0;
+ int num_bytes=2;
+ for(int c=0;c<num_bytes;c++)
+ length+=length_bytes[c]<<(8*(num_bytes-1-c));
+
+ read_message_content(connection, read_buffer, length, endpoint, fin_rsv_opcode);
+ }
+ else
+ connection_error(connection, endpoint, ec);
+ });
+ }
+ else if(length==127) {
+ //8 next bytes is the size of content
+ asio::async_read(*connection->socket, *read_buffer, asio::transfer_exactly(8),
+ [this, connection, read_buffer, &endpoint, fin_rsv_opcode]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(!ec) {
+ std::istream stream(read_buffer.get());
+
+ std::vector<unsigned char> length_bytes;
+ length_bytes.resize(8);
+ stream.read(reinterpret_cast<char*>(&length_bytes[0]), 8);
+
+ size_t length=0;
+ int num_bytes=8;
+ for(int c=0;c<num_bytes;c++)
+ length+=length_bytes[c]<<(8*(num_bytes-1-c));
+
+ read_message_content(connection, read_buffer, length, endpoint, fin_rsv_opcode);
+ }
+ else
+ connection_error(connection, endpoint, ec);
+ });
+ }
+ else
+ read_message_content(connection, read_buffer, length, endpoint, fin_rsv_opcode);
+ }
+ else
+ connection_error(connection, endpoint, ec);
+ });
+ }
+
+ void read_message_content(const std::shared_ptr<Connection> &connection, const std::shared_ptr<asio::streambuf> &read_buffer,
+ size_t length, Endpoint& endpoint, unsigned char fin_rsv_opcode) const {
+ asio::async_read(*connection->socket, *read_buffer, asio::transfer_exactly(4+length),
+ [this, connection, read_buffer, length, &endpoint, fin_rsv_opcode]
+ (const std::error_code& ec, size_t /*bytes_transferred*/) {
+ if(!ec) {
+ std::istream raw_message_data(read_buffer.get());
+
+ //Read mask
+ std::vector<unsigned char> mask;
+ mask.resize(4);
+ raw_message_data.read(reinterpret_cast<char*>(&mask[0]), 4);
+
+ std::shared_ptr<Message> message(new Message());
+ message->length=length;
+ message->fin_rsv_opcode=fin_rsv_opcode;
+
+ std::ostream message_data_out_stream(&message->streambuf);
+ for(size_t c=0;c<length;c++) {
+ message_data_out_stream.put(raw_message_data.get()^mask[c%4]);
+ }
+
+ //If connection close
+ if((fin_rsv_opcode&0x0f)==8) {
+ int status=0;
+ if(length>=2) {
+ unsigned char byte1=message->get();
+ unsigned char byte2=message->get();
+ status=(byte1<<8)+byte2;
+ }
+
+ auto reason=message->string();
+ send_close(connection, status, reason, [this, connection](const std::error_code& /*ec*/) {});
+ connection_close(connection, endpoint, status, reason);
+ return;
+ }
+ else {
+ //If ping
+ if((fin_rsv_opcode&0x0f)==9) {
+ //send pong
+ auto empty_send_stream=std::make_shared<SendStream>();
+ send(connection, empty_send_stream, nullptr, fin_rsv_opcode+1);
+ }
+ else if(endpoint.on_message) {
+ timer_idle_reset(connection);
+ endpoint.on_message(connection, message);
+ }
+
+ //Next message
+ read_message(connection, read_buffer, endpoint);
+ }
+ }
+ else
+ connection_error(connection, endpoint, ec);
+ });
+ }
+
+ void connection_open(const std::shared_ptr<Connection> &connection, Endpoint& endpoint) {
+ timer_idle_init(connection);
+
+ {
+ std::lock_guard<std::mutex> lock(endpoint.connections_mutex);
+ endpoint.connections.insert(connection);
+ }
+
+ if(endpoint.on_open)
+ endpoint.on_open(connection);
+ }
+
+ void connection_close(const std::shared_ptr<Connection> &connection, Endpoint& endpoint, int status, const std::string& reason) const {
+ timer_idle_cancel(connection);
+
+ {
+ std::lock_guard<std::mutex> lock(endpoint.connections_mutex);
+ endpoint.connections.erase(connection);
+ }
+
+ if(endpoint.on_close)
+ endpoint.on_close(connection, status, reason);
+ }
+
+ void connection_error(const std::shared_ptr<Connection> &connection, Endpoint& endpoint, const std::error_code& ec) const {
+ timer_idle_cancel(connection);
+
+ {
+ std::lock_guard<std::mutex> lock(endpoint.connections_mutex);
+ endpoint.connections.erase(connection);
+ }
+
+ if(endpoint.on_error) {
+ std::error_code ec_tmp=ec;
+ endpoint.on_error(connection, ec_tmp);
+ }
+ }
+
+ void timer_idle_init(const std::shared_ptr<Connection> &connection) {
+ if(config.timeout_idle>0) {
+ connection->timer_idle= std::make_unique<asio::system_timer>(connection->socket->get_io_service());
+ connection->timer_idle->expires_from_now(std::chrono::seconds(static_cast<unsigned long>(config.timeout_idle)));
+ timer_idle_expired_function(connection);
+ }
+ }
+ void timer_idle_reset(const std::shared_ptr<Connection> &connection) const {
+ if(config.timeout_idle>0 && connection->timer_idle->expires_from_now(std::chrono::seconds(static_cast<unsigned long>(config.timeout_idle)))>0)
+ timer_idle_expired_function(connection);
+ }
+ void timer_idle_cancel(const std::shared_ptr<Connection> &connection) const {
+ if(config.timeout_idle>0)
+ connection->timer_idle->cancel();
+ }
+
+ void timer_idle_expired_function(const std::shared_ptr<Connection> &connection) const {
+ connection->timer_idle->async_wait([this, connection](const std::error_code& ec){
+ if(!ec)
+ send_close(connection, 1000, "idle timeout"); //1000=normal closure
+ });
+ }
+ };
+
+ template<class socket_type>
+ class SocketServer : public SocketServerBase<socket_type> {
+ public:
+ SocketServer(unsigned short port, size_t timeout_request, size_t timeout_idle)
+ : SocketServerBase<socket_type>(port, timeout_request, timeout_idle)
+ {
+ }
+ };
+
+ using WS = asio::ip::tcp::socket;
+
+ template<>
+ class SocketServer<WS> : public SocketServerBase<WS> {
+ public:
+ SocketServer() : SocketServerBase<WS>(80) {}
+ protected:
+ void accept() override {
+ //Create new socket for this connection (stored in Connection::socket)
+ //Shared_ptr is used to pass temporary objects to the asynchronous functions
+ std::shared_ptr<Connection> connection(new Connection(new WS(*io_context)));
+
+ acceptor->async_accept(*connection->socket, [this, connection](const std::error_code& ec) {
+ //Immediately start accepting a new connection (if io_context hasn't been stopped)
+ if (ec != asio::error::operation_aborted)
+ accept();
+
+ if(!ec) {
+ asio::ip::tcp::no_delay option(true);
+ connection->socket->set_option(option);
+
+ read_handshake(connection);
+ }
+ });
+ }
+ };
+
+ class ws_server : public SocketServer<WS> {
+ public:
+ ws_server() : SocketServer<WS>::SocketServer() {}
+ };
+}
+#endif /* SERVER_WS_HPP */
diff --git a/src/lib/util/server_wss.hpp b/src/lib/util/server_wss.hpp
new file mode 100644
index 00000000000..ecf46fb1524
--- /dev/null
+++ b/src/lib/util/server_wss.hpp
@@ -0,0 +1,82 @@
+// license:MIT
+// copyright-holders:Ole Christian Eidheim, Miodrag Milanovic
+#ifndef SERVER_WSS_HPP
+#define SERVER_WSS_HPP
+
+#include "server_ws.hpp"
+#include "asio/ssl.hpp"
+#include <openssl/ssl.h>
+#include <algorithm>
+
+namespace webpp {
+ using WSS = asio::ssl::stream<asio::ip::tcp::socket>;
+
+ template<>
+ class SocketServer<WSS> : public SocketServerBase<WSS> {
+ std::string session_id_context;
+ bool set_session_id_context = false;
+ public:
+ SocketServer(const std::string& cert_file, const std::string& private_key_file,
+ const std::string& verify_file=std::string()) : SocketServerBase<WSS>(443), context(asio::ssl::context::tlsv12) {
+
+ context.use_certificate_chain_file(cert_file);
+ context.use_private_key_file(private_key_file, asio::ssl::context::pem);
+
+ if (verify_file.size() > 0) {
+ context.load_verify_file(verify_file);
+ context.set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert |
+ asio::ssl::verify_client_once);
+ set_session_id_context=true;
+ }
+ }
+
+ void start() override {
+ if(set_session_id_context) {
+ // Creating session_id_context from address:port but reversed due to small SSL_MAX_SSL_SESSION_ID_LENGTH
+ session_id_context=std::to_string(config.port)+':';
+ session_id_context.append(config.address.rbegin(), config.address.rend());
+ SSL_CTX_set_session_id_context(context.native_handle(), reinterpret_cast<const unsigned char*>(session_id_context.data()),
+ std::min<size_t>(session_id_context.size(), SSL_MAX_SSL_SESSION_ID_LENGTH));
+ }
+ SocketServerBase::start();
+ }
+ protected:
+ asio::ssl::context context;
+
+ void accept() override {
+ //Create new socket for this connection (stored in Connection::socket)
+ //Shared_ptr is used to pass temporary objects to the asynchronous functions
+ std::shared_ptr<Connection> connection(new Connection(new WSS(*io_context, context)));
+
+ acceptor->async_accept(connection->socket->lowest_layer(), [this, connection](const std::error_code& ec) {
+ //Immediately start accepting a new connection (if io_context hasn't been stopped)
+ if (ec != asio::error::operation_aborted)
+ accept();
+
+ if(!ec) {
+ asio::ip::tcp::no_delay option(true);
+ connection->socket->lowest_layer().set_option(option);
+
+ //Set timeout on the following asio::ssl::stream::async_handshake
+ auto timer = get_timeout_timer(connection, config.timeout_request);
+ connection->socket->async_handshake(asio::ssl::stream_base::server,
+ [this, connection, timer](const std::error_code& ec) {
+ if(timer)
+ timer->cancel();
+ if(!ec)
+ read_handshake(connection);
+ });
+ }
+ });
+ }
+ };
+
+ class wss_server : public SocketServer<WSS> {
+ public:
+ wss_server(const std::string& cert_file, const std::string& private_key_file,const std::string& verify_file = std::string()) : SocketServer<WSS>::SocketServer(cert_file, private_key_file, verify_file) {}
+ };
+}
+
+
+#endif /* SERVER_WSS_HPP */
+
diff --git a/src/lib/util/sha1.hpp b/src/lib/util/sha1.hpp
new file mode 100644
index 00000000000..7befbd326f0
--- /dev/null
+++ b/src/lib/util/sha1.hpp
@@ -0,0 +1,181 @@
+// license:BSD-3-Clause
+// copyright-holders:Micael Hildenborg
+/*
+ Copyright (c) 2011, Micael Hildenborg
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Micael Hildenborg nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SHA1_DEFINED
+#define SHA1_DEFINED
+
+namespace sha1 {
+
+namespace { // local
+
+// Rotate an integer value to left.
+inline unsigned int rol(unsigned int value, unsigned int steps) {
+ return ((value << steps) | (value >> (32 - steps)));
+}
+
+// Sets the first 16 integers in the buffert to zero.
+// Used for clearing the W buffert.
+inline void clearWBuffert(unsigned int * buffert)
+{
+ for (int pos = 16; --pos >= 0;)
+ {
+ buffert[pos] = 0;
+ }
+}
+
+inline void innerHash(unsigned int * result, unsigned int * w)
+{
+ unsigned int a = result[0];
+ unsigned int b = result[1];
+ unsigned int c = result[2];
+ unsigned int d = result[3];
+ unsigned int e = result[4];
+
+ int round = 0;
+
+ #define sha1macro(func,val) \
+ { \
+ const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
+ e = d; \
+ d = c; \
+ c = rol(b, 30); \
+ b = a; \
+ a = t; \
+ }
+
+ while (round < 16)
+ {
+ sha1macro((b & c) | (~b & d), 0x5a827999)
+ ++round;
+ }
+ while (round < 20)
+ {
+ w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
+ sha1macro((b & c) | (~b & d), 0x5a827999)
+ ++round;
+ }
+ while (round < 40)
+ {
+ w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
+ sha1macro(b ^ c ^ d, 0x6ed9eba1)
+ ++round;
+ }
+ while (round < 60)
+ {
+ w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
+ sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
+ ++round;
+ }
+ while (round < 80)
+ {
+ w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
+ sha1macro(b ^ c ^ d, 0xca62c1d6)
+ ++round;
+ }
+
+ #undef sha1macro
+
+ result[0] += a;
+ result[1] += b;
+ result[2] += c;
+ result[3] += d;
+ result[4] += e;
+}
+
+} // namespace
+
+/// Calculate a SHA1 hash
+/**
+ * @param src points to any kind of data to be hashed.
+ * @param bytelength the number of bytes to hash from the src pointer.
+ * @param hash should point to a buffer of at least 20 bytes of size for storing
+ * the sha1 result in.
+ */
+inline void calc(void const * src, size_t bytelength, unsigned char * hash) {
+ // Init the result array.
+ unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe,
+ 0x10325476, 0xc3d2e1f0 };
+
+ // Cast the void src pointer to be the byte array we can work with.
+ unsigned char const * sarray = static_cast<unsigned char const *>(src);
+
+ // The reusable round buffer
+ unsigned int w[80];
+
+ // Loop through all complete 64byte blocks.
+
+ size_t endCurrentBlock;
+ size_t currentBlock = 0;
+
+ if (bytelength >= 64) {
+ size_t const endOfFullBlocks = bytelength - 64;
+
+ while (currentBlock <= endOfFullBlocks) {
+ endCurrentBlock = currentBlock + 64;
+
+ // Init the round buffer with the 64 byte block data.
+ for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
+ {
+ // This line will swap endian on big endian and keep endian on
+ // little endian.
+ w[roundPos++] = static_cast<unsigned int>(sarray[currentBlock + 3])
+ | (static_cast<unsigned int>(sarray[currentBlock + 2]) << 8)
+ | (static_cast<unsigned int>(sarray[currentBlock + 1]) << 16)
+ | (static_cast<unsigned int>(sarray[currentBlock]) << 24);
+ }
+ innerHash(result, w);
+ }
+ }
+
+ // Handle the last and not full 64 byte block if existing.
+ endCurrentBlock = bytelength - currentBlock;
+ clearWBuffert(w);
+ size_t lastBlockBytes = 0;
+ for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes) {
+ w[lastBlockBytes >> 2] |= static_cast<unsigned int>(sarray[lastBlockBytes + currentBlock]) << ((3 - (lastBlockBytes & 3)) << 3);
+ }
+
+ w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3);
+ if (endCurrentBlock >= 56) {
+ innerHash(result, w);
+ clearWBuffert(w);
+ }
+ w[15] = bytelength << 3;
+ innerHash(result, w);
+
+ // Store hash in result pointer, and make sure we get in in the correct
+ // order on both endian models.
+ for (int hashByte = 20; --hashByte >= 0;) {
+ hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
+ }
+}
+
+} // namespace sha1
+
+#endif // SHA1_DEFINED
diff --git a/src/mame/arcade.flt b/src/mame/arcade.flt
index 5fdab2a318f..d1a207b97e0 100644
--- a/src/mame/arcade.flt
+++ b/src/mame/arcade.flt
@@ -479,6 +479,7 @@ gyruss.cpp
halleys.cpp
hanaawas.cpp
hankin.cpp
+hapyfish.cpp
harddriv.cpp
hazelgr.cpp
hcastle.cpp
diff --git a/src/mame/drivers/aa310.cpp b/src/mame/drivers/aa310.cpp
index 6a3aa2f042f..f62ebc51a4b 100644
--- a/src/mame/drivers/aa310.cpp
+++ b/src/mame/drivers/aa310.cpp
@@ -38,7 +38,6 @@
* Then reboot / reset the machine, and use cat to (attempt) to load a floppy contents.
*
* TODO:
- * - Make floppies to work;
* - RISC OS Alarm app crash the whole OS
* - RISC OS Draw app uses unimplemented copro instructions
*
@@ -125,9 +124,7 @@ protected:
WRITE_LINE_MEMBER(aa310_state::aa310_wd177x_intrq_w)
{
if (state)
- {
archimedes_request_fiq(ARCHIMEDES_FIQ_FLOPPY);
- }
else
archimedes_clear_fiq(ARCHIMEDES_FIQ_FLOPPY);
}
@@ -135,9 +132,7 @@ WRITE_LINE_MEMBER(aa310_state::aa310_wd177x_intrq_w)
WRITE_LINE_MEMBER(aa310_state::aa310_wd177x_drq_w)
{
if (state)
- {
archimedes_request_fiq(ARCHIMEDES_FIQ_FLOPPY_DRQ);
- }
else
archimedes_clear_fiq(ARCHIMEDES_FIQ_FLOPPY_DRQ);
}
@@ -352,12 +347,6 @@ static INPUT_PORTS_START( aa310 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_4WAY
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_4WAY
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_4WAY
-
- PORT_START("tape")/* tape control */
- PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("TAPE STOP") PORT_CODE(KEYCODE_F5)
- PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("TAPE PLAY") PORT_CODE(KEYCODE_F6)
- PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("TAPE REW") PORT_CODE(KEYCODE_F7)
- PORT_BIT (0xf8, 0x80, IPT_UNUSED)
INPUT_PORTS_END
FLOPPY_FORMATS_MEMBER( aa310_state::floppy_formats )
@@ -415,7 +404,7 @@ static MACHINE_CONFIG_START( aa310, aa310_state )
MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(aa310_state, aa310_wd177x_drq_w))
MCFG_FLOPPY_DRIVE_ADD("fdc:0", aa310_floppies, "35dd", aa310_state::floppy_formats)
MCFG_FLOPPY_DRIVE_SOUND(true)
- MCFG_FLOPPY_DRIVE_ADD("fdc:1", aa310_floppies, "35dd", aa310_state::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:1", aa310_floppies, nullptr, aa310_state::floppy_formats) // rarely had 2nd FDD installed, space was used for HDD
MCFG_FLOPPY_DRIVE_SOUND(true)
MCFG_SOFTWARE_LIST_ADD("flop_list", "archimedes")
@@ -521,6 +510,10 @@ static MACHINE_CONFIG_DERIVED( aa4, aa5000 )
MCFG_CPU_MODIFY("maincpu") // ARM3
MCFG_CPU_CLOCK(XTAL_24MHz)
+ /* video hardware */
+ MCFG_SCREEN_MODIFY("screen")
+ MCFG_SCREEN_TYPE(LCD)
+
/* 765 FDC */
/* 60MB HDD */
@@ -586,6 +579,11 @@ ROM_START( aa305 )
ROMX_LOAD( "0296,044-02.ic27", 0x180000, 0x80000, CRC(707b0c6c) SHA1(345199a33fed23996374b9db8170a52ab63f0380), ROM_BIOS(7) )
ROM_SYSTEM_BIOS( 7, "319", "RISC OS 3.19 (09 Jun 1993)" ) /* Parts 0296,241-01, 0296,242-01, 0296,243-01, 0296,244-01, */
ROMX_LOAD( "riscos319.bin", 0x000000, 0x200000, CRC(00c7a3d3) SHA1(be7a8cba5d6c6c0e1c4838712524056cf4b8c8cb), ROM_BIOS(8) )
+ ROM_SYSTEM_BIOS( 8, "test", "Diagnostic Test ROMs" ) /* Usage described in Archimedes 300 Series Service Manual */
+ ROMX_LOAD( "0276,146-01.ic24", 0x000000, 0x10000, CRC(9c45283c) SHA1(9eb5bd7ad0958f194a3416d79d7e01e4c45741e1), ROM_BIOS(9) | ROM_SKIP(3) )
+ ROMX_LOAD( "0276,147-01.ic25", 0x000001, 0x10000, CRC(ad94e17f) SHA1(1c8e39c69d4ae1b674e0f732aaa62a4403998f41), ROM_BIOS(9) | ROM_SKIP(3) )
+ ROMX_LOAD( "0276,148-01.ic26", 0x000002, 0x10000, CRC(1ab02f2d) SHA1(dd7d216967524e64d1a03076a6081461ec8528c3), ROM_BIOS(9) | ROM_SKIP(3) )
+ ROMX_LOAD( "0276,149-01.ic27", 0x000003, 0x10000, CRC(5fd6a406) SHA1(790af8a4c74d0f6714d528f7502443ce5898a618), ROM_BIOS(9) | ROM_SKIP(3) )
ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
ROM_REGION( 0x400000, "extension", ROMREGION_ERASE00 )
@@ -710,7 +708,7 @@ ROM_END
COMP( 1987, aa305, aa310, 0, aa305, aa310, aa310_state, aa310, "Acorn", "Archimedes 305", MACHINE_NOT_WORKING)
COMP( 1987, aa310, 0, 0, aa310, aa310, aa310_state, aa310, "Acorn", "Archimedes 310", MACHINE_NOT_WORKING)
COMP( 1987, aa440, aa310, 0, aa440, aa310, aa310_state, aa310, "Acorn", "Archimedes 440", MACHINE_NOT_WORKING)
-COMP( 1989, aa3000, aa310, 0, aa3000, aa310, aa310_state, aa310, "Acorn", "Archimedes 3000", MACHINE_NOT_WORKING)
+COMP( 1989, aa3000, aa310, 0, aa3000, aa310, aa310_state, aa310, "Acorn", "BBC A3000", MACHINE_NOT_WORKING)
COMP( 1989, aa4101, aa310, 0, aa4101, aa310, aa310_state, aa310, "Acorn", "Archimedes 410/1", MACHINE_NOT_WORKING)
COMP( 1989, aa4201, aa310, 0, aa4201, aa310, aa310_state, aa310, "Acorn", "Archimedes 420/1", MACHINE_NOT_WORKING)
COMP( 1989, aa4401, aa310, 0, aa4401, aa310, aa310_state, aa310, "Acorn", "Archimedes 440/1", MACHINE_NOT_WORKING)
diff --git a/src/mame/drivers/alpha68k.cpp b/src/mame/drivers/alpha68k.cpp
index 18ab41042a8..df37a9da3f3 100644
--- a/src/mame/drivers/alpha68k.cpp
+++ b/src/mame/drivers/alpha68k.cpp
@@ -1304,10 +1304,10 @@ INPUT_PORTS_END
static INPUT_PORTS_START( skyadvnt )
PORT_START("IN0")
- ALPHA68K_PLAYER_INPUT_LSB( 1, IPT_UNKNOWN, IPT_START1, IP_ACTIVE_LOW )
+ ALPHA68K_PLAYER_INPUT_LSB( 1, IPT_BUTTON3, IPT_START1, IP_ACTIVE_LOW )
PORT_START("IN1")
- ALPHA68K_PLAYER_INPUT_LSB( 2, IPT_UNKNOWN, IPT_START2, IP_ACTIVE_LOW )
+ ALPHA68K_PLAYER_INPUT_LSB( 2, IPT_BUTTON3, IPT_START2, IP_ACTIVE_LOW )
ALPHA68K_MCU
diff --git a/src/mame/drivers/ashnojoe.cpp b/src/mame/drivers/ashnojoe.cpp
index 74328538f48..3bab957d1fc 100644
--- a/src/mame/drivers/ashnojoe.cpp
+++ b/src/mame/drivers/ashnojoe.cpp
@@ -87,15 +87,6 @@ READ16_MEMBER(ashnojoe_state::fake_4a00a_r)
return 0;
}
-WRITE16_MEMBER(ashnojoe_state::ashnojoe_soundlatch_w)
-{
- if (ACCESSING_BITS_0_7)
- {
- m_soundlatch_status = 1;
- m_soundlatch->write(space, 0, data & 0xff);
- }
-}
-
static ADDRESS_MAP_START( ashnojoe_map, AS_PROGRAM, 16, ashnojoe_state )
AM_RANGE(0x000000, 0x01ffff) AM_ROM
AM_RANGE(0x040000, 0x041fff) AM_RAM_WRITE(ashnojoe_tileram3_w) AM_SHARE("tileram_3")
@@ -110,7 +101,7 @@ static ADDRESS_MAP_START( ashnojoe_map, AS_PROGRAM, 16, ashnojoe_state )
AM_RANGE(0x04a002, 0x04a003) AM_READ_PORT("P2")
AM_RANGE(0x04a004, 0x04a005) AM_READ_PORT("DSW")
AM_RANGE(0x04a006, 0x04a007) AM_WRITEONLY AM_SHARE("tilemap_reg")
- AM_RANGE(0x04a008, 0x04a009) AM_WRITE(ashnojoe_soundlatch_w)
+ AM_RANGE(0x04a008, 0x04a009) AM_DEVWRITE8("soundlatch", generic_latch_8_device, write, 0x00ff)
AM_RANGE(0x04a00a, 0x04a00b) AM_READ(fake_4a00a_r) // ??
AM_RANGE(0x04a010, 0x04a019) AM_WRITE(joe_tilemaps_xscroll_w)
AM_RANGE(0x04a020, 0x04a029) AM_WRITE(joe_tilemaps_yscroll_w)
@@ -124,15 +115,9 @@ WRITE8_MEMBER(ashnojoe_state::adpcm_w)
m_adpcm_byte = data;
}
-READ8_MEMBER(ashnojoe_state::sound_latch_r)
-{
- m_soundlatch_status = 0;
- return m_soundlatch->read(space, 0);
-}
-
READ8_MEMBER(ashnojoe_state::sound_latch_status_r)
{
- return m_soundlatch_status;
+ return m_soundlatch->pending_r();
}
static ADDRESS_MAP_START( sound_map, AS_PROGRAM, 8, ashnojoe_state )
@@ -145,7 +130,7 @@ static ADDRESS_MAP_START( sound_portmap, AS_IO, 8, ashnojoe_state )
ADDRESS_MAP_GLOBAL_MASK(0xff)
AM_RANGE(0x00, 0x01) AM_DEVREADWRITE("ymsnd", ym2203_device, read, write)
AM_RANGE(0x02, 0x02) AM_WRITE(adpcm_w)
- AM_RANGE(0x04, 0x04) AM_READ(sound_latch_r)
+ AM_RANGE(0x04, 0x04) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
AM_RANGE(0x06, 0x06) AM_READ(sound_latch_status_r)
ADDRESS_MAP_END
@@ -302,14 +287,12 @@ WRITE_LINE_MEMBER(ashnojoe_state::ashnojoe_vclk_cb)
void ashnojoe_state::machine_start()
{
save_item(NAME(m_adpcm_byte));
- save_item(NAME(m_soundlatch_status));
save_item(NAME(m_msm5205_vclk_toggle));
}
void ashnojoe_state::machine_reset()
{
m_adpcm_byte = 0;
- m_soundlatch_status = 0;
m_msm5205_vclk_toggle = 0;
}
diff --git a/src/mame/drivers/crospang.cpp b/src/mame/drivers/crospang.cpp
index eb9a7f9d1bd..b2702b871ca 100644
--- a/src/mame/drivers/crospang.cpp
+++ b/src/mame/drivers/crospang.cpp
@@ -40,14 +40,6 @@
#include "includes/crospang.h"
-WRITE16_MEMBER(crospang_state::crospang_soundlatch_w)
-{
- if(ACCESSING_BITS_0_7)
- {
- m_soundlatch->write(space, 0, data & 0xff);
- }
-}
-
/* main cpu */
static ADDRESS_MAP_START( crospang_base_map, AS_PROGRAM, 16, crospang_state )
@@ -57,7 +49,7 @@ static ADDRESS_MAP_START( crospang_base_map, AS_PROGRAM, 16, crospang_state )
AM_RANGE(0x122000, 0x1227ff) AM_RAM_WRITE(crospang_bg_videoram_w) AM_SHARE("bg_videoram")
AM_RANGE(0x200000, 0x2005ff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
AM_RANGE(0x210000, 0x2107ff) AM_RAM AM_SHARE("spriteram")
- AM_RANGE(0x270000, 0x270001) AM_WRITE(crospang_soundlatch_w)
+ AM_RANGE(0x270000, 0x270001) AM_DEVWRITE8("soundlatch", generic_latch_8_device, write, 0x00ff)
AM_RANGE(0x270004, 0x270007) AM_WRITENOP // ??
AM_RANGE(0x280000, 0x280001) AM_READ_PORT("P1_P2")
AM_RANGE(0x280002, 0x280003) AM_READ_PORT("COIN")
diff --git a/src/mame/drivers/crshrace.cpp b/src/mame/drivers/crshrace.cpp
index f56cc5643f2..b4ad32f78c0 100644
--- a/src/mame/drivers/crshrace.cpp
+++ b/src/mame/drivers/crshrace.cpp
@@ -143,14 +143,11 @@ WRITE8_MEMBER(crshrace_state::crshrace_sh_bankswitch_w)
m_z80bank->set_entry(data & 0x03);
}
-WRITE16_MEMBER(crshrace_state::sound_command_w)
+WRITE8_MEMBER(crshrace_state::sound_command_w)
{
- if (ACCESSING_BITS_0_7)
- {
- m_pending_command = 1;
- m_soundlatch->write(space, offset, data & 0xff);
- m_audiocpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
- }
+ m_pending_command = 1;
+ m_soundlatch->write(space, offset, data & 0xff);
+ m_audiocpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
}
CUSTOM_INPUT_MEMBER(crshrace_state::country_sndpending_r)
@@ -164,7 +161,6 @@ WRITE8_MEMBER(crshrace_state::pending_command_clear_w)
}
-
static ADDRESS_MAP_START( crshrace_map, AS_PROGRAM, 16, crshrace_state )
AM_RANGE(0x000000, 0x07ffff) AM_ROM
AM_RANGE(0x300000, 0x3fffff) AM_ROM AM_REGION("user1", 0)
@@ -180,7 +176,7 @@ static ADDRESS_MAP_START( crshrace_map, AS_PROGRAM, 16, crshrace_state )
AM_RANGE(0xfff002, 0xfff003) AM_READ_PORT("P2")
AM_RANGE(0xfff004, 0xfff005) AM_READ_PORT("DSW0")
AM_RANGE(0xfff006, 0xfff007) AM_READ_PORT("DSW2")
- AM_RANGE(0xfff008, 0xfff009) AM_WRITE(sound_command_w)
+ AM_RANGE(0xfff008, 0xfff009) AM_WRITE8(sound_command_w, 0x00ff)
AM_RANGE(0xfff00a, 0xfff00b) AM_READ_PORT("DSW1")
AM_RANGE(0xfff00e, 0xfff00f) AM_READ_PORT("P3")
AM_RANGE(0xfff020, 0xfff03f) AM_DEVWRITE("k053936", k053936_device, ctrl_w)
diff --git a/src/mame/drivers/dcheese.cpp b/src/mame/drivers/dcheese.cpp
index 2aad3a511de..59d07364a06 100644
--- a/src/mame/drivers/dcheese.cpp
+++ b/src/mame/drivers/dcheese.cpp
@@ -92,7 +92,6 @@ INTERRUPT_GEN_MEMBER(dcheese_state::dcheese_vblank)
void dcheese_state::machine_start()
{
save_item(NAME(m_irq_state));
- save_item(NAME(m_soundlatch_full));
save_item(NAME(m_sound_control));
save_item(NAME(m_sound_msb_latch));
}
@@ -107,7 +106,7 @@ void dcheese_state::machine_start()
CUSTOM_INPUT_MEMBER(dcheese_state::sound_latch_state_r)
{
- return m_soundlatch_full;
+ return m_soundlatch->pending_r();
}
@@ -123,18 +122,6 @@ WRITE16_MEMBER(dcheese_state::eeprom_control_w)
}
-WRITE16_MEMBER(dcheese_state::sound_command_w)
-{
- if (ACCESSING_BITS_0_7)
- {
- /* write the latch and set the IRQ */
- m_soundlatch_full = 1;
- m_audiocpu->set_input_line(0, ASSERT_LINE);
- m_soundlatch->write(space, 0, data & 0xff);
- }
-}
-
-
/*************************************
*
@@ -142,15 +129,6 @@ WRITE16_MEMBER(dcheese_state::sound_command_w)
*
*************************************/
-READ8_MEMBER(dcheese_state::sound_command_r)
-{
- /* read the latch and clear the IRQ */
- m_soundlatch_full = 0;
- m_audiocpu->set_input_line(0, CLEAR_LINE);
- return m_soundlatch->read(space, 0);
-}
-
-
READ8_MEMBER(dcheese_state::sound_status_r)
{
/* seems to be ready signal on BSMT or latching hardware */
@@ -202,7 +180,7 @@ static ADDRESS_MAP_START( main_cpu_map, AS_PROGRAM, 16, dcheese_state )
AM_RANGE(0x260000, 0x26001f) AM_WRITE(madmax_blitter_xparam_w)
AM_RANGE(0x280000, 0x28001f) AM_WRITE(madmax_blitter_yparam_w)
AM_RANGE(0x2a0000, 0x2a003f) AM_READWRITE(madmax_blitter_vidparam_r, madmax_blitter_vidparam_w)
- AM_RANGE(0x2e0000, 0x2e0001) AM_WRITE(sound_command_w)
+ AM_RANGE(0x2e0000, 0x2e0001) AM_DEVWRITE8("soundlatch", generic_latch_8_device, write, 0x00ff)
AM_RANGE(0x300000, 0x300001) AM_WRITE(madmax_blitter_unknown_w)
ADDRESS_MAP_END
@@ -217,7 +195,7 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( sound_cpu_map, AS_PROGRAM, 8, dcheese_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000, 0x07ff) AM_READWRITE(sound_status_r, sound_control_w)
- AM_RANGE(0x0800, 0x0fff) AM_READ(sound_command_r)
+ AM_RANGE(0x0800, 0x0fff) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
AM_RANGE(0x1000, 0x10ff) AM_MIRROR(0x0700) AM_WRITE(bsmt_data_w)
AM_RANGE(0x1800, 0x1fff) AM_RAM
AM_RANGE(0x2000, 0xffff) AM_ROM
@@ -421,6 +399,7 @@ static MACHINE_CONFIG_START( dcheese, dcheese_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_GENERIC_LATCH_8_ADD("soundlatch")
+ MCFG_GENERIC_LATCH_DATA_PENDING_CB(INPUTLINE("audiocpu", 0))
MCFG_BSMT2000_ADD("bsmt", SOUND_OSC)
MCFG_SOUND_ROUTE(0, "lspeaker", 1.2)
diff --git a/src/mame/drivers/ddenlovr.cpp b/src/mame/drivers/ddenlovr.cpp
index 61a0a227402..96f7bdead39 100644
--- a/src/mame/drivers/ddenlovr.cpp
+++ b/src/mame/drivers/ddenlovr.cpp
@@ -265,24 +265,20 @@ public:
DECLARE_CUSTOM_INPUT_MEMBER(mjflove_blitter_r);
DECLARE_WRITE8_MEMBER(ddenlovr_bgcolor_w);
DECLARE_WRITE8_MEMBER(ddenlovr_bgcolor2_w);
- DECLARE_WRITE16_MEMBER(ddenlovr16_bgcolor_w);
DECLARE_WRITE8_MEMBER(ddenlovr_priority_w);
DECLARE_WRITE8_MEMBER(ddenlovr_priority2_w);
- DECLARE_WRITE16_MEMBER(ddenlovr16_priority_w);
DECLARE_WRITE8_MEMBER(ddenlovr_layer_enable_w);
DECLARE_WRITE8_MEMBER(ddenlovr_layer_enable2_w);
- DECLARE_WRITE16_MEMBER(ddenlovr16_layer_enable_w);
DECLARE_WRITE8_MEMBER(hanakanz_blitter_reg_w);
DECLARE_WRITE8_MEMBER(hanakanz_blitter_data_w);
DECLARE_WRITE8_MEMBER(rongrong_blitter_w);
- DECLARE_WRITE16_MEMBER(ddenlovr_blitter_w);
- DECLARE_WRITE16_MEMBER(ddenlovr_blitter_irq_ack_w);
+ DECLARE_WRITE8_MEMBER(ddenlovr_blitter_w);
+ DECLARE_WRITE8_MEMBER(ddenlovr_blitter_irq_ack_w);
DECLARE_READ8_MEMBER(rongrong_gfxrom_r);
DECLARE_READ16_MEMBER(ddenlovr_gfxrom_r);
- DECLARE_WRITE16_MEMBER(ddenlovr_coincounter_0_w);
- DECLARE_WRITE16_MEMBER(ddenlovr_coincounter_1_w);
+ DECLARE_WRITE8_MEMBER(ddenlovr_coincounter_0_w);
+ DECLARE_WRITE8_MEMBER(ddenlovr_coincounter_1_w);
DECLARE_WRITE8_MEMBER(rongrong_palette_w);
- DECLARE_WRITE16_MEMBER(ddenlovr_palette_w);
DECLARE_WRITE8_MEMBER(ddenlovr_palette_base_w);
DECLARE_WRITE8_MEMBER(ddenlovr_palette_base2_w);
DECLARE_WRITE8_MEMBER(ddenlovr_palette_mask_w);
@@ -291,30 +287,24 @@ public:
DECLARE_WRITE8_MEMBER(ddenlovr_transparency_pen2_w);
DECLARE_WRITE8_MEMBER(ddenlovr_transparency_mask_w);
DECLARE_WRITE8_MEMBER(ddenlovr_transparency_mask2_w);
- DECLARE_WRITE16_MEMBER(ddenlovr16_palette_base_w);
- DECLARE_WRITE16_MEMBER(ddenlovr16_palette_mask_w);
- DECLARE_WRITE16_MEMBER(ddenlovr16_transparency_pen_w);
- DECLARE_WRITE16_MEMBER(ddenlovr16_transparency_mask_w);
DECLARE_READ8_MEMBER(unk_r);
DECLARE_READ16_MEMBER(unk16_r);
- DECLARE_WRITE16_MEMBER(ddenlovr_select_16_w);
DECLARE_WRITE8_MEMBER(ddenlovr_select2_w);
- DECLARE_WRITE16_MEMBER(ddenlovr_select2_16_w);
DECLARE_READ8_MEMBER(rongrong_input2_r);
DECLARE_READ16_MEMBER(quiz365_input2_r);
DECLARE_WRITE8_MEMBER(rongrong_blitter_busy_w);
DECLARE_READ8_MEMBER(rongrong_blitter_busy_r);
- DECLARE_WRITE16_MEMBER(quiz365_coincounter_w);
+ DECLARE_WRITE8_MEMBER(quiz365_coincounter_w);
DECLARE_READ16_MEMBER(quiz365_protection_r);
DECLARE_WRITE16_MEMBER(quiz365_protection_w);
DECLARE_READ16_MEMBER(ddenlovj_dsw_r);
- DECLARE_WRITE16_MEMBER(ddenlovj_coincounter_w);
+ DECLARE_WRITE8_MEMBER(ddenlovj_coincounter_w);
DECLARE_READ16_MEMBER(ddenlovrk_protection1_r);
DECLARE_READ16_MEMBER(ddenlovrk_protection2_r);
DECLARE_WRITE16_MEMBER(ddenlovrk_protection2_w);
DECLARE_READ16_MEMBER(nettoqc_input_r);
DECLARE_READ16_MEMBER(nettoqc_protection1_r);
- DECLARE_WRITE16_MEMBER(nettoqc_coincounter_w);
+ DECLARE_WRITE8_MEMBER(nettoqc_coincounter_w);
DECLARE_READ16_MEMBER(ultrchmp_protection2_r);
DECLARE_WRITE16_MEMBER(ultrchmp_protection2_w);
DECLARE_READ8_MEMBER(rongrong_input_r);
@@ -425,12 +415,12 @@ public:
DECLARE_WRITE8_MEMBER(htengoku_dsw_w);
DECLARE_READ8_MEMBER(htengoku_dsw_r);
DECLARE_WRITE8_MEMBER( quizchq_oki_bank_w );
- DECLARE_WRITE16_MEMBER( ddenlovr_oki_bank_w );
- DECLARE_WRITE16_MEMBER( quiz365_oki_bank1_w );
- DECLARE_WRITE16_MEMBER( quiz365_oki_bank2_w );
+ DECLARE_WRITE8_MEMBER( ddenlovr_oki_bank_w );
+ DECLARE_WRITE8_MEMBER( quiz365_oki_bank1_w );
+ DECLARE_WRITE8_MEMBER( quiz365_oki_bank2_w );
DECLARE_WRITE8_MEMBER( ddenlovr_select_w );
DECLARE_READ8_MEMBER( quiz365_input_r );
- DECLARE_WRITE16_MEMBER( nettoqc_oki_bank_w );
+ DECLARE_WRITE8_MEMBER( nettoqc_oki_bank_w );
DECLARE_WRITE8_MEMBER( hanakanz_oki_bank_w );
DECLARE_WRITE8_MEMBER( mjchuuka_oki_bank_w );
DECLARE_READ8_MEMBER( hginga_dsw_r );
@@ -605,13 +595,6 @@ WRITE8_MEMBER(ddenlovr_state::ddenlovr_bgcolor2_w)
m_ddenlovr_bgcolor2 = data;
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr16_bgcolor_w)
-{
- if (ACCESSING_BITS_0_7)
- ddenlovr_bgcolor_w(space, offset, data);
-}
-
-
WRITE8_MEMBER(ddenlovr_state::ddenlovr_priority_w)
{
m_ddenlovr_priority = data;
@@ -622,13 +605,6 @@ WRITE8_MEMBER(ddenlovr_state::ddenlovr_priority2_w)
m_ddenlovr_priority2 = data;
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr16_priority_w)
-{
- if (ACCESSING_BITS_0_7)
- ddenlovr_priority_w(space, offset, data);
-}
-
-
WRITE8_MEMBER(ddenlovr_state::ddenlovr_layer_enable_w)
{
m_ddenlovr_layer_enable = data;
@@ -640,14 +616,6 @@ WRITE8_MEMBER(ddenlovr_state::ddenlovr_layer_enable2_w)
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr16_layer_enable_w)
-{
- if (ACCESSING_BITS_0_7)
- ddenlovr_layer_enable_w(space, offset, data);
-}
-
-
-
void ddenlovr_state::do_plot( int x, int y, int pen )
{
int addr, temp;
@@ -1511,26 +1479,22 @@ WRITE8_MEMBER(ddenlovr_state::rongrong_blitter_w)
blitter_w(space, 0, offset, data, 0xf8);
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr_blitter_w)
+WRITE8_MEMBER(ddenlovr_state::ddenlovr_blitter_w)
{
- if (ACCESSING_BITS_0_7)
- blitter_w(space, 0, offset, data & 0xff, 0);
+ blitter_w(space, 0, offset, data, 0);
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr_blitter_irq_ack_w)
+WRITE8_MEMBER(ddenlovr_state::ddenlovr_blitter_irq_ack_w)
{
- if (ACCESSING_BITS_0_7)
+ if (data & 1)
{
- if (data & 1)
- {
- m_ddenlovr_blitter_irq_enable = 1;
- }
- else
- {
- m_ddenlovr_blitter_irq_enable = 0;
- m_ddenlovr_blitter_irq_flag = 0;
- }
+ m_ddenlovr_blitter_irq_enable = 1;
+ }
+ else
+ {
+ m_ddenlovr_blitter_irq_enable = 0;
+ m_ddenlovr_blitter_irq_flag = 0;
}
}
@@ -1701,15 +1665,14 @@ CUSTOM_INPUT_MEMBER(ddenlovr_state::ddenlovr_blitter_irq_r)
return m_ddenlovr_blitter_irq_flag;
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr_coincounter_0_w)
+WRITE8_MEMBER(ddenlovr_state::ddenlovr_coincounter_0_w)
{
- if (ACCESSING_BITS_0_7)
- machine().bookkeeping().coin_counter_w(0, data & 1);
+ machine().bookkeeping().coin_counter_w(0, data & 1);
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr_coincounter_1_w)
+
+WRITE8_MEMBER(ddenlovr_state::ddenlovr_coincounter_1_w)
{
- if (ACCESSING_BITS_0_7)
- machine().bookkeeping().coin_counter_w(1, data & 1);
+ machine().bookkeeping().coin_counter_w(1, data & 1);
}
@@ -1731,13 +1694,6 @@ WRITE8_MEMBER(ddenlovr_state::rongrong_palette_w)
m_palette->set_pen_color(indx, pal5bit(r), pal5bit(g), pal5bit(b));
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr_palette_w)
-{
- if (ACCESSING_BITS_0_7)
- rongrong_palette_w(space, offset, data & 0xff);
-}
-
-
WRITE8_MEMBER(ddenlovr_state::ddenlovr_palette_base_w)
{
m_ddenlovr_palette_base[offset] = data;
@@ -1781,62 +1737,26 @@ WRITE8_MEMBER(ddenlovr_state::ddenlovr_transparency_mask2_w)
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr16_palette_base_w)
-{
- if (ACCESSING_BITS_0_7)
- m_ddenlovr_palette_base[offset] = data & 0xff;
-}
-
-WRITE16_MEMBER(ddenlovr_state::ddenlovr16_palette_mask_w)
-{
- if (ACCESSING_BITS_0_7)
- m_ddenlovr_palette_mask[offset] = data & 0xff;
-}
-
-WRITE16_MEMBER(ddenlovr_state::ddenlovr16_transparency_pen_w)
-{
- if (ACCESSING_BITS_0_7)
- m_ddenlovr_transparency_pen[offset] = data & 0xff;
-}
-
-WRITE16_MEMBER(ddenlovr_state::ddenlovr16_transparency_mask_w)
-{
- if (ACCESSING_BITS_0_7)
- m_ddenlovr_transparency_mask[offset] = data & 0xff;
-}
-
-
WRITE8_MEMBER(ddenlovr_state::quizchq_oki_bank_w )
{
m_oki->set_rom_bank(data & 1);
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr_oki_bank_w )
+WRITE8_MEMBER(ddenlovr_state::ddenlovr_oki_bank_w )
{
- if (ACCESSING_BITS_0_7)
- {
- m_oki->set_rom_bank(data & 7);
- }
+ m_oki->set_rom_bank(data & 7);
}
-
-
-WRITE16_MEMBER(ddenlovr_state::quiz365_oki_bank1_w )
+WRITE8_MEMBER(ddenlovr_state::quiz365_oki_bank1_w )
{
- if (ACCESSING_BITS_0_7)
- {
- m_okibank = (m_okibank & 2) | (data & 1);
- m_oki->set_rom_bank(m_okibank);
- }
+ m_okibank = (m_okibank & 2) | (data & 1);
+ m_oki->set_rom_bank(m_okibank);
}
-WRITE16_MEMBER(ddenlovr_state::quiz365_oki_bank2_w )
+WRITE8_MEMBER(ddenlovr_state::quiz365_oki_bank2_w )
{
- if (ACCESSING_BITS_0_7)
- {
- m_okibank = (m_okibank & 1) | ((data & 1) << 1);
- m_oki->set_rom_bank(m_okibank);
- }
+ m_okibank = (m_okibank & 1) | ((data & 1) << 1);
+ m_oki->set_rom_bank(m_okibank);
}
@@ -1857,23 +1777,11 @@ WRITE8_MEMBER(ddenlovr_state::ddenlovr_select_w )
m_dsw_sel = data;
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr_select_16_w)
-{
- if (ACCESSING_BITS_0_7)
- m_dsw_sel = data;
-}
-
WRITE8_MEMBER(ddenlovr_state::ddenlovr_select2_w)
{
m_input_sel = data;
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovr_select2_16_w)
-{
- if (ACCESSING_BITS_0_7)
- m_input_sel = data;
-}
-
READ8_MEMBER(ddenlovr_state::rongrong_input2_r)
{
// logerror("%04x: input2_r offset %d select %x\n", space.device().safe_pc(), offset, m_input_sel);
@@ -1933,15 +1841,12 @@ READ8_MEMBER(ddenlovr_state::rongrong_blitter_busy_r)
}
-WRITE16_MEMBER(ddenlovr_state::quiz365_coincounter_w)
+WRITE8_MEMBER(ddenlovr_state::quiz365_coincounter_w)
{
- if (ACCESSING_BITS_0_7)
+ if (m_input_sel == 0x1c)
{
- if (m_input_sel == 0x1c)
- {
- machine().bookkeeping().coin_counter_w(0, ~data & 1);
- machine().bookkeeping().coin_counter_w(1, ~data & 4);
- }
+ machine().bookkeeping().coin_counter_w(0, ~data & 1);
+ machine().bookkeeping().coin_counter_w(1, ~data & 4);
}
}
@@ -1968,25 +1873,25 @@ WRITE16_MEMBER(ddenlovr_state::quiz365_protection_w)
static ADDRESS_MAP_START( quiz365_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0x000000, 0x17ffff) AM_ROM // ROM
- AM_RANGE(0x200000, 0x2003ff) AM_WRITE(ddenlovr_palette_w) // Palette
+ AM_RANGE(0x200000, 0x2003ff) AM_WRITE8(rongrong_palette_w, 0x00ff)
AM_RANGE(0x200c02, 0x200c03) AM_READ(quiz365_protection_r) // Protection
AM_RANGE(0x200e0a, 0x200e0d) AM_WRITE(quiz365_protection_w) // Protection
// AM_RANGE(0x201000, 0x2017ff) AM_WRITEONLY // ?
- AM_RANGE(0x300200, 0x300201) AM_WRITE(ddenlovr_select2_16_w)
- AM_RANGE(0x300202, 0x300203) AM_WRITE(quiz365_coincounter_w) // Coin Counters + more stuff written on startup
+ AM_RANGE(0x300200, 0x300201) AM_WRITE8(ddenlovr_select2_w, 0x00ff)
+ AM_RANGE(0x300202, 0x300203) AM_WRITE8(quiz365_coincounter_w, 0x00ff) // Coin Counters + more stuff written on startup
AM_RANGE(0x300204, 0x300207) AM_READ(quiz365_input2_r) //
- AM_RANGE(0x300240, 0x300247) AM_WRITE(ddenlovr16_palette_base_w)
- AM_RANGE(0x300248, 0x30024f) AM_WRITE(ddenlovr16_palette_mask_w)
- AM_RANGE(0x300250, 0x300257) AM_WRITE(ddenlovr16_transparency_pen_w)
- AM_RANGE(0x300258, 0x30025f) AM_WRITE(ddenlovr16_transparency_mask_w)
- AM_RANGE(0x300268, 0x300269) AM_WRITE(ddenlovr16_bgcolor_w)
- AM_RANGE(0x30026a, 0x30026b) AM_WRITE(ddenlovr16_priority_w)
- AM_RANGE(0x30026c, 0x30026d) AM_WRITE(ddenlovr16_layer_enable_w)
+ AM_RANGE(0x300240, 0x300247) AM_WRITE8(ddenlovr_palette_base_w, 0x00ff)
+ AM_RANGE(0x300248, 0x30024f) AM_WRITE8(ddenlovr_palette_mask_w, 0x00ff)
+ AM_RANGE(0x300250, 0x300257) AM_WRITE8(ddenlovr_transparency_pen_w, 0x00ff)
+ AM_RANGE(0x300258, 0x30025f) AM_WRITE8(ddenlovr_transparency_mask_w, 0x00ff)
+ AM_RANGE(0x300268, 0x300269) AM_WRITE8(ddenlovr_bgcolor_w, 0x00ff)
+ AM_RANGE(0x30026a, 0x30026b) AM_WRITE8(ddenlovr_priority_w, 0x00ff)
+ AM_RANGE(0x30026c, 0x30026d) AM_WRITE8(ddenlovr_layer_enable_w, 0x00ff)
AM_RANGE(0x300270, 0x300271) AM_READ(unk16_r) // ? must be 78 on startup (not necessary in ddlover)
- AM_RANGE(0x300280, 0x300283) AM_WRITE(ddenlovr_blitter_w)
+ AM_RANGE(0x300280, 0x300283) AM_WRITE8(ddenlovr_blitter_w, 0x00ff)
AM_RANGE(0x300286, 0x300287) AM_READ(ddenlovr_gfxrom_r) // Video Chip
AM_RANGE(0x3002c0, 0x3002c1) AM_DEVREADWRITE8("oki", okim6295_device, read, write, 0x00ff)// Sound
@@ -1994,9 +1899,9 @@ static ADDRESS_MAP_START( quiz365_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0x300340, 0x30035f) AM_DEVREADWRITE8("rtc", msm6242_device, read, write,0x00ff)
AM_RANGE(0x300380, 0x300383) AM_DEVWRITE8("aysnd", ay8910_device, address_data_w, 0x00ff)
AM_RANGE(0x300384, 0x300385) AM_DEVREAD8("aysnd", ay8910_device, data_r, 0x00ff)
- AM_RANGE(0x3003c2, 0x3003c3) AM_WRITE(quiz365_oki_bank1_w)
- AM_RANGE(0x3003ca, 0x3003cb) AM_WRITE(ddenlovr_blitter_irq_ack_w) // Blitter irq acknowledge
- AM_RANGE(0x3003cc, 0x3003cd) AM_WRITE(quiz365_oki_bank2_w)
+ AM_RANGE(0x3003c2, 0x3003c3) AM_WRITE8(quiz365_oki_bank1_w, 0x00ff)
+ AM_RANGE(0x3003ca, 0x3003cb) AM_WRITE8(ddenlovr_blitter_irq_ack_w, 0x00ff)
+ AM_RANGE(0x3003cc, 0x3003cd) AM_WRITE8(quiz365_oki_bank2_w, 0x00ff)
AM_RANGE(0xff0000, 0xffffff) AM_RAM // RAM
ADDRESS_MAP_END
@@ -2011,14 +1916,11 @@ READ16_MEMBER(ddenlovr_state::ddenlovj_dsw_r)
return dsw;
}
-WRITE16_MEMBER(ddenlovr_state::ddenlovj_coincounter_w)
+WRITE8_MEMBER(ddenlovr_state::ddenlovj_coincounter_w)
{
- if (ACCESSING_BITS_0_7)
- {
- machine().bookkeeping().coin_counter_w(0, data & 0x01);
- machine().bookkeeping().coin_counter_w(1, data & 0x04);
- // data & 0x80 ?
- }
+ machine().bookkeeping().coin_counter_w(0, data & 0x01);
+ machine().bookkeeping().coin_counter_w(1, data & 0x04);
+ // data & 0x80 ?
}
CUSTOM_INPUT_MEMBER(ddenlovr_state::ddenlovj_blitter_r)
@@ -2029,18 +1931,18 @@ CUSTOM_INPUT_MEMBER(ddenlovr_state::ddenlovj_blitter_r)
static ADDRESS_MAP_START( ddenlovj_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0x000000, 0x07ffff) AM_ROM // ROM
- AM_RANGE(0x200000, 0x2003ff) AM_WRITE(ddenlovr_palette_w) // Palette
+ AM_RANGE(0x200000, 0x2003ff) AM_WRITE8(rongrong_palette_w, 0x00ff)
// AM_RANGE(0x201000, 0x2017ff) AM_WRITEONLY // ? B0 on startup, then 00
- AM_RANGE(0x300040, 0x300047) AM_WRITE(ddenlovr16_palette_base_w)
- AM_RANGE(0x300048, 0x30004f) AM_WRITE(ddenlovr16_palette_mask_w)
- AM_RANGE(0x300050, 0x300057) AM_WRITE(ddenlovr16_transparency_pen_w)
- AM_RANGE(0x300058, 0x30005f) AM_WRITE(ddenlovr16_transparency_mask_w)
- AM_RANGE(0x300068, 0x300069) AM_WRITE(ddenlovr16_bgcolor_w)
- AM_RANGE(0x30006a, 0x30006b) AM_WRITE(ddenlovr16_priority_w)
- AM_RANGE(0x30006c, 0x30006d) AM_WRITE(ddenlovr16_layer_enable_w)
+ AM_RANGE(0x300040, 0x300047) AM_WRITE8(ddenlovr_palette_base_w, 0x00ff)
+ AM_RANGE(0x300048, 0x30004f) AM_WRITE8(ddenlovr_palette_mask_w, 0x00ff)
+ AM_RANGE(0x300050, 0x300057) AM_WRITE8(ddenlovr_transparency_pen_w, 0x00ff)
+ AM_RANGE(0x300058, 0x30005f) AM_WRITE8(ddenlovr_transparency_mask_w, 0x00ff)
+ AM_RANGE(0x300068, 0x300069) AM_WRITE8(ddenlovr_bgcolor_w, 0x00ff)
+ AM_RANGE(0x30006a, 0x30006b) AM_WRITE8(ddenlovr_priority_w, 0x00ff)
+ AM_RANGE(0x30006c, 0x30006d) AM_WRITE8(ddenlovr_layer_enable_w, 0x00ff)
AM_RANGE(0x300070, 0x300071) AM_READ(unk16_r) // ? must be 78 on startup (not necessary in ddlover)
- AM_RANGE(0x300080, 0x300083) AM_WRITE(ddenlovr_blitter_w)
+ AM_RANGE(0x300080, 0x300083) AM_WRITE8(ddenlovr_blitter_w, 0x00ff)
AM_RANGE(0x300086, 0x300087) AM_READ(ddenlovr_gfxrom_r) // Video Chip
AM_RANGE(0x3000c0, 0x3000c3) AM_DEVWRITE8("ym2413", ym2413_device, write, 0x00ff)
AM_RANGE(0x300100, 0x30011f) AM_DEVREADWRITE8("rtc", msm6242_device, read, write,0x00ff)
@@ -2049,10 +1951,10 @@ static ADDRESS_MAP_START( ddenlovj_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0x300182, 0x300183) AM_READ_PORT("P2")
AM_RANGE(0x300184, 0x300185) AM_READ_PORT("SYSTEM")
AM_RANGE(0x300186, 0x300187) AM_READ(ddenlovj_dsw_r) // DSW
- AM_RANGE(0x300188, 0x300189) AM_WRITE(ddenlovj_coincounter_w) // Coin Counters
+ AM_RANGE(0x300188, 0x300189) AM_WRITE8(ddenlovj_coincounter_w, 0x00ff)
AM_RANGE(0x30018a, 0x30018b) AM_WRITEONLY AM_SHARE("dsw_sel16") // DSW select
- AM_RANGE(0x30018c, 0x30018d) AM_WRITE(ddenlovr_oki_bank_w)
- AM_RANGE(0x3001ca, 0x3001cb) AM_WRITE(ddenlovr_blitter_irq_ack_w) // Blitter irq acknowledge
+ AM_RANGE(0x30018c, 0x30018d) AM_WRITE8(ddenlovr_oki_bank_w, 0x00ff)
+ AM_RANGE(0x3001ca, 0x3001cb) AM_WRITE8(ddenlovr_blitter_irq_ack_w, 0x00ff)
AM_RANGE(0x300240, 0x300241) AM_DEVREADWRITE8("oki", okim6295_device, read, write, 0x00ff)// Sound
AM_RANGE(0xff0000, 0xffffff) AM_RAM // RAM
ADDRESS_MAP_END
@@ -2087,27 +1989,27 @@ static ADDRESS_MAP_START( ddenlovrk_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0x100000, 0x100001) AM_RAM_READ(ddenlovrk_protection1_r) AM_SHARE("protection1")
AM_RANGE(0x200000, 0x200001) AM_READWRITE(ddenlovrk_protection2_r, ddenlovrk_protection2_w) AM_SHARE("protection2")
- AM_RANGE(0xd00000, 0xd003ff) AM_WRITE(ddenlovr_palette_w) // Palette
+ AM_RANGE(0xd00000, 0xd003ff) AM_WRITE8(rongrong_palette_w, 0x00ff)
// AM_RANGE(0xd01000, 0xd017ff) AM_RAM // ? B0 on startup, then 00
- AM_RANGE(0xe00040, 0xe00047) AM_WRITE(ddenlovr16_palette_base_w)
- AM_RANGE(0xe00048, 0xe0004f) AM_WRITE(ddenlovr16_palette_mask_w)
- AM_RANGE(0xe00050, 0xe00057) AM_WRITE(ddenlovr16_transparency_pen_w)
- AM_RANGE(0xe00058, 0xe0005f) AM_WRITE(ddenlovr16_transparency_mask_w)
- AM_RANGE(0xe00068, 0xe00069) AM_WRITE(ddenlovr16_bgcolor_w)
- AM_RANGE(0xe0006a, 0xe0006b) AM_WRITE(ddenlovr16_priority_w)
- AM_RANGE(0xe0006c, 0xe0006d) AM_WRITE(ddenlovr16_layer_enable_w)
+ AM_RANGE(0xe00040, 0xe00047) AM_WRITE8(ddenlovr_palette_base_w, 0x00ff)
+ AM_RANGE(0xe00048, 0xe0004f) AM_WRITE8(ddenlovr_palette_mask_w, 0x00ff)
+ AM_RANGE(0xe00050, 0xe00057) AM_WRITE8(ddenlovr_transparency_pen_w, 0x00ff)
+ AM_RANGE(0xe00058, 0xe0005f) AM_WRITE8(ddenlovr_transparency_mask_w, 0x00ff)
+ AM_RANGE(0xe00068, 0xe00069) AM_WRITE8(ddenlovr_bgcolor_w, 0x00ff)
+ AM_RANGE(0xe0006a, 0xe0006b) AM_WRITE8(ddenlovr_priority_w, 0x00ff)
+ AM_RANGE(0xe0006c, 0xe0006d) AM_WRITE8(ddenlovr_layer_enable_w, 0x00ff)
AM_RANGE(0xe00070, 0xe00071) AM_READNOP
- AM_RANGE(0xe00080, 0xe00083) AM_WRITE(ddenlovr_blitter_w)
+ AM_RANGE(0xe00080, 0xe00083) AM_WRITE8(ddenlovr_blitter_w, 0x00ff)
AM_RANGE(0xe00086, 0xe00087) AM_READ(ddenlovr_gfxrom_r) // Video Chip
AM_RANGE(0xe00100, 0xe00101) AM_READ_PORT("P1")
AM_RANGE(0xe00102, 0xe00103) AM_READ_PORT("P2")
AM_RANGE(0xe00104, 0xe00105) AM_READ_PORT("SYSTEM")
AM_RANGE(0xe00200, 0xe00201) AM_READ_PORT("DSW")
- AM_RANGE(0xe00302, 0xe00303) AM_WRITE(ddenlovr_blitter_irq_ack_w) // Blitter irq acknowledge
- AM_RANGE(0xe00308, 0xe00309) AM_WRITE(ddenlovr_coincounter_0_w) // Coin Counters
- AM_RANGE(0xe0030c, 0xe0030d) AM_WRITE(ddenlovr_coincounter_1_w) //
+ AM_RANGE(0xe00302, 0xe00303) AM_WRITE8(ddenlovr_blitter_irq_ack_w, 0x00ff)
+ AM_RANGE(0xe00308, 0xe00309) AM_WRITE8(ddenlovr_coincounter_0_w, 0x00ff)
+ AM_RANGE(0xe0030c, 0xe0030d) AM_WRITE8(ddenlovr_coincounter_1_w, 0x00ff)
AM_RANGE(0xe00400, 0xe00403) AM_DEVWRITE8("ym2413", ym2413_device, write, 0x00ff)
AM_RANGE(0xe00500, 0xe0051f) AM_DEVREADWRITE8("rtc", msm6242_device, read, write,0x00ff)
@@ -2123,29 +2025,29 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( ddenlovr_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0x000000, 0x07ffff) AM_ROM // ROM
- AM_RANGE(0x300000, 0x300001) AM_WRITE( ddenlovr_oki_bank_w)
+ AM_RANGE(0x300000, 0x300001) AM_WRITE8(ddenlovr_oki_bank_w, 0x00ff)
- AM_RANGE(0xd00000, 0xd003ff) AM_WRITE(ddenlovr_palette_w) // Palette
+ AM_RANGE(0xd00000, 0xd003ff) AM_WRITE8(rongrong_palette_w, 0x00ff)
// AM_RANGE(0xd01000, 0xd017ff) AM_RAM // ? B0 on startup, then 00
- AM_RANGE(0xe00040, 0xe00047) AM_WRITE(ddenlovr16_palette_base_w)
- AM_RANGE(0xe00048, 0xe0004f) AM_WRITE(ddenlovr16_palette_mask_w)
- AM_RANGE(0xe00050, 0xe00057) AM_WRITE(ddenlovr16_transparency_pen_w)
- AM_RANGE(0xe00058, 0xe0005f) AM_WRITE(ddenlovr16_transparency_mask_w)
- AM_RANGE(0xe00068, 0xe00069) AM_WRITE(ddenlovr16_bgcolor_w)
- AM_RANGE(0xe0006a, 0xe0006b) AM_WRITE(ddenlovr16_priority_w)
- AM_RANGE(0xe0006c, 0xe0006d) AM_WRITE(ddenlovr16_layer_enable_w)
+ AM_RANGE(0xe00040, 0xe00047) AM_WRITE8(ddenlovr_palette_base_w, 0x00ff)
+ AM_RANGE(0xe00048, 0xe0004f) AM_WRITE8(ddenlovr_palette_mask_w, 0x00ff)
+ AM_RANGE(0xe00050, 0xe00057) AM_WRITE8(ddenlovr_transparency_pen_w, 0x00ff)
+ AM_RANGE(0xe00058, 0xe0005f) AM_WRITE8(ddenlovr_transparency_mask_w, 0x00ff)
+ AM_RANGE(0xe00068, 0xe00069) AM_WRITE8(ddenlovr_bgcolor_w, 0x00ff)
+ AM_RANGE(0xe0006a, 0xe0006b) AM_WRITE8(ddenlovr_priority_w, 0x00ff)
+ AM_RANGE(0xe0006c, 0xe0006d) AM_WRITE8(ddenlovr_layer_enable_w, 0x00ff)
AM_RANGE(0xe00070, 0xe00071) AM_READ(unk16_r) // ? must be 78 on startup (not necessary in ddlover)
- AM_RANGE(0xe00080, 0xe00083) AM_WRITE(ddenlovr_blitter_w)
+ AM_RANGE(0xe00080, 0xe00083) AM_WRITE8(ddenlovr_blitter_w, 0x00ff)
AM_RANGE(0xe00086, 0xe00087) AM_READ(ddenlovr_gfxrom_r) // Video Chip
AM_RANGE(0xe00100, 0xe00101) AM_READ_PORT("P1")
AM_RANGE(0xe00102, 0xe00103) AM_READ_PORT("P2")
AM_RANGE(0xe00104, 0xe00105) AM_READ_PORT("SYSTEM")
AM_RANGE(0xe00200, 0xe00201) AM_READ_PORT("DSW")
- AM_RANGE(0xe00302, 0xe00303) AM_WRITE(ddenlovr_blitter_irq_ack_w) // Blitter irq acknowledge
- AM_RANGE(0xe00308, 0xe00309) AM_WRITE(ddenlovr_coincounter_0_w) // Coin Counters
- AM_RANGE(0xe0030c, 0xe0030d) AM_WRITE(ddenlovr_coincounter_1_w) //
+ AM_RANGE(0xe00302, 0xe00303) AM_WRITE8(ddenlovr_blitter_irq_ack_w, 0x00ff)
+ AM_RANGE(0xe00308, 0xe00309) AM_WRITE8(ddenlovr_coincounter_0_w, 0x00ff)
+ AM_RANGE(0xe0030c, 0xe0030d) AM_WRITE8(ddenlovr_coincounter_1_w, 0x00ff)
AM_RANGE(0xe00400, 0xe00403) AM_DEVWRITE8("ym2413", ym2413_device, write, 0x00ff)
AM_RANGE(0xe00500, 0xe0051f) AM_DEVREADWRITE8("rtc", msm6242_device, read, write,0x00ff)
@@ -2185,41 +2087,35 @@ READ16_MEMBER(ddenlovr_state::nettoqc_protection1_r)
}
}
-WRITE16_MEMBER(ddenlovr_state::nettoqc_coincounter_w)
+WRITE8_MEMBER(ddenlovr_state::nettoqc_coincounter_w)
{
- if (ACCESSING_BITS_0_7)
- {
- machine().bookkeeping().coin_counter_w(0, data & 0x01);
- machine().bookkeeping().coin_counter_w(1, data & 0x04);
- // data & 0x80 ?
- }
+ machine().bookkeeping().coin_counter_w(0, data & 0x01);
+ machine().bookkeeping().coin_counter_w(1, data & 0x04);
+ // data & 0x80 ?
}
-WRITE16_MEMBER(ddenlovr_state::nettoqc_oki_bank_w )
+WRITE8_MEMBER(ddenlovr_state::nettoqc_oki_bank_w )
{
- if (ACCESSING_BITS_0_7)
- {
- m_oki->set_rom_bank(data & 3);
- }
+ m_oki->set_rom_bank(data & 3);
}
static ADDRESS_MAP_START( nettoqc_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0x000000, 0x17ffff) AM_ROM // ROM
- AM_RANGE(0x200000, 0x2003ff) AM_WRITE(ddenlovr_palette_w) // Palette
+ AM_RANGE(0x200000, 0x2003ff) AM_WRITE8(rongrong_palette_w, 0x00ff)
AM_RANGE(0x200c02, 0x200c03) AM_READ(nettoqc_protection1_r) // Protection 1
AM_RANGE(0x200e0a, 0x200e0d) AM_WRITEONLY AM_SHARE("protection1") // ""
AM_RANGE(0x201000, 0x2017ff) AM_WRITEONLY // ?
- AM_RANGE(0x300040, 0x300047) AM_WRITE(ddenlovr16_palette_base_w)
- AM_RANGE(0x300048, 0x30004f) AM_WRITE(ddenlovr16_palette_mask_w)
- AM_RANGE(0x300050, 0x300057) AM_WRITE(ddenlovr16_transparency_pen_w)
- AM_RANGE(0x300058, 0x30005f) AM_WRITE(ddenlovr16_transparency_mask_w)
- AM_RANGE(0x300068, 0x300069) AM_WRITE(ddenlovr16_bgcolor_w)
- AM_RANGE(0x30006a, 0x30006b) AM_WRITE(ddenlovr16_priority_w)
- AM_RANGE(0x30006c, 0x30006d) AM_WRITE(ddenlovr16_layer_enable_w)
+ AM_RANGE(0x300040, 0x300047) AM_WRITE8(ddenlovr_palette_base_w, 0x00ff)
+ AM_RANGE(0x300048, 0x30004f) AM_WRITE8(ddenlovr_palette_mask_w, 0x00ff)
+ AM_RANGE(0x300050, 0x300057) AM_WRITE8(ddenlovr_transparency_pen_w, 0x00ff)
+ AM_RANGE(0x300058, 0x30005f) AM_WRITE8(ddenlovr_transparency_mask_w, 0x00ff)
+ AM_RANGE(0x300068, 0x300069) AM_WRITE8(ddenlovr_bgcolor_w, 0x00ff)
+ AM_RANGE(0x30006a, 0x30006b) AM_WRITE8(ddenlovr_priority_w, 0x00ff)
+ AM_RANGE(0x30006c, 0x30006d) AM_WRITE8(ddenlovr_layer_enable_w, 0x00ff)
AM_RANGE(0x300070, 0x300071) AM_READ(unk16_r) // ? must be 78 on startup (not necessary in ddlover)
- AM_RANGE(0x300080, 0x300083) AM_WRITE(ddenlovr_blitter_w)
+ AM_RANGE(0x300080, 0x300083) AM_WRITE8(ddenlovr_blitter_w, 0x00ff)
AM_RANGE(0x300086, 0x300087) AM_READ(ddenlovr_gfxrom_r) // Video Chip
AM_RANGE(0x3000c0, 0x3000c3) AM_DEVWRITE8("ym2413", ym2413_device, write, 0x00ff)
AM_RANGE(0x300100, 0x30011f) AM_DEVREADWRITE8("rtc", msm6242_device, read, write,0x00ff)
@@ -2228,10 +2124,10 @@ static ADDRESS_MAP_START( nettoqc_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0x300182, 0x300183) AM_READ_PORT("P2")
AM_RANGE(0x300184, 0x300185) AM_READ_PORT("SYSTEM")
AM_RANGE(0x300186, 0x300187) AM_READ(nettoqc_input_r) // DSW's
- AM_RANGE(0x300188, 0x300189) AM_WRITE(nettoqc_coincounter_w) // Coin Counters
- AM_RANGE(0x30018a, 0x30018b) AM_WRITE(ddenlovr_select_16_w) //
- AM_RANGE(0x30018c, 0x30018d) AM_WRITE(nettoqc_oki_bank_w)
- AM_RANGE(0x3001ca, 0x3001cb) AM_WRITE(ddenlovr_blitter_irq_ack_w) // Blitter irq acknowledge
+ AM_RANGE(0x300188, 0x300189) AM_WRITE8(nettoqc_coincounter_w, 0x00ff)
+ AM_RANGE(0x30018a, 0x30018b) AM_WRITE8(ddenlovr_select_w, 0x00ff)
+ AM_RANGE(0x30018c, 0x30018d) AM_WRITE8(nettoqc_oki_bank_w, 0x00ff)
+ AM_RANGE(0x3001ca, 0x3001cb) AM_WRITE8(ddenlovr_blitter_irq_ack_w, 0x00ff)
AM_RANGE(0x300240, 0x300241) AM_DEVREADWRITE8("oki", okim6295_device, read, write, 0x00ff) // Sound
AM_RANGE(0xff0000, 0xffffff) AM_RAM // RAM
ADDRESS_MAP_END
@@ -2258,31 +2154,31 @@ static ADDRESS_MAP_START( ultrchmp_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0x224680, 0x224681) AM_RAM_READ(ultrchmp_protection2_r) AM_SHARE("protection2") // Protection 2
AM_RANGE(0x313570, 0x313571) AM_WRITE(ultrchmp_protection2_w) // "" + OKI bank
- AM_RANGE(0xd00000, 0xd003ff) AM_WRITE(ddenlovr_palette_w) // Palette
+ AM_RANGE(0xd00000, 0xd003ff) AM_WRITE8(rongrong_palette_w, 0x00ff)
AM_RANGE(0xd00c02, 0xd00c03) AM_READ(nettoqc_protection1_r) // Protection 1
AM_RANGE(0xd00e0a, 0xd00e0d) AM_WRITEONLY AM_SHARE("protection1") // ""
AM_RANGE(0xd01000, 0xd017ff) AM_WRITEONLY // ?
- AM_RANGE(0xe00040, 0xe00047) AM_WRITE(ddenlovr16_palette_base_w)
- AM_RANGE(0xe00048, 0xe0004f) AM_WRITE(ddenlovr16_palette_mask_w)
- AM_RANGE(0xe00050, 0xe00057) AM_WRITE(ddenlovr16_transparency_pen_w)
- AM_RANGE(0xe00058, 0xe0005f) AM_WRITE(ddenlovr16_transparency_mask_w)
- AM_RANGE(0xe00068, 0xe00069) AM_WRITE(ddenlovr16_bgcolor_w)
- AM_RANGE(0xe0006a, 0xe0006b) AM_WRITE(ddenlovr16_priority_w)
- AM_RANGE(0xe0006c, 0xe0006d) AM_WRITE(ddenlovr16_layer_enable_w)
+ AM_RANGE(0xe00040, 0xe00047) AM_WRITE8(ddenlovr_palette_base_w, 0x00ff)
+ AM_RANGE(0xe00048, 0xe0004f) AM_WRITE8(ddenlovr_palette_mask_w, 0x00ff)
+ AM_RANGE(0xe00050, 0xe00057) AM_WRITE8(ddenlovr_transparency_pen_w, 0x00ff)
+ AM_RANGE(0xe00058, 0xe0005f) AM_WRITE8(ddenlovr_transparency_mask_w, 0x00ff)
+ AM_RANGE(0xe00068, 0xe00069) AM_WRITE8(ddenlovr_bgcolor_w, 0x00ff)
+ AM_RANGE(0xe0006a, 0xe0006b) AM_WRITE8(ddenlovr_priority_w, 0x00ff)
+ AM_RANGE(0xe0006c, 0xe0006d) AM_WRITE8(ddenlovr_layer_enable_w, 0x00ff)
AM_RANGE(0xe00070, 0xe00071) AM_READNOP
- AM_RANGE(0xe00080, 0xe00083) AM_WRITE(ddenlovr_blitter_w)
+ AM_RANGE(0xe00080, 0xe00083) AM_WRITE8(ddenlovr_blitter_w, 0x00ff)
AM_RANGE(0xe00086, 0xe00087) AM_READ(ddenlovr_gfxrom_r) // Video Chip
AM_RANGE(0xe00100, 0xe00101) AM_READ_PORT("P1")
AM_RANGE(0xe00102, 0xe00103) AM_READ_PORT("P2")
AM_RANGE(0xe00104, 0xe00105) AM_READ_PORT("SYSTEM")
AM_RANGE(0xe00200, 0xe00201) AM_READ_PORT("DSW")
- AM_RANGE(0xe00302, 0xe00303) AM_WRITE(ddenlovr_blitter_irq_ack_w) // Blitter irq acknowledge
- AM_RANGE(0xe00308, 0xe00309) AM_WRITE(ddenlovr_coincounter_0_w) // Coin Counters
- AM_RANGE(0xe0030c, 0xe0030d) AM_WRITE(ddenlovr_coincounter_1_w) //
+ AM_RANGE(0xe00302, 0xe00303) AM_WRITE8(ddenlovr_blitter_irq_ack_w, 0x00ff)
+ AM_RANGE(0xe00308, 0xe00309) AM_WRITE8(ddenlovr_coincounter_0_w, 0x00ff)
+ AM_RANGE(0xe0030c, 0xe0030d) AM_WRITE8(ddenlovr_coincounter_1_w, 0x00ff)
AM_RANGE(0xe00400, 0xe00403) AM_DEVWRITE8("ym2413", ym2413_device, write, 0x00ff)
AM_RANGE(0xe00500, 0xe0051f) AM_DEVREADWRITE8("rtc", msm6242_device, read, write,0x00ff)
@@ -3749,18 +3645,18 @@ static ADDRESS_MAP_START( akamaru_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0x213570, 0x213571) AM_WRITE(akamaru_protection1_w) // OKI bank
AM_RANGE(0x624680, 0x624681) AM_READ(akamaru_protection1_r)
- AM_RANGE(0xd00000, 0xd003ff) AM_WRITE(ddenlovr_palette_w) // Palette
+ AM_RANGE(0xd00000, 0xd003ff) AM_WRITE8(rongrong_palette_w, 0x00ff)
// AM_RANGE(0xd01000, 0xd017ff) AM_WRITEONLY // 0
- AM_RANGE(0xe00040, 0xe00047) AM_WRITE(ddenlovr16_palette_base_w)
- AM_RANGE(0xe00048, 0xe0004f) AM_WRITE(ddenlovr16_palette_mask_w)
- AM_RANGE(0xe00050, 0xe00057) AM_WRITE(ddenlovr16_transparency_pen_w)
- AM_RANGE(0xe00058, 0xe0005f) AM_WRITE(ddenlovr16_transparency_mask_w)
- AM_RANGE(0xe00068, 0xe00069) AM_WRITE(ddenlovr16_bgcolor_w)
- AM_RANGE(0xe0006a, 0xe0006b) AM_WRITE(ddenlovr16_priority_w)
- AM_RANGE(0xe0006c, 0xe0006d) AM_WRITE(ddenlovr16_layer_enable_w)
+ AM_RANGE(0xe00040, 0xe00047) AM_WRITE8(ddenlovr_palette_base_w, 0x00ff)
+ AM_RANGE(0xe00048, 0xe0004f) AM_WRITE8(ddenlovr_palette_mask_w, 0x00ff)
+ AM_RANGE(0xe00050, 0xe00057) AM_WRITE8(ddenlovr_transparency_pen_w, 0x00ff)
+ AM_RANGE(0xe00058, 0xe0005f) AM_WRITE8(ddenlovr_transparency_mask_w, 0x00ff)
+ AM_RANGE(0xe00068, 0xe00069) AM_WRITE8(ddenlovr_bgcolor_w, 0x00ff)
+ AM_RANGE(0xe0006a, 0xe0006b) AM_WRITE8(ddenlovr_priority_w, 0x00ff)
+ AM_RANGE(0xe0006c, 0xe0006d) AM_WRITE8(ddenlovr_bgcolor_w, 0x00ff)
AM_RANGE(0xe00070, 0xe00071) AM_READ(unk16_r) // ? must be 78 on startup (not necessary in ddlover)
- AM_RANGE(0xe00080, 0xe00083) AM_WRITE(ddenlovr_blitter_w)
+ AM_RANGE(0xe00080, 0xe00083) AM_WRITE8(ddenlovr_blitter_w, 0x00ff)
AM_RANGE(0xe00086, 0xe00087) AM_READ(ddenlovr_gfxrom_r) // Video Chip
AM_RANGE(0xe00100, 0xe00101) AM_READ_PORT("P1")
@@ -3774,11 +3670,11 @@ static ADDRESS_MAP_START( akamaru_map, AS_PROGRAM, 16, ddenlovr_state )
AM_RANGE(0xe00200, 0xe00201) AM_READ(akamaru_dsw_r) // DSW
AM_RANGE(0xe00204, 0xe00205) AM_READ(akamaru_blitter_r) // Blitter Busy & IRQ
- AM_RANGE(0xe00302, 0xe00303) AM_WRITE(ddenlovr_blitter_irq_ack_w) // Blitter irq acknowledge
+ AM_RANGE(0xe00302, 0xe00303) AM_WRITE8(ddenlovr_blitter_irq_ack_w, 0x00ff)
AM_RANGE(0xe00304, 0xe00307) AM_WRITEONLY AM_SHARE("dsw_sel16") // DSW select
- AM_RANGE(0xe00308, 0xe00309) AM_WRITE(ddenlovr_coincounter_0_w) // Coin Counters
- AM_RANGE(0xe0030c, 0xe0030d) AM_WRITE(ddenlovr_coincounter_1_w) //
+ AM_RANGE(0xe00308, 0xe00309) AM_WRITE8(ddenlovr_coincounter_0_w, 0x00ff)
+ AM_RANGE(0xe0030c, 0xe0030d) AM_WRITE8(ddenlovr_coincounter_1_w, 0x00ff)
AM_RANGE(0xe00400, 0xe00403) AM_DEVWRITE8("ym2413", ym2413_device, write, 0x00ff)
AM_RANGE(0xe00500, 0xe0051f) AM_DEVREADWRITE8("rtc", msm6242_device, read, write, 0x00ff)
diff --git a/src/mame/drivers/esd16.cpp b/src/mame/drivers/esd16.cpp
index 8fc6444b932..75483cb0372 100644
--- a/src/mame/drivers/esd16.cpp
+++ b/src/mame/drivers/esd16.cpp
@@ -1367,6 +1367,9 @@ ROM_START( tangtang )
ROM_REGION( 0x40000, "oki", 0 ) /* Samples */
ROM_LOAD( "esd4.su10", 0x00000, 0x20000, CRC(f2dfb02d) SHA1(04001488697aad3e5b2d15c9f5a81dc2b7d0952c) )
+
+ ROM_REGION16_BE( 0x80, "eeprom", ROMREGION_ERASE00 ) // default settings because game doesn't init them properly otherwise
+ ROM_LOAD16_WORD_SWAP( "eeprom", 0x0000, 0x0080, CRC(00514989) SHA1(86cdca86ed48962e3bda13f9e6f8e573e176dec0) )
ROM_END
/*
diff --git a/src/mame/drivers/hapyfish.cpp b/src/mame/drivers/hapyfish.cpp
new file mode 100644
index 00000000000..1d57c35c35a
--- /dev/null
+++ b/src/mame/drivers/hapyfish.cpp
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+/* Happy Fish (xxx-in-1 multigame)
+
+ Primary system components
+
+ SAMSUNG ARM-based Soc
+ 2x SAMSUNG Flash ROMs
+ + a bunch of RAM
+
+ (todo, fill in exact details)
+
+ progress was previously shown with this, booting to the menu at least
+ using (I believe) ghosteo.cpp as a base, but the contributor is no
+ longer active, and that driver was never submitted.
+
+*/
+
+#include "emu.h"
+#include "cpu/arm7/arm7.h"
+#include "cpu/arm7/arm7core.h"
+
+
+class hapyfish_state : public driver_device
+{
+public:
+ hapyfish_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu") { }
+
+ virtual void video_start() override;
+ uint32_t screen_update_hapyfish(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ required_device<cpu_device> m_maincpu;
+};
+
+static ADDRESS_MAP_START( hapyfish_map, AS_PROGRAM, 32, hapyfish_state )
+ AM_RANGE(0x00000000, 0x00003fff) AM_ROM
+ADDRESS_MAP_END
+
+static INPUT_PORTS_START( hapyfish )
+INPUT_PORTS_END
+
+uint32_t hapyfish_state::screen_update_hapyfish(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ return 0;
+}
+
+void hapyfish_state::video_start()
+{
+}
+
+
+
+static MACHINE_CONFIG_START( hapyfish, hapyfish_state )
+
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu", ARM9, 20000000) // ?? ARM baesd CPU
+ MCFG_CPU_PROGRAM_MAP(hapyfish_map)
+ MCFG_DEVICE_DISABLE()
+
+ /* video hardware */
+ MCFG_SCREEN_ADD("screen", RASTER)
+ MCFG_SCREEN_REFRESH_RATE(60)
+ MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
+ MCFG_SCREEN_SIZE(64*8, 64*8)
+ MCFG_SCREEN_VISIBLE_AREA(0*8, 56*8-1, 0*8, 28*8-1)
+ MCFG_SCREEN_UPDATE_DRIVER(hapyfish_state, screen_update_hapyfish)
+MACHINE_CONFIG_END
+
+
+
+ROM_START( hapyfsh2 )
+ ROM_REGION( 0x04000, "maincpu", ROMREGION_ERASE00 )
+ // the SoC copies some data from the flash in order to boot
+
+ ROM_REGION( 0x84000000, "flash1", 0 )
+ ROM_LOAD( "flash.u6", 0x00000000, 0x84000000, CRC(3aa364a2) SHA1(fe09f549a937ecaf8f7a859522a6635e272fe714) )
+
+ ROM_REGION( 0x84000000, "flash2", 0 )
+ ROM_LOAD( "flash.u28", 0x00000000, 0x84000000, CRC(f00a25cd) SHA1(9c33f8e26b84cea957d9c37fb83a686b948c6834) )
+ROM_END
+
+ GAME( 201?, hapyfsh2, 0, hapyfish, hapyfish, driver_device, 0, ROT0, "bootleg", "Happy Fish (V2 PCB, 302-in-1)", MACHINE_IS_SKELETON )
+
diff --git a/src/mame/drivers/harddriv.cpp b/src/mame/drivers/harddriv.cpp
index 815cf4f2032..76a0c668f9b 100644
--- a/src/mame/drivers/harddriv.cpp
+++ b/src/mame/drivers/harddriv.cpp
@@ -461,7 +461,8 @@ harddriv_state::harddriv_state(const machine_config &mconfig, const char *tag, d
m_sound_int_state(0),
m_video_int_state(0),
m_palette(*this, "palette"),
- m_slapstic_device(*this, "slapstic")
+ m_slapstic_device(*this, "slapstic"),
+ m_rs232(*this, "rs232")
{
int i;
@@ -1445,6 +1446,10 @@ static MACHINE_CONFIG_FRAGMENT( driver_nomsp )
MCFG_MC68681_ADD("duartn68681", XTAL_3_6864MHz)
MCFG_MC68681_IRQ_CALLBACK(WRITELINE(harddriv_state, harddriv_duart_irq_handler))
+ MCFG_MC68681_A_TX_CALLBACK(DEVWRITELINE ("rs232", rs232_port_device, write_txd))
+
+ MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, nullptr)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE ("duartn68681", mc68681_device, rx_a_w))
/* video hardware */
MCFG_PALETTE_ADD("palette", 1024)
diff --git a/src/mame/drivers/hh_cop400.cpp b/src/mame/drivers/hh_cop400.cpp
index 28be622fcbf..1795c35e368 100644
--- a/src/mame/drivers/hh_cop400.cpp
+++ b/src/mame/drivers/hh_cop400.cpp
@@ -19,7 +19,7 @@
#include "bship82.lh" // clickable
#include "ctstein.lh" // clickable
#include "einvaderc.lh" // test-layout(but still playable)
-#include "funjacks.lh"
+#include "funjacks.lh" // clickable
#include "funrlgl.lh"
#include "h2hbaskb.lh"
#include "lightfgt.lh" // clickable
@@ -48,16 +48,16 @@ public:
uint8_t m_l; // MCU port L write data
uint8_t m_g; // MCU port G write data
uint8_t m_d; // MCU port D write data
- int m_so; // MCU SO line state
- int m_sk; // MCU SK line state
+ int m_so; // MCU SO line state
+ int m_sk; // MCU SK line state
uint16_t m_inp_mux; // multiplexed inputs mask
uint16_t read_inputs(int columns);
// display common
- int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
- int m_display_maxy; // display matrix number of rows
- int m_display_maxx; // display matrix number of columns (max 31 for now)
+ int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
+ int m_display_maxy; // display matrix number of rows
+ int m_display_maxx; // display matrix number of columns (max 31 for now)
uint32_t m_display_state[0x20]; // display matrix rows data (last bit is used for always-on)
uint16_t m_display_segmask[0x20]; // if not 0, display matrix row is a digit, mask indicates connected segments
diff --git a/src/mame/drivers/hh_hmcs40.cpp b/src/mame/drivers/hh_hmcs40.cpp
index 82d98b65eb8..4cd7736585a 100644
--- a/src/mame/drivers/hh_hmcs40.cpp
+++ b/src/mame/drivers/hh_hmcs40.cpp
@@ -133,9 +133,9 @@ public:
DECLARE_INPUT_CHANGED_MEMBER(single_interrupt_line);
// display common
- int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
- int m_display_maxy; // display matrix number of rows
- int m_display_maxx; // display matrix number of columns (max 47 for now)
+ int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
+ int m_display_maxy; // display matrix number of rows
+ int m_display_maxx; // display matrix number of columns (max 47 for now)
uint32_t m_grid; // VFD current row data
uint64_t m_plate; // VFD current column data
diff --git a/src/mame/drivers/hh_melps4.cpp b/src/mame/drivers/hh_melps4.cpp
index aebaef2ff7e..0e557ee6b58 100644
--- a/src/mame/drivers/hh_melps4.cpp
+++ b/src/mame/drivers/hh_melps4.cpp
@@ -40,9 +40,9 @@ public:
DECLARE_INPUT_CHANGED_MEMBER(reset_button);
// display common
- int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
- int m_display_maxy; // display matrix number of rows
- int m_display_maxx; // display matrix number of columns (max 31 for now)
+ int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
+ int m_display_maxy; // display matrix number of rows
+ int m_display_maxx; // display matrix number of columns (max 31 for now)
uint32_t m_grid; // VFD current row data
uint32_t m_plate; // VFD current column data
diff --git a/src/mame/drivers/hh_pic16.cpp b/src/mame/drivers/hh_pic16.cpp
index 6bb594cc30e..c8b013ecd12 100644
--- a/src/mame/drivers/hh_pic16.cpp
+++ b/src/mame/drivers/hh_pic16.cpp
@@ -54,9 +54,9 @@ public:
uint8_t m_c; // MCU port C data
// display common
- int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
- int m_display_maxy; // display matrix number of rows
- int m_display_maxx; // display matrix number of columns (max 31 for now)
+ int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
+ int m_display_maxy; // display matrix number of rows
+ int m_display_maxx; // display matrix number of columns (max 31 for now)
uint32_t m_display_state[0x20]; // display matrix rows data (last bit is used for always-on)
uint16_t m_display_segmask[0x20]; // if not 0, display matrix row is a digit, mask indicates connected segments
diff --git a/src/mame/drivers/hh_sm510.cpp b/src/mame/drivers/hh_sm510.cpp
index 2d9f21322df..92fc2c56e06 100644
--- a/src/mame/drivers/hh_sm510.cpp
+++ b/src/mame/drivers/hh_sm510.cpp
@@ -34,7 +34,7 @@ public:
optional_device<speaker_sound_device> m_speaker;
// misc common
- uint16_t m_inp_mux; // multiplexed inputs mask
+ uint16_t m_inp_mux; // multiplexed inputs mask
int m_inp_lines; // number of input mux columns
uint8_t m_lcd_output_cache[0x100];
diff --git a/src/mame/drivers/hh_tms1k.cpp b/src/mame/drivers/hh_tms1k.cpp
index d43084098e5..62433eb9e3a 100644
--- a/src/mame/drivers/hh_tms1k.cpp
+++ b/src/mame/drivers/hh_tms1k.cpp
@@ -21,10 +21,11 @@
*MP0057 TMS1000 1978, APH Student Speech+ (same ROM contents as TSI Speech+?)
@MP0158 TMS1000 1979, Entex Soccer (6003)
@MP0163 TMS1000 1979, A-One LSI Match Number/LJN Electronic Concentration
- *MP0168 TMS1000 1979, Conic Basketball/Tandy Sports Arena
+ *MP0168 TMS1000 1979, Conic Multisport/Tandy Sports Arena
@MP0170 TMS1000 1979, Conic Football
*MP0230 TMS1000 1980, Entex Blast It (6015)
@MP0271 TMS1000 1982, Tandy Radio Shack Monkey See
+ *MP0907 TMS1000 1979, Conic/Cardinal Basketball
@MP0914 TMS1000 1979, Entex Baseball 1
@MP0915 TMS1000 1979, Bandai System Control Car: Cheetah/The Incredible Brain Buggy
@MP0919 TMS1000 1979, Tiger Copy Cat (model 7-520)
diff --git a/src/mame/drivers/novag6502.cpp b/src/mame/drivers/novag6502.cpp
index 4f8f5916447..a8558ddb5bc 100644
--- a/src/mame/drivers/novag6502.cpp
+++ b/src/mame/drivers/novag6502.cpp
@@ -62,9 +62,9 @@ public:
uint16_t read_inputs(int columns);
// display common
- int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
- int m_display_maxy; // display matrix number of rows
- int m_display_maxx; // display matrix number of columns (max 31 for now)
+ int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
+ int m_display_maxy; // display matrix number of rows
+ int m_display_maxx; // display matrix number of columns (max 31 for now)
uint32_t m_display_state[0x20]; // display matrix rows data (last bit is used for always-on)
uint16_t m_display_segmask[0x20]; // if not 0, display matrix row is a digit, mask indicates connected segments
diff --git a/src/mame/drivers/pc.cpp b/src/mame/drivers/pc.cpp
index 404fa5746f6..c89282b37da 100644
--- a/src/mame/drivers/pc.cpp
+++ b/src/mame/drivers/pc.cpp
@@ -31,10 +31,23 @@ Video: On board, Text mode 80x25 with 8x8 or 8x10 characters, CGA
Display: non-backlit LCD 640x256 pixels
Mass storage: 1/2x Floppy 3.5" 720K
On board Ports: Floppy, RTC, 1x RS232C + 1x RS232C/RS422 via 8251, speaker
-Options: ext. 5.25" Floppy, int. Bell 103A 300 Baud Modem, 8087 maths cpu
+Options: ext. 5.25" Floppy, int. Bell 103A 300 Baud Modem, 8087 FPU
Expansion: Expansion box, with 5 ISA slots and space for a 5.25" drive and a harddisk; specifically mentioned are the 5.25" drive, color graphics and memory expansion via ISA cards
+Bondwell BW230 (Pro28 series)
+=============
+Links: http://gallery.fdd5-25.net/details.php?image_id=3463&sessionid=1eaeb42abdf2758a020b16204a2a8e5a ; http://www.zonadepruebas.com/viewtopic.php?t=3696 ; ftp://ftp.whtech.com/emulators/mess/old/Complete%20MESS%20Geneve%20emulation/mess/sysinfo/bondwell.htm
+Info: Info is hard to come by. A BW230 is nowhere to be found, the links about the Pro28 series suggest an XT compatible built around a passive backplane and a slot CPU. This is confirmed by the old MESS info.
+Form Factor: Desktop
+CPU: 8088 @ 4.77 MHz (MESS sysinfo: 3.75)/ 8 MHz
+RAM: 512K / 640K
+Bus: at least 2x ISA: 1) CPU, RAM, Floppy controller
+ 2) Graphics, Game, Parallel
+Video: Hercules/CGA
+Mass storage: 1x 5.25" 360K and 20/30MB Harddisk.
+
+
Commodore PC-1
=============
Links: http://www.amiga-stuff.com/hardware/pc-i.html , http://www.zimmers.net/cbmpics/cpci.html
@@ -45,13 +58,13 @@ Bus: Proprietary expansion slot, carrying almost all ISA signals
Video: On board, MDA/Hercules/CGA
Mass storage: 1x 5.25" 360K
On board ports: Floppy, floppy expansion (for Amiga A1010/1011 (720 KB, 3.5") or A1020 (360 KB, 5.25" drives), speaker (but no speaker fitted), mouse,
-Options: 8087 maths CPU
+Options: 8087 FPU
Expansion: Expansion box: 2x ISA
Commodore PC-10 III
=============
-Links: http://dostalgie.de/downloads/pc10III-20III/PC10III_OM_COMMODORE_EN_DE.pdf
+Links: http://dostalgie.de/downloads/pc10III-20III/PC10III_OM_COMMODORE_EN_DE.pdf ; ftp://ftp.zimmers.net/pub/cbm-pc/documents/PC-8088-Information.txt
Info: PC10-III and PC20-III are the same machines - PC10 has two floppies, PC20 one floppy and one harddisk
Form Factor: Desktop
CPU: 8088 @ 4.77 MHz / 7.16 MHz / 9.54 MHz
@@ -60,12 +73,13 @@ Bus: 3x ISA
Video: On board: MDA/CGA/Hercules/Plantronics
Mass storage: 1x Floppy 5.25" 360K and (PC10) another 360K or (PC20) 3.5" harddisk
On board ports: Floppy, XT-IDE Harddisk, Mouse, serial, parallel, RTC, Speaker
-Options: 8087 maths CPU
+Options: 8087 FPU
Zenith SuperSport
=======================
-Links: http://www.focushacks.com/zenith/myzenith.html , http://retro-computing.blogspot.de/2006/08/zds-supersport-laptop.html
+Links: http://www.focushacks.com/zenith/myzenith.html , http://retro-computing.blogspot.de/2006/08/zds-supersport-laptop.html , http://www.minuszerodegrees.net/manuals/Zenith%20Data%20Systems/ZDS%20SupersPort%20-%20Service%20Manual.pdf
+ http://www.minuszerodegrees.net/manuals/Zenith%20Data%20Systems/ZDS%20SupersPort%20-%20User%20and%20Technical%20Manual.pdf
Info: ZWL-184 to distinguish it from the later 80286 based models
Form Factor: Laptop
CPU: 80C88 @ 4.77 MHz or 8 MHz
@@ -75,7 +89,7 @@ Video: CGA
Display: The second link has a picture of a working SuperSport. This shows the LCD display with a green background and blue text/graphics.
Mass storage: 1x 3.5" 720K floppy and 1x720K floppy or 20MB harddisk
On board ports: serial, parallel, ext. keyboard, ext. CGA video, ext. floppy
-Options: 2400 Baud Modem, 8087 maths CPU
+Options: 2400 Baud Modem, 8087 FPU
Siemens Sicomp PC16-05
@@ -91,7 +105,7 @@ Bus: 6x ISA: 1) MDA/Hercules/CGA and parallel port
Video: MDA/Hercules, exchangable via ISA-slot
Mass storage: 1x 5.25" 360K floppy and 1x 5.25" 360K floppy or MFM hard drive (10MB or 20MB)
On board ports: parallel, serial, beeper
-Options: 8087 maths cpu
+Options: 8087 FPU
NCR PC4i
@@ -113,12 +127,13 @@ Video: K510: 4KB Alpha for internal monitor; K511: 32KB Graphics for internal mo
Display: Mono or color CRT 640x400 pixel
Mass storage: 1x 5.25" 360K floppy and 1x 5.25" 360K floppy or 10 MB harddisk
On board ports: parallel, serial, speaker, floppy
-Options: 8087 maths CPU, K101 memory upgrade in 64K steps, 1.2MB floppy and controller board
+Options: 8087 FPU, K101 memory upgrade in 64K steps, 1.2MB floppy and controller board
Olivetti M15
============
-Links: http://www.1000bit.it/ad/bro/olivetti/olivettiM15.pdf , http://electrickery.xs4all.nl/comp/m15/ , http://electrickery.xs4all.nl/comp/m15/doc/M15_InstallationAndOperationsGuide.pdf
+Links: http://www.1000bit.it/ad/bro/olivetti/olivettiM15.pdf , http://electrickery.xs4all.nl/comp/m15/ , http://electrickery.xs4all.nl/comp/m15/doc/M15_InstallationAndOperationsGuide.pdf
+ http://www.museotecnologicamente.it/olivetti-m-15-1987/ , http://www.museotecnologicamente.it/wp-content/uploads/M15_Depliant_inglese.pdf
Info: The info brochure has a picture of a working M15. This shows the LCD display with a green background and blue text/graphics.
Form Factor: Laptop
CPU: 80C88 @ 4.77 MHz
@@ -165,8 +180,33 @@ Mass storage: 1 or 2 5.25" 360K floppies, MFM harddisk on hardcard or via sepera
On board ports: serial, parallel, floppy
-Atari PC-3
-=======================
+Atari PC1
+=========
+Links: http://www.ataripc.net/pc1-8088/ ; http://krap.pl/mirrorz/atari/www.atari-computermuseum.de/pc.htm ; http://www.atari-computermuseum.de/pc1.htm
+Form Factor: Desktop
+CPU: 8088 @ 4.77 MHz / 8 MHz
+RAM: 512K / 640KB
+Bus: ISA signals available on board, no slot
+Video: Hercules/CGA/EGA
+Mass storage: 1 5.25" 360K floppy
+On board ports: floppy, graphics, parallel, serial, mouse, external floppy
+Options: 8087 FPU
+Expansion: Up to two external floppy drives: PCF554, SF314 or SF354
+
+
+Atari PC2
+Links: http://www.binarydinosaurs.co.uk/Museum/atari/pc2.php ; http://www.ataripc.net/pc2-8088/ ; http://www.ataripc.net/components/
+Info: The Atari PC2 mainboard has only one ISA slot, but is expanded via a four slot riser card. BIOS is identical to later PC1 and PC3
+CPU: 8088 @ 4.77 MHz / 8 MHz
+RAM: 512K / 640KB
+Bus: 4x ISA
+Video: Hercules/CGA/EGA
+Mass storage: 1 5.25" 360K floppy and 1 5.25" 360K floppy or 20MB hard drive
+On board ports: floppy, graphics, parallel, serial, mouse
+Expansion: 8087 FPU
+
+Atari PC3
+=========
Links: http://www.atari-computermuseum.de/pc1.htm , http://trelohra.blogspot.de/2015/06/atari-pc3.html , http://www.ataripc.net/pc3-8088/
Form Factor: Desktop
CPU: 8088 @ 4.77 MHz or 8 MHz
@@ -175,7 +215,7 @@ Bus: 5x ISA: 1) Adaptec ACB-2072 RLL Controller Card
Video: On-board MDA/CGA/Hercules/EGA
Mass storage: 1x 5.25" 360K floppy + 30MB RLL harddisk
On board ports: floppy, parallel, serial, mouse, speaker
-Options: 8087 maths CPU
+Options: 8087 FPU
Eagle 1600
@@ -197,7 +237,7 @@ Bus: 8xISA: 1) SASI board, connects to a XEBEC Sl410 SASI => MFM bridge board
8) Parallel board
Video: 80x25 text mode, 720x352 pixel graphics mode
Mass storage: 1x 5.25" QD 780K floppy and 1x 5.25" QD 820K floppy or 10/30MB MFM harddisk
-Options: 8087 maths CPU, EagleNet File server, EightPort serial card, High Resolution color board and video, Video Cassette Adapter board for 80MB backup on video cassette
+Options: 8087 FPU, EagleNet File server, EightPort serial card, High Resolution color board and video, Video Cassette Adapter board for 80MB backup on video cassette
VTech Laser Turbo XT
=======================
@@ -211,7 +251,7 @@ Bus: 8xISA: 1) Monochrome graphics/color graphics card
Video: MDA/CGA/Hercules
Mass storage: 2x 5.25" 360K floppies and 1 or 2 harddisks (20MB / 30MB / 40MB)
On board ports: speaker
-Options: 8087 maths CPU
+Options: 8087 FPU
VTech Laser XT/3
=======================
@@ -225,7 +265,7 @@ Bus: 8x ISA: 1) Monochrome graphics/color graphics card http://th99.classic-comp
Video: MDA/Hercules/CGA
Mass storage: 2x 5.25" 360K or 1x 5.25" 360K and 1x 3.5" 720K, additional harddisk optional
On board ports: speaker
-Options: 8087 maths CPU
+Options: 8087 FPU
***************************************************************************/
@@ -343,22 +383,11 @@ static INPUT_PORTS_START( pccga )
PORT_BIT( 0x01, 0x01, IPT_UNUSED )
INPUT_PORTS_END
-static INPUT_PORTS_START( bondwell )
- PORT_INCLUDE(pccga)
-
- PORT_MODIFY("DSW2") /* IN3 */
- PORT_DIPNAME( 0x02, 0x02, "Turbo Switch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pc_state, pc_turbo_callback, 0)
- PORT_DIPSETTING( 0x00, "Off (4.77 MHz)" )
- PORT_DIPSETTING( 0x02, "On (12 MHz)" )
-INPUT_PORTS_END
static DEVICE_INPUT_DEFAULTS_START( pccga )
DEVICE_INPUT_DEFAULTS("DSW0", 0x30, 0x20)
DEVICE_INPUT_DEFAULTS_END
-static DEVICE_INPUT_DEFAULTS_START( siemens )
- DEVICE_INPUT_DEFAULTS("DSW0", 0x30, 0x30)
-DEVICE_INPUT_DEFAULTS_END
#define MCFG_CPU_PC(mem, port, type, clock) \
MCFG_CPU_ADD("maincpu", type, clock) \
@@ -366,6 +395,7 @@ DEVICE_INPUT_DEFAULTS_END
MCFG_CPU_IO_MAP(port##_io) \
MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("mb:pic8259", pic8259_device, inta_cb)
+
static MACHINE_CONFIG_START( pccga, pc_state )
/* basic machine hardware */
MCFG_CPU_PC(pc8, pc8, I8088, 4772720) /* 4,77 MHz */
@@ -377,6 +407,7 @@ static MACHINE_CONFIG_START( pccga, pc_state )
MCFG_ISA8_SLOT_ADD("mb:isa", "isa2", pc_isa8_cards, "fdc_xt", false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa3", pc_isa8_cards, "lpt", false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa4", pc_isa8_cards, "com", false)
+ MCFG_ISA8_SLOT_ADD("mb:isa", "isa5", pc_isa8_cards, nullptr, false)
/* keyboard */
MCFG_PC_KBDC_SLOT_ADD("mb:pc_kbdc", "kbd", pc_xt_keyboards, STR_KBD_IBM_PC_XT_83)
@@ -389,31 +420,46 @@ static MACHINE_CONFIG_START( pccga, pc_state )
MCFG_SOFTWARE_LIST_ADD("disk_list","ibm5150")
MACHINE_CONFIG_END
-static MACHINE_CONFIG_START( ncrpc4i, pc_state )
- /* basic machine hardware */
- MCFG_CPU_PC(pc8, pc8, I8088, 4772720) /* 4,77 MHz */
- MCFG_IBM5160_MOTHERBOARD_ADD("mb", "maincpu")
- MCFG_DEVICE_INPUT_DEFAULTS(pccga)
+static MACHINE_CONFIG_FRAGMENT( cfg_dual_720K )
+ MCFG_DEVICE_MODIFY("fdc:0")
+ MCFG_SLOT_DEFAULT_OPTION("35dd")
+ MCFG_DEVICE_MODIFY("fdc:1")
+ MCFG_SLOT_DEFAULT_OPTION("35dd")
+MACHINE_CONFIG_END
- MCFG_ISA8_SLOT_ADD("mb:isa", "isa1", pc_isa8_cards, "cga", false)
- MCFG_ISA8_SLOT_ADD("mb:isa", "isa2", pc_isa8_cards, "fdc_xt", false)
- MCFG_ISA8_SLOT_ADD("mb:isa", "isa3", pc_isa8_cards, "lpt", false)
- MCFG_ISA8_SLOT_ADD("mb:isa", "isa4", pc_isa8_cards, "com", false)
- MCFG_ISA8_SLOT_ADD("mb:isa", "isa5", pc_isa8_cards, nullptr, false)
- MCFG_ISA8_SLOT_ADD("mb:isa", "isa6", pc_isa8_cards, nullptr, false)
- MCFG_ISA8_SLOT_ADD("mb:isa", "isa7", pc_isa8_cards, nullptr, false)
+static MACHINE_CONFIG_FRAGMENT( cfg_single_360K )
+ MCFG_DEVICE_MODIFY("fdc:0")
+ MCFG_SLOT_DEFAULT_OPTION("525dd")
+ MCFG_SLOT_FIXED(true)
+ MCFG_DEVICE_REMOVE("fdc:1")
+MACHINE_CONFIG_END
- /* keyboard */
- MCFG_PC_KBDC_SLOT_ADD("mb:pc_kbdc", "kbd", pc_xt_keyboards, STR_KBD_IBM_PC_XT_83)
- /* internal ram */
- MCFG_RAM_ADD(RAM_TAG)
- MCFG_RAM_DEFAULT_SIZE("640K")
- MCFG_RAM_EXTRA_OPTIONS("64K, 128K, 256K, 512K")
- /* software lists */
+//Data General One
+static MACHINE_CONFIG_DERIVED( dgone, pccga )
+ MCFG_DEVICE_MODIFY("isa2")
+ MCFG_SLOT_OPTION_MACHINE_CONFIG("fdc_xt", cfg_dual_720K)
+MACHINE_CONFIG_END
+
+
+// Bondwell BW230
+static INPUT_PORTS_START( bondwell )
+ PORT_INCLUDE(pccga)
+
+ PORT_MODIFY("DSW2") /* IN3 */
+ PORT_DIPNAME( 0x02, 0x02, "Turbo Switch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pc_state, pc_turbo_callback, 0)
+ PORT_DIPSETTING( 0x00, "Off (4.77 MHz)" )
+ PORT_DIPSETTING( 0x02, "On (12 MHz)" )
+INPUT_PORTS_END
+
+static MACHINE_CONFIG_DERIVED(bondwell, pccga)
+ MCFG_DEVICE_REMOVE("maincpu")
+ MCFG_CPU_PC(pc8, pc8, I8088, 4772720) // turbo?
MACHINE_CONFIG_END
+
+// Schetmash Iskra-3104
static DEVICE_INPUT_DEFAULTS_START( iskr3104 )
DEVICE_INPUT_DEFAULTS("DSW0", 0x30, 0x00)
DEVICE_INPUT_DEFAULTS_END
@@ -441,6 +487,7 @@ static MACHINE_CONFIG_START( iskr3104, pc_state )
MACHINE_CONFIG_END
+//Poisk-2
static MACHINE_CONFIG_START( poisk2, pc_state )
/* basic machine hardware */
MCFG_CPU_PC(pc16, pc16, I8086, 4772720)
@@ -461,6 +508,15 @@ static MACHINE_CONFIG_START( poisk2, pc_state )
MCFG_RAM_EXTRA_OPTIONS("64K, 128K, 256K, 512K")
MACHINE_CONFIG_END
+
+//MK-88
+static MACHINE_CONFIG_DERIVED(mk88, poisk2)
+ MCFG_DEVICE_MODIFY("isa1")
+ MCFG_SLOT_DEFAULT_OPTION("cga_ec1841")
+MACHINE_CONFIG_END
+
+
+// Zenith SuperSport
static MACHINE_CONFIG_START( zenith, pc_state )
/* basic machine hardware */
MCFG_CPU_PC(zenith, pc8, I8088, XTAL_14_31818MHz/3) /* 4,77 MHz */
@@ -470,6 +526,7 @@ static MACHINE_CONFIG_START( zenith, pc_state )
MCFG_ISA8_SLOT_ADD("mb:isa", "isa1", pc_isa8_cards, "cga", false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa2", pc_isa8_cards, "fdc_xt", false)
+ MCFG_SLOT_OPTION_MACHINE_CONFIG("fdc_xt", cfg_dual_720K)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa3", pc_isa8_cards, "lpt", false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa4", pc_isa8_cards, "com", false)
@@ -485,6 +542,22 @@ static MACHINE_CONFIG_START( zenith, pc_state )
MACHINE_CONFIG_END
+//NCR PC4i
+static MACHINE_CONFIG_DERIVED ( ncrpc4i, pccga )
+ //MCFG_DEVICE_MODIFY("mb:isa")
+ MCFG_ISA8_SLOT_ADD("mb:isa", "isa6", pc_isa8_cards, nullptr, false)
+ MCFG_ISA8_SLOT_ADD("mb:isa", "isa7", pc_isa8_cards, nullptr, false)
+
+ MCFG_DEVICE_MODIFY(RAM_TAG)
+ MCFG_RAM_DEFAULT_SIZE("640K")
+ MCFG_RAM_EXTRA_OPTIONS("64K, 128K, 256K, 512K")
+MACHINE_CONFIG_END
+
+
+// Siemens Sicomp PC16-05
+static DEVICE_INPUT_DEFAULTS_START( siemens )
+ DEVICE_INPUT_DEFAULTS("DSW0", 0x30, 0x30)
+DEVICE_INPUT_DEFAULTS_END
static MACHINE_CONFIG_START( siemens, pc_state )
/* basic machine hardware */
@@ -509,6 +582,8 @@ static MACHINE_CONFIG_START( siemens, pc_state )
MACHINE_CONFIG_END
+
+// IBM 5550
static MACHINE_CONFIG_START( ibm5550, pc_state )
/* basic machine hardware */
MCFG_CPU_PC(pc16, ibm5550, I8086, 8000000)
@@ -529,21 +604,8 @@ static MACHINE_CONFIG_START( ibm5550, pc_state )
MCFG_RAM_EXTRA_OPTIONS("64K, 128K, 256K, 512K")
MACHINE_CONFIG_END
-static MACHINE_CONFIG_DERIVED(bondwell, pccga)
- MCFG_DEVICE_REMOVE("maincpu")
- MCFG_CPU_PC(pc8, pc8, I8088, 4772720) // turbo?
-MACHINE_CONFIG_END
-
-static MACHINE_CONFIG_DERIVED(mk88, poisk2)
- MCFG_DEVICE_MODIFY("isa1")
- MCFG_SLOT_DEFAULT_OPTION("cga_ec1841")
-MACHINE_CONFIG_END
-
-static MACHINE_CONFIG_DERIVED(eagle1600, pccga)
- MCFG_DEVICE_REMOVE("maincpu")
- MCFG_CPU_PC(pc16, pc16, I8086, 8000000)
-MACHINE_CONFIG_END
+// Olivetti M15
static DEVICE_INPUT_DEFAULTS_START( m15 )
DEVICE_INPUT_DEFAULTS("DSW0", 0x30, 0x20) // TODO: document correct dip settings
DEVICE_INPUT_DEFAULTS("DSW0", 0x01, 0x00)
@@ -552,12 +614,32 @@ DEVICE_INPUT_DEFAULTS_END
static MACHINE_CONFIG_DERIVED(m15, pccga)
MCFG_DEVICE_MODIFY("mb")
MCFG_DEVICE_INPUT_DEFAULTS(m15)
+ MCFG_DEVICE_MODIFY("isa2")
+ MCFG_SLOT_OPTION_MACHINE_CONFIG("fdc_xt", cfg_dual_720K)
MCFG_DEVICE_MODIFY(RAM_TAG)
MCFG_RAM_DEFAULT_SIZE("448K")
MCFG_RAM_EXTRA_OPTIONS("16K, 160K, 304K")
MACHINE_CONFIG_END
-static MACHINE_CONFIG_START( laser_turbo_xt, pc_state )
+
+// Atari PC1
+static MACHINE_CONFIG_DERIVED(ataripc1, pccga)
+ MCFG_DEVICE_MODIFY("isa1")
+ MCFG_SLOT_DEFAULT_OPTION("ega")
+ MCFG_DEVICE_MODIFY("isa2")
+ MCFG_SLOT_OPTION_MACHINE_CONFIG("fdc_xt", cfg_single_360K)
+MACHINE_CONFIG_END
+
+
+//Eagle 1600
+static MACHINE_CONFIG_DERIVED(eagle1600, pccga)
+ MCFG_DEVICE_REMOVE("maincpu")
+ MCFG_CPU_PC(pc16, pc16, I8086, 8000000)
+MACHINE_CONFIG_END
+
+
+//Laser XT/3
+static MACHINE_CONFIG_START( laser_xt3, pc_state )
MCFG_CPU_PC(pc8, pc8, I8088, XTAL_14_31818MHz/3) /* 4,77 MHz */
MCFG_IBM5160_MOTHERBOARD_ADD("mb","maincpu")
@@ -565,7 +647,7 @@ static MACHINE_CONFIG_START( laser_turbo_xt, pc_state )
MCFG_ISA8_SLOT_ADD("mb:isa", "isa1", pc_isa8_cards, "cga", false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa2", pc_isa8_cards, "com", false) // Multi I/O card (includes FDC)
- MCFG_ISA8_SLOT_ADD("mb:isa", "isa3", pc_isa8_cards, "fdc_xt", false)
+ MCFG_ISA8_SLOT_ADD("mb:isa", "isa3", pc_isa8_cards, "fdc_xt", false) // floppy drive A is 5.25" 360K and B is 3.5" 720K
MCFG_ISA8_SLOT_ADD("mb:isa", "isa4", pc_isa8_cards, nullptr, false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa5", pc_isa8_cards, nullptr, false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa6", pc_isa8_cards, nullptr, false)
@@ -578,13 +660,15 @@ static MACHINE_CONFIG_START( laser_turbo_xt, pc_state )
/* internal ram */
MCFG_RAM_ADD(RAM_TAG)
MCFG_RAM_DEFAULT_SIZE("640K")
- MCFG_RAM_EXTRA_OPTIONS("512K,768K,896K,1024K,1408K,1536K,1664K")
+ MCFG_RAM_EXTRA_OPTIONS("512K,1024K,1536K,1664K")
/* software lists */
MCFG_SOFTWARE_LIST_ADD("disk_list","ibm5150")
MACHINE_CONFIG_END
-static MACHINE_CONFIG_START( laser_xt3, pc_state )
+
+//Laser Turbo XT
+static MACHINE_CONFIG_START( laser_turbo_xt, pc_state )
MCFG_CPU_PC(pc8, pc8, I8088, XTAL_14_31818MHz/3) /* 4,77 MHz */
MCFG_IBM5160_MOTHERBOARD_ADD("mb","maincpu")
@@ -592,7 +676,7 @@ static MACHINE_CONFIG_START( laser_xt3, pc_state )
MCFG_ISA8_SLOT_ADD("mb:isa", "isa1", pc_isa8_cards, "cga", false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa2", pc_isa8_cards, "com", false) // Multi I/O card (includes FDC)
- MCFG_ISA8_SLOT_ADD("mb:isa", "isa3", pc_isa8_cards, "fdc_xt", false) // floppy drive A is 5.25" 360K and B is 3.5" 720K
+ MCFG_ISA8_SLOT_ADD("mb:isa", "isa3", pc_isa8_cards, "fdc_xt", false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa4", pc_isa8_cards, nullptr, false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa5", pc_isa8_cards, nullptr, false)
MCFG_ISA8_SLOT_ADD("mb:isa", "isa6", pc_isa8_cards, nullptr, false)
@@ -605,44 +689,63 @@ static MACHINE_CONFIG_START( laser_xt3, pc_state )
/* internal ram */
MCFG_RAM_ADD(RAM_TAG)
MCFG_RAM_DEFAULT_SIZE("640K")
- MCFG_RAM_EXTRA_OPTIONS("512K,1024K,1536K,1664K")
+ MCFG_RAM_EXTRA_OPTIONS("512K,768K,896K,1024K,1408K,1536K,1664K")
/* software lists */
MCFG_SOFTWARE_LIST_ADD("disk_list","ibm5150")
MACHINE_CONFIG_END
-ROM_START( bw230 )
- ROM_REGION(0x10000,"bios", 0)
- ROM_LOAD("bondwell.bin", 0xe000, 0x2000, CRC(d435a405) SHA1(a57c705d1144c7b61940b6f5c05d785c272fc9bb))
-ROM_END
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
-ROM_START( sicpc1605 )
+ROM_START( dgone )
ROM_REGION(0x10000,"bios", 0)
- ROM_LOAD("multitech pc-700 3.1.bin", 0xe000, 0x2000, CRC(0ac7a2e1) SHA1(b9c8504e21213d81a068dde9f51f9c973d726e7b))
+ ROM_LOAD( "dgone.bin", 0x8000, 0x08000, CRC(2c38c86e) SHA1(c0f85a000d1d13cd354965689e925d677822549e))
ROM_END
-ROM_START( ncrpc4i )
+ROM_START( bw230 )
ROM_REGION(0x10000,"bios", 0)
- ROM_LOAD( "ncr_pc4i_biosrom_1985.bin",0xc000, 0x4000, CRC(b9732648) SHA1(0d5d96fbc36089ca4d893b0db84faffa8043a5e4))
+ ROM_LOAD("bondwell.bin", 0xe000, 0x2000, CRC(d435a405) SHA1(a57c705d1144c7b61940b6f5c05d785c272fc9bb))
ROM_END
-ROM_START( zdsupers )
- ROM_REGION(0x10000,"bios", 0)
- ROM_SYSTEM_BIOS( 0, "v31d", "v3.1d" )
- ROMX_LOAD( "z184m v3.1d.10d", 0x8000, 0x8000, CRC(44012c3b) SHA1(f2f28979798874386ca8ba3dd3ead24ae7c2aeb4), ROM_BIOS(1))
- ROM_SYSTEM_BIOS( 1, "v29e", "v2.9e" )
- ROMX_LOAD( "z184m v2.9e.10d", 0x8000, 0x8000, CRC(de2f200b) SHA1(ad5ce601669a82351e412fc6c1c70c47779a1e55), ROM_BIOS(2))
+ROM_START( compc1 )
+ ROM_REGION(0x10000, "bios", 0)
+ ROM_LOAD("pc1_bios.bin", 0xc000, 0x4000, CRC(e37367c8) SHA1(9aac9c38b4ebdb9a740e393199c2eff75a0bde03))
+ ROM_REGION(0x8000, "gfx1", 0)
+ ROM_LOAD("pc1_char.bin", 0x0000, 0x4000, CRC(ee6c27f0) SHA1(e769cc3a49a1d708bd74eb4ac85bb6ea67220d38))
ROM_END
-
-ROM_START( dgone )
- ROM_REGION(0x10000,"bios", 0)
- ROM_LOAD( "dgone.bin", 0x8000, 0x08000, CRC(2c38c86e) SHA1(c0f85a000d1d13cd354965689e925d677822549e))
+// Note: Commodore PC20-III, PC10-III and COLT share the same BIOS
+ROM_START( pc10iii )
+ ROM_REGION(0x10000, "bios", 0)
+ ROM_DEFAULT_BIOS("v441")
+ ROM_SYSTEM_BIOS(0, "v435", "v4.35")
+ ROMX_LOAD("318085-01.u201", 0x8000, 0x8000, CRC(be752d1e) SHA1(5e5e63cd6d6269816cd691602e4c4d209fe3df67), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(1, "v436", "v4.36")
+ ROMX_LOAD("318085-02.u201", 0x8000, 0x8000, NO_DUMP, ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(2, "v436c", "v4.36c")
+ ROMX_LOAD("318085-04.u201", 0x8000, 0x8000, NO_DUMP, ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(3, "v438", "v4.38")
+ ROMX_LOAD("318085-05.u201", 0x8000, 0x8000, CRC(ae9e6a31) SHA1(853ee251cf230818c407a8d13ef060a21c90a8c1), ROM_BIOS(4))
+ ROM_SYSTEM_BIOS(4, "v439", "v4.39")
+ ROMX_LOAD("318085-06.u201", 0x8000, 0x8000, NO_DUMP, ROM_BIOS(5))
+ ROM_SYSTEM_BIOS(5, "v440", "v4.40")
+ ROMX_LOAD("318085-07.u201", 0x8000, 0x8000, NO_DUMP, ROM_BIOS(6))
+ ROM_SYSTEM_BIOS(6, "v441", "v4.41")
+ ROMX_LOAD("318085-08.u201", 0x8000, 0x8000, CRC(7e228dc8) SHA1(958dfdd637bd31c01b949fac729d6973a7e630bc), ROM_BIOS(7))
+ ROM_REGION(0x8000, "gfx1", 0)
+ ROM_LOAD("318086-02.u607", 0x0000, 0x8000, CRC(b406651c) SHA1(856f58353391a74a06ebb8ec9f8333d7d69e5fd6))
+ //ROM_LOAD("5788005.u33", 0x00000, 0x2000, BAD_DUMP CRC(0bf56d70) SHA1(c2a8b10808bf51a3c123ba3eb1e9dd608231916f)) /* temp so you can read the text */
ROM_END
-ROM_START( ssam88s )
- ROM_REGION(0x10000,"bios", 0)
- ROM_LOAD( "samsung_samtron_88s_vers_2.0a.bin", 0x8000, 0x08000, CRC(d1252a91) SHA1(469d15b6ecd7b70234975dc12c6bda4212a66652))
+ROM_START( iskr3104 )
+ ROM_REGION16_LE(0x10000,"bios", 0)
+ ROMX_LOAD( "198.bin", 0xc000, 0x2000, CRC(bcfd8e41) SHA1(e21ddf78839aa51fa5feb23f511ff5e2da31b433),ROM_SKIP(1))
+ ROMX_LOAD( "199.bin", 0xc001, 0x2000, CRC(2da5fe79) SHA1(14d5dccc141a0b3367f7f8a7188306fdf03c2b6c),ROM_SKIP(1))
+ // EGA card from Iskra-3104
+ //ROMX_LOAD( "143-03.bin", 0xc0001, 0x2000, CRC(d0706345) SHA1(e04bb40d944426a4ae2e3a614d3f4953d7132ede),ROM_SKIP(1))
+ //ROMX_LOAD( "143-02.bin", 0xc0000, 0x2000, CRC(c8c18ebb) SHA1(fd6dac76d43ab8b582e70f1d5cc931d679036fb9),ROM_SKIP(1))
ROM_END
ROM_START( mk88 )
@@ -659,15 +762,6 @@ ROM_START( mk88 )
ROMX_LOAD( "b88.bin", 0xe000, 0x2000, CRC(58a418df) SHA1(216398d4e4302ee7efcc2c8f9ff9d8a1161229ea), ROM_BIOS(3))
ROM_END
-ROM_START( iskr3104 )
- ROM_REGION16_LE(0x10000,"bios", 0)
- ROMX_LOAD( "198.bin", 0xc000, 0x2000, CRC(bcfd8e41) SHA1(e21ddf78839aa51fa5feb23f511ff5e2da31b433),ROM_SKIP(1))
- ROMX_LOAD( "199.bin", 0xc001, 0x2000, CRC(2da5fe79) SHA1(14d5dccc141a0b3367f7f8a7188306fdf03c2b6c),ROM_SKIP(1))
- // EGA card from Iskra-3104
- //ROMX_LOAD( "143-03.bin", 0xc0001, 0x2000, CRC(d0706345) SHA1(e04bb40d944426a4ae2e3a614d3f4953d7132ede),ROM_SKIP(1))
- //ROMX_LOAD( "143-02.bin", 0xc0000, 0x2000, CRC(c8c18ebb) SHA1(fd6dac76d43ab8b582e70f1d5cc931d679036fb9),ROM_SKIP(1))
-ROM_END
-
ROM_START( poisk2 )
ROM_REGION16_LE(0x10000,"bios", 0)
ROM_SYSTEM_BIOS(0, "v20", "v2.0")
@@ -697,6 +791,29 @@ ROM_START( mc1702 )
ROM_LOAD( "ba1m_(573rf5).rom", 0x0000, 0x0800, CRC(08d938e8) SHA1(957b6c691dbef75c1c735e8e4e81669d056971e4))
ROM_END
+ROM_START( zdsupers )
+ ROM_REGION(0x10000,"bios", 0)
+ ROM_SYSTEM_BIOS( 0, "v31d", "v3.1d" )
+ ROMX_LOAD( "z184m v3.1d.10d", 0x8000, 0x8000, CRC(44012c3b) SHA1(f2f28979798874386ca8ba3dd3ead24ae7c2aeb4), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS( 1, "v29e", "v2.9e" )
+ ROMX_LOAD( "z184m v2.9e.10d", 0x8000, 0x8000, CRC(de2f200b) SHA1(ad5ce601669a82351e412fc6c1c70c47779a1e55), ROM_BIOS(2))
+ROM_END
+
+ROM_START( sicpc1605 )
+ ROM_REGION(0x10000,"bios", 0)
+ ROM_LOAD("multitech pc-700 3.1.bin", 0xe000, 0x2000, CRC(0ac7a2e1) SHA1(b9c8504e21213d81a068dde9f51f9c973d726e7b))
+ROM_END
+
+ROM_START( ncrpc4i )
+ ROM_REGION(0x10000,"bios", 0)
+ ROM_LOAD( "ncr_pc4i_biosrom_1985.bin",0xc000, 0x4000, CRC(b9732648) SHA1(0d5d96fbc36089ca4d893b0db84faffa8043a5e4))
+ROM_END
+
+ROM_START( olivm15 )
+ ROM_REGION(0x10000,"bios", 0)
+ ROM_LOAD( "oliv_m15.bin",0xc000, 0x04000, CRC(bf2ef795) SHA1(02d497131f5ca2c78f2accd38ab0eab6813e3ebf))
+ROM_END
+
ROM_START( ibm5550 )
ROM_REGION16_LE(0x10000,"bios", 0)
ROM_LOAD( "ipl5550.rom", 0xc000, 0x4000, CRC(40cf34c9) SHA1(d41f77fdfa787b0e97ed311e1c084b8699a5b197))
@@ -708,47 +825,11 @@ ROM_START( pc7000 )
ROMX_LOAD( "mitsubishi-m5l27128k-2.bin", 0x8001, 0x4000, CRC(99b229a4) SHA1(5800c8bafed26873d8cfcc79a05f93a780a31c91), ROM_SKIP(1))
ROM_END
-ROM_START( olivm15 )
- ROM_REGION(0x10000,"bios", 0)
- ROM_LOAD( "oliv_m15.bin",0xc000, 0x04000, CRC(bf2ef795) SHA1(02d497131f5ca2c78f2accd38ab0eab6813e3ebf))
-ROM_END
-
ROM_START( sx16 )
ROM_REGION(0x10000,"bios", 0)
ROM_LOAD( "tmm27128ad.bin",0xc000, 0x4000, CRC(f8543362) SHA1(fef625e260ca89ba02174584bdc12db609f0780e))
ROM_END
-ROM_START( compc1 )
- ROM_REGION(0x10000, "bios", 0)
- ROM_LOAD("pc1_bios.bin", 0xc000, 0x4000, CRC(e37367c8) SHA1(9aac9c38b4ebdb9a740e393199c2eff75a0bde03))
- ROM_REGION(0x8000, "gfx1", 0)
- ROM_LOAD("pc1_char.bin", 0x0000, 0x4000, CRC(ee6c27f0) SHA1(e769cc3a49a1d708bd74eb4ac85bb6ea67220d38))
-ROM_END
-
-
-// Note: Commodore PC20-III, PC10-III and COLT share the same BIOS
-ROM_START( pc10iii )
- ROM_REGION(0x10000, "bios", 0)
- ROM_DEFAULT_BIOS("v441")
- ROM_SYSTEM_BIOS(0, "v435", "v4.35")
- ROMX_LOAD("318085-01.u201", 0x8000, 0x8000, CRC(be752d1e) SHA1(5e5e63cd6d6269816cd691602e4c4d209fe3df67), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(1, "v436", "v4.36")
- ROMX_LOAD("318085-02.u201", 0x8000, 0x8000, NO_DUMP, ROM_BIOS(2))
- ROM_SYSTEM_BIOS(2, "v436c", "v4.36c")
- ROMX_LOAD("318085-04.u201", 0x8000, 0x8000, NO_DUMP, ROM_BIOS(3))
- ROM_SYSTEM_BIOS(3, "v438", "v4.38")
- ROMX_LOAD("318085-05.u201", 0x8000, 0x8000, CRC(ae9e6a31) SHA1(853ee251cf230818c407a8d13ef060a21c90a8c1), ROM_BIOS(4))
- ROM_SYSTEM_BIOS(4, "v439", "v4.39")
- ROMX_LOAD("318085-06.u201", 0x8000, 0x8000, NO_DUMP, ROM_BIOS(5))
- ROM_SYSTEM_BIOS(5, "v440", "v4.40")
- ROMX_LOAD("318085-07.u201", 0x8000, 0x8000, NO_DUMP, ROM_BIOS(6))
- ROM_SYSTEM_BIOS(6, "v441", "v4.41")
- ROMX_LOAD("318085-08.u201", 0x8000, 0x8000, CRC(7e228dc8) SHA1(958dfdd637bd31c01b949fac729d6973a7e630bc), ROM_BIOS(7))
- ROM_REGION(0x8000, "gfx1", 0)
- ROM_LOAD("318086-02.u607", 0x0000, 0x8000, CRC(b406651c) SHA1(856f58353391a74a06ebb8ec9f8333d7d69e5fd6))
- //ROM_LOAD("5788005.u33", 0x00000, 0x2000, BAD_DUMP CRC(0bf56d70) SHA1(c2a8b10808bf51a3c123ba3eb1e9dd608231916f)) /* temp so you can read the text */
-ROM_END
-
ROM_START( mbc16 )
ROM_REGION(0x10000,"bios", 0)
ROM_LOAD( "mbc16.bin", 0xc000, 0x4000, CRC(f3e0934a) SHA1(e4b91c3d395be0414e20f23ad4919b8ac52639b2))
@@ -757,6 +838,14 @@ ROM_START( mbc16 )
ROM_LOAD( "atigssr.bin", 0x0000, 0x2000, CRC(aca81498) SHA1(0d84c89487ee7a6ac4c9e73fdb30c5fd8aa595f8))
ROM_END
+ROM_START ( ataripc1 )
+ ROM_REGION(0x10000,"bios", 0)
+ ROM_SYSTEM_BIOS( 0, "v3.06", "v3.06" )
+ ROMX_LOAD( "award_atari_pc_bios_3.06.bin", 0x8000, 0x8000, CRC(256427ce) SHA1(999f6af64b79f88c1d3492f386d9bee08efb50e7), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS( 1, "v3.08", "v3.08" )
+ ROMX_LOAD( "award_atari_pc_bios_3.08.bin", 0x8000, 0x8000, CRC(929a2443) SHA1(8e98f3c9180c55b1f5521727779c016083d27960), ROM_BIOS(2)) //same as on Atari PC3, also used on Atari PC2
+ROM_END
+
ROM_START( ataripc3 )
ROM_REGION(0x10000,"bios", 0)
ROM_LOAD( "c101701-004 308.u61",0x8000, 0x8000, CRC(929a2443) SHA1(8e98f3c9180c55b1f5521727779c016083d27960))
@@ -768,6 +857,11 @@ ROM_START( ataripc3 )
ROM_LOAD( "c101681 6ffb.u60",0x000, 0x100, NO_DUMP ) // PAL20L10NC
ROM_END
+ROM_START( ssam88s )
+ ROM_REGION(0x10000,"bios", 0)
+ ROM_LOAD( "samsung_samtron_88s_vers_2.0a.bin", 0x8000, 0x08000, CRC(d1252a91) SHA1(469d15b6ecd7b70234975dc12c6bda4212a66652))
+ROM_END
+
ROM_START( eagle1600 )
ROM_REGION(0x10000,"bios", 0)
ROMX_LOAD( "eagle 1600 62-2732-001 rev e u403.bin",0xe000, 0x1000, CRC(3da1e96a) SHA1(77861ba5ebd056da1daf048f5abd459e0528666d), ROM_SKIP(1))
@@ -777,12 +871,12 @@ ROM_START( eagle1600 )
ROM_LOAD("eagle 1600 video char gen u301.bin", 0x00000, 0x1000, CRC(1a7e552f) SHA1(749058783eec9d96a70dc5fdbfccb56196f889dc))
ROM_END
-ROM_START(laser_turbo_xt)
+ROM_START( laser_turbo_xt )
ROM_REGION(0x10000, "bios", 0)
ROM_LOAD("laser_turbo_xt.bin", 0x0e000, 0x02000, CRC(0a6121d3) SHA1(59b1f8dd6fe981ef9a7700adebf6e1adda7cee90)) // version 1.11 - 27c64d
ROM_END
-ROM_START(laser_xt3)
+ROM_START( laser_xt3 )
ROM_REGION(0x10000, "bios", 0)
ROM_LOAD("laser_xt3.bin", 0x0e000, 0x02000, CRC(b45a7dd3) SHA1(62f17c408be0036d00a182e94c5c88b83d46b625)) // version 1.26 - 27c64
ROM_END
@@ -794,34 +888,26 @@ ROM_END
***************************************************************************/
-/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
-COMP( 1984, dgone, ibm5150, 0, pccga, pccga, driver_device, 0, "Data General", "Data General/One" , MACHINE_NOT_WORKING)/* CGA, 2x 3.5" disk drives */
-COMP( 1985, bw230, ibm5150, 0, bondwell, bondwell, pc_state, bondwell, "Bondwell Holding", "BW230 (PRO28 Series)", 0 )
-COMP( 1984, compc1, ibm5150, 0, pccga, pccga, driver_device, 0, "Commodore Business Machines", "Commodore PC-1" , MACHINE_NOT_WORKING)
-COMP( 1987, pc10iii, ibm5150, 0, pccga, pccga, driver_device, 0, "Commodore Business Machines", "Commodore PC-10 III" , MACHINE_NOT_WORKING)
-
-
-COMP( 1992, iskr3104, ibm5150, 0, iskr3104, pccga, driver_device, 0, "Schetmash", "Iskra 3104", MACHINE_NOT_WORKING)
-COMP( 1989, mk88, ibm5150, 0, mk88, pccga, driver_device, 0, "<unknown>", "MK-88", MACHINE_NOT_WORKING)
-COMP( 1991, poisk2, ibm5150, 0, poisk2, pccga, driver_device, 0, "<unknown>", "Poisk-2", MACHINE_NOT_WORKING)
-COMP( 1990, mc1702, ibm5150, 0, pccga, pccga, driver_device, 0, "<unknown>", "Elektronika MC-1702", MACHINE_NOT_WORKING)
-
-COMP( 1987, zdsupers, ibm5150, 0, zenith, pccga, driver_device, 0, "Zenith Data Systems", "SuperSport", 0)
-COMP( 1985, sicpc1605, ibm5150, 0, siemens, pccga, driver_device, 0, "Siemens", "Sicomp PC16-05", MACHINE_NOT_WORKING)
-COMP( 1985, ncrpc4i, ibm5150, 0, ncrpc4i, pccga, driver_device, 0, "NCR","PC4i", MACHINE_NOT_WORKING)
-
-COMP( 198?, olivm15, ibm5150, 0, m15, pccga, driver_device, 0, "Olivetti", "M15", 0)
-
-COMP( 1983, ibm5550, ibm5150, 0, ibm5550, pccga, driver_device, 0, "International Business Machines", "IBM 5550", MACHINE_NOT_WORKING)
-
-COMP( 1985, pc7000, ibm5150, 0, pccga, pccga, driver_device, 0, "Sharp", "PC-7000", MACHINE_NOT_WORKING)
-
-COMP( 1988, sx16, ibm5150, 0, pccga, pccga, driver_device, 0, "Sanyo", "SX-16", MACHINE_NOT_WORKING)
-COMP( 198?, mbc16, ibm5150, 0, pccga, pccga, driver_device, 0, "Sanyo", "MBC-16" , MACHINE_NOT_WORKING)
-
-COMP( 198?, ataripc3, ibm5150, 0, pccga, pccga, driver_device, 0, "Atari", "PC-3" , 0)
-COMP( 1989, ssam88s, ibm5150, 0, pccga, pccga, driver_device, 0, "Samsung", "Samtron 88S" , MACHINE_NOT_WORKING)
-COMP( 1983, eagle1600, ibm5150, 0, eagle1600, pccga, driver_device, 0, "Eagle", "1600" , MACHINE_NOT_WORKING)
-
-COMP ( 1988, laser_turbo_xt, ibm5150, 0, laser_turbo_xt, 0, driver_device, 0, "VTech", "Laser Turbo XT" , 0)
-COMP ( 1989, laser_xt3, ibm5150, 0, laser_xt3, 0, driver_device, 0, "VTech", "Laser XT/3" , 0)
+/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
+COMP( 1984, dgone, ibm5150, 0, dgone, pccga, driver_device, 0, "Data General", "Data General/One" , MACHINE_NOT_WORKING)/* CGA, 2x 3.5" disk drives */
+COMP( 1985, bw230, ibm5150, 0, bondwell, bondwell, pc_state, bondwell, "Bondwell Holding", "BW230 (PRO28 Series)", 0 )
+COMP( 1984, compc1, ibm5150, 0, pccga, pccga, driver_device, 0, "Commodore Business Machines", "Commodore PC-1" , MACHINE_NOT_WORKING)
+COMP( 1987, pc10iii, ibm5150, 0, pccga, pccga, driver_device, 0, "Commodore Business Machines", "Commodore PC-10 III" , MACHINE_NOT_WORKING)
+COMP( 1992, iskr3104, ibm5150, 0, iskr3104, pccga, driver_device, 0, "Schetmash", "Iskra 3104", MACHINE_NOT_WORKING)
+COMP( 1989, mk88, ibm5150, 0, mk88, pccga, driver_device, 0, "<unknown>", "MK-88", MACHINE_NOT_WORKING)
+COMP( 1991, poisk2, ibm5150, 0, poisk2, pccga, driver_device, 0, "<unknown>", "Poisk-2", MACHINE_NOT_WORKING)
+COMP( 1990, mc1702, ibm5150, 0, pccga, pccga, driver_device, 0, "<unknown>", "Elektronika MC-1702", MACHINE_NOT_WORKING)
+COMP( 1987, zdsupers, ibm5150, 0, zenith, pccga, driver_device, 0, "Zenith Data Systems", "SuperSport", 0)
+COMP( 1985, sicpc1605, ibm5150, 0, siemens, pccga, driver_device, 0, "Siemens", "Sicomp PC16-05", MACHINE_NOT_WORKING)
+COMP( 1985, ncrpc4i, ibm5150, 0, ncrpc4i, pccga, driver_device, 0, "NCR", "PC4i", MACHINE_NOT_WORKING)
+COMP( 198?, olivm15, ibm5150, 0, m15, pccga, driver_device, 0, "Olivetti", "M15", 0)
+COMP( 1983, ibm5550, ibm5150, 0, ibm5550, pccga, driver_device, 0, "International Business Machines", "IBM 5550", MACHINE_NOT_WORKING)
+COMP( 1985, pc7000, ibm5150, 0, pccga, pccga, driver_device, 0, "Sharp", "PC-7000", MACHINE_NOT_WORKING)
+COMP( 1988, sx16, ibm5150, 0, pccga, pccga, driver_device, 0, "Sanyo", "SX-16", MACHINE_NOT_WORKING)
+COMP( 198?, mbc16, ibm5150, 0, pccga, pccga, driver_device, 0, "Sanyo", "MBC-16" , MACHINE_NOT_WORKING)
+COMP( 1987, ataripc1, ibm5150, 0, ataripc1, pccga, driver_device, 0, "Atari", "PC1" , 0)
+COMP( 1988, ataripc3, ibm5150, 0, pccga, pccga, driver_device, 0, "Atari", "PC3" , 0)
+COMP( 1989, ssam88s, ibm5150, 0, pccga, pccga, driver_device, 0, "Samsung", "Samtron 88S" , MACHINE_NOT_WORKING)
+COMP( 1983, eagle1600, ibm5150, 0, eagle1600, pccga, driver_device, 0, "Eagle", "1600" , MACHINE_NOT_WORKING)
+COMP( 1988, laser_turbo_xt, ibm5150, 0, laser_turbo_xt, 0, driver_device, 0, "VTech", "Laser Turbo XT" , 0)
+COMP( 1989, laser_xt3, ibm5150, 0, laser_xt3, 0, driver_device, 0, "VTech", "Laser XT/3" , 0)
diff --git a/src/mame/drivers/rm380z.cpp b/src/mame/drivers/rm380z.cpp
index 1d2d93d6bb7..53baa0c3c7c 100644
--- a/src/mame/drivers/rm380z.cpp
+++ b/src/mame/drivers/rm380z.cpp
@@ -170,12 +170,18 @@ static MACHINE_CONFIG_START( rm380z, rm380z_state )
MCFG_GENERIC_KEYBOARD_CB(WRITE8(rm380z_state, keyboard_put))
MACHINE_CONFIG_END
+static MACHINE_CONFIG_DERIVED( rm480z, rm380z )
+ MCFG_SCREEN_MODIFY("screen")
+ MCFG_SCREEN_SIZE(64*8, 24*11)
+ MCFG_SCREEN_VISIBLE_AREA(0, 64*8-1, 0, 24*11-1)
+ MCFG_SCREEN_UPDATE_DRIVER(rm380z_state, screen_update_rm480z)
+MACHINE_CONFIG_END
/* ROM definitions */
ROM_START( rm380z34d )
- ROM_REGION( 0x10000, RM380Z_MAINCPU_TAG, 0 )
+ ROM_REGION( 0x10000, RM380Z_MAINCPU_TAG, 0 )
ROM_LOAD( "cos34d-f.bin", 0x0000, 0x1000, CRC(eb128b40) SHA1(c46f358fb76459987e41750d052995563f2f7d53))
// chargen ROM is undumped, afaik
ROM_REGION( 0x1680, "chargen", 0 )
@@ -199,15 +205,22 @@ ROM_START( rm380z )
// chargen ROM is undumped, afaik
ROM_REGION( 0x1680, "chargen", 0 )
ROM_LOAD( "ch3.raw", 0x0000, 0x1680, BAD_DUMP CRC(c223622b) SHA1(185ef24896419d7ff46f71a760ac217de3811684))
- // The characters on the 480Z are very close (or identical) to the 380Z ones
- //ROM_REGION( 0x2000, "chargen", 0 )
- //ROM_LOAD( "CG06.BIN", 0x0000, 0x2000, CRC(15d40f7e) SHA1(a7266357eb9be849f77a97ff3013b236c0af8289))
+ROM_END
+
+ROM_START( rm480z )
+ ROM_REGION( 0x10000, RM380Z_MAINCPU_TAG, 0 )
+ ROM_LOAD( "cos40b-m.bin", 0x0000, 0x1000, CRC(1f0b3a5c) SHA1(0b29cb2a3b7eaa3770b34f08c4fd42844f42700f))
+ ROM_LOAD( "cos40b-m_f600-f9ff.bin", 0x1000, 0x400, CRC(e3397d9d) SHA1(490a0c834b0da392daf782edc7d51ca8f0668b1a))
+ ROM_LOAD( "cos40b-m_1c00-1dff.bin", 0x1400, 0x200, CRC(0f759f44) SHA1(9689c1c1faa62c56def999cbedbbb0c8d928dcff))
+ ROM_REGION( 0x2000, "chargen", 0 )
+ ROM_LOAD( "cg06.bin", 0x0000, 0x2000, CRC(15d40f7e) SHA1(a7266357eb9be849f77a97ff3013b236c0af8289) )
ROM_END
/* Driver */
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */
-COMP(1978, rm380z, 0, 0, rm380z, rm380z, rm380z_state, rm380z, "Research Machines", "RM-380Z, COS 4.0B", MACHINE_NO_SOUND_HW)
+COMP(1978, rm380z, 0, 0, rm380z, rm380z, rm380z_state, rm380z, "Research Machines", "RM-380Z, COS 4.0B", MACHINE_NO_SOUND_HW)
COMP(1978, rm380z34d, rm380z, 0, rm380z, rm380z, rm380z_state, rm380z34d, "Research Machines", "RM-380Z, COS 3.4D", MACHINE_BTANB_FLAGS)
COMP(1978, rm380z34e, rm380z, 0, rm380z, rm380z, rm380z_state, rm380z34e, "Research Machines", "RM-380Z, COS 3.4E", MACHINE_BTANB_FLAGS)
+COMP(1981, rm480z, rm380z, 0, rm480z, rm380z, rm380z_state, rm380z34e, "Research Machines", "LINK RM-480Z", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW)
diff --git a/src/mame/drivers/rohga.cpp b/src/mame/drivers/rohga.cpp
index e663dffc7a4..3cb74af0a69 100644
--- a/src/mame/drivers/rohga.cpp
+++ b/src/mame/drivers/rohga.cpp
@@ -730,8 +730,8 @@ static INPUT_PORTS_START( hangzo )
PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SW2:7")
- PORT_DIPSETTING( 0x4000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x4000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:8")
PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
diff --git a/src/mame/drivers/stv.cpp b/src/mame/drivers/stv.cpp
index 1cffadd6639..30dd4ec6e68 100644
--- a/src/mame/drivers/stv.cpp
+++ b/src/mame/drivers/stv.cpp
@@ -2833,16 +2833,11 @@ ROM_START( choroqhr ) // set to 1p
ROM_LOAD16_WORD_SWAP( "ic28.bin", 0x0800000, 0x200000, CRC(3c949563) SHA1(ab2a9f9ec23071cc236dee945b436a9cd73efb92) )
ROM_LOAD16_WORD_SWAP( "ic30.bin", 0x0a00000, 0x200000, CRC(7e93078d) SHA1(10fa99029a3e741ea0fddcf00ee07b5fd039bf19) )
ROM_LOAD16_WORD_SWAP( "ic32.bin", 0x0c00000, 0x200000, CRC(86cdcbd8) SHA1(90060cde84c75fd4146ebf6b9101f04140408e88) )
- //ROM_LOAD16_WORD_SWAP( "ic32.bad2.bin", 0x000000, 0x200000, CRC(76709d73) SHA1(a7805e956ee1a3701a803d0af082c33c89c26c3a) )
- //ROM_LOAD16_WORD_SWAP( "ic32.bad3.bin", 0x000000, 0x200000, CRC(b873cf3e) SHA1(8ed42a229e416125d7a2359faaea17208324feb0) )
- //ROM_LOAD16_WORD_SWAP( "ic32.bad4.bin", 0x000000, 0x200000, CRC(ed808ad4) SHA1(b00791ec3ee6255bccde171279a1a14e322d0e6d) )
- //ROM_LOAD16_WORD_SWAP( "ic32.bad5.bin", 0x000000, 0x200000, CRC(ed808ad4) SHA1(b00791ec3ee6255bccde171279a1a14e322d0e6d) )
- //ROM_LOAD16_WORD_SWAP( "ic32.bad6.bin", 0x000000, 0x200000, CRC(ed808ad4) SHA1(b00791ec3ee6255bccde171279a1a14e322d0e6d) )
ROM_LOAD16_WORD_SWAP( "ic34.bin", 0x0e00000, 0x200000, CRC(be2ed0a0) SHA1(a9225ba6b78fa0119fc6484828f4d4cc6ea05d8f) )
ROM_LOAD16_WORD_SWAP( "ic36.bin", 0x1000000, 0x200000, CRC(9a4109e5) SHA1(ba59caac5f5a80fc52c507d8a47f322a380aa9a1) )
- ROM_REGION16_BE( 0x80, "eeprom", 0 ) // preconfigured to 1 player
- ROM_LOAD( "choroqhr.nv", 0x0000, 0x0080, CRC(69a71aea) SHA1(08ca9cd70fa3fa6c3156edd966a81244bad5f0c2) )
+ ROM_REGION16_BE( 0x80, "eeprom", ROMREGION_ERASE00 ) // preconfigured to 1 player
+ ROM_LOAD( "choroqhr.nv", 0x0000, 0x0080, CRC(6e89815f) SHA1(4478f614fb61859f4ee7bf55462f737387887e6f) )
ROM_END
ROM_START( pclub2 ) // set to 1p / runs with the USA bios
@@ -3034,7 +3029,7 @@ ROM_START( prc28su ) // set to 1p
ROM_LOAD( "eeprom", 0x0000, 0x0080, CRC(447bb3bd) SHA1(9fefec09849bfa0c14b49e73ff13e2a538dff511) )
ROM_END
-// this is the first one to offer visual display of the frames in the Frame Coun test menu?
+// this is the first one to offer visual display of the frames in the Frame Count test menu?
ROM_START( prc29au ) // set to 1p
STV_BIOS
@@ -3057,19 +3052,19 @@ ROM_END
-ROM_START( prc2ksu ) // set to 1p (this dump is too damaged to even run the ROM tests properly)
+ROM_START( prc2ksu ) // set to 1p
STV_BIOS
ROM_REGION32_BE( 0x3000000, "cart", ROMREGION_ERASE00 ) /* SH2 code */
-
- // NOTE: Game fails IC7 check, might be okay, might not be - supposedly ST-V print carts are known to have bad ROM tests(?)
- ROM_LOAD16_WORD_SWAP( "ic22.bin", 0x0200000, 0x0200000, CRC(4b3de7df) SHA1(869c3840ac2eab263bb8b79ba1430e5789fa5758) )
- ROM_LOAD16_WORD_SWAP( "ic24.bin", 0x0400000, 0x0200000, BAD_DUMP CRC(02da49b7) SHA1(dd19bfd6c21f432b3af011ce43ba38d295c06c6d) ) // (maybe bad, maybe good, consistent read at least)
- ROM_LOAD16_WORD_SWAP( "ic26.bin", 0x0600000, 0x0200000, BAD_DUMP CRC(a431d614) SHA1(75de91d8eff5af7e1b668012a0613884ba660e21) ) // (maybe bad, maybe good, consistent read at least)
- ROM_LOAD16_WORD_SWAP( "ic28.bin", 0x0800000, 0x0200000, CRC(c0fba1a5) SHA1(5f98be1eed5f74e62fe5a3e33fdcf3b827dda1a7) )
- ROM_LOAD16_WORD_SWAP( "ic30.bin", 0x0a00000, 0x0200000, CRC(0811d0e4) SHA1(b4fd9369c80f76141ae2fb38525b405b4c2f391a) )
+ // NOTE: Game fails IC7 check but rom read consistently, might be okay, might not be - supposedly ST-V print carts are known to have bad ROM tests(?)
+ ROM_LOAD16_WORD_SWAP( "ic22.bin", 0x0200000, 0x0200000, CRC(4b3de7df) SHA1(869c3840ac2eab263bb8b79ba1430e5789fa5758) ) // 'BAD' (tested as IC7) (but maybe OK)
+ ROM_LOAD16_WORD_SWAP( "ic24.bin", 0x0400000, 0x0200000, CRC(02da49b7) SHA1(dd19bfd6c21f432b3af011ce43ba38d295c06c6d) ) // OK (tested as IC2)
+ ROM_LOAD16_WORD_SWAP( "ic26.bin", 0x0600000, 0x0200000, CRC(a431d614) SHA1(75de91d8eff5af7e1b668012a0613884ba660e21) ) // OK (tested as IC2)
+ ROM_LOAD16_WORD_SWAP( "ic28.bin", 0x0800000, 0x0200000, CRC(c0fba1a5) SHA1(5f98be1eed5f74e62fe5a3e33fdcf3b827dda1a7) ) // OK (tested as IC3)
+ ROM_LOAD16_WORD_SWAP( "ic30.bin", 0x0a00000, 0x0200000, CRC(0811d0e4) SHA1(b4fd9369c80f76141ae2fb38525b405b4c2f391a) ) // OK (tested as IC3)
ROM_REGION16_BE( 0x80, "eeprom", ROMREGION_ERASE00 ) // preconfigured to 1 player
+ ROM_LOAD( "prc2ksu.nv", 0x0000, 0x0080, CRC(ee7ffdc5) SHA1(4008e37cae306c0202146c5dd79ca925b8d8edd5) )
ROM_END
@@ -3447,16 +3442,15 @@ GAME( 1997, pckobe99, stvbios, stv, stv, stv_state, stv, ROT0
GAME( 1997, pclub26w, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 Vol. 6 Winter (J 961210 V1.000)", MACHINE_NOT_WORKING ) // internal string is 'PURIKURA2 97FUYU' (but in reality it seems to be an end of 96 Winter version)
GAME( 1997, pclub26wa, pclub26w,stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 Vol. 6 Winter (J 970121 V1.200)", MACHINE_NOT_WORKING ) // ^
GAME( 1997, pclub27s, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 Vol. 7 Spring (J 970313 V1.100)", MACHINE_NOT_WORKING )
-GAME( 1997, prc28su, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 Vol. 8 Summer (J 970616 V1.100)", MACHINE_NOT_WORKING ) // internal string 97SUMMER *** BAD DUMP ***
+GAME( 1997, prc28su, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 Vol. 8 Summer (J 970616 V1.100)", MACHINE_NOT_WORKING ) // internal string 97SUMMER
GAME( 1997, prc29au, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 Vol. 9 Autumn (J V1.100)", MACHINE_NOT_WORKING ) // internal string 97AUTUMN, no date code! (all 0)
GAME( 1997, prc297wi, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 '97 Winter Ver (J 971017 V1.100, set 1)", MACHINE_NOT_WORKING ) // internal string is '97WINTER'
GAME( 1997, prc297wia, prc297wi,stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 '97 Winter Ver (J 971017 V1.100, set 2)", MACHINE_NOT_WORKING ) // different program revision, same date code, clearly didn't get updated properly
GAME( 1998, prc298sp, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 '98 Spring Ver (J 971017 V1.100)", MACHINE_NOT_WORKING ) // again, date doesn't appear to have bene updated, this should be early 98
GAME( 1998, prc298su, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 '98 Summer Ver (J 980603 V1.100)", MACHINE_NOT_WORKING ) //
GAME( 1998, prc298au, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 '98 Autumn Ver (J 980827 V1.000)", MACHINE_NOT_WORKING )
-
-GAME( 2000, prc2ksu, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 2000 Summer", MACHINE_NOT_WORKING ) // *** BAD DUMP *** (even internal strings are corrupt)
-
+GAME( 2000, prc2ksu, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club 2 2000 Summer (J 000509 V1.000) ", MACHINE_NOT_WORKING ) // internal string 2000_SUMMER
+
GAME( 1999, pclubor, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club Goukakenran (J 991104 V1.000)", MACHINE_NOT_WORKING )
GAME( 1999, pclubol, stvbios, stv, stv, stv_state, stv, ROT0, "Atlus", "Print Club Olive (J 980717 V1.000)", MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/vd.cpp b/src/mame/drivers/vd.cpp
index ee0385c6156..84521e20623 100644
--- a/src/mame/drivers/vd.cpp
+++ b/src/mame/drivers/vd.cpp
@@ -5,10 +5,13 @@
PINBALL
Videodens
- PinMAME used as reference (unable to find any info at all on the net).
+ PinMAME used as reference. The Break '86 manual scan available on the net includes
+ a mostly illegible schematic.
Nothing in this driver is confirmed except where noted.
+ Ator runs on different hardware (peyper.cpp).
+
***************************************************************************************/
@@ -25,7 +28,7 @@ public:
m_maincpu(*this, "maincpu")
{ }
- DECLARE_READ8_MEMBER(dsw_r) { return 0; }
+ DECLARE_READ8_MEMBER(ack_r);
DECLARE_WRITE8_MEMBER(col_w);
DECLARE_WRITE8_MEMBER(disp_w);
DECLARE_WRITE8_MEMBER(lamp_w) { };
@@ -44,6 +47,12 @@ private:
};
+READ8_MEMBER(vd_state::ack_r)
+{
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); // guess
+ return 0; // this value is not used
+}
+
static ADDRESS_MAP_START( vd_map, AS_PROGRAM, 8, vd_state )
AM_RANGE(0x0000, 0x5fff) AM_ROM
AM_RANGE(0x6000, 0x62ff) AM_RAM
@@ -52,49 +61,68 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( vd_io, AS_IO, 8, vd_state )
ADDRESS_MAP_GLOBAL_MASK(0xff)
- AM_RANGE(0x00,0x00) AM_READ_PORT("X0")
- AM_RANGE(0x01,0x01) AM_READ_PORT("X1")
- AM_RANGE(0x02,0x02) AM_READ_PORT("X2")
- AM_RANGE(0x03,0x03) AM_READ_PORT("X3")
- AM_RANGE(0x04,0x04) AM_READ_PORT("X4")
- AM_RANGE(0x05,0x05) AM_READ_PORT("X5")
- AM_RANGE(0x20,0x27) AM_WRITE(lamp_w)
- AM_RANGE(0x28,0x28) AM_WRITE(sol_w)
- AM_RANGE(0x40,0x44) AM_WRITE(disp_w)
- AM_RANGE(0x60,0x60) AM_DEVWRITE("ay1", ay8910_device, address_w)
- AM_RANGE(0x61,0x61) AM_READ_PORT("DSW") //AM_READ(dsw_r)
- AM_RANGE(0x62,0x62) AM_DEVWRITE("ay1", ay8910_device, data_w)
- AM_RANGE(0x80,0x80) AM_DEVWRITE("ay2", ay8910_device, address_w)
- AM_RANGE(0x82,0x82) AM_DEVWRITE("ay2", ay8910_device, data_w)
- AM_RANGE(0xa0,0xa0) AM_DEVREAD("ay2", ay8910_device, data_r)
- AM_RANGE(0xc0,0xc0) AM_WRITE(col_w)
+ AM_RANGE(0x00, 0x00) AM_READ_PORT("X0")
+ AM_RANGE(0x01, 0x01) AM_READ_PORT("X1")
+ AM_RANGE(0x02, 0x02) AM_READ_PORT("X2")
+ AM_RANGE(0x03, 0x03) AM_READ_PORT("X3")
+ AM_RANGE(0x04, 0x04) AM_READ_PORT("X4")
+ AM_RANGE(0x05, 0x05) AM_READ_PORT("X5")
+ AM_RANGE(0x20, 0x27) AM_WRITE(lamp_w)
+ AM_RANGE(0x28, 0x28) AM_WRITE(sol_w)
+ AM_RANGE(0x40, 0x44) AM_WRITE(disp_w)
+ AM_RANGE(0x60, 0x60) AM_DEVWRITE("ay1", ay8910_device, address_w)
+ AM_RANGE(0x61, 0x61) AM_DEVREAD("ay1", ay8910_device, data_r)
+ AM_RANGE(0x62, 0x62) AM_DEVWRITE("ay1", ay8910_device, data_w)
+ AM_RANGE(0x80, 0x80) AM_DEVWRITE("ay2", ay8910_device, address_w)
+ AM_RANGE(0x81, 0x81) AM_DEVREAD("ay2", ay8910_device, data_r) // probably never read
+ AM_RANGE(0x82, 0x82) AM_DEVWRITE("ay2", ay8910_device, data_w)
+ AM_RANGE(0xa0, 0xa0) AM_READ(ack_r)
+ AM_RANGE(0xc0, 0xc0) AM_WRITE(col_w)
ADDRESS_MAP_END
-static INPUT_PORTS_START( vd )
- PORT_START("DSW")
- PORT_DIPNAME( 0x0001, 0x0000, "Accounting #1")
- PORT_DIPSETTING(0x0000, DEF_STR(Off))
- PORT_DIPSETTING(0x0001, DEF_STR(On))
- PORT_DIPNAME( 0x0002, 0x0000, "Accounting #2")
- PORT_DIPSETTING(0x0000, DEF_STR(Off))
- PORT_DIPSETTING(0x0002, DEF_STR(On))
- PORT_DIPNAME( 0x0004, 0x0000, "Accounting #3")
- PORT_DIPSETTING(0x0000, DEF_STR(Off))
- PORT_DIPSETTING(0x0004, DEF_STR(On))
- PORT_DIPNAME( 0x0018, 0x0000, "Credits per coin (chute #1/#2)")
- PORT_DIPSETTING(0x0018, "0.5/3" )
- PORT_DIPSETTING(0x0000, "1/5" )
- PORT_DIPSETTING(0x0008, "1/6" )
- PORT_DIPSETTING(0x0010, "2/8" )
- PORT_DIPNAME( 0x0020, 0x0000, "S6")
- PORT_DIPSETTING(0x0000, "0" )
- PORT_DIPSETTING(0x0020, "1" )
- PORT_DIPNAME( 0x0040, 0x0000, "Match feature")
- PORT_DIPSETTING(0x0040, DEF_STR(Off))
- PORT_DIPSETTING(0x0000, DEF_STR(On))
- PORT_DIPNAME( 0x0080, 0x0000, "S8")
- PORT_DIPSETTING(0x0000, "0" )
- PORT_DIPSETTING(0x0080, "1" )
+static INPUT_PORTS_START( break86 )
+ PORT_START("DSW1") // "Micro Swicher Nº 1"
+ PORT_DIPUNKNOWN(0x01, 0x01) PORT_DIPLOCATION("SW1:8") // used but not described in service manual
+ PORT_DIPUNKNOWN(0x02, 0x02) PORT_DIPLOCATION("SW1:7") // used but not described in service manual
+ PORT_DIPUNKNOWN(0x04, 0x04) PORT_DIPLOCATION("SW1:6") // used but not described in service manual
+ PORT_DIPUNUSED(0x08, 0x08) PORT_DIPLOCATION("SW1:5")
+ PORT_DIPNAME(0x30, 0x30, "Power Bumpers") PORT_DIPLOCATION("SW1:4,3") // "Potencia Bu????s" (partly illegible)
+ PORT_DIPSETTING(0x00, "4")
+ PORT_DIPSETTING(0x10, "6")
+ PORT_DIPSETTING(0x20, "8")
+ PORT_DIPSETTING(0x30, "10")
+ PORT_DIPNAME(0xc0, 0xc0, "Bonus Balls") PORT_DIPLOCATION("SW1:2,1") // "Bonos Bola Extra" - "Nº de Bonos"
+ PORT_DIPSETTING(0xc0, "6")
+ PORT_DIPSETTING(0x80, "8")
+ PORT_DIPSETTING(0x40, "10")
+ PORT_DIPSETTING(0x00, "12")
+
+ PORT_START("DSW2") // "Micro Swicher Nº 2"
+ PORT_DIPNAME(0x03, 0x03, "Scoring") PORT_DIPLOCATION("SW2:8,7") // "Tanteo"
+ PORT_DIPSETTING(0x03, "800k / 1.4M / 2.0M / 2.6M") // = "Bola Extra," "1ª Partida," "2ª Partida," "High Score"
+ PORT_DIPSETTING(0x02, "1.0M / 1.6M / 2.2M / 2.8M")
+ PORT_DIPSETTING(0x01, "1.2M / 1.8M / 2.4M / 3.0M")
+ PORT_DIPSETTING(0x00, "1.4M / 2.0M / 2.6M / 3.2M")
+ PORT_DIPNAME(0x04, 0x04, "Balls/Game") PORT_DIPLOCATION("SW2:6") // "Bolas-Partida"
+ PORT_DIPSETTING(0x04, "3")
+ PORT_DIPSETTING(0x00, "5")
+ PORT_DIPNAME(0x18, 0x18, DEF_STR(Coinage)) PORT_DIPLOCATION("SW2:5,4") // "Monederos"
+ PORT_DIPSETTING(0x18, "25 Pts. = 1, 100 Pts. = 5")
+ PORT_DIPSETTING(0x10, "25 Pts. = 1, 100 Pts. = 6")
+ PORT_DIPSETTING(0x08, "25 Pts. = 2, 100 Pts. = 8")
+ PORT_DIPSETTING(0x00, "25 Pts. = 1/2, 100 Pts. = 3")
+ PORT_DIPNAME(0x20, 0x20, "Lottery") PORT_DIPLOCATION("SW2:3") // "Loteria"
+ PORT_DIPSETTING(0x00, DEF_STR(No))
+ PORT_DIPSETTING(0x20, DEF_STR(Yes))
+ PORT_DIPNAME(0x40, 0x40, "Musica-Reclamo") PORT_DIPLOCATION("SW2:2")
+ PORT_DIPSETTING(0x00, DEF_STR(No))
+ PORT_DIPSETTING(0x40, DEF_STR(Yes))
+ PORT_DIPNAME(0x80, 0x80, "Extra Ball/Score") PORT_DIPLOCATION("SW2:1") // "Bola Extra-Tanteo"
+ PORT_DIPSETTING(0x00, DEF_STR(No))
+ PORT_DIPSETTING(0x80, DEF_STR(Yes))
+
+ PORT_START("DSW3")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED) // SW3 not populated
PORT_START("X0")
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_START1)
@@ -109,6 +137,10 @@ static INPUT_PORTS_START( vd )
PORT_START("X5")
INPUT_PORTS_END
+static INPUT_PORTS_START( papillon )
+ PORT_INCLUDE( break86 ) // differences unknown
+INPUT_PORTS_END
+
TIMER_DEVICE_CALLBACK_MEMBER( vd_state::irq )
{
if (m_t_c > 40)
@@ -120,8 +152,10 @@ TIMER_DEVICE_CALLBACK_MEMBER( vd_state::irq )
WRITE8_MEMBER( vd_state::disp_w )
{
segment[offset] = data;
+#if 0 // probably not how this works
if (!offset)
m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
+#endif
}
WRITE8_MEMBER( vd_state::col_w )
@@ -154,8 +188,11 @@ static MACHINE_CONFIG_START( vd, vd_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("ay1", AY8910, 2000000) //?
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.33/3)
+ MCFG_AY8910_PORT_A_READ_CB(IOPORT("DSW2"))
+ MCFG_AY8910_PORT_B_READ_CB(IOPORT("DSW1"))
MCFG_SOUND_ADD("ay2", AY8910, 2000000) //?
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.33/3)
+ MCFG_AY8910_PORT_B_READ_CB(IOPORT("DSW3")) //?
/* Video */
MCFG_DEFAULT_LAYOUT(layout_vd)
@@ -163,6 +200,10 @@ MACHINE_CONFIG_END
/*-------------------------------------------------------------------
/ Break '86 (1986)
+/
+/ The title of this game is somewhat uncertain. The backglass says
+/ only "Break," the flyer also calls it "Super Break" and "Super
+/ Break '86", and the service manual's title page has "Modbreak."
/-------------------------------------------------------------------*/
ROM_START(break86)
ROM_REGION(0x10000, "maincpu", 0)
@@ -181,18 +222,6 @@ ROM_START(papillon)
ROM_LOAD("u6.dat", 0x4000, 0x2000, CRC(6b2867b3) SHA1(720fe8a65b447e839b0eb9ea21e0b3cb0e50cf7a))
ROM_END
-#if 0
-/*-------------------------------------------------------------------
-/ Ator (19??)
-/-------------------------------------------------------------------*/
-ROM_START(ator)
- ROM_REGION(0x10000, "maincpu", 0)
- ROM_LOAD("ator.u4", 0x0000, 0x2000, NO_DUMP)
- ROM_LOAD("ator.u5", 0x2000, 0x2000, NO_DUMP)
- ROM_LOAD("ator.u6", 0x4000, 0x2000, CRC(21aad5c4) SHA1(e78da5d80682710db34cbbfeae5af54241c73371))
-ROM_END
-#endif
-//GAME(19??, ator, 0, vd, vd, driver_device, 0, ROT0, "Videodens", "Ator", MACHINE_IS_SKELETON_MECHANICAL)
-GAME(1986, break86, 0, vd, vd, driver_device, 0, ROT0, "Videodens", "Break '86", MACHINE_IS_SKELETON_MECHANICAL)
-GAME(1986, papillon, 0, vd, vd, driver_device, 0, ROT0, "Videodens", "Papillon", MACHINE_IS_SKELETON_MECHANICAL)
+GAME(1986, break86, 0, vd, break86, driver_device, 0, ROT0, "Videodens", "Break '86", MACHINE_IS_SKELETON_MECHANICAL)
+GAME(1986, papillon, 0, vd, papillon, driver_device, 0, ROT0, "Videodens", "Papillon", MACHINE_IS_SKELETON_MECHANICAL)
diff --git a/src/mame/drivers/x1.cpp b/src/mame/drivers/x1.cpp
index 741895f5a5b..cde608c590a 100644
--- a/src/mame/drivers/x1.cpp
+++ b/src/mame/drivers/x1.cpp
@@ -574,6 +574,62 @@ uint16_t x1_state::check_keyboard_press()
uint32_t f_key = ioport("f_keys")->read();
scancode = 0;
+ static const uint8_t kanatable[52][3] = {
+ // normal, kana, kana + shift
+ {0x2c,0xc8,0xa4}, // , / ne / japanese comma
+ {0x2d,0xce,0x00}, // - / ho
+ {0x2e,0xd9,0xa1}, // . / ru / japanese period
+ {0x2f,0xd2,0xa5}, // / / me / nakaguro
+ {0x30,0xdc,0xa6}, // 0 / wa / wo
+ {0x31,0xc7,0x00}, // 1 / nu
+ {0x32,0xcc,0x00}, // 2 / fu
+ {0x33,0xb1,0xa7}, // 3 / a / small a
+ {0x34,0xb3,0xa9}, // 4 / u / small u
+ {0x35,0xb4,0xaa}, // 5 / e / small e
+ {0x36,0xb5,0xab}, // 6 / o / small o
+ {0x37,0xd4,0xac}, // 7 / ya / small ya
+ {0x38,0xd5,0xad}, // 8 / yu / small yu
+ {0x39,0xd6,0xae}, // 9 / yo / small yo
+ {0x3a,0xb9,0x00}, // : / ke
+ {0x3b,0xda,0x00}, // ; / re
+ {0x3c,0x00,0x00},
+ {0x3d,0x00,0x00},
+ {0x3e,0x00,0x00},
+ {0x3f,0x00,0x00},
+ {0x40,0xde,0x00}, // @ / dakuten
+ {0x41,0xc1,0x00}, // A / chi
+ {0x42,0xba,0x00}, // B / ko
+ {0x43,0xbf,0x00}, // C / so
+ {0x44,0xbc,0x00}, // D / shi
+ {0x45,0xb2,0xa8}, // E / i / small i
+ {0x46,0xca,0x00}, // F / ha
+ {0x47,0xb7,0x00}, // G / ki
+ {0x48,0xb8,0x00}, // H / ku
+ {0x49,0xc6,0x00}, // I / ni
+ {0x4a,0xcf,0x00}, // J / ma
+ {0x4b,0xc9,0x00}, // K / no
+ {0x4c,0xd8,0x00}, // L / ri
+ {0x4d,0xd3,0x00}, // M / mo
+ {0x4e,0xd0,0x00}, // N / mi
+ {0x4f,0xd7,0x00}, // O / ra
+ {0x50,0xbe,0x00}, // P / se
+ {0x51,0xc0,0x00}, // Q / ta
+ {0x52,0xbd,0x00}, // R / su
+ {0x53,0xc4,0x00}, // S / to
+ {0x54,0xb6,0x00}, // T / ka
+ {0x55,0xc5,0x00}, // U / na
+ {0x56,0xcb,0x00}, // V / hi
+ {0x57,0xc3,0x00}, // W / te
+ {0x58,0xbb,0x00}, // X / sa
+ {0x59,0xdd,0x00}, // Y / n
+ {0x5a,0xc2,0xaf}, // Z / tsu / small tsu
+ {0x5b,0xdf,0xa2}, // [ / handakuten / opening quotation mark
+ {0x5c,0xb0,0x00}, // yen symbol / long vowel mark
+ {0x5d,0xd1,0xa3}, // ] / mu / closing quotation mark
+ {0x5e,0xcd,0x00}, // ^ / he
+ {0x5f,0xdb,0x00} // _ / ro
+ };
+
for(port_i=0;port_i<3;port_i++)
{
for(i=0;i<32;i++)
@@ -583,11 +639,26 @@ uint16_t x1_state::check_keyboard_press()
//key_flag = 1;
if(keymod & 0x02) // shift not pressed
{
- if(scancode >= 0x41 && scancode < 0x5a)
+ if ((keymod & 0x04) == 0) // kana on
+ {
+ if (scancode >= 0x2c && scancode <= 0x5f)
+ scancode = kanatable[scancode - 0x2c][1];
+ }
+
+ if (scancode >= 0x41 && scancode < 0x5a)
scancode += 0x20; // lowercase
}
else
{
+ if ((keymod & 0x04) == 0) // kana on
+ {
+ if (scancode >= 0x2c && scancode <= 0x5f)
+ {
+ if (kanatable[scancode - 0x2c][2] != 0)
+ scancode = kanatable[scancode - 0x2c][2];
+ }
+ }
+
if(scancode >= 0x31 && scancode < 0x3a)
scancode -= 0x10;
if(scancode == 0x30)
@@ -595,6 +666,9 @@ uint16_t x1_state::check_keyboard_press()
scancode = 0x3d;
}
}
+
+
+
if((keymod & 0x10) == 0) // graph on
scancode |= 0x80;
@@ -2026,10 +2100,10 @@ INPUT_PORTS_START( x1 )
PORT_BIT(0x00000200,IP_ACTIVE_HIGH,IPT_UNUSED) //0x29 )
PORT_BIT(0x00000400,IP_ACTIVE_HIGH,IPT_UNUSED) //0x2a *
PORT_BIT(0x00000800,IP_ACTIVE_HIGH,IPT_UNUSED) //0x2b +
- PORT_BIT(0x00001000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x2c ,
+ PORT_BIT(0x00001000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',')
PORT_BIT(0x00002000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
- PORT_BIT(0x00004000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x2e .
- PORT_BIT(0x00008000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x2f /
+ PORT_BIT(0x00004000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.')
+ PORT_BIT(0x00008000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/')
PORT_BIT(0x00010000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
PORT_BIT(0x00020000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1')
@@ -2077,7 +2151,7 @@ INPUT_PORTS_START( x1 )
PORT_BIT(0x02000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
PORT_BIT(0x04000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
PORT_BIT(0x08000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[')
- PORT_BIT(0x10000000,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x10000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("\xc2\xa5") // yen
PORT_BIT(0x20000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("]") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']')
PORT_BIT(0x40000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("^") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^')
PORT_BIT(0x80000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("_")
@@ -2108,9 +2182,9 @@ INPUT_PORTS_START( x1 )
PORT_START("key_modifiers")
PORT_BIT(0x00000001,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT(0x00000002,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT)
- PORT_BIT(0x00000004,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("KANA") PORT_CODE(KEYCODE_RCONTROL)
+ PORT_BIT(0x00000004,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("KANA") PORT_CODE(KEYCODE_RCONTROL) PORT_TOGGLE
PORT_BIT(0x00000008,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("CAPS") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE
- PORT_BIT(0x00000010,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("GRPH") PORT_CODE(KEYCODE_LALT)
+ PORT_BIT(0x00000010,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("GRAPH") PORT_CODE(KEYCODE_LALT)
#if 0
PORT_BIT(0x00020000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',')
diff --git a/src/mame/includes/ashnojoe.h b/src/mame/includes/ashnojoe.h
index 74dbac38522..4735df63f43 100644
--- a/src/mame/includes/ashnojoe.h
+++ b/src/mame/includes/ashnojoe.h
@@ -51,7 +51,6 @@ public:
/* sound-related */
uint8_t m_adpcm_byte;
- int m_soundlatch_status;
int m_msm5205_vclk_toggle;
/* devices */
@@ -62,9 +61,7 @@ public:
required_device<generic_latch_8_device> m_soundlatch;
DECLARE_READ16_MEMBER(fake_4a00a_r);
- DECLARE_WRITE16_MEMBER(ashnojoe_soundlatch_w);
DECLARE_WRITE8_MEMBER(adpcm_w);
- DECLARE_READ8_MEMBER(sound_latch_r);
DECLARE_READ8_MEMBER(sound_latch_status_r);
DECLARE_WRITE16_MEMBER(ashnojoe_tileram_w);
DECLARE_WRITE16_MEMBER(ashnojoe_tileram2_w);
diff --git a/src/mame/includes/crospang.h b/src/mame/includes/crospang.h
index 2a7b80e0059..0049f726a56 100644
--- a/src/mame/includes/crospang.h
+++ b/src/mame/includes/crospang.h
@@ -38,7 +38,6 @@ public:
required_device<gfxdecode_device> m_gfxdecode;
required_device<generic_latch_8_device> m_soundlatch;
- DECLARE_WRITE16_MEMBER(crospang_soundlatch_w);
DECLARE_WRITE16_MEMBER(bestri_tilebank_w);
DECLARE_WRITE16_MEMBER(bestri_bg_scrolly_w);
DECLARE_WRITE16_MEMBER(bestri_fg_scrolly_w);
diff --git a/src/mame/includes/crshrace.h b/src/mame/includes/crshrace.h
index 36ef377e777..9d1621000d8 100644
--- a/src/mame/includes/crshrace.h
+++ b/src/mame/includes/crshrace.h
@@ -54,7 +54,7 @@ public:
/* devices */
DECLARE_WRITE8_MEMBER(crshrace_sh_bankswitch_w);
- DECLARE_WRITE16_MEMBER(sound_command_w);
+ DECLARE_WRITE8_MEMBER(sound_command_w);
DECLARE_WRITE8_MEMBER(pending_command_clear_w);
DECLARE_WRITE16_MEMBER(crshrace_videoram1_w);
DECLARE_WRITE16_MEMBER(crshrace_videoram2_w);
diff --git a/src/mame/includes/dcheese.h b/src/mame/includes/dcheese.h
index 396cd2fc0db..853a3b46a83 100644
--- a/src/mame/includes/dcheese.h
+++ b/src/mame/includes/dcheese.h
@@ -38,7 +38,6 @@ public:
/* misc */
uint8_t m_irq_state[5];
- uint8_t m_soundlatch_full;
uint8_t m_sound_control;
uint8_t m_sound_msb_latch;
@@ -50,8 +49,6 @@ public:
required_device<generic_latch_8_device> m_soundlatch;
DECLARE_WRITE16_MEMBER(eeprom_control_w);
- DECLARE_WRITE16_MEMBER(sound_command_w);
- DECLARE_READ8_MEMBER(sound_command_r);
DECLARE_READ8_MEMBER(sound_status_r);
DECLARE_WRITE8_MEMBER(sound_control_w);
DECLARE_WRITE8_MEMBER(bsmt_data_w);
diff --git a/src/mame/includes/fidelz80.h b/src/mame/includes/fidelz80.h
index 5ce7e1f6c82..1fe4e19cb6b 100644
--- a/src/mame/includes/fidelz80.h
+++ b/src/mame/includes/fidelz80.h
@@ -50,9 +50,9 @@ public:
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(scc_cartridge);
// display common
- int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
- int m_display_maxy; // display matrix number of rows
- int m_display_maxx; // display matrix number of columns (max 31 for now)
+ int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
+ int m_display_maxy; // display matrix number of rows
+ int m_display_maxx; // display matrix number of columns (max 31 for now)
uint32_t m_display_state[0x20]; // display matrix rows data (last bit is used for always-on)
uint16_t m_display_segmask[0x20]; // if not 0, display matrix row is a digit, mask indicates connected segments
diff --git a/src/mame/includes/harddriv.h b/src/mame/includes/harddriv.h
index 24cee21b4b1..1ed1894258a 100644
--- a/src/mame/includes/harddriv.h
+++ b/src/mame/includes/harddriv.h
@@ -16,6 +16,7 @@
#include "machine/mc68681.h"
#include "machine/asic65.h"
#include "machine/timekpr.h"
+#include "bus/rs232/rs232.h"
#define HARDDRIV_MASTER_CLOCK XTAL_32MHz
#define HARDDRIV_GSP_CLOCK XTAL_48MHz
@@ -453,6 +454,8 @@ protected:
int get_hblank(screen_device &screen) const { return (screen.hpos() > (screen.width() * 9 / 10)); }
optional_device<atari_slapstic_device> m_slapstic_device;
+ optional_device<rs232_port_device> m_rs232;
+
protected:
//virtual machine_config_constructor device_mconfig_additions() const;
virtual void device_start() override;
diff --git a/src/mame/includes/hh_tms1k.h b/src/mame/includes/hh_tms1k.h
index d08aa797a76..b24642aa789 100644
--- a/src/mame/includes/hh_tms1k.h
+++ b/src/mame/includes/hh_tms1k.h
@@ -51,9 +51,9 @@ public:
virtual DECLARE_WRITE_LINE_MEMBER(auto_power_off);
// display common
- int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
- int m_display_maxy; // display matrix number of rows
- int m_display_maxx; // display matrix number of columns (max 31 for now)
+ int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
+ int m_display_maxy; // display matrix number of rows
+ int m_display_maxx; // display matrix number of columns (max 31 for now)
uint32_t m_grid; // VFD/LED current row data
uint32_t m_plate; // VFD/LED current column data
diff --git a/src/mame/includes/hh_ucom4.h b/src/mame/includes/hh_ucom4.h
index d71115e3fc4..4a0194e3cb0 100644
--- a/src/mame/includes/hh_ucom4.h
+++ b/src/mame/includes/hh_ucom4.h
@@ -45,9 +45,9 @@ public:
DECLARE_INPUT_CHANGED_MEMBER(single_interrupt_line);
// display common
- int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
- int m_display_maxy; // display matrix number of rows
- int m_display_maxx; // display matrix number of columns (max 31 for now)
+ int m_display_wait; // led/lamp off-delay in microseconds (default 33ms)
+ int m_display_maxy; // display matrix number of rows
+ int m_display_maxx; // display matrix number of columns (max 31 for now)
uint32_t m_grid; // VFD current row data
uint32_t m_plate; // VFD current column data
diff --git a/src/mame/includes/namcos2.h b/src/mame/includes/namcos2.h
index ed6dffaeca8..5ad57bee517 100644
--- a/src/mame/includes/namcos2.h
+++ b/src/mame/includes/namcos2.h
@@ -124,9 +124,9 @@ public:
optional_device<cpu_device> m_dspmaster;
optional_device<cpu_device> m_dspslave;
optional_device<m37450_device> m_c68;
- required_device<namco_c148_device> m_master_intc;
- required_device<namco_c148_device> m_slave_intc;
- required_device<namco_c139_device> m_sci;
+ optional_device<namco_c148_device> m_master_intc;
+ optional_device<namco_c148_device> m_slave_intc;
+ optional_device<namco_c139_device> m_sci;
optional_device<cpu_device> m_gpu; //to be moved to namco21_state after disentangling
// game type helpers
diff --git a/src/mame/includes/rm380z.h b/src/mame/includes/rm380z.h
index bc829b4dbe5..763eb043117 100644
--- a/src/mame/includes/rm380z.h
+++ b/src/mame/includes/rm380z.h
@@ -60,12 +60,9 @@ private:
int writenum;
-protected:
virtual void machine_reset() override;
virtual void machine_start() override;
-public:
-
uint8_t m_port0;
uint8_t m_port0_mask;
uint8_t m_port0_kbd;
@@ -96,6 +93,7 @@ public:
required_device<floppy_connector> m_floppy0;
required_device<floppy_connector> m_floppy1;
+public:
rm380z_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, RM380Z_MAINCPU_TAG),
@@ -136,6 +134,7 @@ public:
void config_memory_map();
void update_screen(bitmap_ind16 &bitmap);
uint32_t screen_update_rm380z(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ uint32_t screen_update_rm480z(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
TIMER_CALLBACK_MEMBER(static_vblank_timer);
};
diff --git a/src/mame/machine/alpha8201.h b/src/mame/machine/alpha8201.h
index fb24349333c..241a6d1c3bb 100644
--- a/src/mame/machine/alpha8201.h
+++ b/src/mame/machine/alpha8201.h
@@ -39,9 +39,9 @@ private:
// internal state
int m_bus; // shared RAM bus direction
- uint16_t m_mcu_address; // MCU side RAM address
- uint16_t m_mcu_d; // MCU D output data
- uint8_t m_mcu_r[4]; // MCU R0-R3 output data
+ uint16_t m_mcu_address; // MCU side RAM address
+ uint16_t m_mcu_d; // MCU D output data
+ uint8_t m_mcu_r[4]; // MCU R0-R3 output data
std::unique_ptr<uint8_t[]> m_shared_ram; // 1KB RAM
void mcu_update_address();
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 7bf23ce4aa5..dfa4c588d7f 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -14106,6 +14106,9 @@ howzat //
orbit1 //
shark //
+@source:hapyfish.cpp
+hapyfsh2 // bootleg
+
@source:harddriv.cpp
harddriv // 136052 (c) 1988
harddriv1 // 136052 (c) 1988
@@ -29594,7 +29597,8 @@ pbaction4 // (c) 1985 Tehkan
pbaction5 // (c) 1985 Tehkan
@source:pc.cpp
-ataripc3 //
+ataripc1 // Atari PC1
+ataripc3 // Atari PC3
bw230 // 1985 Bondwell (CGA)
compc1 // 1984 Commodore PC-1
dgone // 1984 Data General/One
@@ -31699,6 +31703,9 @@ rltennis // (c) 1993 TCH
@source:rm380z.cpp
rm380z //
+rm380z34d //
+rm380z34e //
+rm480z //
@source:rmhaihai.cpp
rmhaihai // (c) 1985 Alba
diff --git a/src/mame/video/rm380z.cpp b/src/mame/video/rm380z.cpp
index 23da34017d7..329dcd97ad5 100644
--- a/src/mame/video/rm380z.cpp
+++ b/src/mame/video/rm380z.cpp
@@ -404,3 +404,40 @@ void rm380z_state::update_screen(bitmap_ind16 &bitmap)
}
}
}
+
+// This needs the attributes etc from above to be added
+uint32_t rm380z_state::screen_update_rm480z(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ uint8_t *chargen = memregion("chargen")->base();
+ uint8_t y,ra,chr,gfx;
+ uint16_t sy=0,ma=0,x;
+
+ for (y = 0; y < RM380Z_SCREENROWS; y++)
+ {
+ for (ra = 0; ra < 11; ra++)
+ {
+ uint16_t *p = &bitmap.pix16(sy++);
+
+ for (x = ma; x < ma + 64; x++)
+ {
+ gfx = 0;
+ if (ra < 10)
+ {
+ chr = m_vramchars[x];
+ gfx = chargen[(chr<<4) | ra ];
+ }
+ /* Display a scanline of a character */
+ *p++ = BIT(gfx, 7);
+ *p++ = BIT(gfx, 6);
+ *p++ = BIT(gfx, 5);
+ *p++ = BIT(gfx, 4);
+ *p++ = BIT(gfx, 3);
+ *p++ = BIT(gfx, 2);
+ *p++ = BIT(gfx, 1);
+ *p++ = BIT(gfx, 0);
+ }
+ }
+ ma+=64;
+ }
+ return 0;
+}
diff --git a/src/osd/modules/render/bgfx/chainentry.cpp b/src/osd/modules/render/bgfx/chainentry.cpp
index ab18b4029fa..a53ed759940 100644
--- a/src/osd/modules/render/bgfx/chainentry.cpp
+++ b/src/osd/modules/render/bgfx/chainentry.cpp
@@ -270,7 +270,7 @@ bool bgfx_chain_entry::setup_view(int view, uint16_t screen_width, uint16_t scre
void bgfx_chain_entry::put_screen_buffer(render_primitive* prim, bgfx::TransientVertexBuffer* buffer) const
{
- if (bgfx::checkAvailTransientVertexBuffer(6, ScreenVertex::ms_decl))
+ if (6 == bgfx::getAvailTransientVertexBuffer(6, ScreenVertex::ms_decl))
{
bgfx::allocTransientVertexBuffer(buffer, 6, ScreenVertex::ms_decl);
}
diff --git a/src/osd/modules/render/bgfx/chainmanager.cpp b/src/osd/modules/render/bgfx/chainmanager.cpp
index 64e71bd213a..40776bb20ce 100644
--- a/src/osd/modules/render/bgfx/chainmanager.cpp
+++ b/src/osd/modules/render/bgfx/chainmanager.cpp
@@ -9,6 +9,9 @@
//
//============================================================
+#include <bx/readerwriter.h>
+#include <bx/crtimpl.h>
+
#include "emu.h"
#include "../frontend/mame/ui/slider.h"
@@ -18,8 +21,6 @@
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
-#include <bx/readerwriter.h>
-#include <bx/crtimpl.h>
#include "bgfxutil.h"
#include "chainmanager.h"
diff --git a/src/osd/modules/render/bgfx/effectmanager.cpp b/src/osd/modules/render/bgfx/effectmanager.cpp
index 2b6951e18c8..3affa36f2ec 100644
--- a/src/osd/modules/render/bgfx/effectmanager.cpp
+++ b/src/osd/modules/render/bgfx/effectmanager.cpp
@@ -12,12 +12,12 @@
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
+#include <bx/readerwriter.h>
+#include <bx/crtimpl.h>
+
#include "emu.h"
-#include <bgfx/bgfxplatform.h>
#include <bgfx/bgfx.h>
-#include <bx/readerwriter.h>
-#include <bx/crtimpl.h>
#include "effectmanager.h"
#include "effectreader.h"
diff --git a/src/osd/modules/render/bgfx/shadermanager.cpp b/src/osd/modules/render/bgfx/shadermanager.cpp
index 6e683b9d14c..e4a665d967c 100644
--- a/src/osd/modules/render/bgfx/shadermanager.cpp
+++ b/src/osd/modules/render/bgfx/shadermanager.cpp
@@ -9,14 +9,14 @@
//
//============================================================
-#include "emu.h"
-
-#include <bgfx/bgfxplatform.h>
-#include <bgfx/bgfx.h>
#include <bx/fpumath.h>
#include <bx/readerwriter.h>
#include <bx/crtimpl.h>
+#include "emu.h"
+
+#include <bgfx/bgfx.h>
+
#include "shadermanager.h"
shader_manager::~shader_manager()
diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp
index f23a5084d9f..2fb0d0b3a1e 100644
--- a/src/osd/modules/render/drawbgfx.cpp
+++ b/src/osd/modules/render/drawbgfx.cpp
@@ -5,6 +5,9 @@
// drawbgfx.cpp - BGFX renderer
//
//============================================================
+#include <bx/fpumath.h>
+#include <bx/readerwriter.h>
+
#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) || defined(OSD_UWP)
// standard windows headers
#include <windows.h>
@@ -21,10 +24,8 @@
#include "rendutil.h"
#include "aviwrite.h"
-#include <bgfx/bgfxplatform.h>
#include <bgfx/bgfx.h>
-#include <bx/fpumath.h>
-#include <bx/readerwriter.h>
+#include <bgfx/platform.h>
#include <algorithm>
#include "drawbgfx.h"
@@ -866,7 +867,7 @@ int renderer_bgfx::draw(int update)
void renderer_bgfx::update_recording()
{
- bgfx::blit(s_current_view > 0 ? s_current_view - 1 : 0, m_avi_texture, 0, 0, m_avi_target->target());
+ bgfx::blit(s_current_view > 0 ? s_current_view - 1 : 0, m_avi_texture, 0, 0, bgfx::getTexture(m_avi_target->target()));
bgfx::readTexture(m_avi_texture, m_avi_data);
int i = 0;
@@ -1260,7 +1261,7 @@ void renderer_bgfx::allocate_buffer(render_primitive *prim, uint32_t blend, bgfx
}
}
- if (vertices > 0 && bgfx::checkAvailTransientVertexBuffer(vertices, ScreenVertex::ms_decl))
+ if (vertices > 0 && vertices==bgfx::getAvailTransientVertexBuffer(vertices, ScreenVertex::ms_decl))
{
bgfx::allocTransientVertexBuffer(buffer, vertices, ScreenVertex::ms_decl);
}