soledad penadés
repeat 4[fd 100 rt 90]

And now PSPLink!

20080903 by sole

Screenshot from sprite sample

Messing with the memory stick is fine if you're just going to do it a couple of times, but after a while it becomes tedious.

At that point I decided I would try to make psplink work with my computer. It is another utility programmed by the superclever people at pspdev, and enables you to control the psp and even use your computer's hard drive as readable/writable by the console, so you don't need to copy things to the GAME directory anymore.

The building process was quick and easy, although it could have been faster, if I hadn't mistakenly gone into the psplink directory from pspsdk's SVN repository (which is an older version), instead of going directly to the psplinkusb directory, which is the one that lets you do everything via the USB cable. Also, this version's manual is a tad clearer and more explicit, so unless you have any odd interest in using the older version, go for the newest one, at svn://svn.ps2dev.org/psp/trunk/psplinkusb.

Yes! no more messing with the memory stick! You can even reset the console or get an screenshot, like the one from the picture :-)

PSP joystick & buttons

20080902 by sole

test output

Following the installation of the toolchain, I decided to make a little program to get some information about the PSP's interface, from the programmers point of view. That is, it would use SDL's joystick functions to find out how many axis and buttons and which codes did they report to the program. Although it might seem useless it is an easy exercise in checking events and it could even be the base for a future game.

I first tested the program on my computer, using a Logitech USB pad that I have for playing emulators. I intended to use it for real games but I still haven't found one which doesn't use the mouse. By the way, the pad works flawlessly in linux, just in case you were looking for a compatible joystick for your linux box.

The pad reported as having six axes, where the axes corresponded to the two analog joysticks and one digital joystick (two axes per joystick: vertical and horizontal), so I was expecting to find a very similar result in the PSP, but with four axes since it only has two joysticks.

Logitech dual action pad

Instead, I got an interesting result: two axes only, and the rest were buttons! PSP is reporting the digital joystick as simply four isolated buttons. This, although being surprising, also makes much easier to program simple stuff where you just need to react when a button has been pressed, instead of having to check the value of the axis which is reporting motions, and deduct the appropriate intended direction from there.

I also noticed that the analog joystick can sometimes have a very erratic behaviour, reporting movements while no one is even touching the console. It might be because it's not a brand new PSP and maybe there's some dirt or something in the controls … or maybe we were experiencing a earthquake and nobody noticed? :)

For the record, these are the reported SDL button codes, so you can look for an SDL_JOYBUTTONDOWN type of event, and compare event.jbutton.button to the following values to decide what to do:

Left: 7
Right: 9
Up: 8
Down: 6
L: 4
R: 5
Triangle: 0
Square: 3
Circle: 1
Cross: 2
start: 11
select: 10

I didn't manage to read the other buttons, they seem to be out of the reach of SDL. Maybe it's got something to do with kernel/user mode, but it doesn't worry me for the time being.

If you want to try this at home - worry not, it's safe and harmless! Here's the source code. You'll notice I also used the balls and hats functions, but I must confess that while I suspect that balls is referring to trackballs, I have no idea what hats is referring to. If anybody knows, let me know in the comments so that I can stop imagining a little Mexican hat dressing a gamepad :-D

Here's also a possible sample output, using my logitech pad and pressing buttons and moving sticks randomly:

