Emulation Multi-platform builder scripts for GBA emulators

patters

Well-Known Member
OP
Member
Joined
Jan 28, 2006
Messages
172
Trophies
1
XP
892
Country
The binary data structure is pretty straightforward. Having examined a compilation binary I can see that it's the same format as the one used for the Famicom Advance emulator (which HVCA is descended from), which has source for its builder fca-mkfs.c available here.
 
Last edited by patters,
  • Love
Reactions: hippy dave

hippy dave

BBMB
Member
Joined
Apr 30, 2012
Messages
9,886
Trophies
2
XP
29,357
Country
United Kingdom
HVCA now has a modern multiplatform build script :)
It rebuilds missing FDS headers automatically since these seem to have been stripped from most currently available ROMs.
https://github.com/patters-match/gba-emu-compilation-builders
Amazing, looking forward to trying it out - huge thanks! :gba:
Post automatically merged:

Tried it out with a handful of FDS games, and they built fine (was doing one game per .gba, might try a compilation rom another time). Tested a couple on my GBA and EZF Omega and it's all working great! Like the hvca blurb says, it doesn't support saving to disk, but you can use save states. I found loading save states didn't work in mgba, but worked great on hardware.

One thing that would be an amazing addition if someone can figure it out - the hvca emulator supports adding code to quit back to the flashcard menu, but the ones supplied are for old flashcards because hvca be old. Would be nice to have one for the Omega. Will admit I didn't test to see if the ones for older EZF cards would work on Omega anyway, maybe later.

Thanks again for the build script, made things totally painless!
 
Last edited by hippy dave,

patters

Well-Known Member
OP
Member
Joined
Jan 28, 2006
Messages
172
Trophies
1
XP
892
Country
To use a .cfg it must be renamed to match the filename of the game it targets. I have confirmed I can use a .cfg file to get NES Punch Out!! working. I just amended the file with a clarification to that effect in the help, and to ensure .cfg files also have brackets stripped when -c option is used so they match the ROM naming. Refresh your copy.

I am away at the moment, but I have copied the EZ4 reset code into a new reset .sub file. I will test whether I can get that working on my EZ4. I don't have an Omega though.
 
Last edited by patters,
  • Love
Reactions: hippy dave

patters

Well-Known Member
OP
Member
Joined
Jan 28, 2006
Messages
172
Trophies
1
XP
892
Country
One thing that would be an amazing addition if someone can figure it out - the hvca emulator supports adding code to quit back to the flashcard menu, but the ones supplied are for old flashcards
I spent some time looking at this last night. I disassembled the HVCA-included first gen EZ-Flash example and discovered that it is ARM32 code very similar to the EZ-Flash IV exit ARM Thumb 16bit code here. Notice that the memory addresses are encoded in the .BYTE data at the bottom of the disassembly.

Cross-referencing existing ARM32 examples in the ez3pda source code, we seem to need the following for EZ-Flash IV (in pseudo-code):

//SetRomPage(0x8000) which, judging from the EZ-Flash Omega documentation, will page in the cart's kernel (placing it in OS mode):
We can toggle between OS mode and Game mode by set the bit 15 of Rompage to 1 or 0. Set rompage = 0x8000, system goes to OS mode. Set rompage(0), system goes to Game mode.

Code:
store half-word 0xd200 at address 0x9fe0000
store half-word 0x1500 at address 0x8000000
store half-word 0xd200 at address 0x8020000
store half-word 0x1500 at address 0x8040000
store half-word 0x8000 at address 0x9880000
store half-word 0x1500 at address 0x9fc0000

//minireset
Code:
store half-word 0x0000 at address 0x03007ffa
move word 0x000000fc into register r0
supervisor call 0x01
supervisor call 0x00

The problem is that we can't run these instructions from NOR or PSRAM because the cart is paging its kernel back into the GBA cartridge port address space (replacing the NOR/PSRAM), so the code will need copying to the GBA's RAM first - hence why it's in a file called inram.cpp in the ez3pda source.

