package memory import ( "encoding/binary" "fmt" "io" "sync" ) type MemoryByte struct { Value byte Valid bool Changed bool } func (b MemoryByte) Hex() string { if !b.Valid { return "??" } return fmt.Sprintf("%02x", b.Value) } func (b MemoryByte) Dec() string { if !b.Valid { return "???" } return fmt.Sprintf("%d", b.Value) } func (b MemoryByte) Bin() string { if !b.Valid { return "????????" } return fmt.Sprintf("%08b", b.Value) } type MemorySrc interface { io.ReaderAt io.WriterAt } type Memory struct { src MemorySrc mu sync.Mutex bytes []MemoryByte pendingWrites map[int]byte } func New(src MemorySrc, size int) *Memory { ret := &Memory{ src: src, bytes: make([]MemoryByte, size), pendingWrites: map[int]byte{}, } return ret } func (m *Memory) Len() int { m.mu.Lock() defer m.mu.Unlock() return len(m.bytes) } func (m *Memory) Load(start, count int) error { if m.needsRefresh(start, count) { return m.Refresh(start, count) } return nil } func (m *Memory) needsRefresh(start, count int) bool { m.mu.Lock() defer m.mu.Unlock() for _, b := range m.bytes { if !b.Valid { return true } } return false } func (m *Memory) Refresh(start, count int) error { bs := make([]byte, count) if _, err := m.src.ReadAt(bs, int64(start)); err != nil { return err } m.mu.Lock() defer m.mu.Unlock() for i, v := range bs { m.bytes[start+i] = MemoryByte{v, true, false} } return nil } func (m *Memory) At(addr int) MemoryByte { m.mu.Lock() defer m.mu.Unlock() if addr >= len(m.bytes) { return MemoryByte{} } if v, ok := m.pendingWrites[addr]; ok { return MemoryByte{v, true, true} } return m.bytes[addr] } func (m *Memory) Slice(start, end int) []MemoryByte { ret := make([]MemoryByte, end-start) for i := range ret { ret[i] = m.At(start + i) } return ret } func (m *Memory) ByteSlice(start, end int) []byte { ret := make([]byte, end-start) for i, b := range m.Slice(start, end) { if !b.Valid { return nil } ret[i] = b.Value } return ret } func (m *Memory) Decode(addr int, out any) bool { bs := make([]byte, binary.Size(out)) mem := m.Slice(addr, addr+len(bs)) for i, b := range mem { if !b.Valid { return false } bs[i] = b.Value } if _, err := binary.Decode(bs, binary.BigEndian, out); err != nil { return false } return true } func (m *Memory) Write(addr int, val byte) { m.mu.Lock() defer m.mu.Unlock() m.pendingWrites[addr] = val } func (m *Memory) Commit() error { m.mu.Lock() defer m.mu.Unlock() for addr, val := range m.pendingWrites { if _, err := m.src.WriteAt([]byte{val}, int64(addr)); err != nil { return err } delete(m.pendingWrites, addr) m.bytes[addr] = MemoryByte{val, true, false} } return nil } func (m *Memory) HasPendingWrites() bool { m.mu.Lock() defer m.mu.Unlock() return len(m.pendingWrites) > 0 }