Jump to content



0

Session 13: Playfield Basics


43 replies to this topic

#26 antron OFFLINE  

antron

    Chopper Commander

  • 196 posts

Posted Thu Dec 4, 2003 4:08 PM

Is there a way to get the TIA to end the horizontal blank a little early or late, to shift the playfield (or everything) 1 pixel left or right? I want to scroll the playfield one pixel at a time. Otherwise it will be very jerky (four-pixel jumps).

#27 Andrew Davie OFFLINE  

Andrew Davie

    Stargunner

  • 1,314 posts
  • Location:Tasmania

Posted Thu Dec 4, 2003 4:32 PM

antron said:

Is there a way to get the TIA to end the horizontal blank a little early or late, to shift the playfield (or everything) 1 pixel left or right?  I want to scroll the playfield one pixel at a time.  Otherwise it will be very jerky (four-pixel jumps).

No. The finest playfield scroll possible is 4 colour clocks.
Cheers
A

#28 antron OFFLINE  

antron

    Chopper Commander

  • 196 posts

Posted Fri Dec 5, 2003 7:36 PM

what will RSYNC (reset sync) do if called 3 colour clocks into a horizontal blank?

skip that line?

#29 EricBall OFFLINE  

EricBall

    Dragonstomper

  • 711 posts
  • Location:Markham, Ontario, Canada

Posted Mon Dec 8, 2003 10:52 AM

antron said:

what will RSYNC (reset sync) do if called 3 colour clocks into a horizontal blank? skip that line?

RSYNC resets the TIA's internal horizontal position counter.

Now, if I assume this resets the counter back 0, the same point that WSYNC releases, this would be before the sync pulse. So hitting RSYNC during horizontal blank would probably generate a double sync pulse which would probably throw the TV for a loop, probably causing it to skip down to the next line or half line.

And even if the TV was able to sync properly, it also wouldn't change the object positions since the counters would still put it the same number of clocks after the end of the sync pulse.

#30 antron OFFLINE  

antron

    Chopper Commander

  • 196 posts

Posted Mon Dec 8, 2003 11:33 AM

I will try it anyway.

thanks everyone

#31 antron OFFLINE  

antron

    Chopper Commander

  • 196 posts

Posted Sat Apr 17, 2004 9:19 AM

I wrote to RSYNC 3 CPU cycles into a horizontal blank and this is what I got.

I took it a while to find the correct zero point again, so I decided to help it out by calling RSYNC again at the end of that line. It somewhat worked. Player 1 never got back on track, but that could be fixed. I am just trying to get the playfield into new positions.

Attached Thumbnails

  • shift.jpg
  • fix.jpg


#32 Andrew Davie OFFLINE  

Andrew Davie

    Stargunner

  • 1,314 posts
  • Location:Tasmania

Posted Sat Apr 17, 2004 9:25 AM

antron said:

I wrote to RSYNC 3 CPU cycles into a horizontal blank and this is what I got.

I took it a while to find the correct zero point again, so I decided to help it out by calling RSYNC again at the end of that line.  It somewhat worked.  Player 1 never got back on track, but that could be fixed.  I am just trying to get the playfield into new positions.

Very interesting indeed. Keep up the experiments and let us know the results. I'd suggest you post this to the [stella] list, too :)

Cheers
A

#33 antron OFFLINE  

antron

    Chopper Commander

  • 196 posts

Posted Sat Apr 17, 2004 9:44 AM

Here it is called one cpu cycle (I think) into a h-blank.
I was hoping it wouldn't bounce as much, but it did. The *fix* doesn't help much.

Attached Thumbnails

  • 3cc.jpg


#34 kamakazi OFFLINE  

kamakazi

    Moonsweeper

  • 339 posts
  • Location:Moberly, Missouri

Posted Tue Sep 14, 2010 12:44 AM

I'm hoping that there are still some visiting this that can help me. I took Mr. Davie's playfield code and typed it in manually (instead of copy and paste) to try and understand Assembly and the 2600 as I went along. Upon compiling, DASM didn't return any errors. However, when I tried to run the program through Stella, I'm getting a lot of weird noises and no visuals. I'm going to post the code the way I typed it into Crimson here...

