Jump to content
IGNORED

My second game


batari

Recommended Posts

I'm working on another 1k minigame. The "space minefield" part is loosely based on a BASIC game I made for the VIC-20 a long time ago, plus I took some elements from the Killer Comet game that someone suggested in another thread by adding a mothership at the end that acts similar to how the comet did (you shoot pieces off of it as it falls to earth.)

 

It's playable but I have yet to add sound, scoring and proceeding to the next level, the mothership doesn't shoot at you yet, and if your ship gets hit the game immediately restarts. There's a few bugs here and there too.

 

I'm looking for suggestions to improve it, mostly about gameplay. I realize that the graphics aren't great. This is because the mines and mothership are bitmapped into RAM so as to be shootable, but bitmapping with 128 bytes usually means your pixels become blocks. Also, this means that RAM is really tight, <10 bytes free right now, and ROM's getting tight too (50 bytes left) so improvements can't be huge.

 

As for the name, "Zirconium" stick in my mind for some reason, but I'm open for suggestions if this name sucks.

 

EDIT: To make the final version easier to find, I'll put it here, too, and remove the initial demo (which is barely playable)

Zirconium.zip

Edited by batari
Link to comment
Share on other sites

Why are you limiting yourself to 1k? I could see this turning into a pretty good game.

 

My suggestions:

 

1. I'd like the shot to be shorter. Right now it kind of looks like I'm shooting sausage links.

 

2. It would be cool to have some objects mixed in that give you various things if you touch them. Possible things could be more power, extra points, double shots, some cool ability, and so on.

 

3. I wonder if pulling back the joystick to slow down would help you to reach those objects that I mentioned? Slowing down could burn extra fuel or eat up points to discourage using the ability too much.

 

4. If you go beyond 1k, can you make the ship more colorful or more detailed ('shaded' or something)?

 

That's all I have for now.

Link to comment
Share on other sites

Why are you limiting yourself to 1k? I could see this turning into a pretty good game.

 

1. I'd like the shot to be shorter. Right now it kind of looks like I'm shooting sausage links.

 

2. It would be cool to have some objects mixed in that give you various things if you touch them. Possible things could be more power, extra points, double shots, some cool ability, and so on.

 

3. I wonder if pulling back the joystick to slow down would help you to reach those objects that I mentioned? Slowing down could burn extra fuel or eat up points to discourage using the ability too much.

 

4. If you go beyond 1k, can you make the ship more colorful or more detailed ('shaded' or something)?

 

Thanks for the suggestions. Most of them don't require much ROM space, so I might be able to squeeze them into 1k. The issue right now there are no free cycles in the display kernel. I'm certain that the kernel can be improved, (i.e. if I can ever understand how to use Thomas Jentzsch's Skipdraw) so maybe I can get some of them in. Definitely #1, hopefully 2 and 3. To me, functional changes have priority over visuals, so while I thought of #4, the way I can think of to do it requires 7 kernel cycles which might not be possible, though there may be a compromise here. We'll see.

 

Anyway, the 1k limit is for the annual Minigame Compo. Well, the 2005 competition hasn't been organized yet, but normally I think they start accepting entries near the end of summer. Of course, 1k limits what you can do with a game, so there's the argument that you could be getting something better with a larger size, but there's a double-edged sword here. Larger size can lead to longer development time, and with longer time there's a greater chance of projects being put off. I guess I don't want to start something unless I'm sure I'll finish. Still, whie 1k is the goal, if this turns out to be too limiting I may reconsider.

Link to comment
Share on other sites

Hi there!

 

Please also remember that the 1K and 4K categories aren't put in stone. While they were pretty successful, the 2005 contest organizers may change them as the like. I'm in the very same boat here, currently targetting Crazy Balloon for 4K. It's "on your own risk", just so you be aware of that.

 

Greetings,

Manuel

Link to comment
Share on other sites

Thanks for the warning.  I didn't realize they might change the categories.  Outside of the contest, though, 4k still makes some sense for a 2600 game but 1k really doesn't.  I'll keep my fingers crossed.

 

Well, come up with a couple 1K games and a menu and you can slap 'em together into one 4K cart.

Link to comment
Share on other sites

I'm certain that the kernel can be improved, (i.e. if I can ever understand how to use Thomas Jentzsch's Skipdraw) so maybe I can get some of them in.

