Post subject: Donald Land
Editor, Experienced Forum User, Skilled player (1176)
Joined: 9/27/2008
Posts: 1072
Dream Team Contest #7 had chosen this title. Now that it is concluded, I figure now's a fine time to explain a few things. The winning movie. There's a lot of details I'm skipping over. I won't mind anyone asking, to try to drag out every bit of information out of my head as needed. I'm tired now, so this is just what you get for my initial post. Stage 1 - Home Town World This is the only time we're without the apple power-up, which allows us to have two apples out at once. This is rectified in our very first jump. Not a lot to say, really. Boss goes poof in one hit. Stage 2 - Lake Side World A lot of the stage has us over flat ground. There is a very useful apple dropping pattern where we're in almost constant boosted speed. The boss takes four hits to take down. We don't understand its ouch animation, but somehow found hits that don't trigger it. It's a lot faster than waiting out the animation. Stage 3 - Forest World We drop down toward the bottom of the screen and fly on apples down there. We stay in boosted speed for as long as we have the freedom to stay there. Toss two apples on occasion, three frames apart, so that we can follow them down instead of instantly jumping off of them (and continue to gain too much height). The "boss" would shoot giant instant-death fireballs, but it turns out a magic tile is always available to touch. Actually, it's lucky that mouth animation produces the magic tile for us, or we'd be stuck waiting for the stage to load it in. The magic tile isn't checked for earlier in the stage, so even if its ID existed in Stage 2, landing on it then wouldn't skip Stage 3 for us. Stage 4 - Sky World That balloon stage. Exonym did most of the trickery here. The zips at the end were my work, though. Basically, there are magic pixels the game looks for 12 pixels left and right of the player's feet. If we have any left or right speed, we can trigger a zip. But we need to manually move to the right for each tile zip to give some distance so we don't bump into the same tile as before. Also, I intentionally slow down the zips in order to stay away from the "latest pixel" and therefore delay the loader. This is to keep a magic tile we need for skipping Oasis World. Of note, I haven't spent the time to ensure I went from "slow tile zip" to "fast tile zip" as early as possible. I think we can get one more "fast tile zip" in there, as we have a little loading time to spare, considering how many loaded tiles are left before we overwrite the 0x79 one we need. The boss itself would have a weakpoint tile load in, so that we can damage it. Our zipping stopped that. So instead, we have to rely on the fact the game reads tiles "out of range" with apples in the status HUD above. The screen is aligned with the half where it uses garbage tiles, based on some tile loader the game does. The boss mouth animation occasionally has its weakpoint tile IDs show up there. Single frame windows to land the apple, but single frame windows are just another day in TASing, as we know. Stage 5 - Oasis World We need to touch the magic tile 0x79 in order to reach the boss. Thanks to the fact the game keeps the last tile we touched in memory and uses it before updating it on the first frame means this paragraph is longer than the whole stage. Standard boss kill. The apple boost at the end does speed up the cutscene slightly, while also lasting to the first frame of the next. Stage 6 - Cave World We're limited by the stage loader because of these magic tiles we need to touch. There isn't any way to touch one we need at the end of stage 5 like we did to skip that stage, and they will only load in at the end of each segment. Therefore, the best strategy is to trigger the loader ASAP, putz around waiting for the loader at an average speed of 16 pixels per 7 frames, touch the magic tile ASAP. We despawn enemies to guarantee low lag. Standard boss kill. Yep, that wraparound on the left? Definitely standard. The apple boost seems to keep working during the cutscene. Stage 7 - Pond World There's a 4-pixel gap every 128 pixels. If we're at a pixel just before this gap, and manage to get at a pixel on the other side of this gap with a speed somewhere above 4 pixels/frame, we skip spawning enemies. This is critical, as there are cutscene crocs which freeze us in place while the croc shows itself. But they depend on these spawning gaps like other enemies, for some reason, so we skip 'em. The boss extends depending on a global timer. Apparently, if it is killed during the extension, it warps off the top of the screen and disappears much sooner. We weren't successful for the run, though, thanks to the global timer being just a little too fast for us. Saving a few frames anywhere earlier would help. Stage 8 - Harbor World Exonym pointed out there was air tiles below the ground. The results are clear. Standard boss kill. Luckily, there's a magic tile the next stage is looking for wherever it is we stopped the loader. Stage 9 - Ocean World Swimming stage! First segment skipped thanks to that magic tile ID, which the game stores and uses before refreshing it on the first frame. We're able to move quickly while riding objects because holding Down (and specifically Down, no Left or Right) while on an object prevents an instantaneous 0 walk speed. It's also tricky to despawn enemies, but we also have a larger margin with a speed very close to 5 pixels/frame. Boss needs a magic tile to load for the boss weakpoint, so we're sluggish in the last segment waiting for it. No top of screen glitches today, the screen is stopped on the bad half. Stage 10 - Ghost Town World Much like with Stage 2, a lot of flat ground to traverse, so we can go quickly. The startup plan needs to get past a barrel before it loads in, and we have a fraction of a pixel to spare. The boss gives up before we do anything to it. No, seriously! The boss reappears a fixed distance above our heads, but at the position we stop at, that would wrap around to bottomless pit zone. As a result, their disappearing act is one-way, and we instantly win. Stage 11 - Dark Forest World We can beat this stage quickly, but for a skip to be possible, we need to slow down for the loader. The magic tile we need won't load otherwise. Boss ouch frames seem unskippable in this battle. But it's still down pretty quickly. Stage 12 - Castle World Multiple segments, but for some reason, ending on tile 0x30 in Stage 11 lets us skip a great deal of castle. To the extent we can tell, this is the best warp we can get from Tile Storage. Ghosts won't disappear into the "phantom bottomless pit zone" like in Stage 10, so they are apple'd as normal. Snake-like boss, can't think of any special comments. Hamburgler's boss, we realize attacking the wall is just as valid as attacking the boss itself. Final boss, attacking the floor is just as viable a target.
Experienced Forum User, Experienced player (742)
Joined: 7/20/2011
Posts: 318
Gameboy TAS of 2021
I'll just state some further ideas I had about improving our file, but I have no proof for any of it (except the stage 7 boss trick). Of course as was already stated, if the stage 7 boss is killed during it's head transition it flies off the top of the screen almost instantly. I did take a screenshot of the 1 frame the boss's dead hitbox actually still existed before it flew off screen though: Anyway, with that being said almost any small improvement before stage 7 would probably make this trick possible. Which means I come to my other idea. I was wondering if it were somehow possible to get those throws to land on the garbage boss tiles in stage 4 and still have ronald land on the boss's existing mouth instead of falling all the way to the floor. It seems we miss a phase of boss tiles existing while we're trying to get back in position. Again, no proof just theories. Also, I'm pretty sure some of the other submissions had a better Hamburglar fight near the end of the game: attacking the ground so that the apple's timer runs out sooner than it would by attacking him directly at the start. I didn't actually compare times, just observations. In fact I believe stage 1 can even be improved in theory. In my head, we should have less frames with no apple boost than we do and also we should be flying directly into the boss to get as early hit as possible in. I don't know if any setup would allow for that; but it makes sense in my head. That's about all I have for the moment, I might update this post if anything else comes to mind.
Current thoughts: Hachiemon (J) for GBA.
Editor, Experienced Forum User, Expert player (2261)
Joined: 5/15/2007
Posts: 3825
Location: Germany
Gameboy TASer of 2015NES TAS of 2013Gameboy TASer of 2011Gameboy TASer of 2010
Our team's lua. Note: You need the font "SF Intermosaic B" to be installed. Otherwise, edit line 203 to a different font. - Tile viewer - Lets you view and drag around enemies/objects (I'm proud I was able to code this) - Various memory values... I think bugs/tricks-wise we did not find anything new. Subpixels, buttons held (etc.) is carried over from level to level. And lag can be reduced by 1-3 frames on loading screens by button presses. BrunoValads might want to post our RAM map and sprites information which mainly he worked on.
DrD2k9
He/Him
Editor, Experienced Forum User, Reviewer, Skilled player (1591)
Joined: 8/21/2016
Posts: 924
Location: US
Exotic platforms TASer of 2020First edition TAS of 2020Gameboy TAS of 2020Exotic platforms TASer of 2019Computer TASer of 2017
MUGG wrote:
And lag can be reduced by 1-3 frames on loading screens by button presses.
There's a looped instruction that can be interrupted via these button presses. -7 found the loop and made a lua to show which frames needed altered to minimize the lag by forcibly breaking out of the loop.
Editor, Experienced Forum User, Skilled player (1176)
Joined: 9/27/2008
Posts: 1072
General script Terrain script Timing script Now that I'm awake and alert, here's some scripts that I probably should have handed over a little while ago.
Editor, Experienced Forum User, Skilled player (1384)
Joined: 7/9/2010
Posts: 1312
Glitchy TAS of 2015NES TASer of 2014Speedy TAS of 2014NES TAS of 2013
Here's my specialised script: User movie #51620369168057608 It outputs values to tastudio listview, sets colors, logs positions and draws them to the client screen, numpad#-key displays logged values from branch. All functions should also be included in the team lua script.
Favorite animal: STOCK Gt(ROSA)26Sortm1.1(rtTA,EGFP)Nagy Grm7Tg(SMN2)89Ahmb Smn1tm1Msd Tg(SMN2*delta7)4299Ahmb Tg(tetO-SMN2,-luc)#aAhmb/J YouTube Twitch
Experienced Forum User
Joined: 3/8/2014
Posts: 36
Good job y'all. I'm the person who made those TAS WIPs you all saw for the contest. It's kind of funny; I made those specifically with the intention of drumming up interest from actual TASers as I had little to no knowledge of my own on how to optimize one. I'm also the original realtime runner for the game and it's kind of my baby. I discovered two of those wrong warps on my own and I was jumping out of my carseat watching the Oasis World warp. I had theorized that it would be possible to warp if you could get in the correct position, but had no idea how to get there as the boss is dying. Gonna read through the notes and watch again, but I just wanted to thank y'all for doing it. You made a shitty TASer and a lazy retired speedrunner very happy :)
Experienced Forum User, Experienced player (742)
Joined: 7/20/2011
Posts: 318
Gameboy TAS of 2021
Here was also an interesting, yet completely useless thing I found at some point: Link to video What's happening: the apple I attached to a skull that flies underneath the elevator explodes at just the right time. An exploding apple has an extended hitbox which is larger than the unexploded apple and is actually enough to reach Ronald's hitbox. If timed perfectly the apple expanding can pull ronald off the elevator object that glues ronald to it. Because the elevator requires you to have 0 x velocity in order to trigger it, suddenly now ronald gets a boost applied by the apple after it's triggered. That's why ronald moves to the right. Again, nothing happens as the elevator object is still going on it's path and it reaching the top of the screen is actually what triggers the transition (to my knowledge anyway).
Current thoughts: Hachiemon (J) for GBA.
Warepire
He/Him
Editor, Experienced Forum User
Joined: 3/2/2010
Posts: 2172
Location: A little to the left of nowhere (Sweden)
The scripts we used: Block map: http://tasvideos.org/userfiles/info/51685216242376410 Minimap: http://tasvideos.org/userfiles/info/51685242883649450 Generic hud: http://tasvideos.org/userfiles/info/51685255902414411 We completely overlooked that the blocks in the HUD part might be used, so our Block map does not try drawing them. The HUD contains basic speed info, hit boxes, basic enemy info, basic apple info.
MESHUGGAH
Other
Experienced Forum User, Skilled player (1830)
Joined: 11/14/2009
Posts: 1349
Location: 𝔐𝔞𝔤𝑦𝔞𝔯
NES TASer of 2013NES TAS of 2013NES TAS of 2012NES TAS of 2011
PhD in TASing 🎓 speedrun enthusiast ❤🚷🔥 white hat hacker ▓ black box tester ░ censorships and rules...
Warepire
He/Him
Editor, Experienced Forum User
Joined: 3/2/2010
Posts: 2172
Location: A little to the left of nowhere (Sweden)
Addr 0x4C:
  High byte of camera position of end of current level?

