Jump to content
IGNORED

Session 14: Playfield Wierdness


Recommended Posts

http://www.6502.org/tutorials/6502opcodes.htm


ROL (ROtate Left) 



Affects Flags: S Z C 



MODE           SYNTAX       HEX LEN TIM

Accumulator   ROL A         $2A  1   2

Zero Page     ROL $44       $26  2   5

Zero Page,X   ROL $44,X     $36  2   6

Absolute      ROL $4400     $2E  3   6

Absolute,X    ROL $4400,X   $3E  3   7

:D

Link to comment
Share on other sites

dew2050 wrote:

 CLC

ROL PATTERN_RIGHT

ROL PATTERN_LEFT

BCC SCROLLCOMPLETE



INC PATTERN_RIGHT 



SCROLLCOMPLETE

Nearly perfect! :thumbsup:

 

If you replace the first ROL with ASL then you can remove the CLC. ;)

 

I have a newbie assembler question: How many machine cycles does the ROL commands above take? Is it 5 for zero page?

Yup, excatly.

Link to comment
Share on other sites

Settle down dew :P

It depends how you initialized it.

TEMP_VAR = $80 (Zero page)

or  

TEMP_VAR = $8000 (Absolute)

 

Now that's more helpful. Thanks.

 

If you replace the first ROL with ASL then you can remove the CLC.

 

So ASL sets the carry even if the dropped bit is 0? These subtle nuances are so interesting (programming-wise). Thanks Thomas. It's a lot more clear now.

Link to comment
Share on other sites

So ASL sets the carry even if the dropped bit is 0? These subtle nuances are so interesting (programming-wise). Thanks Thomas. It's a lot more clear now.

 

ASL sets the carry flag only if the high bit (bit 7) was a 1 prior to the shift.

If bit 7 was a 0 prior to the ASL, then the operation clears the carry flag.

 

 

+-+-+-+-+-+-+-+-+

C <- |7|6|5|4|3|2|1|0| <- 0 ASL

+-+-+-+-+-+-+-+-+

 

 

Ben

Link to comment
Share on other sites

This might be a stupid question, but does altering the number of scanlines affect the number of FPS displayed?  Seems to me that if you went with, say, 280 scanlines (keeping 192 for the picture), that the FPS would drop below 60.

Yup, exactly!

 

You can calculate that quite easily:

Artillery Duel: 60/241*262 = ~65Hz

Demon Falcon: 60/280*262 = ~56Hz

PAL games: 60/312*262 = ~50Hz

 

:?: What the advantage of displaying less frames per second? Does this free up more CPU time for other parts of the program?

 

Thanks.

Link to comment
Share on other sites

This might be a stupid question, but does altering the number of scanlines affect the number of FPS displayed?  Seems to me that if you went with, say, 280 scanlines (keeping 192 for the picture), that the FPS would drop below 60.

Yup, exactly!

 

You can calculate that quite easily:

Artillery Duel: 60/241*262 = ~65Hz

Demon Falcon: 60/280*262 = ~56Hz

PAL games: 60/312*262 = ~50Hz

 

:?: What the advantage of displaying less frames per second? Does this free up more CPU time for other parts of the program?

 

Thanks.

 

:!: May have answered my own question. Does this give the CPU more time to create a more advanced display?

Link to comment
Share on other sites

Does this give the CPU more time to create a more advanced display?

Not really, since the time per scanline is still 76 cycles. But it gives you the chance of a taller display and more offscreen calculation time. The latter is important when your game is getting more and more complicated.

 

Remember all calculations (e.g. moving objects, reading joysticks, checking collisons, awarding points, sound... and last not least: preparing data for the display kernel) have to be done offscreen, since during the display kernel, the CPU is normally 100% busy with drawing something.

Link to comment
Share on other sites

Remember all calculations (e.g. moving objects, reading joysticks, checking collisons, awarding points, sound... and last not least: preparing data for the display kernel) have to be done offscreen, since during the display kernel, the CPU is normally 100% busy with drawing something.

 

This might seem trivial but I've been wondering about this for *ages*. As a newbie it's still hard to look at a disassembled game and figure this out on my own. And when coding my own little 'hello world' type stuff I couldn't stop thinking "jeez, it's taking me a lot of time here just to draw my playfield and player graphics - how am I gonna do anything else?"

 

You 'da man Thomas :)

Link to comment
Share on other sites

  • 3 months later...
