Jump to content

SpiceWare

+AtariAge Subscriber
  • Content Count

    16,912
  • Joined

  • Last visited

  • Days Won

    10

Blog Comments posted by SpiceWare


  1. That test screen's fairly consistent with time. With actual game play logic the timer values change practically every frame, but you can still read it well enough to know the values you're seeing.

     

    Used to read Compute! and the Gazette as well. If I recall correctly, in 81 my Vic 20 included a trial subscription to a magazine that had gone under, they replaced it with Compute! and I continued to subscribe to it for a long time.


  2. I can get why D7 could be linked with plus and minus, but how D6 translates to an overflow is beyond me. Sounds like something that just needs to be memorized, but not understood!

     

    The Processor Status is stored in a single byte in the format of NV-BDIZC, so D6 is the overflow flag.

     

    In Stella you can see that representation used just below the Y register and above Zero Page RAM. Stella uses case to display the state of the status flags: lower case = 0, upper case = 1.

     

     


  3. Interesting. I'm surprised that the Stella debugger doesn't just display timer values by default.

    Stella does show the timer, it's on the I/O tab. I just find it easier to see the value in real time, while I'm play testing on real hardware, rather than having to stop the program in Stella to see it. This photo is from Part 6 of the Story of Stay Frosty, time remaining is displayed below the score & lives/level display:

    blogentry-3056-0-55021800-1421003912.jpg

     

    When I do that I'm actually display about 272 scanlines, but my C= 1084S monitor can handle that.


  4. On 1/5/2016 at 2:02 AM, BNE Jeff said:

    Also, are you grouping particular routines in either overscan or vertical blank? In other words, is there an advantage to placing certain logic in either one or the other, or are you maybe following some convention?

    Collect is such a simple game that it's highly probably that all the routines could run in just Overscan or Vertical Blank. I use this loop:

    1. Process User Inputs
    2. Movement logic for things not controlled by a player
    3. Prep for display (position all TIA objects, initialize values needed by Kernel, etc)
    4. Kernel
    5. Collision processing

     

    I know that for a complex game not everything can be run in OverScan or Vertical Blank, and that OS has about half the time that VB does, so I start out with #5 in OS and #1-3 in VB. Some of the routines may need to be shifted as processing time gets used up - in order to know which is running short on time I normally build in a way to capture time remaining:

    DEBUG = 0 ; set to 1 for debug info in score and to flash screen if fireball
    ...
    ; in the Define RAM Usage section 
     if DEBUG = 1
    VBtime ds 1
    OStime ds 1
     endif
    
    ...
    
     if DEBUG = 1
            lda INTIM
            sta VBtime
     endif
    
    Kernel:            
            sta WSYNC       ; Wait for SYNC (halts CPU until end of scanline)
            lda INTIM       ; 4  4 - check the Score+1
            bne Kernel      ; 2  6 - (3 7) Branch if its Not Equal to 0
    
    ...
    
     if DEBUG = 1
            lda INTIM
            sta OStime
     endif
    
    OSwait:
            sta WSYNC   ; Wait for SYNC (halts CPU until end of scanline)
            lda INTIM   ; Check the Score+1
            bne OSwait  ; Branch if its Not Equal to 0
            rts         ; ReTurn from Subroutine
     

    When possible I'll set up a way to display those values, but if it's not then the RAM variables can be checked via Stella's debugger.


  5. Hi.. Is there any reason that D6 and D7 are easy to test with the BIT command? Or are they all easy, but were just happen to be looking for 6 & 7 here?

    From 6502 Opcodes:

     

    The S and V flags are set to match bits 7 and 6 respectively in the value stored at the tested address.

    So after the BIT command you'll use the branch commands BPL or BMI if you're checking the state of bit 7, and BVC or BVS for bit 6. Bits 0-5 do not get copied to a processor flag, so testing those bits is more involved.


  6. The stated goal of this series was to show how to program a very simple game, didn't need 4K for that.

     

    Changing the ORG is all there is to it, that's why that comment is in the source code. I didn't mention larger than 4K because that requires the use of bankswitching, which would just add unnecessary confusion for somebody getting started with 2600 programming.


  7. Has to do with how a single broadcast signal can be divided up to send multiple channels that are known as subchannels. In the first screenshot channel 30 broadcasts 2 subchannels, 34 has 4, 39 has 3, and 43 has 8.

     

    The most subchannels I've seen for a free channel is 12 for a religious network. Picture and audio quality suffer quite a bit when they do that.

     

    I suspect part of what's up is Houston became the most diverse city in the nation a few years ago. We have channels in Chinese, Vietnamese, Spanish, Farsi, etc. Since I don't speak those languages I deselect those channels and the EyeTV DVR software ignores them (it won't record any shows, won't list them in the TV guide, etc). Back when I started this project I discovered that less than half the channels in Houston were in English.


  8. So, if I have this straight,

    Yep


    EOR is switching the right three bits- 0's to ones, and 1s to zeros... I'm still not sure why...Are we converting this remainder to two's compliment negative?

    The remainder is based on the object being positioned at the first of the 15 locations, but it actually ends up in the middle of those 15 positions. The EOR 7 makes it so a remainder of 0 moves the object left by 7. A remainder of 1 moves the object left by 6, ... 6 moves left 1, and 7 becomes 0 so it doesn't move at all.


    By the time we RESPO, isn't our course position timing off? Didn't we use like 19 more cycles to get to it?

    If you check the timing diagram in Step 3, you should notice that the initial 22 cycles are during the Horizontal Blank. If you strobe RESP0 during that time then player0 ends up at position 3.

  9. As another pointer to research this question - step thru PosObject after you change A to 0, then 1, 2, etc thru 14. Then again for 15 thru 29.

    At the end of PosObject, when PC is pointing at the RTS statement, switch from the Prompt tab to the TIA tab. Make note of values in Pos: and HM: for the object being moved (as indicated in the X register).

    You can set a second break at the RTS if you don't wish to step thru each and every instruction in PosObject:
    break F812

    Don't forget that HM value is the adjustment to move the object left. Also don't forget that the HM value is a signed a 4 bit value that's encoded using two's complement. A negative value results in the object moving right right.

     

    0-7 are positive values: 0 = 0, 1 = 1, ...., 6 = 6, 7 = 7

    8-F are negative values: F = -1, E = -2, ..., 9 = -7 and 8 = -8.


  10. except for all of the schematics which I only skimmed because they didn't seem very relevant. (feel free to correct me if I'm wrong on that)

    They're not helpful for me, but for others they can be. batari compared the heavy sixer schematics to those of later models and was able tofigured out why a Melody board revision was not working on the sixer switch systems.

     

    I guess I only understood HMMO, etc. as useful for relative movement, not fine tuning something stationary.

    Fine tuning is a must for position an object, even if stationary. With only 76 cycles per scanline, there's no way we could strobe RESPx at the correct time to position an object to all 160 X locations that it could appear on.

     

     

    It looks like it has a lot of capability.

    It does, that's why I figured a detailed answer showing you how to use it to research this particular question would be more useful than just explaining the subroutine in more detail :)

  11. Per Step 1 you should have downloaded the Stella Programmer's Guide as a reference. Open it up and look at the bottom of page 41 (page 46 per a PDF viewer) and read up on the section for HMP0, HMP1, etc.

     

    In the list of values you should notice that only bits D7, D6, D5 and D4 are used. That means those registers only use the value in the upper nybble, which is why we used the 4 ASL instructions to shift the modified remainder value from the lower nybble to the upper nybble.


  12. Would you be able to elaborate or do a walk-through example on the code below?

    Time to learn Stella's debugger and let it take you on a detailed walk-through:

    • Make sure that files collect.lst and collect.sym are located in the same directory as collect.bin. This is because Stella will reference the content of those files, allowing you to use the label names in the debugger.
    • Start up Stella and load collect.bin.
    • Hit the ` key (it also has the ~, to the left of 1 and above tab) to enter Stella's debugger.
    • In the prompt box, lower left of the debugger window, you should see a couple messages along the lines of:

      loaded /path/to/file/collect.lst OK

      loaded /path/to/file/collect.sym OK

    • If there's a dotted red line surrounding the prompt box, then the prompt has focus. If not, click within the prompt box to give it focus.
    • To see a summary of the debugger commands, type the command:

      help

    • For now, set a break point at the start of PosObject by typing the following command (make sure P and O are capitalized):

      break PosObject

    • You should see a response of:

      Set breakpoint at F800

    • hit the ` key again to resume execution of collect.
    • The debugger will show up again. Notice in the Disassembly box, lower right of the debugger window, that there's a red dot to the left of PosObject. That's the breakpoint you set. The green box that's highlighting PosObject SEC ... is the line of code that will next be executed.
    • Directly above the Disassembly box is the state of 128 bytes of RAM, and above that is the state of the CPU.
    • In the CPU section make note of the value after the A: That's the current value of the Accumulator, which holds the X position we plan to position an object to. The X: just below it is the X register, and it holds which object we're going to set - if it's 0 we're moving player0, if it's 1 we're moving player1.
    • In the top right corner is a Step button. Press it once. Anything that changed with the instruction will be shown with green text in a red box. Watch the PC (the program counter, or next instruction to run), the value in the Accumulator, or the state of the Carry Flag (a capital C means Carry is Set while lower case means carry is clear) as the code runs.
    • Repeatedly press the Step button until you end up on the line EOR #$07. Take note of the value of A - specifically the lower nybble (the right hex digit). That's basically the remainder of the X position / 15. You can ignore the upper nybble, it'll be F and is not used.
    • Press Step button 5 more times and close watch what the EOR and ASL instructions do to value in the Accumulator.

    Also note that you can change the values you see, which makes it easier to test what happens when different values are encountered. Let's force it to position the object at location 64, which is $40 in hex:

    • Hit ` again, you'll end up at the start of PosObject.
    • Double-click the value in the box after A:, you can now enter a new hex value - put in something like 40 then hit RETURN.
    • To the right of the 40 you'll see 64 (the value in decimal) and 01000000 (the value in binary)
    • Alternatively you can double-click the 2nd box after the A: if you'd rather enter a decimal value, or the 3rd box for a binary value.

  13. There's been some questions regarding the ifconst and endif in the Random subroutine. Basically they're instructions that dasm uses to determine whether or not dasm "sees" the code appears between the two instructions.

     

    Basically ifconst is asking "does the value listed next exist in the program?". If the answer is yes, then anything text between the ifconst and endif will be included in your program. If the answer is no, then dasm will ignore any text between the ifconst and endif.

     

    In the case of the Random subroutine dasm checks to see if Rand16 exists in the program. As written our program has this in it:

     

       ; optionally define space for Rand16 for 16 bit random number
    Rand16:         ds 1    ; stored in $AC    
    

    So the answer to ifconst Rand16 is "yes, the value exists" and dasm will "see" the code like this:

    Random:
            lda Rand8
            lsr
            rol Rand16      ; this command is only used if Rand16 has been defined
            bcc noeor
            eor #$B4 
    noeor 
            sta Rand8
            eor Rand16      ; this command is only used if Rand16 has been defined
            rts    
    

    If we deleted the following from our program:

    ; optionally define space for Rand16 for 16 bit random number

    Rand16: ds 1 ; stored in $AC

     

     

    the answer to ifconst Rand16 is "no, the value does not exist" so dasm will "see" the code like this:

    Random:
            lda Rand8
            lsr
            bcc noeor
            eor #$B4 
    noeor 
            sta Rand8
            rts   
    
×
×
  • Create New...