Skip to content

Commit

Permalink
Merge pull request #52 from esp-cpp/feature/sms
Browse files Browse the repository at this point in the history
Sega Master System / Game Gear support via SMSPlus
  • Loading branch information
finger563 committed Jan 7, 2024
2 parents d4f2d5f + 8e2fab2 commit f9f4723
Show file tree
Hide file tree
Showing 102 changed files with 19,817 additions and 687 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/static_analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ jobs:
esp_idf_version: release/v5.2

# (Optional) cppcheck args
cppcheck_args: -i$GITHUB_WORKSPACE/lib -i$GITHUB_WORKSPACE/components/gbc/gnuboy -i$GITHUB_WORKSPACE/components/nes/nofrendo -i$GITHUB_WORKSPACE/components/gui/generated -i$GITHUB_WORKSPACE/components/menu/generated -i$GITHUB_WORKSPACE/components/jpegdec -i$GITHUB_WORKSPACE/components/codec -i$GITHUB_WORKSPACE/components/espp --force --enable=all --inline-suppr --inconclusive --platform=mips32 --suppressions-list=$GITHUB_WORKSPACE/suppressions.txt
cppcheck_args: -i$GITHUB_WORKSPACE/lib -i$GITHUB_WORKSPACE/components/gbc/gnuboy -i$GITHUB_WORKSPACE/components/nes/nofrendo -i$GITHUB_WORKSPACE/components/sms/smsplus -i$GITHUB_WORKSPACE/components/gui/generated -i$GITHUB_WORKSPACE/components/menu/generated -i$GITHUB_WORKSPACE/components/jpegdec -i$GITHUB_WORKSPACE/components/codec -i$GITHUB_WORKSPACE/components/espp --force --enable=all --inline-suppr --inconclusive --platform=mips32 --suppressions-list=$GITHUB_WORKSPACE/suppressions.txt
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ set(NES_COMPONENTS "nes")
set(GBC_COMPONENTS "gbc")

### SMS ###
# set(SMS_COMPONENTS "sms")
set(SMS_COMPONENTS "sms")

### SNES ###
# set(SNES_COMPONENTS "snes")
Expand Down
20 changes: 9 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# esp-box-emu


<table style="padding:10px">
<tr>
<td><img src="./logo/logo.jpeg" alt="Logo" width="250" height="250"></td>
Expand Down Expand Up @@ -59,17 +58,17 @@ This project has the following features (still WIP):

