First, I'd like to point out that NesDev
is a good reference for NES programming and Andrew Jacobs's
site is a good reference for the 6502 CPU in particular. You may want to use the Addressing and Reference pages of the latter site when going over the code that follows.
The emulator I used was FCEUX 2.2.3. If you open the PPU viewer while on the title screen, you see the sprites on the left and the background tiles on the right. It looks like the sprite for the first part of the C is tile 0x3C and the second part is 0x3E; you can get the number by hovering your mouse over the tiles in the PPU viewer. This will be useful later.
Sprites are handled via NES registers $2003, $2004, and $4014. The first one of those determines where data is written into sprite RAM, which is usually called OAM.
The FCEUX debugger comes into play here. Load the ROM and pause emulation at the title screen. Then open up the debugger and add a write breakpoint on $2003 (Add button -> enter 2003 into Address box -> check the Write box -> leave the CPU Mem option toggled -> click OK). This causes emulation to stop on a write to register $2003. Click Run, and the debugger should stop at the following code:
>07:C064:8D 03 20 STA $2003
07:C067:A0 02 LDY #$02
07:C069:8C 14 40 STY $4014
The second and third lines are the useful ones, because they indicate that the sprite information is copied from CPU RAM $0200-$02FF via DMA. DMA is used to copy 256 bytes into OAM at once rather than having to do it byte-by-byte. This means that the sprite information is stored in CPU RAM $0200-$02FF in the order y-coordinate, tile, attributes, x-coordinate for each sprite that you mentioned above. So $0200, $0204, $0208, etc. have the y-coordinate; $0201, $0205, $0209, etc. have the tile; and so on.
Now we need to find out where the data at $0200-$02FF comes from. Set a write breakpoint on that range of addresses using the same process as before, but enter 200 into the first Address box and 2FF into the second. You can disable the $2003 breakpoint by double-clicking on it in the list so that the letter E disappears after the colon. When you click Run, the debugger should stop at the following code:
>00:80F4:9D 00 02 STA $0200,X
00:80F7:B1 08 LDA ($08),Y
00:80F9:9D 01 02 STA $0201,X
This is nice, because the second and third lines indicate that the tile values come from an address related to the value at $0008 in CPU RAM. It may not be the C tile that's being processed, however. To find that one in particular, we'll modify the breakpoint. Select the $0200-$02FF breakpoint, click Edit, enter A==#3C into the Condition box, then hit OK. This is now a conditional breakpoint because it will only work when the A==#3C condition is met. It causes emulation to stop when $0200-$02FF is being written to but only if the accumulator (A) has value 0x3C, which is the first part of the C tile. We know that the accumulator will have that value because of the LDA and STA instructions.
One thing to mention here is that the disassembly you see on the left side of the debugger is not always the order in which the code is executed. Branch and jump instructions can cause instructions to be skipped or can jump to other areas of code. This is relevant because the instruction immediately above the one indicated by the > may not be the one that was executed before it. The trace logger can record the instructions in the order in which they are executed. So open up the trace logger (Debug -> Trace Logger) and set it to log the last 100 lines in the drop-down box. Then click Start Logging. Now go back to the debugger and click Run. It should stop at code similar to
>00:80F9:9D 01 02 STA $0201,X
The last line in the trace logger should be
$80F7:B1 08 LDA ($08),Y @ $9AAB = #$3C
Again, this means that the tile value comes from an address related to the value at $0008 in CPU RAM. The info after the @ symbol indicates that the exact address is $9AAB.
In the hex editor, go to $9AAB; File -> Goto Address is easier than scrolling. You should see that 0x3C value that we want. If you right-click on it and select Go Here In ROM File, you'll end up at 0x1ABB. The nice thing about the hex editor is that you can change values as desired and see the effects without having to modify, save, and reload the ROM file. You may need to reset the emulation, however. Just select the address that you want to modify and type whatever value you want. (Note: This may cause the game to crash depending on what you modify.) To play around with this without interruptions, disable any breakpoints in the debugger and click Stop Logging in the trace logger.
If you look at the values following that 0x3C at 0x1ABB, you'll see 0x3E four bytes later. This is the tile value for the second part of the C. This may be a coincidence, since the data doesn't have to be stored sequentially in the ROM, but changing it in the hex editor also changes that part of the C. Now we can hypothesize that the data indeed is stored sequentially, so the X-coordinate should be two bytes after the tile value, at 0x1ABD. If you change this in the hex editor, the first tile of the C moves horizontally. Keep doing this for every fourth byte, and you'll modify the positions of the sprites on the title screen. You can do File -> Save Rom As to save your hack as a new ROM file when you're done.
There are a number of potential problems with this approach that I could discuss at this point, but what questions do you have first?