/*
CHIP-8 example using Wokwi TV (Analog PAL TV screen)
by Anderson Costa with ❤ for the Wokwi community
Visit https://wokwi.com to learn about the Wokwi Simulator
*/
#include <TVout.h>
#define DEBUG 0 // Enable debug
FILE serial_stdout;
extern "C" {
// Used by the printf function
int serial_putchar(char c, FILE* f) {
if (c == '\n') serial_putchar('\r', f);
return Serial.write(c) == 1 ? 0 : 1;
}
}
// Display settings
#define SCREEN_WIDTH 64
#define SCREEN_HEIGHT 32
#define MARGIN_LEFT 30
#define MARGIN_TOP 10
#define SCREEN_SCALE 2
#define BUZZER_PIN 11
#define BUTTON_PIN A4
#include "chip8.h"
#include "roms.h"
// Keypad pin settings
const uint8_t rowPins[KEY_ROWS] = { 5, 4, 3, 2 };
const uint8_t colPins[KEY_COLS] = { 17, 16, 15, 14 };
Chip8 chip8(rowPins, colPins);
// TVout size - 120 x 96 original size
const uint8_t displayWidth = (SCREEN_WIDTH * 2) - 8;
const uint8_t displayHeight = (SCREEN_WIDTH + SCREEN_HEIGHT) / 2;
TVout tv;
void setup() {
Serial.begin(9600);
// Set stdout stream
fdev_setup_stream(&serial_stdout, serial_putchar, NULL, _FDEV_SETUP_WRITE);
stdout = &serial_stdout;
pinMode(BUZZER_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT);
tv.begin(PAL, displayWidth, displayHeight);
tv.clear_screen();
// Load ROM game
if (!chip8.load(CHIP_8_PIC, CHIP_8_SIZE))
return 1;
// CHIP-8 Intro
uint8_t count = 0;
do {
count++;
chip8.cycle();
if (chip8.drawFlag)
draw(); // Draw on the screen
} while (count < CHIP_8_SIZE);
tv.clear_screen();
// Load ROM game
if (!chip8.load(MISSILE, MISSILE_SIZE))
return 1;
}
void loop() {
chip8.cycle();
chip8.getKeyPressed(); // Check if any key was pressed
if (chip8.drawFlag)
draw(); // Draw on the screen
}
void draw() {
#if DEBUG
chip8.debugRender();
#else
// Draw on the screen
for (uint8_t y = 0; y < SCREEN_HEIGHT; ++y) {
for (uint8_t x = 0; x < SCREEN_WIDTH; ++x) {
if (chip8.screen[(y * SCREEN_WIDTH) + x] != 0) {
tv.set_pixel(x + MARGIN_LEFT, y + MARGIN_TOP, WHITE);
}
}
}
#endif
}