News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

Shifting the screen display 1-line vertically...

Started by ssr86, 19:50, 11 December 13

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ssr86

Out of curiosity...
Is it possible to manipulate the crtc registers to display the screen shifted one-line vertically or you can only shift the screen?
Something similar to what the r3 does horizonatally when using mode0.

What I hoped for is that...
It is possible to display the screen as in Wolfenstrad - every second line is border. Is it possible to display this screen one line lower every second frame  to get a flickery screen but "without" the blank lines?



TFM

You can do:


- Move the whole screen up and down one scanline


- Program the CRTC in a way that one text line does consist out of only one scanline (not 8 like usual). The regular scroll works for you.

TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

redbox

You can scroll the screen vertically using CRTC register 5.  A good example is Mission Genocide.

You can also interlace the CPC screen as seen in many demos.

Not sure about combining the two effects though.

ssr86

I wanted to display the same 160x100 screen in the "thick scanlines mode" normally during odd frames and shifted one scanline down (the entire display on the monitor so I think that's not exactly scrolling...) during the even frames for a 160x100 flickering mode with pixels of double height.

Doesn't setting R9=0 (characters 1 line high) limit the possible vertical resolution too much?

ssr86

Quote from: Executioner on 23:37, 08 May 12
I didn't know about this one. Lots of demos use R9=0, and yes, most emulators do support it as far as I know. The problem with R9=0 is you can only use 1/8th of memory for the screen, and it's always the first 2K of each 16K block. Even using a 32K addressing trick and 64 byte screen width you're limited to a 64 line screen (or 128 if you do a split in the middle and use 8K of memory, one lot of 2K in each 16K block). It can be done if you're using Interrupt Mode 2.

So R9=0 limits the screen to 64 lines but with splitting one could get 128 lines which is how many I would need. But the video memory organisation becomes not very friendly... Is it possible to simpllify it?

arnoldemu

Quote from: ssr86 on 15:09, 12 December 13
So R9=0 limits the screen to 64 lines but with splitting one could get 128 lines which is how many I would need. But the video memory organisation becomes not very friendly... Is it possible to simpllify it?
With R9=0, to get 128 lines you need to set R4 to 128. The counter goes from 0 to 127.
I think he's saying that that can be continuous if you use the r12/r13 overscan trick. (This means partial usage of 2 x 16K blcoks)

To get 256 lines you'll need to repeat this and partial usage of 4 x 16K blocks. You need to use splitting to make this work, and then you'll need to setup another block to make it 312 lines total.

I may be able to make a test program that can show this.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

I started to write a program to show a 256 line screen using R9=0 but then hit a problem quickly.
I would need to use rupture/splitting to make the effect. 52 lines per interrupt, 256 is not exactly divisible by 52. So we must burn some cpu time to get to the correct place to perform the changes. Not good. So It may be possible to split it so it is divisible by 52, then we don't need to worry now and we burn much less cycles.
I think it depends on the time it takes to maintain this screen compared to the time you win for sprites.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

ralferoo

Quote from: arnoldemu on 21:18, 12 December 13
I started to write a program to show a 256 line screen using R9=0 but then hit a problem quickly.
I would need to use rupture/splitting to make the effect. 52 lines per interrupt, 256 is not exactly divisible by 52.
I might be misunderstanding what you're actually trying to achieve, but even if you're going for 256 visible lines, you still need a 312 line screen or the monitor won't be running at 50Hz. 312 of course is 52*6.

Quote
So we must burn some cpu time to get to the correct place to perform the changes. Not good. So It may be possible to split it so it is divisible by 52, then we don't need to worry now and we burn much less cycles.
The 2nd interrupt after VSYNC is just inside the visible area, it's almost ideal for a 256 line display.

For my demo, I logically had 3 "frames" every frame, each 104 lines long. For the first 2, I set the VSYNC to occur after line 105 (so it never happened), changing this to about 70ish on the last 3rd. Also, you want to change the R12/R13 for the start address before each third.

Because you're doing thirds, you can change all these values every 2nd interrupt.

arnoldemu

Quote from: ralferoo on 22:15, 12 December 13
I might be misunderstanding what you're actually trying to achieve, but even if you're going for 256 visible lines, you still need a 312 line screen or the monitor won't be running at 50Hz. 312 of course is 52*6.
The 2nd interrupt after VSYNC is just inside the visible area, it's almost ideal for a 256 line display.

For my demo, I logically had 3 "frames" every frame, each 104 lines long. For the first 2, I set the VSYNC to occur after line 105 (so it never happened), changing this to about 70ish on the last 3rd. Also, you want to change the R12/R13 for the start address before each third.

Because you're doing thirds, you can change all these values every 2nd interrupt.
no probs.

I am trying to achieve a 256 line visible screen area with R9=0, R4 = 127, using R12/R13 overscan trick so it doesn't repeat.

Because of the R4 limit to 127, I have to make 2 sections each 128 lines each.

After both of these is a section which is normal (R9=7) where the vsync will also be triggered and to make up to 312 lines for a correct 50hz screen.

The idea being that it's potentially better for sprites.

I've worked out one method, but 52 doesn't fit well into 128 ;) So I am forced to burn time until the vertical counter resets to 0, then it's safe to make my changes.
I'm just working out the best method to do this that will fit into games and not burn much cpu time. Normally some time is burnt to get to the correct safe place to change the registers.

