Hackers Guide to ESPGaluda II

This document will serve to document ESPGaluda II's internal workings and behavior.

What you will find inside: What you will NOT find inside:

Table of Contents

[TOP]

Overview

If you are here for gameplay tips, a good deal of this page will not be useful for you. I won't be marking what is or isn't gameplay related, so you will have to sift through yourself.

If you are here for hacking into ESPGaluda II, I must warn you: Ikeda is a shitty coder. You will be tearing your hair out at times. I'm sorry.

I will be listing information in the code, regardless of if it is actually used in-game (a good example of this is the bomb count. This is probably left over from whatever codebase ESPGaluda II derives from, since espgal2 uses a bomb gauge instead of actual bombs).

[TOP]

Terminology

Knowing these terms is important, especially if you're hacking the game, since many functions and variables are named with them.

Term Definition
Kinkai Gold.
Muteki Invincibility.
Seirei seki Literally "elemental stone", usually known to western players as gems.
Gage While not technically a term, this misspelling was quite perplexing.
It's just the bomb gauge.
Akasoukou level The charged level for being in Kakusei Over mode. Ranges from 0 to 3.
Bui Literally "region" or "part of". Appears to be parts of the rank system.
Kankin When enemies are killed and turned to kinkai or seirei seki.
Zetsushikai
a.k.a. Zesshikai
Secondary Kakusei mode (active by holding the Kakusei button instead of pressing)

[TOP]

System details

This section will detail many of the core system details.

Game element range

Element Minimum Maximum
Bomb Gauge 0 4000
Lives 0 9
Power 0 6
Akasoukou level 0 3
Kinkai 0 1000
Seirei seki 0 500
Points 0 3999999999

Seirei seki loss on enemy death

Enemy Type = 0 Enemy Type ≠ 0
Stage Boss Stage Boss
Shot Type ≠ 2 Shot Type = 2 Shot Type Irrelevant
Zesshikai Off Stage / 2 + 5 Stage / 2 + 10 Stage + 5 Stage * 2 + 25 Stage * 4 + 25
Zesshikai On 0 (Stage + 3) / 2 (Stage * 2 + 25) / 4 (Stage * 4 + 25) / 2

Stage is the stage number (minus one)

Akasoukou level

Akasoukou level is increased by 1 every 250 frames while in Kakusei Over mode.

Bui counters

The bui counters appear to be used in rank calculation. Bui counters 0 and 1 are added together to for one rank value, and bui counter 2 is used in another value.

What each value affects particularly is currently unknown.

[TOP]

Death effects

Upon the players death, the following happens, in order (though it is effectively instantaneous): [TOP]

Item information

Item Code Name Image Points Description
1up Item1up - 0pts Awards extra life
Bomb ItemBomb - Full gage: 100000pts
Otherwise: 500pts
Awards 2000 gage
Max Power Up ItemMaxPow - Full power: 10000pts
Otherwise: 1000pts
Maxes power level
Power Up ItemPow - Full power: 10000pts
Otherwise: 500pts
Power level +1
Seirei Seki Small Bui_Sk_S - 10pts Seirei seki +1
Bui counter 0 +1
Seirei Seki Medium Bui_Sk_M - 10pts Seirei seki +2
Bui counter 1 +1
Seirei Seki Large Bui_Sk_L - 10pts Seirei seki +3
Bui counter 1 +1
Seirei Seki LargeLarge Bui_Sk_LL - 10pts Seirei seki +4
Bui counter 1 +1
Seirei Seki C 21 (?) Bui_Sk_C_21 - 10pts Seirei seki +2
Bui counter 1 +1
Seirei Seki C 321 (?) Bui_Sk_C_321 - 10pts Seirei seki +3
Bui counter 1 +1
Seirei Seki C 4321 (?) Bui_Sk_C_4321 - 10pts Seirei seki +4
Bui counter 1 +1
Kinkai Lv. 1 Bui_1 - 100pts Kinkai +1
Bui counter 0 +1
Kinkai Lv. 2 Bui_2 - 150pts Kinkai +1
Bui counter 0 +1
Kinkai Lv. 3 Bui_3 - 200pts Kinkai +1
Bui counter 0 +1
Kinkai Lv. 4 Bui_4 - 300pts Kinkai +1
Bui counter 0 +1
Kinkai Lv. 5 Bui_5 - 350pts Kinkai +1
Bui counter 0 +1
Kinkai Lv. 6 Bui_6 - 400pts Kinkai +1
Bui counter 0 +1
Kinkai Lv. 7 Bui_7 - 600pts Kinkai +1
Bui counter 0 +1
Kinkai Lv. 8 Bui_8 - 650pts Kinkai +1
Bui counter 0 +1
Kinkai Lv. 9 Bui_9 - 700pts Kinkai +1
Bui counter 0 +1
Kinkai Lv. 10 Bui_10 - 900pts Kinkai +1
Bui counter 0 +1
Kinkai Lv. 11 Bui_11 - 1000pts Kinkai +1
Bui counter 0 +1

