module mmc5_mixed (
	input         clk,
	input         ce,    // Negedge M2 (aka CPU ce)
	input         enable,
	input         wren,
	input         rden,
	input  [15:0] addr_in,
	input   [7:0] data_in,
	output  [7:0] data_out,
	input  [15:0] audio_in,    // Inverted audio from APU
	output [15:0] audio_out,
	// savestates              
	input       [63:0]  SaveStateBus_Din,
	input       [ 9:0]  SaveStateBus_Adr,
	input               SaveStateBus_wren,
	input               SaveStateBus_rst,
	input               SaveStateBus_load,
	output      [63:0]  SaveStateBus_Dout
);

// NOTE: The apu volume is 100% of MMC5 and the polarity is reversed.
wire [16:0] audio_o = audio + audio_in;
wire [15:0] audio;
assign audio_out = audio_o[16:1];

wire apu_cs = (addr_in[15:5]==11'b0101_0000_000) && (addr_in[3]==0);
wire DmaReq;          // 1 when DMC wants DMA
wire [15:0] DmaAddr;  // Address DMC wants to read
reg odd_or_even;
wire apu_irq;         // TODO: IRQ asserted

reg phi2;
always @(posedge clk) begin
	phi2 <= ce;
	if (~enable)
		odd_or_even <= 0;
	else if (ce)
		odd_or_even <= ~odd_or_even;
		
	if (SaveStateBus_load) begin
		odd_or_even <= SS_MAP1[0];
	end
end

assign SS_MAP1_BACK[    0] = odd_or_even;
assign SS_MAP1_BACK[63: 1] = 63'b0; // free to be used

APU mmc5apu(
	.MMC5           (1),
	.clk            (clk),
	.ce             (ce),
	.PHI2           (phi2),
	.CS             (apu_cs),
	.reset          (~enable | SaveStateBus_load),
	.ADDR           (addr_in[4:0]),
	.DIN            (data_in),
	.DOUT           (data_out),
	.RW             (~wren),
	.audio_channels (5'b10011),
	.Sample         (audio),
	.DmaReq         (DmaReq),
	.DmaAck         (1),
	.DmaAddr        (DmaAddr),
	.DmaData        (0),
	.odd_or_even    (odd_or_even),
	.IRQ            (apu_irq),
	// savestates
	.SaveStateBus_Din  (SaveStateBus_Din ), 
	.SaveStateBus_Adr  (SaveStateBus_Adr ),
	.SaveStateBus_wren (SaveStateBus_wren),
	.SaveStateBus_rst  (SaveStateBus_rst ),
	.SaveStateBus_load (SaveStateBus_load ),
	.SaveStateBus_Dout (SaveStateBus_wired_or[1])
);
defparam mmc5apu.SSREG_INDEX_TOP  = SSREG_INDEX_SNDMAP1;
defparam mmc5apu.SSREG_INDEX_DMC1 = SSREG_INDEX_SNDMAP2;
defparam mmc5apu.SSREG_INDEX_DMC2 = SSREG_INDEX_SNDMAP3;
defparam mmc5apu.SSREG_INDEX_FCT  = SSREG_INDEX_SNDMAP4;

// savestates
localparam SAVESTATE_MODULES    = 2;
wire [63:0] SaveStateBus_wired_or[0:SAVESTATE_MODULES-1];
wire [63:0] SS_MAP1;
wire [63:0] SS_MAP1_BACK;	
wire [63:0] SaveStateBus_Dout_active = SaveStateBus_wired_or[0] | SaveStateBus_wired_or[1];
	
eReg_SavestateV #(SSREG_INDEX_SNDMAP5, 64'h0000000000000000) iREG_SAVESTATE_MAP1 (clk, SaveStateBus_Din, SaveStateBus_Adr, SaveStateBus_wren, SaveStateBus_rst, SaveStateBus_wired_or[0], SS_MAP1_BACK, SS_MAP1);  

assign SaveStateBus_Dout = enable ? SaveStateBus_Dout_active : 64'h0000000000000000;

endmodule