/// <summary> /// Renders to the screen buffer based on the current cycle /// </summary> public void RenderScreen(int toCycle) { // check boundaries if (toCycle > FrameCycleLength) { toCycle = FrameCycleLength; } // render the required number of cycles for (int t = LastTState; t < toCycle; t++) { if (!Border4T || (t & 3) == Border4TStage) { fetchBorder = BorderColor; } else { } //fetchBorder = BorderColor; // get the table entry var item = RenderingTable.Renderer[t]; switch (item.RAction) { case RenderTable.RenderAction.None: break; case RenderTable.RenderAction.Border: ScreenBuffer[item.LineOffset] = ULAPalette[fetchBorder]; ScreenBuffer[item.LineOffset + 1] = ULAPalette[fetchBorder]; break; case RenderTable.RenderAction.BorderAndFetchByte1: ScreenBuffer[item.LineOffset] = ULAPalette[fetchBorder]; ScreenBuffer[item.LineOffset + 1] = ULAPalette[fetchBorder]; fetchB1 = _machine.FetchScreenMemory(item.ByteAddress); break; case RenderTable.RenderAction.BorderAndFetchAttribute1: ScreenBuffer[item.LineOffset] = ULAPalette[fetchBorder]; ScreenBuffer[item.LineOffset + 1] = ULAPalette[fetchBorder]; fetchA1 = _machine.FetchScreenMemory(item.AttributeAddress); ProcessInkPaper(fetchA1); break; case RenderTable.RenderAction.Shift1AndFetchByte2: ScreenBuffer[item.LineOffset] = ((fetchB1 & 0x80) != 0) ? palInk : palPaper; ScreenBuffer[item.LineOffset + 1] = ((fetchB1 & 0x40) != 0) ? palInk : palPaper; fetchB1 <<= 2; fetchB2 = _machine.FetchScreenMemory(item.ByteAddress); break; case RenderTable.RenderAction.Shift1AndFetchAttribute2: ScreenBuffer[item.LineOffset] = ((fetchB1 & 0x80) != 0) ? palInk : palPaper; ScreenBuffer[item.LineOffset + 1] = ((fetchB1 & 0x40) != 0) ? palInk : palPaper; fetchB1 <<= 2; fetchA2 = _machine.FetchScreenMemory(item.AttributeAddress); break; case RenderTable.RenderAction.Shift1: ScreenBuffer[item.LineOffset] = ((fetchB1 & 0x80) != 0) ? palInk : palPaper; ScreenBuffer[item.LineOffset + 1] = ((fetchB1 & 0x40) != 0) ? palInk : palPaper; fetchB1 <<= 2; break; case RenderTable.RenderAction.Shift1Last: ScreenBuffer[item.LineOffset] = ((fetchB1 & 0x80) != 0) ? palInk : palPaper; ScreenBuffer[item.LineOffset + 1] = ((fetchB1 & 0x40) != 0) ? palInk : palPaper; fetchB1 <<= 2; ProcessInkPaper(fetchA2); break; case RenderTable.RenderAction.Shift2: ScreenBuffer[item.LineOffset] = ((fetchB2 & 0x80) != 0) ? palInk : palPaper; ScreenBuffer[item.LineOffset + 1] = ((fetchB2 & 0x40) != 0) ? palInk : palPaper; fetchB2 <<= 2; break; case RenderTable.RenderAction.Shift2AndFetchByte1: ScreenBuffer[item.LineOffset] = ((fetchB2 & 0x80) != 0) ? palInk : palPaper; ScreenBuffer[item.LineOffset + 1] = ((fetchB2 & 0x40) != 0) ? palInk : palPaper; fetchB2 <<= 2; fetchB1 = _machine.FetchScreenMemory(item.ByteAddress); break; case RenderTable.RenderAction.Shift2AndFetchAttribute1: ScreenBuffer[item.LineOffset] = ((fetchB2 & 0x80) != 0) ? palInk : palPaper; ScreenBuffer[item.LineOffset + 1] = ((fetchB2 & 0x40) != 0) ? palInk : palPaper; fetchB2 <<= 2; fetchA1 = _machine.FetchScreenMemory(item.AttributeAddress); ProcessInkPaper(fetchA1); break; } } LastTState = toCycle; }
/// <summary> /// Updates the screen buffer based on the number of T-States supplied /// </summary> /// <param name="_tstates"></param> public virtual void UpdateScreenBuffer(long _tstates) { if (_tstates < actualULAStart) { return; } else if (_tstates >= FrameLength) { _tstates = FrameLength - 1; needsPaint = true; } //the additional 1 tstate is required to get correct number of bytes to output in ircontention.sna elapsedTStates = (_tstates + 1 - lastTState) - 1; //It takes 4 tstates to write 1 byte. Or, 2 pixels per t-state. long numBytes = (elapsedTStates >> 2) + ((elapsedTStates % 4) > 0 ? 1 : 0); int pixelData; int pixel2Data = 0xff; int attrData; int attr2Data; int bright; int ink; int paper; int flash; for (int i = 0; i < numBytes; i++) { if (tstateToDisp[lastTState] > 1) { screenByteCtr = tstateToDisp[lastTState] - 16384; //adjust for actual screen offset pixelData = _machine.FetchScreenMemory((ushort)screenByteCtr); //screen[screenByteCtr]; attrData = _machine.FetchScreenMemory((ushort)(attr[screenByteCtr] - 16384)); //screen[attr[screenByteCtr] - 16384]; lastPixelValue = pixelData; lastAttrValue = attrData; bright = (attrData & 0x40) >> 3; flash = (attrData & 0x80) >> 7; ink = (attrData & 0x07); paper = ((attrData >> 3) & 0x7); int paletteInk = ULAPalette[ink + bright]; int palettePaper = ULAPalette[paper + bright]; if (flashOn && (flash != 0)) //swap paper and ink when flash is on { int temp = paletteInk; paletteInk = palettePaper; palettePaper = temp; } for (int a = 0; a < 8; ++a) { if ((pixelData & 0x80) != 0) { ScreenBuffer[ULAByteCtr++] = paletteInk; lastAttrValue = ink; //pixelIsPaper = false; } else { ScreenBuffer[ULAByteCtr++] = palettePaper; lastAttrValue = paper; } pixelData <<= 1; } } else if (tstateToDisp[lastTState] == 1) { int bor = ULAPalette[borderColour]; for (int g = 0; g < 8; g++) { ScreenBuffer[ULAByteCtr++] = bor; } } lastTState += 4; } }