fruitfly

a technical blog

Blender 2.6: Exporting UV Texture Coordinates

with 2 comments

There is nothing I admire more then a software development team that is not shy of reorganizing an API to the better even though it means stepping on some peoples feet. Well, I guess the Blender team stepped on my foot; because one of my export scripts was no longer working once I upgraded to Blender 2.6. Actually, I should have known; because it is more the rule then the exception that the Python API changes from release to release…

This time it took me some hours to find how to get to the UV texture coordinates of a mesh. After browsing through the API via the python console for some time I took the easy way out and peaked into the .OBJ model exporter coming with blender. So, here is how you get to the UV textures of a triangle for your mesh:

m = bpy.context.active_object.to_mesh(bpy.context.scene, True, 'PREVIEW')
uv1 = m.tessface_uv_textures.active.data[0].uv1
uv2 = m.tessface_uv_textures.active.data[0].uv2
uv3 = m.tessface_uv_textures.active.data[0].uv3

The part of the data path that has changed (at least I was able to get to the UV coordindates differently in the past) is the tessface_uv_textures property.

Note that i am accessing index [0] here. The array indices correspond to the indices of the faces-array. So, this example is for face zero. Also note that the uv1 to uvx depend on how many vertices the face has. Often you would first triangulate the mesh to have only primitive polygons.

I hope t helps someone because also google mostly shows up with results for accessing the UV coordinates that are deprecated for some time by now and thus are no longer working.

Written by 38leinad

May 29, 2012 at 8:51 pm

Posted in blender

Tagged with

Gameboy Development on Mac OS X

with 2 comments

309

1

357294As I have gone more and more low-level over the past month, I was searching for a platform that is well understood/documented, not too fancy and thus allows me to use it for learning on different topics at once in a fun way. I.e. micro-processors/electrical-engineering, emulators, dev-tools.

Well, I found the old Gameboy to match that category:

  • Electrical Engineering: Building own game cartridges/ROMs, ROM-readers/writers and play around with other interfacing possibilities. As it happens, I still have my old Gameboy lying around… somewhere…
  • Emulators: Write a simple emulator for the Gameboy’s Z80 processor. Compared to others, the instruction of the Z80 is “quiet” small. Except for the CHIP-8 language, there are not many other processor that are this popular and have an as small instruction set.
  • Dev-Tools: Understanding how compiler and linker for this platform work and tinkering with it. As one of the most popular tool-chains (Rednex Gameboy Development System358295) is open-source and a comparably small project, this is hopefully not a month-long endeavor.

And I like doing game-development for fun anyway. With a quiet old and restricted platform like the Gameboy, this is a nice thing to do in with limited time and good results. Building only a simple game for PC or any of the latest Mobile-platforms (iOS, Android) can take month when you also have some sense for art and style. With a four-color 160×144 pixel display, you are so restricted on itself, that doing the graphics yourself is quiet easy; even for someone that is not a great artist. I was surprised what can be achieved on a 14 hour flight. Maybe I will even enter the next Ludum Dare359296 with a Gameboy game.

The first step required to dive into the world of Gameboy development is to set up the development tools, emulator and some more useful tools like tile-editors on your Mac. The main purpose of this post is to describe the steps I have taken. And as it was more then just click-click-finish at some stages, I hope this will also be helpful to others.

Development Kit

RGBDS360297 seems to be a popular set of developer tools for the original Gameboy. It contains four command-line tool for which two are the assembler and the linker. Unfortunately, there is no binary available for Mac OS. Fortunately, it is open source. With minor modifications I was able to compile the tools for Mac OS X Lion. You can find the compiled binaries (rgbds.tar361298) and the Makefile I used in my github repository362299.

Emulators

Next thing I needed for development was an emulator with an embeded deugger. Who writes a working game with closed eyes, loads it onto a gameboy cartidge and it works? Well, at least not me.

The emulators I found to be the best matches are no$gmb363300 and bgb364301. Both are similar feature wise; bgb seems to have been implemented based on no$gmb, so both interfaces look alike and also shortcuts in the debugger are mostly the same. bgb is still actively developed and you can also get tips by the developer in the EFNet #gbdev IRC channel.

Both emulators are for windows originally and they are not open source. So, using Wine was the only real option. If you don’t have Wine yet installed, you might want to download MacPorts365302. It is a package manager for Mac OS and also allows to easily install said software. As you also need to have the X11 window server installed for Wine to work properly, best is to follow these instructions366303 for the whole installation.

The Installation of wine itself is straightforward: After the installing MacPorts type “sudo port” in the Terminal.app to start the MacPorts package manager. Supply your user’s password and the prompt of the package manager should appear. Type “install wine” and do something else for the next half hour. This will download all dependencies (a lot) and install Wine on your system. I got an error like