; 2600 For Newbies
; Session 13 - Playfields

	processor 6502
	include "vcs.h"
	include "macro.h"
	
PATTERN = $80
TIMETOCHANGE = 20

	SEG
	ORG $F000

Reset

	ldx #0
	lda #0

Clear

	sta 0,x
	inx
	bne Clear
	
	lda #0
	sta PATTERN
	lda #$45
	sta COLUPF
	ldy #0
	
StartOfFrame

	lda #0
	sta VBLANK
	lda #2
	sta VSYNC
	sta WSYNC
	sta WSYNC
	sta WSYNC
	lda #0
	sta VSYNC
	ldx #0
	
VerticalBlank

	sta WSYNC
	inx
	cpx #37
	bne VerticalBlank
	iny
	cpy #TIMETOCHANGE
	bne notyet
	ldy	#0
	inc PATTERN
	
notyet

	lda PATTERN
	sta PF1
	ldx #0
	
Picture

	stx COLUBK
	sta WSYNC
	inx
	cpx #192
	bne Picture
	lda #%01000010
	sta VBLANK
	ldx #0
	
Overscan

	sta WSYNC
	inx
	cpx #30
	bne Overscan
	jmp StartOfFrame
	
	ORG $FFFA
	
InterruptVectors

	.word Reset
	.word Reset
	.word Reset
	
	END

On the DASM command line, all I did was type at the prompt: dasm playfield.asm -oplayfield. I'd really like to know what I'm doing wrong. In the code, I didn't use most of the remark statements has I was going to refer to the original if I needed to. Help anyone?

Attached Files



#35 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,547 posts
  • Location:Georgia, USA

Posted Tue Sep 14, 2010 1:10 AM

View Postkamakazi, on Tue Sep 14, 2010 12:44 AM, said:

On the DASM command line, all I did was type at the prompt: dasm playfield.asm -oplayfield. I'd really like to know what I'm doing wrong. In the code, I didn't use most of the remark statements has I was going to refer to the original if I needed to. Help anyone?
When I copied and pasted your listing into Crimson Editor, then assembled it, it worked for me, so there's nothing wrong with the code. However...

(1) I had to add an "INCDIR" at the beginning to tell DASM where the include files are, because I happen to have them in a different folder than DASM and the program code. Make sure DASM knows where the "vsc.h" and "macro.h" files are. I assume you have them in the same folder as DASM, since you apparently didn't get any assembly errors about unknown label names, but this is something to keep in mind.

(2) I don't see a "-f3" parameter in your command line. Try this: dasm playfield.asm -f3 -oplayfield.bin

Michael

Edit: Correction, I just noticed that I was already using the "-I" switch in my command line to tell DASM where I have my include files, so I was able to take out the "INCDIR" line and assemble it just fine. Note that if you're using Crimson Editor, you can configure one User Tool to call DASM to assemble your programs, and another User Tool to call Stella to run them. That's a lot easier than typing in command lines. If you need help setting up User Tools in Crimson Editor, I'd be happy to assist you with it.

Edited by SeaGtGruff, Tue Sep 14, 2010 1:28 AM.


#36 kamakazi OFFLINE  

kamakazi

    Moonsweeper

  • 339 posts
  • Location:Moberly, Missouri

Posted Tue Sep 14, 2010 1:46 AM

I would appreciate the help in setting up Crimson User Tools to do those tasks.

EDIT: The -f3 did the trick. Weird. I got used to not using it when trying to compile some 7800 samples.

Edited by kamakazi, Tue Sep 14, 2010 1:52 AM.


#37 kamakazi OFFLINE  

kamakazi

    Moonsweeper

  • 339 posts
  • Location:Moberly, Missouri

Posted Tue Sep 14, 2010 2:25 AM

I know I'm probably the only one that is following this right now as I'm a few years behind...but I did manage to figure out how to reverse the colors so that the background has the solid color while the bars have the rainbow colors. That one was easy...just switch the COLUBK and COLUPF commands around.

