make sound work
This commit is contained in:
@@ -1,6 +0,0 @@
|
|||||||
#define ENABLE_LCD 1
|
|
||||||
#define ENABLE_SOUND 0 // 1
|
|
||||||
#define ENABLE_SDCARD 0 // 1
|
|
||||||
#define PEANUT_GB_HIGH_LCD_ACCURACY 1
|
|
||||||
#define PEANUT_GB_USE_BIOS 0
|
|
||||||
#define PEANUT_FULL_GBC_SUPPORT 1
|
|
||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
@@ -0,0 +1,25 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
def rgb565_to_rgb_components(hex_value):
|
||||||
|
value = int(hex_value, 16)
|
||||||
|
r = (value >> 11) & 0x1F # 5 bits
|
||||||
|
g = (value >> 5) & 0x3F # 6 bits
|
||||||
|
b = value & 0x1F # 5 bits
|
||||||
|
return f"COLOR(0x{r:02X}, 0x{g:02X}, 0x{b:02X})"
|
||||||
|
|
||||||
|
def convert_colors(text):
|
||||||
|
pattern = r'COLOR\(0x([0-9A-Fa-f]{4})\)'
|
||||||
|
return re.sub(pattern, lambda m: rgb565_to_rgb_components(m.group(1)), text)
|
||||||
|
|
||||||
|
def process_file(input_path, output_path):
|
||||||
|
with open(input_path, 'r', encoding='utf-8') as infile:
|
||||||
|
content = infile.read()
|
||||||
|
converted = convert_colors(content)
|
||||||
|
with open(output_path, 'w', encoding='utf-8') as outfile:
|
||||||
|
outfile.write(converted)
|
||||||
|
|
||||||
|
# Beispielnutzung
|
||||||
|
input_file = 'gbcolors.h'
|
||||||
|
output_file = 'gbcolors.h2'
|
||||||
|
process_file(input_file, output_file)
|
||||||
|
print(f"Konvertierte Datei gespeichert unter: {output_file}")
|
||||||
@@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#define NUMBER_OF_MANUAL_PALETTES 13
|
#define NUMBER_OF_MANUAL_PALETTES 13
|
||||||
#define PALETTE_SIZE_IN_BYTES (3 * 4 * sizeof(uint16_t))
|
#define PALETTE_SIZE_IN_BYTES (3 * 4 * sizeof(uint16_t))
|
||||||
@@ -36,15 +38,29 @@ typedef uint16_t palette_t[3][4];
|
|||||||
|
|
||||||
void manual_assign_palette(palette_t palette, uint8_t selection);
|
void manual_assign_palette(palette_t palette, uint8_t selection);
|
||||||
void auto_assign_palette(uint16_t palette[3][4], uint8_t game_checksum, const char *game_title);
|
void auto_assign_palette(uint16_t palette[3][4], uint8_t game_checksum, const char *game_title);
|
||||||
|
void get_colour_palette(palette_t selected_palette,uint8_t table_entry,uint8_t shuffling_flags);
|
||||||
|
|
||||||
#ifndef GBCOLOR_HEADER_ONLY
|
#ifndef GBCOLOR_HEADER_ONLY
|
||||||
|
|
||||||
#ifdef USE_BGR565
|
#ifdef USE_BGR565
|
||||||
#define RGB565(r, g, b) (((b) << 11) | (g << 5) | (r))
|
#define RGB565(r, g, b) (((b) << 11) | ((g) << 5) | (r))
|
||||||
#else
|
#else
|
||||||
#define RGB565(r, g, b) (((r) << 11) | (g << 5) | (b))
|
//#define RGB565(r, g, b) (((r) << 11) | ((g) << 5) | (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint8_t gamma_int = 40;
|
||||||
|
|
||||||
|
void gamma_correct(uint8_t& r, uint8_t& g, uint8_t& b, float gamma_value) {
|
||||||
|
r = (uint8_t)(pow(r / 31.0, 1.0 / gamma_value) * 31.0 + 0.5);
|
||||||
|
g = (uint8_t)(pow(g / 63.0, 1.0 / gamma_value) * 63.0 + 0.5);
|
||||||
|
b = (uint8_t)(pow(b / 31.0, 1.0 / gamma_value) * 31.0 + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t RGB565(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
gamma_correct(r, g, b, gamma_int / 10.);
|
||||||
|
return ((((r) % 32) << 11) | (((g) % 64) << 5) | ((b) % 32));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get an RGB565 colour palette by entry ID & shuffling flags
|
* Get an RGB565 colour palette by entry ID & shuffling flags
|
||||||
*
|
*
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
// -------------------------------------------------- //
|
||||||
|
// This file is autogenerated by pioasm; do not edit! //
|
||||||
|
// -------------------------------------------------- //
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !PICO_NO_HARDWARE
|
||||||
|
#include "hardware/pio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --------- //
|
||||||
|
// audio_i2s //
|
||||||
|
// --------- //
|
||||||
|
|
||||||
|
#define audio_i2s_wrap_target 0
|
||||||
|
#define audio_i2s_wrap 7
|
||||||
|
|
||||||
|
#define audio_i2s_offset_entry_point 7u
|
||||||
|
|
||||||
|
static const uint16_t audio_i2s_program_instructions[] = {
|
||||||
|
// .wrap_target
|
||||||
|
0x7001, // 0: out pins, 1 side 2
|
||||||
|
0x1840, // 1: jmp x--, 0 side 3
|
||||||
|
0x6001, // 2: out pins, 1 side 0
|
||||||
|
0xe82e, // 3: set x, 14 side 1
|
||||||
|
0x6001, // 4: out pins, 1 side 0
|
||||||
|
0x0844, // 5: jmp x--, 4 side 1
|
||||||
|
0x7001, // 6: out pins, 1 side 2
|
||||||
|
0xf82e, // 7: set x, 14 side 3
|
||||||
|
// .wrap
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !PICO_NO_HARDWARE
|
||||||
|
static const struct pio_program audio_i2s_program = {
|
||||||
|
.instructions = audio_i2s_program_instructions,
|
||||||
|
.length = 8,
|
||||||
|
.origin = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline pio_sm_config audio_i2s_program_get_default_config(uint offset) {
|
||||||
|
pio_sm_config c = pio_get_default_sm_config();
|
||||||
|
sm_config_set_wrap(&c, offset + audio_i2s_wrap_target, offset + audio_i2s_wrap);
|
||||||
|
sm_config_set_sideset(&c, 2, false, false);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void audio_i2s_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base) {
|
||||||
|
pio_sm_config sm_config = audio_i2s_program_get_default_config(offset);
|
||||||
|
sm_config_set_out_pins(&sm_config, data_pin, 1);
|
||||||
|
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
|
||||||
|
sm_config_set_out_shift(&sm_config, false, true, 32);
|
||||||
|
pio_sm_init(pio, sm, offset, &sm_config);
|
||||||
|
uint pin_mask = (1u << data_pin) | (3u << clock_pin_base);
|
||||||
|
pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask);
|
||||||
|
pio_sm_set_pins(pio, sm, 0); // clear pins
|
||||||
|
pio_sm_exec(pio, sm, pio_encode_jmp(offset + audio_i2s_offset_entry_point));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
* IN THE SOFTWARE.
|
* IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "i2s.h"
|
#include "i2s-audio.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return the default i2s context used to store information about the setup
|
* return the default i2s context used to store information about the setup
|
||||||
@@ -36,8 +36,8 @@ i2s_config_t i2s_get_default_config(void) {
|
|||||||
.pio = pio0,
|
.pio = pio0,
|
||||||
.sm = 0,
|
.sm = 0,
|
||||||
.dma_channel = 0,
|
.dma_channel = 0,
|
||||||
.dma_buf = NULL,
|
|
||||||
.dma_trans_count = 0,
|
.dma_trans_count = 0,
|
||||||
|
.dma_buf = (uint16_t*) NULL,
|
||||||
.volume = 0,
|
.volume = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ void i2s_init(i2s_config_t *i2s_config) {
|
|||||||
pio_sm_set_enabled(i2s_config->pio, i2s_config->sm, false);
|
pio_sm_set_enabled(i2s_config->pio, i2s_config->sm, false);
|
||||||
|
|
||||||
/* Allocate memory for the DMA buffer */
|
/* Allocate memory for the DMA buffer */
|
||||||
i2s_config->dma_buf=malloc(i2s_config->dma_trans_count*sizeof(uint32_t));
|
i2s_config->dma_buf = (uint16_t*) malloc(i2s_config->dma_trans_count*sizeof(uint32_t));
|
||||||
|
|
||||||
/* Direct Memory Access setup */
|
/* Direct Memory Access setup */
|
||||||
i2s_config->dma_channel = dma_claim_unused_channel(true);
|
i2s_config->dma_channel = dma_claim_unused_channel(true);
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <hardware/dma.h>
|
#include <hardware/dma.h>
|
||||||
#include "audio_i2s.pio.h"
|
#include "audio_i2s.pio.h"
|
||||||
|
|
||||||
typedef struct i2s_config
|
typedef struct i2s_config_t
|
||||||
{
|
{
|
||||||
uint32_t sample_freq;
|
uint32_t sample_freq;
|
||||||
uint16_t channel_count;
|
uint16_t channel_count;
|
||||||
+6
-3
@@ -22,9 +22,12 @@ lib_deps =
|
|||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
-I.
|
-I.
|
||||||
-Isrc/tft-espi-config/
|
-Isrc/tft-espi-config
|
||||||
-Iext
|
-Ilib
|
||||||
-Iext/minigb_apu
|
-DENABLE_SOUND=1
|
||||||
|
-DENABLE_LCD=1
|
||||||
|
-DENABLE_SDCARD=1
|
||||||
|
-DPEANUT_FULL_GBC_SUPPORT=1
|
||||||
|
|
||||||
[env:pico]
|
[env:pico]
|
||||||
extends = pico-base
|
extends = pico-base
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#include "peanut_gb_options.h"
|
#include "minigb_apu.h"
|
||||||
#include "peanut_gb.h"
|
#include "peanut_gb.h"
|
||||||
|
|
||||||
#include "gbcolors.h"
|
#include "gbcolors.h"
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define PEANUT_GB_HEADER_ONLY
|
#define PEANUT_GB_HEADER_ONLY
|
||||||
#include "peanut_gb_options.h"
|
|
||||||
#include "peanut_gb.h"
|
#include "peanut_gb.h"
|
||||||
|
|
||||||
#define GBCOLOR_HEADER_ONLY
|
#define GBCOLOR_HEADER_ONLY
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
#include "i2s-audio.h"
|
||||||
|
|
||||||
#include "gb.h"
|
#include "gb.h"
|
||||||
|
|
||||||
|
extern i2s_config_t i2s_config;
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
unsigned a : 1;
|
unsigned a : 1;
|
||||||
|
|||||||
+19
-7
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define USE_FRAMEBUFFER
|
//#define USE_FRAMEBUFFER
|
||||||
|
|
||||||
static TFT_eSPI tft = TFT_eSPI();
|
static TFT_eSPI tft = TFT_eSPI();
|
||||||
#ifdef USE_FRAMEBUFFER
|
#ifdef USE_FRAMEBUFFER
|
||||||
@@ -16,7 +16,7 @@ static uint8_t scaledLineOffsetTable[LCD_HEIGHT]; // scaled to 240 lines
|
|||||||
/* Pixel data is stored in here. */
|
/* Pixel data is stored in here. */
|
||||||
static uint8_t pixels_buffer[LCD_WIDTH];
|
static uint8_t pixels_buffer[LCD_WIDTH];
|
||||||
|
|
||||||
volatile ScalingMode scalingMode = ScalingMode::NORMAL;
|
volatile ScalingMode scalingMode = ScalingMode::STRETCH_KEEP_ASPECT;
|
||||||
|
|
||||||
static int lcd_line_busy = 0;
|
static int lcd_line_busy = 0;
|
||||||
|
|
||||||
@@ -32,13 +32,14 @@ static void calcExtraLineTable() {
|
|||||||
|
|
||||||
void lcd_init(void) {
|
void lcd_init(void) {
|
||||||
tft.init();
|
tft.init();
|
||||||
// tft.initDMA();
|
#ifdef USE_FRAMEBUFFER
|
||||||
|
tft.initDMA();
|
||||||
|
#endif
|
||||||
tft.setRotation(1);
|
tft.setRotation(1);
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(TFT_BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_draw_line(struct gb_s* gb, const uint8_t pixels[LCD_WIDTH],
|
void lcd_draw_line(struct gb_s* gb, const uint8_t pixels[LCD_WIDTH], const uint_fast8_t line) {
|
||||||
const uint_fast8_t line) {
|
|
||||||
union core_cmd cmd;
|
union core_cmd cmd;
|
||||||
|
|
||||||
/* Wait until previous line is sent. */
|
/* Wait until previous line is sent. */
|
||||||
@@ -71,7 +72,11 @@ void lcd_write_pixels_normal(const uint16_t* pixels, uint8_t line, uint_fast16_t
|
|||||||
const uint16_t colOffset = (DISPLAY_WIDTH - count) / 2;
|
const uint16_t colOffset = (DISPLAY_WIDTH - count) / 2;
|
||||||
const uint16_t screenLineOffset = (DISPLAY_HEIGHT - LCD_HEIGHT) / 2;
|
const uint16_t screenLineOffset = (DISPLAY_HEIGHT - LCD_HEIGHT) / 2;
|
||||||
const uint16_t lineOffset = screenLineOffset + line;
|
const uint16_t lineOffset = screenLineOffset + line;
|
||||||
|
#ifdef USE_FRAMEBUFFER
|
||||||
lcd_pushColors(lineOffset * DISPLAY_WIDTH + colOffset, pixels, count);
|
lcd_pushColors(lineOffset * DISPLAY_WIDTH + colOffset, pixels, count);
|
||||||
|
#else
|
||||||
|
lcd_pushColors(colOffset, lineOffset, pixels, count);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_write_pixels_stretched(const uint16_t* pixels, uint8_t line, uint_fast16_t count) {
|
void lcd_write_pixels_stretched(const uint16_t* pixels, uint8_t line, uint_fast16_t count) {
|
||||||
@@ -94,7 +99,7 @@ void lcd_write_pixels_stretched(const uint16_t* pixels, uint8_t line, uint_fast1
|
|||||||
#else
|
#else
|
||||||
lcd_pushColors(0, lineOffset, doubledPixels, stretchedWidth);
|
lcd_pushColors(0, lineOffset, doubledPixels, stretchedWidth);
|
||||||
if (lineRepeated) {
|
if (lineRepeated) {
|
||||||
lcd_pushColors(0, lineOffset, doubledPixels, stretchedWidth);
|
lcd_pushColors(0, lineOffset + 1, doubledPixels, stretchedWidth);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -123,7 +128,7 @@ void lcd_write_pixels_stretched_keep_aspect(const uint16_t* pixels, uint8_t line
|
|||||||
#else
|
#else
|
||||||
lcd_pushColors(colOffset, lineOffset, doubledPixels, stretchedWidth);
|
lcd_pushColors(colOffset, lineOffset, doubledPixels, stretchedWidth);
|
||||||
if (lineRepeated) {
|
if (lineRepeated) {
|
||||||
lcd_pushColors(colOffset, lineOffset, doubledPixels, stretchedWidth);
|
lcd_pushColors(colOffset, lineOffset + 1, doubledPixels, stretchedWidth);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -173,6 +178,13 @@ void core1_lcd_draw_line(const uint_fast8_t line) {
|
|||||||
|
|
||||||
lcd_write_pixels(fb, line, LCD_WIDTH);
|
lcd_write_pixels(fb, line, LCD_WIDTH);
|
||||||
__atomic_store_n(&lcd_line_busy, 0, __ATOMIC_SEQ_CST);
|
__atomic_store_n(&lcd_line_busy, 0, __ATOMIC_SEQ_CST);
|
||||||
|
|
||||||
|
#ifdef USE_FRAMEBUFFER
|
||||||
|
if (line == LCD_HEIGHT - 1) {
|
||||||
|
tft.setSwapBytes(true);
|
||||||
|
tft.pushImageDMA(0, 0, framebuffer.width(), framebuffer.height(), (uint16_t *) framebuffer.getPointer());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void core1DispatchLoop() {
|
void core1DispatchLoop() {
|
||||||
|
|||||||
+8
-6
@@ -30,7 +30,7 @@
|
|||||||
// #include "sdcard.h"
|
// #include "sdcard.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "game_bin.h"
|
#include "game_bin.h"
|
||||||
#include "i2s.h"
|
#include "i2s-audio.h"
|
||||||
|
|
||||||
#define GBCOLOR_HEADER_ONLY
|
#define GBCOLOR_HEADER_ONLY
|
||||||
#include "gbcolors.h"
|
#include "gbcolors.h"
|
||||||
@@ -63,7 +63,7 @@ static uint8_t manual_palette_selected = 0;
|
|||||||
|
|
||||||
struct gb_s gb;
|
struct gb_s gb;
|
||||||
palette_t palette; // Colour palette
|
palette_t palette; // Colour palette
|
||||||
|
i2s_config_t i2s_config;
|
||||||
uint_fast32_t frames = 0;
|
uint_fast32_t frames = 0;
|
||||||
|
|
||||||
#define putstdio(x) write(1, x, strlen(x))
|
#define putstdio(x) write(1, x, strlen(x))
|
||||||
@@ -205,14 +205,16 @@ void setup() {
|
|||||||
|
|
||||||
#if ENABLE_SOUND
|
#if ENABLE_SOUND
|
||||||
// Allocate memory for the stream buffer
|
// Allocate memory for the stream buffer
|
||||||
stream = malloc(AUDIO_BUFFER_SIZE_BYTES);
|
stream = (uint16_t*) malloc(AUDIO_BUFFER_SIZE_BYTES);
|
||||||
assert(stream != NULL);
|
assert(stream != NULL);
|
||||||
memset(stream, 0, AUDIO_BUFFER_SIZE_BYTES); // Zero out the stream buffer
|
memset(stream, 0, AUDIO_BUFFER_SIZE_BYTES); // Zero out the stream buffer
|
||||||
|
|
||||||
// Initialize I2S sound driver
|
// Initialize I2S sound driver
|
||||||
i2s_config_t i2s_config = i2s_get_default_config();
|
i2s_config = i2s_get_default_config();
|
||||||
i2s_config.sample_freq = AUDIO_SAMPLE_RATE;
|
i2s_config.sample_freq = AUDIO_SAMPLE_RATE;
|
||||||
i2s_config.dma_trans_count = AUDIO_SAMPLES;
|
i2s_config.dma_trans_count = AUDIO_SAMPLES;
|
||||||
|
i2s_config.data_pin = 26, // DIN
|
||||||
|
i2s_config.clock_pin_base = 27, // BCLK + LRC
|
||||||
i2s_volume(&i2s_config, 2);
|
i2s_volume(&i2s_config, 2);
|
||||||
i2s_init(&i2s_config);
|
i2s_init(&i2s_config);
|
||||||
#endif
|
#endif
|
||||||
@@ -241,8 +243,8 @@ void loop() {
|
|||||||
frames++;
|
frames++;
|
||||||
#if ENABLE_SOUND
|
#if ENABLE_SOUND
|
||||||
if (!gb.direct.frame_skip) {
|
if (!gb.direct.frame_skip) {
|
||||||
audio_callback(NULL, stream, AUDIO_BUFFER_SIZE_BYTES);
|
audio_callback(NULL, (int16_t*) stream, AUDIO_BUFFER_SIZE_BYTES);
|
||||||
i2s_dma_write(&i2s_config, stream);
|
i2s_dma_write(&i2s_config, (int16_t*) stream);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user