Jump to content

Photo

[coleco] Sprites Sample ( assembly codes listing )


47 replies to this topic

#1 newcoleco OFFLINE  

newcoleco

    Stargunner

  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Sat Aug 28, 2010 11:08 AM

Here, I'm posting a sample code concerning Sprites. If you have not see my previous posts (messages/videos) please do so in order to understand a few things.

For those who already see my messages, you know that this code is made based on TNIASM, a cross-compiler you can find in the Internet, used for example in the GameBoy homebrew scene for years.

I'm not gonna talk about the video settings, but about sprites.

The following listing doesn't move or change color a bunch of sprites... let's keep it simple and just display sprites on screen. In the video, I'm showing the evolution of this listing starting from 1 sprite to 3,5 and then 7 sprites. With 5 sprites, because the video chip doesn't show more than 4 sprites in a row, I've added a sprites flickering effect based the principle of a circular buffer with the sprites priority table. Other technics like simply swap to the highest priority the non showing sprite might be fast but raise the question why if another sprite (that we are not aware of) does also need to get a higher priority at the same time? That's why I'm using the solution shown here.

The table of sprite priorities is initialized with the numbers 0 to nbr_sprites-1, so if there is 5 sprites to show then the table of priorities is [0,1,2,3,4]. When the flickering effect is needed, the first sprite to be the 5th sprite in a row is retreived from the video register and used as a starting point for the circular buffer. For example, if always the 5th sprite condition occurs for a 5 priorities table, you get the following tables of priorities during time : [0,1,2,3,4] -> [4,0,1,2,3] -> [3,4,0,1,2] -> [2,3,4,0,1] -> [1,2,3,4,0] and so on. This makes all the 5 sprites flickering on screen. With the "swap only the 5th sprite to the highest priority" solution, only 2 sprites are flickering on screen, which seems to be a pretty good solution, but deny the possibility if there is a 6th sprite or even a 7th sprite. The flickering effect with 7 sprites, in this sample program, acts as follow : [0,1,2,3,4,5,6] -> [4,5,6,0,1,2,3] -> [1,2,3,4,5,6,0] -> [5,6,0,1,2,3,4] -> [2,3,4,5,6,0,1] -> [6,0,1,2,3,4,5] -> [3,4,5,6,0,1,2] and so on. Well, it should be this sequence, I can't be sure if the emulator you are using will gives you this sequence of sprites order and so this sprites flickering effect.

As usual, if you appreciate this program, if you find it useful, please consider voting and/or leave a message.

; Colecovision - Sprites Demo
; by Daniel Bienvenu, 2010

NBR_SPRITES: equ 7

	fname "7sprites.rom"
	cpu Z80
	org $8000
	dw $aa55,SprAttrib,$7000,0,0,Start
	dw 0,0,0,0,0,0,0,0,0,0
	ret
Nmi:
	; Display Sprite(s)
	ld a,NBR_SPRITES
	call $1fc4 ; WR_SPR_NM_TBL
	ld a,$d0
	out ($be),a

	; Get Video Status
	call $1fdc ; READ_REGISTER
	bit 6,a
	jr z,DoNothing
	and $1f ; keep only 5bits = sprite#
	ld e,a
	ld d,0
	ld hl,($8004)
	push hl
	add hl,de
	ld c,(hl) ; Get corresponding Sprite entry
	pop hl
	ld a,NBR_SPRITES
	ld b,a
Reordering1:
	ld (hl),c
	inc hl
	inc c
	cp c
	jr nz,Reordering2
	ld c,0
Reordering2:
	djnz Reordering1
DoNothing:
	retn
Start:
	call $1f85 ; MODE_1
	call $1fd6 ; TURN_OFF_SOUND
	; Clear VRAM
	ld hl,0
	ld de,$4000
	xor a
	call $1f82 ; FILL_VRAM
	; Load Sprite Pattern
	ld de,$3800
	ld hl,HappyAlienBugFace
	ld bc,32
	call $1fdf ; WRITE_VRAM
	; Init. Sprites Order
	ld a,NBR_SPRITES
	call $1fc1 ; INIT_SPR_ORDER
	; Turn On Display + Enable NMI
	ld bc,$01e2
	call $1fd9 ; WRITE_REGISTER
TheEnd:
	jp TheEnd

