Understanding the examples: demo_seq

Hi!

I did not received my beamracer yet but this is a good time to train myself!
So I started to look in details at the demo_seq example which looks simple… only displaying an imagine using Display List and the sequenc

But only looks simple:)

A few questions,

1. S_BASE

From the docs, *[font=Courier New]S_BASE[/font] is the memory location where to fetch bitmap data from. *
So, it should point to the start of the logo data right ?

But in the code I see:

MOV    VREG_PBS_BASEL, <(mhl_logo - dl_start)
MOV    VREG_PBS_BASEH, >(mhl_logo - dl_start)

Why dl_start address should be subtracted to the logo address ?

2. S_PADDING

From the docs, S_PADDING contains a 16bits value added to the bitmap sequencer’s internal memory pointer at the end of every line.

What does it mean? At each rasterline, the sequencer skip n bytes. Is 1 byte representing a 8 pixels block ? Starting from the border ?
In the code it says:

- when end-of-line reached, continue to the next byte (no padding),
MOV    VREG_PBS_PADDINGL, 0
MOV    VREG_PBS_PADDINGH, 0

Continue to the next byte, which byte ? In the logo data ? is it to create a window in the logo’s data?

3. S_STEP

From the docs, [font=Courier New]S_STEP[/font] contains a 16bits value added to the bitmap sequencer’s internal memory pointer after every fetch.

In the code, I understand it increments the pointer of 1 byte, so I guess it means logo’s data will be written sequentially except if the step is different than 1 ? Right ?

[font=Courier New]; - fetch bytes from successive memory addresses,[/font]
[font=Courier New]MOV VREG_PBS_STEPL, 1[/font]
[font=Courier New]MOV VREG_PBS_STEPH, 0[/font]

So, same guess? Is it to write the logo’s data in a non contiguous manner (as I guess the step is not used while reading the logo’s data, only for writing)

4. PBS_CONTROL

I guess this register trigger the sequencer but I did not find in the docs how it works. Where can I find the role of each bit?

In the code:

[font=Courier New]; - apart from turning on the sequencer, we also request mirroring,[/font]
[font=Courier New]; because the logo is in .xbm format, which for some reason stores pixels[/font]
[font=Courier New]; in a byte using right-to-left order,[/font]
[font=Courier New]MOV VREG_PBS_CONTROL, 1 << PBS_CONTROL_ACTIVE_BIT | PBS_CONTROL_SWIZZLE_MIRROR[/font]

[font=Arial]In only found the values but not the meaning (I can guess some but)[/font]
[font=Courier New]PBS_CONTROL_ACTIVE_BIT = 3[/font]
[font=Courier New]PBS_CONTROL_RAMBANK_BIT = 0 ; bits 0-2[/font]
[font=Courier New]PBS_CONTROL_RAMBANK_MASK = (%111 << PBS_CONTROL_RAMBANK_BIT)[/font]
[font=Courier New]PBS_CONTROL_UPDATE_BIT = 4 ; bits 4-5[/font]
[font=Courier New]PBS_CONTROL_UPDATE_MASK = (%11 << PBS_CONTROL_UPDATE_BIT)[/font]
[font=Courier New]PBS_CONTROL_UPDATE_NONE = (%00 << PBS_CONTROL_UPDATE_BIT)[/font]
[font=Courier New]PBS_CONTROL_UPDATE_EOL = (%01 << PBS_CONTROL_UPDATE_BIT)[/font]
[font=Courier New]PBS_CONTROL_UPDATE_ALWAYS = (%10 << PBS_CONTROL_UPDATE_BIT)[/font]
[font=Courier New]PBS_CONTROL_SWIZZLE_BIT = 6 ; bits 6-7[/font]
[font=Courier New]PBS_CONTROL_SWIZZLE_MASK = (%11 << PBS_CONTROL_SWIZZLE_BIT)[/font]
[font=Courier New]PBS_CONTROL_SWIZZLE_NONE = (%00 << PBS_CONTROL_SWIZZLE_BIT)[/font]
[font=Courier New]PBS_CONTROL_SWIZZLE_MIRROR = (%01 << PBS_CONTROL_SWIZZLE_BIT)[/font]
[font=Courier New]PBS_CONTROL_SWIZZLE_MULTIMIRROR = (%10 << PBS_CONTROL_SWIZZLE_BIT)[/font]

[font=Courier New][font=Arial]Sorry for the dumb questions…[/font][/font]

The example’s linker configuration initially puts the display list data in the same segment as the code. So when the PRG is loaded into memory, the display list and logo are in regular C64 RAM, somewhere around location $880. To make them accessible to VASYL, they need to be copied to its local memory, and this is what happens in copy_and_activate_dlist. That procedure takes everything between labels dlist and **dlend **and copies it to the start of VASYL memory - address $0 and on. This means that whenever you are referring to a label in the local memory, you need to subtract the original starting address in C64 RAM, which happens to be **dl_start **(or dlist, which is the same).

Come to think of it, this could be more clearly done using a dedicated segment for VASYL data. Good thing the weekend is starting, expect updates to the repo soon. :slight_smile:

