Jump to content

ScumSoft

Members
  • Content Count

    415
  • Joined

  • Last visited

Posts posted by ScumSoft


  1. I've implemented a software 96x192 pixel display output.

    However I am having some issues coming up with a fast method to do mid-byte positioning.

     

    I have a 12byte display output buffer and brute forcing a sprites bits into position would be done like this:

    GeneratePixelOffset:
       lax PlayerX             ;[]+3 Load Players X position 0-95
       ldy XPosTable,X         ;[]+4 Get amount to shift
       sty ShiftAMT            ;[]+3 Store for later
       lsr                     ;[]+2 Divide by 8
       lsr                     ;[]+2
       lsr                     ;[]+2
       tax                     ;[]+2 Use as offset
       lda GFXtable,X          ;[]+4 Get GFXbuffer slot number
       sta P0GFXslot           ;[]+3 Save for later
       rts                     ;[]+6
    GFXtable:
     .byte $00,$06,$01,$07,$02,$08,$03,$09,$04,$0A,$05,$0B ;GFXbuffer 0-11
                 
    XPosTable:
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 00-07
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 08-15
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 16-23
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 24-31
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 32-39
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 40-47
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 48-55
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 56-63
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 64-71
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 72-79
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 80-87
     .byte $00,$01,$02,$03,$04,$05,$06,$07 ;Pixels 88-95
    
    [...]
    
    ***THEN IN THE SCANLINE KERNAL***
    ;Pretend I want to draw the player right now
    ldy GFXindex       ;Which sprite to draw?
    lda (GFXplayer),Y  ;fetch GFX data to be drawn
    
    ldx P0GFXslot      ;calculated outside kernal, 0 to 11
    
    ;Position the sprite roughly into the appropriate GFXbuffer byte
    sta GFXbuffer,X
    
    ;Now rotate into position determined by ShiftAMT
    lda ShiftAMT
    beq .noShift
    lsr
    beq Shift1
    lsr
    beq Shift2
    
    [ect...]

     

    This would take too many cycles just checking to see how many bytes to shift.

    Then if say I am shifting over 3 bytes:

    shift3:
     lsr GFXbuffer,X
     ror GFXbuffer+1,X
     lsr GFXbuffer,X
     ror GFXbuffer+1,X
     lsr GFXbuffer,X
     ror GFXbuffer+1,X
    

     

    Way too many cycles over budget.

    So I am currently looking into doing some smart masking and bit flipping to avoid this much overhead.

     

    Would a simpler method already be known that I could learn from?

    96PixelTest.bin


  2. 		; Unused/undefined registers ($285-$294)
    
               ds 1	; $286
               ds 1	; $287
               ds 1	; $288
    TEMP0	    ds 1	; $289  Writeable and readable
               ds 1	; $28A
    TEMP1	    ds 1	; $28B  Writeable and readable
               ds 1	; $28C
               ds 1	; $28D
               ds 1	; $28E
               ds 1	; $28F
               ds 1	; $290
               ds 1	; $291  Mirror of TEMP0 data
               ds 1	; $292
               ds 1	; $293  Mirror of TEMP1 data

     

    I modified VCS.h like this.

     

    I noticed there was a few undefined bytes of memory space, but I am not sure where this space is located. So I assigned a name to each and tried storing and loading data from each of them, and this is what I got.

     

    Stella can read and write to the above addresses, but I wasn't sure if a real 2600 could, so I loaded GFX data into TEMP0 and TEMP1 each scanline, slapped it into my harmony cart and behold they work on a real 2600.

     

    Where in the 2600 are these bytes located? It defines these in the riot chip, but what parts of this chip are actually unused? The other bytes aren't writable but those 2 are for some reason.

     

    Found a RIOT.txt that explains them as this:

     

    $0286 = (RIOT $06) - Write edge detect control - negative edge, enable int (1)

    $0287 = (RIOT $07) - Write edge detect control - positive edge, enable int (1)

    $0288 = (RIOT $08) - Write DRA

    $0289 = (RIOT $09) - Write DDRA

    $028A = (RIOT $0A) - Write DRB

    $028B = (RIOT $0B) - Write DDRB

    $028C = (RIOT $0C) - Write edge detect control - negative edge, disable int (1)

    $028D = (RIOT $0D) - Write edge detect control - positive edge, disable int (1)

    $028E = (RIOT $0E) - Write edge detect control - negative edge, enable int (1)

    $028F = (RIOT $0F) - Write edge detect control - positive edge, enable int (1)

    $0290 = (RIOT $10) - Write DRA

    $0291 = (RIOT $11) - Write DDRA

    $0292 = (RIOT $12) - Write DRB

    $0293 = (RIOT $13) - Write DDRB

     

    I'm not sure what DRA/DDRA/DRB/DDRB pertain too.


  3. I read somewhere else here, that it was a compromise of the Tia designers realized only too late. There wasn't an expectation during design that programmers would exploit more potential from the system than originally anticipated.

     

    It was designed for basic games...

     

    "Programmers break free. Programmers expand to new territories. Painfully, perhaps even dangerously. But Programmers find a way" :D


  4. The engine I've been working on for my game changes things quite a bit. I've more or less taken the limits on horizontal positioning of P0/P1 and threw them out the window.

    (I had to go fetch my Atari from the neighbors yard afterwards but this is another story) ;)

     

    Instead of worrying about a P0 sprite being placed all over the screen for multiple things, I've decided to lock it in place along with P1 in a 3 by 3 config, 8 pixels apart then splitting this between 2 frames. At the end of the first frame and in the overscan, I move P0 and P1 over 8 pixels which fills in the gaps. This causes some flicker to happen, but only when the entire screen is one color, for smaller sprites it provides very little flicker, more like a shimmer effect.

     

    So what this effectively did, was give me a 96x192 software controlled playfield with 12 sprites per scanline and 24 rows for a total of 288 unique sprites.

    How one uses this is another story, as I am still creating the control logic behind it all. But so far it is VERY flexible and should allow for all sorts of new and neat things to be drawn. After drawing a scanline I have 27 cycles left, and in the interlaced lines I have 64 cycles free. This allows just enough time to stuff a 12-byte pixel buffer with the next scanlines data. Couple this with smart masking and you have a nice display that can do per pixel stuff. It also allows me to set 2 unique colors per sprite, so that is 24 colors per scanline total. I am currently coding the rotation kernal for moving images left and right.

     

    The only sad limit, is while you can do so much, it is limited to 96 pixels wide. So to get around this limit, I've come up with the idea(not completely implemented yet) to move the 96 pixel viewport around the screen as my player moves. This gives the illusion that the world is staying still and only the viewport is moving within the screen bounds.

     

    I was hoping to have a demo up today, but there are some delays I didn't foresee. Hopefully before this weekend is over I'll have something nice to show everyone.


  5. New one has a stronger contrast to the color, the older one looks to be a bit more washed. But I also think it will depend on which game screen is shown.

    Say if you were in a dungeon, would the new one look much better than the old? I think its just the limited shades of green for these screenies.


  6. Oh thank you so much SpiceWare its working great!

    I had the addressing wrong, I was placing commands in the table and not offsets to the routines.

     

    Once I finish my game, I'll have a huge list of problems I've encountered and should compile them together and their appropriate solutions for others to learn by.

    Beginner tutorials are great for getting started, but actual game design problems and their solutions would be a valuable resource don't you think?

     

    Now I can finally proceed. Thanks again.


  7. This could be done so long as you had writable internal storage in the cart itself, and just overwrite the playdata when it asks.

    Though this would be easier said than done. But I'm no expert, it may be impossible for all I really know.

     

    [edit] on second thought, doesn't Dragonstomper stream the data from the cassettes, so all you need is control logic in the game for seeking data from an external storage device hooked directly into the cartridge so as to avoid slow transfers via joy ports right? Hmm, might be easier to just use the harmony cart for this idea.


  8. Alright I give. How does one implement a Jump table in 6507 code? I'd like to hold an offset like such to a table of Jumps:

     

    Offset = 0 through 3

     

    JumpTable:

    jmp doThis

    jmp doThat

    jmp doSomething

    jmp DONTDOTHAT

     

    And I'd like to call it via jmp JumpTable,Offset to land on the right bounce.


  9. Hello again everyone, I've been busy since last week programming up my games framework(see blog for details).

    Its great to be back here and to start coding again.

     

    I have come up with a neat interlaced routine (not sure if something similar has been posted) and

    I need to flip a single bit on and off every frame which sets the interlace routine to even/odd frames:

     

    So what happens is during the kernal I manage it all like this:

               ldy Scanlines           ;[]+3     ;Our Scanline count for our interlaced loops
                                                 ;-Loaded from VBLANK to save precious playfield cycles
    
    PF_LOOP:    tya                     ;[3]+2    ;Interlace frame check
               eor #1                  ;[5]+2    ;Toggle bit, this switches between Draw & Logic scanlines
               and #$01                ;[7]+2    ;Mask all but bit 1
               beq PF_LOGIC            ;[9]+2/3  ;Branch to Logic scanline
    
    PF_DRAW:    ;********************************
               ; [DRAW SCANLINE]
               ; * 96 Scanlines of visible graphics
               ; * Scanline [??], S.cyc [11]
               ; * PixelPos [-35], Color clock [33]
               ;********************************
               
               ;***DO STUFF like draw graphics
    
               jmp PF_Return           ;[]+3    ;Jump out of Draw
    
    PF_LOGIC:   ;********************************
               ; [LOGIC]
               ; * 96 scanlines for logic
               ; * Scanline [39 to ??], S.cyc [12]
               ; * PixelPos [-32], Color clock [36]
               ;********************************
               ;***DO STUFF LIKE
               ;***Blank out graphics so they are not visible on this scanline
               ;***Process updates ect
               ;-Fall through to PF_Return
    
    PF_Return:  dey                     ;Decrement scanline
               sta WSYNC               ;-
               bne PF_LOOP             ;If more scanlines left, loop 
               ;All done? Fall through to overscan
    
    And in the Overscan I do this:
        
               ;***Interlaced display settings***
               lda Interlace           ;This will interlace the display
               eor #1                  ;-toggle bit between 0 and 1
               sta Interlace           ;-store value for next pass
               bne .ODD                ;-if its a 1 then setup for ODD frames
                   lda #191              ;Set to 192 scanlines total (191 to 0)
                   sta Scanlines         ;-used during PF_LOOP
                   lda #33               ;Compensate 1 more scanline for interlace
                   sta TIM64T            ;Will total 262 scanlines
                   jmp .OS_LOGIC         ;Proceed to Overscan logic
               
    .ODD:       lda #192                ;We want 193 scanlines (192 to 0)
               sta Scanlines           ;-store value for next pass
               lda #34                 ;Compensate 1 less scanline for interlace
               sta TIM64T              ;Will total 262 scanlines
               ;-proceed to Overscan logic

     

    Is this a typical way of doing an interlaced kernal? Every frame is alternated starting at Logic->Draw to Draw->Logic and so forth, I find this gives minimal flicker and allows for an entire frames worth of time for logic and drawing collectively.

     

    What I would like to know is if someone invented a better way to do interlaced kernals. This seems to work fine right now for my game, but I am very curious as to what others have done before me.

     

    Okay sleep time, cya all tomorrow.


  10. Alright! My cart showed up just a little while ago. Very impressive, thank you for such a great product!

    It has already showed me a few glaring errors in my games draw routines that seemed to look fine in stella.

     

    Great product! this is going to make programming oh so much more fun.


  11. DOH! Right from the get go I got stuck on the right < border right on the tip.

    I didn't take a screenshot the first time so I managed to do it again for ya.

    capturekf.jpg

     

    Only seems to happen when I set the controls to 45 deg.

    You collide it from the bottom left and you fall off the cliff behind the border, then it spawns you inside the barrier.

     

    Otherwise fantastic job!

    • Like 1

  12. The "Insert Logic Here" comments for VBLANK and Overscan should be placed before their looping labels, instead of after. Otherwise the inserted code will loop N number of times per frame instead of once per frame. (where N depends on the cycle timing of the inserted code.)

     

    I modified my version of the template to use the timer approach for the playfield as well, so I can build up the different sections of the screen (score, radar, whatever) as I go along and still have a 292 cycle count the whole time, but that's just a matter of preference.

     

    Thanks for the nice template! :thumbsup:

     

    Yes this was fixed on my end a little while after I posted, but due to not being able to edit the post after it was replied to I just left it to the user to fix without mention.

    Glad its at least helped some :)

     

    [edit]test test


  13. Yeah I'll be posting something good once it's at a presentable state. In the mean time I am trying to pickup on everything that assists me in understanding the 2600 better.

     

    I am curious though, I was under the impression that the 6507 didn't have enough umph to push the TIA for more than 9 color changes per scanline. How would a chip on the cartridge feed the TIA when it must first pass through the slow 6507? Is there direct access to the TIA from a rom space?

     

    ;)


  14. Very cool, I like it. Any massive hardware tricks required?

    I'm still learning how the 2600 all works and just got Visual Batari running under Win7's XP virtual machine.

     

    Would you have enough cycles left for player movement and enemy updates? If so it would be really cool to play.

×
×
  • Create New...