public GameboyComponent(IApp app) { this.gamepad_ = app.Input.Controller; this.lcd_ = new Lcd(); this.mmu_ = new Mmu(new MemoryMap(new IoAddresses(new SerialBus())), new Registers()); var opcodes = new Opcodes(this.mmu_); this.cpu_ = new Cpu(this.lcd_, this.mmu_, opcodes); this.cpu_.OnEnterVblank += () => { if (!this.pboCacheDirty_) { return; } this.pbo_.SetAllPixels(this.lcd_.PixelData); this.pboCacheDirty_ = false; }; this.apu_ = new Apu(); app.Audio.Factory.NewAudioStreamSource(this.apu_.BufferSubject, 2, 1, Apu.FREQUENCY, 10, Apu.FREQUENCY); var outputPath = "R:/Documents/CSharpWorkspace/FinCSharp/FinCSharpTests/tst/emulation/gb/blargg/output.txt"; this.writer_ = new StreamWriter(outputPath); this.pbo_ = app.Graphics.Textures.Create(201, 144); }
private void UpdateSquareWave_(Channel channel, int total_frames) { if (channel.status) { var square = channel.square_wave; while (total_frames > 0) { int frames = (int)(square.ticks / APU_TICKS); byte sample = Apu.CHANNELX_SAMPLE(channel, square.sample); if (frames <= total_frames) { square.ticks = square.period; square.position = (byte)((square.position + 1) % DUTY_CYCLE_COUNT); square.sample = Apu.GetDuty(square.duty, square.position); } else { frames = total_frames; square.ticks -= (uint)frames * APU_TICKS; } channel.accumulator += sample * (uint)frames; total_frames -= frames; } } }
private void Update_(int cyclesThisIteration) { while (cyclesThisIteration > 0) { var next_seq_ticks = Apu.NextModulo_(this.syncTicks_, FRAME_SEQUENCER_TICKS); if (next_seq_ticks == FRAME_SEQUENCER_TICKS) { this.frame_ = (byte)((this.frame_ + 1) % FRAME_SEQUENCER_COUNT); var updateSweep = this.frame_ == 2 || this.frame_ == 6; var updateLengths = updateSweep || this.frame_ == 0 || this.frame_ == 4; var updateEnvelopes = updateLengths || this.frame_ == 7; if (updateSweep) { this.UpdateSweep_(); } if (updateLengths) { this.UpdateLengths_(); } if (updateEnvelopes) { this.UpdateEnvelopes_(); } } var ticks = Math.Min(next_seq_ticks, cyclesThisIteration); this.UpdateChannels_(ticks / APU_TICKS); cyclesThisIteration -= ticks; } }
public void UpdateNoise_(int total_frames) { var channel4 = this.Channel4; if (channel4.status) { var noise = this.noise; while (total_frames > 0) { int frames = (int)(noise.ticks / APU_TICKS); byte sample = Apu.CHANNELX_SAMPLE(channel4, noise.sample); if (noise.clock_shift <= NOISE_MAX_CLOCK_SHIFT) { if (frames <= total_frames) { ushort bit = (ushort)((noise.lfsr ^ (noise.lfsr >> 1)) & 1); if (noise.lfsr_width == LfsrWidth.LFSR_WIDTH_7) { noise.lfsr = (ushort)(((noise.lfsr >> 1) & ~0x40) | (bit << 6)); } else { noise.lfsr = (ushort)(((noise.lfsr >> 1) & ~0x4000) | (bit << 14)); } noise.sample = (byte)(~noise.lfsr & 1); noise.ticks = noise.period; } else { frames = total_frames; noise.ticks -= (uint)frames * APU_TICKS; } } else { frames = total_frames; } channel4.accumulator += sample * (uint)frames; total_frames = (int)(total_frames - frames); } } }