Ross Light avatar Ross Light committed ce4d4d0

Add loadByte/storeByte methods

Comments (0)

Files changed (2)

 		m.setVariable(ret, 0)
 		return nil
 	}
-	nlocals := int(m.memory[address])
+	nlocals := int(m.loadByte(address))
 	if nlocals > 15 {
 		return errors.New("Routines have a maximum of 15 local variables")
 	}
 	if address == 0 {
 		return nil
 	}
-	nlocals := int(m.memory[address])
+	nlocals := int(m.loadByte(address))
 	if nlocals > 15 {
 		return errors.New("Routines have a maximum of 15 local variables")
 	}
 		m.setVariable(storeVariable, m.loadWord(a))
 	case 0x10:
 		// loadb
-		// TODO: should the value be sign extended?
 		a := Address(ops[0]) + Address(ops[1])
-		m.setVariable(storeVariable, Word(m.memory[a]))
+		m.setVariable(storeVariable, Word(m.loadByte(a)))
 	case 0x11:
 		// get_prop
 		obj := m.loadObject(ops[0])
 		// Sadly, the operand is the address of the property data, so we have to dupe work to extract the length. Le sigh.
 		var size uint8
 		if m.Version() <= 3 {
-			size = m.memory[Address(ops[0])-1]>>5 + 1
+			size = m.loadByte(Address(ops[0])-1)>>5 + 1
 		} else {
-			if m.memory[Address(ops[0])-1]&0x80 == 0 {
+			if m.loadByte(Address(ops[0])-1)&0x80 == 0 {
 				// One-byte
-				size = m.memory[Address(ops[0])-1]>>6 + 1
+				size = m.loadByte(Address(ops[0])-1)>>6 + 1
 			} else {
 				// Two-byte
-				size = m.memory[Address(ops[0])-1] & 0x3f
+				size = m.loadByte(Address(ops[0])-1) & 0x3f
 				if size == 0 {
 					size = 64
 				}
 	case 0x2:
 		// storeb
 		a := Address(ops[0]) + Address(ops[1])
-		m.memory[a] = byte(ops[2])
+		m.storeByte(a, byte(ops[2]))
 	case 0x3:
 		// put_prop
 		obj := m.loadObject(ops[0])
 		textAddr := Address(ops[0])
 		if m.Version() <= 4 {
 			var err error
-			input, err = m.ui.Input(int(m.memory[textAddr]) - 1)
+			input, err = m.ui.Input(int(m.loadByte(textAddr)) - 1)
 			if err != nil {
 				return err
 			}
 			for i := range input {
 				// TODO: Ensure input is ZSCII-clean
 				input[i] = unicode.ToLower(input[i])
-				m.memory[textAddr+1+Address(i)] = byte(input[i])
+				m.storeByte(textAddr+1+Address(i), byte(input[i]))
 			}
-			m.memory[textAddr+1+Address(len(input))] = 0
+			m.storeByte(textAddr+1+Address(len(input)), 0)
 		} else {
 			var err error
-			input, err = m.ui.Input(int(m.memory[Address(ops[0])]))
+			input, err = m.ui.Input(int(m.loadByte(Address(ops[0]))))
 			if err != nil {
 				return err
 			}
 
 			base := textAddr + 2
-			if n := m.memory[textAddr+1]; n > 0 {
+			if n := m.loadByte(textAddr + 1); n > 0 {
 				base += Address(n)
 			}
-			m.memory[textAddr+1] += byte(len(input))
+			m.storeByte(textAddr+1, m.loadByte(textAddr+1)+byte(len(input)))
 			for i := range input {
 				// TODO: Ensure input is ZSCII-clean
-				m.memory[base+Address(i)] = byte(input[i])
+				m.storeByte(base+Address(i), byte(input[i]))
 				input[i] = unicode.ToLower(input[i])
 			}
 		}
 			return err
 		}
 		textAddr := Address(ops[0])
-		n := Address(m.memory[textAddr+1])
+		n := Address(m.loadByte(textAddr + 1))
 		input := make([]rune, n)
 		for i := range input {
-			input[i] = unicode.ToLower(rune(m.memory[textAddr+2+Address(i)]))
+			input[i] = unicode.ToLower(rune(m.loadByte(textAddr + 2 + Address(i))))
 		}
 		m.tokenise(input, dict, Address(ops[1]), len(ops) < 3 || ops[3] == 0)
 	case 0x1d:
 		size := Address(int16(ops[2]))
 		if dst == 0 {
 			for addr := src; addr < src+size; addr++ {
-				m.memory[addr] = 0
+				m.storeByte(addr, 0)
 			}
 			return nil
 		}
 		} else {
 			// Negative size means forcibly copy backward.
 			for i := -size - 1; i >= 0; i-- {
-				m.memory[dst+i] = m.memory[src+i]
+				m.storeByte(dst+i, m.loadByte(src+i))
 			}
 		}
 	case 0x1e:
 		m.memory[flags2] |= 1 << 7
 	}
 	// TODO
-	m.memory[screenWidth] = 255
-	m.memory[screenHeight] = 255
+	m.storeByte(screenWidth, 255)
+	m.storeByte(screenHeight, 255)
 }
 
 // out handles output. This is sent to the UI, unless redirection has been
 		m.storeWord(tab.Start, m.loadWord(tab.Start)+Word(len(s)))
 		for _, r := range s {
 			// rune should already be ZSCII-clean, since we wrote it.
-			m.memory[tab.Curr] = byte(r)
+			m.storeByte(tab.Curr, byte(r))
 			tab.Curr++
 		}
 		return nil
 		return nil
 	}
 
-	isTime := m.memory[1]&0x02 != 0
+	isTime := m.loadByte(1)&0x02 != 0
 	name, err := m.loadObject(m.getVariable(0x10)).FetchName(m)
 	if err != nil {
 		return err
 
 // Version returns the version of the machine, defined in the story file.
 func (m *Machine) Version() byte {
-	return m.memory[0]
+	return m.loadByte(0)
 }
 
 // seed restarts the random generator with the current time as a seed.
 	return Word(m.rand.Uint32()%uint32(s) + 1)
 }
 
+func (m *Machine) loadByte(a Address) byte {
+	return m.memory[a]
+}
+
+func (m *Machine) storeByte(a Address, b byte) {
+	m.memory[a] = b
+}
+
 func (m *Machine) loadWord(a Address) Word {
 	return Word(m.memory[a])<<8 | Word(m.memory[a+1])
 }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.