Skip to content

Extraction scripts for Russian

Michael Steenbeek edited this page Mar 1, 2017 · 1 revision

Interface

This script misses quite a few special codes.

using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Linq;

class rct2string
{

	static void Main()
	{
		var offsets = new List<int>();
		var strings = new List<string>();

		string exePath = @"/home/michael/rct2-ru.exe";
		using (var fs = new FileStream(exePath, FileMode.Open, FileAccess.Read)) {
			var br = new BinaryReader(fs);
			fs.Position = 0x005BF2D4;
			while (fs.Position < 0x005C28B0) {
				offsets.Add(br.ReadInt32() - 0x400000);
			}
		
			foreach (int offset in offsets)
				strings.Add(ParseString(ReadString(fs, offset)));
		}
	
		foreach (string s in strings)
			Console.WriteLine(s);
	}

	static byte[] ReadString(Stream stream, int position)
	{
		stream.Position = position;
		var br = new BinaryReader(stream);
		byte b;
		var buffer = new List<byte>();
		while ((b = br.ReadByte()) != 0) {
			buffer.Add(b);
		}
		return buffer.ToArray();
	}

	static string ParseString(byte[] s)
	{
		var sb = new StringBuilder();
		foreach (byte b in s) {
			switch (b) {
			case 1:
				sb.Append("{MOVE_X}");
				break;
			case 5:
				sb.Append("{NEWLINE}");
				break;
			case 6:
				sb.Append("{NEWLINE_SMALLER}");
				break;
			case 7:
				sb.Append("{TINYFONT}");
				break;
			case 8:
				sb.Append("{BIGFONT}");
				break;
			case 9:
				sb.Append("{MEDIUMFONT}");
				break;
			case 10:
				sb.Append("{SMALLFONT}");
				break;
			case 11:
				sb.Append("{OUTLINE}");
				break;
			case 12:
				sb.Append("{OUTLINE_OFF}");
				break;
			case 13:
				sb.Append("{WINDOW_COLOUR_1}");
				break;
			case 14:
				sb.Append("{WINDOW_COLOUR_2}");
				break;
			case 15:
				sb.Append("{WINDOW_COLOUR_3}");
				break;
			case 17:
				sb.Append("{NEWLINE_X_Y}");
				break;
			case 23:
				sb.Append("{INLINE_SPRITE}");
				break;

			case 123:
				sb.Append("{COMMA16}");
				break;
			case 124:
				sb.Append("{INT32}");
				break;
			case 125:
				sb.Append("{COMMA2DP32}");
				break;
			case 126:
				sb.Append("{COMMA16}");
				break;
			case 127:
				sb.Append("{UINT16}");
				break;
			case 128:
				sb.Append("{CURRENCY2DP}");
				break;
			case 129:
				sb.Append("{CURRENCY}");
				break;
			case 130:
				sb.Append("{STRINGID}");
				break;
			case 131:
				sb.Append("{STRINGID2}");
				break;
			case 132:
				sb.Append("{STRING}");
				break;
			case 133:
				sb.Append("{MONTHYEAR}");
				break;
			case 134:
				sb.Append("{MONTH}");
				break;
			case 135:
				sb.Append("{VELOCITY}");
				break;
			case 136:
				sb.Append("{POP16}");
				break;
			case 137:
				sb.Append("{PUSH16}");
				break;
			case 138:
				sb.Append("{DURATION}");
				break;
			case 139:
				sb.Append("{REALTIME}");
				break;
			case 140:
				sb.Append("{LENGTH}");
				break;
			case 141:
				sb.Append("{SPRITE}");
				break;
			case 142:
				sb.Append("{BLACK}");
				break;
			case 143:
				sb.Append("{GREY}");
				break;
			case 144:
				sb.Append("{WHITE}");
				break;
			case 145:
				sb.Append("{RED}");
				break;
			case 146:
				sb.Append("{GREEN}");
				break;
			case 147:
				sb.Append("{YELLOW}");
				break;
			case 148:
				sb.Append("{TOPAZ}");
				break;
			case 149:
				sb.Append("{CELADON}");
				break;
			case 150:
				sb.Append("{BABYBLUE}");
				break;
			case 151:
				sb.Append("{PALELAVENDER}");
				break;
			case 152:
				sb.Append("{PALEGOLD}");
				break;
			case 153:
				sb.Append("{LIGHTPINK}");
				break;
			case 154:
				sb.Append("{PEARLAQUA}");
				break;
			case 155:
				sb.Append("{PALESILVER}");
				break;
			case 159:
				sb.Append("{AMINUSCULE}");
				break;
			case 162:
				sb.Append("{CENT}");
				break;
			case 163:
				sb.Append("{POUND}");
				break;
			case 165:
				sb.Append("{YEN}");
				break;
			case 169:
				sb.Append("{COPYRIGHT}");
				break;
			case 171:
				sb.Append("{LEFTGUILLEMET}");
				break;
			case 176:
				sb.Append("{DEGREE}");
				break;
			case 178:
				sb.Append("{SQUARED}");
				break;
			case 187:
				sb.Append("{RIGHTGUILLEMET}");
				break;
			case 191:
				sb.Append("{INVERTEDQUESTION}");
				break;

			case (160+32):
				sb.Append("А");
				break;
			case (161+32):
				sb.Append("Б");
				break;
			case (162+32):
				sb.Append("В");
				break;
			case (163+32):
				sb.Append("Г");
				break;
			case (164+32):
				sb.Append("Д");
				break;
			case (165+32):
				sb.Append("Е");
				break;
			case (166+32):
				sb.Append("Ж");
				break;
			case (167+32):
				sb.Append("З");
				break;
			case (168+32):
				sb.Append("И");
				break;
			case (169+32):
				sb.Append("Й");
				break;
			case (170+32):
				sb.Append("К");
				break;
			case (171+32):
				sb.Append("Л");
				break;
			case (172+32):
				sb.Append("М");
				break;
			case (173+32):
				sb.Append("Н");
				break;
			case (174+32):
				sb.Append("О");
				break;
			case (175+32):
				sb.Append("П");
				break;
			case (176+32):
				sb.Append("Р");
				break;
			case (177+32):
				sb.Append("С");
				break;
			case (178+32):
				sb.Append("Т");
				break;
			case (179+32):
				sb.Append("У");
				break;
			case (180+32):
				sb.Append("Ф");
				break;
			case (181+32):
				sb.Append("Х");
				break;
			case (182+32):
				sb.Append("Ц");
				break;
			case (183+32):
				sb.Append("Ч");
				break;
			case (184+32):
				sb.Append("Ш");
				break;
			case (185+32):
				sb.Append("Щ");
				break;
			case (186+32):
				sb.Append("Ъ");
				break;
			case (187+32):
				sb.Append("Ы");
				break;
			case (188+32):
				sb.Append("Ь");
				break;
			case (189+32):
				sb.Append("Э");
				break;
			case (190+32):
				sb.Append("Ю");
				break;
			case (191+32):
				sb.Append("Я");
				break;
			case (192+32):
				sb.Append("а");
				break;
			case (193+32):
				sb.Append("б");
				break;
			case (194+32):
				sb.Append("в");
				break;
			case (195+32):
				sb.Append("г");
				break;
			case (196+32):
				sb.Append("д");
				break;
			case (197+32):
				sb.Append("е");
				break;
			case (198+32):
				sb.Append("ж");
				break;
			case (199+32):
				sb.Append("з");
				break;
			case (200+32):
				sb.Append("и");
				break;
			case (201+32):
				sb.Append("й");
				break;
			case (202+32):
				sb.Append("к");
				break;
			case (203+32):
				sb.Append("л");
				break;
			case (204+32):
				sb.Append("м");
				break;
			case (205+32):
				sb.Append("н");
				break;
			case (206+32):
				sb.Append("о");
				break;
			case (207+32):
				sb.Append("п");
				break;
			case (208+32):
				sb.Append("р");
				break;
			case (209+32):
				sb.Append("с");
				break;
			case (210+32):
				sb.Append("т");
				break;
			case (211+32):
				sb.Append("у");
				break;
			case (212+32):
				sb.Append("ф");
				break;
			case (213+32):
				sb.Append("х");
				break;
			case (214+32):
				sb.Append("ц");
				break;
			case (215+32):
				sb.Append("ч");
				break;
			case (216+32):
				sb.Append("ш");
				break;
			case (217+32):
				sb.Append("щ");
				break;
			case (218+32):
				sb.Append("ъ");
				break;
			case (219+32):
				sb.Append("ы");
				break;
			case (220+32):
				sb.Append("ь");
				break;
			case (221+32):
				sb.Append("э");
				break;
			case (222+32):
				sb.Append("ю");
				break;
			case (223+32):
				sb.Append("я");
				break;
			default:
				sb.Append((char)b);
				break;
			}
		}
		return sb.ToString();
	}
}

