Jump to content

Sky Editor: ROM Hack Projects


Recommended Posts

Most developers make programs that are either save editors or ROM editors. I am not most developers. I originally made Sky Editor to edit save files, but I have expanded beyond that. I'm making another thread since that one's more for the save editing feature (hence it's location in the Save R&D forum), and thise part's for ROM Editing.

If anyone here is familiar with Minecraft Forge, people can make mods for Minecraft. Each mod does some particular thing, from fixing a small glitch to adding giant networks. Mod packs, bring lots of these mods together to enhance the experience, usually through a common theme. Users can then add or remove mods to their liking. I thought, why not apply this to DS ROM editing? People can make mod packs for DS games that consist of multiple mods. These mods could be anything from swapping two music tracks to completely changing the balance of the game. If someone likes the new difficulty but doesn't want the music to change, they can simply disable the music mod. Or import a mod someone else made.

Introducing, ROM Hack Projects! Now you can edit a ROM as much as you like, then easily distribute a patcher, without distributing a bunch of copyrighted data.

Huge Screenshot:

 
2016-02-16.png

To make editing easier, I'm offloading details to Github.

Details & Tutorial

Download

Link to comment
Share on other sites

This is a great idea. The old way of ROM patching has become very unwieldy in the new age of ROMs with multiple levels of archived/compressed/encrypted directory structures. Forgive me for not digging deeper to answer these questions for myself, but how are you handling patching? Maybe you're already doing this, but I think the best way to accomplish it would be to dearchive/decompress/decrypt every constituent file in the ROM to it's logical end point (the raw data for one file) and apply patches using conventional delta methods to those files only. A "mod" could be a zipped collection of patch files in a file tree matching the original ROM along with MD5 hashes of the unmodified file for the sake of sanity checks before applying the patch. There could also be some type of config file detailing added/deleted files for the mods that go beyond edits to existing files.

Obviously you're going the game-specific route here, but I think a generic version of this without all the fancy game-specific features that could work on any decrypted 3DS ROM would be very well received.

EDIT: AFter another look though maybe I'm wrong about the game-specific part. Saw the screenshot and assumed with the sprites and whatnot that you were limiting it to the PMD games.

Link to comment
Share on other sites

A "mod" could be a zipped collection of patch files in a file tree matching the original ROM along with MD5 hashes of the unmodified file for the sake of sanity checks before applying the patch.

Interesting that you suggest this. That's almost exactly what a mod is: a zip file containing patches for each individual file in the ROM (minus the hashes, they aren't there yet). There's a mod.json which identifies which files are added, updated, renamed, or deleted. Files marked for updating are patched with a patch, the exact format of which is determined by the patch extension in the zip. By default, all patches are done with xdelta, but there's support for making custom patchers, so some changes are merge save. A specific example is PMD's language file. Multiple mods can safely change different parts, since I don't use xdelta for that. Instead, I update specific strings using a custom patch format. It's even smart enough to detect which region the source file and patch are, so editing applying a patch made with a European ROM will work on a US ROM. I don't have support for Japanese language files yet, but I might in the future if I can find where things diverge.

Obviously you're going the game-specific route here, but I think a generic version of this without all the fancy game-specific features that could work on any decrypted 3DS ROM would be very well received.

EDIT: AFter another look though maybe I'm wrong about the game-specific part. Saw the screenshot and assumed with the sprites and whatnot that you were limiting it to the PMD games.

It should work with any DS or 3DS ROM, but any game besides PMD: Explorers of Sky, Omega Ruby, or Alpha Sapphire will require the user to make edits using external programs. Well, even with Omega Ruby and Alpha Sapphire, I just supply the external program for those.

I am currently not doing any sort of input validation on the input ROM you give the patcher, although I probably should. An interesting side-effect of this can be seen when editing the results of the personality test in PMD: Explorers of Sky. The results are simply integers at specific offsets in overlay 13. When xdelta makes a patch for overlay 13, it works only for the same region game. However, when I specifically disable the checksum verification, it works perfectly for another region. It would probably be better for me to just write a custom patcher for overlay 13, and re-enable checksum verification, as this won't work in all cases, especially archives that may have different file sizes across regions. I also need to make Sky Editor detect when multiple mods both alter the same file. If there isn't a merge-safe patcher for that format available, the mods would no longer be compatible.