Addr 0xC7:
  Buttons read from joypad 1 (this frame)

Addr 0xC8:
  Last frame's buttons. Copied from 0xC7 before 0xC7 is refilled

Addr 0xCA:
  Value to write to PPUCTRL (0x2000)

Addr 0xCE:
  Y screen position (low?) (pixels)

Addr 0xCC/0xCD:
  X screen position (pixels)

Addr 0xEC:
  Screen mode?
  0x01 = Title screen
  0x02 = Title screen idle animation
  0x03 = Title screen -> First level
  0x04 = Filler/between screens
  0x05 = Playable level

Addr 0x617/0x618:
  X position of the character on the whole stage (pixels)

Addr 0x84 and 0x87:
  Integers indicating the cardinal direction joypad 1's dpad is being held. 0x84 will only show U/D/L/R and 0x87 will only show U/D/L/R/UR/UL/DR/DL.
  0x84:
    1 = Up
    2 = Down
    3 = Left
    4 = Right
    0 = Direction not listed above

  0x87:
    1 = Up
    2 = Down
    3 = Left
    4 = Right
    5 = Up + Left
    6 = Up + Right
    7 = Down + Left
    8 = Down + Right
    0 = Direction not listed above

Addr 0x91/0x92:
  X position of the character on the screen (sub-pixels)

