1 2
12 13 14
Player (54)
Joined: 11/20/2013
Posts: 103
Alright. I don't see anything obvious indicating your speed at first glance. The response seems instantaneous to me when moving left and right so I wouldn't be surprised if you don't really have an X-velocity at all and it's just on/off movement. I could be wrong though.
Player (185)
Joined: 10/8/2006
Posts: 145
Player (54)
Joined: 11/20/2013
Posts: 103
Kay now that I realize that Bizhawk 1.9.1's "Freeze Address" capability is broken and try again on 1.8.1, I did find some stuff. $001022 is your two-byte Y-Velocity. I still can't find an X-Velocity. I think your RNG is $00009C, two bytes. If I freeze that during the first (hippogryph) boss fight, while playing your recording, it desyncs his actions.
Player (54)
Joined: 11/20/2013
Posts: 103
Just to add a bit more, did some looking into how address $00009c works:
80b903 jsl $bc904b   [bc904b] A:0000 X:0001 Y:0004 S:013f D:0000 DB:81 nvMXdiZc V: 17 H:1170
bc904b rep #$20               A:0000 X:0001 Y:0004 S:013c D:0000 DB:81 nvMXdiZc V: 17 H:1224
bc904d lda $009c     [81009c] A:0000 X:0001 Y:0004 S:013c D:0000 DB:81 nvmXdiZc V: 17 H:1242
bc9050 asl a                  A:5160 X:0001 Y:0004 S:013c D:0000 DB:81 nvmXdizc V: 17 H:1276
bc9051 clc                    A:a2c0 X:0001 Y:0004 S:013c D:0000 DB:81 NvmXdizc V: 17 H:1288
bc9052 adc $009c     [81009c] A:a2c0 X:0001 Y:0004 S:013c D:0000 DB:81 NvmXdizc V: 17 H:1300
bc9055 xba                    A:f420 X:0001 Y:0004 S:013c D:0000 DB:81 NvmXdizc V: 17 H:1334
bc9056 sep #$20               A:20f4 X:0001 Y:0004 S:013c D:0000 DB:81 NvmXdizc V: 17 H:1352
bc9058 sta $009d     [81009d] A:20f4 X:0001 Y:0004 S:013c D:0000 DB:81 NvMXdizc V: 18 H:   6
bc905b clc                    A:20f4 X:0001 Y:0004 S:013c D:0000 DB:81 NvMXdizc V: 18 H:  32
bc905c adc $009c     [81009c] A:20f4 X:0001 Y:0004 S:013c D:0000 DB:81 NvMXdizc V: 18 H:  44
bc905f sta $009c     [81009c] A:2054 X:0001 Y:0004 S:013c D:0000 DB:81 nvMXdizC V: 18 H:  70
bc9062 rtl                    A:2054 X:0001 Y:0004 S:013c D:0000 DB:81 nvMXdizC V: 18 H:  96
So it takes the full previous value and multiplies it by 3, writes the hi byte to $009D, then adds $009C to that hi byte and stores the result in $009C. What's interesting about this is, unlike in Dragon View where it uses the H/V Scanline Counters after reading controller input to generate something pseudo-random that changes with controller input, this should be a totally deterministic sequence independent of everything you do. In other words, unless something manually resets it, the only way you can influence the RNG is changing when the decision is made. ie/ a boss fight should go the exact same way every single time, so long as you start it on the same frame (and the RNG began rolling on the same frame) (unless you can change when they make a decision by hitting them at a different time or something). Upon thinking about it some more, it's entirely possible the AI's decision-making could be based on both RNG and something like your position as well. But at least you know where the random element comes from. It seems to be initialzed with value $0D37 and starts running on frame 694 in your file, though it pauses during the lag frames / loading time.
Player (185)
Joined: 10/8/2006
Posts: 145
Khaz wrote:
... this should be a totally deterministic sequence independent of everything you do. In other words, unless something manually resets it, the only way you can influence the RNG is changing when the decision is made. ie/ a boss fight should go the exact same way every single time, so long as you start it on the same frame (and the RNG began rolling on the same frame) (unless you can change when they make a decision by hitting them at a different time or something). Upon thinking about it some more, it's entirely possible the AI's decision-making could be based on both RNG and something like your position as well. But at least you know where the random element comes from. It seems to be initialzed with value $0D37 and starts running on frame 694 in your file, though it pauses during the lag frames / loading time.
I have suspected this. The term "deterministic" is apt. If you look at my boss fight for example, the last sequence, when hippogryph drops down to do his charge attack I was able to manipulate him to choose the same movement (as the optimized route) by adjusting my height by jumping. However, but based on my position/velocity/direction he did not descend but moved closer to me horizontally I'm thinking I will be able to force out the desired behavior still. I'll try altering my jump timings. and see if I can hammer out the last two hits without him initiating the dash (which causes an extra 20 frames of lag) Thank you Khaz, this is great. Are you able to determine what IF anything can reset/alter the RNG (especially mid-fight specifcally vs. the eye balls. That recorded fight was SO CLOSE to . . . my desired outcomg (2 waves of three then 1 wave of four) ??? for example, if I remember correctly (I could scroll back and check when I have another moment) I know someone mentioned that anytime the RNG is triggered (killing an enemy, breaking a pot/statue) <--- in other words, the time at which I kill the mini-eye balls. <--- ES mentioned this had an effect (IIRC) I'll have to scroll back through the thread but right now I can't direct my attention that way. I took a break today since I posted the input file and I was hoping there would be some progress in this area. I really do appreciate your help with the RNG. This will be extremely useful. ESP
Post subject: Long Post of Relevant information from the past
Player (185)
Joined: 10/8/2006
Posts: 145
ElectroSpecter wrote:
OK guys, here's the deal with Ovnunu (I know I've already explained this elsewhere, but bear with me): His slime pulses up and down during the phase where you kill the mini-eyes. Whenever he reaches his lowest point of the pulse, the game checks to see if the mini-eyes are all dead. If they are, he comes out. If not, he goes into another pulse cycle. Each pulse cycle lasts about 300 frames. Now, in my current run, this phase lasts for about 1200 frames (4 pulses). As I hypothesized earlier, it may be possible to shorten this phase to 900 frames (3 pulses). I've gotten quite close with random testing, but it's unfortunately quite tedious. What I'm wondering is if anyone is willing to help me find out what causes these eyeballs to come out and when (the memory addresses, or if some as-of-yet-unknown RNG *shudder* is the cause)....
Dromiceius wrote:
...I found that 7E1DF8 is a counter for eyes that Firebrand has killed. This address is read at $83/D20C, and I'd bet the function you're looking for isn't too far off....
ElectroSpecter wrote:
....I did discover that values 7E1DE7 - 7E1DDE are the true/false values for the eyeballs. They all start at 9, and the moment an eyeball decides to come out, the value turns to 0. Now, I really don't know what I would do with this information, but I'm sure it's of importance to the search. The frustrating thing is, there's got to be a whole lot I'm missing. For example, depending on which frame the slime reaches the top of the vertical passage, different amounts of eyeballs will come out at different times. Also, I think some of the eyeballs are "linked," meaning that the next eyeball in the sequence won't emerge until it's linked eyeball has been defeated (I specified this because I thought at first the game just put a general limit on how many eyes could be out of the slime at one time)....
ElectroSpecter wrote:
83/D3B9:	E230    	SEP #$30     ; set bits x, d, i, 
                                   ; and z = 1
