2014-08-13 07:26:33 +00:00
|
|
|
package i6502
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
)
|
|
|
|
|
2014-08-17 11:07:22 +00:00
|
|
|
/*
|
|
|
|
The AddressBus contains a list of all attached memory components,
|
|
|
|
like Ram, Rom and IO. It takes care of mapping the global 16-bit
|
|
|
|
address space of the Cpu to the relative memory addressing of
|
|
|
|
each component.
|
|
|
|
*/
|
2014-08-13 07:26:33 +00:00
|
|
|
type AddressBus struct {
|
|
|
|
addressables []addressable // Different components
|
|
|
|
}
|
|
|
|
|
|
|
|
type addressable struct {
|
|
|
|
memory Memory // Actual memory
|
|
|
|
start uint16 // First address in address space
|
|
|
|
end uint16 // Last address in address space
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *addressable) String() string {
|
|
|
|
return fmt.Sprintf("\t0x%04X-%04X\n", a.start, a.end)
|
|
|
|
}
|
|
|
|
|
2014-08-17 11:07:22 +00:00
|
|
|
// Creates a new, empty 16-bit AddressBus
|
|
|
|
func NewAddressBus() (*AddressBus, error) {
|
|
|
|
return &AddressBus{addressables: make([]addressable, 0)}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a string with details about the AddressBus and attached memory
|
2014-08-13 07:26:33 +00:00
|
|
|
func (a *AddressBus) String() string {
|
|
|
|
output := "Address Bus:\n"
|
|
|
|
|
|
|
|
for _, addressable := range a.addressables {
|
|
|
|
output += addressable.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
return output
|
|
|
|
}
|
|
|
|
|
2014-08-17 11:07:22 +00:00
|
|
|
/*
|
|
|
|
Attach the given Memory at the specified memory offset.
|
|
|
|
|
|
|
|
To attach 16kB ROM at 0xC000-FFFF, you simple attach the Rom at
|
|
|
|
address 0xC000, the Size of the Memory determines the end-address.
|
2014-08-13 07:26:33 +00:00
|
|
|
|
2014-08-17 11:07:22 +00:00
|
|
|
rom, _ := i6502.NewRom(0x4000)
|
|
|
|
bus.Attach(rom, 0xC000)
|
|
|
|
*/
|
2014-08-13 07:26:33 +00:00
|
|
|
func (a *AddressBus) Attach(memory Memory, offset uint16) {
|
|
|
|
start := offset
|
|
|
|
end := offset + memory.Size() - 1
|
|
|
|
addressable := addressable{memory: memory, start: start, end: end}
|
|
|
|
|
|
|
|
a.addressables = append(a.addressables, addressable)
|
|
|
|
}
|
|
|
|
|
2014-08-17 11:07:22 +00:00
|
|
|
/*
|
|
|
|
Read an 8-bit value from Memory attached at the 16-bit address.
|
2014-08-13 07:26:33 +00:00
|
|
|
|
2014-08-17 11:07:22 +00:00
|
|
|
This will panic if you try to read from an address that has no Memory attached.
|
|
|
|
*/
|
2014-08-13 07:26:33 +00:00
|
|
|
func (a *AddressBus) Read(address uint16) byte {
|
|
|
|
addressable, err := a.addressableForAddress(address)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return addressable.memory.Read(address - addressable.start)
|
|
|
|
}
|
|
|
|
|
2014-08-17 11:07:22 +00:00
|
|
|
/*
|
|
|
|
Convenience method to quickly read a 16-bit value from address and address + 1.
|
|
|
|
|
|
|
|
Note that we first read the LOW byte from address and then the HIGH byte from address + 1.
|
|
|
|
*/
|
2014-08-13 07:26:33 +00:00
|
|
|
func (a *AddressBus) Read16(address uint16) uint16 {
|
|
|
|
lo := uint16(a.Read(address))
|
|
|
|
hi := uint16(a.Read(address + 1))
|
|
|
|
|
|
|
|
return (hi << 8) | lo
|
|
|
|
}
|
|
|
|
|
2014-08-17 11:07:22 +00:00
|
|
|
/*
|
|
|
|
Write an 8-bit value to the Memory at the 16-bit address.
|
|
|
|
|
|
|
|
This will panic if you try to write to an address that has no Memory attached or
|
|
|
|
Memory that is read-only, like Rom.
|
|
|
|
*/
|
2014-08-13 07:26:33 +00:00
|
|
|
func (a *AddressBus) Write(address uint16, data byte) {
|
|
|
|
addressable, err := a.addressableForAddress(address)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
addressable.memory.Write(address-addressable.start, data)
|
|
|
|
}
|
|
|
|
|
2014-08-17 11:07:22 +00:00
|
|
|
/*
|
|
|
|
Convenience method to quickly write a 16-bit value to address and address + 1.
|
|
|
|
|
|
|
|
Note that the LOW byte will be stored in address and the high byte in address + 1.
|
|
|
|
*/
|
2014-08-13 07:26:33 +00:00
|
|
|
func (a *AddressBus) Write16(address uint16, data uint16) {
|
|
|
|
a.Write(address, byte(data))
|
|
|
|
a.Write(address+1, byte(data>>8))
|
|
|
|
}
|
2014-08-17 11:07:22 +00:00
|
|
|
|
|
|
|
// Returns the addressable for the specified address, or an error if no addressable exists.
|
|
|
|
func (a *AddressBus) addressableForAddress(address uint16) (*addressable, error) {
|
|
|
|
for _, addressable := range a.addressables {
|
|
|
|
if addressable.start <= address && addressable.end >= address {
|
|
|
|
return &addressable, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("No addressable memory found at 0x%04X", address)
|
|
|
|
}
|