190 lines
5.1 KiB
C
190 lines
5.1 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "SynthCore.h"
|
|
#include "Player.h"
|
|
|
|
Player *GlobalPlayerPtr;
|
|
|
|
void Player32kProc(Player *player)
|
|
{
|
|
SynthAsm(&(player->synthesizer));
|
|
if (player->decoder.status == STATUS_DECODING)
|
|
player->decoder.currentTick++;
|
|
if (player->synthesizer.decayGenTick < 200)
|
|
player->synthesizer.decayGenTick += 1;
|
|
}
|
|
|
|
void ScoreDecodeProcess(Player *player)
|
|
{
|
|
uint8_t temp;
|
|
|
|
if (player->decoder.status == STATUS_DECODING)
|
|
{
|
|
if ((player->decoder.currentTick >> 8) >= player->decoder.lastScoreTick)
|
|
{
|
|
do
|
|
{
|
|
temp = *(player->decoder.scorePointer);
|
|
player->decoder.scorePointer++;
|
|
if (temp == 0xFF)
|
|
player->decoder.status = STATUS_STOP;
|
|
else
|
|
NoteOnAsm(&(player->synthesizer), temp);
|
|
} while ((temp & 0x80) == 0);
|
|
|
|
UpdateNextScoreTick(&(player->decoder));
|
|
}
|
|
}
|
|
}
|
|
|
|
void PlaySchedulerNextScore(Player *player)
|
|
{
|
|
player->scheduler.switchDirect = SCHEDULER_SCORE_NEXT;
|
|
player->scheduler.status = SCHEDULER_SWITCHING;
|
|
StopDecode(player);
|
|
}
|
|
|
|
void PlaySchedulerPreviousScore(Player *player)
|
|
{
|
|
player->scheduler.switchDirect = SCHEDULER_SCORE_PREV;
|
|
player->scheduler.status = SCHEDULER_SWITCHING;
|
|
StopDecode(player);
|
|
}
|
|
|
|
uint8_t *GetScorePhyiscalAddr(uint32_t addr)
|
|
{
|
|
return (uint8_t *)((uint32_t)(&ScoreDataList) + addr);
|
|
}
|
|
|
|
void PlaySchedulerProcess(Player *player)
|
|
{
|
|
uint32_t *ScoreList = (&(player->scheduler.scoreListHeader)->firstAddr);
|
|
|
|
switch (player->scheduler.status)
|
|
{
|
|
case SCHEDULER_READY_TO_SWITCH:
|
|
if (player->decoder.status == STATUS_STOP)
|
|
{
|
|
player->scheduler.switchDirect = SCHEDULER_SCORE_NEXT;
|
|
player->scheduler.status = SCHEDULER_SWITCHING;
|
|
StopDecode(player);
|
|
}
|
|
break;
|
|
|
|
case SCHEDULER_SWITCHING:
|
|
player->scheduler.status = player->scheduler.switchDirect;
|
|
break;
|
|
|
|
case SCHEDULER_SCORE_PREV:
|
|
player->scheduler.currentScoreIndex--;
|
|
if (player->scheduler.currentScoreIndex < 0)
|
|
player->scheduler.currentScoreIndex = player->scheduler.maxScoreNum - 1;
|
|
PlayScore(player, GetScorePhyiscalAddr(ScoreList[player->scheduler.currentScoreIndex]));
|
|
player->scheduler.status = SCHEDULER_READY_TO_SWITCH;
|
|
|
|
break;
|
|
|
|
case SCHEDULER_SCORE_NEXT:
|
|
player->scheduler.currentScoreIndex++;
|
|
if (player->scheduler.currentScoreIndex >= player->scheduler.maxScoreNum)
|
|
{
|
|
player->scheduler.status = SCHEDULER_STOP;
|
|
player->scheduler.currentScoreIndex = -1;
|
|
}
|
|
else
|
|
{
|
|
PlayScore(player, GetScorePhyiscalAddr(ScoreList[player->scheduler.currentScoreIndex]));
|
|
player->scheduler.status = SCHEDULER_READY_TO_SWITCH;
|
|
}
|
|
|
|
break;
|
|
|
|
case SCHEDULER_STOP:
|
|
/* Do nothing */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void PlayerProcess(Player *player)
|
|
{
|
|
SynthGenEnvelopeProcess(&(player->synthesizer));
|
|
ScoreDecodeProcess(player);
|
|
PlaySchedulerProcess(player);
|
|
}
|
|
|
|
void UpdateNextScoreTick(ScoreDecoder *decoder)
|
|
{
|
|
uint32_t tempU32;
|
|
uint8_t temp;
|
|
tempU32 = decoder->lastScoreTick;
|
|
do
|
|
{
|
|
temp = *(decoder->scorePointer);
|
|
decoder->scorePointer++;
|
|
tempU32 += temp;
|
|
} while (temp == 0xFF);
|
|
decoder->lastScoreTick = tempU32;
|
|
}
|
|
|
|
void StartPlayScheduler(Player *player)
|
|
{
|
|
if (ScoreDataList.identifer[0] == 'S' &&
|
|
ScoreDataList.identifer[1] == 'C' &&
|
|
ScoreDataList.identifer[2] == 'R' &&
|
|
ScoreDataList.identifer[3] == 'E')
|
|
{
|
|
player->scheduler.scoreListHeader = &ScoreDataList;
|
|
player->scheduler.currentScoreIndex = -1;
|
|
player->scheduler.maxScoreNum = (player->scheduler.scoreListHeader)->scoreCount;
|
|
player->scheduler.schedulerMode = MODE_ORDER_PLAY;
|
|
player->scheduler.status = SCHEDULER_READY_TO_SWITCH;
|
|
}
|
|
else
|
|
{
|
|
player->scheduler.status = SCHEDULER_STOP;
|
|
}
|
|
}
|
|
|
|
void SchedulerSetIntialRandomSeed(Player *player, uint8_t randomSeed)
|
|
{
|
|
player->scheduler.currentScoreIndex = (randomSeed % player->scheduler.maxScoreNum) - 1;
|
|
}
|
|
|
|
void StopPlayScheduler(Player *player)
|
|
{
|
|
StopDecode(player);
|
|
player->scheduler.status = SCHEDULER_STOP;
|
|
}
|
|
|
|
void PlayScore(Player *player, uint8_t *score)
|
|
{
|
|
player->synthesizer.hwSet(SYNTH_HW_ON);
|
|
player->decoder.currentTick = 0;
|
|
player->decoder.lastScoreTick = 0;
|
|
|
|
player->decoder.scorePointer = score;
|
|
UpdateNextScoreTick(&(player->decoder));
|
|
player->decoder.status = STATUS_DECODING;
|
|
}
|
|
|
|
void StopDecode(Player *player)
|
|
{
|
|
player->synthesizer.hwSet(SYNTH_HW_OFF);
|
|
player->decoder.status = STATUS_STOP;
|
|
player->decoder.currentTick = 0;
|
|
player->decoder.lastScoreTick = 0;
|
|
}
|
|
|
|
void PlayerInit(Player *player)
|
|
{
|
|
GlobalPlayerPtr = player;
|
|
player->decoder.status = STATUS_STOP;
|
|
player->decoder.currentTick = 0;
|
|
player->decoder.lastScoreTick = 0;
|
|
player->decoder.scorePointer = NULL;
|
|
SynthInit(&(player->synthesizer));
|
|
}
|