Random Stupid Questions I Think Of

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

User avatar
Sogona
Posts: 186
Joined: Thu Jul 23, 2015 7:54 pm
Location: USA
Contact:

Random Stupid Questions I Think Of

Post by Sogona »

I want to use this thread to basically ask any stupid short question I think of that doesn't deserve its own thread, and that I can't find a simple answer to elsewhere. I have a couple of questions right off the bat, and I'll ask more in different posts if/when I think of any.

1. Does $2002 have to be reread everytime something has to be written to a new area of the PPU?

2. What is the difference between bit shifts and bit rotations?

3. Does trying to draw things outside of vblank damage the PPU?

4. Are there any situations when programming the NES where (indirect,x) addressing would come in handy? Also I don't completely understand how this works. I know that (indirect),y addressing gets the address from the value in the pointer and adds y to it, so then does x get added to the pointer itself, and then the address comes from the value in the pointer+x?

5. When I was using NESASM, there was a way to see how much of each 8kb bank had been used. (I believe it was the -s command?) Is there any way to do something like this in ASM6?
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Random Stupid Questions I Think Of

Post by lidnariq »

Sogona wrote:1. Does $2002 have to be reread everytime something has to be written to a new area of the PPU?
No. It's just easier to read $2002 rather than remember what state you left $2005/$2006 's flipflop.
2. What is the difference between bit shifts and bit rotations?
BIT SHIFT
IT SHIFT0
T SHIFT00
 SHIFT000
SHIFT0000

BIT ROTATE
IT ROTATEB
T ROTATEBI
ROTATEBIT
3. Does trying to draw things outside of vblank damage the PPU?
It does cause the PPU's output drivers to get in a fight with the ROM, which isn't great ... and it could randomly scribble over CHR RAM or nametable RAM, so ... don't do that.
4. Are there any situations when programming the NES where (indirect,x) addressing would come in handy?
Arrays of pointers.
does x get added to the pointer itself, and then the address comes from the value in the pointer+x?
Yes.
User avatar
rainwarrior
Posts: 8735
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Random Stupid Questions I Think Of

Post by rainwarrior »

