Skip to content

Instantly share code, notes, and snippets.

@BenGardiner
Last active January 2, 2023 14:38
Show Gist options
  • Save BenGardiner/13fe76fd43f179a872acbb9f5729eb2c to your computer and use it in GitHub Desktop.
Save BenGardiner/13fe76fd43f179a872acbb9f5729eb2c to your computer and use it in GitHub Desktop.
this a writeup for a pair of fun SNES challenges by Zack Deveau, kinda...
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "e752e034-5e8d-4f32-80b0-2c6b5331bb4f",
"metadata": {},
"outputs": [],
"source": [
"# Copyright (c) 2022 Ben Gardiner\n",
"#\n",
"# Permission is hereby granted, free of charge, to any person obtaining a copy\n",
"# of this software and associated documentation files (the \"Software\"), to deal\n",
"# in the Software without restriction, including without limitation the rights\n",
"# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n",
"# copies of the Software, and to permit persons to whom the Software is\n",
"# furnished to do so, subject to the following conditions:\n",
"#\n",
"# The above copyright notice and this permission notice shall be included in all\n",
"# copies or substantial portions of the Software.\n",
"#\n",
"# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n",
"# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n",
"# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n",
"# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n",
"# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n",
"# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n",
"# SOFTWARE.\n",
"\n",
"# tested on r2 84e6cc6a21ec1c816d4d3eb3510d2cdc94330414 tag 5.4.2\n",
"import r2pipe"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "054ab151-db2a-4d03-af33-3527fdffd947",
"metadata": {},
"outputs": [],
"source": [
"def r2cmd(r, c):\n",
" '''\n",
" a simple wrapper for r2pipe command to allow 1) multi line commands and 2) colorized output (at least in jupyter notebooks)\n",
" '''\n",
" # force colorized output through r2pipe 🌈\n",
" r.cmd('e scr.color=true')\n",
" # use the best ANSI theme: bluy; no apologies to all the other trash themes ☜(゚ヮ゚☜)\n",
" r.cmd('eco bluy')\n",
" for a in c.strip().splitlines():\n",
" res = r.cmd(a)\n",
" if len(res) > 0:\n",
" print(res)"
]
},
{
"cell_type": "markdown",
"id": "3a4a5c81-cce0-41e9-8e65-b4e93f9f8c62",
"metadata": {
"tags": []
},
"source": [
"\n",
"This a writeup for a couple CTF challenges, kinda... It mostly follows the way that teamates of `cold_root` solved the pair of fun SNES challenges by Zack Deveau but it has been edited into an r2 tutorial for r2-applied-snes-re-ctf-solving-goodness.\n",
"\n",
"![frame_adv_input_correct.png](frame_adv_input_correct.png)\n"
]
},
{
"cell_type": "markdown",
"id": "55f1ccd3-91e8-4af7-a0c0-c0a2a73f5462",
"metadata": {},
"source": [
"# The Challenges\n",
"\n",
"From NorthSec 2021 CTF: two challenges that involved RE on a custom SNES crackme ROM! Super Fun. After submitting the flag for the first question, you get a second SNES ROM crackme with the same theme but now it's corrupted...\n",
"\n",
"## Sequence 1.\n",
"\n",
"> You know what matters the most in defense? Sturdy swords. The town’s blacksmith is pursuing a study in rare metals that could help him create stronger weaponry for our troops.\n",
"\n",
"> He got hold of a rare metal sequencer. You have to provide the correct sequence and it can create the strongest materials in the whole kingdom.\n",
"\n",
"> You want to help our blacksmith with this? All you have to do is to find the correct sequence.\n",
"\n",
"> The only problem is we don’t know the correct sequence… Can you help us figure it out?\n",
"\n",
"> He has provided the Sequencer https://dl.nsec/sequence_1.smc. You’ll also need what he called an emulator https://www.zsnes.com/ to run it. I don’t know what that means, but that’s why you’re the wizard and I’m just a honest barman serving mugs of ale!\n",
"\n",
"\n",
"## Sequence 2.\n",
"> Wonderful! It worked, but that’s such a heavy metal that it won’t be usable in the field!\n",
"\n",
"> Here’s a new improved sequence. It’s a little… corrupted? But I’m sure you can figure it out too!\n",
"\n",
"---\n",
"\n",
"# Table of Contents\n",
"\n",
"0. Actually Running the Thing\n",
"1. Sequence 1: Reverse Forward\n",
"2. Sequence 2: Reverse Backwards\n",
"\n",
"# 0. Actually Running the Thing\n",
"\n",
"![sequence1](sequence_1_on_snes9x.png)\n",
"\n",
"The ROMs provided in sequence_1.smc and sequence_2.smc are kinda picky. The screenshot above is the only time it ever ran in snes9x. It never did again after any emulator reset. We had similar problems with the rom in other emulators too e.g. bsnes, bsnes-plus, no$sns. (Update: it _will_ run in bsnes too. The trick there is to repeated reset and reload until it works 🤷‍♀️).\n",
"\n",
"The challenge description mentions *znes* emulator and of course it does work there. The trick with zsnes is you need to wrestle with the sources to build it on today's Linux distros -- or an older windows system to reliably run it. \n",
"\n",
"![sequence_1_on_zsnes](sequence_1_on_zsnes.jpg)\n",
"\n",
"This was a really fun challenge so there's probably a ton of other writeups on the trials and tribulations of actually running the thing. I know we spent enough time on that. Until we remembered a teamate has an old windows laptop with ZSNES already setup.\n",
"\n",
"But enough about that b/c in the end running it isn't actually necessary and we could of instead used some r2 commands (more on that in part 2)"
]
},
{
"cell_type": "markdown",
"id": "f604267c-caf7-4eb6-a83f-4e78a068b1d7",
"metadata": {},
"source": [
"# 1. Reversing Forward (sequence_1)\n",
"\n",
"Both sequence ROMs are crackmes that will print the flag (as opposed to the ones where the input _is_ the flag) so one way to get the flag here is to reverse engineer from the input forward to the input tests. The other way (generally speaking) is to work backwards from the flag printing and we'll cover that later).\n",
"\n",
"A rough plan for reversing forward:\n",
"1. What are the SNES joypad inputs?\n",
"2. What is accessing them?\n",
"3. What uses the accesses to the joypad inputs for OK/BAD decisions?\n",
"4. What are the OK inputs?\n",
"5. Press the buttons to make the good inputs. Or print the flag."
]
},
{
"cell_type": "markdown",
"id": "26dede54-316d-465e-a915-a54b76d6eeb1",
"metadata": {},
"source": [
"# RE-fwd 1: Joys\n",
"\n",
"This is a radare2 tutorial, right? So let's get on with it. `r2` is smart enough to recognize the headers of the `sequence_1.smc` as a SNES ROM."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "bd56a1d2-20e5-41e9-af51-6351182ea0de",
"metadata": {},
"outputs": [],
"source": [
"r = r2pipe.open('sequence_1.smc', ['-2'])"
]
},
{
"cell_type": "markdown",
"id": "d2fdf70c-6063-4505-9dc4-a5744a00ae8b",
"metadata": {},
"source": [
"here we launched r2 using `r2pipe.open()` on the rom challenge `sequence_1.smc` with argument `-2` to close stderr. There will be lots of warnings printed when anlyzing this ROM and we'll ignore them anyways ;) so let's just supress them"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "a4f75991-9ddd-4a46-92e0-57fcd951211c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"fd 3\n",
"file sequence_1.smc\n",
"size 0x400000\n",
"humansz 4M\n",
"mode r-x\n",
"format sfc\n",
"iorw false\n",
"block 0x100\n",
"type ROM\n",
"arch snes\n",
"baddr 0xffffffffffffffff\n",
"binsz 4194304\n",
"bits 16\n",
"canary false\n",
"retguard false\n",
"crypto false\n",
"endian little\n",
"havecode true\n",
"laddr 0x0\n",
"linenum false\n",
"lsyms false\n",
"machine Super NES / Super Famicom\n",
"nx false\n",
"os snes\n",
"pic false\n",
"relocs false\n",
"sanitize false\n",
"static true\n",
"stripped false\n",
"va true\n",
"\n"
]
}
],
"source": [
"r2cmd(r,'i')"
]
},
{
"cell_type": "markdown",
"id": "fdf48cc1-4932-4bd6-b29e-54e3c7c1e4b8",
"metadata": {},
"source": [
"Here we inquired about the file information (command: `i`) using a pretty-printing utility function for r2pipe in Jupyter notebooks: `r2cmd()` which we defined above.\n",
"\n",
"It's a _bit_ 'noisy' of output though, right? We just want to know: \"hey `r2`, do you _know_ this is a SNES?\""
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "4e629318-27bb-4247-95b0-733fb0269a40",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"arch snes\n",
"machine Super NES / Super Famicom\n",
"os snes\n",
"\n"
]
}
],
"source": [
"r2cmd(r,'i~+nes')"
]
},
{
"cell_type": "markdown",
"id": "1a631ed4-de67-4804-b179-32a6a4ece4cb",
"metadata": {},
"source": [
"Pretty clear now. What did we do there? We used `r2`'s built-in grep, `~` with case-insentive match `+` for `nes`.\n",
"\n",
"---\n",
"\n",
"We would like to know \"1. \"What are the SNES joypad inputs?\" So we need to ask `r2` for details about what it has analyzed about the rom we gave it. Does it know about the memory locations for joypads (c.f. https://en.wikibooks.org/wiki/Super_NES_Programming/Joypad_Input)?"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "10f663aa-069f-4844-8cc9-9f688ab054d2",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, \"f~+joy\")"
]
},
{
"cell_type": "markdown",
"id": "6a31c4ea-15fa-4e12-9e97-3875b1d9e213",
"metadata": {},
"source": [
"We simply asked `r2` for any `f`lags (no not those flags) command matching `joy` (`+` case insensitive). `r2` uses \"flags\" for naming memory locations in analysis in a binary. \n",
"\n",
"Sadly it does not know anything about the `joy`. But we can teach it...\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "9621b5ff-767d-464d-bf78-fcdf081acd94",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r,\"\"\"\n",
"f counter_en 1 0x4200 Counter Enable\n",
"f status_reg 1 0x4212 Status Register\n",
"f joy1b 1 0x4218 Joypad #1 Status B\n",
"f joy1a 1 0x4219 Joypad #2 Status A\n",
"f joy2b 1 0x421a Joypad #2 Status B\n",
"f joy2a 1 0x421b Joypad #2 Status A\n",
"f old_joy1 1 0x4016 Joypad #1 Old-Style Status\n",
"f old_joy2 1 0x4017 Joypad #2 Old-Style Status\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "6b96d6b7-5158-48c3-922e-0256eefcced8",
"metadata": {},
"source": [
"We added one flag for each of the joypad-related registers we found documented at the previous resource online with `f <flag name> <len> <address> <comment>`."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "4054c30c-26ee-4566-8f57-1f263dc8ca6c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x00004016 1 old_joy1\n",
"0x00004017 1 old_joy2\n",
"0x00004218 1 joy1b\n",
"0x00004219 1 joy1a\n",
"0x0000421a 1 joy2b\n",
"0x0000421b 1 joy2a\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"f~joy\")"
]
},
{
"cell_type": "markdown",
"id": "99fc7e9a-deb7-4f16-8548-3168fde977ef",
"metadata": {},
"source": [
"Now it knows...\n",
"\n",
"---\n",
"\n",
"So now if we're poking around at those memory addresses we will get annotations at those addresses:\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "5940dab2-0f39-4f62-aede-4059ba4e3124",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF comment\n",
"0x00004218 ffff ffff ffff ffff ffff ffff ffff ffff ................ ; joy1b ; joy1a ; joy2b ; joy2a\n",
"\n",
"\u001b[32m- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\u001b[0m\n",
" /j/jo/j/joy2a \n",
"\u001b[30m0x00004218\u001b[0m \u001b[7m\u001b[96mff\u001b[27m\u001b[0m\u001b[7m\u001b[36mff\u001b[27m \u001b[0m\u001b[7m\u001b[36mff\u001b[27m\u001b[0m\u001b[7m\u001b[30mff\u001b[27m \u001b[0mffff ffff ffff ffff ffff ffff\u001b[0m \u001b[7m\u001b[96m\u001b[27m.\u001b[0m\u001b[7m\u001b[36m\u001b[27m.\u001b[0m\u001b[7m\u001b[36m\u001b[27m.\u001b[0m\u001b[7m\u001b[30m\u001b[27m.\u001b[0m............\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r,\"\"\"\n",
"pxc 16 @ joy1b\n",
"pxa 16 @ joy1b\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "34a03c6c-7c66-4727-ab8c-57234fa8ac8a",
"metadata": {},
"source": [
"Here we've used the `p`rint 16 bytes of he`x`adecimal `@` address `joy1b` -- 'with comments' `c` then 'annotations' `a` commands. Of course the data `ffff` there is nonsensical because we're not looking at any memory mapped registers here; this is just a demonstration of the nice annotations of the `pxc` and `pxa` commands."
]
},
{
"cell_type": "markdown",
"id": "2e78ca7d-39c4-4fdb-97ee-532240a76337",
"metadata": {},
"source": [
"## RE-fwd 1: Joys\n",
"\n",
"Flags are great... you know what else having flags (no, not those flags -- see above) does in `r2`? --> It gives you cross-references (xrefs) in the disassembly!\n",
"\n",
"With xrefs we can answer the question: \"What is accessing the SNES joypad inputs?\" A simple way is to grep through the list of all the cross-references (xrefs) created by the `r2` analysis of the ROM with:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "646a5827-9e1d-4411-ba89-faec6b31b20c",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, 'ax~joy')"
]
},
{
"cell_type": "markdown",
"id": "52ebeec3-61f6-4a15-a66c-c0a64b8c3415",
"metadata": {},
"source": [
"OK so it's _supposed to_ give you xrefs in the disassembly. But the answer is _nothing_. In fact it doesn't have data xrefs at all (anywhere in the binary):"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "6358ed0c-7039-4d15-b883-9ff0c9bfbe2e",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, 'ax~DATA')"
]
},
{
"cell_type": "markdown",
"id": "dbb3aeb8-4e72-49b9-9610-c6c26cd4f79b",
"metadata": {},
"source": [
"Since `r2` has no idea about any data xrefs, its analysis of the disassembly did not annotate any.\n",
"\n",
"That is ok -- this happens when using `r2` on odd architectures... Oh well. We need to adapt: and what is an xref anyways? we don't need em / we can make our own.\n",
"\n",
"![what is a flag](what_is_a_flag.png)\n",
"\n",
"---\n",
"\n",
"We will 'make our own' by... grepping! It's a little better than literally `grep needle haystack.txt` (you'll see). Let's go!\n",
"\n",
"Conceptually we want to disassemble everything and grep for the addresses we're interested in as a poor replacement for our missing xrefs. Remember that 'grepping' in `r2` can be done with it's own in-built `~` grep command. For disassembling, there are _alot_ of ways that `r2` can disassemble -- see the `pd?` and `pi?` help output for the multitude of options.\n",
"\n",
"The third and last piece is disassembly _all the code_ so we can search through, _all the code_. We can't just `pD 0x400000` to disassemble all the bytes because not all of that is executable code. `r2` actually did some detection of the regions of the rom that are executable code and marked them with `fcn.xxxxxxxxxx` flags. There is a way to run commands repeatedly in `r2` using `@@`.\n",
"\n",
"We can apply all this. First let's check if this ROM uses the 'old' joy status registers (at `0x4016` and `0x4017`), by grepping:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "52c18c59-06e3-4ee6-86c0-ef61121039c4",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, 'aaa')"
]
},
{
"cell_type": "markdown",
"id": "d95df14f-fbb5-4644-b094-824470653add",
"metadata": {},
"source": [
"Here we ran analysis (defaults). We needed to run analysis steps to get a functions in the ROM recognized (and flagged with a `fcn.*` label)."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "24b0840f-bace-4d81-9cd4-dc89974133e3",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, 'pdf @@ fcn.* ~ 0x4016,0x4017')"
]
},
{
"cell_type": "markdown",
"id": "65aaa769-3f77-4823-ae63-08edfdb6580a",
"metadata": {},
"source": [
"Here we disassembled (`pdf`) every (`@@`) detected function `fcn.*` and grepped for either of the 'old' joy status registers (`0x4016,0x4017`). And there were none. That's great! What about the not-'old' ones?"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "5be64395-a3cf-4b44-b2d0-96d6f25195cc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"│ ╎╎╎╎╎╎╎ 0x000081e2 ad1942 lda 0x4219\n",
"│ ╎╎╎╎╎╎╎ 0x000081ec ad1942 lda 0x4219\n",
"│ ╎╎╎╎╎╎╎ 0x000081ff ad1842 lda 0x4218\n",
"\n"
]
}
],
"source": [
"# BUG: r2 does not substitue flags for the addresses used in non indexed loads (e.g. lda) ; whereas it does for indexed loads (e.g. ldx)\n",
"r2cmd(r, 'pdf @@ fcn.* ~ 0x4218,0x4219,0x421a,0x421b')"
]
},
{
"cell_type": "markdown",
"id": "e37e2652-8e2e-4532-a240-0ad3eeae6836",
"metadata": {},
"source": [
"Yes, both `joy1a` and `joy1b` are being used. But not any `joy2` uses.\n",
"\n",
"---\n",
"\n",
"Those addresses where `joy1a` and `joy1b` are being used show up pretty close together. Are they all in the same function?"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "963d62df-cb9b-4385-8633-5f5adf220ad3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x81d3\n",
"\n",
"0x81d3\n",
"\n",
"0x81d3\n",
"\n"
]
}
],
"source": [
"r2cmd(r,\"\"\"\n",
"s 0x81e2\n",
"sf.\n",
"?v $$\n",
"s 0x81ec\n",
"sf.\n",
"?v $$\n",
"s 0x81ff\n",
"sf.\n",
"?v $$\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "19e5a38b-c76e-4352-8d9c-0dedf48cd7a9",
"metadata": {},
"source": [
"Yes. What we did here is seek (`s`) to each of the addresses and then seek to the function entry point for each (`sf.`) and then printed the current seek offset (`?v $$`). In all cases the entrypoint was the same `0x81d3`. Same function.\n",
"\n",
"---\n",
"\n",
"Let's add some sugar to our diassembly in the form of comments to remind us when `joy1a` and `joy1b` are being accessed.\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "e3a2f12f-8142-4785-aacc-74e3c479813b",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r,\"\"\"\n",
"s 0x81d3\n",
"CC joy1a @@=`pid~0x4219[0] | sort | uniq`\n",
"CC joy1b @@=`pid~0x4218[0] | sort | uniq`\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "b94ea713-5725-4500-a02e-680b9d43e02c",
"metadata": {},
"source": [
"Here we added a `CC`omment for each line output from another command (`@@=`) where that command (`pid~0x4219[0] | sort | uniq` and `pid~0x4218[0] | sort | uniq`) grepped for the joypad register addresses. To add useful comments in the whole ROM we should have done something like pdf for each fcn label (like `pid @@ fcn.*` above). Since all the uses were in one function we just iterated over the output of `pid` of the function."
]
},
{
"cell_type": "markdown",
"id": "7144fc7c-ab3c-480a-b984-faf70576c5f5",
"metadata": {},
"source": [
"## RE-fwd 2: Joypad Reads\n",
"\n",
"At this point we have found the places where the code is accessing joypad registers and marked those code location with comments. Now we need to follow the data flow 'forward.' What does the code do with the joystick registers after accessing them?\n",
"\n",
"The reversing process of looking at the disassembly and starting to understand what it does, 'browsing', has a few ways to make it work in `r2`. You can use the built-in pager (`~..`) on the output of disassemble function (`pdf`). Or you can also use the `V` for visual mode -- see other tutorials for way more info on that.\n",
"\n",
"let's start by dumping the dissasembly of the whole function. It is alot to look at, pay attention to the `joyxx` comments mostly. (just scan over the next output)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "b219814f-fd12-4d01-a91a-2a10597932c6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CALL XREF from fcn.00008000 @ \u001b[93m0x81c5\u001b[93m\u001b[0m\n",
"\u001b[93m┌\u001b[0m 512: \u001b[93mfcn.000081d3\u001b[0m ();\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081d3 ad1012 \u001b[36mlda\u001b[96m \u001b[33m0x1210\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081d6 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000081d8 f001 \u001b[31mbeq\u001b[96m \u001b[33m0x0081db\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081da 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREFS from fcn.000081d3 @ \u001b[93m0x81d8\u001b[93m, 0x81e0\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m┌\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x000081db ad1242 \u001b[36mlda\u001b[96m \u001b[93m0x4212\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081de 2901 \u001b[34mand\u001b[96m #\u001b[33m0x01\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x000081e0 d0f9 \u001b[31mbne\u001b[96m \u001b[33m0x0081db\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081e2 ad1942 \u001b[36mlda\u001b[96m \u001b[93m0x4219\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081e5 2910 \u001b[34mand\u001b[96m #\u001b[33m0x10\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000081e7 d02a \u001b[31mbne\u001b[96m \u001b[33m0x008213\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081e9 ae1c12 \u001b[36mldx\u001b[96m \u001b[33m0x121c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081ec ad1942 \u001b[36mlda\u001b[96m \u001b[93m0x4219\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081ef 8d1c12 \u001b[36msta\u001b[96m \u001b[33m0x121c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081f2 8a \u001b[34mtxa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081f3 4d1c12 \u001b[34meor\u001b[96m \u001b[33m0x121c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081f6 2d1c12 \u001b[34mand\u001b[96m \u001b[33m0x121c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081f9 8d1412 \u001b[36msta\u001b[96m \u001b[33m0x1214\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081fc ae2012 \u001b[36mldx\u001b[96m \u001b[33m0x1220\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000081ff ad1842 \u001b[36mlda\u001b[96m \u001b[93m0x4218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008202 8d2012 \u001b[36msta\u001b[96m \u001b[33m0x1220\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008205 8a \u001b[34mtxa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008206 4d2012 \u001b[34meor\u001b[96m \u001b[33m0x1220\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008209 2d2012 \u001b[34mand\u001b[96m \u001b[33m0x1220\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000820c 8d1812 \u001b[36msta\u001b[96m \u001b[33m0x1218\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000820f 4c1782 \u001b[33mjmp 0x8217\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x81e7\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x00008213 4cd882 \u001b[33mjmp 0x82d8\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x820f\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x00008217 ad0012 \u001b[36mlda\u001b[96m \u001b[33m0x1200\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000821a 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000821c f004 \u001b[31mbeq\u001b[96m \u001b[33m0x008222\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000821e 4c4882 \u001b[33mjmp 0x8248\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x821c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x00008222 ad1812 \u001b[36mlda\u001b[96m \u001b[33m0x1218\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008225 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008227 f004 \u001b[31mbeq\u001b[96m \u001b[33m0x00822d\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008229 4c4482 \u001b[33mjmp 0x8244\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8227\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x0000822d ad1412 \u001b[36mlda\u001b[96m \u001b[33m0x1214\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008230 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008231 4940 \u001b[34meor\u001b[96m #\u001b[33m0x40\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008233 f008 \u001b[31mbeq\u001b[96m \u001b[33m0x00823d\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008235 ad1412 \u001b[36mlda\u001b[96m \u001b[33m0x1214\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008238 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000823a d008 \u001b[31mbne\u001b[96m \u001b[33m0x008244\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000823c 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8233\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x0000823d 8e0012 \u001b[36mstx\u001b[96m \u001b[33m0x1200\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x00008240 4c5381 \u001b[33mjmp 0x8153\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREFS from fcn.000081d3 @ \u001b[93m0x8229\u001b[93m, 0x823a\u001b[93m, 0x825a\u001b[93m, 0x828b\u001b[93m, 0x82b9\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m┌\u001b[0m\u001b[31m└\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[36m┌\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m┌\u001b[0m\u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x00008244 4c3281 \u001b[33mjmp 0x8132\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x821e\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x00008248 ad0412 \u001b[36mlda\u001b[96m \u001b[33m0x1204\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000824b 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000824d f004 \u001b[31mbeq\u001b[96m \u001b[33m0x008253\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000824f 4c7982 \u001b[33mjmp 0x8279\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x824d\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x00008253 ad1812 \u001b[36mlda\u001b[96m \u001b[33m0x1218\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008256 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008258 f004 \u001b[31mbeq\u001b[96m \u001b[33m0x00825e\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x0000825a 4c4482 \u001b[33mjmp 0x8244\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8258\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x0000825e ad1412 \u001b[36mlda\u001b[96m \u001b[33m0x1214\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008261 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008262 4984 \u001b[34meor\u001b[96m #\u001b[33m0x84\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008264 f008 \u001b[31mbeq\u001b[96m \u001b[33m0x00826e\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008266 ad1412 \u001b[36mlda\u001b[96m \u001b[33m0x1214\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008269 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000826b d008 \u001b[31mbne\u001b[96m \u001b[33m0x008275\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000826d 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8264\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x0000826e 8e0412 \u001b[36mstx\u001b[96m \u001b[33m0x1204\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x00008271 4c6e81 \u001b[33mjmp 0x816e\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x826b\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x00008275 4c3281 \u001b[33mjmp 0x8132\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x824f\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x00008279 ad0812 \u001b[36mlda\u001b[96m \u001b[33m0x1208\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000827c 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000827e f004 \u001b[31mbeq\u001b[96m \u001b[33m0x008284\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008280 4caa82 \u001b[33mjmp 0x82aa\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x827e\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x00008284 ad1812 \u001b[36mlda\u001b[96m \u001b[33m0x1218\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008287 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008289 f004 \u001b[31mbeq\u001b[96m \u001b[33m0x00828f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x0000828b 4c4482 \u001b[33mjmp 0x8244\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8289\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x0000828f ad1412 \u001b[36mlda\u001b[96m \u001b[33m0x1214\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008292 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008293 4928 \u001b[34meor\u001b[96m #\u001b[33m0x28\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008295 f008 \u001b[31mbeq\u001b[96m \u001b[33m0x00829f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008297 ad1412 \u001b[36mlda\u001b[96m \u001b[33m0x1214\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000829a 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000829c d008 \u001b[31mbne\u001b[96m \u001b[33m0x0082a6\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000829e 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8295\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x0000829f 8e0812 \u001b[36mstx\u001b[96m \u001b[33m0x1208\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x000082a2 4c8981 \u001b[33mjmp 0x8189\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m \u001b[36m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x829c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x000082a6 4c3281 \u001b[33mjmp 0x8132\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8280\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x000082aa ad0c12 \u001b[36mlda\u001b[96m \u001b[33m0x120c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000082ad 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082af f001 \u001b[31mbeq\u001b[96m \u001b[33m0x0082b2\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000082b1 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82af\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x000082b2 ad1412 \u001b[36mlda\u001b[96m \u001b[33m0x1214\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000082b5 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082b7 f004 \u001b[31mbeq\u001b[96m \u001b[33m0x0082bd\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x000082b9 4c4482 \u001b[33mjmp 0x8244\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82b7\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x000082bd ad1812 \u001b[36mlda\u001b[96m \u001b[33m0x1218\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000082c0 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000082c1 2920 \u001b[34mand\u001b[96m #\u001b[33m0x20\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082c3 d008 \u001b[31mbne\u001b[96m \u001b[33m0x0082cd\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000082c5 ad1812 \u001b[36mlda\u001b[96m \u001b[33m0x1218\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000082c8 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082ca d008 \u001b[31mbne\u001b[96m \u001b[33m0x0082d4\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x000082cc 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82c3\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m\u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x000082cd 8e0c12 \u001b[36mstx\u001b[96m \u001b[33m0x120c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x000082d0 4ca481 \u001b[33mjmp 0x81a4\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m│\u001b[0m \u001b[36m│\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82ca\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x000082d4 4c3281 \u001b[33mjmp 0x8132\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8213\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x000082d8 a20008 \u001b[36mldx\u001b[96m #\u001b[33m0x0800\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082db 8e1621 \u001b[36mstx\u001b[96m \u001b[33m0x2116\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082de a20000 \u001b[36mldx\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082e1 a00000 \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82f4\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082e4 bd4b88 \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082e7 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082e9 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082ec 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082ef c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082f0 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082f1 c00500 \u001b[36mcpy\u001b[96m #\u001b[33m0x0005\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082f4 d0ee \u001b[31mbne\u001b[96m \u001b[33m0x0082e4\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082f6 ae0012 \u001b[36mldx\u001b[96m \u001b[33m0x1200\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082f9 a00000 \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x830c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082fc bd4b88 \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x000082ff 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m 0x00008301 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008304 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008307 c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008308 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008309 c00600 \u001b[36mcpy\u001b[96m #\u001b[33m0x0006\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000830c d0ee \u001b[31mbne\u001b[96m \u001b[33m0x0082fc\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000830e ae0412 \u001b[36mldx\u001b[96m \u001b[33m0x1204\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008311 a00000 \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8324\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008314 bd4b88 \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008317 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008319 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000831c 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000831f c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008320 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008321 c00500 \u001b[36mcpy\u001b[96m #\u001b[33m0x0005\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008324 d0ee \u001b[31mbne\u001b[96m \u001b[33m0x008314\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008326 ae0812 \u001b[36mldx\u001b[96m \u001b[33m0x1208\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008329 a00000 \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x833c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000832c bd4b88 \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000832f 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008331 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008334 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008337 c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008338 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008339 c00500 \u001b[36mcpy\u001b[96m #\u001b[33m0x0005\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000833c d0ee \u001b[31mbne\u001b[96m \u001b[33m0x00832c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000833e ae0c12 \u001b[36mldx\u001b[96m \u001b[33m0x120c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008341 a00000 \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8354\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008344 bd4b88 \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008347 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008349 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000834c 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x0000834f c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008350 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008351 c00a00 \u001b[36mcpy\u001b[96m #\u001b[33m0x000a\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008354 d0ee \u001b[31mbne\u001b[96m \u001b[33m0x008344\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[36m╎\u001b[0m\u001b[36m╎\u001b[0m 0x00008356 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"..\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.00008000 @ \u001b[93m0x812f\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.00008000 @ \u001b[93m0x8376\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.00008000 @ \u001b[93m0x8389\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.00008000 @ \u001b[93m0x8399\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.00008000 @ \u001b[93m0x83b3\u001b[93m\u001b[0m\n",
" \u001b[31m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from syscall.0.2 @ \u001b[93m+0x62\u001b[93m\u001b[0m\n",
" \u001b[93m\u001b[93m; CALL XREF from fcn.00008000 @ \u001b[93m0x81c2\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[31m│\u001b[0m \u001b[93m\u001b[93m; CODE XREFS from fcn.000083d1 @ \u001b[93m0x83dc\u001b[93m, 0x83e9\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000083d1 @ \u001b[93m0x8415\u001b[93m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r,\"e asm.lines.width=16; pdf @ 0x81d3\")"
]
},
{
"cell_type": "markdown",
"id": "a8a4c133-6c3a-41af-9b06-2af3a6145cae",
"metadata": {},
"source": [
"So there's alot going on. The joypad reads are at the beginning of the function. There are three (really only two) places the joypads are read. It would be good to focus-in on those locations a bit.\n",
"\n",
"`r2` has a way to diassembly only the current basic block with `pdb`; we can get the list of basic blocks containing access to the joypads by re-purposing the search above that added the `joyxx` comments; this time we can print the current basic block start `$Fb`\n",
"\n",
"We can optimize the commands above that listed the three locations where `joy1a` or `joy1b` were acccessed. Since the built-in grep `~` actually has a sort `$` and also has multi-word match with `,`: `pid~0x4219[0] | sort | uniq` and `pid~0x4218[0] | sort | uniq` is equivalent to `pid~0x4219,0x4218$[0]`."
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "42463ed0-9739-497c-b4f2-ffe7686dc4b1",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x81e2\n",
"0x81e9\n",
"0x81e9\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"?v $Fb @@=`pid~0x4219,0x4218$[0]`\")"
]
},
{
"cell_type": "markdown",
"id": "c91080a8-2ebf-413e-ba6f-0638790e11ff",
"metadata": {},
"source": [
"So there are only two EBBs (extended basic blocks) that have accesses to the joypads"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "a3329600-c73a-4dc8-896e-0c821dc51c52",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, \"\"\"\n",
"f+ first_joypad_check @ 0x81e2\n",
"f+ second_joypad_check @ 0x81e9\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "708f25ec-8053-4863-a6ff-3cba7ae88ba2",
"metadata": {},
"source": [
"Let's look at the first ebb"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "c9fe6075-3206-4c9b-831f-0daa450edf85",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- first_joypad_check:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e2 ad1942 \u001b[36mlda\u001b[96m \u001b[93m0x4219\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e5 2910 \u001b[34mand\u001b[96m #\u001b[33m0x10\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000081e7 d02a \u001b[31mbne\u001b[96m \u001b[33m0x008213\u001b[0m\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, 'pdb @ 0x81e2')"
]
},
{
"cell_type": "markdown",
"id": "53768381-e231-4c70-9127-98f613965a89",
"metadata": {},
"source": [
"This ebb reads `joy1a` and then tests if a single bit (`0x10` aka 2^9 aka bit 8 aka you get it...) is set then jumps away if it is set. bit 8 in that register is the *start* button (check out https://en.wikibooks.org/wiki/Super_NES_Programming/Joypad_Input). So the `bne` will jump *if* the start button was pressed (remember equality cpu flags are set when prev results is zero). So let's note that and then look at the same ebb again"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "10b1273c-b8f8-4c7b-9805-c5b8c0198981",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- first_joypad_check:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e2 ad1942 \u001b[36mlda\u001b[96m \u001b[93m0x4219\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e5 2910 \u001b[34mand\u001b[96m #\u001b[33m0x10\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000081e7 d02a \u001b[31mbne\u001b[96m \u001b[93m0x008213\u001b[0m\u001b[0m\u001b[0m \u001b[33m; press start to jump\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"s 0x81e7\n",
"CC press start to jump\n",
"f+ start_is_pressed @ $Fj\n",
"f+ start_not_pressed @ $Ff\n",
"\"\"\")\n",
"r2cmd(r, \"pdb @ 0x81e2\")"
]
},
{
"cell_type": "markdown",
"id": "8d6942c1-1f7d-492b-96f3-036486821aaa",
"metadata": {},
"source": [
"Here we added a `CC`omment at the jump and also labelled the jump target (`$Fj`) address and false (`$Ff`) address by adding `f`lags.\n"
]
},
{
"cell_type": "markdown",
"id": "96b1d50f-21e6-4193-a616-f89466d422b7",
"metadata": {},
"source": [
"## RE-fwd 3: The Magic Buttons\n",
"\n",
"The next obvious question is: what happens if you don't press start? `r2` let's you query the destinations of ebb with `$Fj` for the destination if the ebb branch is taken or `$Ff` if it is not.\n",
"\n",
"So, what address does execution continue to if start is not pressed?"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "4b87430e-56d7-4367-aba2-78ddf5e9e3a9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x81e9\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"?v $Ff @ 0x81e2\")"
]
},
{
"cell_type": "markdown",
"id": "3ac8cfc7-98f8-4ba1-8957-380bae5acf25",
"metadata": {},
"source": [
"Aha that's the _other_ joypad check location."
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "706e2c0b-831e-41cb-a799-8bbfe9b67e97",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- second_joypad_check:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e9 ae1c12 \u001b[36mldx\u001b[96m \u001b[33m0x121c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ec ad1942 \u001b[36mlda\u001b[96m \u001b[93m0x4219\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ef 8d1c12 \u001b[36msta\u001b[96m \u001b[33m0x121c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f2 8a \u001b[34mtxa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f3 4d1c12 \u001b[34meor\u001b[96m \u001b[33m0x121c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f6 2d1c12 \u001b[34mand\u001b[96m \u001b[33m0x121c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f9 8d1412 \u001b[36msta\u001b[96m \u001b[33m0x1214\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081fc ae2012 \u001b[36mldx\u001b[96m \u001b[33m0x1220\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ff ad1842 \u001b[36mlda\u001b[96m \u001b[93m0x4218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008202 8d2012 \u001b[36msta\u001b[96m \u001b[33m0x1220\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008205 8a \u001b[34mtxa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008206 4d2012 \u001b[34meor\u001b[96m \u001b[33m0x1220\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008209 2d2012 \u001b[34mand\u001b[96m \u001b[33m0x1220\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000820c 8d1812 \u001b[36msta\u001b[96m \u001b[33m0x1218\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000820f 4c1782 \u001b[33mjmp 0x8217\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, 'pdb @ 0x81e9')"
]
},
{
"cell_type": "markdown",
"id": "b262a27a-eb84-480d-b2b7-ce59b8d24300",
"metadata": {},
"source": [
"We can see that both the `joy1a` value and a derivative value (via exclusive + and) are stored into locations `0x121c` and `0x1214`, respectively.\n",
"\n",
"Similarly, `joy1b` gets stored into `0x1220` and `0x1218`\n",
"\n",
"Let's add flags for those 4 locations and also comments at all accesses to them like we did for `joy1a` and `joy1b` previously.\n",
"\n",
"Then look at the same ebb again:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "b147231d-3098-4db3-a5f2-7ad4d46e460c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- second_joypad_check:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e9 ae1c12 \u001b[36mldx\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ec ad1942 \u001b[36mlda\u001b[96m \u001b[93m0x4219\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ef 8d1c12 \u001b[36msta\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f2 8a \u001b[34mtxa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f3 4d1c12 \u001b[34meor\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f6 2d1c12 \u001b[34mand\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f9 8d1412 \u001b[36msta\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081fc ae2012 \u001b[36mldx\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ff ad1842 \u001b[36mlda\u001b[96m \u001b[93m0x4218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008202 8d2012 \u001b[36msta\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008205 8a \u001b[34mtxa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008206 4d2012 \u001b[34meor\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008209 2d2012 \u001b[34mand\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000820c 8d1812 \u001b[36msta\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000820f 4c1782 \u001b[33mjmp 0x8217\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"f+ joy1a_cache1 @ 0x121c\n",
"f+ joy1a_cache2 @ 0x1214\n",
"f+ joy1b_cache1 @ 0x1220\n",
"f+ joy1b_cache2 @ 0x1218\n",
"\"\"\")\n",
"r2cmd(r,\"\"\"\n",
"e asm.lines=false\n",
"CCu joy1a_cache1 @@=`pdf @@ fcn.* ~0x121c[0] | sort -u`\n",
"CCu joy1a_cache2 @@=`pdf @@ fcn.* ~0x1214[0] | sort -u`\n",
"CCu joy1b_cache1 @@=`pdf @@ fcn.* ~0x1220[0] | sort -u`\n",
"CCu joy1b_cache2 @@=`pdf @@ fcn.* ~0x1218[0] | sort -u`\n",
"e asm.lines=true\n",
"\"\"\")\n",
"\n",
"r2cmd(r, 'pdb @ 0x81e9')"
]
},
{
"cell_type": "markdown",
"id": "e2a00f5f-2b1b-4af1-bf91-b8890073d3ab",
"metadata": {},
"source": [
"We did some iterating over all the output of a command using `@@=` above; and first we configured the dissembly printer to no include the jump lines with `e asm.lines = false` which then lets us grep for the address we're interested in by filtering for column 0 `~...[0]`. Then to remove duplicates we use `sort -u` through a plain-old pipe `|`\n",
"\n",
"Let's look at all the instructions referencing the `*_cache*` globals anywhere in the ROM. We'll `pdf` each function and grep for the comments we just added."
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "04a4bf3b-caac-4b60-be31-5e3118c4f6ae",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x00008044 9c1c12 stz 0x121c ; joy1a_cache1\n",
"0x000081e9 ae1c12 ldx 0x121c ; joy1a_cache1\n",
"0x000081ef 8d1c12 sta 0x121c ; joy1a_cache1\n",
"0x000081f3 4d1c12 eor 0x121c ; joy1a_cache1\n",
"0x000081f6 2d1c12 and 0x121c ; joy1a_cache1\n",
"\n",
"0x00008047 9c1412 stz 0x1214 ; joy1a_cache2\n",
"0x000081f9 8d1412 sta 0x1214 ; joy1a_cache2\n",
"0x0000822d ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x00008235 ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x0000825e ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x00008266 ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x0000828f ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x00008297 ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x000082b2 ad1412 lda 0x1214 ; joy1a_cache2\n",
"\n",
"0x0000804a 9c2012 stz 0x1220 ; joy1b_cache1\n",
"0x000081fc ae2012 ldx 0x1220 ; joy1b_cache1\n",
"0x00008202 8d2012 sta 0x1220 ; joy1b_cache1\n",
"0x00008206 4d2012 eor 0x1220 ; joy1b_cache1\n",
"0x00008209 2d2012 and 0x1220 ; joy1b_cache1\n",
"\n",
"0x0000804d 9c1812 stz 0x1218 ; joy1b_cache2\n",
"0x00008360 c230 rep #0x30 ; joy1b_cache2\n",
"0x0000820c 8d1812 sta 0x1218 ; joy1b_cache2\n",
"0x00008222 ad1812 lda 0x1218 ; joy1b_cache2\n",
"0x00008253 ad1812 lda 0x1218 ; joy1b_cache2\n",
"0x00008284 ad1812 lda 0x1218 ; joy1b_cache2\n",
"0x000082bd ad1812 lda 0x1218 ; joy1b_cache2\n",
"0x000082c5 ad1812 lda 0x1218 ; joy1b_cache2\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"e asm.lines = false\n",
"pdf @@ fcn.* ~joy1a_cache1\n",
"pdf @@ fcn.* ~joy1a_cache2\n",
"pdf @@ fcn.* ~joy1b_cache1\n",
"pdf @@ fcn.* ~joy1b_cache2\n",
"e asm.lines=true\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "fb58c241-8e37-422b-87ba-00aa85193aa4",
"metadata": {},
"source": [
"Looking at the `_cache1`s first: the `joy1a_cache1` and `joy1b_cache1` global variables have only one read location each (the `ldx` instruction locations) at 0x81e9 and 0x81fc, respectively. And those are in the same EBB we've already looked at `second_joypad_check`:"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "72ff71e0-12af-4788-b85f-30dbe2763d45",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- second_joypad_check:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e9 ae1c12 \u001b[36mldx\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ec ad1942 \u001b[36mlda\u001b[96m \u001b[93m0x4219\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ef 8d1c12 \u001b[36msta\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f2 8a \u001b[34mtxa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f3 4d1c12 \u001b[34meor\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f6 2d1c12 \u001b[34mand\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f9 8d1412 \u001b[36msta\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081fc ae2012 \u001b[36mldx\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ff ad1842 \u001b[36mlda\u001b[96m \u001b[93m0x4218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008202 8d2012 \u001b[36msta\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008205 8a \u001b[34mtxa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008206 4d2012 \u001b[34meor\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008209 2d2012 \u001b[34mand\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000820c 8d1812 \u001b[36msta\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000820f 4c1782 \u001b[33mjmp 0x8217\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"pdb @ second_joypad_check\")"
]
},
{
"cell_type": "markdown",
"id": "d99823c5-d728-4bea-a607-20f1282bb99b",
"metadata": {},
"source": [
"The `_cache1`s (both) are used to store the previous joypad state and detect button pushes by xor'ing the previous state with the current state and then and'ing with the current state. The newly pushed buttons state is then stored into the `_cache2` globals which are read in several other places:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "0ca32c88-7304-4b1e-8067-de7146b9dd47",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x00008047 9c1412 stz 0x1214 ; joy1a_cache2\n",
"0x000081f9 8d1412 sta 0x1214 ; joy1a_cache2\n",
"0x0000822d ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x00008235 ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x0000825e ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x00008266 ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x0000828f ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x00008297 ad1412 lda 0x1214 ; joy1a_cache2\n",
"0x000082b2 ad1412 lda 0x1214 ; joy1a_cache2\n",
"\n",
"0x0000804d 9c1812 stz 0x1218 ; joy1b_cache2\n",
"0x00008360 c230 rep #0x30 ; joy1b_cache2\n",
"0x0000820c 8d1812 sta 0x1218 ; joy1b_cache2\n",
"0x00008222 ad1812 lda 0x1218 ; joy1b_cache2\n",
"0x00008253 ad1812 lda 0x1218 ; joy1b_cache2\n",
"0x00008284 ad1812 lda 0x1218 ; joy1b_cache2\n",
"0x000082bd ad1812 lda 0x1218 ; joy1b_cache2\n",
"0x000082c5 ad1812 lda 0x1218 ; joy1b_cache2\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"e asm.lines = false\n",
"pdf @@ fcn.* ~joy1a_cache2\n",
"pdf @@ fcn.* ~joy1b_cache2\n",
"e asm.lines=true\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "a1649b24-56de-4ebd-bea6-5041abcbbde9",
"metadata": {},
"source": [
"The `stz` instructions storing to the `_cache2` globals happen very near each other... let's look at the ebb of the first:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "ba37d6e5-124b-4a59-8616-7a58bfaf91cb",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" \u001b[93m;-- section.ROM_00:\u001b[0m\n",
" \u001b[93m;-- bp:\u001b[0m\n",
" \u001b[93m;-- sp:\u001b[0m\n",
" \u001b[93m\u001b[93m; CODE XREF from start_is_pressed @ \u001b[93m+0x14a\u001b[93m\u001b[0m\n",
"\u001b[93m┌\u001b[0m 406: \u001b[93mfcn.00008000\u001b[0m ();\n",
"\u001b[93m│\u001b[0m 0x00008000 78 \u001b[31msei\u001b[0m\u001b[0m\u001b[0m \u001b[33m; [00] -r-x section size 32768 named ROM_00\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008001 4b \u001b[36mphk\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008002 ab \u001b[36mplb\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008003 18 \u001b[31mclc\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008004 fb \u001b[31mxce\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008005 202c85 \u001b[40m\u001b[33mjsr fcn.0000852c\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008008 c230 \u001b[31mrep\u001b[96m #\u001b[33m0x30\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000800a e220 \u001b[31msep\u001b[96m #\u001b[33m0x20\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000800c a900 \u001b[36mlda\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000800e 5b \u001b[34mtad\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000800f a908 \u001b[36mlda\u001b[96m #\u001b[33m0x08\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008011 8d0721 \u001b[36msta\u001b[96m \u001b[33m0x2107\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008014 a90c \u001b[36mlda\u001b[96m #\u001b[33m0x0c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008016 8d0821 \u001b[36msta\u001b[96m \u001b[33m0x2108\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008019 a922 \u001b[36mlda\u001b[96m #\u001b[33m0x22\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000801b 8d0b21 \u001b[36msta\u001b[96m \u001b[33m0x210b\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000801e a900 \u001b[36mlda\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008020 8d0521 \u001b[36msta\u001b[96m \u001b[33m0x2105\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008023 a903 \u001b[36mlda\u001b[96m #\u001b[33m0x03\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008025 8d2c21 \u001b[36msta\u001b[96m \u001b[33m0x212c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008028 a901 \u001b[36mlda\u001b[96m #\u001b[33m0x01\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000802a ~ 8d0042 \u001b[36msta\u001b[96m \u001b[93m0x4200\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- syscall.0:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000802b 0042 \u001b[31mbrk\u001b[96m \u001b[33m0x42\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000802d a900 \u001b[36mlda\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000802f 8d2121 \u001b[36msta\u001b[96m \u001b[33m0x2121\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008032 a20000 \u001b[36mldx\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008035 9c0012 \u001b[36mstz\u001b[96m \u001b[33m0x1200\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008038 9c0412 \u001b[36mstz\u001b[96m \u001b[33m0x1204\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000803b 9c0812 \u001b[36mstz\u001b[96m \u001b[33m0x1208\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000803e 9c0c12 \u001b[36mstz\u001b[96m \u001b[33m0x120c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008041 9c1012 \u001b[36mstz\u001b[96m \u001b[33m0x1210\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008044 9c1c12 \u001b[36mstz\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008047 9c1412 \u001b[36mstz\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000804a 9c2012 \u001b[36mstz\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000804d 9c1812 \u001b[36mstz\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"pdb @ 0x8047\")"
]
},
{
"cell_type": "markdown",
"id": "e74a0806-20df-49d8-bc01-1d806f5591f5",
"metadata": {},
"source": [
"They are all there, in the entrypoint function; where the globals are all getting initialized so there's no relevance to the crackme solution. So the only writes to these globals are 1) at init and b) at the joypad check locations we looked at previously. We can safely assume that the crackme inputs are checked at the _read_ (i.e. `lda` locations).\n",
"\n",
"Let's look at the _read_ locations for the `_cache2` globals. Those were all `lda` instructions so we can grep that out. We'll use the same techniqe as before; print disassembly (`pdf`) of each function `@@ fcn.*` and grep for the cache2 globals (`~joy1a_cache2,joy1b_cache2`) and look only at the lda instructions (`|grep -w lda` because we can't do a second builtin r2 grep)"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "cb9b05e0-533f-448e-9359-25ae80ac3ab6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x8000\n",
"0x0\n",
"0x0\n",
"0x0\n",
"\n"
]
}
],
"source": [
"# BUG: ?v $Fb @@=`` doesn't work here but does on `pid~0x4219,0x4218[0] | sort -u | awk {'print $1'}` above\n",
"r2cmd(r, \"\"\"\n",
"e asm.lines = false\n",
"?v $Fb @@=`pdf @@ fcn.* ~joy1a_cache2,joy1b_cache|grep -w lda|awk '{ print $1 }'|sort -u`\n",
"e asm.lines=true\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "899dd0a3-6cb1-424f-aeb0-ee9263f80424",
"metadata": {},
"source": [
"Something is wrong here... only 0x8000 (the entrypoint) and 0x0 (not an actual address for SNES) reported. The command above was supposed to run `?v` for each location grepped out. The list to process looks like this:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "e04f42f4-5373-4d83-900f-2ae99f459887",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x00008222\n",
"0x0000822d\n",
"0x00008235\n",
"0x00008253\n",
"0x0000825e\n",
"0x00008266\n",
"0x00008284\n",
"0x0000828f\n",
"0x00008297\n",
"0x000082b2\n",
"0x000082bd\n",
"0x000082c5\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"e asm.lines = false\n",
"pdf @@ fcn.* ~joy1a_cache2,joy1b_cache|grep -w lda|awk '{ print $1 }'|sort -u\n",
"e asm.lines=true\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "99783ee0-35bd-4a54-b60e-e8835a4bf46e",
"metadata": {},
"source": [
"Which looks fine; but sticking the same into a `@@=` doesn't work. This happens sometimes, I don't understand why `?v $Fb @@=` works on the subshell `pid~0x4219,0x4218[0] | sort -u | awk {'print $1'}` but not on this one...\n",
"\n",
"When this happens there are workarounds though; one is to redirect the output of the command you want to subshell into a file, then read it back as r2 commands with `@@.`:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "5f0794a3-b22f-4a69-b18d-fdcff156a025",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x8222\n",
"0x822d\n",
"0x8235\n",
"0x8253\n",
"0x825e\n",
"0x8266\n",
"0x8284\n",
"0x828f\n",
"0x8297\n",
"0x82b2\n",
"0x82bd\n",
"0x82c5\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"e asm.lines = false\n",
"pdf @@ fcn.* ~joy1a_cache2,joy1b_cache|grep -w lda|awk '{ print $1 }'|sort -u > cache2s_read_addr.txt\n",
"e asm.lines=true\n",
"?v $Fb @@.cache2s_read_addr.txt | sort -u\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "9a3357f0-0063-46da-ab33-a06e7a21420c",
"metadata": {},
"source": [
"Which works and shows us there are plenty of ebbs where these read accesses are happening. What about functions? "
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "d25d0f8f-afe2-4938-a89b-a2ab6c28f1c0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x81d3\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"?v $FB@@.cache2s_read_addr.txt |sort -u\")"
]
},
{
"cell_type": "markdown",
"id": "8f96dfaf-2834-4ae5-a010-5b8eb7929ac4",
"metadata": {},
"source": [
"all happening in the same function, which is great. But it's in the same function as we've already been looking at (the big one above) which is bad because it was too big and complex to understand right away. Oh well, let's get into it.\n",
"\n",
"Let's look at the disassembly of just those EBBs that are involved:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "143f9275-b646-484a-8006-8c76b4dec67e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x821c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008222\u001b[0m \u001b[96mad\u001b[96m18\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008225\u001b[0m \u001b[96m29\u001b[34mff\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x00008227\u001b[0m \u001b[96mf0\u001b[96m04\u001b[0m \u001b[31mbeq\u001b[96m \u001b[33m0x00822d\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8227\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000822d\u001b[0m \u001b[96mad\u001b[96m14\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008230\u001b[0m \u001b[96maa\u001b[0m \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008231\u001b[0m \u001b[96m49\u001b[96m40\u001b[0m \u001b[34meor\u001b[96m #\u001b[33m0x40\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x00008233\u001b[0m \u001b[96mf0\u001b[96m08\u001b[0m \u001b[31mbeq\u001b[96m \u001b[33m0x00823d\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008235\u001b[0m \u001b[96mad\u001b[96m14\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008238\u001b[0m \u001b[96m29\u001b[34mff\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x0000823a\u001b[0m \u001b[96md0\u001b[96m08\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x008244\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x824d\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008253\u001b[0m \u001b[96mad\u001b[96m18\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008256\u001b[0m \u001b[96m29\u001b[34mff\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x00008258\u001b[0m \u001b[96mf0\u001b[96m04\u001b[0m \u001b[31mbeq\u001b[96m \u001b[33m0x00825e\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8258\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000825e\u001b[0m \u001b[96mad\u001b[96m14\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008261\u001b[0m \u001b[96maa\u001b[0m \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008262\u001b[0m \u001b[96m49\u001b[96m84\u001b[0m \u001b[34meor\u001b[96m #\u001b[33m0x84\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x00008264\u001b[0m \u001b[96mf0\u001b[96m08\u001b[0m \u001b[31mbeq\u001b[96m \u001b[33m0x00826e\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008266\u001b[0m \u001b[96mad\u001b[96m14\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008269\u001b[0m \u001b[96m29\u001b[34mff\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x0000826b\u001b[0m \u001b[96md0\u001b[96m08\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x008275\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x827e\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008284\u001b[0m \u001b[96mad\u001b[96m18\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008287\u001b[0m \u001b[96m29\u001b[34mff\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x00008289\u001b[0m \u001b[96mf0\u001b[96m04\u001b[0m \u001b[31mbeq\u001b[96m \u001b[33m0x00828f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8289\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000828f\u001b[0m \u001b[96mad\u001b[96m14\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008292\u001b[0m \u001b[96maa\u001b[0m \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008293\u001b[0m \u001b[96m49\u001b[96m28\u001b[0m \u001b[34meor\u001b[96m #\u001b[33m0x28\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x00008295\u001b[0m \u001b[96mf0\u001b[96m08\u001b[0m \u001b[31mbeq\u001b[96m \u001b[33m0x00829f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008297\u001b[0m \u001b[96mad\u001b[96m14\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000829a\u001b[0m \u001b[96m29\u001b[34mff\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x0000829c\u001b[0m \u001b[96md0\u001b[96m08\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x0082a6\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82af\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082b2\u001b[0m \u001b[96mad\u001b[96m14\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082b5\u001b[0m \u001b[96m29\u001b[34mff\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x000082b7\u001b[0m \u001b[96mf0\u001b[96m04\u001b[0m \u001b[31mbeq\u001b[96m \u001b[33m0x0082bd\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82b7\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082bd\u001b[0m \u001b[96mad\u001b[96m18\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082c0\u001b[0m \u001b[96maa\u001b[0m \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082c1\u001b[0m \u001b[96m29\u001b[96m20\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x20\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x000082c3\u001b[0m \u001b[96md0\u001b[96m08\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x0082cd\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082c5\u001b[0m \u001b[96mad\u001b[96m18\u001b[96m12\u001b[0m \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082c8\u001b[0m \u001b[96m29\u001b[34mff\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x000082ca\u001b[0m \u001b[96md0\u001b[96m08\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x0082d4\u001b[0m\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"?v $Fb @@.cache2s_read_addr.txt | sort -u > cache2s_read_bbs.txt\n",
"pdb @@.cache2s_read_bbs.txt\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "9bd1f144-b439-41fe-b844-50c46b1f3137",
"metadata": {},
"source": [
"We can 'categorize' each of these into 1) tests that jump if a button is pressed, 2) tests that jump if no button is pressed and 3) 'other tests'. The latter uses `tax` and `eor` after the `lda` of the `_cache2` variable. It's not clear what those are doing yet.\n",
"\n",
"Let's label all those with flags and comments and then diassemble the same ebbs again:"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "281607e5-e60f-4086-828f-f0330dd770fe",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x821c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008222 ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008225 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008227 f004 \u001b[31mbeq\u001b[96m no_button_pressed.14\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if no button pressed\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.14:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8227\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000822d ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008230 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008231 4940 \u001b[34meor\u001b[96m #\u001b[33m0x40\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_4:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008233 f008 \u001b[31mbeq\u001b[96m \u001b[33m0x00823d\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008235 ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008238 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000823a d008 \u001b[31mbne\u001b[96m any_button_pressed.6\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if button pressed\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x824d\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008253 ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008256 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008258 f004 \u001b[31mbeq\u001b[96m no_button_pressed.12\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if no button pressed\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.12:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8258\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000825e ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008261 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008262 4984 \u001b[34meor\u001b[96m #\u001b[33m0x84\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_3:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008264 f008 \u001b[31mbeq\u001b[96m \u001b[33m0x00826e\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008266 ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008269 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000826b d008 \u001b[31mbne\u001b[96m any_button_pressed.4\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if button pressed\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x827e\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008284 ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008287 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008289 f004 \u001b[31mbeq\u001b[96m no_button_pressed.10\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if no button pressed\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.10:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8289\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000828f ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008292 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008293 4928 \u001b[34meor\u001b[96m #\u001b[33m0x28\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_2:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008295 f008 \u001b[31mbeq\u001b[96m \u001b[33m0x00829f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008297 ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000829a 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x0000829c d008 \u001b[31mbne\u001b[96m any_button_pressed.2\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if button pressed\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82af\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082b2 ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082b5 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082b7 f004 \u001b[31mbeq\u001b[96m no_button_pressed.8\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if no button pressed\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.8:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82b7\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082bd ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c0 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c1 2920 \u001b[34mand\u001b[96m #\u001b[33m0x20\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_1:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082c3 d008 \u001b[31mbne\u001b[96m \u001b[33m0x0082cd\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c5 ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c8 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082ca d008 \u001b[31mbne\u001b[96m any_button_pressed.0\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if button pressed\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r,\"\"\"\n",
"s 0x82ca\n",
"CCu jump if button pressed\n",
"fe any_button_pressed @ $Fj\n",
"fe no_button_pressed @ $Ff\n",
"s 0x829c\n",
"CCu jump if button pressed\n",
"fe any_button_pressed @ $Fj\n",
"fe no_button_pressed @ $Ff\n",
"s 0x826b\n",
"CCu jump if button pressed\n",
"fe any_button_pressed @ $Fj\n",
"fe no_button_pressed @ $Ff\n",
"s 0x823a\n",
"CCu jump if button pressed\n",
"fe any_button_pressed @ $Fj\n",
"fe no_button_pressed @ $Ff\n",
"\"\"\")\n",
"\n",
"r2cmd(r,\"\"\"\n",
"s 0x82b7\n",
"CCu jump if no button pressed\n",
"fe no_button_pressed @ $Fj\n",
"fe any_button_pressed @ $Ff\n",
"s 0x8289\n",
"CCu jump if no button pressed\n",
"fe no_button_pressed @ $Fj\n",
"fe any_button_pressed @ $Ff\n",
"s 0x8258\n",
"CCu jump if no button pressed\n",
"fe no_button_pressed @ $Fj\n",
"fe any_button_pressed @ $Ff\n",
"s 0x8227\n",
"CCu jump if no button pressed\n",
"fe no_button_pressed @ $Fj\n",
"fe any_button_pressed @ $Ff\n",
"\"\"\")\n",
"\n",
"r2cmd(r,\"\"\"\n",
"f+ jump_if_something_1 @ 0x82c3\n",
"f+ jump_if_something_2 @ 0x8295\n",
"f+ jump_if_something_3 @ 0x8264\n",
"f+ jump_if_something_4 @ 0x8233\n",
"\"\"\")\n",
"r2cmd(r, \"pdb @@.cache2s_read_bbs.txt\")"
]
},
{
"cell_type": "markdown",
"id": "7c693416-d1eb-41c6-83f6-42f0f80bb014",
"metadata": {},
"source": [
"That looks like they are all labelled pretty well except for the 'other' category. Let's look at the 'other' category of branches:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "c6424409-adcf-4e96-91c0-9a02cb6c9e9c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.14:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8227\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000822d ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008230 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008231 4940 \u001b[34meor\u001b[96m #\u001b[33m0x40\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_4:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008233 f008 \u001b[31mbeq\u001b[96m \u001b[33m0x00823d\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.12:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8258\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000825e ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008261 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008262 4984 \u001b[34meor\u001b[96m #\u001b[33m0x84\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_3:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008264 f008 \u001b[31mbeq\u001b[96m \u001b[33m0x00826e\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.10:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8289\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000828f ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008292 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008293 4928 \u001b[34meor\u001b[96m #\u001b[33m0x28\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_2:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008295 f008 \u001b[31mbeq\u001b[96m \u001b[33m0x00829f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.8:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82b7\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082bd ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c0 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c1 2920 \u001b[34mand\u001b[96m #\u001b[33m0x20\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_1:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082c3 d008 \u001b[31mbne\u001b[96m \u001b[33m0x0082cd\u001b[0m\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"pdb @@ jump_if_something*\")"
]
},
{
"cell_type": "markdown",
"id": "328123b2-aba0-4a51-8243-2769586f0da7",
"metadata": {},
"source": [
"In all cases the `_cache2` variable (which contains newly-pressed buttons) is read, then a `tax` copies the value from the accumulator register (`A`) to the index register (`X`), then either a bitwise exclusive-or (`eor`) or a bitwise and (`and`) is executed.\n",
"\n",
"To decode what buttons are being tested we need to recall the button map for the `joy1a` and `joy1b` registers:\n",
"\n",
"| bit:|8|7|6|5|4|3|2|1|\n",
"|-|-|-|-|-|-|-|-|-|\n",
"|joy1a|B|Y|select|start|up|down|left|right|\n",
"|joy1b|A|X|L|R|||||\n",
"\n",
"1. The first test (0x8233) is `eor`ing `joy1a` with `0x40` and jumps if zero. i.e. jumps if only **Y is pressed**\n",
"2. @ 0x8264 it is `eor`ing `joy1a` with `0x84` and jumps if zero. i.e. jumps if **B+down is pressed**\n",
"3. @ 0x8295 it is `eor`ing `joy1a` with `0x28` and jumps if zero. i.e. jumps if **select+up is pressed**\n",
"4. @ 0x82c3 it is `and`ing `joy1b` with `0x20` are jumps if not zero. i.e. jumps if at least **L is pressed**"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "987f1ec1-b66e-42a5-a8fd-6cd14aca80a5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.14:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8227\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000822d ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008230 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008231 4940 \u001b[34meor\u001b[96m #\u001b[33m0x40\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_4:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008233 f008 \u001b[31mbeq\u001b[96m y_is_pressed.16\u001b[0m\u001b[0m\u001b[0m \u001b[33m; press only Y to jump\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.12:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8258\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000825e ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008261 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008262 4984 \u001b[34meor\u001b[96m #\u001b[33m0x84\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_3:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008264 f008 \u001b[31mbeq\u001b[96m b_n_down_is_pressed.18\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.10:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8289\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000828f ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008292 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008293 4928 \u001b[34meor\u001b[96m #\u001b[33m0x28\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_2:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x00008295 f008 \u001b[31mbeq\u001b[96m sel_n_up_is_pressed.20\u001b[0m\u001b[0m\u001b[0m \u001b[33m; press only sel+up to jump\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.8:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82b7\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082bd ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c0 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c1 2920 \u001b[34mand\u001b[96m #\u001b[33m0x20\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_1:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082c3 d008 \u001b[31mbne\u001b[96m l_is_pressed.22\u001b[0m\u001b[0m\u001b[0m \u001b[33m; press L to jump\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r,\"\"\"\n",
"s 0x8233\n",
"CCu press only Y to jump\n",
"fe y_is_pressed @ $Fj\n",
"fe y_not_pressed @ $Ff\n",
"s 0x8264\n",
"CCU press only B+down to jump\n",
"fe b_n_down_is_pressed @ $Fj\n",
"fe b_n_down_not_pressed @ $Ff\n",
"s 0x8295\n",
"CCu press only sel+up to jump\n",
"fe sel_n_up_is_pressed @ $Fj\n",
"fe sel_n_up_not_pressed @ $Ff\n",
"s 0x82c3\n",
"CCu press L to jump\n",
"fe l_is_pressed @ $Fj\n",
"fe l_not_pressed @ $Ff\n",
"\"\"\")\n",
"r2cmd(r, \"pdb @@ jump_if_something*\")"
]
},
{
"cell_type": "markdown",
"id": "3ba98c1c-989d-4524-8df8-2173a8efac0d",
"metadata": {},
"source": [
"## RE-fwd 4: Sequence State Saving\n",
"\n",
"Now that we've followed and marked all the joypad reads and value checks: the disassembly of the function (the big one) starts to make a little more sense. Let's disassemble from the first joypad check onwards. You can see lots of the comments and address flags highlighting the logic of the flow. There are some unknown use of globals (so far) and eventually the disassembly gets inscrutable again... (just scan over the next output)(just scan over the next output)"
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "8254d2cb-349d-48d0-94d4-dec63e779d95",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- first_joypad_check:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e2 ad1942 \u001b[36mlda\u001b[96m \u001b[93m0x4219\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e5 2910 \u001b[34mand\u001b[96m #\u001b[33m0x10\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e7 d02a \u001b[31mbne\u001b[96m \u001b[93m0x008213\u001b[0m\u001b[0m\u001b[0m \u001b[33m; press start to jump\u001b[0m\n",
"| // true: 0x00008213 false: 0x000081e9\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- second_joypad_check:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081e9 ae1c12 \u001b[36mldx\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ec ad1942 \u001b[36mlda\u001b[96m \u001b[93m0x4219\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ef 8d1c12 \u001b[36msta\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f2 8a \u001b[34mtxa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f3 4d1c12 \u001b[34meor\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f6 2d1c12 \u001b[34mand\u001b[96m \u001b[93m0x121c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081f9 8d1412 \u001b[36msta\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081fc ae2012 \u001b[36mldx\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000081ff ad1842 \u001b[36mlda\u001b[96m \u001b[93m0x4218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008202 8d2012 \u001b[36msta\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008205 8a \u001b[34mtxa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008206 4d2012 \u001b[34meor\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008209 2d2012 \u001b[34mand\u001b[96m \u001b[93m0x1220\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache1\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000820c 8d1812 \u001b[36msta\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000820f 4c1782 \u001b[33mjmp 0x8217\u001b[0m\u001b[0m\n",
"| // true: 0x00008217\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- start_is_pressed:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x81e7\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008213 4cd882 \u001b[33mjmp 0x82d8\u001b[0m\u001b[0m\n",
"| // true: 0x000082d8\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x820f\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008217 ad0012 \u001b[36mlda\u001b[96m \u001b[33m0x1200\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000821a 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000821c f004 \u001b[31mbeq\u001b[96m \u001b[33m0x008222\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008222 false: 0x0000821e\n",
"\u001b[93m│\u001b[0m 0x0000821e 4c4882 \u001b[33mjmp 0x8248\u001b[0m\u001b[0m\n",
"| // true: 0x00008248\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x821c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008222 ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008225 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008227 f004 \u001b[31mbeq\u001b[96m no_button_pressed.14\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if no button pressed\u001b[0m\n",
"| // true: 0x0000822d false: 0x00008229\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- any_button_pressed.15:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008229 4c4482 \u001b[33mjmp any_button_pressed.6\u001b[0m\u001b[0m\n",
"| // true: 0x00008244\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.14:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8227\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000822d ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008230 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008231 4940 \u001b[34meor\u001b[96m #\u001b[33m0x40\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_4:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008233 f008 \u001b[31mbeq\u001b[96m y_is_pressed.16\u001b[0m\u001b[0m\u001b[0m \u001b[33m; press only Y to jump\u001b[0m\n",
"| // true: 0x0000823d false: 0x00008235\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- y_not_pressed.17:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008235 ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008238 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000823a d008 \u001b[31mbne\u001b[96m any_button_pressed.6\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if button pressed\u001b[0m\n",
"| // true: 0x00008244 false: 0x0000823c\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.7:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000823c 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- y_is_pressed.16:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8233\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000823d 8e0012 \u001b[36mstx\u001b[96m \u001b[33m0x1200\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008240 4c5381 \u001b[33mjmp 0x8153\u001b[0m\u001b[0m\n",
"| // true: 0x00008153\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- any_button_pressed.6:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREFS from fcn.000081d3 @ \u001b[93m0x8229\u001b[93m, 0x823a\u001b[93m, 0x825a\u001b[93m, 0x828b\u001b[93m, 0x82b9\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008244 4c3281 \u001b[33mjmp 0x8132\u001b[0m\u001b[0m\n",
"| // true: 0x00008132\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x821e\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008248 ad0412 \u001b[36mlda\u001b[96m \u001b[33m0x1204\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000824b 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000824d f004 \u001b[31mbeq\u001b[96m \u001b[33m0x008253\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008253 false: 0x0000824f\n",
"\u001b[93m│\u001b[0m 0x0000824f 4c7982 \u001b[33mjmp 0x8279\u001b[0m\u001b[0m\n",
"| // true: 0x00008279\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x824d\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008253 ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008256 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008258 f004 \u001b[31mbeq\u001b[96m no_button_pressed.12\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if no button pressed\u001b[0m\n",
"| // true: 0x0000825e false: 0x0000825a\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- any_button_pressed.13:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000825a 4c4482 \u001b[33mjmp any_button_pressed.6\u001b[0m\u001b[0m\n",
"| // true: 0x00008244\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.12:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8258\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000825e ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008261 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008262 4984 \u001b[34meor\u001b[96m #\u001b[33m0x84\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_3:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008264 f008 \u001b[31mbeq\u001b[96m b_n_down_is_pressed.18\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x0000826e false: 0x00008266\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- b_n_down_not_pressed.19:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008266 ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008269 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000826b d008 \u001b[31mbne\u001b[96m any_button_pressed.4\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if button pressed\u001b[0m\n",
"| // true: 0x00008275 false: 0x0000826d\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.5:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000826d 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- b_n_down_is_pressed.18:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8264\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000826e 8e0412 \u001b[36mstx\u001b[96m \u001b[33m0x1204\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008271 4c6e81 \u001b[33mjmp 0x816e\u001b[0m\u001b[0m\n",
"| // true: 0x0000816e\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- any_button_pressed.4:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x826b\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008275 4c3281 \u001b[33mjmp 0x8132\u001b[0m\u001b[0m\n",
"| // true: 0x00008132\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x824f\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008279 ad0812 \u001b[36mlda\u001b[96m \u001b[33m0x1208\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000827c 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000827e f004 \u001b[31mbeq\u001b[96m \u001b[33m0x008284\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008284 false: 0x00008280\n",
"\u001b[93m│\u001b[0m 0x00008280 4caa82 \u001b[33mjmp 0x82aa\u001b[0m\u001b[0m\n",
"| // true: 0x000082aa\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x827e\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008284 ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008287 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008289 f004 \u001b[31mbeq\u001b[96m no_button_pressed.10\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if no button pressed\u001b[0m\n",
"| // true: 0x0000828f false: 0x0000828b\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- any_button_pressed.11:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000828b 4c4482 \u001b[33mjmp any_button_pressed.6\u001b[0m\u001b[0m\n",
"| // true: 0x00008244\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.10:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8289\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000828f ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008292 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008293 4928 \u001b[34meor\u001b[96m #\u001b[33m0x28\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_2:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008295 f008 \u001b[31mbeq\u001b[96m sel_n_up_is_pressed.20\u001b[0m\u001b[0m\u001b[0m \u001b[33m; press only sel+up to jump\u001b[0m\n",
"| // true: 0x0000829f false: 0x00008297\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- sel_n_up_not_pressed.21:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008297 ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000829a 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000829c d008 \u001b[31mbne\u001b[96m any_button_pressed.2\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if button pressed\u001b[0m\n",
"| // true: 0x000082a6 false: 0x0000829e\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.3:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000829e 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- sel_n_up_is_pressed.20:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8295\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000829f 8e0812 \u001b[36mstx\u001b[96m \u001b[33m0x1208\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082a2 4c8981 \u001b[33mjmp 0x8189\u001b[0m\u001b[0m\n",
"| // true: 0x00008189\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- any_button_pressed.2:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x829c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082a6 4c3281 \u001b[33mjmp 0x8132\u001b[0m\u001b[0m\n",
"| // true: 0x00008132\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8280\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082aa ad0c12 \u001b[36mlda\u001b[96m \u001b[33m0x120c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082ad 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082af f001 \u001b[31mbeq\u001b[96m \u001b[33m0x0082b2\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x000082b2 false: 0x000082b1\n",
"\u001b[93m│\u001b[0m 0x000082b1 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82af\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082b2 ad1412 \u001b[36mlda\u001b[96m \u001b[93m0x1214\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1a_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082b5 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082b7 f004 \u001b[31mbeq\u001b[96m no_button_pressed.8\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if no button pressed\u001b[0m\n",
"| // true: 0x000082bd false: 0x000082b9\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- any_button_pressed.9:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082b9 4c4482 \u001b[33mjmp any_button_pressed.6\u001b[0m\u001b[0m\n",
"| // true: 0x00008244\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.8:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82b7\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082bd ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c0 aa \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c1 2920 \u001b[34mand\u001b[96m #\u001b[33m0x20\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- jump_if_something_1:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c3 d008 \u001b[31mbne\u001b[96m l_is_pressed.22\u001b[0m\u001b[0m\u001b[0m \u001b[33m; press L to jump\u001b[0m\n",
"| // true: 0x000082cd false: 0x000082c5\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- l_not_pressed.23:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c5 ad1812 \u001b[36mlda\u001b[96m \u001b[93m0x1218\u001b[0m\u001b[0m\u001b[0m \u001b[33m; joy1b_cache2\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082c8 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082ca d008 \u001b[31mbne\u001b[96m any_button_pressed.0\u001b[0m\u001b[0m\u001b[0m \u001b[33m; jump if button pressed\u001b[0m\n",
"| // true: 0x000082d4 false: 0x000082cc\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- no_button_pressed.1:\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082cc 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- l_is_pressed.22:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82c3\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082cd 8e0c12 \u001b[36mstx\u001b[96m \u001b[33m0x120c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082d0 4ca481 \u001b[33mjmp 0x81a4\u001b[0m\u001b[0m\n",
"| // true: 0x000081a4\n",
"\u001b[93m│\u001b[0m \u001b[93m;-- any_button_pressed.0:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82ca\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082d4 4c3281 \u001b[33mjmp 0x8132\u001b[0m\u001b[0m\n",
"| // true: 0x00008132\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8213\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082d8 a200 \u001b[36mldx\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082da 08 \u001b[36mphp\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082db 8e1621 \u001b[36mstx\u001b[96m \u001b[33m0x2116\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082de a200 \u001b[36mldx\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082e0 00a0 \u001b[31mbrk\u001b[96m \u001b[33m0xa0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082e2 0000 \u001b[31mbrk\u001b[96m \u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x000082e4\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82f4\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082e4 bd4b88 \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082e7 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082e9 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082ec 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082ef c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082f0 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082f1 c005 \u001b[36mcpy\u001b[96m #\u001b[33m0x05\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082f3 00d0 \u001b[31mbrk\u001b[96m \u001b[33m0xd0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082f5 ee \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x000082e4 false: 0x000082f6\n",
"\u001b[93m│\u001b[0m 0x000082f6 ae0012 \u001b[36mldx\u001b[96m \u001b[33m0x1200\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082f9 a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082fb 00 \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x000082fc\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x830c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082fc bd4b88 \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082ff 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008301 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008304 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008307 c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008308 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008309 c006 \u001b[36mcpy\u001b[96m #\u001b[33m0x06\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000830b 00d0 \u001b[31mbrk\u001b[96m \u001b[33m0xd0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000830d ee \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x000082fc false: 0x0000830e\n",
"\u001b[93m│\u001b[0m 0x0000830e ae0412 \u001b[36mldx\u001b[96m \u001b[33m0x1204\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008311 a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008313 00 \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008314\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8324\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008314 bd4b88 \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008317 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008319 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000831c 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000831f c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008320 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008321 c005 \u001b[36mcpy\u001b[96m #\u001b[33m0x05\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008323 00d0 \u001b[31mbrk\u001b[96m \u001b[33m0xd0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008325 ee \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008314 false: 0x00008326\n",
"\u001b[93m│\u001b[0m 0x00008326 ae0812 \u001b[36mldx\u001b[96m \u001b[33m0x1208\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008329 a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000832b 00 \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x0000832c\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x833c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000832c bd4b88 \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000832f 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008331 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008334 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008337 c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008338 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008339 c005 \u001b[36mcpy\u001b[96m #\u001b[33m0x05\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000833b 00d0 \u001b[31mbrk\u001b[96m \u001b[33m0xd0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000833d ee \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x0000832c false: 0x0000833e\n",
"\u001b[93m│\u001b[0m 0x0000833e ae0c12 \u001b[36mldx\u001b[96m \u001b[33m0x120c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008341 a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008343 00 \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008344\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8354\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008344 bd4b88 \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008347 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008349 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000834c 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000834f c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008350 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008351 c00a \u001b[36mcpy\u001b[96m #\u001b[33m0x0a\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008353 00d0 \u001b[31mbrk\u001b[96m \u001b[33m0xd0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008355 ee \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008344 false: 0x00008356\n",
"\u001b[93m│\u001b[0m 0x00008356 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"\n"
]
}
],
"source": [
"r2cmd(r,\"pdr. @ first_joypad_check\")"
]
},
{
"cell_type": "markdown",
"id": "ddb213b7-516b-470c-92cf-28c6d63aa716",
"metadata": {},
"source": [
"Let's look closer at the paths taken when one of the joypad presses we've recognized happens"
]
},
{
"cell_type": "code",
"execution_count": 38,
"id": "cdd99bdb-4a2b-4d79-b6d8-057838d0e7bb",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- start_is_pressed:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x81e7\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m \u001b[30m0x00008213\u001b[0m \u001b[96m4c\u001b[96md8\u001b[96m82\u001b[0m \u001b[33mjmp 0x82d8\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m;-- y_is_pressed.16:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8233\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[30m0x0000823d\u001b[0m \u001b[96m8e\u001b[34m00\u001b[96m12\u001b[0m \u001b[36mstx\u001b[96m \u001b[33m0x1200\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m \u001b[30m0x00008240\u001b[0m \u001b[96m4c\u001b[96m53\u001b[96m81\u001b[0m \u001b[33mjmp 0x8153\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m;-- b_n_down_is_pressed.18:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8264\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[30m0x0000826e\u001b[0m \u001b[96m8e\u001b[96m04\u001b[96m12\u001b[0m \u001b[36mstx\u001b[96m \u001b[33m0x1204\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m \u001b[30m0x00008271\u001b[0m \u001b[96m4c\u001b[96m6e\u001b[96m81\u001b[0m \u001b[33mjmp 0x816e\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m;-- sel_n_up_is_pressed.20:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8295\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[30m0x0000829f\u001b[0m \u001b[96m8e\u001b[96m08\u001b[96m12\u001b[0m \u001b[36mstx\u001b[96m \u001b[33m0x1208\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m \u001b[30m0x000082a2\u001b[0m \u001b[96m4c\u001b[96m89\u001b[96m81\u001b[0m \u001b[33mjmp 0x8189\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m;-- l_is_pressed.22:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82c3\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[30m0x000082cd\u001b[0m \u001b[96m8e\u001b[96m0c\u001b[96m12\u001b[0m \u001b[36mstx\u001b[96m \u001b[33m0x120c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m \u001b[30m0x000082d0\u001b[0m \u001b[96m4c\u001b[96ma4\u001b[96m81\u001b[0m \u001b[33mjmp 0x81a4\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"# BUG: pdb @@ *_is_pressed doesn't work\n",
"r2cmd(r, \"pdb @@=`f ~_is_pressed[0]`\")"
]
},
{
"cell_type": "markdown",
"id": "44f1f8fa-737b-40f3-a9de-f579872f6e25",
"metadata": {},
"source": [
"We can see the `stx` instructions in most paths. These are storing the copies of the joypad caches made (see above). Let's label those locations, and add some comments for the accesses to them. Let's also label the jump targets of these ebbs to propagate the descriptive labels forward."
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "07314e8c-ff47-45fe-bc1b-180010642326",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, \"\"\"\n",
"fe start_is_pressed @ 0x82d8\n",
"fe y_is_pressed @ 0x8153\n",
"fe b_n_down_is_pressed @ 0x816e\n",
"fe sel_n_up_is_pressed @ 0x8189\n",
"fe l_is_pressed @ 0x81a4\n",
"\"\"\")\n",
"r2cmd(r,\"\"\"\n",
"f+ y_pressed_cache @ 0x1200\n",
"f+ b_n_down_pressed_cache @ 0x1204\n",
"f+ sel_n_up_pressed_cache @ 0x1208\n",
"f+ l_pressed_cache @ 0x120c\n",
"\"\"\")\n",
"r2cmd(r,\"\"\"\n",
"e asm.lines=false\n",
"CCu y_pressed_cache @@=`pdf @@ fcn.* ~0x1200[0] | sort -u`\n",
"CCu b_n_down_pressed_cache @@=`pdf @@ fcn.* ~0x1204[0] | sort -u`\n",
"CCu sel_n_up_pressed_cache @@=`pdf @@ fcn.* ~0x1208[0] | sort -u`\n",
"CCu l_pressed_cache @@=`pdf @@ fcn.* ~0x120c[0] | sort -u`\n",
"e asm.lines=true\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "f8a04308-7f28-4eae-9759-f9c1ea99009b",
"metadata": {},
"source": [
"Following the same approach as when we followed the reads and writes of the `joy*_cache*` globals above, we can look at all the places where these `*_pressed_cache` globals are accessed:"
]
},
{
"cell_type": "code",
"execution_count": 40,
"id": "af710c60-822c-4664-ba6d-3387a919a363",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x00008035 9c0012 stz 0x1200 ; y_pressed_cache\n",
"0x00008038 9c0412 stz 0x1204 ; b_n_down_pressed_cache\n",
"0x0000803b 9c0812 stz 0x1208 ; sel_n_up_pressed_cache\n",
"0x0000803e 9c0c12 stz 0x120c ; l_pressed_cache\n",
"0x00008360 c230 rep #0x30 ; l_pressed_cache\n",
"0x00008217 ad0012 lda 0x1200 ; y_pressed_cache\n",
"0x0000823d 8e0012 stx 0x1200 ; y_pressed_cache\n",
"0x00008248 ad0412 lda 0x1204 ; b_n_down_pressed_cache\n",
"0x0000826e 8e0412 stx 0x1204 ; b_n_down_pressed_cache\n",
"0x00008279 ad0812 lda 0x1208 ; sel_n_up_pressed_cache\n",
"0x0000829f 8e0812 stx 0x1208 ; sel_n_up_pressed_cache\n",
"0x000082aa ad0c12 lda 0x120c ; l_pressed_cache\n",
"0x000082cd 8e0c12 stx 0x120c ; l_pressed_cache\n",
"0x000082f6 ae0012 ldx 0x1200 ; y_pressed_cache\n",
"0x0000830e ae0412 ldx 0x1204 ; b_n_down_pressed_cache\n",
"0x00008326 ae0812 ldx 0x1208 ; sel_n_up_pressed_cache\n",
"0x0000833e ae0c12 ldx 0x120c ; l_pressed_cache\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"e asm.lines = false\n",
"pdf @@ fcn.* ~_pressed_cache\n",
"e asm.lines = true\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "12fabdb0-410c-4203-9357-10a0e87404c2",
"metadata": {},
"source": [
"We got one false match with the `rep #0x30` `¯\\_(ツ)_/¯` What's stranger about it is there is no comment at `0x8360` according to `r2`:"
]
},
{
"cell_type": "code",
"execution_count": 41,
"id": "d492246f-500e-40dc-8bed-222716b89486",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, \"CC, ~0x8360\")"
]
},
{
"cell_type": "markdown",
"id": "3c455508-e592-49d9-a8bb-0a035efbbec9",
"metadata": {},
"source": [
"It's maybe due to some incorrect function identification and matching the `0x8360` address with the last `l_pressed_cache` comment at `0x833e` (see below). But since we can't remove it, we'll just need to ignore it."
]
},
{
"cell_type": "markdown",
"id": "8a843bc8-377a-490f-8e83-711f8eff911d",
"metadata": {},
"source": [
"But otherwise the pattern here is zeroing of the globals, then a check (`lda` / `ldx`) that precedes the store ( `stx`) for each of these caches and then a sequence of checks/loads for each of them later (the `ldx`, `ldx`, `ldx`, `ldx`) sequence. We know the ROM asks for a 'sequence' of inputs before pressing start so this is probabaly the state-machine transitions followed by the check of the entered sequence when start is pressed.\n",
"\n",
"We can look closer at the locations where the globals are accessed by diassembling the ebbs for each location (much as we did for the `_cache` globals above). Remember the is a small bug we need to work around so we'll list all the addresses of read/write (seen above) into a file (we'll also remove the false positive at `0x8360` and the init routine at `0x8000`) and then process that file with `@@.` "
]
},
{
"cell_type": "code",
"execution_count": 42,
"id": "3a28000e-ccbb-47ec-a042-baf61c3ec93c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x820f\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008217 ad0012 \u001b[36mlda\u001b[96m \u001b[93m0x1200\u001b[0m\u001b[0m\u001b[0m \u001b[33m; y_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000821a 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000821c f004 \u001b[31mbeq\u001b[96m \u001b[33m0x008222\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m;-- y_is_pressed.16:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8233\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x0000823d 8e0012 \u001b[36mstx\u001b[96m \u001b[93m0x1200\u001b[0m\u001b[0m\u001b[0m \u001b[33m; y_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x00008240 4c5381 \u001b[33mjmp y_is_pressed.25\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x821e\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008248 ad0412 \u001b[36mlda\u001b[96m \u001b[93m0x1204\u001b[0m\u001b[0m\u001b[0m \u001b[33m; b_n_down_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000824b 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000824d f004 \u001b[31mbeq\u001b[96m \u001b[33m0x008253\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m;-- b_n_down_is_pressed.18:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8264\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x0000826e 8e0412 \u001b[36mstx\u001b[96m \u001b[93m0x1204\u001b[0m\u001b[0m\u001b[0m \u001b[33m; b_n_down_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x00008271 4c6e81 \u001b[33mjmp b_n_down_is_pressed.26\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x824f\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008279 ad0812 \u001b[36mlda\u001b[96m \u001b[93m0x1208\u001b[0m\u001b[0m\u001b[0m \u001b[33m; sel_n_up_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000827c 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000827e f004 \u001b[31mbeq\u001b[96m \u001b[33m0x008284\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m;-- sel_n_up_is_pressed.20:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8295\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x0000829f 8e0812 \u001b[36mstx\u001b[96m \u001b[93m0x1208\u001b[0m\u001b[0m\u001b[0m \u001b[33m; sel_n_up_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x000082a2 4c8981 \u001b[33mjmp sel_n_up_is_pressed.27\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8280\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082aa ad0c12 \u001b[36mlda\u001b[96m \u001b[93m0x120c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; l_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082ad 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082af f001 \u001b[31mbeq\u001b[96m \u001b[33m0x0082b2\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m;-- l_is_pressed.22:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82c3\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x000082cd 8e0c12 \u001b[36mstx\u001b[96m \u001b[93m0x120c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; l_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x000082d0 4ca481 \u001b[33mjmp l_is_pressed.28\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082f6 ae0012 \u001b[36mldx\u001b[96m \u001b[93m0x1200\u001b[0m\u001b[0m\u001b[0m \u001b[33m; y_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082f9 a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082fb 00 \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000830e ae0412 \u001b[36mldx\u001b[96m \u001b[93m0x1204\u001b[0m\u001b[0m\u001b[0m \u001b[33m; b_n_down_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008311 a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008313 00 \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008326 ae0812 \u001b[36mldx\u001b[96m \u001b[93m0x1208\u001b[0m\u001b[0m\u001b[0m \u001b[33m; sel_n_up_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008329 a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000832b 00 \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x0000833e ae0c12 \u001b[36mldx\u001b[96m \u001b[93m0x120c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; l_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008341 a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x00008343 00 \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"e asm.lines = false\n",
"?v $Fb @@=`pdf @@ fcn.* ~_pressed_cache[0]` | grep -v 0x8360 | grep -v 0x8000 | sort -u > pressed_cache_bbs.txt\n",
"e asm.lines=true\n",
"\"\"\")\n",
"r2cmd(r, \"pdb @@.pressed_cache_bbs.txt\")"
]
},
{
"cell_type": "markdown",
"id": "39a1f9a2-d578-4221-8ecf-73a481d4ed4a",
"metadata": {},
"source": [
"It sure looks like we assumed; the `and #0xff` and `beq`s are testing for any keypress; recall that the joypad register value is stored in the `*_pressed_cache*` globals.\n",
"\n",
"The `invalid` instructions here are erroneous. There is probably something going wrong with how `r2` splits ebbs at the `brk` instructions. Compare the snippet in `0x82f6 - 0x82fb` above with the same region grepped out of the whole function disassembly below:"
]
},
{
"cell_type": "code",
"execution_count": 43,
"id": "b88c610e-c545-4dae-9341-0d8f9221a7de",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"│ ╎ ╎ ╎ 0x000082f0 e8 inx\n",
"│ ╎ ╎ ╎ 0x000082f1 c005 cpy #0x05\n",
"│ ╎ ╎ ╎ 0x000082f3 00d0 brk 0xd0\n",
"│ ╎ ╎ 0x000082f5 ~ eeae00 inc 0x00ae\n",
"│ ╎ ╎ 0x000082f6 ae0012 ldx 0x1200 ; y_pressed_cache\n",
"│ ╎ ╎ 0x000082f9 a000 ldy #0x00\n",
"│ ╎ ╎ 0x000082fb ~ 00bd brk 0xbd\n",
"│ ╎ ╎ ┌─> 0x000082fc bd4b88 lda 0x884b,x\n",
"│ ╎ ╎ ╎ 0x000082ff 293f and #0x3f\n",
"\n"
]
}
],
"source": [
"# BUG: r2 breaks EBBS at the wrong byte for SNES `brk` instructions.\n",
"r2cmd(r, \"pdf @ 0x82f6 ~ 0x000082f\")"
]
},
{
"cell_type": "markdown",
"id": "9d85e944-bdac-4422-a8bb-aab616b8d97a",
"metadata": {},
"source": [
"Maybe we can just disassemble recursively from the start_pressed onwards? (just scan over the next output)"
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "9d9bbd61-5fb4-41bc-bc6d-fd9afee5a5a7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- start_is_pressed.24:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8213\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082d8\u001b[0m \u001b[96ma2\u001b[34m00\u001b[96m08\u001b[0m \u001b[36mldx\u001b[96m #\u001b[33m0x0800\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082db\u001b[0m \u001b[96m8e\u001b[96m16\u001b[96m21\u001b[0m \u001b[36mstx\u001b[96m \u001b[33m0x2116\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082de\u001b[0m \u001b[96ma2\u001b[34m00\u001b[34m00\u001b[0m \u001b[36mldx\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082e1\u001b[0m \u001b[96ma0\u001b[34m00\u001b[34m00\u001b[0m \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x000082e4\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82f4\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082e4\u001b[0m \u001b[96mbd\u001b[96m4b\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082e7\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082e9\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082ec\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082ef\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082f0\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082f1\u001b[0m \u001b[96mc0\u001b[96m05\u001b[34m00\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x0005\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082f4\u001b[0m \u001b[96md0\u001b[96mee\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x0082e4\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x000082e4 false: 0x000082f6\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082f6\u001b[0m \u001b[96mae\u001b[34m00\u001b[96m12\u001b[0m \u001b[36mldx\u001b[96m \u001b[93m0x1200\u001b[0m\u001b[0m\u001b[0m \u001b[33m; y_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082f9\u001b[0m \u001b[96ma0\u001b[34m00\u001b[34m00\u001b[0m \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x000082fc\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x830c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082fc\u001b[0m \u001b[96mbd\u001b[96m4b\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082ff\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008301\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008304\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008307\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008308\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008309\u001b[0m \u001b[96mc0\u001b[96m06\u001b[34m00\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x0006\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000830c\u001b[0m \u001b[96md0\u001b[96mee\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x0082fc\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x000082fc false: 0x0000830e\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000830e\u001b[0m \u001b[96mae\u001b[96m04\u001b[96m12\u001b[0m \u001b[36mldx\u001b[96m \u001b[93m0x1204\u001b[0m\u001b[0m\u001b[0m \u001b[33m; b_n_down_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008311\u001b[0m \u001b[96ma0\u001b[34m00\u001b[34m00\u001b[0m \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008314\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8324\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008314\u001b[0m \u001b[96mbd\u001b[96m4b\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008317\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008319\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000831c\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000831f\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008320\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008321\u001b[0m \u001b[96mc0\u001b[96m05\u001b[34m00\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x0005\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008324\u001b[0m \u001b[96md0\u001b[96mee\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x008314\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008314 false: 0x00008326\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008326\u001b[0m \u001b[96mae\u001b[96m08\u001b[96m12\u001b[0m \u001b[36mldx\u001b[96m \u001b[93m0x1208\u001b[0m\u001b[0m\u001b[0m \u001b[33m; sel_n_up_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008329\u001b[0m \u001b[96ma0\u001b[34m00\u001b[34m00\u001b[0m \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x0000832c\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x833c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000832c\u001b[0m \u001b[96mbd\u001b[96m4b\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000832f\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008331\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008334\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008337\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008338\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008339\u001b[0m \u001b[96mc0\u001b[96m05\u001b[34m00\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x0005\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000833c\u001b[0m \u001b[96md0\u001b[96mee\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x00832c\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x0000832c false: 0x0000833e\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000833e\u001b[0m \u001b[96mae\u001b[96m0c\u001b[96m12\u001b[0m \u001b[36mldx\u001b[96m \u001b[93m0x120c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; l_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008341\u001b[0m \u001b[96ma0\u001b[34m00\u001b[34m00\u001b[0m \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008344\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8354\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008344\u001b[0m \u001b[96mbd\u001b[96m4b\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m \u001b[33m0x884b\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008347\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008349\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000834c\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x0000834f\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008350\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008351\u001b[0m \u001b[96mc0\u001b[96m0a\u001b[34m00\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x000a\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008354\u001b[0m \u001b[96md0\u001b[96mee\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x008344\u001b[0m\u001b[0m\u001b[0m\n",
"| // true: 0x00008344 false: 0x00008356\n",
"\u001b[93m│\u001b[0m \u001b[30m0x00008356\u001b[0m \u001b[96m60\u001b[0m \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"pdr. @ `f ~start_is_pressed.[0]`\")"
]
},
{
"cell_type": "markdown",
"id": "db785290-a95b-433f-b7ec-6fe8190db59d",
"metadata": {},
"source": [
"There are some loops and indexed accesses into `0x884b` as well as state tracking in `0x2116`, `0x2118`, and `0x2119`. The `0x2---` are globals (we've seen this address range now. But `0x884b`... that is near all this code. It is near enough to be in the ROM data. What's at that address?"
]
},
{
"cell_type": "code",
"execution_count": 45,
"id": "17ae30f5-d01f-488d-b11b-165f917966a8",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[32m- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\u001b[0m\n",
"\u001b[30m0x0000884b\u001b[0m 464c 4147 2d34 3354 4644 3338 4439 504c\u001b[0m FLAG-43TFD38D9PL\u001b[0m\n",
"\u001b[30m0x0000885b\u001b[0m 5650 3957 5837 4e34 3944 5841 4736 5158\u001b[0m VP9WX7N49DXAG6QX\u001b[0m\n",
"\u001b[30m0x0000886b\u001b[0m 3754 5151 514b 4247 4d43 3951 5242 3654\u001b[0m 7TQQQKBGMC9QRB6T\u001b[0m\n",
"\u001b[30m0x0000887b\u001b[0m 5448 5554 374c 4133 5034 4350 4a50 5551\u001b[0m THUT7LA3P4CPJPUQ\u001b[0m\n",
"\u001b[30m0x0000888b\u001b[0m 5042 5239 5955 4e39 5836 3837 4c46 3959\u001b[0m PBR9YUN9X687LF9Y\u001b[0m\n",
"\u001b[30m0x0000889b\u001b[0m 3943 4436 4333 5150 3746 3958 3333 4735\u001b[0m 9CD6C3QP7F9X33G5\u001b[0m\n",
"\u001b[30m0x000088ab\u001b[0m 4339 3336 4638 394a 564a 5138 3341 5947\u001b[0m C936F89JVJQ83AYG\u001b[0m\n",
"\u001b[30m0x000088bb\u001b[0m 4654 3835 3347 474d 544b 3437 4739 3344\u001b[0m FT853GGMTK47G93D\u001b[0m\n",
"\u001b[30m0x000088cb\u001b[0m 4b39 5539 4848 5159 5238 3857 5050 5235\u001b[0m K9U9HHQYR88WPPR5\u001b[0m\n",
"\u001b[30m0x000088db\u001b[0m 4359 3344 4742 4656 5939 5047 4a47 3439\u001b[0m CY3DGBFVY9PGJG49\u001b[0m\n",
"\u001b[30m0x000088eb\u001b[0m 3748 5033 4745 4a39 4741 5459 564b 3439\u001b[0m 7HP3GEJ9GATYVK49\u001b[0m\n",
"\u001b[30m0x000088fb\u001b[0m 4e59 4c46 3534 5750 3838 3533 494e 4235\u001b[0m NYLF54WP8853INB5\u001b[0m\n",
"\u001b[30m0x0000890b\u001b[0m 5835 5438 3354 3941 3938 5145 394c 3451\u001b[0m X5T83T9A98QE9L4Q\u001b[0m\n",
"\u001b[30m0x0000891b\u001b[0m 4639 5557 5537 3741 4433 4154 4854 3337\u001b[0m F9UWU77AD3ATHT37\u001b[0m\n",
"\u001b[30m0x0000892b\u001b[0m 4d59 3952 3935 4a4e 5239 4659 5842 3934\u001b[0m MY9R95JNR9FYXB94\u001b[0m\n",
"\u001b[30m0x0000893b\u001b[0m 514e 4447 4257 5439 4b48 5654 3950 3644\u001b[0m QNDGBWT9KHVT9P6D\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"pxa @ 0x884b\")"
]
},
{
"cell_type": "markdown",
"id": "900ae8b7-2daf-424d-9b17-bc8df1458573",
"metadata": {},
"source": [
"## RE-fwd 5: FLAG- FLAG\n",
"\n",
"😮🤨. It _looks_ like a flag but it isnt' (trust me I tried to submit it anyways during the CTF 🤷‍♀️). But we know what to do: mark it with flags and comments... (actually _this time_ comments aren't needed because `r2` _does_ substitute flags for indexed load into registers)."
]
},
{
"cell_type": "code",
"execution_count": 46,
"id": "2ab1cbcd-e411-4624-968a-144228b8140c",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, \"\"\"\n",
"f+ flagflag @ 0x884b\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "03982485-da74-4f61-bdef-fcdc0d9b1818",
"metadata": {},
"source": [
"Let's take a closer look at the disassembly from `start_is_pressed.24` onwards. Just the first two ebbs this time."
]
},
{
"cell_type": "code",
"execution_count": 47,
"id": "59ffedfd-6cef-41a7-a18d-560f5a8f5acb",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[93m;-- start_is_pressed.24:\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x8213\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082d8\u001b[0m \u001b[96ma2\u001b[34m00\u001b[96m08\u001b[0m \u001b[36mldx\u001b[96m #\u001b[33m0x0800\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082db\u001b[0m \u001b[96m8e\u001b[96m16\u001b[96m21\u001b[0m \u001b[36mstx\u001b[96m \u001b[33m0x2116\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082de\u001b[0m \u001b[96ma2\u001b[34m00\u001b[34m00\u001b[0m \u001b[36mldx\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[30m0x000082e1\u001b[0m \u001b[96ma0\u001b[34m00\u001b[34m00\u001b[0m \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x82f4\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m┌\u001b[0m\u001b[36m─\u001b[0m\u001b[36m>\u001b[0m \u001b[30m0x000082e4\u001b[0m \u001b[96mbd\u001b[96m4b\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[30m0x000082e7\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[30m0x000082e9\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[30m0x000082ec\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[30m0x000082ef\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[30m0x000082f0\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m \u001b[30m0x000082f1\u001b[0m \u001b[96mc0\u001b[96m05\u001b[34m00\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x0005\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m \u001b[30m0x000082f4\u001b[0m \u001b[96md0\u001b[96mee\u001b[0m \u001b[31mbne\u001b[96m \u001b[33m0x0082e4\u001b[0m\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"s `f ~start_is_pressed.[0]`\n",
"pdb\n",
"s $Fj\n",
"pdb\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "6d6b03fb-d6f7-4ef2-9f6c-2ab70b32b065",
"metadata": {},
"source": [
"Index register `x` gets initialized with `0` and then is used as an offset to copy out `0x0005` following bytes from the `flagflag` buffer. i.e. `FLAG-`\n",
"\n",
"Aha! This is the 'win function'!"
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "236df821-0b25-4d27-a509-800089d58ce4",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, \"f the_win_fn @ 0x82e4\")"
]
},
{
"cell_type": "markdown",
"id": "e18a7aaf-06dd-404e-a1fe-c5f20b998711",
"metadata": {},
"source": [
"But there's a catch...\n",
"\n",
"We could have found the win function by going backwards from the `flagflag` buffer address to the disassembly. During the CTF I tried this first: I patched the ROM to jump directly to the win function. A 'flag' \"FLAG-GBLKASDLKJASDLKJASDLKJASDLKJASLDKJD\" was shown on the screen. But this was not a flag (i.e. it did not submit as a valid flag.\n",
"\n",
"Let's see why by looking at the next two ebbs:"
]
},
{
"cell_type": "code",
"execution_count": 49,
"id": "f688e74a-43ec-492c-81c2-359e91ab546e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m 0x000082f6 ae0012 \u001b[36mldx\u001b[96m \u001b[93m0x1200\u001b[0m\u001b[0m\u001b[0m \u001b[33m; y_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082f9 a00000 \u001b[36mldy\u001b[96m #\u001b[93m0x0000\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"\u001b[93m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081d3 @ \u001b[93m0x830c\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m┌\u001b[0m\u001b[36m─\u001b[0m\u001b[36m>\u001b[0m 0x000082fc bd4b88 \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x000082ff 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x00008301 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x00008304 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x00008307 c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x00008308 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x00008309 c00600 \u001b[36mcpy\u001b[96m #\u001b[33m0x0006\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x0000830c d0ee \u001b[31mbne\u001b[96m \u001b[33m0x0082fc\u001b[0m\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"s the_win_fn\n",
"s $Ff\n",
"pdb\n",
"s $Fj\n",
"pdb\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "90588e6d-3cf2-45ed-a368-78e280dd8bd3",
"metadata": {},
"source": [
"Index register `x` gets loaded with the value in `0x1200` and then copies out `6` bytes from the `flagflag` buffer starting at that offset (`0x40`).\n",
"\n",
"The same thing happens with the rest: copy out segments of the `flagflag` buffer based on the offset read from the `_cache` globals.\n",
"\n",
"This is an anti-cheat technique you might find in video games; it is called *data entanglement* (at least where I've been introduced to it). It is a control-flow protection. If an attacker changes the flow of execution the result will be corrupted. i.e. for this challenge the correct joypad inputs must be entered. No branch jamming allowed.\n",
"\n",
"We _could_ continue to get all the segments; the next reads are of 5, 5, 10 bytes from 0x84, 0x28, 0x20 offsets. Along with the first 2 segments we already discussed above, that looks like:"
]
},
{
"cell_type": "code",
"execution_count": 50,
"id": "b256161f-93f4-4f22-98e6-c91d42e70c8c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"FLAG-\n",
"\n",
"PBR9YU\n",
"\n",
"HHQYR\n",
"\n",
"MC9QR\n",
"\n",
"7TQQQKBGMC\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"ps 5 @ flagflag+0\n",
"ps 6 @ flagflag+0x40\n",
"ps 5 @ flagflag+0x84\n",
"ps 5 @ flagflag+0x28\n",
"ps 10 @ flagflag+0x20\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "6da2c676-8520-494d-bc29-36c162781c58",
"metadata": {},
"source": [
"Which is the whole flag yay!\n",
"\n",
"![frame_adv_input_correct_4_and_flag.png](frame_adv_input_correct_4_and_flag.png)\n",
"\n",
"Of course we didn't have to go _this_ far. When we had decoded the valid inputs above we could stuck them into an emulator (make sure you do frame-perfect inputs for the combos).\n",
"\n",
"> 1. The first test (0x8233) is `eor`ing `joy1a` with `0x40` and jumps if zero. i.e. jumps if only **Y is pressed**\n",
"> 2. @ 0x8264 it is `eor`ing `joy1a` with `0x84` and jumps if zero. i.e. jumps if **B+down is pressed**\n",
"> 3. @ 0x8295 it is `eor`ing `joy1a` with `0x28` and jumps if zero. i.e. jumps if **select+up is pressed**\n",
"> 4. @ 0x82c3 it is `and`ing `joy1b` with `0x20` are jumps if not zero. i.e. jumps if at least **L is pressed**\n",
"\n",
"But we did learn more r2 this way ;)"
]
},
{
"cell_type": "markdown",
"id": "69c5c519-d798-4f08-8303-7012ebd4b63b",
"metadata": {},
"source": [
"# 2. Reversing Backwards (sequence_2)\n",
"\n",
"For the sequence_1 writeup we did reversing of the ROM 'forward': we started with the joypad registers and followed the data flow through execution from there all the way to the flag segment 'win function.'\n",
"\n",
"This time (for sequence_2) let's start with the FLAG buffer and work backwards from there."
]
},
{
"cell_type": "code",
"execution_count": 51,
"id": "d1f632af-8a3a-4444-a6d3-69c12995cda6",
"metadata": {},
"outputs": [],
"source": [
"r = r2pipe.open('../sequence_2/sequence_2.smc', ['-2'])"
]
},
{
"cell_type": "markdown",
"id": "f597189c-0360-48fd-a42a-88887a74ede1",
"metadata": {},
"source": [
"We need to find the `flagflag` as our starting point:"
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "1c1adfd1-698c-4dc8-928b-55a83ecb5f4b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x000088a9 hit0_0 \"|FLAG-HN98KWRK9UWU77A\"\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"/ FLAG\")"
]
},
{
"cell_type": "markdown",
"id": "01aef5ba-3d95-481e-a5af-ef990115c407",
"metadata": {},
"source": [
"When you search (`/`) with `r2` it marks all the found locations with `hitx_y` -- you can see flag `hit0_0` above. We need to delete `hit0_0` and change it to a more descriptive flag..."
]
},
{
"cell_type": "code",
"execution_count": 53,
"id": "08290e8d-e6ca-44d8-8ac8-bb9443ef7a93",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[32m- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\u001b[0m\n",
" /flagflag \n",
"\u001b[30m0x000088a9\u001b[0m \u001b[7m\u001b[96m46\u001b[27m\u001b[0m4c 4147 2d48 4e39 384b 5752 4b39 5557\u001b[0m \u001b[7m\u001b[96m\u001b[27mF\u001b[0mLAG-HN98KWRK9UW\u001b[0m\n",
"\u001b[30m0x000088b9\u001b[0m 5537 3741 4433 4154 3439 4458 4736 5158\u001b[0m U77AD3AT49DXG6QX\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"f- @ 0x88a9\n",
"f flagflag @ 0x88a9\n",
"\"\"\")\n",
"r2cmd(r, \"pxa 32 @ 0x88a9\")"
]
},
{
"cell_type": "markdown",
"id": "1272440e-2011-4010-ad6d-e421d3405eee",
"metadata": {},
"source": [
"We're gonna follow the same pattern of searching for references to something by disassembling all the functions. So we need to get `r2` to identify all the functions in the ROM first. Running default analysis will do the trick."
]
},
{
"cell_type": "code",
"execution_count": 54,
"id": "59025ebd-52f7-44c3-93d2-7f3dc9dd6a1f",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, \"aaa\")"
]
},
{
"cell_type": "markdown",
"id": "a76107cf-e3a6-4726-a630-e41f6e1d1c09",
"metadata": {},
"source": [
"Then asking about any lines in the disassembly that refer to `flagflag` (indexed instructions will look like this) or any lines that have the literal address (non-indexed instructions will look like this)."
]
},
{
"cell_type": "code",
"execution_count": 55,
"id": "c4ab1502-0b58-4ea5-abed-180cb3e201ae",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"│ ┌──> 0x00008348 bda988 lda flagflag,x\n",
"│ ┌──> 0x00008360 bda988 lda flagflag,x\n",
"│ ┌──> 0x00008378 bda988 lda flagflag,x\n",
"│ ┌──> 0x00008390 bda988 lda flagflag,x\n",
"│ ┌──> 0x000083a8 bda988 lda flagflag,x\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"pdf @@ fcn.* ~flagflag,0x88a9\")"
]
},
{
"cell_type": "markdown",
"id": "1d81111b-dbd6-4831-97eb-53a95f83248b",
"metadata": {},
"source": [
"The grep through all the disassembly tells us there's a few locations loading indexed into the `flagflag`. Let's look at each of the ebbs of the indexed loads:"
]
},
{
"cell_type": "code",
"execution_count": 56,
"id": "39e27a94-f5f5-4ee6-8676-50d36450ff7d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x8358\u001b[93m\u001b[0m\n",
"\u001b[30m0x00008348\u001b[0m \u001b[96mbd\u001b[96ma9\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000834b\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000834d\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008350\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008353\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008354\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008355\u001b[0m \u001b[96mc0\u001b[96m05\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x05\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008357\u001b[0m \u001b[34m00\u001b[96md0\u001b[0m \u001b[31mbrk\u001b[96m \u001b[33m0xd0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008359\u001b[0m \u001b[96mee\u001b[0m \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x8370\u001b[93m\u001b[0m\n",
"\u001b[30m0x00008360\u001b[0m \u001b[96mbd\u001b[96ma9\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008363\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008365\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008368\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000836b\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000836c\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000836d\u001b[0m \u001b[96mc0\u001b[96m06\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x06\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000836f\u001b[0m \u001b[34m00\u001b[96md0\u001b[0m \u001b[31mbrk\u001b[96m \u001b[33m0xd0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008371\u001b[0m \u001b[96mee\u001b[0m \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x8388\u001b[93m\u001b[0m\n",
"\u001b[30m0x00008378\u001b[0m \u001b[96mbd\u001b[96ma9\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000837b\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000837d\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008380\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008383\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008384\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008385\u001b[0m \u001b[96mc0\u001b[96m05\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x05\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008387\u001b[0m \u001b[34m00\u001b[96md0\u001b[0m \u001b[31mbrk\u001b[96m \u001b[33m0xd0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008389\u001b[0m \u001b[96mee\u001b[0m \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x83a0\u001b[93m\u001b[0m\n",
"\u001b[30m0x00008390\u001b[0m \u001b[96mbd\u001b[96ma9\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008393\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008395\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008398\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000839b\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000839c\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000839d\u001b[0m \u001b[96mc0\u001b[96m05\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x05\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000839f\u001b[0m \u001b[34m00\u001b[96md0\u001b[0m \u001b[31mbrk\u001b[96m \u001b[33m0xd0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000083a1\u001b[0m \u001b[96mee\u001b[0m \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x83b8\u001b[93m\u001b[0m\n",
"\u001b[30m0x000083a8\u001b[0m \u001b[96mbd\u001b[96ma9\u001b[96m88\u001b[0m \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000083ab\u001b[0m \u001b[96m29\u001b[96m3f\u001b[0m \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000083ad\u001b[0m \u001b[96m8d\u001b[96m18\u001b[96m21\u001b[0m \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000083b0\u001b[0m \u001b[96m9c\u001b[96m19\u001b[96m21\u001b[0m \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000083b3\u001b[0m \u001b[96mc8\u001b[0m \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000083b4\u001b[0m \u001b[96me8\u001b[0m \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000083b5\u001b[0m \u001b[96mc0\u001b[96m0a\u001b[0m \u001b[36mcpy\u001b[96m #\u001b[33m0x0a\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000083b7\u001b[0m \u001b[34m00\u001b[96md0\u001b[0m \u001b[31mbrk\u001b[96m \u001b[33m0xd0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000083b9\u001b[0m \u001b[96mee\u001b[0m \u001b[31minvalid\u001b[0m\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"e asm.lines = false\n",
"pdb @@=`pdf @@ fcn.* ~ flagflag[0]`\n",
"e asm.lines = true\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "aac942ca-9ad1-4c8e-a66b-2dfaaf4c57d9",
"metadata": {},
"source": [
"We recognize this pattern from before; multiple loads into the same `flagflag` buffer. This time using lenghts 5, 6, 5, 5, 10. But we don't have the offsets yet.\n",
"\n",
"To get the offsets we need to look 'backwards' a bit from those locations to see what is loaded into the index register `x` before these loops. \n",
"\n",
"It's not possible (maybe?) to put together a `r2` command tha does temporary seek `@` _and_ iteration `@@` because iteration uses temp seek. Lucky for us we are already in a python environment with r2pipe so we can just write some crappy python:"
]
},
{
"cell_type": "code",
"execution_count": 57,
"id": "5300fd9a-ea58-4ba8-83e1-446f05776992",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x00008342 a200 \u001b[36mldx\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008344 00a0 \u001b[31mbrk\u001b[96m \u001b[33m0xa0\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008346 0000 \u001b[31mbrk\u001b[96m \u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x8358\u001b[93m\u001b[0m\n",
"0x00008348 bda988 \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000834b 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000834d 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008350 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008353 c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008354 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008355 c005 \u001b[36mcpy\u001b[96m #\u001b[33m0x05\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"0x0000835a ae0014 \u001b[36mldx\u001b[96m \u001b[33m0x1400\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000835d a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000835f ~ 00bd \u001b[31mbrk\u001b[96m \u001b[33m0xbd\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x8370\u001b[93m\u001b[0m\n",
"0x00008360 bda988 \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008363 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008365 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008368 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000836b c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000836c e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000836d c006 \u001b[36mcpy\u001b[96m #\u001b[33m0x06\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"0x00008372 ae0414 \u001b[36mldx\u001b[96m \u001b[33m0x1404\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008375 a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008377 ~ 00bd \u001b[31mbrk\u001b[96m \u001b[33m0xbd\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x8388\u001b[93m\u001b[0m\n",
"0x00008378 bda988 \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000837b 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000837d 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008380 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008383 c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008384 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008385 c005 \u001b[36mcpy\u001b[96m #\u001b[33m0x05\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"0x0000838a ae0814 \u001b[36mldx\u001b[96m \u001b[33m0x1408\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000838d a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000838f ~ 00bd \u001b[31mbrk\u001b[96m \u001b[33m0xbd\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x83a0\u001b[93m\u001b[0m\n",
"0x00008390 bda988 \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008393 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008395 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"0x00008398 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000839b c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000839c e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"0x0000839d c005 \u001b[36mcpy\u001b[96m #\u001b[33m0x05\u001b[0m\u001b[0m\u001b[0m\n",
"\n",
"0x000083a2 ae0c14 \u001b[36mldx\u001b[96m \u001b[33m0x140c\u001b[0m\u001b[0m\u001b[0m\n",
"0x000083a5 a000 \u001b[36mldy\u001b[96m #\u001b[93m0x00\u001b[0m\u001b[0m\u001b[0m\n",
"0x000083a7 ~ 00bd \u001b[31mbrk\u001b[96m \u001b[33m0xbd\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x83b8\u001b[93m\u001b[0m\n",
"0x000083a8 bda988 \u001b[36mlda\u001b[96m flagflag\u001b[0m,\u001b[96mx\u001b[0m\u001b[0m\u001b[0m\n",
"0x000083ab 293f \u001b[34mand\u001b[96m #\u001b[33m0x3f\u001b[0m\u001b[0m\u001b[0m\n",
"0x000083ad 8d1821 \u001b[36msta\u001b[96m \u001b[33m0x2118\u001b[0m\u001b[0m\u001b[0m\n",
"0x000083b0 9c1921 \u001b[36mstz\u001b[96m \u001b[33m0x2119\u001b[0m\u001b[0m\u001b[0m\n",
"0x000083b3 c8 \u001b[96miny\u001b[0m\u001b[0m\u001b[0m\n",
"0x000083b4 e8 \u001b[96minx\u001b[0m\u001b[0m\u001b[0m\n",
"0x000083b5 c00a \u001b[36mcpy\u001b[96m #\u001b[33m0x0a\u001b[0m\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"# BUG: you need to `pd` the whole block to correctly disassemble the ldx,ldy and or the and instruction. _not_ doing 'pd' first will result in one or the other not disassembling properly.\n",
"r.cmd(\"pd > /dev/null\")\n",
"\n",
"r.cmd(\"e asm.lines = false\")\n",
"for l in r.cmd(\"pdf @@ fcn.* ~flagflag,0x88a9\").splitlines():\n",
" x = l.split(' ')[0]\n",
" r.cmd(\"s %s\\n\" % x)\n",
" r2cmd(r, \"pd 10 @ -6\")\n",
"_ = r.cmd(\"e asm.lines = true\")"
]
},
{
"cell_type": "markdown",
"id": "5fbee896-e040-409a-b5e0-b1bd31fde917",
"metadata": {},
"source": [
"We can see from the above that like sequence_1 this ROM loads offsets into the flag buffer from some globals -- we called them `_pressed_cache` in sequence_1. For sequence_2 these cache register globals are at `0x1400`, `0x1404`, `0x1408`, and `0x140c`.\n",
"\n",
"We need to keep reversing backwards to see what the correct values for these registers should be."
]
},
{
"cell_type": "code",
"execution_count": 58,
"id": "9423601b-ea27-4ab1-b860-9e30a08c18c5",
"metadata": {},
"outputs": [],
"source": [
"r2cmd(r, \"\"\"\n",
"f+ unk1_pressed_cache @ 0x1400\n",
"f+ unk2_pressed_cache @ 0x1404\n",
"f+ unk3_pressed_cache @ 0x1408\n",
"f+ unk4_pressed_cache @ 0x140c\n",
"\"\"\")\n",
"r2cmd(r,\"\"\"\n",
"e asm.lines=false\n",
"CCu unk1_pressed_cache @@=`pdf @@ fcn.* ~0x1400[0] | sort -u`\n",
"CCu unk2_pressed_cache @@=`pdf @@ fcn.* ~0x1404[0] | sort -u`\n",
"CCu unk3_pressed_cache @@=`pdf @@ fcn.* ~0x1408[0] | sort -u`\n",
"CCu unk4_pressed_cache @@=`pdf @@ fcn.* ~0x140c[0] | sort -u`\n",
"e asm.lines=true\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "6af6c293-8005-4b96-a713-531c63cabade",
"metadata": {},
"source": [
"We'll disassemble all the functions and grep for the locations we're interested in (following the same pattern of grepping all function disassembly again)."
]
},
{
"cell_type": "code",
"execution_count": 59,
"id": "eb330ea0-4791-4dd6-a91b-279356c2e2f8",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"│ ╎ 0x00008035 9c0014 stz 0x1400 ; unk1_pressed_cache\n",
"│ ╎ 0x00008038 9c0414 stz 0x1404 ; unk2_pressed_cache\n",
"│ ╎ 0x0000803b 9c0814 stz 0x1408 ; unk3_pressed_cache\n",
"│ ╎ 0x0000803e 9c0c14 stz 0x140c ; unk4_pressed_cache\n",
"│ └──> 0x000083c4 c230 rep #0x30 ; unk4_pressed_cache\n",
"│ ────────> 0x0000824f ad0014 lda 0x1400 ; unk1_pressed_cache\n",
"│ ────────> 0x0000827c 8e0014 stx 0x1400 ; unk1_pressed_cache\n",
"│ ────────> 0x00008287 ad0414 lda 0x1404 ; unk2_pressed_cache\n",
"│ ╎│└─────> 0x000082b6 8e0414 stx 0x1404 ; unk2_pressed_cache\n",
"│ └──────> 0x000082c1 ad0814 lda 0x1408 ; unk3_pressed_cache\n",
"│ │││╎╎╎ 0x000082e7 8e0814 stx 0x1408 ; unk3_pressed_cache\n",
"│ └─────> 0x00008305 ad0c14 lda 0x140c ; unk4_pressed_cache\n",
"│ ││└───> 0x00008331 8e0c14 stx 0x140c ; unk4_pressed_cache\n",
"│ ╎ 0x0000835a ae0014 ldx 0x1400 ; unk1_pressed_cache\n",
"│ ╎ 0x00008372 ae0414 ldx 0x1404 ; unk2_pressed_cache\n",
"│ ╎ 0x0000838a ae0814 ldx 0x1408 ; unk3_pressed_cache\n",
"│ ╎ 0x000083a2 ae0c14 ldx 0x140c ; unk4_pressed_cache\n",
"│ 0x0003bcd8 dfc00414 cmp 0x1404c0,x ; unk2_pressed_cache\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"pdf @@ fcn.* ~_pressed_cache\")"
]
},
{
"cell_type": "markdown",
"id": "92ee6ca6-7a98-4af0-98b1-0a075a712273",
"metadata": {},
"source": [
"Recall from sequence_1 that there was initialization with `stz` instructions and also checks of current state with `lda` or `ldx` instructions. Since we're hunting backwards for the offset values that will be looked up in the flag buffer we want to know what is stored in the cache globals: So the `stx` instructions are the only parts we're interested in."
]
},
{
"cell_type": "code",
"execution_count": 60,
"id": "82c53c5e-a289-4fed-8d88-92f78edf70f6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"│ ────────> 0x0000827c 8e0014 stx 0x1400 ; unk1_pressed_cache\n",
"│ ╎│└─────> 0x000082b6 8e0414 stx 0x1404 ; unk2_pressed_cache\n",
"│ │││╎╎╎ 0x000082e7 8e0814 stx 0x1408 ; unk3_pressed_cache\n",
"│ ││└───> 0x00008331 8e0c14 stx 0x140c ; unk4_pressed_cache\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"pdf @@ fcn.* ~_pressed_cache|grep stx\")"
]
},
{
"cell_type": "markdown",
"id": "bc806bb6-da73-4352-a2e7-0ff5a54e3914",
"metadata": {},
"source": [
"Let's look at each ebb with the `stx` and also the ebb before it too -- to see what tests are being performed before writes to the globals."
]
},
{
"cell_type": "code",
"execution_count": 61,
"id": "ba9f2a0a-4d40-4970-baa0-28ad48ec1e8c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x8266\u001b[93m\u001b[0m\n",
"\u001b[30m0x0000826c\u001b[0m \u001b[96mad\u001b[96m24\u001b[96m14\u001b[0m \u001b[36mlda\u001b[96m \u001b[33m0x1424\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x0000826f\u001b[0m \u001b[96maa\u001b[0m \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008270\u001b[0m \u001b[96m49\u001b[96m40\u001b[0m \u001b[34meor\u001b[96m #\u001b[33m0x40\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008272\u001b[0m \u001b[96mf0\u001b[96m08\u001b[0m \u001b[31mbeq\u001b[96m \u001b[33m0x00827c\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x8272\u001b[93m\u001b[0m\n",
"\u001b[30m0x0000827c\u001b[0m \u001b[96m8e\u001b[34m00\u001b[96m14\u001b[0m \u001b[36mstx\u001b[96m \u001b[93m0x1400\u001b[0m\u001b[0m\u001b[0m \u001b[33m; unk1_pressed_cache\u001b[0m\n",
"\u001b[30m0x0000827f\u001b[0m \u001b[96m4c\u001b[96m5f\u001b[96m81\u001b[0m \u001b[33mjmp 0x815f\u001b[0m\u001b[0m\n",
"\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x829e\u001b[93m\u001b[0m\n",
"\u001b[30m0x000082a4\u001b[0m \u001b[96mad\u001b[96m14\u001b[96m14\u001b[0m \u001b[36mlda\u001b[96m \u001b[33m0x1414\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000082a7\u001b[0m \u001b[96m49\u001b[96m71\u001b[0m \u001b[34meor\u001b[96m #\u001b[33m0x71\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000082a9\u001b[0m \u001b[96maa\u001b[0m \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000082aa\u001b[0m \u001b[96m49\u001b[96mf1\u001b[0m \u001b[34meor\u001b[96m #\u001b[33m0xf1\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x000082ac\u001b[0m \u001b[96mf0\u001b[96m08\u001b[0m \u001b[31mbeq\u001b[96m \u001b[33m0x0082b6\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x82ac\u001b[93m\u001b[0m\n",
"\u001b[30m0x000082b6\u001b[0m \u001b[96m8e\u001b[96m04\u001b[96m14\u001b[0m \u001b[36mstx\u001b[96m \u001b[93m0x1404\u001b[0m\u001b[0m\u001b[0m \u001b[33m; unk2_pressed_cache\u001b[0m\n",
"\u001b[30m0x000082b9\u001b[0m \u001b[96m4c\u001b[96m7a\u001b[96m81\u001b[0m \u001b[33mjmp 0x817a\u001b[0m\u001b[0m\n",
"\n",
"\u001b[30m0x000082e7\u001b[0m \u001b[96m8e\u001b[96m08\u001b[96m14\u001b[0m \u001b[36mstx\u001b[96m \u001b[93m0x1408\u001b[0m\u001b[0m\u001b[0m \u001b[33m; unk3_pressed_cache\u001b[0m\n",
"\u001b[30m0x000082ea\u001b[0m \u001b[96m4c\u001b[96m95\u001b[96m81\u001b[0m \u001b[33mjmp 0x8195\u001b[0m\u001b[0m\n",
"\u001b[30m0x000082e7\u001b[0m \u001b[96m8e\u001b[96m08\u001b[96m14\u001b[0m \u001b[36mstx\u001b[96m \u001b[93m0x1408\u001b[0m\u001b[0m\u001b[0m \u001b[33m; unk3_pressed_cache\u001b[0m\n",
"\u001b[30m0x000082ea\u001b[0m \u001b[96m4c\u001b[96m95\u001b[96m81\u001b[0m \u001b[33mjmp 0x8195\u001b[0m\u001b[0m\n",
"\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x8319\u001b[93m\u001b[0m\n",
"\u001b[30m0x0000831f\u001b[0m \u001b[96mad\u001b[96m14\u001b[96m14\u001b[0m \u001b[36mlda\u001b[96m \u001b[33m0x1414\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008322\u001b[0m \u001b[96m18\u001b[0m \u001b[31mclc\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008323\u001b[0m \u001b[96m6a\u001b[0m \u001b[34mror\u001b[96m a\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008324\u001b[0m \u001b[96maa\u001b[0m \u001b[34mtax\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008325\u001b[0m \u001b[96m49\u001b[96m20\u001b[0m \u001b[34meor\u001b[96m #\u001b[33m0x20\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[30m0x00008327\u001b[0m \u001b[96mf0\u001b[96m08\u001b[0m \u001b[31mbeq\u001b[96m \u001b[33m0x008331\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x8327\u001b[93m\u001b[0m\n",
"\u001b[30m0x00008331\u001b[0m \u001b[96m8e\u001b[96m0c\u001b[96m14\u001b[0m \u001b[36mstx\u001b[96m \u001b[93m0x140c\u001b[0m\u001b[0m\u001b[0m \u001b[33m; unk4_pressed_cache\u001b[0m\n",
"\u001b[30m0x00008334\u001b[0m \u001b[96m4c\u001b[96mb0\u001b[96m81\u001b[0m \u001b[33mjmp 0x81b0\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r.cmd(\"e asm.lines = false\")\n",
"for l in r.cmd(\"pdf @@ fcn.* ~_pressed_cache|grep stx\").splitlines():\n",
" x = l.split(' ')[0]\n",
" r.cmd(\"s %s\" % x)\n",
" r2cmd(r, \"\"\"\n",
" sb\n",
" pdb @ `axt~[1]`; pdb;\n",
" \"\"\")\n",
"_=r.cmd(\"e asm.lines = true\")"
]
},
{
"cell_type": "markdown",
"id": "bc1ccd97-03c1-43dd-a323-38c2f4db71ac",
"metadata": {},
"source": [
"There is a problem using the `pdb` at prev and current ebb technique for the `unk3_pressed_cache`. Let's try using the `pd 10 @ -6` thing again."
]
},
{
"cell_type": "code",
"execution_count": 62,
"id": "d1daff8c-55d0-4a7a-a4c3-9096e93e8b27",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x000082e1 14aa \u001b[31mtrb\u001b[96m \u001b[33m0xaa\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[36m╎\u001b[0m 0x000082e3 49a0 \u001b[34meor\u001b[96m #\u001b[33m0xa0\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082e5 d007 \u001b[31mbne\u001b[96m \u001b[33m0x0082ee\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m╎\u001b[0m 0x000082e7 8e0814 \u001b[36mstx\u001b[96m \u001b[93m0x1408\u001b[0m\u001b[0m\u001b[0m \u001b[33m; unk3_pressed_cache\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m\u001b[36m└\u001b[0m\u001b[36m─\u001b[0m\u001b[36m<\u001b[0m 0x000082ea 4c9581 \u001b[33mjmp 0x8195\u001b[0m\u001b[0m\n",
" \u001b[31m│\u001b[0m 0x000082ed 60 \u001b[31mrts\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m \u001b[93m\u001b[93m; CODE XREF from fcn.000081e5 @ \u001b[93m0x82e5\u001b[93m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m└\u001b[0m\u001b[31m─\u001b[0m\u001b[31m─\u001b[0m\u001b[31m>\u001b[0m 0x000082ee ad2814 \u001b[36mlda\u001b[96m \u001b[33m0x1428\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m 0x000082f1 29ff \u001b[34mand\u001b[96m #\u001b[33m0xff\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m┌\u001b[0m\u001b[31m─\u001b[0m\u001b[31m<\u001b[0m 0x000082f3 f00b \u001b[31mbeq\u001b[96m \u001b[33m0x008300\u001b[0m\u001b[0m\u001b[0m\n",
"\u001b[93m│\u001b[0m \u001b[31m│\u001b[0m 0x000082f5 ad1814 \u001b[36mlda\u001b[96m \u001b[33m0x1418\u001b[0m\u001b[0m\u001b[0m\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"s 0x000082e7\n",
"pd 10 @ -6\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "7f94f881-9493-4f4a-bdb0-d7863167ecb8",
"metadata": {},
"source": [
"Which finally gets us all the pieces of info we need.\n",
"\n",
"Looking at the tests above we can see what the required values for the `unk*_pressed_cache` globals are:\n",
"* 0x1400: 0x40\n",
"* 0x1404: 0xf1\n",
"* 0x1408: 0xa0\n",
"* 0x140c: 0x20\n",
"\n",
"Then, recall that the flag-segments function pulls lenghts 5, 6, 5, 5, 10 from those offsets. And we can print the flag:"
]
},
{
"cell_type": "code",
"execution_count": 63,
"id": "af331eab-d688-43c8-9674-7d1dd02bea08",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"FLAG-\n",
"\n",
"QYR88W\n",
"\n",
"NDGBW\n",
"\n",
"7HP3G\n",
"\n",
"XRGW49GE5W\n",
"\n"
]
}
],
"source": [
"r2cmd(r, \"\"\"\n",
"s flagflag\n",
"ps 5\n",
"ps 6 @ +0x40\n",
"ps 5 @ +0xf1\n",
"ps 5 @ +0xa0\n",
"ps 10 @ +0x20\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "e32f8b14-e6ae-4673-afb6-0231c4a347ef",
"metadata": {},
"source": [
"No flag glory pictures this time -- never ran it. Don't need to ( •_•)>⌐■-■"
]
},
{
"cell_type": "markdown",
"id": "06c137c7-a32b-4bcf-a5e0-d4096f03f153",
"metadata": {},
"source": [
"# Conclusion\n",
"\n",
"We covered alot of `r2` and some SNES. I hope you had fun! I sure did during the CTF and in putting this together. \n",
"\n",
"Let's not forget that it is thanks to Zack Deveau who made these two challenges (He also made my favorite nsec 2020 challenge which was a dreamcast GD-ROM image -- but that's another story).\n",
"\n",
"## Concept Summary\n",
"\n",
"| | |\n",
"|-|-|\n",
"| grepping | `~` |\n",
"| case insensitive grepping | `~+` |\n",
"| grep sorting | `~$` |\n",
"| grep column selecting | `~[0]` |\n",
"| iterating flag matches | `@@ glob` |\n",
"| iterating command output | `@@=` |\n",
"| iterating file content | `@@.` |\n",
"| print hexidecimal | `?v` |\n",
"| seek to function start | `sf.` |\n",
"| seek to EBB start | `sb` |\n",
"| current seek | `$$` |\n",
"| current EBB start | `$Fb` |\n",
"| current function start | `$FB` |\n",
"| current EBB 'true' / jump destination | `$Fj` |\n",
"| current EBB 'false' destination | `$Ff` |\n",
"| temporary seek | `@` |\n",
"| comment | `CC` `CCu` |\n",
"| disassemble function | `pdf` |\n",
"| disassemble EBB | `pdb` |\n",
"| recursive disassemble from current seek | `pdr.` |\n",
"| diassemble a few instructions | `pd` |\n",
"| search | `/` |\n",
"| print some bytes in ascii | `ps` |\n",
"| configuration variables | `e` | \n",
"| no jump lines from disassembly printer | `e asm.lines = false` |\n",
"\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment