#undef _GLIBCXX_USE_C99_STDIO
#include <cstdio>

int tmp_low;
unsigned cycle_timer;
//FILE *DMA_log = fopen("DMA.log", "w");
char buffer[1024] = {0};

#define create_register(reg, register_function) \
	bool debug_##reg(int data) register_function

//generic output
create_register(0x5000,
	{
		if(!(cpu.regs.p & 0x20)){
			tmp_low = data;
		}else{
			sprintf(buffer, "%02X\n", data);
		}
		return false;
	}
)

create_register(0x5001,
	{
		sprintf(buffer, "%04X\n", (data << 8) | tmp_low);
		return false;
	}
)

//register states

create_register(0x5002,
	{
		int end = 0;
		if(!data){
			data = 0xFF;
		}
		if(data & 0x01){
			end += sprintf(buffer + end, "A: %04X, ", cpu.regs.a);
		}
		if(data & 0x02){
			end += sprintf(buffer + end, "X: %04X, ", cpu.regs.x);
		}
		if(data & 0x04){
			end += sprintf(buffer + end, "Y: %04X, ", cpu.regs.y);
		}
		if(data & 0x08){
			end += sprintf(buffer + end, "S: %04X, ", cpu.regs.s);
		}
		if(data & 0x10){
			end += sprintf(buffer + end, "D: %04X, ", cpu.regs.d);
		}
		if(data & 0x20){
			end += sprintf(buffer + end, "Data bank: %02X, ", cpu.regs.db);
		}
		if(data & 0x40){
			end += sprintf(buffer + end, "P: %08X, ", cpu.regs.p);
		}
		if(data & 0x80){
			end += sprintf(buffer + end, "Program counter: %06X\n", cpu.regs.pc.d);
		}
	}
)

//cpu timings

create_register(0x5003,
	{
		cycle_timer =  cpu.get_master_clocks();
		return false;
	}
)

create_register(0x5004,
	{
		return false;
	}
)

create_register(0x5005,
	{
		sprintf(buffer, "%u\n", cpu.get_master_clocks() - 30 - cycle_timer);
		return false;
	}
)

create_register(0x5006,
	{
		return false;
	}
)

//named outputs

create_register(0x5010,
	{
		sprintf(buffer, "Print 1:");
		debug_0x5000(data);
		return false;
	}
)

create_register(0x5011,
	{
		debug_0x5001(data);
		return false;
	}
)

create_register(0x5012,
	{
		sprintf(buffer, "Print 2:");
		debug_0x5000(data);
		return false;
	}
)

create_register(0x5013,
	{
		debug_0x5001(data);
		return false;
	}
)

create_register(0x5014,
	{
		sprintf(buffer, "Print 3:");
		debug_0x5000(data);
		return false;
	}
)

create_register(0x5015,
	{
		debug_0x5001(data);
		return false;
	}
)

create_register(0x5016,
	{
		sprintf(buffer, "Print 4:");
		debug_0x5000(data);
		return false;
	}
)

create_register(0x5017,
	{
		debug_0x5001(data);
		return false;
	}
)

create_register(0x5018,
	{
		sprintf(buffer, "Print 5:");
		debug_0x5000(data);
		return false;
	}
)

create_register(0x5019,
	{
		debug_0x5001(data);
		return false;
	}
)

create_register(0x501A,
	{
		sprintf(buffer, "Print 6:");
		debug_0x5000(data);
		return false;
	}
)

create_register(0x501B,
	{
		debug_0x5001(data);
		return false;
	}
)

create_register(0x501C,
	{
		sprintf(buffer, "Print 7:");
		debug_0x5000(data);
		return false;
	}
)

create_register(0x501D,
	{
		debug_0x5001(data);
		return false;
	}
)

create_register(0x501E,
	{
		sprintf(buffer, "Print 8:");
		debug_0x5000(data);
		return false;
	}
)

create_register(0x501F,
	{
		debug_0x5001(data);
		return false;
	}
)

#undef create_register


bool mmio_debug_registers(int addr, int data)
{
	#define register_case(reg) case reg: debug_##reg(data); break
	buffer[0] = 0;
	switch(addr){
		register_case(0x5000);
		register_case(0x5001);
		register_case(0x5002);
		register_case(0x5003);
		register_case(0x5004);
		register_case(0x5005);
		register_case(0x5006);
		//prints
		register_case(0x5010);
		register_case(0x5011);
		register_case(0x5012);
		register_case(0x5013);
		register_case(0x5014);
		register_case(0x5015);
		register_case(0x5016);
		register_case(0x5017);
		register_case(0x5018);
		register_case(0x5019);
		register_case(0x501A);
		register_case(0x501B);
		register_case(0x501C);
		register_case(0x501D);
		register_case(0x501E);
		register_case(0x501F);
		
		default:
			if((addr >= 0x2140 && addr <= 0x2184) || //increased by one to avoid 16 bit writes on 2183
			   (addr == 0x4016 || addr == 0x4017) ||
			   (addr >= 0x4200 && addr <= 0x421F) ||
			   (addr >= 0x4300 && addr <= 0x437F)){
				   if(addr == 0x420B){
					//disable DMA console for now
				   	for(unsigned i = 0; i < 8; i++){
						   if(data & (1 << i)){
							   cpu.debug_dma(cpu.regs.pc.d, 
									(cpu.channel[i].source_bank << 16) | cpu.channel[i].source_addr,
									cpu.channel[i].dest_addr, cpu.channel[i].transfer_size, 
									cpu.channel[i].transfer_mode, cpu.channel[i].direction,
									cpu.channel[i].fixed_transfer
									);
						   }
					}
					
				   }
				   return false;
			}
			sprintf(buffer, "%06X: Unhandled register %X with data %02X\n", cpu.regs.pc.d, addr, data);
		break;
	}
	#undef register_case
	cpu.debug_print(buffer);
	
	return false;
}
