dartboy/lib/emulator/timer.dart
2024-08-31 23:57:44 +02:00

107 lines
1.6 KiB
Dart

import 'package:dartboy/emulator/utils.dart';
enum _Clock {
clock4096,
clock262144,
clock65536,
clock16384,
}
class Timer {
int _counter = 0;
int _tima = 0;
int _tma = 0;
bool _enable = false;
_Clock _clock = _Clock.clock4096;
bool _prev = false;
bool interrupt = false;
void _sync() {
var cur = false;
if (_enable) {
int mask;
switch (_clock) {
case _Clock.clock4096:
mask = 1 << 9;
break;
case _Clock.clock262144:
mask = 1 << 3;
break;
case _Clock.clock65536:
mask = 1 << 5;
break;
case _Clock.clock16384:
mask = 1 << 7;
break;
}
cur = _counter & mask > 0;
}
if (_prev && !cur) {
_tima = _tima.wrappingAddU8(1);
if (_counter % 4 == 0 && _tima == 0) {
_tima = _tma;
interrupt = true;
}
}
_prev = cur;
}
void tick() {
_counter = _counter.wrappingAddU16(1);
_sync();
}
int readDiv() => (_counter >> 8).toU8();
void writeDiv(int _) {
_counter = 0;
}
int readTima() => _tima;
void writeTima(int val) {
_sync();
_tima = val;
}
int readTma() => _tma;
void writeTma(int val) {
_tma = val;
_sync();
}
int readTac() {
return bitpack([
false,
false,
false,
false,
false,
_enable,
isSet(_clock.index, 1),
isSet(_clock.index, 0)
]);
}
void writeTac(int val) {
_enable = isSet(val, 2);
final index = val & 3;
_clock = _Clock.values[index];
}
}