Final Fantasy Hacktics

Modding => PSX FFT Hacking => Topic started by: LastingDawn on December 12, 2008, 08:08:10 am

Title: ASM Lessons
Post by: LastingDawn on December 12, 2008, 08:08:10 am
Zodiac taught me the bare bone basics of ASM the other night, but... I can't say how well my ramblings will help in this matter...

Quote[06:12] <Zodiac> o hi thar
[06:12] <Zodiac> ASM Class #0
[06:12] <Lasting_Dawn> Thank you very much Zodiac, hopefully I haven't reached the apex of my "skills" already, well, we're about to find out.
[06:12] <Zodiac> Bitwise operands
[06:12] <Lasting_Dawn> A term long known to me, but one I know next to nothing about.
[06:12] <Zodiac> ahahah
[06:12] <Zodiac> it's not really complicated
[06:12] <Zodiac> you just have to get the hang of binary
[06:12] <Zodiac> can you convert binary to decimal or hex and vice versa?
[06:12] <Lasting_Dawn> Binary is where it's only 0 and 1, right?
[06:12] <Zodiac> yeah
[06:12] <Lasting_Dawn> With... a calculator, certainly.
[06:12] <Zodiac> no, you have to be able to do it manually else you won't be able to code asm
[06:12] <Lasting_Dawn> Oh, alright, let's see this then...
[06:12] <Zodiac> understanding is the key
[06:12] <Lasting_Dawn> Currently looking at a tutorial, I fear to say I never got this far in school.
[06:12] <Zodiac> each bit starting from the left can be worth the double the amount of the previous one
[06:12] <Lasting_Dawn> So... 11101 is...
[06:12] <Zodiac> like in ABCD (let's say this is a binary array) A = 8 or 0 (1;TRUE or 0;FALSE), B = 4/0, C = 2/0 and D = 1/0
[06:12] <Zodiac> of course now I'm converting to decimal ;o
[06:12] <Lasting_Dawn> B = 4 or 0, C = 2 or 0? Is that what you mean?
[06:12] <Zodiac> yeah, just shorter to type
[06:12] <Lasting_Dawn> Alright, I think I understand that part.
[06:12] <Zodiac> I forgot a slash meant "divide" ;o
[06:12] <Zodiac> okay then convert manually this 1101 1001
[06:12] <Lasting_Dawn> The split is important, right?
[06:12] <Zodiac> each set of 4 represents a nibble
[06:12] <Zodiac> the split is only for readability
[06:12] <Lasting_Dawn> Ah, alright, let's see here then...
[06:12] <Zodiac> just as in hex editor you see each byte separately
[06:12] <Lasting_Dawn> 1 = 1, 0 = 0, 0 =0, and 1 = 8?
[06:12] <Lasting_Dawn> Or... vice versa, in this case, as it may be?
[06:12] <Lasting_Dawn> All in all, that makes it 9?
[06:12] <Zodiac> you only calculated the first part
[06:12] <Lasting_Dawn> Alright, second part then.
[06:12] <Zodiac> this is a byte, continue with the other one
[06:12] <Lasting_Dawn> 1 + 4 + 8 = 13 which is... C?
[06:12] <Lasting_Dawn> Or is it D... that always throws me off.
[06:12] <Zodiac> it's C but I never asked for the answer in hex
[06:12] <Lasting_Dawn> Oh, I see. Alright, so just add them 9 + 13?
[06:12] <Zodiac> nope
[06:12] <Lasting_Dawn> Oh, still continue on, I see.
[06:12] <Lasting_Dawn> So the split doesn't split the equation, sorry about that.
[06:12] <Zodiac> only for readability
[06:12] <Zodiac> just like the decimal system: $3,140,599.95
[06:12] <Lasting_Dawn> Yep, just calculating it now.
[06:12] <Lasting_Dawn> 1 + 8 + 16 + 64 + 128 = 217?
[06:12] <Zodiac> yep
[06:12] <Lasting_Dawn> Phew, this is quite simple!
[06:12] <Zodiac> and can you quickly give me the answer in hex?
[06:12] <Zodiac> you already calculated the nibbles earlier
[06:12] <Lasting_Dawn> Not quickly, definitely not quickly, took me long enough to find it earlier.
[06:12] <Zodiac> I was considering the fact you already found C and 9
[06:12] <Lasting_Dawn> Oh, it doesn't come to C9 does it? That's a bit too low for...
[06:12] <Zodiac> wait it's a D
[06:12] <Lasting_Dawn> D9? That makes more sense.
[06:12] <Zodiac> lol anyway, we should be able to start with the bitwise operands now
[06:12] <Lasting_Dawn> So, finding parts of the nibbles, will give you the answer in hex?
[06:12] <Lasting_Dawn> So this is what Hex is based off of? These combined Binaries?
[06:12] <Zodiac> ya
[06:12] <Lasting_Dawn> Well I have to say... that answers a lot of questions at once.
[06:12] <Zodiac> hex is binary easier and faster to read for humans
[06:12] <Zodiac> as is octal
[06:12] <Lasting_Dawn> It makes good sense, I can see why you embrace it so.
[06:12] <Zodiac> but hex is more logical since each character uses 4 (2x2) bits
[06:12] <Lasting_Dawn> And that finally all makes sense to me, heh.
[06:12] <Zodiac> octal uses 3 bits, so characters range from 0-7 :/
[06:12] <Lasting_Dawn> Hmm, I've never heard of Octal used in video games, as far as I'm aware.
[06:12] <Zodiac> Ok so to proceed further on you'll need the Almighty... OPCODE FILEEEEEEEZZZ!!! http://zodiac.ffhacktics.com/PSX-INST.txt (http://zodiac.ffhacktics.com/PSX-INST.txt)
[06:12] <Lasting_Dawn> Oh... very nice.
[06:12] <Lasting_Dawn> Alright, I knew a few of these, but the other's are brand new to me.
[06:12] <Zodiac> rd = register(destination); rs = register(source); rt = register (temp, used as source too); immed. = immediate
[06:12] <Zodiac> to be honest I don't think I know more than 2/3
[06:12] <Zodiac> and only a few are used commonly
[07:12] <Lasting_Dawn> Alright, so rd is basically where the data goes, rs is the source of the data and rt, only temporarily stores things?
[07:12] <Lasting_Dawn> No, rd is where the data Ends up?
[07:12] <Zodiac> rt is the same as rs
[07:12] <Zodiac> ADD rd, rs, rt
[07:12] <Zodiac> rd = rs+rt
[07:12] <Lasting_Dawn> Addword, is adding four bytes to a specified location?
[07:12] <Zodiac> addword!?
[07:12] <Zodiac> ADD means ADDITION
[07:12] <Lasting_Dawn> Oh, heh, my mistake...
[07:12] <Zodiac> do you know what is an immediate?
[07:12] <Lasting_Dawn> Something that takes place... immediately?
[07:12] <Zodiac> well that's good for starters
[07:12] <Lasting_Dawn> Or has first priority?
[07:12] <Zodiac> in asm it is simply a value set in the opcode itself and that isn't loaded from a register
[07:12] <Zodiac> ADDI rt, rs, immed
[07:12] <Zodiac> ADDITION IMMEDIATE
[07:12] <Zodiac> an example of this would be r2, r3, 0x0001
[07:12] <Zodiac> r2 = r3+1
[07:12] <Lasting_Dawn> Ah, alright, that makes sense, whenever I saw r2, r3, I thought they were different storage areas.
[07:12] <Lasting_Dawn> Seems I was quite wrong.
[07:12] <Zodiac> you can freely use 32 registers
[07:12] <Zodiac> r0 to r31
[07:12] <Zodiac> half exception to this is r0 , which is ALWAYS 0
[07:12] <Lasting_Dawn> And what is the functions of the registers? To move data around the ram?
[07:12] <Zodiac> with the help of opcodes it controls everything
[07:12] <Lasting_Dawn> opcodes are the main functions of the game, allowing everything to work in unison?
[07:12] <Zodiac> registers hold the values set and modified by the opcodes
[07:12] <Zodiac> like the game would load the unit's PA in r2, and load the Weapon's WP in r3
[07:12] <Lasting_Dawn> Only one register per function?
[07:12] <Zodiac> no
[07:12] <Zodiac> there can be up to 1 destination register and 2 source registers per opcode
[07:12] <Zodiac> ADD is an example of this
[07:12] <Zodiac> ADD rd, rs, rt
[07:12] <Zodiac> rd = destination; rs/rt = source
07:12] <Lasting_Dawn> The three you just mentioned then?
[07:12] <Zodiac> yeah...
[07:12] <Lasting_Dawn> That didn't come out right, but I can't recall my original thought.
[07:12] <Zodiac> to go back with my example  r2 = 0000000A (10PA) and r3 = 0x0000000F (15WP) then it would use MULT r2, r3 (MULTIPLY)
[07:12] <Lasting_Dawn> Oh, for the normal weapon attack of a sword, for instance?
[07:12] <Zodiac> then it would use MFLO r2 (I'll explain this later, it means move from low where the result is stored)
[07:12] <Zodiac> yeah
[07:12] <Lasting_Dawn> Alright, I think I understand that.
[07:12] <Zodiac> so after those 2 opcodes r2 = 0x00000096
[07:12] <Zodiac> r3 = 0x0000000F because nothing was written there in the process
[07:12] <Zodiac> the value in that register was only read
[07:12] <Lasting_Dawn> Read, but nothing was written.
[07:12] <Zodiac> well exxcept of coruse when it loaded the byte for WP
[07:12] <Zodiac> typo x2*
[07:12] <Lasting_Dawn> Ah, true. I think I understand that, so the WP would still stay loaded, as long as r3 hasn't been rewritten too?
[07:12] <Zodiac> immediates are simple word values (2 bytes) that holds static values, it can be used for counters and loads of other things
[07:12] <Zodiac> yes
[07:12] <Lasting_Dawn> For instance, it's what the game is loading for the WP and PA of character's and the like? Is that the reason that stats (except HP) don't change in the actual battle itself?
[07:12] <Zodiac> most of the registers still hold values of previous routines even after the current one is completed
[07:12] <Lasting_Dawn> Ah, is there any reason why this is?
[07:12] <Zodiac> well yes, sometimes you want to carry over the values
[07:12] <Zodiac> and anywaythe game doesn't know what is a routine
[07:12] <Zodiac> it simple follows the code
[07:12] <Lasting_Dawn> So best to just keep that data loaded in case the game needs it again?
[07:12] <Zodiac> we only call a routine a segment  of code that is called in different circustances
[07:12] <Zodiac> yes precisely
[07:12] <Lasting_Dawn> I think I undersand that now.
[07:12] <Lasting_Dawn> understand*
[07:12] <Zodiac> registers are d-words or integer(as soul would say)
[07:12] <Lasting_Dawn> Ah, so that's what integers are... I only knew them as double words, which is... 8 bytes?
[07:12] <Zodiac> they can hold values of 4 bytes and depending of the opcodes the value can be signed or unsigned
[07:12] <Lasting_Dawn> 64 bits?
[07:12] <Lasting_Dawn> Oh, so they're four bytes and 32 bits?
[07:12] <Zodiac> yeah
[07:12] <Zodiac> a word is 2 bytes
[07:12] <Lasting_Dawn> Oh right... heh, my mistake.
[07:12] <Zodiac> LB      Load Byte         LB      rt, off(base)   rt = memory[base+off] 8 bit
[07:12] <Zodiac> LBU      Load Byte Unsigned      LBU      rt, off(base)   rt = memory[base+off] 8 bit
[07:12] <Zodiac> LB loads values in the register signed as default
[07:12] <Zodiac> as a register is a d-word, -1 is represented as 0xFFFFFFFF
[07:12] <Zodiac> for a byte, it's the same 0xFF
[07:12] <Lasting_Dawn> So only with d-words, can they're be negatives?
[07:12] <Lasting_Dawn> there*
[07:12] <Zodiac> technically speaking you could say that as only opcodes determine if the data will be loaded as signed or unsigned
[07:12] <Zodiac> so let me should you the difference, for a byte holding 0xF0
[07:12] <Zodiac> LBU would become 0x000000F0
[07:12] <Zodiac> on the other hand LB would become 0xFFFFFFF0
[07:12] <Lasting_Dawn> So if it's unsigned, it's always negative?
[07:12] <Lasting_Dawn> No, that seems wrong...
[07:12] <Zodiac> 0xF0 is either worth 240 or -15 depending if it's loaded as sgiedn or unsigned
[07:12] <Lasting_Dawn> unsigned reverses the order?
[07:12] <Zodiac> signed = half values are positives and other half are negative
[07:12] <Zodiac> unsigned = all values are positive
[07:12] <Lasting_Dawn> So, values far beyond 65,535 are possible?
[07:12] <Zodiac> 4,294,967,299 possible values
[07:12] <Lasting_Dawn> Hah, well that's quite a bit...
[07:12] <Zodiac> 4,294,967,296*
[07:12] <Zodiac> 65536*65536 ;o
[07:12] <Lasting_Dawn> So if it's signed, the first word is negative, the second word is positive?
[07:12] <Lasting_Dawn> If it's not signed, they're all positive?
[07:12] <Zodiac> wrong for signed
[07:12] <Zodiac> there is only one word
[07:12] <Lasting_Dawn> Right, right, 4 bytes = one word?
[07:12] <Zodiac> for a word if the value is on the first half, 0x0000 to 0x7FFF, then the value will always be positive no matter what
[07:12] <Zodiac> 2 bytes = word
[07:12] <Lasting_Dawn> But, what you posted has 4 bytes, if I'm not mistaken...
[07:12] <Zodiac> yes, I posted them loaded into registers
[07:12] <Lasting_Dawn> Oh, I see.
[07:12] <Zodiac> with LW and LWU for a word of 0x7FFF, both registers will become 0x00007FFF
[07:12] <Zodiac> as 0x7FFF is a positive value signed, as well as unsigned
[07:12] <Lasting_Dawn> So, regardless of any case, it wouldn't matter if it were signed or unsigned?
[07:12] <Zodiac> exactly
[07:12] <Lasting_Dawn> Ah, alright.
[07:12] <Zodiac> whoever 0x8000 is the start of the other half
[07:12] <Zodiac> while 0x7FFF is the highest positive value of a signed word,
[07:12] <Zodiac> 0x8000 is the lowest negative one
[07:12] <Zodiac> 0x7FFFF = 32767 and 0x8000 = -32768
[07:12] <Lasting_Dawn> So it is -65,536?
[07:12] <Lasting_Dawn> Oh, only half of that.
[07:12] <Lasting_Dawn> I see.
[07:12] <Zodiac> yes, no matterr waht a word can only hold 65536 values :P
[07:12] <Lasting_Dawn> Heh, sorry for that dumb spell.
[07:12] <Lasting_Dawn> So what does this mean? Did those three bytes mean anything?
[07:12] <Lasting_Dawn> Or was it just a test?
[07:12] <Zodiac> just to see if you understood
[07:12] <Zodiac> because you have to understand, phailure is not tolerated
[07:12] <Lasting_Dawn> I think I do now... for the most part.
[07:12] <Zodiac> AND      And            AND      rd, rs, rt
[07:12] <Zodiac> bitwise operand #1! AND
[07:12] <Zodiac> and compares two values (two registers in the case of AND) and stores the value in the destination register
[08:12] <Lasting_Dawn> Which value does it store?
[08:12] <Lasting_Dawn> Both of them?
[08:12] <Zodiac> it compares each bit of each value in pairs and if both bits are TRUE, the result is TRUE
[08:12] <Zodiac> else, FALSE
[08:12] <Zodiac> rd = rs AND rt
[08:12] <Lasting_Dawn> Ah, so IF it does not equal it THEN false?
[08:12] <Zodiac> it compares bits one by one
[08:12] <Zodiac> not the whole values
[08:12] <Lasting_Dawn> So anything with a 00 is automatically false, while anything with 01 or 11, or 10 is true?
[08:12] <Zodiac> I'll show you a small example
[08:12] <Zodiac> 1001 AND 1110
[08:12] <Lasting_Dawn> They're both true, right?
[08:12] <Zodiac> the answer isn't just TRUE or FALSE
[08:12] <Zodiac> if we take the first column of bits, they're 1/1
[08:12] <Zodiac> the result is TRUE (1)
[08:12] <Zodiac> then the second one
[08:12] <Lasting_Dawn> Ah, one is true, one is false?
[08:12] <Zodiac> 0/1, only one is TRUE, therefore the result is FALSE
[08:12] <Zodiac> same for the third one and the last one is 0/0
[08:12] <Zodiac> 1001 AND 1110 = 1000
[08:12] <Lasting_Dawn> False, True, False, False?
[08:12] <Zodiac> true, false, false, false
[08:12] <Lasting_Dawn> But how does it equal that? Does true just automatically go to the front?
[08:12] <Zodiac> no
[08:12] <Lasting_Dawn> Oh, right, combined...
[08:12] <Lasting_Dawn> I see now.
[08:12] <Zodiac> when it compares the fith bit, it will compare each 5th bit
[08:12] <Zodiac> and store the answer in the 5th bit
[08:12] <Zodiac> so try this one 1110 AND 1011
[08:12] <Lasting_Dawn> True, False, False, True (if read from right to left) making it... 0110?
[08:12] <Zodiac> nope
[08:12] <Zodiac> explain how you did it
[08:12] <Lasting_Dawn> Well, the fifth bit was True, but the sixth was False, thereby making it false. the seventh bit was true and so was the eighth, which would make it true,  the first bit is true and so is the second, making that pair true, but third and fourth bit are false, thereby making them false. Since you saiid the answer is stored in the fifth bit, and since the pair was false, that would make a 0, the second part of that sequence would... oh, I see where I went wrong.
[08:12] <Lasting_Dawn> No wait... no I don't. the second part of the sequence would be false., the third sequence is true, making it...
[08:12] <Lasting_Dawn> 1010
[08:12] <Zodiac> ya
[08:12] <Zodiac> break time, 10min
[08:12] <Lasting_Dawn> Ah, alright. I see how that goes now.
[08:12] <Lasting_Dawn> Alright.
[08:12] <Zodiac> resume?
[08:12] <Lasting_Dawn> Alright.
[08:12] <Lasting_Dawn> Took the time to copy and paste the whole of our conversation into a notepad, thus far.
[08:12] <Zodiac> don't copy this line X_X (Voldemort is gay)
[08:12] <Lasting_Dawn> I can't promise anything... heh.
[08:12] <Zodiac> anyway it's been 10min so do it AGAIN: 1001 0111 AND 0011 0110
[08:12] <Lasting_Dawn> Alright, the first one is 0100 the second one is 0001?
[08:12] <Zodiac> not even close
[08:12] <Lasting_Dawn> Wow, I've degraded in the past ten minutes, let me not try to rush...
[08:12] <Zodiac> 1001 0111
[08:12] <Zodiac> 0011 0110
[08:12] <Zodiac> does that help?
[08:12] <Lasting_Dawn> A bit.
[08:12] <Lasting_Dawn> Rigt forgot to reverse... I see where I went wrong.
[08:12] <Zodiac> reverse? you can do it just directly
[08:12] <Lasting_Dawn> Wow, I must have some mental problem or something... this should be 1000 and... 0010?
[08:12] <Zodiac> not at all
[08:12] <Zodiac> so what are you doing?
[08:12] <Lasting_Dawn> Oy... what am I doing wrong here? Fifth bit is false, sixth bit is true, thereby false... seventh and eight are true, thereby true... first is true, second is false, thereby false, third is false and fourth is true, thereby false...
[08:12] <Lasting_Dawn> False, False, True, False... hmm...
[08:12] <Lasting_Dawn> 0010, for the first one...?
[08:12] <Lasting_Dawn> Oy, combining the two...
[08:12] <Lasting_Dawn> False, True, False, False, it's 0100... as far as I can figure.
[08:12] <Zodiac> I'm not even sure what you're doing but I can tell it's wrong
[08:12] <Lasting_Dawn> Oh, did you want me to add them up, or give you the decimal numbers?
[08:12] <Zodiac> 1001 0111
[08:12] <Zodiac> 0011 0110
[08:12] <Zodiac> 0001 0110
[08:12] <Zodiac> last line is the result
[08:12] <Zodiac> if the bits in each value are TRUE, the result is TRUE, else FALSE
[08:12] <Lasting_Dawn> Yes, I have that much... what was I doing wrong?
[08:12] <Zodiac> what were you doing to begin with?
[08:12] <Lasting_Dawn> Oh, I see... what was I reading? I was starting from the fifth bit and onwards.
[08:12] <Zodiac> huh?
[08:12] <Lasting_Dawn> That I started with 0 false, 1 true, = 0 false, then to seven and eight, which was true, and true, which was true.
[08:12] <Lasting_Dawn> I forgot to just read them straight. I'm really not sure what I was thinking.
[08:12] <Zodiac> can you try this one? 1101 1010 AND 0010 0111
[08:12] <Lasting_Dawn> 1000 and 0001?
[08:12] <Zodiac> there is ONE answer
[08:12] <Zodiac> stop splitting
[08:12] <Lasting_Dawn> Bah! Right, I completely forgot about that step... I'm really not sure what I was thinking.
[08:12] <Zodiac> step? there is only one thing to do AFAIK :/
[08:12] <Lasting_Dawn> So the answer is 0001?
[08:12] <Lasting_Dawn> No, wait...
[08:12] <Lasting_Dawn> One is true, one is false, thereby false, both of the other's are false, thereby false, and the second set is false as well as the fourth...
[08:12] <Lasting_Dawn> 0000?
[08:12] <Zodiac> I gave you 2 sets of 8 bits, the answer should be 8bits
[08:12] <Lasting_Dawn> 10000001?
[08:12] <Lasting_Dawn> So... this isn't a decimal answer?
[08:12] <Zodiac> wrong again, okay, what is the first bit of each set?
[08:12] <Lasting_Dawn> 1 and 0
[08:12] <Zodiac> I,ve only posted in binary when it related to binary stuff yet
[08:12] <Zodiac> so FALSE, next bits?
[08:12] <Lasting_Dawn> Oh, I do apologize, I had thought this was a review, I hadn't realized this part was new, sorry I think I have it.
[08:12] <Zodiac> it isn,t new :/
[08:12] <Lasting_Dawn> 00000010
[08:12] <Lasting_Dawn> Wrong, no doubt, hmm...
[08:12] <Zodiac> why? it's the right answer
[08:12] <Lasting_Dawn> Oh, alright. So I understand that part now.
[08:12] <Lasting_Dawn> At first I thought we were just doing before the break,
[08:12] <Lasting_Dawn> Understand, that answer I gave before the break was given through misconstrued means, just a lucky "guess" based on incorrect reasoning.
[08:12] <Zodiac> ah
[08:12] <Lasting_Dawn> Heh, eh well. confusion gone.
[08:12] <Lasting_Dawn> I should be able to proceed.
[08:12] <Zodiac> 1110 1011
[08:12] <Zodiac> 0101 0101
[08:12] <Zodiac> last one
[08:12] <Lasting_Dawn> 10100101?
[08:12] <Zodiac> not at all
[08:12] <Lasting_Dawn> Wow, I feel like a dunce...
[08:12] <Zodiac> the first line is the first value and the second one is the second value
[09:12] <Zodiac> I think you,re comparing the 4 first bits on the line with the 4 last ones
[09:12] <Lasting_Dawn> Oh, I see.
[09:12] <Lasting_Dawn> 01000001?
[09:12] <Zodiac> yeah
[09:12] <Lasting_Dawn> Alright, that makes sense now.
[09:12] <Lasting_Dawn> Of course... I just said that...
[09:12] <Lasting_Dawn> And ended up...
[09:12] <Lasting_Dawn> Screwing up, heh.
[09:12] <Zodiac> heh
[09:12] <Zodiac> and you should try putting spaces every 4 bits
[09:12] <Zodiac> just as you should put 0x or $ before hex numbers
[09:12] <Lasting_Dawn> Alright, I''ll keep that in mind.
[09:12] <Lasting_Dawn> $?
[09:12] <Lasting_Dawn> Any difference from 0s?
[09:12] <Lasting_Dawn> 0x*
[09:12] <Zodiac> in most programming languages it is used to design hex numbers
[09:12] <Lasting_Dawn> Ah, well so all $ this means is ox?
[09:12] <Lasting_Dawn> 0x*
[09:12] <Zodiac> it's a zero, not a o
[09:12] <Lasting_Dawn> Yes, I know, that's a common mistake of mine.
[09:12] <Zodiac> makes me wonder who's the retard that made 0 a number and O a letter
[09:12] <Zodiac> 1 and l are too similar as well
[09:12] <Lasting_Dawn> They are... exactly alike on paper, except 0's a little more oval looking.
[09:12] <Lasting_Dawn> I have to say, I never noticed the similarity between l and 1... until you just mentioned it.
[09:12] <Zodiac> with some fonts there is no difference
[09:12] <Lasting_Dawn> Hah...
[09:12] <Zodiac> as for me I always put more detail into my ones, a habit
[09:12] <Lasting_Dawn> Into l?
[09:12] <Zodiac> 1
[09:12] <Zodiac> I draw the base and the little thingy at the top
[09:12] <Lasting_Dawn> Ah, definitely an odd habit.
[09:12] <Zodiac> let's move to OR
[09:12] <Lasting_Dawn> Certainly, I'm ready.
[09:12] <Lasting_Dawn> Or... hmm, always wondered how this works.
[09:12] <Zodiac> with AND; 1/1 = 1 else 0
[09:12] <Lasting_Dawn> Same case with OR?
[09:12] <Zodiac> with OR; 0/0 = 0 else 1
[09:12] <Lasting_Dawn> Ah.
[09:12] <Lasting_Dawn> Alright.
[09:12] <Zodiac> the opposite
[09:12] <Zodiac> or in other terms, as long as there is one bit true, the answer is true
[09:12] <Lasting_Dawn> Understood.
[09:12] <Zodiac> think you can give it a shot right now?
[09:12] <Lasting_Dawn> Yep.
[09:12] <Zodiac> 1110 1011
[09:12] <Zodiac> 0101 0101
[09:12] <Zodiac> same as last :P
[09:12] <Lasting_Dawn> Ah, but there is a Jump Return, isn't there?
[09:12] <Lasting_Dawn> Nope, there is not... not on this list anyhow.
[09:12] <Zodiac> then MOST of the time, to end routine a JR r31 will be there
[09:12] <Lasting_Dawn> So ending a routine requires using r31?
[09:12] <Zodiac> yes because JAL stores the current position in r31 before moving to the routine
[09:12] <Lasting_Dawn> Alright, I think I understand that part.
[09:12] <Zodiac> now that you know what JAL does, DON'T USE IT
[09:12] <Lasting_Dawn> Oh?
[09:12] <Zodiac> chances are, you're already in a routine, and that would mean r31 already has a return offset
[09:12] <Lasting_Dawn> Therefore it would screw something up?
[09:12] <Zodiac> if you were to use JAL, it would overwrite it with the current location
[09:12] <Zodiac> and it would never go back from where it came
[09:12] <Lasting_Dawn> Ouch... reload at that point?
[09:12] <Zodiac> chances of freezing are almost guaranteed
[09:12] <Zodiac> yeah maybe reload, that's quite rare with me though lol
[09:12] <Lasting_Dawn> Hmm, so avoid using JAL for most cases.
[09:12] <Zodiac> I get about 60% freeze, 30% crash, 10% resert
[09:12] <Zodiac> reset*
[09:12] <Lasting_Dawn> That's right.. the game sometimes resets itself?
[09:12] <Zodiac> yeah
[09:12] <Zodiac> pretty rare though
[09:12] <Zodiac> I hate when it crashes
[09:12] <Zodiac> have to reload the emulator and the debugger :/
[09:12] <Lasting_Dawn> That requires shutting out of the sys... yeah.
[09:12] <Zodiac> so... if you didn't guess it already JUMP just, well JUMPS
[09:12] <Lasting_Dawn> Yep, jumps to a point somewhere in the 256 MB range?
[09:12] <Zodiac> well the only problem is...
[09:12] <Zodiac> the PSX has 2mb RAM
[09:12] <Zodiac> not 256
[09:12] <Zodiac> it will probably just crash if you try to go that far :D
[10:12] <Souylsin> There's different types of branches
[10:12] <Souylsin> theres
[10:12] <Souylsin> BNE
[10:12] <Souylsin> which is
[10:12] <Souylsin> Branch not Equal
[10:12] <Souylsin> so
[10:12] <Souylsin> BNE T2,T3,target
[10:12] <Lasting_Dawn> If t2 doesn't equal t3, then...?
[10:12] <Souylsin> IF T2 doesnt equal T3 then jump to targt
[10:12] <Souylsin> target*
[10:12] <Souylsin> Yes!
[10:12] <Souylsin> Exactly that
[10:12] * Cadet19 is now known as Kokojo
[10:12] <Souylsin> simple, right?
[10:12] <Lasting_Dawn> Ah, alright. but there must be quite a few minutae that use that for many, many things?
[10:12] <Souylsin> yeah
[10:12] <Lasting_Dawn> I'll keep that in mind, it is pretty simple.
[10:12] <Kokojo> hey souylsin, sorry if thats totally random, but is it some sort of choice ? (yes, i din't follow, but i want to know something about choices in FFT)
[10:12] <Souylsin> wut
[10:12] <Souylsin> ok
[10:12] <Souylsin> Generally all branches are just IF statements/commands
[10:12] <Souylsin> in asm form
[10:12] <Souylsin> :D
[10:12] <Souylsin> ZODIAC HOW ARE THOSE HARD TO TEACH
[10:12] <Lasting_Dawn> Alright I think I have those.
[10:12] * Souylsin facepalmfacepalmfacepalmfacepalm
[10:12] <Zodiac> not my fault if the others understands everything but branches and it's the exact opposite with LD
[10:12] <Souylsin> ku bad teacherz
[10:12] <Souylsin> btw i recommend n64 opcode listz
[10:12] <Souylsin> fo u zodiac
[10:12] <Zodiac> Souylsin NOT cool NOR awesome
[10:12] <Lasting_Dawn> Heh... I did a bit of experiementing with them (unknowingly...) in my Zelda hacking days, so I know a slight bit about them, therefore it came easy.
[10:12] <Cheetah> are you saving all this stuff too LD?
[10:12] <Lasting_Dawn> On here...? I probably should.
[10:12] <Zodiac> ya do it
[10:12] <Souylsin> Zodiac: gogogo http://www.zophar.net/fileuploads/2/106 ... 4ops03.txt (http://www.zophar.net/fileuploads/2/10655uytsm/N64ops03.txt)
[10:12] <Souylsin> syscall gogogo
[10:12] <Souylsin> what im interested in is how it allocates space for stuff
[10:12] <Lasting_Dawn> Oh it is right here, very nice.
[10:12] <Cheetah> yeah, plus those two links, and then upload it all in a new ASM thread
[10:12] <Lasting_Dawn> Alright, I'll do that then.
[10:12] <Souylsin> CACHE    op,offset(base)  CACHE <--- looks cool
[10:12] <Lasting_Dawn> CACHE? I don't recall that...
[10:12] <Lasting_Dawn> Not in the PSX version.
[10:12] <Souylsin> probably isnt in it
[10:12] <Lasting_Dawn> of... wait... I thought N64 and PSX had the same ASM?
[10:12] <Souylsin> probably n64 specific
[10:12] <Zodiac> cuz PSX is OUTDATED
[10:12] <Souylsin> OH ZODIAC
[10:12] <Souylsin> Have you taught floating point instructions
[10:12] <Souylsin> yety
[10:12] <Souylsin> yet&
[10:12] <Zodiac> no
[10:12] <Zodiac> never used them
[10:12] <Souylsin> LOL GOOD LUCK
Title:
Post by: Vanya on December 12, 2008, 12:53:20 pm
Thanks for posting this, LD! ^_^
I only read the first half, but I learned a lot already.
To be honest it's just what expected from MIPS.
Much more complex than 6502 ASM. I only get 2 registers on the NES. =P
On the other hand it allows the programmer to do a lot more. ^_^
I Hope you post more of these.
The more ppl we have working on the ASM problems we come up with the better!
Title:
Post by: DarthPaul on December 12, 2008, 12:58:16 pm
This will definitely help people......then again I already understood 85% of it lol :)
Title:
Post by: Vanya on December 12, 2008, 01:07:14 pm
I wish I did already. I only consider myself 60% good at 6502. I've got a ways to go yet. Fucked up part is I could recreate most of the FFT engine in like a week if I did it in GameMaker with GML only. =P
Title:
Post by: DarthPaul on December 12, 2008, 01:09:18 pm
I don't think I could do it in a timely manner so you beat me there Vanya, but I did learn from this so it was a worth while read despite its length.
Title:
Post by: Vanya on December 12, 2008, 01:20:00 pm
I agree. ^_^
Title:
Post by: Xifanie on December 12, 2008, 03:33:29 pm
Class #0 was about learning the ASM basics. The few things I didn't have time to explain will be explained in the next class.

Class #1 will focus mainly on learning on how to use the tools provided and Class #2 will be hax0ring.

Stay tuned biatchez.
Title:
Post by: DarthPaul on December 12, 2008, 04:00:42 pm
Can't wait for class 2 so I can see where my hax0ring is going wrong.
Title:
Post by: Vanya on December 12, 2008, 04:32:47 pm
Me, too. I really want to lend a hand in all this and so few ppl are willing to teach. Much props to you 1337 haxx0r z0D14k!! ^_^
Title:
Post by: nates1984 on December 12, 2008, 07:23:04 pm
Begin random question in ASM topic:

Some registries are assigned to sprites, that's why there's a limitation on how many different ones can be included in each battle.

The fix would be to rewrite everything, formulas or whatever else is stored into registries, so that say registry 6, or 6-12 (whatever) isn't used anymore, then it could be assigned to a sprite. Then you could increase the number of sprites allowed in a battle by sacrificing something somewhere else.

In short: time consuming and never gonna happen?

Is this win? Y/N

I have heard the sprite limitation is due to the RAM, so you're basically working within a system where the amount of space is determined beforehand. Registries are basically there to say what to load into the RAM, what to do with it, ect? You could increase the RAM, but you'd have to increase the amount of allowable registries to take advantage of it?

Or am I totally off base on all counts?

During a battle, some registries are used for character sprites, map files, ect. So the formulas for damage and what-not are going in and out of certain registries, as are animation instructions and other things.

Do formulas use shared values? Like is there information there for PA, and multiple formulas call that same PA piece for use? Or, I should say, each characters PA is stored in the registers in a fight. Then a formula will call for that characters PA, but doing it using the same PA value instruction, so changing the PA value to MA would make more then just that one formula use MA instead of PA?
Title:
Post by: Cheetah on December 12, 2008, 07:54:47 pm
So sweet, keep posting these please :).
Title:
Post by: Vanya on December 13, 2008, 01:05:48 am
Quote from: "nates1984"Begin random question in ASM topic:

