Skip to content

Commit

Permalink
# v1.0.0
Browse files Browse the repository at this point in the history
Massive speedup without frameskip
  • Loading branch information
xrip committed Oct 12, 2023
1 parent b768a0a commit c734076
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 32 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/create-release-on-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,11 @@ jobs:
cmake -DOVERCLOCKING=300 .. && make && \
cmake -DOVERCLOCKING=312 .. && make && \
cmake -DOVERCLOCKING=333 .. && make && \
cmake -DOVERCLOCKING=346 .. && make && \
cmake -DOVERCLOCKING=366 .. && make && \
cmake -DOVERCLOCKING=396 .. && make && \
cmake -DOVERCLOCKING=412 .. && make
cmake -DOVERCLOCKING=412 .. && make && \\
cmake -DOVERCLOCKING=416 .. && make
- name: Create release
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# v1.1.0

PS2 keyboard support

# v1.0.1

Sound enabled. Realy usable only near to maximum overclock.
Expand Down
8 changes: 5 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ MARK_AS_ADVANCED(

add_subdirectory(TotalSMS)
add_subdirectory(drivers/audio)
add_subdirectory(drivers/ps2kbd)
add_subdirectory(drivers/vga)
add_subdirectory(drivers/nespad)
add_subdirectory(drivers/fatfs)
Expand All @@ -52,8 +53,8 @@ add_executable(sms
main.cpp
)

pico_set_program_name(sms "sms Emulator for MURMULATOR devboard")
pico_set_program_version(sms "v0.1")
pico_set_program_name(sms "Sega Master System/GameGear emulator by xrip for MURMULATOR devboard")
pico_set_program_version(sms "dev")

if(OVERCLOCKING)
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}-${OVERCLOCKING}MHz")
Expand All @@ -74,7 +75,7 @@ endif ()
target_include_directories(sms PRIVATE TotalSMS)

pico_enable_stdio_uart(sms 0)
pico_enable_stdio_usb(sms 0)
pico_enable_stdio_usb(sms 1)

