Jump to content

2

My first Homebrew: Vong


93 replies to this topic

#1 Wickeycolumbus OFFLINE  

Wickeycolumbus

    River Patroller

  • 4,301 posts
  • Location:Michigan

Posted Fri Mar 28, 2008 8:31 PM

This is my first homebrew for the 2600 written in assembly, and I am very proud of it, since I am only 14 years old.  The name of it is "Vong" for Vertical pong.  It plays like pong, but instead of the ball going side to side, it goes up and down, hence the name Vong.  There is some AI, but it is not too good.  I plan to change all of the colors to black and white, like the original pong.  There is no scoring currently, but there will be in a future update.  I would also like to add paddle support, and a 2 player option.

Enjoy!

Attached Files



#2 Devin OFFLINE  

Devin

    Moonsweeper

  • 489 posts
  • Its all HCLR to me!
  • Location:Sacramento, California,

Posted Fri Mar 28, 2008 8:49 PM

View PostWickeycolumbus, on Fri Mar 28, 2008 7:31 PM, said:

This is my first homebrew for the 2600 written in assembly, and I am very proud of it, since I am only 14 years old.  The name of it is "Vong" for Vertical pong.  It plays like pong, but instead of the ball going side to side, it goes up and down, hence the name Vong.  There is some AI, but it is not too good.  I plan to change all of the colors to black and white, like the original pong.  There is no scoring currently, but there will be in a future update.  I would also like to add paddle support, and a 2 player option.

Enjoy!

It's looking great so far! I look forward to see how this project progresses. Cheers.

#3 retrogeek OFFLINE  

retrogeek

    Chopper Commander

  • 240 posts
  • Location:In your cereal box

Posted Fri Mar 28, 2008 8:49 PM

View PostWickeycolumbus, on Fri Mar 28, 2008 9:31 PM, said:

This is my first homebrew for the 2600 written in assembly, and I am very proud of it, since I am only 14 years old.  The name of it is "Vong" for Vertical pong.  It plays like pong, but instead of the ball going side to side, it goes up and down, hence the name Vong.  There is some AI, but it is not too good.  I plan to change all of the colors to black and white, like the original pong.  There is no scoring currently, but there will be in a future update.  I would also like to add paddle support, and a 2 player option.

Enjoy!

Nice! Very impressive for your age!

#4 Wickeycolumbus OFFLINE  

Wickeycolumbus

    River Patroller

  • 4,301 posts
  • Location:Michigan

Posted Fri Mar 28, 2008 8:50 PM

Thanks Guys!

#5 accousticguitar OFFLINE  

accousticguitar

    Quadrunner

  • 5,528 posts
  • Sherlock made it to 15 before he left us.
  • Location:Idaho

Posted Fri Mar 28, 2008 9:16 PM

I am impressed with ANYONE who can program ANYTHING using assembly language on the 2600.

#6 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!, Boulder Dash

  • 17,488 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Sat Mar 29, 2008 2:27 AM

Kudos for going the hard way and use assembler! :thumbsup:

#7 Wickeycolumbus OFFLINE  

Wickeycolumbus

    River Patroller

  • 4,301 posts
  • Location:Michigan

Posted Sat Mar 29, 2008 8:56 AM

View PostThomas Jentzsch, on Sat Mar 29, 2008 4:27 AM, said:

Kudos for going the hard way and use assembler! :thumbsup:

Thank you, I like a challenge.

#8 gambler172 OFFLINE  

gambler172

    River Patroller

  • 2,270 posts
  • none
  • Location:germany

Posted Sat Mar 29, 2008 11:42 AM

Hi Wickey
Great,for a young guy.Now you need to add scores.This can become a nice game.
greetings Walter

#9 Wickeycolumbus OFFLINE  

Wickeycolumbus

    River Patroller

  • 4,301 posts
  • Location:Michigan

Posted Sat Mar 29, 2008 12:34 PM

Ok, I made it black and white like real pong, put a white line it the middle of the play field, and made the opponent's paddle a bit bigger in hopes of better AI.  There is still some screen rolling though, and I plan to fix that and add scoring in the next version.

Attached Files



#10 SpiceWare ONLINE  

SpiceWare

    Quadrunner

  • 6,880 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Sat Mar 29, 2008 2:09 PM

I posted sample paddle reading code here.

