def load(self, filename): filename = filename.lower() if not filename in MTB_DIR: _LOGGER.error("Invalid MTB file: %s" % filename) return self.filename = filename script_dir = MTB_DIR[filename] self.script_pack = ScriptPack(script_dir, common.editor_config.data01_dir) # --- MTB FORMAT --- # A nested pak of our standard game paks. # Each file comes with three paks (four in the first game). # The first pak has a single file with information about the MTB as a whole. # The second one contains information about individual lines. # The third one, I dunno. Always seems to have 120 items? mtb = ConstBitStream(filename=os.path.join( common.editor_config.data01_dir, BIN_DIR, self.filename)) paks = [data for name, data in get_pak_files(mtb)] mtb_data = paks[0] line_data = paks[1] for name, data in get_pak_files(mtb_data): mtb_index = data.read("uintle:16") sprite_char = data.read("uintle:16") voice_char = data.read("uintle:16") sprite_id = data.read("uintle:16") sprite = SpriteId(SPRITE_TYPE.stand, sprite_char, sprite_id) for name, data in get_pak_files(line_data): file_id = data.read("uintle:16") voice_ch = data.read("uintle:16") voice_id = data.read("uintle:16") voice = VoiceId(voice_char, voice_ch, voice_id) self.script_pack[file_id].scene_info.sprite = sprite self.script_pack[file_id].scene_info.voice = voice
def load(self, filename): filename = filename.lower() if not filename in DIR_MAP: _LOGGER.error("Invalid nonstop file: %s" % filename) return self.filename = filename script_dir = DIR_MAP[filename] self.script_pack = ScriptPack(script_dir, common.editor_config.data01_dir) file_order = [] # --- NONSTOP FORMAT --- # XX XX -- ??? # XX XX -- Number of lines (not necessarily files) # # [68 bytes per line] # XX XX -- File number # XX XX XX XX # * 0x00000000 = normal line # * 0x01000100 = chatter # * 0x01000000 = ??? (Only appears in SDR2) # * 0x02000000 = ??? (Only appears in SDR2) # * 0x03000000 = ??? (Only appears in SDR2) # * 0x04000000 = ??? (Only appears in SDR2) # XX XX -- Ammo ID that reacts to this line. # XX XX -- Converted line ID that reacts to this line. # XX XX -- ??? # XX XX -- 1 = has a weak point, 0 = has no weak point # XX XX -- The amount of time before the next line is shown (in sixtieths of seconds (frames?)). # XX XX -- Unknown (Possibly line orientation? Only 0 in the first game, but sometimes 2 in the second.) # XX XX -- Effect used when transitioning text in. # XX XX -- Effect used when transitioning text out. # * 0: fade # * 1: spin in/out # * 2: zoom out # * 3: slide in/out # XX XX -- The amount of the the line stays on-screen (in sixtieths of seconds (frames?)). # XX XX -- Initial X position (text centered around this pos). # XX XX -- Initial Y position (text centered around this pos). # XX XX -- Text velocity. # XX XX -- Angle of motion. # XX XX -- Initial text zoom (in percent). # XX XX -- Change in zoom over time (in percent). # * 90% means it gradually shrinks. # * 100% means it stays the same size the whole time. # * 110% means it gradually grows. # XX XX -- 0 = no shake, 1 = shake # XX XX -- Rotate the text clockwise to this angle. # XX XX -- Text spins clockwise at this rate. # XX XX -- Speaker (00 00 if chatter) # XX XX -- Sprite ID (00 00 if chatter) # XX XX XX XX -- ??? # XX XX -- Voice index (FF FF if chatter) # XX XX -- ??? # XX XX -- Chapter # XX XX XX XX -- ??? (padding?) nonstop = ConstBitStream(filename=os.path.join( common.editor_config.data01_dir, NONSTOP_DIR, self.filename)) self.magic = nonstop.read(16) num_lines = nonstop.read('uintle:16') # Four byte header plus 68 bytes per line. if nonstop.len < (4 + (num_lines * 68)) * 8: raise Exception("Invalid nonstop file.") prev_non_chatter = -1 self.lines = [] for i in range(num_lines): line = NonstopLine() line.file_num = nonstop.read('uintle:16') line.line_type = nonstop.read(32) if line.line_type in LINE_TYPE_MAP: line.line_type = LINE_TYPE_MAP[line.line_type] line.ammo_id = nonstop.read('intle:16') line.converted_id = nonstop.read('intle:16') line.unknown1 = nonstop.read(16) line.weak_point = nonstop.read('uintle:16') line.delay = nonstop.read('intle:16') line.orientation = nonstop.read('intle:16') line.in_effect = nonstop.read('intle:16') line.out_effect = nonstop.read('intle:16') line.time_visible = nonstop.read('intle:16') line.x_start = nonstop.read('intle:16') line.y_start = nonstop.read('intle:16') line.velocity = nonstop.read('intle:16') line.angle = nonstop.read('intle:16') line.zoom_start = nonstop.read('intle:16') line.zoom_change = nonstop.read('intle:16') line.shake = nonstop.read('intle:16') line.rot_angle = nonstop.read('intle:16') line.spin_vel = nonstop.read('intle:16') line.speaker = nonstop.read('intle:16') # Since we mess with speaker a little bit later, we want to keep the ID for the sprite. line.char_id = line.speaker line.sprite_id = nonstop.read('intle:16') line.unknown3 = nonstop.read(32) line.voice_id = nonstop.read('intle:16') line.unknown4 = nonstop.read(16) line.chapter = nonstop.read('intle:16') line.unknown5 = nonstop.read(32) line.unknown6 = nonstop.read(64) format = copy.deepcopy(TEXT_FORMATS[common.SCENE_MODES.debate]) format.orient = TEXT_ORIENT.hor if line.orientation == 0 else TEXT_ORIENT.ver format.align = TEXT_ALIGN.center if format.orient == TEXT_ORIENT.ver: format.y = format.h format.x = format.w / 3.5 self.script_pack[line.file_num].scene_info.format = format if line.line_type == NONSTOP_LINE_TYPE.normal: prev_non_chatter = line.file_num # Fixing some weirdness. # if filename in ["nonstop_06_003.dat", "nonstop_06_005.dat", "nonstop_06_006.dat", "nonstop_06_007.dat"] and line.speaker == 16: # line.speaker = 15 # if filename[:10] == "nonstop_06" and int(filename[11:14]) >= 10 and line.speaker == 10: # line.speaker = 18 # if filename in ["nonstop_02_003.dat", "nonstop_02_005.dat", "nonstop_04_005.dat", "nonstop_04_006.dat"] and line.speaker == 10: # line.speaker = 18 self.script_pack[ line.file_num].scene_info.speaker = line.speaker sprite = SpriteId(SPRITE_TYPE.stand, line.char_id, line.sprite_id) self.script_pack[line.file_num].scene_info.sprite = sprite voice = VoiceId(line.speaker, line.chapter, line.voice_id) self.script_pack[line.file_num].scene_info.voice = voice self.script_pack[ line. file_num].scene_info.special = common.SCENE_SPECIAL.debate elif "hanron" in str(line.line_type): self.script_pack[ line.file_num].scene_info.speaker = line.speaker sprite = SpriteId(SPRITE_TYPE.stand, line.char_id, line.sprite_id) self.script_pack[line.file_num].scene_info.sprite = sprite voice = VoiceId(line.speaker, line.chapter, line.voice_id) self.script_pack[line.file_num].scene_info.voice = voice self.script_pack[ line. file_num].scene_info.special = common.SCENE_SPECIAL.hanron elif line.line_type == NONSTOP_LINE_TYPE.chatter: self.script_pack[line.file_num].scene_info.speaker = -1 self.script_pack[ line. file_num].scene_info.special = common.SCENE_SPECIAL.chatter self.script_pack[ line.file_num].scene_info.extra_val = prev_non_chatter else: _LOGGER.error("Invalid line type: %s" % line.line_type) file_order.append(line.file_num) self.lines.append(line) for index in xrange(len(self.script_pack)): if not index in file_order: file_order.append(index) self.script_pack.script_files = [ self.script_pack[i] for i in file_order ]
def __init__(self): self.script_pack = ScriptPack() self.filename = "" self.magic = None self.lines = []
def script_to_text(dir, translated = True, strip_clt = False, only_voiced = False, line_numbers = True): script_pack = ScriptPack() if dir[:7] == "nonstop": parser = NonstopParser() parser.load(dir) script_pack = parser.script_pack elif dir[:8] == "hs_mtb_s": parser = MTBParser() parser.load(dir) script_pack = parser.script_pack elif dir[:7] == "anagram": return u"" else: script_pack.load_dir(dir, common.editor_config.umdimage_dir) # pack = ScriptPack(directory = dir, umdimage = "X:/Danganronpa/Demo_FINAL/umdimage/") output = [] if len(script_pack) > 0: output.append("==================================================\n=== %s" % dir) room = get_map_name(script_pack[0].scene_info.room) if not room == None: output.append("\n=== Room: %s" % room) output.append("\n==================================================\n\n") for script in script_pack: voice = get_voice_file(script.scene_info.voice) if voice == None and only_voiced: continue if script.scene_info.special in [common.SCENE_SPECIAL.checkobj, common.SCENE_SPECIAL.checkchar, common.SCENE_SPECIAL.option, common.SCENE_SPECIAL.showopt]: output.append("********************\n\n") if line_numbers: output.append("[%04d.txt]" % script.scene_info.file_id) output.append("\n") output.append("[%s]\n" % (common.CHAR_IDS[script.scene_info.speaker] if script.scene_info.speaker in common.CHAR_IDS else "N/A")) if not voice == None: # output.append(" [Voice: %04d.at3, %s]\n" % (voice, common.CHAR_IDS[script.scene_info.voice.char_id] if script.scene_info.voice.char_id in common.CHAR_IDS else "N/A")) output.append("[Voice: %04d.at3" % (voice)) if script.scene_info.voice.chapter == 0x63: output.append(" (Generic)") output.append("]\n") # output.append("\n") line = "" if translated and script.translated: if strip_clt: line = script.translated_notags else: line = script.translated else: if strip_clt: line = script.original_notags else: line = script.original output.append(" %s" % line.strip().replace("\n", "\n ")) output.append("\n\n") return u''.join(output)
def load(self, filename): filename = filename.lower() if not filename in MTB_DIR: _LOGGER.error("Invalid MTB file: %s" % filename) return self.filename = filename script_dir = MTB_DIR[filename] self.script_pack = ScriptPack(script_dir, common.editor_config.umdimage_dir) # --- MTB FORMAT --- # 12 bytes -- ??? # XX XX XX XX -- Table offset # 24 bytes -- ??? # # XX XX -- MTB Index # XX XX -- Char ID for sprites # XX XX -- Char ID for voices (chapter for voices is 0x63) # XX XX -- Initial sprite ID (?) mtb = ConstBitStream(filename=os.path.join( common.editor_config.umdimage_dir, self.filename)) mtb.read(12 * 8) table_offset = mtb.read("uintle:32") mtb.read(24 * 8) mtb_index = mtb.read("uintle:16") sprite_char = mtb.read("uintle:16") voice_char = mtb.read("uintle:16") sprite_id = mtb.read("uintle:16") sprite = SpriteId(SPRITE_TYPE.stand, sprite_char, sprite_id) # --- TABLE FORMAT --- # XX XX XX XX -- Number of files # # [for each line] # XX XX XX XX -- Offset (from table start) of voice info. # # -- Voice Info -- # XX XX -- File ID # XX XX -- Voice ID (with char ID above and the chapter ID 0x63, we know which voice file to use) mtb.bytepos = table_offset num_files = mtb.read("uintle:32") for i in range(num_files): voice_offset = mtb.read("uintle:32") # Store our position in the table so we can jump back to it. table_pos = mtb.bytepos mtb.bytepos = table_offset + voice_offset file_id = mtb.read("uintle:16") voice_id = mtb.read("uintle:16") # Chapter is 0x63, which is where the non-Trial voice samples are stored, # but I don't see the information actually recorded in the MTB files, # so I'm magic-numbering it here. voice = VoiceId(voice_char, 0x63, voice_id) self.script_pack[file_id].scene_info.sprite = sprite self.script_pack[file_id].scene_info.voice = voice # Restore it to our old position. mtb.bytepos = table_pos
def __init__(self): self.script_pack = ScriptPack() self.filename = ""
def script_to_text(dir, translated = True, strip_clt = False, only_voiced = False, line_numbers = True): script_pack = ScriptPack() if dir[:7] == "nonstop": parser = NonstopParser() parser.load(dir) script_pack = parser.script_pack elif dir[:8] == "hs_mtb_s": parser = MTBParser() parser.load(dir) script_pack = parser.script_pack elif dir[:7] == "anagram": return u"" else: script_pack.load_dir(dir, common.editor_config.data01_dir) # pack = ScriptPack(directory = dir, umdimage = "X:/Danganronpa/Demo_FINAL/umdimage/") output = [] if len(script_pack) > 0: output.append("==================================================\n=== %s" % dir) room = get_map_name(script_pack[0].scene_info.room) if not room == None: output.append("\n=== Room: %s" % room) output.append("\n==================================================\n\n") for script in script_pack: voice = get_voice_file(script.scene_info.voice) if voice == None and only_voiced: continue if script.scene_info.special in [common.SCENE_SPECIAL.checkobj, common.SCENE_SPECIAL.checkchar, common.SCENE_SPECIAL.option, common.SCENE_SPECIAL.showopt]: output.append("********************\n\n") if line_numbers: output.append("[%04d.txt]" % script.scene_info.file_id) output.append("\n") char_name = get_char_name(script.scene_info.speaker) output.append("[%s]\n" % (char_name if char_name else "N/A")) if not voice == None: # output.append(" [Voice: %04d.at3, %s]\n" % (voice, common.CHAR_IDS[script.scene_info.voice.char_id] if script.scene_info.voice.char_id in common.CHAR_IDS else "N/A")) output.append("[Voice: %04d.at3" % (voice)) if script.scene_info.voice.chapter == 0x63: output.append(" (Generic)") output.append("]\n") # output.append("\n") line = "" if translated and script[common.editor_config.lang_trans]: if strip_clt: line = script.notags[common.editor_config.lang_trans] else: line = script[common.editor_config.lang_trans] else: if strip_clt: line = script.notags[common.editor_config.lang_orig] else: line = script[common.editor_config.lang_orig] output.append(" %s" % line.strip().replace("\n", "\n ")) output.append("\n\n") return u''.join(output)