diff --git a/CMakeLists.txt b/CMakeLists.txt index 60aa618..6a2d091 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,8 @@ project(EmuEngine) set(SOURCE_FILES src/main.cpp src/window/window.cpp + src/window/audio.cpp + src/window/renderer.cpp src/emulators/bytepusher/bytepusher.cpp ) diff --git a/src/emulators/bytepusher/bytepusher.cpp b/src/emulators/bytepusher/bytepusher.cpp index a8926b1..c0fecc4 100644 --- a/src/emulators/bytepusher/bytepusher.cpp +++ b/src/emulators/bytepusher/bytepusher.cpp @@ -3,11 +3,9 @@ // Sets surface pixel void set_pixel(SDL_Surface *surface, int x, int y, uint32_t pixel) { - uint32_t *const target_pixel = (Uint32*)( - (Uint8*) surface -> pixels + y * surface -> pitch - + x * surface->format->BytesPerPixel); - *target_pixel = pixel; -} + uint32_t *const target_pixel = (uint32_t*)((uint8_t*) surface -> pixels + y * surface -> pitch + x * surface->format->BytesPerPixel); + *target_pixel = pixel; +} // Get value from the memory uint32_t BytePusherEmu::getVal(uint32_t pc, uint32_t length) @@ -36,6 +34,9 @@ BytePusherEmu::BytePusherEmu() // These pixels are black for(int i = 216; i <= 255; i++) pallete[i] = 0xFF000000; + + // Init sound + sound = new Audio(); } void BytePusherEmu::load(std::string path) @@ -104,11 +105,14 @@ void BytePusherEmu::updateKey(SDL_Keycode key, int value) void BytePusherEmu::input(SDL_Event event) { - // Set or unset keys - if(event.type == SDL_KEYDOWN) - updateKey(event.key.keysym.sym, 1); - else if(event.type == SDL_KEYUP) - updateKey(event.key.keysym.sym, 0); + if(!isQuit) + { + // Set or unset keys + if(event.type == SDL_KEYDOWN) + updateKey(event.key.keysym.sym, 1); + else if(event.type == SDL_KEYUP) + updateKey(event.key.keysym.sym, 0); + } } void BytePusherEmu::innerLoop() @@ -147,6 +151,9 @@ void BytePusherEmu::update(float dt) set_pixel(result, i, j, pallete[frame[(j << 8) | i]]); } + // Push audio section to the sound engine + sound -> push((int8_t*)(memory + (getVal(6, 2) << 8)), 256); + // 60 Hz, forced counter -= 1.0 / 60; } @@ -158,6 +165,6 @@ void BytePusherEmu::draw(Window* win) if(!isQuit) { // Copy the surface to the screen - SDL_BlitSurface(result, NULL, win -> getSurface(), NULL); + win -> getRenderer() -> render(result); } } \ No newline at end of file diff --git a/src/emulators/bytepusher/bytepusher.h b/src/emulators/bytepusher/bytepusher.h index a22bb45..214556d 100644 --- a/src/emulators/bytepusher/bytepusher.h +++ b/src/emulators/bytepusher/bytepusher.h @@ -2,6 +2,7 @@ #define BYTEPUSHER_H #include "../emulator.h" +#include "../../window/audio.h" #include "../../window/window.h" #include #include @@ -22,6 +23,7 @@ class BytePusherEmu : public UnthreadedEmulator // Output SDL_Surface* result = SDL_CreateRGBSurface(0, 256, 256, 32, 0, 0, 0, 0); uint32_t pallete[256]; + Audio* sound; // Input SDL_Keycode keys[0x10] = { diff --git a/src/main.cpp b/src/main.cpp index d124c12..c694b63 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,14 +45,15 @@ int main(int argc, char* argv[]) // Update the emu emu -> update(window -> getDelta()); - emu -> draw(window); // If emu stopped, close everything if(!emu -> isRunning()) window -> quit(); // Update the window - SDL_UpdateWindowSurface(window -> getWin()); + window -> getRenderer() -> drawStart(); + emu -> draw(window); + window -> getRenderer() -> drawEnd(); // Wait a bit so CPU usage is not high SDL_Delay(2); diff --git a/src/window/audio.cpp b/src/window/audio.cpp new file mode 100644 index 0000000..513ab8e --- /dev/null +++ b/src/window/audio.cpp @@ -0,0 +1,22 @@ +#include "audio.h" + +Audio::Audio() +{ + if(SDL_Init(SDL_INIT_AUDIO) < 0) + printf("{E}: Audio init failed! %s", SDL_GetError()); + + SDL_zero(wanted); + wanted.freq = 15360; + wanted.samples = 256; + wanted.format = AUDIO_S8; + wanted.channels = 1; + + SDL_OpenAudio(&wanted, NULL); + + SDL_PauseAudio(0); +} + +void Audio::push(int8_t* where, int32_t size) +{ + SDL_QueueAudio(1, where, size); +} \ No newline at end of file diff --git a/src/window/audio.h b/src/window/audio.h new file mode 100644 index 0000000..81d5a5d --- /dev/null +++ b/src/window/audio.h @@ -0,0 +1,16 @@ +#ifndef AUDIO_H +#define AUDIO_H + +#include +#include + +class Audio +{ +private: + SDL_AudioSpec wanted; +public: + Audio(); + void push(int8_t *from, int32_t size); +}; + +#endif \ No newline at end of file diff --git a/src/window/renderer.cpp b/src/window/renderer.cpp new file mode 100644 index 0000000..3a10829 --- /dev/null +++ b/src/window/renderer.cpp @@ -0,0 +1,35 @@ +#include "renderer.h" + +void SoftwareRenderer::drawStart() +{ + SDL_FillRect(SDL_GetWindowSurface(parentWin), NULL, 0x000000); +} + +void SoftwareRenderer::render(SDL_Surface* surf) +{ + SDL_BlitSurface(surf, NULL, SDL_GetWindowSurface(parentWin), NULL); +} + +void SoftwareRenderer::drawEnd() +{ + SDL_UpdateWindowSurface(parentWin); +} + +void AcceleratedRenderer::render(SDL_Surface* surf) +{ + SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surf); + + SDL_RenderCopy(renderer, texture, NULL, NULL); + + SDL_DestroyTexture(texture); +} + +void AcceleratedRenderer::drawStart() +{ + SDL_RenderClear(renderer); +} + +void AcceleratedRenderer::drawEnd() +{ + SDL_RenderPresent(renderer); +} \ No newline at end of file diff --git a/src/window/renderer.h b/src/window/renderer.h new file mode 100644 index 0000000..e872920 --- /dev/null +++ b/src/window/renderer.h @@ -0,0 +1,44 @@ +#ifndef RENDERER_H +#define RENDERER_H + +#include +#include + +class Renderer +{ +protected: + SDL_Window* parentWin = NULL; +public: + Renderer(SDL_Window* win){ + parentWin = win; + } + virtual void render(SDL_Surface* surf) = 0; + virtual void drawStart() = 0; + virtual void drawEnd() = 0; +}; + +class SoftwareRenderer : public Renderer +{ +public: + void render(SDL_Surface* surf) override; + void drawStart() override; + void drawEnd() override; + SoftwareRenderer(SDL_Window* win) : Renderer(win) {}; +}; + +class AcceleratedRenderer : public Renderer +{ +private: + SDL_Renderer* renderer = nullptr; +public: + void render(SDL_Surface* surf) override; + void drawStart() override; + void drawEnd() override; + AcceleratedRenderer(SDL_Window* win) : Renderer(win) { + renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if(renderer == nullptr) + printf("{E}: SDL_CreateRenderer Error: %s\n", SDL_GetError()); + } +}; + +#endif \ No newline at end of file diff --git a/src/window/window.cpp b/src/window/window.cpp index e8c3ce3..dfc4408 100644 --- a/src/window/window.cpp +++ b/src/window/window.cpp @@ -10,6 +10,8 @@ Window::Window() window = SDL_CreateWindow("EmuEngine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 256, 256, 0); + renderer = new SoftwareRenderer(window); + deltaTime = 0; NOW = SDL_GetPerformanceCounter(); LAST = 0; @@ -20,6 +22,11 @@ SDL_Window* Window::getWin() return window; } +Renderer* Window::getRenderer() +{ + return renderer; +} + SDL_Surface* Window::getSurface() { return SDL_GetWindowSurface(window); diff --git a/src/window/window.h b/src/window/window.h index 3476a6e..d953b67 100644 --- a/src/window/window.h +++ b/src/window/window.h @@ -4,6 +4,7 @@ #include #include #include +#include "renderer.h" class Window { @@ -12,6 +13,7 @@ class Window double deltaTime; SDL_Window* window = NULL; bool appQuit = false; + Renderer* renderer; public: Window(); @@ -21,6 +23,7 @@ class Window void quit(); void setTitle(std::string name = "EmuEngine"); SDL_Surface* getSurface(); + Renderer* getRenderer(); SDL_Window* getWin(); };