#11 Wickeycolumbus OFFLINE  

Wickeycolumbus

    River Patroller

  • 4,301 posts
  • Location:Michigan

Posted Sat Mar 29, 2008 3:58 PM

View PostSpiceWare, on Sat Mar 29, 2008 4:09 PM, said:

I posted sample paddle reading code here.

thank you for the link.  Are those macros a part of macro.h?

and I also have some questions about the code.

		MAC READ_PADDLE_1
		lda INPT0	   ; 3   - always 9
		bpl .save	   ; 2 3
		.byte $2d	   ; 4 0   What does this do?
.save   sty Paddle1	 ; 0 3  To read the paddle you read Paddle1? (lda Paddle1)
		ENDM

You say before you posted this code that Y holds the current scanline.  Do you have to put the current scanline into Y, or does that just happen after you use the macro?

Thanks.

#12 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!, Boulder Dash

  • 17,488 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Sat Mar 29, 2008 4:31 PM

View PostWickeycolumbus, on Sat Mar 29, 2008 10:58 PM, said:

	.byte $2d	; 4 0   What does this do?
This is the byte code for the "BIT absolute" instruction ($2c, NOT $2d!). The trick is, that it uses the two next bytes (sty Paddle1) as argument to read from, effectively doing nothing and just skipping the next two bytes with constant(!) cycle count. It takes 4 cycles to execute.

Quote

	.save   sty Paddle1; 0 3  To read the paddle you read Paddle1?
No, that's just the name of a RAM variable you write to as long as the paddle's capacitor hasn't loaded. INPT0 is reading the first paddle (BTW: actually that's paddle 0, not 1).

Quote

Do you have to put the current scanline into Y, or does that just happen after you use the macro?
Yes. Though a lot of kernels use Y as a global scanline count variable, so then you have the value required there already and save some cycles.

The code was originally discussed here.

Edited by Thomas Jentzsch, Sat Mar 29, 2008 4:39 PM.


#13 Impaler_26 OFFLINE  

Impaler_26

    Cookie Meister

  • 2,382 posts
  • Braindead
  • Location:Hueco Mundo

Posted Sat Mar 29, 2008 5:04 PM

Nice work so far, keep it up!  :thumbsup:

#14 Wickeycolumbus OFFLINE  

Wickeycolumbus

    River Patroller

  • 4,301 posts
  • Location:Michigan

Posted Sat Mar 29, 2008 6:58 PM

View PostThomas Jentzsch, on Sat Mar 29, 2008 6:31 PM, said:

View PostWickeycolumbus, on Sat Mar 29, 2008 10:58 PM, said:

	.byte $2d; 4 0   What does this do?
This is the byte code for the "BIT absolute" instruction ($2c, NOT $2d!). The trick is, that it uses the two next bytes (sty Paddle1) as argument to read from, effectively doing nothing and just skipping the next two bytes with constant(!) cycle count. It takes 4 cycles to execute.

Quote

	.save   sty Paddle1; 0 3  To read the paddle you read Paddle1?
No, that's just the name of a RAM variable you write to as long as the paddle's capacitor hasn't loaded. INPT0 is reading the first paddle (BTW: actually that's paddle 0, not 1).

Quote

Do you have to put the current scanline into Y, or does that just happen after you use the macro?
Yes. Though a lot of kernels use Y as a global scanline count variable, so then you have the value required there already and save some cycles.

The code was originally discussed here.


Ok, so I run the macro, with the current scanline count in Y.  I still dont really get how you read it tho...

EDIT:  I clicked the link, and it was dead.

EDIT: I clicked it again and it worked.

EDIT: So would something like this work?

	sta HMCLR
	lda INPT0
	cmp shadowINPT0
	bmi paddleminus
	bpl  paddleplus

paddleminus
	lda #%00010000
	sta HMP1
	sta shadowHMP1
	jmp regular

paddleplus
	lda #%11110000
	sta HMP1
	sta shadowHMP1

regular

   ;on with the rest of the program

Edited by Wickeycolumbus, Sat Mar 29, 2008 7:05 PM.


#15 Wickeycolumbus OFFLINE  

Wickeycolumbus

    River Patroller

  • 4,301 posts
  • Location:Michigan

Posted Sat Mar 29, 2008 9:23 PM

slightly better AI, still needs to be improved more tho...

Attached Files



#16 SpiceWare ONLINE  

