More video code
authorslack <slack@ommadawn.(none)>
Sun, 29 Jun 2008 01:30:27 +0000 (03:30 +0200)
committerslack <slack@ommadawn.(none)>
Sun, 29 Jun 2008 01:31:53 +0000 (03:31 +0200)
GBMemory.h
GBVideo.cc
GBVideo.h
Makefile
util.h [new file with mode: 0644]

index 55563f194d045028d850fff7dbee67988d295d48..56bd5704f6ec81c34df7eb144fb63f81efaf4823 100644 (file)
@@ -24,6 +24,7 @@ class GBIO
        static const u16 OBP0 = 0xFF48; // Object Pallete 0 data(R/W)
        static const u16 OBP1 = 0xFF49; // Object Pallete 1 data(R/W)
        static const u16 DMA  = 0xFF46; // DMA Transfer & Start addr (W)
+       static const u16 IF   = 0xFF0F; // Interrupt flag       (R/W)
 
        u8   read(int addr) const;
        void write(int addr, u8 value);
index 2789af8b95a0627a4e78eac751c7d5b09f8a8017..86521decb91fe3198fe8a10f2aa6586acd6d0341 100644 (file)
@@ -1,5 +1,7 @@
 #include "GBVideo.h"
-       
+#include "gbcore.h"
+#include "util.h"
+
 GBVideo::GBVideo(GameBoy *core):
        display(0),
        core(core)
@@ -20,22 +22,38 @@ GBVideo::~GBVideo()
 
 u8   GBVideo::read_VRAM (int addr) const
 {
-       return VRAM[addr-VRAM_BASE];
+       int STAT = memory.read(GBIO::STAT);
+       if ((STAT & 3) == 3)
+               return 0xFF; // VRAM access disabled
+       else
+               return VRAM[addr-VRAM_BASE];
 }
 
 u8   GBVideo::read_OAM  (int addr) const
 {
-       return OAM[addr-OAM_BASE];
+       int STAT = memory.read(GBIO::STAT);
+       if ((STAT & 3) >= 2)
+               return 0xFF; // OAM access disabled
+       else
+               return OAM[addr-OAM_BASE];
 }
 
 void GBVideo::write_VRAM(int addr, u8 value)
 {
-       VRAM[addr-VRAM_BASE] = value;
+       int STAT = memory.read(GBIO::STAT);
+       if ((STAT & 3) == 3)
+               return; // VRAM access disabled
+       else
+               VRAM[addr-VRAM_BASE] = value;
 }
 
 void GBVideo::write_OAM (int addr, u8 value)
 {
-       OAM[addr-OAM_BASE] = value;
+       int STAT = memory.read(GBIO::STAT);
+       if ((STAT & 3) >= 2)
+               return; // OAM access disabled
+       else
+               OAM[addr-OAM_BASE] = value;
 }
 
 void GBVideo::update()
@@ -46,12 +64,68 @@ void GBVideo::update()
        //70224 clks.)
        //
        // sequence:
-       // 2: 80 clocks           \
-       // 3: 172 clocks          |-> for each one of the 144 lines
-       // 0: 204 clocks (HBlank) /
+       // 2: 80 clocks  (reading OAM)       |
+       // 3: 172 clocks (reading OAM+VRAM)  |-> for each one of the 144 lines
+       // 0: 204 clocks (HBlank)            |
        // 1: 4560 clocks -> VBlank
-       
+       //
+       // mode 2 starts at 0, 456, 912...
+       // mode 3 starts at 80, 536, 992...
+       // mode 0 starts at 252, 708, 1164...
+       // vblank starts at 65664
+
+       int STAT = core->memory.read(GBIO::STAT);
+       int LYC  = core->memory.read(GBIO::LYC);
+       int LY   = core->memory.read(GBIO::LY);
+
        int t = core->cycle_count % 70224;
        
+       if (t >= 65665)
+       {
+               if (t == 65665 && check_bit(STAT,4))
+                       core->irq(GameBoy::IRQ_VBLANK);
+
+               // preserve bits 3-6, set mode to 1 (VBlank) and coincidence to 0
+               STAT = (STAT&0xF8) | 1;
+       }
+       else
+       {
+               LY = t/456;
+               int hline_t = t%456;
+               if (LY == LYC)
+               {
+                       STAT = set_bit(STAT, 2); // set coincidence flag
+                       if (hline_t == 0 && check_bit(STAT, 6))
+                               core->irq(GameBoy::IRQ_LCD_STAT);
+               }
+
+               if (hline_t < 80)
+               {
+                       if (hline_t == 0 && check_bit(STAT, 5))
+                               core->irq(GameBoy::IRQ_LCD_STAT);
+
+                       // preserve bits 2-6, set mode 2
+                       STAT = (STAT&0xFC) | 2;
+               }
+               else if (hline_t < 252)
+               {
+                       // preserve bits 2-6, set mode 3
+                       STAT = (STAT&0xFC) | 3;
+               }
+               else
+               {
+                       // HBlank (preserve bits 2-6, mode = 0)
+                       STAT = (STAT&0xFC);
+                       if (hline_t == 252 && check_bit(STAT, 3))
+                               core->irq(GameBoy::IRQ_LCD_STAT);
+               }
+               
+       }
+       
+       core->memory.write(GBIO::LY, LY);
+       core->memory.write(GBIO::STAT, STAT);
+
+       // Draw the background
+       
 
 }
index 8e35bedc4d0c85a91d94c025abc3c65f305eaa5a..63c8d7599818af8f7867ab00c0491dc01f8c4966 100644 (file)
--- a/GBVideo.h
+++ b/GBVideo.h
@@ -1,6 +1,11 @@
+#ifndef GBVIDEO_H
+#define GBVIDEO_H
+
 #include "GBMemory.h"
 #include "SDL.h"
 
+class GameBoy;
+
 class GBVideo
 {
        SDL_Surface *display;
@@ -35,4 +40,5 @@ class GBVideo
 
 };
 
+#endif
 
index dabd46a56aef4379830ed23e956da5d098c80198..927c58843cf20ebc21fec7aa1e37f540e6e14047 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ all: tests
 
 tests: tests/test_gbrom tests/test_core
 
-GBVideo.o: GBVideo.cc GBVideo.h Logger.h
+GBVideo.o: GBVideo.cc GBVideo.h Logger.h util.h
        g++ $(CXXFLAGS) -c -o $@ $<
 
 GBMemory.o: GBMemory.cc GBMemory.h Logger.h
diff --git a/util.h b/util.h
new file mode 100644 (file)
index 0000000..65a551f
--- /dev/null
+++ b/util.h
@@ -0,0 +1,31 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#include "sized_types.h"
+
+uint32 set_bit(uint32 pos, uint32 val)
+{
+       uint32 mask = 1<<pos;
+       return val | mask;
+}
+
+uint32 reset_bit(uint32 pos, uint32 val)
+{
+       uint32 mask = ~(1<<pos);
+       return val & mask;
+}
+
+uint32 flip_bit(uint32 pos, uint32 val)
+{
+       uint32 mask = 1<<pos;
+       return val ^ mask;
+}
+
+bool check_bit(uint32 pos, uint32 val)
+{
+       uint32 mask = 1<<pos;
+       return ((val&mask) != 0);
+}
+
+#endif
+