use super::extended::{block_transfer, port_block_out};
use super::{AddressSource, AluOp, Context, Decoded, Z80nCommand};
use crate::control::{bus, step};
#[allow(clippy::too_many_lines)]
pub(super) fn extended_z80n(context: Context, out: &mut Decoded) {
if !context.z80n_enabled {
return;
}
let ir = context.ir;
let cycle = context.machine_cycle.number();
match ir {
0x91 => {
out.machine_cycles = 5;
match cycle {
1 | 5 => out.set_inc_pc(),
2 => {
out.set_inc_pc();
out.z80n_data = context.data;
out.set_z80n_strobe_hi();
}
3 => {
out.z80n_data = context.data;
out.set_z80n_strobe_lo();
}
4 => {
out.z80n_command = Some(Z80nCommand::NextRegWrite);
out.set_z80n_dout();
}
_ => {}
}
}
0x92 => {
out.machine_cycles = 4;
match cycle {
1 => {
out.set_inc_pc();
out.z80n_data = context.accumulator;
out.set_z80n_strobe_lo();
}
2 => {
out.z80n_data = context.data;
out.set_z80n_strobe_hi();
}
3 => {
out.z80n_command = Some(Z80nCommand::NextRegWrite);
out.set_z80n_dout();
}
4 => out.set_inc_pc(),
_ => {}
}
}
0x30 => simple_z80n(out, Z80nCommand::MulDe),
0x31 => simple_z80n(out, Z80nCommand::AddHlA),
0x32 => simple_z80n(out, Z80nCommand::AddDeA),
0x33 => simple_z80n(out, Z80nCommand::AddBcA),
0x23 => simple_z80n(out, Z80nCommand::SwapNibbleA),
0x24 => simple_z80n(out, Z80nCommand::MirrorA),
0x93 => simple_z80n(out, Z80nCommand::PixelDown),
0x94 => simple_z80n(out, Z80nCommand::PixelAddress),
0x95 => simple_z80n(out, Z80nCommand::SetAE),
0x28 => simple_z80n(out, Z80nCommand::BslaDeB),
0x29 => simple_z80n(out, Z80nCommand::BsraDeB),
0x2A => simple_z80n(out, Z80nCommand::BsrlDeB),
0x2B => simple_z80n(out, Z80nCommand::BsrfDeB),
0x2C => simple_z80n(out, Z80nCommand::BrlcDeB),
0x27 => {
out.machine_cycles = 2;
if cycle == 2 {
out.set_inc_pc();
out.set_save_alu();
out.set_bus_b_to = bus::DATA_LATCH;
out.set_bus_a_to = bus::ACCUMULATOR;
}
}
0x98 => {
out.machine_cycles = 2;
out.t_states = 4;
out.z80n_command = Some(Z80nCommand::JpC);
match cycle {
1 => out.set_addr_to = AddressSource::Bc,
2 => out.set_iorq(),
_ => {}
}
}
0x34..=0x36 => {
out.t_states = 4;
out.z80n_command = Some(match ir {
0x34 => Z80nCommand::AddHlImmediate,
0x35 => Z80nCommand::AddDeImmediate,
_ => Z80nCommand::AddBcImmediate,
});
out.machine_cycles = 3;
match cycle {
1 => out.set_inc_pc(),
2 => {
out.set_inc_pc();
out.set_ldz();
}
3 => {
out.set_inc_pc();
out.set_ldw();
}
_ => {}
}
}
0x8A => {
out.machine_cycles = 6;
match cycle {
1 => {
out.set_inc_pc();
out.set_ldz();
}
2 | 4 => {
out.inc_dec_16 = step::down(step::STACK);
out.set_addr_to = AddressSource::Sp;
out.set_bus_b_to = bus::DATA_LATCH;
}
3 => {
out.set_inc_pc();
out.set_ldz();
out.set_write();
}
5 => out.set_write(),
_ => {}
}
}
0xB7 => {
out.z80n_command = Some(Z80nCommand::LdPirx);
out.machine_cycles = 4;
match cycle {
1 => {
out.set_ldz();
out.set_addr_to = AddressSource::IndexOrHl;
out.inc_dec_16 = step::down(step::BC);
}
2 => out.set_bus_b_to = bus::DATA_LATCH,
3 => {
out.set_i_bt();
out.t_states = 5;
out.set_write_to(context.accumulator != context.data);
out.inc_dec_16 = step::up(step::DE);
}
4 => {
out.set_no_read();
out.t_states = 5;
}
_ => {}
}
}
0xA4 | 0xB4 => block_transfer(context, out),
0xA5 => {
out.machine_cycles = 3;
match cycle {
1 => {
out.set_addr_to = AddressSource::IndexOrHl;
out.set_bus_b_to = bus::ONE;
out.set_bus_a_to = bus::L;
out.set_read_to_reg();
out.set_save_alu();
out.alu_op = AluOp::Add;
}
2 => {
out.set_addr_to = AddressSource::De;
out.set_bus_b_to = bus::DATA_LATCH;
out.set_bus_a_to = bus::ACCUMULATOR;
out.alu_op = AluOp::Add;
}
3 => {
out.set_i_bt();
out.t_states = 3;
out.set_write();
out.set_bus_b_to = bus::ONE;
out.set_bus_a_to = bus::D;
out.set_read_to_reg();
out.set_save_alu();
out.alu_op = AluOp::Add;
}
_ => {}
}
}
0xB6 => {
out.z80n_command = Some(Z80nCommand::LdirScale);
out.machine_cycles = 4;
match cycle {
1 => {
out.set_addr_to = AddressSource::IndexOrHl;
out.inc_dec_16 = step::down(step::BC);
}
2 => {
out.set_bus_b_to = bus::DATA_LATCH;
out.set_bus_a_to = bus::ACCUMULATOR;
out.alu_op = AluOp::Add;
out.set_addr_to = AddressSource::De;
out.inc_dec_16 = step::up(step::HL);
}
3 => {
out.set_i_bt();
out.t_states = 5;
out.set_write_to(context.accumulator != context.data);
out.inc_dec_16 = step::up(step::DE);
}
4 => {
out.set_no_read();
out.t_states = 5;
}
_ => {}
}
}
0xAC | 0xBC => {
out.machine_cycles = 4;
match cycle {
1 => {
out.set_addr_to = AddressSource::IndexOrHl;
out.inc_dec_16 = step::down(step::BC);
}
2 => {
out.set_bus_b_to = bus::DATA_LATCH;
out.set_bus_a_to = bus::ACCUMULATOR;
out.alu_op = AluOp::Add;
out.set_addr_to = AddressSource::De;
out.inc_dec_16 = step::down(step::HL);
}
3 => {
out.set_i_bt();
out.t_states = 5;
out.set_write_to(context.accumulator != context.data);
out.inc_dec_16 = step::up(step::DE);
}
4 => {
out.set_no_read();
out.t_states = 5;
}
_ => {}
}
}
0x90 => port_block_out(context, out, true),
_ => {}
}
}
fn simple_z80n(out: &mut Decoded, command: Z80nCommand) {
out.t_states = 4;
out.z80n_command = Some(command);
}