diff options
Diffstat (limited to 'src')
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 ¶m_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 ®ex_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 ®ex_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 ®ex_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, ®ex_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); } |