Skip to content

Commit

Permalink
v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
akatsuki105 committed Apr 24, 2021
1 parent 1d7a53b commit 587472d
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 36 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,27 @@ $ ./build/darwin-amd64/mettaur XXXX.gba

## ToDo

- [ ] Sound DMA
- [ ] Clear sound
- [ ] Window
- [ ] Mosaic
- [ ] Blend
- [ ] GUI
- [ ] Serial communication
- [ ] BG mode5
- [ ] GameBoy Compatibility
- [ ] Debug feature
- [ ] Fix some bugs

## Game Compatibility List

| Game Title | Compatibility |
| -------------------- | ------------- |
| バトルネットワーク ロックマンエグゼ3 BLACK ||
| ロックマンエグゼ4 トーナメント ブルームーン ||
| ロックマンエグゼ6 電脳獣グレイガ・電脳獣ファルザー ||
| ポケットモンスター ファイアレッド ||
| ドラゴンクエストモンスターズ キャラバンハート | 🔺 |


## References

- [GBATEK](https://problemkaputt.de/gbatek.htm)
Expand Down
4 changes: 2 additions & 2 deletions pkg/gba/apu.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const (
BUFF_SAMPLES_MSK = ((BUFF_SAMPLES) - 1)
SAMPLE_TIME float64 = 1.0 / SND_FREQUENCY
SAMPLE_RATE = SND_FREQUENCY
STREAM_LEN = 2940 // 2 * 2 * sampleRate * (1/60)
STREAM_LEN = 2184 // 2 * 2 * sampleRate * (1/60)
)

const (
Expand Down Expand Up @@ -498,7 +498,7 @@ func (g *GBA) soundClock(cycles uint32) {

cnth := uint16(g._getRAM(ram.SOUNDCNT_H)) // snd_pcm_vol
volADiv, volBDiv := int16((cnth>>2)&0b1), int16((cnth>>3)&0b1)
sampCh4, sampCh5 := fifoASamp>>volADiv, fifoBSamp>>volBDiv
sampCh4, sampCh5 := (int16(fifoASamp)<<1)>>volADiv, (int16(fifoBSamp)<<1)>>volBDiv
// sampCh4, sampCh5 = 0, 0

// Left
Expand Down
58 changes: 31 additions & 27 deletions pkg/gba/dma.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ const (
)

type DMA struct {
io [12]byte
src, dst uint32
io [12]byte
src, dst uint32
count, defaultCount int
}

func NewDMA() [4]*DMA { return [4]*DMA{&DMA{}, &DMA{}, &DMA{}, &DMA{}} }
func NewDMA() [4]*DMA {
return [4]*DMA{&DMA{defaultCount: 0x4000}, &DMA{defaultCount: 0x4000}, &DMA{defaultCount: 0x4000}, &DMA{defaultCount: 0x10000}}
}
func (ch *DMA) cnt() uint32 { return util.LE32(ch.io[8:]) }
func (ch *DMA) setCnt(v uint32) {
ch.io[8], ch.io[9], ch.io[10], ch.io[11] = byte(v), byte(v>>8), byte(v>>16), byte(v>>24)
Expand All @@ -33,16 +36,21 @@ func (ch *DMA) set(ofs uint32, b byte) bool {
old := byte(ch.cnt() >> 24)
ch.io[ofs] = b
if ofs == 11 {
ch.src, ch.dst = util.LE32(ch.io[0:]), util.LE32(ch.io[4:])
switch ch.size() {
case 32:
ch.src &= ^uint32(3)
ch.dst &= ^uint32(3)
case 16:
ch.src &= ^uint32(1)
ch.dst &= ^uint32(1)
turnon := !util.Bit(old, 7) && util.Bit(b, 7)
if turnon {
ch.src, ch.dst = util.LE32(ch.io[0:]), util.LE32(ch.io[4:])
ch.count = ch.wordCount()
switch ch.size() {
case 32:
ch.src &= ^uint32(3)
ch.dst &= ^uint32(3)
case 16:
ch.src &= ^uint32(1)
ch.dst &= ^uint32(1)
}
}
return !util.Bit(old, 7) && util.Bit(b, 7) && (ch.timing() == 0)

return turnon && ch.timing() == 0
}
return false
}
Expand Down Expand Up @@ -81,13 +89,10 @@ func (ch *DMA) timing() dmaTiming { return dmaTiming((ch.cnt() >> (16 + 12)) & 0
func (ch *DMA) irq() bool { return util.Bit(ch.cnt(), 16+14) }
func (ch *DMA) enabled() bool { return util.Bit(ch.cnt(), 16+15) }
func (ch *DMA) disable() { ch.setCnt(ch.cnt() & 0x7fff_ffff) }
func (ch *DMA) wordCount(i int) int {
func (ch *DMA) wordCount() int {
wordCount := ch.cnt() & 0xffff
if wordCount == 0 {
wordCount = 0x4000
if i == 3 {
wordCount = 0x10000
}
return ch.defaultCount
}
return int(wordCount)
}
Expand All @@ -98,11 +103,9 @@ func (g *GBA) dmaTransfer(t dmaTiming) {
continue
}

g.timer(2)

wc, size := ch.wordCount(i), ch.size()
size := ch.size()
srcInc, dstInc := ch.srcCnt(), ch.dstCnt()
for wc > 0 {
for ch.count > 0 {
switch size {
case 16:
g.setRAM16(ch.dst, g.getRAM16(ch.src, true), true)
Expand All @@ -111,20 +114,21 @@ func (g *GBA) dmaTransfer(t dmaTiming) {
}

ch.dst, ch.src = uint32(int64(ch.dst)+dstInc), uint32(int64(ch.src)+srcInc)
wc--
ch.count--
}

if ch.irq() {
g.triggerIRQ(IRQID(irqDMA0 + i))
}

if !ch.repeat() {
if ch.repeat() {
ch.count = ch.wordCount()
if ch.dstReload() {
ch.dst = util.LE32(ch.io[4:])
}
} else {
ch.disable()
}

if ch.dstReload() {
ch.dst = util.LE32(ch.io[4:])
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/gba/gba.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (g *GBA) exec(cycles int) {
for g.cycle < cycles {
g.step()
if g.halt {
g.cycle = cycles
g.timer(cycles - g.cycle)
}
}
g.cycle -= cycles
Expand Down
8 changes: 4 additions & 4 deletions pkg/gba/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ func (g *GBA) _getRAM(addr uint32) uint32 {
idx := (bank ^ 0x10) | (addr & 0xf)
return util.LE32(waveRAM[idx:])
case isDMA0IO(addr):
return g.dma[0].get(addr - 0x0400_00b0)
return g.dma[0].get(addr - ram.DMA0SAD)
case isDMA1IO(addr):
return g.dma[1].get(addr - 0x0400_00bc)
return g.dma[1].get(addr - ram.DMA1SAD)
case isDMA2IO(addr):
return g.dma[2].get(addr - 0x0400_00c8)
return g.dma[2].get(addr - ram.DMA2SAD)
case isDMA3IO(addr):
return g.dma[3].get(addr - 0x0400_00d4)
return g.dma[3].get(addr - ram.DMA3SAD)
case IsTimerIO(addr):
return g.timers.GetIO(addr - 0x0400_0100)
case addr == ram.KEYINPUT || addr == ram.KEYINPUT+1:
Expand Down

0 comments on commit 587472d

Please sign in to comment.