Jump to content
IGNORED

Concepting a Conversion #1: Fire One


Cybergoth

Recommended Posts

Since my current Atari 2600 project is going no where, I'll volunteer to help with the programming.

 

I'm new to 2600 programming, but not new to assembly language or programming in general. So I'm willing to take on tasks 7 and 8 if no one else has their hearts set on them.

 

I have no hardware or musical skills, so 4 and 3 are out.

Link to comment
Share on other sites

Hi there!

 

So, with someone working on the intro screen and someone working on the main display, this project can be started. :)

 

Let's just wait a few more days to see if more people are going to join the team before we're really starting into it.

 

Also, as this is intended to be a learning experience for everyone interested, it is ok if someone wants to help with a task that is already taken.

 

I'd also say that it is fine for people to join later on. Also, when we're analysing certain tasks in detail, maybe there's people suddenly getting interested in trying to do this or that.

 

Greetings,

Manuel

Link to comment
Share on other sites

Just a question, will the development of this project be made public somewhere as it's being done? So those of us who are feeling WAY inept at our 2600 abilities :ponder: to actually contribute can at least watch and learn bit by bit. :)

 

--

Mord

Link to comment
Share on other sites

hello

 

i startet 2600 coding last year. i had some own ideas for games, but i simply don't have the time right now to code a whole game by myself.

 

i'd, however, have the time to do for instance #5 =)

 

tom

Link to comment
Share on other sites

Hi there!

 

Ok, I had some thoughts of how the continuation of this project will work.

 

I'll try to spend a few hours every weekend on this project, starting this weekend. I'll present a small skeleton ready-to-go framework, that is compiling into a proper 8K binary for the start. I'll also mark sections where specific code has to be placed. I'll do the same with RAM and equates declaration, so everyone has a precise spot to work in.

 

Also from this weekend on I'll try to plan and analyse the required display kernels. I'll start with the main display, since this is not only the most important part, but also the one that is being tweaked and rewritten the most.

 

During the week, I'll answer any questions and discuss problems (and solutions :) ) but I won't actively do anything.

 

Whenever anyone of you has progressed something on your part, you can mail that to me and every weekend I'll merge all progress into into a new common starting base for the next week. We will also base any discussions on how to progress on this common base.

 

That does not mean that everyone has to deliver something new every week. I know best that there's times when nothing can be done.

 

To motivate you a little: Sometime in April/May I will meet TJ and Oliver Achten for a whole weekend and we'll try to develop a working solution for the 2 player console-link.

 

Greetings,

Manuel

Link to comment
Share on other sites

Hi there!

 

Ok, so here I have the kick off source for you. As promised, I'll provide the framework for the game. For the first iteration it does - nothing. :-)

 

Well, ok it does a few things. It compiles into a proper 8K binary. And it already does fully functiong bankswitching. But that is really all it does. It constantly switches between both banks.

 

Still I assume this might be already an awful lot of things to understand. I'm just not sure up to which detail I should explain it, not wanting to interfere with Andrews lessons. I'm sure he'll do bankswitching in full detail in a future sesson.

 

For the moment, I'll give you a "blackbox" answer.

 

It's all hidden in the last bytes of our 2 4K banks. There's memory locations working as "hotspots". If you touch them, both banks swap their positions and your programm continues at the precise spot on the other bank.

 

So there's two switches implemented, as simple as:

 

SwitchToBank1

BIT $1FF8

JMP Maingame

 

and

 

SwitchToBank0

BIT $1FF8

JMP Intro

 

All you have to do to "Jump" to the other Bank, is simply jumping to the switch.

 

For example, if your're in Bank0, in the main game and you want to go back to the intro, you just do

 

JMP SwitchToBank1

 

There the BIT instruction touches the hotspot, both banks are swapped and the code continues right there with the next instruction, "JMP Intro" and we're done.

 

Ok, please have a good look at it, try to see if you can compile it and ask questions if you have some.

 

Feel free to experiment with the source, or maybe even try to work on one of the required tasks.

 

Well, unless one of you is already so quick to do so by yourself, I'll continue the work on the framework by adding stable display screens to both banks next weekend.

 

