Date : Mon, 18 Oct 1999 14:06:47 +0100
From : jgh@... (Jonathan Graham Harston)
Subject: ADFS floating point type
> Message-Id: <E11acDH-00007Q-00@...>
"I.J.Clark" <I.Clark@...> wrote:
> I am currently trying to convert data from the BBC for use on a PC,
> specifically, I'm trying to convert 5-byte ADFS floating point types into
ADFS is a filing system, nothing to do with floating point numbers at all.
> standard 32bit floating point numbers for use with a PC. I can obtain
> the 40bit pattern, but I don't know which bit is the sign bit and which
> bits are the mantissa and exponent. I'm sure that some emulator writers
> will have done this in the past so I hope that someone out there can help.
If you mean: you want to read (and write) data saved from BBCBasic with
PRINT# on a PC system, then the following may be of use.
>::: Area #155 (comp.sys.acorn.networking)
>Message: #32225 (Read 7 times, has 0 replies, 6280 bytes)
>Date : Sun May 24 20:07:36 1998
>From : Jonathan Graham Harston of fidonet#2:254/27
>To : All
>Subject: Using BBCBasic Data Files in VisualBasic
Usual warnings!!! I haven't tested this **AT ALL** as the office is
closed, and even if it was open, we don't have VisualBasic installed. I
suppose I'd better spend a couple of hours one day installing it.
Feel free to fix any mistakes and mail the results back to me.
Somewhere in your program, do:
eg:
filename$="DATAFILE.BBC"
filenumber=1
Open filename$ For Binary As #filenumber
... and then you can use:
<...> = BBC_ReadFromFile (filenumber)
to read the data in, and
BBC_WriteToFile(filenumber, variable, vartype)
to write the data, set vartype to &00 (string), &40 (integer), &FF (real).
The functions are:
Function BBC_ReadFromFile (File_Channel) ' Returns a Variant value
Dim Data_Integer As Long ' 4-byte integer
Dim Data_Byte As String * 1 ' 1-byte single byte
Dim Data_Real As Double ' 8-byte floating real
Get #File_Channel, , Data_Byte ' What's the next data type?
Select Case Data_Byte
Case 0 ' String
' Format: 00, len, reversed string
Data_Length = Input$(1, File_Channel) ' Get string length
Data_String$ = "" ' Initialise string
If Data_Length > 0 Then
For Loop = 1 To Data_Length ' Read in the reversed string
Data_String$ = Input$(1, File_Channel) + Data_String$
Next Loop
BBC_ReadFromFile = Data_String ' Assign return value
End If
Case 1, 64 ' 32-bit Integer
' Format: 01 or 40, b3, b2, b1, b0 - integer &b3b2b1b0
' I *think* that VB stores ints as b0,b1,b2,b3, so need to read
' bytes in manually
Data_Integer = 0
Get #File_Channel, , Data_Byte
Data_Integer = Data_Byte * &h1000000 ' But this might overflow?
Get #File_Channel, , Data_Byte
Data_Integer = Data_Integer Or (Data_Byte * &h10000)
Get #file_Channel, , Data_Byte
Data_Integer = Data_Integer Or (Data_Byte * &h100)
Get #File_Channel, , Data_Byte
Data_Integer = Data_Integer Or Data_Byte
BBC_ReadFromFile = Data_Integer
Case 255 ' 40-bit Real
' Format: FF, m0, m1, m2, m3, ex - exponent ex, mantissa &m3m2m1m0
Get #File_Channel, , Data_Byte
Data_Integer = Data_Byte
Get #File_Channel, , Data_Byte
Data_Integer = Data_Integer Or (Data_Byte * &h100)
Get #File_Channel, , Data_Byte
Data_Integer = Data_Integer Or (Data_Byte * &h10000)
Get #File_Channel, , Data_Byte
Minus = (Data_Byte > 127)
Data_Byte = Data_Byte And 127
Data_Integer = Data_Integer Or (Data_Byte * &h1000000)
Get #File_Channel, , Data_Byte
If Data_Integer = 0 And Data_Byte = 0 And Not Minus Then
BBC_ReadFromFile = 0
Else
Data_Real = Data_Integer + 2147483648
Data_Real = Data_Real * 2 ^ (Data_Byte - &hA0)
If Minus Then Data_Real = -Data_Real
BBC_ReadFromFile = Data_Real
Case Else
BBC_ReadFromFile = 0 ' Unrecognised - return zero
End Select
End Function
Function BBC_WriteToFile (File_Channel, Data_Var, Data_Type)
Dim Data_Integer As Long ' 4-byte integer
Dim Data_Byte As String * 1 ' Single byte
Dim Data_Real As Double ' 8-byte float
Data_Byte = Data_Type
Put #File_Channel, , Data_Byte ' Write out the data type
Select Case Data_Type
Case 0 ' String
' Format: 00, len, reversed string
Data_Byte = Len(Data_Var)
Put #File_Channel, , Data_Byte
If Data_Byte > 0 Then
For Loop = Data_Byte To 1 Step -1 ' Read in the reversed string
Data_Byte = Mid$( Data_Var, Loop, 1)
Put #File_Channel, , Data_Byte
Next Loop
End If
Case 1, 64 ' 32-bit Integer
' Format: 01 or 40, b3, b2, b1, b0 - integer &b3b2b1b0
' I *think* that VB stores ints as b0,b1,b2,b3, so need to read
' bytes in manually
Data_Integer = Data_Var
Data_Byte = (Data_Integer And &hFF000000) Div &h1000000
Put #File_Channel, , Data_Byte
Data_Byte = (Data_Integer And &hFF0000) Div &h10000
Put #File_Channel, , Data_Byte
Data_Byte = (Data_Integer And &hFF00) Div &h100
Put #File_Channel, , Data_Byte
Data_Byte = Data_Integer And &hFF
Put #File_Channel, , Data_Byte
Case 255 ' 40-bit Real
' Format: FF, m0, m1, m2, m3, ex - exponent ex, mantissa &m3m2m1m0
Data_Real = Data_Var
Minus = Data_Real < 0
Data_Real = Abs (Data_Real)
Data_Exponent = 1 + Int (Ln (Data_Real) / Ln (2) )
Data_Real = Data_Real / ( 2 ^ (Data_Exponent - 32))
Data_Real = Data_Real - 2147483648
Data_Integer = Data_Real
Data_Byte = Data_Integer And &hFF
Put #File_Channel, , Data_Byte
Data_Byte = (Data_Integer And &hFF00) Div &h100
Put #File_Channel, , Data_Byte
Data_Byte = (Data_Integer And &hFF0000) Div &h10000
Put #File_Channel, , Data_Byte
Data_Byte = (Data_Integer And &hFF000000) Div &h1000000
If Minus Then Data_Byte = Data_Byte Or &h80
Put #File_Channel, , Data_Byte
Data_Byte = Data_Exponent + &hA0
Put #File_Channel, , Data_Byte
End Select
End Function
<fx: Clarkson> Arrgh!!!, horrible, horrible, horrible microsoft. "Let's
try to be as helpful as possible by throwing things at the programmer and
hiding what the code /actually/ does." Gimmie a BGet and a BPut. And
memory indirections. And cleaner interfaces. Hell, give me an Acorn.
--
J.G.Harston (JGH BBC PD Library) 70 Camm Street, Walkley, SHEFFIELD S6 3TR
BBC+Master / Z80+6502 / CoPro+Tubes / Econet+SJ / Devolution / Transport /
Planning / Highways http://homepages.nildram.co.uk/~amilton/walkley.htm
jgh@... (( Anti-UCE address added by Arcade, not by me ))