It is currently Mon Dec 18, 2017 9:49 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: MMC1 graphical glitches
PostPosted: Wed Jul 02, 2014 12:32 am 
Offline

Joined: Wed Jul 02, 2014 12:00 am
Posts: 12
Hello there folks, I'm new here. Brief background: I have learned programming a few different periods in my life. The last time, I was a teenager learning Java and Visual Basic, just over a decade ago now. Then I abandoned programming for theatre school, but that's a long story. I'm a quick learner, but a bit rusty, so please go easy on me. A while ago I completed about half of the Nerdy Nights NES tutorials, and I've read up a lot on various things relating to NES/6502 assembler, branched out a bit into a couple different assemblers just to soak up some knowledge, and now I'm back for more of the good stuff.

So now that that's out of the way. I am trying to convert some 2D animations I made into NES roms as a learning exercise. I made a 9 frame heartbeat animation into a fluid, beautiful NES program, but now I'm working on a lunar eclipse animation. A bit more tricky, and as a result I've discovered that I need to choose my mapper wisely if I want to include lots of CHR data and switch out CHR sets.

With the heartbeat I only needed one 4kb CHR set, but so far for the eclipse (which has up to 290 frames of data, most of which can be recycled), has required 8kb for a very simplified version of the end product I have in mind. I've finally figured out how to alternate between CHR banks, but now I'm having all kinds of graphical glitches in my animation. One sprite out of most of the frames is displaying the incorrect tile, and the other 63 on-screen sprites are correct. Oddly, upon Reset the glitches disappear, but when Powering On the glitches return. Another odd thing is that the glitch tile seems to move around the screen with no rhyme or reason. I'm sure someone here has a simple explanation, or can at least point me in the right direction.

I included the current version of the program which I realize is a little inefficiently coded. Assemble with NESASM3. Thanks for your time.


Attachments:
eclipse rough draft.zip [7.31 KiB]
Downloaded 67 times
Top
 Profile  
 
PostPosted: Wed Jul 02, 2014 5:18 am 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1047
The program you uploaded is missing 3 files (the three .pal files, "eclipse.pal", "ourpal.pal" and "eclipse2.pal"). Uploading either those or just a compiled rom would be cool.

There's a bunch of little problems in your source code that may be contributing to the problem.

setMMC1ControlMode doesn't have an RTS, so it runs into setCHRPage0000. In initMMC1Mapper, TXA is used despite X not being used in any way. This is sort of fine if intended except the first time it's called, X's value is undefined.

Reset hits. This stuff is done:
Code:
Start:
  bit $2002   ;; clear the VBL flag if it was set at reset time
vwait1:
  bit $2002
  bpl vwait1  ;; at this point, about 27384 cycles have passed
vwait2:
  bit $2002
  bpl vwait2  ;; at this point, about 57165 cycles have passed

  lda #%10000000
  sta $2000
  lda #%00011110
  sta $2001


  lda #%00011000
  jsr setMMC1ControlMode

setMMC1ControlMode also calls setCHRPage0000 because it has no RTS as stated before. Notice how X is not loaded with anything known in the above code, or in setMMC1ControlMode. The next line after the above is jsr initMMC1Mapper.

Inside initMMC1Mapper is this:
Code:
initMMC1Mapper:
  LDA #$80
  STA $8000

  TXA
  JSR setMMC1ControlMode

Which uses whatever is in X to set the MMC1Control Mode, but X has never been set. I'm actually unaware of what X would be in this case, but my guess would be either whatever it was on the last poweron from reset, or something "random" from a cold boot. Possibly "random" both times, either way it's not what you want. According to this, X would be zero on cold boot, and whatever it was last after a reset.

If you're used to other languages, you may potentially be used to the RAM being zereod out automatically by the compiler. This is not true on NES. You should assume that nothing is in a known state. For instance, after doing the above and a little more, you do this:

Code:
WaitForVBlank:
  lda VBlankOrNo ; A = VBlankOrNO
  cmp #1         ; if A == 1 then is VBlank

But VBlankOrNo is undefined the first time the program hits this, because it's never initialized.

Sprite 64 is not fully setup by your program.
Code:
 LDX #$00
LoadSpritesLoop:
  LDA sprites, x

  STA $0200, x
  INX
  CPX #$FF
  BNE LoadSpritesLoop

X is 0.
load data for sprites+x
Store it in $0200+x
X is 1
Compare X to #$FF
If equal stop.
This means through 0 to FE, the data under the sprites label is put in the same relative place to $0200, except for sprites+#$FF being put into $0200+#$FF.

