6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 5:38 pm

All times are UTC




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sat Aug 03, 2024 6:31 am 
Offline

Joined: Sat Aug 03, 2024 6:24 am
Posts: 8
I am new to 6502 programming. I wanted to make a game using this assembly language. My first program fills the whole display with white pixels.
Code:
Code:
ldx #$ff
lda #$01
drawPixel:
    dex
    cpx #$00
    sta $0200,x
    sta $0300,x
    sta $0400,x
    sta $0500,x
    bne drawPixel
    brk

However it is not doing it correctly. It stops before the last pixel so it doesn't fill some pixels. How do I make it fill every single pixel?


Attachments:
File comment: Result
IMG_20240803_122709.jpg
IMG_20240803_122709.jpg [ 8.51 KiB | Viewed 1345 times ]
Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 7:06 am 
Offline

Joined: Tue Sep 03, 2002 12:58 pm
Posts: 336
Can you see why your code doesn't work? It's worth spending a little time walking through it yourself instruction by instruction to see exactly what it's doing, and think about how that differs from what you expected.

Spoilers below:

I assume you have a 32x32 display, with each pixel being represented by one byte in the range $0200 - $05FF. To clear it, you want to write to every byte in this range. You're counting down to 0, which is an idiomatic thing to do on the 6502 as many instructions automatically set the Z flag. So you want the first bytes to be written at $02FF, $03FF, $04FF, and $05FF.

Your code loads X with $FF, which you'd think would be right. But the first thing it does is decrement it, so the first time through the loop it's actually writing to $02FE, $03FE, $04FE, and $05FE. What you want is for X to be $FF after that first decrement. Loading it with $00 will do that.

I said before that many 6502 instructions automatically set the Z flag. DEX is one of them, so you don't need the CPX #$00 after it. It's not wrong to leave it in, but idiomatic 6502 code will omit it. It's worth noting that STA doesn't change the flags, so although separating the branch from the instruction that sets the flag makes me nervous, there's nothing wrong with it.

This code should work:
Code:
ldx #$ff
lda #$00                             ; changed $ff to $00 so the first writes are to $xxff
drawPixel:
    dex
                                          ; removed cpx #$00 as it is redundant
    sta $0200,x
    sta $0300,x
    sta $0400,x
    sta $0500,x
    bne drawPixel
    brk


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 8:25 am 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
An additional comment:

You do an operation that sets the flags, then do some other operations, and only then check the flag.
When you further work with the code, it is easy to forget about that and insert other operations that change the flags. For example, if you want to change the loop to invert the screen, suddenly you have flag changing operations between the dex and the check with beq.
Therefore I recommend keeping the flag change and the check closer together.

Also, John's version already uses the fact that the index registers are 8 bits and overflow after $ff (or underflow to $ff when you decrement them from $00).
Here's my version that uses that fact the other way:

Code:
    LDX #$00
    TXA               ; reuse the value from XR and copy it to AC to clear - saves a byte
L1  STA $0200,X
    STA $0300,X
    STA $0400,X
    STA $0500,X
    INX               ; count from 0 to $ff and overflow to 0 again
    BNE L1            ; loop as long as 0 is not yet reached again
    BRK

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 8:32 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8545
Location: Southern California
To the preceding excellent replies, I will add that if you have a 65c02 (ie, CMOS, not NMOS), you can omit the LDA #0 and use STZ $0200,X (STZ being "STore Zero") in place of STA $0200,X (and $300,X, $400,X, and $500,X).

And, to expand, an automatic compare-to-zero instruction is built into the following 65c02 instructions: LDA, LDX, LDY, INC, INX, INY, DEC, DEX, DEY, INA, DEA, AND, ORA, EOR, ASL, LSR, ROL, ROR, PLA, PLX, PLY, SBC, ADC, TAX, TXA, TAY, TYA, and TSX, reflecting the result of the operation.

The 6502 Primer's programming-tips page has more of this kind of stuff.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 9:18 am 
Offline

Joined: Sat Aug 03, 2024 6:24 am
Posts: 8
John West wrote:
Can you see why your code doesn't work? It's worth spending a little time walking through it yourself instruction by instruction to see exactly what it's doing, and think about how that differs from what you expected.

Spoilers below:

I assume you have a 32x32 display, with each pixel being represented by one byte in the range $0200 - $05FF. To clear it, you want to write to every byte in this range. You're counting down to 0, which is an idiomatic thing to do on the 6502 as many instructions automatically set the Z flag. So you want the first bytes to be written at $02FF, $03FF, $04FF, and $05FF.

Your code loads X with $FF, which you'd think would be right. But the first thing it does is decrement it, so the first time through the loop it's actually writing to $02FE, $03FE, $04FE, and $05FE. What you want is for X to be $FF after that first decrement. Loading it with $00 will do that.

I said before that many 6502 instructions automatically set the Z flag. DEX is one of them, so you don't need the CPX #$00 after it. It's not wrong to leave it in, but idiomatic 6502 code will omit it. It's worth noting that STA doesn't change the flags, so although separating the branch from the instruction that sets the flag makes me nervous, there's nothing wrong with it.

This code should work:
Code:
ldx #$ff
lda #$00                             ; changed $ff to $00 so the first writes are to $xxff
drawPixel:
    dex
                                          ; removed cpx #$00 as it is redundant
    sta $0200,x
    sta $0300,x
    sta $0400,x
    sta $0500,x
    bne drawPixel
    brk


Well first I did check multiple times what happened its just the same result everytime. I did notice that the DEX decrements it and makes it 2FE 3FE... But shifting the position of DEX makes it end before a pixel. Using your code the same result happened it still started after a pixel.