[TOP]

Enemy information

This list is currently incomplete.

Enemy Name Code Name Image Type Priority Points Initializer
 
? Ens01 - 0 0? ? def_init_0
? Ens01_1 - 0 130 ? Ens01_1_Init_Set
? Ens01_2 - 0 130 ? Ens01_2_Init_Set
? Ens01_3 - 0 130 ? Ens01_3_Init_Set
? Ens01_4 - 0 130 ? Ens01_4_Init_Set
? Ens01_5 - 0 130 ? Ens01_5_Init_Set
? Ens01_6 - 0 130 ? Ens01_6_Init_Set
? Ens01_7 - 0 130 ? Ens01_7_Init_Set
? Ens01_8 - 0 130 ? Ens01_8_Init_Set
? Sol_s01 - 0 130 ? Sol_s01Init
? St1Avr - 0 0? ? St1AvrInit
? St1Kiri - 0 0? ? St1KiriInit
? St1Start - 0 0? ? St1StartInit
? St1bg_Umi - 0 100 ? St1bg_UmiInit
Tsubame St1boss - 0 130 100000/500000 St1bossInit
Shimurugu St1mboss - 5 130 ? St1mbossInit
? Tank01a - 0 60 ? Tank01aInit
? Tank01b - 0 60 ? Tank01bInit
 
? En02s - 0 130 230/2260 En02sInit
? St22Kumo - 0 0? ? St22KumoInit
? St2BgBokon - 0 99 ? St2BgBokonInit
? St2BgCover - 0 98 ? St2BgCoverInit
? St2BgElev - 0 96 ? St2BgElevInit
? St2CanB - 0 90 ? St2CanBInit
? St2CanS - 0 90 ? St2CanSInit
? St2Kumo - 0 0? ? St2KumoInit
? St2Nami - 0 0? ? St2NamiInit
Crane St2Yusou - 0 90 ? St2YusouInit
? St2bAppear - 0 80 ? St2bAppearInit
? St2bKirai - 0 133 ? St2bKiraiInit
Yorumungando St2boss - 0 130 ? St2bossInit
? St2mbShibuki - 0 0? ? St2mbShibukiInit
Madara St2mboss - 0 130 ? St2mbossInit
? Tank02c - 0 100 ? Tank02cInit
 
? En03s - 0 60 ? En03sInit
? En3big - 0 130 ? En3bigInit
? En3zk - 0 130 ? En3zkInit
? En3zk2 - 0 0? ? def_init
? En3zk2_1 - 0 130 ? En3zk2_1_Init_Set
? En3zk2_2 - 0 130 ? En3zk2_2_Init_Set
? En3zk2_3 - 0 130 ? En3zk2_3_Init_Set
? En3zk2_4 - 0 130 ? En3zk2_4_Init_Set
? En3zk2_5 - 0 130 ? En3zk2_5_Init_Set
? En3zk2_6 - 0 130 ? En3zk2_6_Init_Set
? En3zk2_7 - 0 130 ? En3zk2_7_Init_Set
? En3zk2_8 - 0 130 ? En3zk2_8_Init_Set
? Gun3a - 0 60 ? Gun3aInit
? Gun3b - 0 60 ? Gun3bInit
? St3Avr - 0 0? ? St3AvrInit
? St3Kumo - 0 0? ? St3KumoInit
Janome St3boss - 0 130 ? St3bossInit
? St3mboss - 0 120 ? St3mbossInit
? Tank34 - 0 100 ? Tank34Init
 
