MBC1 Implemented
authorslack <slack@codemaniacs.com>
Sat, 19 Jul 2008 22:48:48 +0000 (00:48 +0200)
committerslack <slack@codemaniacs.com>
Sat, 19 Jul 2008 22:48:48 +0000 (00:48 +0200)
MBC.cc
MBC.h
MBC1.cc [new file with mode: 0644]
MBC1.h [new file with mode: 0644]
Makefile
NoMBC.cc [new file with mode: 0644]
NoMBC.h [new file with mode: 0644]

diff --git a/MBC.cc b/MBC.cc
index 5437dbdf3f4a9ca574d1880299935012c382c867..6dc90ed9dcdf8704f4290ca70f53773583a6bfb2 100644 (file)
--- a/MBC.cc
+++ b/MBC.cc
@@ -1,18 +1,15 @@
 #include "MBC.h"
-#include "Logger.h"
-#include <cstring>
-#include <sstream>
-#include <iostream>
-#include <iomanip>
+#include "NoMBC.h"
+#include "MBC1.h"
 
-using namespace cartridge_types;
+#include "Logger.h"
 
 MBC *create_MBC(GBRom *rom)
 {
        switch (rom->header.cartridge_type)
        {
-               case ROM_ONLY:          return new NoMBC(rom);
-               //case MBC1:            return new MBC1(rom);
+               case cartridge_types::ROM_ONLY:         return new NoMBC(rom);
+               case cartridge_types::MBC1:                     return new MBC1(rom);
                default:
                        logger.critical("Unsupported cartridge type ", 
                                        int(rom->header.cartridge_type));
@@ -20,40 +17,3 @@ MBC *create_MBC(GBRom *rom)
        }
 }
 
-u8 NoMBC::read(int addr) const
-{
-       if (addr <= 0x7FFF)
-               return ROM[addr];
-       else //if ((addr&0xE000) == 0xA000)   //(addr >= 0xA000 && addr <= 0xBFFF)
-               return RAM[addr-0xA000];
-       //else
-       //      logger.error("NoMBC: Incorrect read");
-       return 0;
-}
-
-u16 NoMBC::read16(int addr) const
-{
-       if (addr <= 0x7FFF)
-               return ROM[addr]+(ROM[addr+1] << 8);
-       else //if ((addr&0xE000) == 0xA000)   //(addr >= 0xA000 && addr <= 0xBFFF)
-               return RAM[addr-0xA000] + (RAM[addr-0xA000+1] << 8);
-       //else
-       //      logger.error("NoMBC: Incorrect read");
-       return 0;
-}
-
-void NoMBC::write(int addr, u8 value)
-{
-       if ((addr&0xE000) == 0xA000) //(addr >= 0xA000 && addr <= 0xBFFF)
-       {
-               RAM[addr-0xA000]=value;
-               return;
-       }
-       else 
-       {
-               std::ostringstream errmsg;
-               errmsg <<"NoMBC: trying to write in ROM, addr=0x"<<std::hex<<addr;
-               logger.debug(errmsg.str());
-       }
-}
-
diff --git a/MBC.h b/MBC.h
index 35bb400f3d286a35194ff7f604bde2663f5f1629..fd7ee442e6ffd0b6f05429b97df69ecdc2da953d 100644 (file)
--- a/MBC.h
+++ b/MBC.h
@@ -7,25 +7,12 @@
 class MBC
 {
        public:
-       virtual u8   read(int addr) const=0;
-       virtual u16  read16(int addr) const=0;
-       virtual void write(int addr, u8 value)=0;
+       virtual u8   read  (u16 addr) const=0;
+       virtual u16  read16(u16 addr) const=0;
+       virtual void write (u16 addr, u8 value)=0;
        virtual ~MBC() {};
 };
 
-class NoMBC: public MBC
-{
-       u8 ROM[32768];
-       u8 RAM[8192];
-       
-       public:
-       NoMBC(GBRom *rom) { memcpy(ROM, rom->data, 32768); }
-       u8   read (int addr) const;
-       void write(int addr, u8 value);
-
-       u16  read16(int addr) const;
-};
-
 
 MBC *create_MBC(GBRom *rom);
 
