Updating pattern table and name table at the same time?

Page 1/3
| 2 | 3

By pizzapower

Master (133)

pizzapower's picture

16-10-2022, 15:54

Hi. I am testing a vertical scrolling algorithm, but I get some flicker when I try to update both pattern and name tables at the same frame on each 8th frame. This roughly is what I am trying to do:

#include <stdint.h>
#include <stdbool.h>

extern const uint8_t map_data[MAP_WIDTH*MAP_HEIGHT];
uint8_t *map_data_p = map_data;

void run_loop() {
    int8_t frame = -1;
    bool game_running = true;

    while (game_running) {
        frame++;
        update_tiles(); // move the maze up pixel by pixel by changing the pattern table
        if (frame == 7) {
            frame = -1; // reset frame counter
            map_data_p += 32;     // update map pointer by width size (point to the next line)
            update_map();         // move the maze up tile by tile by changing the name table
        }
        // process user input and update sprites
        // ...
        wait();  // wait the allotted frame time to finish
    }

Has anyone implemented this type of scrolling engine successfully without flicker?

Login or register to post comments

By thegeps

Paragon (1156)

thegeps's picture

16-10-2022, 16:35

I did, but in assembly and redefining dynamically 32 chars for each pixel scrolled. It should be faster with preshifted chars...

By pizzapower

Master (133)

pizzapower's picture

16-10-2022, 21:44

My tiles are simple, so I could use them preallocated too. The problems seems to be that update_tiles() and update_map() are not fast enough, even though it runs right after the vsync. Maybe if I use ei and di between them I could stop the VDP from updating itself?

By thegeps

Paragon (1156)

thegeps's picture

17-10-2022, 12:13

Can't you use an inline asm routine? If you have preallocated tiles it is very trivial to do. Hope you are using a RAM buffer fornthe nametable and copying all the data in one go...
(Need the tiles' frames to be consecutive, I'm supposing you are scrolling down. Not tested, just written on my smartphone XD)

     Ld  hl,videobuffer
     Ld a,(frame_counter)    ;should be 1 atvthe beginning
     And a
     Jp z,shift_whole_screen
     Ld b,0
update_buffer1:
     Inc (hl)
     Inc hl
     Djnz update_buffer1
update_buffer2:
     Inc (hl)
     Inc hl
     Djnz update_buffer2
update_buffer3:
     Inc (hl)
     Inc hl
     Djnz update_buffer3
     Inc a
     And 7
     Ld (frame_counter),a
     Jp to_screen
shift_whole_screen:
     Ld b,0
reset_block1:
     Ld a,(hl)
     Add a,-7
     Ld (hl),a
     Inc hl
     Djnz reset_block1
reset_block2:
     Ld a,(hl)
     Add a,-7
     Ld (hl),a
     Inc hl
     Djnz reset_block2
     Ld b,224  ;you don't need to update last 32 bytes
reset_block3:
     Ld a,(hl)
     Add a,-7
     Ld (hl),a
     Inc hl
     Djnz reset_block3
     Ld hl,videobuffer+735
     Ld de,videobuffer+767
     Ld bc,736
     Lddr    ;can be unrolling optimized

     ;update your screen first line here

     Ld a,1
     Ld (frame_counter),a
To screen:

If videobuffer is aligned you can gain some cycles using "inc l" instead of "inc hl" in update loop and inserting "inc h" inbetween the loops themselves

By thegeps

Paragon (1156)

thegeps's picture

17-10-2022, 12:14

To screen: routine copy in one go the videobuffer to vram, of course. Tell me if you need the asm code to do so

By santiontanon

Paragon (1735)

santiontanon's picture

17-10-2022, 14:03

How many bytes do "update_tiles" and "update_map" copy to the VDP? VBLANK is short, so, if you are expecting to change lots of tiles during that period, you might not have enough time for it...

By albs_br

Champion (467)

albs_br's picture

17-10-2022, 14:26

It looks like you are not waiting Vblank. Update VRAM out of Vblank lead to strange behaviours, such as flickering.

Example of Vblank sync'ed logic in C language:

void GameLoop() {

  while(!gameOver) {

    word lastJiffy = JIFFY;
    //d_value = 0;
    while (lastJiffy == JIFFY) {
      //d_value++;
    }
    // Game loop sync'ed at 60/50 Hz starts here

  
}

From Arya: https://github.com/albs-br/arya/blob/main/src/GameLogic.h

By ro

Scribe (4867)

ro's picture

17-10-2022, 15:28

"flickering".. what do you mean? Could be that your copy process is somewhere around the screen build up trace shizl perhaps? More in line of what albs_br said. Does your playfield update fit in one screen refresh frame?

Futher more, geps, wouldn't this be faster?

     Ld bc,-7  ;c=-7, b=0
reset_block1:
     Ld a,(hl)
     Add a,c
     Ld (hl),a
     Inc hl
     Ld a,(hl)
     Add a,c
     Ld (hl),a
     Inc hl
     Djnz reset_block1

You know, doing 512 shifts in one go
but, perhaps this one's out of context. Smile I know assembly when I see it haha

By pizzapower

Master (133)

pizzapower's picture

17-10-2022, 17:13

santiontanon wrote:

How many bytes do "update_tiles" and "update_map" copy to the VDP? VBLANK is short, so, if you are expecting to change lots of tiles during that period, you might not have enough time for it...

I tried making it use the least amount of resources possible. The screen contains a maze made of a single 8x8 block, so I change 3 tiles each frame to create the scrolling effect. The tile at the top that the 8x8 block is being drawn into, a sliding tile in the middle and a tile at the bottom where the 8x8 block is moving out of. Two stacked blocks are made of 3 tiles and look like this:

A single 8x8 block on the screen is created by a blue and a red tile on top of each other.

By geijoenr

Champion (359)

geijoenr's picture

17-10-2022, 18:50

You need to wait for vsync before sending data to avoid flicker, for this just do EI and HALT at the beginning of the loop.

Then you have a limited amount of bytes you can send over during VBLANK, I think somebody measured the exact amount (maybe somewhere in here https://map.grauw.nl/articles/) which is different for 50Hz/60Hz but probably around 1-1.2KB?

If you update the VDP outside VBLANK you may see flicker or weird effects indeed.

By thegeps

Paragon (1156)

thegeps's picture

17-10-2022, 20:04

ro wrote:

"flickering".. what do you mean? Could be that your copy process is somewhere around the screen build up trace shizl perhaps? More in line of what albs_br said. Does your playfield update fit in one screen refresh frame?

Futher more, geps, wouldn't this be faster?

     Ld bc,-7  ;c=-7, b=0
reset_block1:
     Ld a,(hl)
     Add a,c
     Ld (hl),a
     Inc hl
     Ld a,(hl)
     Add a,c
     Ld (hl),a
     Inc hl
     Djnz reset_block1

You know, doing 512 shifts in one go
but, perhaps this one's out of context. Smile I know assembly when I see it haha

Yep, faster indeed Smile

Page 1/3
| 2 | 3