Addr 0xA9:
  Speed gained from riding an enemy/apple
  Fetched from [0x583 + enemy_slot_id]

Addr 0x98/0x99:
  Speed (sub-pixels)

Addr 0x9A:
  Effective speed (pixels). This is the sum of the whole pixel speed and any boost

Addr 0xA9:
  Speed boost added to the regular speed.

It looks like speed can be pretty well optimized by keeping a close eye on the effective speed in 0x9A and trying to keep it high.
You have a running speed (holding B) of 2 pixels per frame and can get a boost of 2 more from bomb jumping.

Address 0x53:
  For level 1, starts at 0x08, gets changed to 0when screen scroll X becomes 0x0808
  Maybe some kind of switch to load other level data?

Address 0xA8:
  Seems to be flags
  0x80 = Being hit?
  0x20 = riding enemy?
  0x01 = On ground?

Addr 0x4ED:
  Seems to be a counter of how many enemies have been seen? Seems like the high 6 bytes are also used to compare against the high byte for the player position (ish).

Addr 0x4F1:
  Enemy slot ID that hit you

Addr 0x4F3-0x4FA (8 slots):
  0x00 = Slot empty
  0x02 = Enemy is on screen
  0x03 = Enemy is off screen

Addr 0x4FB-0x500 (6 slots):
  Seems like enemy type ID
  Only related to enemies (not apples, range is 0-5)
  if value is 0x15 a section of code doesn't run
  Other values checked for: 0x13, 0x10, 0x39, 0x3B, 0x3C, 0x3F, 0x44, 0x46, 0x00, 0x16

