More ML confusion

Basic and Machine Language

Moderator: Moderators

User avatar
GreyGhost
Vic 20 Nerd
Posts: 525
Joined: Wed Oct 05, 2005 11:10 pm

More ML confusion

Post by GreyGhost »

I started writing a little graphics demo today and I am confused as to why its not working right.

Code: Select all

start:
   ldx #$00
   lda #$03 
character:        ;draws a 2 pixel thick diagonal line?
   sta $1c00,x     
   rol 
   inx
   cpx #$08
   bne character 
set video
   lda #$ff
   sta $9005

   ldx #$00
screen:   
   lda #$00
   sta $1e00,x
   sta $1f00,x
   lda #$0e
   sta $9600,x
   sta $9700,x
   inx
   bne screen
loop:
   ldx #$00
shift:               ;rotates all bits in character to the left by 1
   rol $1c00,x
   inx
   cpx #$08
   bne shift
   jmp loop
I end up with a blank screen. Am I not using the ROL op right or something? Do I have to clear the carry flag before I ROL or ROR?
Rob
Kananga
Vic 20 Afficionado
Posts: 317
Joined: Mon Mar 08, 2010 2:11 pm

Re: More ML confusion

Post by Kananga »

GreyGhost wrote:

Code: Select all

loop:
   ldx #$00
shift:               ;rotates all bits in character to the left by 1
   rol $1c00,x
   inx
   cpx #$08
   bne shift
   jmp loop
Your loop shifts the bits out quickly before you even see the pixels.
CPX clears carry while x is less than 8, hence ROL shifts zeros into each row.
GreyGhost wrote:I end up with a blank screen. Am I not using the ROL op right or something? Do I have to clear the carry flag before I ROL or ROR?
If you don't want carry shifted in, you can use ASL instead of ROL, which always shifts 0 into the lowest bit. (The highest bit still goes to the carry flag)
Buy the new Bug-Wizard, the first 100 bugs are free!
User avatar
GreyGhost
Vic 20 Nerd
Posts: 525
Joined: Wed Oct 05, 2005 11:10 pm

Post by GreyGhost »

This was my intentions:

Code: Select all

.C:0338   A2 00           LDX #$00
.C:033a   A9 03           LDA #$03
.C:033c   9D 00 1C        STA $1C00,X
.C:033f   2A              ROL A
.C:0340   69 00           ADC #$00
.C:0342   E8              INX
.C:0343   E0 08           CPX #$08
.C:0345   D0 F5           BNE $033C
.C:0347   A2 00           LDX #$00
.C:0349   A9 00           LDA #$00
.C:034b   9D 00 1E        STA $1E00,X
.C:034e   9D 00 1F        STA $1F00,X
.C:0351   A9 0A           LDA #$0A
.C:0353   9D 00 96        STA $9600,X
.C:0356   9D 00 97        STA $9700,X
.C:0359   E8              INX
.C:035a   D0 ED           BNE $0349
.C:035c   A9 FF           LDA #$FF
.C:035e   8D 05 90        STA $9005
.C:0361   A2 00           LDX #$00
.C:0363   BD 00 1C        LDA $1C00,X
.C:0366   2A              ROL A
.C:0367   69 00           ADC #$00
.C:0369   9D 00 1C        STA $1C00,X
.C:036c   E8              INX
.C:036d   E0 08           CPX #$08
.C:036f   D0 F2           BNE $0363
.C:0371   4C 61 03        JMP $0361

I got to reading about ROL and ROR. Seems as the far bit on the left or right rolls out of view, the carry flag is set. I then decided that rolling left would be simpler than rolling right. So, I issue ROL on the accumulator, and then add the extra bit to the right by ADC#$00. Seems to work fairly well. I was trying to get that effect I've seen in some games that have the water constantly rolling or waving.


On a lighter note, and so you guys can giggle at me. Last night when I was working on this, I got stumped for like an hour trying to figure out why the little character drawing routine at the top of the listing wasn't working. I like to use the cassette buffer to do these small ML programs. Well I'd check the code and then go and type in SYS828 to see if I got it working. Nope. Then I'd check the code, and repeat. Stare at the screen for a bit scratching my head. WTF. After at least an hour I looked at the starting address; 824. That's where I usually start character data for just for fun programs I do. I typed in SYS 824 and bam ! there it was. :oops:

Go figure.

