News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_redbox

Using the ASIC for Pallete and Split Screen

Started by redbox, 01:27, 18 January 10

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

redbox

I have been trying out using some Plus features for my demo with help from code at CPCtech and CPCRulez, but am having a few problems.

For example, if I setup the colour pallete in MODE 0 as the following:


;Setup CPC+ screen colours

org &8000 ;must not be between &4000 and &7FFF

start: di ;unlock ASIC
ld b,&bc
ld hl,sequence
ld e,17
seq: ld a,(hl)
out (c),a
inc hl
dec e
jr nz,seq
ei

ld bc,&7fb8 ;page-in ASIC registers to &4000-&7FFF
out (c),c

ld hl,colours ;copy colours into ASIC palette registers
ld de,&6400
ld bc,17*2
ldir

ld bc,&7fa0 ;page-out asic registers
out (c),c

jr start

;two bytes per colour.
;format xGRB

.colours
defw &0000 ; colour for pen 0
defw &0111 ; colour for pen 1
defw &0222 ; colour for pen 2
defw &0333 ; colour for pen 3
defw &0444 ; colour for pen 4
defw &0555 ; colour for pen 5
defw &0666 ; colour for pen 6
defw &0777 ; colour for pen 7
defw &0888 ; colour for pen 8
defw &0999 ; colour for pen 9
defw &0AAA ; colour for pen 10
defw &0BBB ; colour for pen 11
defw &0CCC ; colour for pen 12
defw &0DDD ; colour for pen 13
defw &0EEE ; colour for pen 14
defw &0FFF ; colour for pen 15
defw &0000 ; colour for border

;unlock ASIC sequence

.sequence
defb &ff,&00,&ff,&77,&b3,&51,&a8,&d4,&62,&39,&9c,&46,&2b,&15,&8a,&cd,&ee


...it works fine as long as I loop back (jr start) and keep on repeating the code.  However, if I set it up once and then do something else then it resets and reverts to the normal CPC colours.  Do you have to keep refreshing the ASIC registers or can you set it up once and leave it?

Also, I was looking at the split screen (rupture) feature of the CPC+ and got it working.  But I can't believe there is no ASIC register to set the screen mode up for the split (so you can have for example MODE 0 at the top and MODE 1 at the bottom) - does this mean you still need to time it yourself in the frame flyback and still OUT the mode you want via 7FXX to the CRTC like on a normal CPC...?!

Grim

#1
Your ASIC palette does not last because the firmware periodically (speed ink delays) updates the palette too (while the framefly back).

If you do not need the firmware facilities, simply kill it's interrupt service routine (put EI:RET at &0038) and you're done. Otherwise you can cheat some of it's internal variable so that it stops updating the palette. This can be done with eg. a frame flyback event:


;Setup CPC+ screen colours

org &8000 ;must not be between &4000 and &7FFF

start: di ;unlock ASIC
ld b,&bc
ld hl,sequence
ld e,17
seq: ld a,(hl)
out (c),a
inc hl
dec e
jr nz,seq
ei


; Setup a frame flyback event to prevent
; the firmware from updating the colours
ld hl,data_inklocker
        ld b,%10000001
        ld c,0
        ld de,inklocker
        call &bcd7 ; KL NEW FRAME FLY


ld bc,&7fb8 ;page-in ASIC registers to &4000-&7FFF
out (c),c

ld hl,colours ;copy colours into ASIC palette registers
ld de,&6400
ld bc,17*2
ldir

ld bc,&7fa0 ;page-out asic registers
out (c),c

ret
;jr start


; this routine will be called by the firmware on every frame flyback
; The trickery at &B7F8 only works with Firmware v2+
inklocker
ld a,&FF ; continually resets an internal
ld (&B7F8),a ; speedink counter so that the
ret ; kernel never updates the colours

;two bytes per colour.
;format xGRB

.colours
defw &0000 ; colour for pen 0
defw &0111 ; colour for pen 1
defw &0222 ; colour for pen 2
defw &0333 ; colour for pen 3
defw &0444 ; colour for pen 4
defw &0555 ; colour for pen 5
defw &0666 ; colour for pen 6
defw &0777 ; colour for pen 7
defw &0888 ; colour for pen 8
defw &0999 ; colour for pen 9
defw &0AAA ; colour for pen 10
defw &0BBB ; colour for pen 11
defw &0CCC ; colour for pen 12
defw &0DDD ; colour for pen 13
defw &0EEE ; colour for pen 14
defw &0FFF ; colour for pen 15
defw &0000 ; colour for border

