Jump to content

Planet Bob

  • entries
    430
  • comments
    1,870
  • views
    659,801

A Kickman Kernel...

Sign in to follow this  
Cybergoth

903 views

Hi there!

 

Well, based on previous Kickman discussions I just "prototyped" a Kickman kernel. Prototyped as in "consider everything hardcoded would be RAM driven in a later version" :)

 

A Screenshot:

kicks.gif

 

Source and binary are available: blue_2.jpg

 

EDIT: Emulatorz only! Don't try on a TV!

 

Greetings,

Manuel

Sign in to follow this  


25 Comments


Recommended Comments

Uihjha! Looks nice, Manuel. Can't wait to see the rest.

 

Is the intention to flicker the rows when other things go in front of them? If you don't mind full-time 30Hz flicker and restrict the game to having one object in front of a row of balloons at a time, you could even do nine balloons per row.

Share this comment


Link to comment
Uihjha! Looks nice, Manuel. Can't wait to see the rest.

 

Thanks! :D

 

Is the intention to flicker the rows when other things go in front of them?

 

No. This is a Galaxianesque kernel, it can still utilize the second sprite with 18 spare cycles to use :D

 

The set of compromise I chose here is:

 

- fixed color per row

- only 6 objects per row

+ No flicker required so far

+ Smooth transition of the falling object

 

Greetings,

Manuel

Share this comment


Link to comment

Hm... I have two questions to the multi-resp-trick experts in these waters :D

 

1. Why do all demos I saw, especially 11 Invaders stuff, use both sprites? It seems that one should be enough already. Else, what was the plan to display explosions?!?

 

2. What strategies are available to "not" display sprites in the chain?

Share this comment


Link to comment

1. Why do all demos I saw, especially 11 Invaders stuff, use both sprites? It seems that one should be enough already. Else, what was the plan to display explosions?!?

1a) Spacing

1b) No explosions, just let them flicker

 

2. What strategies are available to "not" display sprites in the chain?

Selfmodifying code in RAM.

Share this comment


Link to comment
1a) Spacing

 

Hm... I think I tweaked Eriks code some, just turning all STA RESP1 into STA RESP0 and it looked exactly the same :D

 

1b) No explosions, just let them flicker

 

Oha! :D

 

Selfmodifying code in RAM.

 

Of course. I wanted to know "how" to modify it :D

 

The only way I see right now would be clearing the GRP register. Just removing the matching RESP wouldn't do anything useful I think.

Share this comment


Link to comment

Hm... I think I tweaked Eriks code some, just turning all STA RESP1 into STA RESP0 and it looked exactly the same :D

Shouldn't be. When you RESP then the first copy doesn't show up. So NUSIZ has to be set to two copies close, with GRP0 and GRP1 interleaving.

 

The only way I see right now would be clearing the GRP register. Just removing the matching RESP wouldn't do anything useful I think.

Actually removing the RESP is exactly the right approach. Maybe you should have a look at my 11 Invaders code.

Share this comment


Link to comment
What is the maximum number of columns in the original game?

 

It does 8. You can't make any assumptions on gameplay changes based on the loss of the 2 colums only though. You also need to take the difference in aspect ratio into account, as well as the increased gaps between columns. Also, in the arcade the balloons get stacked up to 8 rows high onto the clown, which may have to be altered as well. (Plus some minor loss of randomness: The first dropped balloon will be yellow ;))

 

Besides all those changes, on the pro side, you have two mighty adjustment screws to even all odds, making it just as playable as the arcade: The "Downfall Speed" & The "Player Speed"! :D

 

Shouldn't be. When you RESP then the first copy doesn't show up. So NUSIZ has to be set to two copies close, with GRP0 and GRP1 interleaving.

 

Hm... wouldn't each RESP produce a copy in a three cycle distance, so it doesn't matter wether it's GRP0 or GRP1 that is displayed?!? I really thought I got the same result with RESP0 only... Ok... it was late at night when I tried that... :D :D

 

BTW: I thought the first copy _does_ show up. Else why is the final gap always a bit smaller inbetween the last two sprites of the chain? The last two sprites must be copy 1 and 2, no?

 

The only way I see right now would be clearing the GRP register. Just removing the matching RESP wouldn't do anything useful I think.
Actually removing the RESP is exactly the right approach. Maybe you should have a look at my 11 Invaders code.

 

Wow, that really worked! :D

 

Really ;) :D :D

 

I thought you were doing some weird things with all the "patch" bits in order to blank the gaps. Then those are only to offset the whole set of rows, making it move, or?

 

Anyway, way cool!!!

 