I'm planning on at least partially re-writing the ROM patcher included in the zips this generates, so I'll make sure it has better support for input verification. I might also be able to accept input from Braindump, and output Hans compatible files in the future.

Link to comment
Share on other sites

  • 4 weeks later...

Updated to alpha 4.0.0.14. This version lets you create ROM hack projects using a romfs/exefs made using braindump. Unfortunately, the ROM patcher doesn't export to hans compatible files yet. It is a planned feature, however.

To update, simply start up Sky Editor, and it will automatically update.

Link to comment
Share on other sites

Alright, so I fixed the crash error by giving the new update.

All I wanted to do was change the Vulpix starter to Ninetails and the partner to something else. ( Haven't decided)

But now it's giving me an output error

Or most of the time, it crashes/stops working, again.

Executing C: \Users\paper_000\AppData\Local\Apps\2.0\Data\1EK7WMA3.ETH\12RDR9GM.HRQ\skye..tion_2412c5da0eb810a1_0004.0000_b469bc202d09f380\Data\Plugins/ROM Editor\ndstool.exe -v -x "C: \Users\paper_000\AppData\Local\Apps\2.0\Data\1EK7WMA3.ETH\12RDR9GM.HRQ\skye..tion_2412c5da0eb810a1_0004.0000_b469bc202d09f380\Data\Plugins/SkyEditor\5e3c73df-a25d-4e16-a6cb-eb7864615f70.tmp" -9 "Visa's Adventures\BaseRom RawFiles/arm9.bin" -7 "Visa's Adventures\BaseRom RawFiles/arm7.bin" -y9 "Visa's Adventures\BaseRom RawFiles/y9.bin" -y7 "Visa's Adventures\BaseRom RawFiles/y7.bin" -d "Visa's Adventures\BaseRom RawFiles/data" -y "Visa's Adventures\BaseRom RawFiles/overlay" -t "Visa's Adventures\BaseRom RawFiles/banner.bin" -h "Visa's Adventures\BaseRom RawFiles/header.bin"

"C: \Users\paper_000\AppData\Local\Apps\2.0\Data\1EK7WMA3.ETH\12RDR9GM.HRQ\skye..tion_2412c5da0eb810a1_0004.0000_b469bc202d09f380\Data\Plugins/ROM Editor\ndstool.exe" finished running.

System.IO.DirectoryNotFoundException: Could not find a part of the path 'C: \Users\paper_000\AppData\Local\Apps\2.0\BDC0RXEQ.H9N\ODCBNLZX.4RN\skye..tion_2412c5da0eb810a1_0004.0000_b469bc202d09f380\Visa's Adventures\Mods\EditStarters\RawFiles\Overlay\overlay_0013.bin'.

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)

at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)

at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)

at System.IO.File.InternalReadAllBytes(String path, Boolean checkHost)

at System.IO.File.ReadAllBytes(String path)

at ROMEditor.FileFormats.Overlay13..ctor(String Filename)

at ROMEditor.Mods.SkyStarterMod.Initialize(Project CurrentProject)

at ROMEditor.Mods.GenericMod._Closure$__12-0._Lambda$__0()

at System.Threading.Tasks.Task.InnerInvoke()

at System.Threading.Tasks.Task.Execute()

--- End of stack trace from previous location where exception was thrown ---

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

at ROMEditor.Mods.GenericMod.VB$StateMachine_12_InitializeAsync.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

at ROMEditor.GenericNDSModProject.VB$StateMachine_17_NDSRomProject_FileAdded.MoveNext()

Edited by Amaai
Link to comment
Share on other sites

  • 3 weeks later...
I can't download your latest editor, because it comes up as malware.

It's probably your virus scanner being over protective of newly released programs. "This program is not commonly downloaded..."

I would say that it's perfectly safe and doesn't contain viruses (because there aren't any), but that's what everyone says, so it wouldn't mean anything.

Link to comment
Share on other sites

  • 1 month later...
  • 7 months later...

The github usage tutorial just says "make appropriate changes." This is clearly meant for people who actually have skills, which I do not - my bad. I'm trying to cut out the Run Away ability (god dammit, Eevee, I am NOT good enough to keep running after you/healing you!), but I don't know where the ability data is stored or what it would look like even if I knew where. Can you point me at somewhere that I could figure this out? Google's finding me nothing.

Oh, and I checked out your Sky Rom Editor from a while ago. It just opened the command line and immediately closed. Is this because they're now trying to run on Windows 10, or what?

Link to comment
Share on other sites

The github usage tutorial just says "make appropriate changes." This is clearly meant for people who actually have skills, which I do not - my bad.

Sorry about that. This tool is still in active development, and this release is sort of a proof-of-concept, although it should still work. Basically you create a project, and make changes related to what you want to do. If you're using the Generic Mod, you go to the project folder and edit files in the "Raw Files" folder using external tools.

I'm trying to cut out the Run Away ability (god dammit, Eevee, I am NOT good enough to keep running after you/healing you!), but I don't know where the ability data is stored or what it would look like even if I knew where. Can you point me at somewhere that I could figure this out? Google's finding me nothing.

You'll need to edit the monster.md file. If you don't want to use a hex editor, PPMD StatsUtil should be able to edit it.

Oh, and I checked out your Sky Rom Editor from a while ago. It just opened the command line and immediately closed. Is this because they're now trying to run on Windows 10, or what?

Which version? Do you mean Sky Editor 4 Beta 2?

Link to comment
Share on other sites

  • 1 year later...

Hello, I am new here and I don't know if this is the right place to post this, but I couldn't manage to find a better place to discuss the Sky Editor Rom Editor.

I am trying my hand at making a script/text mod for PSMD. For now, I've just been testing and getting accustomed to the editor. While editing messages and scripts is fairly straightforward, I haven't been successful at adding new messages. Any messages added with the "Add" button simply don't work, and they disappear from the message list if I save and reopen the file. As you can imagine, not being able to use more messages than there are in the original script, is quite limiting. Am I doing something wrong, or is adding messages just not functional yet?

I am using version 4.1.0.50 if that makes a difference.

Edit: I've discovered \EE00, and so I've been able to work around this problem for the most part.

Edited by Gemzo
Link to comment
Share on other sites

I've ran into another problem using the ROM Editor. Any of my changes to the script for the last part of chapter 1 (shinryokuclear1st.lua) are not present in-game. Other script edits prior to this point in the story have worked fine, but this script always remains vanilla for some reason. Even building with a totally empty script still has the cutscene proceed normally, besides the message edits.

Edit: I encountered the same issue when editing the second part of chapter 2 (nanikanokehai.lua). No script changes apply on build.

Edited by Gemzo
Link to comment
Share on other sites

Sorry for the late reply. This is one of the things where I have to sit down and investigate, and I have limited time through the week. (And I'm sad to say, I probably would have forgotten about your post if it wasn't for your PM. I'll try to do better.)

On 11/5/2017 at 10:59 AM, Gemzo said:

I am trying my hand at making a script/text mod for PSMD. For now, I've just been testing and getting accustomed to the editor. While editing messages and scripts is fairly straightforward, I haven't been successful at adding new messages. Any messages added with the "Add" button simply don't work, and they disappear from the message list if I save and reopen the file. As you can imagine, not being able to use more messages than there are in the original script, is quite limiting. Am I doing something wrong, or is adding messages just not functional yet?

I am using version 4.1.0.50 if that makes a difference.

Fixed in version 4.1.0.51. However, when building the mod, you'll need to use version 4.1.0.37 (or was it 4.1.0.36? It's been a while). Later versions have a problem when building ROMs that I haven't had time to fix yet, as it requires fixing nearly all of the dependencies. Believe it or not, one of the many things that needs to be updated is the save editor. I've been waiting for the save editor to be perfect before releasing it, but in all honesty, it's probably good enough for what the ROM editor needs it for. I have no ETA for when I can move forward and fix it, but I do plan to.

On 11/7/2017 at 4:27 AM, Gemzo said:

I've ran into another problem using the ROM Editor. Any of my changes to the script for the last part of chapter 1 (shinryokuclear1st.lua) are not present in-game. Other script edits prior to this point in the story have worked fine, but this script always remains vanilla for some reason. Even building with a totally empty script still has the cutscene proceed normally, besides the message edits.

Edit: I encountered the same issue when editing the second part of chapter 2 (nanikanokehai.lua). No script changes apply on build.

I've had a similar problem when there's a syntax error with my edits. There's currently no real error checking when compiling scripts, so try compiling the script manually to see if Lua gives any errors. The Lua compiler can be found at SkyEditor.ROMEditor.Windows/lua/luac5.1.exe in the zip file. Try using command prompt to launch luac.exe -o <output> <script>, where <script> is the script you're editing, and <output> is some temporary path to save the script. Don't forget to put paths in quotation marks if they contain spaces.

  • V-Wheeeeeel!!! 1
Link to comment
Share on other sites

On 11/10/2017 at 5:37 PM, evandixon said:

Sorry for the late reply. This is one of the things where I have to sit down and investigate, and I have limited time through the week. (And I'm sad to say, I probably would have forgotten about your post if it wasn't for your PM. I'll try to do better.)

Fixed in version 4.1.0.51. However, when building the mod, you'll need to use version 4.1.0.37 (or was it 4.1.0.36? It's been a while). Later versions have a problem when building ROMs that I haven't had time to fix yet, as it requires fixing nearly all of the dependencies. Believe it or not, one of the many things that needs to be updated is the save editor. I've been waiting for the save editor to be perfect before releasing it, but in all honesty, it's probably good enough for what the ROM editor needs it for. I have no ETA for when I can move forward and fix it, but I do plan to.

No worries! I was fully expecting the ROM editor to be on the back burner. You seem to have quite a lot on your plate, after all. I'm happy just to get information about the ROM editor and my issues; I wasn't expecting a fix! So thank you for finding the time to respond, and for going the extra mile on that one.

On 11/10/2017 at 5:37 PM, evandixon said:

I've had a similar problem when there's a syntax error with my edits. There's currently no real error checking when compiling scripts, so try compiling the script manually to see if Lua gives any errors. The Lua compiler can be found at SkyEditor.ROMEditor.Windows/lua/luac5.1.exe in the zip file. Try using command prompt to launch luac.exe -o <output> <script>, where <script> is the script you're editing, and <output> is some temporary path to save the script. Don't forget to put paths in quotation marks if they contain spaces.

I don't know if I should feel stupid, or relieved. I've been banging my head into this issue to no avail, and of course the problem is just a rogue  )  floating around. But on the other hand, it's something actually I can actually fix myself, so I'm happy for that! It might have been as simple as uttering the words "syntax error," but you've helped me a great deal by doing so. Thank you!
 