Index: 0
Name: Logitech Logitech Dual Action
Num axes: 6
Num balls: 0
Num hats: 0
Num buttons: 12
// moving the digital stick
Axis motion: j index = 0 axis = 5 value = -32767
Axis motion: j index = 0 axis = 5 value = 0
Axis motion: j index = 0 axis = 5 value = 32767
Axis motion: j index = 0 axis = 5 value = 0
Axis motion: j index = 0 axis = 4 value = -32767
Axis motion: j index = 0 axis = 4 value = 0
Axis motion: j index = 0 axis = 4 value = 32767
Axis motion: j index = 0 axis = 4 value = 0
// moving analog sticks, note the values aren't "all, minus all or nothing" here
// you should get similar values with the psp's analog stick
Axis motion: j index = 0 axis = 0 value = 337
Axis motion: j index = 0 axis = 0 value = 1013
Axis motion: j index = 0 axis = 0 value = 2026
Axis motion: j index = 0 axis = 0 value = 4053
Axis motion: j index = 0 axis = 0 value = 5742
Axis motion: j index = 0 axis = 0 value = 7094
Axis motion: j index = 0 axis = 0 value = 10134
Axis motion: j index = 0 axis = 0 value = 13174
Axis motion: j index = 0 axis = 0 value = 15877
Axis motion: j index = 0 axis = 0 value = 19593
Axis motion: j index = 0 axis = 0 value = 22633
Axis motion: j index = 0 axis = 0 value = 26349
Axis motion: j index = 0 axis = 0 value = 30741
Axis motion: j index = 0 axis = 0 value = 32767
Axis motion: j index = 0 axis = 1 value = -1014
Axis motion: j index = 0 axis = 1 value = -3379
Axis motion: j index = 0 axis = 1 value = -4392
Axis motion: j index = 0 axis = 1 value = -5743
Axis motion: j index = 0 axis = 1 value = -7432
Axis motion: j index = 0 axis = 1 value = -9121
Axis motion: j index = 0 axis = 1 value = -11486
Axis motion: j index = 0 axis = 1 value = -13175
Axis motion: j index = 0 axis = 1 value = -14189
Axis motion: j index = 0 axis = 1 value = -16553
Axis motion: j index = 0 axis = 1 value = -19932
Axis motion: j index = 0 axis = 1 value = -22296
Axis motion: j index = 0 axis = 1 value = -25337
Axis motion: j index = 0 axis = 1 value = -28039
Axis motion: j index = 0 axis = 1 value = -32767
Axis motion: j index = 0 axis = 0 value = 25673
Axis motion: j index = 0 axis = 0 value = 16890
Axis motion: j index = 0 axis = 0 value = 8445
Axis motion: j index = 0 axis = 0 value = 3378
Axis motion: j index = 0 axis = 0 value = 1013
Axis motion: j index = 0 axis = 0 value = 0
Axis motion: j index = 0 axis = 1 value = -31755
Axis motion: j index = 0 axis = 1 value = -27026
Axis motion: j index = 0 axis = 1 value = -22296
Axis motion: j index = 0 axis = 1 value = -13851
Axis motion: j index = 0 axis = 1 value = -3379
Axis motion: j index = 0 axis = 1 value = 0
Axis motion: j index = 0 axis = 2 value = 3040
Axis motion: j index = 0 axis = 2 value = 7769
Axis motion: j index = 0 axis = 2 value = 10472
Axis motion: j index = 0 axis = 3 value = -3041
Axis motion: j index = 0 axis = 2 value = 13512
Axis motion: j index = 0 axis = 3 value = -5068
Axis motion: j index = 0 axis = 2 value = 16215
Axis motion: j index = 0 axis = 3 value = -10473
Axis motion: j index = 0 axis = 2 value = 19593
Axis motion: j index = 0 axis = 3 value = -17229
Axis motion: j index = 0 axis = 2 value = 22971
Axis motion: j index = 0 axis = 3 value = -24661
Axis motion: j index = 0 axis = 2 value = 26011
Axis motion: j index = 0 axis = 3 value = -32767
Axis motion: j index = 0 axis = 2 value = 28038
Axis motion: j index = 0 axis = 2 value = 30741
Axis motion: j index = 0 axis = 2 value = 31078
Axis motion: j index = 0 axis = 2 value = 30065
Axis motion: j index = 0 axis = 2 value = 28038
Axis motion: j index = 0 axis = 2 value = 22295
Axis motion: j index = 0 axis = 2 value = 15539
Axis motion: j index = 0 axis = 2 value = 9458
Axis motion: j index = 0 axis = 2 value = 3040
Axis motion: j index = 0 axis = 2 value = 0
Axis motion: j index = 0 axis = 2 value = -676
Axis motion: j index = 0 axis = 2 value = -2365
Axis motion: j index = 0 axis = 2 value = -3041
Axis motion: j index = 0 axis = 2 value = -3716
Axis motion: j index = 0 axis = 2 value = -4392
Axis motion: j index = 0 axis = 2 value = -5068
Axis motion: j index = 0 axis = 2 value = -7432
Axis motion: j index = 0 axis = 2 value = -11148
Axis motion: j index = 0 axis = 2 value = -13513
Axis motion: j index = 0 axis = 2 value = -16216
Axis motion: j index = 0 axis = 2 value = -18580
Axis motion: j index = 0 axis = 2 value = -19932
Axis motion: j index = 0 axis = 2 value = -21621
Axis motion: j index = 0 axis = 3 value = -31755
Axis motion: j index = 0 axis = 3 value = -27363
Axis motion: j index = 0 axis = 3 value = -22972
Axis motion: j index = 0 axis = 3 value = -19594
Axis motion: j index = 0 axis = 3 value = -16216
Axis motion: j index = 0 axis = 3 value = -15202
Axis motion: j index = 0 axis = 3 value = -11824
Axis motion: j index = 0 axis = 2 value = -19932
Axis motion: j index = 0 axis = 3 value = -10135
Axis motion: j index = 0 axis = 2 value = -18580
Axis motion: j index = 0 axis = 3 value = -8784
Axis motion: j index = 0 axis = 2 value = -14864
Axis motion: j index = 0 axis = 3 value = -6419
Axis motion: j index = 0 axis = 2 value = -8108
Axis motion: j index = 0 axis = 3 value = -3041
Axis motion: j index = 0 axis = 2 value = -676
Axis motion: j index = 0 axis = 3 value = -1014
Axis motion: j index = 0 axis = 2 value = 0
Axis motion: j index = 0 axis = 3 value = 0
// buttons!
Pressed button 0
Pressed button 1
Pressed button 3
Pressed button 2
Pressed button 2
Pressed button 1
Pressed button 7
Pressed button 5
Pressed button 6
Pressed button 4
Pressed button 5
Pressed button 4
Pressed button 6
Pressed button 9
Pressed button 8

Installing the PSP toolchain in Ubuntu

20080901 by sole

(As all the guides I found out there were either outdated or specific to windows/cygwin, I decided to put this here just so that I remember how to do this next time I have to install the toolchain on another computer :-) )

First, check out the toolchain sources from svn://svn.ps2dev.org/psp/trunk/psptoolchain into say ~/tmp/psptoolchain:

mkdir ~/tmp/psptoolchain
cd ~/tmp/psptoolchain
svn co svn://svn.ps2dev.org/psp/trunk/psptoolchain .

Notice the svn:// and not http://, most tutorials are still using http://svn… and it won't work.

Now read ~/tmp/psptoolchain/readme-ubuntu.txt. It tells you to make sure you have a series of packages installed; a pity they forgot to add a couple of packages (libmpfr-dev and libgmp3-dev). This is the full, updated list of packages to install:

sudo apt-get install build-essential autoconf automake bison flex \
  libncurses5-dev libreadline-dev libusb-dev texinfo libmpfr-dev \
  libgmp3-dev

with that and following the remaining instructions in the readme-ubuntu.txt file you should be able to get the toolchain installed in your computer. It will take some time depending on your processor etc, on my powerpc mac it takes a lot of time (in the order of hours), whereas in my brand new ubuntu machine with quad processor it took ~25 minutes, if I remember correctly.

So once it finishes, everything will be installed at /usr/local/pspdev. You might want to create a shortcut to the samples, which are in /usr/local/pspdev/psp/sdk/samples, but have a look at the other folders anyway, since the .h files are in there too and it's good to know what you're dealing with.

