e.g. BGI 1.64. Like BGI (old) but with a different operation encoding. Used in Nursery Rhyme.

   1 #!/usr/bin/env python
   2 
   3 from sys import argv, exit, stdout
   4 from mmap import mmap, ACCESS_COPY, ACCESS_READ
   5 from struct import unpack, iter_unpack
   6 
   7 def print(s, end="\n"):
   8     stdout.buffer.write((str(s) + end).encode("utf-8"))
   9 
  10 def uint(f):
  11     return unpack("<I", f.read(4))[0]
  12 def ushort(f):
  13     return unpack("<H", f.read(2))[0]
  14 def byte(f):
  15     return unpack("<B", f.read(1))[0]
  16 def char(f):
  17     return unpack("<c", f.read(1))[0]
  18 def string(f):
  19     mystr = bytes()
  20     c = char(f)
  21     while c[0] != 0:
  22         mystr += c
  23         c = char(f)
  24     return mystr
  25 
  26 def short(x):
  27     return "0x%04X" % x
  28 def long(x):
  29     return "0x%08X" % x
  30 
  31 if len(argv) < 2:
  32     print("No input given")
  33     exit()
  34 
  35 for fn in argv[1:]:
  36     with open(fn, "rb") as f:
  37         lowest_string_addr = -1
  38         nullonly = False
  39         string_addrs = []
  40         while 1:
  41             addr = f.tell()
  42             if lowest_string_addr >= 0 and addr+1 >= lowest_string_addr:
  43                 #print(f"entered string table at {lowest_string_addr:08X} in {fn}")
  44                 break
  45             try:
  46                 op = ushort(f)
  47             except:
  48                 break
  49             #print(f"\nop_{op:04X}")
  50             if   op in [0x0000]: # means we're in padding, not a NOP
  51                 nullonly = True
  52                 pass
  53             elif nullonly:
  54                 #print(f"non-null command at {f.tell()-2:08X} after seeing null command")
  55                 #print(f"lowest_string_addr is {lowest_string_addr:08X}")
  56                 break
  57             elif   op in [0xFEFE]:
  58                 pass
  59             elif op in [
  60                  0x0011,
  61                  0x001D,
  62                  0x0020,
  63                  0x0021,
  64                  0x0082,
  65                  0x0083, # ?
  66                  0x00C9,
  67                  0x00B8,
  68                  ]:
  69                  pass
  70             elif op in [
  71                  0x0040,
  72                  0x0041,
  73                  ]:
  74                 num = uint(f)
  75                 num = uint(f)
  76                 x = string(f)
  77                 #print(f"{x.decode('shift-jis')}")
  78                 num = uint(f)
  79                 num = uint(f)
  80             elif op in [
  81                  0x0042,
  82                  0x0043,
  83                  0x0044,
  84                  0x0045,
  85                  ]:
  86                 num = uint(f)
  87                 num = uint(f)
  88                 x = string(f)
  89                 #print(f"{x.decode('shift-jis')}")
  90                 num = uint(f)
  91             elif op in [
  92                  0x0028,
  93                  ]:
  94                 x = string(f)
  95                 #print(f"{x.decode('shift-jis')}")
  96                 num = uint(f)
  97                 #print(f"{num}")
  98             elif op in [
  99                  0x002B,
 100                  ]:
 101                 x = string(f)
 102                 #print(f"{x.decode('shift-jis')}")
 103                 num = uint(f)
 104             elif op in [
 105                  0x0050,
 106                  0x0053,
 107                  ]:
 108                 x = string(f)
 109                 #print(f"{x.decode('shift-jis')}")
 110                 num = uint(f) # not var
 111             elif op in [
 112                  0x0080,
 113                  ]:
 114                 x = string(f)
 115                 #print(f"{x.decode('shift-jis')}")
 116                 num = uint(f)
 117             elif op in [
 118                  0x0046,
 119                  0x0047,
 120                  0x0070,
 121                  0x0074,
 122                  ]:
 123                 num = uint(f) # not var?
 124                 x = string(f)
 125                 #print(f"{x.decode('shift-jis')}")
 126                 num = uint(f) # not var?
 127             elif op in [
 128                  0x0014,
 129                  0x0085,
 130                  ]:
 131                 x = string(f)
 132                 #print(f"{x.decode('shift-jis')}")
 133             elif op in [
 134                  0x00C8, # command text?
 135                  ]:
 136                 x = string(f)
 137                 #print(f"{x.decode('shift-jis')}")
 138             elif op in [
 139                  0x00C0, # jump to another script (and don't come back?)
 140                  0x00C1, # jump to another script (and come back?)
 141                  ]:
 142                 x = string(f)
 143                 #print(f"{x.decode('shift-jis')}")
 144             elif op in [
 145                  0x00C2, # often comes after 0x00C0
 146                  ]:
 147                 pass
 148             elif op in [
 149                  0x0010,
 150                  ]:
 151                 num = uint(f)
 152                 #print(f"{num}")
 153                 if num != 0: exit()
 154                 num = uint(f)
 155                 num = uint(f)
 156                 #print(f"{num}") # content text address
 157                 if lowest_string_addr == -1 or num < lowest_string_addr:
 158                     lowest_string_addr = num
 159                 string_addrs += [num]
 160             elif op in [
 161                  0x006D,
 162                  ]:
 163                 num = uint(f)
 164                 #print(f"{num}")
 165                 num = uint(f)
 166                 #print(f"{num}")
 167                 if num != 256: exit()
 168                 num = uint(f)
 169                 #print(f"{num}")
 170             elif op in [
 171                  0x0072,
 172                  0x0076,
 173                  ]:
 174                 num = uint(f)
 175                 #print(f"{num}")
 176                 num = uint(f)
 177                 #print(f"{num}")
 178                 num = uint(f)
 179                 #print(f"{num}")
 180             elif op in [
 181                  0x0048,
 182                  ]:
 183                 num = uint(f)
 184                 #print(f"{num}")
 185                 num = uint(f)
 186                 #print(f"{num}")
 187             elif op in [
 188                  0x0049,
 189                  ]:
 190                 num = uint(f)
 191                 #print(f"{num}")
 192                 num = uint(f)
 193                 #print(f"{num}")
 194             elif op in [
 195                  0x0035,
 196                  0x003D,
 197                  ]:
 198                 num = uint(f)
 199                 #print(f"{num}")
 200                 num = uint(f)
 201                 #print(f"{num}")
 202             elif op in [
 203                  0x00A3, # some kind of test/jump?
 204                  0x00A4, # some kind of test/jump?
 205                  0x00A5, # some kind of test/jump?
 206                  0x00A7, # some kind of test/jump?
 207                  0x00A8, # some kind of test/jump?
 208                  ]:
 209                 num = ushort(f)
 210                 #print(f"{num}")
 211                 num = ushort(f)
 212                 #print(f"{num}")
 213                 num = uint(f)
 214                 #print(f"{num}")
 215                 num = uint(f)
 216                 #print(f"{num}")
 217             elif op in [
 218                  0x00A1, # some kind of test/jump?
 219                  0x00A2, # some kind of test/jump?
 220                  ]:
 221                 num = uint(f)
 222                 #print(f"{num}")
 223                 num = uint(f)
 224                 #print(f"{num}")
 225             elif op in [
 226                  0x00AE, # unconditional?
 227                  ]:
 228                 num = uint(f)
 229             elif op in [
 230                  0x002A,
 231                  0x0052,
 232                  0x0067,
 233                  0x0068,
 234                  0x0069,
 235                  0x006A,
 236                  0x006C,
 237                  0x006F,
 238                  0x0071,
 239                  0x0075,
 240                  0x008C,
 241                  0x008D,
 242                  0x008E,
 243                  0x0090,
 244                  0x0092,
 245                  0x00A0,
 246                  0x00BA,
 247                  0x00C4,
 248                  ]:
 249                 num = uint(f)
 250                 #print(f"{num}")
 251             elif op in [
 252                  0x0066,
 253                  ]:
 254                 num = uint(f)
 255                 #print(f"{num}")
 256                 num = uint(f)
 257                 #print(f"{num}")
 258             elif op in [
 259                  0x0029,
 260                  0x0051,
 261                  ]:
 262                 x = string(f)
 263                 #print(f"{x.decode('shift-jis')}")
 264                 x = string(f)
 265                 #print(f"{x.decode('shift-jis')}")
 266                 num = uint(f)
 267                 #print(f"{num}")
 268             elif op in [
 269                  0x0012, # furigana mapper?
 270                  ]:
 271                 x = string(f)
 272                 #print(f"{x.decode('shift-jis')}")
 273                 x = string(f)
 274                 #print(f"{x.decode('shift-jis')}")
 275             elif op in [
 276                  0x0013, # reuse furigana mapping?
 277                  ]:
 278                 x = string(f)
 279                 #print(f"{x.decode('shift-jis')}")
 280             elif op in [
 281                  0x00D4,
 282                  0x00D8,
 283                  0x00DA,
 284                  0x00DB,
 285                  0x00DC,
 286                  ]:
 287                 uint(f)
 288             elif op in [
 289                  0x0098,
 290                  0x0099,
 291                  ]:
 292                 ushort(f)
 293                 ushort(f)
 294                 ushort(f)
 295                 ushort(f)
 296             elif op in [
 297                  0x00B9,
 298                  ]:
 299                 ushort(f)
 300                 ushort(f)
 301             elif op in [
 302                  0x00B0,
 303                  ]:
 304                 num = uint(f)
 305                 #print(f"{num}")
 306                 for i in range(num):
 307                     x = string(f)
 308                     #print(f"{x.decode('shift-jis')}")
 309             elif op in [
 310                  0x00A9,
 311                  ]:
 312                 num = uint(f)
 313                 #print(f"{num}")
 314                 for i in range(num):
 315                     uint(f)
 316             elif op in [
 317                  0x0034, # effect related
 318                  ]:
 319                 uint(f)
 320                 x = string(f)
 321                 #print(f"{x.decode('shift-jis')}")
 322                 for i in range(5):
 323                     uint(f)
 324             elif op in [
 325                  0x0036, # ?
 326                  0x016E, # ???
 327                  ]:
 328                 for i in range(6):
 329                     uint(f)
 330             elif op in [
 331                  0x013A,
 332                  0x0139,
 333                  ]:
 334                 uint(f)
 335             elif op in [
 336                  0x0138,
 337                  ]:
 338                 uint(f)
 339                 uint(f)
 340             elif op in [
 341                  0x0137, # some kind of cut effect
 342                  ]:
 343                 uint(f)
 344                 x = string(f)
 345                 #print(f"{x.decode('shift-jis')}")
 346                 uint(f)
 347                 uint(f)
 348                 uint(f)
 349             elif op in [
 350                  0x002c, # background related (pan and zoom?)
 351                  ]:
 352                 
 353                 x = string(f)
 354                 #print(f"{x.decode('shift-jis')}")
 355                 
 356                 for i in range(8):
 357                     uint(f)
 358             elif op in [
 359                  0x0018,
 360                  0x001C,
 361                  0x002D, # background related (pan and zoom?)
 362                  ]:
 363                 
 364                 for i in range(5):
 365                     uint(f)
 366             elif op in [
 367                  0x001A,
 368                  0x001E,
 369                  ]:
 370                 
 371                 uint(f)
 372                 uint(f)
 373                 uint(f)
 374             elif op in [
 375                  0x001B,
 376                  ]:
 377                 
 378                 x = string(f)
 379                 
 380                 for i in range(7):
 381                     uint(f)
 382             elif op in [
 383                  0x0088, # play movie or something
 384                  ]:
 385                 
 386                 x = string(f)
 387                 #print(f"{x.decode('shift-jis')}")
 388             else:
 389                 print(f"unknown op {op:04X} at {f.tell()-2:08X} in {fn}")
 390                 exit(0)
 391         if len(string_addrs) > 0:
 392             if True: # the right way to do it
 393                 for addr in string_addrs:
 394                     f.seek(addr)
 395                     x = string(f)
 396                     print(f"{x.decode('shift-jis')}")
 397             else: # the wrong way, but validates that we captured all the text
 398                 f.seek(lowest_string_addr)
 399                 while True:
 400                     try:
 401                         x = string(f)
 402                         print(f"{x.decode('shift-jis')}")
 403                     except:
 404                         break
 405             print("\n\n")

BGI (older) (last edited 2018-04-12 01:38:25 by weh)