#include "shared.h"
#include "md_ntsc.h"
#include "sms_ntsc.h"
extern int cinterface_render_bga;
extern int cinterface_render_bgb;
extern int cinterface_render_bgw;
extern int cinterface_render_obj;
extern uint8 cinterface_custom_backdrop;
extern uint32 cinterface_custom_backdrop_color;
extern md_ntsc_t *md_ntsc;
extern sms_ntsc_t *sms_ntsc;
#if defined(USE_8BPP_RENDERING)
#define PIXEL_OUT_T uint8
#elif defined(USE_32BPP_RENDERING)
#define PIXEL_OUT_T uint32
#else
#define PIXEL_OUT_T uint16
#endif
#define LUT_MAX (6)
#define LUT_SIZE (0x10000)
#ifdef ALIGN_LONG
#undef READ_LONG
#undef WRITE_LONG
INLINE uint32 READ_LONG(void *address)
{
if ((uint32)address & 3)
{
#ifdef LSB_FIRST
return ( *((uint8 *)address) +
(*((uint8 *)address+1) << 8) +
(*((uint8 *)address+2) << 16) +
(*((uint8 *)address+3) << 24) );
#else
return ( *((uint8 *)address+3) +
(*((uint8 *)address+2) << 8) +
(*((uint8 *)address+1) << 16) +
(*((uint8 *)address) << 24) );
#endif
}
else return *(uint32 *)address;
}
INLINE void WRITE_LONG(void *address, uint32 data)
{
if ((uint32)address & 3)
{
#ifdef LSB_FIRST
*((uint8 *)address) = data;
*((uint8 *)address+1) = (data >> 8);
*((uint8 *)address+2) = (data >> 16);
*((uint8 *)address+3) = (data >> 24);
#else
*((uint8 *)address+3) = data;
*((uint8 *)address+2) = (data >> 8);
*((uint8 *)address+1) = (data >> 16);
*((uint8 *)address) = (data >> 24);
#endif
return;
}
else *(uint32 *)address = data;
}
#endif
#define GET_LSB_TILE(ATTR, LINE) \
atex = atex_table[(ATTR >> 13) & 7]; \
src = (uint32 *)&bg_pattern_cache[(ATTR & 0x00001FFF) << 6 | (LINE)];
#define GET_MSB_TILE(ATTR, LINE) \
atex = atex_table[(ATTR >> 29) & 7]; \
src = (uint32 *)&bg_pattern_cache[(ATTR & 0x1FFF0000) >> 10 | (LINE)];
#define GET_LSB_TILE_IM2(ATTR, LINE) \
atex = atex_table[(ATTR >> 13) & 7]; \
src = (uint32 *)&bg_pattern_cache[((ATTR & 0x000003FF) << 7 | (ATTR & 0x00001800) << 6 | (LINE)) ^ ((ATTR & 0x00001000) >> 6)];
#define GET_MSB_TILE_IM2(ATTR, LINE) \
atex = atex_table[(ATTR >> 29) & 7]; \
src = (uint32 *)&bg_pattern_cache[((ATTR & 0x03FF0000) >> 9 | (ATTR & 0x18000000) >> 10 | (LINE)) ^ ((ATTR & 0x10000000) >> 22)];
#ifdef ALIGN_LONG
#ifdef LSB_FIRST
#define DRAW_COLUMN(ATTR, LINE) \
GET_LSB_TILE(ATTR, LINE) \
WRITE_LONG(dst, src[0] | atex); \
dst++; \
WRITE_LONG(dst, src[1] | atex); \
dst++; \
GET_MSB_TILE(ATTR, LINE) \
WRITE_LONG(dst, src[0] | atex); \
dst++; \
WRITE_LONG(dst, src[1] | atex); \
dst++;
#define DRAW_COLUMN_IM2(ATTR, LINE) \
GET_LSB_TILE_IM2(ATTR, LINE) \
WRITE_LONG(dst, src[0] | atex); \
dst++; \
WRITE_LONG(dst, src[1] | atex); \
dst++; \
GET_MSB_TILE_IM2(ATTR, LINE) \
WRITE_LONG(dst, src[0] | atex); \
dst++; \
WRITE_LONG(dst, src[1] | atex); \
dst++;
#else
#define DRAW_COLUMN(ATTR, LINE) \
GET_MSB_TILE(ATTR, LINE) \
WRITE_LONG(dst, src[0] | atex); \
dst++; \
WRITE_LONG(dst, src[1] | atex); \
dst++; \
GET_LSB_TILE(ATTR, LINE) \
WRITE_LONG(dst, src[0] | atex); \
dst++; \
WRITE_LONG(dst, src[1] | atex); \
dst++;
#define DRAW_COLUMN_IM2(ATTR, LINE) \
GET_MSB_TILE_IM2(ATTR, LINE) \
WRITE_LONG(dst, src[0] | atex); \
dst++; \
WRITE_LONG(dst, src[1] | atex); \
dst++; \
GET_LSB_TILE_IM2(ATTR, LINE) \
WRITE_LONG(dst, src[0] | atex); \
dst++; \
WRITE_LONG(dst, src[1] | atex); \
dst++;
#endif
#else
#ifdef LSB_FIRST
#define DRAW_COLUMN(ATTR, LINE) \
GET_LSB_TILE(ATTR, LINE) \
*dst++ = (src[0] | atex); \
*dst++ = (src[1] | atex); \
GET_MSB_TILE(ATTR, LINE) \
*dst++ = (src[0] | atex); \
*dst++ = (src[1] | atex);
#define DRAW_COLUMN_IM2(ATTR, LINE) \
GET_LSB_TILE_IM2(ATTR, LINE) \
*dst++ = (src[0] | atex); \
*dst++ = (src[1] | atex); \
GET_MSB_TILE_IM2(ATTR, LINE) \
*dst++ = (src[0] | atex); \
*dst++ = (src[1] | atex);
#else
#define DRAW_COLUMN(ATTR, LINE) \
GET_MSB_TILE(ATTR, LINE) \
*dst++ = (src[0] | atex); \
*dst++ = (src[1] | atex); \
GET_LSB_TILE(ATTR, LINE) \
*dst++ = (src[0] | atex); \
*dst++ = (src[1] | atex);
#define DRAW_COLUMN_IM2(ATTR, LINE) \
GET_MSB_TILE_IM2(ATTR, LINE) \
*dst++ = (src[0] | atex); \
*dst++ = (src[1] | atex); \
GET_LSB_TILE_IM2(ATTR, LINE) \
*dst++ = (src[0] | atex); \
*dst++ = (src[1] | atex);
#endif
#endif
#ifdef ALT_RENDERER
#ifdef LSB_FIRST
#define DRAW_BG_TILE(SRC_A, SRC_B) \
*lb++ = table[((SRC_B << 8) & 0xff00) | (SRC_A & 0xff)]; \
*lb++ = table[(SRC_B & 0xff00) | ((SRC_A >> 8) & 0xff)]; \
*lb++ = table[((SRC_B >> 8) & 0xff00) | ((SRC_A >> 16) & 0xff)]; \
*lb++ = table[((SRC_B >> 16) & 0xff00) | ((SRC_A >> 24) & 0xff)];
#else
#define DRAW_BG_TILE(SRC_A, SRC_B) \
*lb++ = table[((SRC_B >> 16) & 0xff00) | ((SRC_A >> 24) & 0xff)]; \
*lb++ = table[((SRC_B >> 8) & 0xff00) | ((SRC_A >> 16) & 0xff)]; \
*lb++ = table[(SRC_B & 0xff00) | ((SRC_A >> 8) & 0xff)]; \
*lb++ = table[((SRC_B << 8) & 0xff00) | (SRC_A & 0xff)];
#endif
#ifdef ALIGN_LONG
#ifdef LSB_FIRST
#define DRAW_BG_COLUMN(ATTR, LINE, SRC_A, SRC_B) \
GET_LSB_TILE(ATTR, LINE) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
GET_MSB_TILE(ATTR, LINE) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B)
#define DRAW_BG_COLUMN_IM2(ATTR, LINE, SRC_A, SRC_B) \
GET_LSB_TILE_IM2(ATTR, LINE) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
GET_MSB_TILE_IM2(ATTR, LINE) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B)
#else
#define DRAW_BG_COLUMN(ATTR, LINE, SRC_A, SRC_B) \
GET_MSB_TILE(ATTR, LINE) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
GET_LSB_TILE(ATTR, LINE) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B)
#define DRAW_BG_COLUMN_IM2(ATTR, LINE, SRC_A, SRC_B) \
GET_MSB_TILE_IM2(ATTR, LINE) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
GET_LSB_TILE_IM2(ATTR, LINE) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = READ_LONG((uint32 *)lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B)
#endif
#else
#ifdef LSB_FIRST
#define DRAW_BG_COLUMN(ATTR, LINE, SRC_A, SRC_B) \
GET_LSB_TILE(ATTR, LINE) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
GET_MSB_TILE(ATTR, LINE) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B)
#define DRAW_BG_COLUMN_IM2(ATTR, LINE, SRC_A, SRC_B) \
GET_LSB_TILE_IM2(ATTR, LINE) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
GET_MSB_TILE_IM2(ATTR, LINE) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B)
#else
#define DRAW_BG_COLUMN(ATTR, LINE, SRC_A, SRC_B) \
GET_MSB_TILE(ATTR, LINE) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
GET_LSB_TILE(ATTR, LINE) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B)
#define DRAW_BG_COLUMN_IM2(ATTR, LINE, SRC_A, SRC_B) \
GET_MSB_TILE_IM2(ATTR, LINE) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
GET_LSB_TILE_IM2(ATTR, LINE) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[0] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B) \
SRC_A = *(uint32 *)(lb); \
SRC_B = (src[1] | atex); \
DRAW_BG_TILE(SRC_A, SRC_B)
#endif
#endif
#endif
#define DRAW_SPRITE_TILE(WIDTH,ATTR,TABLE) \
if (!cinterface_render_obj) return; \
for (i=0;i<WIDTH;i++) \
{ \
temp = *src++; \
if (temp & 0x0f) \
{ \
temp |= (lb[i] << 8); \
lb[i] = TABLE[temp | ATTR]; \
status |= ((temp & 0x8000) >> 10); \
} \
}
#define DRAW_SPRITE_TILE_ACCURATE(WIDTH,ATTR,TABLE) \
if (!cinterface_render_obj) return; \
for (i=0;i<WIDTH;i++) \
{ \
temp = *src++; \
if (temp & 0x0f) \
{ \
temp |= (lb[i] << 8); \
lb[i] = TABLE[temp | ATTR]; \
if ((temp & 0x8000) && !(status & 0x20)) \
{ \
spr_col = (v_counter << 8) | ((xpos + i + 13) >> 1); \
status |= 0x20; \
} \
} \
}
#define DRAW_SPRITE_TILE_ACCURATE_2X(WIDTH,ATTR,TABLE) \
for (i=0;i<WIDTH;i+=2) \
{ \
temp = *src++; \
if (temp & 0x0f) \
{ \
temp |= (lb[i] << 8); \
lb[i] = TABLE[temp | ATTR]; \
if ((temp & 0x8000) && !(status & 0x20)) \
{ \
spr_col = (v_counter << 8) | ((xpos + i + 13) >> 1); \
status |= 0x20; \
} \
temp &= 0x00FF; \
temp |= (lb[i+1] << 8); \
lb[i+1] = TABLE[temp | ATTR]; \
if ((temp & 0x8000) && !(status & 0x20)) \
{ \
spr_col = (v_counter << 8) | ((xpos + i + 1 + 13) >> 1); \
status |= 0x20; \
} \
} \
}
#if defined(USE_8BPP_RENDERING)
#define MAKE_PIXEL(r,g,b) (((r) >> 1) << 5 | ((g) >> 1) << 2 | (b) >> 2)
#elif defined(USE_15BPP_RENDERING)
#define MAKE_PIXEL(r,g,b) ((r) << 11 | ((r) >> 3) << 10 | (g) << 6 | ((g) >> 3) << 5 | (b) << 1 | (b) >> 3)
#elif defined(USE_16BPP_RENDERING)
#define MAKE_PIXEL(r,g,b) ((r) << 12 | ((r) >> 3) << 11 | (g) << 7 | ((g) >> 2) << 5 | (b) << 1 | (b) >> 3)
#elif defined(USE_32BPP_RENDERING)
#define MAKE_PIXEL(r,g,b) (0xff000000 | (r) << 20 | (r) << 16 | (g) << 12 | (g) << 8 | (b) << 4 | (b))
#endif
static struct clip_t
{
uint8 left;
uint8 right;
uint8 enable;
} clip[2];
static const uint32 atex_table[] =
{
0x00000000,
0x10101010,
0x20202020,
0x30303030,
0x40404040,
0x50505050,
0x60606060,
0x70707070
};
static const uint8 tms_crom[16] =
{
0x00, 0x00, 0x08, 0x0C,
0x10, 0x30, 0x01, 0x3C,
0x02, 0x03, 0x05, 0x0F,
0x04, 0x33, 0x15, 0x3F
};
#if defined(USE_8BPP_RENDERING)
static const uint8 tms_palette[16] =
{
0x00, 0x00, 0x39, 0x79,
0x4B, 0x6F, 0xC9, 0x5B,
0xE9, 0xED, 0xD5, 0xD9,
0x35, 0xCE, 0xDA, 0xFF
};
#elif defined(USE_15BPP_RENDERING)
static const uint16 tms_palette[16] =
{
0x0000, 0x0000, 0x1308, 0x2F6F,
0x295D, 0x3DDF, 0x6949, 0x23BE,
0x7D4A, 0x7DEF, 0x6B0A, 0x7330,
0x12A7, 0x6177, 0x6739, 0x7FFF
};
#elif defined(USE_16BPP_RENDERING)
static const uint16 tms_palette[16] =
{
0x0000, 0x0000, 0x2648, 0x5ECF,
0x52BD, 0x7BBE, 0xD289, 0x475E,
0xF2AA, 0xFBCF, 0xD60A, 0xE670,
0x2567, 0xC2F7, 0xCE59, 0xFFFF
};
#elif defined(USE_32BPP_RENDERING)
static const uint32 tms_palette[16] =
{
0x000000, 0x000000, 0x21C842, 0x5EDC78,
0x5455ED, 0x7D76FC, 0xD4524D, 0x42EBF5,
0xFC5554, 0xFF7978, 0xD4C154, 0xE6CE80,
0x21B03B, 0xC95BB4, 0xCCCCCC, 0xFFFFFF
};
#endif
uint8 *bg_pattern_cache;
static uint8 name_lut[0x400];
uint32 *vdp_bp_lut;
#define bp_lut vdp_bp_lut
uint8 **vdp_lut;
#define lut vdp_lut
PIXEL_OUT_T pixel[0x100];
static PIXEL_OUT_T pixel_lut[3][0x200];
static PIXEL_OUT_T pixel_lut_m4[0x40];
static uint8 linebuf[2][0x200];
static uint8 spr_ovr;
typedef struct
{
uint16 ypos;
uint16 xpos;
uint16 attr;
uint16 size;
} object_info_t;
static object_info_t obj_info[2][20];
static uint8 object_count[2];
uint16 spr_col;
void (*render_bg)(int line);
void (*render_obj)(int line);
void (*parse_satb)(int line);
void (*update_bg_pattern_cache)(int index);
static void make_name_lut(void)
{
int vcol, vrow;
int width, height;
int flipx, flipy;
int i;
for (i = 0; i < 0x400; i += 1)
{
vcol = i & 3;
vrow = (i >> 2) & 3;
height = (i >> 4) & 3;
width = (i >> 6) & 3;
flipx = (i >> 8) & 1;
flipy = (i >> 9) & 1;
if ((vrow > height) || vcol > width)
{
name_lut[i] = -1;
}
else
{
if(flipx) vcol = (width - vcol);
if(flipy) vrow = (height - vrow);
name_lut[i] = vrow + (vcol * (height + 1));
}
}
}
static void make_bp_lut(void)
{
int x,i,j;
uint32 out;
for(i = 0; i < 0x100; i++)
for(j = 0; j < 0x100; j++)
{
out = 0;
for(x = 0; x < 8; x++)
{
out |= (j & (0x80 >> x)) ? (uint32)(8 << (x << 2)) : 0;
out |= (i & (0x80 >> x)) ? (uint32)(4 << (x << 2)) : 0;
}
#ifdef LSB_FIRST
bp_lut[(j << 8) | (i)] = out;
#else
bp_lut[(i << 8) | (j)] = out;
#endif
}
}
static uint32 make_lut_bg(uint32 bx, uint32 ax)
{
int bf = (bx & 0x7F);
int bp = (bx & 0x40);
int b = (bx & 0x0F);
int af = (ax & 0x7F);
int ap = (ax & 0x40);
int a = (ax & 0x0F);
int c = (ap ? (a ? af : bf) : (bp ? (b ? bf : af) : (a ? af : bf)));
if((c & 0x0F) == 0x00) c &= 0x80;
return (c);
}
static uint32 make_lut_bg_ste(uint32 bx, uint32 ax)
{
int bf = (bx & 0x7F);
int bp = (bx & 0x40);
int b = (bx & 0x0F);
int af = (ax & 0x7F);
int ap = (ax & 0x40);
int a = (ax & 0x0F);
int c = (ap ? (a ? af : bf) : (bp ? (b ? bf : af) : (a ? af : bf)));
c |= ((ap | bp) << 1);
if((c & 0x0F) == 0x00) c &= 0x80;
return (c);
}
static uint32 make_lut_obj(uint32 bx, uint32 sx)
{
int c;
int bf = (bx & 0x7F);
int bs = (bx & 0x80);
int sf = (sx & 0x7F);
if((sx & 0x0F) == 0) return bx;
c = (bs ? bf : sf);
if((c & 0x0F) == 0x00) c &= 0xC0;
return (c | 0x80);
}
static uint32 make_lut_bgobj(uint32 bx, uint32 sx)
{
int c;
int bf = (bx & 0x3F);
int bs = (bx & 0x80);
int bp = (bx & 0x40);
int b = (bx & 0x0F);
int sf = (sx & 0x3F);
int sp = (sx & 0x40);
int s = (sx & 0x0F);
if(s == 0) return bx;
if(bs) return bx;
c = (sp ? sf : (bp ? (b ? bf : sf) : sf));
if((c & 0x0F) == 0x00) c &= 0x80;
return (c | 0x80);
}
static uint32 make_lut_bgobj_ste(uint32 bx, uint32 sx)
{
int c;
int bf = (bx & 0x3F);
int bp = (bx & 0x40);
int b = (bx & 0x0F);
int bi = (bx & 0x80) >> 1;
int sf = (sx & 0x3F);
int sp = (sx & 0x40);
int s = (sx & 0x0F);
int si = sp | bi;
if(sp)
{
if(s)
{
if((sf & 0x3E) == 0x3E)
{
if(sf & 1)
{
c = (bf | 0x00);
}
else
{
c = (bx & 0x80) ? (bf | 0x80) : (bf | 0x40);
}
}
else
{
if(sf == 0x0E || sf == 0x1E || sf == 0x2E)
{
c = (sf | 0x40);
}
else
{
c = (sf | si);
}
}
}
else
{
c = (bf | bi);
}
}
else
{
if(bp)
{
if(b)
{
c = (bf | bi);
}
else
{
if(s)
{
if((sf & 0x3E) == 0x3E)
{
if(sf & 1)
{
c = (bf | 0x00);
}
else
{
c = (bx & 0x80) ? (bf | 0x80) : (bf | 0x40);
}
}
else
{
if(sf == 0x0E || sf == 0x1E || sf == 0x2E)
{
c = (sf | 0x40);
}
else
{
c = (sf | si);
}
}
}
else
{
c = (bf | bi);
}
}
}
else
{
if(s)
{
if((sf & 0x3E) == 0x3E)
{
if(sf & 1)
{
c = (bf | 0x00);
}
else
{
c = (bx & 0x80) ? (bf | 0x80) : (bf | 0x40);
}
}
else
{
if(sf == 0x0E || sf == 0x1E || sf == 0x2E)
{
c = (sf | 0x40);
}
else
{
c = (sf | si);
}
}
}
else
{
c = (bf | bi);
}
}
}
if((c & 0x0f) == 0x00) c &= 0xC0;
return (c);
}
static uint32 make_lut_bgobj_m4(uint32 bx, uint32 sx)
{
int c;
int bf = (bx & 0x3F);
int bs = (bx & 0x80);
int bp = (bx & 0x20);
int b = (bx & 0x0F);
int s = (sx & 0x0F);
int sf = (s | 0x10);
if(s == 0) return bx;
if(bs) return bx;
c = (bp ? (b ? bf : sf) : sf);
return (c | 0x80);
}
INLINE void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width)
{
do
{
*dst++ = table[(*srcb++ << 8) | (*srca++)];
}
while (--width);
}
static void palette_init(void)
{
int r, g, b, i;
for (i = 0; i < 0x200; i++)
{
r = (i >> 0) & 7;
g = (i >> 3) & 7;
b = (i >> 6) & 7;
pixel_lut[0][i] = MAKE_PIXEL(r,g,b);
pixel_lut[1][i] = MAKE_PIXEL(r<<1,g<<1,b<<1);
pixel_lut[2][i] = MAKE_PIXEL(r+7,g+7,b+7);
}
for (i = 0; i < 0x40; i++)
{
r = (i >> 0) & 3;
g = (i >> 2) & 3;
b = (i >> 4) & 3;
pixel_lut_m4[i] = MAKE_PIXEL((r << 2) | r, (g << 2) | g, (b << 2) | b);
}
}
void color_update_m4(int index, unsigned int data)
{
switch (system_hw)
{
case SYSTEM_GG:
{
int r = (data >> 0) & 0x0F;
int g = (data >> 4) & 0x0F;
int b = (data >> 8) & 0x0F;
data = MAKE_PIXEL(r,g,b);
break;
}
case SYSTEM_SG:
{
if (index & 0x0F)
{
data = tms_palette[index & 0x0F];
}
else
{
data = tms_palette[reg[7] & 0x0F];
}
break;
}
default:
{
if (!(reg[0] & 0x04))
{
if (system_hw & SYSTEM_MD)
{
data = 0x00;
}
else if (system_hw != SYSTEM_GGMS)
{
if (index & 0x0F)
{
data = tms_crom[index & 0x0F];
}
else
{
data = tms_crom[reg[7] & 0x0F];
}
}
}
data = pixel_lut_m4[data & 0x3F];
break;
}
}
if (reg[0] & 0x04)
{
pixel[0x00 | index] = data;
pixel[0x20 | index] = data;
pixel[0x80 | index] = data;
pixel[0xA0 | index] = data;
}
else
{
if ((index == 0x40) || (index == (0x10 | (reg[7] & 0x0F))))
{
pixel[0x40] = data;
pixel[0x10] = data;
pixel[0x30] = data;
pixel[0x90] = data;
pixel[0xB0] = data;
}
if (index & 0x0F)
{
pixel[0x00 | index] = data;
pixel[0x20 | index] = data;
pixel[0x80 | index] = data;
pixel[0xA0 | index] = data;
}
}
}
void color_update_m5(int index, unsigned int data)
{
if (!(reg[0] & 0x04))
{
data &= 0x49;
}
if (index == 0 && cinterface_custom_backdrop)
{
pixel[0x00] = pixel[0x40] = pixel[0x80] = cinterface_custom_backdrop_color;
}
else
{
if(reg[12] & 0x08)
{
pixel[0x00 | index] = pixel_lut[0][data];
pixel[0x40 | index] = pixel_lut[1][data];
pixel[0x80 | index] = pixel_lut[2][data];
}
else
{
data = pixel_lut[1][data];
pixel[0x00 | index] = data;
pixel[0x40 | index] = data;
pixel[0x80 | index] = data;
}
}
}
void render_bg_m0(int line)
{
uint8 color, name, pattern;
uint8 *lb = &linebuf[0][0x20];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
uint8 *ct = &vram[((reg[3] << 6) & 0x3FC0)];
uint8 *pg = &vram[((reg[4] << 11) & 0x3800) + (line & 7)];
int width = 32;
do
{
name = *nt++;
color = ct[name >> 3];
pattern = pg[name << 3];
*lb++ = 0x10 | ((color >> (((pattern >> 7) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 6) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 5) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 4) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 3) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 2) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 1) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 0) & 1) << 2)) & 0x0F);
}
while (--width);
}
void render_bg_m1(int line)
{
uint8 pattern;
uint8 color = reg[7];
uint8 *lb = &linebuf[0][0x20];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line >> 3) * 40)];
uint8 *pg = &vram[((reg[4] << 11) & 0x3800) + (line & 7)];
int width = 40;
memset (lb, 0x40, 8);
lb += 8;
do
{
pattern = pg[*nt++ << 3];
*lb++ = 0x10 | ((color >> (((pattern >> 7) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 6) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 5) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 4) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 3) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 2) & 1) << 2)) & 0x0F);
}
while (--width);
memset(lb, 0x40, 8);
}
void render_bg_m1x(int line)
{
uint8 pattern;
uint8 *pg;
uint8 color = reg[7];
uint8 *lb = &linebuf[0][0x20];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line >> 3) * 40)];
uint16 pg_mask = ~0x3800 ^ (reg[4] << 11);
int width = 40;
if (system_hw > SYSTEM_SMS)
{
pg_mask |= 0x1800;
}
pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + (line & 7)];
memset (lb, 0x40, 8);
lb += 8;
do
{
pattern = pg[*nt++ << 3];
*lb++ = 0x10 | ((color >> (((pattern >> 7) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 6) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 5) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 4) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 3) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 2) & 1) << 2)) & 0x0F);
}
while (--width);
memset(lb, 0x40, 8);
}
void render_bg_m2(int line)
{
uint8 color, pattern;
uint16 name;
uint8 *ct, *pg;
uint8 *lb = &linebuf[0][0x20];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
uint16 ct_mask = ~0x3FC0 ^ (reg[3] << 6);
uint16 pg_mask = ~0x3800 ^ (reg[4] << 11);
int width = 32;
if (system_hw > SYSTEM_SMS)
{
ct_mask |= 0x1FC0;
pg_mask |= 0x1800;
}
ct = &vram[((0x2000 + ((line & 0xC0) << 5)) & ct_mask) + (line & 7)];
pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + (line & 7)];
do
{
name = *nt++ << 3 ;
color = ct[name & ct_mask];
pattern = pg[name];
*lb++ = 0x10 | ((color >> (((pattern >> 7) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 6) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 5) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 4) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 3) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 2) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 1) & 1) << 2)) & 0x0F);
*lb++ = 0x10 | ((color >> (((pattern >> 0) & 1) << 2)) & 0x0F);
}
while (--width);
}
void render_bg_m3(int line)
{
uint8 color;
uint8 *lb = &linebuf[0][0x20];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
uint8 *pg = &vram[((reg[4] << 11) & 0x3800) + ((line >> 2) & 7)];
int width = 32;
do
{
color = pg[*nt++ << 3];
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 0) & 0x0F);
*lb++ = 0x10 | ((color >> 0) & 0x0F);
*lb++ = 0x10 | ((color >> 0) & 0x0F);
*lb++ = 0x10 | ((color >> 0) & 0x0F);
}
while (--width);
}
void render_bg_m3x(int line)
{
uint8 color;
uint8 *pg;
uint8 *lb = &linebuf[0][0x20];
uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
uint16 pg_mask = ~0x3800 ^ (reg[4] << 11);
int width = 32;
if (system_hw > SYSTEM_SMS)
{
pg_mask |= 0x1800;
}
pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + ((line >> 2) & 7)];
do
{
color = pg[*nt++ << 3];
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 0) & 0x0F);
*lb++ = 0x10 | ((color >> 0) & 0x0F);
*lb++ = 0x10 | ((color >> 0) & 0x0F);
*lb++ = 0x10 | ((color >> 0) & 0x0F);
}
while (--width);
}
void render_bg_inv(int line)
{
uint8 color = reg[7];
uint8 *lb = &linebuf[0][0x20];
int width = 40;
memset (lb, 0x40, 8);
lb += 8;
do
{
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 4) & 0x0F);
*lb++ = 0x10 | ((color >> 0) & 0x0F);
*lb++ = 0x10 | ((color >> 0) & 0x0F);
}
while (--width);
memset(lb, 0x40, 8);
}
void render_bg_m4(int line)
{
int column;
uint16 *nt;
uint32 attr, atex, *src;
int width = 32;
int index = ((reg[0] & 0x40) && (line < 0x10)) ? 0x100 : reg[0x08];
int shift = index & 7;
uint32 *dst = (uint32 *)&linebuf[0][0x20 + shift];
int v_line = line + vscroll;
uint16 nt_mask = ~0x3C00 ^ (reg[2] << 10);
if (system_hw > SYSTEM_SMS)
{
nt_mask |= 0x400;
}
if (bitmap.viewport.h > 192)
{
v_line = v_line % 256;
nt = (uint16 *)&vram[(0x3700 & nt_mask) + ((v_line >> 3) << 6)];
}
else
{
v_line = v_line % 224;
nt = (uint16 *)&vram[(0x3800 + ((v_line >> 3) << 6)) & nt_mask];
}
v_line = (v_line & 7) << 3;
index = (0x100 - index) >> 3;
if (shift)
{
memset(&linebuf[0][0x20], 0, shift);
index++;
}
for(column = 0; column < width; column++, index++)
{
if((column == 24) && (reg[0] & 0x80))
{
if (bitmap.viewport.h > 192)
{
nt = (uint16 *)&vram[(0x3700 & nt_mask) + ((line >> 3) << 6)];
}
else
{
nt = (uint16 *)&vram[(0x3800 + ((line >> 3) << 6)) & nt_mask];
}
v_line = (line & 7) << 3;
}
attr = nt[index % width];
#ifndef LSB_FIRST
attr = (((attr & 0xFF) << 8) | ((attr & 0xFF00) >> 8));
#endif
atex = atex_table[(attr >> 11) & 3];
src = (uint32 *)&bg_pattern_cache[((attr & 0x7FF) << 6) | (v_line)];
#ifdef ALIGN_DWORD
WRITE_LONG(dst, src[0] | atex);
dst++;
WRITE_LONG(dst, src[1] | atex);
dst++;
#else
*dst++ = (src[0] | atex);
*dst++ = (src[1] | atex);
#endif
}
}
#ifndef ALT_RENDERER
void render_bg_m5(int line)
{
int column;
uint32 atex, atbuf, *src, *dst;
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = *(uint32 *)&vsram[0];
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
int start = 0;
int end = bitmap.viewport.w >> 4;
#ifdef LSB_FIRST
uint32 shift = (xscroll >> 16) & 0x0F;
uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
uint32 v_line = (line + (yscroll >> 16)) & pf_row_mask;
#else
uint32 shift = (xscroll & 0x0F);
uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
uint32 v_line = (line + yscroll) & pf_row_mask;
#endif
uint32 *nt;
if (cinterface_render_bgb)
{
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
if(shift)
{
dst = (uint32 *)&linebuf[0][0x10 + shift];
atbuf = nt[(index - 1) & pf_col_mask];
DRAW_COLUMN(atbuf, v_line)
}
else
{
dst = (uint32 *)&linebuf[0][0x20];
}
for(column = 0; column < end; column++, index++)
{
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN(atbuf, v_line)
}
}
else
{
memset(&linebuf[0][0], 0, 512);
}
if (w == (line >= a))
{
a = 0;
w = 1;
}
else
{
a = clip[0].enable;
w = clip[1].enable;
}
if (a && cinterface_render_bga)
{
start = clip[0].left;
end = clip[0].right;
#ifdef LSB_FIRST
shift = (xscroll & 0x0F);
index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
v_line = (line + yscroll) & pf_row_mask;
#else
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
v_line = (line + (yscroll >> 16)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
if(shift)
{
dst = (uint32 *)&linebuf[1][0x10 + shift + (start << 4)];
if (start)
{
atbuf = nt[index & pf_col_mask];
}
else
{
atbuf = nt[(index - 1) & pf_col_mask];
}
DRAW_COLUMN(atbuf, v_line)
}
else
{
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
}
for(column = start; column < end; column++, index++)
{
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN(atbuf, v_line)
}
start = clip[1].left;
end = clip[1].right;
}
else if (!cinterface_render_bga)
{
memset(&linebuf[1][0], 0, 512);
}
if (w && cinterface_render_bgw)
{
nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
v_line = (line & 7) << 3;
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
for(column = start; column < end; column++)
{
atbuf = nt[column];
DRAW_COLUMN(atbuf, v_line)
}
}
merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[(reg[12] & 0x08) >> 2], bitmap.viewport.w);
}
void render_bg_m5_vs(int line)
{
int column;
uint32 atex, atbuf, *src, *dst;
uint32 v_line, *nt;
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = 0;
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
uint32 *vs = (uint32 *)&vsram[0];
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
int start = 0;
int end = bitmap.viewport.w >> 4;
#ifdef LSB_FIRST
uint32 shift = (xscroll >> 16) & 0x0F;
uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
#else
uint32 shift = (xscroll & 0x0F);
uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
#endif
if (reg[12] & 1)
{
yscroll = vs[19] & (vs[19] >> 16);
}
if (cinterface_render_bgb)
{
if(shift)
{
v_line = (line + yscroll) & pf_row_mask;
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
dst = (uint32 *)&linebuf[0][0x10 + shift];
atbuf = nt[(index - 1) & pf_col_mask];
DRAW_COLUMN(atbuf, v_line)
}
else
{
dst = (uint32 *)&linebuf[0][0x20];
}
for(column = 0; column < end; column++, index++)
{
#ifdef LSB_FIRST
v_line = (line + (vs[column] >> 16)) & pf_row_mask;
#else
v_line = (line + vs[column]) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN(atbuf, v_line)
}
}
else
{
memset(&linebuf[0][0], 0, 512);
}
if (w == (line >= a))
{
a = 0;
w = 1;
}
else
{
a = clip[0].enable;
w = clip[1].enable;
}
if (a && cinterface_render_bga)
{
start = clip[0].left;
end = clip[0].right;
#ifdef LSB_FIRST
shift = (xscroll & 0x0F);
index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
#else
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
#endif
if(shift)
{
v_line = (line + yscroll) & pf_row_mask;
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
dst = (uint32 *)&linebuf[1][0x10 + shift + (start << 4)];
if (start)
{
atbuf = nt[index & pf_col_mask];
}
else
{
atbuf = nt[(index - 1) & pf_col_mask];
}
DRAW_COLUMN(atbuf, v_line)
}
else
{
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
}
for(column = start; column < end; column++, index++)
{
#ifdef LSB_FIRST
v_line = (line + vs[column]) & pf_row_mask;
#else
v_line = (line + (vs[column] >> 16)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN(atbuf, v_line)
}
start = clip[1].left;
end = clip[1].right;
}
else if (!cinterface_render_bga)
{
memset(&linebuf[1][0], 0, 512);
}
if (w && cinterface_render_bgw)
{
nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
v_line = (line & 7) << 3;
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
for(column = start; column < end; column++)
{
atbuf = nt[column];
DRAW_COLUMN(atbuf, v_line)
}
}
merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[(reg[12] & 0x08) >> 2], bitmap.viewport.w);
}
void render_bg_m5_im2(int line)
{
int column;
uint32 atex, atbuf, *src, *dst;
int odd = odd_frame;
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = *(uint32 *)&vsram[0];
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
int start = 0;
int end = bitmap.viewport.w >> 4;
#ifdef LSB_FIRST
uint32 shift = (xscroll >> 16) & 0x0F;
uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
uint32 v_line = (line + (yscroll >> 17)) & pf_row_mask;
#else
uint32 shift = (xscroll & 0x0F);
uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
uint32 v_line = (line + (yscroll >> 1)) & pf_row_mask;
#endif
uint32 *nt;
if (cinterface_render_bgb)
{
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
if(shift)
{
dst = (uint32 *)&linebuf[0][0x10 + shift];
atbuf = nt[(index - 1) & pf_col_mask];
DRAW_COLUMN_IM2(atbuf, v_line)
}
else
{
dst = (uint32 *)&linebuf[0][0x20];
}
for(column = 0; column < end; column++, index++)
{
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN_IM2(atbuf, v_line)
}
}
else
{
memset(&linebuf[0][0], 0, 512);
}
if (w == (line >= a))
{
a = 0;
w = 1;
}
else
{
a = clip[0].enable;
w = clip[1].enable;
}
if (a && cinterface_render_bga)
{
start = clip[0].left;
end = clip[0].right;
#ifdef LSB_FIRST
shift = (xscroll & 0x0F);
index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
v_line = (line + (yscroll >> 1)) & pf_row_mask;
#else
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
v_line = (line + (yscroll >> 17)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
if(shift)
{
dst = (uint32 *)&linebuf[1][0x10 + shift + (start << 4)];
if (start)
{
atbuf = nt[index & pf_col_mask];
}
else
{
atbuf = nt[(index - 1) & pf_col_mask];
}
DRAW_COLUMN_IM2(atbuf, v_line)
}
else
{
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
}
for(column = start; column < end; column++, index++)
{
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN_IM2(atbuf, v_line)
}
start = clip[1].left;
end = clip[1].right;
}
else if (!cinterface_render_bga)
{
memset(&linebuf[1][0], 0, 512);
}
if (w && cinterface_render_bgw)
{
nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
v_line = ((line & 7) << 1 | odd) << 3;
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
for(column = start; column < end; column++)
{
atbuf = nt[column];
DRAW_COLUMN_IM2(atbuf, v_line)
}
}
merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[(reg[12] & 0x08) >> 2], bitmap.viewport.w);
}
void render_bg_m5_im2_vs(int line)
{
int column;
uint32 atex, atbuf, *src, *dst;
uint32 v_line, *nt;
int odd = odd_frame;
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = 0;
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
uint32 *vs = (uint32 *)&vsram[0];
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
int start = 0;
int end = bitmap.viewport.w >> 4;
#ifdef LSB_FIRST
uint32 shift = (xscroll >> 16) & 0x0F;
uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
#else
uint32 shift = (xscroll & 0x0F);
uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
#endif
if (reg[12] & 1)
{
yscroll = (vs[19] >> 1) & (vs[19] >> 17);
}
if (cinterface_render_bgb)
{
if(shift)
{
v_line = (line + yscroll) & pf_row_mask;
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
dst = (uint32 *)&linebuf[0][0x10 + shift];
atbuf = nt[(index - 1) & pf_col_mask];
DRAW_COLUMN_IM2(atbuf, v_line)
}
else
{
dst = (uint32 *)&linebuf[0][0x20];
}
for(column = 0; column < end; column++, index++)
{
#ifdef LSB_FIRST
v_line = (line + (vs[column] >> 17)) & pf_row_mask;
#else
v_line = (line + (vs[column] >> 1)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN_IM2(atbuf, v_line)
}
}
else
{
memset(&linebuf[0][0], 0, 512);
}
if (w == (line >= a))
{
a = 0;
w = 1;
}
else
{
a = clip[0].enable;
w = clip[1].enable;
}
if (a && cinterface_render_bga)
{
start = clip[0].left;
end = clip[0].right;
#ifdef LSB_FIRST
shift = (xscroll & 0x0F);
index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
#else
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
#endif
if(shift)
{
v_line = (line + yscroll) & pf_row_mask;
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
dst = (uint32 *)&linebuf[1][0x10 + shift + (start << 4)];
if (start)
{
atbuf = nt[index & pf_col_mask];
}
else
{
atbuf = nt[(index - 1) & pf_col_mask];
}
DRAW_COLUMN_IM2(atbuf, v_line)
}
else
{
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
}
for(column = start; column < end; column++, index++)
{
#ifdef LSB_FIRST
v_line = (line + (vs[column] >> 1)) & pf_row_mask;
#else
v_line = (line + (vs[column] >> 17)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN_IM2(atbuf, v_line)
}
start = clip[1].left;
end = clip[1].right;
}
else if (!cinterface_render_bga)
{
memset(&linebuf[1][0], 0, 512);
}
if (w && cinterface_render_bgw)
{
nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
v_line = ((line & 7) << 1 | odd) << 3;
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
for(column = start; column < end; column++)
{
atbuf = nt[column];
DRAW_COLUMN_IM2(atbuf, v_line)
}
}
merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[(reg[12] & 0x08) >> 2], bitmap.viewport.w);
}
#else
void render_bg_m5(int line)
{
int column, start, end;
uint32 atex, atbuf, *src, *dst;
uint32 shift, index, v_line, *nt;
uint8 *lb;
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = *(uint32 *)&vsram[0];
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
int width = bitmap.viewport.w >> 4;
uint8 *table = lut[(reg[12] & 8) >> 2];
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
if (w == (line >= a))
{
a = 0;
w = 1;
}
else
{
a = clip[0].enable;
w = clip[1].enable;
}
if (a)
{
start = clip[0].left;
end = clip[0].right;
#ifdef LSB_FIRST
shift = (xscroll & 0x0F);
index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
v_line = (line + yscroll) & pf_row_mask;
#else
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
v_line = (line + (yscroll >> 16)) & pf_row_mask;
#endif
dst = (uint32 *)&linebuf[0][0x20 + (start << 4) + shift];
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
if(shift)
{
dst -= 4;
if (start)
{
atbuf = nt[index & pf_col_mask];
}
else
{
atbuf = nt[(index-1) & pf_col_mask];
}
DRAW_COLUMN(atbuf, v_line)
}
for(column = start; column < end; column++, index++)
{
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN(atbuf, v_line)
}
start = clip[1].left;
end = clip[1].right;
}
else
{
start = 0;
end = width;
}
if (w)
{
dst = (uint32 *)&linebuf[0][0x20 + (start << 4)];
nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
v_line = (line & 7) << 3;
for(column = start; column < end; column++)
{
atbuf = nt[column];
DRAW_COLUMN(atbuf, v_line)
}
}
#ifdef LSB_FIRST
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
v_line = (line + (yscroll >> 16)) & pf_row_mask;
#else
shift = (xscroll & 0x0F);
index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
v_line = (line + yscroll) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
lb = &linebuf[0][0x20];
if(shift)
{
lb -= (0x10 - shift);
atbuf = nt[(index-1) & pf_col_mask];
DRAW_BG_COLUMN(atbuf, v_line, xscroll, yscroll)
}
for(column = 0; column < width; column++, index++)
{
atbuf = nt[index & pf_col_mask];
DRAW_BG_COLUMN(atbuf, v_line, xscroll, yscroll)
}
}
void render_bg_m5_vs(int line)
{
int column, start, end;
uint32 atex, atbuf, *src, *dst;
uint32 shift, index, v_line, *nt;
uint8 *lb;
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = 0;
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
uint32 *vs = (uint32 *)&vsram[0];
int width = bitmap.viewport.w >> 4;
uint8 *table = lut[(reg[12] & 8) >> 2];
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
if (w == (line >= a))
{
a = 0;
w = 1;
}
else
{
a = clip[0].enable;
w = clip[1].enable;
}
if (reg[12] & 1)
{
yscroll = vs[19] & (vs[19] >> 16);
}
if (a)
{
start = clip[0].left;
end = clip[0].right;
#ifdef LSB_FIRST
shift = (xscroll & 0x0F);
index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
#else
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
#endif
dst = (uint32 *)&linebuf[0][0x20 + (start << 4) + shift];
if(shift)
{
dst -= 4;
v_line = (line + yscroll) & pf_row_mask;
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
if (start)
{
atbuf = nt[index & pf_col_mask];
}
else
{
atbuf = nt[(index-1) & pf_col_mask];
}
DRAW_COLUMN(atbuf, v_line)
}
for(column = start; column < end; column++, index++)
{
#ifdef LSB_FIRST
v_line = (line + vs[column]) & pf_row_mask;
#else
v_line = (line + (vs[column] >> 16)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN(atbuf, v_line)
}
start = clip[1].left;
end = clip[1].right;
}
else
{
start = 0;
end = width;
}
if (w)
{
dst = (uint32 *)&linebuf[0][0x20 + (start << 4)];
nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
v_line = (line & 7) << 3;
for(column = start; column < end; column++)
{
atbuf = nt[column];
DRAW_COLUMN(atbuf, v_line)
}
}
#ifdef LSB_FIRST
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
#else
shift = (xscroll & 0x0F);
index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
#endif
lb = &linebuf[0][0x20];
if(shift)
{
lb -= (0x10 - shift);
v_line = (line + yscroll) & pf_row_mask;
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[(index-1) & pf_col_mask];
DRAW_BG_COLUMN(atbuf, v_line, xscroll, yscroll)
}
for(column = 0; column < width; column++, index++)
{
#ifdef LSB_FIRST
v_line = (line + (vs[column] >> 16)) & pf_row_mask;
#else
v_line = (line + vs[column]) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (v_line & 7) << 3;
atbuf = nt[index & pf_col_mask];
DRAW_BG_COLUMN(atbuf, v_line, xscroll, yscroll)
}
}
void render_bg_m5_im2(int line)
{
int column, start, end;
uint32 atex, atbuf, *src, *dst;
uint32 shift, index, v_line, *nt;
uint8 *lb;
int odd = odd_frame;
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = *(uint32 *)&vsram[0];
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
int width = bitmap.viewport.w >> 4;
uint8 *table = lut[(reg[12] & 8) >> 2];
int a = (reg[18] & 0x1F) << 3;
int w = (reg[18] >> 7) & 1;
if (w == (line >= a))
{
a = 0;
w = 1;
}
else
{
a = clip[0].enable;
w = clip[1].enable;
}
if (a)
{
start = clip[0].left;
end = clip[0].right;
#ifdef LSB_FIRST
shift = (xscroll & 0x0F);
index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
v_line = (line + (yscroll >> 1)) & pf_row_mask;
#else
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
v_line = (line + (yscroll >> 17)) & pf_row_mask;
#endif
dst = (uint32 *)&linebuf[0][0x20 + (start << 4) + shift];
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
if(shift)
{
dst -= 4;
if (start)
{
atbuf = nt[index & pf_col_mask];
}
else
{
atbuf = nt[(index-1) & pf_col_mask];
}
DRAW_COLUMN_IM2(atbuf, v_line)
}
for(column = start; column < end; column++, index++)
{
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN_IM2(atbuf, v_line)
}
start = clip[1].left;
end = clip[1].right;
}
else
{
start = 0;
end = width;
}
if (w)
{
dst = (uint32 *)&linebuf[0][0x20 + (start << 4)];
nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
v_line = ((line & 7) << 1 | odd) << 3;
for(column = start; column < end; column++)
{
atbuf = nt[column];
DRAW_COLUMN_IM2(atbuf, v_line)
}
}
#ifdef LSB_FIRST
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
v_line = (line + (yscroll >> 17)) & pf_row_mask;
#else
shift = (xscroll & 0x0F);
index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
v_line = (line + (yscroll >> 1)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
lb = &linebuf[0][0x20];
if(shift)
{
lb -= (0x10 - shift);
atbuf = nt[(index-1) & pf_col_mask];
DRAW_BG_COLUMN_IM2(atbuf, v_line, xscroll, yscroll)
}
for(column = 0; column < width; column++, index++)
{
atbuf = nt[index & pf_col_mask];
DRAW_BG_COLUMN_IM2(atbuf, v_line, xscroll, yscroll)
}
}
void render_bg_m5_im2_vs(int line)
{
int column, start, end;
uint32 atex, atbuf, *src, *dst;
uint32 shift, index, v_line, *nt;
uint8 *lb;
int odd = odd_frame;
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
uint32 yscroll = 0;
uint32 pf_col_mask = playfield_col_mask;
uint32 pf_row_mask = playfield_row_mask;
uint32 pf_shift = playfield_shift;
uint32 *vs = (uint32 *)&vsram[0];
int width = bitmap.viewport.w >> 4;
uint8 *table = lut[(reg[12] & 8) >> 2];
uint32 a = (reg[18] & 0x1F) << 3;
uint32 w = (reg[18] >> 7) & 1;
if (w == (line >= a))
{
a = 0;
w = 1;
}
else
{
a = clip[0].enable;
w = clip[1].enable;
}
if (reg[12] & 1)
{
yscroll = (vs[19] >> 1) & (vs[19] >> 17);
}
if (a)
{
start = clip[0].left;
end = clip[0].right;
#ifdef LSB_FIRST
shift = (xscroll & 0x0F);
index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
#else
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
#endif
dst = (uint32 *)&linebuf[0][0x20 + (start << 4) + shift];
if(shift)
{
dst -= 4;
v_line = (line + yscroll) & pf_row_mask;
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
if (start)
{
atbuf = nt[index & pf_col_mask];
}
else
{
atbuf = nt[(index-1) & pf_col_mask];
}
DRAW_COLUMN_IM2(atbuf, v_line)
}
for(column = start; column < end; column++, index++)
{
#ifdef LSB_FIRST
v_line = (line + (vs[column] >> 1)) & pf_row_mask;
#else
v_line = (line + (vs[column] >> 17)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
atbuf = nt[index & pf_col_mask];
DRAW_COLUMN_IM2(atbuf, v_line)
}
start = clip[1].left;
end = clip[1].right;
}
else
{
start = 0;
end = width;
}
if (w)
{
dst = (uint32 *)&linebuf[0][0x20 + (start << 4)];
nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
v_line = ((line & 7) << 1 | odd) << 3;
for(column = start; column < end; column++)
{
atbuf = nt[column];
DRAW_COLUMN_IM2(atbuf, v_line)
}
}
#ifdef LSB_FIRST
shift = (xscroll >> 16) & 0x0F;
index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
#else
shift = (xscroll & 0x0F);
index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
#endif
lb = &linebuf[0][0x20];
if(shift)
{
lb -= (0x10 - shift);
v_line = (line + yscroll) & pf_row_mask;
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
atbuf = nt[(index-1) & pf_col_mask];
DRAW_BG_COLUMN_IM2(atbuf, v_line, xscroll, yscroll)
}
for(column = 0; column < width; column++, index++)
{
#ifdef LSB_FIRST
v_line = (line + (vs[column] >> 17)) & pf_row_mask;
#else
v_line = (line + (vs[column] >> 1)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
v_line = (((v_line & 7) << 1) | odd) << 3;
atbuf = nt[index & pf_col_mask];
DRAW_BG_COLUMN_IM2(atbuf, v_line, xscroll, yscroll)
}
}
#endif
void render_obj_tms(int line)
{
int x, start, end;
uint8 *lb, *sg;
uint8 color, pattern[2];
uint16 temp;
object_info_t *object_info = obj_info[line];
int count = object_count[line];
int width = 8;
width <<= ((reg[1] & 0x02) >> 1);
width <<= (reg[1] & 0x01);
status |= spr_ovr;
spr_ovr = 0;
while (count--)
{
start = object_info->xpos;
color = object_info->size;
start -= ((color & 0x80) >> 2);
lb = &linebuf[0][0x20 + start];
if ((start + width) > 256)
{
end = 256 - start;
start = 0;
}
else
{
end = width;
if (start < 0)
{
start = 0 - start;
}
else
{
start = 0;
}
}
color &= 0x0F;
temp = object_info->attr;
temp &= ~((reg[1] & 0x02) >> 0);
temp &= ~((reg[1] & 0x02) >> 1);
sg = (uint8 *)&vram[((reg[6] << 11) & 0x3800) | (temp << 3) | object_info->ypos];
pattern[0] = sg[0x00];
pattern[1] = sg[0x10];
if (reg[1] & 0x01)
{
for (x=start; x<end; x+=2)
{
temp = pattern[(x >> 4) & 1];
temp = (temp >> (7 - ((x >> 1) & 7))) & 0x01;
temp = temp * color;
temp |= (lb[x] << 8);
lb[x] = lut[5][temp];
status |= ((temp & 0x8000) >> 10);
temp &= 0x00FF;
temp |= (lb[x+1] << 8);
lb[x+1] = lut[5][temp];
status |= ((temp & 0x8000) >> 10);
}
}
else
{
for (x=start; x<end; x++)
{
temp = pattern[(x >> 3) & 1];
temp = (temp >> (7 - (x & 7))) & 0x01;
temp = temp * color;
temp |= (lb[x] << 8);
lb[x] = lut[5][temp];
status |= ((temp & 0x8000) >> 10);
}
}
object_info++;
}
if ((system_hw == SYSTEM_GG) && !config.gg_extra && (v_counter < bitmap.viewport.h))
{
int line = v_counter - (bitmap.viewport.h - 144) / 2;
if ((line < 0) || (line >= 144))
{
memset(&linebuf[0][0x20], 0x40, 256);
}
else
{
if (bitmap.viewport.x > 0)
{
memset(&linebuf[0][0x20], 0x40, 48);
memset(&linebuf[0][0x20+48+160], 0x40, 48);
}
}
}
}
void render_obj_m4(int line)
{
int i, xpos, end;
uint8 *src, *lb;
uint16 temp;
object_info_t *object_info = obj_info[line];
int count = object_count[line];
int width = 8;
uint16 sg_mask = (~0x1C0 ^ (reg[6] << 6)) & (~((reg[1] & 0x02) >> 1));
if (system_hw < SYSTEM_MD)
{
width <<= (reg[1] & 0x01);
}
if (system_hw > SYSTEM_SMS)
{
sg_mask |= 0xC0;
}
status |= spr_ovr;
spr_ovr = 0;
while (count--)
{
temp = (object_info->attr | 0x100) & sg_mask;
src = (uint8 *)&bg_pattern_cache[(temp << 6) | (object_info->ypos << 3)];
xpos = object_info->xpos;
xpos -= (reg[0] & 0x08);
if (xpos < 0)
{
src = src - xpos;
end = xpos + width;
xpos = 0;
}
else if ((xpos + width) > 256)
{
end = 256 - xpos;
}
else
{
end = width;
}
lb = &linebuf[0][0x20 + xpos];
if (width > 8)
{
DRAW_SPRITE_TILE_ACCURATE_2X(end,0,lut[5])
if (system_hw < SYSTEM_SMS2)
{
if (count == (object_count[line] - 4))
{
width = 8;
}
}
}
else
{
DRAW_SPRITE_TILE_ACCURATE(end,0,lut[5])
}
object_info++;
}
if ((system_hw == SYSTEM_GG) && !config.gg_extra && (v_counter < bitmap.viewport.h))
{
int line = v_counter - (bitmap.viewport.h - 144) / 2;
if ((line < 0) || (line >= 144))
{
memset(&linebuf[0][0x20], 0x40, 256);
}
else
{
if (bitmap.viewport.x > 0)
{
memset(&linebuf[0][0x20], 0x40, 48);
memset(&linebuf[0][0x20+48+160], 0x40, 48);
}
}
}
}
void render_obj_m5(int line)
{
int i, column;
int xpos, width;
int pixelcount = 0;
int masked = 0;
uint8 *src, *s, *lb;
uint32 temp, v_line;
uint32 attr, name, atex;
object_info_t *object_info = obj_info[line];
int count = object_count[line];
while (count--)
{
xpos = object_info->xpos;
if (xpos)
{
spr_ovr = 1;
}
else if (spr_ovr)
{
masked = 1;
}
xpos = xpos - 0x80;
temp = object_info->size;
width = 8 + ((temp & 0x0C) << 1);
pixelcount += width;
if (((xpos + width) > 0) && (xpos < bitmap.viewport.w) && !masked)
{
attr = object_info->attr;
v_line = object_info->ypos;
atex = (attr >> 9) & 0x70;
name = attr & 0x07FF;
attr &= 0x1800;
s = &name_lut[((attr >> 3) & 0x300) | (temp << 4) | ((v_line & 0x18) >> 1)];
lb = &linebuf[0][0x20 + xpos];
if (pixelcount > max_sprite_pixels)
{
width -= (pixelcount - max_sprite_pixels);
}
width = width >> 3;
v_line = (v_line & 7) << 3;
for (column = 0; column < width; column++, lb+=8)
{
temp = attr | ((name + s[column]) & 0x07FF);
src = &bg_pattern_cache[(temp << 6) | (v_line)];
DRAW_SPRITE_TILE(8,atex,lut[1])
}
}
if (pixelcount >= max_sprite_pixels)
{
spr_ovr = (pixelcount >= bitmap.viewport.w);
return;
}
object_info++;
}
spr_ovr = 0;
}
void render_obj_m5_ste(int line)
{
int i, column;
int xpos, width;
int pixelcount = 0;
int masked = 0;
uint8 *src, *s, *lb;
uint32 temp, v_line;
uint32 attr, name, atex;
object_info_t *object_info = obj_info[line];
int count = object_count[line];
memset(&linebuf[1][0], 0, bitmap.viewport.w + 0x40);
while (count--)
{
xpos = object_info->xpos;
if (xpos)
{
spr_ovr = 1;
}
else if (spr_ovr)
{
masked = 1;
}
xpos = xpos - 0x80;
temp = object_info->size;
width = 8 + ((temp & 0x0C) << 1);
pixelcount += width;
if (((xpos + width) > 0) && (xpos < bitmap.viewport.w) && !masked)
{
attr = object_info->attr;
v_line = object_info->ypos;
atex = (attr >> 9) & 0x70;
name = attr & 0x07FF;
attr &= 0x1800;
s = &name_lut[((attr >> 3) & 0x300) | (temp << 4) | ((v_line & 0x18) >> 1)];
lb = &linebuf[1][0x20 + xpos];
if (pixelcount > max_sprite_pixels)
{
width -= (pixelcount - max_sprite_pixels);
}
width = width >> 3;
v_line = (v_line & 7) << 3;
for (column = 0; column < width; column++, lb+=8)
{
temp = attr | ((name + s[column]) & 0x07FF);
src = &bg_pattern_cache[(temp << 6) | (v_line)];
DRAW_SPRITE_TILE(8,atex,lut[3])
}
}
if (pixelcount >= max_sprite_pixels)
{
spr_ovr = (pixelcount >= bitmap.viewport.w);
merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[4], bitmap.viewport.w);
return;
}
object_info++;
}
spr_ovr = 0;
merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[4], bitmap.viewport.w);
}
void render_obj_m5_im2(int line)
{
int i, column;
int xpos, width;
int pixelcount = 0;
int masked = 0;
int odd = odd_frame;
uint8 *src, *s, *lb;
uint32 temp, v_line;
uint32 attr, name, atex;
object_info_t *object_info = obj_info[line];
int count = object_count[line];
while (count--)
{
xpos = object_info->xpos;
if (xpos)
{
spr_ovr = 1;
}
else if (spr_ovr)
{
masked = 1;
}
xpos = xpos - 0x80;
temp = object_info->size;
width = 8 + ((temp & 0x0C) << 1);
pixelcount += width;
if (((xpos + width) > 0) && (xpos < bitmap.viewport.w) && !masked)
{
attr = object_info->attr;
v_line = object_info->ypos;
atex = (attr >> 9) & 0x70;
name = attr & 0x03FF;
attr &= 0x1800;
s = &name_lut[((attr >> 3) & 0x300) | (temp << 4) | ((v_line & 0x18) >> 1)];
lb = &linebuf[0][0x20 + xpos];
if (pixelcount > max_sprite_pixels)
{
width -= (pixelcount - max_sprite_pixels);
}
width = width >> 3;
v_line = (((v_line & 7) << 1) | odd) << 3;
for(column = 0; column < width; column ++, lb+=8)
{
temp = attr | (((name + s[column]) & 0x3ff) << 1);
src = &bg_pattern_cache[((temp << 6) | (v_line)) ^ ((attr & 0x1000) >> 6)];
DRAW_SPRITE_TILE(8,atex,lut[1])
}
}
if (pixelcount >= max_sprite_pixels)
{
spr_ovr = (pixelcount >= bitmap.viewport.w);
return;
}
object_info++;
}
spr_ovr = 0;
}
void render_obj_m5_im2_ste(int line)
{
int i, column;
int xpos, width;
int pixelcount = 0;
int masked = 0;
int odd = odd_frame;
uint8 *src, *s, *lb;
uint32 temp, v_line;
uint32 attr, name, atex;
object_info_t *object_info = obj_info[line];
int count = object_count[line];
memset(&linebuf[1][0], 0, bitmap.viewport.w + 0x40);
while (count--)
{
xpos = object_info->xpos;
if (xpos)
{
spr_ovr = 1;
}
else if (spr_ovr)
{
masked = 1;
}
xpos = xpos - 0x80;
temp = object_info->size;
width = 8 + ((temp & 0x0C) << 1);
pixelcount += width;
if (((xpos + width) > 0) && (xpos < bitmap.viewport.w) && !masked)
{
attr = object_info->attr;
v_line = object_info->ypos;
atex = (attr >> 9) & 0x70;
name = attr & 0x03FF;
attr &= 0x1800;
s = &name_lut[((attr >> 3) & 0x300) | (temp << 4) | ((v_line & 0x18) >> 1)];
lb = &linebuf[1][0x20 + xpos];
if (pixelcount > max_sprite_pixels)
{
width -= (pixelcount - max_sprite_pixels);
}
width = width >> 3;
v_line = (((v_line & 7) << 1) | odd) << 3;
for(column = 0; column < width; column ++, lb+=8)
{
temp = attr | (((name + s[column]) & 0x3ff) << 1);
src = &bg_pattern_cache[((temp << 6) | (v_line)) ^ ((attr & 0x1000) >> 6)];
DRAW_SPRITE_TILE(8,atex,lut[3])
}
}
if (pixelcount >= max_sprite_pixels)
{
spr_ovr = (pixelcount >= bitmap.viewport.w);
merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[4], bitmap.viewport.w);
return;
}
object_info++;
}
spr_ovr = 0;
merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[4], bitmap.viewport.w);
}
void parse_satb_tms(int line)
{
int i = 0;
int count = 0;
if (!(reg[1] & 0x10))
{
int ypos;
object_info_t *object_info = obj_info[(line + 1) & 1];
uint8 *st = &vram[(reg[5] << 7) & 0x3F80];
int height = 8;
height <<= ((reg[1] & 0x02) >> 1);
height <<= (reg[1] & 0x01);
do
{
ypos = st[i << 2];
if (ypos == 0xD0)
{
break;
}
if (ypos >= 224)
{
ypos -= 256;
}
ypos = line - ypos;
if ((ypos >= 0) && (ypos < height))
{
if (count == 4)
{
if (line < bitmap.viewport.h)
{
spr_ovr = 0x40;
}
break;
}
ypos >>= (reg[1] & 0x01);
object_info->ypos = ypos;
object_info->xpos = st[(i << 2) + 1];
object_info->attr = st[(i << 2) + 2];
object_info->size = st[(i << 2) + 3];
++count;
object_info++;
}
}
while (++i < 32);
}
object_count[(line + 1) & 1] = count;
status = (status & 0xE0) | (i & 0x1F);
}
void parse_satb_m4(int line)
{
int i = 0;
uint8 *st;
int count = 0;
int ypos;
object_info_t *object_info = obj_info[(line + 1) & 1];
int height = 8 + ((reg[1] & 0x02) << 2);
uint16 st_mask = ~0x3F80 ^ (reg[5] << 7);
if (system_hw > SYSTEM_SMS)
{
st_mask |= 0x80;
}
st = &vram[st_mask & 0x3F00];
do
{
ypos = st[i];
if (ypos == (bitmap.viewport.h + 16))
{
break;
}
if (ypos >= 240)
{
ypos -= 256;
}
ypos = line - ypos;
if (system_hw < SYSTEM_MD)
{
ypos >>= (reg[1] & 0x01);
}
if ((ypos >= 0) && (ypos < height))
{
if (count == 8)
{
if ((line >= 0) && (line < bitmap.viewport.h))
{
spr_ovr = 0x40;
}
break;
}
object_info->ypos = ypos;
object_info->xpos = st[(0x80 + (i << 1)) & st_mask];
object_info->attr = st[(0x81 + (i << 1)) & st_mask];
++count;
object_info++;
}
}
while (++i < 64);
object_count[(line + 1) & 1] = count;
}
void parse_satb_m5(int line)
{
int ypos;
int height;
int size;
int link = 0;
int count = 0;
int max = bitmap.viewport.w >> 4;
int total = max_sprite_pixels >> 2;
uint16 *p = (uint16 *) &vram[satb];
uint16 *q = (uint16 *) &sat[0];
object_info_t *object_info = obj_info[(line + 1) & 1];
line += 0x81;
do
{
ypos = (q[link] >> im2_flag) & 0x1FF;
if (line >= ypos)
{
size = q[link + 1] >> 8;
height = 8 + ((size & 3) << 3);
ypos = line - ypos;
if (ypos < height)
{
if (count == max)
{
status |= 0x40;
break;
}
object_info->attr = p[link + 2];
object_info->xpos = p[link + 3] & 0x1ff;
object_info->ypos = ypos;
object_info->size = size & 0x0f;
++count;
object_info++;
}
}
link = (q[link + 1] & 0x7F) << 2;
if ((link == 0) || (link >= bitmap.viewport.w)) break;
}
while (--total);
object_count[line & 1] = count;
}
void update_bg_pattern_cache_m4(int index)
{
int i;
uint8 x, y, c;
uint8 *dst;
uint16 name, bp01, bp23;
uint32 bp;
for(i = 0; i < index; i++)
{
name = bg_name_list[i];
for(y = 0; y < 8; y++)
{
if(bg_name_dirty[name] & (1 << y))
{
dst = &bg_pattern_cache[name << 6];
bp01 = *(uint16 *)&vram[(name << 5) | (y << 2) | (0)];
bp23 = *(uint16 *)&vram[(name << 5) | (y << 2) | (2)];
bp = (bp_lut[bp01] >> 2) | (bp_lut[bp23]);
for(x = 0; x < 8; x++)
{
c = bp & 0x0F;
dst[0x00000 | (y << 3) | (x)] = (c);
dst[0x08000 | (y << 3) | (x ^ 7)] = (c);
dst[0x10000 | ((y ^ 7) << 3) | (x)] = (c);
dst[0x18000 | ((y ^ 7) << 3) | (x ^ 7)] = (c);
bp = bp >> 4;
}
}
}
bg_name_dirty[name] = 0;
}
}
void update_bg_pattern_cache_m5(int index)
{
int i;
uint8 x, y, c;
uint8 *dst;
uint16 name;
uint32 bp;
for(i = 0; i < index; i++)
{
name = bg_name_list[i];
for(y = 0; y < 8; y ++)
{
if(bg_name_dirty[name] & (1 << y))
{
dst = &bg_pattern_cache[name << 6];
bp = *(uint32 *)&vram[(name << 5) | (y << 2)];
for(x = 0; x < 8; x ++)
{
c = bp & 0x0F;
#ifdef LSB_FIRST
dst[0x00000 | (y << 3) | (x ^ 3)] = (c);
dst[0x20000 | (y << 3) | (x ^ 4)] = (c);
dst[0x40000 | ((y ^ 7) << 3) | (x ^ 3)] = (c);
dst[0x60000 | ((y ^ 7) << 3) | (x ^ 4)] = (c);
#else
dst[0x00000 | (y << 3) | (x ^ 7)] = (c);
dst[0x20000 | (y << 3) | (x)] = (c);
dst[0x40000 | ((y ^ 7) << 3) | (x ^ 7)] = (c);
dst[0x60000 | ((y ^ 7) << 3) | (x)] = (c);
#endif
bp = bp >> 4;
}
}
}
bg_name_dirty[name] = 0;
}
}
void window_clip(unsigned int data, unsigned int sw)
{
int hp = (data & 0x1f);
int hf = (data >> 7) & 1;
int a = hf;
int w = hf ^ 1;
sw = 16 + (sw << 2);
if(hp)
{
if(hp > sw)
{
clip[w].left = 0;
clip[w].right = sw;
clip[w].enable = 1;
clip[a].enable = 0;
}
else
{
clip[w].left = 0;
clip[a].right = sw;
clip[a].left = clip[w].right = hp;
clip[0].enable = clip[1].enable = 1;
}
}
else
{
clip[a].left = 0;
clip[a].right = sw;
clip[a].enable = 1;
clip[w].enable = 0;
}
}
void render_init(void)
{
int bx, ax;
uint16 index;
for (bx = 0; bx < 0x100; bx++)
{
for (ax = 0; ax < 0x100; ax++)
{
index = (bx << 8) | (ax);
lut[0][index] = make_lut_bg(bx, ax);
lut[1][index] = make_lut_bgobj(bx, ax);
lut[2][index] = make_lut_bg_ste(bx, ax);
lut[3][index] = make_lut_obj(bx, ax);
lut[4][index] = make_lut_bgobj_ste(bx, ax);
lut[5][index] = make_lut_bgobj_m4(bx,ax);
}
}
palette_init();
make_name_lut();
make_bp_lut();
}
void render_reset(void)
{
memset(bitmap.data, 0, bitmap.pitch * bitmap.height);
memset(linebuf, 0, sizeof(linebuf));
memset(pixel, 0, sizeof(pixel));
memset ((char *) bg_pattern_cache, 0, sizeof (bg_pattern_cache));
spr_ovr = spr_col = object_count[0] = object_count[1] = 0;
}
void render_line(int line)
{
if (reg[1] & 0x40)
{
if (bg_list_index)
{
update_bg_pattern_cache(bg_list_index);
bg_list_index = 0;
}
render_bg(line);
render_obj(line & 1);
if (reg[0] & 0x20)
{
if (system_hw > SYSTEM_SG)
{
memset(&linebuf[0][0x20], 0x40, 8);
}
}
if (line < (bitmap.viewport.h - 1))
{
parse_satb(line);
}
if (bitmap.viewport.x > 0)
{
memset(&linebuf[0][0x20 - bitmap.viewport.x], 0x40, bitmap.viewport.x);
memset(&linebuf[0][0x20 + bitmap.viewport.w], 0x40, bitmap.viewport.x);
}
}
else
{
if (system_hw < SYSTEM_MD)
{
status |= spr_ovr;
spr_ovr = 0;
parse_satb(line);
}
memset(&linebuf[0][0x20 - bitmap.viewport.x], 0x40, bitmap.viewport.w + 2*bitmap.viewport.x);
}
remap_line(line);
}
void blank_line(int line, int offset, int width)
{
memset(&linebuf[0][0x20 + offset], 0x40, width);
remap_line(line);
}
void remap_line(int line)
{
int width = bitmap.viewport.w + 2*bitmap.viewport.x;
uint8 *src = &linebuf[0][0x20 - bitmap.viewport.x];
line = (line + bitmap.viewport.y) % lines_per_frame;
if (line < 0) return;
if (interlaced && config.render)
{
line = (line * 2) + odd_frame;
}
#if defined(USE_15BPP_RENDERING) || defined(USE_16BPP_RENDERING)
if (config.ntsc)
{
if (reg[12] & 0x01)
{
md_ntsc_blit(md_ntsc, ( MD_NTSC_IN_T const * )pixel, src, width, line);
}
else
{
sms_ntsc_blit(sms_ntsc, ( SMS_NTSC_IN_T const * )pixel, src, width, line);
}
}
else
#endif
{
#ifdef CUSTOM_BLITTER
CUSTOM_BLITTER(line, width, pixel, src)
#else
PIXEL_OUT_T *dst =((PIXEL_OUT_T *)&bitmap.data[(line * bitmap.pitch)]);
do
{
*dst++ = pixel[*src++];
}
while (--width);
#endif
}
}