Also, cycles_to_next_video_update in core was moved to cycles_to_next_update in video.
GBVideo::GBVideo(GameBoy *core):
display(0),
core(core),
+ cur_window_line(0),
+ mode(2),
OAM(),
+ OAM_BUSY(false),
+ VRAM_BUSY(false),
frames_rendered(0),
t0(0),
t_last_frame(0),
oldscreen(0), newscreen(0),
- cur_window_line(0),
- mode(2),
- display_mode(NORMAL)
+ display_mode(NORMAL),
+ cycles_until_next_update(0)
{
SDL_Init(SDL_INIT_VIDEO);
display=SDL_SetVideoMode(320,288,32,SDL_SWSURFACE | SDL_DOUBLEBUF);
delete [] newscreen;
}
+void GBVideo::reset()
+{
+ cycles_until_next_update = 0;
+}
+
#if 0
u8 GBVideo::read_VRAM (int addr) const
{
// mode 0 starts at 252, 708, 1164...
// vblank starts at 65664
- int cycles_until_next_update=0;
int STAT = core->memory.high[GBMemory::I_STAT];
int LYC = core->memory.high[GBMemory::I_LYC];
int LY = core->memory.high[GBMemory::I_LY];
case 0:
// HBlank (preserve bits 2-6, mode = 0)
STAT = (STAT&0xFC);
+ OAM_BUSY = false;
+ VRAM_BUSY = false;
if (check_bit(STAT, 3))
{
logger.trace("Requesting IRQ_LCD_STAT -- HBLANK");
mode = 2;
break;
case 1:
+ OAM_BUSY = false;
+ VRAM_BUSY = false;
if (LY == 144)
{
logger.trace("Requesting IRQ_VBLANK");
mode = 1;
break;
case 2: {
+ OAM_BUSY = true;
+ VRAM_BUSY = false;
if (LY == LYC)
{
STAT = set_bit(STAT, 2); // set coincidence flag
break;
}
case 3:
+ OAM_BUSY = false;
+ VRAM_BUSY = true;
draw();
// preserve bits 2-6, set mode 3
STAT = (STAT&0xFC) | 3;
bool operator< (const Sprite& other) const { return (x < other.x); }
};
- SDL_Surface *display;
- GameBoy *core;
-
u8 VRAM[8192];
union {
u8 raw[160];
EIGHT_BY_EIGHT=0,
EIGHT_BY_SIXTEEN=1,
};
+
+
+ SDL_Surface *display;
+ GameBoy *core;
+
+ u8 cur_window_line;
+ int mode;
+ bool OAM_BUSY;
+ bool VRAM_BUSY;
u32 colors[4];
u32 frames_rendered;
u32 t_last_frame;
u8 *oldscreen, *newscreen;
- u8 cur_window_line;
- int mode;
-
public:
enum DisplayMode {
NORMAL = 0,
DisplayMode display_mode;
public:
+ int cycles_until_next_update;
static const u16 VRAM_BASE = 0x8000;
static const u16 OAM_BASE = 0xFE00;
GBVideo(GameBoy *core);
~GBVideo();
+ void reset();
+
// VRAM/OAM access
- inline u8 read_VRAM (int addr) const { return VRAM[addr-VRAM_BASE]; }
- inline u8 read_OAM (int addr) const { return OAM.raw[addr-OAM_BASE]; }
- inline u16 read16_VRAM (int addr) const { return VRAM[addr-VRAM_BASE]+(VRAM[addr-VRAM_BASE+1] << 8); }
- inline u16 read16_OAM (int addr) const { return OAM.raw[addr-OAM_BASE]+(OAM.raw[addr-OAM_BASE+1] << 8); }
- inline void write_VRAM(int addr, u8 value) { VRAM[addr-VRAM_BASE] = value; }
- inline void write_OAM (int addr, u8 value) { OAM.raw[addr-OAM_BASE] = value; }
+ inline u8 read_VRAM (int addr) const
+ {
+ if (!VRAM_BUSY) return VRAM[addr-VRAM_BASE];
+ else return 0xFF;
+ }
+
+ inline u8 read_OAM (int addr) const
+ {
+ if (!OAM_BUSY) return OAM.raw[addr-OAM_BASE];
+ else return 0xFF;
+ }
+
+ inline u16 read16_VRAM (int addr) const
+ {
+ if (!VRAM_BUSY) return VRAM[addr-VRAM_BASE]+(VRAM[addr-VRAM_BASE+1] << 8);
+ else return 0xFF;
+ }
+
+ inline u16 read16_OAM (int addr) const
+ {
+ if (!OAM_BUSY) return OAM.raw[addr-OAM_BASE]+(OAM.raw[addr-OAM_BASE+1] << 8);
+ else return 0xFF;
+ }
+
+ inline void write_VRAM(int addr, u8 value)
+ {
+ if (!VRAM_BUSY) VRAM[addr-VRAM_BASE] = value;
+ }
+
+ inline void write_OAM (int addr, u8 value)
+ {
+ if (!OAM_BUSY) OAM.raw[addr-OAM_BASE] = value;
+ }
// drawing control
void draw();
HALT(0),
STOP(0),
cycle_count(0),
- cycles_until_video_update(0),
cycles_until_next_instruction(0),
divider_count(0),
timer_count(0),
IME = 1;
HALT = 0;
cycle_count = 0;
- cycles_until_video_update = 0;
cycles_until_next_instruction = 0;
+ video.reset();
+
regs.PC = 0x0100;
regs.AF = 0x01B0;
regs.BC = 0x0013;
}
// Video
- if (cycles_until_video_update <= 0)
- cycles_until_video_update = video.update();
- cycles_until_video_update -= CYCLE_STEP;
+ if (video.cycles_until_next_update <= 0)
+ video.update();
+ video.cycles_until_next_update -= CYCLE_STEP;
// Divider
divider_count++;
u8 STOP; // Is the CPU & LCD halted waiting for a keypress?
u32 cycle_count;
- u32 cycles_until_video_update;
u32 cycles_until_next_instruction;
u8 divider_count; // resets every 256 cycles, so we don't need a cmp
u32 timer_count;