mirror of
https://github.com/JetSetIlly/Gopher2600.git
synced 2024-06-02 20:18:20 -04:00
ELF byte streaming now works with a fixed sized array
This commit is contained in:
parent
7de45d3d25
commit
a921130414
|
@ -219,19 +219,20 @@ func (cart *Elf) Reset() {
|
|||
func (cart *Elf) reset() {
|
||||
// stream bytes rather than injecting them into the VCS as they arrive. we
|
||||
// can't currently accomodate this if the ROM requires bus stuffing of data
|
||||
cart.mem.streaming = !cart.mem.busStuff
|
||||
cart.mem.stream.active = !cart.mem.busStuff
|
||||
|
||||
// initialise ROM for the VCS
|
||||
if cart.mem.streaming {
|
||||
cart.mem.stream = append(cart.mem.stream, streamEntry{
|
||||
if cart.mem.stream.active {
|
||||
cart.mem.stream.push(streamEntry{
|
||||
addr: 0x1ffc,
|
||||
data: 0x00,
|
||||
})
|
||||
cart.mem.stream = append(cart.mem.stream, streamEntry{
|
||||
cart.mem.stream.push(streamEntry{
|
||||
addr: 0x1ffd,
|
||||
data: 0x10,
|
||||
})
|
||||
cart.mem.drain = true
|
||||
cart.mem.strongarm.nextRomAddress = 0x1000
|
||||
cart.mem.stream.startDrain()
|
||||
} else {
|
||||
cart.mem.setStrongArmFunction(vcsEmulationInit)
|
||||
}
|
||||
|
@ -247,17 +248,13 @@ func (cart *Elf) reset() {
|
|||
|
||||
// Access implements the mapper.CartMapper interface.
|
||||
func (cart *Elf) Access(addr uint16, _ bool) (uint8, uint8, error) {
|
||||
if cart.mem.streaming {
|
||||
if addr == cart.mem.stream[0].addr&memorymap.CartridgeBits {
|
||||
if !cart.mem.drain {
|
||||
cart.runARM()
|
||||
}
|
||||
cart.mem.gpio.data[DATA_ODR] = cart.mem.stream[0].data
|
||||
cart.mem.stream = cart.mem.stream[1:]
|
||||
|
||||
if len(cart.mem.stream) < 10 {
|
||||
cart.mem.drain = false
|
||||
}
|
||||
if cart.mem.stream.active {
|
||||
if !cart.mem.stream.drain {
|
||||
cart.runARM()
|
||||
}
|
||||
if addr == cart.mem.stream.peekAddr()&memorymap.CartridgeBits {
|
||||
e := cart.mem.stream.pull()
|
||||
cart.mem.gpio.data[DATA_ODR] = e.data
|
||||
}
|
||||
}
|
||||
cart.mem.busStuffDelay = true
|
||||
|
@ -285,7 +282,7 @@ func (cart *Elf) Patch(_ int, _ uint8) error {
|
|||
}
|
||||
|
||||
func (cart *Elf) runARM() bool {
|
||||
if cart.mem.drain {
|
||||
if cart.mem.stream.drain {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -332,7 +329,7 @@ func (cart *Elf) AccessPassive(addr uint16, data uint8) {
|
|||
cart.mem.gpio.data[ADDR_IDR+1] = uint8(addr >> 8)
|
||||
|
||||
// check that strongarm is set and panic if not (see WARNING comment above)
|
||||
if !cart.mem.streaming {
|
||||
if !cart.mem.stream.active {
|
||||
if cart.mem.strongarm.running.function == nil {
|
||||
panic("ELF ROMs do not handle non strongarm reading of the GPIO")
|
||||
}
|
||||
|
@ -349,7 +346,7 @@ func (cart *Elf) AccessPassive(addr uint16, data uint8) {
|
|||
cart.runARM()
|
||||
|
||||
// check that strongarm is set and panic if not (see WARNING comment above)
|
||||
if !cart.mem.streaming {
|
||||
if !cart.mem.stream.active {
|
||||
if cart.mem.strongarm.running.function == nil {
|
||||
panic("ELF ROMs do not handle non strongarm reading of the GPIO")
|
||||
}
|
||||
|
|
|
@ -152,14 +152,7 @@ type elfMemory struct {
|
|||
yield coprocessor.CoProcYield
|
||||
|
||||
// byte stream support
|
||||
streaming bool
|
||||
stream []streamEntry
|
||||
drain bool
|
||||
}
|
||||
|
||||
type streamEntry struct {
|
||||
addr uint16
|
||||
data uint8
|
||||
stream stream
|
||||
}
|
||||
|
||||
func newElfMemory() *elfMemory {
|
||||
|
@ -754,13 +747,12 @@ func (mem *elfMemory) MapAddress(addr uint32, write bool) (*[]byte, uint32) {
|
|||
if f.support {
|
||||
mem.runStrongArmFunction(f.function)
|
||||
} else {
|
||||
if mem.streaming {
|
||||
if mem.stream.active {
|
||||
mem.setStrongArmFunction(f.function)
|
||||
for mem.strongarm.running.function != nil {
|
||||
mem.strongarm.running.function(mem)
|
||||
}
|
||||
if len(mem.stream) >= 1000 {
|
||||
mem.drain = true
|
||||
if mem.stream.drain {
|
||||
mem.arm.Interrupt()
|
||||
}
|
||||
} else {
|
||||
|
|
79
hardware/memory/cartridge/elf/stream.go
Normal file
79
hardware/memory/cartridge/elf/stream.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
// This file is part of Gopher2600.
|
||||
//
|
||||
// Gopher2600 is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Gopher2600 is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package elf
|
||||
|
||||
import "fmt"
|
||||
|
||||
type streamEntry struct {
|
||||
addr uint16
|
||||
data uint8
|
||||
}
|
||||
|
||||
func (s streamEntry) String() string {
|
||||
return fmt.Sprintf("%04x=%02x", s.addr, s.data)
|
||||
}
|
||||
|
||||
type stream struct {
|
||||
active bool
|
||||
stream [1000]streamEntry
|
||||
ptr int
|
||||
|
||||
drain bool
|
||||
drainPtr int
|
||||
drainTop int
|
||||
}
|
||||
|
||||
func (s *stream) startDrain() {
|
||||
s.drain = true
|
||||
s.drainTop = s.ptr
|
||||
s.drainPtr = 0
|
||||
}
|
||||
|
||||
func (s *stream) push(e streamEntry) {
|
||||
s.stream[s.ptr] = e
|
||||
s.ptr++
|
||||
|
||||
// the stream can be pushed to even if the drain has started. this can
|
||||
// happen when the pushBoundary has been reached but there are still bytes
|
||||
// to be pushed from the current strongarm function
|
||||
if s.drain {
|
||||
s.drainTop = s.ptr
|
||||
} else {
|
||||
// the pushBoundary prevents out-of-bounds errors in the event of an
|
||||
// instruction pushing more bytes than are available. a sufficiently
|
||||
// high boundary value means that the drain will start before the next
|
||||
// strongarm function is reached but allowing the current function to
|
||||
// complete
|
||||
const pushBoundary = 10
|
||||
if s.ptr >= len(s.stream)-pushBoundary {
|
||||
s.startDrain()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stream) pull() streamEntry {
|
||||
e := s.stream[s.drainPtr]
|
||||
s.drainPtr++
|
||||
if s.drainPtr >= s.drainTop {
|
||||
s.drain = false
|
||||
s.ptr = 0
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (s *stream) peekAddr() uint16 {
|
||||
return s.stream[s.drainPtr].addr
|
||||
}
|
|
@ -75,8 +75,8 @@ func (mem *elfMemory) setNextRomAddress(addr uint16) {
|
|||
}
|
||||
|
||||
func (mem *elfMemory) injectRomByte(v uint8) bool {
|
||||
if mem.streaming {
|
||||
mem.stream = append(mem.stream, streamEntry{
|
||||
if mem.stream.active {
|
||||
mem.stream.push(streamEntry{
|
||||
addr: mem.strongarm.nextRomAddress,
|
||||
data: v,
|
||||
})
|
||||
|
@ -99,7 +99,7 @@ func (mem *elfMemory) injectRomByte(v uint8) bool {
|
|||
}
|
||||
|
||||
func (mem *elfMemory) yieldDataBus(addr uint16) bool {
|
||||
if mem.streaming {
|
||||
if mem.stream.active {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ func (mem *elfMemory) yieldDataBus(addr uint16) bool {
|
|||
}
|
||||
|
||||
func (mem *elfMemory) yieldDataBusToStack() bool {
|
||||
if mem.streaming {
|
||||
if mem.stream.active {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ func vcsSta3(mem *elfMemory) {
|
|||
|
||||
// uint8_t snoopDataBus(uint16_t address)
|
||||
func snoopDataBus(mem *elfMemory) {
|
||||
if mem.streaming {
|
||||
if mem.stream.active {
|
||||
mem.endStrongArmFunction()
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue