Skip to content

Commit

Permalink
Merge pull request #60 from esp-cpp/feature/genesis
Browse files Browse the repository at this point in the history
Feature/genesis
  • Loading branch information
finger563 committed May 18, 2024
2 parents fedd0d5 + 2971af0 commit 7973ef5
Show file tree
Hide file tree
Showing 81 changed files with 63,513 additions and 53 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/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 --std=c++17 --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/genesis/gwenesis -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 --std=c++17 --suppressions-list=$GITHUB_WORKSPACE/suppressions.txt
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ set(SMS_COMPONENTS "sms")
### MSX ###
# set(MSX_COMPONENTS "msx")

### GENESIS ###
set(GENESIS_COMPONENTS "genesis")

### DOOM ###
# set(DOOM_COMPONENTS "doom")

Expand Down Expand Up @@ -54,6 +57,11 @@ if(MSX_COMPONENTS)
add_compile_definitions(ENABLE_MSX)
endif()

# if GENESIS_COMPONENTS is set, add compile definitions for the GENESIS
if(GENESIS_COMPONENTS)
add_compile_definitions(ENABLE_GENESIS)
endif()

# if DOOM_COMPONENTS is set, add compile definitions for the DOOM
if(DOOM_COMPONENTS)
add_compile_definitions(ENABLE_DOOM)
Expand All @@ -66,6 +74,7 @@ set(EMULATOR_COMPONENTS
${SMS_COMPONENTS}
${SNES_COMPONENTS}
${MSX_COMPONENTS}
${GENESIS_COMPONENTS}
${DOOM_COMPONENTS}
)

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ESP32-S3-BOX-3 which provides:
- NES Emulator (nofrendo)
- Gameboy / Gameboy Color emulator (gnuboy)
- Sega Master System / Game Gear emulator (smsplus)
- Genesis emulator (gwenesis); NOTE: this is a WIP and does not support full-speed / sound / savestates yet.
- LVGL main menu with rom select (including boxart display) and settings page
(all generated from Squareline Studio)
- LVGL emulation paused menu with save slot select, save slot image display,
Expand Down Expand Up @@ -72,7 +73,7 @@ This project has the following features (still WIP):
- [x] GB/GBC emulator
- [x] Sega Master System (SMS) / GameGear (GG) emulator
- [ ] MSX emulator (WIP)
- [ ] Sega Mega Drive / Genesis emulator (WIP)
- [x] Sega Mega Drive / Genesis emulator (WIP)
- [ ] SNES emulator
- [ ] Doom emulator (WIP)
- [x] uSD card (FAT) filesystem over SPI
Expand Down
Binary file added boxart/aladdin-genesis.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/castle-of-illusion-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/lion-king-genesis.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-1-genesis.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-2-genesis.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-3-genesis.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-and-knuckles-genesis.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/aladdin-genesis.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
Binary file added boxart/source/lion-king-genesis.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-1-genesis.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-2-genesis.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-3-genesis.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-and-knuckles-genesis.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.
Binary file added boxart/spider-man-and-venom-maximum-carnage.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions components/box-emu-hal/include/box.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ static constexpr gpio_num_t lcd_sclk_io = GPIO_NUM_7;
static constexpr gpio_num_t lcd_reset_io = GPIO_NUM_48;
static constexpr gpio_num_t lcd_dc_io = GPIO_NUM_4;
static constexpr gpio_num_t backlight_io = GPIO_NUM_45;
static constexpr size_t screen_width = 320;
static constexpr size_t screen_height = 240;
static constexpr size_t lcd_width = 320;
static constexpr size_t lcd_height = 240;
static constexpr bool backlight_value = true;
static constexpr bool reset_value = false;
static constexpr bool invert_colors = true;
Expand Down
4 changes: 2 additions & 2 deletions components/box-emu-hal/include/box_3.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ static constexpr gpio_num_t lcd_sclk_io = GPIO_NUM_7;
static constexpr gpio_num_t lcd_reset_io = GPIO_NUM_48;
static constexpr gpio_num_t lcd_dc_io = GPIO_NUM_4;
static constexpr gpio_num_t backlight_io = GPIO_NUM_47; // was 45 on ESP32-S3-BOX
static constexpr size_t screen_width = 320;
static constexpr size_t screen_height = 240;
static constexpr size_t lcd_width = 320;
static constexpr size_t lcd_height = 240;
static constexpr bool backlight_value = true;
static constexpr bool reset_value = true; // was false on ESP32-S3-BOX
static constexpr bool invert_colors = true;
Expand Down
6 changes: 6 additions & 0 deletions components/box-emu-hal/include/box_emu_hal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ namespace hal {
void set_video_setting(const VideoSetting& setting);

// audio

// NOTE: changing the audio sample rate doesn't seem to affect the NES
// emulator behavior or audio, but does affect the performance of the GB/C
// emulator. Rates faster than this cause the GBC emulator to run fast and
// increase the pitch of the sound, while rates lower than this cause it to
// run slow and decrease the pitch of the sound.
static constexpr int AUDIO_SAMPLE_RATE = 32000;
static constexpr int AUDIO_BUFFER_SIZE = AUDIO_SAMPLE_RATE / 5;
static constexpr int AUDIO_SAMPLE_COUNT = AUDIO_SAMPLE_RATE / 60;
Expand Down
17 changes: 13 additions & 4 deletions components/box-emu-hal/src/battery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,26 @@ void hal::battery_init() {
// get the voltage (V)
auto voltage = battery_->get_battery_voltage(ec);
if (ec) {
return false;
fmt::print("Error getting battery voltage: {}\n", ec.message());
fmt::print("Battery is probably not connected!\n");
fmt::print("Stopping battery task...\n");
return true;
}
// get the state of charge (%)
auto soc = battery_->get_battery_percentage(ec);
if (ec) {
return false;
fmt::print("Error getting battery percentage: {}\n", ec.message());
fmt::print("Battery is probably not connected!\n");
fmt::print("Stopping battery task...\n");
return true;
}
// get the charge rate (+/- % per hour)
auto charge_rate = battery_->get_battery_charge_rate(ec);
if (ec) {
return false;
fmt::print("Error getting battery charge rate: {}\n", ec.message());
fmt::print("Battery is probably not connected!\n");
fmt::print("Stopping battery task...\n");
return true;
}

// NOTE: we could also get voltage from the adc for the battery if we
Expand All @@ -95,7 +104,7 @@ void hal::battery_init() {
espp::EventManager::get().publish(battery_topic, battery_info_data);
return false;
},
.stack_size_bytes = 3 * 1024});
.stack_size_bytes = 4 * 1024});
battery_task_->start();
battery_initialized_ = true;
}
Expand Down
4 changes: 2 additions & 2 deletions components/box-emu-hal/src/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ static void init_input_v0() {
.port_1_direction_mask = EmuV0::PORT_1_DIRECTION_MASK,
.port_1_interrupt_mask = EmuV0::PORT_1_INTERRUPT_MASK,
.write = std::bind(&espp::I2c::write, external_i2c.get(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
.read = std::bind(&espp::I2c::read_at_register, external_i2c.get(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
.read_register = std::bind(&espp::I2c::read_at_register, external_i2c.get(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
.log_level = espp::Logger::Verbosity::WARN
}));
input.reset(raw_input);
Expand All @@ -215,7 +215,7 @@ static void init_input_v1() {
.port_1_direction_mask = EmuV1::PORT_1_DIRECTION_MASK,
.port_1_interrupt_mask = EmuV1::PORT_1_INTERRUPT_MASK,
.write = std::bind(&espp::I2c::write, external_i2c.get(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
.read = std::bind(&espp::I2c::read_at_register, external_i2c.get(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
.write_then_read = std::bind(&espp::I2c::write_read, external_i2c.get(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5),
.log_level = espp::Logger::Verbosity::WARN
}));
input.reset(raw_input);
Expand Down
1 change: 0 additions & 1 deletion components/box-emu-hal/src/mmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,5 @@ extern "C" uint8_t *osd_getromdata() {
}

uint8_t *get_mmapped_romdata() {
fmt::print("Initialized. ROM@{}\n", fmt::ptr(romdata));
return romdata;
}
6 changes: 3 additions & 3 deletions components/box-emu-hal/src/spi_lcd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
static spi_device_handle_t spi;
static spi_device_interface_config_t devcfg;

static constexpr size_t pixel_buffer_size = screen_width * hal::NUM_ROWS_IN_FRAME_BUFFER;
static constexpr size_t pixel_buffer_size = lcd_width * hal::NUM_ROWS_IN_FRAME_BUFFER;
static std::shared_ptr<espp::Display> display;

std::shared_ptr<espp::Display> hal::get_display() {
Expand Down Expand Up @@ -229,8 +229,8 @@ void hal::lcd_init() {
// initialize the display / lvgl
using namespace std::chrono_literals;
display = std::make_shared<espp::Display>(espp::Display::AllocatingConfig{
.width = screen_width,
.height = screen_height,
.width = lcd_width,
.height = lcd_height,
.pixel_buffer_size = pixel_buffer_size,
.flush_callback = DisplayDriver::flush,
.backlight_pin = backlight_io,
Expand Down
25 changes: 15 additions & 10 deletions components/box-emu-hal/src/video_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ using namespace hal;
static std::shared_ptr<espp::Task> video_task_;
static QueueHandle_t video_queue_;

static size_t display_width = screen_width;
static size_t display_height = screen_height;
static size_t display_width = lcd_width;
static size_t display_height = lcd_height;

static size_t native_width = screen_width;
static size_t native_height = screen_height;
static int native_pitch = screen_width;
static size_t native_width = lcd_width;
static size_t native_height = lcd_height;
static int native_pitch = lcd_width;

static const uint16_t* palette = nullptr;
static size_t palette_size = 256;
Expand Down Expand Up @@ -68,11 +68,11 @@ static bool is_native() {
}

static int get_x_offset() {
return (screen_width-display_width)/2;
return (lcd_width-display_width)/2;
}

static int get_y_offset() {
return (screen_height-display_height)/2;
return (lcd_height-display_height)/2;
}

static const uint16_t* get_palette() {
Expand Down Expand Up @@ -104,16 +104,19 @@ static bool video_task(std::mutex &m, std::condition_variable& cv) {
if (has_palette()) {
const uint8_t* _frame = (const uint8_t*)_frame_ptr;
for (int i=0; i<num_lines; i++) {
// TODO: write two pixels (32 bits) at a time because it's faster
for (int j=0; j<display_width; j++) {
int index = (y+i)*native_pitch + j;
_buf[i*display_width + j] = _palette[_frame[index] % palette_size];
}
}
} else {
const uint16_t* _frame = (const uint16_t*)_frame_ptr;
for (int i=0; i<num_lines; i++)
for (int i=0; i<num_lines; i++) {
// TODO: write two pixels (32 bits) at a time because it's faster
for (int j=0; j<display_width; j++)
_buf[i*display_width + j] = _frame[(y+i)*native_pitch + j];
}
}
lcd_write_frame(x_offset, y + y_offset, display_width, num_lines, (uint8_t*)&_buf[0]);
}
Expand All @@ -122,8 +125,8 @@ static bool video_task(std::mutex &m, std::condition_variable& cv) {
// if we don't have a custom palette, we just need to scale/fill the frame
float y_scale = (float)display_height/native_height;
float x_scale = (float)display_width/native_width;
int max_y = screen_height;
int max_x = std::clamp<int>(x_scale * native_width, 0, screen_width);
int max_y = lcd_height;
int max_x = std::clamp<int>(x_scale * native_width, 0, lcd_width);
for (int y=0; y<max_y; y+=num_lines_to_write) {
// each iteration of the loop, we swap the vram index so that we can
// write to the other buffer while the other one is being transmitted
Expand All @@ -140,13 +143,15 @@ static bool video_task(std::mutex &m, std::condition_variable& cv) {
// balance for perfomance of the check?
if (has_palette()) {
const uint8_t* _frame = (const uint8_t*)_frame_ptr;
// TODO: write two pixels (32 bits) at a time because it's faster
for (int x=0; x<max_x; x++) {
int source_x = (float)x/x_scale;
int index = source_y*native_pitch + source_x;
_buf[i*max_x + x] = _palette[_frame[index] % palette_size];
}
} else {
const uint16_t* _frame = (const uint16_t*)_frame_ptr;
// TODO: write two pixels (32 bits) at a time because it's faster
for (int x=0; x<max_x; x++) {
int source_x = (float)x/x_scale;
_buf[i*max_x + x] = _frame[source_y*native_pitch + source_x];
Expand Down
2 changes: 1 addition & 1 deletion components/espp
Submodule espp updated 573 files
3 changes: 2 additions & 1 deletion components/gbc/gnuboy/include/gnuboy/lcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ struct obj

struct lcd
{
byte vbank[2][8192];
// byte vbank[2][8192];
byte *vbank; // [2][8192];
union
{
byte mem[256];
Expand Down
3 changes: 2 additions & 1 deletion components/gbc/gnuboy/include/gnuboy/mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ struct rom
struct ram
{
byte hi[256];
byte ibank[8][4096];
// byte ibank[8][4096];
byte *ibank;
byte (*sbank)[8192];
byte loaded;
byte sram_dirty;
Expand Down
23 changes: 15 additions & 8 deletions components/gbc/gnuboy/src/lcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ static const byte* IRAM_ATTR get_patpix(int i, int x)

int j;
int a, c;
const byte* const vram = lcd.vbank[0];
const byte* const vram = &lcd.vbank[0];

switch (rotation)
{
Expand Down Expand Up @@ -161,8 +161,8 @@ static void IRAM_ATTR tilebuf()


base = ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5) + S;
tilemap = lcd.vbank[0] + base;
attrmap = lcd.vbank[1] + base;
tilemap = &lcd.vbank[0] + base;
attrmap = &lcd.vbank[8192] + base;
tilebuf = BG;
wrap = wraptable + S;
cnt = ((WX + 7) >> 3) + 1;
Expand Down Expand Up @@ -209,8 +209,8 @@ static void IRAM_ATTR tilebuf()
if (WX >= 160) return;

base = ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
tilemap = lcd.vbank[0] + base;
attrmap = lcd.vbank[1] + base;
tilemap = &lcd.vbank[0] + base;
attrmap = &lcd.vbank[8192] + base;
tilebuf = WND;
cnt = ((160 - WX) >> 3) + 1;

Expand Down Expand Up @@ -361,7 +361,7 @@ static void IRAM_ATTR bg_scan_pri()
i = S;
cnt = WX;
dest = PRI;
src = lcd.vbank[1] + ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5);
src = &lcd.vbank[8192] + ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5);

if (!priused(src))
{
Expand Down Expand Up @@ -391,7 +391,7 @@ static void IRAM_ATTR wnd_scan_pri()
i = 0;
cnt = 160 - WX;
dest = PRI + WX;
src = lcd.vbank[1] + ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
src = &lcd.vbank[8192] + ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);

if (!priused(src))
{
Expand Down Expand Up @@ -778,9 +778,12 @@ void IRAM_ATTR pal_write_dmg(int i, int mapnum, byte d)

inline void vram_write(int a, byte b)
{
// byte (*vbank_arry)[2][8192] = (byte (*)[2][8192])lcd.vbank;
//if (lcd.vbank[R_VBK&1][a] != b)
{
lcd.vbank[R_VBK&1][a] = b;
// lcd.vbank[R_VBK&1][a] = b;
lcd.vbank[(R_VBK&1) * 8192 + a] = b;
// (*vbank_arry)[R_VBK&1][a] = b;
if (a >= 0x1800) return;
}
}
Expand Down Expand Up @@ -810,7 +813,11 @@ void pal_dirty()

void lcd_reset()
{
// save the vbank pointer
byte *vbank = lcd.vbank;
memset(&lcd, 0, sizeof lcd);
// restore the vbank pointer
lcd.vbank = vbank;

lcd_begin();
vram_dirty();
Expand Down
Loading

0 comments on commit 7973ef5

Please sign in to comment.