;unlock ASIC sequence

.sequence
defb &ff,&00,&ff,&77,&b3,&51,&a8,&d4,&62,&39,&9c,&46,&2b,&15,&8a,&cd,&ee

;event block data
.data_inklocker
ds 9,0


Quote[...] does this mean you still need to time it yourself in the frame flyback [...]

Indeed there's no ASIC facility for the screen-mode. However, you can use the programmable raster interrupt to do that easily.


redbox

Quote from: Grim on 03:28, 18 January 10
If you do not need the firmware facilities, simply kill it's interrupt service routine (put EI:RET at &0038) and you're done.

Thanks Grim - I'm not using the firmware so I killed the interrupt (using DI:RET) at &0038:


        org &8000

ld a,&F3 ;kill interupt so it doesn't mess with ASIC settings
ld (&0038),a ;puts DI, RET at 0038h
ld a,&C9
ld (&0039),a
        ....


Quote from: Grim on 03:28, 18 January 10
Indeed there's no ASIC facility for the screen-mode. However, you can use the programmable raster interrupt to do that easily.

Yes, I see from CPCRulez that there is a programmable interrupt at &6800 in the ASIC (http://cpcrulez.fr/coding_cpcplus48.htm) and some explanation of it too (http://cpcrulez.fr/coding_cpcplus47.htm) but I don't understand it because my french is not good at all, I'm afraid  :(

I want to be able to split the screen so the first 22 rows are MODE 0 and the bottom 3 rows are MODE 1.  I was going to use the CPC+ split screen at line 176 and use it to set the mode, but now I know it's not possible.

Can you show me how to do it with the ASIC interrupt?



fano

#3
Quote from: redbox on 05:32, 18 January 10I was going to use the CPC+ split screen at line 176 and use it to set the mode, but now I know it's not possible.
Why is it not possible ? you can use PRogrammable Interrupts to create an interrupt at line 176-1 , wait interrupt w/ HALT and change to mode 1.
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

redbox

Quote from: fano on 07:33, 18 January 10
Why is it not possible ? you can use PRogrammable Interrupts to create an interrupt at line 176-1 , wait interrupt w/ HALT and change to mode 1.

Yes, this is what I want to do, but don't know how. Can you give me an example of the code?

Grim

#5
I added split-screen/mode features to your source code example.

There's a very important thing to take care of when paging-in/out the ASIC bank within an interrupt service routine, which is to know how to restore the ASIC bank to it's original state (paged in/out) when the ISR finishes.

For example: the main program is happily poking into the ASIC registers when an interrupt occurs. The ISR does it's stuff and page-out the ASIC bank on exit. When returning to the main program, it will start poking into regular RAM instead of the ASIC registers! Ooops!

To avoid this problem, when the main program page-in/out the ASIC bank it must also set a flag somewhere so that the ISR knows which state to restore (paged-in/out). See the asic_pagein, asic_pageout and asic_pageres routines in the example below.



;Setup CPC+ screen colours

org &8000 ;must not be between &4000 and &7FFF

cnf_splitline equ 20*8

start: di
im 1 ; setup the IM1 ISR
ld a,&C3
ld hl,isr_screenmode
ld (&38),a
ld (&39),hl


ld b,&bc ;unlock ASIC
ld hl,sequence
ld e,17
seq: ld a,(hl)
out (c),a
inc hl
dec e
jr nz,seq

call asic_pagein ;page-in ASIC registers to &4000-&7FFF

ld hl,colours ;copy colours into ASIC palette registers
ld de,&6400
ld bc,17*2
ldir

ld a,cnf_splitline
ld (&6800),a ; set the raster interrupt scanline (PRI)
ld (&6801),a ; set the splitscreen scanline (SPLT)
ld hl,&0030 ; set the splitscreen address (SSA) for the bottom 3 rows
ld (&6802),hl ; (caution => SSA is a 16bit big endian register!!!)

call asic_pageout ;page-out asic registers
ei

; scramble the main screen offset
ld bc,&BC0D
out (c),c
inc b
scramble
inc c
out (c),c
jr scramble


isr_screenmode:
push af ; save all CPU registers
push bc ; modified by the ISR

ld bc,&7FB8 ; page-in ASIC registers
out (c),c

ld a,cnf_splitline-1
var_pri equ $-1
xor cnf_splitline-1 XOR 220 ; switch PRI between 175 and 220
ld (&6800),a ; set the raster interrupt scanline
ld (var_pri),a

sub 220 ; switch screenmode
ld a,&8D
sbc a,0
out (c),a

call asic_pageres ; restore the RMR2 to it's previous state.

pop bc ; restore CPU register
pop af
ei ; and exit
ret


asic_pagein: ; page-in ASIC registers
ld bc,&7FB8
jr asic_pageset
asic_pageout: ; page-out ASIC registers
ld bc,&7FA0

; Input
;  BC = &7F00 + RMR2 value
asic_pageset: ; set custom RMR2 value
ld (asic_pageres+1),bc ; save the RMR2 value

asic_pageres:
ld bc,0 ; restore the saved RMR2
out (c),c
ret


;two bytes per colour.
;format xGRB

.colours
defw &0000 ; colour for pen 0
defw &0664 ; colour for pen 1
defw &0222 ; colour for pen 2
defw &0333 ; colour for pen 3
defw &0444 ; colour for pen 4
defw &0555 ; colour for pen 5
defw &0666 ; colour for pen 6
defw &0777 ; colour for pen 7
defw &0888 ; colour for pen 8
defw &0999 ; colour for pen 9
defw &0AAA ; colour for pen 10
defw &0BBB ; colour for pen 11
defw &0CCC ; colour for pen 12
defw &0DDD ; colour for pen 13
defw &0EEE ; colour for pen 14
defw &0FFF ; colour for pen 15
defw &0000 ; colour for border

;unlock ASIC sequence

.sequence
defb &ff,&00,&ff,&77,&b3,&51,&a8,&d4,&62,&39,&9c,&46,&2b,&15,&8a,&cd,&ee


sorry for the fuzzy or lack of explanations, I'm completely off, need to sleep now :)

redbox

Quote from: Grim on 08:11, 18 January 10
I added split-screen/mode features to your source code example.

That's great and thanks for the explanation Grim.

One problem - when I assemble and run the code example under WinAPE the bottom part of the screen (MODE 1) is static but the top half (MODE 0) jumps around all over the place.  It would appear that the code to scramble the main screen offset is being called all the time when it shouldn't be...?

Grim

I just added the scramble routine to get some action going on the screen and see that the splitscreen at the bottom is working properly (it is not affected). Of course, you should synchronize the changes applied to the main screen (and/or splitscreen) offset with the VSync somehow, but that is left to you :)

