2153 lines
68 KiB
C
2153 lines
68 KiB
C
////////////////////////////////////////////////////////////////////////////////
|
|
// GPU
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// 7.04.2002: Fixed sprites order
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
#include "log.h"
|
|
#include "rom.h"
|
|
#include "./nec/nec.h"
|
|
#include "io.h"
|
|
#include "gpu.h"
|
|
#include "ws.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
extern uint8_t *internalRam;
|
|
|
|
enum VideoModes
|
|
{
|
|
DISPLAY_MODE_GRAY = 0,
|
|
DISPLAY_MODE_2BPP = 4,
|
|
DISPLAY_MODE_P_4BPP = 7,
|
|
DISPLAY_MODE_L_4BPP = 6,
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#define RGB555(R,G,B) ((((int)(R))<<10)|(((int)(G))<<5)|((int)(B)))
|
|
|
|
uint8_t ws_gpu_operatingInColor;
|
|
uint8_t ws_videoMode;
|
|
uint8_t ws_gpu_scanline=0;
|
|
int16_t ws_palette[16*4];
|
|
int8_t ws_paletteColors[8];
|
|
int16_t wsc_palette[16*16];
|
|
int16_t ws_shades[16];
|
|
|
|
|
|
// white
|
|
#define SHADE_COLOR_RED 1.00
|
|
#define SHADE_COLOR_GREEN 1.00
|
|
#define SHADE_COLOR_BLUE 1.00
|
|
|
|
int16_t ws_colour_scheme_default[16]=
|
|
{
|
|
RGB555(SHADE_COLOR_RED*30,SHADE_COLOR_GREEN*30,SHADE_COLOR_BLUE*30),
|
|
RGB555(SHADE_COLOR_RED*28,SHADE_COLOR_GREEN*28,SHADE_COLOR_BLUE*28),
|
|
RGB555(SHADE_COLOR_RED*26,SHADE_COLOR_GREEN*26,SHADE_COLOR_BLUE*26),
|
|
RGB555(SHADE_COLOR_RED*24,SHADE_COLOR_GREEN*24,SHADE_COLOR_BLUE*24),
|
|
RGB555(SHADE_COLOR_RED*22,SHADE_COLOR_GREEN*22,SHADE_COLOR_BLUE*22),
|
|
RGB555(SHADE_COLOR_RED*20,SHADE_COLOR_GREEN*20,SHADE_COLOR_BLUE*20),
|
|
RGB555(SHADE_COLOR_RED*18,SHADE_COLOR_GREEN*18,SHADE_COLOR_BLUE*18),
|
|
RGB555(SHADE_COLOR_RED*16,SHADE_COLOR_GREEN*16,SHADE_COLOR_BLUE*16),
|
|
RGB555(SHADE_COLOR_RED*14,SHADE_COLOR_GREEN*14,SHADE_COLOR_BLUE*14),
|
|
RGB555(SHADE_COLOR_RED*12,SHADE_COLOR_GREEN*12,SHADE_COLOR_BLUE*12),
|
|
RGB555(SHADE_COLOR_RED*10,SHADE_COLOR_GREEN*10,SHADE_COLOR_BLUE*10),
|
|
RGB555(SHADE_COLOR_RED*8,SHADE_COLOR_GREEN*8,SHADE_COLOR_BLUE*8),
|
|
RGB555(SHADE_COLOR_RED*6,SHADE_COLOR_GREEN*6,SHADE_COLOR_BLUE*6),
|
|
RGB555(SHADE_COLOR_RED*4,SHADE_COLOR_GREEN*4,SHADE_COLOR_BLUE*4),
|
|
RGB555(SHADE_COLOR_RED*2,SHADE_COLOR_GREEN*2,SHADE_COLOR_BLUE*2),
|
|
RGB555(SHADE_COLOR_RED*0,SHADE_COLOR_GREEN*0,SHADE_COLOR_BLUE*0)
|
|
};
|
|
// green
|
|
#undef SHADE_COLOR_RED
|
|
#undef SHADE_COLOR_GREEN
|
|
#undef SHADE_COLOR_BLUE
|
|
#define SHADE_COLOR_RED 0.20
|
|
#define SHADE_COLOR_GREEN 0.90
|
|
#define SHADE_COLOR_BLUE 0.20
|
|
|
|
int16_t ws_colour_scheme_green[16]=
|
|
{
|
|
RGB555(SHADE_COLOR_RED*30,SHADE_COLOR_GREEN*30,SHADE_COLOR_BLUE*30),
|
|
RGB555(SHADE_COLOR_RED*28,SHADE_COLOR_GREEN*28,SHADE_COLOR_BLUE*28),
|
|
RGB555(SHADE_COLOR_RED*26,SHADE_COLOR_GREEN*26,SHADE_COLOR_BLUE*26),
|
|
RGB555(SHADE_COLOR_RED*24,SHADE_COLOR_GREEN*24,SHADE_COLOR_BLUE*24),
|
|
RGB555(SHADE_COLOR_RED*22,SHADE_COLOR_GREEN*22,SHADE_COLOR_BLUE*22),
|
|
RGB555(SHADE_COLOR_RED*20,SHADE_COLOR_GREEN*20,SHADE_COLOR_BLUE*20),
|
|
RGB555(SHADE_COLOR_RED*18,SHADE_COLOR_GREEN*18,SHADE_COLOR_BLUE*18),
|
|
RGB555(SHADE_COLOR_RED*16,SHADE_COLOR_GREEN*16,SHADE_COLOR_BLUE*16),
|
|
RGB555(SHADE_COLOR_RED*14,SHADE_COLOR_GREEN*14,SHADE_COLOR_BLUE*14),
|
|
RGB555(SHADE_COLOR_RED*12,SHADE_COLOR_GREEN*12,SHADE_COLOR_BLUE*12),
|
|
RGB555(SHADE_COLOR_RED*10,SHADE_COLOR_GREEN*10,SHADE_COLOR_BLUE*10),
|
|
RGB555(SHADE_COLOR_RED*8,SHADE_COLOR_GREEN*8,SHADE_COLOR_BLUE*8),
|
|
RGB555(SHADE_COLOR_RED*6,SHADE_COLOR_GREEN*6,SHADE_COLOR_BLUE*6),
|
|
RGB555(SHADE_COLOR_RED*4,SHADE_COLOR_GREEN*4,SHADE_COLOR_BLUE*4),
|
|
RGB555(SHADE_COLOR_RED*2,SHADE_COLOR_GREEN*2,SHADE_COLOR_BLUE*2),
|
|
RGB555(SHADE_COLOR_RED*0,SHADE_COLOR_GREEN*0,SHADE_COLOR_BLUE*0)
|
|
};
|
|
// amber
|
|
#undef SHADE_COLOR_RED
|
|
#undef SHADE_COLOR_GREEN
|
|
#undef SHADE_COLOR_BLUE
|
|
#define SHADE_COLOR_RED 1.00
|
|
#define SHADE_COLOR_GREEN 0.61
|
|
#define SHADE_COLOR_BLUE 0.00
|
|
|
|
int16_t ws_colour_scheme_amber[16]=
|
|
{
|
|
RGB555(SHADE_COLOR_RED*30,SHADE_COLOR_GREEN*30,SHADE_COLOR_BLUE*30),
|
|
RGB555(SHADE_COLOR_RED*28,SHADE_COLOR_GREEN*28,SHADE_COLOR_BLUE*28),
|
|
RGB555(SHADE_COLOR_RED*26,SHADE_COLOR_GREEN*26,SHADE_COLOR_BLUE*26),
|
|
RGB555(SHADE_COLOR_RED*24,SHADE_COLOR_GREEN*24,SHADE_COLOR_BLUE*24),
|
|
RGB555(SHADE_COLOR_RED*22,SHADE_COLOR_GREEN*22,SHADE_COLOR_BLUE*22),
|
|
RGB555(SHADE_COLOR_RED*20,SHADE_COLOR_GREEN*20,SHADE_COLOR_BLUE*20),
|
|
RGB555(SHADE_COLOR_RED*18,SHADE_COLOR_GREEN*18,SHADE_COLOR_BLUE*18),
|
|
RGB555(SHADE_COLOR_RED*16,SHADE_COLOR_GREEN*16,SHADE_COLOR_BLUE*16),
|
|
RGB555(SHADE_COLOR_RED*14,SHADE_COLOR_GREEN*14,SHADE_COLOR_BLUE*14),
|
|
RGB555(SHADE_COLOR_RED*12,SHADE_COLOR_GREEN*12,SHADE_COLOR_BLUE*12),
|
|
RGB555(SHADE_COLOR_RED*10,SHADE_COLOR_GREEN*10,SHADE_COLOR_BLUE*10),
|
|
RGB555(SHADE_COLOR_RED*8,SHADE_COLOR_GREEN*8,SHADE_COLOR_BLUE*8),
|
|
RGB555(SHADE_COLOR_RED*6,SHADE_COLOR_GREEN*6,SHADE_COLOR_BLUE*6),
|
|
RGB555(SHADE_COLOR_RED*4,SHADE_COLOR_GREEN*4,SHADE_COLOR_BLUE*4),
|
|
RGB555(SHADE_COLOR_RED*2,SHADE_COLOR_GREEN*2,SHADE_COLOR_BLUE*2),
|
|
RGB555(SHADE_COLOR_RED*0,SHADE_COLOR_GREEN*0,SHADE_COLOR_BLUE*0)
|
|
};
|
|
|
|
uint8_t *ws_tile_cache;
|
|
uint8_t *ws_hflipped_tile_cache;
|
|
|
|
uint8_t *wsc_tile_cache;
|
|
uint8_t *wsc_hflipped_tile_cache;
|
|
|
|
uint8_t *ws_modified_tile;
|
|
uint8_t *wsc_modified_tile;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void ws_gpu_set_colour_scheme(int scheme)
|
|
{
|
|
switch (scheme)
|
|
{
|
|
case COLOUR_SCHEME_DEFAULT:
|
|
memcpy(ws_shades,ws_colour_scheme_default,16*sizeof(int16_t));
|
|
break;
|
|
|
|
case COLOUR_SCHEME_AMBER :
|
|
memcpy(ws_shades,ws_colour_scheme_amber,16*sizeof(int16_t));
|
|
break;
|
|
|
|
case COLOUR_SCHEME_GREEN :
|
|
memcpy(ws_shades,ws_colour_scheme_green,16*sizeof(int16_t));
|
|
break;
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void ws_gpu_init(void)
|
|
{
|
|
ws_tile_cache = (uint8_t*)malloc(1024*8*8);
|
|
wsc_tile_cache = (uint8_t*)malloc(1024*8*8);
|
|
|
|
ws_hflipped_tile_cache = (uint8_t*)malloc(1024*8*8);
|
|
wsc_hflipped_tile_cache = (uint8_t*)malloc(1024*8*8);
|
|
|
|
ws_modified_tile = (uint8_t*)malloc(1024);
|
|
wsc_modified_tile = (uint8_t*)malloc(1024);
|
|
|
|
memset(ws_tile_cache,0x00,1024*8*8);
|
|
memset(wsc_tile_cache,0x00,1024*8*8);
|
|
|
|
memset(ws_hflipped_tile_cache,0x00,1024*8*8);
|
|
memset(wsc_hflipped_tile_cache,0x00,1024*8*8);
|
|
|
|
memset(ws_modified_tile,0x01,1024);
|
|
memset(wsc_modified_tile,0x01,1024);
|
|
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void ws_gpu_done(void)
|
|
{
|
|
free(ws_tile_cache);
|
|
free(wsc_tile_cache);
|
|
free(ws_hflipped_tile_cache);
|
|
free(wsc_hflipped_tile_cache);
|
|
free(ws_modified_tile);
|
|
free(wsc_modified_tile);
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void ws_gpu_changeVideoMode(uint8_t value)
|
|
{
|
|
if (ws_videoMode != (value >> 5))
|
|
{
|
|
ws_videoMode = value >> 5;
|
|
memset(ws_modified_tile, 0x01, 1024);
|
|
}
|
|
ws_gpu_operatingInColor = 0;
|
|
if (value & 0x80)
|
|
{
|
|
ws_gpu_operatingInColor = 1;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void ws_gpu_reset(void)
|
|
{
|
|
memset(ws_modified_tile,0x01,1024);
|
|
ws_gpu_scanline=0;
|
|
ws_gpu_changeVideoMode(0x00);
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void ws_gpu_clearCache(void)
|
|
{
|
|
memset(ws_modified_tile,0x01,1024);
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
uint8_t *ws_tileCache_getTileRow(uint32_t tileIndex, uint32_t line,
|
|
uint32_t vFlip, uint32_t hFlip, uint32_t bank)
|
|
{
|
|
if (ws_gpu_operatingInColor)
|
|
{
|
|
if (bank)
|
|
{
|
|
tileIndex+=512;
|
|
}
|
|
|
|
// need to update tile cache ?
|
|
// 4 colors tiles
|
|
if ((ws_videoMode == DISPLAY_MODE_2BPP) && ( ws_modified_tile[tileIndex]) )
|
|
{
|
|
uint8_t *tileInCachePtr = &wsc_tile_cache[tileIndex<<6];
|
|
uint8_t *hflippedTileInCachePtr = &wsc_hflipped_tile_cache[tileIndex<<6];
|
|
uint16_t *tileInRamPtr = (uint16_t*)&internalRam[0x2000+(tileIndex<<4)];
|
|
uint16_t tileLine;
|
|
|
|
for (int line=0; line<8; line++)
|
|
{
|
|
tileLine=*tileInRamPtr++;
|
|
|
|
tileInCachePtr[0]=((tileLine&0x80)>>7)|((tileLine&0x8000)>>14);
|
|
hflippedTileInCachePtr[7]=tileInCachePtr[0];
|
|
tileInCachePtr[1]=((tileLine&0x40)>>6)|((tileLine&0x4000)>>13);
|
|
hflippedTileInCachePtr[6]=tileInCachePtr[1];
|
|
tileInCachePtr[2]=((tileLine&0x20)>>5)|((tileLine&0x2000)>>12);
|
|
hflippedTileInCachePtr[5]=tileInCachePtr[2];
|
|
tileInCachePtr[3]=((tileLine&0x10)>>4)|((tileLine&0x1000)>>11);
|
|
hflippedTileInCachePtr[4]=tileInCachePtr[3];
|
|
tileInCachePtr[4]=((tileLine&0x08)>>3)|((tileLine&0x0800)>>10);
|
|
hflippedTileInCachePtr[3]=tileInCachePtr[4];
|
|
tileInCachePtr[5]=((tileLine&0x04)>>2)|((tileLine&0x0400)>>9);
|
|
hflippedTileInCachePtr[2]=tileInCachePtr[5];
|
|
tileInCachePtr[6]=((tileLine&0x02)>>1)|((tileLine&0x0200)>>8);
|
|
hflippedTileInCachePtr[1]=tileInCachePtr[6];
|
|
tileInCachePtr[7]=((tileLine&0x01)>>0)|((tileLine&0x0100)>>7);
|
|
hflippedTileInCachePtr[0]=tileInCachePtr[7];
|
|
|
|
tileInCachePtr+=8;
|
|
hflippedTileInCachePtr+=8;
|
|
}
|
|
|
|
ws_modified_tile[tileIndex]=0;
|
|
}
|
|
else if (wsc_modified_tile[tileIndex])
|
|
{
|
|
// 16 colors by tile layered mode
|
|
if (ws_videoMode == DISPLAY_MODE_L_4BPP)
|
|
{
|
|
uint8_t *tileInCachePtr = &wsc_tile_cache[tileIndex<<6];
|
|
uint8_t *hflippedTileInCachePtr = &wsc_hflipped_tile_cache[tileIndex<<6];
|
|
uint32_t *tileInRamPtr = (uint32_t*)&internalRam[0x4000+(tileIndex<<5)];
|
|
uint32_t tileLine;
|
|
|
|
for (int line=0; line<8; line++)
|
|
{
|
|
tileLine=*tileInRamPtr++;
|
|
|
|
tileInCachePtr[0]=((tileLine&0x00000080)>>7)|((tileLine&0x00008000)>>14)|
|
|
((tileLine&0x00800000)>>21)|((tileLine&0x80000000)>>28);
|
|
hflippedTileInCachePtr[7]=tileInCachePtr[0];
|
|
|
|
tileInCachePtr[1]=((tileLine&0x00000040)>>6)|((tileLine&0x00004000)>>13)|
|
|
((tileLine&0x00400000)>>20)|((tileLine&0x40000000)>>27);
|
|
hflippedTileInCachePtr[6]=tileInCachePtr[1];
|
|
|
|
tileInCachePtr[2]=((tileLine&0x00000020)>>5)|((tileLine&0x00002000)>>12)|
|
|
((tileLine&0x00200000)>>19)|((tileLine&0x20000000)>>26);
|
|
hflippedTileInCachePtr[5]=tileInCachePtr[2];
|
|
|
|
tileInCachePtr[3]=((tileLine&0x00000010)>>4)|((tileLine&0x00001000)>>11)|
|
|
((tileLine&0x00100000)>>18)|((tileLine&0x10000000)>>25);
|
|
hflippedTileInCachePtr[4]=tileInCachePtr[3];
|
|
|
|
tileInCachePtr[4]=((tileLine&0x00000008)>>3)|((tileLine&0x00000800)>>10)|
|
|
((tileLine&0x00080000)>>17)|((tileLine&0x08000000)>>24);
|
|
hflippedTileInCachePtr[3]=tileInCachePtr[4];
|
|
|
|
tileInCachePtr[5]=((tileLine&0x00000004)>>2)|((tileLine&0x00000400)>>9)|
|
|
((tileLine&0x00040000)>>16)|((tileLine&0x04000000)>>23);
|
|
hflippedTileInCachePtr[2]=tileInCachePtr[5];
|
|
|
|
tileInCachePtr[6]=((tileLine&0x00000002)>>1)|((tileLine&0x00000200)>>8)|
|
|
((tileLine&0x00020000)>>15)|((tileLine&0x02000000)>>22);
|
|
hflippedTileInCachePtr[1]=tileInCachePtr[6];
|
|
|
|
tileInCachePtr[7]=((tileLine&0x00000001)>>0)|((tileLine&0x00000100)>>7)|
|
|
((tileLine&0x00010000)>>14)|((tileLine&0x01000000)>>21);
|
|
hflippedTileInCachePtr[0]=tileInCachePtr[7];
|
|
|
|
tileInCachePtr+=8;
|
|
hflippedTileInCachePtr+=8;
|
|
}
|
|
|
|
}
|
|
else
|
|
|
|
// 16 colors by tile packed mode
|
|
if (ws_videoMode == DISPLAY_MODE_P_4BPP)
|
|
{
|
|
uint8_t *tileInCachePtr = &wsc_tile_cache[tileIndex<<6];
|
|
uint8_t *hflippedTileInCachePtr = &wsc_hflipped_tile_cache[tileIndex<<6];
|
|
uint32_t *tileInRamPtr = (uint32_t*)&internalRam[0x4000+(tileIndex<<5)];
|
|
uint32_t tileLine;
|
|
|
|
for (int line=0; line<8; line++)
|
|
{
|
|
tileLine=*tileInRamPtr++;
|
|
|
|
tileInCachePtr[0]=(tileLine>>4)&0x0f;
|
|
hflippedTileInCachePtr[7]=tileInCachePtr[0];
|
|
tileInCachePtr[1]=(tileLine>>0)&0x0f;
|
|
hflippedTileInCachePtr[6]=tileInCachePtr[1];
|
|
tileInCachePtr[2]=(tileLine>>12)&0x0f;
|
|
hflippedTileInCachePtr[5]=tileInCachePtr[2];
|
|
tileInCachePtr[3]=(tileLine>>8)&0x0f;
|
|
hflippedTileInCachePtr[4]=tileInCachePtr[3];
|
|
tileInCachePtr[4]=(tileLine>>20)&0x0f;
|
|
hflippedTileInCachePtr[3]=tileInCachePtr[4];
|
|
tileInCachePtr[5]=(tileLine>>16)&0x0f;
|
|
hflippedTileInCachePtr[2]=tileInCachePtr[5];
|
|
tileInCachePtr[6]=(tileLine>>28)&0x0f;
|
|
hflippedTileInCachePtr[1]=tileInCachePtr[6];
|
|
tileInCachePtr[7]=(tileLine>>24)&0x0f;
|
|
hflippedTileInCachePtr[0]=tileInCachePtr[7];
|
|
|
|
tileInCachePtr+=8;
|
|
hflippedTileInCachePtr+=8;
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// unknown mode
|
|
}
|
|
|
|
// tile cache updated
|
|
wsc_modified_tile[tileIndex]=0;
|
|
}
|
|
|
|
if (vFlip)
|
|
{
|
|
line=7-line;
|
|
}
|
|
|
|
if (hFlip)
|
|
{
|
|
return(&wsc_hflipped_tile_cache[(tileIndex<<6)+(line<<3)]);
|
|
}
|
|
else
|
|
{
|
|
return(&wsc_tile_cache[(tileIndex<<6)+(line<<3)]);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// need to update tile cache ?
|
|
if (ws_modified_tile[tileIndex])
|
|
{
|
|
uint8_t *tileInCachePtr = &ws_tile_cache[tileIndex<<6];
|
|
uint8_t *hflippedTileInCachePtr = &ws_hflipped_tile_cache[(tileIndex<<6)+7];
|
|
uint32_t *tileInRamPtr = (uint32_t*)&internalRam[0x2000+(tileIndex<<4)];
|
|
uint32_t tileLine;
|
|
|
|
for (int line=0; line<4; line++)
|
|
{
|
|
tileLine=*tileInRamPtr++;
|
|
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x80)>>7)|((tileLine&0x8000)>>14);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x40)>>6)|((tileLine&0x4000)>>13);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x20)>>5)|((tileLine&0x2000)>>12);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x10)>>4)|((tileLine&0x1000)>>11);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x08)>>3)|((tileLine&0x0800)>>10);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x04)>>2)|((tileLine&0x0400)>>9);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x02)>>1)|((tileLine&0x0200)>>8);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x01)>>0)|((tileLine&0x0100)>>7);
|
|
hflippedTileInCachePtr+=16;
|
|
tileLine>>=16;
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x80)>>7)|((tileLine&0x8000)>>14);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x40)>>6)|((tileLine&0x4000)>>13);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x20)>>5)|((tileLine&0x2000)>>12);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x10)>>4)|((tileLine&0x1000)>>11);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x08)>>3)|((tileLine&0x0800)>>10);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x04)>>2)|((tileLine&0x0400)>>9);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x02)>>1)|((tileLine&0x0200)>>8);
|
|
*hflippedTileInCachePtr--=*tileInCachePtr++=((tileLine&0x01)>>0)|((tileLine&0x0100)>>7);
|
|
hflippedTileInCachePtr+=16;
|
|
}
|
|
|
|
// tile cache updated
|
|
ws_modified_tile[tileIndex]=0;
|
|
}
|
|
|
|
if (vFlip)
|
|
{
|
|
line=7-line;
|
|
}
|
|
|
|
if (hFlip)
|
|
{
|
|
return(&ws_hflipped_tile_cache[(tileIndex<<6)+(line<<3)]);
|
|
}
|
|
else
|
|
{
|
|
return(&ws_tile_cache[(tileIndex<<6)+(line<<3)]);
|
|
}
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void ws_drawClippedSpriteLine(int16_t *framebuffer, uint16_t scanline,
|
|
uint32_t x, uint32_t y, uint32_t tileIndex, uint32_t paletteIndex,
|
|
uint32_t vFlip, uint32_t hFlip,
|
|
uint32_t clip_x0, uint32_t clip_y0, uint32_t clip_x1, uint32_t clip_y1)
|
|
{
|
|
|
|
if ((scanline<y)||(scanline>(y+7)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (((x+7<clip_x0)||(x>=clip_x1)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(scanline>clip_y0 && scanline<clip_y1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow(tileIndex,(scanline-y)&0x07,hFlip,vFlip, 0);
|
|
uint16_t nbPixels=8;
|
|
|
|
if (x<clip_x0)
|
|
{
|
|
ws_tileRow+=clip_x0-x;
|
|
nbPixels-=clip_x0-x;
|
|
x=clip_x0;
|
|
}
|
|
|
|
if (x+nbPixels>clip_x1)
|
|
{
|
|
nbPixels=(clip_x1-x);
|
|
}
|
|
|
|
framebuffer+=x;
|
|
|
|
if (ws_gpu_operatingInColor)
|
|
{
|
|
int16_t *wsc_paletteAlias=&wsc_palette[paletteIndex<<4];
|
|
|
|
while (nbPixels)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*framebuffer=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
framebuffer++;
|
|
ws_tileRow++;
|
|
nbPixels--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int16_t *ws_paletteAlias=&ws_palette[paletteIndex<<2];
|
|
|
|
if (paletteIndex&0x04)
|
|
{
|
|
while (nbPixels)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*framebuffer=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
framebuffer++;
|
|
ws_tileRow++;
|
|
nbPixels--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (nbPixels)
|
|
{
|
|
*framebuffer=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
framebuffer++;
|
|
ws_tileRow++;
|
|
nbPixels--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void ws_gpu_renderScanline(int16_t *framebuffer)
|
|
{
|
|
|
|
if (ws_gpu_scanline>143)
|
|
{
|
|
return;
|
|
}
|
|
|
|
framebuffer+=(224*ws_gpu_scanline);
|
|
|
|
// fill with background color
|
|
int16_t backgroundColor;
|
|
|
|
if (ws_gpu_operatingInColor)
|
|
{
|
|
backgroundColor=wsc_palette[ws_ioRam[0x01]];
|
|
}
|
|
else
|
|
{
|
|
backgroundColor=ws_shades[ws_paletteColors[ws_palette[((ws_ioRam[0x01]&0xf0)>>2)+(ws_ioRam[0x01]&0x03)]]];
|
|
}
|
|
|
|
for (int i=0; i<224; i++)
|
|
{
|
|
framebuffer[i]=backgroundColor;
|
|
}
|
|
|
|
|
|
// render background layer
|
|
if (ws_ioRam[0x00]&0x01)
|
|
{
|
|
int ws_bgScroll_x=ws_ioRam[0x10];
|
|
int ws_bgScroll_y=ws_ioRam[0x11];
|
|
|
|
// seek to the first tile
|
|
ws_bgScroll_y=(ws_bgScroll_y+ws_gpu_scanline)&0xff;
|
|
|
|
// note: byte ordering assumptions!
|
|
int ws_currentTile=(ws_bgScroll_x>>3);
|
|
uint16_t *ws_bgScrollRamBase=(uint16_t*)(internalRam+(((uint32_t)ws_ioRam[0x07]&0x0f)<<11)+
|
|
((ws_bgScroll_y&0xfff8)<<3));
|
|
|
|
int lineInTile = ws_bgScroll_y&0x07;
|
|
int columnInTile = ws_bgScroll_x&0x07;
|
|
|
|
int16_t *scanlinePtr=framebuffer;
|
|
|
|
if (ws_gpu_operatingInColor)
|
|
{
|
|
// render the first clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_bgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile, tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
ws_tileRow+=columnInTile;
|
|
|
|
for (int i=columnInTile; i<8; i++)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
|
|
// render the tiles between them
|
|
int nbTiles=28;
|
|
|
|
if (columnInTile)
|
|
{
|
|
nbTiles=27;
|
|
}
|
|
|
|
for (int i=0; i<nbTiles; i++)
|
|
{
|
|
uint16_t tileInfo=ws_bgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile, tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
|
|
// render the last clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_bgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
|
|
for (int i=0; i<columnInTile; i++)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// render the first clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_bgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
ws_tileRow+=columnInTile;
|
|
|
|
if ((tileInfo>>9)&0x04)
|
|
{
|
|
for (int i=columnInTile; i<8; i++)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i=columnInTile; i<8; i++)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
}
|
|
|
|
int nbTiles=28;
|
|
|
|
if (columnInTile)
|
|
{
|
|
nbTiles=27;
|
|
}
|
|
|
|
for (int i=0; i<nbTiles; i++)
|
|
{
|
|
uint16_t tileInfo=ws_bgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
|
|
if ((tileInfo>>9)&0x04)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
else
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
|
|
}
|
|
|
|
// render the last clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_bgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
|
|
|
|
if ((tileInfo>>9)&0x04)
|
|
{
|
|
for (int i=0; i<columnInTile; i++)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i=0; i<columnInTile; i++)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// render sprites which are between both layers
|
|
if (ws_ioRam[0x00]&0x04)
|
|
{
|
|
int ws_sprWindow_x0=ws_ioRam[0x0c];
|
|
int ws_sprWindow_y0=ws_ioRam[0x0d];
|
|
int ws_sprWindow_x1=ws_sprWindow_x0+ws_ioRam[0x0e];
|
|
int ws_sprWindow_y1=ws_sprWindow_y0+ws_ioRam[0x0f];
|
|
uint32_t *ws_sprRamBase=(uint32_t*)(internalRam+(((uint32_t)ws_ioRam[0x04])<<9));
|
|
|
|
// seek to first sprite
|
|
ws_sprRamBase+=ws_ioRam[0x06]-1;
|
|
|
|
for (int i=ws_ioRam[0x06]; i>ws_ioRam[0x05]; i--)
|
|
{
|
|
uint32_t spr=*ws_sprRamBase--;
|
|
|
|
if (!(spr&0x2000))
|
|
{
|
|
// sprite window on ?
|
|
if ((ws_ioRam[0x00]&0x08)&&(spr&0x1000)&&(ws_sprWindow_x0!=ws_sprWindow_x1))
|
|
{
|
|
ws_drawClippedSpriteLine(framebuffer,ws_gpu_scanline,(spr&0xff000000)>>24, (spr&0x00ff0000)>>16,
|
|
spr&0x1ff,8+((spr&0xe00)>>9),spr&0x4000,spr&0x8000,
|
|
ws_sprWindow_x0,ws_sprWindow_y0,ws_sprWindow_x1,ws_sprWindow_y1);
|
|
}
|
|
else
|
|
{
|
|
ws_drawClippedSpriteLine(framebuffer,ws_gpu_scanline,(spr&0xff000000)>>24, (spr&0x00ff0000)>>16,
|
|
spr&0x1ff,8+((spr&0xe00)>>9),spr&0x4000,spr&0x8000,
|
|
//0,0,224,144);
|
|
0,0,224,0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// render foreground layer
|
|
if (ws_ioRam[0x00]&0x02)
|
|
{
|
|
int ws_fgWindow_x0=ws_ioRam[0x08];
|
|
int ws_fgWindow_x1=ws_ioRam[0x0a];
|
|
int ws_fgScroll_x=ws_ioRam[0x12];
|
|
int ws_fgScroll_y=ws_ioRam[0x13];
|
|
|
|
int windowMode = ws_ioRam[0x00]&0x30;
|
|
|
|
// seek to the first tile
|
|
ws_fgScroll_y=(ws_fgScroll_y+ws_gpu_scanline)&0xff;
|
|
|
|
// note: byte ordering assumptions!
|
|
int ws_currentTile=(ws_fgScroll_x>>3);
|
|
uint16_t *ws_fgScrollRamBase=(uint16_t*)(internalRam+(((uint32_t)ws_ioRam[0x07]&0xf0)<<7)+
|
|
((ws_fgScroll_y&0xfff8)<<3));
|
|
|
|
int lineInTile = ws_fgScroll_y&0x07;
|
|
int columnInTile = ws_fgScroll_x&0x07;
|
|
|
|
int16_t *scanlinePtr=framebuffer;
|
|
|
|
|
|
// window disabled
|
|
if (!windowMode)
|
|
{
|
|
if (ws_gpu_operatingInColor)
|
|
{
|
|
// render the first clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow(
|
|
tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000,
|
|
tileInfo&0x4000,
|
|
tileInfo&0x2000);
|
|
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
ws_tileRow+=columnInTile;
|
|
|
|
for (int i=columnInTile; i<8; i++)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
|
|
// render the tiles between them
|
|
int nbTiles=28;
|
|
|
|
if (columnInTile)
|
|
{
|
|
nbTiles=27;
|
|
}
|
|
|
|
for (int i=0; i<nbTiles; i++)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
|
|
// render the last clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
|
|
for (int i=0; i<columnInTile; i++)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// render the first clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
ws_tileRow+=columnInTile;
|
|
|
|
if ((tileInfo>>9)&0x04)
|
|
{
|
|
for (int i=columnInTile; i<8; i++)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i=columnInTile; i<8; i++)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
}
|
|
|
|
int nbTiles=28;
|
|
|
|
if (columnInTile)
|
|
{
|
|
nbTiles=27;
|
|
}
|
|
|
|
for (int i=0; i<nbTiles; i++)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
|
|
if ((tileInfo>>9)&0x04)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
else
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
|
|
// render the last clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
|
|
|
|
if ((tileInfo>>9)&0x04)
|
|
{
|
|
for (int i=0; i<columnInTile; i++)
|
|
{
|
|
if (*ws_tileRow)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i=0; i<columnInTile; i++)
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
|
|
// foreground layer displayed only inside the window
|
|
if (windowMode==0x20)
|
|
{
|
|
int column=0;
|
|
|
|
if (ws_gpu_operatingInColor)
|
|
{
|
|
// render the first clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
ws_tileRow+=columnInTile;
|
|
|
|
for (int i=columnInTile; i<8; i++)
|
|
{
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
column++;
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
|
|
// render the tiles between them
|
|
int nbTiles=28;
|
|
|
|
if (columnInTile)
|
|
{
|
|
nbTiles=27;
|
|
}
|
|
|
|
for (int i=0; i<nbTiles; i++)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
}
|
|
|
|
// render the last clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
|
|
for (int i=0; i<columnInTile; i++)
|
|
{
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
column++;
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// render the first clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
ws_tileRow+=columnInTile;
|
|
|
|
for (int i=columnInTile; i<8; i++)
|
|
{
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
column++;
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
|
|
int nbTiles=28;
|
|
|
|
if (columnInTile)
|
|
{
|
|
nbTiles=27;
|
|
}
|
|
|
|
for (int i=0; i<nbTiles; i++)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
}
|
|
|
|
// render the last clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
|
|
|
|
for (int i=0; i<columnInTile; i++)
|
|
{
|
|
if ((*ws_tileRow)&&(column>=ws_fgWindow_x0)&&(column<=ws_fgWindow_x1))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
column++;
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
|
|
// foreground layer displayed only outside the window
|
|
if (windowMode==0x30)
|
|
{
|
|
int column=0;
|
|
|
|
if (ws_gpu_operatingInColor)
|
|
{
|
|
// render the first clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
ws_tileRow+=columnInTile;
|
|
|
|
for (int i=columnInTile; i<8; i++)
|
|
{
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
column++;
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
|
|
// render the tiles between them
|
|
int nbTiles=28;
|
|
|
|
if (columnInTile)
|
|
{
|
|
nbTiles=27;
|
|
}
|
|
|
|
for (int i=0; i<nbTiles; i++)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
}
|
|
|
|
// render the last clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *wsc_paletteAlias=&wsc_palette[((tileInfo>>9)&0x0f)<<4];
|
|
|
|
|
|
for (int i=0; i<columnInTile; i++)
|
|
{
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=wsc_paletteAlias[*ws_tileRow];
|
|
}
|
|
|
|
column++;
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// render the first clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
ws_tileRow+=columnInTile;
|
|
|
|
for (int i=columnInTile; i<8; i++)
|
|
{
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
column++;
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
|
|
int nbTiles=28;
|
|
|
|
if (columnInTile)
|
|
{
|
|
nbTiles=27;
|
|
}
|
|
|
|
for (int i=0; i<nbTiles; i++)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile, tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
column++;
|
|
}
|
|
|
|
// render the last clipped tile
|
|
if (columnInTile)
|
|
{
|
|
uint16_t tileInfo=ws_fgScrollRamBase[ws_currentTile&0x1f];
|
|
ws_currentTile++;
|
|
uint8_t *ws_tileRow=ws_tileCache_getTileRow( tileInfo&0x1ff, lineInTile,
|
|
tileInfo&0x8000, tileInfo&0x4000, tileInfo&0x2000);
|
|
int16_t *ws_paletteAlias=&ws_palette[((tileInfo>>9)&0x0f)<<2];
|
|
|
|
|
|
for (int i=0; i<columnInTile; i++)
|
|
{
|
|
if ((*ws_tileRow)&&((column<ws_fgWindow_x0)||(column>ws_fgWindow_x1)))
|
|
{
|
|
*scanlinePtr=ws_shades[ws_paletteColors[ws_paletteAlias[*ws_tileRow]]];
|
|
}
|
|
|
|
column++;
|
|
scanlinePtr++;
|
|
ws_tileRow++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// unknown
|
|
}
|
|
}
|
|
|
|
|
|
// render sprites
|
|
if (ws_ioRam[0x00]&0x04)
|
|
{
|
|
int ws_sprWindow_x0=ws_ioRam[0x0c];
|
|
int ws_sprWindow_y0=ws_ioRam[0x0d];
|
|
int ws_sprWindow_x1=ws_ioRam[0x0e];
|
|
int ws_sprWindow_y1=ws_ioRam[0x0f];
|
|
uint32_t *ws_sprRamBase=(uint32_t*)(internalRam+(((uint32_t)ws_ioRam[0x04])<<9));
|
|
|
|
// seek to first sprite
|
|
ws_sprRamBase+=ws_ioRam[0x06]-1;
|
|
|
|
for (int i=ws_ioRam[0x06]; i>ws_ioRam[0x05]; i--)
|
|
{
|
|
uint32_t spr=*ws_sprRamBase--;
|
|
|
|
if (spr&0x2000)
|
|
{
|
|
// sprite window on ?
|
|
if ((ws_ioRam[0x00]&0x08)&&(spr&0x1000)&&(ws_sprWindow_x0!=ws_sprWindow_x1))
|
|
{
|
|
ws_drawClippedSpriteLine(framebuffer,ws_gpu_scanline,(spr&0xff000000)>>24, (spr&0x00ff0000)>>16,
|
|
spr&0x1ff,8+((spr&0xe00)>>9),spr&0x4000,spr&0x8000,
|
|
ws_sprWindow_x0,ws_sprWindow_y0,ws_sprWindow_x1,ws_sprWindow_y1);
|
|
}
|
|
else
|
|
{
|
|
ws_drawClippedSpriteLine(framebuffer,ws_gpu_scanline,(spr&0xff000000)>>24, (spr&0x00ff0000)>>16,
|
|
spr&0x1ff,8+((spr&0xe00)>>9),spr&0x4000,spr&0x8000,
|
|
// 0,0,224,144);
|
|
0,0,224,0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void ws_gpu_write_byte(uint32_t offset, uint8_t value)
|
|
{
|
|
// ws 4 color tiles
|
|
if ((offset>=0x2000)&&(offset<0x4000))
|
|
{
|
|
if (internalRam[offset]!=value)
|
|
{
|
|
ws_modified_tile[(offset&0x1fff)>>4]=1;
|
|
}
|
|
|
|
// update the ram
|
|
internalRam[offset]=value;
|
|
}
|
|
|
|
if (ws_gpu_operatingInColor)
|
|
{
|
|
// wsc 16 color tiles bank 0
|
|
if ((offset>=0x4000)&&(offset<0x8000))
|
|
{
|
|
if (internalRam[offset]!=value)
|
|
{
|
|
wsc_modified_tile[(offset&0x3fff)>>5]=1;
|
|
}
|
|
}
|
|
else
|
|
|
|
// wsc 16 color tiles bank 1
|
|
if ((offset>=0x8000)&&(offset<0xC000))
|
|
{
|
|
if (internalRam[offset]!=value)
|
|
{
|
|
wsc_modified_tile[512+((offset&0x3fff)>>5)]=1;
|
|
}
|
|
}
|
|
|
|
// update the ram
|
|
internalRam[offset]=value;
|
|
|
|
// palette ram
|
|
if (offset>=0xfe00)
|
|
{
|
|
// RGB444 format
|
|
uint16_t color=(internalRam[(offset&0xfffe)+1]);
|
|
color<<=8;
|
|
color|=(internalRam[(offset&0xfffe)]);
|
|
|
|
wsc_palette[(offset&0x1ff)>>1]=RGB555(((color>>8)&0x0f)<<1,((color>>4)&0x0f)<<1,(color&0x0f)<<1);
|
|
}
|
|
}
|
|
else if (offset<0x4000)
|
|
{
|
|
internalRam[offset]=value;
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
unsigned int ws_gpu_unknownPort;
|
|
|
|
int ws_gpu_port_write(uint32_t port, uint8_t value)
|
|
{
|
|
ws_gpu_unknownPort = 0;
|
|
|
|
switch (port)
|
|
{
|
|
case 0x60:
|
|
if (ws_get_system() != WS_SYSTEM_MONO)
|
|
{
|
|
ws_gpu_changeVideoMode(value);
|
|
}
|
|
return 0;
|
|
|
|
case 0x1C:
|
|
ws_paletteColors[0] = value & 0xf;
|
|
ws_paletteColors[1] = (value >> 4) & 0xf;
|
|
return 0;
|
|
|
|
case 0x1D:
|
|
ws_paletteColors[2] = value & 0xf;
|
|
ws_paletteColors[3] = (value >> 4) & 0xf;
|
|
return 0;
|
|
|
|
case 0x1E:
|
|
ws_paletteColors[4] = value & 0xf;
|
|
ws_paletteColors[5] = (value >> 4) & 0xf;
|
|
return 0;
|
|
|
|
case 0x1F:
|
|
ws_paletteColors[6] = value & 0xf;
|
|
ws_paletteColors[7] = (value >> 4) & 0xf;
|
|
return 0;
|
|
|
|
default:ws_gpu_unknownPort = 1;
|
|
}
|
|
|
|
if ((port >= 0x20) && (port <= 0x3f))
|
|
{
|
|
ws_gpu_unknownPort = 0;
|
|
port -= 0x20;
|
|
int paletteIndex = port >> 1;
|
|
|
|
if (port & 0x01)
|
|
{
|
|
ws_palette[(paletteIndex << 2) + 2] = value & 0x7;
|
|
ws_palette[(paletteIndex << 2) + 3] = (value >> 4) & 0x7;
|
|
}
|
|
else
|
|
{
|
|
ws_palette[(paletteIndex << 2) + 0] = value & 0x7;
|
|
ws_palette[(paletteIndex << 2) + 1] = (value >> 4) & 0x7;
|
|
}
|
|
}
|
|
|
|
return ws_gpu_unknownPort;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
uint8_t ws_gpu_port_read(uint8_t port)
|
|
{
|
|
switch (port)
|
|
{
|
|
case 0xa0:
|
|
ws_ioRam[0xA0] |= 0x80;
|
|
if (ws_get_system() == WS_SYSTEM_MONO)
|
|
{
|
|
return ws_ioRam[0xa0] & (~0x2);
|
|
}
|
|
else
|
|
{
|
|
return ws_ioRam[0xa0] | 2;
|
|
}
|
|
break;
|
|
|
|
case 0xaa:
|
|
return vblank_count & 0xff;
|
|
|
|
case 0xab:
|
|
return (vblank_count >> 8) & 0xff;
|
|
|
|
case 0xac:
|
|
return (vblank_count >> 16) & 0xff;
|
|
|
|
case 0xad:
|
|
return (vblank_count >> 24) & 0xff;
|
|
}
|
|
|
|
return (ws_ioRam[port]);
|
|
}
|