Commit 1b209238 authored by Jack's avatar Jack
Browse files

working on music structure in memory, in APU and loading from .p8 file

parent 53600f43
......@@ -65,7 +65,7 @@ void LoaderP8::load(const std::string& path, Machine& m)
//TODO: not efficient but for now it's fine
std::stringstream code;
coord_t sy = 0, my = 0, fy = 0, snd = 0;
coord_t sy = 0, my = 0, fy = 0, snd = 0, msc = 0;
static constexpr size_t DIGITS_PER_PIXEL_ROW = 128;
static constexpr size_t BYTES_PER_GFX_ROW = DIGITS_PER_PIXEL_ROW / 2;
......@@ -74,6 +74,7 @@ void LoaderP8::load(const std::string& path, Machine& m)
static constexpr size_t DIGITS_PER_SPRITE_FLAGS_ROW = 128*2;
static constexpr size_t DIGITS_PER_SOUND = 168;
static constexpr size_t DIGITS_PER_MUSIC_PATTERN = 2 + 1 + 8;
for (auto& line : lines)
......@@ -167,7 +168,41 @@ void LoaderP8::load(const std::string& path, Machine& m)
break;
}
case State::MUSIC:
{
const char* p = line.c_str();
if (!line.empty())
{
sfx::Music* music = m.memory().music(msc);
/* XX AABBCCDD*/
constexpr sfx::sound_index_t UNUSED_CHANNEL = 0x40;
uint8_t flags = valueForUint8(p);
if (flags & 0b1) music->markLoopBegin();
else if (flags & 0b10) music->markLoopEnd();
else if (flags & 0b100) music->markStop();
for (sfx::channel_index_t i = 0; i < sfx::APU::CHANNEL_COUNT; ++i)
{
sfx::sound_index_t index = valueForUint8(p + 3 + 2 * i);
if (index < UNUSED_CHANNEL)
music->setSound(i, index);
else
assert(index == UNUSED_CHANNEL + i);
}
++msc;
}
break;
}
}
}
}
......
......@@ -23,6 +23,7 @@ protected:
bool willQuit;
u32 ticks;
float _lastFrameTicks;
u32 frameRate;
float ticksPerFrame;
......@@ -41,6 +42,8 @@ public:
this->ticksPerFrame = 1000 / (float)frameRate;
}
float lastFrameTicks() const { return _lastFrameTicks; }
bool init();
void deinit();
void capFPS();
......@@ -111,14 +114,12 @@ void SDL<EventHandler, Renderer>::capFPS()
u32 ticks = SDL_GetTicks();
u32 elapsed = ticks - SDL::ticks;
//printf("Ticks: %u, waiting %f ticks, aticks: %u\n", elapsed, TICKS_PER_FRAME - elapsed, Gfx::fticks);
u32 frameTime = elapsed;
_lastFrameTicks = elapsed;
if (elapsed < ticksPerFrame)
{
SDL_Delay(ticksPerFrame - elapsed);
frameTime = ticksPerFrame;
_lastFrameTicks = ticksPerFrame;
}
SDL::ticks = SDL_GetTicks();
......
......@@ -10,7 +10,8 @@ namespace r8 = retro8;
retro8::Machine machine;
GameView::GameView(ViewManager* manager) : manager(manager), _paused(false)
GameView::GameView(ViewManager* manager) : manager(manager),
_paused(false), _showFPS(false), _showCartridgeName(false)
{
}
......@@ -151,10 +152,6 @@ void GameView::render()
SDL_UpdateTexture(_outputTexture, nullptr, _output->pixels, _output->pitch);
}
text(_path, 2, 2);
SDL_Rect dest;
//SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, machine.screen());
#ifdef _WIN32
......@@ -169,6 +166,11 @@ else
dest = { 0, 0, 320, 240 };
#endif
text(_path.c_str(), 10, 10);
char buffer[16];
sprintf(buffer, "%.0f", 1000.0f / manager->lastFrameTicks());
text(buffer, 10, 22);
SDL_RenderCopy(renderer, _outputTexture, nullptr, &dest);
#if DEBUGGER
......@@ -213,10 +215,8 @@ else
SDL_RenderCopy(renderer, texture, nullptr, &destr);
SDL_DestroyTexture(texture);
SDL_FreeSurface(palettes);
}
/* palette */
{
/*static SDL_Surface* tilemap = nullptr;
......@@ -256,12 +256,13 @@ else
void GameView::text(const std::string& text, int32_t x, int32_t y)
{
constexpr float scale = 2.0;
constexpr int32_t GLYPHS_PER_ROW = 16;
for (size_t i = 0; i < text.length(); ++i)
{
SDL_Rect src = { 8 * (i % GLYPHS_PER_ROW), 8 * (i / GLYPHS_PER_ROW), 4, 6 };
SDL_Rect dest = { x + 4 * i, y, 4, 6 };
SDL_Rect src = { 8 * (text[i] % GLYPHS_PER_ROW), 8 * (text[i] / GLYPHS_PER_ROW), 4, 6 };
SDL_Rect dest = { x + 4 * i * scale, y, 4 * scale, 6 * scale };
SDL_RenderCopy(manager->renderer(), _font, &src, &dest);
}
}
......
......@@ -35,7 +35,9 @@ namespace ui
bool _paused;
void rasterize();
bool _showFPS;
bool _showCartridgeName;
void render();
void update();
......
......@@ -68,6 +68,7 @@ namespace retro8
integral_t* cartData(index_t idx) { return as<integral_t>(address::CART_DATA + idx * sizeof(integral_t)); } //TODO: ENDIANNESS!!
sfx::Sound* sound(sfx::sound_index_t i) { return as<sfx::Sound>(address::SOUNDS + sizeof(sfx::Sound)*i); }
sfx::Music* music(sfx::music_index_t i) { return as<sfx::Music>(address::MUSIC + sizeof(sfx::Music)*i); }
sprite_flags_t* spriteFlagsFor(sprite_index_t index)
{
......
......@@ -274,6 +274,7 @@ void APU::handleCommands()
if (c.channel >= 0 && c.channel < channels.size() && c.index >= 0 && c.index <= SOUND_COUNT)
{
/* overtaking channel */
auto& channel = channels[c.channel];
channel.soundIndex = c.index;
......@@ -294,6 +295,22 @@ void APU::handleCommands()
/* stop sound on channel*/
}
void APU::updateMusic()
{
if (music.music)
{
for (channel_index_t i = 0; i < CHANNEL_COUNT; ++i)
{
/* will use channel if channel is forced or there's no sound currently playing there */
bool willUseChannel = ((music.channelMask & (1 << i)) != 0) || !channels[i].sound;
}
}
}
void APU::renderSounds(int16_t* dest, size_t totalSamples)
{
handleCommands();
......
......@@ -21,6 +21,7 @@ namespace retro8
using frequency_t = int32_t;
using channel_index_t = int32_t;
using sound_index_t = int32_t;
using music_index_t = int32_t;
enum class Waveform
{
......@@ -60,11 +61,11 @@ namespace retro8
//TODO: endianness is a fail here
uint16_t value;
bool useSfx() const { return value & 0x8000; }
Effect effect() const { return Effect((value & EffectMask) >> EffectShift); }
Waveform waveform() const { return Waveform((value & WaveformMask) >> WaveformShift); }
volume_t volume() const { return (value & VolumeMask) >> VolumeShift; }
pitch_t pitch() const { return value & PitchMask; }
inline bool useSfx() const { return value & 0x8000; }
inline Effect effect() const { return Effect((value & EffectMask) >> EffectShift); }
inline Waveform waveform() const { return Waveform((value & WaveformMask) >> WaveformShift); }
inline volume_t volume() const { return (value & VolumeMask) >> VolumeShift; }
inline pitch_t pitch() const { return value & PitchMask; }
void setPitch(pitch_t pitch) { value = (value & ~PitchMask) | pitch; }
void setVolume(volume_t volume) { value = (value & ~VolumeMask) | (volume << VolumeShift); }
......@@ -83,7 +84,27 @@ namespace retro8
struct Music
{
uint8_t dummy[4];
private:
constexpr static uint8_t SOUND_INDEX_MASK = 0xb00111111;
constexpr static uint8_t CONFIG_MASK = 0xb11000000;
constexpr static uint8_t SOUND_ON_FLAG = 0b01000000;
constexpr static uint8_t LOOP_FLAG = 0b10000000;
std::array<uint8_t, 4> indices;
public:
void setSound(channel_index_t channel, sound_index_t index) { indices[channel] = (indices[channel] & CONFIG_MASK) | index | SOUND_ON_FLAG; }
void markLoopBegin() { indices[0] |= LOOP_FLAG; }
void markLoopEnd() { indices[1] |= LOOP_FLAG; }
void markStop() { indices[2] |= LOOP_FLAG; }
inline bool isLoopBegin() const { return (indices[0] & LOOP_FLAG) != 0; }
inline bool isLoopEnd() const { return (indices[1] & LOOP_FLAG) != 0; }
inline bool isStop() const { return (indices[2] & LOOP_FLAG) != 0; }
inline bool isChannelEnabled(channel_index_t channel) { return (indices[channel] & SOUND_ON_FLAG) != 0; }
sound_index_t sound(channel_index_t channel) const { return indices[channel] & SOUND_INDEX_MASK; }
};
using sound_t = Sound;
......@@ -101,6 +122,14 @@ namespace retro8
uint32_t position; // absolute
uint32_t end;
};
struct MusicState
{
std::array<SoundState, 4> channels;
Music* music;
music_index_t pattern;
uint8_t channelMask;
};
class DSP
{
......@@ -125,6 +154,10 @@ namespace retro8
class APU
{
public:
static constexpr size_t CHANNEL_COUNT = 4;
private:
retro8::Memory& memory;
struct Command
......@@ -135,17 +168,21 @@ namespace retro8
uint32_t end;
};
static constexpr size_t CHANNEL_COUNT = 4;
SDL_AudioSpec spec;
SDL_AudioDeviceID device;
std::array<SoundState, CHANNEL_COUNT> channels;
MusicState music;
std::mutex queueMutex;
std::vector<Command> queue;
void handleCommands();
void updateMusic();
public:
APU(Memory& memory) : memory(memory) { }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment