trunk/src/mess/drivers/binbug.c
| r20287 | r20288 | |
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | |
| 3 | | BINBUG |
| 3 | BINBUG and DG640 |
| 4 | 4 | |
| 5 | 5 | 2013-01-14 Driver created |
| 6 | 6 | |
| r20287 | r20288 | |
| 10 | 10 | A - See and alter memory |
| 11 | 11 | B - Set breakpoint (2 permitted) |
| 12 | 12 | C - Clear breakpoint |
| 13 | | D - Dump memory to paper tape |
| 13 | D - cassette save |
| 14 | 14 | G - Go to address, run |
| 15 | | L - Load memory from paper tape |
| 15 | L - cassette load |
| 16 | 16 | S - See and alter registers |
| 17 | 17 | |
| 18 | 18 | BINBUG is an alternate bios to PIPBUG, however it uses its own |
| 19 | 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. |
| 20 | Applied Technology) which uses a MCM6574 as a character generator. |
| 21 | The DG640 also supports blinking, reverse-video, and LORES graphics. |
| 22 | It is a S100 card. |
| 22 | 23 | |
| 23 | 24 | Keyboard input, like PIPBUG, is via a serial device. |
| 24 | 25 | The baud rate is 300, 8N1. |
| 25 | 26 | |
| 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. |
| 27 | The SENSE and FLAG lines are used for 300 baud cassette, in |
| 28 | conjunction with unknown hardware. |
| 29 | 29 | |
| 30 | 30 | There are 3 versions of BINBUG: |
| 31 | 31 | |
| r20287 | r20288 | |
| 36 | 36 | - 5.2 ACOS tape system, 1200 baud terminal |
| 37 | 37 | |
| 38 | 38 | |
| 39 | Status: |
| 40 | - DG640 is completely emulated, even though BINBUG doesn't use most |
| 41 | of its features. |
| 42 | - BINBUG works except that the cassette interface isn't the same as |
| 43 | real hardware. But you can save, and load it back. |
| 44 | |
| 39 | 45 | ToDo: |
| 40 | | - Need dumps of 4.4 and 5.2, also the DG640 CGEN. |
| 41 | | - Add cassette |
| 46 | - Need dumps of 4.4 and 5.2. |
| 47 | - Fix cassette |
| 42 | 48 | |
| 43 | 49 | ****************************************************************************/ |
| 44 | 50 | |
| 45 | 51 | #include "emu.h" |
| 46 | 52 | #include "cpu/s2650/s2650.h" |
| 47 | | #include "machine/terminal.h" |
| 48 | 53 | #include "machine/keyboard.h" |
| 54 | #include "imagedev/cassette.h" |
| 55 | #include "sound/wave.h" |
| 49 | 56 | #include "imagedev/snapquik.h" |
| 50 | 57 | |
| 51 | 58 | |
| r20287 | r20288 | |
| 55 | 62 | binbug_state(const machine_config &mconfig, device_type type, const char *tag) |
| 56 | 63 | : driver_device(mconfig, type, tag), |
| 57 | 64 | m_keyboard(*this, KEYBOARD_TAG), |
| 58 | | // m_terminal(*this, TERMINAL_TAG), |
| 59 | | m_p_videoram(*this, "videoram") { } |
| 65 | m_cass(*this, CASSETTE_TAG), |
| 66 | m_p_videoram(*this, "videoram"), |
| 67 | m_p_attribram(*this, "attribram") { } |
| 60 | 68 | |
| 61 | 69 | DECLARE_WRITE8_MEMBER(binbug_ctrl_w); |
| 62 | 70 | DECLARE_READ8_MEMBER(binbug_serial_r); |
| 63 | 71 | DECLARE_WRITE8_MEMBER(binbug_serial_w); |
| 64 | 72 | const UINT8 *m_p_chargen; |
| 73 | UINT8 m_framecnt; |
| 65 | 74 | virtual void video_start(); |
| 66 | 75 | UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 67 | 76 | required_device<serial_keyboard_device> m_keyboard; |
| 68 | | // required_device<serial_terminal_device> m_terminal; |
| 77 | required_device<cassette_image_device> m_cass; |
| 69 | 78 | required_shared_ptr<const UINT8> m_p_videoram; |
| 79 | required_shared_ptr<const UINT8> m_p_attribram; |
| 70 | 80 | }; |
| 71 | 81 | |
| 72 | 82 | WRITE8_MEMBER( binbug_state::binbug_ctrl_w ) |
| r20287 | r20288 | |
| 75 | 85 | |
| 76 | 86 | READ8_MEMBER( binbug_state::binbug_serial_r ) |
| 77 | 87 | { |
| 78 | | return m_keyboard->tx_r(); |
| 88 | return m_keyboard->tx_r() & (m_cass->input() < 0.03); |
| 79 | 89 | } |
| 80 | 90 | |
| 81 | 91 | WRITE8_MEMBER( binbug_state::binbug_serial_w ) |
| 82 | 92 | { |
| 83 | | // m_terminal->rx_w(data); |
| 93 | m_cass->output(BIT(data, 0) ? -1.0 : +1.0); |
| 84 | 94 | } |
| 85 | 95 | |
| 86 | 96 | static ADDRESS_MAP_START(binbug_mem, AS_PROGRAM, 8, binbug_state) |
| 87 | 97 | ADDRESS_MAP_UNMAP_HIGH |
| 88 | 98 | AM_RANGE( 0x0000, 0x03ff) AM_ROM |
| 89 | 99 | AM_RANGE( 0x0400, 0x77ff) AM_RAM |
| 90 | | AM_RANGE( 0x7800, 0x7fff) AM_RAM AM_SHARE("videoram") |
| 100 | AM_RANGE( 0x7800, 0x7bff) AM_RAM AM_SHARE("videoram") |
| 101 | AM_RANGE( 0x7c00, 0x7fff) AM_RAM AM_SHARE("attribram") |
| 91 | 102 | ADDRESS_MAP_END |
| 92 | 103 | |
| 93 | 104 | static ADDRESS_MAP_START(binbug_io, AS_IO, 8, binbug_state) |
| r20287 | r20288 | |
| 100 | 111 | static INPUT_PORTS_START( binbug ) |
| 101 | 112 | INPUT_PORTS_END |
| 102 | 113 | |
| 103 | | static const serial_terminal_interface terminal_intf = |
| 114 | static const serial_keyboard_interface keyboard_intf = |
| 104 | 115 | { |
| 105 | 116 | DEVCB_NULL |
| 106 | 117 | }; |
| r20287 | r20288 | |
| 112 | 123 | |
| 113 | 124 | UINT32 binbug_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 114 | 125 | { |
| 115 | | UINT8 y,ra,chr,gfx; |
| 126 | // attributes bit 0 = flash, bit 1 = lores. Also bit 7 of the character = reverse-video (text only). |
| 127 | UINT8 y,ra,chr,gfx,attr,inv,gfxbit; |
| 116 | 128 | UINT16 sy=0,ma=0,x; |
| 129 | bool flash; |
| 130 | m_framecnt++; |
| 117 | 131 | |
| 118 | 132 | for (y = 0; y < 16; y++) |
| 119 | 133 | { |
| 120 | | for (ra = 0; ra < 10; ra++) |
| 134 | for (ra = 0; ra < 16; ra++) |
| 121 | 135 | { |
| 122 | 136 | UINT16 *p = &bitmap.pix16(sy++); |
| 123 | 137 | |
| 124 | 138 | for (x = ma; x < ma + 64; x++) |
| 125 | 139 | { |
| 126 | | gfx = 0; |
| 127 | | if (ra < 9) |
| 140 | attr = m_p_attribram[x]; |
| 141 | chr = m_p_videoram[x]; |
| 142 | flash = BIT(m_framecnt, 4) & BIT(attr, 0); |
| 143 | |
| 144 | if (BIT(attr, 1)) // lores gfx - can flash |
| 128 | 145 | { |
| 129 | | chr = m_p_videoram[x]; |
| 130 | | gfx = m_p_chargen[(chr<<4) | ra ] ^ (BIT(chr, 7) ? 0xff : 0); |
| 146 | if (flash) chr = 0; // blank part of flashing |
| 147 | |
| 148 | gfxbit = (ra & 0x0c)>>1; |
| 149 | /* Display one line of a lores character (8 pixels) */ |
| 150 | *p++ = BIT(chr, gfxbit); |
| 151 | *p++ = BIT(chr, gfxbit); |
| 152 | *p++ = BIT(chr, gfxbit); |
| 153 | *p++ = BIT(chr, gfxbit); |
| 154 | gfxbit++; |
| 155 | *p++ = BIT(chr, gfxbit); |
| 156 | *p++ = BIT(chr, gfxbit); |
| 157 | *p++ = BIT(chr, gfxbit); |
| 158 | *p++ = BIT(chr, gfxbit); |
| 131 | 159 | } |
| 160 | else |
| 161 | { |
| 162 | gfx = 0; |
| 132 | 163 | |
| 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); |
| 164 | if (!flash) |
| 165 | { |
| 166 | inv = BIT(chr, 7) ? 0xff : 0; // text with bit 7 high is reversed |
| 167 | chr &= 0x7f; |
| 168 | gfx = inv; |
| 169 | |
| 170 | // if g,j,p,q,y; lower the descender |
| 171 | if ((chr==0x2c)||(chr==0x3b)||(chr==0x67)||(chr==0x6a)||(chr==0x70)||(chr==0x71)||(chr==0x79)) |
| 172 | { |
| 173 | if (ra > 6) |
| 174 | gfx = m_p_chargen[(chr<<4) | (ra-7) ] ^ inv; |
| 175 | } |
| 176 | else |
| 177 | { |
| 178 | if ((ra > 3) & (ra < 13)) |
| 179 | gfx = m_p_chargen[(chr<<4) | (ra-4) ] ^ inv; |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | /* Display a scanline of a character */ |
| 184 | *p++ = BIT(gfx, 7); |
| 185 | *p++ = BIT(gfx, 6); |
| 186 | *p++ = BIT(gfx, 5); |
| 187 | *p++ = BIT(gfx, 4); |
| 188 | *p++ = BIT(gfx, 3); |
| 189 | *p++ = BIT(gfx, 2); |
| 190 | *p++ = BIT(gfx, 1); |
| 191 | *p++ = BIT(gfx, 0); |
| 192 | } |
| 142 | 193 | } |
| 143 | 194 | } |
| 144 | 195 | ma+=64; |
| r20287 | r20288 | |
| 146 | 197 | return 0; |
| 147 | 198 | } |
| 148 | 199 | |
| 200 | /* F4 Character Displayer */ |
| 201 | static const gfx_layout dg640_charlayout = |
| 202 | { |
| 203 | 7, 9, /* 7 x 9 characters */ |
| 204 | 128, /* 128 characters */ |
| 205 | 1, /* 1 bits per pixel */ |
| 206 | { 0 }, /* no bitplanes */ |
| 207 | /* x offsets */ |
| 208 | { 0, 1, 2, 3, 4, 5, 6 }, |
| 209 | /* y offsets */ |
| 210 | { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8 }, |
| 211 | 8*16 /* every char takes 16 bytes */ |
| 212 | }; |
| 213 | |
| 214 | static GFXDECODE_START( dg640 ) |
| 215 | GFXDECODE_ENTRY( "chargen", 0x0000, dg640_charlayout, 0, 1 ) |
| 216 | GFXDECODE_END |
| 217 | |
| 149 | 218 | QUICKLOAD_LOAD( binbug ) |
| 150 | 219 | { |
| 151 | 220 | address_space &space = image.device().machine().device("maincpu")->memory().space(AS_PROGRAM); |
| r20287 | r20288 | |
| 227 | 296 | MCFG_SCREEN_REFRESH_RATE(50) |
| 228 | 297 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ |
| 229 | 298 | MCFG_SCREEN_UPDATE_DRIVER(binbug_state, screen_update) |
| 230 | | MCFG_SCREEN_SIZE(512, 160) |
| 231 | | MCFG_SCREEN_VISIBLE_AREA(0, 511, 0, 159) |
| 299 | MCFG_SCREEN_SIZE(512, 256) |
| 300 | MCFG_SCREEN_VISIBLE_AREA(0, 511, 0, 255) |
| 301 | MCFG_GFXDECODE(dg640) |
| 232 | 302 | MCFG_PALETTE_LENGTH(2) |
| 233 | 303 | MCFG_PALETTE_INIT(monochrome_amber) |
| 234 | 304 | |
| 235 | | MCFG_SERIAL_KEYBOARD_ADD(KEYBOARD_TAG, terminal_intf, 300) |
| 236 | | // MCFG_SERIAL_TERMINAL_ADD(TERMINAL_TAG, terminal_intf, 300) |
| 305 | /* Keyboard */ |
| 306 | MCFG_SERIAL_KEYBOARD_ADD(KEYBOARD_TAG, keyboard_intf, 300) |
| 237 | 307 | |
| 308 | /* Cassette */ |
| 309 | MCFG_CASSETTE_ADD( CASSETTE_TAG, default_cassette_interface ) |
| 310 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 311 | MCFG_SOUND_WAVE_ADD(WAVE_TAG, CASSETTE_TAG) |
| 312 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 313 | |
| 238 | 314 | /* quickload */ |
| 239 | 315 | MCFG_QUICKLOAD_ADD("quickload", binbug, "pgm", 1) |
| 240 | 316 | MACHINE_CONFIG_END |
| r20287 | r20288 | |
| 245 | 321 | ROM_REGION( 0x8000, "maincpu", ROMREGION_ERASEFF ) |
| 246 | 322 | ROM_LOAD( "binbug.rom", 0x0000, 0x0400, CRC(2cb1ac6e) SHA1(a969883fc767484d6b0fa103cfa4b4129b90441b) ) |
| 247 | 323 | |
| 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)) |
| 324 | ROM_REGION( 0x0800, "chargen", 0 ) |
| 325 | ROM_LOAD( "6574.bin", 0x0000, 0x0800, CRC(fd75df4f) SHA1(4d09aae2f933478532b7d3d1a2dee7123d9828ca) ) |
| 251 | 326 | ROM_FILL(0, 16, 0) |
| 252 | 327 | ROM_END |
| 253 | 328 | |
| 254 | 329 | /* Driver */ |
| 255 | 330 | |
| 256 | 331 | /* 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 ) |
| 332 | COMP( 1980, binbug, pipbug, 0, binbug, binbug, driver_device, 0, "MicroByte", "BINBUG 3.6", 0 ) |