redbox

Quote from: Grim on 16:28, 20 January 10
I just added the scramble routine to get some action going on the screen and see that the splitscreen at the bottom is working properly (it is not affected). Of course, you should synchronize the changes applied to the main screen (and/or splitscreen) offset with the VSync somehow, but that is left to you :)

Ah ok, thanks Grim for your help, I will have a play with the code and see what I come up with  :)

Trebmint

Can I just ask if any ASIC coder knows anything about the soft scroll, cos in the manual it says the soft scroll effects the whole screen. From this and a bit of my memory back doing fluff and smart + back when I seem to recall this means that it can't be set via the line interrupt and therefore everything on the screen is offset by the soft scroll settings whateve you do. Makes doing score panels etc difficult

Would the only around this be in say Mode 0 to have 4 pixel shifted versions of the panel, and adjust the screen address on the interrupt up or down &800 depending on the vertical softscroll setting?

Anyone

redbox

Quote from: Trebmint on 19:47, 11 February 10
Can I just ask if any ASIC coder knows anything about the soft scroll, cos in the manual it says the soft scroll effects the whole screen. From this and a bit of my memory back doing fluff and smart + back when I seem to recall this means that it can't be set via the line interrupt and therefore everything on the screen is offset by the soft scroll settings whateve you do. Makes doing score panels etc difficult

Yep.  I've been writing a scroller and it does scroll the whole screen regardless of the interupt/split.  I've also been debating what to do about the score panel and have so far settled on a hardware sprite for energy/score because they stay in the same place without you having to do anything...

Quote from: Trebmint on 19:47, 11 February 10
Would the only around this be in say Mode 0 to have 4 pixel shifted versions of the panel, and adjust the screen address on the interrupt up or down &800 depending on the vertical softscroll setting?

Not tried this myself, but I will give it a go now you've mentioned it  8)

Trebmint

