One more code

This commit is contained in:
RunasSudo 2017-02-06 14:09:53 +10:30
parent dbc021967a
commit 4660539f34
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
4 changed files with 47 additions and 3 deletions

17
dbg_pdb.py Normal file
View File

@ -0,0 +1,17 @@
# synacor.py - An implementation of the Synacor Challenge
# Copyright © 2017 RunasSudo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
DBG_FLAG = True

View File

@ -252,3 +252,27 @@ Similarly, the `R1` for the teleporter code is the value of `R8` from the Ackerm
1592 set R1 R8
The remaining two codes, for the coins and the vault, are more complicated still, but follow the same pattern of determining `R1` based on the player's history.
For the coins, the call to `0731` derives an `R1` from the values at memory locations `69de` to `69e2`. One would presume that this relates to the order in which coins are inserted into the puzzle, and following the trail of callbacks for the coins confirms this. The important lines are:
13c0 rmem R3 099e # nr of coins inserted
13c3 add R3 R3 69dd
13c7 add R3 R3 0001
13cb wmem R3 R2 # R2 is the number of dots on the coin
Thus the values should be 9, 2, 5, 7 and 3: the missing numbers in the solved equation.
It is now trivial to generate the correct value of `R1`. Based on the code beginning, `15fd`:
```python
data_69de = [9, 2, 5, 7, 3]
R1 = 0
for i in range(len(data_69de)):
R2 = data_69de[i]
R1 = R1 + R2
R1 = (R1 * 0x7bac) % 0x8000
R1 = R1 ^ R2
```
The result is `0b3b`.

View File

@ -130,7 +130,9 @@ while True:
if len(SYN_STK) == 0:
raise Exception('Attempted to return with empty stack at {}'.format(SYN_PTR))
SYN_PTR = SYN_STK.pop()
DBG_CSTK.pop()
if len(DBG_CSTK) > 0:
DBG_CSTK.pop()
elif instruction == 19: #OUT
print(chr(swallowOp().get()), end='')
elif instruction == 20: #IN

View File

@ -21,6 +21,7 @@ import sys
IV_LEN = 3
CODE_LEN = 12
# Emulate 0731
def generate_code(R1, R2, R3, R4):
R2data = SYN_MEM[R2+1:R2+1+SYN_MEM[R2]]
R4data = SYN_MEM[R4+1:R4+1+SYN_MEM[R4]]
@ -63,12 +64,12 @@ for R2 in range(0x17b4, 0x7562):
R1 ^= 0x4154
SYN_MEM[R2] = R1
# Look for calls to 0731
# Calls to 0731
CODE_PARAMS = [
(0x0058, 0x650a, 0x7fff, 0x6e8b), # R1 from the maze
(0x1092, 0x650a, 0x7fff, 0x6eed),
(0x6486, 0x650a, 0x7fff, 0x7239), # R1 is R8 from Ackermann
# 162e is a bit tricky
(0x0b3b, 0x650a, 0x7fff, 0x73df), # R1 from the dots on the coins
# 1691 is a bit tricky
]