Skip to content

Commit

Permalink
fixes: megadrive audio
Browse files Browse the repository at this point in the history
  • Loading branch information
stelcheck committed Mar 25, 2021
1 parent 37770c0 commit a77dfd7
Show file tree
Hide file tree
Showing 22 changed files with 310 additions and 207 deletions.
2 changes: 1 addition & 1 deletion higan/component/processor/z80/instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ auto Z80::instruction() -> void {

if(code == 0xcb && prefix != Prefix::hl) {
WZ = HL + (int8)operand();
wait(1);
wait(2); // +1 fetch, +1 memory read
//R is not incremented here
instructionCBd(WZ, opcode());
} else if(code == 0xcb) {
Expand Down
8 changes: 7 additions & 1 deletion higan/component/processor/z80/z80.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ auto Z80::power(MOSFET mosfet) -> void {
}

auto Z80::irq(bool maskable, uint16 pc, uint8 extbus) -> bool {
if(maskable && !IFF1) return false;
if((maskable && !IFF1) || EI) return false;
uint cycles;
R.bit(0,6)++;

push(PC);
Expand All @@ -36,12 +37,14 @@ auto Z80::irq(bool maskable, uint16 pc, uint8 extbus) -> bool {
case 0: {
//external data bus ($ff = RST $38)
WZ = extbus;
cycles = extbus|0x38 == 0xFF ? 6 : 7;
break;
}

case 1: {
//constant address
WZ = pc;
cycles = maskable ? 7 : 5;
break;
}

Expand All @@ -50,6 +53,7 @@ auto Z80::irq(bool maskable, uint16 pc, uint8 extbus) -> bool {
uint16 addr = I << 8 | extbus;
WZL = read(addr + 0);
WZH = read(addr + 1);
cycles = 7;
break;
}

Expand All @@ -62,6 +66,8 @@ auto Z80::irq(bool maskable, uint16 pc, uint8 extbus) -> bool {
if(P) PF = 0;
P = 0;
Q = 0;

wait(cycles);
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion higan/fc/apu/apu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ auto APU::main() -> void {
int output = 0;
output += pulseDAC[pulse_output];
output += dmcTriangleNoiseDAC[dmc_output][triangle_output][noise_output];
stream->sample(sclamp<16>(output) / 32768.0);
stream->sample(sclamp<16>(output) / 32768.0f);

tick();
}
Expand Down
45 changes: 28 additions & 17 deletions higan/md/apu/apu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ auto APU::main() -> void {
bus->grant(false);
#endif

if(!state.enabled) {
updateBus();

if(!running()) {
return step(1);
}

Expand Down Expand Up @@ -67,35 +69,44 @@ auto APU::step(uint clocks) -> void {
#endif
}

auto APU::setNMI(bool value) -> void {
auto APU::setNMI(uint1 value) -> void {
state.nmiLine = value;
}

auto APU::setINT(bool value) -> void {
auto APU::setINT(uint1 value) -> void {
state.intLine = value;
}

auto APU::enable(bool value) -> void {
//68K cannot disable the Z80 without bus access
if(!bus->granted() && !value) return;
if(state.enabled && !value) reset();
state.enabled = value;
auto APU::setRES(uint1 value) -> void {
if(!value && arbstate.resetLine) {
power(true);
}
arbstate.resetLine = value;
}

auto APU::power(bool reset) -> void {
Z80::bus = this;
Z80::power();
bus->grant(false);
Thread::create(system.frequency() / 15.0, {&APU::main, this});
if(!reset) ram.allocate(8_KiB);
state = {};
auto APU::setBREQ(uint1 value) -> void {
arbstate.busreqLine = value;
}

auto APU::reset() -> void {
auto APU::updateBus() -> void {
if(!arbstate.resetLine) return; // Z80 bus switch may be blocked by reset
if(arbstate.busreqLine && !arbstate.busreqLatch) {
step(9); // estimated minimum wait time to allow 68K to read back unavailable bus status (Fatal Rewind)
}
arbstate.busreqLatch = arbstate.busreqLine;
}

auto APU::power(bool reset) -> void {
Z80::bus = this;
Z80::power();
bus->grant(false);
ym2612.power(reset);
Thread::create(system.frequency() / 15.0, {&APU::main, this});
if(!reset) {
ram.allocate(8_KiB);
arbstate = {};
}
state = {};
io = {};
}

}
23 changes: 18 additions & 5 deletions higan/md/apu/apu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,20 @@ struct APU : Z80, Z80::Bus, Thread {
auto main() -> void;
auto step(uint clocks) -> void override;

auto enable(bool) -> void;
auto power(bool reset) -> void;
auto reset() -> void;

auto setNMI(bool value) -> void;
auto setINT(bool value) -> void;
auto running() -> bool { return arbstate.resetLine && busStatus(); }

auto setNMI(uint1 value) -> void;
auto setINT(uint1 value) -> void;
auto setRES(uint1 value) -> void;
auto setBREQ(uint1 value) -> void;

auto updateBus() -> void;
auto busStatus() -> uint1 {
// 0->68K, 1->Z80
return (arbstate.resetLine & arbstate.busreqLatch) ^ 1;
}

//bus.cpp
auto read(uint16 address) -> uint8 override;
Expand All @@ -38,8 +46,13 @@ struct APU : Z80, Z80::Bus, Thread {
uint9 bank;
} io;

struct ArbState {
uint1 resetLine;
uint1 busreqLine = 1;
uint1 busreqLatch = 1;
} arbstate;

struct State {
uint1 enabled;
uint1 nmiLine;
uint1 intLine;
} state;
Expand Down
4 changes: 3 additions & 1 deletion higan/md/apu/serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ auto APU::serialize(serializer& s) -> void {

s.integer(io.bank);

s.integer(state.enabled);
s.integer(arbstate.resetLine);
s.integer(arbstate.busreqLine);
s.integer(arbstate.busreqLatch);
s.integer(state.nmiLine);
s.integer(state.intLine);
}
4 changes: 2 additions & 2 deletions higan/md/cpu/bus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ auto CPU::read(uint1 upper, uint1 lower, uint24 address, uint16 data) -> uint16
}

if(address >= 0xa00000 && address <= 0xa0ffff) {
if(!apu.granted()) return data;
if(apu.busStatus()) return data;
address.bit(15) = 0; //a080000-a0ffff mirrors a00000-a07fff
//word reads load the even input byte into both output bytes
auto byte = apu.read(address | !upper); //upper==0 only on odd byte reads
Expand Down Expand Up @@ -79,7 +79,7 @@ auto CPU::write(uint1 upper, uint1 lower, uint24 address, uint16 data) -> void {
}

if(address >= 0xa00000 && address <= 0xa0ffff) {
if(!apu.granted()) return;
if(apu.busStatus()) return;
address.bit(15) = 0; //a08000-a0ffff mirrors a00000-a07fff
//word writes store the upper input byte into the lower output byte
return apu.write(address | !upper, data.byte(upper)); //upper==0 only on odd byte reads
Expand Down
6 changes: 3 additions & 3 deletions higan/md/cpu/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ auto CPU::readIO(uint1 upper, uint1 lower, uint24 address, uint16 data) -> uint1
}

if(address >= 0xa11100 && address <= 0xa111ff) {
data.byte(1) = !apu.granted();
data.bit(8) = apu.busStatus();
return data;
}

Expand Down Expand Up @@ -85,13 +85,13 @@ auto CPU::writeIO(uint1 upper, uint1 lower, uint24 address, uint16 data) -> void

if(address >= 0xa11100 && address <= 0xa111ff) {
if(!upper) return; //unconfirmed
apu.request(data.bit(8));
apu.setBREQ(data.bit(8));
return;
}

if(address >= 0xa11200 && address <= 0xa112ff) {
if(!upper) return; //unconfirmed
apu.enable(data.bit(8));
apu.setRES(data.bit(8));
return;
}

Expand Down
2 changes: 2 additions & 0 deletions higan/md/interface/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ Interface* interface = nullptr;

auto MegaDriveInterface::configure(string name, uint value) -> void {
if(name.match("vdp/optimizeSteps")) {
#if defined(PROFILE_PERFORMANCE)
vdp.optimizeSteps = (bool) value;
#endif
} else if(name.match("vdp/skipframe")) {
vdp.isSkipping = (bool) value;
}
Expand Down
8 changes: 6 additions & 2 deletions higan/md/system/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,17 @@ auto System::power(bool reset) -> void {

random.entropy(Random::Entropy::Low);

if(!reset) {
controllerPort1.power();
controllerPort2.power();
extensionPort.power();
}

cartridge.power();
expansion.power();
cpu.power(reset);
apu.power(reset);
vdp.power(reset);
psg.power(reset);
ym2612.power(reset);
if(MegaCD()) mcd.power(reset);
scheduler.power(cpu);

Expand Down
5 changes: 3 additions & 2 deletions higan/md/vdp-performance/vdp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ auto VDP::load(Node::Object parent, Node::Object from) -> void {

screen = Node::append<Node::Screen>(parent, from, "Screen");
screen->colors(3 * (1 << 9), {&VDP::color, this});
screen->setSize(1280, 480);
screen->setScale(0.25, 0.50);
screen->setSize(640, 480);
screen->setScale(0.50, 0.50);
screen->setAspect(1.0, 1.0);
from = Node::scan(parent = screen, from);

Expand Down Expand Up @@ -240,6 +240,7 @@ auto VDP::power(bool reset) -> void {
for(auto& data : cram.palette) data = 0;

dma.power();
psg.power(reset);

planeA.io = {};
window.io = {};
Expand Down
9 changes: 7 additions & 2 deletions higan/md/vdp/render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ auto VDP::scanline() -> void {

if(state.vcounter == 240) {
#if defined(SCHEDULER_SYNCHRO)
refresh();
hasRendered = true;
// Render early, exit at the top of CPU::main
if (!isSkipping || !skip) {
refresh();
}

skip = !skip;
hasRendered = true;
#else
scheduler.exit(Event::Frame);
#endif
Expand Down
25 changes: 17 additions & 8 deletions higan/md/vdp/vdp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,20 @@ auto VDP::main() -> void {
cpu.lower(CPU::Interrupt::VerticalBlank);
}

if(state.vcounter == screenHeight()) {
if(state.vcounter < screenHeight()) {
counter = 2;
} else if(state.vcounter == screenHeight()) {
if(io.verticalBlankInterruptEnable) {
io.vblankIRQ = true;
cpu.raise(CPU::Interrupt::VerticalBlank);
}
//todo: should only stay high for ~2573/2 clocks
apu.setINT(true);
}

if(state.vcounter < screenHeight()) {
counter = 2;
} else {
// only stay high for ~2573/2 clocks
apu.setINT(true);
counter = 4;
return step(2573/2);
} else {
counter = 5;
return step(1710);
}
break;
Expand All @@ -102,11 +103,17 @@ auto VDP::main() -> void {
}
}

counter = 4;
counter = 5;
return step(430);
break;

case 4:
apu.setINT(false);
counter = 5;
return step(1710-(2573/2));
break;

case 5:
state.hdot = 0;
state.hcounter = 0;
if(++state.vcounter >= frameHeight()) {
Expand Down Expand Up @@ -172,6 +179,8 @@ auto VDP::power(bool reset) -> void {
planeB.power();
sprite.power();
dma.power();

psg.power(reset);
}

}
Expand Down
2 changes: 2 additions & 0 deletions higan/md/vdp/vdp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ struct VDP : Thread {
Node::String region;

bool hasRendered;
bool isSkipping;
bool skip;

//vdp.cpp
auto load(Node::Object, Node::Object) -> void;
Expand Down
Loading

0 comments on commit a77dfd7

Please sign in to comment.