Later,
Rob
User avatar
GreyGhost
Vic 20 Nerd
Posts: 525
Joined: Wed Oct 05, 2005 11:10 pm

Post by GreyGhost »

I was reading in another post that sometimes CMP, CMX, and CPY sets the carry flag, so I added CLC at the beginning of my two loops that used CPX and now it is working great.


Now on to another ML question I have. I started writing a simple program last night to move a ball figure ($51) around the screen using the keyboard. This is as far as I got:

Code: Select all

* = $0338

variables:

char_loc = $1c00 - $1c01

start:
   lda #$00        ;set up variable
   sta $1c00       ; 
   lda #$1e        ;char location
   sta $1c01       ;
   
   lda #$20        ;space char
   ldy #$00        ;
clr_scrn:        
   sta $1e00,y     ;clears the
   sta $1f00,y     ;screen
   iny             ;
   bne  clr_scrn   ;
   
   lda #$51
   sta  

I'm not sure where to go from here. I was wanting to get the information from the variable I set up, but I don't know how to go about it. How do I read the screen location that the ball needs to go into from the variable that I set up. Can someone explain?

Later,
Rob
Kananga
Vic 20 Afficionado
Posts: 317
Joined: Mon Mar 08, 2010 2:11 pm

Post by Kananga »

GreyGhost wrote:I was reading in another post that sometimes CMP, CMX, and CPY sets the carry flag, so I added CLC at the beginning of my two loops that used CPX and now it is working great.
Hint:

Code: Select all

CLC
ROL A
is equivalent to:

Code: Select all

ASL A
and is shorter.
GreyGhost wrote: I'm not sure where to go from here. I was wanting to get the information from the variable I set up, but I don't know how to go about it. How do I read the screen location that the ball needs to go into from the variable that I set up. Can someone explain?
From your example I conclude that you want to use the variable as a pointer to screen memory. That is only possible with zeropage locations. (Or self-modifying code).
Example:

Code: Select all

char_loc = $FE
start:
   LDA #0
   STA char_loc
   LDA #$1E
   STA char_loc+1
...

   LDA #$51
   LDY #0
   STA (char_loc), Y
The last line stores A into the address at $FE/$FF + Y.
Buy the new Bug-Wizard, the first 100 bugs are free!
User avatar
GreyGhost
Vic 20 Nerd
Posts: 525
Joined: Wed Oct 05, 2005 11:10 pm

Post by GreyGhost »

For the demo above my intent was to rotate the bits. As in:
LDX #$00
beginning:
CLC
LDA $1c00,x
ROLA
ADC #$00 <-- adds the bit that went into the carry flag
STA $1c00,x
INX
CPX #$08<-- to see if all bytes in character have been ROLed
BNE to beginning

A ASL would eventually end up with a blank space.

For using the variable, I see what you are saying. If I can only use that in zero page, what are some areas that I can use for it besides $FE/$FF?

So, I set Y register to the beginning of the pointer I need (in this case $FE) and the Accumulator reads that location + the next location to get the memory location to store the ball figure.
Rob
Kananga
Vic 20 Afficionado
Posts: 317
Joined: Mon Mar 08, 2010 2:11 pm

Post by Kananga »

GreyGhost wrote:A ASL would eventually end up with a blank space.
Why?
GreyGhost wrote:For using the variable, I see what you are saying. If I can only use that in zero page, what are some areas that I can use for it besides $FE/$FF?
See this thread.

Happy coding!
Buy the new Bug-Wizard, the first 100 bugs are free!
User avatar
GreyGhost
Vic 20 Nerd
Posts: 525
Joined: Wed Oct 05, 2005 11:10 pm

Post by GreyGhost »

A quote from "Top Down Assembly Language Programming for Your Vic 20 or Commodore 64" by Ken Skier

Pg. 37 - "Rotate a byte nine times and you'll still have the original byte. The same is true if you rotate a byte to the right. But shift a byte left nine times, or right nine times, and you know what you've got left? Nothing!"

That's where I got that from. Also looking at some other manuals, ASL or LSR does effect the carry bit, but doesn't continue back to the other side like ROL or ROR.

Try it, I may be wrong. I'm still wetting my feet for the first time with some of this stuff.