Sogona wrote:1. Does $2002 have to be reread everytime something has to be written to a new area of the PPU?
No, it only needs to be read when you don't know what state the $2005/2006 latch is in. It's a good idea to read it the first time you're using $2005/2006 in your NMI, and then after every pair of two writes to $2005/2006 it will be back to where it started. No need to read $2002 again.
2. What is the difference between bit shifts and bit rotations?
When you shift/rotate, you move all the bits over. One bit falls out the end (goes into the carry bit) and a hole is created at the other end. To fill that hole: a shift (asl/lsr) moves a 0 into the hole. A rotate (rol/ror) moves whatever is in the carry flag into that hole.
3. Does trying to draw things outside of vblank damage the PPU?
No, it does not harm the PPU. (This would be a huuuuge design flaw if it did! Don't let programmers break your hardware with their bugs!) It just results in corruptions to the VRAM, i.e. visual problems.
4. Are there any situations when programming the NES where (indirect,x) addressing would come in handy? Also I don't completely understand how this works. I know that (indirect),y addressing gets the address from the value in the pointer and adds y to it, so then does x get added to the pointer itself, and then the address comes from the value in the pointer+x?
It's not that commonly used, but the intent is that you can create a table of pointers in zeropage RAM, and use X to index those pointers. X is added to the address of the pointer (i.e. the result will be on the zero page still), it is not added to the address the pointer points to (e.g. indirect Y), nor the value the pointer fetches.
5. When I was using NESASM, there was a way to see how much of each 8kb bank had been used. (I believe it was the -s command?) Is there any way to do something like this in ASM6?
There are a few ways to do this using cc65, such as using the linker flag that generates a "map" file. If you need it in code, you may be able to use * to find the position of a piece of code, so you could put something at the end that calculates (* - $8000) or wherever the bank started.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Random Stupid Questions I Think Of

Post by thefox »

One nice feature of STA (foo,x) is that it doesn't generate dummy reads, so if you happen to have a pointer to a hardware register with side-effects on reads and need to access it, that can be done safely (with X=0). STA (foo),y always generates a dummy read. I admit this is not a common occurrence, but I took advantage of it in my generic memory copy/fill routines.

Similarly, LDA (foo,x) has a property that it always takes the same amount of time (unlike LDA (foo),y), so it can be useful for pointer dereferencing in timed code (again, only applicable if indexing is not needed, so X=0).
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Random Stupid Questions I Think Of

Post by tokumaru »

Sogona wrote:1. Does $2002 have to be reread everytime something has to be written to a new area of the PPU?
I prefer not to. I always use $2005 and $2006 in pairs, so the latch should never be left in the wrong state. But if by any chance it is, I want this bug to show during development, so I can fix it. I do read $2002 every once in a while though (not every frame).
4. Are there any situations when programming the NES where (indirect,x) addressing would come in handy?
I remember people mentioning it could be useful for reading music tracks. A music engine could use generic code to process tracks, so it would simply change the index register and be ready to read data from any track.
5. When I was using NESASM, there was a way to see how much of each 8kb bank had been used. (I believe it was the -s command?) Is there any way to do something like this in ASM6?
I'm not aware of anything of the kind in ASM6. You can generate a listing file (with -l), open it and look at the address of the last thing in the bank. If you want something more automatic, you can make a macro to warn you when there are less than X bytes until the next boundary:

Code: Select all

.macro CheckBoundary Size, Limit
	Mask = Size - 1
	Remaining = Size - ($ & Mask)
	.if Remaining < Limit
		.error "The limit was reached!"
	.endif
.endm
If you want to be warned when there are less than 1KB left in an 8KB bank, just call the macro like this (right after all the code and data in the bank): CheckBoundary 8192, 1024

The bank size has to be a power of 2, the limit can be anything. It's not perfect, since it doesn't give you an exact number, and won't detect overflows, but it's something.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Random Stupid Questions I Think Of

Post by tepples »

lidnariq wrote:
Sogona wrote:1. Does $2002 have to be reread everytime something has to be written to a new area of the PPU?
No. It's just easier to read $2002 rather than remember what state you left $2005/$2006 's flipflop.
Unless you're disciplined enough to always leave it in "ready for first write" state except when doing raster effects. Somehow tokumaru and I have never had a problem with this.
lidnariq wrote:BIT SHIFT
IT SHIFT0
T SHIFT00
 SHIFT000
SHIFT0000

BIT ROTATE
IT ROTATEB
T ROTATEBI
ROTATEBIT
Clever :-)
Sogona wrote:3. Does trying to draw things outside of vblank damage the PPU?
Probably not. And in fact, you're encouraged to draw things out of vblank if you have forced blank turned on ($2001 = $00).
lidnariq wrote:
Sogona wrote:4. Are there any situations when programming the NES where (indirect,x) addressing would come in handy?
Arrays of pointers.
Specifically, the only time I've seen an array of pointers on zero page being useful is a music engine, as tokumaru mentioned, with one or more pointers for each channel. In the music engine I used in RHDE: Furniture Fight and previous games, pointers on zero page represent position in a musical phrase, position in an instrument envelope, and position in sound effect data.
rainwarrior wrote:If you need [amount used in a memory area] in code, you may be able to use * to find the position of a piece of code, so you could put something at the end that calculates (* - $8000) or wherever the bank started.
For example, I rigged the credits screen of development versions of RHDE to display how full the ROM was. But it's tricky to get right because the size across all source files isn't known until link time, and .byte .sprintf(...) in ca65 requires that its argument be constant at assembly time. So instead I had to construct each ASCII digit like this (untested, as my RHDE project files are in another castle at the moment), which is resolved properly at link time:

Code: Select all

permill_full = (__CODE_SIZE__ + __RODATA_SIZE__) * 1000 / 32768
tenths_full = permill_full / 100
hundredths_full = (permill_full .MOD 100) / 10
thousandths_full = permill_full .MOD 10
.byte tenths_full|'0', hundredths_full|'0', '.', thousandths_full|'0', "% full", 0
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Random Stupid Questions I Think Of

Post by tokumaru »

lidnariq wrote:BIT SHIFT
IT SHIFT0
T SHIFT00
 SHIFT000
SHIFT0000

BIT ROTATE
IT ROTATEB
T ROTATEBI
ROTATEBIT
Rotate is more like this though:

Code: Select all

BIT ROTATE
IT ROTATE?
T ROTATE?B
 ROTATE?BI
