diff options
Diffstat (limited to 'src/mame/video/bbc.c')
-rw-r--r-- | src/mame/video/bbc.c | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/src/mame/video/bbc.c b/src/mame/video/bbc.c new file mode 100644 index 00000000000..5e059647705 --- /dev/null +++ b/src/mame/video/bbc.c @@ -0,0 +1,306 @@ +// license:BSD-3-Clause +// copyright-holders:Gordon Jefferyes, Nigel Barnes +/****************************************************************************** + BBC Model B + + MESS Driver By: + + Gordon Jefferyes + mess_bbc@romvault.com + + 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.) + +******************************************************************************/ + +#include "emu.h" +#include "includes/bbc.h" +#include "video/saa5050.h" +#include "video/mc6845.h" + +/************************************************************************ + * C0 and C1 along with MA12 output from the 6845 drive 4 NAND gates in ICs 27,36 and 40 + * the outputs from these NAND gates (B1 to B4) along with MA8 to MA11 from the 6845 (A1 to B4) are added together + * in IC39 74LS283 4 bit adder to form (S1 to S4) the logic is used to loop the screen memory for hardware scrolling. + * when MA13 from the 6845 is low the latches IC8 and IC9 are enabled + * they control the memory addressing for the Hi-Res modes. + * when MA13 from the 6845 is high the latches IC10 and IC11 are enabled + * they control the memory addressing for the Teletext mode. + * IC 8 or IC10 drives the row select in the memory (the lower 7 bits in the memory address) and + * IC 9 or IC11 drives the column select in the memory (the next 7 bits in the memory address) this + * gives control of the bottom 14 bits of the memory, in a 32K model B 15 bits are needed to access + * all the RAM, so S4 for the adder drives the CAS0 and CAS1 to access the top bit, in a 16K model A + * the output of S4 is linked out to a 0v supply by link S25 to just access the 16K memory area. + ************************************************************************/ + +unsigned int bbc_state::calculate_video_address(int ma,int ra) +{ + // ma = output from IC2 6845 MA address + + int c0=m_b4_video0; // output from IC32 74LS259 bits 4 and 5 + int c1=m_b5_video1; + + /* 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 */ + int ma12=(ma>>12)&1; + + // 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) */ + int b3=(~(c0 & ma12)) & 1; + /* 3 input NAND part of IC 36 */ + int b2=(~(c1 & b3 & ma12)) & 1; + /* 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 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; + + /* 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 hight then IC10 and IC11 are used to calculate the memory location for the teletext chip*/ + unsigned int m; + if ((ma>>13)&1) + { + // IC 10 and IC 11 + m=((ma&0x3ff)|0x3c00)|((s&0x8)<<11); + } else { + // IC 8 and IC 9 + m=((ma&0xff)<<3)|(s<<11)|(ra&0x7); + } + if (m_memorySize==16) + return m & 0x3fff; + + return m; +} + +/************************************************************************ + * VideoULA + ************************************************************************/ + +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] = (((i>>7)&1)<<3) | (((i>>5)&1)<<2) | (((i>>3)&1)<<1) | (((i>>1)&1)<<0); + } +} + + +WRITE8_MEMBER(bbc_state::bbc_videoULA_w) +{ + // Make sure vpos is never <0 2008-10-11 PHS. + int vpos=machine().first_screen()->vpos(); + if(vpos==0) + machine().first_screen()->update_partial(vpos); + else + machine().first_screen()->update_partial(vpos -1 ); + + logerror("setting videoULA %.4x to:%.4x at :%d \n",data,offset,machine().first_screen()->vpos() ); + + + switch (offset&0x01) + { + // Set the control register in the Video ULA + case 0: + { + m_videoULA_Reg=data; + m_videoULA_master_cursor_size= (m_videoULA_Reg>>7)&0x01; + m_videoULA_width_of_cursor= (m_videoULA_Reg>>5)&0x03; + m_videoULA_6845_clock_rate= (m_videoULA_Reg>>4)&0x01; + m_videoULA_characters_per_line= (m_videoULA_Reg>>2)&0x03; + m_videoULA_teletext_normal_select=(m_videoULA_Reg>>1)&0x01; + m_videoULA_flash_colour_select= m_videoULA_Reg &0x01; + + m_videoULA_pallet_lookup=m_videoULA_flash_colour_select?m_videoULA_pallet0:m_videoULA_pallet1; + + m_emulation_cursor_size=width_of_cursor_set[m_videoULA_width_of_cursor|(m_videoULA_master_cursor_size<<2)]; + + // this is the number of BBC pixels held in each byte + if (m_videoULA_teletext_normal_select) + { + m_pixels_per_byte=6; + } else { + m_pixels_per_byte=pixels_per_byte_set[m_videoULA_characters_per_line|(m_videoULA_6845_clock_rate<<2)]; + } + m_mc6845->set_hpixels_per_column(m_pixels_per_byte); + if (m_videoULA_6845_clock_rate) + m_mc6845->set_clock(2000000); + else + m_mc6845->set_clock(1000000); + } + break; + // Set a pallet register in the Video ULA + case 1: + int tpal=(data>>4)&0x0f; + int tcol=data&0x0f; + m_videoULA_pallet0[tpal]=tcol; + m_videoULA_pallet1[tpal]=tcol<8?tcol:tcol^7; + break; + } +} + +/************************************************************************ + * BBC circuits controlled by 6845 Outputs + ************************************************************************/ + +MC6845_UPDATE_ROW( bbc_state::crtc_update_row ) +{ + const rgb_t *palette = m_palette->palette()->entry_list_raw(); + + if (m_videoULA_teletext_normal_select) + { + 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 (((ma>>13)&1)==0) + { + m_Teletext_Latch=0; + } + else + { + m_Teletext_Latch=(m_BBC_Video_RAM[calculate_video_address(ma+x_pos,ra)]); + } + + m_trom->write((m_Teletext_Latch&0x3f)|(m_Teletext_Latch&0x40)); + + m_trom->f1_w(1); + m_trom->f1_w(0); + + for(int pixelno=0;pixelno<6;pixelno++) + { + m_trom->tr6_w(1); + m_trom->tr6_w(0); + + int col=m_trom->get_rgb() ^ ((x_pos==cursor_x) ? 7 : 0); + + int r = BIT(col, 0) * 0xff; + int g = BIT(col, 1) * 0xff; + int b = BIT(col, 2) * 0xff; + + rgb_t rgb = rgb_t(r, g, b); + + bitmap.pix32(y, (x_pos*m_pixels_per_byte)+pixelno) = rgb; + } + } + + if (ra == 18) + { + m_trom->lose_w(1); + m_trom->lose_w(0); + } + } + else + { + // this is IC38 and IC41 takes 6845 DisplayEnabled and 6845 RA3 + int DE= !(ra>=8); + + if (DE) + { + for(int x_pos=0; x_pos<x_count; x_pos++) + { + int vmem=calculate_video_address(ma+x_pos,ra); + unsigned char i=m_BBC_Video_RAM[vmem]; + + for(int pixelno=0;pixelno<m_pixels_per_byte;pixelno++) + { + int col=m_videoULA_pallet_lookup[m_pixel_bits[i]] ^ ((x_pos==cursor_x) ? 7 : 0); + bitmap.pix32(y, (x_pos*m_pixels_per_byte)+pixelno)=palette[col]; + i=(i<<1)|1; + } + } + } + else + { + for(int x_pos=0; x_pos<x_count; x_pos++) + { + for(int pixelno=0;pixelno<m_pixels_per_byte;pixelno++) + { + bitmap.pix32(y, (x_pos*m_pixels_per_byte)+pixelno)=palette[7]; + } + } + } + } +} + +WRITE_LINE_MEMBER(bbc_state::bbc_vsync) +{ + m_trom->dew_w(state); +} + + +/**** BBC B+ Shadow Ram change ****/ + +void bbc_state::bbcbp_setvideoshadow(int vdusel) +{ + if (vdusel) + { + m_BBC_Video_RAM= m_region_maincpu->base()+0x8000; + } else { + m_BBC_Video_RAM= m_region_maincpu->base(); + } +} + +/************************************************************************ + * bbc_vh_start + * Initialize the BBC video emulation + ************************************************************************/ + +void bbc_state::common_init(int memorySize) +{ + m_emulation_cursor_size = 1; + + m_VideoULA_CR = 7; + m_VideoULA_CR_counter = 0; + + set_pixel_lookup(); + + m_BBC_Video_RAM = m_region_maincpu->base(); + m_memorySize=memorySize; + +} + +VIDEO_START_MEMBER(bbc_state,bbca) +{ + common_init(m_ram->size()/1024); +} + +VIDEO_START_MEMBER(bbc_state,bbcb) +{ + common_init(32); +} + +VIDEO_START_MEMBER(bbc_state,bbcbp) +{ + common_init(32); +} + +VIDEO_START_MEMBER(bbc_state,bbcm) +{ + common_init(32); +} |