I have added support of creation of 8xp files to Assemblex. To my surprise, it would only work in files with x size. I did find out that somewhere in the header the length of the program data and the length of the program data+x are written.


Code:
2A2A54493833462A1A0A0046696C652067656E6572617465
64206279205761626269745369676E00000000000000000000000
0000029000D0018000650524F4752414D00000018001600BB6DEF
40453E01C60526006FEF0745EF7249EF4045C9CE0B


This is a .8xp file (assembly) that displays 6, it has an add a,l, and then displays HL, some bcalls, here is the data:


Code:
EF40453E01C60526006FEF0745EF7249EF4045C9


This file was generated by SPASM, so in the header it says SPASM made it, like in SourceCoder, Tokens or DevPack8x. What I need to understand is from where to where is what (size, program it was made by).



Code:
All values are in decimal.

8XP File:
(1-11)Header (11 bytes): 42,42,84,73,56,51,70,42,26,10,0
(12-52)Comment (42 bytes): 42 bytes of ASCII, if the comment is <42 bytes then fill the rest of the space with 0s
(53)Comment Delimiter: 0
(54-55)Length of the Data Section (2 bytes): Length of the data section+19
(56-57)Random Stuff (2 bytes): 13,0
(58-59)Length of the Data Section (2 bytes): Length of the data section+2
(60)Protected (1 byte): 6 if yes, 5 if no
(61-68)Program Name (8 bytes): Program Name (in ASCII)-fill with 0s if <8 bytes
(69-70)More Random Stuff (2 bytes): 0,0
(71-72)Length of the Data Section (2 bytes): Length of the data section+2
(73-74)Length of the Data Section (2 bytes): Length of the data section
(75-?)Data Section (Varies): The program's data
Checksum: Checksum of 56 bytes to the byte before the checksum

For more info on calculating the checksum, see Peter's origional file.


I found this at ticalc.org, but it doesn't seem very correct, according to files made with Brass/DevPack8x and SPASM. So, I need your help with the structure of the 8xp file (mainly size, name of program, and text header which means who made it).

Edit by Tanner: Added line breaks in the first code section
Have you read through this document? If/once you have, is there anything specifically unclear about it?
Thanks much merth!


Code:
2A2A54493833462A1A0A0047656e65726174656420627920
417373656d626c65782c20627920446176696420476f6d65730000
000029000D0018000650524F4752414D00000018001600BB6DEF4
0453E01C60526006FEF0745EF7249EF7249C9CE0B


I understood that and already made my own description ("Generated by Assemblex, by David Gomes").

However, after the comment it says:


Code:
Length, in bytes, of the data section of the file. This number should be 57 (39h) bytes less than the file size.


What I find in my code is 2900.

2900... The length of the program data is 40 characters, which means 20 bytes. The program size is 98 bytes. So, why 2900?

Edit by Tanner: Same deal as above.
You have to keep in mind that the numbers are stored in little-endian. This means that 0x2900 = 41. So, your program is 98 bytes, 98-57 is 41, which is 0x2900. Does that make sense?
merthsoft wrote:
You have to keep in mind that the numbers are stored in little-endian. This means that 0x2900 = 41. So, your program is 98 bytes, 98-57 is 41, which is 0x2900. Does that make sense?
The key is indeed little-endian. Surely you should be familiar with this from your disassembler work. Smile
Oh I see! Now it makes sense, is there any way, in python to convert a number to Little Endian automatically?
ScoutDavid wrote:
Oh I see! Now it makes sense, is there any way, in python to convert a number to Little Endian automatically?
I'm not familiar with Python at that level, so Kerm might better answer, but I think you'll want to use a struct. There are some examples there, so hopefully that at least points you in the right direction.
Program names are 8 letters long and can't start with Numbers. So, I will do that for Assemblex, 8 letters long.
ScoutDavid wrote:
Program names are 8 letters long and can't start with Numbers. So, I will do that for Assemblex, 8 letters long.
And names less than 8 letters must be padded with zeros, don't forget. I'd give you a hint of some Python code I have released that already does .8xp header creation, but I want you to figure this out on your own (with our help, of course). As far as little-endianness, I usually do it with bitmath:


Code:
Byte0 = size|0x000000ff;
Byte1 = (size>>8)|0x000000ff;
Hum, so as the comment, padded with zeros.

Concerning little endian, I don't really understand your point Kerm, but I think I could do my own engine.

I convert the number to hex (98-57=41). 41 in hex is 29. The little endian value is 2900.

Oh wait, it's not that simple xD
/me did a little explanation here:

http://www.cemetech.net/forum/viewtopic.php?p=132898#132898

http://www.cemetech.net/forum/viewtopic.php?p=132905#132905

http://www.cemetech.net/forum/viewtopic.php?p=132911#132911