I will tackle the other questions tomorrow. Incidentally, this weekend we will also publish the “Sequencer Programming” section of the docs, which should make this topic much clearer.

Ah! It makes sense. I took the wrong assumption that S_BASEL was a pointer in the C64 memory and I did not notice the incbin was between the dl_start / dlend labels.
And yes defining segments for VASYL DL code and for data would be nice, at least for clarity.

Hurry to read the Sequencer docs!

Yes, one byte is 8 hires pixels or 4 multicolor ones, depending on the currently active graphics mode.

Sort of. Look at this image. If the logo data is placed sequentially in memory (as is in our case), there is nothing to skip over at the end of line - hence we set both lo and hi byte to zero. But you could as well place each line of the logo in its own memory page (to scroll it around, or to be able to compute lines’ starting addresses easily), and then you would like to instruct the sequencer to skip over empty regions at the end of a line, doing
[font=Courier New]
MOV[size=][font=Courier New] [/font][/size]VREG_PBS_PADDINGL, <(256 - logo_width_in_bytes)
MOV[size=][font=Courier New] [/font][/size]VREG_PBS_PADDINGH, >(256 - logo_width_in_bytes)

[/font]Or you could e.g. skip negative number of bytes, to the beginning of the line that just finished displaying (-29 in this case), and the line would be displayed again.

To clarify - in each cycle when the sequencer is active, the logo data is being *read *(or fetched) from the memory, to be immediately handed over to VIC. You could say that it is also being *written *(to VIC’s bus), but I just want to make sure we are talking about the same thing.

As for S_STEP, yes, if data is sequential in memory (the typical case), the step is going to be 1 (again, see the picture). However, being able to change the fetching order can be helpful in creating visual effects, mirror and upside-down being the two demonstrated by the example code.

Have you looked at the register description document? We realize it is not super detailed, but the sequencer document is coming along nicely, we’re still planning it for this weekend (California time).

Also, all examples have been updated to keep VASYL data in its own segment, which simplified address references in display lists, and in general looks nicer. Thanks for helping improve the BeamRacer!

Thanks! Now it really make sense.
Yes I saw that you updated the examples yesterday, clearer now with the memory segment!

Padding, swizzling, steps can be useful yes.
But thinking of effects I could achieve (mirroring, reversing, interlacing,…) I was wondering if a register which takes any pointer in local memory as a look-up table would not more generic and useful. Each value of the lut would be an address (or index) in the local bitmap data that the PBS would follow to select which byte to write.

Is it a dumb idea ? Probably :smiley: I need to experiment more with the current capabilities (damn Poland is far !!! I’m so hurry!)

About the [font=Courier New]PBS_CONTROL[/font] register, my bad, my brains are so lazy that the fact the bits description are organized in the table like the next registers, I just skipped them… shame on me. The description was good.

Sure, you could do that, but then a) everyone would have to set up look-up tables in order to display an image, b) more memory bandwidth would be needed to handle an extra level of indirection, even if it is not used for anything.

Of course, if you really need the flexibility, it is there - that’s what display lists are for:

[size=][size=][size=][size=][size=][size=][font=Courier New] [/font][/size][/size][/size][/size][/size][/size][font=Courier New]MOV VREG_ADR0L, <ptr_table[/font]
[font=Courier New][size=][size=][size=][size=][size=] [/size][/size][/size][/size][/size]MOV VREG_ADR0H, >ptr_table[/font]
[font=Courier New][size=][size=][size=][size=][size=] [/size][/size][/size][/size][/size]MOV VREG_STEP0, 1[/font]
[font=Courier New][size=][size=][size=][size=][size=] [/size][/size][/size][/size][/size]SETA ptr_count - 1[/font]
[size=][size=][size=][font=Courier New] WAIT start_line, 0[/font][/size][/size][/size]
[size=][size=][size=][font=Courier New]loop:[/font][/size][/size][/size]
[size=][size=][size=][font=Courier New] XFER VREG_PBS_BASEL, (0)[/font][/size][/size][/size]
[size=][size=][size=][font=Courier New][size=][size=][size=][size=][size=][size=] XFER VREG_PBS_BASEH, (0)[/size][/size][/size][/size][/size][/size][/size][/size][/size][/font]
[size=][size=][size=][size=][size=][size=][size=][size=][size=][font=Courier New] DELAYV 1[/font][/size][/size][/size][/size][/size][/size][/size][/size][/size]
[size=][size=][size=][size=][size=][size=][size=][size=][size=][font=Courier New] DECA[/font][/size][/size][/size][/size][/size][/size][/size][/size][/size]
[size=][size=][size=][size=][size=][size=][size=][size=][size=][font=Courier New] BRA loop[/font][/size][/size][/size][/size][/size][/size][/size][/size][/size]

[size=][size=][size=][size=][size=][size=][size=][size=][size=][font=Courier New][size=][font=Tahoma, Verdana, Arial, sans-serif]This snippet will repeatedly read data from ‘‘ptr_table’’ and use it [size=][font=Tahoma, Verdana, Arial, sans-serif]at the beginning of every line [/font][/size][/size][/size][/size][/size][/size][/size][/size][/size][/size][/size]to initialize the bitmap pointer.[/font][/font]