And this is entirely optional, but if you want to install SDL and other libraries, the easiest way I found is to use their psplibraries script. It is hosted in the same SVN repository so you just need to check it out:

mkdir ~/tmp/psplibraries
cd ~/tmp/psplibraries
svn co svn://svn.ps2dev.org/psp/trunk/psplibraries .

Again, there's a readme-ubuntu.txt file; you might need to install libtool as specified there, and after that, simply run the libraries-sudo.sh file and let it work for a while since it needs to grab the sources for the libraries and build them.

Once that is finished too, the libraries will be also ready for your consumption and linkage inside the /usr/local/pspdev folder too, so everything is nice and clean. The guys at pspdev did a good job, kudos to them!

Create .ZIPs from multiple folders

20080826 by sole

There we go with yet another exercise in Python :-)

The idea here is to archive several folders, having each folder in a ZIP file. So if you have two folders, A and B, you end up with A.zip and B.zip.

No doubt this can be done with shell programming (and it will be much better since this solution doesn't provide support for recursion) but this is intended as a way of improving my python skills, so no moaning about the choice of language here! ;-)

And here is the little script:

import os
import sys
import zipfile

if len(sys.argv) > 1:
        folder = sys.argv[1]
else:
        folder = '.'
       
for item in os.listdir(folder):
       
        full_path = os.path.join(folder, item)
       
        if not os.path.isdir(full_path):
                continue
       
        dst_filename = item + '.zip'
       
        dst_item = os.path.join(folder, dst_filename)
       
       
        if os.path.exists(dst_item) and os.path.getsize(dst_item) > 0:
                continue
       
        output_file = zipfile.ZipFile(dst_item, "w", zipfile.ZIP_DEFLATED)
       
        for item_file in os.listdir(full_path):
                output_file.write(os.path.join(full_path, item_file), item_file)
               
        output_file.close()

You can download it from my supersnippets repository, and then execute it with

python zip_folders.py name_of_folder_to_process

Maybe changing the way I do the imports would help, so instead of doing import os and then using os.listdir, I would write from os import listdir and then simply use listdir from then on, but for some reason I kind of prefer the more verbose way for now, so that I don't have to guess where does each function come from.

I suppose once I get more fluent with Python, I won't need to use those long statements.

Neon v2 goes open source

20080804 by sole

Neon v2

If you're interested in VJ software, you may probably have heard about Neon v2, the VJ application that shine/xplsv.com developed a few years ago and which has been used not only for lots of VJ gigs but also for creating several real-time demos (including the euskal 2005 winner demo, Sound Pressure)

Unfortunately Shine is very busy right now. But instead of letting the software stagnate, he has made the full sources available under a GPL license, for whoever wants to pick up the development. This pretty much follows the story of Neon v1: when the author (mac/xplsv.com) got too busy, he released the sources for Neon V1 and Shine continued it, creating Neon v2 a while after.

You can check the sources from the SVN repository with your favourite SVN tool, or just be curious and browse them. It has lots of interesting stuff in it. Some examples that come to mind:

  • a full real-time 3d engine, with support for pixel and vertex shaders for building really cool effects
  • 3dsmax mesh export plug-in - if you want to know how to build a plug in for 3dsmax, here's an example
  • integration with Lua for scripting - allows you to use the engine features programmatically
  • video play, using native windows video support and also ffmpeg for other formats
  • custom skinnable gui

etc etc etc… there are more things but I'll let you find out by yourself!

As Shine says in the news, if you make new features for it, contact him and we'll include them on the repository. If the updating gets active we could then manage new users with write-access for the SVN.

I personally wish someone with better knowledge of OpenGL and GUI's than me would port the software to Mac/Linux (fingers crossed). It would be awesome to have it working without depending on DirectX as it does now (hint hint hint!)