don't click here

Modifying Sonic and Gens to end after an Act is complete.

Discussion in 'Engineering & Reverse Engineering' started by ShadowDog, Oct 4, 2009.

Thread Status:
Not open for further replies.
  1. ShadowDog

    ShadowDog

    Member
    I was wondering weather to put this in technical discussion or here. Move this if you need to (though please PM me so I'm not confused).

    Basically, what I wanted to do was have an RPG, but rather than having standard RPG battles, you complete an Act. I suppose it wouldn't be too difficult to start Sonic 1 ingame, and to reorder the level progression so that the first Act listed in the list is the one started (I have 149 Gigabytes on my external harddrive. 20 or so different ROMs is of no concern to me ;D). However, I wanted to know if it was possible to have Gens write 0 or 1 to a file (let's say Results.txt) and exit when you lose all your lives (0) or beat the Act (1). I was thinking about changing 2 invalid opcodes to write 0/1 and exit. Then I'd call those opcodes in the DisASM when needed.

    3 things:
    1.) What is Gens compiled in? I couldn't get it to compile in Visual Studio 2005. Would Visual Studio 6 work?
    2.) Where is Gens are the opcodes (and, if it's not immedeatly obvious, how wouls I add 2 new ones?)
    3.) How would I call a raw opcode in the Sonic 1 DisASM? I'm using the SVN build. What's the format? I hope they aren't completely inaccessible.
     
  2. JoseTB

    JoseTB

    Tech Member
    716
    59
    28
    By any chance, did you consider using the SRAM? :P

    Edit: Okay, you won't be able to make Gens or any emulator exit without modifications but I think it's worth to look for an alternative on whatever you want to do.
     
  3. Cinossu

    Cinossu

    Administrator
    2,832
    44
    28
    London, UK
    Sonic the Hedgehog Extended Edition
    It would probably be possible with something like Gens/GS with its plugin support (once Gerbil finishes it), but you'd have to write all the handling of it yourself for that.. plus it means you're limited to just using that one emulator, and it most certainly won't work on real hardware.
     
  4. ShadowDog

    ShadowDog

    Member
    I'd use Kega Fusion, but it's not open source, so I can't put in new opcodes without doing some pd/YR style ASM hacking of the Kega executable. Since Gens is open source, I decided to use that. As I'm using the Acts as a replacement for RPG battles in my Sonic RPG, I don't really care about it working on real hardware.

    Anyway, what should I use to compile Gens?

    EDIT: I still don't know, but I remembered to end questions with a question mark. Thus the term "question mark". ;D
     
  5. Alriightyman

    Alriightyman

    I am back... from the dead! Tech Member
    357
    11
    18
    Somewhere in hot, death Florida
    0101001101101111011011100110100101100011 00000010: 0101001100000011 01000101011001000110100101110100011010010110111101101110
    I believe Gens is coded in C++. So I would assume any C++ compiler should work.
     
  6. ShadowDog

    ShadowDog

    Member
    That's what I thought to. Nearly had an ameurism getting it to compile in VS2005. I actually found one of the files I needed in my VS6 install. Of course, it would have been a lot easier if I had VC7.

    POINT IS: I got the blasted thing to compile. I gutted the NetPlay, ConsoleClassix, and (probably) screwed up the Game Genie code, but it works now. Though the changing from 32-bit mode to 32-bit mode doesn't quite make sense to me. That, or it starts in fullscreen then goes to a window. I don't quite know. Again, I use Kega. I've managed to modify the emulator's menus so that you can't select a file or load a savestate (the main game will boot up the emulator and rom when needed. I swear I would have gone insane if it turned out you couldn't specify the file to open in Gens via the command line).

    The current problem: First, I'm not able to type very well at the moment due to my mental exhaustion (I don't know how the people who write these things don't go insane). Second, tomarow's a school day. Third, and [/offtopic], I can't figure out where the opcodes are. It's not that I don't have hunches, it's just I don't know much about Gens' inner workings or 68k ASM.

    SH2.c has an opcode table. I need some help with this. My idea is to make 2 copies of nop, and change their affects. The first part of that would be to figure out why nop is filled out in that table the way it is:
    Code (Text):
    1.     { IFMT_0,   0x0009, SH2I_NOP      },
    later in the same file:
    Code (Text):
    1.     { IFMT_0,   0x0009, SH2I_NOP_DS      },
    In SH2.h (listing this particular one mainly for my own purposes):
    Code (Text):
    1. void SH2I_NOP();
    Later:
    Code (Text):
    1. void SH2I_NOP_DS();
    SH2a.asm:
    Code (Text):
    1. ALIGN32
    2.  
    3. DECLF SH2I_NOP
    4.  
    5.     RET 1, 1, 1
    Later:
    Code (ASM):
    1. DECLF SH2I_NOP_DS
    2.  
    3.     RET_DS 1, 1, 1
    Apparently, _DS means delay slot:
    Code (Text):
    1. // Delay-slot instruction function definition
    What is a delay slot or whatever?

    Let me get this straight: SH2.h is predefining the ASM functions in SH2a.asm? Crazy.

    So I want to know the following:
    First, take this:
    Code (Text):
    1.     { IFMT_0,   0x0009, SH2I_NOP      },
    What is IFMT_0?
    Why does it use 0x0009? Is it like the raw opcode or something? If I were to put this in place of nop in the Sonic 1 disasm, would it work as nop or would the compiler explode?
    SH2I_NOP is the name of a procedure. Is it calling the procedure or a constant?

    And in this:
    Code (Text):
    1. ALIGN32
    2.  
    3. DECLF SH2I_NOP
    4.  
    5.     RET 1, 1, 1
    I saw a lot of things going RET 1, 1, 1. If I'm just exiting Gens, does this really matter?

    Finally, how would I go about accessing Gens from these Opcodes? I saw a lot of references to ebp, and I think that's where the Genesis's memory starts. Could I use a C procedure instead of an ASM procedure and just tell Gens to exit?

    Thanks in advance.

    P.S. Gens appears to be coded in C and ASM. Might be C++, not sure.

    EDIT: Is there anyway to get the SVN's default assembler to recognize 0xED00 and 0xED01 as valid opcodes. I was lucky enough to figure out it knows they're opcodes, but not what kind. They take no arguments, by the way. I can't really test if my idea's working until someone does this.

    Actually, it seems it's 78 and 79. Lol. Talk to you guys later.

    Update: I haven't got it to write to a file, but I got Gens to recognize 78 and 79 as opcodes. To verify this, I used nop and rts in the same places in my ASM hack, and compared where they were. I replaced 71 (nop) with 78 (my 1st custom opcode). In my modified Gens, it does nothing unusual after you hit the spikes (where the opcode is), but in Kega, it screws up completely. Unless Gens by default handles invalid opcodes more gracefully, then that is proof my opcode at least doesb't break the world in half. But I really need a 68k assembler with support for opcodes 78 and 79 (win and lose, maybe?)
     
  7. Dr. Kylstein

    Dr. Kylstein

    Member
    86
    0
    6
    Inventing new opcodes just to control the emulator... :psyduck: Can't you just make Gens monitor a particular location in the emulated RAM?
     
  8. Aquaslash

    Aquaslash

    <The Has-been Legend> Moderator
    Can I just say that this sounds like a horrible game breaking idea? No really, what possible benefit could you get to ending the program upon act completion? Talk about discouraging replay.
     
  9. x64

    x64

    clicked the [x] button Banned
    92
    1
    0
    Vernal Equinox
    I'm working on your mom.
    You don't need to modify gens at all to make this work. All you need to do is save the value to SRAM, and while the emulator is running, have your program run in a tight loop of monitoring the filename where the SRAM would be saved to see if it's been modified. (or you can use filesystem notification if you're leet), and once the SRAM file is modified, you can read the value and kill the gens.exe process.

    That's what I'd do.
     
  10. Animemaster

    Animemaster

    Prison bitch! Member
    346
    0
    0
    UK
    Sonic 1 Revelation
    You said you are creating an rpg, so why don't you use and rpg maker program instead?.
     
  11. ShadowDog

    ShadowDog

    Member
    That requires more knowledge of Gens than I will probably ever have and I could potentially use these opcodes whenever I want.

    Because I'm using them inplace of battles in my "RPG" (at this point, it really stopped being an RPG). The whole point is that there's only 1 level.

    I'm not leet enough to do any of that.

    My project sort of shifted in focus. I was thinking of using a modified version of my own battle system, but eventually decided to have the classic platforming segments instead of RPG battles.
    Also, RPG Maker crashes my system.

    Now for the progress update. I've got to where I can run C++ code in those two opcodes. The problem is none of the procedures I call seem to be in scope or whatever it's called. I will update later.
     
  12. SMTP

    SMTP

    Tech Member
    X64's idea seems the easiest really...

    Adding Sram to the game is simple, basicly all you need to do is monitor the file....
     
  13. ShadowDog

    ShadowDog

    Member
    Wait, wasn't SRAM the stuff games use to save the game?

    Anyway, could someone help me? I'm in main68kgen.c, and I can't figure our how to call any procedures. I'm, oddly enough, better at ASM than C. Which means I have no clue how to get Gens to close. If someone could look through the source for me and see what code you'd have use to exit Gens, that would be great. I'm pretty sure I can get the file stuff to work (my main program deletes the file after loading it, so it will always create a new file. Wait, didn't a new file being made require some more code or something? Urgh, forgot about that for a moment.) Anyway, if you want to help, paste this under i_nop(void). It doesn't have to be a valid opcode, it just needs to compile. If it compiles, you've figured it out.
    Code (Text):
    1. static void i_custom1(void)
    2. {    //BOOKMARK
    3. //    Open results.txt
    4. //    Append "1" to file
    5. //    Close file
    6. //    Exit
    7.     ret_timing(4);
    8. }
    Thanks in advance.

    EDIT: Rereading x64's idea, that actually does seem like a good idea. I'll look into it.
     
Thread Status:
Not open for further replies.