I'd have really been in trouble if there wasn't such a simple solution: As I load two kind of shape data into A and X already, clearing GRP would've required loading zero into Y, which'd have complicated matters extremely down the road... :D

Share this comment


Link to comment

Question: I've never played Kick Man in the arcade; doesn't it use a spinner? Do you plan to support paddles? (Likely not, since you have previously avowed a certain antipathy towards them!)

 

So, driving controller? Joystick?

Share this comment


Link to comment
Question: I've never played Kick Man in the arcade; doesn't it use a spinner? Do you plan to support paddles? (Likely not, since you have previously avowed a certain antipathy towards them!)

 

So, driving controller? Joystick?

 

Joystick of course! :D

 

Interesting enough, while the Arcade indeed uses an analog controler, all the MARP pros rely on a digital configuration, as either the Arcade controller (spinner/paddle? No clue actually :D) or the MAME driver or the Arcade code itself tends to oversteer easily with analog input (coming from a mouse for example :D), so with digital input you incredibly gain on control precission for this game in MAME :D

 

EDIT: I'm toying with that damn resp technique for a while now, and I don't get that odd final gap. It's only there when resping in 6 cycles intervals (STA GRP + STA RESP) (18 pixels) but not when resping in 7 cycle intervals (STA GRP + STA.w RESP) (21 pixels). If it weren't for that oddity, I could do 7 ballons/row without any extra cost :D

Share this comment


Link to comment
Question: I've never played Kick Man in the arcade; doesn't it use a spinner? Do you plan to support paddles? (Likely not, since you have previously avowed a certain antipathy towards them!)

 

So, driving controller? Joystick?

 

 

Joystick of course!

 

Interesting enough, while the Arcade indeed uses an analog controler, all the MARP pros rely on a digital configuration, as either the Arcade controller (spinner/paddle? No clue actually ) or the MAME driver or the Arcade code itself tends to oversteer easily, so with digital input you incredibly gain on control precission for this game in MAME

 

Seems like you'd also need speed, which a joystick won't give you. Or rather, whatever speed it gives you you lose in precision. I played it a bit in MAME (without spinner) and I often was wishing for a spinner so that the silly clown would just move...a...little...bit...faster! Oh well, if I want a paddle version I suppose the solution is to write one myself.

 

And according to KLOV, it's an optical spinner. I wonder how well the DC would work, reading once per frame - probably not real well. I wonder...you could probably squeeze in 2 DC reads during the kernel, for a total of 4 reads per frame. Wonder if that would be enough?

Share this comment


Link to comment
Seems like you'd also need speed, which a joystick won't give you. Or rather, whatever speed it gives you you lose in precision.

 

Here's my setup for the "Analog Controls" Menu:

 

Dial Digital Speed: 100

Dial Autocenter Speed: 0

Dial Reverse: On

Dial Sensitivity: 4%

 

That works pretty good with a digital pad or cursor keys, if you give it a few tries to get used to :D

 

I played it a bit in MAME (without spinner) and I often was wishing for a spinner so that the silly clown would just move...a...little...bit...faster! Oh well, if I want a paddle version I suppose the solution is to write one myself. :D

 

I think you can optimize the game for both. If you write a paddle driver, you need to make anything else faster and harder, so in the end it's only a matter of personal preference. In style, it seems this game is intended to be played significantly slower then say Kaboom, so I guess the Arcade was already at fault for using a spinner :D

 

I wonder how well the DC would work, reading once per frame - probably not real well. I wonder...you could probably squeeze in 2 DC reads during the kernel, for a total of 4 reads per frame. Wonder if that would be enough?

 

I can try adding DC controls, then we'll see :D

Share this comment


Link to comment
Here's my setup for the "Analog Controls" Menu:

 

Dial Digital Speed: 100

Dial Autocenter Speed: 0

Dial Reverse: On

Dial Sensitivity: 4%

 

That works pretty good with a digital pad or cursor keys, if you give it a few tries to get used to :D

Thanks; I'll try that out. :D

I wonder how well the DC would work, reading once per frame - probably not real well. I wonder...you could probably squeeze in 2 DC reads during the kernel, for a total of 4 reads per frame. Wonder if that would be enough?

 

I can try adding DC controls, then we'll see :D

Cool. :D :D Now I just gotta get some DCs...

Share this comment


Link to comment

The only way I see right now would be clearing the GRP register. Just removing the matching RESP wouldn't do anything useful I think.

Actually removing the RESP is exactly the right approach. Maybe you should have a look at my 11 Invaders code.

It's a little more complicated for a row of just 1 object, yes? It seems to me you'd have to mess with NUSIZx or use the PF to cover extraneous sprites.

 

