mirror of
https://github.com/libretro/RACE.git
synced 2024-11-27 11:00:21 +00:00
1392 lines
41 KiB
C
1392 lines
41 KiB
C
/*---------------------------------------------------------------------------
|
|
* 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. See also the license.txt file for
|
|
* additional informations.
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* graphics.cpp: implementation of the graphics class. */
|
|
|
|
#include "types.h"
|
|
#include "graphics.h"
|
|
#include "race-memory.h"
|
|
|
|
#if defined(ABGR1555)
|
|
#define RMASK 0x001f
|
|
#define GMASK 0x03e0
|
|
#define BMASK 0x7c00
|
|
#else
|
|
#define RMASK 0xf800
|
|
#define GMASK 0x07e0
|
|
#define BMASK 0x001f
|
|
#endif
|
|
|
|
extern struct ngp_screen* screen;
|
|
extern int gfx_hacks;
|
|
|
|
/*
|
|
* 16 bit graphics buffers
|
|
* At the moment there's no system which uses more than 16 bit
|
|
* colors.
|
|
* A graphics buffer holds number referencing to the color from
|
|
* the "total palette" for that system.
|
|
*/
|
|
int totalpalette[32*32*32];
|
|
|
|
/* Allows application of a 'dark filter' to reduce the
|
|
* glare of white backgrounds when viewing NGP content
|
|
* on a backlit screen
|
|
* Note: This code has no consistency regarding variable
|
|
* names - so we just use the normal libretro standard of
|
|
* delimiter-separated words...
|
|
*/
|
|
static unsigned dark_filter_level = 0;
|
|
|
|
static unsigned short *drawBuffer;
|
|
|
|
/* NGP specific
|
|
* precalculated pattern structures */
|
|
const unsigned char mypatterns[256*4] =
|
|
{
|
|
0,0,0,0, 0,0,0,1, 0,0,0,2, 0,0,0,3, 0,0,1,0, 0,0,1,1, 0,0,1,2, 0,0,1,3,
|
|
0,0,2,0, 0,0,2,1, 0,0,2,2, 0,0,2,3, 0,0,3,0, 0,0,3,1, 0,0,3,2, 0,0,3,3,
|
|
0,1,0,0, 0,1,0,1, 0,1,0,2, 0,1,0,3, 0,1,1,0, 0,1,1,1, 0,1,1,2, 0,1,1,3,
|
|
0,1,2,0, 0,1,2,1, 0,1,2,2, 0,1,2,3, 0,1,3,0, 0,1,3,1, 0,1,3,2, 0,1,3,3,
|
|
0,2,0,0, 0,2,0,1, 0,2,0,2, 0,2,0,3, 0,2,1,0, 0,2,1,1, 0,2,1,2, 0,2,1,3,
|
|
0,2,2,0, 0,2,2,1, 0,2,2,2, 0,2,2,3, 0,2,3,0, 0,2,3,1, 0,2,3,2, 0,2,3,3,
|
|
0,3,0,0, 0,3,0,1, 0,3,0,2, 0,3,0,3, 0,3,1,0, 0,3,1,1, 0,3,1,2, 0,3,1,3,
|
|
0,3,2,0, 0,3,2,1, 0,3,2,2, 0,3,2,3, 0,3,3,0, 0,3,3,1, 0,3,3,2, 0,3,3,3,
|
|
1,0,0,0, 1,0,0,1, 1,0,0,2, 1,0,0,3, 1,0,1,0, 1,0,1,1, 1,0,1,2, 1,0,1,3,
|
|
1,0,2,0, 1,0,2,1, 1,0,2,2, 1,0,2,3, 1,0,3,0, 1,0,3,1, 1,0,3,2, 1,0,3,3,
|
|
1,1,0,0, 1,1,0,1, 1,1,0,2, 1,1,0,3, 1,1,1,0, 1,1,1,1, 1,1,1,2, 1,1,1,3,
|
|
1,1,2,0, 1,1,2,1, 1,1,2,2, 1,1,2,3, 1,1,3,0, 1,1,3,1, 1,1,3,2, 1,1,3,3,
|
|
1,2,0,0, 1,2,0,1, 1,2,0,2, 1,2,0,3, 1,2,1,0, 1,2,1,1, 1,2,1,2, 1,2,1,3,
|
|
1,2,2,0, 1,2,2,1, 1,2,2,2, 1,2,2,3, 1,2,3,0, 1,2,3,1, 1,2,3,2, 1,2,3,3,
|
|
1,3,0,0, 1,3,0,1, 1,3,0,2, 1,3,0,3, 1,3,1,0, 1,3,1,1, 1,3,1,2, 1,3,1,3,
|
|
1,3,2,0, 1,3,2,1, 1,3,2,2, 1,3,2,3, 1,3,3,0, 1,3,3,1, 1,3,3,2, 1,3,3,3,
|
|
2,0,0,0, 2,0,0,1, 2,0,0,2, 2,0,0,3, 2,0,1,0, 2,0,1,1, 2,0,1,2, 2,0,1,3,
|
|
2,0,2,0, 2,0,2,1, 2,0,2,2, 2,0,2,3, 2,0,3,0, 2,0,3,1, 2,0,3,2, 2,0,3,3,
|
|
2,1,0,0, 2,1,0,1, 2,1,0,2, 2,1,0,3, 2,1,1,0, 2,1,1,1, 2,1,1,2, 2,1,1,3,
|
|
2,1,2,0, 2,1,2,1, 2,1,2,2, 2,1,2,3, 2,1,3,0, 2,1,3,1, 2,1,3,2, 2,1,3,3,
|
|
2,2,0,0, 2,2,0,1, 2,2,0,2, 2,2,0,3, 2,2,1,0, 2,2,1,1, 2,2,1,2, 2,2,1,3,
|
|
2,2,2,0, 2,2,2,1, 2,2,2,2, 2,2,2,3, 2,2,3,0, 2,2,3,1, 2,2,3,2, 2,2,3,3,
|
|
2,3,0,0, 2,3,0,1, 2,3,0,2, 2,3,0,3, 2,3,1,0, 2,3,1,1, 2,3,1,2, 2,3,1,3,
|
|
2,3,2,0, 2,3,2,1, 2,3,2,2, 2,3,2,3, 2,3,3,0, 2,3,3,1, 2,3,3,2, 2,3,3,3,
|
|
3,0,0,0, 3,0,0,1, 3,0,0,2, 3,0,0,3, 3,0,1,0, 3,0,1,1, 3,0,1,2, 3,0,1,3,
|
|
3,0,2,0, 3,0,2,1, 3,0,2,2, 3,0,2,3, 3,0,3,0, 3,0,3,1, 3,0,3,2, 3,0,3,3,
|
|
3,1,0,0, 3,1,0,1, 3,1,0,2, 3,1,0,3, 3,1,1,0, 3,1,1,1, 3,1,1,2, 3,1,1,3,
|
|
3,1,2,0, 3,1,2,1, 3,1,2,2, 3,1,2,3, 3,1,3,0, 3,1,3,1, 3,1,3,2, 3,1,3,3,
|
|
3,2,0,0, 3,2,0,1, 3,2,0,2, 3,2,0,3, 3,2,1,0, 3,2,1,1, 3,2,1,2, 3,2,1,3,
|
|
3,2,2,0, 3,2,2,1, 3,2,2,2, 3,2,2,3, 3,2,3,0, 3,2,3,1, 3,2,3,2, 3,2,3,3,
|
|
3,3,0,0, 3,3,0,1, 3,3,0,2, 3,3,0,3, 3,3,1,0, 3,3,1,1, 3,3,1,2, 3,3,1,3,
|
|
3,3,2,0, 3,3,2,1, 3,3,2,2, 3,3,2,3, 3,3,3,0, 3,3,3,1, 3,3,3,2, 3,3,3,3,
|
|
};
|
|
|
|
/* target window */
|
|
/*
|
|
unsigned short p2[16] = {
|
|
0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
|
|
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000
|
|
};
|
|
*/
|
|
|
|
#define BLIT_X_OFFSET 8
|
|
#define BLIT_Y_OFFSET 8
|
|
#define BLIT_OFFSET (BLIT_X_OFFSET + (BLIT_Y_OFFSET*SIZEX))
|
|
#define BLIT_WIDTH (160)
|
|
#define BLIT_HEIGHT (152)
|
|
#define SCREEN_X_OFFSET ((screen->w - BLIT_WIDTH)/2)
|
|
#define SCREEN_Y_OFFSET ((screen->h - BLIT_HEIGHT)/2)
|
|
|
|
/* (32) 32 is good for 480x272 -64 is for 320x240 (squish) */
|
|
#define PSP_FUDGE 0
|
|
/* extra fudge factor for PSP? */
|
|
#define SCREEN_OFFET (SCREEN_X_OFFSET + (SCREEN_Y_OFFSET*(screen->w+PSP_FUDGE)))
|
|
|
|
/* Flavor - For speed testing, you can turn off screen updates */
|
|
|
|
#if 0
|
|
#define NO_SCREEN_OUTPUT /* seems to give about 4-6FPS on GP2X */
|
|
#endif
|
|
|
|
/*
|
|
*
|
|
* Palette Initialization
|
|
*
|
|
*/
|
|
|
|
void (*palette_init)(DWORD dwRBitMask, DWORD dwGBitMask, DWORD dwBBitMask);
|
|
|
|
void palette_init32(DWORD dwRBitMask, DWORD dwGBitMask, DWORD dwBBitMask)
|
|
{
|
|
/* dbg_print("in palette_init32(0x%X, 0x%X, 0x%X)\n", dwRBitMask, dwGBitMask, dwBBitMask);
|
|
|
|
char RShiftCount = 0, GShiftCount = 0, BShiftCount = 0;
|
|
char RBitCount = 0, GBitCount = 0, BBitCount = 0;
|
|
int r,g,b;
|
|
DWORD i;
|
|
|
|
i = dwRBitMask;
|
|
while (!(i&1))
|
|
{
|
|
i = i >> 1;
|
|
RShiftCount++;
|
|
}
|
|
while (i&1)
|
|
{
|
|
i = i >> 1;
|
|
RBitCount++;
|
|
}
|
|
i = dwGBitMask;
|
|
while (!(i&1))
|
|
{
|
|
i = i >> 1;
|
|
GShiftCount++;
|
|
}
|
|
while (i&1)
|
|
{
|
|
i = i >> 1;
|
|
GBitCount++;
|
|
}
|
|
i = dwBBitMask;
|
|
while (!(i&1))
|
|
{
|
|
i = i >> 1;
|
|
BShiftCount++;
|
|
}
|
|
while (i&1)
|
|
{
|
|
i = i >> 1;
|
|
BBitCount++;
|
|
}
|
|
switch(m_emuInfo.machine)
|
|
{
|
|
case NGP:
|
|
case NGPC:
|
|
case GAMEGEAR:
|
|
case LYNX:
|
|
case WONDERSWAN:
|
|
case WONDERSWANCOLOR:
|
|
case ADVISION:
|
|
for (b=0; b<16; b++)
|
|
for (g=0; g<16; g++)
|
|
for (r=0; r<16; r++)
|
|
totalpalette[b*256+g*16+r] =
|
|
(((b<<(BBitCount-4))+(b>>(4-(BBitCount-4))))<<BShiftCount) +
|
|
(((g<<(GBitCount-4))+(g>>(4-(GBitCount-4))))<<GShiftCount) +
|
|
(((r<<(RBitCount-4))+(r>>(4-(RBitCount-4))))<<RShiftCount);
|
|
break;
|
|
case GAMEBOY:
|
|
case GAMEBOYPOCKET:
|
|
case GAMEBOYCOLOR:
|
|
case SUPERGAMEBOY:
|
|
case SUPERVISION:
|
|
case NES:
|
|
for (b=0; b<32; b++)
|
|
for (g=0; g<32; g++)
|
|
for (r=0; r<32; r++)
|
|
totalpalette[b*32*32+g*32+r] =
|
|
(((b<<(BBitCount-5))+(b>>(5-(BBitCount-5))))<<BShiftCount) +
|
|
(((g<<(GBitCount-5))+(g>>(5-(GBitCount-5))))<<GShiftCount) +
|
|
(((r<<(RBitCount-5))+(r>>(5-(RBitCount-5))))<<RShiftCount);
|
|
break;
|
|
}*/
|
|
}
|
|
|
|
/* RGB range: [0,1] */
|
|
static void darken_rgb(float *r, float *g, float *b)
|
|
{
|
|
/* Note: This is *very* approximate...
|
|
* - Should be done in linear colour space. It isn't.
|
|
* - Should alter brightness by performing an RGB->HSL->RGB
|
|
* conversion. We just do simple linear scaling instead.
|
|
* Basically, this is intended for use on devices that are
|
|
8 too weak to run shaders (i.e. why would you want a 'dark filter'
|
|
* if your device supports proper LCD shaders?). We therefore
|
|
* cut corners for the sake of performance...
|
|
*
|
|
* Constants
|
|
* > Luminosity factors: photometric/digital ITU BT.709
|
|
*static const float luma_r = 0.2126f;
|
|
*static const float luma_g = 0.7152f;
|
|
*static const float luma_b = 0.0722f;
|
|
* > Luminosity factors: Digital ITU BT.601
|
|
* (seems to produce better results than ITU BT.709)
|
|
*/
|
|
static const float luma_r = 0.299f;
|
|
static const float luma_g = 0.587f;
|
|
static const float luma_b = 0.114f;
|
|
/* Calculate luminosity */
|
|
float luma = (luma_r * (*r)) + (luma_g * (*g)) + (luma_b * (*b));
|
|
/* Get 'darkness' scaling factor
|
|
* > User set 'dark filter' level scaled by current luminosity
|
|
* (i.e. lighter colours affected more than darker colours)
|
|
*/
|
|
float dark_factor = 1.0f - (((float)(dark_filter_level) * 0.01f) * luma);
|
|
dark_factor = dark_factor < 0.0f ? 0.0f : dark_factor;
|
|
/* Perform scaling... */
|
|
*r = (*r) * dark_factor;
|
|
*g = (*g) * dark_factor;
|
|
*b = (*b) * dark_factor;
|
|
}
|
|
|
|
void palette_init16(DWORD dwRBitMask, DWORD dwGBitMask, DWORD dwBBitMask)
|
|
{
|
|
#if 0
|
|
dbg_print("in palette_init16(0x%X, 0x%X, 0x%X)\n", dwRBitMask, dwGBitMask, dwBBitMask);
|
|
#endif
|
|
|
|
char RShiftCount = 0, GShiftCount = 0, BShiftCount = 0;
|
|
char RBitCount = 0, GBitCount = 0, BBitCount = 0;
|
|
int r,g,b;
|
|
DWORD i;
|
|
|
|
i = dwRBitMask;
|
|
while (!(i&1))
|
|
{
|
|
i = i >> 1;
|
|
RShiftCount++;
|
|
}
|
|
while (i&1)
|
|
{
|
|
i = i >> 1;
|
|
RBitCount++;
|
|
}
|
|
i = dwGBitMask;
|
|
while (!(i&1))
|
|
{
|
|
i = i >> 1;
|
|
GShiftCount++;
|
|
}
|
|
while (i&1)
|
|
{
|
|
i = i >> 1;
|
|
GBitCount++;
|
|
}
|
|
i = dwBBitMask;
|
|
while (!(i&1))
|
|
{
|
|
i = i >> 1;
|
|
BShiftCount++;
|
|
}
|
|
while (i&1)
|
|
{
|
|
i = i >> 1;
|
|
BBitCount++;
|
|
}
|
|
switch(m_emuInfo.machine)
|
|
{
|
|
case NGP:
|
|
case NGPC:
|
|
if (dark_filter_level > 0)
|
|
{
|
|
static const float rgb_max = 15.0f;
|
|
static const float rgb_max_inv = 1.0f / rgb_max;
|
|
float r_float, g_float, b_float;
|
|
int r_final, g_final, b_final;
|
|
|
|
/* Perform RGB assignment with colour conversion */
|
|
for (b=0; b<16; b++)
|
|
{
|
|
for (g=0; g<16; g++)
|
|
{
|
|
for (r=0; r<16; r++)
|
|
{
|
|
/* Convert colour range from [0,0xF] to [0,1] */
|
|
r_float = (float)(r) * rgb_max_inv;
|
|
g_float = (float)(g) * rgb_max_inv;
|
|
b_float = (float)(b) * rgb_max_inv;
|
|
/* Perform image darkening */
|
|
darken_rgb(&r_float, &g_float, &b_float);
|
|
/* Convert back to 4bit unsigned */
|
|
r_final = (int)((r_float * rgb_max) + 0.5f) & 0xF;
|
|
g_final = (int)((g_float * rgb_max) + 0.5f) & 0xF;
|
|
b_final = (int)((b_float * rgb_max) + 0.5f) & 0xF;
|
|
|
|
totalpalette[b*256+g*16+r] =
|
|
(((b_final<<(BBitCount-4))+(b_final>>(4-(BBitCount-4))))<<BShiftCount) +
|
|
(((g_final<<(GBitCount-4))+(g_final>>(4-(GBitCount-4))))<<GShiftCount) +
|
|
(((r_final<<(RBitCount-4))+(r_final>>(4-(RBitCount-4))))<<RShiftCount);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Use fast RGB assignment */
|
|
for (b=0; b<16; b++)
|
|
for (g=0; g<16; g++)
|
|
for (r=0; r<16; r++)
|
|
totalpalette[b*256+g*16+r] =
|
|
(((b<<(BBitCount-4))+(b>>(4-(BBitCount-4))))<<BShiftCount) +
|
|
(((g<<(GBitCount-4))+(g>>(4-(GBitCount-4))))<<GShiftCount) +
|
|
(((r<<(RBitCount-4))+(r>>(4-(RBitCount-4))))<<RShiftCount);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Again, there is no consistency in naming...
|
|
* Most interface functions seem to use camel case,
|
|
* so do the same here...
|
|
*/
|
|
void graphicsSetDarkFilterLevel(unsigned filterLevel)
|
|
{
|
|
unsigned prev_dark_filter_level = dark_filter_level;
|
|
|
|
dark_filter_level = filterLevel;
|
|
dark_filter_level = (dark_filter_level > 100) ? 100 : dark_filter_level;
|
|
|
|
if (dark_filter_level != prev_dark_filter_level)
|
|
palette_init16(RMASK, GMASK, BMASK);
|
|
}
|
|
|
|
void palette_init8(DWORD dwRBitMask, DWORD dwGBitMask, DWORD dwBBitMask)
|
|
{
|
|
}
|
|
|
|
void pngpalette_init(void)
|
|
{
|
|
/* int r,g,b;
|
|
|
|
switch(m_emuInfo.machine)
|
|
{
|
|
case NGP:
|
|
case NGPC:
|
|
case GAMEGEAR:
|
|
case LYNX:
|
|
case WONDERSWAN:
|
|
case WONDERSWANCOLOR:
|
|
case ADVISION:
|
|
for (b=0; b<16; b++)
|
|
for (g=0; g<16; g++)
|
|
for (r=0; r<16; r++)
|
|
{
|
|
totalpalette32[b*256+g*16+r] =
|
|
(((b<<(8-4))+(b>>(4-(8-4))))<<0) +
|
|
(((g<<(8-4))+(g>>(4-(8-4))))<<8) +
|
|
(((r<<(8-4))+(r>>(4-(8-4))))<<16);
|
|
}
|
|
break;
|
|
case GAMEBOY:
|
|
case GAMEBOYPOCKET:
|
|
case GAMEBOYCOLOR:
|
|
case SUPERGAMEBOY:
|
|
case SUPERVISION:
|
|
case NES:
|
|
for (b=0; b<32; b++)
|
|
for (g=0; g<32; g++)
|
|
for (r=0; r<32; r++)
|
|
{
|
|
totalpalette32[b*32*32+g*32+r] =
|
|
(((b<<(8-5))+(b>>(5-(8-5))))<<0) +
|
|
(((g<<(8-5))+(g>>(5-(8-5))))<<8) +
|
|
(((r<<(8-5))+(r>>(5-(8-5))))<<16);
|
|
}
|
|
break;
|
|
}*/
|
|
}
|
|
|
|
/*
|
|
*
|
|
* Neogeo Pocket & Neogeo Pocket color rendering
|
|
*
|
|
*/
|
|
|
|
#if 0
|
|
static const bwTable[8] = { 0x0000, 0x0333, 0x0555, 0x0777, 0x0999, 0x0BBB, 0x0DDD, 0x0FFF };
|
|
#endif
|
|
|
|
/* NOTA Color para juegos b/n */
|
|
static const unsigned short bwTable[8] =
|
|
{
|
|
/* NOTA nose,nose,window,nose,nose,nose,nose,nose
|
|
* B, G,R */
|
|
0x0FFF, 0x0DDD, 0x0BBB, 0x0999, 0x0777, 0x0555, 0x0333, 0x0000
|
|
};
|
|
|
|
/* used for rendering the sprites */
|
|
|
|
typedef struct
|
|
{
|
|
unsigned short offset; /* offset in graphics buffer to blit, Flavor hopes 16bits is good enough */
|
|
unsigned short pattern; /* pattern code including palette number */
|
|
unsigned short *tilept; /* pointer into the tile description */
|
|
unsigned short *palette; /* palette used to render this sprite */
|
|
}
|
|
SPRITE;
|
|
|
|
typedef struct
|
|
{
|
|
unsigned short *gbp; /* (0,x) base for drawing */
|
|
unsigned char count[152];
|
|
SPRITE sprite[152][64];
|
|
}
|
|
SPRITEDEFS;
|
|
|
|
#if 0
|
|
unsigned int spritesDirty = true;
|
|
#endif
|
|
|
|
SPRITEDEFS spriteDefs[3]; /* 4 priority levels */
|
|
|
|
/* definitions of types and variables that are used internally during
|
|
* rendering of a screen */
|
|
|
|
typedef struct
|
|
{
|
|
unsigned short *gbp; /* pointer into graphics buffer */
|
|
unsigned char oldScrollX; /* keep an eye on the old and previous values */
|
|
unsigned char *newScrollX; /* of the scroll values */
|
|
unsigned char oldScrollY;
|
|
unsigned char *newScrollY;
|
|
unsigned short *tileBase; /* start address of the tile table this structure represents */
|
|
short tile[21]; /* the tile code */
|
|
unsigned short *palettes[21]; /* palettes associated with tiles */
|
|
unsigned short *tilept[21]; /* tile lines to render */
|
|
unsigned short *palette; /* palette for the tiles this VSYNC */
|
|
}
|
|
TILECACHE;
|
|
|
|
unsigned short palettes[16*4+16*4+16*4]; /* placeholder for the converted palette */
|
|
|
|
|
|
TILECACHE tCBack; /* tile pointer cache for the back buffer */
|
|
TILECACHE tCFront; /* tile pointer cache for the front buffer */
|
|
|
|
#if 0
|
|
int BGCol; /* placeholder for the background color this VSYNC */
|
|
int OOWCol; /* placeholder for the outside window color this VSYNC */
|
|
unsigned char SprPriLo, SprPriHi, SprPri = 0;
|
|
#endif
|
|
|
|
static inline void set_paletteCol(
|
|
unsigned short *palette_table,
|
|
unsigned short *sprite,
|
|
unsigned short *front,
|
|
unsigned short *back)
|
|
{
|
|
int i;
|
|
/* initialize palette table
|
|
*
|
|
* initialize back plane palette table
|
|
*/
|
|
|
|
for(i=0;i<16*4;i++)
|
|
{
|
|
#if 0
|
|
sprite[i] = *palette_table & 0x0FFF;
|
|
#endif
|
|
sprite[i] = NGPC_TO_SDL16(palette_table[i]);
|
|
}
|
|
|
|
/* initialize front plane palette table */
|
|
for(i=0;i<16*4;i++)
|
|
{
|
|
#if 0
|
|
front[i] = *palette_table & 0x0FFF;
|
|
#endif
|
|
front[i] = NGPC_TO_SDL16(palette_table[i+16*4]);
|
|
}
|
|
|
|
/* initialize sprite palette table (?) */
|
|
for(i=0;i<16*4;i++)
|
|
{
|
|
#if 0
|
|
back[i] = *palette_table & 0x0FFF;
|
|
#endif
|
|
back[i] = NGPC_TO_SDL16(palette_table[i+16*4*2]);
|
|
}
|
|
}
|
|
|
|
static inline void set_paletteBW(
|
|
unsigned short *palette_table,
|
|
unsigned short *sprite,
|
|
unsigned short *front,
|
|
unsigned short *back)
|
|
{
|
|
int i;
|
|
unsigned char *pt = ((unsigned char *)palette_table)-0x0100; /* get b/w color table */
|
|
|
|
/* initialize palette table */
|
|
for(i=0;i<4;i++)
|
|
{
|
|
/* initialize sprite palette table */
|
|
sprite[i] = NGPC_TO_SDL16(bwTable[pt[i] & 0x07]);
|
|
sprite[4+i] = NGPC_TO_SDL16(bwTable[pt[4+i] & 0x07]);
|
|
/* initialize front plane palette table */
|
|
front[i] = NGPC_TO_SDL16(bwTable[pt[8+i] & 0x07]);
|
|
front[4+i] = NGPC_TO_SDL16(bwTable[pt[8+4+i] & 0x07]);
|
|
/* initialize back plane palette table */
|
|
back[i] = NGPC_TO_SDL16(bwTable[pt[16+i] & 0x07]);
|
|
back[4+i] = NGPC_TO_SDL16(bwTable[pt[16+4+i] & 0x07]);
|
|
}
|
|
}
|
|
|
|
/* I think there's something wrong with this on the GP2X, because CFC2's intro screen is all red */
|
|
static inline void lineClear(TILECACHE *tC, unsigned short col)
|
|
{
|
|
for(int i=0; i<21*8; i++)
|
|
tC->gbp[i] = col;
|
|
}
|
|
|
|
static inline void clipLeftRight(SPRITEDEFS *sprDef, unsigned short OOWCol)
|
|
{
|
|
int i,j;
|
|
|
|
j = *wndTopLeftX + 8;
|
|
if (j > (NGPC_SIZEX+8))
|
|
j = NGPC_SIZEX+8;
|
|
for(i=8; i<j; i++)
|
|
sprDef->gbp[i] = OOWCol;
|
|
j = j + *wndSizeX;
|
|
if (j > (NGPC_SIZEX+8))
|
|
j = NGPC_SIZEX+8;
|
|
for(i=j; i < (NGPC_SIZEX+8); i++)
|
|
sprDef->gbp[i] = OOWCol;
|
|
}
|
|
|
|
static inline void lineFront(TILECACHE *tC)
|
|
{
|
|
int i;
|
|
unsigned char a,b;
|
|
const unsigned char *p2;
|
|
unsigned short *gb;
|
|
|
|
/* for 8bit SDL, this would set gb to the index of the proper color
|
|
* then, we'd set gb to p2[n]+(i*sizeof(palette)) */
|
|
|
|
gb = tC->gbp;
|
|
for (i=0;i<21;i++)
|
|
{
|
|
a = *(((unsigned char *)tC->tilept[i])+1);
|
|
b = *((unsigned char *)tC->tilept[i]);
|
|
if (tC->tile[i]&0x8000)
|
|
{
|
|
p2 = &mypatterns[b*4];
|
|
if (p2[3])
|
|
gb[0] = tC->palettes[i][p2[3]];
|
|
if (p2[2])
|
|
gb[1] = tC->palettes[i][p2[2]];
|
|
if (p2[1])
|
|
gb[2] = tC->palettes[i][p2[1]];
|
|
if (p2[0])
|
|
gb[3] = tC->palettes[i][p2[0]];
|
|
p2 = &mypatterns[a*4];
|
|
if (p2[3])
|
|
gb[4] = tC->palettes[i][p2[3]];
|
|
if (p2[2])
|
|
gb[5] = tC->palettes[i][p2[2]];
|
|
if (p2[1])
|
|
gb[6] = tC->palettes[i][p2[1]];
|
|
if (p2[0])
|
|
gb[7] = tC->palettes[i][p2[0]];
|
|
}
|
|
else
|
|
{
|
|
p2 = &mypatterns[a*4];
|
|
if (p2[0])
|
|
gb[0] = tC->palettes[i][p2[0]];
|
|
if (p2[1])
|
|
gb[1] = tC->palettes[i][p2[1]];
|
|
if (p2[2])
|
|
gb[2] = tC->palettes[i][p2[2]];
|
|
if (p2[3])
|
|
gb[3] = tC->palettes[i][p2[3]];
|
|
p2 = &mypatterns[b*4];
|
|
if (p2[0])
|
|
gb[4] = tC->palettes[i][p2[0]];
|
|
if (p2[1])
|
|
gb[5] = tC->palettes[i][p2[1]];
|
|
if (p2[2])
|
|
gb[6] = tC->palettes[i][p2[2]];
|
|
if (p2[3])
|
|
gb[7] = tC->palettes[i][p2[3]];
|
|
}
|
|
if (tC->tile[i]&0x4000)
|
|
tC->tilept[i]-= 1;
|
|
else
|
|
tC->tilept[i]+= 1;
|
|
gb+= 8;
|
|
}
|
|
}
|
|
|
|
static inline void lineSprite(SPRITEDEFS *sprDefs)
|
|
{
|
|
SPRITE *spr;
|
|
unsigned short *gb;
|
|
unsigned char a,b;
|
|
const unsigned char *p2;
|
|
|
|
/* for 8bit SDL, this would set gb to the index of the proper color
|
|
* then, we'd set gb to p2[n] */
|
|
|
|
for (int i=sprDefs->count[*scanlineY];i>0;i--)
|
|
{
|
|
spr = &sprDefs->sprite[*scanlineY][i-1];
|
|
gb = &sprDefs->gbp[spr->offset];
|
|
a = *(((unsigned char *)spr->tilept)+1);
|
|
b = *((unsigned char *)spr->tilept);
|
|
if (spr->pattern&0x8000)
|
|
{
|
|
p2 = &mypatterns[b*4];
|
|
if (p2[3])
|
|
gb[0] = spr->palette[p2[3]];
|
|
if (p2[2])
|
|
gb[1] = spr->palette[p2[2]];
|
|
if (p2[1])
|
|
gb[2] = spr->palette[p2[1]];
|
|
if (p2[0])
|
|
gb[3] = spr->palette[p2[0]];
|
|
p2 = &mypatterns[a*4];
|
|
if (p2[3])
|
|
gb[4] = spr->palette[p2[3]];
|
|
if (p2[2])
|
|
gb[5] = spr->palette[p2[2]];
|
|
if (p2[1])
|
|
gb[6] = spr->palette[p2[1]];
|
|
if (p2[0])
|
|
gb[7] = spr->palette[p2[0]];
|
|
}
|
|
else
|
|
{
|
|
p2 = &mypatterns[a*4];
|
|
if (p2[0])
|
|
gb[0] = spr->palette[p2[0]];
|
|
if (p2[1])
|
|
gb[1] = spr->palette[p2[1]];
|
|
if (p2[2])
|
|
gb[2] = spr->palette[p2[2]];
|
|
if (p2[3])
|
|
gb[3] = spr->palette[p2[3]];
|
|
p2 = &mypatterns[b*4];
|
|
if (p2[0])
|
|
gb[4] = spr->palette[p2[0]];
|
|
if (p2[1])
|
|
gb[5] = spr->palette[p2[1]];
|
|
if (p2[2])
|
|
gb[6] = spr->palette[p2[2]];
|
|
if (p2[3])
|
|
gb[7] = spr->palette[p2[3]];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* sort all the sprites according to their priorities */
|
|
#if 0
|
|
static void spriteSort(unsigned int bw)
|
|
{
|
|
unsigned short spriteCode;
|
|
unsigned short *pt;
|
|
unsigned char x, y, prevx=0, prevy=0;
|
|
int i, j;
|
|
|
|
SPRITEDEFS *SprPri00 = &spriteDefs[0];
|
|
SPRITEDEFS *SprPri40 = &spriteDefs[1];
|
|
SPRITEDEFS *SprPri80 = &spriteDefs[2];
|
|
SPRITEDEFS *SprPriC0 = &spriteDefs[3];
|
|
|
|
/* initialize the number of sprites in each structure */
|
|
SprPri00->count = 0;
|
|
SprPri40->count = 0;
|
|
SprPri80->count = 0;
|
|
SprPriC0->count = 0;
|
|
for (i=0;i<64;i++)
|
|
{
|
|
spriteCode = *((unsigned short *)(sprite_table+4*i));
|
|
if (spriteCode & 0x0400)
|
|
prevx+= *(sprite_table+4*i+2);
|
|
else
|
|
prevx = *(sprite_table+4*i+2) + 8;
|
|
x = prevx + *scrollSpriteX;
|
|
if (spriteCode & 0x0200)
|
|
prevy+= *(sprite_table+4*i+3);
|
|
else
|
|
prevy = *(sprite_table+4*i+3) + 8;
|
|
y = prevy + *scrollSpriteY;
|
|
j = *scanlineY+8 - y;
|
|
if ((spriteCode>0xff) && (j >= 0) && (j < 8) && (x<168)) /* is this sprite visable on the current scanline? */
|
|
{
|
|
// if ((j >= 0) && (j < 8) && (x<168)) {
|
|
SPRITE *spr = NULL;
|
|
// *(sprite_palette_numbers+i)
|
|
pt = (unsigned short *)(pattern_table + 16*(spriteCode & 0x01ff)
|
|
+ ((spriteCode&0x4000) ? (7-j)*2 : j*2));
|
|
switch (spriteCode & 0x1800)
|
|
{
|
|
// case order reversed because priority 3 (and 2) sprites occur most of the time
|
|
case 0x1800:
|
|
spr = &SprPriC0->sprite[SprPriC0->count];
|
|
SprPriC0->count++;
|
|
break;
|
|
case 0x1000:
|
|
spr = &SprPri80->sprite[SprPri80->count];
|
|
SprPri80->count++;
|
|
break;
|
|
case 0x0800:
|
|
spr = &SprPri40->sprite[SprPri40->count];
|
|
SprPri40->count++;
|
|
break;
|
|
case 0x0000:
|
|
spr = &SprPri00->sprite[SprPri00->count];
|
|
SprPri00->count++;
|
|
break;
|
|
}
|
|
spr->pattern = spriteCode;
|
|
spr->offset = x;
|
|
spr->tilept = pt;
|
|
spr->palette = ((bw) ? &palettes[(spriteCode>>11)&0x04]
|
|
: &palettes[(*(sprite_palette_numbers+i)&0x0F)*4]);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static inline void spriteSortAll(unsigned int bw)
|
|
{
|
|
unsigned int spriteCode;
|
|
unsigned short *pt;
|
|
unsigned char x, y, prevx=0, prevy=0;
|
|
unsigned int i, j, k, scanline;
|
|
SPRITE *spr;
|
|
|
|
SPRITEDEFS *SprPri40 = &spriteDefs[0];
|
|
SPRITEDEFS *SprPri80 = &spriteDefs[1];
|
|
SPRITEDEFS *SprPriC0 = &spriteDefs[2];
|
|
|
|
/* initialize the number of sprites in each structure */
|
|
memset(SprPri40->count, 0, 152);
|
|
memset(SprPri80->count, 0, 152);
|
|
memset(SprPriC0->count, 0, 152);
|
|
for (i=0;i<64;i++)
|
|
{
|
|
spriteCode = *((unsigned short *)(sprite_table+4*i));
|
|
|
|
if ((spriteCode<=0xff) || ((spriteCode & 0x1800)==0))
|
|
continue;
|
|
|
|
if (spriteCode & 0x0400)
|
|
prevx+= *(sprite_table+4*i+2);
|
|
else
|
|
prevx = *(sprite_table+4*i+2) + 8;
|
|
x = prevx + *scrollSpriteX;
|
|
|
|
if (spriteCode & 0x0200)
|
|
prevy+= *(sprite_table+4*i+3);
|
|
else
|
|
prevy = *(sprite_table+4*i+3) + 8;
|
|
y = prevy + *scrollSpriteY;
|
|
|
|
if (x>167 || y>151)
|
|
continue;
|
|
|
|
for(k=0; k<8; k++)
|
|
{
|
|
scanline = y+k-8;
|
|
if(scanline < 0 || scanline >= 152)
|
|
continue;
|
|
|
|
#if 0
|
|
if ((x<168) && (spriteCode>0xff) && (spriteCode & 0x1800))
|
|
{
|
|
#endif
|
|
switch (spriteCode & 0x1800)
|
|
{
|
|
/* case order reversed because priority 3 (and 2) sprites occur most of the time */
|
|
case 0x1800:
|
|
spr = &SprPriC0->sprite[scanline][SprPriC0->count[scanline]++];
|
|
break;
|
|
case 0x1000:
|
|
spr = &SprPri80->sprite[scanline][SprPri80->count[scanline]++];
|
|
break;
|
|
case 0x0800:
|
|
spr = &SprPri40->sprite[scanline][SprPri40->count[scanline]++];
|
|
break;
|
|
}
|
|
j = scanline+8 - y;
|
|
spr->pattern = spriteCode;
|
|
spr->offset = x;
|
|
spr->tilept = (unsigned short *)(pattern_table + 16*(spriteCode & 0x01ff)
|
|
+ ((spriteCode&0x4000) ? (7-j)*2 : j*2));
|
|
spr->palette = ((bw) ? &palettes[(spriteCode>>11)&0x04]
|
|
: &palettes[(*(sprite_palette_numbers+i)&0x0F)*4]);
|
|
#if 0
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* initialize drawing/blitting of a screen */
|
|
static void graphicsBlitInit(void)
|
|
{
|
|
/* buffers 0 and 1
|
|
* definitions for the back frame */
|
|
tCBack.gbp = &drawBuffer[8*SIZEX + (8-((*scrollBackX)&7))];
|
|
tCBack.newScrollX = scrollBackX;
|
|
tCBack.newScrollY = scrollBackY;
|
|
tCBack.tileBase = tile_table_back;
|
|
tCBack.palette = &palettes[16*4+16*4];
|
|
/* definitions for the front frame */
|
|
tCFront.gbp = &drawBuffer[8*SIZEX + (8-((*scrollFrontX)&7))];
|
|
tCFront.newScrollX = scrollFrontX;
|
|
tCFront.newScrollY = scrollFrontY;
|
|
tCFront.tileBase = tile_table_front;
|
|
tCFront.palette = &palettes[16*4];
|
|
/* definitions for sprite priorities */
|
|
#if 0
|
|
SprPriLo = *frame1Pri>>6;
|
|
SprPriHi = *frame0Pri>>6; /* ? */
|
|
#endif
|
|
spriteDefs[0].gbp = &drawBuffer[8*SIZEX];
|
|
spriteDefs[1].gbp = &drawBuffer[8*SIZEX];
|
|
spriteDefs[2].gbp = &drawBuffer[8*SIZEX];
|
|
#if 0
|
|
spriteDefs[3].gbp = &drawBuffer[8*SIZEX];
|
|
#endif
|
|
/* force recalculations for first line */
|
|
tCBack.oldScrollX = *tCBack.newScrollX;
|
|
tCBack.oldScrollY = *tCBack.newScrollY+1; /* force calculation of structure data */
|
|
tCFront.oldScrollX = *tCFront.newScrollX;
|
|
tCFront.oldScrollY = *tCFront.newScrollY+1; /* force calculation of structure data */
|
|
/* start drawing at line 0 */
|
|
#if 0
|
|
*scanlineY = 0;
|
|
#endif
|
|
}
|
|
|
|
static inline void RenderTileCache(TILECACHE *tC, unsigned int bw)
|
|
{
|
|
int i;
|
|
unsigned char line;
|
|
unsigned short *temp;
|
|
|
|
if ((tC->oldScrollX != *tC->newScrollX) ||
|
|
(tC->oldScrollY != *tC->newScrollY) ||
|
|
(((*tC->newScrollY + *scanlineY)&7) == 0))
|
|
{
|
|
/* update the structure to reflect the changed scroll registers
|
|
* first update pointer into render buffer */
|
|
tC->gbp = tC->gbp + (tC->oldScrollX&7) - (*tC->newScrollX&7);
|
|
|
|
tC->oldScrollX = *tC->newScrollX;
|
|
tC->oldScrollY = *tC->newScrollY;
|
|
|
|
temp = tC->tileBase + (((tC->oldScrollY + *scanlineY)&0xf8)<<2);
|
|
for (i=0;i<21;i++)
|
|
{
|
|
tC->tile[i] = *(temp + (((tC->oldScrollX>>3) + i)&31));
|
|
line = (*tC->newScrollY + *scanlineY)&7;
|
|
tC->palettes[i] = ((bw) ? tC->palette + ((tC->tile[i] & 0x2000) ? 4 : 0)
|
|
: tC->palette + ((tC->tile[i]>>7) & 0x3C));
|
|
tC->tilept[i] = (unsigned short *)(pattern_table + ((tC->tile[i] & 0x01ff)<<4));
|
|
tC->tilept[i]+= ((tC->tile[i]&0x4000) ? 7-line : line);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* THOR'S GRAPHIC CORE
|
|
*/
|
|
|
|
typedef struct
|
|
{
|
|
unsigned char flip;
|
|
unsigned char x;
|
|
unsigned char pal;
|
|
} MYSPRITE;
|
|
|
|
typedef struct
|
|
{
|
|
unsigned short tile;
|
|
unsigned char id;
|
|
} MYSPRITEREF;
|
|
|
|
typedef struct
|
|
{
|
|
unsigned char count[152];
|
|
MYSPRITEREF refs[152][64];
|
|
} MYSPRITEDEF;
|
|
|
|
MYSPRITEDEF mySprPri40,mySprPri80,mySprPriC0;
|
|
MYSPRITE mySprites[64];
|
|
unsigned short myPalettes[192];
|
|
|
|
void sortSprites(unsigned int bw)
|
|
{
|
|
unsigned int spriteCode;
|
|
unsigned char x, y, prevx=0, prevy=0;
|
|
unsigned int i, j;
|
|
unsigned short tile;
|
|
MYSPRITEREF *spr;
|
|
|
|
/* initialize the number of sprites in each structure */
|
|
memset(mySprPri40.count, 0, 152);
|
|
memset(mySprPri80.count, 0, 152);
|
|
memset(mySprPriC0.count, 0, 152);
|
|
|
|
for (i=0;i<64;i++)
|
|
{
|
|
spriteCode = *((unsigned short *)(sprite_table+4*i));
|
|
|
|
prevx = (spriteCode & 0x0400 ? prevx : 0) + *(sprite_table+4*i+2);
|
|
x = prevx + *scrollSpriteX;
|
|
|
|
prevy = (spriteCode & 0x0200 ? prevy : 0) + *(sprite_table+4*i+3);
|
|
y = prevy + *scrollSpriteY;
|
|
|
|
if ((x>167 && x<249) || (y>151 && y<249) || (spriteCode<=0xff) || ((spriteCode & 0x1800)==0))
|
|
continue;
|
|
|
|
mySprites[i].x = x;
|
|
mySprites[i].pal = bw ? ((spriteCode>>11)&0x04) : ((sprite_palette_numbers[i]&0xf)<<2);
|
|
mySprites[i].flip = spriteCode>>8;
|
|
tile = (spriteCode & 0x01ff)<<3;
|
|
|
|
for (j = 0; j < 8; ++j,++y)
|
|
{
|
|
if (y>151)
|
|
continue;
|
|
switch (spriteCode & 0x1800)
|
|
{
|
|
case 0x1800:
|
|
spr = &mySprPriC0.refs[y][mySprPriC0.count[y]++];
|
|
break;
|
|
case 0x1000:
|
|
spr = &mySprPri80.refs[y][mySprPri80.count[y]++];
|
|
break;
|
|
case 0x0800:
|
|
spr = &mySprPri40.refs[y][mySprPri40.count[y]++];
|
|
break;
|
|
default: continue;
|
|
}
|
|
spr->id = i;
|
|
spr->tile = tile + (spriteCode&0x4000 ? 7-j : j);
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawSprites(unsigned short* draw,
|
|
MYSPRITEREF *sprites,int count,
|
|
int x0,int x1)
|
|
{
|
|
unsigned short*pal;
|
|
unsigned int pattern,pix,cnt;
|
|
MYSPRITE *spr;
|
|
int i,cx;
|
|
|
|
for (i=count-1;i>=0;--i)
|
|
{
|
|
pattern = patterns[sprites[i].tile];
|
|
if (pattern==0)
|
|
continue;
|
|
|
|
spr = &mySprites[sprites[i].id];
|
|
|
|
if (spr->x>248)
|
|
cx = spr->x-256;
|
|
else
|
|
cx = spr->x;
|
|
|
|
if (cx+8<=x0 || cx>=x1)
|
|
continue;
|
|
|
|
pal = &myPalettes[spr->pal];
|
|
|
|
if (cx<x0)
|
|
{
|
|
cnt = 8-(x0-cx);
|
|
if (spr->flip&0x80)
|
|
{
|
|
pattern>>=((8-cnt)<<1);
|
|
for (cx=x0;pattern;++cx)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[cx] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pattern &= (0xffff>>((8-cnt)<<1));
|
|
for (cx = x0+cnt-1;pattern;--cx)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[cx] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
}
|
|
else if (cx+7<x1)
|
|
{
|
|
if (spr->flip&0x80)
|
|
{
|
|
for (;pattern;++cx)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[cx] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (cx+=7;pattern;--cx)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[cx] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cnt = x1-cx;
|
|
if (spr->flip&0x80)
|
|
{
|
|
pattern &= (0xffff>>((8-cnt)<<1));
|
|
for (;pattern;++cx)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[cx] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pattern>>=((8-cnt)<<1);
|
|
for (cx+=cnt-1;pattern;--cx)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[cx] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawScrollPlane(unsigned short* draw,
|
|
unsigned short* tile_table,int scrpal,
|
|
unsigned char dx,unsigned char dy,
|
|
int x0,int x1,unsigned int bw)
|
|
{
|
|
unsigned short*tiles;
|
|
unsigned short*pal;
|
|
unsigned int pattern;
|
|
unsigned int j,count,pix,idy,tile;
|
|
int i,x2;
|
|
|
|
dx+=x0;
|
|
tiles = tile_table+((dy>>3)<<5)+(dx>>3);
|
|
|
|
count = 8-(dx&0x7);
|
|
dx &= 0xf8;
|
|
dy &= 0x7;
|
|
idy = 7-dy;
|
|
|
|
i = x0;
|
|
|
|
if (count<8)
|
|
{
|
|
tile = *(tiles++);
|
|
pattern = patterns[(((tile&0x1ff))<<3) + (tile&0x4000 ? idy:dy)];
|
|
if (pattern)
|
|
{
|
|
pal = &myPalettes[scrpal + (bw ? (tile&0x2000 ? 4 : 0) : ((tile>>7)&0x3c))];
|
|
if (tile&0x8000)
|
|
{
|
|
pattern>>=((8-count)<<1);
|
|
for (j=i;pattern;++j)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[j] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pattern &= (0xffff>>((8-count)<<1));
|
|
for (j=i+count-1;pattern;--j)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[j] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
}
|
|
i+=count;
|
|
dx+=8;
|
|
if (dx==0)
|
|
tiles-=32;
|
|
}
|
|
|
|
x2 = i+((x1-i)&0xf8);
|
|
|
|
for (;i<x2;i+=8)
|
|
{
|
|
tile = *(tiles++);
|
|
pattern = patterns[(((tile&0x1ff))<<3) + (tile&0x4000 ? idy:dy)];
|
|
if (pattern)
|
|
{
|
|
pal = &myPalettes[scrpal + (bw ? (tile&0x2000 ? 4 : 0) : ((tile>>7)&0x3c))];
|
|
if (tile&0x8000)
|
|
{
|
|
for (j=i;pattern;++j)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[j] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (j=i+7;pattern;--j)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[j] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
}
|
|
dx+=8;
|
|
if (dx==0)
|
|
tiles-=32;
|
|
}
|
|
|
|
if (x2!=x1)
|
|
{
|
|
count = x1-x2;
|
|
tile = *(tiles++);
|
|
pattern = patterns[(((tile&0x1ff))<<3) + (tile&0x4000 ? idy:dy)];
|
|
if (pattern)
|
|
{
|
|
pal = &myPalettes[scrpal + (bw ? (tile&0x2000 ? 4 : 0) : ((tile>>7)&0x3c))];
|
|
if (tile&0x8000)
|
|
{
|
|
pattern &= (0xffff>>((8-count)<<1));
|
|
for (j=i;pattern;++j)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[j] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pattern>>=((8-count)<<1);
|
|
for (j=i+count-1;pattern;--j)
|
|
{
|
|
pix = pattern & 0x3;
|
|
if (pix)
|
|
draw[j] = pal[pix];
|
|
pattern>>=2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void myGraphicsBlitLine(unsigned char render) /* NOTA */
|
|
{
|
|
int i,x0,x1;
|
|
if (*scanlineY < 152)
|
|
{
|
|
if(render)
|
|
{
|
|
#if __LIBRETRO__
|
|
unsigned short* draw = &drawBuffer[(*scanlineY)*(screen->w)];
|
|
#else
|
|
unsigned short* draw = &drawBuffer[(*scanlineY)*(screen->w+PSP_FUDGE)];/* extra fudge factor for PSP??? */
|
|
#endif
|
|
unsigned short bgcol;
|
|
unsigned int bw = (m_emuInfo.machine == NGP);
|
|
unsigned short OOWCol = NGPC_TO_SDL16(oowTable[*oowSelect & 0x07]);
|
|
unsigned short* pal;
|
|
unsigned short* mempal;
|
|
|
|
if (*scanlineY==0)
|
|
sortSprites(bw);
|
|
if (*scanlineY<*wndTopLeftY || *scanlineY>*wndTopLeftY+*wndSizeY || *wndSizeX==0 || *wndSizeY==0)
|
|
{
|
|
|
|
for (i=0;i<NGPC_SIZEX;i++)
|
|
draw[i] = OOWCol;
|
|
}
|
|
else
|
|
{
|
|
if (((*scanlineY)&7) == 0)
|
|
{
|
|
if (bw)
|
|
{
|
|
for(i=0;i<4;i++)
|
|
{
|
|
myPalettes[i] = NGPC_TO_SDL16(bwTable[bw_palette_table[i] & 0x07]);
|
|
myPalettes[4+i] = NGPC_TO_SDL16(bwTable[bw_palette_table[4+i] & 0x07]);
|
|
myPalettes[64+i] = NGPC_TO_SDL16(bwTable[bw_palette_table[8+i] & 0x07]);
|
|
myPalettes[68+i] = NGPC_TO_SDL16(bwTable[bw_palette_table[12+i] & 0x07]);
|
|
myPalettes[128+i] = NGPC_TO_SDL16(bwTable[bw_palette_table[16+i] & 0x07]);
|
|
myPalettes[132+i] = NGPC_TO_SDL16(bwTable[bw_palette_table[20+i] & 0x07]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pal = myPalettes;
|
|
mempal = palette_table;
|
|
|
|
for (i=0;i<192;i++)
|
|
*(pal++) = NGPC_TO_SDL16(*(mempal++));
|
|
}
|
|
}
|
|
|
|
|
|
if(*bgSelect & 0x80)
|
|
bgcol = NGPC_TO_SDL16(bgTable[*bgSelect & 0x07]);
|
|
else if(bw)
|
|
bgcol = NGPC_TO_SDL16(bwTable[0]);
|
|
else
|
|
bgcol = NGPC_TO_SDL16(bgTable[0]); /* maybe 0xFFF? */
|
|
|
|
/* NOTA arregla algo en m pure tlcsMemWriteB(0x83E0, 0xFF); */
|
|
|
|
|
|
x0 = *wndTopLeftX;
|
|
x1 = x0+*wndSizeX;
|
|
if (x1>NGPC_SIZEX)
|
|
x1 = NGPC_SIZEX;
|
|
|
|
for (i=x0;i<x1;i++)
|
|
draw[i] = bgcol;
|
|
|
|
if (mySprPri40.count[*scanlineY])
|
|
drawSprites(draw,mySprPri40.refs[*scanlineY],mySprPri40.count[*scanlineY],x0,x1);
|
|
|
|
if (*frame1Pri & 0x80)
|
|
{
|
|
drawScrollPlane(draw,tile_table_front,64,*scrollFrontX,*scrollFrontY+*scanlineY,x0,x1,bw);
|
|
if (mySprPri80.count[*scanlineY])
|
|
drawSprites(draw,mySprPri80.refs[*scanlineY],mySprPri80.count[*scanlineY],x0,x1);
|
|
|
|
/* NOTA Wrestling Madness && Big Bang Pro Wrestling */
|
|
if (mainrom[0x000020] != 0x66)
|
|
drawScrollPlane(draw,tile_table_back,128,*scrollBackX,*scrollBackY+*scanlineY,x0,x1,bw);
|
|
|
|
else{
|
|
if (*scrollBackY > 0)
|
|
drawScrollPlane(draw,tile_table_back,128,*scrollBackX,*scrollBackY+*scanlineY,x0,x1,bw);
|
|
else
|
|
drawScrollPlane(draw,tile_table_back,128,1,*scrollBackY+*scanlineY,x0,x1,bw);}
|
|
|
|
}
|
|
else
|
|
{
|
|
drawScrollPlane(draw,tile_table_back,128,*scrollBackX,*scrollBackY+*scanlineY,x0,x1,bw);
|
|
if (mySprPri80.count[*scanlineY])
|
|
drawSprites(draw,mySprPri80.refs[*scanlineY],mySprPri80.count[*scanlineY],x0,x1);
|
|
drawScrollPlane(draw,tile_table_front,64,*scrollFrontX,*scrollFrontY+*scanlineY,x0,x1,bw);
|
|
}
|
|
|
|
if (mySprPriC0.count[*scanlineY])
|
|
drawSprites(draw,mySprPriC0.refs[*scanlineY],mySprPriC0.count[*scanlineY],x0,x1);
|
|
|
|
for (i=0;i<x0;i++)
|
|
draw[i] = OOWCol;
|
|
for (i=x1;i<NGPC_SIZEX;i++)
|
|
draw[i] = OOWCol;
|
|
|
|
}
|
|
}
|
|
if (*scanlineY == 151)
|
|
{
|
|
/* start VBlank period */
|
|
tlcsMemWriteB(0x00008010,tlcsMemReadB(0x00008010) | 0x40);
|
|
if (render)
|
|
graphics_paint();
|
|
}
|
|
*scanlineY+= 1;
|
|
}
|
|
else if (*scanlineY == 198)
|
|
{
|
|
/* stop VBlank period */
|
|
tlcsMemWriteB(0x00008010,tlcsMemReadB(0x00008010) & ~0x40);
|
|
|
|
*scanlineY = 0;
|
|
}
|
|
else
|
|
*scanlineY+= 1;
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
* General Routines
|
|
*
|
|
*/
|
|
|
|
BOOL graphics_init(void)
|
|
{
|
|
#ifdef __LIBRETRO__
|
|
palette_init = palette_init16;
|
|
palette_init(RMASK, GMASK, BMASK);
|
|
drawBuffer = (unsigned short*)screen->pixels;
|
|
#else
|
|
dbg_print("in graphics_init\n");
|
|
|
|
switch (screen->format->BitsPerPixel)
|
|
{
|
|
case 8:
|
|
palette_init = palette_init8;
|
|
break;
|
|
case 16:
|
|
palette_init = palette_init16;
|
|
break;
|
|
case 32:
|
|
palette_init = palette_init32;
|
|
break;
|
|
}
|
|
|
|
drawBuffer = ((unsigned short*) screen->pixels) + SCREEN_OFFET;
|
|
|
|
palette_init(screen->format->Rmask,
|
|
screen->format->Gmask, screen->format->Bmask);
|
|
|
|
pngpalette_init();
|
|
#endif
|
|
|
|
switch(m_emuInfo.machine)
|
|
{
|
|
case NGP:
|
|
bgTable = (unsigned short *)bwTable;
|
|
oowTable = (unsigned short *)bwTable;
|
|
#if 0
|
|
set_palette = set_paletteBW;
|
|
#endif
|
|
graphicsBlitInit();
|
|
*scanlineY = 0;
|
|
break;
|
|
case NGPC:
|
|
bgTable = (unsigned short *)get_address(0x000083E0);
|
|
oowTable = (unsigned short *)get_address(0x000083F0);
|
|
#if 0
|
|
set_palette = set_paletteCol;
|
|
#endif
|
|
graphicsBlitInit();
|
|
*scanlineY = 0;
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|