Greetings,

Manuel

fireone.zip

Link to comment
Share on other sites

Hi there!

 

Ok, I said that we'll try to plan the main display at first.

 

Let's have a good look at it again, further analyzing it. What elements do need to display there each frame? Or better what elemts *can* we display there?

 

firemain.gif

 

I see the following:

 

- The background is changing its color

- There's an arrow at the top, indicating where a torpedo would hit

- There's two lines of ships, on on the horizon and one in the middle.

- There's another arrow at the bottom, indicating direction and speed of our sub

- There's torpedoes moving vertically

 

There's two more things to display which we don't see in my last milestone:

 

- Explosions

- The top arrow will indicate targets in hitting range by changing it's color.

 

Phew... how do we do that?!?

 

Well, it's not easy...

 

The first interesting thing to notice should be, that by our concept, we only need to display 2 ships per frame, per level.

 

Also, I'm sure we can display both arrows easily with 2 sprites.

 

Now, couldn't we... write a subroutine that can display all four segments of the display as in

 

- Top Arrow

- Horizon ships

- Midscreen ships

- Bottom Arrow

 

?

 

You see, the basic idea is, to call one and the same subroutine code 4 times, just by telling it things like:

 

Use this arrow shape now and place it there.

 

As for our code, simplified it'd look like:

 

Top

; Prepare Arrow code

JSR DisplayMainStripe

; Prepare Ships1 code

JSR DisplayMainStripe

; Prepare Ships2 code

JSR DisplayMainStripe

; Prepare Arrow2 code

JSR DisplayMainStripe

 

JMP Top

 

Aha!

 

So we can break it into two smaller tasks. One is the preparation code and one is the actual sub that is then drawing our stuff.

 

Ok, I'll quit here to give you some time to think about it. If there's any questions so far, please ask. Also, If you want to start into programming and experimenting feel free to do so. Please give feedback on how well your experiments do and where your main obstacles are.

 

Next weekend we'll analyse the subroutine "DisplayMainStripe" in deepest details.

 

As for the intro and state display programmers... well, feel free to start and experiment on your own as well. I hope I can give you some more direction in the next weeks. Please give me feedback about any experiments of yours as well. I'm sure the major hurdle for you will be the 6 char display routine, but we'll soon tame that beast, promised.

 

Also, please give me any feedback regarding wether I'm going to quick or to slow and don't hesitate to ask any question any time.

 

Greetings,

Manuel

Link to comment
Share on other sites

Hi Cybergoth, I haven't had time to go through your latest post in detail, but I have looked at the framework you posted and I have some questions.

 

This looks like it is the F8 bankswitching scheme I've read about. It starts out with variables for the first bank, which are divided into variables common to both banks, and variables local to bank 0. The variables for the second bank have a similar layout.

 

So my first question is, won't the too banks clobber each other's local variables? I suppose it isn't a problem with the intro screen, since it won't be used during the game. But I imagine the game logic would need to switch over to the networking code to get the moves for the second player.

 

Second, I'd like to confirm my understanding of how the DASM ORGs and RORGs are being used.

 

The first segment uses an ORG 1000 To put it at that location in the dasm output file. And then a RORG D000. The second segment uses an ORG 2000 to put it after the first segment in the output file, and an RORG F000. Am I interpreting this correctly? Since D000 and F000 will look the same to the 6507, is the difference between the RORGs so that the assembler won't get confused between addresses in the two banks?

 

I noticed that the RAM segment for the first bank is named "vars", but the RAM segment for the second bank is named "variables". Is this so that the assembler won't get confused between the two segments?

 

And finally, I noticed that each segment ends with a series of interrupt vectors that point to the FirstInit for each segment. The second segment has an ORG $2FEF/RORG $FFEF to move the interrupt vectors to the end of the bank. Shouldn't the first bank have similar statements?

 

That's it for now, I will start digesting your other message later today.

Link to comment
Share on other sites

Hi there!

 

Ok, I said that we'll try to plan the main display at first.

 

Let's have a good look at it again, further analyzing it. What elements do need to display there each frame? Or better what elemts *can* we display there?

 

firemain.gif

 

I see the following:

 

- The background is changing its color

- There's an arrow at the top, indicating where a torpedo would hit

- There's two lines of ships, on on the horizon and one in the middle.

- There's another arrow at the bottom, indicating direction and speed of our sub

- There's torpedoes moving vertically

 

There's two more things to display which we don't see in my last milestone:

 

- Explosions

- The top arrow will indicate targets in hitting range by changing it's color.

 

But from what I've seen of the game, the top arrow is different from the targgeting arrows. The black arrow is where a torpedo will go if it's fired, the red targeting arrows are where on a ship a torpedo would hit if it's fired, taking into account the ship's speed and direction.

 

Also in the arcade version, there can be multiple targeting arrows if there are multiple ships that could be hit by a torpedo.

 

So could we have to up to five arrows, red ones for targeting the ships, and a black one for the where the torpedo will go? Perhaps using the two player sprites, two missle sprites and the ball? Or maybe we'd just limit it to one red arrow? Perhaps I'm getting ahead of myself here.

 

What I'd like to do is to break it up into small milestones that I can start working off one by one. Here's what I think might work:

 

Milestone 1: Get the background colors of the horizon and the ocean drawn. This will be fairly easy as there's no sprites to mess with.

 

Milestone 2: Get two ships in the foreground drawn.

 

Milestone 3: Get the two ships in the foreground moving. Maybe just by adding temporary joystick control to the ships. What I want to do is get the display code that reads the fractional ship positions working, but not worry about the game logic for calculating velocity and movement yet.

 

Milestone 4: Get two more ships in the foreground, this involves adding flicker to alternate frames.

 

Milestone 5: Add the enemy sub. This might be a part of mileston 4, but I was wondering if we could move the enemy sub to be between the foreground ships and the horizon ships. This would eliminate flicker on the enemy sub. And it makes sense as the sonar screen shows the enemy sub as between the two rows of ships. Of course this means we have 8 ships on the screen at one time, plus the enemy sub, so there's extra memory used.

 

Milestone 6:

Add the ships on the horizon.

 

Milestone 7:

Add the top black arrow.

 

Milestone 8:

Add any top red targeting arrows, or maybe not if we decide not to do that.

 

Milestone 9:

Add the bottom arrow.

 

And then it would probably be time to switch to implementing some game logic before adding torpedoes and explosions and stuff. But I don't feel like making up mile stones for that right now.

 

So what do you think. Is this the right approach? Are there any mistakes or weaknesses in this plan of attack?

 

Depending on how my work responsibilities go this week, I'll try to get at least milestone one completed before next weekend.

 

Also, please give me any feedback regarding wether I'm going to quick or to slow and don't hesitate to ask any question any time.

 

Greetings,

Manuel

 

So far I think this level and detail and level of speed is perfect. Thanks so much for organizing this, this looks like it's gong to be fun!

Link to comment
Share on other sites

Hi there!

 

So my first question is, won't the too banks clobber each other's local variables?  I suppose it isn't a problem with the intro screen, since it won't be used during the game.  But I imagine the game logic would need to switch over to the networking code to get the moves for the second player.

 

This is a good observation. The variables in the "both banks" section will be the global ones as you are assuming correctly.

 

The bank specific are the local ones and we'll in fact need to take that into account when switching banks. We'll carefully need to initialize all our local variables in the new bank, as they may contain any random content.

 

The networking code will most likely not only need a few more global variables added to work with, it'll also need an extra bankswitch executed every single frame, which does not destroy the current variables of the actual game.

 

The first segment uses an ORG 1000 To put it at that location in the dasm output file.  And then a RORG D000.  The second segment uses an ORG 2000 to put it after the first segment in the output file, and an RORG F000.  Am I interpreting this correctly? Since D000 and F000 will look the same to the 6507, is the difference between the RORGs so that the assembler won't get confused between addresses in the two banks?

 

I'm no expert in that, but my ideas of how this works match yours exactly. :)

 

I noticed that the RAM segment for the first bank is named "vars", but the RAM segment for the second bank is named "variables".  Is this so that the assembler won't get confused between the two segments?

 