On second thought, it's not that hard to write a separate routine for just 1 piece.

Share this comment


Link to comment
EDIT: I'm toying with that damn resp technique for a while now, and I don't get that odd final gap. It's only there when resping in 6 cycles intervals (STA GRP + STA RESP) (18 pixels) but not when resping in 7 cycle intervals (STA GRP + STA.w RESP) (21 pixels). If it weren't for that oddity, I could do 7 ballons/row without any extra cost :D

 

With sprites set to two copies close, hitting RESPx less than six cycles after the previous hit will clobber the earlier sprite without it being displayed. Doing it more than six cycles after the previous hit will result in the previous sprite being unaffected by the RESPx (which is what you want). Doing it at exactly six cycles will cause the previous sprite to be shifted over by a pixel. Annoying, but since Atari wasn't planning on people doing this sort of nonsense you can't blame them too much.

 

Since it would be ugly to have a mixture of player copies that are and are not shifted by that funny pixel, you need a way to blank out unwanted copies. I would suggest that you have the RESPx in place for all the sprite copies whether you want them or next. If a particular sprite copy is unwanted, replace its GRPx store with another RESPx. This will work for all but the last one. For the end of the line, do something like:

 sta RESP1; Trigger #4
 sta GRP1 ; Shape #4
 sta RESP1; Trigger #5
 sta GRP1 ; Shape #5
 sta RESP1; Trigger #6
 and #xx   ; Blanker for #6
 sta GRP1 ; Shape #6

Replace the "xx" with zero in order to kill the last shape.

Share this comment


Link to comment
It's a little more complicated for a row of just 1 object, yes? It seems to me you'd have to mess with NUSIZx or use the PF to cover extraneous sprites.

 

If you kill sprites by re-RESPing them before they can appear, you can avoid the need to special-case things other than the last sprite.

 

In my Sudoku kernel, I had some difficulties getting rid of extra sprite copies. That was complicated by the fact that the kernel was using both GRP0 and GRP1 in arbitrary order. What I ended up doing was making it so that at the end of each line I RESPx the sprite I didn't use last and set both shapes to blank.

Share this comment


Link to comment
=Interesting enough, while the Arcade indeed uses an analog controler, all the MARP pros rely on a digital configuration, as either the Arcade controller (spinner/paddle? No clue actually ) or the MAME driver or the Arcade code itself tends to oversteer easily, so with digital input you incredibly gain on control precission for this game in MAME

And according to KLOV, it's an optical spinner. I wonder how well the DC would work, reading once per frame - probably not real well. I wonder...you could probably squeeze in 2 DC reads during the kernel, for a total of 4 reads per frame. Wonder if that would be enough?

 

Kick used a 1-axis (L-R) trackball. IMHO a paddle would work best, although I don't know whether you have enough cycles in the kernel for it. You'd have to read a DC during the kernel as well, which would probably eat up even more cycles. A joystick can't do the fast/slow you really need.

Share this comment


Link to comment
Replace the "xx" with zero in order to kill the last shape.

 

I tried that and can confirm that it works! :D

 

Yet unfortunately it doesn't provide a real gain here. Right now I do 6 sprites with:

 

ROMLoop
sta WSYNC
ldx shape2,Y
lda shape1,Y
SLEEP 12
STA.w RESP0
stx GRP0 
STA.w RESP0
sta GRP0  
STA.w RESP0
stx GRP0	
STA.w RESP0 
stx GRP0	  
STA.w RESP0 
stx GRP0	  
STA.w RESP0 
sta GRP0	  
SLEEP 6
dey			  
BPL ROMLoop

 

The suggested modification will do 7 sprites with:

ROMLoop
sta WSYNC  
ldx shape2,Y 
lda shape1,Y  
SLEEP 10
STA RESP0	 
stx GRP0		
STA RESP0	 
stx GRP0		
STA RESP0	 
stx GRP0		
STA RESP0	 
sta GRP0	   
STA RESP0	
stx GRP0	   
STA RESP0	
sta GRP0	  
STA RESP0   
sta GRP0	 
STA RESP0  
LDA #0
sta GRP0	
dey			
BPL ROMLoop

 

So while I gain 6 cycles for removing the .w, I immediately lose them for the 7th sprite and another 8 for the 8th (invisible) sprite. (All this aside, I could only display 5 pixel wide sprites with this.)

 

Finally, I could do 7 sprites already for 7 cycles:

 

