CodeDesigner 3 finally has a demo release! I can't debug everything myself so it would be helpful to get some people to play with it and let me know what they think. It has made so many improvements over the old VB6 version. Now writing your 32 Bit MIPS routines is easier than ever. Utilizing some of the C syntax for implementation of IF, SWITCH, FOR Loops, While Loops, FNC Calls, etc, projects can be knocked out faster.
Download: CD3.rar
Update *Fixed issue with mouse click on source viewer, fixed a bug found with the multi-line comments
Update *Added Threading, Events, Updated function Calls, Fixed minor GUI bugs, allowed function calls to pass data instead of just arguments
It is not finished yet, it still lacks some of the features for now (but will be added soon). Some things to look forward to in the near future would be the Code Debugger, Memory dump analyzing (and possibly *decompiling* to an extent), library creation and archiving, ELF creation / modification, etc.
If the read me file doesn't explain how to utilize newly implemented functionality, I am always here to answer any questions.
The current (pretty sloppy, still cleaning it up) source code can be found on GIT: https://github.com/mbacker80/CodeDesigner3
README:
Some of the screen shots:



Code Examples (String Manipulation)
Live Code Example for Threading and Events:
Download: CD3.rar
Update *Fixed issue with mouse click on source viewer, fixed a bug found with the multi-line comments
Update *Added Threading, Events, Updated function Calls, Fixed minor GUI bugs, allowed function calls to pass data instead of just arguments
It is not finished yet, it still lacks some of the features for now (but will be added soon). Some things to look forward to in the near future would be the Code Debugger, Memory dump analyzing (and possibly *decompiling* to an extent), library creation and archiving, ELF creation / modification, etc.
If the read me file doesn't explain how to utilize newly implemented functionality, I am always here to answer any questions.
The current (pretty sloppy, still cleaning it up) source code can be found on GIT: https://github.com/mbacker80/CodeDesigner3
README:
Code:
CodeDesigner 3 (Created by Gtlcpimp)
CodeDesigner has finally made its way onto the .NET framework. During the transition it has picked up
a lot more functionality. Combining some syntax from C with the MIPS32 instruction set, it is capable
of so much more possibilities than the original design. The build is not yet completely finished,
however is ready enough to be toyed with (or even build projects with). Here's a look at the updates:
====================================================================================================
1) Shorthand Math
Yes! Finally! Shorthand math! I bet we are all sick of seeing all those ADDIU's and what not. Well
you can't replace them entirely just yet, shorthand math is limited to 16 Bit integer math. So you'll
still need those hideous LUI's and ADDIU's for larger values. Here's what we have for short handing:
++ // Register + 1
-- // Register - 1
+= // Register + Value (or another register)
-= // Register - Value (or another register)
Here's some examples:
a0++ // Increases the value of a0 by 1
a0-- // Decreases the value of a0 by 1
a0 += 50 // Increase the value of a0 by 50
a0 -= v0 // Decrease the value of a0 by the value of v0
Oh and don't forget bit shifting!
>> // Shift right X bits (srl)
<< // Shift left X bits (sll)
>>> // DOUBLE shift right X bits (dsrl)
<<< // DOUBLE shift left X bits (dsll)
>>32 // DOUBLE shift right X bits times 32 (dsrl32)
<<32 // DOUBLE shift right X bits times 32 (dsll32)
Examples:
a0 >> 10 // Shifts the 32 bit word value in a0 to the right by 10 bits
v0 << 4 // Shifts the 32 bit word value in v0 to the left by 4 bits
t0 >>> 16 // Shifts the 64 bit double word value in t0 to the right by 16 bits
t1 <<< 16 // Shifts the 64 bit double word value in t1 to the left by 16 bits
v0 >>32 0 // Shifts the 64 bit double word value in v0 to the right by 32 bits
v1 <<32 0 // Shifts the 64 bit double word value in v1 to the left by 32 bits
Shorthand math is super simple, and can be implemented virtually everywhere in your project. What
would we do without it? It makes life so much easier.
====================================================================================================
2) IF Statements
There are multiple ways to declare an IF statement. You can either do a single instruction IF or a
multiple instruction IF. The difference is literally in the braces. If you do not include braces
after declaring IF, it will compile it as a single instruction. If you do include the braces, it
compiles as a multiple instruction IF. Here is the syntax for the declaration:
//Single Instruction IF
if (condition)
//ONE (ONLY ONE) Instruction goes here
// Multiple Instruction IF
if (condition)
{
/*
As many instructions as your heart desires can go here
*/
}
The conditions are very simple:
> Greater than
< Less than
>= Greather than or equal to
<= Less than or equal to
== Is equal to
<> Does not equal
Live code examples:
//Single Instruction IF
if (a0 > t3)
v0 = 1
// Multiple Instruction IF
if (v0 <= 0)
{
a0 += 4
lw v0, $0000(a0)
/*
Etc.
*/
}
Now we can't forget about our ELSE statements, yes we have those too! They follow the exact same
guidelines as the IF declarations, with the exact same syntax. All except for the ELSE itself,
of course. ELSE IF is used for an extra conditional statement, as many times as you need. The
ELSE statement itself however, is the fallback condition for if the IF did not execute. Here's
the examples:
// Single Instruction IF/ELSE
if (a0 > 0)
lw v0, $0000(a0)
else
v0 = -1
Single Instruction IF's can be combined with a Single Instruction ELSE only. You cannot use ELSE IF
here. That is reserved for the multi-instruction declaration (literally just add braces).
// Multi-conditional IF/ELSE IF/ELSE
if (a0 == 1)
{
v0 = 1
}
else if (a0 == 2)
{
v0 = 2
}
else if (a0 == 3)
{
v0 = 3
}
else
{
v0 = 0
}
What this code gets compiled out to is this:
addiu at, zero, $0001
beq a0, at, $0007
addiu at, zero, $0002
beq a0, at, $0008
addiu at, zero, $0003
beq a0, at, $0009
nop
beq zero, zero, $000a
nop
addiu v0, zero, $0001
beq zero, zero, $0008
nop
addiu v0, zero, $0002
beq zero, zero, $0005
nop
addiu v0, zero, $0003
beq zero, zero, $0002
nop
daddu v0, zero, zero
You can have as many ELSE IF's as you want as long as you keep them wrapped with those braces! Also
you must note that it utilizes the "at" register (which stands for Assembler Temporary), so avoid
the use of this register at all cost if using the IF statements.
====================================================================================================
3) SWITCH Statements
SWITCH Statements are very similar to the IF statements, however only compares the value of a single
register to multiple cases that are specified. Syntax as follows:
switch (a0)
{
case 0
{
v0 = 0
}
case 1
{
v0 = 1
}
case 2
{
v0 = 2
}
case 3
{
v0 = 3
}
case default
{
v0 = -1
}
}
You can have as many cases as you like, with any value you choose. The default is similiar to the ELSE
of an IF statement, it gets executed if none of the cases were true. Since everything is required to
be wrapped in braces, you can have as many lines of code inside the cases as you desire. The SWITCH
also compiles using the "at" register to do comparisons just like the IF statement, so avoid the use
of this register when using a SWITCH.
What the example would compile to is:
beq a0, zero, $000b
ori at, zero, $0001
beq a0, at, $000c
ori at, zero, $0002
beq a0, at, $000d
ori at, zero, $0003
beq a0, at, $000e
ori at, zero, $0000
beq a0, at, $000f
nop
beq zero, zero, $0010
nop
daddu v0, zero, zero
beq zero, zero, $000d
nop
addiu v0, zero, $0001
beq zero, zero, $000a
nop
addiu v0, zero, $0002
beq zero, zero, $0007
nop
addiu v0, zero, $0003
beq zero, zero, $0004
nop
addiu v0, zero, $ffff
beq zero, zero, $0001
nop
====================================================================================================
3) FNC Declarations
You now have the capability to declare functions to save time and energy. Functions must be wrapped
with braces, and you can specify extra stack space if needed for preserving more registers.
Syntax:
fnc MyFunction(EE a0, EE a1, EE a2) \s0,s1,s2,s3,s4
{
s0 = a0
s1 = a1
s2 = a2
/*
do some stuff
*/
return 1;
}
As you see, you declare "fnc" followed by the name of your function, then in the paranthesis you
can specify any arguments you want it to use. The backslash at the end declares what registers you
want to be preserved onto the stack. The compiler does all of the work for you. You can force the
function to exit by calling "return" followed by whatever value you want to have returned. The return
will place the specified value (or register value) into "v0".
As you can see, this code will compile out to this:
addiu sp, sp, $ffa0
sq ra, $0000(sp)
sq s0, $0010(sp)
sq s1, $0020(sp)
sq s2, $0030(sp)
sq s3, $0040(sp)
sq s4, $0050(sp)
daddu s0, a0, zero
daddu s1, a1, zero
daddu s2, a2, zero
beq zero, zero, $0001
ori v0, zero, $0001
lq ra, $0000(sp)
lq s0, $0010(sp)
lq s1, $0020(sp)
lq s2, $0030(sp)
lq s3, $0040(sp)
lq s4, $0050(sp)
jr ra
addiu sp, sp, $0060
====================================================================================================
3) FOR Loops
FOR loops can help cut down code, and remove the need to always calculate branch values or throwing
labels everywhere. It follows the same concept from C, where you have the syntax:
for (init; condition; increment)
{
// Code
}
You can use shorthand math in the increment statement. Live code example:
for (a0 = 0; a0 < 100; a0++)
{
v0++
}
What this would compile to:
daddu a0, zero, zero
addiu at, zero, $0064
subu at, a0, at
bgez at, $0004
nop
addiu v0, v0, $0001
beq zero, zero, $fffa
addiu a0, a0, $0001
====================================================================================================
4) WHILE Loops
WHILE Loops are conditional only loops. While the condition is TRUE, it keeps looping. It can be used
to create an infinite loop:
while (1)
{
// Code
}
Or an actual conditional loop:
while (a0 < 100)
{
v0++
}
What this example would compile out to:
addiu at, zero, $0064
subu at, a0, at
bgez at, $0004
nop
addiu v0, v0, $0001
beq zero, zero, $fffa
nop
====================================================================================================
5) BREAK
BREAK has been implemented naturally since we have SWITCH, FOR, and WHILE statements. Yes there is
a MIPS instruction called BREAK already, so what has been done is the compiler checks to see if you
are using the instruction or the command.
break; // Breaks out of current loop (or case)
break(1); // Breaks out of current loop and parent loop (or case)
break(2); // ^ + next parent loop (or case)
So on, so forth. To use the actual MIPS instruction, you must specifically use the syntax for the
instruction itself:
break (00000)
====================================================================================================
6) Compiler Specific "Commands"
Address $00100000 // Specifies code output addressing
Labels: // Declares a label at this current section of the source
setreg v0, $12345678 // Sets a 32 bit value into the register
setfpr f0, $3f800000 // Sets the float regsiter to the 32 bit value
setfloat f0, 5 // Sets the float register to the specified integer value
goto :label
goto $00100000 // Sets a direct branch (or jump if target address is out of branch range)
extern $00100000 funcName(EE t0, EE t1, COP1 f0) // Similiar to FNC only declaring an "external" function
at the specified memory address so you can call
to it.
call funcname(s0, s1, s2) // Calls a function you have declared, placing the arguments you specify into the
corresponding argument registers
define labelName $12345678 // Defines a new label of the specified value
hexcode $12345678 // Directly outputs the value to the code output
print "string" // Prints the string directly to the code output
string labelName "my string" // Creates a string, appends to the END of the code output, preserving its
memory address in the specified label
padding $20 // Generates 0's in the code output to the specified size
====================================================================================================
7) Threading
Yes and no. It's not actual "threading" its similiar but not the actual same. The EE can't do real
multi-threading. So what we are going to be doing, is creating a list of functions that will be
executed in order. Just to keep it simple to understanding, we're going to call it threading.
First off let's start with how to declare a thread. Syntax is very simple:
thread myFunc
Simple enough, right? Let's take a look at the options available for it:
thread myFunc /delay 100
thread myFunc /off
thread myFunc /delay 100 /off
What does that mean? Well, the delay is an iteration delay to basically "slow down" how often it
executes. So if you follow the example, a delay of 100 means it will only execute the thread every
100th iteration of the main process. As for the "off", that means that our thread is not going to
be active until specified within one of our actual functions. Default is on, without delay.
A thread can be started and stopped, also put to sleep (set on delay) or woken up (delay removed).
The syntax is simple:
thread.sleep (myFunc, 1000) // Put's thread "myFunc" to a delay to only execute once every 1000th iteration
thread.wakeup (myFunc) // Removes the delay and allows it to run as fast as the main process can call it
thread.stop (myFunc) // Stops the execution of the thread entirely, it will never execute until its started
thread.start (myFunc) // Starts a thread back up so it will start executing again
====================================================================================================
8) Data-Watch Events
Data-Watch events are basically a thread that watches a memory address, and executes your function
if the data you set to watch appears in the memory address. Think of it like an IF statement, but
simplified, on a higher level. Here's the syntax:
event myFunc $00100000 $12345678 /w
In the syntax, you declare your functions name, then the memory address to watch, followed by the
data that you are looking for. The "/w" is the statement that declares if it's a byte "/b", half word
"/h", or word "/w".
Here's a live example:
event padInput_X $007157dc $bfff /h
In this example, we are setting an event to watch if the button 'x' is being held down
(on SOCOM: Combined Assault)
====================================================================================================
8) Hooks
How can any of our routines run if we don't hook them from the game? We now have a simplified method
for this. As long as you know what the memory address is you want to hook from, you can use the HOOK
feature. Let's look at the syntax:
hook myFunc $00100000 -j
In this example, we are placing a "jump" hook to our function at memory address $00100000. We can do
other types of hooks by changing the option. For example:
-j = Jump
-jal = Jump and Link
-pointer = Pointer
Pretty obvious, and very simple. Now for something important. We introduced threading, and events.
Now we obviously must hook our handler that operates those features. For that, we have a seperate
command called "ProcHook" (short for Process Hook). If we know what the memory address is that
we want to hook from, and have our threads and events set up, we will do this:
prochook $00100000 -j // or -jal or -pointer whichever is needed
This will allow our event handler and thread manager to run.
Code Examples (String Manipulation)
Code:
/*
Strings Library
Created by: Gtlcpimp
*/
//============================================================
// Upper Case -> Converts to Upper Case
/*
Input:
a0 = &String
C Syntax Equivalent:
void toUpperCase(char *src)
*/
fnc UCase(EE a0) \s0,s1
{
// Take our pointer to the string
s0 = a0
// Find out the length of the string
call strLen(s0)
s1 = v0
// Loop through the entire string by its length
for (a0 = 0; a0 < s1; a0++)
{
// Load the character at our current position
lbu v0, $0000(s0)
// Check to see if it's a lower 'a' or greater value
if (v0 >= $61)
{
// Check to see if it's a lower 'z' or less (a-z)
if (v0 < $7b)
{
// Decrease it's value to that of the Upper
// Case letters, then store back in place
v0 -= $20
sb v0, $0000(s0)
}
}
// Increment our position in the string
s0++
}
// Return nothing, function is void
}
//============================================================
// Lower Case -> Converts to Lower Case
/*
Input:
a0 = &String
C Syntax Equivalent:
void toLowerCase(char *src)
*/
fnc LCase(EE a0) \s0,s1
{
// Take our pointer to the string
s0 = a0
// Find out the length of the string
call strLen(s0)
s1 = v0
// Loop through the entire string by its length
for (a0 = 0; a0 < s1; a0++)
{
// Load the character at our current position
lbu v0, $0000(s0)
// Check to see if it's a capital 'A' or greater value
if (v0 >= $41)
{
// Check to see if it's a capital 'Z' or less (A-Z)
if (v0 < $5b)
{
// Increment it's value to that of the Lower
// Case letters, then store back in place
v0 += $20
sb v0, $0000(s0)
}
}
// Increment our position in the string
s0++
}
// Return nothing, function is void
}
//============================================================
// String Length -> Gets the length of the string
/*
Input:
a0 = String
Output:
v0 = String Length
C Syntax Equivalent:
int strLen(char *src)
*/
fnc strLen(EE a0)
{
// Start our counter at 0
v0 = 0
// Check the first character to make sure it's not empty
lbu v1, $0000(a0)
while (v1)
{
// Load the character at our current position
lbu v1, $0000(a0)
// Check if it's the end of the string
if (v1 == 0)
break;
// Increment our position in the string
a0++
// Increment our counter, we aren't at the end yet
v0++
}
// Return register v0 is already loaded as the counter
// and will be returned to the parent function
}
//============================================================
// String Clear -> Erases the entire string (places NULL chars)
/*
Input:
a0 = String
C Syntax Equivalent:
void strClear(char *src)
*/
fnc strClear(EE a0)
{
// Make sure we aren't already at the end of the string
lbu v0, $0000(a0)
while (v0)
{
// Store a NULL char (erasing the existing char)
sb zero, $0000(a0)
// Increment our position in the string
a0++
// Load the next char for checking if it's the end
lbu v0, $0000(a0)
}
// Return nothing, function is void
}
//============================================================
// String Copy -> Copies a string to the specified destination
/*
Input:
a0 = Source String
a1 = Destination String
a2 = Source Start Position (index)
Output:
v0 = End of Source String (NULL + 1)
v1 = Number of chars copied
C Syntax Equivalent:
int strCopy(char *src, char *dst, int index)
*/
fnc strCopy(EE a0, EE a1, EE a2) \s0,s1
{
// Set our position in the Source String
daddu s0, a0, a2
// Set our destination
s1 = a1
// Make sure we aren't at the end of the source string
lbu v1, $0000(s0)
while (v1)
{
// Store our character in the destination string
sb v1, $0000(s1)
// Increment to the next position in the Source
s0++
// Increment to the next position in the Destination
s1++
// Load the character next character to copy
lbu v1, $0000(s1)
}
// End our destination string by placing a NULL character
sb zero, $0000(s1)
// Set our return register v1 to the copied byte count
subu v1, s1, a1
// Set our return register v0 to be end of source + 1
addiu v0, s1, 1
}
//============================================================
// String Compare -> Compares 2 Strings
/*
Input:
a0 = String 1
a1 = String 2
Output:
v0 = -1 or 0 or 1
-1: String 1 goes before String 2 (alphabetically)
0: Strings are identical
1: String 1 goes after String 2 (alphabetically)
C Syntax Equivalent:
int strCompare(char *str1, char *str2)
*/
fnc strCompare(EE a0, EE a1) \s0,s1,s2
{
s0 = a0
s1 = a1
// Get length of String 1
call strLen(s0)
s2 = v0
// Get length of String 2
call strLen(s1)
// Check if String 1 is shorter than String 2
if (s2 < v0)
return -1
// Check if String 1 is longer than String 2
if (s2 > v0)
return 1
for (a0 = 0; a0 < s2; a0++)
{
lbu v0, $0000(s0)
lbu v1, $0000(s1)
// Compare if str1[x] is less than str2[x]
if (v0 < v1)
return -1
// Compare if str1[x] is greater than str2[x]
if (v0 > v1)
return 1
}
// Both strings are 100% identical
v0 = 0
}
Live Code Example for Threading and Events:
Code:
/*
CodeDesigner v3 ~ Created by: Gtlcpimp
*/
address $000c0000
prochook $002e4e74 -j
event padInput_X $007157dc $bfff /h
thread threadedRunner
fnc threadedRunner(void)
{
/*
We are always running
*/
}
fnc padInput_X(void)
{
/*
We only get here if X button is pressed
*/
}
Comment