Skip to content

Commit

Permalink
add support to MBC3 cartridges
Browse files Browse the repository at this point in the history
  • Loading branch information
gonccalo committed Apr 21, 2017
1 parent bc07d85 commit 2adb373
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 6 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Gameboy emulator in go
* Joypad
* Video
* Timers
* Support MBC1 & MBC2 roms
* Support MBC1, MBC2 & MBC3 roms
* Load saved games
* Cpu test roms passed
### Tested Games
Expand All @@ -19,14 +19,16 @@ Gameboy emulator in go
* The Legend of Zelda - Link's Awakening
* The Final Fantasy Legend
* Seiken Densetsu
* Pokemon - Red Version
* Pokemon - Gold Version

![out3](https://cloud.githubusercontent.com/assets/5223817/25020097/09d047b4-2085-11e7-87af-c88fafc6a51a.gif)
![out2](https://cloud.githubusercontent.com/assets/5223817/24856667/7309c2f0-1ddd-11e7-82f3-ff527d51b0d8.gif)
![out](https://cloud.githubusercontent.com/assets/5223817/23906938/74379006-08c7-11e7-9f99-e7e6121e1a64.gif)

## TODO:
* STOP and HALT instructions
* Support MBC3 & MBC5
* Support MBC5
* Sound

## Compile and run
Expand Down
4 changes: 4 additions & 0 deletions gameboygo/MBC1_cart.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"os"
"io/ioutil"
"fmt"
)
Expand Down Expand Up @@ -89,6 +90,9 @@ func (r *MBC1)ramWrite(addr uint16, b uint8) {
func (r *MBC1)loadRam() {
newCartRam, err := ioutil.ReadFile(r.rom_file + "_save")
if err != nil {
if os.IsNotExist(err){
return
}
fmt.Printf("ERROR reading cart Ram")
return
}
Expand Down
4 changes: 4 additions & 0 deletions gameboygo/MBC2_cart.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"os"
"io/ioutil"
"fmt"
)
Expand Down Expand Up @@ -68,6 +69,9 @@ func (r *MBC2)ramWrite(addr uint16, b uint8) {
func (r *MBC2)loadRam() {
newCartRam, err := ioutil.ReadFile(r.rom_file + "_save")
if err != nil {
if os.IsNotExist(err){
return
}
fmt.Printf("ERROR reading cart Ram")
return
}
Expand Down
110 changes: 110 additions & 0 deletions gameboygo/MBC3_cart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package main

import (
"os"
"io/ioutil"
"fmt"
)

type MBC3 struct {
rom_file string
head rom_header
RomData []uint8
cartRam []uint8
RTCregs []uint8
romBank uint8
ramBank uint8
mapRTC bool
ramRTCEnabled bool
}
func (r *MBC3)init(data []uint8, filename string) bool{
r.head.init(data)
r.rom_file = filename
r.romBank = 1
r.RTCregs = make([]uint8, 5)
r.cartRam = make([]uint8, 0x1FFF*4)
r.loadRam()
r.RomData = make([]uint8, len(data))
if num := copy(r.RomData, data); num != len(data){
return false
}
return true
}
func (r *MBC3)romRead(addr uint16) uint8 {
if addr >= 0x4000 {
return r.RomData[(0x4000 * uint32(r.romBank)) + (uint32(addr)-0x4000)]
}
return r.RomData[addr]
}
func (r *MBC3)romWrite(addr uint16, b uint8) {
if addr >= 0x2000 && addr <= 0x3FFF{
switch b & 0x7F{
case 0x00:
r.romBank = 0x01
default:
r.romBank = (b & 0x7F)
}
} else if addr >= 0x4000 && addr <= 0x5FFF{
if b >= 0x08 && b <= 0x0C{
r.mapRTC = true
r.ramBank = b
return
}
if b <= 0x03 {
r.mapRTC = false
r.ramBank = b
}
} else if addr >= 0x0000 && addr <= 0x1FFF{
//enable or disable ram
if b & 0x0F == 0x0A{
r.ramRTCEnabled = true
} else{
r.ramRTCEnabled = false
}
} else if addr >= 0x6000 && addr <= 0x7FFF{
if b == 0x01 {
//latch rtc
}
}
}
func (r *MBC3)ramRead(addr uint16) uint8 {
if !r.ramRTCEnabled {
return 0xFF
}
if r.mapRTC {
return r.RTCregs[r.ramBank - 0x08]
}
return r.cartRam[(0x1FFF * uint32(r.ramBank)) + (uint32(addr)-0xA000)]
}
func (r *MBC3)ramWrite(addr uint16, b uint8) {
if !r.ramRTCEnabled {
return
}
if r.mapRTC {
r.RTCregs[r.ramBank - 0x08] = b
return
}
r.cartRam[(0x1FFF * uint32(r.ramBank)) + (uint32(addr)-0xA000)] = b
}

func (r *MBC3)loadRam() {
newCartRam, err := ioutil.ReadFile(r.rom_file + "_save")
if err != nil {
if os.IsNotExist(err){
return
}
fmt.Printf("ERROR reading cart Ram")
return
}
if len(newCartRam) != len(r.cartRam) {
fmt.Printf("ERROR reading cart Ram")
return
}
r.cartRam = newCartRam
}

func (r *MBC3)saveCartRam() {
if err := ioutil.WriteFile(r.rom_file + "_save", r.cartRam, 0666); err != nil{
panic(err)
}
}
6 changes: 2 additions & 4 deletions gameboygo/rom.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ type rom_header struct{
ram_size uint8
header_checksum uint8
version uint8
rom_file string
}

type Cart interface{
Expand Down Expand Up @@ -71,13 +70,12 @@ func Load_rom(filename string) bool{
}
switch RomData[0x147]{
case ROM_MBC1, ROM_MBC1_RAM, ROM_MBC1_RAM_BATT:
fmt.Printf("MBC1\n")
cart = new(MBC1)
case ROM_MBC2, ROM_MBC2_BATT:
fmt.Printf("MBC2\n")
cart = new(MBC2)
case ROM_MBC3_TIMER_BATT, ROM_MBC3_TIMER_RAM_BATT, ROM_MBC3, ROM_MBC3_RAM, ROM_MBC3_RAM_BATT:
cart = new(MBC3)
default:
fmt.Printf("Gen\n")
cart = new(genericCart)
}
if !cart.init(RomData, filename){
Expand Down

0 comments on commit 2adb373

Please sign in to comment.