Some registries are assigned to sprites, that's why there's a limitation on how many different ones can be included in each battle.

ok. i'M DRUNK OFF OF WODKA, BUT i KNOE THIS MUCH1 YOUR FISRT STATEMENT IS ERRONEOUS.

sPRITES ARE HELD IN ram NOT REGISTRIES. tHE LIMIT OF THE NUMBER OF SPRITES HAS TO DO WITH THE pLAYSTATIONS'S LIMITED VIDEO ram. PPL CRITISIZED THE SYSTEM FOR IT'S LIMITED VIDEO RAM FOR A LONG TIME. iT HAD LESS VIDEO RAM THAN THE snes, Iirc.

sO. TO GO BEYOND IT'S LIMITED VIDEO ram YOU'D HAVE TO PROGRAM A SPECIAL emulator to use more video RAM.

^_^
Title:
Post by: The Damned on December 13, 2008, 01:34:06 am
Thank you very much, both LastingDawn and Zodiac. As the latter knows, I had been meaning to learn this in an attempt to help out with it.

I pretty much understood everything up to the base 2 and base 16 part, but after that, I got lost, maybe because I didn't click on the link. Oh well, it's probably better for me to read it tomorrow anyway since I just got back from work and I've been tired all day.
Title:
Post by: Vanya on December 13, 2008, 02:16:23 am
thee tutorils have the potential to boost the community into a golden age. They are very appreciated!! ^_^
Title:
Post by: BeoulveBlack on December 13, 2008, 12:08:46 pm
oh boy.... my head's spinning after the first half. i'll finish reading it when i get back from work; i'm excited about the next class though. i really would rather not bother people (SB) about ASM stuff if i can learn it myself.
Title:
Post by: DarthPaul on December 13, 2008, 01:46:48 pm
Vanya you know posting when your drunk gives us all the laugh of a lifetime.
Title:
Post by: Xifanie on December 13, 2008, 11:13:05 pm
LD Where are you, it's time for the next class you...!!
Title:
Post by: Vanya on December 14, 2008, 01:28:31 pm
I live to bring joy to others... and make a small profit if possible. ^_^
Title:
Post by: LastingDawn on December 15, 2008, 08:22:29 pm
Sorry about that, I was at my brother's for a couple of days, three day weekend and I hardly get to see them anymore. But yes, whenever you're ready to teach, I'll be around.
Title:
Post by: LastingDawn on December 16, 2008, 08:59:09 am
Part 2 of Basics
Part 1 of Tools