3.  Write some solid shape(s) to PF0, PF1, PF2 (ie:  lda #%01011110, sta PF0, sta PF1, sta PF2) and then play with changing the playfield colour several times during a scanline.  How many colour changes (maximum) do you think you can get on any line?  Why is there a limit?

 


StartOfFrame



  ; Start of new frame - VBLANK is still ON



               lda #2

               sta VSYNC



               sta WSYNC

               sta WSYNC

               sta WSYNC               ; 3 scanlines of VSYNC signal



      ;------------------------------------------------

      ; 37 scanlines of vertical blank...



               ldx #0     ; Tuning off VSYNC

               stx VSYNC



VerticalBlank   sta WSYNC

               inx                ; 2

               cpx #37            ; 2

               bne VerticalBlank  ; 2



      ;------------------------------------------------

      ; Do 192 scanlines - Begin of the 1st line



               ldx #0     ; 2 this counts our scanline number

               stx VBLANK ; 3 and this turns VBLANK off





Picture         sta WSYNC



               SLEEP 16   ; H blank - any change here would not be seen



               lda #$0F   ; 2

               sta COLUPF ; 3  = 21



               adc #$10   ; 2

               sta COLUPF ; 3  = 26



               adc #$10   ; 2

               sta COLUPF ; 3  = 31



               adc #$10   ; 2

               sta COLUPF ; 3  = 36



               adc #$10   ; 2

               sta COLUPF ; 3  = 41



               adc #$10   ; 2

               sta COLUPF ; 3  = 46



               adc #$10   ; 2

               sta COLUPF ; 3  = 51



               adc #$10   ; 2

               sta COLUPF ; 3  = 56



               adc #$10   ; 2

               sta COLUPF ; 3  = 61



               adc #$10   ; 2

               sta COLUPF ; 3  = 66



               inx        ; 2

               cpx #192   ; 2

               bne Picture; 3

              ;sta WSYNC ; 3  = 76





      ;------------------------------------------------

      ; 30 scanlines of overscan...



               sta WSYNC ; 3  = 75



               lda #%01000010

               sta VBLANK          ; end of screen - enter blanking



               ldx #0

               stx COLUPF





Overscan        sta WSYNC

               inx

               cpx #29

               bne Overscan





               jmp StartOfFrame

 

Thats 9 different playfield colours per scanline. If I add 1 more adc/sta pair, the screens gets really screwed up. I know a loop would be a LOT more elegant, but i would waste precious cycles with it, and would get no extra colors.

 

As for the actual theorical limit... humm, lets see:

 

- we have 76 cpu cycles

 

- theres no reason to change color while in horizontal blank, because new colour would not be visible. So, all we can do in the first 22 cycles is to set a colour for free and wait till it comes visible.

 

- For the remaining 76 - 22 = 58 cycles, 10 are used for housekeeping and loop maintance (inx, cpx, bne and sta wsync). Yes, i know that experienced programmers use less then 10 cycles, but as im not a Jedi Master (yet), I'll use 10 for my math. So we actually have 58 - 10 = 48 cycles to change colour like crazy.

 

- As far as I know, you cant change playfield colour in less then 5 cycles. 2 to set the desired colour (either by inx, iny, adc, whatever) + 3 to store that colour in COLUBK register

 

- 48 remaining cycles / 5 cycles per colour change = 9.6 Rouding down, thats 9 color changes

 

So, we have 1 initial colour + 9 changes = 10 different colors per scanline at most. Correct?

 

A Jedi Master that could reduce the loop maintenance to 8 cycles would achieve 11 colors, but thats as good as it gets.

 

Isnt it?

 

PS: Why the hell my 1st scanline is screwed up after the first color change?

post-4052-1063611927_thumb.jpg

Link to comment
Share on other sites

  • 6 months later...

Woah, nobody's posted here in a long time.

 

Anyway, I have an idea for a program. How about a simple utility that allows you to draw 20 pixels of a playfield (and lets you see the other half mirrored or normal) and then gives you the values of PF0 PF1 and PF2? It would probably be pretty simple to make, and I can see it being a very useful tool for newbies (like me!). Figuring out how to make the playfield look the way you want is a pain in the butt.

Link to comment
Share on other sites

  • 3 years later...

Man...now we are getting into some wierd stuff. I was editing my code to do the background solid colors and the bars in rainbow (dubbed kernel reversed). After compiling and running the code...i only got the rainbow on the left side of the screen and I don't know what I did...

 
 

processor 6502

include "vcs.h"

include "macro.h"

;---------------------------------------------------------------

PATTERN = $80
TIMETOCHANGE = 20

;----------------------------------------------------------------


SEG

ORG $F000



Reset

;Clear RAM and all TIA registers

ldx #0
lda #0
Clear sta 0,x
inx
bne Clear

;----------------------------------------------------------------

; Once-only initialization

lda #0
sta PATTERN

lda #$45
sta COLUPF

ldy #0

;----------------------------------------------------------------



StartOfFrame



; Start of vertical blank processing



lda #0

sta VBLANK



lda #2

sta VSYNC



sta WSYNC

sta WSYNC

sta WSYNC ; 3 scanlines of VSYNC signal



lda #0

sta VSYNC



; 37 scanlines of vertical blank...

ldx #0

VerticalBlank sta WSYNC

inx

cpx #37

bne VerticalBlank

;--------------------------------------------------------------------

;Handle a change in the pattern once every 20 frames
;and write the pattern to the PF1 register

iny

cpy #TIMETOCHANGE

bne notyet

ldy #0

inc PATTERN

notyet

lda PATTERN

sta PF0
sta PF1

;--------------------------------------------------------------------



;--------------------------------------------------------------------

; 192 scanlines of picture...



ldx #$45
stx COLUBK

ldx #0


Picture stx COLUPF

SLEEP 40

lda #$45

sta COLUPF

sta WSYNC

inx

cpx #242

bne Picture


;-------------------------------------------------------------------

lda #%01000010

sta VBLANK ; end of screen - enter blanking



; 30 scanlines of overscan...

ldx #0

Overscan sta WSYNC

inx

cpx #30

bne Overscan



jmp StartOfFrame





ORG $FFFA



.word Reset ; NMI

.word Reset ; RESET

.word Reset ; IRQ



END

 

Help me understand what I did?

post-18904-1206530798_thumb.png

Link to comment
Share on other sites

  • 6 years later...

man this stuff is rock hard, and even when it works it only just works! I am trying to work out the playfield scrolling - I know this won't work as is, but I can;t even get this to work. So it just rol's the PF0 register every 20 frames - but it only works once, the second time it seems to skip it and nothing happens. What is wrong with this code - it seems like it should be simple but it only rols the first time and not again, it just sits there

(ScrollTimer = $80)
(PF0 = 160 decimal)

           ; 36 scanlines of vertical blank...
        ; last line for scroll - doesn't work???
        
                    ldx #0
 
VertBlank        sta WSYNC
                    inx
                    cpx #36
                    bne VertBlank
 
        ;-----------------------------------
 
                dec ScrollTimer
                bne NOTYET
                    rol PF0
                    ldx #20
                    stx ScrollTimer
                    
NOTYET        
        
            sta WSYNC

Thanks for any help - the rest just draws the two bars of PF0 down the screen using the counter to make it multi coloured using the code from the last lessons.

Link to comment
Share on other sites

man this stuff is rock hard, and even when it works it only just works! I am trying to work out the playfield scrolling - I know this won't work as is, but I can;t even get this to work. So it just rol's the PF0 register every 20 frames - but it only works once, the second time it seems to skip it and nothing happens. What is wrong with this code - it seems like it should be simple but it only rols the first time and not again, it just sits there

(ScrollTimer = $80)
(PF0 = 160 decimal)

           ; 36 scanlines of vertical blank...
        ; last line for scroll - doesn't work???
        
                    ldx #0
 
VertBlank        sta WSYNC
                    inx
                    cpx #36
                    bne VertBlank
 
        ;-----------------------------------
 
                dec ScrollTimer
                bne NOTYET
                    rol PF0
                    ldx #20
                    stx ScrollTimer
                    
NOTYET        
        
            sta WSYNC

Thanks for any help - the rest just draws the two bars of PF0 down the screen using the counter to make it multi coloured using the code from the last lessons.

 

Is PF0 a readable register, or write-only?

Try putting your data in a RAM variable, and copy it from there to PF0.

Also, remember 'rol' uses the carry flag, so whatever is in that will be shifted onto the right hand bit (D0). You may wish to use 'asl' instead.

Link to comment
Share on other sites

Thanks, such a stoopid error lol. I was working on this before but ended up working in a kitchen all the hours god sends (I am not an IT person unfortunately) so was too tired to carry on, but am working more normally now so am back on it. Will plough on slowly. I have done some Java in the past and this makes Java seem like childs play! I have also changed to ubuntu and am trying to learn a bit of c - the syntax is ok for me, as it is very similar to Java, but I keep wanting to write objects!

 

Edit - why does it say Dr.Boo under your username?

Edited by marienbad
Link to comment
Share on other sites

Yeah the whole read only and write only registers take a bit to get used to - especially once you learn that they can share the same addresses :o . The write only address of PF0 is the same as the read only address of INPT5 (right joystick's fire button).

 

Dr. Boo is what Andrew put in his Custom Status field. Mine's Medieval Mayhem, for my first 2600 game.

 

In the top-right corner of the site you'll see your alias. Click it to reveal a drop-down menu. Select My Settings.

post-3056-0-24197100-1422299575_thumb.png

 

Scroll down to the bottom where you'll find Custom Status.

post-3056-0-85620000-1422299581_thumb.png

Link to comment
Share on other sites

ok, I almost got it!! It scrolls but it isn't quite right. I have PF0/1/2 Pattern and then I asl/lsr them and save the carry in PF0/1/2_temp, then add them (PF0_temp to PF2_Pattern, etc). It scrolls but is not right. sorry for being a pain and total n00b. Anyway, this is what I got:

 

processor 6502

include "vcs.h"
include "macro.h"

;------------------------------------------------------------------------------
; variables and memory stuff

ScrollTimer = $80
PF0_Pattern = $81
PF1_Pattern = $82
PF2_Pattern = $83

PF0_temp = $84
PF1_temp = $85
PF2_temp = $86

;------------------------------------------------------------------------------

SEG

ORG $F000

Reset

; Clear RAM and all TIA registers

ldx #0
lda #0
Clear sta 0,x
inx
bne Clear

;--------------------------------------------

; Once-only initialisation...


lda #%10100101
sta PF0_Pattern
sta PF1_Pattern
sta PF2_Pattern
sta PF0
sta PF1
sta PF2

lda #46
sta COLUPF
lda #20
sta ScrollTimer

;------------------------------------------------

StartOfFrame

; Start of new frame

; Start of vertical blank processing

lda #0
sta VBLANK

lda #2
sta VSYNC

sta WSYNC
sta WSYNC
sta WSYNC ; 3 scanlines of VSYNC signal

lda #0
sta VSYNC

;------------------------------------------------

; 35 scanlines of vertical blank...

ldx #0

VertBlank sta WSYNC
inx
cpx #35
bne VertBlank

;-----------------------------------

dec ScrollTimer
bne NoScroll
asl PF0_Pattern
bcc PF0_zero
lda #128
sta PF0_temp
jmp PF1_scroll

PF0_zero lda #0
sta PF0_temp

PF1_scroll lsr PF1_Pattern
bcc PF1_zero
lda #1
sta PF1_temp
jmp PF2_scroll

PF1_zero lda #0
sta PF1_temp

PF2_scroll asl PF2_Pattern
bcc PF2_zero
lda #128
sta PF2_temp
jmp Additions

PF2_zero lda #0
sta PF2_temp

Additions lda PF2_Pattern
adc PF0_temp
sta PF2_Pattern
sta PF2

lda PF1_Pattern
adc PF2_temp
sta PF1_Pattern
sta PF1

lda PF0_Pattern
adc PF1_temp
sta PF0_Pattern
sta PF0

ldx #20
stx ScrollTimer

NoScroll sta WSYNC

Picture

ldy #192 ; 192 scanlines of picture...

.loop:

dey

sty COLUPF


sta WSYNC


bne .loop ; loop until Y == 0

;------------------------------------------------

lda #%01000010
sta VBLANK ; end of screen - enter blanking

; 30 scanlines of overscan...

ldx #0
Overscan sta WSYNC
inx
cpx #30
bne Overscan

jmp StartOfFrame


;------------------------------------------------------------------------------


ORG $FFFA

;InterruptVectors

.word Reset ; NMI
.word Reset ; RESET
.word Reset ; IRQ

END

 

 

(I also looked at some stuff I did last time and was trying to make a rasterbar type thing moving up and down changing BKColour. It works but there is an extra bit on the bottom left, where am I going wrong with this code - again sorry for being a n00b:

 

processor 6502

include "vcs.h"
include "macro.h"

;------------------------------------------------------------------------------
; variables and memory stuff


;------------------------------------------------------------------------------

SEG

ORG $F000

TopLimit = $80
BaseLimit = $81

TopLine = $82
BaseLine = $83

NewColor = $84
OldColor = $85
Direction = $86

SineCounter = $87
LineCounter = $88


Reset

; Clear RAM and all TIA registers

ldx #0
lda #0
Clear sta 0,x
inx
bne Clear

;--------------------------------------------

; Once-only initialisation...

lda #00
sta COLUBK
sta OldColor
sta Direction

lda #$0E
sta NewColor

lda #50
sta TopLimit
lda #150
sta BaseLimit

lda #60
sta TopLine

lda #80
sta BaseLine

lda #9
sta SineCounter

lda #8
sta LineCounter

;------------------------------------------------

StartOfFrame

; Start of new frame

; Start of vertical blank processing



lda #0
sta VBLANK

lda #2
sta VSYNC

sta WSYNC
sta WSYNC
sta WSYNC ; 3 scanlines of VSYNC signal

lda #0
sta VSYNC

;------------------------------------------------

; 37 scanlines of vertical blank...



ldx #0


VerticalBlank sta WSYNC
inx
cpx #37
bne VerticalBlank

;-----------------------------------

ldx #0

Picture
cpx TopLine
bne not_top
lda NewColor
sta COLUBK

not_top cpx BaseLine
bne nochange
lda OldColor
sta COLUBK

nochange sta WSYNC
inx
cpx #192
bne Picture

;------------------------------------------------

lda #%01000010
sta VBLANK ; end of screen - enter blanking

; 30 scanlines of overscan...


up lda Direction
bne down
dec TopLine
dec BaseLine

lda TopLine
cmp TopLimit
bne done
lda #1
sta Direction

down inc TopLine
inc BaseLine

lda BaseLine
cmp BaseLimit
bne done
lda #0
sta Direction


done ldx #0
Overscan sta WSYNC
inx
cpx #29
bne Overscan

jmp StartOfFrame


;------------------------------------------------------------------------------


;------------------------------------------------------------------------------

ORG $FC00

Sines
.byte 0
.byte 1
.byte 3
.byte 4
.byte 6
.byte 7
.byte 8
.byte 9
.byte 10
.byte 10


ORG $FFFA

;InterruptVectors

.word Reset ; NMI
.word Reset ; RESET
.word Reset ; IRQ

END

 

)

 

finally - am I thinking about this in the right way, if that makes sense?)

Link to comment
Share on other sites

  • 2 weeks later...

ok, I almost got it!! It scrolls but it isn't quite right. I have PF0/1/2 Pattern and then I asl/lsr them and save the carry in PF0/1/2_temp, then add them (PF0_temp to PF2_Pattern, etc).

No need to use temps...carry status can be used directly (i.e. pushing it onto the left or right bit positions of your pattern variables):

 

 

Scroll_Left:
      lsr    PF2_Pattern ;D0 -> carry, D7 blank
      rol    PF1_Pattern ;carry -> D0, D7 -> carry
      ror    PF0_Pattern ;carry -> D7
;lower 4 bits of PF0 unused...so check D3 for
;the scrolled bit
      lda    PF0_Pattern
      and    #$08 ;bit D3
      beq    No_Left_Bit ;branch if nothing
      lda    PF2_Pattern
      ora    #$80 ;otherwise, update D7 of PF2
      sta    PF2_Pattern
No_Left_Bit:
      lda    PF0_Pattern
      jmp    Done_Scrolling
 
Scroll_Right:
      asl    PF0_Pattern ;D7 -> carry
      ror    PF1_Pattern ;carry -> D7, D0 -> carry
      rol    PF2_Pattern ;carry -> D0, D7 -> carry
      lda    PF0_Pattern
      bcc    Done_Scrolling ;branch if no carry from above rol
      ora    #$10 ;otherwise, update D4 of PF0
Done_Scrolling
;tidy up PF0 pattern for next time
      and    #$F0 ;keep only the upper 4 bits
      sta    PF0_Pattern

 

This method was lifted from Defender's cityscape code. If you want to do fullscreen asymmetrical, you need to double the number of variables that you rol/ror bits to.

Link to comment
Share on other sites

  • 4 years later...

So after some research, my idea for the scrolling is to use ROL.  However, ROL A is listed as a legitimate command, yet the assembler flags it as illegal? What am I missing?  EDIT: looking at some of the older posts here, I see others also use ROL, but directly on the pattern variable.  At this point I'm just wondering why the examples elsewhere (like ROL A) are so different and don't appear to work with dasm.

 

--- Unresolved Symbol List
A                        0000 ????         (R )

 

Code here:

  iny      
	
                cpy #TIMETOCHANGE      ; has it reached our "change point"?

                bne notyet             ; no, so branch past
				lda PATTERN
				ROL A

 

Edited by SavedByZero
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...