Fixed text-mode page flipping (needed more aggressive, but still careful, cache invalidation)

This commit is contained in:
Jeff Parsons 2016-03-31 14:44:40 -07:00
commit 265851d963
7 changed files with 917 additions and 891 deletions

View file

@ -1114,7 +1114,8 @@
</xsl:call-template> </xsl:call-template>
</xsl:template> </xsl:template>
<xsl:template name="comment"> <xsl:template match="comment">
<xsl:comment><xsl:apply-templates/></xsl:comment>
</xsl:template> </xsl:template>
</xsl:stylesheet> </xsl:stylesheet>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -5054,7 +5054,7 @@ Video.prototype.checkMode = function(fForce)
* setMode(nMode, fForce) * setMode(nMode, fForce)
* *
* Set fForce to true to update the mode regardless of previous mode, or false to perform * Set fForce to true to update the mode regardless of previous mode, or false to perform
* a normal update that bypasses updateScreen() but still calls initCellCache(). * a normal update that bypasses updateScreen() but still calls initCache().
* *
* @this {Video} * @this {Video}
* @param {number|null} nMode * @param {number|null} nMode
@ -5125,7 +5125,7 @@ Video.prototype.setMode = function(nMode, fForce)
} }
} }
this.setDimensions(); this.setDimensions();
this.invalidateScreen(true); this.invalidateCache(true);
this.updateScreen(); this.updateScreen();
} }
return true; return true;
@ -5152,17 +5152,17 @@ Video.prototype.setPixel = function(imageData, x, y, rgb)
}; };
/** /**
* initCellCache() * initCache()
* *
* Initializes the contents of our internal cell cache. * Initializes the contents of our internal cell cache.
* *
* TODO: Consider changing this to a cache of RGB values, so that when the buffer is merely being color-cycled, * TODO: Consider changing this to a cache of RGB values, so that when the buffer is merely being color-cycled,
* we don't have to update the entire screen. This will also allow invalidateScreen() to honor the fModified flag, * we don't have to update the entire screen. This will also allow invalidateCache() to honor the fModified flag,
* bypassing initCellCache() when it is false. * bypassing initCache() when it is false.
* *
* @this {Video} * @this {Video}
*/ */
Video.prototype.initCellCache = function() Video.prototype.initCache = function()
{ {
this.cBlinkVisible = -1; // invalidate the visible blinking character count, to force updateScreen() to recount this.cBlinkVisible = -1; // invalidate the visible blinking character count, to force updateScreen() to recount
this.fCellCacheValid = false; this.fCellCacheValid = false;
@ -5173,7 +5173,7 @@ Video.prototype.initCellCache = function()
}; };
/** /**
* invalidateScreen(fModified) * invalidateCache(fModified)
* *
* Ensure that the next updateScreen() will update every cell; intended for situations where the entire screen needs * Ensure that the next updateScreen() will update every cell; intended for situations where the entire screen needs
* to be redrawn, even though the underlying data in the video buffer has not changed (and therefore cleanMemory() will * to be redrawn, even though the underlying data in the video buffer has not changed (and therefore cleanMemory() will
@ -5184,10 +5184,10 @@ Video.prototype.initCellCache = function()
* @this {Video} * @this {Video}
* @param {boolean} [fModified] (true if the buffer may have been modified, false if only color(s) may have changed) * @param {boolean} [fModified] (true if the buffer may have been modified, false if only color(s) may have changed)
*/ */
Video.prototype.invalidateScreen = function(fModified) Video.prototype.invalidateCache = function(fModified)
{ {
if (!fModified) this.fRGBValid = false; if (!fModified) this.fRGBValid = false;
this.initCellCache(); this.initCache();
}; };
/** /**
@ -5340,7 +5340,7 @@ Video.prototype.updateChar = function(col, row, data, context)
* are the periodic updates coming from the CPU. * are the periodic updates coming from the CPU.
* *
* For every cell in the video buffer, compare it to the cell stored in the cell cache, render if it differs, * For every cell in the video buffer, compare it to the cell stored in the cell cache, render if it differs,
* and then update the cell cache to match. Since initCellCache() sets every cell in the cell cache to an * and then update the cell cache to match. Since initCache() sets every cell in the cell cache to an
* invalid value, we're assured that the next call to updateScreen() will redraw the entire (visible) video buffer. * invalid value, we're assured that the next call to updateScreen() will redraw the entire (visible) video buffer.
* *
* @this {Video} * @this {Video}
@ -5372,7 +5372,7 @@ Video.prototype.updateScreen = function(fForce)
if (!fEnabled && !fForce) return; if (!fEnabled && !fForce) return;
if (fForce) { if (fForce) {
this.initCellCache(); this.initCache();
} }
else { else {
/* /*
@ -5435,7 +5435,14 @@ Video.prototype.updateScreen = function(fForce)
* multi-display configuration. * multi-display configuration.
*/ */
if ((this.getRetraceBits(card) & Card.CGA.STATUS.VRETRACE) || card.nVertPeriodsStartAddr && card.nVertPeriodsStartAddr < card.nVertPeriods) { if ((this.getRetraceBits(card) & Card.CGA.STATUS.VRETRACE) || card.nVertPeriodsStartAddr && card.nVertPeriodsStartAddr < card.nVertPeriods) {
card.offStartAddr = ((card.regCRTData[Card.CRTC.START_ADDR_HI] << 8) + card.regCRTData[Card.CRTC.START_ADDR_LO])|0; /*
* PARANOIA: Don't call invalidateCache() unless the address we're about to "latch" actually changed.
*/
var offStartAddr = ((card.regCRTData[Card.CRTC.START_ADDR_HI] << 8) + card.regCRTData[Card.CRTC.START_ADDR_LO])|0;
if (card.offStartAddr !== offStartAddr) {
card.offStartAddr = offStartAddr;
this.invalidateCache();
}
card.nVertPeriodsStartAddr = 0; card.nVertPeriodsStartAddr = 0;
} }
@ -6162,8 +6169,14 @@ Video.prototype.outATC = function(port, bOut, addrFrom)
/* /*
* HACK: offStartAddr is supposed to be "latched" ONLY at the start of every VRETRACE interval, but * HACK: offStartAddr is supposed to be "latched" ONLY at the start of every VRETRACE interval, but
* other "triggers" are helpful; see updateScreen() for details. * other "triggers" are helpful; see updateScreen() for details.
*
* PARANOIA: Don't call invalidateCache() unless the start address we just "latched" actually changed.
*/ */
card.offStartAddr = ((card.regCRTData[Card.CRTC.START_ADDR_HI] << 8) + card.regCRTData[Card.CRTC.START_ADDR_LO])|0; var offStartAddr = ((card.regCRTData[Card.CRTC.START_ADDR_HI] << 8) + card.regCRTData[Card.CRTC.START_ADDR_LO])|0;
if (card.offStartAddr != offStartAddr) {
card.offStartAddr = offStartAddr;
this.invalidateCache();
}
card.nVertPeriodsStartAddr = 0; card.nVertPeriodsStartAddr = 0;
} else { } else {
card.fATCData = false; card.fATCData = false;
@ -6174,7 +6187,7 @@ Video.prototype.outATC = function(port, bOut, addrFrom)
this.printMessageIO(port, bOut, addrFrom, "ATC." + card.asATCRegs[iReg]); this.printMessageIO(port, bOut, addrFrom, "ATC." + card.asATCRegs[iReg]);
} }
card.regATCData[iReg] = bOut; card.regATCData[iReg] = bOut;
this.invalidateScreen(false); this.invalidateCache(false);
} }
} }
} }
@ -6510,7 +6523,7 @@ Video.prototype.outDACData = function(port, bOut, addrFrom)
var dwNew = (dw & ~(0x3f << this.cardEGA.regDACShift)) | ((bOut & 0x3f) << this.cardEGA.regDACShift); var dwNew = (dw & ~(0x3f << this.cardEGA.regDACShift)) | ((bOut & 0x3f) << this.cardEGA.regDACShift);
if (dw !== dwNew) { if (dw !== dwNew) {
this.cardEGA.regDACData[this.cardEGA.regDACAddr] = dwNew; this.cardEGA.regDACData[this.cardEGA.regDACAddr] = dwNew;
this.invalidateScreen(false); this.invalidateCache(false);
} }
this.cardEGA.regDACShift += 6; this.cardEGA.regDACShift += 6;
if (this.cardEGA.regDACShift > 12) { if (this.cardEGA.regDACShift > 12) {
@ -6795,7 +6808,7 @@ Video.prototype.outCGAColor = function(port, bOut, addrFrom)
} }
if (this.cardColor.regColor !== bOut) { if (this.cardColor.regColor !== bOut) {
this.cardColor.regColor = bOut; this.cardColor.regColor = bOut;
this.invalidateScreen(false); this.invalidateCache(false);
} }
}; };
@ -6909,7 +6922,14 @@ Video.prototype.outCRTCData = function(card, port, bOut, addrFrom)
* the vertical period count and latch it later, in updateScreen(), once the count has advanced. * the vertical period count and latch it later, in updateScreen(), once the count has advanced.
*/ */
if (this.getRetraceBits(card) & Card.CGA.STATUS.RETRACE) { if (this.getRetraceBits(card) & Card.CGA.STATUS.RETRACE) {
card.offStartAddr = ((card.regCRTData[Card.CRTC.START_ADDR_HI] << 8) + card.regCRTData[Card.CRTC.START_ADDR_LO])|0; /*
* PARANOIA: Don't call invalidateCache() unless the address we're about to "latch" actually changed.
*/
var offStartAddr = ((card.regCRTData[Card.CRTC.START_ADDR_HI] << 8) + card.regCRTData[Card.CRTC.START_ADDR_LO])|0;
if (card.offStartAddr !== offStartAddr) {
card.offStartAddr = offStartAddr;
this.invalidateCache();
}
} else if (!card.nVertPeriodsStartAddr) { } else if (!card.nVertPeriodsStartAddr) {
card.nVertPeriodsStartAddr = card.nVertPeriods; card.nVertPeriodsStartAddr = card.nVertPeriods;
} }

View file

@ -1114,7 +1114,8 @@
</xsl:call-template> </xsl:call-template>
</xsl:template> </xsl:template>
<xsl:template name="comment"> <xsl:template match="comment">
<xsl:comment><xsl:apply-templates/></xsl:comment>
</xsl:template> </xsl:template>
</xsl:stylesheet> </xsl:stylesheet>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long