It's not a short time since Alchemy emerged in 2008.
To my disapointment, scarcely any more great C projects ported to Flash after doom and quake.
And there is no updates for this great tool.I like alchemy and use it a lot because it allows you to do flash in C. Alchemy is much more than the new fast memory opcodes, it is a C virtual machine, which wraps the standard C lib for ActionScript. Do flash in C, makes porting C programs easy and also makes your flash program portable. Moreover, the gcc and llvm compilers can optimaize your code a lot. That's why although there are both powerful tools like apparat, yogda and handy tools like azoth which let you to use those alchemy memory opcodes in pure AS3, I'm still using alchemy. Actually, if there is no alchemy, I was already a Haxer in 2008.
The obvious disadvantage to use alchemy is this tool has lots of bugs and it is very hard to debug. As far as I know most bugs are with C++(broken string.h, can't use cin/cout, the class initialization function will never initialize), so don't try to port a C++ program with alchemy now unless you're ready to port the C++ program to C first. What's more, it lacks documentations and developing resources. Although the official forum is a good place to discuss alchemy, it' not easy to find some advanced and detailed things. There is no instructions for inline asm and memory manipulation which many people may be intereted in.
After some search, finally I got some useful things.
So I wrote this little code snippet, hope to help those who want to know more about how to use alchemy. I hope Adobe can give more emphasis on alchemy, update it, remove the bugs, make it stable and make the developing process easier. It is a great thing and should not only be an experimental project, which be played with for some moment, then thrown into some dark corner of the lab and let it decay. I even wish Adobe could make C/C++ an official alternative for ActionScript to develop flash.
/* [Adobe Alchemy Hacks] AlchemyVM_hack.c {Simple example for using inline asm and accessing memory of Alchemy Virtual Machine in C} By Bruce Jawn (January/14/2011) [http://bruce-lab.blogspot.com] To compile this source file with Alchemy: cd /cygdrive/f/alchemy/ source /cygdrive/f/alchemy/alchemy-setup alc-on gcc AlchemyVM_hack.c -O3 -Wall -swf -o AlchemyVM_hack.swf */ #includeThe compiled swf will display:#include //get the Alchemy C Virtual Machine memory //use asm to embed AS3 code asm("var ALCVM_Memory:ByteArray = gstate.ds;"); int main () { /*Test Memory Write*/ //array of int for the test int* testData = malloc(0xff * sizeof(int)); //get the address of testdata in memory AS3_Val Adr=AS3_Ptr(testData); int AdrInt=AS3_IntValue(Adr); //the test value we will write into testData via memory int testValue=123; //write the testValue into testData //gcc AT&T inline assembly used here asm("ALCVM_Memory[%0] = %1;" : : "r"(AdrInt), "r"(testValue)); //ALCVM_Memory[AdrInt] = testValue; //Check if testValue has been written into testData printf("%d\n",testData[0]);//should print 123 /*Test Memory Read*/ int readedValue; asm("%0 ALCVM_Memory[%1];" : "=r"(readedValue) : "r"(AdrInt)); printf("%d\n",readedValue);//should print 123 /*Test Inline ASM*/ //label and jump asm("__asm(jump, target('myLable'))"); printf("%s\n","not jumped!");//this line will be skipped asm("__asm(label, lbl('myLable'))"); printf("%s\n","jumped!"); //switch jump asm("var myState:int=1;"); asm("__asm(push(myState), switchjump('state0','state1','state2'));"); asm("__asm(lbl('state0'))"); printf("%s\n","This is state0."); asm("__asm(lbl('state1'))"); printf("%s\n","This is state1."); asm("__asm(lbl('state2'))"); printf("%s\n","This is state2."); //iftrue jump asm("var temp:int=1;"); asm("__asm(push(temp!=0), iftrue, target('turejump'));"); printf("%s\n","iftrue not jumped!");//this line will be skipped asm("__asm(label, lbl('turejump'))"); printf("%s\n","iftrue jumped!"); /*Test Alchemy Memory Instructions*/ //All memory opcodes listed here: /* Get a 32 bit value at the location addr and return as an int: _mr32(addr:int):int{ return __xasm (push(addr), op(0x37)); } Get a 16 bit unsigned value at the location addr and return as an int:. _mru16(addr:int):int { return __xasm (push(addr), op(0x36)); } Get a 16 bit signed value at the location addr and return as an int: _mrs16(addr:int):int { return __xasm (push(addr), op(0x36)); } // li16 Get a 8 bit value at the location addr and return as an int: _mru8(addr:int):int { return __xasm (push(addr), op(0x35)); } Get a 8 bit value at the location addr and return as an int: _mrs8(addr:int):int { return __xasm (push(addr), op(0x35)); } Get a float value at the location addr and return as an Number: _mrf(addr:int):Number { return __xasm (push(addr), op(0x38)); } Get a double value at the location addr and return as an Number: _mrd(addr:int):Number { return __xasm (push(addr), op(0x39)); } Write an int as a 32 bit value at the location addr: _mw32(addr:int, val:int):void { __asm(push(val), push(addr), op(0x3c)); } Write an int as a 16 bit value at the location addr: _mw16(addr:int, val:int):void { __asm(push(val), push(addr), op(0x3b)); } Write an int as a 8 bit value at the location addr: _mw8(addr:int, val:int):void { __asm(push(val), push(addr), op(0x3a)); } Write a Number as a float at the location addr: _mwf(addr:int, val:Number):void { __asm(push(val), push(addr), op(0x3d)); } Write a Number as a double at the location addr: _mwd(addr:int, val:Number):void { __asm(push(val), push(addr), op(0x3e)); } */ //Write an int 654321 as a 32 bit value at the location 1000 asm("__asm(push(654321),push(1000),op(0x3c));"); //Trace the memory asm("ALCVM_Memory.position=1000"); asm("trace(ALCVM_Memory.readInt());");//should trace 654321 in flashlog.txt //Get a 32 bit value at the location 1000 and return as an int asm("var temp:int=__xasm (push(1000), op(0x37));"); asm("trace(temp)");//should trace 654321 in flashlog.txt /*Test some AVM2 Instructions*/ //More AVM2 Instructions can be found at: //http://www.anotherbigidea.com/javaswf/avm2/AVM2Instructions.html //test add: 0xA0 int var1=123; int var2=321; //write (var1+var2)=444 to testData[0] via memory //ALCVM_Memory.position=AdrInt; //ALCVM_Memory.writeInt(var1+var2); asm("__asm(push(%0), push(%1), op(0xA0), push(%2), op(0x3c))" : : "r"(var1), "r"(var2), "r"(AdrInt)); printf("%d\n",testData[0]);//should print 444 //test subtract: 0xA1 asm("var result:int=__xasm(push(%0), push(%1), op(0xA1));" : : "r"(var1), "r"(var2));//var result=var1-var2; //write (var1-var2)=-198 to testData[1] via memory in a different way asm("__asm(push(result),push(%0),op(0x3c));":: "r"(AdrInt+4)); printf("%d\n",testData[1]);//should print -198 return 0; } /* References: http://labs.adobe.com/wiki/index.php/Alchemy:Documentation:Developing_with_Alchemy:AS3_API http://blog.frankula.com/?p=211 http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html http://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html Special thanks to zazzo9 (http://forums.adobe.com/people/zazzo9) http://forums.adobe.com/thread/660099 http://forums.adobe.com/message/2101303 http://forums.adobe.com/message/1059161 http://forums.adobe.com/message/1915605 http://forums.adobe.com/message/2101405 http://forums.adobe.com/message/1914780 */
123
123
jumped!
This is state2.
iftrue jumped!
444
-198
The flashlog(C:\Documents and Settings\Administrator\Application Data\Macromedia\Flash Player\Logs\flashlog.txt)
654321
654321
[object AlchemyExit]
at global/shellExit()
at cmodule.AlchemyVM_hack::CSystemLocal/exit()
at cmodule.AlchemyVM_hack::CRunner/work()
at
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick
[Update 2012/Jan/06]
Alchemy GOODIES: The C and AS3 mixed syntax using ASM.
It is not a good habit to mix C code with AS3, but this can be handy sometimes:
//AS3 values to C int myINT = 0; asm("var ASvar1 = 1; var ASvar2 = 2;");//Embed AS3 code in C asm("%0 ASvar1+ASvar2" : "=r"(myINT) : );//myINT=ASvar1+ASvar2; AS3_Trace(AS3_String("myINT=")); AS3_Trace(AS3_Int(myINT));//will print 3 //C values to AS3 int myINT0 = 123456; asm("var ASvar0:int;"); asm("ASvar0 = %0" :: "r" (myINT0) ); asm("trace('ASvar0=');"); asm("trace(ASvar0);");//will print 123456
No comments:
Post a Comment