If you post your source I'd be happy to take a look at it to see if I can tighten up your kernel at all :) If you want.

 

And switchdraw is kind of hard to understand; it took me a day or two of thinking about it to understand it. But it is pretty slick :)

Link to comment
Share on other sites

Sure, I'm not above asking for help :?

 

; kernel setup

               LDA #13  

               STA T1024T; RIOT timer ensures timing - (162 lines?)

               

               LDA line; number of lines at top of PF

                           ; changes each frame for scrolling effect

               STA decline; height of blocks

               LDA #0 

               sta mask; draw mask

               STA VBLANK     ; Enable TIA Output

               ldy #255-142; scanline + 113 (designed to wrap)

               LDX #minefield; RAM pointer for space mines
;begin kernel



drawpf

               STA WSYNC

               STA.w GRP0; delay for proper PF timing

               LDA 0,X

               STA PF0

               LDA 1,X

               STA PF1

               LDA 2,X

               STA PF2

               INY; waste cycles plus increment

               LDA 3,X

               STA PF0

               LDA 4,X

               STA PF1

               LDA 5,X

               STA PF2

               LDA INTIM; use RIOT for timing

               BEQ done; kernel done

               DEC decline; 12 lines for PF blocks

               BNE skip2;if not taken, blank line in kernel

               LDA ship,Y; load ship GFX

               AND mask; $FF or $00 to turn on/off

       STA WSYNC

sta GRP0

       LDA #0; clear PF

       STA PF0

       STA PF1

       STA PF2

       sta ENAM0;clear missile

               LDA INTIM; RIOT for timing

               BEQ done; kernel done

       stx COLUPF; change PF color

               TXA

nodraw          CLC; seems to be needed

               ADC #6   

               TAX; add 6 to PF index

               LDA #11; reset for 11 lines of PF

               STA decline 



               INY

               CPY #12; check to see if we will draw missile

               BCS nope; if taken, no

               DEC mask; if not taken, make mask $FF to enable drawing

nope

       LDA firing; are we firing?

       BEQ skip2; if taken, no.

       CPY missilepos; is missile in right position?

       BMI skip2; if taken, no.

       STA ENAM0; draw missile

skip2

               LDA ship,Y; load ship GFX

               AND mask

               JMP drawpf



 

I believe the longest chains use 72 cycles at last count (could be wrong.) Asymmetric playfields burn a lot of cycles!

 

To handle the player, I used AND masking to turn it on and off, which probably isn't the best way but I can't figure out how to apply skipdraw here. The way I've designed this, you can only change the AND mask every 12 lines (in the gap between PF blocks.) This requires padding the GFX table with a dozen zeros.

 

I want to change the missile to be shorter, and I want to add a second player, and maybe a second missile (or just flicker them, not a big deal on this) and if there's extra cycles, shade the player(s). Maybe I'm being too ambitious on this one...

 

If none of the above is possible, I will consider removing the left PF0 since it's just 4 bits anyway, and use only the lower 4 bits of the right PF2 which may save some cycles (and some RAM) at a cost of making the playfield a little narrower. Also, maybe checking Y instead of the RIOT for timing will help.

 

Also, if anything in the kernel can be improved by using a two-line gap between PF blocks instead of one, I'm willing to do this, just not a striped PF! That doesn't work here.

Link to comment
Share on other sites

but you are running at 242 scanlines most of the time

 

That's what I get for doing arithmetic in my head :dunce:

 

That's good, though, since it gives me 20 more lines for more graphics. I can use it show how many ships are left or something of that sort.

