Primary Zelda Hacking
April 21, 2014, 10:50:23 PM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: The website has switched hosts and now has the domain zeldahacking.net!
 
  Home Help Search Login Register  
  Show Posts
Pages: 1 ... 25 26 [27] 28 29 ... 38
391  Oracles Hacking / Tools / Re: ZOSE - Zelda Oracles Script Editor [WIP] on: October 23, 2010, 11:40:35 AM
Making more very good progress. I am in the process of writing a small emulator that just emulates code until the scripting procedure is called, where the script address would have been loaded. It works so far. Here's the emulator's code:

Code:
using System;
using System.Collections.Generic;
using System.Text;

namespace ZOSE
{
public class Emulator
{
GBHL.GBFile gb;
Stack<int> stack = new Stack<int>(); //An int because we push the PC onto here which is GBFile.BufferLocation (integer)
byte a, b, c, d, e, f, h, l;
byte bank;
bool zero, carry;
int final = -1;
byte[] ram; //Note: No bank support!

private ushort hl
{
get { return (ushort)(h * 0x100 + l); }
set { h = (byte)(value >> 8); l = (byte)(value & 0xFF); }
}

private ushort af
{
get { return (ushort)(a * 0x100 + f); }
set { a = (byte)(value >> 8); f = (byte)(value & 0xFF); }
}

private ushort bc
{
get { return (ushort)(b * 0x100 + c); }
set { b = (byte)(value >> 8); c = (byte)(value & 0xFF); }
}

private ushort de
{
get { return (ushort)(d * 0x100 + e); }
set { d = (byte)(value >> 8); e = (byte)(value & 0xFF); }
}

public Emulator(GBHL.GBFile g)
{
gb = g;
}

public int EmulateUntilScript(int id, int x, int y)
{
//Some initialization
this.a = b = c = d = e = f = h = l = 0;
//Because this isn't a REAL emulator, we'll set D to... D0
d = 0xD0;
zero = carry = false;
gb.BufferLocation = 0;
ram = new byte[0x10000];
stack = new Stack<int>();
for (int i = 0; i < 0x4000; i++)
ram[i] = gb.ReadByte();
for (int i = 0; i < 0x10; i++)
{
ram[0xD040 + i * 0x100] = 1; //We'll say we have all 16 interactions active
ram[0xD041 + i * 0x100] = (byte)(id >> 8);
ram[0xD042 + i * 0x100] = (byte)id;
ram[0xD04B + i * 0x100] = (byte)y;
ram[0xD04D + i * 0x100] = (byte)x;
//ram[0xD044 + i * 0x100] = 1; //We'll say we have all 16 interactions active
}
for (int i = 0; i < 0x20; i++)
stack.Push(0); //Emulate things for a bit
ram[0xCD00] = 1;
ram[0xC6D2] = 0x2F;
final = -1;
//Calculate the interaction's assembly address
byte first = (byte)(id >> 8);
byte second = (byte)(id);
byte a = first;
byte bank = 0;
if (a < 0x3E) bank = 08;
else if (a < 0x67) bank = 09;
else if (a < 0x98) bank = 0x0A;
else if (a < 0xDC) bank = 0x0B;
else bank = 0x0C;
int pointer = 0x3B8B + (a * 2);
gb.BufferLocation = pointer;
gb.BufferLocation = bank * 0x4000 + gb.ReadByte() + ((gb.ReadByte() - 0x40) * 0x100);

this.bank = bank;
Emulate(gb.BufferLocation);

if (final == -1)
return -1;

return 0x30000 + (final - 0x4000);
}

public int GetAddress()
{
int pointer = gb.ReadByte() + gb.ReadByte() * 0x100;
if (pointer < 0x4000 || pointer > 0x7FFF)
return pointer;
return bank * 0x4000 + pointer - 0x4000;
}

public int Emulate(int address)
{
int retCount = 0;

gb.BufferLocation = address;
byte blank, before;

while (gb.BufferLocation != 0x2518 && retCount != -1)
{
if (final != -1)
return final;
byte opcode = gb.ReadByte();
switch (opcode)
{

case 00: //NOP
break;

case 01: //LD BC,nn
c = gb.ReadByte();
b = gb.ReadByte();
break;

case 05: //DEC B
before = b;
b = (byte)(b - 1);
if (b > before)
carry = true;
else
carry = false;
if (b == 0)
zero = true;
else
zero = false;
break;

case 06: //LD B,n
b = gb.ReadByte();
break;

case 07: //RLCA
a = RotateLeft(a);
if ((a & 1) != 0)
carry = true;
else
carry = false;
if (a == 0)
zero = true;
else
zero = false;
break;

case 09: //ADD HL,BC
hl = (ushort)(hl + bc);
break;

case 0xA: //LD A,(BC)
a = ram[bc];
break;

case 0x0E: //LD C,n
c = gb.ReadByte();
break;

case 0x12: //LD (DE),A
ram[de] = a;
break;

case 0x18: //JR n
sbyte s = (sbyte)gb.ReadByte();
gb.BufferLocation += s;
break;

case 0x1A: //LD A,(DE)
a = ReadByte(de);
break;

case 0x1C: //INC E
before = e;
e = (byte)(e + 1);
if (e < before)
carry = true;
else
carry = false;
if (l == 0)
zero = true;
else
zero = false;
break;

case 0x1E: //LD E,n
e = gb.ReadByte();
break;

case 0x20: //JR NZ,n
blank = gb.ReadByte();
if (!zero)
{
gb.BufferLocation += blank;
}
break;

case 0x21: //LD HL,nn
l = gb.ReadByte();
h = gb.ReadByte();
break;

case 0x22: //LDI (HL),A
ram[hl++] = a;
break;

case 0x24: //INC H
before = h;
h = (byte)(h + 1);
if (h < before)
carry = true;
else
carry = false;
if (h == 0)
zero = true;
else
zero = false;
break;

case 0x28: //JR Z,n
blank = gb.ReadByte();
if (zero)
{
gb.BufferLocation += blank;
}
break;

case 0x2A: //LDI A,(HL)
a = ReadByte(hl++);
break;

case 0x2C: //INC L
before = l;
l = (byte)(l + 1);
if (l < before)
carry = true;
else
carry = false;
if (l == 0)
zero = true;
else
zero = false;
break;

case 0x2E: //LD L,n
l = gb.ReadByte();
break;

case 0x30: //JR NC,n
blank = gb.ReadByte();
if (!carry)
{
gb.BufferLocation += blank;
}
break;

case 0x35: //DEC (HL)
before = ram[hl];
ram[hl] = (byte)(ram[hl] - 1);
if (ram[hl] > before)
carry = true;
else
carry = false;
if (ram[hl] == 0)
zero = true;
else
zero = false;
break;

case 0x38: //JR C,n
blank = gb.ReadByte();
if (carry)
{
gb.BufferLocation += blank;
}
break;

case 0x3C: //INC A
before = a;
a = (byte)(a + 1);
if (a < before)
carry = true;
else
carry = false;
if (l == 0)
zero = true;
else
zero = false;
break;

case 0x3E: //LD A,n
a = gb.ReadByte();
break;

case 0x44: //LD B,H
b = h;
break;

case 0x47: //LD B,A
b = a;
break;

case 0x4F: //LD C,A
c = a;
break;

case 0x62: //LD H,D
h = d;
break;

case 0x66: //LD H,(HL)
h = ReadByte(hl);
break;

case 0x6F: //LD L,A
l = a;
break;

case 0x70: //LD (HL),B
ram[hl] = b;
break;

case 0x71: //LD (HL),C
ram[hl] = c;
break;

case 0x77: //LD (HL),A
ram[hl] = a;
break;

case 0x78: //LD A,B
a = b;
break;

case 0x79: //LD A,C
a = c;
break;

case 0x7C: //LD A,H
a = h;
break;

case 0x7D: //LD A,L
a = l;
break;

case 0x7E: //LD A,(HL)
a = ReadByte(hl);
break;

case 0x81: //ADD C
before = a;
a = (byte)(a + c);
if (a < before || (a == before && c != 0))
carry = true;
else
carry = false;
if (a == 0)
zero = true;
else
zero = false;
break;

case 0x85: //ADD L
before = a;
a = (byte)(a + l);
if (a < before || (a == before && l != 0))
carry = true;
else
carry = false;
if (a == 0)
zero = true;
else
zero = false;
break;

case 0x87: //ADD A
before = a;
a = (byte)(a + a);
if (a < before || (a == before && before != 0))
carry = true;
else
carry = false;
if (a == 0)
zero = true;
else
zero = false;
break;

case 0x91: //SUB C
before = a;
a = (byte)(a - c);
if (a > before || (a == before && c != 0))
carry = true;
else
carry = false;
if (a == 0)
zero = true;
else
zero = false;
break;

case 0xA6: //AND (HL)
a = (byte)(a & ram[hl]);
if (a == 0)
zero = true;
else
zero = false;
break;

case 0xAF: //XOR A
a = (byte)(a ^ a);
if (a == 0)
zero = true;
else
zero = false;
break;

case 0xB7: //OR A
a = (byte)(a | a);
if (a == 0)
zero = true;
else
zero = true;
break;

case 0xB8: //CP B
if (a == b)
zero = true;
else
zero = false;
break;

case 0xC0: //RET NZ
if (!zero)
{
retCount--;
gb.BufferLocation = PopPC();
break;
}
break;

case 0xC1: //POP BC
bc = (ushort)stack.Pop();
break;

case 0xC2: //JP NZ,nn
int addr = gb.ReadByte() + gb.ReadByte() * 0x100;
if (!zero)
{
gb.BufferLocation = CalculatePC(addr);
}
break;

case 0xC3: //JP nn
gb.BufferLocation = CalculatePC(gb.ReadByte() + gb.ReadByte() * 0x100);
break;

case 0xC5: //PUSH BC
stack.Push(bc);
break;

case 0xC7: //RST 00
PushPC();
Emulate(0);
break;

case 0xC8: //RET Z
if (zero)
{
retCount--;
gb.BufferLocation = PopPC();
break;
}
break;

case 0xC9: //RET
retCount--;
gb.BufferLocation = PopPC();
break;

case 0xCB: //VARYING
switch (gb.ReadByte())
{
case 0x37: //SWAP A
a = (byte)(((a & 0xF) << 4) + (a >> 4));
break;
}
break;

case 0xCD: //Call
address = GetAddress();
PushPC();
if (address == 0x2518)
{
final = hl;
return final;
}
if (address == 0x2544)
{
final = hl;
return final;
}
int i = Emulate(address);
/*if (address == 0x2518)
{
final = hl;
return final;
}
gb.BufferLocation = PopPC();*/
break;

case 0xD1: //POP DE
de = (ushort)stack.Pop();
break;

case 0xD9: //RETI
retCount--;
gb.BufferLocation = PopPC();
break;

case 0xDF: //RST 18
PushPC();
Emulate(0x18);
break;

case 0xE1: //POP HL
hl = (ushort)stack.Pop();
break;

case 0xE5: //PUSH HL
stack.Push(hl);
break;

case 0xE6: //AND A,n
a &= gb.ReadByte();
break;

case 0xE9: //JP HL
gb.BufferLocation = CalculatePC(hl);
break;

case 0xEF: //RST 28
PushPC();
Emulate(0x28);
break;

case 0xF0: //LD A,(FF00+n)
a = ram[0xFF00 + gb.ReadByte()];
break;

case 0xF1: //POP AF
af = (ushort)stack.Pop();
break;

case 0xF6: //OR A,n
a = (byte)(a | gb.ReadByte());
break;

case 0xFA: //LD A,(nn)
a = ReadByte(GetAddress());
break;

case 0xFE: //CP A,n
if (a == gb.ReadByte())
zero = true;
else
zero = false;
break;

default:
opcode = (byte)(opcode - 0);
break;
}
}

if (retCount == -1)
return -1;
return gb.BufferLocation;
}

public byte RotateLeft(byte b)
{
byte carry = (byte)(b >> 7);
return (byte)((b << 1) | carry);
}

public byte ReadByte(int address)
{
if (address < 0x4000 || address > 0x7FFF)
return ram[address];
return gb.Buffer[bank * 0x4000 + address - 0x4000];
}

public int CalculatePC(int address)
{
if (address < 0x4000)
return address;
return bank * 0x4000 + address - 0x4000;
}

public void PushPC()
{
int address = gb.BufferLocation;
if (address < 0x4000)
{
stack.Push(address);
return;
}
address = address % 0x4000;
address += 0x4000;
stack.Push(address);
}

public int PopPC()
{
int address = stack.Pop();
if (address < 0x4000)
return address;
address += bank * 0x4000 - 0x4000;
return address;
}
}
}