My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

ralferoo

Quote from: arnoldemu on 10:32, 13 December 13
I've worked out one method, but 52 doesn't fit well into 128 ;) So I am forced to burn time until the vertical counter resets to 0, then it's safe to make my changes.
I'm just working out the best method to do this that will fit into games and not burn much cpu time. Normally some time is burnt to get to the correct safe place to change the registers.
One observation is that 260 divides pretty well by 52, so you might want to consider that.

Quote from: arnoldemu on 10:32, 13 December 13
I am trying to achieve a 256 line visible screen area with R9=0, R4 = 127, using R12/R13 overscan trick so it doesn't repeat.
With R9=0, you'll only be using the first 2KB of every 16KB block, so a maximum of 8KB for the entire screen. If you want 256 visible lines, that's only 16 characters wide.

So, I'm presuming you're also planning to do the alternating long/normal R1 trick to make lines repeat and get extra thick lines. In this case you'll be cycle counting your main loop reasonable accurately, so doing the other CRTC registers at any particular line shouldn't be much harder.

Much more importantly, you'll need to bear in mind that to the right of the normal screen edge, you'll get alternate lines of display, so it'll look something like:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD

The only way to solve this really is to make the display wider than you really need and have blanks. I found by experimentation that for 64 wides, 82 bytes wide works well if you offset the image so that each line starts with 18 empty bytes.

If you're using the full 64KB as screen space, you'll probably still want to use the interrupt vectors (at #38), so your available memory is #0040-#07ff, #4000-#47ff, #8000-#87ff, #c000-#c7ff, for a total of 8118 bytes. That makes a maximum of 99 thick lines if each line is 82 bytes wide, so 198 visible lines of nominally 32 characters.

And if you're pushing that to the limit, there no space for anything else, so there's no point changing back to 8 pixel lines per character, you might as well leave R9=0 for the duration... In Sugarlumps, I stuck to the top 32KB and used an 8-pixel per line screen at #4000 for the scrolltext.

ssr86

Quote from: ralferoo on 14:01, 13 December 13
So, I'm presuming you're also planning to do the alternating long/normal R1 trick to make lines repeat and get extra thick lines.

You can get doubled lines display on the cpc?
How does that work?

@Arnoldemu: How did your experiments end?

ralferoo

Quote from: ssr86 on 12:24, 23 December 14
You can get doubled lines display on the cpc?
How does that work?
The CRTC counters are checked for equality against registers not "greater than or equal to" as it's much easier to implement in hardware. So, if a counter never reaches the value, then the action that normally happens at that point never happens.

In this case, if the "width" of the screen (r3) is larger than the "horizontal total" (r0), the normal end-of line behaviour is subverted. However, you'll need to understand a bit more about how the CRTC works...

The primary counter is MA which represents the character offset from the start of the screen memory. Character line 0 starts at 0, line 1 at 40, line 2 at 80, etc... As you know, there are (usually) 8 pixels per character line, and this is counted using RA.

When the horizontal counter reaches the width, MA stops incrementing and if it's the last pixel line of the character (i.e. RA=r9) then MA is latched into a temporary register and this temporary register is used to reset MA at the start of each pixel line. This means that MA is restored to the correct place for the next pixel row or advances to the next line for the first pixel row of the next character row. This temporary register is initialised from r12/r13 during vertical blank.

So, if you have an extra wide line then this latch is never updated and so for the next character line MA is unchanged from the previous character line. You can couple this with 1-pixel high characters by setting r9 to 0 (although this can cause other problems). If you then change the "width" of the line (r1), you can restore the normal behaviour for 1 line to advance to the next line and then go back to the extra long lines to repeat the last line. You can use this to have arbitrarily thick lines (but only needed to write the data once) and a linear screen memory (it'd all be from C000-C7FF normally).

One of the problems of doing this include the fact that the vtotal (r4) is only 7-bit and so for a PAL screen you'd need to split the screen into 3 CRTC frames.

Take a look at the source for sugarlumps (ralferoo/sugarlumps · GitHub) which does this exact thing...

Powered by SMFPacks Menu Editor Mod