Addr 0x501-0x508 (8 slots):
  ? Related to enemies
  compared == 0x0D at 0xE8FF

Addr 0x51B-0x520 (6 slots):
  An offset into a pointer table for animation data for this specific enemy
  Seems to choose what animation this enemy should perform (move vertically upwards, oscillate up and down/left and right, etc)
  Used at D507 to get an address in bank 3 (A9B2 + value * 2)

Addr 0x521-0x526 (6 slots):
  ? Related to enemies
  Looks like a counter for this enemy, probably used to determine where in the animation cycle the enemy is
  Used as an offset to the address fetched via the above value
  [(bank 3)A9B2 + [0x51B + enemy_slot_id * 2]] + [0x521 + enemy_slot_id * 2] * 4 = addr of the start of some data for enemy
  Entries in the data are probably 4 bytes, and this value is used to get the data for the current frame.
  If the first value in the next entry is 0x80 this counter restarts (and 0x515 + enemy_slot_id is incremented)


Addr 0x527-0x52E (8 slots):
  ? Related to enemies
  Flags
  0x40 - might indicate enemy is dying? Seems like you can't be damaged by them if it is set.
  0x80 - is often cleared when updating/checking enemies
         might indicate player is riding this enemy?
  0x08 - ? if set you can't get hit by it? you also can't ride it
  0x04 - ? if set you can't get hit by it?

Addr 0x535-0x53C (8 slots):
  ? Related to enemies
  compared < 0x04 at 0xE906
    if true, sets 0x40 in flags 0xA8

Addr 0x543-0x54A (8 slots):
  Enemy X position (high)

Addr 0x54B-0x552 (8 slots):
  Enemy X position (low)

Addr $0563-0x56A (8 slots):
  Enemy Y position

Addr 0x573-0x57A (8 slots):
  ? Related to enemies
  Might be hitbox horizontal size

Addr 0x57B-0x582 (8 slots):
  ? Related to enemies
  Might be hitbox vertical size

Function 0xE994
  Seems to check player against enemy position.
  hitbox_h = [0x573 + enemy_slot_id] + 0x07
  hitbox_w = [0x57b + enemy_slot_id] + 0x0F

  This function checks if the follow are all true:
  player_y < (enemy_y + hitbox_h)
    Make sure player is not too low
  (enemy_x - hitbox_w) < (screen_scroll_X + player_onscreen_x)
    Make sure player is not too far left
  (screen_scroll_X + player_onscreen_x) < (enemy_x + hitbox_w)
    Make sure player is not too far right
  (enemy_y - hitbox_h) < player_y
    Make sure player is not too high

  (enemy_y - hitbox_h) - player_y is stored to 0x0006
  This value must be negative to fit the condition above
  If this value -1 to -8 the game considers you as riding the enemy

Bank 3:

Starting at 0xB1AA is an array of addresses
B1CE - level 00 (??)
BB16 - level 01
B1CE - level 02
B648 - level 03
B822 - level 04
B94E - level 05
B32A - level 06
B4AA - level 07
B9F6 - level 08
B744 - level 09
B3E4 - level 10
BA68 - level 11
BBE8 - level 12
B1CE - level 13 (??)
B1CE - level 14 (??)
B1CE - level 15 (??)
B1CE - level 16 (??)
B1CE - level 17 (??)

