Skip to content

Instantly share code, notes, and snippets.

@pleonex
Last active December 12, 2023 10:16
Show Gist options
  • Save pleonex/4d5761b9dfc3ed6e111020021e31568a to your computer and use it in GitHub Desktop.
Save pleonex/4d5761b9dfc3ed6e111020021e31568a to your computer and use it in GitHub Desktop.
Test using Jupyter Notebooks and VS Code Polyglot extension to create a Yarhl converter
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Digamos que tenemos un fichero que queremos probar... usando Yarhl"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"const string FilePath = @\"C:\\Users\\benit\\source\\repos\\reverse_engineering\\games\\PokemonConquest\\AmbitionConquest\\GameData\\root\\rom\\data\\Pokemon.dat\";"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"¡Vamos a usar Yarhl!\n",
"Como todavía no he sacado la release, tenemos que usar el _feed Preview_:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [
{
"data": {
"text/html": [
"<div><div><strong>Restore sources</strong><ul><li><span>https://pkgs.dev.azure.com/SceneGate/SceneGate/_packaging/SceneGate-Preview/nuget/v3/index.json</span></li></ul></div><div></div><div><strong>Installed Packages</strong><ul><li><span>Yarhl, 4.0.0-preview.283</span></li></ul></div></div>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#i \"nuget:https://pkgs.dev.azure.com/SceneGate/SceneGate/_packaging/SceneGate-Preview/nuget/v3/index.json\"\n",
"#r \"nuget:Yarhl, 4.0.0-preview.283\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lo primero es ver su contenido binario en formato hexadecimal...\n",
"Tengo por aquí una _pequeña_ función que muestra una parte del fichero en hexadecimal... Sería interesante añadirla a Yarhl."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"static string DumpStreamToHexString(System.IO.Stream stream, long startPosition, int length)\n",
"{\n",
" const int BytesPerRow = 0x10;\n",
" const char horizontalBar = '─'; // or '|' for non-Unicode terminals\n",
" const char verticalBar = '│'; // or '-' for non-Unicode terminals\n",
" const char crossBar = '┼'; // or '|' for non-Unicode terminals\n",
"\n",
" byte[] buffer = new byte[length];\n",
" int read = stream.Read(buffer);\n",
"\n",
" var content = new StringBuilder();\n",
" var textLineBuilder = new StringBuilder();\n",
"\n",
" // Header\n",
" content.AppendFormat(\"Offset {0} \", verticalBar);\n",
" for (int i = 0; i < BytesPerRow; i++) {\n",
" content.AppendFormat(\"{0:X2} \", i);\n",
" }\n",
"\n",
" content.AppendFormat(\"{0} ASCII\\n\", verticalBar);\n",
" content.Append(new string(horizontalBar, 9));\n",
" content.Append(crossBar);\n",
" content.Append(new string(horizontalBar, 1 + (BytesPerRow * 3)));\n",
" content.Append(crossBar);\n",
" content.AppendLine(new string(horizontalBar, 1 + (BytesPerRow * 2)));\n",
"\n",
" // For each line: offset, hex content and text content\n",
" content.AppendFormat(\"{0:X8} {1} \", startPosition, verticalBar);\n",
" for (int i = 0; i < read; i++) {\n",
" char ch = (buffer[i] >= 0x21 && buffer[i] <= 0x7F) ? (char)buffer[i] : '.';\n",
" textLineBuilder.AppendFormat(\"{0} \", ch);\n",
"\n",
" if (i != 0 && ((i + 1) % BytesPerRow == 0)) {\n",
" content.AppendFormat(\"{0:X2} {2} {1}\\n\", buffer[i], textLineBuilder.ToString(), verticalBar);\n",
" content.AppendFormat(\"{0:X8} {1} \", startPosition + (i + 1), verticalBar);\n",
" textLineBuilder.Clear();\n",
" } else {\n",
" content.AppendFormat(\"{0:X2} \", buffer[i]);\n",
" }\n",
" }\n",
"\n",
" return content.ToString();\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Offset │ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F │ ASCII\n",
"─────────┼─────────────────────────────────────────────────┼─────────────────────────────────\r\n",
"00000000 │ 45 65 76 65 65 00 00 00 00 00 00 2D DC 64 02 45 │ E e v e e . . . . . . - . d . E \n",
"00000010 │ 73 DC 31 07 E0 17 F8 0F 5B 34 20 51 FF FF FF 27 │ s . 1 . . . . . [ 4 . Q . . . ' \n",
"00000020 │ 00 30 40 21 00 00 00 00 00 00 00 00 33 00 00 00 │ . 0 @ ! . . . . . . . . 3 . . . \n",
"00000030 │ 56 61 70 6F 72 65 6F 6E 00 00 00 2D 72 5D 22 49 │ V a p o r e o n . . . - r ] \" I \n",
"00000040 │ E1 7C 72 08 E2 7B F8 0F 02 C0 58 50 62 FE FF 27 │ . | r . . { . . . . X P b . . ' \n",
"00000050 │ 78 C5 AB 21 00 00 00 00 00 00 00 00 B9 00 00 00 │ x . . ! . . . . . . . . . . . . \n",
"00000060 │ 4A 6F 6C 74 65 6F 6E 00 00 00 00 2D F0 5C 02 49 │ J o l t e o n . . . . - . \\ . I \n",
"00000070 │ E1 7C 92 10 E3 8F F8 0F 5B 82 5C 50 63 FE FF 27 │ . | . . . . . . [ . \\ P c . . ' \n",
"00000080 │ "
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"using Yarhl.IO;\n",
"\n",
"BinaryFormat binary = new BinaryFormat(FilePath, FileOpenMode.Read);\n",
"display(DumpStreamToHexString(binary.Stream, 0, 0x80));"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"¡Sugoiiii!\n",
"Ahora definamos el formato para nuestro fichero."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"using System.Collections.ObjectModel;\n",
"using Yarhl.FileFormat;\n",
"\n",
"public class PokemonList : IFormat\n",
"{\n",
" public PokemonList()\n",
" {\n",
" Pokemons = new Collection<PokemonInfo>();\n",
" }\n",
"\n",
" public static int Count => 200;\n",
"\n",
" public static int MetadataSize => 0xB8;\n",
"\n",
" public Collection<PokemonInfo> Pokemons { get; }\n",
"\n",
" public byte[] Metadata { get; set; }\n",
"}\n",
"\n",
"public class PokemonInfo\n",
"{\n",
" public PokemonInfo(string name) => Name = name;\n",
"\n",
" public static int MaxNameLength => 0x0B;\n",
"\n",
" public static int MetadataSize => 0x25;\n",
"\n",
" public string Name { get; }\n",
"\n",
" public byte[] Metadata { get; set; }\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sencillo, ¿no?\n",
"Ahora el conversor:\n",
"```mermaid\n",
"flowchart LR\n",
" source(BinaryFormat) -->|Binary2PokemonList| dest(PokemonList)\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"public class Binary2PokemonList : IConverter<IBinary, PokemonList>\n",
"{\n",
" public PokemonList Convert(IBinary source)\n",
" {\n",
" ArgumentNullException.ThrowIfNull(source);\n",
"\n",
" var list = new PokemonList();\n",
"\n",
" source.Stream.Position = 0;\n",
" var reader = new DataReader(source.Stream) {\n",
" DefaultEncoding = Encoding.GetEncoding(\"shift_jis\"),\n",
" };\n",
"\n",
" for (int i = 0; i < PokemonList.Count; i++) {\n",
" string name = reader.ReadString(PokemonInfo.MaxNameLength).Replace(\"\\0\", string.Empty);\n",
" var pokemon = new PokemonInfo(name) {\n",
" Metadata = reader.ReadBytes(PokemonInfo.MetadataSize),\n",
" };\n",
"\n",
" list.Pokemons.Add(pokemon);\n",
" }\n",
"\n",
" list.Metadata = reader.ReadBytes(PokemonList.MetadataSize);\n",
"\n",
" return list;\n",
" }\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"¡Probemos el resultado!"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [
{
"data": {
"text/html": [
"<details open=\"open\" class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonList</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Pokemons</td><td><table><thead><tr><th><i>index</i></th><th>value</th></tr></thead><tbody><tr><td>0</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Eevee</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 220, 100, 2, 69, 115, 220, 49, 7, 224, 23, 248, 15, 91, 52, 32, 81, 255, 255, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>1</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Vaporeon</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 114, 93, 34, 73, 225, 124, 114, 8, 226, 123, 248, 15, 2, 192, 88, 80, 98, 254, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>2</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Jolteon</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 240, 92, 2, 73, 225, 124, 146, 16, 227, 143, 248, 15, 91, 130, 92, 80, 99, 254, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>3</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Flareon</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 240, 92, 2, 73, 9, 189, 114, 8, 225, 59, 248, 15, 46, 190, 84, 80, 97, 254, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>4</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Espeon</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 240, 80, 33, 73, 9, 125, 18, 14, 234, 63, 249, 15, 1, 56, 88, 81, 70, 254, 43 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>5</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Umbreon</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 44, 81, 1, 73, 135, 212, 115, 8, 239, 183, 249, 15, 99, 116, 116, 80, 70, 254, 63 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>6</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Leafeon</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 240, 72, 1, 73, 225, 28, 51, 140, 228, 175, 248, 15, 97, 56, 212, 80, 94, 254, 19 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>7</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Glaceon</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 240, 68, 1, 73, 9, 69, 115, 8, 229, 195, 248, 15, 3, 128, 136, 80, 91, 254, 23 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>8</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Ralts</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 235, 166, 100, 2, 69, 95, 4, 81, 5, 234, 55, 249, 15, 28, 52, 88, 81, 255, 255, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>9</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Kirlia</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 120, 186, 68, 2, 73, 135, 124, 145, 6, 234, 75, 249, 15, 28, 52, 88, 81, 44, 254, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>10</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Gardevoir</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 246, 68, 2, 77, 255, 228, 82, 10, 234, 83, 249, 15, 28, 52, 64, 81, 75, 254, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>11</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Gallade</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 246, 156, 1, 73, 255, 228, 82, 10, 202, 76, 249, 15, 27, 196, 172, 80, 105, 254, 3 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>12</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Magikarp</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 255, 150, 100, 6, 73, 25, 60, 81, 10, 226, 3, 248, 15, 48, 158, 144, 81, 255, 255, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>13</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Gyarados</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 45, 44, 69, 42, 81, 255, 220, 114, 10, 34, 117, 248, 15, 76, 154, 140, 80, 16, 254, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>14</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Pichu</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 190, 150, 100, 2, 65, 75, 220, 208, 7, 227, 127, 248, 15, 32, 158, 12, 81, 255, 255, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>15</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Pikachu</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 150, 180, 80, 2, 69, 105, 44, 145, 11, 227, 143, 248, 15, 32, 144, 100, 80, 50, 254, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>16</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Raichu</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 75, 230, 92, 2, 73, 185, 44, 210, 12, 227, 155, 248, 15, 32, 56, 100, 80, 99, 254, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>17</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Wooper</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 255, 220, 100, 34, 69, 55, 44, 49, 2, 2, 101, 248, 15, 48, 88, 88, 80, 255, 255, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>18</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Quagsire</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 90, 44, 65, 34, 73, 175, 108, 178, 4, 2, 25, 249, 15, 99, 88, 88, 80, 94, 254, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>19</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>Submission#10+PokemonInfo</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Name</td><td><div class=\"dni-plaintext\"><pre>Igglybuff</pre></div></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 170, 34, 101, 2, 65, 65, 156, 48, 2, 224, 7, 248, 15, 73, 158, 64, 81, 255, 255, 255 ... (17 more) ]</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td colspan=\"2\"><i>(180 more)</i></td></tr></tbody></table></td></tr><tr><td>Metadata</td><td><div class=\"dni-plaintext\"><pre>[ 20, 32, 129, 16, 3, 11, 132, 16, 20, 160, 65, 16, 68, 224, 129, 13, 4, 161, 56, 16 ... (164 more) ]</pre></div></td></tr></tbody></table></div></details><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"var converter = new Binary2PokemonList();\n",
"PokemonList output = converter.Convert(binary);\n",
"\n",
"display(output);"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.11.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment