Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
akatsuki105 committed Apr 12, 2021
1 parent d6fad49 commit 58066c4
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 133 deletions.
7 changes: 7 additions & 0 deletions pkg/gba/apu.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,5 +465,12 @@ func (g *GBA) soundClock(cycles uint32) {

sampPsgL >>= psgRshLut[(cnth>>0)&3]
sampPsgR >>= psgRshLut[(cnth>>0)&3]

sndBuffer[sndCurWrite&BUFF_SAMPLES_MSK] = g.clip(sampPsgL + int32(sampPcmL))
sndCurWrite++
sndBuffer[sndCurWrite&BUFF_SAMPLES_MSK] = g.clip(sampPsgR + int32(sampPcmR))
sndCurWrite++

sndCycles -= SAMP_CYCLES
}
}
36 changes: 36 additions & 0 deletions pkg/gba/dma.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ func NewDMA() [4]*DMA { return [4]*DMA{&DMA{}, &DMA{}, &DMA{}, &DMA{}} }
func (ch *DMA) src() uint32 { return util.LE32(ch.io[:]) }
func (ch *DMA) dst() uint32 { return util.LE32(ch.io[4:]) }
func (ch *DMA) cnt() uint32 { return util.LE32(ch.io[8:]) }
func (ch *DMA) setSrc(v uint32) {
ch.io[0] = byte(v)
ch.io[1] = byte(v >> 8)
ch.io[2] = byte(v >> 16)
ch.io[3] = byte(v >> 24)
}
func (ch *DMA) setCnt(v uint32) {
ch.io[8] = byte(v)
ch.io[9] = byte(v >> 8)
Expand Down Expand Up @@ -131,3 +137,33 @@ func (g *GBA) dmaTransfer(t dmaTiming) {
}
}
}

func (g *GBA) dmaTransferFifo(dma int) {
ch := g.dma[dma] // DMA1 or DMA2
if !ch.enabled() || ch.timing() != dmaSpecial {
return
}

// 32bit × 4 = 4 words
for i := 0; i < 4; i++ {
src, dst := ch.src(), ch.dst()
g.setRAM32(dst, g.getRAM32(src, true), true)

if dma == 1 {
g.fifoACopy()
} else {
g.fifoBCopy()
}

switch (ch.cnt() >> 7) & 0b11 {
case 0:
ch.setSrc(src + 4)
case 1:
ch.setSrc(src - 4)
}
}

if ch.irq() {
g.triggerIRQ(IRQID(irqDMA0 + dma))
}
}
3 changes: 1 addition & 2 deletions pkg/gba/gba.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"mettaur/pkg/gpu"
"mettaur/pkg/joypad"
"mettaur/pkg/ram"
"mettaur/pkg/timer"
"mettaur/pkg/util"
)

