News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_eto

read and write file header

Started by eto, 19:37, 30 April 22

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

eto

I want to change the load address in the header from BASIC, which obviously is not possible directly.

Would someone have an example where (only) the header is loaded and then saved again?

(Or is there a way to specify the load address when using SAVE "filename",b in BASIC?)

m_dr_m

If you want to change from OLD to NEUF:

MEMORY NEUF
LOAD"teto",NEUF
SAVE"teto",b,NEUF,SIZE,EXEC

BASIC alternatives:
  • Create the header yourself in an "ascii" stream. Acrobatic and not tested.
  • Utopia's |SAVE allows to save an arbitrary area and to specify a distinct "load address".

Non-BASIC alternatives:
  • Le hackeur (hackit) allows that as well.
  • Edit the header with a sector editor.

GUNHED

Using FutureOS you can load files into RAM including the header, you can load the header alone and you can save a file including a header you did edit in RAM.

Let me know if you're interested in that topic, then I will elaborate on that.  :)
http://futureos.de --> Get the revolutionary FutureOS (Update: 2023.11.30)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> Get the RSX-ROM for LambdaSpeak :-) (Updated: 2021.12.26)

eto

Quote from: GUNHED on 00:48, 01 May 22Using FutureOS you can load files into RAM including the header,
Nice. But in my case not an option as I would prefer to have it in BASIC.
 

Quote from: m_dr_m on 00:03, 01 May 22If you want to change from OLD to NEUF:

MEMORY NEUF
LOAD"teto",NEUF
SAVE"teto",b,NEUF,SIZE,EXEC


BASIC alternatives:
  • Create the header yourself in an "ascii" stream. Acrobatic and not tested.
  • Utopia's |SAVE allows to save an arbitrary area and to specify a distinct "load address".


Load / Save is not an option as it would be addresses that can be in the area below &400. Ascii stream might be tricky. Utopias |save could be an option. Maybe I can disassemble it and understand what it's doing to extract that part and create my own routine. 

GUNHED

Well, without FutureOS I would suggest an disc-editor (Discology f.e.), but in this case you need to adapt the checksum by hand.
http://futureos.de --> Get the revolutionary FutureOS (Update: 2023.11.30)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> Get the RSX-ROM for LambdaSpeak :-) (Updated: 2021.12.26)

Nworc

Quote from: etoI want to change the load address in the header from BASIC, which obviously is not possible directly.

Would someone have an example where (only) the header is loaded and then saved again?

Here comes the "why" question, why would you like to do that - what do you want to achieve?

The point is, no matter what you set the load address in the header to, BASIC will ignore that and load the file to &0170, if you are using BASIC to load it.

Using an MC program one way to change the load address would be to load the file to a different location and save it from there using the regular AmsDOS functions for load and save (BASIC has the filetype 0 btw). That way the BASIC file will get the desired load address in the header. Again, the question is what for, as AmsDOS won't care.

eto

Quote from: Nworc on 16:27, 03 May 22Here comes the "why" question, why would you like to do that - what do you want to achieve?
tldr; to create self-deflating executables from within BASIC - out of curiosity based on an idea I had and to share something hopefully useful with others. 

And here the "slightly" longer WHY:

BASIC might not be the most elegant or the most intelligent thing and I will definitely find other ways but during following an idea I had, I came across this question - and although I can solve it differently and maybe better, I am still curious if it might work. 

Maybe you have seen my post regarding ZX0 decompressors for BASIC. I'm trying to make ZX0 available to people that are not familiar with assembler. Not sure if they exist, but hey - it's just about an idea I have. So, besides the cases I have already mentioned there, there is another case that I am trying to solve from within BASIC. ZX0 can also decompress backwards, so that it's e.g. possible to decompress a game that fills basically the whole RAM. E.g. the game Hacker starts around 0x152 and it grows beyond HIMEM. The original loader uses LDIR to copy the binary from 0x100 to 0x152 (not sure about the exact numbers)... Using a normal ZX0 decompression routine, I was not able to decompress without crashing. However it works when I used a decompressor routine that started at 0x100 and concatened it directly with the ZX0 compressed binary. I did that in Windows and used a Windows tool to set the right values in the header. Then I could run the binary, it decompresses Hacker into the right position and then calls the exec address. Works perfectly fine and reduces the space required on disc from 42KB to 20.

I liked the approach to have a self-deflating executable and I was now thinking about, if that can be less of a manual process AND be something I can share with others in a way that they do NOT need anything special, except for ZX0. So my idea was, to make that in BASIC. Create a generic decompressor routine, load a ZX0 compressed binary to RAM directly following the decompressor routine, patching some values 
AND THEN write everything to disk so it can be executed. But for that I would need to change the load-address, as it needs to be loaded to an address that is occupied by my BASIC program while patching. 

Then my ideas were:
1) is it possible to patch the header itself? Can I e.g. save the binary and then just load the header and change the loading address to 0x100. => but I couldn't find an example code that would do that.
2) Or is there a way to save the binary and specify the loading-address differently from the address in RAM. |save from Utopia is doing exactly that, but it's nothing I would then see as a solution I can provide to others. I tried to follow what Utopia is doing there using the WinApe debugger, but I didn't get how they managed to patch the header data. 

It doesn't need to be BASIC, assembler is fine, I just don't have the experience/knowledge to start from scratch but could adapt something existing. 

Nworc

In those rare cases where I had to patch the start address, I was also using a disc editor to do the patching.

For your manual efforts and for testing/experimenting I would recommend SMon1.4: if you press the Tab key it toggles to the 2nd RAM set and allows to load a file (L key) to any address you want in the whole 64K (it will be the 2nd 64K set), you can then save the file (S key) and it will receive the properties from the save action, so just load it whereever you want to have it to, and then just save it, the parameters from loading are remembered so you don't have to type them again. Escape from SMon using !, re-enter it using |SM.

For your task I would recommend the following, it's just an idea and other people will have other ideas ...

I would do a small program (MC) that just accepts an arbitrary file (should accept both BASIC and binary). The properties of that file (Name, Type, Start, Length, Exec-Point) are remembered, but the file will just be read to a fixed location that suits the decompressor algo.

After compressing, the file will be written as a binary file, with a small MC routine in front of it which will be executed once that file is started (so the new Exec-Point will be that of the decompressor, and the new filetype will be binary). The former Exec-Point and filetype is also stored in that decompresser algo (before saving).

If that saved binary file is then started from within BASIC (run"file"), after loading the decompressor would be executed, and would do the decompressing to the right location and will then either exeute the program as MC using the stored Exec-Point, or otherwise start the BASIC program if the filetype was BASIC.


GUNHED

BTW... or not-completely-off-topic...

Using maxam you can save a file with the WRITE"xxx.COM" option. In this case a binary is written without any file-header.
Now, if you just start your code with 128 bytes "DB xx,xx,xx,xx, ...." you will create an artificial header. This way the file-header will contain what you want. After the header you use the "ORG xxxx" directive to define the start of your code.
(I do that on a regular base to add small icons to a file header for example).
http://futureos.de --> Get the revolutionary FutureOS (Update: 2023.11.30)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> Get the RSX-ROM for LambdaSpeak :-) (Updated: 2021.12.26)

eto

Thanks for all the ideas.


I was curious if it would be possible from within BASIC so it can be reused by others, without the need for anything special.

Not a big deal that this will not work out, I do have some other options that will work for me. I will probably use WinApe assembler to include the compressed binary directly into the output. That generates an executable binary with all required data included and the attributes set properly.

(btw: I like the idea to include icons into the unused header part)

Powered by SMFPacks Menu Editor Mod