Skip to content

Commit 83cefc0

Browse files
authored
Merge pull request #93 from skx/embed
Simplify our embedding of the CCPs
2 parents baf8f1b + 35f6301 commit 83cefc0

File tree

3 files changed

+71
-37
lines changed

3 files changed

+71
-37
lines changed

ccp/ccp.go

+26-12
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
// Package ccp contains a pair of embedded CCP binaries, which can
22
// be used by the emulator as shells.
3+
//
4+
// At build-time we include "*.BIN" from the ccp/ directory, which
5+
// means it's easy to add a new CCP driver - however we must also
6+
// ensure there is a matching name-entry added to the code, so it isn't
7+
// 100% automatic.
38
package ccp
49

510
import (
6-
_ "embed"
11+
"embed"
712
"fmt"
813
"strings"
914
)
1015

11-
// ccps contains the global array of the CCP variants we have.
12-
var ccps []Flavour
13-
1416
// Flavour contains details about a possible CCP the user might run.
1517
type Flavour struct {
1618
// Name has the name of the CCP.
19+
//
20+
// NOTE: This name is visible to end-users, and will be used in the "-ccp" command-line flag,
21+
// or as the name when changing at run-time via the "CCP.COM" utility.
1722
Name string
1823

1924
// Description has the description of the CCP.
@@ -26,27 +31,34 @@ type Flavour struct {
2631
Start uint16
2732
}
2833

29-
//go:embed DR.BIN
30-
var ccpBin []uint8
34+
var (
35+
// ccps contains the global array of the CCP variants we have.
36+
ccps []Flavour
3137

32-
//go:embed CCPZ.BIN
33-
var ccpzBin []uint8
38+
//go:embed *.BIN
39+
ccpFiles embed.FS
40+
)
3441

3542
// init sets up our global ccp array, by adding the two embedded CCPs to
3643
// the array, with suitable names/offsets.
3744
func init() {
45+
46+
// Load the CCP from DR
47+
ccp, _ := ccpFiles.ReadFile("DR.BIN")
3848
ccps = append(ccps, Flavour{
3949
Name: "ccp",
40-
Description: "CP/M v2.2",
50+
Description: "CP/M v2.2skx",
4151
Start: 0xDE00,
42-
Bytes: ccpBin,
52+
Bytes: ccp,
4353
})
4454

55+
// Load the alternative CCP
56+
ccpz, _ := ccpFiles.ReadFile("CCPZ.BIN")
4557
ccps = append(ccps, Flavour{
4658
Name: "ccpz",
4759
Description: "CCPZ v4.1skx",
4860
Start: 0xDE00,
49-
Bytes: ccpzBin,
61+
Bytes: ccpz,
5062
})
5163
}
5264

@@ -57,13 +69,15 @@ func GetAll() []Flavour {
5769

5870
// Get returns the CCP version specified, by name, if it exists.
5971
//
60-
// If the given name is invalid then an error will be returned.
72+
// If the given name is invalid then an error will be returned instead.
6173
func Get(name string) (Flavour, error) {
6274

6375
valid := []string{}
6476

6577
for _, ent := range ccps {
6678

79+
// When changing at runtime, via "CCP.COM", we will have had
80+
// the name upper-cased by the CCP so we need to downcase here.
6781
if strings.ToLower(name) == ent.Name {
6882
return ent, nil
6983
}

ccp/ccp_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func TestCCPTrivial(t *testing.T) {
2121

2222
// The CCPs are small, but bigger than 1k and smaller than 8k
2323
if len(bytes) < 1024 {
24-
t.Fatalf("CCP %s is too small", n.Name)
24+
t.Fatalf("CCP %s is too small got %d bytes", n.Name, len(bytes))
2525
}
2626

2727
if len(bytes) > 8192 {

cpm/cpm_bios.go

+44-24
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,27 @@ func BiosSysCallReserved1(cpm *CPM) error {
190190
c := cpm.CPU.States.BC.Lo
191191
de := cpm.CPU.States.DE.U16()
192192

193+
//
194+
// Helper to read a null/space terminated string from
195+
// memory.
196+
//
197+
// Here because our custom syscalls read a string when
198+
// setting both CCP and DisplayDriver.
199+
//
200+
getStringFromMemory := func(addr uint16) string {
201+
str := ""
202+
c := cpm.Memory.Get(addr)
203+
for c != ' ' && c != 0x00 {
204+
str += string(c)
205+
addr++
206+
c = cpm.Memory.Get(addr)
207+
}
208+
209+
// Useful when the CCP has passed a string, because
210+
// that uppercases all input
211+
return strings.ToLower(str)
212+
}
213+
193214
switch hl {
194215
case 0x0000:
195216
// Magic values in the registers
@@ -209,6 +230,7 @@ func BiosSysCallReserved1(cpm *CPM) error {
209230
end--
210231
}
211232

233+
// now populate with our name/version/information
212234
for i, c := range vers {
213235
cpm.Memory.Set(addr+uint16(i), uint8(c))
214236
}
@@ -220,17 +242,10 @@ func BiosSysCallReserved1(cpm *CPM) error {
220242
} else {
221243
cpm.input.SetInterruptCount(int(c))
222244
}
223-
case 0x0002:
224-
str := ""
225-
226-
c := cpm.Memory.Get(de)
227-
for c != ' ' && c != 0x00 {
228-
str += string(c)
229-
de++
230-
c = cpm.Memory.Get(de)
231-
}
232245

233-
str = strings.ToLower(str)
246+
case 0x0002:
247+
// Get the string pointed to by DE
248+
str := getStringFromMemory(de)
234249

235250
// Output driver needs to be created
236251
driver, err := consoleout.New(str)
@@ -243,41 +258,46 @@ func BiosSysCallReserved1(cpm *CPM) error {
243258
}
244259

245260
old := cpm.output.GetName()
261+
cpm.output = driver
262+
263+
// when running quietly don't show any output
264+
if cpm.quiet {
265+
return nil
266+
}
267+
246268
if old != str {
247269
fmt.Printf("Console driver changed from %s to %s.\n", cpm.output.GetName(), driver.GetName())
248-
cpm.output = driver
249270
} else {
250271
fmt.Printf("console driver is already %s, making no change.\n", str)
251272
}
252-
case 0x0003:
253-
str := ""
254273

255-
c := cpm.Memory.Get(de)
256-
for c != ' ' && c != 0x00 {
257-
str += string(c)
258-
de++
259-
c = cpm.Memory.Get(de)
260-
}
274+
case 0x0003:
261275

262-
// CP/M will upper-case command-lines (and therefor their arguments)
263-
str = strings.ToLower(str)
276+
// Get the string pointed to by DE
277+
str := getStringFromMemory(de)
264278

265279
// See if the CCP exists
266-
_, err := ccp.Get(str)
280+
entry, err := ccp.Get(str)
267281
if err != nil {
268282
fmt.Printf("Invalid CCP name %s\n", str)
269283
return nil
270284
}
271285

272286
// old value
273287
old := cpm.ccp
288+
cpm.ccp = str
289+
290+
// when running quietly don't show any output
291+
if cpm.quiet {
292+
return nil
293+
}
274294

275295
if old != str {
276-
fmt.Printf("CCP changed from %s to %s.\n", old, str)
277-
cpm.ccp = str
296+
fmt.Printf("CCP changed to %s [%s] Size:0x%04X Entry-Point:0x%04X\n", str, entry.Description, len(entry.Bytes), entry.Start)
278297
} else {
279298
fmt.Printf("CCP is already %s, making no change.\n", str)
280299
}
300+
281301
case 0x0004:
282302
if c == 0x00 {
283303
cpm.quiet = true

0 commit comments

Comments
 (0)