Initial commit
Bare-bones functionality so far. Lists blocks in a rom with minimal information.
This commit is contained in:
commit
93c056db49
|
|
@ -0,0 +1,2 @@
|
||||||
|
bin/
|
||||||
|
*.fds
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
CMDS= \
|
||||||
|
bin/fdslist
|
||||||
|
|
||||||
|
all: bin $(CMDS)
|
||||||
|
|
||||||
|
bin:
|
||||||
|
mkdir bin
|
||||||
|
|
||||||
|
bin/%: cmd/%.go *.go
|
||||||
|
go build -o $@ $<
|
||||||
|
|
@ -0,0 +1,194 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
BoodReadFileCode 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"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
//"encoding/binary"
|
||||||
|
//"bufio"
|
||||||
|
//"bytes"
|
||||||
|
//"io"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/alexflint/go-arg"
|
||||||
|
|
||||||
|
"git.zorchenhimer.com/go-fds"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Arguments struct {
|
||||||
|
Input string `arg:"positional,required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
args := &Arguments{}
|
||||||
|
arg.MustParse(args)
|
||||||
|
|
||||||
|
err := run(args)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(args *Arguments) error {
|
||||||
|
file, err := os.Open(args.Input)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
//reader := bufio.NewReader(file)
|
||||||
|
//magic, err := reader.Peek(4)
|
||||||
|
//if err != nil {
|
||||||
|
// return fmt.Errorf("Unable to peek header: %w", err)
|
||||||
|
//}
|
||||||
|
|
||||||
|
//header := &fds.FdsHeader{}
|
||||||
|
|
||||||
|
//// "FDS" + EOF. header may be omitted.
|
||||||
|
//if bytes.Equal(magic, []byte{0x46, 0x44, 0x53, 0x1A}) {
|
||||||
|
// err = binary.Read(reader, binary.LittleEndian, header)
|
||||||
|
// if err != nil {
|
||||||
|
// return fmt.Errorf("Error reading header: %w", err)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if header != nil {
|
||||||
|
// fmt.Println("Header found. sides:", header.Sides)
|
||||||
|
//} else {
|
||||||
|
// fmt.Println("No header")
|
||||||
|
//}
|
||||||
|
|
||||||
|
//blocks, err := fds.ReadBlocks(reader, true)
|
||||||
|
//if err != nil {
|
||||||
|
// return err
|
||||||
|
//}
|
||||||
|
|
||||||
|
rom, err := fds.ReadRom(file, filepath.Ext(args.Input) == ".fds")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, block := range rom.Blocks {
|
||||||
|
fmt.Println(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
module git.zorchenhimer.com/go-fds
|
||||||
|
|
||||||
|
go 1.25.4
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/alexflint/go-arg v1.6.0
|
||||||
|
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1
|
||||||
|
)
|
||||||
|
|
||||||
|
require github.com/alexflint/go-scalar v1.2.0 // indirect
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
github.com/alexflint/go-arg v1.6.0 h1:wPP9TwTPO54fUVQl4nZoxbFfKCcy5E6HBCumj1XVRSo=
|
||||||
|
github.com/alexflint/go-arg v1.6.0/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8=
|
||||||
|
github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw=
|
||||||
|
github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1 h1:NVK+OqnavpyFmUiKfUMHrpvbCi2VFoWTrcpI7aDaJ2I=
|
||||||
|
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
@ -0,0 +1,599 @@
|
||||||
|
package fds
|
||||||
|
|
||||||
|
func LicenseeEnName(id byte) string {
|
||||||
|
lic, ok := Licensees[id]
|
||||||
|
if !ok {
|
||||||
|
return "????"
|
||||||
|
}
|
||||||
|
|
||||||
|
return lic.English
|
||||||
|
}
|
||||||
|
|
||||||
|
func LicenseeJpName(id byte) string {
|
||||||
|
lic, ok := Licensees[id]
|
||||||
|
if !ok {
|
||||||
|
return "????"
|
||||||
|
}
|
||||||
|
|
||||||
|
return lic.Japanese
|
||||||
|
}
|
||||||
|
|
||||||
|
type Licensee struct {
|
||||||
|
Id byte
|
||||||
|
English string
|
||||||
|
Japanese string
|
||||||
|
}
|
||||||
|
|
||||||
|
var Licensees = map[byte]Licensee{
|
||||||
|
0x00: Licensee{ Id:0x00,
|
||||||
|
English:"<unlicensed>",
|
||||||
|
Japanese:"<非公認>" },
|
||||||
|
|
||||||
|
0x01: Licensee{ Id:0x01,
|
||||||
|
English:"Nintendo",
|
||||||
|
Japanese:"任天堂" },
|
||||||
|
|
||||||
|
0x07: Licensee{ Id:0x07,
|
||||||
|
English:"Nomura Securities? (unverified)",
|
||||||
|
Japanese:"野村證券? (未確認)" },
|
||||||
|
|
||||||
|
0x08: Licensee{ Id:0x08,
|
||||||
|
English:"Capcom",
|
||||||
|
Japanese:"カプコン" },
|
||||||
|
|
||||||
|
0x09: Licensee{ Id:0x09,
|
||||||
|
English:"Hot-B",
|
||||||
|
Japanese:"ホット・ビィ" },
|
||||||
|
|
||||||
|
0x0A: Licensee{ Id:0x0A,
|
||||||
|
English:"Jaleco",
|
||||||
|
Japanese:"ジャレコ" },
|
||||||
|
|
||||||
|
0x0B: Licensee{ Id:0x0B,
|
||||||
|
English:"Coconuts Japan Entertainment",
|
||||||
|
Japanese:"ココナッツジャパンエンターテイメント" },
|
||||||
|
|
||||||
|
0x13: Licensee{ Id:0x13,
|
||||||
|
English:"Electronic Arts (Japan)",
|
||||||
|
Japanese:"エレクトロニック・アーツ (日本)" },
|
||||||
|
|
||||||
|
0x18: Licensee{ Id:0x18,
|
||||||
|
English:"Hudson Soft",
|
||||||
|
Japanese:"ハドソン" },
|
||||||
|
|
||||||
|
0x21: Licensee{ Id:0x21,
|
||||||
|
English:"Tokai Engineering",
|
||||||
|
Japanese:"東海エンジニアリング" },
|
||||||
|
|
||||||
|
0x28: Licensee{ Id:0x28,
|
||||||
|
English:"Kemco (Japan)",
|
||||||
|
Japanese:"ケムコ (日本)" },
|
||||||
|
|
||||||
|
0x29: Licensee{ Id:0x29,
|
||||||
|
English:"SETA (Japan)",
|
||||||
|
Japanese:"セタ (日本)" },
|
||||||
|
|
||||||
|
0x2B: Licensee{ Id:0x2B,
|
||||||
|
English:"Tamtex",
|
||||||
|
Japanese:"タムテックス" },
|
||||||
|
|
||||||
|
0x35: Licensee{ Id:0x35,
|
||||||
|
English:"Hector Playing Interface (Hect)",
|
||||||
|
Japanese:"ヘクト" },
|
||||||
|
|
||||||
|
0x3D: Licensee{ Id:0x3D,
|
||||||
|
English:"Loriciel",
|
||||||
|
Japanese:"ロリシエル" },
|
||||||
|
|
||||||
|
0x3E: Licensee{ Id:0x3E,
|
||||||
|
English:"Gremlin",
|
||||||
|
Japanese:"グレムリン" },
|
||||||
|
|
||||||
|
0x40: Licensee{ Id:0x40,
|
||||||
|
English:"Seika Corporation",
|
||||||
|
Japanese:"セイカ" },
|
||||||
|
|
||||||
|
0x41: Licensee{ Id:0x41,
|
||||||
|
English:"Ubisoft",
|
||||||
|
Japanese:"ウビソフト" },
|
||||||
|
|
||||||
|
0x46: Licensee{ Id:0x46,
|
||||||
|
English:"System 3",
|
||||||
|
Japanese:"システム 3" },
|
||||||
|
|
||||||
|
0x49: Licensee{ Id:0x49,
|
||||||
|
English:"Irem",
|
||||||
|
Japanese:"アイレム" },
|
||||||
|
|
||||||
|
0x4A: Licensee{ Id:0x4A,
|
||||||
|
English:"Gakken",
|
||||||
|
Japanese:"学習研究社" },
|
||||||
|
|
||||||
|
0x50: Licensee{ Id:0x50,
|
||||||
|
English:"Absolute",
|
||||||
|
Japanese:"アブソールト" },
|
||||||
|
|
||||||
|
0x51: Licensee{ Id:0x51,
|
||||||
|
English:"Acclaim (NA)",
|
||||||
|
Japanese:"アクレイム (北米)" },
|
||||||
|
|
||||||
|
0x52: Licensee{ Id:0x52,
|
||||||
|
English:"Activision",
|
||||||
|
Japanese:"アクティビシォン" },
|
||||||
|
|
||||||
|
0x53: Licensee{ Id:0x53,
|
||||||
|
English:"American Sammy",
|
||||||
|
Japanese:"アメリカン サミー" },
|
||||||
|
|
||||||
|
0x54: Licensee{ Id:0x54,
|
||||||
|
English:"GameTek",
|
||||||
|
Japanese:"ガメテック" },
|
||||||
|
|
||||||
|
0x55: Licensee{ Id:0x55,
|
||||||
|
English:"Hi Tech Expressions",
|
||||||
|
Japanese:"ハイ テック エクスープレシオンス" },
|
||||||
|
|
||||||
|
0x56: Licensee{ Id:0x56,
|
||||||
|
English:"LJN",
|
||||||
|
Japanese:"LJN" },
|
||||||
|
|
||||||
|
0x57: Licensee{ Id:0x57,
|
||||||
|
English:"Matchbox Toys",
|
||||||
|
Japanese:"マッチョボックス トイズ" },
|
||||||
|
|
||||||
|
0x58: Licensee{ Id:0x58,
|
||||||
|
English:"Mattel",
|
||||||
|
Japanese:"マッテル" },
|
||||||
|
|
||||||
|
0x59: Licensee{ Id:0x59,
|
||||||
|
English:"Milton Bradley",
|
||||||
|
Japanese:"ミルトン ブラッドリー" },
|
||||||
|
|
||||||
|
0x5A: Licensee{ Id:0x5A,
|
||||||
|
English:"Mindscape / Software Toolworks",
|
||||||
|
Japanese:"マインドスケップ / ソフトワー トゥールウアクス" },
|
||||||
|
|
||||||
|
0x5B: Licensee{ Id:0x5B,
|
||||||
|
English:"SETA (NA)",
|
||||||
|
Japanese:"セタ (北米)" },
|
||||||
|
|
||||||
|
0x5C: Licensee{ Id:0x5C,
|
||||||
|
English:"Taxan",
|
||||||
|
Japanese:"タクサン" },
|
||||||
|
|
||||||
|
0x5D: Licensee{ Id:0x5D,
|
||||||
|
English:"Tradewest",
|
||||||
|
Japanese:"トレードワェスト" },
|
||||||
|
|
||||||
|
0x5E: Licensee{ Id:0x5E,
|
||||||
|
English:"INTV Corporation",
|
||||||
|
Japanese:"INTV" },
|
||||||
|
|
||||||
|
0x60: Licensee{ Id:0x60,
|
||||||
|
English:"Titus",
|
||||||
|
Japanese:"タイタス" },
|
||||||
|
|
||||||
|
0x61: Licensee{ Id:0x61,
|
||||||
|
English:"Virgin Games",
|
||||||
|
Japanese:"ヴァージン" },
|
||||||
|
|
||||||
|
0x67: Licensee{ Id:0x67,
|
||||||
|
English:"Ocean",
|
||||||
|
Japanese:"オシャン" },
|
||||||
|
|
||||||
|
0x69: Licensee{ Id:0x69,
|
||||||
|
English:"Electronic Arts (NA)",
|
||||||
|
Japanese:"エレクトロニック・アーツ (北米)" },
|
||||||
|
|
||||||
|
0x6B: Licensee{ Id:0x6B,
|
||||||
|
English:"Beam Software",
|
||||||
|
Japanese:"ビーム" },
|
||||||
|
|
||||||
|
0x6E: Licensee{ Id:0x6E,
|
||||||
|
English:"Elite Systems",
|
||||||
|
Japanese:"エリット" },
|
||||||
|
|
||||||
|
0x6F: Licensee{ Id:0x6F,
|
||||||
|
English:"Electro Brain",
|
||||||
|
Japanese:"エレクトロ ブレイン" },
|
||||||
|
|
||||||
|
0x70: Licensee{ Id:0x70,
|
||||||
|
English:"Infogrames",
|
||||||
|
Japanese:"インフォグレムス" },
|
||||||
|
|
||||||
|
0x72: Licensee{ Id:0x72,
|
||||||
|
English:"JVC",
|
||||||
|
Japanese:"JVC" },
|
||||||
|
|
||||||
|
0x73: Licensee{ Id:0x73,
|
||||||
|
English:"Parker Brothers",
|
||||||
|
Japanese:"パーカー ブロザーズ" },
|
||||||
|
|
||||||
|
0x75: Licensee{ Id:0x75,
|
||||||
|
English:"The Sales Curve / SCi",
|
||||||
|
Japanese:"ザ・セルズ・カーヴ / SCi" },
|
||||||
|
|
||||||
|
0x78: Licensee{ Id:0x78,
|
||||||
|
English:"THQ",
|
||||||
|
Japanese:"THQ" },
|
||||||
|
|
||||||
|
0x79: Licensee{ Id:0x79,
|
||||||
|
English:"Accolade",
|
||||||
|
Japanese:"アッコレド" },
|
||||||
|
|
||||||
|
0x7A: Licensee{ Id:0x7A,
|
||||||
|
English:"Triffix",
|
||||||
|
Japanese:"トリフィクス" },
|
||||||
|
|
||||||
|
0x7C: Licensee{ Id:0x7C,
|
||||||
|
English:"Microprose Software",
|
||||||
|
Japanese:"マイクロプロス" },
|
||||||
|
|
||||||
|
0x7F: Licensee{ Id:0x7F,
|
||||||
|
English:"Kemco (NA)",
|
||||||
|
Japanese:"ケムコ (北米)" },
|
||||||
|
|
||||||
|
0x80: Licensee{ Id:0x80,
|
||||||
|
English:"Misawa Entertainment",
|
||||||
|
Japanese:"ミサワエンターテインメント" },
|
||||||
|
|
||||||
|
0x83: Licensee{ Id:0x83,
|
||||||
|
English:"G. Amusements Co.",
|
||||||
|
Japanese:"ジー・アミューズメント" },
|
||||||
|
|
||||||
|
0x85: Licensee{ Id:0x85,
|
||||||
|
English:"G.O 1",
|
||||||
|
Japanese:"ジー・オー・ワン" },
|
||||||
|
|
||||||
|
0x86: Licensee{ Id:0x86,
|
||||||
|
English:"Tokuma Shoten Intermedia",
|
||||||
|
Japanese:"徳間書店インターメディア" },
|
||||||
|
|
||||||
|
0x89: Licensee{ Id:0x89,
|
||||||
|
English:"Nihon Maicom Kaihatsu (NMK)",
|
||||||
|
Japanese:"NMK" },
|
||||||
|
|
||||||
|
0x8B: Licensee{ Id:0x8B,
|
||||||
|
English:"BulletProof Software (BPS)",
|
||||||
|
Japanese:"BPS" },
|
||||||
|
|
||||||
|
0x8C: Licensee{ Id:0x8C,
|
||||||
|
English:"VIC Tokai",
|
||||||
|
Japanese:"ビック東海" },
|
||||||
|
|
||||||
|
0x8D: Licensee{ Id:0x8D,
|
||||||
|
English:"Sanritsu",
|
||||||
|
Japanese:"サンリツ" },
|
||||||
|
|
||||||
|
0x8E: Licensee{ Id:0x8E,
|
||||||
|
English:"Character Soft",
|
||||||
|
Japanese:"キャラクターソフト" },
|
||||||
|
|
||||||
|
0x8F: Licensee{ Id:0x8F,
|
||||||
|
English:"I'Max",
|
||||||
|
Japanese:"アイマックス" },
|
||||||
|
|
||||||
|
0x94: Licensee{ Id:0x94,
|
||||||
|
English:"Toaplan",
|
||||||
|
Japanese:"株式会社東亜プラン" },
|
||||||
|
|
||||||
|
0x95: Licensee{ Id:0x95,
|
||||||
|
English:"Varie",
|
||||||
|
Japanese:"バリエ" },
|
||||||
|
|
||||||
|
0x96: Licensee{ Id:0x96,
|
||||||
|
English:"Yonezawa Party Room 21 / S'Pal",
|
||||||
|
Japanese:"ヨネザワPR21 / エスパル" },
|
||||||
|
|
||||||
|
0x99: Licensee{ Id:0x99,
|
||||||
|
English:"Pack-In-Video",
|
||||||
|
Japanese:"パックインビデオ" },
|
||||||
|
|
||||||
|
0x9A: Licensee{ Id:0x9A,
|
||||||
|
English:"Nihon Bussan",
|
||||||
|
Japanese:"日本物産" },
|
||||||
|
|
||||||
|
0x9B: Licensee{ Id:0x9B,
|
||||||
|
English:"Tecmo",
|
||||||
|
Japanese:"テクモ" },
|
||||||
|
|
||||||
|
0x9C: Licensee{ Id:0x9C,
|
||||||
|
English:"Imagineer",
|
||||||
|
Japanese:"イマジニア" },
|
||||||
|
|
||||||
|
0x9E: Licensee{ Id:0x9E,
|
||||||
|
English:"Face",
|
||||||
|
Japanese:"フェイス" },
|
||||||
|
|
||||||
|
0xA2: Licensee{ Id:0xA2,
|
||||||
|
English:"Scorpion Soft",
|
||||||
|
Japanese:"スコーピオンソフト" },
|
||||||
|
|
||||||
|
0xA3: Licensee{ Id:0xA3,
|
||||||
|
English:"Broderbund",
|
||||||
|
Japanese:"ブロダーブンド" },
|
||||||
|
|
||||||
|
0xA4: Licensee{ Id:0xA4,
|
||||||
|
English:"Konami",
|
||||||
|
Japanese:"コナミ" },
|
||||||
|
|
||||||
|
0xA5: Licensee{ Id:0xA5,
|
||||||
|
English:"K. Amusement Leasing Co. (KAC)",
|
||||||
|
Japanese:"ケイ・アミューズメントリース" },
|
||||||
|
|
||||||
|
0xA6: Licensee{ Id:0xA6,
|
||||||
|
English:"Kawada Co., Ltd.",
|
||||||
|
Japanese:"河田" },
|
||||||
|
|
||||||
|
0xA7: Licensee{ Id:0xA7,
|
||||||
|
English:"Takara",
|
||||||
|
Japanese:"タカラ" },
|
||||||
|
|
||||||
|
0xA8: Licensee{ Id:0xA8,
|
||||||
|
English:"Royal Industries",
|
||||||
|
Japanese:"ロイヤル工業" },
|
||||||
|
|
||||||
|
0xA9: Licensee{ Id:0xA9,
|
||||||
|
English:"Tecnos",
|
||||||
|
Japanese:"テクノス" },
|
||||||
|
|
||||||
|
0xAA: Licensee{ Id:0xAA,
|
||||||
|
English:"Victor Musical Industries",
|
||||||
|
Japanese:"ビクター音楽産業" },
|
||||||
|
|
||||||
|
0xAB: Licensee{ Id:0xAB,
|
||||||
|
English:"Hi-Score Media Work",
|
||||||
|
Japanese:"ハイスコアメディアワーク" },
|
||||||
|
|
||||||
|
0xAC: Licensee{ Id:0xAC,
|
||||||
|
English:"Toei Animation",
|
||||||
|
Japanese:"東映動画" },
|
||||||
|
|
||||||
|
0xAD: Licensee{ Id:0xAD,
|
||||||
|
English:"Toho (Japan)",
|
||||||
|
Japanese:"東宝 (日本)" },
|
||||||
|
|
||||||
|
0xAE: Licensee{ Id:0xAE,
|
||||||
|
English:"TSS",
|
||||||
|
Japanese:"ティーエスエス" },
|
||||||
|
|
||||||
|
0xAF: Licensee{ Id:0xAF,
|
||||||
|
English:"Namco",
|
||||||
|
Japanese:"ナムコ" },
|
||||||
|
|
||||||
|
0xB0: Licensee{ Id:0xB0,
|
||||||
|
English:"Acclaim (Japan)",
|
||||||
|
Japanese:"アクレイム" },
|
||||||
|
|
||||||
|
0xB1: Licensee{ Id:0xB1,
|
||||||
|
English:"ASCII Corporation / Nexoft",
|
||||||
|
Japanese:"アスキー / Nexoft" },
|
||||||
|
|
||||||
|
0xB2: Licensee{ Id:0xB2,
|
||||||
|
English:"Bandai",
|
||||||
|
Japanese:"バンダイ" },
|
||||||
|
|
||||||
|
0xB3: Licensee{ Id:0xB3,
|
||||||
|
English:"Soft Pro Inc.",
|
||||||
|
Japanese:"ソフトプロ" },
|
||||||
|
|
||||||
|
0xB4: Licensee{ Id:0xB4,
|
||||||
|
English:"Enix",
|
||||||
|
Japanese:"エニックス" },
|
||||||
|
|
||||||
|
0xB5: Licensee{ Id:0xB5,
|
||||||
|
English:"dB-SOFT",
|
||||||
|
Japanese:"デービーソフト" },
|
||||||
|
|
||||||
|
0xB6: Licensee{ Id:0xB6,
|
||||||
|
English:"HAL Laboratory",
|
||||||
|
Japanese:"HAL研究所" },
|
||||||
|
|
||||||
|
0xB7: Licensee{ Id:0xB7,
|
||||||
|
English:"SNK",
|
||||||
|
Japanese:"SNK" },
|
||||||
|
|
||||||
|
0xB9: Licensee{ Id:0xB9,
|
||||||
|
English:"Pony Canyon",
|
||||||
|
Japanese:"ポニーキャニオン" },
|
||||||
|
|
||||||
|
0xBA: Licensee{ Id:0xBA,
|
||||||
|
English:"Culture Brain",
|
||||||
|
Japanese:"カルチャーブレーン" },
|
||||||
|
|
||||||
|
0xBB: Licensee{ Id:0xBB,
|
||||||
|
English:"Sunsoft",
|
||||||
|
Japanese:"サンソフト" },
|
||||||
|
|
||||||
|
0xBC: Licensee{ Id:0xBC,
|
||||||
|
English:"Toshiba EMI",
|
||||||
|
Japanese:"東芝EMI" },
|
||||||
|
|
||||||
|
0xBD: Licensee{ Id:0xBD,
|
||||||
|
English:"CBS/Sony Group",
|
||||||
|
Japanese:"CBS・ソニー" },
|
||||||
|
|
||||||
|
0xBF: Licensee{ Id:0xBF,
|
||||||
|
English:"Sammy Corporation",
|
||||||
|
Japanese:"サミー" },
|
||||||
|
|
||||||
|
0xC0: Licensee{ Id:0xC0,
|
||||||
|
English:"Taito",
|
||||||
|
Japanese:"タイトー" },
|
||||||
|
|
||||||
|
0xC1: Licensee{ Id:0xC1,
|
||||||
|
English:"Sunsoft / Ask Co., Ltd.",
|
||||||
|
Japanese:"サンソフト / アスク講談社" },
|
||||||
|
|
||||||
|
0xC2: Licensee{ Id:0xC2,
|
||||||
|
English:"Kemco",
|
||||||
|
Japanese:"ケムコ" },
|
||||||
|
|
||||||
|
0xC3: Licensee{ Id:0xC3,
|
||||||
|
English:"Square / Disk Original Group (DOG)",
|
||||||
|
Japanese:"スクウェア / ディスク・オリジナル・グループ" },
|
||||||
|
|
||||||
|
0xC4: Licensee{ Id:0xC4,
|
||||||
|
English:"Tokuma Shoten",
|
||||||
|
Japanese:"徳間書店" },
|
||||||
|
|
||||||
|
0xC5: Licensee{ Id:0xC5,
|
||||||
|
English:"Data East",
|
||||||
|
Japanese:"データイースト" },
|
||||||
|
|
||||||
|
0xC6: Licensee{ Id:0xC6,
|
||||||
|
English:"Tonkin House / Tokyo Shoseki",
|
||||||
|
Japanese:"トンキンハウス / 東京書籍" },
|
||||||
|
|
||||||
|
0xC7: Licensee{ Id:0xC7,
|
||||||
|
English:"East Cube / Toho (NA)",
|
||||||
|
Japanese:"イーストキューブ / 東宝 (北米)" },
|
||||||
|
|
||||||
|
0xC8: Licensee{ Id:0xC8,
|
||||||
|
English:"Koei",
|
||||||
|
Japanese:"コーエー" },
|
||||||
|
|
||||||
|
0xC9: Licensee{ Id:0xC9,
|
||||||
|
English:"UPL",
|
||||||
|
Japanese:"ユーピーエル" },
|
||||||
|
|
||||||
|
0xCA: Licensee{ Id:0xCA,
|
||||||
|
English:"Konami / Ultra / Palcom",
|
||||||
|
Japanese:"コナミ" },
|
||||||
|
|
||||||
|
0xCB: Licensee{ Id:0xCB,
|
||||||
|
English:"NTVIC / VAP",
|
||||||
|
Japanese:"バップ" },
|
||||||
|
|
||||||
|
0xCC: Licensee{ Id:0xCC,
|
||||||
|
English:"Use Co., Ltd.",
|
||||||
|
Japanese:"ユース" },
|
||||||
|
|
||||||
|
0xCD: Licensee{ Id:0xCD,
|
||||||
|
English:"Meldac",
|
||||||
|
Japanese:"メルダック" },
|
||||||
|
|
||||||
|
0xCE: Licensee{ Id:0xCE,
|
||||||
|
English:"Pony Canyon / FCI",
|
||||||
|
Japanese:"ポニーキャニオン" },
|
||||||
|
|
||||||
|
0xCF: Licensee{ Id:0xCF,
|
||||||
|
English:"Angel",
|
||||||
|
Japanese:"エンジェル" },
|
||||||
|
|
||||||
|
0xD0: Licensee{ Id:0xD0,
|
||||||
|
English:"Disco",
|
||||||
|
Japanese:"ディスコ" },
|
||||||
|
|
||||||
|
0xD1: Licensee{ Id:0xD1,
|
||||||
|
English:"Sofel",
|
||||||
|
Japanese:"ソフエル" },
|
||||||
|
|
||||||
|
0xD2: Licensee{ Id:0xD2,
|
||||||
|
English:"Bothtec, Inc. / Quest",
|
||||||
|
Japanese:"ボーステック / クエスト" },
|
||||||
|
|
||||||
|
0xD3: Licensee{ Id:0xD3,
|
||||||
|
English:"Sigma Enterprises",
|
||||||
|
Japanese:"シグマ商事" },
|
||||||
|
|
||||||
|
0xD4: Licensee{ Id:0xD4,
|
||||||
|
English:"Ask Corp.",
|
||||||
|
Japanese:"アスク講談社" },
|
||||||
|
|
||||||
|
0xD5: Licensee{ Id:0xD5,
|
||||||
|
English:"Kyugo Trading Co.",
|
||||||
|
Japanese:"九娯貿易" },
|
||||||
|
|
||||||
|
0xD6: Licensee{ Id:0xD6,
|
||||||
|
English:"Naxat Soft / Kaga Tech",
|
||||||
|
Japanese:"ナグザットソフト / 加賀テック" },
|
||||||
|
|
||||||
|
0xD8: Licensee{ Id:0xD8,
|
||||||
|
English:"Status",
|
||||||
|
Japanese:"ステイタス" },
|
||||||
|
|
||||||
|
0xD9: Licensee{ Id:0xD9,
|
||||||
|
English:"Banpresto",
|
||||||
|
Japanese:"バンプレスト" },
|
||||||
|
|
||||||
|
0xDA: Licensee{ Id:0xDA,
|
||||||
|
English:"Tomy",
|
||||||
|
Japanese:"トミー" },
|
||||||
|
|
||||||
|
0xDB: Licensee{ Id:0xDB,
|
||||||
|
English:"Hiro Co., Ltd.",
|
||||||
|
Japanese:"ヒロ" },
|
||||||
|
|
||||||
|
0xDD: Licensee{ Id:0xDD,
|
||||||
|
English:"Nippon Computer Systems (NCS) / Masaya Games",
|
||||||
|
Japanese:"日本コンピュータシステム / メサイヤゲームス" },
|
||||||
|
|
||||||
|
0xDE: Licensee{ Id:0xDE,
|
||||||
|
English:"Human Creative",
|
||||||
|
Japanese:"ヒューマン" },
|
||||||
|
|
||||||
|
0xDF: Licensee{ Id:0xDF,
|
||||||
|
English:"Altron",
|
||||||
|
Japanese:"アルトロン" },
|
||||||
|
|
||||||
|
0xE0: Licensee{ Id:0xE0,
|
||||||
|
English:"K.K. DCE",
|
||||||
|
Japanese:"K.K. DCE" },
|
||||||
|
|
||||||
|
0xE1: Licensee{ Id:0xE1,
|
||||||
|
English:"Towa Chiki",
|
||||||
|
Japanese:"トーワチキ" },
|
||||||
|
|
||||||
|
0xE2: Licensee{ Id:0xE2,
|
||||||
|
English:"Yutaka",
|
||||||
|
Japanese:"ユタカ" },
|
||||||
|
|
||||||
|
0xE3: Licensee{ Id:0xE3,
|
||||||
|
English:"Kaken Corporation",
|
||||||
|
Japanese:"科学技研株式会社" },
|
||||||
|
|
||||||
|
0xE5: Licensee{ Id:0xE5,
|
||||||
|
English:"Epoch",
|
||||||
|
Japanese:"エポック" },
|
||||||
|
|
||||||
|
0xE7: Licensee{ Id:0xE7,
|
||||||
|
English:"Athena",
|
||||||
|
Japanese:"アテナ" },
|
||||||
|
|
||||||
|
0xE8: Licensee{ Id:0xE8,
|
||||||
|
English:"Asmik",
|
||||||
|
Japanese:"アスミック" },
|
||||||
|
|
||||||
|
0xE9: Licensee{ Id:0xE9,
|
||||||
|
English:"Natsume",
|
||||||
|
Japanese:"ナツメ" },
|
||||||
|
|
||||||
|
0xEA: Licensee{ Id:0xEA,
|
||||||
|
English:"King Records",
|
||||||
|
Japanese:"キングレコード" },
|
||||||
|
|
||||||
|
0xEB: Licensee{ Id:0xEB,
|
||||||
|
English:"Atlus",
|
||||||
|
Japanese:"アトラス" },
|
||||||
|
|
||||||
|
0xEC: Licensee{ Id:0xEC,
|
||||||
|
English:"Sony Music Entertainment",
|
||||||
|
Japanese:"ソニー・ミュージックエンタテインメント" },
|
||||||
|
|
||||||
|
0xED: Licensee{ Id:0xED,
|
||||||
|
English:"Pixel Corporation",
|
||||||
|
Japanese:"ピクセル" },
|
||||||
|
|
||||||
|
0xEE: Licensee{ Id:0xEE,
|
||||||
|
English:"Information Global Service (IGS)",
|
||||||
|
Japanese:"アイ・ジー・エス" },
|
||||||
|
|
||||||
|
0xEF: Licensee{ Id:0xEF,
|
||||||
|
English:"Fujimic",
|
||||||
|
Japanese:"フジミック" },
|
||||||
|
|
||||||
|
0xF0: Licensee{ Id:0xF0,
|
||||||
|
English:"A-Wave",
|
||||||
|
Japanese:"エイ・ウェーブ" },
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
package fds
|
||||||
|
|
||||||
|
import (
|
||||||
|
//"os"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"github.com/sigurn/crc16"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ReadRom(r io.Reader, IsFds bool) (*Rom, error) {
|
||||||
|
reader := bufio.NewReader(r)
|
||||||
|
magic, err := reader.Peek(4)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Unable to peek header: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rom := &Rom{Header: &FdsHeader{}}
|
||||||
|
|
||||||
|
// "FDS" + EOF. header may be omitted.
|
||||||
|
if bytes.Equal(magic, FdsHeaderMagic) {
|
||||||
|
err = binary.Read(reader, binary.LittleEndian, rom.Header)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Error reading header: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rom.Blocks, err = ReadBlocks(reader, IsFds)
|
||||||
|
return rom, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadBlocks(r io.Reader, IsFds bool) ([]DiskBlock, error) {
|
||||||
|
blocks := []DiskBlock{}
|
||||||
|
dataSize := -1
|
||||||
|
readBytes := 0
|
||||||
|
|
||||||
|
reader := bufio.NewReader(r)
|
||||||
|
|
||||||
|
for {
|
||||||
|
raw, err := reader.Peek(1)
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocks, fmt.Errorf("error peeking block type: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var readLen int
|
||||||
|
var block DiskBlock
|
||||||
|
idByte := raw[0]
|
||||||
|
|
||||||
|
switch idByte {
|
||||||
|
case 0x01:
|
||||||
|
block = &BlockInfo{}
|
||||||
|
case 0x02:
|
||||||
|
block = &BlockFileAmount{}
|
||||||
|
case 0x03:
|
||||||
|
block = &BlockFileHeader{}
|
||||||
|
case 0x04:
|
||||||
|
block = &BlockFileData{}
|
||||||
|
|
||||||
|
// variable length
|
||||||
|
readLen = dataSize+3
|
||||||
|
|
||||||
|
case 0x00:
|
||||||
|
reader.Discard(1)
|
||||||
|
continue
|
||||||
|
|
||||||
|
default:
|
||||||
|
fmt.Printf("readBytes: %d ($%04X)\n", readBytes, readBytes)
|
||||||
|
return blocks, fmt.Errorf("Invalid block type: $%02X", idByte)
|
||||||
|
}
|
||||||
|
//fmt.Println("")
|
||||||
|
|
||||||
|
if idByte != 0x04 {
|
||||||
|
readLen = binary.Size(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
//fmt.Println("readLen:;", readLen)
|
||||||
|
// FDS doesn't have the two byte CRC in the data
|
||||||
|
if IsFds {
|
||||||
|
readLen -=2
|
||||||
|
}
|
||||||
|
|
||||||
|
//fmt.Println("readLen::", readLen)
|
||||||
|
buf := make([]byte, readLen)
|
||||||
|
n, err := io.ReadFull(reader, buf)
|
||||||
|
if err != nil {
|
||||||
|
return blocks, fmt.Errorf("Error reading block id 0x%02X: %w", idByte, err)
|
||||||
|
}
|
||||||
|
readBytes += n
|
||||||
|
|
||||||
|
//var sum uint16
|
||||||
|
if IsFds {
|
||||||
|
//sum = crc16.Checksum(buf, crc16.MakeTable(crc16.CRC16_KERMIT))
|
||||||
|
//fmt.Printf("checksum: %04X\n", sum)
|
||||||
|
buf = append(buf, []byte{0x00, 0x00}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
//fmt.Printf("idByte:$%02X\nreadLen:%d\nlen(buf):%d\nblocksize:%d\n", idByte, readLen, len(buf), binary.Size(block))
|
||||||
|
|
||||||
|
if idByte != 0x04 {
|
||||||
|
_, err = binary.Decode(buf, binary.LittleEndian, block)
|
||||||
|
if err != nil {
|
||||||
|
return blocks, fmt.Errorf("Error decoding block id 0x%02X: %w", idByte, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if idByte == 0x03 {
|
||||||
|
fh := block.(*BlockFileHeader)
|
||||||
|
dataSize = int(fh.FileSize)
|
||||||
|
} else {
|
||||||
|
dataSize = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
db := block.(*BlockFileData)
|
||||||
|
db.BlockCode = buf[0]
|
||||||
|
|
||||||
|
if !IsFds {
|
||||||
|
db.CRC = uint16(buf[len(buf)-2]) | (uint16(buf[len(buf)-2])<<8)
|
||||||
|
readLen -= 2
|
||||||
|
|
||||||
|
} else {
|
||||||
|
db.CRC = crc16.Checksum(buf[:len(buf)-2], crc16.MakeTable(crc16.CRC16_KERMIT))
|
||||||
|
}
|
||||||
|
|
||||||
|
db.Data = buf[1:readLen]
|
||||||
|
//fmt.Println("len(db.Data)", len(db.Data))
|
||||||
|
block = db
|
||||||
|
//fmt.Printf("Block:%#v\n", block)
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks = append(blocks, block)
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//func ReadBlocksFds(r io.Reader) ([]FdsBlock, error) {
|
||||||
|
// reader := bufio.NewReader(r)
|
||||||
|
//
|
||||||
|
// var dataSize int
|
||||||
|
// blocks := []FdsBlock{}
|
||||||
|
// for {
|
||||||
|
// typ, err := reader.Peek(1)
|
||||||
|
// if err != nil {
|
||||||
|
// if err == io.EOF {
|
||||||
|
// break
|
||||||
|
// } else {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if len(typ) != 1 {
|
||||||
|
// return nil, fmt.Errorf("typ read length error")
|
||||||
|
// }
|
||||||
|
// //fmt.Printf("typ: %v\n", typ)
|
||||||
|
//
|
||||||
|
// if typ[0] == 0x00 {
|
||||||
|
// //fmt.Println("00 'block'")
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var block FdsBlock
|
||||||
|
// switch BlockType(typ[0]) {
|
||||||
|
// case BlockInfo:
|
||||||
|
// block = &FdsBlockInfo{}
|
||||||
|
// case BlockFileAmount:
|
||||||
|
// block = &FdsFileAmount{}
|
||||||
|
// case BlockFileHeader:
|
||||||
|
// block = &FdsFileHeader{}
|
||||||
|
// case BlockFileData:
|
||||||
|
// block = &FdsFileData{}
|
||||||
|
// default:
|
||||||
|
// return nil, fmt.Errorf("invalid block type: %02X", typ[0])
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if block.Type() != BlockFileData {
|
||||||
|
// err = binary.Read(reader, binary.LittleEndian, block)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, fmt.Errorf("decode error: %w", err)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// fb := block.(*FdsFileData)
|
||||||
|
// fb.BlockCode = byte(BlockFileData)
|
||||||
|
// reader.Discard(1)
|
||||||
|
//
|
||||||
|
// if dataSize == 0 {
|
||||||
|
// return nil, fmt.Errorf("FileData without size")
|
||||||
|
// }
|
||||||
|
// fmt.Println("dataSize:", dataSize)
|
||||||
|
//
|
||||||
|
// fb.Data = make([]byte, dataSize)
|
||||||
|
// _, err = reader.Read(fb.Data)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, fmt.Errorf("data read err: %w", err)
|
||||||
|
// }
|
||||||
|
// dataSize = 0
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// switch block.Type() {
|
||||||
|
// case BlockFileHeader:
|
||||||
|
// bh := block.(*FdsFileHeader)
|
||||||
|
// dataSize = int(bh.FileSize)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fmt.Println(block)
|
||||||
|
// blocks = append(blocks, block)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return blocks, nil
|
||||||
|
//}
|
||||||
Loading…
Reference in New Issue