Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/mcume #38

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ set(NES_COMPONENTS "nes")
set(GBC_COMPONENTS "gbc")

### SMS ###
# set(SMS_COMPONENTS "sms")
set(SMS_COMPONENTS "sms")

### SNES ###
# set(SNES_COMPONENTS "snes")
Expand Down
8 changes: 8 additions & 0 deletions components/sms/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
idf_component_register(
INCLUDE_DIRS "include"
SRC_DIRS "src" "teensysms"
PRIV_INCLUDE_DIRS "teensysms"
REQUIRES box-emu-hal
)
# target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-char-subscripts -Wno-attributes -Wno-implicit-fallthrough -Wno-unused-function -Wno-unused-variable -Wno-discarded-qualifiers)
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-pointer-arith -Wno-int-conversion -Wno-parentheses)
26 changes: 26 additions & 0 deletions components/sms/include/sms.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <string>
#include <string_view>
#include <vector>

void reset_sms();
void init_sms(uint8_t *romdata, size_t rom_data_size);
void init_gg(uint8_t *romdata, size_t rom_data_size);
void load_sms(std::string_view save_path);
void save_sms(std::string_view save_path);
void start_sms_tasks();
void stop_sms_tasks();
void run_sms_rom();
void deinit_sms();
void set_sms_video_original();
void set_sms_video_fit();
void set_sms_video_fill();
std::vector<uint8_t> get_sms_video_buffer();

extern "C" {
void sms_pause_video_task();
void sms_resume_video_task();
void sms_pause_audio_task();
void sms_resume_audio_task();
}
103 changes: 103 additions & 0 deletions components/sms/src/sms.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include "sms.hpp"

// include private sms headers
extern "C" {
#include "sms.h"
#include "wrapemu.h"
#include "vdp.h"
}

#include <string>

#include "fs_init.hpp"
#include "format.hpp"
#include "spi_lcd.h"
#include "st7789.hpp"

static const int SMS_SCREEN_WIDTH = 256;
static const int SMS_SCREEN_HEIGHT = 192;
static const int SMS_VISIBLE_HEIGHT = 192;

static std::atomic<bool> scaled = false;
static std::atomic<bool> filled = true;

void set_sms_video_original() {
scaled = false;
filled = false;
}

void set_sms_video_fit() {
scaled = true;
filled = false;
}

void set_sms_video_fill() {
scaled = false;
filled = true;
}

void reset_sms() {
}

void emu_DrawLinePal16(unsigned char * VBuf, int width, int height, int line) {
// TODO: implement
}

void init_sms(uint8_t *romdata, size_t rom_data_size) {
sms_Init();
sms.ram = (uint8_t*)get_vram0();
sms.sram= (uint8_t*)get_vram1();
sms.dummy = get_frame_buffer1();
vdp.vram = get_frame_buffer0();
sms_Start(romdata, rom_data_size);
}

void init_gg(uint8_t *romdata, size_t rom_data_size) {
sms_Init();
sms.ram = (uint8_t*)get_vram0();
sms.sram= (uint8_t*)get_vram1();
sms.dummy = get_frame_buffer1();
vdp.vram = get_frame_buffer0();
gg_Start(romdata, rom_data_size);
}

void run_sms_rom() {
auto start = std::chrono::high_resolution_clock::now();
sms_Step();
// frame rate should be 60 FPS, so 1/60th second is what we want to sleep for
auto delay = std::chrono::duration<float>(1.0f/60.0f);
std::this_thread::sleep_until(start + delay);
}

void load_sms(std::string_view save_path) {
// sms_prep_emulation((char *)save_path.data(), console_sms);
}

void save_sms(std::string_view save_path) {
// save_sram((char *)save_path.data(), console_sms);
}

std::vector<uint8_t> get_sms_video_buffer() {
std::vector<uint8_t> frame(SMS_SCREEN_WIDTH * SMS_VISIBLE_HEIGHT * 2);
// the frame data for the SMS is stored in frame_buffer0 as a 8 bit index into the palette
// we need to convert this to a 16 bit RGB565 value
// uint8_t *frame_buffer0 = get_frame_buffer0();
// uint16_t *palette = nullptr; // get_sms_palette();
// for (int i = 0; i < SMS_SCREEN_WIDTH * SMS_VISIBLE_HEIGHT; i++) {
// uint8_t index = frame_buffer0[i];
// uint16_t color = palette[index];
// frame[i * 2] = color & 0xFF;
// frame[i * 2 + 1] = color >> 8;
// }
return frame;
}

void stop_sms_tasks() {
}

void start_sms_tasks() {
}

void deinit_sms() {
sms_DeInit();
}
192 changes: 192 additions & 0 deletions components/sms/teensysms/AudioPlaySystem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
extern "C" {
#include "emuapi.h"
}

