public void FrameAdvance(bool render, bool rendersound) { _lagged = true; DriveLightOn = false; Frame++; CheckSpriteLimit(); PSG.BeginFrame(Cpu.TotalExecutedCycles); Cpu.Debug = Tracer.Enabled; if (SuperGrafx) { VPC.ExecFrame(render); } else { VDC1.ExecFrame(render); } PSG.EndFrame(Cpu.TotalExecutedCycles); if (_lagged) { _lagCount++; _isLag = true; } else { _isLag = false; } }
private void WritePort(ushort port, byte value) { port &= 0xFF; if (port >= 0xA0 && port <= 0xBF) { if ((port & 1) == 0) { VDP.WriteVdpData(value); } else { VDP.WriteVdpControl(value); } return; } if (port >= 0x80 && port <= 0x9F) { InputPortSelection = InputPortMode.Right; return; } if (port >= 0xC0 && port <= 0xDF) { InputPortSelection = InputPortMode.Left; return; } if (port >= 0xE0) { PSG.WritePsgData(value, Cpu.TotalExecutedCycles); return; } }
private void SyncState(Serializer ser) { byte[] core = null; if (ser.IsWriter) { var ms = new MemoryStream(); ms.Close(); core = ms.ToArray(); } _cpu.SyncState(ser); ser.BeginSection("Coleco"); _vdp.SyncState(ser); PSG.SyncState(ser); ser.Sync("RAM", ref _ram, false); ser.Sync("Frame", ref _frame); ser.Sync("LagCount", ref _lagCount); ser.Sync("IsLag", ref _isLag); ser.EndSection(); if (ser.IsReader) { SyncAllByteArrayDomains(); } }
void WriteMemorySGX(int addr, byte value) { if (addr >= 0x1F0000 && addr < 0x1F8000) // write RAM. Ram[addr & 0x7FFF] = value; else if (addr >= 0x1FE000) // hardware page. { if (addr < 0x1FE400) { addr &= 0x1F; if (addr <= 0x07) VDC1.WriteVDC(addr, value); else if (addr <= 0x0F) VPC.WriteVPC(addr, value); else if (addr <= 0x17) VDC2.WriteVDC(addr, value); } else if (addr < 0x1FE800) { Cpu.PendingCycles--; VCE.WriteVCE(addr, value); } else if (addr < 0x1FEC00) { IOBuffer = value; PSG.WritePSG((byte)addr, value, Cpu.TotalExecutedCycles); } else if (addr == 0x1FEC00) { IOBuffer = value; Cpu.WriteTimer(value); } else if (addr == 0x1FEC01) { IOBuffer = value; Cpu.WriteTimerEnable(value); } else if (addr >= 0x1FF000 && addr < 0x1FF400) { IOBuffer = value; WriteInput(value); } else if (addr == 0x1FF402) { IOBuffer = value; Cpu.WriteIrqControl(value); } else if (addr == 0x1FF403) { IOBuffer = value; Cpu.WriteIrqStatus(); } else Log.Error("MEM", "unhandled hardware write [{0:X6}] : {1:X2}", addr, value); } else Log.Error("MEM", "UNHANDLED WRITE: {0:X6}:{1:X2}", addr, value); }
public void FrameAdvance(IController controller, bool render, bool renderSound) { _controller = controller; _cpu.Debug = _tracer.Enabled; _frame++; _isLag = true; PSG.BeginFrame(_cpu.TotalExecutedCycles); if (_cpu.Debug && _cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first { _cpu.Logger = (s) => _tracer.Put(s); } byte tempRet1 = ControllerDeck.ReadPort1(controller, true, true); byte tempRet2 = ControllerDeck.ReadPort2(controller, true, true); bool intPending = (!tempRet1.Bit(4)) | (!tempRet2.Bit(4)); _vdp.ExecuteFrame(intPending); PSG.EndFrame(_cpu.TotalExecutedCycles); if (_isLag) { _lagCount++; } }
public void FrameAdvance(bool render, bool renderSound) { Cpu.Debug = Tracer.Enabled; Frame++; _isLag = true; PSG.BeginFrame(Cpu.TotalExecutedCycles); if (Cpu.Debug && Cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first { Cpu.Logger = (s) => Tracer.Put(s); } byte temp_ret1 = ControllerDeck.ReadPort1(Controller, true, true); byte temp_ret2 = ControllerDeck.ReadPort2(Controller, true, true); bool Int_pending = (!temp_ret1.Bit(4)) | (!temp_ret2.Bit(4)); VDP.ExecuteFrame(Int_pending); PSG.EndFrame(Cpu.TotalExecutedCycles); if (_isLag) { _lagCount++; } }
/// <summary> /// Writes to Port C /// </summary> private void OUTPortC(int data) { // latch the data Regs[PORT_C] = (byte)data; if (DirPortCL == PortDirection.Output) { // lower Port C bits OUT // keyboard line update Keyboard.CurrentLine = Regs[PORT_C] & 0x0f; } if (DirPortCU == PortDirection.Output) { // upper Port C bits OUT // write to PSG using latched data PSG.SetFunction(data); PSG.PortWrite(Regs[PORT_A]); // cassete write data //not implemeted // cas motor control Tape.TapeMotor = Regs[PORT_C].Bit(4); } }
public bool FrameAdvance(IController controller, bool render, bool renderSound) { _controller = controller; _lagged = true; DriveLightOn = false; CheckSpriteLimit(); PSG.BeginFrame(Cpu.TotalExecutedCycles); Cpu.Debug = Tracer.IsEnabled(); if (SuperGrafx) { VPC.ExecFrame(render); } else { VDC1.ExecFrame(render); } PSG.EndFrame(Cpu.TotalExecutedCycles); if (_lagged) { _lagCount++; _isLag = true; } else { _isLag = false; } Frame++; return(true); }
public void PSG_reset(PSG psg) { int i; psg.base_count = 0; for (i = 0; i < 3; i++) { psg.cout[i] = 0; psg.count[i] = 0x1000; psg.freq[i] = 0; psg.edge[i] = 0; psg.volume[i] = 0; } psg.mask = 0; for (i = 0; i < 16; i++) { psg.reg[i] = 0; } psg.adr = 0; psg.noise_seed = 0xffff; psg.noise_count = 0x40; psg.noise_freq = 0; psg.env_volume = 0; psg.env_ptr = 0; psg.env_freq = 0; psg.env_count = 0; psg.env_pause = 1; psg._out = 0; }
private void SyncState(Serializer ser) { byte[] core = null; if (ser.IsWriter) { var ms = new MemoryStream(); ms.Close(); core = ms.ToArray(); } Cpu.SyncState(ser); ser.BeginSection("SMS"); Vdp.SyncState(ser); PSG.SyncState(ser); ser.Sync("RAM", ref SystemRam, false); ser.Sync("RomBank0", ref RomBank0); ser.Sync("RomBank1", ref RomBank1); ser.Sync("RomBank2", ref RomBank2); ser.Sync("RomBank3", ref RomBank3); ser.Sync("Port01", ref Port01); ser.Sync("Port02", ref Port02); ser.Sync("Port3E", ref Port3E); ser.Sync("Port3F", ref Port3F); ser.Sync("Paddle1High", ref Paddle1High); ser.Sync("Paddle2High", ref Paddle2High); ser.Sync("LatchLightPhaser", ref LatchLightPhaser); if (SaveRAM != null) { ser.Sync("SaveRAM", ref SaveRAM, false); ser.Sync("SaveRamBank", ref SaveRamBank); } if (ExtRam != null) { ser.Sync("ExtRAM", ref ExtRam, true); } if (HasYM2413) { YM2413.SyncState(ser); } if (EEPROM != null) { EEPROM.SyncState(ser); } ser.Sync("Frame", ref _frame); ser.Sync("LagCount", ref _lagCount); ser.Sync("IsLag", ref _isLag); ser.EndSection(); if (ser.IsReader) { SyncAllByteArrayDomains(); } }
/// <summary> /// Writes to Port A /// </summary> private void OUTPortA(int data) { // latch the data Regs[PORT_A] = (byte)data; if (DirPortA == PortDirection.Output) { // PSG write PSG.PortWrite(data); } }
public void PSG_writeIO(PSG psg, UInt32 adr, UInt32 val) { if ((adr & 1) != 0) { PSG_writeReg(psg, psg.adr, val); } else { psg.adr = val & 0x1f; } }
public UInt32 PSG_toggleMask(PSG psg, UInt32 mask) { UInt32 ret = 0; if (psg != null) { ret = psg.mask; psg.mask ^= mask; } return(ret); }
private void SyncState(Serializer ser) { ser.BeginSection("Coleco"); Cpu.SyncState(ser); VDP.SyncState(ser); PSG.SyncState(ser); ser.Sync("RAM", ref Ram, false); ser.Sync("Frame", ref frame); ser.Sync("LagCount", ref _lagCount); ser.Sync("IsLag", ref _isLag); ser.EndSection(); }
public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; _lagged = true; _frame++; PSG.BeginFrame(Cpu.TotalExecutedCycles); if (!IsGameGear) { PSG.StereoPanning = Settings.ForceStereoSeparation ? ForceStereoByte : (byte)0xFF; } if (Tracer.Enabled) { Cpu.TraceCallback = s => Tracer.Put(s); } else { Cpu.TraceCallback = null; } if (IsGameGear_C == false) { Cpu.NonMaskableInterrupt = controller.IsPressed("Pause"); } else if (!IsGameGear && IsGameGear_C) { Cpu.NonMaskableInterrupt = controller.IsPressed("P1 Start"); } if (IsGame3D && Settings.Fix3D) { Vdp.ExecFrame((Frame & 1) == 0); } else { Vdp.ExecFrame(render); } PSG.EndFrame(Cpu.TotalExecutedCycles); if (_lagged) { _lagCount++; _isLag = true; } else { _isLag = false; } return(true); }
/// <summary> /// Writes to the control register /// </summary> /// <param name="data"></param> private void OUTControl(int data) { if (data.Bit(7)) { // update configuration Regs[PORT_CONTROL] = (byte)data; // Writing to PIO Control Register (with Bit7 set), automatically resets PIO Ports A,B,C to 00h each Regs[PORT_A] = 0; Regs[PORT_B] = 0; Regs[PORT_C] = 0; } else { // register is used to set/reset a single bit in Port C bool isSet = data.Bit(0); // get the bit in PortC that we wish to change var bit = (data >> 1) & 7; // modify this bit if (isSet) { Regs[PORT_C] = (byte)(Regs[PORT_C] | (bit * bit)); } else { Regs[PORT_C] = (byte)(Regs[PORT_C] & ~(bit * bit)); } // any other ouput business if (DirPortCL == PortDirection.Output) { // update keyboard line Keyboard.CurrentLine = Regs[PORT_C] & 0x0f; } if (DirPortCU == PortDirection.Output) { // write to PSG using latched data PSG.SetFunction(data); PSG.PortWrite(Regs[PORT_A]); // cassete write data //not implemeted // cas motor control Tape.TapeMotor = Regs[PORT_C].Bit(4); } } }
public void WriteMemoryZ80(ushort address, byte value) { if (address < 0x4000) { //Console.WriteLine("write z80 memory {0:X4}: {1:X2}",address, value); Z80Ram[address & 0x1FFF] = value; return; } if (address >= 0x4000 && address < 0x6000) { //Console.WriteLine(" === Z80 WRITES YM2612 {0:X4}:{1:X2} ===",address, value); YM2612.Write(address & 3, value, SoundCPU.TotalExecutedCycles); return; } if (address < 0x6100) { BankRegion >>= 1; BankRegion |= (value & 1) << 23; BankRegion &= 0x00FF8000; //Console.WriteLine("Bank pointing at {0:X8}",BankRegion); return; } if (address >= 0x7F00 && address < 0x7F20) { switch (address & 0x1F) { case 0x00: case 0x02: VDP.WriteVdpData((ushort)((value << 8) | value)); return; case 0x04: case 0x06: VDP.WriteVdpControl((ushort)((value << 8) | value)); return; case 0x11: case 0x13: case 0x15: case 0x17: PSG.WritePsgData(value, SoundCPU.TotalExecutedCycles); return; } } if (address >= 0x8000) { WriteByte(BankRegion | (address & 0x7FFF), (sbyte)value); return; } Console.WriteLine("UNHANDLED Z80 WRITE {0:X4}:{1:X2}", address, value); }
/// <summary> /// Reads from Port A /// </summary> /// <returns></returns> private int INPortA() { if (DirPortA == PortDirection.Input) { // read from PSG return(PSG.PortRead()); } else { // Port A is set to output // return latched value return(Regs[PORT_A]); } }
private void internal_refresh(PSG psg) { if (psg.quality != 0) { psg.base_incr = 1 << GETA_BITS; psg.realstep = (UInt32)((1 << 31) / psg.rate); psg.psgstep = (UInt32)((1 << 31) / (psg.clk / 16)); psg.psgtime = 0; } else { psg.base_incr = (UInt32)((double)psg.clk * (1 << GETA_BITS) / (16 * psg.rate)); } }
public void PSG_setVolumeMode(PSG psg, Int32 type) { switch (type) { case 1: psg.voltbl = voltbl[EMU2149_VOL_YM2149]; break; case 2: psg.voltbl = voltbl[EMU2149_VOL_AY_3_8910]; break; default: psg.voltbl = voltbl[EMU2149_VOL_DEFAULT]; break; } }
private void SyncState(Serializer ser) { ser.BeginSection("Coleco"); _cpu.SyncState(ser); _vdp.SyncState(ser); PSG.SyncState(ser); ser.Sync("RAM", ref _ram, false); ser.Sync("Frame", ref _frame); ser.Sync("LagCount", ref _lagCount); ser.Sync("IsLag", ref _isLag); ser.EndSection(); if (ser.IsReader) { SyncAllByteArrayDomains(); } }
public PSG PSG_new(UInt32 c, UInt32 r) { PSG psg; psg = new PSG(); if (psg == null) { return(null); } PSG_setVolumeMode(psg, EMU2149_VOL_DEFAULT); psg.clk = c; psg.rate = r != 0 ? r : 44100; PSG_set_quality(psg, 0); return(psg); }
private void SyncState(Serializer ser) { ser.BeginSection("SMS"); Cpu.SyncState(ser); Vdp.SyncState(ser); PSG.SyncState(ser); ser.Sync("RAM", ref SystemRam, false); ser.Sync("RomBank0", ref RomBank0); ser.Sync("RomBank1", ref RomBank1); ser.Sync("RomBank2", ref RomBank2); ser.Sync("RomBank3", ref RomBank3); ser.Sync("Port01", ref Port01); ser.Sync("Port02", ref Port02); ser.Sync("Port3E", ref Port3E); ser.Sync("Port3F", ref Port3F); if (SaveRAM != null) { ser.Sync("SaveRAM", ref SaveRAM, false); ser.Sync("SaveRamBank", ref SaveRamBank); } if (ExtRam != null) { ser.Sync("ExtRAM", ref ExtRam, true); } if (HasYM2413) { YM2413.SyncState(ser); } ser.Sync("Frame", ref frame); ser.Sync("LagCount", ref _lagCount); ser.Sync("IsLag", ref _isLag); ser.EndSection(); if (ser.IsReader) { SyncAllByteArrayDomains(); } }
public Int16 PSG_calc(PSG psg) { if (psg.quality == 0) { return((Int16)(calc(psg) << 4)); } /* Simple rate converter */ while (psg.realstep > psg.psgtime) { psg.psgtime += psg.psgstep; psg._out += calc(psg); psg._out >>= 1; } psg.psgtime = psg.psgtime - psg.realstep; return((Int16)(psg._out << 4)); }
public void FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; _lagged = true; _frame++; PSG.BeginFrame(Cpu.TotalExecutedCycles); Cpu.Debug = Tracer.Enabled; if (!IsGameGear) { PSG.StereoPanning = Settings.ForceStereoSeparation ? ForceStereoByte : (byte)0xFF; } if (Cpu.Debug && Cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first { Cpu.Logger = s => Tracer.Put(s); } if (IsGameGear == false) { Cpu.NonMaskableInterrupt = controller.IsPressed("Pause"); } if (IsGame3D && Settings.Fix3D) { Vdp.ExecFrame((Frame & 1) == 0); } else { Vdp.ExecFrame(render); } PSG.EndFrame(Cpu.TotalExecutedCycles); if (_lagged) { _lagCount++; _isLag = true; } else { _isLag = false; } }
public void FrameAdvance(bool render, bool renderSound) { Cpu.Debug = Tracer.Enabled; Frame++; _isLag = true; PSG.BeginFrame(Cpu.TotalExecutedCycles); if (Cpu.Debug && Cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first { Cpu.Logger = (s) => Tracer.Put(s); } VDP.ExecuteFrame(); PSG.EndFrame(Cpu.TotalExecutedCycles); if (_isLag) { _lagCount++; } }
public void FrameAdvance(IController controller, bool render, bool renderSound) { _controller = controller; // NOTE: Need to research differences between reset and power cycle if (_controller.IsPressed("Power")) { HardReset(); } if (_controller.IsPressed("Reset")) { SoftReset(); } _frame++; _isLag = true; PSG.BeginFrame(_cpu.TotalExecutedCycles); if (_tracer.Enabled) { _cpu.TraceCallback = s => _tracer.Put(s); } else { _cpu.TraceCallback = null; } byte tempRet1 = ControllerDeck.ReadPort1(controller, true, true); byte tempRet2 = ControllerDeck.ReadPort2(controller, true, true); bool intPending = (!tempRet1.Bit(4)) | (!tempRet2.Bit(4)); _vdp.ExecuteFrame(intPending); PSG.EndFrame(_cpu.TotalExecutedCycles); if (_isLag) { _lagCount++; } }
public void FrameAdvance(IController controller, bool render, bool renderSound) { _controller = controller; // NOTE: Need to research differences between reset and power cycle if (_controller.IsPressed("Power")) { HardReset(); } if (_controller.IsPressed("Reset")) { SoftReset(); } _cpu.Debug = _tracer.Enabled; _frame++; _isLag = true; PSG.BeginFrame(_cpu.TotalExecutedCycles); if (_cpu.Debug && _cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first { _cpu.Logger = (s) => _tracer.Put(s); } byte tempRet1 = ControllerDeck.ReadPort1(controller, true, true); byte tempRet2 = ControllerDeck.ReadPort2(controller, true, true); bool intPending = (!tempRet1.Bit(4)) | (!tempRet2.Bit(4)); _vdp.ExecuteFrame(intPending); PSG.EndFrame(_cpu.TotalExecutedCycles); if (_isLag) { _lagCount++; } }
private void SyncState(Serializer ser) { byte[] core = null; if (ser.IsWriter) { var ms = new MemoryStream(); ms.Close(); core = ms.ToArray(); } _cpu.SyncState(ser); ser.BeginSection("Coleco"); _vdp.SyncState(ser); ControllerDeck.SyncState(ser); PSG.SyncState(ser); SGM_sound.SyncState(ser); ser.Sync("UseSGM", ref use_SGM); ser.Sync("is_MC", ref is_MC); ser.Sync("MC_bank", ref MC_bank); ser.Sync("EnableSGMhigh", ref enable_SGM_high); ser.Sync("EnableSGMlow", ref enable_SGM_low); ser.Sync("Port_0x53", ref port_0x53); ser.Sync("Port_0x7F", ref port_0x7F); ser.Sync("RAM", ref _ram, false); ser.Sync("SGM_high_RAM", ref SGM_high_RAM, false); ser.Sync("SGM_low_RAM", ref SGM_low_RAM, false); ser.Sync("Frame", ref _frame); ser.Sync("LagCount", ref _lagCount); ser.Sync("IsLag", ref _isLag); ser.EndSection(); if (ser.IsReader) { SyncAllByteArrayDomains(); } }
public bool FrameAdvance(IController controller, bool render, bool renderSound) { _controller = controller; // NOTE: Need to research differences between reset and power cycle if (_controller.IsPressed("Power")) { HardReset(); } if (_controller.IsPressed("Reset")) { SoftReset(); } _frame++; _isLag = true; if (_tracer.Enabled) { _cpu.TraceCallback = s => _tracer.Put(s); } else { _cpu.TraceCallback = null; } byte tempRet1 = ControllerDeck.ReadPort1(controller, true, false); byte tempRet2 = ControllerDeck.ReadPort2(controller, true, false); bool intPending = false; // the return values represent the controller's current state, but the sampling rate is not high enough // to catch all changes in wheel orientation // so we use the wheel variable and interpolate between frames // first determine how many degrees the wheels changed, and how many regions have been traversed float change1 = (float)(((ControllerDeck.wheel1 - ControllerDeck.temp_wheel1) % 180) / 1.25); float change2 = (float)(((ControllerDeck.wheel2 - ControllerDeck.temp_wheel2) % 180) / 1.25); // special cases if ((ControllerDeck.temp_wheel1 > 270) && (ControllerDeck.wheel1 < 90)) { change1 = (float)((ControllerDeck.wheel1 + (360 - ControllerDeck.temp_wheel1)) / 1.25); } if ((ControllerDeck.wheel1 > 270) && (ControllerDeck.temp_wheel1 < 90)) { change1 = -(float)((ControllerDeck.temp_wheel1 + (360 - ControllerDeck.wheel1)) / 1.25); } if ((ControllerDeck.temp_wheel2 > 270) && (ControllerDeck.wheel2 < 90)) { change2 = (float)((ControllerDeck.wheel2 + (360 - ControllerDeck.temp_wheel2)) / 1.25); } if ((ControllerDeck.wheel2 > 270) && (ControllerDeck.temp_wheel2 < 90)) { change2 = -(float)((ControllerDeck.temp_wheel2 + (360 - ControllerDeck.wheel2)) / 1.25); } int changes1 = change1 > 0 ? (int)Math.Floor(change1) : (int)Math.Ceiling(change1); int changes2 = change2 > 0 ? (int)Math.Floor(change2) : (int)Math.Ceiling(change2); for (int scanLine = 0; scanLine < 262; scanLine++) { _vdp.RenderScanline(scanLine); if (scanLine == 192) { _vdp.InterruptPending = true; if (_vdp.EnableInterrupts) { _cpu.NonMaskableInterrupt = true; } } for (int i = 0; i < 228; i++) { PSG.generate_sound(1); if (use_SGM) { SGM_sound.generate_sound(1); } _cpu.ExecuteOne(); // pick out sound samples from the sound devices twice per scanline int v = PSG.Sample(); if (use_SGM) { v += SGM_sound.Sample(); } if (v != _latchedSample) { _blip.AddDelta((uint)_sampleClock, v - _latchedSample); _latchedSample = v; } _sampleClock++; } // starting from scanline 20, changes to the wheel are added once per scanline (up to 144) if (scanLine > 20) { if (changes1 != 0) { if (changes1 > 0) { ControllerDeck.temp_wheel1 = (float)((ControllerDeck.temp_wheel1 + 1.25) % 360); changes1--; } else { ControllerDeck.temp_wheel1 = (float)((ControllerDeck.temp_wheel1 - 1.25) % 360); changes1++; } } if (changes2 != 0) { if (changes2 > 0) { ControllerDeck.temp_wheel2 = (float)((ControllerDeck.temp_wheel2 + 1.25) % 360); changes2--; } else { ControllerDeck.temp_wheel2 = (float)((ControllerDeck.temp_wheel2 - 1.25) % 360); changes2++; } } } tempRet1 = ControllerDeck.ReadPort1(controller, true, true); tempRet2 = ControllerDeck.ReadPort2(controller, true, true); intPending = (!tempRet1.Bit(4) && temp_1_prev) | (!tempRet2.Bit(4) && temp_2_prev); _cpu.FlagI = false; if (intPending) { _cpu.FlagI = true; intPending = false; } temp_1_prev = tempRet1.Bit(4); temp_2_prev = tempRet2.Bit(4); } ControllerDeck.temp_wheel1 = ControllerDeck.wheel1; ControllerDeck.temp_wheel2 = ControllerDeck.wheel2; if (_isLag) { _lagCount++; } return(true); }