-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain_tron.cpp
134 lines (112 loc) · 4.16 KB
/
main_tron.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
// Modified From Project F: FPGA Pong - Pong Game Verilator C++
// (C)2023 Will Green, open source software released under the MIT License
// Learn more at https://projectf.io/posts/fpga-pong/
#include <stdio.h>
#include <SDL.h>
#include <verilated.h>
#include "Vtop_tron.h" // generated by Verilator
// screen dimensions
const int H_RES = 640;
const int V_RES = 480;
typedef struct Pixel { // for SDL texture
uint8_t a; // transparency
uint8_t b; // blue
uint8_t g; // green
uint8_t r; // red
} Pixel;
int main(int argc, char* argv[]) {
Verilated::commandArgs(argc, argv);
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL init failed.\n");
return 1;
}
Pixel screenbuffer[H_RES*V_RES];
SDL_Window* sdl_window = NULL;
SDL_Renderer* sdl_renderer = NULL;
SDL_Texture* sdl_texture = NULL;
sdl_window = SDL_CreateWindow("Tron", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, H_RES, V_RES, SDL_WINDOW_SHOWN);
if (!sdl_window) {
printf("Window creation failed: %s\n", SDL_GetError());
return 1;
}
sdl_renderer = SDL_CreateRenderer(sdl_window, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (!sdl_renderer) {
printf("Renderer creation failed: %s\n", SDL_GetError());
return 1;
}
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_TARGET, H_RES, V_RES);
if (!sdl_texture) {
printf("Texture creation failed: %s\n", SDL_GetError());
return 1;
}
// reference SDL keyboard state array: https://wiki.libsdl.org/SDL_GetKeyboardState
const Uint8 *keyb_state = SDL_GetKeyboardState(NULL);
printf("Simulation running. Press 'Q' in simulation window to quit.\n\n");
// initialize Verilog module
Vtop_tron* top = new Vtop_tron;
// reset
top->sim_rst = 1;
top->clk_pix = 0;
top->eval();
top->clk_pix = 1;
top->eval();
top->sim_rst = 0;
top->clk_pix = 0;
top->eval();
uint64_t frame_count = 0;
uint64_t start_ticks = SDL_GetPerformanceCounter();
while (1) {
// cycle the clock
top->clk_pix = 1;
top->eval();
top->clk_pix = 0;
top->eval();
// update pixel if not in blanking interval
if (top->sdl_de) {
Pixel* p = &screenbuffer[top->sdl_sy*H_RES + top->sdl_sx];
p->a = 0xFF; // transparency
p->b = top->sdl_b;
p->g = top->sdl_g;
p->r = top->sdl_r;
}
// update texture and keyboard input once per frame (in blanking)
if (top->sdl_sy == V_RES && top->sdl_sx == 0) {
// check for quit event
SDL_Event e;
if (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
break;
}
}
if (keyb_state[SDL_SCANCODE_Q]) break; // quit if user presses 'Q'
// update keyboard state
top->btn_right_p1 = keyb_state[SDL_SCANCODE_D];
top->btn_left_p1 = keyb_state[SDL_SCANCODE_A];
top->btn_up_p1 = keyb_state[SDL_SCANCODE_W];
top->btn_down_p1 = keyb_state[SDL_SCANCODE_S];
top->btn_right_p2 = keyb_state[SDL_SCANCODE_RIGHT];
top->btn_left_p2 = keyb_state[SDL_SCANCODE_LEFT];
top->btn_up_p2 = keyb_state[SDL_SCANCODE_UP];
top->btn_down_p2 = keyb_state[SDL_SCANCODE_DOWN];
top->btn_start = keyb_state[SDL_SCANCODE_SPACE];
SDL_UpdateTexture(sdl_texture, NULL, screenbuffer, H_RES*sizeof(Pixel));
SDL_RenderClear(sdl_renderer);
SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
SDL_RenderPresent(sdl_renderer);
frame_count++;
}
}
uint64_t end_ticks = SDL_GetPerformanceCounter();
double duration = ((double)(end_ticks-start_ticks))/SDL_GetPerformanceFrequency();
double fps = (double)frame_count/duration;
printf("Frames per second: %.1f\n", fps);
top->final(); // simulation done
SDL_DestroyTexture(sdl_texture);
SDL_DestroyRenderer(sdl_renderer);
SDL_DestroyWindow(sdl_window);
SDL_Quit();
return 0;
}