195 lines
3.7 KiB
Go
195 lines
3.7 KiB
Go
package fds
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
type BlockType byte
|
|
|
|
const (
|
|
BtInfo BlockType = 0x01
|
|
BtFileAmount BlockType = 0x02
|
|
BtFileHeader BlockType = 0x03
|
|
BtFileData BlockType = 0x04
|
|
)
|
|
|
|
func (bt BlockType) String() string {
|
|
switch bt {
|
|
case BtInfo:
|
|
return "BlockInfo"
|
|
case BtFileAmount:
|
|
return "BlockAmount"
|
|
case BtFileHeader:
|
|
return "BlockFileHeader"
|
|
case BtFileData:
|
|
return "BlockFileData"
|
|
}
|
|
|
|
return "Unknown block"
|
|
}
|
|
|
|
type DiskBlock interface {
|
|
Type() BlockType
|
|
String() string
|
|
}
|
|
|
|
// Block 1
|
|
type BlockInfo struct {
|
|
// always 0x01
|
|
BlockCode byte
|
|
|
|
// literal ASCII: "*NINTENDO-HVC*"
|
|
DiskVerification [14]byte
|
|
Licensee uint8
|
|
|
|
// 3 byte ASCII code
|
|
GameName [3]byte
|
|
|
|
// 0x20: " " normal disk
|
|
// 0x45: "E" Event
|
|
// 0x4A: "J" Unknown
|
|
// 0x52: "R" Reduction in price via advert (lmao what?)
|
|
GameType uint8
|
|
|
|
GameVersion uint8
|
|
SideNumber uint8
|
|
DiskNumber uint8
|
|
|
|
// 0x01 for FMC blue-disk
|
|
// 0x00 otherwise
|
|
DiskType uint8
|
|
|
|
Unknown_18 uint8 // unknown; 0x00 in all known games
|
|
|
|
BootReadFileCode uint8
|
|
|
|
Unknown_1A [5]byte // unknown; 0xFF x5
|
|
|
|
// BCD YMD, but 1-indexed from Japanese calendar era (fuck you, lmao).
|
|
ManufacturingDate [3]byte
|
|
|
|
CountryCode uint8 // 0x49 = japan
|
|
Unknown_23 uint8 // region code?
|
|
Unknown_24 uint8 // location/site?
|
|
Unknown_25 [2]byte // raw: 0x00 0x22
|
|
Unknown_27 [5]byte // game info representation?
|
|
|
|
// BCD YMD (same as above). Disk Writer kiosk write date?
|
|
RewrittenDate [3]byte
|
|
|
|
Unknown_2F uint8
|
|
Unknown_30 uint8 // raw: 0x80
|
|
|
|
DiskWriterSerial uint16
|
|
|
|
Unknown_33 uint8 // raw: 0x07
|
|
|
|
// BCD format. 0x00 == original
|
|
RewriteCount byte
|
|
|
|
// 0x00 = SideA; 0x01 = SideB
|
|
ActualDiskSide uint8
|
|
|
|
// 0x00 yellow
|
|
// 0xFF blue
|
|
// 0xFE prototype/internal (white or pink)
|
|
DiskTypeOther uint8
|
|
|
|
DiskVersion uint8
|
|
|
|
// CRC-16/KERMIT. apparently this will work: github.com/sigurn/crc16
|
|
CRC uint16 // omitted from FDS files (fucking whyyyyyyy)
|
|
}
|
|
|
|
func (b *BlockInfo) Type() BlockType {
|
|
return BtInfo
|
|
}
|
|
|
|
func (b *BlockInfo) String() string {
|
|
return fmt.Sprintf("FdsBlockInfo Licensee:%02X GameName:%q GameType:%c",
|
|
b.Licensee,
|
|
b.GameName,
|
|
b.GameType,
|
|
)
|
|
}
|
|
|
|
const Template_FdsBlockInfo string = `Licensee: {{.Licensee}}
|
|
{{.LicEn}}
|
|
{{.LicJp}}
|
|
Name: {{.GameName}} Version: {{.GameVersion}} Type: {{.GameType}}`
|
|
|
|
func (b *BlockInfo) Info() string {
|
|
return "yup"
|
|
}
|
|
|
|
//func (b *BlockInfo) Info() string {
|
|
// return fmt.Sprintf("Licensee:%02X\n %s\n %s\nGameName: %s",
|
|
// b.Licensee,
|
|
// LicenseeEnName(b.Licensee),
|
|
// LicenseeJpName(b.Licensee),
|
|
// )
|
|
//}
|
|
|
|
type BlockFileAmount struct {
|
|
BlockCode byte // raw: 0x02
|
|
FileAmount uint8
|
|
CRC uint16 // omitted from FDS files (fucking whyyyyyyy)
|
|
}
|
|
|
|
func (b *BlockFileAmount) Type() BlockType {
|
|
return BtFileAmount
|
|
}
|
|
|
|
func (b *BlockFileAmount) String() string {
|
|
return fmt.Sprintf("BlockFileAmount FileAmount:%d", b.FileAmount)
|
|
}
|
|
|
|
type BlockFileHeader struct {
|
|
BlockCode byte // raw: 0x03
|
|
|
|
FileNumber uint8
|
|
FileId uint8
|
|
FileName [8]byte
|
|
FileAddress uint16 // destination when loading
|
|
FileSize uint16
|
|
|
|
// 0x00: Program (PRAM)
|
|
// 0x01: Character (CRAM)
|
|
// 0x02: Nametable (VRAM)
|
|
FileType uint8
|
|
|
|
CRC uint16 // omitted from FDS files (fucking whyyyyyyy)
|
|
}
|
|
|
|
func (b *BlockFileHeader) Type() BlockType {
|
|
return BtFileHeader
|
|
}
|
|
|
|
func (b *BlockFileHeader) String() string {
|
|
return fmt.Sprintf("BlockFileHeader FileNumber:%d FileId:%d FileName:%q FileAddress:$%04X FileSize:%d FileType:%d",
|
|
b.FileNumber,
|
|
b.FileId,
|
|
string(b.FileName[:]),
|
|
b.FileAddress,
|
|
b.FileSize,
|
|
b.FileType,
|
|
)
|
|
}
|
|
|
|
type BlockFileData struct {
|
|
BlockCode byte // raw: 0x04
|
|
|
|
// Disk data (FdsFileHeader.FileSize length)
|
|
Data []byte
|
|
|
|
CRC uint16 // omitted from FDS files (fucking whyyyyyyy)
|
|
}
|
|
|
|
func (b *BlockFileData) Type() BlockType {
|
|
return BtFileData
|
|
}
|
|
|
|
func (b *BlockFileData) String() string {
|
|
return "BlockFileData"
|
|
}
|