Jump to content
IGNORED

Pro Eye Needed - Gremlins


Heaven/TQA

Recommended Posts

thanks miker...will have a look... ah...just looked into the code...its antic e... but i can not use antic e for Beyond Evil as i need anyway a charbased screen to handle the drop/picking/door routine. so thats why i went down the road for soft sprites in antic 4...but maybe we can found games which use that mode instead of antic e....

 

and for all who think that you can have antic 4 softsprites for free can have a look into the source code....that is the overhead you need for 1 8x16 sprite... ;) (ok...the code is not optimised yet like unroll code, lookup tables but...)

Link to comment
Share on other sites

f.e. download Dropzone from Fandal's website. Enter Monitor by Hitting F8 and enter "A 380C". now we are altering the DLI code and switching back the playfield area into system font.... so enter the codes "LDA #$E0", "NOP" and press RETURN to go back to the monitor...now restart the game by entering CONT. start a game and you will see the "mess"... ;)

Link to comment
Share on other sites

f.e. download Dropzone from Fandal's website. Enter Monitor by Hitting F8 and enter "A 380C". now we are altering the DLI code and switching back the playfield area into system font.... so enter the codes "LDA #$E0", "NOP" and press RETURN to go back to the monitor...now restart the game by entering CONT. start a game and you will see the "mess"... ;)

 

You need to type "A 380D" actually. That's interesting, especially interesting when the guy blows up. All those single pixels are actually characters... wierd. I also always liked the display list effects in the title screen/attract mode. So easy to do on the Atari, but effective.

Link to comment
Share on other sites

small update of the soft sprite test.... it's now with masking the background...so now we have "real sprites". now let us check how we can optimise the code and/or the data (f.e. store gfx/mask upside down).

 

when the stuff works i will through the engine into Beyond Evil and see what happens. :D

sprite3.zip

Link to comment
Share on other sites

  • 2 weeks later...

i guess i find a solution for Beyond... i will have 4 different monster types per floor level. so i can write 4 different sub routines for handling the soft sprites. the routine can look like this:

 

set_sprite_monster0:
;set pointer to desired sprite #0 - #3 (no*9 = charoffset)
...
ldy #0
ldx #15
loop_stripe0: lda (charpointer),y
and monster0_mask,x
ora monster0_data,x
sta (charpointer),y
iny
dex
bpl loop_stripe0

ldx #15
ldy #24
loop_stripe1: lda (charpointer),y
and monster0_mask+16,x
ora monster0_data+16,x
sta (charpointer),y
iny
dex
bpl loop_stripe1

ldx #15
ldy #48
loop_stripe2: lda (charpointer),y
and monster0_mask+32,x
ora monster0_data+32,x
sta (charpointer),y
iny
dex
bpl loop_stripe2
...

 

i am thinking about a faster way without preshifting sprite data in y direction as well... but havent found any yet. Menace does only move in y-direction in 8 pixel (1 char) steps so the copy routine is more compact but i haven't found any solution for Beyond Evil yet.

 

what do you think? looks good imho. so when player is entering new tower level the monster sprite data + mask data is copied into the 4 different monster buffers. so when using 4 different sprite routines this could simplify things.

 

the sprite pointer is set to correct sprite chars depending on the sprite no. and the y-offset for the data is stored directly into the pointer.

Link to comment
Share on other sites

I suspect that some of the techniques discussed back in May with bitmapped soft-sprites can also be applied here. I don't know how necessary they would be if you only have 4 softsprites on screen though.

 

The basic idea boiled down to:

lda (chardata_stripe1),y 
and #160			; spritemask byte 0
ora #160			 ; sprite data byte 0
sta (chardata_stripe1),y

lda (chardata_stripe2),y 
and #3			; spritemask byte 16
ora #2			 ; sprite data byte 16
sta (chardata_stripe2),y

lda (chardata_stripe3),y 
and #160			; spritemask byte 32
ora #160			 ; sprite data byte 32
sta (chardata_stripe3),y

iny

lda (chardata_stripe1),y 
and #168			; spritemask byte 1
ora #168			 ; sprite data byte 1
sta (chardata_stripe1),y
.
.
.

 

Of course, you can optimize each of the shifted sprites when they fall on even character borders (when any horiz pos x&4=0, it will only be 2 strips wide, not 3); Depending on the how you are using the code, you may even be able to use x indexing instead of zero,y. Certainly, this will work for the player character that will always be the same shape in the same character range:

 

lda playersprite_stripe1,x
and #160
ora #160
sta playersprite_stripe1,x
.
.
.
inx
.
.
.

 

which could save a number of cycles. This might be able to work with the monsters, as long as there are no more than 3 on screen:

 

ldx #0 ; base offset for enemy 0
jsr drawsprite

ldx #72; base offset for enemy 1
jsr drawsprite

