mirror of
https://github.com/libretro/gambatte-libretro.git
synced 2024-11-27 01:40:23 +00:00
do sprite sorting and cycle calculations pr line as needed instead of all at once
git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@105 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
parent
e899db1bf5
commit
a2c291b48f
@ -94,7 +94,7 @@ LCD::LCD(const uint8_t *const oamram, const uint8_t *const vram_in) :
|
||||
m3EventQueue(11, VideoEventComparer()),
|
||||
irqEventQueue(4, VideoEventComparer()),
|
||||
vEventQueue(5, VideoEventComparer()),
|
||||
m3ExtraCycles(spriteMapper, scxReader, weMasterChecker, wyReg, we, wxReader),
|
||||
m3ExtraCycles(*this),
|
||||
weMasterChecker(m3EventQueue, wyReg, lyCounter),
|
||||
wyReg(lyCounter, weMasterChecker),
|
||||
wxReader(m3EventQueue, we.enableChecker(), we.disableChecker()),
|
||||
@ -1259,9 +1259,10 @@ void LCD::cgb_drawSprites(T * const buffer_line, const unsigned ypos) {
|
||||
const unsigned wx = wxReader.wx() < 7 ? 0 : wxReader.wx() - 7;
|
||||
//const bool enableWindow = (memory.fastread(0xFF40) & 0x20) && (ypos >= memory.fastread(0xFF4A)) && (wx < 160);
|
||||
const bool enableWindow = (weMasterChecker.weMaster() || ypos == wyReg.value()) && we.value() && wyReg.value() <= ypos && wxReader.wx() < 0xA7;
|
||||
const unsigned short *const spriteMapLine = spriteMapper.sprites(ypos);
|
||||
|
||||
for (int i = spriteMapper.spriteMap()[ypos * 12 + 10] - 1; i >= 0; --i) {
|
||||
const uint8_t *const spriteInfo = spriteMapper.oamram + (spriteMapper.spriteMap()[ypos*12+i] & 0xFF);
|
||||
for (int i = spriteMapper.numSprites(ypos) - 1; i >= 0; --i) {
|
||||
const uint8_t *const spriteInfo = spriteMapper.oamram + (spriteMapLine[i] & 0xFF);
|
||||
const unsigned spx = spriteInfo[1];
|
||||
|
||||
if (spx < 168 && spx) {
|
||||
@ -1431,9 +1432,10 @@ void LCD::drawSprites(T * const buffer_line, const unsigned ypos) {
|
||||
const unsigned scy = (scReader.scy() + ypos)/*&0xFF*/;
|
||||
const unsigned wx = wxReader.wx() < 7 ? 0 : wxReader.wx() - 7;
|
||||
const bool enableWindow = (weMasterChecker.weMaster() || ypos == wyReg.value()) && we.value() && wyReg.value() <= ypos && wxReader.wx() < 0xA7;
|
||||
const unsigned short *const spriteMapLine = spriteMapper.sprites(ypos);
|
||||
|
||||
for (int i = spriteMapper.spriteMap()[ypos * 12 + 10] - 1; i >= 0; --i) {
|
||||
const uint8_t *const spriteInfo = spriteMapper.oamram + (spriteMapper.spriteMap()[ypos * 12 + i] & 0xFF);
|
||||
for (int i = spriteMapper.numSprites(ypos) - 1; i >= 0; --i) {
|
||||
const uint8_t *const spriteInfo = spriteMapper.oamram + (spriteMapLine[i] & 0xFF);
|
||||
const unsigned spx = spriteInfo[1];
|
||||
|
||||
if (spx < 168 && spx) {
|
||||
|
@ -50,6 +50,8 @@ class Filter;
|
||||
#include "video/m3_extra_cycles.h"
|
||||
|
||||
class LCD {
|
||||
friend class M3ExtraCycles;
|
||||
|
||||
//static const uint8_t xflipt[0x100];
|
||||
uint32_t dmgColorsRgb32[3 * 4];
|
||||
uint32_t dmgColorsRgb16[3 * 4];
|
||||
|
@ -15,36 +15,21 @@
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
***************************************************************************/
|
||||
#include "m3_extra_cycles.h"
|
||||
|
||||
#include "sprite_mapper.h"
|
||||
#include "scx_reader.h"
|
||||
#include "we_master_checker.h"
|
||||
#include "wy.h"
|
||||
#include "we.h"
|
||||
#include "wx_reader.h"
|
||||
#include "../video.h"
|
||||
|
||||
M3ExtraCycles::M3ExtraCycles(const SpriteMapper &spriteMapper_in,
|
||||
const ScxReader &scxReader_in,
|
||||
const WeMasterChecker &weMasterChecker_in,
|
||||
const Wy &wyReg_in,
|
||||
const We &we_in,
|
||||
const WxReader &wxReader_in) :
|
||||
spriteMapper(spriteMapper_in),
|
||||
scxReader(scxReader_in),
|
||||
weMasterChecker(weMasterChecker_in),
|
||||
wyReg(wyReg_in),
|
||||
we(we_in),
|
||||
wxReader(wxReader_in)
|
||||
M3ExtraCycles::M3ExtraCycles(const LCD &video) :
|
||||
video(video)
|
||||
{}
|
||||
|
||||
unsigned M3ExtraCycles::operator()(const unsigned ly) const {
|
||||
unsigned cycles = spriteMapper.spriteMap()[ly * 12 + 11];
|
||||
unsigned cycles = video.spriteMapper.spriteCycles(ly);
|
||||
|
||||
cycles += scxReader.scxAnd7();
|
||||
cycles += video.scxReader.scxAnd7();
|
||||
|
||||
if ((weMasterChecker.weMaster() || ly == wyReg.value()) && we.value() && wyReg.value() <= ly && wxReader.wx() < 0xA7)
|
||||
if (video.we.value() && video.wxReader.wx() < 0xA7 && ly >= video.wyReg.value() && (video.weMasterChecker.weMaster() || ly == video.wyReg.value()))
|
||||
cycles += 6;
|
||||
|
||||
return cycles;
|
||||
|
@ -15,33 +15,17 @@
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
***************************************************************************/
|
||||
#ifndef VIDEO_M3_EXTRA_CYCLES_H
|
||||
#define VIDEO_M3_EXTRA_CYCLES_H
|
||||
|
||||
class SpriteMapper;
|
||||
class ScxReader;
|
||||
class WeMasterChecker;
|
||||
class Wy;
|
||||
class We;
|
||||
class WxReader;
|
||||
class LCD;
|
||||
|
||||
class M3ExtraCycles {
|
||||
const SpriteMapper &spriteMapper;
|
||||
const ScxReader &scxReader;
|
||||
const WeMasterChecker &weMasterChecker;
|
||||
const Wy &wyReg;
|
||||
const We &we;
|
||||
const WxReader &wxReader;
|
||||
const LCD &video;
|
||||
|
||||
public:
|
||||
M3ExtraCycles(const SpriteMapper &spriteMapper_in,
|
||||
const ScxReader &scxReader_in,
|
||||
const WeMasterChecker &weMasterChecker_in,
|
||||
const Wy &wyReg_in,
|
||||
const We &we_in,
|
||||
const WxReader &wxReader_in);
|
||||
|
||||
M3ExtraCycles(const LCD &video);
|
||||
unsigned operator()(unsigned ly) const;
|
||||
};
|
||||
|
||||
|
@ -21,7 +21,8 @@
|
||||
#include "scx_reader.h"
|
||||
#include "../event_queue.h"
|
||||
|
||||
#include <algorithm>
|
||||
// #include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
SpriteMapper::SpriteMapper(const SpriteSizeReader &spriteSizeReader_in,
|
||||
const ScxReader &scxReader_in,
|
||||
@ -37,17 +38,53 @@ SpriteMapper::SpriteMapper(const SpriteSizeReader &spriteSizeReader_in,
|
||||
}
|
||||
|
||||
void SpriteMapper::clearMap() {
|
||||
for (uint16_t* i = &spritemap[10]; i < &spritemap[144 * 12]; i += 12)
|
||||
i[1] = i[0] = 0;
|
||||
std::memset(cycles, CYCLES_INVALID, sizeof(cycles));
|
||||
std::memset(num, 0, sizeof(num));
|
||||
}
|
||||
|
||||
static void insertionSort(uint16_t *const start, uint16_t *const end) {
|
||||
uint16_t *a = start;
|
||||
void SpriteMapper::mapSprites() {
|
||||
clearMap();
|
||||
|
||||
const unsigned spriteHeight = 8 << spriteSizeReader.largeSprites();
|
||||
|
||||
for (unsigned i = 0x00; i < 0xA0; i += 4) {
|
||||
const unsigned bottom_pos = oamram[i] - (17 - spriteHeight);
|
||||
|
||||
if (bottom_pos >= 143 + spriteHeight)
|
||||
continue;
|
||||
|
||||
const unsigned spx = oamram[i + 1];
|
||||
const unsigned value = spx << 8 | i;
|
||||
|
||||
unsigned short *map = spritemap;
|
||||
unsigned char *n = num;
|
||||
|
||||
if (bottom_pos >= spriteHeight) {
|
||||
const unsigned startly = bottom_pos + 1 - spriteHeight;
|
||||
n += startly;
|
||||
map += startly * 10;
|
||||
}
|
||||
|
||||
unsigned char *const end = num + (bottom_pos >= 143 ? 143 : bottom_pos);
|
||||
|
||||
do {
|
||||
if (*n < 10)
|
||||
map[(*n)++] = value;
|
||||
|
||||
map += 10;
|
||||
++n;
|
||||
} while (n <= end);
|
||||
}
|
||||
}
|
||||
|
||||
// unsafe if start is at the end of allocated memory, since start+1 could be undefined/of.
|
||||
static void insertionSort(unsigned short *const start, unsigned short *const end) {
|
||||
unsigned short *a = start;
|
||||
|
||||
while (++a < end) {
|
||||
const unsigned e = *a;
|
||||
|
||||
uint16_t *b = a;
|
||||
unsigned short *b = a;
|
||||
|
||||
while (b != start && *(b - 1) > e) {
|
||||
*b = *(b - 1);
|
||||
@ -58,77 +95,54 @@ static void insertionSort(uint16_t *const start, uint16_t *const end) {
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteMapper::mapSprites() {
|
||||
clearMap();
|
||||
|
||||
const unsigned spriteHeight = 8 << spriteSizeReader.largeSprites();
|
||||
|
||||
for (unsigned i = 0x00; i < 0xA0; i += 4) {
|
||||
const unsigned bottom_pos = oamram[i] - (17 - spriteHeight);
|
||||
if (bottom_pos >= 143 + spriteHeight)
|
||||
continue;
|
||||
|
||||
const unsigned spx = oamram[i + 1];
|
||||
const unsigned value = (spx << 8) | i;
|
||||
|
||||
uint16_t *tmp = &spritemap[bottom_pos < spriteHeight ? 0 : ((bottom_pos + 1 - spriteHeight) * 12)];
|
||||
uint16_t *const end = &spritemap[bottom_pos >= 143 ? 143 * 12 : (bottom_pos * 12)];
|
||||
|
||||
do {
|
||||
if (tmp[10] < 10)
|
||||
tmp[tmp[10]++] = value;
|
||||
tmp += 12;
|
||||
} while (tmp <= end);
|
||||
void SpriteMapper::updateLine(const unsigned ly) const {
|
||||
if (num[ly] == 0) {
|
||||
cycles[ly] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t sortBuf[11];
|
||||
unsigned short sortBuf[10];
|
||||
unsigned short *tmp = spritemap + ly * 10;
|
||||
|
||||
for (uint16_t *mapPos = spritemap; mapPos < spritemap + 144 * 12; mapPos += 12) {
|
||||
if (mapPos[10] == 0)
|
||||
continue;
|
||||
if (cgb) {
|
||||
std::memcpy(sortBuf, tmp, sizeof(sortBuf));
|
||||
tmp = sortBuf;
|
||||
}
|
||||
|
||||
insertionSort(tmp, tmp + num[ly]);
|
||||
// std::sort(tmp, tmp + num[ly]);
|
||||
|
||||
unsigned sum = 0;
|
||||
|
||||
for (unsigned i = 0; i < num[ly]; ++i) {
|
||||
const unsigned spx = tmp[i] >> 8;
|
||||
|
||||
uint16_t *tmp = mapPos;
|
||||
if (spx > 167)
|
||||
break;
|
||||
|
||||
if (cgb) {
|
||||
std::memcpy(sortBuf, tmp, sizeof(sortBuf));
|
||||
tmp = sortBuf;
|
||||
}
|
||||
unsigned cycles = 6;
|
||||
const unsigned posAnd7 = scxReader.scxAnd7() + spx & 7;
|
||||
|
||||
insertionSort(tmp, tmp + tmp[10]);
|
||||
// std::sort(tmp, tmp + tmp[10]);
|
||||
|
||||
unsigned sum = 0;
|
||||
|
||||
for (unsigned i = 0; i < tmp[10]; ++i) {
|
||||
const unsigned spx = tmp[i] >> 8;
|
||||
if (posAnd7 < 5) {
|
||||
cycles = 11 - posAnd7;
|
||||
|
||||
if (spx > 167)
|
||||
break;
|
||||
|
||||
unsigned cycles = 6;
|
||||
const unsigned posAnd7 = scxReader.scxAnd7() + spx & 7;
|
||||
|
||||
if (posAnd7 < 5) {
|
||||
cycles = 11 - posAnd7;
|
||||
for (unsigned j = i; j--;) {
|
||||
const unsigned tmpSpx = tmp[j] >> 8;
|
||||
|
||||
for (unsigned j = i; j--;) {
|
||||
const unsigned tmpSpx = tmp[j] >> 8;
|
||||
|
||||
if (spx - tmpSpx > 4U)
|
||||
break;
|
||||
|
||||
if ((scxReader.scxAnd7() + tmpSpx & 7) < 4 || spx == tmpSpx) {
|
||||
cycles = 6;
|
||||
break;
|
||||
}
|
||||
if (spx - tmpSpx > 4U)
|
||||
break;
|
||||
|
||||
if ((scxReader.scxAnd7() + tmpSpx & 7) < 4 || spx == tmpSpx) {
|
||||
cycles = 6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sum += cycles;
|
||||
}
|
||||
|
||||
mapPos[11] = sum;
|
||||
sum += cycles;
|
||||
}
|
||||
|
||||
cycles[ly] = sum;
|
||||
}
|
||||
|
||||
void SpriteMapper::doEvent() {
|
||||
|
@ -29,7 +29,11 @@ class SpriteSizeReader;
|
||||
class ScxReader;
|
||||
|
||||
class SpriteMapper : public VideoEvent {
|
||||
uint16_t spritemap[144*12];
|
||||
enum { CYCLES_INVALID = 0xFF };
|
||||
|
||||
mutable unsigned short spritemap[144*10];
|
||||
mutable unsigned char cycles[144];
|
||||
unsigned char num[144];
|
||||
|
||||
const SpriteSizeReader &spriteSizeReader;
|
||||
const ScxReader &scxReader;
|
||||
@ -38,11 +42,12 @@ public:
|
||||
const uint8_t *const oamram;
|
||||
|
||||
private:
|
||||
uint8_t timeDiff;
|
||||
unsigned char timeDiff;
|
||||
bool cgb;
|
||||
|
||||
void clearMap();
|
||||
void mapSprites();
|
||||
void updateLine(unsigned ly) const;
|
||||
|
||||
public:
|
||||
SpriteMapper(const SpriteSizeReader &spriteSizeReader_in,
|
||||
@ -66,8 +71,22 @@ public:
|
||||
timeDiff = dS ? 85 * 2 - 40 : (82 - 16);
|
||||
}
|
||||
|
||||
const uint16_t * spriteMap() const {
|
||||
return spritemap;
|
||||
unsigned numSprites(const unsigned ly) const {
|
||||
return num[ly];
|
||||
}
|
||||
|
||||
unsigned spriteCycles(const unsigned ly) const {
|
||||
if (cycles[ly] == CYCLES_INVALID)
|
||||
updateLine(ly);
|
||||
|
||||
return cycles[ly];
|
||||
}
|
||||
|
||||
const unsigned short* sprites(const unsigned ly) const {
|
||||
if (cycles[ly] == CYCLES_INVALID)
|
||||
updateLine(ly);
|
||||
|
||||
return spritemap + ly * 10;
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user