Expand Down Expand Up @@ -53,7 +52,7 @@ type GBA struct {
line int
halt bool
pipe Pipe
timers timer.Timers
timers Timers
dma [4]*DMA
joypad joypad.Joypad
DoSav bool
Expand Down
5 changes: 2 additions & 3 deletions pkg/gba/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"mettaur/pkg/gpu"
"mettaur/pkg/ram"
"mettaur/pkg/timer"
"mettaur/pkg/util"
"strings"
)
Expand All @@ -21,7 +20,7 @@ func (g *GBA) _getRAM(addr uint32) uint32 {
return g.dma[2].get(addr - 0x0400_00c8)
case isDMA3IO(addr):
return g.dma[3].get(addr - 0x0400_00d4)
case timer.IsIO(addr):
case IsTimerIO(addr):
return g.timers.GetIO(addr - 0x0400_0100)
case addr == ram.KEYINPUT || addr == ram.KEYINPUT+1:
return util.LE32(g.joypad.Input[addr-ram.KEYINPUT:])
Expand Down Expand Up @@ -113,7 +112,7 @@ func (g *GBA) _setRAM8(addr uint32, b byte) {
if g.dma[3].set(addr-0x0400_00d4, b) {
g.dmaTransfer(dmaImmediate)
}
case timer.IsIO(addr):
case IsTimerIO(addr):
g.timers.SetIO(addr-0x0400_0100, b)
case addr == ram.KEYINPUT || addr == ram.KEYINPUT+1 || addr == ram.KEYCNT || addr == ram.KEYCNT+1:
g.joypad.Input[addr-ram.KEYINPUT] = b
Expand Down
145 changes: 144 additions & 1 deletion pkg/gba/timer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gba

import (
"mettaur/pkg/ram"
"mettaur/pkg/util"
)

var (
Expand Down Expand Up @@ -76,7 +77,7 @@ func (g *GBA) waitBus(addr uint32, size int, s bool) int {
func (g *GBA) timer(cycle int) {
for cycle > 0 {
g.cycle++
irqs := g.timers.Tick()
irqs := g.Tick()
for i, irq := range irqs {
if irq {
g.triggerIRQ(IRQID(i + 3))
Expand All @@ -85,3 +86,145 @@ func (g *GBA) timer(cycle int) {
cycle--
}
}

type Timers [4]Timer

type Timer struct {
Count uint16
Next int // if this value is 0, count up timer.Count
Reload uint16
Control byte
}

func (t *Timer) period() int {
switch t.Control & 0b11 {
case 0:
return 1
case 1:
return 64
case 2:
return 256
default:
return 1024
}
}
func (t *Timer) cascade() bool { return util.Bit(t.Control, 2) }
func (t *Timer) irq() bool { return util.Bit(t.Control, 6) }
func (t *Timer) enable() bool { return util.Bit(t.Control, 7) }
func (t *Timer) increment() bool {
t.Next = t.period()
previous := t.Count
t.Count++
current := t.Count
return current < previous // if overflow occurs
}
func (t *Timer) overflow() bool {
t.Count = t.Reload
return t.irq()
}

// IsIO returns true if addr is for Timer IO register.
func IsTimerIO(addr uint32) bool {
return (addr >= 0x0400_0100) && (addr < 0x0400_0110)
}
func (ts *Timers) GetIO(offset uint32) uint32 {
idx := offset / 4
ofs := offset % 4
switch ofs {
case 0:
return uint32(ts[idx].Count)
case 1:
return uint32(ts[idx].Count >> 8)
case 2:
return uint32(ts[idx].Control)
case 3:
return 0
}
return 0
}

func (ts *Timers) SetIO(offset uint32, b byte) {
idx := offset / 4
ofs := offset % 4
switch ofs {
case 0:
ts[idx].Reload = (ts[idx].Reload & 0xff00) | uint16(b)
case 1:
ts[idx].Reload = (ts[idx].Reload & 0x00ff) | (uint16(b) << 8)
case 2:
previous := util.Bit(ts[idx].Control, 7)
ts[idx].Control = b
// The reload value is copied into the counter when the timer start bit becomes changed from 0 to 1.
if !previous && util.Bit(ts[idx].Control, 7) {
ts[idx].Count = ts[idx].Reload
}
}
}

func (g *GBA) Tick() [4]bool {
overflow, irq := false, [4]bool{}
ts := &g.timers
if ts[0].enable() {
ts[0].Next--
if ts[0].Next == 0 {
overflow = ts[0].increment()
if overflow {
cnth := uint16(g._getRAM(ram.SOUNDCNT_H))
switch {
case (cnth>>10)&1 == 0:
g.fifoALoad()
if fifoALen < 0x10 {
g.dmaTransferFifo(1)
}
case (cnth>>14)&1 == 0:
g.fifoBLoad()
if fifoBLen < 0x10 {
g.dmaTransferFifo(2)
}
}
if ts[0].overflow() {
irq[0] = true
}
}
}
}

for i := 1; i < 4; i++ {
if !ts[i].enable() {
continue
}

countUp := false
if ts[i].cascade() {
countUp = overflow
overflow = false
} else {
ts[i].Next--
countUp = ts[1].Next == 0
}

if countUp {
overflow = ts[i].increment()
if overflow {
cnth := uint16(g._getRAM(ram.SOUNDCNT_H))
switch {
case (cnth>>10)&1 == uint16(i):
g.fifoALoad()
if fifoALen < 0x10 {
g.dmaTransferFifo(1)
}
case (cnth>>14)&1 == uint16(i):
g.fifoBLoad()
if fifoBLen < 0x10 {
g.dmaTransferFifo(2)
}
}
if ts[i].overflow() {
irq[i] = true
}
}
}
}

return irq
}
38 changes: 0 additions & 38 deletions pkg/timer/tick.go

This file was deleted.

89 changes: 0 additions & 89 deletions pkg/timer/timer.go

This file was deleted.

0 comments on commit 58066c4

Please sign in to comment.