Jump to content
IGNORED

Session 23: Moving Sprites Vertically


Recommended Posts

Hey Guys,

 

Although I'm having a great time messing around with this stuff, I was hoping you could give me a hand as I think if I keep going by Im going to be leading myself into a path of pain.

 

I've got a lil' guy moving up and down... kind of. He magically gets a hat when going down and a podium when going up. THough this isn't the bit thats really troubling me. I don't know where in each frame (before the frame starts, after the vertical syncs, during the screen drawing etc) I should be doing:

* Joystick checking

* Horizontal Positioning

* vertical positioning

 

In the horizontal positioning subroutine that Andrew listed it starts with "sta WSYNC" - does that mean I don't do the wsync at the end of the main loop as well?

 

Thank for your help

spriteMove.zip

Link to comment
Share on other sites

I don't know where in each frame (before the frame starts, after the vertical syncs, during the screen drawing etc) I should be doing:

* Joystick checking

* Horizontal Positioning

* vertical positioning

Joystick: best before positioning, since you want to react to the players input immediately.

Positioning: before the display kernel, after stuff like joystick, collision checking etc.

 

Actually, there is no strict pattern you have to follow. Just do it in some logical order. Later on, you might discover that reordering your code may make things easier.

 

In the horizontal positioning subroutine that Andrew listed it starts with "sta WSYNC" - does that mean I don't do the wsync at the end of the main loop as well?

The RESPx commands have to be timed exactly, so you need a WSYNC before. But that doesn't mean you have to do it inside the kernel. You can do everything whereever you want (except HMOVEs during vertical sync).

Link to comment
Share on other sites

Yes! Thanks Thomas!

 

I was trying to run the xpositioning code during the screen draw. Whoops! Now I've got a lil' guy running round the screen - on an atari 2600!!!

 

I have another query on the WSYNC thing though - if I do the 37 vertical blank WSYNC before drawing, then one WSYNC for the X Positioning code - then 192 WSYNCS for the screen then 30 WSYNCS for the overscan... don't I have 1 WSYNC too many? Doesn't that WSYNC I called for the X positioning push everything down one line?

Link to comment
Share on other sites

Yep, but most TVs are forgiving if you provide too many or too few lines, provided it's the same number of lines each time. ie sending 263, 263, 263 would be OK, but sending 262, 263, 262 will cause the screen to jiggle up/down.

 

You'll probably want to next look at replacing the 37 vertical blank WSYNCs and 30 overscan WSYNCs with the timer. Check this sample code from khryssun where he's using the timer for the vertical blank. The key things are setting the timer using TIM64T and checking if the timer is done using INTIM.

Edited by SpiceWare
Link to comment
Share on other sites

I love your Medieval Mayhem game too - great idea.

Thanks! I decided to do it after getting my nephew's friends hooked on Warlords when I was visiting this past Xmas. Having grown up with PS2s, they'd been been slamming the Atari's graphics. They changed their tune once they realized graphics weren't everything :lol:.

 

If you'd like to see the source for it, it's available in my blog.

Link to comment
Share on other sites

  • 9 years later...

does anyone have a working example of a skipdraw routine? I have seen many postings of the code for just the routine, but never a simple program that draws a sprite on the screen using skip draw. I have tried for the past few weeks, but can't seem to get it to work. I think if I saw a simple example that works, then I could see where I am going wrong. Any help would be much appreciated.

Thanks.

Link to comment
Share on other sites

  • 1 year later...

does anyone have a working example of a skipdraw routine? I have seen many postings of the code for just the routine, but never a simple program that draws a sprite on the screen using skip draw. I have tried for the past few weeks, but can't seem to get it to work. I think if I saw a simple example that works, then I could see where I am going wrong. Any help would be much appreciated.

Thanks.

I'm asking my self the same,

 

i have the same problem with this skipdraw routine, and can't understand how it works just for a few lines

 

how's possible to write pointer content to GRP0 register if A register isn't transferred to Y regsiter as index?

 

a little confused, even i saw this url:

 

http://www.biglist.com/lists/stella/archives/200309/msg00059.html

 

