22 : vdp(vdp_), vram(vdp.getVRAM())
23 , limitSpritesSetting(renderSettings.getLimitSprites())
24 , frameStartTime(time)
38 updateSpritesMethod = &SpriteChecker::updateSprites1;
47 a = (a | (a >> 8)) & 0xFF00FF00;
48 a = (a | (a >> 4)) & 0xF0F0F0F0;
49 a = (a | (a >> 2)) & 0xCCCCCCCC;
50 a = (a | (a >> 1)) & 0xAAAAAAAA;
55 unsigned patternNr,
unsigned y)
58 unsigned index = patternNr * 8 + y;
61 pattern |= patternPtr[index + 16] << 16;
63 return !vdp.
isSpriteMag() ? pattern : doublePattern(pattern);
66 unsigned patternNr,
unsigned y)
71 unsigned index = patternNr * 8 + y;
72 const byte* patternPtr = (index & 1) ? ptr1 : ptr0;
76 pattern |= patternPtr[index + (16 / 2)] << 16;
78 return !vdp.
isSpriteMag() ? pattern : doublePattern(pattern);
81 void SpriteChecker::updateSprites1(
int limit)
86 checkSprites1(currentLine, limit);
90 if ((currentLine <= l0) && (l0 < limit)) {
91 checkSprites1(l0, l0 + 1);
98 inline void SpriteChecker::checkSprites1(
int minLine,
int maxLine)
106 bool limitSprites = limitSpritesSetting.
getValue();
109 int magSize = (mag + 1) * size;
111 byte patternIndexMask = size == 16 ? 0xFC : 0xFF;
113 for (; sprite < 32; sprite++, attributePtr += 4) {
114 int y = attributePtr[0];
116 for (
int line = minLine; line < maxLine; ++line) {
118 int displayLine = line + displayDelta;
119 int spriteLine = (displayLine - y) & 0xFF;
120 if (spriteLine >= magSize) {
122 line += 256 - spriteLine - 1;
125 int visibleIndex = spriteCount[line];
126 if (visibleIndex == 4) {
131 if ((status & 0xC0) == 0) {
133 0x40 | (status & 0x20) | sprite);
135 if (limitSprites)
continue;
138 SpriteInfo& sip = spriteBuffer[line][visibleIndex];
139 int patternIndex = attributePtr[2] & patternIndexMask;
140 if (mag) spriteLine /= 2;
141 sip.
pattern = calculatePatternNP(patternIndex, spriteLine);
142 sip.x = attributePtr[1];
143 if (attributePtr[3] & 0x80) sip.x -= 32;
144 sip.colorAttrib = attributePtr[3];
148 if (~status & 0x40) {
176 for (
int line = minLine; line < maxLine; ++line) {
177 int minXCollision = 999;
178 for (
int i = std::min(4, spriteCount[line]); --i >= 1; ) {
179 int x_i = spriteBuffer[line][i].
x;
181 for (
int j = i; --j >= 0; ) {
183 int x_j = spriteBuffer[line][j].
x;
184 int dist = x_j - x_i;
185 if ((-magSize < dist) && (dist < magSize)) {
195 colPat &= (1 << (32 + x_i)) - 1;
199 assert(xCollision >= 0);
200 minXCollision = std::min(minXCollision, xCollision);
205 if (minXCollision < 256) {
211 collisionX = minXCollision + 12;
218 void SpriteChecker::updateSprites2(
int limit)
224 checkSprites2(currentLine, limit);
228 if ((currentLine <= l0) && (l0 < limit)) {
229 checkSprites2(l0, l0 + 1);
236 inline void SpriteChecker::checkSprites2(
int minLine,
int maxLine)
244 bool limitSprites = limitSpritesSetting.
getValue();
247 int magSize = (mag + 1) * size;
248 int patternIndexMask = (size == 16) ? 0xFC : 0xFF;
254 const byte* attributePtr0;
255 const byte* attributePtr1;
257 512, 32 * 4, attributePtr0, attributePtr1);
259 for (; sprite < 32; ++sprite) {
260 int y = attributePtr0[2 * sprite + 0];
262 for (
int line = minLine; line < maxLine; ++line) {
264 int displayLine = line + displayDelta;
265 int spriteLine = (displayLine - y) & 0xFF;
266 if (spriteLine >= magSize) {
268 line += 256 - spriteLine - 1;
271 int visibleIndex = spriteCount[line];
272 if (visibleIndex == 8) {
278 if ((status & 0xC0) == 0) {
280 0x40 | (status & 0x20) | sprite);
282 if (limitSprites)
continue;
284 if (mag) spriteLine /= 2;
285 int colorIndex = (-1 << 10) | (sprite * 16 + spriteLine);
290 if ((colorAttrib & 0x40) && visibleIndex == 0)
continue;
291 spriteCount[line] = visibleIndex + 1;
292 SpriteInfo& sip = spriteBuffer[line][visibleIndex];
293 int patternIndex = attributePtr0[2 * sprite + 1] & patternIndexMask;
294 sip.
pattern = calculatePatternPlanar(patternIndex, spriteLine);
295 sip.x = attributePtr1[2 * sprite + 0];
296 if (colorAttrib & 0x80) sip.x -= 32;
297 sip.colorAttrib = colorAttrib;
299 spriteBuffer[line][visibleIndex + 1].
colorAttrib = 0;
303 const byte* attributePtr0 =
306 for (; sprite < 32; ++sprite) {
307 int y = attributePtr0[4 * sprite + 0];
309 for (
int line = minLine; line < maxLine; ++line) {
311 int displayLine = line + displayDelta;
312 int spriteLine = (displayLine - y) & 0xFF;
313 if (spriteLine >= magSize) {
315 line += 256 - spriteLine - 1;
318 int visibleIndex = spriteCount[line];
319 if (visibleIndex == 8) {
325 if ((status & 0xC0) == 0) {
327 0x40 | (status & 0x20) | sprite);
329 if (limitSprites)
continue;
331 if (mag) spriteLine /= 2;
332 int colorIndex = (-1 << 10) | (sprite * 16 + spriteLine);
337 if ((colorAttrib & 0x40) && visibleIndex == 0)
continue;
338 spriteCount[line] = visibleIndex + 1;
339 SpriteInfo& sip = spriteBuffer[line][visibleIndex];
340 int patternIndex = attributePtr0[4 * sprite + 2] & patternIndexMask;
341 sip.
pattern = calculatePatternNP(patternIndex, spriteLine);
342 sip.x = attributePtr0[4 * sprite + 1];
343 if (colorAttrib & 0x80) sip.x -= 32;
344 sip.colorAttrib = colorAttrib;
353 spriteBuffer[line][visibleIndex + 1].
colorAttrib = 0;
359 if (~status & 0x40) {
389 for (
int line = minLine; line < maxLine; ++line) {
390 int minXCollision = 999;
391 SpriteInfo* visibleSprites = spriteBuffer[line];
392 for (
int i = std::min(8, spriteCount[line]); --i >= 1; ) {
394 if (visibleSprites[i].colorAttrib & 0x60)
continue;
396 int x_i = visibleSprites[i].
x;
398 for (
int j = i; --j >= 0; ) {
400 if (visibleSprites[j].colorAttrib & 0x60)
continue;
403 int x_j = visibleSprites[j].x;
404 int dist = x_j - x_i;
405 if ((-magSize < dist) && (dist < magSize)) {
415 colPat &= (1 << (32 + x_i)) - 1;
419 assert(xCollision >= 0);
420 minXCollision = std::min(minXCollision, xCollision);
425 if (minXCollision < 256) {
429 collisionX = minXCollision + 12;
438 template<
typename Archive>
453 for (
int i = 0; i < 313; i++) spriteCount[i] = 0;
456 ar.serialize(
"collisionX", collisionX);
457 ar.serialize(
"collisionY", collisionY);
458 if (ar.versionAtLeast(version, 2)) {
459 ar.serialize(
"currentLine", currentLine);