Unrelated: Since I've had trouble finding info while editing PSMD scripts, I'm going to leave a nugget of information for others to find.
You can use these lines to change the partner's gender. This comes in handy when you want to test both the cool and cute versions of a scene without a second save file.

SYSTEM:SetPartnerSex(SEX.MALE)
SYSTEM:SetPartnerSex(SEX.FEMALE)

Now, that's useful for testing instances of WINDOW:SwitchTalk, but I wanted to do more gender-unique changes to the cutscenes. So I would need a way to check the partner's current gender... I wasn't expecting to find anything, but opening up ExeFS/code.bin and searching through the gibberish did turn up an instance of "SetPartnerSex" and right next to it was "IsPartnerFemale"... But, trying to check if SYSTEM:IsPartnerFemale == true just gave me a syntax error. Perhaps there's a correct way to use that, or maybe it's just a nonfunctional thing.

Edit: Proving I really don't know what I'm doing, it was as simple as putting a '()' after it. Now I can do everything I wanted to!

if SYSTEM:IsPartnerFemale() then
  cute partner stuff
else
  cool partner stuff
end

 

Edited by Gemzo
  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...
On 11/10/2017 at 7:37 PM, evandixon said:

Fixed in version 4.1.0.51. However, when building the mod, you'll need to use version 4.1.0.37 (or was it 4.1.0.36? It's been a while). Later versions have a problem when building ROMs that I haven't had time to fix yet, as it requires fixing nearly all of the dependencies. Believe it or not, one of the many things that needs to be updated is the save editor. I've been waiting for the save editor to be perfect before releasing it, but in all honesty, it's probably good enough for what the ROM editor needs it for. I have no ETA for when I can move forward and fix it, but I do plan to.