SpiceWare

    Quadrunner

  • 6,880 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Sat Mar 29, 2008 9:32 PM

View PostThomas Jentzsch, on Sat Mar 29, 2008 5:31 PM, said:

View PostWickeycolumbus, on Sat Mar 29, 2008 10:58 PM, said:

	.byte $2d; 4 0   What does this do?
This is the byte code for the "BIT absolute" instruction ($2c, NOT $2d!).
Oops-  my mistake, it's correctly using $2c in the "2 paddle" macros which is what I used in MM and the sample.

#17 Omegamatrix OFFLINE  

Omegamatrix

    Quadrunner

  • 5,208 posts
  • Location:Canada

Posted Sun Mar 30, 2008 12:48 AM

Impressive for someone so young to be able to play around with programming a 6502. I look forward to updates of this game. :)

#18 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 22,641 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Sun Mar 30, 2008 12:57 AM

Can you just attach the .bin file in the future so the game can be played directly instead of needing to download and unzip?


Thanks.

#19 ovalbugmann OFFLINE  

ovalbugmann

    River Patroller

  • 2,008 posts
  • Location:Phoenix, Arizona

Posted Sun Mar 30, 2008 1:11 AM

Thanks for the Pong style game :)  :cool:, I'm going to try to load it onto a 2600 with a supercharger.  What are you using to load it into a 2600?  Or are you using Stella for the PC?

#20 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!, Boulder Dash

  • 17,488 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Sun Mar 30, 2008 4:17 AM

View PostWickeycolumbus, on Sun Mar 30, 2008 2:58 AM, said:

EDIT: So would something like this work?
I suppose you want to execute the code once each frame right? Won't work.

The problem is, that INPT0 does NOT contain a variable value. It either contains 0 or 1 (at bit 7, the other bits are unused here), so your code has to measure how long it takes to switch that bit. And this is usually done during the display kernel.

BTW: After posting my answer here yesterday, I found an even faster (though a bit more complicated) solution:
  bit INPT0   ; 3
  bmi .save+1 ; 2/3
.save:
  sty paddle  ; 3/2	paddle has to be at the address of an 1 byte, 2 cycles opcode, e.g. $ea (NOP)
Total: 8 cycles, 1 cycle saved :)

Edited by Thomas Jentzsch, Sun Mar 30, 2008 4:25 AM.


#21 Wickeycolumbus OFFLINE  

Wickeycolumbus

    River Patroller

  • 4,301 posts
  • Location:Michigan

Posted Sun Mar 30, 2008 10:27 AM

View PostRandom Terrain, on Sun Mar 30, 2008 2:57 AM, said:

Can you just attach the .bin file in the future so the game can be played directly instead of needing to download and unzip?


Thanks.

Sure.  I did not think of that.

#22 Wickeycolumbus OFFLINE  

Wickeycolumbus

    River Patroller

  • 4,301 posts
  • Location:Michigan

Posted Sun Mar 30, 2008 10:28 AM

View Postovalbugmann, on Sun Mar 30, 2008 3:11 AM, said:

Thanks for the Pong style game :)  :cool:, I'm going to try to load it onto a 2600 with a supercharger.  What are you using to load it into a 2600?  Or are you using Stella for the PC?

I have been using Stella os X, but I do have an Eprom programmer that I use to do testing with too.

#23 Wickeycolumbus OFFLINE  

Wickeycolumbus

    River Patroller

  • 4,301 posts
  • Location:Michigan

Posted Sun Mar 30, 2008 10:35 AM

View PostThomas Jentzsch, on Sun Mar 30, 2008 6:17 AM, said:

View PostWickeycolumbus, on Sun Mar 30, 2008 2:58 AM, said:

EDIT: So would something like this work?
I suppose you want to execute the code once each frame right? Won't work.

The problem is, that INPT0 does NOT contain a variable value. It either contains 0 or 1 (at bit 7, the other bits are unused here), so your code has to measure how long it takes to switch that bit. And this is usually done during the display kernel.

BTW: After posting my answer here yesterday, I found an even faster (though a bit more complicated) solution:
  bit INPT0  ; 3
  bmi .save+1; 2/3
.save:
  sty paddle ; 3/2	paddle has to be at the address of an 1 byte, 2 cycles opcode, e.g. $ea (NOP)