SprAttrib:
	db 82, 24,0,13 ; Y=82, X= 24, Pattern#0, Color=13
	db 84, 56,0, 8 ; Y=84, X= 56, Pattern#0, Color=8
	db 86, 88,0, 9 ; Y=86, X= 88, Pattern#0, Color=9
	db 88,120,0,10 ; Y=88, X=120, Pattern#0, Color=10
	db 90,152,0, 3 ; Y=90, X=152, Pattern#0, Color=3
	db 92,184,0, 7 ; Y=92, X=184, Pattern#0, Color=7
	db 94,216,0, 4 ; Y=94, X=216, Pattern#0, Color=4

HappyAlienBugFace:
	db %00011000
	db %01100100
	db %11000011
	db %00001111
	db %00011001
	db %00110000
	db %00110110
	db %01111111
	db %01111111
	db %01111111
	db %01110000
	db %00110000
	db %00111000
	db %00011110
	db %00001111
	db %00000011

	db %00001100
	db %00010010
	db %11100011
	db %11111001
	db %11001100
	db %10000110
	db %10110110
	db %11111111
	db %11111111
	db %11111111
	db %00000111
	db %00000110
	db %00001110
	db %00111100
	db %11111000
	db %11100000

http://www.youtube.com/watch?v=2dHoBzpOE6s

Edited by newcoleco, Sat Aug 28, 2010 11:56 AM.


#2 Kiwi ONLINE  

Kiwi

    Dragonstomper

  • 587 posts

Posted Sat Aug 28, 2010 1:46 PM

That video is very interesting. Assembly is very interesting programming language since you have more control over the machine. I did mess around with ASM for the Atari 2600, but I will mess around with the later since I want to finish programming the game I'm making for Colecovision.

I decided to try to program sprite flickering routine in C to my scratch program, Hello World. Please note, I'm playing around with 8x8 sprite_simple mode. Also, this isn't a serious program so do laugh if it is funny. I had to test 8x8 mode. For some reason, Centipede was able to display 8 sprites without flickering in NewColeco video, unless there's prosper mode for BlueMSX.

http://www.youtube.com/watch?v=jApljk09zX8

Last night, I figured out the how and when to use NMI. When this function was enabled while writing the, print_at(1,20,"The yellow ghost filled with lemonade is being controlled by joypad!!! RUN!!!");, text, It only drew, "The". When I nest that with disable_nmi() enable_nmi(). The text printed out completely.

Anyway here what I did. I declared x globally. Right after the local variable declaration in the main(), I put x=0. SpriteFlicker() is added to the NMI routine along with sprite update. Here's the code for the flicker routine...

static void SpriteFlicker(void)
	{
	
	sprites[0+x].x = 8;
	sprites[0+x].y = 24;
	sprites[0+x].pattern = 12;
	sprites[0+x].colour = 2;
	sprites[1+x].x = 16;
	sprites[1+x].y = 24;
	sprites[1+x].pattern = 12;
	sprites[1+x].colour = 3;
	sprites[2+x].x = 24;
	sprites[2+x].y = 24;
	sprites[2+x].pattern = 12;
	sprites[2+x].colour = 4;
	sprites[3+x].x = 32;
	sprites[3+x].y = 24;
	sprites[3+x].pattern = 12;
	sprites[3+x].colour = 5;
	sprites[4-x].x = 40;
	sprites[4-x].y = 28;
	sprites[4-x].pattern = 12;
	sprites[4-x].colour = 6;
	sprites[5-x].x = 48;
	sprites[5-x].y = 28;
	sprites[5-x].pattern = 12;
	sprites[5-x].colour = 7;
	sprites[6-x].x = 56;
	sprites[6-x].y = 28;
	sprites[6-x].pattern = 12;
	sprites[6-x].colour = 8;
	sprites[7-x].x = 64;
	sprites[7-x].y = 28;
	sprites[7-x].pattern = 12;
	sprites[7-x].colour = 9;
		if(x==0)
		{
			x=4;
			goto here;
		}
		else
		{
			x=0;
			goto here;
		}	
here:
	}

I think it is sloppy and slow, but it works. I think if I want to move these sprites, then their attributes will have to be variable instead of a fixed number.

Edited by Kiwi, Sat Aug 28, 2010 1:51 PM.


#3 newcoleco OFFLINE  

newcoleco

    Stargunner

  • Topic Starter
  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Sat Aug 28, 2010 3:00 PM

You have to understand this when you program in C : to access a value within a data structure, the program need to do a multiplication with teh size of the structure in order to access the right area. But, you can optimize this by moving around a pointer in the sprites table insted of using multiple times the way of accessing data with [ ].

I didn't try this code yet, but I think you'll get the idea pretty quickly.


function blahblah() {

sprite_t *pointer;
pointer = &sprite[x+0];

pointer.y = ...; /* equals to sprite[x+0].y = ... */
pointer.x = ...;
pointer.pattern = ...;
pointer.colour = ...;

pointer += 4; /* Because sprite_t size is 4. I don't know if it works under SDCC. */

pointer.y = ...; /* equals to sprite[x+1].y = ... */
pointer.x = ...;
pointer.pattern = ...;
pointer.colour = ...;

...

}

In C, [x+0] is calculated as x times 4 by adding 4 times the number x (or maybe it's x times adding the number 4, I can't remember) which takes a lot of time. So if you do this multiple times you multiply the time needed to proceed through your sprites flickering effect.

#4 newcoleco OFFLINE  

newcoleco

    Stargunner

  • Topic Starter
  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Sat Aug 28, 2010 7:00 PM

I've taken time to continue my Sprites Sample program to add a simple movement with a ball bouncing effect.

; Colecovision - Sprites Demo
; by Daniel Bienvenu, 2010

NBR_SPRITES: equ 7

	fname "7spritesmoving.rom"
	cpu Z80
	org $8000
	dw $aa55,$7100,$7000,0,0,Start
	dw 0,0,0,0,0,0,0,0,0,0
	ret
Nmi:
	; Display Sprite(s)
	ld a,NBR_SPRITES
	call $1fc4 ; WR_SPR_NM_TBL
	ld a,$d0
	out ($be),a

	; Update Sprites position (for next time)
	ld de,($8002)
	ld hl,$7180
	ld b,NBR_SPRITES
UpdateSpritesCoor:
	ld a,160
	call AddfromHLinDE
	ld a,216
	call AddfromHLinDE
	inc de
	inc de
	djnz UpdateSpritesCoor
    
	; Get Video Status
	call $1fdc ; READ_REGISTER
	bit 6,a
	jr z,DoNothing
	and $1f ; keep only 5bits = sprite#
	ld e,a
	ld d,0
	ld hl,($8004)
	push hl
	add hl,de
	ld c,(hl) ; Get corresponding Sprite entry
	pop hl
	ld a,NBR_SPRITES
	ld b,a
reordering1:
	ld (hl),c
	inc hl
	inc c
	cp c
	jr nz,reordering2
	ld c,0
reordering2:
	djnz reordering1
DoNothing:
	retn

	; Apply movement incrementation and bounce effect (max limit in register A)
AddfromHLinDE:
	push bc
	ld b,a
	ld c,(hl)
	ld a,(de)
	add a,c
	; if new position is lower than 24 or higher than max limit then bounce
	cp 24
	jr c,bounce
	cp b
	jr nc,bounce
	jr endbounce
bounce:
	ld a,c
	neg
	ld (hl),a
	ld c,a
	ld a,(de)
	add a,c
endbounce:
	ld (de),a
	inc hl
	inc de
	pop bc
	ret
    
Start:
	call $1f85 ; MODE_1
	call $1fd6 ; TURN_OFF_SOUND
	; Clear VRAM
	ld hl,0
	ld de,$4000
	xor a
	call $1f82 ; FILL_VRAM
	; Load Sprite Pattern
	ld de,$3800
	ld hl,HappyAlienBugFace
	ld bc,32
	call $1fdf ; WRITE_VRAM
	; Init. Sprites Order
	ld a,NBR_SPRITES
	call $1fc1 ; INIT_SPR_ORDER
	ld de,($8002)
	ld hl,SprAttrib
	ld bc,NBR_SPRITES*4
	ldir
	;ld hl,SprMovements ; Optim : HL already = SprMovements table address
	ld de,$7180
	ld bc,NBR_SPRITES*2
	ldir
	; Turn On Display + Enable NMI
	ld bc,$01e2
	call $1fd9 ; WRITE_REGISTER
TheEnd:
	jp TheEnd

