It is currently Tue Oct 23, 2018 2:03 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Mon Oct 05, 2015 7:36 pm 
Offline
User avatar

Joined: Thu Jul 23, 2015 7:54 pm
Posts: 180
Location: USA
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?


Top
 Profile  
 
PostPosted: Mon Oct 05, 2015 7:44 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7682
Location: Seattle
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.

Quote:
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

Quote:
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.

Quote:
4. Are there any situations when programming the NES where (indirect,x) addressing would come in handy?
Arrays of pointers.

Quote:
does x get added to the pointer itself, and then the address comes from the value in the pointer+x?
Yes.


Top
 Profile  
 
PostPosted: Mon Oct 05, 2015 7:48 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6900
Location: Canada
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.

Quote:
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.

Quote:
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.

Quote:
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.

Quote:
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.


Top
 Profile  
 
PostPosted: Mon Oct 05, 2015 8:18 pm 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 3132
Location: Tampere, Finland
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


Top
 Profile  
 
PostPosted: Mon Oct 05, 2015 11:12 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10914
Location: Rio de Janeiro - Brazil
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).

Quote:
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.

Quote:
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:
.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.


Top
 Profile  
 
PostPosted: Tue Oct 06, 2015 8:21 am 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20690
Location: NE Indiana, USA (NTSC)
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:
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


Top
 Profile  
 
PostPosted: Tue Oct 06, 2015 8:41 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10914
Location: Rio de Janeiro - Brazil
lidnariq wrote:
BIT SHIFT
IT SHIFT0
T SHIFT00
 SHIFT000
SHIFT0000

BIT ROTATE
IT ROTATEB
T ROTATEBI
ROTATEBIT

Rotate is more like this though:

Code:
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.


Top
 Profile  
 
PostPosted: Tue Oct 06, 2015 8:50 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2308
Location: DIGDUG
Quote:
copy bit 7 (when rotating left) or bit 0 (when rotating right) into the carry before rotating.


How about this approach?

Code:
LDA $00
rol a ;puts bit 7 in carry
rol $00


And
Code:
LDA $00
ror a ;puts 0 bit in carry
ror $00

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


Last edited by dougeff on Tue Oct 06, 2015 8:50 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Oct 06, 2015 8:50 am 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20690
Location: NE Indiana, USA (NTSC)
tokumaru wrote:
Rotate is more like this though:

Code:
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:
C:Accum...
B:ITROTATE
I:TROTATEB
T:ROTATEBI
R:OTATEBIT

Copying bit 7 when rotating left uses CMP #$80:
Code:
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.


Top
 Profile  
 
PostPosted: Tue Oct 06, 2015 9:03 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10914
Location: Rio de Janeiro - Brazil
dougeff wrote:
Code:
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.


Top
 Profile  
 
PostPosted: Mon Oct 19, 2015 10:16 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2308
Location: DIGDUG
Alternate way to do this...

12345678
23456781
34567812

Code:
asl a
adc #00

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


Top
 Profile  
 
PostPosted: Wed Jan 20, 2016 9:28 pm 
Offline
User avatar

Joined: Thu Jul 23, 2015 7:54 pm
Posts: 180
Location: USA
What's the deal with color $0D of the PPU's palette?


Top
 Profile  
 
PostPosted: Wed Jan 20, 2016 9:52 pm 
Offline
Formerly Espozo
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3380
Location: Richmond, Virginia
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.


Top
 Profile  
 
PostPosted: Wed Jan 20, 2016 10:23 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7682
Location: Seattle
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)


Top
 Profile  
 
PostPosted: Thu Jan 28, 2016 11:23 pm 
Offline
User avatar

Joined: Thu Jul 23, 2015 7:54 pm
Posts: 180
Location: USA
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.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 3 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:  
Powered by phpBB® Forum Software © phpBB Group