I finally got around to fixing this. See the blog post for the download link.

This should make it easier to do ROM editing, @Gemzo. Thanks for your interest in the project!

  • V-Wheeeeeel!!! 1
Link to comment
Share on other sites

8 hours ago, evandixon said:

I finally got around to fixing this. See the blog post for the download link.

This should make it easier to do ROM editing, @Gemzo. Thanks for your interest in the project!

Awesome! Not having to fiddle with getting the thing to build successfully every time certainly helps a lot.

However... I still can't get the add button to work. The added message still shows a blank dialogue window ingame, and the message still disappears from the list upon reopening the script. Saving and then reopening the editor results in added messages starting at ID 1 again, with no text leftover from previous attempts at adding that message ID.

Also, a few times during testing I had it hang for a while and then crash after clicking the add button, but I couldn't figure out how to reproduce it reliably.
This is the log it gave me: https://pastebin.com/ddxDhUik

Semi-related: Using script sort with short message IDs (1, 2, 3, etc, like the ones the add button creates) didn't seem to behave nicely. Every instance of the ID number in the script is put in the list, even if it's part of another ID. For example, message ID -11473915 being present would make message ID 1 show up 3 extra times when using script sort. Longer scripts that use a lot of messages turn into a huge mess due to this. Or, well, it would be a huge mess, if I could get adding messages to work.

Link to comment
Share on other sites

On 11/22/2017 at 7:14 PM, Gemzo said:

However... I still can't get the add button to work. The added message still shows a blank dialogue window ingame, and the message still disappears from the list upon reopening the script. Saving and then reopening the editor results in added messages starting at ID 1 again, with no text leftover from previous attempts at adding that message ID.

It turns out that after I fixed this the first time, I forgot to actually push the change. Sorry about that. Pushed it for real this time. I double-checked the changes in Team City and everything.

On 11/22/2017 at 7:14 PM, Gemzo said:

Also, a few times during testing I had it hang for a while and then crash after clicking the add button, but I couldn't figure out how to reproduce it reliably.
This is the log it gave me: https://pastebin.com/ddxDhUik

Fixed. Both changes should be in this build.

On 11/22/2017 at 7:14 PM, Gemzo said:

Semi-related: Using script sort with short message IDs (1, 2, 3, etc, like the ones the add button creates) didn't seem to behave nicely. Every instance of the ID number in the script is put in the list, even if it's part of another ID. For example, message ID -11473915 being present would make message ID 1 show up 3 extra times when using script sort. Longer scripts that use a lot of messages turn into a huge mess due to this. Or, well, it would be a huge mess, if I could get adding messages to work.

It should be using the full number for the sorting. Could there be some other single 1's in the script?

  • V-Wheeeeeel!!! 1
Link to comment
Share on other sites

5 hours ago, evandixon said:

It turns out that after I fixed this the first time, I forgot to actually push the change. Sorry about that. Pushed it for real this time. I double-checked the changes in Team City and everything.

Fixed. Both changes should be in this build.

Phew, I was worried it was something on my end. It definitely works now, thanks!

5 hours ago, evandixon said:

It should be using the full number for the sorting. Could there be some other single 1's in the script?

You're right, I was making an assumption when I thought it was the other message IDs. I dunno why I was so convinced of that, really.

Anyway, the issue. Within the code below, seven instances of message ID 0 show up before -831791279 while using script sort. There are five instances of decimals that technically have "lone" 0's (if script sort ignores the decimal point), but I'm not sure where the other two would come from in that case, as all other instances of 0 are not lone numbers.