SprAttrib:
	db 82, 24,0,13 ; Y=82, X= 24, Pattern#0, Color=13
	db 84, 56,0, 8 ; Y=84, X= 56, Pattern#0, Color=8
	db 86, 88,0, 9 ; Y=86, X= 88, Pattern#0, Color=9
	db 88,120,0,10 ; Y=88, X=120, Pattern#0, Color=10
	db 90,152,0, 3 ; Y=90, X=152, Pattern#0, Color=3
	db 92,184,0, 7 ; Y=92, X=184, Pattern#0, Color=7
	db 94,216,0, 4 ; Y=94, X=216, Pattern#0, Color=4
    
SprMovements:
	db 0,0
	db 1,0
	db 0,1
	db -1,0
	db 0,-1
	db 1,1
	db -1,-1

HappyAlienBugFace:
	db %00011000
	db %01100100
	db %11000011
	db %00001111
	db %00011001
	db %00110000
	db %00110110
	db %01111111
	db %01111111
	db %01111111
	db %01110000
	db %00110000
	db %00111000
	db %00011110
	db %00001111
	db %00000011

	db %00001100
	db %00010010
	db %11100011
	db %11111001
	db %11001100
	db %10000110
	db %10110110
	db %11111111
	db %11111111
	db %11111111
	db %00000111
	db %00000110
	db %00001110
	db %00111100
	db %11111000
	db %11100000

Edited by newcoleco, Sat Aug 28, 2010 7:00 PM.


#5 youki OFFLINE  

youki

    Stargunner

  • 1,751 posts

Posted Sun Aug 29, 2010 1:05 AM

For some reason, Centipede was able to display 8 sprites without flickering in NewColeco video, unless there's prosper mode for BlueMSX.


There is on option in Blue Msx to reduce the flicking.


@newcoleco : your video are really great!.

I would love to see some example of use of Put_mobile put_semimobile etc... :) (if possible used from C!!)

#6 newcoleco OFFLINE  

newcoleco

    Stargunner

  • Topic Starter
  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Sun Aug 29, 2010 9:38 AM

Please, keep in mind that sometimes a bunch of moving objects on screen may also be composed of characters which allow, for example, to put more ennemies (or ennemi parts) in a row without any flickering... like ennemies in Spectar and animals legs in Joust... but I'm not covering this subject here.

Terms like semi-mobile and mobile objects for the ColecoVision BIOS are refered as 16x16 graphics you can put on screen as characters but not limited to the 32x24 places you can put character. A semi-mobile object is simply lmited to moving into corridors of characters in horizontal and vertical, like in Spectar if you want. A mobile object is put anywhere on screen like a sprite but it's a bunch of characters. The objects routines use (if I remember correctly) the charset range $80-$FF to generate the characters that will be put on screen. I'll need to dig up into the documentation because I've never tried using the functions for moving objects before. It's better to use a more adapted solution for your needs because it's usually more optimized than a more generic function, so you may find using these mobile functions a bit painful, and if you want to use it under a project in C language, well you need to modify the header "crtcv.s" in order to set the work_space to an address where these functions can calculated freely whitout corrupting your game variables. In the devkit, I've actually set the work_space to be $7000-$701F which is not enough even for the semi-mobile objects... but it's just enough for the flip and rotate graphics manipulations functions.

#7 retroclouds ONLINE  

retroclouds

    Stargunner

  • 1,367 posts
  • Location:Germany

Posted Mon Aug 30, 2010 11:09 AM

Please, keep in mind that sometimes a bunch of moving objects on screen may also be composed of characters which allow, for example, to put more ennemies (or ennemi parts) in a row without any flickering... like ennemies in Spectar and animals legs in Joust... but I'm not covering this subject here.

Terms like semi-mobile and mobile objects for the ColecoVision BIOS are refered as 16x16 graphics you can put on screen as characters but not limited to the 32x24 places you can put character. A semi-mobile object is simply lmited to moving into corridors of characters in horizontal and vertical, like in Spectar if you want. A mobile object is put anywhere on screen like a sprite but it's a bunch of characters. The objects routines use (if I remember correctly) the charset range $80-$FF to generate the characters that will be put on screen. I'll need to dig up into the documentation because I've never tried using the functions for moving objects before. It's better to use a more adapted solution for your needs because it's usually more optimized than a more generic function, so you may find using these mobile functions a bit painful, and if you want to use it under a project in C language, well you need to modify the header "crtcv.s" in order to set the work_space to an address where these functions can calculated freely whitout corrupting your game variables. In the devkit, I've actually set the work_space to be $7000-$701F which is not enough even for the semi-mobile objects... but it's just enough for the flip and rotate graphics manipulations functions.