Smile
ScoutDavid wrote:
Hum, so as the comment, padded with zeros.

Concerning little endian, I don't really understand your point Kerm, but I think I could do my own engine.

I convert the number to hex (98-57=41). 41 in hex is 29. The little endian value is 2900.

Oh wait, it's not that simple xD
What? Don't just ignore what I said because it looks complicated; try to understand what it means. And definitely take a look at Deep Thought's well-phrased and thoroughly-researched explanations.

Code:
def to_binary(hex_string):
         ints = [int(hex_string[i:i+2], 16) for i in range(0,len(hex_string),2)]
         return struct.pack('B' * len(ints), *ints)
      
      dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "8XP Files (*.8xp)|*.8xp", \
            wx.SAVE | wx.OVERWRITE_PROMPT)
            
      if dlg.ShowModal() == wx.ID_OK:
         
         programData = self.inputText.GetValue()
         
         inputLength = ((len(programData)+106+42+8)/2)-57
         
         print inputLength
         
         print str(hex(inputLength))
         
         finalProgram = "2A2A54493833462A1A0A0047656e65726174656420627920417373656d626c65782c20627920446176696420476f6d657300000000"+str(hex(inputLength))+
"000D0018000650524F4752414D00000018001600BB6D"+programData+"CE0B"
         
         self.filename=dlg.GetFilename()
         self.dirname=dlg.GetDirectory()
         filehandle=open(os.path.join(self.dirname, self.filename),'wb')
         
         
         filehandle.write(to_binary(finalProgram))
         filehandle.close()
            
         self.SetTitle('Assemblex - '+self.filename)
         
      dlg.Destroy()


This is what i have so far, but it's not working.

Deep Thought's explanation look much better than all the ones I'd seen before!
Well, you know your routine will never run more than the first two lines the way you have it written currently, correct?


Code:
       ints = [int(hex_string[i:i+2], 16) for i in range(0,len(hex_string),2)]
         return struct.pack('B' * len(ints), *ints)
Kerm, this code used to work:


Code:
def to_binary(hex_string):
         ints = [int(hex_string[i:i+2], 16) for i in range(0,len(hex_string),2)]
         return struct.pack('B' * len(ints), *ints)
       
      dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "8XP Files (*.8xp)|*.8xp", \
            wx.SAVE | wx.OVERWRITE_PROMPT)
             
      if dlg.ShowModal() == wx.ID_OK:
         
         programData = self.inputText.GetValue()
         
         inputLength = ((len(programData)+106+42+8)/2)-57
         
         print inputLength
         
         print str(hex(inputLength))
         
         finalProgram = "2A2A54493833462A1A0A004
7656e6572617465642062
7920417373656
d626c65782c20627920446176696420476f6d657300000000290
00D0018000650524F4752414D00000018001600BB6DEF40453E
01C60526006FEF07
45EF7249EF4045C9CE0B"
         
         self.filename=dlg.GetFilename()
         self.dirname=dlg.GetDirectory()
         filehandle=open(os.path.join(self.dirname, self.filename),'wb')
         
         
         filehandle.write(to_binary(finalProgram))
         filehandle.close()
             
         self.SetTitle('Assemblex - '+self.filename)
         
      dlg.Destroy()


The to_binary() created 8xp files, but only for files the same size as the one in finalProgram.
Ah, then you're somehow showing me improper indenting (do you copy-and-paste code from somewhere, and thus have a mix of tabs and spaces? That's what it looks like) so it looked like all of that code was in the body of the to_binary(hex_string) function. Can you explain where you got "inputLength = ((len(programData)+106+42+8)/2)-57" from?
KermMartian wrote:
Ah, then you're somehow showing me improper indenting (do you copy-and-paste code from somewhere, and thus have a mix of tabs and spaces? That's what it looks like) so it looked like all of that code was in the body of the to_binary(hex_string) function. Can you explain where you got "inputLength = ((len(programData)+106+42+8)/2)-57" from?


That would be the size of the program (header+length of the program data).

I divide it by two to be the number of bytes, not characters. -57 to get the number I need to put in the code.
There are the same number of bytes and characters; one byte is one character. A3 is a byte, and it's a character. A or 4 or F or 0 is one nibble, four bits, half a byte, half a character, not a whole byte or a whole character. The header is 57 bytes long, but that whole /2 part makes me worry that you still are confused about the difference between a hex nibble and a byte.
I think that was there so he could take the hexadecimal decompiling characters (minus the newlines, of course) and figure out the new file size. Though I very well could be wrong.
_player1537 wrote:
I think that was there so he could take the hexadecimal decompiling characters (minus the newlines, of course) and figure out the new file size. Though I very well could be wrong.
I think you're exactly right, but I also think he should be dealing with bytes, not nibbles. Smile
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 3
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement