Jump to content
IGNORED

Player missiles and Wsync.


Grevle

Recommended Posts

im trying to improve my racing game, On real hardware the cars coming Down the screen seems to have some small artifacts related to the way the players are drawn or perhaps missing wsync og duble buffering, so what would be the correct way of drawing players moving Down screen, and how can i implement wsync or double buffering ?,

 

since im a beginner With Assembler my code is kinda sloppy i Guess , heres how i Draw the cars coming Down the screen, fetching the CAR data directly:

 

 

0365 CAR1

0370 ;Draw Roadcar 1

0430 LDX #0

0450 LDY P0Y

0470 LORA

0490 LDA CAR,X

0510 STA P0,Y

0530 INX

0550 INY

0570 CPX #36

0580 BNE LORA

0595 INC P0Y

0560 RTS

Link to comment
Share on other sites

im trying to improve my racing game, On real hardware the cars coming Down the screen seems to have some small artifacts related to the way the players are drawn or perhaps missing wsync og duble buffering, so what would be the correct way of drawing players moving Down screen, and how can i implement wsync or double buffering ?,

 

since im a beginner With Assembler my code is kinda sloppy i Guess , heres how i Draw the cars coming Down the screen, fetching the CAR data directly:

 

 

0365 CAR1

0370 ;Draw Roadcar 1

0430 LDX #0

0450 LDY P0Y

0470 LORA

0490 LDA CAR,X

0510 STA P0,Y

0530 INX

0550 INY

0570 CPX #36

0580 BNE LORA

0595 INC P0Y

0560 RTS

 

Without exactly seeing/kowing what kind of artefacts you've got I can only think of two things:

 

1) Do you have emtpy line(s) above (and below) your sprite data?

If not you have to clear the data from the last frame

 

2) Do you call this routine in the vertical blank time (scan-lines 248- 7)?

 

 

You didn't asked for it, but here goes a tip you might even know.

Try always to count down to 0 or -1. In that case you can skip the CPX instruction.

For example:

clc                     ; or skip if state of C is known
lda P0Y
adc #36-1
tay
ldx #36-1               ; "-1" because auf BPL. See below

...
DEX
DEY
BPL LORA
INC P0Y
RTS

 

 

Oh, you could save even more cycles:

    clc                     ; or skip if state of C is known
    lda P0Y
    adc #36                 ; (1) see below
    tay
    ldx #36-1

LORA:
    LDA CAR,X
    STA P0Y-1,Y              ; compensate for (1)
    DEX
    DEY
    BNE LORA                ; the last iteration is special
    STY P0Y                 ; should be P0Y+1

; last iteration with X=0
    LDA CAR,X
    STA P0Y-1,Y
    RTS

DISCLAIMER:

I just woke up, so if I made a mistake above please someone correct me :)

Link to comment
Share on other sites

WSync should only matter if you're plugging the graphics registers directly or changing the HPOS registers onscreen in order to generate more objects.

 

Store to WSync generally means the next store to a hardware register will occur a couple of character cells to the right of a standard width screen, Altirra with extra width applied to the video window shows this well, the ubiquitous rainbow colour curtains will show the colour change illustrating where the register store has occurred.

 

Ripping onscreen can sometimes be an emulation issue so always good idea to test on real HW.

 

Other cause of such a thing might be if you're doing animation/movement stuff during the active display. It's a good idea to do that stuff during VBlank so that you don't risk it.

Link to comment
Share on other sites

Well its probably a VBI issue, as the artifacts looks similar to tearing, so Im realy not sure on how to go about this, Move players during Vblank, does this mean the actual drawing or only the movement itself, ?, i read som articles on the net and being a beginner With assembler, Its not so easy get a Clear understanding on exaclty this work and how i can implement it into my code.

Link to comment
Share on other sites

Move players during Vblank, does this mean the actual drawing or only the movement itself, ?, i read som articles on the net and being a beginner With assembler, Its not so easy get a Clear understanding on exaclty this work and how i can implement it into my code.

The actual drawing. The short version is that, at least until you become experienced enough to see how it works and what uses the side effects can be put to, you should try to avoid changing anything on screen when it's actually being displayed.

Link to comment
Share on other sites

If you are moving the car horizontally the artifacting should look like tearing, if you are only moving up or down the artifacting should look like the sprite expands or shrink vertically.

Do you have all your code in assembler? Are you using some form of screen syncronization (to know that you only do one logic step per frame)? If not when you add more code/logic to your program the speed of everything is going to change..

Normally you should draw the graphics outside the screen draw time (or in a way that the electron beam doesn't catch you x) ). You could do that using a VBI or DLI.

Also you could use an easy check for the value in VCOUNT, like this:

   lda #100     ; sync draw to this scan line position
b1 cmp VCOUNT
   bne b1

And then draw your sprites. You shouldn't have more than one of those checks per frame.

Also remember that with this you can waste a lot of useful time, just waiting to get to that line .. is not the ideal method. A DLI or VBI is a better one, most of the time.

If you didn't have your program already in sync with the screen draws, then probably your code is going to be "slower" now (but you should do this at some point anyway).

 

The advice to erase the previous data is a good one, if not you should add more blank lines to your sprite data if you increase the Y speed of your cars.

 

 

Link to comment
Share on other sites

You should of course read up on the VBI stuff. You need it in EVERY game you code.

Reasons for that are hidden in NRV's post.

But for now, you can use the code below. When you see that it works then you might be more patient to read what you are actually doing :)


; in the init of your program
    LDX #>isr_vbi
    LDY #<isr_vbi
    LDA #7
    JSR $E45C        ; SETVBV


