Log in

Tutorial

Contents

Level 0 - Adding Basic Cards

What is a level 0 card?

A "level 0" card is a card that can be added without writing any code at all!

Generally, these cards have an identical ability of an existing card. For example, 'Nantuko Shade' is a level 0 card because it has an identical ability as 'Frozen Shade', even though its casting cost, creature type, and power are different.

Card type does not even need to be the same, just ability. In this way, 'Magus of the Library, and Disk' are all level 0, since they have the same ability as an existing land and artifact, respectively.

Finally, a small set of basic abilities can be added to other cards without any code changes. Those are basic landwalk, flying, banding, trample, first strike, protection, reach, rampage, and shroud. Therefore you can add Spectral Lynx (regen + pro green), but not Bull Cerodon (haste + vigilence).

Prerequisites

Before you add any card, make sure you have the most up-to-date version of the Magic software. That can generally be found in the stickied post Manalink Update (Newest Date).

Next, download the most recent version of the SkyMagic Editor. That can be found here.

Creating a Card

For this exercise, we will be creating the card Skyknight Legionnaire. (yes, this card does already exist, so we'll actually create it with a new name)

  • Open up SkyMagic Editor. It should look something like this:
  • Use the binoculars icon to search for the card that has the same ability as the card you want to create. Remember that in this case, the ability is "haste", since we get flying for free. Raging Goblin has "haste", so we'll search for that.
    Remember this card's id.
  • This is a new card, so we need to enter a new ID. Scroll all the way to the bottom of the list of cards to see what the highest ID currently is. Set your ID to the next highest number.
  • Fill in 'Name' and 'Full Name' with the name of your card. Call it 'Test Card', so that we don't interfere with the real Skyknight Legionnaire.
  • 'CODED CARD' indicates the card is done, and ready to show up in the deck editor. Leave this as '1' unless you do not plan on finishing your card now.
  • The next few fields, 'Expansion', 'Color', and 'Card Type' all have dropdowns of values to choose from. Select the appropriate values. For Expansion, choose whichever one feels like a best fit.
  • Leave 'DB Card Type 2' alone, and fill in the the rarity for the card. Choices show at the bottom of the editor.
  • The 'Req ...' fields set up the casting cost for the card. Our card costs 1WR, so Req Colorless, Red, and White should all be 1. If this cost 2RW, then Req Colorless would be 2 instead, etc.
  • Set 'Num Pics' to 1, since we only plan on adding 1 picture for this card.
  • The next several fields give hints to the computer about how to use the card. Assuming we selected a card similar to the one we are building, these values can be left alone.
  • 'AI Power/Toughness' should be set to a creature's power and toughness.
  • Go all the way down to 'Exp Rarity'. If you want your card to show up in multiple sets for Sealed play, enter the appropriate sets here. Otherwise enter '0h'.
  • Enter the 'Power' and 'Toughness' again for your creature.
  • Skip down to the 'Subtype' and 'Subtype 2' fields. Use the dropdowns to enter your creature's tyes. Only 2 types are allowed, and if your creature is lenegdary, you must select that as one of your types. To blank a type out, chose '211'.
  • Fill in your card's 'Type Text', 'Rules Text', and 'Flavor Text'. You can find the exact wording for these by looking them up on Gatherer.
  • If your card has mana symbols in them, you need to use special syntax. 8 colorless mana is represented by |8, blue mana by |U, tap by |T, etc.
    Add blank lines by adding \n.
    If a basic land type appears in the text, precede it with |H1.
    If a color word appears in the text, precede it with |S.
  • If necessary, update the rest of the text fields as necessary.
  • Click 'Save Record'. You should be prompted 'Append Test Card'? Choose yes to save.
  • Click the 'Save' icon in the upper left to save your changes to disk. Congratulations, you're half way there.
  • Click on the 'Magic.exe' tab. Use the binoculars icon to search for the original card (Raging Goblin) by id.
  • Doubleclick on Raging Goblin to update the right pane.
  • Replace the name and ID with the information for your card.
  • Update the 'Card Type', 'Card SubType', and 'Card Color' as appropriate. Remember that this card is white AND red.
  • The card CC slots help the computer know when a card is available to cast. Generally, put the total colorless cost into 'Card CC 1', and the total colored cost into 'Card CC 2'. So we'd enter 1, and 2.
  • Enter your card's power and toughness yet again.
  • 'Code Pointer' tells the program where to find the code for your card's ability. Since we did not write any code, leave this alone.
  • Use the dropdowns for the 'Static Abilities' to add on any of the "free" abilities to your creature. If you have done this correctly, you will see '20' (for flying) in static abilities 1.
  • Leave 'Reserved information alone.
  • Now for the odd part. Search for the card with the ID one less than your card's ID. Scroll down one more spot on the left and you should see 'Dummy'. Singleclick 'Dummy'.
  • Click 'Save Record'. You should be prompted 'Overwrite Dummy'? Choose yes to save. After you do, your card's information should still be in the right pane.
  • Click the 'Save' icon in the upper left to save your changes to disk.
  • You are done with SkyMagic Editor. You can close it now if you want.
  • In your Magic directory, run csv2dat.exe. A blank screen should flicker. As long as there was no error text on it, it worked.
  • The last thing we need is an image for the card. You can get this from many sources, including Gatherer.
    You can crop the image using MS Paint or another program.
    Save the image in Magic/CardArtNew/ID.jpg, where ID the your card's ID.
  • Your card is created! Test it by running the magic program. To make testing easier, you can turn on debug mode in duels. Just fit F12, and then right-click for a whole bunch of great options.
  • The last thing you'll want to do is share your card with the world. To do this, zip up the following files: Magic.exe, Manalink.csv, Cards.dat, and the image you created. Voila, you are a productive member of the slightymagic community.

Level 1 - Very Easy Mods

What is a level 1 card?

A "level 1" card is a card that can be added without really understanding anything about coding, other than a couple basics explained here.

To create level 1 cards, we will take existing cards and make very tiny tweaks. It is not always obvious when a card can be made with only level 1 tweaks. It really depends on how the original card was coded.

Prerequisites

  • Be a master at creating Level 0 cards.
  • Download the Olly debugger.
  • Download the ExtraCopy Plugin for Olly.

Creating a Card

For this exercise, we will be creating the card Tidings. (yes, this card does already exist, so we'll actually create it with a new name)

  • Follow all the steps you learned from the Level 0 Tutorial to create a card identical to Counsel of the Soratami, but with all the information for Tidings.
    Your new card should be called Test Card, but behave exactly like Counsel.
  • In SkyMagic Editor, go to the Magic.exe tab and search for your card. Find the 'Code Pointer' section and click the '...'.
    You are now in the (somewhat) scary View Assembler tab.
  • Hilight all the code for the card you are copying. The code will always start at the top of the screen with the command

55     push    ebp

It will end with

C3     ret    
In this case, the code takes up almost exactly one screen.

  • With the code hilighted, click the leftmost icon, export patch. Save the patch as Counsel.skp.
  • Next we need to find an empty space to put our new code. The easiest way of doing this is search for the last card created, and click its code pointer.

Scroll down to the end of that proc, and it should be followed by a bunch of

2020    and     [eax], ah 
  • The first one of those is where we can put our code, so remember the address for that line. In the image below, the address we want is 004E0B7.
  • Go back to your card in the Magic.exe tab and update you card's Code Pointer with this new value.
  • Click 'Save Record'. You should be prompted 'Overwrite Test Card'? Choose yes to save.
  • Click the 'Save' icon in the upper left to save your changes to disk.
  • Click the '...' in the 'Code Pointer' section.
  • Click the first line, and then click the 2nd icon, 'Import Patch'.
  • Import Counsel.skp
  • Click File -> Magic -> Save.
  • Now is a good time to test your card in Magic.exe. Is should still only draw 2 cards.

Finally, it is time to update our card. We can do this either in Olly or in SkyMagic Editor. I'll explain both ways, starting with Olly.

Editing using Olly

  • Start Olly and open Magic.exe. Ignore the warnings.
  • Control-G to search by address. Find your card by the address you put in the 'Code Pointer' section of SkyMagic editor.
  • Even if you don't know anything about the code, you know that Counsel had the word '2' in it. So scour the code for an isolated 2.

If you look carefully, you'll see this line:

6A02   push    2
  • Double click that line, and change push 2 to push 4 (for 4 cards).
  • You can test your changes by starting Debug Mode. Just press F9.
  • Test out your card and voila! Tidings now draws you 4 cards.
    You'll notice that if you use F12 to open debug mode in magic.exe, the screen will flip back to Olly. Just hit F9 again, and switch back to magic. Debug mode will be on.
  • To save your changes, hilight and sections of code you have changed. Right-click and choose Copy to Executable -> Selection.
  • Close the new window, and choose 'Yes', and then save. You are done!
    Note: You can only save your file as Magic.exe once. To save again, you'll need to either close and re-open Olly, or rename your file.

Editing using SkyMagic Editor

This is recommended for only the most trivial changes.

  • Go back to viewing your code in the 'View Assembly' tab.
  • Even if you don't know anything about the code, you know that Counsel had the word '2' in it. So scour the code for an isolated 2.

If you look carefully, you'll see this line:

6A02   push    0x00000002
  • This editor will only let you update the ugly hex code (6A02), not the actual instruction. In this case, we can guess how to change the hex code.
    Double click on that line and change 6A02 to 6A04.
    The code should now be updated to
6A04   push    0x00000004
  • Click File -> Magic -> Save.
  • Test your changes by running the Magic.exe game. It works, you are done.

One more note about editing in SkyMagic. Open up the 'View Assembly' tab and click the funnel icon (Disasm). Type in 4DEB70 to jump to that line. You should see:

68A4050000           push                0x000005A4

Notice that the argument to push is 000005A4, but in the HEX code the numbers are jumbled. The first 2 digits are the instruction (in this case, push). After that, the number gets re-ordered, so 12345678 becomes 78563412. In this example, 000005A4 becomes A4050000.


Level 2 - Glue Togethers

What is a level 2 card?

A "level 2" card is a card that is created by combining two cards into one. These are only slightly more complicated than level 1 cards, but still only require little or no programming knowledge.

The quick and dirty methods of creating level 2 cards are fairly straightforward. The resulting code isn't necessarily pretty or short, but it's easy and effective.

Prerequisites

  • Be familiar with creating Level 1 cards.

Creating a Creature Card

For this exercise, we will be creating the card Rorix Bladewing. (yes, this card does already exist, so we'll actually create it with a new name) If you're wondering what 2 abilities Rorix has, the first is Haste, and the second is the Legend Rule. Remember, flying comes for free.

  • Use the steps learned in the Level 1 Tutorial to create a new version of Bull Cerodon.
    We will use this as the template for glue together creatures.
  • You'll notice that there are 2 lines in a row that have the operation 'call'.
  • The numbers in parenthesis after the 'call' are the code pointers for 2 abilities of Bull Cerodon.
    We want to replace these numbers with the code pointers for the abilities on Rorix.
    So we just have to think of the simplest possible creatures with haste and the legend rule.
    Raging Goblin and Isamaru come to mind.
  • Locate and write down the code pointers for each of those cards.
    (They should be 0040B5A0 and 00403090)
  • Use Olly to change the call arguments to the code pointers for haste and legend rule. (If you are observant, you'll notice that haste was already one of the abilities).
  • Save, test, and you're done!

Keep in mind that you cannot easily glue 2 activated abilities together, since they clobber each other. If you glue an activated ability together with a different ability, put the activated ability last.

Creating a Spell

For this exercise, we will be creating the card Kiss of the Amesha. (yes, this card does already exist, so we'll actually create it with a new name) Kiss = Sacred Nectar (mostly) + Counsel of the Soratami.

  • Use the steps learned in the Level 1 Tutorial to create a new version of sacred Nectar that gains 7 life instead of 4.
  • Export the code for Counsel of Soratami to a patch (you may have already done this in the Level 1 Tutorial).
  • in SkyMagic Editor, go into your new code that gains 7 life and click on the last line (ret).
  • Click the import patch button to import Counsel's patch.
    Note: You can do these last few steps in Olly as well using the ExtraCopy plugin.
  • Save, test, and you're done.

Level 3 - Small Updates

What is a level 3 card?

A "level 3" card is a card that is requires more than copy/paste or slight hacks to put together. They require understanding the basics of how cards are coded, but not necessarily advanced knowledge. If applied correctly, small changes can have a huge impact (turning Transmute Artifact to Tinker is a 2-letter change... finding those 2 letters it the tricky part). Like always, though, some cards are hit or miss. For example, turning Lhurgoyf into Terravore would be a massive effort.

Prerequisites

  • Be a master at creating Level 1 and 2 cards.
  • Basic programming knowledge is recommended.
  • Patience

Creating a Card

For this exercise, we will be creating the card Symbiotic Wurm. (yes, this card does already exist, so we'll actually create it with a new name) Level 3 and 4 cards are not straightforward like the previous cards, so this tutorial instead captures my own thought process as I tried to create this card, including failures. Be warned that this card does involve several failures, too. Try not to get discouraged. Even though it may seem like a lot now, once you have some experience, all these steps will come naturally. For example, this card only look me about 15 minutes to make, despite all the steps.

  • Before you even begin to create a card, it's time to learn some assembler basics.
    I strongly recommend reading through the 'Reference' section to become familiar with the terms you will shortly see.
  • The first trick is to think of some cards that do similar things to the card you want to make. There is no card (when I made Wurm) that creatures creatures when it dies. Bummer. However, there are cards that make creatures when they come into play. So I started with Cloudgoat Ranger.
  • Once you know what card you might want to clone, use SkyMagic Editor to export its code as a patch, and also copy the code to a text editor. This will make it easier to read.
  • To make changes to the code, first we're going to have to be able to try to interpret the current code, or at least parts of it. Re-read the top section of Operation Codes, and then try to read through the annotations for Archivist.
    The first time I read the annotation I only understood a little, but the more experience you get making cards, the more will make sense.
  • Now you should understand that the code for each card is broken down into separate sections, based on the operation code. Go into your text editor and put a blank line above each section. The image below shows the result, and I have labeled the sections 1, 2, and 3.
SECTION 1
004DF9EA 55                   push                ebp
004DF9EB 8BEC                 mov                 ebp, esp
004DF9ED 53                   push                ebx
004DF9EE 56                   push                esi
004DF9EF 57                   push                edi
004DF9F0 813D782D7A00DB000000 cmp                 0x007A2D78, 0x000000DB
004DF9FA 755E                 jnz                 +0x0000005E (0x004DFA5A)
004DF9FC A18C397A00           mov                 eax, 0x007A398C
004DFA01 39450C               cmp                 [ebp+0x0C], eax
004DFA04 7554                 jnz                 +0x00000054 (0x004DFA5A)
004DFA06 3B05209A7300         cmp                 eax, 0x00739A20
004DFA0C 754C                 jnz                 +0x0000004C (0x004DFA5A)
004DFA0E A1848C7300           mov                 eax, 0x00738C84
004DFA13 3B057CC16200         cmp                 eax, 0x0062C17C
004DFA19 753F                 jnz                 +0x0000003F (0x004DFA5A)
004DFA1B 394508               cmp                 [ebp+0x08], eax
004DFA1E 753A                 jnz                 +0x0000003A (0x004DFA5A)
004DFA20 39051C7E7300         cmp                 0x00737E1C, eax
004DFA26 7532                 jnz                 +0x00000032 (0x004DFA5A)

SECTION 2
004DFA28 807D107D             cmp                 [ebp+0x10], 0x0000007D
004DFA2C 7509                 jnz                 +0x00000009 (0x004DFA37)
004DFA2E 830DB405620002       or                  0x006205B4, 0x00000002
004DFA35 EB23                 jmp                 +0x00000023 (0x004DFA5A)

SECTION 3
004DFA37 807D107E             cmp                 [ebp+0x10], 0x0000007E
004DFA3B 751D                 jnz                 +0x0000001D (0x004DFA5A)
004DFA3D 68B9050000           push                0x000005B9
004DFA42 90                   nop                 
004DFA43 90                   nop                 
004DFA44 90                   nop                 
004DFA45 FF7508               push                [ebp+0x08]
004DFA48 E80FEFFFFF           call                -0x000010F1 (0x004DE95C)
004DFA4D E80AEFFFFF           call                -0x000010F6 (0x004DE95C)
004DFA52 E805EFFFFF           call                -0x000010FB (0x004DE95C)
004DFA57 83C404               add                 esp, 0x00000004
004DFA5A 33C0                 xor                 eax, eax
004DFA5C 8D65F4               lea                 esp, [ebp-0x0C]
004DFA5F 5F                   pop                 edi
004DFA60 5E                   pop                 esi
004DFA61 5B                   pop                 ebx
004DFA62 5D                   pop                 ebp
004DFA63 C3                   ret                 
  • Notice that section1 doesn't have any operation code. This code will get executed no matter what operation is called. So let's skip that.
  • Section 2 has the operation code '7D' and section 3 has '7E'. If you look these up on the operation code chart, you'll see that they both represent 'comes into play abilities', so that doesn't narrow it down much.
  • The next step is to scan the code for pieces that we recognize. For example, the code at address 004DFA48 is
call                -0x000010F1 (0x004DE95C)

or, ignoring the unimportant part, Looking back at the Useful Procs section, you'll see that 4DE95C is the proc for creating token creatures. We have found what we are looking for! (Of course, you might have guessed this was the correct part since the same things is called 3 times in a row, and Cloudgoat Ranger makes 3 tokens).

  • Looking once more at the ..., we see that there is a code for 'going to graveyard', 77. Maybe we just change the '7E' to '77' and the card will create 3 tokens when it dies.
  • Now that we have a handle on the changes we might make, we can finally the steps learned in the Level 1 Tutorial to create a new version of Cloudgoat Ranger.
  • Use Olly to make the change, and test your card.
  • Well, when it comes into play, it no longer makes tokens. But when it dies, nothing happens. Darn.
  • Remember that field on the Magic.exe tab called 'Reserved Information'?
    Sometimes that has imformation in it about which operations a card gets called for.
    So maybe our card works, but the operation is never getting called. So let's steal the 'Reserved Information' from a card that has a goes to graveyard ability, like Aven Fisher. Make the changes, save, and test.
  • Still no luck. What's wrong? Truly, I don't know. I tried changing the '7D' operation code to '77' also, and other various permutations. I had no luck with this approach.
  • If this was my first Level 3 card, I might have given up here. Lucky you, there is a tutorial to keep you going!

Attempt 2

We tried to make Symbiotic Wurm based on a token producer, and failed. Let's try from the opposite direction, a leaves play creature, and see if we have any success.

  • Pick a simple 'goes to graveyard' creature. I chose Aven Fisher.
  • Repeat the steps above of copying the code and analyzing it the best you can.
  • I looked for the place where the 'draw a card' procedure is. According to the Useful Procs page, that proc is 433190. When Isearch for that, though, I don't fine anything. Not wanting to dig too deeply into unfamiliar code, I instead switch to another goes to graveyard creature.
  • Next I tried Onulet, and ran into the same problem. The 'gain life' procedure was nowhere to be found. This simple card is turning out to be not so simple.
  • Next on the list is Su-Chi. This card once again fails the test, since there I don't see the 'add mana' proc anythere. However, I proceed anyway, since Su-Chi has 2 nice benefits. First, it is short. The less code, the better. Second, I see a beautiful push 0x00000004 line. This must be where the mana ability is.
  • When modifying cards, I try to change as little as possible. In this case, I only want to change the call that generates mana with one that generates creatures. The other code may not be necessary in my final version, but as long as it is not doing any harm, I don't mind.
  • Change the 'make mana' code with the 'creature creature' code from Cloud Ranger. I.e.: change
6A04                 push                0x00000004
6A00                 push                0x00000000
FF7508               push                [ebp+0x08]
E820CF0400           call                +0x0004CF20 (0x0049D490)
83C40C               add                 esp, 0x0000000C

to

68B9050000           push                0x000005B9      
FF7508               push                [ebp+0x08]
E80FEFFFFF           call                -0x000010F1 (0x004DE95C)
83C404               add                 esp, 0x00000008

Notice how the code for calling a procedure starts with a push, then the call, and then an add. The 'add' resets the pointer. The number added should be 4 times the number of things pushed.

  • When we pasted the new code, we accidentally spilled into the code that came later. In Assembly, there is no cocept for 'insert', just 'overwrite'. So if what we are adding is bigger than what we are replacing, this overflow will happen. To correct this, we need to re-add anything that came after our addition.
  • You can retype it in this case, since there are only a few lines, but it would probably be easier to copy the code from the original Su-Chi back to here.
00450573 33C0                 xor                 eax, eax
00450575 5E                   pop                 esi
00450576 C9                   leave               
00450577 C3                   ret                 
  • As if that wasn't annoying enough, any previous jumps that referenced the lines we clobbered will need to be fixed. For example, we see several lines in the original Su-Chi that look similar to this:
00450562 740F                 jz                  +0x0000000F (0x00450573)

0x00450573 used to be the xor eax, eax line (you have this copied into your text editor, right?). So all the jumps that used to go to 0x00450573 should now point to where the xor line currently is. You'll have to change this in 5!! places.

  • IF you got this all right, your card should work. When it dies, it will create a single Kithkin token. If this doesn't work, compare your work to the actual code for Symbiotic Wurm to see what went wrong.
  • Our card is almost done, but we have 2 more changes to make. First, we want to make Insects, not Kithkin, and second, we want 7 of them!
  • Let's address the easy one first, making Insects. First, you need to create a totally new card in SkyMagic Editor called Insect. Make sure you set its type and set to 'token'.
  • You rememberd to run csv2dat, right?
  • To change Kithkin to Insects in the code, we just have to change one of the args to the token making proc. Figure out what the card id of your new token is IN HEX (the windows calculator tool does the conversion for you). Use Olly to make the change.
  • Finally, to make 7 guys instead of 1, just copy the token-making code 7 times. As seen in Cloudgoat Ranger, you really only need to replicate the 'call' command, not the 'push' and 'add'.
  • Re-add the code you clobbered, and update those jumps again.
  • You're done. It was hard, but you did it!

Level 4 - Everything Else

What is a level 4 card?

A "level 4" card is a every card that you might want to make that doesn't fit a previous level. These cards are only limited by the game engine and your genius.

Prerequisites

  • Be a master at creating Level 1 and 2 cards.
  • A solid understanding of how Magic Cads are coded is required.
  • Even more patience
  • Creativity!

Creating a Card

For this exercise, we will be creating the card Diabolic Edict. (yes, this card does already exist, so we'll actually create it with a new name) Level 4 cards can sometimes be half technical, half art. Again, this tutorial instead captures my own thought process as I tried to create this card, including failures.

  • The first trick is to think of some cards that do similar things to the card you want to make. This is where creativity kicks in. Cards like Atog allow you to sacrifice cards as an activated ability. Are there any cards where sacrifices are mandatory, though? (preferably creature sacrifice)
    Two cards come to mind: Lord of the Pit and Balance.
  • Use SkyMagic Editor to export the code for both as patches, and also copy the code to a text editor.
  • The code for both of these cards is fairly large, so we need to isolate just the part of the code that prompts for a sacrifice. Hopefully by now you are familiar enough with the Useful Procs to recognize 4779F0 when you see it. Sacrificing a creature requires putting it in the graveyard, so that proc should be near what we're looking for.
  • In both Balance and Lord of the Pit, we see that there is a call to 4CB3D0 preceding the call to 4779F0. This might be the 'sacrifice' code we are looking for. Let's export that entire chunk of code from Lord of the Pit, starting with the Op Code check for '04' down to the next Op Code check for '86'. You should have exported this code:
004C9ED9 837D1004             cmp                 [ebp+0x10], 0x00000004
004C9EDD 0F8590000000         jnz                 +0x00000090 (0x004C9F73)
004C9EE3 8B4D0C               mov                 ecx, [ebp+0x0C]
004C9EE6 390D8C397A00         cmp                 0x007A398C, ecx
004C9EEC 0F8581000000         jnz                 +0x00000081 (0x004C9F73)
004C9EF2 8B4508               mov                 eax, [ebp+0x08]
004C9EF5 3905848C7300         cmp                 0x00738C84, eax
004C9EFB 7576                 jnz                 +0x00000076 (0x004C9F73)
004C9EFD E87E7BF3FF           call                -0x000C8482 (0x00401A80)
004C9F02 FF4638               inc                 [esi+0x38]
004C9F05 8B450C               mov                 eax, [ebp+0x0C]
004C9F08 50                   push                eax
004C9F09 8B4508               mov                 eax, [ebp+0x08]
004C9F0C 50                   push                eax
004C9F0D E87E010000           call                +0x0000017E (0x004CA090)
004C9F12 83C408               add                 esp, 0x00000008
004C9F15 85C0                 test                eax, eax
004C9F17 744E                 jz                  +0x0000004E (0x004C9F67)
004C9F19 814E0800001000       or                  [esi+0x08], 0x00100000
004C9F20 C705D058710000000000 mov                 0x007158D0, 0x00000000
004C9F2A E83183FAFF           call                -0x00057CCF (0x00472260)
004C9F2F 686CEA4E00           push                0x004EEA6C
004C9F34 6A00                 push                0x00000000
004C9F36 E8F17FF3FF           call                -0x000C800F (0x00401F2C)
004C9F3B 83C408               add                 esp, 0x00000008
004C9F3E FF7508               push                [ebp+0x08]
004C9F41 E88A140000           call                +0x0000148A (0x004CB3D0)
004C9F46 83C404               add                 esp, 0x00000004
004C9F49 8945FC               mov                 [ebp-0x04], eax
004C9F4C 816608FFFFEFFF       and                 [esi+0x08], 0xFFEFFFFF
004C9F53 6A03                 push                0x00000003
004C9F55 8B45FC               mov                 eax, [ebp-0x04]
004C9F58 50                   push                eax
004C9F59 8B4508               mov                 eax, [ebp+0x08]
004C9F5C 50                   push                eax
004C9F5D E88EDAFAFF           call                -0x00052572 (0x004779F0)
004C9F62 83C40C               add                 esp, 0x0000000C
004C9F65 EB07                 jmp                 +0x00000007 (0x004C9F6E)
004C9F67 830DB405620001       or                  0x006205B4, 0x00000001
004C9F6E E909010000           jmp                 +0x00000109 (0x004CA07C)
  • At this point, it is not important to know what each and every one of those lines does, only what the ability as a whole does.
  • The next big step is to take this code and build a card around it. Why bother building a whole new card, though, when we can steal from other cards? What is the simplest card that has the same targets and can be cast with the same restrictions as Diabolic Edict? Well, Edict targets players and can be cast any time. So we might want to steal that code from Ancestral Recall. For now, let's not even worry about the targeting piece. So let's steal the code from Counsel of the Soratami, one of the game's most basic cards.
  • Go ahead and create a new card that is just a copy of Counsel. Next, go into Olly and remove as much code as possible so that the card can still be cast, but no longer has the 'draw cards' ability.

We start with:

004D9DD0 55                   push                ebp
004D9DD1 8BEC                 mov                 ebp, esp
004D9DD3 56                   push                esi
004D9DD4 807D1074             cmp                 [ebp+0x10], 0x00000074
004D9DD8 7507                 jnz                 +0x00000007 (0x004D9DE1)
004D9DDA B801000000           mov                 eax, 0x00000001
004D9DDF EB25                 jmp                 +0x00000025 (0x004D9E06)
004D9DE1 807D1071             cmp                 [ebp+0x10], 0x00000071
004D9DE5 751D                 jnz                 +0x0000001D (0x004D9E04)
004D9DE7 6A02                 push                0x00000002
004D9DE9 FF7508               push                [ebp+0x08]
004D9DEC E89F23F4FF           call                -0x000BDC61 (0x0041C190)
004D9DF1 83C408               add                 esp, 0x00000008
004D9DF4 6A01                 push                0x00000001
004D9DF6 FF750C               push                [ebp+0x0C]
004D9DF9 FF7508               push                [ebp+0x08]
004D9DFC E8EFDBF9FF           call                -0x00062411 (0x004779F0)
004D9E01 83C40C               add                 esp, 0x0000000C
004D9E04 33C0                 xor                 eax, eax
004D9E06 5E                   pop                 esi
004D9E07 C9                   leave               
004D9E08 C3                   ret                 

What can we remove? Not much. You should be able to analyze all the code for this basic card. Doing so reveals that you can only remove the 'draw 2 cards' code, which is 004D9DE7-004D9DF1.

  • Test this card, and make sure it does what you expect (nothing but go to the graveyard when you cast it). Testing steps like this may seem silly, but I have wasted many hours trying to find bugs that came down to not creating a blank card correctly.
  • We removed 4 lines of code, but we're going to want to add a lot more than 4 lines in. Since there is no 'insert' ability in Olly, we'll have to do this the hard way.
    ExtraCopy all the code from 004D9DF4-004D9E08, and then fill that space with NOPs. Then fill in the next 200 or so lines with NOPs. Better to give ourselves more space and not need it than to run out later. Then paste the code you copied at the end. You're going to have to update the JMPs on line 004D9DDF and 004D9DDF to point to the new location of that line. Sometimes this requires changing a short jump to a long jump, which requires even more rearranging. This is not a big deal for such a small card, but when modifying larger cards, it can be a real hassle, and other workarounds are preferred.
    Once you have added a bunch of NOPs and updated the jump, test your card again.

    The easy way, in theory, is to add a JMP in the blank lines. Jump to the section of code after your proc ends, and then put your new code there. At the end of your new code, jump back up to where you left off. This makes large updates very easy, with the only downside of making the code a little less readable. If you can get this to work, fantastic! Do that instead. I've had some weird results, though.
  • Time for the fun part. Import your Lord of the Pit section of code into your giant block of NOPs. Make sure to leave some space at the top, just in case we need to insert our own code later.
    Update the JMPs, if necessary.
    You'll notice that there is some redundant code checking the Op Code. We want Edict to happen when the spell resolves, not during upkeep, so keep the '74' check from Counsel and remove the '04' check from Lord.
  • Test your code. It works! Or at least, it should do something other than crash. Ideally, if you control a creature, it will ask you to sacrifice one. Otherwise it won't do anything. This is a great start.
  • We want the Edict to hit our opponent, not us. Let's try updating the card to change any references to the current player to target the computer instead.
    A few things to remember here are
    • [ebp+0x08] represents the person casting the spell, and
    • 0 is the constant for you, and 1 for your opponent.
    So change all the references in the Lord code from [ebp+0x08] to 1.
    Test, and it should be working. Now the Edict hits your opponent instead of you! Unfortunately, since we hard-coded '1', the Edict will hit your opponent even when they cast it. Oops. Let's update the code to hit the opponent of the caster instead of a hard-coded player.
  • If [ebp+0x08] is the current player, then who is the opponent? To calculate this, use one of my favorite functions, y=1-x. This turns 0 to 1 and 1 to 0.
    Or, in assembly speak,
mov eax, 1
sub eax, [ebp+0x08]

This puts the value for the opponent into eax. EAX is already used by the Lord code, so let's use ECX instead in our code.

  • Add the opponent calculating code prior to the Lord code, and then change all those references to '1' back to ECX.
  • Test, and the card works beautifully, no matter who casts it.
  • What about that weird Lord vestige that puts a circle with a slash through it on Edict? We don't want that to show. So remove the line of code that adds that. Which line is it? Well, assuming you can't analyze the entire code, trial and error is your best friend here. Try removing lines that look suspect.
    All of these lines look suspicious, if you ask me:
004C9F19 814E0800001000       or                  [esi+0x08], 0x00100000
004C9F20 C705D058710000000000 mov                 0x007158D0, 0x00000000
004C9F2A E83183FAFF           call                -0x00057CCF (0x00472260)
004C9F2F 686CEA4E00           push                0x004EEA6C

It turns out that the first line is the culprit, so remove that.

  • And there you have it, a non-targeting version of Diabolic Edict.
    If there are a lot of NOPs, I would recommend condensing the code, since there is currently a limited amout of space to add new cards.

Adding Targeting

Now that we have the hard part of the card coded, it's not that hard to add targeting.

  • Inspect some other cards that target a player. The example mentioned earlier was Ancestral Recall.
  • Remember how we took out the extra junk from Counsel of Soratami to make a blank card? Do the same thing with Ancestral Recall. You should create a bank card that targets a player and then does nothing.
  • Add in your Edict code and make sure that the card works, even though it will still only edict your opponent.
  • Next, find the section of code in Ancestral Recall that actually draws a player cards.
004A2D0F 6A03                 push                0x00000003
004A2D11 FF7674               push                [esi+0x74]
004A2D14 E87794F7FF           call                -0x00086B89 (0x0041C190)
004A2D19 83C408               add                 esp, 0x00000008
  • Notice that instead of the normal push [ebp+0x08], there is push [esi+0x74]. This is the code that says apply this effect to the chosen player.
  • We simply need to change our opponent calculating code with the esi code. I.e., replace:
mov ecx, 1
sub ecx, [ebp+0x08]

with

mov ecx, [esi+0x74]
  • That's all! Congratulations, you just created a difficult card.