These addresses point to a data for the powerup boxes in each level.
Each entry in those arrays is 6 bytes long:
[0] - X screen pos (high)
[1] - X screen pos (low)
[2] - ?
[3] - X pos on screen
[4] - Y pos
[5] - Type

Seems like this list of boxes is terminated with 0xFF in [0] and [1]

Known types:
1 -> Extra life
2 -> ?
3 -> Burger
4 -> Heart
5 -> Apple


Function F176:
This function runs level specific code. Using the level ID (address 0x51) it looks up an address:
  0xF19B + (level_id * 2)
  0xF19A + (level_id * 2)

It then uses the section ID (address 0x52) to get a function address
  addr + (section_id * 2)

The value fetched is pushed to the stack, then an RTS instruction is issued. RTS pushes the (16 bit value from stack + 1) to PC, so the addresses stored in the rom are 1 off from the start of the function

Most levels have more than one function pointer in this area. The function is usually to handle moving to the next section or world, or to determine when you have finished the world (usually the last section handler)

(Function addresses in this table have already had 1 added to them)
                         Section
                         0      1      2      3      4      5      6      7      8      9      10     11     12     13     14     15     16     17     18     19     20     21     22
Level 00 (???)  [F1C0]   F23C
Level 01        [F1C2]   F243   F287
Level 02        [F1C6]   F294   F2AB
Level 03        [F1CA]   F2B8   F2D7   F330
Level 04        [F1D0]   F337   F362   F3A0
Level 05        [F1D6]   F3AC   F3DD
Level 06        [F1DA]   F40A   F40A   F40A   F433   F458
Level 07        [F1E4]   F468   F4D4
Level 08        [F1E8]   F4E1   F4F8
Level 09        [F1EC]   F505   F505   F505   F505   F505   F521   F540   F576
Level 10        [F1FA]   F58B   F5B2   F5E8
Level 11        [F200]   F5F8   F60F
Level 12        [F204]   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F61C   F713   F733

World 1 section 0 (F243):
  Handles the "Good luck" guy
  When the screen scroll reaches 0x0808 addr 0x53 is changed from 0x08 to 0x00
  If Screen scroll X == 0x0BXX, level section is increased (boss is triggered)
World 1 section 1 (F287):
  Waits for 0x4F3 (Object enabled) to become 0

World 2 section 0 (F294):
  If Screen scroll X == 0x17XX, level section is increased (boss is triggered)
World 2 section 1 (F2AB):
  Waits for 0x4F3 (Object enabled) to become 0

World 3 section 0 (F2B8):
  If Screen scroll X == 0x16XX, level section is increased (boss is triggered?)
World 3 section 1 (F2D7):
  ???
  if 0xE2 >= 5, move to section 2
World 3 section 2 (F330):
  Seems to be hard coded to move to the next world.

World 4 section 0 (F337):
  If Screen scroll X == 0x0FXX, level section is increased (boss is triggered?)
World 4 section 1 (F362):
  ??? Similar to W3S1
World 4 section 2 (F3A0):
  ??? Similar to W3S2

World 5 section 0 (F3AC):
  If block player is in front of (0x615) == 0x79, level section is increased (move to boss room)
World 5 section 1 (F3DD):
  ???

World 6 section 0-2 (F40A):
  If block player is in front of (0x615) == 0x38, level section is increased (causes a screen transition?)
  If Screen scroll X == 0x13XX, level section is increased
World 6 section 3 (F433):
  ???
World 6 section 4 (F458):
  Waits for 0x4F3 (Object enabled) to become 0

World 7 section 0 (F468):
  ?complex stuff?
  If Screen scroll X == 0x16XX, level section is increased
World 7 section 1 (F4D4):
  Waits for 0x4F3 (Object enabled) to become 0

World 8 section 0 (F4E1):
  If Screen scroll X == 0x0BXX, level section is increased
World 8 section 1 (F4F8):
  Waits for 0x4F3 (Object enabled) to become 0

World 9 section 0-4 (F505):
  If block player is in front of (0x615) == 0x30, level section is increased (causes a screen transition?)
  If block player is in front of (0x615) == 0x83, level section is increased (causes a screen transition?)
World 9 section 5 (F521):
  If Screen scroll X == 0x20XX, level section is increased
World 9 section 6 (F540):
  ??? Similar to W3S1
World 9 section 7 (F576):
  ???

World 10 section 0 (F58B):
  If Screen scroll X == 0x0FXX, level section is increased
World 10 section 1 (F5B2):
  Monitors 0x4F3 and 0x4F4
  ???