ROTATE?BIT
Where "?" depends on the state of the carry when you start rotation. If you want to avoid the "?" gap actually have it like lidnariq posted, you have to copy bit 7 (when rotating left) or bit 0 (when rotating right) into the carry before rotating.
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: Random Stupid Questions I Think Of

Post by dougeff »

copy bit 7 (when rotating left) or bit 0 (when rotating right) into the carry before rotating.
How about this approach?

Code: Select all

LDA $00
rol a ;puts bit 7 in carry
rol $00
And

Code: Select all

LDA $00
ror a ;puts 0 bit in carry
ror $00
Last edited by dougeff on Tue Oct 06, 2015 8:50 am, edited 1 time in total.
nesdoug.com -- blog/tutorial on programming for the NES
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Random Stupid Questions I Think Of

Post by tepples »

tokumaru wrote:Rotate is more like this though:

Code: Select all

BIT ROTATE
IT ROTATE?
T ROTATE?B
 ROTATE?BI
ROTATE?BIT
Where "?" depends on the state of the carry when you start rotation. If you want to avoid the "?" gap actually have it like lidnariq posted, you have to copy bit 7 (when rotating left) or bit 0 (when rotating right) into the carry before rotating.
Good point. But on an 8-bit system, doesn't B start in the gap?

Code: Select all

C:Accum...
B:ITROTATE
I:TROTATEB
T:ROTATEBI
R:OTATEBIT
Copying bit 7 when rotating left uses CMP #$80:

Code: Select all

lda #ROTATION  ; X:ROTATION
cmp #$80       ; R:ROTATION
rol a          ; R:OTATIONR
cmp #$80       ; O:OTATIONR
rol a          ; O:TATIONRO
cmp #$80       ; T:TATIONRO
rol a          ; T:ATIONROT
For more rotation tricks see patterns on our wiki.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Random Stupid Questions I Think Of

Post by tokumaru »

dougeff wrote:

Code: Select all

LDA $00
rol a ;puts bit 7 in carry
rol $00
Like tepples pointed out, when rotating left you can copy bit 7 to the carry using CMP $80. I use that a lot. Rotating right has to be like you wrote though, AFAIK.
tepples wrote:But on an 8-bit system, doesn't B start in the gap?
Are you saying that because the phrase "BIT ROTATE" has more than 8 characters? I assumed we were abstracting the register size, since lidnariq's examples had 9 and 10 characters, respectively. I just assumed the whole phrase could be loaded into the accumulator, at which point the carry would be in whatever state the previous instructions left it in.
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: Random Stupid Questions I Think Of

Post by dougeff »

Alternate way to do this...

12345678
23456781
34567812

Code: Select all

asl a
adc #00
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
Sogona
Posts: 186
Joined: Thu Jul 23, 2015 7:54 pm
Location: USA
Contact:

Re: Random Stupid Questions I Think Of

Post by Sogona »

What's the deal with color $0D of the PPU's palette?
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: Random Stupid Questions I Think Of

Post by Drew Sebastino »

I don't know the specifics, but for a short answer, I think it's something like the color is a signal outside of what the TV is expecting, so depending on the TV, it will either show as black and nothing else, or it will show as black but make the whole scanline screwy.

This is actually a picture demonstrating how it looks from the forum:

Image

I still think it would look cool for if you were trying to make a trippy effect on the game.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Random Stupid Questions I Think Of

Post by lidnariq »

There are so many things you could mean by "What's the deal".

Answers include:
It's "darker" (a lower voltage) than black
It's an accident of how the PPU generates colors, and its inclusion is an oversight.
The TV accidentally perceives this too low voltage as maybe the start of a new horizontal line of pixels. (TVs were originally entirely analog devices, so it can be halfway to thinking something)
User avatar
Sogona
Posts: 186
Joined: Thu Jul 23, 2015 7:54 pm
Location: USA
Contact:

Re: Random Stupid Questions I Think Of

Post by Sogona »

I'm a little confused on the difference between the negative flag and the overflow flag on the 6502. From what I've read, the latter is only affected by math, bit testing, and some stack operations. So for example, if I just want to check if something's negative or positve, I'd use BPL and BMI, but if, after adding something to the accumulator, you'd use BVS or BVC instead?

P.S when I say overflow flag, I mean the flag in the status byte, not in $2000, if there was any ambiguity.
Post Reply