mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
x1.cpp: moved video functions into own file, also improved OO ownership of variables and functions [Angelo Salese]
This commit is contained in:
parent
d36a79d7e7
commit
29d963a4fb
@ -2915,6 +2915,7 @@ files {
|
||||
MAME_DIR .. "src/mame/drivers/x1.cpp",
|
||||
MAME_DIR .. "src/mame/includes/x1.h",
|
||||
MAME_DIR .. "src/mame/machine/x1.cpp",
|
||||
MAME_DIR .. "src/mame/video/x1.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/x1twin.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/mz2500.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/mz3500.cpp",
|
||||
|
@ -209,7 +209,6 @@
|
||||
#include "emu.h"
|
||||
#include "includes/x1.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "softlist.h"
|
||||
#include "speaker.h"
|
||||
|
||||
@ -220,350 +219,6 @@
|
||||
#define VDP_CLOCK XTAL(42'954'545)
|
||||
#define MCU_CLOCK XTAL(6'000'000)
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Video Functions
|
||||
*
|
||||
*************************************/
|
||||
|
||||
VIDEO_START_MEMBER(x1_state,x1)
|
||||
{
|
||||
m_avram = make_unique_clear<uint8_t[]>(0x800);
|
||||
m_tvram = make_unique_clear<uint8_t[]>(0x800);
|
||||
m_kvram = make_unique_clear<uint8_t[]>(0x800);
|
||||
m_gfx_bitmap_ram = make_unique_clear<uint8_t[]>(0xc000*2);
|
||||
m_pal_4096 = make_unique_clear<uint8_t[]>(0x1000*3);
|
||||
}
|
||||
|
||||
void x1_state::x1_draw_pixel(bitmap_rgb32 &bitmap,int y,int x,uint16_t pen,uint8_t width,uint8_t height)
|
||||
{
|
||||
if(!machine().first_screen()->visible_area().contains(x, y))
|
||||
return;
|
||||
|
||||
if(width && height)
|
||||
{
|
||||
bitmap.pix32(y+0+m_ystart, x+0+m_xstart) = m_palette->pen(pen);
|
||||
bitmap.pix32(y+0+m_ystart, x+1+m_xstart) = m_palette->pen(pen);
|
||||
bitmap.pix32(y+1+m_ystart, x+0+m_xstart) = m_palette->pen(pen);
|
||||
bitmap.pix32(y+1+m_ystart, x+1+m_xstart) = m_palette->pen(pen);
|
||||
}
|
||||
else if(width)
|
||||
{
|
||||
bitmap.pix32(y+m_ystart, x+0+m_xstart) = m_palette->pen(pen);
|
||||
bitmap.pix32(y+m_ystart, x+1+m_xstart) = m_palette->pen(pen);
|
||||
}
|
||||
else if(height)
|
||||
{
|
||||
bitmap.pix32(y+0+m_ystart, x+m_xstart) = m_palette->pen(pen);
|
||||
bitmap.pix32(y+1+m_ystart, x+m_xstart) = m_palette->pen(pen);
|
||||
}
|
||||
else
|
||||
bitmap.pix32(y+m_ystart, x+m_xstart) = m_palette->pen(pen);
|
||||
}
|
||||
|
||||
#define mc6845_h_char_total (m_crtc_vreg[0])
|
||||
#define mc6845_h_display (m_crtc_vreg[1])
|
||||
#define mc6845_h_sync_pos (m_crtc_vreg[2])
|
||||
#define mc6845_sync_width (m_crtc_vreg[3])
|
||||
#define mc6845_v_char_total (m_crtc_vreg[4])
|
||||
#define mc6845_v_total_adj (m_crtc_vreg[5])
|
||||
#define mc6845_v_display (m_crtc_vreg[6])
|
||||
#define mc6845_v_sync_pos (m_crtc_vreg[7])
|
||||
#define mc6845_mode_ctrl (m_crtc_vreg[8])
|
||||
#define mc6845_tile_height (m_crtc_vreg[9]+1)
|
||||
#define mc6845_cursor_y_start (m_crtc_vreg[0x0a])
|
||||
#define mc6845_cursor_y_end (m_crtc_vreg[0x0b])
|
||||
#define mc6845_start_addr (((m_crtc_vreg[0x0c]<<8) & 0x3f00) | (m_crtc_vreg[0x0d] & 0xff))
|
||||
#define mc6845_cursor_addr (((m_crtc_vreg[0x0e]<<8) & 0x3f00) | (m_crtc_vreg[0x0f] & 0xff))
|
||||
#define mc6845_light_pen_addr (((m_crtc_vreg[0x10]<<8) & 0x3f00) | (m_crtc_vreg[0x11] & 0xff))
|
||||
#define mc6845_update_addr (((m_crtc_vreg[0x12]<<8) & 0x3f00) | (m_crtc_vreg[0x13] & 0xff))
|
||||
|
||||
|
||||
/* adjust tile index when we are under double height condition */
|
||||
uint8_t x1_state::check_prev_height(int x,int y,int x_size)
|
||||
{
|
||||
uint8_t prev_tile = m_tvram[(x+((y-1)*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
uint8_t cur_tile = m_tvram[(x+(y*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
uint8_t prev_attr = m_avram[(x+((y-1)*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
uint8_t cur_attr = m_avram[(x+(y*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
|
||||
if(prev_tile == cur_tile && prev_attr == cur_attr)
|
||||
return 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Exoa II - Warroid: if double height isn't enabled on the first tile of the line then double height is disabled on everything else. */
|
||||
uint8_t x1_state::check_line_valid_height(int y,int x_size,int height)
|
||||
{
|
||||
uint8_t line_attr = m_avram[(0+(y*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
|
||||
if((line_attr & 0x40) == 0)
|
||||
return 0;
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
void x1_state::draw_fgtilemap(bitmap_rgb32 &bitmap,const rectangle &cliprect)
|
||||
{
|
||||
/*
|
||||
attribute table:
|
||||
x--- ---- double width
|
||||
-x-- ---- double height
|
||||
--x- ---- PCG select
|
||||
---x ---- color blinking
|
||||
---- x--- reverse color
|
||||
---- -xxx color pen
|
||||
|
||||
x--- ---- select Kanji ROM
|
||||
-x-- ---- Kanji side (0=left, 1=right)
|
||||
--x- ---- Underline
|
||||
---x ---- Kanji ROM select (0=level 1, 1=level 2) (TODO: implement this)
|
||||
---- xxxx Kanji upper 4 bits
|
||||
*/
|
||||
|
||||
int y,x,res_x,res_y;
|
||||
uint32_t tile_offset;
|
||||
uint8_t x_size,y_size;
|
||||
|
||||
x_size = mc6845_h_display;
|
||||
y_size = mc6845_v_display;
|
||||
|
||||
if(x_size == 0 || y_size == 0)
|
||||
return; //don't bother if screen is off
|
||||
|
||||
if(x_size != 80 && x_size != 40 && y_size != 25)
|
||||
popmessage("%d %d",x_size,y_size);
|
||||
|
||||
for (y=0;y<y_size;y++)
|
||||
{
|
||||
for (x=0;x<x_size;x++)
|
||||
{
|
||||
int tile = m_tvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
int color = m_avram[((x+y*x_size)+mc6845_start_addr) & 0x7ff] & 0x1f;
|
||||
int width = BIT(m_avram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 7);
|
||||
int height = BIT(m_avram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 6);
|
||||
int pcg_bank = BIT(m_avram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 5);
|
||||
uint8_t *gfx_data = pcg_bank ? m_pcg_ram.get() : m_cg_rom; //machine.root_device().memregion(pcg_bank ? "pcg" : "cgrom")->base();
|
||||
int knj_enable = 0;
|
||||
int knj_side = 0;
|
||||
int knj_bank = 0;
|
||||
int knj_uline = 0;
|
||||
if(m_is_turbo)
|
||||
{
|
||||
knj_enable = BIT(m_kvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 7);
|
||||
knj_side = BIT(m_kvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 6);
|
||||
knj_uline = BIT(m_kvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 5);
|
||||
//knj_lv2 = BIT(m_kvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 4);
|
||||
knj_bank = m_kvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff] & 0x0f;
|
||||
if(knj_enable)
|
||||
{
|
||||
gfx_data = m_kanji_rom;
|
||||
tile = ((tile + (knj_bank << 8)) << 1) + (knj_side & 1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int pen[3],pen_mask,pcg_pen,xi,yi,dy;
|
||||
|
||||
pen_mask = color & 7;
|
||||
|
||||
dy = 0;
|
||||
|
||||
height = check_line_valid_height(y,x_size,height);
|
||||
|
||||
if(height && y)
|
||||
dy = check_prev_height(x,y,x_size);
|
||||
|
||||
/* guess: assume that Kanji VRAM doesn't double the vertical size */
|
||||
if(knj_enable) { height = 0; }
|
||||
|
||||
for(yi=0;yi<mc6845_tile_height;yi++)
|
||||
{
|
||||
for(xi=0;xi<8;xi++)
|
||||
{
|
||||
if(knj_enable) //kanji select
|
||||
{
|
||||
tile_offset = tile * 16;
|
||||
tile_offset += (yi+dy*(m_scrn_reg.v400_mode+1)) >> (height+m_scrn_reg.v400_mode);
|
||||
pen[0] = gfx_data[tile_offset+0x0000]>>(7-xi) & (pen_mask & 1)>>0;
|
||||
pen[1] = gfx_data[tile_offset+0x0000]>>(7-xi) & (pen_mask & 2)>>1;
|
||||
pen[2] = gfx_data[tile_offset+0x0000]>>(7-xi) & (pen_mask & 4)>>2;
|
||||
|
||||
if(yi == mc6845_tile_height-1 && knj_uline) //underlined attribute
|
||||
{
|
||||
pen[0] = (pen_mask & 1)>>0;
|
||||
pen[1] = (pen_mask & 2)>>1;
|
||||
pen[2] = (pen_mask & 4)>>2;
|
||||
}
|
||||
|
||||
if((yi >= 16 && m_scrn_reg.v400_mode == 0) || (yi >= 32 && m_scrn_reg.v400_mode == 1))
|
||||
pen[0] = pen[1] = pen[2] = 0;
|
||||
}
|
||||
else if(pcg_bank) // PCG
|
||||
{
|
||||
tile_offset = tile * 8;
|
||||
tile_offset += (yi+dy*(m_scrn_reg.v400_mode+1)) >> (height+m_scrn_reg.v400_mode);
|
||||
|
||||
pen[0] = gfx_data[tile_offset+0x0000]>>(7-xi) & (pen_mask & 1)>>0;
|
||||
pen[1] = gfx_data[tile_offset+0x0800]>>(7-xi) & (pen_mask & 2)>>1;
|
||||
pen[2] = gfx_data[tile_offset+0x1000]>>(7-xi) & (pen_mask & 4)>>2;
|
||||
|
||||
if((yi >= 8 && m_scrn_reg.v400_mode == 0) || (yi >= 16 && m_scrn_reg.v400_mode == 1))
|
||||
pen[0] = pen[1] = pen[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tile_offset = tile * (8*(m_scrn_reg.ank_sel+1));
|
||||
tile_offset += (yi+dy*(m_scrn_reg.v400_mode+1)) >> (height+m_scrn_reg.v400_mode);
|
||||
|
||||
pen[0] = gfx_data[tile_offset+m_scrn_reg.ank_sel*0x0800]>>(7-xi) & (pen_mask & 1)>>0;
|
||||
pen[1] = gfx_data[tile_offset+m_scrn_reg.ank_sel*0x0800]>>(7-xi) & (pen_mask & 2)>>1;
|
||||
pen[2] = gfx_data[tile_offset+m_scrn_reg.ank_sel*0x0800]>>(7-xi) & (pen_mask & 4)>>2;
|
||||
|
||||
if(m_scrn_reg.ank_sel)
|
||||
{
|
||||
if((yi >= 16 && m_scrn_reg.v400_mode == 0) || (yi >= 32 && m_scrn_reg.v400_mode == 1))
|
||||
pen[0] = pen[1] = pen[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((yi >= 8 && m_scrn_reg.v400_mode == 0) || (yi >= 16 && m_scrn_reg.v400_mode == 1))
|
||||
pen[0] = pen[1] = pen[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pcg_pen = pen[2]<<2|pen[1]<<1|pen[0]<<0;
|
||||
|
||||
if(color & 0x10 && machine().first_screen()->frame_number() & 0x10) //reverse flickering
|
||||
pcg_pen^=7;
|
||||
|
||||
if(pcg_pen == 0 && (!(color & 8)))
|
||||
continue;
|
||||
|
||||
if(color & 8) //revert the used color pen
|
||||
pcg_pen^=7;
|
||||
|
||||
if((m_scrn_reg.blackclip & 8) && (color == (m_scrn_reg.blackclip & 7)))
|
||||
pcg_pen = 0; // clip the pen to black
|
||||
|
||||
res_x = x*8+xi*(width+1);
|
||||
res_y = y*(mc6845_tile_height)+yi;
|
||||
|
||||
if(res_y < cliprect.min_y || res_y > cliprect.max_y) // partial update, TODO: optimize
|
||||
continue;
|
||||
|
||||
x1_draw_pixel(bitmap,res_y,res_x,pcg_pen,width,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(width) //skip next char if we are under double width condition
|
||||
x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Priority Mixer Calculation (pri)
|
||||
*
|
||||
* If pri is 0xff then the bitmap entirely covers the tilemap, if it's 0x00 then
|
||||
* the tilemap priority is entirely above the bitmap. Any other value mixes the
|
||||
* bitmap and the tilemap priorities based on the pen value, bit 0 = entry 0 <-> bit 7 = entry 7
|
||||
* of the bitmap.
|
||||
*
|
||||
*/
|
||||
int x1_state::priority_mixer_pri(int color)
|
||||
{
|
||||
int pri_i,pri_mask_calc;
|
||||
|
||||
pri_i = 0;
|
||||
pri_mask_calc = 1;
|
||||
|
||||
while(pri_i < 7)
|
||||
{
|
||||
if((color & 7) == pri_i)
|
||||
break;
|
||||
|
||||
pri_i++;
|
||||
pri_mask_calc<<=1;
|
||||
}
|
||||
|
||||
return pri_mask_calc;
|
||||
}
|
||||
|
||||
void x1_state::draw_gfxbitmap(bitmap_rgb32 &bitmap,const rectangle &cliprect, int plane,int pri)
|
||||
{
|
||||
int xi,yi,x,y;
|
||||
int pen_r,pen_g,pen_b,color;
|
||||
int pri_mask_val;
|
||||
uint8_t x_size,y_size;
|
||||
int gfx_offset;
|
||||
|
||||
x_size = mc6845_h_display;
|
||||
y_size = mc6845_v_display;
|
||||
|
||||
if(x_size == 0 || y_size == 0)
|
||||
return; //don't bother if screen is off
|
||||
|
||||
if(x_size != 80 && x_size != 40 && y_size != 25)
|
||||
popmessage("%d %d",x_size,y_size);
|
||||
|
||||
//popmessage("%04x %02x",mc6845_start_addr,mc6845_tile_height);
|
||||
|
||||
for (y=0;y<y_size;y++)
|
||||
{
|
||||
for(x=0;x<x_size;x++)
|
||||
{
|
||||
for(yi=0;yi<(mc6845_tile_height);yi++)
|
||||
{
|
||||
for(xi=0;xi<8;xi++)
|
||||
{
|
||||
gfx_offset = ((x+(y*x_size)) + mc6845_start_addr) & 0x7ff;
|
||||
gfx_offset+= ((yi >> m_scrn_reg.v400_mode) * 0x800) & 0x3fff;
|
||||
pen_b = (m_gfx_bitmap_ram[gfx_offset+0x0000+plane*0xc000]>>(7-xi)) & 1;
|
||||
pen_r = (m_gfx_bitmap_ram[gfx_offset+0x4000+plane*0xc000]>>(7-xi)) & 1;
|
||||
pen_g = (m_gfx_bitmap_ram[gfx_offset+0x8000+plane*0xc000]>>(7-xi)) & 1;
|
||||
|
||||
color = (pen_g<<2 | pen_r<<1 | pen_b<<0) | 8;
|
||||
|
||||
pri_mask_val = priority_mixer_pri(color);
|
||||
if(pri_mask_val & pri) continue;
|
||||
|
||||
if((color == 8 && m_scrn_reg.blackclip & 0x10) || (color == 9 && m_scrn_reg.blackclip & 0x20)) // bitmap color clip to black conditions
|
||||
color = 0;
|
||||
|
||||
if(y*(mc6845_tile_height)+yi < cliprect.min_y || y*(mc6845_tile_height)+yi > cliprect.max_y) // partial update TODO: optimize
|
||||
continue;
|
||||
|
||||
x1_draw_pixel(bitmap,y*(mc6845_tile_height)+yi,x*8+xi,color,0,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t x1_state::screen_update_x1(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bitmap.fill(rgb_t(0xff,0x00,0x00,0x00), cliprect);
|
||||
|
||||
/* TODO: correct calculation thru mc6845 regs */
|
||||
m_xstart = ((mc6845_h_char_total - mc6845_h_sync_pos) * 8) / 2;
|
||||
m_ystart = ((mc6845_v_char_total - mc6845_v_sync_pos) * 8) / 2;
|
||||
|
||||
// popmessage("%d %d %d %d",mc6845_h_sync_pos,mc6845_v_sync_pos,mc6845_h_char_total,mc6845_v_char_total);
|
||||
|
||||
draw_gfxbitmap(bitmap,cliprect,m_scrn_reg.disp_bank,m_scrn_reg.pri);
|
||||
draw_fgtilemap(bitmap,cliprect);
|
||||
draw_gfxbitmap(bitmap,cliprect,m_scrn_reg.disp_bank,m_scrn_reg.pri^0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Keyboard MCU simulation
|
||||
@ -1197,8 +852,8 @@ uint16_t x1_state::check_chr_addr()
|
||||
|
||||
uint16_t x1_state::get_pcg_addr( uint16_t width, uint8_t y_char_size )
|
||||
{
|
||||
int hbeam = machine().first_screen()->hpos() >> 3;
|
||||
int vbeam = machine().first_screen()->vpos() / y_char_size;
|
||||
int hbeam = m_screen->hpos() >> 3;
|
||||
int vbeam = m_screen->vpos() / y_char_size;
|
||||
uint16_t pcg_offset = ((hbeam + vbeam*width) + (((m_crtc_vreg[0x0c]<<8) & 0x3f00) | (m_crtc_vreg[0x0d] & 0xff))) & 0x7ff;
|
||||
|
||||
//printf("%08x %d %d %d %d\n",(hbeam+vbeam*width),hbeam,vbeam,machine.first_screen()->vpos() & 7,width);
|
||||
@ -1234,7 +889,7 @@ READ8_MEMBER( x1_state::x1_pcg_r )
|
||||
y_char_size = ((m_crtc_vreg[9]+1) > 8) ? 8 : m_crtc_vreg[9]+1;
|
||||
if(y_char_size == 0) { y_char_size = 1; }
|
||||
pcg_offset = m_tvram[get_pcg_addr(m_crtc_vreg[1], y_char_size)]*8;
|
||||
pcg_offset+= machine().first_screen()->vpos() & (y_char_size-1);
|
||||
pcg_offset+= m_screen->vpos() & (y_char_size-1);
|
||||
if(addr) { pcg_offset+= ((addr-1)*0x800); }
|
||||
res = gfx_data[pcg_offset];
|
||||
}
|
||||
@ -1274,7 +929,7 @@ WRITE8_MEMBER( x1_state::x1_pcg_w )
|
||||
y_char_size = (m_crtc_vreg[9]+1) > 8 ? (m_crtc_vreg[9]+1)-8 : m_crtc_vreg[9]+1;
|
||||
if(y_char_size == 0) { y_char_size = 1; }
|
||||
pcg_offset = m_tvram[get_pcg_addr(m_crtc_vreg[1], y_char_size)]*8;
|
||||
pcg_offset+= machine().first_screen()->vpos() & (y_char_size-1);
|
||||
pcg_offset+= m_screen->vpos() & (y_char_size-1);
|
||||
pcg_offset+= ((addr-1)*0x800);
|
||||
|
||||
m_pcg_ram[pcg_offset] = data;
|
||||
@ -1308,7 +963,7 @@ void x1_state::set_current_palette()
|
||||
|
||||
// TODO: disabled for now, causes issues with Thunder Force. x1fdemo changes palette dynamically during initial logo.
|
||||
// Likely it needs a video rewrite in order to make this to work correctly.
|
||||
// machine().first_screen()->update_partial(machine().first_screen()->vpos());
|
||||
// m_screen->update_partial(m_screen->vpos());
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( x1_state::x1turboz_4096_palette_w )
|
||||
@ -1892,8 +1547,8 @@ READ8_MEMBER( x1_state::x1_portb_r )
|
||||
uint8_t res = 0;
|
||||
int vblank_line = m_crtc_vreg[6] * (m_crtc_vreg[9]+1);
|
||||
int vsync_line = m_crtc_vreg[7] * (m_crtc_vreg[9]+1);
|
||||
m_vdisp = (machine().first_screen()->vpos() < vblank_line) ? 0x80 : 0x00;
|
||||
m_vsync = (machine().first_screen()->vpos() < vsync_line) ? 0x00 : 0x04;
|
||||
m_vdisp = (m_screen->vpos() < vblank_line) ? 0x80 : 0x00;
|
||||
m_vsync = (m_screen->vpos() < vsync_line) ? 0x00 : 0x04;
|
||||
|
||||
// popmessage("%d",vsync_line);
|
||||
// popmessage("%d",vblank_line);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "formats/x1_tap.h"
|
||||
#include "bus/generic/slot.h"
|
||||
#include "bus/generic/carts.h"
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
// ======================> x1_keyboard_device
|
||||
@ -50,32 +51,6 @@ private:
|
||||
class x1_state : public driver_device
|
||||
{
|
||||
public:
|
||||
struct scrn_reg_t
|
||||
{
|
||||
uint8_t gfx_bank;
|
||||
uint8_t disp_bank;
|
||||
uint8_t pcg_mode;
|
||||
uint8_t v400_mode;
|
||||
uint8_t ank_sel;
|
||||
|
||||
uint8_t pri;
|
||||
uint8_t blackclip; // x1 turbo specific
|
||||
};
|
||||
|
||||
struct turbo_reg_t
|
||||
{
|
||||
uint8_t pal;
|
||||
uint8_t gfx_pal;
|
||||
uint8_t txt_pal[8];
|
||||
uint8_t txt_disp;
|
||||
};
|
||||
|
||||
struct x1_rtc_t
|
||||
{
|
||||
uint8_t sec, min, hour, day, wday, month, year;
|
||||
};
|
||||
|
||||
|
||||
x1_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this,"x1_cpu"),
|
||||
@ -88,6 +63,7 @@ public:
|
||||
m_floppy3(*this, "fdc:3"),
|
||||
m_crtc(*this, "crtc"),
|
||||
m_ctc(*this, "ctc"),
|
||||
m_screen(*this, "screen"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_palette(*this, "palette"),
|
||||
m_dma(*this, "dma")
|
||||
@ -105,117 +81,7 @@ public:
|
||||
required_device<floppy_connector> m_floppy3;
|
||||
required_device<mc6845_device> m_crtc;
|
||||
required_device<z80ctc_device> m_ctc;
|
||||
|
||||
std::unique_ptr<uint8_t[]> m_tvram; /**< Pointer for Text Video RAM */
|
||||
std::unique_ptr<uint8_t[]> m_avram; /**< Pointer for Attribute Video RAM */
|
||||
std::unique_ptr<uint8_t[]> m_kvram; /**< Pointer for Extended Kanji Video RAM (X1 Turbo) */
|
||||
uint8_t *m_ipl_rom; /**< Pointer for IPL ROM */
|
||||
std::unique_ptr<uint8_t[]> m_work_ram; /**< Pointer for base work RAM */
|
||||
std::unique_ptr<uint8_t[]> m_emm_ram; /**< Pointer for EMM RAM */
|
||||
std::unique_ptr<uint8_t[]> m_pcg_ram; /**< Pointer for PCG GFX RAM */
|
||||
uint8_t *m_cg_rom; /**< Pointer for GFX ROM */
|
||||
uint8_t *m_kanji_rom; /**< Pointer for Kanji ROMs */
|
||||
int m_xstart, /**< Start X offset for screen drawing. */
|
||||
m_ystart; /**< Start Y offset for screen drawing. */
|
||||
uint8_t m_hres_320; /**< Pixel clock divider setting: (1) 48 (0) 24 */
|
||||
uint8_t m_io_switch; /**< Enable access for special bitmap RMW phase in isolated i/o. */
|
||||
uint8_t m_io_sys; /**< Read-back for PPI port C */
|
||||
uint8_t m_vsync; /**< Screen V-Sync bit, active low */
|
||||
uint8_t m_vdisp; /**< Screen V-Disp bit, active high */
|
||||
uint8_t m_io_bank_mode; /**< Helper for special bitmap RMW phase. */
|
||||
std::unique_ptr<uint8_t[]> m_gfx_bitmap_ram; /**< Pointer for bitmap layer RAM. */
|
||||
uint8_t m_pcg_reset; /**< @todo Unused variable. */
|
||||
uint8_t m_sub_obf; /**< MCU side: OBF flag active low, indicates that there are parameters in comm buffer. */
|
||||
uint8_t m_ctc_irq_flag; /**< @todo Unused variable. */
|
||||
scrn_reg_t m_scrn_reg; /**< Base Video Registers. */
|
||||
turbo_reg_t m_turbo_reg; /**< Turbo Z Video Registers. */
|
||||
x1_rtc_t m_rtc; /**< Struct for RTC related variables */
|
||||
emu_timer *m_rtc_timer; /**< Pointer for RTC timer. */
|
||||
uint8_t m_pcg_write_addr; /**< @todo Unused variable. */
|
||||
uint8_t m_sub_cmd; /**< MCU side: current command issued from Main to Sub. */
|
||||
uint8_t m_sub_cmd_length; /**< MCU side: number of parameters, in bytes. */
|
||||
uint8_t m_sub_val[8]; /**< MCU side: parameters buffer. */
|
||||
int m_sub_val_ptr; /**< MCU side: index for parameter read-back */
|
||||
int m_key_i; /**< MCU side: index for keyboard read-back during OBF phase. */
|
||||
uint8_t m_irq_vector; /**< @todo Unused variable. */
|
||||
uint8_t m_cmt_current_cmd; /**< MCU side: CMT command issued. */
|
||||
uint8_t m_cmt_test; /**< MCU side: Tape BREAK status bit. */
|
||||
uint8_t m_rom_index[3]; /**< Current ROM address. */
|
||||
uint32_t m_kanji_offset; /**< @todo Unused variable. */
|
||||
uint8_t m_bios_offset; /**< @todo Unused variable. */
|
||||
uint8_t m_x_b; /**< Palette Register for Blue Gun */
|
||||
uint8_t m_x_g; /**< Palette Register for Green Gun */
|
||||
uint8_t m_x_r; /**< Palette Register for Red Gun */
|
||||
uint16_t m_kanji_addr_latch; /**< Internal Kanji ROM address. */
|
||||
uint32_t m_kanji_addr; /**< Latched Kanji ROM address. */
|
||||
uint8_t m_kanji_eksel; /**< Kanji ROM register bit for latch phase. */
|
||||
uint8_t m_pcg_reset_occurred; /**< @todo Unused variable. */
|
||||
uint32_t m_old_key1; /**< Keyboard read buffer for i/o port "key1" */
|
||||
uint32_t m_old_key2; /**< Keyboard read buffer for i/o port "key2" */
|
||||
uint32_t m_old_key3; /**< Keyboard read buffer for i/o port "key3" */
|
||||
uint32_t m_old_key4; /**< Keyboard read buffer for i/o port "tenkey" */
|
||||
uint32_t m_old_fkey; /**< Keyboard read buffer for i/o port "f_keys" */
|
||||
uint8_t m_key_irq_flag; /**< Keyboard IRQ pending. */
|
||||
uint8_t m_key_irq_vector; /**< Keyboard IRQ vector. */
|
||||
uint32_t m_emm_addr; /**< EMM RAM current address */
|
||||
std::unique_ptr<uint8_t[]> m_pal_4096; /**< X1 Turbo Z: pointer for 4096 palette entries */
|
||||
uint8_t m_crtc_vreg[0x100], /**< CRTC register buffer. */
|
||||
m_crtc_index; /**< CRTC register index. */
|
||||
uint8_t m_is_turbo; /**< Machine type: (0) X1 Vanilla, (1) X1 Turbo */
|
||||
uint8_t m_ex_bank; /**< X1 Turbo Z: RAM bank register */
|
||||
uint8_t m_ram_bank; /**< Regular RAM bank for 0x0000-0x7fff memory window: (0) ROM/IPL (1) RAM */
|
||||
/**
|
||||
@brief Refresh current bitmap palette.
|
||||
*/
|
||||
void set_current_palette();
|
||||
/**
|
||||
@brief Retrieves the current PCG address.
|
||||
|
||||
@param width Number of currently setted up CRTC characters
|
||||
@param y_char_size Number of scanlines per character.
|
||||
@return Destination PCG address.
|
||||
*/
|
||||
uint16_t get_pcg_addr(uint16_t width, uint8_t y_char_size);
|
||||
/**
|
||||
@brief X1 Turbo: Retrieves the current CHR ROM address in Hi-Speed Mode.
|
||||
|
||||
@return Destination CHR address.
|
||||
*/
|
||||
uint16_t check_chr_addr();
|
||||
/**
|
||||
@brief X1 Turbo: Retrieves the current PCG ROM address in Hi-Speed Mode.
|
||||
|
||||
@return Destination CHR address.
|
||||
*/
|
||||
uint16_t check_pcg_addr();
|
||||
/**
|
||||
@brief MCU side: retrieve keycode to game key conversion.
|
||||
|
||||
@param port Address to convert.
|
||||
@return The converted game key buffer
|
||||
*/
|
||||
uint8_t get_game_key(uint8_t port);
|
||||
/**
|
||||
@brief MCU side: retrieve keyboard special key register.
|
||||
|
||||
@return
|
||||
x--- ---- TEN: Numpad, Function key, special input key
|
||||
-x-- ---- KIN: Valid key
|
||||
--x- ---- REP: Key repeat
|
||||
---x ---- GRAPH key ON
|
||||
---- x--- CAPS lock ON
|
||||
---- -x-- KANA lock ON
|
||||
---- --x- SHIFT ON
|
||||
---- ---x CTRL ON
|
||||
*/
|
||||
uint8_t check_keyboard_shift();
|
||||
/**
|
||||
@brief convert MAME input to raw scancode for keyboard.
|
||||
|
||||
@return the converted scancode
|
||||
@todo Unoptimized.
|
||||
*/
|
||||
uint16_t check_keyboard_press();
|
||||
required_device<screen_device> m_screen;
|
||||
|
||||
DECLARE_READ8_MEMBER(x1_mem_r);
|
||||
DECLARE_WRITE8_MEMBER(x1_mem_w);
|
||||
@ -279,7 +145,45 @@ public:
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(x1_keyboard_callback);
|
||||
DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(hdl_w);
|
||||
uint8_t m_fdc_ctrl;
|
||||
|
||||
DECLARE_READ8_MEMBER(memory_read_byte);
|
||||
DECLARE_WRITE8_MEMBER(memory_write_byte);
|
||||
DECLARE_READ8_MEMBER(io_read_byte);
|
||||
DECLARE_WRITE8_MEMBER(io_write_byte);
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
optional_device<z80dma_device> m_dma;
|
||||
void x1turbo(machine_config &config);
|
||||
void x1(machine_config &config);
|
||||
|
||||
uint8_t m_key_irq_flag; /**< Keyboard IRQ pending. */
|
||||
uint8_t m_key_irq_vector; /**< Keyboard IRQ vector. */
|
||||
|
||||
private:
|
||||
struct scrn_reg_t
|
||||
{
|
||||
uint8_t gfx_bank;
|
||||
uint8_t disp_bank;
|
||||
uint8_t pcg_mode;
|
||||
uint8_t v400_mode;
|
||||
uint8_t ank_sel;
|
||||
|
||||
uint8_t pri;
|
||||
uint8_t blackclip; // x1 turbo specific
|
||||
};
|
||||
|
||||
struct turbo_reg_t
|
||||
{
|
||||
uint8_t pal;
|
||||
uint8_t gfx_pal;
|
||||
uint8_t txt_pal[8];
|
||||
uint8_t txt_disp;
|
||||
};
|
||||
|
||||
struct x1_rtc_t
|
||||
{
|
||||
uint8_t sec, min, hour, day, wday, month, year;
|
||||
};
|
||||
|
||||
void x1_draw_pixel(bitmap_rgb32 &bitmap,int y,int x,uint16_t pen,uint8_t width,uint8_t height);
|
||||
void draw_fgtilemap(bitmap_rgb32 &bitmap,const rectangle &cliprect);
|
||||
@ -291,15 +195,117 @@ public:
|
||||
void cmt_command( uint8_t cmd );
|
||||
uint16_t jis_convert(int kanji_addr);
|
||||
|
||||
DECLARE_READ8_MEMBER(memory_read_byte);
|
||||
DECLARE_WRITE8_MEMBER(memory_write_byte);
|
||||
DECLARE_READ8_MEMBER(io_read_byte);
|
||||
DECLARE_WRITE8_MEMBER(io_write_byte);
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
optional_device<z80dma_device> m_dma;
|
||||
void x1turbo(machine_config &config);
|
||||
void x1(machine_config &config);
|
||||
std::unique_ptr<uint8_t[]> m_tvram; /**< Pointer for Text Video RAM */
|
||||
std::unique_ptr<uint8_t[]> m_avram; /**< Pointer for Attribute Video RAM */
|
||||
std::unique_ptr<uint8_t[]> m_kvram; /**< Pointer for Extended Kanji Video RAM (X1 Turbo) */
|
||||
uint8_t *m_ipl_rom; /**< Pointer for IPL ROM */
|
||||
std::unique_ptr<uint8_t[]> m_work_ram; /**< Pointer for base work RAM */
|
||||
std::unique_ptr<uint8_t[]> m_emm_ram; /**< Pointer for EMM RAM */
|
||||
std::unique_ptr<uint8_t[]> m_pcg_ram; /**< Pointer for PCG GFX RAM */
|
||||
uint8_t *m_cg_rom; /**< Pointer for GFX ROM */
|
||||
uint8_t *m_kanji_rom; /**< Pointer for Kanji ROMs */
|
||||
int m_xstart, /**< Start X offset for screen drawing. */
|
||||
m_ystart; /**< Start Y offset for screen drawing. */
|
||||
uint8_t m_hres_320; /**< Pixel clock divider setting: (1) 48 (0) 24 */
|
||||
uint8_t m_io_switch; /**< Enable access for special bitmap RMW phase in isolated i/o. */
|
||||
uint8_t m_io_sys; /**< Read-back for PPI port C */
|
||||
uint8_t m_vsync; /**< Screen V-Sync bit, active low */
|
||||
uint8_t m_vdisp; /**< Screen V-Disp bit, active high */
|
||||
uint8_t m_io_bank_mode; /**< Helper for special bitmap RMW phase. */
|
||||
std::unique_ptr<uint8_t[]> m_gfx_bitmap_ram; /**< Pointer for bitmap layer RAM. */
|
||||
uint8_t m_pcg_reset; /**< @todo Unused variable. */
|
||||
uint8_t m_sub_obf; /**< MCU side: OBF flag active low, indicates that there are parameters in comm buffer. */
|
||||
uint8_t m_ctc_irq_flag; /**< @todo Unused variable. */
|
||||
scrn_reg_t m_scrn_reg; /**< Base Video Registers. */
|
||||
turbo_reg_t m_turbo_reg; /**< Turbo Z Video Registers. */
|
||||
x1_rtc_t m_rtc; /**< Struct for RTC related variables */
|
||||
emu_timer *m_rtc_timer; /**< Pointer for RTC timer. */
|
||||
uint8_t m_pcg_write_addr; /**< @todo Unused variable. */
|
||||
uint8_t m_sub_cmd; /**< MCU side: current command issued from Main to Sub. */
|
||||
uint8_t m_sub_cmd_length; /**< MCU side: number of parameters, in bytes. */
|
||||
uint8_t m_sub_val[8]; /**< MCU side: parameters buffer. */
|
||||
int m_sub_val_ptr; /**< MCU side: index for parameter read-back */
|
||||
int m_key_i; /**< MCU side: index for keyboard read-back during OBF phase. */
|
||||
uint8_t m_irq_vector; /**< @todo Unused variable. */
|
||||
uint8_t m_cmt_current_cmd; /**< MCU side: CMT command issued. */
|
||||
uint8_t m_cmt_test; /**< MCU side: Tape BREAK status bit. */
|
||||
uint8_t m_rom_index[3]; /**< Current ROM address. */
|
||||
uint32_t m_kanji_offset; /**< @todo Unused variable. */
|
||||
uint8_t m_bios_offset; /**< @todo Unused variable. */
|
||||
uint8_t m_x_b; /**< Palette Register for Blue Gun */
|
||||
uint8_t m_x_g; /**< Palette Register for Green Gun */
|
||||
uint8_t m_x_r; /**< Palette Register for Red Gun */
|
||||
uint16_t m_kanji_addr_latch; /**< Internal Kanji ROM address. */
|
||||
uint32_t m_kanji_addr; /**< Latched Kanji ROM address. */
|
||||
uint8_t m_kanji_eksel; /**< Kanji ROM register bit for latch phase. */
|
||||
uint8_t m_pcg_reset_occurred; /**< @todo Unused variable. */
|
||||
uint32_t m_old_key1; /**< Keyboard read buffer for i/o port "key1" */
|
||||
uint32_t m_old_key2; /**< Keyboard read buffer for i/o port "key2" */
|
||||
uint32_t m_old_key3; /**< Keyboard read buffer for i/o port "key3" */
|
||||
uint32_t m_old_key4; /**< Keyboard read buffer for i/o port "tenkey" */
|
||||
uint32_t m_old_fkey; /**< Keyboard read buffer for i/o port "f_keys" */
|
||||
uint32_t m_emm_addr; /**< EMM RAM current address */
|
||||
std::unique_ptr<uint8_t[]> m_pal_4096; /**< X1 Turbo Z: pointer for 4096 palette entries */
|
||||
uint8_t m_crtc_vreg[0x100], /**< CRTC register buffer. */
|
||||
m_crtc_index; /**< CRTC register index. */
|
||||
uint8_t m_is_turbo; /**< Machine type: (0) X1 Vanilla, (1) X1 Turbo */
|
||||
uint8_t m_ex_bank; /**< X1 Turbo Z: RAM bank register */
|
||||
uint8_t m_ram_bank; /**< Regular RAM bank for 0x0000-0x7fff memory window: (0) ROM/IPL (1) RAM */
|
||||
/**
|
||||
@brief Refresh current bitmap palette.
|
||||
*/
|
||||
void set_current_palette();
|
||||
/**
|
||||
@brief Retrieves the current PCG address.
|
||||
|
||||
@param width Number of currently setted up CRTC characters
|
||||
@param y_char_size Number of scanlines per character.
|
||||
@return Destination PCG address.
|
||||
*/
|
||||
uint16_t get_pcg_addr(uint16_t width, uint8_t y_char_size);
|
||||
/**
|
||||
@brief X1 Turbo: Retrieves the current CHR ROM address in Hi-Speed Mode.
|
||||
|
||||
@return Destination CHR address.
|
||||
*/
|
||||
uint16_t check_chr_addr();
|
||||
/**
|
||||
@brief X1 Turbo: Retrieves the current PCG ROM address in Hi-Speed Mode.
|
||||
|
||||
@return Destination CHR address.
|
||||
*/
|
||||
uint16_t check_pcg_addr();
|
||||
/**
|
||||
@brief MCU side: retrieve keycode to game key conversion.
|
||||
|
||||
@param port Address to convert.
|
||||
@return The converted game key buffer
|
||||
*/
|
||||
uint8_t get_game_key(uint8_t port);
|
||||
/**
|
||||
@brief MCU side: retrieve keyboard special key register.
|
||||
|
||||
@return
|
||||
x--- ---- TEN: Numpad, Function key, special input key
|
||||
-x-- ---- KIN: Valid key
|
||||
--x- ---- REP: Key repeat
|
||||
---x ---- GRAPH key ON
|
||||
---- x--- CAPS lock ON
|
||||
---- -x-- KANA lock ON
|
||||
---- --x- SHIFT ON
|
||||
---- ---x CTRL ON
|
||||
*/
|
||||
uint8_t check_keyboard_shift();
|
||||
/**
|
||||
@brief convert MAME input to raw scancode for keyboard.
|
||||
|
||||
@return the converted scancode
|
||||
@todo Unoptimized.
|
||||
*/
|
||||
uint16_t check_keyboard_press();
|
||||
|
||||
uint8_t m_fdc_ctrl;
|
||||
|
||||
};
|
||||
|
||||
/*----------- defined in machine/x1.c -----------*/
|
||||
|
@ -1,5 +1,13 @@
|
||||
// license:LGPL-2.1+
|
||||
// copyright-holders:Angelo Salese, Barry Rodewald
|
||||
/****************************************************
|
||||
*
|
||||
* Sharp X1 Keyboard device
|
||||
*
|
||||
* TODO:
|
||||
* - de-stateize X1 public variables
|
||||
*
|
||||
***************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/x1.h"
|
||||
|
354
src/mame/video/x1.cpp
Normal file
354
src/mame/video/x1.cpp
Normal file
@ -0,0 +1,354 @@
|
||||
// license:LGPL-2.1+
|
||||
// copyright-holders:Angelo Salese, Barry Rodewald
|
||||
/****************************************************************************
|
||||
*
|
||||
* Sharp X1 Video functions
|
||||
*
|
||||
* TODO:
|
||||
* - make this to be scanline renderer, fix palette partial updates;
|
||||
* - take mc6845 device functions into account;
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/x1.h"
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Video Functions
|
||||
*
|
||||
*************************************/
|
||||
|
||||
VIDEO_START_MEMBER(x1_state,x1)
|
||||
{
|
||||
m_avram = make_unique_clear<uint8_t[]>(0x800);
|
||||
m_tvram = make_unique_clear<uint8_t[]>(0x800);
|
||||
m_kvram = make_unique_clear<uint8_t[]>(0x800);
|
||||
m_gfx_bitmap_ram = make_unique_clear<uint8_t[]>(0xc000*2);
|
||||
m_pal_4096 = make_unique_clear<uint8_t[]>(0x1000*3);
|
||||
}
|
||||
|
||||
void x1_state::x1_draw_pixel(bitmap_rgb32 &bitmap,int y,int x,uint16_t pen,uint8_t width,uint8_t height)
|
||||
{
|
||||
if(!m_screen->visible_area().contains(x, y))
|
||||
return;
|
||||
|
||||
if(width && height)
|
||||
{
|
||||
bitmap.pix32(y+0+m_ystart, x+0+m_xstart) = m_palette->pen(pen);
|
||||
bitmap.pix32(y+0+m_ystart, x+1+m_xstart) = m_palette->pen(pen);
|
||||
bitmap.pix32(y+1+m_ystart, x+0+m_xstart) = m_palette->pen(pen);
|
||||
bitmap.pix32(y+1+m_ystart, x+1+m_xstart) = m_palette->pen(pen);
|
||||
}
|
||||
else if(width)
|
||||
{
|
||||
bitmap.pix32(y+m_ystart, x+0+m_xstart) = m_palette->pen(pen);
|
||||
bitmap.pix32(y+m_ystart, x+1+m_xstart) = m_palette->pen(pen);
|
||||
}
|
||||
else if(height)
|
||||
{
|
||||
bitmap.pix32(y+0+m_ystart, x+m_xstart) = m_palette->pen(pen);
|
||||
bitmap.pix32(y+1+m_ystart, x+m_xstart) = m_palette->pen(pen);
|
||||
}
|
||||
else
|
||||
bitmap.pix32(y+m_ystart, x+m_xstart) = m_palette->pen(pen);
|
||||
}
|
||||
|
||||
#define mc6845_h_char_total (m_crtc_vreg[0])
|
||||
#define mc6845_h_display (m_crtc_vreg[1])
|
||||
#define mc6845_h_sync_pos (m_crtc_vreg[2])
|
||||
#define mc6845_sync_width (m_crtc_vreg[3])
|
||||
#define mc6845_v_char_total (m_crtc_vreg[4])
|
||||
#define mc6845_v_total_adj (m_crtc_vreg[5])
|
||||
#define mc6845_v_display (m_crtc_vreg[6])
|
||||
#define mc6845_v_sync_pos (m_crtc_vreg[7])
|
||||
#define mc6845_mode_ctrl (m_crtc_vreg[8])
|
||||
#define mc6845_tile_height (m_crtc_vreg[9]+1)
|
||||
#define mc6845_cursor_y_start (m_crtc_vreg[0x0a])
|
||||
#define mc6845_cursor_y_end (m_crtc_vreg[0x0b])
|
||||
#define mc6845_start_addr (((m_crtc_vreg[0x0c]<<8) & 0x3f00) | (m_crtc_vreg[0x0d] & 0xff))
|
||||
#define mc6845_cursor_addr (((m_crtc_vreg[0x0e]<<8) & 0x3f00) | (m_crtc_vreg[0x0f] & 0xff))
|
||||
#define mc6845_light_pen_addr (((m_crtc_vreg[0x10]<<8) & 0x3f00) | (m_crtc_vreg[0x11] & 0xff))
|
||||
#define mc6845_update_addr (((m_crtc_vreg[0x12]<<8) & 0x3f00) | (m_crtc_vreg[0x13] & 0xff))
|
||||
|
||||
|
||||
/* adjust tile index when we are under double height condition */
|
||||
uint8_t x1_state::check_prev_height(int x,int y,int x_size)
|
||||
{
|
||||
uint8_t prev_tile = m_tvram[(x+((y-1)*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
uint8_t cur_tile = m_tvram[(x+(y*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
uint8_t prev_attr = m_avram[(x+((y-1)*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
uint8_t cur_attr = m_avram[(x+(y*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
|
||||
if(prev_tile == cur_tile && prev_attr == cur_attr)
|
||||
return 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Exoa II - Warroid: if double height isn't enabled on the first tile of the line then double height is disabled on everything else. */
|
||||
uint8_t x1_state::check_line_valid_height(int y,int x_size,int height)
|
||||
{
|
||||
uint8_t line_attr = m_avram[(0+(y*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
|
||||
if((line_attr & 0x40) == 0)
|
||||
return 0;
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
void x1_state::draw_fgtilemap(bitmap_rgb32 &bitmap,const rectangle &cliprect)
|
||||
{
|
||||
/*
|
||||
attribute table:
|
||||
x--- ---- double width
|
||||
-x-- ---- double height
|
||||
--x- ---- PCG select
|
||||
---x ---- color blinking
|
||||
---- x--- reverse color
|
||||
---- -xxx color pen
|
||||
|
||||
x--- ---- select Kanji ROM
|
||||
-x-- ---- Kanji side (0=left, 1=right)
|
||||
--x- ---- Underline
|
||||
---x ---- Kanji ROM select (0=level 1, 1=level 2) (TODO: implement this)
|
||||
---- xxxx Kanji upper 4 bits
|
||||
*/
|
||||
|
||||
int y,x,res_x,res_y;
|
||||
uint32_t tile_offset;
|
||||
uint8_t x_size,y_size;
|
||||
|
||||
x_size = mc6845_h_display;
|
||||
y_size = mc6845_v_display;
|
||||
|
||||
if(x_size == 0 || y_size == 0)
|
||||
return; //don't bother if screen is off
|
||||
|
||||
if(x_size != 80 && x_size != 40 && y_size != 25)
|
||||
popmessage("%d %d",x_size,y_size);
|
||||
|
||||
for (y=0;y<y_size;y++)
|
||||
{
|
||||
for (x=0;x<x_size;x++)
|
||||
{
|
||||
int tile = m_tvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff];
|
||||
int color = m_avram[((x+y*x_size)+mc6845_start_addr) & 0x7ff] & 0x1f;
|
||||
int width = BIT(m_avram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 7);
|
||||
int height = BIT(m_avram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 6);
|
||||
int pcg_bank = BIT(m_avram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 5);
|
||||
uint8_t *gfx_data = pcg_bank ? m_pcg_ram.get() : m_cg_rom; //machine.root_device().memregion(pcg_bank ? "pcg" : "cgrom")->base();
|
||||
int knj_enable = 0;
|
||||
int knj_side = 0;
|
||||
int knj_bank = 0;
|
||||
int knj_uline = 0;
|
||||
if(m_is_turbo)
|
||||
{
|
||||
knj_enable = BIT(m_kvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 7);
|
||||
knj_side = BIT(m_kvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 6);
|
||||
knj_uline = BIT(m_kvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 5);
|
||||
//knj_lv2 = BIT(m_kvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff], 4);
|
||||
knj_bank = m_kvram[((x+y*x_size)+mc6845_start_addr) & 0x7ff] & 0x0f;
|
||||
if(knj_enable)
|
||||
{
|
||||
gfx_data = m_kanji_rom;
|
||||
tile = ((tile + (knj_bank << 8)) << 1) + (knj_side & 1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int pen[3],pen_mask,pcg_pen,xi,yi,dy;
|
||||
|
||||
pen_mask = color & 7;
|
||||
|
||||
dy = 0;
|
||||
|
||||
height = check_line_valid_height(y,x_size,height);
|
||||
|
||||
if(height && y)
|
||||
dy = check_prev_height(x,y,x_size);
|
||||
|
||||
/* guess: assume that Kanji VRAM doesn't double the vertical size */
|
||||
if(knj_enable) { height = 0; }
|
||||
|
||||
for(yi=0;yi<mc6845_tile_height;yi++)
|
||||
{
|
||||
for(xi=0;xi<8;xi++)
|
||||
{
|
||||
if(knj_enable) //kanji select
|
||||
{
|
||||
tile_offset = tile * 16;
|
||||
tile_offset += (yi+dy*(m_scrn_reg.v400_mode+1)) >> (height+m_scrn_reg.v400_mode);
|
||||
pen[0] = gfx_data[tile_offset+0x0000]>>(7-xi) & (pen_mask & 1)>>0;
|
||||
pen[1] = gfx_data[tile_offset+0x0000]>>(7-xi) & (pen_mask & 2)>>1;
|
||||
pen[2] = gfx_data[tile_offset+0x0000]>>(7-xi) & (pen_mask & 4)>>2;
|
||||
|
||||
if(yi == mc6845_tile_height-1 && knj_uline) //underlined attribute
|
||||
{
|
||||
pen[0] = (pen_mask & 1)>>0;
|
||||
pen[1] = (pen_mask & 2)>>1;
|
||||
pen[2] = (pen_mask & 4)>>2;
|
||||
}
|
||||
|
||||
if((yi >= 16 && m_scrn_reg.v400_mode == 0) || (yi >= 32 && m_scrn_reg.v400_mode == 1))
|
||||
pen[0] = pen[1] = pen[2] = 0;
|
||||
}
|
||||
else if(pcg_bank) // PCG
|
||||
{
|
||||
tile_offset = tile * 8;
|
||||
tile_offset += (yi+dy*(m_scrn_reg.v400_mode+1)) >> (height+m_scrn_reg.v400_mode);
|
||||
|
||||
pen[0] = gfx_data[tile_offset+0x0000]>>(7-xi) & (pen_mask & 1)>>0;
|
||||
pen[1] = gfx_data[tile_offset+0x0800]>>(7-xi) & (pen_mask & 2)>>1;
|
||||
pen[2] = gfx_data[tile_offset+0x1000]>>(7-xi) & (pen_mask & 4)>>2;
|
||||
|
||||
if((yi >= 8 && m_scrn_reg.v400_mode == 0) || (yi >= 16 && m_scrn_reg.v400_mode == 1))
|
||||
pen[0] = pen[1] = pen[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tile_offset = tile * (8*(m_scrn_reg.ank_sel+1));
|
||||
tile_offset += (yi+dy*(m_scrn_reg.v400_mode+1)) >> (height+m_scrn_reg.v400_mode);
|
||||
|
||||
pen[0] = gfx_data[tile_offset+m_scrn_reg.ank_sel*0x0800]>>(7-xi) & (pen_mask & 1)>>0;
|
||||
pen[1] = gfx_data[tile_offset+m_scrn_reg.ank_sel*0x0800]>>(7-xi) & (pen_mask & 2)>>1;
|
||||
pen[2] = gfx_data[tile_offset+m_scrn_reg.ank_sel*0x0800]>>(7-xi) & (pen_mask & 4)>>2;
|
||||
|
||||
if(m_scrn_reg.ank_sel)
|
||||
{
|
||||
if((yi >= 16 && m_scrn_reg.v400_mode == 0) || (yi >= 32 && m_scrn_reg.v400_mode == 1))
|
||||
pen[0] = pen[1] = pen[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((yi >= 8 && m_scrn_reg.v400_mode == 0) || (yi >= 16 && m_scrn_reg.v400_mode == 1))
|
||||
pen[0] = pen[1] = pen[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pcg_pen = pen[2]<<2|pen[1]<<1|pen[0]<<0;
|
||||
|
||||
if(color & 0x10 && m_screen->frame_number() & 0x10) //reverse flickering
|
||||
pcg_pen^=7;
|
||||
|
||||
if(pcg_pen == 0 && (!(color & 8)))
|
||||
continue;
|
||||
|
||||
if(color & 8) //revert the used color pen
|
||||
pcg_pen^=7;
|
||||
|
||||
if((m_scrn_reg.blackclip & 8) && (color == (m_scrn_reg.blackclip & 7)))
|
||||
pcg_pen = 0; // clip the pen to black
|
||||
|
||||
res_x = x*8+xi*(width+1);
|
||||
res_y = y*(mc6845_tile_height)+yi;
|
||||
|
||||
if(res_y < cliprect.min_y || res_y > cliprect.max_y) // partial update, TODO: optimize
|
||||
continue;
|
||||
|
||||
x1_draw_pixel(bitmap,res_y,res_x,pcg_pen,width,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(width) //skip next char if we are under double width condition
|
||||
x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Priority Mixer Calculation (pri)
|
||||
*
|
||||
* If pri is 0xff then the bitmap entirely covers the tilemap, if it's 0x00 then
|
||||
* the tilemap priority is entirely above the bitmap. Any other value mixes the
|
||||
* bitmap and the tilemap priorities based on the pen value, bit 0 = entry 0 <-> bit 7 = entry 7
|
||||
* of the bitmap.
|
||||
*
|
||||
*/
|
||||
int x1_state::priority_mixer_pri(int color)
|
||||
{
|
||||
int pri_i,pri_mask_calc;
|
||||
|
||||
pri_i = 0;
|
||||
pri_mask_calc = 1;
|
||||
|
||||
while(pri_i < 7)
|
||||
{
|
||||
if((color & 7) == pri_i)
|
||||
break;
|
||||
|
||||
pri_i++;
|
||||
pri_mask_calc<<=1;
|
||||
}
|
||||
|
||||
return pri_mask_calc;
|
||||
}
|
||||
|
||||
void x1_state::draw_gfxbitmap(bitmap_rgb32 &bitmap,const rectangle &cliprect, int plane,int pri)
|
||||
{
|
||||
int xi,yi,x,y;
|
||||
int pen_r,pen_g,pen_b,color;
|
||||
int pri_mask_val;
|
||||
uint8_t x_size,y_size;
|
||||
int gfx_offset;
|
||||
|
||||
x_size = mc6845_h_display;
|
||||
y_size = mc6845_v_display;
|
||||
|
||||
if(x_size == 0 || y_size == 0)
|
||||
return; //don't bother if screen is off
|
||||
|
||||
if(x_size != 80 && x_size != 40 && y_size != 25)
|
||||
popmessage("%d %d",x_size,y_size);
|
||||
|
||||
//popmessage("%04x %02x",mc6845_start_addr,mc6845_tile_height);
|
||||
|
||||
for (y=0;y<y_size;y++)
|
||||
{
|
||||
for(x=0;x<x_size;x++)
|
||||
{
|
||||
for(yi=0;yi<(mc6845_tile_height);yi++)
|
||||
{
|
||||
for(xi=0;xi<8;xi++)
|
||||
{
|
||||
gfx_offset = ((x+(y*x_size)) + mc6845_start_addr) & 0x7ff;
|
||||
gfx_offset+= ((yi >> m_scrn_reg.v400_mode) * 0x800) & 0x3fff;
|
||||
pen_b = (m_gfx_bitmap_ram[gfx_offset+0x0000+plane*0xc000]>>(7-xi)) & 1;
|
||||
pen_r = (m_gfx_bitmap_ram[gfx_offset+0x4000+plane*0xc000]>>(7-xi)) & 1;
|
||||
pen_g = (m_gfx_bitmap_ram[gfx_offset+0x8000+plane*0xc000]>>(7-xi)) & 1;
|
||||
|
||||
color = (pen_g<<2 | pen_r<<1 | pen_b<<0) | 8;
|
||||
|
||||
pri_mask_val = priority_mixer_pri(color);
|
||||
if(pri_mask_val & pri) continue;
|
||||
|
||||
if((color == 8 && m_scrn_reg.blackclip & 0x10) || (color == 9 && m_scrn_reg.blackclip & 0x20)) // bitmap color clip to black conditions
|
||||
color = 0;
|
||||
|
||||
if(y*(mc6845_tile_height)+yi < cliprect.min_y || y*(mc6845_tile_height)+yi > cliprect.max_y) // partial update TODO: optimize
|
||||
continue;
|
||||
|
||||
x1_draw_pixel(bitmap,y*(mc6845_tile_height)+yi,x*8+xi,color,0,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t x1_state::screen_update_x1(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bitmap.fill(rgb_t(0xff,0x00,0x00,0x00), cliprect);
|
||||
|
||||
/* TODO: correct calculation thru mc6845 regs */
|
||||
m_xstart = ((mc6845_h_char_total - mc6845_h_sync_pos) * 8) / 2;
|
||||
m_ystart = ((mc6845_v_char_total - mc6845_v_sync_pos) * 8) / 2;
|
||||
|
||||
// popmessage("%d %d %d %d",mc6845_h_sync_pos,mc6845_v_sync_pos,mc6845_h_char_total,mc6845_v_char_total);
|
||||
|
||||
draw_gfxbitmap(bitmap,cliprect,m_scrn_reg.disp_bank,m_scrn_reg.pri);
|
||||
draw_fgtilemap(bitmap,cliprect);
|
||||
draw_gfxbitmap(bitmap,cliprect,m_scrn_reg.disp_bank,m_scrn_reg.pri^0xff);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user