mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-01-03 11:30:29 +00:00
Support 3.5 disks and HDV format. Generalize the hard disk support to be used for any SmartPort device.
This commit is contained in:
parent
caa312c12a
commit
c2b620ec01
15
README.md
15
README.md
@ -12,9 +12,10 @@ Portable emulator of an Apple II+ or //e. Written in Go.
|
|||||||
- Apple //e enhanced with 128Kb of RAM
|
- Apple //e enhanced with 128Kb of RAM
|
||||||
- Base64A clone with 48Kb of base RAM and paginated ROM
|
- Base64A clone with 48Kb of base RAM and paginated ROM
|
||||||
- Storage
|
- Storage
|
||||||
- 16 Sector diskettes in NIB, DSK or PO format
|
- 16 Sector 5 1/4 diskettes in NIB, DSK or PO format
|
||||||
- 16 Sector diskettes in WOZ 1.0 or 2.0 format (read only)
|
- 16 Sector 5 1/4 diskettes in WOZ 1.0 or 2.0 format (read only)
|
||||||
- Hard disk with ProDOS and SmartPort support
|
- 3.5 disks in PO or 2MG format
|
||||||
|
- Hard disk in HDV or 2MG format with ProDOS and SmartPort support
|
||||||
- Emulated extension cards:
|
- Emulated extension cards:
|
||||||
- DiskII controller
|
- DiskII controller
|
||||||
- 16Kb Language Card
|
- 16Kb Language Card
|
||||||
@ -22,7 +23,7 @@ Portable emulator of an Apple II+ or //e. Written in Go.
|
|||||||
- 1Mb Memory Expansion Card (slinky)
|
- 1Mb Memory Expansion Card (slinky)
|
||||||
- RAMWorks style expansion Card (up to 16MB additional) (Apple //e only)
|
- RAMWorks style expansion Card (up to 16MB additional) (Apple //e only)
|
||||||
- ThunderClock Plus real time clock
|
- ThunderClock Plus real time clock
|
||||||
- Bootable hard disk card
|
- Bootable Smartport / ProDOS card
|
||||||
- Apple //e 80 columns with 64Kb extra RAM and optional RGB modes
|
- Apple //e 80 columns with 64Kb extra RAM and optional RGB modes
|
||||||
- VidHd, limited to the ROM signature and SHR as used by Total Replay, only for //e models with 128Kb
|
- VidHd, limited to the ROM signature and SHR as used by Total Replay, only for //e models with 128Kb
|
||||||
- FASTChip, limited to what Total Replay needs to set and clear fast mode
|
- FASTChip, limited to what Total Replay needs to set and clear fast mode
|
||||||
@ -154,6 +155,8 @@ Only valid on SDL mode
|
|||||||
file to load on the first disk drive (default "<internal>/dos33.dsk")
|
file to load on the first disk drive (default "<internal>/dos33.dsk")
|
||||||
-disk2Slot int
|
-disk2Slot int
|
||||||
slot for the disk driver. -1 for none. (default 6)
|
slot for the disk driver. -1 for none. (default 6)
|
||||||
|
-disk35 string
|
||||||
|
file to load on the SmartPort disk (slot 5)
|
||||||
-diskRom string
|
-diskRom string
|
||||||
rom file for the disk drive controller (default "<internal>/DISK2.rom")
|
rom file for the disk drive controller (default "<internal>/DISK2.rom")
|
||||||
-diskb string
|
-diskb string
|
||||||
@ -165,7 +168,7 @@ Only valid on SDL mode
|
|||||||
-fastDisk
|
-fastDisk
|
||||||
set fast mode when the disks are spinning (default true)
|
set fast mode when the disks are spinning (default true)
|
||||||
-hd string
|
-hd string
|
||||||
file to load on the hard disk
|
file to load on the boot hard disk
|
||||||
-hdSlot int
|
-hdSlot int
|
||||||
slot for the hard drive if present. -1 for none. (default -1)
|
slot for the hard drive if present. -1 for none. (default -1)
|
||||||
-languageCardSlot int
|
-languageCardSlot int
|
||||||
@ -195,7 +198,7 @@ Only valid on SDL mode
|
|||||||
-traceCpu
|
-traceCpu
|
||||||
dump to the console the CPU execution. Use F11 to toggle.
|
dump to the console the CPU execution. Use F11 to toggle.
|
||||||
-traceHD
|
-traceHD
|
||||||
dump to the console the hd commands
|
dump to the console the hd/smartport commands
|
||||||
-traceMLI
|
-traceMLI
|
||||||
dump to the console the calls to ProDOS machine language interface calls to $BF00
|
dump to the console the calls to ProDOS machine language interface calls to $BF00
|
||||||
-traceSS
|
-traceSS
|
||||||
|
@ -126,14 +126,14 @@ func (a *Apple2) AddDisk2(slot int, diskRomFile string, diskImage, diskBImage st
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddHardDisk adds a ProDos hard dirve with a 2MG image
|
// AddSmartPortDisk adds a smart port card and image
|
||||||
func (a *Apple2) AddHardDisk(slot int, hdImage string, trace bool) error {
|
func (a *Apple2) AddSmartPortDisk(slot int, hdImage string, trace bool) error {
|
||||||
var c cardHardDisk
|
var c cardHardDisk
|
||||||
c.setTrace(trace)
|
c.setTrace(trace)
|
||||||
c.loadRom(buildHardDiskRom(slot))
|
c.loadRom(buildHardDiskRom(slot))
|
||||||
a.insertCard(&c, slot)
|
a.insertCard(&c, slot)
|
||||||
|
|
||||||
hd, err := openHardDisk2mg(hdImage)
|
hd, err := openBlockDisk(hdImage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -194,6 +194,7 @@ func (a *Apple2) AddRGBCard() {
|
|||||||
setupRGBCard(a)
|
setupRGBCard(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddRAMWorks inserts adds RAMWorks style RAM to the Apple IIe 80 col 64KB card
|
||||||
func (a *Apple2) AddRAMWorks(banks int) {
|
func (a *Apple2) AddRAMWorks(banks int) {
|
||||||
setupRAMWorksCard(a, banks)
|
setupRAMWorksCard(a, banks)
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,15 @@ func MainApple() *Apple2 {
|
|||||||
hardDiskImage := flag.String(
|
hardDiskImage := flag.String(
|
||||||
"hd",
|
"hd",
|
||||||
"",
|
"",
|
||||||
"file to load on the hard disk")
|
"file to load on the boot hard disk (slot 7)")
|
||||||
hardDiskSlot := flag.Int(
|
hardDiskSlot := flag.Int(
|
||||||
"hdSlot",
|
"hdSlot",
|
||||||
-1,
|
-1,
|
||||||
"slot for the hard drive if present. -1 for none.")
|
"slot for the hard drive if present. -1 for none.")
|
||||||
|
smartPortImage := flag.String(
|
||||||
|
"disk35",
|
||||||
|
"",
|
||||||
|
"file to load on the SmartPort disk (slot 5)")
|
||||||
cpuClock := flag.Float64(
|
cpuClock := flag.Float64(
|
||||||
"mhz",
|
"mhz",
|
||||||
CPUClockMhz,
|
CPUClockMhz,
|
||||||
@ -104,7 +108,7 @@ func MainApple() *Apple2 {
|
|||||||
traceHD := flag.Bool(
|
traceHD := flag.Bool(
|
||||||
"traceHD",
|
"traceHD",
|
||||||
false,
|
false,
|
||||||
"dump to the console the hd commands")
|
"dump to the console the hd/smarport commands")
|
||||||
dumpChars := flag.Bool(
|
dumpChars := flag.Bool(
|
||||||
"dumpChars",
|
"dumpChars",
|
||||||
false,
|
false,
|
||||||
@ -237,6 +241,18 @@ func MainApple() *Apple2 {
|
|||||||
if *vidHDCardSlot >= 0 {
|
if *vidHDCardSlot >= 0 {
|
||||||
a.AddVidHD(*vidHDCardSlot)
|
a.AddVidHD(*vidHDCardSlot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *smartPortImage != "" {
|
||||||
|
err := a.AddSmartPortDisk(5, *smartPortImage, *traceHD)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if *fastChipCardSlot == 5 {
|
||||||
|
// Don't use fastChipCard if the slot 5 is already in use
|
||||||
|
*fastChipCardSlot = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if *fastChipCardSlot >= 0 {
|
if *fastChipCardSlot >= 0 {
|
||||||
a.AddFastChip(*fastChipCardSlot)
|
a.AddFastChip(*fastChipCardSlot)
|
||||||
}
|
}
|
||||||
@ -251,7 +267,7 @@ func MainApple() *Apple2 {
|
|||||||
// If there is a hard disk image, but no slot assigned, use slot 7.
|
// If there is a hard disk image, but no slot assigned, use slot 7.
|
||||||
*hardDiskSlot = 7
|
*hardDiskSlot = 7
|
||||||
}
|
}
|
||||||
err := a.AddHardDisk(*hardDiskSlot, *hardDiskImage, *traceHD)
|
err := a.AddSmartPortDisk(*hardDiskSlot, *hardDiskImage, *traceHD)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
98
blockDisk.go
Normal file
98
blockDisk.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package apple2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Valid for ProDos disks with 512 bytes blocks. Can be diskettes or hard disks
|
||||||
|
*/
|
||||||
|
|
||||||
|
const (
|
||||||
|
proDosBlockSize = uint32(512)
|
||||||
|
proDosMaxBlocks = uint32(65536)
|
||||||
|
)
|
||||||
|
|
||||||
|
type blockDisk struct {
|
||||||
|
file *os.File
|
||||||
|
readOnly bool
|
||||||
|
dataOffset uint32
|
||||||
|
blocks uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func openBlockDisk(filename string) (*blockDisk, error) {
|
||||||
|
var bd blockDisk
|
||||||
|
|
||||||
|
bd.readOnly = false
|
||||||
|
file, err := os.OpenFile(filename, os.O_RDWR, 0)
|
||||||
|
if os.IsPermission(err) {
|
||||||
|
// Retry in read-only mode
|
||||||
|
bd.readOnly = true
|
||||||
|
file, err = os.OpenFile(filename, os.O_RDONLY, 0)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bd.file = file
|
||||||
|
|
||||||
|
err2mg := parse2mg(&bd)
|
||||||
|
if err2mg == nil {
|
||||||
|
// It's a 2mg file, ready to use
|
||||||
|
return &bd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's try to load as raw ProDOS Blocks
|
||||||
|
fileInfo, err := bd.file.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fileInfo.Size() > int64(proDosBlockSize*proDosMaxBlocks) {
|
||||||
|
return nil, fmt.Errorf("File is too big OR %s", err2mg.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
size := uint32(fileInfo.Size())
|
||||||
|
if size%proDosBlockSize != 0 {
|
||||||
|
return nil, fmt.Errorf("File size os invalid OR %s", err2mg.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's a valid raw file
|
||||||
|
bd.blocks = size / proDosBlockSize
|
||||||
|
bd.dataOffset = 0
|
||||||
|
return &bd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bd *blockDisk) read(block uint32) ([]uint8, error) {
|
||||||
|
if block >= bd.blocks {
|
||||||
|
return nil, errors.New("disk block number is too big")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]uint8, proDosBlockSize)
|
||||||
|
|
||||||
|
offset := int64(bd.dataOffset + block*proDosBlockSize)
|
||||||
|
_, err := bd.file.ReadAt(buf, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bd *blockDisk) write(block uint32, data []uint8) error {
|
||||||
|
if bd.readOnly {
|
||||||
|
return errors.New("can't write in a readonly disk")
|
||||||
|
}
|
||||||
|
if block >= bd.blocks {
|
||||||
|
return errors.New("disk block number is too big")
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := int64(bd.dataOffset + block*proDosBlockSize)
|
||||||
|
_, err := bd.file.WriteAt(data, offset)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -15,7 +15,7 @@ See:
|
|||||||
|
|
||||||
type cardHardDisk struct {
|
type cardHardDisk struct {
|
||||||
cardBase
|
cardBase
|
||||||
disk *hardDisk
|
disk *blockDisk
|
||||||
mliParams uint16
|
mliParams uint16
|
||||||
trace bool
|
trace bool
|
||||||
}
|
}
|
||||||
@ -132,11 +132,11 @@ func (c *cardHardDisk) assign(a *Apple2, slot int) {
|
|||||||
}, "HDCOMMAND")
|
}, "HDCOMMAND")
|
||||||
c.addCardSoftSwitchR(1, func(*ioC0Page) uint8 {
|
c.addCardSoftSwitchR(1, func(*ioC0Page) uint8 {
|
||||||
// Blocks available, low byte
|
// Blocks available, low byte
|
||||||
return uint8(c.disk.header.Blocks)
|
return uint8(c.disk.blocks)
|
||||||
}, "HDBLOCKSLO")
|
}, "HDBLOCKSLO")
|
||||||
c.addCardSoftSwitchR(2, func(*ioC0Page) uint8 {
|
c.addCardSoftSwitchR(2, func(*ioC0Page) uint8 {
|
||||||
// Blocks available, high byte
|
// Blocks available, high byte
|
||||||
return uint8(c.disk.header.Blocks >> 8)
|
return uint8(c.disk.blocks >> 8)
|
||||||
}, "HDBLOCKHI")
|
}, "HDBLOCKHI")
|
||||||
|
|
||||||
c.addCardSoftSwitchR(3, func(*ioC0Page) uint8 {
|
c.addCardSoftSwitchR(3, func(*ioC0Page) uint8 {
|
||||||
@ -218,7 +218,7 @@ func (c *cardHardDisk) writeBlock(block uint16, source uint16) uint8 {
|
|||||||
return proDosDeviceNoError
|
return proDosDeviceNoError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cardHardDisk) addDisk(disk *hardDisk) {
|
func (c *cardHardDisk) addDisk(disk *blockDisk) {
|
||||||
c.disk = disk
|
c.disk = disk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
84
file2mg.go
Normal file
84
file2mg.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package apple2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Valid for ProDos disks in 2MG format.
|
||||||
|
|
||||||
|
See:
|
||||||
|
https://apple2.org.za/gswv/a2zine/Docs/DiskImage_2MG_Info.txt
|
||||||
|
*/
|
||||||
|
|
||||||
|
const (
|
||||||
|
file2mgPreamble = uint32(1196247346) // "2IMG"
|
||||||
|
file2mgFormatProdos = 1
|
||||||
|
file2mgVersion = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
type file2mgHeader struct {
|
||||||
|
Preamble uint32
|
||||||
|
Creator uint32
|
||||||
|
HeaderSize uint16
|
||||||
|
Version uint16
|
||||||
|
Format uint32
|
||||||
|
Flags uint32
|
||||||
|
Blocks uint32
|
||||||
|
OffsetData uint32
|
||||||
|
LengthData uint32
|
||||||
|
OffsetComment uint32
|
||||||
|
LengthComment uint32
|
||||||
|
OffsetCreator uint32
|
||||||
|
LengthCreator uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse2mg(bd *blockDisk) error {
|
||||||
|
fileInfo, err := bd.file.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var header file2mgHeader
|
||||||
|
minHeaderSize := binary.Size(&header)
|
||||||
|
if fileInfo.Size() < int64(minHeaderSize) {
|
||||||
|
return errors.New("Invalid 2MG file")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = readHeader(bd.file, &header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
bd.blocks = header.Blocks
|
||||||
|
bd.dataOffset = header.OffsetData
|
||||||
|
|
||||||
|
if fileInfo.Size() < int64(bd.dataOffset+bd.blocks*proDosBlockSize) {
|
||||||
|
return errors.New("The 2MG file is too small")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readHeader(buf io.Reader, header *file2mgHeader) error {
|
||||||
|
err := binary.Read(buf, binary.LittleEndian, header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Preamble != file2mgPreamble {
|
||||||
|
return errors.New("The 2mg file must start with '2IMG'")
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Format != file2mgFormatProdos {
|
||||||
|
return errors.New("Only prodos disks are supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Version != file2mgVersion {
|
||||||
|
return errors.New("Version of 2MG image not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
135
hardDisk.go
135
hardDisk.go
@ -1,135 +0,0 @@
|
|||||||
package apple2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Valid for ProDos hard disks in 2MG format.
|
|
||||||
|
|
||||||
See:
|
|
||||||
https://apple2.org.za/gswv/a2zine/Docs/DiskImage_2MG_Info.txt
|
|
||||||
*/
|
|
||||||
|
|
||||||
const (
|
|
||||||
proDosBlockSize = uint32(512)
|
|
||||||
hardDisk2mgPreamble = uint32(1196247346) // "2IMG"
|
|
||||||
hardDisk2mgFormatProdos = 1
|
|
||||||
hardDisk2mgVersion = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
type hardDisk struct {
|
|
||||||
file *os.File
|
|
||||||
readOnly bool
|
|
||||||
header hardDisk2mgHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
type hardDisk2mgHeader struct {
|
|
||||||
Preamble uint32
|
|
||||||
Creator uint32
|
|
||||||
HeaderSize uint16
|
|
||||||
Version uint16
|
|
||||||
Format uint32
|
|
||||||
Flags uint32
|
|
||||||
Blocks uint32
|
|
||||||
OffsetData uint32
|
|
||||||
LengthData uint32
|
|
||||||
OffsetComment uint32
|
|
||||||
LengthComment uint32
|
|
||||||
OffsetCreator uint32
|
|
||||||
LengthCreator uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hd *hardDisk) read(block uint32) ([]uint8, error) {
|
|
||||||
if block >= hd.header.Blocks {
|
|
||||||
return nil, errors.New("disk block number is too big")
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := make([]uint8, proDosBlockSize)
|
|
||||||
|
|
||||||
offset := int64(hd.header.OffsetData + block*proDosBlockSize)
|
|
||||||
_, err := hd.file.ReadAt(buf, offset)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hd *hardDisk) write(block uint32, data []uint8) error {
|
|
||||||
if hd.readOnly {
|
|
||||||
return errors.New("can't write in a readonly disk")
|
|
||||||
}
|
|
||||||
if block >= hd.header.Blocks {
|
|
||||||
return errors.New("disk block number is too big")
|
|
||||||
}
|
|
||||||
|
|
||||||
offset := int64(hd.header.OffsetData + block*proDosBlockSize)
|
|
||||||
_, err := hd.file.WriteAt(data, offset)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func openHardDisk2mg(filename string) (*hardDisk, error) {
|
|
||||||
var hd hardDisk
|
|
||||||
|
|
||||||
hd.readOnly = false
|
|
||||||
file, err := os.OpenFile(filename, os.O_RDWR, 0)
|
|
||||||
if os.IsPermission(err) {
|
|
||||||
// Retry in read-only mode
|
|
||||||
hd.readOnly = true
|
|
||||||
file, err = os.OpenFile(filename, os.O_RDONLY, 0)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
hd.file = file
|
|
||||||
|
|
||||||
fileInfo, err := hd.file.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
minHeaderSize := binary.Size(&hd.header)
|
|
||||||
if fileInfo.Size() < int64(minHeaderSize) {
|
|
||||||
return nil, errors.New("Invalid 2MG file")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = readHeader(hd.file, &hd.header)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if fileInfo.Size() < int64(hd.header.OffsetData+hd.header.Blocks*proDosBlockSize) {
|
|
||||||
return nil, errors.New("Thr 2MG file is too small")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &hd, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func readHeader(buf io.Reader, header *hardDisk2mgHeader) error {
|
|
||||||
err := binary.Read(buf, binary.LittleEndian, header)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if header.Preamble != hardDisk2mgPreamble {
|
|
||||||
return errors.New("2mg file must start with '2IMG'")
|
|
||||||
}
|
|
||||||
|
|
||||||
if header.Format != hardDisk2mgFormatProdos {
|
|
||||||
return errors.New("Only prodos hard disks are supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
if header.Version != hardDisk2mgVersion {
|
|
||||||
return errors.New("Version of 2MG image not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user