Jump to content

ScumSoft

Members
  • Content Count

    415
  • Joined

  • Last visited

Posts posted by ScumSoft


  1. Okay, I rewrote the display kernal to update in a linear fashion (needed to start thinking DPC+ style) and it looks correct now. However I still have that display corruption issue past scanline 190(stella counts vsync+vblank), so it starts on Playfield Scanline 153 to 192.

     

    This would place it at pointer offset #1836, so this is 468 bytes that aren't being parsed correctly.

    00-DPCtest.zip


  2. OH! Yes, I know exactly why it's doing this now. My original kernal I wrote used a 6-byte ram buffer and I called them back in the correct order, when it is done linearly it's causing this jumble.

    Thanks for the help, I can modify the parsing routine to adjust the bytes appropriately.

     

    Ok time to get some sleep, been up all night pondering over this :P

     

    [edit]The original code looked like this:

                ;Preload P0(0) and P1(0)
               lda GFXbuffer+0         ;[23]+3 Load  P0(0)
               sta GRP0                ;[26]+3 Store P0(0)
               lda GFXbuffer+3         ;[29]+3 Load  P1(0)
               sta GRP1                ;[32]+3 Store P1(0)            
               ;***2 Cyc.left of HB, TIME TO DRAW!***            
               ;***Wait for P0(0) to draw***
               ;Update P0 2 More times
               lda GFXbuffer+1         ;[35]+3 Load P0(1)
               sta GRP0                ;[38]+3 Draw P0(1)            
               lda GFXbuffer+2         ;[41]+3 Load P0(2)
               sta GRP0                ;[44]+3 DRAW P0(2)
               stx.w GRP0              ;[47]+4 Clear GRP0           
               ;***Wait for P1(0) to draw***
               ;Update P1 2 More times
               lda GFXbuffer+4         ;[51]+3 Load P1(1)            
               sta GRP1                ;[54]+3 Draw P1(1)
               lda GFXbuffer+5         ;[57]+3 Load P1(2)
               sta GRP1                ;[60]+3 Draw P1(2)
               ;***FINISHED DRAWING***                
               stx.w GRP1              ;[63]+4   ;Clear GRP1


  3. Correction to the cycle times on Frame2, they were off 2 cycles and causing the video to skew a bit.

    ;*************
    ;* [FRAME 2/4]
    ;*************
    FRAME2:     sta WSYNC               ;[]+3     ;-PixelPos [-68], Color clock [0]
               dey                     ;[0]+2    ;Decrement scanline and compare to #0
               bne .doDraw2            ;[2]+2/3  ;If more scanlines left, branch
               jmp OVERSCAN            ;[]+3     ;EXIT PLAYFIELD KERNAL
               ;***CYCLE EXACT DRAW KERNAL*** 
    .doDraw2    sleep 17                ;[5]+17   ;Cycle padding         
               ;***Preload P0(0) and P1(0)
               lda #<DF2DATA           ;[22]+2 Load  P0(0) 
               sta.w GRP0              ;[24]+4 Store P0(0)
               lda #<DF2DATA           ;[28]+2 Load  P1(0) 
               sta.w GRP1              ;[30]+4 Store P1(0)       
               ;***TIME TO DRAW!         
               ;***Waiting for P0(0) to draw
               ;***Update P0 2 More times
               lda #<DF2DATA           ;[34]+2 Load P0(1)  
               sta.w GRP0              ;[36]+4 Draw P0(1)             
               lda #<DF2DATA           ;[40]+2 Load P0(2) 
               sta.w GRP0              ;[42]+4 Draw P0(2)  
               sleep 4                 ;[46]+4 Padding    
               ;***Waiting for P1(0) to draw
               ;***Update P1 2 More times
               lda #<DF2DATA           ;[50]+2 Load P1(1)        
               sta.w GRP1              ;[52]+4 Draw P1(1) 
               lda #<DF2DATA           ;[56]+2 Load P1(2)  
               sta.w GRP1              ;[58]+4 Draw P1(2)      
               ;***END DRAW***            
               jmp FRAME2              ;[62]+3 ;Will WSYNC after jump  

     

    Notice how "TESTING12345" is "TEING1ST2345"


  4. Indeed I will, once I get it working :P

     

    I'm completely stumped, it's not fetching the data correctly after all :( I'm not sure why so I'll post it here for you all to look at.

    It should display "TESTING12345" on the screen, but it fetches the data in the wrong order.

    I stripped it down to bare bones for less confusion.

     

    It should split the test pattern into 2 ScreenRAM banks for drawing between 2 frames. I'm trying to take advantage of the Data Fetchers self advancing pointer to parse the entire set of data.

     

    If you have any questions about what it going on let me know, and I'll do my best to explain it.

     

    Also don't go stealing my kernal implementation because it's just so amazing okay :D

    But if you want to help me make it better, then by all means let me know how I can improve it!

    DPCtest.zip


  5. I see, works fine now. Thank you again.

    [edit] Also forgot the #< for DF0DATA as well :) the code I post is used for example and not what I am actually using right now. It's always changing so don't bother posting improvements to it. Just in case some of you wanted to.


  6. New problem, most likely an oversight as I've been coding all day.

    FillScreenRAM:
               ;***Set Data Fetcher 0 to TitleScreen***
               lda #<TitleScreen       ;Bank5
               sta DF0LOW
               lda #>TitleScreen
               sta DF0HI
               ;***Set Data Fetchers 1,2 to ScreenRAM***
               lda #<ScreenRAM1        ;Bank6
               sta DF1LOW
               lda #>ScreenRAM1
               sta DF1HI
               lda #<ScreenRAM2        ;Bank6
               sta DF2LOW
               lda #>ScreenRAM2
               sta DF2HI
               lda #$0                 ;Enable FastFetch
               sta FASTFETCH           ;-
               ;***Start ScreenRAM fill***
               ldx #11                 ;Load 2304 bytes total
    .fillRAM    ldy #$E8                ;-230 bytes * 10 blocks of data
    .fillRAMa   lda DF0DATA             ;Load byte from DF0
               sta DF2WRITE            ;Store in DF2
               dey                     ;Next byte counter
               lda DF0DATA             ;Load next byte from DF0
               sta DF1WRITE            ;Store in DF1
               dey                     ;Next byte counter
               bne .fillRAMa           ;repeat
               dex                     ;Next data block
               bne .fillRAM            ;repeat
               ;***Done***
               lda #$FF                ;Disable FastFetch mode
               sta FASTFETCH           ;-
               rts                     ;Return
    

    I am tying to transfer in a 2304-byte block of data from bank 5 into the ScreenRAM buffers:

    ;--------------------------------------------------------------------------------------------------
    ;*********************
    ; [sTART OF BANK 5]
    ;*********************
     ORG  $5000                        ;Relocatable ORG address
     RORG $1000                        ;-
     JUMP_TABLE                        ;Required Jump table for bank switching
    ;********************
    Bank5Code:
    
    TitleScreen: ;Placeholder for code testing right now
     ;***[2304 bytes]***
     REPEAT 2304
     .byte #$FF
     REPEND
    ;********************
     ORG  $5FF6                        ;Relocatable ORG address
     RORG $1FF6                        ;-
     BANKS_AND_VECTORS                 ;Required Jump table for bank switching
    ;/////////////////////
    ;---[END OF BANK 5]---
    ;/////////////////////
    
    ;********************************
    ;   [*GRAPHICS ONLY* BANK 6]
    ;********************************
     ORG $6000
     RORG $0000
     
    ScreenRAM1 ds 1152
    ScreenRAM2 ds 1152
    
     ds ($1400 - *)
    

     

    Yet it never fetches the data and returns all #$00's instead of #$FF

     

    What did I miss this time?


  7. Nevermind I fixed it, thank you.

    ;*************
    ;* [FRAME 1/2]
    ;*************
    FRAME1:     sta WSYNC               ;[]+3   ;-PixelPos [-68], Color clock [0]
               dey                     ;[0]+2    ;Decrement scanline and compare to #0
               bne .doDraw1            ;[2]+2/3  ;If more scanlines left, branch
               lda #$FF                ;[]+2     ;Disable FastFetch mode        
               sta FASTFETCH           ;[]+4     ;-
               jmp OVERSCAN            ;[]+3     ;EXIT PLAYFIELD KERNAL
               ;***CYCLE EXACT DRAW KERNAL*** 
    .doDraw1    sleep 14                ;[5]+14   ;Cycle padding         
               ;***Preload P0(0) and P1(0)
               lda #<DF0DATA           ;[19]+2 Load  P0(0) ;[18] <-Cycles we need to be at
               sta.w GRP0              ;[21]+4 Store P0(0) ;[21]
               lda #<DF0DATA           ;[25]+2 Load  P1(0) ;[24]
               sta.w GRP1              ;[27]+4 Store P1(0) ;[27]      
               ;***TIME TO DRAW!         
               ;***Waiting for P0(0) to draw
               ;***Update P0 2 More times
               lda #<DF0DATA           ;[31]+2 Load P0(1)  ;[30]
               sta.w GRP0              ;[33]+4 Draw P0(1)  ;[33]            
               lda #<DF0DATA           ;[37]+2 Load P0(2)  ;[36]
               sta.w GRP0              ;[39]+4 Draw P0(2)  ;[39]
               sleep 4                 ;[43]+4 Padding     ;[42]
               ;***Waiting for P1(0) to draw
               ;***Update P1 2 More times
               lda #<DF0DATA           ;[47]+2 Load P1(1)  ;[46]      
               sta.w GRP1              ;[49]+4 Draw P1(1)  ;[49]
               lda #<DF0DATA           ;[53]+2 Load P1(2)  ;[52]
               sta.w GRP1              ;[55]+4 Draw P1(2)  ;[55]    
               ;***END DRAW***            
               jmp FRAME1              ;[]+3 ;Will WSYNC after jump
    

    [edit] Corrected the timing. "Slaps forehead"

    Why didnt I just adjust my initial sleep delay 1 cycle to begin with.


  8. Can I get "lDA #<DF0DATA" to take 3 cycles to execute instead of 2?

     

    I've got some cycle exact display timing going on and being 1 cycle off makes things look messy. I don't have the luxury of adjusting the timing elsewhere. The loads have to be 3 cycles :( and I really want to use the DPC+ as a display output buffer. It's so much nicer this way :D

     

    If not, then much sadness on my end.


  9. Always appreciate the info.

     

    What is the proper method for padding out each bank?

    I've tried doing a "ds ($1000 - *)" in each bank after the code segment before the vector table but dasm just sits there churning out a huge file.

     

    I've looked at the example project and not sure why this wouldn't work the same. Might be incorrect addressing of *? each bank is RORG to $F000.

     

    ;**********************************************************
    ;--------------------
    ;---[sTART BANK 5]--- 
    ;--------------------
     ORG  $5000  
     RORG $F000
     JUMP_TABLE
    Bank5Code:
    ;********************
     BASIC_KERNAL  ;MACRO  
     ;Pad remaining bank space
     ds ($0FF6 - *) ;Refuses to work here...
    ;********************
     ORG  $5FF6
     RORG $FFF6
     BANKS_AND_VECTORS 
    ;---------------------
    ;---[END OF BANK 5]--- 
    ;---------------------
    
    ;********************************
    ;   [*GRAPHICS ONLY* BANK 6]
    ;********************************
     ORG  $6000
     RORG $0000
     
    ,[...] Graphic data ect
    
     ds ($1000 - *) ;Works fine here
    

     

    I use INCBIN at the head of the file to attach the DPCplus.arm code stub, so the rest "should" pad to the correct 32k size.


  10. I enjoy the challenge it poses to programmers. The limitations of the console cause one to think outside the box in order to perform the simplest of things.

    Because of this, the reward of creating a fully working title is something to be VERY proud of and says allot about the hardships the original developers faced.

    I tip my hat to every person whose managed to created a published product.

    batariBasic doesn't count, that's cheating :D (Well...not really but it's far simpler to use than ASM)

     

    My appeal is academic. I have some nostalgia from having one when I was little, but I only enjoy a handful of games on it. Most Activision titles are amazing programming feats and really show what the console can do, back when Activision was a cool company. Most known programing tricks for this console were taken from Activision titles! so I second the recommendation to check them out.

    • Like 1

  11. Does Stella correctly reflect the cycle times when FastFetch mode is enabled? It should read 2 cycles for any LDA instruction from DPC registers such as:

     

    lda DF0DATA, however it still shows 4 cycles so I assume it was never updated to reflect this mode? I just want to be sure FastFetch is working properly before I go pushing my kernal to the cycle maximums.


  12. Okay here is the Rotate byte routine:

    ;********************************
    ;     [ROTATE ROUTINES]
    ;********************************
    RotateBytes:
       lda #>Ror1              ;[]+3 Save high byte
       sta GENpoint+1          ;[]+3 Store in general pointer    
       ldy P0shift             ;[]+3 Load amount to rotate
       lda ROtableJmp,Y        ;[]+4 Use shift as index
       sta GENpoint            ;[]+3 Ready for jmp
       ldx #15                 ;[]+2 Use counter as byte index
    .RORa
       lda P0buffer,X          ;[]+4 Load Sprite byte to be rotated
       jmp (GENpoint)          ;[]+5 Engage!
       
       ;Will have always branched by now, no need for further checks
    Ror4:
       lsr                     ;[]+2
       bcc *+4                 ;[]+2/3
       ora #$80                ;[]+2
    Ror3:
       lsr                     ;[]+2
       bcc *+4                 ;[]+2/3
       ora #$80                ;[]+2
    Ror2:
       lsr                     ;[]+2
       bcc *+4                 ;[]+2/3
       ora #$80                ;[]+2
    Ror1:
       lsr                     ;[]+2
       bcc *+4                 ;[]+2/3
       ora #$80                ;[]+2
       jmp .RotCont            ;[]+3
    Rol5:
       asl                     ;[]+2
       adc #0                  ;[]+2
    Rol6:
       asl                     ;[]+2
       adc #0                  ;[]+2
    Rol7:
       asl                     ;[]+2
       adc #0                  ;[]+2 
    .RotCont
       sta P0buffer,X          ;[]+4 Store Result into 16-byte SPRITE buffer
       dex                     ;[]+2 Decrement counter
       bpl .RORa               ;[]+2/3 Branch if more bytes to rotate
       rts
    
    ROtableJmp:
       .byte <.RORa, <Ror1, <Ror2, <Ror3, <Ror4, <Rol5, <Rol6, <Rol7  

     

    I haven't traced out the best/worst case scenarios for this yet, so it may be slower/same/faster.

    Just wanted to show that I am taking what was posted and learning from it.

     

    Thanks again guys as always!

     

    Here is a demo of it in action, nothing special just a 8x16 sprite you can move around of my guy with a sword.

    White color is drawn on Frame1

    Red is drawn on Frame2

     

    96x96 software controlled pixel playfield.

    SpriteTest.bin


  13. Thanks for the advice, I think I got it now thanks to your ideas:

    P0slot = 0 through 11

    FrameNum = 0 or 1 for Frame1 and Frame2

    ;********************************
    ;     [MASKING ROUTINE]
    ;********************************
    MaskData:
       ldy P0shift             ;[]+3 Load player shift amount
       ldx MaskTable,Y         ;[]+4 Load mask into X
       ldy #15                 ;[]+2 Y will be our counter for 16-bytes 
       ;********************************
       ;Choose from 4 scenarios
       ;Slot / Frame
       ;0/0 = 0 .F1SE    
       ;0/1 = 1 .F1SO (no inc slot)
       ;1/0 = 1 .F1SO = Inc P0slot
       ;1/1 = 0 .F1SE
       ;********************************
       lda P0slot              ;[]+3 Load player GFXslot number
       and #1                  ;[]+2 Clear all but bit 0
       eor FrameNum            ;[]+3 Will result in truth table above    
       beq .doMask             ;[]+2/3 Scenarios 1 and 4
       ;In scenario 2 or 3 so invert mask
       txa                     ;[]+2
       eor #$FF                ;[]+2
       tax                     ;[]+2     
       lda FrameNum            ;[]+3 Test Scenario 2 or 3
       bne .doMask             ;[]+2/3 FrameNum = 1 = Scenario 2
       inc P0slot              ;[]+5 Scenario 3, INC P0slot
       
    ;[MASK BYTES]
    .doMask              
       lda P0buffer,Y          ;[]+4
       sax P0buffer,Y          ;[]+4
       dey                     ;[]+2
       bpl .doMask             ;[]+2/3
       rts                     ;[]+6
    
    ;********************************
    ;     [TABLES]
    ;********************************    
    MaskTable:
          ;$00,$01,$02,$03,$04,$05,$06,$07
     .byte $FF,$7F,$3F,$1F,$0F,$07,$03,$01 
    

     

    What do you think? Greatly simplified from my initial posting Or did I miss something from your ideas?

     

    I am still understanding the rotate method Thomas posted, I think I've come up with a faster way to do them, but I'll see once I complete it.


  14. Has no intersecting lines, nor right angles?

     

    [edit] In that case then "Has both direct and indirect addressing modes"

    But I can't think of an way to explain both this and what direct and indirect modes do at the same time.

     

    Direct addressing grabs a value straight from the address.

    Indirect grabs the address from the address...then the value

     

    lda Number     = Number is a memory address which holds (5)
    lda Number,Y   = Address of Number+Y (Y = 0-255) and returns value stored at Number+Y
    lda (Number)   = Number holds an address not a direct value, so it returns an address which points to the value.
    lda (Number),Y = Same as above but returns (Address) then Number+Y

     

    Hmmm, going from memory here so I might have gotten this wrong :P


  15. That reply I made then quickly fixed would be the typo :) I should proof before I hit reply. Sorry to confuse! It should be anded with decimal 10 or HEX (A).

     

    For the first 16 values of FrameNum ie 0-15,

    if you and with decimal 10 you take the beq branch when

    FrameNum 0,1,4,5 the rest fall thru and that repeats

    for every subsequent 16 values. That doesn't look like

    odd frames to me except for the first 8 ie 0-7

    The odd frames fall thru.

    FrameNum only counts 4 frames, 0,2,4,6 that was it then I reset it to 0.

     

    So worry not anymore about my Frame counter, all it does is index a jump later to the correct frame kernal, which is aligned to the position offsets of P0 and P1 for drawing in the Pixel slots. You can safely disregard its use in the Masking routines.

×
×
  • Create New...