-
Notifications
You must be signed in to change notification settings - Fork 2
/
emu.c
131 lines (106 loc) · 2.51 KB
/
emu.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "gnuboy.h"
#include "defs.h"
#include "regs.h"
#include "hw.h"
#include "cpu.h"
#include "sound.h"
#include "mem.h"
#include "lcd.h"
#include "rtc.h"
#include "rc.h"
static int framelen = 16743;
static int framecount;
rcvar_t emu_exports[] =
{
RCV_INT("framelen", &framelen),
RCV_INT("framecount", &framecount),
RCV_END
};
void emu_init()
{
}
/*
* emu_reset is called to initialize the state of the emulated
* system. It should set cpu registers, hardware registers, etc. to
* their appropriate values at powerup time.
*/
void emu_reset()
{
hw_reset();
lcd_reset();
cpu_reset();
mbc_reset();
sound_reset();
}
/* emu_step()
make CPU catch up with LCDC
*/
void emu_step()
{
cpu_emulate(cpu.lcdc);
}
/*
Time intervals throughout the code, unless otherwise noted, are
specified in double-speed machine cycles (2MHz), each unit
roughly corresponds to 0.477us.
For CPU each cycle takes 2dsc (0.954us) in single-speed mode
and 1dsc (0.477us) in double speed mode.
Although hardware gbc LCDC would operate at completely different
and fixed frequency, for emulation purposes timings for it are
also specified in double-speed cycles.
line = 228 dsc (109us)
frame (154 lines) = 35112 dsc (16.7ms)
of which
visible lines x144 = 32832 dsc (15.66ms)
vblank lines x10 = 2280 dsc (1.08ms)
*/
void emu_run()
{
void *timer = sys_timer();
int delay;
vid_begin();
lcd_begin();
for (;;)
{
/* FRAME BEGIN */
/* FIXME: djudging by the time specified this was intended
to emulate through vblank phase which is handled at the
end of the loop. */
cpu_emulate(2280);
/* FIXME: R_LY >= 0; comparsion to zero can also be removed
altogether, R_LY is always 0 at this point */
while (R_LY > 0 && R_LY < 144)
{
/* Step through visible line scanning phase */
emu_step();
}
/* VBLANK BEGIN */
vid_end();
rtc_tick();
sound_mix();
/* pcm_submit() introduces delay, if it fails we use
sys_sleep() instead */
if (!pcm_submit())
{
delay = framelen - sys_elapsed(timer);
sys_sleep(delay);
sys_elapsed(timer);
}
doevents();
vid_begin();
if (framecount) { if (!--framecount) message("finished\n"); die(2,1);}
if (!(R_LCDC & 0x80)) {
/* LCDC operation stopped */
/* FIXME: djudging by the time specified, this is
intended to emulate through visible line scanning
phase, even though we are already at vblank here */
cpu_emulate(32832);
}
while (R_LY > 0) {
/* Step through vblank phase */
emu_step();
}
/* VBLANK END */
/* FRAME END */
}
}