Attachments:
File comment: New result
IMG_20240803_151423.jpg
IMG_20240803_151423.jpg [ 10.28 KiB | Viewed 1321 times ]
Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 9:35 am 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
I think John's code has an issue in that he changed the value of A to $00 instead of X - this should have been changed to $00.

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 9:40 am 
Offline

Joined: Sat Aug 03, 2024 6:24 am
Posts: 8
John West wrote:
Can you see why your code doesn't work? It's worth spending a little time walking through it yourself instruction by instruction to see exactly what it's doing, and think about how that differs from what you expected.

Spoilers below:

I assume you have a 32x32 display, with each pixel being represented by one byte in the range $0200 - $05FF. To clear it, you want to write to every byte in this range. You're counting down to 0, which is an idiomatic thing to do on the 6502 as many instructions automatically set the Z flag. So you want the first bytes to be written at $02FF, $03FF, $04FF, and $05FF.

Your code loads X with $FF, which you'd think would be right. But the first thing it does is decrement it, so the first time through the loop it's actually writing to $02FE, $03FE, $04FE, and $05FE. What you want is for X to be $FF after that first decrement. Loading it with $00 will do that.

I said before that many 6502 instructions automatically set the Z flag. DEX is one of them, so you don't need the CPX #$00 after it. It's not wrong to leave it in, but idiomatic 6502 code will omit it. It's worth noting that STA doesn't change the flags, so although separating the branch from the instruction that sets the flag makes me nervous, there's nothing wrong with it.

This code should work:
Code:
ldx #$ff
lda #$00                             ; changed $ff to $00 so the first writes are to $xxff
drawPixel:
    dex
                                          ; removed cpx #$00 as it is redundant
    sta $0200,x
    sta $0300,x
    sta $0400,x
    sta $0500,x
    bne drawPixel
    brk


Ok I fixed somethings and it's now fixed. Basically your code is almost correct but the problem is that your setting the LDA to $00 instead of LDX I mean the LDA is used for setting the pixel color and setting it to $00 dosent change anything because the position (LDX) is still $ff. I did a idiotic thing trying to count down from $ff so now I fixed it and it now counts from $00. Thank you for your code it works :D .


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 9:41 am 
Offline

Joined: Sat Aug 03, 2024 6:24 am
Posts: 8
fachat wrote:
I think John's code has an issue in that he changed the value of A to $00 instead of X - this should have been changed to $00.

Yes you are correct thanks for telling. I almost forgot that LDX is used for position.


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 9:43 am 
Offline

Joined: Sat Aug 03, 2024 6:24 am
Posts: 8
fachat wrote:
An additional comment:

You do an operation that sets the flags, then do some other operations, and only then check the flag.
When you further work with the code, it is easy to forget about that and insert other operations that change the flags. For example, if you want to change the loop to invert the screen, suddenly you have flag changing operations between the dex and the check with beq.
Therefore I recommend keeping the flag change and the check closer together.

Also, John's version already uses the fact that the index registers are 8 bits and overflow after $ff (or underflow to $ff when you decrement them from $00).
Here's my version that uses that fact the other way:

Code:
    LDX #$00
    TXA               ; reuse the value from XR and copy it to AC to clear - saves a byte
L1  STA $0200,X
    STA $0300,X
    STA $0400,X
    STA $0500,X
    INX               ; count from 0 to $ff and overflow to 0 again
    BNE L1            ; loop as long as 0 is not yet reached again
    BRK


This code has a problem see it is transferring the X value to A. A is used for color so setting the A to 0 (value of X) makes it black and you can't change the color at all. I replaced it with LDA #$01 to make it white and make it so that I can change the color.

But Thank you for your reply it helped and I fixed the code.


Last edited by Nabir14 on Sat Aug 03, 2024 9:47 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 9:45 am 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
Great you managed to fix it! First steps into a new world!

What you haven't told us (or I missed it), what system are you working on/for?

André

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 9:52 am 
Offline

Joined: Sat Aug 03, 2024 6:24 am
Posts: 8
fachat wrote:
Great you managed to fix it! First steps into a new world!

What you haven't told us (or I missed it), what system are you working on/for?

André


I am learning assembly languages and I wanted to use an assembly language where accessing the display is very easy so I can draw graphics on it. To make games too. I am working on Linux.


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 11:06 am 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
Sorry I meant to ask what 6502 system you are developing for.

I am unaware of a real 6502 that has its screen at $0200.
It would be a pity if you develop a game and it only runs on a PC in a simulator.

Obviously you are using a simulator or emulator, which one is this?

André

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 11:48 am 
Online
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Welcome, Nabir14!

I wouldn't be surprised to learn that you're using easy6502 by Nick Morgan:
https://skilldrick.github.io/easy6502/#first-program


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 6:16 pm 
Offline

Joined: Sat Aug 03, 2024 6:24 am
Posts: 8
BigEd wrote:
Welcome, Nabir14!

I wouldn't be surprised to learn that you're using easy6502 by Nick Morgan:
https://skilldrick.github.io/easy6502/#first-program

I am absolutely :)


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 03, 2024 6:17 pm 
Offline

Joined: Sat Aug 03, 2024 6:24 am
Posts: 8
fachat wrote:
Sorry I meant to ask what 6502 system you are developing for.

I am unaware of a real 6502 that has its screen at $0200.
It would be a pity if you develop a game and it only runs on a PC in a simulator.

Obviously you are using a simulator or emulator, which one is this?

André


No I am not even close to make games. I want to make games for the NES. For now I am learning 6502 and I am following the Nick Morgans Easy6502 tutorial.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 65 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: