Page 1 of 2

Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 10:30 am
by humungus
Hi to all !

First accept my apologies for maybe stupid and easy question...but simply, I do not know how do it.
Before one month I start to learn PB, reading book and documentation but do not have experience, still learning.

Problem is next, this is a binary file example which I want to load to buffer or just read , then do some mathematics
and then to show result in Textgadget.

AA 10 01 FF FF FF FF FF FF FF FF FF FF 1E 29 33
C7 D2 D1 FF FF FF FF 37 78 22 7D 27 7E FF FF 4B
A2 40 A0 24 0D 63 43 16 07 02 C1 81 31 55 32 37
31 31 66 99 FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

For showing result I use this command SetGadgetText(#Text_6, Text$). Main problem is how to read this kind of file or read it in buffer? I tried on this way but do not work.....sorry, that`s best what I can at this moment.

Procedure LoadF()
file$=OpenFileRequester("Please choose file...","","<*.bin> | *.bin", 0)
If file$
ReadFile(0,file$)
While Eof(0) = 0
Wend
CloseFile(0)
EndIf
EndProcedure

I know that problem is that before showing result I must have result as string, but.... :oops:

Can You help me please and explain me how to think in future?

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 11:03 am
by infratec
Hi,

and welcome.

If your file is binary, than you have to read it binary and than you can convert it into a string.

So something like:

Code: Select all

Procedure.s LoadF()
  
  Text$ = ""
  file$=OpenFileRequester("Please choose file...","","<*.bin> | *.bin", 0)
  If file$
    If ReadFile(0,file$)
      While Not Eof(0)
        Text$ + RSet(Hex(ReadByte(0)), 2, "0") + " "
      Wend
      CloseFile(0)
    EndIf
  EndIf
  
  ProcedureReturn Text$
  
EndProcedure 

Debug LoadF()
That's the easiest, but slowest way.
If you are more experienced look for ReadData() and read the file complete in memory.
That's much faster.

Bernd

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 11:10 am
by KJ67
If the file contains datas, and you know of the format, you could also think about the ReadData() function.

Code: Select all

Structure SomeFileFormat
  ; Format not known?
  A.a ; Variables better have logical names...
  B.a
  C.a
  D.a
  E.i
  F.i
  G.u
  H.f
  ;.....
EndStructure


Procedure LoadF()
  Protected *p.SomeFileFormat
  *p = AllocateMemory(SizeOf(SomeFileFormat))
  If *p <> #Null
    file$=OpenFileRequester("Please choose file...","","<*.bin> | *.bin", 0)
    If Len(file$) > 0
      Fh = ReadFile(#PB_Any,file$)
      If Fh <> #Null
        ReadData(Fh, *p, SizeOf(SomeFileFormat))
        CloseFile(Fh)
      EndIf
    EndIf
  EndIf
  ProcedureReturn *p
EndProcedure 

Procedure Main()
  ;
  ; ... Open window etc...
  ;
  Define *SomeDataBlock.SomeFileFormat
  *SomeDataBlock = LoadF()
  If *SomeDataBlock <> #Null
    SetGadgetText(#MyGadget, Str(*SomeDataBlock\E))
    ;
    ; ....
    ;
    FreeMemory(*SomeDataBlock)
  Else
    Debug "Failed allocating memory"
  EndIf
EndProcedure

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 11:11 am
by infratec
Oh,

you also want it a bit formatted:

Code: Select all

Procedure.s LoadF()
  
  Text$ = ""
  
  file$=OpenFileRequester("Please choose file...","","<*.bin> | *.bin", 0)
  If file$
    If ReadFile(0,file$)
      i = 0
      While Not Eof(0)
        Text$ + RSet(Hex(ReadByte(0)), 2, "0")
        i + 1
        If i = 15
          Text$ + #CR$
          i = 0
        Else
          Text$ + " "
        EndIf
      Wend
      CloseFile(0)
    EndIf
  EndIf
  
  ProcedureReturn Text$
  
EndProcedure 

MessageRequester("Test", LoadF())
Bernd

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 3:19 pm
by humungus
Thanx guys!
It`s working, but,... because of lack of knowledge I did not described exactly what I want to do...since morning I `m trying to find solution, no success. It seems that I approach to problem in wrong way. Excuse me for stupidity :oops:

I will try to explain again more detailed. This is memory dump ( file saved like data.bin) and on this way I can see it in bin or hex editor.

0000: AA 10 01 FF FF FF FF FF FF FF FF FF FF 1E 29 33
0010: C7 D2 D1 FF FF FF FF 37 78 22 7D 27 7E FF FF 4B
0020: A2 40 A0 24 0D 63 43 16 07 02 C1 81 31 55 32 37
0030: 31 31 66 99 FF FF FF FF FF FF FF FF FF FF FF FF
0040: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0050: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0060: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0070: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0080: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0090: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00A0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00B0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00C0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00D0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00E0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00F0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

So, I would like to read or open memory dump -file data.bin (it`s not necessary to show data in any gadget) and then to choose some bytes from some addresses (for this example it could be bytes from address $31 = 31 and data from address $1F=4B). Now I want to for example do some logic operation: 31 AND 4B = 7B (all must be HEX values to able to do it), and now to convert result 7B to string and show it textgadget.
I hope that I didn`t screw up this time :?

Do You have any idea how to do it? I`m thinking about load file into two dimensional array....but is it good approach or not?

Please, advise me what to do and how? Also, if You post some code, if it`s possible put some comments on it then I will analyze it in details to understand.

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 3:28 pm
by Baldrick
@humungus
Would this be data from a uC eeprom saved to a file by any chance?
That being the case, you wish to edit this file so you can then load back to eeprom?
Also, if this is the case, what is the size of the eeprom? ( 256 bytes from the look of the data you have posted?)

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 3:51 pm
by humungus
Would this be data from a uC eeprom saved to a file by any chance?
Yes Baldric :wink: ....it`s data from 24C02 (256bytes) serial eeprom. But this is only for example.
I saw that many people from electronic world started to use Purebasic because it perfectly suits to our needs.
So, here I`m too.
That being the case, you wish to edit this file so you can then load back to eeprom?
For now, I do not plan to load it back. When I learn more it will be next step...and few more.
Also, if this is the case, what is the size of the eeprom?
I used for example dump from 24C02, but I need possibility to open larger dumps. At this moment it`s irrelevant...I must to make first step.

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 4:05 pm
by Baldrick
Np, It is really pretty easy but i would suggest for you to place a copy of an eprom file on here for us to download so we can make a good working example for you.
Basicly you will read the file into a linked list as bytes. then you can decide how you wish to display, edit, etc & then save back to the file so you can push back to the eprom using whatever bootloader / programmer you are using.
I am sure myself or 1 of the people here will soon knock up a quick sample for you once we get a real file to chew on. :)

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 4:39 pm
by humungus
O.K. Baldrick :) , thank You very much!

I do not see how to upload file here, so, here is download link:

http://www.megaupload.com/?d=9O6Q8RT8

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 5:01 pm
by Demivec
humungus wrote:Do You have any idea how to do it? I`m thinking about load file into two dimensional array....but is it good approach or not?

Please, advise me what to do and how? Also, if You post some code, if it`s possible put some comments on it then I will analyze it in details to understand.
Here's an example that uses a simple memory buffer that is the size of the file:

Code: Select all

;So, I would like to read or open memory dump -file data.bin 
Procedure LoadF()
  Protected file$, fileNum, fileSize, *buffer
  file$ = OpenFileRequester("Please choose file...","","<*.bin> | *.bin", 0)
  If file$
    fileNum = ReadFile(#PB_Any, file$) ;open file for read
    If fileNum
      fileSize = Lof(fileNum) 
      If fileSize
        *buffer = AllocateMemory(fileSize)
        If *buffer
          ReadData(fileNum, *buffer, fileSize)
        EndIf 
      EndIf 
      CloseFile(fileNum)
    EndIf 
  EndIf
  ProcedureReturn *buffer ;return buffer pointer, size is determine by MemorySize(*buffer)
EndProcedure 

Define *buffer = LoadF()
If *buffer = 0 ;didn't create a buffer, either no file or no memory
  End ;quit
EndIf 

;and then to choose some bytes from some addresses 
;  (for this example it could be bytes from address $31 = 31 and data from address $1F=4B).
Procedure getByte(*buffer, offset) ;this procedure is just for convenience and readability
  ProcedureReturn PeekB(*buffer + offset)
EndProcedure

Define.a byte_1, byte_2, byte_3, byte_4 ;using '.a' ascii type for values 0 - 255, type '.b' is ok also
byte_1 = getByte(*buffer, $31) ;notice constants can be entered as hex values using $
byte_2 = getByte(*buffer, $1F) 

;Now I want to for example do some logic operation: 31 AND 4B = 7B
;  (all must be HEX values to able to do it),
byte_3 = byte_1 & byte_2 ;using the AND bit operator; all values here are integers, not HEX!
byte_4 = byte_1 | byte_2 ;using the OR bit operator, to get the results you were hoping for ;)

;and now to convert result 7B to string
Define Text$ = Hex(byte_3, #PB_Ascii) + ", " + Hex(byte_4, #PB_Ascii) ;convert integers to hex representation for display

;and show it textgadget.
#Text_6 = 0
OpenWindow(0, 0, 0, 100, 100, "Result", #PB_Window_SystemMenu) ;need a window for TextGadget
TextGadget(#Text_6, 0, 0, 50, 20, Text$) ;text can also be changed later with SetGadgetText()

Repeat: Until WaitWindowEvent() = #PB_Event_CloseWindow ;simple event loop

FreeMemory(*buffer) ;clean up
@Edit: Added FreeMemory() to clean up the allocated buffer. This is needed when the buffer is no longer needed.

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sat Jan 22, 2011 5:42 pm
by Baldrick
Very quick 1 as it is waaay past my bedtime & i should be asleep atm.
Will do 1 up into a simple gui using a linked list later when i get time, but this should be enough for you to see what to do.

Code: Select all

Procedure loadF()
    file$ = OpenFileRequester("Please choose file...","","<*.bin> | *.bin", 0)
    If file$<>""
        fileNum = ReadFile(#PB_Any, file$)
        If fileNum
                While Not Eof(fileNum)
                        dt.a= ReadByte(fileNum) 
                        Debug ".............."
                        Debug "location "+Str(a)
                        Debug dt
                        Debug "as hex = "+ Hex(dt) 
                        a+1
                Wend  
            CloseFile(fileNum)
        EndIf 
    EndIf 
        
EndProcedure 

loadF() 

Re: Exctrating data from binary file - NEWBIE :(

Posted: Sun Jan 23, 2011 12:11 pm
by humungus
Big thanx to Demivec and Baldrick!

Exactly what I need :D !

Re: Exctrating data from binary file - NEWBIE :(

Posted: Mon Jan 24, 2011 11:01 am
by Baldrick
Quickie knocked up a rough little sample, but should be enough to give the idea.
It will load the sample hex file into a linked list which is then displayed using a combo gadget to display list data in decimal, hex & 8 bit binary numbers. You can then edit the list & if you want save it back to a new file.

Code: Select all

Enumeration
  #Window_0
  #Combo_0
  #Text_Dec
  #Text_Hex
  #Text_Bin
  #Button_Edit
  #Text_3
  #Text_4
  #Text_5
  #Button_Save
  ;
  #Window_1
  #Text_1_1
  #Text_1_loc
  #Text_1_2
  #String_1_Val
  #Button_1_OK
  #Button_1_Cancel
EndEnumeration
Global NewList eepromDat.a()  ; make global so can be used between procedures easily
; cast list as type unsigned ascii to make life easier when dealing with 8 bit eeprom data
Procedure SetStatus(status)
  SelectElement(eepromDat(),status)
  SetGadgetState(#Combo_0,status) 
  SetGadgetText(#Text_Dec,RSet(Str(eepromDat()),3,"0")) 
  SetGadgetText(#Text_Hex,RSet(Hex(eepromDat()),2,"0")) 
  SetGadgetText(#Text_Bin,RSet(Bin(eepromDat()),8,"0"))
EndProcedure 

Procedure loadF()
    file$ = OpenFileRequester("Please choose file...","","*.bin | *.bin", 0)
    If file$<>""
      fileNum = ReadFile(#PB_Any, file$)
      If fileNum
        ClearList(eepromDat())  ; make sure list is empty
          While Not Eof(fileNum)
            AddElement(eepromDat()) ; add elements
            eepromDat()=ReadByte(fileNum) ; place data from file into list
          Wend 
        CloseFile(fileNum)
        SelectElement(eepromDat(),0) ; set to 1st element
        ProcedureReturn 1 
      EndIf
    EndIf      
EndProcedure

Procedure SaveF()
  File$=SaveFileRequester("Save File","","*.bin | *.bin",0) 
    If File$<>""
      overwrite=#PB_MessageRequester_Yes
      filenum=ReadFile(#PB_Any,File$)
      If filenum
        CloseFile(filenum) 
        overwrite=MessageRequester("File already exists","Overwrite file?",#PB_MessageRequester_YesNo) 
      EndIf
      file$=RemoveString(file$,GetExtensionPart(file$))
      file$=RemoveString(file$,".")   
      File$=GetPathPart(File$)+GetFilePart(File$)+".bin"
      If overwrite=#PB_MessageRequester_Yes
        newfile=CreateFile(#PB_Any,File$)
        If newfile
          size=ListSize(eepromDat()) 
          FirstElement(eepromDat()) 
          While a<size
            WriteByte(newfile,eepromDat()) 
            NextElement(eepromDat()) 
            a+1
          Wend 
          CloseFile(newfile) 
        EndIf 
      EndIf 
      If overwrite=#PB_MessageRequester_No
        SaveF()
      EndIf 
    EndIf 
EndProcedure 

Procedure ProcessUpdate() 
  NewVal=Val(GetGadgetText(#String_1_Val))
  position=Val(GetGadgetText(#Text_1_Loc))
    If NewVal<256
      SelectElement(eepromDat(),position)
      eepromDat()=NewVal
      SetStatus(position)
      CloseWindow(#Window_1)
      DisableWindow(#Window_0,0) 
      ProcedureReturn 1
    EndIf 
EndProcedure 

Procedure Open_Window_1(position) 
  If OpenWindow(#Window_1,216,0,150,90,"Edit",#PB_Window_SystemMenu,WindowID(#Window_0))
    TextGadget(#Text_1_1,20,10,50,20,"Location")
    TextGadget(#Text_1_Loc,20,30,50,20,Str(position),#PB_Text_Border)
    TextGadget(#Text_1_2,90,10,50,20,"Value")
    SelectElement(eepromDat(),position)
    StringGadget(#String_1_Val,90,30,50,20,Str(eepromDat()),#PB_String_Numeric)
    ButtonGadget(#Button_1_OK,20,60,50,20,"OK")
    ButtonGadget(#Button_1_Cancel,80,60,50,20,"Cancel")
    ProcedureReturn 1
  EndIf 
EndProcedure 

Procedure Open_Window_0()
  If OpenWindow(#Window_0, 216, 0, 550, 75, "New window ( 0 )",  #PB_Window_SystemMenu  | #PB_Window_TitleBar )
      ComboBoxGadget(#Combo_0, 20, 30, 80, 20)
      TextGadget(#Text_Dec, 110, 30, 60, 20, "", #PB_Text_Border)
      TextGadget(#Text_Hex, 180, 30, 60, 20, "", #PB_Text_Border)
      TextGadget(#Text_Bin, 250, 30, 100, 20, "", #PB_Text_Border)
      ButtonGadget(#Button_Edit, 360, 30, 80, 20, "Edit")
      TextGadget(#Text_3, 110, 10, 60, 20, "Dec", #PB_Text_Center)
      TextGadget(#Text_4, 180, 10, 60, 20, "Hex", #PB_Text_Center)
      TextGadget(#Text_5, 250, 10, 100, 20, "Bin", #PB_Text_Center)
      ButtonGadget(#Button_Save, 450, 30, 80, 20, "Save")
      ProcedureReturn 1 
  EndIf
EndProcedure

If Not loadF()
  MessageRequester("Fault","no file loaded") 
  End 
EndIf 

If Not Open_Window_0()
  MessageRequester("Fault","Main window initialisation fail")
  End 
    Else 
  a=0
  While a<ListSize(eepromDat())
    AddGadgetItem(#Combo_0,-1,Str(a))
    a+1
  Wend  
  SetGadgetState(#Combo_0,0) ; set the gadgets with data to start up
  SetStatus(0)
  SetActiveGadget(#Combo_0)
EndIf 

Repeat 
  Ev=WaitWindowEvent(1)
    If Ev=#PB_Event_Gadget 
      Select EventGadget()
        Case #Button_Edit 
          If Open_Window_1(GetGadgetState(#Combo_0))
            DisableWindow(#Window_0,1)
          EndIf 
        Case #Combo_0
          SetStatus(GetGadgetState(#Combo_0))
        Case #Button_Save
          SaveF()
        Case #Button_1_OK
          If Not ProcessUpdate()
            MessageRequester("Error","Value out of range, please use a different value") 
          EndIf 
        Case #Button_1_Cancel
          CloseWindow(#Window_1) 
          DisableWindow(#Window_0,0)
      EndSelect 
    EndIf 
 
    If Ev=#PB_Event_CloseWindow 
      Select EventWindow() 
        Case #Window_0
          quit=1
        Case #Window_1
          CloseWindow(#Window_1) 
          DisableWindow(#Window_0,0) 
      EndSelect 
    EndIf 
Until quit

Re: Exctrating data from binary file - NEWBIE :(

Posted: Mon Jan 24, 2011 12:26 pm
by ultralazor
This is probably the best example you'll see: http://www.purebasic.fr/english/viewtop ... 79#p214779

You have to manually handle endianness and byte conversion despite what some 'experts' here say. Here is a simple example, but only reads byte-per-byte so no endian handling(endian isn't a problem in most binaries, just things like executable wrappers and dumps):

Code: Select all

Global.l dos_stub_end
OpenConsole()
file$ = OpenFileRequester("Path to binary","file.exe","EXE|*.exe;DLL|*.dll;SYS|*.sys",0)
If ReadFile(0,file$)
  FileSeek(0,$3C)
  dos_stub_end = Val(Hex(ReadByte(0))+Hex(ReadByte(0))) ;actual hex or short stub would break this, and a parser would have to be done like you would in masm,,this is BASIC^^
  FileSeek(0,0)
  PrintN("Using common stub length:")
  Repeat
    If Loc(0) = $100 : Debug Chr(ReadByte(0))+Chr(ReadByte(0)) : Break : Else : hex$+Hex(ReadByte(0)) : EndIf
  ForEver
  PrintN(hex$)
  PrintN("Using read pointer to end:")
  FileSeek(0,0)
  Repeat
    hex$ + Hex(ReadByte(0))
    ;simple demo..doesn't handle pointer with >9 place, it'd need to be manually converted and de-endiened etc..
    If Loc(0) = dos_stub_end : Debug Chr(ReadByte(0))+Chr(ReadByte(0)) : Break : Else : hex$+Hex(ReadByte(0)) : EndIf
  ForEver
  Print(hex$)
  dd$=Input()
EndIf
End
NOTE:dumping into a buffer and reading 8 bytes at a time then parsing seems to be the fastest for typical binaries.

Re: Exctrating data from binary file - NEWBIE :(

Posted: Wed Jan 26, 2011 5:20 pm
by humungus
Hi to all,

after analyzing codes, I decided to try with code provided from Demivec (because I almost understood whole code).
But now I have another problem. I want to make some calculation and to show result using one of this two procedures:

Code: Select all

Procedure.s calculation()
  data1= (PeekB(*buffer +$1E) ! $10) + $25
  data2=(PeekB(*buffer + $1F) ! $10)+ $25
  data3=(PeekB(*buffer + $20) ! $10)+ $25
  data4=(PeekB(*buffer + $21) ! $10)+ $25
  Result$ = Hex(data1, #PB_Byte)+Hex(data2, #PB_Byte)+Hex(data3, #PB_Byte)+Hex(data4, #PB_Byte)
   ProcedureReturn Result$
  EndProcedure

or second way (basically it`s the same) :

Code: Select all

Procedure getByte(*buffer, offset) ;this procedure is just for convenience and readability
  ProcedureReturn PeekB(*buffer + offset)
EndProcedure

Procedure.s calculation()
 
  data1= (getByte(*buffer, $1E) ! $10)+ $25
  data2=(getByte(*buffer, $1F) ! $10) + $25
  data3=(getByte(*buffer, $20) ! $10) + $25
  data4=(getByte(*buffer, $21) ! $10) + $25
  Result$ = Hex(data1, #PB_Byte )+Hex(data2, #PB_Byte )+Hex(data3, #PB_Byte )+Hex(data4, #PB_Byte )
   ProcedureReturn Result$
EndProcedure

but in both cases program crash with error report: Invalid memory access when i call it with:

Code: Select all

...
ElseIf EventGadget = #Button_4
calculation()
SetGadgetText(#Text_6,Result$)

it works only when i call it on this way:

...

Code: Select all

ElseIf EventGadget = #Button_4
  data1= (getByte(*buffer, $1E) ! $10)+ $25
  data2=(getByte(*buffer, $1F) ! $10) + $25
  data3=(getByte(*buffer, $20) ! $10) + $25
  data4=(getByte(*buffer, $21) ! $10) + $25
  Result$ = Hex(data1, #PB_Byte )+Hex(data2, #PB_Byte )+Hex(data3, #PB_Byte )+Hex(data4, #PB_Byte )
  SetGadgetText(#Text_6,Result$)
  
So, when I`m not using procedures it`s correct :-(
I can finish it on this way but I want to learn Purebasic well, so, I must to complete task with using procedures.....again I readed chapter6 and chapter13 from begginers guide..I can not understand where is error. Can You tell me what I`m doing wrong ?