Example #1
0
int main(int argc, char* argv[])
{
	mos6502 cpu(MemoryRead, MemoryWrite);
	disasm dasm;
	int SPEED = 100; // %
	int CPUFREQ = 1000000; // Hz - CPU clock frequency
	bool HALT = false;
	// Todo optimize this string buffer size?
	char str[400];

	if (argc < 2)
	{
		std::cout << "Filename required!" << std::endl;
		return 0;
	}

	if (rom.loadFromFile(argv[1]) == 0)
	{
		std::cout << "Rom invalid!" << std::endl;
	}

	std::string caption("CBS6000 Emulator - (C)2015 Koen van Vliet");
	sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), caption);
	sf::RenderWindow dbgwindow(sf::VideoMode(DBGWINDOW_WIDTH, DBGWINDOW_HEIGHT), caption);
	sf::RenderWindow zpwindow(sf::VideoMode(ZPWINDOW_WIDTH, ZPWINDOW_HEIGHT), caption);
	window.setFramerateLimit(FPS);
	dbgwindow.setFramerateLimit(FPS);
	zpwindow.setFramerateLimit(FPS);

	if (!term.load("terminal8x16.png",8,16))
	{
		std::cout << "Failed to open bitmap font file!" << std::endl;
		return 0;
	}

	if (!dbgterm.load("terminal8x16.png",8,16))
	{
		std::cout << "Failed to open bitmap font file!" << std::endl;
		return 0;
	}

	if (!dasmterm.load("terminal8x16.png",8,16))
	{
		std::cout << "Failed to open bitmap font file!" << std::endl;
		return 0;
	}

	if (!regterm.load("terminal8x16.png",8,16))
	{
		std::cout << "Failed to open bitmap font file!" << std::endl;
		return 0;
	}

	if (!zpterm.load("terminal8x16.png",8,16))
	{
		std::cout << "Failed to open bitmap font file!" << std::endl;
		return 0;
	}

	int ctile = 177;
	term.setCursorTile(ctile);
	dbgterm.setCursorTile(ctile);
	dbgterm.enableCursor(false);
	dbgterm.setTextColor(sf::Color::Green);
	dasmterm.enableCursor(false);
	dasmterm.setTextColor(sf::Color::Cyan);
	regterm.enableCursor(false);
	regterm.setTextColor(sf::Color::White);
	zpterm.enableCursor(false);
	zpterm.setTextColor(sf::Color::White);

	consoleLog("---[Debug console]---");
	consoleLog(versionInfo);
	net.init();
	consoleLog("Starting CPU emulation");

	// Reset Cpu and internal IO port for the 6510
	Direction = 0x00;
	PortOut = 0x00;
	cpu.Reset();

	bool SHOWDASM = false;

	while(window.isOpen())
	{
		if (SPEED <= 20)
		{
			SHOWDASM = true;
		}

		sf::Event event;
		while (window.pollEvent(event))
		{
			switch (event.type) {
				case sf::Event::Closed :
					window.close();
					break;
				case sf::Event::TextEntered:
					if (event.text.unicode < 128)
					{
						char c = (char)event.text.unicode;
						term.feedChar(c);
					}
					break;
				case sf::Event::KeyPressed :
					// Increase and decrease the CPU speed
					if (event.key.code == sf::Keyboard::PageUp)
					{
						if (SPEED < 500)
						{
							SPEED += 5;
						}

						sprintf(str, "%d%% speed", SPEED);
						consoleLog(str);
					}
					if (event.key.code == sf::Keyboard::PageDown)
					{
						if (SPEED)
						{
							SPEED -= 5;
							if (SPEED < 0)
							{
								SPEED = 0;
							}
							sprintf(str, "%d%% speed", SPEED);
							consoleLog(str);
						}
					}

					// Stop execution
					if (event.key.code == sf::Keyboard::Delete)
					{
						HALT = true;
						SHOWDASM = true;
						consoleLog("F8 to continue, F5 to step");
					}

					// Stop/Resume execution
					if (event.key.code == sf::Keyboard::F8)
					{
						if (HALT)
						{
							HALT = false;
							consoleLog("Resumed execution...");
						}
						else
						{
							HALT = true;
							SHOWDASM = true;
							consoleLog("F8 to continue, F5 to step");
						}
					}
					// Execute single instruction
					if (event.key.code == sf::Keyboard::F5)
					{
						if (HALT)
						{
							cpu.Run(1);
							SHOWDASM = true;
						}
					}


					if (event.key.code == sf::Keyboard::End)
					{
						// Reset Cpu and internal IO port for the 6510
						Direction = 0x00;
						PortOut = 0x00;
						cpu.Reset();
						HALT = false;
						consoleLog("Reset CPU");
					}

					break;
				default:
					break;
			}
		}

		// Run a bunch of instructions
		if(!HALT)
		{
			int IPF = (CPUFREQ * SPEED) /(FPS * AVG_INSTRUCTION_CYCLES * 100); 			// Instructions per frame
			cpu.Run(IPF);
		}

		if (SHOWDASM)
		{
			// Show live disassembly of the memory
			SHOWDASM = false;
			// Todo fix pc
			uint16_t state[6];
			uint8_t buff[3];
			uint16_t pc;
			cpu.GetState(state);
			pc = state[3];
			for(int i = 0; i< 9; i++)
			{
				uint pc_prev = pc;
				dasmterm.printString("\r\n");
				buff[0] = MemoryRead(pc);
				buff[1] = MemoryRead(pc+1);
				buff[2] = MemoryRead(pc+2);
				pc += 1 + dasm.getDisassembly((char*)str, buff, 1, pc_prev);
				if(i ==0)
					dasmterm.printString(">");
				else
					dasmterm.printString(" ");
				dasmterm.printString(str);
			}

			// Display CPU register contents
			char charA = state[0], charX = state[1], charY = state[2];

			if (charA < ' ')
			{
				charA = ' ';
			}
			if (charX < ' ')
			{
				charX = ' ';
			}
			if (charY < ' ')
			{
				charY = ' ';
			}

			sprintf(str,"\r\n"
						"A:  $%02X  %03d \'%c\'\r\n"
						"X:  $%02X  %03d \'%c\'\r\n"
						"Y:  $%02X  %03d \'%c\'\r\n"
						"PC: $%04X\r\n"
						"SP: $%02X  %03d\r\n"
						"SR: $%02X, Z: %d, C: %d",
						state[0],
						state[0],
						charA,
						state[1],
						state[1],
						charX,
						state[2],
						state[2],
						charY,
						state[3],
						state[4],
						state[4],
						state[5],
						(state[5]>>1) & 1,
						state[5] & 1);
			regterm.printString(str);

			// Show zero page contents
			zpterm.setTextColor(sf::Color::Cyan);
			zpterm.printString("\r\n----: -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F");
			zpterm.setTextColor(sf::Color::White);
			for(int i = 0; i < 16; i++)
			{
				uint8_t d;
				zpterm.printString("\r\n");
				sprintf(str, "%04X: ", (uint16_t)(i * 16));
				zpterm.printString(str);
				for(int j = 0; j < 16; j++)
				{
					d = MemoryRead(i*16 + j);
					if (j == 15)
						sprintf(str,"%02X",d);
					else
						sprintf(str,"%02X,",d);
					if(i*16 + j >= 0x5C && i*16+j < 0x5C+ 0x27)
						zpterm.setTextColor(sf::Color::Green);
					zpterm.printString(str);
					zpterm.setTextColor(sf::Color::White);
				}
				for(int j = 0; j < 16; j++)
				{
					d = MemoryRead(i*16 + j);
					if (d < ' ')
					{
						d = ' ';
					}
					if(i*16 + j >= 0x5C && i*16+j < 0x5C+ 0x27)
						zpterm.setTextColor(sf::Color::Green);
					zpterm.Write(d);
					zpterm.setTextColor(sf::Color::Blue);
					zpterm.Write(ctile);
					zpterm.setTextColor(sf::Color::White);
				}
				zpterm.setTextColor(sf::Color::Blue);
				for(int i = 0; i< 86; i++)
					zpterm.Write(177);
				zpterm.setTextColor(sf::Color::White);
			}
		}

		// Update the screen
		window.clear();
		dbgwindow.clear();
		zpwindow.clear();
		net.update();
		term.update();
		dbgterm.update();
		dasmterm.update();
		zpterm.update();
		regterm.update();
		window.draw(term);
		dbgwindow.draw(dbgterm);
		zpwindow.draw(zpterm);
		//if(HALT)
		//{
			dbgwindow.draw(dasmterm);
			dbgwindow.draw(regterm);
		//}
		window.display();
		dbgwindow.display();
		zpwindow.display();
	}
	return 0;
}