static void debug_process_command()

in cores/snes/debug.cpp [1365:1921]


static void debug_process_command (char *Line)
{
	uint8	Bank = Registers.PB;
	uint32	Address = Registers.PCw;
	uint16	Hold = 0;
	uint16	Number;
	short	ErrorCode;
	char	string[512];

	if (strncasecmp(Line, "dump", 4) == 0)
	{
		int	Count;

		if (sscanf(&Line[4], "%x %d", &Address, &Count) == 2)
		{
			FILE	*fs;

			sprintf(string, "%06x%05d.sd2", Address, Count);
			fs = fopen(string, "wb");
			if (fs)
			{
				for (int i = 0; i < Count; i++)
					putc(S9xDebugGetByte(Address + i), fs);
				fclose(fs);
			}
			else
				printf("Can't open %s for writing\n", string);
		}
		else
			printf("Usage: dump start_address_in_hex count_in_decimal\n");

		return;
	}

	if (*Line == 'i')
	{
		printf("Vectors:\n");
		sprintf(string, "      8 Bit   16 Bit ");
		debug_line_print(string);
		sprintf(string, "ABT $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF8), S9xDebugGetWord(0xFFE8));
		debug_line_print(string);
		sprintf(string, "BRK $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFE6));
		debug_line_print(string);
		sprintf(string, "COP $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF4), S9xDebugGetWord(0xFFE4));
		debug_line_print(string);
		sprintf(string, "IRQ $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFEE));
		debug_line_print(string);
		sprintf(string, "NMI $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFA), S9xDebugGetWord(0xFFEA));
		debug_line_print(string);
		sprintf(string, "RES     $00:%04X", S9xDebugGetWord(0xFFFC));
		debug_line_print(string);
	}

/*
	if (strncmp(Line, "ai", 2) == 0)
	{
		printf("APU vectors:");

		for (int i = 0; i < 0x40; i += 2)
		{
			if (i % 16 == 0)
				printf("\n%04x ", 0xffc0 + i);

			printf("%04x ", APU.ExtraRAM[i]);
		}

		printf("\n");
	}
*/

	if (*Line == 's')
	{
		Registers.PCw += debug_cpu_op_print(string, Bank, Address);
		Bank = Registers.PB;
		Address = Registers.PCw;
		*Line = 'r';
	}

	if (*Line == 'z')
	{
		uint16	*p = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];

		for (int l = 0; l < 32; l++)
		{
			for (int c = 0; c < 32; c++, p++)
				printf("%04x,", *p++);

			printf("\n");
		}
	}

	if (*Line == 'c')
	{
		printf("Colours:\n");

		for (int i = 0; i < 256; i++)
			printf("%02x%02x%02x  ", PPU.CGDATA[i] & 0x1f, (PPU.CGDATA[i] >> 5) & 0x1f, (PPU.CGDATA[i] >> 10) & 0x1f);

		printf("\n");
	}

	if (*Line == 'S')
	{
		int	SmallWidth, LargeWidth, SmallHeight, LargeHeight;

		switch ((Memory.FillRAM[0x2101] >> 5) & 7)
		{

			case 0:
				SmallWidth = SmallHeight = 8;
				LargeWidth = LargeHeight = 16;
				break;

			case 1:
				SmallWidth = SmallHeight = 8;
				LargeWidth = LargeHeight = 32;
				break;

			case 2:
				SmallWidth = SmallHeight = 8;
				LargeWidth = LargeHeight = 64;
				break;

			case 3:
				SmallWidth = SmallHeight = 16;
				LargeWidth = LargeHeight = 32;
				break;

			case 4:
				SmallWidth = SmallHeight = 16;
				LargeWidth = LargeHeight = 64;
				break;

			default:
			case 5:
				SmallWidth = SmallHeight = 32;
				LargeWidth = LargeHeight = 64;
				break;

			case 6:
				SmallWidth = 16;
				SmallHeight = 32;
				LargeWidth = 32;
				LargeHeight = 64;
				break;

			case 7:
				SmallWidth = 16;
				SmallHeight = 32;
				LargeWidth = LargeHeight = 32;
				break;
		}

		printf("Sprites: Small: %dx%d, Large: %dx%d, OAMAddr: 0x%04x, OBJNameBase: 0x%04x, OBJNameSelect: 0x%04x, First: %d\n",
		       SmallWidth, SmallHeight, LargeWidth, LargeHeight, PPU.OAMAddr, PPU.OBJNameBase, PPU.OBJNameSelect, PPU.FirstSprite);

		for (int i = 0; i < 128; i++)
		{
			printf("X:%3d Y:%3d %c%c%d%c ",
			       PPU.OBJ[i].HPos,
			       PPU.OBJ[i].VPos,
			       PPU.OBJ[i].VFlip ? 'V' : 'v',
			       PPU.OBJ[i].HFlip ? 'H' : 'h',
			       PPU.OBJ[i].Priority,
			       PPU.OBJ[i].Size ? 'S' : 's');

			if (i % 4 == 3)
				printf("\n");
		}
	}

	if (*Line == 'T')
	{
		if (Line[1] == 'S')
		{
			SA1.Flags ^= TRACE_FLAG;

			if (SA1.Flags & TRACE_FLAG)
			{
				printf("SA1 CPU instruction tracing enabled.\n");
				ENSURE_TRACE_OPEN(trace2, "trace_sa1.log", "wb")
			}
			else
			{
				printf("SA1 CPU instruction tracing disabled.\n");
				fclose(trace2);
				trace2 = NULL;
			}
		}
		else
		{
			CPU.Flags ^= TRACE_FLAG;

			if (CPU.Flags & TRACE_FLAG)
			{
				printf("CPU instruction tracing enabled.\n");
				ENSURE_TRACE_OPEN(trace, "trace.log", "wb")
			}
			else
			{
				printf("CPU instruction tracing disabled.\n");
				fclose(trace);
				trace = NULL;
			}
		}
	}

	if (*Line == 'E')
	{
		Settings.TraceHCEvent = !Settings.TraceHCEvent;
		printf("HC event tracing %s.\n", Settings.TraceHCEvent ? "enabled" : "disabled");
	}

	if (*Line == 'A')
		spc_core->debug_toggle_trace();

/*
	if (*Line == 'B')
	{
		Settings.TraceSoundDSP = !Settings.TraceSoundDSP;
		printf("Sound DSP register tracing %s.\n", Settings.TraceSoundDSP ? "enabled" : "disabled");
	}

	if (*Line == 'x')
		S9xPrintSoundDSPState();

	if (*Line == 'C')
	{
		printf("SPC700 sample addresses at 0x%04x:\n", APU.DSP[APU_DIR] << 8);

		for (int i = 0; i < 256; i++)
		{
			uint8	*dir = IAPU.RAM + (((APU.DSP[APU_DIR] << 8) + i * 4) & 0xffff);
			int		addr = *dir + (*(dir + 1) << 8);
			int		addr2 = *(dir + 2) + (*(dir + 3) << 8);
			printf("%04X %04X;", addr, addr2);

			if (i % 8 == 7)
				printf("\n");
		}
	}
*/

	if (*Line == 'R')
	{
		S9xReset();
		printf("SNES reset.\n");
		CPU.Flags |= DEBUG_MODE_FLAG;
	}

/*
	if (strncmp(Line, "ad", 2) == 0)
	{
		uint32	Count = 16;
		Address = 0;

		if (sscanf(Line + 2, "%x,%x", &Address, &Count) != 2)
		{
			if (sscanf(Line + 2, "%x", &Address) == 1)
				Count = 16;
		}

		printf("APU RAM dump:\n");

		for (uint32 l = 0; l < Count; l += 16)
		{
			printf("%04X ", Address);

			for (int i = 0; i < 16; i++)
				printf("%02X ", IAPU.RAM[Address++]);

			printf("\n");
		}

		*Line = 0;
	}

	if (*Line == 'a')
	{
		printf("APU in-ports : %02X %02X %02X %02X\n", IAPU.RAM[0xF4], IAPU.RAM[0xF5], IAPU.RAM[0xF6], IAPU.RAM[0xF7]);
		printf("APU out-ports: %02X %02X %02X %02X\n", APU.OutPorts[0], APU.OutPorts[1], APU.OutPorts[2], APU.OutPorts[3]);
		printf("ROM/RAM switch: %s\n", (IAPU.RAM[0xf1] & 0x80) ? "ROM" : "RAM");

		for (int i = 0; i < 3; i++)
			if (APU.TimerEnabled[i])
				printf("Timer%d enabled, Value: 0x%03X, 4-bit: 0x%02X, Target: 0x%03X\n",
				       i, APU.Timer[i], IAPU.RAM[0xfd + i], APU.TimerTarget[i]);
	}

	if (*Line == 'P')
	{
		Settings.TraceDSP = !Settings.TraceDSP;
		printf("DSP tracing %s.\n", Settings.TraceDSP ? "enabled" : "disabled");
	}
*/

	if (*Line == 'p')
	{
		S9xBreakpoint[5].Enabled = FALSE;
		Address += debug_cpu_op_print(string, Bank, Address);

		if (strncmp(&string[18], "JMP", 3) != 0 &&
		    strncmp(&string[18], "JML", 3) != 0 &&
		    strncmp(&string[18], "RT" , 2) != 0 &&
		    strncmp(&string[18], "BRA", 3))
		{
			S9xBreakpoint[5].Enabled = TRUE;
			S9xBreakpoint[5].Bank = Bank;
			S9xBreakpoint[5].Address = Address;
		}
		else
		{
			CPU.Flags |= SINGLE_STEP_FLAG;
			CPU.Flags &= ~DEBUG_MODE_FLAG;
		}
	}

	if (*Line == 'b')
	{
		if (Line[1] == 's')
		{
			debug_get_number(Line + 2, &Hold);

			if (Hold > 4)
				Hold = 0;

			if (Hold < 5)
			{
				if (debug_get_start_address(Line + 5, &Bank, &Address) == -1)
					S9xBreakpoint[Hold].Enabled = FALSE;
				else
				{
					S9xBreakpoint[Hold].Enabled = TRUE;
					S9xBreakpoint[Hold].Bank = Bank;
					S9xBreakpoint[Hold].Address = Address;
					CPU.Flags |= BREAK_FLAG;
				}
			}

			Line[1] = 'v';
		}

		if (Line[1] == 'v')
		{
			Number = 0;

			if (debug_get_number(Line + 2, &Number) == -1 && Number < 5)
			{
				debug_line_print("Breakpoints:");

				for (Number = 0; Number != 5; Number++)
				{
					if (S9xBreakpoint[Number].Enabled)
						sprintf(string, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address);
					else
						sprintf(string, "%i @ Disabled", Number);

					debug_line_print(string);
				}
			}
			else
			{
				debug_line_print("Breakpoint:");

				if (S9xBreakpoint[Number].Enabled)
					sprintf(string, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address);
				else
					sprintf(string, "%i @ Disabled", Number);

				debug_line_print(string);
			}
		}
	}

	if (*Line == '?' || strcasecmp(Line, "help") == 0)
	{
		for (int i = 0; HelpMessage[i] != NULL; i++)
			debug_line_print(HelpMessage[i]);
	}

	if (*Line == 't')
	{
		CPU.Flags |= SINGLE_STEP_FLAG;
		CPU.Flags &= ~DEBUG_MODE_FLAG;
	}

	if (*Line == 'f')
	{
		CPU.Flags |= FRAME_ADVANCE_FLAG;
		CPU.Flags &= ~DEBUG_MODE_FLAG;

		IPPU.RenderThisFrame = TRUE;
		IPPU.FrameSkip = 0;

		if (sscanf(&Line[1], "%u", &ICPU.FrameAdvanceCount) != 1)
			ICPU.Frame = 0;
	}

	if (*Line == 'g')
	{
		S9xBreakpoint[5].Enabled = FALSE;

		bool8	found = FALSE;

		for (int i = 0; i < 5; i++)
		{
			if (S9xBreakpoint[i].Enabled)
			{
				found = TRUE;

				if (S9xBreakpoint[i].Bank == Registers.PB && S9xBreakpoint[i].Address == Registers.PCw)
				{
					S9xBreakpoint[i].Enabled = 2;
					break;
				}
			}
		}

		if (!found)
			CPU.Flags &= ~BREAK_FLAG;

		ErrorCode = debug_get_start_address(Line, &Bank, &Address);

		if (ErrorCode == 1)
		{
			S9xBreakpoint[5].Enabled = TRUE;
			S9xBreakpoint[5].Bank = Bank;
			S9xBreakpoint[5].Address = Address;
			CPU.Flags |= BREAK_FLAG;
		}

		CPU.Flags &= ~DEBUG_MODE_FLAG;
	}

	if (*Line == 'D')
	{
		Settings.TraceDMA = !Settings.TraceDMA;
		printf("DMA tracing %s.\n", Settings.TraceDMA ? "enabled" : "disabled");
	}

	if (*Line == 'V')
	{
		Settings.TraceVRAM = !Settings.TraceVRAM;
		printf("Non-DMA VRAM write tracing %s.\n", Settings.TraceVRAM ? "enabled" : "disabled");
	}

	if (*Line == 'H')
	{
		Settings.TraceHDMA = !Settings.TraceHDMA;
		printf("HDMA tracing %s.\n", Settings.TraceHDMA ? "enabled" : "disabled");
	}

	if (*Line == 'U')
	{
		Settings.TraceUnknownRegisters = !Settings.TraceUnknownRegisters;
		printf("Unknown registers read/write tracing %s.\n", Settings.TraceUnknownRegisters ? "enabled" : "disabled");
	}

	if (*Line == 'd')
	{
		int		CLine;
		int		CByte;
		uint8	MemoryByte;

		if (Debug.Dump.Bank != 0 || Debug.Dump.Address != 0)
		{
			Bank = Debug.Dump.Bank;
			Address = Debug.Dump.Address;
		}

		ErrorCode = debug_get_start_address(Line, &Bank, &Address);

		for (CLine = 0; CLine != 10; CLine++)
		{
			sprintf(string, "$%02X:%04X", Bank, Address);

			for (CByte = 0; CByte != 16; CByte++)
			{
				if (Address + CByte == 0x2140 ||
				    Address + CByte == 0x2141 ||
				    Address + CByte == 0x2142 ||
				    Address + CByte == 0x2143 ||
				    Address + CByte == 0x4210)
					MemoryByte = 0;
				else
					MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte);

				sprintf(string, "%s %02X", string, MemoryByte);
			}

			sprintf(string, "%s-", string);

			for (CByte = 0; CByte != 16; CByte++)
			{
				if (Address + CByte == 0x2140 ||
				    Address + CByte == 0x2141 ||
				    Address + CByte == 0x2142 ||
				    Address + CByte == 0x2143 ||
				    Address + CByte == 0x4210)
					MemoryByte = 0;
				else
					MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte);

				if (MemoryByte < 32 || MemoryByte >= 127)
					MemoryByte = '?';

				sprintf(string, "%s%c", string, MemoryByte);
			}

			Address += 16;

			debug_line_print(string);
		}

		Debug.Dump.Bank = Bank;
		Debug.Dump.Address = Address;
	}

	if (*Line == 'q')
		S9xExit();

	if (*Line == 'W')
		debug_whats_missing();

	if (*Line == 'w')
		debug_whats_used();

	if (*Line == 'r')
	{
		debug_cpu_op_print(string, Bank, Address);
		debug_line_print(string);
	}

	if (*Line == 'u')
	{
		if (Debug.Unassemble.Bank != 0 || Debug.Unassemble.Address != 0)
		{
			Bank = Debug.Unassemble.Bank;
			Address = Debug.Unassemble.Address;
		}

		ErrorCode = debug_get_start_address(Line, &Bank, &Address);

		for (int i = 0; i != 10; i++)
		{
			Address += debug_cpu_op_print(string, Bank, Address);
			debug_line_print(string);
		}

		Debug.Unassemble.Bank = Bank;
		Debug.Unassemble.Address = Address;
	}

	debug_line_print("");

	return;
}