target_link_libraries(sms PRIVATE
TotalSMS
Expand All @@ -84,6 +85,7 @@ target_link_libraries(sms PRIVATE
sdcard
fatfs
nespad
ps2kbd

pico_runtime
pico_stdlib
Expand Down
7 changes: 5 additions & 2 deletions drivers/vga/vga_vmode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
// ****************************************************************************

#include "include.h"
#ifndef OVERCLOCKING
#define OVERCLOCKING 270
#endif

sVmode Vmode; // videomode setup
sVgaCfg Cfg; // required configuration
Expand Down Expand Up @@ -211,8 +214,8 @@ void VgaCfgDef(sVgaCfg* cfg)
cfg->height = 480; // height in lines
cfg->wfull = 0; // width of full screen, corresponding to 'hfull' time (0=use 'width' parameter)
cfg->video = &VideoVGA; // used video timings
cfg->freq = 396*1000; // required minimal system frequency in kHz (real frequency can be higher)
cfg->fmax = 396*1000; // maximal system frequency in kHz (limit resolution if needed)
cfg->freq = OVERCLOCKING*1000; // required minimal system frequency in kHz (real frequency can be higher)
cfg->fmax = OVERCLOCKING*1000; // maximal system frequency in kHz (limit resolution if needed)
cfg->dbly = False; // double in Y direction
cfg->lockfreq = True; // lock required frequency, do not change it
}
Expand Down
133 changes: 107 additions & 26 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,23 @@
#include "pico/multicore.h"
#include "sms.h"
#include "vga.h"

#define ENABLE_SOUND 1
#if ENABLE_SOUND

#include "audio.h"

#endif

#include "nespad.h"
#include "f_util.h"
#include "ff.h"
#include "VGA_ROM_F16.h"
#include "ps2kbd_mrmltr.h"

#ifndef OVERCLOCKING
#define OVERCLOCKING 270
#endif

#pragma GCC optimize("Ofast")

Expand All @@ -46,6 +54,66 @@ uint8_t SCREEN[SMS_SCREEN_WIDTH * SMS_SCREEN_HEIGHT];
char textmode[30][80];
uint8_t colors[30][80];

struct input_bits_t {
bool a: true;
bool b: true;
bool select: true;
bool start: true;
bool right: true;
bool left: true;
bool up: true;
bool down: true;
};
static input_bits_t keyboard_bits = {false, false, false, false, false, false, false, false};
static input_bits_t gamepad1_bits = {false, false, false, false, false, false, false, false};
static input_bits_t gamepad2_bits = {false, false, false, false, false, false, false, false};

void nespad_tick() {
nespad_read();

gamepad1_bits.a = (nespad_state & DPAD_A) != 0;
gamepad1_bits.b = (nespad_state & DPAD_B) != 0;
gamepad1_bits.select = (nespad_state & DPAD_SELECT) != 0;
gamepad1_bits.start = (nespad_state & DPAD_START) != 0;
gamepad1_bits.up = (nespad_state & DPAD_UP) != 0;
gamepad1_bits.down = (nespad_state & DPAD_DOWN) != 0;
gamepad1_bits.left = (nespad_state & DPAD_LEFT) != 0;
gamepad1_bits.right = (nespad_state & DPAD_RIGHT) != 0;

}

static bool isInReport(hid_keyboard_report_t const *report, const unsigned char keycode) {
for (unsigned char i: report->keycode) {
if (i == keycode) {
return true;
}
}
return false;
}

void
__not_in_flash_func(process_kbd_report)(hid_keyboard_report_t const *report, hid_keyboard_report_t const *prev_report) {
/* printf("HID key report modifiers %2.2X report ", report->modifier);
for (unsigned char i: report->keycode)
printf("%2.2X", i);
printf("\r\n");
*/
keyboard_bits.start = isInReport(report, HID_KEY_ENTER);
keyboard_bits.select = isInReport(report, HID_KEY_BACKSPACE);
keyboard_bits.a = isInReport(report, HID_KEY_Z);
keyboard_bits.b = isInReport(report, HID_KEY_X);
keyboard_bits.up = isInReport(report, HID_KEY_ARROW_UP);
keyboard_bits.down = isInReport(report, HID_KEY_ARROW_DOWN);
keyboard_bits.left = isInReport(report, HID_KEY_ARROW_LEFT);
keyboard_bits.right = isInReport(report, HID_KEY_ARROW_RIGHT);
//-------------------------------------------------------------------------
}

Ps2Kbd_Mrmltr ps2kbd(
pio1,
0,
process_kbd_report);

typedef enum {
RESOLUTION_NATIVE,
RESOLUTION_TEXTMODE,
Expand All @@ -72,7 +140,7 @@ void load_cart_rom_file(char *filename) {
FIL fil;
FRESULT fr;

size_t bufsize = sizeof(SCREEN)&0xfffff000;
size_t bufsize = sizeof(SCREEN) & 0xfffff000;
BYTE *buffer = (BYTE *) SCREEN;
auto ofs = FLASH_TARGET_OFFSET;

Expand Down Expand Up @@ -201,23 +269,27 @@ void rom_file_selector() {
draw_text(filenames[selected], 0, selected, 0xFF, 0xF8);

while (true) {
nespad_read();
ps2kbd.tick();
nespad_tick();
sleep_ms(33);
nespad_read();
nespad_tick();
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
if ((nespad_state & DPAD_SELECT) != 0) {
if (keyboard_bits.select || gamepad1_bits.select) {
gpio_put(PICO_DEFAULT_LED_PIN, true);
break;
}
if ((nespad_state & DPAD_A) != 0 || (nespad_state & DPAD_B) != 0 || (nespad_state & DPAD_START) != 0) {

if (keyboard_bits.start || gamepad1_bits.start || gamepad1_bits.a || gamepad1_bits.b) {
/* copy the rom from the SD card to flash and start the game */
char pathname[255];
sprintf(pathname, "SMS\\%s", filenames[selected]);
load_cart_rom_file(pathname);
break;
}
if ((nespad_state & DPAD_DOWN) != 0) {

if (keyboard_bits.down || gamepad1_bits.down) {
/* select the next rom */
draw_text(filenames[selected], 0, selected, 0xFF, 0x00);
selected++;
Expand All @@ -226,7 +298,8 @@ void rom_file_selector() {
draw_text(filenames[selected], 0, selected, 0xFF, 0xF8);
sleep_ms(150);
}
if ((nespad_state & DPAD_UP) != 0) {

if (keyboard_bits.up || gamepad1_bits.up) {
/* select the previous rom */
draw_text(filenames[selected], 0, selected, 0xFF, 0x00);
if (selected == 0) {
Expand All @@ -237,7 +310,8 @@ void rom_file_selector() {
draw_text(filenames[selected], 0, selected, 0xFF, 0xF8);
sleep_ms(150);
}
if ((nespad_state & DPAD_RIGHT) != 0) {

if (keyboard_bits.right || gamepad1_bits.right) {
/* select the next page */
num_page++;
numfiles = rom_file_selector_display_page(filenames, num_page);
Expand All @@ -251,7 +325,8 @@ void rom_file_selector() {
draw_text(filenames[selected], 0, selected, 0xFF, 0xF8);
sleep_ms(150);
}
if ((nespad_state & DPAD_LEFT) != 0 && num_page > 0) {

if ((keyboard_bits.left || gamepad1_bits.left) && num_page > 0) {
/* select the previous page */
num_page--;
numfiles = rom_file_selector_display_page(filenames, num_page);
Expand All @@ -265,19 +340,21 @@ void rom_file_selector() {
}

static void handle_input() {
nespad_read();

SMS_set_port_a(&sms, JOY1_DOWN_BUTTON, (nespad_state & DPAD_DOWN) != 0);
SMS_set_port_a(&sms, JOY1_UP_BUTTON, (nespad_state & DPAD_UP) != 0);
SMS_set_port_a(&sms, JOY1_LEFT_BUTTON, (nespad_state & DPAD_LEFT) != 0);
SMS_set_port_a(&sms, JOY1_RIGHT_BUTTON, (nespad_state & DPAD_RIGHT) != 0);
SMS_set_port_b(&sms, RESET_BUTTON, (nespad_state & DPAD_SELECT) != 0);
SMS_set_port_a(&sms, JOY1_A_BUTTON, (nespad_state & DPAD_B) != 0);
SMS_set_port_a(&sms, JOY1_B_BUTTON, (nespad_state & DPAD_A) != 0);
nespad_tick();
ps2kbd.tick();

SMS_set_port_a(&sms, JOY1_DOWN_BUTTON, keyboard_bits.down || gamepad1_bits.down);
SMS_set_port_a(&sms, JOY1_UP_BUTTON, keyboard_bits.up || gamepad1_bits.up);
SMS_set_port_a(&sms, JOY1_LEFT_BUTTON, keyboard_bits.left || gamepad1_bits.left);
SMS_set_port_a(&sms, JOY1_RIGHT_BUTTON, keyboard_bits.right || gamepad1_bits.right);
SMS_set_port_b(&sms, RESET_BUTTON, keyboard_bits.select || gamepad1_bits.select);
SMS_set_port_a(&sms, JOY1_A_BUTTON, keyboard_bits.a || gamepad1_bits.a);
SMS_set_port_a(&sms, JOY1_B_BUTTON, keyboard_bits.b || gamepad1_bits.b);
if (is_gg) {
SMS_set_port_b(&sms, PAUSE_BUTTON, (nespad_state & DPAD_START) != 0);
SMS_set_port_b(&sms, PAUSE_BUTTON, keyboard_bits.start || gamepad1_bits.start);
}
}

#define X2(a) (a | (a << 8))
#define X4(a) (a | (a << 8) | (a << 16) | (a << 24))
#define CHECK_BIT(var, pos) (((var)>>(pos)) & 1)
Expand Down Expand Up @@ -359,7 +436,7 @@ __attribute__((always_inline)) inline uint32_t core_colour_callback(void *user,

uint_fast32_t frames = 0;
uint64_t start_time;
#define FRAME_SKIP (0)
#define FRAME_SKIP (OVERCLOCKING < 366 ? 1 : 0)

static void core_vblank_callback(void *user) {
//(void) user;
Expand All @@ -382,20 +459,22 @@ i2s_config_t i2s_config;
#define SAMPLES 4096
static struct SMS_ApuSample sms_audio_samples[SAMPLES];

__attribute__((always_inline)) inline void core_audio_callback(void* user, struct SMS_ApuSample* samples, uint32_t size) {
(void)user;
static int16_t audio_buffer[SAMPLES*2];
__attribute__((always_inline)) inline void
core_audio_callback(void *user, struct SMS_ApuSample *samples, uint32_t size) {
(void) user;
static int16_t audio_buffer[SAMPLES * 2];
SMS_apu_mixer_s16(samples, reinterpret_cast<int16_t *>(audio_buffer), size);
i2s_dma_write(&i2s_config, reinterpret_cast<const int16_t *>(audio_buffer));
}

#endif

int main() {
/* Overclock. */
hw_set_bits(&vreg_and_chip_reset_hw->vreg, VREG_AND_CHIP_RESET_VREG_VSEL_BITS);
sleep_ms(33);

set_sys_clock_khz(396 * 1000, true);
set_sys_clock_khz(OVERCLOCKING * 1000, true);

gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
Expand All @@ -414,6 +493,7 @@ int main() {
vmode = Video(DEV_VGA, RES_HVGA);
sleep_ms(50);

ps2kbd.init_gpio();
nespad_begin(clock_get_hz(clk_sys) / 1000, NES_GPIO_CLK, NES_GPIO_DATA, NES_GPIO_LAT);

if (!SMS_init(&sms)) {
Expand All @@ -426,10 +506,11 @@ int main() {
#if ENABLE_SOUND
i2s_config = i2s_get_default_config();
i2s_config.sample_freq = AUDIO_FREQ;
i2s_config.dma_trans_count = sizeof(sms_audio_samples)/sizeof(sms_audio_samples[0]);
i2s_config.dma_trans_count = sizeof(sms_audio_samples) / sizeof(sms_audio_samples[0]);
i2s_volume(&i2s_config, 0);
i2s_init(&i2s_config);
SMS_set_apu_callback(&sms, core_audio_callback, sms_audio_samples, sizeof(sms_audio_samples)/sizeof(sms_audio_samples[0]), AUDIO_FREQ);
SMS_set_apu_callback(&sms, core_audio_callback, sms_audio_samples,
sizeof(sms_audio_samples) / sizeof(sms_audio_samples[0]), AUDIO_FREQ);
#endif
SMS_set_pixels(&sms, &SCREEN, SMS_SCREEN_WIDTH, 8);

Expand Down

0 comments on commit c734076

Please sign in to comment.