Beautiful, isn't it? Because of that, we'll be able view the scripts of countless more interactions and increase the flexibility of Oracles editing by loads.
392  Oracles Hacking / Tools / Re: ZOSE - Zelda Oracles Script Editor [WIP] on: October 23, 2010, 03:39:13 AM
Making great progress:

393  Oracles Hacking / Tools / Re: ZOSE - Zelda Oracles Script Editor [WIP] on: October 23, 2010, 12:01:56 AM
GREAT news! This may lead to being able to edit almost every interaction if my theories and tests are correct! No more being stuck with existing events! It seems that every type 2 (and other) interaction uses the scripting engine, so with a little emulation, ZOSE might be able to decompile/edit the scripts of regular interactions like people and triggers!
394  Oracles Hacking / ZOLE / Re: ZOLE 4 Version 1.11 Released! on: October 22, 2010, 10:45:00 PM
Version 1.11. Update log from ReadMe:

Ability to drag and select tiles in the tileset, edit room (palette) transitions, and edit area properties (flags, the dungeon a tileset has). Also, fixed the ASM event (type 1 interacion) to have the proper name and made it so you can't search map scripts on map 0.
395  Oracles Hacking / Tutorials / Re: Calculating Dungeon-Only Script Addresses (Interaction with ID 20xx) on: October 22, 2010, 08:07:32 PM
Yes, actually the ID does get (maybe temporarily) cached into the RAM. When loading an interaction, what the game does is loops through each Dx40 address incrementing x one time until it hits an address with the value of 00 or E0, in which case it stops. It then sets the value to 01 to indicate there's something there, and loads the first value into Dx41 and the second into Dx42, and uses the values there from then on. The current RAM address's upper byte (Dx) is stored somewhere in FFxx, perhaps FFF8 or something, and taken out whenever needed.