This means $02FF is undefined for the entirety of the animation. On a real NES, a value in RAM at reset could be anything. So after resetting or powering on, the 64th sprite could move along the X axis.

I don't have time to check any more, but basically the problem is likely related to using variables (RAM) before initializing them. There may be smaller issues like the sprite one above, where you did try to initialize the RAM, but have an off by one error.

_________________
https://kasumi.itch.io/indivisible


Top
 Profile  
 
PostPosted: Fri Jul 04, 2014 10:58 am 
Offline

Joined: Wed Jul 02, 2014 12:00 am
Posts: 12
First off, sorry about the missing palettes. Ourpal: is a label referring to eclipse.pal, so there are just 2 .pal files included. I was a bit disorganized earlier this week due to a broken router, and had to copy files to my laptop. Secondly, thank you for your response :). I'm reviewing your post in more detail now, and will edit this post to respond soon.

Edit:

So I made some changes, mostly based on your recommendations. I think I have now properly initialized the "variables" and the 64th sprite. I moved some INX's, and removed that transfer instruction, and still had problems with later frames. Somehow I fixed the problem by adding a DMA transfer after loading sprites the first time.

Code:
LoadSprites:
  LDX #$FF
LoadSpritesLoop:
  INX
  LDA sprites, x
  STA $0200, x
  CPX #$FF
  BNE LoadSpritesLoop
  lda #$02
  sta $4014


I also put those 2 instructions after each frame. This fixed it, though I'm still trying to wrap my head around the concepts, my trial and error involving the DMA register seemed to help. So much information to absorb, I feel like my head is spinning. But the program works. Next I'd like to figure out how to load my frames via a loop. How would I go about writing such a loop, rather than having 10 near-identical labels? I want to add another 20 or so frames to the animation.

The working eclipse animation/source code is attached, if anyone wants to see it.

Thank you for your help so far Kasumi.


Attachments:
eclipse3.nes [40.02 KiB]
Downloaded 56 times
eclipse3.asm [11.12 KiB]
Downloaded 60 times
palettes.zip [287 Bytes]
Downloaded 48 times
Top
 Profile  
 
PostPosted: Fri Jul 04, 2014 10:21 pm 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1047
Quote:
Next I'd like to figure out how to load my frames via a loop. How would I go about writing such a loop, rather than having 10 near-identical labels?

With indirect indexed addressing and 16bit math.

Since you're using nesasm, you have to use [] instead of () for indirect indexed. First, you need two contiguous bytes in RAM that hold the address of the first frame. Note that the low byte must be "first" in RAM. That is have the lower address. (If your two bytes are $00 and $01, $00 needs to have the low byte. If your two bytes are $5D and $5E, $5D needs to have the low byte.) To initialize them, store the address of whatever the first frame is in those two bytes.

Code:
lda #low(frame1)
sta framelow
lda #high(frame1)
sta framehigh


To load the next frame, just add the framesize to the address. (Looks like 64 in this case.) This works because the address for the next frame is obviously (framesize) bytes greater than the previous frame if all frames are the same size, and if all frames are contiguous.
Code:
lda framelow
clc
adc #64
sta framelow

lda framehigh
adc #0
sta framehigh


To access the data, you used to do this:
Code:
lda frame1, x

This adds x to the address frame1 represents, then loads the value from the resulting address.
instead, you want to do this:
Code:
lda [framelow],y