- [x] Squareline Studio design files for generating boilerplate LVGL ([SLS files](./squareline), [Generated files](./components/gui/generated))
- [x] LVGL gui for selecting emulators / roms (showing boxart and name)
- [x] LVGL gui for controlling settings (such as volume, video, haptics) (using [gui component](./components/gui))
- [x] LVGL gui for controlling settings (such as volume, video, haptics)
- [x] Loading of gui data (rom titles and boxart) from metadata file (example [here](./metadata.csv))
- [x] Audio output (using I2S + es8311 audio codec, [es8311 component](./components/codec))
- [x] Interaction with d-pad + buttons (using [controller component](./components/controller))
- [x] User input with d-pad + buttons (a/b/x/y, start/select) (using MCP23x17 [v0 hardware] or AW9523 [v1 hardware])
- [x] Interaction with touchscreen (using [tt21100 component](./components/tt21100))
- [x] Navigation of LVGL rom menu with controller (up,down,start)
- [x] Runnable emulators (automatically selected by rom extension):
- [x] NES emulator (~100 FPS running Legend of Zelda)
- [x] GB/GBC emulator (~100 FPS running Link's Awakening DX (GBC))
- [x] NES emulator
- [x] GB/GBC emulator
- [x] Sega Master System (SMS) / GameGear (GG) emulator
- [ ] MSX emulator (WIP)
- [ ] Sega Master System (SMS) / GameGear (GG) emulator (WIP)
- [ ] Sega Mega Drive / Genesis emulator (WIP)
- [ ] SNES emulator
- [ ] Doom emulator (WIP)
Expand All @@ -79,12 +78,11 @@ This project has the following features (still WIP):
(SPIFLASH)
- [X] Emulator framebuffers on SPIRAM
- [x] Queued transfers of screen data for maximum draw speed while running emulation
- [x] Scaling of GB/GBC display to support original, fit, and fill video scaling modes
- [x] Scaling for NES display to support original (which is fit) and fill video scaling modes
- [x] Scaling of emulator video data to support ORIGINAL, FIT, and FILL modes of display data to screen
- [x] Use mute button to toggle volume output while running the roms
- [x] Feedback through tiny haptic motor (DRV2605)
- [x] Save state (with automated save screenshot creation saved to uSD card)
- [x] Load state
- [x] Load state (up to 5 slots per game)
- [x] State management (UI to select state when loading roms, ui/buttons for
saving/loading states while running, and displaying save screenshots)
- [x] Schematic / Layout for control board peripheral containing
Expand All @@ -101,7 +99,7 @@ This project has the following features (still WIP):
- [x] start / select buttons (same location as GBC)
- [x] ABXY buttons (basically same size / location as GBC)
- [x] Directional Pad (same size / location as GBC)
- [ ] Use same audio + video tasks for both NES and GB/C emulation
- [x] Use same audio + video tasks for all emulators
- [ ] Graphics in black borders next to rom display during NES / GB/C emulation

## Cloning
Expand All @@ -110,7 +108,7 @@ Since this repo contains a submodule, you need to make sure you clone it
recursively, e.g. with:

``` sh
git clone --recurse-submodules <your repo name>
git clone --recurse-submodules git@github.com:esp-cpp/esp-box-emu
```

Alternatively, you can always ensure the submodules are up to date after cloning
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added boxart/aladdin-gg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added boxart/jurassic-park-gg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added boxart/sonic-the-hedgehog-2-gg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added boxart/sonic-the-hedgehog-2-sms.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added boxart/source/aladdin-gg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added boxart/source/jurassic-park-gg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added boxart/source/sonic-the-hedgehog-2-gg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added boxart/source/sonic-the-hedgehog-2-sms.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions components/box-emu-hal/include/audio_task.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"

#include "format.hpp"
#include "i2s_audio.h"
#include "task.hpp"

namespace hal {
void init_audio_task();
void set_audio_sample_count(size_t count);
void push_audio(const void* audio);
} // namespace hal
8 changes: 5 additions & 3 deletions components/box-emu-hal/include/i2s_audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ extern "C" {
#endif

#define AUDIO_SAMPLE_RATE (32000)
#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_RATE / 3 + 1)
#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_RATE / 5)
#define AUDIO_SAMPLE_COUNT (AUDIO_SAMPLE_RATE / 60)

void audio_init();
int16_t* get_audio_buffer();
void audio_play_frame(uint8_t *data, uint32_t num_bytes);
int16_t* get_audio_buffer0();
// int16_t* get_audio_buffer1();
void audio_play_frame(const uint8_t *data, uint32_t num_bytes);

bool is_muted();
void set_muted(bool mute);
Expand Down
4 changes: 4 additions & 0 deletions components/box-emu-hal/include/statistics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <algorithm>
#include <atomic>

#include "format.hpp"

void update_frame_time(float frame_time);
void reset_frame_time();

Expand All @@ -11,3 +13,5 @@ float get_frame_time();
float get_frame_time_max();
float get_frame_time_min();
float get_frame_time_avg();

void print_statistics();
16 changes: 16 additions & 0 deletions components/box-emu-hal/include/video_task.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"

#include "format.hpp"
#include "spi_lcd.h"
#include "task.hpp"

namespace hal {
void init_video_task();
void set_display_size(size_t width, size_t height);
void set_native_size(size_t width, size_t height, int pitch = -1);
void set_palette(const uint16_t* palette, size_t size = 256);
void push_frame(const void* frame);
} // namespace hal
65 changes: 65 additions & 0 deletions components/box-emu-hal/src/audio_task.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include "audio_task.hpp"

using namespace hal;

static size_t audio_sample_count = 0;
static std::shared_ptr<espp::Task> audio_task_;
static QueueHandle_t audio_queue_;

static bool audio_task(std::mutex &m, std::condition_variable& cv);

void hal::init_audio_task() {
static bool initialized = false;
if (initialized) {
return;
}
// audio_queue_ = xQueueCreate(1, sizeof(uint16_t*));
// audio_task_ = std::make_shared<espp::Task>(espp::Task::Config{
// .name = "audio task",
// .callback = audio_task,
// .stack_size_bytes = 4*1024,
// .priority = 20,
// .core_id = 1
// });
// audio_task_->start();
initialized = true;
}

void hal::set_audio_sample_count(size_t count) {
audio_sample_count = count;
}

void hal::push_audio(const void* audio) {
// if (audio_queue_ == nullptr) {
// fmt::print("audio queue is null, make sure to call init_audio_task() first\n");
// return;
// }
// xQueueSend(audio_queue_, &audio, 10 / portTICK_PERIOD_MS);
// we got a valid audio frame, so let's play it
const uint8_t* audio_ptr = (const uint8_t*)audio;
// multiply by 2 since we're 16-bit
audio_play_frame(audio_ptr, audio_sample_count*2);
}

static bool audio_task(std::mutex &m, std::condition_variable& cv) {
const void *_audio_ptr;
if (xQueuePeek(audio_queue_, &_audio_ptr, 100 / portTICK_PERIOD_MS) != pdTRUE) {
// we couldn't get anything from the queue, return
return false;
}
if (_audio_ptr == nullptr) {
// make sure we clear the queue
xQueueReceive(audio_queue_, &_audio_ptr, 10 / portTICK_PERIOD_MS);
// we got a nullptr, return
return false;
}
// we got a valid audio frame, so let's play it
const uint8_t* audio_ptr = (const uint8_t*)_audio_ptr;
// multiply by 2 since we're 16-bit
audio_play_frame(audio_ptr, audio_sample_count*2);

// we don't have to worry here since we know there was an item in the queue
// since we peeked earlier.
xQueueReceive(audio_queue_, &_audio_ptr, 10 / portTICK_PERIOD_MS);
return false;
}
16 changes: 11 additions & 5 deletions components/box-emu-hal/src/i2s_audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,19 @@ using namespace box_hal;
static i2s_chan_handle_t tx_handle = NULL;
static i2s_chan_handle_t rx_handle = NULL;

static int16_t *audio_buffer;
static int16_t *audio_buffer0;
static int16_t *audio_buffer1;

const std::string mute_button_topic = "mute/pressed";
static std::atomic<bool> muted_{false};
static std::atomic<int> volume_{60};

int16_t *get_audio_buffer() {
return audio_buffer;
int16_t *get_audio_buffer0() {
return audio_buffer0;
}

int16_t *get_audio_buffer1() {
return audio_buffer1;
}

void update_volume_output() {
Expand Down Expand Up @@ -270,7 +275,8 @@ void audio_init() {
es7210_init_default();
es8311_init_default();

audio_buffer = (int16_t*)heap_caps_malloc(AUDIO_BUFFER_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
audio_buffer0 = (int16_t*)heap_caps_malloc(sizeof(int16_t) * AUDIO_BUFFER_SIZE + 10, MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
// audio_buffer1 = (int16_t*)heap_caps_malloc(sizeof(int16_t) * AUDIO_BUFFER_SIZE + 10, MALLOC_CAP_8BIT | MALLOC_CAP_DMA);

// now initialize the mute gpio
init_mute_button();
Expand All @@ -287,7 +293,7 @@ void audio_deinit() {
initialized = false;
}

void audio_play_frame(uint8_t *data, uint32_t num_bytes) {
void audio_play_frame(const uint8_t *data, uint32_t num_bytes) {
size_t bytes_written = 0;
auto err = ESP_OK;
err = i2s_channel_write(tx_handle, data, num_bytes, &bytes_written, 1000);
Expand Down
8 changes: 8 additions & 0 deletions components/box-emu-hal/src/statistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,11 @@ float get_frame_time_min() {
float get_frame_time_avg() {
return frame_time_avg;
}

void print_statistics() {
fmt::print("Statistics:\n");
fmt::print("-----------\n");
fmt::print("Frames: {}\n", num_frames);
fmt::print("FPS: {:.1f}\n", get_fps());
fmt::print("Frame Time: [{:.1f}, {:.1f}, {:.1f}]\n", get_frame_time_min(), get_frame_time_avg(), get_frame_time_max());
}
Loading

0 comments on commit f9f4723

Please sign in to comment.