-
Notifications
You must be signed in to change notification settings - Fork 1
/
bbcdisasm.go
executable file
·77 lines (65 loc) · 1.98 KB
/
bbcdisasm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package bbcdisasm
import (
"strings"
)
// DiskImage represents an Acorn DFS disk image
type DiskImage struct {
Title string
Sectors int
BootOpt int
Cycle int
Files []Catalog
}
// Catalog represents a file in Acorn DFS
type Catalog struct {
Filename string
Dir string
Length int
LoadAddr int
ExecAddr int
StartSector int
Attr byte
}
// ParseDFS reads the disk and file catalogs from binary data
// Resources
// http://mdfs.net/Docs/Comp/Disk/Format/DFS
// http://chrisacorns.computinghistory.org.uk/docs/Acorn/Manuals/Acorn_DiscSystemUGI2.pdf
func ParseDFS(dfs []byte) *DiskImage {
img := &DiskImage{}
nfiles := int(dfs[0x105]) / 8
img.Title = strings.TrimRight(string(dfs[0:8])+string(dfs[0x100:0x104]), "\000")
img.Sectors = int(dfs[0x107]) + int(dfs[0x106]&3)*256
img.BootOpt = int(dfs[0x106]&48) >> 4
img.Cycle = int(dfs[0x104])
img.Files = make([]Catalog, nfiles)
// Read file catalog entries
for i := 0; i < nfiles; i++ {
file := &img.Files[i]
// Read out the filename
var offset int
offset = 0x008 + i*8
file.Filename, file.Attr = readFilename(dfs[offset : offset+7])
file.Dir = string(dfs[offset+7])
// Read file info
offset = 0x108 + i*8
file.Length = int(dfs[offset+4]) + int(dfs[offset+5])*256 + int(dfs[offset+6]&0b110000)*4096
file.LoadAddr = int(dfs[offset+0]) + int(dfs[offset+1])*256 + int(dfs[offset+6]&0b1100)*16384
file.ExecAddr = int(dfs[offset+2]) + int(dfs[offset+3])*256 + int(dfs[offset+6]&0b11000000)*1024
file.StartSector = int(dfs[offset+7]) + int(dfs[offset+6]&0b11)*256
}
return img
}
func readFilename(block []byte) (string, byte) {
if len(block) < 7 {
panic("block is too short")
}
// Read out file attributes, stored in the top bit of filename characters,
// and clear out for a printable ASCII filename.
name := make([]byte, len(block))
var attr byte
for i, v := range block {
attr |= (v & 0x80) >> (7 - i)
name[i] = v & 0x7f
}
return strings.TrimRight(string(name), " "), attr
}