Sunday, December 30, 2012

Migrating from Alchemy to FlasCC - Compiling C/C++ to SWC



New year, new tools! The updated new version of Alchemy, the C/C++ to AS3 compiler - FlasCC was released some time ago. Many things have been changed. These two tools - Alchemy and FlasCC have very different APIs. However, if you have some experience with the old Alchemy, migrating from it to FlasCC is not hard.

In this post I will share my experience of migrating from Alchemy to FlasCC. I ported the very classic Alchemy example to FlasCC - Ralph Hauwert's Alchemy lookup-table effects. I will use that example to show you how to compile C/C++ code to SWC, how to use FlasCC to manipulate screen buffers, as well as the changes of the APIs.

The installation of FlasCC has been greatly simplified. You don't need to install Cygwin separately like Alchemy because the new FlasCC tool is already integrated with Cygwin. First, you have to get the FlasCC tools at
http://gaming.adobe.com/technologies/flascc/.
Unzip the package to somewhere (mine is "D:\FlasCC_1.0.0"), click "run.bat", then you will open the Cygwin window.

Let compile the sample first:

cd 05_SWC
make FLASCC=/cygdrive/d/FlasCC_1.0.0/sdk FLEX=/cygdrive/d/Program\ Files/FlashDevelop/Tools/flexsdk
This sample is a very simple and good start. You should try to read the source code and the official notes:
http://www.adobe.com/devnet-docs/flascc/docs/samples.html#T5

To create a SWC from some C/C++ functions, we need to write some wrapper code (as3api.cpp) to expose the functions to AS3.
In Alchemy, it will be something in the C/C++'s main() function like this:
int main()
{
AS3_Val initializeScreenDiffuseBufferMethod = AS3_Function(NULL, initializeScreenDiffuseBuffer);
AS3_Val rasterizeMethod = AS3_Function(NULL, rasterize);
AS3_Val setupLookupTablesMethod = AS3_Function(NULL, setupLookupTables);
AS3_Val initializeDiffuseBufferMethod = AS3_Function(NULL, initializeDiffuseBuffer);
AS3_Val result = AS3_Object("initializeScreenDiffuseBuffer: AS3ValType, rasterize:AS3ValType,setupLookupTables:AS3ValType,initializeDiffuseBuffer:AS3ValType"
,initializeScreenDiffuseBufferMethod, rasterizeMethod,setupLookupTablesMethod,initializeDiffuseBufferMethod);
AS3_Release( initializeScreenDiffuseBufferMethod );
AS3_Release( rasterizeMethod );
AS3_Release( setupLookupTablesMethod );
AS3_Release( initializeDiffuseBufferMethod );
AS3_LibInit( result );
return 0;
} 
While in FlasCC, it will be some declarations and wrapper functions outside the main function like this:
void rasterize_AS3() __attribute__((used,
annotate("as3sig:public function rasterize_AS3():void"),
annotate("as3package:FlasCCTest.lookupeffect")));

void rasterize_AS3()
{
rasterize();
}

void setupLookupTables_AS3() __attribute__((used,
annotate("as3sig:public function setupLookupTables_AS3():void"),
annotate("as3package:FlasCCTest.lookupeffect")));

void setupLookupTables_AS3()
{
setupLookupTables();
}
And the main function in FlasCC:
int main()
{
AS3_GoAsync();
}

The basic framework for using C/C++ to manipulate screen buffers:
1. Pass the texture's pixel data as ByteArray to C/C++ array.
2. Process the textures in C/C++.
3. Retrieve the screen buffer array (as bytearray) to flash and use a bitmap to render it.
The best way to pass bytearray between C/C++ and AS3 is to use pointers and C machine's RAM.

Please read the full source code of my example for details.

To pass parameters from AS3 to C/C++, and return the pointer of the array tBuffer (the screen buffer) in Alchemy:
AS3_Val initializeScreenDiffuseBuffer(void* self, AS3_Val args)
{
AS3_ArrayValue(args, "IntType, IntType", &resX, &resY);
tBuffer = malloc( resX * resY * sizeof(int) );
return AS3_Ptr(tBuffer);
}
In FlasCC:
int* initializeScreenDiffuseBuffer(int resX, int  resY)
{
tBuffer = (int*)malloc( resX * resY * sizeof(int) );
return tBuffer;//&(tBuffer[0]);//return the pointer to the screen buffer
}

void initializeScreenDiffuseBuffer_AS3() __attribute__((used,
annotate("as3sig:public function initializeScreenDiffuseBuffer_AS3(resX0:int,resY0:int):uint"),
annotate("as3package:FlasCCTest.lookupeffect")));

void initializeScreenDiffuseBuffer_AS3()
{
int* result;
//copy the AS3 resolution variables resX0, resY0 (parameters of the swc function initializeScreenDiffuseBuffer_AS3) 
//to C variables resX, resY in lookupeffect.c
AS3_GetScalarFromVar(resX,resX0);
AS3_GetScalarFromVar(resY,resY0);
//get the pointer of the screen buffer
result = initializeScreenDiffuseBuffer(resX,resY);
// return the result (using an AS3 return rather than a C/C++ return)
AS3_Return(result);
}