World 10 section 2 (F5E8):
  Waits for 0x4F3 (Object enabled) to become 0

World 11 section 0 (F5F8):
  If Screen scroll X == 0x0BXX, level section is increased
World 11 section 1 (F60F):
  Waits for 0x4F3 (Object enabled) to become 0

World 12 section 0-20 (F61C):
  ???
  There is a table at 0xF781 used to compare the block the player is in front of, and to decide where to warp the player:
    Block ID      Map section
          BF  --  01
          7A  --  0F
          C0  --  00
          C1  --  10
          30  --  11
          BD  --  12
          BE  --  13
  ???
World 12 section 21 (F713):
  Waits for 0x4F3 (Object enabled) to become 0
World 12 section 22 (F733):
  Waits for 0x4F3 (Object enabled) to become 0

Movement when riding an enemy:
Your final movement speed is calculated from a number of different sources
0xA9 is probably the horizontal speed gained from riding an enemy

Skipping shop:
  at 0xF7B0 the burger count (0x61E) is compared to 0 which skips a function that likely starts the shop routine.

Title screen:
  Address 0x22 is a counter for the start button. It is reset to 4 and counts down when the start button is held. When the counter reaches 0 the game advances to the next screen/into the game.

Level timer length:
  There is table at 0xC3D6 which specifies the timer length per level:
  Level 00? -  0xC3D6  =  24792 ???
  Level 01  -  0xC3D8  =  300
  Level 02  -  0xC3D8  =  300
  Level 03  -  0xC3D8  =  400
  Level 04  -  0xC3D8  =  400
  Level 05  -  0xC3D8  =  300
  Level 06  -  0xC3D8  =  400
  Level 07  -  0xC3D8  =  400
  Level 08  -  0xC3D8  =  300
  Level 09  -  0xC3D8  =  500
  Level 10  -  0xC3D8  =  300
  Level 11  -  0xC3D8  =  200
  Level 12  -  0xC3D8  =  500

Castle:
  Section 0x02 has two doors. The left door warps you to section 00 (entrance to the castle).

  The right door warps you to the left side of section 0x10, which looks identical to section 0x02. Going back through the door in section 0x10 brings you to section 0x0F, which is also identical to 0x02 and 0x10.

  Seems like 0x02 starts from the elevator down, 0x10 starts from the room on the left, and 0x0F starts from the door on the right.

  Ending level 11 on a 0x30 block ID wrong warps you to section 0x11 which looks like a hidden shop. Taking the elevator up takes you to section 0x08 which is identical to 0x0C. This is around halfway through the castle.

  Section 0x12 and 0x13 start from falling out of the ceiling on section 0x03.

  Section 0x05 is 0x03 coming down from the elevator from section 0x04.

  Section 0x07 is 0x03 on the elevator back from 0x06.

  Section 0x0D is 0x03 coming down from the elevator from section 0x0C

  Section 0x14 is the same as 0x15 (final boss room).

  Section 0x16 is a glitched version of 0x00 and 0x01 combined.

Level data ROM bank:
  The table at 0xC5AD says what bank each level's data is in:
  Level 01 - 3
  Level 02 - 3
  Level 03 - 0
  Level 04 - 0
  Level 05 - 1
  Level 06 - 2
  Level 07 - 0
  Level 08 - 1
  Level 09 - 3
  Level 10 - 1
  Level 11 - 2
  Level 12 - 3

Address 0x4f-0x50
  This address is filled from a table at 0xD102. The address fetched is then incremented by 3 before being stored to 0x4F and 0x50

  Level 01 - 8000 + 3 = 8003
  Level 02 - 8000 + 3 = 8003
  Level 03 - 90b7 + 3 = 90BA
  Level 04 - 8000 + 3 = 8003
  Level 05 - 8000 + 3 = 8003
  Level 06 - a0b4 + 3 = A0B7
  Level 07 - 9133 + 3 = 9136
  Level 08 - 8953 + 3 = 8956
  Level 09 - a0ee + 3 = A0F1
  Level 10 - 90d3 + 3 = 90D6
  Level 11 - 930c + 3 = 930F
  Level 12 - a206 + 3 = A209

Address 0x54-0x55
  This address is filled from a table at 0xCD9F.

  Level 01 - 9c0a
  Level 02 - 800f
  Level 03 - 801b
  Level 04 - 90d2
  Level 05 - 8013
  Level 06 - 8013
  Level 07 - a0cb
  Level 08 - 914e
  Level 09 - 8962
  Level 10 - a112
  Level 11 - 90e6
  Level 12 - 931b