diff --git a/MBC1.cc b/MBC1.cc
new file mode 100644 (file)
index 0000000..1b35e02
--- /dev/null
+++ b/MBC1.cc
@@ -0,0 +1,98 @@
+#include "MBC1.h"
+#include "Logger.h"
+
+#include <iomanip>
+#include <cassert>
+
+u8 MBC1::read(u16 addr) const
+{
+       if (addr <= 0x3FFF)       // ROM Bank 0
+               return ROM[addr];
+       else if (addr <= 0x7FFF)  // ROM (switchable)
+       {
+               u8 rom_bank = rom_bank_low;
+               if (mode == ROM_BANKING_MODE) rom_bank |= (ram_bank << 5);
+
+               u32 base = 16384*rom_bank;
+               return ROM[base + (addr-0x4000)];
+       }
+       else // if ((addr&0xE000) == 0xA000)   //(addr >= 0xA000 && addr <= 0xBFFF)
+       {
+               if (ram_enabled)
+               {
+                       u32 base = (mode == RAM_BANKING_MODE ? 8192*ram_bank : 0);
+                       return RAM[base + (addr-0xA000)];
+               }
+               else return 0xFF;
+       }
+       //else
+       //      logger.error("MBC1: Incorrect read");
+       return 0;
+}
+
+u16 MBC1::read16(u16 addr) const
+{
+       assert (addr != 0x3FFF);
+       assert (addr != 0x7FFF);
+       assert (addr != 0xBFFF);
+
+       if (addr <= 0x3FFF)       // ROM Bank 0
+               return ROM[addr] | (ROM[addr+1] << 8);
+       else if (addr <= 0x7FFF)  // ROM (switchable)
+       {
+               u8 rom_bank = rom_bank_low;
+               if (mode == ROM_BANKING_MODE) rom_bank |= (ram_bank << 5);
+
+               u32 offset = 16384*rom_bank + (addr-0x4000);
+               return ROM[offset] | (ROM[offset+1] << 8);
+       }
+       else // if ((addr&0xE000) == 0xA000)   //(addr >= 0xA000 && addr <= 0xBFFF)
+       {
+               if (ram_enabled)
+               {
+                       u32 base = (mode == RAM_BANKING_MODE ? 8192*ram_bank : 0);
+                       u32 offset = base + (addr-0xA000);
+                       return RAM[offset] | (RAM[offset+1] << 8);
+               }
+               else return 0xFFFF;
+       }
+       //else
+       //      logger.error("MBC1: Incorrect read");
+       return 0;
+}
+
+void MBC1::write(u16 addr, u8 value)
+{
+       if (addr <= 0x1FFF)
+       {
+               if ((value & 0x0F) == 0x0A)
+                       ram_enabled = true;
+               else
+                       ram_enabled = false;
+       }
+       else if (addr <= 0x3FFF)
+       {
+               rom_bank_low = value & 0x1F;
+               if (rom_bank_low == 0) rom_bank_low = 1;
+       }
+       else if (addr <= 0x5FFF)
+       {
+               ram_bank = value & 0x03;
+       }
+       else if (addr <= 0x7FFF)
+       {
+               mode = BankingMode(value & 1);
+       }
+       else if ((addr&0xE000) == 0xA000) //(addr >= 0xA000 && addr <= 0xBFFF)
+       {
+               u32 base = (mode == RAM_BANKING_MODE ? 8192*ram_bank : 0);
+               RAM[base + (addr-0xA000)]=value;
+               return;
+       }
+       else
+       {
+               logger.debug("MBC1: trying to write in ROM, addr=0x",std::hex,addr);
+       }
+}
+
+
diff --git a/MBC1.h b/MBC1.h
new file mode 100644 (file)
index 0000000..ac23e2c
--- /dev/null
+++ b/MBC1.h
@@ -0,0 +1,35 @@
+#ifndef MBC1_H
+#define MBC1_H
+
+
+#include "MBC.h"
+
+
+class MBC1: public MBC
+{
+       u8 ROM[128*16384];
+       u8 RAM[  4* 8192];
+
+       u8 rom_bank_low;
+       u8 ram_bank;
+       bool ram_enabled;
+
+       enum BankingMode
+       {
+               ROM_BANKING_MODE=0,
+               RAM_BANKING_MODE=1
+       } mode;
+
+       public:
+       MBC1(GBRom *rom): rom_bank_low(1), ram_bank(0), ram_enabled(false), mode(ROM_BANKING_MODE)
+       {
+               memcpy(ROM, rom->data, 32768 << rom->header.rom_size);
+       }
+
+       u8   read  (u16 addr) const;
+       u16  read16(u16 addr) const;
+       void write (u16 addr, u8 value);
+};
+
+#endif
+
index 75f4b6aeda0f6325e171d5e914d2d624f523afe2..b9f3565a114b4b7e1a037dc953508d3743b17768 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,5 @@
-CXXFLAGS=-pg -O3 -g -Wall -Weffc++ -Wstrict-null-sentinel -Wold-style-cast \
+#CXXFLAGS=-pg -O3 -g -Wall -Weffc++ -Wstrict-null-sentinel -Wold-style-cast
+CXXFLAGS=-pg -O3 -g -Wall -Weffc++ -Wold-style-cast \
         -Woverloaded-virtual $(shell sdl-config --cflags)
 LDFLAGS=-pg -g $(shell sdl-config --libs)
 