ROMLoop
sta WSYNC	  
ldx shape2,Y   
lda shape1,Y   
SLEEP 11
sta.w RESP0	
stx GRP0	   
sta.w RESP0	
stx GRP0	   
sta.w RESP0	
stx GRP0	   
sta.w RESP0	
sta GRP0	   
sta.w RESP0	
stx GRP0	   
sta.w RESP0	
sta GRP0	   
sta.w RESP0	
sta GRP0	   
dey			
BPL ROMLoop

 

BTW: Replacing sta GRP0 with sta RESP0 in the above code will blank any sprite (Even the last! At least in Z26! :D), so it seems better than NOPing the RESPs! Thanks for that info! :D

Share this comment


Link to comment
BTW: Replacing sta GRP0 with sta RESP0 in the above code will blank any sprite (Even the last! At least in Z26! :D), so it seems better than NOPing the RESPs! Thanks for that info! :D

 

Uhm... actually there is a problem, that is always when you replace the _last_ grp with resp, while any other sprite(s) is still on.

Well, but no big deal: It seems one can hide that little sprite garbage just under the first and last bit of the playfield :D

Share this comment


Link to comment

I briefly looked at the Garfield prototype code last night to see how it managed 8 sprites. Interestingly, there are only four writes to RESP0 along with four writes to NUSIZ0. I don't know if this technique has been studied before, but I just thought I'd mention it. Maybe it could be useful here.

Share this comment


Link to comment
]Actually removing the RESP is exactly the right approach. Maybe you should have a look at my 11 Invaders code.

I thought you were doing some weird things with all the "patch" bits in order to blank the gaps. Then those are only to offset the whole set of rows, making it move, or?

No, the offset is done by the code which jumps to the RAM display kernel.

 

The patch bits are there for enabling and disabling the invaders. The code could be much simplier, but I tried to make the invaders moving range as wide a possible, so there are some extra patches necessary.

Share this comment


Link to comment
I don't know if this technique has been studied before, but I just thought I'd mention it. Maybe it could be useful here.

 

If you just want to display many copies of the same thing, you can set NUSIZx to 3 and then use one RESPx for every two objects to be displayed. If you do a RESPx every 11 cycles, the object spacing will alternate between 16 and 17 pixels but not in the way one would expect; the RESPx for objects 3 and 4 nudges object #2 to the right one pixel.

 

Unfortunately, although reducing the number of RESPx operations would seem to make more time available for GRPx writes, things don't work out that way. More cycles are available, but some aren't available while needed.

 

Incidentally, hitting RESPx every six cycles yields an 18-pixel spacing, BUT sticking "ST? GRPx" instructions between the RESPx's will change the graphics midway through the shape. Irksome.

Share this comment


Link to comment
Incidentally, hitting RESPx every six cycles yields an 18-pixel spacing, BUT sticking "ST? GRPx" instructions between the RESPx's will change the graphics midway through the shape. Irksome.

 

That's what I meant when saying that you can do only 5 pixel wide sprites with that.

Share this comment


Link to comment
Incidentally, hitting RESPx every six cycles yields an 18-pixel spacing, BUT sticking "ST? GRPx" instructions between the RESPx's will change the graphics midway through the shape. Irksome.

 

That's what I meant when saying that you can do only 5 pixel wide sprites with that.

 

Well, there are ways of doing 8-wide sprites, but it's more limiting and may often require using more RAM.

 

For example, suppose there are Pac-Men, balloons, and ghosts, shaped like this:

-XXXXXX- --XXXX-- --XXXX--
XXXXXXXX -XXXXXX- -XXXXXX-
X  XX  X XXXXXXXX XXXXXXXX
XXXXXXXX XXXXXX-- XXXXXXXX
XXXXXXXX XXXX---- XXXXXXXX
XXXXXXXX XXXXXX-- XXXXXXXX
XXXXXXXX XXXXXXXX -XXXXXX-
XXXXXXXX -XXXXXX- -XXXXXX-
XXXXXXXX --XXXX-- --XXXX--
X XXXX X -------- ---XX---

On each line, there are only two different shapes, and all of the pixels present in one shape are present in the other (though not vice versa). Load Y with the shape that has more pixels. Load A with a composite shape whose left half has more pixels and whose right half has fewer. Load X with a composite whose right half has more pixels and whose left half has fewer. Thus, an STY, STA, STX, or SAX to GRPx will handle any necessary possibilities. For the "no pixels" case, do a gratuitous hit of RESPx instead of GRPx.

 

This approach would almost certainly require expansion RAM to give the three shapes above since there would be five kernels: lines 0, 1, 7, and 8; line 2; lines 3, 4, and 5 yet another; line 6; line 9. On the other hand, it would allow the use of full 8-pixel-wide sprites.

Share this comment


Link to comment
Guest
Add a comment...

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