Jump to content
IGNORED

K.O. Cruiser - my first homebrew


Devin

Recommended Posts

Hey Devin,

 

I had the chance to test on hardware this weekend and, well, you can see there are some bugs that the emulator doesn't show. This is probably due to writing to some of the HMxx registers too early in the scanline, the results of which are one of the few traits of the 2600 that emulators don't replicate. I had to learn this the hard way too.

 

post-2163-1205764198_thumb.jpg

 

I've also attached a very short video clip that shows the sprites going berzerk:

KO_Cruiser_WIP_2008_03_11_001.zip

Link to comment
Share on other sites

Hey Devin,

 

I had the chance to test on hardware this weekend and, well, you can see there are some bugs that the emulator doesn't show. This is probably due to writing to some of the HMxx registers too early in the scanline, the results of which are one of the few traits of the 2600 that emulators don't replicate. I had to learn this the hard way too.

 

post-2163-1205764198_thumb.jpg

 

I've also attached a very short video clip that shows the sprites going berzerk:

KO_Cruiser_WIP_2008_03_11_001.zip

 

Thanks Zach. I'm aligning the initial position of the ball during the VBlank period. Does it need to be done during the kernal? I call HMOVE right after the STA WSYNC call.

 

I'm not sure when in the scanline I am setting the HMBL register. The head and body code set HMBL. The head also sets the size of the ball.

Link to comment
Share on other sites

Thanks Zach. I'm aligning the initial position of the ball during the VBlank period. Does it need to be done during the kernal? I call HMOVE right after the STA WSYNC call.

 

I'm not sure when in the scanline I am setting the HMBL register. The head and body code set HMBL. The head also sets the size of the ball.

It is definitely OK to set HMBL during VBlank. As I understand it, the 2600 still counts cycles during Vblank, and you still need to watch when you write to the register. To find out at which cycle you are setting HMBL, you can use the trace feature in z26. Use the -t switch, but be sure to exit z26 quickly, or you will end up with an excessively large log file. You can also use the Stella debugger and set a breakpoint when something is written at HMBL. I don't know at exactly which cycle setting HMxx becomes reliable, but you should be OK if it's at cycle 50 or greater.

Link to comment
Share on other sites

Thanks Zach. I'm aligning the initial position of the ball during the VBlank period. Does it need to be done during the kernal? I call HMOVE right after the STA WSYNC call. I'm not sure when in the scanline I am setting the HMBL register. The head and body code set HMBL. The head also sets the size of the ball.

 

It is fine to set the position of the sprites during the VBlank period. However, one thing to watch is the following (from the Stella Programmers Guide guide): "These motion registers should not be modified during the 24 computer cycles immediately following an HMOVE command. Unpredictable motion values may result". This can cause the effect that you are seeing here, so check that you aren't touching HMCLR or HMxx too soon after an HMOVE.

 

Chris

Link to comment
Share on other sites

The docs say to set HMxx registers no earlier than 24 cycles after HMOVE:

 

I think I found the suspect code in the section of the kernal that draws the computer's head. It is under 24 cycles. Would the bug cause all the balls to to stick together on the screen? The ball graphics are aligned relative to each other correctly. Odd. But, that what makes programming the 2600 so fun!

 

DrawHead
LDY  ScrnHeadIndex

 ;----------
 ;Ball
 ;----------
LDA  TableHeadBallColor,Y	;Ball color
STA  Temp2				;BallColor

LDA  TableHeadBallCntrl,Y;mmmmssss   m=move constant, s=size #
STA  HMBL
AND  #$0F				;get index into control table
TAX

LDA  TableBallCntrl,X	;Get CTRLPF and ENABL codes
STA  Temp3

 ;----------
 ;Player 1
 ;----------
...

 

I'll flip the code - do Player 1 first.

 

I'm aligning the ball using the same subroutine that I am using for the players and missiles. I modified another sub I found on these forums. In the code below, I capitalized the statements where I made changes. I would appreciate if someone far more knowledgeable than I can give it a thumbs-up. The sub is as follows:

 

PositionSprite
	sta  HMCLR