This issue isn't the biggest deal in the world, as it will not happen nearly as much after you get done editing the scripts that use single digit message IDs... But, if you're using all ten of those message IDs in an already long script, then script sort will be pretty unusable for that script.

dofile("script/include/inc_all.lua")
dofile("script/include/inc_event.lua")
function groundInit()
end
function groundStart()
end
function main02_partnertonodeai01_init()
end
function main02_partnertonodeai01_start()
  CAMERA:SetSisaAzimuthDifferenceVolume(Volume(3))
  CAMERA:SetSisaRateVolume(Volume(0.5))
  CAMERA:SetEye(SymCam("CAMERA_00"))
  CAMERA:SetTgt(SymCam("CAMERA_00"))
  CH("HERO"):WalkTo(SymPos("P01_HERO"), Speed(1.5))
  SOUND:FadeInEnv(SymSnd("SE_ENV_CROSSROAD_LP"), TimeSec(0.5), Volume(256))
  SCREEN_A:FadeIn(TimeSec(0.5), true)
  CH("HERO"):WaitMove()
  CAMERA:SetEye(SymCam("CAMERA_01"))
  CAMERA:SetTgt(SymCam("CAMERA_01"))
  TASK:Sleep(TimeSec(0.3))
  CH("HERO"):SetMotion(SymMot("EV001_CONFIRMS"), LOOP.OFF)
  TASK:Sleep(TimeSec(0.2))
  CH("HERO"):WaitPlayMotion()
  CH("HERO"):SetMotion(SymMot("WAIT02"), LOOP.ON)
  WINDOW:DrawFace(324, 88, SymAct("HERO"), FACE_TYPE.SPECIAL02)
  WINDOW:Monologue(-831791279)

 

Link to comment
Share on other sites

On 11/25/2017 at 9:52 PM, Gemzo said:

You're right, I was making an assumption when I thought it was the other message IDs. I dunno why I was so convinced of that, really.

Anyway, the issue. Within the code below, seven instances of message ID 0 show up before -831791279 while using script sort. There are five instances of decimals that technically have "lone" 0's (if script sort ignores the decimal point), but I'm not sure where the other two would come from in that case, as all other instances of 0 are not lone numbers.

This issue isn't the biggest deal in the world, as it will not happen nearly as much after you get done editing the scripts that use single digit message IDs... But, if you're using all ten of those message IDs in an already long script, then script sort will be pretty unusable for that script.


dofile("script/include/inc_all.lua")
dofile("script/include/inc_event.lua")
function groundInit()
end
function groundStart()
end
function main02_partnertonodeai01_init()
end
function main02_partnertonodeai01_start()
  CAMERA:SetSisaAzimuthDifferenceVolume(Volume(3))
  CAMERA:SetSisaRateVolume(Volume(0.5))
  CAMERA:SetEye(SymCam("CAMERA_00"))
  CAMERA:SetTgt(SymCam("CAMERA_00"))
  CH("HERO"):WalkTo(SymPos("P01_HERO"), Speed(1.5))
  SOUND:FadeInEnv(SymSnd("SE_ENV_CROSSROAD_LP"), TimeSec(0.5), Volume(256))
  SCREEN_A:FadeIn(TimeSec(0.5), true)
  CH("HERO"):WaitMove()
  CAMERA:SetEye(SymCam("CAMERA_01"))
  CAMERA:SetTgt(SymCam("CAMERA_01"))
  TASK:Sleep(TimeSec(0.3))
  CH("HERO"):SetMotion(SymMot("EV001_CONFIRMS"), LOOP.OFF)
  TASK:Sleep(TimeSec(0.2))
  CH("HERO"):WaitPlayMotion()
  CH("HERO"):SetMotion(SymMot("WAIT02"), LOOP.ON)
  WINDOW:DrawFace(324, 88, SymAct("HERO"), FACE_TYPE.SPECIAL02)
  WINDOW:Monologue(-831791279)

 

Fixed in the latest build. It might still show short IDs out of order though.

  • Like 1
  • V-Wheeeeeel!!! 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...