diff --git a/build-tools.ps1 b/build-tools.ps1 index 3acef7d..5d73e18 100644 --- a/build-tools.ps1 +++ b/build-tools.ps1 @@ -5,3 +5,5 @@ $pwd = $pwd.Path if ($LASTEXITCODE -ne 0) { exit -1 } & dotnet build tools/RenderCastRoll -o "$([IO.Path]::Combine($pwd, "bin/RenderCastRoll"))" if ($LASTEXITCODE -ne 0) { exit -1 } +& dotnet build tools/RenderStaffCredits -o "$([IO.Path]::Combine($pwd, "bin/RenderStaffCredits"))" +if ($LASTEXITCODE -ne 0) { exit -1 } diff --git a/build.ps1 b/build.ps1 index 863bea9..6d5f70c 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,16 +1,17 @@ [Environment]::CurrentDirectory = (Get-Location -PSProvider FileSystem).ProviderPath #Region Variables -$input_rom_file = "bin/m12fresh.gba" -$output_rom_file = "bin/m12.gba" -$eb_rom_file = "bin/eb.smc" -$working_dir = "working" -$src_dir = "src" -$data_dir = "src/data" -$cast_roll_file = "working/cast_roll.json" -$compiled_asm_file = "src/m2-compiled.asm" -$includes_asm_file = "m12-includes.asm" # implicitly rooted in working_dir -$hack_asm_file = "m2-hack.asm" # implicitly rooted in src_dir +$input_rom_file = "bin/m12fresh.gba" +$output_rom_file = "bin/m12.gba" +$eb_rom_file = "bin/eb.smc" +$working_dir = "working" +$src_dir = "src" +$data_dir = "src/data" +$cast_roll_file = "working/cast_roll.json" +$staff_credits_file = "working/staff_text.md" +$compiled_asm_file = "src/m2-compiled.asm" +$includes_asm_file = "m12-includes.asm" # implicitly rooted in working_dir +$hack_asm_file = "m2-hack.asm" # implicitly rooted in src_dir $input_c_files = "src/c/ext.c", @@ -25,18 +26,19 @@ $input_c_files = "src/c/psi.c", "src/c/luminehall.c" -$base_c_address = 0x83755B8; -$scripttool_cmd = "bin/ScriptTool/ScriptTool.dll" -$rendercastroll_cmd= "bin/RenderCastRoll/RenderCastRoll.dll" -$gcc_cmd = "arm-none-eabi-gcc" -$ld_cmd = "arm-none-eabi-ld" -$objdump_cmd = "arm-none-eabi-objdump" -$readelf_cmd = "arm-none-eabi-readelf" -$combined_obj_file = "src/c/combined.o" -$linked_obj_file = "src/c/linked.o" -$combine_script = "src/c/combine.ld" -$link_script = "src/c/link.ld" -$undefine_obj_file = "src/c/ext.o" +$base_c_address = 0x83755B8; +$scripttool_cmd = "bin/ScriptTool/ScriptTool.dll" +$rendercastroll_cmd = "bin/RenderCastRoll/RenderCastRoll.dll" +$renderstaffcredits_cmd = "bin/RenderStaffCredits/RenderStaffCredits.dll" +$gcc_cmd = "arm-none-eabi-gcc" +$ld_cmd = "arm-none-eabi-ld" +$objdump_cmd = "arm-none-eabi-objdump" +$readelf_cmd = "arm-none-eabi-readelf" +$combined_obj_file = "src/c/combined.o" +$linked_obj_file = "src/c/linked.o" +$combine_script = "src/c/combine.ld" +$link_script = "src/c/link.ld" +$undefine_obj_file = "src/c/ext.o" If ($IsWindows) { $asm_cmd = "bin/armips.exe" } ElseIf ($IsLinux -or $IsMacOS) { $asm_cmd = "bin/armips" } @@ -56,6 +58,10 @@ $scripttool_args = $rendercastroll_args = $cast_roll_file, $data_dir + +$renderstaffcredits_args = + $staff_credits_file, + $data_dir $gcc_args = "-c", @@ -360,6 +366,10 @@ if ($LASTEXITCODE -ne 0) { exit -1 } & dotnet $rendercastroll_cmd $rendercastroll_args if ($LASTEXITCODE -ne 0) { exit -1 } +"Pre-rendering staff credits..." +& dotnet $renderstaffcredits_cmd $renderstaffcredits_args +if ($LASTEXITCODE -ne 0) { exit -1 } + # ------------------------ ASSEMBLE GAME TEXT ----------------------- "Assembling game text..." & $asm_cmd -root $working_dir -sym $includes_sym_file $includes_asm_file diff --git a/src/c/credits.c b/src/c/credits.c index 6769960..216d824 100644 --- a/src/c/credits.c +++ b/src/c/credits.c @@ -5,18 +5,20 @@ void printPlayerNameCredits(unsigned short *arrangements) //Converts the player name to arrangements int length = 0; byte *player_name = m2_player1; + unsigned short yPosition = m2_credits_extras[0]; + unsigned short defaultNameLength = m2_credits_extras[1]; //First things first, it calculates the length of the string for(length = 0; length < PLAYER_NAME_SIZE && (*(++player_name)) != 0xFF; length++); //Gets where to position the arrangements... int start_pos = ((0x1F - length) >> 1) + 1; - int start_pos_default = ((0x1F - 5) >> 1) + 1; - unsigned short *player_name_arrangements = ((0x89 << 2) << 5) + arrangements + start_pos; - unsigned short *default_player_name_arrangements = ((0x89 << 2) << 5) + arrangements + start_pos_default; + int start_pos_default = ((0x1F - defaultNameLength) >> 1) + 1; + unsigned short *player_name_arrangements = (yPosition << 5) + arrangements + start_pos; + unsigned short *default_player_name_arrangements = (yPosition << 5) + arrangements + start_pos_default; player_name = m2_player1; //Clears the default MARIO player name... - for(int i = 0; i < 5; i++) + for(int i = 0; i < defaultNameLength; i++) { default_player_name_arrangements[i] = 0xF19B; default_player_name_arrangements[i + 0x20] = 0xF19B; diff --git a/src/c/credits.h b/src/c/credits.h index 297c70d..04375aa 100644 --- a/src/c/credits.h +++ b/src/c/credits.h @@ -35,6 +35,7 @@ extern byte m2_player1[]; extern byte cast_vwf_names[]; extern unsigned short m2_cast_vwf_free; extern unsigned short m2_credits_conversion_table[]; +extern unsigned short m2_credits_extras[]; extern int m2_bits_to_nybbles_fast_cast[]; #endif \ No newline at end of file diff --git a/src/data/m2-credits-arrangements_[c].bin b/src/data/m2-credits-arrangements_[c].bin new file mode 100644 index 0000000..40ad86f Binary files /dev/null and b/src/data/m2-credits-arrangements_[c].bin differ diff --git a/src/data/m2-credits-extra-data.bin b/src/data/m2-credits-extra-data.bin new file mode 100644 index 0000000..afa79fd Binary files /dev/null and b/src/data/m2-credits-extra-data.bin differ diff --git a/src/data/m2-credits-scroll-size-limit.bin b/src/data/m2-credits-scroll-size-limit.bin new file mode 100644 index 0000000..c96f311 Binary files /dev/null and b/src/data/m2-credits-scroll-size-limit.bin differ diff --git a/src/data/m2-credits-scroll-size.bin b/src/data/m2-credits-scroll-size.bin new file mode 100644 index 0000000..6176e69 Binary files /dev/null and b/src/data/m2-credits-scroll-size.bin differ diff --git a/src/data/m2-credits-size.bin b/src/data/m2-credits-size.bin new file mode 100644 index 0000000..2f1a466 Binary files /dev/null and b/src/data/m2-credits-size.bin differ diff --git a/src/m2-hack.asm b/src/m2-hack.asm index 680d164..1db9eed 100644 --- a/src/m2-hack.asm +++ b/src/m2-hack.asm @@ -1742,6 +1742,10 @@ nop //Repoint credits font (Before it pointed to 0x82FF1B8) .org 0x82DB284 :: dw m2_credits_font +.org 0x82DB28C :: dw m2_credits_arrangements +.org 0x82DB2A4 :: .incbin "data/m2-credits-size.bin" +.org 0x80B53BC :: .incbin "data/m2-credits-scroll-size-limit.bin" +.org 0x80B53C0 :: .incbin "data/m2-credits-scroll-size.bin" .org 0x801352E :: bl printPlayerNameCredits //Repoint cast graphical data @@ -1971,10 +1975,19 @@ m2_cast_arrangements: m2_credits_font: .incbin "data/m2-credits-font_[c].bin" +.align 4 +m2_credits_arrangements: +.incbin "data/m2-credits-arrangements_[c].bin" + +.align 2 +m2_credits_extras: +.incbin "data/m2-credits-extra-data.bin" + .align 4 m2_end_frame1: .incbin "data/the_end_arrangements_frame1.bin" +.align 4 optimized_byte_4bpp_to_1bpp_table: .incbin "data/optimized-byte-4bpp-to-1bpp-table.bin" diff --git a/tools/M12Tools.sln b/tools/M12Tools.sln index 62fcd10..4fe7504 100644 --- a/tools/M12Tools.sln +++ b/tools/M12Tools.sln @@ -7,7 +7,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptTool", "ScriptTool\Sc EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptToolGui", "ScriptToolGui\ScriptToolGui.csproj", "{BAE5CBBF-D0B3-4F82-A80A-957CEC379238}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenderCastRoll", "RenderCastRoll\RenderCastRoll.csproj", "{DD1C607C-5A74-4921-81A4-6BF530A191D7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderCastRoll", "RenderCastRoll\RenderCastRoll.csproj", "{DD1C607C-5A74-4921-81A4-6BF530A191D7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenderStaffCredits", "RenderStaffCredits\RenderStaffCredits.csproj", "{D4885175-8BD3-4B91-B905-6BA845DBDC2F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -27,6 +29,10 @@ Global {DD1C607C-5A74-4921-81A4-6BF530A191D7}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD1C607C-5A74-4921-81A4-6BF530A191D7}.Release|Any CPU.ActiveCfg = Release|Any CPU {DD1C607C-5A74-4921-81A4-6BF530A191D7}.Release|Any CPU.Build.0 = Release|Any CPU + {D4885175-8BD3-4B91-B905-6BA845DBDC2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4885175-8BD3-4B91-B905-6BA845DBDC2F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4885175-8BD3-4B91-B905-6BA845DBDC2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4885175-8BD3-4B91-B905-6BA845DBDC2F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/tools/RenderStaffCredits/Asset.cs b/tools/RenderStaffCredits/Asset.cs new file mode 100644 index 0000000..2b8d793 --- /dev/null +++ b/tools/RenderStaffCredits/Asset.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; + +namespace RenderStaffCredits +{ + public static class Asset + { + public static readonly string AssetPath; + + static Asset() + { + AssetPath = AppDomain.CurrentDomain.BaseDirectory; + } + + public static string GetFullPath(string path) + => Path.Combine(AssetPath, path); + + public static string ReadAllText(string path) + => File.ReadAllText(GetFullPath(path)); + + public static byte[] ReadAllBytes(string path) + => File.ReadAllBytes(GetFullPath(path)); + + public static string[] ReadAllLines(string path) + => File.ReadAllLines(GetFullPath(path)); + + public static void WriteAllText(string path, string text) + => File.WriteAllText(GetFullPath(path), text); + } +} diff --git a/tools/RenderStaffCredits/LZ77.cs b/tools/RenderStaffCredits/LZ77.cs new file mode 100644 index 0000000..36f57ef --- /dev/null +++ b/tools/RenderStaffCredits/LZ77.cs @@ -0,0 +1,167 @@ +using System.Collections.Generic; + +namespace GBA +{ + class LZ77 + { + public static int Decompress(byte[] data, int address, out byte[] output) + { + output = null; + int start = address; + + if (data[address++] != 0x10) return -1; // Check for LZ77 signature + + // Read the block length + int length = data[address++]; + length += (data[address++] << 8); + length += (data[address++] << 16); + output = new byte[length]; + + int bPos = 0; + while (bPos < length) + { + byte ch = data[address++]; + for (int i = 0; i < 8; i++) + { + switch ((ch >> (7 - i)) & 1) + { + case 0: + + // Direct copy + if (bPos >= length) break; + output[bPos++] = data[address++]; + break; + + case 1: + + // Compression magic + int t = (data[address++] << 8); + t += data[address++]; + int n = ((t >> 12) & 0xF) + 3; // Number of bytes to copy + int o = (t & 0xFFF); + + // Copy n bytes from bPos-o to the output + for (int j = 0; j < n; j++) + { + if (bPos >= length) break; + output[bPos] = output[bPos - o - 1]; + bPos++; + } + + break; + + default: + break; + } + } + } + + return address - start; + } + + public static byte[] Compress(byte[] data) + { + return Compress(data, 0, data.Length); + } + + public static byte[] Compress(byte[] data, int address, int length) + { + int start = address; + + List obuf = new List(); + List tbuf = new List(); + int control = 0; + + // Let's start by encoding the signature and the length + obuf.Add(0x10); + obuf.Add((byte)(length & 0xFF)); + obuf.Add((byte)((length >> 8) & 0xFF)); + obuf.Add((byte)((length >> 16) & 0xFF)); + + while ((address - start) < length) + { + tbuf.Clear(); + control = 0; + for (int i = 0; i < 8; i++) + { + bool found = false; + + // First byte should be raw + if (address == start) + { + tbuf.Add(data[address++]); + found = true; + } + else if ((address - start) >= length) + { + break; + } + else + { + // We're looking for the longest possible string + // The farthest possible distance from the current address is 0x1000 + int max_length = -1; + int max_distance = -1; + + for (int k = 1; k <= 0x1000; k++) + { + if ((address - k) < start) break; + + int l = 0; + for (; l < 18; l++) + { + if (((address - start + l) >= length) || + (data[address - k + l] != data[address + l])) + { + if (l > max_length) + { + max_length = l; + max_distance = k; + } + break; + } + } + + // Corner case: we matched all 18 bytes. This is + // the maximum length, so don't bother continuing + if (l == 18) + { + max_length = 18; + max_distance = k; + break; + } + } + + if (max_length >= 3) + { + address += max_length; + + // We hit a match, so add it to the output + int t = (max_distance - 1) & 0xFFF; + t |= (((max_length - 3) & 0xF) << 12); + tbuf.Add((byte)((t >> 8) & 0xFF)); + tbuf.Add((byte)(t & 0xFF)); + + // Set the control bit + control |= (1 << (7 - i)); + + found = true; + } + } + + if (!found) + { + // If we didn't find any strings, copy the byte to the output + tbuf.Add(data[address++]); + } + } + + // Flush the temp buffer + obuf.Add((byte)(control & 0xFF)); + obuf.AddRange(tbuf.ToArray()); + } + + return obuf.ToArray(); + } + } +} diff --git a/tools/RenderStaffCredits/Program.cs b/tools/RenderStaffCredits/Program.cs new file mode 100644 index 0000000..1b18a7f --- /dev/null +++ b/tools/RenderStaffCredits/Program.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Newtonsoft.Json; + +namespace RenderStaffCredits +{ + class Program + { + static readonly ushort Palette = 0xF000; + static IDictionary m12BigCharArrLookup; + static IDictionary m12SmallCharArrLookup; + static ushort[] Arrangements; + static readonly ushort Empty = 0x9B; + static readonly ushort arrStart = 0x100; + static readonly byte defaultOffset = 0xD; + static readonly string defaultPlayerName = "MARIO"; + static int player_Y_Pos = 0; + + static void Main(string[] args) + { + //Load the stuff we'll use + string[] staff_text = File.ReadAllLines(args[0]); + string dataFolder = args[1] + Path.DirectorySeparatorChar; + m12BigCharArrLookup = JsonConvert.DeserializeObject>(Asset.ReadAllText("m12-big-arr-lookup.json")); + m12SmallCharArrLookup = JsonConvert.DeserializeObject>(Asset.ReadAllText("m12-small-arr-lookup.json")); + + //Prepare the empty arrangements + Arrangements = createArrangements(getStaffTextLength(staff_text)); + int pos = 0; + for (int i = 0; i < staff_text.Length; i++) + { + //Handle a single line and increment the current YPosition accordingly + pos += handleStr(staff_text[i], Arrangements, pos); + } + + //Save the arrangements + File.WriteAllBytes(dataFolder + "m2-credits-arrangements_[c].bin", GBA.LZ77.Compress(convertUShortArrToByteArrLE(Arrangements))); + //Save some data that tells us where to put the player name at runtime + byte[] extra_things = new byte[4]; + writeIntToByteArrLE(extra_things, player_Y_Pos, 0, 2); + writeIntToByteArrLE(extra_things, defaultPlayerName.Length, 2, 2); + File.WriteAllBytes(dataFolder + "m2-credits-extra-data.bin", extra_things); + //Save some data that tells us how many vertical tiles long the arrangement is + int arrSize = Arrangements.Length / 0x20; + byte[] size = new byte[4]; + writeIntToByteArrLE(size, arrSize, 0, 4); + File.WriteAllBytes(dataFolder + "m2-credits-size.bin", size); + //Save some data that tells us where to end scrolling at runtime (in pixels) + int scrollSize = (arrSize + defaultOffset) * 8; + byte[] size_full = new byte[4]; + writeIntToByteArrLE(size_full, scrollSize, 0, 4); + File.WriteAllBytes(dataFolder + "m2-credits-scroll-size.bin", size_full); + byte[] size_minus_one = new byte[4]; + writeIntToByteArrLE(size_minus_one, scrollSize - 1, 0, 4); + File.WriteAllBytes(dataFolder + "m2-credits-scroll-size-limit.bin", size_minus_one); + + } + + static void writeIntToByteArrLE(byte[] arr, int value, int pos, int limiter) + { + for (int i = 0; i < limiter; i++) + arr[pos + i] = (byte)((value >> (8 * i)) & 0xFF); + } + + static byte[] convertUShortArrToByteArrLE(ushort[] arr) + { + byte[] newArr = new byte[arr.Length * 2]; + for (int i = 0; i < arr.Length; i++) + { + newArr[(i * 2)] = (byte)((arr[i]) & 0xFF); + newArr[(i * 2) + 1] = (byte)((arr[i] >> 8) & 0xFF); + } + return newArr; + } + + static int handleStr(string str, ushort[] Arrangements, int YPosition) + { + if (str.StartsWith("# ")) + { + handleSmallText(getStrContent(str), Arrangements, YPosition); + return 1; + } + if (str.StartsWith("- ")) + { + handleBigText(getStrContent(str), Arrangements, YPosition); + return 2; + } + if (str.StartsWith("player_name")) + { + //Save data that tells us where to put the player_name at runtime + player_Y_Pos = YPosition; + handleBigText(defaultPlayerName, Arrangements, YPosition); + return 2; + } + if (str.StartsWith("> ")) + return parseEmptyArrLine(getStrContent(str)); + return 0; + } + + static void handleBigText(string content, ushort[] Arrangements, int YPosition) + { + //The big text, normally, has a top tile and a bottom tile. The bottom tile is 0x20 tiles after the top tile + content = content.ToUpper(); + int XPosition = getStrStartPos(content); + for (int i = 0; i < content.Length; i++) + { + string value = content[i].ToString(); + if (m12BigCharArrLookup.ContainsKey(value)) + { + Arrangements[(YPosition * 0x20) + XPosition + i] = (ushort)(Palette | (arrStart + m12BigCharArrLookup[value])); + Arrangements[(YPosition * 0x20) + XPosition + i + 0x20] = (ushort)(Palette | (arrStart + m12BigCharArrLookup[value] + 0x20)); + } + } + } + + static void handleSmallText(string content, ushort[] Arrangements, int YPosition) + { + content = content.ToUpper(); + int XPosition = getStrStartPos(content); + for (int i = 0; i < content.Length; i++) + { + string value = content[i].ToString(); + if (m12SmallCharArrLookup.ContainsKey(value)) + Arrangements[(YPosition * 0x20) + XPosition + i] = (ushort)(Palette | (arrStart + m12SmallCharArrLookup[value])); + } + } + + static int getStrStartPos(string str) + { + int len = getStrLen(str); + return 1 + ((0x1F - len) >> 1); + } + + static int getStrLen(string str) + { + return str.Length; + } + + static int getStaffTextLength(string[] staff_text) + { + int arrLen = 0; + for (int i = 0; i < staff_text.Length; i++) + { + string str = staff_text[i]; + if (str.StartsWith("# ")) + arrLen += 1; + else if (str.StartsWith("- ") || str.StartsWith("player_name")) + arrLen += 2; + else if (str.StartsWith("> ")) + arrLen += parseEmptyArrLine(getStrContent(str)); + } + return arrLen; + } + + static string getStrContent(string str) + { + return str.Substring(2); + } + + static int parseEmptyArrLine(string str) + { + return int.Parse(str); + } + + static ushort[] createArrangements(int len) + { + ushort[] arrangements = new ushort[len * 0x20]; + for (int i = 0; i < len; i++) + for (int j = 0; j < 0x20; j++) + arrangements[(i * 0x20) + j] = (ushort)(Palette | (Empty + arrStart)); + return arrangements; + } + } +} diff --git a/tools/RenderStaffCredits/Properties/launchSettings.json b/tools/RenderStaffCredits/Properties/launchSettings.json new file mode 100644 index 0000000..0c015e9 --- /dev/null +++ b/tools/RenderStaffCredits/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "ScriptTool": { + "commandName": "Project", + "commandLineArgs": "-compile -main -misc \"..\\working\" \"..\\eb.smc\" \"..\\m12fresh.gba\"", + "workingDirectory": "C:\\Users\\jeffe\\M12\\bin\\ScriptTool" + } + } +} \ No newline at end of file diff --git a/tools/RenderStaffCredits/RenderStaffCredits.csproj b/tools/RenderStaffCredits/RenderStaffCredits.csproj new file mode 100644 index 0000000..efaebb2 --- /dev/null +++ b/tools/RenderStaffCredits/RenderStaffCredits.csproj @@ -0,0 +1,22 @@ + + + + Exe + netcoreapp2.1 + true + + + + + + + + + Always + + + Always + + + + diff --git a/tools/RenderStaffCredits/m12-big-arr-lookup.json b/tools/RenderStaffCredits/m12-big-arr-lookup.json new file mode 100644 index 0000000..067207f --- /dev/null +++ b/tools/RenderStaffCredits/m12-big-arr-lookup.json @@ -0,0 +1,53 @@ +{ + " ": 74, + "!": 80, + "@": 81, + "\"": 91, + "'": 78, + ",": 95, + "-": 79, + "_": 93, + ".": 94, + "/": 77, + "0": 64, + "1": 65, + "2": 66, + "3": 67, + "4": 68, + "5": 69, + "6": 70, + "7": 71, + "8": 72, + "9": 73, + ";": 84, + "?": 76, + "A": 0, + "B": 1, + "C": 2, + "D": 3, + "E": 4, + "F": 5, + "G": 6, + "H": 7, + "I": 8, + "J": 9, + "K": 10, + "L": 11, + "M": 12, + "N": 13, + "O": 14, + "P": 15, + "Q": 16, + "R": 17, + "S": 18, + "T": 19, + "U": 20, + "V": 21, + "W": 22, + "X": 23, + "Y": 24, + "Z": 25, + "[AC]": 88, + "~": 87, + "[AF]": 89 +} \ No newline at end of file diff --git a/tools/RenderStaffCredits/m12-small-arr-lookup.json b/tools/RenderStaffCredits/m12-small-arr-lookup.json new file mode 100644 index 0000000..65948b8 --- /dev/null +++ b/tools/RenderStaffCredits/m12-small-arr-lookup.json @@ -0,0 +1,30 @@ +{ + "A": 128, + "B": 129, + "C": 130, + "D": 131, + "E": 132, + "F": 133, + "G": 134, + "H": 135, + "I": 136, + "J": 137, + "K": 138, + "L": 139, + "M": 140, + "N": 141, + "O": 142, + "P": 143, + "Q": 144, + "R": 145, + "S": 146, + "T": 147, + "U": 148, + "V": 149, + "W": 150, + "X": 151, + "Y": 152, + "Z": 153, + ".": 154, + " ": 155 +} \ No newline at end of file diff --git a/working/staff_text.md b/working/staff_text.md new file mode 100644 index 0000000..b03fe5e --- /dev/null +++ b/working/staff_text.md @@ -0,0 +1,295 @@ +- STAFF +- _____ +> 6 + +# PRODUCED AND DIRECTED BY +- SHIGESATO ITOI +> 2 + +# WRITTEN BY +- SHIGESATO ITOI +> 2 + +# MUSIC BY +- KEIICHI SUZUKI +- HIROKAZU TANAKA +> 6 + +# GAME DESIGNER +- AKIHIKO MIURA +> 2 + +# ART DIRECTOR +- KOUICHI OOYAMA +> 2 + +# SOUND DIRECTOR +- HIROKAZU TANAKA +> 2 + +# PROGRAM DIRECTOR +- SATORU IWATA +> 2 + +# U.S. CONVERSION DIRECTOR +- KOUJI MALTA +> 2 + +# TRANSLATION DIRECTORS +- MARCUS LINDBLOM +- MASAYUKI MIURA +> 6 + +# PROGRAMMERS +- SATORU IWATA +- SATOSHI MITSUHARA +- YOSHIMI TAKAHASHI +- SEIJI OTOGURO +- BOU NAKAJIMA +- SEIKA ABE +- YOSHIKI SUZUKI +- JUN YAMAZAKI +- TOSHIYUKI UENO +- TAKASHI SASAKI +- TAKASHI SAKUMA +- KAZUO SATO +- KOUJI MALTA +> 2 + +# SOUND PROGRAMMER +- HIROKAZU TANAKA +> 2 + +# SYSTEM ENGINEERING +- MAKOTO KANAI +- TAKASHI SAKUMA +> 6 + +# GRAPHICS ARTISTS +- KOUICHI OOYAMA +- HIROYUKI SAKIYAMA +- KOUICHI YAMADA +- MAKIO KATAOKA +- TETSUYA NOTOYA +- YASUNORI YANAGISAWA +> 2 + +# SPECIAL EFFECTS ARTIST +- TSUNEKAZ ISHIHARA +> 2 + +# FONT DESIGNERS +- AKIHIKO MIURA +- KOUICHI OOYAMA +> 2 + +# CONCEPT OF SATURN FONT BY +- SHIGESATO ITOI +> 6 + +# GRAPHICS DATA MANAGER +- YASUNORI YANAGISAWA +> 2 + +# MESSAGE DATA MANAGERS +- MASAYUKI MIURA +- HITOSHI MATSUI +> 6 + +# ADDITIONAL MUSIC COMPOSED BY +- HIROSHI KANAZU +- TOSHIYUKI UENO +> 2 + +# SOUND STAFF +- TOSHIYUKI UENO +- KOZUE ISHIKAWA +> 6 + +# ASSISTANT PROGRAMMERS +- IKUHO HAGIYA +- KATSUYOSHI IRIE +> 2 + +# ASSISTANT GAME DESIGNERS +- KOUICHI OOYAMA +- TAKEHIKO MASUDA +- CHIAKI YOSHIZAWA +- MASAYUKI MIURA +- AKIHITO TODA +- HITOSHI MATSUI +- KATSUYOSHI IRIE +> 2 + +# ASSISTANT SCENARIO WRITERS +- MASAYUKI MIURA +- AKIHITO TODA +- HIROYUKI JINNAI +> 2 + +# ENGLISH TEXT WRITERS +- MARCUS LINDBLOM +- DAN OWSEN +> 2 + +# TRANSLATORS +- KEIKO TAMURA +- YUKA NAKATA +> 6 + +# CHIEF DEBUGGERS +- TAKUMI AKABANE +- HITOSHI MATSUI +> 6 + +# NOA DEBUG COORDINATORS +- SEAN O'CONNOR +- MICHAEL KELBAUGH +> 6 + +# APE DEBUGGING TEAM +- TAKAHIRO NAGAI +- JUNICHI AKAMA +- AKIRA MATSUMOTO +> 6 + +# NINTENDO DEBUG COORDINATORS +- TOHRU HASHIMOTO +- TATSUYA HISHIDA +> 2 + +# NINTENDO DEBUGGING TEAM +- KAZUHIDE OHGOE +- ATSUSHI MIYAKE +- HAJIME NAKAMURA +- MAO HAMAMOTO +- MAYUMI TADA +- MAKOTO KEDOUIN +- KIMIKO TSUCHIDA +- SAYAKA KOMURA +> 2 + +# MAP CHECKERS +- MAPPER KOJIMA +- KATSUYOSHI IRIE +> 6 + +# SAMPLING VOICES +- SHIGESATO OK? ITOI +- YUKARI WHISTLE SAITO +- HIROKAZU BELCH KOYANO +- ETSUKO VENUS KAWANO +- TAKASHI MU WATANABE +> 2 + +# OPENING ROCK GUITAR +- M.D.SEEGER +> 6 + +# HARDWARE SUPPORT +- HIRONOBU KAKUI +- SHIGEKI YAMASHIRO +> 6 + +# PRODUCTION MANAGERS +- TAKASHI KAWAGUCHI +- KEIZO KATO +- IKUO HYAKUTA +- YUKARI SAITO +> 2 + +# COORDINATORS +- TAKASHI WATANABE +- RYO KAGAWA +- HIROYUKI JINNAI +- ETSUKO KAWANO +- KAZUYUKI YAMAMOTO +- ATSUKO KAWAHARA +> 6 + +# SOUND PRODUCERS +- AKIO OHMORI +- RITSUO KAMIMURA +> 6 + +# SPECIAL THANKS TO +- KENJI ANDO +- MIYUKI KURE +- TAKAYUKI ONODERA +- FUKASHI OMORITA +- YUKIO TAKAHASHI +- KAZUHIKO AMEMIYA +- YASUHIRO KUMAGAI +- YOSHIO HONGO +- NAOKO KANAZAWA +- BENIMARU ITOH +- MOTOHIRO ISHII +- HIROKAZU KOYANO +- MASAO TOTTORI +- NOBUYASU MAKINO +- HIROMI TAMAGAWA +- NANCY YOSHITAKE +> 2 + +- AND MANY OTHERS +> 6 + +# THE PRODUCERS WISH TO THANK +- ISHEL ARTVISION +- MOONRIDERS OFFICE +- SEDIC INC. +- SETA CO.,LTD. +- LUCKY NICE +- OKUBO DESIGN STUDIO +- ON ASSOCIATES +- SAI KOUBOU +- ASHURA OFFICE +- SHOGAKUKAN +- SHINCHO SHA +> 6 + +# CHIEF COORDINATOR +- MARCUS LINDBLOM +> 6 + +# LINE PRODUCER +- TSUNEKAZ ISHIHARA +> 6 + +# COPRODUCER +- SATORU IWATA +> 6 + +# NOA PRODUCER +- MIKE FUKUDA +> 6 + +# SUPERVISOR +- SHIGERU MIYAMOTO +> 6 + +# EXECUTIVE PRODUCERS +- HIROSHI YAMAUCHI +- MINORU ARAKAWA +> 6 + +# PRESENTED BY +- NINTENDO +> 2 + +# IN ASSOCIATION WITH +- APE INC. +> 2 + +# AND +- HAL LABORATORY,INC. +> 12 + +# AND... +# +> 14 + +# PLAYER +player_name +> 1 +