and there's a tay instruction before loading accumulator with pointer

 

TAY

LDA (ZERO_PAGE_PTR),y

STA GRP0

 

BUMP...

Edited by zilog_z80a
Link to comment
Share on other sites

ok, think it's done, now will take the bin and run into stella's debugger to understand in a more detailed way what's going on with carry and brach.

 

cheers.

 

 

processor 6502

include "vcs.h"
include "macro.h"
seg.u uninitialized
org $80
SpriteEnd ds 1
SPRITEHEIGHT equ 8
spriteP0 ds 2
SEG DATA
ORG $F000
Reset
lda #0
ldx #0
clear_mem
sta $0,x
inx
bne clear_mem
lda #30
sta COLUP0
lda #60
sta SpriteEnd ; SPRITE Y POSITION
lda #<Sprite0Data
sta spriteP0
lda #>Sprite0Data
sta spriteP0+1
Start_of_frame:
lda #0
sta VBLANK
lda #2
sta VSYNC
sta WSYNC
sta WSYNC
sta WSYNC
lda #0
sta VSYNC
ldy #36
vertical_blank
sta WSYNC
dey
bne vertical_blank
ldx #191
scan_lines:
sta WSYNC
sec
txa
sbc SpriteEnd
adc #SPRITEHEIGHT
bcc .skipDraw
tay
lda (spriteP0),y
sta GRP0
.skipDraw
dex
bne scan_lines
lda #%01000010
sta VBLANK
ldy #29
overscan
sta WSYNC
dey
bne overscan
jmp Start_of_frame
Sprite0Data
.byte #%00000000
.byte #%11111111
.byte #%00000000
.byte #%11111111
.byte #%00000000
.byte #%11111111
.byte #%11111111
.byte #%11111111
ORG $FFFA
InterruptVectors
.word Reset
.word Reset
.word Reset
END
Edited by zilog_z80a
Link to comment
Share on other sites

the only way i found to make Andrew's solution work was adding one instruction TAY please correct me if i'm wrong.

 

Andrew's solution

sec; ;2 can often be guaranteed, and omitted

tya ; 2
sbc SpriteEnd ; 3
adc #SPRITE_HEIGHT ; 2
bcs .MBDraw3 ; 2(3)
nop ; 2
nop ; 2
sec ; 2
bcs .skipMBDraw3 ; 3
.MBDraw3
lda (Sprite),y ; 5
sta GRP0 ; 3
.skipMBDraw3

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ldx #191
scan_lines:
sta WSYNC
sec
txa
sbc SpriteEnd
adc #SPRITEHEIGHT
bcs .draw
nop
nop
nop
sec
bcs .skipdraw
.draw
tay ; <······························································ EXTRA INSTRUCTION
lda (spriteP0),y ; use indirect loading here
sta GRP0
.skipdraw
dex
bne scan_lines
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Cheers.
Edited by zilog_z80a
Link to comment
Share on other sites

No, that's not the way it is meant to be.

 

SkipDraw is optimized for CPU time, therefore you have to setup the sprite pointers correctly outside the kernel. Also SkipDraw assumes that Y contains your current scanline and not X. Only then you can use Y directly for pointer reads and X is completely free for other stuff.

 

Also the branch to .draw wastes one cycle. To avoid that, branch the non-draw to somewhere outside the kernel and then return to .skipDraw.

Edited by Thomas Jentzsch
  • Like 1
Link to comment
Share on other sites

 

No, that's not the way it is meant to be.

 

SkipDraw is optimized for CPU time, therefore you have to setup the sprite pointers correctly outside the kernel. Also SkipDraw assumes that Y contains your current scanline and not X. Only then you can use Y directly for pointer reads and X is completely free for other stuff.

 

Also the branch to .draw wastes one cycle. To avoid that, branch the non-draw to somewhere outside the kernel and then return to .skipDraw.

 

Hi Thomas, ty for your fast reply, please can you show me some url with example code?
do you mean with, outside kernel, to set something outside the 192 scanlines? i have arranged pointers outside the 192 scanlines. am i right? (code bellow)
  processor 6502
   include "vcs.h"
   include "macro.h"
   
   seg.u uninitialized
   org $80
 