About 2 years ago I was looking into the Colecovision BIOS using your superb documentation. I was fascinated by the many OS7 functions availabe.
So, I built a primitive disassembler and scanned many of the game roms for OS7 calls. Too my surprise only a few games were using a wider variety of OS7 calls.
Don't recall exactly, but I can't remember having found any game that used any of the "mobile" functions.

Then again that could have been due to my disassembler failing :P

I like many of the concepts used in OS7. I wonder why they weren't used by the developers as much.

Could it be because they didn't have the documentation? Could imagine that as an external colecovision developer you had to pay some $$$ for training and perhaps a license ?
Another reason could have been that the publisher wanted to make a game available for multiple Z80 / TMS9918 platforms (e.g. MSX) and then it would not make sense to use any platform dependant BIOS calls.

#8 retroclouds ONLINE  

retroclouds

    Stargunner

  • 1,367 posts
  • Location:Germany

Posted Mon Aug 30, 2010 11:20 AM

Just for the fun of it. Here are 3 games I took a closer look at. If you scroll to the end of the files you'll find a list of OS7 routines that were found by the scanner.
These really are quite buggy disassemblies, but it did allow me to take a peek at some of the calls.

Attached File  disasm.zip   86.21KB   115 downloads

#9 newcoleco OFFLINE  

newcoleco

    Stargunner

  • Topic Starter
  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Mon Aug 30, 2010 11:30 AM

Don't recall exactly, but I can't remember having found any game that used any of the "mobile" functions.

You should start a topic with this subject of the most commonly and rarely used routines for the CV bios.

As for mobile and semi-mobile routines, I think there were used in Donkey Kong and Freezy, but don't quote me on that.


Too my surprise only a few games were using a wider variety of OS7 calls.

...

Could it be because they didn't have the documentation? Could imagine that as an external colecovision developer you had too pay some $$$ for training and perhaps a license ?

Yes, the documentation wasn't free. I remember someone saying that they pretty much had to use at first reverse engineering methods to figure out what they can do with this game system. But I think paying for the documentation came with the license, so in order to make games for the game system, the developpers had to pay for the documentation, even if they decided to use pretty much nothing of what is in the ColecoVision bios. Again, I'm not 100% sure, so don't quote me on that too.


Just for the fun of it. Here are 3 games I took a closer look at. If you scroll to the end of the files you'll find a list of OS7 routines that were found by the scanner.

I'm kinda surprised that you didn't bring up a listing from a game like Q*Bert where sounds aren't played through the sound manager system in the ColecoVision bios.

But yes, they tend to use what they find useful for the game project and make their own routines for the rest, which gives usually a better result because it fits perfectly the needs instead of being too generic and then slower than wanted. See these bios routines as a toolbox... to make an analogy, it's not necessary to use all your tools to build a bed or fix your car.

Edited by newcoleco, Mon Aug 30, 2010 11:44 AM.


#10 newcoleco OFFLINE  

newcoleco

    Stargunner

  • Topic Starter
  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Wed Sep 8, 2010 8:54 PM

This video is only the PART 2 of the Sprites Demo.



I'm just patching the previous listing that contains sprites flickering to also make the sprites moving on screen, no rebound effect.

Edited by newcoleco, Wed Sep 8, 2010 8:54 PM.


#11 retroclouds ONLINE  

retroclouds

    Stargunner

  • 1,367 posts
  • Location:Germany

Posted Thu Sep 9, 2010 1:32 PM

As always very nice Daniel!
Not only what you are trying to bring accross, but also how you do it is really cool :thumbsup: :thumbsup: :thumbsup:

#12 Heaven/TQA ONLINE  

Heaven/TQA

    Quadrunner

  • 8,910 posts
  • Location:Baden-Württemberg, Germany

Posted Wed May 25, 2011 3:53 AM

hi guys, I am not a Z80 expert but when I am going through your code and try to understand where is actually the flickering happening? the reordering routine does what?

#13 newcoleco OFFLINE  