Yes that was my intention. I'm not sure if it is really required though. It's just good practice to give a different segment a different name.

 

And finally, I noticed that each segment ends with a series of interrupt vectors that point to the FirstInit for each segment.  The second segment has an ORG $2FEF/RORG $FFEF to move the interrupt vectors to the end of the bank.  Shouldn't the first bank have similar statements?

 

Ooooops :dunce:

 

You're right, certainly. Please add these above the FirstInit label:

 

ORG $1FEC

RORG $DFEC

 

Greetings,

Manuel

Link to comment
Share on other sites

Hi there!

 

So what do you think. Is this the right approach? Are there any mistakes or weaknesses in this plan of attack?

 

Your plan is perfect so far from a point of view based on the game logic.

 

For the actual display code, I'll try to add a level of abstraction in the next lesson, though. I'll try to get you away from thinking in the actual game terms like "ship, sub and arrow" already, but rather go a step beyond that and have us thinking about a more generic "game engine" approach. I'm sure it'll help us later to go that little extra mile first.

 

I like your idea about moving the sub on an extra level between the two ship rows, I think we should try to do that. As for the arrows, I think, as you suggested, having two of them would be fine. The second arrow can automatically deal with the "nearest ship" then.

 

Depending on how my work responsibilities go this week, I'll try to get at least milestone one completed before next weekend.

 

This would be excellent. As I said, next step in the framework would be providing two stable screens, so different background colors in the part you chose would be a very nice milestone where we already get to see something.

 

So far I think this level and detail and level of speed is perfect.  Thanks so much for organizing this, this looks like it's gong to be fun!

 

Ok, thanks. Please feel free to direct me back on track if I'm getting too quick or too slow or if I'm going too far away from you :)

 

Greetings,

Manuel

Link to comment
Share on other sites

Hi there!

 

TADA! Bad Panda Bear just submitted his first code, which is a major milestone:

 

fire1.gif

 

Check out the new base source, as attached. Next lesson will hopefully follow tomorrow, so you have time to read the source :)

 

If there's any questions regarding doing a stable TV screen, please first reread the according lessons in Andrews tutorial. If there's still any questions left after doing so, please feel free to ask.

 

Greetings,

Manuel

fireone.zip

Link to comment
Share on other sites

cool. i've toyed around a bit with a damage bar, but it's far from being any good yet.

 

something else: we're doing f8 bank switching, and the adresses that trigger the bankswitches are 1ff8/1ff9. so why do you reserve 4 bytes

from 1ff6-1ff9 ? as a reserve in case we run out of rom space, so that we can change to a 16k game ?

 

and again something else:

 


   SEG.U vars

   ORG $80


; Both Banks:

gameState       ds 1

bcdScore        ds 1

frameCounter    ds 1

rnd             ds 1

tempVar1        ds 1

tempVar2        ds 1

tempVar3        ds 1

tempVar4      



...



   SEG.U   variables

   ORG     $80


; Both Banks:

gameState       ds 1

bcdScore        ds 1

frameCounter    ds 1

rnd             ds 1

tempVar1        ds 1

tempVar2        ds 1

tempVar3        ds 1

tempVar4      

 

so this are variables that are needed by both banks. but why do you duplicate them in the source code ? imo this shouldn't be necessary,

i mean, the ram doesn't have to do anything with bankswitching, that is, it's always there, no matter which bank is switched in...

 

wouldn't something like this be better (since no code is duplicated) ?

 


  ; variables for both banks

   seg.u commondata

   org $80

gameState       ds 1

bcdScore        ds 1

frameCounter    ds 1

rnd             ds 1

tempVar1        ds 1

tempVar2        ds 1

tempVar3        ds 1

tempVar4

COMMONDATA_END = .



  ; variables for bank 0

   seg.u bank0data

   ORG COMMONDATA_END

  ; define variables for bank0 here



  ; variables for bank 1

   seg.u bank1data

   ORG COMMONDATA_END

  ; define variables for bank1 here

 

as you can see, the segment commondata starts at 0x80.

then we have two segments, bank0data and bank1data.

those start both at COMMONDATA_END (right after commondata),

and they share the same address space, so it's actually

