VT100 supports both 80-column and 132-column modes now

This commit is contained in:
Jeff Parsons 2016-08-15 12:06:30 -07:00
commit aa08c7a94b

View file

@ -152,7 +152,7 @@ function Video(parmsVideo, canvas, context, textarea, container)
/* /*
* Now that we've finished using nRowsBuffer to help define the screen size, we add one more * Now that we've finished using nRowsBuffer to help define the screen size, we add one more
* row for text modes, to simplify smooth-scrolling down the road. * row for text modes, to account for the VT100's scroll line buffer (used for smooth scrolling).
*/ */
if (this.cyCell > 1) this.nRowsBuffer++; if (this.cyCell > 1) this.nRowsBuffer++;
@ -292,6 +292,9 @@ Video.VT100 = {
/** /**
* initBuffers() * initBuffers()
*
* @this {Video}
* @return {boolean}
*/ */
Video.prototype.initBuffers = function() Video.prototype.initBuffers = function()
{ {
@ -308,10 +311,11 @@ Video.prototype.initBuffers = function()
cyBuffer = this.cxBuffer; cyBuffer = this.cxBuffer;
} }
this.sizeBuffer = ((this.cxBuffer * this.nBitsPerPixel) >> 3) * this.cyBuffer; this.sizeBuffer = 0;
if (!this.fUseRAM) { if (!this.fUseRAM) {
this.sizeBuffer = ((this.cxBuffer * this.nBitsPerPixel) >> 3) * this.cyBuffer;
if (!this.bus.addMemory(this.addrBuffer, this.sizeBuffer, Memory.TYPE.VIDEO)) { if (!this.bus.addMemory(this.addrBuffer, this.sizeBuffer, Memory.TYPE.VIDEO)) {
return; return false;
} }
} }
@ -319,15 +323,15 @@ Video.prototype.initBuffers = function()
* imageBuffer is only used for graphics modes. For text modes, we create a canvas * imageBuffer is only used for graphics modes. For text modes, we create a canvas
* for each font and draw characters by drawing from the font canvas to the target canvas. * for each font and draw characters by drawing from the font canvas to the target canvas.
*/ */
if (this.cxCell > 1) { if (this.sizeBuffer) {
this.imageBuffer = this.contextScreen.createImageData(cxBuffer, cyBuffer);
this.nPixelsPerCell = (16 / this.nBitsPerPixel)|0;
this.initCellCache(this.sizeBuffer >> 1);
} else {
/* /*
* We add an extra column per row to store the visible line length at the start of every row. * We add an extra column per row to store the visible line length at the start of every row.
*/ */
this.initCellCache((this.nColsBuffer + 1) * this.nRowsBuffer); this.initCellCache((this.nColsBuffer + 1) * this.nRowsBuffer);
} else {
this.imageBuffer = this.contextScreen.createImageData(cxBuffer, cyBuffer);
this.nPixelsPerCell = (16 / this.nBitsPerPixel)|0;
this.initCellCache(this.sizeBuffer >> 1);
} }
this.canvasBuffer = document.createElement("canvas"); this.canvasBuffer = document.createElement("canvas");
@ -383,6 +387,7 @@ Video.prototype.initBuffers = function()
this.abLineBuffer = new Array(this.nColsBuffer); this.abLineBuffer = new Array(this.nColsBuffer);
} }
return true;
}; };
/** /**
@ -461,7 +466,8 @@ Video.prototype.doneLoad = function(sURL, sFontData, nErrorCode)
* Minimal font data validation, just to make sure we're not getting garbage from the server. * Minimal font data validation, just to make sure we're not getting garbage from the server.
*/ */
if (abFontData.length == 2048) { if (abFontData.length == 2048) {
this.createFonts(abFontData); this.abFontData = abFontData;
this.createFonts();
} }
else { else {
this.notice("Unrecognized font data length (" + abFontData.length + ")"); this.notice("Unrecognized font data length (" + abFontData.length + ")");
@ -484,30 +490,33 @@ Video.prototype.doneLoad = function(sURL, sFontData, nErrorCode)
}; };
/** /**
* createFonts(abFontData) * createFonts()
* *
* @this {Video} * @this {Video}
* @param {Array.<number>} abFontData * @return {boolean}
*/ */
Video.prototype.createFonts = function(abFontData) Video.prototype.createFonts = function()
{ {
/* /*
* We retain abFontData in case we have to rebuild the fonts (eg, when we switch from 80 to 132 columns) * We retain abFontData in case we have to rebuild the fonts (eg, when we switch from 80 to 132 columns)
*/ */
this.abFontData = abFontData; if (this.abFontData) {
this.fDotStretcher = (this.nFormat == Video.FORMAT.VT100); this.fDotStretcher = (this.nFormat == Video.FORMAT.VT100);
this.aFonts[Video.VT100.FONT.NORML] = [ this.aFonts[Video.VT100.FONT.NORML] = [
this.createFontVariation(this.cxCell, this.cyCell), this.createFontVariation(this.cxCell, this.cyCell),
this.createFontVariation(this.cxCell, this.cyCell, this.fUnderline) this.createFontVariation(this.cxCell, this.cyCell, this.fUnderline)
]; ];
this.aFonts[Video.VT100.FONT.DWIDE] = [ this.aFonts[Video.VT100.FONT.DWIDE] = [
this.createFontVariation(this.cxCell*2, this.cyCell), this.createFontVariation(this.cxCell*2, this.cyCell),
this.createFontVariation(this.cxCell*2, this.cyCell, this.fUnderline) this.createFontVariation(this.cxCell*2, this.cyCell, this.fUnderline)
]; ];
this.aFonts[Video.VT100.FONT.DHIGH] = this.aFonts[Video.VT100.FONT.DHIGH_BOT] = [ this.aFonts[Video.VT100.FONT.DHIGH] = this.aFonts[Video.VT100.FONT.DHIGH_BOT] = [
this.createFontVariation(this.cxCell*2, this.cyCell*2), this.createFontVariation(this.cxCell*2, this.cyCell*2),
this.createFontVariation(this.cxCell*2, this.cyCell*2, this.fUnderline) this.createFontVariation(this.cxCell*2, this.cyCell*2, this.fUnderline)
]; ];
return true;
}
return false;
}; };
/** /**
@ -724,6 +733,19 @@ Video.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
Video.prototype.updateDimensions = function(nCols, nRows) Video.prototype.updateDimensions = function(nCols, nRows)
{ {
this.println("updateDimensions(" + nCols + "," + nRows + ")"); this.println("updateDimensions(" + nCols + "," + nRows + ")");
this.nColsBuffer = nCols;
/*
* Even when the number of effective rows is 14 (or 15 counting the scroll line buffer), we want
* to leave the number of rows at 24 (or 25 counting the scroll line buffer), because the VT100 doesn't
* actually change character height (only character width).
*
* this.nRowsBuffer = nRows+1; // +1 for scroll line buffer
*/
this.cxCell = this.cxCellDefault;
if (nCols > 80) this.cxCell--; // VT100 font cells are 9x10 instead of 10x10 in 132-column mode
if (this.initBuffers()) {
this.createFonts();
}
}; };
/** /**
@ -1085,8 +1107,8 @@ Video.prototype.updateVT100 = function(fForced)
if (cUpdated && this.contextBuffer) { if (cUpdated && this.contextBuffer) {
/* /*
* NOTE: We must subtract cyCell from cyBuffer to avoid displaying the extra row that we normally buffer * NOTE: We must subtract cyCell from cyBuffer to avoid displaying the extra "scroll line" that we normally
* in support of smooth-scrolling. * buffer to support smooth-scrolling.
*/ */
this.contextScreen.drawImage(this.canvasBuffer, 0, 0, this.cxBuffer, this.cyBuffer - this.cyCell, this.xScreenOffset, this.yScreenOffset, this.cxScreenOffset, this.cyScreenOffset); this.contextScreen.drawImage(this.canvasBuffer, 0, 0, this.cxBuffer, this.cyBuffer - this.cyCell, this.xScreenOffset, this.yScreenOffset, this.cxScreenOffset, this.cyScreenOffset);
} }
@ -1139,9 +1161,10 @@ Video.prototype.updateScreen = function(n)
} }
/* /*
* Since this is not a forced update, if our cell cache is valid AND the buffer is clean, then do nothing. * Since this is not a forced update, if our cell cache is valid AND we allocated our own buffer AND the buffer
* is clean, then there's nothing to do.
*/ */
if (fUpdate && this.fCellCacheValid) { if (fUpdate && this.fCellCacheValid && this.sizeBuffer) {
if ((fClean = this.bus.cleanMemory(this.addrBuffer, this.sizeBuffer))) { if ((fClean = this.bus.cleanMemory(this.addrBuffer, this.sizeBuffer))) {
fUpdate = false; fUpdate = false;
} }