It is currently Tue Oct 17, 2017 3:36 pm

 All times are UTC - 7 hours

 Page 1 of 1 [ 8 posts ]
 Print view Previous topic | Next topic
Author Message
 Post subject: Scrolling and Math. Advanced Nerdy NightsPosted: Thu Jan 26, 2017 5:40 pm

Joined: Sat Jan 14, 2017 8:40 am
Posts: 23
Hi all, its me again, Hundo!

So I find myself now on the advanced Nerdy Nights tutorial about horizontal scrolling. Step 4 of specifically, and there is a portion of that code that just doesn't make sense to me. I've debugged it by hand, while following the debugger in FCEUX and it just doesn't make sense to me what is happening. Would anyone here care to shed some light on my questions as to how this particular piece of code works? First I'll show the code and then I'll ask my question about it.

Code:
DrawNewColumn:
LDA scroll       ; calculate new column address using scroll register
LSR A
LSR A
LSR A            ; shift right 3 times = divide by 8
STA columnLow    ; \$00 to \$1F, screen is 32 tiles wide

LDA nametable     ; calculate new column address using current nametable
EOR #\$01          ; invert low bit, A = \$00 or \$01
ASL A             ; shift up, A = \$00 or \$02
ASL A             ; \$00 or \$04
CLC
STA columnHigh    ; now address = \$20 or \$24 for nametable 0 or 1

LDA columnNumber  ; column number * 32 = column data offset
ASL A
ASL A
ASL A
ASL A
ASL A
STA sourceLow
LDA columnNumber
AND #%11111000
LSR A
LSR A
LSR A
STA sourceHigh

LDA sourceLow       ; column data start + offset = address to load column data from
CLC
STA sourceLow
LDA sourceHigh
STA sourceHigh

Here we have the code which draws a new column of background data every time the scroll counter reaches a multiple of 8 (tiles are 8 pixels wide...).

I'm pretty sure I understand the first 12 lines of code correctly. If I'm correct, here we are calculating what PPU memory address we will be writing the first byte of data too for our new off screen column. Is this correct? Pretty sure I am correct on that, but its the next piece of code that I really don't undrstand.

Its the code that start with "LDA ColumnNumber". Can anyone tell me exactly what this piece of code is doing? Finally the logic behind the code is destroying my brain. In the code bunny loads a column number. Lets say the column number is 24, arbitrarily. He then multiples that number by 32 with 5 ASL's. After that, he stores the result of this previous multiplication as the low byte of the variable "sourceLow". Now, if the column number is 24, (and it can be because he's loading 128 columns of data in this example), and you multiply 24 by 32, your decimal result is 1800. Now one byte of data only holds up to 255, so how can this value be placed into the variable "sourceLow"? When I follow the sequence of ASL's in the FCEUX debugger, the results that I'm expecting for the multiplies do not add up there either.

Bunny also AND's the "columnNumber" value with the number #%11111000. If I understand the logic right here, any 8-bit number AND'ed with 11111000 can only equal the values 24 or 00 (decimal). Why does he want one or the other of these two values as his High byte for the "sourceHigh" variable?

Any advice for this would be greatly appreciated. Thank you!

-Hundo

Top

 Post subject: Re: Scrolling and Math. Advanced Nerdy NightsPosted: Thu Jan 26, 2017 7:43 pm

Joined: Fri May 08, 2015 7:17 pm
Posts: 1770
Location: DIGDUG
I am not looking at the nerdy nights code, but this looks to be selecting a column from the BG data.

Addresses in Nametable #0 go from \$2000 to \$23ff. So, \$400 bytes of data...0-\$3ff.

Thus the uncompressed data needs 3 bits for the high byte, and ...not 8 bits for the low, since he is always starting the column from the top, we only need 5 bits for the low byte...0 to \$1f.

EDIT: He's multiplying the column # by 32 to get the correct offset in the data, since each chunk is 32 bytes apart from each other.

He's adding this to the start address of the data, to find the start address of the column within the data. I would have (if carry set on the low byte math) allow for adding 1 to the high byte, in the rare case of the data crossing a page...like...

Ldx #highByteData
Lda #lowByteData
Clc
Bcc +
Inx
+
Txa ;high byte
Clc

_________________
nesdoug.com -- blog/tutorial on programming for the NES

Last edited by dougeff on Thu Jan 26, 2017 8:57 pm, edited 2 times in total.

Top

 Post subject: Re: Scrolling and Math. Advanced Nerdy NightsPosted: Thu Jan 26, 2017 8:27 pm

Joined: Fri May 08, 2015 7:17 pm
Posts: 1770
Location: DIGDUG
OK, so I'm looking at the Scrolling #4 code...

the BG data is not stored as I would expect...like, cut and pasted from a PPU dump...but rather the first 32 bytes represents the first column (30 + 2 bytes of padding)...

2424242424242424242424242424242424242424242424242430B4B6B4B60000

...so each column is 32 bytes offset from each other x 32 columns wide = 1024 bytes = \$400 bytes x 4 nametables worth of data = 4k bytes of data = \$1000.

Ok, so, seeing as each chunk is 32 bytes apart, we skip ahead 32 bytes for each step of the way (asl x 5 is the same as multiply by 32, in hex \$20). columnNumber goes from 0-\$7f...\$80 x \$20 = \$1000 bytes.

