|
Post by Jason777 on May 3, 2012 23:09:35 GMT -5
Hot damn this is sounding/looking amazing.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 3, 2012 23:46:23 GMT -5
Glad to see you're excited! ;D
It took a little longer to figure out how to hook PJ64's functions than I had wished, but after testing about 5 or 6 methods I've finished writing the namespace for the HookInstaller:
/* HookInstaller.h - Visual C++ Header for DLL and Process injection * @author: SoulofDeity * * The comments in this file are formatted to appear neatly in the MSVC tooltips * when you hover the mouse above them. */ #include <Windows.h> #include <tchar.h> #include <Psapi.h> #include <tlhelp32.h>
/* The name of the dll we're going to inject into the process. */ /* Make sure you end it with \0 */ #define HI_DLLNAME "snagContext.dll\0" #define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
/* This is the stub that is injected into the process by the */ /* ProcessHook class to call our functions. */ #pragma unmanaged DWORD WINAPI HI_STUB(LPVOID lpParameter) { __asm { mov eax, [lpParameter] call eax push 0 call ExitThread } return 0; }
DWORD WINAPI HI_LOCALSTUB(LPVOID lpParameter) { __try { __asm { mov eax, [lpParameter] call eax push 0 call ExitThread } } __except(EXCEPTION_EXECUTE_HANDLER) { } return 0; } #pragma managed
/* */ /* This is the namespace for SoulofDeity's DLL and Process injections. */ /* */ /* It consists of 2 classes: */ /* > hi_Process - A container for process info. */ /* > ShellCodeHook - API for Process Injections */ namespace HookInstaller {
/* */ /* This is a class used by the ProcessHook class to inject code */ /* into a running process.*/ public ref class hi_Process { public: DWORD id; // Process ID System::String^ name; // Process Name };
/* */ /* Class containing functions for injecting code into a process. */ public ref class ShellCodeHook { public: ShellCodeHook() {} // No initialization needed private: ~ShellCodeHook() {} // No Destructor needed public:
/* */ /* This function gets the name of a process by it's id. */ System::String^ getProcessName(DWORD id) { System::String^ name; if (id == 0) return name; TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>"); HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, id); if (handle == NULL) return name; HMODULE hMod; DWORD cbNeeded; if (EnumProcessModules(handle, &hMod, sizeof(hMod), &cbNeeded)) GetModuleBaseName(handle, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR)); CloseHandle(handle); name = gcnew System::String(szProcessName); return name; }
/* */ /* Builds a hi_Process array of the current running processes in Windows. */ /* */ /* Example Usage: */ /* > array<hi_Process^>^ processes = enumProcesses(); */ /* > if (processes->Length != 0) { */ /* > MessageBox::Show(process[0]->name, "Name of process 0", MessageBoxButtons::OK); */ /* > } */ /* */ /* Note that not all processes have names, in which case they will be */ /* labelled as <unknown>. */ array<hi_Process^>^ enumProcesses() { array<hi_Process^>^ process = gcnew array<hi_Process^>(0); DWORD aProcesses[1024], cbNeeded, cProcesses; if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) return process; cProcesses = cbNeeded / sizeof(DWORD); for (unsigned int i=0; i<cProcesses; i++) { TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>"); if (aProcesses[i] != 0) { hi_Process^ proc = gcnew hi_Process(); proc->id = aProcesses[i]; proc->name = getProcessName(proc->id); System::Array::Resize(process, process->Length+1); process[process->Length-1] = proc; } } return process; }
/* */ /* Installs the process hook. */ /* */ /* Note that argument supplied here is the id of the process, not a */ /* hi_Process class. */ /* Returns true if installation was successful. */ bool installHook(DWORD id) { int tid; void* RemoteString; void* RemoteStub; unsigned long oldprot; if (!id) return false; HANDLE Proc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, id); if (!Proc) return false; RemoteString = VirtualAllocEx(Proc, NULL, (strlen(HI_DLLNAME)+1), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (RemoteString == NULL) { CloseHandle(Proc); return false; } if (!WriteProcessMemory(Proc, RemoteString, HI_DLLNAME, strlen(HI_DLLNAME), NULL)) { CloseHandle(Proc); return false; } RemoteStub = VirtualAllocEx(Proc, NULL, 32, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (RemoteStub == NULL) { CloseHandle(Proc); return false; } VirtualProtect(HI_STUB, 32, PAGE_EXECUTE_READWRITE, &oldprot); if (!WriteProcessMemory(Proc, RemoteStub, HI_STUB, 32, NULL)) { CloseHandle(Proc); return false; } HANDLE RemoteThread = CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)RemoteStub, (LPVOID)RemoteString, NULL, NULL); CloseHandle(Proc); if (RemoteThread == NULL) return false; void* StringPtr = VirtualAlloc(NULL, (strlen(HI_DLLNAME)+1), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); strncpy((char*)StringPtr, HI_DLLNAME, strlen(HI_DLLNAME)); HANDLE LocalThread = CreateThread(NULL, 0, HI_LOCALSTUB, StringPtr, 0, (LPDWORD)&tid); WaitForSingleObject(LocalThread, INFINITE); return true; } }; }
Whatcha think?
EDIT:
I just realized while I was reviewing the post that the comments mention a class called ProcessHook. When I started writing this header, I had intended to implement 2 methods involving DLL injection and shell code injection called DLLHook and ProcessHook. The implementation of DLLHook was dropped and the name of the ProcessHook class was changed to ShellCodeHook.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 4, 2012 3:56:14 GMT -5
I took a break from the process injection ordeal to improve the filesystem editor a bit more. * Added a field for the address of the end of the file * Added support for exporting files that have no name in the "start - end.ext" format (like ZRE exports them) * Status bar displays the number of files extracted out of the number of files selected for extraction while exporting and progress bar updates to show the progress. * Status bar now displays a message when the rom is loading * Files can now be extracted via both the toolbar and a context menu * File replacement has been added, this currently only works if the replacement file is the same size since filetable recalculation has yet to be added.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 7, 2012 11:56:04 GMT -5
When it's finally released, it'll be open source. I've been a bit occupied the last couple of days and haven't had much time to work on HC, but I contacted Zeth on youtube last night to see if he can lend me some of his knowledge of the not-so-well known methods of hacking. Such as adding/removing cutscenes, skipping the game intro, rewriting the main menu to detect savegame changes, LZ filesystem adding, creating custom actors, etc. I actually got a bit hyped up seeing how Zelda URA looks
|
|
|
Post by Jason777 on May 7, 2012 12:55:17 GMT -5
I can help with the creation of a general template for a custom actor. If you need an example to go off, I'll send you a basic one I created about a month ago when I was learning how to create them myself (of course, it works). The source code is littered with comments. For cutscenes, you may want to contact DeathBasket. Also, mzxrules would be the guy to ask about Zelda 64's gamesave, however, there is an article on the Z64 Wiki about gamesaves.
|
|
|
Post by Arcaith on May 7, 2012 13:26:43 GMT -5
If you're adding support for file formats, consider plain text .x format. It supports a lot more things than .obj, like vertex colour/alpha.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 7, 2012 15:02:35 GMT -5
Jason777: cool, that template would be very useful! Arcaith: I'm currently adding support for .obj, .smd, and .blend. I'm not really familiar with .x, but I'll see what I can do. Here's the latest addition to HC, the Patch Manager. * Supports the creation of ppf patches with and without unpatching data * Supports the ability to apply and unapply multiple patches at once The patches in the list are generated from the ppf files in a directory called 'patches'. Pretty simple to use, you just check the names of the patches you want to apply or unapply and click "Create / Apply" or "Unpatch". I couldn't find documentation for the ppf file format, so HC uses applyppf and makeppf from PPF-Studio in the subdirectory "tools". They're run in the background, so no annoying command prompts pop up when you create or apply patches. EDIT: Just added some stuff to the patch manager: * Added arguments to the patch manager form so the original and modified rom fields are automatically filled out. * Added a '*' button next to the modified rom input's 'browse' button. When clicked, the name of the currently open rom is put in the field. * Added smart-correct for the patch name. If you type something in the patch name field instead of using the "Save As" button, HC will automatically add a .ppf extension (if an extension isn't already supplied), and set the path to .\patches\ if you don't supply a path. For example, if you type 'test' HC will change it to '.\patches\test.ppf' * Added context menu for patch list to refresh the list Update: My code was getting really messy, so I've spent the last few hours rewriting it in the form of classes and namespaces. Everything's a lot cleaner now, but there appears to be a 2,000 KB memory leak every time you change roms :/ Anyway, once I hunt this down I'll work on model loading.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 8, 2012 19:17:35 GMT -5
Update: * Just added feature to load file names from an external file. The file name is the internal name of the game followed by the country / game / language code separated by ' - ' with the .fnl extension (meaning File Name List). For example, when you load the OoT Debug Rom, it will load the names from a file called 'THE LEGEND OF ZELDA - CZLE.fnl". Loading these names externally not only allows the use of custom filenames, but also makes loading time faster. If the file doesn't exist, the list is generated from the internal name table (if it exists). * Just added the file renaming feature. If you look in one of the previously shown pics, you'll see there's an input field with a blue letter icon to the right of it. To rename a file, you select the name in the list, type the name in the input field, then click the button. The new name will be saved in the .fnl file so every time you open that rom, the new name will be shown. NOTE: This also works with the MM and OoT 1.0 roms which don't have file names. Being able to create and exchange .fnl files will make hacking those games much easier. * Just added file search by name. If you look in one of the previously shown pics, you'll see there's an input field with a magnifying glass icon to the right of it. You type something in the input field and click the icon to search for any files containing that text in their name. The result is highlighted and scrolled to. If a file is selected before the search, the search will continue from that point, meaning you can keep finding the next result by clicking the icon. If no files are selected, than it just searches for the first file containing that text in it's name. Yet another innovation to make life easier for Zelda hackers! ^_^ * Simple knick-knack, you can also just hit enter when searching for renaming files instead of clicking their respective buttons. (I suppress the enter key so it doesn't 'twang') * Forgot to mention, earlier today I added support for decompressing Yaz0 compressed files when extracting. * Added a new utility, the Rom Properties: You can put whatever you want in the Internal Name and ID fields, the manufacturer and country can be selected from their respective droplists. (the only listed manufacturer is Nintendo, country's included are USA, Germany, Japan, Europe, Australia) Note that HC uses the internal name and id to determine the name of the file to load the file name list from. Lastly, the green check icon only appears if the CRC is correct. If it's incorrect, it will be a red error icon. If you click it, it will correct the CRC checksum of the rom. Changes aren't applied unless you click 'OK' * Boring stuff, added an about dialog. The build version and notes are loaded from common.h, so build extending upon HC can add their names to HC_NOTES. * Boring stuff, created a compiled help file (.chm) for Hylian Cartographer in HTML Workshop and set the "Help Contents" button to open it -------------------------------------------- >.> I know I keep putting off graphics stuff saying 'I'll do it next', I just loaaaath doing it. There's so much work involved and after not doing any Zelda hacking for a year, I'm not familiar or comfortable with the structure of ZOBJ / ZMAP / ZSCENE files anymore. I might just end up doing everything else first at this rate...
|
|
|
Post by Jason777 on May 9, 2012 20:22:57 GMT -5
Sorry, for taking so long to reply-- I have finals this week. I'll be taking my last final tomorrow so I'll probably be sending you the custom actor and its spawn function (a GS code written in C) tomorrow or Friday at the latest; I'm adding a little bit more to the actor so you have more things to take note of (usage of variables, maybe rendering a shadow, switching models on the fly, and text display).
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 9, 2012 22:51:35 GMT -5
awesome, can't wait to get my cold...feely hands on that actor! Btw, I just had an idea: since files are loaded to ram and gs codes only apply to ram, it may be possible to permanently apply static gs codes (meaning ones that don't need to be constantly re-applied like infinite ammo) by comparing their locations with the virtual addresses of the files, converting them into physical addresses, and then applying them to the rom. Just a theory, but if it works I'll add a GS Code Patcher to HC.
|
|
|
Post by Jason777 on May 10, 2012 6:59:25 GMT -5
awesome, can't wait to get my cold...feely hands on that actor! Btw, I just had an idea: since files are loaded to ram and gs codes only apply to ram, it may be possible to permanently apply static gs codes (meaning ones that don't need to be constantly re-applied like infinite ammo) by comparing their locations with the virtual addresses of the files, converting them into physical addresses, and then applying them to the rom. Just a theory, but if it works I'll add a GS Code Patcher to HC. There are certain files which are always transferred to the same area of RAM. So, technically, any GS codes which modify areas of RAM that happen to be located within that file can be patched quite easily. For example, CODE.zdata (or CODE.zasm) is always loaded into the same area of RAM: wiki.spinout182.com/w/Code_notesOther ways to patch codes would be to look for the raw representation (opcodes in their hexidecimal form) which precede a certain RAM address and search for any occurences in the ROM.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 10, 2012 15:13:36 GMT -5
Oh cool, I figured out something that was already figured out Guess that means I could just go ahead and throw it in.
|
|
|
Post by Jason777 on May 10, 2012 18:37:56 GMT -5
You really are taking on quite a bit of work, soulofdeity But it will be greatly appreciated and not in vain! Alright, I just decided to throw everything in together... so basically, the download contains alot of C hacks and a few little personal notes. Disclaimer: not everything in the download works; for example, ovl_en_PZGD_mask doesn't work properly and neither does Sword_of_Sages. The folder that you are interested in is "ovl_en_example", I decided to just release it in the simplest form possible-- it only contains code that is REQUIRED to have a working custom actor (except for the two lines of code that represent the main function): www.mediafire.com/?x6qpj8kqsy9vzv5NOTE: Compressed with 7-ZIP
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 10, 2012 21:31:42 GMT -5
EPIC. I'll work on this next, right now I'm writing loaders for 2 more HC-specific file types. The first, a .cfg file, tells which files in the rom to use for the banks of objects and where to find the ocarina songs (I saw those on that link you gave me and figured I may as well throw in an ocarina song editor since it's so simple). In order to account for the fact that the positions and names of files in the file table can change, the HC .cfg files references the files by their index. The second file type, .fvl (file variable list), stores a list of all the variables within a specific file that can be edited. Here's an incomplete .fvl file called "THE LEGEND OF ZELDA - CZLE - 0028.fvl" for code.zasm in the OoT Debug Rom: start "Interface" UINT16 0005CCEE "Hearts Per Line" start "HUD Colors" RGB16 0005BC0A 0005BC5E ???????? "Normal Heart Color" RGB16 0005BD42 0005BD6A 0005BD82 "Beating Heart Color" RGB16 0005BDDE 0005BE0A 0005BE26 "Beating Heart Outline Color" end end
start "Tunic Colors" RGB8 001091A8 001091A9 001091AA "Kokiri Tunic Color" RGB8 001091AB 001091AC 001091AD "Goron Tunic Color" RGB8 001091AE 001091AF 001091B0 "Zora Tunic Color" end
start "Object Colors" RGBA8 000F9134 000F9135 000F9136 000F9137 "Navi Color" RGBA8 000F9144 000F9145 000F9146 000F9147 "NPC Color" RGBA8 000F914C 000F914D 000F914E 000F914F "Enemy Color" RGBA8 000F9154 000F9155 000F9156 000F9157 "Sign Color" RGBA8 000F915C 000F915D 000F915E 000F915F "Checkable Spot Color" RGBA8 000F916C 000F916D 000F916E 000F916F "Boss Color" end
start "Rupee Worths" UINT16 00108C3C "Green Rupee" UINT16 00108C3E "Blue Rupee" UINT16 00108C40 "Red Rupee" UINT16 00108C42 "Purple Rupee" UINT16 00108C44 "Orange Rupee" end
start "Item Maximums" UINT16 0010A39E "Small Quiver" UINT16 0010A3A0 "Medium Quiver" UINT16 0010A3A2 "Large Quiver" UINT16 0010A3A6 "Small Bomb Bag" UINT16 0010A3A8 "Medium Bomb Bag" UINT16 0010A3AA "Large Bomb Bag" UINT16 0010A3BC "Small Wallet" UINT16 0010A3BE "Medium Wallet" UINT16 0010A3C0 "Large Wallet" UINT16 0010A3C6 "Small Seed Bag" UINT16 0010A3C8 "Medium Seed Bag" UINT16 0010A3CA "Large Seed Bag" UINT16 0010A3CE "Small Deku Sticks" UINT16 0010A3D0 "Medium Deku Sticks" UINT16 0010A3D2 "Large Deku Sticks" UINT16 0010A3D6 "Small Deku Nuts" UINT16 0010A3D8 "Medium Deku Nuts" UINT16 0010A3DA "Large Deku Nuts" end
* These addresses are all relative to the start of code.zasm. Note the 0028 in the filename, this the index of code.zasm in the rom's file table. The format for a variable: TYPE ADDRESS... NAME For colors, there is an address for each channel (eg. an address for red, green, and blue). These variables are sorted into groups. Each group begins with: start "GROUPNAME" and ends with: end Note that you'll be able to create variable lists for any file you want. HC will display them in a tree view and let you easily edit them. I'll post screenies of this and the song editor when they're complete. Updates: * Just finished writing the loader for the .cfg files. Though not implemented yet, I figured I might wanna give you guys a gist of what the song editor looks like: I think it's a pretty good layout. You have your staff, a control to switch between staffs (for use with the scarecrows song), then the familiar A, B, ^, v, <, >. The B button will be used to delete the last note. I also had an idea where if you singleclick the notes it plays the sound, and if you doubleclick it actually adds the note to the staff. Anyway, there's A LOT of open space in that tab. Who knows what I'll end up doing with it.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on May 17, 2012 21:18:10 GMT -5
Sorry for my absence, between bobo getting me addicted to Portal 2, taking mint requests, and working on a secret project that I'm frikkin sure will become 100 times more viral than Minecraft, I've kinda been distracted from HC. Just coming back here to state that didn't run out on everyone ;P
I'd give you more details on this secret project of mine, but several of the game's features have never been used in gaming before, and I don't wanna risk someone else stealing my ideas (CLASSIFIED!!! lol). I'll upload a pre-release of HC sometime tomorrow that has the filesystem editor, patch manager, and makerom editor.
|
|