yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
emu.cc
Go to the documentation of this file.
1#if __APPLE__
3#endif
4
5#include <SDL.h>
6
7#include <memory>
8#include <string>
9#include <vector>
10
11#include "absl/debugging/failure_signal_handler.h"
12#include "absl/debugging/symbolize.h"
13#include "absl/status/status.h"
15#include "app/emu/snes.h"
16#include "app/rom.h"
17
19
20int main(int argc, char **argv) {
21 absl::InitializeSymbolizer(argv[0]);
22
23 absl::FailureSignalHandlerOptions options;
24 options.symbolize_stacktrace = true;
25 options.alarm_on_failure_secs = true;
26 absl::InstallFailureSignalHandler(options);
27
28 SDL_SetMainReady();
29
30 std::unique_ptr<SDL_Window, SDL_Deleter> window_;
31 std::unique_ptr<SDL_Renderer, SDL_Deleter> renderer_;
32 if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
33 return EXIT_FAILURE;
34 } else {
35 SDL_DisplayMode displayMode;
36 SDL_GetCurrentDisplayMode(0, &displayMode);
37 window_ = std::unique_ptr<SDL_Window, SDL_Deleter>(
38 SDL_CreateWindow("Yaze Emulator", // window title
39 SDL_WINDOWPOS_UNDEFINED, // initial x position
40 SDL_WINDOWPOS_UNDEFINED, // initial y position
41 512, // width, in pixels
42 480, // height, in pixels
43 SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI),
44 SDL_Deleter());
45 if (window_ == nullptr) {
46 return EXIT_FAILURE;
47 }
48 }
49
50 renderer_ = std::unique_ptr<SDL_Renderer, SDL_Deleter>(
51 SDL_CreateRenderer(window_.get(), -1,
52 SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
53 SDL_Deleter());
54 if (renderer_ == nullptr) {
55 return EXIT_FAILURE;
56 } else {
57 SDL_SetRenderDrawBlendMode(renderer_.get(), SDL_BLENDMODE_BLEND);
58 SDL_SetRenderDrawColor(renderer_.get(), 0x00, 0x00, 0x00, 0x00);
59 }
60
61 int audio_frequency_ = 48000;
62 SDL_AudioSpec want, have;
63 SDL_memset(&want, 0, sizeof(want));
64 want.freq = audio_frequency_;
65 want.format = AUDIO_S16;
66 want.channels = 2;
67 want.samples = 2048;
68 want.callback = NULL; // Uses the queue
69 auto audio_device_ = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
70 if (audio_device_ == 0) {
71 return EXIT_FAILURE;
72 }
73 auto audio_buffer_ = new int16_t[audio_frequency_ / 50 * 4];
74 SDL_PauseAudioDevice(audio_device_, 0);
75
76#ifdef __APPLE__
77 yaze_initialize_cocoa();
78#endif
79
80 auto ppu_texture_ =
81 SDL_CreateTexture(renderer_.get(), SDL_PIXELFORMAT_RGBX8888,
82 SDL_TEXTUREACCESS_STREAMING, 512, 480);
83 if (ppu_texture_ == NULL) {
84 printf("Failed to create texture: %s\n", SDL_GetError());
85 return EXIT_FAILURE;
86 }
87
88 yaze::Rom rom_;
89 yaze::emu::Snes snes_;
90 std::vector<uint8_t> rom_data_;
91
92 bool running = true;
93 bool loaded = false;
94 auto count_frequency = SDL_GetPerformanceFrequency();
95 auto last_count = SDL_GetPerformanceCounter();
96 auto time_adder = 0.0;
97 int wanted_frames_ = 0;
98 int wanted_samples_ = 0;
99 SDL_Event event;
100
101 if (!rom_.LoadFromFile("inidisp_hammer_0f00.sfc").ok()) {
102 return EXIT_FAILURE;
103 }
104
105 if (rom_.is_loaded()) {
106 rom_data_ = rom_.vector();
107 snes_.Init(rom_data_);
108 wanted_frames_ = 1.0 / (snes_.Memory().pal_timing() ? 50.0 : 60.0);
109 wanted_samples_ = 48000 / (snes_.Memory().pal_timing() ? 50 : 60);
110 loaded = true;
111 }
112
113 while (running) {
114 while (SDL_PollEvent(&event)) {
115 switch (event.type) {
116 case SDL_DROPFILE:
117 rom_.LoadFromFile(event.drop.file);
118 if (rom_.is_loaded()) {
119 rom_data_ = rom_.vector();
120 snes_.Init(rom_data_);
121 wanted_frames_ = 1.0 / (snes_.Memory().pal_timing() ? 50.0 : 60.0);
122 wanted_samples_ = 48000 / (snes_.Memory().pal_timing() ? 50 : 60);
123 loaded = true;
124 }
125 SDL_free(event.drop.file);
126 break;
127 case SDL_KEYDOWN:
128 break;
129 case SDL_KEYUP:
130 break;
131 case SDL_WINDOWEVENT:
132 switch (event.window.event) {
133 case SDL_WINDOWEVENT_CLOSE:
134 running = false;
135 break;
136 case SDL_WINDOWEVENT_SIZE_CHANGED:
137 break;
138 default:
139 break;
140 }
141 break;
142 default:
143 break;
144 }
145 }
146
147 uint64_t current_count = SDL_GetPerformanceCounter();
148 uint64_t delta = current_count - last_count;
149 last_count = current_count;
150 float seconds = delta / (float)count_frequency;
151 time_adder += seconds;
152 // allow 2 ms earlier, to prevent skipping due to being just below wanted
153 while (time_adder >= wanted_frames_ - 0.002) {
154 time_adder -= wanted_frames_;
155
156 if (loaded) {
157 snes_.RunFrame();
158
159 snes_.SetSamples(audio_buffer_, wanted_samples_);
160 if (SDL_GetQueuedAudioSize(audio_device_) <= wanted_samples_ * 4 * 6) {
161 SDL_QueueAudio(audio_device_, audio_buffer_, wanted_samples_ * 4);
162 }
163
164 void *ppu_pixels_;
165 int ppu_pitch_;
166 if (SDL_LockTexture(ppu_texture_, NULL, &ppu_pixels_, &ppu_pitch_) !=
167 0) {
168 printf("Failed to lock texture: %s\n", SDL_GetError());
169 return EXIT_FAILURE;
170 }
171 snes_.SetPixels(static_cast<uint8_t *>(ppu_pixels_));
172 SDL_UnlockTexture(ppu_texture_);
173 }
174 }
175
176 SDL_RenderClear(renderer_.get());
177 SDL_RenderCopy(renderer_.get(), ppu_texture_, NULL, NULL);
178 SDL_RenderPresent(renderer_.get()); // should vsync
179 }
180
181 SDL_PauseAudioDevice(audio_device_, 1);
182 SDL_CloseAudioDevice(audio_device_);
183 delete[] audio_buffer_;
184 //ImGui_ImplSDLRenderer2_Shutdown();
185 //ImGui_ImplSDL2_Shutdown();
186 //ImGui::DestroyContext();
187 SDL_Quit();
188
189 return EXIT_SUCCESS;
190}
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:59
absl::Status LoadFromFile(const std::string &filename, bool z3_load=true)
Definition rom.cc:173
auto vector() const
Definition rom.h:169
bool is_loaded() const
Definition rom.h:154
void SetSamples(int16_t *sample_data, int wanted_samples)
Definition snes.cc:537
void RunFrame()
Definition snes.cc:80
auto Memory() -> MemoryImpl &
Definition snes.h:60
void Init(std::vector< uint8_t > &rom_data)
Definition snes.cc:28
void SetPixels(uint8_t *pixel_data)
Definition snes.cc:541
int main(int argc, char **argv)
Definition emu.cc:20
Deleter for SDL_Window and SDL_Renderer.
Definition sdl_deleter.h:12