trunk/src/mess/drivers/binbug.c
r0 | r20247 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | BINBUG |
| 4 | |
| 5 | 2013-01-14 Driver created |
| 6 | |
| 7 | All input must be in uppercase. |
| 8 | |
| 9 | Commands: |
| 10 | A - See and alter memory |
| 11 | B - Set breakpoint (2 permitted) |
| 12 | C - Clear breakpoint |
| 13 | D - Dump memory to paper tape |
| 14 | G - Go to address, run |
| 15 | L - Load memory from paper tape |
| 16 | S - See and alter registers |
| 17 | |
| 18 | BINBUG is an alternate bios to PIPBUG, however it uses its own |
| 19 | video output. Method of output is through a DG640 board (sold by |
| 20 | Applied Technology) which one can suppose a character generator |
| 21 | rom would be used; therefore undumped. |
| 22 | |
| 23 | Keyboard input, like PIPBUG, is via a serial device. |
| 24 | The baud rate is 300, 8N1. |
| 25 | |
| 26 | The terminal output (via D command) seems to contain binary |
| 27 | data, so it is disabled for now. It is most likely the tape |
| 28 | output mentioned below. |
| 29 | |
| 30 | There are 3 versions of BINBUG: |
| 31 | |
| 32 | - 3.6 300 baud tape routines, 300 baud keyboard, memory-mapped VDU |
| 33 | |
| 34 | - 4.4 300 baud keyboard, ACOS tape system, advanced video routines |
| 35 | |
| 36 | - 5.2 ACOS tape system, 1200 baud terminal |
| 37 | |
| 38 | |
| 39 | ToDo: |
| 40 | - Need dumps of 4.4 and 5.2, also the DG640 CGEN. |
| 41 | - Add cassette |
| 42 | |
| 43 | ****************************************************************************/ |
| 44 | |
| 45 | #include "emu.h" |
| 46 | #include "cpu/s2650/s2650.h" |
| 47 | #include "machine/terminal.h" |
| 48 | #include "machine/keyboard.h" |
| 49 | #include "imagedev/snapquik.h" |
| 50 | |
| 51 | |
| 52 | class binbug_state : public driver_device |
| 53 | { |
| 54 | public: |
| 55 | binbug_state(const machine_config &mconfig, device_type type, const char *tag) |
| 56 | : driver_device(mconfig, type, tag), |
| 57 | m_keyboard(*this, KEYBOARD_TAG), |
| 58 | // m_terminal(*this, TERMINAL_TAG), |
| 59 | m_p_videoram(*this, "videoram") { } |
| 60 | |
| 61 | DECLARE_WRITE8_MEMBER(binbug_ctrl_w); |
| 62 | DECLARE_READ8_MEMBER(binbug_serial_r); |
| 63 | DECLARE_WRITE8_MEMBER(binbug_serial_w); |
| 64 | const UINT8 *m_p_chargen; |
| 65 | virtual void video_start(); |
| 66 | UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 67 | required_device<serial_keyboard_device> m_keyboard; |
| 68 | // required_device<serial_terminal_device> m_terminal; |
| 69 | required_shared_ptr<const UINT8> m_p_videoram; |
| 70 | }; |
| 71 | |
| 72 | WRITE8_MEMBER( binbug_state::binbug_ctrl_w ) |
| 73 | { |
| 74 | } |
| 75 | |
| 76 | READ8_MEMBER( binbug_state::binbug_serial_r ) |
| 77 | { |
| 78 | return m_keyboard->tx_r(); |
| 79 | } |
| 80 | |
| 81 | WRITE8_MEMBER( binbug_state::binbug_serial_w ) |
| 82 | { |
| 83 | // m_terminal->rx_w(data); |
| 84 | } |
| 85 | |
| 86 | static ADDRESS_MAP_START(binbug_mem, AS_PROGRAM, 8, binbug_state) |
| 87 | ADDRESS_MAP_UNMAP_HIGH |
| 88 | AM_RANGE( 0x0000, 0x03ff) AM_ROM |
| 89 | AM_RANGE( 0x0400, 0x77ff) AM_RAM |
| 90 | AM_RANGE( 0x7800, 0x7fff) AM_RAM AM_SHARE("videoram") |
| 91 | ADDRESS_MAP_END |
| 92 | |
| 93 | static ADDRESS_MAP_START(binbug_io, AS_IO, 8, binbug_state) |
| 94 | ADDRESS_MAP_UNMAP_HIGH |
| 95 | AM_RANGE(S2650_CTRL_PORT, S2650_CTRL_PORT) AM_WRITE(binbug_ctrl_w) |
| 96 | AM_RANGE(S2650_SENSE_PORT, S2650_FO_PORT) AM_READWRITE(binbug_serial_r,binbug_serial_w) |
| 97 | ADDRESS_MAP_END |
| 98 | |
| 99 | /* Input ports */ |
| 100 | static INPUT_PORTS_START( binbug ) |
| 101 | INPUT_PORTS_END |
| 102 | |
| 103 | static const serial_terminal_interface terminal_intf = |
| 104 | { |
| 105 | DEVCB_NULL |
| 106 | }; |
| 107 | |
| 108 | void binbug_state::video_start() |
| 109 | { |
| 110 | m_p_chargen = memregion("chargen")->base(); |
| 111 | } |
| 112 | |
| 113 | UINT32 binbug_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 114 | { |
| 115 | UINT8 y,ra,chr,gfx; |
| 116 | UINT16 sy=0,ma=0,x; |
| 117 | |
| 118 | for (y = 0; y < 16; y++) |
| 119 | { |
| 120 | for (ra = 0; ra < 10; ra++) |
| 121 | { |
| 122 | UINT16 *p = &bitmap.pix16(sy++); |
| 123 | |
| 124 | for (x = ma; x < ma + 64; x++) |
| 125 | { |
| 126 | gfx = 0; |
| 127 | if (ra < 9) |
| 128 | { |
| 129 | chr = m_p_videoram[x]; |
| 130 | gfx = m_p_chargen[(chr<<4) | ra ] ^ (BIT(chr, 7) ? 0xff : 0); |
| 131 | } |
| 132 | |
| 133 | /* Display a scanline of a character */ |
| 134 | *p++ = BIT(gfx, 7); |
| 135 | *p++ = BIT(gfx, 6); |
| 136 | *p++ = BIT(gfx, 5); |
| 137 | *p++ = BIT(gfx, 4); |
| 138 | *p++ = BIT(gfx, 3); |
| 139 | *p++ = BIT(gfx, 2); |
| 140 | *p++ = BIT(gfx, 1); |
| 141 | *p++ = BIT(gfx, 0); |
| 142 | } |
| 143 | } |
| 144 | ma+=64; |
| 145 | } |
| 146 | return 0; |
| 147 | } |
| 148 | |
| 149 | QUICKLOAD_LOAD( binbug ) |
| 150 | { |
| 151 | address_space &space = image.device().machine().device("maincpu")->memory().space(AS_PROGRAM); |
| 152 | int i; |
| 153 | int quick_addr = 0x0440; |
| 154 | int exec_addr; |
| 155 | int quick_length; |
| 156 | UINT8 *quick_data; |
| 157 | int read_; |
| 158 | |
| 159 | quick_length = image.length(); |
| 160 | quick_data = (UINT8*)malloc(quick_length); |
| 161 | if (!quick_data) |
| 162 | { |
| 163 | image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot open file"); |
| 164 | image.message(" Cannot open file"); |
| 165 | return IMAGE_INIT_FAIL; |
| 166 | } |
| 167 | |
| 168 | read_ = image.fread( quick_data, quick_length); |
| 169 | if (read_ != quick_length) |
| 170 | { |
| 171 | image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file"); |
| 172 | image.message(" Cannot read the file"); |
| 173 | return IMAGE_INIT_FAIL; |
| 174 | } |
| 175 | |
| 176 | if (quick_data[0] != 0xc4) |
| 177 | { |
| 178 | image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid header"); |
| 179 | image.message(" Invalid header"); |
| 180 | return IMAGE_INIT_FAIL; |
| 181 | } |
| 182 | |
| 183 | exec_addr = quick_data[1] * 256 + quick_data[2]; |
| 184 | |
| 185 | if (exec_addr >= quick_length) |
| 186 | { |
| 187 | image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Exec address beyond end of file"); |
| 188 | image.message(" Exec address beyond end of file"); |
| 189 | return IMAGE_INIT_FAIL; |
| 190 | } |
| 191 | |
| 192 | if (quick_length < 0x444) |
| 193 | { |
| 194 | image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); |
| 195 | image.message(" File too short"); |
| 196 | return IMAGE_INIT_FAIL; |
| 197 | } |
| 198 | |
| 199 | if (quick_length > 0x8000) |
| 200 | { |
| 201 | image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); |
| 202 | image.message(" File too long"); |
| 203 | return IMAGE_INIT_FAIL; |
| 204 | } |
| 205 | |
| 206 | for (i = quick_addr; i < quick_length; i++) |
| 207 | { |
| 208 | space.write_byte(i, quick_data[i]); |
| 209 | } |
| 210 | |
| 211 | /* display a message about the loaded quickload */ |
| 212 | image.message(" Quickload: size=%04X : exec=%04X",quick_length,exec_addr); |
| 213 | |
| 214 | // Start the quickload |
| 215 | image.device().machine().device("maincpu")->state().set_pc(exec_addr); |
| 216 | return IMAGE_INIT_PASS; |
| 217 | } |
| 218 | |
| 219 | static MACHINE_CONFIG_START( binbug, binbug_state ) |
| 220 | /* basic machine hardware */ |
| 221 | MCFG_CPU_ADD("maincpu",S2650, XTAL_1MHz) |
| 222 | MCFG_CPU_PROGRAM_MAP(binbug_mem) |
| 223 | MCFG_CPU_IO_MAP(binbug_io) |
| 224 | |
| 225 | /* video hardware */ |
| 226 | MCFG_SCREEN_ADD("screen", RASTER) |
| 227 | MCFG_SCREEN_REFRESH_RATE(50) |
| 228 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ |
| 229 | MCFG_SCREEN_UPDATE_DRIVER(binbug_state, screen_update) |
| 230 | MCFG_SCREEN_SIZE(512, 160) |
| 231 | MCFG_SCREEN_VISIBLE_AREA(0, 511, 0, 159) |
| 232 | MCFG_PALETTE_LENGTH(2) |
| 233 | MCFG_PALETTE_INIT(monochrome_amber) |
| 234 | |
| 235 | MCFG_SERIAL_KEYBOARD_ADD(KEYBOARD_TAG, terminal_intf, 300) |
| 236 | // MCFG_SERIAL_TERMINAL_ADD(TERMINAL_TAG, terminal_intf, 300) |
| 237 | |
| 238 | /* quickload */ |
| 239 | MCFG_QUICKLOAD_ADD("quickload", binbug, "pgm", 1) |
| 240 | MACHINE_CONFIG_END |
| 241 | |
| 242 | |
| 243 | /* ROM definition */ |
| 244 | ROM_START( binbug ) |
| 245 | ROM_REGION( 0x8000, "maincpu", ROMREGION_ERASEFF ) |
| 246 | ROM_LOAD( "binbug.rom", 0x0000, 0x0400, CRC(2cb1ac6e) SHA1(a969883fc767484d6b0fa103cfa4b4129b90441b) ) |
| 247 | |
| 248 | /* character generator not dumped, using the one from 'c10' for now */ |
| 249 | ROM_REGION( 0x2000, "chargen", 0 ) |
| 250 | ROM_LOAD( "c10_char.bin", 0x0000, 0x2000, BAD_DUMP CRC(cb530b6f) SHA1(95590bbb433db9c4317f535723b29516b9b9fcbf)) |
| 251 | ROM_FILL(0, 16, 0) |
| 252 | ROM_END |
| 253 | |
| 254 | /* Driver */ |
| 255 | |
| 256 | /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ |
| 257 | COMP( 1980, binbug, pipbug, 0, binbug, binbug, driver_device, 0, "MicroByte", "BINBUG 3.6", GAME_NO_SOUND_HW ) |