83/D3BB:	A542    	LDA $42      ; load the accumulator 
                                   ; with memory, also 
                                   ; deals with Direct Page?
83/D3BD:	F044    	BEQ $D403    ; something to do with a 
                                   ; branch to 83/D403?
83/D3BF:	220F8882	JSR $82880F  ; jump to subroutine at
                                   ; 82880F (not sure what
                                   ; this means)
83/D3C3:	903E    	BCC $D403    ; clear the carry bit at
                                   ; D403?
83/D3C5:	A636    	LDX $36      ; Load X register from 
                                   ; direct page
83/D3C7:	AD820D  	LDA $0D82    ; Load the accumulator
                                   ; with memory at 0D82
83/D3CA:	38      	SEC          ; set bit c = 1
Dromiceius wrote:
83/D3B9:   E230       SEP #$30     ; set bits x, d, i,
                                   ; and z = 1
Not quite. The sigil ($) means we're using hexadecimal. Decimal 30 = 00011110, which is how you got nvmXDIZc, whereas $30 = 00110000 = nvMXdizc. You can find out more about this by searching "flag register" in the asmtutor, but what SEP #$30 does is set the M and X flags, both of which tell the CPU that we're working in 16-bit mode, rather than 8-bit mode. The sharp (#) means that rather than loading an address, it's using an absolute value. I should also tell you about Geiger's debugging snes9x. If you don't already have it, you should get it, because it allows you to step through the code as it's being executed.
83/D3BB:   A542       LDA $42      ; load the accumulator
                                   ; with memory, also
                                   ; deals with Direct Page?
Loads the accumulator with whatever is in 7E0042. I don't think the direct page actually comes into play when digging around in disassembly. At least, I've never seen it.
83/D3BD:   F044       BEQ $D403    ; something to do with a
                                   ; branch to 83/D403?
Branch if EQual checks to see if the zero flag is set, and if it is, it jumps to the address given, within this code bank. (The ROM is divided into chunks or "banks" of (IIRC) $8000 bytes. We're looking at bank $83 right now, hence the jump to $83/D403.)
83/D3BF:   220F8882   JSR $82880F  ; jump to subroutine at
                                   ; 82880F (not sure what
                                   ; this means)
If the z flag wasn't set at the BEQ, the processor will proceed to this line, and jump unconditionally to $82/880F, which is code bank $82. Once there, it executes whatever it finds until it hits the RET code, and returns to $83/D3BF. If you need to see what bank $82 (or any other bank) does, Modify that batch file to dump it by changing "83" to the bank number and renaming the output file.
83/D3C3:   903E       BCC $D403    ; clear the carry bit at
                                   ; D403?
Branch if Carry Clear. If the program had, for example, incremented the accumulator until it carried over to the next byte, the carry flag would be set, and it would jump to 83/D403, as with the BEQ above. We don't know by looking at disassembled code whether this branch actually happens or not, or under what circumstances. Hence the importance of Geiger's debugger.
83/D3C5:   A636       LDX $36      ; Load X register from
                                   ; direct page
In addition to the Accumulator, data is often loaded into the X and Y indices. Usually, these are used as loop counters as you would use "int i" in a for loop in C/++. LDX $36 loads 7E0036 to the x index, the contents of which are listed in the disassembly pane of Geiger's debugger.
83/D3C7:   AD820D     LDA $0D82    ; Load the accumulator
                                   ; with memory at 0D82
Right- and remember that you can find 0D82 in the cheat search by putting 7E in front of it.
83/D3CA:   38         SEC          ; set bit c = 1
Manually sets the carry flag. It's unclear from what you've posted why it would do this.
ElectroSpecter wrote:
83/BC4E:	ADF81D  	LDA $1DF8  ; Load the accumulator with 
                                 ; the value at 7E1DF8 (the
                                 ; counter for eyes you killed)
83/BC51:	C90A    	CMP #$0A   ; and compare it with the 
                                 ; value 10
83/BC53:	D019    	BNE $BC6E  ; if it isn't equal (i.e. you
                                 ; haven't killed all the eyes)
                                 ; branch to $83/BC6E
(I think those comments should be correct, though it's still my first day of learning to read disassembly so bear with me). Now, this bit of data isn't of much use, but it did clue me in that I may be getting closer to what I'm looking for. The beginning of this block begins at $83/BC2B, and it (and the next block) contain the values 1DDE,Y and 1DDE,X as well as commands to switch the Y and X values. (remember, 7E1DDE is the address for whether the first eyeball is active or not; I'm assuming that the X and Y after this value will change the address and affect different eyes?).
HHS wrote:
Yes, 7E009C is the random number, which is generated with this algorithm. It's run every frame and it's also run when a random number is needed:
BC:904B RNG:                                    ; CODE XREF: _80:A8FAP
BC:904B                                         ; _80:AE67P ...
BC:904B                 rep     #$20
BC:904D                 .ACCU 16
BC:904D                 lda     RandomNumber
BC:9050                 asl     A
BC:9051                 clc     
BC:9052                 adc     RandomNumber
BC:9055                 xba     
BC:9056                 sep     #$20
BC:9058                 .ACCU 8
BC:9058                 sta     (RandomNumber+1)
BC:905B                 clc     
BC:905C                 adc     RandomNumber
BC:905F                 sta     RandomNumber
BC:9062                 rtl
The number of eyes that come out at a time is random. When you start fighting, the probability is 50% of 2 coming out, 37.5% of 3 coming out and 12.5% of 4 coming out. There is a 33 frame delay between them. Afterwards, there is a 128 frame delay, and there is: - 12.5% chance of 1 coming out, 50% chance of 2 coming out, 25% chance of 3 coming out and 12.5% chance of 4 coming out with 0 eyes out, - 37.5% chance of 1 coming out, 50% chance of 2 coming out and 12.5% chance of 3 coming out with 1 eye out, - 37.5% chance of 0 coming out, 50% chance of 1 coming out and 12.5% chance of 2 coming out with 2 eyes out, - 87.5% chance of 0 coming out and 12.5% chance of 1 coming out with 3 eyes out. Otherwise, no eyes come out. In that case, Ovnunu just waits another 128 frames again, which he also does if all the eyes are already out but haven't been killed yet. So you have to kill the last eye before the next is supposed to come out or you'll have to wait another 128 frames. When it's time to send out another eye and you've killed all 10, Ovnunu will decide to jump out the next time he reaches the bottom. Luck manipulation might be hard since all you have to work with is the amount of eyes killed before it's going to send out more eyes, and the amount of wait frames before you start (Ovnunu begins to wake up when your X coordinate is at least 128 or your Y position is less than 568)
TheAxeMan wrote:
Boss hp is at 7E1336 for most bosses. Memwatch that to learn a lot. It looks like that boss may be a special case. I checked on Arma and it turns out there is a check before the hit. It checks to see if the high bit of that hp address is set (with a bpl instruction). In other words, the invulnerability flag is packed into the same byte as the hp. For some reason that flag is never set for hippogriff. Memwatch that hp and you'll see that several other bosses are vulnerable. In most cases this just means that a ground gargoyle shot hits twice. Somulo doesn't set that bit but there is something else going on because he dies at 1 hp instead of 0. Arma's invulnerability timer is at 7E1DD5, but that doesn't seem to be the case for other bosses.
THIS: The number of eyes that come out at a time is random. When you start fighting, the probability is 50% of 2 coming out, 37.5% of 3 coming out and 12.5% of 4 coming out. There is a 33 frame delay between them. Afterwards, there is a 128 frame delay, and there is: - 12.5% chance of 1 coming out, 50% chance of 2 coming out, 25% chance of 3 coming out and 12.5% chance of 4 coming out with 0 eyes out, - 37.5% chance of 1 coming out, 50% chance of 2 coming out and 12.5% chance of 3 coming out with 1 eye out, - 37.5% chance of 0 coming out, 50% chance of 1 coming out and 12.5% chance of 2 coming out with 2 eyes out, - 87.5% chance of 0 coming out and 12.5% chance of 1 coming out with 3 eyes out. Otherwise, no eyes come out. In that case, Ovnunu just waits another 128 frames again, which he also does if all the eyes are already out but haven't been killed yet. So you have to kill the last eye before the next is supposed to come out or you'll have to wait another 128 frames. When it's time to send out another eye and you've killed all 10, Ovnunu will decide to jump out the next time he reaches the bottom. Luck manipulation might be hard since all you have to work with is the amount of eyes killed before it's going to send out more eyes, and the amount of wait frames before you start (Ovnunu begins to wake up when your X coordinate is at least 128 or your Y position is less than 568) IS the most important info. Particularly THIS: (Ovnunu begins to wake up when your X coordinate is at least 128 or your Y position is less than 568)
Player (185)
Joined: 10/8/2006
Posts: 145
*crickets chirping* After a month off I am back to work on this monster. I learned that "frame perfect" isn't always optimal.
Joined: 5/12/2009
Posts: 748
Location: Brazil
Good luck, Brookman! I like this game a lot and look forward to seeing some progress!
Player (185)
Joined: 10/8/2006
Posts: 145
Joined: 7/2/2007
Posts: 3960
The video's private.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Player (185)
Joined: 10/8/2006
Posts: 145
thanks I'll fix that :x
Player (185)
Joined: 10/8/2006
Posts: 145
fixed thanks sorry for double post, didnt realize I posted already cause the first went onto a new page.
Joined: 5/12/2009
Posts: 748
Location: Brazil
Nice fight, Brookman! Hope you can find a way to save those 5 seconds. Good luck!
Player (185)
Joined: 10/8/2006
Posts: 145
http://i.imgur.com/sw62qSn.png Shamelessly using ES's boss fights because . . .they're so good XD Just wrapped up stave IV! WHEW. I made up to stage IV over a month ago and I'm finally making progress again.
Player (185)
Joined: 10/8/2006
Posts: 145
I have completed all of my "optimizations" now all that is left is Scula, crawler, holuthorion, and phalanx. Getting very close to the end.
Joined: 7/2/2007
Posts: 3960
Awesome! Hope everything goes smoothly from here on out.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Joined: 5/12/2009
Posts: 748
Location: Brazil
That's great! Keep it up, Brookman!
Player (185)
Joined: 10/8/2006
Posts: 145
at this rate I will definitely have this submitted by the end of the week. As long as there's no unforeseen interference!
Joined: 5/12/2009
Posts: 748
Location: Brazil
Nice!!! I really look forward to watching this run! Hopefully everthing goes as planned. Good luck!
Player (185)
Joined: 10/8/2006
Posts: 145
Samsara
She/They
Senior Judge, Site Admin, Expert player (2240)
Joined: 11/13/2006
Posts: 2822
Location: Northern California
You can edit the header of the BK2 file if you want the re-record count to be accurate.
TASvideos Admin and acting Senior Judge 💙 Currently unable to dedicate a lot of time to the site, taking care of family. Now infrequently posting on Bluesky
warmCabin wrote:
You shouldn't need a degree in computer science to get into this hobby.
Player (185)
Joined: 10/8/2006
Posts: 145
http://imgur.com/UhCuxaM I think there might be some potential here. The platforms have some form of collission, so they are able to push firebrand slightly. Normally, if firebrand comes into contact with a ceiling that while attempting to board a platform the platform will disappear, that is apparently not the case with walls though. So I'll try to see if I can get him inside a wall :D this is more along the lines of what I expect to happen: http://imgur.com/kvpyvIt the platforms are programmed to prevent these sorts of collision glitches by evaporating. Although, since . .. . there is a ceiling involved in this pic I will have to test on a different spot. I'll also have to test if. .. getting hit is triggering the collision glitches or if it can be done anywhere. http://imgur.com/EAOQQwp in the second gif he's only in the wall for 1 frame. http://imgur.com/Cr2vkoh again, since there'sa ceiling involved here. .. . I'm going to try slightly lower.
HHS
Active player (286)
Joined: 10/8/2006
Posts: 356
To the person who was wondering about positions and speeds: I just found my old disassembly which I thought I had lost. Here are some sprite variables (the player is at $7E1000, others are in a table at $7E1080 of $50 bytes each of 17 entries): 00 - Flags (01 = New, 02 = Active, 04 = Initialized, 08 = Done, 20 = Frozen, 40 = Can't hit) 01 - ID 02 - Type 03 - Parameter 07 - Strength 09 - Direction flags (01 = right, 02 = left, 04 = down, 08 = up) 0A - Display flags 0B - Plane 10 - Display X 12 - Display Y 16 - Pointer to frame data 1B - Flag set if fired by player 1C - Previous X pos (2 bytes) 1E - Previous Y pos (2 bytes) 20 - X speed (2 bytes) 22 - Y speed (2 bytes) 28 - Pointer to sprite collision size 2A - Pointer to BG collision size 2C - Freeze timer 2E - Pointer to damage table 30 - X subpixel 31 - X pos (2 bytes) 33 - Y subpixel 34 - Y pos (2 bytes)
Player (185)
Joined: 10/8/2006
Posts: 145
THANK YOU HHS!!!!!!!!
1 2
12 13 14