2017-06-04 18:25:21 +00:00
/******************************************************************************/
/* Mednafen Sega Saturn Emulation Module */
/******************************************************************************/
/* vdp2_render.cpp - VDP2 Rendering
* * Copyright ( C ) 2016 Mednafen Team
* *
* * This program is free software ; you can redistribute it and / or
* * modify it under the terms of the GNU General Public License
* * as published by the Free Software Foundation ; either version 2
* * of the License , or ( at your option ) any later version .
* *
* * This program is distributed in the hope that it will be useful ,
* * but WITHOUT ANY WARRANTY ; without even the implied warranty of
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* * GNU General Public License for more details .
* *
* * You should have received a copy of the GNU General Public License
* * along with this program ; if not , write to the Free Software Foundation , Inc . ,
* * 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
// TODO: 31KHz monitor mode.
// When implementing GetRegister(), remember RPRCTL and window x start and end registers can
// change outside of direct register writes
// Ignore T4-T7 in hires and 31KHz monitor mode.
# include "ss.h"
// #include <mednafen/Time.h>
# include "vdp2_common.h"
# include "vdp2_render.h"
# include <array>
# include <atomic>
# include <algorithm>
// "Array" is a bit of a misnomer, but it helps avoid confusion with memset() semantics hopefully.
static INLINE void MDFN_FastArraySet ( uint64 * const dst , const uint64 value , const size_t count )
{
# if defined(ARCH_X86) && defined(__x86_64__)
{
uint32 dummy_output0 , dummy_output1 ;
asm volatile (
" cld \n \t "
" rep stosq \n \t "
: " =D " ( dummy_output0 ) , " =c " ( dummy_output1 )
: " a " ( value ) , " D " ( dst ) , " c " ( count )
: " cc " , " memory " ) ;
}
# else
for ( uint64 * ai = dst ; MDFN_LIKELY ( ai ! = ( dst + count ) ) ; ai + + )
MDFN_ennsb < uint64 , true > ( ai , value ) ;
# endif
}
static INLINE void MDFN_FastArraySet ( uint32 * const dst , const uint32 value , const size_t count )
{
# if defined(ARCH_X86) && !defined(__x86_64__)
{
uint32 dummy_output0 , dummy_output1 ;
asm volatile (
" cld \n \t "
" rep stosl \n \t "
: " =D " ( dummy_output0 ) , " =c " ( dummy_output1 )
: " a " ( value ) , " D " ( dst ) , " c " ( count )
: " cc " , " memory " ) ;
return ;
}
# else
if ( 0 = = ( ( uintptr_t ) dst & ( sizeof ( uint64 ) - 1 ) ) & & ! ( count & 1 ) )
MDFN_FastArraySet ( ( uint64 * ) dst , value | ( ( uint64 ) value < < 32 ) , count > > 1 ) ;
else
{
for ( uint32 * ai = dst ; MDFN_LIKELY ( ai ! = ( dst + count ) ) ; ai + + )
MDFN_ennsb < uint32 , true > ( ai , value ) ;
}
# endif
}
static INLINE void MDFN_FastArraySet ( uint16 * const dst , const uint16 value , const size_t count )
{
if ( 0 = = ( ( uintptr_t ) dst & ( sizeof ( uint32 ) - 1 ) ) & & ! ( count & 1 ) )
MDFN_FastArraySet ( ( uint32 * ) dst , value | ( value < < 16 ) , count > > 1 ) ;
else
{
for ( uint16 * ai = dst ; MDFN_LIKELY ( ai ! = ( dst + count ) ) ; ai + + )
MDFN_ennsb < uint16 , true > ( ai , value ) ;
}
}
static INLINE void MDFN_FastArraySet ( uint8 * const dst , const uint16 value , const size_t count )
{
if ( 0 = = ( ( uintptr_t ) dst & ( sizeof ( uint16 ) - 1 ) ) & & ! ( count & 1 ) )
MDFN_FastArraySet ( ( uint16 * ) dst , value | ( value < < 8 ) , count > > 1 ) ;
else
{
for ( uint8 * ai = dst ; MDFN_LIKELY ( ai ! = ( dst + count ) ) ; ai + + )
* ai = value ;
}
}
namespace MDFN_IEN_SS
{
//uint8 vdp2rend_prepad_bss
static EmulateSpecStruct * espec = NULL ;
static bool PAL ;
bool CorrectAspect ;
bool ShowHOverscan ;
bool DoHBlend ;
int LineVisFirst , LineVisLast ;
static uint32 OutLineCounter ;
static bool Clock28M ;
static unsigned VisibleLines ;
static VDP2Rend_LIB LIB [ 256 ] ;
static uint16 VRAM [ 262144 ] ;
static uint16 CRAM [ 2048 ] ;
static uint8 HRes , VRes ;
static bool BorderMode ;
static uint8 InterlaceMode ;
enum { IM_NONE , IM_ILLEGAL , IM_SINGLE , IM_DOUBLE } ;
static bool CRKTE ;
static uint8 CRAM_Mode ;
enum
{
CRAM_MODE_RGB555_1024 = 0 ,
CRAM_MODE_RGB555_2048 = 1 ,
CRAM_MODE_RGB888_1024 = 2 ,
CRAM_MODE_ILLEGAL = 3
} ;
static uint8 VRAM_Mode ;
static uint8 RDBS_Mode ;
static uint8 VCPRegs [ 4 ] [ 8 ] ;
static const uint16 DummyTileNT [ 8 * 8 * 4 / sizeof ( uint16 ) ] = { 0 } ;
static uint32 UserLayerEnableMask ;
//
//
//
static uint16 BGON ;
static uint16 MZCTL ;
static uint8 MosaicVCount ;
static uint8 SFSEL ;
static uint16 SFCODE ;
static uint16 CHCTLA ;
static uint16 CHCTLB ;
static uint16 BMPNA ;
static uint8 BMPNB ;
static uint16 PNCN [ 4 ] ;
static uint16 PNCNR ;
static uint16 PLSZ ;
static uint16 MPOFN ;
static uint16 MPOFR ;
static uint8 MapRegs [ 4 ] [ 4 ] ;
static uint8 RotMapRegs [ 2 ] [ 16 ] ;
//
static uint16 XScrollI [ 4 ] , YScrollI [ 4 ] ;
static uint8 XScrollF [ 2 ] , YScrollF [ 2 ] ;
static uint16 ZMCTL ;
static uint16 SCRCTL ;
static uint32 LineScrollAddr [ 2 ] ;
static uint32 VCScrollAddr ;
static uint32 VCLast [ 2 ] ;
static uint16 XCoordInc [ 2 ] , YCoordInc [ 2 ] ;
static uint32 YCoordAccum [ 2 ] ;
static uint32 MosEff_YCoordAccum [ 2 ] ;
static uint32 CurXScrollIF [ 2 ] ;
static uint32 CurYScrollIF [ 2 ] ;
static uint16 CurXCoordInc [ 2 ] ;
static uint32 CurLSA [ 2 ] ;
static uint16 NBG23_YCounter [ 2 ] ;
static uint16 MosEff_NBG23_YCounter [ 2 ] ;
//
static uint8 RPMD ;
static uint8 KTCTL [ 2 ] ;
static uint16 OVPNR [ 2 ] ;
//
static uint32 BKTA ;
static uint32 CurBackTabAddr ;
static uint16 CurBackColor ;
static uint32 LCTA ;
static uint32 CurLCTabAddr ;
static uint16 CurLCColor ;
static uint8 LineColorEn ;
static uint16 SFPRMD ;
static uint16 CCCTL ;
static uint16 SFCCMD ;
//
static uint8 NBGPrioNum [ 4 ] ;
static uint8 RBG0PrioNum ;
static uint8 NBGCCRatio [ 4 ] ;
static uint8 RBG0CCRatio ;
static uint8 LineColorCCRatio ;
static uint8 BackCCRatio ;
//
static struct
{
uint16 XStart , XEnd ;
uint16 YStart , YEnd ;
uint32 LineWinAddr ;
bool LineWinEn ;
//
bool YMet ;
uint16 CurXStart , CurXEnd ;
uint32 CurLineWinAddr ;
} Window [ 2 ] ;
static uint8 WinControl [ 8 ] ;
enum
{
WINLAYER_NBG0 = 0 ,
WINLAYER_NBG1 = 1 ,
WINLAYER_NBG2 = 2 ,
WINLAYER_NBG3 = 3 ,
WINLAYER_RBG0 = 4 ,
WINLAYER_SPRITE = 5 ,
WINLAYER_ROTPARAM = 6 ,
WINLAYER_CC = 7 ,
} ;
static std : : array < unsigned , 5 > WinPieces ;
//
static uint8 SpriteCCCond ;
static uint8 SpriteCCNum ;
static uint8 SPCTL_Low ;
static uint16 SDCTL ;
static uint8 SpritePrioNum [ 8 ] ;
static uint8 SpriteCCRatio [ 8 ] ;
static uint8 SpriteCCLUT [ 8 ] ; // Temp optimization data
static uint8 SpriteCC3Mask ; // Temp optimization data
//
static uint8 CRAMAddrOffs_NBG [ 4 ] ;
static uint8 CRAMAddrOffs_RBG0 ;
static uint8 CRAMAddrOffs_Sprite ;
//
static uint8 ColorOffsEn ;
static uint8 ColorOffsSel ;
//enum
//{
// COLOFFS_ENSEL_NBG0 = 0,
// COLOFFS_ENSEL_NBG1 = 0,
//};
static int32 ColorOffs [ 2 ] [ 3 ] ; // [A,B] [R << 0, G << 8, B << 16]
template < bool IsRot >
struct TileFetcher
{
unsigned CRAOffs ;
bool BMSCC ;
bool BMSPR ;
unsigned BMPalNo ;
unsigned BMSize ;
unsigned PlaneSize ;
unsigned PlaneOver ;
uint16 PlaneOverChar ;
bool PNDSize ;
bool CharSize ;
bool AuxMode ;
unsigned Supp ;
//
//
//
unsigned BMOffset ;
unsigned BMWShift ;
unsigned BMWMask ;
unsigned BMHMask ;
uint32 adj_map_regs [ IsRot ? 16 : 4 ] ;
uint32 doxm , doym ;
bool nt_ok [ 4 ] ;
bool cg_ok [ 4 ] ;
// n=0...3, NBG0...3
// n=4, RBG0
// n=5, RBG1
INLINE void Start ( const unsigned n , const bool bmen , const unsigned map_offset , const uint8 * map_regs )
{
BMOffset = map_offset < < 16 ;
BMWShift = ( ( BMSize & 2 ) ? 10 : 9 ) ;
BMWMask = ( 1U < < BMWShift ) - 8 ;
BMHMask = ( BMSize & 1 ) ? 0x1FF : 0xFF ;
const unsigned psshift = ( 13 - PNDSize - ( CharSize < < 1 ) ) ;
for ( unsigned i = 0 ; i < ( IsRot ? 16 : 4 ) ; i + + )
{
adj_map_regs [ i ] = ( ( map_offset < < 6 ) + ( map_regs [ i ] & ~ PlaneSize ) ) < < psshift ;
}
if ( IsRot )
{
if ( bmen )
{
doxm = ~ ( BMWMask + 7 ) ;
doym = ~ BMHMask ;
}
else
{
doxm = ~ ( ( 1U < < ( ( 9 + ( bool ) ( PlaneSize & 0x1 ) ) + ( IsRot ? 2 : 1 ) ) ) - 1 ) ;
doym = ~ ( ( 1U < < ( ( 9 + ( bool ) ( PlaneSize & 0x2 ) ) + ( IsRot ? 2 : 1 ) ) ) - 1 ) ;
}
if ( PlaneOver = = 0 )
doxm = doym = 0 ;
else if ( PlaneOver = = 3 )
doxm = doym = ~ 511 ;
}
// Kludgeyness:
for ( unsigned bank = 0 ; bank < 4 ; bank + + )
{
const unsigned esb = bank & ( 2 | ( ( VRAM_Mode > > ( bank > > 1 ) ) & 1 ) ) ;
const uint8 rdbs = ( RDBS_Mode > > ( esb < < 1 ) ) & 0x3 ;
if ( IsRot )
{
if ( ! ( BGON & 0x20 ) | | n = = 4 )
{
nt_ok [ bank ] = ( rdbs = = RDBS_NAME ) & & ( bank < 2 | | ! ( BGON & 0x20 ) ) ;
cg_ok [ bank ] = ( rdbs = = RDBS_CHAR ) & & ( bank < 2 | | ! ( BGON & 0x20 ) ) ;
}
else
{
nt_ok [ bank ] = ( bank = = 3 ) ;
cg_ok [ bank ] = ( bank = = 2 ) ;
}
}
else
{
nt_ok [ bank ] = false ;
cg_ok [ bank ] = false ;
if ( ! ( BGON & 0x30 ) | | rdbs = = RDBS_UNUSED )
{
for ( unsigned ac = 0 ; ac < ( ( HRes & 0x6 ) ? 4 : 8 ) ; ac + + )
{
if ( VCPRegs [ esb ] [ ac ] = = ( VCP_NBG0_CG + n ) )
cg_ok [ bank ] = true ;
if ( VCPRegs [ esb ] [ ac ] = = ( VCP_NBG0_NT + n ) )
nt_ok [ bank ] = true ;
}
}
}
}
# if 1
pcco = 0 ;
spr = false ;
scc = false ;
tile_vrb = nullptr ;
cellx_xor = 0 ;
# endif
}
//
//
//
uint32 pcco ;
bool spr ;
bool scc ;
const uint16 * tile_vrb ;
uint32 cellx_xor ;
template < unsigned TA_bpp >
INLINE bool Fetch ( const bool bmen , const uint32 ix , const uint32 iy )
{
size_t cg_addr ;
uint32 palno ;
bool is_outside = false ;
if ( IsRot )
is_outside = ( ix & doxm ) | ( iy & doym ) ;
if ( bmen )
{
palno = BMPalNo ;
spr = BMSPR ;
scc = BMSCC ;
cellx_xor = ( ix & ~ 0x7 ) ;
cg_addr = ( BMOffset + ( ( ( ( ix & BMWMask ) + ( ( iy & BMHMask ) < < BMWShift ) ) * TA_bpp ) > > 4 ) ) & 0x3FFFF ;
}
else
{
bool vflip , hflip ;
uint16 charno ;
uint32 mapidx , planeidx , planeoffs , pageoffs ;
const uint16 * pnd ;
uint32 celly ;
size_t nt_addr ;
if ( IsRot )
mapidx = ( ( ix > > ( 9 + ( bool ) ( PlaneSize & 0x1 ) ) ) & 0x3 ) | ( ( iy > > ( 9 + ( bool ) ( PlaneSize & 0x2 ) - 2 ) ) & 0xC ) ;
else
mapidx = ( ( ix > > ( 9 + ( bool ) ( PlaneSize & 0x1 ) ) ) & 0x1 ) | ( ( iy > > ( 9 + ( bool ) ( PlaneSize & 0x2 ) - 1 ) ) & 0x2 ) ;
planeidx = ( ( ix > > 9 ) & PlaneSize & 0x1 ) | ( ( iy > > ( 9 - 1 ) ) & PlaneSize & 0x2 ) ;
planeoffs = planeidx < < ( 13 - PNDSize - ( CharSize < < 1 ) ) ;
pageoffs = ( ( ( ( ix > > 3 ) & 0x3F ) > > CharSize ) + ( ( ( ( iy > > 3 ) & 0x3F ) > > CharSize ) < < ( 6 - CharSize ) ) ) < < ( 1 - PNDSize ) ;
nt_addr = ( adj_map_regs [ mapidx ] + planeoffs + pageoffs ) & 0x3FFFF ;
pnd = & VRAM [ nt_addr ] ;
if ( ! nt_ok [ nt_addr > > 16 ] )
pnd = DummyTileNT ;
if ( IsRot & & is_outside & & PlaneOver = = 1 )
{
pnd = & PlaneOverChar ;
goto OverCharCase ;
}
if ( ! PNDSize )
{
uint16 tmp = pnd [ 0 ] ;
palno = tmp & 0x7F ;
vflip = ( bool ) ( tmp & 0x8000 ) ;
hflip = ( bool ) ( tmp & 0x4000 ) ;
spr = ( bool ) ( tmp & 0x2000 ) ;
scc = ( bool ) ( tmp & 0x1000 ) ;
charno = pnd [ 1 ] & 0x7FFF ;
}
else
{
OverCharCase : ;
uint16 tmp = pnd [ 0 ] ;
if ( TA_bpp > = 8 )
palno = ( ( tmp > > 12 ) & 0x7 ) < < 4 ;
else
palno = ( ( tmp > > 12 ) & 0xF ) | ( ( ( Supp > > 5 ) & 0x7 ) < < 4 ) ;
spr = ( bool ) ( Supp & 0x200 ) ;
scc = ( bool ) ( Supp & 0x100 ) ;
if ( ! AuxMode )
{
vflip = ( bool ) ( tmp & 0x800 ) ;
hflip = ( bool ) ( tmp & 0x400 ) ;
if ( CharSize )
charno = ( ( tmp & 0x3FF ) < < 2 ) + ( ( Supp & 0x1C ) < < 10 ) + ( Supp & 0x3 ) ;
else
charno = ( tmp & 0x3FF ) + ( ( Supp & 0x1F ) < < 10 ) ;
}
else
{
hflip = vflip = false ;
if ( CharSize )
charno = ( ( tmp & 0xFFF ) < < 2 ) + ( ( Supp & 0x10 ) < < 10 ) + ( Supp & 0x3 ) ;
else
charno = ( tmp & 0xFFF ) + ( ( Supp & 0x1C ) < < 10 ) ;
}
}
if ( CharSize )
{
uint32 cidx = ( ( ( ix > > 3 ) ^ hflip ) & 0x1 ) + ( ( ( iy > > 2 ) ^ ( vflip < < 1 ) ) & 0x2 ) ;
charno = ( charno + cidx * ( TA_bpp > > 2 ) ) & 0x7FFF ;
}
cellx_xor = ( ix & ~ 0x7 ) | ( hflip ? 0x7 : 0x0 ) ;
celly = ( iy & 0x7 ) ^ ( vflip ? 0x7 : 0 ) ;
cg_addr = ( ( charno < < 4 ) + ( ( celly * TA_bpp ) > > 1 ) ) & 0x3FFFF ;
}
tile_vrb = & VRAM [ cg_addr ] ;
if ( ! cg_ok [ cg_addr > > 16 ] )
{
//printf("Goop: %08zx, %d %02x, %016llx %016llx %016llx %016llx\n", cg_addr, TA_bpp, VRAM_Mode, MDFN_de64lsb(VCPRegs[0]), MDFN_de64lsb(VCPRegs[1]), MDFN_de64lsb(VCPRegs[2]), MDFN_de64lsb(VCPRegs[3]));
tile_vrb = DummyTileNT ;
}
//
//
//
pcco = ( ( palno < < 4 ) & ~ ( ( 1U < < ( TA_bpp & 0x1F ) ) - 1 ) ) + CRAOffs ;
return IsRot & & is_outside & & ( PlaneOver & 2 ) ;
}
} ;
struct RotVars
{
int32 Xsp , Ysp ; // .10
int32 Xp , Yp ; // .10
int32 dX , dY ; // .10
int32 kx , ky ; // .16
bool use_coeff ;
uint32 base_coeff ;
TileFetcher < true > tf ;
} ;
static struct
{
uint64 spr [ 704 ] ;
uint64 rbg0 [ 704 ] ;
union
{
uint64 nbg [ 4 ] [ 8 + 704 + 8 ] ;
struct
{
uint8 dummy [ sizeof ( nbg ) / 2 ] ;
uint16 vcscr [ 2 ] [ 88 + 1 + 1 ] ; // + 1 for fine x scroll != 0, + 1 for pointer shenanigans in FetchVCScroll
} ;
struct
{
uint8 rotdummy [ sizeof ( nbg ) / 4 ] ;
uint8 rotabsel [ 352 ] ; // Also used as a scratch buffer in T_DrawRBG() to handle mosaic-related junk.
RotVars rotv [ 2 ] ;
uint32 rotcoeff [ 352 ] ;
} ;
} ;
alignas ( 16 ) uint8 lc [ 704 ] ;
} LB ;
// ColorOffsEn, etc. ?...hmm, discrepancy with ColorCalcEn and LineColorEn...
enum
{
LAYER_NBG0 = 0 ,
//LAYER_RBG1 = 0,
LAYER_NBG1 = 1 ,
//LAYER_EXBG = 1,
LAYER_NBG2 = 2 ,
LAYER_NBG3 = 3 ,
LAYER_RBG0 = 4 ,
LAYER_BACK = 5 , // Line color?
LAYER_SPRITE = 6 ,
} ;
//
//
//
static uint32 ColorCache [ 2048 ] ;
static void CacheCRE ( const unsigned cri )
{
if ( CRAM_Mode & CRAM_MODE_RGB888_1024 )
{
( ColorCache + 0x000 ) [ cri > > 1 ] = ( ColorCache + 0x400 ) [ cri > > 1 ] = ( ( ( CRAM + 0x000 ) [ ( cri > > 1 ) & 0x3FF ] & 0x80FF ) < < 16 ) | ( ( CRAM + 0x400 ) [ ( cri > > 1 ) & 0x3FF ] < < 0 ) ;
}
else
{
const uint16 t = CRAM [ cri & ( ( CRAM_Mode = = CRAM_MODE_RGB555_1024 ) ? 0x3FF : 0x7FF ) ] ;
const uint32 col = ( ( t < < 3 ) & 0xF8 ) | ( ( t < < 6 ) & 0xF800 ) | ( ( t < < 9 ) & 0xF80000 ) | ( ( t < < 16 ) & 0x80000000 ) ;
if ( CRAM_Mode = = CRAM_MODE_RGB555_1024 )
( ColorCache + 0x000 ) [ cri & 0x3FF ] = ( ColorCache + 0x400 ) [ cri & 0x3FF ] = col ;
else
ColorCache [ cri ] = col ;
}
}
static void RecalcColorCache ( void )
{
if ( CRAM_Mode & CRAM_MODE_RGB888_1024 )
{
for ( unsigned i = 0 ; i < 2048 ; i + = 2 )
CacheCRE ( i ) ;
}
else
{
const unsigned count = ( CRAM_Mode = = CRAM_MODE_RGB555_2048 ) ? 2048 : 1024 ;
for ( unsigned i = 0 ; i < count ; i + + )
CacheCRE ( i ) ;
}
}
//
// Register writes seem to always be 16-bit
//
static INLINE void RegsWrite ( uint32 A , uint16 V )
{
A & = 0x1FE ;
switch ( A )
{
default :
break ;
case 0x00 :
//DisplayOn = (V >> 15) & 0x1;
BorderMode = ( V > > 8 ) & 0x1 ;
InterlaceMode = ( V > > 6 ) & 0x3 ;
VRes = ( V > > 4 ) & 0x3 ;
HRes = ( V > > 0 ) & 0x7 ;
break ;
case 0x02 :
//ExLatchEnable = (V >> 9) & 0x1;
//ExSyncEnable = (V >> 8) & 0x1;
//DispAreaSelect = (V >> 1) & 0x1;
//ExBGEnable = (V >> 0) & 0x1;
break ;
case 0x0E :
{
const unsigned old_CRAM_Mode = CRAM_Mode ;
CRKTE = ( V > > 15 ) & 0x1 ;
CRAM_Mode = ( V > > 12 ) & 0x3 ; ;
VRAM_Mode = ( V > > 8 ) & 0x3 ;
RDBS_Mode = V & 0xFF ;
if ( old_CRAM_Mode ! = CRAM_Mode )
RecalcColorCache ( ) ;
}
break ;
//
case 0x10 :
case 0x12 :
case 0x14 :
case 0x16 :
case 0x18 :
case 0x1A :
case 0x1C :
case 0x1E :
{
uint8 * const b = & VCPRegs [ ( A > > 2 ) & 3 ] [ ( A & 0x2 ) < < 1 ] ;
b [ 0 ] = ( V > > 12 ) & 0xF ;
b [ 1 ] = ( V > > 8 ) & 0xF ;
b [ 2 ] = ( V > > 4 ) & 0xF ;
b [ 3 ] = ( V > > 0 ) & 0xF ;
}
break ;
//
case 0x20 :
BGON = V & 0x1F3F ;
break ;
case 0x22 :
MZCTL = V & 0xFF1F ;
break ;
case 0x24 :
SFSEL = V & 0x1F ;
break ;
case 0x26 :
SFCODE = V ;
break ;
case 0x28 :
CHCTLA = V & 0x3F7F ;
break ;
case 0x2A :
CHCTLB = V & 0x7733 ;
break ;
case 0x2C :
BMPNA = V & 0x3737 ;
break ;
case 0x2E :
BMPNB = V & 0x37 ;
break ;
//
case 0x30 :
case 0x32 :
case 0x34 :
case 0x36 :
PNCN [ ( A & 0x6 ) > > 1 ] = V & 0xC3FF ;
break ;
case 0x38 :
PNCNR = V & 0xC3FF ;
break ;
//
case 0x3A :
PLSZ = V ; // Plane size
break ;
case 0x3C :
MPOFN = V & 0x7777 ; // Map offset NBG
break ;
case 0x3E :
MPOFR = V & 0x0077 ; // Map offset RBG
break ;
//
case 0x40 :
case 0x42 :
case 0x44 :
case 0x46 :
case 0x48 :
case 0x4A :
case 0x4C :
case 0x4E :
MapRegs [ ( A & 0xC ) > > 2 ] [ ( A & 0x2 ) + 0 ] = ( V > > 0 ) & 0x3F ;
MapRegs [ ( A & 0xC ) > > 2 ] [ ( A & 0x2 ) + 1 ] = ( V > > 8 ) & 0x3F ;
break ;
case 0x50 : case 0x52 : case 0x54 : case 0x56 : case 0x58 : case 0x5A : case 0x5C : case 0x5E :
case 0x60 : case 0x62 : case 0x64 : case 0x66 : case 0x68 : case 0x6A : case 0x6C : case 0x6E :
RotMapRegs [ ( bool ) ( A & 0x20 ) ] [ ( A & 0xE ) + 0 ] = ( V > > 0 ) & 0x3F ;
RotMapRegs [ ( bool ) ( A & 0x20 ) ] [ ( A & 0xE ) + 1 ] = ( V > > 8 ) & 0x3F ;
break ;
//
case 0x70 :
case 0x80 :
XScrollI [ A > > 7 ] = V & 0x7FF ;
break ;
case 0x72 :
case 0x82 :
XScrollF [ A > > 7 ] = ( V > > 8 ) & 0xFF ;
break ;
case 0x74 :
case 0x84 :
YScrollI [ A > > 7 ] = V & 0x7FF ;
break ;
case 0x76 :
case 0x86 :
YScrollF [ A > > 7 ] = ( V > > 8 ) & 0xFF ;
break ;
case 0x78 :
case 0x88 :
XCoordInc [ A > > 7 ] = ( XCoordInc [ A > > 7 ] & 0xFF ) | ( ( V & 0x7 ) < < 8 ) ;
break ;
case 0x7A :
case 0x8A :
XCoordInc [ A > > 7 ] = ( XCoordInc [ A > > 7 ] & 0x700 ) | ( ( V > > 8 ) & 0xFF ) ;
break ;
case 0x7C :
case 0x8C :
YCoordInc [ A > > 7 ] = ( YCoordInc [ A > > 7 ] & 0xFF ) | ( ( V & 0x7 ) < < 8 ) ;
break ;
case 0x7E :
case 0x8E :
YCoordInc [ A > > 7 ] = ( YCoordInc [ A > > 7 ] & 0x700 ) | ( ( V > > 8 ) & 0xFF ) ;
break ;
case 0x90 :
case 0x94 :
XScrollI [ 2 + ( bool ) ( A & 0x4 ) ] = V & 0x7FF ;
break ;
case 0x92 :
case 0x96 :
{
const unsigned which = ( bool ) ( A & 0x4 ) ;
NBG23_YCounter [ which ] = YScrollI [ 2 + which ] = V & 0x7FF ;
}
break ;
case 0x98 :
ZMCTL = V & 0x0303 ;
break ;
case 0x9A :
SCRCTL = V & 0x3F3F ;
break ;
case 0x9C :
VCScrollAddr = ( VCScrollAddr & 0xFFFF ) | ( ( V & 0x7 ) < < 16 ) ;
break ;
case 0x9E :
VCScrollAddr = ( VCScrollAddr & 0x70000 ) | ( V & 0xFFFE ) ;
break ;
case 0xA0 :
LineScrollAddr [ 0 ] = ( LineScrollAddr [ 0 ] & 0xFFFF ) | ( ( V & 0x7 ) < < 16 ) ;
break ;
case 0xA2 :
LineScrollAddr [ 0 ] = ( LineScrollAddr [ 0 ] & 0x70000 ) | ( V & 0xFFFE ) ;
break ;
case 0xA4 :
LineScrollAddr [ 1 ] = ( LineScrollAddr [ 1 ] & 0xFFFF ) | ( ( V & 0x7 ) < < 16 ) ;
break ;
case 0xA6 :
LineScrollAddr [ 1 ] = ( LineScrollAddr [ 1 ] & 0x70000 ) | ( V & 0xFFFE ) ;
break ;
//
case 0xA8 :
LCTA = ( LCTA & 0xFFFF ) | ( ( V & 0x8007 ) < < 16 ) ;
break ;
case 0xAA :
LCTA = ( LCTA & ~ 0xFFFF ) | V ;
break ;
case 0xAC :
BKTA = ( BKTA & 0xFFFF ) | ( ( V & 0x8007 ) < < 16 ) ;
break ;
case 0xAE :
BKTA = ( BKTA & ~ 0xFFFF ) | V ;
break ;
//
case 0xB0 :
RPMD = V & 0x3 ;
break ;
case 0xB4 :
KTCTL [ 0 ] = ( V > > 0 ) & 0x1F ;
KTCTL [ 1 ] = ( V > > 8 ) & 0x1F ;
break ;
case 0xB8 :
OVPNR [ 0 ] = V ;
break ;
case 0xBA :
OVPNR [ 1 ] = V ;
break ;
//
case 0xC0 : Window [ 0 ] . XStart = V & 0x3FF ; break ;
case 0xC2 : Window [ 0 ] . YStart = V & 0x1FF ; break ;
case 0xC4 : Window [ 0 ] . XEnd = V & 0x3FF ; break ;
case 0xC6 : Window [ 0 ] . YEnd = V & 0x1FF ; break ;
case 0xC8 : Window [ 1 ] . XStart = V & 0x3FF ; break ;
case 0xCA : Window [ 1 ] . YStart = V & 0x1FF ; break ;
case 0xCC : Window [ 1 ] . XEnd = V & 0x3FF ; break ;
case 0xCE : Window [ 1 ] . YEnd = V & 0x1FF ; break ;
case 0xD0 :
case 0xD2 :
case 0xD4 :
WinControl [ ( A & 0x6 ) + 0 ] = ( V > > 0 ) & 0xBF ;
WinControl [ ( A & 0x6 ) + 1 ] = ( V > > 8 ) & 0xBF ;
break ;
case 0xD6 :
WinControl [ ( A & 0x6 ) + 0 ] = ( V > > 0 ) & 0x8F ; // Rot
WinControl [ ( A & 0x6 ) + 1 ] = ( V > > 8 ) & 0xBF ; // CC
break ;
case 0xD8 :
case 0xDC :
{
const unsigned w = ( A & 0x4 ) > > 2 ;
Window [ w ] . LineWinEn = ( bool ) ( V & 0x8000 ) ;
Window [ w ] . LineWinAddr = ( Window [ w ] . LineWinAddr & 0xFFFF ) | ( ( V & 0x7 ) < < 16 ) ;
}
break ;
case 0xDA :
case 0xDE :
{
const unsigned w = ( A & 0x4 ) > > 2 ;
Window [ w ] . LineWinAddr = ( Window [ w ] . LineWinAddr & 0x70000 ) | ( V & 0xFFFE ) ;
}
break ;
//
case 0xE0 :
SpriteCCCond = ( V > > 12 ) & 0x3 ;
SpriteCCNum = ( V > > 8 ) & 0x7 ;
SPCTL_Low = V & 0x3F ;
break ;
case 0xE2 :
SDCTL = V & 0x13F ;
break ;
case 0xE4 :
CRAMAddrOffs_NBG [ 0 ] = ( V > > 0 ) & 0x7 ;
CRAMAddrOffs_NBG [ 1 ] = ( V > > 4 ) & 0x7 ;
CRAMAddrOffs_NBG [ 2 ] = ( V > > 8 ) & 0x7 ;
CRAMAddrOffs_NBG [ 3 ] = ( V > > 12 ) & 0x7 ;
break ;
case 0xE6 :
CRAMAddrOffs_RBG0 = ( V > > 0 ) & 0x7 ;
CRAMAddrOffs_Sprite = ( V > > 4 ) & 0x7 ;
break ;
case 0xE8 :
LineColorEn = V & 0x3F ;
break ;
case 0xEA :
SFPRMD = V & 0x3FF ;
break ;
case 0xEC :
CCCTL = V & 0xF77F ;
break ;
case 0xEE :
SFCCMD = V & 0x3FF ;
break ;
case 0xF0 :
case 0xF2 :
case 0xF4 :
case 0xF6 :
SpritePrioNum [ ( A & 0x6 ) + 0 ] = ( ( V > > 0 ) & 0x7 ) ;
SpritePrioNum [ ( A & 0x6 ) + 1 ] = ( ( V > > 8 ) & 0x7 ) ;
break ;
case 0xF8 :
NBGPrioNum [ 0 ] = ( V > > 0 ) & 0x7 ;
NBGPrioNum [ 1 ] = ( V > > 8 ) & 0x7 ;
break ;
case 0xFA :
NBGPrioNum [ 2 ] = ( V > > 0 ) & 0x7 ;
NBGPrioNum [ 3 ] = ( V > > 8 ) & 0x7 ;
break ;
case 0xFC :
RBG0PrioNum = ( V > > 0 ) & 0x7 ;
break ;
case 0x100 :
case 0x102 :
case 0x104 :
case 0x106 :
SpriteCCRatio [ ( A & 0x6 ) + 0 ] = ( V > > 0 ) & 0x1F ;
SpriteCCRatio [ ( A & 0x6 ) + 1 ] = ( V > > 8 ) & 0x1F ;
break ;
case 0x108 :
case 0x10A :
NBGCCRatio [ ( A & 0x2 ) + 0 ] = ( V > > 0 ) & 0x1F ;
NBGCCRatio [ ( A & 0x2 ) + 1 ] = ( V > > 8 ) & 0x1F ;
break ;
case 0x10C :
RBG0CCRatio = V & 0x1F ;
break ;
case 0x10E :
LineColorCCRatio = ( V > > 0 ) & 0x1F ;
BackCCRatio = ( V > > 8 ) & 0x1F ;
break ;
case 0x110 :
ColorOffsEn = V & 0x7F ;
break ;
case 0x112 :
ColorOffsSel = V & 0x7F ;
break ;
case 0x114 : // A Red
case 0x116 : // A Green
case 0x118 : // A Blue
case 0x11A : // B Red
case 0x11C : // B Green
case 0x11E : // B Blue
{
const unsigned ab = ( A > = 0x11A ) ;
const unsigned wcc = ( ( A - 0x114 ) > > 1 ) % 3 ;
ColorOffs [ ab ] [ wcc ] = ( uint32 ) sign_x_to_s32 ( 9 , V ) < < ( wcc < < 3 ) ;
}
break ;
}
}
template < typename T >
static INLINE void MemW ( uint32 A , const uint16 DB )
{
A & = 0x1FFFFF ;
//
// VRAM
//
if ( A < 0x100000 )
{
const size_t vri = ( A & 0x7FFFF ) > > 1 ;
const unsigned mask = ( sizeof ( T ) = = 2 ) ? 0xFFFF : ( 0xFF00 > > ( ( A & 1 ) < < 3 ) ) ;
VRAM [ vri ] = ( VRAM [ vri ] & ~ mask ) | ( DB & mask ) ;
return ;
}
//
// CRAM
//
if ( A < 0x180000 )
{
const unsigned cri = ( A & 0xFFF ) > > 1 ;
switch ( CRAM_Mode )
{
case CRAM_MODE_RGB555_1024 :
( CRAM + 0x000 ) [ cri & 0x3FF ] = DB ;
( CRAM + 0x400 ) [ cri & 0x3FF ] = DB ;
CacheCRE ( cri ) ;
break ;
case CRAM_MODE_RGB555_2048 :
CRAM [ cri ] = DB ;
CacheCRE ( cri ) ;
break ;
case CRAM_MODE_RGB888_1024 :
case CRAM_MODE_ILLEGAL :
default :
CRAM [ ( ( cri > > 1 ) & 0x3FF ) | ( ( cri & 1 ) < < 10 ) ] = DB ;
CacheCRE ( cri ) ;
break ;
}
return ;
}
//
// Registers
//
if ( A < 0x1C0000 )
{
RegsWrite ( A , DB ) ;
return ;
}
}
static void Reset ( bool powering_up )
{
if ( powering_up )
{
memset ( VRAM , 0 , sizeof ( VRAM ) ) ;
memset ( CRAM , 0 , sizeof ( CRAM ) ) ;
}
//
//
CRKTE = false ;
CRAM_Mode = 0 ;
VRAM_Mode = 0 ;
RDBS_Mode = 0 ;
HRes = 0 ;
VRes = 0 ;
BorderMode = false ;
InterlaceMode = 0 ;
//
memset ( VCPRegs , 0 , sizeof ( VCPRegs ) ) ;
//
BGON = 0 ;
MZCTL = 0 ;
MosaicVCount = 0 ;
SFSEL = 0 ;
SFCODE = 0 ;
CHCTLA = 0 ;
CHCTLB = 0 ;
BMPNA = 0 ;
BMPNB = 0 ;
for ( unsigned n = 0 ; n < 4 ; n + + )
PNCN [ n ] = 0 ;
PNCNR = 0 ;
PLSZ = 0 ;
MPOFN = 0 ;
MPOFR = 0 ;
for ( unsigned n = 0 ; n < 4 ; n + + )
{
for ( unsigned i = 0 ; i < 4 ; i + + )
MapRegs [ n ] [ i ] = 0 ;
}
for ( unsigned rn = 0 ; rn < 2 ; rn + + )
{
for ( unsigned i = 0 ; i < 16 ; i + + )
RotMapRegs [ rn ] [ i ] = 0 ;
}
//
for ( unsigned n = 0 ; n < 4 ; n + + )
{
XScrollI [ n ] = 0 ;
YScrollI [ n ] = 0 ;
if ( n < 2 )
{
XScrollF [ n ] = 0 ;
YScrollF [ n ] = 0 ;
XCoordInc [ n ] = 0 ;
YCoordInc [ n ] = 0 ;
YCoordAccum [ n ] = 0 ;
MosEff_YCoordAccum [ n ] = 0 ;
}
else
{
NBG23_YCounter [ n & 1 ] = 0 ;
MosEff_NBG23_YCounter [ n & 1 ] = 0 ;
}
}
ZMCTL = 0 ;
SCRCTL = 0 ;
LineScrollAddr [ 0 ] = 0 ;
LineScrollAddr [ 1 ] = 0 ;
VCScrollAddr = 0 ;
VCLast [ 0 ] = VCLast [ 1 ] = 0 ;
for ( unsigned n = 0 ; n < 2 ; n + + )
{
CurXScrollIF [ n ] = 0 ;
CurYScrollIF [ n ] = 0 ;
CurLSA [ n ] = 0 ;
CurXCoordInc [ n ] = 0 ;
}
for ( unsigned n = 0 ; n < 4 ; n + + )
NBGPrioNum [ n ] = 0 ;
RBG0PrioNum = 0 ;
for ( unsigned n = 0 ; n < 4 ; n + + )
NBGCCRatio [ n ] = 0 ;
RBG0CCRatio = 0 ;
LineColorCCRatio = 0 ;
BackCCRatio = 0 ;
for ( unsigned w = 0 ; w < 2 ; w + + )
{
Window [ w ] . XStart = 0 ;
Window [ w ] . XEnd = 0 ;
Window [ w ] . YStart = 0 ;
Window [ w ] . YEnd = 0 ;
Window [ w ] . LineWinAddr = 0 ;
Window [ w ] . LineWinEn = false ;
Window [ w ] . YMet = false ;
Window [ w ] . CurXStart = 0 ;
Window [ w ] . CurXEnd = 0 ;
Window [ w ] . CurLineWinAddr = 0 ;
}
for ( unsigned i = 0 ; i < 8 ; i + + )
WinControl [ i ] = 0 ;
//
RPMD = 0 ;
for ( unsigned i = 0 ; i < 2 ; i + + )
{
KTCTL [ i ] = 0 ;
OVPNR [ i ] = 0 ;
}
//
BKTA = 0 ;
CurBackTabAddr = 0 ;
CurBackColor = 0 ;
LCTA = 0 ;
CurLCTabAddr = 0 ;
CurLCColor = 0 ;
LineColorEn = 0 ;
SFPRMD = 0 ;
SFCCMD = 0 ;
CCCTL = 0 ;
//
SpriteCCCond = 0 ;
SpriteCCNum = 0 ;
SPCTL_Low = 0 ;
SDCTL = 0 ;
//
for ( auto & spn : SpritePrioNum )
spn = 0 ;
//
for ( auto & scr : SpriteCCRatio )
scr = 0 ;
//
for ( auto & ao : CRAMAddrOffs_NBG )
ao = 0 ;
CRAMAddrOffs_RBG0 = 0 ;
CRAMAddrOffs_Sprite = 0 ;
//
ColorOffsEn = 0 ;
ColorOffsSel = 0 ;
for ( auto & co : ColorOffs )
for ( auto & coe : co )
coe = 0 ;
}
// Prio(3 bits), color calc(1 bit), layer num(3 bits), 1 bit for palette/rgb format, 1 bit for line color enable, 1 bit for color offs enable, 1 bit for color offs select
// 1 bit for line color screen enable?, 1 bit allow sprite shadow, 1 bit do sprite shadow
// Prio, color calc, layer num
enum
{
PIX_ISRGB_SHIFT = 0 , // original format, 0 = paletted, 1 = RGB
PIX_LCE_SHIFT = 1 , // Line color enable
PIX_COE_SHIFT = 2 , // Color offs enable
PIX_COSEL_SHIFT = 3 , // Color offset select(which color offset registers to use)
PIX_CCE_SHIFT = 4 , // Color calc enable
//
// Sprite shadow nonsense
// Keep these in this order at these bit positions
PIX_SHADEN_SHIFT = 5 , //
PIX_DOSHAD_SHIFT = 6 ,
PIX_SELFSHAD_SHIFT = 7 ,
PIX_SHADHALVTEST8_VAL = 0x60 ,
//
//
//
//
// 8 ... 15
PIX_PRIO_TEST_SHIFT = 8 ,
PIX_PRIO_SHIFT = PIX_PRIO_TEST_SHIFT + 3 ,
//
PIX_GRAD_SHIFT = 16 ,
PIX_LAYER_CCE_SHIFT = 17 , // For extended color calculation
// 24...31
PIX_CCRATIO_SHIFT = 24 ,
// 32 ... 55
PIX_RGB_SHIFT = 32 ,
//
PIX_SWBIT_SHIFT = 56 ,
// Reminder that highest bit can be == 1 when RGB data is pulled from ColorCache
//SPECIAL_CCALC_SHIFT = 63
} ;
static INLINE void GetCWV ( const uint8 ctrl , const bool * const xmet , bool * cwv )
{
const bool logic = ( ctrl > > 7 ) & 1 ; // 0 = OR, 1 = AND
const bool w_enable [ 2 ] = { ( bool ) ( ctrl & 0x02 ) , ( bool ) ( ctrl & 0x08 ) } ;
const bool w_area [ 2 ] = { ( bool ) ( ctrl & 0x01 ) , ( bool ) ( ctrl & 0x04 ) } ;
const bool sw_enable = ctrl & 0x20 ;
const bool sw_area = ctrl & 0x10 ;
for ( unsigned swinput = 0 ; swinput < 2 ; swinput + + )
{
bool wval [ 2 ] ;
bool swval ;
wval [ 0 ] = ( w_enable [ 0 ] ? ( ( xmet [ 0 ] & Window [ 0 ] . YMet ) ^ w_area [ 0 ] ) : logic ) ;
wval [ 1 ] = ( w_enable [ 1 ] ? ( ( xmet [ 1 ] & Window [ 1 ] . YMet ) ^ w_area [ 1 ] ) : logic ) ;
swval = sw_enable ? ( swinput ^ sw_area ) : logic ;
if ( logic )
cwv [ swinput ] = wval [ 0 ] & wval [ 1 ] & swval ;
else
cwv [ swinput ] = wval [ 0 ] | wval [ 1 ] | swval ;
}
}
static void GetWinRotAB ( void )
{
unsigned x = 0 ;
for ( unsigned piece = 0 ; piece < WinPieces . size ( ) ; piece + + )
{
bool xmet [ 2 ] ;
xmet [ 0 ] = ( ( x > = Window [ 0 ] . CurXStart ) & ( x < = Window [ 0 ] . CurXEnd ) ) ;
xmet [ 1 ] = ( ( x > = Window [ 1 ] . CurXStart ) & ( x < = Window [ 1 ] . CurXEnd ) ) ;
//
//
//
bool cwv [ 2 ] ;
GetCWV ( WinControl [ WINLAYER_ROTPARAM ] , xmet , cwv ) ;
if ( HRes & 0x2 )
{
for ( ; MDFN_LIKELY ( x < WinPieces [ piece ] ) ; x + = 2 )
LB . rotabsel [ x > > 1 ] = cwv [ ( LB . spr [ x ] > > PIX_SWBIT_SHIFT ) & 1 ] ;
}
else
{
for ( ; MDFN_LIKELY ( x < WinPieces [ piece ] ) ; x + + )
LB . rotabsel [ x ] = cwv [ ( LB . spr [ x ] > > PIX_SWBIT_SHIFT ) & 1 ] ;
}
}
}
static void ApplyWin ( const unsigned wlayer , uint64 * buf )
{
unsigned x = 0 ;
//printf("%d %d %d %d %d --- %d %d\n", WinPieces[0], WinPieces[1], WinPieces[2], WinPieces[3], WinPieces[4], Window[0].CurXStart, Window[0].CurXEnd);
for ( unsigned piece = 0 ; piece < WinPieces . size ( ) ; piece + + )
{
bool xmet [ 2 ] ;
xmet [ 0 ] = ( ( x > = Window [ 0 ] . CurXStart ) & ( x < = Window [ 0 ] . CurXEnd ) ) ;
xmet [ 1 ] = ( ( x > = Window [ 1 ] . CurXStart ) & ( x < = Window [ 1 ] . CurXEnd ) ) ;
//
//
//
bool cwv [ 2 ] ;
bool cc_cwv [ 2 ] ;
GetCWV ( WinControl [ wlayer ] , xmet , cwv ) ;
GetCWV ( WinControl [ WINLAYER_CC ] , xmet , cc_cwv ) ;
if ( ! ( ( cwv [ 0 ] ^ cwv [ 1 ] ) | ( cc_cwv [ 0 ] ^ cc_cwv [ 1 ] ) ) ) // Fast path(no sprite window, or sprite window wouldn't have an effect in this piece).
{
if ( cwv [ 0 ] )
{
for ( ; MDFN_LIKELY ( x < WinPieces [ piece ] ) ; x + + )
buf [ x ] & = ~ ( uint64 ) 0xFFFFFFFF ;
}
else if ( cc_cwv [ 0 ] )
{
for ( ; MDFN_LIKELY ( x < WinPieces [ piece ] ) ; x + + )
buf [ x ] & = ~ ( uint64 ) ( 1U < < PIX_CCE_SHIFT ) ;
}
x = WinPieces [ piece ] ;
}
else
{
uint64 masks [ 2 ] ;
for ( unsigned i = 0 ; i < 2 ; i + + )
{
uint64 m = ~ ( uint64 ) 0 ;
if ( cwv [ i ] )
m = ~ ( uint64 ) 0xFFFFFFFF ;
if ( cc_cwv [ i ] )
m & = ~ ( uint64 ) ( 1U < < PIX_CCE_SHIFT ) ;
masks [ i ] = m ;
}
for ( ; MDFN_LIKELY ( x < WinPieces [ piece ] ) ; x + + )
{
buf [ x ] & = masks [ ( LB . spr [ x ] > > PIX_SWBIT_SHIFT ) & 1 ] ;
}
}
}
}
# pragma GCC push_options
# pragma GCC optimize("no-unroll-loops,no-peel-loops,no-crossjumping")
static NO_INLINE void ApplyHMosaic ( const unsigned layer , uint64 * buf , const unsigned w )
{
if ( ! ( MZCTL & ( 1U < < layer ) ) )
return ;
const unsigned moz_horiz_param = ( ( MZCTL > > 8 ) & 0xF ) ;
const unsigned moz_wmax = w - moz_horiz_param ;
unsigned x = 0 ;
switch ( moz_horiz_param )
{
case 0x0 : x = moz_wmax ; break ;
case 0x1 : for ( ; x < moz_wmax ; x + = 0x2 ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; } break ;
case 0x2 : for ( ; x < moz_wmax ; x + = 0x3 ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; } break ;
case 0x3 : for ( ; x < moz_wmax ; x + = 0x4 ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; } break ;
case 0x4 : for ( ; x < moz_wmax ; x + = 0x5 ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; } break ;
case 0x5 : for ( ; x < moz_wmax ; x + = 0x6 ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; } break ;
case 0x6 : for ( ; x < moz_wmax ; x + = 0x7 ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; buf [ x + 6 ] = b ; } break ;
case 0x7 : for ( ; x < moz_wmax ; x + = 0x8 ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; buf [ x + 6 ] = b ; buf [ x + 7 ] = b ; } break ;
case 0x8 : for ( ; x < moz_wmax ; x + = 0x9 ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; buf [ x + 6 ] = b ; buf [ x + 7 ] = b ; buf [ x + 8 ] = b ; } break ;
case 0x9 : for ( ; x < moz_wmax ; x + = 0xA ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; buf [ x + 6 ] = b ; buf [ x + 7 ] = b ; buf [ x + 8 ] = b ; buf [ x + 9 ] = b ; } break ;
case 0xA : for ( ; x < moz_wmax ; x + = 0xB ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; buf [ x + 6 ] = b ; buf [ x + 7 ] = b ; buf [ x + 8 ] = b ; buf [ x + 9 ] = b ; buf [ x + 10 ] = b ; } break ;
case 0xB : for ( ; x < moz_wmax ; x + = 0xC ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; buf [ x + 6 ] = b ; buf [ x + 7 ] = b ; buf [ x + 8 ] = b ; buf [ x + 9 ] = b ; buf [ x + 10 ] = b ; buf [ x + 11 ] = b ; } break ;
case 0xC : for ( ; x < moz_wmax ; x + = 0xD ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; buf [ x + 6 ] = b ; buf [ x + 7 ] = b ; buf [ x + 8 ] = b ; buf [ x + 9 ] = b ; buf [ x + 10 ] = b ; buf [ x + 11 ] = b ; buf [ x + 12 ] = b ; } break ;
case 0xD : for ( ; x < moz_wmax ; x + = 0xE ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; buf [ x + 6 ] = b ; buf [ x + 7 ] = b ; buf [ x + 8 ] = b ; buf [ x + 9 ] = b ; buf [ x + 10 ] = b ; buf [ x + 11 ] = b ; buf [ x + 12 ] = b ; buf [ x + 13 ] = b ; } break ;
case 0xE : for ( ; x < moz_wmax ; x + = 0xF ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; buf [ x + 6 ] = b ; buf [ x + 7 ] = b ; buf [ x + 8 ] = b ; buf [ x + 9 ] = b ; buf [ x + 10 ] = b ; buf [ x + 11 ] = b ; buf [ x + 12 ] = b ; buf [ x + 13 ] = b ; buf [ x + 14 ] = b ; } break ;
case 0xF : for ( ; x < moz_wmax ; x + = 0x10 ) { auto b = buf [ x ] ; buf [ x + 1 ] = b ; buf [ x + 2 ] = b ; buf [ x + 3 ] = b ; buf [ x + 4 ] = b ; buf [ x + 5 ] = b ; buf [ x + 6 ] = b ; buf [ x + 7 ] = b ; buf [ x + 8 ] = b ; buf [ x + 9 ] = b ; buf [ x + 10 ] = b ; buf [ x + 11 ] = b ; buf [ x + 12 ] = b ; buf [ x + 13 ] = b ; buf [ x + 14 ] = b ; buf [ x + 15 ] = b ; } break ;
}
assert ( x < = w ) ;
for ( auto b = buf [ x ] ; x < w ; x + + )
buf [ x ] = b ;
}
# pragma GCC pop_options
//
// NBG0(HRES=0x1):
// Cycle 0: OK
// Cycle 1: OK
//
// Cycle 2:
// [Entry 0] [Entry 0] [Entry 1] [Entry 2]
// Cycle 3 ... 7:
// [Entry 44] [Entry 44] [Entry 0] [Entry 1]
//
static void FetchVCScroll ( const unsigned w )
{
const bool vcon [ 2 ] = { ( bool ) ( SCRCTL & BGON & ! ( MZCTL & 0x1 ) ) , ( bool ) ( ( SCRCTL > > 8 ) & ( BGON > > 1 ) & ! ( MZCTL & 0x2 ) & 0x1 ) } ;
const unsigned max_cyc = ( HRes & 0x6 ) ? 4 : 8 ;
const unsigned tc = ( w > > 3 ) + 1 ;
uint32 tmp [ 2 ] = { VCLast [ 0 ] , VCLast [ 1 ] } ;
uint32 vcaddr = VCScrollAddr & 0x3FFFE ;
uint32 base [ 2 ] ;
unsigned inc [ 8 ] ;
uint8 VRMVCPCache [ 4 ] [ 8 ] ;
for ( unsigned bank = 0 ; bank < 4 ; bank + + )
{
//unsigned brm[4];
//brm[bank] = bank & (2 | ((VRAM_Mode >> (bank >> 1)) & 1));
const unsigned esb = bank & ( 2 | ( ( VRAM_Mode > > ( bank > > 1 ) ) & 1 ) ) ;
memcpy ( VRMVCPCache [ bank ] , VCPRegs [ esb ] , 8 ) ;
}
for ( unsigned n = 0 ; n < 2 ; n + + )
base [ n ] = CurYScrollIF [ n ] + YCoordAccum [ n ] ;
for ( unsigned cyc = 0 ; cyc < max_cyc ; cyc + + )
{
unsigned do_inc = 0 ;
for ( unsigned bank = 0 ; bank < 4 ; bank + + )
{
const unsigned act = VRMVCPCache [ bank ] [ cyc ] ;
do_inc | = vcon [ 0 ] & ( act = = VCP_NBG0_VCS ) ;
do_inc | = vcon [ 1 ] & ( act = = VCP_NBG1_VCS ) ;
}
inc [ cyc ] = do_inc < < 1 ;
}
for ( unsigned tile = 0 ; MDFN_LIKELY ( tile < tc ) ; tile + + )
{
for ( unsigned cyc = 0 ; cyc < max_cyc ; cyc + + )
{
const unsigned act = VRMVCPCache [ vcaddr > > 16 ] [ cyc ] ;
// NBG0
if ( vcon [ 0 ] )
{
if ( cyc = = 3 )
LB . vcscr [ 0 ] [ tile ] = ( ( base [ 0 ] + tmp [ 0 ] ) > > 8 ) ;
if ( cyc = = 3 )
tmp [ 0 ] = VCLast [ 0 ] ;
if ( act = = VCP_NBG0_VCS )
{
VCLast [ 0 ] = ( VRAM [ vcaddr + 0 ] < < 8 ) | ( VRAM [ vcaddr + 1 ] > > 8 ) ;
if ( cyc < = ( 1 + ! tile ) )
tmp [ 0 ] = VCLast [ 0 ] ;
}
}
// NBG1
if ( vcon [ 1 ] )
{
if ( cyc = = 4 )
LB . vcscr [ 1 ] [ tile ] = ( ( base [ 1 ] + tmp [ 1 ] ) > > 8 ) ;
if ( cyc = = 4 )
tmp [ 1 ] = VCLast [ 1 ] ;
if ( act = = VCP_NBG1_VCS )
{
VCLast [ 1 ] = ( VRAM [ vcaddr + 0 ] < < 8 ) | ( VRAM [ vcaddr + 1 ] > > 8 ) ;
if ( cyc < = 2 ) //(2 + !tile)) // TODO: Check
tmp [ 1 ] = VCLast [ 1 ] ;
}
}
vcaddr = ( vcaddr + inc [ cyc ] ) & 0x3FFFE ;
}
}
}
template < unsigned TA_PrioMode , unsigned TA_CCMode >
static INLINE void MakeSFCodeLUT ( const unsigned layer , int16 * const sfcode_lut )
{
const uint8 code = SFCODE > > ( ( ( SFSEL > > layer ) & 1 ) < < 3 ) ;
for ( unsigned i = 0 ; i < 8 ; i + + )
{
uint16 tmp = 0xFFFF ;
if ( ! ( ( code > > i ) & 1 ) )
{
if ( TA_PrioMode & 2 )
tmp & = ~ ( 1U < < PIX_PRIO_SHIFT ) ;
if ( TA_CCMode = = 2 )
tmp & = ~ ( 1U < < PIX_CCE_SHIFT ) ;
}
sfcode_lut [ i ] = tmp ;
}
}
static INLINE uint32 rgb15_to_rgb24 ( uint16 src )
{
return ( ( ( ( src < < 3 ) & 0xF8 ) | ( ( src < < 6 ) & 0xF800 ) | ( ( src < < 9 ) & 0xF80000 ) | ( ( src < < 16 ) & 0x80000000 ) ) ) ; ;
}
template < bool TA_bmen , unsigned TA_bpp , bool TA_isrgb , bool TA_igntp , unsigned TA_PrioMode , unsigned TA_CCMode , typename T >
static INLINE uint64 MakeNBGRBGPix ( T & tf , const uint32 pix_base_or , const int16 * sfcode_lut , const uint32 ix , const uint32 iy )
{
uint32 cellx = ( ix ^ tf . cellx_xor ) ;
const uint16 * vrb = & tf . tile_vrb [ ( ( cellx * TA_bpp ) > > 4 ) ] ;
//
//
//
uint32 pbor = pix_base_or ;
uint32 rgb24 ;
bool opaque ;
if ( TA_CCMode = = 1 | | ( TA_CCMode = = 2 & & ! TA_isrgb ) )
pbor | = ( tf . scc < < PIX_CCE_SHIFT ) ;
if ( TA_PrioMode = = 1 | | ( TA_PrioMode = = 2 & & ! TA_isrgb ) )
pbor | = ( tf . spr < < PIX_PRIO_SHIFT ) ;
if ( TA_isrgb )
{
if ( TA_bpp = = 32 )
{
uint32 tmp = ( vrb [ 0 ] < < 16 ) | vrb [ 1 ] ;
rgb24 = tmp & 0xFFFFFF ;
opaque = ( bool ) ( tmp & 0x80000000 ) ;
}
else
{
uint32 tmp = vrb [ 0 ] ;
rgb24 = rgb15_to_rgb24 ( tmp & 0x7FFF ) ;
opaque = ( bool ) ( tmp & 0x8000 ) ;
}
if ( TA_CCMode = = 3 )
pbor | = ( 1 < < PIX_CCE_SHIFT ) ;
}
else
{
uint32 dcc ;
uint32 tmp = vrb [ 0 ] ; //charno ^ (charno << 8); //vrb[0];
if ( TA_bpp = = 16 )
dcc = tmp & 0x7FF ;
else if ( TA_bpp = = 8 )
dcc = ( tmp > > ( ( ( cellx & 1 ) ^ 1 ) < < 3 ) ) & 0xFF ;
else
dcc = ( tmp > > ( ( ( cellx & 3 ) ^ 3 ) < < 2 ) ) & 0x0F ;
opaque = ( bool ) dcc ;
rgb24 = ColorCache [ ( tf . pcco + dcc ) & 2047 ] ;
if ( TA_CCMode = = 3 )
pbor | = ( ( int32 ) rgb24 > > 31 ) & ( 1 < < PIX_CCE_SHIFT ) ;
//
if ( TA_PrioMode = = 2 | | TA_CCMode = = 2 )
pbor & = * ( const int16 * ) ( ( const uint8 * ) sfcode_lut + ( dcc & 0xE ) ) ;
}
if ( ! TA_igntp & & ! opaque )
pbor = 0 ;
return pbor | ( ( uint64 ) rgb24 < < PIX_RGB_SHIFT ) ;
}
template < bool TA_bmen , unsigned TA_bpp , bool TA_isrgb , bool TA_igntp , unsigned TA_PrioMode , unsigned TA_CCMode >
static void T_DrawNBG ( const unsigned n , uint64 * bgbuf , const unsigned w , const uint32 pix_base_or )
{
assert ( n < 2 ) ;
//
//
const bool VCSEn = ( ( SCRCTL > > ( n < < 3 ) ) & 0x1 ) & & ! ( MZCTL & ( 1U < < n ) ) ;
//
TileFetcher < false > tf ;
uint32 xcinc ;
uint32 xc ;
uint32 iy ;
int16 sfcode_lut [ 8 ] ;
tf . CRAOffs = CRAMAddrOffs_NBG [ n ] < < 8 ;
//
tf . BMSCC = ( ( BMPNA > > ( 4 + ( n < < 3 ) ) ) & 1 ) ;
tf . BMSPR = ( ( BMPNA > > ( 5 + ( n < < 3 ) ) ) & 1 ) ;
tf . BMPalNo = ( ( BMPNA > > ( 0 + ( n < < 3 ) ) ) & 0x7 ) < < 4 ;
tf . BMSize = ( ( CHCTLA > > ( 2 + ( n < < 3 ) ) ) & 0x3 ) ;
//
tf . PlaneSize = ( PLSZ > > ( n < < 1 ) ) & 0x3 ;
tf . PNDSize = ( PNCN [ n ] > > 15 ) & 1 ; // 0 = 2 words, 1 = 1 word
tf . CharSize = ( ( CHCTLA > > ( 0 + ( n < < 3 ) ) ) & 1 ) ;
tf . AuxMode = ( PNCN [ n ] > > 14 ) & 1 ;
tf . Supp = ( PNCN [ n ] & 0x3FF ) ; // Supplement bits when PNDSize == 1
//
tf . Start ( n , TA_bmen , ( MPOFN > > ( n < < 2 ) ) & 0x7 , MapRegs [ n ] ) ;
MakeSFCodeLUT < TA_PrioMode , TA_CCMode > ( n , sfcode_lut ) ;
xc = CurXScrollIF [ n ] ;
iy = ( CurYScrollIF [ n ] + MosEff_YCoordAccum [ n ] ) > > 8 ;
xcinc = CurXCoordInc [ n ] ;
//if(line == 64)
// printf("Mega %d: planesize=0x%1x charsize=%d pndsize=%d(auxmode=%d,supp=0x%04x) bpp=%d/%d ccmode=0x%04x SFSEL=0x%04x SFCODE=0x%04x SFCCMD=0x%04x\n", n, PlaneSize, CharSize, PNDSize, AuxMode, Supp, TA_bpp, TA_isrgb, TA_CCMode, SFSEL, SFCODE, SFCCMD);
//printf("Mega %d %02x %d --- %04x %04x -- %04x --- lsa=0x%06x vcsa=0x%06x --- imode=0x%01x\n", TA_bpp, BMSize, w, xcinc, ycinc, SCRCTL, LineScrollAddr[n], VCScrollAddr, InterlaceMode);
// Map: 2x2 planes
// Plane: 1x1, 2x1, or 2x2 pages
// Page: 64x64 cells
// Character: 1x1, 2x2 cells
// Cell: 8x8 dots
uint32 prev_ix = ~ 0U ;
if ( ( ( ZMCTL > > ( n < < 3 ) ) & 0x3 ) & & VCSEn )
{
for ( unsigned i = 0 ; MDFN_LIKELY ( i < w ) ; i + + )
{
const uint32 ix = xc > > 8 ;
iy = LB . vcscr [ n ] [ i > > 3 ] ;
tf . Fetch < TA_bpp > ( TA_bmen , ix , iy ) ;
//
//
//
bgbuf [ i ] = MakeNBGRBGPix < TA_bmen , TA_bpp , TA_isrgb , TA_igntp , TA_PrioMode , TA_CCMode > ( tf , pix_base_or , sfcode_lut , ix , iy ) ;
xc + = xcinc ;
}
}
else
{
for ( unsigned i = 0 ; MDFN_LIKELY ( i < w ) ; i + + )
{
const uint32 ix = xc > > 8 ;
if ( ( ix > > 3 ) ! = prev_ix )
{
prev_ix = ix > > 3 ;
//
if ( VCSEn )
iy = LB . vcscr [ n ] [ ( i + 7 ) > > 3 ] ;
tf . Fetch < TA_bpp > ( TA_bmen , ix , iy ) ;
}
//
//
//
bgbuf [ i ] = MakeNBGRBGPix < TA_bmen , TA_bpp , TA_isrgb , TA_igntp , TA_PrioMode , TA_CCMode > ( tf , pix_base_or , sfcode_lut , ix , iy ) ;
xc + = xcinc ;
}
}
}
static void ( * DrawNBG [ 2 /*bitmap enable*/ ] [ 5 /*col mode*/ ] [ 2 /*igntp*/ ] [ 3 /*priomode*/ ] [ 4 /*ccmode*/ ] ) ( const unsigned n , uint64 * bgbuf , const unsigned w , const uint32 pix_base_or ) =
{
{
{ { { T_DrawNBG < 0 , 4 , 0 , 0 , 0 , 0 > , T_DrawNBG < 0 , 4 , 0 , 0 , 0 , 1 > , T_DrawNBG < 0 , 4 , 0 , 0 , 0 , 2 > , T_DrawNBG < 0 , 4 , 0 , 0 , 0 , 3 > , } , { T_DrawNBG < 0 , 4 , 0 , 0 , 1 , 0 > , T_DrawNBG < 0 , 4 , 0 , 0 , 1 , 1 > , T_DrawNBG < 0 , 4 , 0 , 0 , 1 , 2 > , T_DrawNBG < 0 , 4 , 0 , 0 , 1 , 3 > , } , { T_DrawNBG < 0 , 4 , 0 , 0 , 2 , 0 > , T_DrawNBG < 0 , 4 , 0 , 0 , 2 , 1 > , T_DrawNBG < 0 , 4 , 0 , 0 , 2 , 2 > , T_DrawNBG < 0 , 4 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawNBG < 0 , 4 , 0 , 1 , 0 , 0 > , T_DrawNBG < 0 , 4 , 0 , 1 , 0 , 1 > , T_DrawNBG < 0 , 4 , 0 , 1 , 0 , 2 > , T_DrawNBG < 0 , 4 , 0 , 1 , 0 , 3 > , } , { T_DrawNBG < 0 , 4 , 0 , 1 , 1 , 0 > , T_DrawNBG < 0 , 4 , 0 , 1 , 1 , 1 > , T_DrawNBG < 0 , 4 , 0 , 1 , 1 , 2 > , T_DrawNBG < 0 , 4 , 0 , 1 , 1 , 3 > , } , { T_DrawNBG < 0 , 4 , 0 , 1 , 2 , 0 > , T_DrawNBG < 0 , 4 , 0 , 1 , 2 , 1 > , T_DrawNBG < 0 , 4 , 0 , 1 , 2 , 2 > , T_DrawNBG < 0 , 4 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawNBG < 0 , 8 , 0 , 0 , 0 , 0 > , T_DrawNBG < 0 , 8 , 0 , 0 , 0 , 1 > , T_DrawNBG < 0 , 8 , 0 , 0 , 0 , 2 > , T_DrawNBG < 0 , 8 , 0 , 0 , 0 , 3 > , } , { T_DrawNBG < 0 , 8 , 0 , 0 , 1 , 0 > , T_DrawNBG < 0 , 8 , 0 , 0 , 1 , 1 > , T_DrawNBG < 0 , 8 , 0 , 0 , 1 , 2 > , T_DrawNBG < 0 , 8 , 0 , 0 , 1 , 3 > , } , { T_DrawNBG < 0 , 8 , 0 , 0 , 2 , 0 > , T_DrawNBG < 0 , 8 , 0 , 0 , 2 , 1 > , T_DrawNBG < 0 , 8 , 0 , 0 , 2 , 2 > , T_DrawNBG < 0 , 8 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawNBG < 0 , 8 , 0 , 1 , 0 , 0 > , T_DrawNBG < 0 , 8 , 0 , 1 , 0 , 1 > , T_DrawNBG < 0 , 8 , 0 , 1 , 0 , 2 > , T_DrawNBG < 0 , 8 , 0 , 1 , 0 , 3 > , } , { T_DrawNBG < 0 , 8 , 0 , 1 , 1 , 0 > , T_DrawNBG < 0 , 8 , 0 , 1 , 1 , 1 > , T_DrawNBG < 0 , 8 , 0 , 1 , 1 , 2 > , T_DrawNBG < 0 , 8 , 0 , 1 , 1 , 3 > , } , { T_DrawNBG < 0 , 8 , 0 , 1 , 2 , 0 > , T_DrawNBG < 0 , 8 , 0 , 1 , 2 , 1 > , T_DrawNBG < 0 , 8 , 0 , 1 , 2 , 2 > , T_DrawNBG < 0 , 8 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawNBG < 0 , 16 , 0 , 0 , 0 , 0 > , T_DrawNBG < 0 , 16 , 0 , 0 , 0 , 1 > , T_DrawNBG < 0 , 16 , 0 , 0 , 0 , 2 > , T_DrawNBG < 0 , 16 , 0 , 0 , 0 , 3 > , } , { T_DrawNBG < 0 , 16 , 0 , 0 , 1 , 0 > , T_DrawNBG < 0 , 16 , 0 , 0 , 1 , 1 > , T_DrawNBG < 0 , 16 , 0 , 0 , 1 , 2 > , T_DrawNBG < 0 , 16 , 0 , 0 , 1 , 3 > , } , { T_DrawNBG < 0 , 16 , 0 , 0 , 2 , 0 > , T_DrawNBG < 0 , 16 , 0 , 0 , 2 , 1 > , T_DrawNBG < 0 , 16 , 0 , 0 , 2 , 2 > , T_DrawNBG < 0 , 16 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawNBG < 0 , 16 , 0 , 1 , 0 , 0 > , T_DrawNBG < 0 , 16 , 0 , 1 , 0 , 1 > , T_DrawNBG < 0 , 16 , 0 , 1 , 0 , 2 > , T_DrawNBG < 0 , 16 , 0 , 1 , 0 , 3 > , } , { T_DrawNBG < 0 , 16 , 0 , 1 , 1 , 0 > , T_DrawNBG < 0 , 16 , 0 , 1 , 1 , 1 > , T_DrawNBG < 0 , 16 , 0 , 1 , 1 , 2 > , T_DrawNBG < 0 , 16 , 0 , 1 , 1 , 3 > , } , { T_DrawNBG < 0 , 16 , 0 , 1 , 2 , 0 > , T_DrawNBG < 0 , 16 , 0 , 1 , 2 , 1 > , T_DrawNBG < 0 , 16 , 0 , 1 , 2 , 2 > , T_DrawNBG < 0 , 16 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawNBG < 0 , 16 , 1 , 0 , 0 , 0 > , T_DrawNBG < 0 , 16 , 1 , 0 , 0 , 1 > , T_DrawNBG < 0 , 16 , 1 , 0 , 0 , 2 > , T_DrawNBG < 0 , 16 , 1 , 0 , 0 , 3 > , } , { T_DrawNBG < 0 , 16 , 1 , 0 , 1 , 0 > , T_DrawNBG < 0 , 16 , 1 , 0 , 1 , 1 > , T_DrawNBG < 0 , 16 , 1 , 0 , 1 , 2 > , T_DrawNBG < 0 , 16 , 1 , 0 , 1 , 3 > , } , { T_DrawNBG < 0 , 16 , 1 , 0 , 2 , 0 > , T_DrawNBG < 0 , 16 , 1 , 0 , 2 , 1 > , T_DrawNBG < 0 , 16 , 1 , 0 , 2 , 2 > , T_DrawNBG < 0 , 16 , 1 , 0 , 2 , 3 > , } , } , { { T_DrawNBG < 0 , 16 , 1 , 1 , 0 , 0 > , T_DrawNBG < 0 , 16 , 1 , 1 , 0 , 1 > , T_DrawNBG < 0 , 16 , 1 , 1 , 0 , 2 > , T_DrawNBG < 0 , 16 , 1 , 1 , 0 , 3 > , } , { T_DrawNBG < 0 , 16 , 1 , 1 , 1 , 0 > , T_DrawNBG < 0 , 16 , 1 , 1 , 1 , 1 > , T_DrawNBG < 0 , 16 , 1 , 1 , 1 , 2 > , T_DrawNBG < 0 , 16 , 1 , 1 , 1 , 3 > , } , { T_DrawNBG < 0 , 16 , 1 , 1 , 2 , 0 > , T_DrawNBG < 0 , 16 , 1 , 1 , 2 , 1 > , T_DrawNBG < 0 , 16 , 1 , 1 , 2 , 2 > , T_DrawNBG < 0 , 16 , 1 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawNBG < 0 , 32 , 1 , 0 , 0 , 0 > , T_DrawNBG < 0 , 32 , 1 , 0 , 0 , 1 > , T_DrawNBG < 0 , 32 , 1 , 0 , 0 , 2 > , T_DrawNBG < 0 , 32 , 1 , 0 , 0 , 3 > , } , { T_DrawNBG < 0 , 32 , 1 , 0 , 1 , 0 > , T_DrawNBG < 0 , 32 , 1 , 0 , 1 , 1 > , T_DrawNBG < 0 , 32 , 1 , 0 , 1 , 2 > , T_DrawNBG < 0 , 32 , 1 , 0 , 1 , 3 > , } , { T_DrawNBG < 0 , 32 , 1 , 0 , 2 , 0 > , T_DrawNBG < 0 , 32 , 1 , 0 , 2 , 1 > , T_DrawNBG < 0 , 32 , 1 , 0 , 2 , 2 > , T_DrawNBG < 0 , 32 , 1 , 0 , 2 , 3 > , } , } , { { T_DrawNBG < 0 , 32 , 1 , 1 , 0 , 0 > , T_DrawNBG < 0 , 32 , 1 , 1 , 0 , 1 > , T_DrawNBG < 0 , 32 , 1 , 1 , 0 , 2 > , T_DrawNBG < 0 , 32 , 1 , 1 , 0 , 3 > , } , { T_DrawNBG < 0 , 32 , 1 , 1 , 1 , 0 > , T_DrawNBG < 0 , 32 , 1 , 1 , 1 , 1 > , T_DrawNBG < 0 , 32 , 1 , 1 , 1 , 2 > , T_DrawNBG < 0 , 32 , 1 , 1 , 1 , 3 > , } , { T_DrawNBG < 0 , 32 , 1 , 1 , 2 , 0 > , T_DrawNBG < 0 , 32 , 1 , 1 , 2 , 1 > , T_DrawNBG < 0 , 32 , 1 , 1 , 2 , 2 > , T_DrawNBG < 0 , 32 , 1 , 1 , 2 , 3 > , } , } , } ,
} ,
{
{ { { T_DrawNBG < 1 , 4 , 0 , 0 , 0 , 0 > , T_DrawNBG < 1 , 4 , 0 , 0 , 0 , 1 > , T_DrawNBG < 1 , 4 , 0 , 0 , 0 , 2 > , T_DrawNBG < 1 , 4 , 0 , 0 , 0 , 3 > , } , { T_DrawNBG < 1 , 4 , 0 , 0 , 1 , 0 > , T_DrawNBG < 1 , 4 , 0 , 0 , 1 , 1 > , T_DrawNBG < 1 , 4 , 0 , 0 , 1 , 2 > , T_DrawNBG < 1 , 4 , 0 , 0 , 1 , 3 > , } , { T_DrawNBG < 1 , 4 , 0 , 0 , 2 , 0 > , T_DrawNBG < 1 , 4 , 0 , 0 , 2 , 1 > , T_DrawNBG < 1 , 4 , 0 , 0 , 2 , 2 > , T_DrawNBG < 1 , 4 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawNBG < 1 , 4 , 0 , 1 , 0 , 0 > , T_DrawNBG < 1 , 4 , 0 , 1 , 0 , 1 > , T_DrawNBG < 1 , 4 , 0 , 1 , 0 , 2 > , T_DrawNBG < 1 , 4 , 0 , 1 , 0 , 3 > , } , { T_DrawNBG < 1 , 4 , 0 , 1 , 1 , 0 > , T_DrawNBG < 1 , 4 , 0 , 1 , 1 , 1 > , T_DrawNBG < 1 , 4 , 0 , 1 , 1 , 2 > , T_DrawNBG < 1 , 4 , 0 , 1 , 1 , 3 > , } , { T_DrawNBG < 1 , 4 , 0 , 1 , 2 , 0 > , T_DrawNBG < 1 , 4 , 0 , 1 , 2 , 1 > , T_DrawNBG < 1 , 4 , 0 , 1 , 2 , 2 > , T_DrawNBG < 1 , 4 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawNBG < 1 , 8 , 0 , 0 , 0 , 0 > , T_DrawNBG < 1 , 8 , 0 , 0 , 0 , 1 > , T_DrawNBG < 1 , 8 , 0 , 0 , 0 , 2 > , T_DrawNBG < 1 , 8 , 0 , 0 , 0 , 3 > , } , { T_DrawNBG < 1 , 8 , 0 , 0 , 1 , 0 > , T_DrawNBG < 1 , 8 , 0 , 0 , 1 , 1 > , T_DrawNBG < 1 , 8 , 0 , 0 , 1 , 2 > , T_DrawNBG < 1 , 8 , 0 , 0 , 1 , 3 > , } , { T_DrawNBG < 1 , 8 , 0 , 0 , 2 , 0 > , T_DrawNBG < 1 , 8 , 0 , 0 , 2 , 1 > , T_DrawNBG < 1 , 8 , 0 , 0 , 2 , 2 > , T_DrawNBG < 1 , 8 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawNBG < 1 , 8 , 0 , 1 , 0 , 0 > , T_DrawNBG < 1 , 8 , 0 , 1 , 0 , 1 > , T_DrawNBG < 1 , 8 , 0 , 1 , 0 , 2 > , T_DrawNBG < 1 , 8 , 0 , 1 , 0 , 3 > , } , { T_DrawNBG < 1 , 8 , 0 , 1 , 1 , 0 > , T_DrawNBG < 1 , 8 , 0 , 1 , 1 , 1 > , T_DrawNBG < 1 , 8 , 0 , 1 , 1 , 2 > , T_DrawNBG < 1 , 8 , 0 , 1 , 1 , 3 > , } , { T_DrawNBG < 1 , 8 , 0 , 1 , 2 , 0 > , T_DrawNBG < 1 , 8 , 0 , 1 , 2 , 1 > , T_DrawNBG < 1 , 8 , 0 , 1 , 2 , 2 > , T_DrawNBG < 1 , 8 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawNBG < 1 , 16 , 0 , 0 , 0 , 0 > , T_DrawNBG < 1 , 16 , 0 , 0 , 0 , 1 > , T_DrawNBG < 1 , 16 , 0 , 0 , 0 , 2 > , T_DrawNBG < 1 , 16 , 0 , 0 , 0 , 3 > , } , { T_DrawNBG < 1 , 16 , 0 , 0 , 1 , 0 > , T_DrawNBG < 1 , 16 , 0 , 0 , 1 , 1 > , T_DrawNBG < 1 , 16 , 0 , 0 , 1 , 2 > , T_DrawNBG < 1 , 16 , 0 , 0 , 1 , 3 > , } , { T_DrawNBG < 1 , 16 , 0 , 0 , 2 , 0 > , T_DrawNBG < 1 , 16 , 0 , 0 , 2 , 1 > , T_DrawNBG < 1 , 16 , 0 , 0 , 2 , 2 > , T_DrawNBG < 1 , 16 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawNBG < 1 , 16 , 0 , 1 , 0 , 0 > , T_DrawNBG < 1 , 16 , 0 , 1 , 0 , 1 > , T_DrawNBG < 1 , 16 , 0 , 1 , 0 , 2 > , T_DrawNBG < 1 , 16 , 0 , 1 , 0 , 3 > , } , { T_DrawNBG < 1 , 16 , 0 , 1 , 1 , 0 > , T_DrawNBG < 1 , 16 , 0 , 1 , 1 , 1 > , T_DrawNBG < 1 , 16 , 0 , 1 , 1 , 2 > , T_DrawNBG < 1 , 16 , 0 , 1 , 1 , 3 > , } , { T_DrawNBG < 1 , 16 , 0 , 1 , 2 , 0 > , T_DrawNBG < 1 , 16 , 0 , 1 , 2 , 1 > , T_DrawNBG < 1 , 16 , 0 , 1 , 2 , 2 > , T_DrawNBG < 1 , 16 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawNBG < 1 , 16 , 1 , 0 , 0 , 0 > , T_DrawNBG < 1 , 16 , 1 , 0 , 0 , 1 > , T_DrawNBG < 1 , 16 , 1 , 0 , 0 , 2 > , T_DrawNBG < 1 , 16 , 1 , 0 , 0 , 3 > , } , { T_DrawNBG < 1 , 16 , 1 , 0 , 1 , 0 > , T_DrawNBG < 1 , 16 , 1 , 0 , 1 , 1 > , T_DrawNBG < 1 , 16 , 1 , 0 , 1 , 2 > , T_DrawNBG < 1 , 16 , 1 , 0 , 1 , 3 > , } , { T_DrawNBG < 1 , 16 , 1 , 0 , 2 , 0 > , T_DrawNBG < 1 , 16 , 1 , 0 , 2 , 1 > , T_DrawNBG < 1 , 16 , 1 , 0 , 2 , 2 > , T_DrawNBG < 1 , 16 , 1 , 0 , 2 , 3 > , } , } , { { T_DrawNBG < 1 , 16 , 1 , 1 , 0 , 0 > , T_DrawNBG < 1 , 16 , 1 , 1 , 0 , 1 > , T_DrawNBG < 1 , 16 , 1 , 1 , 0 , 2 > , T_DrawNBG < 1 , 16 , 1 , 1 , 0 , 3 > , } , { T_DrawNBG < 1 , 16 , 1 , 1 , 1 , 0 > , T_DrawNBG < 1 , 16 , 1 , 1 , 1 , 1 > , T_DrawNBG < 1 , 16 , 1 , 1 , 1 , 2 > , T_DrawNBG < 1 , 16 , 1 , 1 , 1 , 3 > , } , { T_DrawNBG < 1 , 16 , 1 , 1 , 2 , 0 > , T_DrawNBG < 1 , 16 , 1 , 1 , 2 , 1 > , T_DrawNBG < 1 , 16 , 1 , 1 , 2 , 2 > , T_DrawNBG < 1 , 16 , 1 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawNBG < 1 , 32 , 1 , 0 , 0 , 0 > , T_DrawNBG < 1 , 32 , 1 , 0 , 0 , 1 > , T_DrawNBG < 1 , 32 , 1 , 0 , 0 , 2 > , T_DrawNBG < 1 , 32 , 1 , 0 , 0 , 3 > , } , { T_DrawNBG < 1 , 32 , 1 , 0 , 1 , 0 > , T_DrawNBG < 1 , 32 , 1 , 0 , 1 , 1 > , T_DrawNBG < 1 , 32 , 1 , 0 , 1 , 2 > , T_DrawNBG < 1 , 32 , 1 , 0 , 1 , 3 > , } , { T_DrawNBG < 1 , 32 , 1 , 0 , 2 , 0 > , T_DrawNBG < 1 , 32 , 1 , 0 , 2 , 1 > , T_DrawNBG < 1 , 32 , 1 , 0 , 2 , 2 > , T_DrawNBG < 1 , 32 , 1 , 0 , 2 , 3 > , } , } , { { T_DrawNBG < 1 , 32 , 1 , 1 , 0 , 0 > , T_DrawNBG < 1 , 32 , 1 , 1 , 0 , 1 > , T_DrawNBG < 1 , 32 , 1 , 1 , 0 , 2 > , T_DrawNBG < 1 , 32 , 1 , 1 , 0 , 3 > , } , { T_DrawNBG < 1 , 32 , 1 , 1 , 1 , 0 > , T_DrawNBG < 1 , 32 , 1 , 1 , 1 , 1 > , T_DrawNBG < 1 , 32 , 1 , 1 , 1 , 2 > , T_DrawNBG < 1 , 32 , 1 , 1 , 1 , 3 > , } , { T_DrawNBG < 1 , 32 , 1 , 1 , 2 , 0 > , T_DrawNBG < 1 , 32 , 1 , 1 , 2 , 1 > , T_DrawNBG < 1 , 32 , 1 , 1 , 2 , 2 > , T_DrawNBG < 1 , 32 , 1 , 1 , 2 , 3 > , } , } , } ,
}
} ;
template < bool TA_igntp , unsigned TA_PrioMode , unsigned TA_CCMode >
static INLINE uint64 MakeNBG23Pix ( uint32 dcc , uint32 pbor , const int16 * sfcode_lut , uint32 colcacheoffs )
{
uint32 rgb24 ;
rgb24 = ColorCache [ ( colcacheoffs + dcc ) & 2047 ] ;
if ( TA_CCMode = = 3 )
pbor | = ( ( int32 ) rgb24 > > 31 ) & ( 1 < < PIX_CCE_SHIFT ) ;
if ( TA_PrioMode = = 2 | | TA_CCMode = = 2 )
pbor & = * ( const int16 * ) ( ( const uint8 * ) sfcode_lut + ( dcc & 0xE ) ) ;
if ( ! TA_igntp & & ! dcc )
pbor = 0 ;
return pbor + ( ( uint64 ) rgb24 < < PIX_RGB_SHIFT ) ;
}
//
// CCMode will be forced to 0 in the effective instantiation if corresponding NBG CCE bit in CCCTL is 0.
//
template < unsigned TA_bpp , bool TA_igntp , unsigned TA_PrioMode , unsigned TA_CCMode >
static void T_DrawNBG23 ( const unsigned n , uint64 * bgbuf , const unsigned w , const uint32 pix_base_or )
{
assert ( n > = 2 ) ;
TileFetcher < false > tf ;
int16 sfcode_lut [ 8 ] ;
unsigned tc = 1 + ( w > > 3 ) ;
const unsigned xscr = XScrollI [ n ] ;
const unsigned yscr = MosEff_NBG23_YCounter [ n & 1 ] ;
unsigned tx ;
tf . CRAOffs = CRAMAddrOffs_NBG [ n ] < < 8 ;
//
tf . PlaneSize = ( PLSZ > > ( n < < 1 ) ) & 0x3 ;
tf . PNDSize = ( PNCN [ n ] > > 15 ) & 1 ; // 0 = 2 words, 1 = 1 word
tf . CharSize = ( ( CHCTLB > > ( 0 + ( ( n & 1 ) < < 2 ) ) ) & 1 ) ;
tf . AuxMode = ( PNCN [ n ] > > 14 ) & 1 ;
tf . Supp = ( PNCN [ n ] & 0x3FF ) ; // Supplement bits when PNDSize == 1
//
tf . Start ( n , false , ( MPOFN > > ( n < < 2 ) ) & 0x7 , MapRegs [ n ] ) ;
MakeSFCodeLUT < TA_PrioMode , TA_CCMode > ( n , sfcode_lut ) ;
bgbuf - = xscr & 0x7 ;
tx = xscr > > 3 ;
//if(TA_bpp == 4 && n == 3)
// printf("Goop: %d %d %02x, %016llx %016llx %016llx %016llx\n", n, TA_bpp, VRAM_Mode, MDFN_de64lsb(VCPRegs[0]), MDFN_de64lsb(VCPRegs[1]), MDFN_de64lsb(VCPRegs[2]), MDFN_de64lsb(VCPRegs[3]));
// Kludge for Akumajou Dracula X
if ( MDFN_UNLIKELY ( TA_bpp = = 4 & & n = = 3 & & VRAM_Mode = = 0x2 & & MDFN_de64lsb ( VCPRegs [ 0 ] ) = = 0x0f0f070406060505ULL & & MDFN_de64lsb ( VCPRegs [ 2 ] ) = = 0x0f0f03000f0f0201ULL & & MDFN_de64lsb ( VCPRegs [ 3 ] ) = = 0x0f0f0f0f0f0f0f0fULL ) )
{
for ( unsigned i = 0 ; i < 8 ; i + + )
* bgbuf + + = 0 ;
tc - - ;
}
while ( MDFN_LIKELY ( tc - - ) )
{
uint32 pbor = pix_base_or ;
tf . Fetch < TA_bpp > ( false , tx < < 3 , yscr ) ;
if ( TA_CCMode = = 1 | | TA_CCMode = = 2 )
pbor | = ( tf . scc < < PIX_CCE_SHIFT ) ;
if ( TA_PrioMode = = 1 | | TA_PrioMode = = 2 )
pbor | = ( tf . spr < < PIX_PRIO_SHIFT ) ;
//
//
auto * const mbp = MakeNBG23Pix < TA_igntp , TA_PrioMode , TA_CCMode > ;
if ( TA_bpp = = 8 )
{
if ( tf . cellx_xor & 0x7 )
{
bgbuf [ 7 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 0 ] > > 8 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 6 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 0 ] > > 0 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 5 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 1 ] > > 8 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 4 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 1 ] > > 0 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 3 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 2 ] > > 8 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 2 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 2 ] > > 0 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 1 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 3 ] > > 8 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 0 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 3 ] > > 0 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
}
else
{
bgbuf [ 0 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 0 ] > > 8 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 1 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 0 ] > > 0 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 2 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 1 ] > > 8 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 3 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 1 ] > > 0 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 4 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 2 ] > > 8 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 5 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 2 ] > > 0 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 6 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 3 ] > > 8 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 7 ] = mbp ( ( uint8 ) ( tf . tile_vrb [ 3 ] > > 0 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
}
}
else
{
if ( tf . cellx_xor & 0x7 )
{
bgbuf [ 7 ] = mbp ( ( tf . tile_vrb [ 0 ] > > 12 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 6 ] = mbp ( ( tf . tile_vrb [ 0 ] > > 8 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 5 ] = mbp ( ( tf . tile_vrb [ 0 ] > > 4 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 4 ] = mbp ( ( tf . tile_vrb [ 0 ] > > 0 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 3 ] = mbp ( ( tf . tile_vrb [ 1 ] > > 12 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 2 ] = mbp ( ( tf . tile_vrb [ 1 ] > > 8 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 1 ] = mbp ( ( tf . tile_vrb [ 1 ] > > 4 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 0 ] = mbp ( ( tf . tile_vrb [ 1 ] > > 0 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
}
else
{
bgbuf [ 0 ] = mbp ( ( tf . tile_vrb [ 0 ] > > 12 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 1 ] = mbp ( ( tf . tile_vrb [ 0 ] > > 8 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 2 ] = mbp ( ( tf . tile_vrb [ 0 ] > > 4 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 3 ] = mbp ( ( tf . tile_vrb [ 0 ] > > 0 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 4 ] = mbp ( ( tf . tile_vrb [ 1 ] > > 12 ) , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 5 ] = mbp ( ( tf . tile_vrb [ 1 ] > > 8 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 6 ] = mbp ( ( tf . tile_vrb [ 1 ] > > 4 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
bgbuf [ 7 ] = mbp ( ( tf . tile_vrb [ 1 ] > > 0 ) & 0xF , /**/ pbor , sfcode_lut , tf . pcco ) ;
}
}
//
//
//
tx + + ;
bgbuf + = 8 ;
}
}
static void ( * DrawNBG23 [ 2 /*col mode*/ ] [ 2 /*igntp*/ ] [ 3 /*priomode*/ ] [ 4 /*ccmode*/ ] ) ( const unsigned n , uint64 * bgbuf , const unsigned w , const uint32 pix_base_or ) =
{
{
{ { T_DrawNBG23 < 4 , 0 , 0 , 0 > , T_DrawNBG23 < 4 , 0 , 0 , 1 > , T_DrawNBG23 < 4 , 0 , 0 , 2 > , T_DrawNBG23 < 4 , 0 , 0 , 3 > , } , { T_DrawNBG23 < 4 , 0 , 1 , 0 > , T_DrawNBG23 < 4 , 0 , 1 , 1 > , T_DrawNBG23 < 4 , 0 , 1 , 2 > , T_DrawNBG23 < 4 , 0 , 1 , 3 > , } , { T_DrawNBG23 < 4 , 0 , 2 , 0 > , T_DrawNBG23 < 4 , 0 , 2 , 1 > , T_DrawNBG23 < 4 , 0 , 2 , 2 > , T_DrawNBG23 < 4 , 0 , 2 , 3 > , } , } ,
{ { T_DrawNBG23 < 4 , 1 , 0 , 0 > , T_DrawNBG23 < 4 , 1 , 0 , 1 > , T_DrawNBG23 < 4 , 1 , 0 , 2 > , T_DrawNBG23 < 4 , 1 , 0 , 3 > , } , { T_DrawNBG23 < 4 , 1 , 1 , 0 > , T_DrawNBG23 < 4 , 1 , 1 , 1 > , T_DrawNBG23 < 4 , 1 , 1 , 2 > , T_DrawNBG23 < 4 , 1 , 1 , 3 > , } , { T_DrawNBG23 < 4 , 1 , 2 , 0 > , T_DrawNBG23 < 4 , 1 , 2 , 1 > , T_DrawNBG23 < 4 , 1 , 2 , 2 > , T_DrawNBG23 < 4 , 1 , 2 , 3 > , } , } ,
} ,
{
{ { T_DrawNBG23 < 8 , 0 , 0 , 0 > , T_DrawNBG23 < 8 , 0 , 0 , 1 > , T_DrawNBG23 < 8 , 0 , 0 , 2 > , T_DrawNBG23 < 8 , 0 , 0 , 3 > , } , { T_DrawNBG23 < 8 , 0 , 1 , 0 > , T_DrawNBG23 < 8 , 0 , 1 , 1 > , T_DrawNBG23 < 8 , 0 , 1 , 2 > , T_DrawNBG23 < 8 , 0 , 1 , 3 > , } , { T_DrawNBG23 < 8 , 0 , 2 , 0 > , T_DrawNBG23 < 8 , 0 , 2 , 1 > , T_DrawNBG23 < 8 , 0 , 2 , 2 > , T_DrawNBG23 < 8 , 0 , 2 , 3 > , } , } ,
{ { T_DrawNBG23 < 8 , 1 , 0 , 0 > , T_DrawNBG23 < 8 , 1 , 0 , 1 > , T_DrawNBG23 < 8 , 1 , 0 , 2 > , T_DrawNBG23 < 8 , 1 , 0 , 3 > , } , { T_DrawNBG23 < 8 , 1 , 1 , 0 > , T_DrawNBG23 < 8 , 1 , 1 , 1 > , T_DrawNBG23 < 8 , 1 , 1 , 2 > , T_DrawNBG23 < 8 , 1 , 1 , 3 > , } , { T_DrawNBG23 < 8 , 1 , 2 , 0 > , T_DrawNBG23 < 8 , 1 , 2 , 1 > , T_DrawNBG23 < 8 , 1 , 2 , 2 > , T_DrawNBG23 < 8 , 1 , 2 , 3 > , } , } ,
} ,
} ;
static INLINE uint32 GetCoeffAddr ( const unsigned i , uint32 offset )
{
const uint32 src_mask = ( CRKTE ? 0x3FF : 0x3FFFF ) ;
offset > > = 10 ;
offset < < = ! ( KTCTL [ i ] & 0x2 ) ;
offset & = src_mask ;
return offset ;
}
static INLINE uint32 ReadCoeff ( const unsigned i , const uint32 addr )
{
const uint16 * src = ( CRKTE ? & CRAM [ 0x400 ] : VRAM ) ;
uint32 coeff ;
if ( KTCTL [ i ] & 0x2 )
{
const uint16 tmp = src [ addr ] ;
coeff = ( sign_x_to_s32 ( 21 , tmp < < 6 ) & 0x00FFFFFF ) | ( ( tmp & 0x8000 ) < < 16 ) ;
//printf("%d Coeff %08x, %04x -- %08x\n", i, offset, tmp, coeff);
}
else
{
const uint16 * ea = & src [ addr ] ;
coeff = ( ea [ 0 ] < < 16 ) | ea [ 1 ] ;
}
return coeff ;
}
// Coefficient table reading can (temporarily) override kx, ky, and/or Xp
//
// When RBG1 is enabled, line color screen uses rotation parameter A coefficient table
//
// RBG1 always uses MSB of coefficient data as transparent bit.
//
// RBG1 requires RPMD == 0, or else bad things happen?
template < typename T >
static void SetupRotVars ( const T * rs , const unsigned rbg_w )
{
const uint8 EffRPMD = ( ( BGON & 0x20 ) ? 0 : RPMD ) ;
if ( EffRPMD < 2 )
{
for ( unsigned x = 0 ; MDFN_LIKELY ( x < rbg_w ) ; x + + )
LB . rotabsel [ x ] = RPMD ;
}
else if ( EffRPMD = = 3 )
GetWinRotAB ( ) ;
//
//
//
for ( unsigned i = 0 ; i < 2 ; i + + )
{
auto & r = LB . rotv [ i ] ;
r . Xsp = rs [ i ] . Xsp ;
r . Ysp = rs [ i ] . Ysp ;
r . Xp = rs [ i ] . Xp ;
r . Yp = rs [ i ] . Yp ;
r . dX = rs [ i ] . dX ;
r . dY = rs [ i ] . dY ;
r . kx = rs [ i ] . kx ;
r . ky = rs [ i ] . ky ;
LB . rotv [ i ] . tf . BMSCC = ( ( BMPNB > > 4 ) & 1 ) ;
LB . rotv [ i ] . tf . BMSPR = ( ( BMPNB > > 5 ) & 1 ) ;
LB . rotv [ i ] . tf . BMPalNo = ( ( BMPNB > > 0 ) & 0x7 ) < < 4 ;
LB . rotv [ i ] . tf . BMSize = ( ( CHCTLB > > 10 ) & 0x1 ) ;
//
//
//
//
//
//
if ( ( BGON & 0x20 ) & & i )
{
LB . rotv [ 1 ] . tf . CRAOffs = CRAMAddrOffs_NBG [ 0 ] < < 8 ;
LB . rotv [ 1 ] . tf . PNDSize = ( PNCN [ 0 ] > > 15 ) & 1 ;
LB . rotv [ 1 ] . tf . CharSize = ( ( CHCTLA > > 0 ) & 1 ) ;
LB . rotv [ 1 ] . tf . AuxMode = ( PNCN [ 0 ] > > 14 ) & 1 ;
LB . rotv [ 1 ] . tf . Supp = ( PNCN [ 0 ] & 0x3FF ) ;
}
else
{
LB . rotv [ i ] . tf . CRAOffs = CRAMAddrOffs_RBG0 < < 8 ;
LB . rotv [ i ] . tf . PNDSize = ( PNCNR > > 15 ) & 1 ;
LB . rotv [ i ] . tf . CharSize = ( ( CHCTLB > > 8 ) & 1 ) ;
LB . rotv [ i ] . tf . AuxMode = ( PNCNR > > 14 ) & 1 ;
LB . rotv [ i ] . tf . Supp = ( PNCNR & 0x3FF ) ;
}
LB . rotv [ i ] . tf . PlaneSize = ( PLSZ > > ( 8 + ( i < < 2 ) ) ) & 0x3 ;
LB . rotv [ i ] . tf . PlaneOver = ( PLSZ > > ( 10 + ( i < < 2 ) ) ) & 0x3 ;
LB . rotv [ i ] . tf . PlaneOverChar = OVPNR [ i ] ;
LB . rotv [ i ] . tf . Start ( 4 + i , ! i & & ( ( CHCTLB > > 9 ) & 1 ) , ( MPOFR > > ( i < < 2 ) ) & 0x7 , RotMapRegs [ i ] ) ;
}
//
//
//
{
bool bank_tab [ 4 ] ;
for ( unsigned i = 0 ; i < 4 ; i + + )
bank_tab [ i ] = ( ( RDBS_Mode > > ( i < < 1 ) ) & 0x3 ) = = RDBS_COEFF ;
//
if ( ! ( VRAM_Mode & 0x1 ) )
bank_tab [ 1 ] = bank_tab [ 0 ] ;
if ( ! ( VRAM_Mode & 0x2 ) )
bank_tab [ 3 ] = bank_tab [ 2 ] ;
if ( BGON & 0x20 )
bank_tab [ 2 ] = bank_tab [ 3 ] = false ;
//
if ( CRKTE )
bank_tab [ 0 ] = bank_tab [ 1 ] = bank_tab [ 2 ] = bank_tab [ 3 ] = true ;
//
//
LB . rotv [ 0 ] . use_coeff = ( bool ) ( KTCTL [ 0 ] & 0x1 ) ;
LB . rotv [ 1 ] . use_coeff = ( bool ) ( KTCTL [ 1 ] & 0x1 ) ;
uint32 coeff [ 2 ] ;
for ( unsigned i = 0 ; i < 2 ; i + + )
LB . rotv [ i ] . base_coeff = coeff [ i ] = ReadCoeff ( i , GetCoeffAddr ( i , rs [ i ] . KAstAccum ) ) ;
//if(grumpus == 120)
// printf("BankTab: %d %d %d %d, UC: %d %d, Coeff: @0x%05x=0x%08x @0x%05x=0x%08x, DKAx: %f %f\n", bank_tab[0], bank_tab[1], bank_tab[2], bank_tab[3], LB.rotv[0].use_coeff, LB.rotv[1].use_coeff, GetCoeffAddr(0, rs[0].KAstAccum), coeff[0], GetCoeffAddr(1, rs[1].KAstAccum), coeff[1], rs[0].DKAx / 1024.0, rs[1].DKAx / 1024.0);
for ( unsigned x = 0 ; MDFN_LIKELY ( x < rbg_w ) ; x + + )
{
const unsigned i = ( ( EffRPMD = = 2 ) ? 0 : LB . rotabsel [ x ] ) ;
const uint32 addr = GetCoeffAddr ( i , rs [ i ] . KAstAccum + ( x * rs [ i ] . DKAx ) ) ;
if ( bank_tab [ addr > > 16 ] )
coeff [ i ] = ReadCoeff ( i , addr ) ;
if ( KTCTL [ i ] & 0x10 )
LB . lc [ x ] = ( coeff [ i ] > > 24 ) & 0x7F ;
if ( EffRPMD = = 2 )
{
uint32 tmp = coeff [ 0 ] ;
LB . rotabsel [ x ] = tmp > > 31 ;
if ( ( int32 ) tmp < 0 )
tmp = coeff [ 1 ] ;
LB . rotcoeff [ x ] = tmp ;
}
else
LB . rotcoeff [ x ] = coeff [ i ] ;
}
}
}
// const bool TA_bmen = ((rn == 1) ? false : ((CHCTLB >> 9) & 1));
template < bool TA_bmen , unsigned TA_bpp , bool TA_isrgb , bool TA_igntp , unsigned TA_PrioMode , unsigned TA_CCMode >
static void T_DrawRBG ( const bool rn , uint64 * bgbuf , const unsigned w , const uint32 pix_base_or )
{
// Full color format selection for both RBG0 and RBG1
// Bitmap only allowed for RBG0
// RBG0 can use rot param A and B, RBG1 is fixed to rot param B
// RBG1 shares setting bitfields with NBG0
// 16 planes instead of 4 like with NBG*
// Mosaic only has effect in the horizontal direction?
//
int16 sfcode_lut [ 8 ] ;
MakeSFCodeLUT < TA_PrioMode , TA_CCMode > ( ( rn ? 0 : 4 ) , sfcode_lut ) ;
for ( unsigned i = 0 ; MDFN_LIKELY ( i < w ) ; i + + )
{
const unsigned ab = LB . rotabsel [ i ] ;
auto & r = LB . rotv [ ab ] ;
auto & tf = r . tf ;
uint32 Xp = r . Xp ;
int32 kx = r . kx ;
int32 ky = r . ky ;
bool rot_tp = false ;
if ( r . use_coeff )
{
const uint32 coeff = ( rn ? r . base_coeff : LB . rotcoeff [ i ] ) ;
rot_tp = ( ( int32 ) coeff < 0 ) ;
const uint32 sext = sign_x_to_s32 ( 24 , coeff ) ;
switch ( ( KTCTL [ ab ] > > 2 ) & 0x3 )
{
case 0 : kx = ky = sext ; break ;
case 1 : kx = sext ; break ;
case 2 : ky = sext ; break ;
case 3 : Xp = sext < < 2 ; break ;
}
}
const uint32 ix = ( Xp + ( uint32 ) ( ( ( int64 ) kx * ( int32 ) ( r . Xsp + ( r . dX * i ) ) ) > > 16 ) ) > > 10 ;
const uint32 iy = ( r . Yp + ( uint32 ) ( ( ( int64 ) ky * ( int32 ) ( r . Ysp + ( r . dY * i ) ) ) > > 16 ) ) > > 10 ;
rot_tp | = tf . Fetch < TA_bpp > ( TA_bmen , ix , iy ) ;
LB . rotabsel [ i ] = rot_tp ;
//
//
//
bgbuf [ i ] = MakeNBGRBGPix < TA_bmen , TA_bpp , TA_isrgb , TA_igntp , TA_PrioMode , TA_CCMode > ( tf , pix_base_or , sfcode_lut , ix , iy ) ;
}
}
//template<unsigned TA_bpp, bool TA_isrgb, bool TA_igntp, unsigned TA_PrioMode, unsigned TA_CCMode>
static void ( * DrawRBG [ 2 /*bitmap enable*/ ] [ 5 /*col mode*/ ] [ 2 /*igntp*/ ] [ 3 /*priomode*/ ] [ 4 /*ccmode*/ ] ) ( const bool rn , uint64 * bgbuf , const unsigned w , const uint32 pix_base_or ) =
{
{
{ { { T_DrawRBG < 0 , 4 , 0 , 0 , 0 , 0 > , T_DrawRBG < 0 , 4 , 0 , 0 , 0 , 1 > , T_DrawRBG < 0 , 4 , 0 , 0 , 0 , 2 > , T_DrawRBG < 0 , 4 , 0 , 0 , 0 , 3 > , } , { T_DrawRBG < 0 , 4 , 0 , 0 , 1 , 0 > , T_DrawRBG < 0 , 4 , 0 , 0 , 1 , 1 > , T_DrawRBG < 0 , 4 , 0 , 0 , 1 , 2 > , T_DrawRBG < 0 , 4 , 0 , 0 , 1 , 3 > , } , { T_DrawRBG < 0 , 4 , 0 , 0 , 2 , 0 > , T_DrawRBG < 0 , 4 , 0 , 0 , 2 , 1 > , T_DrawRBG < 0 , 4 , 0 , 0 , 2 , 2 > , T_DrawRBG < 0 , 4 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawRBG < 0 , 4 , 0 , 1 , 0 , 0 > , T_DrawRBG < 0 , 4 , 0 , 1 , 0 , 1 > , T_DrawRBG < 0 , 4 , 0 , 1 , 0 , 2 > , T_DrawRBG < 0 , 4 , 0 , 1 , 0 , 3 > , } , { T_DrawRBG < 0 , 4 , 0 , 1 , 1 , 0 > , T_DrawRBG < 0 , 4 , 0 , 1 , 1 , 1 > , T_DrawRBG < 0 , 4 , 0 , 1 , 1 , 2 > , T_DrawRBG < 0 , 4 , 0 , 1 , 1 , 3 > , } , { T_DrawRBG < 0 , 4 , 0 , 1 , 2 , 0 > , T_DrawRBG < 0 , 4 , 0 , 1 , 2 , 1 > , T_DrawRBG < 0 , 4 , 0 , 1 , 2 , 2 > , T_DrawRBG < 0 , 4 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawRBG < 0 , 8 , 0 , 0 , 0 , 0 > , T_DrawRBG < 0 , 8 , 0 , 0 , 0 , 1 > , T_DrawRBG < 0 , 8 , 0 , 0 , 0 , 2 > , T_DrawRBG < 0 , 8 , 0 , 0 , 0 , 3 > , } , { T_DrawRBG < 0 , 8 , 0 , 0 , 1 , 0 > , T_DrawRBG < 0 , 8 , 0 , 0 , 1 , 1 > , T_DrawRBG < 0 , 8 , 0 , 0 , 1 , 2 > , T_DrawRBG < 0 , 8 , 0 , 0 , 1 , 3 > , } , { T_DrawRBG < 0 , 8 , 0 , 0 , 2 , 0 > , T_DrawRBG < 0 , 8 , 0 , 0 , 2 , 1 > , T_DrawRBG < 0 , 8 , 0 , 0 , 2 , 2 > , T_DrawRBG < 0 , 8 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawRBG < 0 , 8 , 0 , 1 , 0 , 0 > , T_DrawRBG < 0 , 8 , 0 , 1 , 0 , 1 > , T_DrawRBG < 0 , 8 , 0 , 1 , 0 , 2 > , T_DrawRBG < 0 , 8 , 0 , 1 , 0 , 3 > , } , { T_DrawRBG < 0 , 8 , 0 , 1 , 1 , 0 > , T_DrawRBG < 0 , 8 , 0 , 1 , 1 , 1 > , T_DrawRBG < 0 , 8 , 0 , 1 , 1 , 2 > , T_DrawRBG < 0 , 8 , 0 , 1 , 1 , 3 > , } , { T_DrawRBG < 0 , 8 , 0 , 1 , 2 , 0 > , T_DrawRBG < 0 , 8 , 0 , 1 , 2 , 1 > , T_DrawRBG < 0 , 8 , 0 , 1 , 2 , 2 > , T_DrawRBG < 0 , 8 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawRBG < 0 , 16 , 0 , 0 , 0 , 0 > , T_DrawRBG < 0 , 16 , 0 , 0 , 0 , 1 > , T_DrawRBG < 0 , 16 , 0 , 0 , 0 , 2 > , T_DrawRBG < 0 , 16 , 0 , 0 , 0 , 3 > , } , { T_DrawRBG < 0 , 16 , 0 , 0 , 1 , 0 > , T_DrawRBG < 0 , 16 , 0 , 0 , 1 , 1 > , T_DrawRBG < 0 , 16 , 0 , 0 , 1 , 2 > , T_DrawRBG < 0 , 16 , 0 , 0 , 1 , 3 > , } , { T_DrawRBG < 0 , 16 , 0 , 0 , 2 , 0 > , T_DrawRBG < 0 , 16 , 0 , 0 , 2 , 1 > , T_DrawRBG < 0 , 16 , 0 , 0 , 2 , 2 > , T_DrawRBG < 0 , 16 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawRBG < 0 , 16 , 0 , 1 , 0 , 0 > , T_DrawRBG < 0 , 16 , 0 , 1 , 0 , 1 > , T_DrawRBG < 0 , 16 , 0 , 1 , 0 , 2 > , T_DrawRBG < 0 , 16 , 0 , 1 , 0 , 3 > , } , { T_DrawRBG < 0 , 16 , 0 , 1 , 1 , 0 > , T_DrawRBG < 0 , 16 , 0 , 1 , 1 , 1 > , T_DrawRBG < 0 , 16 , 0 , 1 , 1 , 2 > , T_DrawRBG < 0 , 16 , 0 , 1 , 1 , 3 > , } , { T_DrawRBG < 0 , 16 , 0 , 1 , 2 , 0 > , T_DrawRBG < 0 , 16 , 0 , 1 , 2 , 1 > , T_DrawRBG < 0 , 16 , 0 , 1 , 2 , 2 > , T_DrawRBG < 0 , 16 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawRBG < 0 , 16 , 1 , 0 , 0 , 0 > , T_DrawRBG < 0 , 16 , 1 , 0 , 0 , 1 > , T_DrawRBG < 0 , 16 , 1 , 0 , 0 , 2 > , T_DrawRBG < 0 , 16 , 1 , 0 , 0 , 3 > , } , { T_DrawRBG < 0 , 16 , 1 , 0 , 1 , 0 > , T_DrawRBG < 0 , 16 , 1 , 0 , 1 , 1 > , T_DrawRBG < 0 , 16 , 1 , 0 , 1 , 2 > , T_DrawRBG < 0 , 16 , 1 , 0 , 1 , 3 > , } , { T_DrawRBG < 0 , 16 , 1 , 0 , 2 , 0 > , T_DrawRBG < 0 , 16 , 1 , 0 , 2 , 1 > , T_DrawRBG < 0 , 16 , 1 , 0 , 2 , 2 > , T_DrawRBG < 0 , 16 , 1 , 0 , 2 , 3 > , } , } , { { T_DrawRBG < 0 , 16 , 1 , 1 , 0 , 0 > , T_DrawRBG < 0 , 16 , 1 , 1 , 0 , 1 > , T_DrawRBG < 0 , 16 , 1 , 1 , 0 , 2 > , T_DrawRBG < 0 , 16 , 1 , 1 , 0 , 3 > , } , { T_DrawRBG < 0 , 16 , 1 , 1 , 1 , 0 > , T_DrawRBG < 0 , 16 , 1 , 1 , 1 , 1 > , T_DrawRBG < 0 , 16 , 1 , 1 , 1 , 2 > , T_DrawRBG < 0 , 16 , 1 , 1 , 1 , 3 > , } , { T_DrawRBG < 0 , 16 , 1 , 1 , 2 , 0 > , T_DrawRBG < 0 , 16 , 1 , 1 , 2 , 1 > , T_DrawRBG < 0 , 16 , 1 , 1 , 2 , 2 > , T_DrawRBG < 0 , 16 , 1 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawRBG < 0 , 32 , 1 , 0 , 0 , 0 > , T_DrawRBG < 0 , 32 , 1 , 0 , 0 , 1 > , T_DrawRBG < 0 , 32 , 1 , 0 , 0 , 2 > , T_DrawRBG < 0 , 32 , 1 , 0 , 0 , 3 > , } , { T_DrawRBG < 0 , 32 , 1 , 0 , 1 , 0 > , T_DrawRBG < 0 , 32 , 1 , 0 , 1 , 1 > , T_DrawRBG < 0 , 32 , 1 , 0 , 1 , 2 > , T_DrawRBG < 0 , 32 , 1 , 0 , 1 , 3 > , } , { T_DrawRBG < 0 , 32 , 1 , 0 , 2 , 0 > , T_DrawRBG < 0 , 32 , 1 , 0 , 2 , 1 > , T_DrawRBG < 0 , 32 , 1 , 0 , 2 , 2 > , T_DrawRBG < 0 , 32 , 1 , 0 , 2 , 3 > , } , } , { { T_DrawRBG < 0 , 32 , 1 , 1 , 0 , 0 > , T_DrawRBG < 0 , 32 , 1 , 1 , 0 , 1 > , T_DrawRBG < 0 , 32 , 1 , 1 , 0 , 2 > , T_DrawRBG < 0 , 32 , 1 , 1 , 0 , 3 > , } , { T_DrawRBG < 0 , 32 , 1 , 1 , 1 , 0 > , T_DrawRBG < 0 , 32 , 1 , 1 , 1 , 1 > , T_DrawRBG < 0 , 32 , 1 , 1 , 1 , 2 > , T_DrawRBG < 0 , 32 , 1 , 1 , 1 , 3 > , } , { T_DrawRBG < 0 , 32 , 1 , 1 , 2 , 0 > , T_DrawRBG < 0 , 32 , 1 , 1 , 2 , 1 > , T_DrawRBG < 0 , 32 , 1 , 1 , 2 , 2 > , T_DrawRBG < 0 , 32 , 1 , 1 , 2 , 3 > , } , } , } ,
} ,
{
{ { { T_DrawRBG < 1 , 4 , 0 , 0 , 0 , 0 > , T_DrawRBG < 1 , 4 , 0 , 0 , 0 , 1 > , T_DrawRBG < 1 , 4 , 0 , 0 , 0 , 2 > , T_DrawRBG < 1 , 4 , 0 , 0 , 0 , 3 > , } , { T_DrawRBG < 1 , 4 , 0 , 0 , 1 , 0 > , T_DrawRBG < 1 , 4 , 0 , 0 , 1 , 1 > , T_DrawRBG < 1 , 4 , 0 , 0 , 1 , 2 > , T_DrawRBG < 1 , 4 , 0 , 0 , 1 , 3 > , } , { T_DrawRBG < 1 , 4 , 0 , 0 , 2 , 0 > , T_DrawRBG < 1 , 4 , 0 , 0 , 2 , 1 > , T_DrawRBG < 1 , 4 , 0 , 0 , 2 , 2 > , T_DrawRBG < 1 , 4 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawRBG < 1 , 4 , 0 , 1 , 0 , 0 > , T_DrawRBG < 1 , 4 , 0 , 1 , 0 , 1 > , T_DrawRBG < 1 , 4 , 0 , 1 , 0 , 2 > , T_DrawRBG < 1 , 4 , 0 , 1 , 0 , 3 > , } , { T_DrawRBG < 1 , 4 , 0 , 1 , 1 , 0 > , T_DrawRBG < 1 , 4 , 0 , 1 , 1 , 1 > , T_DrawRBG < 1 , 4 , 0 , 1 , 1 , 2 > , T_DrawRBG < 1 , 4 , 0 , 1 , 1 , 3 > , } , { T_DrawRBG < 1 , 4 , 0 , 1 , 2 , 0 > , T_DrawRBG < 1 , 4 , 0 , 1 , 2 , 1 > , T_DrawRBG < 1 , 4 , 0 , 1 , 2 , 2 > , T_DrawRBG < 1 , 4 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawRBG < 1 , 8 , 0 , 0 , 0 , 0 > , T_DrawRBG < 1 , 8 , 0 , 0 , 0 , 1 > , T_DrawRBG < 1 , 8 , 0 , 0 , 0 , 2 > , T_DrawRBG < 1 , 8 , 0 , 0 , 0 , 3 > , } , { T_DrawRBG < 1 , 8 , 0 , 0 , 1 , 0 > , T_DrawRBG < 1 , 8 , 0 , 0 , 1 , 1 > , T_DrawRBG < 1 , 8 , 0 , 0 , 1 , 2 > , T_DrawRBG < 1 , 8 , 0 , 0 , 1 , 3 > , } , { T_DrawRBG < 1 , 8 , 0 , 0 , 2 , 0 > , T_DrawRBG < 1 , 8 , 0 , 0 , 2 , 1 > , T_DrawRBG < 1 , 8 , 0 , 0 , 2 , 2 > , T_DrawRBG < 1 , 8 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawRBG < 1 , 8 , 0 , 1 , 0 , 0 > , T_DrawRBG < 1 , 8 , 0 , 1 , 0 , 1 > , T_DrawRBG < 1 , 8 , 0 , 1 , 0 , 2 > , T_DrawRBG < 1 , 8 , 0 , 1 , 0 , 3 > , } , { T_DrawRBG < 1 , 8 , 0 , 1 , 1 , 0 > , T_DrawRBG < 1 , 8 , 0 , 1 , 1 , 1 > , T_DrawRBG < 1 , 8 , 0 , 1 , 1 , 2 > , T_DrawRBG < 1 , 8 , 0 , 1 , 1 , 3 > , } , { T_DrawRBG < 1 , 8 , 0 , 1 , 2 , 0 > , T_DrawRBG < 1 , 8 , 0 , 1 , 2 , 1 > , T_DrawRBG < 1 , 8 , 0 , 1 , 2 , 2 > , T_DrawRBG < 1 , 8 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawRBG < 1 , 16 , 0 , 0 , 0 , 0 > , T_DrawRBG < 1 , 16 , 0 , 0 , 0 , 1 > , T_DrawRBG < 1 , 16 , 0 , 0 , 0 , 2 > , T_DrawRBG < 1 , 16 , 0 , 0 , 0 , 3 > , } , { T_DrawRBG < 1 , 16 , 0 , 0 , 1 , 0 > , T_DrawRBG < 1 , 16 , 0 , 0 , 1 , 1 > , T_DrawRBG < 1 , 16 , 0 , 0 , 1 , 2 > , T_DrawRBG < 1 , 16 , 0 , 0 , 1 , 3 > , } , { T_DrawRBG < 1 , 16 , 0 , 0 , 2 , 0 > , T_DrawRBG < 1 , 16 , 0 , 0 , 2 , 1 > , T_DrawRBG < 1 , 16 , 0 , 0 , 2 , 2 > , T_DrawRBG < 1 , 16 , 0 , 0 , 2 , 3 > , } , } , { { T_DrawRBG < 1 , 16 , 0 , 1 , 0 , 0 > , T_DrawRBG < 1 , 16 , 0 , 1 , 0 , 1 > , T_DrawRBG < 1 , 16 , 0 , 1 , 0 , 2 > , T_DrawRBG < 1 , 16 , 0 , 1 , 0 , 3 > , } , { T_DrawRBG < 1 , 16 , 0 , 1 , 1 , 0 > , T_DrawRBG < 1 , 16 , 0 , 1 , 1 , 1 > , T_DrawRBG < 1 , 16 , 0 , 1 , 1 , 2 > , T_DrawRBG < 1 , 16 , 0 , 1 , 1 , 3 > , } , { T_DrawRBG < 1 , 16 , 0 , 1 , 2 , 0 > , T_DrawRBG < 1 , 16 , 0 , 1 , 2 , 1 > , T_DrawRBG < 1 , 16 , 0 , 1 , 2 , 2 > , T_DrawRBG < 1 , 16 , 0 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawRBG < 1 , 16 , 1 , 0 , 0 , 0 > , T_DrawRBG < 1 , 16 , 1 , 0 , 0 , 1 > , T_DrawRBG < 1 , 16 , 1 , 0 , 0 , 2 > , T_DrawRBG < 1 , 16 , 1 , 0 , 0 , 3 > , } , { T_DrawRBG < 1 , 16 , 1 , 0 , 1 , 0 > , T_DrawRBG < 1 , 16 , 1 , 0 , 1 , 1 > , T_DrawRBG < 1 , 16 , 1 , 0 , 1 , 2 > , T_DrawRBG < 1 , 16 , 1 , 0 , 1 , 3 > , } , { T_DrawRBG < 1 , 16 , 1 , 0 , 2 , 0 > , T_DrawRBG < 1 , 16 , 1 , 0 , 2 , 1 > , T_DrawRBG < 1 , 16 , 1 , 0 , 2 , 2 > , T_DrawRBG < 1 , 16 , 1 , 0 , 2 , 3 > , } , } , { { T_DrawRBG < 1 , 16 , 1 , 1 , 0 , 0 > , T_DrawRBG < 1 , 16 , 1 , 1 , 0 , 1 > , T_DrawRBG < 1 , 16 , 1 , 1 , 0 , 2 > , T_DrawRBG < 1 , 16 , 1 , 1 , 0 , 3 > , } , { T_DrawRBG < 1 , 16 , 1 , 1 , 1 , 0 > , T_DrawRBG < 1 , 16 , 1 , 1 , 1 , 1 > , T_DrawRBG < 1 , 16 , 1 , 1 , 1 , 2 > , T_DrawRBG < 1 , 16 , 1 , 1 , 1 , 3 > , } , { T_DrawRBG < 1 , 16 , 1 , 1 , 2 , 0 > , T_DrawRBG < 1 , 16 , 1 , 1 , 2 , 1 > , T_DrawRBG < 1 , 16 , 1 , 1 , 2 , 2 > , T_DrawRBG < 1 , 16 , 1 , 1 , 2 , 3 > , } , } , } ,
{ { { T_DrawRBG < 1 , 32 , 1 , 0 , 0 , 0 > , T_DrawRBG < 1 , 32 , 1 , 0 , 0 , 1 > , T_DrawRBG < 1 , 32 , 1 , 0 , 0 , 2 > , T_DrawRBG < 1 , 32 , 1 , 0 , 0 , 3 > , } , { T_DrawRBG < 1 , 32 , 1 , 0 , 1 , 0 > , T_DrawRBG < 1 , 32 , 1 , 0 , 1 , 1 > , T_DrawRBG < 1 , 32 , 1 , 0 , 1 , 2 > , T_DrawRBG < 1 , 32 , 1 , 0 , 1 , 3 > , } , { T_DrawRBG < 1 , 32 , 1 , 0 , 2 , 0 > , T_DrawRBG < 1 , 32 , 1 , 0 , 2 , 1 > , T_DrawRBG < 1 , 32 , 1 , 0 , 2 , 2 > , T_DrawRBG < 1 , 32 , 1 , 0 , 2 , 3 > , } , } , { { T_DrawRBG < 1 , 32 , 1 , 1 , 0 , 0 > , T_DrawRBG < 1 , 32 , 1 , 1 , 0 , 1 > , T_DrawRBG < 1 , 32 , 1 , 1 , 0 , 2 > , T_DrawRBG < 1 , 32 , 1 , 1 , 0 , 3 > , } , { T_DrawRBG < 1 , 32 , 1 , 1 , 1 , 0 > , T_DrawRBG < 1 , 32 , 1 , 1 , 1 , 1 > , T_DrawRBG < 1 , 32 , 1 , 1 , 1 , 2 > , T_DrawRBG < 1 , 32 , 1 , 1 , 1 , 3 > , } , { T_DrawRBG < 1 , 32 , 1 , 1 , 2 , 0 > , T_DrawRBG < 1 , 32 , 1 , 1 , 2 , 1 > , T_DrawRBG < 1 , 32 , 1 , 1 , 2 , 2 > , T_DrawRBG < 1 , 32 , 1 , 1 , 2 , 3 > , } , } , } ,
}
} ;
template < typename T >
static INLINE void Doubleize ( T * ptr , const int orig_len )
{
for ( int i = orig_len - 1 ; MDFN_LIKELY ( i > = 0 ) ; i - - )
{
auto tmp = * ( ptr + i ) ;
* ( ptr + ( i < < 1 ) + 0 ) = tmp ;
* ( ptr + ( i < < 1 ) + 1 ) = tmp ;
}
}
static void RBGPP ( const unsigned layer , uint64 * buf , const unsigned rbg_w )
{
ApplyHMosaic ( layer , buf , rbg_w ) ;
for ( unsigned i = 0 ; i < rbg_w ; i + + )
{
uint64 tmp = buf [ i ] ;
if ( LB . rotabsel [ i ] )
tmp & = ~ ( uint64 ) 0xFFFFFFFF ;
buf [ i ] = tmp ;
}
if ( HRes & 0x2 )
Doubleize ( buf , rbg_w ) ;
ApplyWin ( layer , buf ) ;
}
// Call before DrawSpriteData()
static INLINE void MakeSpriteCCLUT ( void )
{
const bool cce = ( ( CCCTL > > 6 ) & 1 ) ;
for ( unsigned pr = 0 ; pr < 8 ; pr + + )
{
bool mask = false ;
switch ( SpriteCCCond )
{
case 0 : mask = ( SpritePrioNum [ pr ] < = SpriteCCNum ) ; break ;
case 1 : mask = ( SpritePrioNum [ pr ] = = SpriteCCNum ) ; break ;
case 2 : mask = ( SpritePrioNum [ pr ] > = SpriteCCNum ) ; break ;
}
SpriteCCLUT [ pr ] = ( cce & mask ) < < PIX_CCE_SHIFT ;
}
SpriteCC3Mask = 0 ;
if ( SpriteCCCond = = 3 & & cce )
SpriteCC3Mask = 1U < < PIX_CCE_SHIFT ;
}
template < bool TA_HiRes , bool TA_TPShadSel , unsigned TA_SPCTL_Low >
static void T_DrawSpriteData ( const uint16 * vdp1sb , const bool vdp1_hires8 , unsigned w )
{
const unsigned SpriteType = ( TA_SPCTL_Low & 0xF ) ;
const bool SpriteWinEn = ( TA_SPCTL_Low & 0x10 ) ;
const bool SpriteColorMode = ( TA_SPCTL_Low & 0x20 ) ;
//
const size_t cao = CRAMAddrOffs_Sprite < < 8 ;
uint32 spix_base_or = 0 ;
spix_base_or | = ( ( ColorOffsEn > > 6 ) & 1 ) < < PIX_COE_SHIFT ;
spix_base_or | = ( ( ColorOffsSel > > 6 ) & 1 ) < < PIX_COSEL_SHIFT ;
spix_base_or | = ( ( LineColorEn > > 5 /*5 here, not 6*/ ) & 1 ) < < PIX_LCE_SHIFT ;
spix_base_or | = ( ( ( CCCTL > > 12 ) & 0x7 ) = = 0x0 ) < < PIX_GRAD_SHIFT ;
spix_base_or | = ( ( CCCTL > > 6 ) & 1 ) < < PIX_LAYER_CCE_SHIFT ;
for ( unsigned i = 0 ; MDFN_LIKELY ( i < w ) ; i + + )
{
unsigned src ;
unsigned pr = 0 , cc = 0 ;
bool tp = false ;
uint64 spix ;
src = vdp1sb [ i > > TA_HiRes ] ;
if ( vdp1_hires8 )
{
if ( TA_HiRes )
src = 0xFF00 | ( src > > ( ( ( i & 1 ) ^ 1 ) < < 3 ) ) ;
else
src = 0xFF00 | ( src > > 8 ) ;
}
if ( SpriteColorMode & & ( src & 0x8000 ) )
{
spix = ( uint64 ) rgb15_to_rgb24 ( src ) < < PIX_RGB_SHIFT ;
spix | = 1U < < PIX_ISRGB_SHIFT ;
spix | = SpriteCC3Mask ;
if ( SpriteType & 0x8 )
tp = ! ( src & 0xFF ) ;
else if ( SpriteWinEn )
{
if ( SpriteType > = 0x2 & & SpriteType < = 0x7 )
tp = ! ( src & 0x7FFF ) ;
}
}
else
{
bool nshad = false ;
bool sd = false ;
unsigned dc ;
if ( SpriteType & 0x8 )
src & = 0xFF ;
tp = ! src ;
switch ( SpriteType )
{
case 0x0 :
pr = ( src > > 14 ) & 0x3 ;
cc = ( src > > 11 ) & 0x7 ;
dc = src & 0x7FF ;
nshad = ( dc = = 0x7FE ) ;
break ;
case 0x1 :
pr = ( src > > 13 ) & 0x7 ;
cc = ( src > > 11 ) & 0x3 ;
dc = src & 0x7FF ;
nshad = ( dc = = 0x7FE ) ;
break ;
case 0x2 :
sd = ( src > > 15 ) & 0x1 ;
pr = ( src > > 14 ) & 0x1 ;
cc = ( src > > 11 ) & 0x7 ;
dc = src & 0x7FF ;
nshad = ( dc = = 0x7FE ) ;
break ;
case 0x3 :
sd = ( src > > 15 ) & 0x1 ;
pr = ( src > > 13 ) & 0x3 ;
cc = ( src > > 11 ) & 0x3 ;
dc = src & 0x7FF ;
nshad = ( dc = = 0x7FE ) ;
break ;
case 0x4 :
sd = ( src > > 15 ) & 0x1 ;
pr = ( src > > 13 ) & 0x3 ;
cc = ( src > > 10 ) & 0x7 ;
dc = src & 0x3FF ;
nshad = ( dc = = 0x3FE ) ;
break ;
case 0x5 :
sd = ( src > > 15 ) & 0x1 ;
pr = ( src > > 12 ) & 0x7 ;
cc = ( src > > 11 ) & 0x1 ;
dc = src & 0x7FF ;
nshad = ( dc = = 0x7FE ) ;
break ;
case 0x6 :
sd = ( src > > 15 ) & 0x1 ;
pr = ( src > > 12 ) & 0x7 ;
cc = ( src > > 10 ) & 0x3 ;
dc = src & 0x3FF ;
nshad = ( dc = = 0x3FE ) ;
break ;
case 0x7 :
sd = ( src > > 15 ) & 0x1 ;
pr = ( src > > 12 ) & 0x7 ;
cc = ( src > > 9 ) & 0x7 ;
dc = src & 0x1FF ;
nshad = ( dc = = 0x1FE ) ;
break ;
//
//
//
case 0x8 :
pr = ( src > > 7 ) & 0x1 ;
dc = src & 0x7F ;
nshad = ( dc = = 0x7E ) ;
break ;
case 0x9 :
pr = ( src > > 7 ) & 0x1 ;
cc = ( src > > 6 ) & 0x1 ;
dc = src & 0x3F ;
nshad = ( dc = = 0x3E ) ;
break ;
case 0xA :
pr = ( src > > 6 ) & 0x3 ;
dc = src & 0x3F ;
nshad = ( dc = = 0x3E ) ;
break ;
case 0xB :
cc = ( src > > 6 ) & 0x3 ;
dc = src & 0x3F ;
nshad = ( dc = = 0x3E ) ;
break ;
//
case 0xC :
pr = ( src > > 7 ) & 0x1 ;
dc = src & 0xFF ;
nshad = ( dc = = 0xFE ) ;
break ;
case 0xD :
pr = ( src > > 7 ) & 0x1 ;
cc = ( src > > 6 ) & 0x1 ;
dc = src & 0xFF ;
nshad = ( dc = = 0xFE ) ;
break ;
case 0xE :
pr = ( src > > 6 ) & 0x3 ;
dc = src & 0xFF ;
nshad = ( dc = = 0xFE ) ;
break ;
case 0xF :
cc = ( src > > 6 ) & 0x3 ;
dc = src & 0xFF ;
nshad = ( dc = = 0xFE ) ;
break ;
}
//
//
//
uint32 rgb24 = ColorCache [ ( cao + dc ) & 0x7FF ] ;
spix = ( uint64 ) rgb24 < < PIX_RGB_SHIFT ;
spix | = ( ( int32 ) rgb24 > > 31 ) & SpriteCC3Mask ;
if ( SpriteWinEn ) // Sprite window enable
spix | = ( ( uint64 ) sd < < PIX_SWBIT_SHIFT ) ;
if ( nshad )
spix | = 1 < < PIX_DOSHAD_SHIFT ;
else
{
if ( SpriteWinEn )
{
if ( SpriteType > = 0x2 & & SpriteType < = 0x7 )
tp = ! ( src & 0x7FFF ) ;
}
else if ( sd )
{
if ( src & 0x7FFF )
spix | = 1 < < PIX_SELFSHAD_SHIFT ;
else if ( TA_TPShadSel )
spix | = 1 < < PIX_DOSHAD_SHIFT ;
else
tp = true ;
}
}
}
spix | = spix_base_or ;
spix | = ( tp ? 0 : SpritePrioNum [ pr ] ) < < PIX_PRIO_SHIFT ;
spix | = SpriteCCRatio [ cc ] < < PIX_CCRATIO_SHIFT ;
spix | = SpriteCCLUT [ pr ] ;
LB . spr [ i ] = spix ;
}
}
static void ( * DrawSpriteData [ 2 ] [ 2 ] [ 0x40 ] ) ( const uint16 * vdp1sb , const bool vdp1_hires8 , unsigned w ) =
{
{
{ T_DrawSpriteData < 0 , 0 , 0x00 > , T_DrawSpriteData < 0 , 0 , 0x01 > , T_DrawSpriteData < 0 , 0 , 0x02 > , T_DrawSpriteData < 0 , 0 , 0x03 > , T_DrawSpriteData < 0 , 0 , 0x04 > , T_DrawSpriteData < 0 , 0 , 0x05 > , T_DrawSpriteData < 0 , 0 , 0x06 > , T_DrawSpriteData < 0 , 0 , 0x07 > , T_DrawSpriteData < 0 , 0 , 0x08 > , T_DrawSpriteData < 0 , 0 , 0x09 > , T_DrawSpriteData < 0 , 0 , 0x0a > , T_DrawSpriteData < 0 , 0 , 0x0b > , T_DrawSpriteData < 0 , 0 , 0x0c > , T_DrawSpriteData < 0 , 0 , 0x0d > , T_DrawSpriteData < 0 , 0 , 0x0e > , T_DrawSpriteData < 0 , 0 , 0x0f > , T_DrawSpriteData < 0 , 0 , 0x10 > , T_DrawSpriteData < 0 , 0 , 0x11 > , T_DrawSpriteData < 0 , 0 , 0x12 > , T_DrawSpriteData < 0 , 0 , 0x13 > , T_DrawSpriteData < 0 , 0 , 0x14 > , T_DrawSpriteData < 0 , 0 , 0x15 > , T_DrawSpriteData < 0 , 0 , 0x16 > , T_DrawSpriteData < 0 , 0 , 0x17 > , T_DrawSpriteData < 0 , 0 , 0x18 > , T_DrawSpriteData < 0 , 0 , 0x19 > , T_DrawSpriteData < 0 , 0 , 0x1a > , T_DrawSpriteData < 0 , 0 , 0x1b > , T_DrawSpriteData < 0 , 0 , 0x1c > , T_DrawSpriteData < 0 , 0 , 0x1d > , T_DrawSpriteData < 0 , 0 , 0x1e > , T_DrawSpriteData < 0 , 0 , 0x1f > , T_DrawSpriteData < 0 , 0 , 0x20 > , T_DrawSpriteData < 0 , 0 , 0x21 > , T_DrawSpriteData < 0 , 0 , 0x22 > , T_DrawSpriteData < 0 , 0 , 0x23 > , T_DrawSpriteData < 0 , 0 , 0x24 > , T_DrawSpriteData < 0 , 0 , 0x25 > , T_DrawSpriteData < 0 , 0 , 0x26 > , T_DrawSpriteData < 0 , 0 , 0x27 > , T_DrawSpriteData < 0 , 0 , 0x28 > , T_DrawSpriteData < 0 , 0 , 0x29 > , T_DrawSpriteData < 0 , 0 , 0x2a > , T_DrawSpriteData < 0 , 0 , 0x2b > , T_DrawSpriteData < 0 , 0 , 0x2c > , T_DrawSpriteData < 0 , 0 , 0x2d > , T_DrawSpriteData < 0 , 0 , 0x2e > , T_DrawSpriteData < 0 , 0 , 0x2f > , T_DrawSpriteData < 0 , 0 , 0x30 > , T_DrawSpriteData < 0 , 0 , 0x31 > , T_DrawSpriteData < 0 , 0 , 0x32 > , T_DrawSpriteData < 0 , 0 , 0x33 > , T_DrawSpriteData < 0 , 0 , 0x34 > , T_DrawSpriteData < 0 , 0 , 0x35 > , T_DrawSpriteData < 0 , 0 , 0x36 > , T_DrawSpriteData < 0 , 0 , 0x37 > , T_DrawSpriteData < 0 , 0 , 0x38 > , T_DrawSpriteData < 0 , 0 , 0x39 > , T_DrawSpriteData < 0 , 0 , 0x3a > , T_DrawSpriteData < 0 , 0 , 0x3b > , T_DrawSpriteData < 0 , 0 , 0x3c > , T_DrawSpriteData < 0 , 0 , 0x3d > , T_DrawSpriteData < 0 , 0 , 0x3e > , T_DrawSpriteData < 0 , 0 , 0x3f > } ,
{ T_DrawSpriteData < 0 , 1 , 0x00 > , T_DrawSpriteData < 0 , 1 , 0x01 > , T_DrawSpriteData < 0 , 1 , 0x02 > , T_DrawSpriteData < 0 , 1 , 0x03 > , T_DrawSpriteData < 0 , 1 , 0x04 > , T_DrawSpriteData < 0 , 1 , 0x05 > , T_DrawSpriteData < 0 , 1 , 0x06 > , T_DrawSpriteData < 0 , 1 , 0x07 > , T_DrawSpriteData < 0 , 1 , 0x08 > , T_DrawSpriteData < 0 , 1 , 0x09 > , T_DrawSpriteData < 0 , 1 , 0x0a > , T_DrawSpriteData < 0 , 1 , 0x0b > , T_DrawSpriteData < 0 , 1 , 0x0c > , T_DrawSpriteData < 0 , 1 , 0x0d > , T_DrawSpriteData < 0 , 1 , 0x0e > , T_DrawSpriteData < 0 , 1 , 0x0f > , T_DrawSpriteData < 0 , 1 , 0x10 > , T_DrawSpriteData < 0 , 1 , 0x11 > , T_DrawSpriteData < 0 , 1 , 0x12 > , T_DrawSpriteData < 0 , 1 , 0x13 > , T_DrawSpriteData < 0 , 1 , 0x14 > , T_DrawSpriteData < 0 , 1 , 0x15 > , T_DrawSpriteData < 0 , 1 , 0x16 > , T_DrawSpriteData < 0 , 1 , 0x17 > , T_DrawSpriteData < 0 , 1 , 0x18 > , T_DrawSpriteData < 0 , 1 , 0x19 > , T_DrawSpriteData < 0 , 1 , 0x1a > , T_DrawSpriteData < 0 , 1 , 0x1b > , T_DrawSpriteData < 0 , 1 , 0x1c > , T_DrawSpriteData < 0 , 1 , 0x1d > , T_DrawSpriteData < 0 , 1 , 0x1e > , T_DrawSpriteData < 0 , 1 , 0x1f > , T_DrawSpriteData < 0 , 1 , 0x20 > , T_DrawSpriteData < 0 , 1 , 0x21 > , T_DrawSpriteData < 0 , 1 , 0x22 > , T_DrawSpriteData < 0 , 1 , 0x23 > , T_DrawSpriteData < 0 , 1 , 0x24 > , T_DrawSpriteData < 0 , 1 , 0x25 > , T_DrawSpriteData < 0 , 1 , 0x26 > , T_DrawSpriteData < 0 , 1 , 0x27 > , T_DrawSpriteData < 0 , 1 , 0x28 > , T_DrawSpriteData < 0 , 1 , 0x29 > , T_DrawSpriteData < 0 , 1 , 0x2a > , T_DrawSpriteData < 0 , 1 , 0x2b > , T_DrawSpriteData < 0 , 1 , 0x2c > , T_DrawSpriteData < 0 , 1 , 0x2d > , T_DrawSpriteData < 0 , 1 , 0x2e > , T_DrawSpriteData < 0 , 1 , 0x2f > , T_DrawSpriteData < 0 , 1 , 0x30 > , T_DrawSpriteData < 0 , 1 , 0x31 > , T_DrawSpriteData < 0 , 1 , 0x32 > , T_DrawSpriteData < 0 , 1 , 0x33 > , T_DrawSpriteData < 0 , 1 , 0x34 > , T_DrawSpriteData < 0 , 1 , 0x35 > , T_DrawSpriteData < 0 , 1 , 0x36 > , T_DrawSpriteData < 0 , 1 , 0x37 > , T_DrawSpriteData < 0 , 1 , 0x38 > , T_DrawSpriteData < 0 , 1 , 0x39 > , T_DrawSpriteData < 0 , 1 , 0x3a > , T_DrawSpriteData < 0 , 1 , 0x3b > , T_DrawSpriteData < 0 , 1 , 0x3c > , T_DrawSpriteData < 0 , 1 , 0x3d > , T_DrawSpriteData < 0 , 1 , 0x3e > , T_DrawSpriteData < 0 , 1 , 0x3f > } ,
} ,
{
{ T_DrawSpriteData < 1 , 0 , 0x00 > , T_DrawSpriteData < 1 , 0 , 0x01 > , T_DrawSpriteData < 1 , 0 , 0x02 > , T_DrawSpriteData < 1 , 0 , 0x03 > , T_DrawSpriteData < 1 , 0 , 0x04 > , T_DrawSpriteData < 1 , 0 , 0x05 > , T_DrawSpriteData < 1 , 0 , 0x06 > , T_DrawSpriteData < 1 , 0 , 0x07 > , T_DrawSpriteData < 1 , 0 , 0x08 > , T_DrawSpriteData < 1 , 0 , 0x09 > , T_DrawSpriteData < 1 , 0 , 0x0a > , T_DrawSpriteData < 1 , 0 , 0x0b > , T_DrawSpriteData < 1 , 0 , 0x0c > , T_DrawSpriteData < 1 , 0 , 0x0d > , T_DrawSpriteData < 1 , 0 , 0x0e > , T_DrawSpriteData < 1 , 0 , 0x0f > , T_DrawSpriteData < 1 , 0 , 0x10 > , T_DrawSpriteData < 1 , 0 , 0x11 > , T_DrawSpriteData < 1 , 0 , 0x12 > , T_DrawSpriteData < 1 , 0 , 0x13 > , T_DrawSpriteData < 1 , 0 , 0x14 > , T_DrawSpriteData < 1 , 0 , 0x15 > , T_DrawSpriteData < 1 , 0 , 0x16 > , T_DrawSpriteData < 1 , 0 , 0x17 > , T_DrawSpriteData < 1 , 0 , 0x18 > , T_DrawSpriteData < 1 , 0 , 0x19 > , T_DrawSpriteData < 1 , 0 , 0x1a > , T_DrawSpriteData < 1 , 0 , 0x1b > , T_DrawSpriteData < 1 , 0 , 0x1c > , T_DrawSpriteData < 1 , 0 , 0x1d > , T_DrawSpriteData < 1 , 0 , 0x1e > , T_DrawSpriteData < 1 , 0 , 0x1f > , T_DrawSpriteData < 1 , 0 , 0x20 > , T_DrawSpriteData < 1 , 0 , 0x21 > , T_DrawSpriteData < 1 , 0 , 0x22 > , T_DrawSpriteData < 1 , 0 , 0x23 > , T_DrawSpriteData < 1 , 0 , 0x24 > , T_DrawSpriteData < 1 , 0 , 0x25 > , T_DrawSpriteData < 1 , 0 , 0x26 > , T_DrawSpriteData < 1 , 0 , 0x27 > , T_DrawSpriteData < 1 , 0 , 0x28 > , T_DrawSpriteData < 1 , 0 , 0x29 > , T_DrawSpriteData < 1 , 0 , 0x2a > , T_DrawSpriteData < 1 , 0 , 0x2b > , T_DrawSpriteData < 1 , 0 , 0x2c > , T_DrawSpriteData < 1 , 0 , 0x2d > , T_DrawSpriteData < 1 , 0 , 0x2e > , T_DrawSpriteData < 1 , 0 , 0x2f > , T_DrawSpriteData < 1 , 0 , 0x30 > , T_DrawSpriteData < 1 , 0 , 0x31 > , T_DrawSpriteData < 1 , 0 , 0x32 > , T_DrawSpriteData < 1 , 0 , 0x33 > , T_DrawSpriteData < 1 , 0 , 0x34 > , T_DrawSpriteData < 1 , 0 , 0x35 > , T_DrawSpriteData < 1 , 0 , 0x36 > , T_DrawSpriteData < 1 , 0 , 0x37 > , T_DrawSpriteData < 1 , 0 , 0x38 > , T_DrawSpriteData < 1 , 0 , 0x39 > , T_DrawSpriteData < 1 , 0 , 0x3a > , T_DrawSpriteData < 1 , 0 , 0x3b > , T_DrawSpriteData < 1 , 0 , 0x3c > , T_DrawSpriteData < 1 , 0 , 0x3d > , T_DrawSpriteData < 1 , 0 , 0x3e > , T_DrawSpriteData < 1 , 0 , 0x3f > } ,
{ T_DrawSpriteData < 1 , 1 , 0x00 > , T_DrawSpriteData < 1 , 1 , 0x01 > , T_DrawSpriteData < 1 , 1 , 0x02 > , T_DrawSpriteData < 1 , 1 , 0x03 > , T_DrawSpriteData < 1 , 1 , 0x04 > , T_DrawSpriteData < 1 , 1 , 0x05 > , T_DrawSpriteData < 1 , 1 , 0x06 > , T_DrawSpriteData < 1 , 1 , 0x07 > , T_DrawSpriteData < 1 , 1 , 0x08 > , T_DrawSpriteData < 1 , 1 , 0x09 > , T_DrawSpriteData < 1 , 1 , 0x0a > , T_DrawSpriteData < 1 , 1 , 0x0b > , T_DrawSpriteData < 1 , 1 , 0x0c > , T_DrawSpriteData < 1 , 1 , 0x0d > , T_DrawSpriteData < 1 , 1 , 0x0e > , T_DrawSpriteData < 1 , 1 , 0x0f > , T_DrawSpriteData < 1 , 1 , 0x10 > , T_DrawSpriteData < 1 , 1 , 0x11 > , T_DrawSpriteData < 1 , 1 , 0x12 > , T_DrawSpriteData < 1 , 1 , 0x13 > , T_DrawSpriteData < 1 , 1 , 0x14 > , T_DrawSpriteData < 1 , 1 , 0x15 > , T_DrawSpriteData < 1 , 1 , 0x16 > , T_DrawSpriteData < 1 , 1 , 0x17 > , T_DrawSpriteData < 1 , 1 , 0x18 > , T_DrawSpriteData < 1 , 1 , 0x19 > , T_DrawSpriteData < 1 , 1 , 0x1a > , T_DrawSpriteData < 1 , 1 , 0x1b > , T_DrawSpriteData < 1 , 1 , 0x1c > , T_DrawSpriteData < 1 , 1 , 0x1d > , T_DrawSpriteData < 1 , 1 , 0x1e > , T_DrawSpriteData < 1 , 1 , 0x1f > , T_DrawSpriteData < 1 , 1 , 0x20 > , T_DrawSpriteData < 1 , 1 , 0x21 > , T_DrawSpriteData < 1 , 1 , 0x22 > , T_DrawSpriteData < 1 , 1 , 0x23 > , T_DrawSpriteData < 1 , 1 , 0x24 > , T_DrawSpriteData < 1 , 1 , 0x25 > , T_DrawSpriteData < 1 , 1 , 0x26 > , T_DrawSpriteData < 1 , 1 , 0x27 > , T_DrawSpriteData < 1 , 1 , 0x28 > , T_DrawSpriteData < 1 , 1 , 0x29 > , T_DrawSpriteData < 1 , 1 , 0x2a > , T_DrawSpriteData < 1 , 1 , 0x2b > , T_DrawSpriteData < 1 , 1 , 0x2c > , T_DrawSpriteData < 1 , 1 , 0x2d > , T_DrawSpriteData < 1 , 1 , 0x2e > , T_DrawSpriteData < 1 , 1 , 0x2f > , T_DrawSpriteData < 1 , 1 , 0x30 > , T_DrawSpriteData < 1 , 1 , 0x31 > , T_DrawSpriteData < 1 , 1 , 0x32 > , T_DrawSpriteData < 1 , 1 , 0x33 > , T_DrawSpriteData < 1 , 1 , 0x34 > , T_DrawSpriteData < 1 , 1 , 0x35 > , T_DrawSpriteData < 1 , 1 , 0x36 > , T_DrawSpriteData < 1 , 1 , 0x37 > , T_DrawSpriteData < 1 , 1 , 0x38 > , T_DrawSpriteData < 1 , 1 , 0x39 > , T_DrawSpriteData < 1 , 1 , 0x3a > , T_DrawSpriteData < 1 , 1 , 0x3b > , T_DrawSpriteData < 1 , 1 , 0x3c > , T_DrawSpriteData < 1 , 1 , 0x3d > , T_DrawSpriteData < 1 , 1 , 0x3e > , T_DrawSpriteData < 1 , 1 , 0x3f > } ,
}
} ;
// Don't change these constants without also updating the template variable
// setup for the call into MixIt(and the contents of MixIt itself...).
enum
{
MIXIT_SPECIAL_NONE = 0x0 ,
MIXIT_SPECIAL_GRAD = 0x1 ,
MIXIT_SPECIAL_EXCC_CRAM0 = 0x2 ,
MIXIT_SPECIAL_EXCC_CRAM12 = 0x3 ,
MIXIT_SPECIAL_EXCC_LINE_CRAM0 = 0x4 ,
MIXIT_SPECIAL_EXCC_LINE_CRAM12 = 0x5
} ;
template < bool TA_rbg1en , unsigned TA_Special , bool TA_CCRTMD , bool TA_CCMD >
static void T_MixIt ( uint32 * target , const unsigned vdp2_line , const unsigned w , const uint32 back_rgb24 , const uint64 * blursrc )
{
//printf("MixIt: %d, %d, %d, %d\n", TA_rbg1en, TA_Special, TA_CCRTMD, TA_CCMD);
const uint32 * lclut = & ColorCache [ CurLCColor & ~ 0x7F ] ;
uint32 blurprev [ 2 ] ;
if ( TA_Special = = MIXIT_SPECIAL_GRAD )
blurprev [ 0 ] = blurprev [ 1 ] = * blursrc > > PIX_RGB_SHIFT ;
uint32 line_pix_l ;
{
line_pix_l = 0U < < PIX_ISRGB_SHIFT ;
line_pix_l | = LineColorCCRatio < < PIX_CCRATIO_SHIFT ;
line_pix_l | = ( ( CCCTL > > 5 ) & 1 ) < < PIX_CCE_SHIFT ;
line_pix_l | = ( ( CCCTL > > 5 ) & 1 ) < < PIX_LAYER_CCE_SHIFT ;
}
//
//
uint64 back_pix ;
{
back_pix = ( uint64 ) back_rgb24 < < PIX_RGB_SHIFT ;
back_pix | = 1U < < PIX_ISRGB_SHIFT ;
back_pix | = ( ( ColorOffsEn > > 5 ) & 1 ) < < PIX_COE_SHIFT ;
back_pix | = ( ( ColorOffsSel > > 5 ) & 1 ) < < PIX_COSEL_SHIFT ;
back_pix | = ( ( SDCTL > > 5 ) & 1 ) < < PIX_SHADEN_SHIFT ;
back_pix | = BackCCRatio < < PIX_CCRATIO_SHIFT ;
}
for ( uint32 i = 0 ; MDFN_LIKELY ( i < w ) ; i + + )
{
uint64 pix = back_pix ;
uint32 blurcake ;
//
// Listed from lowest priority to greatest priority when prio levels are equal(back pixel has prio level of 0,
// and should display on "top" of any other layers).
//
uint64 tmp_pix [ 8 ] =
{
( TA_rbg1en ? 0 : ( LB . nbg [ 3 ] + 8 ) [ i ] ) ,
( TA_rbg1en ? 0 : ( LB . nbg [ 2 ] + 8 ) [ i ] ) ,
( TA_rbg1en ? 0 : ( LB . nbg [ 1 ] + 8 ) [ i ] ) ,
( LB . nbg [ 0 ] + 8 ) [ i ] ,
LB . rbg0 [ i ] ,
LB . spr [ i ] ,
0 /*null pixel*/ ,
back_pix
} ;
uint64 pt ;
unsigned st ;
pt = 0x01ULL < < ( uint8 ) ( tmp_pix [ 0 ] > > PIX_PRIO_TEST_SHIFT ) ;
pt | = 0x02ULL < < ( uint8 ) ( tmp_pix [ 1 ] > > PIX_PRIO_TEST_SHIFT ) ;
pt | = 0x04ULL < < ( uint8 ) ( tmp_pix [ 2 ] > > PIX_PRIO_TEST_SHIFT ) ;
pt | = 0x08ULL < < ( uint8 ) ( tmp_pix [ 3 ] > > PIX_PRIO_TEST_SHIFT ) ;
pt | = 0x10ULL < < ( uint8 ) ( tmp_pix [ 4 ] > > PIX_PRIO_TEST_SHIFT ) ;
pt | = 0x20ULL < < ( uint8 ) ( tmp_pix [ 5 ] > > PIX_PRIO_TEST_SHIFT ) ;
pt | = 0xC0ULL ; // Back pixel(0x80) and null pixel(0x40)
st = 63 ^ MDFN_lzcount64_0UD ( pt ) ;
pt ^ = 1ULL < < st ;
pt | = 0x40 ; // Restore the null!
pix = tmp_pix [ st & 0x7 ] ;
if ( pix & ( 1U < < PIX_DOSHAD_SHIFT ) )
{
st = 63 ^ MDFN_lzcount64_0UD ( pt ) ;
pt ^ = 1ULL < < st ;
pt | = 0x40 ; // Restore the null!
pix = tmp_pix [ st & 0x7 ] ;
pix | = ( 1U < < PIX_DOSHAD_SHIFT ) ;
}
if ( TA_Special = = MIXIT_SPECIAL_GRAD )
{
const uint32 blurpie = blursrc [ i ] > > PIX_RGB_SHIFT ;
blurcake = ( ( blurprev [ 0 ] + blurprev [ 1 ] ) - ( ( blurprev [ 0 ] ^ blurprev [ 1 ] ) & 0x01010101 ) ) > > 1 ;
blurcake = ( ( blurcake + blurpie ) - ( ( blurcake ^ blurpie ) & 0x01010101 ) ) > > 1 ;
blurprev [ 0 ] = blurprev [ 1 ] ;
blurprev [ 1 ] = blurpie ;
}
//
// Color calculation
//
if ( pix & ( 1U < < PIX_CCE_SHIFT ) )
{
uint64 pix2 , pix3 ;
st = 63 ^ MDFN_lzcount64_0UD ( pt ) ;
pt ^ = 1ULL < < st ;
pt | = 0x40 ; // Restore the null!
pix2 = tmp_pix [ st & 0x7 ] ;
st = 63 ^ MDFN_lzcount64_0UD ( pt ) ;
pt ^ = 1ULL < < st ;
pt | = 0x40 ; // Restore the null!
pix3 = tmp_pix [ st & 0x7 ] ;
if ( TA_Special = = MIXIT_SPECIAL_GRAD )
{
if ( ( pix | pix2 ) & ( 1U < < PIX_GRAD_SHIFT ) )
pix2 = ( uint32 ) pix2 | ( ( uint64 ) blurcake < < PIX_RGB_SHIFT ) ; // Be sure to preserve the color calc ratio, at least.
}
else if ( pix & ( 1U < < PIX_LCE_SHIFT ) )
{
//
// Line color
//
const uint64 pix4 = pix3 ;
const uint32 line_pix_rgb = lclut [ LB . lc [ i ] ] ;
pix3 = pix2 ;
pix2 = line_pix_l | ( ( uint64 ) line_pix_rgb < < PIX_RGB_SHIFT ) ;
if ( TA_Special = = MIXIT_SPECIAL_EXCC_LINE_CRAM0 )
{
uint32 sec_rgb = line_pix_rgb ;
uint32 third_rgb = ( pix3 > > PIX_RGB_SHIFT ) ;
if ( pix3 & ( 1U < < PIX_LAYER_CCE_SHIFT ) )
third_rgb = ( third_rgb > > 1 ) & 0x7F7F7F ;
sec_rgb = ( ( sec_rgb + third_rgb ) - ( ( sec_rgb ^ third_rgb ) & 0x01010101 ) ) > > 1 ;
pix2 = ( uint32 ) pix2 | ( ( uint64 ) sec_rgb < < PIX_RGB_SHIFT ) ;
}
else if ( TA_Special = = MIXIT_SPECIAL_EXCC_LINE_CRAM12 )
{
uint32 sec_rgb = line_pix_rgb ;
uint32 third_rgb = ( pix3 > > PIX_RGB_SHIFT ) ;
if ( pix3 & ( 1U < < PIX_ISRGB_SHIFT ) )
{
if ( ( pix3 & ( 1U < < PIX_LAYER_CCE_SHIFT ) ) & & ( pix4 & ( 1U < < PIX_ISRGB_SHIFT ) ) )
{
const uint32 fourth_rgb = ( pix4 > > PIX_RGB_SHIFT ) ;
third_rgb = ( ( third_rgb + fourth_rgb ) - ( ( third_rgb ^ fourth_rgb ) & 0x01010101 ) ) > > 1 ;
}
sec_rgb = ( ( sec_rgb + third_rgb ) - ( ( sec_rgb ^ third_rgb ) & 0x01010101 ) ) > > 1 ;
pix2 = ( uint32 ) pix2 | ( ( uint64 ) sec_rgb < < PIX_RGB_SHIFT ) ;
}
}
}
else
{
if ( TA_Special = = MIXIT_SPECIAL_EXCC_CRAM0 | | TA_Special = = MIXIT_SPECIAL_EXCC_CRAM12 | | TA_Special = = MIXIT_SPECIAL_EXCC_LINE_CRAM0 | | TA_Special = = MIXIT_SPECIAL_EXCC_LINE_CRAM12 )
{
if ( pix2 & ( 1U < < PIX_LAYER_CCE_SHIFT ) )
{
if ( TA_Special = = MIXIT_SPECIAL_EXCC_CRAM0 | | TA_Special = = MIXIT_SPECIAL_EXCC_LINE_CRAM0 | | ( pix3 & ( 1U < < PIX_ISRGB_SHIFT ) ) )
{
uint32 sec_rgb = pix2 > > PIX_RGB_SHIFT ;
const uint32 third_rgb = ( pix3 > > PIX_RGB_SHIFT ) ;
sec_rgb = ( ( sec_rgb + third_rgb ) - ( ( sec_rgb ^ third_rgb ) & 0x01010101 ) ) > > 1 ;
pix2 = ( uint32 ) pix2 | ( ( uint64 ) sec_rgb < < PIX_RGB_SHIFT ) ;
}
}
}
}
uint32 fore_rgb = pix > > PIX_RGB_SHIFT ;
uint32 sec_rgb = pix2 > > PIX_RGB_SHIFT ;
uint32 new_rgb ;
if ( TA_CCMD ) // Ignore ratio, add as-is.
{
new_rgb = std : : min < unsigned > ( 0x0000FF , ( fore_rgb & 0x0000FF ) + ( sec_rgb & 0x0000FF ) ) ;
new_rgb | = std : : min < unsigned > ( 0x00FF00 , ( fore_rgb & 0x00FF00 ) + ( sec_rgb & 0x00FF00 ) ) ;
new_rgb | = std : : min < unsigned > ( 0xFF0000 , ( fore_rgb & 0xFF0000 ) + ( sec_rgb & 0xFF0000 ) ) ;
}
else
{
unsigned fore_ratio = ( ( uint32 ) ( TA_CCRTMD ? pix2 : pix ) > > PIX_CCRATIO_SHIFT ) ^ 0x1F ;
unsigned sec_ratio = 0x20 - fore_ratio ;
new_rgb = ( ( ( ( fore_rgb & 0x0000FF ) * fore_ratio ) + ( ( sec_rgb & 0x0000FF ) * sec_ratio ) ) > > 5 ) ;
new_rgb | = ( ( ( ( fore_rgb & 0x00FF00 ) * fore_ratio ) + ( ( sec_rgb & 0x00FF00 ) * sec_ratio ) ) > > 5 ) & 0x00FF00 ;
new_rgb | = ( ( ( ( fore_rgb & 0xFF0000 ) * fore_ratio ) + ( ( sec_rgb & 0xFF0000 ) * sec_ratio ) ) > > 5 ) & 0xFF0000 ;
}
pix = ( ( uint64 ) new_rgb < < 32 ) | ( uint32 ) pix ;
}
//
// Color offset
//
if ( pix & ( 1U < < PIX_COE_SHIFT ) )
{
const unsigned sel = ( pix > > PIX_COSEL_SHIFT ) & 1 ;
const uint32 rgb_tmp = pix > > PIX_RGB_SHIFT ;
int32 rt , gt , bt ;
rt = ColorOffs [ sel ] [ 0 ] + ( rgb_tmp & 0x000000FF ) ;
if ( rt < 0 ) rt = 0 ;
if ( rt & 0x00000100 ) rt = 0x000000FF ;
gt = ColorOffs [ sel ] [ 1 ] + ( rgb_tmp & 0x0000FF00 ) ;
if ( gt < 0 ) gt = 0 ;
if ( gt & 0x00010000 ) gt = 0x0000FF00 ;
bt = ColorOffs [ sel ] [ 2 ] + ( rgb_tmp & 0x00FF0000 ) ;
if ( bt < 0 ) bt = 0 ;
if ( bt & 0x01000000 ) bt = 0x00FF0000 ;
pix = ( uint32 ) pix | ( ( uint64 ) ( uint32 ) ( rt | gt | bt ) < < PIX_RGB_SHIFT ) ;
}
//
// Sprite shadow
//
if ( ( uint8 ) pix > = PIX_SHADHALVTEST8_VAL )
pix = ( uint32 ) pix | ( ( pix > > 1 ) & 0x7F7F7F00000000ULL ) ;
target [ i ] = pix > > PIX_RGB_SHIFT ;
}
}
//template<bool TA_rbg1en, unsigned TA_Special, bool TA_CCRTMD, bool TA_CCMD>
static void ( * MixIt [ 2 ] [ 6 ] [ 2 ] [ 2 ] ) ( uint32 * target , const unsigned vdp2_line , const unsigned w , const uint32 back_rgb24 , const uint64 * blursrc ) =
{
{ { { T_MixIt < 0 , 0 , 0 , 0 > , T_MixIt < 0 , 0 , 0 , 1 > , } , { T_MixIt < 0 , 0 , 1 , 0 > , T_MixIt < 0 , 0 , 1 , 1 > , } , } , { { T_MixIt < 0 , 1 , 0 , 0 > , T_MixIt < 0 , 1 , 0 , 1 > , } , { T_MixIt < 0 , 1 , 1 , 0 > , T_MixIt < 0 , 1 , 1 , 1 > , } , } , { { T_MixIt < 0 , 2 , 0 , 0 > , T_MixIt < 0 , 2 , 0 , 1 > , } , { T_MixIt < 0 , 2 , 1 , 0 > , T_MixIt < 0 , 2 , 1 , 1 > , } , } , { { T_MixIt < 0 , 3 , 0 , 0 > , T_MixIt < 0 , 3 , 0 , 1 > , } , { T_MixIt < 0 , 3 , 1 , 0 > , T_MixIt < 0 , 3 , 1 , 1 > , } , } , { { T_MixIt < 0 , 4 , 0 , 0 > , T_MixIt < 0 , 4 , 0 , 1 > , } , { T_MixIt < 0 , 4 , 1 , 0 > , T_MixIt < 0 , 4 , 1 , 1 > , } , } , { { T_MixIt < 0 , 5 , 0 , 0 > , T_MixIt < 0 , 5 , 0 , 1 > , } , { T_MixIt < 0 , 5 , 1 , 0 > , T_MixIt < 0 , 5 , 1 , 1 > , } , } , } ,
{ { { T_MixIt < 1 , 0 , 0 , 0 > , T_MixIt < 1 , 0 , 0 , 1 > , } , { T_MixIt < 1 , 0 , 1 , 0 > , T_MixIt < 1 , 0 , 1 , 1 > , } , } , { { T_MixIt < 1 , 1 , 0 , 0 > , T_MixIt < 1 , 1 , 0 , 1 > , } , { T_MixIt < 1 , 1 , 1 , 0 > , T_MixIt < 1 , 1 , 1 , 1 > , } , } , { { T_MixIt < 1 , 2 , 0 , 0 > , T_MixIt < 1 , 2 , 0 , 1 > , } , { T_MixIt < 1 , 2 , 1 , 0 > , T_MixIt < 1 , 2 , 1 , 1 > , } , } , { { T_MixIt < 1 , 3 , 0 , 0 > , T_MixIt < 1 , 3 , 0 , 1 > , } , { T_MixIt < 1 , 3 , 1 , 0 > , T_MixIt < 1 , 3 , 1 , 1 > , } , } , { { T_MixIt < 1 , 4 , 0 , 0 > , T_MixIt < 1 , 4 , 0 , 1 > , } , { T_MixIt < 1 , 4 , 1 , 0 > , T_MixIt < 1 , 4 , 1 , 1 > , } , } , { { T_MixIt < 1 , 5 , 0 , 0 > , T_MixIt < 1 , 5 , 0 , 1 > , } , { T_MixIt < 1 , 5 , 1 , 0 > , T_MixIt < 1 , 5 , 1 , 1 > , } , } , } ,
} ;
static int32 ApplyHBlend ( uint32 * const target , int32 w )
{
# define BHALF(m, n) ((((uint64)(m) + (n)) - (((m) ^ (n)) & 0x01010101)) >> 1)
assert ( w > = 4 ) ;
# if 1
if ( ! ( HRes & 0x2 ) )
{
target [ ( w - 1 ) * 2 + 1 ] = target [ w - 1 ] ;
target [ ( w - 1 ) * 2 + 0 ] = BHALF ( BHALF ( target [ w - 2 ] , target [ w - 1 ] ) , target [ w - 1 ] ) ;
for ( int32 x = w - 2 ; x > 0 ; x - - )
{
uint32 ptxm1 = target [ x - 1 ] ;
uint32 ptx = target [ x ] ;
uint32 ptxp1 = target [ x + 1 ] ;
uint32 ptxm1_ptx = BHALF ( ptxm1 , ptx ) ;
uint32 ptx_ptxp1 = BHALF ( ptx , ptxp1 ) ;
target [ x * 2 + 0 ] = BHALF ( ptxm1_ptx , ptx ) ;
target [ x * 2 + 1 ] = BHALF ( ptx_ptxp1 , ptx ) ;
}
target [ 1 ] = BHALF ( BHALF ( target [ 0 ] , target [ 1 ] ) , target [ 0 ] ) ;
target [ 0 ] = target [ 0 ] ;
return w < < 1 ;
}
else
# else
if ( ! ( HRes & 0x2 ) )
{
for ( int32 x = w - 1 ; x > = 0 ; x - - )
target [ x * 2 + 0 ] = target [ x * 2 + 1 ] = target [ x ] ;
w < < = 1 ;
}
# endif
{
uint32 a = target [ 0 ] ;
for ( int32 x = 0 ; x < w - 1 ; x + + )
{
uint32 b = target [ x ] ;
uint32 c = target [ x + 1 ] ;
uint32 ac = BHALF ( a , c ) ;
uint32 bac = BHALF ( b , ac ) ;
target [ x ] = bac ;
a = b ;
}
return w ;
}
# undef BHALF
}
2017-06-05 21:33:45 +00:00
static void ReorderRGB ( uint32 * target , const unsigned w )
2017-06-04 18:25:21 +00:00
{
2017-06-05 21:33:45 +00:00
const unsigned Rshift = 16 ;
const unsigned Gshift = 8 ;
const unsigned Bshift = 0 ;
2017-06-04 18:25:21 +00:00
assert ( ! ( w & 1 ) ) ;
uint32 * const bound = target + w ;
while ( MDFN_LIKELY ( target ! = bound ) )
{
const uint32 tmp0 = target [ 0 ] ;
const uint32 tmp1 = target [ 1 ] ;
target [ 0 ] = ( ( uint8 ) ( tmp0 > > 0 ) < < Rshift ) |
( ( uint8 ) ( tmp0 > > 8 ) < < Gshift ) |
( ( uint8 ) ( tmp0 > > 16 ) < < Bshift ) ;
target [ 1 ] = ( ( uint8 ) ( tmp1 > > 0 ) < < Rshift ) |
( ( uint8 ) ( tmp1 > > 8 ) < < Gshift ) |
( ( uint8 ) ( tmp1 > > 16 ) < < Bshift ) ;
target + = 2 ;
}
2017-06-05 21:33:45 +00:00
}
2017-06-04 18:25:21 +00:00
static NO_INLINE void DrawLine ( const uint16 out_line , const uint16 vdp2_line , const bool field )
{
uint32 * target ;
const int32 tvdw = ( ( ! CorrectAspect | | Clock28M ) ? 352 : 330 ) < < ( ( HRes & 0x2 ) > > 1 ) ;
const unsigned rbg_w = ( ( HRes & 0x1 ) ? 352 : 320 ) ;
const unsigned w = ( ( HRes & 0x1 ) ? 352 : 320 ) < < ( ( HRes & 0x2 ) > > 1 ) ;
const int32 tvxo = std : : max < int32 > ( 0 , ( int32 ) ( tvdw - w ) > > 1 ) ;
uint32 back_rgb24 ;
uint32 border_ncf ;
target = espec - > pixels + out_line * espec - > pitch32 ;
espec - > LineWidths [ out_line ] = tvdw ;
if ( ! ShowHOverscan )
{
const int32 ntdw = tvdw * 1024 / 1056 ;
const int32 tadj = std : : max < int32 > ( 0 , espec - > x - ( ( tvdw - ntdw ) > > 1 ) ) ;
//if(out_line == 100)
// printf("tvdw=%d, ntdw=%d, tadj=%d --- tvdw+tadj=%d\n", tvdw, ntdw, tadj, tvdw + tadj);
assert ( ( tvdw + tadj ) < = 704 ) ;
target + = tadj ;
espec - > LineWidths [ out_line ] = ntdw ;
}
//
// FIXME: Timing
//
if ( vdp2_line = = 0 )
{
CurBackTabAddr = ( BKTA & 0x7FFFF ) + ( ( BKTA & 0x80000000 ) & & InterlaceMode = = IM_DOUBLE & & field ) ;
CurLCTabAddr = ( LCTA & 0x7FFFF ) + ( ( LCTA & 0x80000000 ) & & InterlaceMode = = IM_DOUBLE & & field ) ;
for ( unsigned n = 0 ; n < 2 ; n + + )
{
YCoordAccum [ n ] = ( InterlaceMode = = IM_DOUBLE & & field ) ? YCoordInc [ n ] : 0 ;
CurLSA [ n ] = LineScrollAddr [ n ] ;
if ( InterlaceMode = = IM_DOUBLE & & field )
{
const uint8 sc = ( SCRCTL > > ( n < < 3 ) ) ;
CurLSA [ n ] + = ( ( bool ) ( sc & 0x2 ) + ( bool ) ( sc & 0x4 ) + ( bool ) ( sc & 0x8 ) ) < < 1 ;
}
//
//
NBG23_YCounter [ n & 1 ] = YScrollI [ 2 + n ] ;
}
for ( unsigned d = 0 ; d < 2 ; d + + )
{
Window [ d ] . CurLineWinAddr = Window [ d ] . LineWinAddr ;
if ( InterlaceMode = = IM_DOUBLE & & field )
Window [ d ] . CurLineWinAddr + = 2 ;
}
MosaicVCount = 0 ;
}
if ( vdp2_line ! = 0xFFFF )
{
CurBackColor = VRAM [ CurBackTabAddr & 0x3FFFF ] & 0x7FFF ;
if ( BKTA & 0x80000000 )
CurBackTabAddr + = 1 < < ( InterlaceMode = = IM_DOUBLE ) ;
//
CurLCColor = VRAM [ CurLCTabAddr & 0x3FFFF ] & 0x07FF ;
if ( LCTA & 0x80000000 )
CurLCTabAddr + = 1 < < ( InterlaceMode = = IM_DOUBLE ) ;
}
back_rgb24 = rgb15_to_rgb24 ( CurBackColor ) ;
if ( BorderMode )
2017-06-05 21:33:45 +00:00
border_ncf = back_rgb24 & 0xff00 | back_rgb24 < < 16 & & 0xff0000 | back_rgb24 > > 16 & 0xff ;
2017-06-04 18:25:21 +00:00
else
border_ncf = 0 ;
if ( vdp2_line = = 0xFFFF )
{
for ( int32 i = 0 ; i < tvdw ; i + + )
target [ i ] = border_ncf ;
}
else
{
//
// Line scroll
//
unsigned ls_comp_line = vdp2_line ;
for ( unsigned n = 0 ; n < 2 ; n + + )
{
const uint8 sc = ( SCRCTL > > ( n < < 3 ) ) ;
const uint8 lss = ( ( sc > > 4 ) & 0x3 ) ;
if ( ( ls_comp_line & ( ( 1 < < lss ) - 1 ) ) = = 0 )
{
if ( sc & 0x2 ) // X
{
CurXScrollIF [ n ] = ( VRAM [ CurLSA [ n ] & 0x3FFFF ] & 0x7FF ) < < 8 ;
CurLSA [ n ] + + ;
CurXScrollIF [ n ] | = VRAM [ CurLSA [ n ] & 0x3FFFF ] > > 8 ;
CurLSA [ n ] + + ;
CurXScrollIF [ n ] + = ( XScrollI [ n ] < < 8 ) + XScrollF [ n ] ;
}
if ( sc & 0x4 ) // Y
{
YCoordAccum [ n ] = 0 ; // Don't (InterlaceMode == IM_DOUBLE && field)
//
CurYScrollIF [ n ] = ( VRAM [ CurLSA [ n ] & 0x3FFFF ] & 0x7FF ) < < 8 ;
CurLSA [ n ] + + ;
CurYScrollIF [ n ] | = VRAM [ CurLSA [ n ] & 0x3FFFF ] > > 8 ;
CurLSA [ n ] + + ;
CurYScrollIF [ n ] + = ( YScrollI [ n ] < < 8 ) + YScrollF [ n ] ;
//printf("%d %d %08x: %08x \n", vdp2_line, n, CurLSA[n], CurYScrollIF[n]);
}
if ( sc & 0x8 ) // X zoom
{
CurXCoordInc [ n ] = ( VRAM [ CurLSA [ n ] & 0x3FFFF ] & 0x7 ) < < 8 ;
CurLSA [ n ] + + ;
CurXCoordInc [ n ] | = VRAM [ CurLSA [ n ] & 0x3FFFF ] > > 8 ;
CurLSA [ n ] + + ;
}
if ( InterlaceMode = = IM_DOUBLE )
CurLSA [ n ] + = ( ( bool ) ( sc & 0x2 ) + ( bool ) ( sc & 0x4 ) + ( bool ) ( sc & 0x8 ) ) < < 1 ;
}
if ( ! ( sc & 0x2 ) )
CurXScrollIF [ n ] = ( XScrollI [ n ] < < 8 ) + XScrollF [ n ] ;
if ( ! ( sc & 0x4 ) )
CurYScrollIF [ n ] = ( YScrollI [ n ] < < 8 ) + YScrollF [ n ] ;
if ( ! ( sc & 0x8 ) )
CurXCoordInc [ n ] = XCoordInc [ n ] ;
}
//
// Line Window
//
{
int32 w_ycomp_line ;
if ( InterlaceMode = = IM_DOUBLE )
w_ycomp_line = ( vdp2_line < < 1 ) + field ;
else
w_ycomp_line = vdp2_line ;
for ( unsigned d = 0 ; d < 2 ; d + + )
{
int32 ys = Window [ d ] . YStart , ye = Window [ d ] . YEnd ;
if ( Window [ d ] . LineWinEn )
{
const uint16 * vrt = & VRAM [ Window [ d ] . CurLineWinAddr & 0x3FFFE ] ;
Window [ d ] . XStart = vrt [ 0 ] & 0x3FF ;
Window [ d ] . XEnd = vrt [ 1 ] & 0x3FF ;
//printf("LWin %d, %d(%08x): %04x %04x\n", vdp2_line, d, Window[d].CurLineWinAddr & 0x3FFFE, vrt[0], vrt[1]);
}
//
//
//
int32 xs = Window [ d ] . XStart , xe = Window [ d ] . XEnd ;
// FIXME: Kludge, until we can figure out what's going on.
if ( xs > = 0x380 )
xs = 0 ;
// FIXME: Kludge, until we can figure out what's going on.
if ( xe > = 0x380 )
{
xs = 2 ;
xe = 0 ;
}
if ( ! ( HRes & 0x2 ) )
{
xs > > = 1 ;
xe > > = 1 ;
}
Window [ d ] . CurXStart = xs ;
Window [ d ] . CurXEnd = xe ;
Window [ d ] . CurLineWinAddr + = 2 < < ( InterlaceMode = = IM_DOUBLE ) ;
if ( InterlaceMode ! = IM_DOUBLE )
{
ys > > = 1 ;
ye > > = 1 ;
}
Window [ d ] . YMet = ( w_ycomp_line > = Window [ d ] . YStart ) & ( w_ycomp_line < = Window [ d ] . YEnd ) ;
//
//
//
}
//
//
//
WinPieces [ 0 ] = Window [ 0 ] . CurXStart ;
WinPieces [ 1 ] = Window [ 0 ] . CurXEnd + 1 ;
WinPieces [ 2 ] = Window [ 1 ] . CurXStart ;
WinPieces [ 3 ] = Window [ 1 ] . CurXEnd + 1 ;
WinPieces [ 4 ] = w ;
for ( unsigned piece = 0 ; piece < WinPieces . size ( ) ; piece + + )
WinPieces [ piece ] = std : : min < unsigned > ( w , WinPieces [ piece ] ) ; // Almost forgot to do this...
std : : sort ( WinPieces . begin ( ) , WinPieces . end ( ) ) ;
}
//
//
//
if ( vdp2_line = = 64 )
{
//printf("%d:%d, %d:%d (%d) --- %d:%d, %d:%d (%d)\n", Window[0].XStart, Window[0].YStart, Window[0].XEnd, Window[0].YEnd, Window[0].LineWinEn, Window[1].XStart, Window[1].YStart, Window[1].XEnd, Window[1].YEnd, Window[1].LineWinEn);
//printf("SPCTL_Low: %02x, SDCTL: %03x, SpriteCCCond: %01x, CCNum: %01x -- %01x %01x %01x %01x %01x %01x %01x %01x \n", SPCTL_Low, SDCTL, SpriteCCCond, SpriteCCNum, SpriteCCRatio[0], SpriteCCRatio[1], SpriteCCRatio[2], SpriteCCRatio[3], SpriteCCRatio[4], SpriteCCRatio[5], SpriteCCRatio[6], SpriteCCRatio[7]);
//printf("WinControl[WINLAYER_CC]=%02x\n", WinControl[WINLAYER_CC]);
}
//
// Process sprite data before NBG0-3 and RBG0-1, but defer applying the window until after NBG and RBG are handled(so the sprite window
// bit in the sprite linebuffer data isn't trashed prematurely).
//
if ( MDFN_LIKELY ( UserLayerEnableMask & ( 1U < < 6 ) ) )
{
MakeSpriteCCLUT ( ) ;
DrawSpriteData [ ( HRes & 0x2 ) > > 0x1 ] [ ( SDCTL > > 8 ) & 0x1 ] [ SPCTL_Low ] ( LIB [ vdp2_line ] . vdp1_line , LIB [ vdp2_line ] . vdp1_hires8 , w ) ;
}
else
MDFN_FastArraySet ( LB . spr , 0 , w ) ;
//
//
//
//
//
//
//
if ( BGON & 0x30 )
{
MDFN_FastArraySet ( LB . lc , CurLCColor & 0x7F , rbg_w ) ;
SetupRotVars ( LIB [ vdp2_line ] . rv , rbg_w ) ;
if ( HRes & 0x2 )
Doubleize ( LB . lc , rbg_w ) ;
// RBG0
if ( MDFN_LIKELY ( UserLayerEnableMask & 0x10 ) )
{
const bool igntp = ( BGON > > 12 ) & 1 ;
const bool bmen = ( CHCTLB > > 9 ) & 1 ;
const unsigned colornum = std : : min < unsigned > ( 4 , ( CHCTLB > > 12 ) & 0x7 ) ; // TODO: Test 5 ... 7
const unsigned priomode = ( SFPRMD > > 8 ) & 0x3 ;
const unsigned ccmode = ( CCCTL & 0x10 ) ? ( ( SFCCMD > > 8 ) & 0x3 ) : 0 ;
const uint32 prio = RBG0PrioNum ;
uint32 pix_base_or ;
pix_base_or = ( ( colornum > = 3 ) < < PIX_ISRGB_SHIFT ) ;
pix_base_or | = ( ( ColorOffsEn > > 4 ) & 1 ) < < PIX_COE_SHIFT ;
pix_base_or | = ( ( ColorOffsSel > > 4 ) & 1 ) < < PIX_COSEL_SHIFT ;
pix_base_or | = ( ( LineColorEn > > 4 ) & 1 ) < < PIX_LCE_SHIFT ;
pix_base_or | = RBG0CCRatio < < PIX_CCRATIO_SHIFT ;
pix_base_or | = ( ( ( CCCTL > > 12 ) & 0x7 ) = = 0x1 ) < < PIX_GRAD_SHIFT ;
pix_base_or | = ( ( CCCTL > > 4 ) & 1 ) < < PIX_LAYER_CCE_SHIFT ;
pix_base_or | = ( ( SDCTL > > 4 ) & 1 ) < < PIX_SHADEN_SHIFT ;
if ( ccmode = = 0 )
pix_base_or | = ( ( CCCTL > > 4 ) & 1 ) < < PIX_CCE_SHIFT ;
if ( priomode > = 1 )
pix_base_or | = ( ( prio & ~ 1 ) < < PIX_PRIO_SHIFT ) ;
else
pix_base_or | = ( prio < < PIX_PRIO_SHIFT ) ;
DrawRBG [ bmen ] [ colornum ] [ igntp ] [ priomode % 3 ] [ ccmode ] ( 0 , LB . rbg0 , rbg_w , pix_base_or ) ;
RBGPP ( 4 , LB . rbg0 , rbg_w ) ;
}
else
MDFN_FastArraySet ( LB . rbg0 , 0 , w ) ;
// RBG1
if ( BGON & UserLayerEnableMask & 0x20 )
{
const bool igntp = ( BGON > > 8 ) & 1 ;
const unsigned colornum = std : : min < unsigned > ( 4 , ( CHCTLA > > 4 ) & 0x7 ) ; // TODO: Test 5 ... 7
const unsigned priomode = ( SFPRMD > > 0 ) & 0x3 ;
const unsigned ccmode = ( CCCTL & 0x01 ) ? ( ( SFCCMD > > 0 ) & 0x3 ) : 0 ;
const uint32 prio = NBGPrioNum [ 0 ] ;
uint32 pix_base_or ;
pix_base_or = ( false < < PIX_ISRGB_SHIFT ) ;
pix_base_or | = ( ( ColorOffsEn > > 0 ) & 1 ) < < PIX_COE_SHIFT ;
pix_base_or | = ( ( ColorOffsSel > > 0 ) & 1 ) < < PIX_COSEL_SHIFT ;
pix_base_or | = ( ( LineColorEn > > 0 ) & 1 ) < < PIX_LCE_SHIFT ;
pix_base_or | = NBGCCRatio [ 0 ] < < PIX_CCRATIO_SHIFT ;
pix_base_or | = ( ( ( CCCTL > > 12 ) & 0x7 ) = = 0x2 ) < < PIX_GRAD_SHIFT ;
pix_base_or | = ( ( CCCTL > > 0 ) & 1 ) < < PIX_LAYER_CCE_SHIFT ;
pix_base_or | = ( ( SDCTL > > 0 ) & 1 ) < < PIX_SHADEN_SHIFT ;
if ( ccmode = = 0 )
pix_base_or | = ( ( CCCTL > > 0 ) & 1 ) < < PIX_CCE_SHIFT ;
if ( priomode > = 1 )
pix_base_or | = ( ( prio & ~ 1 ) < < PIX_PRIO_SHIFT ) ;
else
pix_base_or | = ( prio < < PIX_PRIO_SHIFT ) ;
MDFN_FastArraySet ( LB . rotabsel , 1 , rbg_w ) ;
DrawRBG [ false ] [ colornum ] [ igntp ] [ priomode % 3 ] [ ccmode ] ( 1 , LB . nbg [ 0 ] + 8 , rbg_w , pix_base_or ) ;
RBGPP ( 0 , LB . nbg [ 0 ] + 8 , rbg_w ) ;
}
else if ( BGON & 0x20 )
MDFN_FastArraySet ( LB . nbg [ 0 ] + 8 , 0 , w ) ;
}
else
{
MDFN_FastArraySet ( LB . lc , CurLCColor & 0x7F , w ) ;
MDFN_FastArraySet ( LB . rbg0 , 0 , w ) ;
}
//
//
//
for ( unsigned n = 0 ; n < 4 ; n + + )
{
if ( ! MosaicVCount | | ! ( MZCTL & ( 1U < < n ) ) )
{
if ( n < 2 )
{
MosEff_YCoordAccum [ n ] = YCoordAccum [ n ] ; // Don't + (InterlaceMode == IM_DOUBLE && field)
}
else
{
MosEff_NBG23_YCounter [ n & 1 ] = NBG23_YCounter [ n & 1 ] + ( InterlaceMode = = IM_DOUBLE & & field ) ;
}
}
}
if ( SCRCTL & 0x0101 )
FetchVCScroll ( w ) ; // Call after handling line scroll, and before DrawNBG() stuff
if ( ! ( BGON & 0x20 ) )
{
for ( unsigned n = 0 ; n < 4 ; n + + )
{
if ( ( ( BGON > > n ) & 1 ) & & MDFN_LIKELY ( ( UserLayerEnableMask > > n ) & 1 ) )
{
const bool igntp = ( BGON > > ( n + 8 ) ) & 1 ;
bool bmen = false ;
unsigned colornum ;
unsigned priomode ;
unsigned ccmode ;
if ( n < 2 )
{
const unsigned nshift = ( n & 1 ) < < 3 ;
bmen = ( CHCTLA > > ( 1 + nshift ) ) & 1 ;
colornum = ( CHCTLA > > ( 4 + nshift ) ) & ( n ? 0x3 : 0x7 ) ;
}
else // n >= 2
{
const unsigned nshift = ( n & 1 ) < < 2 ;
colornum = ( CHCTLB > > ( 1 + nshift ) ) & 1 ;
}
if ( colornum > 4 ) // TODO: test 5 ... 7
colornum = 4 ;
priomode = ( SFPRMD > > ( n < < 1 ) ) & 0x3 ;
ccmode = ( SFCCMD > > ( n < < 1 ) ) & 0x3 ;
if ( ! ( ( CCCTL > > n ) & 1 ) )
ccmode = 0 ;
//
//
const uint32 prio = NBGPrioNum [ n ] ;
uint32 pix_base_or ;
pix_base_or = ( ( colornum > = 3 ) < < PIX_ISRGB_SHIFT ) ;
pix_base_or | = ( ( ColorOffsEn > > n ) & 1 ) < < PIX_COE_SHIFT ;
pix_base_or | = ( ( ColorOffsSel > > n ) & 1 ) < < PIX_COSEL_SHIFT ;
pix_base_or | = ( ( LineColorEn > > n ) & 1 ) < < PIX_LCE_SHIFT ;
pix_base_or | = NBGCCRatio [ n ] < < PIX_CCRATIO_SHIFT ;
pix_base_or | = ( ( ( CCCTL > > 12 ) & 0x7 ) = = ( 3 + n - ! n ) ) < < PIX_GRAD_SHIFT ;
pix_base_or | = ( ( CCCTL > > n ) & 1 ) < < PIX_LAYER_CCE_SHIFT ;
pix_base_or | = ( ( SDCTL > > n ) & 1 ) < < PIX_SHADEN_SHIFT ;
if ( ccmode = = 0 )
pix_base_or | = ( ( CCCTL > > n ) & 1 ) < < PIX_CCE_SHIFT ;
if ( priomode > = 1 )
pix_base_or | = ( ( prio & ~ 1 ) < < PIX_PRIO_SHIFT ) ;
else
pix_base_or | = ( prio < < PIX_PRIO_SHIFT ) ;
if ( n < 2 )
DrawNBG [ bmen ] [ colornum ] [ igntp ] [ priomode % 3 ] [ ccmode ] ( n , LB . nbg [ n ] + 8 , w , pix_base_or ) ;
else
DrawNBG23 [ colornum ] [ igntp ] [ priomode % 3 ] [ ccmode ] ( n , LB . nbg [ n ] + 8 , w , pix_base_or ) ;
ApplyHMosaic ( n , LB . nbg [ n ] + 8 , w ) ;
ApplyWin ( n , LB . nbg [ n ] + 8 ) ;
}
else
MDFN_FastArraySet ( LB . nbg [ n ] + 8 , 0 , w ) ;
}
}
//
//
//
//
//
// Apply window to sprite linebuffer after BG layers have windows applied.
ApplyWin ( WINLAYER_SPRITE , LB . spr ) ;
//
for ( int32 i = 0 ; i < tvxo ; i + + )
target [ i ] = border_ncf ;
for ( int32 i = tvxo + w ; i < tvdw ; i + + )
target [ i ] = border_ncf ;
{
const bool rbg1en = ( bool ) ( BGON & 0x20 ) ;
unsigned special = MIXIT_SPECIAL_NONE ;
const bool CCRTMD = ( bool ) ( CCCTL & 0x0200 ) ;
const bool CCMD = ( bool ) ( CCCTL & 0x0100 ) ;
static const uint64 * blurremap [ 8 ] = { LB . spr , LB . rbg0 , LB . nbg [ 0 ] + 8 , /*Dummy:*/ LB . spr ,
LB . nbg [ 1 ] + 8 , LB . nbg [ 2 ] + 8 , LB . nbg [ 3 ] + 8 , /*Dummy:*/ LB . spr
} ;
const uint64 * blursrc = blurremap [ ( CCCTL > > 12 ) & 0x7 ] ;
if ( ! ( HRes & 0x6 ) )
{
if ( CCCTL & 0x8000 )
{
if ( CRAM_Mode = = 0 )
special = MIXIT_SPECIAL_GRAD ;
}
else if ( CCCTL & 0x0400 )
{
special = 0x2 ;
special + = ( bool ) CRAM_Mode ;
special + = ( CCCTL > > 4 ) & 0x2 ;
}
}
MixIt [ rbg1en ] [ special ] [ CCRTMD ] [ CCMD ] ( target + tvxo , vdp2_line , w , back_rgb24 , blursrc ) ;
2017-06-05 21:33:45 +00:00
ReorderRGB ( target + tvxo , w ) ;
2017-06-04 18:25:21 +00:00
}
//
//
//
// FIXME: Timing
//
for ( unsigned n = 0 ; n < 2 ; n + + )
{
YCoordAccum [ n ] + = YCoordInc [ n ] < < ( InterlaceMode = = IM_DOUBLE ) ;
NBG23_YCounter [ n & 1 ] + = 1 < < ( InterlaceMode = = IM_DOUBLE ) ;
}
if ( MosaicVCount > = ( ( MZCTL > > 12 ) & 0xF ) )
MosaicVCount = 0 ;
else
MosaicVCount + + ;
}
//
//
//
if ( DoHBlend )
{
espec - > LineWidths [ out_line ] = ApplyHBlend ( espec - > pixels + out_line * espec - > pitch32 + espec - > x , espec - > LineWidths [ out_line ] ) ;
// Kind of late, but meh. ;p
assert ( ( espec - > x + espec - > LineWidths [ out_line ] ) < = 704 ) ;
}
}
enum
{
COMMAND_WRITE8 = 0 ,
COMMAND_WRITE16 ,
COMMAND_DRAW_LINE ,
COMMAND_SET_LEM ,
COMMAND_RESET ,
COMMAND_EXIT
} ;
static int32 LastDrawnLine ;
static INLINE void WWQ ( uint16 command , uint32 arg32 = 0 , uint16 arg16 = 0 )
{
switch ( command )
{
case COMMAND_WRITE8 :
MemW < uint8 > ( arg32 , arg16 ) ;
break ;
case COMMAND_WRITE16 :
MemW < uint16 > ( arg32 , arg16 ) ;
break ;
case COMMAND_DRAW_LINE :
//for(unsigned i = 0; i < 2; i++)
DrawLine ( ( uint16 ) arg32 , arg32 > > 16 , arg16 ) ;
//
LastDrawnLine = ( uint16 ) arg32 ;
break ;
case COMMAND_RESET :
Reset ( arg32 ) ;
break ;
case COMMAND_SET_LEM :
UserLayerEnableMask = arg32 ;
break ;
}
}
//
//
//
//
//
void VDP2REND_Init ( const bool IsPAL )
{
PAL = IsPAL ;
VisibleLines = PAL ? 288 : 240 ;
//
UserLayerEnableMask = ~ 0U ;
}
void VDP2REND_StartFrame ( EmulateSpecStruct * espec_arg , const bool clock28m , const int SurfInterlaceField )
{
OutLineCounter = 0 ;
Clock28M = clock28m ;
espec = espec_arg ;
if ( SurfInterlaceField > = 0 )
{
espec - > LineWidths [ 0 ] = 0 ;
espec - > InterlaceOn = true ;
espec - > InterlaceField = SurfInterlaceField ;
}
else
espec - > InterlaceOn = false ;
espec - > x = ( ShowHOverscan ? 0 : 10 ) ;
espec - > y = LineVisFirst < < espec - > InterlaceOn ;
espec - > h = ( LineVisLast + 1 - LineVisFirst ) < < espec - > InterlaceOn ;
}
void VDP2REND_EndFrame ( void )
{
if ( OutLineCounter < VisibleLines )
{
//printf("OutLineCounter(%d) < VisibleLines(%d)\n", OutLineCounter, VisibleLines);
do
{
uint16 out_line = OutLineCounter ;
uint32 * target ;
if ( espec - > InterlaceOn )
out_line = ( out_line < < 1 ) | espec - > InterlaceField ;
target = espec - > pixels + out_line * espec - > pitch32 ;
target [ 0 ] = target [ 1 ] = target [ 2 ] = target [ 3 ] = 0 ;
espec - > LineWidths [ out_line ] = 4 ;
} while ( + + OutLineCounter < VisibleLines ) ;
}
espec = NULL ;
}
VDP2Rend_LIB * VDP2REND_GetLIB ( unsigned line )
{
assert ( line < ( PAL ? 256 : 240 ) ) ; // NO: VisibleLines);
return & LIB [ line ] ;
}
void VDP2REND_DrawLine ( int vdp2_line , const bool field )
{
if ( MDFN_LIKELY ( OutLineCounter < VisibleLines ) )
{
uint16 out_line = OutLineCounter ;
if ( espec - > InterlaceOn )
out_line = ( out_line < < 1 ) | espec - > InterlaceField ;
WWQ ( COMMAND_DRAW_LINE , ( ( uint16 ) vdp2_line < < 16 ) | out_line , field ) ;
OutLineCounter + + ;
}
}
void VDP2REND_Reset ( bool powering_up )
{
WWQ ( COMMAND_RESET , powering_up ) ;
}
void VDP2REND_SetLayerEnableMask ( uint64 mask )
{
WWQ ( COMMAND_SET_LEM , mask ) ;
}
void VDP2REND_Write8_DB ( uint32 A , uint16 DB )
{
//if(DrawCounter.load(std::memory_order_acquire) != 0)
WWQ ( COMMAND_WRITE8 , A , DB ) ;
//else
// MemW<uint8>(A, DB);
}
void VDP2REND_Write16_DB ( uint32 A , uint16 DB )
{
//if(DrawCounter.load(std::memory_order_acquire) != 0)
WWQ ( COMMAND_WRITE16 , A , DB ) ;
//else
// MemW<uint16>(A, DB);
}
}