diff options
Diffstat (limited to 'src/mame/acorn/bbc_v.cpp')
| -rw-r--r-- | src/mame/acorn/bbc_v.cpp | 252 |
1 files changed, 136 insertions, 116 deletions
diff --git a/src/mame/acorn/bbc_v.cpp b/src/mame/acorn/bbc_v.cpp index bed02846781..86c2fbd60c6 100644 --- a/src/mame/acorn/bbc_v.cpp +++ b/src/mame/acorn/bbc_v.cpp @@ -2,21 +2,45 @@ // copyright-holders:Gordon Jefferyes, Nigel Barnes /****************************************************************************** - BBC Model B - - This is the first go around at converting the BBC code over to using - mames built in mc6845, there are a number of features now incorrect - or missing in this build: - - BBC split modes no longer work (Like is used in Elite.) + BBC Micro and Master series video code + + TODO: + - move palette handling to a VIDPROC device. + - improve 6845 video emulation, fix show border area for VSYNC timing. + + Benchmark games: (+ working, - not working) + + Alien 8 (and probably other Ultimate games) - FCxx/FDxx must return FF if no hardware present + - Boffin - overscan + + By Fair Means or Foul - palette change timing + - Crazee Rider (Master)- correct handling of undocumented sound chip writes (drums will sound wrong if this is not correct) + + Dr Who: The First Adventure - non-standard keyboard handling + + Doctor Who and the Mines of Terror - ROM/B+ sideways RAM + + Empire Strikes Back - interrupt timing when CLI immediately followed by SEI + - Elite (Superior re-release) - 2nd processor, split screen mode + - Exile - correct handling of flags in BCD mode, and palette change timing + - Firetrack - smooth scrolling, intro part uses horizontal overscan on model B (not Master) + - Frogger (Trickysoft) - defines multiple displays areas per frame + - Lunar Jetman - in addition to the protection, requires a programmed VSYNC length of 0 to be treated as 16, otherwise the mode/palette split will be in the wrong place + - Nightshade - tape protection + + Pharaoh's Curse - lightpen abuse + - Revs - interrupt timing (6522 T1) + - Rig Attack - interrupt timing + + Snapper - timer output on VIA port B + + Spy Hunter (disc version) - sampled speech playback + - Stryker's Run (Master)- music fidelity + - Time and Magik (Master) - video effects + + Ultimate games (Jet-Pac, Cookie, Atic Atac, Sabre Wulf) - correct handling of 'flash' bit in video ULA + - Uridium - vertical rupture + + Volcano - something VIA related + + Zalaga - illegal opcodes + - Some Nasty Effects - multiple palette changes per scanline + - Skirmish - VIA timers ******************************************************************************/ #include "emu.h" #include "bbc.h" -#include "video/saa5050.h" -#include "video/mc6845.h" -#include "screen.h" + /************************************************************************ * C0 and C1 along with MA12 output from the 6845 drive 4 NAND gates in ICs 27,36 and 40 @@ -35,49 +59,50 @@ uint16_t bbc_state::calculate_video_address(uint16_t ma, uint8_t ra) { - /* output from IC32 74LS259 bits 4 and 5 */ + // output from IC32 74LS259 bits 4 and 5 int c0 = m_latch->q4_r(); int c1 = m_latch->q5_r(); - /* the 4 bit input port b on IC39 are produced by 4 NAND gates. These NAND gates take their inputs - from c0 and c1 (from IC32) and ma12 (from the 6845) */ + // the 4 bit input port b on IC39 are produced by 4 NAND gates. These NAND gates take their inputs + // from c0 and c1 (from IC32) and ma12 (from the 6845) - /* get bit m12 from the 6845 */ + // get bit m12 from the 6845 int ma12 = BIT(ma, 12); - /* 4 bit input B on IC39 74LS283 (4 bit adder) */ - /* 3 input NAND part of IC 36 */ + // 4 bit input B on IC39 74LS283 (4 bit adder) + // 3 input NAND part of IC 36 int b1 = (~(c1 & c0 & ma12)) & 1; - /* 2 input NAND part of IC40 (b3 is calculated before b2 and b4 because b3 feed back into b2 and b4) */ + // 2 input NAND part of IC40 (b3 is calculated before b2 and b4 because b3 feed back into b2 and b4) int b3 = (~(c0 & ma12)) & 1; - /* 3 input NAND part of IC 36 */ + // 3 input NAND part of IC 36 int b2 = (~(c1 & b3 & ma12)) & 1; - /* 2 input NAND part of IC 27 */ + // 2 input NAND part of IC 27 int b4 = (~(b3 & ma12)) & 1; - /* inputs port b to IC39 are taken from the NAND gates b1 to b4 */ - int b = (b1<<0) | (b2<<1) | (b3<<2) | (b4<<3); + // inputs port b to IC39 are taken from the NAND gates b1 to b4 + int b = (b1 << 0) | (b2 << 1) | (b3 << 2) | (b4 << 3); - /* inputs port a to IC39 are MA8 to MA11 from the 6845 */ - int a = (ma>>8) & 0xf; + // inputs port a to IC39 are MA8 to MA11 from the 6845 + int a = (ma >> 8) & 0xf; - /* IC39 performs the 4 bit add with the carry input set high */ - int s = (a+b+1) & 0xf; + // IC39 performs the 4 bit add with the carry input set high + int s = (a + b + 1) & 0xf; - /* if MA13 (TTXVDU) is low then IC8 and IC9 are used to calculate - the memory location required for the hi res video. - if MA13 is high then IC10 and IC11 are used to calculate the memory location for the teletext chip */ - uint16_t m; + // if MA13 (TTXVDU) is low then IC8 and IC9 are used to calculate + // the memory location required for the hires video. + // if MA13 is high then IC10 and IC11 are used to calculate the memory location for the teletext chip + uint16_t addr; if (BIT(ma, 13)) - m = ((ma & 0x3ff) | 0x3c00) | ((s & 0x8)<<11); + addr = ((ma & 0x3ff) | 0x3c00) | ((s & 0x8) << 11); else - m = ((ma & 0xff)<<3) | (s<<11) | (ra & 0x7); + addr = ((ma & 0xff) << 3) | (s << 11) | (ra & 0x7); - if (m_ram->size() == 16 * 1024) m &= 0x3fff; + if (m_ram->size() == 16 * 1024) addr &= 0x3fff; - return m; + return addr; } + /*************************************************************************** * Palette ***************************************************************************/ @@ -107,47 +132,32 @@ void bbc_state::update_palette(monitor_type monitor_type) } } + /************************************************************************ * VideoULA ************************************************************************/ -static const int pixels_per_byte_set[8]={ 2,4,8,16,1,2,4,8 }; +static const int pixels_per_byte_set[8] = { 2,4,8,16,1,2,4,8 }; -static const int width_of_cursor_set[8]={ 0,0,1,2,1,0,2,4 }; - -/* this is a quick lookup array that puts bits 0,2,4,6 into bits 0,1,2,3 - this is used by the palette lookup in the video ULA */ -void bbc_state::set_pixel_lookup() -{ - for (int i=0; i<256; i++) - { - m_pixel_bits[i] = (BIT(i,7)<<3) | (BIT(i,5)<<2) | (BIT(i,3)<<1) | (BIT(i,1)<<0); - } -} +static const int width_of_cursor_set[8] = { 0,0,1,2,1,0,2,4 }; void bbc_state::video_ula_w(offs_t offset, uint8_t data) { - int vpos = m_screen->vpos(); - if (vpos == 0) - m_screen->update_partial(vpos); - else - m_screen->update_partial(vpos - 1); + m_screen->update_partial(m_screen->vpos()); uint8_t mask = m_vnula.disable ? 0x01 : 0x03; switch (offset & mask) { - case 0: - /* Video ULA control register - b7 Master cursor size - b6-b5 Width of cursor in bytes - b4 6845 clock rate select - b3-b2 Number of characters per line - b1 Teletext/Normal select - b0 Flash colour select - */ - - /* flash colour select has changed */ + case 0: // Video ULA control register + // b7 Master cursor size + // b6-b5 Width of cursor in bytes + // b4 6845 clock rate select + // b3-b2 Number of characters per line + // b1 Teletext/Normal select + // b0 Flash colour select + + // flash colour select has changed if (BIT(m_vula_ctrl ^ data, 0)) { for (int i = 0; i < 16; i++) @@ -162,21 +172,26 @@ void bbc_state::video_ula_w(offs_t offset, uint8_t data) m_vula_ctrl = data; m_cursor_size = width_of_cursor_set[(data >> 5) & 7]; - /* number of BBC pixels held in each byte */ + // number of pixels held in each byte if (BIT(data, 1)) + { m_pixels_per_byte = 12; + m_pixel_width = 1; + } else + { m_pixels_per_byte = pixels_per_byte_set[(data >> 2) & 7]; + m_pixel_width = 1 << (~(data >> 2) & 0x03); + } - m_hd6845->set_hpixels_per_column(m_pixels_per_byte); + m_crtc->set_hpixels_per_column(m_pixels_per_byte); if (BIT(data, 4) || BIT(data, 1)) // FIXME: double clock for MODE7 until interlace is implemented - m_hd6845->set_unscaled_clock(16_MHz_XTAL / 8); + m_crtc->set_unscaled_clock(16_MHz_XTAL / 8); else - m_hd6845->set_unscaled_clock(16_MHz_XTAL / 16); + m_crtc->set_unscaled_clock(16_MHz_XTAL / 16); break; - case 1: - /* Video ULA palette register */ + case 1: // Video ULA palette register m_vula_palette[data >> 4] = data & 0x0f; if (BIT(data, 3) && BIT(m_vula_ctrl, 0) && m_vnula.flash[data & 7]) m_vula_palette_lookup[data >> 4] = data & 0x0f; @@ -184,24 +199,19 @@ void bbc_state::video_ula_w(offs_t offset, uint8_t data) m_vula_palette_lookup[data >> 4] = (data & 0x0f) ^ 7; break; - case 2: - /* Video NuLA auxiliary control register */ + case 2: // Video NuLA auxiliary control register switch (data >> 4) { - case 1: - /* Set palette mode */ + case 1: // Set palette mode m_vnula.palette_mode = data & 0x01; break; - case 2: - /* Set horizontal scroll offset */ + case 2: // Set horizontal scroll offset m_vnula.horiz_offset = data & 0x07; break; - case 3: - /* Set left-hand side blanking size */ + case 3: // Set left-hand side blanking size m_vnula.left_blank = data & 0x0f; break; - case 4: - /* Reset additional features */ + case 4: // Reset additional features update_palette(monitor_type::COLOUR); for (int i = 0; i < 8; i++) m_vnula.flash[i] = 1; @@ -212,27 +222,22 @@ void bbc_state::video_ula_w(offs_t offset, uint8_t data) m_vnula.attr_text = 0; m_vnula.palette_write = 0; break; - case 5: - /* Disable A1 address line */ + case 5: // Disable A1 address line m_vnula.disable = 1; break; - case 6: - /* Enable/disable attribute modes */ + case 6: // Enable/disable attribute modes m_vnula.attr_mode = data & 0x01; break; - case 7: - /* Enable/disable 8-colour attribute text modes */ + case 7: // Enable/disable 8-colour attribute text modes m_vnula.attr_text = data & 0x01; break; - case 8: - /* Set flashing flags for colours 8-11 */ + case 8: // Set flashing flags for colours 8-11 m_vnula.flash[0] = data & 0x08; m_vnula.flash[1] = data & 0x04; m_vnula.flash[2] = data & 0x02; m_vnula.flash[3] = data & 0x01; break; - case 9: - /* Set flashing flags for colours 12-15 */ + case 9: // Set flashing flags for colours 12-15 m_vnula.flash[4] = data & 0x08; m_vnula.flash[5] = data & 0x04; m_vnula.flash[6] = data & 0x02; @@ -241,13 +246,12 @@ void bbc_state::video_ula_w(offs_t offset, uint8_t data) } break; - case 3: - /* Video NuLA auxiliary palette register */ + case 3: // Video NuLA auxiliary palette register if (m_vnula.palette_write) { uint8_t col = m_vnula.palette_byte >> 4; m_palette->set_pen_color(col, rgb_t(pal4bit(m_vnula.palette_byte & 0x0f), pal4bit(data >> 4), pal4bit(data & 0x0f))); - /* redefined colour becomes solid */ + // redefined colour becomes solid if (BIT(col, 3)) m_vnula.flash[col & 7] = 0; @@ -268,25 +272,40 @@ void bbc_state::video_ula_w(offs_t offset, uint8_t data) } } + /************************************************************************ * BBC circuits controlled by 6845 Outputs ************************************************************************/ -MC6845_UPDATE_ROW( bbc_state::crtc_update_row ) +MC6845_RECONFIGURE(bbc_state::crtc_reconfigure) +{ + // ensure all graphics modes render to same bitmap size (for split-screen modes) + rectangle rect(visarea.min_x * m_pixel_width, visarea.min_x + (visarea.width() * m_pixel_width) - 1, visarea.min_y, visarea.max_y); + m_screen->configure(width * m_pixel_width, height, rect, frame_period); +} + +MC6845_UPDATE_ROW(bbc_state::crtc_update_row) { const rgb_t *palette = m_palette->palette()->entry_list_raw(); + uint32_t *p = &bitmap.pix(y); + if (BIT(m_vula_ctrl, 1)) { m_trom->lose_w(1); m_trom->lose_w(0); - for (int x_pos = 0; x_pos < x_count; x_pos++) + if (bitmap.height() <= 312) // HACK: not interlaced so skip a line (requires SAA5050 improvements) { - /* Teletext Latch bits 0 to 5 go to bits 0 to 5 on the Teletext chip - Teletext Latch bit 6 is only passed onto bits 6 on the Teletext chip if DE is true - Teletext Latch bit 7 goes to LOSE on the Teletext chip */ + m_trom->lose_w(1); + m_trom->lose_w(0); + } + for (int x_pos = 0; x_pos < x_count; x_pos++) + { + // Teletext Latch bits 0 to 5 go to bits 0 to 5 on the Teletext chip + // Teletext Latch bit 6 is only passed onto bits 6 on the Teletext chip if DE is true + // Teletext Latch bit 7 goes to LOSE on the Teletext chip if (BIT(ma, 13) == 0) m_teletext_latch = 0; else @@ -304,42 +323,47 @@ MC6845_UPDATE_ROW( bbc_state::crtc_update_row ) int col = m_trom->get_rgb() ^ ((x_pos == cursor_x) ? 7 : 0); - bitmap.pix(y, (x_pos*m_pixels_per_byte) + pixelno) = de ? palette[col] : rgb_t::black(); + for (int i = 0; i < m_pixel_width; i++) + { + *p = de ? palette[col] : rgb_t::black(); p++; + } } } } else { - for (int x_pos = 0; x_pos<x_count; x_pos++) + for (int x_pos = 0; x_pos < x_count; x_pos++) { uint8_t data = m_video_ram[calculate_video_address(ma + x_pos, ra)]; for (int pixelno = 0; pixelno < m_pixels_per_byte; pixelno++) { - int col = !(ra & 0x08) ? m_vula_palette_lookup[m_pixel_bits[data]] : 0; + int col = !(ra & 0x08) ? m_vula_palette_lookup[bitswap<4>(data, 7, 5, 3, 1)] : 0; col ^= ((cursor_x != -1 && x_pos >= cursor_x && x_pos < (cursor_x + m_cursor_size)) ? 7 : 0); - bitmap.pix(y, (x_pos*m_pixels_per_byte) + pixelno) = de ? palette[col] : rgb_t::black(); + for (int i = 0; i < m_pixel_width; i++) + { + *p = de ? palette[col] : rgb_t::black(); p++; + } data = (data << 1) | 1; } } } } -void bbc_state::bbc_hsync_changed(int state) +void bbc_state::hsync_changed(int state) { - m_hsync = state; + //m_trom->glr_w(!state); } -void bbc_state::bbc_vsync_changed(int state) +void bbc_state::vsync_changed(int state) { - m_vsync = state; - m_via6522_0->write_ca1(state); // screen refresh interrupts + m_sysvia->write_ca1(state); // screen refresh interrupt m_trom->dew_w(state); } -void bbc_state::bbc_de_changed(int state) +void bbc_state::de_changed(int state) { if (!state) m_teletext_latch |= 0x80; @@ -355,7 +379,6 @@ uint8_t bbc_state::bus_video_data() return m_video_ram[calculate_video_address(hpos, vpos)]; } -/**** BBC B+/Master Shadow Ram change ****/ void bbc_state::setvideoshadow(int vdusel) { @@ -368,16 +391,13 @@ void bbc_state::setvideoshadow(int vdusel) m_video_ram = m_ram->pointer(); } + /************************************************************************ * Initialize the BBC video emulation ************************************************************************/ void bbc_state::video_start() { - m_cursor_size = 1; - - set_pixel_lookup(); - m_video_ram = m_ram->pointer(); // register save states @@ -396,11 +416,11 @@ void bbc_state::video_start() void bbc_state::video_reset() { for (int i = 0; i < 8; i++) - m_vnula.flash[i] = 1; - m_vnula.palette_mode = 0; - m_vnula.horiz_offset = 0; - m_vnula.left_blank = 0; - m_vnula.disable = !BIT(m_bbcconfig.read_safe(0), 3); - m_vnula.palette_byte = 0; + m_vnula.flash[i] = 1; + m_vnula.palette_mode = 0; + m_vnula.horiz_offset = 0; + m_vnula.left_blank = 0; + m_vnula.disable = !BIT(m_bbcconfig.read_safe(0), 3); + m_vnula.palette_byte = 0; m_vnula.palette_write = 0; } |