Attached Thumbnails

  • playfield.bin.png

Attached Files



#38 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,547 posts
  • Location:Georgia, USA

Posted Tue Sep 14, 2010 8:43 PM

View Postkamakazi, on Tue Sep 14, 2010 1:46 AM, said:

I would appreciate the help in setting up Crimson User Tools to do those tasks.
To set up a User Tool for assembling with DASM...

(1) Start Crimson Editor.

(2) Select "Tools" and "Conf. User Tools".

(3) Click on the entry you want to set up, presumably the first one that says "- Empty -" (which is probably already highlighted).

(4) Click in the "Menu Text:" field and enter whatever you want it to say on the menu-- e.g., "Assemble 6502 Program", or "Assemble with DASM", etc.

(5) Click in the "Command:" field and enter the name of the program you want to call (run) whenever you choose this tool, including its path if it isn't in the current folder. I have mine set up to say

C:\Atari2600\bB\dasm.exe

because I've put DASM in a folder named C:\Atari2600\bB on my computer.

(6) Click in the "Argument:" field and enter the *parameters* for the command line. I have mine set up to say

"$(FilePath)" -f3 -IIncludes -o"$(FilePath).bin" -l"$(FilePath).lst"

In order, these are

"$(FilePath)" -- $(FilePath) is Crimson Editor's name for the file that's displayed in the active tab, including its full path (e.g., C:\MyFolder\MyFile.asm). Putting it in quotes lets you include spaces in the path and/or filename without confusing DASM (e.g., "C:\My Folder\My File.asm").

-f3 -- tells DASM to output the assembled ROM image in the "raw" format, which is the format required for Atari 2600 ROM images.

-IIncludes -- tells DASM which folder the include files are in. This is optional, but is helpful if (like me) you prefer to create subfolders for organizing things. It can be a full path, including surrounding quotes if the path contains spaces in it, or it can be just a folder name if the indicated folder is a subfolder of the current folder.

-o"$(FilePath).bin" -- tells DASM what to call the output file. $(FilePath) is described above, but Crimson Editor has other options available (see below). If you use this just as I've shown here, assembling a file named "C:\My Folder\My File.asm" will produce a ROM image named "C:\My Folder\My File.asm.bin".

-l"$(FilePath).lst" -- tells DASM what to call the listing file. This is optional, and you might not need to look at the listing file, but I find it helpful to have the assembly listing available in case of bugs, because you can check the listing to see what machine code was generated, along with any error messages. If you use this just as I've shown, assembling a file named "C:\My Folder\My File.asm" will produce a listing named "C:\My Folder\My File.asm.lst".

(7) Click in the "Initial Dir:" field and enter the path for the folder you want to use as the "current" or "start in" directory when using this tool. I have mine set to say

C:\Atari200\bB

(8 ) You can click in the "Hot Key:" field and assign a hot key to this tool if you want.

(9) Check or uncheck the boxes for the options you want to use with this tool. For my DASM tool I have the following two boxes checked:

Capture output -- so you can see the messages that DASM produces when you run it.

Save before execute -- so that if you select this tool without remembering to save any changes first, the file in the active tab will be automatically saved before DASM assembles it.

(10) Click on the "Apply" button to save the setup for this tool before you set up another one.



To set up a User Tool for running the assembled program in the Stella emulator...

(1) Click on another entry that says "- Empty -". I'll just list what I put in the other fields, since the general procedure is already described above.

(2) "Menu Text:" -- Run Program in Stella

(3) "Command:" -- C:\Atari\2600\Emus\Stella\3.2.1\32-bit\stella.exe

(Your entry will probably look a lot simpler than mine!)

(4) "Argument:" -- "$(FilePath).bin"

(5) "Initial Dir:" -- C:\Atari\2600\Emus\Stella\3.2.1\32-bit

(6) "Hot Key:" -- None

(7) Checked options:

Close on exit

(8 ) Click "Apply", or else click "OK" if you're done setting up your User Tools.