Anyways, thanks for the link. I'll look into it. I did read some place that if basic isn't going to be used at all, there are a lot of free zero page locations I can use. And that's my goal mostly basic free, except maybe some of the math functions in rom.
Rob
Kananga
Vic 20 Afficionado
Posts: 317
Joined: Mon Mar 08, 2010 2:11 pm

Post by Kananga »

GreyGhost wrote:Pg. 37 - "Rotate a byte nine times and you'll still have the original byte. The same is true if you rotate a byte to the right. But shift a byte left nine times, or right nine times, and you know what you've got left? Nothing!"
All true, but missing the point. I didn't say ASL=ROL.

EDIT:
But back to the pointer-to-cell issue:

Take a look at the addressing modes (ZP),Y and (ZP,X).
The former takes the address from two consecutive zeropage bytes and adds the value of Y. The result is the location of your operand.
The latter adds X to the ZP location and the two consecutive bytes from the resulting address are the operand address.
Probably better explained in the book.

Usually $FA-$FE are safe with BASIC.
Buy the new Bug-Wizard, the first 100 bugs are free!
tlr
Vic 20 Nerd
Posts: 567
Joined: Mon Oct 04, 2004 10:53 am

Post by tlr »

GreyGhost wrote:For the demo above my intent was to rotate the bits. As in:
LDX #$00
beginning:
CLC
LDA $1c00,x
ROLA
ADC #$00 <-- adds the bit that went into the carry flag
STA $1c00,x
INX
CPX #$08<-- to see if all bytes in character have been ROLed
BNE to beginning

A ASL would eventually end up with a blank space.
No, because you are inserting the shifted out bit with an ADC.
This, as suggested by kananga, works (and saves 1 byte):

Code: Select all

 LDX #$00
beginning:
 LDA $1c00,x
 ASL A
 ADC #$00 <-- adds the bit that went into the carry flag
 STA $1c00,x
 INX
 CPX #$08<-- to see if all bytes in character have been ROLed
 BNE to beginning
Better yet (saving 4 more bytes):

Code: Select all

 LDX #$07 <-- start at index 7
beginning:
 LDA $1c00,x
 ASL
 ROL $1c00,x
 DEX
 BPL to beginning <-- continue unless less than 0
FD22
Vic 20 Hobbyist
Posts: 148
Joined: Mon Feb 15, 2010 12:31 pm

Post by FD22 »

Despite being a 6502 coder of 30 years, I still have this page as one of my default browser tabs: http://homepage.ntlworld.com/cyborgsyst ... 2/6502.htm
User avatar
GreyGhost
Vic 20 Nerd
Posts: 525
Joined: Wed Oct 05, 2005 11:10 pm

Post by GreyGhost »

I am seeing better now. My concerns was with the CPX setting the carry flag, but with ASL clearing carry for me and then doing a ROL, It is doing the same thing in a different order than I had it. Thanks for explaining it and not getting frustrated with me.

That second bit of code, can you explain that one for me. I see that the accumulator gets loaded with a byte, ASL and then never gets put back. What's happening there?
Rob
tlr
Vic 20 Nerd
Posts: 567
Joined: Mon Oct 04, 2004 10:53 am

Post by tlr »

GreyGhost wrote:I am seeing better now. My concerns was with the CPX setting the carry flag, but with ASL clearing carry for me and then doing a ROL, It is doing the same thing in a different order than I had it. Thanks for explaining it and not getting frustrated with me.

That second bit of code, can you explain that one for me. I see that the accumulator gets loaded with a byte, ASL and then never gets put back. What's happening there?
Sure:

Code: Select all

LDA $1c00,x <-- load previous value to accumulator.
ASL         <-- load C-flag with MSB of previous value
ROL $1c00,x <-- perform actual operation on $1c00,x, i.e rotate.
Btw using reverse loops like I did also avoids having the carry overwritten by a compare. (though not necessary in this example)
User avatar
GreyGhost
Vic 20 Nerd
Posts: 525
Joined: Wed Oct 05, 2005 11:10 pm

Post by GreyGhost »

Ah, very cool and very understandable. A preset carry flag for the ROL op to do its natural thing.
Rob
User avatar
GreyGhost
Vic 20 Nerd
Posts: 525
Joined: Wed Oct 05, 2005 11:10 pm

Post by GreyGhost »

A question about my other demo I'm working on. How would I check to see if my ball character has left the screen boundaries using the pointer I set up ($fe-$ff)?
Rob
Post Reply