Memory Full

Forum / Development

Orgams - Useful tips.

m_dr_m * 08 May 2022 17:47:22

Use Orgams as a hacker!

I am not talking about that.

I wanted to hack the Soundtrakker Azerty version, requiring the following steps:
• Load the executable.
• Patch it so it returns after decrunching.
• Call the decruncher.

Well, you can script all those steps as an Orgams source! And even add some extra verification (see check around size).

start = &ff5
size = &7738
exec = &8680

   ORG start
   LOAD"soundt"

; Sanity check --------
   IF start+size - $
    !!! Unexpected size. Is it the right version?
   END
 
; Patch ---------------
   ORG exec+&17
      RET Z:NOP:NOP  ; replace the JP Z,&8c5

   ENT exec



Then CONTROL-2!

Pro:
- Ultra fast if you have to do it several time ("SOUNDT" will be cached in extra memory).
- Less risk to enter the wrong address for execution.
- Far more handy than the 'assemble' command of Hackeur 7.1.

Con:
- The patch itself is done blindly.

Just make sure to use FF Beta E or more recent.

m_dr_m * 04 Jun 2022 19:56:08

== Skip tip ==

Bug #127 was fixed this week, this is a near-perfect opportunity to remind you the usefulness of the SKIP directive. Make sure to install FF beta F.

`SKIP n` advances $ and $$ without emitting code. Importantly, it doesn't update low-high addresses which are used for binary save.

What is it good for?

1. Memory maps

When you have tables and structures with some custom sizes, replace

table1 = &1000 
table2 = table1 + MAX_Y*MAX_CHAR*2 
table3 = table2 + MAX_ENTRIES*SIZE_ENTRY
table4 = &2000   ; Must be at &2000



by

    ORG &1000
table1 SKIP MAX_Y * MAX_CHAR * 2
table2 SKIP MAX_ENTRIES * SIZE_ENTRY
table3
     ALIGN(&2000) ; Make sure no overlap occurs.
table4



Advantages:
* Each size is associated with its table.
* It's more legible, and make it easier to insert another table or to re-order them.
* We ensure tables aren't overlapping each other by mistake.

2. Structures

We often deals with contiguous fields whose offset we want to know. Exemple:

dot_x = 0    ; It's a word 
dot_y = 2    ; It's a byte
dot_rgb = 3 ; It's 3 bytes
dot_size = 6  

[...]
   ld (ix+dot_y),a



Instead, we can use the fact that no code is emitted to write:

   ORG 0   ; Won't assemble anything at 0...
dot_x     WORD  ; (equivalent to SKIP 2)
dot_y     BYTE  ; (equivalent to SKIP 1)
dot_rgb  SKIP 3
dot_size



Since we are fiddling with ORG, it should be done before the main ORG, or the last thing in the source.
You could also store/restore like that:

savepc = $
saveobj = $$

; define all your structs and tables.
   ORG 0
... 

   ORG savepc, saveobj



Admittedly, it's a bit more hackish than a dedicated "STRUCT" directive. On the other hand, I appreciate the ability to achieve functionalities with basic building blocks. By the way SKIP could (should?) have been a MACRO.

   MACRO DO_SKIP n
       ORG $+n,$$+n
   ENDM



What is it not good for?

For alignement, you'd rather use FILL, so that the padding is... filled, hence more crunchable (*), in a dedicated MACRO to show intent. See ALIGN.

Also, it does nothing for your gut issues.

(*) Note that filling with a uniform byte like 0 doesn't always give the best compression, but that's another matter.