summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/hp9845.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/hp9845.cpp')
-rw-r--r--src/mame/drivers/hp9845.cpp3954
1 files changed, 0 insertions, 3954 deletions
diff --git a/src/mame/drivers/hp9845.cpp b/src/mame/drivers/hp9845.cpp
deleted file mode 100644
index 52a1fc5ab1e..00000000000
--- a/src/mame/drivers/hp9845.cpp
+++ /dev/null
@@ -1,3954 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Curt Coder, F. Ulivi, Ansgar Kueckes
-/*
-
- HP 9845
-
- http://www.hp9845.net/
-
-*/
-// *******************************
-// Driver for HP 9845B/C/T systems
-// *******************************
-//
-// What's in:
-// - Emulation of 45B, 45C and 45T systems
-// - Emulation of both 5061-3001 CPUs
-// - LPU & PPU ROMs
-// - LPU & PPU RAMs
-// - Text mode screen
-// - Graphic screen
-// - Keyboard (US & German layouts)
-// - T14 and T15 tape drive
-// - Software list to load optional ROMs
-// - Beeper
-// - Correct character generator ROMs (a huge "thank you" to Ansgar Kueckes for the dumps!)
-// - 98775 light pen controller
-// - Display softkeys on 45C & 45T
-// - HLE of integral printer
-// What's not yet in:
-// - Better naming of tape drive image (it's now "magt1" and "magt2", should be "t15" and "t14")
-// - Better documentation of this file
-// What's wrong:
-// - Speed, as usual
-// - Light pen tracing sometimes behaves erratically in 45C and 45T
-// What will probably never be in:
-// - Fast LPU processor (dump of microcode PROMs is not available)
-
-#include "emu.h"
-#include "includes/hp9845.h"
-
-#include "machine/hp9845_optrom.h"
-#include "bus/hp9845_io/hp9845_io.h"
-#include "machine/timer.h"
-
-#include "render.h"
-#include "softlist.h"
-#include "speaker.h"
-
-#include "hp9845b.lh"
-
-#include "machine/hp9845_printer.h"
-
-// Debugging
-#define VERBOSE 0
-#include "logmacro.h"
-
-#define BIT_MASK(n) (1U << (n))
-
-// Macros to clear/set single bits
-#define BIT_CLR(w , n) ((w) &= ~BIT_MASK(n))
-#define BIT_SET(w , n) ((w) |= BIT_MASK(n))
-
-/*
-
- The 9845 has three possible display options:
-
- 98750A: Standard monochrome (alpha with graphics option)
- 98780A: Enhanced monochrome (alpha with hardware accelerated monochrome graphics)
- 98770A: Color (color alpha with hardware accelerated color graphics with three planes)
-
- All displays use a 560x455 graphics raster. Alpha and graphics share the
- same dots within a 720x455 super matrix. All pixels have a 1:1 ratio (square
- pixels).
-
- The 98750A uses a 25x80 alpha area, either alpha or graphics can be enabled,
- but not both at the same time. In fact, both modes use different video circuits.
-
- Timing and pixel size for real 98750A are slightly different between
- alpha and graphics raster (dual raster):
-
- alpha graphics
- ------------------------------------------------------
- Matrix: 720x375 560x455
- Clock frequency: 20.85 MHz 20.85 MHz
- Horizontal scan frequency: 23.4 kHz 28.7 kHz
- Horizontal retrace time: 8.2 us 8.0 us
- Frame frequency: 60 Hz 60 Hz
- Vertical retrace time: 641 us 800 us
- Size on screen: 9.3"x4.84" 7.9"x6.4"
-
-
- The 98770A and 98780A both use a 720x455 raster, implemented with a single video
- circuit, which again is shared by the alpha and graphics logic, with alpha
- dominant over graphics. So, nominally the alpha area for those systems can
- hold up to 30 rows with full size characters plus some lines for one row with
- cropped characters:
-
- 98770A 98780A
- ------------------------------------------------------
- Matrix: 720x455 720x455
- Clock frequency: 29.7984 MHz 28.224 MHz
- Horizontal scan frequency: 29.1 kHz 31.5 kHz
- Horizontal retrace time: 10.02 us 4.145 us
- Frame frequency: 60 Hz 60 Hz
- Vertical retrace time: 1.03 ms 2.22 ms
- Size on screen: 247x154 mm 236x149 mm
- Dot size: 0.343 mm 0.33 mm
-
-*/
-
-// Base address of video buffer
-#define VIDEO_BUFFER_BASE_LOW 0x16000 // for 98770A and 98780A
-#define VIDEO_BUFFER_BASE_HIGH 0x17000 // for 98750A
-
-// For test "B" of alpha video to succeed this must be < 234
-// Basically "B" test is designed to intentionally prevent line buffer to be filled so that display is blanked
-// from 2nd row on. This in turn prevents "BAD" text to be visible on screen.
-#define MAX_WORD_PER_ROW 220
-
-// Constants of alpha video
-#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_HBSTART (VIDEO_CHAR_WIDTH * VIDEO_CHAR_COLUMNS)
-#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)
-#define VIDEO_TOT_HPIXELS (VIDEO_CHAR_WIDTH * VIDEO_CHAR_COLUMNS)
-
-// 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)
-
-// Constants of 98770A video
-// HBEND & VBEND probably are not really 0
-#define VIDEO_770_PIXEL_CLOCK 29798400
-#define VIDEO_770_HTOTAL 1024
-#define VIDEO_770_HBEND 0
-#define VIDEO_770_HBSTART (VIDEO_CHAR_COLUMNS * VIDEO_CHAR_WIDTH)
-#define VIDEO_770_VTOTAL 485
-#define VIDEO_770_VBEND 0
-#define VIDEO_770_VBSTART (VIDEO_770_VBEND + GVIDEO_VPIXELS)
-#define VIDEO_770_ALPHA_L_LIM 80 // Left-side limit of alpha-only horizontal part
-#define VIDEO_770_ALPHA_R_LIM 640 // Right-side limit of alpha-only horizontal part
-
-// Constants of 98780A video
-#define VIDEO_780_PIXEL_CLOCK 28224000
-#define VIDEO_780_HTOTAL 896
-#define VIDEO_780_VTOTAL 525
-#define VIDEO_780_HBEND 0
-#define VIDEO_780_HBSTART (VIDEO_CHAR_COLUMNS * VIDEO_CHAR_WIDTH)
-#define VIDEO_780_VBEND 0
-#define VIDEO_780_VBSTART (VIDEO_780_VBEND + GVIDEO_VPIXELS)
-#define VIDEO_780_ALPHA_L_LIM 80 // Left-side limit of alpha-only horizontal part
-#define VIDEO_780_ALPHA_R_LIM 640 // Right-side limit of alpha-only horizontal part
-
-#define I_GR 0xb0 // graphics intensity
-#define I_AL 0xd0 // alpha intensity
-#define I_CU 0xf0 // graphics cursor intensity
-#define I_LP 0xff // light pen cursor intensity
-
-// Palette indexes (for monochromatic screens)
-#define PEN_BLACK 0 // Black
-#define PEN_GRAPHIC 1 // Graphics
-#define PEN_ALPHA 2 // Text
-#define PEN_CURSOR 3 // Graphic cursor
-#define PEN_LP 4 // Light pen cursor
-
-// Light pen constants
-constexpr unsigned LP_FOV = 9; // Field of view
-constexpr unsigned LP_XOFFSET = 5; // x-offset of LP (due to delay in hit recognition)
-
-// Peripheral Addresses (PA)
-#define PRINTER_PA 0
-#define IO_SLOT_FIRST_PA 1
-#define IO_SLOT_LAST_PA 12
-#define GVIDEO_PA 13
-#define T14_PA 14
-#define T15_PA 15
-
-#define KEY_SCAN_OSCILLATOR 327680
-
-class hp9845_state : public driver_device
-{
-public:
- hp9845_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag)
- { }
-
- void hp9845a(machine_config &config);
- void hp9835a(machine_config &config);
-
-private:
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-};
-
-static INPUT_PORTS_START( hp9845 )
-INPUT_PORTS_END
-
-uint32_t hp9845_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- return 0;
-}
-
-static INPUT_PORTS_START(hp9845_base)
- // Keyboard is arranged in a 8 x 16 matrix. Of the 128 possible positions, 118 are used.
- // Keys are mapped on bit b of KEYn
- // where b = (row & 1) << 4 + column, n = row >> 1
- // column = [0..15]
- // row = [0..7]
- PORT_START("KEY0")
- PORT_BIT(BIT_MASK(0) , IP_ACTIVE_HIGH , IPT_UNUSED) // N/U
- PORT_BIT(BIT_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_TOGGLE PORT_NAME("Prt all") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845_base_state, togglekey_changed, 1) // Print All
- PORT_BIT(BIT_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) // KP +
- PORT_BIT(BIT_MASK(3) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA_PAD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) // KP ,
- PORT_BIT(BIT_MASK(4) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) // KP .
- PORT_BIT(BIT_MASK(5) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) // KP 0
- PORT_BIT(BIT_MASK(6) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_NAME("Execute") // Execute
- PORT_BIT(BIT_MASK(7) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_NAME("Cont") PORT_CHAR(13) // Cont
- PORT_BIT(BIT_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) // Right
- PORT_BIT(BIT_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') // Space
- PORT_BIT(BIT_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') // /
- PORT_BIT(BIT_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') // <
- PORT_BIT(BIT_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') // N
- PORT_BIT(BIT_MASK(13) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') // V
- PORT_BIT(BIT_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') // X
- PORT_BIT(BIT_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) // Shift
- PORT_BIT(BIT_MASK(16) , IP_ACTIVE_HIGH , IPT_UNUSED) // N/U
- PORT_BIT(BIT_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_TOGGLE PORT_NAME("Auto st") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845_base_state, togglekey_changed, 2) // Auto Start
- PORT_BIT(BIT_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) // KP -
- PORT_BIT(BIT_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) // KP 3
- PORT_BIT(BIT_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) // KP 2
- PORT_BIT(BIT_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) // KP 1
- PORT_BIT(BIT_MASK(22) , IP_ACTIVE_HIGH , IPT_UNUSED) // N/U
- PORT_BIT(BIT_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) // Left
- PORT_BIT(BIT_MASK(24) , IP_ACTIVE_HIGH , IPT_UNUSED) // Repeat
- PORT_BIT(BIT_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) // Down
- PORT_BIT(BIT_MASK(26) , IP_ACTIVE_HIGH , IPT_UNUSED) // N/U
- PORT_BIT(BIT_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') // >
- PORT_BIT(BIT_MASK(28) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') // M
- PORT_BIT(BIT_MASK(29) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') // B
- PORT_BIT(BIT_MASK(30) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') // C
- PORT_BIT(BIT_MASK(31) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') // Z
-
- PORT_START("KEY1")
- PORT_BIT(BIT_MASK(0) , IP_ACTIVE_HIGH , IPT_UNUSED) // N/U
- PORT_BIT(BIT_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_INSERT) PORT_NAME("Ins chr") // Ins Char
- PORT_BIT(BIT_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) // KP *
- PORT_BIT(BIT_MASK(3) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) // KP 6
- PORT_BIT(BIT_MASK(4) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) // KP 5
- PORT_BIT(BIT_MASK(5) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) // KP 4
- PORT_BIT(BIT_MASK(6) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS_PAD) PORT_CHAR(UCHAR_MAMEKEY(EQUALS_PAD)) // KP =
- PORT_BIT(BIT_MASK(7) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Pause") // Pause
- PORT_BIT(BIT_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) // Up
- PORT_BIT(BIT_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Store") // Store
- PORT_BIT(BIT_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') // :
- PORT_BIT(BIT_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') // K
- PORT_BIT(BIT_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') // H
- PORT_BIT(BIT_MASK(13) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') // F
- PORT_BIT(BIT_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') // S
- PORT_BIT(BIT_MASK(15) , IP_ACTIVE_HIGH , IPT_UNUSED) // N/U
- PORT_BIT(BIT_MASK(16) , IP_ACTIVE_HIGH , IPT_UNUSED) // N/U
- PORT_BIT(BIT_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Ins ln") // Ins Ln
- PORT_BIT(BIT_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) // KP /
- PORT_BIT(BIT_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) // KP 9
- PORT_BIT(BIT_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) // KP 8
- PORT_BIT(BIT_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) // KP 7
- PORT_BIT(BIT_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Result") // Result
- PORT_BIT(BIT_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Run") // Run
- PORT_BIT(BIT_MASK(24) , IP_ACTIVE_HIGH , IPT_UNUSED) // N/U
- PORT_BIT(BIT_MASK(25) , IP_ACTIVE_HIGH , IPT_UNUSED) // N/U
- PORT_BIT(BIT_MASK(26) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') // "
- PORT_BIT(BIT_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') // L
- PORT_BIT(BIT_MASK(28) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') // J
- PORT_BIT(BIT_MASK(29) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') // G
- PORT_BIT(BIT_MASK(30) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') // D
- PORT_BIT(BIT_MASK(31) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') // A
-
- PORT_START("KEY2")
- PORT_BIT(BIT_MASK(0) , IP_ACTIVE_HIGH , IPT_UNUSED) // N/U
- PORT_BIT(BIT_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Del ln") // Del Ln
- PORT_BIT(BIT_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Keypad ^") // KP ^
- PORT_BIT(BIT_MASK(3) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Keypad )") // KP )
- PORT_BIT(BIT_MASK(4) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Keypad (") // KP (
- PORT_BIT(BIT_MASK(5) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Keypad E") // KP E
- PORT_BIT(BIT_MASK(6) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Clear line") // Clear Line
- PORT_BIT(BIT_MASK(7) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) PORT_NAME("Stop") // Stop
- PORT_BIT(BIT_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') // |
- PORT_BIT(BIT_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') // ]
- PORT_BIT(BIT_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') // P
- PORT_BIT(BIT_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') // I
- PORT_BIT(BIT_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') // Y
- PORT_BIT(BIT_MASK(13) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') // R
- PORT_BIT(BIT_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') // W
- PORT_BIT(BIT_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) // Control
- PORT_BIT(BIT_MASK(16) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Typwtr") // Typwtr
- PORT_BIT(BIT_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_NAME("Del chr") // Del Char
- PORT_BIT(BIT_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_PGDN) PORT_NAME("Roll down") // Roll down
- PORT_BIT(BIT_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_PGUP) PORT_NAME("Roll up") // Roll up
- PORT_BIT(BIT_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_NAME("Home") // Home
- PORT_BIT(BIT_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_END) PORT_NAME("Clr to end") // Clr to end
- PORT_BIT(BIT_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Clear") // Clear
- PORT_BIT(BIT_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') // ~
- PORT_BIT(BIT_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) // BS
- PORT_BIT(BIT_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') // +
- PORT_BIT(BIT_MASK(26) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') // [
- PORT_BIT(BIT_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') // O
- PORT_BIT(BIT_MASK(28) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') // U
- PORT_BIT(BIT_MASK(29) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') // T
- PORT_BIT(BIT_MASK(30) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') // E
- PORT_BIT(BIT_MASK(31) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') // Q
-
- PORT_START("KEY3")
- PORT_BIT(BIT_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Tab set") // Tab set
- PORT_BIT(BIT_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Recall") // Recall
- PORT_BIT(BIT_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("K15") // K15
- PORT_BIT(BIT_MASK(3) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("K14") // K14
- PORT_BIT(BIT_MASK(4) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("K13") // K13
- PORT_BIT(BIT_MASK(5) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_NAME("K12") // K12
- PORT_BIT(BIT_MASK(6) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_NAME("K11") // K11
- PORT_BIT(BIT_MASK(7) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_NAME("K10") // K10
- PORT_BIT(BIT_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_NAME("K9") // K9
- PORT_BIT(BIT_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_NAME("K8") // K8
- PORT_BIT(BIT_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') // 0
- PORT_BIT(BIT_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') // 8
- PORT_BIT(BIT_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') // 6
- PORT_BIT(BIT_MASK(13) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') // 4
- PORT_BIT(BIT_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') // 2
- PORT_BIT(BIT_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t') // Tab
- PORT_BIT(BIT_MASK(16) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Tab clr") // Tab clr
- PORT_BIT(BIT_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Step") // Step
- PORT_BIT(BIT_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_NAME("K7") // K7
- PORT_BIT(BIT_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_NAME("K6") // K6
- PORT_BIT(BIT_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_NAME("K5") // K5
- PORT_BIT(BIT_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_NAME("K4") // K4
- PORT_BIT(BIT_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_NAME("K3") // K3
- PORT_BIT(BIT_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_NAME("K2") // K2
- PORT_BIT(BIT_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_NAME("K1") // K1
- PORT_BIT(BIT_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("K0") // K0
- PORT_BIT(BIT_MASK(26) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') // _
- PORT_BIT(BIT_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') // 9
- PORT_BIT(BIT_MASK(28) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') // 7
- PORT_BIT(BIT_MASK(29) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') // 5
- PORT_BIT(BIT_MASK(30) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') // 3
- PORT_BIT(BIT_MASK(31) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') // 1
-
- PORT_START("SHIFTLOCK");
- PORT_BIT(BIT_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_NAME("Shift lock") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845_base_state, togglekey_changed, 0) // Shift lock
-
-INPUT_PORTS_END
-
-/*
- German keyboard layout
-
- Remarks:
- - Most keys including umlauts map correctly to the German keyboard layout of the 9845 without special configuration,
- provided that the German keyboard firmware ROM is used on the 9845
- - '#' maps positionally correct to Shift+3
- - AltGr modifier on the Germany PC keyboard for 9845 shifted keycodes 23=| and 5=@ need to get assigned dynamically
- - ~{}\'` are not available on the German 9845 keyboard, ^ is available via keypad only
-*/
-static INPUT_PORTS_START(hp9845_base_de)
- PORT_INCLUDE(hp9845_base)
-
- PORT_MODIFY("KEY0")
- PORT_BIT(BIT_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_') // - _
- PORT_BIT(BIT_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';') // , ;
- PORT_BIT(BIT_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':') // . :
- PORT_BIT(BIT_MASK(31) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('y') PORT_CHAR('Y') // Y
-
- PORT_MODIFY("KEY1")
- PORT_BIT(BIT_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00f6) PORT_CHAR(0x00d6) // Ö
- PORT_BIT(BIT_MASK(26) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00e4) PORT_CHAR(0x00c4) // Ä
-
- PORT_MODIFY("KEY2")
- PORT_BIT(BIT_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') // < >
- PORT_BIT(BIT_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('+') PORT_CHAR('*') // + *
- PORT_BIT(BIT_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('z') PORT_CHAR('Z') // Z
- PORT_BIT(BIT_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) // Backspace
- PORT_BIT(BIT_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR(']') PORT_CHAR('@') // ] @
- PORT_BIT(BIT_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('[') PORT_CHAR('|') // [ |
- PORT_BIT(BIT_MASK(26) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00fc) PORT_CHAR(0x00dc) // Ü
-
- PORT_MODIFY("KEY3")
- PORT_BIT(BIT_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') // 0 =
- PORT_BIT(BIT_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') // 8 (
- PORT_BIT(BIT_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') // 6 &
- PORT_BIT(BIT_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') // 2 "
- PORT_BIT(BIT_MASK(26) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(0x00df) PORT_CHAR('?') // ß ?
- PORT_BIT(BIT_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') // 9 )
- PORT_BIT(BIT_MASK(28) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') // 7 /
-INPUT_PORTS_END
-
-// *******************
-// hp9845_base_state
-// *******************
-hp9845_base_state::hp9845_base_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag),
- m_lpu(*this, "lpu"),
- m_ppu(*this, "ppu"),
- m_io_sys(*this , "io_sys"),
- m_screen(*this, "screen"),
- m_palette(*this, "palette"),
- m_gv_timer(*this, "gv_timer"),
- m_io_key(*this, "KEY%u", 0U),
- m_io_shiftlock(*this, "SHIFTLOCK"),
- m_t14(*this, "t14"),
- m_t15(*this, "t15"),
- m_beeper(*this, "beeper"),
- m_beep_timer(*this, "beep_timer"),
- m_io_slot(*this, "slot%u", 0U),
- m_ram(*this, RAM_TAG),
- m_softkeys(*this, "Softkey%u", 0U),
- m_chargen(*this, "chargen")
-{
-}
-
-void hp9845_base_state::setup_ram_block(unsigned block , unsigned offset)
-{
- unsigned block_addr = block << 16;
- m_lpu->space(AS_PROGRAM).install_ram(block_addr , block_addr + 0x7fff , m_ram->pointer() + offset);
- m_ppu->space(AS_PROGRAM).install_ram(block_addr , block_addr + 0x7fff , m_ram->pointer() + offset);
-}
-
-void hp9845_base_state::machine_start()
-{
- m_softkeys.resolve();
- m_screen->register_screen_bitmap(m_bitmap);
-
- // setup RAM dynamically for -ramsize
- // 0K..64K
- setup_ram_block(0 , 0);
- if (m_ram->size() >= 192 * 1024) {
- // 64K..192K
- setup_ram_block(004 , 0x10000);
- setup_ram_block(006 , 0x20000);
- }
- if (m_ram->size() >= 320 * 1024) {
- // 192K..320K
- setup_ram_block(010 , 0x30000);
- setup_ram_block(012 , 0x40000);
- }
- if (m_ram->size() >= 448 * 1024) {
- // 320K..448K
- setup_ram_block(014 , 0x50000);
- setup_ram_block(016 , 0x60000);
- }
-}
-
-void hp9845_base_state::device_reset()
-{
- // First, unmap every r/w handler in 1..12 select codes
- for (unsigned sc = IO_SLOT_FIRST_PA; sc < (IO_SLOT_LAST_PA + 1); sc++) {
- m_ppu->space(AS_IO).unmap_readwrite(sc * 4 , sc * 4 + 3);
- }
-
- // Then, set r/w handlers of all installed I/O cards
- int sc;
- read16_delegate rhandler(*this);
- write16_delegate whandler(*this);
- for (unsigned i = 0; 4 > i; ++i) {
- if ((sc = m_io_slot[i]->get_rw_handlers(rhandler , whandler)) >= 0) {
- logerror("Install R/W handlers for slot %u @ SC = %d\n", i, sc);
- m_ppu->space(AS_IO).install_readwrite_handler(sc * 4 , sc * 4 + 3 , rhandler , whandler);
- if (m_io_slot[ i ]->has_dual_sc()) {
- logerror("Installing dual SC\n");
- m_ppu->space(AS_IO).install_readwrite_handler(sc * 4 + 4 , sc * 4 + 7 , rhandler , whandler);
- }
- }
- m_slot_sc[ i ] = sc;
- }
-}
-
-void hp9845_base_state::machine_reset()
-{
- m_lpu->halt_w(1);
- m_ppu->halt_w(0);
-
- // Some sensible defaults
- m_video_load_mar = false;
- m_video_first_mar = false;
- m_video_byte_idx = false;
- m_video_buff_idx = false;
- m_video_blanked = false;
- m_graphic_sel = false;
- m_gv_fsm_state = GV_STAT_RESET;
- m_gv_int_en = false;
- m_gv_dma_en = false;
-
- m_io_sys->set_sts(GVIDEO_PA , true);
-
- memset(&m_kb_state[ 0 ] , 0 , sizeof(m_kb_state));
- m_kb_scancode = 0x7f;
- m_kb_status = 0;
-
- m_beeper->set_state(0);
-
- m_prt_irl = false;
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER(hp9845_base_state::gv_timer)
-{
- advance_gv_fsm(false , false);
-}
-
-attotime hp9845_base_state::time_to_gv_mem_availability() const
-{
- if (m_graphic_sel) {
- int hpos = m_screen->hpos();
- if (hpos < (34 - GVIDEO_HCNT_OFF) || hpos >= (628 - GVIDEO_HCNT_OFF)) {
- // Access to graphic memory available now
- return attotime::zero;
- } else {
- // Wait until start of hblank
- return m_screen->time_until_pos(m_screen->vpos() , 628);
- }
- } else {
- // TODO:
- return attotime::zero;
- }
-}
-
-void hp9845_base_state::kb_scan_ioport(ioport_value pressed , ioport_port &port , unsigned idx_base , int& max_seq_len , unsigned& max_seq_idx)
-{
- while (pressed) {
- unsigned bit_no = 31 - count_leading_zeros(pressed);
- ioport_value mask = BIT_MASK(bit_no);
- int seq_len = port.field(mask)->seq().length();
- if (seq_len > max_seq_len) {
- max_seq_len = seq_len;
- max_seq_idx = bit_no + idx_base;
- }
- pressed &= ~mask;
- }
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER(hp9845_base_state::kb_scan)
-{
- ioport_value input[ 4 ]{
- m_io_key[0]->read(),
- m_io_key[1]->read(),
- m_io_key[2]->read(),
- m_io_key[3]->read() };
-
- // Shift lock
- ioport_value shiftlock = m_io_shiftlock->read();
-
- // Set status bits for "shift", "control", "auto start" & "print all" keys
- // ** Print all **
- // (R,C) = (0,1)
- // Bit 12 in kb status
- if (BIT(input[ 0 ] , 1)) {
- BIT_SET(m_kb_status , 12);
- BIT_CLR(input[ 0 ] , 1);
- } else {
- BIT_CLR(m_kb_status, 12);
- }
- // ** Auto start **
- // (R,C) = (1,1)
- // Bit 13 in kb status
- if (BIT(input[ 0 ] , 17)) {
- BIT_SET(m_kb_status , 13);
- BIT_CLR(input[ 0 ] , 17);
- } else {
- BIT_CLR(m_kb_status, 13);
- }
- // ** Control **
- // (R,C) = (4,15)
- // Bit 14 in kb status
- if (BIT(input[ 2 ] , 15)) {
- BIT_SET(m_kb_status , 14);
- BIT_CLR(input[ 2 ] , 15);
- } else {
- BIT_CLR(m_kb_status, 14);
- }
- // ** Shift **
- // (R,C) = (0,15)
- // Bit 15 in kb status
- if (BIT(input[ 0 ] , 15) || shiftlock) {
- BIT_SET(m_kb_status , 15);
- BIT_CLR(input[ 0 ] , 15);
- } else {
- BIT_CLR(m_kb_status, 15);
- }
-
- int max_seq_len = 0;
- unsigned max_seq_idx = 0;
- for (unsigned i = 0; 4 > i; ++i)
- kb_scan_ioport(input[i] & ~m_kb_state[i] , *m_io_key[i] , i << 5 , max_seq_len , max_seq_idx);
- // TODO: handle repeat key
- // TODO: handle ctrl+stop
-
- if (max_seq_len) {
- // Key pressed, store scancode & generate IRL
- m_kb_scancode = max_seq_idx;
- BIT_SET(m_kb_status, 0);
- update_kb_prt_irq();
-
- // Special case: pressing stop key sets LPU "status" flag
- if (max_seq_idx == 0x47) {
- m_lpu->status_w(1);
- }
- }
-
- memcpy(&m_kb_state[ 0 ] , &input[ 0 ] , sizeof(m_kb_state));
-}
-
-READ16_MEMBER(hp9845_base_state::kb_scancode_r)
-{
- return ~m_kb_scancode & 0x7f;
-}
-
-READ16_MEMBER(hp9845_base_state::kb_status_r)
-{
- return m_kb_status;
-}
-
-WRITE16_MEMBER(hp9845_base_state::kb_irq_clear_w)
-{
- BIT_CLR(m_kb_status, 0);
- update_kb_prt_irq();
- m_lpu->status_w(0);
-
- if (BIT(data , 15)) {
- // Start beeper
- m_beep_timer->adjust(attotime::from_ticks(64, KEY_SCAN_OSCILLATOR / 512));
- m_beeper->set_state(1);
- }
-}
-
-void hp9845_base_state::update_kb_prt_irq()
-{
- bool state = BIT(m_kb_status , 0) || m_prt_irl;
- m_io_sys->set_irq(0 , state);
-}
-
-void hp9845_base_state::set_irq_slot(unsigned slot , int state)
-{
- int sc = m_slot_sc[ slot ];
- assert(sc >= 0);
- m_io_sys->set_irq(uint8_t(sc) , state);
-}
-
-void hp9845_base_state::set_sts_slot(unsigned slot , int state)
-{
- int sc = m_slot_sc[ slot ];
- assert(sc >= 0);
- m_io_sys->set_sts(uint8_t(sc) , state);
-}
-
-void hp9845_base_state::set_flg_slot(unsigned slot , int state)
-{
- int sc = m_slot_sc[ slot ];
- assert(sc >= 0);
- m_io_sys->set_flg(uint8_t(sc) , state);
-}
-
-void hp9845_base_state::set_irq_nextsc_slot(unsigned slot , int state)
-{
- int sc = m_slot_sc[ slot ];
- assert(sc >= 0);
- m_io_sys->set_irq(uint8_t(sc + 1) , state);
-}
-
-void hp9845_base_state::set_sts_nextsc_slot(unsigned slot , int state)
-{
- int sc = m_slot_sc[ slot ];
- assert(sc >= 0);
- m_io_sys->set_sts(uint8_t(sc + 1) , state);
-}
-
-void hp9845_base_state::set_flg_nextsc_slot(unsigned slot , int state)
-{
- int sc = m_slot_sc[ slot ];
- assert(sc >= 0);
- m_io_sys->set_flg(uint8_t(sc + 1) , state);
-}
-
-void hp9845_base_state::set_dmar_slot(unsigned slot , int state)
-{
- int sc = m_slot_sc[ slot ];
- assert(sc >= 0);
- m_io_sys->set_dmar(uint8_t(sc) , state);
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER(hp9845_base_state::beeper_off)
-{
- m_beeper->set_state(0);
-}
-
-WRITE_LINE_MEMBER(hp9845_base_state::prt_irl_w)
-{
- m_prt_irl = state;
- update_kb_prt_irq();
-}
-
-INPUT_CHANGED_MEMBER(hp9845_base_state::togglekey_changed)
-{
- uint32_t togglekey = param;
- switch (togglekey) {
- case 0: // Shift lock
- {
- bool state = m_io_shiftlock->read();
- popmessage("SHIFT LOCK %s", state ? "ON" : "OFF");
- output().set_value("shift_lock_led" , state);
- }
- break;
- case 1: // Prt all
- {
- bool state = BIT(m_io_key[0]->read(), 1);
- popmessage("PRT ALL %s", state ? "ON" : "OFF");
- output().set_value("prt_all_led" , state);
- }
- break;
- case 2: // Auto st
- {
- bool state = BIT(m_io_key[0]->read(), 17);
- popmessage("AUTO ST %s", state ? "ON" : "OFF");
- output().set_value("auto_st_led" , state);
- }
- break;
- }
-}
-
-// ***************
-// hp9845b_state
-// ***************
-class hp9845b_state : public hp9845_base_state
-{
-public:
- hp9845b_state(const machine_config &mconfig, device_type type, const char *tag);
-
- void hp9845b(machine_config &config);
-
-private:
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- virtual void machine_start() override;
- virtual void machine_reset() override;
-
- virtual DECLARE_READ16_MEMBER(graphic_r) override;
- virtual DECLARE_WRITE16_MEMBER(graphic_w) override;
-
- TIMER_DEVICE_CALLBACK_MEMBER(scanline_timer);
-
- DECLARE_WRITE_LINE_MEMBER(vblank_w);
-
- void set_graphic_mode(bool graphic);
- void set_video_mar(uint16_t mar);
- void video_fill_buff(bool buff_idx);
- void video_render_buff(unsigned video_scanline , unsigned line_in_row, bool buff_idx);
- void graphic_video_render(unsigned video_scanline);
-
- virtual void advance_gv_fsm(bool ds , bool trigger) override;
- void update_graphic_bits();
-
- // Optional character generator
- required_region_ptr<uint8_t> m_optional_chargen;
-
- uint8_t m_video_attr;
- uint16_t m_gv_cursor_w; // U38 & U39 (GS)
- std::vector<uint16_t> m_graphic_mem;
-};
-
-hp9845b_state::hp9845b_state(const machine_config &mconfig, device_type type, const char *tag)
- : hp9845_base_state(mconfig , type , tag),
- m_optional_chargen(*this , "optional_chargen")
-{
-}
-
-uint32_t hp9845b_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &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;
-}
-
-void hp9845b_state::machine_start()
-{
- // Common part first
- hp9845_base_state::machine_start();
-
- m_graphic_mem.resize(GVIDEO_MEM_SIZE);
-
- // initialize palette
- m_palette->set_pen_color(PEN_BLACK , 0x00, 0x00, 0x00); // black
- m_palette->set_pen_color(PEN_GRAPHIC, 0x00, I_GR, 0x00); // graphics
- m_palette->set_pen_color(PEN_ALPHA , 0x00, I_AL, 0x00); // alpha
- m_palette->set_pen_color(PEN_CURSOR , 0x00, I_CU, 0x00); // graphics cursor
-}
-
-void hp9845b_state::machine_reset()
-{
- // Common part first
- hp9845_base_state::machine_reset();
-
- set_video_mar(0);
- m_video_attr = 0;
- update_graphic_bits();
-}
-
-READ16_MEMBER(hp9845b_state::graphic_r)
-{
- uint16_t 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); // ID
- 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_t)(data & 0xf);
- m_gv_dma_en = BIT(data , 6) != 0;
- m_gv_int_en = BIT(data , 7) != 0;
- if (BIT(data , 5)) {
- m_gv_fsm_state = GV_STAT_RESET;
- }
- 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;
- }
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER(hp9845b_state::scanline_timer)
-{
- unsigned video_scanline = param;
-
- if (m_graphic_sel) {
- if (video_scanline >= GVIDEO_VBEND && video_scanline < GVIDEO_VBSTART) {
- graphic_video_render(video_scanline);
- }
- } else if (video_scanline < VIDEO_ACTIVE_SCANLINES) {
- unsigned row = video_scanline / VIDEO_CHAR_HEIGHT;
- unsigned line_in_row = video_scanline - row * VIDEO_CHAR_HEIGHT;
-
- 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(video_scanline , line_in_row , m_video_buff_idx);
- }
-}
-
-WRITE_LINE_MEMBER(hp9845b_state::vblank_w)
-{
- // 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_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);
- // Set graphic mode view (1.23:1 aspect ratio)
- machine().render().first_target()->set_view(1);
- } else {
- m_screen->configure(VIDEO_HTOTAL , VIDEO_VTOTAL , rectangle(0 , VIDEO_HBSTART - 1 , 0 , VIDEO_ACTIVE_SCANLINES - 1) , HZ_TO_ATTOSECONDS(VIDEO_PIXEL_CLOCK) * VIDEO_HTOTAL * VIDEO_VTOTAL);
- // Set alpha mode view (1.92:1 aspect ratio)
- machine().render().first_target()->set_view(0);
- }
- }
-}
-
-void hp9845b_state::set_video_mar(uint16_t mar)
-{
- m_video_mar = (mar & 0xfff) | VIDEO_BUFFER_BASE_HIGH;
-}
-
-void hp9845b_state::video_fill_buff(bool buff_idx)
-{
- unsigned char_idx = 0;
- unsigned iters = 0;
- uint8_t byte;
- address_space& prog_space = m_ppu->space(AS_PROGRAM);
-
- m_video_buff[ buff_idx ].full = false;
-
- while (1) {
- if (!m_video_byte_idx) {
- if (iters++ >= MAX_WORD_PER_ROW) {
- // Limit on accesses per row reached
- break;
- }
- m_video_word = prog_space.read_word(m_video_mar);
- if (m_video_load_mar) {
- // Load new address into MAR after start of a new frame or NWA instruction
- 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;
- } else {
- // Read normal word from frame buffer, start parsing at MSB
- set_video_mar(m_video_mar + 1);
- byte = (uint8_t)(m_video_word >> 8);
- m_video_byte_idx = true;
- }
- } else {
- // Parse LSB
- byte = (uint8_t)(m_video_word & 0xff);
- m_video_byte_idx = false;
- }
- if ((byte & 0xc0) == 0x80) {
- // Attribute command
- m_video_attr = byte & 0x1f;
- } else if ((byte & 0xc1) == 0xc0) {
- // New Word Address (NWA)
- m_video_load_mar = true;
- m_video_byte_idx = false;
- } else if ((byte & 0xc1) == 0xc1) {
- // End of line (EOL)
- // Fill rest of buffer with spaces
- memset(&m_video_buff[ buff_idx ].chars[ char_idx ] , 0x20 , 80 - char_idx);
- memset(&m_video_buff[ buff_idx ].attrs[ char_idx ] , m_video_attr , 80 - char_idx);
- m_video_buff[ buff_idx ].full = true;
- break;
- } else {
- // Normal character
- m_video_buff[ buff_idx ].chars[ char_idx ] = byte;
- m_video_buff[ buff_idx ].attrs[ char_idx ] = m_video_attr;
- char_idx++;
- if (char_idx == 80) {
- m_video_buff[ buff_idx ].full = true;
- break;
- }
- }
- }
-}
-
-void hp9845b_state::video_render_buff(unsigned video_scanline , unsigned line_in_row, bool buff_idx)
-{
- if (!m_video_buff[ buff_idx ].full) {
- m_video_blanked = true;
- }
-
- const pen_t *pen = m_palette->pens();
-
- if (m_video_blanked) {
- // Blank scanline
- for (unsigned i = 0; i < VIDEO_HBSTART; i++) {
- m_bitmap.pix32(video_scanline , i) = pen[ PEN_BLACK ];
- }
- } else {
- bool cursor_line = line_in_row == 12;
- bool ul_line = line_in_row == 14;
- unsigned video_frame = (unsigned)m_screen->frame_number();
- bool cursor_blink = BIT(video_frame , 3);
- bool char_blink = BIT(video_frame , 4);
-
- for (unsigned i = 0; i < 80; i++) {
- uint8_t charcode = m_video_buff[ buff_idx ].chars[ i ];
- uint8_t attrs = m_video_buff[ buff_idx ].attrs[ i ];
- uint16_t chrgen_addr = ((uint16_t)(charcode ^ 0x7f) << 4) | line_in_row;
- uint16_t pixels;
-
- if ((ul_line && BIT(attrs , 3)) ||
- (cursor_line && cursor_blink && BIT(attrs , 0))) {
- pixels = ~0;
- } else if (char_blink && BIT(attrs , 2)) {
- pixels = 0;
- } else if (BIT(attrs , 4)) {
- pixels = (uint16_t)(m_optional_chargen[ chrgen_addr ] & 0x7f) << 1;
- } else {
- pixels = (uint16_t)(m_chargen[ chrgen_addr ] & 0x7f) << 1;
- }
-
- if (BIT(attrs , 1)) {
- pixels = ~pixels;
- }
-
- for (unsigned j = 0; j < 9; j++) {
- bool pixel = (pixels & (1U << j)) != 0;
-
- m_bitmap.pix32(video_scanline , i * 9 + j) = pen[ pixel ? PEN_ALPHA : PEN_BLACK ];
- }
- }
- }
-}
-
-void hp9845b_state::graphic_video_render(unsigned video_scanline)
-{
- const pen_t *pen = m_palette->pens();
- bool yc = (video_scanline + GVIDEO_VCNT_OFF) == (m_gv_cursor_y + 6);
- bool yw;
- bool blink;
-
- if (m_gv_cursor_fs) {
- yw = true;
- // Steady cursor
- blink = true;
- } else {
- yw = (video_scanline + GVIDEO_VCNT_OFF) >= (m_gv_cursor_y + 2) &&
- (video_scanline + GVIDEO_VCNT_OFF) <= (m_gv_cursor_y + 10);
- // Blinking cursor (frame freq. / 16)
- blink = BIT(m_screen->frame_number() , 3) != 0;
- }
-
- unsigned mem_idx = 36 * (video_scanline - GVIDEO_VBEND);
- for (unsigned i = 0; i < GVIDEO_HPIXELS; i += 16) {
- uint16_t word = m_graphic_mem[ mem_idx++ ];
- unsigned x = i;
- for (uint16_t mask = 0x8000; mask != 0; mask >>= 1) {
- unsigned cnt_h = x + GVIDEO_HBEND + GVIDEO_HCNT_OFF;
- bool xc = cnt_h == (m_gv_cursor_x + 6);
- bool xw = m_gv_cursor_fs || (cnt_h >= (m_gv_cursor_x + 2) && cnt_h <= (m_gv_cursor_x + 10));
- unsigned pixel;
- if (blink && ((xw && yc) || (yw && xc && m_gv_cursor_gc))) {
- // Cursor
- pixel = PEN_CURSOR;
- } else {
- // Normal pixel
- pixel = (word & mask) != 0 ? PEN_GRAPHIC : PEN_BLACK;
- }
- m_bitmap.pix32(video_scanline - GVIDEO_VBEND , x++) = pen[ pixel ];
- }
- }
-}
-
-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:
- if ((m_gv_cmd & 0xc) == 0xc) {
- // Read command (11xx)
- m_gv_fsm_state = GV_STAT_WAIT_MEM_0;
- } else if (ds) {
- // Wait for data strobe (r/w on r4 or r6)
- 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;
- // 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;
- } 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;
- }
- 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 ];
- m_gv_io_counter = (m_gv_io_counter + 1) & GVIDEO_ADDR_MASK;
- m_gv_fsm_state = GV_STAT_WAIT_DS_1;
- } else {
- m_gv_timer->adjust(time_mem_av);
- 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
- 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 {
- m_gv_timer->adjust(time_mem_av);
- 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
- uint16_t 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 {
- m_gv_timer->adjust(time_mem_av);
- 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()
-{
- bool 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;
-
- m_io_sys->set_flg(GVIDEO_PA , gv_ready);
-
- bool irq = m_gv_int_en && !m_gv_dma_en && gv_ready;
-
- m_io_sys->set_irq(GVIDEO_PA , irq);
-
- bool dmar = gv_ready && m_gv_dma_en;
-
- m_io_sys->set_dmar(GVIDEO_PA , dmar);
-}
-
-// ***************
-// hp9845ct_base_state
-// ***************
-
-class hp9845ct_base_state : public hp9845_base_state
-{
-public:
- hp9845ct_base_state(const machine_config &mconfig, device_type type, const char *tag);
-
- virtual void machine_start() override;
- virtual void machine_reset() override;
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- DECLARE_WRITE_LINE_MEMBER(vblank_w);
- DECLARE_INPUT_CHANGED_MEMBER(softkey_changed);
-
-protected:
- required_ioport m_io_softkeys;
- required_ioport m_lightpen_x;
- required_ioport m_lightpen_y;
- required_ioport m_lightpen_sw;
-
- virtual void set_graphic_mode(bool graphic , bool alpha) = 0;
- void set_video_mar(uint16_t mar);
- void video_fill_buff(bool buff_idx);
- virtual void plot(uint16_t x, uint16_t y, bool draw_erase) = 0;
- void draw_line(unsigned x0 , unsigned y0 , unsigned x1 , unsigned y1);
- void update_line_pattern();
- void pattern_fill(uint16_t x0 , uint16_t y0 , uint16_t x1 , uint16_t y1 , unsigned fill_idx);
- static uint16_t get_gv_mem_addr(unsigned x , unsigned y);
- virtual void update_graphic_bits() = 0;
- static int get_wrapped_scanline(unsigned scanline);
- void render_lp_cursor(unsigned video_scanline , unsigned pen_idx);
-
- void lp_r4_w(uint16_t data);
- uint16_t lp_r4_r();
- void lp_r5_w(uint16_t data);
- bool lp_segment_intersect(unsigned yline) const;
- void compute_lp_data();
- void lp_scanline_update(unsigned video_scanline);
-
- virtual void update_gcursor() = 0;
-
- bool m_alpha_sel;
- bool m_gv_sk_en;
- bool m_gv_gr_en;
- bool m_gv_opt_en;
- bool m_gv_dsa_en;
- bool m_gv_lp_status;
- bool m_gv_sk_status;
- uint16_t m_gv_lp_cursor_x;
- uint16_t m_gv_lp_cursor_y;
- bool m_gv_lp_cursor_fs;
- bool m_gv_lp_en;
- uint8_t m_gv_last_cmd;
- uint16_t m_gv_word_x_position;
- uint16_t m_gv_word_y_position;
- uint16_t m_gv_memory_control;
- uint16_t m_gv_line_type_area_fill;
- uint16_t m_gv_line_type_mask;
- uint8_t m_gv_repeat_count;
- uint16_t m_gv_xpt;
- uint16_t m_gv_ypt;
- uint16_t m_gv_last_xpt;
- uint16_t m_gv_last_ypt;
- uint16_t m_gv_lp_data[ 3 ];
- uint16_t m_gv_next_lp_data[ 3 ];
- unsigned m_gv_next_lp_scanline[ 3 ];
- bool m_gv_lp_selftest;
- bool m_gv_lp_interlace;
- bool m_gv_lp_vblank;
- bool m_gv_lp_1sthit;
- bool m_gv_lp_vbint;
- bool m_gv_lp_fullbright;
- bool m_gv_lp_threshold;
- uint16_t m_gv_lp_x;
- uint16_t m_gv_lp_y;
- bool m_gv_lp_sw;
- uint8_t m_gv_lp_reg_cnt;
- bool m_gv_lp_int_en;
- bool m_gv_lp_hit_lt192;
- bool m_gv_lp_int_256;
- uint16_t m_gv_lxc;
- uint16_t m_gv_lyc;
- uint8_t m_gv_softkey;
-
- static const uint16_t m_line_type[];
- static const uint16_t m_area_fill[];
-};
-
-/*
- For 9845C and 9845T we just add the light pen support via MAME's lightgun device.
-
- Note that the LIGHTGUN device needs '-lightgun' and '-lightgun_device mouse' for light gun emulation if no real light gun device is installed.
- */
-static INPUT_PORTS_START(hp9845ct)
- PORT_INCLUDE(hp9845_base)
- PORT_START("SOFTKEYS")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey0") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey1") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey2") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey3") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey4") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey5") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey6") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey7") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
-
- PORT_START("LIGHTPENX")
- PORT_BIT( 0x3ff, 0x000, IPT_LIGHTGUN_X ) PORT_SENSITIVITY(20) PORT_MINMAX(0, VIDEO_TOT_HPIXELS - 1) PORT_CROSSHAIR(X, 1.0, 0.0, 0)
-
- PORT_START("LIGHTPENY")
- PORT_BIT( 0x3ff, 0x000, IPT_LIGHTGUN_Y ) PORT_SENSITIVITY(20) PORT_MINMAX(0, GVIDEO_VPIXELS - 1) PORT_CROSSHAIR(Y, 1.0, 0.0, 0)
-
- PORT_START("GKEY")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("Gkey")
-INPUT_PORTS_END
-
-static INPUT_PORTS_START(hp9845ct_de)
- PORT_INCLUDE(hp9845_base_de)
- PORT_START("SOFTKEYS")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey0") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey1") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey2") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey3") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey4") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey5") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey6") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Softkey7") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9845ct_base_state, softkey_changed, 0)
-
- PORT_START("LIGHTPENX")
- PORT_BIT( 0x3ff, 0x000, IPT_LIGHTGUN_X ) PORT_SENSITIVITY(20) PORT_MINMAX(0, VIDEO_TOT_HPIXELS - 1) PORT_CROSSHAIR(X, 1.0, 0.0, 0)
-
- PORT_START("LIGHTPENY")
- PORT_BIT( 0x3ff, 0x000, IPT_LIGHTGUN_Y ) PORT_SENSITIVITY(20) PORT_MINMAX(0, GVIDEO_VPIXELS - 1) PORT_CROSSHAIR(Y, 1.0, 0.0, 0)
-
- PORT_START("GKEY")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("Gkey")
-INPUT_PORTS_END
-
-hp9845ct_base_state::hp9845ct_base_state(const machine_config &mconfig, device_type type, const char *tag)
- : hp9845_base_state(mconfig , type , tag),
- m_io_softkeys(*this, "SOFTKEYS"),
- m_lightpen_x(*this, "LIGHTPENX"),
- m_lightpen_y(*this, "LIGHTPENY"),
- m_lightpen_sw(*this, "GKEY")
-{
-}
-
-void hp9845ct_base_state::machine_start()
-{
- // Common part first
- hp9845_base_state::machine_start();
-}
-
-void hp9845ct_base_state::machine_reset()
-{
- // Common part first
- hp9845_base_state::machine_reset();
-
- m_alpha_sel = true;
- m_gv_sk_en = false;
- m_gv_gr_en = false;
- m_gv_opt_en = false;
- m_gv_dsa_en = false;
- m_gv_lp_status = false;
- m_gv_sk_status = false;
- m_gv_lp_cursor_x = 944;
- m_gv_lp_cursor_y = 50;
- m_gv_lp_cursor_fs = false;
- m_gv_lp_en = false;
- m_gv_last_cmd = 0;
- m_gv_word_x_position = 0;
- m_gv_word_y_position = 0;
- m_gv_memory_control = 0;
- m_gv_line_type_area_fill = 0;
- m_gv_line_type_mask = 0xffff;
- m_gv_repeat_count = 0;
- m_gv_xpt = 0;
- m_gv_ypt = 0;
- m_gv_last_xpt = 0;
- m_gv_last_ypt = 0;
- m_gv_lp_selftest = false;
- m_gv_lp_interlace = false;
- m_gv_lp_vblank = false;
- m_gv_lp_1sthit = false;
- m_gv_lp_vbint = false;
- m_gv_lp_fullbright = false;
- m_gv_lp_threshold = false;
- m_gv_lp_x = 0;
- m_gv_lp_y = 0;
- m_gv_lp_sw = false;
- m_gv_lp_int_en = false;
-
- update_graphic_bits();
-}
-
-uint32_t hp9845ct_base_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
-
- return 0;
-}
-
-WRITE_LINE_MEMBER(hp9845ct_base_state::vblank_w)
-{
- // 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_blanked = false;
- m_video_buff_idx = !m_video_buff_idx;
- video_fill_buff(!m_video_buff_idx);
-
- // lightpen
- m_gv_lp_vblank = true;
- m_gv_lp_sw = m_lightpen_sw->read();
- m_gv_lp_x = m_lightpen_x->read();
- if (m_gv_lp_x > (VIDEO_TOT_HPIXELS - 1)) {
- m_gv_lp_x = VIDEO_TOT_HPIXELS - 1;
- }
- m_gv_lp_y = m_lightpen_y->read();
- if (m_gv_lp_y > (GVIDEO_VPIXELS - 1)) {
- m_gv_lp_y = GVIDEO_VPIXELS - 1;
- }
- } else {
- m_gv_lp_vblank = false;
- update_gcursor();
- }
-}
-
-INPUT_CHANGED_MEMBER(hp9845ct_base_state::softkey_changed)
-{
- uint8_t softkey_data = m_io_softkeys->read();
- unsigned softkey;
- for (softkey = 0; softkey < 8; softkey++) {
- m_softkeys[softkey] = !BIT(softkey_data , 7 - softkey);
- }
- for (softkey = 0; softkey < 8 && BIT(softkey_data , 7 - softkey); softkey++) {
- }
- LOG("SK %02x => %u\n" , softkey_data , softkey);
- if (softkey < 8 && !m_gv_sk_status) {
- // softkey pressed
- m_gv_softkey = softkey;
- m_gv_sk_status = true;
- update_graphic_bits();
- }
-}
-
-void hp9845ct_base_state::set_video_mar(uint16_t mar)
-{
- m_video_mar = (mar & 0x1fff) | VIDEO_BUFFER_BASE_LOW;
-}
-
-void hp9845ct_base_state::video_fill_buff(bool buff_idx)
-{
- unsigned char_idx = 0;
- unsigned iters = 0;
- address_space& prog_space = m_ppu->space(AS_PROGRAM);
-
- m_video_buff[ buff_idx ].full = false;
-
- while (1) {
- if ((m_video_mar & 0x1fff) > 0x1dff) {
- // CRT buffer ends at 0x7dff
- break;
- }
- // Get video word
- if (iters++ >= MAX_WORD_PER_ROW) {
- // Limit on accesses per row reached
- break;
- }
- m_video_word = prog_space.read_word(m_video_mar);
- if (m_video_load_mar) {
- // Load new address into MAR after start of a new frame or NWA instruction
- if (m_video_first_mar) {
- set_graphic_mode(BIT(m_video_word , 15), BIT(m_video_word , 14));
- m_video_first_mar = false;
- }
- set_video_mar(~m_video_word);
- m_video_load_mar = false;
- continue;
- } else {
- // Update counter for next word fetch
- set_video_mar(m_video_mar + 1);
- }
- // Parse video word
- if (m_video_word == 0x8020) {
- // End-of-line (EOL)
- // Fill rest of buffer with spaces
- memset(&m_video_buff[ buff_idx ].chars[ char_idx ] , 0x20 , 80 - char_idx);
- memset(&m_video_buff[ buff_idx ].attrs[ char_idx ] , 0 , 80 - char_idx);
- m_video_buff[ buff_idx ].full = true;
- break;
- } else if ((m_video_word & 0xc020) == 0x8000) {
- // New word address (NWA)
- m_video_load_mar = true;
- } else if ((m_video_word & 0xc000) == 0xc000) {
- // NOP
- } else {
- // fill line buffer
- m_video_buff[ buff_idx ].chars[ char_idx ] = (uint8_t)(m_video_word & 0xff);
- m_video_buff[ buff_idx ].attrs[ char_idx ] = (uint8_t)(m_video_word >> 8);
- char_idx++;
- if (char_idx == 80) {
- m_video_buff[ buff_idx ].full = true;
- break;
- }
- }
- }
-}
-
-void hp9845ct_base_state::draw_line(unsigned x0 , unsigned y0 , unsigned x1 , unsigned y1)
-{
- int dx, dy, sx, sy, x, y, err, e2;
-
- // draw line, vector generator uses Bresenham's algorithm
- x = x0;
- y = y0;
- dx = abs((int) (x1 - x));
- sx = x < x1 ? 1 : -1; // actually always 1 because of normalization
- dy = abs((int) (y1 - y));
- sy = y < y1 ? 1 : -1;
- err = (dx > dy ? dx : -dy) / 2;
-
- for(;;){
- plot(x, y, BIT(m_gv_line_type_mask, 15));
- update_line_pattern();
-
- if (x == x1 && y == y1) break;
-
- e2 = err;
- if (e2 > -dx) {
- err -= dy;
- x += sx;
- }
- if (e2 < dy) {
- err += dx;
- y += sy;
- }
- }
-}
-
-void hp9845ct_base_state::update_line_pattern()
-{
- // update line pattern
- m_gv_repeat_count++;
- if (m_gv_repeat_count > ((m_gv_line_type_area_fill >> 5) & 0xf)) {
- // Rotate m_gv_line_type_mask 1 bit to the left
- bool save_bit = BIT(m_gv_line_type_mask , 15);
- m_gv_line_type_mask = save_bit | (m_gv_line_type_mask << 1);
- m_gv_repeat_count = 0;
- }
-}
-
-void hp9845ct_base_state::pattern_fill(uint16_t x0 , uint16_t y0 , uint16_t x1 , uint16_t y1 , unsigned fill_idx)
-{
- uint16_t x,y,xmax,ymax;
- uint16_t pixel_mask, fill_mask;
-
- x = std::min(x0 , x1);
- xmax = std::max(x0 , x1);
- y = std::min(y0 , y1);
- ymax = std::max(y0 , y1);
-
- for (;y <= ymax; y++) {
- fill_mask = (m_area_fill[ fill_idx ] << (y % 4) * 4) & 0xf000;
- fill_mask |= (fill_mask >> 4) | (fill_mask >> 8) | (fill_mask >> 12);
- for (;x <= xmax; x++) {
- pixel_mask = (0x8000 >> (x % 16));
- plot(x , y , (pixel_mask & fill_mask) != 0);
- }
- }
-}
-
-uint16_t hp9845ct_base_state::get_gv_mem_addr(unsigned x , unsigned y)
-{
- return (uint16_t)((x + y * 35) & GVIDEO_ADDR_MASK);
-}
-
-int hp9845ct_base_state::get_wrapped_scanline(unsigned scanline)
-{
- // The 770's VTOTAL applies to 780, too.
- // The 780 hw generates a line clock (GVclk in Duell's schematics) that's suppressed
- // for lines in [485..524] range so that the total number of lines per frame counted
- // by this clock matches the total count of lines in 770 (i.e. 485).
- int wrapped_cursor_y = (int)scanline;
- if (wrapped_cursor_y >= GVIDEO_VPIXELS && wrapped_cursor_y < VIDEO_770_VTOTAL) {
- wrapped_cursor_y -= VIDEO_770_VTOTAL;
- }
-
- return wrapped_cursor_y;
-}
-
-void hp9845ct_base_state::render_lp_cursor(unsigned video_scanline , unsigned pen_idx)
-{
- int cursor_y_top = get_wrapped_scanline(m_gv_lp_cursor_y);
-
- bool yw;
- if (m_gv_lp_cursor_fs) {
- yw = true;
- } else {
- yw = (int)video_scanline >= cursor_y_top &&
- (int)video_scanline <= (cursor_y_top + 48);
- }
- if (!yw) {
- return;
- }
-
- if (!m_gv_lp_cursor_fs && m_gv_lp_cursor_x >= (VIDEO_TOT_HPIXELS + 24)) {
- return;
- }
-
- bool yc = video_scanline == (cursor_y_top + 24);
-
- const pen_t &pen = m_palette->pen(pen_idx);
- if (!yc) {
- if (m_gv_lp_cursor_x < VIDEO_TOT_HPIXELS) {
- m_bitmap.pix32(video_scanline , m_gv_lp_cursor_x) = pen;
- }
- } else if (m_gv_lp_cursor_fs) {
- for (unsigned x = 0; x < VIDEO_TOT_HPIXELS; x++) {
- m_bitmap.pix32(video_scanline , x) = pen;
- }
- } else {
- for (unsigned x = std::max(0 , (int)m_gv_lp_cursor_x - 24); x <= (m_gv_lp_cursor_x + 25) && x < VIDEO_TOT_HPIXELS; x++) {
- m_bitmap.pix32(video_scanline , x) = pen;
- }
- }
-}
-
-void hp9845ct_base_state::lp_r4_w(uint16_t data)
-{
- if (m_gv_lp_en) {
- switch (m_gv_lp_reg_cnt) {
- case 2:
- // LP Y cursor + threshold + interlace + vertical blank interrupt
- m_gv_lp_cursor_y = ((~data >> 6) & 0x1ff);
- m_gv_lp_fullbright = BIT(data, 1);
- m_gv_lp_threshold = BIT(data, 3);
- m_gv_lp_interlace = !BIT(data, 4);
- m_gv_lp_vbint = BIT(data, 5);
- LOG("LP Y cursor y = %d, threshold = %d, interlace = %d, vbint = %d\n",
- m_gv_lp_cursor_y, m_gv_lp_threshold, m_gv_lp_interlace, m_gv_lp_vbint);
- m_gv_lp_reg_cnt--;
- break;
-
- case 3:
- // LP X cursor + cursor type
- m_gv_lp_cursor_x = ((data >> 6) & 0x3ff) + 1;
- m_gv_lp_cursor_fs = !BIT(data, 0);
- LOG("LP X cursor x = %d, fs = %d\n", m_gv_lp_cursor_x, m_gv_lp_cursor_fs);
- m_gv_lp_reg_cnt--;
- break;
-
- default:
- logerror("Writing to unmapped LP register %u\n" , m_gv_lp_reg_cnt);
- }
- }
-}
-
-uint16_t hp9845ct_base_state::lp_r4_r()
-{
- uint16_t res = 0;
-
- if (m_gv_lp_en) {
- switch (m_gv_lp_reg_cnt) {
- case 4:
- // YLO
- res = m_gv_lp_data[ 2 ];
- m_gv_lp_reg_cnt--;
- m_gv_lp_status = false;
- m_gv_lp_1sthit = false;
- update_graphic_bits();
- break;
-
- case 5:
- // XLEFT
- res = m_gv_lp_data[ 1 ];
- m_gv_lp_reg_cnt--;
- break;
-
- case 6:
- // YHI
- res = m_gv_lp_data[ 0 ];
- if (!m_gv_lp_vblank) {
- BIT_SET(res, 12);
- }
- if (m_gv_lp_sw) {
- BIT_SET(res, 14);
- }
- if (m_gv_lp_1sthit) {
- BIT_SET(res, 15);
- }
- m_gv_lp_reg_cnt--;
- break;
-
- default:
- logerror("Reading from unmapped LP register %u\n" , m_gv_lp_reg_cnt);
- }
- }
- return res;
-}
-
-void hp9845ct_base_state::lp_r5_w(uint16_t data)
-{
- m_gv_lp_reg_cnt = data & 7;
- m_gv_lp_en = (data & 0x700) == 0x400; // enables writes on R4 to set LP data (actually FB bit), also enables LP command processing and LP IRQs
- m_gv_lp_int_en = (data & 0x500) == 0x400;
- m_gv_lp_selftest = m_gv_lp_en && m_gv_lp_reg_cnt == 7;
- update_graphic_bits();
-}
-
-bool hp9845ct_base_state::lp_segment_intersect(unsigned yline) const
-{
- int xp = m_gv_lp_x;
- int yp = m_gv_lp_y;
- int xc = (int)m_gv_lp_cursor_x + 1 - LP_XOFFSET;
-
- unsigned h = (unsigned)abs((int)yline - yp);
-
- if (h > LP_FOV) {
- return false;
- }
-
- int dt = (int)sqrt(LP_FOV * LP_FOV - h * h);
- int ex = xp - dt;
- int fx = xp + dt;
-
- // Consider [xc..xc+24] segment (i.e. the right-hand side of cursor interlace window)
- return fx >= xc && ex <= (xc + 24);
-}
-
-void hp9845ct_base_state::compute_lp_data()
-{
- // get LP hit data, returns three words for cmd=6 and one word for cmd=4
- // actually simulating the 9845 lightpen is a bit more complex, since YHI, XLEFT and YLO
- // depend on an circular field of view, moving on the screen
- // bit 0..10 x bzw y
- // bit 11 = IRQ (YHI + XLEFT + YLO)
- // bit 12 = vblank (YHI)
- // bit 13 = xwindow (YHI + XLEFT + YLO) = X is in [xcursor-24, xcursor+24] and Y in [ycursor-8,ycursor+8]
- // bit 14 = sw (YHI) bzw. ywindow (XLEFT + YLO)
- // bit 15 = 1st hit (YHI) = valid hit
-
- bool xwindow[ 3 ] = { false , false , false };
- bool ywindow[ 3 ] = { false , false , false };
- // hit coordinates
- uint16_t yhi = 0;
- uint16_t xleft = 0;
- uint16_t yleft = 0;
- uint16_t ylo = 0;
- uint16_t xp = m_gv_lp_x; // light gun pointer
- uint16_t yp = m_gv_lp_y;
- int yc = get_wrapped_scanline(m_gv_lp_cursor_y) + 24;
-
- if (m_gv_lp_selftest) {
- constexpr int offset = 57 - VIDEO_770_ALPHA_L_LIM;
- xwindow[ 0 ] = xwindow[ 1 ] = xwindow[ 2 ] = true;
- ywindow[ 0 ] = ywindow[ 1 ] = ywindow[ 2 ] = true;
- yhi = m_gv_lp_cursor_y + 16; // YHI
- xleft = m_gv_lp_cursor_x + offset; // XLEFT
- yleft = yhi;
- ylo = m_gv_lp_cursor_y + 32; // YLO
- } else {
- // Hit in a cursor-only part.
- bool yhi_hit = false;
- uint16_t y_top = std::max(0 , (int)yp - (int)LP_FOV);
-
- // XLEFT: x coordinate of 1st hit in the frame or hit on cursor line
- unsigned dy = abs((int)yp - yc);
- if (dy <= LP_FOV) {
- // Hit on horizontal cursor line
- xleft = (uint16_t)std::max(0 , (int)xp - (int)sqrt(LP_FOV * LP_FOV - dy * dy));
- yleft = yc;
- } else {
- // 1st hit in the frame
- dy = abs((int)yp - (int)y_top);
- xleft = (uint16_t)std::max(0 , (int)xp - (int)sqrt(LP_FOV * LP_FOV - dy * dy));
- yleft = y_top;
- }
- xleft += LP_XOFFSET;
-
- if (m_gv_lp_interlace) {
- // **** Interlaced mode ****
- unsigned ywd_top = (unsigned)std::max(yc - 24 , 0);
- unsigned ywd_bot = std::min((unsigned)(GVIDEO_VPIXELS - 1) , (unsigned)(yc + 24));
- unsigned even_odd = (unsigned)m_screen->frame_number() & 1;
-
- // Scan the cursor window [yc-24..yc+24]
- // Only consider each other line. LSB of frame number selects either even-numbered
- // (0) or odd-numbered lines (1).
- for (unsigned line = ywd_top; line <= ywd_bot; line++) {
- if ((line & 1) == even_odd) {
- // YHI: y coordinate of 1st hit in the frame or 1st hit in cursor-only part
- bool curs_hit = lp_segment_intersect(line);
- if (!yhi_hit && curs_hit) {
- yhi = line;
- yhi_hit = true;
- }
- // YLO: y coordinate of last hit in cursor-only part
- if (curs_hit) {
- ylo = line;
- }
- }
- }
- }
-
- if (!m_gv_lp_interlace || !yhi_hit) {
- // **** Non-interlaced mode ****
- // YHI: y coordinate of 1st hit in the frame
- yhi = y_top;
-
- // YLO: y coordinate of last hit in the frame
- ylo = std::min((unsigned)(GVIDEO_VPIXELS - 1) , yp + LP_FOV);
- }
-
- xwindow[ 0 ] = yhi_hit;
- xwindow[ 1 ] = yhi_hit && yleft >= yhi;
- xwindow[ 2 ] = yhi_hit;
-
- ywindow[ 1 ] = yleft == yc;
- ywindow[ 2 ] = yleft == yc && ylo >= yleft;
- }
- m_gv_next_lp_data[ 0 ] = ~yhi & 0x1ff; // YHI
- m_gv_next_lp_data[ 1 ] = ~xleft & 0x3ff; // XLEFT
- m_gv_next_lp_data[ 2 ] = ~ylo & 0x1ff; // YLO
-
- if (!xwindow[ 0 ]) {
- BIT_SET(m_gv_next_lp_data[ 0 ], 13);
- }
- if (!xwindow[ 1 ]) {
- BIT_SET(m_gv_next_lp_data[ 1 ], 13);
- }
- if (!xwindow[ 2 ]) {
- BIT_SET(m_gv_next_lp_data[ 2 ], 13);
- }
- if (!ywindow[ 1 ]) {
- BIT_SET(m_gv_next_lp_data[ 1 ], 14);
- }
- if (!ywindow[ 2 ]) {
- BIT_SET(m_gv_next_lp_data[ 2 ], 14);
- }
-
- m_gv_next_lp_scanline[ 0 ] = yhi;
- m_gv_next_lp_scanline[ 1 ] = yleft;
- m_gv_next_lp_scanline[ 2 ] = ylo;
-
- m_gv_lp_hit_lt192 = yhi < 192;
- LOG("LP data %d %d %d %d (%u;%d) (%u;%u) %u %u %u %04x %04x %04x\n" , m_gv_lp_selftest , m_gv_lp_interlace , m_gv_lp_sw , m_gv_lp_hit_lt192 , m_gv_lp_cursor_x , yc , m_gv_lp_x , m_gv_lp_y , yhi , xleft , ylo , m_gv_next_lp_data[ 0 ] , m_gv_next_lp_data[ 1 ] , m_gv_next_lp_data[ 2 ]);
-}
-
-void hp9845ct_base_state::lp_scanline_update(unsigned video_scanline)
-{
- if (video_scanline == 0) {
- compute_lp_data();
- }
-
- if (video_scanline == 256 && !m_gv_lp_status && m_gv_lp_hit_lt192) {
- LOG("Hit < 192 @%d\n" , m_screen->vpos());
- m_gv_lp_status = true;
- m_gv_lp_int_256 = true;
- update_graphic_bits();
- }
-
- if (video_scanline == 456) {
- // VB interrupt
- if (m_gv_lp_vbint || !m_gv_lp_int_256) {
- m_gv_lp_status = true;
- }
- m_gv_lp_int_256 = false;
- update_graphic_bits();
- }
-
- for (unsigned i = 0; i < 3; i++) {
- if (m_gv_next_lp_scanline[ i ] == video_scanline) {
- m_gv_lp_data[ i ] = m_gv_next_lp_data[ i ];
- if (!m_gv_lp_status) {
- BIT_SET(m_gv_lp_data[ i ], 11);
- }
- m_gv_lp_1sthit = true;
- }
- }
-}
-
-const uint16_t hp9845ct_base_state::m_line_type[] = {
- 0xffff, 0xaaaa, 0xff00, 0xfff0, 0xfffa, 0xfff6, 0xffb6, 0x0000
-};
-
-const uint16_t hp9845ct_base_state::m_area_fill[] = {
- 0xffff, 0xefff, 0xefbf, 0xefaf, 0xafaf, 0xadaf, 0xada7, 0xada5,
- 0xa5a5, 0xa4a5, 0xa4a1, 0xa4a0, 0xa0a0, 0x80a0, 0x8020, 0x8000
-};
-
-// ***************
-// hp9845c_state
-// ***************
-class hp9845c_state : public hp9845ct_base_state
-{
-public:
- hp9845c_state(const machine_config &mconfig, device_type type, const char *tag);
-
- void hp9845c(machine_config &config);
-
-private:
- virtual void machine_start() override;
- virtual void machine_reset() override;
-
- virtual DECLARE_READ16_MEMBER(graphic_r) override;
- virtual DECLARE_WRITE16_MEMBER(graphic_w) override;
-
- TIMER_DEVICE_CALLBACK_MEMBER(scanline_timer);
-
- virtual void set_graphic_mode(bool graphic , bool alpha) override;
- void video_render_buff(unsigned video_scanline , unsigned line_in_row, bool buff_idx);
- void graphic_video_render(unsigned video_scanline);
- virtual void plot(uint16_t x, uint16_t y, bool draw_erase) override;
-
- void check_io_counter_restore();
- void advance_io_counter();
- virtual void advance_gv_fsm(bool ds , bool trigger) override;
- virtual void update_graphic_bits() override;
-
- virtual void update_gcursor() override;
-
- // Palette indexes
- static constexpr unsigned pen_graphic(unsigned rgb) { return rgb; }
- static constexpr unsigned pen_alpha(unsigned rgb) { return 8 + rgb; }
- static constexpr unsigned pen_cursor(unsigned rgb) { return 16 + rgb; }
-
- // Optional character generator
- required_region_ptr<uint8_t> m_optional_chargen;
-
- std::vector<uint16_t> m_graphic_mem[ 3 ];
- uint16_t m_gv_music_memory;
- uint8_t m_gv_cursor_color;
- uint8_t m_gv_plane;
- bool m_gv_plane_wrap;
- bool m_gv_lp_int_latched;
- bool m_gv_sk_int_latched;
-};
-
-hp9845c_state::hp9845c_state(const machine_config &mconfig, device_type type, const char *tag)
- : hp9845ct_base_state(mconfig , type , tag),
- m_optional_chargen(*this , "optional_chargen")
-{
-}
-
-void hp9845c_state::machine_start()
-{
- // Common part first
- hp9845ct_base_state::machine_start();
-
- m_graphic_mem[ 0 ].resize(GVIDEO_MEM_SIZE);
- m_graphic_mem[ 1 ].resize(GVIDEO_MEM_SIZE);
- m_graphic_mem[ 2 ].resize(GVIDEO_MEM_SIZE);
-
- // initialize palette
- // graphics colors
- m_palette->set_pen_color(0, 0x00, 0x00, 0x00); // black
- m_palette->set_pen_color(1, I_GR, 0x00, 0x00); // red
- m_palette->set_pen_color(2, 0x00, I_GR, 0x00); // green
- m_palette->set_pen_color(3, I_GR, I_GR, 0x00); // yellow
- m_palette->set_pen_color(4, 0x00, 0x00, I_GR); // blue
- m_palette->set_pen_color(5, I_GR, 0x00, I_GR); // magenta
- m_palette->set_pen_color(6, 0x00, I_GR, I_GR); // cyan
- m_palette->set_pen_color(7, I_GR, I_GR, I_GR); // white
-
- // alpha colors
- m_palette->set_pen_color(8, 0x00, 0x00, 0x00); // black
- m_palette->set_pen_color(9, I_AL, 0x00, 0x00); // red
- m_palette->set_pen_color(10, 0x00, I_AL, 0x00); // green
- m_palette->set_pen_color(11, I_AL, I_AL, 0x00); // yellow
- m_palette->set_pen_color(12, 0x00, 0x00, I_AL); // blue
- m_palette->set_pen_color(13, I_AL, 0x00, I_AL); // magenta
- m_palette->set_pen_color(14, 0x00, I_AL, I_AL); // cyan
- m_palette->set_pen_color(15, I_AL, I_AL, I_AL); // white
-
- // cursor colors
- m_palette->set_pen_color(16, 0x80, 0x80, 0x80); // grey
- m_palette->set_pen_color(17, I_CU, 0x00, 0x00); // red
- m_palette->set_pen_color(18, 0x00, I_CU, 0x00); // green
- m_palette->set_pen_color(19, I_CU, I_CU, 0x00); // yellow
- m_palette->set_pen_color(20, 0x00, 0x00, I_CU); // blue
- m_palette->set_pen_color(21, I_CU, 0x00, I_CU); // magenta
- m_palette->set_pen_color(22, 0x00, I_CU, I_CU); // cyan
- m_palette->set_pen_color(23, I_CU, I_CU, I_CU); // white
-}
-
-void hp9845c_state::machine_reset()
-{
- // Common part first
- hp9845ct_base_state::machine_reset();
-
- set_video_mar(0);
-
- // red -> plane #1, green -> plane #2, blue -> plane #3
- m_gv_music_memory = 0x1 | (0x2 << 3) | (0x4 << 6);
- // TODO: correct?
- m_gv_cursor_color = 7;
- m_gv_plane = 0;
- m_gv_plane_wrap = false;
- m_gv_lp_int_latched = false;
- m_gv_sk_int_latched = false;
-}
-
-READ16_MEMBER(hp9845c_state::graphic_r)
-{
- uint16_t res = 0;
-
- switch (offset) {
- case 2:
- // R6: data register with DMA TC
- m_gv_dma_en = false;
- // Intentional fall-through
-
- case 0:
- // R4: data register
- if (m_gv_lp_en) {
- res = lp_r4_r();
- } else if (m_gv_sk_int_latched) {
- res = m_gv_softkey;
- m_gv_sk_status = false;
- } else {
- res = m_gv_data_r;
- }
- advance_gv_fsm(true , false);
- update_graphic_bits();
- break;
-
- case 1:
- // R5: status register
- if (m_gv_int_en) {
- BIT_SET(res, 7);
- }
- if (m_gv_dma_en) {
- BIT_SET(res, 6);
- }
- if (m_gv_lp_int_latched) {
- BIT_SET(res, 0); // Lightpen service request
- }
- if (m_gv_sk_int_latched) {
- BIT_SET(res, 1); // Softkey service request
- }
- // TODO: check! Should it be 10 instead?
- BIT_SET(res, 11); // ID
- break;
-
- case 3:
- // R7: not mapped
- break;
- }
-
- LOG("rd gv R%u = %04x\n", 4 + offset , res);
-
- return res;
-}
-
-WRITE16_MEMBER(hp9845c_state::graphic_w)
-{
- LOG("wr gv R%u = %04x\n", 4 + offset , data);
-
- switch (offset) {
- case 0:
- // R4: data register
- m_gv_data_w = data;
- advance_gv_fsm(true , false);
- lp_r4_w(data);
- break;
-
- case 1:
- // R5: command register
- m_gv_cmd = (uint8_t)(data & 0xf);
- m_gv_dma_en = BIT(data , 6) != 0;
- m_gv_int_en = BIT(data , 7) != 0;
- m_gv_gr_en = BIT(data , 8); // enables graphics controller & vector generator command processing and IRQs
- m_gv_sk_en = BIT(data , 9); // enables reads on R4 to return SK keycode, also enables SK IRQs
- m_gv_opt_en = BIT(data , 11); // not really used
- m_gv_dsa_en = BIT(data , 12); // for factory use only (unknown)
- if (BIT(data, 5)) {
- m_gv_fsm_state = GV_STAT_RESET; // command/reset state machine
- }
- advance_gv_fsm(false , false);
- lp_r5_w(data);
- update_graphic_bits();
- break;
-
- case 2:
- // R6: data register with DMA TC
- m_gv_dma_en = false;
- m_gv_data_w = data;
- advance_gv_fsm(true , false);
- lp_r4_w(data);
- break;
-
- case 3:
- // R7: trigger
- advance_gv_fsm(false , true);
- break;
- }
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER(hp9845c_state::scanline_timer)
-{
- unsigned video_scanline = param;
-
- if (video_scanline >= VIDEO_770_VBEND && video_scanline < VIDEO_770_VBSTART) {
- if (m_graphic_sel) {
- graphic_video_render(video_scanline - VIDEO_770_VBEND);
- }
- unsigned row = (video_scanline - VIDEO_770_VBEND) / VIDEO_CHAR_HEIGHT;
- unsigned line_in_row = (video_scanline - VIDEO_770_VBEND) - row * VIDEO_CHAR_HEIGHT;
-
- 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(video_scanline , line_in_row , m_video_buff_idx);
- // Lightpen cursor
- if (m_graphic_sel) {
- render_lp_cursor(video_scanline - VIDEO_770_VBEND , pen_cursor(7));
- }
- }
- lp_scanline_update(video_scanline - VIDEO_770_VBEND);
-}
-
-void hp9845c_state::set_graphic_mode(bool graphic , bool alpha)
-{
- m_graphic_sel = graphic;
- m_alpha_sel = alpha;
-}
-
-void hp9845c_state::video_render_buff(unsigned video_scanline , unsigned line_in_row, bool buff_idx)
-{
- if (!m_video_buff[ buff_idx ].full) {
- m_video_blanked = true;
- }
-
- const pen_t *pen = m_palette->pens();
-
- if (m_video_blanked || !m_alpha_sel) {
- // Blank scanline
- for (unsigned i = 0; i < VIDEO_770_ALPHA_L_LIM; i++) {
- m_bitmap.pix32(video_scanline , i) = pen[ pen_alpha(0) ];
- }
- if (!m_graphic_sel) {
- for (unsigned i = VIDEO_770_ALPHA_L_LIM; i < VIDEO_770_ALPHA_R_LIM; i++) {
- m_bitmap.pix32(video_scanline , i) = pen[ pen_alpha(0) ];
- }
- }
- for (unsigned i = VIDEO_770_ALPHA_R_LIM; i < VIDEO_TOT_HPIXELS; i++) {
- m_bitmap.pix32(video_scanline , i) = pen[ pen_alpha(0) ];
- }
- } else {
- bool cursor_line = line_in_row == 12;
- bool ul_line = line_in_row == 14;
- unsigned video_frame = (unsigned)m_screen->frame_number();
- bool cursor_blink = BIT(video_frame , 4);
- bool char_blink = !BIT(video_frame , 4);
-
- for (unsigned i = 0; i < 80; i++) {
- uint8_t charcode = m_video_buff[ buff_idx ].chars[ i ] & 0x7f;
- uint8_t attrs = m_video_buff[ buff_idx ].attrs[ i ];
- uint16_t chrgen_addr = ((uint16_t)(charcode ^ 0x7f) << 4) | line_in_row;
- uint16_t pixels;
- uint8_t color = (attrs >> 4) & 7;
-
- if (ul_line && BIT(attrs , 3)) {
- // Color of underline: same as character
- pixels = ~0;
- } else if (cursor_line && cursor_blink && BIT(attrs , 0)) {
- // Color of cursor: white
- color = 7;
- pixels = ~0;
- } else if (char_blink && BIT(attrs , 2)) {
- pixels = 0;
- } else if (BIT(m_video_buff[ buff_idx ].chars[ i ] , 7)) {
- // 98770A has hw support to fill the 1st and the 9th column of character matrix
- // with pixels in 2nd and 8th columns, respectively. This feature is used in
- // 98780A to make horizontal lines of line-drawing characters appear continuous
- // (see hp9845t_state::video_render_buff).
- // Apparently, though, HP did not use this feature at all in real
- // machines (i.e. horizontal lines are broken by gaps)
- pixels = (uint16_t)(m_optional_chargen[ chrgen_addr ] & 0x7f) << 1;
- } else {
- pixels = (uint16_t)(m_chargen[ chrgen_addr ] & 0x7f) << 1;
- }
-
- if (BIT(attrs , 1)) {
- pixels = ~pixels;
- }
-
- for (unsigned j = 0; j < 9; j++) {
- bool pixel = (pixels & (1U << j)) != 0;
- unsigned x = i * 9 + j;
-
- if (m_graphic_sel && x >= VIDEO_770_ALPHA_L_LIM && x < VIDEO_770_ALPHA_R_LIM) {
- // alpha overlays graphics (non-dominating)
- if (pixel) {
- m_bitmap.pix32(video_scanline , x) = pen[ pen_alpha(color) ];
- }
- } else {
- // Graphics disabled or alpha-only zone
- m_bitmap.pix32(video_scanline , x) = pen[ pixel ? pen_alpha(color) : pen_alpha(0) ];
- }
- }
- }
- }
-}
-
-void hp9845c_state::graphic_video_render(unsigned video_scanline)
-{
- // video_scanline is 0-based, i.e. the topmost visible line of graphic screen is 0
- const pen_t *pen = m_palette->pens();
- bool yc, yw;
- uint16_t word0, word1, word2;
- uint8_t pen0, pen1, pen2;
-
- // apply music memory
- pen0 = (m_gv_music_memory & 0x001) | ((m_gv_music_memory & 0x008) >> 2) | ((m_gv_music_memory & 0x040) >> 4);
- pen1 = ((m_gv_music_memory & 0x002) >> 1) | ((m_gv_music_memory & 0x010) >> 3) | ((m_gv_music_memory & 0x080) >> 5);
- pen2 = ((m_gv_music_memory & 0x004) >> 2) | ((m_gv_music_memory & 0x020) >> 4) | ((m_gv_music_memory & 0x100) >> 6);
-
- if (m_gv_cursor_fs) {
- // Full-screen cursor
- yw = false;
- yc = video_scanline == m_gv_cursor_y;
- } else if (m_gv_cursor_gc) {
- // 15 x 15 crosshair
- int cursor_y_top = get_wrapped_scanline(m_gv_cursor_y);
- int int_scanline = (int)video_scanline;
- yw = (int_scanline >= (cursor_y_top + 1) && int_scanline <= (cursor_y_top + 6)) ||
- (int_scanline >= (cursor_y_top + 10) && int_scanline <= (cursor_y_top + 15));
- yc = int_scanline == cursor_y_top + 8;
- } else {
- // 9-pixel blinking line
- int cursor_y_top = get_wrapped_scanline(m_gv_cursor_y);
- int int_scanline = (int)video_scanline;
- yw = false;
- yc = int_scanline == cursor_y_top + 8;
- }
-
- unsigned mem_idx = get_gv_mem_addr(0 , video_scanline);
- for (unsigned i = 0; i < GVIDEO_HPIXELS; i += 16) {
- word0 = m_graphic_mem[ 0 ][ mem_idx ];
- word1 = m_graphic_mem[ 1 ][ mem_idx ];
- word2 = m_graphic_mem[ 2 ][ mem_idx ];
- mem_idx++;
- unsigned x = i;
- for (uint16_t mask = 0x8000; mask != 0; mask >>= 1) {
- bool cursor = false;
- unsigned pixel;
-
- if (m_gv_cursor_fs) {
- // Full-screen cursor
- cursor = yc || (x + 111) == m_gv_cursor_x;
- } else if (m_gv_cursor_gc) {
- bool xc = (x + 103) == m_gv_cursor_x;
- bool xw = ((x + 96) <= m_gv_cursor_x && (x + 101) >= m_gv_cursor_x) ||
- ((x + 105) <= m_gv_cursor_x && (x + 110) >= m_gv_cursor_x);
-
- // 15 x 15 crosshair
- cursor = (yc && xw) || (yw && xc);
- } else if (BIT(m_screen->frame_number() , 3)) {
- // 9-pixel blinking line
- cursor = yc && (x + 107) >= m_gv_cursor_x && (x + 99) <= m_gv_cursor_x;
- }
- if (cursor) {
- // Cursor
- pixel = pen_cursor(m_gv_cursor_color);
- } else {
- // Normal pixel
- pixel = pen_graphic(((word0 & mask) ? pen0 : 0) | ((word1 & mask) ? pen1 : 0) | ((word2 & mask) ? pen2 : 0));
- }
- m_bitmap.pix32(video_scanline , VIDEO_770_ALPHA_L_LIM + x++) = pen[ pixel ];
- }
- }
-}
-
-void hp9845c_state::plot(uint16_t x, uint16_t y, bool draw_erase)
-{
- uint16_t addr, pixel_mask;
- bool do_draw, do_erase, dominance;
-
- pixel_mask = 0x8000 >> (x & 0xf);
-
- addr = get_gv_mem_addr(x >> 4 , y);
- dominance = BIT(m_gv_memory_control, 6);
- if (BIT(m_gv_memory_control, 0)) {
- do_erase = dominance;
- do_draw = draw_erase;
- if (!BIT(m_gv_memory_control, 3) && draw_erase) {
- do_draw = false;
- do_erase = true;
- }
- if (do_draw)
- m_graphic_mem[0][ addr ] |= pixel_mask;
- else if (do_erase)
- m_graphic_mem[0][ addr ] &= ~pixel_mask;
- }
- if (BIT(m_gv_memory_control, 1)) {
- do_erase = dominance;
- do_draw = draw_erase;
- if (!BIT(m_gv_memory_control, 4) && draw_erase) {
- do_draw = false;
- do_erase = true;
- }
- if (do_draw)
- m_graphic_mem[1][ addr ] |= pixel_mask;
- else if (do_erase)
- m_graphic_mem[1][ addr ] &= ~pixel_mask;
- }
- if (BIT(m_gv_memory_control, 2)) {
- do_erase = dominance;
- do_draw = draw_erase;
- if (!BIT(m_gv_memory_control, 5) && draw_erase) {
- do_draw = false;
- do_erase = true;
- }
- if (do_draw)
- m_graphic_mem[2][ addr ] |= pixel_mask;
- else if (do_erase)
- m_graphic_mem[2][ addr ] &= ~pixel_mask;
- }
-}
-
-void hp9845c_state::check_io_counter_restore()
-{
- if (m_gv_last_cmd != m_gv_cmd) {
- // restore memory counter
- m_gv_io_counter = get_gv_mem_addr(m_gv_word_x_position , m_gv_word_y_position);
- // no auto-increment when switching commands
- if (m_gv_plane_wrap) {
- m_gv_plane = 2;
- } else if (m_gv_plane > 0) {
- m_gv_plane--;
- }
- m_gv_last_cmd = m_gv_cmd;
- }
-}
-
-void hp9845c_state::advance_io_counter()
-{
- m_gv_plane++;
- if (m_gv_plane > 2) {
- if (m_gv_io_counter < GVIDEO_ADDR_MASK) {
- m_gv_plane = 0;
- m_gv_io_counter++;
- } else {
- m_gv_plane = 2;
- }
- m_gv_plane_wrap = true;
- }
-}
-
-void hp9845c_state::advance_gv_fsm(bool ds , bool trigger)
-{
- if (!m_gv_gr_en) {
- return;
- }
-
- bool get_out = false;
-
- attotime time_mem_av;
-
- do {
- // U73 on vector generator board
- bool act_trig = trigger || m_gv_int_en || !BIT(m_gv_cmd , 0);
-
- switch (m_gv_fsm_state) {
- case GV_STAT_WAIT_DS_0:
- // inital state (same as GV_STAT_RESET), command received
- if (m_gv_cmd == 0x1) {
- // read words command
- check_io_counter_restore();
- LOG("read words, last = %x\n", m_gv_last_cmd);
- m_gv_fsm_state = GV_STAT_WAIT_MEM_0; // -> read stream
- m_gv_last_cmd = m_gv_cmd;
- } else if (ds) {
- if ((m_gv_cmd == 0x0) || (m_gv_cmd == 0x2)) {
- // write words & clear/set words commands
- check_io_counter_restore();
- if (m_gv_cmd == 0x2) LOG("clear/set words, last = %x\n", m_gv_last_cmd);
- else LOG("write words, last = %x\n", m_gv_last_cmd);
- m_gv_fsm_state = GV_STAT_WAIT_TRIG_1; // -> write stream
- } else {
- // any other command
- m_gv_fsm_state = GV_STAT_WAIT_TRIG_0; // -> wait for trigger
- }
- m_gv_last_cmd = m_gv_cmd;
- } else {
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_TRIG_0:
- // process data on R4 or R6
- if (act_trig) {
- switch (m_gv_cmd) {
- case 0x8: // load X I/O address
- m_gv_word_x_position = ~m_gv_data_w & 0x3f; // 0..34
- LOG("load X I/O adress = %04x\n", m_gv_word_x_position);
- m_gv_io_counter = get_gv_mem_addr(m_gv_word_x_position , m_gv_word_y_position);
- m_gv_plane = 0;
- m_gv_plane_wrap = false;
- break;
- case 0x9: // load Y I/O address
- m_gv_word_y_position = ~m_gv_data_w & 0x1ff; // 0..454
- LOG("load Y I/O adress = %04x\n", m_gv_word_y_position);
- m_gv_io_counter = get_gv_mem_addr(m_gv_word_x_position , m_gv_word_y_position);
- m_gv_plane = 0;
- m_gv_plane_wrap = false;
- break;
- case 0xa: // load memory control
- m_gv_memory_control = m_gv_data_w & 0x7f;
- LOG("load memory control = %04x\n", m_gv_memory_control);
- break;
- case 0xb: // set line type/area fill
- m_gv_line_type_area_fill = m_gv_data_w & 0x1ff;
- if (BIT(m_gv_line_type_area_fill, 4)) {
- m_gv_line_type_mask = m_line_type[ m_gv_line_type_area_fill & 0x7 ];
- m_gv_repeat_count = 0;
- }
- LOG("set line type = %04x\n", m_gv_line_type_area_fill);
- break;
- case 0xc: // load color mask
- m_gv_music_memory = m_gv_data_w & 0x1ff;
- LOG("load color mask = %04x\n", m_gv_music_memory);
- break;
- case 0xd: // load end points
- m_gv_ypt = ~m_gv_data_w & 0x1ff;
- LOG("load end points y = %d\n", m_gv_ypt);
- break;
- case 0xe: // Y cursor position & color
- m_gv_lyc = m_gv_data_w;
- break;
- case 0xf: // X cursor position & type
- m_gv_lxc = m_gv_data_w;
- break;
- default:
- logerror("unknown 98770A command = %d, parm = 0x%04x\n", m_gv_cmd, m_gv_data_w);
- }
- if (m_gv_cmd == 0xd) {
- m_gv_fsm_state = GV_STAT_WAIT_DS_2; // -> get second data word
- } else {
- get_out = true;
- m_gv_fsm_state = GV_STAT_WAIT_DS_0; // -> done
- }
- } else {
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_MEM_0:
- // process data during read transfer
- 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_plane ][ m_gv_io_counter ];
- LOG("read words @%04x = %04x, plane #%d\n" , m_gv_io_counter , m_gv_data_r, m_gv_plane + 1);
- advance_io_counter();
- m_gv_fsm_state = GV_STAT_WAIT_DS_1; // -> proceed with read stream
- } else {
- m_gv_timer->adjust(time_mem_av);
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_DS_1:
- // wait for data word to be read
- if (ds) {
- // -- next word
- m_gv_fsm_state = GV_STAT_WAIT_MEM_0; // -> process data word
- } else {
- // -- done
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_DS_2:
- // wait for data word to be written
- if (ds) {
- // -- next word
- m_gv_fsm_state = GV_STAT_WAIT_TRIG_1; // -> process data word
- } else {
- // done
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_TRIG_1:
- // process multi-word parameters & data during write transfer
- if (act_trig) {
- if (m_gv_cmd == 0xd) {
- // load endpoints command
- m_gv_xpt = ~m_gv_data_w & 0x3ff;
- if (BIT(m_gv_data_w, 10)) {
- // draw vector
- LOG("load end points x = %d (draw)\n", m_gv_xpt);
- m_gv_fsm_state = GV_STAT_WAIT_MEM_2; // -> proceed with draw vector
- } else {
- LOG("load end points x = %d (move)\n", m_gv_xpt);
- m_gv_last_xpt = m_gv_xpt;
- m_gv_last_ypt = m_gv_ypt;
- m_gv_fsm_state = GV_STAT_WAIT_DS_0; // -> proceed with next word pair
- }
- } else if (m_gv_cmd == 0x2) {
- // clear/set words command
- m_gv_data_w = BIT(m_gv_memory_control, m_gv_plane + 3) ? 0xffff : 0;
- m_gv_fsm_state = GV_STAT_WAIT_MEM_1; // -> proceed with next word
- } else if (m_gv_cmd == 0x0) {
- // write words command
- m_gv_fsm_state = GV_STAT_WAIT_MEM_1; // -> proceed with next word
- }
- } else {
- // done
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_MEM_1:
- // -- transfer from bus to graphics memory to bus within write transfer
- time_mem_av = time_to_gv_mem_availability();
- if (time_mem_av.is_zero()) {
- // Write a full word to graphic memory
- LOG("write words @%04x = %04x, plane #%d\n" , m_gv_io_counter , m_gv_data_w, m_gv_plane + 1);
- if ((m_gv_cmd == 0x0) || BIT(m_gv_memory_control, m_gv_plane)) {
- m_graphic_mem[ m_gv_plane ][ m_gv_io_counter ] = m_gv_data_w;
- }
- advance_io_counter();
- m_gv_fsm_state = GV_STAT_WAIT_DS_2; // -> proceed with write stream
- } else {
- m_gv_timer->adjust(time_mem_av);
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_MEM_2:
- // vector generator
- time_mem_av = time_to_gv_mem_availability();
- if (time_mem_av.is_zero()) {
- if (BIT (m_gv_line_type_area_fill, 4)) {
- unsigned x0;
- unsigned x1;
- unsigned y0;
- unsigned y1;
-
- // vector generator uses normalization
- if (m_gv_xpt > m_gv_last_xpt) {
- x0 = m_gv_last_xpt;
- y0 = m_gv_last_ypt;
- x1 = m_gv_xpt;
- y1 = m_gv_ypt;
- } else {
- x0 = m_gv_xpt;
- y0 = m_gv_ypt;
- x1 = m_gv_last_xpt;
- y1 = m_gv_last_ypt;
- }
- draw_line(x0 , y0 , x1 , y1);
- } else {
- // fill area with pattern
- LOG("area fill (%d,%d) -> (%d,%d) pattern=%04x\n", m_gv_last_xpt, m_gv_last_ypt, m_gv_xpt, m_gv_ypt, m_gv_line_type_area_fill);
-
- pattern_fill(m_gv_xpt , m_gv_ypt , m_gv_last_xpt , m_gv_last_ypt , m_gv_line_type_area_fill & 0xf);
- }
- m_gv_last_xpt = m_gv_xpt;
- m_gv_last_ypt = m_gv_ypt;
- m_gv_fsm_state = GV_STAT_WAIT_DS_0; // -> proceed with next word pair
- } else {
- m_gv_timer->adjust(time_mem_av);
- 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 hp9845c_state::update_graphic_bits()
-{
- bool lp_int = m_gv_lp_int_en && m_gv_lp_status;
- bool sk_int = m_gv_sk_status && m_gv_sk_en;
-
- if (lp_int && !m_gv_sk_int_latched) {
- m_gv_lp_int_latched = true;
- } else if (sk_int && !m_gv_lp_int_latched) {
- m_gv_sk_int_latched = true;
- } else if (!lp_int && !sk_int) {
- m_gv_lp_int_latched = false;
- m_gv_sk_int_latched = false;
- }
-
- bool gv_ready = m_gv_lp_int_latched || m_gv_sk_int_latched;
-
- if (m_gv_gr_en && !gv_ready) {
- gv_ready = m_gv_fsm_state == GV_STAT_WAIT_DS_0 ||
- m_gv_fsm_state == GV_STAT_WAIT_TRIG_0 ||
- m_gv_fsm_state == GV_STAT_WAIT_DS_1 ||
- m_gv_fsm_state == GV_STAT_WAIT_DS_2 ||
- m_gv_fsm_state == GV_STAT_WAIT_TRIG_1;
- }
-
- m_io_sys->set_flg(GVIDEO_PA , gv_ready);
-
- bool irq = m_gv_int_en && !m_gv_dma_en && gv_ready;
-
- m_io_sys->set_irq(GVIDEO_PA , irq);
-
- bool dmar = gv_ready && m_gv_dma_en;
-
- m_io_sys->set_dmar(GVIDEO_PA , dmar);
-}
-
-void hp9845c_state::update_gcursor()
-{
- m_gv_cursor_color = ~m_gv_lyc & 0x7;
- m_gv_cursor_y = (~m_gv_lyc >> 6) & 0x1ff;
- m_gv_cursor_fs = BIT(m_gv_lxc, 0);
- m_gv_cursor_gc = BIT(m_gv_lxc, 1);
- m_gv_cursor_x = (m_gv_lxc >> 6) & 0x3ff;
-}
-
-// ***************
-// hp9845t_state
-// ***************
-class hp9845t_state : public hp9845ct_base_state
-{
-public:
- hp9845t_state(const machine_config &mconfig, device_type type, const char *tag);
-
- void hp9845t(machine_config &config);
-
-private:
- virtual void machine_start() override;
- virtual void machine_reset() override;
-
- virtual DECLARE_READ16_MEMBER(graphic_r) override;
- virtual DECLARE_WRITE16_MEMBER(graphic_w) override;
-
- TIMER_DEVICE_CALLBACK_MEMBER(scanline_timer);
-
- virtual void set_graphic_mode(bool graphic , bool alpha) override;
- void video_render_buff(unsigned video_scanline , unsigned line_in_row, bool buff_idx);
- void graphic_video_render(unsigned video_scanline);
- virtual void plot(uint16_t x, uint16_t y, bool draw_erase) override;
- void draw_arc(uint16_t x0, uint16_t y0, int xstart, int ystart, uint16_t radius, int quadrant, int& draw_counter);
- void draw_full_arc(int x0 , int y0 , int dx , int dy , int draw_counter);
-
- virtual void advance_gv_fsm(bool ds , bool trigger) override;
- virtual void update_graphic_bits() override;
-
- virtual void update_gcursor() override;
-
- std::vector<uint16_t> m_graphic_mem;
-
- bool m_gv_stat;
- bool m_gv_increment_to_next_row;
-
- uint16_t m_gv_scan_start_x;
- uint16_t m_gv_scan_start_y;
- uint8_t m_gv_rb_control;
- uint16_t m_gv_rb_counter;
- uint16_t m_gv_rb_memory[ 256 ];
- uint16_t m_gv_arc[ 4 ];
- uint8_t m_gv_arc_parm;
- bool m_back_arrow_cursor;
-
- static const uint8_t m_back_arrow_shape[];
-};
-
-hp9845t_state::hp9845t_state(const machine_config &mconfig, device_type type, const char *tag)
- : hp9845ct_base_state(mconfig , type , tag)
-{
-}
-
-void hp9845t_state::machine_start()
-{
- // Common part first
- hp9845ct_base_state::machine_start();
-
- m_graphic_mem.resize(GVIDEO_MEM_SIZE);
-
- // initialize palette
- m_palette->set_pen_color(PEN_BLACK , 0x00, 0x00, 0x00); // black
- m_palette->set_pen_color(PEN_GRAPHIC, 0x00, I_GR, 0x00); // graphics
- m_palette->set_pen_color(PEN_ALPHA , 0x00, I_AL, 0x00); // alpha
- m_palette->set_pen_color(PEN_CURSOR , 0x00, I_CU, 0x00); // graphics cursor
- m_palette->set_pen_color(PEN_LP , 0x00, I_LP, 0x00); // lightpen cursor
-}
-
-void hp9845t_state::machine_reset()
-{
- // Common part first
- hp9845ct_base_state::machine_reset();
-
- m_gv_stat = false;
- m_gv_increment_to_next_row = false;
- m_gv_scan_start_x = 0;
- m_gv_scan_start_y = 0;
- m_gv_rb_control = 0;
- m_gv_rb_counter = 0;
- memset(m_gv_rb_memory, 0, sizeof(m_gv_rb_memory));
- m_back_arrow_cursor = false;
-
- set_video_mar(0);
-}
-
-READ16_MEMBER(hp9845t_state::graphic_r)
-{
- uint16_t res = 0;
-
- switch (offset) {
- case 2:
- // R6: data register with DMA TC
- m_gv_dma_en = false;
- // Intentional fall-through
-
- case 0:
- // R4: data register
- if (m_gv_lp_en) {
- res = lp_r4_r();
- } else if (m_gv_sk_en) {
- res = m_gv_softkey;
- m_gv_sk_status = false;
- } else {
- res = m_gv_data_r;
- }
- advance_gv_fsm(true , false);
- update_graphic_bits();
- break;
-
- case 1:
- // R5: status register
- if (m_gv_int_en) {
- BIT_SET(res, 7);
- }
- if (m_gv_dma_en) {
- BIT_SET(res, 6);
- }
- if (m_gv_lp_status && m_gv_lp_int_en) {
- BIT_SET(res, 0); // Lightpen service request
- }
- // TODO: gsr/
- if (m_gv_sk_status) {
- BIT_SET(res, 1); // Softkey service request
- }
- BIT_SET(res, 9); // ID
- BIT_SET(res, 11); // ID
- if (m_gv_stat) {
- BIT_SET(res, 13); // error indication
- }
- break;
-
- case 3:
- // R7: not mapped
- break;
- }
-
- LOG("rd gv R%u = %04x\n", 4 + offset , res);
-
- return res;
-}
-
-WRITE16_MEMBER(hp9845t_state::graphic_w)
-{
- LOG("wr gv R%u = %04x\n", 4 + offset , data);
-
- switch (offset) {
- case 0:
- // R4: data register
- m_gv_data_w = data;
- advance_gv_fsm(true , false);
- lp_r4_w(data);
- if (m_gv_lp_int_en) {
- m_gv_lp_fullbright = BIT(data , 1);
- }
- break;
-
- case 1:
- // R5: command register
- m_gv_cmd = (uint8_t)(data & 0xf);
- m_gv_dma_en = BIT(data , 6) != 0;
- m_gv_int_en = BIT(data , 7) != 0;
- m_gv_gr_en = BIT(data , 8); // enables graphics controller & vector generator command processing and IRQs
- m_gv_sk_en = (data & 0xb00) == 0x200; // enables reads on R4 to return SK keycode, also enables SK IRQs
- m_gv_opt_en = BIT(data , 11); // not really used
- m_gv_dsa_en = BIT(data , 12); // for factory use only (function unknown)
- m_gv_fsm_state = GV_STAT_RESET; // command/reset state machine
- lp_r5_w(data);
- advance_gv_fsm(false , false);
- break;
-
- case 2:
- // R6: data register with DMA TC
- m_gv_dma_en = false;
- m_gv_data_w = data;
- lp_r4_w(data);
- if (m_gv_lp_int_en) {
- m_gv_lp_fullbright = BIT(data , 1);
- }
- advance_gv_fsm(true , false);
- break;
-
- case 3:
- // R7: not mapped
- break;
- }
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER(hp9845t_state::scanline_timer)
-{
- unsigned video_scanline = param;
-
- if (video_scanline >= VIDEO_780_VBEND && video_scanline < VIDEO_780_VBSTART) {
- if (m_graphic_sel) {
- graphic_video_render(video_scanline - VIDEO_780_VBEND);
- }
- unsigned row = (video_scanline - VIDEO_780_VBEND) / VIDEO_CHAR_HEIGHT;
- unsigned line_in_row = (video_scanline - VIDEO_780_VBEND) - row * VIDEO_CHAR_HEIGHT;
-
- 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(video_scanline , line_in_row , m_video_buff_idx);
- // Lightpen cursor
- if (m_graphic_sel) {
- render_lp_cursor(video_scanline - VIDEO_780_VBEND , PEN_LP);
- }
- }
- lp_scanline_update(video_scanline - VIDEO_780_VBEND);
-}
-
-void hp9845t_state::set_graphic_mode(bool graphic , bool alpha)
-{
- m_back_arrow_cursor = graphic; // triggers back arrow cursor, 98780A uses video on/off command for enabling/disabling graphics
- m_alpha_sel = alpha;
-}
-
-void hp9845t_state::video_render_buff(unsigned video_scanline , unsigned line_in_row, bool buff_idx)
-{
- if (!m_video_buff[ buff_idx ].full) {
- m_video_blanked = true;
- }
-
- const pen_t *pen = m_palette->pens();
-
- if (m_video_blanked || !m_alpha_sel) {
- // Blank scanline
- for (unsigned i = 0; i < VIDEO_780_ALPHA_L_LIM; i++) {
- m_bitmap.pix32(video_scanline , i) = pen[ PEN_BLACK ];
- }
- if (!m_graphic_sel) {
- for (unsigned i = VIDEO_780_ALPHA_L_LIM; i < VIDEO_780_ALPHA_R_LIM; i++) {
- m_bitmap.pix32(video_scanline , i) = pen[ PEN_BLACK ];
- }
- }
- for (unsigned i = VIDEO_780_ALPHA_R_LIM; i < VIDEO_TOT_HPIXELS; i++) {
- m_bitmap.pix32(video_scanline , i) = pen[ PEN_BLACK ];
- }
- } else {
- bool cursor_line = line_in_row == 12;
- bool ul_line = line_in_row == 14;
- unsigned video_frame = (unsigned)m_screen->frame_number();
- bool cursor_blink = BIT(video_frame , 3);
- bool char_blink = BIT(video_frame , 4);
-
- for (unsigned i = 0; i < 80; i++) {
- uint8_t attrs = m_video_buff[ buff_idx ].attrs[ i ];
- uint16_t pixels;
-
- if (!BIT(attrs , 2) || char_blink) {
- if (ul_line && BIT(attrs , 3)) {
- pixels = ~0;
- } else {
- // The 98780A uses two identical 4KB ROMs interlaced to keep up with the speed of
- // the video circuit. Each of the 4K ROMs contains the full character set.
- // The 98780A fills row 0 (space between characters) controlled by row 1 and 2 from
- // the character ROM, thereby providing line drawing characters for continuous lines
- uint8_t charcode = m_video_buff[ buff_idx ].chars[ i ];
- uint16_t chrgen_addr = ((uint16_t)(charcode ^ 0xff) << 4) | (line_in_row + 1);
- pixels = (uint16_t)m_chargen[ chrgen_addr ] << 1;
- if ((charcode & 0xe0) == 0xe0 && (pixels & 0x6) == 0x6) {
- pixels |= 1;
- }
- }
- } else {
- pixels = 0;
- }
-
- if (cursor_blink && BIT(attrs , 0)) {
- if (m_back_arrow_cursor) {
- // back arrow cursor (HP's hardware easter egg)
- pixels |= m_back_arrow_shape[ line_in_row ];
- } else if (cursor_line) {
- pixels = ~0;
- }
- }
-
- if (BIT(attrs , 1)) {
- pixels = ~pixels;
- }
-
- for (unsigned j = 0; j < 9; j++) {
- bool pixel = (pixels & (1U << j)) != 0;
- unsigned x = i * 9 + j;
-
- if (m_graphic_sel && x >= VIDEO_780_ALPHA_L_LIM && x < VIDEO_780_ALPHA_R_LIM) {
- // alpha overlays graphics (non-dominating)
- if (pixel) {
- m_bitmap.pix32(video_scanline , x) = pen[ PEN_ALPHA ];
- }
- } else {
- // Graphics disabled or alpha-only zone
- m_bitmap.pix32(video_scanline , x) = pen[ pixel ? PEN_ALPHA : PEN_BLACK ];
- }
- }
- }
- }
-}
-
-void hp9845t_state::graphic_video_render(unsigned video_scanline)
-{
- // video_scanline is 0-based, i.e. the topmost visible line of graphic screen is 0
- const pen_t *pen = m_palette->pens();
- bool yc, yw;
- uint16_t word;
-
- if (m_gv_cursor_fs) {
- // Full-screen cursor
- yw = false;
- yc = video_scanline == m_gv_cursor_y;
- } else if (m_gv_cursor_gc) {
- // 9 x 9 crosshair
- int cursor_y_top = get_wrapped_scanline(m_gv_cursor_y);
- int int_scanline = (int)video_scanline;
- yw = int_scanline >= cursor_y_top && int_scanline <= (cursor_y_top + 8);
- yc = int_scanline == cursor_y_top + 4;
- } else {
- // 9-pixel blinking line
- int cursor_y_top = get_wrapped_scanline(m_gv_cursor_y);
- int int_scanline = (int)video_scanline;
- yw = false;
- yc = int_scanline == cursor_y_top + 4;
- }
-
- unsigned mem_idx = get_gv_mem_addr(m_gv_scan_start_x >> 4, video_scanline + m_gv_scan_start_y);
- for (unsigned i = 0; i < GVIDEO_HPIXELS; i += 16) {
- word = m_graphic_mem[ mem_idx ];
- mem_idx++;
- // Is wraparound better?
- if (mem_idx > GVIDEO_ADDR_MASK) return;
- unsigned x = i;
- for (uint16_t mask = 0x8000; mask != 0; mask >>= 1) {
- bool cursor = false;
- unsigned pixel;
- if (m_gv_cursor_fs) {
- // Full-screen cursor
- cursor = yc || (x + 184) == m_gv_cursor_x;
- } else if (m_gv_cursor_gc) {
- bool xc = (x + 184) == m_gv_cursor_x;
- bool xw = (x + 180) <= m_gv_cursor_x && (x + 188) >= m_gv_cursor_x;
-
- // 9 x 9 crosshair
- cursor = (yc && xw) || (yw && xc);
- } else if (BIT(m_screen->frame_number() , 3)) {
- // 9-pixel blinking line
- cursor = yc && (x + 188) >= m_gv_cursor_x && (x + 180) <= m_gv_cursor_x;
- }
- if (cursor) {
- pixel = PEN_CURSOR;
- } else {
- // Normal pixel
- if (m_gv_lp_fullbright)
- pixel = word & mask ? PEN_LP : PEN_BLACK;
- else
- pixel = word & mask ? PEN_GRAPHIC : PEN_BLACK;
- }
- m_bitmap.pix32(video_scanline , VIDEO_780_ALPHA_L_LIM + x++) = pen[ pixel ];
- }
- }
-}
-
-void hp9845t_state::plot(uint16_t x, uint16_t y, bool draw_erase)
-{
- uint16_t addr, pixel_mask;
- bool do_draw;
-
- pixel_mask = 0x8000 >> (x & 0xf);
- addr = get_gv_mem_addr(x >> 4 , y);
- if (BIT(m_gv_rb_control, 1)) {
- // save graphics memory to rubber band memory
- if (m_graphic_mem[ addr ] & pixel_mask)
- m_gv_rb_memory[m_gv_rb_counter/16] |= 0x1 << (m_gv_rb_counter % 16); // set
- else
- m_gv_rb_memory[m_gv_rb_counter/16] &= ~(0x1 << (m_gv_rb_counter % 16)); // clear
- m_gv_rb_counter++;
- if (m_gv_rb_counter > 4095) {
- m_gv_stat = true; // we might prevent data corruption here, but the original hardware doesn't
- m_gv_rb_counter = 0;
- }
- } else if (BIT(m_gv_rb_control, 0)) {
- // restore graphics memory from rubber band memory
- if (BIT(m_gv_rb_memory[m_gv_rb_counter / 16], m_gv_rb_counter % 16))
- m_graphic_mem[ addr ] |= pixel_mask; // set
- else
- m_graphic_mem[ addr ] &= ~pixel_mask; // clear
- m_gv_rb_counter++;
- if (m_gv_rb_counter > 4095) {
- m_gv_stat = true;
- m_gv_rb_counter = 0;
- }
- } else {
- // draw/erase pixel
- do_draw = m_gv_memory_control ? draw_erase : !draw_erase;
- if (do_draw)
- m_graphic_mem[ addr ] |= pixel_mask;
- else
- m_graphic_mem[ addr ] &= ~pixel_mask;
- }
-}
-
-void hp9845t_state::draw_arc(uint16_t x0, uint16_t y0, int xstart, int ystart, uint16_t radius, int quadrant, int& draw_counter)
-{
- int i, x1, y1, d;
- bool draw_erase;
- bool do_plot = (xstart < 0) || (ystart < 0);
- int save_x1[560];
-
- /* quadrants:
- *
- * 1 | 0
- * ---+---
- * 2 | 3
- *
- * Note: we are using Horn's algorithm here, however it is not 100% pixel
- * accurate with the original vector generator
- */
-
- d = -radius;
- x1 = radius;
- y1 = 0;
- i = 0;
- while ((x1 > 0) && (draw_counter > 0)) {
- // check for plot start
- if (!do_plot) {
- if ((quadrant % 2) == 0) {
- if ((x1 <= xstart) && (y1 >= ystart)) do_plot = true;
- } else {
- if ((y1 >= xstart) && (x1 <= ystart)) do_plot = true;
- }
- }
-
- // draw pixels in quadrants
- draw_erase = BIT(m_gv_line_type_mask, 15);
- if (do_plot) {
- switch (quadrant) {
- case 0:
- plot(x0 + x1, y0 - y1, draw_erase); // quadrant 0
- break;
- case 1:
- plot(x0 - y1, y0 - x1, draw_erase); // quadrant 1
- break;
- case 2:
- plot(x0 - x1, y0 + y1, draw_erase); // quadrant 2
- break;
- case 3:
- plot(x0 + y1, y0 + x1, draw_erase); // quadrant 3
- break;
- }
- }
-
- // update coordinates
- if (x1 > y1) {
- save_x1[i++] = x1;
- d += 2 * y1 + 1;
- y1++;
- if (do_plot) draw_counter--;
- if (d > 0) {
- x1--;
- if (do_plot) draw_counter--;
- d -= 2 * x1;
- }
- if (x1 <= y1) draw_counter++;
- }
- else {
- x1--;
- y1 = save_x1[--i];
- if (do_plot) {
- draw_counter--;
- if (save_x1[i] != save_x1[i+1])
- draw_counter--;
- }
- }
- update_line_pattern();
- }
-}
-
-void hp9845t_state::draw_full_arc(int x0 , int y0 , int dx , int dy , int draw_counter)
-{
- // radius
- int radius = sqrt(dx * dx + dy * dy);
-
- LOG("midpoint = (%d,%d) radius = %d ctrl = %d count = %d\n", x0, y0, radius, m_gv_memory_control, draw_counter);
-
- /* quadrants:
- *
- * 1 | 0
- * ---+---
- * 2 | 3
- */
-
- int quadrant = 0;
-
- // determine the start quadrant
- if (dx > 0)
- quadrant = (dy < 0) ? 1 : 2;
- else
- quadrant = (dy <= 0) ? 0 : 3;
-
- draw_arc(x0, y0, abs(dx), abs(dy), radius, quadrant, draw_counter);
- while (draw_counter > 0) {
- quadrant++;
- if (quadrant > 3) {
- quadrant = 0;
- }
- draw_arc(x0, y0, -1, -1, radius, quadrant, draw_counter);
- }
-}
-
-void hp9845t_state::advance_gv_fsm(bool ds , bool trigger)
-{
- if (!m_gv_gr_en) {
- return;
- }
-
- bool get_out = false;
-
- attotime time_mem_av;
-
- do {
- switch (m_gv_fsm_state) {
- case GV_STAT_WAIT_DS_0:
- // inital state (same as GV_STAT_RESET), command received
- if (m_gv_cmd == 0x9) {
- // read words command
- if (m_gv_last_cmd != m_gv_cmd) {
- m_gv_io_counter = get_gv_mem_addr(m_gv_word_x_position , m_gv_word_y_position);
- }
- LOG("read words, last = %x\n", m_gv_last_cmd);
- m_gv_fsm_state = GV_STAT_WAIT_MEM_0; // -> read stream
- m_gv_last_cmd = m_gv_cmd;
- } else if (m_gv_cmd == 0xd) {
- // fast clear/set command
- m_gv_fsm_state = GV_STAT_WAIT_MEM_2;
- m_gv_last_cmd = m_gv_cmd;
- } else if (ds) {
- if (m_gv_cmd == 0x8) {
- // write words command
- if (m_gv_last_cmd != m_gv_cmd) {
- m_gv_io_counter = get_gv_mem_addr(m_gv_word_x_position , m_gv_word_y_position);
- }
- LOG("write words\n");
- m_gv_fsm_state = GV_STAT_WAIT_TRIG_1; // -> write stream
- } else {
- // any other command
- m_gv_fsm_state = GV_STAT_WAIT_TRIG_0; // -> wait for trigger
- }
- m_gv_last_cmd = m_gv_cmd;
- } else {
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_TRIG_0:
- // process data on R4 or R6
- switch (m_gv_cmd) {
- case 0x1: // load end points
- m_gv_ypt = m_gv_data_w & 0x3ff;
- LOG("load end points y = %d\n", m_gv_ypt);
- break;
- case 0x3: // load arc
- m_gv_arc_parm = 0;
- m_gv_arc[ m_gv_arc_parm ] = m_gv_data_w;
- LOG("load arc parm%d = %04x\n", m_gv_arc_parm, m_gv_arc[m_gv_arc_parm]);
- m_gv_arc_parm++;
- break;
- case 0x5: // load scan
- m_gv_scan_start_x = m_gv_data_w & 0x3ff; // 0..559
- LOG("load scan x = %d\n", m_gv_scan_start_x);
- break;
- case 0x6: // set line type/area fill
- m_gv_line_type_area_fill = m_gv_data_w & 0x1ff;
- if (BIT(m_gv_line_type_area_fill, 4)) {
- m_gv_line_type_mask = m_line_type[ m_gv_line_type_area_fill & 0x7 ];
- m_gv_repeat_count = 0;
- }
- LOG("set line type = %04x\n", m_gv_line_type_area_fill);
- break;
- case 0x7: // load X/Y I/O address
- m_gv_word_y_position = m_gv_data_w & 0x1ff; // 0..454
- LOG("load X/Y I/O adress y = %04x\n", m_gv_word_y_position);
- break;
- case 0xa: // load memory control
- // A single bit is saved (InvBit)
- m_gv_memory_control = (m_gv_data_w & 0x9) == 9 || (m_gv_data_w & 0x12) == 0x12 || (m_gv_data_w & 0x24) == 0x24;
- LOG("load memory control = %04x\n", m_gv_memory_control);
- break;
- case 0xb: // video on/off - enable graphics video output (1=on 2=off)
- m_graphic_sel = BIT(m_gv_data_w, 0);
- LOG("video on/off parm = %d\n", m_gv_data_w & 0x3);
- break;
- case 0xc: // load color mask (no effect, just for compatibility with 9845c), takes a single word as parameter
- break;
- case 0xe: // Y cursor position
- m_gv_lyc = m_gv_data_w;
- break;
- case 0xf: // X cursor position
- m_gv_lxc = m_gv_data_w;
- break;
- default:
- LOG("unknown 98780A command = %d, parm = 0x%04x\n", m_gv_cmd, m_gv_data_w);
- }
- if ((m_gv_cmd == 0x1) || (m_gv_cmd == 0x3) || (m_gv_cmd == 0x5) || (m_gv_cmd == 0x7)) {
- m_gv_fsm_state = GV_STAT_WAIT_DS_2; // -> get second data word
- } else {
- get_out = true;
- m_gv_fsm_state = GV_STAT_WAIT_DS_0; // -> done
- }
- break;
-
- case GV_STAT_WAIT_MEM_0:
- // process data during read transfer
- 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 ];
- LOG("read words @%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; // -> proceed with read stream
- } else {
- m_gv_timer->adjust(time_mem_av);
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_DS_1:
- // wait for data word to be read
- if (ds) {
- // -- next word
- m_gv_fsm_state = GV_STAT_WAIT_MEM_0; // -> process data word
- } else {
- // -- done
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_DS_2:
- // wait for data word to be written
- if (ds) {
- // -- next word
- m_gv_fsm_state = GV_STAT_WAIT_TRIG_1; // -> process data word
- } else {
- // done
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_TRIG_1:
- // process multi-word parameters & data during write transfer
- switch (m_gv_cmd) {
- case 0x1:
- // load endpoints command
- m_gv_xpt = m_gv_data_w & 0x3ff;
- // RB control is actually set whenever a data word is written into R4/R6 register, not just here
- m_gv_rb_control = (m_gv_data_w >> 13) & 0x7;
- if (BIT(m_gv_rb_control, 2)) {
- m_gv_rb_counter = 0;
- m_gv_stat = false;
- }
- if (BIT(m_gv_data_w, 11)) {
- // draw vector
- LOG("load end points x = %d, rb = %d (draw)\n", m_gv_xpt, m_gv_rb_control);
- m_gv_fsm_state = GV_STAT_WAIT_MEM_2; // -> proceed with draw vector
- } else {
- LOG("load end points x = %d, rb = %d (move)\n", m_gv_xpt, m_gv_rb_control);
- m_gv_last_xpt = m_gv_xpt;
- m_gv_last_ypt = m_gv_ypt;
- m_gv_fsm_state = GV_STAT_WAIT_DS_0; // -> proceed with next word pair
- }
- break;
-
- case 0x3:
- // load arc
- m_gv_arc[ m_gv_arc_parm ] = m_gv_data_w;
- LOG("load arc parm%d = %04x\n", m_gv_arc_parm, m_gv_arc[m_gv_arc_parm]);
- m_gv_arc_parm++;
- if (m_gv_arc_parm < 4) {
- m_gv_fsm_state = GV_STAT_WAIT_DS_2; // -> proceed with next word
- } else {
- m_gv_fsm_state = GV_STAT_WAIT_MEM_2; // -> proceed with draw vector
- }
- break;
-
- case 0x5:
- // load scan
- m_gv_scan_start_y = m_gv_data_w & 0x3ff; // 0..454
- LOG("load scan y = %d\n", m_gv_scan_start_y);
- m_gv_fsm_state = GV_STAT_WAIT_DS_0;
- break;
-
- case 0x7:
- // load X/Y I/O address
- m_gv_word_x_position = (m_gv_data_w & 0x3f0) >> 4; // 0..34
- m_gv_increment_to_next_row = BIT(m_gv_data_w, 11);
- m_gv_io_counter = get_gv_mem_addr(m_gv_word_x_position , m_gv_word_y_position);
- LOG("load X/Y I/O adress x = %04x increment = %d\n", m_gv_word_x_position, m_gv_increment_to_next_row);
- m_gv_fsm_state = GV_STAT_WAIT_DS_0;
- break;
-
- case 0x8:
- // write words command
- m_gv_fsm_state = GV_STAT_WAIT_MEM_1; // -> proceed with next word
- break;
- }
- break;
-
- case GV_STAT_WAIT_MEM_1:
- // -- transfer from bus to graphics memory to bus within write transfer
- time_mem_av = time_to_gv_mem_availability();
- if (time_mem_av.is_zero()) {
- // Write a full word to graphic memory
- LOG("write words @%04x = %04x\n" , m_gv_io_counter , m_gv_data_w);
- m_graphic_mem[ m_gv_io_counter ] = m_gv_data_w;
- if (!m_gv_increment_to_next_row || (m_gv_word_x_position < 34)) {
- m_gv_io_counter = (m_gv_io_counter + 1) & GVIDEO_ADDR_MASK;
- }
- m_gv_fsm_state = GV_STAT_WAIT_DS_2; // -> proceed with write stream
- } else {
- m_gv_timer->adjust(time_mem_av);
- get_out = true;
- }
- break;
-
- case GV_STAT_WAIT_MEM_2:
- // vector generator
- time_mem_av = time_to_gv_mem_availability();
- if (time_mem_av.is_zero()) {
- if (m_gv_cmd == 0xd) {
- // fast clear/set command
- if (m_gv_memory_control) {
- LOG("fast clear/set (set)\n");
- for (auto& el : m_graphic_mem) {
- el = 0xffff;
- }
- } else {
- LOG("fast clear/set (clear)\n");
- for (auto& el : m_graphic_mem) {
- el = 0;
- }
- }
- } else {
- if (m_gv_cmd == 0x3) {
- // draw arc/circle
- // drawing is performed counter-clockwise by using Horn's algorithm
- // m_gv_arc[0] is the delta last load endpoint y coordinate minus the midpoint y coordinate
- // m_gv_arc[1] is the delta last load endpoint x coordinate minus the midpoint x coordinate
- // m_gv_arc[2] is the (probably) the start count (?), actually ignored
- // m_gv_arc[3] is the total horizontal + vertical count for the 4 quadrants counter-clockwise, starting at the last load endpoint (equals 4 times radius for full circles)
- LOG("arc draw\n");
-
- // midpoint
- int dx = BIT(m_gv_arc[ 1 ] , 15) ? (int)m_gv_arc[ 1 ] - 65536 : m_gv_arc[ 1 ] & 0x7ff;
- int dy = BIT(m_gv_arc[ 0 ] , 15) ? (int)m_gv_arc[ 0 ] - 65536 : m_gv_arc[ 0 ];
- int x0 = m_gv_xpt + dx;
- int y0 = m_gv_ypt - dy;
-
- draw_full_arc(x0 , y0 , dx , dy , m_gv_arc[ 3 ]);
- } else if (BIT (m_gv_line_type_area_fill, 4)) {
- unsigned x0;
- unsigned x1;
- unsigned y0;
- unsigned y1;
-
- LOG("line draw (%d,%d)->(%d,%d)\n", m_gv_last_xpt, m_gv_last_ypt, m_gv_xpt, m_gv_ypt);
-
- // vector generator uses normalization
- if (m_gv_xpt > m_gv_last_xpt) {
- x0 = m_gv_last_xpt;
- y0 = m_gv_last_ypt;
- x1 = m_gv_xpt;
- y1 = m_gv_ypt;
- } else {
- x0 = m_gv_xpt;
- y0 = m_gv_ypt;
- x1 = m_gv_last_xpt;
- y1 = m_gv_last_ypt;
- }
- draw_line(x0 , y0 , x1 , y1);
- } else {
- // fill area with pattern
- LOG("area fill (%d,%d) -> (%d,%d) pattern=%04x\n", m_gv_last_xpt, m_gv_last_ypt, m_gv_xpt, m_gv_ypt, m_gv_line_type_area_fill);
-
- pattern_fill(m_gv_xpt , m_gv_ypt , m_gv_last_xpt , m_gv_last_ypt , 15 - (m_gv_line_type_area_fill & 0xf));
- }
- m_gv_last_xpt = m_gv_xpt;
- m_gv_last_ypt = m_gv_ypt;
- }
- m_gv_fsm_state = GV_STAT_WAIT_DS_0;
- } else {
- m_gv_timer->adjust(time_mem_av);
- }
- get_out = true;
- break;
-
- default:
- logerror("Invalid state reached %d\n" , m_gv_fsm_state);
- m_gv_fsm_state = GV_STAT_RESET;
- }
-
- ds = false;
- } while (!get_out);
-
- update_graphic_bits();
-}
-
-void hp9845t_state::update_graphic_bits()
-{
- bool gv_ready = (m_gv_lp_int_en && m_gv_lp_status) || (m_gv_sk_en && m_gv_sk_status);
-
- if (m_gv_gr_en && !gv_ready) {
- 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;
- }
-
- // WARNING! Race conditions here!
- // FLG and IRQ are raised together. In enhgfxb ROM a SFC instruction
- // that spins on itself waiting for FLG to be true was getting
- // stuck because the interrupt always took precedence (and the ISR
- // cleared the FLG bit).
- // In real hw there was a non-zero chance that SFC exited the loop before
- // interrupt was serviced. In case SFC stayed in the loop, it got another
- // chance at the next interrupt.
- // Fix for this problem is in commit 27004d00
- // My apologies to Tony Duell for doubting at one point the correctness
- // of his 98780A schematics.. :)
- m_io_sys->set_flg(GVIDEO_PA , gv_ready);
-
- bool irq = m_gv_int_en && !m_gv_dma_en && gv_ready;
-
- m_io_sys->set_irq(GVIDEO_PA , irq);
-
- bool dmar = gv_ready && m_gv_dma_en;
-
- m_io_sys->set_dmar(GVIDEO_PA , dmar);
-}
-
-void hp9845t_state::update_gcursor()
-{
- m_gv_cursor_fs = (m_gv_lyc & 0x3) == 0;
- m_gv_cursor_gc = !BIT(m_gv_lyc , 1);
- m_gv_cursor_y = (~m_gv_lyc >> 7) & 0x1ff;
- m_gv_cursor_x = (m_gv_lxc >> 6) & 0x3ff;
-}
-
-const uint8_t hp9845t_state::m_back_arrow_shape[] = {
- 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xfc,
- 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00
-};
-
-void hp9845_state::hp9845a(machine_config &config)
-{
- //HP_5061_3010(config, m_lpu, XTAL(11'400'000));
- //HP_5061_3011(config, m_ppu, XTAL(11'400'000));
-
- // video hardware
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(hp9845_state::screen_update));
- screen.set_refresh_hz(60);
- screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500));
- screen.set_size(560, 455);
- screen.set_visarea(0, 560-1, 0, 455-1);
-
- SOFTWARE_LIST(config, "optrom_list").set_original("hp9845a_rom");
-}
-
-void hp9845_state::hp9835a(machine_config &config)
-{
- //HP_5061_3001(config, m_lpu, XTAL(11'400'000));
- //HP_5061_301(1config, m_ppu, XTAL(11'400'000));
-
- // video hardware
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(hp9845_state::screen_update));
- screen.set_refresh_hz(60);
- screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500));
- screen.set_size(560, 455);
- screen.set_visarea(0, 560-1, 0, 455-1);
-
- SOFTWARE_LIST(config, "optrom_list").set_original("hp9835a_rom");
-}
-
-/*
- Global memory map in blocks of 32 kwords / 64 kbytes each:
-
- block 0: 0x000000 - 0x007fff (LPU RAM)
- block 1: 0x008000 - 0x00ffff (PPU RAM, only 0x00c000 - 0x00ffff used)
- block 2: 0x010000 - 0x017fff (unused)
- block 3: 0x018000 - 0x01ffff (LPU system ROM)
- block 4: 0x020000 - 0x027fff (LPU RAM)
- block 5: 0x028000 - 0x02ffff (PPU system ROM)
- block 6: 0x030000 - 0x037fff (LPU RAM)
- block 7: 0x038000 - 0x03ffff (LPU option ROM)
- block 10: 0x040000 - 0x047fff (LPU RAM)
- block 11: 0x048000 - 0x04ffff (PPU option ROM)
- block 12: 0x050000 - 0x057fff (LPU RAM)
- block 13: 0x058000 - 0x05ffff (LPU option ROM)
- block 14: 0x060000 - 0x067fff (LPU RAM)
- block 15: 0x068000 - 0x06ffff (PPU option ROM)
- block 16: 0x070000 - 0x077fff (LPU RAM)
- block 17: 0x078000 - 0x07ffff (unused)
-
- notes:
- - all block numbers are octal
- - blocks 20 to 76 are reserved for 512 kbyte RAM boards (p/n 09845-66590)
- - block 45 is reserved for the Test ROM
- - memory addresses are continuous (for convenience, the mapping below uses block numbers as
- address part above 0xffff, so there are gaps between 0x8000 and 0xffff which are masked out).
- - all LPU RAM is dynamically mapped at machine start according to -ramsize option
-*/
-
-void hp9845_base_state::global_mem_map(address_map &map)
-{
- map.global_mask(0x3f7fff);
- map.unmap_value_low();
- map(0x014000, 0x017fff).ram().share("ppu_ram");
- map(0x030000, 0x037fff).rom().region("lpu", 0);
- map(0x050000, 0x057fff).rom().region("ppu", 0);
-}
-
-void hp9845_base_state::ppu_io_map(address_map &map)
-{
- map.unmap_value_low();
- // PA = 0, IC = 0..1
- // Internal printer
- map(HP_MAKE_IOADDR(PRINTER_PA, 0), HP_MAKE_IOADDR(PRINTER_PA, 1)).rw("printer", FUNC(hp9845_printer_device::printer_r), FUNC(hp9845_printer_device::printer_w));
- // PA = 0, IC = 2
- // Keyboard scancode input
- map(HP_MAKE_IOADDR(0, 2), HP_MAKE_IOADDR(0, 2)).r(FUNC(hp9845_base_state::kb_scancode_r));
- // PA = 0, IC = 3
- // Keyboard status input & keyboard interrupt clear
- map(HP_MAKE_IOADDR(0, 3), HP_MAKE_IOADDR(0, 3)).rw(FUNC(hp9845_base_state::kb_status_r), FUNC(hp9845_base_state::kb_irq_clear_w));
- // PA = 13, IC = 0..3
- // Graphic video
- map(HP_MAKE_IOADDR(GVIDEO_PA, 0), HP_MAKE_IOADDR(GVIDEO_PA, 3)).rw(FUNC(hp9845_base_state::graphic_r), FUNC(hp9845_base_state::graphic_w));
- // PA = 14, IC = 0..3
- // Left-hand side tape drive (T14)
- map(HP_MAKE_IOADDR(T14_PA, 0), HP_MAKE_IOADDR(T14_PA, 3)).rw(m_t14, FUNC(hp_taco_device::reg_r), FUNC(hp_taco_device::reg_w));
- // PA = 15, IC = 0..3
- // Right-hand side tape drive (T15)
- map(HP_MAKE_IOADDR(T15_PA, 0), HP_MAKE_IOADDR(T15_PA, 3)).rw(m_t15, FUNC(hp_taco_device::reg_r), FUNC(hp_taco_device::reg_w));
-}
-
-void hp9845_base_state::hp9845_base(machine_config &config)
-{
- HP_5061_3001(config , m_lpu , 5700000);
- m_lpu->set_addrmap(AS_PROGRAM , &hp9845_base_state::global_mem_map);
- m_lpu->set_9845_boot_mode(true);
- m_lpu->set_rw_cycles(6 , 6);
- m_lpu->set_relative_mode(true);
- HP_5061_3001(config , m_ppu , 5700000);
- m_ppu->set_addrmap(AS_PROGRAM , &hp9845_base_state::global_mem_map);
- m_ppu->set_addrmap(AS_IO , &hp9845_base_state::ppu_io_map);
- m_ppu->set_9845_boot_mode(true);
- m_ppu->set_rw_cycles(6 , 6);
- m_ppu->set_relative_mode(true);
- m_ppu->set_irq_acknowledge_callback("io_sys" , FUNC(hp98x5_io_sys_device::irq_callback));
- m_ppu->pa_changed_cb().set(m_io_sys , FUNC(hp98x5_io_sys_device::pa_w));
-
- HP98X5_IO_SYS(config , m_io_sys , 0);
- m_io_sys->irl().set_inputline(m_ppu, HPHYBRID_IRL);
- m_io_sys->irh().set_inputline(m_ppu, HPHYBRID_IRH);
- m_io_sys->sts().set(m_ppu , FUNC(hp_5061_3001_cpu_device::status_w));
- m_io_sys->flg().set(m_ppu , FUNC(hp_5061_3001_cpu_device::flag_w));
- m_io_sys->dmar().set(m_ppu , FUNC(hp_5061_3001_cpu_device::dmar_w));
-
- // video hardware
- SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
-
- TIMER(config, m_gv_timer).configure_generic(FUNC(hp9845_base_state::gv_timer));
-
- // Actual keyboard refresh rate should be KEY_SCAN_OSCILLATOR / 128 (2560 Hz)
- TIMER(config, "kb_timer").configure_periodic(FUNC(hp9845_base_state::kb_scan), attotime::from_hz(100));
-
- // Beeper
- SPEAKER(config, "mono").front_center();
- BEEP(config, m_beeper , KEY_SCAN_OSCILLATOR / 512).add_route(ALL_OUTPUTS , "mono" , 0.50);
-
- TIMER(config, m_beep_timer).configure_generic(FUNC(hp9845_base_state::beeper_off));
-
- // Tape drives
- HP_TACO(config , m_t15 , 4000000);
- m_t15->irq().set([this](int state) { m_io_sys->set_irq(T15_PA , state); });
- m_t15->flg().set([this](int state) { m_io_sys->set_flg(T15_PA , state); });
- m_t15->sts().set([this](int state) { m_io_sys->set_sts(T15_PA , state); });
- HP_TACO(config , m_t14 , 4000000);
- m_t14->irq().set([this](int state) { m_io_sys->set_irq(T14_PA , state); });
- m_t14->flg().set([this](int state) { m_io_sys->set_flg(T14_PA , state); });
- m_t14->sts().set([this](int state) { m_io_sys->set_sts(T14_PA , state); });
-
- // In real machine there were 8 slots for LPU ROMs and 8 slots for PPU ROMs in
- // right-hand side and left-hand side drawers, respectively.
- // Here we do away with the distinction between LPU & PPU ROMs: in the end they
- // are visible to both CPUs at the same addresses.
- HP9845_OPTROM(config, "drawer1", 0);
- HP9845_OPTROM(config, "drawer2", 0);
- HP9845_OPTROM(config, "drawer3", 0);
- HP9845_OPTROM(config, "drawer4", 0);
- HP9845_OPTROM(config, "drawer5", 0);
- HP9845_OPTROM(config, "drawer6", 0);
- HP9845_OPTROM(config, "drawer7", 0);
- HP9845_OPTROM(config, "drawer8", 0);
-
- // I/O slots
- for (unsigned slot = 0; slot < 4; slot++) {
- auto& finder = m_io_slot[ slot ];
- hp9845_io_slot_device& tmp( HP9845_IO_SLOT(config , finder , 0) );
- tmp.irq().set([this , slot](int state) { set_irq_slot(slot , state); });
- tmp.sts().set([this , slot](int state) { set_sts_slot(slot , state); });
- tmp.flg().set([this , slot](int state) { set_flg_slot(slot , state); });
- tmp.irq_nextsc().set([this , slot](int state) { set_irq_nextsc_slot(slot , state); });
- tmp.sts_nextsc().set([this , slot](int state) { set_sts_nextsc_slot(slot , state); });
- tmp.flg_nextsc().set([this , slot](int state) { set_flg_nextsc_slot(slot , state); });
- tmp.dmar().set([this , slot](int state) { set_dmar_slot(slot , state); });
- }
-
- // LPU memory options
- RAM(config, RAM_TAG).set_default_size("192K").set_extra_options("64K, 320K, 448K");
-
- // Internal printer
- hp9845_printer_device& prt{ HP9845_PRINTER(config , "printer" , 0) };
- prt.irq().set(FUNC(hp9845_base_state::prt_irl_w));
- prt.flg().set([this](int state) { m_io_sys->set_flg(PRINTER_PA , state); });
- prt.sts().set([this](int state) { m_io_sys->set_sts(PRINTER_PA , state); });
-}
-
-void hp9845b_state::hp9845b(machine_config &config)
-{
- hp9845_base(config);
- // video hardware
- m_screen->set_screen_update(FUNC(hp9845b_state::screen_update));
- m_screen->screen_vblank().set(FUNC(hp9845b_state::vblank_w));
- m_screen->set_color(rgb_t::green());
- // These parameters are for alpha video
- m_screen->set_raw(VIDEO_PIXEL_CLOCK , VIDEO_HTOTAL , 0 , VIDEO_HBSTART , VIDEO_VTOTAL , 0 , VIDEO_ACTIVE_SCANLINES);
- PALETTE(config, m_palette).set_entries(4);
- TIMER(config, "scantimer").configure_scanline(FUNC(hp9845b_state::scanline_timer), "screen", 0, 1);
-
- config.set_default_layout(layout_hp9845b);
-
- SOFTWARE_LIST(config, "optrom_list").set_original("hp9845b_rom");
-}
-
-void hp9845c_state::hp9845c(machine_config &config)
-{
- hp9845_base(config);
- // video hardware
- m_screen->set_screen_update(FUNC(hp9845c_state::screen_update));
- m_screen->screen_vblank().set(FUNC(hp9845c_state::vblank_w));
- m_screen->set_raw(VIDEO_770_PIXEL_CLOCK , VIDEO_770_HTOTAL , VIDEO_770_HBEND , VIDEO_770_HBSTART , VIDEO_770_VTOTAL , VIDEO_770_VBEND , VIDEO_770_VBSTART);
- PALETTE(config, m_palette).set_entries(24);
- TIMER(config, "scantimer").configure_scanline(FUNC(hp9845c_state::scanline_timer), "screen", 0, 1);
-
- SOFTWARE_LIST(config, "optrom_list").set_original("hp9845b_rom");
-}
-
-void hp9845t_state::hp9845t(machine_config &config)
-{
- hp9845_base(config);
- // video hardware
- m_screen->set_screen_update(FUNC(hp9845t_state::screen_update));
- m_screen->screen_vblank().set(FUNC(hp9845t_state::vblank_w));
- m_screen->set_color(rgb_t::green());
- m_screen->set_raw(VIDEO_780_PIXEL_CLOCK , VIDEO_780_HTOTAL , VIDEO_780_HBEND , VIDEO_780_HBSTART , VIDEO_780_VTOTAL , VIDEO_780_VBEND , VIDEO_780_VBSTART);
- PALETTE(config, m_palette).set_entries(5);
- TIMER(config, "scantimer").configure_scanline(FUNC(hp9845t_state::scanline_timer), "screen", 0, 1);
-
- SOFTWARE_LIST(config, "optrom_list").set_original("hp9845b_rom");
-}
-
- ROM_START( hp9845a )
- ROM_REGION( 0200000, "lpu", ROMREGION_16BIT | ROMREGION_BE )
- ROM_LOAD( "09845-65544-65547-03-system_lpu.bin", 0000000, 0200000, CRC(47beb87f) SHA1(456caefacafcf19435e1e7e68b1c1e4010841664) )
-
- ROM_REGION( 0200000, "ppu", ROMREGION_16BIT | ROMREGION_BE )
- ROM_LOAD( "09845-65540-65543-01-system_ppu.bin", 0000000, 0160000, CRC(bc0a34cc) SHA1(9ff215f4ba32ad85f144845d15f762a71e35588b) )
-ROM_END
-
-#define rom_hp9845s rom_hp9845a
-
-ROM_START( hp9835a )
- ROM_REGION( 0200000, "lpu", ROMREGION_16BIT | ROMREGION_BE )
- ROM_LOAD( "1818-2800-03_00-system-lpu.bin", 0000000, 020000, CRC(e0b0977a) SHA1(5afdc6c725abff70b674e46688d8ab38ccf8f3c1) )
- ROM_LOAD( "1818-2801-03_10-system-lpu.bin", 0020000, 020000, CRC(c51c1e3a) SHA1(798964fa2e7a1fc149ce4400b694630049293119) )
- ROM_LOAD( "1818-2802-03_20-system-lpu.bin", 0040000, 020000, CRC(bba70a7e) SHA1(2d488594493f8dfcd753e462414cc51c24596a2c) )
- ROM_LOAD( "1818-2803-03_30-system-lpu.bin", 0060000, 020000, CRC(65e9eba6) SHA1(a11f5d37e8ed14a428335c43e785d635b02d1129) )
- ROM_LOAD( "1818-2804-03_40-system-lpu.bin", 0100000, 020000, CRC(ef83b695) SHA1(8ca2914609ece2c9c59ebba6ece3fcbc8929aeaf) )
- ROM_LOAD( "1818-2805-03_50-system-lpu.bin", 0120000, 020000, CRC(401d539f) SHA1(00bda59f71632c4d4fc3268c04262bb81ef0eeba) )
- ROM_LOAD( "1818-2806-03_60-system-lpu.bin", 0140000, 020000, CRC(fe353db5) SHA1(0fb52d82d3743008cdebebb20c488e34ce2fca4b) )
- ROM_LOAD( "1818-2807-03_70-system-lpu.bin", 0160000, 020000, CRC(45a3cc5e) SHA1(35c9959331acf7c98ab6a880915b03e3e783a656) )
-
- ROM_REGION( 0200000, "ppu", ROMREGION_16BIT | ROMREGION_BE )
- ROM_LOAD( "1818-2808-05_00-system-ppu.bin", 0000000, 020000, CRC(d0c96276) SHA1(cc578d586c4eda81469f29eb7cab7f667e0d5977) )
- ROM_LOAD( "1818-2809-05_30-system-ppu.bin", 0060000, 020000, CRC(ccdb7171) SHA1(1d24596bc1219983e7cb81f6987af094f2ca7d81) )
- ROM_LOAD( "1818-2810-05_40-system-ppu.bin", 0100000, 020000, CRC(97487d24) SHA1(823cd16671de8e6ff2c245060c99778acb6ff79c) )
- ROM_LOAD( "1818-2811-05_50-system-ppu.bin", 0120000, 020000, CRC(18aee6fd) SHA1(388d3b2a063ea2cfdfe9fb9f864fa5f08af817b0) )
- ROM_LOAD( "1818-2812-05_60-system-ppu.bin", 0140000, 020000, CRC(c0beeeae) SHA1(a5db36a7f7bad84c1013bd3ec4813c355f72427d) )
- ROM_LOAD( "1818-2813-05_70-system-ppu.bin", 0160000, 020000, CRC(75361bbf) SHA1(40f499c597da5c8c9a55a2a891976d946a54926b) )
-ROM_END
-
-#define rom_hp9835b rom_hp9835a
-
-ROM_START( hp9845b )
- ROM_REGION(0x800 , "chargen" , 0)
- ROM_LOAD("chrgen.bin" , 0 , 0x800 , CRC(fe9e844f) SHA1(0c45ae00766ceba94a19bd5e154bd6d23e208cca))
-
- ROM_REGION(0x800 , "optional_chargen" , 0)
- ROM_LOAD("optional_chrgen.bin" , 0 , 0x800 , CRC(0ecfa63b) SHA1(c295e6393d1503d903c1d2ce576fa597df9746bf))
-
- ROM_REGION(0x10000, "lpu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-lpu-standard-processor.bin", 0, 0x10000, CRC(dc266c1b) SHA1(1cf3267f13872fbbfc035b70f8b4ec6b5923f182))
-
- ROM_REGION(0x10000, "ppu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-ppu-standard-graphics.bin", 0, 0x10000, CRC(f866510f) SHA1(3e22cd2072e3a5f3603a1eb8477b6b4a198d184d))
-
-#if 0
- ROM_REGION( 0200000, "lpu", ROMREGION_16BIT | ROMREGION_BE )
- ROM_LOAD( "1818-0823-0827-03_00-revb-system_lpu.bin", 0000000, 020000, CRC(7e49c781) SHA1(866c9ebd98d94bb6f99692e29d2d83f55b38c4b6) )
- ROM_LOAD( "1818-0823-0827-03_10-revb-system_lpu.bin", 0020000, 020000, CRC(2f819e3d) SHA1(250886378c3ce2253229997007c7bf0be80a8d1d) )
- ROM_LOAD( "1818-0824-0828-03_20-reva-system_lpu.bin", 0040000, 020000, CRC(834f7063) SHA1(5c390ed74671e4663cc80d899d07b69fd1fb4be6) )
- ROM_LOAD( "1818-0824-0828-03_20-revb-system_lpu.bin", 0040000, 020000, CRC(aa221deb) SHA1(7878643405ee45405dc5269c3b6dc9459f39437b) )
- ROM_LOAD( "1818-0824-0828-03_30-reva-system_lpu.bin", 0060000, 020000, CRC(0ebafdb2) SHA1(80733bfb7026d39a294841221d80ec40eafffe34) )
- ROM_LOAD( "1818-0824-0828-03_30-revb-system_lpu.bin", 0060000, 020000, CRC(0ebafdb2) SHA1(80733bfb7026d39a294841221d80ec40eafffe34) )
- ROM_LOAD( "1818-0825-0829-03_40-revb-system_lpu.bin", 0100000, 020000, CRC(beb09a57) SHA1(b832b995fa21c219673f0c7cf215dee70698f4f1) )
- ROM_LOAD( "1818-0825-0829-03_50-revb-system_lpu.bin", 0120000, 020000, CRC(bbb06222) SHA1(b0bfe1b48fac61eb955e27e0ddfbea020e09e0eb) )
- ROM_LOAD( "1818-0826-0830-03_60-revc-system_lpu.bin", 0140000, 020000, CRC(5c1c3abe) SHA1(fa9f99bf7c8a6df5c71e9fd8c807f0a2ff06640d) )
- ROM_LOAD( "1818-0826-0830-03_70-revc-system_lpu.bin", 0160000, 020000, CRC(0c61a266) SHA1(0cfbf482e7f8e99c87b97c77cf178682cd7af7d6) )
-
- ROM_REGION( 0200000, "lpu_fast", ROMREGION_16BIT | ROMREGION_BE )
- ROM_LOAD( "1818-1506-1502-03_00-reva-system_fast_lpu.bin", 0000000, 020000, CRC(b77194d8) SHA1(6feec8605331783e6f5a2ab6d6cbd9285036e863) )
- ROM_LOAD( "1818-1506-1502-03_10-reva-system_fast_lpu.bin", 0020000, 020000, CRC(bc5557a5) SHA1(282237e561c3f2304cdeb45efa2432748581af45) )
- ROM_LOAD( "1818-1507-1503-03_20-reva-system_fast_lpu.bin", 0040000, 020000, CRC(2ebc71e2) SHA1(a2d39fb24d565465304833dfd0ff87dd5ef26fb3) )
- ROM_LOAD( "1818-1507-1503-03_30-reva-system_fast_lpu.bin", 0060000, 020000, CRC(82e56bc4) SHA1(36201f343382e533c248ddd123507a2e195cca39) )
- ROM_LOAD( "1818-1508-1504-03_40-reva-system_fast_lpu.bin", 0100000, 020000, CRC(70b0fcb0) SHA1(3f7ce60cad0ffec8344f33d584869492c7f73026) )
- ROM_LOAD( "1818-1508-1504-03_50-reva-system_fast_lpu.bin", 0120000, 020000, CRC(935fab96) SHA1(ecb1da2a0bd46e8c0da2875a1af8cf71d8f4bb56) )
- ROM_LOAD( "1818-1509-1505-03_60-reva-system_fast_lpu.bin", 0140000, 020000, CRC(f4119af7) SHA1(72a3e8b8d7d306e55f8adf0e23225bb81bc2b4ba) )
- ROM_LOAD( "1818-1509-1505-03_70-reva-system_fast_lpu.bin", 0160000, 020000, CRC(22fb0864) SHA1(4e1dce32e84ba216dbbd4116f3b22ca7f254f529) )
-
- ROM_REGION( 0200000, "ppu", ROMREGION_16BIT | ROMREGION_BE )
- ROM_LOAD( "1818-0833-0837-05_40-revc-system_ppu.bin", 0100000, 020000, CRC(d790795c) SHA1(7ba1e245a98379a34833a780898a784049e33b86) )
- ROM_LOAD( "1818-0833-0837-05_40-revd-system_ppu.bin", 0100000, 020000, CRC(49897e40) SHA1(780a9973ff26d40f470e2004fccceb1019f8ba7f) )
- ROM_LOAD( "1818-0833-0837-05_50-revc-system_ppu.bin", 0120000, 020000, CRC(ef8acde4) SHA1(e68648543aac2b841b08d7758949ba1339a83701) )
- ROM_LOAD( "1818-0833-0837-05_50-revd-system_ppu.bin", 0120000, 020000, CRC(54f61d07) SHA1(f807fb8a59cd9cd221f63907e6a86948a0bf7c1d) )
- ROM_LOAD( "1818-0834-0838-05_60-revc-system_ppu.bin", 0140000, 020000, CRC(20f2100a) SHA1(9304f0b069de9233d697588328f9657dbeabc254) )
- ROM_LOAD( "1818-0834-0838-05_60-revd-system_ppu.bin", 0140000, 020000, CRC(454af601) SHA1(54b56e67e855fd2d699a0dbef0b4d2e8c150c39b) )
- ROM_LOAD( "1818-0834-0838-05_70-revc-system_ppu.bin", 0160000, 020000, CRC(43f62491) SHA1(a9489b37b3fa8768ca6e503f346bd023833ae3ac) )
- ROM_LOAD( "1818-0834-0838-05_70-revd-system_ppu.bin", 0160000, 020000, CRC(43f62491) SHA1(a9489b37b3fa8768ca6e503f346bd023833ae3ac) )
- ROM_LOAD( "1818-1899-1898-05_60-reva-system_ppu.bin", 0140000, 020000, CRC(454af601) SHA1(54b56e67e855fd2d699a0dbef0b4d2e8c150c39b) )
- ROM_LOAD( "1818-1899-1898-05_70-reva-system_ppu.bin", 0160000, 020000, CRC(049604f2) SHA1(89bfd8e086bc9365f156966b0a62c3ac720fc627) )
-
- ROM_REGION( 0200000, "ppu_tops", ROMREGION_16BIT | ROMREGION_BE )
- ROM_LOAD( "1818-0831-0835-05_00-reva-tops_ppu.bin", 0000000, 020000, CRC(7ddce706) SHA1(746e34d3de52a17372af9a9eb1ed4974a4eae656) )
- ROM_LOAD( "1818-0831-0835-05_10-reva-tops_ppu.bin", 0020000, 020000, CRC(d7fc3d47) SHA1(a3d723fe62f047cb0c17d405d07bb0b08d08e830) )
- ROM_LOAD( "1818-1209-1208-05_00-revb-tops_ppu.bin", 0000000, 020000, CRC(0dc90614) SHA1(94c07553a62b2c86414bc95314601f90eb4e4022) )
- ROM_LOAD( "1818-1209-1208-05_10-revb-tops_ppu.bin", 0020000, 020000, CRC(4e362657) SHA1(b09098c0acd56b11ec3b72ff3e8b5a1e14ef3ae8) )
- ROM_LOAD( "1818-1592-1591-05_00-revb-tops_ppu.bin", 0000000, 020000, CRC(8cfe29a8) SHA1(f1007b6b1d3f2b603653880c44cec48b23701263) )
- ROM_LOAD( "1818-1592-1591-05_10-revb-tops_ppu.bin", 0020000, 020000, CRC(95048264) SHA1(36cfddef9d1289fdaf69596e10d95f88a520feae) )
-
- ROM_REGION( 0200000, "ppu_kbd_us", ROMREGION_16BIT | ROMREGION_BE )
- ROM_LOAD( "1818-0832-0836-05_20-revc-keyboard_us.bin", 0040000, 020000, CRC(3bf6268a) SHA1(65d7dfeaf34c74dbc86ebe5d3bb65c6bd10163cb) )
- ROM_LOAD( "1818-0832-0836-05_30-revc-keyboard_us.bin", 0060000, 020000, CRC(2dfc619c) SHA1(5c54ff502d1344907817210bfdfcab7f8d6b61bd) )
-
- ROM_REGION( 0200000, "ppu_kbd_de", ROMREGION_16BIT | ROMREGION_BE )
- ROM_LOAD( "1818-0841-0846-05_20-revc-keyboard_german.bin", 0040000, 020000, CRC(76667eca) SHA1(ac63e5d584d1f2da5668d8a9560f927f48e25e03) )
- ROM_LOAD( "1818-0841-0846-05_20-revd-keyboard_german.bin", 0060000, 020000, CRC(3bf6268a) SHA1(65d7dfeaf34c74dbc86ebe5d3bb65c6bd10163cb) )
- ROM_LOAD( "1818-0841-0846-05_30-revc-keyboard_german.bin", 0040000, 020000, CRC(2b83db22) SHA1(6eda714ce05d2d75f4c041e36b6b6df40697d94a) )
- ROM_LOAD( "1818-0841-0846-05_30-revd-keyboard_german.bin", 0060000, 020000, CRC(b4006959) SHA1(584a85f746a3b0c262fdf9e4be8e696c80cfd429) )
-#endif
-ROM_END
-
-ROM_START( hp9845c )
- ROM_REGION(0x800 , "chargen" , 0)
- ROM_LOAD("chrgen.bin" , 0 , 0x800 , CRC(fe9e844f) SHA1(0c45ae00766ceba94a19bd5e154bd6d23e208cca))
-
- ROM_REGION(0x800 , "optional_chargen" , 0)
- ROM_LOAD("optional_chrgen.bin" , 0 , 0x800 , CRC(0ecfa63b) SHA1(c295e6393d1503d903c1d2ce576fa597df9746bf))
-
- ROM_REGION(0x10000, "lpu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-lpu-standard-processor.bin", 0, 0x10000, CRC(dc266c1b) SHA1(1cf3267f13872fbbfc035b70f8b4ec6b5923f182))
-
- ROM_REGION(0x10000, "ppu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-ppu-color-enhanced-graphics.bin", 0, 0x10000, CRC(96e11edc) SHA1(3f1da50edb35dfc57ec2ecfd816a8c8230e110bd))
-ROM_END
-
-ROM_START( hp9845t )
- ROM_REGION(0x1000 , "chargen" , 0)
- ROM_LOAD("1818-1395.bin" , 0 , 0x1000 , CRC(7b555edf) SHA1(3b08e094635ef02aef9a2e37b049c61bcf1ec037))
-
- ROM_REGION(0x10000, "lpu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-lpu-standard-processor.bin", 0, 0x10000, CRC(dc266c1b) SHA1(1cf3267f13872fbbfc035b70f8b4ec6b5923f182))
-
- ROM_REGION(0x10000, "ppu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-ppu-color-enhanced-graphics.bin", 0, 0x10000, CRC(96e11edc) SHA1(3f1da50edb35dfc57ec2ecfd816a8c8230e110bd))
-ROM_END
-
-ROM_START( hp9845b_de )
- ROM_REGION(0x800 , "chargen" , 0)
- ROM_LOAD("chrgen.bin" , 0 , 0x800 , CRC(fe9e844f) SHA1(0c45ae00766ceba94a19bd5e154bd6d23e208cca))
-
- ROM_REGION(0x800 , "optional_chargen" , 0)
- ROM_LOAD("optional_chrgen.bin" , 0 , 0x800 , CRC(0ecfa63b) SHA1(c295e6393d1503d903c1d2ce576fa597df9746bf))
-
- ROM_REGION(0x10000, "lpu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-lpu-standard-processor.bin", 0, 0x10000, CRC(dc266c1b) SHA1(1cf3267f13872fbbfc035b70f8b4ec6b5923f182))
-
- ROM_REGION(0x10000, "ppu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-ppu-standard-graphics-ger.bin", 0, 0x10000, CRC(c968363d) SHA1(bc6805403371ca49d1a137f22cd254e3b0e0dbb4))
-ROM_END
-
-ROM_START( hp9845c_de )
- ROM_REGION(0x800 , "chargen" , 0)
- ROM_LOAD("chrgen.bin" , 0 , 0x800 , CRC(fe9e844f) SHA1(0c45ae00766ceba94a19bd5e154bd6d23e208cca))
-
- ROM_REGION(0x800 , "optional_chargen" , 0)
- ROM_LOAD("optional_chrgen.bin" , 0 , 0x800 , CRC(0ecfa63b) SHA1(c295e6393d1503d903c1d2ce576fa597df9746bf))
-
- ROM_REGION(0x10000, "lpu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-lpu-standard-processor.bin", 0, 0x10000, CRC(dc266c1b) SHA1(1cf3267f13872fbbfc035b70f8b4ec6b5923f182))
-
- ROM_REGION(0x10000, "ppu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-ppu-color-enhanced-graphics-ger.bin", 0, 0x10000, CRC(a7ef79ee) SHA1(637742ed8fc8201a8e7bac62654f21c5409dfb76))
-ROM_END
-
-ROM_START( hp9845t_de )
- ROM_REGION(0x1000 , "chargen" , 0)
- ROM_LOAD("1818-1395.bin" , 0 , 0x1000 , CRC(7b555edf) SHA1(3b08e094635ef02aef9a2e37b049c61bcf1ec037))
-
- ROM_REGION(0x10000, "lpu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-lpu-standard-processor.bin", 0, 0x10000, CRC(dc266c1b) SHA1(1cf3267f13872fbbfc035b70f8b4ec6b5923f182))
-
- ROM_REGION(0x10000, "ppu", ROMREGION_16BIT | ROMREGION_BE)
- ROM_LOAD("9845-ppu-color-enhanced-graphics-ger.bin", 0, 0x10000, CRC(a7ef79ee) SHA1(637742ed8fc8201a8e7bac62654f21c5409dfb76))
-ROM_END
-
-// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
-COMP( 1977, hp9845a, 0, 0, hp9845a, hp9845, hp9845_state, empty_init, "Hewlett-Packard", "9845A", MACHINE_IS_SKELETON )
-COMP( 1977, hp9845s, hp9845a, 0, hp9845a, hp9845, hp9845_state, empty_init, "Hewlett-Packard", "9845S", MACHINE_IS_SKELETON )
-COMP( 1979, hp9835a, 0, 0, hp9835a, hp9845, hp9845_state, empty_init, "Hewlett-Packard", "9835A", MACHINE_IS_SKELETON )
-COMP( 1979, hp9835b, hp9835a, 0, hp9835a, hp9845, hp9845_state, empty_init, "Hewlett-Packard", "9835B", MACHINE_IS_SKELETON )
-COMP( 1979, hp9845b, 0, 0, hp9845b, hp9845_base, hp9845b_state, empty_init, "Hewlett-Packard", "9845B", 0 )
-COMP( 1982, hp9845t, 0, 0, hp9845t, hp9845ct, hp9845t_state, empty_init, "Hewlett-Packard", "9845T", 0 )
-COMP( 1980, hp9845c, 0, 0, hp9845c, hp9845ct, hp9845c_state, empty_init, "Hewlett-Packard", "9845C", 0 )
-COMP( 1979, hp9845b_de, hp9845b, 0, hp9845b, hp9845_base_de, hp9845b_state, empty_init, "Hewlett-Packard", "9845B (Germany)", 0 )
-COMP( 1982, hp9845t_de, hp9845t, 0, hp9845t, hp9845ct_de, hp9845t_state, empty_init, "Hewlett-Packard", "9845T (Germany)", 0 )
-COMP( 1980, hp9845c_de, hp9845c, 0, hp9845c, hp9845ct_de, hp9845c_state, empty_init, "Hewlett-Packard", "9845C (Germany)", 0 )