mirror of
https://github.com/ariejan/i6502.git
synced 2025-04-08 21:43:30 +00:00
Merge pull request #3 from ariejan/issue_3_acia6551
Add support for 6551 Asynchronous Communications Interface Adapter (ACIA)
This commit is contained in:
commit
4764cb24ca
165
acia6551.go
Normal file
165
acia6551.go
Normal file
@ -0,0 +1,165 @@
|
||||
package i6502
|
||||
|
||||
const (
|
||||
aciaData = iota
|
||||
aciaStatus
|
||||
aciaCommand
|
||||
aciaControl
|
||||
)
|
||||
|
||||
/*
|
||||
ACIA 6551 Serial IO
|
||||
|
||||
This Asynchronous Communications Interface Adapater can be
|
||||
directly attached to the 6502's address and data busses.
|
||||
|
||||
It provides serial IO.
|
||||
|
||||
The supplied Rx and Tx channels can be used to read and wirte
|
||||
data to the ACIA 6551.
|
||||
*/
|
||||
type Acia6551 struct {
|
||||
rx byte
|
||||
tx byte
|
||||
|
||||
commandData byte
|
||||
controlData byte
|
||||
|
||||
rxFull bool
|
||||
txEmpty bool
|
||||
|
||||
rxIrqEnabled bool
|
||||
txIrqEnabled bool
|
||||
|
||||
overrun bool
|
||||
}
|
||||
|
||||
func NewAcia6551() (*Acia6551, error) {
|
||||
acia := &Acia6551{}
|
||||
acia.Reset()
|
||||
|
||||
return acia, nil
|
||||
}
|
||||
|
||||
func (a *Acia6551) Size() uint16 {
|
||||
// We have a only 4 addresses, Data, Status, Command and Control
|
||||
return 0x04
|
||||
}
|
||||
|
||||
// Emulates a hardware reset
|
||||
func (a *Acia6551) Reset() {
|
||||
a.rx = 0
|
||||
a.rxFull = false
|
||||
|
||||
a.tx = 0
|
||||
a.txEmpty = true
|
||||
|
||||
a.rxIrqEnabled = false
|
||||
a.txIrqEnabled = false
|
||||
|
||||
a.overrun = false
|
||||
|
||||
a.setControl(0)
|
||||
a.setCommand(0)
|
||||
}
|
||||
|
||||
func (a *Acia6551) setControl(data byte) {
|
||||
a.controlData = data
|
||||
}
|
||||
|
||||
func (a *Acia6551) setCommand(data byte) {
|
||||
a.commandData = data
|
||||
|
||||
a.rxIrqEnabled = (data & 0x02) != 0
|
||||
a.txIrqEnabled = ((data & 0x04) != 0) && ((data & 0x08) != 1)
|
||||
}
|
||||
|
||||
func (a *Acia6551) statusRegister() byte {
|
||||
status := byte(0)
|
||||
|
||||
if a.rxFull {
|
||||
status |= 0x08
|
||||
}
|
||||
|
||||
if a.txEmpty {
|
||||
status |= 0x10
|
||||
}
|
||||
|
||||
if a.overrun {
|
||||
status |= 0x04
|
||||
}
|
||||
|
||||
return status
|
||||
}
|
||||
|
||||
// Implements io.Reader, for external programs to read TX'ed data from
|
||||
// the serial output.
|
||||
func (a *Acia6551) Read(p []byte) (n int, err error) {
|
||||
a.txEmpty = true
|
||||
copy(p, []byte{a.tx})
|
||||
// TODO: Handle txInterrupt
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
// Implements io.Writer, for external programs to write to the
|
||||
// ACIA's RX
|
||||
func (a *Acia6551) Write(p []byte) (n int, err error) {
|
||||
for _, b := range p {
|
||||
a.rxWrite(b)
|
||||
}
|
||||
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// Used by the AddressBus to read data from the ACIA 6551
|
||||
func (a *Acia6551) ReadByte(address uint16) byte {
|
||||
switch address {
|
||||
case aciaData:
|
||||
return a.rxRead()
|
||||
case aciaStatus:
|
||||
return a.statusRegister()
|
||||
case aciaCommand:
|
||||
return a.commandData
|
||||
case aciaControl:
|
||||
return a.controlData
|
||||
}
|
||||
|
||||
return 0x00
|
||||
}
|
||||
|
||||
// Used by the AddressBus to write data to the ACIA 6551
|
||||
func (a *Acia6551) WriteByte(address uint16, data byte) {
|
||||
switch address {
|
||||
case aciaData:
|
||||
a.txWrite(data)
|
||||
case aciaStatus:
|
||||
a.Reset()
|
||||
case aciaCommand:
|
||||
a.setCommand(data)
|
||||
case aciaControl:
|
||||
a.setControl(data)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Acia6551) rxRead() byte {
|
||||
a.overrun = false
|
||||
a.rxFull = false
|
||||
return a.rx
|
||||
}
|
||||
|
||||
func (a *Acia6551) rxWrite(data byte) {
|
||||
// Oh no, overrun. Set the appropriate status
|
||||
if a.rxFull {
|
||||
a.overrun = true
|
||||
}
|
||||
|
||||
a.rx = data
|
||||
a.rxFull = true
|
||||
|
||||
// TODO: Interrupts
|
||||
}
|
||||
|
||||
func (a *Acia6551) txWrite(data byte) {
|
||||
a.tx = data
|
||||
a.txEmpty = false
|
||||
}
|
157
acia6551_test.go
Normal file
157
acia6551_test.go
Normal file
@ -0,0 +1,157 @@
|
||||
package i6502
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func AciaSubject() *Acia6551 {
|
||||
acia, _ := NewAcia6551()
|
||||
return acia
|
||||
}
|
||||
|
||||
func TestNewAcia6551(t *testing.T) {
|
||||
acia, err := NewAcia6551()
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 0x4, acia.Size())
|
||||
}
|
||||
|
||||
func TestAciaReset(t *testing.T) {
|
||||
a := AciaSubject()
|
||||
|
||||
a.Reset()
|
||||
|
||||
assert.Equal(t, a.tx, 0)
|
||||
assert.True(t, a.txEmpty)
|
||||
|
||||
assert.Equal(t, a.rx, 0)
|
||||
assert.False(t, a.rxFull)
|
||||
|
||||
assert.False(t, a.txIrqEnabled)
|
||||
assert.False(t, a.rxIrqEnabled)
|
||||
|
||||
assert.False(t, a.overrun)
|
||||
assert.Equal(t, 0, a.controlData)
|
||||
}
|
||||
|
||||
func TestAciaWriteByteAndReader(t *testing.T) {
|
||||
a := AciaSubject()
|
||||
|
||||
// CPU writes data
|
||||
a.WriteByte(aciaData, 0x42)
|
||||
|
||||
// System reads from Tx
|
||||
value := make([]byte, 1)
|
||||
bytesRead, _ := a.Read(value)
|
||||
|
||||
if assert.Equal(t, 1, bytesRead) {
|
||||
assert.Equal(t, 0x42, value[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestAciaWriterAndReadByte(t *testing.T) {
|
||||
a := AciaSubject()
|
||||
|
||||
// System writes a single byte
|
||||
bytesWritten, _ := a.Write([]byte{0x42})
|
||||
|
||||
if assert.Equal(t, 1, bytesWritten) {
|
||||
assert.Equal(t, 0x42, a.ReadByte(aciaData))
|
||||
}
|
||||
|
||||
// System writes multiple bytes
|
||||
bytesWritten, _ = a.Write([]byte{0x42, 0x32, 0xAB})
|
||||
|
||||
if assert.Equal(t, 3, bytesWritten) {
|
||||
assert.Equal(t, 0xAB, a.ReadByte(aciaData))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAciaCommandRegister(t *testing.T) {
|
||||
a := AciaSubject()
|
||||
assert.False(t, a.rxIrqEnabled)
|
||||
assert.False(t, a.txIrqEnabled)
|
||||
|
||||
a.WriteByte(aciaCommand, 0x02) // b0000 0010 RX Irq enabled
|
||||
assert.True(t, a.rxIrqEnabled)
|
||||
assert.False(t, a.txIrqEnabled)
|
||||
|
||||
a.WriteByte(aciaCommand, 0x04) // b0000 0100 TX Irq enabled
|
||||
assert.False(t, a.rxIrqEnabled)
|
||||
assert.True(t, a.txIrqEnabled)
|
||||
|
||||
a.WriteByte(aciaCommand, 0x06) // b0000 0110 RX + TX Irq enabled
|
||||
assert.True(t, a.rxIrqEnabled)
|
||||
assert.True(t, a.txIrqEnabled)
|
||||
|
||||
assert.Equal(t, 0x06, a.ReadByte(aciaCommand))
|
||||
}
|
||||
|
||||
func TestAciaControlRegister(t *testing.T) {
|
||||
a := AciaSubject()
|
||||
|
||||
a.WriteByte(aciaControl, 0xB8)
|
||||
assert.Equal(t, 0xB8, a.ReadByte(aciaControl))
|
||||
}
|
||||
|
||||
func TestAciaStatusRegister(t *testing.T) {
|
||||
a := AciaSubject()
|
||||
|
||||
a.rxFull = false
|
||||
a.txEmpty = false
|
||||
a.overrun = false
|
||||
assert.Equal(t, 0x00, a.ReadByte(aciaStatus))
|
||||
|
||||
a.rxFull = true
|
||||
a.txEmpty = false
|
||||
a.overrun = false
|
||||
assert.Equal(t, 0x08, a.ReadByte(aciaStatus))
|
||||
|
||||
a.rxFull = false
|
||||
a.txEmpty = true
|
||||
a.overrun = false
|
||||
assert.Equal(t, 0x10, a.ReadByte(aciaStatus))
|
||||
|
||||
a.rxFull = false
|
||||
a.txEmpty = false
|
||||
a.overrun = true
|
||||
assert.Equal(t, 0x04, a.ReadByte(aciaStatus))
|
||||
}
|
||||
|
||||
func TestAciaIntegration(t *testing.T) {
|
||||
// Create a system
|
||||
// * 32kB RAM at 0x0000-7FFFF
|
||||
// * ACIA at 0x8800-8803
|
||||
ram, _ := NewRam(0x8000)
|
||||
acia, _ := NewAcia6551()
|
||||
bus, _ := NewAddressBus()
|
||||
bus.Attach(ram, 0x0000)
|
||||
bus.Attach(acia, 0x8800)
|
||||
cpu, _ := NewCpu(bus)
|
||||
|
||||
program := []byte{
|
||||
0xA9, 0x00, // LDA #$00
|
||||
0x8D, 0x01, 0x88, // STA AciaStatus (Reset)
|
||||
0xA9, 0x42, // LDA #$42
|
||||
0x8D, 0x00, 0x88, // STA AciaData (Write)
|
||||
0xAD, 0x00, 0x88, // LDA AciaData (Read)
|
||||
}
|
||||
|
||||
cpu.LoadProgram(program, 0x0200)
|
||||
cpu.Steps(2)
|
||||
|
||||
acia.Write([]byte{0xAB})
|
||||
|
||||
cpu.Steps(3)
|
||||
|
||||
value := make([]byte, 1)
|
||||
bytesRead, _ := acia.Read(value)
|
||||
|
||||
if assert.Equal(t, 1, bytesRead) {
|
||||
assert.Equal(t, 0x42, value[0])
|
||||
}
|
||||
|
||||
assert.Equal(t, 0xAB, cpu.A)
|
||||
}
|
@ -62,13 +62,13 @@ Read an 8-bit value from Memory attached at the 16-bit address.
|
||||
|
||||
This will panic if you try to read from an address that has no Memory attached.
|
||||
*/
|
||||
func (a *AddressBus) Read(address uint16) byte {
|
||||
func (a *AddressBus) ReadByte(address uint16) byte {
|
||||
addressable, err := a.addressableForAddress(address)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return addressable.memory.Read(address - addressable.start)
|
||||
return addressable.memory.ReadByte(address - addressable.start)
|
||||
}
|
||||
|
||||
/*
|
||||
@ -77,8 +77,8 @@ 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.
|
||||
*/
|
||||
func (a *AddressBus) Read16(address uint16) uint16 {
|
||||
lo := uint16(a.Read(address))
|
||||
hi := uint16(a.Read(address + 1))
|
||||
lo := uint16(a.ReadByte(address))
|
||||
hi := uint16(a.ReadByte(address + 1))
|
||||
|
||||
return (hi << 8) | lo
|
||||
}
|
||||
@ -89,13 +89,13 @@ 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.
|
||||
*/
|
||||
func (a *AddressBus) Write(address uint16, data byte) {
|
||||
func (a *AddressBus) WriteByte(address uint16, data byte) {
|
||||
addressable, err := a.addressableForAddress(address)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
addressable.memory.Write(address-addressable.start, data)
|
||||
addressable.memory.WriteByte(address-addressable.start, data)
|
||||
}
|
||||
|
||||
/*
|
||||
@ -104,8 +104,8 @@ 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.
|
||||
*/
|
||||
func (a *AddressBus) Write16(address uint16, data uint16) {
|
||||
a.Write(address, byte(data))
|
||||
a.Write(address+1, byte(data>>8))
|
||||
a.WriteByte(address, byte(data))
|
||||
a.WriteByte(address+1, byte(data>>8))
|
||||
}
|
||||
|
||||
// Returns the addressable for the specified address, or an error if no addressable exists.
|
||||
|
@ -1,8 +1,9 @@
|
||||
package i6502
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEmptyAddressBus(t *testing.T) {
|
||||
@ -37,29 +38,29 @@ func TestBusReadWrite(t *testing.T) {
|
||||
bus.Attach(ram2, 0x8000)
|
||||
|
||||
// 8-bit Writing
|
||||
bus.Write(0x1234, 0xFA)
|
||||
assert.Equal(0xFA, ram.Read(0x1234))
|
||||
bus.WriteByte(0x1234, 0xFA)
|
||||
assert.Equal(0xFA, ram.ReadByte(0x1234))
|
||||
|
||||
// 16-bit Writing
|
||||
bus.Write16(0x1000, 0xAB42)
|
||||
assert.Equal(0x42, ram.Read(0x1000))
|
||||
assert.Equal(0xAB, ram.Read(0x1001))
|
||||
assert.Equal(0x42, ram.ReadByte(0x1000))
|
||||
assert.Equal(0xAB, ram.ReadByte(0x1001))
|
||||
|
||||
// 8-bit Reading
|
||||
ram.Write(0x5522, 0xDA)
|
||||
assert.Equal(0xDA, bus.Read(0x5522))
|
||||
ram.WriteByte(0x5522, 0xDA)
|
||||
assert.Equal(0xDA, bus.ReadByte(0x5522))
|
||||
|
||||
// 16-bit Reading
|
||||
ram.Write(0x4440, 0x7F)
|
||||
ram.Write(0x4441, 0x56)
|
||||
ram.WriteByte(0x4440, 0x7F)
|
||||
ram.WriteByte(0x4441, 0x56)
|
||||
assert.Equal(0x567F, bus.Read16(0x4440))
|
||||
|
||||
//// Test addressing memory not mounted at 0x0000
|
||||
|
||||
// Read from relative addressable Ram2: $C123
|
||||
ram2.Write(0x4123, 0xEF)
|
||||
assert.Equal(0xEF, bus.Read(0xC123))
|
||||
ram2.WriteByte(0x4123, 0xEF)
|
||||
assert.Equal(0xEF, bus.ReadByte(0xC123))
|
||||
|
||||
bus.Write(0x8001, 0x12)
|
||||
assert.Equal(0x12, ram2.Read(0x0001))
|
||||
bus.WriteByte(0x8001, 0x12)
|
||||
assert.Equal(0x12, ram2.ReadByte(0x0001))
|
||||
}
|
||||
|
50
cpu.go
50
cpu.go
@ -90,12 +90,18 @@ func (c *Cpu) handleIrq(PC uint16) {
|
||||
// and point the Program Counter to the beginning of the program.
|
||||
func (c *Cpu) LoadProgram(data []byte, location uint16) {
|
||||
for i, b := range data {
|
||||
c.Bus.Write(location+uint16(i), b)
|
||||
c.Bus.WriteByte(location+uint16(i), b)
|
||||
}
|
||||
|
||||
c.PC = location
|
||||
}
|
||||
|
||||
func (c *Cpu) Steps(steps int) {
|
||||
for i := 0; i < steps; i++ {
|
||||
c.Step()
|
||||
}
|
||||
}
|
||||
|
||||
// Read and execute the instruction pointed to by the Program Counter (PC)
|
||||
func (c *Cpu) Step() {
|
||||
instruction := c.readNextInstruction()
|
||||
@ -158,13 +164,13 @@ func (c *Cpu) execute(instruction Instruction) {
|
||||
c.setA(c.A ^ value)
|
||||
case sta:
|
||||
address := c.memoryAddress(instruction)
|
||||
c.Bus.Write(address, c.A)
|
||||
c.Bus.WriteByte(address, c.A)
|
||||
case stx:
|
||||
address := c.memoryAddress(instruction)
|
||||
c.Bus.Write(address, c.X)
|
||||
c.Bus.WriteByte(address, c.X)
|
||||
case sty:
|
||||
address := c.memoryAddress(instruction)
|
||||
c.Bus.Write(address, c.Y)
|
||||
c.Bus.WriteByte(address, c.Y)
|
||||
case tax:
|
||||
c.setX(c.A)
|
||||
case tay:
|
||||
@ -264,7 +270,7 @@ func (c *Cpu) execute(instruction Instruction) {
|
||||
|
||||
func (c *Cpu) readNextInstruction() Instruction {
|
||||
// Read the opcode
|
||||
opcode := c.Bus.Read(c.PC)
|
||||
opcode := c.Bus.ReadByte(c.PC)
|
||||
|
||||
optype, ok := opTypes[opcode]
|
||||
if !ok {
|
||||
@ -275,7 +281,7 @@ func (c *Cpu) readNextInstruction() Instruction {
|
||||
switch instruction.Size {
|
||||
case 1: // Zero operand instruction
|
||||
case 2: // 8-bit operand
|
||||
instruction.Op8 = c.Bus.Read(c.PC + 1)
|
||||
instruction.Op8 = c.Bus.ReadByte(c.PC + 1)
|
||||
case 3: // 16-bit operand
|
||||
instruction.Op16 = c.Bus.Read16(c.PC + 1)
|
||||
}
|
||||
@ -297,7 +303,7 @@ func (c *Cpu) resolveOperand(in Instruction) uint8 {
|
||||
case immediate:
|
||||
return in.Op8
|
||||
default:
|
||||
return c.Bus.Read(c.memoryAddress(in))
|
||||
return c.Bus.ReadByte(c.memoryAddress(in))
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,17 +362,17 @@ func (c *Cpu) sbc(in Instruction) {
|
||||
|
||||
func (c *Cpu) inc(in Instruction) {
|
||||
address := c.memoryAddress(in)
|
||||
value := c.Bus.Read(address) + 1
|
||||
value := c.Bus.ReadByte(address) + 1
|
||||
|
||||
c.Bus.Write(address, value)
|
||||
c.Bus.WriteByte(address, value)
|
||||
c.setArithmeticFlags(value)
|
||||
}
|
||||
|
||||
func (c *Cpu) dec(in Instruction) {
|
||||
address := c.memoryAddress(in)
|
||||
value := c.Bus.Read(address) - 1
|
||||
value := c.Bus.ReadByte(address) - 1
|
||||
|
||||
c.Bus.Write(address, value)
|
||||
c.Bus.WriteByte(address, value)
|
||||
c.setArithmeticFlags(value)
|
||||
}
|
||||
|
||||
@ -378,10 +384,10 @@ func (c *Cpu) asl(in Instruction) {
|
||||
c.setArithmeticFlags(c.A)
|
||||
default:
|
||||
address := c.memoryAddress(in)
|
||||
value := c.Bus.Read(address)
|
||||
value := c.Bus.ReadByte(address)
|
||||
c.setCarry((value >> 7) == 1)
|
||||
value <<= 1
|
||||
c.Bus.Write(address, value)
|
||||
c.Bus.WriteByte(address, value)
|
||||
c.setArithmeticFlags(value)
|
||||
}
|
||||
}
|
||||
@ -394,10 +400,10 @@ func (c *Cpu) lsr(in Instruction) {
|
||||
c.setArithmeticFlags(c.A)
|
||||
default:
|
||||
address := c.memoryAddress(in)
|
||||
value := c.Bus.Read(address)
|
||||
value := c.Bus.ReadByte(address)
|
||||
c.setCarry((value & 0x01) == 1)
|
||||
value >>= 1
|
||||
c.Bus.Write(address, value)
|
||||
c.Bus.WriteByte(address, value)
|
||||
c.setArithmeticFlags(value)
|
||||
}
|
||||
}
|
||||
@ -412,10 +418,10 @@ func (c *Cpu) rol(in Instruction) {
|
||||
c.setArithmeticFlags(c.A)
|
||||
default:
|
||||
address := c.memoryAddress(in)
|
||||
value := c.Bus.Read(address)
|
||||
value := c.Bus.ReadByte(address)
|
||||
c.setCarry((value & 0x80) != 0)
|
||||
value = value<<1 | carry
|
||||
c.Bus.Write(address, value)
|
||||
c.Bus.WriteByte(address, value)
|
||||
c.setArithmeticFlags(value)
|
||||
}
|
||||
}
|
||||
@ -430,10 +436,10 @@ func (c *Cpu) ror(in Instruction) {
|
||||
c.setArithmeticFlags(c.A)
|
||||
default:
|
||||
address := c.memoryAddress(in)
|
||||
value := c.Bus.Read(address)
|
||||
value := c.Bus.ReadByte(address)
|
||||
c.setCarry(value&0x01 == 1)
|
||||
value = value>>1 | carry<<7
|
||||
c.Bus.Write(address, value)
|
||||
c.Bus.WriteByte(address, value)
|
||||
c.setArithmeticFlags(value)
|
||||
}
|
||||
}
|
||||
@ -513,15 +519,15 @@ func (c *Cpu) sbcDecimal(a uint8, b uint8, carryIn uint8) {
|
||||
}
|
||||
|
||||
func (c *Cpu) stackPush(data byte) {
|
||||
c.Bus.Write(StackBase+uint16(c.SP), data)
|
||||
c.Bus.WriteByte(StackBase+uint16(c.SP), data)
|
||||
c.SP -= 1
|
||||
}
|
||||
|
||||
func (c *Cpu) stackPeek() byte {
|
||||
return c.Bus.Read(StackBase + uint16(c.SP+1))
|
||||
return c.Bus.ReadByte(StackBase + uint16(c.SP+1))
|
||||
}
|
||||
|
||||
func (c *Cpu) stackPop() byte {
|
||||
c.SP += 1
|
||||
return c.Bus.Read(StackBase + uint16(c.SP))
|
||||
return c.Bus.ReadByte(StackBase + uint16(c.SP))
|
||||
}
|
||||
|
341
cpu_test.go
341
cpu_test.go
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,6 @@ and become accessible by the Cpu.
|
||||
*/
|
||||
type Memory interface {
|
||||
Size() uint16
|
||||
Read(address uint16) byte
|
||||
Write(address uint16, data byte)
|
||||
ReadByte(address uint16) byte
|
||||
WriteByte(address uint16, data byte)
|
||||
}
|
||||
|
4
ram.go
4
ram.go
@ -16,10 +16,10 @@ func (r *Ram) Size() uint16 {
|
||||
return uint16(len(r.data))
|
||||
}
|
||||
|
||||
func (r *Ram) Read(address uint16) byte {
|
||||
func (r *Ram) ReadByte(address uint16) byte {
|
||||
return r.data[address]
|
||||
}
|
||||
|
||||
func (r *Ram) Write(address uint16, data byte) {
|
||||
func (r *Ram) WriteByte(address uint16, data byte) {
|
||||
r.data[address] = data
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
package i6502
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRamSize(t *testing.T) {
|
||||
@ -18,6 +19,6 @@ func TestRamReadWrite(t *testing.T) {
|
||||
assert.Equal(t, 0x00, ram.data[i])
|
||||
}
|
||||
|
||||
ram.Write(0x1000, 0x42)
|
||||
assert.Equal(t, 0x42, ram.Read(0x1000))
|
||||
ram.WriteByte(0x1000, 0x42)
|
||||
assert.Equal(t, 0x42, ram.ReadByte(0x1000))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user