drawsprite:
lda enemy0_stripe1,x
and #160
ora #160
sta enemy0_stripe1,x
.
.
.

 

Of course, unrolling a sprite will take something like 4-5k per unique shape (I think I was calculating for 12 bytes tall, not 16) which may be too much memory. Also, filling in the playerdata from the background is expensive, and not accounted for here.

 

I suppose you could unroll the player only, since it will always be displayed, and use the slower, but significantly more memory efficient method for the monsters.

 

I was hoping to use this method for driving ~10 character sprites during an NTSC VBI, but I don't think it will fit in the time slice (I wasn't planning on masking, only on ora'ing in the data). I may need to try writing up a routine for timing.

Link to comment
Share on other sites

there is one issue in my code which i havent covered...and makes the thing again more complicated... of course i need sprite masks for the shifted sprite data and the shifted sprite data as well... and with my absolute ANDs and ORAs without pointers... i can't move pixelwise in x-direction... grrr...

Link to comment
Share on other sites

ok. more thoughts yesterday... as i need flexible pointers (for animation, positioning the preshifted data) i thought that using a pointer for the LDA/STA (sprite),y is not the best way to go as the AND/ORA (DATA),y will change more often but the sprite-adresses (the char-adresses for each sprite) are fixed. so it does make more sense to use self modified code for these 2 instructions than for the masks and data.

 

so the loop might be like this

 

...
;set sprite start adresses for each stripe
ldx sprite_nr
lda sprite_stripe0_lo,x
sta set0+1
lda sprite_stripe0_hi,x
sta set00+2
lda sprite_stripe1_lo,x
sta set1+1
lda sprite_stripe1_hi,x
sta set11+2
lda sprite_stripe2_lo,x
sta set2+1
lda sprite_stripe2_hi,x
sta set22+2

lda sprite_y
and #7
tax
stx temp

ldy #15
loop: 
set0: lda spritead,x
and (mask),y
ora (data),y
set00: sta spritead,x
inx
dey
bpl loop

ldx temp
ldy #15
loop: 
set1: lda spritead,x
and (mask),y
ora (data),y
set11: sta spritead,x
inx
dey
bpl loop

ldx temp
ldy #15
loop: 
set2: lda spritead,x
and (mask),y
ora (data),y
set22: sta spritead,x
inx
dey
bpl loop
...

 

so the pointers mask/data can be adjusted each frame and for pixel positioning. they are changing more frequently than the fixed chars used for the softsprites...

 

looks better than the old one. tss... thanks for lookup tables which i haven't used for ages... ;) seems i am too long in game mode and not demo mode where most of the time you are using precalculated stuff... ;)

Edited by Heaven/TQA
Link to comment
Share on other sites

and some more errors... ;)

 

aarg.... i hate it... :) some philosophy question...can code have some errors as i am writing the code...so how can the code have some? hmmm...seems like the same like in the WoW south park episode... "how can you kill someone who has no life"?

Link to comment
Share on other sites

ok...here is the correct code:

 

et_sprite_monster0:
	lda x;div 4
	lsr
	lsr
	sta xp
	lda y;div 8
	lsr
	lsr
	lsr
	tax
	lda linetabl,x
	clc
	adc xp
	sta pointer
	lda linetabh,x
	adc #0
	sta pointer+1
	jsr copy_background;copy background chars into sprite chars

;now set sprite on screen
	lda char
	tax
	ldy #0
	sta (pointer),y
	inx
	txa
	ldy #40
	sta (pointer),y
	inx
	txa
	ldy #80
	sta (pointer),y
	inx
	txa
	ldy #1
	sta (pointer),y
	inx
	txa
	ldy #41
	sta (pointer),y
	inx
	txa
	ldy #81
	sta (pointer),y
	inx
	txa
	ldy #2
	sta (pointer),y
	inx
	txa
	ldy #42
	sta (pointer),y
	inx
	txa
	ldy #82
	sta (pointer),y

	lda x
	and #3
	tay
			
	lda #<sprmaskr
	clc 
	adc x_offsettab,y
	sta pointer2
	lda #>sprmaskr
	sta pointer2+1
	lda #<sprdatar
	clc 
	adc x_offsettab,y
	sta pointer3
	lda #>sprdatar
	sta pointer3+1

	
;set sprite start adresses for each stripe
	ldx sprite_nr
	ldx #0
	
	lda sprite_stripe0_lo,x
	sta set_stripe0+1
	sta set_stripe00+1
	lda sprite_stripe0_hi,x
	sta set_stripe0+2
	sta set_stripe00+2
	lda sprite_stripe1_lo,x
	sta set_stripe1+1
	sta set_stripe11+1
	lda sprite_stripe1_hi,x
	sta set_stripe1+2
	sta set_stripe11+2
	lda sprite_stripe2_lo,x
	sta set_stripe2+1
	sta set_stripe22+1
	lda sprite_stripe2_hi,x
	sta set_stripe2+2
	sta set_stripe22+2

	lda y
	and #7
	tax
	sta temp
	
	ldy #15