? Bm4Miss - 0 132 ? Bm4MissInit
? En04s - 0 60 ? En04sInit
? En4Big - 0 120 ? En4BigInit
? En4Mid - 0 130 ? En4MidInit
? En4Mini - 0 12 ? En4MiniInit
? St4Kumo - 0 0? ? St4KumoInit
? St4Mizu - 0 0? ? St4MizuInit
? St4Taki - 0 0? ? St4Taki_init
? St4Taki_sf - 0 0? ? St4Taki_sf_init
? St4Taki_sh - 0 0? ? St4Taki_sh_init
? St4Taki_si - 0 0? ? St4Taki_si_init
? St4Taki_sj - 0 0? ? St4Taki_sj_init
? St4Taki_sk - 0 0? ? St4Taki_sk_init
? St4Taki_sl - 0 0? ? St4Taki_sl_init
? St4Taki_sm - 0 0? ? St4Taki_sm_init
? St4Taki_sn - 0 0? ? St4Taki_sn_init
? St4Taki_so - 0 0? ? St4Taki_so_init
? St4Taki_sp - 0 0? ? St4Taki_sp_init
? St4Taki_sq - 0 0? ? St4Taki_sq_init
Madara St4boss - 0 120 ? St4bossInit
Andre Alfus (?) St4mboss - 0 120 ? St4mbossInit
 
? En05s - 0 130 ? En05sInit
Aliman En5Aliman - 0 130 ? En5AlimanInit
? En5Bic - 0 0? ? def_init_1
? En5Bic_6 - 0 130 ? En5Bic_6_Init_Set
Psicrops En5Psicrops - 0 130 ? En5PsicropsInit
Tiamat En5Tiamat - 0 130 ? En5TiamatInit
Fafneal Fafneal - 0 100 ? FafnealInit
? St50bMissile - 0 120 ? St50bMissileInit
Seseri St50boss - 0 130 ? St50bossInit
? St5Kumo - 0 0? ? St5KumoInit
? St5SeseriKumo - 0 0? ? St5SeseriKumoInit
? St5bAppear - 0 90 ? St5bAppearInit
? St5bLevi - 0 0? ? St5bLeviInit
? St5bMissile - 0 120 ? St5bMissileInit
? St5bNmd - 0 0? ? St5bNmdInit
? St5bWeapon - 0 133 ? St5bWeaponInit
Seseri St5boss - 0 130 ? St5bossInit
 
? En06s - 0 130 ? En06sInit
Asagi Clone En6AClone - 0 0? ? def_init_2
? En6AClone_1 - 0 60 ? En6AClone_1_Init
? En6AClone_2 - 0 60 ? En6AClone_2_Init
? En6AClone_3 - 0 60 ? En6AClone_3_Init
? En6AClone_4ku - 0 130 ? En6AClone_4ku_Init
? En6AClone_6 - 0 130 ? En6AClone_6_Init
? En6AClone_6a - 0 130 ? En6AClone_6a_Init
? En6AClone_7 - 0 130 ? En6AClone_7_Init
? En6AClone_7 - 0 130 ? En6AClone_7a_Init
? En6Kb - 0 130 ? En6KbInit
? En6Tank - 0 60 ? En6TankInit
Shimurugu St61mboss - 5 130 ? St61mbossInit
? St62bOptA - 0 130 ? St62bOptAInit
? St62bOptB - 0 130 ? St62bOptBInit
Goddess Galuda St62boss - 0 120 ? St62bossInit
Andre Alfus (?) St62mbAppear - 0 130 ? St62mbAppearInit
? St62mboss - 0 130 ? St62mbossInit
? St6Kumo - 0 0? ? St6KumoInit
True Galuda Kujaku St6boss - 0 120 ? St6bossInit
Unknown stuff...
? Solg - 0 60 ? SolgInit
? S_Can0 - 0 60 ? S_Can0Init
? Up1 - 0 60 ? Up1Init

[TOP]

Scoring details

This section is incomplete.

If in Kakusei over mode, seirei seki count ≠ 0, and you're not fighting the stage boss, points are awarded per frame according to this algorithm:

points = aka_po[akasoukou_level * 6 + stage]
if ( zesshikai )
  points *= 2
score += points

aka_po:
 20,  50,  80, 110, 140, 170,
 50,  80, 110, 140, 170, 200,
 80, 110, 140, 170, 200, 230,
110, 140, 170, 200, 230, 260

When an enemy is killed, EneKankinReq() is always called, which does the math and subsequent calls for converting an enemy to seirei seki or kinkai. The following algorithm explains the calculations:

r4 = arg0
if ( bomb ) // If the player is currently bombing
  return; // No seirei seki nor kinkai
