use framebuffer

This commit is contained in:
Tobias Gunkel
2025-08-16 11:50:13 +02:00
parent 7d815de240
commit a9d2851688
8 changed files with 385 additions and 319 deletions
+15 -271
View File
@@ -13,9 +13,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
// Peanut-GB emulator settings
#include "peanut_gb_options.h"
#include "peanut_gb.h"
#include "gb.h"
/* C Headers */
#include <stdio.h>
@@ -25,40 +23,19 @@
/* RP2040 Headers */
#include <hardware/vreg.h>
#include <PCF8574.h>
/* Project headers */
#include "hedley.h"
#include "minigb_apu.h"
// #include "sdcard.h"
#include "core.h"
#include "common.h"
#include "game_bin.h"
#include "i2s.h"
#define GBCOLOR_HEADER_ONLY
#include "gbcolors.h"
/* GPIO Connections. */
#ifdef USE_PAD_GPIO
#define PIN_UP 2
#define PIN_DOWN 3
#define PIN_LEFT 4
#define PIN_RIGHT 5
#define PIN_A 6
#define PIN_B 7
#define PIN_SELECT 8
#define PIN_START 9
#else
#define PIN_UP 0
#define PIN_DOWN 1
#define PIN_LEFT 2
#define PIN_RIGHT 3
#define PIN_A 5
#define PIN_B 4
#define PIN_SELECT 6
#define PIN_START 7
#endif
#include "input.h"
#if ENABLE_SOUND
/**
@@ -84,22 +61,10 @@ static unsigned char rom_bank0[65536];
static uint8_t ram[32768];
static uint8_t manual_palette_selected = 0;
static PCF8574 pcf8574(0x20, 16, 17);
struct gb_s gb;
palette_t palette; // Colour palette
static struct
{
unsigned a : 1;
unsigned b : 1;
unsigned select : 1;
unsigned start : 1;
unsigned right : 1;
unsigned left : 1;
unsigned up : 1;
unsigned down : 1;
} prev_joypad_bits;
uint_fast32_t frames = 0;
#define putstdio(x) write(1, x, strlen(x))
@@ -145,14 +110,12 @@ void gb_error(struct gb_s* gb, const enum gb_error_e gb_err, const uint16_t addr
#endif
}
void reset();
void startEmulator() {
#if ENABLE_LCD
#if ENABLE_SDCARD
/* ROM File selector */
lcd_init();
lcd_fill(TFT_BLACK); // 0x0000);
tft.fillScreen(TFT_BLACK);
rom_file_selector();
#endif
#endif
@@ -204,63 +167,18 @@ void reset() {
watchdog_reboot(0,0,0);
}
#ifdef USE_PAD_GPIO
void initJoypad() {
gpio_set_function(GPIO_UP, GPIO_FUNC_SIO);
gpio_set_function(GPIO_DOWN, GPIO_FUNC_SIO);
gpio_set_function(GPIO_LEFT, GPIO_FUNC_SIO);
gpio_set_function(GPIO_RIGHT, GPIO_FUNC_SIO);
gpio_set_function(GPIO_A, GPIO_FUNC_SIO);
gpio_set_function(GPIO_B, GPIO_FUNC_SIO);
gpio_set_function(GPIO_SELECT, GPIO_FUNC_SIO);
gpio_set_function(GPIO_START, GPIO_FUNC_SIO);
void overclock() {
const unsigned vco = 1596 * 1000 * 1000; /* 266MHz */
const unsigned div1 = 6, div2 = 1;
gpio_set_dir(GPIO_UP, false);
gpio_set_dir(GPIO_DOWN, false);
gpio_set_dir(GPIO_LEFT, false);
gpio_set_dir(GPIO_RIGHT, false);
gpio_set_dir(GPIO_A, false);
gpio_set_dir(GPIO_B, false);
gpio_set_dir(GPIO_SELECT, false);
gpio_set_dir(GPIO_START, false);
gpio_pull_up(GPIO_UP);
gpio_pull_up(GPIO_DOWN);
gpio_pull_up(GPIO_LEFT);
gpio_pull_up(GPIO_RIGHT);
gpio_pull_up(GPIO_A);
gpio_pull_up(GPIO_B);
gpio_pull_up(GPIO_SELECT);
gpio_pull_up(GPIO_START);
vreg_set_voltage(VREG_VOLTAGE_1_15);
sleep_ms(2);
set_sys_clock_pll(vco, div1, div2);
sleep_ms(2);
}
#else
void initJoypad() {
for (int pin = 0; pin < 8; ++pin) {
pcf8574.pinMode(pin, INPUT_PULLUP);
}
pcf8574.setLatency(5);
if (pcf8574.begin()){
Serial.println("PCF8574 initialized");
}else{
Serial.println("PCF8574 initialization failed");
while (true) ;
}
}
#endif
void setup(void) {
/* Overclock. */
{
const unsigned vco = 1596 * 1000 * 1000; /* 266MHz */
const unsigned div1 = 6, div2 = 1;
vreg_set_voltage(VREG_VOLTAGE_1_15);
sleep_ms(2);
set_sys_clock_pll(vco, div1, div2);
sleep_ms(2);
}
void setup() {
overclock();
/* Initialise USB serial connection for debugging. */
Serial.begin(115200);
@@ -312,181 +230,7 @@ void prevPalette() {
manual_assign_palette(palette, manual_palette_selected);
}
void handleSerial(uint_fast32_t& frames) {
static uint64_t start_time = time_us_64();
/* Serial monitor commands */
int input = Serial.read();
if (input <= 0) {
return;
}
switch (input) {
case 'i':
gb.direct.interlace = !gb.direct.interlace;
break;
case 'f':
gb.direct.frame_skip = !gb.direct.frame_skip;
break;
case 'b': {
uint64_t end_time;
uint32_t diff;
uint32_t fps;
end_time = time_us_64();
diff = end_time - start_time;
fps = ((uint64_t)frames * 1000 * 1000) / diff;
Serial.printf("Frames: %u\n"
"Time: %lu us\n"
"FPS: %lu\n",
frames, diff, fps);
Serial.flush();
frames = 0;
start_time = time_us_64();
break;
}
case '\n':
case '\r': {
gb.direct.joypad_bits.start = 0;
break;
}
case '\b': {
gb.direct.joypad_bits.select = 0;
break;
}
case '8': {
gb.direct.joypad_bits.up = 0;
break;
}
case '2': {
gb.direct.joypad_bits.down = 0;
break;
}
case '4': {
gb.direct.joypad_bits.left = 0;
break;
}
case '6': {
gb.direct.joypad_bits.right = 0;
break;
}
case 'z':
case 'w': {
gb.direct.joypad_bits.a = 0;
break;
}
case 'x': {
gb.direct.joypad_bits.b = 0;
break;
}
case 'q':
reset();
case 'p':
nextPalette();
default:
break;
}
}
void handlePad() {
/* Update buttons state */
prev_joypad_bits.up = gb.direct.joypad_bits.up;
prev_joypad_bits.down = gb.direct.joypad_bits.down;
prev_joypad_bits.left = gb.direct.joypad_bits.left;
prev_joypad_bits.right = gb.direct.joypad_bits.right;
prev_joypad_bits.a = gb.direct.joypad_bits.a;
prev_joypad_bits.b = gb.direct.joypad_bits.b;
prev_joypad_bits.select = gb.direct.joypad_bits.select;
prev_joypad_bits.start = gb.direct.joypad_bits.start;
#ifdef USE_PAD_GPIO
gb.direct.joypad_bits.up = gpio_get(PIN_UP);
gb.direct.joypad_bits.down = gpio_get(PIN_DOWN);
gb.direct.joypad_bits.left = gpio_get(PIN_LEFT);
gb.direct.joypad_bits.right = gpio_get(PIN_RIGHT);
gb.direct.joypad_bits.a = gpio_get(PIN_A);
gb.direct.joypad_bits.b = gpio_get(PIN_B);
gb.direct.joypad_bits.select = gpio_get(PIN_SELECT);
gb.direct.joypad_bits.start = gpio_get(PIN_START);
#else
#if 0
Serial.printf("pins:\n");
for (int i = 0; i < 8; ++i) {
int in = pcf8574.digitalRead(i);
Serial.printf(" %d", in);
}
Serial.printf("\n");
#endif
gb.direct.joypad_bits.up = pcf8574.digitalRead(PIN_UP);
gb.direct.joypad_bits.down = pcf8574.digitalRead(PIN_DOWN);
gb.direct.joypad_bits.left = pcf8574.digitalRead(PIN_LEFT);
gb.direct.joypad_bits.right = pcf8574.digitalRead(PIN_RIGHT);
gb.direct.joypad_bits.a = pcf8574.digitalRead(PIN_A);
gb.direct.joypad_bits.b = pcf8574.digitalRead(PIN_B);
gb.direct.joypad_bits.select = pcf8574.digitalRead(PIN_SELECT);
gb.direct.joypad_bits.start = pcf8574.digitalRead(PIN_START);
#endif
/* hotkeys (select + * combo)*/
if (!gb.direct.joypad_bits.select) {
#if ENABLE_SOUND
if (!gb.direct.joypad_bits.up && prev_joypad_bits.up) {
/* select + up: increase sound volume */
i2s_increase_volume(&i2s_config);
}
if (!gb.direct.joypad_bits.down && prev_joypad_bits.down) {
/* select + down: decrease sound volume */
i2s_decrease_volume(&i2s_config);
}
#endif
if (!gb.direct.joypad_bits.right && prev_joypad_bits.right) {
/* select + right: select the next manual color palette */
nextPalette();
}
if (!gb.direct.joypad_bits.left && prev_joypad_bits.left) {
/* select + left: select the previous manual color palette */
prevPalette();
}
if (!gb.direct.joypad_bits.start && prev_joypad_bits.start) {
/* select + start: save ram and resets to the game selection menu */
#if ENABLE_SDCARD
write_cart_ram_file(&gb);
#endif
reset();
}
if (!gb.direct.joypad_bits.a && prev_joypad_bits.a) {
/* select + A: enable/disable frame-skip => fast-forward */
gb.direct.frame_skip = !gb.direct.frame_skip;
Serial.printf("I gb.direct.frame_skip = %d\n", gb.direct.frame_skip);
}
if (!gb.direct.joypad_bits.b && prev_joypad_bits.b) {
/* select + B: change scaling mode */
scalingMode = (ScalingMode)(((int) scalingMode + 1) % ((int) ScalingMode::COUNT));
union core_cmd cmd;
cmd.cmd = CORE_CMD_IDLE_SET;
multicore_fifo_push_blocking(cmd.full);
Serial.printf("I Scaling mode: = %d\n", scalingMode);
}
}
}
void loop() {
static uint_fast32_t frames = 0;
gb.gb_frame = 0;
do {
@@ -503,5 +247,5 @@ void loop() {
#endif
handlePad();
handleSerial(frames);
handleSerial();
}