johannes-fetz / joengine

Jo Engine is an open source 2D and 3D game engine for the Sega Saturn written in C under MIT license
http://jo-engine.org/
MIT License
205 stars 32 forks source link

Line scroll demo not working on the console #75

Closed fafling closed 6 months ago

fafling commented 6 months ago

On the console or with an emulator that checks that VDP2's cycle pattern allow the display of an NBG, the line scroll demo displays nothing.

The graphics is initialized on NBG1 with a 16 bpp bitmap when jo_core_init calls jo_core_init_vdp that calls __jo_init_vdp2. NBG1 is then set to an 8bpp tilemap when jo_set_background_8bits_sprite calls jo_vdp2_set_nbg1_8bits_image.

The problem is that jo_vdp2_set_nbg1_8bits_image doesn't update VDP2's cycle pattern that remains set to the value that allows the display of NBG1 as a 16 bpp bitmap. Cycle pattern value displayed by Kronos v2.6.1 in VDP2 debug screen :

A0 = 5555FEEE
A1 = 5555FEEE
B0 = FFFFEEEE
B1 = 044FEEEE

What prevents the display of NBG1 8bpp tilemap is that there's no access for its pattern name (it would show as a nibble set to1).

Adding a call to slScrAutoDisp at the end of jo_vdp2_set_nbg1_8bits_image in vdp2.c solves that issue :

void                            jo_vdp2_set_nbg1_8bits_image(jo_img_8bits *img, int palette_id, bool vertical_flip)
{
    __jo_switch_to_8bits_mode();
    if (nbg1_cell != JO_NULL)
        jo_vdp2_free(nbg1_cell);
    slPlaneNbg1(PL_SIZE_1x1);
    slCharNbg1(COL_TYPE_256, CHAR_SIZE_1x1);
    if (nbg1_map == JO_NULL)
        nbg1_map = (unsigned short *)jo_vdp2_malloc(JO_VDP2_RAM_MAP_NBG1, JO_VDP2_MAP_SIZE);
    slMapNbg1(nbg1_map, nbg1_map, nbg1_map, nbg1_map);
    nbg1_cell = (unsigned char *)jo_vdp2_malloc(JO_VDP2_RAM_CELL_NBG1, img->width * img->height);
    slPageNbg1(nbg1_cell, 0, PNB_1WORD | CN_12BIT);
    jo_img_to_vdp2_cells(img, vertical_flip, nbg1_cell);
    __jo_create_map(img, nbg1_map, palette_id, JO_VDP2_CELL_TO_MAP_OFFSET(nbg1_cell));
    JO_ADD_FLAG(screen_flags, NBG1ON);
    slScrAutoDisp(screen_flags); // Ensures that NBG1 displays with correct cycle pattern.
}

Resulting cycle pattern :

A0 = 55FEEEEE
A1 = FFFEEEEE
B0 = 1FFFEEEE
B1 = 044FEEEE

In fact, slScrAutoDisp should be called each time screen_flags is modified, which isn't the case in NBG1 related functions in vdp2.c.

johannes-fetz commented 6 months ago

Thx @fafling, I fixed the issue as you suggested.