gzdoom-gles/libraries/opnmidi/chips/np2/fmgen_fmtimer.cpp
Wohlstand 87d46ddd11 Update libOPNMIDI library to 1.5.0
## 1.5.0   2020-09-28
 * Drum note length expanding is now supported in real-time mode (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!)
 * Added support for OPNA chip with Neko Project II Kai YM2602 emulator usage (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!)
 * Added VGM file dumper which allows to output OPN2 commands into VGM file. (A new MIDI to VGM tool is now created with basing on libOPNMIDI)
 * Fixed an incorrect work of CC-121 (See https://github.com/Wohlstand/libADLMIDI/issues/227 for details)
 * Internality has been refactored and improved
2020-10-04 12:50:10 +02:00

217 lines
4.7 KiB
C++

// ---------------------------------------------------------------------------
// FM sound generator common timer module
// Copyright (C) cisc 1998, 2000.
// ---------------------------------------------------------------------------
// $Id: fmtimer.cpp,v 1.1 2000/09/08 13:45:56 cisc Exp $
#include "fmgen_headers.h"
#include "fmgen_fmtimer.h"
using namespace FM;
// ---------------------------------------------------------------------------
// タイマー制御
//
void Timer::SetTimerControl(uint data)
{
uint tmp = regtc ^ data;
regtc = uint8(data);
if (data & 0x10)
ResetStatus(1);
if (data & 0x20)
ResetStatus(2);
if (tmp & 0x01)
timera_count = (data & 1) ? timera : 0;
if (tmp & 0x02)
timerb_count = (data & 2) ? timerb : 0;
}
#if 1
// ---------------------------------------------------------------------------
// タイマーA 周期設定
//
void Timer::SetTimerA(uint addr, uint data)
{
uint tmp;
regta[addr & 1] = uint8(data);
tmp = (regta[0] << 2) + (regta[1] & 3);
timera = (1024-tmp) * timer_step;
// LOG2("Timer A = %d %d us\n", tmp, timera >> 16);
}
// ---------------------------------------------------------------------------
// タイマーB 周期設定
//
void Timer::SetTimerB(uint data)
{
timerb = (256-data) * timer_step;
// LOG2("Timer B = %d %d us\n", data, timerb >> 12);
}
// ---------------------------------------------------------------------------
// タイマー時間処理
//
bool Timer::Count(int32 us)
{
bool event = false;
if (timera_count)
{
timera_count -= us << 16;
if (timera_count <= 0)
{
event = true;
TimerA();
while (timera_count <= 0)
timera_count += timera;
if (regtc & 4)
SetStatus(1);
}
}
if (timerb_count)
{
timerb_count -= us << 12;
if (timerb_count <= 0)
{
event = true;
while (timerb_count <= 0)
timerb_count += timerb;
if (regtc & 8)
SetStatus(2);
}
}
return event;
}
// ---------------------------------------------------------------------------
// 次にタイマーが発生するまでの時間を求める
//
int32 Timer::GetNextEvent()
{
uint32 ta = ((timera_count + 0xffff) >> 16) - 1;
uint32 tb = ((timerb_count + 0xfff) >> 12) - 1;
return (ta < tb ? ta : tb) + 1;
}
// ---------------------------------------------------------------------------
void Timer::DataSave(struct TimerData* data)
{
data->status = status;
data->regtc = regtc;
data->regta[0] = regta[0];
data->regta[1] = regta[1];
data->timera = timera;
data->timera_count = timera_count;
data->timerb = timerb;
data->timerb_count = timerb_count;
data->timer_step = timer_step;
}
// ---------------------------------------------------------------------------
void Timer::DataLoad(struct TimerData* data)
{
status = data->status;
regtc = data->regtc;
regta[0] = data->regta[0];
regta[1] = data->regta[1];
timera = data->timera;
timera_count = data->timera_count;
timerb = data->timerb;
timerb_count = data->timerb_count;
timer_step = data->timer_step;
}
// ---------------------------------------------------------------------------
// タイマー基準値設定
//
void Timer::SetTimerBase(uint clock)
{
timer_step = int32(1000000. * 65536 / clock);
}
#else
// ---------------------------------------------------------------------------
// タイマーA 周期設定
//
void Timer::SetTimerA(uint addr, uint data)
{
regta[addr & 1] = uint8(data);
timera = (1024 - ((regta[0] << 2) + (regta[1] & 3))) << 16;
}
// ---------------------------------------------------------------------------
// タイマーB 周期設定
//
void Timer::SetTimerB(uint data)
{
timerb = (256-data) << (16 + 4);
}
// ---------------------------------------------------------------------------
// タイマー時間処理
//
bool Timer::Count(int32 us)
{
bool event = false;
int tick = us * timer_step;
if (timera_count)
{
timera_count -= tick;
if (timera_count <= 0)
{
event = true;
TimerA();
while (timera_count <= 0)
timera_count += timera;
if (regtc & 4)
SetStatus(1);
}
}
if (timerb_count)
{
timerb_count -= tick;
if (timerb_count <= 0)
{
event = true;
while (timerb_count <= 0)
timerb_count += timerb;
if (regtc & 8)
SetStatus(2);
}
}
return event;
}
// ---------------------------------------------------------------------------
// 次にタイマーが発生するまでの時間を求める
//
int32 Timer::GetNextEvent()
{
uint32 ta = timera_count - 1;
uint32 tb = timerb_count - 1;
uint32 t = (ta < tb ? ta : tb) + 1;
return (t+timer_step-1) / timer_step;
}
// ---------------------------------------------------------------------------
// タイマー基準値設定
//
void Timer::SetTimerBase(uint clock)
{
timer_step = clock * 1024 / 15625;
}
#endif