Fetching level data:
  All accesses are in the bank for thr level. See the table above to find that bank.

  The address in 0x54-0x55 is for the level data.
  The address in 0x4F-0x50 is for a table of offsets into the level data. Each offset is 208 bytes long.

  To fetch level data:
  Take the high byte of the position
  Use that as an offset into the table from 0x4F-0x50 and fetch a byte value
  Take the value, multiple it by 208, and add it to the address in 0x54-0x55
  The resulting address is the beginning of that segment of data.

Enemy data
  Table in bank 5 at 0xAF63, add level_id * 2

  Level 01 - b9d7
  Level 02 - af87
  Level 03 - b507
  Level 04 - b697
  Level 05 - baa7
  Level 06 - b117
  Level 07 - b377
  Level 08 - bbb7
  Level 09 - b7a7
  Level 10 - b267
  Level 11 - bc87
  Level 12 - bd57

  That address points to another table, entries are 4 bytes long. Game fetches 0x4ED, multiplies it by 4, and adds it to get an address. Note: this addition (0xD24F) seems wrong and may have issues with bit overflow if the lower byte would overflow. Might be abusable for something?

  [0].b - Enemy position (low byte)
  [1].b - Enemy Y position?
  [2].b - Enemy type?
  [3].b - ???

  0x4ED seems to have room for 4 enemies per high position byte. If any of those are unused the data is all 0 in the above table.