; somewhere else
isr_vbi:
    jsr car_move      ; change position of car
    jsr car_draw      ; write data to PMG memory
    jmp $E462         ; XITVBV

BTW, when you are beginner its best to start writing the code nice and clean.

A JSR/RTS does only cost 12 cycles and avoids unreadable code.

Edited by Creature XL
  • Like 1
Link to comment
Share on other sites

  • 4 weeks later...

I started to try to understand the VBI Stuff and as i understand a VBI interrupt is a Jump to a user specific Rotuine during Vblank, Ideal to Draw players , and then does the program just jump back to the end of the Vblank and contuine as normal ?

 

I tried the examples above and the LDA#100 Wait for line 100 is very slow, the other example With the isr_vbi gives me error when trying to assemble With atasm the error is unknown symbol isr_vbi, being a beginner im i dont know what adress should be equalent to isr_bvi ?

 

I probably need some "roadchart" to VBI i mean, easy explanation on the vbi stuff, mostly just the basics of a small vbi routine.

Link to comment
Share on other sites

the other example With the isr_vbi gives me error when trying to assemble With atasm the error is unknown symbol isr_vbi, being a beginner im i dont know what adress should be equalent to isr_bvi ?

 

I probably need some "roadchart" to VBI i mean, easy explanation on the vbi stuff, mostly just the basics of a small vbi routine.

 

Regarding my post above.

What I wanted to express is the following:

You need a subroutine - in the context of interrupts also called "Interupt Service Routine (isr)" which should be executed when the interrupt, in your case the VBI is triggered.

This routine I called "isr_vbi" It starts with the label "isr_vbi" and extends up to the final "JMP $e462". if your assembler handles labels differently then you have to adjust the code.

For example, some assemblers might not like the ":" or that a label is on a line all alone.

Secondly, you need to set the address whcih the CPU should jump to. This is done with the SETVBV routine by the Atari OS. See the first code box in my post above.

 

What happens (in simple words) is that ANTIC will trigger the VBI in scanline 248. The 6502 will then jump thru the vectro at $fffa/$fffb. This location is in the Atari OS ROM and points to a routine inside the Atari OS, which does some things and finally jumps thru another vector (containing the address of your VBI routine set by SETVBV).

You end your routine with JMP XITVBV ($e462). At that location is another routine from Atari which does some things and finally executes the instruction "RTI (Return from Interupt)" which is kinda like "RTS" and from that point on the main loop is continued.

 

I hope that helps. If you need more information just post.

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

I managed to create a small vbi, but as i understand the vertical Blank is 60 times a second ? so then Player would be drawn 60 times each second ?, that actually is slowing Down the program so isn,t it enough to Draw the player maybe 3 , 4 or five times each second ? and this is partially aswered in another post but does one use the rtclock adress here ? to tell when to Draw so that it no draws the player 60 times each second ?.

 

Whats the common way of doing this ?

 

Any small assembler example on the Rclock use or other common way on doing this would be helpful.

 

Thank you. :?

Link to comment
Share on other sites

I managed to create a small vbi, but as i understand the vertical Blank is 60 times a second ?

You're in PAL land so 50 times a second, but there's not much in it...

 

so then Player would be drawn 60 times each second ?, that actually is slowing Down the program so isn,t it enough to Draw the player maybe 3 , 4 or five times each second ?

Really you want to be redrawing players (and preferably, anything else moving) every frame to maintain smoothness, the slower you refresh the less smooth that movement becomes. If the reason you want to go slower is animation, go for a redraw every frame but only change which animation frame is being drawn every four refreshes and it'll slow down that side of things without making player movement look rough.

Link to comment
Share on other sites

Yes one Draw each frame is prefferable, heres what i dont understand, does one frame Equal the vbi drawing at 60 times a second , does the 60 times a second reffer to all lines of the screen being drawn from top to bottom 60 times a second or is the vbi after each line being Draw from left to right ? or is the vbi only after the all lines being drawn and the the beam Returns to top after the vbi ?

Link to comment
Share on other sites

Any halfway efficient PMG draw routine shouldn't cause slowdown.

 

The trick is of course, don't redraw all 1280 bytes of PMG data every frame.

 

Wipe all the PMG data back to zeros at certain times, e.g. game start, level start, game over before return to title screen etc.

 

For actual draws just maintain old/new vertical position. There's various methods to do draws.

The simplest is simply write zeros to "old" position for however tall the animation cell is.

Another simple method is have zeros surrounding the animation cells that are copied to the PMGs, then start the player draw just before and finish just after it's VPos. Although that only works if the object doesn't move too fast.

 

Possibly most efficient but more complex to write is to do a loop that conditionally writes zeroes before or after the object dependant on what directional change occurred, ie look at "old" vs "current" position.

 

Missiles can be somewhat complex but really it's just a case of clever merging operations.

Probably best method to use at first - wipe all missiles by writing zeroes to "old" positions for all.

For first missile, you can then simply write the data direct.

For other 3, use merging, ie load the data, OR it with what's already there then store it back.

Link to comment
Share on other sites

So i managed to create my first VBI, A little program With moving player and the movement is very smooth :).

 

I also realized that one sort of builds the Program/Game around the VBI , So My game Speedway One would need a huge part of rewriting to implement it , and that i have no motivation to do.

 

I Rather Put some efforts into New Projects.

 

I put Version 2.2 on my homepage . that is the Last Version of the game, the game have some small artifacts relating as of missing VBI but its not destroying the game. It has to stand as it is as a step

on the Atari 8-Bit Programming learning ladder ;) .

Edited by Grevle
  • Like 2
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...