mirror of
https://github.com/holub/mame
synced 2025-07-05 01:48:29 +03:00
brother/pn8800fxb: Major improvements
* Add timer interrupt * Add keyboard emulation * Improve video emulation, support more modes * Cleanup low memory emulation
This commit is contained in:
parent
fdad8d351c
commit
a0a91cf41e
@ -17,16 +17,27 @@
|
|||||||
- XTAL XT5 16.0MHz (near FDC)
|
- XTAL XT5 16.0MHz (near FDC)
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
- Almost everything, draws the initial screen
|
- Fix ROM banking (ROM self-test shows NG)
|
||||||
|
- Improve video emulation (offset, modes, etc.)
|
||||||
|
- RTC
|
||||||
|
- Floppy
|
||||||
|
- Buzzer
|
||||||
|
- Centronics
|
||||||
|
- Modem
|
||||||
|
- Soft power off/on
|
||||||
|
- RAM contents should be retained when turning off
|
||||||
|
- Bookman (unlikely to make progress, extra PCB contains custom CPU)
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
- There is a serially connected daughterbord containing the Bookman logic
|
- There is a serially connected daughterbord containing the Bookman logic
|
||||||
|
- Press CODE+SHIFT+BS on the main menu for a self-test screen
|
||||||
|
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
|
|
||||||
#include "cpu/z180/z180.h"
|
#include "cpu/z180/z180.h"
|
||||||
|
#include "machine/timer.h"
|
||||||
|
|
||||||
#include "emupal.h"
|
#include "emupal.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
@ -46,7 +57,9 @@ public:
|
|||||||
m_maincpu(*this, "maincpu"),
|
m_maincpu(*this, "maincpu"),
|
||||||
m_rombank(*this, "rombank"),
|
m_rombank(*this, "rombank"),
|
||||||
m_palette(*this, "palette"),
|
m_palette(*this, "palette"),
|
||||||
m_gfxdecode(*this, "gfxdecode")
|
m_gfxdecode(*this, "gfxdecode"),
|
||||||
|
m_keys(*this, "KO%u", 0U),
|
||||||
|
m_lomem_view(*this, "lomem")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void pn8800fxb(machine_config &config);
|
void pn8800fxb(machine_config &config);
|
||||||
@ -60,29 +73,43 @@ private:
|
|||||||
required_memory_bank m_rombank;
|
required_memory_bank m_rombank;
|
||||||
required_device<palette_device> m_palette;
|
required_device<palette_device> m_palette;
|
||||||
required_device<gfxdecode_device> m_gfxdecode;
|
required_device<gfxdecode_device> m_gfxdecode;
|
||||||
|
required_ioport_array<9> m_keys;
|
||||||
|
memory_view m_lomem_view;
|
||||||
|
|
||||||
|
uint8_t m_key_select;
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> m_vram;
|
std::unique_ptr<uint8_t[]> m_vram;
|
||||||
|
uint16_t m_cursor_addr;
|
||||||
uint16_t m_video_addr;
|
uint16_t m_video_addr;
|
||||||
uint8_t m_video_ctrl;
|
uint8_t m_video_ctrl;
|
||||||
|
uint8_t m_video_offset;
|
||||||
|
uint8_t m_cursor_ctrl;
|
||||||
uint8_t m_mem_change;
|
uint8_t m_mem_change;
|
||||||
|
|
||||||
void mem_map(address_map &map);
|
void mem_map(address_map &map);
|
||||||
void io_map(address_map &map);
|
void io_map(address_map &map);
|
||||||
|
|
||||||
|
uint8_t keyboard_r();
|
||||||
|
void keyboard_w(uint8_t data);
|
||||||
|
|
||||||
void palette(palette_device &palette) const;
|
void palette(palette_device &palette) const;
|
||||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||||
|
|
||||||
|
void cursor_addr_lo_w(uint8_t data);
|
||||||
|
void cursor_addr_hi_w(uint8_t data);
|
||||||
void video_addr_lo_w(uint8_t data);
|
void video_addr_lo_w(uint8_t data);
|
||||||
void video_addr_hi_w(uint8_t data);
|
void video_addr_hi_w(uint8_t data);
|
||||||
uint8_t video_data_r();
|
uint8_t video_data_r();
|
||||||
void video_data_w(uint8_t data);
|
void video_data_w(uint8_t data);
|
||||||
uint8_t video_ctrl_r();
|
uint8_t video_ctrl_r();
|
||||||
void video_ctrl_w(uint8_t data);
|
void video_ctrl_w(uint8_t data);
|
||||||
|
void video_offset_w(uint8_t data);
|
||||||
|
void cursor_ctrl_w(uint8_t data);
|
||||||
|
|
||||||
void mem_change_w(uint8_t data);
|
void mem_change_w(uint8_t data);
|
||||||
void bank_select_w(uint8_t data);
|
void bank_select_w(uint8_t data);
|
||||||
uint8_t lo_mem_r(offs_t offset);
|
void int_ack_w(uint8_t data);
|
||||||
void lo_mem_w(offs_t offset, uint8_t data);
|
TIMER_DEVICE_CALLBACK_MEMBER(int1_timer);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -93,43 +120,49 @@ private:
|
|||||||
void pn8800fxb_state::mem_map(address_map &map)
|
void pn8800fxb_state::mem_map(address_map &map)
|
||||||
{
|
{
|
||||||
map(0x00000, 0x01fff).rom();
|
map(0x00000, 0x01fff).rom();
|
||||||
map(0x02000, 0x07fff).rw(FUNC(pn8800fxb_state::lo_mem_r), FUNC(pn8800fxb_state::lo_mem_w));
|
map(0x02000, 0x05fff).ram().share("window1");
|
||||||
|
map(0x06000, 0x07fff).view(m_lomem_view);
|
||||||
|
m_lomem_view[0](0x06000, 0x07fff).ram().share("window2");
|
||||||
|
m_lomem_view[1](0x06000, 0x07fff).rom().region("maincpu", 0x06000);
|
||||||
map(0x08000, 0x3ffff).rom();
|
map(0x08000, 0x3ffff).rom();
|
||||||
map(0x40000, 0x41fff).unmaprw();
|
map(0x40000, 0x41fff).unmaprw();
|
||||||
map(0x42000, 0x45fff).rom().region("maincpu", 0x2000);
|
map(0x42000, 0x45fff).rom().region("maincpu", 0x02000);
|
||||||
map(0x46000, 0x4ffff).unmaprw();
|
map(0x46000, 0x4ffff).unmaprw();
|
||||||
map(0x50000, 0x5ffff).bankr(m_rombank);
|
map(0x50000, 0x5ffff).bankr(m_rombank);
|
||||||
map(0x60000, 0x7ffff).ram();
|
map(0x60000, 0x61fff).ram();
|
||||||
|
map(0x62000, 0x65fff).ram().share("window1");
|
||||||
|
map(0x66000, 0x67fff).ram().share("window2");
|
||||||
|
map(0x68000, 0x7ffff).ram();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pn8800fxb_state::io_map(address_map &map)
|
void pn8800fxb_state::io_map(address_map &map)
|
||||||
{
|
{
|
||||||
map.global_mask(0xff);
|
map.global_mask(0xff);
|
||||||
map(0x00, 0x3f).noprw(); // z180 internal
|
map(0x00, 0x3f).noprw(); // z180 internal
|
||||||
// 70 cursor
|
map(0x70, 0x70).w(FUNC(pn8800fxb_state::cursor_addr_lo_w));
|
||||||
// 71 cursor
|
map(0x71, 0x71).w(FUNC(pn8800fxb_state::cursor_addr_hi_w));
|
||||||
map(0x72, 0x72).w(FUNC(pn8800fxb_state::video_addr_lo_w));
|
map(0x72, 0x72).w(FUNC(pn8800fxb_state::video_addr_lo_w));
|
||||||
map(0x73, 0x73).w(FUNC(pn8800fxb_state::video_addr_hi_w));
|
map(0x73, 0x73).w(FUNC(pn8800fxb_state::video_addr_hi_w));
|
||||||
map(0x74, 0x74).rw(FUNC(pn8800fxb_state::video_data_r), FUNC(pn8800fxb_state::video_data_w));
|
map(0x74, 0x74).rw(FUNC(pn8800fxb_state::video_data_r), FUNC(pn8800fxb_state::video_data_w));
|
||||||
map(0x75, 0x75).rw(FUNC(pn8800fxb_state::video_ctrl_r), FUNC(pn8800fxb_state::video_ctrl_w));
|
map(0x75, 0x75).rw(FUNC(pn8800fxb_state::video_ctrl_r), FUNC(pn8800fxb_state::video_ctrl_w));
|
||||||
// 76 display offset
|
map(0x76, 0x76).w(FUNC(pn8800fxb_state::video_offset_w));
|
||||||
// 77 cursor control
|
map(0x77, 0x77).w(FUNC(pn8800fxb_state::cursor_ctrl_w));
|
||||||
// 78-7f mode select
|
// 78-7f mode select
|
||||||
// 80-87 fdc
|
// 80-87 fdc
|
||||||
// 88-8f input
|
// 88-8f input
|
||||||
map(0x90, 0x90).mirror(0x07).w(FUNC(pn8800fxb_state::mem_change_w));
|
map(0x90, 0x90).mirror(0x07).w(FUNC(pn8800fxb_state::mem_change_w));
|
||||||
// 98-9f rs break
|
// 98-9f rs break
|
||||||
// a0-a7 rs232
|
// a0-a7 rs232
|
||||||
// a8-af not used
|
map(0xa8, 0xa8).mirror(0x07).nopr(); // "not used" - but read often
|
||||||
// b0-b7 power supply
|
// b0-b7 power supply
|
||||||
// b8-bf keyboard
|
map(0xb8, 0xb8).rw(FUNC(pn8800fxb_state::keyboard_r), FUNC(pn8800fxb_state::keyboard_w));
|
||||||
// c0-c7 cdcc data
|
// c0-c7 cdcc data
|
||||||
// c8-cf cdcc control
|
// c8-cf cdcc control
|
||||||
// d0-df rtc
|
map(0xd0, 0xdf).noprw(); // rtc
|
||||||
map(0xe0, 0xe0).mirror(0x07).w(FUNC(pn8800fxb_state::bank_select_w));
|
map(0xe0, 0xe0).mirror(0x07).w(FUNC(pn8800fxb_state::bank_select_w));
|
||||||
// e8-ef ga test
|
// e8-ef ga test
|
||||||
// f0-f7 buzzer
|
// f0-f7 buzzer
|
||||||
// f8-ff interrupt ack
|
map(0xf8, 0xf8).mirror(0x07).w(FUNC(pn8800fxb_state::int_ack_w));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -138,8 +171,112 @@ void pn8800fxb_state::io_map(address_map &map)
|
|||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
|
|
||||||
static INPUT_PORTS_START( pn8800fxb )
|
static INPUT_PORTS_START( pn8800fxb )
|
||||||
|
PORT_START("KO0")
|
||||||
|
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
|
||||||
|
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_NAME("\xe2\x86\x90 EXPR") // ←
|
||||||
|
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) PORT_NAME("BS")
|
||||||
|
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_NAME("RETURN IND CLR =")
|
||||||
|
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_NAME("\xe2\x86\x91 PRE S") // ↑
|
||||||
|
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
|
||||||
|
|
||||||
|
PORT_START("KO1")
|
||||||
|
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[') PORT_CHAR(']') PORT_NAME(u8"[ ] ½ ¼")
|
||||||
|
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') PORT_NAME("= + L OUT")
|
||||||
|
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_NAME("0 ) W OUT")
|
||||||
|
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') PORT_NAME("- _ -")
|
||||||
|
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_NAME("p P PRINT +")
|
||||||
|
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') PORT_NAME("/ ? /")
|
||||||
|
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
|
||||||
|
PORT_START("KO2")
|
||||||
|
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_NAME("\xe2\x86\x93 NEXT S") // ↓
|
||||||
|
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
|
||||||
|
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_NAME("l L L IND 3")
|
||||||
|
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_NAME("9 ( T CLR 9")
|
||||||
|
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_NAME("o O JUST 6")
|
||||||
|
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_CHAR(']') PORT_NAME(". > ] .")
|
||||||
|
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') PORT_NAME("; : *")
|
||||||
|
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_NAME("\xe2\x86\x92 RELOC") // →
|
||||||
|
|
||||||
|
PORT_START("KO3")
|
||||||
|
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_NAME("k K KB 2")
|
||||||
|
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_NAME("8 * DT SET 8")
|
||||||
|
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
|
||||||
|
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_NAME("7 & T SET 7")
|
||||||
|
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_NAME("i I INSERT 5")
|
||||||
|
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') PORT_CHAR('[')
|
||||||
|
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
|
||||||
|
PORT_START("KO4")
|
||||||
|
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
|
||||||
|
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_NAME("j J LAYOUT 1")
|
||||||
|
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR('{') PORT_NAME("y Y { <")
|
||||||
|
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR('}') PORT_NAME("u U } >")
|
||||||
|
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_NAME("h H HELP")
|
||||||
|
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_NAME("m M M CODE 0")
|
||||||
|
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
|
||||||
|
PORT_START("KO5")
|
||||||
|
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
|
||||||
|
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
|
||||||
|
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_NAME("t T TEMP")
|
||||||
|
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
|
||||||
|
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_NAME("g G GOTO")
|
||||||
|
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'`')
|
||||||
|
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
|
||||||
|
PORT_START("KO6")
|
||||||
|
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) PORT_NAME("CANCEL")
|
||||||
|
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
|
||||||
|
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_NAME("3 # M REL")
|
||||||
|
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_NAME("5 % R MAR")
|
||||||
|
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_NAME("4 $ L MAR")
|
||||||
|
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
|
||||||
|
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
|
||||||
|
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_NAME("MENU FILE")
|
||||||
|
|
||||||
|
PORT_START("KO7")
|
||||||
|
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR('|') PORT_NAME(u8"x X | ²")
|
||||||
|
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'¢')
|
||||||
|
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) PORT_NAME("TAB P IND")
|
||||||
|
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PORT_NAME("2 @ LINE")
|
||||||
|
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_NAME("s S CALC")
|
||||||
|
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
|
||||||
|
PORT_START("KO8")
|
||||||
|
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||||
|
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_NAME("a A ABBR")
|
||||||
|
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
|
||||||
|
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR(U'`') PORT_CHAR('~') PORT_NAME(u8"` ~ SPELL ± °")
|
||||||
|
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_NAME("1 ! PITCH")
|
||||||
|
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("CAPS SHIFT LOCK")
|
||||||
|
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR('\\') PORT_NAME(u8"z Z \\ §")
|
||||||
|
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("CODE")
|
||||||
INPUT_PORTS_END
|
INPUT_PORTS_END
|
||||||
|
|
||||||
|
uint8_t pn8800fxb_state::keyboard_r()
|
||||||
|
{
|
||||||
|
if (m_key_select < 9)
|
||||||
|
return m_keys[m_key_select]->read();
|
||||||
|
else
|
||||||
|
logerror("keyboard_r from %02x\n", m_key_select);
|
||||||
|
|
||||||
|
return 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pn8800fxb_state::keyboard_w(uint8_t data)
|
||||||
|
{
|
||||||
|
m_key_select = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
// VIDEO EMULATION
|
// VIDEO EMULATION
|
||||||
@ -147,8 +284,8 @@ INPUT_PORTS_END
|
|||||||
|
|
||||||
void pn8800fxb_state::palette(palette_device &palette) const
|
void pn8800fxb_state::palette(palette_device &palette) const
|
||||||
{
|
{
|
||||||
palette.set_pen_color(0, rgb_t(131, 238, 47));
|
palette.set_pen_color(0, rgb_t(86, 228, 94));
|
||||||
palette.set_pen_color(1, rgb_t(31, 84, 67));
|
palette.set_pen_color(1, rgb_t(58, 86, 143));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pn8800fxb_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
uint32_t pn8800fxb_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||||
@ -157,26 +294,99 @@ uint32_t pn8800fxb_state::screen_update(screen_device &screen, bitmap_rgb32 &bit
|
|||||||
|
|
||||||
const pen_t *const pen = m_palette->pens();
|
const pen_t *const pen = m_palette->pens();
|
||||||
|
|
||||||
for (int y = 0; y < 22; y++)
|
// 22 line text mode doesn't cover the full screen
|
||||||
|
bitmap.fill(pen[0], cliprect);
|
||||||
|
|
||||||
|
if (BIT(m_video_ctrl, 0))
|
||||||
{
|
{
|
||||||
for (int x = 0; x < 80; x++)
|
if (BIT(m_video_ctrl, 3))
|
||||||
{
|
{
|
||||||
//uint8_t attr = m_vram[y * 0x100 + x * 2 + 0];
|
// graphics mode
|
||||||
uint8_t code = m_vram[y * 0x100 + x * 2 + 1];
|
uint8_t *vram = m_vram.get();
|
||||||
|
|
||||||
// draw 9 lines
|
// left 512 pixels of screen
|
||||||
for (int l = 0; l < 9; l++)
|
for (int y = 0; y < 200; y++)
|
||||||
|
for (int x = 0; x < 512; x += 8, vram++)
|
||||||
|
for (int p = 0; p < 8; p++)
|
||||||
|
bitmap.pix(y, x + p) = pen[BIT(*vram, 7 - p)];
|
||||||
|
|
||||||
|
// right 128 pixels of screen
|
||||||
|
for (int y = 0; y < 200; y++)
|
||||||
|
for (int x = 0; x < 128; x += 8, vram++)
|
||||||
|
for (int p = 0; p < 8; p++)
|
||||||
|
bitmap.pix(y, 512 + x + p) = pen[BIT(*vram, 7 - p)];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// text mode
|
||||||
|
int lines = BIT(m_video_ctrl, 5) ? 25 : 22;
|
||||||
|
|
||||||
|
for (int y = 0; y < lines; y++)
|
||||||
{
|
{
|
||||||
uint8_t data = 0x00;
|
for (int x = 0; x < 80; x++)
|
||||||
|
|
||||||
// line 9 always blank?
|
|
||||||
if (l < 8)
|
|
||||||
data = m_vram[0x3000 + (code << 3) + l];
|
|
||||||
|
|
||||||
// draw 8 pixels of the character
|
|
||||||
for (int b = 0; b < 8; b++)
|
|
||||||
{
|
{
|
||||||
bitmap.pix(y * 9 + l, x * 8 + b) = pen[BIT(data, 7 - b)];
|
// attributes
|
||||||
|
//
|
||||||
|
// 7------- unknown
|
||||||
|
// -6------ subscript
|
||||||
|
// --5----- superscript
|
||||||
|
// ---4---- invert
|
||||||
|
// ----3--- vertical line
|
||||||
|
// -----2-- code high bit
|
||||||
|
// ------1- overline
|
||||||
|
// -------0 underline
|
||||||
|
|
||||||
|
uint8_t attr = m_vram[y * 0x100 + x * 2 + 0];
|
||||||
|
uint16_t code = m_vram[y * 0x100 + x * 2 + 1];
|
||||||
|
|
||||||
|
// apply code high bit (high table contains bold characters)
|
||||||
|
code |= (BIT(attr, 2) << 8) | code;
|
||||||
|
|
||||||
|
bool cursor_active = (y * 0x100 + x * 2) == (m_cursor_addr << 1);
|
||||||
|
|
||||||
|
// draw 8 or 9 lines
|
||||||
|
for (int l = 0; l < 9; l++)
|
||||||
|
{
|
||||||
|
uint8_t data = 0x00;
|
||||||
|
|
||||||
|
// skip empty line in 25 line mode
|
||||||
|
if (lines == 25 && l == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// character data (or cursor) in lines 1 to 8
|
||||||
|
if (l > 0)
|
||||||
|
{
|
||||||
|
if (cursor_active)
|
||||||
|
data = 0xff;
|
||||||
|
else
|
||||||
|
data = m_vram[0x3000 + (code << 3) + l - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// underline?
|
||||||
|
if (BIT(attr, 0) && l == 8)
|
||||||
|
data = 0xff;
|
||||||
|
|
||||||
|
// overline?
|
||||||
|
if (BIT(attr, 1) && l == 0)
|
||||||
|
data = 0xff;
|
||||||
|
|
||||||
|
// vertical line?
|
||||||
|
if (BIT(attr, 3))
|
||||||
|
data |= 0x01;
|
||||||
|
|
||||||
|
// invert?
|
||||||
|
if (BIT(attr, 4))
|
||||||
|
data ^= 0xff;
|
||||||
|
|
||||||
|
// draw 8 pixels of the character
|
||||||
|
for (int b = 0; b < 8; b++)
|
||||||
|
{
|
||||||
|
if (lines == 25)
|
||||||
|
bitmap.pix(y * 8 + l - 1, x * 8 + b) = pen[BIT(data, 7 - b)];
|
||||||
|
else
|
||||||
|
bitmap.pix(y * 9 + l, x * 8 + b) = pen[BIT(data, 7 - b)];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,6 +395,17 @@ uint32_t pn8800fxb_state::screen_update(screen_device &screen, bitmap_rgb32 &bit
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pn8800fxb_state::cursor_addr_lo_w(uint8_t data)
|
||||||
|
{
|
||||||
|
m_cursor_addr = (m_cursor_addr & 0xff00) | (data << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pn8800fxb_state::cursor_addr_hi_w(uint8_t data)
|
||||||
|
{
|
||||||
|
data &= 0x0f;
|
||||||
|
m_cursor_addr = (data << 8) | (m_cursor_addr & 0x00ff);
|
||||||
|
}
|
||||||
|
|
||||||
void pn8800fxb_state::video_addr_lo_w(uint8_t data)
|
void pn8800fxb_state::video_addr_lo_w(uint8_t data)
|
||||||
{
|
{
|
||||||
m_video_addr = (m_video_addr & 0xff00) | (data << 0);
|
m_video_addr = (m_video_addr & 0xff00) | (data << 0);
|
||||||
@ -213,8 +434,8 @@ uint8_t pn8800fxb_state::video_ctrl_r()
|
|||||||
{
|
{
|
||||||
// 7------- mm
|
// 7------- mm
|
||||||
// -6------ not used
|
// -6------ not used
|
||||||
// --5----- 8r
|
// --5----- 8r (in text mode, 8 pixel height line instead of 9?)
|
||||||
// ---4---- 8lp
|
// ---4---- blp
|
||||||
// ----3--- grph
|
// ----3--- grph
|
||||||
// -----2-- not used
|
// -----2-- not used
|
||||||
// ------1- rev
|
// ------1- rev
|
||||||
@ -225,11 +446,33 @@ uint8_t pn8800fxb_state::video_ctrl_r()
|
|||||||
|
|
||||||
void pn8800fxb_state::video_ctrl_w(uint8_t data)
|
void pn8800fxb_state::video_ctrl_w(uint8_t data)
|
||||||
{
|
{
|
||||||
logerror("video_ctrl_w: %02x\n", data);
|
if (0)
|
||||||
|
logerror("video_ctrl_w: %02x\n", data);
|
||||||
|
|
||||||
m_video_ctrl = data;
|
m_video_ctrl = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pn8800fxb_state::video_offset_w(uint8_t data)
|
||||||
|
{
|
||||||
|
// 765----- not used
|
||||||
|
// ---4---- oy
|
||||||
|
// ----3210 ox6 to ox3
|
||||||
|
|
||||||
|
m_video_offset = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pn8800fxb_state::cursor_ctrl_w(uint8_t data)
|
||||||
|
{
|
||||||
|
// 7------- curu
|
||||||
|
// -6------ curl
|
||||||
|
// --5----- cbkh
|
||||||
|
// ---4---- crev
|
||||||
|
// ----3--- curb
|
||||||
|
// -----210 not used
|
||||||
|
|
||||||
|
m_cursor_ctrl = data;
|
||||||
|
}
|
||||||
|
|
||||||
static const gfx_layout charlayout =
|
static const gfx_layout charlayout =
|
||||||
{
|
{
|
||||||
8, 8,
|
8, 8,
|
||||||
@ -249,29 +492,6 @@ GFXDECODE_END
|
|||||||
// MACHINE EMULATION
|
// MACHINE EMULATION
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
|
|
||||||
uint8_t pn8800fxb_state::lo_mem_r(offs_t offset)
|
|
||||||
{
|
|
||||||
uint8_t data = 0xff;
|
|
||||||
offset += 0x2000;
|
|
||||||
|
|
||||||
if (offset < 0x6000)
|
|
||||||
data = m_maincpu->space(AS_PROGRAM).read_byte(0x60000 + offset);
|
|
||||||
else
|
|
||||||
data = memregion("maincpu")->base()[offset];
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pn8800fxb_state::lo_mem_w(offs_t offset, uint8_t data)
|
|
||||||
{
|
|
||||||
offset += 0x2000;
|
|
||||||
|
|
||||||
if (offset < 0x6000)
|
|
||||||
m_maincpu->space(AS_PROGRAM).write_byte(0x60000 + offset, data);
|
|
||||||
else
|
|
||||||
logerror("write 6000-7fff %04x %02x\n", offset, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pn8800fxb_state::mem_change_w(uint8_t data)
|
void pn8800fxb_state::mem_change_w(uint8_t data)
|
||||||
{
|
{
|
||||||
// 7------- dua
|
// 7------- dua
|
||||||
@ -280,9 +500,11 @@ void pn8800fxb_state::mem_change_w(uint8_t data)
|
|||||||
// ------1- dicsel
|
// ------1- dicsel
|
||||||
// -------0 rgex
|
// -------0 rgex
|
||||||
|
|
||||||
logerror("mem_change_w: dua %d ramin %d dicsel %d rgex %d\n", BIT(data, 7), BIT(data, 6), BIT(data, 1), BIT(data, 0));
|
if (data != 0x40)
|
||||||
|
logerror("mem_change_w: dua %d ramin %d dicsel %d rgex %d\n", BIT(data, 7), BIT(data, 6), BIT(data, 1), BIT(data, 0));
|
||||||
|
|
||||||
m_mem_change = data;
|
m_mem_change = data;
|
||||||
|
m_lomem_view.select(BIT(data, 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pn8800fxb_state::bank_select_w(uint8_t data)
|
void pn8800fxb_state::bank_select_w(uint8_t data)
|
||||||
@ -290,10 +512,21 @@ void pn8800fxb_state::bank_select_w(uint8_t data)
|
|||||||
// 7654---- not used
|
// 7654---- not used
|
||||||
// ----3210 bank selection
|
// ----3210 bank selection
|
||||||
|
|
||||||
logerror("bank_select_w: %02x\n", data);
|
if (0)
|
||||||
|
logerror("bank_select_w: %02x\n", data);
|
||||||
|
|
||||||
if (data < 12)
|
if (data < 12)
|
||||||
m_rombank->set_entry(data ^ 8); // TODO, but works for now
|
m_rombank->set_entry(data & 0x07); // TODO, but works for now
|
||||||
|
}
|
||||||
|
|
||||||
|
void pn8800fxb_state::int_ack_w(uint8_t data)
|
||||||
|
{
|
||||||
|
m_maincpu->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TIMER_DEVICE_CALLBACK_MEMBER( pn8800fxb_state::int1_timer )
|
||||||
|
{
|
||||||
|
m_maincpu->set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pn8800fxb_state::machine_start()
|
void pn8800fxb_state::machine_start()
|
||||||
@ -308,15 +541,20 @@ void pn8800fxb_state::machine_start()
|
|||||||
m_rombank->configure_entries(0, 12, memregion("maincpu")->base() + 0x40000, 0x10000);
|
m_rombank->configure_entries(0, 12, memregion("maincpu")->base() + 0x40000, 0x10000);
|
||||||
|
|
||||||
// register for save states
|
// register for save states
|
||||||
|
save_item(NAME(m_key_select));
|
||||||
save_pointer(NAME(m_vram), 0x4000);
|
save_pointer(NAME(m_vram), 0x4000);
|
||||||
|
save_item(NAME(m_cursor_addr));
|
||||||
save_item(NAME(m_video_addr));
|
save_item(NAME(m_video_addr));
|
||||||
save_item(NAME(m_video_ctrl));
|
save_item(NAME(m_video_ctrl));
|
||||||
|
save_item(NAME(m_video_offset));
|
||||||
|
save_item(NAME(m_cursor_ctrl));
|
||||||
save_item(NAME(m_mem_change));
|
save_item(NAME(m_mem_change));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pn8800fxb_state::machine_reset()
|
void pn8800fxb_state::machine_reset()
|
||||||
{
|
{
|
||||||
m_mem_change = 0x00;
|
m_mem_change = 0x00;
|
||||||
|
m_lomem_view.select(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -330,6 +568,8 @@ void pn8800fxb_state::pn8800fxb(machine_config &config)
|
|||||||
m_maincpu->set_addrmap(AS_PROGRAM, &pn8800fxb_state::mem_map);
|
m_maincpu->set_addrmap(AS_PROGRAM, &pn8800fxb_state::mem_map);
|
||||||
m_maincpu->set_addrmap(AS_IO, &pn8800fxb_state::io_map);
|
m_maincpu->set_addrmap(AS_IO, &pn8800fxb_state::io_map);
|
||||||
|
|
||||||
|
TIMER(config, "1khz").configure_periodic(FUNC(pn8800fxb_state::int1_timer), attotime::from_hz(1000));
|
||||||
|
|
||||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
|
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
|
||||||
screen.set_size(640, 200);
|
screen.set_size(640, 200);
|
||||||
screen.set_visarea_full();
|
screen.set_visarea_full();
|
||||||
|
Loading…
Reference in New Issue
Block a user