if ( kakusei )
{
  // dec seirei seki
}
else
{
  if ( SeireiSekiCount < 500 )
  {
    if ( sex != 0 )
    {
      if ( SeireiSekiCount == 0 )
      {
        if ( AkasoukouLevel == 0 )
          arg0 *= 1.5;
        if ( AkasoukouLevel == 1 )
        {
          r3 = arg0 * 3;
          if ( r3 < 0 )
            r3 += 3;
          arg0 -= r3 >> 2;
        }
        if ( AkasoukouLevel == 3 )
        {
          if ( r5[3] == 0 )
            arg0 += 1;
          else
            arg0 += 2;
        }
        if ( zesshikai )
        {
          if ( AkasoukouLevel == 0 )
            arg0 *= 1.5;
          if ( AkasoukouLevel == 1 )
            arg0 *= 2;
          if ( AkasoukouLevel == 2 )
            arg0 *= 2.5;
          if ( AkasoukouLevel == 3 )
            arg0 *= 3;
        }
        r5 = 0;
        while ( arg0 > r5 )
        {
          r5++;
          x = (CRandom(0x10) - 8) << 16;
          y = (CRandom(0x10) - 8) << 16;
          BuiReq(kinkai_rate, x, y, 0x8C);
        }
        return 0;
      }
    }
    else
    {
      if ( arg0 != 0 )
      {
        r0 = AkasoukouLevel << ((r5[3] == 0) ? 2 : 1);
        r4 = r0 + 1;
        if ( r10 >= 0x1280000 || r10 <= 0x300000 )
          r4++;
      }
      if ( SeireiSekiCount < 400 )
      {
        r5 = 0;
        while ( arg0 > r5 )
        {
          r5++;
          x = (CRandom(0x10) - 8) << 16;
          y = (CRandom(0x10) - 8) << 16;
          BuiReq(kinkai_rate, x, y, 0x8C);
        }
      }
      else
      {
        r3 = *r8;
        r6 = 0;
        while ( arg0 > r6 )
        {
          r6++;
          x = (CRandom(0x10) - 8) << 16;
          y = (CRandom(0x10) - 8) << 16;
          BuiReq(( r3 & 4 ) ? 0xB : 0x11, x, y, 0x8C);
        }
      }
    }
  }
  else
  {
    if ( arg0 != 0 )
    {
      BuiReq(kinkai_rate, x, y, 0x8C);
    }
  }
}

Ignore these notes please!

FShotHitPost: // Possibly when a bullet hits an object
score += ((Base score + 1) + AkasoukouLevel) * 10

FShot_FirstSet:
basescore = ?
FShotCollision = FShotHitPost (points=power level)

FShot_AI_Req
FShot_FirstSet_0:
basescore = power level
FShotCollision = FShotHitPost
[TOP]

iOS Data Binary Encoding

All of the data binaries (which include such resources as sprites and music) are encrypted with a simple XOR cipher. A program to decrypt the binaries is provided below (downloadable here):

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef uint32_t u32;
typedef uint8_t u8;

void decrypt_bin(u8 *binary, u32 size)
{
  u8 magic[4] = { 0x6C, 0x37, 0x51, 0x73 };
  u32 idx, window;
  for ( window=0, idx=0; idx < size; idx++, window++ )
  {
    window &= 3;
    binary[idx] ^= magic[window];
  }
}

int main(int argc, char *argv[])
{
  if ( argc < 3 )
  {
    fprintf(stderr, "Usage:\n\t%s in.bin out.bin\n", argv[0]);
    return EXIT_FAILURE;
  }

  FILE *fp = fopen(argv[1], "rb");
  if ( fp == NULL )
    return EXIT_FAILURE;
  fseek(fp, 0, SEEK_END);
  u32 size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  u8 *binary = malloc(size);
  if ( binary == NULL )
  {
    fclose(fp);
    return EXIT_FAILURE;
  }
  fread(binary, size, 1, fp);
  fclose(fp);

  decrypt_bin(binary, size);

  fp = fopen(argv[2], "wb");
  if ( fp == NULL )
  {
    free(binary);
    return EXIT_FAILURE;
  }
  fwrite(binary, size, 1, fp);
  fclose(fp);
  free(binary);
  return EXIT_SUCCESS;
}

Data files data0000.bin through data0059.bin and data0235.bin through data0239.bin are PNGs, and data0060.bin through data0234.bin are WAVs.

[TOP]

Changelog

07 Oct 2011

04 Oct 2011

[TOP]

Credits

If I forgot you, I didn't mean to! Please tell me and I'll make sure to update!

Thanks to the following people: austere, potemkin, nimitz, nZero, GaijinPunch, Udderdude, Ilfak Guilfanov, Igor Skochinsky, and Manabu Namiki.

Thanks to the following companies: CAVE, Hex-Rays, W3C.

Thanks to the following IRC channels: #raidenii @ EFnet, #typex @ EFnet, #shmups @ EFnet, #HACKERCHANNEL @ Freenode.
[TOP]