It is currently Fri Nov 17, 2017 12:41 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 49 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject:
PostPosted: Mon Jan 18, 2010 4:49 am 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 1518
Location: Fukuoka, Japan
For now I just delay it a few frames so if you press "just enough" and release the button, it will move one pixel. This is the code I did before I started to re-factor with velocity. This part has an impact then.

For the information about how much pixel to move in X condition, I found that site useful, a TAS side about Mega man. There was a lot of interesting tidbits there.

Regarding the jump, I didn't saw it yet maybe because I was focusing more on the scrolling to work properly. I knew people would argument more on small details since I try to reproduce a mega man's game but that was to be expected ;) Either the collision logic is wrong for floor or the frames for the jump animation is not centered properly, causing it to enter the floor. The jumping frame is taller than the usual ones so I will need to check the data.

edit:

Tested all nes version of mega man very fast and for the jump, 1 to 5 doesn't enter the floor but 6 does (why). One thing they all do but I don't is that before touching the floor, they go 1 frame in running state then stop moving. In my own code, if there if no button pressed, I go standing right away, if not, I just run. I guess they did it that way to simplify the logic. I may change it later too if it does make it simpler.

For the tapping, all of them are sensible to different degree (less in earlier ones and more later on), more then my current build so I will take that into consideration.

Edit2:

In MM9, Mega man's feet do enter the floor so it is "faithful" to the original hmm.. So it becomes more a matter of taste. For the tapping, it is quite sensible so this is a fix for sure. But the "landing in the feet in the ground" bug, if we can call it that way, doesn't have much impact on game play so I will think about it if I should improve MM9 or stick to the way it is ;)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 18, 2010 6:28 am 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 1518
Location: Fukuoka, Japan
Sorry for the double post since I think that question should be in that thread anyway. I still have all kind of small bugs to fix but I think now I'm ready for the next step. I need to scroll vertically. A normal scroll is not really an issue IF there is no gap between the screens (...). MM9 doesn't have 16x15 metatiles per screen but 16x14... So either you create new data or you will have to be fancy with the raster effect during scrolling to hide the black tiles.

This is how the map looks like at the moment:

Image

This screenshot from fceux, as you can see, there is a gap between the 2 screens. Now what I want to know is (and I think we talked about it a little before and maybe it was Tokumaru that was giving ideas on the subject), can I do some raster effect to skip the empty spot while scrolling? I guess that must be possible since people used raster tricks to show some info bar or something. I don't mind to use any IRQ if I have to since it's just a proof of concept anyway. If I don't need then even better. I don't mind using any mapper to do it but first, is it possible at all? I think the answer is yes but I'm not sure yet how.

For the people that likes details, I changed the logic for the tapping by using velocity. The new build is here. I think it's better now ;)

Edit:
After retesting the build, the tapping could be a little bit too fast. I may have to adjust the ratio to something slower but that's not a difficult task now that it's working.

Edit2:
Updated the build again to be slower for tapping. Just updated this message since it was not worth it to make new one.


Last edited by Banshaku on Mon Jan 18, 2010 6:44 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 18, 2010 6:40 am 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19220
Location: NE Indiana, USA (NTSC)
It's possible to skip the gap without a raster effect by only scrolling 224 pixels. The most obvious way complicates map updates: you're splitting map writes across the bottom and top of the nametable all the time.

But if you want to simplify your map update routines, use a sprite 0-triggered scroll split.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 18, 2010 6:46 am 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 1518
Location: Fukuoka, Japan
I guess I'm not in the mood for re-factoring (again) the scrolling so I will investigate the sprite-0 hit since it will really simplify the nt update. There must be a sample somewhere, hopefully on the wiki or is it?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 18, 2010 7:04 am 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19220
Location: NE Indiana, USA (NTSC)
Banshaku wrote:
I guess I'm not in the mood for re-factoring (again) the scrolling so I will investigate the sprite-0 hit since it will really simplify the nt update. There must be a sample somewhere, hopefully on the wiki or is it?

stuff by Damian Yerrick: My "Tall Pixel" demo does a scroll split every 3 scanlines, and it works on my NES+PowerPak.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 18, 2010 7:34 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7265
Location: Chexbres, VD, Switzerland
Banshaku wrote:
Tested all nes version of mega man very fast and for the jump, 1 to 5 doesn't enter the floor but 6 does (why). One thing they all do but I don't is that before touching the floor, they go 1 frame in running state then stop moving. In my own code, if there if no button pressed, I go standing right away, if not, I just run. I guess they did it that way to simplify the logic. I may change it later too if it does make it simpler.


