Skip to content

Commit

Permalink
Use a better way of keeping track of file-handles
Browse files Browse the repository at this point in the history
We used to assume that the address of the FCB entry which was used
for opening a file would be used for later read/write operations, so
we could cache our file-handles keyed on that address.

I've just noticed that multi-file projects in turbo-pascal jump
around with their FCB addresses.

So on open/make file requests we store the original FCB address
in FCB.AL[0,1] - which will be stable across operations, even if
the FCB is in a different address.

I guess we could use file-no instead, but for the moment this seems
simple.  If N files are opened from the same FCB address we'll be
in trouble, but we'll cross that bridge later.

This closes #127.
  • Loading branch information
skx committed Jun 20, 2024
1 parent 19c37d4 commit 7686b78
Showing 1 changed file with 36 additions and 7 deletions.
43 changes: 36 additions & 7 deletions cpm/cpm_bdos.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,10 @@ func BdosSysCallFileOpen(cpm *CPM) error {
fcbPtr.RC = fLen
}

// Write our cache-key in the FCB
fcbPtr.Al[0] = uint8(ptr & 0xFF)
fcbPtr.Al[1] = uint8(ptr >> 8)

// Update the FCB in memory.
cpm.Memory.SetRange(ptr, fcbPtr.AsBytes()...)

Expand Down Expand Up @@ -483,6 +487,10 @@ func BdosSysCallFileOpen(cpm *CPM) error {
slog.Int("record_count", int(fcbPtr.RC)),
slog.Int64("file_size", fileSize))

// Write our cache-key in the FCB
fcbPtr.Al[0] = uint8(ptr & 0xFF)
fcbPtr.Al[1] = uint8(uint16(ptr >> 8))

// Update the FCB in memory.
cpm.Memory.SetRange(ptr, fcbPtr.AsBytes()...)

Expand All @@ -509,8 +517,11 @@ func BdosSysCallFileClose(cpm *CPM) error {
// Create a structure with the contents
fcbPtr := fcb.FromBytes(xxx)

// Get our cache-key from the FCB
key := uint16(uint16(fcbPtr.Al[1])<<8 + uint16(fcbPtr.Al[0]))

// Get the file handle from our cache.
obj, ok := cpm.files[ptr]
obj, ok := cpm.files[key]
if !ok {
cpm.Logger.Debug("SysCallFileClose tried to close a file that wasn't open",
slog.Int("fcb", int(ptr)))
Expand Down Expand Up @@ -554,10 +565,12 @@ func BdosSysCallFileClose(cpm *CPM) error {
}

// delete the entry from the cache.
delete(cpm.files, ptr)
delete(cpm.files, key)

// Update the FCB in RAM
// cpm.Memory.SetRange(ptr, fcbPtr.AsBytes()...)
fcbPtr.Al[0] = 0x00
fcbPtr.Al[1] = 0x00
cpm.Memory.SetRange(ptr, fcbPtr.AsBytes()...)

// Record success
cpm.CPU.States.AF.Hi = 0x00
Expand Down Expand Up @@ -787,8 +800,11 @@ func BdosSysCallRead(cpm *CPM) error {
// Create a structure with the contents
fcbPtr := fcb.FromBytes(xxx)

// Get our cache-key from the FCB
key := uint16(uint16(fcbPtr.Al[1])<<8 + uint16(fcbPtr.Al[0]))

// Get the file handle in our cache.
obj, ok := cpm.files[ptr]
obj, ok := cpm.files[key]
if !ok {
cpm.Logger.Error("SysCallRead: Attempting to read from a file that isn't open")
cpm.CPU.States.AF.Hi = 0xFF
Expand Down Expand Up @@ -893,8 +909,11 @@ func BdosSysCallWrite(cpm *CPM) error {
// Create a structure with the contents
fcbPtr := fcb.FromBytes(xxx)

// Get our cache-key from the FCB
key := uint16(uint16(fcbPtr.Al[1])<<8 + uint16(fcbPtr.Al[0]))

// Get the file handle in our cache.
obj, ok := cpm.files[ptr]
obj, ok := cpm.files[key]
if !ok {
cpm.Logger.Error("SysCallWrite: Attempting to write to a file that isn't open")
cpm.CPU.States.AF.Hi = 0xFF
Expand Down Expand Up @@ -1023,6 +1042,10 @@ func BdosSysCallMakeFile(cpm *CPM) error {
fcbPtr.RC = fLen
}

// Write our cache-key in the FCB
fcbPtr.Al[0] = uint8(ptr & 0xFF)
fcbPtr.Al[1] = uint8(ptr >> 8)

// Save the file-handle
cpm.files[ptr] = FileCache{name: fileName, handle: file}

Expand Down Expand Up @@ -1269,8 +1292,11 @@ func BdosSysCallReadRand(cpm *CPM) error {
// Create a structure with the contents
fcbPtr := fcb.FromBytes(xxx)

// Get our cache-key from the FCB
key := uint16(uint16(fcbPtr.Al[1])<<8 + uint16(fcbPtr.Al[0]))

// Get the file handle in our cache.
obj, ok := cpm.files[ptr]
obj, ok := cpm.files[key]
if !ok {
cpm.Logger.Error("SysCallReadRand: Attempting to read from a file that isn't open")
cpm.CPU.States.AF.Hi = 0xFF
Expand Down Expand Up @@ -1319,8 +1345,11 @@ func BdosSysCallWriteRand(cpm *CPM) error {
// Create a structure with the contents
fcbPtr := fcb.FromBytes(xxx)

// Get our cache-key from the FCB
key := uint16(uint16(fcbPtr.Al[1])<<8 + uint16(fcbPtr.Al[0]))

// Get the file handle in our cache.
obj, ok := cpm.files[ptr]
obj, ok := cpm.files[key]
if !ok {
cpm.Logger.Error("SysCallWriteRand: Attempting to write to a file that isn't open")
cpm.CPU.States.AF.Hi = 0xFF
Expand Down

0 comments on commit 7686b78

Please sign in to comment.