2068 lines
72 KiB
C
2068 lines
72 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 = 0;
|
|
uint8_t ws_videoMode = DISPLAY_MODE_GRAY;
|
|
uint8_t ws_gpu_scanline = 0;
|
|
int16_t ws_palette[16 * 4];
|
|
int8_t ws_paletteColors[8];
|
|
int16_t wsc_palette[16 * 16];
|
|
|
|
// white
|
|
#define SHADE_COLOR_RED 1.00
|
|
#define SHADE_COLOR_GREEN 1.00
|
|
#define SHADE_COLOR_BLUE 1.00
|
|
|
|
int16_t ws_shades[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_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]);
|
|
}
|