Original Post

I am trying to get Affine Mode working for a new game project, but I am having some problems with it. I want to “tilt” an image into the screen, as seen on the attached mock-up. I have the param table and world header correctly set up and i can use the affine_fast_scale() function from David Tucker’s Affine Demos. But when I try to use the Affine functions found included in the vbJAEngine, I don’t get any results rendered on the screen. So, how do I call, for example, affineRotateZ() correctly to achieve the desired results? Below is my code and the Affine function:

u16* const param = (u16*)0x0003C000;

copymem((void*)CharSeg0, (void*)CHTEST, 512*16);
copymem((void*)BGMap(0), (void*)BGTEST, 512*16);

WORLD_MSET(31, 0, 0, 0);
WORLD_GSET(31, 0, 0, 0);
WORLD_SIZE(31, 384, 224);
WORLD_PARAM(31, (u32)param);
WORLD_OVER(31, 0x90);


affineRotateZ(31, ITOFIX7_9(1), ITOFIX7_9(1), 384, 224, 0, 0, 45);

void affineRotateZ(u16 param, fix7_9 zoomX, fix7_9 zoomY, s16 bg_x, s16 bg_y, s16 fg_x, s16 fg_y, int alpha)
–PDx_ST pdx;–


–if(zoomX < 0) --{-- ----fg_x *= (-1); --} --pdx.pa = FIX7_9_DIV(COS(alpha), zoomX); --pdx.pb = FIX7_9TOFIX13_3(FIX7_9_DIV(SIN(alpha), zoomY)); --pdx.pc = FIX7_9_DIV(SIN(alpha), zoomY); --pdx.pd = abs(FIX7_9TOFIX13_3(pdx.pa)); -- --pdx.dx = ITOFIX13_3(bg_x - (FIX7_9TOI(pdx.pa) * fg_x + FIX13_3TOI(pdx.pb) * fg_y)); --pdx.dy = ITOFIX13_3(bg_y - (FIX7_9TOI(pdx.pc) * fg_x + FIX13_3TOI(pdx.pd) * fg_y)); --pdx.paralax = 0x0000; -- --{-- ----AFFINE_ST *affine = (AFFINE_ST*)PARAM(param); -- ----AFFINE_ST source = { --------pdx.dx, --------pdx.paralax, --------pdx.dy, --------pdx.pa, --------pdx.pc -------- ----}; ----int i = FIX7_9TOI(FIX7_9_MULT(ITOFIX7_9(fg_y << 1), zoomY)) + 2; ---- ----affine[0] = source; ---- ----for (; --i; ) ----{ ------fix13_3 iFix = ITOFIX13_3(i);------ ------source.pb_y = FIX13_3_MULT(iFix, pdx.pb) + pdx.dx; ------source.pd_y = FIX13_3_MULT(iFix, pdx.pd) + pdx.dy; ------affine = source;

10 Replies

Try setting param to 0xE000:

u16* const param = (u16*)0x0000E000;


I think the first parameter of affineRotateZ is supposed to be the address of the parameter table, not the number of the world.

affineRotateZ(param, ITOFIX7_9(1), ITOFIX7_9(1), 384, 224, 0, 0, 45);

But, since the param address stored in the World attributes has to be:

(addr - 0x00020000) >> 1

where “addr” is the address in VB space, and since I don’t know what Jorge’s PARAM macro does, you might have to tweak those. But, I’m pretty sure it’s the address of the table that’s at fault.

Also, is it really “rotateZ” that you want? Your mockup looks more like a rotate around the X axis…

EDIT: Turns out it’s actually the libgccvb PARAM macro and all it does is mask a value and add it to the base of the parameter table. So, basically, affineRotateZ wants the actual param table address, but the World attributes want the one as calculated above.

So just…


WORLD_PARAM(31, (u32)param);

// to:
WORLD_PARAM(31, (u32)((param - 0x00020000) >> 1));

and the call to affineRotateZ and that should work.

  • This reply was modified 12 years, 1 month ago by RunnerPack.
  • This reply was modified 12 years, 1 month ago by RunnerPack.
  • This reply was modified 12 years, 1 month ago by RunnerPack.

Hi Krisse, If I recall correctly, there are some affine functions which are not complete or don’t work as I expected, but I got bored and didn’t take the time to polish them, so that could be the problem :-).


Thanks RunnerPack! It still does not work, so it looks like this function is incomplete. I want a rotation around the X axis, yeah, but sadly there’s no function for that. 🙁

Jorge, is there a chance that you look at your functions again? 🙂
Or would it be possible to generate a parameter table for an image rotated 45° around the x axis by hand?

Are you looking to do something like the view in Mario Kart (except just on an image)? I optimized my function a bunch, but David has a demo posted on his site that had that perspective (affine demo 2 in: http://www.goliathindustries.com/vb/download/affine_demos.zip ). IIRC, the main thing you need to do is divide pa and pd by the pdx loop counter. I don’t have time to look at it right now, but if I get a sec, I’ll try to help out if you still need it.


Yup, that’s about what I want to do. Attached is a mockup of the game I was thinking of: 3D Blockout! I assume that, once a World is Affine transformed, I can change it in any way I want without losing the transformation?

I looked at David’s demos but couldn’t get the right transformation working.


I know very little about the math involved in affine transforms. But, if you could do without the perspective “fore-shortening” effect, you could do the same thing with just the h-bias mode. I’ve done a “tiled sidewalk” that way, and it looks fairly decent. You could even simulate the perspective part by designing your bgmaps/sprites correctly, but that would probably be more work than using affine…

Blockout looks cool, but I would like to see support for the SNES mouse or maybe custom spinner hardware 😀

Yeah, that’s definitely doable, assuming you’re actually modifying the BGMap. The problem that I ran across in Mario Kart is placing other objects on the screen that line up with the rendered BGMap, but not flat on the BGMap (ie karts upright, while track is laying down). Of course even that’d be easy if you have a static image like that, and aren’t rotating the playfield. Lemme see if I can throw something together for you.


Alright… is this what you’re trying to do (Up/Down adjust the tilt)? I quickly hacked this together from DT’s demos: http://home.comcast.net/~virtual.boy/VB/affine_demo_k.zip . I basically combined the affine_set_all function with the affine_scale function, so I could have it generate a different scale for each line (determined by the loop counter). Of course it’s far from optimal, since it still uses floating point and has redundant code/unnecessary intermediate variables, but that should get you started.


Awesome, that looks perfect! I will get into it next week. Thanks Pat! 🙂

No prob… glad to help.



Write a reply

You must be logged in to reply to this topic.