From 461df167c642f057e8d77a26f858260d5212899c Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 10 Dec 2014 00:16:41 +1100 Subject: (MESS) excalibur : added keyboard, system is usable. Can save and load cassettes. (nw) --- src/mess/drivers/excali64.c | 147 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 136 insertions(+), 11 deletions(-) diff --git a/src/mess/drivers/excali64.c b/src/mess/drivers/excali64.c index af1d2c121a7..0af9983b2e3 100644 --- a/src/mess/drivers/excali64.c +++ b/src/mess/drivers/excali64.c @@ -8,6 +8,19 @@ Skeleton driver created on 2014-12-09. Chips: Z80A, 8251, 8253, 8255, 6845 +ToDo: +- Some keys can be connected to more than one position in the matrix. Need to + determine the correct positions. +- The position of the "Line Insert" key is unknown. +- The video section has attributes and colour, none of this is done. +- Disk controller +- Banking +- The schematic shows the audio counter connected to 2MHz, but this produces + sounds that are too high. Connected to 1MHz for now. +- Serial +- Parallel / Centronics +- Need software + ****************************************************************************/ #include "emu.h" @@ -32,11 +45,14 @@ public: , m_palette(*this, "palette") , m_maincpu(*this, "maincpu") , m_cass(*this, "cassette") + , m_io_keyboard(*this, "KEY") { } DECLARE_DRIVER_INIT(excali64); + DECLARE_WRITE8_MEMBER(ppib_w); DECLARE_READ8_MEMBER(ppic_r); DECLARE_WRITE8_MEMBER(ppic_w); + DECLARE_READ8_MEMBER(port00_r); DECLARE_READ8_MEMBER(port50_r); DECLARE_WRITE8_MEMBER(port70_w); DECLARE_WRITE8_MEMBER(video_w); @@ -44,32 +60,34 @@ public: DECLARE_WRITE_LINE_MEMBER(crtc_de); DECLARE_WRITE_LINE_MEMBER(crtc_vs); - const UINT8 *m_p_chargen; - UINT8 *m_p_videoram; required_device m_palette; private: + const UINT8 *m_p_chargen; + UINT8 *m_p_videoram; UINT8 m_sys_status; + UINT8 m_kbdrow; bool m_crtc_vs; bool m_crtc_de; required_device m_maincpu; required_device m_cass; + required_ioport_array<8> m_io_keyboard; }; static ADDRESS_MAP_START(excali64_mem, AS_PROGRAM, 8, excali64_state) AM_RANGE(0x0000, 0x1FFF) AM_ROM - AM_RANGE(0x2000, 0x2FFF) AM_ROM AM_WRITE(video_w) - AM_RANGE(0x3000, 0x3FFF) AM_ROM + AM_RANGE(0x2000, 0x3FFF) AM_ROM AM_WRITE(video_w) AM_RANGE(0x4000, 0xFFFF) AM_RAM ADDRESS_MAP_END static ADDRESS_MAP_START(excali64_io, AS_IO, 8, excali64_state) ADDRESS_MAP_GLOBAL_MASK(0xff) + AM_RANGE(0x00, 0x0f) AM_READ(port00_r) AM_RANGE(0x10, 0x10) AM_MIRROR(0x0e) AM_DEVREADWRITE("uart",i8251_device, data_r, data_w) AM_RANGE(0x11, 0x11) AM_MIRROR(0x0e) AM_DEVREADWRITE("uart", i8251_device, status_r, control_w) AM_RANGE(0x20, 0x23) AM_MIRROR(0x0c) AM_DEVREADWRITE("pit", pit8253_device, read, write) - AM_RANGE(0x30, 0x30) AM_DEVREADWRITE("crtc", mc6845_device, status_r, address_w) - AM_RANGE(0x31, 0x31) AM_DEVREADWRITE("crtc", mc6845_device, register_r, register_w) + AM_RANGE(0x30, 0x30) AM_MIRROR(0x0e) AM_DEVREADWRITE("crtc", mc6845_device, status_r, address_w) + AM_RANGE(0x31, 0x31) AM_MIRROR(0x0e) AM_DEVREADWRITE("crtc", mc6845_device, register_r, register_w) AM_RANGE(0x50, 0x5f) AM_READ(port50_r) AM_RANGE(0x60, 0x63) AM_MIRROR(0x0c) AM_DEVREADWRITE("ppi", i8255_device, read, write) AM_RANGE(0x70, 0x7f) AM_WRITE(port70_w) @@ -78,8 +96,102 @@ ADDRESS_MAP_END /* Input ports */ static INPUT_PORTS_START( excali64 ) + //PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LINEFEED") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(0x0a)//H + //PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("REPT") PORT_CODE(KEYCODE_LALT)//0x11 + //PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("(Down)") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))//B + //PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("(Up)") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) + //PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("(Fire)") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT)) + //PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\ |")PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') PORT_CHAR(0x1c) + //PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("(Right)") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) + //PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("BRK") PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(0x03) + //PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("(Left)") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) + + PORT_START("KEY.0") /* line 0 */ + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHAR('R') PORT_CHAR(0x12) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHAR('W') PORT_CHAR(0x17) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CHAR('E') PORT_CHAR(0x05) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("TAB") PORT_CODE(KEYCODE_TAB) PORT_CHAR(0x09) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CAPSLOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHAR('A') PORT_CHAR(0x01) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHAR('Q') PORT_CHAR(0x11) + + PORT_START("KEY.1") /* line 1 */ + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2)//= + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) // space + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) // F1 + + PORT_START("KEY.2") /* line 2 */ + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHAR('M') PORT_CHAR(0x0d) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHAR('B') PORT_CHAR(0x02) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) //B + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHAR('N') PORT_CHAR(0x0e) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) //N + + PORT_START("KEY.3") /* line 3 */ + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x27) PORT_CHAR(0x22) PORT_CHAR(0x27) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('L') PORT_CHAR(0x0c) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('J') PORT_CHAR(0x0a) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHAR('G') PORT_CHAR(0x07) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHAR('K') PORT_CHAR(0x0b) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHAR('H') PORT_CHAR(0x08) + + PORT_START("KEY.4") /* line 4 */ + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2 @") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(0x7f) PORT_CHAR(0x7f) PORT_CHAR(0x1f) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC) PORT_CHAR(0x1b) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) //1 + + PORT_START("KEY.5") /* line 5 */ + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[ {") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') PORT_CHAR(0x1b) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('O') PORT_CHAR(0x0f) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("] }") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') PORT_CHAR(0x1d) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('P') PORT_CHAR(0x10) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHAR('U') PORT_CHAR(0x15) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHAR('T') PORT_CHAR(0x14) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHAR('I') PORT_CHAR(0x09)//0x12 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHAR('Y') PORT_CHAR(0x19)//0x14 + + PORT_START("KEY.6") /* line 6 */ + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHAR('F') PORT_CHAR(0x06) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('X') PORT_CHAR(0x18) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHAR('V') PORT_CHAR(0x16) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHAR('C') PORT_CHAR(0x03) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('D') PORT_CHAR(0x04) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHAR('S') PORT_CHAR(0x13) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHAR('Z') PORT_CHAR(0x1a) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) //Z + + PORT_START("KEY.7") /* line 7 */ + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("= +") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') PORT_CHAR('=') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0 )") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(0x08) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 *") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6 ^") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 (") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7 &") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') INPUT_PORTS_END +WRITE8_MEMBER( excali64_state::ppib_w ) +{ + m_kbdrow = data; +} + READ8_MEMBER( excali64_state::ppic_r ) { UINT8 data = 0xf7; @@ -87,6 +199,19 @@ READ8_MEMBER( excali64_state::ppic_r ) return data; } +READ8_MEMBER( excali64_state::port00_r ) +{ + UINT8 data = 0xff; + + for (int i = 0; i < 8; i++) + { + if (!BIT(m_kbdrow, i)) + data &= m_io_keyboard[i]->read(); + } + + return data; +} + /* d0 : /rom ; screen d1 : ram on @@ -140,7 +265,7 @@ DRIVER_INIT_MEMBER( excali64_state, excali64 ) MC6845_UPDATE_ROW( excali64_state::update_row ) { const rgb_t *palette = m_palette->palette()->entry_list_raw(); - UINT8 chr,gfx=0; + UINT8 chr,gfx; UINT16 mem,x; UINT32 *p = &bitmap.pix32(y); @@ -175,7 +300,7 @@ static MACHINE_CONFIG_START( excali64, excali64_state ) //MCFG_I8251_RTS_HANDLER(DEVWRITELINE("rs232", rs232_port_device, write_rts)) MCFG_DEVICE_ADD("pit", PIT8253, 0) - MCFG_PIT8253_CLK0(XTAL_16MHz / 8) /* Timer 0: tone gen for speaker */ + MCFG_PIT8253_CLK0(XTAL_16MHz / 16) /* Timer 0: tone gen for speaker */ MCFG_PIT8253_OUT0_HANDLER(DEVWRITELINE("speaker", speaker_sound_device, level_w)) MCFG_PIT8253_CLK1(XTAL_16MHz / 8) /* Timer 1: baud rate gen for 8251 */ //MCFG_PIT8253_OUT1_HANDLER(WRITELINE(excali64_state, write_uart_clock)) @@ -183,9 +308,9 @@ static MACHINE_CONFIG_START( excali64, excali64_state ) MCFG_DEVICE_ADD("ppi", I8255A, 0 ) //MCFG_I8255_IN_PORTA_CB(READ8(excali64_state, ppia_r)) - //MCFG_I8255_OUT_PORTA_CB(WRITE8(excali64_state, ppia_w)) + //MCFG_I8255_OUT_PORTA_CB(WRITE8(excali64_state, ppia_w)) // parallel port //MCFG_I8255_IN_PORTB_CB(READ8(excali64_state, ppib_r)) - //MCFG_I8255_OUT_PORTB_CB(WRITE8(excali64_state, ppib_w)) + MCFG_I8255_OUT_PORTB_CB(WRITE8(excali64_state, ppib_w)) MCFG_I8255_IN_PORTC_CB(READ8(excali64_state, ppic_r)) MCFG_I8255_OUT_PORTC_CB(WRITE8(excali64_state, ppic_w)) @@ -224,7 +349,7 @@ ROM_START( excali64 ) ROM_LOAD( "rom_1.bin", 0x0000, 0x4000, CRC(e129a305) SHA1(e43ec7d040c2b2e548d22fd6bbc7df8b45a26e5a) ) ROM_LOAD( "rom_2.bin", 0x2000, 0x2000, CRC(916d9f5a) SHA1(91c527cce963481b7bebf077e955ca89578bb553) ) - ROM_REGION(0x1000, "videoram", ROMREGION_ERASE00) + ROM_REGION(0x2000, "videoram", ROMREGION_ERASE00) ROM_REGION(0x1000, "chargen", 0) ROM_LOAD( "genex_3.bin", 0x0000, 0x1000, CRC(b91619a9) SHA1(2ced636cb7b94ba9d329868d7ecf79963cefe9d9) ) -- cgit v1.2.3