Quote[08:12] <Zodiac> o hi thar
[08:12] <Zodiac> ASM Class #1
[08:12] <Lasting_Dawn> Ready and waiting. As always, thank you.
[08:12] <Zodiac> loading/storing and...
[08:12] <Zodiac> multiply/divide
[08:12] <Lasting_Dawn> Aie, division... well this should be interesting.
[08:12] <Zodiac> Soul explained to you all the stuff with branches right&
[08:12] <Lasting_Dawn> Indeed.
[08:12] <Zodiac> ANd I think you forgot to put your conversation with soul in the topic
[08:12] <Lasting_Dawn> Did I? I thought I got that part? At the very end?
[08:12] <Zodiac> oh right
[08:12] <Zodiac> anyway which do you wanna start with?
[08:12] <Lasting_Dawn> LEt's see... loading/storing
[08:12] <Lasting_Dawn> Let's*
[08:12] <Zodiac> the processor can load/store bytes/words/d-words
[08:12] <Lasting_Dawn> And it stores them in registers?
[08:12] <Zodiac> store means taking the value in a register and write it in the ram
[08:12] <Zodiac> the opposite of loading
[08:12] <Lasting_Dawn> So it takes a value in a register,  and writes it, effectively storing it somewhere in RAM?
[08:12] <Zodiac> maybe my idea of a word was wrong all this time? http://zodiac.ffhacktics.com/PSX-INST.txt (http://zodiac.ffhacktics.com/PSX-INST.txt) says a "half-word" is 16bit, a word is 32bit and a d-word is 64bit :/
[08:12] <Lasting_Dawn> So... I was right, last time then?
[08:12] <Zodiac> mmm Delphi's help says I'm right though
[08:12] <Zodiac> Byte   0..255   unsigned 8-bit
[08:12] <Zodiac> Word   0..65535   unsigned 16-bit
[08:12] <Zodiac> Longword   0..4294967295   unsigned 32-bit
[08:12] <Zodiac> anyway a "half-word" sounds pretty stupid if you ask me
[08:12] <Lasting_Dawn> Well, I have to admit, I was taught that a word was 4 bytes, a half word, 2 bytes and a d-word was 8 bytes.
[08:12] <Zodiac> where?
[08:12] <Lasting_Dawn> From the folks at ZSO.
[08:12] <Zodiac> huh..
[08:12] <Lasting_Dawn> Though the majority were squabbling power hungry fools, some of them actually knew what they were talking about, I never doubted their skills and knowledge, just their characters...
[08:12] <Zodiac> now I see, this is rather stupid... the length of "words" vary depending on the processor
[08:12] <Lasting_Dawn> Hah! Well... that clears that up, but makes explanations oh so confusing...
[08:12] <Zodiac> definitely, I'd rather all "words" have the same length
[08:12] <Lasting_Dawn> In any case, that covered Storing, but what of Loading?
[08:12] <Zodiac> well I guess I'll have to adapt
[08:12] <Lasting_Dawn> And is there anything we missed with Storing?
[08:12] <Zodiac> lb = load byte; lh = load half word; lw = load word
[08:12] <Zodiac> they all got store versions of course and the first two have unsigned versions
[08:12] <Zodiac> to load or store you need a memory address in a register
[08:12] <Lasting_Dawn> Ah, this will tell what format is the data you are looking for, I believe?
[08:12] <Zodiac> yeah well there is no point in loading 4 bytes when you only need one
[08:12] <Lasting_Dawn> If you see an LB instruction it will be pointing towards a single byte?
[08:12] <Zodiac> yeah
[08:12] <Lasting_Dawn> Alright, I understand that, so that's it for Storing and Loading?
[08:12] <Zodiac> no,
[08:12] <Zodiac> you ahve to be able to create a memory address
[08:12] <Zodiac> you need at least lui in order to do so
[08:12] <Lasting_Dawn> Oh? Please explain.
[08:12] <Zodiac> it resets the register and writes the immediate in the upper part of the register
[08:12] <Zodiac> hence "load upper immediate"
[08:12] <Lasting_Dawn> For loading, this applies to?
[08:12] <Lasting_Dawn> But if I recall, you haven't taught me about the upper and lower parts of a "register" yet.
[08:12] <Zodiac> like if you want to load cure's JP cost which has a memory address of 0x8005EBF8
[08:12] <Zodiac> the upper part is simply the 2 highest bytes
[08:12] <Zodiac> out of 4
[08:12] <Zodiac> so loading that one would be rather simple
[08:12] <Lasting_Dawn> So when you load higher it's just two bytes and lower is the later two bytes?
[08:12] <Zodiac> lui r2, 0x8005
[08:12] <Zodiac> lhu r2, 0xEBF8(r2)
[08:12] <Zodiac> yes
[08:12] <Zodiac> this is the fastest way to load a single value
[08:12] <Lasting_Dawn> Ah, that clears up quite a bit.
[08:12] <Zodiac> if you need many values in the same range, you can use addiu r2, r2, 0xEBF8
[08:12] <Lasting_Dawn> add immediate upper, register 2, register 2?
[08:12] <Zodiac> then load like this lhu r3, 0x0000(r2)
[08:12] <Zodiac> lhu r4, 0x0001(r2)
[08:12] <Zodiac> lhu r5, 0x0002(r2)
[08:12] <Zodiac> errr u = unsigned
[08:12] <Lasting_Dawn> Oh right, heh...
[08:12] <Zodiac> whenever you see a register in parenthesis, it means it will load/store at from the location in the register PLUS the specified immediate
[08:12] <Lasting_Dawn> load or store, or load and store, in this case?
[08:12] <Zodiac> lhu r5, 0x0002(r2) would load r2: 0x8005EBF8, and add 0x0002 for location 0x8005EBFA
[08:12] <Zodiac> or
[08:12] <Zodiac> since when can a slash mean and? did I miss something O_O
[08:12] <Lasting_Dawn> True, true, good point.
[08:12] <Zodiac> if you need to use the register again, I'd recommand leaving it with the memory address so you don't have to write it again in order for it to store the new value
[08:12] <Zodiac> use other registers instead
[08:12] <Lasting_Dawn> But what decides where these are written to in RAM? I noticed you put memory addresses, but I can't see how they were logically conceived, in this case.
[08:12] <Zodiac> GS codes use memory address
[08:12] <Zodiac> asm code does as well
[08:12] <Zodiac> j 0x801924B8 means jumping to that memory address
[08:12] <Lasting_Dawn> Ah? Sometimes they are simply displayed where it is in the memory?
[08:12] <Zodiac> asm is just hex, 4 bytes each
[08:12] <Zodiac> I'm not sure what you were trying to say
[08:12] <Lasting_Dawn> I understand that, yes. But in a few of the instructions there are actual memory addresses put? Such as the one you put there.
[08:12] <Lasting_Dawn> 0x801924BB
[08:12] <Zodiac> yes
[09:12] <Lasting_Dawn> And that helps us identify where things lead and the like?
[09:12] <Zodiac> yeah well jumps are related more to asm code itself where concerning our storing/loading the memory address is in a register itself
[09:12] <Lasting_Dawn> Ah, I see where my confusion arises, just one minute.
[09:12] <Lasting_Dawn> lhu r5, 0x0002(r2) would load r2: 0x8005EBF8, and add 0x0002 for location 0x8005EBFA
[09:12] <Lasting_Dawn> What is in this that says to load 0x8005EBF8?
[09:12] <Zodiac> with lui r2, 0x8005
[09:12] <Zodiac> lhu r2, 0xEBF8(r2)
[09:12] <Zodiac> r2 = 0x8005EBF8
[09:12] <Zodiac> wait wtf
[09:12] <Zodiac> woops this should be more like this:
[09:12] <Zodiac> lui r2, 0x8005
[09:12] <Zodiac> addiu r2, r2, 0xEBF8
[09:12] <Zodiac> sorry
[09:12] <Lasting_Dawn> Ah, that makes more sense, thank.
[09:12] <Zodiac> then it would take  0x8005EBF8 in r2, add 0x0002 because of the immediate and load in r5 from 0x8005EBFA
[09:12] <Lasting_Dawn> Perfect! I understaodd that word for word.
[09:12] <Lasting_Dawn> understood*
[09:12] <Zodiac> alright, we'll jump to multiply/divide
[09:12] <Lasting_Dawn> Alright.
[09:12] <Zodiac> to avoid confusion I'm the first one I'll start division before multiply
[09:12] <Lasting_Dawn> Sounds fine to me.
[09:12] <Zodiac> do you know what a remainder is?
[09:12] <Lasting_Dawn> What is left of an imperfect division?
[09:12] <Zodiac> yeah
[09:12] <Lasting_Dawn> Indeed.
[09:12] <Zodiac> 19/8 = 2 and 3/8
[09:12] <Zodiac> well it works pretty much like that
[09:12] <Zodiac> there are two special registers concerning mult and div
[09:12] <Zodiac> HI and LO
[09:12] <Zodiac> div 19, 8 would store 2 in LO and 3 in HI
[09:12] <Zodiac> because there are two different results this is why you cannot specify a target register with div and mult
[09:12] <Lasting_Dawn> Ah, therefore it's not the best idea to search for specifics using them?
[09:12] <Zodiac> div rs, rt
[09:12] <Zodiac> specifics? like what
[09:12] <Lasting_Dawn> A target, as you just said.
[09:12] <Zodiac> as they are special register you can't directly read/write them
[09:12] <Zodiac> div/mult writes to them and mflo/mfhi reads them and stores the value in the target register
[09:12] <Lasting_Dawn> Doesn't that mean they can't be altered them?
[09:12] <Zodiac> mflo stands for move from low
[09:12] <Zodiac> if you want to use them, you need to pull themm out of the LO/HI registers
[09:12] <Zodiac> and if you don't want you wouldn't have used mult/div to begin with :(
[09:12] <Lasting_Dawn> Heh, I've always remained well knowing in subjects that interest me, FFT, Zelda 64, and History are basically those three.
[09:12] <Lasting_Dawn> Oh yes, spelling of words as well.
[09:12] <Zodiac> I'm getting a bit trouble with that in French, probably a lack of pratice because I type, type, then hit enter and notice my grammatical mistakes at the same instant
[09:12] <Zodiac> but gravity and cinetic energy pullls so hard and then, too late; message sent ;(
[09:12] <Lasting_Dawn> Well I normally try to look over my messages before I send them, though sometimes, I screw up as well.
[09:12] <Zodiac> well I guess that sums it for divide
[09:12] <Zodiac> mult is a two registers opcode too
[09:12] <Lasting_Dawn> That wasn't as complicated as I thought, it's mainly used in those formulas then?
[09:12] <Zodiac> yeah mainly
[09:12] <Lasting_Dawn> Multiplying though is used for nearly every formula though, isn't it?
[09:12] <Zodiac> yep
[09:12] <Lasting_Dawn> So that will show up much more often? But it will follow the same rules as division with a HI and LO?
[09:12] <Zodiac> now why the heck is there no target register again?
[09:12] <Lasting_Dawn> Because there could be different results?
[09:12] <Zodiac> LOW holds the low 32 bits of the multiply, HI holds the high 32 bits of the multiply.
[09:12] <Zodiac> not really necessary IMHO
[09:12] <Zodiac> I'd rather have a target register
[09:12] <Lasting_Dawn> So is it that they don't have a target register, or is it that it's more difficult to find?
[09:12] <Zodiac> plus it's pretty hard to use a value of 64bit when registers are only 32bit
[09:12] <Zodiac> like huh what? it doesn,t have a target register because it stores the higher result in HI and the other part in LO
[09:12] <Lasting_Dawn> Ah, that's the part I wasn't understanding, alright I see it now.
[09:12] <Lasting_Dawn> So HI and LO are reserved ffor Multiplying and Dividing?
[09:12] <Zodiac> and unless you need to calculate a number over 4294967296 you'll never use HI
[09:12] <Zodiac> yeah
[09:12] <Lasting_Dawn> Oh, but the game uses HI for the CT in Math Skills, does it not?
[09:12] <Zodiac> we're still talking about multiplications
[09:12] <Lasting_Dawn> Oh, good.
[09:12] <Zodiac> don't take division into account now ;o
[09:12] <Zodiac> HI mult = never used
[09:12] <Lasting_Dawn> So you'll only need LO mult?
[09:12] <Zodiac> basically yeah
[09:12] <Lasting_Dawn> Alright, that clears that.
[09:12] <Zodiac> unless you,re gonna do HUGE ass multiplications HI will always be 0
[09:12] <Zodiac> well that sums it for the basics!
[09:12] <Lasting_Dawn> Ah? Well that all wasn't too difficult, I was admittedly a bit frightened with multiplication and dividing.
[09:12] <Lasting_Dawn> But it doesn't seem that complicated at all.
[09:12] <Lasting_Dawn> It seems the important part to remember is HI and LO when dealing with these?
[09:12] <Zodiac> if you know what result they hold, you'll remember

Quote[09:12] <Zodiac> Second part of the class: TOOLS
[09:12] <Zodiac> - pSX 1.13 debugger http://psxemulator.gazaxian.com/pSX_1_13.rar (http://psxemulator.gazaxian.com/pSX_1_13.rar) (just for other people reading); the emulator we'll use
[09:12] <Lasting_Dawn> Hehe, alright. A good idea.
[09:12] <Zodiac> - Renegade 64 http://zodiac.ffhacktics.com/renegade64v169.rar (http://zodiac.ffhacktics.com/renegade64v169.rar)
[09:12] <Lasting_Dawn> Currently copying the first part to keep it seperate from the second.
[09:12] <Zodiac> - A memory editor of your choice (I recommand Cheat Engine: http://www.heijnen1.demon.nl/CheatEngine54.exe (http://www.heijnen1.demon.nl/CheatEngine54.exe))
[09:12] <Zodiac> - A hex editor
[09:12] <Zodiac> - FFTPatcher
[09:12] <Zodiac> - Windows Calc
[09:12] <Lasting_Dawn> Ah, Renegade can use PS1 games?
[09:12] <Zodiac> r3000 and r4000 are VERY similar
[09:12] <Zodiac> In fact, I have no idea what new instructions the r4000 got
[09:12] <Lasting_Dawn> Didn't it get that syscall or whatever Souylsin was referring to?
[09:12] <Zodiac> mmm I'm not sure if the PSX got that or not
[09:12] <Zodiac> anyway tell me when you got everything
[10:12] <Lasting_Dawn> Let me check that Renegade version.
[10:12] <Lasting_Dawn> Hmm... I have RenegadeEx100, their newest version, I think.
[10:12] <Lasting_Dawn> Should I use that one?
[10:12] <Zodiac> don't know I'd need to try out Ex100 but I can,t find it
[10:12] <Lasting_Dawn> Oh, I'll put it in my FTP.
[10:12] <Lasting_Dawn> Should be there now.
[10:12] <Zodiac> nope, that version won't do
[10:12] <Lasting_Dawn> Alright, I'll use the one in the link then.
[10:12] <Zodiac> because the one you have cannot assemble code
[10:12] <Lasting_Dawn> Ah, that is a problem...
[10:12] <Zodiac> and I couldn't make it support pSX anyway
[10:12] <Lasting_Dawn> Souylsin was wrong then, eh well... it happens.
[10:12] <Lasting_Dawn> Alright. Done.
[10:12] <Zodiac> got everything in the list?
[10:12] <Lasting_Dawn> Everything besides a Windows Calculator.
[10:12] <Lasting_Dawn> Can I use one on an internet page?
[10:12] <Zodiac> huh... sure
[10:12] <Zodiac> it's just to add/subtract 0x02B0 anyway
[10:12] <Lasting_Dawn> Alright, that's everything then.
[10:12] <Zodiac> well you know how to use a memory editor I suppose?
[10:12] <Lasting_Dawn> I know my way around one, slightly.
[10:12] <Zodiac> can you find ramza's HP in battle easily?
[10:12] <Lasting_Dawn> Definitely not, I honestly had no idea that Renegade could attach to a PSX!
[10:12] <Lasting_Dawn> But Renegade is a memory editor I have some slight experience with, but I can't make heads or tails of Cheat Engine.
[10:12] <Zodiac> I never talked about renegade
[10:12] <Zodiac> well first of all you need to attach Cheat Engine to pSX
[10:12] <Zodiac> click the flashy icon and select pSX's process
[10:12] <Lasting_Dawn> Alright, that should take but a second.
[10:12] <Lasting_Dawn> Attached.
[10:12] <Zodiac> ok load savestate with ramza in battle or anyone else
[10:12] <Lasting_Dawn> Has to be savestate?
[10:12] <Lasting_Dawn> Oh well, done.
[10:12] <Zodiac> no jsut way faster :/
[10:12] <Zodiac> ok what's your current HP
[10:12] <Lasting_Dawn> Alright, well I do happen to have one, when I was testing out an Ability for Mercenaries, let's see here...
[10:12] <Lasting_Dawn> 429
[10:12] <Zodiac> and what integer type is HP?
[10:12] <Lasting_Dawn> Two bytes, or a half word?
[10:12] <Zodiac> yep
[10:12] <Lasting_Dawn> So search for 429 in hex?
[10:12] <Zodiac> does the game displays HP in decimal on in hex on your screen?
[10:12] <Zodiac> or in hex*
[10:12] <Lasting_Dawn> Haha! Of course, of course.
[10:12] <Lasting_Dawn> 429 turns to 1AD
[10:12] <Lasting_Dawn> So search AD01?
[10:12] <Zodiac> why bother so much
[10:12] <Zodiac> you see the checkbox on the left?
[10:12] <Lasting_Dawn> Of cheat engine?
[10:12] <Zodiac> left of the value fiedl
[10:12] <Lasting_Dawn> Hex, right...
[10:12] <Lasting_Dawn> Heh, how did I miss that.
[10:12] <Lasting_Dawn> Just search 429 then...
[10:12] <Zodiac> exactly
[10:12] <Lasting_Dawn> Quite a few results.
[10:12] <Zodiac> well that's what next search is for
[10:12] <Zodiac> now ALTER your HP
[10:12] <Zodiac> and search for it's new value
[10:12] <Zodiac> given HP is two bytes, only once should be enough
[10:12] <Lasting_Dawn> AlrighAlright 429 to 259
[10:12] <Lasting_Dawn> Should I run a search for 259 now?
[10:12] <Zodiac> yes but using next search
[10:12] <Zodiac> next scan*
[10:12] <Lasting_Dawn> Alright, I get a lot of results.
[10:12] <Zodiac> that stuff was taking me 30sec-2mins on my old computer
[10:12] <Zodiac> now barely 1 second lol
[10:12] <Lasting_Dawn> Haha, all you need now is a better internet, and you'll be set!
[10:12] <Zodiac> yeah, but taht won't happen here. I'm gonna leave for Japan way before we can get high speed.
[10:12] <Lasting_Dawn> Haha! Wow... that's... a long time.
[10:12] <Zodiac> how much results do you have right now?
[10:12] <Lasting_Dawn> For 259?
[10:12] <Zodiac> ya
[10:12] <Lasting_Dawn> A ton.
[10:12] <Lasting_Dawn> 1222
[10:12] <Zodiac> that's impoossible you didn't click NEXT SCAN
[10:12] <Zodiac> you clicked New Scan
[10:12] <Lasting_Dawn> Ah, sorry about that, what's the difference, if I may ask?
[10:12] <Zodiac> when you start a new scan, it will memorize the location of all bytes/halfwords/words or whatever that has the value you specified
[10:12] <Zodiac> when you use thex search, it checks only those values  and list again but only those with the new values
[10:12] <Lasting_Dawn> Ah, I see! that's convenient!
[10:12] <Zodiac> and if you ever do a mistake you can undo scan; but only once
[10:12] <Lasting_Dawn> Odd, I reset the whole thing, New Scanned 429 then next scanned my current HP and didn't get a result it looks.
[10:12] <Zodiac> it usually doesn't take many searches to find the right offset anyway
[10:12] <Zodiac> if you new searched for 429 HP when ramza DIDN'T have 429 HP you can't find the HP
[10:12] <Lasting_Dawn> Ah! Got it!
[10:12] <Zodiac> because it was not part of the original search to begin with
[10:12] <Lasting_Dawn> Went to a different savestate and restarted, hurt Ramza 14 and I have one result.
[10:12] <Lasting_Dawn> 0204D064
[10:12] <Zodiac> you can double click it and it will go in the editable list
[10:12] <Lasting_Dawn> Haha! I feel so dumb not knowing this all this time!
[10:12] <Zodiac> change the value to 999 and go check ramza's HP
[10:12] <Zodiac> you can make it higher too for the lulz
[10:12] <Lasting_Dawn> FFFF apparently makes his HP bar read 0, but he still has the same amount according to the game.
[10:12] <Lasting_Dawn> But that couldn't be further from the truth.
[10:12] <Zodiac> if you don't change the max HP as well (which are the 2 next bytes right after the current HP btw)
[10:12] <Zodiac> if you don't change the max HP as well (which are the 2 next bytes right after the current HP btw)
[10:12] <Zodiac> it will reset back to Max HP
[10:12] <Lasting_Dawn> Yes, it did, interesting...
[10:12] <Zodiac> 65535/400 > 400/400
[10:12] <Lasting_Dawn> Wow, that made his HP jump off the map! The bar is literally off screen!
[10:12] <Zodiac> hehe
[10:12] <Zodiac> that happens
[10:12] <Lasting_Dawn> Odd, but that reset as well, when I left that menu.
[10:12] <Zodiac> huh weird
[10:12] <Zodiac> ok so now you can handle the memory editor properly?
[10:12] <Lasting_Dawn> Yep, I think I can.
[10:12] <Zodiac> sadly you can't use 0204D064 as a memory address
[10:12] <Lasting_Dawn> Hmm?
[10:12] <Zodiac> because this is a proccess memory address and not the PSX's in the emulator
[10:12] <Lasting_Dawn> That does explain a few things...
[10:12] <Zodiac> there are two ways to convert it
[10:12] <Zodiac> subtract from it a specific value, or search for the surrounding values in the savestate
[10:12] <Zodiac> for the first one you need to the the second one a first time anyway
[10:12] <Lasting_Dawn> Those are the only two ways? Doesn't that leave our options rather limited then? I've seen an absolute ton outside of the range.
[10:12] <Zodiac> right click on the row with the HP value/offset and stuff
[10:12] <Zodiac> nah not really much ways
[10:12] <Zodiac> and click browse memory editor
[10:12] <Zodiac> browse this memory region*
[11:12] <Lasting_Dawn> Crash, my fault...
[11:12] <Lasting_Dawn> Forgot I took out Card.out to see what it did...
[11:12] <Lasting_Dawn> Well, I found out what it does, heh...
[11:12] <Zodiac> and what does it do?
[11:12] <Lasting_Dawn> It's used to show the Job Scroll in battle.
[11:12] <Zodiac> :O
[11:12] <Zodiac> weird
[11:12] <Lasting_Dawn> Indeed... but there's seperate text in there as well, which is very odd, since I know changing it in other files loads it as appropriate (for once...)
[11:12] <Lasting_Dawn> In any case... now where were we?
[11:12] <Zodiac> right click browse memory region
[11:12] <Lasting_Dawn> Done.
[11:12] <Zodiac> now the first 2 bytes are you HP, the 2 next one are you max HP afterwards lots of other stats
[11:12] <Zodiac> but this hardly matter, right now make a savestate and load it in your hex editor
[11:12] <Lasting_Dawn> Load a savestate in my hex editor...? I've... never done this before.
[11:12] <Zodiac> take 4-8 bytes on that line and search for them in the savestate
[11:12] <Zodiac> what? lol!
[11:12] <Zodiac> I've been hacking savestates for a LONG time
[11:12] <Lasting_Dawn> I've never hacked a... savestate,
[11:12] <Zodiac> well can you at least search hex with your hex editor?
[11:12] <Lasting_Dawn> Of course.
[11:12] <Zodiac> then search for those bytes
[11:12] <Zodiac> 4-8 is a good amount depending on the amount of 0x00
[11:12] <Lasting_Dawn> So I just open the savestate with any hex editor?
[11:12] <Zodiac> yeah
[11:12] <Lasting_Dawn> I feel idiotic... heh, alright, but a minute.
[11:12] <Lasting_Dawn> Found it.
[11:12] <Zodiac> what address?
[11:12] <Lasting_Dawn> 14D2FD
[11:12] <Zodiac> continue search, that's the world map stats
[11:12] <Lasting_Dawn> I only had one result, and it seems that was it...?
[11:12] <Zodiac> ;o
[11:12] <Zodiac> well huh... okay change the value to something else and reload the savestate
[11:12] <Lasting_Dawn> I see the HP went down when I reload it, but the change is only temporal.
[11:12] <Lasting_Dawn> When something happens regarding HP Ramza's HP resets.
[11:12] <Zodiac> you only found 1 result with the memory editor?
[11:12] <Lasting_Dawn> That's correct. And when I reloaded the effect changed only exists for as long as the game doesn't take into account his Actual HP.
[11:12] <Zodiac> you only changed his displayed HP then
[11:12] <Lasting_Dawn> Well, none of the numbers changed.
[11:12] <Lasting_Dawn> It was just the bar.
[11:12] <Zodiac> that's rather weird though, search for the HP again
[11:12] <Lasting_Dawn> Hmm...Same area.
[11:12] <Zodiac> mmm don't know...
[11:12] <Zodiac> when exactly are you searching for both values?
[11:12] <Lasting_Dawn> Load savestate, full HP. 467
[11:12] <Lasting_Dawn> Hit with X-Potion -14 or -127
[11:12] <Lasting_Dawn> I search for either 452 or 326
[11:12] <Zodiac> alchemist potion?
[11:12] <Lasting_Dawn> I see the byte I have marked as "Ramza's HP" change each time, they are hit.
[11:12] <Lasting_Dawn> Just a test.
[11:12] <Lasting_Dawn> An... old test at that.
[11:12] <Zodiac> were those numbers random? because 467-14 =/= 452 and 467-127 =/= 326
[11:12] <Lasting_Dawn> 452*
[11:12] <Lasting_Dawn> Ahem...
[11:12] <Lasting_Dawn> 453*
[11:12] <Lasting_Dawn> Wait, you're right...
[11:12] <Lasting_Dawn> I am horrible at math, hehe...
[11:12] <Zodiac> you can just use value decreased by...
[11:12] <Lasting_Dawn> Of course! I'll try that then.
[11:12] <Lasting_Dawn> Is this after I use it?
[11:12] <Zodiac> you can't have a decreased value if you don,t have a value to start with
[11:12] <Zodiac> don,t you agree?
[11:12] <Lasting_Dawn> True, but I've now tried that method and haven't had anything happen.
[11:12] <Lasting_Dawn> No results.
[11:12] <Zodiac> you searched exact 467 then searched decreased value by 14/127 and nothing?
[11:12] <Lasting_Dawn> Nothing that I could find, no.
[11:12] <Zodiac> if only I could easily see what you,re ding exactly...
[11:12] <Lasting_Dawn> That would probably work better.
[11:12] <Zodiac> you,re doing*
[11:12] <Zodiac> you're*
[11:12] <Lasting_Dawn> 467 First Scan
[11:12] <Lasting_Dawn> Decreased Value by 14
[11:12] <Lasting_Dawn> Next Scan, after using the X-Potion
[11:12] <Lasting_Dawn> No results.
[11:12] <Zodiac> and your HP is now 453?
[11:12] <Lasting_Dawn> Indeed, that gives one result by that point.
[11:12] <Zodiac> you,re doing new scan when you start over right?
[11:12] <Lasting_Dawn> Indeed.
[11:12] <Zodiac> well well, what the heck
[11:12] <Zodiac> could you make a screenshot of your cheatengine?
[11:12] <Zodiac> I'll check the parameter
[11:12] <Lasting_Dawn> Alright, it might have something to do with that savestate, using another one now.
[11:12] <Zodiac> parameters*
[11:12] <Lasting_Dawn> Hmm... alright, I'll send it your way, I'm nearly convinced I'm doing something wrong
[11:12] <Lasting_Dawn> What do you need to see?
[11:12] <Zodiac> whole cheat engine
[11:12] <Lasting_Dawn> At what point? Anything specific?
[11:12] <Zodiac> I'm pretty sure too because if you found something with exact value and not with decreased it doesn't make any sense
[11:12] <Zodiac> all the window
[11:12] <Lasting_Dawn> http://img385.imageshack.us/my.php?imag ... ineps3.png (http://img385.imageshack.us/my.php?image=cheatengineps3.png)
[11:12] <Lasting_Dawn> Did I really... oh my.
[11:12] <Lasting_Dawn> Heh... just one second...
[11:12] <Zodiac> ................................
[11:12] <Zodiac> ....................................................
[11:12] <Zodiac> you dummy
[11:12] <Lasting_Dawn> Very much so.
[11:12] <Lasting_Dawn> Oh? Did I do something wrong, other then the picture>?
[11:12] <Zodiac> you searched 4 bytes for a 2 bytes value? :/
[11:12] <Lasting_Dawn> Tick...
[11:12] <Lasting_Dawn> Tock...
[11:12] <Lasting_Dawn> Whoops.
[11:12] <Lasting_Dawn> Well, that might explain where I've gone wrong every step of the way,
[11:12] <Lasting_Dawn> 469 results for 429 now.
[11:12] <Zodiac> alter, next scan
[11:12] <Lasting_Dawn> Done.
[11:12] <Lasting_Dawn> That worked...
[11:12] <Lasting_Dawn> Heh...
[11:12] <Lasting_Dawn> Heh...
[11:12] <Lasting_Dawn> Hmm...
[11:12] <Zodiac> no wonder..
[11:12] <Lasting_Dawn> That only took a chunk of about 40 minutes.
[11:12] <Lasting_Dawn> So what I found earlier was... the bar'?
[11:12] <Zodiac> ya
[11:12] <Lasting_Dawn> Interesting...
[11:12] <Zodiac> the bar is either 4 bytes or the two next bytes remained 0 the whole time
[11:12] <Lasting_Dawn> That they did.
[12:12] <Zodiac> End of class
[12:12] <Lasting_Dawn> 12:00 AM...
[12:12] <Lasting_Dawn> Boy did I screw up tonight, eh well... I learned a lot!
[12:12] <Lasting_Dawn> As always, thank you Zodiac, and next time I'll try not to be such a dunce.
[12:12] <Lasting_Dawn> Copying, pasting, then calling it a night.
[12:12] <Lasting_Dawn> Have a nice night, Zodiac.
Title:
Post by: LastingDawn on December 22, 2008, 02:08:35 am
I can say with certainty, if you've been following along, this lesson will be of true worth, this is the second part of Tools and this explains and uses a lot of what the other lessons established.

Quote[11:12] <Zodiac> o hi thar
[11:12] <Zodiac> ASM Class #2
[11:12] <Zodiac> Tools
[11:12] <LastingDawn> Ah yes, I'll get them ready.
[11:12] <Zodiac> So can you use well the memory editor now?
[11:12] <LastingDawn> I think so.
[11:12] <Zodiac> a "I think so" won't do
[11:12] <LastingDawn> I recall the basics of what you told me, and how multiple scans can really find things.
[11:12] <Zodiac> hack your Gil to 999999999
[11:12] <LastingDawn> This of course has to be on the menu screen, right?
[11:12] <Zodiac> world map, or shops
[11:12] <LastingDawn> brb
[11:12] <LastingDawn> Alright, done.
[11:12] <LastingDawn> Searched for my money, spent it, searched the new value, found it.
[11:12] <Zodiac> screen?
[11:12] <LastingDawn> Sorry that took so long.
[11:12] <LastingDawn> http://i112.photobucket.com/albums/n198 ... 9_0220.png (http://i112.photobucket.com/albums/n198/LastingDawn/SCUS_94221_21122008_234839_0220.png)
[11:12] <Zodiac> good good, that was just a little warmup
[11:12] <Zodiac> next we'll learn how to use FFTPatcher for debugging
[11:12] <LastingDawn> Ah? Alright.
[11:12] <Zodiac> I want you to change the value of something in FFTPatcher then tell me what GS code it generated
[11:12] <LastingDawn> Oh... I never thought of that!
[11:12] <LastingDawn> Best to use a "new patch" function for this, I would guess?
[11:12] <Zodiac> GS codes are basically memory addresses with values and a writing type or specification when to write
[11:12] <Zodiac> ya
[11:12] <LastingDawn> Alright, I have the code.
[11:12] <Zodiac> copy/paste
[11:12] <LastingDawn> 30063ABE 0001
[11:12] <Zodiac> the memory address is 0x80063ABE
[11:12] <Zodiac> it doesn't really matter if the first 8 is there or not
[11:12] <LastingDawn> So it''s 63ABE, basically?
[11:12] <Zodiac> opcodes interpret  0x80063ABE and  0x00063ABE the same way
[11:12] <LastingDawn> What is the purpose of the "8" then?
[11:12] <Zodiac> well I find it great when talking to know that we're talking about a memory address and not a value
[11:12] <Zodiac> even if the second is possible, it's much lesss probable
[11:12] <Zodiac> the reason the 8 is used in the code though, that I can't tell
[11:12] <LastingDawn> Hmm, eh well, so we'll use 8 as a memory address, instead of a value in our discussions then?
[11:12] <Zodiac> yeah and you might as well code with 8 too
[11:12] <Zodiac> well for FFTPatcher it's as simple as that, it's extremely useful
[12:12] <Zodiac> because you will use that address to break when the value is read
[12:12] <Zodiac> anyway we'll move to renegade64
[12:12] <Zodiac> coding some real stuff
[12:12] <LastingDawn> Yes, you mentioned Renegade the other day, but I thought it couldn't be used on a PSX?
[12:12] <Zodiac> Asm/Assemble Code
[12:12] <Zodiac> use the version I gave you
[12:12] <Zodiac> we'll only use it for coding
[12:12] <LastingDawn> I'm trying to think of where I put it... but I can't seem to find it.
[12:12] <LastingDawn> Oh wait, that was the very confusing part, I was using my "own" and didn't pick yours up before we moved on.
[12:12] <LastingDawn> There we are, found it.
[12:12] <LastingDawn> Zodiac? Still around?
[12:12] <Zodiac> ya
[12:12] <LastingDawn> Well, I have it open, but to put it plainly, this tool has always confused me.
[12:12] <Zodiac> Asm/Assemble Code
[12:12] <LastingDawn> Done.
[12:12] <Zodiac> ok you need to select Output Type: 32-Bit Values (No Ad???)
[12:12] <LastingDawn> Alright.
[12:12] <Zodiac> ok well try typing in a few lines of codes then click assemble
[12:12] <Zodiac> copy/paste the output here
[12:12] <LastingDawn> By typing, you mean copy and paste, from elsewhere?
[12:12] <Zodiac> copy/paste the generated hex after clicking "Assemble"
[12:12] <Zodiac> of course you ened code to start with, anything will do
[12:12] <LastingDawn> Such as from Cheta Engine and the like?
[12:12] <LastingDawn> Cheat*
[12:12] <Zodiac> ...no we're just working with renegade right now
[12:12] <LastingDawn> Unknown Opcode 37
[12:12] <Zodiac> what did you type?
[12:12] <LastingDawn> The bytes for money and a few lines after that.
[12:12] <Zodiac> ...what?
[12:12] <Zodiac> you have to type code
[12:12] <Zodiac> like andi r2, r3, r2
[12:12] <Zodiac> or lb r2, 0x0000(r1)
[12:12] <LastingDawn> Oh! That code... right.
[12:12] <Zodiac> woops andu for the first one
[12:12] <LastingDawn> Alright, I used your example (mainly because I couldn't find any other place to draw from...)
[12:12] <LastingDawn> Warning: R2,R3,R2 - immediate value can only be 0-FFFF
[12:12] <Zodiac> I said andu
[12:12] <LastingDawn> Andu said it was malformed.
[12:12] <Zodiac> that's whay you get for using MY code :O
[12:12] <Zodiac> huh...
[12:12] <LastingDawn> Unknown Opcode: ANDU
[12:12] <Zodiac> well whatever just just and
[12:12] <Zodiac> ah lol, it's because I meant addu
[12:12] <LastingDawn> That makes sense.
[12:12] <LastingDawn> 00621021
[12:12] <Zodiac> 00 62 10 21 FLIP TO >>> 21 10 62 00
[12:12] <Zodiac> Renegade's main disadvantage
[12:12] <LastingDawn> Oh, the bytes are flipped...?
[12:12] <Zodiac> yeah well it shows the real order but opcodes (and everything else) is flipped when stored in the ram
[12:12] <Zodiac> so when searching for opcodes and writing new ones you need to flip the bytes
[12:12] <LastingDawn> That seems rather... tiresome after a while.
[12:12] <LastingDawn> Or does it eventually become second nature?
[12:12] <Zodiac> well I made myself an excel workbook to automatically flip the bytes but unless you plan to do big hacks it shouldn't be too tiresome
[12:12] <LastingDawn> Oh, alright then.
[12:12] <Zodiac> so... I suppose we'll move to the last tool
[12:12] <Zodiac> the DEBUGGER
[12:12] <LastingDawn> First, can you give me a bit of a test with the Renegade tool?
[12:12] <LastingDawn> So I can completely understand it, with hands on training?
[12:12] <Zodiac> not really, all you can do is have a good syntax
[12:12] <Zodiac> after the debugger we're gonna hack fo' real
[12:12] <Zodiac> last class
[12:12] <LastingDawn> Alright, we'll get to the debugger then.
[12:12] <Zodiac> pSX 1.13, Debug/Monitor/r3000
[12:12] <Zodiac> this is a my debugger setup, quite effective: http://zodiac.ffhacktics.com/debugger.png (http://zodiac.ffhacktics.com/debugger.png)
[12:12] <LastingDawn> Currently open and 100% confused by it.
[12:12] <Zodiac> lol that's because I haven't started explaining
[12:12] <LastingDawn> Oh, I had meant, I've seen it many times before, but up until now has been a brick wall to the face.
[12:12] <Zodiac> there are 7 windows but I doubt you'll use more than 4 just like I do
[12:12] <Zodiac> the Memory one is pretty simple, it's the memory, to move just use ctrl+g and enter the address
[12:12] <LastingDawn> So that's the secret!
[12:12] <LastingDawn> Well I feel like an idiot.
[12:12] <Zodiac> the register window has the value of every register used by opcodes, you can even modify them if you click click them but only really doable when the game is on break
[12:12] <Zodiac> right click*
[12:12] <Zodiac> Dissassembly well, it's asm...
[12:12] <Zodiac> and the last one, the core of debugging, the Breakpoints
[12:12] <Zodiac> you have to right click to set a new breakpoint (and always use memory breakpoints)
[12:12] <Zodiac> when the game reads/write at the given address, the game will break
[12:12] <Zodiac> basically it will freeze right after it executes the opcode
[12:12] <Zodiac> then you can play around with registers and with the routine to see how it works and what to change
[12:12] <LastingDawn> And the key to doing such is knowing what to break on?
[12:12] <Zodiac> yeah
[12:12] <LastingDawn> Hmm, well that works.
[12:12] <Zodiac> they're just memory address, so most of the time, FFTPatcher will save you tons of work
[12:12] <LastingDawn> Will it? Ah, I suppose that's true.
[12:12] <Zodiac> so are you currently in the world map or a battle?
[12:12] <Zodiac> we're gonna test this out
[12:12] <LastingDawn> World map.
[12:12] <Zodiac> ok well go to a shop that sells a certain item and break on its price
[12:12] <LastingDawn> In hex, of course?
[12:12] <Zodiac> and you,re talking about waht now?
[12:12] <LastingDawn> Oh right, FFT Patcher, lower price, find where that was located, and break on it?
[01:12] <Zodiac> if you're gonna use FFTPatcher you can just change the price and convert the GS code to a memory address
[01:12] <Zodiac> btw don't forgot to put 0x before the address else it will consider it as decimal :/
[01:12] <LastingDawn> Indeed, that was my plan.
[01:12] <LastingDawn> Change the breakpoint to Memory?
[01:12] <Zodiac> yes, and read
[01:12] <LastingDawn> jr r 31
[01:12] <Zodiac> write would be useless as the game never writes a value there, it only reads a static price
[01:12] <LastingDawn> jump and return register 31?
[01:12] <Zodiac> what?
[01:12] <LastingDawn> 03E00008
[01:12] <LastingDawn> That's what the Disassembly jumped to.
[01:12] <LastingDawn> Does that look and sound right?
[01:12] <LastingDawn> Breaking on the price of the Koutetsu Knife.
[01:12] <Zodiac> not at all
[01:12] <LastingDawn> What did I do wrong then?
[01:12] <LastingDawn> Rhetorical question...
[01:12] <LastingDawn> Only I would know.
[01:12] <LastingDawn> Wait, isn't the size 02?
[01:12] <LastingDawn> Not 01?
[01:12] <Zodiac> doesn't really matter
[01:12] <Zodiac> don't bother with size unless you want to debug a large array of address
[01:12] <Zodiac> so what's the current value of your breakpoint?
[01:12] <LastingDawn> x00063478
[01:12] <Zodiac> what did you do to make it break?
[01:12] <LastingDawn> Put it in, changed it to Write, and pressed break.
[01:12] <LastingDawn> Wait... Read, not Write...
[01:12] <Zodiac> I'm talking after that
[01:12] <Zodiac> it broke instantly?
[01:12] <LastingDawn> Oh no, I thought you had to hit Break?
[01:12] <Zodiac> you can't do that lol
[01:12] <LastingDawn> Oh, hah... alright.
[01:12] <Zodiac> I even wonder why there is such a function, manually breaking is just random
[01:12] <Zodiac> it has to break by itself
[01:12] <Zodiac> resume with F9 (if not already done)
[01:12] <Zodiac> and enter the shop
[01:12] <LastingDawn> Alright.
[01:12] <LastingDawn> Done, so what am I doing wrong here? The game doesn't seem to breakpoint on it's own.
[01:12] <Zodiac> it doesn't with me neither
[01:12] <Zodiac> you got a wrong address
[01:12] <Zodiac> bad LD >:(
[01:12] <LastingDawn> Hmm, but I got the address straight from the patcher...
[01:12] <LastingDawn> 30063478
[01:12] <LastingDawn> The 3 gets changed to 0, right?
[01:12] <Zodiac> 30063094
[01:12] <Zodiac> that's kotetsu's price
[01:12] <Zodiac> don,t know how you got 478
[01:12] <LastingDawn> 478 was what I changed when I failed to make it work with Koutetsu, it's Shuriken...
[01:12] <LastingDawn> Probably... should have said something.
[01:12] <Zodiac> then you can just head to the item list
[01:12] <Zodiac> and it will break
[01:12] <Zodiac> chemist/ninja/stuff items
[01:12] <LastingDawn> It's Read, right?
[01:12] <Zodiac> yeah, although having write wouldn't change anything in our case
[01:12] <Zodiac> in cases the value is often read/written it's nice to only have the one you want activated
[01:12] <LastingDawn> Hmm, it jumped immediately to that jr address.
[01:12] <LastingDawn> jr r 31
[01:12] <Zodiac> what's your current address?
[01:12] <LastingDawn> 00123724
[01:12] <Zodiac> I can't reach that location, what's your breakpoint currently?
[01:12] <LastingDawn> 0x00063478
[01:12] <Zodiac> ah ok, reached
[01:12] <Zodiac> my debugger is acting funny again.. damnit
[01:12] <LastingDawn> Well I think we can agree the PSXFin isn't an ideal... debugger.
[01:12] <Zodiac> not changing any values and I can't get shuriken to display, well it did once but at 17436gil
[01:12] <Zodiac> and I never changed any values lol
[01:12] <LastingDawn> Haha! Well that's... that's a problem.
[01:12] <Zodiac> Well I think "Excecute" nulls all read/write concerning that value
[01:12] <LastingDawn> Bah! Emulator just crashed... very odd.
[01:12] <Zodiac> that address*
[01:12] <LastingDawn> Execute makes it so nothing can be done to that value?
[01:12] <Zodiac> seems so
[01:12] <Zodiac> I used to just shift to execute to remove the breakpoints while keeping the address but it looks like this was troublesome in some cases
[01:12] <LastingDawn> Sorry for the wait, back up.
[01:12] <Zodiac> so that jr r31 you see there, it is the next opcode to be executed
[01:12] <Zodiac> the previous one was the one that actually loaded the price
[01:12] <LastingDawn> I see what you mean now about the Execute... how odd.
[01:12] <Zodiac> so I'll just show you something simple before I go to sleep
[01:12] <LastingDawn> Alright, certainly.
[01:12] <Zodiac> remember what a jump/branch does before going to a next location?
[01:12] <LastingDawn> It reads the opcode below it.
[01:12] <Zodiac> yep
[01:12] <LastingDawn> Which is why in most cases it is a nop?
[01:12] <Zodiac> and oh what do I see here? space for free opcode
[01:12] <LastingDawn> So where it Jumps, we can place what we like in there?
[01:12] <Zodiac> we probably can't raise the price (I doubt the game would support more than 5 digits
[01:12] <LastingDawn> If it is already nop?
[01:12] <Zodiac> yeah, we can change it no worries
[01:12] <Zodiac> but we only have ONE opcode for this simple stuff so we'll go for something like
[01:12] <Zodiac> and that will be a srl
[01:12] <LastingDawn> shift right logical?
[01:12] <Zodiac> ya
[01:12] <Zodiac> so look at what you'll do
[01:12] <Zodiac> create a srl opcode with destination r2 (and of coruse source as well) with the immediate you want
[01:12] <Zodiac> assemble it and flip the bytes
[01:12] <Zodiac> then go in the memory window, press ctrl+g and go to location 0x80123728
[01:12] <Zodiac> type in the 4 bytes
[01:12] <LastingDawn> 000210C2
[01:12] <LastingDawn> Flipped are...
[01:12] <LastingDawn> C2100200?
[01:12] <Zodiac> yep
[01:12] <LastingDawn> Ah, that wasn't too difficult.
[01:12] <Zodiac> coding is the easy part of hacking lol
[01:12] <Zodiac> debugging, on the other side, is a mess :(
[01:12] <LastingDawn> Haha!
[01:12] <Zodiac> Well that's all for today's class
[01:12] <LastingDawn> Eh?
[01:12] <LastingDawn> It changed all prices...
[01:12] <LastingDawn> That's what you meant, hehe.
[01:12] <Zodiac> Next lesson will be about HACKING
[01:12] <LastingDawn> Well this lesson has been extremely informative! And I'm glad to see I was able to use some slight form of my new knowledge
[01:12] <Zodiac> yes because even if the gmae reads shuriken's price there, it reads ALL the item,s price there
[01:12] <Zodiac> because it's a routine to "calculate" and display the cost
[01:12] <Zodiac> I'll try to typo less next time
[01:12] <LastingDawn> And we make that happen by using the Jump and Return instruction?
[01:12] <LastingDawn> So I also learned today how to tell what some numbers are, but is there a way to reverse it? To use numbers to tell what an instruction is?
[01:12] <LastingDawn> bytes*
[01:12] <Zodiac> uhh you can use jr but JAL isn't safe unless you store the address somewhere beforehand
[01:12] <Zodiac> .. check in the debugger? it's what it does :P
[01:12] <LastingDawn> Understood, oh right... well I can read things a bit easier now.
Title:
Post by: Gamesoul Master on December 27, 2008, 04:04:53 am
Quote from: "Vanya"
Quote from: "nates1984"Begin random question in ASM topic:

Some registries are assigned to sprites, that's why there's a limitation on how many different ones can be included in each battle.

ok. i'M DRUNK OFF OF WODKA, BUT i KNOE THIS MUCH1 YOUR FISRT STATEMENT IS ERRONEOUS.

sPRITES ARE HELD IN ram NOT REGISTRIES. tHE LIMIT OF THE NUMBER OF SPRITES HAS TO DO WITH THE pLAYSTATIONS'S LIMITED VIDEO ram. PPL CRITISIZED THE SYSTEM FOR IT'S LIMITED VIDEO RAM FOR A LONG TIME. iT HAD LESS VIDEO RAM THAN THE snes, Iirc.

sO. TO GO BEYOND IT'S LIMITED VIDEO ram YOU'D HAVE TO PROGRAM A SPECIAL emulator to use more video RAM.

^_^

Uhh... two things:

1) PS1 has 1 MB of video RAM, SNES has 64 KB of video RAM (with each having system RAM double of its video RAM).

2) The reason for the amount of sprites allowed can't be because of video RAM, and it would extremely poor programming practice if it was. Reasons for this being... they already coded the game so that in any given battle, they wouldn't be exceeding the sprite limit, so there would be no need to impose a limit on the sprites allowed, because by their own programming, it'd never be exceeded anyway. And besides that, let's say they somehow missed a battle or two and accidentally added one or two more sprites than they felt the video RAM could handle. They wouldn't impose a sprite limit and cause a mistake like that to look worse than it is.

If this problem only occurred on the console, I could see the justification. But it also happens on emulators that have no such RAM limitations. It just seems like something in the game itself isn't allocating enough memory for the game to have more sprites than the "limit", so after that amount, it just pulls from what would logically be the next sprite in memory (except there's no sprite there because that memory location wasn't allocated to sprites).

My real question to that is... why doesn't the game notice the problem sooner? When all the sprites are first loaded, what happens to the sprites that exceed the limit? Shouldn't they still be written *somewhere*? And if they are, wouldn't they be read in the same sequence as they're written (since it's easier to do read/write code for the same data, in the same order), therefore causing the extra sprites to load correctly and something *else* to not be written/read correctly?


Anyway... sorry to derail a bit, but I just wanted to get a couple things off my chest while reading through this thread.

I do like what's been posted thus far. As a programmer, I know some of it already, but some things here haven't been covered/used in the C++/Java programming I've learned (I'm not some advanced programmer, just a single year of each one thus far). Glad to see the informal lessons being posted though... serves to be a great opportunity for some to learn, and others to realize that it isn't as easy as they may have thought.
Title:
Post by: Vanya on December 27, 2008, 05:26:35 pm
Now that I'm not drunk, but rather just high on cold medication...

There's one basic flaw in your reasoning. The PSX emulators do emulate the same RAM restriction as the real hardware. If this were not the case you'd see Hacks & home brew projects that go beyond the limits of the original hardware. It just isn't possible without rewriting the emulator and the game.

Why doesn't the game notice the problem sooner? It isn't programmed to do so.

No matter how many sprites you place in a battle the system will never be able to display more than the allowed limit because that is how it was programmed. It is limited by the available VRAM. Remember that the data in the VRAM includes all the graphics being processes, not just the sprites. It's handling the effect graphics, the map graphics, and the equipment graphics, too. When you go over the limit the game probably only allocates to the space allowed for sprites, but then reads beyond that space when displaying them. It's probably reading non-sprite data as if it were; which causes the sprite look like a garbled mess. In another game the effect of going beyond the sprite limit could be completely different; causing a crash instead.

The simplest way to read/write data depends greatly on how it's set up. There's no single way that is best for all platforms. Also, the PSX's ASM language is very different from C++ or Java; having many limitations that you won't find in higher languages.

These lessons are extremely useful to many of us because this type stuff isn't easily found. Generic ASM programming info is very plentiful. However, when you get down to the specifics of ASM ROM hacking the ROM hackers tend to be very tight lipped and unwilling to teach others in this fashion. This topic is very much appreciated! ^_^
Title:
Post by: Gamesoul Master on December 27, 2008, 05:45:09 pm
Point taken, and thank you for the thought out response. At least that answers a question plenty of people have asked (can the sprite limit be expanded) with a resounding "NO"... lol. Because no matter what you try to tell the game to do, the emulator will always restrict it anyway.

One thing I want to say though... why would people create homebrew for PS1 that exceeded the hardware's capabilities if that obviously meant it couldn't be run on the PS1? Writing homebrew to run solely on an emulator (homebrew that would actually bother to push the limitations instead of simply being useful to test something in an emulator) would be completely pointless. Basically, besides homebrew that is *meant* to be run only on emulators and would (usually) have no need to exceed hardware limitations, nobody would write homebrew that can't be run on the console in the first place, and would therefore make sure it fits within hardware limitations whether an emulator can handle it or not. (This whole paragraph is half observation, half question... If there's something I'm overlooking, feel free to point it out. I just don't normally see homebrew made purely for emulation purposes besides testing/debugging.)

But yeah, so I guess the problem here is based on the game's programming (because the programmers made a horrible rookie mistake and didn't add a check for data exceeding the maximum limit). I suppose I shouldn't be surprised, but it's a bit disappointing to come to grips with that reality... :/

You didn't need to explain that whole memory allocation bit, by the way... lol. I already understood all that, but I didn't realize that emulators were programmed to actually emulate the amounts of RAM the actual PS1 had available to it. I simply started off with a faulty assumption. Thank you though... it's nice to see people give a complete answer to fully get the point across (that's not sarcasm, I do appreciate it).

I am surprised though, that the programmers allowed their code to read data out of bounds when they went through the trouble of not letting it write out of bounds. Another rookie oversight on their part. Then again, *most* games are chock full of mistakes and oversights like that... XD

[/derail]
Title:
Post by: Vanya on December 27, 2008, 06:49:33 pm
Indeed! I've seen a lot of WTF code while hacking Mega Man 5. ^_^
Title:
Post by: The Damned on January 24, 2009, 09:40:26 pm
Okay. So I finally got through all of this yesterday after work.

Surprisingly, I understood most of it better than what Lasting Dawn seemed to from the initial lessons, so it was a lot easier than I thought it was going to be.

That said, I still don't understand a few things in here, probably because this is the first thing I've ever tried to hack and also possibly because I have no idea how to use CDProg at the moment--I've been hesitant to use CDProg because Vista kept saying it was a virus, but I at least got that cleared up for me by...goldblade?

Anyway, the things I'm not understanding seem to be of course be key things--I got everything that was pretty much math-related--that Lasting Dawn already knew due to this apparent experience with Zelda (which I know nothing about). There are about five or six groups of these terms:


I'm pretty sure I understood everything else, but...yeah.

A little help would be much appreciated since I want to start being actual useful around here (and get some ASM hacking experience for something else that I now plan on doing).
Title:
Post by: nates1984 on January 24, 2009, 10:43:31 pm
Signed and unsigned. = signed can be a positive or negative, unsigned can only be positive (so a -2 becomes a 2,  or rather then having half of the possible numbers negative and half positive, there are only positive numbers), i might be getting these two switched, and i havent really figured out how the PSX uses these, the standard definition for other languages i have experience with may not apply

byte = 2 numbers (8 bits, 1 byte), such as 08, 19, ect
word = 8 numbers, or 4 bytes, a register has space for 8 digits, you can only fit a single word in the registers, its hard to give a consistent definition for this, but when you see the "lw" or "load word" command, it means its going to load 8 digits, or 4 bytes
half-word = 4 digits, or 2 bytes, or half of the available space in a register

branches are conditional jumps, just like the guy said in the chat logs, uhhh, i dont think i could offer an explanation any more clear then what he said

immediate = http://en.wikipedia.org/wiki/Constant_(computer_science (http://en.wikipedia.org/wiki/Constant_(computer_science))#Constants
"In many machine assembly languages or instruction set specifications, constant values are termed immediate values because they are available immediately (often embedded as part of the instruction stream) without needing to load a value from the data cache[1]."
immediates can be seen as values being directly being inputed into the registry, so that the value itself stays in the registry, rather then the register going to the values memory address and loading that value instead, at least thats the gist of it within other contexts ive looked at, but it may operate differently in the PSX

registers = r2, r9, r17, ect, if youve looked at the debugger youll see a list of these values, values are loaded into the registers so they can be used through opcodes (instructions)

breakpoint = basically, you tell the game to instantly freeze once this address is read, or this instruction is executed, ect. that way you see see exactly where in the hex data a particular instruction is, what the game is doing at that very moment, this is pretty much the most important part of ASM editing, to get started, in your debugger, add a break point (memory, read, youll see these options) and put this address: 0x80192D94, then do something, like use an ability, cast a spell, or use a physical attack
Title: Re: ASM Lessons
Post by: Choto on February 02, 2012, 09:16:00 am
I'm gonna necrobump this thread and ask that it be organized somewhere along with the other ASM hacks maybe in a place called "ASM learning corner". These kinds of threads along with the tutorials are invaluable to beginner ASMers such as myself, even if it may not seem like it to the more skilled and experienced. Even when I am writing hacks I find myself with most of these threads open for easy reference. I think that organizing all of these helpful threads may lead to more people learning ASM, and more help/contributions to dissecting FFT. Just my opinion :)
Title: Re: ASM Lessons
Post by: Pickle Girl Fanboy on February 02, 2012, 09:41:19 pm
Ditto.
Title: Re: ASM Lessons
Post by: Glain on February 02, 2012, 10:30:56 pm
If we had a section that was about ASM learning, I'd potentially have quite a bit to contribute to it...
Title: Re: ASM Lessons
Post by: RavenOfRazgriz on February 02, 2012, 10:33:23 pm
Quote from: Glain on February 02, 2012, 10:30:56 pm
If we had a section that was about ASM learning, I'd potentially have quite a bit to contribute to it...


http://ffhacktics.com/smf/index.php?board=43.0

Not good enough for you?  It should be Learning/Tutorials but no one on this forum ever listens to me.  :|
Title: Re: ASM Lessons
Post by: Vanya on February 03, 2012, 03:00:51 am
Quote from: RavenOfRazgriz on February 02, 2012, 10:33:23 pm
http://ffhacktics.com/smf/index.php?board=43.0

It should be Learning/Tutorials but no one on this forum ever listens to me.  :|


I agree with that idea. It would attract the attention of noobs better if it were called something like that.
Title: Re: ASM Lessons
Post by: Eternal on February 03, 2012, 03:02:56 am
Don't you guys think Tutorials is clear enough? >_>
Title: Re: ASM Lessons
Post by: Celdia on February 03, 2012, 03:40:43 am
Quote from: Eternal248 on February 03, 2012, 03:02:56 am
Don't you guys think Tutorials is clear enough? >_>


Quote from: Did you even read what they posted?
Quote from: Glain on February 02, 2012, 10:30:56 pm
If we had a section that was about ASM learning, I'd potentially have quite a bit to contribute to it...

Quote from: RavenOfRazgriz on February 02, 2012, 10:33:23 pm
It should be Learning/Tutorials

Quote from: Vanya on February 03, 2012, 03:00:51 am
I agree with that idea. It would attract the attention of noobs better if it were called something like that.


Apparently not.
Title: Re: ASM Lessons
Post by: RavenOfRazgriz on February 03, 2012, 03:44:27 am
Quote from: Eternal248 on February 03, 2012, 03:02:56 am
Don't you guys think Tutorials is clear enough? >_>


Lessons/Tutorials also means you could post active lessons, get groups together, etc. explicitly.

Website 101: Be explicit.  You don't want people to think "Oh, Tutorials, I guess this fits there."  You want people to see "Lessons/Tutorials, oh, I can give/find/ask for/set up Lessons on things there in addition to outright Tutorials!  That's fucking sweet!"

So yes, change it to Lessons/Tutorials, make it explicit that you can offer to give, ask for, etc. lessons on things in addition to just writing Tutorials there.  Be explicit damnit.
Title: Re: ASM Lessons
Post by: Choto on February 03, 2012, 09:36:37 am
The only reason I really brought this up was because threads like this and the other one I posted in were lost in the later pages of hacking, while they are actually really helpful to a certain group of people (people learning ASM). Its not a huge deal, but it would help to have all of that information in one place.

The thing is, people explain ASM differently. Xif's, FDC's, and pokeytax's ASM tutorials all cover different topics. Because ASM is quite intimidating at first, even hearing the same things said in a different way are instrumental in learning.
Title: Re: ASM Lessons
Post by: Mysfit on February 09, 2012, 12:57:50 pm
I'd like to suggest, as a total ASM nubcake, that,if at all possible, the opcode documentation (http://zodiac.ffhacktics.com/PSX-INST.txt) mentioned in Lesson #0 be featured somewhere more prominently (perhaps in the Tutorial section of the main site or as a sticky in the Tutorial forum), because until after having discovered this just now, I had been entirely in the dark as to where all of these mysterious operators mentioned in the routine hacks were coming from and what they meant, rendering a lot of the ASM tutorial information and hack suggestions I had been reading up to this point to hermetically sealed secrets of black magic and sorcery. I'm certain making that document easier to find for others would clear up a lot of people's initial confusions and apprehensions. If it already is featured somewhere, then I concede to my blindness and accordingly rescind my suggestion.
Title: Re: ASM Lessons
Post by: Glain on February 09, 2012, 02:24:46 pm
For a list of the more 'standard', most-often-seen commands, take a look at this (http://vhouten.home.xs4all.nl/mipsel/r3000-isa.html) list of commands. The PSX doesn't have a floating point unit so the floating point sections can be ignored. It also only has 2 MB of RAM.

I'm honestly not sure about that document you linked - it does seem to be a list of MIPS commands but that might be for a later version of the architecture. Some of those commands (the doubleword stuff in particular) really have me wondering.

I'm intending to go into the guidelines of how registers are used in my ASM learning series thread in the tutorials subforum (i.e. which registers should be used for what, routine calls, which registers retain values after routine calls, and why); there are very few hard-and-fast restrictions, but there are a lot of rules/guidelines the code uses that make things a lot easier.

EDIT: On second thought, that list is missing a few instructions, notably the load/store for anything other than a word. Maybe just look at the integer instruction table in the Wikipedia entry on MIPS (http://en.wikipedia.org/wiki/MIPS_architecture). Other than the doubleword stuff and maybe some of the coprocessor stuff, I don't see anything that wouldn't apply to the PSX. The "compiler register usage" section is also basically what I was talking about going over.
Title: Re: ASM Lessons
Post by: Pride on February 09, 2012, 02:55:08 pm
I generally use this list here (http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html)

Not sure if there's much difference between the two you posted but I thought I'd share.
Title: Re: ASM Lessons
Post by: The Damned on March 24, 2012, 03:44:46 am
(I just realized I didn't get around to updating my thread by last night like I said I would. Oh well, there's always Sunday.)

On the behest of formerdeathcorps, I have been asked to post this excerpt from his attempts to go over the first half or so of the basics of ASM to Aero as a refresher and to the brick wall that is me as a basically new start-up. Please try to not facepalm to hard at my ineptitude; I can't be held responsible for your injuries:

Session Start: Fri Mar 23 21:31:25 2012
Session Ident: #ffhs
[21:31] * Now talking in #ffhs
[21:31] <fdc> all right
[21:31] <fdc> so Aero has some faint memory of ASM
[21:31] <fdc> and the Damned has read through Xif's tutorial but doesn't understand much of it
[21:31] <fdc> all right...
[21:31] <fdc> so I think we should do a review?
[21:32] <TheDamned[Staves]> If Aero doesn't mind. Otherwise we can do what Aero wants.
[21:32] <Aero[Supernatural]> yes, just so we know how far along we are
[21:32] <Aero[Supernatural]> I'll forgive the patronizing
[21:32] <Aero[Supernatural]> *forgive any
[21:32] <fdc> all right...the basic unit is the byte.
[21:32] <fdc> in MIPS
[21:32] <fdc> and most other 32-bit assembly languages
[21:32] <Aero[Supernatural]> motorola IPS?
[21:33] <fdc> Should be similar, but not exact
[21:33] <Aero[Supernatural]> no, is that what you meant by MIPS?
[21:33] <fdc> http://en.wikipedia.org/wiki/MIPS_architecture
[21:33] <fdc> No, it's not
[21:33] <Aero[Supernatural]> oh
[21:33] <Aero[Supernatural]> ic
[21:33] <fdc> all right.
[21:33] <fdc> we know that to express numbers as bytes, we use hex
[21:33] <fdc> or base 16
[21:34] <fdc> familiar ground so far?
[21:34] <TheDamned[Staves]> Yes.
[21:34] <Aero[Supernatural]> definitely
[21:34] <fdc> ok good
[21:34] <fdc> I presume then that most of you know what signed bytes are?
[21:35] <Aero[Supernatural]> yes
[21:35] <fdc> and I don't need to explain the difference between add with overflow and add without?
[21:35] <TheDamned[Staves]> I vaguely remembering that being part of my confusion, actually.
[21:35] <fdc> or shift right logical vs. shift right arithmetic
[21:35] <Aero[Supernatural]> remind me
[21:35] <fdc> ok
[21:35] <TheDamned[Staves]> I mean, I sort of understand, but meh.
[21:35] <Aero[Supernatural]> logical shift, no
[21:35] <Aero[Supernatural]> arithmetic shift, remind me
[21:35] <fdc> one byte has 8 bits, right?
[21:35] <fdc> which we can see as 8 1/0 binary switches
[21:35] <Aero[Supernatural]> know that
[21:35] <fdc> 0/1 0/1 0/1 0/1 0/1 0/1 0/1 0/1
[21:36] <fdc> A number is signed if the uppermost bit determines the sign
[21:36] <fdc> 0 being positive
[21:36] <fdc> and 1 being negative
[21:36] <TheDamned[Staves]> Uppermost being the leftmost?
[21:36] <fdc> thus, in hex, the signed positive bytes are from 01-7F
[21:36] <fdc> yes, Damned
[21:36] <TheDamned[Staves]> Okay.
[21:36] <fdc> and the signed negative bytes are from 80-FF
[21:37] <fdc> however, the system is called two's complement
[21:37] <fdc> this means
[21:37] <fdc> that FF = -1
[21:37] <fdc> while 80 = -128
[21:37] <fdc> while 7F = 127
[21:38] <fdc> with me so far?
[21:38] <TheDamned[Staves]> Yes, 112 + 15 = 127.
[21:38] <fdc> where does 112 come from?
[21:38] <TheDamned[Staves]> I can't say I really understand why complement is that way, but I understand what you're getting at.
[21:38] <TheDamned[Staves]> 7*16
[21:39] <fdc> no, I mean
[21:39] <fdc> do you all see why FF = 01
[21:39] <fdc> -1
[21:39] <fdc> while 80 = -128?
[21:39] <TheDamned[Staves]> No then.
[21:39] <TheDamned[Staves]> Aero?
[21:39] <Aero[Supernatural]> Sorry, kinda multitasking here
[21:40] <fdc> ok...here's how I'd look at it
[21:40] <fdc> two's complement means
[21:40] <fdc> that if a number's upper hex digit is 8 or above, it is negative, right?
[21:41] <Aero[Supernatural]> I understood that back when I first learned it, but now that i'm looking at it again and my attention is getting severed, it doesn't make a lot of sense
[21:41] <fdc> just add the negative number it's supposed to be
[21:41] <Aero[Supernatural]> hold on
[21:41] <fdc> and it will always add up to the next power of 16
[21:41] <fdc> thus, FF + 1 = 256 base 10
[21:41] <fdc> as does 80 + 128 = 256 base 10
[21:41] <fdc> so FF = -1
[21:41] <fdc> and 80 = -128
[21:42] <TheDamned[Staves]> Hmmm...I need to try process this a moment since now "modulo" stuff is popping up when I see this and that's not helping.
[21:42] <fdc> you can also try seeing it as bits
[21:42] <fdc> FF = 1111 1111
[21:42] <fdc> if you had one more 1, you'd have the next power of 16
[21:43] <fdc> 1 0000 0000
[21:43] <fdc> Thus, FF is -1 when signed
[21:43] <fdc> the algorithm is exactly the same thing.
[21:43] <fdc> flipping bits
[21:43] <fdc> and then adding 1
[21:43] <TheDamned[Staves]> Okay.
[21:43] <fdc> If you flip all the bits on FF
[21:43] <fdc> you get
[21:43] <fdc> 0000 0000
[21:43] <fdc> if you add 1, you get 1
[21:43] <fdc> so FF = -1
[21:44] <TheDamned[Staves]> Okay, so that makes sense with regards to FF I guess.
[21:44] <fdc> everyone still with me here?
[21:44] <TheDamned[Staves]> Why 80, though?
[21:44] <fdc> ok
[21:44] <Aero[Supernatural]> I think I understand
[21:44] <fdc> 80 is 1000 0000 in binary, right?
[21:44] <fdc> you need to add 1000 0000 to get the next power of 16
[21:44] <Aero[Supernatural]> so it's whatever the opposite of the current number is, +1?
[21:45] <fdc> yeah
[21:45] <Aero[Supernatural]> in binary/hex?
[21:45] <fdc> yeah
[21:45] <Aero[Supernatural]> just checking
[21:45] <Aero[Supernatural]> i remember now
[21:45] <Aero[Supernatural]> was never really useful to me in college, but I guess it'll be very important here
[21:45] <Aero[Supernatural]> I'll try to memorize it
[21:45] <fdc> back to the Damned, because you have to add 1000 0000 to get the next power of 16
[21:45] <fdc> 80 = -128

[21:46] <fdc> do you see now?
[21:46] <TheDamned[Staves]> I'm not seeing how 80 is 1000 0000. Wouldn't that just be regular 128? I thought 80 in binary was 0101 0000.
[21:46] <Aero[Supernatural]> @the damned: 64 in binary is 01000000
[21:46] <fdc> I mean 0x80
[21:46] <fdc> in hex
[21:46] <Aero[Supernatural]> the twos complement would be 10111111
[21:46] <fdc> sorry, I should be more clear
[21:46] <TheDamned[Staves]> Oh, 80 in hex. Right.
[21:47] <TheDamned[Staves]> That makes sense then. Sorry. It slipped my mind.
[21:47] <Aero[Supernatural]> that would be 191 in decimal
[21:47] <Aero[Supernatural]> +1 = -192?
[21:47] <Aero[Supernatural]> or did I just do it wrong?
[21:47] <fdc> No
[21:48] <fdc> remember that the first bit determines the sign
[21:48] <fdc> so 1100 0000 signed
[21:48] <fdc> is 0011 1111 + 1
[21:48] <fdc> or 0100 0000
[21:48] <fdc> so 0xC0 = -64
[21:48] <Aero[Supernatural]> no no
[21:48] <fdc> that's right the first time you said it
[21:49] <fdc> where are you getting +1 from ?
[21:49] <Aero[Supernatural]> I was trying to convert 64 to signed
[21:49] <fdc> oh
[21:49] <fdc> ...
[21:49] <fdc> don't
[21:49] <fdc> the thing is
[21:49] <fdc> in signed
[21:49] <fdc> positive numbers stay the same
[21:49] <fdc> but negative numbers are simply really large positives if you ignored the sign
[21:50] <Aero[Supernatural]> derp
[21:50] <Aero[Supernatural]> I wasn't using a number large enough
[21:50] <Aero[Supernatural]> i think
[21:50] <Aero[Supernatural]> 143
[21:50] <fdc> 143 unsigned...
[21:50] <fdc> is 0x08F
[21:50] <fdc> do you see what I did?
[21:50] <fdc> the leading digit is now the 0
[21:50] <Aero[Supernatural]> no
[21:50] <fdc> not the 8
[21:50] <fdc> meaning that negatives here will start after 0x800
[21:51] <fdc> but that's not one byte anymore
[21:51] <Aero[Supernatural]> no
[21:51] <Aero[Supernatural]> i was going to convert it to signed
[21:51] <fdc> in other words...143 unsigned
[21:51] <fdc> oh...sorry
[21:51] <fdc> 143 unsigned...go ahead
[21:51] <Aero[Supernatural]> 10001111 => 01110000
[21:52] <Aero[Supernatural]> then I shift until the 9th bit is 1?
[21:52] <Aero[Supernatural]> or just the 8th bit?
[21:52] <fdc> then you add 1, right
[21:52] <Aero[Supernatural]> ah
[21:52] <Aero[Supernatural]> it works
[21:52] <Aero[Supernatural]> it becomes - 113
[21:52] <fdc> right
[21:52] <fdc> and 143 + 113 = 256
[21:52] <Aero[Supernatural]> i knew I was doing something wrong
[21:53] <Aero[Supernatural]> i was just using a number too small before
[21:53] <Aero[Supernatural]> ... did we lose you, damned?
[21:53] <TheDamned[Staves]> I'm still confused, mostly as to the purpose/import of this. So yes.
[21:53] <fdc> ok...that's coming up
[21:53] <Aero[Supernatural]> signed/unsigned is how the system represents negative numbers
[21:53] <fdc> there's a concept called overflow.
[21:53] <Aero[Supernatural]> whenever that's necessary
[21:53] <fdc> in other words
[21:54] <fdc> let's say you have a register holding the value FFFF FFFF
[21:54] <fdc> and you add 0x03 to it
[21:54] <TheDamned[Staves]> Register?
[21:54] <fdc> register are the things that hold values
[21:54] <fdc> think of them as variables
[21:54] <fdc> but that they physicaly would exist on a real PSX machine
[21:54] <TheDamned[Staves]> Ugh. I loathe variables, but okay.
[21:54] <fdc> (or would be simulated exactly by an emulator like pSXfin
[21:54] <TheDamned[Staves]> Weird thing to say as someone that likes math, but okay.
[21:55] <TheDamned[Staves]> My comment, that is.
[21:55] <fdc> but back to what I said...let's say we have FFFF FFFF + 0x0000 0003
[21:55] <fdc> you'd get an overflow
[21:55] <fdc> but what kind of overflow?
[21:55] <fdc> if your number was signed, you have -1 + 3
[21:55] <fdc> which is 2
[21:55] <TheDamned[Staves]> Right.
[21:56] <fdc> but if your number was unsigned, you have 2^32 - 1 + 3
[21:56] <fdc> which the computer cannot express but will still say is 2
[21:56] <fdc> becausee your register can't hold any more data.
[21:56] <fdc> now, you can argue this is no problem since you get 2 in any case, may as well assume FFFF is signed
[21:56] <fdc> *FFFF FFFF
[21:56] <fdc> but...
[21:56] <fdc> what if it was 7FFF FFFF + 0x0000 0003?
[21:56] <fdc> if this is unsigned, this is simply 2^30 -1 + 3
[21:56] <fdc> which is an expressible number
[21:57] <fdc> but if this was signed, 7FFF FFFF + 0x0000 0003 would also yield an overflow
[21:57] <fdc> because 8000 0002
[21:57] <fdc> as a signed number
[21:57] <fdc> is negative
[21:57] <fdc> and obviously, POS + POS = NEG is wrong
[21:57] <fdc> hence the need for signed and unsigned addition.
[21:57] <fdc> are you all with me?
[21:58] <Aero[Supernatural]> yes
[21:58] <TheDamned[Staves]> Not really.
[21:58] <TheDamned[Staves]> I mean, I get why that's "wrong", but not what the above does to "fix" it per se, especially since I'm still silghtly confused about the whole conversion thing and when to use it.
[21:58] <fdc> OK
[21:58] <fdc> let's say there's an instance where you want a number to be unsigned
[21:59] <fdc> *want the result
[21:59] <fdc> then you use the unsigned addition
[21:59] <fdc> addu
[21:59] <fdc> or addiu
[21:59] * Aero[Supernatural] is now known as Aero
[21:59] <fdc> and if there was an opposite instance where being signed is prefered
[21:59] <fdc> you use add or addi
[22:00] <Aero> btw, those are ASM functions, damned
[22:00] <Aero> the 'i' in addi/u means "integer"
[22:00] <TheDamned[Staves]> Right, I have Xifanie's tutorial open even if it still confuses me.
[22:01] <TheDamned[Staves]> Good to now, though.
[22:01] <fdc> no
[22:01] <fdc> i means immediate
[22:01] <fdc> as in you add a constant value
[22:01] <Aero> ... derp
[22:01] <fdc> otherwise, you are adding registers to each other
[22:01] <Aero> so addi is for constants and add is for registers
[22:01] <fdc> right
[22:01] <Aero> what happens if you swap arguments?
[22:01] <Aero> compile error?
[22:02] <fdc> what do you mean?
[22:02] <fdc> you do addi r3, r3, r4?
[22:02] <fdc> yeah
[22:02] <TheDamned[Staves]> Constants?
[22:02] <Aero> try to add a constant with add?
[22:02] <fdc> won't work
[22:02] <fdc> your compiler won't let you
[22:02] <Aero> as i thought
[22:02] <fdc> and if you actually tried that mechanically with the opcodes
[22:02] <Aero> compile error
[22:02] <fdc> ...you'd get something weird
[22:02] <fdc> like add r3, r25, r18
[22:02] <Aero> @damned: non-variable numbers
[22:02] <fdc> instead of add r3, r2, 0x3000
[22:02] <Aero> like a constant would be "127"
[22:03] <Aero> as opposed to a registers (we'll say r2) holding the number "127"
[22:03] <Aero> *register
[22:03] <fdc> IN other words, constants are hard-coded as something you just add
[22:03] <fdc> while registers hold values to be edited during the course of the program by program instructions
[22:03] <fdc> like variables
[22:04] <Aero> it's context sensitive, though
[22:04] <TheDamned[Staves]> No, I get that. I just mean, I guess, I'm not sure where this stuff is coming up.
[22:04] <TheDamned[Staves]> Yeah, I'm missing context. Big time.
[22:04] <fdc> ok
[22:04] <fdc> let's give a real example
[22:04] <Aero> in a high level language, a "constant" could be instantiated, and would mean a value that can't be modified
[22:04] <fdc> remember when I wanted to make FFT make items that subtracted statts?
[22:04] <fdc> like armor that was +250 HP, -1 SPD?
[22:04] <Aero> like const papermache 20
[22:05] <fdc> right.
[22:05] <Aero> so if I used the variable papermache in a program, and tried to add the value 50 to it, i'd get a runtime error
[22:05] <Aero> because it's constant
[22:05] <Aero> in this case, it's not really the same thing
[22:05] <Aero> although there are technically "constant" registers, yes?
[22:05] <TheDamned[Staves]> papermache?
[22:05] <Aero> just an example name of a variable
[22:06] <fdc> yeah
[22:06] <fdc> r0 is always 0
[22:06] <fdc> it's hardcoded that way
[22:06] <Aero> ic
[22:06] <fdc> you can't change it
[22:06] <Aero> so let me rephrase, then
[22:06] <Aero> there are constant values, which are hard-coded values which can't be changed
[22:07] <Aero> and there are constant VARIABLES (in this case, registers) which HOLD hard-coded values which can't be changed
[22:07] <Aero> what we were discussing is, when you want to apply a constant VALUE to a register, you use addi or addiu if it's unsigned
[22:08] <Aero> otherwise, you get a compile error - the program will not execute
[22:08] <fdc> ...yeah...our compiler is glain's MassHex
[22:08] <fdc> which will catch errors like that
[22:08] <Aero> *if you try to use add or addu, you'll get a compile error
[22:08] <Aero> or not
[22:08] <fdc> if you tried typing in the opcodes for these commands directly into your debugger
[22:08] <fdc> you'll get nonsense commands
[22:08] <Aero> let's not overwhelm damned with opcodes and catch functions
[22:09] <fdc> ok
[22:10] * TheDamned[Staves] is now known as TheDamned[Phone]
[22:10] <fdc> ok...is it break time?
[22:10] <fdc> or can I continue?
[22:10] <Aero> yeah, wait a moment
[22:11] <TheDamned[Phone]> You can continue.
[22:11] <fdc> ok
[22:11] <fdc> so you wanted a real life example
[22:11] <fdc> remember when I made the patch that lets you make negative stats?
[22:11] <fdc> like +250 HP -1 SP on armor?
[22:11] <fdc> can you guess what I did?
[22:11] <fdc> just knowing what you do now about signed and unsigned?
[22:12] <Aero> i know what you did
[22:12] <Aero> i'll wait for damned's answer
[22:13] <fdc> Do you see, Damned?
[22:13] <TheDamned[Phone]> Sorry, but I don't.
[22:14] <fdc> FFT by default read everything from your equip data
[22:14] <fdc> as unsigned
[22:14] <fdc> this means that +255 SP means +255 SP
[22:14] <fdc> I changed every one of those reads to signed arithmetic
[22:14] <fdc> so +255 SP really meant -1 SPD
[22:15] <TheDamned[Phone]> Did that affect every SP above 128 inclusive then?
[22:15] <fdc> yes
[22:15] * TheDamned[Phone] is now known as TheDamned[Idiot]
[22:15] <fdc> though of course, you could have underflow
[22:15] <fdc> like 5 base SPD - 7 from equips
[22:15] <fdc> which would give you -2 or 0xFE SPD
[22:15] <fdc> which really was...um...254?
[22:16] * TheDamned[Idiot] shrugs.
[22:16] <fdc> but you see in principle what I mean, right?
[22:16] <TheDamned[Idiot]> In principle with that example, yes.
[22:16] <fdc> (by the way...I actually checked for underflow so if your number was less than or equal to 0, it was set to 1)
[22:17] <fdc> I'll be honest, most of FFT's larger numbers
[22:17] <fdc> like HP
[22:17] <fdc> MP
[22:17] <fdc> and DMG
[22:17] <fdc> are so small compared to maximum size (65536)
[22:17] <fdc> that it really doesn't matter whether you use signed or unsigned
[22:17] <fdc> but for some of the other stats...espeically the ones that are usually only +Stats, it does matter
[22:18] <TheDamned[Idiot]> Why would that be the case when those are even smaller?
[22:18] <fdc> what is "those"?
[22:19] <TheDamned[Idiot]> Stats.
[22:20] <fdc> which ones?
[22:20] <fdc> PA/MA or HP/DMG/MP?
[22:20] <TheDamned[Idiot]> PA & MA & SP. Sorry.
[22:20] <fdc> ok
[22:20] <fdc> the reason is because FFT's formulas
[22:20] <fdc> often are unidirection for thosee
[22:20] <fdc> you can increase PA with PA Save or accumulate
[22:20] <fdc> you can't reduce PA with the same formulas
[22:20] <fdc> and the formulas that reduce PA can't increase them.
[22:20] <fdc> ditto with equips
[22:21] <Aero> hard-coded?
[22:21] <TheDamned[Idiot]> Oh, okay. I guess I see what you're saying. So the HP & DMG generally aren't issues due to "Absorb" then?
[22:21] <fdc> no
[22:21] <fdc> because DMG is capped at 999
[22:22] <fdc> HP rarely exceeds 10k
[22:22] <fdc> and in those ranges, signed and unsigned are the same
[22:22] <fdc> and the formulas for adding and removing HP have a lot more parity
[22:22] <fdc> because of absorb, as you mentioned
[22:23] <TheDamned[Idiot]> Hmmm...I'm still not getting the basics of signed and unsigned then. I know we're talking about decimal in this instance, but where does the hex for that come in here then? (Let's pretend that I fully understand how freely converse things and am not an idiot.)
[22:24] <fdc> I'm not sure what you're asking
[22:24] <Aero> when you program in ASM, you're not going to be using decimal values
[22:24] <Aero> you're going to be using mostly hex, and sometimes binary
[22:24] <TheDamned[Idiot]> I get that.
[22:24] <Aero> oh
[22:24] <Aero> then, i'm with fdc
[22:25] <TheDamned[Idiot]> I mean, when it comes to the HP values, you're saying that they don't need to modified despite going to 65,536. But the signed thing in hex seems like it comes in way before that? So what, exactly, am I not getting here? (Besides far too much.)
[22:26] <fdc> The signed thing in hex
[22:26] <fdc> is exactly at half the value
[22:26] <fdc> or 65535 / 2
[22:26] <fdc> or 2^15
[22:27] <fdc> but the thing is...nothing can have that much HP
[22:27] <TheDamned[Idiot]> ...I guess I get that.
[22:27] <fdc> and you obviously can't do that much damage per unit
[22:27] <TheDamned[Idiot]> Wait, why not?
[22:27] <TheDamned[Idiot]> I mean, that much HP.
[22:27] <fdc> capped at 999
[22:27] <fdc> *because even if your HP multiplier was 255 and growth was 1
[22:27] <fdc> that caps at around 30k at level 99
[22:27] <TheDamned[Idiot]> Oh, okay.
[22:27] <fdc> with lucavi stats
[22:27] <TheDamned[Idiot]> Makes sense.
[22:28] <Aero> it'd probably be an issue if the raw stats where jacked up ludicrously high
[22:28] <Aero> but as they are now, not really
[22:28] <fdc> my point is that the basic operations that then affect HP: dealing damage, healing, and HP total (when you grow)
[22:28] <fdc> cannot exceed the bound of 2^15
[22:28] <Aero> *were jacked up
[22:28] <fdc> and thus, it doesn't matter whether you use signed or not
[22:29] <TheDamned[Idiot]> I had actually wanted to up the raw stats, but not "ridiculously high". Still good to know that I'd have to stay below 32,768 HP.
[22:29] <fdc> all right...what was the next topic?
[22:30] <fdc> logical and arithmetic shifts?
[22:30] <Aero> arithmetic shift, remind me
[22:30] <Aero> that's just addition, isn't it?
[22:30] <fdc> multiplying your number by a power of 2
[22:30] <fdc> or dividing
[22:30] <Aero> oh
[22:30] <Aero> it's just the decimal representation of logical shift, then?
[22:31] <Aero> *a decimal abstraction
[22:31] <fdc> yes
[22:31] <Aero> cool
[22:31] <fdc> Damned, are you with us?
[22:31] <Aero> you can explain logical shift to damned
[22:31] <fdc> ok
[22:31] <fdc> in base 10
[22:32] <fdc> if I add a zero after a number, I multiply by 10, right?
[22:32] <fdc> i.e. 5=>50
[22:32] <TheDamned[Idiot]> Right.
[22:32] <fdc> well...in base 2 or binary
[22:32] <fdc> if I add a zero after a number, I multiply by 2
[22:32] <fdc> i.e. 111=>1110
[22:32] <TheDamned[Idiot]> Right.
[22:33] <fdc> that's the basis for a logical shift
[22:33] <Aero> that's 7 => 14
[22:33] <fdc> a logical shift left
[22:33] <Aero> btw
[22:33] <fdc> adds zeroes to the end.
[22:33] <TheDamned[Idiot]> Right. I understand binary and hex. I just don't get everything else.
[22:33] <fdc> so it multiplies by 2.
[22:33] <Aero> oh
[22:33] <fdc> a logical shift right removes zeroes
[22:33] <Aero> sorry
[22:33] <fdc> so it divides by 2
[22:33] <Aero> i must sound awfully condenscending
[22:33] <TheDamned[Idiot]> Is there a logical shift right?
[22:33] <fdc> yes
[22:33] <fdc> lsr
[22:33] <TheDamned[Idiot]> No problem, Aero. You didn't know.
[22:34] <fdc> anyways...
[22:34] <fdc> there's one thing to remember
[22:34] <fdc> you always round down
[22:34] <TheDamned[Idiot]> Okay. So, lsr isn't arthimetic shift?
[22:34] <Aero> nope
[22:34] <fdc> err...wait
[22:35] <fdc> that's in another programming languge
[22:35] <Aero> Logical Shift Right
[22:35] <fdc> MIPS uses
[22:35] <fdc> sll for logical left shift
[22:35] <fdc> and srl for logical right shift
[22:35] <Aero> interesting
[22:35] <TheDamned[Idiot]> No, I get that. I mean Logical Shift Right isn't arthimetic shift? Given that's it not, what is Arthimetic Shift?
[22:35] <TheDamned[Idiot]> I know you said it above, but...yeah.
[22:36] <Aero> it's the decimal abstraction of logical shift
[22:36] <Aero> you're doing a logical shift with real integers
[22:36] <Aero> in the case of 7 => 14
[22:36] <Aero> you multiply 7 by 2^1
[22:37] <Aero> if you wanted to shift it twice, it'd be 2^2
[22:37] <Aero> 7 => 28
[22:37] <Aero> etc.
[22:37] <TheDamned[Idiot]> Oh, okay. So it's not related to binary at all. I thought it was just converting back from binary to decimal for a bit after a logical shift. Good to know that's not the case.
[22:37] <fdc> now...an arithmetic shift
[22:37] <fdc> is simply a the logical shift but it preserves the signed bit
[22:37] <fdc> in other words
[22:37] <fdc> shift left arithemtic
[22:38] <fdc> for 0x7F is 0x0FE
[22:38] <Aero> ah, that's important to know
[22:38] <fdc> while shift right arithmetic for 0xFE
[22:38] <fdc> is 0xFF
[22:38] <Aero> arithmetic, in this case, is just another word for "signed"
[22:38] <fdc> right
[22:38] <fdc> Damned, do you see how I got both of those numbers?
[22:39] <TheDamned[Idiot]> Yes. 127 => 254.
[22:39] <fdc> right
[22:39] <fdc> but why is it not 0xFE?
[22:39] <TheDamned[Idiot]> It?
[22:39] <fdc> in other words, why did I add a leading zero?
[22:40] <TheDamned[Idiot]> Oh. Ummm...not sure.
[22:40] <fdc> hint...what is 0xFE signed?
[22:40] <TheDamned[Idiot]> -2?
[22:40] <fdc> yeah
[22:40] <fdc> so does 127 * 2 = -2?
[22:40] <TheDamned[Idiot]> No. Okay, I guess I get that even if the whole signed thing is still hazy to me.
[22:41] <TheDamned[Idiot]> I don't get the shift right arthimetic one, though.
[22:41] <fdc> ok
[22:43] <fdc> do you understand why a certain number is negative or positive?
[22:43] <TheDamned[Idiot]> I guess not still, so I'll go with "no".
[22:44] <fdc> ok
[22:45] <fdc> look at the leading digit
[22:45] <fdc> of any hex number
[22:45] <fdc> like 0x32
[22:45] <fdc> or 0x867
[22:45] <fdc> or whatever
[22:45] <fdc> if the leading digit is 8 or greater
[22:45] <fdc> it is negative
[22:45] <fdc> otherwise, it is positive
[22:45] <fdc> IF you are treating it as signed
[22:46] <TheDamned[Idiot]> I get that. I just don't get the "why" behind it, but okay.
[22:46] <Aero> but only if the number is larger than 127 (7F)
[22:46] <TheDamned[Idiot]> Wait, so any leading digit even when the number of hex places is odd?
[22:46] <fdc> yes
[22:47] <Aero> it's just the way programmers have it setup to converve memory
[22:47] <TheDamned[Idiot]> Okay, so between that and what Aero just said, I guess that makes "sense".
[22:47] <TheDamned[Idiot]> So, if that's the case, then something like 0x723 is positive?
[22:47] <fdc> yes
[22:47] <TheDamned[Idiot]> Okay. Slightly more sensical. I doubt I still get all of it, but that makes sense now at least.
[22:48] <fdc> all right, now, since shift right arithmetic must preserve the sign of a number
[22:48] <fdc> do you see why 0xFE turns into 0xFF?
[22:48] <fdc> after 1 application of sra?
[22:48] <TheDamned[Idiot]> Give me a minute go back and check.
[22:48] <TheDamned[Idiot]> Please.
[22:50] <fdc> ok...
[22:50] <TheDamned[Idiot]> Oh, okay. I think I get it. It's because -2 => -1?
[22:50] <fdc> right.
[22:50] <fdc> but notice how sra actually makes numbers bigger in the unsigned sense
[22:50] <TheDamned[Idiot]> Yay. I can do basic math. I feel so accomplished....
[22:50] <fdc> all right...like I said earlier...right shifts
[22:50] <fdc> round down
[22:50] <TheDamned[Idiot]> Okay.
[22:50] <fdc> so 0xFD sra is also 0xFF
[22:51] <TheDamned[Idiot]> Makes sense.
[22:51] <fdc> all right
[22:51] <fdc> some particulars to MIPS
[22:51] <fdc> shift left arithmetic does not exist
[22:51] <fdc> you don't need to worry about it
[22:51] <Aero> what is it rounding?
[22:51] <Aero> brb
[22:51] <TheDamned[Idiot]> Doesn't exist?
[22:52] <fdc> yeah, that command doesn't exist
[22:52] <TheDamned[Idiot]> Isn't that...problematic?
[22:52] <fdc> no
[22:52] <TheDamned[Idiot]> How so?
[22:52] <TheDamned[Idiot]> (You'll probably confuse me, but don't let that stop you.)
[22:53] <fdc> Imagine you wanted to make a positive number large
[22:53] <fdc> you simply use sll
[22:53] <fdc> right?
[22:53] <fdc> if you wanted to make a negative number larger in the negative sense
[22:53] <fdc> you just use sll
[22:53] <fdc> why does this work?
[22:53] <fdc> because if you have 1111 1111
[22:53] <fdc> and you do sll
[22:54] <fdc> you get 1 1111 1110
[22:54] <fdc> but that doesn't fit on one register
[22:54] <fdc> so the upper one is lopped off in the overflow
[22:54] <fdc> and you get 1111 1110
[22:54] <fdc> which is the same thing as if you did sla
[22:54] <Aero> back
[22:54] <Aero> what is sra rounding?
[22:55] <TheDamned[Idiot]> Okay, if you say so.
[22:55] <fdc> you mean from 0xFD to 0xFF?
[22:55] <Aero> yes
[22:55] <fdc> 1111 1101 to 1111 1111
[22:55] <fdc> well, you are taking -3 and turning it into -1
[22:55] <fdc> right?
[22:55] <Aero> why is it rounding it?
[22:56] <fdc> well...if you did 3 srl
[22:56] <fdc> you have 11
[22:56] <fdc> shifting to the right logically simply lops off the lowest bit
[22:56] <fdc> so you have 1 left, right?
[22:56] <Aero> oh
[22:56] <Aero> didn't think of that
[22:57] <Aero> but wait
[22:57] <TheDamned[Idiot]> By "11" you mean 0000 0011?
[22:57] <fdc> mm?
[22:57] <fdc> yeah
[22:57] <TheDamned[Idiot]> Okay.
[22:57] <fdc> I did
[22:57] <Aero> wouldn't it still be 1111111?
[22:57] <Aero> not 11111111?
[22:57] <Aero> oh right
[22:57] <Aero> nvm
[22:57] <fdc> no
[22:57] <fdc> you figured it out
[22:57] <Aero> since it's signed, the number gets larger
[22:57] <fdc> arithmetic = sign preserve
[22:57] <fdc> yeah
[22:58] <fdc> all right...back to some common hex practices
[22:58] <fdc> A) shift left arithemtic
[22:58] <fdc> does not exist
[22:58] <fdc> because sll obviates it
[22:59] <fdc> B) Square often does mutliplication by shift left logical
[22:59] <fdc> as in...if Square wants to multiply by 0x1C0
[22:59] <fdc> they'll do...sll 0x03 (mult by 2^3)
[22:59] <fdc> - copy of self (mult by 7)
[23:00] <fdc> sll 0x0C
[23:00] <fdc> I think that's right...
[23:00] <fdc> wait...no
[23:00] <fdc> err...sll 0x07 (2^7 * 7 = 128 * 7 = 856)
[23:01] <fdc> C) sra is a way to clear a number
[23:01] <fdc> namely, they'll take any register and do sra 0x1F
[23:01] <fdc> recall registers hold 0000 0000 - FFFF FFFF or 4 bytes
[23:02] <fdc> 2^0x1F = 8000 0000
[23:02] <fdc> but obviously, if you do that division without remainder, you get 0
[23:02] <Aero> wait back up
[23:02] <fdc> mm?
[23:02] <Aero> multiply by 0x1C0
[23:02] <Aero> multiply what by 0x1C0
[23:02] * Pride (~Pride@adsl-99-146-31-224.dsl.lsan03.sbcglobal.net) has joined #ffhs
[23:02] <fdc> unit ID
[23:02] <fdc> actually
[23:03] <Aero> or are you saying sll 0x07 is x * 0x1C0?
[23:03] <Aero> because then I don't get how you came up with that
[23:03] <fdc> I meant 2^6
[23:03] <fdc> sorry
[23:03] <Aero> *figured that out
[23:03] <fdc> that's a miscalculation on my part
[23:03] <TheDamned[Idiot]> Formerdeathcorps, would you mind filling in Pride since he can't see the rest of our conversation and I'd be pretty useless trying to tell him what we've gone over?
[23:03] <fdc> so it should be sll 0x06?
[23:03] <fdc> Pride knows most of this
[23:04] <fdc> Pride, ASM lessons here
[23:04] <TheDamned[Idiot]> I know he does.
[23:04] <fdc> I went over signed stuff
[23:04] <Pride> I see
[23:04] <fdc> so why it exists, an example of why it's important
[23:04] <fdc> and now we're talking about how square uses shift left logicals
[23:04] <Aero> why would shifiting logically be 2^6 be the same as multiplying by 448?
[23:04] <fdc> it's not
[23:04] <fdc> the entire process is
[23:04] <fdc> if you start with unit ID
[23:04] <fdc> multiply by 8
[23:04] <fdc> i.e. sll 0x03
[23:04] <fdc> subtract a copy
[23:05] <fdc> i.e. multiply by 7
[23:05] <fdc> and then do sll 0x06
[23:05] <fdc> you multiply by 7 * 64 = 448
[23:05] <Aero> okay
[23:05] <fdc> why is this important?  Because Square uses this to find your unit data table
[23:05] <fdc> that stores all the conditions necessary to determine your unit
[23:05] <Aero> why would shifting logically by 2^3 be the same as multiplying by 8?
[23:06] <Aero> oh wait
[23:06] <Aero> dumb question
[23:06] <Pride> 2 * 2 * 2 = 8
[23:06] <Aero> okay
[23:06] <TheDamned[Idiot]> Why is Subtracting a copy the same as multiplying by 7?
[23:06] <fdc> Damned, do you see all this?
[23:06] <Pride> Its used like this in game
[23:06] <Pride> 0017df0c: 001510c0 sll r2,r21,0x03
[23:06] <Pride> 0017df10: 00551023 subu r2,r2,r21
[23:06] <TheDamned[Idiot]> No, not really.
[23:06] <Pride> 0017df14: 00021180 sll r2,r2,0x06
[23:06] <TheDamned[Idiot]> Subu?
[23:06] <fdc> because if you have 8 copies, and you take one away, you have 7 copies
[23:06] <fdc> subtract unsigned
[23:06] <Pride> It multiplies by 8 then subtracts effictively making  * 7
[23:07] <fdc> before we get there, Pride, I think we need to talk about fractions
[23:07] <fdc> and multiplication
[23:07] <TheDamned[Idiot]> Hmmm...yeah, the "r2" stuff isn't really helping me here.
[23:07] <fdc> all right...
[23:07] <Aero> ignore what pride said
[23:07] <Pride> lol
[23:07] <fdc> Nah...we're getting there...
[23:07] <fdc> just if I started with that, people get lost
[23:08] <fdc> all right...
[23:08] <TheDamned[Idiot]> Also, I kind get what he's saying, just not why "r2" is there twice or, I guess, the specific 8-bit strings in question.
[23:08] <fdc> obviously, every game needs a way to represent fractions
[23:08] <TheDamned[Idiot]> Right.
[23:08] <fdc> FFT does this in an unusual way
[23:08] <fdc> obviously, powers of two can be represented by srl
[23:08] <fdc> or sra
[23:09] <fdc> but how do you express, say...1/3?
[23:09] <fdc> or 1/100?
[23:09] <Aero> upper 8 bits is numerator, lower is denominator?
[23:09] <fdc> That's what I did
[23:09] <fdc> ...but that's not what Square did
[23:09] <TheDamned[Idiot]> Lower?
[23:09] <Aero> oh dear
[23:09] <fdc> yeah...
[23:09] <fdc> what they did is this
[23:09] <fdc> for 1/3
[23:09] <fdc> they multiplied by 5555 5556
[23:10] <fdc> now...
[23:10] <fdc> this is undoubtedly confusing.
[23:10] <fdc> but...
[23:10] <fdc> let's first go over multiplication
[23:10] <Pride> I would suggest too confusing right now
[23:11] <fdc> when you mutliply two 4 byte numbers
[23:11] <fdc> you can potentially get a number with 8 bytes, right?
[23:11] <Aero> sorry, just went back and realized what you did with the whole multiplying by 448 thing
[23:11] <fdc> OK...I'll wait until you all have caught up
[23:12] <Aero> shifted by 8, then subtracted 1?
[23:12] <fdc> yeah
[23:12] <Aero> then shifted again by 64
[23:12] <Aero> or 2^8
[23:12] <fdc> *2^6
[23:12] <Aero> erm... derp
[23:12] <Aero> 2^6
[23:12] <Aero> lol
[23:12] <TheDamned[Idiot]> 2^8 is 256, right?
[23:12] <fdc> yes
[23:12] <Pride> Yes
[23:12] <TheDamned[Idiot]> Also, I get the byte multiplication thing.
[23:13] <fdc> all right...so you should know that
[23:13] <fdc> there are two special registers
[23:13] <fdc> hi
[23:13] <fdc> and lo
[23:13] <fdc> hi stores the upper 4 bytes of your multiplication
[23:13] <fdc> lo stores the lower 4 bytes
[23:13] <fdc> from this...why does 3 * 5555 5556 the equivalent of 3 * 1/3?
[23:13] <TheDamned[Idiot]> Oh, okay. So the first block is what you meant by "lower" earlier?
[23:14] <fdc> can you quote what I said?
[23:14] <TheDamned[Idiot]> Oh, whoops. That was Aero.
[23:14] <Aero> yes, that's what I meant
[23:15] <TheDamned[Idiot]> Oh, okay. Continue.
[23:15] <fdc> all right....I'm posing the question
[23:15] <Aero> he asked us a question
[23:15] <TheDamned[Idiot]> I know.
[23:15] <Aero> and tbh, i don't know
[23:15] <fdc> why does 3 * 5555 5556 the equivalent of 3 * 1/3?
[23:15] <fdc> just do the multiplication by hand if you aren't sure
[23:15] <fdc> 6 * 3 = 18 = 2 carry over 1
[23:15] <fdc> 5 * 3 = F + 1 = 0 carry over 1
[23:16] <fdc> *18 decimal
[23:16] <Aero> 100000002
[23:16] <fdc> right
[23:16] <fdc> now separate that into 4 byte chunks
[23:16] <Aero> used calc, sorry =P
[23:16] <fdc> it's fine
[23:16] <Pride> ^
[23:17] <fdc> you will need your calculator for the following
[23:17] <Aero> in 4 byte chunks, its nine bytes
[23:17] <fdc> right.
[23:17] <TheDamned[Idiot]> Wait, are we supposed to multiple the 5555 5556 as if it's in decimal?
[23:17] <fdc> *no
[23:17] <fdc> it's not
[23:18] <fdc> yes, Damned
[23:18] <fdc> beacuse one byte = 2 hex digits
[23:18] <fdc> so you really have 4.5 bytes
[23:18] <fdc> in the answer
[23:18] <TheDamned[Idiot]> Oh. That makes a lot more sense. I'm getting kind of confused by the whole switching back in forth.
[23:18] <Aero> it's 2 bytes
[23:18] <Aero> *3 bytes
[23:18] <Aero> sorry
[23:18] <Aero> 2 bytes, 4 bits to be exact
[23:18] <fdc> right.
[23:19] <fdc> but we only need precision up to the nearest hex digit
[23:19] <fdc> because that's how precision will be displayed in hex
[23:19] <Aero> right.
[23:20] <fdc> so in groups of 4 bytes, your answer was
[23:20] <fdc> 1
[23:20] <fdc> 0000 0002
[23:20] <fdc> where I subdivide in groups of 2 bytes just for convenience
[23:21] <fdc> Damned, still with us?
[23:21] <TheDamned[Idiot]> Not, really. What I was supposed to be doing with the decimal version 100,000,002?
[23:21] <TheDamned[Idiot]> *Not really.
[23:21] <fdc> nothing
[23:21] <fdc> you want to look at the hex version
[23:22] <TheDamned[Idiot]> Oh.
[23:22] <TheDamned[Idiot]> Hmmmm....
[23:23] <fdc> Do you see what I just mentioned?
[23:23] <fdc> and how it is subdivided?
[23:24] <Aero> 1/2?
[23:24] <fdc> yeah
[23:24] <fdc> so what is in hi?
[23:24] <fdc> and what is in lo?
[23:24] <Aero> 1 is in hi
[23:24] <Aero> 2 is in low
[23:24] <fdc> right
[23:24] <Aero> that is so lame
[23:24] <TheDamned[Idiot]> No, bu that's more because I don't have a working calculator that can go beyond 8 decimal spaces--that has 9--and thus I don't see what that number is in hex.
[23:24] <fdc> but here's the thing...
[23:24] <fdc> oh...
[23:24] <fdc> Damned
[23:24] <TheDamned[Idiot]> *but
[23:24] <fdc> use your Windows Calculator
[23:24] <fdc> don't use a storebought one
[23:25] <fdc> type in 3 * 5555 5556 in hex
[23:25] <TheDamned[Idiot]> Let me find that then. Sigh. Please continue.
[23:25] <fdc> ok
[23:25] <fdc> since 3 * 5555 5556 caused hi to have the value of 1
[23:25] <fdc> we can conclude that hi has the value of 3 * 1/3
[23:25] <fdc> now...why does this work?
[23:25] <fdc> how does multiplying by a very large number give you this?
[23:26] <Aero> because of overflow
[23:26] <fdc> correct
[23:27] <fdc> but specifically, why does 5555 5556 represent 1/3?
[23:27] <Aero> because it's in lo? =_=
[23:28] <fdc> no
[23:28] <fdc> think...what's the largest number allowed in 4 byte representation?
[23:28] <Aero> FFFF FFFF
[23:28] <fdc> right
[23:28] <fdc> and what's FFFF FFFF / 3?
[23:29] <Aero> 5555 5555, apparently
[23:29] <Aero> so it's an overflow using 5555 5555 + 1
[23:29] <fdc> right
[23:29] <fdc> Damned, you with us?
[23:29] <Aero> would it be different if it were actually 1/2?
[23:30] <Aero> or do they always use 5555 5556?
[23:30] <TheDamned[Idiot]> Sorry, I'm an idiot. I took me a while to find Windows Calculator since I've never used it before. Please give me a bit while Aero keeps asking questions.
[23:30] <Aero> k
[23:31] <TheDamned[Idiot]> Hunh. Is the Calculators in Accessory not the same thing you're talking?
[23:31] <TheDamned[Idiot]> *Calculator
[23:32] <Pride> o.o
[23:32] <Pride> That should be the one
[23:32] <fdc> yeah, that's the same thing
[23:32] <fdc> set the mode to scientific
[23:32] <fdc> and turn it to HEX mode
[23:32] <TheDamned[Idiot]> Ah.
[23:33] <TheDamned[Idiot]> Wait, I'm getting the same thing, then? But I thought 100,000,002 wasn't in hex?
[23:33] <fdc> it is
[23:33] <fdc> 5555 5556 * 3 in decimal
[23:34] <fdc> is 1 6666 6668
[23:34] <fdc> I think
[23:34] <TheDamned[Idiot]> Oh, right.
[23:34] * TheDamned[Idiot] is still horribly confused.
[23:34] <fdc> remember when I talked earlier about hi?
[23:34] <TheDamned[Idiot]> Now I need to go back and look at something.
[23:34] <fdc> and lo?
[23:34] <TheDamned[Idiot]> Yes.
[23:35] <fdc> so do you see why 1 is hi?
[23:35] <fdc> and 2 is in lo?
[23:35] <TheDamned[Idiot]> Wait. Is a byte two spaces? Or four spaces?
[23:35] <fdc> a byte is 2 hex digits
[23:35] <TheDamned[Idiot]> Oh, right. This is hex. You said that earlier.
[23:35] * TheDamned[Idiot] facepalms.
[23:35] <TheDamned[Idiot]> Okay, that makes sense then.
[23:36] <TheDamned[Idiot]> Like you and Aero said earlier, 1 is in hi and 0000 0002 is in lo.
[23:37] <fdc> right
[23:37] <fdc> and thus, hi contains 3 * 1/3, right?
[23:37] <fdc> do you see why 5555 5556 must represent 1/3?
[23:37] <fdc> Aero, if you're getting bored
[23:37] <fdc> try figuring out what 1/5
[23:37] <fdc> and 1/7 must be
[23:38] <TheDamned[Idiot]> I'm not seeing why the hi contain 3 * 1/3.
[23:38] <fdc> because 1 is in hi
[23:38] <fdc> and 1 = 3 * 1/3
[23:38] <fdc> right?
[23:38] <fdc> err...3 * 5555 5556
[23:38] <TheDamned[Idiot]> Oh, you literally meant that. Yeah, then.
[23:39] <TheDamned[Idiot]> Sorry of like that modulo inverse thing, not to try to complicate things.
[23:39] <TheDamned[Idiot]> Just takesa  while to get used to.
[23:39] <fdc> ok.
[23:39] <TheDamned[Idiot]> So, then. To find fractions, we just want the hi to equal 1?
[23:39] <TheDamned[Idiot]> Or does the lo actually matter?
[23:39] <fdc> hi only matters
[23:40] <TheDamned[Idiot]> Then wouldn't more things than 5555 5556 be equivalent to 1/3 for 3?
[23:40] <fdc> right
[23:40] <fdc> but why is that true?
[23:41] <Aero> hmmm
[23:41] <TheDamned[Idiot]> Why is what true? That more things than 5555 5556 work?
[23:41] <fdc> (Aero, you already got it, I'm posing this question only to the Damned)
[23:41] <fdc> no, that 5555 5556 functions as 1/3
[23:42] <fdc> for any number until you get to inconceivably large numbers
[23:42] <fdc> why does that always hold true?
[23:42] <TheDamned[Idiot]> I'm...really not sure, especially if only the hi matters.
[23:42] <fdc> think...what is 5555 5555 * 3?
[23:42] <Aero> would 1/5th be.... 3333 3334?
[23:42] <TheDamned[Idiot]> In Hex?
[23:42] <fdc> yes, Aero
[23:43] <fdc> yes, Damned
[23:43] <TheDamned[Idiot]> FFFF FFFF.
[23:43] <fdc> right
[23:43] <fdc> in that case, what is hi?
[23:43] <Aero> and 1/7... 24924925?
[23:43] <TheDamned[Idiot]> 0.
[23:43] <fdc> yes, Aero
[23:43] <Aero> okie-dokie
[23:44] <fdc> do you see how this works now, Damned?
[23:44] <fdc> one less gives you the maximum allowed number in hex
[23:44] <fdc> for 4 bytes
[23:44] <fdc> thus...
[23:44] <fdc> if you divide that number by 3 and add 1, you should always get the desired fraction, right?
[23:45] <fdc> or at the least, a VERY VERY close estimate?
[23:45] <TheDamned[Idiot]> ...I'm just not sure why this is.
[23:45] <Aero> really this is overcomplicating it, isn't it?
[23:45] <fdc> We overflow the excess to hi, right?
[23:45] <Aero> fractions are just division
[23:45] <fdc> right, but Square multiplies a lot of stuff this way
[23:45] <Aero> ic
[23:46] <TheDamned[Idiot]> Overflow in the sense that anything after 4 bytes is hi?
[23:46] <fdc> yes
[23:46] <TheDamned[Idiot]> Right, we do, but I don't get why we do, which is why this and most of the problems I'm having with this are bothering me. I'm trying to see the logic behind it, but I'm just really blind, apparently.
[23:47] * TheDamned[Idiot] is now known as TheDamned[Blind]
[23:47] <fdc> Pride...am I just not explaining well?
[23:49] <Aero> would F * 5555 5556 yield 3?
[23:49] <fdc> yes
[23:49] <fdc> in hi at least
[23:49] <TheDamned[Blind]> Meh, I'm sure you're explaining it fine. I'm just an idiot.
[23:49] <Aero> well, it doesn't for me
[23:49] <TheDamned[Blind]> A tired idiot.
[23:49] <Aero> it yields 5
[23:49] <fdc> err...wait
[23:49] <Aero> oh derp
[23:49] <fdc> 15 / 3 = 5
[23:49] <Aero> it SHOULD yield 5
[23:49] <Aero> i'm dumb
[23:50] <Aero> so basically, hi becomes the answer
[23:50] <Aero> low is just... excess
[23:50] <fdc> right
[23:50] <fdc> in this case, yes
[23:50] <Aero> okay so, damned
[23:50] <Aero> when you apply said number, the overflow is the result you want
[23:50] <Aero> due to how big it is
[23:50] <TheDamned[Blind]> Right. I get that.
[23:51] <TheDamned[Blind]> Just not why it's necessarily fractional to everything as 1/3.
[23:51] <Aero> because of the overflow
[23:51] <fdc> Damned...think of it this way
[23:51] <fdc> imagine you are multiplying by 0.33333333
[23:51] <TheDamned[Blind]> Okay.
[23:51] <fdc> and the excess goes into HI
[23:52] <fdc> err...
[23:52] <fdc> I mean 33333333
[23:52] <fdc> and then you divide by the appropriate power of 10
[23:52] <TheDamned[Blind]> Uh, okay.
[23:52] <fdc> would you not agree that is an estimate of 1/3?
[23:52] <fdc> not exact, but close?
[23:52] <TheDamned[Blind]> Yes.
[23:52] <fdc> that's the same idea
[23:52] <fdc> but in hex
[23:52] <fdc> 5555 5555 * 3 = FFFF FFFF
[23:53] <fdc> so by the overflow...5555 5556 must approximate 1/3 very well
[23:53] <fdc> the same way 3333 3334 approximates 1/3 in decimal
[23:53] <Aero> in otherwords, damned
[23:53] <Aero> fdc came about that number by dividing FFFF FFFF by 3
[23:53] <Aero> and adding 1
[23:54] <TheDamned[Blind]> I understand that much. I guess I'm just not getting why the overflow of "just" 1 is, in actuality, "always" 1/3.
[23:55] <Aero> it isn't
[23:55] <fdc> because you're multiplying by really small numbers
[23:55] <Aero> it's actually supposed to be 0
[23:55] <Aero> but it's necessary to represent the system using hi and lo registers
[23:55] <fdc> ...and thus, your overflow isn't 4 bytes long
[23:55] <fdc> and because of it
[23:55] <Aero> so by default, there will always be an overflow of at least 1
[23:55] <Aero> right?
[23:55] <fdc> the result in hi isn't affected by what's in lo
[23:55] <fdc> right, Aero
[23:55] <Aero> 3 * 1/3 = 1
[23:56] <Aero> derp, that first part I said is totally wrong
[23:56] <TheDamned[Blind]> I guess I'm really just not getting this, then. Because I get all that, but I don't the general concept that fdc was trying to end on.
[23:56] <fdc> All right...that's it
[23:56] <fdc> Damned...multiply 3 * 3334
[23:56] <fdc> what do you get?
[23:57] <TheDamned[Blind]> 10002
[23:57] <fdc> now group the digits in groups of 4
[23:57] <TheDamned[Blind]> 1 0002. Okay.
[23:57] <fdc> would you say that the first number represents 3 * 1/3?
[23:57] <fdc> the first group of 4 digits?
[23:58] <fdc> ...still here?
[23:58] <TheDamned[Blind]> Well, 1 is equivalent to 1/3 * 3, yes. However, I'm still not getting why 5555 5556 is the *only* number to be 1/3?
[23:58] <TheDamned[Blind]> *be 1/3.
[23:58] <fdc> it's the best one
[23:58] <TheDamned[Blind]> I mean, what if we did 5555 5557.
[23:59] <TheDamned[Blind]> *5555 5557?
[23:59] <fdc> think...why would you approximate 1/3 as 3334 / 10000?>
[23:59] <fdc> and not 3335 / 10000?
[23:59] <fdc> like we did in that example above?
[23:59] <TheDamned[Blind]> It's a closer approximation because it's the lowest possible fit (ignoring 3333)?
[23:59] <Aero> right
Session Time: Sat Mar 24 00:00:00 2012
[00:00] <Aero> closest possible fit without excess
[00:00] <fdc> right.
[00:00] <fdc> that's the same reason for 5555 5556
[00:00] <TheDamned[Blind]> Oh. Okay. That makes sense then. When asked up above, I thought fdc had said that 5555 5556 was the *only* thing that would function as 1/3, not just the best one. That clears up everything then.
[00:00] <TheDamned[Blind]> Sorry.
[00:00] <fdc> it's OK
[00:00] <TheDamned[Blind]> Like I said at the beginning of this, I'm a brick wall.
[00:00] <fdc> as long as you get it
[00:01] <Aero> it's 12:00 over here
[00:01] <fdc> yeah
[00:01] <TheDamned[Blind]> Barely at this point. I'm still not entirely sure I get the signed thing, but let's continue. Maybe we'll see if I can get my emulator running and screw up a status horribly.
[00:01] <Aero> you guys can continue, but i'm calling it quits
[00:01] <fdc> same for the Damned
[00:01] <fdc> ok
[00:02] <TheDamned[Blind]> Oh, right. You're ahead of us too, fdc.
[00:02] <Aero> Damned is in west coast?
[00:02] <TheDamned[Blind]> You should probably go to bed.
[00:02] <fdc> yes
[00:02] <TheDamned[Blind]> Yeah.
[00:02] <fdc> We haven't covered the structure of commands yet
[00:02] <fdc> but I think we've done more than enough to think about



NAMED EDIT: I figured that I should probably make it more apparent the name of the "teacher" who put up with my idiocy for 2 and a half hours. After all, credit where credit is due.
Title: Re: ASM Lessons
Post by: formerdeathcorps on March 24, 2012, 03:50:49 am
The next session will be sometime tomorrow afternoon (PST).  I presume that whoever wishes to join me tomorrow understands Xif's tutorial on the website's main page (Xif's ASM tutorial (http://ffhacktics.com/tutorials.php?id=11)).
Title: Re: ASM Lessons
Post by: AeroGP on March 24, 2012, 09:25:41 pm
Session Start (FFHacktics:#ffhs): Sat Mar 24 15:23:16 2012 -0700
*** Aero[homework] has joined #ffhs
<formerdeathcorps> hey Aero
<formerdeathcorps> ready for the lesson?
*** iRyu has quit IRC: Ping timeout: 204 seconds
<Aero[homework]> nope
<Aero[homework]> i'm just preparing
<Aero[homework]> in case you start without me
<formerdeathcorps> I'm not
<Aero[homework]> that way I can follow along
<formerdeathcorps> as no students have shown up
<Aero[homework]> =/
<Aero[homework]> I'll be ready in... an hour tops
<Aero[homework]> I'm going to do a small portion of my homework and try to finish everything tomorrow
<Aero[homework]> I guess I work better with a fire lit under my ass
*** Pride has joined #ffhs
<formerdeathcorps> Pride, do you have the revised weapon XA hack with you?
<Pride> (Link: http://ffhacktics.com/wiki/Base_Weapon_XA_Rewrite)http://ffhacktics.com/wiki/Base_Weapon_XA_Rewrite
<secondadvent> should i throw in some graphical code to be mean? :v
<secondadvent> or to be really mean, BoF3 code? :P
<formerdeathcorps> in the lesson itself?
<formerdeathcorps> not yet
<secondadvent> what -not- to do
<formerdeathcorps> oh yeah
<formerdeathcorps> but no human being is that stupid
<formerdeathcorps> only compilers doing type casts can
<formerdeathcorps> do that
<formerdeathcorps> SA, actually I want you to talk about disk sectors
<formerdeathcorps> and compression
<formerdeathcorps> you know more about both than me
<formerdeathcorps> but that won't be necessary until we talk about "special topics"
<secondadvent> (Link: http://www.gamefront.com/files/21463912/facepalm.txt)http://www.gamefront.com/files/21463912/facepalm.txt
<secondadvent> while these two routines are badly done, it should still be something that's somewhat easy to read/get started with :P
<secondadvent> not FFT, but still
<Aero[homework]> why hasn't someone rewritten most of the game yet?
<Aero[homework]> i mean small patches are nice, but you'd think with all this information sweeping optimizations would have been made
<Aero[homework]> in at least one area, anyways
<Aero[homework]> or am I uninformed?
<formerdeathcorps> Have you written code before, Aero?
<Aero[homework]> not ASM for FFT
<Aero[homework]> is it overbearing?
<Aero[homework]> *overwhelming
<formerdeathcorps> It's worse than Squarecode
<Aero[homework]> You mean code Square uses for games other than FFT?
<formerdeathcorps> No
<formerdeathcorps> I mean code written by kids just out of college
<formerdeathcorps> who forgot their Data Structures class
<Aero[homework]> ... I was talking about that word "Squarecode"
<formerdeathcorps> No, Aero...that's Square's code
<formerdeathcorps> for any game
<formerdeathcorps> FFT/FFVII anything
<formerdeathcorps> though...to be honest, FFI was atrocious
<formerdeathcorps> it's gotten better over time
<Aero[homework]> okay, so then you confused what I was referring to
<Aero[homework]> I am not talking about BoF3
<formerdeathcorps> maybe I did get confused
<formerdeathcorps> what were you trying to say?
<Aero[homework]> why hasn't someone done some major changes to FFT outside of small patches?
<Aero[homework]> optimizations, restructuring, stuff like that?
<formerdeathcorps> have you written code before?
<Aero[homework]> same answer, eh?
<formerdeathcorps> My point is that
<formerdeathcorps> if you have
<formerdeathcorps> you'd know that in any High LEvel Language
<formerdeathcorps> the logic of whatever you write
<formerdeathcorps> usually takes up a few KB at most
<formerdeathcorps> after weeks of work
<formerdeathcorps> the rest is simply filler space
<formerdeathcorps> now...BATTLE.BIN is 1.5 MB
<Aero[homework]> ah
<formerdeathcorps> or something close to that
<Aero[homework]> it's hard to find routines, yes?
<formerdeathcorps> no.
<formerdeathcorps> rather...
<formerdeathcorps> imagine if we had to replace 20 KB
<formerdeathcorps> of routines
<formerdeathcorps> entirely customly
<formerdeathcorps> that's the equivalent of doing this as a full time job for about 4 months
<formerdeathcorps> and because of the support structure
<Aero[homework]> i can't imagine it taking that long for someone as talented as you
<Aero[homework]> o_O
<formerdeathcorps> your custom stuff has to "fit"
<formerdeathcorps> within the rest of it.
<formerdeathcorps> you know...let's say I wanted to expand the item table to 512 items
<Aero[homework]> if it were written in an even higher level like c++
<formerdeathcorps> to do that reuiqres changing every single instance that reads items
<Aero[homework]> and you could see the miles of data structures and stuff
<formerdeathcorps> to halfword
<formerdeathcorps> correct, Aero
<formerdeathcorps> but there's one thing...doing that
<Aero[homework]> I still can't imagine taking more than 2 months to do a full overhaul of one aspect
<formerdeathcorps> *we can't increase file-size AEro
<Aero[homework]> oh
<Aero[homework]> you know, that could have been the first thing you said
<Aero[homework]> I'd understand that
<Aero[homework]> same issue with hacking sonic games
*** Aero[homework] is now known as Aero
<Aero> in any case, i'm finishing homework tomorrow
<secondadvent> there's also testing/planning/rewriting of your own code
<secondadvent> sometimes a single mistake can require a ton of changes that could set you back a ways
<secondadvent> and then there's occasionally times when you can't figure out why something isn't working correctly, which requires time to debug/change code to fix it
<Aero> well, i do that all the time with my fangame
<formerdeathcorps> because the RAM is 2 MB
<formerdeathcorps> and because we don't know ROM expansion
<formerdeathcorps> seeing miles of data structures is fine...we already do...but fixing them requires you do fix all the cross-references...something that's much harder to do in ASM than with a nice comipler pointing out the entire run cycle for you
<formerdeathcorps> *fixing them entirely as you want
<formerdeathcorps> and much of the cross-reference "linker" routines are uncharted territory because they're not as much the "meat" as the code that actually determines damage and stuff
<formerdeathcorps> but if you want to change the data strucutres, you need to fix those too
<formerdeathcorps> The problem is also...if you tried reverse transcribing FFT into C
<formerdeathcorps> you'll also get stuff that will be marked poorly or left out with ???
<formerdeathcorps> exactly, the trials of a coder
<formerdeathcorps> Pokeytax wrote close to 2 KB of code
<formerdeathcorps> and a 10 KB data structure
<Aero> whoa, wtf?
<formerdeathcorps> ...it took him 4 months?
<Aero> my internet must have hiccuped
<formerdeathcorps> and seriously...it wore him out
*** -NickServ- This nickname is registered. Please choose a different nickname, or identify via /msg NickServ identify <password>.
<Aero> hold on
<formerdeathcorps> and is bugged like crazy
*** -to NickServ-: r@gingst0rm
*** -NickServ- Invalid command. Use /msg NickServ help for a command listing.
<formerdeathcorps> sorry
*** -to NickServ-: identify r@gingst0rm
*** -NickServ- You are now identified for Aero.
<formerdeathcorps> all right
<formerdeathcorps> ready, AEro?
<Aero> hold on, just reread what my dumb internet had backlogged somehow
<Aero> at least, I think it was me
<formerdeathcorps> I read it.
<Aero> <Aero> well, i do that all the time with my fangame
<Aero> whos post was directly before this one?
<formerdeathcorps> oh, must have missed that one
<Aero> *message
<Aero> ^
<secondadvent> my internet seemed to hiccup as well
<Aero> it might be fdc, or the server
<Aero> or something
<Aero> anyways, i was responding to 2nd
<Aero> but it doesn't matter
<Aero> that longass explanation fdc gave convinced me
<Aero> I guess I'm ready
<formerdeathcorps> all right
<formerdeathcorps> we left off yesterday at mult
<formerdeathcorps> I think you got the hang of how to create fractions
<Aero> yes
<formerdeathcorps> just as a quick exercise
<formerdeathcorps> how would you do 30%?
<Aero> it's wierd that square would do it that way, but I guess it's so they can still have numeric values up to 4294967295
<Aero> as for your question
<formerdeathcorps> right.
<Aero> 3 * 5555 5556
<Aero> although it wouldn't really be 30%
<formerdeathcorps> it's not
<Aero> it's be more like 33.3333333%
<Aero> *it'd
<formerdeathcorps> in short...we did the unit fraction case last night
<formerdeathcorps> if we were to do non-unit fractions, how would you proceed?
<Aero> what would be different about it?
<formerdeathcorps> well...go through the process and you tell me
<Aero> hmm
<Aero> 30% is 3/10
<formerdeathcorps> right
<Aero> so it'd be 3 * 1/10
<formerdeathcorps> ok
<Aero> which is 3 * 1000 0000
<Aero> erm... hmmm
<Aero> derp
<Aero> 3 * 1999999A
<Aero> ... still no
<Aero> fuck
<formerdeathcorps> hint...
<formerdeathcorps> take FFFFFFFF as a decimal
<formerdeathcorps> multiply by 3/10
<formerdeathcorps> and then round up
<Aero> oh
<Aero> i keep just dividing by 10
<Aero> or rather A
<Aero> for 1/10
<formerdeathcorps> right
<secondadvent> i usually go 0x100000000 instead of FFFFFFFF
<Aero> but then just multiplying by 3 wouldn't teh same
<Aero> *wouldn't be the same
<Aero> would it?
<Aero> or would my answer just be incomplete
<Aero> duh, of course it would
<Aero> 3 * 1999999A
<formerdeathcorps> you divide last
<Aero> ... oh
<formerdeathcorps> so you do 3 * FFFF FFFF first
<formerdeathcorps> and then divide
<formerdeathcorps> and add 1
<Aero> 4CCCCCCD
<formerdeathcorps> do you see why?
<Aero> what, but...
<formerdeathcorps> you do this rather than the opposite?
<Aero> the way I did it before was just as good an answer
<formerdeathcorps> except there's one problem...
<formerdeathcorps> the +1 part?
<Aero> it isn't closest to the factional equivalent?
<formerdeathcorps> was to estimate right?
<formerdeathcorps> a roundoff error
<Aero> oh
<formerdeathcorps> you also want to make that roundoff error last
<formerdeathcorps> in any list of calculations
<Aero> can't round off until after all is said and done
<formerdeathcorps> to limit total error
<formerdeathcorps> right
<Aero> hold on
<formerdeathcorps> FFFF FFFF / A
<Aero> 19999999
<formerdeathcorps> you add 1
<formerdeathcorps> to get 1/10
<Aero> 1999 999A
<formerdeathcorps> but that leaves a roundoff error there
<formerdeathcorps> which you then amplify by multiplication
<Aero> =/
<secondadvent> what i usually do is use wincalc in scientific mode, enter the decimal value i want, * 0x100000000 and get the value i want (still need to round though) :P
<formerdeathcorps> now...let's see some examples from Square
<formerdeathcorps> The DEFUP code
<formerdeathcorps> is * 2/3 right?
<Aero> that'd be [(FFFF FFFF * 2)/3]+1
<Aero> which is AAAAAAAB
<formerdeathcorps> you would think so
<formerdeathcorps> Square, however
<formerdeathcorps> does not do that
<formerdeathcorps> they split the steps up
<Aero> -_-;
<formerdeathcorps> 1) XA * 2
<formerdeathcorps> then divide by 3
<secondadvent> they do * 1/3 then sll 0x1 right?
<formerdeathcorps> do they, SA?
<secondadvent> i forget
<secondadvent> :P
<formerdeathcorps> that's even worse, that leaves round off errors
<formerdeathcorps> point is...Square is inefficient
<secondadvent> i'm working on no sleep here
<formerdeathcorps> Aero, want to guess the reason why they don't do that?
<Aero> well, i don't expect them to process the whole calculation in one line
<Aero> ASM can't do that
<formerdeathcorps> ASM can
<formerdeathcorps> simply type in AAAA AAAB
<secondadvent> yep
<Aero> ... oh
<formerdeathcorps> and have your compiler figure out properly how to do fractions
<Aero> derp, forgot that's how it's used
<formerdeathcorps> but guess why Square didn't
<formerdeathcorps> (hint...remember the discussion we had yesterday about signed numbers)
<Aero> okay... why doesn't square do it that way?
<Aero> oh
<Aero> is the damage signed?
<Aero> due to absorb?
<formerdeathcorps> yeah
<Aero> ah
<formerdeathcorps> there's two forms of sign
<formerdeathcorps> *mult
<formerdeathcorps> rather
<formerdeathcorps> mult and multu
<formerdeathcorps> signed and unsigned
<formerdeathcorps> as a practice, to stop stupidity, always use multu
<formerdeathcorps> just so you can express all fractions
<Aero> k
<formerdeathcorps> there is another way...slightly less precise
<formerdeathcorps> but it's the way SA and I use
<formerdeathcorps> we simply multiply by a byte
<formerdeathcorps> and divide by 128
<secondadvent> oh derp, i had the order reversed
<secondadvent> i need sleep
<formerdeathcorps> (i.e. srl 0x07)
<formerdeathcorps> Square never does this
<formerdeathcorps> but you'll see this in my code and SA's
<Aero> ic
<formerdeathcorps> in that system
<formerdeathcorps> 56 is 1/3
<formerdeathcorps> 34 is 1/5
<formerdeathcorps> err...no
<Aero> ;p;
<Aero> *lol
<formerdeathcorps> 2B is 1/3
<formerdeathcorps> anyways...the advantages here
<formerdeathcorps> is that you only need to multiply by one byte
<formerdeathcorps> so you can just extract your number from lo
<formerdeathcorps> and that you can use small numbers (faster operations when you do the srl)
<Aero> cool
<formerdeathcorps> also...you can express all multipliers
<formerdeathcorps> from 0 to 2
<Aero> how'd you determine the bytes?
<Aero> FF / 128?
<formerdeathcorps> the same way as you did before, Aero
<formerdeathcorps> no
<formerdeathcorps> 7F * MULT + 1
<Aero> where MULT is?
<formerdeathcorps> your desired multiplier
<formerdeathcorps> between 0 and 2
<formerdeathcorps> obviously, if your multiplier is 0
<formerdeathcorps> just clear out your variable
<formerdeathcorps> and if it's a power of two, use the shift right / left logicals
<Aero> okay, i'm getting like damned now, though
<formerdeathcorps> sorry
<Aero> why only between 0 and 2
<Aero> *?
<Aero> show me an example
<Aero> show me how you got 2B
<formerdeathcorps> 7F * 1/3 + 1
<formerdeathcorps> 7F * 1/3 = 2A
<formerdeathcorps> +1 is 2B
<Aero> oh
<formerdeathcorps> why is it only between 0 and 2?
<Aero> you cut the fraction down to 7 bytes?
<formerdeathcorps> yeah
<Aero> interesting
<formerdeathcorps> this is just a simple way of doing fractions by bytes
<formerdeathcorps> that way people don't need to remember large numbers
<formerdeathcorps> obviously, if you have large denominators like 100, you don't have a choice
<Aero> OH DERP
<Aero> i got confused again, but I figured it out
<Aero> instead of FFFF FFFF, you used 7F
<formerdeathcorps> but for small fractions, this approximation holds for all values up to around 60 or so
<formerdeathcorps> right
<Aero> now I wonder how I got the wrong numbers before
<Aero> what was I thinking?
<Aero> o_O
<formerdeathcorps> do you see why the multipliers are between 0 and 2?
<Aero> yes
<formerdeathcorps> ok
<formerdeathcorps> now...
<formerdeathcorps> Square, sadly, is not this smart
<Aero> there aren't enough bytes to properly represent fractions larger than 2
<formerdeathcorps> correct, Aero
<formerdeathcorps> just like base 10 can't represent anything not a power of 2 or 5
<formerdeathcorps> SA, care to explain how Square does percents?
<Aero> I wouldn't blanket term them
<Aero> we have interviews and such, don't we
<Aero> it was a very poor, very specific team
<formerdeathcorps> ok, sure
<Aero> that is probably no longer working there
<formerdeathcorps> SA, can you explain how FFT coded percents?
<Aero> lol
<formerdeathcorps> just to give a comparison?
<formerdeathcorps> all right... I will
<formerdeathcorps> FFT does percents
<secondadvent> you go ahead, i'm ready to pass out. i'll try to be more helpful tomorrow :P
<formerdeathcorps> by dividing by 1/320 or something like that
<Aero> o_O
<formerdeathcorps> and then multiplies by 2^5
<formerdeathcorps> and divides by 10
<formerdeathcorps> it's awful
<Pride> lol
<Aero> so... they round it to 1/100th then they scale back up?
<formerdeathcorps> yeah
<Aero> >_<
<formerdeathcorps> The reason why Square does this?
<formerdeathcorps> Speed
<formerdeathcorps> sll / srl
<formerdeathcorps> are the fastest operations
<formerdeathcorps> mind you...this wastes space
<formerdeathcorps> ...and that's what matters most to us
<Aero> so you took a trade-off - ease of user for slight speed disadvantage?
<formerdeathcorps> Aero, since most of us use emulators
<formerdeathcorps> on machines far stronger than the PSX
<formerdeathcorps> That's hardly an issue since the same thing would run on the real machine
<formerdeathcorps> just a few microseconds slower
<Aero> yeah, I get you
<Aero> Knowing that they did it for speed, though
<Aero> I wouldn't blame 'em
<formerdeathcorps> back to your earlier question yesterday
<Aero> They still ended up with slowdown, but they tried
<Aero> =/
<formerdeathcorps> why don't we just multiply and divide
<formerdeathcorps> divide exists also as a FFT function
<formerdeathcorps> but there's two things to know immediately
<formerdeathcorps> DIV / DIVU
<formerdeathcorps> is a very costly operation
<formerdeathcorps> it is twice as costly as multiplication
<formerdeathcorps> and if you think about why...it makes sense
<Aero> of course
* Pride didn't know that
<Aero> division operators are always more costly
<formerdeathcorps> to be able to divide you need to be able to multiply
<Aero> apparently
<formerdeathcorps> and subtract
<Aero> it's simpler to multiply by a fraction than directly divide an integer.
<formerdeathcorps> correct
<Aero> for some reason
<formerdeathcorps> which is why Square does what it does
<formerdeathcorps> in MIPS
<formerdeathcorps> the reason is simple
<formerdeathcorps> everything is an int
<formerdeathcorps> floating point does not exist
<Aero> ah
<formerdeathcorps> video game systems tend to have fast integer based engines
<Aero> so extra processor time is spent rounding off the excess
<formerdeathcorps> most consoles have floating point
<formerdeathcorps> exactly
<Aero> that makes sense
<formerdeathcorps> *most PCs I mean
<formerdeathcorps> *most consoles have the integer engines
<formerdeathcorps> anyways...
<formerdeathcorps> the only time square uses divide
<formerdeathcorps> is usually when the number they are dividing by
<formerdeathcorps> is variable
<formerdeathcorps> and not constant
<Aero> so they can't readily conver it
<Aero> *convert
<formerdeathcorps> right
<formerdeathcorps> which is why your computer must be stronger a processor than the console
<formerdeathcorps> which is also why emulating the PS2 is so hard
<formerdeathcorps> it uses SO much resources
<formerdeathcorps> because we need to remember that just based on processor speed, for when it was released, the PS2 was several years ahead of its field
<formerdeathcorps> anyhow...this is a serious digression
<formerdeathcorps> you just need to remember that div
<formerdeathcorps> stores the result in hi
<formerdeathcorps> and the remainder in lo
<Aero> k
<formerdeathcorps> the only thing is...the remainder is virtually never used in FFT
<formerdeathcorps> even though I found it quite useful...mathematically
<Aero> because they round EVERYTHING
<formerdeathcorps> well, no
<formerdeathcorps> let's say you want to calculate patterns in the Zodiac
<formerdeathcorps> the easy way is to use modular divison
<formerdeathcorps> the stupid way is to waste space the way Square did
<Pride> lol
<formerdeathcorps> ...making separate flags for when units had opposite alignment and stuff
<Aero> can't even stay consistent with their own design ethic
<Aero> dur, zodiac patterns are good place to break our edict on saving processor speed hur!
<formerdeathcorps> the result is their routine is longer
<formerdeathcorps> and actually just as bad
<Aero> actually, i should ask this
<formerdeathcorps> mm?
<Aero> why does the filesize need to be maintained?
<formerdeathcorps> you can't make the file larger
<secondadvent> their way FFT usually does it is -> base - (base / X * X)
<formerdeathcorps> because each file is given a fixed number of disk sectors
<formerdeathcorps> and after each file is the next one
<formerdeathcorps> on the disk
<Aero> oh
<formerdeathcorps> thus, if you made one file larger
<Aero> that can't be adjusted?
<formerdeathcorps> you'll have to edit every other file
<secondadvent> i can increase filesize in BoF3 though
<Aero> or is it just too costly
<formerdeathcorps> *not easily, Aero
<Aero> okay
<formerdeathcorps> also...you have to adjust it in RAM
<Aero> just curious
<secondadvent> since it has a neat little LBA table
<formerdeathcorps> and that's the really nasty part
<formerdeathcorps> because if I made BATTLE.BIN larger
<formerdeathcorps> I'd have to make another file smaller
<secondadvent> and has a file header for how large the subfiles are, and where to load in RAM
<formerdeathcorps> and adjust every single pointer to that second file
<Aero> what a hassle
<formerdeathcorps> exactly
<formerdeathcorps> which is why I'd prefer not to think about it
<Pride> A shame really
<formerdeathcorps> now...onwards to OPCODES
<secondadvent> nop
<Pride> :x
* secondadvent losing powe...
<formerdeathcorps> these make up the basic instructions of MIPS
<formerdeathcorps> I've already introduced you to some, Aero
<formerdeathcorps> shifts
<formerdeathcorps> adds
<formerdeathcorps> subtracts
<formerdeathcorps> you probably should remember these
<formerdeathcorps> as an example
<formerdeathcorps> add r1, r2, r3
<formerdeathcorps> what does this mean?
<formerdeathcorps> it takes r2 and r3
<formerdeathcorps> the values in them
<formerdeathcorps> adds them
<formerdeathcorps> and puts the result in r1
<formerdeathcorps> in general, when you read opcodes
<formerdeathcorps> the first register given
<Aero> so if you just wanted one or the other, it'd be
<Aero> add r1, r2?
<formerdeathcorps> is always the one whose value gets replaced
<Aero> or addi, r1, r2, 0?
<formerdeathcorps> right
<formerdeathcorps> except since MIPS is 32-bit
<Aero> ... erm, which one
<formerdeathcorps> you always have 3 arguments
<Aero> oh
<Aero> k
<formerdeathcorps> the first one is always the value that gets replaced
<Aero> i do remember argument order
<Aero> from my class
<formerdeathcorps> right.
<formerdeathcorps> just know that since 32-bit commands
<formerdeathcorps> have 3 arguments
<formerdeathcorps> the first one has no place
<formerdeathcorps> in the calculation itself
<Aero> k
<Aero> argument1 is the destination
<formerdeathcorps> right
<Aero> argument2 is formula argument 1
<formerdeathcorps> hence known as the rd
<formerdeathcorps> rs
<Aero> argument3 is formula argument2
<formerdeathcorps> right
<formerdeathcorps> but argument 3 is sometimes a constant
<Aero> right
<formerdeathcorps> (all constants in MIPS are halfwords
<formerdeathcorps> i.e. 2 bytes
<Aero> so they can't be larger than FF FF?
<formerdeathcorps> right
<Aero> i guess 65536 is sufficiently large
<formerdeathcorps> also...one thing to note
<Aero> *6553
<Aero> *5
<formerdeathcorps> all constants are signed
<Aero> ugh
<Aero> so it's not even that
<formerdeathcorps> except for logic commands
<formerdeathcorps> like and / xor
<formerdeathcorps> err...
<formerdeathcorps> andi / xori / ori
<Aero> it's {-255, 255}
<Aero> lame
<formerdeathcorps> no
<formerdeathcorps> more like (-2^15, 2^15)
<formerdeathcorps> a very large space
<formerdeathcorps> now...let's refer to my list
<Aero> {-32768, 32768}
<formerdeathcorps> (Link: http://ffhacktics.com/smf/index.php?topic=6728.0)http://ffhacktics.com/smf/index.php?topic=6728.0
<Aero> onto your list
<Aero> ah
<Aero> okay, so now you guy's code snippets make sense
<Aero> first 2 bytes is the opcode
<Aero> all others are arguments
<Aero> right?
<formerdeathcorps> right
<Aero> so I just gotta memorize the op codes
<Aero> hmmm
<formerdeathcorps> back in the old days...yes
<formerdeathcorps> you did
<formerdeathcorps> now we have massHex
<Aero> oh
<formerdeathcorps> and you just need to be able to write opcodes
<formerdeathcorps> symbolically
<Aero> ah
<secondadvent> i still do it in a hex editor though
<formerdeathcorps> correct
<formerdeathcorps> because of that
<formerdeathcorps> it is still advised you memorize opcodes
<Aero> the snippets are just how your compiler exports the high level language
<Pride> I'm surprised you don't have Jump Register on that list
<Aero> figures
<formerdeathcorps> I don't?
<Aero> he doesn't?
<formerdeathcorps> yes I do
<Pride> Oh I see it
<Pride> nvm
<formerdeathcorps> it's under R commands
<Pride> Yeah I was just looking under the jump commands
<Aero> in my class, we use visual studio to write ASM
<Aero> so we didn't have to remember the opcodes in hex
<Aero> just the shorthands
<Aero> so I know some of them
<formerdeathcorps> Aero, to know the opcodes you have to deconstruct the commands in binary
<Aero> but not the IDs
<formerdeathcorps> let's give an example
<formerdeathcorps> add r1, r2, r3
<formerdeathcorps> the first is add
<Aero> oh dur
<formerdeathcorps> 100 000
<formerdeathcorps> or 1000 00
<formerdeathcorps> err...wait
<Aero> wait, no
<formerdeathcorps> 10 0000
<Aero> hmmm
<formerdeathcorps> notice that is hex for 20
<Aero> where'd you get that number?
<formerdeathcorps> the first four zeroes
<formerdeathcorps> form the 0 byte
<formerdeathcorps> *0 hex digit
<Aero> no
<Aero> not the 20
<Aero> the binary
<formerdeathcorps> right
<formerdeathcorps> 10 0000 = 0010 0000
<formerdeathcorps> the first hex digit is 0
<formerdeathcorps> 0010 is 2
<formerdeathcorps> right?
<Aero> ...
<Aero> NO
<Aero> not the 20
<formerdeathcorps> what?
<Aero> where'd you get 0010 0000
<Aero> *?
<formerdeathcorps> look at the tutorial
<Aero> they're predefined, then?
<formerdeathcorps> the opcode for ADD is 10 0000
<formerdeathcorps> yeah
<Aero> why'd you say: <formerdeathcorps> Aero, to know the opcodes you have to deconstruct the commands in binary
<formerdeathcorps> because 20 = 10 0000 in binary?
<Aero> <Aero> in my class, we use visual studio to write ASM <Aero> so we didn't have to remember the opcodes in hex <Aero> just the shorthands <Aero> so I know some of them
<formerdeathcorps> right.
<Aero> semantics: you were complaining that I said that i didn't need to know them in hex, but they're in binary first
<Aero> semantics
<Aero> you know what I meant. >_<
<formerdeathcorps> you don't need to know them in hex, because we have the tools to ignore this
<formerdeathcorps> but if you want to know it
<Aero> ....
<formerdeathcorps> you need to be able to use binary to decompose stuff
<Aero> seems you didn't know what I meant
<Aero> my point was, i didn't need to know the opcodes
<Aero> before
<Aero> nothing more
<Aero> semantics
<formerdeathcorps> oh, right
<formerdeathcorps> ok...are we cool now?
<Aero> yes
<formerdeathcorps> in the example add r1, r2, r3
<formerdeathcorps> add has opcode of 10 0000
<formerdeathcorps> or 20
<formerdeathcorps> this means
<formerdeathcorps> you have byte 1 as 20
<formerdeathcorps> now...the r1 would be 08
<formerdeathcorps> r2 would be 10
<formerdeathcorps> and so on...
<Aero> already understood that
<formerdeathcorps> so you have 20 0 8
<formerdeathcorps> *20 08
<formerdeathcorps> next is the other two registers
<formerdeathcorps> r2 / r3
<formerdeathcorps> you double the value
<formerdeathcorps> of r2
<formerdeathcorps> so it is 4
<formerdeathcorps> you leave 3 alone
<formerdeathcorps> so you have 3
<formerdeathcorps> On all R-commands
<formerdeathcorps> *i.e. those that use 3 registers
<formerdeathcorps> the last command is always 00
<formerdeathcorps> *byte
<Aero> k
<formerdeathcorps> not really though...
<formerdeathcorps> using the formulas given
<formerdeathcorps> try....
<formerdeathcorps> writing
<formerdeathcorps> add r15, r6, r26
<formerdeathcorps> Still here?
<Aero> yes
<Aero> okay, um...
<Aero> 20 1E 06 00?
<formerdeathcorps> no
<formerdeathcorps> hing
<formerdeathcorps> what is r15?
<Aero> what IS r15?
<Aero> is it a constant
<Aero> *?
<formerdeathcorps> no
<formerdeathcorps> it's a register
<formerdeathcorps> and it fits in byte 2
<Aero> okay
<Aero> you never said what was in it
<Aero> or any of them
<formerdeathcorps> oh right...
<formerdeathcorps> anything with r before it
<formerdeathcorps> designates a register
<Aero> i know
<Aero> oh derp
<Aero> no wait
<Aero> question
<Aero> why'd you double r2 before?
<formerdeathcorps> because it's the register in the second position
<formerdeathcorps> you always doulbe that one and place it in the first hex digit of byte 3
<Aero> is 15 * 2 1E or 2A?
<formerdeathcorps> carrying over what you must
<formerdeathcorps> except that's the first register
<formerdeathcorps> which means you multiply by 8
<Aero> wait
<Aero> i didn't see that part
<Aero> o_O
<Aero> i must have nodded "yes" to the wrong thing
<Aero> oy vay
<Aero> okay, i see it now
<Aero> first register is multiplied by 8
<Aero> 2nd by 4
<Aero> third by 2
<Aero> okay
<formerdeathcorps> no
<formerdeathcorps> 2nd by 2
<formerdeathcorps> 3rd not at all
<Aero> okay
<formerdeathcorps> and anything that requires you to carry over digits, you do so
<formerdeathcorps> into the next digit
<Aero> 20 78 0C 1A
<formerdeathcorps> almost
<formerdeathcorps> the second and third registers share the same byte
<Aero> 20 78 C1 A0?
<formerdeathcorps> no
<formerdeathcorps> you carry over into the second byte
<formerdeathcorps> i.e.
<formerdeathcorps> C0 + 1A
<formerdeathcorps> *second digit
<Aero> i don't get it
<formerdeathcorps> think of the second register as the "tens place"
<formerdeathcorps> and the third register as the "ones"
<Aero> why is it done that way?
<formerdeathcorps> becuase they all occupy distinct binary digits
<formerdeathcorps> register 2 occupies the next 5 after the opcode
<Aero> but why don't they just occup 2 bytes each?
<Aero> *occupy
<formerdeathcorps> but we only have 32 registers
<formerdeathcorps> so we only need 5 bits
<formerdeathcorps> for each register
<formerdeathcorps> saving space in the opcode so we can address more command types
<Aero> but you're left with extra space anyways
<formerdeathcorps> right
<formerdeathcorps> but that lets you make more MIPS commands
<formerdeathcorps> in later MIPS versions
<Aero> oh
<Aero> =/
<Aero> okay
<Aero> wierd way to do it
<Aero> so it's 20 78 C0 1A
<formerdeathcorps> no
<formerdeathcorps> remember I said the second and third registers
<formerdeathcorps> share the third byte
<formerdeathcorps> so you have C0 + 1A = DA
<Aero> hmm
<Aero> oh
<Aero> 20 78 DA 00
<formerdeathcorps> if these seems confusing, imagine stacking groups of 5 bits next to each other
<Aero> that's... awkward to work with
<formerdeathcorps> the opcode is 6 bits
<formerdeathcorps> 10 0000
<Aero> you'd have to look at the binary
<Aero> or at least, I'd have to
<formerdeathcorps> Yeah
<formerdeathcorps> that's why this system is cumbersome
<formerdeathcorps> but notice
<formerdeathcorps> the next two bytes
<Aero> so it's not even a full word, it's just 10 bits
<formerdeathcorps> right
<Aero> =/
<Aero> well, not 10
<formerdeathcorps> 0000 0 | 000 00 | 00 000 UNUSED
<Aero> 24
<Aero> ugh
<formerdeathcorps> I'm not done with complexity
<formerdeathcorps> when you read the HEX
<formerdeathcorps> it's all backwards
<formerdeathcorps> so you actually read 00 DA 78 20
<formerdeathcorps> in the hex editor
<Aero> little endian
<formerdeathcorps> right
<Aero> like the guide says
<formerdeathcorps> but only each command is little endian
<formerdeathcorps> the commands read in forward order
<Aero> right
<formerdeathcorps> ok...just so you know and aren't going to pull a Damned moment on me
<formerdeathcorps> is there any command you don't get?
<formerdeathcorps> that I wrote??
<Aero> such as?
<formerdeathcorps> as in...do you understand all the symbolic three letter commands? I wrote
<formerdeathcorps> what they do?
<Aero> let me see
<formerdeathcorps> as well as the overall types of commands
<formerdeathcorps> I / R / J
<Aero> i - immediate
<Aero> r - register
<Aero> j - jump/
<Aero> *?
<formerdeathcorps> right
<formerdeathcorps> do you understand the difference, opcode wise?
<formerdeathcorps> and function wise?
<Aero> immediate handles constants
<Aero> register handles registers
<Aero> jump moves to a specified point in code
<formerdeathcorps> right
<Aero> yeah, as long as I know the shorthands, i'm good
<Aero> it becomes... something close to traditional programming
*** Chotokukyan has joined #ffhs
<Aero> and I worked with this in my class when i had it
<formerdeathcorps> ok, good
<Aero> i actually have a working maze game
<formerdeathcorps> Choto, we're doing review over opcodes
<Aero> too bad I wouldn't be able to tell you how the hell I pulled that off
<formerdeathcorps> (Link: http://ffhacktics.com/smf/index.php?topic=6728.0)http://ffhacktics.com/smf/index.php?topic=6728.0
<Aero> hold on, i'll grab it and upload it so you can lol at it
<Chotokukyan> ah k
<Aero> I wonder if it's even compatible with your comp
<formerdeathcorps> OK...Aero, if you're good with this
<formerdeathcorps> we're going to talk about...load delay
<Aero> (Link: http://64digits.com/users/AeroGP/asm_maze.rar)http://64digits.com/users/AeroGP/asm_maze.rar
<Aero> k
<formerdeathcorps> Choto, you probably should stay here
<Aero> you won't be able to compile it, but an executable is available
<Aero> and the code is readable
<formerdeathcorps> all right.
<formerdeathcorps> let's finish up
<Aero> k
<formerdeathcorps> Load Delay
<formerdeathcorps> this is important
<formerdeathcorps> and one of my first assignements to all of you
<formerdeathcorps> would be to fix Pokeytax and Xif's work
<formerdeathcorps> namely, here's the problem
<formerdeathcorps> every branch and jump command
<formerdeathcorps> will execute the command after it
<formerdeathcorps> before it jumps
<formerdeathcorps> this is not true in EVERY assembly language
<formerdeathcorps> it's actually particular only to early versions of MIPS
<formerdeathcorps> what this means, though
<formerdeathcorps> is that we can do stuff like
<formerdeathcorps> addu STUFF
<formerdeathcorps> jump
<Aero> that sounds easy enough - you just move the last command down into the branch as if the branch starts after it
<formerdeathcorps> right
<formerdeathcorps> there's only one thing
<formerdeathcorps> there's also what is known as a pipeline hazard
<formerdeathcorps> this occurs first because each MIPS command has 4 stages
<formerdeathcorps> and while the first command runs, the second command starts
<formerdeathcorps> this can lead to paradoxes of time
<formerdeathcorps> this is called a pipeline hazard
<formerdeathcorps> MIPS can catch some of the more obvious ones
<Aero> so commands are semi-threaded?
<formerdeathcorps> but not all of them
<formerdeathcorps> *yes, Aero
<Aero> interesting
<formerdeathcorps> they're threaded 4 deep
<formerdeathcorps> *no more than
<Aero> i can see how that'd result in paradoxes
<formerdeathcorps> to avoid this
<formerdeathcorps> the rules are as thus
<formerdeathcorps> if you load a variable
<formerdeathcorps> *load a value into a register
<formerdeathcorps> you can't use it immediately after
<Aero> because it isn't executed right away
<formerdeathcorps> correct
<Aero> got it
<formerdeathcorps> another thing
<formerdeathcorps> if you use mult or div
<formerdeathcorps> and then mfhi mflo
<formerdeathcorps> you can't use mult or div again for the next two commands after the mfhi / mflo
<formerdeathcorps> or you'll mess up the values of hi and lo
<Aero> because it takes 2 steps to release hi and lo?
<formerdeathcorps> correct
<formerdeathcorps> mult and div take longer
<formerdeathcorps> than other commands
<Aero> right
<formerdeathcorps> also...one more thing...
<formerdeathcorps> you can't store a register's value into a location
<formerdeathcorps> and then load that location right after
<formerdeathcorps> ...it's the inverse of loading
<formerdeathcorps> but it's the same kind of problem
<formerdeathcorps> as you can imagine
<Aero> ic
<formerdeathcorps> this can get tricky if you do stuff like
<formerdeathcorps> addiu r3, r0, 0x00C0
<formerdeathcorps> jal PLACE
<formerdeathcorps> lbu r2, PLACE (r1)
<formerdeathcorps> *PLACE2
<Aero> so in general, ram manipulation takes a step to finalize, so don't do anything funny with addresses right after you've modified them
<formerdeathcorps> Right
<formerdeathcorps> just remember that if you jump
<formerdeathcorps> this is also possible
<Aero> okay
<formerdeathcorps> because you execute that lbu right before the first step
<formerdeathcorps> so you probably shouldn't use r2
<Aero> k

Your homework: grab Xifanie's Ability Requirements Hack (ARH) (http://ffhacktics.com/smf/index.php?topic=7344.0). Transcribe each line and point out any and all pipeline hazards.

Hint: Whatever it says in BATTLE.BIN as an offset, add +0x67000... ~Formerdeathcorps
Title: Re: ASM Lessons
Post by: Glain on March 25, 2012, 02:29:07 pm
Gah. I keep hearing about how Square does things this way or that, when you're dealing with the specifics of how things like multiplication are done in the ASM. Almost every single thing you're attributing to Square is actually being done by their compiler. I'm not saying there aren't legit things to point out about Square's code (hardcoding is a big offender, and some of the stuff you mentioned about rounding errors is relevant), but a lot of this stuff... they probably didn't have anything to do with. As far as I know, for example, they probably did something like:

return (fix)(1/3) * number; // No FPU, using fixed point

and the compiler created something like:

lui r3,0x5555
ori r3,r3,0x5556
mult r3,r4
mfhi r2
jr r31
nop

It's not as if they went "HMMM... 0x55555556 is how to represent 1/3". Same with the percents. The 32 is probably because it's 2^5 and the compiler wanted to do a bit shift.

Also... you memorize opcodes?! That amazes me. Also, they're only 6 bits. Trying to break up an encoded instruction by byte isn't going to work that well. Opcodes are 6 bits, register indexes are 5, shift amount is... 5, I think... jump addresses are 26... it doesn't cleanly divide into eights (bytes). You need to use binary to represent them.

Regarding absorb... very interesting. Are you saying that if you do negative damage, it counts as absorb? The way the elemental  absorb routine (0x1870fc) does it, it checks to see if you absorbed the attack and if you did, it takes the HP damage, moves it to HP healing, sets the HP damage to 0, and sets the ability type to [HP Healing].
Title: Re: ASM Lessons
Post by: formerdeathcorps on March 25, 2012, 04:05:28 pm
Quote
Regarding absorb... very interesting. Are you saying that if you do negative damage, it counts as absorb? The way the elemental  absorb routine (0x1870fc) does it, it checks to see if you absorbed the attack and if you did, it takes the HP damage, moves it to HP healing, sets the HP damage to 0, and sets the ability type to [HP Healing].


No, that's not what's supposed to happen, though I may have accidentally implied that.  All finalized damage in the game is treated as if it was signed, though.  This is why mult is used almost exclusively over multu in the damage calculation steps (and why you have 5555 5556 instead of AAAA AAAB).  Of course, it doesn't quite matter since when you store data from registers, the signs are ignored.  It's also worth noting that all the original loads of PA / MA / SP / X / Y are unsigned and the results are guaranteed within the part of the number line where unsigned = signed (often quite forcefully on the stat up/down routines), so there are no discrepancies with the results.  The fact both are used is probably a holdover of the production process: different teams worked on adjoining pieces of code, but one team used unsigned int, and other used signed int.
Title: Re: ASM Lessons
Post by: Glain on March 26, 2012, 01:09:22 pm
The book I used shows 5 stages for MIPS instructions... basically the ones shown in this link (http://en.wikibooks.org/wiki/Microprocessor_Design/Pipelined_Processors).

Memory loading is where you have to watch out for delay (Load delay):

lbu r4,0x0034(r5)
addi r4,r4,1               # Oops, pipeline hazard - load delay - r4's value isn't loaded yet.

Memory storing may also have the same one command delay, but, well...?

sb r4,0x0034(r5)        # Save the value to memory...
lbu r4,0x0034(r5)       # Now load it from memory, even though it's still in the register, for no reason! \o/

And if you do that, then, well, uh...  :shock:
So there's nothing to worry about with storing values to memory, it's just the loading that you have to watch out for.

We talk about avoiding pipeline hazards here (http://ffhacktics.com/smf/index.php?topic=7346.0).
Title: Re: ASM Lessons
Post by: Pickle Girl Fanboy on April 04, 2012, 07:27:50 pm
FDC's Lesson on MIPS R3000A syntax

16:13    PickleGirlFanboy: hey
16:13    PickleGirlFanboy: i have about an hour
16:13    formerdeathcorps: sure
16:13    PickleGirlFanboy: care to explain some of the syntax of mips r3000a, and answer some questions for me
16:14    formerdeathcorps: ok
16:14    formerdeathcorps: COMMAND rD, rA, rB
16:14    PickleGirlFanboy: reverse polish notation, correct?
16:14    formerdeathcorps: these are known as R type commands
16:14    formerdeathcorps: this means you do the operation A COMMAND B
16:14    formerdeathcorps: and apply the result to D
16:15    PickleGirlFanboy: what about stuff in parenthesis
16:15    formerdeathcorps: it's not post-fix
16:15    formerdeathcorps: next type of commands
16:15    formerdeathcorps: COMMAND rD, OFFSET (rS)
16:15    PickleGirlFanboy: and i'm screencapping this
16:16    formerdeathcorps: in this case, you apply the command at rS + Offset
16:16    formerdeathcorps: and you either write to rD
16:16    formerdeathcorps: or you dump rD's contents to rS + OFFSET in memory
16:16    PickleGirlFanboy: depending on the command?
16:18    PickleGirlFanboy: and that's it? just those two types?
16:18    formerdeathcorps: well...yeah
16:18    formerdeathcorps: because the only commands like this
16:18    formerdeathcorps: are load and store
16:19    PickleGirlFanboy: i mean just those two types of commands to worry about: COMMAND rD rA rB; and COMMAND rD, OFFSET (rS)
16:19    formerdeathcorps: Oh no
16:19    formerdeathcorps: there's more
16:20    PickleGirlFanboy: how many
16:20    formerdeathcorps: there's also COMMAND rD, rS, OFFSET
16:20    formerdeathcorps: here, you apply COMMAND to rS by the amount of the OFFSET
16:20    formerdeathcorps: 3 main types, and a few subtypes
16:20    formerdeathcorps: and you dump the result in rD
16:21    formerdeathcorps: collectively, commands of the form COMMAND rD, rS, OFFSET or COMMAND rD, OFFSET (rS)
16:21    formerdeathcorps: are known as I type commands
16:21    PickleGirlFanboy: i or 1?
16:21    formerdeathcorps: I
16:21    PickleGirlFanboy: gotcha
16:21    formerdeathcorps: I stands for Immediate
16:21    formerdeathcorps: because the OFFSET
16:21    formerdeathcorps: because the IMMEDIATE value
16:21    formerdeathcorps: can be used as a offset
16:21    formerdeathcorps: or a number
16:22    formerdeathcorps: except in logical operations, though
16:22    formerdeathcorps: it is always signed
16:23    formerdeathcorps: then there's the last type
16:23    formerdeathcorps: J commands
16:23    PickleGirlFanboy: and, IMO, I'm a decent writer - I'm not "good" because I haven't sold anything (because I haven't tried yet, homeless), but I can read your writing and critique it
16:23    formerdeathcorps: COMMAND: OFFSET
16:24    formerdeathcorps: or COMMAND: REGISTER
16:24    formerdeathcorps: J stands for jump
16:24    formerdeathcorps: all they do is jump to a place
16:24    formerdeathcorps: thanks, PGF
16:24    formerdeathcorps: in either case, any value in the register is read as an offset
16:25    formerdeathcorps: then there's a few oddballs
16:25    formerdeathcorps: lui rD, VALUE
16:25    formerdeathcorps: gives rD the value of VALUE in the upper 2 bytes and 0000 in the lower 2 bytes
16:25    formerdeathcorps: mflo rD takes the value in the register lo
16:25    formerdeathcorps: and stuffs it into rD
16:25    formerdeathcorps: mfhi is the same, but for the register hi
16:26    formerdeathcorps: obviously, you have the corollary mtlo/hi, which dump stuff into those registers
16:26    formerdeathcorps: ...any questions?
16:26    PickleGirlFanboy: wait a minute I'm copying and pasting
16:27    PickleGirlFanboy: are you sure floating point math isn't used in FFT?
16:27    PickleGirlFanboy: it's used extensively in saga frontier
16:27    PickleGirlFanboy: according to zaraktheus
16:27    formerdeathcorps: MIPS isn't the most space-conservant system for opcodes
16:27    formerdeathcorps: hence, the code will always be somewhat larger
16:27    formerdeathcorps: It is not, PGF
16:27    formerdeathcorps: the PSX machine can't do floating point.
16:28    formerdeathcorps: it's possible to simulate floating point though
16:28    PickleGirlFanboy: he did talk about weirdness
16:28    formerdeathcorps: It's not going to be your standard floating point
16:28    formerdeathcorps: it would have to be an improvised system
16:28    formerdeathcorps: of doing the same thing
16:29    PickleGirlFanboy: improvised - that's the definition of saga froniter
16:30    PickleGirlFanboy: and i actually do know a lot about writing fiction. i've read - almost memorized a few textbooks on the matter, and the only book i now own is eb white & william strunk's elements of style
16:30    formerdeathcorps: Anyways...back to MIPS
16:30    PickleGirlFanboy: i can recommend useful books, i'm saying
16:30    formerdeathcorps: it's one of the more intutive systems out there
16:30    formerdeathcorps: And its opcodes are structured logically
16:30    formerdeathcorps: so they're relatively easy to remember
16:31    formerdeathcorps: and are also structured for relatively simple construction and runtime
16:31    formerdeathcorps: Also, because it's 32 bit
16:31    formerdeathcorps: you have free range for logical comparators
16:31    formerdeathcorps: something 16 bit ASM languages lack
16:32    formerdeathcorps: Are there more space conservant langauges out there? Yes
16:32    formerdeathcorps: but those tend to be hard to upgrade
16:32    formerdeathcorps: because you don't have the space to make more commands
16:32    formerdeathcorps: without overriding functionality of old systems
16:32    PickleGirlFanboy: so mips has room to grow?
16:32    formerdeathcorps: and 32-bit space conservant commands do like 3-4 things at once
16:33    formerdeathcorps: so it's nearly impossible to read
16:33    formerdeathcorps: if you don't believe me
16:33    formerdeathcorps: open up your VBA
16:33    formerdeathcorps: and look at any game boy game in ARM
16:33    formerdeathcorps: ...it's a disaster, trying to read any of that
16:33    formerdeathcorps: yes, MIPS has much more room to grow
16:33    formerdeathcorps: though the commands MIPS added for later versions
16:33    formerdeathcorps: were mostly bug fixes and double (64-bit) and float specific supports
16:35    PickleGirlFanboy: got about 5 minutes left
16:35    formerdeathcorps: Questions?
16:35    PickleGirlFanboy: just anything else u think i need to know as i get into this
16:36    PickleGirlFanboy: would it be useful to memorize which bits correspond to which instructions, registers, and possible values?
16:37    formerdeathcorps: Yes
16:37    formerdeathcorps: or...rather
16:37    formerdeathcorps: you should know how to do it
16:37    formerdeathcorps: in case you are away from your commputer
16:37    formerdeathcorps: or are trying to hack some other game
16:37    formerdeathcorps: ...in another assembly langauge you don't recognize
16:37    formerdeathcorps: now...should you be doing it habitually?
16:37    formerdeathcorps: no
16:37    formerdeathcorps: because massHex
16:37    formerdeathcorps: by Glain
16:37    formerdeathcorps: does it all for you
16:38    PickleGirlFanboy: one of the texbooks i pirated had tables in it, so that should be useful. wait, what? other asm languages use the same bits for similar things?
16:38    PickleGirlFanboy: ...in another assembly langauge you don't recognize
16:38    PickleGirlFanboy: ^Refering to this
16:39    PickleGirlFanboy: and fyi, masshexasm doesn't work for me, unless i feel like downloading the latest java and setting it up - i'm kinda worried it might affect the stability of my computer, so instead i'll try to get the windows version to work with wine.
16:40    formerdeathcorps: No
16:40    formerdeathcorps: every assembly language
16:40    formerdeathcorps: must use opcodes
16:40    formerdeathcorps: of some kind
16:40    formerdeathcorps: just they won't use the same setup as MIPS
16:40    formerdeathcorps: but they'll use opcodes
16:40    formerdeathcorps: either in little or big endian format
16:40    formerdeathcorps: so knowing how to decode these things
16:40    formerdeathcorps: is good
16:41    PickleGirlFanboy: ok, thanks.
16:41    PickleGirlFanboy: i got a ways to go before i start programming in a high level language - like a year, probably, if i don't fail any math classes
16:41    PickleGirlFanboy: but the first two projects i do for myself will be
16:42    PickleGirlFanboy: a hex editor with features i wish i had when i was save state hacking
16:42    PickleGirlFanboy: for linux
16:42    PickleGirlFanboy: and a linux assembler and disassembler, probably for mips, and for snes or gba asm if i ever get around to finishing my projects for those games
16:43    formerdeathcorps: ok
16:43    formerdeathcorps: sounds good
16:43    formerdeathcorps: but I will tell you
16:43    PickleGirlFanboy: unrelated, this is just what i think about when walking around town, waiting for places to open up
16:43    formerdeathcorps: a disassembler
16:43    PickleGirlFanboy: ^all that stuff, i mean
16:43    formerdeathcorps: is not fun to code
16:43    PickleGirlFanboy: excessive tedium?
16:44    PickleGirlFanboy: oh yeah, and a library for input/output in ps1 disc images, too
16:45    formerdeathcorps: What do you mean there?
16:45    PickleGirlFanboy: input/output?
16:45    PickleGirlFanboy: in ps1 disc images?
16:45    PickleGirlFanboy: is that what ur askin gabout?
16:45    formerdeathcorps: oh
16:46    formerdeathcorps: you mean the ability to read it regardless of the file format?
16:46    PickleGirlFanboy: exactly
16:46    formerdeathcorps: and then distinguish between JP/EU/USA
16:46    formerdeathcorps: PAL or whatever else?
16:46    PickleGirlFanboy: to alter game files inside the disc image, instead of the disc image iteslf - and to recognize paths, and update disc image-y things
16:47    PickleGirlFanboy: because patching disc images directly = stupid
16:47    PickleGirlFanboy: what if the disc image is expanded, and your data table is moved?
16:48    PickleGirlFanboy: or a file is shrunk, for that matter, which comes before your data table in the disc image?
16:48    PickleGirlFanboy: also, you can't expand shit in a disc image, you gotta move EVERYTHING around (or so i imagine)
16:48    PickleGirlFanboy: working with the actual files and directories inside the disc image is much smarter, i think
16:50    PickleGirlFanboy: ok, see you later - thanks for the syntax (and, seemingly, semantics) tutorial