mirror of
https://github.com/holub/mame
synced 2025-06-03 19:36:26 +03:00
Merge pull request #4368 from shattered/_b49d142
hp95lx: new NOT_WORKING machine -- Hewlett-Packard 95LX palmtop
This commit is contained in:
commit
141c263204
@ -2260,6 +2260,7 @@ files {
|
||||
MAME_DIR .. "src/mame/drivers/hp2620.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/hp700.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/hp2640.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/hp95lx.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/hp9825.cpp",
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,7 @@ const double XTAL::known_xtals[] = {
|
||||
5'000'000, /* 5_MHz_XTAL Mutant Night */
|
||||
5'068'800, /* 5.0688_MHz_XTAL Usually used as MC2661 or COM8116 baud rate clock */
|
||||
5'185'000, /* 5.185_MHz_XTAL Intel INTELLEC® 4 */
|
||||
5'370'000, /* 5.37_MHz_XTAL HP 95LX */
|
||||
5'460'000, /* 5.46_MHz_XTAL ec1840 and ec1841 keyboard */
|
||||
5'529'600, /* 5.5296_MHz_XTAL Kontron PSI98 keyboard */
|
||||
5'626'000, /* 5.626_MHz_XTAL RCA CDP1869 PAL dot clock */
|
||||
|
771
src/mame/drivers/hp95lx.cpp
Normal file
771
src/mame/drivers/hp95lx.cpp
Normal file
@ -0,0 +1,771 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Sergey Svishchev
|
||||
/***************************************************************************
|
||||
|
||||
Hewlett-Packard 95LX palmtop, code name Jaguar.
|
||||
|
||||
NEC V20 CPU @ 5.37 MHz
|
||||
HP F1000-80054 "Hopper" ASIC
|
||||
Display controller
|
||||
Keyboard controler
|
||||
UART
|
||||
Interrupt controller (8259 core)
|
||||
Interval timer (8254 core)
|
||||
Real time clock
|
||||
PCMCIA 1.0 controller
|
||||
ADC (4 channels; used to measure battery voltages)
|
||||
DAC (1 channel; can be used as tone generator)
|
||||
512KB or 1MB of RAM
|
||||
1MB of BIOS ROM (banked)
|
||||
P/N 18-5301 ABD \\ HN62318BFC26
|
||||
LCD, 240x128 pixels (40x16 chars in MDA-compatible text mode)
|
||||
|
||||
To do:
|
||||
- blue on green LCD palette
|
||||
- native keyboard
|
||||
- 1MB model
|
||||
- identify RTC core
|
||||
- everything else
|
||||
|
||||
Technical info:
|
||||
- http://web.archive.org/web/20071012040320/http://www.daniel-hertrich.de/download/95lx_devguide.zip
|
||||
- http://cd.textfiles.com/blackphilesii/PHILES/HP95/HP95DEV.ZIP
|
||||
|
||||
Useful links:
|
||||
- https://hermocom.com/hplx/view-all-hp-palmtop-articles/41-95lx
|
||||
- ftp://netflora.demon.co.uk/main/TEXT/hp95lxfaq.txt
|
||||
- https://www.finseth.com/hpdata/hp95lx.php
|
||||
has keyboard layout
|
||||
- http://cfile3.uf.tistory.com/attach/152BF03E50054B2925840F
|
||||
Explorer's Guide to the HP 95LX
|
||||
- http://www.palmtoppaper.com/ptphtml/12/pt120055.htm
|
||||
Evolution of the HP Palmtops
|
||||
- http://web.archive.org/web/20150423014908/http://www.sp.uconn.edu/~mchem1/HPLX.shtml
|
||||
HPLX-L mailing list archive
|
||||
|
||||
Software:
|
||||
- http://www.retroisle.com/others/hp95lx/software.php
|
||||
- http://www.mizj.com/
|
||||
- http://www.hp200lx.net/
|
||||
- http://www.nic.funet.fi/index/misc/hp95lx/Index
|
||||
- http://cd.textfiles.com/blackphilesii/PHILES/HP95/
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "machine/nvram.h"
|
||||
#include "machine/pic8259.h"
|
||||
#include "machine/pit8253.h"
|
||||
#include "bus/isa/isa.h"
|
||||
#include "bus/isa/isa_cards.h"
|
||||
#include "bus/pc_kbd/keyboards.h"
|
||||
#include "bus/pc_kbd/pc_kbdc.h"
|
||||
#include "cpu/nec/nec.h"
|
||||
#include "machine/bankdev.h"
|
||||
#include "machine/ram.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "emupal.h"
|
||||
#include "softlist.h"
|
||||
|
||||
|
||||
//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already
|
||||
#define LOG_KEYBOARD (1U << 1)
|
||||
#define LOG_DEBUG (1U << 2)
|
||||
|
||||
#define VERBOSE (LOG_DEBUG)
|
||||
//#define LOG_OUTPUT_FUNC printf
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGKBD(...) LOGMASKED(LOG_KEYBOARD, __VA_ARGS__)
|
||||
#define LOGDBG(...) LOGMASKED(LOG_DEBUG, __VA_ARGS__)
|
||||
|
||||
#define KBDC_TAG "pc_kbdc"
|
||||
|
||||
|
||||
class hp95lx_state : public driver_device
|
||||
{
|
||||
public:
|
||||
hp95lx_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_bankdev_c000(*this, "bankdev_c000")
|
||||
, m_bankdev_d000(*this, "bankdev_d000")
|
||||
, m_bankdev_e000(*this, "bankdev_e000")
|
||||
, m_bankdev_e400(*this, "bankdev_e400")
|
||||
, m_bankdev_e800(*this, "bankdev_e800")
|
||||
, m_bankdev_ec00(*this, "bankdev_ec00")
|
||||
, m_ram(*this, RAM_TAG)
|
||||
, m_nvram2(*this, "nvram2")
|
||||
, m_nvram3(*this, "nvram3")
|
||||
, m_isabus(*this, "isa")
|
||||
, m_pic8259(*this, "pic8259")
|
||||
, m_pit8254(*this, "pit8254")
|
||||
, m_screen(*this, "screen")
|
||||
, m_p_videoram(*this, "video")
|
||||
, m_p_chargen(*this, "gfx1")
|
||||
{ }
|
||||
|
||||
DECLARE_MACHINE_START(hp95lx);
|
||||
DECLARE_MACHINE_RESET(hp95lx);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(d300_w);
|
||||
DECLARE_READ8_MEMBER(d300_r);
|
||||
DECLARE_WRITE8_MEMBER(e300_w);
|
||||
DECLARE_READ8_MEMBER(e300_r);
|
||||
DECLARE_WRITE8_MEMBER(f300_w);
|
||||
DECLARE_READ8_MEMBER(f300_r);
|
||||
|
||||
DECLARE_PALETTE_INIT(hp95lx);
|
||||
void hp95lx(machine_config &config);
|
||||
void hp95lx_io(address_map &map);
|
||||
void hp95lx_map(address_map &map);
|
||||
void hp95lx_romdos(address_map &map);
|
||||
|
||||
protected:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<address_map_bank_device> m_bankdev_c000;
|
||||
required_device<address_map_bank_device> m_bankdev_d000;
|
||||
required_device<address_map_bank_device> m_bankdev_e000;
|
||||
required_device<address_map_bank_device> m_bankdev_e400;
|
||||
required_device<address_map_bank_device> m_bankdev_e800;
|
||||
required_device<address_map_bank_device> m_bankdev_ec00;
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<nvram_device> m_nvram2;
|
||||
optional_device<nvram_device> m_nvram3;
|
||||
required_device<isa8_device> m_isabus;
|
||||
required_device<pic8259_device> m_pic8259;
|
||||
required_device<pit8254_device> m_pit8254;
|
||||
required_device<screen_device> m_screen;
|
||||
|
||||
private:
|
||||
DECLARE_WRITE_LINE_MEMBER(keyboard_clock_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(keyboard_data_w);
|
||||
DECLARE_READ8_MEMBER(keyboard_r);
|
||||
DECLARE_WRITE8_MEMBER(keyboard_w);
|
||||
DECLARE_READ8_MEMBER(video_r);
|
||||
DECLARE_WRITE8_MEMBER(video_w);
|
||||
DECLARE_WRITE8_MEMBER(video_address_w);
|
||||
DECLARE_READ8_MEMBER(video_register_r);
|
||||
DECLARE_WRITE8_MEMBER(video_register_w);
|
||||
DECLARE_WRITE8_MEMBER(debug_w);
|
||||
|
||||
required_shared_ptr<u8> m_p_videoram;
|
||||
required_region_ptr<u8> m_p_chargen;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
u8 m_mapper[32], m_rtcram[2];
|
||||
|
||||
// crtc
|
||||
u8 m_crtc[64], m_cursor_start_ras;
|
||||
u16 m_disp_start_addr, m_cursor_addr, m_window_start_addr;
|
||||
int m_register_address_latch;
|
||||
bool m_graphics_mode;
|
||||
|
||||
// from pt68k4.cpp
|
||||
bool m_kclk;
|
||||
uint8_t m_kdata;
|
||||
uint8_t m_scancode;
|
||||
uint8_t m_kbdflag;
|
||||
int m_kbit;
|
||||
};
|
||||
|
||||
|
||||
PALETTE_INIT_MEMBER(hp95lx_state, hp95lx)
|
||||
{
|
||||
palette.set_pen_color(0, 0xa0, 0xa8, 0xa0);
|
||||
palette.set_pen_color(1, 0x30, 0x38, 0x10);
|
||||
}
|
||||
|
||||
uint32_t hp95lx_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int x, y, offset;
|
||||
uint16_t gfx, *p;
|
||||
uint8_t chr, attr;
|
||||
|
||||
if (m_graphics_mode)
|
||||
{
|
||||
for (y = 0; y < 128; y++)
|
||||
{
|
||||
p = &bitmap.pix16(y);
|
||||
offset = y * (240 / 8);
|
||||
|
||||
for (x = offset; x < offset + (240 / 8); x++)
|
||||
{
|
||||
gfx = m_p_videoram[x];
|
||||
|
||||
for (int i = 7; i >= 0; i--)
|
||||
{
|
||||
*p++ = BIT(gfx, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool blink((m_screen->frame_number() % 10) > 4);
|
||||
|
||||
// screen memory is normal MDA 80x25, but only a scrollable 40x16 window is displayed
|
||||
for (y = 0; y < 128; y++)
|
||||
{
|
||||
p = &bitmap.pix16(y);
|
||||
offset = (y / 8) * 160 + m_window_start_addr;
|
||||
|
||||
for (x = offset; x < offset + 80; x += 2)
|
||||
{
|
||||
chr = m_p_videoram[x];
|
||||
attr = m_p_videoram[x + 1];
|
||||
|
||||
gfx = m_p_chargen[(chr)*8 + (y % 8)];
|
||||
|
||||
if ((x >> 1) == m_cursor_addr && blink && (y % 8) >= m_cursor_start_ras)
|
||||
{
|
||||
gfx = 0xff;
|
||||
}
|
||||
|
||||
switch (attr)
|
||||
{
|
||||
case 0x00:
|
||||
gfx = 0;
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
if (y % 8 == 7) gfx = 0xff;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
gfx ^= 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 5; i >= 0; i--)
|
||||
{
|
||||
*p++ = BIT(gfx, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
MACHINE_START_MEMBER(hp95lx_state, hp95lx)
|
||||
{
|
||||
save_item(NAME(m_mapper));
|
||||
save_item(NAME(m_rtcram));
|
||||
save_item(NAME(m_crtc));
|
||||
save_item(NAME(m_graphics_mode));
|
||||
|
||||
//
|
||||
save_item(NAME(m_kclk));
|
||||
save_item(NAME(m_kdata));
|
||||
save_item(NAME(m_scancode));
|
||||
save_item(NAME(m_kbdflag));
|
||||
save_item(NAME(m_kbit));
|
||||
|
||||
memcpy(m_p_chargen, memregion("romdos")->base() + 0xffa6e, 0x0400);
|
||||
memcpy(m_p_chargen + 0x0400, memregion("romdos")->base() + 0xfb200, 0x0400);
|
||||
}
|
||||
|
||||
MACHINE_RESET_MEMBER(hp95lx_state, hp95lx)
|
||||
{
|
||||
std::fill(std::begin(m_mapper), std::end(m_mapper), 0);
|
||||
std::fill(std::begin(m_rtcram), std::end(m_rtcram), 0);
|
||||
|
||||
std::fill(std::begin(m_crtc), std::end(m_crtc), 0);
|
||||
m_graphics_mode = false;
|
||||
m_cursor_start_ras = 7;
|
||||
m_disp_start_addr = 0;
|
||||
m_cursor_addr = 0;
|
||||
|
||||
m_kclk = true;
|
||||
m_kbit = 0;
|
||||
m_scancode = 0;
|
||||
m_kbdflag = 0;
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(hp95lx_state::d300_w)
|
||||
{
|
||||
LOG("%s: IO %04x <- %02x\n", machine().describe_context(), 0xd300 + offset, data);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
m_window_start_addr = ((data & 0xff) << 0) | (m_window_start_addr & 0xff00);
|
||||
break;
|
||||
case 1:
|
||||
m_window_start_addr = ((data & 0x3f) << 8) | (m_window_start_addr & 0x00ff);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_graphics_mode = !BIT(data, 4);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
m_rtcram[offset - 6] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp95lx_state::d300_r)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
data = m_window_start_addr;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
data = m_window_start_addr >> 8;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
data = 0x2;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
data = m_rtcram[offset - 6];
|
||||
break;
|
||||
}
|
||||
|
||||
LOG("%s: IO %04x == %02x\n", machine().describe_context(), 0xd300 + offset, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp95lx_state::e300_w)
|
||||
{
|
||||
LOG("%s: IO %04x <- %02x\n", machine().describe_context(), 0xe300 + offset, data);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 1: // b1 = 'IR interrupt enable' (per IR.DOC)
|
||||
break;
|
||||
|
||||
case 2: // interrupt control (per snd.c), 0: disable all, 127: enable all
|
||||
break;
|
||||
|
||||
case 5: // DAC out (per snd.c)
|
||||
break;
|
||||
|
||||
case 9: // b1 = 'a2d power' (per snd.c)
|
||||
break;
|
||||
|
||||
case 10: // IRFMAT register (per IR.DOC)
|
||||
break;
|
||||
|
||||
case 11: // IR transmit/receive register (per IR.DOC)
|
||||
break;
|
||||
|
||||
case 13: // reset?
|
||||
break;
|
||||
|
||||
case 14: // keyboard output?
|
||||
case 15:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp95lx_state::e300_r)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 2: // b6 = low battery? (FD97Eh)
|
||||
break;
|
||||
|
||||
case 4: // Card Detect Register (per chap5.txt)
|
||||
data = 0x50; // memory card inserted
|
||||
break;
|
||||
|
||||
case 7:
|
||||
data = 0x20;
|
||||
break;
|
||||
|
||||
case 9: // FF889h. b0 = ADC ready? (per snd2.c)
|
||||
break;
|
||||
|
||||
case 10: // IRFMAT register (per IR.DOC)
|
||||
break;
|
||||
|
||||
case 11: // IR transmit/receive register (per IR.DOC)
|
||||
break;
|
||||
|
||||
case 14: // keyboard status?
|
||||
case 15:
|
||||
return data;
|
||||
break;
|
||||
}
|
||||
|
||||
LOG("%s: IO %04x == %02x\n", machine().describe_context(), 0xe300 + offset, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp95lx_state::f300_w)
|
||||
{
|
||||
address_map_bank_device *mapper;
|
||||
const char *mapname;
|
||||
|
||||
LOG("%s: IO %04x <- %02x\n", machine().describe_context(), 0xf300 + offset, data);
|
||||
|
||||
if (offset >= sizeof(m_mapper)) return;
|
||||
|
||||
m_mapper[offset] = data;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x11: // E0000 16K
|
||||
mapper = m_bankdev_e000;
|
||||
mapname = "E0000";
|
||||
break;
|
||||
|
||||
case 0x13: // E4000 16K
|
||||
mapper = m_bankdev_e400;
|
||||
mapname = "E4000";
|
||||
break;
|
||||
|
||||
case 0x15: // E8000 16K
|
||||
mapper = m_bankdev_e800;
|
||||
mapname = "E8000";
|
||||
break;
|
||||
|
||||
case 0x17: // EC000 16K
|
||||
mapper = m_bankdev_ec00;
|
||||
mapname = "EC000";
|
||||
break;
|
||||
|
||||
case 0x18: // C0000 64K
|
||||
mapper = m_bankdev_c000;
|
||||
mapname = "C0000";
|
||||
break;
|
||||
|
||||
case 0x19: // D0000 64K
|
||||
mapper = m_bankdev_d000;
|
||||
mapname = "D0000";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x11: case 0x13: case 0x15: case 0x17:
|
||||
switch (data)
|
||||
{
|
||||
case 0: // internal
|
||||
if (m_mapper[offset - 1])
|
||||
{
|
||||
LOG("MAPPER %s <- %05X\n", mapname, (m_mapper[offset - 1] & 127) * 0x2000);
|
||||
mapper->set_bank((m_mapper[offset - 1] >> 1) & 63);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // unknown
|
||||
case 2:
|
||||
break;
|
||||
|
||||
case 4: // card slot
|
||||
LOG("MAPPER %s <- %06X (card)\n", mapname, (m_mapper[offset - 1]) * 0x2000);
|
||||
mapper->set_bank(0x1000 + (m_mapper[offset - 1] >> 1));
|
||||
break;
|
||||
|
||||
case 7: // XXX unmap
|
||||
LOG("MAPPER %s <- unmap\n", mapname);
|
||||
mapper->set_bank(0x400);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x18: case 0x19:
|
||||
switch (data & 7)
|
||||
{
|
||||
case 0:
|
||||
if ((data & 0x87) == 0x80)
|
||||
{
|
||||
LOG("MAPPER %s <- %X0000\n", mapname, (data >> 3) & 15);
|
||||
mapper->set_bank((data >> 3) & 15);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // XXX
|
||||
break;
|
||||
|
||||
case 7: // XXX unmap
|
||||
LOG("MAPPER %s <- unmap\n", mapname);
|
||||
mapper->set_bank(0x40);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp95lx_state::f300_r)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
|
||||
LOG("%s: IO %04x == %02x\n", machine().describe_context(), 0xf300 + offset, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* keyboard HLE -- adapted from pt68k4.cpp */
|
||||
|
||||
READ8_MEMBER(hp95lx_state::keyboard_r)
|
||||
{
|
||||
if (offset == 0)
|
||||
{
|
||||
LOGKBD("kbd: read %02X == %02X\n", offset + 0x60, m_scancode);
|
||||
m_pic8259->ir1_w(CLEAR_LINE);
|
||||
return m_scancode;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp95lx_state::keyboard_w)
|
||||
{
|
||||
LOGKBD("kbd: write %02X <= %02X\n", offset + 0x60, data);
|
||||
m_pic8259->ir1_w(CLEAR_LINE);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp95lx_state::keyboard_clock_w)
|
||||
{
|
||||
LOGKBD("kbd: KCLK: %d kbit: %d\n", state ? 1 : 0, m_kbit);
|
||||
|
||||
if ((state == ASSERT_LINE) && (!m_kclk))
|
||||
{
|
||||
if (m_kbit >= 1 && m_kbit <= 8)
|
||||
{
|
||||
m_scancode >>= 1;
|
||||
m_scancode |= m_kdata;
|
||||
}
|
||||
|
||||
// stop bit?
|
||||
if (m_kbit == 9)
|
||||
{
|
||||
m_scancode >>= 1;
|
||||
m_scancode |= m_kdata;
|
||||
// XXX map F2..F10 to blue function keys
|
||||
if (m_scancode > 0x3B && m_scancode < 0x45) m_scancode += 0x36;
|
||||
LOGKBD("kbd: scancode %02x\n", m_scancode);
|
||||
m_kbit = 0;
|
||||
m_pic8259->ir1_w(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_kbit++;
|
||||
}
|
||||
}
|
||||
|
||||
m_kclk = (state == ASSERT_LINE) ? true : false;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp95lx_state::keyboard_data_w)
|
||||
{
|
||||
LOGKBD("kbd: KDATA: %d\n", state ? 1 : 0);
|
||||
m_kdata = (state == ASSERT_LINE) ? 0x80 : 0x00;
|
||||
}
|
||||
|
||||
/* video HLE */
|
||||
|
||||
READ8_MEMBER(hp95lx_state::video_register_r)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
|
||||
switch (m_register_address_latch)
|
||||
{
|
||||
case 0x0e:
|
||||
ret = (m_cursor_addr >> 8) & 0xff;
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
ret = (m_cursor_addr >> 0) & 0xff;
|
||||
break;
|
||||
|
||||
/* all other registers are write only and return 0 */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp95lx_state::video_register_w)
|
||||
{
|
||||
switch (m_register_address_latch)
|
||||
{
|
||||
case 0x0a:
|
||||
m_cursor_start_ras = data & 0x7f;
|
||||
break;
|
||||
|
||||
case 0x0c:
|
||||
m_disp_start_addr = ((data & 0x3f) << 8) | (m_disp_start_addr & 0x00ff);
|
||||
break;
|
||||
|
||||
case 0x0d:
|
||||
m_disp_start_addr = ((data & 0xff) << 0) | (m_disp_start_addr & 0xff00);
|
||||
break;
|
||||
|
||||
case 0x0e:
|
||||
m_cursor_addr = ((data & 0x3f) << 8) | (m_cursor_addr & 0x00ff);
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
m_cursor_addr = ((data & 0xff) << 0) | (m_cursor_addr & 0xff00);
|
||||
m_pic8259->ir2_w(ASSERT_LINE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp95lx_state::video_address_w)
|
||||
{
|
||||
m_register_address_latch = data & 0x3f;
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp95lx_state::video_r)
|
||||
{
|
||||
int data = 0xff;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 1: case 3: case 5: case 7:
|
||||
data = video_register_r(space, offset);
|
||||
break;
|
||||
|
||||
case 10:
|
||||
data = 0xf0; // video_status_r(offset):
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp95lx_state::video_w)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: case 2: case 4: case 6:
|
||||
video_address_w(space, offset, data);
|
||||
break;
|
||||
|
||||
case 1: case 3: case 5: case 7:
|
||||
video_register_w(space, offset, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp95lx_state::debug_w)
|
||||
{
|
||||
LOGDBG("%11.6f %s debug: port %02X <= %02X\n", machine().time().as_double(), machine().describe_context(), offset + 0x90, data);
|
||||
}
|
||||
|
||||
|
||||
void hp95lx_state::hp95lx_romdos(address_map &map)
|
||||
{
|
||||
map(0x0000000, 0x00fffff).rom().region("romdos", 0);
|
||||
map(0x4000000, 0x41fffff).ram().share("nvram3");
|
||||
}
|
||||
|
||||
void hp95lx_state::hp95lx_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x00000, 0x7ffff).ram().share("nvram2");
|
||||
map(0xa0000, 0xaffff).rom().region("romdos", 0xe0000); // OS functions (DOS, COMMAND.COM)
|
||||
map(0xb0000, 0xb0fff).ram().share("video");
|
||||
map(0xc0000, 0xcffff).rw(m_bankdev_c000, FUNC(address_map_bank_device::read8), FUNC(address_map_bank_device::write8));
|
||||
map(0xd0000, 0xdffff).rw(m_bankdev_d000, FUNC(address_map_bank_device::read8), FUNC(address_map_bank_device::write8));
|
||||
map(0xe0000, 0xe3fff).rw(m_bankdev_e000, FUNC(address_map_bank_device::read8), FUNC(address_map_bank_device::write8));
|
||||
map(0xe4000, 0xe7fff).rw(m_bankdev_e400, FUNC(address_map_bank_device::read8), FUNC(address_map_bank_device::write8));
|
||||
map(0xe8000, 0xebfff).rw(m_bankdev_e800, FUNC(address_map_bank_device::read8), FUNC(address_map_bank_device::write8));
|
||||
map(0xec000, 0xeffff).rw(m_bankdev_ec00, FUNC(address_map_bank_device::read8), FUNC(address_map_bank_device::write8));
|
||||
map(0xf0000, 0xfffff).rom().region("romdos", 0xf0000); // BIOS ROM and SysMgr
|
||||
}
|
||||
|
||||
void hp95lx_state::hp95lx_io(address_map &map)
|
||||
{
|
||||
map.unmap_value_low();
|
||||
map(0x0020, 0x002f).rw("pic8259", FUNC(pic8259_device::read), FUNC(pic8259_device::write));
|
||||
map(0x0040, 0x004f).rw("pit8254", FUNC(pit8254_device::read), FUNC(pit8254_device::write));
|
||||
map(0x0060, 0x0063).rw(FUNC(hp95lx_state::keyboard_r), FUNC(hp95lx_state::keyboard_w));
|
||||
// map(0x0090, 0x009f).w(FUNC(hp95lx_state::debug_w));
|
||||
map(0x03b0, 0x03bf).rw(FUNC(hp95lx_state::video_r), FUNC(hp95lx_state::video_w));
|
||||
// map(0x0070, 0x007f) RTC
|
||||
map(0xd300, 0xd30f).rw(FUNC(hp95lx_state::d300_r), FUNC(hp95lx_state::d300_w));
|
||||
map(0xe300, 0xe30f).rw(FUNC(hp95lx_state::e300_r), FUNC(hp95lx_state::e300_w));
|
||||
map(0xf300, 0xf31f).rw(FUNC(hp95lx_state::f300_r), FUNC(hp95lx_state::f300_w));
|
||||
}
|
||||
|
||||
|
||||
MACHINE_CONFIG_START(hp95lx_state::hp95lx)
|
||||
MCFG_DEVICE_ADD("maincpu", V20, XTAL(5'370'000))
|
||||
MCFG_DEVICE_PROGRAM_MAP(hp95lx_map)
|
||||
MCFG_DEVICE_IO_MAP(hp95lx_io)
|
||||
MCFG_DEVICE_IRQ_ACKNOWLEDGE_DEVICE("pic8259", pic8259_device, inta_cb)
|
||||
|
||||
MCFG_MACHINE_START_OVERRIDE(hp95lx_state, hp95lx)
|
||||
MCFG_MACHINE_RESET_OVERRIDE(hp95lx_state, hp95lx)
|
||||
|
||||
ADDRESS_MAP_BANK(config, "bankdev_c000").set_map(&hp95lx_state::hp95lx_romdos).set_options(ENDIANNESS_LITTLE, 8, 32, 0x10000);
|
||||
ADDRESS_MAP_BANK(config, "bankdev_d000").set_map(&hp95lx_state::hp95lx_romdos).set_options(ENDIANNESS_LITTLE, 8, 32, 0x10000);
|
||||
ADDRESS_MAP_BANK(config, "bankdev_e000").set_map(&hp95lx_state::hp95lx_romdos).set_options(ENDIANNESS_LITTLE, 8, 32, 0x4000);
|
||||
ADDRESS_MAP_BANK(config, "bankdev_e400").set_map(&hp95lx_state::hp95lx_romdos).set_options(ENDIANNESS_LITTLE, 8, 32, 0x4000);
|
||||
ADDRESS_MAP_BANK(config, "bankdev_e800").set_map(&hp95lx_state::hp95lx_romdos).set_options(ENDIANNESS_LITTLE, 8, 32, 0x4000);
|
||||
ADDRESS_MAP_BANK(config, "bankdev_ec00").set_map(&hp95lx_state::hp95lx_romdos).set_options(ENDIANNESS_LITTLE, 8, 32, 0x4000);
|
||||
|
||||
PIT8254(config, m_pit8254, 0);
|
||||
m_pit8254->set_clk<0>(XTAL(14'318'181)/12); /* heartbeat IRQ */
|
||||
m_pit8254->out_handler<0>().set(m_pic8259, FUNC(pic8259_device::ir0_w));
|
||||
m_pit8254->set_clk<1>(XTAL(14'318'181)/12); /* misc IRQ */
|
||||
m_pit8254->out_handler<1>().set(m_pic8259, FUNC(pic8259_device::ir2_w));
|
||||
|
||||
PIC8259(config, m_pic8259, 0);
|
||||
m_pic8259->out_int_callback().set_inputline(m_maincpu, 0);
|
||||
|
||||
MCFG_MACHINE_RESET_OVERRIDE(hp95lx_state, hp95lx)
|
||||
|
||||
ISA8(config, m_isabus, 0);
|
||||
m_isabus->set_cputag("maincpu");
|
||||
|
||||
MCFG_DEVICE_ADD("board0", ISA8_SLOT, 0, "isa", pc_isa8_cards, "com", true)
|
||||
|
||||
MCFG_DEVICE_ADD(KBDC_TAG, PC_KBDC, 0)
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE(*this, hp95lx_state, keyboard_clock_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE(*this, hp95lx_state, keyboard_data_w))
|
||||
MCFG_PC_KBDC_SLOT_ADD(KBDC_TAG, "kbd", pc_xt_keyboards, STR_KBD_KEYTRONIC_PC3270)
|
||||
|
||||
NVRAM(config, "nvram2", nvram_device::DEFAULT_ALL_0); // RAM
|
||||
NVRAM(config, "nvram3", nvram_device::DEFAULT_ALL_0); // card slot
|
||||
|
||||
// XXX When the AC adapter is plugged in, the LCD refresh rate is 73.14 Hz.
|
||||
// XXX When the AC adapter is not plugged in (ie, running off of batteries) the refresh rate is 56.8 Hz.
|
||||
MCFG_SCREEN_ADD_MONOCHROME("screen", LCD, rgb_t::white())
|
||||
MCFG_SCREEN_UPDATE_DRIVER(hp95lx_state, screen_update)
|
||||
MCFG_SCREEN_RAW_PARAMS(XTAL(5'370'000) / 2, 300, 0, 240, 180, 0, 128)
|
||||
|
||||
MCFG_SCREEN_PALETTE("palette")
|
||||
MCFG_PALETTE_ADD("palette", 2)
|
||||
MCFG_PALETTE_INIT_OWNER(hp95lx_state, hp95lx)
|
||||
|
||||
RAM(config, RAM_TAG).set_default_size("512K");
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
ROM_START( hp95lx )
|
||||
ROM_REGION16_LE(0x100000, "romdos", 0)
|
||||
// Version A ... ROM BIOS Ver 2.14 ... 04/02/91
|
||||
ROM_LOAD("18-5301.abd.bin", 0, 0x100000, CRC(18121c48) SHA1(c3bfb45cbbf4f57ae67fb5659da40f371d8e5c54))
|
||||
|
||||
ROM_REGION(0x800,"gfx1", ROMREGION_ERASE00)
|
||||
ROM_END
|
||||
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1991, hp95lx, 0, 0, hp95lx, 0, hp95lx_state, empty_init, "Hewlett-Packard", "HP 95LX", MACHINE_NOT_WORKING|MACHINE_NO_SOUND )
|
@ -15343,6 +15343,9 @@ hp64k //
|
||||
hp700_70 //
|
||||
hp700_92 //
|
||||
|
||||
@source:hp95lx.cpp
|
||||
hp95lx //
|
||||
|
||||
@source:hp9825.cpp
|
||||
hp9825b // HP 9825B
|
||||
|
||||
|
@ -297,6 +297,7 @@ hp48.cpp
|
||||
hp49gp.cpp
|
||||
hp64k.cpp
|
||||
hp700.cpp
|
||||
hp95lx.cpp
|
||||
hp9825.cpp
|
||||
hp9845.cpp
|
||||
hp9k.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user