6502Android/app/src/main/kotlin/android/emu6502/nes/INESFileParser.kt

51 lines
1.8 KiB
Kotlin

package android.emu6502.nes
import java.io.DataInputStream
import java.io.File
import java.io.InputStream
internal class INESFileParser {
companion object {
internal val INES_FILE_MAGIC = byteArrayOf(0x4e, 0x45, 0x53, 0x1a)/*0x4e45531a*/
internal val PADDING = byteArrayOf(0, 0, 0, 0, 0, 0, 0)
internal fun parseFileHeader(stream: InputStream): INESFileHeader {
val dataStream = DataInputStream(stream.buffered())
return INESFileHeader(
(0..3).map { dataStream.readByte() }.toByteArray(),
dataStream.readByte(),
dataStream.readByte(),
dataStream.readByte(),
dataStream.readByte(),
dataStream.readByte(),
(0..6).map { dataStream.readByte() }.toByteArray())
}
internal fun parseCartridge(file: File): Cartridge =
file.inputStream().use {
val inesFileHeader = parseFileHeader(it)
// mapper type
val control1 = inesFileHeader.control1.toInt()
val mapper1 = control1 shr 4
val mapper2 = inesFileHeader.control2.toInt() shr 4
val mapper = mapper1 or (mapper2 shl 4)
// mirroring type
val mirror1 = control1 and 1
val mirror2 = (control1 shr 3) and 1
val mirror = mirror1 or (mirror2 shl 1)
// battery-backed RAM
val battery = (control1 shr 1).and(1).toByte()
// read prg-rom bank(s)
val prg = ByteArray(inesFileHeader.numPRG.toInt() * 16384)
it.read(prg)
// read chr-rom bank(s)
val chr = ByteArray(inesFileHeader.numCHR.toInt() * 8192)
it.read(chr)
return Cartridge(
prg.map(Byte::toInt).toIntArray(),
chr.map(Byte::toInt).toIntArray(),
mapper.toByte(), mirror, battery
)
}
}
}