void RenderFromStartClockTo(ulong endClock) { RenderClock: if (StartClock >= endClock) return; ++HSync; if (StartClock == StartHMOVEClock) { // turn on HMOVE HMoveLatch = true; HMoveCounter = 0xf; P0mmr = P1mmr = M0mmr = M1mmr = BLmmr = true; } else if (HSync == 0) { // just wrapped around, clear late HBLANK HMoveLatch = false; } // position counters are incremented during the visible portion of the scanline if (HSync >= 68 + (HMoveLatch ? 8 : 0)) { ++P0; ++P1; ++M0; ++M1; ++BL; } // HMOVE compare, once every 1/4 CLK when on if (HMoveCounter >= 0 && (HSync & 3) == 0) { if (((HMoveCounter ^ RegW[HMP0]) & 0xf) == 0xf) P0mmr = false; if (((HMoveCounter ^ RegW[HMP1]) & 0xf) == 0xf) P1mmr = false; if (((HMoveCounter ^ RegW[HMM0]) & 0xf) == 0xf) M0mmr = false; if (((HMoveCounter ^ RegW[HMM1]) & 0xf) == 0xf) M1mmr = false; if (((HMoveCounter ^ RegW[HMBL]) & 0xf) == 0xf) BLmmr = false; if (HMoveCounter >= 0) HMoveCounter--; } // HMOVE increment, once every 1/4 CLK, 2 CLK after first compare when on if (HMoveCounter < 0xf && (HSync & 3) == 2) { if (HSync < 68 + (HMoveLatch ? 8 : 0)) { if (P0mmr) ++P0; if (P1mmr) ++P1; if (M0mmr) ++M0; if (M1mmr) ++M1; if (BLmmr) ++BL; } } if (HSync == 68 + 76) PFReflectionState = RegW[CTRLPF] & 0x01; var fbyte = (byte)0; var fbyte_colupf = colupf; TIACxFlags cxflags = 0; if (vblankon || HSync < 68 + (HMoveLatch ? 8 : 0)) goto WritePixel; fbyte = colubk; var colupfon = false; if ((PF210 & TIATables.PFMask[PFReflectionState][HSync - 68]) != 0) { if (scoreon) fbyte_colupf = (HSync - 68) < 80 ? colup0 : colup1; colupfon = true; cxflags |= TIACxFlags.PF; } if (blon && BL >= 0 && TIATables.BLMask[BLsize][BL]) { colupfon = true; cxflags |= TIACxFlags.BL; } if (!pfpriority && colupfon) { fbyte = fbyte_colupf; } if (m1on && M1 >= 0 && TIATables.MxMask[M1size][M1type][M1]) { fbyte = colup1; cxflags |= TIACxFlags.M1; } if (P1 >= 0 && (TIATables.PxMask[P1suppress][P1type][P1] & EffGRP1) != 0) { fbyte = colup1; cxflags |= TIACxFlags.P1; } if (m0on && M0 >= 0 && TIATables.MxMask[M0size][M0type][M0]) { fbyte = colup0; cxflags |= TIACxFlags.M0; } if (P0 >= 0 && (TIATables.PxMask[P0suppress][P0type][P0] & EffGRP0) != 0) { fbyte = colup0; cxflags |= TIACxFlags.P0; } if (pfpriority && colupfon) { fbyte = fbyte_colupf; } WritePixel: Collisions |= TIATables.CollisionMask[(int)cxflags]; if (HSync >= 68) { M.FrameBuffer.VideoBuffer[FrameBufferIndex++] = fbyte; if (FrameBufferIndex == M.FrameBuffer.VideoBufferByteLength) FrameBufferIndex = 0; if (HSync == 227) ScanLine++; } if (P0 >= 156) P0suppress = 0; if (P1 >= 156) P1suppress = 0; // denote this CLK has been completed by incrementing to the next StartClock++; goto RenderClock; }
void opCXCLR(ushort addr, byte data) { Collisions = 0; }
public TIA(DeserializationContext input, MachineBase m) : this() { if (input == null) throw new ArgumentNullException("input"); if (m == null) throw new ArgumentNullException("m"); M = m; TIASound = input.ReadTIASound(M, CPU_TICKS_PER_AUDIO_SAMPLE); input.CheckVersion(2); RegW = input.ReadExpectedBytes(0x40); HSync = input.ReadInt32(); HMoveCounter = input.ReadInt32(); ScanLine = input.ReadInt32(); FrameBufferIndex = input.ReadInt32(); //FrameBufferElement = input.ReadBufferElement(); StartHMOVEClock = input.ReadUInt64(); HMoveLatch = input.ReadBoolean(); StartClock = input.ReadUInt64(); P0 = input.ReadInt32(); P0mmr = input.ReadBoolean(); EffGRP0 = input.ReadByte(); OldGRP0 = input.ReadByte(); P0type = input.ReadInt32(); P0suppress = input.ReadInt32(); P1 = input.ReadInt32(); P1mmr = input.ReadBoolean(); EffGRP1 = input.ReadByte(); OldGRP1 = input.ReadByte(); P1type = input.ReadInt32(); P1suppress = input.ReadInt32(); M0 = input.ReadInt32(); M0mmr = input.ReadBoolean(); M0type = input.ReadInt32(); M0size = input.ReadInt32(); m0on = input.ReadBoolean(); M1 = input.ReadInt32(); M1mmr = input.ReadBoolean(); M1type = input.ReadInt32(); M1size = input.ReadInt32(); m1on = input.ReadBoolean(); BL = input.ReadInt32(); BLmmr = input.ReadBoolean(); OldENABL = input.ReadBoolean(); BLsize = input.ReadInt32(); blon = input.ReadBoolean(); PF210 = input.ReadUInt32(); PFReflectionState = input.ReadInt32(); colubk = input.ReadByte(); colupf = input.ReadByte(); colup0 = input.ReadByte(); colup1 = input.ReadByte(); vblankon = input.ReadBoolean(); scoreon = input.ReadBoolean(); pfpriority = input.ReadBoolean(); DumpEnabled = input.ReadBoolean(); DumpDisabledCycle = input.ReadUInt64(); Collisions = (TIACxPairFlags)input.ReadInt32(); WSYNCDelayClocks = input.ReadInt32(); EndOfFrame = input.ReadBoolean(); }
void RenderFromStartClockTo(ulong endClock) { RenderClock: if (StartClock >= endClock) { return; } ++HSync; if (StartClock == StartHMOVEClock) { // turn on HMOVE HMoveLatch = true; HMoveCounter = 0xf; P0mmr = P1mmr = M0mmr = M1mmr = BLmmr = true; } else if (HSync == 0) { // just wrapped around, clear late HBLANK HMoveLatch = false; } // position counters are incremented during the visible portion of the scanline if (HSync >= 68 + (HMoveLatch ? 8 : 0)) { ++P0; ++P1; ++M0; ++M1; ++BL; } // HMOVE compare, once every 1/4 CLK when on if (HMoveCounter >= 0 && (HSync & 3) == 0) { if (((HMoveCounter ^ RegW[HMP0]) & 0xf) == 0xf) { P0mmr = false; } if (((HMoveCounter ^ RegW[HMP1]) & 0xf) == 0xf) { P1mmr = false; } if (((HMoveCounter ^ RegW[HMM0]) & 0xf) == 0xf) { M0mmr = false; } if (((HMoveCounter ^ RegW[HMM1]) & 0xf) == 0xf) { M1mmr = false; } if (((HMoveCounter ^ RegW[HMBL]) & 0xf) == 0xf) { BLmmr = false; } if (HMoveCounter >= 0) { HMoveCounter--; } } // HMOVE increment, once every 1/4 CLK, 2 CLK after first compare when on if (HMoveCounter < 0xf && (HSync & 3) == 2) { if (HSync < 68 + (HMoveLatch ? 8 : 0)) { if (P0mmr) { ++P0; } if (P1mmr) { ++P1; } if (M0mmr) { ++M0; } if (M1mmr) { ++M1; } if (BLmmr) { ++BL; } } } if (HSync == 68 + 76) { PFReflectionState = RegW[CTRLPF] & 0x01; } var fbyte = (byte)0; var fbyte_colupf = colupf; TIACxFlags cxflags = 0; if (vblankon || HSync < 68 + (HMoveLatch ? 8 : 0)) { goto WritePixel; } fbyte = colubk; var colupfon = false; if ((PF210 & TIATables.PFMask[PFReflectionState][HSync - 68]) != 0) { if (scoreon) { fbyte_colupf = (HSync - 68) < 80 ? colup0 : colup1; } colupfon = true; cxflags |= TIACxFlags.PF; } if (blon && BL >= 0 && TIATables.BLMask[BLsize][BL]) { colupfon = true; cxflags |= TIACxFlags.BL; } if (!pfpriority && colupfon) { fbyte = fbyte_colupf; } if (m1on && M1 >= 0 && TIATables.MxMask[M1size][M1type][M1]) { fbyte = colup1; cxflags |= TIACxFlags.M1; } if (P1 >= 0 && (TIATables.PxMask[P1suppress][P1type][P1] & EffGRP1) != 0) { fbyte = colup1; cxflags |= TIACxFlags.P1; } if (m0on && M0 >= 0 && TIATables.MxMask[M0size][M0type][M0]) { fbyte = colup0; cxflags |= TIACxFlags.M0; } if (P0 >= 0 && (TIATables.PxMask[P0suppress][P0type][P0] & EffGRP0) != 0) { fbyte = colup0; cxflags |= TIACxFlags.P0; } if (pfpriority && colupfon) { fbyte = fbyte_colupf; } WritePixel: Collisions |= TIATables.CollisionMask[(int)cxflags]; if (HSync >= 68) { M.FrameBuffer.VideoBuffer[FrameBufferIndex++] = fbyte; if (FrameBufferIndex == M.FrameBuffer.VideoBufferByteLength) { FrameBufferIndex = 0; } if (HSync == 227) { ScanLine++; } } if (P0 >= 156) { P0suppress = 0; } if (P1 >= 156) { P1suppress = 0; } // denote this CLK has been completed by incrementing to the next StartClock++; goto RenderClock; }
public TIA(DeserializationContext input, MachineBase m) : this() { if (input == null) { throw new ArgumentNullException("input"); } if (m == null) { throw new ArgumentNullException("m"); } M = m; TIASound = input.ReadTIASound(M, CPU_TICKS_PER_AUDIO_SAMPLE); input.CheckVersion(2); RegW = input.ReadExpectedBytes(0x40); HSync = input.ReadInt32(); HMoveCounter = input.ReadInt32(); ScanLine = input.ReadInt32(); FrameBufferIndex = input.ReadInt32(); //FrameBufferElement = input.ReadBufferElement(); StartHMOVEClock = input.ReadUInt64(); HMoveLatch = input.ReadBoolean(); StartClock = input.ReadUInt64(); P0 = input.ReadInt32(); P0mmr = input.ReadBoolean(); EffGRP0 = input.ReadByte(); OldGRP0 = input.ReadByte(); P0type = input.ReadInt32(); P0suppress = input.ReadInt32(); P1 = input.ReadInt32(); P1mmr = input.ReadBoolean(); EffGRP1 = input.ReadByte(); OldGRP1 = input.ReadByte(); P1type = input.ReadInt32(); P1suppress = input.ReadInt32(); M0 = input.ReadInt32(); M0mmr = input.ReadBoolean(); M0type = input.ReadInt32(); M0size = input.ReadInt32(); m0on = input.ReadBoolean(); M1 = input.ReadInt32(); M1mmr = input.ReadBoolean(); M1type = input.ReadInt32(); M1size = input.ReadInt32(); m1on = input.ReadBoolean(); BL = input.ReadInt32(); BLmmr = input.ReadBoolean(); OldENABL = input.ReadBoolean(); BLsize = input.ReadInt32(); blon = input.ReadBoolean(); PF210 = input.ReadUInt32(); PFReflectionState = input.ReadInt32(); colubk = input.ReadByte(); colupf = input.ReadByte(); colup0 = input.ReadByte(); colup1 = input.ReadByte(); vblankon = input.ReadBoolean(); scoreon = input.ReadBoolean(); pfpriority = input.ReadBoolean(); DumpEnabled = input.ReadBoolean(); DumpDisabledCycle = input.ReadUInt64(); Collisions = (TIACxPairFlags)input.ReadInt32(); WSYNCDelayClocks = input.ReadInt32(); EndOfFrame = input.ReadBoolean(); }
void opCXCLR(ushort addr, byte data) { Collisions = 0; }
static TIACxPairFlags[] BuildCollisionMaskTable() { var tabl = new TIACxPairFlags[64]; for (var i = 0; i < 64; i++) { tabl[i] = 0; if (tstCx(i, TIACxFlags.M0, TIACxFlags.P1)) { tabl[i] |= TIACxPairFlags.M0P1; } if (tstCx(i, TIACxFlags.M0, TIACxFlags.P0)) { tabl[i] |= TIACxPairFlags.M0P0; } if (tstCx(i, TIACxFlags.M1, TIACxFlags.P0)) { tabl[i] |= TIACxPairFlags.M1P0; } if (tstCx(i, TIACxFlags.M1, TIACxFlags.P1)) { tabl[i] |= TIACxPairFlags.M1P1; } if (tstCx(i, TIACxFlags.P0, TIACxFlags.PF)) { tabl[i] |= TIACxPairFlags.P0PF; } if (tstCx(i, TIACxFlags.P0, TIACxFlags.BL)) { tabl[i] |= TIACxPairFlags.P0BL; } if (tstCx(i, TIACxFlags.P1, TIACxFlags.PF)) { tabl[i] |= TIACxPairFlags.P1PF; } if (tstCx(i, TIACxFlags.P1, TIACxFlags.BL)) { tabl[i] |= TIACxPairFlags.P1BL; } if (tstCx(i, TIACxFlags.M0, TIACxFlags.PF)) { tabl[i] |= TIACxPairFlags.M0PF; } if (tstCx(i, TIACxFlags.M0, TIACxFlags.BL)) { tabl[i] |= TIACxPairFlags.M0BL; } if (tstCx(i, TIACxFlags.M1, TIACxFlags.PF)) { tabl[i] |= TIACxPairFlags.M1PF; } if (tstCx(i, TIACxFlags.M1, TIACxFlags.BL)) { tabl[i] |= TIACxPairFlags.M1BL; } if (tstCx(i, TIACxFlags.BL, TIACxFlags.PF)) { tabl[i] |= TIACxPairFlags.BLPF; } if (tstCx(i, TIACxFlags.P0, TIACxFlags.P1)) { tabl[i] |= TIACxPairFlags.P0P1; } if (tstCx(i, TIACxFlags.M0, TIACxFlags.M1)) { tabl[i] |= TIACxPairFlags.M0M1; } } return(tabl); }
static TIACxPairFlags[] BuildCollisionMaskTable() { var tabl = new TIACxPairFlags[64]; for (var i = 0; i < 64; i++) { tabl[i] = 0; if (tstCx(i, TIACxFlags.M0, TIACxFlags.P1)) { tabl[i] |= TIACxPairFlags.M0P1; } if (tstCx(i, TIACxFlags.M0, TIACxFlags.P0)) { tabl[i] |= TIACxPairFlags.M0P0; } if (tstCx(i, TIACxFlags.M1, TIACxFlags.P0)) { tabl[i] |= TIACxPairFlags.M1P0; } if (tstCx(i, TIACxFlags.M1, TIACxFlags.P1)) { tabl[i] |= TIACxPairFlags.M1P1; } if (tstCx(i, TIACxFlags.P0, TIACxFlags.PF)) { tabl[i] |= TIACxPairFlags.P0PF; } if (tstCx(i, TIACxFlags.P0, TIACxFlags.BL)) { tabl[i] |= TIACxPairFlags.P0BL; } if (tstCx(i, TIACxFlags.P1, TIACxFlags.PF)) { tabl[i] |= TIACxPairFlags.P1PF; } if (tstCx(i, TIACxFlags.P1, TIACxFlags.BL)) { tabl[i] |= TIACxPairFlags.P1BL; } if (tstCx(i, TIACxFlags.M0, TIACxFlags.PF)) { tabl[i] |= TIACxPairFlags.M0PF; } if (tstCx(i, TIACxFlags.M0, TIACxFlags.BL)) { tabl[i] |= TIACxPairFlags.M0BL; } if (tstCx(i, TIACxFlags.M1, TIACxFlags.PF)) { tabl[i] |= TIACxPairFlags.M1PF; } if (tstCx(i, TIACxFlags.M1, TIACxFlags.BL)) { tabl[i] |= TIACxPairFlags.M1BL; } if (tstCx(i, TIACxFlags.BL, TIACxFlags.PF)) { tabl[i] |= TIACxPairFlags.BLPF; } if (tstCx(i, TIACxFlags.P0, TIACxFlags.P1)) { tabl[i] |= TIACxPairFlags.P0P1; } if (tstCx(i, TIACxFlags.M0, TIACxFlags.M1)) { tabl[i] |= TIACxPairFlags.M0M1; } } return tabl; }