SpriteEnd ds 1
SPRITEHEIGHT equ 8
spriteP0 ds 2
 
   SEG DATA
   ORG $F000
Reset
 
   lda #0
   ldx #0
clear_mem
   sta $0,x   
   inx
   bne clear_mem
   
   lda #30
   sta COLUP0
   lda #60
   sta SpriteEnd ; SPRITE Y POSITION

;--------------------------------------------------------------------------------------------------------------------------- 
   lda #<Sprite0Data
   sta spriteP0
   lda #>Sprite0Data
   sta spriteP0+1
;--------------------------------------------------------------------------------------------------------------------------- 

I saw here: http://www.biglist.com/lists/stella/archives/200309/msg00060.html

 

this:

> .contDrawPlayer:
>     dey
>     tya
>     sbc yPosP0
>     adc #H_TANK
>     bcs.doDrawP0
>     lda #0
>     NOP_W
> .doDrawP0:
>     lda (ptrP0),y
>     sta.w GRP0

The key is the NOP_W, which is an equate for $0C, which is the opcode NOP
abs.  (An illegal/undocumented version of NOP.  The documented way is to use
$2C which is BIT abs)  So if the bcs is not taken the lda (ptrP0),y gets
absorbed into the NOP and is not executed.
 

Is sta.w another undocumented opcode too or just a type error?
i have found undocumented opcodes for 6502 but dunno if it works with 6507

http://nesdev.com/undocumented_opcodes.txt

returning about this subject, vertical position,

Dear Thomas, any example code would be really really appreciated.

Thanks again and thanks in advance.

 

 

Subject: [stella] Usefull illegal opcodes (part 1)
From: "Thomas Jentzsch" <tjentzsch@xxxxxx>
Date: Fri, 23 Feb 2001 08:59:28 +0100
Hi,yesterday, i was thinking about a faster way to decide in a kernel if you are on a sprite drawing line or not.The best way, i knew until now, was (if y contains linecounter):  tya                   ; 2 (sec                   ; 2) <- this can sometimes be avoided  sbc SpriteEnd         ; 3  adc #SPRITEHEIGHT     ; 2  bcx .skipDraw         ; 2 = 9-11 cycles  ...If you like using illegal opcodes, you can use dcp (dec,cmp) here:  lda #SPRITEHEIGHT     ; 2  dcp SpriteEnd         ; 5     initial value has to be adjusted  bcx .skipDraw         ; 2 = 9  ...Advantages:- state of carry flag doesn't matter anymore (may save 2 cycles)- a remains constant, could be useful for a 2nd sprite- you could use the content of SpriteEnd instead of y for accesing sprite data- ???Have fun!Thomas

 

Edited by zilog_z80a
Link to comment
Share on other sites

:idea: Check this post.

 

.w just tells the assembler to create a 3 byte instruction when you access a zero page address, which is useful if you want to waste 1 cycle.

 

 

Ty Thomas, was searching around the web for skipdraw and have found a lot of info, once my brain be able to process it... will post something here to receive your blessing.

 

pd: ty 4 da url.

 

cheers.

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

  • 7 months later...

 

2) Create another data table, and use a variable to determine which of the two data tables to display. You might like to have it switch between these tables every second, or perhaps use the joystick button to determine which is displayed. As a hint - remember, you need to setup the zero page pointer to point to the table for your sprite draw to use - so all you need to do is change this pointer, and leave your kernel code alone.

 

I am back after a 13-year hiatus. I was about to give up on this one, but after having a little talk with Jesus, I figured it out. I was beginning to think that my 47-year old brain didn't work well anymore. Anyway, I borrowed a little code from Kirk Israel and nmoog, and came up with the attached solution to Exercise 2. It uses a variable to point to one of 6 tables based on input (or lack thereof) from the joystick. Programming the Atari VCS is definitely challenging, but I am determined.

 

The program reacts accordingly to joystick left, right, up, down, button or no input at all. Now on to exercise 3. :grin:

kernel10-2.bin

Edited by Sheldon Sims
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...