mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-10-01 11:18:22 +03:00
Android: Generate xsystem35.gr file
The installer writes xsystem35.gr file into the game root directory. Now save files are created at `files/save` directory, which is outside the game directory. This scheme is the same as Kichikuou on Web, so it would make transferring save data between two easier.
This commit is contained in:
@@ -41,7 +41,7 @@ class GameActivity : SDLActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
cdda = CddaPlayer(intent.getStringExtra(EXTRA_PLAYLIST_FILE))
|
||||
cdda = CddaPlayer(File(intent.getStringExtra(EXTRA_PLAYLIST_FILE)))
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
@@ -81,15 +81,14 @@ class GameActivity : SDLActivity() {
|
||||
@Suppress("unused") fun midiCurrentPosition() = midi.currentPosition()
|
||||
}
|
||||
|
||||
private class CddaPlayer(playlistPath: String?) {
|
||||
private val playlist = playlistPath?.let {
|
||||
private class CddaPlayer(private val playlistPath: File) {
|
||||
private val playlist =
|
||||
try {
|
||||
File(it).readLines()
|
||||
playlistPath.readLines()
|
||||
} catch (e: IOException) {
|
||||
Log.e("loadPlaylist", "Cannot load $playlistPath", e)
|
||||
null
|
||||
emptyList<String>()
|
||||
}
|
||||
} ?: emptyList()
|
||||
private var currentTrack = 0
|
||||
private val player = MediaPlayer()
|
||||
private var playerPaused = false
|
||||
@@ -104,7 +103,7 @@ private class CddaPlayer(playlistPath: String?) {
|
||||
try {
|
||||
player.apply {
|
||||
reset()
|
||||
setDataSource(f)
|
||||
setDataSource(File(playlistPath.parent, f).path)
|
||||
isLooping = loop == 0
|
||||
prepare()
|
||||
start()
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.os.Message
|
||||
import android.util.Log
|
||||
import java.io.*
|
||||
import java.nio.charset.Charset
|
||||
import java.util.*
|
||||
import java.util.zip.ZipInputStream
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
@@ -61,9 +62,14 @@ class Launcher private constructor(private val rootDir: File) {
|
||||
private set
|
||||
|
||||
init {
|
||||
var saveDirFound = false
|
||||
for (path in rootDir.listFiles()) {
|
||||
if (!path.isDirectory)
|
||||
continue
|
||||
if (path.name == "save") {
|
||||
saveDirFound = true
|
||||
continue
|
||||
}
|
||||
try {
|
||||
val title = File(path, TITLE_FILE).readText()
|
||||
games.add(Entry(path, title))
|
||||
@@ -72,6 +78,9 @@ class Launcher private constructor(private val rootDir: File) {
|
||||
path.deleteRecursively()
|
||||
}
|
||||
}
|
||||
if (!saveDirFound) {
|
||||
File(rootDir, "save").mkdir()
|
||||
}
|
||||
}
|
||||
|
||||
fun install(input: InputStream) {
|
||||
@@ -118,7 +127,7 @@ class Launcher private constructor(private val rootDir: File) {
|
||||
|
||||
private fun extractFiles(input: InputStream, outDir: File, handler: Handler) {
|
||||
try {
|
||||
val playlistWriter = PlaylistWriter()
|
||||
val configWriter = GameConfigWriter()
|
||||
val zip = if (Build.VERSION.SDK_INT >= 24) {
|
||||
ZipInputStream(input.buffered(), Charset.forName("Shift_JIS"))
|
||||
} else {
|
||||
@@ -135,11 +144,13 @@ class Launcher private constructor(private val rootDir: File) {
|
||||
val output = FileOutputStream(path).buffered()
|
||||
zip.copyTo(output)
|
||||
output.close()
|
||||
playlistWriter.maybeAdd(path.path)
|
||||
configWriter.maybeAdd(zipEntry.name)
|
||||
}
|
||||
zip.close()
|
||||
playlistWriter.write(outDir)
|
||||
configWriter.write(outDir)
|
||||
handler.sendMessage(handler.obtainMessage(SUCCESS, outDir))
|
||||
} catch (e: InstallFailureException) {
|
||||
handler.sendMessage(handler.obtainMessage(FAILURE, e.msgId))
|
||||
} catch (e: UTFDataFormatException) {
|
||||
// Attempted to read Shift_JIS zip in Android < 7
|
||||
handler.sendMessage(handler.obtainMessage(FAILURE, R.string.unsupported_zip))
|
||||
@@ -149,12 +160,40 @@ class Launcher private constructor(private val rootDir: File) {
|
||||
}
|
||||
}
|
||||
|
||||
private class PlaylistWriter {
|
||||
class InstallFailureException(val msgId: Int) : Exception()
|
||||
|
||||
// A helper class which generates xsystem35.gr and playlist.txt in the game root directory.
|
||||
private class GameConfigWriter {
|
||||
private val grLines: ArrayList<String> = arrayListOf()
|
||||
private var basename: String? = null
|
||||
private val aldRegex = """(.*?)([a-z])([a-z])\.ald""".toRegex(RegexOption.IGNORE_CASE)
|
||||
private val resourceType = mapOf(
|
||||
"d" to "Data",
|
||||
"g" to "Graphics",
|
||||
"m" to "Midi",
|
||||
"r" to "Resource",
|
||||
"s" to "Scenario",
|
||||
"w" to "Wave")
|
||||
|
||||
private val audioRegex = """.*?(\d+)\.(wav|mp3|ogg)""".toRegex(RegexOption.IGNORE_CASE)
|
||||
private val audioFiles: Array<String?> = arrayOfNulls(100)
|
||||
|
||||
fun maybeAdd(path: String) {
|
||||
audioRegex.matchEntire(path)?.let {
|
||||
val name = File(path).name
|
||||
|
||||
if (name.toLowerCase(Locale.US) == "system39.ain") {
|
||||
grLines.add("Ain ${path}")
|
||||
return
|
||||
}
|
||||
aldRegex.matchEntire(name)?.let {
|
||||
val type = resourceType[it.groupValues[2]]
|
||||
val id = it.groupValues[3].toUpperCase(Locale.US)
|
||||
if (type != null) {
|
||||
grLines.add("$type$id $path")
|
||||
basename = it.groupValues[1]
|
||||
}
|
||||
}
|
||||
audioRegex.matchEntire(name)?.let {
|
||||
val track = it.groupValues[1].toInt()
|
||||
if (track < audioFiles.size)
|
||||
audioFiles[track] = path
|
||||
@@ -162,8 +201,17 @@ class Launcher private constructor(private val rootDir: File) {
|
||||
}
|
||||
|
||||
fun write(outDir: File) {
|
||||
val text = audioFiles.joinToString("\n") { it ?: "" }.trimEnd('\n')
|
||||
File(outDir, PLAYLIST_FILE).writeText(text)
|
||||
basename ?: throw InstallFailureException(R.string.cannot_find_ald)
|
||||
for (id in 'A' .. 'Z') {
|
||||
grLines.add("Save$id ../save/${basename}s${id.toLowerCase()}.asd")
|
||||
}
|
||||
grLines.add("")
|
||||
val gr = grLines.joinToString("\n")
|
||||
Log.d("xsystem35.gr", gr)
|
||||
File(outDir, "xsystem35.gr").writeText(gr)
|
||||
|
||||
val playlist = audioFiles.joinToString("\n") { it ?: "" }.trimEnd('\n')
|
||||
File(outDir, PLAYLIST_FILE).writeText(playlist)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,6 @@ import android.widget.ArrayAdapter
|
||||
import android.widget.ListView
|
||||
import java.io.*
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
class LauncherActivity : ListActivity(), AdapterView.OnItemLongClickListener, LauncherObserver {
|
||||
private lateinit var launcher: Launcher
|
||||
private lateinit var adapter: ArrayAdapter<String>
|
||||
@@ -100,14 +98,9 @@ class LauncherActivity : ListActivity(), AdapterView.OnItemLongClickListener, La
|
||||
}
|
||||
|
||||
private fun startGame(path: File) {
|
||||
val gameRoot = findGameRoot(path)
|
||||
if (gameRoot == null) {
|
||||
errorDialog(R.string.cannot_find_ald)
|
||||
return
|
||||
}
|
||||
val i = Intent()
|
||||
i.setClass(applicationContext, GameActivity::class.java)
|
||||
i.putExtra(GameActivity.EXTRA_GAME_ROOT, gameRoot.path)
|
||||
i.putExtra(GameActivity.EXTRA_GAME_ROOT, path.path)
|
||||
i.putExtra(GameActivity.EXTRA_TITLE_FILE, File(path, Launcher.TITLE_FILE).path)
|
||||
i.putExtra(GameActivity.EXTRA_PLAYLIST_FILE, File(path, Launcher.PLAYLIST_FILE).path)
|
||||
startActivity(i)
|
||||
@@ -150,12 +143,3 @@ class ProgressDialogFragment : DialogFragment() {
|
||||
dialog.setMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
private fun findGameRoot(path: File): File? {
|
||||
path.walkTopDown().forEach {
|
||||
val name = it.name.toLowerCase(Locale.US)
|
||||
if (name == "xsystem35.gr" || name.endsWith(".ald"))
|
||||
return it.parentFile
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user