mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2026-10-25 15:05:25 +00:00
88 lines
1.9 KiB
C
88 lines
1.9 KiB
C
/*
|
|
Digital clock for Game Boy, reading the MBC3 real-time clock.
|
|
|
|
The cartridge header declares an MBC3 + timer + battery cart, so
|
|
the emulator runs a wall-clock RTC that starts at the current time.
|
|
Reading the clock is the same on real hardware:
|
|
|
|
- write 0x08-0x0C to 0x4000 to select a register
|
|
(0x08 seconds, 0x09 minutes, 0x0A hours, 0x0B/0x0C days+flags)
|
|
- write 0x00 then 0x01 to 0x6000 to latch the live time
|
|
- read the latched value from 0xA000
|
|
|
|
The screen redraws only when the seconds change.
|
|
*/
|
|
|
|
//#symbol ld GB_MAPPER=0x10
|
|
|
|
#include <stdint.h>
|
|
#include "gb/types.h"
|
|
#include "gb/hardware.h"
|
|
#include "gb/gb.h"
|
|
#include "gbtext.h"
|
|
|
|
// MBC3 registers
|
|
#define MBC_SELECT (*(volatile uint8_t*)0x4000)
|
|
#define MBC_LATCH (*(volatile uint8_t*)0x6000)
|
|
#define RTC_DATA (*(volatile uint8_t*)0xA000)
|
|
|
|
// latch the live clock into the readable registers
|
|
static void rtc_latch(void) {
|
|
MBC_LATCH = 0x00;
|
|
MBC_LATCH = 0x01;
|
|
}
|
|
|
|
// read a latched register (0x08-0x0C)
|
|
static uint8_t rtc_read(uint8_t reg) {
|
|
MBC_SELECT = reg;
|
|
return RTC_DATA;
|
|
}
|
|
|
|
// write two decimal digits, zero-padded
|
|
static void put2(char* p, uint8_t v) {
|
|
p[0] = '0' + (v / 10) % 10;
|
|
p[1] = '0' + (v % 10);
|
|
}
|
|
|
|
void main(void) {
|
|
char buf[9];
|
|
uint8_t last_sec = 0xFF;
|
|
uint8_t sec, min, hour;
|
|
|
|
buf[8] = '\0';
|
|
|
|
// enable cartridge RAM/RTC access
|
|
MBC_SELECT = 0x00;
|
|
*(volatile uint8_t*)0x0000 = 0x0A;
|
|
|
|
DISPLAY_OFF;
|
|
BGP_REG = 0xE4;
|
|
OBP0_REG = OBP1_REG = 0xE4;
|
|
|
|
font_init();
|
|
put_str(6, 7, "MBC3 RTC");
|
|
put_str(6, 9, "--:--:--");
|
|
|
|
SHOW_BKG;
|
|
DISPLAY_ON;
|
|
|
|
while (1) {
|
|
wait_vbl_done();
|
|
|
|
rtc_latch();
|
|
sec = rtc_read(0x08);
|
|
min = rtc_read(0x09);
|
|
hour = rtc_read(0x0A);
|
|
|
|
if (sec != last_sec) {
|
|
last_sec = sec;
|
|
put2(buf + 0, hour);
|
|
buf[2] = ':';
|
|
put2(buf + 3, min);
|
|
buf[5] = ':';
|
|
put2(buf + 6, sec);
|
|
put_str(6, 9, buf);
|
|
}
|
|
}
|
|
}
|