-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchip8.c
150 lines (119 loc) · 2.82 KB
/
chip8.c
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
#include "chip8.h"
#include <sys/time.h>
#include <stddef.h>
#include <stdbool.h>
typedef struct {
u8* data;
size_t size;
} Chip8__Rom__;
static Chip8__Rom__
Chip8__load_rom__(Chip8* self, String rom_path);
static u64
__time_ms__(void);
static void
Chip8__on_quit__(void* arg);
Chip8
Chip8_init(String rom_path, u8 screen_scale, u8 speed)
{
Chip8 chip8 = {};
chip8.fps = 60;
chip8.fps_interval = 1000 / chip8.fps;
chip8.is_running = true;
u64 start_time = __time_ms__();
chip8.past_time = chip8.start_time;
chip8.now = chip8.start_time;
chip8.keyboard = malloc(sizeof(Keyboard));
chip8.renderer = malloc(sizeof(Renderer));
chip8.speaker = malloc(sizeof(Speaker));
if(!chip8.keyboard || !chip8.renderer || !chip8.speaker)
{
chip8.valid = false;
return chip8;
}
*chip8.keyboard = Keyboard_init();
*chip8.renderer = Renderer_init(screen_scale);
*chip8.speaker = Speaker_init();
chip8.cpu = Cpu_init(chip8.renderer, chip8.keyboard, chip8.speaker, speed);
Chip8__Rom__ rom = Chip8__load_rom__(&chip8, rom_path);
Cpu_load_program(&chip8.cpu, rom.data, rom.size);
free(rom.data);
chip8.valid = true;
return chip8;
}
void
Chip8_mainloop(Chip8* self)
{
while(!self->keyboard->quit_pressed)
{
Cpu_cycle(&self->cpu);
SDL_Delay(self->fps_interval);
}
}
void
Chip8_deinit(Chip8* self)
{
if(!self)
{
return;
}
Keyboard_deinit(self->keyboard);
Renderer_deinit(self->renderer);
Speaker_deinit(self->speaker);
free(self->keyboard);
free(self->renderer);
free(self->speaker);
// Clean up SDL2 and exit the program
SDL_Quit();
}
// Private functions
static u64
__time_ms__(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (((u64)tv.tv_sec) * 1000) + (tv.tv_usec / 1000);
}
void
Chip8__on_quit__(void* arg)
{
if(arg == NULL)
{
puts("ylahwaaaaaaaay");
}
((Chip8*)arg)->is_running = false;
}
Chip8__Rom__
Chip8__load_rom__(Chip8* self, String rom_path)
{
Chip8__Rom__ rom = {};
if(rom_path.len == 0)
{
fputs("Error: CPU: error loading rom_file", stderr);
abort();
}
FILE* rom_file = fopen(rom_path.data, "rb");
if(!rom_file)
{
fprintf(stderr, "Couldn't open %s\n", rom_path.data);
abort();
}
// obtain file size:
fseek (rom_file , 0 , SEEK_END);
rom.size = ftell (rom_file);
rewind (rom_file);
// allocate memory to contain the whole file:
rom.data = (u8*) malloc (sizeof(char) * rom.size);
if (rom.data == NULL)
{
fputs("Couldn't allocate memory for the program", stderr);
abort();
}
rom.size = fread(
rom.data,
sizeof(u8),
rom.size,
rom_file
);
fclose(rom_file);
return rom;
}