Crimson Editor recognizes the following symbolic names for the file in the active tab:

$(FilePath) -- the file path, filename, and file extension.

$(FileDir) -- just the file path, *without* the filename and file extension.

$(FileName) -- just the filename and file extension, *without* the file path.

$(FileTitle) -- just the filename, *without* the file path and file extension.

You can combine these if you wish, although the only combination that's of much use is $(FileDir)\$(FileTitle), since that lets you get rid of the original file extension and tack on a different file extension (like ".bin").

For example, if the file in the active tab is called C:\My Folder\My File.asm, the various symbolic names would be as follows:

$(FilePath) -- C:\My Folder\My File.asm

$(FileDir) -- C:\My Folder

$(FileName) -- My File.asm

$(FileTitle) -- My File

$(FileDir)\$(FileTitle).bin -- C:\My Folder\My File.bin

$(FileDir)\$(FileTitle).lst -- C:\My Folder\My File.lst



Michael

Edited by SeaGtGruff, Tue Sep 14, 2010 8:44 PM.


#39 kamakazi OFFLINE  

kamakazi

    Moonsweeper

  • 339 posts
  • Location:Moberly, Missouri

Posted Wed Sep 15, 2010 2:02 AM

Yea...I'm using DASM that came with batari Basic as well. But it works and includes the needed vcs and macros files. I'll configure Crimson now.

#40 kamakazi OFFLINE  

kamakazi

    Moonsweeper

  • 339 posts
  • Location:Moberly, Missouri

Posted Mon Sep 20, 2010 11:38 PM

While we are on the playfield basics, am I understanding correctly that the 2600 can produce a 160x192 resolution? Am I also understanding correctly that in a single horizontal scanline, I can "control" what playfield pixel goes where by simply knowing where the beam is? Now...if that is the case...and I'm still getting confused on the playfield portion, what Assembly opcodes do I use to start and stop a playfield graphic position?

#41 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 20,458 posts
  • Location:The land of Gorch

Posted Tue Sep 21, 2010 12:11 AM

Might be time to look at this thread ;)

#42 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,547 posts
  • Location:Georgia, USA

Posted Tue Sep 21, 2010 4:25 AM

View Postkamakazi, on Mon Sep 20, 2010 11:38 PM, said:

While we are on the playfield basics, am I understanding correctly that the 2600 can produce a 160x192 resolution? Am I also understanding correctly that in a single horizontal scanline, I can "control" what playfield pixel goes where by simply knowing where the beam is? Now...if that is the case...and I'm still getting confused on the playfield portion, what Assembly opcodes do I use to start and stop a playfield graphic position?
The "160x192 resolution" is an idealized number that represents the total number of *positions* on the screen, as measured in color clocks and scan lines. (The 2600 can display more than 192 scan lines, but 192 is considered to be the "preferred" number of scan lines for an NTSC game, so we'll stick with that.) Since the playfield is the *only* graphical object on the 2600 that can span the full width of the screen (aside from the background), and playfield pixels are 4 color clocks wide, it's probably more accurate to say that the 2600 has a resolution of 40x192, but with sprites that can have a higher resolution than that. If you use the "score trick" to display 6 player sprites side-by-side (3 copies of player0, and 3 copies of player1), you can display a bitmap with a resolution of 48x192, where each pixel is 1 color clock wide. And if you spread out the copies of the players, and use 30Hz flickering, you can get a resolution of 96x192-- but it isn't a "solid" image, because each pixel will flicker. So even though it's usually stated that the 2600 has a "resolution" of 160x192, you can't actually display an image with that resolution on the screen (i.e., where each 160x192 position is individually addressable).

Also, you can't control where a playfield pixel goes on the screen-- the playfield pixels are at set positions, and all you can do is turn a particular playfield pixel on or off. There are only 3 playfield registers-- or to be more exact, 2.5 playfield registers, since one of them (PF0) is only half-size (4 bits or 4 pixels), and the other two are full-size (8 bits or 8 pixels). That gives you 20 playfield pixels that you can turn on or off (4+8+8=20). Since the screen is 40 playfield pixels wide, that means the 20 playfield pixels cover only one-half of the screen. The screen is divided into a left half and a right half, and the same playfield pixels that are drawn on the left half get reused to draw the right half. The left half is always drawn the same way-- PF0 (first 4 playfield pixels), PF1 (next 8 playfield pixels), and PF2 (next 8 playfield pixels). There are two different modes that determine how (or where) the playfield pixels will be displayed for the right half-- repeated mode, and reflected mode. In the repeated mode, the right half of the screen is drawn just like the left half-- PF0, PF1, and PF2. In the reflected mode, the right half of the screen is a mirror image of the left half-- PF2, PF1, and PF0, with the bits of the playfield registers displayed in the opposite order from normal.

To get an "asymmetrical" playfield-- where the left and right halves are completely different than each other (neither repeated nor reflected), you have to set the PF0, PF1, and PF2 registers for the left half of the screen, then change them midline before the right half of the screen is drawn. You still have to choose either repeated or reflected mode, and the mode you choose will affect the timing for when you can update each register midline. To set that register for the left half of the screen, you must do so between the time it's finished being drawn on the right half and the time it's starting to be drawn on the left half. And to set that register for the right half of the screen, you must do so between the time it's finished being drawn on the left half and the time it's starting to be drawn on the right half.

Updating PF0 (repeated mode):
|. . . . . . . . . . . . . . . . .|. . . . left half of the screen . . . .|. . . .right half of the screen . . . .|
|. horizontal blanking interval. .|. PF0 .|. . . PF1 . . .|. . . PF2 . . .|. PF0 .|. . . PF1 . . .|. . . PF2 . . .|
|. . . . . . . . . . . . . . . . .|. . . .|. . . . . . . .|. . . . . . . .|. . . .|. . . . . . . .|. . . . . . . .|
|. . . . . . . . . . . . . . . . .A. . . .B. . . . . . . . . . . . . . . .C. . . .D. . . . . . . . . . . . . . . .|
For the left copy of PF0, set PF0 to the desired value between point D and point A.
For the right copy of PF0, set PF0 to the desired value between point B and point C.

Updating PF1 (repeated mode):
|. . . . . . . . . . . . . . . . .|. . . . left half of the screen . . . .|. . . .right half of the screen . . . .|
|. horizontal blanking interval. .|. PF0 .|. . . PF1 . . .|. . . PF2 . . .|. PF0 .|. . . PF1 . . .|. . . PF2 . . .|
|. . . . . . . . . . . . . . . . .|. . . .|. . . . . . . .|. . . . . . . .|. . . .|. . . . . . . .|. . . . . . . .|
|. . . . . . . . . . . . . . . . . . . . .A. . . . . . . .B. . . . . . . . . . . .C. . . . . . . .D. . . . . . . .|
For the left copy of PF1, set PF1 to the desired value between point D and point A.
For the right copy of PF1, set PF1 to the desired value between point B and point C.

Updating PF2 (repeated mode):
|. . . . . . . . . . . . . . . . .|. . . . left half of the screen . . . .|. . . .right half of the screen . . . .|
|. horizontal blanking interval. .|. PF0 .|. . . PF1 . . .|. . . PF2 . . .|. PF0 .|. . . PF1 . . .|. . . PF2 . . .|
|. . . . . . . . . . . . . . . . .|. . . .|. . . . . . . .|. . . . . . . .|. . . .|. . . . . . . .|. . . . . . . .|
D. . . . . . . . . . . . . . . . . . . . . . . . . . . . .A. . . . . . . .B. . . . . . . . . . . .C. . . . . . . .D
For the left copy of PF2, set PF2 to the desired value between point D and point A.
For the right copy of PF2, set PF2 to the desired value between point B and point C.

Updating PF0 (reflected mode):
|. . . . . . . . . . . . . . . . .|. . . . left half of the screen . . . .|. . . .right half of the screen . . . .|
|. horizontal blanking interval. .|. PF0 .|. . . PF1 . . .|. . . PF2 . . .|. . . PF2 . . .|. . . PF1 . . .|. PF0 .|
|. . . . . . . . . . . . . . . . .|. . . .|. . . . . . . .|. . . . . . . .|. . . . . . . .|. . . . . . . .|. . . .|
D. . . . . . . . . . . . . . . . .A. . . .B. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .C. . . .D
For the left copy of PF0, set PF0 to the desired value between point D and point A.
For the right copy of PF0, set PF0 to the desired value between point B and point C.

Updating PF1 (reflected mode):
|. . . . . . . . . . . . . . . . .|. . . . left half of the screen . . . .|. . . .right half of the screen . . . .|
|. horizontal blanking interval. .|. PF0 .|. . . PF1 . . .|. . . PF2 . . .|. . . PF2 . . .|. . . PF1 . . .|. PF0 .|
|. . . . . . . . . . . . . . . . .|. . . .|. . . . . . . .|. . . . . . . .|. . . . . . . .|. . . . . . . .|. . . .|
|. . . . . . . . . . . . . . . . . . . . .A. . . . . . . .B. . . . . . . . . . . . . . . .C. . . . . . . .D. . . .|
For the left copy of PF1, set PF1 to the desired value between point D and point A.
For the right copy of PF1, set PF1 to the desired value between point B and point C.

Updating PF2 (reflected mode):
|. . . . . . . . . . . . . . . . .|. . . . left half of the screen . . . .|. . . .right half of the screen . . . .|
|. horizontal blanking interval. .|. PF0 .|. . . PF1 . . .|. . . PF2 . . .|. . . PF2 . . .|. . . PF1 . . .|. PF0 .|
|. . . . . . . . . . . . . . . . .|. . . .|. . . . . . . .|. . . . . . . .|. . . . . . . .|. . . . . . . .|. . . .|
|. . . . . . . . . . . . . . . . . . . . . . . . . . . . .A. . . . . . . .B. . . . . . . .C. . . . . . . . . . . .|
For the left copy of PF2, set PF2 to the desired value between point C and point A.
For the right copy of PF2, set PF2 to the desired value *exactly* at point B.

The repeated mode gives you the greatest leeway as far as when you can update each register midline, because with the reflected mode the timing for changing PF2 must be exact, since the left and right copies of PF2 are displayed side-by-side in the reflected mode. But even though the repeated mode is the most forgiving as far as the timing of the midline changes, many programs that draw an asymmetrical playfield use the reflected mode, because in that mode the PF0 register appears at the far left and far right sides of the screen, such that you can leave PF0 blank and just use PF1 and PF2 to get a 32x192 playfield if you want.

Michael

Edited by SeaGtGruff, Tue Sep 21, 2010 4:41 AM.


#43 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 20,458 posts
  • Location:The land of Gorch

Posted Tue Sep 21, 2010 4:50 AM

There are ways to create the illusion that playfield pixels are being set or cleared on color-clock intervals, tho (such as masking over them using player sprites).

BTW the thread linked above details cycle time counts where it's safe to alter playfield registers for each mode...and a handy chart that combines all of this info.

#44 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,547 posts
  • Location:Georgia, USA

Posted Tue Sep 21, 2010 5:03 AM

View PostNukey Shay, on Tue Sep 21, 2010 4:50 AM, said:

There are ways to create the illusion that playfield pixels are being set or cleared on color-clock intervals, tho (such as masking over them using player sprites).
True, and you can also turn a playfield pixel on or off *while* it's being drawn (if you couldn't spare a sprite to mask it)-- although you can only do that at intervals of 3 color clocks.

View PostNukey Shay, on Tue Sep 21, 2010 4:50 AM, said:

BTW the thread linked above details cycle time counts where it's safe to alter playfield registers for each mode...and a handy chart that combines all of this info.
I know. It *is* a handy chart. :) But one thing to be careful of is that the exact timing can vary from machine to machine (specifically on Gemini "clones"? I forget which machine it is). I made a chart that should work for either case (the standard timing or the very-slightly-delayed timing), and I posted it somewhere in the forums, but I'll have to dig around for it.

Michael




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users