Objects

using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using RCT2ObjectData;
using RCT2ObjectData.DataObjects;

class openrct2oostrings
{
	static void Main()
	{
		string path = @"/home/michael/RCT2RUSS";
		string[] files = Directory.GetFiles(path);
		var objects = files
			.Select(x => RCT2ObjectData.DataObjects.ObjectData.FromFile(x))
			.Where(x => x != null)
			.ToArray();
	
		Func<RCT2ObjectData.DataObjects.ObjectData, int> getGame = obj => {
			switch (obj.Source) {
			case RCT2ObjectData.DataObjects.SourceTypes.RCT2: return 0;
			case RCT2ObjectData.DataObjects.SourceTypes.WW: return 1;
			case RCT2ObjectData.DataObjects.SourceTypes.TT: return 2;
			default: return 3;
			}
		};
	
		objects = objects
			.OrderBy(x => getGame(x))
			.ThenBy(x => x.Type)
			.ThenBy(x => x.Subtype)
			.ToArray();

		foreach (var obj in objects) {	
			// GOG used the US English fields for the base game objects and UK English for the expansion objects
			int offset = (getGame(obj) == 0) ? 1 : 0;
			Console.WriteLine("[" + obj.ObjectHeader.FileName + "]");
			switch (obj.Type) {
			case ObjectTypes.Attraction:
				Console.WriteLine("STR_NAME    :{0}", obj.StringTable.Entries[0].Languages[offset]);
				Console.WriteLine("STR_DESC    :{0}", obj.StringTable.Entries[1].Languages[offset]);
				if (obj.Subtype != ObjectSubtypes.Stall)
					Console.WriteLine("STR_CPTY    :{0}", obj.StringTable.Entries[2].Languages[offset]);
				break;
			default:
				Console.WriteLine("STR_NAME    :{0}", obj.StringTable.Entries[0].Languages[offset]);
				break;
			}
			Console.WriteLine();
		}
	}
}