;		ldx temp
set_stripe0: lda sprite,x
	and (pointer2),y
	ora (pointer3),y
set_stripe00: sta sprite,x
	inx
	dey
	bpl set_stripe0

	ldy #31
	ldx temp
	lda #15
	sta temp2
set_stripe1: lda sprite,x
	and (pointer2),y
	ora (pointer3),y
set_stripe11: sta sprite,x
	inx
	dey
	dec temp2
	bpl set_stripe1

	ldy #47
	lda #15
	sta temp2
	ldx temp
set_stripe2: lda sprite,x
	and (pointer2),y
	ora (pointer3),y
set_stripe22:	sta sprite,x
	inx
	dey
	dec temp2
	bpl set_stripe2

	rts

copy_background: 
	lda #<sprite
	sta temp3
	lda #>sprite
	sta temp3+1
	ldy #0
	lda (pointer),y
	jsr copy_char
	ldy #40
	lda (pointer),y
	jsr copy_char
	ldy #80
	lda (pointer),y
	jsr copy_char
	ldy #1
	lda (pointer),y
	jsr copy_char
	ldy #41
	lda (pointer),y
	jsr copy_char
	ldy #81
	lda (pointer),y
	jsr copy_char
	ldy #2
	lda (pointer),y
	jsr copy_char
	ldy #42
	lda (pointer),y
	jsr copy_char
	ldy #82
	lda (pointer),y
	jmp copy_char

copy_char:	
;char*8		
	
	tax
	lda fonttabl,x
	sta temp
	lda fonttabh,x
	sta temp+1
	
	ldy #7
copy_char1 lda (temp),y
	sta (temp3),y
	dey
	bpl copy_char1
	lda temp3
	clc
	adc #8
	sta temp3
	bcc copy_char2
	inc temp3+1
copy_char2 rts 


		org $5000
x_offsettab dta 0,48,96,144;sprite offset 48 bytes per sprite(3 stripes a 16 bytes)
sprite_stripe0_lo: dta <sprite
sprite_stripe0_hi: dta >sprite
sprite_stripe1_lo: dta <(sprite+24) 
sprite_stripe1_hi: dta >(sprite+24)
sprite_stripe2_lo: dta <(sprite+48)
sprite_stripe2_hi: dta >(sprite+48)

 

not optimised...but hopefully some can imagine that the guys with hardware sprite all are doing this in hardware... leaving cpu free for many things more....;)

 

ps. first optimising stept is to change the draw order f.e. stripe 3, 2, 1 so i can leave the reloading of the index...

Link to comment
Share on other sites

and...this is code for 1 8x16 sprite.... C64 has 8x 24x21...moveable with some STAs.... man...why did atari used the damned 2600 like player/missles...

Atari did that because it was the mid 1970s when it was designed and that type of circuit was already available to the engineers. The C64 was an 80's design and CBM had their own chip manufacturing plants.

 

Also remember, to animate the sprite you don't need a complete new routine for each frame of the animation (if you hard code each sprite)... you just point the sprite hardware to the new data location. That saves a LOT of memory and clock cycles.

That and the SID is why I gave the C64 the edge as a game machine over the Atari in another thread.

But then... it depends on the game now doesn't it. The Speccy had a lot of 3D and Isometric games for it because it's 1 bit/pixel display was fast to update and it was clocked pretty fast for a Z80 machine of that time.

 

Just for the record... the Plus/4 has had a lot of C64 games hacked to run on it just by doing this sort of thing so it is definitely possible. True sprites do save a lot of CPU time and memory though.

 

Hmmmm... do you suppose it might be faster to move a sprite from 1 location to another on the C64 in BASIC than it is for the Atari to do this? :ponder:

Edited by JamesD
Link to comment
Share on other sites

ok. here is the first "multiple" soft sprite test engine... its so "fast" that it can not handle 2 sprites per VBL... ;) thats why the 2nd sprite is not moving in y-direction (as it would disappear at the top screen area). but that's ok as in Beyond Evil the sprite will not move fast anyway so the max. 4 enemy monsters will be handled in separate VBL cycles anyway.

 

next will be to the background sprite buffer which needs to be implemented as at the moment the vram is filled each frame. but for Beyond Evil i need a proper sprite buffer for scanning the items covered by the sprite.

 

when this is done i will make a first test with the Beyond Evil engine and hope it does not get screwed up.

sprite4.zip

post-528-1191770389_thumb.png

Link to comment
Share on other sites