Enemy spawn:
  Starting at 0xD229
  0x4ED seems to hold the next(?) enemy id to load for the level. The following must be true for the enemy to spawn:
    Player's position high byte must be <= end of level (0x4C)
    (Player's position + 0x90) (high byte) == Enemy high position byte
    (Player's position + 0x90) (low byte) < Enemy low position byte
    (Player's position + 0x193) (high byte) >= Enemy high position byte
      if equal:
        (Player's position + 0x193) (low byte) > Enemy low position byte
  what this boils down to is that the game checks every half screen (0x80 pixels) and increments the counter if you are in the first 4 pixels.
  you can skip the spawns for that half screen by being at 5 speed at a point where you move the screen from 0x7F->0x84 or 0xFF->0x04

World/Section Min/Max:
  Table at 0xBC00 (bank 4), indexed by level_id * 2. These are pointers to data for each world:
  Level 01 - bc36
  Level 02 - bc56
  Level 03 - bc76
  Level 04 - bca6
  Level 05 - bcc6
  Level 06 - bce6
  Level 07 - bd16
  Level 08 - bd36
  Level 09 - bd56
  Level 10 - bdb6
  Level 11 - bdd6
  Level 12 - bdf6
  
  Fetch that address and add section_id * 16
  Data in that table:
  [5].b = Min camera position 
  [6].b = Max camera position
Editor, Experienced Forum User, Player (51)
Joined: 6/22/2005
Posts: 1001
I looked into this game a bit early in the contest and found these addresses that don't appear to be listed above or that complement the above info:
0x95 Y-position of player character
0x94 Y-subpixel

0x9C Y-speed of player character
0x9D Y-subpixel speed

0x9E Max X-speed
0x9F Max X-subpixel speed
0xA0 Max Y-speed
0xA1 Max Y-subpixel speed

0xA8 flags
  0x00 = jumping or falling
  0x01 = standing on ground
  0x02 = jumping/falling/standing/whatever against a barrier
  0x20 = standing on platform / enemy / projectile
  0x80 = taking damage

0xAB flags related to jumping
  0x00 = not jumping
  0x01 = jumping
  0x02 = falling after jumping

0xAC Counter related to jumping
I also modified my Wizards & Warriors III Lua script to exhaustively generate vertical jump information, but analysis of the first 0x3000000 trials showed that all of the data was present after the first 0x2000. Only ran it in the first level, though. I can upload that info, if desired, but it may not be useful due to the bomb boosts/jumps.
Current Projects: TAS: Wizards & Warriors III.
Warepire
He/Him
Editor, Experienced Forum User
Joined: 3/2/2010
Posts: 2172
Location: A little to the left of nowhere (Sweden)
From IRC:
09:24 <FatRatKnight> In any case, I am aware that along with A9 for boost speed, you missed the sub-boost speed at AA.
09:24 <FatRatKnight> Or boost subspeed, I guess.
09:24 <FatRatKnight> Somewhere a sub should be.
09:24 <Warepire> Interesting.
09:25 <FatRatKnight> The fractional value is mostly pertinent for riding apples, as enemies generally have a lovely zero for their subspeed.
09:26 <Warepire> That means we also missed the subpixel boost value in the enemy data structures
09:26 <FatRatKnight> My notes claim that would be 058B, along with the following 7 addresses.
09:30 <Warepire> May I paste relevant bits in the topic later?
09:31 <FatRatKnight> Go ahead.
Editor, Experienced Forum User, Skilled player (1176)
Joined: 9/27/2008
Posts: 1072
I haven't felt any desire to really finish Donald Land, tying together all known improvements. The easy thing would simply be to graft Team 7's castle onto Team 4's run, and call it mostly optimal. I do strongly believe that the movement patterns we (Team 4) took on flat ground and over the abyss is the fastest strategy to take. Start-ups, "rough terrain", and meshing together other things seems to be stuff Team 7 had some respectable knowledge in. The 2.75 apple tosses are attractive for having an extra 0.25 over the 2.5 apple drops. I've been finding that the delays where we're at zero boost to be much worse with the 2.75 tosses in general, as the apple doesn't actually move right away when thrown rather than dropped. They're totally apples, not bombs. How can such a lovable character like Ronald be throwing dangerous explosives everywhere? I'm sure with the natural sugar in them, apples can explode, right? ... Right? Besides, who hasn't dreamed of flying through the sky with nothing but a sack of apples and a strong throwing arm? I'll be around in case there's some random bits Team 4 did that needs explaining, or possibly prettify some scripts. I just don't want to do the TASing.
Memory
She/Her
Experienced Forum User, Site Admin, Skilled player (1329)
Joined: 3/20/2014
Posts: 1677
Location: Dumpster
GBA TASer of 2020GBA TAS of 2020GBA TASer of 2019Exotic platforms TAS of 2018
If noone is interested in patching it all together I will take a look at it once the year is over.
[16:36:31] <Mothrayas> I have to say this argument about robot drug usage is a lot more fun than whatever else we have been doing in the past two+ hours
[16:08:10] <BenLubar> a TAS is just the limit of a segmented speedrun as the segment length approaches zero
DrD2k9
He/Him
Editor, Experienced Forum User, Reviewer, Skilled player (1591)
Joined: 8/21/2016
Posts: 924
Location: US
Exotic platforms TASer of 2020First edition TAS of 2020Gameboy TAS of 2020Exotic platforms TASer of 2019Computer TASer of 2017
Memory wrote:
If noone is interested in patching it all together I will take a look at it once the year is over.
I'm willing to help. But I also will likely need to wait until the year is over.
Experienced Forum User, Experienced player (742)
Joined: 7/20/2011
Posts: 318
Gameboy TAS of 2021
FatRatKnight wrote:
The easy thing would simply be to graft Team 7's castle onto Team 4's run, and call it mostly optimal.
At this point this seems like the best option, since it seems no one is willing to actively improve this (myself included). It's still a pretty entertaining run and I think it should be published and people can improve it later.
Current thoughts: Hachiemon (J) for GBA.
Memory
She/Her
Experienced Forum User, Site Admin, Skilled player (1329)
Joined: 3/20/2014
Posts: 1677
Location: Dumpster
GBA TASer of 2020GBA TAS of 2020GBA TASer of 2019Exotic platforms TAS of 2018
I've successfully added team 7's last stage to team 4's movie (with some modifications in order to sync). Should I just directly add team 7's rerecord count to this movie? Not sure how this typically works. EDIT: For now I'll just use the combined rerecord count. What are people's thoughts on me claiming co-authorship? I had to edit the end of team 4's second to last stage and one portion of team 7's final stage to get it to sync.
[16:36:31] <Mothrayas> I have to say this argument about robot drug usage is a lot more fun than whatever else we have been doing in the past two+ hours
[16:08:10] <BenLubar> a TAS is just the limit of a segmented speedrun as the segment length approaches zero
DrD2k9
He/Him
Editor, Experienced Forum User, Reviewer, Skilled player (1591)
Joined: 8/21/2016
Posts: 924
Location: US
Exotic platforms TASer of 2020First edition TAS of 2020Gameboy TAS of 2020Exotic platforms TASer of 2019Computer TASer of 2017
Memory wrote:
What are people's thoughts on me claiming co-authorship? I had to edit the end of team 4's second to last stage and one portion of team 7's final stage to get it to sync.
Claim it. Re-syncing is a part of authorship when combining parts from multiple runs. Think about it this way. If we had two published runs of some game (a 100% and an any%) and you saw ways to combine parts of each to yield an even faster any% run; the combination and re-syncing is your contribution. In this case it would be appropriate to include yourself as an author on the new submission even though you didn't necessarily add anything new/novel. The only difference between that hypothetical scenario and the Donald Land situation is that Donald Land isn't currently published. You're still contributing via combination and re-syncing, so you should get authorship credit.