-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
194 lines (153 loc) · 4.33 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//File: main.cpp
//Author: Nicholas J D Dean
//Date Created: 2017-01-27
#include <iostream>
#include <cmath>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "chip8.h"
const int PIXEL_SIZE = 13, //chip8 pixel side length in pixels
WIDTH = 64, //width in chip8 pixels
HEIGHT = 32, //height in chip8 pixels
NUM_PIXELS = WIDTH * HEIGHT; //num of chip8 pixels
const int SAMPLES = 44100, //1s
SAMPLE_RATE = 44100; //44.1KHz
typedef sf::RectangleShape display[NUM_PIXELS];
sf::Keyboard::Key keyMap[] = //used to map all of the keys to an index
{
sf::Keyboard::Num1, sf::Keyboard::Num2, sf::Keyboard::Num3,
sf::Keyboard::Num4,
sf::Keyboard::Q, sf::Keyboard::W, sf::Keyboard::E, sf::Keyboard::R,
sf::Keyboard::A, sf::Keyboard::S, sf::Keyboard::D, sf::Keyboard::F,
sf::Keyboard::Z, sf::Keyboard::X, sf::Keyboard::C, sf::Keyboard::V
};
bool keyPressed[16] = {false}; //tracks the state of all keys in keyMap
//fills the given array with a full sine wave
void fillWithSamples(sf::Int16 (&raw)[SAMPLES]) //output
{
float TWO_PI = 3.1415926535f * 2.0f,
AMP = 30000.0f,
increment = 600.0f / SAMPLE_RATE,
x = 0.0f;
for(int i = 0; i < SAMPLES; i++)
{
raw[i] = AMP * sin(x * TWO_PI);
x += increment;
}
}
//initialise the size, position and colour of all the rectnagles
//representing pixels on the screen
void initScreen(display &d)
{
for(int i = 0; i < NUM_PIXELS; i++)
{
d[i].setSize(sf::Vector2f(PIXEL_SIZE, PIXEL_SIZE));
d[i].setPosition((i % WIDTH) * PIXEL_SIZE,
(i / WIDTH) * PIXEL_SIZE);
d[i].setFillColor(sf::Color(0, 0, 0));
}
}
inline void updateScreen(display &d, bool *newDisplay)
{
//update all pixel colours
for(int i = 0; i < NUM_PIXELS; i++)
{
//CAREFUL: assuming size of newDisplay is
//NUM_PIXELS
if(newDisplay[i])
{
d[i].setFillColor(sf::Color::White);
}
else
{
d[i].setFillColor(sf::Color::Black);
}
}
}
int main(int argc, char *argv[])
{
Chip8 chip; //the emulator
int window_width = WIDTH * PIXEL_SIZE,
window_height = HEIGHT * PIXEL_SIZE;
sf::Clock clock, cycleClock; //for timing decTimers() and clock speed
sf::SoundBuffer soundBuff; //to load the samples
sf::Int16 rawSamples[SAMPLES]; //will hold the sine wave for the sound
sf::RectangleShape pixels[NUM_PIXELS]; //all the rectangles that represent pixels
sf::Sound sound; //to play and pause the sound
fillWithSamples(rawSamples);
soundBuff.loadFromSamples(rawSamples, SAMPLES, 1, SAMPLE_RATE);
sound.setBuffer(soundBuff);
sound.setLoop(true);
sf::RenderWindow window(sf::VideoMode(window_width, window_height),
"Fydrechip",
sf::Style::Titlebar | sf::Style::Close);
//use first command line argument as rom path
chip.loadRom(argv[1]);
initScreen(pixels);
std::cout << "\nWelcome to FydreChip!\n";
std::cout << "Press <F5> to reset.\n";
std::cout << "---------------------\n";
//main window loop
while(window.isOpen())
{
sf::Event event;
//print the cycle time
std::cout << "\rLast cycle time (ms): "
<< cycleClock.getElapsedTime().asMilliseconds();
cycleClock.restart();
//poll the window's events
while(window.pollEvent(event))
{
if(event.type == sf::Event::Closed)
{
window.close();
}
}
//poll keyboard for reset key
if(sf::Keyboard::isKeyPressed(sf::Keyboard::F5))
{
chip.hardReset();
chip.loadRom(argv[1]);
}
window.clear(sf::Color::Black);
//update the screen if there has been a draw
//by the emulator
if(chip.drawFlag())
{
updateScreen(pixels, chip.getDisplay());
}
//start or stop the sound
chip.soundFlag() ? sound.play() : sound.pause();
//draw all pixels
for(int i = 0; i < NUM_PIXELS; i++)
{
window.draw(pixels[i]);
}
//update key states
for(int i = 0; i < 0x10; ++i)
{
if(sf::Keyboard::isKeyPressed(keyMap[i]))
{
keyPressed[i] = true;
}
else
{
keyPressed[i] = false;
}
}
//send key states to emulator
chip.setKeys(keyPressed);
//emulate next cycle
chip.runSingleCycle();
//decrement timers at 60Hz
if(clock.getElapsedTime() >= sf::milliseconds(1000/60))
{
chip.decTimers();
clock.restart();
}
window.display();
}
std::cout << std::endl;
return 0;
}