newcoleco

    Stargunner

  • Topic Starter
  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Wed May 25, 2011 7:58 PM

hi guys, I am not a Z80 expert but when I am going through your code and try to understand where is actually the flickering happening? the reordering routine does what?

I don't know if it's clear but...

The reordering routine set a new "priority order" for the sprites. The top priority gives the advantage to the sprite to be shown without a problem screen. So if at least one sprite is the 5th sprite in a row, and so not displayed properly on screen, its number is set in the video register. Then we get its number and adjust the "priority" table to make this sprite the first one to be displayed. That's what the reordering code do. The routine that display the sprites on screen based ont the "priorities" table is the call $1fc4, a ColecoVision BIOS function named "WR_SPR_NM_TBL" for Write Sprite Name Table... or if you prefer, updating the sprites attributes (Y,X,Pattern#,Color) in the order defined by the table modified (or not) by the reordering routine.

#14 Heaven/TQA ONLINE  

Heaven/TQA

    Quadrunner

  • 8,910 posts
  • Location:Baden-Württemberg, Germany

Posted Wed May 25, 2011 11:39 PM

Thanks...

but can you comment the part in your source? because I played around with multiplexing sprites some years ago but on A8. so i discovered the ringbuffer approach on msx machines. why do I find this approach interesting? because A8 has 4 hardware sprites per scanline limit, too...

#15 newcoleco OFFLINE  

newcoleco

    Stargunner

  • Topic Starter
  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Thu May 26, 2011 3:30 PM

Nmi:
        ; Display Sprite(s) based on the priority table
        ld a,NBR_SPRITES
        call $1fc4 ; WR_SPR_NM_TBL

        ; Add the infamous $D0 that tells the video chip that there is no more sprites to display
        ld a,$d0
        out ($be),a

...

    
        ; Get Video Status
        call $1fdc ; READ_REGISTER

        ; If there is no 5th sprite issue, do nothing
        bit 6,a
        jr z,DoNothing

        ; Otherwise filter to get the sprite#
        and $1f ; keep only 5bits = sprite#

        ; Get the corresponding sprite entry from the priority table
        ld e,a
        ld d,0
        ld hl,($8004)
        add hl,de ; Add offset to the table address
        ld c,(hl) ; Get corresponding Sprite entry

        ; Do a sprites rotation, starting with the sprite that was identified as the 5th sprite
        ld hl,($8004)
        ld a,NBR_SPRITES
        ld b,a
reordering1:
        ld (hl),c
        inc hl
        inc c
        ; If the next sprite ID correspond to the number of sprites, set it instead as ID 0
        cp c
        jr nz,reordering2
        ld c,0
reordering2:
        djnz reordering1
DoNothing:
        retn

In words now, if there is no 5th sprite issue, the priority table stay the way it is. Otherwise, the routine I've coded here place the sprite detected as the 5th sprite to be the top priority by putting its ID as the first one in the priority table. The followed sprite IDs are in order the way you seem to have already experimented by using a ringbuffer if you like. The effect is of course displayed at the beggining of the next NMI interuption.

The initialization of the priority table for sprites is done in the main coding part, not in the NMI routine of course, and it's done by a call to a Coleco BIOS routine. And that's it!

#16 Heaven/TQA ONLINE  

Heaven/TQA

    Quadrunner

  • 8,910 posts
  • Location:Baden-Württemberg, Germany

Posted Mon May 30, 2011 12:15 PM

ok. which sorting algo did you use? and does it not get slow when rendering f.e. 32 sprites?

#17 Heaven/TQA ONLINE  

Heaven/TQA

    Quadrunner

  • 8,910 posts
  • Location:Baden-Württemberg, Germany

Posted Mon May 30, 2011 12:27 PM

and as far as I know the video chip sets 5th bit?

#18 newcoleco OFFLINE  

newcoleco

    Stargunner

  • Topic Starter
  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Mon May 30, 2011 3:03 PM

and as far as I know the video chip sets 5th bit?

You are talking here about the video status register we have to read everytime and in which we can get a valuable information. Yes, it's supposed to be the 5th bit...

The video status register is structured into 3 flags, 1 bit each, and a sprite # (from 0 to 31) in 5 bits.

Please note that bits are numbered according to the power of 2 they represent, so the lowest bit is also named bit-0 (2^0 = 1), and the highest bit (in a byte) is named bit-7 (2^7 = 128).