This adds y to the address stored at framelow and framelow+1, then loads the value from the resulting address. So if framelow and framelow+1 (which should be framehigh if you've been following) contain the address for frame1, it's equivalent to lda frame1,y. If framelow and framelow+1 contain the address for frame2, it's equivalent to lda frame2,y.

If framelow and framehigh contain the address for frame1, adding 64 will make them contain the address for frame2. That is what to do, and why it works.

Note that you must use y for indirect indexed, so you'll have to change your code around since you are currently using X to access the frame data.

You do not necessarily need to use a compare to end a loop, because flags are set after each instruction.

Code:
LoadSprites:
  LDX #$00
LoadSpritesLoop:
  LDA sprites, x
  STA $0200, x
  INX
  BNE LoadSpritesLoop

This works because inx will set the zero flag if it the addition of one caused X to be equal to zero. It will clear it if the addition of one caused X to be different than zero.

You start X with zero. Load and store the zeroth element. INX is hit, making X equal 1. Which is not equal to zero, so it goes back to the start. (Notice that we did zero, but incremented X before the check for 0)
It's now at 1. Load and store the first element. INX is hit, making X equal 2. Which is not equal to zero, so it goes back to the start.
etc.
It's now at 255 ($FF). Load and store the 255th element. INX is hit, making X equal 0. The loop completes without even doing zero twice.

This change seems small, but it's a good thing to recognize. Each instruction you run takes a little bit of time. Because of the loop, that compare was done 256 times which is a lot of extra time on such a weak processor. You can avoid it completely.

Edit: For something like this, I would use binary files instead of .db statements.

Code:
frame1:
.incbin "frame1.bin";A 64 byte file
.incbin "frame2.bin";Another 64 byte file
;etc

Or rather than have a separate file for each frame, you could just include one file with all that data, and the indirect indexed thing would work the same anyway.
Code:
frame1:;just preserving the name to work with the example above
.incbin "animationdata.bin";A 64*howevermanyframesthereare byte file


edit2:

Quote:
Somehow I fixed the problem by adding a DMA transfer after loading sprites the first time.

Some of the problems you're experiencing make me think you're testing on a real NES. Are you?

Anyway, you probably want to do a sprite DMA every frame (and not just every time it changes), becuase the RAM used to hold the information about sprites in the PPU degrades.

And woah, looking at this, I just found something scary in your code.

Code:
.org $FFFA
  .dw NMI
  .dw Start
  .dw 0

and
Code:
  .org $FFFA
  .dw VBlank_Routine
  .dw Start
  .dw 0

It's uh... certainly possible and okay to have different things in your vectors, but I don't think you meant to in this case.

Your routine called VBlank_Routine literally never runs, because your rom apparently assembles with the address for NMI at $FFFA.

Which... in fact leads me to find further stuff I'm not sure you meant to do... Like VBlank_Routine is totally designed to break this loop:

Code:
WaitForVBlank:
  lda VBlankOrNo ; A = VBlankOrNO
  cmp #1         ; if A == 1 then is VBlank
  beq WaitForVBlank ; if not VBlank, then loop and do again
  dec VBlankOrNo ; 1-- or VBlankOrNO - 1 . VBlankOrNo will be 0 again.

Your program would get stuck in that loop if it didn't (and the loop was in the right place). But... remember that VBlank_Routine is NEVER run.

The program doesn't crash because that loop isn't in the right place. It should be underneath infin, so that you wait for vblank every frame. But then your program would crash, because VBlank_Routine is never run to change it after the first time. VBlankOrNo would stay zero basically. To fix that, delete VBlank routine and the extra set of vectors (the .org $FFFA and three .dws after) and move inc VBlankOrNo to NMI. Then move that loop to below infin.

Actually, this might explain a lot of the random corruption you're getting. Basically your program isn't updating things at the start of a frame, because the thing that detects the start of a frame is not in the main loop of the program. So the sprites could be getting drawn to the screen when the CPU isn't done updating them.

There might be more odd stuff about this program's structure, but once again I gotta go.

_________________
https://kasumi.itch.io/indivisible


Last edited by Kasumi on Fri Jul 04, 2014 11:36 pm, edited 2 times in total.

Top
 Profile  
 
PostPosted: Fri Jul 04, 2014 11:10 pm 
Offline

Joined: Wed Jul 02, 2014 12:00 am
Posts: 12
That's a lot of great advice, and something I will work towards implementing soon. I'll post back here with what I cobble together.

Kasumi wrote:
Edit: For something like this, I would use binary files instead of .db statements.


Is there an easy way to create these binary files from an array of info in a text document, such as my current DB statements? Aside from reinventing the wheel myself by creating a program that makes it (or manually hex editing), I have a feeling several others have created a program to do this. I found an old one a while ago designed for just this purpose, but it didn't work properly on Windows 7(64bit) for me at the time.


Top
 Profile  
 
PostPosted: Fri Jul 04, 2014 11:27 pm 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2983
Location: Tampere, Finland
insomniakc wrote:
Is there an easy way to create these binary files from an array of info in a text document, such as my current DB statements? Aside from reinventing the wheel myself by creating a program that makes it (or manually hex editing), I have a feeling several others have created a program to do this. I found an old one a while ago designed for just this purpose, but it didn't work properly on Windows 7(64bit) for me at the time.

That's pretty much what an assembler does. Just run your .db statements through it and you get a binary file. Unless you have a real reason to use binary files, though, you can just keep on using .db statements.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Fri Jul 04, 2014 11:30 pm 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1047
First off: Check the "edit2" I just made to the previous post. Your program has quite a few fundamental issues I didn't notice because it basically runs fine. But when I looked into it to give you other advice, I started to see a lot of stuff.

Quote:
Is there an easy way to create these binary files from an array of info in a text document, such as my current DB statements?

I'm sure there is one that does specifically that, but I don't know it offhand. I actually made a thing that converts comma separated decimal numbers into a binary file specifically because it seemed like it was taking me longer to find a thing that did it for me (with no hassle/install) than it would take to write one.

That said, if you're already hand typing the stuff into a text document, hand typing into a hex editor isn't much better/different. (As the thefox said when he ninja'd me) XVI32 will let you paste a space separated hex string from the copy buffer (Like "0D FF 04" etc.) if you use edit, clipboard, paste from hex string, though. But again, not too much benefit. I guess I'm sorry I mentioned it.

I kind of assumed you already had written some sort of program, instead of hand typing the .db statements. The whole animation creation process could be automated, including the conversion of whatever moon thing you're using to 3 colors/creating the sprite tile info from the frames.

_________________
https://kasumi.itch.io/indivisible


Top
 Profile  
 
PostPosted: Sat Jul 05, 2014 6:03 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2983
Location: Tampere, Finland
Kasumi wrote:
XVI32 will let you paste a space separated hex string from the copy buffer (Like "0D FF 04" etc.) if you use edit, clipboard, paste from hex string, though.

On the topic of hex editors, I have to say that HxD is vastly better than XVI32.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Sat Jul 05, 2014 9:01 am 
Offline

Joined: Wed Jul 02, 2014 12:00 am
Posts: 12
Kasumi wrote:
First off: Check the "edit2" I just made to the previous post. Your program has quite a few fundamental issues I didn't notice because it basically runs fine. But when I looked into it to give you other advice, I started to see a lot of stuff.


Edit 2 certainly does clarify some things for me that I was unsure of regarding the VBlank. I'm starting to move away from the copy-pasting I did on the heartbeat animation, which also runs fine and has a ton of issues. The information from the nerdy nights tutorials I did last summer is sinking in slowly as I find more information which relates. So right now I'm at about 75% comprehension of what I am actually doing, but I'm enjoying it.

I'm actually not testing on a real NES right now, though I would like to someday. I'm finding all kinds of books and stuff on 6502 assembler which is distracting me from this little project but also helping me figure things out. And speaking of automation, I've already created a macro to convert my higher res cartoony moon images into 8 bit appropriately sized images and used tile layer pro to import them and TLP/YYCHR at different times to touch them up a bit after converting them to 4 colors. My question, since you have intrigued me by mentioning this, is how would I convert a batch of 300 8 bit bmp images into 4 colors using some sort of automated process? I could do it with a macro and TLP, but I kind of don't like the way the images come out. A lot of space is converted black that I manually have to touch up. It would make my life easier. Also, I'd love a way to automate sequencing the tiles in order that they are accessed in memory rather than the way TLP does it. I have to manually move each tile, the way I'm doing it now.

As for all the programming advice, it'll take me a few days to really implement all of this, since my attention is a bit divided at the moment. Also, thanks Kasumi and thefox for the useful tools, I will check both of them out.

edit:
I included the source and .nes for my heartbeat, which I used as a starting point for this eclipse. Just bear in mind I created these about a year ago, so I am not really working on them at the moment, and all your advice from the Eclipse applies to them, just thought I'd share for anyone who wants to see a poorly coded 8 bit animated heartbeat that actually works smoothly :).


Attachments:
heartbeat.nes [24.02 KiB]
Downloaded 60 times
heartbeat.asm [7.91 KiB]
Downloaded 50 times
Top
 Profile  
 
PostPosted: Sat Jul 05, 2014 10:26 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19356
Location: NE Indiana, USA (NTSC)
insomniakc wrote:
I've already created a macro to convert my higher res cartoony moon images into 8 bit appropriately sized images and used tile layer pro to import them and TLP/YYCHR at different times to touch them up a bit after converting them to 4 colors. My question, since you have intrigued me by mentioning this, is how would I convert a batch of 300 8 bit bmp images into 4 colors using some sort of automated process?

I'd do the conversion in a paint program, which produces BMP or PNG sprite sheets that you can feed into any BMP-to-CHR program such as the one that comes with my ca65 project template.


Top
 Profile  
 
PostPosted: Sat Jul 05, 2014 10:58 am 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1047
Quote:
My question, since you have intrigued me by mentioning this, is how would I convert a batch of 300 8 bit bmp images into 4 colors using some sort of automated process?

Can do it with irfanview. File, batch conversion, choose your output format, check advanced options, change color depth, 4 colors, browse to the folder where the 300 images are stored and hit add all. Then choose the output folder, and click start batch.

I'm sure here's a way with ImageMagick as well. It can do whatever to images. (But I don't know a method offhand.)

edit2: Then I suppose use Tepples' thing linked here: viewtopic.php?f=22&t=7991
I should say what I meant when I said it could be automated was that it is a task that requires no thinking a computer couldn't do, not that tools necessarily already exist to do specifically this in one step fashion. The more specific the needs, the harder it is to find a random program that'll do it. But task that would take me longer to do than write a program for, I'd write a program for. I am not sure what other languages you might be familiar with, though.

edit:
Quote:
Also, I'd love a way to automate sequencing the tiles in order that they are accessed in memory rather than the way TLP does it. I have to manually move each tile, the way I'm doing it now.


In any case, could you be more specific about how TLP does things (I've never used it, and downloading it won't help me see what happens for this specific task anyway), and what you actually want? Maybe there exists a thing, or maybe it's easy to write.

_________________
https://kasumi.itch.io/indivisible


Top
 Profile  
 
PostPosted: Sat Jul 05, 2014 6:38 pm 
Offline

Joined: Wed Jul 02, 2014 12:00 am
Posts: 12
Well just say you have 16 columns of tiles in TLP and you import an 8 tile by 8 tile image into the program, it will preserve the image rather than sequencing the tiles so this diagram represents what I get (00 is just an empty black tile, or whatever was there when I imported)

01 02 03 04 05 06 07 08 00 00 00 00 00 00 00 00
09 0A 0B 0C 0D 0E 0F 10 00 00 00 00 00 00 00 00
10 11 12 .. .. ..

So then I need to drag tile 09 next to tile 08, and so forth to fill up the black spaces and not waste CHR table space, and to prevent making my life figuring out what tile is next while programming a real headache. I spent about 3 hours for this eclipse on menial tasks that you folks have shown me better methods for, aside from this whole drag and drop circus. It's like doing a puzzle backwards...

And by the way, I'm stunned by the amount of support I'm getting. Thank you! *bow's head*


Top
 Profile  
 
PostPosted: Sat Jul 05, 2014 7:11 pm 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1047
So if I'm understanding correctly I can think of thing that can help you do that, but it won't save you all that much time anyway. PyxelEdit (note the free version at the bottom) can identify duplicate tiles and will tell you which tiles make up your image by mousing over them. (It can even dump an actual map of tile numbers for the image. i.e. the data you have underneath each frame label. In fact this program is the reason I made the comma separated decimal number to bin converter I mentioned earlier ) However, it doesn't work with CHR.

So your process is like...
1. Convert moon images to 4 color BMPs.

Then...
1. Import frame image to PyxelEdit.
2. Get rid of duplicate tiles.
3. Dump tile map for that frame.
4. Import next frame image to PyxelEdit.
5. Get rid of duplicate tiles.
6. Dump tile map for that frame.
Do this for as many frames as you can until you have a tileset of 256 (or enough that the next frame will push you over 256)
7. Export the tilemap.
8. Convert that to CHR.

Which is...pretty yikes, honestly.

It would be absolutely be faster to make a thing specifically suited for the task rather than doing this 300 times. But faster != fast i.e. At least I am not willing to make it for you.

Maybe I have an idea. You could create a "sprite sheet" of all 300 images. (So basically one 64x19200 image)

Import that to PyxelEdit. Find out which is the first frame that uses a tile greater than 256. (you'd have to check manually, but that's not that bad, since the program can display which tiles are being used if you press tab.)

Truncate the image to the frame before the first that uses one greater than 256. Export the tileset (and convert to CHR), dump the tilemap numbers. You now have all the info needed to recreate those frames in the rom, and also know how many frames before you need to swap tilesets.

Remove those frames from your sprite sheet. (So... if 8 frames fit in one tileset, you now have a 64x18688 image that starts at the frame that pushed you over the tile limit.)

Import into pyxeledit. find out... (repeat the steps above basically)

That sounds... better, but better doesn't mean good. :lol: Anyway, you can create/import/truncate spritesheets pretty easily with ASEPRITE. (Once again, note the free version. Both of these programs are paid software that are nice enough to let you get an old version) Does this sound any better than what you planned to do? If so, I'll write you steps on how to do the spritesheet stuff in ASEPRITE as well, assuming no one is nice enough to just write a program to do all this in one step.

PS: I totally checked and ASEPRITE does indeed support cutting up a 64x19200 indexed spritesheet. PyxelEdit probably wouldn't be able to import it, but no biggie. You could just export the first 20 frames or so, since that'd be guaranteed to fill the limit anyway.

Either way, good luck. Sorry my posts are always so long.

_________________
https://kasumi.itch.io/indivisible


Top
 Profile  
 
PostPosted: Sat Jul 05, 2014 10:24 pm 
Offline

Joined: Wed Jul 02, 2014 12:00 am
Posts: 12
Hey, not a problem, no need to apologize. I like long posts.

I think before I do all of that I'm going to identify which frames are too similar and cut them out. I should end up with 60ish frames that are actually different enough, that'll make my life easier, and all the things you have suggested. I've already set to work. You've given me enough to fill up my spare time for a while :). Perhaps once my programming abilities are better I'll make a tile sorting program, but for now I'll stick with what's available. You've increased my repertoire of programs for my purposes, so thanks for everything so far.


Top
 Profile  
 
PostPosted: Sun Jul 06, 2014 7:53 am 
Offline

Joined: Wed Jul 02, 2014 12:00 am
Posts: 12
Kasumi wrote:
Quote:
Next I'd like to figure out how to load my frames via a loop. How would I go about writing such a loop, rather than having 10 near-identical labels?

With indirect indexed addressing and 16bit math.

Since you're using nesasm, you have to use [] instead of () for indirect indexed. First, you need two contiguous bytes in RAM that hold the address of the first frame. Note that the low byte must be "first" in RAM. That is have the lower address. (If your two bytes are $00 and $01, $00 needs to have the low byte. If your two bytes are $5D and $5E, $5D needs to have the low byte.) To initialize them, store the address of whatever the first frame is in those two bytes.

Code:
lda #low(frame1)
sta framelow
lda #high(frame1)
sta framehigh


To load the next frame, just add the framesize to the address. (Looks like 64 in this case.) This works because the address for the next frame is obviously (framesize) bytes greater than the previous frame if all frames are the same size, and if all frames are contiguous.
Code:
lda framelow
clc
adc #64
sta framelow

lda framehigh
adc #0
sta framehigh


To access the data, you used to do this:
Code:
lda frame1, x

This adds x to the address frame1 represents, then loads the value from the resulting address.
instead, you want to do this:
Code:
lda [framelow],y

This adds y to the address stored at framelow and framelow+1, then loads the value from the resulting address. So if framelow and framelow+1 (which should be framehigh if you've been following) contain the address for frame1, it's equivalent to lda frame1,y. If framelow and framelow+1 contain the address for frame2, it's equivalent to lda frame2,y.

If framelow and framehigh contain the address for frame1, adding 64 will make them contain the address for frame2. That is what to do, and why it works.

Note that you must use y for indirect indexed, so you'll have to change your code around since you are currently using X to access the frame data.


I've been working on the suggestions I just quoted from you and I have created a bit of a mess with my graphics. The first frame loads, I can tell because I see it flash on the screen, but the successive frames are just nonsense. I am probably doing things in the wrong order, or have misunderstood something. I'll paraphrase your post first so you can correct my understanding of what you said.

So I need to use indirect indexed addressing in order to access $E0FF to read the first frame from my new binary file of frame data. To do this I need two contiguous bytes in RAM that hold address $E0FF. framelow holds $E0 and framehigh holds $FF. My code for this is

Code:
   lda $FF
  sta framehigh
  lda $E0
  sta framelow


Then I add 64 to the low byte and add (0+carry) to the high byte in order to increment the address that is being accessed by 64, and repeat the loop to transfer frame data to the PPU, and the DMA register.


So I thought this is what I did when editing my program, but I'm getting just the first frame, then a mess of tiles. I feel like this has something to do with things being done in the wrong order. Also, I'm aware that I have it set to cycle indefinitely through memory, though this code is incomplete (just wanted to see the first couple of frames load before adding bank switch, etc).


Attachments:
eclipse4.nes [40.02 KiB]
Downloaded 62 times
frames.bin [640 Bytes]
Downloaded 49 times
eclipse4.asm [5.03 KiB]
Downloaded 57 times
Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Bing [Bot] and 2 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