:info:build Assembler messages:
:info:build Fatal error: invalid listing option `r'
:info:build winebuild: /opt/local/bin/gas -arch i386 failed with status 256

while installing Wine because it seemed to interfere with other packages I have already had installed. If you also encounter this problem, follow the workaround at the bottom of this bug-ticket367304:

sudo port clean wine
sudo port -f deactivate binutils
sudo port install wine
sudo port activate binutils

Once you have installed wine successfully, you can start the emulator. I was not able to get bgb running yet but no$gmb works just fine. Get the 32-bit Windows version from here368305 and start it with “wine NO$GMB.EXE” from the commandline.

Tools

As said before, a quiet restricted platform like the Gameboy allows also a developer without a hand for art to create nice games. Still, you might want some tools to assist in the process. The Gameboy Tile Designer369306 and the Gameboy Map Builder370307 are two such tools. Easily generate tiles and maps and directly export them into an assembler-file containing the required data to directly work with the tiles/maps. These tools are again windows-only but work just fine with wine.

Unfortunately, as of this writing, the host for these tools seems to be shutting down its operation completely, so I hope the owner of these tools will find another host soon.

Getting Started

That’s about what you need if you want to get into Gameboy development and have some retro-fun. To point you in the right direction for getting started I can recommend the notes of the Wichita State University’s 2008 Z80 Assembler Programming lecture371308. Luckily, the exact same tools we just installed on our system are used 🙂

Written by 38leinad

March 3, 2012 at 1:57 pm

Posted in gameboy, macos

Practical Blender with GLKit – Part 2 – Blender Scripting with Python

with 12 comments

Welcome to the second part of this practical series on Blender for the use with GLKit-based iOS-applications. The first part focused on setting up a basic GLKit Xcode-project as the prerequisite for the following parts. As it is a quiet new API, I think it was worth it. I also tried to give some links and tipps for learning the basics of Blender modeling.

Within this part, we will directly jump into the Python API of Blender. So, for this part I assumed you already have tinkered with Blender, done some basic modeling and find your way around the UI.  I will also assume you have some basic knowledge of the Python scripting language. If not, I recommend googling for “python in 10 minutes” . We will only be using the most basic features of the language.

In contrast to my initial plans, this is a rather lengthy post as we have to introduce some basics, will go the full way to already write a very simple export-functionality from Blender  and also write corresponding import-functionality for our iOS application, respectively. My feeling while writing was that it wraps things up much more nicely if we actually have some kind of result in our iOS application to show of at the end of this part.

Introduction

Depending on how close a look at Blender you had already, you might actually know that it comes with its own python runtime in the application bundle. The whole application is written in python (correct me if I am wrong) including all operation and actions that you can trigger via the user-interface. If you have a look into the application-bundle, you will find the subfolder /Applications/blender.app/Contents/MacOS/2.59/scripts/ containing lots of python script-files. “addons” contains a lot of export scripts for different kind of model formats. This is a very rich stash of code snippets you should be able to understand after this post.

When it comes to writing and executing your own Python scripts and tinker with the API you basically have three different options:

  1. Start Blender with a Python script for execution.
  2. Write a python script within the integrated Text Editor of Blender and execute it with the push of a button.
  3. Use the interactive Python command-line to write and execute a script line-by-line.
Up until now I have never used approach 1 because I am still in the learning phase. This makes sense for a bulk operation on many blender-model files though, I assume. Approach 2 we will use later (You can still use an external editor to write the script) to execute a whole script of operations on our Blender model. Approach 3 is really the one that makes exploring the API very easy. You can step-by-step explore operations, see the changes to your model and copy the lines into a full script-file if the result was as expected.

Python Console

Lets have a close look at approach 3 and explore data-structures and operations via the powerful Python Console. Open up this Blender model of the apple-logo. If you still have the default interface-layout, select the button in the lower-left corner of the window that should show the animation time-line. Change it to the Python Console like in the following picture.

Change one of the subviews to the interactive “Python Console”

This is the interactive Python Console/REPL; just like the regular Python Console. Read the blue output: Pressing Up/Down to go back and forth in the command-history is not a so special feature, but Auto-completion is really the killer-feature to quickly discover the API. Have a try and type:
>>> bpy.
and hit Ctrl-Space. You should see a list of possible sub-modules you can expand the command with. Type
>>> bpy.context.
and hit Ctrl-Space again. You see a list of all methods and properties you can call on the context. Make it
>>> bpy.context.scene.objects
bpy.data.scenes["Scene"].objects 
and press Enter. This prints the list-object containing all objects in the scene. Unfortunately, it is no native list so it does not actually list its contents. Go one back in the command history to display the command again and enclose it in a list-call: 
>>> list(bpy.context.scene.objects)
[bpy.data.objects["Point"], bpy.data.objects["Apple"], bpy.data.objects["Camera"]]
If you execute this, you should see a list of the objects in the scene. For me, the scene consists of three objects named “Point”, “Apple” and “Camera”. The first is a light-source, the second our apple-logo model and the last is the camera object in the scene.
But what if you don’t know this ahead and need to find out in one of your scripts what type an object is (for a simple model exporter that we will write later, we are only interest in exporting the actual model)? Well, we can try to ask for the type. Let’s do it the Python-way:
>>> for o in bpy.context.scene.objects: type(o) 
... <Press Enter>
<class 'bpy_types.Object'>
<class 'bpy_types.Object'>
<class 'bpy_types.Object'>

Ok, so obviously, many objects are represented by the type bpy_types.Object in Blender. But there is also a property “type” on bpy_type.Object (which you can find easily with the auto-completion feature). Lets try it:

>>> for o in bpy.context.scene.objects: o.type
... 
'LAMP'
'MESH'
'CAMERA'

So, if we are interest in the camera, we can simply check for the type-property of the object. Actually, we do not bother so much for the camera (and the light), but we want to work with the apple-logo which is of type “MESH”; basically representing a set of polygons. Assign it to a variable by executing this:

>>> apple = bpy.data.objects["Apple"]

We will use this variable soon when we are going to explore what we can do with our model. But first, let’s get some general introduction to the different modules of the API.

Common Modules

“bpy” is the main module of the python API. It contains most other blender-related sub-modules to access and interact with almost everything you can also do with a press of a button or other interface element in the UI. The most important modules are:

The context – bpy.context

This basically gives you access to the current state of the blender UI and is necessary to understand as we will use our scripts like Macros you might know from other application. If we switch a mode, we will actually see a change in the Blender UI; this is represented in the context.

  • bpy.context.mode: What is the current mode of Blender? When you work with your models and are a beginner like me, you are mostly either in Object- or Edit-mode. So, if you access this property, you should get “OBJECT” or “EDIT” as return-value.
  • bpy.context.active_object: What object is currently active? To be truthful, I haven’t found much use for this property yet, as I mostly only have one object selected at any time; in that case, the active-object is also the selected object. Which you can query with the next property.
  • bpy.context.selected_objects: Which objects are currently selected? Select/deselect the apple-logo or the camera and see as the property changes.
  • bpy.context.scene: We already played with this before. It gives you access to all parts of the scene. So, whatever you see in the Outliner-view, you can access it from here.

The Outliner-view

The data – bpy.data

This submodule gives you access to all data that is part of the currently opened Blender-file (.blend). This might be a super-set of what is available through the context as you might create objects programmatically that do not show up in the scene. If you try it for now, you should actually get the same list of objects as in the scene:

>>> list(bpy.data.objects)
[bpy.data.objects["Apple"], bpy.data.objects["Camera"], bpy.data.objects["Point"]]

When we start to make copies of objects to work on, this list will temporarily contain more objects.

The operations – bpy.ops

If you have been playing around yourself with the above introduced property “bpy.context.mode” you might have noticed that it is not possible to set it. It is read-only and changing it requires to call a corresponding operation from the “bpy.ops” module. In specific, the operations are grouped within submodules again. To operate on an object (bpy_types.Object), check for “bpy.ops.object”, for operations on a mesh check “bpy.ops.mesh”. We will later see how easy it is to find the Python API call for a button/element in the Blender UI. But, let’s play around with some basic operations first: 

>>> bpy.ops.object.mode_set(mode='EDIT')
{'FINISHED'}
>>> bpy.ops.object.mode_set(mode='OBJECT')
{'FINISHED'}

If you were in Object-mode before executing these commands, you should have seen that the Blender UI switched to Edit-mode and with the second command back to Object-mode. This is an important command, because you only can perform certain operations in Edit-mode, just like you are only able to do certain things in the UI when you are in a specific mode. It also depends on the object currently selected what modes are available. Select the camera-object via the UI (right mouse-click) and see that the call which worked before now fails:

>>> bpy.ops.object.mode_set(mode='EDIT')
Traceback (most recent call last):
 File "<blender_console>", line 1, in <module>
 File "/Applications/blender.app/Contents/MacOS/2.59/scripts/modules/bpy/ops.py", line 179, in __call__
 ret = op_call(self.idname_py(), None, kw)
TypeError: Converting py args to operator properties: enum "EDIT" not found in ('OBJECT')

Scripting Workflow

We will see that whole experience of Python scripting in Blender is very beginner-friendly; and if you follow a specific workflow you can very easily develop rather complex scripts in no time.

I will show you this workflow based on a simple example. We now want to do one very common operation that we usually will need to export a model for  use with OpenGL ES: Triangulation (OpenGL ES only allows us to draw triangles and not quads like in standard OpenGL). It is a concret example but might also help you in the future for a lot other problems:

  1. Do your steps manually: Find out what you want to do with the help of the UI. I.e. Select the apple-logo model, switch into Edit-mode, select all vertices (Select -> Deselect/Select All) and triangulate via Mesh -> Faces -> Quads to Tris. This should triangulate our model (Actually, most part of the apple is already triangulated; only the outer rim is quads). If that worked, undo the steps. If you know you can do it in the UI, you for sure can do it also easily via the Python API.

    Select all vertices with Select -> Select/Deselect All

    Triangulate via Mesh -> Faces -> Quads to Tris

  2. Do it step-by-step in the Python-console: The manual steps worked fine, so let’s try it step by step in the Python console again. Some steps we have actually already done before:
    >>> apple.select = True
    >>> bpy.ops.object.mode_set(mode='EDIT')
    {'FINISHED'}
    But now: How to select all vertices and how to call the "Quads to Tris" operation? Well, when you did the steps manually, you might have seen something in Blender that is quiet neat. While hovering over an operation in the menu, you see the Python API call that lies behind it (see the last two screenshots). For "Select/Deselect All", bpy.ops.mesh.select_all is shown.
    >>> bpy.ops.mesh.select_all( <Press Ctrl-Space>
     select_all()
    bpy.ops.mesh.select_all(action='TOGGLE')

    You see, that I first pressed Ctrl-Space after the function-name so I see the doc-string and thus know which parameters are required for the function. I noticed that it says “action=’TOGGLE'” in the example. That sounds a little error-prone, because it might actually deselect everything if we have already some vertices selected before this operation (for whatever reason). Let’s maybe look this one up in the API reference to make sure we do not deselect but select all: Go to Help -> API Reference in the Info-view. A browser should open up with the documentation. Click on Operators (bpy.types) and further click on Mesh Operators on the next page. We see that ‘SELECT’ is the action that we want.

    >>> bpy.ops.mesh.select_all(action='SELECT')
    {'FINISHED'}

    For our last step, the actual triangulation, we can also see from the menu (see screenshot above) that the Python-call is bpy.ops.mesh.quads_to_tris:

    >>> bpy.ops.mesh.quads_convert_to_tris()
    {'FINISHED'}
    We did it. And it was not so hard because of this unbelieavably neat feature of giving us hints on the Python API directly within the UI. This works for many different things. E.g. if you are in Object-mode and hover over one of the XYZ-sliders in the Transform/Location-section it shows "Object.location". So, we directly know to which property of the Object-type it maps to: For our model, it is apple.location (actually there is something more to it to actually apply the transform to our underlying mesh, but we will see this in the next part of the series).

    Hovering over interface elements will give you a hint on the underlying Python API call

    I just cannot stop pointing out how neat this feature is 🙂

    Now, we just have to package it up into one Python script which we can execute as a whole; which is the next step.

  3. Create a script of the individual steps/commands from step 2. Basically, you can paste the individual commands from step 2 into a text-file line-by-line to get a very static script. Enrich it with some variable/if-then-else-cases and you are done.

You should have gotten the general idea of the three-step approach. Step 3 was only theory, though. We will now see how it can be done in practice with the Python Text Editor.

Python Text Editor

Take all the steps we have executed on the Python-console and put them in a file “my_simple_exporter.py” with your favorite text-editor for python and save the file (we do the actual export-stuff later). The script should look something like this:

1
2
3
4
5
apple = bpy.data.objects["Apple"]
apple.select = True
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.quads_convert_to_tris()

Lets open it up in Blender. For one of the views (I took the one from the Python Console) change it to “Text Editor” like this:

Switching to the Blender “Text Editor” view

Go to “Text -> Open Text Block” to open our script-file. Note that Blender only has a reference to that external file so that you can still do all your editing with your favorite text-editor. Blender will notice any changes (a small safety-ring is shown) and allow you to reload the file like this:

Blender will pick up on changes to the script and allow an easy reload

Let’s try to run the script via the “Run Script” button. You will see that Blender complains and nothing really happens. Our script failed. But why? Bad thing is that we cannot really see what Blender complained about. The Console.app should normally come to the rescue, but due to some bug/different behavior on MacOS the output is only written to the log-daemon after Blender is closed. At least that is how it is for me and I have read other people had the same problem. The way I worked around this is by opening up Blender always via the Terminal. The Terminal then directly will print our error.

Save the Blender file and close Blender. Open Blender again via the Terminal. For me, Blender is opened with this path:

/Applications/blender.app/Contents/MacOS/blender

Go into the Blender Text Editor, select my_simple_exporter.py and press “Run Script”. The following output should show up within the terminal:

Traceback (most recent call last): 
 File "/Users/daniel/Desktop/Blender/Session2/apple_for_logo.blend/my_simple_exporter.py", line 1, in <module> 
NameError: name 'bpy' is not defined

Well, if you are an advanced python developer, you might have seen this coming right from the beginning: We have forgotten to import the required modules. The Python console already imports this for us by default; if we create our own script-file, we have to do it ourselves. Add the following line to the beginning of you script-file:

import bpy

Try again. This time it should have worked fine.

The Mesh – Vertices, Faces, Normals

You might remember when we called apple.type, that Blender was telling us our model is of type “MESH”, but still all objects (model, camera and light) where of the Python-type “bpy_types.Object”. For sure all these thing should have different properties: A light should have properties like luminance, a camera has a direction it is facing to and a mesh should have vertices, edges, faces, normals, etc.

Blender hides this specifics behind the data-property. With it, you get access to all these type-specifics. Have a try and check the types of the data-property for camera, light and model:

>>> for k in bpy.context.scene.objects.keys(): print('%s has a data-property of type %s' % (k, type(bpy.context.scene.objects[k].data)))
... <Press Enter>
Point has a data-property of type <class 'bpy.types.PointLamp'>
Apple has a data-property of type <class 'bpy_types.Mesh'>
Camera has a data-property of type <class 'bpy.types.Camera'>

As we want to exporting our model, we are most-interested in the type “bpy_types.Mesh”. You can use the trick with auto-completion to see a full list, or check on the Python API reference we used before. The properties we are most interest in for now are “vertices” and “faces”.

  • Mesh.vertices gives us a list of vertices (bpy.types.MeshVertex) in the model. A MeshVertex has as property “co” that gives us access to its coordinate and a property “normal” for the normal.
  • Mesh.faces gives us a list of faces (bpy_types.MeshFace). Each face again has a property “vertices” that gives us a list of the indices into the Mesh.vertices-list. These indices define the face. After triangulating our model, we should only have three elements in each of the face’s vertices-lists.

Let’s try to list all faces with their vertex-coordindates:

>>> for (i,f) in enumerate(apple.data.faces): <Press Enter>
... for vertex_index in f.vertices: print('Face %d has has vertex %s' % (i, apple.data.vertices[vertex_index].co)) <Press Enter>
... <Press Enter>
Face 0 has has vertex Vector((-0.27777254581451416, 0.23545005917549133, 5.628979206085205))
Face 0 has has vertex Vector((-0.2777732014656067, -0.17912480235099792, 4.809228897094727))
Face 0 has has vertex Vector((-0.27777382731437683, 0.802850067615509, 4.097628593444824))
Face 1 has has vertex Vector((-0.2777732014656067, -0.17912480235099792, 4.809228897094727))
Face 1 has has vertex Vector((-0.27777382731437683, -0.233199805021286, 3.773179292678833))
Face 1 has has vertex Vector((-0.27777382731437683, 0.802850067615509, 4.097628593444824))
<and a lot more...>

Note that I have inserted a tab in the second line (firstline that starts with “…”) for this to work.

UPDATE: With Blender 2.6, the property “faces” has been renamed to “polygons”.

The first Export Script

With basic Python file-IO knowledge, we now have all the information we need to write a very basic model-exporter. Open up my_first_exporter.py within the Python Text Editor or your external Text-Editor and modify it so it looks as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import bpy
import os

# Change if file should be written some place else
file = open(os.path.expanduser("~/Desktop/mymodel.mdl"), "w")

model_object = None
model_mesh = None

# Search for the first object of type MESH
for obj in bpy.context.scene.objects:
    if obj.type == 'MESH':
        model_object = obj
        model_mesh = obj.data

# Triangulate
model_object.select = True
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.quads_convert_to_tris()

for face in model_mesh.faces:
    for vertex_index in face.vertices:
        vertex = model_mesh.vertices[vertex_index]
        # Write each vertex in a seperate line with x,y,z seperated by a tab
        file.write(str(vertex.co[0]))
        file.write('\t')
        file.write(str(vertex.co[1]))
        file.write('\t')
        file.write(str(vertex.co[2]))
        file.write('\n')
There are basically three blocks of code:
  1. We find the first object in our Blender file that is of type “MESH”. This is a little bit more generic then the code we had before where we just used the model with name “Apple”.
  2. We triangulate our mesh; this should look familiar.
  3. We traverse all faces and vertex-indices to write each vertex of a face in a new line of the output file (x,y,z are separated by tabs). As we have triangulated our mesh, we know that always three lines in our exported model-file define one face.
Execute this file within the Python Text Editor and check that a file called “mymodel.mdl” has been created on our Desktop.

Loading the Model

So, what’s left is to actually import our model into our iOS Application and render it. As the model-format is quiet straight-forward and we assume basic OpenGL ES knowledge, I will only briefly describe the steps and let the code speak for itself.

Open up the Xcode project “GLKitAndBlender” from Part 1 and create a new Objective-C class “MyModel”.

1
2
3
4
5
6
7
8
9
#import <Foundation/Foundation.h>

@interface MyModel : NSObject

- (id)initWithFilename:(NSString *)filepath;
- (BOOL)load;
- (void)render;

@end

The interface consists of an initializer that takes the path to the model to load (mymodel.mdl), a load-method to actually read the file and a render-method to do the OpenGL-calls for rendering the model to the screen:

Here is the implementation of the class:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#import "MyModel.h"

#import <GLKit/GLKit.h>

@interface MyModel () {
@private
    NSUInteger _num_vertices;
    GLfloat *_vertices;

    NSString *_filepath;
}
@end

@implementation MyModel

- (id)initWithFilename:(NSString *)filepath
{
    self = [super init];
    if (self) {
        _filepath = filepath;
    }

    return self;
}

- (BOOL)load
{
    NSString *file_content = [NSString stringWithContentsOfFile:_filepath encoding:NSUTF8StringEncoding error:nil];
    NSArray *coordinates = [file_content componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\n\t"]];
    _num_vertices = [coordinates count] / 3;
    _vertices = malloc(sizeof(GLfloat) * 3 * _num_vertices);

    NSLog(@"Number of vertices to load: %d", _num_vertices);

    int i=0;
    for (NSString *coordinate in coordinates) {
        _vertices[i++] = atof([coordinate cStringUsingEncoding:NSUTF8StringEncoding]);
    }

    NSLog(@"Model loaded");

    return YES;
}

- (void)render
{
    static const float color[] = {
        0.8f, 0.8f, 0.8f, 1.0f
    };

    glVertexAttrib4fv(GLKVertexAttribColor, color);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, _vertices);

    glDrawArrays(GL_TRIANGLES, 0, _num_vertices);

    glDisableVertexAttribArray(GLKVertexAttribPosition);
}

- (void)dealloc
{
    free(_vertices);
}

@end
The load-method  reads each coordinate seperatly and converts it from an NSString to a GLfloat and stuffs it into the GLfloat-array under the name _vertices. The render-method then draws our model in the same way it already did for the swinging square from Part 1. We only disabled the color-attribute as we draw everything with the same grayish color.
What’s left is to actually use the MyModel-class. For this, first import the “mymodel.mdl” file into the Xcode project. Once you have done this add an instance variable “model” to the GLKitAndBlenderViewController-class header. The changes to the GLKitAndBlenderViewController-class implementation-file contain comments and can be seen below:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#import "GLKitAndBlenderViewController.h"

#import "MyModel.h"

@implementation GLKitAndBlenderViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    GLKView *glkView = (GLKView *)self.view;
    glkView.delegate = self;
    glkView.context = aContext;

    glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    glkView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
    glkView.drawableMultisample = GLKViewDrawableMultisample4X;

    self.delegate = self;
    self.preferredFramesPerSecond = 30;

    effect = [[GLKBaseEffect alloc] init];

    // Load the model
    model = [[MyModel alloc] initWithFilename:[[NSBundle mainBundle] pathForResource:@"mymodel" ofType:@"mdl"]];
    [model load];

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glEnable(GL_DEPTH_TEST);
}

#pragma mark GLKViewControllerDelegate

- (void)glkViewControllerUpdate:(GLKViewController *)controller
{
    static float transY = 0.0f;
    transY += 0.175f;

    static float deg = 0.0;
    deg += 0.1;
    if (deg >= 2*M_PI) {
        deg-=2*M_PI;
    }

    static GLKMatrix4 modelview;
    modelview = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, -25.0f);
    modelview = GLKMatrix4Rotate(modelview, deg, 0.0f, 1.0f, 0.0f);

    // Correction for loaded model because in blender z-axis is facing upwards
    modelview = GLKMatrix4Rotate(modelview, -M_PI/2.0f, 0.0f, 1.0f, 0.0f);
    modelview = GLKMatrix4Rotate(modelview, -M_PI/2.0f, 1.0f, 0.0f, 0.0f);

    effect.transform.modelviewMatrix = modelview;

    static GLKMatrix4 projection;
    GLfloat ratio = self.view.bounds.size.width/self.view.bounds.size.height;
    projection = GLKMatrix4MakePerspective(45.0f, ratio, 0.1f, 100.0f);
    effect.transform.projectionMatrix = projection;}

#pragma mark GLKViewDelegate

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    [effect prepareToDraw];

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Render the model
    [model render];
}

@end
  1. We load the model within our viewDidLoad:-method
  2. We make some adjustments to the model-view-matrix because in contrast to OpenGL, in Blender the z-axis is facing upwards. If we would not do this, the model would be render in the wrong orientation. (We also changed the model-view matrix so the rendered apple-logo is nicely spinning)
  3. Within the glkView:drawInRect:-method we call the render-method of our model.
You can get the full Xcode project here.
If you run the application in the simulator, you should see a rotating apple-logo. The 3D-effect is not so powerful as we did not introduce lightning yet and we used the same color for all faces; but still: Well done!

The final result; imagine the logo is rotating 😉

What’s next?

I wanted to end this second part of the series with something that already shows us some nice result based on what we have learned. Thus, we have created a very simple exporter for our model, but we have missed a lot of points we have to tackel in the next part of the series:

  • When we do the triangulation of our model, we do it on the model that is stored in the Blender file itself. What we want in the future is actually to make a copy of our model so we can work on this. We might later on want to enhance/remodel and if we have triangulated the model that might make it harder. We could obviously make sure to not save the Blender model after executing the script or always press Undo, but there are better ways.
  • The export-script we have written is no real Blender Export script that appears under File -> Export. We should change this so we can also offer the user a dialog where to actual store our exported model and under which name. After all, we might work with a designer that does not want to modify python-code to change the location of a saved file.
  • In Blender the z-axis is pointing in the upwards direction. This is different to OpenGL where the y-axis is the one facing upwards. If we don’t want to correct the orientation with the model-view-matrix in our OpenGL code, we have to enhance the export-script to do this conversion already.
  • Our model-format at the moment is very inefficient as we have a lot of duplicate vertices in our model-file (adjacent faces have common vertices). Second, exporting to a binary format format spares us the string-to-float conversion and would be much faster for loading the model. Third, the final result in the iOS simulator does not look very 3Dish yet. This is due to the missing normals for the the lightning calculations. Also, textures/materials for the faces are missing.
You see, we have a lot to enhance here. Stay tuned for the next part of the series where we will tackle all of these points (except materials/textues; that’s for an own part).

Update:

I accidentally checked in the apple_logo.blend-file while in EDIT-mode. Unfortunately, the Object.data is never updated, until this mode is left again. So, even though, the model looks triangulated in Blender, the underlying data isn’t and the export-script will not export triangles. I updated the file in github, but you can just go back to OBJECT-mode and try the export again if you already download the files before. Thanks to Johnson Tsay for noticing this!

Written by 38leinad

November 2, 2011 at 9:54 am

Practical Blender with GLKit – Part 1 – Introducing GLKit

with 20 comments

This is my first post for idevblogaday.com and I am quiet excited to be part of this community. The main reason to do this is so I do more constant iOS development. Hopefully I can keep up with the bi-weekly schedule.

With this post, I would like to start a series about the use of Blender for iOS game development. I will additionally base this series on the new iOS 5 framework GLKit. I will try to keep it rather practical and  assume knowledge of OpenGL ES and Blender basics. If that is not the case for you, I will give reference to some literature for self-learning:

The general idea for the different parts of the series is at the moment as follows:

  1. Introduction: Basically set up a GLKit-based project from ground. This will be rather a beginners-type topic to get started. As GLKit is a just newly introduced API in iOS 5 I think that it makes sense to spend a whole post on it.
  2. Blender and Python: I will try to introduce the powerful python scripting engine underneath Blender. How to write own scripts that access the modeled object and modify them.
  3. Blender Exporting: We will use Blender’s python scripting engine to write our own export-function to a custom 3D model format and write the corresponding model-loader for our GLKit project of Part 1.
  4. Blender Animations: We will extend our model to contain skeletal animation and add the necessary adjustments to our Blender export-script and our GLKit project.
  5. We will see what I can come up with. I am not this far yet.
Please note that this series is supposed to be rather practical on how to use GLKit and in specific Blender for game-development. So, I will assume knowledge on OpenGL and some self-teaching on Blender and Python (whatever basics you are missing). I will not try to write just another introduction to OpenGL and Blender as there are already plenty good out there that I will hint to.

OpenGL ES Links

If you have followed this blog before, you might know that I expect you to read some external resource on your own to get the necessary concepts if you don’t know them yet. So here, some external literature for OpenGL ES, if you need to refresh your knowledge:

Introduction

So what is actually GLKit? If you have been working with OpenGL ES 1 and its fixed-function pipeline a lot and then at some point in time tried to switch to OpenGL ES 2 with its shader-based freely programmable model (because Apple said this is the way to go), you know that this transition is not easy at first.
OpenGL ES 2 gives you great flexibility if you are an advanced developer in this area (unlike me) but you feel overwehlmed when you first see the Xcode template for it:
  • You have to learn the shader language
  • You have to write the code for loading, compiling and linking the shaders yourself (well, it is in the template; but anyway)
  • You have to set up the different buffers (pixelbuffer, depthbuffer, stencilbuffer, …) yourself (again; in the template, but it just leaves a bad feel in your stomach)
  • You loose a lot of the beloved APIs for manipulating the modelview and projection matrices.
The overhead when you start a new project is just quiet high. GLKit tries to tackel this and actually does this quiet well by replicating the fixed-function pipeline of OpenGL ES 1; so you can choose to do some basic rendering with the capabilities of the fixed-function pipeline and only resort to OpenGL ES 2 features for some advanced effects. Lets have a look.

Project Setup

Open up Xcode 4 and create a “Single View Application” named “GLKitAndBlender. I made it a “storyboard-based” application and Automatic-Reference-Counted  as it is the new hip thing to do; but note that we will not really need anything related to the storyboard as we only have one scene worth of information (our OpenGL view).
As we will use OpenGL ES and the new GLKit framework, add them both to the linked libraries in the Build Phase pane.

Link the project with GLKit and OpenGLES

Next, go to the autogenerated GLKitAndBlenderViewController.h header-file and give it the protocols, methods, and member as you see below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>

@interface GLKitAndBlenderViewController : GLKViewController <GLKViewControllerDelegate, GLKViewDelegate> {
@private
    GLKBaseEffect *effect;
}

#pragma mark GLKViewControllerDelegate
- (void)glkViewControllerUpdate:(GLKViewController *)controller;

#pragma mark GLKViewDelegate
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect;

@end

We do four main things here:

  1. Define this controller as a subclass of GLKViewController. This controller plus the GLKView we will define in the next step in interface-builder save a lot of work in regard of automatically setting up a render-loop and managing the framebuffer.
  2. We make this controller its own delegate by implementing the GLKViewControllerDelegate protocol. This protocol defines the method glkViewControllerUpdate: that is called each time before a new frame will be render. You can use it for any kind of calculations that have to be performed prior to the actual rendering; so, the render-method itself is as lightweight as possible. In a game you might also use this method to update your game-physics and -state.
  3. We also implement the GLKViewDelegate that defines us our actual render-method glkView:drawInRect:.
  4. Also, don’t forget to import the GLKit header-files!
Additionally, we have defined a member of type GLKBaseEffect that we will see in action later. GLKit defines different effects that basically bundle vertex- and fragment shaders internally, and allow you to easily set the uniforms of the shaders via convenient properties.
GLKBaseEffect is the class that gives use the OpenGL ES 1 fixed-function pipeline very conveniently in the OpenGL ES 2 context. It will internally load the right shaders that implements the lightning-, texture- and material-model of the fixed-function pipeline. Lightning setup is no longer done via glLight(), glLightModel() and friends but with the methods/properties defined on GLKBaseEffect. Have a look in the API for details. We will shortly see the basics on setting up the modelview and projection matrices as only one example.
The next small step is to select the storyboard-file (this is a new feature of iOS 5 and basically a bundle of NIBs; so don’t be suprised that there is no MainMenu.xib) and make the view an instance of GLKView via the inspector on the right side. You might have to repeat this for the iPhone- or iPad-storyboard file depending on if you want use/test both.

Make the view an instance of GLKView

Reimplementing the Swinging Square

You might know the standard OpenGL ES template in XCode, that displays a swinging, multi-colored square. We will reimplement this with the help of GLKit and the GLKBaseEffect. Once you have that running, you have a minimal GLKit template and we have a good basis for the next part of the series.

Let’s first review the viewDidLoad-method:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
- (void)viewDidLoad
{
    [super viewDidLoad];

    EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    GLKView *glkView = (GLKView *)self.view;
    glkView.delegate = self;
    glkView.context = aContext;

    glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    glkView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
    glkView.drawableMultisample = GLKViewDrawableMultisample4X;

    self.delegate = self;
    self.preferredFramesPerSecond = 30;

    effect = [[GLKBaseEffect alloc] init];

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

First, we set up the OpenGL Context (EAGLContext) for OpenGL ES 2 and set it on the GLKView (line 9). We also define us as the delegate for the GLKView and set some properties on the view so it can set up the framebuffer correctly.

From line 15 one, we first set us as the delegate for ourself (always good if you know how to help yourself!) and set the prefered framerate the GLKViewController will try to manage for us.

Oh; and we create an instance of GLKBaseEffect. If we look into the implementation of the GLKViewController delegate-method, we see what we can do with this effect-class:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
- (void)glkViewControllerUpdate:(GLKViewController *)controller
{
    static float transY = 0.0f;
    float y = sinf(transY)/2.0f;
    transY += 0.175f;

    GLKMatrix4 modelview = GLKMatrix4MakeTranslation(0, y, -5.0f);
    effect.transform.modelviewMatrix = modelview;

    GLfloat ratio = self.view.bounds.size.width/self.view.bounds.size.height;
    GLKMatrix4 projection = GLKMatrix4MakePerspective(45.0f, ratio, 0.1f, 20.0f);
    effect.transform.projectionMatrix = projection;
}

As OpenGL ES 2 is missing all the APIs to easily manipulate the modelview and projection matrix (except from within the vertex-shader), GLKit defines a rich set of methods to create and manipulate matrices. So, equivalent to the code

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslate3f(0, y, -5.0f);

we can do a GLKMatrixMakeTranslation() to create the translation-matrix and then set it on our GLKBaseEffect effect.transform.modelview-property. The internals will make sure to hand this over to the vertex-shader.

Same for defining our projection-matrix. Instead of glPerspective() in good ole OpenGL ES 1, we use GLKMatrix4MakePerspective() and set it on the effect-instance so these uniforms are internally passed to the shaders.

In fact, in the render-method, the first thing we have to do is call prepareToDraw on our GLKBaseEffect. Here the magic happends and the instance will bind uniforms/attributes that are internally defined and link the shaders. After that, it is rather standard OpenGL ES 2 code that defines verticies and colours for the vertecies and sticks them into the the standard glVertexAttribPointer-methods to feed them in the vertex-shader. Note though, that we have to use the GLKit constants GLKVertexAttribPosition and GLKVertexAttribColor so GLKit binds the attributes correctly to the variables in the shaders.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    [effect prepareToDraw];

    static const GLfloat squareVertices[] = {
        -0.5f, -0.5f, 1,
        0.5f, -0.5f, 1,
        -0.5f,  0.5f, 1,
        0.5f,  0.5f, 1
    };

    static const GLubyte squareColors[] = {
        255, 255,   0, 255,
        0,   255, 255, 255,
        0,     0,   0,   0,
        255,   0, 255, 255,
    };

    glClear(GL_COLOR_BUFFER_BIT);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glEnableVertexAttribArray(GLKVertexAttribColor);

    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, squareVertices);
    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, squareColors);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableVertexAttribArray(GLKVertexAttribPosition);
    glDisableVertexAttribArray(GLKVertexAttribColor);
}

And, due to the glDrawArrays()-call we actually should see the swinging square when your run the project in the simulator. You can find the full project over at github.

The final result

So you see, GLKit is a quiet nice API that makes the transition to OpenGL ES 2 not so harsh. You get a great matrix-library and can also use the fixed-function pipeline from OpenGL ES 1 for some rendering where you are just fine with those capabilities.

And there is more: A class for easy texture-loading (GLKTextureLoader; no copying of  Texture2D into your project as the first action), skybox-effects (GLKReflectionMapEffect) and Quaternions (GLKQuaternion). All stuff that you normally have to redo/reimport into your project to even get started.

What I was missing a bit at first was a base-class to derive and define your own effects. So, basically, get at least some help in loading and linking the shaders with a nice object-oriented API (there only is a protocol GLKNamedEffect you can implement to define your own effects). But this is only a minor point compared to all the other stuff you get for free. And, I assume we can look forward to some quiet nice additional effect in iOS 6+.

Blender Links & Hints

In the next part, we will start to use some advanced Blender scripting features. So, I will assume some basic blender knowledge up front. Here comes a list of what has helped me a lot to get started:

  • The best resources can be found directly at blender.org in the Tutorials section. I basically did the introductory series and some advanced tutorials (1, 2) to model static objects. Once you have done the steps in the webcasts on your own, you should have a good overview of the basic blender features and check on advanced topics if you like. And don’t worry if you don’t get everything in the advanced tutorials; every part you get is great, the rest will come later.
  • A great online-resource is the Blender 3D: Noob to Pro series.
  • There is a great number of Blender video tutorials out there. Unfortunately, a lot are for older version. As the interface has been changed over time, be sure to look for the right tutorials; i.e. the interface in the webcasts should look the same as for your Blender version (presumable 2.5X) or you might not get the most out of it.
  • Blender has a lot of keyboard shortcuts and mastering them is the key in becoming a Blender guru. This keyboard shortcut sheet helped me a lot in that regard.
  • If you read this, chances are high that you work on a MacBook. Unfortunately, Blender makes good use of the numerical keypad and the third mouse-button for changing the viewport in the 3D view. So, I recommend using a three-button mouse for modeling. To at least emulate the 3-button mouse and the numerical keypad, there exist useful settings in the Preferences of Blender (File -> User Preferences): Check “Emulate 3-button mouse” to use Alt-left-mouse-button to rotate the 3D view and “Emulate numpad” to use the standard number-keys as a replacement for the num-pad. Don’t forget to press “Save as Default” if you want Blender to remember this until the next launch.

Check "Emulate 3-button mouse" and "Emulate numpad" on your MacBook

Have fun modeling. You will see Blender is just an amazing tool.

Written by 38leinad

October 19, 2011 at 10:36 am

Cracking Cocoa Apps for Dummies

with 7 comments

As a first note, please understand that the intention of this post is not to encourage people to start going around and crack software. And as a second note, all shown in this post can be done by an average programmer with a basic understanding of low-level computer science anyway. This post is merely to raise awareness among those developers that might have forgotten: The average indie-application is not well-protected against crackers. Good point is that the Mac/Cocoa-community is still not as much affected by this problem then the Windows-community, but still it is worth emphasizing.

What do I mean with “cracking”? Here the definition of wikipedia:

Software cracking is the modification of software to remove or disable features which are considered undesirable by the person cracking the software, usually related to protection methods: copy protection, trial/demo version, serial number, hardware key, date checks, CD check or software annoyances like nag screens and adware.

The common example is a “demo” application made available for download that has some functionality blocked until you buy the application  and enter a valid license key. A cracker could try to modify the application binary to get around this license-checking.

To be honest, I sometimes do this myself. For example yesterday: If found a very cool cocoa app in the web that I am fully interested in buying officially (and actually did after “testing” it). But, a key part of the functionality is blocked in the demo-app. Without being able to test this feature, the whole point of a demo-app is eradicated. So, before buying the app, I wanted to fully test it. This post describes the general steps I did to unlock the application and hopefully this raises some awareness for how poorly protected most apps are (AND that a demo-app should not block a core-functionality that makes the demo-app pointless; better, make it time-limited).

Demo App: MySuperCoolApp

Obviously, I will not expose any particular application, so we will go through the steps based on a very simple dummy-application that accounts for 90% of the cocoa apps out there in regard to how demo-versions are implemented. You can get the full Xcode project on github if you want to try the steps along the way yourself.

It is a simple window-based application with a single button blocking some functionality only available in the full-version. And code-wise, it looks like this:

- (IBAction)buttonPressed:(id)sender
{
    if (!self.licensed) {
        [[NSAlert alertWithMessageText:@"Unlicensed version"
                         defaultButton:@"Ok"
                       alternateButton:nil
                           otherButton:nil
             informativeTextWithFormat:@"You did not license this app, so you miss this cool feature!"]
         runModal];
    }
    else {
        // Hidden feature not available in demo-app
        [self.label setStringValue:@"Hello World"];
    }
}

Based on some property (here called “licensed”), the if-statement either gives us access to the functionality, or shows some alert-dialog asking us to buy the full-version if we need this functionality.

Step 1: Searching for the weak spot

Obviously, we don’t have the source-code available for the average app, so where to start? We can start by disassembling the application and getting a feel of how the demo-feature might be implemented. For this, there are a number of nice tools out there and as we will see, Objective-C makes it particularly easy most times to find our way into the application:

  • otool: A command-line tool coming with the MacOS developer tools that allows to inspect the contents of a binary and disassembly its text-segment. If you know objdump from linux: this is the equivalent in the Mac-world.
  • otx: A tool set on top of otool that “enhances the disassembled output” and “displayes the names and data types of Objective-C methods even if symbols have been stripped” (cited from the website). Unfortunately, it does not support 64-bit executables, so it is getting rather useless on todays systems.
  • class-dump: Another nice tool set on top of otool that generates us the header-files of our Objective-C classes. You heard right: Run it on an executable and it regenerates the .h-files for us. The only mainstream language I know of where this is even easier, is Java. Good for Java, that there are not so many good applications out there that are worth cracking 😉
  • F-Script: A scripting language that is closely integrated with Cocoa and Objective-C. For a simple introduction go here (read “Crash Course on F-Script Syntax”). If you don’t like it already: Go here and download a service that allows you to inject an F-Script instance into a running cocoa app. This basically allows for inspecting the running application very easily. This tool is for thoses, like me, that don’t use gdb if they don’t have to.
  • hexfiend: A nice hex-editor for MacOS which we will use to patch our binary.
  • gdb: The GNU Debugger is a mighty tool, but is also hard to use master as a beginner; so, I will be using F-Script in this post only. And it is sufficient any…
Ok; after introducing our tool-chain, lets try get a feel for our “to be cracked” application. Let’s execute class-dump on our binary. If you downloaded the Xcode project and built it yourself, you will find the binary somewhere around here:
/Users/<your-username>/DLibrary/Developer/Xcode/DerivedData/MySuperCoolApp-<some-uid>/Build/Products/Debug/MySuperCoolApp.app/MySuperCoolApp
Run “class-dump -H MySuperCoolApp” and the Objective-C headers will be disassembled/regenerated for you. A quick search for terms like “license” or “registered” mostly lead to some promising result.  For our dummy-app we find the following in MySuperCoolAppAppDelegate.h:
@class NSTextField, NSWindow;

@interface MySuperCoolAppAppDelegate : NSObject <NSApplicationDelegate>
{
    NSWindow *window;
    NSTextField *label;
    BOOL licensed;
}

@property(nonatomic, getter=isLicensed) BOOL licensed; // @synthesize licensed;
@property(retain, nonatomic) NSTextField *label; // @synthesize label;
@property NSWindow *window; // @synthesize window;
- (void)buttonPressed:(id)arg1;
- (void)awakeFromNib;
- (void)applicationDidFinishLaunching:(id)arg1;

@end

A variable “licensed” and accompanying synthesized property. Lets try if we are on the right track. We could now use gdb but as I said: F-Script is much easier to handle for Cocoa applications.

Step 2: Verifying the weak spot

Install F-Script and the additional service for injecting it into a running application. When you now start MySuperCoolApp, you should be able to select the following from the services-submenu:

An additional menu-item called “F-Script” should appear after a few seconds next to the “Help” item. Select “Show Console” from the submenu. A console-like window should appear that now places us in the heart of the cocoa application.

We noticed before the property “licensed” of the class “MySuperCoolAppAppDelegate”. If you are familiar with cocoa, you should know the object hierarchy that leads you to this property. Type

NSApplication sharedApplication delegate setLicensed:YES

and try again the “Click me!” button. We have unlocked the hidden functionality.

Step 3: Understanding the machine code

As the next (and often hardest step if you are like me not a crack on intel-assembler) we will have to redo our modification done in F-Script on the level of machine- and assembly-code within the binar. For this. we first have to find the assembly-code segement for the getter of the “licensed”-property.

Run “otool -Vt MySuperCoolApp > out.txt” and search within “out.txt” for “licensed” (it could appear multiple times in a universal-binary containing 32-bit and 64-bit code; you can run “otool -vf to see what architectures are bundle in the executable and which comes first). You should find a code-segement like this:

-[MySuperCoolAppAppDelegate isLicensed]:
00000001000015e0	pushq	%rbp
00000001000015e1	movq	%rsp,%rbp
00000001000015e4	movq	%rdi,0xf8(%rbp)
00000001000015e8	movq	%rsi,0xf0(%rbp)
00000001000015ec	movq	0xf8(%rbp),%rsi
00000001000015f0	movq    0x00000a91(%rip),%rdi
00000001000015f7	movb    (%rsi,%rdi),%al
00000001000015fa	movsbl  %al,%eax
00000001000015fd	popq    %rbp
00000001000015fe	ret
00000001000015ff	nop

I am not an expert on intel assembler myself, but with some minor knowledge (and thus also the awareness that the return-value of a function is handed back via the eax-register) you basically can guess that we have to try to insert a call like “mov 0x01, %eax” which says: move the value 0x01 (which stands for YES/true) into the eax register.  With some knowledge of assembly you could also know that address 1000015f0 is basically the first instruction after the prolog of the method. So, we will basically insert our mov-instruction there either followed immeditaly by “pop %rbsp” and “ret” (which is the epilog of “every” method) or we just fill the gap to the existing “popq” and “ret” with “nop” (no operations). We will choose the second approach.

So, how do instructions actually look like in machine-code; i.e. our executable file? Espacially, we have to know how a “mov” and “nop” look like, which we want to insert. Let’s call “otool -t MySuperCoolApp” to get the raw binary data of the instructions and not the disassembled assembly code:

00000001000015b0 89 7d d8 48 8b 7d e0 89 4d d4 48 8b 4d d8 44 8b
00000001000015c0 45 d4 44 8b 4d d4 88 45 d3 e8 68 00 00 00 48 83
00000001000015d0 c4 30 5d c3 66 0f 1f 44 00 00 66 0f 1f 44 00 00
00000001000015e0 55 48 89 e5 48 89 7d f8 48 89 75 f0 48 8b 75 f8
00000001000015f0 48 8b 3d 91 0a 00 00 8a 04 3e 0f be c0 5d c3 90 
0000000100001600 55 48 89 e5 88 d0 48 89 7d f8 48 89 75 f0 88 45
0000000100001610 ef 8a 45 ef 48 8b 75 f8 48 8b 3d 69 0a 00 00 88
0000000100001620 04 3e 5d c3

Based on the first column of the previous assembly output (memory-address), we can paint a picture of the binary output we see here as follows.

  • The 7-bytes in red is the instruction “movq 0x00000a91(%rip),%rdi”
  • The green byte is the “popq %rbp”
  • The yellow byte is the “ret” return of the method
  • The blue byte is a nop
With the knowledge that “mov 0x01, %eax” in machine code is B8 01 00 00 00 and “nop” is 90, we would like to change the binary content of the file as follows:
00000001000015b0 89 7d d8 48 8b 7d e0 89 4d d4 48 8b 4d d8 44 8b
00000001000015c0 45 d4 44 8b 4d d4 88 45 d3 e8 68 00 00 00 48 83
00000001000015d0 c4 30 5d c3 66 0f 1f 44 00 00 66 0f 1f 44 00 00
00000001000015e0 55 48 89 e5 48 89 7d f8 48 89 75 f0 48 8b 75 f8
00000001000015f0 B8 01 00 00 00 90 90 90 90 90 90 90 90 5d c3 90 
0000000100001600 55 48 89 e5 88 d0 48 89 7d f8 48 89 75 f0 88 45
0000000100001610 ef 8a 45 ef 48 8b 75 f8 48 8b 3d 69 0a 00 00 88
0000000100001620 04 3e 5d c3

Like said before, in red, our “mov 0x01, %eax” instruction, after that we filled everything up with nop’s and after it follows the standard epilog that basically returns from the method so the caller gets eax=1=YES as the return value.

You might now be interested how i came up with “B8 01 00 00 00” for our “mov” instruction. Basically, you have two options: Either, you write a small C-program that hopefully produces you some assembly snippet that you expect to get, or you go the full way and have a look in Intel’s I64 and IA-32 Instruction Set Manuel. It is a though read, but if you follow along the following sections, you might be able to understand how i came up with the above bytes:

  • Beginning of Chapter 2, so you get a glimpse of understanding for Figure 2-1. Figure 2-2 and Table 2-2
  • Beginning of Chapter 3 (including 3.1.1)
  • The Section on the “mov”-instruction starting on page 3-641; our particular intrest is instruction “MOV R32, IMM32”
Step 4: Patching the executable

As a last step, we have to put our theoretical crack in the binary. Unfortunatly, the address, column that is shown by otool, is not the absolute address within the binary file, but a virtual address. We could now calculate back the absolute address in the binary (read this post on how to do it) but for all practial purposes we can just use the search-functionality of HexFiend to find the likely place of code we want to modify. Just open the binary with HexFiend and search for “48 8b 3d 91 0a 00 00 8a 04 3e 0f be c0 5d c3 90“. It is rather unlikely that it appears multiple times.

We have found the bytes we were searching for; so, lets modify them with what we already layed out in theory. It should look like this after the modification:

Save it and execute “otool -vt MySuperCoolApp” once again to see if the assembly looks like we would expect:

-[MySuperCoolAppAppDelegate isLicensed]:
00000001000015e0	pushq	%rbp
00000001000015e1	movq	%rsp,%rbp
00000001000015e4	movq	%rdi,0xf8(%rbp)
00000001000015e8	movq	%rsi,0xf0(%rbp)
00000001000015ec	movq	0xf8(%rbp),%rsi
00000001000015f0	movl	$0x00000001,%eax
00000001000015f5	nop
00000001000015f6	nop
00000001000015f7	nop
00000001000015f8	nop
00000001000015f9	nop
00000001000015fa	nop
00000001000015fb	nop
00000001000015fc	nop
00000001000015fd	popq	%rbp
00000001000015fe	ret
00000001000015ff	nop

Ok, looks good; we can give it a try an execute the application again:
Hello World! …it worked! And in most cases it is not harder to do it for a real cocoa application.

Countermeasures

The Windows scene shows us that there is really no app that cannot be cracked. So, you cannot really protect against the type of people doing it “professionally”. But you can protect against people like me that only have limited knowledge of assembly and will give up if no obvious weak spot can be found in a reasonable time. So, what should you do?

  • Don’t name your sensitiv methods in any obvious way like in our dummy app. “licensed, isLicensed, registered, …” -> bad
  • Write you license checking code in pure C. Objective-C is very chatty regarding the information on method names in the executable; even with debug symbols stripped (what you should strip anyway). This stems from the dynamic nature of it. With C, the cracker at least has to have a good knowledge of assembly to find the weak spot.

The End

I hope this post was an interesting read in two ways:

  • Firstly, it should remind everyone that in the end your app is just a sequence of bytes that can be manipulated. And especially with Objective-C’s rather verbose/dynamic nature, it is relatively easy to reverse-engineer critical parts of an application against your will as a developer.
  • Secondly, doing this stuff out of own curiosity as a developer can give you a deeper understanding of the magic that is abstracted away so nicely when you work with Xcode only.

Further Reading

Written by 38leinad

May 12, 2011 at 6:54 pm

Posted in macos, tutorial

Tagged with , ,

ARM Assembler for iOS: Part 2 – First Steps

with 2 comments

As this series is mainly to write down my own learning experience and recap on it, I assume you have made your homework from Part 1 as well as I have. Mainly, reading the Whirlwind tour of ARM Assembly (Sections 23.1 – 23.3 should be enough for now). From here, we will start to write our own first assembly functions and get familiar with the the toolchain. In detail, we will learn the following in this part:

  • Writing a simple assembler function that uses simple instructions like mov and add
  • Compiling/linking an assembler-file to C-code
  • Using gdb to debug your assembly code

Recap

Let’s start with a quick summary of what you should have learn from the Whirlwind tour of ARM Assembly:

  • There basically exist three types of assembler instructions: data– (e.g. add, sub, mov, cmp), memory– (e.g. ldr,sdr,sdmfd) and –branch-instructions (e.g. b,bl,bx)
  • All instructions are 32 bit in size (except for THUMB-mode which has only 16 bit instructions); this leads to the problem that immediate values to be mov’ed into a register have only 12 bit left (20 bit are used to encode the rest of the instruction): 8 bit for a number n and 4 bit for a right-rotation r; based on this encoding, the represented number is given as n ror (2*r). Effectively, allowing a call like mov r0, #0x4 (not mov r0, #0xfff0) because 0x4 = 0x4 ror (2*0) (not possible for 0xfff0 because 0xfff does not even fit into the 8 bits of n).
  • The above limitation can be worked around by calculating the required value 0xfff0 with multiple assembler instructions or loading it from memory. ldr r0, =0xfff0 (note the “=”) does this implicitly: If representable by a so-called immediate value, it is a direct mov, but in the example it will be converted to a memory-load
  • There exist registers r0 to r15; where, r13 to r15 have special purposes and also an alias that can be used in assembly (r13/sp: Stack Pointer, r14/lr: Link Register, r15/pc: Program Counter). Actually, r11 and r12 too, but we omitt that here. r0-r3 and r12 are scratch registers that can be changed within a function-call; everything else (r4-r11) has to be restored correctly in the epilog of a called function.
  • All assembler instructions can be executed conditionally. E.g. cmp r0, r1, movlt r3, #4: movlt is only executed when r0 < r1 (less than). The cmp-instruction sets the status-flags that are read out by the next instruction. Generally, every instruction (where it makes sense) can also be executed to set the status-flags correctly by appending an “s”; e.g. subs r0, r1, r2 (r0=r1-r2 and update status-flags). Thus, the general form of a data-statement is op{cond}{status}
  • The Barrel Shifter can be applied to the last operand of a statement to shift/rotate its bits by a fixed amount or an amount given within a register. E.g. mov r0, r1, lsl #3 (in C-Syntax r1 << 3). This is basically free and is executed with the statement in one processor cycle and is preferable over multiplication operations whenever possible.
  • Data instructions (mov, add, etc.) can only work on registers and immediate values; not memory address; they need to be loaded in a register via a memory operation first. Also, there is no operation for division and multiplications are only possible on registers (not immediate values)
  • Memory Instructions (e.g. ldr r0 [r1]: load in register; in C-syntax: r0=*r1). The memory address defined by the bracketed statement ([]) can consist of a register, register + index-regsiter or register + immediate value and either case with additional barrel-shifting. E.g. ldr r0, [r1, r2, lsl #4] (r0=*(r1 + (r2 <<4))). It can also be used to load half-words (2 bytes) or  a single byte only. Append the following to the instruction for this: h (half-word), sh (signed half-word), b (byte), sb (signed byte).
  • Memory addresses in an ldr-instruction do not fit in the instruction (same reason as for the above limitation on immediate values (only 12 bits)). But, assembler will transparently convert used memory labels to so-called PC-relative addresses (address is calculated based on the current program-counter by the assembler). Alternatives are memory-pools which are created when using ldr r0, =labelname (note the “=”); note: this only loads the address of labelname into r0; not the value!!!
  • Bulk-memory operations like stm* and ldm* can be used to load a vector (array of memory values) from memory in a list of register and store it back, respectively. These operations are also used for pushing/poping parameters to/from the stack. There actually exist aliases for different stack-implementations. Generally, the full-decrementing stack is used on the ARM architecture: I.e. the stack-pointer (sp) points to the currently used stack-address and grows to beginning of the memory area. You can see in the figure below what an stmfd statement is doing internally, when storing r0 on the stack. Note also, that the exclamation mark “!” is the auto-indexing feature of these memory operations: sp is internally decremented to the next memory location automatically.

  • Branch Instructions are the GOTOs of assembly. You can change/redirect the flow of our assembly-code. Mainly, we have “b LABELNAME” to jump to a labeled position in your assembly and bl and bx to call subroutines and return again. “bl LABELNAME” will jump to a labeled point in your assembly-code and set the lr-register to the current pc-value (Program counter); when we want to return from our sub-routine (as a “return” in C-code), we call bx which is basically an alias for “mov pc, lr”; meaning: restore the program counter to the saved value and thus cotinue with the next assembly instruction after the sub-routine call. The only difference between “bx lr” and “mov pc, lr” is that the former is required for inter-operability between normal ARM assembly and THUMB-mode.

The first assembler function

Let us write a first simple assembler function based on our already gained knowledge. It will be located in an own assembler-file and will be called from our C-code’s main-method.

Create a file asmlib.s with the following assembly-code:

@ ARM Assembler Test Library

@ int asm_sum(int a, int b)
	.align 2				@ Align to word boundary
	.arm					@ This is ARM code
	.global asm_sum			@ This makes it a real symbol
asm_sum:					@ Start of function definition
	add     r2, r0, r1		@ Add up a (r0) and b (r1) and store result in r2
	mov		r0, r2			@ Store sum (r2) in r0 which stores return-value
	mov		pc, lr			@ Set program counter to lr (was set by caller)

We have defined a very simple assembler function to multiple the two arguments a and b (which are actually handed to the function in register r0 and r1) and return back the sum within r0 to the caller. We will get into the details of the call-conventions in the next Part of the series. For now, just take it for granted that the arguments are handed over in this way and returned in r0. You should know by now that the “asm_sum:” is a label to this instruction-block and when jumped to will first execute the “add”, “mov” and last reset the program-counter (pc) to the next statement of the callers code (was stored in lr by caller).

There are some ARM-asembler directives used in the begining of the file to align the function-label to the next word-boundary (.align x means align to 2^x byte boundary). In general, the ARM processor should be able to handle unaligned access as well, but the Apple documents specifically state that functions have to be aligned. To know the details on why aligned access is important, read this post. “.arm” defines this as ARM-code and “.global” exposes the label as a global symbol. This is important so we can call this function from our C-code.

Some more information is given in the comments starting with “@”. One additional note: We could actual remove the “mov r0, r2” call if we had called “add r0, r0, r1” in the first place, but to learn assembly, it is not bad to have some more explicit code.

Next, we will call our defined function that returns the sum of its two arguments from our main-method in C-code. We use the following main.c for this:

#include <stdio.h>

extern int asm_sum(int a, int b);

int main(int argc, char *argv[])
{
	printf("== sum ==\n");
	int a = 71;
	int b = 29;
	printf("%d + %d = %d\n", a, b, asm_sum(a, b));

	return 0;
}

The only thing that you will notice is that we have to define the asm_sum-method as as external symbol, as we don’t define it here in our C-code.

You can now try to compile and link both files to an executable with the following calls (the last line is already for running our executable):

arm-elf-gcc -mcpu=arm7 -O2 -g -c asmlib.s  -o asmlib.o
arm-elf-gcc -mcpu=arm7 -O2 -g -c main.c  -o main.o
arm-elf-gcc -mcpu=arm7 -o armtest *.o -lc
arm-elf-run armtest

Running the program should show you the expected result; i.e. display the printf-statement in the stdout. Good job!

Debugging

Lets step through our assembly code with the debugger. First, create a file named “.gdbinit” in the folder where also the other two files are located and put in the following lines:

file armtest
target sim
load

This file will be loaded on startup of gdb and already set our executable, set the target architecture to the ARM simulator and load the code into memory. We can now do some simple debugging:

macbook:ARMAssembly_Part2 daniel$ arm-elf-gdb
GNU gdb 6.0
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "--host=powerpc-apple-darwin6.8 --target=arm-elf".
Connected to the simulator.
Loading section .init, size 0x1c vma 0x8000
Loading section .text, size 0x8a3c vma 0x801c
Loading section .fini, size 0x18 vma 0x10a58
Loading section .rodata, size 0x248 vma 0x10a70
Loading section .data, size 0x8bc vma 0x10db8
Loading section .eh_frame, size 0x4 vma 0x11674
Loading section .ctors, size 0x8 vma 0x11678
Loading section .dtors, size 0x8 vma 0x11680
Loading section .jcr, size 0x4 vma 0x11688
Start address 0x811c
Transfer rate: 306272 bits in <1 sec.
(gdb) break asmlib.s:9
Breakpoint 1 at 0x8228: file asmlib.s, line 9.
(gdb) run
Starting program: /Users/daniel/Dev/Test/ARMAssembly_Part2/armtest
== sum ==

Breakpoint 1, asm_sum () at asmlib.s:9
9		mov		r0, r2			@ Store sum (r2) in r0 which stores return-value
Current language:  auto; currently asm
(gdb) print $r0
$1 = 71
(gdb) print $r1
$2 = 29
(gdb) print $r2
$3 = 100
(gdb) stepi
10		mov		pc, lr			@ Set program counter to lr (was set by caller)
(gdb) continue
Continuing.
71 + 29 = 100

Program exited normally.
[Switching to process 0]
Current language:  auto; currently c
(gdb)

You see, that we first define a breakpoint at line 9 of the file asmlib.s, then we “run” the executable. The simulator stops at the breakpoint. “print $regname” allows us to print the content of a register. As exepected, the function parameters one and two are stored in r0 and r1 (compare with the values set for a and b in main.c). After that, we use “stepi” to step to the next instruction and then call “continue” so the normal execution proceeded and finally ends the program. These few gdb-commands should already allow you to do some simple debugging. For more details on gdb, google is your friend 🙂

Some more instructions in a nutshell

Lets write one more assembly function to get familiar with some more instructions. How about a multiply-routine that returns for two parameter a and b the value a*b:

@ int asm_mul(int a, int b)
	.align 2
	.arm
	.global asm_mul
asm_mul:
	stmfd   sp!, {r4-r11}   @ in case we needed to work with more than registers r0-r3,
                            @ have to save the first on the stack (only r0-r3 and r12 are scratch registers)
                            @ Here, actually don't need them...

	mov     r3, #0          @ Initialize register holding result of multiplication

	movs    r2, r0          @ Move "a" into r2 and set status-flags (mov"s")
	beq     asm_mul_return  @ Immediately return if a==0

	movs    r2, r1          @ Move "b" into r2 and set status-flags (mov"s")
	beq     asm_mul_return  @ Immediately return if b==0

asm_mul_loop:
	add     r3, r3, r0      @ r3 = r3 + r0
	subs    r1, r1, #1      @ r1 = r1 - 1 (decrement)
	bne     asm_mul_loop    @ If the zero-flag is not set (r1 > 0), loop once more

asm_mul_return:
	ldmfd   sp!, {r4-r11}   @ Restore the registers
	mov     r0, r3          @ Store result in r0 (return register)
	mov     pc, lr

Please note that we could have used assembly instructions to do the multiplication for us, but this way we can recap on some instructions we have learned more easily.

The algorithm implemented is basically: result = 0; if (a == 0 or b==0) return result; else while(b>0) result = result + a; b = b – 1 and should be quiet straight-forward. Here are some points to take away though:

  • “subs” not only does a substraction, but because we append the “s”, the status-register will be set; in specific, the zero-flag. If not zero (ne=not equal: a little confusing, but think of it as “if the result is non-zero, the two operands to sub must be not equal“; or have a look in the table in Section 23.3.4 of the well-known tutorial guiding this series) we branch to the label asm_mul_loop.
  • You see, that the status-register can be set by almost any data-instruction; also “mov” can be appended with “s” to set it. Here, we read out again the zero-flag.
  • We use stmfd to store registers r4-r11 on the stack and restore it at the end of the routine via lmfd. This, you would in general always do, if you need to use more then registers r0-r3 in your routine. As r4-r11 are no scratch-registers, it is the convention that they are the same after a functional call as before.

To test your routine, you will have to add a method-declaration for asm_mul to main.c and call it within your main-method. You can find the full sources and a Makefile of our examples on github.

Further Reading

As we will be covering function-call conventions in iOS within the next part, I recommend the following read as preparation:

Written by 38leinad

April 13, 2011 at 6:56 pm

Posted in arm, tutorial

Tagged with ,

ARM Assembler for iOS: Part 1 – Environment Setup

with 15 comments

A few weeks ago I came into the need of optimizing some OpenGL code for iOS. There was alot of matrix- and vector-calculations going on that could greatly be improved by taking advantage of the NEON coprocessor found in every of the newer iPhone and iPad versions. It is a vector-based processor also allowing single-precission float-point calculations. Taking advantage of this processor for OpenGL applications can make a signification difference as you often do vector-based floating-point calculations. Nicely, there already exist a library that provides all that is needed regarding vector- and matrix-opertions and leverages the NEON chip by implementing the main functionality directly in assembly code (you are not able to directly access that coprocessor from your C-code). My only problem: I always like to understand what I am doing and would even sometimes rather re-implement some library myself then blindly reusing something I don’t understand the inner-workings of. Not sure if this is a good quality or a bad one…

This led me to the goal for this series of posts: Learn assembly for the ARM chip, which is found in all of the iOS-powered devices by Apple (and also in most other phones that play in the same league as the iPhone). I will try to write down my experience and the learned stuff within this series to help others getting started as well. For this, I will heavily rely on external resources like documentations, blog-posts and tutorials. This “diary” will function as the glue that holds everything together and makes me stick with my set goal to learn ARM assembly.

In this parts of the series we will focus on setting up the environment and make sure that our tool-chain is working. Namely, we will do the following:

  • Install the GNU ARM Assembler toolchain
  • Build a first Hello-World C-application that we will compile, run and debug with the installed toolchain

Lets get started!

Installing the GNU ARM toolchain

As the iOS applications compiled for the iPhone Simulator are translated to normal x68 code (the simulator does not simulate an ARM chip) we cannot just write assembly code in your iOS project and run it in the simulator. For sure, we don’t want to connect an iOS device for our early fiddling with the ARM chip. Thus we will install the GNU ARM Assembler tool-chain which is free and comes with a simulator that allows us to run the developed code without a real device.

Go to the GNU ARM webpage and download the binary for your architecture. As I am focusing on Apple mobile devices, i assume you will download the toolchain for Mac OSX.

After unpacking and installing the download, you should have the following tools installed, that you are able to call from you command-line shell

  • arm-elf-gcc The gcc compiler to build executables
  • arm-elf-run To run executables
  • arm-elf-gdb The debugger to debug built executables
  • arm-elf-objdump To disassemble/read out sections of the library

As you might notice, these are all the standard binutils you already know. They only support (and compile for) the ARM architecture, but if you are familiar with gcc, gdb, etc, you should have no big problems with these tools.

The only small negative point is that these tools build and run ELF-based executables and not the Mach-O executables known from Mac OSX and iOS. So, you will have to use objdump here, but use otool for example on your iOS executables. But it is not really justified to make such a complaint…

Building a simple Hello-World App for the ARM chip

Lets build a very simple Hello-World app. We will compile, link, run and debug that app with the just installed tools.

Create a helloworld.c file with the following content:

 

#include <stdio.h>

int main(int argc, char *argv[])
{
	char *str = "hello world";
	printf("%s\n", str);

	asm volatile("mov r0,r0");

	return 0;
}

You can see that the file only prints out “hello world” and has a simple stub for adding some assembly-code to playing around with the ARM-specifics. The “mov r0,r0”, is basically a no-op and we don’t worry about it for now.

Perform the following set of calls to build, link and run the executable (named “hw”):

 

arm-elf-gcc -mcpu=arm7 -O2 -g -c helloworld.c  -o helloworld.o
arm-elf-gcc -mcpu=arm7 -o hw helloworld.o -lc
arm-elf-run hw

There should be no problems with these steps and running the “hw” exectuable should actually print “hello world” to the commandline; but I just also want to show you how to start the executable in the debugger:

 

macbook:arm-asm daniel$ arm-elf-gdb
GNU gdb 6.0
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "--host=powerpc-apple-darwin6.8 --target=arm-elf".
(gdb) file hw
Reading symbols from hw...done.
(gdb) target sim
Connected to the simulator.
(gdb) load
Loading section .init, size 0x1c vma 0x8000
Loading section .text, size 0x2d74 vma 0x801c
Loading section .fini, size 0x18 vma 0xad90
Loading section .rodata, size 0x18 vma 0xada8
Loading section .data, size 0x8a8 vma 0xaec0
Loading section .eh_frame, size 0x4 vma 0xb768
Loading section .ctors, size 0x8 vma 0xb76c
Loading section .dtors, size 0x8 vma 0xb774
Loading section .jcr, size 0x4 vma 0xb77c
Start address 0x811c
Transfer rate: 111616 bits in <1 sec.
(gdb) run
Starting program: /Users/daniel/tmp/arm-asm/hw
hello world

Program exited normally.
[Switching to process 0]

You see, it requires first to call “file hw”, to load the executable, “target sim”, then “load” and finally “run” to run the executable. All further commands, like setting break-points and stepping through the code is standard gdb and you can look it up in any regular tutorial on this toolchain (you can already do alot with break, stepi, nexti, continue, list and print).

Do you remember the “mov r0,r0” assembly instruction in our code? We can use “arm-elf-objdump -d hw” to actually disassembly the executable and see it listed as a “nop”:

 

macbook:arm-asm daniel$ arm-elf-objdump -d hw | grep -A 12 "<main>:"
00008224 <main>:
    8224:	e1a0c00d 	mov	ip, sp
    8228:	e92dd800 	stmdb	sp!, {fp, ip, lr, pc}
    822c:	e24cb004 	sub	fp, ip, #4	; 0x4
    8230:	e59f000c 	ldr	r0, [pc, #12]	; 8244 <main+0x20>
    8234:	eb00023e 	bl	8b34 <puts>
 8238: e1a00000 nop (mov r0,r0)
    823c:	e3a00000 	mov	r0, #0	; 0x0
    8240:	e91ba800 	ldmdb	fp, {fp, sp, pc}
    8244:	0000ada8 	andeq	sl, r0, r8, lsr #27

00008248 <atexit>:
    8248:	e1a0c00d 	mov	ip, sp

Congratulations! You have successfully installed the tool-chain and are now ready to fiddle around with ARM assembly.

Further Reading

As a homework for the next part of the series, i will assume you have a look at the following really great resources:

The first tutorial was originally written for the Gameboy Advanced, but that should not confuse you. The GBA also uses an ARM7-chip and thus we can transfer almost all of the learned to our iOS devices.

You actually might wamt to play around a little with what you learn in the tutorial. Do you remember the “asm volatile” block in your main-method? You could use it to put some simple assembler code in and just play around. Details on how to pass and return back C-based variables to/from this inline-code, can be found in this very well-written blog-post. I don’t assume you go through it in every detail (we will come back to it later), but it will help you if you want to pass values between C- and assembly-code and not have to worry about call-conventions between C- and assembly-code too much. Actually, this will be the topic in Part 2 or 3 of the series.

Written by 38leinad

April 6, 2011 at 7:34 pm

Posted in arm

Tagged with ,