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:
sinamas 2007-11-17 23:31:39 +00:00
parent e899db1bf5
commit a2c291b48f
6 changed files with 121 additions and 115 deletions

View File

@ -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) {

View File

@ -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];

View File

@ -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;

View File

@ -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;
};

View File

@ -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() {

View File

@ -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;
}
};