ok. here is the first "multiple" soft sprite test engine... its so "fast" that it can not handle 2 sprites per VBL... ;) thats why the 2nd sprite is not moving in y-direction (as it would disappear at the top screen area). but that's ok as in Beyond Evil the sprite will not move fast anyway so the max. 4 enemy monsters will be handled in separate VBL cycles anyway.

 

next will be to the background sprite buffer which needs to be implemented as at the moment the vram is filled each frame. but for Beyond Evil i need a proper sprite buffer for scanning the items covered by the sprite.

 

when this is done i will make a first test with the Beyond Evil engine and hope it does not get screwed up.

 

I was thinking about this a bit over the weekend. There are a few shortcuts I can make in the project I am working on, and perhaps you can make some of the same assumptions:

 

The important bit is the following:

Overlap is only between sprites, no background/sprite overlap.

I was surprised by this, but after tweaking my character set a bit, I realized that picking up objects, running into walls, etc. could be modified to always be character boundaries. The entire map could be reduced to impassible (filled chars) or passable (blank)

 

This basic assumption leads to a few interesting optimizations:

  • If the player is updated every frame (and always drawn first), you do not need to perform any masking or eor'ing of data, the player data can be copied straight across - if this does not completely hold, the first sprite drawn each frame can be handled this way. It might be worth making the player character always first, since then you can hardcode the destination address.
     
    Sprite/Sprite interaction - if sprites cannot visually overlap, then you can remove the masking of each frame. The only needed operation is the eor (or ora);
     
    Finally: Mostly sprites will be drawn over blank characters. When this happens, no eor/mask or background character copy is required. It is probably worth checking this case, assuming overhead of the test is low enough.

Even if you are planning on allowing background or visual sprite overlap, the common case will tend to be no overlap (well as long as you have a consistent single character background - preferably blank) . This makes it more important to figure out a good way to perform the check cheaply.

Link to comment
Share on other sites

i was thinking in a similar way. but before leaving out the masking and do other things i will try to implement it straight away and see what happens. the "draw player first" is a valid point to consider. but what about following steps to think about:

 

- avoid overlapping of the sprites (have to think about a quick check with the xp,yp of one sprite agains the 4 others (incl. 3 monster, 1 player)

- the design of the sprites are done in a way where players would notice "black background" when moving over the loot f.e. imagine the bird sprite or the snake or even the player. and i do not want to give too many restriction to the artists.

- do not draw the "buffer chars" when on even x mod 4 and y mod 8 lines as they are not needed. or as alternative...only copy background into those chars...

 

so it's correct that they are still many ways to optimise the whole bunch of code. see Menace where the sprites do not move by pixel for faster code.

Link to comment
Share on other sites

i guess i do not let the monsters overlap. but i am not sure if this is not already done? can not remember, if not...anybody has a quick solution for checking overlapping? this must be some kind of common issue for ages in computer science?

 

anyway... i am sure some of you know the VIC20 game Amok!... what do you think of that engine? and as my pro eyeunderstands the game itselft only moves the shots, 1 robot and the player per frame?

 

the game itself is here...use vice! emulator for vic...

 

http://www.zimmers.net/anonftp/pub/cbm/vic...nded/index.html

post-528-1191958104_thumb.png

Link to comment
Share on other sites

i guess i do not let the monsters overlap. but i am not sure if this is not already done? can not remember, if not...anybody has a quick solution for checking overlapping? this must be some kind of common issue for ages in computer science?

 

I would use bounding boxes. Particularly with a small number of sprites, this should be fast enough. I think there have been a number of discussions here about this.

 

One good on is here:

http://www.atariage.com/forums/index.php?showtopic=64287

 

I think there was on in the 6502 killer hacks thread. Hmmmm.... here:

http://www.atariage.com/forums/index.php?s...st&p=873438

 

It is not pixel perfect collision, but more than enough for avoiding overlap.

Link to comment
Share on other sites

here is another small update of the sprite routines...now different speed per sprite and clearing of the background of each sprite (not restore yet)... i am moving 4 monsters so actually this will be the speed in the game.

 

you notice a flicker when sprites are overlapping each others (same like in dropzone btw...) but as i am avoiding overlapping should be no major issue... i am still not 100% sure if i will copy the background gfx into the sprites... more checks later...

sprite4.zip

post-528-1192284286_thumb.png

Link to comment
Share on other sites

small update...now with background restore... the background gets messed up simply because i am not avoiding overlapping...

 

well... as more i am into it...i have to say... sprite hardware rules... look how many cpu cycle are needed, look how much code (not even optimised f.e. like with unrolled loops etc... which cause more code), many lookup tables and i am not able to move more than 1 sprite per frame...and the sprite is a 8x16 one... vertical movement of player/missles is simple compared to own soft sprite routines... now i know why a lot of people went for antic e games instead of using chars... it's far simpler and faster (but not for beyond evil... ;))

sprite4.zip

post-528-1192461707_thumb.png

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...