Now let's see some differences of the AS3 APIs:
To initialize the C/C++ SWC Lib in Alchemy:
cLibInit = new CLibInit();
alcLookupLib = cLibInit.init();
In FlasCC:
CModule.startAsync(this);
To call the SWC functions:
Alchemy:
alcLookupLib.setupLookupTables();
alcDiffuseBitmapPointer = alcLookupLib.initializeScreenDiffuseBuffer(IMAGE_WIDTH,IMAGE_HEIGHT);
FlasCC:
setupLookupTables_AS3();
alcDiffuseBitmapPointer = initializeScreenDiffuseBuffer_AS3(IMAGE_WIDTH, IMAGE_HEIGHT); 
To use domain memory - the C machine's RAM (http://www.adobe.com/devnet-docs/flascc/docs/apidocs/com/adobe/flascc/CModule.html#ram):
Alchemy:
var ns : Namespace = new Namespace( "cmodule.lookupeffect");
alchemyMemory = (ns::gstate).ds;
alchemyMemory.position = alcDiffusePointer;
alchemyMemory.writeBytes(ba,0,ba.length);

alchemyMemory.position = alcDiffuseBitmapPointer;
screenDiffuseBitmapData.setPixels(screenDiffuseBitmapData.rect, alchemyMemory);
FlasCC:
CModule.writeBytes(alcDiffusePointer, ba.length, ba);
CModule.readBytes(alcDiffuseBitmapPointer, 512 * 512 * 4, ba);
or
CModule.ram.position = alcDiffuseBitmapPointer;
screenDiffuseBitmapData.setPixels(screenDiffuseBitmapData.rect, CModule.ram);

The source code:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/FlasCC_SWC

Links:
http://www.adobe.com/devnet-docs/flascc/docs/Reference.html
http://unitzeroone.com/blog/2009/04/06/more-play-with-alchemy-lookup-table-effects/
http://blog.debit.nl/2009/03/using-bytearrays-in-actionscript-and-alchemy/

Wednesday, December 26, 2012

Bengine Race - Full Source Code of the Game and the Engine Released!

Here is the full source code for the game Bengine Race:
https://flaswf.googlecode.com/svn/trunk/Games/BengineRace

This release includes the C source code of the voxel engine - Bengine and the AS3 source code of the experimental game - Bengine Race.

You need Alchemy V0.5 (the "outdated" one, not FlasCC) to compile the C source code files to the swc.
You can find my backup of Alchemy Tools here:
https://docs.google.com/folder/d/0B5V2PrQ8xX_EN2NCWHkySGlMclE/edit
Or try the Alchemy Repack for Win32:
http://www.covergraph.com/blog/?p=367

Bengine is still under active development. This release is actually a very old version of Bengine. Since there is no schedule for an "official" release, I decided to share this early version first.

Sunday, December 23, 2012

Use HxSL/Stage3D to Create 2D Filters/Shaders

Update on 2014/01/04:
Many things changed since the original post was published. Now HaXe is 3.0 and HXSL reaches 2.0. So here is the updated source code of the example for HaXe 3 and HXSL 2:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/HxSL2DShader/HaXe3HXSL2/
====================

Maybe you know how to use Pixel Bender in your Flash project to create some custom filters. Alternatively, with the new Stage3D API introduced in Flash 11, we can write 2D filters running with GPU. Here is the example:



The idea is simple: draw a plane using two triangles, upload the images you want to process as textures and do all the magic in your fragment shaders. I recommended you to try HxSL, an advanced shader language which has similar grammar to the Pixel Bender language. The above example - Poster Effect is ported from the Pixel Bender filter with only a few modifications of the original Pixel Bender filter code.

The full source code of the above example (HaXe/HxSL):
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/HxSL2DShader
The source code of the Poster Shader in Pixel Bender Language:
http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&loc=en_us&extid=2400022

Links:
Announcing HxSL:
http://ncannasse.fr/blog/announcing_hxsl
Using Flash 3D API:
http://haxe.org/doc/advanced/flash3d
HxSL API:
http://haxe.org/manual/hxsl

GIMP as Pixel Editor

Some notes and tips for using GIMP (2.8) as a Pixel Editor:

1. The Grid: View->Show Grid, Image->Configure Grid (Spacing 16x16)
2. The brush: Tools->Paint Tools->Pencil(N)/Eraser(Shift+E)
Windows->Dockable Dialogs->Tool Options->Brush->Pixel&Size->1.0
3. Preview: View->New View, View->Zoom
4. Palettes from images:
Windows->Dockable Dialogs->Palettes->Palettes Menu->Import Palette->
Select Source->Image(Must be an image already opened in GIMP)

Links:
http://www.gimp.org/
http://www.eglug.org/gimpixel
http://karnakgames.com/wp/2010/10/gimp-for-pixel-art-shortcuts-setup-and-tips/
http://www.youtube.com/playlist?list=PLC6BCB8E64F315574&feature=plcp
http://www.blendernation.com/2014/11/03/learn-ow-to-create-pixel-art-in-blender/
Pixel Editors:
http://www.piskelapp.com/
https://github.com/juliandescottes/piskel
http://www.aseprite.org/
https://github.com/aseprite/

Sponsors