Link to comment
Share on other sites

Thanks for the warning.  I didn't realize they might change the categories.  Outside of the contest, though, 4k still makes some sense for a 2600 game but 1k really doesn't.  I'll keep my fingers crossed.

 

Well, come up with a couple 1K games and a menu and you can slap 'em together into one 4K cart.

 

I proposed just this to batari yesterday, similar to what Thomas Jentzsch is doing with his three 1K minigame titles. Putting three 1K minigames on a single cartridge with a nice menu makes it a bit more compelling. :)

 

..Al

Link to comment
Share on other sites

I believe the longest chains use 72 cycles at last count (could be wrong.)  Asymmetric playfields burn a lot of cycles!

 

To handle the player, I used AND masking to turn it on and off, which probably isn't the best way but I can't figure out how to apply skipdraw here.  The way I've designed this, you can only change the AND mask every 12 lines (in the gap between PF blocks.)  This requires padding the GFX table with a dozen zeros.

 

I want to change the missile to be shorter, and I want to add a second player, and maybe a second missile (or just flicker them, not a big deal on this) and if there's extra cycles, shade the player(s). Maybe I'm being too ambitious on this one...

 

If none of the above is possible, I will consider removing the left PF0 since it's just 4 bits anyway, and use only the lower 4 bits of the right PF2 which may save some cycles (and some RAM) at a cost of making the playfield a little narrower.  Also, maybe checking Y instead of the RIOT for timing will help.

 

Also, if anything in the kernel can be improved by using a two-line gap between PF blocks instead of one, I'm willing to do this, just not a striped PF!  That doesn't work here.

 

Well...I rewrote your kernel a bit - it will give you some of what you wanted, but to get it all I think your best bet is to use a narrower screen (like you mentioned). The best way to do that, though, isn't the way you said: better to reflect the PF and then ignore PF0. It makes the timing a little tighter, and less flexible, but you eliminate two PF writes per scanline (plus saves 1/3 of your RAM usage).

 

Anyway, here is the rewritten kernel. I'll post some explanation at the bottom:

 

                  ;--come in at 65 cycles

Loop

  lda #P0HEIGHT  ;+2   67

  dcp P0Y        ;+5   72

  bcs DoDraw     ;+2   74

  lda #0         ;+2   76

  .byte $2C      ;-1   75

DoDraw

  lda (),Y       ;+5    4

  sta GRP0       ;+3    7

  lda MissileSwitch

  sta ENAM0      ;+6   13



  lda PF0Data,X

  sta PF0        ;+7   20

  lda PF1Data,X

  sta PF1        ;+7   27

  lda PF2Data,X

  sta PF2        ;+7   34

  lda PF3Data,X

  sta PF0        ;+7   41

  lda PF4Data,X

  sta PF1        ;+7   48

  lda PF5Data,X

  sta PF2        ;+7   55   I think all PF register writes come at the right time



  dey            ;+2   57

  beq Done       ;+2   59

  cpy SwitchLine ;+3   62

  bne Loop       ;+2/3 64/65

  dex            ;+2   66



  lda #P0HEIGHT  ;+2   68

  dcp P0Y        ;+5   73

  bcs DoDraw2    ;+2   75

  lda #0         ;+2    1

  .byte $2C      ;-1   76

DoDraw2

  lda (),Y       ;+5    5

  sta GRP0       ;+3    8

  lda #0         ;+2   10

  sta ENAM0

  sta PF0

  sta PF1

  sta PF2        ;+12  22

  stx COLUPF     ;+3   25

  lda SwitchLine ;+3   28

  sec            ;+2   30

  sbc #BLOCKHEIGHT;+2   32

  sta SwitchLine ;+3   35



  lda #MISSILEHEIGHT  ;+2   37   height in (blocks-1), not scanlines

  dcp MissileY        ;+5   42   Y-position in blocks

  sbc #MISSILEHEIGHT-2;+2   44   if carry is set (i.e., we want to turn missile on), 

                      ;          then A will hold -2.  Else A will hold -3.

  sta MissileSwitch   ;+3   47



  SLEEP 13            ;+13  60

  dey                 ;+2   62

  bne Loop            ;+2/3 64/65



Done                   ;     60/65

 

Changes:

-made timing of everything constant so I could eliminate WSYNCs - that's one of the great things about SkipDraw (which I used in a slightly modified form here) - it takes the same number of cycles, drawing or not.

-Not using INTIM counter. Instead, using Y to count scanlines, and counting down (instead of up) so don't have to cpy to know when I'm at the end.

-Using SkipDraw to draw player - which means he can move vertically if you want. If not, you can probably shave a few cycles off of the time to draw him.

-Using, um, BobDraw (Ha!) to draw the missile.

To not draw the missile, position it offscreen (make MissileY == 255 or something).

If you were willing to restrict the height of the missile to one 'block', then you could point the stack at ENAM0 and do this instead:

cpy MissileY

php

pha

and shave a few cycles more.

 

To get two simultaneous players you could probably go one of two ways:

a two-line kernel (2LK), VDELing one of the players, or

reflect the PF and only use the middle 2 registers.

Either way you could probably find room for both players.

 

Hope this helps and my code isn't too confusing.

 

Oh, and:

in SkipDraw, the .byte $2C is just a slick way to skip ahead two bytes:

$2C is opcode for bit abs, so it takes 4 cycles and skips the next two-byte instruction.

And dcp is an illegal opcode, it decrements memory and then compares it to the accumulator, all in 5 cycles :) - Which reminds me: P0Y (and MissileY), since they are counting down, need to be set as the distance from the top of the screen, not the bottom.

Link to comment
Share on other sites

Cool! 8) Thanks for your efforts in tightening up that kernel. This has been the hardest thing about 2600 programming for me. I already knew the 6502 pretty well going in, but I never worried much about cycles before except in a really limited way.

 

I didn't know you could make a reflected PF asymmetrical. Since there are two PF2 writes in a row, I imagine that timing needs to be dead-on. But I can live with losing PF0 since RAM is already tight and it will free up 7 cycles (albeit non-contiguous cycles.) Now that I see skipdraw in the proper context, it makes sense! That's what I needed, really, as the explanations on the Dig didn't really describe it well enough for me.

 

Looking at this, I think that two more cycles can be saved in the blank line part:

 


  lda #P0HEIGHT  ;+2   68

  dcp P0Y        ;+5   73 

  bcs DoDraw2    ;+2   75

  lda #0         ;+2    1

  .byte $2C      ;-1   76

DoDraw2

...



  sec            ;+2   30 

 

Now if we get to that 2C, the carry is cleared, otherwise it is set. I think we could change the LDA #0 to ADC #256-POHEIGHT which would set A to 0 but also set the carry, thus eliminating the SEC below and saving 2 cycles. Eliminating PF0 as well will give me 18 total here, so I'll try to think of some way to use these up.

 

Now I'll try to find something useful to do in two sets of 7 non-contiguous cycles in the main kernel. Anyway, time to get to work...

Link to comment
Share on other sites

Now if we get to that 2C, the carry is cleared, otherwise it is set.  I think we could change the LDA #0 to ADC #256-POHEIGHT which would set A to 0 but also set the carry, thus eliminating the SEC below and saving 2 cycles.

Good point. Should work.

 

If you want to save more cycles, try to use SwitchDraw.

Link to comment
Share on other sites

Oh, I forgot to mention:

The actual SkipDraw routine (as opposed to the DoDraw routine I used above) only takes 17 cycles, but it requires a little bit of fancy code organization. Probably not a problem for your kernel. Looks like this:

 

   lda #PLAYERHEIGHT   ;+2    2

  dcp PlayerY         ;+5    7

  bcc SkipDraw        ;+2/3  9

  lda (),Y            ;+5   14

  sta GRP0            ;+3   17