This was all recalled by memory, so something might be a tad wrong. And yeah, I wonder things like that too. The game does a lot of weird things, like jumps to addresses relative to the assembly address depending on a certain value.
396  Oracles Hacking / Tools / Re: ZOSE - Zelda Oracles Script Editor [WIP] on: October 22, 2010, 02:49:51 AM
Big update: Decompiling (and also compiling), by interaction ID or address:

397  Oracles Hacking / Lists / Re: Bank 0C event scripting code(WIP) on: October 22, 2010, 01:20:05 AM
I've been debugging with various opcodes, and 83 catches my attention. It calls procedure 486, which I could've sworn is used for loading palettes, but also seems to be loaded with other things. Basically what it does is reads a 3 bytes pointer to read data from and throws 0x100 bytes of it into 0xC300. I'm not sure why, or what I'll call it. Other than that, 80 sets the interaction is enabled (atleast that's what I have marked for Dx44), 81 sets Dx45, and 82 I believe is not used.

Also, F5 and F6 seem to be the same thing, except something gets added to an address based on the lower nybble in the opcode. Are you sure F6 checks the monster clear flag? It doesn't seem like it, because something gets loaded and that gets written to Dx46.
398  Oracles Hacking / Tutorials / Calculating Dungeon-Only Script Addresses (Interaction with ID 20xx) on: October 22, 2010, 12:19:51 AM
Thanks to Jigglysaint for an example script, I was able to crack down the reading on it and backtrace some stuff, and debug more stuff to create this. Very simple, and I don't see why I didn't see it earlier. Anyway, here is the formula to get the addresses of the scripts for the things like the bracelet. This will be built into the script editor.

PointerLocation = 20C2C + (dungeon * 2)
Calculate the pointer there using bank 8 (20000)
PointerLocation = CalculatedLocation + (index * 2) //index = second ID byte
FinalLocation = (Calculated pointer at PointerLocation) with bank 0C (30000)

~Lin
399  Oracles Hacking / Tools / Re: ZOSE - Zelda Oracles Script Editor [WIP] on: October 21, 2010, 11:06:31 PM
Alright, well this is going to be re-worked a bit. Instead of inserting assembly, it will generate a script using the game's already existing scripting engine. It is currently only dungeon-only, but when have limits actually limited us? It will insert a custom assembly script to make them work outside of dungeons, which is a very simple hack. So keep your hopes up!
400  Oracles Hacking / Progress / Re: ZOLE 1.2 - Transition Editor on: October 21, 2010, 09:06:35 AM
Okay, so the editor is finally done. The game actually uses pointers to the palettes, but I made it so ZOLE loops through each original palette and compares addresses until it finds suitable ones. It actually works great.



I know the from is 16 and technically should be 45, but the game has it loading palette 10 because they're the exact same.
401  Oracles Hacking / Progress / Re: ZOLE 1.2 - Transition Editor on: October 21, 2010, 07:44:33 AM
Actually, I found out there's other data between the transitions I purposely skipped, but it turns out they play an important role on how the palette changes. I gotta add editing for those and then it'll be done.

EDIT: I added the editing ability, and although I labeled the 4 new values as "unknown", I have an idea of what two of them do. For example, if you want the palette change to fade into the palette of the map below you, you add a palette on that map (the one you're going down into), and make sure Unknown1 is 30 and Unknown2 is 90. If you're going up, the values will be 90 and 30. Pretty funky. I have no idea what the other unknowns do.

EDIT2: The unknown values might be pointer sets. The first one is what it will go into and the second is what you're coming from.

EDIT3: Assembly has shown in fact that the unknown values are both pointers.
402  Oracles Hacking / Progress / ZOLE 1.11 - Transition Editor on: October 21, 2010, 06:58:33 AM
Yes, it's been needed for a while, and since I needed it pretty badly in my hack, I decided to take a look at it and found it pretty fast. Note that these room transitions are for palette changes only, not, for example, going into the Maku Tree map. Here's what the editor window looks like.



It's already done. The map shown there is the first graveyard map you encounter. All you have to do is set a map and the direction you enter the map to set the transition and it's all good. The old palette fades into the new one properly.

~Lin
403  Oracles Hacking / Progress / ZOLE 1.x - Operation: Interactions on: October 21, 2010, 04:32:17 AM
Over the past couple days I learned things about the interactions. For example, I learned how to get the address for type 2 interactions, and it also turns out type 1 interactions, the "asm pointer", uses the same exact pointer system. It bugs be that ZOLE is wrong, so I'm going to be looking into them.

~Lin
404  Oracles Hacking / Help / Re: Where can I find a good quality Oracle of Ages Rom? on: October 20, 2010, 09:59:43 PM
www.romhustler.net - Best site ever.
405  Oracles Hacking / Progress / ZOLE 1.11 - A sneak peak of what to expect on: October 20, 2010, 02:46:23 AM
Title says it all. Here's a screenshot showing off a new editing ability. ZOLE 1.11 will have some reprogramming on some part to make the editing process a lot faster than it used to be with selection tools.



~Lin
Pages: 1 ... 25 26 [27] 28 29 ... 38
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2013, Simple Machines Valid XHTML 1.0! Valid CSS!