PositionSpriteNoClr
	sec
	sta	WSYNC	  
	STA	HMOVE	;+3 --------------------- ADDED BY DEVIN 

PositionSpriteLoop
	sbc	#15
	bcs	PositionSpriteLoop;+4/5	7/12.../57

	eor	#7			;+2	  9/14.../59
	asl
	asl
	asl
	asl					 ;+8	 17/22.../66

  ;In the following code, I reversed the HMP0,x and RESP0,x 
  ;commands and added a NOP to align the code to the original 5 cycles.
	
	NOP					 ;+2	 19/24.../66 
	STA	RESP0,X		  ;+4	 23/28/33/38/43/48/53/58/63/68/73
	STA.wx HMP0,X		;+5

	sta	WSYNC			;+3	  0			  begin line 2
	sta	HMOVE			;+3
	rts					 ;+6	  9

 

It works great, even with the modification (probably poorly done). Here's the code that calls the sub to align the ball. This takes place before the end of VBlank.

 

  ;---------------------------
 ;Align Ball
 ;---------------------------
InitBall
 ;Contains position of head
LDA  CompuPosX
CLC			  
ADC  #6			  ;Atari's 1 pixel bug
LDX  #4			  ;4 = ball
JSR  PositionSprite

LDA  #$00	  ;BLACK BACKGROUND
STA  COLUBK
  
STA  HMCLR  ;Important

 

Which is also breaking the 24-cycle rule. Argh.

 

Thanks everyone for their help!

Edited by Devin
Link to comment
Share on other sites

Which is also breaking the 24-cycle rule. Argh.

 

Each object has a 4-bit motion-compare value (loaded via HMxx or HMCLR) and a pulser on-off latch (not directly accessible). The system also has a 4-bit motion counter, a "counter force enable" latch, and a "HMOVE triggered" latch. The motion circuitry operates using the TIA's system clock (which I'll qclock) which runs at a rate of one cycle every four pixels (i.e. once every 1.33 CPU cycles, or 57 times per line).

 

Hitting HMOVE turns on all objects' "move enable" latches, as well as the system's "counter force enable" and "HMOVE triggered" latches. Those latches get turned off as described below.

 

-1- Every object's "move enable" latch will get cleared any time it matches the system motion counter xor'ed with 8.

 

-2- The "counter force enable" latch gets cleared after one qclock.

 

-3- The system motion counter will count once per qclock unless it's at zero and the "counter force enable" latch is not set.

 

-4- The "HMOVE triggered" latch is continuously cleared during the visible part of the screen. When set, it delays the visible part of the screen by 8 pixels.

 

-5- Each object will receive a count pulse once per pixel during the visible part of the screen, and will receive one count per qclock when its "move enable" latch is set. Each object will be displayed when its count reaches 160; players and missiles may also be displayed when their counts hit 16, 32, or 64, based on NUSIZx.

 

If an object's "move enable" latch is set when a new value is written into HMxx, a variety of things can happen based on the values of the system motion counter and the new HMxx. If HMxx is $80, the object will end up receiving 16 motion pulses. If (HMxx xor $80) is greater than the motion counter value, the move will simply use the new value. If (HMxx xor $80) is non-zero but less than the motion counter value, the motion-enable latch will remain set until either another HMOVE is performed or HMxx is written with $80.

Link to comment
Share on other sites

Which is also breaking the 24-cycle rule. Argh.

 

Each object has a 4-bit motion-compare value (loaded via HMxx or HMCLR) and a pulser on-off latch (not directly accessible). The system also has a 4-bit motion counter, a "counter force enable" latch, and a "HMOVE triggered" latch. The motion circuitry operates using the TIA's system clock (which I'll qclock) which runs at a rate of one cycle every four pixels (i.e. once every 1.33 CPU cycles, or 57 times per line).

 

Hitting HMOVE turns on all objects' "move enable" latches, as well as the system's "counter force enable" and "HMOVE triggered" latches. Those latches get turned off as described below.

 

-1- Every object's "move enable" latch will get cleared any time it matches the system motion counter xor'ed with 8.

 

-2- The "counter force enable" latch gets cleared after one qclock.

 