However, there is no indication at all that this presumably working EZ-Flash I code from HVCA is copying itself to RAM. Logically it would need to, since this flashcart works in a very similar way to its later evolved designs. I strongly suspect then, that HVCA is handling that part, and we only need to drop the actual reset code into the .sub file. This might explain why the existing EZ-Flash IV code from other emulators doesn't work. It doesn't need to be that complex - it doesn't need to copy itself to RAM because HVCA will do that.

Now that I have worked this out by writing it all out, I will try again later...
 
Last edited by patters,
  • Love
Reactions: hippy dave

hippy dave

BBMB
Member
Joined
Apr 30, 2012
Messages
9,886
Trophies
2
XP
29,357
Country
United Kingdom
I spent some time looking at this last night. I disassembled the HVCA-included EZ-Flash I example and discovered that it is ARM32 code very similar to the EZ-Flash IV exit ARM Thumb code here.

Cross-referencing existing ARM32 examples in the ez3pda source code, we seem to need the following for EZ-Flash IV (in pseudo-code):

//SetRomPage(0x8000) which, judging from the EZ-Flash Omega documentation, will page in the cart's bootloader:
Code:
store half-word 0xd200 at address 0x9fe0000
store half-word 0x1500 at address 0x8000000
store half-word 0xd200 at address 0x8020000
store half-word 0x1500 at address 0x8040000
store half-word 0x8000 at address 0x9880000
store half-word 0x1500 at address 0x9fc0000

//minireset
Code:
store half-word 0x0000 at address 0x03007ffa
move word 0x000000fc into register r0
software interrupt 0x01
software interrupt 0x00

Now that I have worked this out, I will try again later. I think perhaps my previous attempts weren't working owing to differences in implementation between ARM32 (as per the ez3pda source) and 16bit Thumb mode (which Kuwanger's code used for resetting).
Amazing work as always :gba:
 

patters

