wx affects sprite m3 cycles. cache m3 cycles, related refactoring. readjust cgb dma cycles to previously changed m3 timing. clean up goofy lyc calculation.

git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@113 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
sinamas 2008-01-08 05:02:29 +00:00
parent 630e0e6c3a
commit 6eb9761b10
80 changed files with 501 additions and 468 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -33,7 +33,6 @@ sourceFiles = Split('''
src/video/sc_reader.cpp
src/video/scx_reader.cpp
src/video/sprite_mapper.cpp
src/video/sprite_size_reader.cpp
src/video/we_master_checker.cpp
src/video/we.cpp
src/video/wx_reader.cpp

View File

@ -1,41 +1,51 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* 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 "sprite_size_reader.h"
#include "sprite_mapper.h"
#include "basic_add_event.h"
SpriteSizeReader::SpriteSizeReader(event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue_in,
SpriteMapper &spriteMapper_in, const LyCounter &lyCounter_in) :
VideoEvent(0),
m3EventQueue(m3EventQueue_in),
spriteMapper(spriteMapper_in),
lyCounter(lyCounter_in)
{
setSource(false);
reset();
}
void SpriteSizeReader::doEvent() {
largeSprites_ = src_;
addEvent(spriteMapper, lyCounter, time(), m3EventQueue);
setTime(DISABLED_TIME);
}
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* 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 INSERTION_SORT_H
#define INSERTION_SORT_H
#include <functional>
template<typename T, class Less>
void insertionSort(T *const start, T *const end, Less less) {
if (start >= end)
return;
T *a = start;
while (++a < end) {
const T e = *a;
T *b = a;
while (b != start && less(e, *(b - 1))) {
*b = *(b - 1);
b = b - 1;
}
*b = e;
}
}
template<typename T>
inline void insertionSort(T *const start, T *const end) {
insertionSort(start, end, std::less<T>());
}
#endif /*INSERTION_SORT_H*/

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -339,8 +339,6 @@ unsigned long Memory::event(unsigned long cycleCounter) {
unsigned dmaDest = dmaDestination;
unsigned dmaLength = ((memory[0xFF55] & 0x7F) + 0x1) * 0x10;
cycleCounter += (6 >> doubleSpeed) + doubleSpeed;
unsigned length = hdma_transfer ? 0x10 : dmaLength;
if (static_cast<unsigned long>(dmaDest) + length & 0x10000) {
@ -353,6 +351,8 @@ unsigned long Memory::event(unsigned long cycleCounter) {
if (!(memory[0xFF40] & 0x80))
dmaLength = 0;
cycleCounter += 4;
while (length--) {
write(0x8000 | dmaDest++ & 0x1FFF, read(dmaSrc++ & 0xFFFF, cycleCounter), cycleCounter);
cycleCounter += 2 << doubleSpeed;

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -94,13 +94,10 @@ LCD::LCD(const unsigned char *const oamram, const unsigned char *const vram_in)
m3EventQueue(11, VideoEventComparer()),
irqEventQueue(4, VideoEventComparer()),
vEventQueue(5, VideoEventComparer()),
m3ExtraCycles(*this),
weMasterChecker(m3EventQueue, wyReg, lyCounter),
wyReg(lyCounter, weMasterChecker),
wxReader(m3EventQueue, we.enableChecker(), we.disableChecker()),
spriteSizeReader(m3EventQueue, spriteMapper, lyCounter),
scxReader(m3EventQueue, /*wyReg.reader3(),*/ wxReader, we.enableChecker(), we.disableChecker()),
spriteMapper(spriteSizeReader, scxReader, oamram),
win(m3EventQueue, lyCounter, m3ExtraCycles),
scxReader(m3EventQueue, /*wyReg.reader3(),*/ win.wxReader, win.we.enableChecker(), win.we.disableChecker(), m3ExtraCycles),
spriteMapper(m3ExtraCycles, oamram),
m3ExtraCycles(spriteMapper, scxReader, win),
breakEvent(drawStartCycle, scReadOffset),
mode3Event(m3EventQueue, vEventQueue, mode0Irq, irqEvent),
lycIrq(ifReg),
@ -158,10 +155,10 @@ void LCD::reset(const bool cgb_in) {
we = false;*/
scxReader.setSource(0);
wxReader.setSource(0);
wyReg.setSource(0);
spriteSizeReader.setSource(false);
we.setSource(false);
win.wxReader.setSource(0);
win.wyReg.setSource(0);
spriteMapper.setLargeSpritesSource(false);
win.we.setSource(false);
// weMasterChecker.setSource(false);
scReader.setScxSource(0);
scReader.setScySource(0);
@ -178,8 +175,7 @@ void LCD::setDoubleSpeed(const bool ds) {
doubleSpeed = ds;
lyCounter.setDoubleSpeed(doubleSpeed);
scxReader.setDoubleSpeed(doubleSpeed);
wxReader.setDoubleSpeed(doubleSpeed);
spriteMapper.setDoubleSpeed(doubleSpeed);
win.wxReader.setDoubleSpeed(doubleSpeed);
scReader.setDoubleSpeed(doubleSpeed);
breakEvent.setDoubleSpeed(doubleSpeed);
lycIrq.setDoubleSpeed(doubleSpeed);
@ -225,21 +221,20 @@ void LCD::resetVideoState(const unsigned statReg, const unsigned long cycleCount
vEventQueue.push(&lyCounter);
scxReader.reset();
wxReader.reset();
wyReg.reset();
spriteSizeReader.reset();
win.wxReader.reset();
win.wyReg.reset();
spriteMapper.reset();
we.reset();
win.we.reset();
scReader.reset();
breakEvent.reset();
mode3Event.reset();
weMasterChecker.reset();
weMasterChecker.schedule(wyReg.getSource(), we.getSource(), cycleCounter);
win.weMasterChecker.reset();
win.weMasterChecker.schedule(win.wyReg.getSource(), win.we.getSource(), cycleCounter);
if (weMasterChecker.time() != VideoEvent::DISABLED_TIME) {
m3EventQueue.push(&weMasterChecker);
if (win.weMasterChecker.time() != VideoEvent::DISABLED_TIME) {
m3EventQueue.push(&win.weMasterChecker);
mode3Event.schedule();
vEventQueue.push(&mode3Event);
}
@ -266,6 +261,8 @@ void LCD::resetVideoState(const unsigned statReg, const unsigned long cycleCount
irqEvent.schedule();
vEventQueue.push(&irqEvent);
m3ExtraCycles.invalidateCache();
}
// static VideoBlitter *vBlitter = NULL;
@ -402,24 +399,23 @@ void LCD::rescheduleEvents(const unsigned long cycleCounter) {
vEventQueue.push(&lyCounter);
rescheduleIfActive(scxReader, lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(spriteSizeReader, lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(spriteMapper, lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(wxReader, scxReader, lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(wyReg.reader1(), lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(wyReg.reader2(), lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(win.wxReader, scxReader, lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(win.wyReg.reader1(), lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(win.wyReg.reader2(), lyCounter, cycleCounter, m3EventQueue);
// rescheduleIfActive(wyReg.reader3(), scxReader, lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(wyReg.reader4(), lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(we.disableChecker(), scxReader, wxReader, lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(we.enableChecker(), scxReader, wxReader, lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(win.wyReg.reader4(), lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(win.we.disableChecker(), scxReader, win.wxReader, lyCounter, cycleCounter, m3EventQueue);
rescheduleIfActive(win.we.enableChecker(), scxReader, win.wxReader, lyCounter, cycleCounter, m3EventQueue);
if (wyReg.reader3().time() != VideoEvent::DISABLED_TIME) {
wyReg.reader3().schedule(wxReader.getSource(), scxReader, cycleCounter);
m3EventQueue.push(&wyReg.reader3());
if (win.wyReg.reader3().time() != VideoEvent::DISABLED_TIME) {
win.wyReg.reader3().schedule(win.wxReader.getSource(), scxReader, cycleCounter);
m3EventQueue.push(&win.wyReg.reader3());
}
if (weMasterChecker.time() != VideoEvent::DISABLED_TIME) {
weMasterChecker.schedule(wyReg.getSource(), we.getSource(), cycleCounter);
m3EventQueue.push(&weMasterChecker);
if (win.weMasterChecker.time() != VideoEvent::DISABLED_TIME) {
win.weMasterChecker.schedule(win.wyReg.getSource(), win.we.getSource(), cycleCounter);
m3EventQueue.push(&win.weMasterChecker);
}
if (scReader.time() != VideoEvent::DISABLED_TIME) {
@ -588,12 +584,12 @@ void LCD::weChange(const bool newValue, const unsigned long cycleCounter) {
update(cycleCounter);
// printf("%u: weChange: %u\n", videoCycles, newValue);
addEvent(weMasterChecker, wyReg.getSource(), newValue, cycleCounter, m3EventQueue);
addEvent(win.weMasterChecker, win.wyReg.getSource(), newValue, cycleCounter, m3EventQueue);
// addEvent(weMasterChecker, lyCounter, cycleCounter, m3EventQueue);
we.setSource(newValue);
addEvent(we.disableChecker(), scxReader.scxAnd7(), wxReader.wx(), lyCounter, cycleCounter, m3EventQueue);
addEvent(we.enableChecker(), scxReader.scxAnd7(), wxReader.wx(), lyCounter, cycleCounter, m3EventQueue);
win.we.setSource(newValue);
addEvent(win.we.disableChecker(), scxReader.scxAnd7(), win.wxReader.wx(), lyCounter, cycleCounter, m3EventQueue);
addEvent(win.we.enableChecker(), scxReader.scxAnd7(), win.wxReader.wx(), lyCounter, cycleCounter, m3EventQueue);
addEvent(mode3Event, vEventQueue);
}
@ -602,11 +598,11 @@ void LCD::wxChange(const unsigned newValue, const unsigned long cycleCounter) {
update(cycleCounter);
// printf("%u: wxChange: 0x%X\n", videoCycles, newValue);
wxReader.setSource(newValue);
addEvent(wxReader, scxReader.scxAnd7(), lyCounter, cycleCounter, m3EventQueue);
win.wxReader.setSource(newValue);
addEvent(win.wxReader, scxReader.scxAnd7(), lyCounter, cycleCounter, m3EventQueue);
if (wyReg.reader3().time() != VideoEvent::DISABLED_TIME)
addEvent(wyReg.reader3(), wxReader.getSource(), scxReader, cycleCounter, m3EventQueue);
if (win.wyReg.reader3().time() != VideoEvent::DISABLED_TIME)
addEvent(win.wyReg.reader3(), win.wxReader.getSource(), scxReader, cycleCounter, m3EventQueue);
addEvent(mode3Event, vEventQueue);
}
@ -615,13 +611,13 @@ void LCD::wyChange(const unsigned newValue, const unsigned long cycleCounter) {
update(cycleCounter);
// printf("%u: wyChange: 0x%X\n", videoCycles, newValue);
wyReg.setSource(newValue);
addEvent(wyReg.reader1(), lyCounter, cycleCounter, m3EventQueue);
addEvent(wyReg.reader2(), lyCounter, cycleCounter, m3EventQueue);
addEvent(wyReg.reader3(), wxReader.getSource(), scxReader, cycleCounter, m3EventQueue);
addEvent(wyReg.reader4(), lyCounter, cycleCounter, m3EventQueue);
win.wyReg.setSource(newValue);
addEvent(win.wyReg.reader1(), lyCounter, cycleCounter, m3EventQueue);
addEvent(win.wyReg.reader2(), lyCounter, cycleCounter, m3EventQueue);
addEvent(win.wyReg.reader3(), win.wxReader.getSource(), scxReader, cycleCounter, m3EventQueue);
addEvent(win.wyReg.reader4(), lyCounter, cycleCounter, m3EventQueue);
addEvent(weMasterChecker, newValue, we.getSource(), cycleCounter, m3EventQueue);
addEvent(win.weMasterChecker, newValue, win.we.getSource(), cycleCounter, m3EventQueue);
addEvent(mode3Event, vEventQueue);
}
@ -633,10 +629,8 @@ void LCD::scxChange(const unsigned newScx, const unsigned long cycleCounter) {
scxReader.setSource(newScx);
addEvent(scxReader, lyCounter, cycleCounter, m3EventQueue);
addEvent(spriteMapper, lyCounter, cycleCounter, m3EventQueue);
if (wyReg.reader3().time() != VideoEvent::DISABLED_TIME)
addEvent(wyReg.reader3(), wxReader.getSource(), scxReader, cycleCounter, m3EventQueue);
if (win.wyReg.reader3().time() != VideoEvent::DISABLED_TIME)
addEvent(win.wyReg.reader3(), win.wxReader.getSource(), scxReader, cycleCounter, m3EventQueue);
addEvent(mode3Event, vEventQueue);
@ -669,12 +663,8 @@ void LCD::spriteSizeChange(const bool newLarge, const unsigned long cycleCounter
update(cycleCounter);
//printf("spriteSizeChange\n");
spriteSizeReader.setSource(newLarge);
addEvent(spriteSizeReader, lyCounter, cycleCounter, m3EventQueue);
//if (spriteSizeReader.time() < spriteMapper.time()) {
// addEvent(spriteMapper, m3EventQueue);
//}
spriteMapper.setLargeSpritesSource(newLarge);
addEvent(spriteMapper, lyCounter, cycleCounter, m3EventQueue);
addEvent(mode3Event, vEventQueue);
}
@ -885,15 +875,11 @@ unsigned LCD::get_stat(const unsigned lycReg, const unsigned long cycleCounter)
stat = 3;
}
}
unsigned lyc;
if (lycReg)
lyc = lyCounter.ly() == lycReg && timeToNextLy > 4U - (doubleSpeed << 2);
else
lyc = (lyCounter.ly() == 153 && (timeToNextLy >> doubleSpeed) <= 456 - 8) || (lyCounter.ly() == 0 && timeToNextLy > 4U - (doubleSpeed << 2));
stat |= lyc << 2;
if (lyCounter.ly() == lycReg && timeToNextLy > 4U - doubleSpeed * 4U ||
lycReg == 0 && lyCounter.ly() == 153 && timeToNextLy >> doubleSpeed <= 456 - 8) {
stat |= 4;
}
}
return stat;
@ -915,7 +901,7 @@ void LCD::do_update(unsigned cycles) {
winYPos = 0xFF;
//scy[0] = scy[1] = memory.fastread(0xFF42);
//scx[0] = scx[1] = memory.fastread(0xFF43);
weMasterChecker.unset();
win.weMasterChecker.unset();
}
videoCycles += cycles;
@ -1003,7 +989,7 @@ void LCD::setDmgPaletteColor(const unsigned palNum, const unsigned colorNum, con
}
void LCD::null_draw(unsigned /*xpos*/, const unsigned ypos, const unsigned endX) {
const bool enableWindow = we.value() && wxReader.wx() < 0xA7 && ypos >= wyReg.value() && (weMasterChecker.weMaster() || ypos == wyReg.value());
const bool enableWindow = win.enabled(ypos);
if (enableWindow && winYPos == 0xFF)
winYPos = /*ypos - wyReg.value()*/ 0;
@ -1018,24 +1004,24 @@ template<typename T>
void LCD::cgb_draw(unsigned xpos, const unsigned ypos, const unsigned endX) {
const unsigned effectiveScx = scReader.scx();
const bool enableWindow = we.value() && wxReader.wx() < 0xA7 && ypos >= wyReg.value() && (weMasterChecker.weMaster() || ypos == wyReg.value());
const bool enableWindow = win.enabled(ypos);
if (enableWindow && winYPos == 0xFF)
winYPos = /*ypos - wyReg.value()*/ 0;
T *const bufLine = static_cast<T*>(dbuffer) + ypos * static_cast<unsigned long>(dpitch);
if (!(enableWindow && wxReader.wx() <= xpos + 7)) {
if (!(enableWindow && win.wxReader.wx() <= xpos + 7)) {
const unsigned fby = scReader.scy() + ypos /*& 0xFF*/;
const unsigned end = std::min(enableWindow ? wxReader.wx() - 7 : 160U, endX);
const unsigned end = std::min(enableWindow ? win.wxReader.wx() - 7 : 160U, endX);
cgb_bg_drawPixels(bufLine, xpos, end, effectiveScx, bgTileMap + (fby & 0xF8) * 4, bgTileData, fby & 7);
}
if (enableWindow && endX + 7 > wxReader.wx()) {
const unsigned start = std::max(wxReader.wx() < 7 ? 0U : (wxReader.wx() - 7), xpos);
if (enableWindow && endX + 7 > win.wxReader.wx()) {
const unsigned start = std::max(win.wxReader.wx() < 7 ? 0U : (win.wxReader.wx() - 7), xpos);
cgb_bg_drawPixels(bufLine, start, endX, 7u - wxReader.wx(), wdTileMap + (winYPos & 0xF8) * 4, bgTileData, winYPos & 7);
cgb_bg_drawPixels(bufLine, start, endX, 7u - win.wxReader.wx(), wdTileMap + (winYPos & 0xF8) * 4, bgTileData, winYPos & 7);
}
if (endX == 160) {
@ -1051,7 +1037,7 @@ template<typename T>
void LCD::dmg_draw(unsigned xpos, const unsigned ypos, const unsigned endX) {
const unsigned effectiveScx = scReader.scx();
const bool enableWindow = we.value() && wxReader.wx() < 0xA7 && ypos >= wyReg.value() && (weMasterChecker.weMaster() || ypos == wyReg.value());
const bool enableWindow = win.enabled(ypos);
if (enableWindow && winYPos == 0xFF)
winYPos = /*ypos - wyReg.value()*/ 0;
@ -1059,17 +1045,17 @@ void LCD::dmg_draw(unsigned xpos, const unsigned ypos, const unsigned endX) {
T *const bufLine = static_cast<T*>(dbuffer) + ypos * static_cast<unsigned long>(dpitch);
if (bgEnable) {
if (!(enableWindow && wxReader.wx() <= xpos + 7)) {
if (!(enableWindow && win.wxReader.wx() <= xpos + 7)) {
const unsigned fby = scReader.scy() + ypos /*& 0xFF*/;
const unsigned end = std::min(enableWindow ? wxReader.wx() - 7 : 160U, endX);
const unsigned end = std::min(enableWindow ? win.wxReader.wx() - 7 : 160U, endX);
bg_drawPixels(bufLine, xpos, end, effectiveScx, bgTileMap + (fby & 0xF8) * 4, bgTileData + (fby & 7) * 2);
}
if (enableWindow && endX + 7 > wxReader.wx()) {
const unsigned start = std::max(wxReader.wx() < 7 ? 0U : (wxReader.wx() - 7), xpos);
if (enableWindow && endX + 7 > win.wxReader.wx()) {
const unsigned start = std::max(win.wxReader.wx() < 7 ? 0U : (win.wxReader.wx() - 7), xpos);
bg_drawPixels(bufLine, start, endX, 7u - wxReader.wx(), wdTileMap + (winYPos & 0xF8) * 4, bgTileData + (winYPos & 7) * 2);
bg_drawPixels(bufLine, start, endX, 7u - win.wxReader.wx(), wdTileMap + (winYPos & 0xF8) * 4, bgTileData + (winYPos & 7) * 2);
}
} else
std::fill_n(bufLine + xpos, endX - xpos, bgPalette[0]);
@ -1256,13 +1242,12 @@ static unsigned cgb_toplayerBG_mask(const unsigned spx, const unsigned bgStart,
template<typename T>
void LCD::cgb_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 = (memory.fastread(0xFF40) & 0x20) && (ypos >= memory.fastread(0xFF4A)) && (wx < 160);
const bool enableWindow = we.value() && wxReader.wx() < 0xA7 && ypos >= wyReg.value() && (weMasterChecker.weMaster() || ypos == wyReg.value());
const unsigned short *const spriteMapLine = spriteMapper.sprites(ypos);
const unsigned wx = win.wxReader.wx() < 7 ? 0 : win.wxReader.wx() - 7;
const bool enableWindow = win.enabled(ypos);
const unsigned char *const spriteMapLine = spriteMapper.sprites(ypos);
for (int i = spriteMapper.numSprites(ypos) - 1; i >= 0; --i) {
const unsigned char *const spriteInfo = spriteMapper.oamram + (spriteMapLine[i] & 0xFF);
const unsigned char *const spriteInfo = spriteMapper.oamram + spriteMapLine[i];
const unsigned spx = spriteInfo[1];
if (spx < 168 && spx) {
@ -1270,7 +1255,7 @@ void LCD::cgb_drawSprites(T * const buffer_line, const unsigned ypos) {
unsigned spTile = spriteInfo[2];
const unsigned attributes = spriteInfo[3];
if (spriteSizeReader.largeSprites()) {
if (spriteMapper.largeSprites()) {
if (attributes & 0x40) //yflip
spLine = 15 - spLine;
@ -1430,12 +1415,12 @@ static unsigned prioritizedBG_mask(const unsigned spx, const unsigned bgStart, c
template<typename T>
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 = we.value() && wxReader.wx() < 0xA7 && ypos >= wyReg.value() && (weMasterChecker.weMaster() || ypos == wyReg.value());
const unsigned short *const spriteMapLine = spriteMapper.sprites(ypos);
const unsigned wx = win.wxReader.wx() < 7 ? 0 : win.wxReader.wx() - 7;
const bool enableWindow = win.enabled(ypos);
const unsigned char *const spriteMapLine = spriteMapper.sprites(ypos);
for (int i = spriteMapper.numSprites(ypos) - 1; i >= 0; --i) {
const unsigned char *const spriteInfo = spriteMapper.oamram + (spriteMapLine[i] & 0xFF);
const unsigned char *const spriteInfo = spriteMapper.oamram + spriteMapLine[i];
const unsigned spx = spriteInfo[1];
if (spx < 168 && spx) {
@ -1443,7 +1428,7 @@ void LCD::drawSprites(T * const buffer_line, const unsigned ypos) {
unsigned spTile = spriteInfo[2];
const unsigned attributes = spriteInfo[3];
if (spriteSizeReader.largeSprites()) {
if (spriteMapper.largeSprites()) {
if (attributes & 0x40) //yflip
spLine = 15 - spLine;

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -32,11 +32,7 @@ class Filter;
#include "video/video_event_comparer.h"
#include "video/ly_counter.h"
#include "video/sprite_size_reader.h"
#include "video/wx_reader.h"
#include "video/wy.h"
#include "video/we.h"
#include "video/we_master_checker.h"
#include "video/window.h"
#include "video/scx_reader.h"
#include "video/sprite_mapper.h"
#include "video/sc_reader.h"
@ -51,8 +47,6 @@ class Filter;
#include "video/m3_extra_cycles.h"
class LCD {
friend class M3ExtraCycles;
//static const uint8_t xflipt[0x100];
unsigned long dmgColorsRgb32[3 * 4];
unsigned long dmgColorsRgb16[3 * 4];
@ -85,16 +79,11 @@ class LCD {
event_queue<VideoEvent*,VideoEventComparer> irqEventQueue;
event_queue<VideoEvent*,VideoEventComparer> vEventQueue;
const M3ExtraCycles m3ExtraCycles;
LyCounter lyCounter;
We we;
WeMasterChecker weMasterChecker;
Wy wyReg;
WxReader wxReader;
SpriteSizeReader spriteSizeReader;
Window win;
ScxReader scxReader;
SpriteMapper spriteMapper;
M3ExtraCycles m3ExtraCycles;
ScReader scReader;
BreakEvent breakEvent;
Mode3Event mode3Event;

View File

@ -17,20 +17,85 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "m3_extra_cycles.h"
#include "scx_reader.h"
#include "window.h"
#include "sprite_mapper.h"
#include "../insertion_sort.h"
#include "../video.h"
M3ExtraCycles::M3ExtraCycles(const LCD &video) :
video(video)
{}
unsigned M3ExtraCycles::operator()(const unsigned ly) const {
unsigned cycles = video.spriteMapper.spriteCycles(ly);
cycles += video.scxReader.scxAnd7();
if (video.we.value() && video.wxReader.wx() < 0xA7 && ly >= video.wyReg.value() && (video.weMasterChecker.weMaster() || ly == video.wyReg.value()))
cycles += 6;
return cycles;
M3ExtraCycles::M3ExtraCycles(const SpriteMapper &spriteMapper,
const ScxReader &scxReader,
const Window &win) :
spriteMapper(spriteMapper),
scxReader(scxReader),
win(win)
{
invalidateCache();
}
static const unsigned char* addLineCycles(const unsigned char *const start, const unsigned char *const end,
const unsigned maxSpx, const unsigned scwxAnd7, const unsigned char *const oamram_plus1, unsigned char *cycles_out) {
unsigned sum = 0;
const unsigned char *a = start;
for (; a < end; ++a) {
const unsigned spx = oamram_plus1[*a];
if (spx > maxSpx)
break;
unsigned cycles = 6;
const unsigned posAnd7 = scwxAnd7 + spx & 7;
if (posAnd7 < 5) {
cycles = 11 - posAnd7;
for (const unsigned char *b = a; b > start;) {
const unsigned bSpx = oamram_plus1[*--b];
if (spx - bSpx > 4U)
break;
if ((scwxAnd7 + bSpx & 7) < 4 || spx == bSpx) {
cycles = 6;
break;
}
}
}
sum += cycles;
}
*cycles_out += sum;
return a;
}
void M3ExtraCycles::updateLine(const unsigned ly) const {
const bool windowEnabled = win.enabled(ly);
cycles[ly] = windowEnabled ? scxReader.scxAnd7() + 6 : scxReader.scxAnd7();
const unsigned numSprites = spriteMapper.numSprites(ly);
if (numSprites == 0)
return;
unsigned char sortBuf[10];
const unsigned char *tmp = spriteMapper.sprites(ly);
if (spriteMapper.isCgb()) {
std::memcpy(sortBuf, tmp, sizeof(sortBuf));
insertionSort(sortBuf, sortBuf + numSprites);
tmp = sortBuf;
}
const unsigned char *const tmpend = tmp + numSprites;
const unsigned char *const oamram_plus1 = spriteMapper.oamram + 1;
if (windowEnabled) {
addLineCycles(addLineCycles(tmp, tmpend, win.wxReader.wx(), scxReader.scxAnd7(), oamram_plus1, cycles + ly),
tmpend, 167, 7 - win.wxReader.wx(), oamram_plus1, cycles + ly);
} else
addLineCycles(tmp, tmpend, 167, scxReader.scxAnd7(), oamram_plus1, cycles + ly);
}

View File

@ -19,14 +19,38 @@
#ifndef VIDEO_M3_EXTRA_CYCLES_H
#define VIDEO_M3_EXTRA_CYCLES_H
class LCD;
class ScxReader;
class Window;
class SpriteMapper;
#include <cstring>
class M3ExtraCycles {
const LCD &video;
enum { CYCLES_INVALID = 0xFF };
mutable unsigned char cycles[144];
const SpriteMapper &spriteMapper;
const ScxReader &scxReader;
const Window &win;
void updateLine(unsigned ly) const;
public:
M3ExtraCycles(const LCD &video);
unsigned operator()(unsigned ly) const;
M3ExtraCycles(const SpriteMapper &spriteMapper,
const ScxReader &scxReader_in,
const Window &win);
void invalidateCache() {
std::memset(cycles, CYCLES_INVALID, sizeof(cycles));
}
unsigned operator()(const unsigned ly) const {
if (cycles[ly] == CYCLES_INVALID)
updateLine(ly);
return cycles[ly];
}
};
#endif

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -19,18 +19,21 @@
#include "scx_reader.h"
#include "../event_queue.h"
#include "m3_extra_cycles.h"
ScxReader::ScxReader(event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue_in,
// VideoEvent &wyReader3_in,
VideoEvent &wxReader_in,
VideoEvent &weEnableChecker_in,
VideoEvent &weDisableChecker_in) :
VideoEvent &weDisableChecker_in,
M3ExtraCycles &m3ExtraCycles) :
VideoEvent(1),
m3EventQueue(m3EventQueue_in),
// wyReader3(wyReader3_in),
wxReader(wxReader_in),
weEnableChecker(weEnableChecker_in),
weDisableChecker(weDisableChecker_in)
weDisableChecker(weDisableChecker_in),
m3ExtraCycles(m3ExtraCycles)
{
setDoubleSpeed(false);
setSource(0);
@ -53,5 +56,7 @@ void ScxReader::doEvent() {
rescheduleEvent(weEnableChecker, diff);
rescheduleEvent(weDisableChecker, diff);
m3ExtraCycles.invalidateCache();
setTime(DISABLED_TIME);
}

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -20,6 +20,7 @@
#define SCX_READER_H
template<typename T, class Comparer> class event_queue;
class M3ExtraCycles;
#include "video_event.h"
#include "video_event_comparer.h"
@ -31,6 +32,7 @@ class ScxReader : public VideoEvent {
VideoEvent &wxReader;
VideoEvent &weEnableChecker;
VideoEvent &weDisableChecker;
M3ExtraCycles &m3ExtraCycles;
unsigned char scxAnd7_;
unsigned char src;
@ -43,7 +45,8 @@ public:
// VideoEvent &wyReader3_in,
VideoEvent &wxReader_in,
VideoEvent &weEnableChecker_in,
VideoEvent &weDisableChecker_in);
VideoEvent &weDisableChecker_in,
M3ExtraCycles &m3ExtraCycles);
void doEvent();

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -17,35 +17,43 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "sprite_mapper.h"
#include "sprite_size_reader.h"
#include "scx_reader.h"
#include "../event_queue.h"
// #include <algorithm>
#include "m3_extra_cycles.h"
#include "../insertion_sort.h"
#include <cstring>
SpriteMapper::SpriteMapper(const SpriteSizeReader &spriteSizeReader_in,
const ScxReader &scxReader_in,
const unsigned char *const oamram_in) :
// #include <algorithm>
class SpxLess {
const unsigned char *const oamram_plus1;
public:
SpxLess(const unsigned char *const oamram) : oamram_plus1(oamram + 1) {}
bool operator()(const unsigned char l, const unsigned char r) const {
return oamram_plus1[l] < oamram_plus1[r];
}
};
SpriteMapper::SpriteMapper(M3ExtraCycles &m3ExtraCycles,
const unsigned char *const oamram) :
VideoEvent(2),
spriteSizeReader(spriteSizeReader_in),
scxReader(scxReader_in),
oamram(oamram_in)
m3ExtraCycles(m3ExtraCycles),
oamram(oamram)
{
setDoubleSpeed(false);
setCgb(false);
setLargeSpritesSource(false);
largeSprites_ = largeSpritesSrc_;
clearMap();
}
void SpriteMapper::clearMap() {
std::memset(cycles, CYCLES_INVALID, sizeof(cycles));
std::memset(num, 0, sizeof(num));
std::memset(num, cgb ? 0 : NEED_SORTING_MASK, sizeof(num));
}
void SpriteMapper::mapSprites() {
clearMap();
const unsigned spriteHeight = 8u << spriteSizeReader.largeSprites();
const unsigned spriteHeight = 8u << largeSprites();
for (unsigned i = 0x00; i < 0xA0; i += 4) {
const unsigned bottom_pos = oamram[i] - (17u - spriteHeight);
@ -53,10 +61,7 @@ void SpriteMapper::mapSprites() {
if (bottom_pos >= 143 + spriteHeight)
continue;
const unsigned spx = oamram[i + 1];
const unsigned value = spx << 8 | i;
unsigned short *map = spritemap;
unsigned char *map = spritemap;
unsigned char *n = num;
if (bottom_pos >= spriteHeight) {
@ -68,95 +73,30 @@ void SpriteMapper::mapSprites() {
unsigned char *const end = num + (bottom_pos >= 143 ? 143 : bottom_pos);
do {
if (*n < 10)
map[(*n)++] = value;
if ((*n & ~NEED_SORTING_MASK) < 10)
map[(*n)++ & ~NEED_SORTING_MASK] = i;
map += 10;
++n;
} while (n <= end);
}
m3ExtraCycles.invalidateCache();
}
// 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;
unsigned short *b = a;
while (b != start && *(b - 1) > e) {
*b = *(b - 1);
b = b - 1;
}
*b = e;
}
}
void SpriteMapper::updateLine(const unsigned ly) const {
if (num[ly] == 0) {
cycles[ly] = 0;
return;
}
unsigned short sortBuf[10];
unsigned short *tmp = spritemap + ly * 10;
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;
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;
if (spx - tmpSpx > 4U)
break;
if ((scxReader.scxAnd7() + tmpSpx & 7) < 4 || spx == tmpSpx) {
cycles = 6;
break;
}
}
}
sum += cycles;
}
cycles[ly] = sum;
void SpriteMapper::sortLine(const unsigned ly) const {
num[ly] &= ~NEED_SORTING_MASK;
insertionSort(spritemap + ly * 10, spritemap + ly * 10 + num[ly], SpxLess(oamram));
}
void SpriteMapper::doEvent() {
largeSprites_ = largeSpritesSrc_;
mapSprites();
if (spriteSizeReader.time() < scxReader.time())
setTime(spriteSizeReader.time() + timeDiff);
else
setTime(scxReader.time());
setTime(DISABLED_TIME);
}
void SpriteMapper::reset() {
mapSprites();
setTime(DISABLED_TIME);
doEvent();
}
/*void SpriteMapper::schedule() {

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -23,67 +23,63 @@
//#include "video_event_comparer.h"
#include "ly_counter.h"
template<typename T, class Comparer> class event_queue;
class SpriteSizeReader;
class ScxReader;
class M3ExtraCycles;
class SpriteMapper : public VideoEvent {
enum { CYCLES_INVALID = 0xFF };
enum { NEED_SORTING_MASK = 0x80 };
mutable unsigned short spritemap[144*10];
mutable unsigned char cycles[144];
unsigned char num[144];
mutable unsigned char spritemap[144*10];
mutable unsigned char num[144];
const SpriteSizeReader &spriteSizeReader;
const ScxReader &scxReader;
M3ExtraCycles &m3ExtraCycles;
public:
const unsigned char *const oamram;
private:
unsigned char timeDiff;
bool largeSprites_;
bool largeSpritesSrc_;
bool cgb;
void clearMap();
void mapSprites();
void updateLine(unsigned ly) const;
void sortLine(unsigned ly) const;
public:
SpriteMapper(const SpriteSizeReader &spriteSizeReader_in,
const ScxReader &scxReader_in,
SpriteMapper(M3ExtraCycles &m3ExtraCycles,
const unsigned char *const oamram_in);
void doEvent();
bool isCgb() const {
return cgb;
}
bool largeSprites() const {
return largeSprites_;
}
unsigned numSprites(const unsigned ly) const {
return num[ly] & ~NEED_SORTING_MASK;
}
void reset();
void schedule(const LyCounter &lyCounter, const unsigned long cycleCounter) {
// synced to scxReader.
setTime(lyCounter.nextLineCycle(82 + lyCounter.isDoubleSpeed() * 3, cycleCounter));
setTime(lyCounter.nextLineCycle(16 + lyCounter.isDoubleSpeed() * 4, cycleCounter));
}
void setCgb(const bool cgb_in) {
cgb = cgb_in;
}
void setDoubleSpeed(const bool dS) {
timeDiff = dS ? 85 * 2 - 40 : (82 - 16);
void setLargeSpritesSource(const bool src) {
largeSpritesSrc_ = src;
}
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);
const unsigned char* sprites(const unsigned ly) const {
if (num[ly] & NEED_SORTING_MASK)
sortLine(ly);
return spritemap + ly * 10;
}

View File

@ -32,6 +32,7 @@ public:
static const unsigned long DISABLED_TIME = 0xFFFFFFFF;
VideoEvent(const unsigned priority_in) :
time_(DISABLED_TIME),
priority_(priority_in)
{}

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -18,36 +18,35 @@
***************************************************************************/
#include "we.h"
We::WeEnableChecker::WeEnableChecker(bool &we_in, const bool &src_in) :
We::WeEnableChecker::WeEnableChecker(We &we) :
VideoEvent(8),
we(we_in),
src(src_in)
we(we)
{}
void We::WeEnableChecker::doEvent() {
we = src;
we.set(we.src_);
setTime(DISABLED_TIME);
}
We::WeDisableChecker::WeDisableChecker(bool &we_in, const bool &src_in) :
We::WeDisableChecker::WeDisableChecker(We &we) :
VideoEvent(9),
we(we_in),
src(src_in)
we(we)
{}
void We::WeDisableChecker::doEvent() {
we = we && src;
we.set(we.we_ & we.src_);
setTime(DISABLED_TIME);
}
We::We() :
enableChecker_(we_, src_),
disableChecker_(we_, src_)
We::We(M3ExtraCycles &m3ExtraCycles) :
m3ExtraCycles_(m3ExtraCycles),
enableChecker_(*this),
disableChecker_(*this)
{
setSource(false);
reset();
we_ = src_;
}
void We::reset() {

View File

@ -21,14 +21,14 @@
#include "video_event.h"
#include "ly_counter.h"
#include "m3_extra_cycles.h"
class We {
class WeEnableChecker : public VideoEvent {
bool &we;
const bool &src;
We &we;
public:
WeEnableChecker(bool &we_in, const bool &src_in);
WeEnableChecker(We &we);
void doEvent();
@ -38,11 +38,10 @@ class We {
};
class WeDisableChecker : public VideoEvent {
bool &we;
const bool &src;
We &we;
public:
WeDisableChecker(bool &we_in, const bool &src_in);
WeDisableChecker(We &we);
void doEvent();
@ -51,15 +50,25 @@ class We {
}
};
friend class WeEnableChecker;
friend class WeDisableChecker;
M3ExtraCycles &m3ExtraCycles_;
WeEnableChecker enableChecker_;
WeDisableChecker disableChecker_;
bool we_;
bool src_;
void set(const bool value) {
if (we_ != value)
m3ExtraCycles_.invalidateCache();
we_ = value;
}
public:
We();
We(M3ExtraCycles &m3ExtraCycles);
WeDisableChecker& disableChecker() {
return disableChecker_;

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -24,13 +24,15 @@
WeMasterChecker::WeMasterChecker(event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue_in,
Wy &wy_in,
const LyCounter &lyCounter_in) :
const LyCounter &lyCounter_in,
M3ExtraCycles &m3ExtraCycles) :
VideoEvent(10),
m3EventQueue(m3EventQueue_in),
wy(wy_in),
lyCounter(lyCounter_in)
lyCounter(lyCounter_in),
m3ExtraCycles(m3ExtraCycles)
{
reset();
weMaster_ = false;
}
void WeMasterChecker::doEvent() {
@ -40,7 +42,7 @@ void WeMasterChecker::doEvent() {
addEvent(wy.reader4(), lyCounter, time(), m3EventQueue);
}
weMaster_ |= true;
set(true);
// }
setTime(time() + (70224U << lyCounter.isDoubleSpeed()));

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -25,18 +25,28 @@ class Wy;
#include "video_event.h"
#include "video_event_comparer.h"
#include "ly_counter.h"
#include "m3_extra_cycles.h"
class WeMasterChecker : public VideoEvent {
event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue;
Wy &wy;
const LyCounter &lyCounter;
M3ExtraCycles &m3ExtraCycles;
bool weMaster_;
void set(const bool value) {
if (weMaster_ != value)
m3ExtraCycles.invalidateCache();
weMaster_ = value;
}
public:
WeMasterChecker(event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue_in,
Wy &wy_in,
const LyCounter &lyCounter_in);
const LyCounter &lyCounter_in,
M3ExtraCycles &m3ExtraCycles);
void doEvent();
@ -53,7 +63,7 @@ public:
}
void unset() {
weMaster_ = false;
set(false);
}
bool weMaster() const {

View File

@ -1,61 +1,47 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* 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 SPRITE_SIZE_READER_H
#define SPRITE_SIZE_READER_H
template<typename T, class Comparer> class event_queue;
class SpriteMapper;
#include "video_event.h"
#include "ly_counter.h"
#include "video_event_comparer.h"
class SpriteSizeReader : public VideoEvent {
event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue;
SpriteMapper &spriteMapper;
const LyCounter &lyCounter;
bool largeSprites_;
bool src_;
public:
SpriteSizeReader(event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue_in,
SpriteMapper &spriteMapper_in, const LyCounter &lyCounter_in);
void doEvent();
bool largeSprites() const {
return largeSprites_;
}
void reset() {
largeSprites_ = src_;
setTime(DISABLED_TIME);
}
void setSource(const bool src) {
src_ = src;
}
void schedule(const LyCounter &lyCounter, const unsigned long cycleCounter) {
setTime(lyCounter.nextLineCycle(16 + lyCounter.isDoubleSpeed() * 4, cycleCounter));
}
};
#endif
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* 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 WINDOW_H
#define WINDOW_H
#include "we.h"
#include "we_master_checker.h"
#include "wy.h"
#include "wx_reader.h"
struct Window {
We we;
WeMasterChecker weMasterChecker;
Wy wyReg;
WxReader wxReader;
Window(event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue,
const LyCounter &lyCounter,
M3ExtraCycles &m3ExtraCycles) :
we(m3ExtraCycles),
weMasterChecker(m3EventQueue, wyReg, lyCounter, m3ExtraCycles),
wyReg(lyCounter, weMasterChecker, m3ExtraCycles),
wxReader(m3EventQueue, we.enableChecker(), we.disableChecker(), m3ExtraCycles)
{}
bool enabled(const unsigned ly) const {
return we.value() && wxReader.wx() < 0xA7 && ly >= wyReg.value() && (weMasterChecker.weMaster() || ly == wyReg.value());
}
};
#endif /*WINDOW_H*/

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -19,14 +19,17 @@
#include "wx_reader.h"
#include "../event_queue.h"
#include "m3_extra_cycles.h"
WxReader::WxReader(event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue_in,
VideoEvent &weEnableChecker_in,
VideoEvent &weDisableChecker_in) :
WxReader::WxReader(event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue,
VideoEvent &weEnableChecker,
VideoEvent &weDisableChecker,
M3ExtraCycles &m3ExtraCycles) :
VideoEvent(7),
m3EventQueue(m3EventQueue_in),
weEnableChecker(weEnableChecker_in),
weDisableChecker(weDisableChecker_in)
m3EventQueue(m3EventQueue),
weEnableChecker(weEnableChecker),
weDisableChecker(weDisableChecker),
m3ExtraCycles(m3ExtraCycles)
{
setDoubleSpeed(false);
setSource(0);
@ -47,6 +50,8 @@ void WxReader::doEvent() {
rescheduleEvent(weEnableChecker, diff);
rescheduleEvent(weDisableChecker, diff);
m3ExtraCycles.invalidateCache();
setTime(DISABLED_TIME);
}

View File

@ -20,6 +20,7 @@
#define WX_READER_H
template<typename T, class Comparer> class event_queue;
class M3ExtraCycles;
#include "video_event.h"
#include "video_event_comparer.h"
@ -29,6 +30,7 @@ class WxReader : public VideoEvent {
event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue;
VideoEvent &weEnableChecker;
VideoEvent &weDisableChecker;
M3ExtraCycles &m3ExtraCycles;
unsigned char wx_;
unsigned char src_;
@ -39,7 +41,8 @@ class WxReader : public VideoEvent {
public:
WxReader(event_queue<VideoEvent*,VideoEventComparer> &m3EventQueue_in,
VideoEvent &weEnableChecker_in,
VideoEvent &weDisableChecker_in);
VideoEvent &weDisableChecker_in,
M3ExtraCycles &m3ExtraCycles);
void doEvent();

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -22,83 +22,77 @@
#include "scx_reader.h"
#include "../event_queue.h"
Wy::WyReader1::WyReader1(unsigned char &wy, const unsigned char &src, const LyCounter &lyCounter, const WeMasterChecker &weMasterChecker) :
Wy::WyReader1::WyReader1(Wy &wy, const WeMasterChecker &weMasterChecker) :
VideoEvent(3),
lyCounter(lyCounter),
weMasterChecker(weMasterChecker),
wy(wy),
src(src)
weMasterChecker(weMasterChecker)
{}
void Wy::WyReader1::doEvent() {
if (src >= lyCounter.ly() && /*wy >= lyCounter.ly()*/ !weMasterChecker.weMaster()) {
wy = src;
}
if (wy.src_ >= wy.lyCounter.ly() && /*wy >= lyCounter.ly()*/ !weMasterChecker.weMaster())
wy.set(wy.src_);
setTime(DISABLED_TIME);
}
Wy::WyReader2::WyReader2(unsigned char &wy_in, const unsigned char &src_in, const LyCounter &lyCounter_in) :
Wy::WyReader2::WyReader2(Wy &wy) :
VideoEvent(4),
lyCounter(lyCounter_in),
wy(wy_in),
src(src_in)
wy(wy)
{}
void Wy::WyReader2::doEvent() {
if (wy == lyCounter.ly() + 1 - lyCounter.isDoubleSpeed() && src > wy)
wy = src;
if (wy.wy_ == wy.lyCounter.ly() + 1 - wy.lyCounter.isDoubleSpeed() && wy.src_ > wy.wy_)
wy.set(wy.src_);
setTime(DISABLED_TIME);
}
Wy::WyReader3::WyReader3(unsigned char &wy_in, const unsigned char &src_in, const LyCounter &lyCounter_in) :
Wy::WyReader3::WyReader3(Wy &wy) :
VideoEvent(5),
lyCounter(lyCounter_in),
wy(wy_in),
src(src_in)
wy(wy)
{}
void Wy::WyReader3::doEvent() {
if (src == lyCounter.ly() && wy > lyCounter.ly())
wy = src;
if (wy.src_ == wy.lyCounter.ly() && wy.wy_ > wy.lyCounter.ly())
wy.set(wy.src_);
setTime(DISABLED_TIME);
}
void Wy::WyReader3::schedule(const unsigned wxSrc, const ScxReader &scxReader, const unsigned long cycleCounter) {
const unsigned curLineCycle = 456 - (lyCounter.time() - cycleCounter >> lyCounter.isDoubleSpeed());
const unsigned baseTime = 78 + lyCounter.isDoubleSpeed() * 6 + wxSrc;
const unsigned curLineCycle = 456 - (wy.lyCounter.time() - cycleCounter >> wy.lyCounter.isDoubleSpeed());
const unsigned baseTime = 78 + wy.lyCounter.isDoubleSpeed() * 6 + wxSrc;
if (curLineCycle >= 82U + lyCounter.isDoubleSpeed() * 3) {
if (curLineCycle >= 82U + wy.lyCounter.isDoubleSpeed() * 3) {
if (baseTime + scxReader.scxAnd7() > curLineCycle)
setTime(lyCounter.time() + (baseTime + scxReader.scxAnd7() << lyCounter.isDoubleSpeed()) - lyCounter.lineTime());
setTime(wy.lyCounter.time() + (baseTime + scxReader.scxAnd7() << wy.lyCounter.isDoubleSpeed()) - wy.lyCounter.lineTime());
else
setTime(lyCounter.time() + (baseTime + scxReader.getSource() << lyCounter.isDoubleSpeed()));
setTime(wy.lyCounter.time() + (baseTime + scxReader.getSource() << wy.lyCounter.isDoubleSpeed()));
} else
setTime(lyCounter.nextLineCycle(baseTime + scxReader.getSource(), cycleCounter));
setTime(wy.lyCounter.nextLineCycle(baseTime + scxReader.getSource(), cycleCounter));
}
Wy::WyReader4::WyReader4(unsigned char &wy_in, const unsigned char &src_in) :
Wy::WyReader4::WyReader4(Wy &wy) :
VideoEvent(6),
wy(wy_in),
src(src_in)
wy(wy)
{}
void Wy::WyReader4::doEvent() {
wy = src;
wy.set(wy.src_);
setTime(DISABLED_TIME);
}
Wy::Wy(const LyCounter &lyCounter, const WeMasterChecker &weMasterChecker) :
reader1_(wy_, src_, lyCounter, weMasterChecker),
reader2_(wy_, src_, lyCounter),
reader3_(wy_, src_, lyCounter),
reader4_(wy_, src_)
Wy::Wy(const LyCounter &lyCounter, const WeMasterChecker &weMasterChecker, M3ExtraCycles &m3ExtraCycles) :
lyCounter(lyCounter),
m3ExtraCycles(m3ExtraCycles),
reader1_(*this, weMasterChecker),
reader2_(*this),
reader3_(*this),
reader4_(*this)
{
setSource(0);
reset();
wy_ = src_;
}
void Wy::reset() {

View File

@ -26,16 +26,16 @@ template<typename T, class Comparer> class event_queue;
#include "video_event.h"
#include "video_event_comparer.h"
#include "ly_counter.h"
#include "m3_extra_cycles.h"
class Wy {
public:
class WyReader1 : public VideoEvent {
const LyCounter &lyCounter;
Wy &wy;
const WeMasterChecker &weMasterChecker;
unsigned char &wy;
const unsigned char &src;
public:
WyReader1(unsigned char &wy_in, const unsigned char &src_in, const LyCounter &lyCounter_in, const WeMasterChecker &weMasterChecker);
WyReader1(Wy &wy, const WeMasterChecker &weMasterChecker);
void doEvent();
@ -45,12 +45,10 @@ class Wy {
};
class WyReader2 : public VideoEvent {
const LyCounter &lyCounter;
unsigned char &wy;
const unsigned char &src;
Wy &wy;
public:
WyReader2(unsigned char &wy_in, const unsigned char &src_in, const LyCounter &lyCounter_in);
WyReader2(Wy &wy);
void doEvent();
@ -59,28 +57,11 @@ class Wy {
}
};
class WyReader4 : public VideoEvent {
unsigned char &wy;
const unsigned char &src;
public:
WyReader4(unsigned char &wy_in, const unsigned char &src_in);
void doEvent();
void schedule(const LyCounter &lyCounter, const unsigned long cycleCounter) {
setTime(lyCounter.nextFrameCycle(lyCounter.isDoubleSpeed() * 4, cycleCounter));
}
};
public:
class WyReader3 : public VideoEvent {
const LyCounter &lyCounter;
unsigned char &wy;
const unsigned char &src;
Wy &wy;
public:
WyReader3(unsigned char &wy_in, const unsigned char &src_in, const LyCounter &lyCounter_in);
WyReader3(Wy &wy);
void doEvent();
void schedule(unsigned wxSrc, const ScxReader &scxReader, unsigned long cycleCounter);
@ -90,7 +71,27 @@ public:
//}
};
class WyReader4 : public VideoEvent {
Wy &wy;
public:
WyReader4(Wy &wy);
void doEvent();
void schedule(const LyCounter &lyCounter, const unsigned long cycleCounter) {
setTime(lyCounter.nextFrameCycle(lyCounter.isDoubleSpeed() * 4, cycleCounter));
}
};
friend class WyReader1;
friend class WyReader2;
friend class WyReader3;
friend class WyReader4;
private:
const LyCounter &lyCounter;
M3ExtraCycles &m3ExtraCycles;
WyReader1 reader1_;
WyReader2 reader2_;
WyReader3 reader3_;
@ -99,8 +100,15 @@ private:
unsigned char wy_;
unsigned char src_;
void set(const unsigned char value) {
if (wy_ != value)
m3ExtraCycles.invalidateCache();
wy_ = value;
}
public:
Wy(const LyCounter &lyCounter, const WeMasterChecker &weMasterChecker);
Wy(const LyCounter &lyCounter, const WeMasterChecker &weMasterChecker, M3ExtraCycles &m3ExtraCycles);
WyReader1& reader1() {
return reader1_;
@ -128,16 +136,16 @@ public:
src_ = src;
}
void setValue(const unsigned val) {
wy_ = val;
}
//void setValue(const unsigned val) {
// wy_ = val;
//}
unsigned value() const {
return wy_;
}
void weirdAssWeMasterEnableOnWyLineCase() {
++wy_;
set(wy_ + 1);
}
};