an overlay.

 

that's btw the mechanism i use in my own 2600 coding experiments to create overlays. so far it has always worked fine for me =)

probably you can't have it more convenient with dasm, but with ca65/ld65 you could of course write yourself a neat linker script and let the linker sort it out for you.

(note that i'm NOT suggesting to switch to ca65, i just said it could be even more convenient)

Link to comment
Share on other sites

so this are variables that are needed by both banks. but why do you duplicate them in the source code ? imo this shouldn't be necessary,

i mean, the ram doesn't have to do anything with bankswitching, that is, it's always there, no matter which bank is switched in...

Because the location $80 is relative to the bank your in. (taking a guess here ;) )

Link to comment
Share on other sites

Hi there!

 

i've toyed around a bit with a damage bar, but it's far from being any good yet.

 

Ah, fine that you already try to do this. So far I have just thought about the basic idea for this, which is simple sounding, but probably very complicated to execute:

 

- Have a red colored 48 pixel wide playfield block centered in the middle of the screen and have it overlayed with a green six-char display.

 

For the start you should probably best research about 6 char displays in the [stella] archives. We'll probably also need one for the title screen, so understanding this technique is very essential. (Hm... actually, the title Screen might probably look way more impressive using the PF... let's think about this...)

 

We'll talk about this in 2-3 weeks, but it shouldn't stop you from trying on your own... :)

 

something else: we're doing f8 bank switching, and the adresses that trigger the bankswitches are 1ff8/1ff9. so why do you reserve 4 bytes from 1ff6-1ff9 ? as a reserve in case we run out of rom space, so that we can change to a 16k game ?

 

Exactly. If we desperately need those reserved bytes, we can still claim them later.

 

so this are variables that are needed by both banks. but why do you duplicate them in the source code ? imo this shouldn't be necessary, i mean, the ram doesn't have to do anything with bankswitching, that is, it's always there, no matter which bank is switched in...

 

as you can see, the segment commondata starts at 0x80.

then we have two segments, bank0data and bank1data.

those start both at COMMONDATA_END (right after commondata),

and they share the same address space, so it's actually

an overlay.

 

Excellent suggestion! I'll change this with the next iteration of the source!

 

Greetings,

Manuel

Link to comment
Share on other sites

Hi there!

 

Because the location $80 is relative to the bank your in. (taking a guess here ;) )

 

No, Tom is right :)

 

The RAM location is absolute. I just never thought this "problem" as far to the end as Tom and he presented a very elegant way of both eliminating redundant code and minimizing the risk of possible errors by mismatching RAM equates.

 

Greetings,

Manuel

Link to comment
Share on other sites

- Have a red colored 48 pixel wide playfield block centered in the middle of the screen and have it overlayed with a green six-char display.

 

For the start you should probably best research about 6 char displays in the [stella] archives. We'll probably also need one for the title screen, so understanding this technique is very essential. (Hm... actually, the title Screen might probably look way more impressive using the PF... let's think about this...)

 

yes, that's the basic approach i chose. the problem is i end up getting a red line (from the playfield) above the actual damage bar, which i can't get rid of. here's how i do it:

 

- set up pointers and sprites positions,size etc for the damage bar

- set the playfield data for the red background

- wait until PF2 isn't displayed anmore

- set the PF color to red

- jump to sixchar routine

 

the problem is that one of the first things the sixchar routine i'm using (it's the stock sixchar routine i found in the atari 7800 devkit) is a WSYNC. before that it does some initialization stuff, and the WSYNC happens just right AFTER the start of the next scanline, so i get a scanline with just the red area, before the sixchar routine actually kicks in and draws the green area. hope that makes sense =)

 

perhaps i could rework the routine so that the PF color is set inside the kernel. first i tried to do a generic sixchar routine that can be used for the damage bar and the torpedo display and the title screen, but it might be better (or at least simpler) to use an adapted version for the damage bar:

since every line of the damage bar is the same, the usual

 

lda (gfxptr),y

 

instructions could be changed to something like

 

lda gfxptr

 

which would free up way enough cycles to set the PF color inside the kernel.