Oh thats a really stupid feature then, especially given the lack of sprites and the time it takes to fill them. Glad to have given you an idea, but it's a waste of good memory isn't. Could you use that a combination of crtc register 3? to shift a byte and therefore only do 2 copies. Perhaps thats pushing it.
Also since you're already writing this routine, perhaps you could make the code universal with a mapping format. We could then all use a few simple function calls to pixel perfect scrolling. Would simplfy writing a game immensly.


Axelay

Not having a plus, I wasnt able to try anything on real hardware, but I did play with the soft scroll in Winape a while ago.  What seemed to work was to set up the programmable interrupt to match the screen split, set the soft scroll at the start of the frame and have the code do what ever it needs to do in the time available before the split.  Then halt to wait for the interrupt, and set the soft scroll variable a second time, giving a static score line.  I didnt take it any further at the time, but perhaps it might even be possible make that second soft scroll setting under interrupt, doing away with the need for the halt.

arnoldemu

#13
Quote from: Trebmint on 19:47, 11 February 10
Can I just ask if any ASIC coder knows anything about the soft scroll, cos in the manual it says the soft scroll effects the whole screen. From this and a bit of my memory back doing fluff and smart + back when I seem to recall this means that it can't be set via the line interrupt and therefore everything on the screen is offset by the soft scroll settings whateve you do. Makes doing score panels etc difficult

Would the only around this be in say Mode 0 to have 4 pixel shifted versions of the panel, and adjust the screen address on the interrupt up or down &800 depending on the vertical softscroll setting?

Anyone
It can actually affect just part of the screen. If you set a pixel offset and then set it back to 0 some cycles later, then part of the screen will scroll.

Especially when considering vertical scroll.

I've tested this.

So it should be possible to re-program it on a screen split and give you a static panel.

I think Copter271 does this for vertical scroll.

The thing to be careful with is setting the pixel scroll to be the same as the pixel size of the mode. If you don't do that you can get some weird pixel stretching going on. I've not discovered exactly what is happening here so I can't say exactly what you'll see.
I just remember scrolling a mode 0 screen in mode 2 pixel increments and seeing the pixels kind of stretch or like they were dragging. A bit difficult to explain.


EDIT: You'll still need to do what Axelay suggests. You'll need to setup a raster int. But then you can hook the code into your interrupt handler and get it to set it there. So you don't really need the HALT. Just keep track of which raster interrupt your handling and you'll be cool.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

redbox

#14
Quote from: Trebmint on 22:26, 11 February 10
Also since you're already writing this routine, perhaps you could make the code universal with a mapping format. We could then all use a few simple function calls to pixel perfect scrolling. Would simplfy writing a game immensly.

With my scroll I stretched the screen to 50 chars wide so that 48 were visible and 1 char is left either side of the screen to draw to.  The mapping and calculating of screen addresses is then done by the routine that prints the background, and I'm currently re-writing this routine so that it draws the background from tiles that can be re-used throughout the game level.  I might well make a CPC tile mapper utility too so that I can use it again and other people can design levels etc.

At present, my code scrolls the screen perfectly using the hardware pixel scroll and I've got the hardware sprite animated.  All of the routines haven't been optimised yet but I just wanted to get it working...  :)

I've attached a DSK image here so you can download it and see what I've done (and of course, it looks cooler on a real Plus machine  8) ).  Use RUN"DISC to load and then CURSOR RIGHT to scroll the screen and animate the monkey.

Quote from: arnoldemu on 11:35, 12 February 10
EDIT: You'll still need to do what Axelay suggests. You'll need to setup a raster int. But then you can hook the code into your interrupt handler and get it to set it there. So you don't really need the HALT. Just keep track of which raster interrupt your handling and you'll be cool.

This is a good idea and I'll give it a go as I have a lot of the raster interrupt code from my demo  :D

Trebmint

That looks so cool. Great stuff.

Hmmm, now if we had a function that allowed you to say just set the scroll address in two 2 16 bit values for the X and Y of top left of the scroll, and it automatically updated updated the screen from the old value, so the routine would fill in any part necessary, so you could shift just a pixel or even have the entire screen redrawn.

With that and an editor erm well thats half way to game creation tool.

redbox

#16
Quote from: Trebmint on 19:03, 12 February 10
Hmmm, now if we had a function that allowed you to say just set the scroll address in two 2 16 bit values for the X and Y of top left of the scroll, and it automatically updated updated the screen from the old value, so the routine would fill in any part necessary, so you could shift just a pixel or even have the entire screen redrawn.