All that bit shifting is just a way to multiply by 32.

_________________
nesdoug.com -- blog/tutorial on programming for the NES

Top

 Post subject: Re: Scrolling and Math. Advanced Nerdy NightsPosted: Fri Jan 27, 2017 5:52 am

Joined: Sat Jan 14, 2017 8:40 am
Posts: 23
Hi Doug! Thanks for the reply. I appreciate the help and I understand what the code is doing now conceptually, I'm still having trouble understanding one part though. When the code ASL's the A register 5 times to multiply by 32, how does it store the result in the "sourceLow" variable, since "sourceLow" allows for only one byte (0 - 255) of storage. Example, if the columnNumber is 20 and we multiply 20 by 32 we get 280 in hex. In binary form Hex 280 is 1010000000. This value is larger than an 8 bit number, so how can we store it into "sourceLow", if source low is only 1 byte worth of storage?

Top

 Post subject: Re: Scrolling and Math. Advanced Nerdy NightsPosted: Fri Jan 27, 2017 7:34 am

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19091
Location: NE Indiana, USA (NTSC)
ASL forgets the old value of carry and moves bit 7 into carry. If you open the debugger in FCEUX for Windows and "Step Into" through shifting \$14 to the left five times, you'll see this:

Initial: A=14 C=don't care
ASL 1: A=28 C=0
ASL 2: A=50 C=0
ASL 3: A=A0 C=0
ASL 4: A=40 C=1
ASL 5: A=80 C=0

Top

 Post subject: Re: Scrolling and Math. Advanced Nerdy NightsPosted: Fri Jan 27, 2017 4:39 pm

Joined: Sat Jan 14, 2017 8:40 am
Posts: 23
tepples wrote:
ASL forgets the old value of carry and moves bit 7 into carry. If you open the debugger in FCEUX for Windows and "Step Into" through shifting \$14 to the left five times, you'll see this:

Initial: A=14 C=don't care
ASL 1: A=28 C=0
ASL 2: A=50 C=0
ASL 3: A=A0 C=0
ASL 4: A=40 C=1
ASL 5: A=80 C=0

Thank you Tepples. I traced this in FCEUX to verify what you said is correct.

Does this mean we are using the resulting overflow as the value stored in "sourceLow"? for values over 256 (Decimal)?

For example, if we are starting with #\$14 (20)

A = #\$14 Decimal(20)
ASL 1: A = #\$28 Decimal(40)
ASL 2: A = #\$50 Decimal(80)
ASL 3: A = #\$A0 Decimal160)
ASL 4: A = \$140 or \$40 C=1 - Decimal value is originally 320. After bit 7 has been shifted into carry, value is now Decimal 64. Are we using 64 as sourceLow byte?

Thank you. Sorry if I'm being annoying on this question, just want to make sure I understand the math correctly.

-Spencer

Top

 Post subject: Re: Scrolling and Math. Advanced Nerdy NightsPosted: Fri Jan 27, 2017 6:48 pm

Joined: Fri May 08, 2015 7:17 pm
Posts: 1770
Location: DIGDUG
Quote:
Are we using 64 as sourceLow byte

Yes. The upper bits are discarded. Then this math gets the upper byte...

LDA columnNumber
AND #%11111000
LSR A
LSR A
LSR A
STA sourceHigh

Another way, (16 bit shift) requires rolling the bits from carry to (a zeroed) upper byte.

Lda #0
Sta sourceHigh
Sta sourceLow
Asl sourceLow (shifts high bit to carry)
Rol sourceHigh (shifts from carry into high byte)

Repeat asl/rol combo per # of shifts.

_________________
nesdoug.com -- blog/tutorial on programming for the NES

Top

 Post subject: Re: Scrolling and Math. Advanced Nerdy NightsPosted: Fri Jan 27, 2017 6:55 pm

Joined: Sat Jan 14, 2017 8:40 am
Posts: 23
dougeff wrote:
Quote:
Are we using 64 as sourceLow byte

Yes. The upper bits are discarded. Then this math gets the upper byte...

LDA columnNumber
AND #%11111000
LSR A
LSR A
LSR A
STA sourceHigh

Another way, (16 bit shift) requires rolling the bits from carry to (a zeroed) upper byte.

Lda #0
Sta sourceHigh
Sta sourceLow
Asl sourceLow (shifts high bit to carry)
Rol sourceHigh (shifts from carry into high byte)

Repeat asl/rol combo per # of shifts.

Thank you Dougeff and Tepples! Much appreciated. I had been struggling with that for two days : )

Top

 Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending
 Page 1 of 1 [ 8 posts ]

 All times are UTC - 7 hours

#### Who is online

Users browsing this forum: Bing [Bot] and 5 guests

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

Search for:
 Jump to:  Select a forum ------------------ NES / Famicom    NESdev    NESemdev    NES Graphics    NES Music    Homebrew Projects       2017 NESdev Competition       2016 NESdev Competition       2014 NESdev Competition       2011 NESdev Competition    Newbie Help Center    NES Hardware and Flash Equipment       Reproduction    NESdev International       FCdev       NESdev China       NESdev Middle East Other    General Stuff    Membler Industries    Other Retro Dev       SNESdev       GBDev    Test Forum Site Issues    phpBB Issues    Web Issues    nesdevWiki