From 89ae9aea6e7dd818ff0044cdb1ddff8848f3045e Mon Sep 17 00:00:00 2001 From: Ram Dobson Date: Tue, 14 Feb 2023 16:02:09 -0500 Subject: [PATCH 1/9] custom instruments --- source/Audio.cpp | 213 +++++++++++++++++++++++++++----------------- source/Audio.h | 3 +- source/PicoRam.h | 25 +++++- test/audiotests.cpp | 105 ++++++++++++++++++++++ 4 files changed, 263 insertions(+), 83 deletions(-) diff --git a/source/Audio.cpp b/source/Audio.cpp index 8b4f0594..314cc264 100644 --- a/source/Audio.cpp +++ b/source/Audio.cpp @@ -265,6 +265,8 @@ static float key_to_freq(float key) return 440.f * exp2((key - 33.f) / 12.f); } +const float C2_FREQ = key_to_freq(24); + int16_t Audio::getCurrentSfxId(int channel){ return _audioState._sfxChannels[channel].sfxId; } @@ -287,109 +289,77 @@ int16_t Audio::getMusicTickCount(){ return _audioState._musicChannel.offset * _audioState._musicChannel.speed; } -//adapted from zepto8 sfx.cpp (wtfpl license) -int16_t Audio::getSampleForChannel(int channelId){ - using std::fabs; - using std::fmod; - using std::floor; +float Audio::getSampleForSfx(rawSfxChannel &channel, float freqShift) { using std::max; - int const samples_per_second = 22050; - int16_t sample = 0; - - const int index = _audioState._sfxChannels[channelId].sfxId; - - sfxChannel *channel = &_audioState._sfxChannels[channelId]; - - // Advance music using the master channel - if (channelId == _audioState._musicChannel.master && _audioState._musicChannel.pattern != -1) - { - float const offset_per_second = 22050.f / (183.f * _audioState._musicChannel.speed); - float const offset_per_sample = offset_per_second / samples_per_second; - _audioState._musicChannel.offset += offset_per_sample; - _audioState._musicChannel.volume += _audioState._musicChannel.volume_step / samples_per_second; - _audioState._musicChannel.volume = clamp(_audioState._musicChannel.volume, 0.f, 1.f); - - if (_audioState._musicChannel.volume_step < 0 && _audioState._musicChannel.volume <= 0) - { - // Fade out is finished, stop playing the current song - for (int i = 0; i < 4; ++i) { - if (_audioState._sfxChannels[i].is_music) { - _audioState._sfxChannels[i].sfxId = -1; - } - } - _audioState._musicChannel.pattern = -1; - } - else if (_audioState._musicChannel.offset >= _audioState._musicChannel.length) - { - int16_t next_pattern = _audioState._musicChannel.pattern + 1; - int16_t next_count = _audioState._musicChannel.count + 1; - //todo: pull out these flags, get memory storage correct as well - if (_memory->songs[_audioState._musicChannel.pattern].getStop()) //stop part of the loop flag - { - next_pattern = -1; - next_count = _audioState._musicChannel.count; - } - else if (_memory->songs[_audioState._musicChannel.pattern].getLoop()){ - while (--next_pattern > 0 && !_memory->songs[next_pattern].getStart()) - ; - } - - _audioState._musicChannel.count = next_count; - set_music_pattern(next_pattern); - } - } - - if (index < 0 || index > 63) { + if (channel.sfxId < 0 || channel.sfxId > 63) { //no (valid) sfx here. return silence return 0; } - - struct sfx const &sfx = _memory->sfx[index]; + struct sfx const &sfx = _memory->sfx[channel.sfxId]; // Speed must be 1—255 otherwise the SFX is invalid int const speed = max(1, (int)sfx.speed); - float const offset = channel->offset; - // PICO-8 exports instruments as 22050 Hz WAV files with 183 samples // per speed unit per note, so this is how much we should advance float const offset_per_second = 22050.f / (183.f * speed); float const offset_per_sample = offset_per_second / samples_per_second; - float next_offset = offset + offset_per_sample; + float next_offset = channel.offset + offset_per_sample; // Handle SFX loops. From the documentation: “Looping is turned // off when the start index >= end index”. float const loop_range = float(sfx.loopRangeEnd - sfx.loopRangeStart); - if (loop_range > 0.f && next_offset >= sfx.loopRangeStart && channel->can_loop) { + if (loop_range > 0.f && next_offset >= sfx.loopRangeStart && channel.can_loop) { next_offset = fmod(next_offset - sfx.loopRangeStart, loop_range) + sfx.loopRangeStart; } - int const note_idx = (int)floor(offset); - channel->current_note.n=sfx.notes[note_idx]; + int const note_idx = (int)floor(channel.offset); + channel.current_note.n=sfx.notes[note_idx]; int const next_note_idx = (int)floor(next_offset); - uint8_t key = sfx.notes[note_idx].getKey(); - float volume = sfx.notes[note_idx].getVolume() / 7.f; + /* + if (volume == 0.f){ + //volume all the way off. return silence, but make sure to set stuff + channel.offset = next_offset; + + if (next_offset >= 32.f){ + channel.sfxId = -1; + if (channel.getChildChannel()) { + channel.getChildChannel()->sfxId = -1; + } + } + else if (next_note_idx != note_idx){ + channel.prev_note = sfx.notes[note_idx]; + } + + return 0; + } + */ + // tiniest fade in/out to fix popping // the real version uses a crossfade it looks like // 25 samples was estimated from looking at pcm out from pico-8 float const fade_duration = offset_per_sample * 25; - float offset_part = fmod(channel->offset, 1.f); + float offset_part = fmod(channel.offset, 1.f); float crossfade = 0; if (offset_part < fade_duration) { crossfade = (fade_duration-offset_part)/fade_duration; } - float waveform = this->getSampleForNote(channel->current_note, *channel, channel->prev_note.n, false); + + bool custom = (bool) sfx.notes[note_idx].getCustom() && channel.getChildChannel() != NULL; + // it seems we're not allowed to play custom instruments + // recursively inside a custom instrument. + float waveform = this->getSampleForNote(channel.current_note, channel, channel.getChildChannel(), channel.prev_note.n, freqShift, false); if (crossfade > 0) { waveform *= (1.0f-crossfade); note dummyNote; - waveform+= crossfade * this->getSampleForNote(channel->prev_note, *channel, dummyNote, true); + waveform+= crossfade * this->getSampleForNote(channel.prev_note, channel, channel.getPrevChildChannel(), dummyNote, freqShift, true); } uint8_t len = sfx.loopRangeEnd == 0 ? 32 : sfx.loopRangeEnd; bool lastNote = note_idx == len - 1; @@ -399,31 +369,37 @@ int16_t Audio::getSampleForChannel(int channelId){ // Apply master music volume from fade in/out // FIXME: check whether this should be done after distortion - if (channel->is_music) { + if (channel.is_music) { waveform *= _audioState._musicChannel.volume; } - channel->offset = next_offset; + channel.offset = next_offset; if (next_offset >= 32.f){ - channel->sfxId = -1; + channel.sfxId = -1; + if (custom) { + channel.getChildChannel()->sfxId = -1; + } } else if (next_note_idx != note_idx){ - channel->prev_note = channel->current_note; //sfx.notes[note_idx].getKey(); - channel->current_note.n = sfx.notes[next_note_idx]; - channel->current_note.phi = channel->prev_note.phi; + channel.prev_note = channel.current_note; //sfx.notes[note_idx].getKey(); + channel.current_note.n = sfx.notes[next_note_idx]; + channel.current_note.phi = channel.prev_note.phi; + if (custom) { + if (!sfx.notes[next_note_idx].getCustom() || + sfx.notes[next_note_idx].getKey() != sfx.notes[note_idx].getKey() || + sfx.notes[next_note_idx].getWaveform() != sfx.notes[note_idx].getWaveform() + ) { + channel.rotateChannels(); + channel.getChildChannel()->sfxId = -1; + } + } } + return waveform; - sample = (int16_t)(32767.99f * waveform); - - // TODO: Apply hardware effects - if (_memory->hwState.distort & (1 << channelId)) { - sample = sample / 0x1000 * 0x1249; - } - return sample; } -float Audio::getSampleForNote(noteChannel &channel, sfxChannel &parentChannel, note prev_note, bool forceRemainder) { +float Audio::getSampleForNote(noteChannel &channel, rawSfxChannel &parentChannel, rawSfxChannel *childChannel, note prev_note, float freqShift, bool forceRemainder) { using std::max; float offset = parentChannel.offset; int const samples_per_second = 22050; @@ -490,9 +466,86 @@ float Audio::getSampleForNote(noteChannel &channel, sfxChannel &parentChannel, break; } } + freq*=freqShift; + bool custom = (bool) channel.n.getCustom() && childChannel != NULL; float waveform; - waveform = volume * z8::synth::waveform(channel.n.getWaveform(), channel.phi); + if (custom) { + if (childChannel->sfxId == -1) { + // initialize child channel + childChannel->sfxId = channel.n.getWaveform(); + childChannel->offset = 0; + childChannel->current_note.phi = 0; + childChannel->can_loop = true; + // don't want to double lower volume for music subchannel + childChannel->is_music = false; + childChannel->prev_note.n.setKey(0); + childChannel->prev_note.n.setVolume(0); + } + waveform = volume * this->getSampleForSfx(*childChannel, freq/C2_FREQ); + } else { + waveform = volume * z8::synth::waveform(channel.n.getWaveform(), channel.phi); + } channel.phi = channel.phi + freq / samples_per_second; return waveform; } + + +//adapted from zepto8 sfx.cpp (wtfpl license) +int16_t Audio::getSampleForChannel(int channel){ + using std::fabs; + using std::fmod; + using std::floor; + using std::max; + + int const samples_per_second = 22050; + + int16_t sample = 0; + + // Advance music using the master channel + if (channel == _audioState._musicChannel.master && _audioState._musicChannel.pattern != -1) + { + float const offset_per_second = 22050.f / (183.f * _audioState._musicChannel.speed); + float const offset_per_sample = offset_per_second / samples_per_second; + _audioState._musicChannel.offset += offset_per_sample; + _audioState._musicChannel.volume += _audioState._musicChannel.volume_step / samples_per_second; + _audioState._musicChannel.volume = clamp(_audioState._musicChannel.volume, 0.f, 1.f); + + if (_audioState._musicChannel.volume_step < 0 && _audioState._musicChannel.volume <= 0) + { + // Fade out is finished, stop playing the current song + for (int i = 0; i < 4; ++i) { + if (_audioState._sfxChannels[i].is_music) { + _audioState._sfxChannels[i].sfxId = -1; + } + } + _audioState._musicChannel.pattern = -1; + } + else if (_audioState._musicChannel.offset >= _audioState._musicChannel.length) + { + int16_t next_pattern = _audioState._musicChannel.pattern + 1; + int16_t next_count = _audioState._musicChannel.count + 1; + //todo: pull out these flags, get memory storage correct as well + if (_memory->songs[_audioState._musicChannel.pattern].getStop()) //stop part of the loop flag + { + next_pattern = -1; + next_count = _audioState._musicChannel.count; + } + else if (_memory->songs[_audioState._musicChannel.pattern].getLoop()){ + while (--next_pattern > 0 && !_memory->songs[next_pattern].getStart()) + ; + } + + _audioState._musicChannel.count = next_count; + set_music_pattern(next_pattern); + } + } + + sample = (int16_t) (32767.99f * this->getSampleForSfx(_audioState._sfxChannels[channel])); + + // TODO: Apply hardware effects + if (_memory->hwState.distort & (1 << channel)) { + sample = sample / 0x1000 * 0x1249; + } + return sample; +} diff --git a/source/Audio.h b/source/Audio.h index 864335ec..4d8f4dbd 100644 --- a/source/Audio.h +++ b/source/Audio.h @@ -93,8 +93,9 @@ class Audio { void set_music_pattern(int pattern); public: + float getSampleForSfx(rawSfxChannel &channel, float freqShift = 1.0f); int16_t getSampleForChannel(int channel); - float getSampleForNote(noteChannel &channel, sfxChannel &parentChannel, note prev_note, bool forceRemainder); + float getSampleForNote(noteChannel ¬e_channel, rawSfxChannel &parentChannel, rawSfxChannel *childChannel, note prev_note, float freqShift, bool forceRemainder); public: Audio(PicoRam* memory); diff --git a/source/PicoRam.h b/source/PicoRam.h index 90d66f07..ff4c4e9b 100644 --- a/source/PicoRam.h +++ b/source/PicoRam.h @@ -135,13 +135,35 @@ struct noteChannel { note n; }; -struct sfxChannel { +struct rawSfxChannel { int16_t sfxId = -1; float offset = 0; bool can_loop = true; bool is_music = false; noteChannel current_note; noteChannel prev_note; + virtual rawSfxChannel *getChildChannel() { + return NULL; + } + virtual rawSfxChannel *getPrevChildChannel() { + return NULL; + } + virtual void rotateChannels() { + } +}; + +struct sfxChannel : rawSfxChannel { + rawSfxChannel customInstrumentChannel; + rawSfxChannel prevInstrumentChannel; + virtual rawSfxChannel *getChildChannel() { + return &(this->customInstrumentChannel); + } + virtual rawSfxChannel *getPrevChildChannel() { + return &(this->prevInstrumentChannel); + } + virtual void rotateChannels() { + prevInstrumentChannel = customInstrumentChannel; + } }; struct audioState_t { @@ -295,4 +317,3 @@ struct PicoRam uint8_t data[0x10000]; }; }; - diff --git a/test/audiotests.cpp b/test/audiotests.cpp index f9cc6b7a..4e019465 100644 --- a/test/audiotests.cpp +++ b/test/audiotests.cpp @@ -59,6 +59,111 @@ TEST_CASE("audio class behaves as expected") { Audio* audio = new Audio(&picoRam); audioState_t* audioState = audio->getAudioState(); + SUBCASE("custom instruments same note"){ + note c; + + c.setCustom(true); + c.setWaveform(1); + c.setVolume(5); + c.setKey(24); + + picoRam.sfx[0].speed = 32; + picoRam.sfx[0].notes[0] = c; + picoRam.sfx[0].notes[1] = c; + + picoRam.sfx[1].speed=8; + //183 is one tick + for (int i=0;i<8;i++) { + picoRam.sfx[1].notes[i].setVolume(5); + picoRam.sfx[1].notes[i].setWaveform(1); + } + picoRam.sfx[1].notes[0].setKey(24); + picoRam.sfx[1].notes[1].setKey(26); + picoRam.sfx[1].notes[2].setKey(28); + picoRam.sfx[1].notes[3].setKey(29); + picoRam.sfx[1].notes[4].setKey(31); + picoRam.sfx[1].notes[5].setKey(33); + picoRam.sfx[1].notes[6].setKey(35); + picoRam.sfx[1].notes[7].setKey(36); + + sfxChannel s; + s.sfxId=0; + s.offset=0; + s.current_note.phi=0; + + for (int i=0; i<183*4; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 24); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 26); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 28); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 29); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 31); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 33); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 35); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 36); + } + + SUBCASE("custom instruments different note"){ + note c,d; + + c.setCustom(true); + c.setWaveform(1); + c.setVolume(5); + c.setKey(24); + d.setCustom(true); + d.setWaveform(1); + d.setVolume(5); + d.setKey(26); + + picoRam.sfx[0].speed = 32; + picoRam.sfx[0].notes[0] = c; + picoRam.sfx[0].notes[1] = d; + + picoRam.sfx[1].speed=8; + //183 is one tick + for (int i=0;i<8;i++) { + picoRam.sfx[1].notes[i].setVolume(5); + picoRam.sfx[1].notes[i].setWaveform(1); + } + picoRam.sfx[1].notes[0].setKey(24); + picoRam.sfx[1].notes[1].setKey(26); + picoRam.sfx[1].notes[2].setKey(28); + picoRam.sfx[1].notes[3].setKey(29); + picoRam.sfx[1].notes[4].setKey(31); + picoRam.sfx[1].notes[5].setKey(33); + picoRam.sfx[1].notes[6].setKey(35); + picoRam.sfx[1].notes[7].setKey(36); + + sfxChannel s; + s.sfxId=0; + s.offset=0; + s.current_note.phi=0; + + for (int i=0; i<183*4; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 24); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 26); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 28); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 29); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 24); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 26); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 28); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + CHECK_EQ(s.getChildChannel()->current_note.n.getKey(), 29); + for (int i=0; i<183*8; i++) { audio->getSampleForSfx(s); } + } + SUBCASE("Audio constructor sets sfx channels to -1") { bool allChannelsOff = true; From 94c56842a93b35d456cfba8b63e69867650d81ce Mon Sep 17 00:00:00 2001 From: Jon Bell Date: Sun, 19 Feb 2023 19:21:53 -0700 Subject: [PATCH 2/9] Add new cart ctor to load png cart from memory --- source/cart.cpp | 85 ++++++++++++++++++++++++++++++------------ source/cart.h | 3 ++ source/filehelpers.cpp | 18 +++++++++ source/filehelpers.h | 3 ++ test/carttests.cpp | 22 +++++++++++ 5 files changed, 108 insertions(+), 23 deletions(-) diff --git a/source/cart.cpp b/source/cart.cpp index 0383df3f..53244573 100644 --- a/source/cart.cpp +++ b/source/cart.cpp @@ -150,29 +150,8 @@ static std::string pxa_decompress(uint8_t const *input) #define HEADERLEN 8 - -bool Cart::loadCartFromPng(std::string filename){ - std::vector image; //the raw pixels - unsigned width, height; - - //decode - unsigned error = lodepng::decode(image, width, height, filename); - //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, - - //if there's an error, display it - if(error) { - LoadError = "png decoder error " + std::string(lodepng_error_text(error)); - Logger_Write("%s%s", LoadError.c_str(), "\n"); - return false; - } - - if (width != 160 || height != 205) { - LoadError = "Invalid png dimensions"; - Logger_Write("invalid dimensions\n"); - return false; - } - - //160x205 == 32800 == 0x8020 +bool Cart::loadCartFromPng(std::vector image) { + //160x205 == 32800 == 0x8020 //0x8000 is actual used data size size_t imageBytes = image.size(); @@ -294,11 +273,71 @@ bool Cart::loadCartFromPng(std::string filename){ } return true; +} + +bool Cart::loadCartFromPng(const unsigned char* cartData, size_t size){ + std::vector image; //the raw pixels + unsigned width, height; + + //decode + unsigned error = lodepng::decode(image, width, height, cartData, size); + + //if there's an error, display it + if(error) { + LoadError = "png decoder error " + std::string(lodepng_error_text(error)); + Logger_Write("%s%s", LoadError.c_str(), "\n"); + return false; + } + + if (width != 160 || height != 205) { + LoadError = "Invalid png dimensions"; + Logger_Write("invalid dimensions\n"); + return false; + } + + return loadCartFromPng(image); +} + + +bool Cart::loadCartFromPng(std::string filename){ + std::vector image; //the raw pixels + unsigned width, height; + + //decode + unsigned error = lodepng::decode(image, width, height, filename); + //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, + + //if there's an error, display it + if(error) { + LoadError = "png decoder error " + std::string(lodepng_error_text(error)); + Logger_Write("%s%s", LoadError.c_str(), "\n"); + return false; + } + + if (width != 160 || height != 205) { + LoadError = "Invalid png dimensions"; + Logger_Write("invalid dimensions\n"); + return false; + } + return loadCartFromPng(image); } static std::regex _includeRegex = std::regex("\\s*#include\\s+([\\\\/A-Za-z0-9_\\-\\.]+)"); +Cart::Cart (const unsigned char* cartData, size_t size){ + //TODO: check if it is a text cart, decode string, then parse + bool success = loadCartFromPng(cartData, size); + + if (!success){ + return; + } + + LoadError = ""; + Logger_Write("got valid png cart\n"); + +} + //tac08 based cart parsing and stripping of emoji Cart::Cart(std::string filename, std::string cartDirectory){ //the leading # indicates it is the BBS key. In the future, it would be nice to fetch them, diff --git a/source/cart.h b/source/cart.h index b5f95511..a2208abc 100644 --- a/source/cart.h +++ b/source/cart.h @@ -35,9 +35,12 @@ class Cart { void setMusic(std::string musicString); bool loadCartFromPng(std::string filename); + bool loadCartFromPng(const unsigned char* cartData, size_t size); + bool loadCartFromPng(std::vector image); public: Cart (std::string filename, std::string cartDirectory); + Cart (const unsigned char* cartData, size_t size); ~Cart(); std::string FullCartPath; diff --git a/source/filehelpers.cpp b/source/filehelpers.cpp index 50099d18..fc9a6fc1 100644 --- a/source/filehelpers.cpp +++ b/source/filehelpers.cpp @@ -19,6 +19,24 @@ std::string get_file_contents(std::string filename){ return ""; } +std::vector get_file_as_buffer(std::string filename){ + std::ifstream in(filename, std::ios::in | std::ios::binary); + if (in) + { + in.seekg(0, std::ios::end); + std::streamsize size = in.tellg(); + in.seekg(0, std::ios::beg); + + std::vector buffer(size); + if (in.read(buffer.data(), size)) { + return buffer; + } + } + + std::vector buffer(0); + return buffer; +} + std::string get_first_four_chars(std::string filename){ std::ifstream in(filename, std::ios::in | std::ios::binary); if (in) diff --git a/source/filehelpers.h b/source/filehelpers.h index a4c9b029..1482ca4b 100644 --- a/source/filehelpers.h +++ b/source/filehelpers.h @@ -1,7 +1,10 @@ #include +#include std::string get_file_contents(std::string filename); +std::vector get_file_as_buffer(std::string filename); + std::string get_first_four_chars(std::string filename); std::string getDirectory(const std::string& fname); diff --git a/test/carttests.cpp b/test/carttests.cpp index b3fa6f52..73868921 100644 --- a/test/carttests.cpp +++ b/test/carttests.cpp @@ -1,5 +1,6 @@ #include "doctest.h" #include "../source/cart.h" +#include "../source/filehelpers.h" TEST_CASE("Loads bios cart") { Cart* cart = new Cart("__FAKE08-BIOS.p8", ""); @@ -224,5 +225,26 @@ TEST_CASE("cart loading options") { CHECK(cart->FullCartPath == "carts/cartparsetest.p8"); } + delete cart; +} + +TEST_CASE("Load legacy png cart from memory") { + auto buffer = get_file_as_buffer("carts/test_legacypng_cart.p8.png"); + const unsigned char* char_array = reinterpret_cast(buffer.data()); + Cart* cart = new Cart(char_array, buffer.size()); + + SUBCASE("error is empty") { + CHECK(cart->LoadError == ""); + } + SUBCASE("Lua section is populated") { + CHECK(cart->LuaString == "print(\"0.1.10c\")\n"); + } + SUBCASE("Gfx data is populated") { + CHECK(cart->CartRom.SpriteSheetData[0] == 0); + CHECK(cart->CartRom.SpriteSheetData[1] == 0); + CHECK(cart->CartRom.SpriteSheetData[2] == 0); + CHECK(cart->CartRom.SpriteSheetData[3] == 0); + } + delete cart; } \ No newline at end of file From 13bd0e79e4940cda6cd1712b24e36d5be48b9a2c Mon Sep 17 00:00:00 2001 From: Jon Bell Date: Sun, 19 Feb 2023 20:09:09 -0700 Subject: [PATCH 3/9] Allow libretro to load roms from memory --- platform/libretro/libretro.cpp | 17 +++++++++++++++-- source/vm.cpp | 35 +++++++++++++++++++++++++++++++++- source/vm.h | 4 ++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/platform/libretro/libretro.cpp b/platform/libretro/libretro.cpp index 927ea8d4..2b289ee8 100644 --- a/platform/libretro/libretro.cpp +++ b/platform/libretro/libretro.cpp @@ -150,7 +150,7 @@ EXPORT void retro_get_system_info(struct retro_system_info *info) info->library_name = "fake-08"; info->library_version = "0.0.2.19"; //todo: get from build flags info->valid_extensions = "p8|png"; - info->need_fullpath = true; // we load our own carts for now + info->need_fullpath = false; } EXPORT void retro_get_system_av_info(struct retro_system_av_info *info) @@ -456,13 +456,26 @@ EXPORT void retro_cheat_set(unsigned index, bool enabled, const char *code) EXPORT bool retro_load_game(struct retro_game_info const *info) { + printf("loading game\n"); auto containingDir = getDirectory(info->path); + printf("containing dir: %s\n", containingDir.c_str()); + if (containingDir.length() > 0) { setCartDirectory(containingDir); } - _vm->QueueCartChange(info->path); + if (info->size > 0) { + printf("using memory for rom. size: %zu\n", info->size); + const unsigned char* data = reinterpret_cast(info->data); + _vm->QueueCartChange(data, info->size); + + } + else { + printf("using file path for rom %s\n", info->path); + _vm->QueueCartChange(info->path); + } + return true; } diff --git a/source/vm.cpp b/source/vm.cpp index 10118dca..36316293 100644 --- a/source/vm.cpp +++ b/source/vm.cpp @@ -434,6 +434,24 @@ void Vm::LoadCart(std::string filename, bool loadBiosOnFail){ } } +void Vm::LoadCart(const unsigned char* cartData, size_t size, bool loadBiosOnFail){ + Logger_Write("Loading cart from memory\n"); + CloseCart(); + + Logger_Write("Calling Cart Constructor\n"); + Cart *cart = new Cart(cartData, size); + + _cartLoadError = cart->LoadError; + + bool success = loadCart(cart); + + if (loadBiosOnFail && !success) { + CloseCart(); + //todo: show an error message on the bios? + LoadBiosCart(); + } +} + void Vm::togglePauseMenu(){ _input->SetState(0, 0); if (_memory->drawState.suppressPause) { @@ -527,7 +545,12 @@ void Vm::UpdateAndDraw() { if (_cartChangeQueued) { _prevCartKey = CurrentCartFilename(); - LoadCart(_nextCartKey); + if (_nextCartSize > 0){ + LoadCart(_nextCartData, _nextCartSize); + } + else { + LoadCart(_nextCartKey); + } } if (_pauseMenu){ @@ -622,6 +645,16 @@ void Vm::CloseCart() { void Vm::QueueCartChange(std::string filename){ _nextCartKey = filename; + _nextCartData = nullptr; + _nextCartSize = 0; + _cartChangeQueued = true; + _pauseMenu = false; +} + +void Vm::QueueCartChange(const unsigned char* cartData, size_t size){ + _nextCartKey = ""; + _nextCartData = cartData; + _nextCartSize = size; _cartChangeQueued = true; _pauseMenu = false; } diff --git a/source/vm.h b/source/vm.h index 2107b048..e4c30318 100644 --- a/source/vm.h +++ b/source/vm.h @@ -42,6 +42,8 @@ class Vm { bool _pauseMenu; string _prevCartKey; string _nextCartKey; + const unsigned char* _nextCartData; + size_t _nextCartSize; string _cartLoadError; @@ -70,6 +72,7 @@ class Vm { void LoadSettingsCart(); void LoadCart(string filename, bool loadBiosOnFail = true); + void LoadCart(const unsigned char* cartData, size_t size, bool loadBiosOnFail = true); void UpdateAndDraw(); @@ -81,6 +84,7 @@ class Vm { void CloseCart(); void QueueCartChange(string newcart); + void QueueCartChange(const unsigned char* cartData, size_t size); int GetTargetFps(); From 6279216964e351409201e987653e3d708fd4ad78 Mon Sep 17 00:00:00 2001 From: Jon Bell Date: Tue, 21 Feb 2023 21:40:27 -0700 Subject: [PATCH 4/9] Allow loading p8 text carts from memory --- source/cart.cpp | 171 +++++++++++++++++++++++++++------------------ source/cart.h | 2 + test/Makefile | 2 +- test/carttests.cpp | 23 ++++++ 4 files changed, 129 insertions(+), 69 deletions(-) diff --git a/source/cart.cpp b/source/cart.cpp index 53244573..bd5e71f9 100644 --- a/source/cart.cpp +++ b/source/cart.cpp @@ -26,7 +26,7 @@ static char const *legacyCompressionLut = "\n 0123456789abcdefghijklmnopqrstuvwxyz!#%(){}[]<>+=/*:;.,~_"; - +static std::regex _includeRegex = std::regex("\\s*#include\\s+([\\\\/A-Za-z0-9_\\-\\.]+)"); //https://github.com/samhocevar/zepto8/blob/b1a13516945c49e47495c739e6a43a241ad99291/src/pico8/code.cpp // Move to front structure @@ -323,18 +323,111 @@ bool Cart::loadCartFromPng(std::string filename){ return loadCartFromPng(image); } -static std::regex _includeRegex = std::regex("\\s*#include\\s+([\\\\/A-Za-z0-9_\\-\\.]+)"); +bool Cart::loadCartFromString(std::string cartStr) { + fullCartText = cartStr; + + std::istringstream s(cartStr); + std::string line; + std::string currSec = ""; + std::smatch sm; + + while (std::getline(s, line)) { + line = utils::trimright(line, " \n\r"); + line = charset::utf8_to_pico8(line); + //line = convert_emojis(line); + + if (line.length() > 2 && line[0] == '_' && line[1] == '_') { + currSec = line; + } + else if (currSec == "__lua__"){ + if (std::regex_match(line, sm, _includeRegex)) { + auto dir = getDirectory(FullCartPath); + auto fullPath = dir + "/" + sm[1].str(); + + auto includeContents = get_file_contents(fullPath); + if (includeContents.length() > 0){ + includeContents = charset::utf8_to_pico8(includeContents); + LuaString += includeContents + "\n"; + } + else{ + //todo: report error + //error: can't find included file + LoadError = "Can't find included file"; + return false; + } + } + else { + LuaString += line + "\n"; + } + } + else if (currSec == "__gfx__"){ + SpriteSheetString += line + "\n"; + } + else if (currSec == "__gff__"){ + SpriteFlagsString += line + "\n"; + } + else if (currSec == "__map__"){ + MapString += line + "\n"; + } + else if (currSec == "__sfx__"){ + SfxString += line + "\n"; + } + else if (currSec == "__music__"){ + MusicString += line + "\n"; + } + else if (currSec == "__label__"){ + LabelString += line + "\n"; + } + } + + Logger_Write("Setting cart graphics rom data from strings\n"); + setSpriteSheet(SpriteSheetString); + setSpriteFlags(SpriteFlagsString); + setMapData(MapString); + + Logger_Write("Setting cart audio rom data from strings\n"); + setSfx(SfxString); + setMusic(MusicString); + + return true; +} Cart::Cart (const unsigned char* cartData, size_t size){ + if (size < 5) { + LoadError = "Invalid cart. Less than 5 bytes"; + return; + } + //TODO: check if it is a text cart, decode string, then parse - bool success = loadCartFromPng(cartData, size); + if ((char)cartData[0] == '\x89' && + (char)cartData[1] == 'P' && + (char)cartData[2] == 'N' && + (char)cartData[3] == 'G') { + bool success = loadCartFromPng(cartData, size); - if (!success){ - return; + if (!success){ + return; + } + LoadError = ""; + Logger_Write("got valid png cart\n"); } + else if((char)cartData[0] == 'p' && + (char)cartData[1] == 'i' && + (char)cartData[2] == 'c' && + (char)cartData[3] == 'o') { + std::string strContents(reinterpret_cast(cartData), size); - LoadError = ""; - Logger_Write("got valid png cart\n"); + bool success = loadCartFromString(strContents); + + if (!success){ + return; + } + LoadError = ""; + Logger_Write("got valid p8 cart\n"); + } + else { + LoadError = "unknown cart file format"; + } } @@ -377,69 +470,11 @@ Cart::Cart(std::string filename, std::string cartDirectory){ } Logger_Write("Got file contents... parsing cart\n"); - fullCartText = cartStr; - - std::istringstream s(cartStr); - std::string line; - std::string currSec = ""; - std::smatch sm; - - while (std::getline(s, line)) { - line = utils::trimright(line, " \n\r"); - line = charset::utf8_to_pico8(line); - //line = convert_emojis(line); + bool success = loadCartFromString(cartStr); - if (line.length() > 2 && line[0] == '_' && line[1] == '_') { - currSec = line; - } - else if (currSec == "__lua__"){ - if (std::regex_match(line, sm, _includeRegex)) { - auto dir = getDirectory(FullCartPath); - auto fullPath = dir + "/" + sm[1].str(); - - auto includeContents = get_file_contents(fullPath); - if (includeContents.length() > 0){ - includeContents = charset::utf8_to_pico8(includeContents); - LuaString += includeContents + "\n"; - } - else{ - //todo: report error - //error: can't find included file - return; - } - } - else { - LuaString += line + "\n"; - } - } - else if (currSec == "__gfx__"){ - SpriteSheetString += line + "\n"; - } - else if (currSec == "__gff__"){ - SpriteFlagsString += line + "\n"; - } - else if (currSec == "__map__"){ - MapString += line + "\n"; - } - else if (currSec == "__sfx__"){ - SfxString += line + "\n"; - } - else if (currSec == "__music__"){ - MusicString += line + "\n"; - } - else if (currSec == "__label__"){ - LabelString += line + "\n"; - } + if (!success){ + return; } - - Logger_Write("Setting cart graphics rom data from strings\n"); - setSpriteSheet(SpriteSheetString); - setSpriteFlags(SpriteFlagsString); - setMapData(MapString); - - Logger_Write("Setting cart audio rom data from strings\n"); - setSfx(SfxString); - setMusic(MusicString); } else if (firstFourChars == "\x89PNG") { bool success = loadCartFromPng(FullCartPath); diff --git a/source/cart.h b/source/cart.h index a2208abc..dfb27de7 100644 --- a/source/cart.h +++ b/source/cart.h @@ -37,6 +37,8 @@ class Cart { bool loadCartFromPng(std::string filename); bool loadCartFromPng(const unsigned char* cartData, size_t size); bool loadCartFromPng(std::vector image); + + bool loadCartFromString(std::string cartStr); public: Cart (std::string filename, std::string cartDirectory); diff --git a/test/Makefile b/test/Makefile index c2bdeeac..966cd1e2 100644 --- a/test/Makefile +++ b/test/Makefile @@ -16,7 +16,7 @@ INCLUDES := ../source ../include ../libs/z8lua ../libs/utf8-util ../libs/lodep #--------------------------------------------------------------------------------- CC = $(CXX) -CFLAGS := -g -O2 -Wall -Wno-deprecated -ffunction-sections -std=c++17 \ +CFLAGS := -g -Wall -Wno-deprecated -ffunction-sections -std=c++17 \ $(DEFINES) CFLAGS += $(INCLUDE) -DVER_STR=\"$(APP_VERSION)\" diff --git a/test/carttests.cpp b/test/carttests.cpp index 73868921..24e918ff 100644 --- a/test/carttests.cpp +++ b/test/carttests.cpp @@ -246,5 +246,28 @@ TEST_CASE("Load legacy png cart from memory") { CHECK(cart->CartRom.SpriteSheetData[3] == 0); } + delete cart; +} + +TEST_CASE("Load text cart from memory") { + auto buffer = get_file_as_buffer("carts/cartparsetest.p8"); + const unsigned char* char_array = reinterpret_cast(buffer.data()); + Cart* cart = new Cart(char_array, buffer.size()); + + SUBCASE("error is empty") { + CHECK(cart->LoadError == ""); + } + SUBCASE("Lua section is populated") { + CHECK(cart->LuaString == "a=1\n"); + } + SUBCASE("Gfx section is populated") { + CHECK(cart->SpriteSheetString == + "ff102030555555550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n"); + } + SUBCASE("Sprite flags section is populated") { + CHECK(cart->SpriteFlagsString == + "0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n"); + } + delete cart; } \ No newline at end of file From 0e35e233b20d97333708032edf8237935f157a98 Mon Sep 17 00:00:00 2001 From: Ram Dobson Date: Tue, 28 Feb 2023 23:16:37 -0500 Subject: [PATCH 5/9] Update miyoo mini instructions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e381540..63e53da0 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Launch FAKE-08 either via the homebrew menu or normal system UI (depending on ho For bittboy and similar consoles, back up `emus/pico8/pico8.elf` and replace it with the one from the release. Place your cart files in `roms/pico-8/` and use the front end of choice to launch games. Press the menu button to return to the menu (though you can also press start and exit to the FAKE-08 bios menu if you would like). -To launch on a Miyoo Mini you need to call the executable directly from the terminal emulator, or create a shortcut. I'm not sure exactly how that works and don't have a device to figure it out, so help is welcome if anyone would like to provide guidance there. +To launch on a Miyoo Mini you need to call the executable directly from the terminal emulator, or create a shortcut. I'm not sure exactly how that works and don't have a device to figure it out, so help is welcome if anyone would like to provide guidance there. If you are using onion OS just copy FAKE08 to the Emu/PICO directory, overwriting the existing build (make a backup first just in case). Libretro cores are still in early development but should be working. Installation can be tricky however. In general you'll need to install the core (Load Core -> Install or Restore a Core -> {Navigate to core file location}) and also drop the fake08_libretro.info into the retroarch cores directory. This directory may be hidden and its location varies from platform to platform. Once that file is in place, you should be able to scan for Pico-8 carts using "Scan Directory." If that doesn't work for some reason, you can do a "Manual Scan." If doing a manual scan, choose the directory, set the custom system name to "Pico-8", set the default core to the one you just installed, and file extensions to "p8 png" and it should add a playlist of your Pico-8 carts associated with the newly installed core. From 769c98ca5d9ad8c8e91257abe0a28cc59619b44d Mon Sep 17 00:00:00 2001 From: Jon Bell Date: Sat, 4 Mar 2023 20:08:12 -0700 Subject: [PATCH 6/9] Honor custom font dimensions Fix pico world race big numbers --- source/printHelper.cpp | 5 ++ test/carts/ppwr-big-digit-test.p8 | 60 ++++++++++++++++++ .../screenshots/ppwr-big-digit-test_f01.png | Bin 0 -> 638 bytes test/endtoendtests.cpp | 14 ++++ 4 files changed, 79 insertions(+) create mode 100644 test/carts/ppwr-big-digit-test.p8 create mode 100644 test/carts/screenshots/ppwr-big-digit-test_f01.png diff --git a/source/printHelper.cpp b/source/printHelper.cpp index 5187e199..c7b435bc 100644 --- a/source/printHelper.cpp +++ b/source/printHelper.cpp @@ -156,6 +156,11 @@ int print(std::string str, int x, int y, uint8_t c) { printMode = 0; } + if ((printMode & PRINT_MODE_CUSTOM_FONT)) { + charWidth = _ph_mem->data[0x5600]; + charHeight = _ph_mem->data[0x5602]; + } + uint8_t* drawPal = _ph_mem->drawState.drawPaletteMap; int framesBetweenChars = 0; diff --git a/test/carts/ppwr-big-digit-test.p8 b/test/carts/ppwr-big-digit-test.p8 new file mode 100644 index 00000000..31878392 --- /dev/null +++ b/test/carts/ppwr-big-digit-test.p8 @@ -0,0 +1,60 @@ +pico-8 cartridge // http://www.pico-8.com +version 41 +__lua__ +--font used from Pico World Race https://www.lexaloffle.com/bbs/?pid=106518 +--https://creativecommons.org/licenses/by-nc-sa/4.0/ +-- custom font +font="8,8,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,248,252,28,28,0,0,0,15,31,63,56,56,0,0,0,192,192,192,128,128,0,0,0,3,3,3,3,3,0,0,0,252,252,252,0,240,0,0,0,15,31,63,56,63,0,0,0,252,252,252,0,252,0,0,0,15,31,63,56,63,0,0,0,224,240,120,60,28,0,0,0,28,28,28,28,28,0,0,0,252,252,252,28,252,0,0,0,63,63,63,0,15,0,0,0,240,248,252,28,252,0,0,0,31,31,31,0,15,0,0,0,240,248,252,28,0,0,0,0,15,31,63,56,56,28,28,28,252,248,240,0,0,56,56,56,63,31,15,0,0,128,128,128,128,128,128,0,0,3,3,3,3,3,3,0,0,248,252,28,252,252,252,0,0,31,15,0,63,63,63,0,0,252,252,0,252,252,252,0,0,63,63,56,63,31,15,0,0,28,252,248,0,0,0,0,0,28,63,63,28,28,28,0,0,252,252,0,252,252,252,0,0,31,63,56,63,31,15,0,0,252,252,28,252,248,240,0,0,31,63,56,63,31,15,0,0,0,0,0,0,128,128,0,0,56,60,30,15,7,3,0,0,0,0,0,240,248,252,28,252,0,0,0,15,31,63,56,63,0,0,0,240,248,252,28,252,0,0,0,15,31,63,56,63,0,0,0,240,248,252,28,156,0,0,0,63,63,63,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252,252,28,252,248,240,0,0,63,63,56,63,31,15,0,0,252,248,0,248,248,248,0,0,63,63,56,63,63,31,0,0,156,156,28,252,248,240,0,0,63,63,56,63,63,63,0,0,0,0,0,0,0,0,0,0,0" + + +function _init() +--font init +memset(0x5600,0,256*8) +poke(0x5600,unpack(split(font))) + +end + +function _draw() +cls(1) +printbigdigitoutline( 10,50,30, 0 ) +printbigdigit(10,50,30) + +printbigdigitoutline(5,50,50,0 ) +printbigdigit(5,50,50) + +printbigdigit(3,10,10) + +printbigdigitoutline(4,10,30,7) + +printbigdigit(9,10,50) + +end + +function printbigdigit( n, x, y,nrend) +x-=2 +if not nrend then +poke(0x5f58, 0x1 | 0x80) --custom font + n1=n*2+16+n\8*16 + print(chr(n1)..chr(n1+1).."\n"..chr(n1+16)..chr(n1+17),x,y-3,7) --4 chars to print 1 big +poke(0x5f58, 0x0) --default font +end +if (n==1) return 12 +return 16 +end + +function printbigdigitoutline( n, x, y, col ) +i=n+1 +pal( 7, col ) +printbigdigit( n, x-1, y ) +printbigdigit( n, x+1, y ) +printbigdigit( n, x, y-1 ) +printbigdigit( n, x, y+1 ) +pal( 7, 7 ) +end +__gfx__ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/test/carts/screenshots/ppwr-big-digit-test_f01.png b/test/carts/screenshots/ppwr-big-digit-test_f01.png new file mode 100644 index 0000000000000000000000000000000000000000..07416717ec52f00cdd359e360ced52d9d5b68fd7 GIT binary patch literal 638 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1SEZ8zRh7^VAAw-aSW+oe0%rc#6=Dg4Hr{S z?+(|Wz#ut+Em5F9aYCEqgocy;T892gil7#J8C7L?v@&7bdo{J`B+FXtqjGFLdW*wjs+d55xwL5fW6FWCiOlsy>U zFx+IkE$i4A?sAcF&cFBCr*@Tc<=Zr|fLtfQ!0^j)x4M0~o$UMnD`w^Wy6@5JEWacA zS}q&IQDghZg?Bc)8cDSOE8E+$@7KQxjR!w*aLupVlWt%0EBYqm<;(q6#oNk$aa${# zeChw(=brV0o2ql3e33u9PoVNmLq3B_BwO@-#)Kdyl{uD|Ge7Sz+tTu$t((6hWckgP z`_~GFnBHBk{jFTaEph z*PHVFeUyG`*IljyKTGEPt-e|^(eHoRUY)u%H{^{BBIF$7=hpq0_K*L-BSGVcOwMrM z?=PdC{}%myIQ)8BnZqIV+A_(M;$Qa}DpuxQ_cmkWR?gTO_?fx6@P+wC=4F@dzwv3j zHZ%BT9DV4ta>n16_I!Weyg0wCloseCart(); } + SUBCASE("custom font test"){ + //font used from Pico World Race https://www.lexaloffle.com/bbs/?pid=106518 + //https://creativecommons.org/licenses/by-nc-sa/4.0/ + vm->LoadCart("ppwr-big-digit-test.p8"); + + SUBCASE("sceen matches screenshot"){ + vm->UpdateAndDraw(); + + CHECK(verifyScreenshot(vm, host, "carts/screenshots/ppwr-big-digit-test_f01.png")); + } + + vm->CloseCart(); + } + delete vm; delete host; From 5714443295947a112a87c1da5f47c575616cfe21 Mon Sep 17 00:00:00 2001 From: Jon Bell Date: Mon, 6 Mar 2023 18:05:00 -0700 Subject: [PATCH 7/9] Update z8lua with inext --- libs/z8lua | 2 +- test/endtoendtests.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/z8lua b/libs/z8lua index abd65e3b..3a3a47b4 160000 --- a/libs/z8lua +++ b/libs/z8lua @@ -1 +1 @@ -Subproject commit abd65e3b05e285da0c6f86912b2817e7dc6bf6ea +Subproject commit 3a3a47b437715840535af15abb5419a297ab289d diff --git a/test/endtoendtests.cpp b/test/endtoendtests.cpp index 43a20af8..62fb1445 100644 --- a/test/endtoendtests.cpp +++ b/test/endtoendtests.cpp @@ -395,7 +395,7 @@ TEST_CASE("Loading and running carts") { "poke4", "memcpy", "memset", "max", "min", "mid", "flr", "ceil", "cos", "sin", "atan2", "rnd", "srand", "band", "bor", "bxor", "bnot", "shl", "shr", "lshr", "rotl", "rotr", - "mapdraw", "extcmd" + "mapdraw", "extcmd", "next", "inext", "pairs", "ipairs" }; string missing = ""; From 565822eb98edac3c1874f0607a5479907d46e6c4 Mon Sep 17 00:00:00 2001 From: Jon Bell Date: Mon, 6 Mar 2023 18:05:49 -0700 Subject: [PATCH 8/9] bump build number --- Makefile | 2 +- platform/libretro/libretro.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index d6c3c504..15d25ccf 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ export APP_AUTHOR = jtothebell export V_MAJOR = 0 export V_MINOR = 0 export V_PATCH = 2 -export V_BUILD = 19 +export V_BUILD = 20 export APP_VERSION = v$(V_MAJOR).$(V_MINOR).$(V_PATCH).$(V_BUILD) diff --git a/platform/libretro/libretro.cpp b/platform/libretro/libretro.cpp index 927ea8d4..aac740fb 100644 --- a/platform/libretro/libretro.cpp +++ b/platform/libretro/libretro.cpp @@ -148,7 +148,7 @@ EXPORT void retro_get_system_info(struct retro_system_info *info) { memset(info, 0, sizeof(*info)); info->library_name = "fake-08"; - info->library_version = "0.0.2.19"; //todo: get from build flags + info->library_version = "0.0.2.20"; //todo: get from build flags info->valid_extensions = "p8|png"; info->need_fullpath = true; // we load our own carts for now } @@ -161,7 +161,7 @@ EXPORT void retro_get_system_av_info(struct retro_system_av_info *info) info->geometry.max_width = PicoScreenWidth; info->geometry.max_height = PicoScreenHeight; info->geometry.aspect_ratio = 1.f; - info->timing.fps = 60.f; //todo: update this to 60, then handle 30 at callback level? + info->timing.fps = 60.f; info->timing.sample_rate = 22050.f; retro_pixel_format pf = RETRO_PIXEL_FORMAT_RGB565; From 3a550491076310bc5622e35d51deb954e0ceceb9 Mon Sep 17 00:00:00 2001 From: Jon Bell Date: Mon, 6 Mar 2023 18:12:46 -0700 Subject: [PATCH 9/9] Remove logging messages --- platform/libretro/libretro.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/platform/libretro/libretro.cpp b/platform/libretro/libretro.cpp index 75ad67d5..540861cc 100644 --- a/platform/libretro/libretro.cpp +++ b/platform/libretro/libretro.cpp @@ -456,23 +456,18 @@ EXPORT void retro_cheat_set(unsigned index, bool enabled, const char *code) EXPORT bool retro_load_game(struct retro_game_info const *info) { - printf("loading game\n"); auto containingDir = getDirectory(info->path); - printf("containing dir: %s\n", containingDir.c_str()); - if (containingDir.length() > 0) { setCartDirectory(containingDir); } if (info->size > 0) { - printf("using memory for rom. size: %zu\n", info->size); const unsigned char* data = reinterpret_cast(info->data); _vm->QueueCartChange(data, info->size); } else { - printf("using file path for rom %s\n", info->path); _vm->QueueCartChange(info->path); }