adding 'kind flag' to the savegame format so the file can be determined if it contains player or world data

This commit is contained in:
minjaesong
2022-12-04 16:09:07 +09:00
parent 400cdd5b3c
commit b2479028af
7 changed files with 62 additions and 16 deletions

View File

@@ -195,7 +195,7 @@ class SavegameCracker(
it.entries.toSortedMap().forEach { (i, entry) ->
if (i != 0L) println(
ccNoun + i.toString(10).padStart(11, ' ') + " " +
ccNoun2 + (diskIDtoReadableFilename(entry.entryID) + cc0).padEnd(40) { if (it == 0) ' ' else '.' } +
ccNoun2 + (diskIDtoReadableFilename(entry.entryID, it.saveKind) + cc0).padEnd(40) { if (it == 0) ' ' else '.' } +
ccConst + " " + entry.contents.getSizePure() + " bytes"
)
}

View File

@@ -62,6 +62,7 @@ class WorldSavingThread(
override fun save() {
disk.saveMode = 2 * isAuto.toInt() // no quick
disk.saveKind = VDSaveKind.WORLD_DATA
if (hasThumbnail) {
while (!IngameRenderer.fboRGBexportedLatch) {
@@ -224,6 +225,7 @@ class PlayerSavingThread(
override fun save() {
disk.saveMode = 2 * isAuto.toInt() // no quick
disk.saveKind = VDSaveKind.PLAYER_DATA
disk.capacity = 0L
WriteSavegame.saveProgress = 0f

View File

@@ -140,9 +140,12 @@ class QuickSingleplayerWorldSavingThread(
}
disk.saveKind = VDSaveKind.WORLD_DATA
skimmer.rewriteDirectories()
skimmer.injectDiskCRC(disk.hashCode())
skimmer.setSaveMode(1 + 2 * isAuto.toInt())
skimmer.setSaveKind(VDSaveKind.WORLD_DATA)
printdbg(this, "Game saved with size of ${outFile.length()} bytes")

View File

@@ -169,10 +169,10 @@ removefile:
if (typeFlag > 0) {
entryToOffsetTable[entryID] = offset
debugPrintln("[DiskSkimmer] ... successfully read the entry $entryID at offset $offset (name: ${diskIDtoReadableFilename(entryID)})")
debugPrintln("[DiskSkimmer] ... successfully read the entry $entryID at offset $offset (name: ${diskIDtoReadableFilename(entryID, getSaveKind())})")
}
else {
debugPrintln("[DiskSkimmer] ... discarding entry $entryID at offset $offset (name: ${diskIDtoReadableFilename(entryID)})")
debugPrintln("[DiskSkimmer] ... discarding entry $entryID at offset $offset (name: ${diskIDtoReadableFilename(entryID, getSaveKind())})")
}
}
@@ -343,11 +343,21 @@ removefile:
fa.writeByte(bits)
}
fun setSaveKind(bits: Int) {
fa.seek(50L)
fa.writeByte(bits)
}
fun getSaveMode(): Int {
fa.seek(49L)
return fa.read()
}
fun getSaveKind(): Int {
fa.seek(50L)
return fa.read()
}
override fun getDiskName(charset: Charset): String {
val bytes = ByteArray(268)
fa.seek(10L)

View File

@@ -173,7 +173,7 @@ object VDUtil {
val crcMsg =
"CRC failed: stored value is ${entryCRC.toHex()}, but calculated value is ${calculatedCRC.toHex()}\n" +
"at file \"${diskIDtoReadableFilename(diskEntry.entryID)}\" (entry ID ${diskEntry.entryID})"
"at file \"${diskIDtoReadableFilename(diskEntry.entryID, vdisk.saveKind)}\" (entry ID ${diskEntry.entryID})"
if (calculatedCRC != entryCRC) {
@@ -196,7 +196,7 @@ object VDUtil {
}
}
catch (e: ArrayIndexOutOfBoundsException) {
System.err.println("An error occurred while reading a file (entryID: $entryID (${diskIDtoReadableFilename(entryID)}), typeFlag: $entryTypeFlag)")
System.err.println("An error occurred while reading a file (entryID: $entryID (${diskIDtoReadableFilename(entryID, vdisk.saveKind)}), typeFlag: $entryTypeFlag)")
System.err.println("Stack trace:")
e.printStackTrace()
break

View File

@@ -1,6 +1,8 @@
package net.torvald.terrarum.savegame
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.savegame.VDSaveKind.PLAYER_DATA
import net.torvald.terrarum.savegame.VDSaveKind.WORLD_DATA
import net.torvald.terrarum.serialise.Common
import net.torvald.terrarum.serialise.toUint
import java.io.File
@@ -66,12 +68,18 @@ Version 254 is a customised version of TEVD tailored to be used as a savegame fo
4. for elems on list: update crc with the elem (crc = calculateCRC(crc, elem))
Int8 Version
Int8 0xFE
< BEGIN extraInfoBytes >
Int8 Disk properties flag 1
0th bit: readonly
Int8 Save type
0th bit: unset - full save; set - quick save
1st bit: set - generated by autosave
Int8[14] Extra info bytes
0th bit: unset - full save; set - quick save
1st bit: set - generated by autosave
Int8 Kind of the Save file
0: Undefined (old version of the game?)
1: Player Data
2: World Data
Int8[13] Extra info bytes
< END extraInfoBytes >
Unit8[236] Rest of the long disk name (268 bytes total)
(Header size: 300 bytes)
@@ -141,6 +149,9 @@ class VirtualDisk(
var saveMode: Int
set(value) { extraInfoBytes[1] = value.toByte() }
get() = extraInfoBytes[1].toUint()
var saveKind: Int
set(value) { extraInfoBytes[2] = value.toByte() }
get() = extraInfoBytes[2].toUint()
override fun getDiskName(charset: Charset) = diskName.toCanonicalString(charset)
val root: DiskEntry
get() = entries[0]!!
@@ -234,6 +245,12 @@ class VirtualDisk(
}
}
object VDSaveKind {
const val UNDEFINED = 0
const val PLAYER_DATA = 1
const val WORLD_DATA = 2
}
object VDFileID {
const val ROOT = 0L
const val SAVEGAMEINFO = -1L
@@ -245,11 +262,21 @@ object VDFileID {
const val BODYPARTGLOW_TO_ENTRY_MAP = -1026L
}
fun diskIDtoReadableFilename(id: EntryID): String = when (id) {
fun diskIDtoReadableFilename(id: EntryID, saveKind: Int?): String = when (id) {
VDFileID.ROOT -> "root"
VDFileID.SAVEGAMEINFO -> "savegameinfo.json"
VDFileID.THUMBNAIL, VDFileID.SPRITEDEF -> "thumbnail.tga.gz (world)/spritedef (player)"
VDFileID.SPRITEDEF_GLOW -> "spritedef-glow (player)"
VDFileID.THUMBNAIL, VDFileID.SPRITEDEF ->
if (saveKind == PLAYER_DATA)
"spritedef"
else if (saveKind == WORLD_DATA)
"thumbnail.tga.gz"
else
"thumbnail.tga.gz (world)/spritedef (player)"
VDFileID.SPRITEDEF_GLOW ->
if (saveKind == PLAYER_DATA)
"spritedef-glow"
else
"file #$id"
VDFileID.LOADORDER -> "loadOrder.txt"
// -16L -> "blockcodex.json.gz"
// -17L -> "itemcodex.json.gz"
@@ -259,7 +286,11 @@ fun diskIDtoReadableFilename(id: EntryID): String = when (id) {
// -1024L -> "apocryphas.json.gz"
VDFileID.BODYPART_TO_ENTRY_MAP -> "bodypart-to-entry.map"
VDFileID.BODYPARTGLOW_TO_ENTRY_MAP -> "bodypartglow-to-entry.map"
in 1..65535 -> "bodypart #$id.tga.gz (player)"
in 1..65535 ->
if (saveKind == PLAYER_DATA)
"bodypart #$id.tga.gz"
else
"file #$id"
in 1048576..2147483647 -> "actor #$id.json"
in 0x0000_0001_0000_0000L..0x0000_FFFF_FFFF_FFFFL ->
"World${id.ushr(32)}-L${id.and(0xFF00_0000).ushr(24)}-C${id.and(0xFFFFFF)}.gz"
@@ -324,7 +355,7 @@ class DiskEntry(
override fun equals(other: Any?) = if (other == null) false else this.hashCode() == other.hashCode()
override fun toString() = "DiskEntry(name: ${diskIDtoReadableFilename(entryID)}, ID: $entryID, parent: $parentEntryID, type: ${contents.getTypeFlag()}, contents size: ${contents.getSizeEntry()}, crc: ${hashCode().toHex()})"
override fun toString() = "DiskEntry(name: ${diskIDtoReadableFilename(entryID, null)}, ID: $entryID, parent: $parentEntryID, type: ${contents.getTypeFlag()}, contents size: ${contents.getSizeEntry()}, crc: ${hashCode().toHex()})"
}

View File

@@ -139,7 +139,7 @@ class VirtualDiskCracker(val sysCharset: Charset = Charsets.UTF_8) : JFrame() {
if (vdisk != null) {
val entry = currentDirectoryEntries!![rowIndex - 1]
return when(columnIndex) {
0 -> diskIDtoReadableFilename(entry.entryID)
0 -> diskIDtoReadableFilename(entry.entryID, vdisk?.saveKind)
1 -> Instant.ofEpochSecond(entry.modificationDate).
atZone(TimeZone.getDefault().toZoneId()).
format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
@@ -623,7 +623,7 @@ class VirtualDiskCracker(val sysCharset: Charset = Charsets.UTF_8) : JFrame() {
private fun updateDiskInfo() {
val sb = StringBuilder()
directoryHierarchy.forEach {
sb.append(diskIDtoReadableFilename(it))
sb.append(diskIDtoReadableFilename(it, vdisk?.saveKind))
sb.append('/')
}
sb.dropLast(1)
@@ -647,7 +647,7 @@ Write protected: ${disk.isReadOnly.toEnglish()}"""
private fun getFileInfoText(file: DiskEntry): String {
return """Name: ${diskIDtoReadableFilename(file.entryID)}
return """Name: ${diskIDtoReadableFilename(file.entryID, vdisk?.saveKind)}
Size: ${file.getEffectiveSize()}
Type: ${DiskEntry.getTypeString(file.contents)}
CRC: ${file.hashCode().toHex()}