[NES] pcm sound channel
This commit is contained in:
parent
f1b460f6f1
commit
8d9dfd5469
|
@ -25,8 +25,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
public APU(NES nes)
|
public APU(NES nes)
|
||||||
{
|
{
|
||||||
this.nes = nes;
|
this.nes = nes;
|
||||||
|
dmc = new DMCUnit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int[] DMC_RATE_NTSC = { 428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 84, 72, 54 };
|
||||||
static int[] LENGTH_TABLE = { 10, 254, 20, 2, 40, 4, 80, 6, 160, 8, 60, 10, 14, 12, 26, 14, 12, 16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30 };
|
static int[] LENGTH_TABLE = { 10, 254, 20, 2, 40, 4, 80, 6, 160, 8, 60, 10, 14, 12, 26, 14, 12, 16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30 };
|
||||||
static byte[,] PULSE_DUTY = {
|
static byte[,] PULSE_DUTY = {
|
||||||
{0,1,0,0,0,0,0,0}, //(12.5%)
|
{0,1,0,0,0,0,0,0}, //(12.5%)
|
||||||
|
@ -386,7 +388,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
//misc..
|
//misc..
|
||||||
int lenctr_en;
|
int lenctr_en;
|
||||||
int linear_counter, timer, timer_cnt_reload;
|
int linear_counter, timer, timer_cnt_reload;
|
||||||
int seq;
|
int seq = 15;
|
||||||
public int sample;
|
public int sample;
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
|
@ -416,6 +418,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
public void WriteReg(int addr, byte val)
|
public void WriteReg(int addr, byte val)
|
||||||
{
|
{
|
||||||
|
//Console.WriteLine("tri writes addr={0}, val={1:x2}", addr, val);
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -447,7 +450,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
//except when linear counter or
|
//except when linear counter or
|
||||||
//length counter is 0
|
//length counter is 0
|
||||||
|
|
||||||
bool en = len_cnt != 0 && linear_counter != 0;
|
bool en = len_cnt != 0 && linear_counter != 0 || (seq != 16 && seq != 15);
|
||||||
|
|
||||||
//length counter and linear counter
|
//length counter and linear counter
|
||||||
//is clocked in frame counter.
|
//is clocked in frame counter.
|
||||||
|
@ -460,10 +463,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
timer = timer_cnt_reload;
|
timer = timer_cnt_reload;
|
||||||
}
|
}
|
||||||
//if(CFG_DECLICK)
|
//if(CFG_DECLICK)
|
||||||
// sample = TRIANGLE_TABLE[(seq+8)&0x1F];
|
//sample = TRIANGLE_TABLE[(seq+8)&0x1F];
|
||||||
//else
|
//else
|
||||||
sample = TRIANGLE_TABLE[seq];
|
sample = TRIANGLE_TABLE[seq];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -485,9 +489,192 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
{
|
{
|
||||||
linear_counter--;
|
linear_counter--;
|
||||||
}
|
}
|
||||||
if (control_flag == 0)
|
|
||||||
|
//declick when the sound begins
|
||||||
|
//if (halt_flag == 1 && control_flag == 0)
|
||||||
|
//{
|
||||||
|
// seq = 16;
|
||||||
|
// Console.WriteLine("declicked triangle");
|
||||||
|
//}
|
||||||
|
|
||||||
|
////declick on end of sound
|
||||||
|
//bool en = len_cnt != 0 && linear_counter != 0;
|
||||||
|
//if (!en)
|
||||||
|
// if (sample < 0) sample++; else if (sample > 0) sample--;
|
||||||
|
|
||||||
|
halt_flag = control_flag;
|
||||||
|
}
|
||||||
|
} //class TriangleUnit
|
||||||
|
|
||||||
|
class DMCUnit
|
||||||
|
{
|
||||||
|
APU apu;
|
||||||
|
public DMCUnit(APU apu)
|
||||||
|
{
|
||||||
|
this.apu = apu;
|
||||||
|
out_silence = true;
|
||||||
|
timer_reload = DMC_RATE_NTSC[0];
|
||||||
|
sample_buffer_filled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool irq_enabled;
|
||||||
|
bool loop_flag;
|
||||||
|
int timer_reload;
|
||||||
|
|
||||||
|
int timer;
|
||||||
|
int user_address, user_length;
|
||||||
|
int sample_address, sample_length, sample_buffer;
|
||||||
|
bool sample_buffer_filled;
|
||||||
|
|
||||||
|
int out_shift, out_bits_remaining, out_deltacounter;
|
||||||
|
bool out_silence;
|
||||||
|
|
||||||
|
public int sample;
|
||||||
|
|
||||||
|
public void SyncState(Serializer ser)
|
||||||
|
{
|
||||||
|
ser.Sync("irq_enabled", ref irq_enabled);
|
||||||
|
ser.Sync("loop_flag", ref loop_flag);
|
||||||
|
ser.Sync("timer_reload", ref timer_reload);
|
||||||
|
|
||||||
|
ser.Sync("timer", ref timer);
|
||||||
|
ser.Sync("user_address", ref user_address);
|
||||||
|
ser.Sync("user_length", ref user_length);
|
||||||
|
|
||||||
|
ser.Sync("sample_address", ref sample_address);
|
||||||
|
ser.Sync("sample_length", ref sample_length);
|
||||||
|
ser.Sync("sample_buffer", ref sample_buffer);
|
||||||
|
ser.Sync("sample_buffer_filled", ref sample_buffer_filled);
|
||||||
|
|
||||||
|
ser.Sync("out_shift", ref out_shift);
|
||||||
|
ser.Sync("out_bits_remaining", ref out_bits_remaining);
|
||||||
|
ser.Sync("out_deltacounter", ref out_deltacounter);
|
||||||
|
ser.Sync("out_silence", ref out_silence);
|
||||||
|
|
||||||
|
ser.Sync("sample", ref sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
if (timer > 0) timer--;
|
||||||
|
if (timer == 0)
|
||||||
{
|
{
|
||||||
halt_flag = 0;
|
timer = timer_reload;
|
||||||
|
Clock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncSample()
|
||||||
|
{
|
||||||
|
sample = (out_deltacounter - 64) / 4;
|
||||||
|
//Console.WriteLine("dmc sample: {0}", sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clock()
|
||||||
|
{
|
||||||
|
if (!out_silence)
|
||||||
|
{
|
||||||
|
//apply current sample bit to delta counter
|
||||||
|
if (out_shift.Bit(0))
|
||||||
|
{
|
||||||
|
if (out_deltacounter < 126)
|
||||||
|
out_deltacounter += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (out_deltacounter > 1)
|
||||||
|
out_deltacounter -= 2;
|
||||||
|
}
|
||||||
|
SyncSample();
|
||||||
|
out_shift >>= 1;
|
||||||
|
//apu.nes.LogLine("dmc out sample: {0}", out_deltacounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_bits_remaining==0)
|
||||||
|
{
|
||||||
|
out_bits_remaining = 7;
|
||||||
|
if (sample_length > 0)
|
||||||
|
{
|
||||||
|
if (sample_buffer_filled)
|
||||||
|
{
|
||||||
|
out_silence = false;
|
||||||
|
out_shift = sample_buffer;
|
||||||
|
sample_buffer_filled = false;
|
||||||
|
//TODO - cpu/apu DMC reads need to be emulated better!
|
||||||
|
}
|
||||||
|
Fetch();
|
||||||
|
}
|
||||||
|
else out_silence = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out_bits_remaining--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_lenctr_en(bool en)
|
||||||
|
{
|
||||||
|
if (!en)
|
||||||
|
//disable playback
|
||||||
|
sample_length = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//only start playback if sample length is 0 (playback is stopped
|
||||||
|
if (sample_length == 0)
|
||||||
|
{
|
||||||
|
sample_address = user_address;
|
||||||
|
sample_length = user_length;
|
||||||
|
out_deltacounter = 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//irq is acknowledged or sure to be clear, in either case
|
||||||
|
apu.dmc_irq = false;
|
||||||
|
apu.SyncIRQ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsLenCntNonZero()
|
||||||
|
{
|
||||||
|
return sample_length != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteReg(int addr, byte val)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("DMC writes addr={0}, val={1:x2}", addr, val);
|
||||||
|
switch (addr)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
irq_enabled = val.Bit(7);
|
||||||
|
loop_flag = val.Bit(6);
|
||||||
|
timer_reload = DMC_RATE_NTSC[val & 0xF];
|
||||||
|
if (!irq_enabled) apu.dmc_irq = false;
|
||||||
|
apu.SyncIRQ();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
out_deltacounter = val & 0x7F;
|
||||||
|
//apu.nes.LogLine("~~ out_deltacounter set to {0}", out_deltacounter);
|
||||||
|
SyncSample();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
user_address = 0xC000 | (val << 6);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
user_length = (val << 4) + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fetch()
|
||||||
|
{
|
||||||
|
sample_buffer = apu.nes.ReadMemory((ushort)sample_address);
|
||||||
|
sample_buffer_filled = true;
|
||||||
|
sample_address = (ushort)(sample_address + 1);
|
||||||
|
sample_length--;
|
||||||
|
if (sample_length == 0)
|
||||||
|
{
|
||||||
|
if (loop_flag)
|
||||||
|
{
|
||||||
|
sample_address = user_address;
|
||||||
|
sample_length = user_length;
|
||||||
|
}
|
||||||
|
else if (irq_enabled) apu.dmc_irq = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,15 +685,26 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
ser.Sync("sequencer_step", ref sequencer_step);
|
ser.Sync("sequencer_step", ref sequencer_step);
|
||||||
ser.Sync("sequencer_mode", ref sequencer_mode);
|
ser.Sync("sequencer_mode", ref sequencer_mode);
|
||||||
ser.Sync("sequencer_irq_inhibit", ref sequencer_irq_inhibit);
|
ser.Sync("sequencer_irq_inhibit", ref sequencer_irq_inhibit);
|
||||||
|
ser.Sync("sequencer_irq", ref sequencer_irq);
|
||||||
|
ser.Sync("dmc_irq", ref dmc_irq);
|
||||||
pulse[0].SyncState(ser);
|
pulse[0].SyncState(ser);
|
||||||
pulse[1].SyncState(ser);
|
pulse[1].SyncState(ser);
|
||||||
triangle.SyncState(ser);
|
triangle.SyncState(ser);
|
||||||
noise.SyncState(ser);
|
noise.SyncState(ser);
|
||||||
|
dmc.SyncState(ser);
|
||||||
}
|
}
|
||||||
|
|
||||||
PulseUnit[] pulse = { new PulseUnit(0), new PulseUnit(1) };
|
PulseUnit[] pulse = { new PulseUnit(0), new PulseUnit(1) };
|
||||||
TriangleUnit triangle = new TriangleUnit();
|
TriangleUnit triangle = new TriangleUnit();
|
||||||
NoiseUnit noise = new NoiseUnit();
|
NoiseUnit noise = new NoiseUnit();
|
||||||
|
DMCUnit dmc;
|
||||||
|
bool sequencer_irq;
|
||||||
|
public bool dmc_irq;
|
||||||
|
|
||||||
|
public void RunDMCFetch()
|
||||||
|
{
|
||||||
|
dmc.Fetch();
|
||||||
|
}
|
||||||
|
|
||||||
int sequencer_counter, sequencer_step, sequencer_mode, sequencer_irq_inhibit;
|
int sequencer_counter, sequencer_step, sequencer_mode, sequencer_irq_inhibit;
|
||||||
void sequencer_reset()
|
void sequencer_reset()
|
||||||
|
@ -529,8 +727,16 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
sequencer_check();
|
sequencer_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SyncIRQ()
|
||||||
|
{
|
||||||
|
nes.irq_apu = sequencer_irq | dmc_irq;
|
||||||
|
//if (nes.irq_apu) Console.WriteLine("apu irq");
|
||||||
|
nes.sync_irq();
|
||||||
|
}
|
||||||
|
|
||||||
void sequencer_check()
|
void sequencer_check()
|
||||||
{
|
{
|
||||||
|
//Console.WriteLine("sequencer mode {0} step {1}", sequencer_mode, sequencer_step);
|
||||||
switch (sequencer_mode)
|
switch (sequencer_mode)
|
||||||
{
|
{
|
||||||
case 0: //4-step
|
case 0: //4-step
|
||||||
|
@ -549,7 +755,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
{
|
{
|
||||||
if (sequencer_irq_inhibit == 0)
|
if (sequencer_irq_inhibit == 0)
|
||||||
{
|
{
|
||||||
nes.irq_apu = true;
|
sequencer_irq = true;
|
||||||
|
SyncIRQ();
|
||||||
}
|
}
|
||||||
sequencer_step = 0;
|
sequencer_step = 0;
|
||||||
}
|
}
|
||||||
|
@ -560,7 +767,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
pulse[0].clock_env();
|
pulse[0].clock_env();
|
||||||
pulse[1].clock_env();
|
pulse[1].clock_env();
|
||||||
triangle.clock_linear_counter();
|
triangle.clock_linear_counter();
|
||||||
noise.clock_env();
|
//noise.clock_env();
|
||||||
}
|
}
|
||||||
if (sequencer_step == 1 || sequencer_step == 3)
|
if (sequencer_step == 1 || sequencer_step == 3)
|
||||||
{
|
{
|
||||||
|
@ -578,6 +785,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
|
|
||||||
public void WriteReg(int addr, byte val)
|
public void WriteReg(int addr, byte val)
|
||||||
{
|
{
|
||||||
|
//Console.WriteLine("apu writereg {0:x4}", addr);
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x4000: case 0x4001: case 0x4002: case 0x4003:
|
case 0x4000: case 0x4001: case 0x4002: case 0x4003:
|
||||||
|
@ -592,17 +800,24 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
case 0x400C: case 0x400D: case 0x400E: case 0x400F:
|
case 0x400C: case 0x400D: case 0x400E: case 0x400F:
|
||||||
noise.WriteReg(addr - 0x400C, val);
|
noise.WriteReg(addr - 0x400C, val);
|
||||||
break;
|
break;
|
||||||
|
case 0x4010: case 0x4011: case 0x4012: case 0x4013:
|
||||||
|
dmc.WriteReg(addr - 0x4010, val);
|
||||||
|
break;
|
||||||
case 0x4015:
|
case 0x4015:
|
||||||
pulse[0].set_lenctr_en(val & 1);
|
pulse[0].set_lenctr_en(val & 1);
|
||||||
pulse[1].set_lenctr_en((val >> 1) & 1);
|
pulse[1].set_lenctr_en((val >> 1) & 1);
|
||||||
triangle.set_lenctr_en((val >> 2) & 1);
|
triangle.set_lenctr_en((val >> 2) & 1);
|
||||||
noise.set_lenctr_en((val >> 3) & 1);
|
noise.set_lenctr_en((val >> 3) & 1);
|
||||||
|
dmc.set_lenctr_en(val.Bit(4));
|
||||||
break;
|
break;
|
||||||
case 0x4017:
|
case 0x4017:
|
||||||
sequencer_mode = (val>>7)&1;
|
sequencer_mode = (val>>7)&1;
|
||||||
sequencer_irq_inhibit = (val >> 6) & 1;
|
sequencer_irq_inhibit = (val >> 6) & 1;
|
||||||
if (sequencer_irq_inhibit == 1)
|
if (sequencer_irq_inhibit == 1)
|
||||||
nes.irq_apu = false;
|
{
|
||||||
|
sequencer_irq = false;
|
||||||
|
SyncIRQ();
|
||||||
|
}
|
||||||
sequencer_reset();
|
sequencer_reset();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -616,17 +831,18 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
{
|
{
|
||||||
//notice a missing bit here. should properly emulate with empty bus
|
//notice a missing bit here. should properly emulate with empty bus
|
||||||
//if an interrupt flag was set at the same moment of the read, it will read back as 1 but it will not be cleared.
|
//if an interrupt flag was set at the same moment of the read, it will read back as 1 but it will not be cleared.
|
||||||
int dmc_irq_flag = 0; //todo
|
int dmc_nonzero = dmc.IsLenCntNonZero() ? 1 : 0;
|
||||||
int dmc_nonzero = 0; //todo
|
|
||||||
int noise_nonzero = noise.IsLenCntNonZero() ? 1 : 0;
|
int noise_nonzero = noise.IsLenCntNonZero() ? 1 : 0;
|
||||||
int tri_nonzero = triangle.IsLenCntNonZero() ? 1 : 0;
|
int tri_nonzero = triangle.IsLenCntNonZero() ? 1 : 0;
|
||||||
int pulse1_nonzero = pulse[1].IsLenCntNonZero() ? 1 : 0;
|
int pulse1_nonzero = pulse[1].IsLenCntNonZero() ? 1 : 0;
|
||||||
int pulse0_nonzero = pulse[0].IsLenCntNonZero() ? 1 : 0;
|
int pulse0_nonzero = pulse[0].IsLenCntNonZero() ? 1 : 0;
|
||||||
int ret = (dmc_irq_flag << 7) | ((nes.irq_apu?1:0) << 6) | (dmc_nonzero << 4) | (noise_nonzero << 3) | (tri_nonzero<<2) | (pulse1_nonzero<<1) | (pulse0_nonzero);
|
int ret = ((dmc_irq?1:0) << 7) | ((sequencer_irq?1:0) << 6) | (dmc_nonzero << 4) | (noise_nonzero << 3) | (tri_nonzero<<2) | (pulse1_nonzero<<1) | (pulse0_nonzero);
|
||||||
nes.irq_apu = false;
|
sequencer_irq = false;
|
||||||
|
SyncIRQ();
|
||||||
return (byte)ret;
|
return (byte)ret;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
//don't return 0xFF here or SMB will break
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -648,12 +864,14 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
pulse[1].Run();
|
pulse[1].Run();
|
||||||
triangle.Run();
|
triangle.Run();
|
||||||
noise.Run();
|
noise.Run();
|
||||||
|
dmc.Run();
|
||||||
|
|
||||||
int mix = 0;
|
int mix = 0;
|
||||||
mix += pulse[0].sample;
|
mix += pulse[0].sample;
|
||||||
mix += pulse[1].sample;
|
mix += pulse[1].sample;
|
||||||
mix += triangle.sample;
|
mix += triangle.sample;
|
||||||
mix += noise.sample;
|
mix += noise.sample>>1;
|
||||||
|
mix += dmc.sample;
|
||||||
|
|
||||||
EmitSample(mix);
|
EmitSample(mix);
|
||||||
|
|
||||||
|
@ -694,7 +912,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
double factional_remainder = (this_samp - last_hwsamp) * (1-ratio);
|
double factional_remainder = (this_samp - last_hwsamp) * (1-ratio);
|
||||||
accumulate += fractional;
|
accumulate += fractional;
|
||||||
|
|
||||||
accumulate *= 540; //32768/(15*4) -- adjust later for other sound channels
|
accumulate *= 436; //32768/(15*4) -- adjust later for other sound channels
|
||||||
int outsamp = (int)(accumulate / kInvMixRate);
|
int outsamp = (int)(accumulate / kInvMixRate);
|
||||||
if (CFG_USE_METASPU)
|
if (CFG_USE_METASPU)
|
||||||
metaspu.buffer.enqueue_sample((short)outsamp, (short)outsamp);
|
metaspu.buffer.enqueue_sample((short)outsamp, (short)outsamp);
|
||||||
|
@ -717,7 +935,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
MyGetSamples(samples);
|
MyGetSamples(samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
//static BinaryWriter bw = new BinaryWriter(File.OpenWrite("d:\\out.raw"));
|
//static BinaryWriter bw = new BinaryWriter(new FileStream("d:\\out.raw",FileMode.Create,FileAccess.Write,FileShare.Read));
|
||||||
void MyGetSamples(short[] samples)
|
void MyGetSamples(short[] samples)
|
||||||
{
|
{
|
||||||
//Console.WriteLine("a: {0} with todo: {1}",squeue.Count,samples.Length/2);
|
//Console.WriteLine("a: {0} with todo: {1}",squeue.Count,samples.Length/2);
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
{
|
{
|
||||||
//configuration
|
//configuration
|
||||||
int prg_bank_mask_32k, chr_bank_mask_8k;
|
int prg_bank_mask_32k, chr_bank_mask_8k;
|
||||||
bool mirror_control_enabled;
|
//bool mirror_control_enabled;
|
||||||
|
|
||||||
//state
|
//state
|
||||||
int chr_bank_8k, prg_bank_32k;
|
int chr_bank_8k, prg_bank_32k;
|
||||||
|
@ -145,8 +145,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
||||||
chr_bank_8k = ((value >> 3) & 7);
|
chr_bank_8k = ((value >> 3) & 7);
|
||||||
prg_bank_32k &= prg_bank_mask_32k;
|
prg_bank_32k &= prg_bank_mask_32k;
|
||||||
prg_bank_32k &= chr_bank_mask_8k;
|
prg_bank_32k &= chr_bank_mask_8k;
|
||||||
if (mirror_control_enabled)
|
//if (mirror_control_enabled) SetMirrorType(value.Bit(7) ? EMirrorType.Vertical : EMirrorType.Horizontal);
|
||||||
SetMirrorType(value.Bit(7) ? EMirrorType.Vertical : EMirrorType.Horizontal);
|
|
||||||
//NES.LogLine("chr={0:X2}, prg={1:X2}, with val={2:X2}", chr_reg, prg_reg, value);
|
//NES.LogLine("chr={0:X2}, prg={1:X2}, with val={2:X2}", chr_reg, prg_reg, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,12 @@ namespace BizHawk
|
||||||
return (b & (1 << index)) != 0;
|
return (b & (1 << index)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool Bit(this int b, int index)
|
||||||
|
{
|
||||||
|
return (b & (1 << index)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static string GetPrecedingString(this string str, string value)
|
public static string GetPrecedingString(this string str, string value)
|
||||||
{
|
{
|
||||||
int index = str.IndexOf(value);
|
int index = str.IndexOf(value);
|
||||||
|
|
Loading…
Reference in New Issue