Check if VRAM or OAM are busy before accessing them.
authorslack <slack@codemaniacs.com>
Sat, 12 Jul 2008 18:29:13 +0000 (20:29 +0200)
committerslack <slack@codemaniacs.com>
Sat, 12 Jul 2008 18:29:13 +0000 (20:29 +0200)
Also, cycles_to_next_video_update in core was moved to cycles_to_next_update in video.

GBVideo.cc
GBVideo.h
gbcore.cc
gbcore.h

index cbf778d0e7f6873d60f596ee91aa5241325be6f8..ac11a1acb544a53d94c6ae1d5bf5097d508b40b6 100644 (file)
 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);
@@ -43,6 +46,11 @@ GBVideo::~GBVideo()
        delete [] newscreen;
 }
 
+void GBVideo::reset()
+{
+       cycles_until_next_update = 0;
+}
+
 #if 0
 u8   GBVideo::read_VRAM (int addr) const
 {
@@ -118,7 +126,6 @@ u32 GBVideo::update()
        // 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];
@@ -128,6 +135,8 @@ u32 GBVideo::update()
                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");
@@ -140,6 +149,8 @@ u32 GBVideo::update()
                                mode = 2;
                        break;
                case 1:
+                       OAM_BUSY  = false;
+                       VRAM_BUSY = false;
                        if (LY == 144)
                        {
                                logger.trace("Requesting IRQ_VBLANK");
@@ -200,6 +211,8 @@ u32 GBVideo::update()
                                mode = 1;
                        break;
                case 2: {
+                       OAM_BUSY  = true;
+                       VRAM_BUSY = false;
                        if (LY == LYC)
                        {
                                STAT = set_bit(STAT, 2); // set coincidence flag
@@ -224,6 +237,8 @@ u32 GBVideo::update()
                        break;
                }
                case 3:
+                       OAM_BUSY  = false;
+                       VRAM_BUSY = true;
                        draw();
                        // preserve bits 2-6, set mode 3
                        STAT = (STAT&0xFC) | 3;
index c7604a6a615efd2f512a5d232ddc7e261e076643..60471310b47cae88fc1066034ef58d486650e210 100644 (file)
--- a/GBVideo.h
+++ b/GBVideo.h
@@ -23,9 +23,6 @@ class GBVideo
                bool operator< (const Sprite& other) const { return (x < other.x); }
        };
 
-       SDL_Surface *display;
-       GameBoy *core;
-
        u8 VRAM[8192];
        union {
                u8 raw[160];
@@ -36,6 +33,15 @@ class GBVideo
                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;
@@ -43,9 +49,6 @@ class GBVideo
        u32 t_last_frame;
        u8 *oldscreen, *newscreen;
 
-       u8  cur_window_line;
-       int mode;
-
        public:
        enum DisplayMode {
                NORMAL = 0,
@@ -57,19 +60,49 @@ class GBVideo
        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();
index 90e40ba39477b18d0562db05db12d7f8779839f8..62d72c7ac33de22269fac57e2970d5fdd34e2f4c 100644 (file)
--- a/gbcore.cc
+++ b/gbcore.cc
@@ -19,7 +19,6 @@ GameBoy::GameBoy(std::string rom_name, GameBoyType type):
        HALT(0),
        STOP(0),
        cycle_count(0),
-       cycles_until_video_update(0),
        cycles_until_next_instruction(0),
        divider_count(0),
        timer_count(0),
@@ -41,9 +40,10 @@ void GameBoy::reset()
        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;
@@ -1319,9 +1319,9 @@ GameBoy::run_status GameBoy::run_cycle()
        }
 
        // 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++;
index d8bf8bb55ce4e2686bfb134664d98a1fe137c719..699e68d37c695039402535607e063ac22f83ebf4 100644 (file)
--- a/gbcore.h
+++ b/gbcore.h
@@ -71,7 +71,6 @@ class GameBoy
        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;