Total: 8 cycles, 1 cycle saved :)

So paddle is just any RAM address and it contains the number of scanlines that it took to get a 1 from INPT0?  Dont you have to do something before you execute that code to instruct the paddle to start charging the capicitor?

#24 SpiceWare ONLINE  

SpiceWare

    Quadrunner

  • 6,880 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Sun Mar 30, 2008 11:08 AM

Yep - done via VBLANK.  At the MiniDig you can find the Stella Programmer's Guide which has this on page 11:

Quote

12.1 Dumped Input Ports (INPT0 thru INPT3)
These four ports are used to read up to four paddle controllers.  Each paddle controller contains an adjustable pot controlled by the knob on the controller.  The output of the pot is used to charge a capacitor in the console, and when the capacitor is charged the input port goes HI.  The microprocessor discharges this capacitor by writing a "1" to D7 of VBLANK then measures the time it takes to detect a logic one at that port.  This information can be used to position objects on the screen based on the position of the knob on the paddle controller.

The D7 refers to a specific bit, whenever ordered as 76543210.  $80 has bit 7 turned on.  $82 has bits 7 and 1 turned on.  The detail for VBLANK can be found on page 38:

Quote

VBLANK
This address controls vertical blank and the latches and dumping transistors on the input
ports by writing into bits D7, D6 and D1 of the VBLANK register.

D1 [ 1 = start vert. blank, 0 = stop vert. blank]
D6 [ 1 = Enable I4 I5 latches, 0 = disable I4 I5 latches]
D7 [ 1 = dump I6I1I2I3 ports to ground, 0 = remove dump path to ground]
Note : Disable latches (D6 = 0) also resets latches to logic true

The code from my demo:
VerticalBlank:
		lda #$82
		sta WSYNC
		sta VSYNC		; 3	start vertical sync, D1=1
		sta VBLANK	   ; 3  6 start vertical blank and dump paddles to ground

...

	ldx Paddles2Read
	lda #153	  ; prep paddle results with highest possible value
	sta Paddle1,x ; our initial paddle results will be 1-153
	sta Paddle3,x ; and will be adjusted to 0-152 in overscan
	lda #0

VblankWait
		lda INTIM
		bpl VblankWait
	
		sta WSYNC
		sta HMCLR		; clear hmoves for next time around
		stx VBLANK	   ; turn on video output & remove paddle dump to ground

The lda #0 just before VblankWait was supposed to be ldx #0 so that the stx VLBANK would be zeroing out all bits.  However X can only have a value of 0 or 1, which is stored in bit 0 - lucky for me, as seen in the bit from page 38, VBLANK only cares about what's in bits 7, 6 and 1.

#25 supercat OFFLINE  

supercat

    Quadrunner

  • 6,391 posts

Posted Sun Mar 30, 2008 12:11 PM

View PostThomas Jentzsch, on Sun Mar 30, 2008 5:17 AM, said:

The problem is, that INPT0 does NOT contain a variable value. It either contains 0 or 1 (at bit 7, the other bits are unused here), so your code has to measure how long it takes to switch that bit. And this is usually done during the display kernel.

Atari implemented their paddles the cheapest way possible.  Discharge a capacitor, release it, charge it through a variable resistance, and time how long it takes to reach a certain threshold.  That time will be directly proportional to the variable resistance; on the 2600, it's designed to vary from almost nothing to something over a full frame (though I don't think any games use the latter part of the range).

One approach which can be handy in certain types of kernels is to vary the time that you release the cap, so that it will reach the threshold within a fairly narrow range of scan lines.  It's only possible to read one paddle per frame with this approach, but it's possible to read paddles with single-line resolution even if much of the screen has large groups of lines with no spare cycles.

For example, if your screen is divided into 10-line blocks, and you only have a few cycles at the end of each such block, all you need to squeeze in once every ten lines is something like (preferably do this just before a loop branch so you won't have to copy much code)
  ldx paddlectr
  dex
  bne nohit
  stx.w VBLANK
  .. one copy of succeeding code
nohit:
  stx lctr
  .. another copy of succeeding code
Ten cycles, every ten scan lines.  Some time later on the screen, you'll need a loop which checks the paddle every line, and you'll have to adjust the starting value of paddlectr so that the paddle is expected to time out around the middle of that loop.

A somewhat tricky approach, but it can yield very nice results.




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users