diff --git a/.gitignore b/.gitignore index 4709183..6302b72 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,8 @@ +.DS_Store + # Godot 4+ specific ignores .godot/ + +export_presets.cfg + +/AuthKey_VSYTQ75GZQ.p8 diff --git a/AssetLoaders/Enums.gd b/AssetLoaders/Enums.gd new file mode 100644 index 0000000..57aadf3 --- /dev/null +++ b/AssetLoaders/Enums.gd @@ -0,0 +1,70 @@ +class_name Enums + +enum TileID { + TileVoid = 0, + TileBlank = 1, + TileHome = 2, + TileBattle = 3, + TileDraw = 4, + TileBonus = 5, + TileDrop = 6, + TileWarp = 7, + TileDrawx2 = 8, + TileBonusx2 = 9, + TileDropx2 = 10, + TileFlatWall = 11, + TileVoid2 = 12, # i'm not sure why there's 8 voids, or if they're even used + TileVoid3 = 13, + TileVoid4 = 14, + TileVoid5 = 15, + TileVoid6 = 16, + TileVoid7 = 17, + TileDeck = 18, + TileVoid8 = 19, + TileBattlex2 = 20, + TileMove = 21, + TileMovex2 = 22, + TileWarpMove = 23, + TileWarpMovex2 = 24, + TileIce = 25, + TileSnow = 26, + TileHeal = 27, + TileHealx2 = 28, + TileEvent = 29, # OJEdit says "Event (Blank Tile)" + TileUnknown = 30, + TileCoopBoss = 31, + TileDamage = 32, + TileDamagex2 = 33 +} + +static func get_tile_texture(id: int): + match id: + 0: return "" + 1: return "mass_common0.dat" + 2: return "mass_check0.dat" + 3: return "mass_encount0.dat" + 4: return "mass_draw0.dat" + 5: return "mass_bonus0.dat" + 6: return "mass_drop0.dat" + 7: return "mass_warp0.dat" + 8: return "mass_drawL2.dat" + 9: return "mass_bonusL2.dat" + 10: return "mass_dropL2.dat" + 11: return "mass_common0.dat" + 12, 13, 14, 15, 16, 17: return "" + 18: return "mass_editordeck.dat" + 19: return "" + 20: return "mass_encountL2.dat" + 21: return "mass_move0.dat" + 22: return "mass_moveL2.dat" + 23: return "mass_warpmove0.dat" + 24: return "mass_warpmoveL2.dat" + 25: return "mass_snow0.dat" + 26: return "mass_snow0.dat" + 27: return "mass_heal0.dat" + 28: return "mass_healL2.dat" + 29: return "mass_common0.dat" + 30: return "mass_common0.dat" + 31: return "mass_boss.dat" + 32: return "mass_damage.dat" + 33: return "mass_damageL2.dat" \ No newline at end of file diff --git a/AssetLoaders/PakAssetLoader.gd b/AssetLoaders/PakAssetLoader.gd new file mode 100644 index 0000000..bc5371d --- /dev/null +++ b/AssetLoaders/PakAssetLoader.gd @@ -0,0 +1,99 @@ +class_name PakAssetLoader + +static var key = "a8Yb5$IpVobR,1Xph!k(#!B9h$V[o[r-I'x.37Q%E;lt2wGgk)hNF_p_!mF?Ds54.*8ErbCK,30".to_utf8_buffer() + +#loads a file from a .pak file. +static func load_file(path: String): + var split = path.split(".pak/") + var pak = split[0] + var filename = split[1] + + var zip_reader = ZIPReader.new() + var err = zip_reader.open(pak + ".pak") + if err != OK: + report_errors(err, pak + ".pak") + zip_reader.close() + var bytes = zip_reader.read_file(filename) + zip_reader.close() + if bytes.size() == 0: + report_errors(ERR_FILE_NOT_FOUND, filename) + + if filename.ends_with(".dat"): + var magic = bytes[0]+bytes[1]+bytes[2]+bytes[3] + if magic == 0x25 + 0x7C + 0x0A + 0x42: #XOR'ed DDS file + unXOR(bytes) + magic = bytes[0]+bytes[1]+bytes[2]+bytes[3] + + if magic == 0x44 + 0x44 + 0x53 + 0x20: #DDS file + var header = bytes.slice(0, 0x80) + bytes = bytes.slice(0x80) + var height = header[0xc] + (header[0xd] * 256) + var width = header[0x10] + (header[0x11] * 256) + var format = header[0x54]+header[0x55]+header[0x56]+header[0x57] + if format == 0: + fix_BGRA(bytes) + var img = Image.create_from_data(width, height, false, Image.FORMAT_RGBA8, bytes) + return ImageTexture.create_from_image(img) + elif format == 0x44 + 0x58 + 0x54 + 0x35: + var img = Image.create_from_data(width, height, false, Image.FORMAT_DXT5, bytes) + return ImageTexture.create_from_image(img) + else: + report_errors(ERR_FILE_UNRECOGNIZED, filename) + return + else: + report_errors(ERR_FILE_UNRECOGNIZED, filename) + return + elif filename.ends_with(".ogg"): + var magic = bytes[0]+bytes[1]+bytes[2]+bytes[3] + + if magic == 0x4F + 0x67 + 0x67 + 0x53: + var stream = AudioStreamOggVorbis.load_from_buffer(bytes) + stream.loop = true + stream.loop_offset = get_loop_off(filename) + return stream + else: + report_errors(ERR_FILE_UNRECOGNIZED, filename) + elif filename.ends_with(".fld"): + return bytes + + +static func fix_BGRA(bytes: PackedByteArray): + for i in range(0, bytes.size(), 4): + var tmp = bytes[i] + bytes[i] = bytes[i+2] + bytes[i+2] = tmp + +static func unXOR(bytes: PackedByteArray): + for i in range(bytes.size()): + bytes[i] ^= key[i % key.size()] + + +static func get_loop_off(filename: String): + match filename: + "bgm/0.ogg": + return 1.72 + "bgm/1.ogg": + return 2 + + +static func report_errors(err: int, filepath): + # See: https://docs.godotengine.org/en/latest/classes/class_@globalscope.html#enum-globalscope-error + var result_hash = { + ERR_FILE_NOT_FOUND: "File: not found", + ERR_FILE_BAD_DRIVE: "File: Bad drive error", + ERR_FILE_BAD_PATH: "File: Bad path error.", + ERR_FILE_NO_PERMISSION: "File: No permission error.", + ERR_FILE_ALREADY_IN_USE: "File: Already in use error.", + ERR_FILE_CANT_OPEN: "File: Can't open error.", + ERR_FILE_CANT_WRITE: "File: Can't write error.", + ERR_FILE_CANT_READ: "File: Can't read error.", + ERR_FILE_UNRECOGNIZED: "File: Unrecognized error.", + ERR_FILE_CORRUPT: "File: Corrupt error.", + ERR_FILE_MISSING_DEPENDENCIES: "File: Missing dependencies error.", + ERR_FILE_EOF: "File: End of file (EOF) error." + } + if err in result_hash: + print("Error: ", result_hash[err], " ", filepath) + else: + print("Unknown error with file ", filepath, " error code: ", err) +