~modified RGB565 color palette

This commit is contained in:
ekeeke31 2009-07-03 16:18:16 +00:00
parent 086548476c
commit 9800c00f5a
3 changed files with 363 additions and 395 deletions

View File

@ -7,7 +7,7 @@ Genesis Plus GX 1.3.2 (??/??/????) (Eke-Eke)
* optimized SN76489 core * optimized SN76489 core
* modified SN76489 cut-off frequency (thanks to Steve Snake) * modified SN76489 cut-off frequency (thanks to Steve Snake)
* added SN76489 linear synthesis using Blip Buffer (thanks to Blargg) * modified SN76489 core to use Blip Buffer linear synthesis , Noise channel is now linear averaged (thanks to Blargg)
* added an option to boost SN76489 Noise Channel * added an option to boost SN76489 Noise Channel
* removed now outdated Gens YM2612 core * removed now outdated Gens YM2612 core
* improved YM2612 emulation accuracy (SSG-EG, CSM mode...) (thanks to Nemesis for his tests on real hardware) * improved YM2612 emulation accuracy (SSG-EG, CSM mode...) (thanks to Nemesis for his tests on real hardware)

View File

@ -41,34 +41,6 @@ typedef struct
uint8 enable; uint8 enable;
}clip_t; }clip_t;
/* Function prototypes */
static void palette_init(void);
static void make_name_lut(void);
static uint32 make_lut_bg(uint32 bx, uint32 ax);
static uint32 make_lut_obj(uint32 bx, uint32 sx);
static uint32 make_lut_bg_ste(uint32 bx, uint32 ax);
static uint32 make_lut_obj_ste(uint32 bx, uint32 sx);
static uint32 make_lut_bgobj_ste(uint32 bx, uint32 sx);
static void color_update_16(int index, uint16 data);
#ifndef NGC
static void color_update_8(int index, uint16 data);
static void color_update_15(int index, uint16 data);
static void color_update_32(int index, uint16 data);
static inline void remap_8(uint8 *src, uint8 *dst, uint8 *table, int length);
static inline void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length);
static inline void remap_32(uint8 *src, uint32 *dst, uint32 *table, int length);
#else
static inline void remap_texture(uint8 *src, uint16 *dst, uint32 tiles);
#endif
static inline void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, uint32 width);
static inline void update_bg_pattern_cache(uint32 index);
static inline uint32 get_hscroll(uint32 line);
static void render_bg(uint32 line, uint32 width);
static void render_bg_im2(uint32 line, uint32 width, uint32 odd);
static void render_bg_vs(uint32 line, uint32 width);
static void render_obj(uint32 line, uint8 *buf, uint8 *table);
static void render_obj_im2(uint32 line, uint32 odd, uint8 *buf, uint8 *table);
#undef ALIGN_LONG #undef ALIGN_LONG
#ifdef ALIGN_LONG #ifdef ALIGN_LONG
/* Or change the names if you depend on these from elsewhere.. */ /* Or change the names if you depend on these from elsewhere.. */
@ -110,8 +82,8 @@ static __inline__ void WRITE_LONG(void *address, uint32 data)
*((uint8 *)address) = (data >> 24); *((uint8 *)address) = (data >> 24);
#endif /* LSB_FIRST */ #endif /* LSB_FIRST */
return; return;
} }
else *(uint32 *)address = data; else *(uint32 *)address = data;
} }
#endif /* ALIGN_LONG */ #endif /* ALIGN_LONG */
@ -327,10 +299,9 @@ static __inline__ void WRITE_LONG(void *address, uint32 data)
*lb++ = table[(*lb << 8) |(*src++ | palette)]; *lb++ = table[(*lb << 8) |(*src++ | palette)];
.. claiming the result on lb is undefined. .. claiming the result on lb is undefined.
So we manually advance lb and use constant offsets into the line buffer. So we manually advance lb and use constant offsets into the line buffer.
*/
/* added sprite collision detection: Added sprite collision detection
check if non-transparent sprite data has been previously drawn (check if non-transparent sprite data has been previously drawn)
*/ */
#define DRAW_SPRITE_TILE \ #define DRAW_SPRITE_TILE \
for(i=0; i<8; i++) \ for(i=0; i<8; i++) \
@ -340,22 +311,67 @@ static __inline__ void WRITE_LONG(void *address, uint32 data)
} }
/* Pixel creation macros, input is four bits each */ /**************************************************/
#ifndef NGC /* Pixel creation macros */
/* Input is four bits each (R,G,B), 12 bits total */
/* 8:8:8 RGB */ /* Color range depends on the S/TE mode: */
#define MAKE_PIXEL_32(r,g,b) ((r) << 20 | (g) << 12 | (b) << 4) /* */
/* normal mode : xxx0 (0-14) */
/* 5:5:5 RGB */ /* shadow mode : 0xxx (0-7) */
#define MAKE_PIXEL_15(r,g,b) ((r) << 11 | (g) << 6 | (b) << 1) /* highlight mode: 1xxx (8-15) */
/* */
/* 3:3:2 RGB */ /* with xxx0 = original 4-bits CRAM value */
#define MAKE_PIXEL_8(r,g,b) ((r) << 5 | (g) << 2 | ((b) >> 1)) /**************************************************/
#endif
/* 5:6:5 RGB */ /* 5:6:5 RGB */
#define MAKE_PIXEL_16(r,g,b) ((r) << 11 | (g) << 5 | (b)) /* This RGB format uses 5 or 6bits color */
/* 4 bits color value need to be dithered */
/* to match the whole color range: */
/* */
/* R,B (5 bits) : yyyyy (0-31) */
/* G (6 bits) : yyyyyy (0-63) */
/* */
/* normal mode : xxx0 (0-14) */
/* 0000 -> 00000 (000000) */
/* 0010 -> 00100 (001000) */
/* 0100 -> 01000 (010001) */
/* 0110 -> 01100 (011001) */
/* 1000 -> 10001 (100010) */
/* 1010 -> 10101 (101010) */
/* 1100 -> 11001 (110011) */
/* 1110 -> 11101 (111011) */
/* */
/* shadow mode : 0xxx (0-7) */
/* 0000 -> 00000 (000000) */
/* 0001 -> 00010 (000100) */
/* 0010 -> 00100 (001000) */
/* 0011 -> 00110 (001100) */
/* 0100 -> 01000 (010001) */
/* 0101 -> 01010 (010101) */
/* 0110 -> 01100 (011001) */
/* 0111 -> 01110 (011101) */
/* */
/* highlight mode: 1xxx (8-15) */
/* 1000 -> 10001 (100010) */
/* 1001 -> 10011 (100110) */
/* 1010 -> 10101 (101010) */
/* 1011 -> 10111 (101110) */
/* 1100 -> 11001 (110011) */
/* 1101 -> 11011 (110111) */
/* 1110 -> 11101 (111011) */
/* 1111 -> 11111 (111111) */
/* */
/******************************************/
#define MAKE_PIXEL_16(r,g,b) (((r) << 12) | (((r) >> 3) << 12) | ((g) << 7) | (((g) >> 2) << 5) | ((b) << 1) | ((b) >> 3) )
#ifndef NGC
/* 8:8:8 RGB */
#define MAKE_PIXEL_32(r,g,b) ((r) << 20 | (g) << 12 | (b) << 4)
/* 5:5:5 RGB */
#define MAKE_PIXEL_15(r,g,b) ((r) << 11 | (g) << 6 | (b) << 1)
/* 3:3:2 RGB */
#define MAKE_PIXEL_8(r,g,b) ((r) << 5 | (g) << 2 | ((b) >> 1))
#endif
/* Clip data */ /* Clip data */
@ -411,347 +427,6 @@ static uint8 obj_buf[0x200]; /* Object layer line buffer */
/* Sprite line buffer data */ /* Sprite line buffer data */
static uint32 object_index_count; static uint32 object_index_count;
/*
3:3:3 to 5:6:5 RGB pixel extrapolation tables
this is used to convert 3bits RGB values to 5bits (R,B) or 6bits (G) values
there is three color modes:
normal: RGB range is [0;MAX]
half: RGB range is [0;MAX/2] (shadow mode)
high: RGB range is [MAX/2;MAX] (highlight mode)
MAX is 31 (R,B) or 63 (G) for 5:6:5 pixels and 7 (R,G,B) for 3:3:3 pixels
MAX/2 is rounded to inferior value (15, 31 or 3)
the extrapolation is linear and calculated like this:
for (i=0; i<8; i++)
{
rgb565_norm[0][i] = round(((double)i * 31.0) / 7.0);
rgb565_norm[1][i] = round(((double)i * 63.0) / 7.0);
rgb565_half[0][i] = round(((double)i * 31.0) / 7.0 / 2.0);
rgb565_half[1][i] = round(((double)i * 63.0) / 7.0 / 2.0);
rgb565_high[0][i] = round(((double)i * 31.0) / 7.0 / 2.0 + 15.5);
rgb565_high[1][i] = round(((double)i * 63.0) / 7.0 / 2.0 + 31.5);
}
*/
static const uint8 rgb565_norm[2][8] =
{
{0 , 4, 9, 13, 18, 22, 27, 31},
{0 , 9, 18, 27, 36, 45, 54, 63}
};
static const uint8 rgb565_half[2][8] =
{
{0 , 2, 4, 6, 9, 11, 13, 15},
{0 , 4, 9, 13, 18, 22, 27, 31}
};
static const uint8 rgb565_high[2][8] =
{
{15, 17, 19, 21, 24, 26, 28, 31},
{31, 35, 40, 44, 49, 53, 58, 63}
};
/*--------------------------------------------------------------------------*/
/* Init, reset, shutdown routines */
/*--------------------------------------------------------------------------*/
void render_init(void)
{
int bx, ax, i;
/* Allocate and align pixel look-up tables */
if (lut_base == NULL) lut_base = malloc ((LUT_MAX * LUT_SIZE) + LUT_SIZE);
lut[0] = (uint8 *) (((uint32) lut_base + LUT_SIZE) & ~(LUT_SIZE - 1));
for (i = 1; i < LUT_MAX; i += 1) lut[i] = lut[0] + (i * LUT_SIZE);
/* Make pixel look-up table data */
for (bx = 0; bx < 0x100; bx += 1)
for (ax = 0; ax < 0x100; ax += 1)
{
uint16 index = (bx << 8) | (ax);
lut[0][index] = make_lut_bg (bx, ax);
lut[1][index] = make_lut_obj (bx, ax);
lut[2][index] = make_lut_bg_ste (bx, ax);
lut[3][index] = make_lut_obj_ste (bx, ax);
lut[4][index] = make_lut_bgobj_ste (bx, ax);
}
/* Make pixel data tables */
palette_init();
/* Set up color update function */
#ifndef NGC
switch(bitmap.depth)
{
case 8: color_update = color_update_8; break;
case 15: color_update = color_update_15; break;
case 16: color_update = color_update_16; break;
case 32: color_update = color_update_32; break;
}
#else
color_update = color_update_16;
#endif
/* Make sprite name look-up table */
make_name_lut();
}
void render_reset(void)
{
/* Clear display bitmap */
memset(bitmap.data, 0, bitmap.pitch * bitmap.height);
memset(bg_buf, 0, sizeof(bg_buf));
memset(tmp_buf, 0, sizeof(tmp_buf));
memset(nta_buf, 0, sizeof(nta_buf));
memset(ntb_buf, 0, sizeof(ntb_buf));
memset(obj_buf, 0, sizeof(obj_buf));
#ifndef NGC
memset(&pixel_8, 0, sizeof(pixel_8));
memset(&pixel_15, 0, sizeof(pixel_15));
memset(&pixel_32, 0, sizeof(pixel_32));
#endif
memset(&pixel_16, 0, sizeof(pixel_16));
window_clip();
}
void render_shutdown(void)
{
if(lut_base) free(lut_base);
}
/*--------------------------------------------------------------------------*/
/* Line render function */
/*--------------------------------------------------------------------------*/
void render_line(uint32 line, uint32 overscan)
{
uint32 width = bitmap.viewport.w;
uint32 x_offset = bitmap.viewport.x;
/* display OFF */
if (reg[0] & 0x01) return;
/* background color (blanked display or vertical borders) */
if (!(reg[1] & 0x40) || overscan)
{
width += 2 * x_offset;
memset(&tmp_buf[0x20 - x_offset], 0x40, width);
}
else
{
uint8 *lb = tmp_buf;
/* update pattern generator */
if (bg_list_index)
{
update_bg_pattern_cache(bg_list_index);
bg_list_index = 0;
}
/* double-resolution mode */
if(im2_flag)
{
uint32 odd = odd_frame;
/* render BG layers */
render_bg_im2(line, width, odd);
if (reg[12] & 8)
{
/* Shadow & Highlight */
merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], width);
memset(&obj_buf[0x20], 0, width);
if (object_index_count) render_obj_im2(line, odd, obj_buf, lut[3]);
merge(&obj_buf[0x20], &bg_buf[0x20], &lb[0x20], lut[4], width);
}
else
{
merge(&nta_buf[0x20], &ntb_buf[0x20], &lb[0x20], lut[0], width);
if (object_index_count) render_obj_im2(line, odd, lb, lut[1]);
}
}
else
{
/* render BG layers */
if(reg[11] & 4) render_bg_vs(line, width);
else render_bg(line, width);
if(reg[12] & 8)
{
/* Shadow & Highlight */
merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], width);
memset(&obj_buf[0x20], 0, width);
render_obj(line, obj_buf, lut[3]);
merge(&obj_buf[0x20], &bg_buf[0x20], &lb[0x20], lut[4], width);
}
else
{
merge(&nta_buf[0x20], &ntb_buf[0x20], &lb[0x20], lut[0], width);
render_obj(line, lb, lut[1]);
}
}
/* Mode 4 feature only (unemulated, no games rely on this) */
/*if(!(reg[1] & 0x04) && (reg[0] & 0x20)) memset(&lb[0x20], 0x40, 0x08);*/
/* borders */
if (x_offset)
{
memset(&lb[0x20 - x_offset], 0x40, x_offset);
memset(&lb[0x20 + width], 0x40, x_offset);
width += 2 * x_offset;
}
}
/* pixel color remapping */
remap_buffer(line,width);
}
void remap_buffer(uint32 line, uint32 width)
{
/* get line offset from framebuffer */
line = (line + bitmap.viewport.y) % lines_per_frame;
/* double resolution mode */
if (config.render && interlaced) line = (line * 2) + odd_frame;
/* NTSC Filter */
if (config.ntsc)
{
if (reg[12]&1) md_ntsc_blit(&md_ntsc, ( MD_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line);
else sms_ntsc_blit(&sms_ntsc, ( SMS_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line);
return;
}
#ifdef NGC
/* directly fill the RGB565 texture */
/* one tile is 32 byte = 4x4 pixels */
/* tiles are stored continuously in texture memory */
width = width >> 2;
int offset = ((width << 5) * (line >> 2)) + ((line & 3) * 8);
remap_texture(tmp_buf+0x20-bitmap.viewport.x, (uint16 *)(texturemem + offset), width);
#else
void *out =((void *)&bitmap.data[(line * bitmap.pitch)]);
switch(bitmap.depth)
{
case 8:
remap_8(tmp_buf+0x20-bitmap.viewport.x, (uint8 *)out, pixel_8, width);
break;
case 15:
remap_16(tmp_buf+0x20-bitmap.viewport.x, (uint16 *)out, pixel_15, width);
break;
case 16:
remap_16(tmp_buf+0x20-bitmap.viewport.x, (uint16 *)out, pixel_16, width);
break;
case 32:
remap_32(tmp_buf+0x20-bitmap.viewport.x, (uint32 *)out, pixel_32, width);
break;
}
#endif
}
/* Update Window Clipping (only called when registers change) */
void window_clip(void)
{
/* Window size and invert flags */
int hp = (reg[17] & 0x1f);
int hf = (reg[17] >> 7) & 1;
/* Display size */
int sw = bitmap.viewport.w >> 4;
/* Clear clipping data */
memset(&clip, 0, sizeof(clip));
/* Perform horizontal clipping; the results are applied in reverse
if the horizontal inversion flag is set */
int a = hf;
int w = hf ^ 1;
if(hp)
{
if(hp > sw)
{
/* Plane W takes up entire line */
clip[w].right = sw;
clip[w].enable = 1;
}
else
{
/* Window takes left side, Plane A takes right side */
clip[w].right = hp;
clip[a].left = hp;
clip[a].right = sw;
clip[0].enable = clip[1].enable = 1;
}
}
else
{
/* Plane A takes up entire line */
clip[a].right = sw;
clip[a].enable = 1;
}
}
/*--------------------------------------------------------------------------*/
/* Sprites Parsing function */
/*--------------------------------------------------------------------------*/
void parse_satb(uint32 line)
{
uint8 sizetab[] = {8, 16, 24, 32};
uint32 link = 0;
uint32 count, ypos, size, height;
uint32 limit = (reg[12] & 1) ? 20 : 16;
uint32 total = limit << 2;
uint16 *p = (uint16 *) &vram[satb];
uint16 *q = (uint16 *) &sat[0];
object_index_count = 0;
for(count = 0; count < total; count += 1)
{
ypos = (q[link] >> im2_flag) & 0x1FF;
size = q[link + 1] >> 8;
height = sizetab[size & 3];
if((line >= ypos) && (line < (ypos + height)))
{
/* sprite limit (max. 16 or 20 sprites displayed per line) */
if(object_index_count == limit)
{
if(vint_pending == 0) status |= 0x40;
return;
}
// using xpos from internal satb stops sprite x
// scrolling in bloodlin.bin,
// but this seems to go against the test prog
object_info[object_index_count].attr = p[link + 2];
object_info[object_index_count].xpos = p[link + 3];
object_info[object_index_count].ypos = ypos;
object_info[object_index_count].size = size;
++object_index_count;
}
link = (q[link + 1] & 0x7F) << 2;
if(link == 0) break;
}
}
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* Look-up table functions (handles priority between layers pixels) */ /* Look-up table functions (handles priority between layers pixels) */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -782,11 +457,10 @@ static void palette_init(void)
pixel_32_lut[2][i] = MAKE_PIXEL_32(r|8,g|8,b|8); pixel_32_lut[2][i] = MAKE_PIXEL_32(r|8,g|8,b|8);
#endif #endif
/* RGB 565 format: we extrapolate each 3-bit value into a 5-bit (R,B) or 6-bit (G) value pixel_16_lut[0][i] = MAKE_PIXEL_16(r,g,b);
this is needed to correctly cover full color range: [0-31] for R,B or [0-63] for G */ pixel_16_lut[1][i] = MAKE_PIXEL_16(r<<1,g<<1,b<<1);
pixel_16_lut[0][i] = MAKE_PIXEL_16(rgb565_half[0][r],rgb565_half[1][g],rgb565_half[0][b]);
pixel_16_lut[1][i] = MAKE_PIXEL_16(rgb565_norm[0][r],rgb565_norm[1][g],rgb565_norm[0][b]); pixel_16_lut[2][i] = MAKE_PIXEL_16(r|8,g|8,b|8);
pixel_16_lut[2][i] = MAKE_PIXEL_16(rgb565_high[0][r],rgb565_high[1][g],rgb565_high[0][b]);
} }
} }
@ -1849,3 +1523,298 @@ static void render_obj_im2(uint32 line, uint32 odd, uint8 *buf, uint8 *table)
spr_over = 0; spr_over = 0;
} }
/*--------------------------------------------------------------------------*/
/* Init, reset, shutdown routines */
/*--------------------------------------------------------------------------*/
void render_init(void)
{
int bx, ax, i;
/* Allocate and align pixel look-up tables */
if (lut_base == NULL) lut_base = malloc ((LUT_MAX * LUT_SIZE) + LUT_SIZE);
lut[0] = (uint8 *) (((uint32) lut_base + LUT_SIZE) & ~(LUT_SIZE - 1));
for (i = 1; i < LUT_MAX; i += 1) lut[i] = lut[0] + (i * LUT_SIZE);
/* Make pixel look-up table data */
for (bx = 0; bx < 0x100; bx += 1)
for (ax = 0; ax < 0x100; ax += 1)
{
uint16 index = (bx << 8) | (ax);
lut[0][index] = make_lut_bg (bx, ax);
lut[1][index] = make_lut_obj (bx, ax);
lut[2][index] = make_lut_bg_ste (bx, ax);
lut[3][index] = make_lut_obj_ste (bx, ax);
lut[4][index] = make_lut_bgobj_ste (bx, ax);
}
/* Make pixel data tables */
palette_init();
/* Set up color update function */
#ifndef NGC
switch(bitmap.depth)
{
case 8: color_update = color_update_8; break;
case 15: color_update = color_update_15; break;
case 16: color_update = color_update_16; break;
case 32: color_update = color_update_32; break;
}
#else
color_update = color_update_16;
#endif
/* Make sprite name look-up table */
make_name_lut();
}
void render_reset(void)
{
/* Clear display bitmap */
memset(bitmap.data, 0, bitmap.pitch * bitmap.height);
memset(bg_buf, 0, sizeof(bg_buf));
memset(tmp_buf, 0, sizeof(tmp_buf));
memset(nta_buf, 0, sizeof(nta_buf));
memset(ntb_buf, 0, sizeof(ntb_buf));
memset(obj_buf, 0, sizeof(obj_buf));
#ifndef NGC
memset(&pixel_8, 0, sizeof(pixel_8));
memset(&pixel_15, 0, sizeof(pixel_15));
memset(&pixel_32, 0, sizeof(pixel_32));
#endif
memset(&pixel_16, 0, sizeof(pixel_16));
window_clip();
}
void render_shutdown(void)
{
if(lut_base) free(lut_base);
}
/*--------------------------------------------------------------------------*/
/* Line render function */
/*--------------------------------------------------------------------------*/
void render_line(uint32 line, uint32 overscan)
{
uint32 width = bitmap.viewport.w;
uint32 x_offset = bitmap.viewport.x;
/* display OFF */
if (reg[0] & 0x01) return;
/* background color (blanked display or vertical borders) */
if (!(reg[1] & 0x40) || overscan)
{
width += 2 * x_offset;
memset(&tmp_buf[0x20 - x_offset], 0x40, width);
}
else
{
uint8 *lb = tmp_buf;
/* update pattern generator */
if (bg_list_index)
{
update_bg_pattern_cache(bg_list_index);
bg_list_index = 0;
}
/* double-resolution mode */
if(im2_flag)
{
uint32 odd = odd_frame;
/* render BG layers */
render_bg_im2(line, width, odd);
if (reg[12] & 8)
{
/* Shadow & Highlight */
merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], width);
memset(&obj_buf[0x20], 0, width);
if (object_index_count) render_obj_im2(line, odd, obj_buf, lut[3]);
merge(&obj_buf[0x20], &bg_buf[0x20], &lb[0x20], lut[4], width);
}
else
{
merge(&nta_buf[0x20], &ntb_buf[0x20], &lb[0x20], lut[0], width);
if (object_index_count) render_obj_im2(line, odd, lb, lut[1]);
}
}
else
{
/* render BG layers */
if(reg[11] & 4) render_bg_vs(line, width);
else render_bg(line, width);
if(reg[12] & 8)
{
/* Shadow & Highlight */
merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], width);
memset(&obj_buf[0x20], 0, width);
render_obj(line, obj_buf, lut[3]);
merge(&obj_buf[0x20], &bg_buf[0x20], &lb[0x20], lut[4], width);
}
else
{
merge(&nta_buf[0x20], &ntb_buf[0x20], &lb[0x20], lut[0], width);
render_obj(line, lb, lut[1]);
}
}
/* Mode 4 feature only (unemulated, no games rely on this) */
/*if(!(reg[1] & 0x04) && (reg[0] & 0x20)) memset(&lb[0x20], 0x40, 0x08);*/
/* borders */
if (x_offset)
{
memset(&lb[0x20 - x_offset], 0x40, x_offset);
memset(&lb[0x20 + width], 0x40, x_offset);
width += 2 * x_offset;
}
}
/* pixel color remapping */
remap_buffer(line,width);
}
void remap_buffer(uint32 line, uint32 width)
{
/* get line offset from framebuffer */
line = (line + bitmap.viewport.y) % lines_per_frame;
/* double resolution mode */
if (config.render && interlaced) line = (line * 2) + odd_frame;
/* NTSC Filter */
if (config.ntsc)
{
if (reg[12]&1) md_ntsc_blit(&md_ntsc, ( MD_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line);
else sms_ntsc_blit(&sms_ntsc, ( SMS_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line);
return;
}
#ifdef NGC
/* directly fill the RGB565 texture */
/* one tile is 32 byte = 4x4 pixels */
/* tiles are stored continuously in texture memory */
width = width >> 2;
int offset = ((width << 5) * (line >> 2)) + ((line & 3) * 8);
remap_texture(tmp_buf+0x20-bitmap.viewport.x, (uint16 *)(texturemem + offset), width);
#else
void *out =((void *)&bitmap.data[(line * bitmap.pitch)]);
switch(bitmap.depth)
{
case 8:
remap_8(tmp_buf+0x20-bitmap.viewport.x, (uint8 *)out, pixel_8, width);
break;
case 15:
remap_16(tmp_buf+0x20-bitmap.viewport.x, (uint16 *)out, pixel_15, width);
break;
case 16:
remap_16(tmp_buf+0x20-bitmap.viewport.x, (uint16 *)out, pixel_16, width);
break;
case 32:
remap_32(tmp_buf+0x20-bitmap.viewport.x, (uint32 *)out, pixel_32, width);
break;
}
#endif
}
/* Update Window Clipping (only called when registers change) */
void window_clip(void)
{
/* Window size and invert flags */
int hp = (reg[17] & 0x1f);
int hf = (reg[17] >> 7) & 1;
/* Display size */
int sw = bitmap.viewport.w >> 4;
/* Clear clipping data */
memset(&clip, 0, sizeof(clip));
/* Perform horizontal clipping; the results are applied in reverse
if the horizontal inversion flag is set */
int a = hf;
int w = hf ^ 1;
if(hp)
{
if(hp > sw)
{
/* Plane W takes up entire line */
clip[w].right = sw;
clip[w].enable = 1;
}
else
{
/* Window takes left side, Plane A takes right side */
clip[w].right = hp;
clip[a].left = hp;
clip[a].right = sw;
clip[0].enable = clip[1].enable = 1;
}
}
else
{
/* Plane A takes up entire line */
clip[a].right = sw;
clip[a].enable = 1;
}
}
/*--------------------------------------------------------------------------*/
/* Sprites Parsing function */
/*--------------------------------------------------------------------------*/
void parse_satb(uint32 line)
{
uint8 sizetab[] = {8, 16, 24, 32};
uint32 link = 0;
uint32 count, ypos, size, height;
uint32 limit = (reg[12] & 1) ? 20 : 16;
uint32 total = limit << 2;
uint16 *p = (uint16 *) &vram[satb];
uint16 *q = (uint16 *) &sat[0];
object_index_count = 0;
for(count = 0; count < total; count += 1)
{
ypos = (q[link] >> im2_flag) & 0x1FF;
size = q[link + 1] >> 8;
height = sizetab[size & 3];
if((line >= ypos) && (line < (ypos + height)))
{
/* sprite limit (max. 16 or 20 sprites displayed per line) */
if(object_index_count == limit)
{
if(vint_pending == 0) status |= 0x40;
return;
}
// using xpos from internal satb stops sprite x
// scrolling in bloodlin.bin,
// but this seems to go against the test prog
object_info[object_index_count].attr = p[link + 2];
object_info[object_index_count].xpos = p[link + 3];
object_info[object_index_count].ypos = ypos;
object_info[object_index_count].size = size;
++object_index_count;
}
link = (q[link + 1] & 0x7F) << 2;
if(link == 0) break;
}
}

View File

@ -410,7 +410,6 @@ void vdp_ctrl_w(unsigned int data)
*/ */
unsigned int vdp_ctrl_r(void) unsigned int vdp_ctrl_r(void)
{ {
/* update FIFO flags */ /* update FIFO flags */
fifo_update(); fifo_update();
if (fifo_write_cnt < 4) if (fifo_write_cnt < 4)