#include "AudioPlaySystem.h"
#include "esp_system.h"

#include "driver/i2s.h"
#include "freertos/queue.h"
#include "string.h"
#define I2S_NUM ((i2s_port_t)0)

volatile uint16_t *Buffer;
volatile uint16_t BufferSize;


static const short square[]={
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
};

const short noise[] {
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,32767,-32767,
-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,
-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,32767,32767,-32767,
-32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,-32767,32767,32767,-32767,
-32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,-32767,-32767,
32767,-32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767,-32767,
32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,32767,32767,-32767,32767,-32767,32767,-32767,-32767,
32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,32767,-32767,32767,-32767,-32767,
};

#define NOISEBSIZE 0x100

typedef struct
{
unsigned int spos;
unsigned int sinc;
unsigned int vol;
} Channel;

volatile bool playing = false;


static Channel chan[6] = {
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0} };


static void snd_Reset(void)
{
chan[0].vol = 0;
chan[1].vol = 0;
chan[2].vol = 0;
chan[3].vol = 0;
chan[4].vol = 0;
chan[5].vol = 0;
chan[0].sinc = 0;
chan[1].sinc = 0;
chan[2].sinc = 0;
chan[3].sinc = 0;
chan[4].sinc = 0;
chan[5].sinc = 0;
}

#ifdef CUSTOM_SND
extern "C" {
void SND_Process(void *sndbuffer, int sndn);
}
#endif


static void snd_Mixer16(uint16_t * stream, int len )
{
if (playing)
{
#ifdef CUSTOM_SND
SND_Process((void*)stream, len);
#else
int i;
long s;
//len = len >> 1;

short v0=chan[0].vol;
short v1=chan[1].vol;
short v2=chan[2].vol;
short v3=chan[3].vol;
short v4=chan[4].vol;
short v5=chan[5].vol;
for (i=0;i<len;i++)
{
s = ( v0*(square[(chan[0].spos>>8)&0x3f]) );
s+= ( v1*(square[(chan[1].spos>>8)&0x3f]) );
s+= ( v2*(square[(chan[2].spos>>8)&0x3f]) );
s+= ( v3*(noise[(chan[3].spos>>8)&(NOISEBSIZE-1)]) );
s+= ( v4*(noise[(chan[4].spos>>8)&(NOISEBSIZE-1)]) );
s+= ( v5*(noise[(chan[5].spos>>8)&(NOISEBSIZE-1)]) );
*stream++ = int16_t((s>>11));
chan[0].spos += chan[0].sinc;
chan[1].spos += chan[1].sinc;
chan[2].spos += chan[2].sinc;
chan[3].spos += chan[3].sinc;
chan[4].spos += chan[4].sinc;
chan[5].spos += chan[5].sinc;
}
#endif
}
}

void AudioPlaySystem::begin(void)
{
}

void AudioPlaySystem::start(void)
{
playing = true;
}

void AudioPlaySystem::setSampleParameters(float clockfreq, float samplerate) {
}

void AudioPlaySystem::reset(void)
{
snd_Reset();
}

void AudioPlaySystem::stop(void)
{
playing = false;
}

bool AudioPlaySystem::isPlaying(void)
{
return playing;
}


void AudioPlaySystem::sound(int C, int F, int V) {
if (C < 6) {
//printf("play %d %d %d\n",C,F,V);

chan[C].vol = V;
chan[C].sinc = F>>1;
}
}

void AudioPlaySystem::step(void)
{
if (playing) {
int left=DEFAULT_SAMPLERATE/50;

while(left) {
int n=DEFAULT_SAMPLESIZE;
if (n>left) n=left;
snd_Mixer16((uint16_t*)Buffer, n);
//16 bit mono -> 16 bit r+l
for (int i=n-1; i>=0; i--) {
Buffer[i*2+1]=Buffer[i]+32767;
Buffer[i*2]=Buffer[i]+32767;
}
// TODO: update this to use hal
// i2s_write_bytes(I2S_NUM, (const void*)Buffer, n*4, portMAX_DELAY);
left-=n;
}
}
}
23 changes: 23 additions & 0 deletions components/sms/teensysms/AudioPlaySystem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef audioplaysystem_h_
#define audioplaysystem_h_

#define DEFAULT_SAMPLESIZE 512 // 22050/50=443 samples per 20ms
#define DEFAULT_SAMPLERATE 22050

class AudioPlaySystem
{
public:
AudioPlaySystem(void) { begin(); }
void begin(void);
void setSampleParameters(float clockfreq, float samplerate);
void reset(void);
void start(void);
void stop(void);
bool isPlaying(void);
void sound(int C, int F, int V);
void buzz(int size, int val);
void step(void);
};


#endif
Loading
Loading