FLAGS

Bit 7 (aka INT-eruption) is set when the screen is refreshed, because my engine is coded into the NMI part, this information is useless.

Bit 6 (aka C-ollision) is set when there is a sprite collision, unfortunately you don't know which sprite made the collision.

Bit 5 (aka 5th-sprite) is set when there is a 5th sprite issue, and the sprite number (from 0 to 31) is set into 5 bits (bit 4, bit 3, bit 2, bit 1 and bit 0).

So, I'm wrongly checking bit 6 for the 5th sprite issue... good observation! I'm wondering now why my code sample is working... maybe it's by luck or my source documentation is wrong (I don't think so) or you can't trust emulators or a mix of all these probabilities.

As for the sorting algorithm, I'm not trying to order sprites by sorting them but by shifting their priorities... this is the fastest and easiest way to deal with it. It's just a simple loop to cover the number of sprites, with almost no cpu usage each loop. So, it's really fast, but can't be the proper one to use for each project.

#19 Heaven/TQA ONLINE  

Heaven/TQA

    Quadrunner

  • 8,910 posts
  • Location:Baden-Württemberg, Germany

Posted Mon May 30, 2011 10:36 PM

ok. Daniel, now it gets interesting as you mentioned no sorting...

what if in worst case all 32 sprites are sitting on the same line? the video hardware will mark the first 5th sprite? so you assume that all others are on the same then afterwards?

what if you have 6 on the same line while sprite 7-32 are having no 5th sprite issue at all?

I played around with some sprite multiplexer on c64 and a8 and most of them sort the sprites by y-axis and then perfom checks if sprite limit is reached for each scanline or screen zone.

and ring buffer method is used mainly on MSX/TI/COLECO machines.

A8 has 4 sprite hardware per scanline but no hardware is detecting the bandwith but this could be done by software no problem at all. I only know one Atari800 game... check out Joust which uses ring buffer IMHO.

thanks for explaining more...

#20 newcoleco OFFLINE  

newcoleco

    Stargunner

  • Topic Starter
  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Tue May 31, 2011 12:51 AM

Ok, I will try with something more visual. Suppose the following list the table of sprites priorities, telling simply which sprite to display first, second, etc.

The initial state :
  • 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

The ColecoVision BIOS routine look at this table and "display" the sprites in this order : first it's sprite#0, then sprite#1, etc. Let's suppose the video register tells you that the 7th sprite it displayed on screen do have an issue of 5th sprite in a row and so didn't display entirely on screen. My alorithm look for the sprite# is the 7th sprite in the prority table, instantly we get sprite#6. Then, my algorithm constuct the next table of sprites priorities like this, staring with sprite#6.


New state, starting with sprite#6 :
  • 6
  • 7
  • 8
  • 9
  • 0
  • 1
  • 2
  • 3
  • 4
  • 5

Because it's the first sprite to be displayed on screen, sprite#6 is displayed properly, no 5th sprite issue for this one. You bet that there is still a 5th sprite issue if these sprites are pretty much at the same positions as before on screen, but this time it's not sprite#6 that will have an issue.

The way my algorithm build up the new table of priorities is simply : first it's sprite#6, increment, second it's sprite#7, increment, third it's sprite#8, increment, fourth it's sprite#9, increment *warning next sprite# can't be 10*, fifth it's sprite#0, increment, and so on. As you can see, there is no sorting, it's just shifting the sprites order, nothing complex to keep it runs fast.

In the case of 32 sprites on screen, there is just more possibilities to get a 5th sprite issue, the algorithm doesn't change really, except for the number of sprites to show and consider when it's time to reorder them in the sprites priority table.

If I understand the video chip documentation correctly, in case of many 5th (or even 6th, 7th...) sprite issues, it's the first one detected based on the scanlines that is registered in the video register status. Scanlines are from top to bottom, left to right. It's not something we control, it's hardware stuff we have to deal with.

You may want to force a certain order that is different than what my solution provides, and as I said my routines presented here in these codes aren't necessary appropriate for any projects, and so you have to make some experimentations first, more thinking than simply reusing again and again a solution like the one I'm suggesting here and hope it works.

#21 Heaven/TQA ONLINE  