This is what I was talking about. Sorry, but I think it's very important you make Mega Man landing correctly. It really makes the animation smoother to have it landing on both of his feet before standing up. You do that when you jump in real life too (you absorb the energy in your knees instead of your back).

I don't know what to suggest for the vertical scrolling. A raster effect is certainly possible (writing $00 twice to $2006 when you'd encounter the "black bar" should do the trick) - the hard part is that the time you'd do the write will scroll across the whole screen so you'd want to wait for the sprite zero hit BEFORE the frame logic if it's in the first half of the screen, and AFTER the frame logic if it's in the lower half. This assumes the frame logic takes less than 50% of the CPU.

Otherwise I'd say create data for 15 rows or just deal with 14 rows and non-aligned level to nametable - I deal with screejs non-aligned vertically with nametable in my game, but aligned horizontally, as it would be your case. You just need a few more variables to know where the topleft of the screen is in the nametable, and code able to split attribute blocks in lower/upper half.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 18, 2010 2:50 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10112
Location: Rio de Janeiro - Brazil
Banshaku wrote:
Updated the build again to be slower for tapping.

Ah! That's more like it! =)

tepples wrote:
It's possible to skip the gap without a raster effect by only scrolling 224 pixels. The most obvious way complicates map updates: you're splitting map writes across the bottom and top of the nametable all the time.

I was gonna suggest the same thing, because I don't know if you can guarantee a sprite 0 hit every time (what if a particular screen has transparent background where the hit is supposed to happen?).

Banshaku wrote:
I guess I'm not in the mood for re-factoring (again) the scrolling

I just though of a trick that won't require any refactoring, or IRQs. I looked at how MM1 does it, and it first decodes the new screen horizontally (apparently the decoding is meant to work horizontally only) to the hidden NT, and then copies it to the visible one row by row as the screen scrolls up. What if you do the exact same thing, but when copying from the hidden NT to the visible one you skip the unused row?

What I mean is, the screen that is decoded to the hidden NT is perfectly aligned vertically, but when you copy it for the scrolling sequence the copy is not aligned, but once the scrolling sequence is over you can set the scrolling to show the other NT where you copied the data from, which IS aligned vertically, so you can continue scrolling from it without a single change to your scrolling engine.

Let me show it with drawings, which are much better than words. Here is Mega Man going up some stairs:

Code:
+------------+------------+
|  (hidden)  |           -|
|            |           M|
|            |           -|
|            |           -|
|            |FFFFFFFFFFFF|
|            |FFFFFFFFFFFF|
|            S............|
+------------+------------+

The floor is "F", Mega Man is "M" and "............" is the blank row of blocks. The left NT is hidden because the scroll is at "S". OK, when MM touches the top of the screen, you decode the screen that goes on top of the current one to the hidden NT like this:

Code:
+------------+------------+
|           -|           M|
|  -FFFFFFFFF|           -|
|  -         |           -|
|  -         |           -|
|  FFFFFFFFF-|FFFFFFFFFFFF|
|  FFFFFFFFF-|FFFFFFFFFFFF|
|............S............|
+------------+------------+

Yup, with the blank row at the bottom, so it's aligned as your scrolling engine likes it. Now you copy the contents of the hidden NT to the visible one row by row as you scroll up, but shifted one row down so that there is no empty row between the screens:

Code:
+------------+------------+
|           -S............|
|  -FFFFFFFFF|           -|
|  -         |  -FFFFFFFFF|
|  -         |  -         |
|  FFFFFFFFF-|  -         |
|  FFFFFFFFF-|  FFFFFFFFF-|
|............|  FFFFFFFFFM|
+------------+------------+

So now you've scrolled to the top and the whole new scree is visible, but it's not vertically aligned to the NT, but the left side is perfectly aligned and has the same contents, so you can just move the scroll to it and continue as if nothing happened:

Code:
+------------+------------+
|           -|............|
|  -FFFFFFFFF|           -|
|  -         |  -FFFFFFFFF|
|  -         |  -         |
|  FFFFFFFFF-|  -         |
|  FFFFFFFFFM|  FFFFFFFFF-|
S............|  FFFFFFFFF-|
+------------+------------+