ReturnFromSkipDraw





elsewheres...





SkipDraw                 ;     10

  SLEEP 4               ;+4   14

  bcc ReturnFromSkipDraw;+3   17    branch always

There's another cycle right there! :) This one isn't so good when you are VDELing, since it does, indeed, skip the write to GRP0. But it is faster and it does give you 4 cycles to play around with.

Link to comment
Share on other sites

There's another cycle right there!

 

One cycle is exactly what I need to display P1! The seven cycles at one or the other end of the PF writes was enough to shade P0 but I needed exactly 8 to display P1 (due to a 5-cycle indirect indexed addressing and 3 cycle zero page store.) P1 will be for the powerups and will move in tandem with the PF blocks so all I need to do here is set the index in the blank line to either point to zeros or P1 graphics. I'll probably use most of those 18 free cycles in the blank line to set this up.

 

If you want to save more cycles, try to use SwitchDraw.

 

I searched [stella] and the forums and found mention of Switchdraw but I can't seem to locate the code itself or even its theory of operation. Perhaps someone can point me in the right direction.

Link to comment
Share on other sites

I searched [stella] and the forums and found mention of Switchdraw but I can't seem to locate the code itself or even its theory of operation. Perhaps someone can point me in the right direction.

:idea: Have a look at this thread:

http://www.biglist.com/lists/stella/archiv...2/msg00058.html

Link to comment
Share on other sites

I didn't know you could make a reflected PF asymmetrical.  Since there are two PF2 writes in a row, I imagine that timing needs to be dead-on.  But I can live with losing PF0 since RAM is already tight and it will free up 7 cycles (albeit non-contiguous cycles.)

 

This sounds like it would be a very useful thing to do. From the timing diagram it looks like you would have to finish writing PF2 at exactly cycle 49? However, the testcode below does not work (in Stella and Z26) unless the write finishes on cycle 48? Will this actually work on real 2600 hardware?

 

Chris

 

; Asymmetrical Reflected Playfield Test

       PROCESSOR 6502

       INCLUDE vcs.h

       INCLUDE macro.h

       SEG CODE

       ORG $F800

Start   CLEAN_START

       lda #%00000011          

       sta CTRLPF             ; Reflected Playfield

       lda #$76                        

       sta COLUP0             ; LHS Colour

       lda #$55 

       sta COLUP1             ; RHS Colour

Main    VERTICAL_SYNC

       lda #43

       sta TIM64T

VBlk    lda INTIM

       bne VBlk

       sta VBLANK

       ldy #192  

Screen  sta WSYNC              ; [0] 

       SLEEP 20               ; [0] + 20

       lda #%10101010         ; [20] + 2

       sta PF1                ; [22] + 3  < 28

       lda #%11111111         ; [25] + 2

       sta PF2                ; [27] + 3  < 38

       lda #%01010101         ; [30] + 2 

       SLEEP 13               ; [32] + 13

       sta PF2                ; [45] + 3 = 48

       lda #%11111111         ; [48] + 2

       sta PF1                ; [50] + 3   

       dey

       bne Screen

       sta WSYNC

       lda #2

       sta VBLANK

       ldy #30    

OScan   sta WSYNC

       dey

       bne OScan          

       jmp Main

       ORG $FFFC

       .word Start

       .word Start

Link to comment
Share on other sites

Huh, kinda like Worm War I

 

Just tried that Worm War I. I'd never played it before. The shootable blocks idea is similar, and it looks like the author considered some of the same design compromises. However, I've been thinking about doing something much more interesting with the game engine than just random shootable blocks. We'll see...

 

I didn't know you could make a reflected PF asymmetrical. Since there are two PF2 writes in a row, I imagine that timing needs to be dead-on.

This sounds like it would be a very useful thing to do.

 

The reflected PF greatly reduced the complexity of the PF rotations, which saved both ROM and cycles. And it only worked on exactly cycle 48 for me too.

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