The way I did it was to get the far right top line screen address, print the next part of the background and increase the screen address to print to by one byte.  Then when the screen address reaches &C800 (i.e. the next pixel line down on the display) after scrolling, reset it.  This is because the hardware scroll wraps the screen around when scrolling and you need to offset this.  It's not much of a problem though because the screen has to be drawn on the right when you scroll anyway.

You can then easily calculate the top left screen address (using the same method as above) and then convert x and y to an address anywhere on the screen using one of the methods Grim and Arnoldemu suggested in this thread.

Not sure why you would need to re-draw the whole screen with this type of scroller though?

Axelay

Looks great!  That monkey sprite reminds me of Toki, a game I played a fair bit on my brothers Amiga.  Are you looking to make it scroll vertically as well, or sticking with horizontal scrolling?

redbox

Quote from: Axelay on 01:54, 14 February 10
Looks great!  That monkey sprite reminds me of Toki, a game I played a fair bit on my brothers Amiga.  Are you looking to make it scroll vertically as well, or sticking with horizontal scrolling?

Thanks - the graphics are imported from the Atari ST version of Magic Pockets, but I'm not looking to do a re-make, more of a 'spin-off' if you see what I mean  :)

I was going to do horizontal scrolling only when starting out (just to get it working really) but, the more I think about it, vertical scrolling as well would make the routines a lot more useful and make it look better.  Also, I was worrying about the overhead, but the actual scroll routine is fast and adaptable because of the hardware handling so I should be worrying more about the slow background printing routine really  :o

Executioner

i know Kev has already answered this. You can set the soft-scroll register at ANY time during ANY scan line and it will only affect those pixels drawn during that time. It is therefore possible to soft-scroll a small rectangle in the middle of the screen if you really wanted to do that. My Frogger game individually soft-scrolls each 16 pixel high row of river or road using soft-scroll and hardware splitting about 14 times during each frame.

redbox

Quote from: Executioner on 01:55, 16 February 10
You can set the soft-scroll register at ANY time during ANY scan line and it will only affect those pixels drawn during that time.

This is good to know. 

Only reason I said I thought it was not possible is because in the Arnold V Specification it states "This soft scrolling mechanism affects the whole of the main screen, regardless of the split screen facility, but it does not affect sprites".  They obviously didn't know about the true capabilities of the machine, which is also evident when reading the source code comments in the RP11 Diagnostic Rom Cartridge.

Trebmint

Quote from: Executioner on 01:55, 16 February 10
i know Kev has already answered this. You can set the soft-scroll register at ANY time during ANY scan line and it will only affect those pixels drawn during that time. It is therefore possible to soft-scroll a small rectangle in the middle of the screen if you really wanted to do that. My Frogger game individually soft-scrolls each 16 pixel high row of river or road using soft-scroll and hardware splitting about 14 times during each frame.

Oh blimey I wish I knew that years ago. Will do so experiments with this now I think. CPC Plus rulez

Ast

@redbox :


Hi, i just want to know more about your project ? Is your game finished now ? Can you tell us more about it ? CAN  see any preview ? Thanks.
_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

ralferoo

Quote from: Grim on 03:28, 18 January 10
If you do not need the firmware facilities, simply kill it's interrupt service routine (put EI:RET at &0038) and you're done. Otherwise you can cheat some of it's internal variable so that it stops updating the palette. This can be done with eg. a frame flyback event [...]
You don't actually need to do any of that for the the video mode (although you do for palette etc).

B' always contains &7F, C' contains the current gate array settings, which includes mode and ROM settings. So, you just need to put the correct mode bits into BC' and the screen mode will stay correct even through interrupts and firmware calls.

fgbrain

The info shared above proved extremely useful to my attempt to code something on 6128 plus.

It should be included in the wiki pages for future reference...


BUT I got another question:

OK we have the split screens scroll independently - all working fine, but what to do about the hardware sprites that overlap with parts of screen which is static (say a HUD) ?
Is there a way to force sprites to appear only in the main screen?

I suspect to use CRTC Reg6 but it doesn't work..
_____

6128 (UK keyboard, Crtc type 0/2), 6128+ (UK keyboard), 3.5" and 5.25" drives, Reset switch and Digiblaster (selfmade), Inicron Romram box, Bryce Megaflash, SVideo & PS/2 mouse, , Magnum Lightgun, X-MEM, X4 Board, C4CPC, Multiface2 X4, RTC X4 and Gotek USB Floppy emulator.

Powered by SMFPacks Menu Editor Mod