Mirroring is set to vertical all the time, no need to change it.

The thing you do have to worry about no matter what solution you pick (sprite 0, IRQs or my suggestion) are the black borders. You do have a black border at the top, but when scrolling you want the next screen to connect to the current one without gaps. With whatever method you use, the black border will turn into actual tiles when scrolling vertically, and once the scrolling is done the borders will come back. I guess the only way to avoid this is using IRQs to mask the top and bottom 8 scanlines, but IMO this is a lot of work and you're better off simply accepting some garbage at the edges (which several official MM games have - not 9, for obvious reasons).

Oh, one thing I forgot to mention about my method is that although the rows of tiles can be copied directly from one NT to the other, you will need to do some nibble work on the attributes, but honesty, that shouldn't be hard at all.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 18, 2010 5:51 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10112
Location: Rio de Janeiro - Brazil
OK, I gave some more thought to my idea and I think I have the answer. I don't know at what rate (how many pixels per frame) the original game scrolls vertically, but if you are OK with 8 pixels per frame, my method can work without any glitches.

Here's an animated GIF of the process:

Image

I saw that you already have the new screen completely decoded by the time MM reaches the ladder, so it will be even easier. Every frame you copy a row of tiles from the hidden NT to the visible one, and blank the two scanlines immediately above it (this will keep the top and bottom 8 scanlines of the screen always black). Just do this until all rows are copied (you don't need to copy the 2 blank ones, because you are already blanking 2 rows above the each one copied).

The only thing that's slightly complicated about this process is that attributes can't be directly copied from one side to the other because the screens are offset by half an attribute block. So every 2 rows of tiles copied from the hidden side you have to take the corresponding attribute bytes, move the nibbles to the other half of the byte so that they can be inserted at the correct place in the other NT. Not complicated at all really, just slithly annoying to code.

Well, this is it. If you think 8 pixels per frame is OK when scrolling vertically I'm sure this is the most straightforward way to do it, and much easier than messing with sprite 0 hits, IRQs and mid-frame scroll changes.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 19, 2010 3:09 am 
Offline
User avatar

Joined: Tue Aug 19, 2008 11:01 pm
Posts: 186
Location: Japan
That's a really cool trick tokumaru. I never would have thought to use one nametable to scroll and then flip the scroll to an aligned copy.

_________________
MetalSlime runs away.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 19, 2010 4:50 am 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 1518
Location: Fukuoka, Japan
@Bregalad:

I should be able to add this extra running frame when mega man land. The frame is so fast that you have a hard time to see it, if you ever see it at all thought. I only saw it when doing some frame per frame analysis with Nintendulator. I never could discern it in the real MM9 jumping animation but I could be wrong. It's a small fix so I will do it for the sake of completeness.

@Tepples:

I checked the code and it seems to rely on precise timing to do the job. There is no code in the NMI or anything else. What would happen if you use this trick with a sound engine and other things running in the nmi a the same time, hmmm..

@Tokumaru:

Like you mentioned and I remember seeing it once while testing it, MM1 does a similar trick for scrolling. I will think about it as one possibility. The only draw back is now you have to keep track of the starting location of the map to re-adjust the scroll so you won't see the black bars. This affect the metatile column drawing a little bit.

Edit:

For the screen already decoded, I didn't do much. I saw that MM2 always had one screen decoded in advance before scrolling. I did the same thing by adding every row of the second map data just after the first map row. So when you reach the end of the screen, it's ends up decoding the next one without asking anything.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 19, 2010 5:35 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10112
Location: Rio de Janeiro - Brazil
Banshaku wrote:
The only draw back is now you have to keep track of the starting location of the map to re-adjust the scroll so you won't see the black bars. This affect the metatile column drawing a little bit.

I must admit I don't understand what you mean here.

You mean that if you move the X scroll to the hidden NT it will be desynchronized with the X coordinate of the camera? If this is it, maybe after you switch the scroll to the hidden NT you could copy the data to the other (now hidden) NT again, but this time vertically aligned, and switch back to it.

I believe that the NES games have a pause before scrolling and after scrolling, so you could easily use the second pause for this second copy process.

If this is not what you meant, I'm lost. I can't see what the start of the level has to do with the black bars.

Quote:
For the screen already decoded, I didn't do much. I saw that MM2 always had one screen decoded in advance before scrolling. I did the same thing by adding every row of the second map data just after the first map row. So when you reach the end of the screen, it's ends up decoding the next one without asking anything.

That works great for the first vertical screen after a few horizontal ones, but you still have to think of a way to load the vertical screens after the first in advance too... Maybe you can load the next vertical screen as soon as the scroll sequence to the current one finishes.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 19, 2010 6:22 am 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 1518
Location: Fukuoka, Japan
I guess my comment is quite unclear actually and I should rephrase it. What I meant is in map 1, the black bar is at the bottom. So you have to scroll the Y at $E8 to split it as 1 tile row at the top and one at the bottom to hide them. When you write the next map this way, 2 small things changes (but not big): the black bar is now at the top and where you will need to start to write metatile in the NT changed too. So you have to keep track of those 2 details. It's a very small compromise that could simplify a lot of the screen transition so I will consider this scrolling system since it quite simple.

For the buffering of the next map, this was just a test I did so I could start to try to do some quick experimenting for map transitions. I'm not sure if I will keep it that way. In MM2, when the screen finish to scroll, the next possible screen is loaded in the hidden NT. Maybe I should try to check what MM1 did since the process was similar.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 19, 2010 7:49 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10112
Location: Rio de Janeiro - Brazil
Banshaku wrote:
When you write the next map this way, 2 small things changes (but not big): the black bar is now at the top and where you will need to start to write metatile in the NT changed too. So you have to keep track of those 2 details.

But the whole point of the trick is that in the end you move the scroll to the hidden NT (see the green frame at the end of the animation I posted), which has the black bar at the bottom, like it was supposed to be, so you don't have to mess with the metatile rendering at all.

Look at the animation carefully, because I don't think you understood the trick. =) The idea is to leave your current rendering completely untouched, you'd only have to code a new routine to copy the hidden NT to the visible one row by row (but shifted 2 rows down) and at the end switch to the hidden NT, and from there you can continue as normal, the black bar will still be at the bottom.

The trick is that by the end of the scrolling sequence both NTs contain the same thing, the screen that just scrolled in. The one at the right is not aligned to your map rendering engine because we had to skip the black bar so that the screens would connect, but the one on the left is aligned to your scrolling engine, so you can just switch to it, the player will never notice the switch because the exact same contents will be displayed.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 19, 2010 8:08 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7265
Location: Chexbres, VD, Switzerland
Well I also never fully understood how MM1 and MM2 scrolls, but I guess they do the following :
- When scrolling horizontally, always load data from the next screen and write it to VRAM (even if it's impossible to scroll to it)
- When finished fast-scrolling vertically, load data from the following screen so that it's ready to scroll horizontally.

I don't think it ever "copies" data from one nametable to the other - it just happen that when scrolling vertically the data from the map above or below the one Megaman was is already in VRAM. In fact there is some case in MM2 where this is not the case I belive. I might be wrong tough.

Aside of that tokumaru's suggetion is a good one if you don't want to add a 15th row. Altough you'd need a piece of code to write metatiles one row lower (which implies crossing attribute nybbles) - but that's nothing really overcomplicated I think.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 19, 2010 8:29 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10112
Location: Rio de Janeiro - Brazil
Bregalad wrote:
I don't think it ever "copies" data from one nametable to the other - it just happen that when scrolling vertically the data from the map above or below the one Megaman was is already in VRAM.

I assumed it was copying because if you look at the NT viewer in FCEUXD when going up ladders in MM! you can see that the next screen is quickly loaded to the hidden NT horizontally (that's the pause before the vertical scroll), then the exact same data is written to the visible NT as the vertical scroll happens.

Then, when the vertical scroll finishes, the scroll is set to display the previously hidden NT and the one that was used during the vertical scroll is loaded with the next screen (that's the second pause).

Now, if it's actually copying from one NT to the other I don't know. I set up a breakpoint for $2007 reads and in fact it does happen during the vertical scroll, but it seems to be reading just 2 bytes per frame, not a lot of data, so maybe it's just doing it for the attributes or something.

If it was my game, I'd copy from the other NT. There is enough time in VBlank to read a row of tiles from a NT and writing it to the other, and it's much easier to copy this already decompressed data than to make a different map decoding routine that outputs rows rather than columns.

Quote:
Altough you'd need a piece of code to write metatiles one row lower (which implies crossing attribute nybbles) - but that's nothing really overcomplicated I think.

Like always, attributes are a pain to handle, but shifting them 1 nibble down isn't so hard.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 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