195 lines
4.2 KiB
C++
195 lines
4.2 KiB
C++
/**
|
|
* Copyright (C) 2022 by Mahyar Koshkouei <mk@deltabeard.com>
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include "gb.h"
|
|
|
|
// C Headers
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
// RP2040 Headers
|
|
#include <hardware/vreg.h>
|
|
|
|
// Project headers
|
|
#include "hedley.h"
|
|
|
|
#include "common.h"
|
|
#include "input.h"
|
|
|
|
#if ENABLE_SDCARD
|
|
#include "card_loader.h"
|
|
#include "SdFat.h"
|
|
#ifdef ENABLE_USB_STORAGE_DEVICE
|
|
#include "msc.h"
|
|
#endif
|
|
#endif
|
|
|
|
#if ENABLE_SOUND
|
|
#include "i2s-audio.h"
|
|
#include "minigb_apu.h"
|
|
|
|
/**
|
|
* Global variables for audio task
|
|
* stream contains N=AUDIO_SAMPLES samples
|
|
* each sample is 32 bits
|
|
* 16 bits for the left channel + 16 bits for the right channel in stereo interleaved format)
|
|
* This is intended to be played at AUDIO_SAMPLE_RATE Hz
|
|
*/
|
|
uint16_t* stream;
|
|
|
|
i2s_config_t i2s_config;
|
|
#endif
|
|
|
|
uint_fast32_t frames = 0;
|
|
|
|
void startEmulator() {
|
|
#if ENABLE_LCD
|
|
#if ENABLE_SDCARD
|
|
Serial.println("Starting ROM file selector ...");
|
|
rom_file_selector();
|
|
#endif
|
|
#endif
|
|
|
|
Serial.println("Init GB context ...");
|
|
initGbContext();
|
|
|
|
/* Automatically assign a colour palette to the game */
|
|
char rom_title[16];
|
|
//auto_assign_palette(palette, gb_colour_hash(&gb), gb_get_rom_name(&gb, rom_title));
|
|
get_colour_palette(palette, 0x16, 0x00);
|
|
|
|
#if ENABLE_LCD
|
|
gb_init_lcd(&gb, &lcd_draw_line);
|
|
|
|
/* Start Core1, which processes requests to the LCD. */
|
|
Serial.println("Starting Core1 ...");
|
|
multicore_launch_core1(core1_init);
|
|
#endif
|
|
|
|
#if ENABLE_SOUND
|
|
// Initialize audio emulation
|
|
Serial.println("Starting audio ...");
|
|
audio_init();
|
|
#endif
|
|
|
|
#if ENABLE_SDCARD
|
|
//Serial.println("Load save file ...");
|
|
//read_cart_ram_file(&gb);
|
|
#endif
|
|
|
|
Serial.print("\n> ");
|
|
}
|
|
|
|
void reset(uint32_t sleepMs) {
|
|
Serial.println("\nEmulation Ended");
|
|
|
|
sleep_ms(sleepMs);
|
|
|
|
/* stop lcd task running on core 1 */
|
|
multicore_reset_core1();
|
|
watchdog_reboot(0, 0, 0);
|
|
}
|
|
|
|
void halt() {
|
|
while (true) {}
|
|
}
|
|
|
|
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 initSound() {
|
|
#if ENABLE_SOUND
|
|
Serial.println("Initialize Sound ...");
|
|
|
|
// Allocate memory for the stream buffer
|
|
stream = (uint16_t*) malloc(AUDIO_BUFFER_SIZE_BYTES);
|
|
assert(stream != NULL);
|
|
memset(stream, 0, AUDIO_BUFFER_SIZE_BYTES); // Zero out the stream buffer
|
|
|
|
// Initialize I2S sound driver
|
|
i2s_config = i2s_get_default_config();
|
|
i2s_config.sample_freq = AUDIO_SAMPLE_RATE;
|
|
i2s_config.dma_trans_count = AUDIO_SAMPLES;
|
|
i2s_config.data_pin = I2S_DIN_PIN,
|
|
i2s_config.clock_pin_base = I2S_BCLK_LRC_PIN_BASE,
|
|
i2s_volume(&i2s_config, 2);
|
|
i2s_init(&i2s_config);
|
|
|
|
Serial.println("Sound initialized");
|
|
#endif
|
|
}
|
|
|
|
void setup() {
|
|
#if ENABLE_LCD
|
|
lcd_init(false);
|
|
#endif
|
|
|
|
overclock();
|
|
|
|
// Initialise USB serial connection for debugging.
|
|
Serial.begin(115200);
|
|
//while (!Serial) ;
|
|
//delay(2000);
|
|
|
|
#if ENABLE_SDCARD
|
|
init_sdcard();
|
|
#if ENABLE_USB_STORAGE_DEVICE
|
|
initUsbStorageDevice();
|
|
#endif
|
|
#endif
|
|
|
|
initJoypad();
|
|
|
|
initSound();
|
|
|
|
startEmulator();
|
|
}
|
|
|
|
void loop() {
|
|
gb.gb_frame = 0;
|
|
do {
|
|
__gb_step_cpu(&gb);
|
|
tight_loop_contents();
|
|
} while (HEDLEY_LIKELY(gb.gb_frame == 0));
|
|
|
|
frames++;
|
|
#if ENABLE_SOUND
|
|
if (!gb.direct.frame_skip) {
|
|
audio_callback(NULL, (int16_t*) stream, AUDIO_BUFFER_SIZE_BYTES);
|
|
i2s_dma_write(&i2s_config, (int16_t*) stream);
|
|
}
|
|
#endif
|
|
|
|
handleJoypad();
|
|
handleSerial();
|
|
}
|
|
|
|
void error(String message) {
|
|
tft.fillScreen(TFT_BLACK);
|
|
tft.setTextColor(TFT_RED);
|
|
tft.drawString(message, 0, ERROR_TEXT_OFFSET, FONT_ID);
|
|
Serial.printf("E %s\n", message.c_str());
|
|
Serial.flush();
|
|
reset(5000);
|
|
}
|