it would probably free up so many cycles that one could change the sprite color too and have some nice color gradient in y direction on the damage bar =)

Link to comment
Share on other sites

Hi there!

 

perhaps i could rework the routine so that the PF color is set inside the kernel.

 

That is the first thing I'd try. There's not much you can do in a sixchar line, but IRRC those 5 cycles are there. Come to think of it, that is exactly what the sixchar on top of my current Seawolf project does.

 

it would probably free up so many cycles that one could change the sprite color too and have some nice color gradient in y direction on the damage bar =)

 

Sounds also cool and I'm sure it's doable that way. I'm not sure if it matches to the rest of the game in "style" though, as all other gfx in the game are single colored ;)

 

Greetings,

Manuel

Link to comment
Share on other sites

Hi there!

 

Ok, let's continue with the main kernel. I already said, that I'll get you away from thinking in game terms already, so the next milestone we'll try to reach will look ~ like this:

 

firegarb.gif

 

:)

 

Ok, let's have a look at our essential display code so far:. There's a main loop, looking like this:

 

 

    LDA #FIRST_SKY_COLOR

   LDY #SKY_SLICE_HEIGHT

   JSR DisplayMainStripe



   LDA #SECOND_SKY_COLOR

   LDY #SKY_SLICE_HEIGHT

   JSR DisplayMainStripe



   LDA #THIRD_SKY_COLOR

   LDY #SKY_SLICE_HEIGHT

   JSR DisplayMainStripe



   LDA #FOURTH_SKY_COLOR

   LDY #SKY_SLICE_HEIGHT

   JSR DisplayMainStripe



   LDA #OCEAN_COLOR

   LDY #((START_MAIN_DISP - END_MAIN_DISP)- (4 * SKY_SLICE_HEIGHT))

   JSR DisplayMainStripe

 

and our DisplayMainStripe sub currently looks like this:

 

DisplayMainStripe SUBROUTINE

 ;; Set background color as first part of the scanline

  STA WSYNC

  STA COLUBK

  DEY

  DEX



 ;; Call WSYNC for all but the last line of the slice

.loop

  STA WSYNC

  DEX

  DEY

  BNE .loop

  RTS

 

So far so good. The code as is, does a good job in displaying the background colors. Basically you give the subroutine a color and a height and then it'll draw background stripes just as specified.

 

Now, we'll try and tweak this a little, to get it displaying the random garbage as in the milestone picture above.

 

Basically I'd suggest to let it do something like

 

STX GRP0

STX GRP1

 

So, by some good chance (horizontal position) and with X being our scannline counter we get to see some sprite garbage on the screen, just by adding these two writes to our sub.

 

Now, one flaw in the code as is, is that the stripes it draws are fixed to draw the horizontal background color. I want us to try and change this. I want our stripes to be fixed to our grafix garbage. Here's another image to illustrate what I'm talking about:

 

firegarb2.gif

 

On the left and red colored you see our current subroutine calls. On the right and green colored are our future subroutine calls. As you can see the green blocks won't draw the whole screen. The gaps are indicated in white.

 

Now what do we do now?

 

-> We'll just do another sub, that does - nothing

 

Well, ok it does nothing, but a nothing of variable height :)

 

So our next iteration of framework loop will soon probably look like this:

 


  ; Prepare Nothing

   JSR Displaynothing



  ; Prepare Arrow

   JSR DisplayMainStripe



  ; Prepare Top ships

   JSR DisplayMainStripe



  ; Prepare Nothing

   JSR Displaynothing



  ;Optional Prepare sub 

  ;Optional JSR DisplayMainStripe

  ;Optional Prepare Nothing

  ;Optional JSR Displaynothing



  ; Prepare middle ships

   JSR DisplayMainStripe



  ; Prepare Nothing

   JSR Displaynothing



 

Hm... but what do we do with the background color?

 

For the moment we could do something very wasteful:

 

We could do a table with 192 entries of background color values. during our display we have our linecounter in X, so on every scannline we'll just

do this:

 

LDA backgroundcolortable,X

STA COLUBK

 

Phew... what a waste of memory. We'll definitely need to optimize that later...

 

Greetings,

Manuel

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