hp_ipc: added configurable VRAM size, auto configuration & a few minor

commands to HP1LL3 GPU
This commit is contained in:
fulivi 2018-08-14 11:00:01 +02:00 committed by Vas Crabb
parent 1db10c9857
commit 717115443c
3 changed files with 184 additions and 82 deletions

View File

@ -19,13 +19,6 @@
- windows with blitter (copy, fill and scroll) and clipping - windows with blitter (copy, fill and scroll) and clipping
To do: To do:
. proper cursor and mouse pointers [cursor can be offset from the pen location]
+ variable width fonts [?? placed relative to current window]
+ basic lines
- patterned lines
. bit blits & scroll
. meaning of WRRR bits
. meaning of CONF data [+ autoconfiguration]
- interrupt generation - interrupt generation
- realistic timing? - realistic timing?
- &c. - &c.
@ -145,9 +138,6 @@ constexpr uint16_t MSB_MASK = 0x8000; // Mask of MSB
} \ } \
} while (0) } while (0)
// This is the size for 9807. To be made configurable.
#define HPGPU_VRAM_SIZE 16384
// Index of words in configuration vector // Index of words in configuration vector
enum : unsigned enum : unsigned
{ {
@ -161,18 +151,18 @@ enum : unsigned
CONF_VER_3 = 7, // Vertical timing, 4th word CONF_VER_3 = 7, // Vertical timing, 4th word
CONF_WPL = 8, // Words per line CONF_WPL = 8, // Words per line
CONF_LINES = 9, // Lines CONF_LINES = 9, // Lines
CONF_RAM_SIZE = 10 // RAM size (?) CONF_OPTS = 10 // RAM size or option bits (more likely)
}; };
// Fields of hor/ver timing words // Fields of hor/ver timing words
enum : uint16_t enum : uint16_t
{ {
HV_CNT_MASK = 0x3ff, // Mask of counter part HV_CNT_MASK = 0x3ff, // Mask of counter part
HV_ZONE_MASK = 0xc000, // Mask of zone part HV_ZONE_MASK = 0xc00, // Mask of zone part
HV_ZONE_0 = 0x0000, // Value for zone 0 HV_ZONE_0 = 0x000, // Value for zone 0
HV_ZONE_1 = 0x4000, // Value for zone 1 HV_ZONE_1 = 0x400, // Value for zone 1
HV_ZONE_2 = 0x8000, // Value for zone 2 HV_ZONE_2 = 0x800, // Value for zone 2
HV_ZONE_3 = 0xc000 // Value for zone 3 HV_ZONE_3 = 0xc00 // Value for zone 3
}; };
//************************************************************************** //**************************************************************************
@ -194,10 +184,10 @@ DEFINE_DEVICE_TYPE(HP1LL3, hp1ll3_device, "hp1ll3", "Hewlett-Packard 1LL3-0005 G
hp1ll3_device::hp1ll3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) hp1ll3_device::hp1ll3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, HP1LL3, tag, owner, clock) : device_t(mconfig, HP1LL3, tag, owner, clock)
, device_video_interface(mconfig, *this) , device_video_interface(mconfig, *this)
, m_vram_size(16)
{ {
} }
//------------------------------------------------- //-------------------------------------------------
// device_start - device-specific startup // device_start - device-specific startup
//------------------------------------------------- //-------------------------------------------------
@ -211,17 +201,17 @@ void hp1ll3_device::device_start()
screen().register_screen_bitmap(m_bitmap); screen().register_screen_bitmap(m_bitmap);
m_videoram = std::make_unique<uint16_t[]>(HPGPU_VRAM_SIZE); m_videoram = std::make_unique<uint16_t[]>(m_vram_size);
save_pointer(NAME(m_videoram), HPGPU_VRAM_SIZE); save_pointer(NAME(m_videoram) , m_vram_size);
m_ram_addr_mask = 0x3fff; m_ram_addr_mask = uint16_t(m_vram_size - 1);
m_horiz_pix_total = visarea.max_x + 1; m_horiz_pix_total = visarea.max_x + 1;
m_vert_pix_total = visarea.max_y + 1; m_vert_pix_total = visarea.max_y + 1;
} }
void hp1ll3_device::device_reset() void hp1ll3_device::device_reset()
{ {
m_io_ptr = m_command = 0; m_rd_ptr = m_wr_ptr = m_command = 0;
m_sad = m_fad = m_dad = m_org = m_rr = m_udl = 0; m_sad = m_fad = m_dad = m_org = m_rr = m_udl = 0;
m_enable_video = m_enable_cursor = m_enable_sprite = m_busy = false; m_enable_video = m_enable_cursor = m_enable_sprite = m_busy = false;
} }
@ -357,13 +347,23 @@ void hp1ll3_device::line(int x1, int y1, int x2, int y2)
} }
} }
void hp1ll3_device::get_font(uint16_t& font_data, uint16_t& font_height) const
{
font_data = m_fad + rd_video(m_fad + 1) + 2;
font_height = rd_video(m_fad);
}
void hp1ll3_device::label(uint8_t chr, int width) void hp1ll3_device::label(uint8_t chr, int width)
{ {
draw_cursor_sprite(); draw_cursor_sprite();
uint16_t font_data;
uint16_t font_height;
get_font(font_data, font_height);
Rectangle clip = get_window(); Rectangle clip = get_window();
Rectangle dst{{ m_cursor_x, m_cursor_y }, { uint16_t(width), m_fontheight }}; Rectangle dst{{ m_cursor_x, m_cursor_y }, { uint16_t(width), font_height }};
bitblt(m_fontdata + chr * 16, 16, 16, Point { 0, 0 }, clip, dst, m_rr); bitblt(font_data + chr * 16, 16, 16, Point { 0, 0 }, clip, dst, m_rr);
m_cursor_x += width; m_cursor_x += width;
draw_cursor_sprite(); draw_cursor_sprite();
} }
@ -639,6 +639,18 @@ void hp1ll3_device::set_sprite_pos(Point p)
} }
} }
void hp1ll3_device::disable_cursor()
{
draw_cursor();
m_enable_cursor = false;
}
void hp1ll3_device::disable_sprite()
{
draw_sprite();
m_enable_sprite = false;
}
hp1ll3_device::Rectangle hp1ll3_device::get_window() const hp1ll3_device::Rectangle hp1ll3_device::get_window() const
{ {
return Rectangle{{ m_window.org_x, m_window.org_y }, { m_window.width, m_window.height }}; return Rectangle{{ m_window.org_x, m_window.org_y }, { m_window.width, m_window.height }};
@ -649,9 +661,49 @@ hp1ll3_device::Rectangle hp1ll3_device::get_screen() const
return Rectangle{{ 0, 0 }, { uint16_t(m_horiz_pix_total), uint16_t(m_vert_pix_total) }}; return Rectangle{{ 0, 0 }, { uint16_t(m_horiz_pix_total), uint16_t(m_vert_pix_total) }};
} }
void hp1ll3_device::get_hv_timing(bool vertical, unsigned& total, unsigned& active) const
{
unsigned idx = vertical ? CONF_VER_0 : CONF_HOR_0;
// Look for active part (zone 1) & compute total time
total = 0;
active = 0;
for (unsigned i = 0; i < 4; ++i) {
unsigned cnt = (m_conf[idx + i] & HV_CNT_MASK) + 1;
total += cnt;
if ((m_conf[idx + i] & HV_ZONE_MASK) == HV_ZONE_1) {
active = cnt;
// It seems that if a zone 2 comes immediately before a zone 1, it's
// counted in the active part
unsigned idx_1 = (i + 3) % 4 + idx;
if ((m_conf[idx_1] & HV_ZONE_MASK) == HV_ZONE_2) {
active += (m_conf[idx_1] & HV_CNT_MASK) + 1;
}
}
}
DBG_LOG(2, 0, ("H/V=%d total=%u active=%u\n", vertical, total, active));
}
void hp1ll3_device::apply_conf() void hp1ll3_device::apply_conf()
{ {
// TODO: unsigned h_total;
unsigned h_active;
unsigned v_total;
unsigned v_active;
get_hv_timing(false, h_total, h_active);
get_hv_timing(true, v_total, v_active);
// Dot clock is 4 times the GPU clock, H timings are in units of half the GPU clock
// I suspect that the GPU has a kind of "double clock" mode that is enabled by option bits in the last conf word.
// Without clock doubling, the HP-9808A video has a strange frame rate (~32Hz).
h_total *= 8;
h_active *= 8;
attotime frame_rate{clocks_to_attotime(h_total * v_total)};
screen().configure(h_total, v_total, rectangle{0, int32_t(h_active - 1), 0, int32_t(v_active - 1)}, frame_rate.attoseconds() / 4);
m_horiz_pix_total = h_active;
m_vert_pix_total = v_active;
} }
uint32_t hp1ll3_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) uint32_t hp1ll3_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
@ -662,10 +714,9 @@ uint32_t hp1ll3_device::screen_update(screen_device &screen, bitmap_ind16 &bitma
return 0; return 0;
} }
// XXX last line is not actually drawn on real hw
for (int y = 0; y < m_vert_pix_total; y++) for (int y = 0; y < m_vert_pix_total; y++)
{ {
int const offset = m_sad + y * (m_horiz_pix_total / 16); int const offset = m_sad + y*m_conf[CONF_WPL];
uint16_t *p = &m_bitmap.pix16(y); uint16_t *p = &m_bitmap.pix16(y);
for (int x = offset; x < offset + m_horiz_pix_total / 16; x++) for (int x = offset; x < offset + m_horiz_pix_total / 16; x++)
@ -723,7 +774,7 @@ READ8_MEMBER( hp1ll3_device::read )
} }
else else
{ {
if (!(m_io_ptr & 1)) if (!(m_rd_ptr & 1))
{ {
switch (m_command) switch (m_command)
{ {
@ -762,19 +813,39 @@ READ8_MEMBER( hp1ll3_device::read )
break; break;
case RDP: case RDP:
if (m_io_ptr == 0) if (m_rd_ptr == 0)
m_io_word = m_cursor_x; m_io_word = m_cursor_x;
else if (m_io_ptr == 2) else if (m_rd_ptr == 2)
m_io_word = m_cursor_y; m_io_word = m_cursor_y;
break; break;
case RDSP: case RDSP:
if (m_io_ptr == 0) if (m_rd_ptr == 0)
m_io_word = m_sprite_x; m_io_word = m_sprite_x;
else if (m_io_ptr == 2) else if (m_rd_ptr == 2)
m_io_word = m_sprite_y; m_io_word = m_sprite_y;
break; break;
case RDWINPARM:
switch (m_rd_ptr)
{
case 0:
m_io_word = m_window.org_x;
break;
case 2:
m_io_word = m_window.org_y;
break;
case 4:
m_io_word = m_window.width;
break;
case 6:
m_io_word = m_window.height;
break;
default:
break;
}
break;
case ID: case ID:
/* /*
* 'diagb' ROM accepts either of these ID values * 'diagb' ROM accepts either of these ID values
@ -788,7 +859,7 @@ READ8_MEMBER( hp1ll3_device::read )
{ {
data = m_io_word & 0xff; data = m_io_word & 0xff;
} }
m_io_ptr++; m_rd_ptr++;
} }
DBG_LOG(1,"HPGPU", ("R @ %d == %02x\n", offset, data)); DBG_LOG(1,"HPGPU", ("R @ %d == %02x\n", offset, data));
@ -811,7 +882,7 @@ WRITE8_MEMBER( hp1ll3_device::write )
} }
else else
{ {
if (!(m_io_ptr & 1)) if (!(m_wr_ptr & 1))
{ {
m_io_word = uint16_t(data) << 8; m_io_word = uint16_t(data) << 8;
} }
@ -821,11 +892,11 @@ WRITE8_MEMBER( hp1ll3_device::write )
switch (m_command) switch (m_command)
{ {
case CONF: case CONF:
m_conf[m_io_ptr >> 1] = m_io_word; m_conf[m_wr_ptr >> 1] = m_io_word;
DBG_LOG(1,"HPGPU",("CONF data word %d received: %04X\n", m_io_ptr >> 1, m_io_word)); DBG_LOG(1,"HPGPU",("CONF data word %d received: %04X\n", m_wr_ptr >> 1, m_io_word));
if ((m_io_ptr >> 1) == 10) { if ((m_wr_ptr >> 1) == 10) {
apply_conf(); apply_conf();
m_io_ptr = -1; m_wr_ptr = -1;
m_command = NOP; m_command = NOP;
} }
break; break;
@ -844,10 +915,7 @@ WRITE8_MEMBER( hp1ll3_device::write )
unsigned bit = m_rw_win_x % WS; unsigned bit = m_rw_win_x % WS;
int width = m_window.width + m_window.org_x - m_rw_win_x; int width = m_window.width + m_window.org_x - m_rw_win_x;
if (width <= 0) if (width <= 0)
{
m_command = NOP; m_command = NOP;
draw_cursor_sprite();
}
else else
{ {
unsigned w = std::min(WS, unsigned(width)); unsigned w = std::min(WS, unsigned(width));
@ -871,22 +939,19 @@ WRITE8_MEMBER( hp1ll3_device::write )
m_rw_win_x = m_window.org_x; m_rw_win_x = m_window.org_x;
m_rw_win_y++; m_rw_win_y++;
if (m_rw_win_y >= (m_window.height + m_window.org_y)) if (m_rw_win_y >= (m_window.height + m_window.org_y))
{
m_command = NOP; m_command = NOP;
draw_cursor_sprite();
}
} }
} }
} }
break; break;
default: default:
if (m_io_ptr <= 4) if (m_wr_ptr <= 4)
m_input[m_io_ptr / 2] = m_io_word; m_input[m_wr_ptr / 2] = m_io_word;
DBG_LOG(2,"HPGPU",("wrote %02x at %d, input buffer is %04X %04X\n", data, m_io_ptr, m_input[0], m_input[1])); DBG_LOG(2,"HPGPU",("wrote %02x at %d, input buffer is %04X %04X\n", data, m_wr_ptr, m_input[0], m_input[1]));
} }
} }
m_io_ptr++; m_wr_ptr++;
} }
} }
@ -909,10 +974,6 @@ void hp1ll3_device::command(int command)
case WRMEM: case WRMEM:
DBG_LOG(1,"HPGPU",("WRMEM of %d words to %04X complete\n", m_memory_ptr - m_input[0], m_input[0])); DBG_LOG(1,"HPGPU",("WRMEM of %d words to %04X complete\n", m_memory_ptr - m_input[0], m_input[0]));
break; break;
case WRWIN:
draw_cursor_sprite();
break;
} }
break; break;
@ -930,8 +991,7 @@ void hp1ll3_device::command(int command)
case DISSP: case DISSP:
DBG_LOG(2,"HPGPU",("command: DISSP [%d, 0x%x]\n", command, command)); DBG_LOG(2,"HPGPU",("command: DISSP [%d, 0x%x]\n", command, command));
draw_sprite(); disable_sprite();
m_enable_sprite = false;
break; break;
case ENSP: case ENSP:
@ -945,8 +1005,7 @@ void hp1ll3_device::command(int command)
case DISCURS: case DISCURS:
DBG_LOG(2,"HPGPU",("command: DISCURS [%d, 0x%x]\n", command, command)); DBG_LOG(2,"HPGPU",("command: DISCURS [%d, 0x%x]\n", command, command));
draw_cursor(); disable_cursor();
m_enable_cursor = false;
break; break;
// type 1 commands -- 1 word of data expected in the buffer // type 1 commands -- 1 word of data expected in the buffer
@ -961,13 +1020,11 @@ void hp1ll3_device::command(int command)
case WRFAD: case WRFAD:
DBG_LOG(2,"HPGPU",("command: WRFAD [%d, 0x%x] (0x%04x)\n", command, command, m_input[0])); DBG_LOG(2,"HPGPU",("command: WRFAD [%d, 0x%x] (0x%04x)\n", command, command, m_input[0]));
m_fad = m_input[0]; m_fad = m_input[0];
break;
// ?? used by diagnostic ROM // ?? used by diagnostic ROM
case 6: case 6:
m_fontheight = rd_video(m_fad); DBG_LOG(1,"HPGPU",("command: 6\n"));
m_fontdata = m_fad + rd_video(m_fad + 1) + 2;
DBG_LOG(1,"HPGPU",("font data set: FAD %04X header %d bitmaps %04X height %d\n",
m_fad, rd_video(m_fad + 1), m_fontdata, m_fontheight));
break; break;
// start of data area // start of data area
@ -1018,19 +1075,15 @@ void hp1ll3_device::command(int command)
// Write window // Write window
case WRWIN: case WRWIN:
DBG_LOG(2,"HPGPU",("command: WRWIN [%d, 0x%x] offset=%u size(%d,%d)\n",command, command, m_input[0], m_window.width, m_window.height));
// m_input[0] is offset (to be implemented)
m_rw_win_x = m_window.org_x;
m_rw_win_y = m_window.org_y;
draw_cursor_sprite();
break;
// Read window // Read window
case RDWIN: case RDWIN:
DBG_LOG(2,"HPGPU",("command: RDWIN [%d, 0x%x] offset=%u\n",command, command, m_input[0])); DBG_LOG(2,"HPGPU",("command: %s [%d, 0x%x] offset=%u size(%d,%d)\n",
command == RDWIN ? "RDWIN":"WRWIN", command, command, m_input[0], m_window.width, m_window.height));
// m_input[0] is offset (to be implemented) // m_input[0] is offset (to be implemented)
m_rw_win_x = m_window.org_x; m_rw_win_x = m_window.org_x;
m_rw_win_y = m_window.org_y; m_rw_win_y = m_window.org_y;
disable_cursor();
disable_sprite();
break; break;
// type 2 commands -- 2 words of data expected in the buffer // type 2 commands -- 2 words of data expected in the buffer
@ -1079,6 +1132,13 @@ void hp1ll3_device::command(int command)
m_saved_x = m_cursor_x; m_saved_x = m_cursor_x;
break; break;
// move pointer incremental
case IMOVEP:
DBG_LOG(2,"HPGPU",("command: IMOVEP [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1]));
set_pen_pos(Point{ uint16_t(m_cursor_x + m_input[0]), uint16_t(m_cursor_y + m_input[1]) });
m_saved_x = m_cursor_x;
break;
// Scroll UP // Scroll UP
case SCROLUP: case SCROLUP:
{ {
@ -1087,7 +1147,8 @@ void hp1ll3_device::command(int command)
Point src_p{ m_window.org_x, uint16_t(m_window.org_y + m_input[1]) }; Point src_p{ m_window.org_x, uint16_t(m_window.org_y + m_input[1]) };
Rectangle dst_rect = get_window(); Rectangle dst_rect = get_window();
dst_rect.size.y -= m_input[1]; dst_rect.size.y -= m_input[1];
bitblt(m_org, m_horiz_pix_total, m_vert_pix_total, src_p, get_window(), dst_rect, m_rr); unsigned rounded_width = m_conf[CONF_WPL] * WS;
bitblt(m_org, rounded_width, m_vert_pix_total, src_p, get_window(), dst_rect, m_rr);
dst_rect.origin.y += dst_rect.size.y; dst_rect.origin.y += dst_rect.size.y;
dst_rect.size.y = m_input[1]; dst_rect.size.y = m_input[1];
fill(dst_rect, m_input[0]); fill(dst_rect, m_input[0]);
@ -1104,7 +1165,8 @@ void hp1ll3_device::command(int command)
Rectangle dst_rect = get_window(); Rectangle dst_rect = get_window();
dst_rect.origin.y += m_input[1]; dst_rect.origin.y += m_input[1];
dst_rect.size.y -= m_input[1]; dst_rect.size.y -= m_input[1];
bitblt(m_org, m_horiz_pix_total, m_vert_pix_total, src_p, get_window(), dst_rect, m_rr); unsigned rounded_width = m_conf[CONF_WPL] * WS;
bitblt(m_org, rounded_width, m_vert_pix_total, src_p, get_window(), dst_rect, m_rr);
dst_rect.origin.y = m_window.org_y; dst_rect.origin.y = m_window.org_y;
dst_rect.size.y = m_input[1]; dst_rect.size.y = m_input[1];
fill(dst_rect, m_input[0]); fill(dst_rect, m_input[0]);
@ -1124,8 +1186,15 @@ void hp1ll3_device::command(int command)
// carriage return, line feed // carriage return, line feed
case CRLFx: case CRLFx:
DBG_LOG(2,"HPGPU",("command: CRLF [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1])); {
set_pen_pos(Point{ m_saved_x, uint16_t(m_cursor_y + m_fontheight) }); DBG_LOG(2,"HPGPU",("command: CRLF [%d, 0x%x]\n", command, command));
uint16_t font_data;
uint16_t font_height;
get_font(font_data, font_height);
set_pen_pos(Point{ m_saved_x, uint16_t(m_cursor_y + font_height) });
}
break; break;
// move sprite absolute // move sprite absolute
@ -1154,11 +1223,25 @@ void hp1ll3_device::command(int command)
DBG_LOG(2,"HPGPU",("command: %s [%d, 0x%x] (0x%04x)\n", DBG_LOG(2,"HPGPU",("command: %s [%d, 0x%x] (0x%04x)\n",
command == RDMEM?"RDMEM":"WRMEM", command, command, m_input[0])); command == RDMEM?"RDMEM":"WRMEM", command, command, m_input[0]));
m_memory_ptr = m_input[0]; // memory is word-addressable m_memory_ptr = m_input[0]; // memory is word-addressable
disable_cursor();
disable_sprite();
break; break;
// type 3 read commands // type 3 read commands
case RDP: case RDP:
DBG_LOG(2,"HPGPU",("command: RDP [%d, 0x%x]\n", command, command));
break;
case RDSP: case RDSP:
DBG_LOG(2,"HPGPU",("command: RDSP [%d, 0x%x]\n", command, command));
break;
case RDWINPARM:
DBG_LOG(2,"HPGPU",("command: RDWINPARM [%d, 0x%x]\n", command, command));
break;
case ID:
DBG_LOG(2,"HPGPU",("command: ID [%d, 0x%x]\n", command, command));
break; break;
default: default:
@ -1166,6 +1249,7 @@ void hp1ll3_device::command(int command)
break; break;
} }
m_io_ptr = 0; m_rd_ptr = 0;
m_wr_ptr = 0;
m_command = command; m_command = command;
} }

View File

@ -25,6 +25,10 @@ public:
// construction/destruction // construction/destruction
hp1ll3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); hp1ll3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// Configuration
// Set VRAM size (in kw). Parameter must be <= 128 and it must be a power of 2.
void set_vram_size(unsigned kw) { m_vram_size = kw * 1024; }
DECLARE_READ8_MEMBER(read); DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write); DECLARE_WRITE8_MEMBER(write);
@ -50,6 +54,7 @@ private:
uint16_t get_pix_addr(uint16_t x, uint16_t y) const; uint16_t get_pix_addr(uint16_t x, uint16_t y) const;
inline void point(int x, int y, bool pix, const uint16_t masks[]); inline void point(int x, int y, bool pix, const uint16_t masks[]);
void get_font(uint16_t& font_data, uint16_t& font_height) const;
void label(uint8_t chr, int width); void label(uint8_t chr, int width);
void line(int x_from, int y_from, int x_to, int y_to); void line(int x_from, int y_from, int x_to, int y_to);
void wr_video(uint16_t addr, uint16_t v); void wr_video(uint16_t addr, uint16_t v);
@ -69,19 +74,22 @@ private:
void draw_cursor_sprite(); void draw_cursor_sprite();
void set_pen_pos(Point p); void set_pen_pos(Point p);
void set_sprite_pos(Point p); void set_sprite_pos(Point p);
void disable_cursor();
void disable_sprite();
Rectangle get_window() const; Rectangle get_window() const;
Rectangle get_screen() const; Rectangle get_screen() const;
void get_hv_timing(bool vertical, unsigned& total, unsigned& active) const;
void apply_conf(); void apply_conf();
uint16_t m_conf[11], m_input[2], m_io_word; uint16_t m_conf[11], m_input[2], m_io_word;
int m_io_ptr, m_memory_ptr; int m_rd_ptr, m_wr_ptr, m_memory_ptr;
int m_command, m_horiz_pix_total, m_vert_pix_total; int m_command, m_horiz_pix_total, m_vert_pix_total;
uint16_t m_sad; uint16_t m_sad;
uint16_t m_org; uint16_t m_org;
uint16_t m_dad; uint16_t m_dad;
uint16_t m_rr; uint16_t m_rr;
uint16_t m_fad, m_fontdata, m_fontheight; uint16_t m_fad;
uint16_t m_udl; uint16_t m_udl;
bool m_enable_video, m_enable_cursor, m_enable_sprite; bool m_enable_video, m_enable_cursor, m_enable_sprite;
@ -94,6 +102,7 @@ private:
uint16_t width, height, org_x, org_y; uint16_t width, height, org_x, org_y;
} m_window; } m_window;
std::unique_ptr<uint16_t[]> m_videoram; std::unique_ptr<uint16_t[]> m_videoram;
unsigned m_vram_size;
uint16_t m_ram_addr_mask; uint16_t m_ram_addr_mask;
uint16_t m_rw_win_x, m_rw_win_y; uint16_t m_rw_win_x, m_rw_win_y;

View File

@ -387,6 +387,7 @@ public:
, m_bankdev(*this, "bankdev") , m_bankdev(*this, "bankdev")
, m_fdc(*this, "fdc") , m_fdc(*this, "fdc")
, m_ram(*this, RAM_TAG) , m_ram(*this, RAM_TAG)
, m_gpu(*this , "gpu")
, m_screen(*this, "screen") , m_screen(*this, "screen")
{ } { }
@ -431,6 +432,7 @@ private:
required_device<address_map_bank_device> m_bankdev; required_device<address_map_bank_device> m_bankdev;
required_device<wd2797_device> m_fdc; required_device<wd2797_device> m_fdc;
required_device<ram_device> m_ram; required_device<ram_device> m_ram;
required_device<hp1ll3_device> m_gpu;
required_device<screen_device> m_screen; required_device<screen_device> m_screen;
uint32_t m_mmu[4], m_lowest_ram_addr; uint32_t m_mmu[4], m_lowest_ram_addr;
@ -485,7 +487,7 @@ void hp_ipc_state::hp_ipc_mem_inner_base(address_map &map)
map(0x1000000, 0x17FFFFF).rw(FUNC(hp_ipc_state::ram_r), FUNC(hp_ipc_state::ram_w)); map(0x1000000, 0x17FFFFF).rw(FUNC(hp_ipc_state::ram_r), FUNC(hp_ipc_state::ram_w));
map(0x1800000, 0x187FFFF).rom().region("maincpu", 0); map(0x1800000, 0x187FFFF).rom().region("maincpu", 0);
map(0x1E00000, 0x1E0FFFF).rw(FUNC(hp_ipc_state::mmu_r), FUNC(hp_ipc_state::mmu_w)); map(0x1E00000, 0x1E0FFFF).rw(FUNC(hp_ipc_state::mmu_r), FUNC(hp_ipc_state::mmu_w));
map(0x1E20000, 0x1E2000F).rw("gpu", FUNC(hp1ll3_device::read), FUNC(hp1ll3_device::write)).umask16(0x00ff); map(0x1E20000, 0x1E2000F).rw(m_gpu, FUNC(hp1ll3_device::read), FUNC(hp1ll3_device::write)).umask16(0x00ff);
map(0x1E40000, 0x1E4002F).rw("rtc", FUNC(mm58167_device::read), FUNC(mm58167_device::write)).umask16(0x00ff); map(0x1E40000, 0x1E4002F).rw("rtc", FUNC(mm58167_device::read), FUNC(mm58167_device::write)).umask16(0x00ff);
// supervisor mode // supervisor mode
@ -495,7 +497,7 @@ void hp_ipc_state::hp_ipc_mem_inner_base(address_map &map)
map(0x0600000, 0x060FFFF).rw(FUNC(hp_ipc_state::mmu_r), FUNC(hp_ipc_state::mmu_w)); map(0x0600000, 0x060FFFF).rw(FUNC(hp_ipc_state::mmu_r), FUNC(hp_ipc_state::mmu_w));
map(0x0610000, 0x0610007).rw(FUNC(hp_ipc_state::floppy_id_r), FUNC(hp_ipc_state::floppy_id_w)).umask16(0x00ff); map(0x0610000, 0x0610007).rw(FUNC(hp_ipc_state::floppy_id_r), FUNC(hp_ipc_state::floppy_id_w)).umask16(0x00ff);
map(0x0610008, 0x061000F).rw(m_fdc, FUNC(wd2797_device::read), FUNC(wd2797_device::write)).umask16(0x00ff); map(0x0610008, 0x061000F).rw(m_fdc, FUNC(wd2797_device::read), FUNC(wd2797_device::write)).umask16(0x00ff);
map(0x0620000, 0x0620007).rw("gpu", FUNC(hp1ll3_device::read), FUNC(hp1ll3_device::write)).umask16(0x00ff); map(0x0620000, 0x0620007).rw(m_gpu, FUNC(hp1ll3_device::read), FUNC(hp1ll3_device::write)).umask16(0x00ff);
map(0x0630000, 0x063FFFF).mask(0xf).rw("hpib" , FUNC(tms9914_device::reg8_r) , FUNC(tms9914_device::reg8_w)).umask16(0x00ff); map(0x0630000, 0x063FFFF).mask(0xf).rw("hpib" , FUNC(tms9914_device::reg8_r) , FUNC(tms9914_device::reg8_w)).umask16(0x00ff);
map(0x0640000, 0x064002F).rw("rtc", FUNC(mm58167_device::read), FUNC(mm58167_device::write)).umask16(0x00ff); map(0x0640000, 0x064002F).rw("rtc", FUNC(mm58167_device::read), FUNC(mm58167_device::write)).umask16(0x00ff);
map(0x0660000, 0x06600FF).rw("mlc", FUNC(hp_hil_mlc_device::read), FUNC(hp_hil_mlc_device::write)).umask16(0x00ff); // 'caravan', scrn/caravan.h map(0x0660000, 0x06600FF).rw("mlc", FUNC(hp_hil_mlc_device::read), FUNC(hp_hil_mlc_device::write)).umask16(0x00ff); // 'caravan', scrn/caravan.h
@ -738,7 +740,7 @@ MACHINE_CONFIG_START(hp_ipc_state::hp_ipc_base)
MCFG_DEVICE_ADD("maincpu", M68000, 15.92_MHz_XTAL / 2) MCFG_DEVICE_ADD("maincpu", M68000, 15.92_MHz_XTAL / 2)
MCFG_DEVICE_PROGRAM_MAP(hp_ipc_mem_outer) MCFG_DEVICE_PROGRAM_MAP(hp_ipc_mem_outer)
HP1LL3(config , "gpu" , 24_MHz_XTAL / 8).set_screen("screen"); HP1LL3(config , m_gpu , 24_MHz_XTAL / 8).set_screen("screen");
// XXX actual clock is 1MHz; remove this workaround (and change 2000 to 100 in hp_ipc_dsk.cpp) // XXX actual clock is 1MHz; remove this workaround (and change 2000 to 100 in hp_ipc_dsk.cpp)
// XXX when floppy code correctly handles 600 rpm drives. // XXX when floppy code correctly handles 600 rpm drives.
@ -794,6 +796,9 @@ MACHINE_CONFIG_START(hp_ipc_state::hp_ipc)
MCFG_ADDRESS_MAP_BANK_DATA_WIDTH(16) MCFG_ADDRESS_MAP_BANK_DATA_WIDTH(16)
MCFG_ADDRESS_MAP_BANK_STRIDE(0x1000000) MCFG_ADDRESS_MAP_BANK_STRIDE(0x1000000)
// 16kw/32kb video RAM
m_gpu->set_vram_size(16);
// horizontal time = 60 us (min) // horizontal time = 60 us (min)
// ver.refresh period = ~300 us // ver.refresh period = ~300 us
// ver.period = 16.7ms (~60 hz) // ver.period = 16.7ms (~60 hz)
@ -817,12 +822,16 @@ MACHINE_CONFIG_START(hp_ipc_state::hp9808a)
MCFG_ADDRESS_MAP_BANK_DATA_WIDTH(16) MCFG_ADDRESS_MAP_BANK_DATA_WIDTH(16)
MCFG_ADDRESS_MAP_BANK_STRIDE(0x1000000) MCFG_ADDRESS_MAP_BANK_STRIDE(0x1000000)
MCFG_SCREEN_ADD_MONOCHROME("screen", LCD, rgb_t::amber()) // actually a kind of EL display // 64kw/128kb video RAM
MCFG_SCREEN_UPDATE_DEVICE("gpu", hp1ll3_device, screen_update) m_gpu->set_vram_size(64);
MCFG_SCREEN_RAW_PARAMS(6_MHz_XTAL * 2, 720, 0, 640, 480, 0, 400)
MCFG_SCREEN_VBLANK_CALLBACK(WRITELINE("mlc", hp_hil_mlc_device, ap_w)) SCREEN(config , m_screen , SCREEN_TYPE_LCD);
m_screen->set_color(rgb_t::amber()); // actually a kind of EL display
m_screen->set_screen_update("gpu" , FUNC(hp1ll3_device::screen_update));
m_screen->set_raw(6_MHz_XTAL * 2 , 880 , 0 , 640 , 425 , 0 , 400);
m_screen->screen_vblank().set("mlc", FUNC(hp_hil_mlc_device::ap_w)); // XXX actually it's driven by 555 (U59)
m_screen->set_palette("palette");
MCFG_SCREEN_PALETTE("palette")
MCFG_PALETTE_ADD_MONOCHROME("palette") MCFG_PALETTE_ADD_MONOCHROME("palette")
MACHINE_CONFIG_END MACHINE_CONFIG_END