Recently I found an old note pad that I used to scribble ideas down for programming the Amstrad.
On the wiki there was a routine for fast compiled sprites:
LD HL,screen address
LD BC,#800+[most used byte]
LD DE,#C050
LD (HL),byte1:INC HL ;plot line 1
LD (HL),byte2:INC HL
LD (HL),C
LD A,H:ADD B:LD H,A
JR NC,line2
ADD HL,DE
.line2
LD (HL),byte6:DEC HL ;plot line 2
LD (HL),C :DEC HL
LD (HL),byte4
LD A,H:ADD B:LD H,A
JR NC,line3
ADD HL,DE
.line3
LD A,(HL):AND #55:OR byte7:LD (HL),A:INC HL ;plot line 3 (contains transparent areas)
LD (HL),byte8:INC HL
LD A,(HL):AND #AA:OR byte9:LD (HL),A
RET
This was pretty much the same as the one I did, except that I sacrificed 1024 bytes for a look up table to calculate the next line address which allowed the problem area for hardware scrolling to be dealt with ease. The reason why the table was 1024 bytes was that it catered for two screens worth of offsets that allowed for the wrapping of the hardware scroll. This was all designed for a Mission Genocide type of scroll so the problem area never caused a problem. So what I did was calculate which line you were on for the hardware scroll and load the Stack Pointer to that position and the code basically did this:
LD HL,Screen address
LD SP, Current line for sprite in offset table
LD BC, Most used bytes stored in B and C
LD (HL),byte1:INC L ;plot line 1
LD (HL),byte2:INC L
LD (HL),C
POP DE
ADD HL,DE
LD (HL),byte6:DEC L ;plot line 2
LD (HL),C :DEC L
LD (HL),B
LD A,H:ADD B:LD H,A
POP DE
ADD HL,DE
LD A,(HL):AND #55:OR byte7:LD (HL),A:INC L ;plot line 3 (contains transparent areas)
LD (HL),byte8:INC L
LD A,(HL):AND #AA:OR byte9:LD (HL),A
RET
I'm curious if there are any faster methods than this? By doing this I managed to get quite a lot of sprites on a vertical scrolling screen. From what I remember of the tech demo I did was that I never used interrupts and used Halt to time things up and basically raced the monitors Electron Beam when updating the sprites. The sprite updates started when the rupture happened at the bottom of the screen. Anyway all good fun remembering all this :)
Just edited the example I gave. Instead of INC HL I do INC L... I basically block copied the Wiki example and forgot to change that.
So was this a single pixel vertical scroll like Mission Genocide?
There was a recent thread on how many bullets/sprites could be achieved on a vertical shootem up, where Axelay did a nice little demo.
Did you get much further with your routine as I'm sure your input would be valuable.
How many bullets can be drawn on screen? (http://www.cpcwiki.eu/forum/games/how-many-bullets-can-be-drawn-on-screen/)
That thread was an interesting read... It's very hard to remember that far back. Basically when mission genocide was released I reversed engineered it to find out how it achieved vertical scrolling and got rid of the firmware stuff. Then I did my compiled sprite routines and had that working over the scrolling backdrop. Then I changed computers and never looked at it again until I found that note pad.
According to what I wrote in it I had plans to do a Uridium type of game but the scroll was vertical instead of horizontal. So the scroll would of catered for up and down movement. I had plans to use 16k for that look-up table, storage for the compiled sprites and the score panel. 16k used for the screen and the other 32k used for the rest of the game. I wanted to use all the palette for graphics to get a better look than the C64 graphics.
It's funny reading through all the Amstrad knowledge base now with all the different techniques discovered, so armed with this now I could probably do a better job than I did on that tech demo all those years ago. If only I could find time I would not mind doing that Uridium type of game now because it would prove the Amstrad CPC was a cool machine for the time and it would actually make the C64 look pale in comparison because the Amstrad would certainly have cooler graphics by using 16 colours and it would look arcade looking because of the portrait look of the scroll. But we can only dream :)
Speccy ports basically ruined the potential of the CPC.
@Andy Coates (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1717)
For mission genocide the "problem area" is never a problem it is always on the left and never moves from the left because the width of the screen (64 bytes) divides 2048 exactly and because the scrolling is always vertical. Quick sprite drawing is much less of a problem.
The problem is when the screen is scrolled horizontally more than a certain amount. So more a problem of continuous hardware horizontal scrolling. (Some games can avoid it by shrinking the height of the screen and limiting scrolling left and right). The problem shows up plotting each line of the sprite because potentially a line may or may not be on that problem area. The problem being when the byte to the right of &C7FF is not &C7FF+1, but &C000. It's a horizontal and not vertical problem.
Have you looked at a way to do compiled sprites that works with that?
Also your use of INC L only will not work with horizontally scrolled screens as far as I can tell.
Quote from: arnoldemu on 13:00, 05 April 16
@Andy Coates (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1717)
For mission genocide the "problem area" is never a problem it is always on the left and never moves from the left because the width of the screen (64 bytes) divides 2048 exactly and because the scrolling is always vertical. Quick sprite drawing is much less of a problem.
The problem is when the screen is scrolled horizontally more than a certain amount. So more a problem of continuous hardware horizontal scrolling. (Some games can avoid it by shrinking the height of the screen and limiting scrolling left and right). The problem shows up plotting each line of the sprite because potentially a line may or may not be on that problem area. The problem being when the byte to the right of &C7FF is not &C7FF+1, but &C000. It's a horizontal and not vertical problem.
Have you looked at a way to do compiled sprites that works with that?
Also your use of INC L only will not work with horizontally scrolled screens as far as I can tell.
Thanks ArnoldEmu :) This was all for a vertical scroll. What I meant for the problem area was that it catered for the wrap problem of hardware scrolling. The look-up table basically gave you the offset to the next line with the wrap correction built in so just by doing:
POP DE
ADD HL,DE
Solves all the problems with the Amstrads strange screen layout and the wrap around calculation. Plus it's quicker and avoids the JR instruction and the usual screen address fixes for the next line. It's actually 4 bytes shorter than the Wiki example. But of course the look-up table adds in 1024 bytes. Probably the more compiled sprites added in would get that table back with the 4 byte saving.
Actually looking at the Wiki fast sprite stuff it accrued to me that you could speed up the general purpose transparent sprite routine using a lookup table to calculate the next line. Using the same restrictions as the 32 char mode 1 screen you could do this. If no scrolling is used you could use a 512byte look-up table for a screen of 256 pixels high or if vertical hardware scrolling is used the 1024 byte table. Each look-up address has an offset to add to the high part of the byte to the screen. And by using:
POP AF
ADD D
LD D,A
Will get the correct next line. The pop brings in the data to use for A and the F part not used. So that routine becomes:
;Entry: BC = Sprite address, D = width, E = height, HL = screen address
; Set the stack pointer to the right part in the look-up table. Needs code added to do this
LD LX,D ;LX = width
LD HY,E ;HY = height
EX DE,HL
LD H,andmasks / 256
.rowloop
LD HX,LX ;HX <= width
.dobyte
LD A,(BC):INC C
LD L,A:LD A,(DE)
AND (HL):INC H:OR (HL):DEC H
LD (DE),A:INC E
DEC HX
JR NZ,dobyte
DEC HY
RET Z
LD A,E
SUB LX
LD E,A
POP AF
ADD D
LD D,A
JR rowloop
So we have pretty much removed all the code to calculate the next line.
I'm having some fun thinking in z80 again :) I'm now really temped to play around with an emulator now!
Actually there is a bug here because of the RET Z because the stack pointer is been mis-used. Just rearrange the loop to remove the problem as I cannot be bothered now. But the idea is pretty sound still.
I decided to correct it:
;Entry: BC = Sprite address, D = width, E = height, HL = screen address
LD LX,D ;LX = width
LD HY,E ;HY = height
EX DE,HL
LD H,andmasks / 256
.rowloop
LD HX,LX ;HX <= width
.dobyte
LD A,(BC):INC C
LD L,A:LD A,(DE)
AND (HL):INC H:OR (HL):DEC H
LD (DE),A:INC E
DEC HX
JR NZ,dobyte
LD A,E
SUB LX
LD E,A
POP AF
ADD D
LD D,A
DEC HY
JR NZ, rowloop
;Set stack pointer back
RET
Actually reading the Wiki on fast sprites this is actually hinted at :doh: I think I'll stop re-inventing the wheel because I guess after 30 years programmers have tried every trick in the book. But it was fun thinking about the problem... I just realised I miss programming in assembly language after using C++ for years.
Out of completeness, I realised that what I did in that note pad and the demo I did all those years ago was not as fast as it could of been. This is the new revised version. People have probably already thought of this for compiled sprites with the interrupts turned off years ago, including me. But I'm pretty shocked I never did this and replaced:
POP DE
ADD HL,DE
with:
POP AF
LD H,A
And to boot BC and DE can hold the most used bytes. Anyway no more nostalgia and re-inventing the wheel. And here's the routine which is probably the fastest it can go:
; Inputs
LD DE, Screen address
LD HL, Current line for sprite in offset table
; Output destroys all
.Sprite
LD (nn),SP
LD SP,HL
EX DE,HL
LD BC, Most used bytes stored in B and C
LD DE, Most used bytes stored in D and E
LD (HL),byte1:INC L ;plot line 1
LD (HL),D:INC L
LD (HL),C
POP AF
LD H,A
LD (HL),byte6:DEC L ;plot line 2
LD (HL),C :DEC L
LD (HL),B
LD A,H:ADD B:LD H,A
POP AF
LD H,A
LD A,(HL):AND #55:OR byte7:LD (HL),A:INC L ;plot line 3 (contains transparent areas)
LD (HL),E:INC L
LD A,(HL):AND #AA:OR byte9:LD (HL),A
LD SP,(nn)
RET
it would be really interesting to see this in action on a simple scrolling background with as many bullets on screen.
Quote from: Andy Coates on 17:22, 05 April 16
POP DE
ADD HL,DE
with:
POP AF
LD H,A
Well that's never going to work on the 7th scan line of a character is it! Stay with your original POP DE:ADD HL,DE, and the lookup table only has to be 526 bytes since there's only ever one wrap around case all the other values will be either #800 or #c840, except the one which is #c040. For that, you can change one byte in the table from #c8 to #c0 depending on the current scroll position.
You don't have to modify H at all before doing that, so it's simply:
ld (hl),byte
pop de
add hl,de
ld (hl),byte
etc.
Now to optimise it a little further (since your sprite is likely to be more that 1 byte wide), alternate between increment and decrement of L, so your compiled sprite code looks something like:
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte
pop de
add hl,de
ld (hl),byte:dec l
ld (hl),byte:dec l
ld (hl),byte:dec l
ld (hl),byte
pop de
add hl,de
Substituting ld (hl),byte with the appropriate thing, ie. ld (hl),r/ld (hl),n or nothing for blank, or if you want to use masks: ld a,(hl):and mask:or value:ld (hl),a.
Clipping at the left and right edges is always going to be a problem with compiled sprites, there are only really a few options:
1. Create separate compiled sprites for each clipped version (good if you have few sprite types and they're not too wide).
2. Self-modify your compiled sprite code (this is likely to counter the benefit of compiled sprites altogether).
3. Make your display area wider than the actual display (this is probably okay if you're not scrolling as you can control where the page boundaries lie, but unless you can manage 128 bytes wide it's not going to be easy to avoid splits in the middle of the display. The only way to use 128 bye wide screen is adjust horizontal total to 65 which probably shouldn't be done).
4. Write a separate non-compiled version that can cater for all left/right clipping.
5. Probably the best option is to not bother. If the sprite x < 0 or > screen_width - width then don't display it.
Vertical clipping is also a bit of a pain with compiled sprites. You can use some of the above ideas, or have a list of code offsets into the compiled sprite code for top clipping and perhaps self-modify with a RET for bottom clipping. Another simple idea is not to use 256 lines of display and just draw it on the bits that aren't currently displayed (similar to option 3 above, but somewhat easier vertically).
Quote from: Executioner on 05:24, 06 April 16
Well that's never going to work on the 7th scan line of a character is it! Stay with your original POP DE:ADD HL,DE, and the lookup table only has to be 526 bytes since there's only ever one wrap around case all the other values will be either #800 or #c840, except the one which is #c040. For that, you can change one byte in the table from #c8 to #c0 depending on the current scroll position.
I'm embarrassed to say you are correct - this is what happens when you are tired, late at night. I do like your idea for shortening the look-up table! Clipping on the horizontal will always be the problem with compiled sprites. In my original demo I never dealt with it but for a game it will have to be dealt with. The sensible thing to do would have a normal transparent sprite draw routine and switch to that when any sprites need to be horizontally clipped. The downside is you need the cater for the graphics again but if you compiled in the clipping that would waste bytes so the extra data for for a traditional sprite routine maybe ok.
Quote from: sigh on 21:55, 05 April 16
it would be really interesting to see this in action on a simple scrolling background with as many bullets on screen.
I am tempted to give it ago again. I might allocate a few evenings to this because I had fun looking at z80 again.
Because most of the time you only add #800, I think you can save some speed this way:
draw_sprite
ld de,#800
ld bc,#c840
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte
line0
add hl,de
ld (hl),byte:dec l
ld (hl),byte:dec l
ld (hl),byte:dec l
ld (hl),byte
line1
add hl,de
...
And before call it, poke an "add hl,bc" in the correct linex labels, and restore the "add hl,de" after.
For example, for sprites of 17 pixels height, you can have this to set the scanline skips:
setSpriteSkips_0
ld (line0),a
ld (line8),a
...
setSpriteSkips_1
ld (line1),a
ld (line9),a
...
setSpriteSkips_7
ld (line7),a
ld (line15),a
...
And call to setSpriteSkips_X according the Y of the sprite with a=#9 before, and #19 after call the draw routine
Or you can use "add hl,sp" instead of "add hl,bc" to have bc for common bytes. And for sprites + vertical scrolling, sp = #c040, and poke it when necessary.
Quote from: Rhino on 13:14, 06 April 16
Because most of the time you only add #800, I think you can save some speed this way:
draw_sprite
ld de,#800
ld bc,#c840
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte
line0
add hl,de
ld (hl),byte:dec l
ld (hl),byte:dec l
ld (hl),byte:dec l
ld (hl),byte
line1
add hl,de
...
And before call it, poke an "add hl,bc" in the correct linex labels, and restore the "add hl,de" after.
For example, for sprites of 17 pixels height, you can have this to set the scanline skips:
setSpriteSkips_0
ld (line0),a
ld (line8),a
...
setSpriteSkips_1
ld (line1),a
ld (line9),a
...
setSpriteSkips_7
ld (line7),a
ld (line15),a
...
And call to setSpriteSkips_X according the Y of the sprite with a=#9 before, and #19 after call the draw routine
Or you can use "add hl,sp" instead of "add hl,bc" to have bc for common bytes. And for sprites + vertical scrolling, sp = #c040, and poke it when necessary.
That's another great idea!
I think I'm convincing myself to give this a go now. Nostalgia has gripped me. So today I was thinking about sprite updates and racing the Electron Beam for a flicker free update. My original demo did not really use the interrupts... I just had a simple one that returned and used Halts to time with. In retrospect this was bloody awful to manage but it was workable. So today I was thinking that you would use the interrupts for the scroll and rupture stuff, plus a sprite management system. That way you know which interrupt is safe to remove and update sprites in regions. The only down side is that you need to be wary of not over running critical parts for the timings of the scroll and rupture with sprite updates.
Just wondering what peoples thoughts are on this and the best approach? I think updating the sprites in an interrupt means I can abuse the Stack Pointer without fear of an interrupt kicking in.
I have a feeling this thread will branch off topic :P
Quote from: Andy Coates on 15:18, 06 April 16
That's another great idea!
I think I'm convincing myself to give this a go now. Nostalgia has gripped me. So today I was thinking about sprite updates and racing the Electron Beam for a flicker free update. My original demo did not really use the interrupts... I just had a simple one that returned and used Halts to time with. In retrospect this was bloody awful to manage but it was workable. So today I was thinking that you would use the interrupts for the scroll and rupture stuff, plus a sprite management system. That way you know which interrupt is safe to remove and update sprites in regions. The only down side is that you need to be wary of not over running critical parts for the timings of the scroll and rupture with sprite updates.
Just wondering what peoples thoughts are on this and the best approach? I think updating the sprites in an interrupt means I can abuse the Stack Pointer without fear of an interrupt kicking in.
I have a feeling this thread will branch off topic :P
Do you not have memory for a double buffer? :)
Deepening in the alternative proposed before, this can be a compiled sprite implementation when scroll is not involved:
; hl = draw a compiled sprite routine
; ix = back address
draw_compiled_sprite_9_to_17_height
ld sp,hl
; calculate the screen address from the sprite coords
; ...
; hl = draw_sprite_compiled_routine
; de = screen adress
; a = y coord
exx
and 7
add a ; x2
add a ; x4
sub 8*4
ld l,a
ld h,#ff
add hl,sp
ld sp,hl
pop hl
pop de
ld a,#39 ; #39 = add hl,sp
ld (hl),a
ld (de),a
exx
ld sp,#c840
jp (hl) ; jump to the draw routine
unused_line_skip
db 0
; Example of compiled sprite
dw line_skip8 ; -32
dw line_skip16 ; use unused_line_skip if not need (height < 17)
dw line_skip7 ; -28
dw line_skip15 ; use unused_line_skip if not need (height < 17)
dw line_skip6 ; -24
dw line_skip14 ; use unused_line_skip if not need (height < 17)
dw line_skip5 ; -20
dw line_skip13 ; use unused_line_skip if not need (height < 17)
dw line_skip4 ; -16
dw line_skip12 ; use unused_line_skip if not need (height < 17)
dw line_skip3 ; -12
dw line_skip11 ; use unused_line_skip if not need (height < 17)
dw line_skip2 ; -8
dw line_skip10 ; use unused_line_skip if not need (height < 17)
dw line_skip1 ; -4
dw line_skip9
draw_a_compiled_sprite_17h
ex hl,de ; hl = screen adress
ld de,#800
ld bc,#xxxx ; 2 common bytes
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte
line_skip1
add hl,de
ld (hl),byte:dec l
ld (hl),byte:dec l
ld (hl),byte:dec l
ld (hl),byte
line_skip2
add hl,de
...
line_skip16
add hl,de
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte
exx
ld a,#19 ; #19 = add hl,de
ld (hl),a
ld (de),a
jp (ix) ; back
If scrolling, pop de: add hl,de may be a better solution if there are many repeated bytes in the sprites, because you have bc free for it.
Quote from: Rhino on 19:45, 06 April 16
Do you not have memory for a double buffer? :)
If this actually turns into a game then all memory will be valuable and double buffering the screen is wasted memory. That extra 16k will be valuable for graphics and such. The good thing about doing a vertical hardware scroll game is the Amstrad is very suited in hardware to do that really well and it would be nice to get a really polished 2 way vertical scroll working to show off what the machine is actually capable off. I can imagine a defender type of scroll with nice inertia and really good pixel art using the 16 colours to max. Now that's something a C64 could never achieve - loads of colours and an arcade looking screen size. The game would be sort of be like Uridium but with more depth in game play.
I think I'm getting serious about doing this now as a hobby and I want to aim high ;) And I do have the experience to pull this off because I've been a games coder for over 25 years.
So this evening using WinApe I've got ruptures working top and bottom with the play area in the middle. I'd forgotten how much fun programming low level is!
I'm not committing to a game yet. But at the moment I'm working on a scrolling demo with sprites... just to see what is possible.
Quote from: Rhino on 20:26, 06 April 16
Deepening in the alternative proposed before, this can be a compiled sprite implementation when scroll is not involved:
; hl = draw a compiled sprite routine
; ix = back address
draw_compiled_sprite_9_to_17_height
ld sp,hl
; calculate the screen address from the sprite coords
; ...
; hl = draw_sprite_compiled_routine
; de = screen adress
; a = y coord
exx
and 7
add a ; x2
add a ; x4
sub 8*4
ld l,a
ld h,#ff
add hl,sp
ld sp,hl
pop hl
pop de
ld a,#39 ; #39 = add hl,sp
ld (hl),a
ld (de),a
exx
ld sp,#c840
jp (hl) ; jump to the draw routine
unused_line_skip
db 0
; Example of compiled sprite
dw line_skip8 ; -32
dw line_skip16 ; use unused_line_skip if not need (height < 17)
dw line_skip7 ; -28
dw line_skip15 ; use unused_line_skip if not need (height < 17)
dw line_skip6 ; -24
dw line_skip14 ; use unused_line_skip if not need (height < 17)
dw line_skip5 ; -20
dw line_skip13 ; use unused_line_skip if not need (height < 17)
dw line_skip4 ; -16
dw line_skip12 ; use unused_line_skip if not need (height < 17)
dw line_skip3 ; -12
dw line_skip11 ; use unused_line_skip if not need (height < 17)
dw line_skip2 ; -8
dw line_skip10 ; use unused_line_skip if not need (height < 17)
dw line_skip1 ; -4
dw line_skip9
draw_a_compiled_sprite_17h
ex hl,de ; hl = screen adress
ld de,#800
ld bc,#xxxx ; 2 common bytes
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte
line_skip1
add hl,de
ld (hl),byte:dec l
ld (hl),byte:dec l
ld (hl),byte:dec l
ld (hl),byte
line_skip2
add hl,de
...
line_skip16
add hl,de
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte:inc l
ld (hl),byte
exx
ld a,#19 ; #19 = add hl,de
ld (hl),a
ld (de),a
jp (ix) ; back
If scrolling, pop de: add hl,de may be a better solution if there are many repeated bytes in the sprites, because you have bc free for it.
More cool ideas :) Thanks for your input in all this.
Wow that's some serious Z80 coding there. It took me awhile to get my head around that!
Quote from: Andy Coates on 20:35, 06 April 16
If this actually turns into a game then all memory will be valuable and double buffering the screen is wasted memory. That extra 16k will be valuable for graphics and such. The good thing about doing a vertical hardware scroll game is the Amstrad is very suited in hardware to do that really well and it would be nice to get a really polished 2 way vertical scroll working to show off what the machine is actually capable off. I can imagine a defender type of scroll with nice inertia and really good pixel art using the 16 colours to max. Now that's something a C64 could never achieve - loads of colours and an arcade looking screen size. The game would be sort of be like Uridium but with more depth in game play.
I think I'm getting serious about doing this now as a hobby and I want to aim high ;) And I do have the experience to pull this off because I've been a games coder for over 25 years.
So this evening using WinApe I've got ruptures working top and bottom with the play area in the middle. I'd forgotten how much fun programming low level is!
I'm not committing to a game yet. But at the moment I'm working on a scrolling demo with sprites... just to see what is possible.
Nice to see you so motivated! :)
Another idea to optimize large sprites is skip lines with inc h.
For example, for a sprite of 65 pixel height:
draw line 0...
inc h
draw line 32...
add hl,de ; de = #800-#100
draw line 1...
inc h
draw line 33...
add hl,de
...
Note that this skip lines in 2 nops of average aprox, when usually it take 6 nops or more.
The previous implementation adapted for large sprites would be:
; hl = draw_sprite_compiled_routine
; ix = back address
draw_compiled_sprite_65_height
ld sp,hl
; calculate the screen address from the sprite coords
; ...
; hl = draw_sprite_compiled_routine
; de = screen adress
; a = y coord
exx
and 7
ld l,a
add a ; x2
add l ; x3
add a ; x6
sub 8*6
ld l,a
ld h,#ff
add hl,sp
ld sp,hl
pop hl
pop de
pop bc
ld a,#39 ; #39 = add hl,sp
ld (hl),a
ld (de),a
ld (bc),a
exx
ld sp,#c840-#100
jp (hl) ; jump to the draw routine
unused_line_skip
db 0
; Example of compiled sprite
dw line_skip8
dw line_skip16
dw line_skip24
dw line_skip7
dw line_skip15
dw line_skip23
dw line_skip6
dw line_skip14
dw line_skip22
dw line_skip5
dw line_skip13
dw line_skip21
dw line_skip4
dw line_skip12
dw line_skip20
dw line_skip3
dw line_skip11
dw line_skip19
dw line_skip2
dw line_skip10
dw line_skip18
dw line_skip1
dw line_skip9
dw line_skip17
draw_a_compiled_sprite_65h
ex hl,de ; hl = screen adress
ld de,#800-#100
ld bc,#xxxx ; 2 common bytes
; draw line 0
...
inc h
; draw line 32
...
line_skip1
add hl,de
; draw line 1
...
inc h
; draw line 33
...
line_skip2
add hl,de
; draw line 2
...
...
exx
ld a,#19 ; #19 = add hl,de
ld (hl),a
ld (de),a
ld (bc),a
jp (ix)
That some pretty clever code there. Again thanks for the input :)
Quote from: Andy Coates on 21:31, 06 April 16
That some pretty clever code there. Again thanks for the input :)
Thanks, though I must say that currently I am working in a game where sprites are drawn approximately 40% faster than everything said here.
But still is not the time to spread all the magic than the CPC can do :)
Regards
That will be great to see! :D
@Andy Coates (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1717):
I think you should go ahead and program the cpc you can confirm your ideas and try things out. You will see what works and doesn't work and perhaps that will lead to a finished game? :)
Quote from: Rhino on 21:59, 06 April 16
But still is not the time to spread all the magic than the CPC can do :)
Too much magic in one go takes away all the suprises ;)
I know it'll be worth waiting for.
Quote from: Rhino on 21:59, 06 April 16
Thanks, though I must say that currently I am working in a game where sprites are drawn approximately 40% faster than everything said here.
But still is not the time to spread all the magic than the CPC can do :)
Regards
That's very intriguing... I suppose you don't want to share anything on this yet?
Today I was thinking about graphics and map compression. I need to investigate some good fast compression routines that are written in Z80. Then I need to investigate the compression ratio of 4096 bytes worth of graphics data (which is 256 chars). If the ratio is good then it's worth allocating a 4096byte buffer for the level graphics and use the screen area to unpack into for how many levels of compression on the data and then the final unpack to the buffer.
The map can be built from meta tile chunks that reference the chars. If the compression ratio and unpacking speed is fast then each row of the map can be unpacked into a small buffer for the scroll update to use. If it's slow then using a largish buffer will be needed to unpack the map data in. The maps should not be that big anyway because if the scroll is like Defender and wraps around on itself then you will have a continuous scroll that the player can move up and down from.
Quote from: arnoldemu on 09:04, 07 April 16
@Andy Coates (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1717):
I think you should go ahead and program the cpc you can confirm your ideas and try things out. You will see what works and doesn't work and perhaps that will lead to a finished game? :)
You are right :) I'm just working towards a little demo at the moment. I'm actually enjoying looking into this - takes me back to when I was learning to code on an Amstrad all those years ago.
I was just thinking that if you wanted an alternative to having smooth scrolling starfield, you could use palette changes by having a 2 frame animation of a star that is 2 pixels wide and 2 pixels long (mode 0):
1) The first frame has the first top of these pixels in black and the pixel below is white.
2) The second frame has this pixel in reverse.
If you now scroll this using a normal hardware scroll while switching between them, it will give the illusion of smooth pixel movement. This is a method suggested by andycadley when the forum was helping me with ideas to achieve smooth scrolling on a football game. However - it's a horizontal scroll, but you would just make it vertical for your use.
You can see the example:
Football Fever (aka - Games with smooth "1" pixel multi directional scrolling.) (http://www.cpcwiki.eu/forum/games/games-with-smooth-'1'-pixel-multi-directional-scrolling/270/)
Quote from: Rhino on 21:59, 06 April 16
Thanks, though I must say that currently I am working in a game where sprites are drawn approximately 40% faster than everything said here.
But still is not the time to spread all the magic than the CPC can do :)
Regards
This sounds like how Ultimate worked in the eighties :)
Nice thread and good luck with your testing can never have too many shoot em ups :)
Quote from: Rhino on 21:59, 06 April 16
Thanks, though I must say that currently I am working in a game where sprites are drawn approximately 40% faster than everything said here.
But still is not the time to spread all the magic than the CPC can do :)
Regards
Beat the number and speed of the sprites in Cyber Chicken and you write history.[nb]Not the ROM version, the 128 KB version on disc of course.[/nb] ;) :) :)
Quote from: TFM on 18:03, 16 April 16
Beat the number and speed of the sprites in Cyber Chicken and you write history.[nb]Not the ROM version, the 128 KB version on disc of course.[/nb] ;) :) :)
Do not worry. When the game launches, it will be necessary to rewrite the whole CPC history... again... ;D
Quote from: Rhino on 20:48, 19 April 16
Do not worry. When the game launches, it will be necessary to rewrite the whole CPC history... again... ;D
Great to ear that you have the time to acheive a new ambicious project! 8)
Quote from: Rhino on 20:48, 19 April 16
Do not worry. When the game launches, it will be necessary to rewrite the whole CPC history... again... ;D
Make us dreaming m8, we need challenge :-*
Quote from: fano on 07:32, 20 April 16
Make us dreaming m8, we need challenge :-*
(http://vanitycrew.free.fr/bb.png)
the sprite record is still owned by Vanity
website: Vanity (http://vanitycrew.free.fr/)
dsk of the record: http://vanitycrew.free.fr/Boules%20et%20Bits%20 (http://vanitycrew.free.fr/Boules%20et%20Bits%20)(Vanity).zip
Sorry , forgot something : this is for a game with a decent gameplay, not a demo or a game with frustating gameplay due to technical constraints :P
There is long time i found i was not able to compete demomakers ;D
Quote from: Rhino on 20:48, 19 April 16
Do not worry. When the game launches, it will be necessary to rewrite the whole CPC history... again... ;D
What ? A new Batman Game ? Batman returns ? Batman vs Superman ?
Tell us more about proprieties ? Hardscrolls ? horizontal, vertical ? How many sprites ? Mode 0 ?
Quote from: Ast on 09:33, 20 April 16
What ? A new Batman Game ? Batman returns ? Batman vs Superman ?
Tell us more about proprieties ? Hardscrolls ? horizontal, vertical ? How many sprites ? Mode 0 ?
Personally, I prefer the surprise to discover a game and known nothing[nb]We should expect a 32x32 MODE 0 vertical scroller game, because that open the best optimizations on CPC to make crazy sprites and effects.
I will love something like an Ikaruga clone, because its an ingenious and adictive gameplay... (not yet another puzzle game)
[/nb] about it before... ;D
Another puzzle game ? I don't think so!
Quote from: roudoudou on 08:13, 20 April 16the sprite record is still owned by Vanity
As I have seen, it was beat last year for an unreleased demo.
Quote from: TotO on 13:15, 20 April 16
As I have seen, it was beat last year for an unreleased demo.
Unreleased ? So the record is still taken by vanity ^^
Quote from: Rhino on 20:48, 19 April 16
Do not worry. When the game launches, it will be necessary to rewrite the whole CPC history... again... ;D
Really looking forward! :) Meanwhile I take a look at some nice place at the old folks home, to have an comfy spot to play your upcoming game. ;) :)
I know good work takes it's time, but now we got something to wait for. :)
Quote from: Ast on 10:04, 20 April 16
Another puzzle game ? I don't think so!
Not another puzzle game :)
I was wondering how fast the cpc can draw compiled sprites also, my reasoning was most optimistic writing the same value from A register in every byte of 16kb video memory we might be able to get 50fps, not useful as every byte is the same every frame. If 4kb of video memory is sprites and the rest blank, and rather than trying to achieve 50fps, maybe we get 1/8 cpu time for sprite drawing and 7/8 preparing next frames or other stuff...
Am I far off? If compiled sprites are mixed with my stack programming example we have quite a very tight game loop... perhaps 2 x 2k exploding fixed type sprites at 25fps could be achievable if memory is enough to hold the animation frames... which are all compiled. If these frames were in rom then we don't need as much banking, I suspect similar to what Alcon does.
Am I wrong?