Well-Known Member
OP
Member
Joined
Jan 28, 2006
Messages
172
Trophies
1
XP
892
Country
For good measure - here are the disassemblies of each of HVCA's flashcart reboot functions:
Each of these routines has a consistent end section:
Code:
mov r0, #0
mov r1, #0x4000000
strh r0, [r1, #-6]     @ store half-word 0x0000 at address 0x3fffffa
mov r0, #0xfc          @ move word 0x000000fc into register r0
svc #0x10000           @ supervisor call 0x10000
svc #0                 @ supervisor call 0x00000

More known-good EZ-Flash reset code here:
https://github.com/EvilJagaGenius/jagoombacolor/blob/master/src/visoly.s

It also uses supervisor call 0x10000 followed by supervisor call 0x00000.
Post automatically merged:

Ok, so here is my tweaking of the flash_ez1.sub disassembled source to create flash_ez4.sub:
Code:
# HVCA exit code for EZ-Flash IV / 3in1 / Omega
# by patters in 2023
#
# https://gbatemp.net/threads/multi-platform-builder-scripts-for-gba-emulators.611219/post-10138443

add   sb, pc, #0x48          @ sb = start of .BYTE definitions
ldm   sb, {r1, r2, r3, r4}
mov   r5, #0xd200
mov   r6, #0x1500
strh  r5, [r1]               @ 0x9fe0000 = 0xd200
strh  r6, [r2]               @ 0x8000000 = 0x1500
strh  r5, [r3]               @ 0x8020000 = 0xd200
strh  r6, [r4]               @ 0x8040000 = 0x1500
mov   r0, #0x8000
ldr   r1, [pc, #0x34]        @ 5th .BYTE
strh  r0, [r1]               @ 0x9880000 = 0x8000
mov   r0, #0x1500
ldr   r1, [pc, #0x2c]        @ 6th .BYTE
strh  r0, [r1]               @ 0x9fc0000 = 0x1500
mov   r0, #0
mov   r1, #0x4000000         @ 0x9fc0000 = 0x1500
strh  r0, [r1, #-6]          @ 0x3fffffa = 0x0000
mov   r0, #0xfc
svc   #0x10000
svc   #0
.BYTE 0x00, 0x00, 0xfe, 0x09
.BYTE 0x00, 0x00, 0x00, 0x08
.BYTE 0x00, 0x00, 0x02, 0x08
.BYTE 0x00, 0x00, 0x04, 0x08
.BYTE 0x00, 0x00, 0x88, 0x09
.BYTE 0x00, 0x00, 0xfc, 0x09

...which assembles into the 104 byte file which is attached to this post.
:yaysp: And it actually works on my EZ-Flash IV! I'm very pleased with that. :toot:

I think it ought to work on EZ-Flash 3in1 / Omega / Omega DE too. Please try it and let me know. You'll need to add the exit sub using my build script's -x command line option.

The final point of confusion is that if you select <EXIT Emulation> from the menu it only resets the emulator. You need to Hold L+R whilst in the menu to actually exit back to the flashcart menu (keep holding while the screen turns black). The clue to this was in the rather intriguing controls schematic in the HVCA readme.

Take note - all of this was made possible by Open Source. I know next to nothing about ARM ASM, and I'm not a software developer. If I can do this then so can you, with curiosity, logic, and patience.
 

Attachments

  • flash_ez4.zip
    1.3 KB · Views: 19
Last edited by patters,
  • Like
Reactions: hippy dave

patters

Well-Known Member
OP
Member
Joined
Jan 28, 2006
Messages
172
Trophies
1
XP
892
Country
Thanks, can you explain what the difference is to an ASM novice like me?
Is it that you're setting RomPage to 0x8002? The ez3pda source and examples I linked to all use 0x8000. The Omega docs say kernel is at 0x8002.

My reset code definitely works on my DS Lite with my EZ-Flash IV though - so does the hang you described apply to EZ-Flash Omega only?
 
Last edited by patters,

TechieSaru

Well-Known Member
Newcomer
Joined
Mar 2, 2022
Messages
67
Trophies
0
Location
Somewhere, Out there
XP
806
Country
United States
Thanks, can you explain what the difference is to an ASM novice like me?
Is it that you're setting RomPage to 0x8002? The ez3pda source and examples I linked to all use 0x8000. The Omega docs say kernel is at 0x8002.

My reset code definitely works on my DS Lite though - so is the hang you described only for EZ-Flash Omega?
The difference is mine is disables IME (Interrupt Master Enable 0x04000208). The hang must be Omega specific then, because that's what I was using at the time. Also, mine has a slightly larger literal pool (series of .BYTE statements which are just raw binary data)

IME controls whether or not Interrupt Requests (IRQ) are allowed by the software.
 

patters

Well-Known Member
OP
Member
Joined
Jan 28, 2006
Messages
172
Trophies
1
XP
892
Country
The difference is mine is disables IME (Interrupt Master Enable 0x04000208). The hang must be Omega specific then, because that's what I was using at the time. Also, mine has a slightly larger literal pool (series of .BYTE statements which are just raw binary data)

IME controls whether or not Interrupt Requests (IRQ) are allowed by the software.

Cool, I guess we have both reset drivers 'out there' now. May I upload yours to my repo with mine and the build script? If so I'll include the source with a credit to you.
 
Last edited by patters,

TechieSaru

Well-Known Member
Newcomer
Joined
Mar 2, 2022
Messages
67
Trophies
0
Location
Somewhere, Out there
XP
806
Country
United States
Actually, forget what I said about it hanging on the Omega. There must have been something wrong with the code at the time when I was working on it, because it has no issue at all. In general my code is lighter, faster, and easier to understand. I also updated my code in the post above.

The IME stuff was also irrelevant.

Why is it that things like this ALWAYS happen to me and make me sound like a fool? *sigh*

Do whatever you like. I have no objections. Also, thanks for the credit.
 

patters

Well-Known Member
OP
Member
Joined
Jan 28, 2006
Messages
172
Trophies
1
XP
892
Country
Actually, forget what I said about it hanging on the Omega. There must have been something wrong with the code at the time when I was working on it, because it has no issue at all. In general my code is lighter, faster, and easier to understand. I also updated my code in the post above.

The IME stuff was also irrelevant.

Why is it that things like this ALWAYS happen to me and make me sound like a fool? *sigh*

Do whatever you like. I have no objections. Also, thanks for the credit.
Yours is 4 bytes leaner :) I probably won't add it then if it's functionally identical. I'd rather keep mine in closer alignment with the ez3pda source code example from EZ Team.
 

TechieSaru

Well-Known Member
Newcomer
Joined
Mar 2, 2022
Messages
67
Trophies
0
Location
Somewhere, Out there
XP
806
Country
United States
Yours is 4 bytes leaner :) I probably won't add it then if it's functionally identical. I'd rather keep mine in closer alignment with the ez3pda source code example from EZ Team.
I updated my code. I updated the attachment as well (I was a little slow on this). It's actually 12 bytes lighter B-).

Edit: WTF. My edit must have been eaten earlier or something. The code is now updated.

Edit 2: I went ahead and removed my code since it won't be used. Oh well.
 
Last edited by TechieSaru,
  • Like
Reactions: patters

patters

Well-Known Member
OP
Member
Joined
Jan 28, 2006
Messages
172
Trophies
1
XP
892
Country
I updated my code. I updated the attachment as well (I was a little slow on this). It's actually 12 bytes lighter B-).

Edit: WTF. My edit must have been eaten earlier or something. The code is now updated.

Edit 2: I went ahead and removed my code since it won't be used. Oh well.
You should leave it here in case someone later finds a problem with mine. Remember - I don't have an Omega to test. Not sure why you'd delete it.

Based on your example ASM, I think I could optimize mine to the following which would be 92 bytes. Will test tonight.
Code:
add r0, pc, #0x2c
ldm    r0, {r1, r2, r3, r4, r5, r6, r7, r8, sb, sp}
strh   r7, [r1]              @ 0x9fe0000 = 0xd200
strh   r8, [r2]              @ 0x8000000 = 0x1500
strh   r7, [r3]              @ 0x8020000 = 0xd200
strh   r8, [r4]              @ 0x8040000 = 0x1500
strh   sb, [r5]              @ 0x9880000 = 0x8000
strh   r8, [r6]              @ 0x9fc0000 = 0x1500
mov    r1, #0
strh   r1, [sp]              @ 0x3fffffa = 0x0000
mov    r0, #0xfc
svc    #0x10000
svc    #0
.BYTE 0x00, 0x00, 0xfe, 0x09
.BYTE 0x00, 0x00, 0x00, 0x08
.BYTE 0x00, 0x00, 0x02, 0x08
.BYTE 0x00, 0x00, 0x04, 0x08
.BYTE 0x00, 0x00, 0x88, 0x09
.BYTE 0x00, 0x00, 0xfc, 0x09
.BYTE 0x00, 0xd2, 0x00, 0x00
.BYTE 0x00, 0x15, 0x00, 0x00
.BYTE 0x00, 0x80, 0x00, 0x00
.BYTE 0xfa, 0xff, 0xff, 0x3f

Some reset examples seem to write zero to 0x3fffffa just before the reset and some (yours included) seem to write zero to 0x3007ffa. Do you know what the difference is?

Kuwanger's EZ4 reset code contains the cryptic comment
#0x3FFFFFA (mirror of #0x3007FFA
Can they be used interchangeably?
 
Last edited by patters,

TechieSaru

Well-Known Member
Newcomer
Joined
Mar 2, 2022
Messages
67
Trophies
0
Location
Somewhere, Out there
XP
806
Country
United States
My code being more optimized was one of the things I pointed out.

The byte at 0x03007FFA is the reset bit that the bios checks.

Code:
03007FFA (Bios Soft Reset bit):

Destination:
0 - 0x08000000 (ROM)
1 - 0x02000000 (EXWRAM)

03007FFA and 03FFFFFA can indeed be used interchangeably because 03FFFFFA is a mirror, or in other words exactly the same address.

I just do it as a formality and also because I reset the stack pointer to the default (0x03007F00) which is just another formality.
 

patters

Well-Known Member
OP
Member
Joined
Jan 28, 2006
Messages
172
Trophies
1
XP
892
Country
I reset the stack pointer to the default (0x03007F00) which is just another formality.
Where in your code was sp being reset? Was there a newer version than this below?

Code:
add r0, pc, #0x34
ldm r0, {r1, r2, r3, r4, r5, r6, r7, r8, sb, sp}
strh r7, [r1]
strh r8, [r2]
strh r7, [r3]
strh r8, [r4]
strh sb, [r5]
strh r8, [r6]
mov r0, #0x4000000
mov r1, #0
strb r1, [r0, #0x208]
strb r1, [sp, #0xfa]
mov r0, #0xfc
svc #0x10000
svc #0
.BYTE 0x00, 0x00, 0xfe, 0x09
.BYTE 0x00, 0x00, 0x00, 0x08
.BYTE 0x00, 0x00, 0x02, 0x08
.BYTE 0x00, 0x00, 0x04, 0x08
.BYTE 0x00, 0x00, 0x88, 0x09
.BYTE 0x00, 0x00, 0xfc, 0x09
.BYTE 0x00, 0xd2, 0x00, 0x00
.BYTE 0x00, 0x15, 0x00, 0x00
.BYTE 0x02, 0x80, 0x00, 0x00
.BYTE 0x00, 0x7f, 0x00, 0x03

I think we should prob put them both in after all - i.e. have flash_ez4.sub using RomPage 0x8000 in line with all the established EZ4 examples, and your flash_ezo.sub using RomPage 0x8002 with that additional IME disable one for EZ-Flash Omega.
 

TechieSaru

Well-Known Member
Newcomer
Joined
Mar 2, 2022
Messages
67
Trophies
0
Location
Somewhere, Out there
XP
806
Country
United States
The IME is not needed. That was my mistake. I literally tested the code myself and It works perfectly fine on both devices.

Here is my updated code:
Code:
add r0, pc, #0x2c
ldm r0, {r1 - r9, sp}
strh r7, [r1]
strh r8, [r2]
strh r7, [r3]
strh r8, [r4]
strh r9, [r5]
strh r8, [r6]
mov r0, #0
strb r0, [sp, #0xfa]
mov r0, #0xfc
swi #0x10000
swi #0
.word 0x09FE0000
.word 0x08000000
.word 0x08020000
.word 0x08040000
.word 0x09880000
.word 0x09FC0000
.word 0x0000D200
.word 0x00001500
.word 0x00008002
.word 0x03007F00

I used a shorthand to include all of the registers from 1 through 9. I changed the "sb" register label to its more proper label of "r9". I also changed the "svc" labels to "swi" because on the GBA they are referred to as "Software Interrupts". I also changed the data type for the literals to "word"s so they are more legible than byte arrays.

The stack pointer reset is part of the "ldm" instruction. Note the "03007F00" literal at the end of the list. That gets loaded into the SP register.
 

patters

Well-Known Member
OP
Member
Joined
Jan 28, 2006
Messages
172
Trophies
1
XP
892
Country
Gotcha. I had wondered why you were doing the #03007F00 plus #0xFA. Very polished and much more readable too. My only doubt lies with the RomPage. All the examples I can find seem to use 0x8000 (including Goomba Color and Jagoomba). Do you think I should keep two versions of the function?
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
    SylverReZ @ SylverReZ: https://www.youtube.com/watch?v=fv6vlP2qSyo