• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
March 29, 2024, 01:29:54 am

News:

Use of ePSXe before 2.0 is highly discouraged. Mednafen, RetroArch, and Duckstation are recommended for playing/testing, pSX is recommended for debugging.


ASM Lessons

Started by LastingDawn, December 12, 2008, 08:08:10 am

LastingDawn

December 22, 2008, 02:08:35 am #20 Last Edit: December 31, 1969, 07:00:00 pm by LastingDawn
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
[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
[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.
"Moment's anger can revert to joy,
sadness can be turned to delight.
A nation destroyed cannot be restored,
the dead brought back to life."

Art of War

Beta & Gretchen Forever!!!!

Gamesoul Master

December 27, 2008, 04:04:53 am #21 Last Edit: December 31, 1969, 07:00:00 pm by Gamesoul Master
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.

Vanya

December 27, 2008, 05:26:35 pm #22 Last Edit: December 31, 1969, 07:00:00 pm by Vanya
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! ^_^
  • Modding version: Other/Unknown
¯\(°_0)/¯

Gamesoul Master

December 27, 2008, 05:45:09 pm #23 Last Edit: December 31, 1969, 07:00:00 pm by Gamesoul Master
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]

Vanya

December 27, 2008, 06:49:33 pm #24 Last Edit: December 31, 1969, 07:00:00 pm by Vanya
Indeed! I've seen a lot of WTF code while hacking Mega Man 5. ^_^
  • Modding version: Other/Unknown
¯\(°_0)/¯

The Damned

January 24, 2009, 09:40:26 pm #25 Last Edit: December 31, 1969, 07:00:00 pm by The Damned
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:

  • Signed and unsigned.
  • Consistent definitions of word, byte, and double-word. (Byte is the most "troubling" one for me.
  • Branches.
  • Immediate. (With regards to this hacking, of course. I know what the adjective "immediate" is, but here it keeps getting used as a noun.)
  • Registers.
  • Breakpoint.

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).
"Sorrow cannot be abolished. It is meaningless to try." - FFX's Yunalesca

"Good and evil are relative, but being a dick cannot be allowed." - Oglaf's Thaumaturge in "The Abyss"

"Well, see, the real magic isn't believing in yourself. The real magic is manipulating people by telling them to believe in themselves. The more you believe, the less you check facts."  - Oglaf's Vanka in "Conviction"

nates1984

January 24, 2009, 10:43:31 pm #26 Last Edit: December 31, 1969, 07:00:00 pm by nates1984
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)#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

Choto

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 :)


Glain

If we had a section that was about ASM learning, I'd potentially have quite a bit to contribute to it...
  • Modding version: Other/Unknown


Vanya

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.
  • Modding version: Other/Unknown
¯\(°_0)/¯

Eternal

Don't you guys think Tutorials is clear enough? >_>
  • Modding version: PSX & WotL
"You, no less human than we? Ha! Now there's a beastly thought. You've been less than we from the moment your baseborn father fell upon your mother in whatever gutter saw you sired! You've been chattel since you came into the world drenched in common blood!"
  • Discord username: eternal248#1817

Celdia

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.
  • Modding version: PSX
  • Discord username: Celdia#0

RavenOfRazgriz

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.

Choto

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.

Mysfit

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.
  • Modding version: PSX

Glain

February 09, 2012, 02:24:46 pm #37 Last Edit: February 09, 2012, 02:40:04 pm by Glain
For a list of the more 'standard', most-often-seen commands, take a look at this 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. 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.
  • Modding version: Other/Unknown

Pride

I generally use this list here

Not sure if there's much difference between the two you posted but I thought I'd share.
  • Modding version: PSX
Check out my ASM thread. Who doesn't like hax?

The Damned

March 24, 2012, 03:44:46 am #39 Last Edit: March 24, 2012, 03:55:37 am by The Damned
(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.
"Sorrow cannot be abolished. It is meaningless to try." - FFX's Yunalesca

"Good and evil are relative, but being a dick cannot be allowed." - Oglaf's Thaumaturge in "The Abyss"

"Well, see, the real magic isn't believing in yourself. The real magic is manipulating people by telling them to believe in themselves. The more you believe, the less you check facts."  - Oglaf's Vanka in "Conviction"