I've been building a basic interface for dealing with graphic surfaces lately. I
already had most of the routines for 16bpp and 8bpp bitmaps in older Toncs, but
but their use was still somewhat awkward because you had to provide some
details of the destination manually; most notably a base pointer and the pitch.
This got more than a little annoying, especially when trying to make blitters as
well. So I made some changes.
For each of these three, I have the most important rendering functions:
plotting pixels, lines, rectangles and blits. Yes, blits too. Even for
chr4c
-mode. There are routines for frames (empty
rectangles) and floodfill as well. The functions have a uniform interface
with respect to surface-type, so switching between them should be
easy were it necessary. There are also tables with function pointers
to these routines, so by using those you need not really care about
the details of the surface after its creation. I'll probably add a
pointer to such a table in TSurface
in the future.
The image on the right is the result of the following routine.
Turret pic semi-knowingly provided by
Kawa.
void test_surface_procs(const TSurface *src, TSurface *dst,
const TSurfaceProcTab *procs, u16 colors[])
{
// Init object text
tte_init_obj(&oam_mem[127], ATTR0_TALL, ATTR1_SIZE_8, 512,
CLR_YELLOW, 0, &vwf_default, NULL);
tte_init_con();
tte_set_margins(8, 140, 160, 152);
// And go!
tte_printf("#{es;P}%s surface primitives#{w:60}", procs->name);
tte_printf("#{es;P}Rect#{w:20}");
procs->rect(dst, 20, 20, 100, 100, colors[0]);
tte_printf("#{w:30;es;P}Frame#{w:20}");
procs->frame(dst, 21, 21, 99, 99, colors[1]);
tte_printf("#{w:30;es;P}Hlines#{w:20}");
procs->hline(dst, 23, 23, 96, colors[2]);
procs->hline(dst, 23, 96, 96, colors[2]);
tte_printf("#{w:30;es;P}Vlines#{w:20}");
procs->vline(dst, 23, 25, 94, colors[3]);
procs->vline(dst, 96, 25, 94, colors[3]);
tte_printf("#{w:30;es;P}Lines#{w:20}");
procs->line(dst, 25, 25, 94, 40, colors[4]);
procs->line(dst, 94, 25, 79, 94, colors[4]);
procs->line(dst, 94, 94, 25, 79, colors[4]);
procs->line(dst, 25, 94, 40, 25, colors[4]);
tte_printf("#{w:30;es;P}Full blit#{w:20}");
procs->blit(dst, 120, 16, src->width, src->height, src, 0, 0);
tte_printf("#{w:30;es;P}Partial blit#{w:20}");
procs->blit(dst, 40, 40, 40, 40, src, 12, 8);
tte_printf("#{w:30;es;P}Floodfill#{w:20}");
procs->flood(dst, 40, 32, colors[5]);
tte_printf("#{w:30;es;P}Again !#{w:20}");
procs->flood(dst, 40, 32, colors[6]);
tte_printf("#{w:30;es;P;w:30}Ta-dah!!!#{w:20}");
key_wait_till_hit(KEY_ANY);
}
// Test 4bpp tiled, column-major surfaces
void test_chr4c_procs()
{
TSurface turret, dst;
// Init turret for blitting.
srf_init(&turret, SRF_CHR4C, turretChr4cTiles, 128, 128, 4, NULL);
// Init destination surface
srf_init(&dst, SRF_CHR4C, tile_mem[0], 240, 160, 4, pal_bg_mem);
schr4c_prep_map(&dst, se_mem[31], 0);
GRIT_CPY(pal_bg_mem, turretChr4cPal);
// Set video stuff
REG_DISPCNT= DCNT_MODE0 | DCNT_BG2 | DCNT_OBJ | DCNT_OBJ_1D;
REG_BG2CNT= BG_CBB(0)|BG_SBB(31);
u16 colors[8]= { 6, 13, 1, 14, 15, 0, 14, 0 };
// Run internal tester
test_surface_procs(&turret, &dst, &chr4c_tab, colors);
}