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