-3- The system motion counter will count once per qclock unless it's at zero and the "counter force enable" latch is not set.

 

-4- The "HMOVE triggered" latch is continuously cleared during the visible part of the screen. When set, it delays the visible part of the screen by 8 pixels.

 

-5- Each object will receive a count pulse once per pixel during the visible part of the screen, and will receive one count per qclock when its "move enable" latch is set. Each object will be displayed when its count reaches 160; players and missiles may also be displayed when their counts hit 16, 32, or 64, based on NUSIZx.

 

If an object's "move enable" latch is set when a new value is written into HMxx, a variety of things can happen based on the values of the system motion counter and the new HMxx. If HMxx is $80, the object will end up receiving 16 motion pulses. If (HMxx xor $80) is greater than the motion counter value, the move will simply use the new value. If (HMxx xor $80) is non-zero but less than the motion counter value, the motion-enable latch will remain set until either another HMOVE is performed or HMxx is written with $80.

 

Thanks. It might take me a while to digest all of that.

 

In a nutshell, as long as I do my HMxxx calls after 24 cycles, I should be okay? I'm only updating my graphics registers during horizontal blank (with the exception of HMxxx).

Link to comment
Share on other sites

In a nutshell, as long as I do my HMxxx calls after 24 cycles, I should be okay? I'm only updating my graphics registers during horizontal blank (with the exception of HMxxx).

 

Yeah. The exact number of cycles you have to wait depends how the object is being moved. The worst case is trying to move 7 pixels left with a convention HMOVE (or 15 with an 'early' one). The best case is 7 or 8 pixels right (or 0-1 left with an 'early' move); in that case there's no restriction.

Link to comment
Share on other sites

Go here to read about "early" HMOVEs. You'll find it under "HMOVE Timing Chart". In short it's a trick that lets you do HMOVE without leaving a black line on the left of the screen. The catch is that it only moves sprite leftward, and if you need them to go right you'll have to use RESxx.

Link to comment
Share on other sites

Can't wait to see the rest of your characters, Devin.

 

Here's what I have created so far:

  • Line 1 contains characters that I created for my original Commodore 64 version. The second guy, in green trunks, is the champ.
  • Line 2 contains characters I created for a possible "Holiday" related sequel. They are Santa Claus, Frosty, St. Patrick's Day (I might put a shirt on him), Independence Day, Halloween (maybe), Jack O'Lantern (Halloween), and Easter (which is the goofiest picture ever).
  • Line 3 contains miscellaneous characters. The first two might go into a "Time" related sequel. I could also incorporate the Soviet from the top row. The ninja could get associated with feudal Japan. The next two are clowns: Pennywise from IT (from the book) and a generic clown (not evil). Finally, I have a lumberjack and a thief.
  • The last line contains characters from Homestar Runner. I doubt I would be able to create this, though I'm sure the creator would find it funny. I then have masked fighter and a stereotypical representative of spanish television. Finally, I have Michael Moore.

 

I would love to hear everyone's feedback on the designs.

post-17256-1205952559_thumb.jpg

Edited by Devin
Link to comment
Share on other sites

watch out.,.its DANCIN BUBS!!

Dude, ya gota put me on a "to buy" list when this thing comes all out!

 

He would definitely have dance combo! Strong Sad might be the only fighter than just knocks himself out - "Oh, I can't win anyway....". :)

Link to comment
Share on other sites

The diversity of characters are gonna make this game shine! are you gonna use all of em? That's an impressive lineup you got! I really like the "Mad Bomber" character as from the game Kaboom! I'd love to finaly deal with him personaly and drop kick him into a bucket of water! :evil:

 

He-he, how bout' a "smiley face" as a wrestler? ;-) ..who likes to taunt ya :P ;.. and changes emotions when punched on the nose! :mad: ...or below the belt :-o ... :lol:

Edited by espire8
Link to comment
Share on other sites

  • 1 month later...
Wondering if any more work has been completed. This looks promising so I'll give it a bump.

I haven't had a chance to work on the program for quite some time. Hopefully, I can get a better working demo out sometime next month.

 

Just found this thread today. Can't wait to see this game get finished.

Thank you!

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...