@@ -15,7 +16,13 @@ GBVideo.o: GBVideo.cc GBVideo.h Logger.h util.h gbcore.h
 GBMemory.o: GBMemory.cc GBMemory.h Logger.h MBC.h gbcore.h
        g++ $(CXXFLAGS) -c -o $@ $<
 
-MBC.o: MBC.cc MBC.h Logger.h
+MBC.o: MBC.cc MBC.h Logger.h NoMBC.h MBC1.h
+       g++ $(CXXFLAGS) -c -o $@ $<
+
+NoMBC.o: NoMBC.cc NoMBC.h Logger.h
+       g++ $(CXXFLAGS) -c -o $@ $<
+
+MBC1.o: MBC1.cc MBC1.h Logger.h
        g++ $(CXXFLAGS) -c -o $@ $<
 
 gbcore.o: gbcore.cc gbcore.h opcodes.h disasm.h \
@@ -23,11 +30,11 @@ gbcore.o: gbcore.cc gbcore.h opcodes.h disasm.h \
        g++ $(CXXFLAGS) -c -o $@ $<
                
 tests/test_gbrom: GBRom.cc GBRom.h 
-       g++ $(CXXFLAGS) $(LDFLAGS) -DTEST_GBROM -o $@ GBRom.cc 
+       g++ $(CXXFLAGS)  -DTEST_GBROM -o $@ GBRom.cc $(LDFLAGS)
 
 tests/test_core: tests/test_core.cc gbcore.o MBC.o GBMemory.o GBRom.o \
-       GBVideo.o util.o
-       g++ $(CXXFLAGS) $(LDFLAGS) -o $@ $^
+       GBVideo.o util.o NoMBC.o MBC1.o
+       g++ $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
 
 clean:
        rm -f *.o tests/test_gbrom tests/test_core
diff --git a/NoMBC.cc b/NoMBC.cc
new file mode 100644 (file)
index 0000000..1f13c40
--- /dev/null
+++ b/NoMBC.cc
@@ -0,0 +1,44 @@
+#include "NoMBC.h"
+#include "Logger.h"
+
+#include <iomanip>
+
+u8 NoMBC::read(u16 addr) const
+{
+       if (addr <= 0x7FFF)
+               return ROM[addr];
+       else //if ((addr&0xE000) == 0xA000)   //(addr >= 0xA000 && addr <= 0xBFFF)
+               return RAM[addr-0xA000];
+       //else
+       //      logger.error("NoMBC: Incorrect read");
+       return 0;
+}
+
+u16 NoMBC::read16(u16 addr) const
+{
+       if (addr <= 0x7FFF)
+               return ROM[addr] | (ROM[addr+1] << 8);
+       else //if ((addr&0xE000) == 0xA000)   //(addr >= 0xA000 && addr <= 0xBFFF)
+       {
+               u16 offset = addr - 0xA000;
+               return RAM[offset] | (RAM[offset+1] << 8);
+       }
+       //else
+       //      logger.error("NoMBC: Incorrect read");
+       return 0;
+}
+
+void NoMBC::write(u16 addr, u8 value)
+{
+       if ((addr&0xE000) == 0xA000) //(addr >= 0xA000 && addr <= 0xBFFF)
+       {
+               RAM[addr-0xA000]=value;
+               return;
+       }
+       else
+       {
+               logger.debug("NoMBC: trying to write in ROM, addr=0x", std::hex, addr);
+       }
+}
+
+
diff --git a/NoMBC.h b/NoMBC.h
new file mode 100644 (file)
index 0000000..81b3fd3
--- /dev/null
+++ b/NoMBC.h
@@ -0,0 +1,19 @@
+#ifndef NOMBC_H
+#define NOMBC_H
+
+#include "MBC.h"
+
+class NoMBC: public MBC
+{
+       u8 ROM[32768];
+       u8 RAM[8192];
+
+       public:
+       NoMBC(GBRom *rom) { memcpy(ROM, rom->data, 32768); }
+       u8   read  (u16 addr) const;
+       u16  read16(u16 addr) const;
+       void write (u16 addr, u8 value);
+
+};
+
+#endif