Heaven/TQA

    Quadrunner

  • 8,910 posts
  • Location:Baden-Württemberg, Germany

Posted Tue May 31, 2011 8:35 AM

ok. assume following... you have 32 virtual sprites. like in Konami games...so the VDP detects the 5th sprite but not more... so you would need to do it via software?

so calculating the overlappings? or how is Konami working with it's ring buffer?

#22 newcoleco OFFLINE  

newcoleco

    Stargunner

  • Topic Starter
  • 1,170 posts
  • In depression
  • Location:Quebec

Posted Tue May 31, 2011 11:03 AM

ok. assume following... you have 32 virtual sprites. like in Konami games...so the VDP detects the 5th sprite but not more... so you would need to do it via software?

so calculating the overlappings? or how is Konami working with it's ring buffer?

It all depends on what you want to accomplish... I'm not sure what you are looking for either. Anyway, overall my solution is very simple and works fine for some cases, it's enough complex to introduce people to the principle of sprites flickering. I've said already that it's not proper for every projects, it's not a miracle solution, but it does the job regardless of the number of sprites.

If we consider a 32 sprites case, which is the limit for this video chip, the case of flickering sprites is always a question of what is the "best looking" result. My solution provides a quick solution that flickers only a small number of sprites. For some games, a solution like this isn't appropriate, and a more "ghostly" effect is done by flickering pretty much all sprites all the time and the idea is to avoid some sprites to be too often not shown properly on screen by giving somehow an equal chance for every sprite. Also, it may be considered important to not flicker the player's avatar (or spaceship or whatever) because there can be an issue of not knowing where it is on screen... and so on about special cases, what you want to accomplish, etc.

There are other things than sprites in a videogame project that are also important to deal with, so it's important to not use too much CPU time for sprites. And because each programmer and each videogame project are different, if it's important for a project to know all the 5th, 6th, 7th sprites cases, of course the coding for sprites (including the flickering effect) will be more complex, using more CPU time. I'm telling you that you can't do it, like what you suggested in you last message, I'm simply telling you that it might not be necessary. For certain game engines that need a lot of calculations, a too complex approach will slow down the rendering which is not good. So you have to decide what is more important and code it well, and simplify what isn't that important in order to make the videogame run fast. If you simply use the same sprites flickering effect for every project, it may be fine for your needs, but a more specific approach depending on the project specifications is always a better idea but need of course more coding to do (compared to re-using the same codes again and again). And if you are looking for a simple approach that runs fast, my solution is pretty much the best one around, but again may not be suitable for your needs.

As for Konami routines, I have no clue... ask those who made ports of Konami games.

I hope this answer all your questions regarding my ColecoVision sprites sample assembly codes listing.

Edited by newcoleco, Tue May 31, 2011 11:04 AM.


#23 SpiceWare ONLINE  

SpiceWare

    Quadrunner

  • 8,169 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Tue Feb 7, 2012 10:26 PM

Busy evening - got the current version of zasm to compile on my MacBook Pro and started work on a mode file (syntax coloring rules) for jEdit.

Dropped in your sample from the first post
cv_jedit.png

and after commenting out fname and cpu, voila
cv_mugrat.png
(yes, the flicker works as expected)

Now to start learning Z80 assembly!


Wonder how long until my SD cart arrives(I ordered it last Tuesday). Anticipation :D

#24 evg2000 OFFLINE  

evg2000

    Dragonstomper

  • 968 posts
  • Location:N. Cal

Posted Tue Feb 7, 2012 11:40 PM

Busy evening - got the current version of zasm to compile on my MacBook Pro and started work on a mode file (syntax coloring rules) for jEdit.

Any chance of getting a copy of zasm for mac and your jedit mode file? Not sure if I would ever be able to do anything with it, but figure it doesn't hurt to have around. Years ago I started working on trying to code a CV game in C on my PC, but now I use a mac and don't know if there are any mac tools for CV coding. Yes I know I could run xp in bootcamp or in a VM, but really don't want to.

Edited by evg2000, Tue Feb 7, 2012 11:41 PM.


#25 SpiceWare ONLINE  

SpiceWare

    Quadrunner

  • 8,169 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Tue Feb 7, 2012 11:51 PM

I plan to post them in my blog when I finish the first draft of my mode file.

Edited by SpiceWare, Tue Feb 7, 2012 11:52 PM.





0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users