mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
hp9845: first draft of graphic video support: no cursor yet, reading
from graphic RAM is not working
This commit is contained in:
parent
cc6d5a643d
commit
4175e66e34
@ -131,6 +131,11 @@ WRITE_LINE_MEMBER(hp_hybrid_cpu_device::flag_w)
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 hp_hybrid_cpu_device::pa_r(void) const
|
||||
{
|
||||
return CURRENT_PA;
|
||||
}
|
||||
|
||||
hp_hybrid_cpu_device::hp_hybrid_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname , UINT8 addrwidth)
|
||||
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, __FILE__),
|
||||
m_pa_changed_func(*this),
|
||||
|
@ -87,6 +87,8 @@ public:
|
||||
DECLARE_WRITE_LINE_MEMBER(status_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(flag_w);
|
||||
|
||||
UINT8 pa_r(void) const;
|
||||
|
||||
template<class _Object> static devcb_base &set_pa_changed_func(device_t &device, _Object object) { return downcast<hp_hybrid_cpu_device &>(device).m_pa_changed_func.set_callback(object); }
|
||||
|
||||
protected:
|
||||
|
@ -49,12 +49,37 @@
|
||||
// from 2nd row on. This in turn prevents "BAD" text to be visible on screen.
|
||||
#define MAX_WORD_PER_ROW 220
|
||||
|
||||
#define VIDEO_PIXEL_CLOCK 20849400
|
||||
#define VIDEO_CHAR_WIDTH 9
|
||||
#define VIDEO_CHAR_HEIGHT 15
|
||||
#define VIDEO_CHAR_COLUMNS 80
|
||||
#define VIDEO_CHAR_TOTAL 99
|
||||
#define VIDEO_CHAR_ROWS 25
|
||||
#define VIDEO_ROWS_TOTAL 26
|
||||
#define VIDEO_HTOTAL (VIDEO_CHAR_WIDTH * VIDEO_CHAR_TOTAL)
|
||||
#define VIDEO_VTOTAL (VIDEO_CHAR_HEIGHT * VIDEO_ROWS_TOTAL)
|
||||
#define VIDEO_ACTIVE_SCANLINES (VIDEO_CHAR_HEIGHT * VIDEO_CHAR_ROWS)
|
||||
|
||||
// Constants of graphic video
|
||||
// Pixel clock is 20.8494 MHz (the same as alpha video)
|
||||
// Horizontal counter counts in [1..727] range
|
||||
// Vertical counter counts in [34..511] range
|
||||
#define GVIDEO_HTOTAL 727
|
||||
#define GVIDEO_HCNT_OFF 1 // Actual start value of h counter
|
||||
#define GVIDEO_HBEND (69 - GVIDEO_HCNT_OFF)
|
||||
#define GVIDEO_HPIXELS 560
|
||||
#define GVIDEO_HBSTART (GVIDEO_HBEND + GVIDEO_HPIXELS)
|
||||
#define GVIDEO_VTOTAL 478
|
||||
#define GVIDEO_VCNT_OFF 34 // Actual start value of v counter
|
||||
#define GVIDEO_VBEND (50 - GVIDEO_VCNT_OFF)
|
||||
#define GVIDEO_VPIXELS 455
|
||||
#define GVIDEO_VBSTART (GVIDEO_VBEND + GVIDEO_VPIXELS)
|
||||
#define GVIDEO_MEM_SIZE 16384
|
||||
#define GVIDEO_ADDR_MASK (GVIDEO_MEM_SIZE - 1)
|
||||
#define GVIDEO_PA 13
|
||||
|
||||
#define T15_PA 15
|
||||
|
||||
#define KEY_SCAN_OSCILLATOR 327680
|
||||
|
||||
class hp9845_state : public driver_device
|
||||
@ -77,6 +102,7 @@ public:
|
||||
driver_device(mconfig, type, tag),
|
||||
m_lpu(*this , "lpu"),
|
||||
m_ppu(*this , "ppu"),
|
||||
m_screen(*this , "screen"),
|
||||
m_palette(*this , "palette"),
|
||||
m_io_key0(*this , "KEY0"),
|
||||
m_io_key1(*this , "KEY1"),
|
||||
@ -94,6 +120,13 @@ public:
|
||||
|
||||
void vblank_w(screen_device &screen, bool state);
|
||||
|
||||
void set_graphic_mode(bool graphic);
|
||||
DECLARE_READ16_MEMBER(graphic_r);
|
||||
DECLARE_WRITE16_MEMBER(graphic_w);
|
||||
attotime time_to_gv_mem_availability(void) const;
|
||||
void advance_gv_fsm(bool ds , bool trigger);
|
||||
void update_graphic_bits(void);
|
||||
|
||||
IRQ_CALLBACK_MEMBER(irq_callback);
|
||||
void update_irq(void);
|
||||
|
||||
@ -111,6 +144,7 @@ public:
|
||||
private:
|
||||
required_device<hp_5061_3001_cpu_device> m_lpu;
|
||||
required_device<hp_5061_3001_cpu_device> m_ppu;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_ioport m_io_key0;
|
||||
required_ioport m_io_key1;
|
||||
@ -137,6 +171,7 @@ private:
|
||||
offs_t m_video_mar;
|
||||
UINT16 m_video_word;
|
||||
bool m_video_load_mar;
|
||||
bool m_video_first_mar;
|
||||
bool m_video_byte_idx;
|
||||
UINT8 m_video_attr;
|
||||
bool m_video_buff_idx;
|
||||
@ -144,6 +179,35 @@ private:
|
||||
UINT8 m_video_frame;
|
||||
video_buffer_t m_video_buff[ 2 ];
|
||||
|
||||
// Graphic video
|
||||
typedef enum {
|
||||
GV_STAT_RESET,
|
||||
GV_STAT_WAIT_DS_0 = GV_STAT_RESET,
|
||||
GV_STAT_WAIT_TRIG_0,
|
||||
GV_STAT_WAIT_MEM_0,
|
||||
GV_STAT_WAIT_DS_1,
|
||||
GV_STAT_WAIT_DS_2,
|
||||
GV_STAT_WAIT_TRIG_1,
|
||||
GV_STAT_WAIT_MEM_1,
|
||||
GV_STAT_WAIT_MEM_2
|
||||
} gv_fsm_state_t;
|
||||
|
||||
bool m_graphic_sel;
|
||||
gv_fsm_state_t m_gv_fsm_state;
|
||||
bool m_gv_int_en;
|
||||
bool m_gv_dma_en;
|
||||
bool m_gv_ready;
|
||||
UINT8 m_gv_cmd; // U65 (GC)
|
||||
UINT16 m_gv_data_w; // U29, U45, U28 & U44 (GC)
|
||||
UINT16 m_gv_data_r; // U59 & U60 (GC)
|
||||
UINT16 m_gv_io_counter; // U1, U2, U14 & U15 (GC)
|
||||
UINT16 m_gv_cursor_w; // U38 & U39 (GS)
|
||||
UINT16 m_gv_cursor_x; // U31 & U23 (GS)
|
||||
UINT16 m_gv_cursor_y; // U15 & U8 (GS)
|
||||
bool m_gv_cursor_gc; // U8 (GS)
|
||||
bool m_gv_cursor_fs; // U8 (GS)
|
||||
std::vector<UINT16> m_graphic_mem;
|
||||
|
||||
// Interrupt handling
|
||||
UINT8 m_irl_pending;
|
||||
UINT8 m_irh_pending;
|
||||
@ -152,9 +216,6 @@ private:
|
||||
ioport_value m_kb_state[ 4 ];
|
||||
UINT8 m_kb_scancode;
|
||||
UINT16 m_kb_status;
|
||||
|
||||
// State of PPU I/O
|
||||
UINT8 m_ppu_pa;
|
||||
};
|
||||
|
||||
static INPUT_PORTS_START(hp9845b)
|
||||
@ -308,7 +369,11 @@ UINT32 hp9845_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
|
||||
|
||||
UINT32 hp9845b_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
|
||||
if (m_graphic_sel) {
|
||||
copybitmap(bitmap, m_bitmap, 0, 0, GVIDEO_HBEND, GVIDEO_VBEND, cliprect);
|
||||
} else {
|
||||
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -318,6 +383,8 @@ void hp9845b_state::machine_start()
|
||||
machine().first_screen()->register_screen_bitmap(m_bitmap);
|
||||
|
||||
m_chargen = memregion("chargen")->base();
|
||||
|
||||
m_graphic_mem.resize(GVIDEO_MEM_SIZE);
|
||||
}
|
||||
|
||||
void hp9845b_state::machine_reset()
|
||||
@ -328,11 +395,17 @@ void hp9845b_state::machine_reset()
|
||||
// Some sensible defaults
|
||||
m_video_mar = VIDEO_BUFFER_BASE;
|
||||
m_video_load_mar = false;
|
||||
m_video_first_mar = false;
|
||||
m_video_byte_idx = false;
|
||||
m_video_attr = 0;
|
||||
m_video_buff_idx = false;
|
||||
m_video_blanked = false;
|
||||
m_video_frame = 0;
|
||||
m_graphic_sel = false;
|
||||
m_gv_fsm_state = GV_STAT_RESET;
|
||||
m_gv_int_en = false;
|
||||
m_gv_dma_en = false;
|
||||
m_gv_ready = true;
|
||||
|
||||
m_irl_pending = 0;
|
||||
m_irh_pending = 0;
|
||||
@ -340,8 +413,6 @@ void hp9845b_state::machine_reset()
|
||||
memset(&m_kb_state[ 0 ] , 0 , sizeof(m_kb_state));
|
||||
m_kb_scancode = 0x7f;
|
||||
m_kb_status = 0;
|
||||
|
||||
m_ppu_pa = 0;
|
||||
}
|
||||
|
||||
void hp9845b_state::set_video_mar(UINT16 mar)
|
||||
@ -367,7 +438,10 @@ void hp9845b_state::video_fill_buff(bool buff_idx)
|
||||
m_video_word = prog_space.read_word(m_video_mar << 1);
|
||||
if (m_video_load_mar) {
|
||||
// Load new address into MAR after start of a new frame or NWA instruction
|
||||
// TODO: decode graphic/alpha mode bit
|
||||
if (m_video_first_mar) {
|
||||
set_graphic_mode(!BIT(m_video_word , 15));
|
||||
m_video_first_mar = false;
|
||||
}
|
||||
set_video_mar(~m_video_word);
|
||||
m_video_load_mar = false;
|
||||
continue;
|
||||
@ -415,13 +489,13 @@ void hp9845b_state::video_render_buff(unsigned line_in_row, bool buff_idx)
|
||||
m_video_blanked = true;
|
||||
}
|
||||
|
||||
const rgb_t *palette = m_palette->palette()->entry_list_raw();
|
||||
const pen_t *pen = m_palette->pens();
|
||||
|
||||
if (m_video_blanked) {
|
||||
// Blank scanline
|
||||
for (unsigned i = 0; i < (80 * 9); i++) {
|
||||
m_bitmap.pix32(m_video_scanline , i) = palette[ 0 ];
|
||||
}
|
||||
// Blank scanline
|
||||
for (unsigned i = 0; i < (80 * 9); i++) {
|
||||
m_bitmap.pix32(m_video_scanline , i) = pen[ 0 ];
|
||||
}
|
||||
} else {
|
||||
bool cursor_line = line_in_row == 12;
|
||||
bool ul_line = line_in_row == 14;
|
||||
@ -453,7 +527,7 @@ void hp9845b_state::video_render_buff(unsigned line_in_row, bool buff_idx)
|
||||
for (unsigned j = 0; j < 9; j++) {
|
||||
bool pixel = (pixels & (1U << (8 - j))) != 0;
|
||||
|
||||
m_bitmap.pix32(m_video_scanline , i * 9 + j) = palette[ pixel ? 1 : 0 ];
|
||||
m_bitmap.pix32(m_video_scanline , i * 9 + j) = pen[ pixel ? 1 : 0 ];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -461,44 +535,332 @@ void hp9845b_state::video_render_buff(unsigned line_in_row, bool buff_idx)
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(hp9845b_state::scanline_timer)
|
||||
{
|
||||
m_video_scanline = param;
|
||||
m_video_scanline = param;
|
||||
//logerror("sl=%d\n" , param);
|
||||
|
||||
if (m_video_scanline < VIDEO_ACTIVE_SCANLINES) {
|
||||
unsigned row = m_video_scanline / 15;
|
||||
unsigned line_in_row = m_video_scanline - row * 15;
|
||||
if (m_graphic_sel) {
|
||||
if (m_video_scanline >= GVIDEO_VBEND && m_video_scanline < GVIDEO_VBSTART) {
|
||||
const pen_t *pen = m_palette->pens();
|
||||
|
||||
if (line_in_row == 0) {
|
||||
// Start of new row, swap buffers
|
||||
m_video_buff_idx = !m_video_buff_idx;
|
||||
video_fill_buff(!m_video_buff_idx);
|
||||
}
|
||||
unsigned mem_idx = 36 * (m_video_scanline - GVIDEO_VBEND);
|
||||
for (unsigned i = 0; i < GVIDEO_HPIXELS; i += 16) {
|
||||
UINT16 word = m_graphic_mem[ mem_idx++ ];
|
||||
unsigned x = i;
|
||||
for (UINT16 mask = 0x8000; mask != 0; mask >>= 1) {
|
||||
m_bitmap.pix32(m_video_scanline - GVIDEO_VBEND , x++) = pen[ (word & mask) != 0 ];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (m_video_scanline < VIDEO_ACTIVE_SCANLINES) {
|
||||
unsigned row = m_video_scanline / 15;
|
||||
unsigned line_in_row = m_video_scanline - row * 15;
|
||||
|
||||
video_render_buff(line_in_row , m_video_buff_idx);
|
||||
}
|
||||
if (line_in_row == 0) {
|
||||
// Start of new row, swap buffers
|
||||
m_video_buff_idx = !m_video_buff_idx;
|
||||
video_fill_buff(!m_video_buff_idx);
|
||||
}
|
||||
|
||||
video_render_buff(line_in_row , m_video_buff_idx);
|
||||
}
|
||||
}
|
||||
|
||||
void hp9845b_state::vblank_w(screen_device &screen, bool state)
|
||||
{
|
||||
// VBlank signal is fed into HALT flag of PPU
|
||||
m_ppu->halt_w(state);
|
||||
//logerror("vb=%d\n" , state);
|
||||
|
||||
if (state) {
|
||||
// Start of V blank
|
||||
set_video_mar(0);
|
||||
m_video_load_mar = true;
|
||||
m_video_byte_idx = false;
|
||||
m_video_blanked = false;
|
||||
m_video_frame++;
|
||||
m_video_buff_idx = !m_video_buff_idx;
|
||||
video_fill_buff(!m_video_buff_idx);
|
||||
}
|
||||
// VBlank signal is fed into HALT flag of PPU
|
||||
m_ppu->halt_w(state);
|
||||
|
||||
if (state) {
|
||||
// Start of V blank
|
||||
set_video_mar(0);
|
||||
m_video_load_mar = true;
|
||||
m_video_first_mar = true;
|
||||
m_video_byte_idx = false;
|
||||
m_video_blanked = false;
|
||||
m_video_frame++;
|
||||
m_video_buff_idx = !m_video_buff_idx;
|
||||
video_fill_buff(!m_video_buff_idx);
|
||||
}
|
||||
}
|
||||
|
||||
void hp9845b_state::set_graphic_mode(bool graphic)
|
||||
{
|
||||
if (graphic != m_graphic_sel) {
|
||||
m_graphic_sel = graphic;
|
||||
logerror("GS=%d\n" , graphic);
|
||||
if (m_graphic_sel) {
|
||||
m_screen->configure(GVIDEO_HTOTAL , GVIDEO_VTOTAL , rectangle(GVIDEO_HBEND , GVIDEO_HBSTART - 1 , GVIDEO_VBEND , GVIDEO_VBSTART - 1) , HZ_TO_ATTOSECONDS(VIDEO_PIXEL_CLOCK) * GVIDEO_HTOTAL * GVIDEO_VTOTAL);
|
||||
} else {
|
||||
m_screen->configure(VIDEO_HTOTAL , VIDEO_VTOTAL , rectangle(0 , (VIDEO_CHAR_WIDTH * VIDEO_CHAR_COLUMNS) - 1 , 0 , VIDEO_ACTIVE_SCANLINES - 1) , HZ_TO_ATTOSECONDS(VIDEO_PIXEL_CLOCK) * VIDEO_HTOTAL * VIDEO_VTOTAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
READ16_MEMBER(hp9845b_state::graphic_r)
|
||||
{
|
||||
UINT16 res = 0;
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
// R4: data register
|
||||
res = m_gv_data_r;
|
||||
advance_gv_fsm(true , false);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// R5: status register
|
||||
if (m_gv_int_en) {
|
||||
BIT_SET(res, 7);
|
||||
}
|
||||
if (m_gv_dma_en) {
|
||||
BIT_SET(res, 6);
|
||||
}
|
||||
BIT_SET(res, 5);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// R6: data register with DMA TC
|
||||
m_gv_dma_en = false;
|
||||
res = m_gv_data_r;
|
||||
advance_gv_fsm(true , false);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// R7: not mapped
|
||||
break;
|
||||
}
|
||||
|
||||
logerror("rd gv R%u = %04x\n", 4 + offset , res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hp9845b_state::graphic_w)
|
||||
{
|
||||
logerror("wr gv R%u = %04x\n", 4 + offset , data);
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
// R4: data register
|
||||
m_gv_data_w = data;
|
||||
m_gv_cursor_w = data;
|
||||
advance_gv_fsm(true , false);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// R5: command register
|
||||
m_gv_cmd = (UINT8)(data & 0xf);
|
||||
if (BIT(data , 5)) {
|
||||
m_gv_fsm_state = GV_STAT_RESET;
|
||||
}
|
||||
m_gv_dma_en = BIT(data , 6) != 0;
|
||||
m_gv_int_en = BIT(data , 7) != 0;
|
||||
advance_gv_fsm(false , false);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// R6: data register with DMA TC
|
||||
m_gv_dma_en = false;
|
||||
m_gv_data_w = data;
|
||||
m_gv_cursor_w = data;
|
||||
advance_gv_fsm(true , false);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// R7: trigger
|
||||
advance_gv_fsm(false , true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
attotime hp9845b_state::time_to_gv_mem_availability(void) const
|
||||
{
|
||||
// TODO:
|
||||
return attotime::zero;
|
||||
}
|
||||
|
||||
void hp9845b_state::advance_gv_fsm(bool ds , bool trigger)
|
||||
{
|
||||
bool get_out = false;
|
||||
|
||||
attotime time_mem_av;
|
||||
|
||||
do {
|
||||
bool act_trig = trigger || m_gv_dma_en || !BIT(m_gv_cmd , 2);
|
||||
|
||||
switch (m_gv_fsm_state) {
|
||||
case GV_STAT_WAIT_DS_0:
|
||||
// Wait for data strobe (r/w on r4 or r6)
|
||||
if (ds) {
|
||||
m_gv_fsm_state = GV_STAT_WAIT_TRIG_0;
|
||||
} else {
|
||||
get_out = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GV_STAT_WAIT_TRIG_0:
|
||||
// Wait for trigger
|
||||
if (act_trig) {
|
||||
if (BIT(m_gv_cmd , 3)) {
|
||||
// Not a cursor command
|
||||
// Load memory address
|
||||
m_gv_io_counter = ~m_gv_data_w & GVIDEO_ADDR_MASK;
|
||||
if (BIT(m_gv_cmd , 2)) {
|
||||
// Read command (11xx)
|
||||
m_gv_fsm_state = GV_STAT_WAIT_MEM_0;
|
||||
} else {
|
||||
// Write commands (10xx)
|
||||
m_gv_fsm_state = GV_STAT_WAIT_DS_2;
|
||||
}
|
||||
} else {
|
||||
// Cursor command (0xxx)
|
||||
if (BIT(m_gv_cmd , 2)) {
|
||||
// Write X cursor position (01xx)
|
||||
m_gv_cursor_x = (~m_gv_cursor_w >> 6) & 0x3ff;
|
||||
logerror("gv x curs pos = %u\n" , m_gv_cursor_x);
|
||||
} else {
|
||||
// Write Y cursor position and type (00xx)
|
||||
m_gv_cursor_y = (~m_gv_cursor_w >> 6) & 0x1ff;
|
||||
m_gv_cursor_gc = BIT(m_gv_cmd , 1) == 0;
|
||||
m_gv_cursor_fs = BIT(m_gv_cmd , 0) != 0;
|
||||
logerror("gv y curs pos = %u gc = %d fs = %d\n" , m_gv_cursor_y , m_gv_cursor_gc , m_gv_cursor_fs);
|
||||
}
|
||||
m_gv_fsm_state = GV_STAT_WAIT_DS_0;
|
||||
}
|
||||
} else {
|
||||
get_out = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GV_STAT_WAIT_MEM_0:
|
||||
time_mem_av = time_to_gv_mem_availability();
|
||||
if (time_mem_av.is_zero()) {
|
||||
// Read a word from graphic memory
|
||||
m_gv_data_r = m_graphic_mem[ m_gv_io_counter ];
|
||||
logerror("rd gv mem @%04x = %04x\n" , m_gv_io_counter , m_gv_data_r);
|
||||
m_gv_io_counter = (m_gv_io_counter + 1) & GVIDEO_ADDR_MASK;
|
||||
m_gv_fsm_state = GV_STAT_WAIT_DS_1;
|
||||
} else {
|
||||
get_out = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GV_STAT_WAIT_DS_1:
|
||||
if (ds) {
|
||||
m_gv_fsm_state = GV_STAT_WAIT_MEM_0;
|
||||
} else {
|
||||
get_out = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GV_STAT_WAIT_DS_2:
|
||||
// Wait for data word to be written
|
||||
if (ds) {
|
||||
m_gv_fsm_state = GV_STAT_WAIT_TRIG_1;
|
||||
} else {
|
||||
get_out = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GV_STAT_WAIT_TRIG_1:
|
||||
// Wait for trigger
|
||||
if (act_trig) {
|
||||
if (BIT(m_gv_cmd , 1)) {
|
||||
// Clear words (101x)
|
||||
m_gv_data_w = 0;
|
||||
m_gv_fsm_state = GV_STAT_WAIT_MEM_1;
|
||||
} else if (BIT(m_gv_cmd , 0)) {
|
||||
// Write a single pixel (1001)
|
||||
m_gv_fsm_state = GV_STAT_WAIT_MEM_2;
|
||||
} else {
|
||||
// Write words (1000)
|
||||
m_gv_fsm_state = GV_STAT_WAIT_MEM_1;
|
||||
}
|
||||
} else {
|
||||
get_out = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GV_STAT_WAIT_MEM_1:
|
||||
time_mem_av = time_to_gv_mem_availability();
|
||||
if (time_mem_av.is_zero()) {
|
||||
// Write a full word to graphic memory
|
||||
logerror("wr gv mem @%04x = %04x\n" , m_gv_io_counter , m_gv_data_w);
|
||||
m_graphic_mem[ m_gv_io_counter ] = m_gv_data_w;
|
||||
m_gv_io_counter = (m_gv_io_counter + 1) & GVIDEO_ADDR_MASK;
|
||||
m_gv_fsm_state = GV_STAT_WAIT_DS_2;
|
||||
} else {
|
||||
get_out = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GV_STAT_WAIT_MEM_2:
|
||||
time_mem_av = time_to_gv_mem_availability();
|
||||
if (time_mem_av.is_zero()) {
|
||||
// Write a single pixel to graphic memory
|
||||
logerror("wr gv pixel @%04x:%x = %d\n" , m_gv_io_counter , m_gv_data_w & 0xf , BIT(m_gv_data_w , 15));
|
||||
UINT16 mask = 0x8000 >> (m_gv_data_w & 0xf);
|
||||
if (BIT(m_gv_data_w , 15)) {
|
||||
// Set pixel
|
||||
m_graphic_mem[ m_gv_io_counter ] |= mask;
|
||||
} else {
|
||||
// Clear pixel
|
||||
m_graphic_mem[ m_gv_io_counter ] &= ~mask;
|
||||
}
|
||||
// Not really needed
|
||||
m_gv_io_counter = (m_gv_io_counter + 1) & GVIDEO_ADDR_MASK;
|
||||
m_gv_fsm_state = GV_STAT_WAIT_DS_0;
|
||||
} else {
|
||||
get_out = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("Invalid state reached %d\n" , m_gv_fsm_state);
|
||||
m_gv_fsm_state = GV_STAT_RESET;
|
||||
}
|
||||
|
||||
ds = false;
|
||||
trigger = false;
|
||||
} while (!get_out);
|
||||
|
||||
update_graphic_bits();
|
||||
}
|
||||
|
||||
void hp9845b_state::update_graphic_bits(void)
|
||||
{
|
||||
m_gv_ready = m_gv_fsm_state == GV_STAT_WAIT_DS_0 ||
|
||||
m_gv_fsm_state == GV_STAT_WAIT_DS_1 ||
|
||||
m_gv_fsm_state == GV_STAT_WAIT_DS_2;
|
||||
|
||||
bool irq = m_gv_int_en && !m_gv_dma_en && m_gv_ready;
|
||||
|
||||
if (irq) {
|
||||
BIT_SET(m_irh_pending, GVIDEO_PA - 8);
|
||||
} else {
|
||||
BIT_CLR(m_irh_pending, GVIDEO_PA - 8);
|
||||
}
|
||||
|
||||
update_irq();
|
||||
|
||||
bool dmar = m_gv_ready && m_gv_dma_en;
|
||||
|
||||
m_ppu->dmar_w(dmar);
|
||||
|
||||
if (m_ppu->pa_r() == GVIDEO_PA) {
|
||||
m_ppu->flag_w(m_gv_ready);
|
||||
}
|
||||
}
|
||||
|
||||
IRQ_CALLBACK_MEMBER(hp9845b_state::irq_callback)
|
||||
{
|
||||
if (irqline == HPHYBRID_IRL) {
|
||||
logerror("irq ack L %02x\n" , m_irl_pending);
|
||||
return m_irl_pending;
|
||||
} else {
|
||||
logerror("irq ack H %02x\n" , m_irh_pending);
|
||||
return m_irh_pending;
|
||||
}
|
||||
}
|
||||
@ -600,13 +962,15 @@ WRITE16_MEMBER(hp9845b_state::kb_irq_clear_w)
|
||||
|
||||
WRITE8_MEMBER(hp9845b_state::pa_w)
|
||||
{
|
||||
m_ppu_pa = data;
|
||||
|
||||
// TODO: handle sts & flg
|
||||
if (data == 15) {
|
||||
if (data == T15_PA) {
|
||||
// RHS tape drive (T15)
|
||||
m_ppu->status_w(m_t15->sts_r());
|
||||
m_ppu->flag_w(m_t15->flg_r());
|
||||
} else if (data == GVIDEO_PA) {
|
||||
// Graphic video
|
||||
m_ppu->status_w(1);
|
||||
m_ppu->flag_w(m_gv_ready);
|
||||
} else {
|
||||
m_ppu->status_w(0);
|
||||
m_ppu->flag_w(0);
|
||||
@ -616,23 +980,23 @@ WRITE8_MEMBER(hp9845b_state::pa_w)
|
||||
WRITE_LINE_MEMBER(hp9845b_state::t15_irq_w)
|
||||
{
|
||||
if (state) {
|
||||
BIT_SET(m_irh_pending , 7);
|
||||
BIT_SET(m_irh_pending , T15_PA - 8);
|
||||
} else {
|
||||
BIT_CLR(m_irh_pending , 7);
|
||||
BIT_CLR(m_irh_pending , T15_PA - 8);
|
||||
}
|
||||
update_irq();
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp9845b_state::t15_flg_w)
|
||||
{
|
||||
if (m_ppu_pa == 15) {
|
||||
if (m_ppu->pa_r() == T15_PA) {
|
||||
m_ppu->flag_w(state);
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp9845b_state::t15_sts_w)
|
||||
{
|
||||
if (m_ppu_pa == 15) {
|
||||
if (m_ppu->pa_r() == T15_PA) {
|
||||
m_ppu->status_w(state);
|
||||
}
|
||||
}
|
||||
@ -684,9 +1048,12 @@ static ADDRESS_MAP_START(ppu_io_map , AS_IO , 16 , hp9845b_state)
|
||||
// PA = 0, IC = 3
|
||||
// Keyboard status input & keyboard interrupt clear
|
||||
AM_RANGE(HP_MAKE_IOADDR(0 , 3) , HP_MAKE_IOADDR(0 , 3)) AM_READWRITE(kb_status_r , kb_irq_clear_w)
|
||||
// PA = 13, IC = 0..3
|
||||
// Graphic video
|
||||
AM_RANGE(HP_MAKE_IOADDR(GVIDEO_PA , 0) , HP_MAKE_IOADDR(GVIDEO_PA , 3)) AM_READWRITE(graphic_r , graphic_w)
|
||||
// PA = 15, IC = 0..3
|
||||
// Right-hand side tape drive (T15)
|
||||
AM_RANGE(HP_MAKE_IOADDR(15 , 0) , HP_MAKE_IOADDR(15 , 3)) AM_DEVREADWRITE("t15" , hp_taco_device , reg_r , reg_w)
|
||||
AM_RANGE(HP_MAKE_IOADDR(T15_PA , 0) , HP_MAKE_IOADDR(T15_PA , 3)) AM_DEVREADWRITE("t15" , hp_taco_device , reg_r , reg_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static MACHINE_CONFIG_START( hp9845b, hp9845b_state )
|
||||
@ -703,7 +1070,8 @@ static MACHINE_CONFIG_START( hp9845b, hp9845b_state )
|
||||
// video hardware
|
||||
MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::green)
|
||||
MCFG_SCREEN_UPDATE_DRIVER(hp9845b_state, screen_update)
|
||||
MCFG_SCREEN_RAW_PARAMS(20849400 , 99 * 9 , 0 , 80 * 9 , 26 * 15 , 0 , 25 * 15)
|
||||
// These parameters are for alpha video
|
||||
MCFG_SCREEN_RAW_PARAMS(VIDEO_PIXEL_CLOCK , VIDEO_HTOTAL , 0 , VIDEO_CHAR_WIDTH * VIDEO_CHAR_COLUMNS , VIDEO_VTOTAL , 0 , VIDEO_ACTIVE_SCANLINES)
|
||||
MCFG_SCREEN_VBLANK_DRIVER(hp9845b_state, vblank_w)
|
||||
MCFG_PALETTE_ADD_MONOCHROME("palette")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user