3DO Play Emulator


• June 6, 2012 • 3 Comments

3DOPlay 3DO emulator works really well and I was happy to see people working on this again. I loved the Panasonic 3DO game console from the nineties and I get all nostalgic sometimes and need a 3DO fix. Unfortunately there was only one emulator for the longest time, which had some issues, mainly in sound. These guys took that source code and fixed all those issues and added some nice features, like screen resizing.

Since I mainly run OS X and Linux I packaged it up in Wineskin for the Mac and it runs flawlessly on OS X 10.7 Lion as well in Wine on Linux, yay!

3DOPlay includes the 3DO BIOs, but the games are up to you to find. You can load physical cd, iso, or rom. Games tested and working 100%: Gex, Road Rash, Slayer and Monster Manor

Download 3DOPlay 1.8

OS X Screenshot

MyPaint OS X Lion Install via Wineskin or Macports


• June 2, 2012 • Leave a Comment

MyPaint is an open source and free to use natural painting application similar to Painter. It’s really good, but unfortunately there isn’t a native port to the Mac. No fears, thanks to Wineskin it’s trivial to use it on your Macintosh. I created an easy to follow instruction to walk you through the process of created a Wine wrapper so you can run MyPaint on OS X, download it here. You could probably use this walk through with any Windows software that works well in Wine.

MyPaint Screenshot

If you’re more interested in a faster more stable MyPaint and don’t mind getting your hands dirty, and you have plenty of drive space, go the Macports route – it’s really easy. I found this to be a better alternative to Wine. This guide is for Mountain Lion, but should work on previous versions. Not sure about 10.5 or lower though…

The first thing you need is XCode 4.4, which is free from the AppStore. Once XCode is installed open XCode and go into Preferences, Downloads tab and install the Command Line Tools.

Mountain Lion no longer includes x11 so you will need to download and install XQuartz. This is free also. Once that is finished download and install Macports.

Fire up the Terminal, which is in ‘/Applications/Utilities’.

Type the following to install a more Mac like theme for the program window:

sudo port install gtk-theme-switch

Go get some coffee and a sandwich… Once finished install the theme:

sudo port install gtk2-aurora

Once it’s finished type: switch2

Select Aurora if it’s not already selected.

Now it’s time to install MyPaint, type:

sudo port install mypaint

Go take a nice nap… When you wake up hopefully it’s finished loading and compiling everything including MyPaint.

To run MyPaint simply go into /Applications/Macports and click on MyPaint like any other Mac app.

So what’s this Macports stuff anyway? Macports allows you to run Linux software on the Mac. It manages software dependencies and all the hard stuff like compiling everything. If you are familiar with Linux then you’ll likely compare it to Apt or Yum package managers. If you’re worried what it has done under the hood don’t worry too much. It installs the majority of files in /opt keeping it fairly separated from the Mac file system. To uninstall you can simply delete the Macports files. A command to do this can be found here.

Enjoy

Moon Phase Icons, All 24.


• June 1, 2012 • Leave a Comment

I’ve been working on a script to calculate all twenty four moon phases and I needed some images since I was only able to find the common eight phase images. I made a series of individual high resolution PNGs with the Photoshop layered file included if anyone is interested. Download here and share!

pyGUI & wake a sleeping Mac example.


• May 28, 2012 • Leave a Comment

I started playing around with pyGUI a year or two ago, which allows fast gui development on OS X, Windows, and Linux from Python. I’m really liking it. I wrote a liitle app to wake up Macs awhile back and packaged it as a standard Mac bundle. In theory the raw Python should run on Windows, but be aware that I use arp. ;) Anyway, this app will wake a sleeping Macintosh with either an IP or MAC address. This is a very simple example of a basic window, textbox, and button, but I was playing! I also wrote a little calculator, mostly done minus a few bugs, but it’s an example of pyGUI and I likely will never do anything else with it.

Download WakeUp . Includes source and is public domain. Special thanks to Ocal who created the coffee cup icon I used.

If you’re unsure of how to package a Python App Bundle I’ll walk you through it now. Install XCode. Create your Python program. Right click your script and select Open With, Build Applet.App. Python version 2.6 would not work with pyGUI so I selected 2.5. Now you need to right click your new app bundle and select Show Package Contents. Drill down into Resources folder. Copy the GUI folder in the pyGUI (I keep the pyGUI download handy on my desktop) lib and paste it into Resources. Your app should run with a GUI now since it has the pyGUI libraries available. To change the icon, just get an icon you like and use Icon Composer, which is in Utilities in the Development folder. Drag the image into the box and save as the same name as the icns in Resources in the app bundle. Copy over it and you’re set. I have not tested bundling on Lion, but the bundled apps run fine.

Get duplicate files with Python and Objective-C


• May 28, 2012 • Leave a Comment

I put together a little script to find duplicate files using pure Python, and it’s pretty quick too. It comes in handy as I do a lot of graphic work where I end up with tons of files as I work – paranoid I suppose, but losing hours of work has made me this way. Anyway, this works perfectly, but can be slow when finding tons of matches in huge amounts of data. Download the code just copy paste below. This should work on Linux, Windows as well as OS X, just change to your path.

"""
Author:  C. Nichols

Find duplicate files and report age in days from creation timestamp.
No licensing, pretty standard stuff - just enjoy it if you need it!
"""
import os
import fnmatch
import hashlib
import datetime
# =============================================================================

def fileAgeFromTodayInDays(secs):
    """fileAgeFromTodayInDays(secs) -> int"""
    file_time = datetime.datetime.fromtimestamp(secs)
    now = datetime.datetime.now()
    diff = now - file_time
    return diff.days

def getDigest(file_input):
    """getDigest(file_input) -> str"""
    handle = open(file_input)
    h = hashlib.md5()
    h.update(handle.read())
    val=h.hexdigest()
    handle.close()
    return val

def fileStats(path):
    """fileStats(path) -> stat results"""
    return os.stat(path)

def traverseFiles(root, pattern='*.*'):
    """traverseFiles(root, pattern='*.*') -> tuple"""
    root=os.path.normpath(root)
    for root, dirs, files in os.walk(root):
        for filename in fnmatch.filter(files, pattern):
            filepath=os.path.join(root,filename)
            try:
                yield filepath,getDigest(filepath)
            except:
                pass #access denied; system file maybe. log it maybe?

# =============================================================================
# MAIN: Set your start directory, c:/ or /home, etc...
Where='/Users/mohawke/Desktop/dupes' # My path on Mac, change...

#Find='*.py'      ## search by extension.
#Find='Script5.*' ## search by filename
Find='*.*' ## get all files; comment out to override.
# =============================================================================
# Get file listing.
# =============================================================================
master={}
count=0
for one in traverseFiles(Where,pattern=Find):
    fpath,hdigest=one
    if hdigest not in master:
        master[hdigest]=[]
    master[hdigest].append(fpath)

    # This just provides some feedback, not important.
    count+=1
    strOut='searching %s\r' %count
    print strOut,

# Show results, do something with results here...
for k,dupes in master.items():
    if len(dupes)>1: # if no duplicate, ignore...
        print '\nMATCH:\n'
        for item in dupes:
            print item, fileAgeFromTodayInDays( fileStats(item).st_mtime ), 'days old'

Here it is in Objective-C. I tried to get the MD5 to work on my own, but I ran across this awesome bit of C code while looking for examples. I don’t think I can do better than this at this point. It’s good stuff so why reinvent the wheel, right? This will go through all files and find duplicates based on the hash. You can download the compiled version here, takes the path and extension you’re looking for as args OR you can copy paste the code below, just create a terminal app in XCode and change the path and extension you’re looking for. You can replace the hard coded paths for the argv, I left them in…

//  main.m
//  superduper
//
//  Created by Charles Nichols on 3/24/11.
//  Copyright None. All rights not reserved;

// Standard library
#include <stdint.h>
#include <stdio.h>

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>

// In bytes
#define FileHashDefaultChunkSizeForReadingData 4096

/*
 Function FileMD5HashCreateWithPath to compute MD5 hash
 written by Joel Lopes Da Silva.

 It’s really simple to adapt this function to other algorithms.
 Say you want to adapt it to get the SHA1 hash instead.
 Here’s what you need to do:

 replace CC_MD5_CTX with CC_SHA1_CTX;
 replace CC_MD5_Init with CC_SHA1_Init;
 replace CC_MD5_Update with CC_SHA1_Update;
 replace CC_MD5_Final with CC_SHA1_Final;
 replace CC_MD5_DIGEST_LENGTH with CC_SHA1_DIGEST_LENGTH;
 */

CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,
                                      size_t chunkSizeForReadingData) {

    // Declare needed variables
    CFStringRef result = NULL;
    CFReadStreamRef readStream = NULL;

    // Get the file URL
    CFURLRef fileURL =
    CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
                                  (CFStringRef)filePath,
                                  kCFURLPOSIXPathStyle,
                                  (Boolean)false);
    if (!fileURL) goto done;

    // Create and open the read stream
    readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,
                                            (CFURLRef)fileURL);
    if (!readStream) goto done;
    bool didSucceed = (bool)CFReadStreamOpen(readStream);
    if (!didSucceed) goto done;

    // Initialize the hash object
    CC_MD5_CTX hashObject;
    CC_MD5_Init(&hashObject);

    // Make sure chunkSizeForReadingData is valid
    if (!chunkSizeForReadingData) {
        chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData;
    }

    // Feed the data to the hash object
    bool hasMoreData = true;
    while (hasMoreData) {
        uint8_t buffer[chunkSizeForReadingData];
        CFIndex readBytesCount = CFReadStreamRead(readStream,
                                                  (UInt8 *)buffer,
                                                  (CFIndex)sizeof(buffer));
        if (readBytesCount == -1) break;
        if (readBytesCount == 0) {
            hasMoreData = false;
            continue;
        }
        CC_MD5_Update(&hashObject,
                      (const void *)buffer,
                      (CC_LONG)readBytesCount);
    }

    // Check if the read operation succeeded
    didSucceed = !hasMoreData;

    // Compute the hash digest
    unsigned char digest[CC_MD5_DIGEST_LENGTH];
    CC_MD5_Final(digest, &hashObject);

    // Abort if the read operation failed
    if (!didSucceed) goto done;

    // Compute the string result
    char hash[2 * sizeof(digest) + 1];
    size_t i = 0;
    for (i = 0; i < sizeof(digest); ++i) {
        snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i]));
    }
    result = CFStringCreateWithCString(kCFAllocatorDefault,
                                       (const char *)hash,
                                       kCFStringEncodingUTF8);

done:

    if (readStream) {
        CFReadStreamClose(readStream);
        CFRelease(readStream);
    }
    if (fileURL) {
        CFRelease(fileURL);
    }
    return result;
}

int main (int argc, const char * argv[])
{

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSString *path_input = "/Users/mohawke/Desktop/dupes/";
    NSString *ext_input  = "png";

    if (path_input && ext_input){
        NSString *path = [[NSString alloc] initWithUTF8String: path_input];
        NSString *ext = [[NSString alloc] initWithUTF8String: ext_input];

    // get user input from term.
    //if (argv[1] && argv[2]){
    //    NSString *path = [[NSString alloc] initWithUTF8String: argv[1]];
    //    NSString *ext = [[NSString alloc] initWithUTF8String: argv[2]];

        // Get all the files in our path.
        NSDirectoryEnumerator *fm = [[NSFileManager defaultManager]
                                                     enumeratorAtPath:path];

        NSString *newPath;
        NSString *file;

        NSMutableDictionary *_matchesDictionary = [[NSMutableDictionary alloc] init];
        int count = 0;
        while ((file = [fm nextObject]))
        {
            fprintf(stderr, "searching %u\r", count++);

            if ([[file pathExtension] compare: ext options:NSCaseInsensitiveSearch] == NSOrderedSame)
                {
                    //NSString *filelower = [file lowercaseString];
                    newPath = [path stringByAppendingPathComponent: file];
                    CFStringRef md5hash = FileMD5HashCreateWithPath((CFStringRef)newPath,
                                                    FileHashDefaultChunkSizeForReadingData);
                    if (md5hash!=nil){

                        NSString *hashKey = [NSString stringWithFormat:@"%@", md5hash];

                        // check if key is already in dict.
                        if ([_matchesDictionary objectForKey: hashKey])
                        {
                            // pull existing array from dict and add new entry to array
                            // for said key.
                            NSMutableArray *keyArray = [_matchesDictionary objectForKey:
                                                                       hashKey];
                            [keyArray addObject: newPath];

                            // put the array back into the dict for said key.
                            [_matchesDictionary setObject: keyArray forKey: hashKey];

                        } else {

                            // create new array, assign empty array to said key in dict.
                            NSMutableArray *keyArray = [NSMutableArray array];
                            [keyArray addObject: newPath];
                            [_matchesDictionary setObject: keyArray forKey: hashKey];

                        }
                    }
                }
        }

        // we have gathered all paths and calculated hash for each file,
        // any hash that matches would be a dupe file.
        NSEnumerator *keyEnum = [_matchesDictionary keyEnumerator];
        id key;
        int sz = 0;
        while ((key = [keyEnum nextObject]))
        {
            id value = [_matchesDictionary objectForKey:key];
            if ([value count] > 1){
                NSString * dupe_files = [[value valueForKey:@"description"] componentsJoinedByString:@"\n"];
                fprintf(stderr, "Dupes [%s]\n%s\n\n", [key UTF8String], [dupe_files UTF8String]);
                //NSLog(@"%@ %@", value, key);
            }
        }

    } else {
        fprintf(stderr, "Please provide a search path and extension;\ndupe /search_path/ file_extension\n");
    }

    [pool drain];
    return 0;
}

 

Random Number Generator in Python and Objective-C


• May 28, 2012 • 2 Comments

If you want a simple number generator for say picking Keno, lotto, or self made contests, here’s just how simple it is to do in Python. I was listening to Linux Outlaws awhile back and they were using a couple of different scripts to generate winners for a contest so why not write one real quick?

#! /usr/bin/python
'''
C. Nichols
'''
import random

def slot_machine(slot_range=(1,100),slots=6):
    """slot_machine(slot_range=(1,100),slots=6) -> tuple(int(slot),int(pick))"""
    min,max=slot_range
    pool=[num for num in range(min,max+1)]
    for slot in range(1,slots+1):
       yield slot,random.choice(pool)   

# ============================================================================
# Main: #    Run two common draws as an example.
# ============================================================================
print 'Typical Kino, with slot number.'
for n in slot_machine(slot_range=(1,80),slots=20):
    print n  

print '\nOhio "Classic Lotto", showing just the pick.'
for n in slot_machine(slot_range=(1,49),slots=6):
    print n[-1]

Here’s a another version. Also, I have a iPhone example that will not repeat numbers that you can download here.

#! /usr/bin/python

"""
Author: C. Nichols 
Site: http://www.darkartistry.com

Simple randomizer function.
"""
import random

def random_set(limit_picks=3, choices=[1,2,3,4,5,6,7,8], last_picks=[1,5,8]):
    """Picks random items in a list returning a list of the amount you want
    and filtering the last set of picks."""
    item_count = set()

    random.shuffle(choices)

    for random_item in choices:
        # see if it's already been picked.
        if random_item in last_picks: continue
        # get a count.
        if len(item_count) == limit_picks: break
        item_count.add(random_item)
        # return the result.
        yield random_item

# MAIN: get and print random items from a list...
results = [i for i in random_set()]
print results

 

I am learning Objective-C so I decided to create a similar one in XCode. Maybe it can be useful to someone.

//  main.m
//  NumGenie
//
//  Created by Charles Nichols.

#import 
#include 

NSDictionary * slot_machine (int minRange, int maxRange, int slotCount)
{
    NSMutableDictionary *myNumbers = [NSMutableDictionary dictionary];
    do
    {
        int number = (arc4random() % (maxRange - minRange)) + minRange;
        [myNumbers setObject:[NSNumber numberWithInt:number]
                                          forKey:[NSNumber numberWithInt:slotCount]];
        slotCount--;
    } while (slotCount > 0);
    return myNumbers;
}

// Main
int main (int argc, const char * argv[])
{

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Here's the Keno example in Objective-C
    NSDictionary *myDraw = [NSMutableDictionary dictionary];
    myDraw = slot_machine(1,80,20);

    // Sort our dictionary and print.
    NSArray *sortedKeys = [[myDraw allKeys]
                                  sortedArrayUsingSelector: @selector(compare:)];
    for (NSString *key in sortedKeys)
        NSLog(@"slot=%@ value=%@", key, [myDraw objectForKey:key]);

    [pool drain];
    return 0;
}

Geektool + Python = Desktop Weather (& moonphase)


• May 20, 2012 • 2 Comments

I had some free time today and was playing with Geektool, which is like the desktop toys I used to play with years ago on Linux – SuperKaramba comes to mind. I wrote a Python script as an example to do some weather stuff, which can be edited to work behind the scenes or to directly display weather in Geektool. It also will download an animated radar image and gets the weather icon file that you can map to your own icons or, with a minor code edit, download directly from Yahoo. Read the comments to setup in Geektool.

#! /usr/bin/python
# -*- coding: utf-8 -*-
"""
Author: C. Nichols <mohawke@gmail.com>
Site: http://www.darkartistry.com

Weather script to be used with Geektool,
or whatever you like...
Ref: http://developer.yahoo.com/weather/
"""
import subprocess,StringIO
import urllib
from xml.dom import minidom
import re
import shutil

def get_attribute(html, attr):
    res = re.search(r'%s="(.*?)"' % attr, html)
    return res.group(1)

def curl(url):
    c = subprocess.Popen(["curl", url], stdout=subprocess.PIPE)
    (out,err) = c.communicate()
    return out

def get_radar(image_out):
    image_url = "http://images.myforecast.com/images/cw/radar/northeast/northeast_anim.gif"
    result = curl(image_url)
    if result:
        open(image_out,'wb').write(result)
    else:
        print 'unable to retrieve image file.'

def weather_for_zip(zip_code):
    WEATHER_URL = 'http://xml.weather.yahoo.com/forecastrss?p=%s'
    WEATHER_NS  = 'http://xml.weather.yahoo.com/ns/rss/1.0'
    wurl = WEATHER_URL % zip_code

    results = curl(wurl)
    weather_icon = get_attribute(results, 'src')
    icon = weather_icon.split('/')[-1]

    dom = minidom.parseString(results)
    forecasts = []
    for node in dom.getElementsByTagNameNS(WEATHER_NS, 'forecast'):
        forecasts.append({
            'date': node.getAttribute('date'),
            'low': node.getAttribute('low'),
            'high': node.getAttribute('high'),
            'condition': node.getAttribute('text')
        })
    ycondition = dom.getElementsByTagNameNS(WEATHER_NS, 'condition')[0]
    return {
        'current_condition': ycondition.getAttribute('text'),
        'current_temp': ycondition.getAttribute('temp'),
        'forecasts': forecasts,
        'title': dom.getElementsByTagName('title')[0].firstChild.data,
        'icon': icon
    }
'''
You can now simply build your output from a simple key/val dictionary
including the weather icon buy pointing to your icon set or change
to download from Yahoo. Also, grab the radar if you want one.  

To run in Geektool, open shell and add: python /path/to/your/weather.py 

Don't forget the change the paths to the image files below.
'''
try:
    myWeather = weather_for_zip("43230")
    forcasts = []
    for i in myWeather['forecasts']:
        forcasts.append(i['date']+': '+i['condition']+'\n')

    message = u"%s°F %s\n%s" %(myWeather['current_temp'],
                               myWeather['current_condition'],
                               forcasts[-1])
    print message.encode('utf-8')

    # Copy yahoo weather icon to weather...
    localIcon = "/Users/mohawke/Geektool/Symbols/%s.png" %myWeather['icon'].split('.')[0]
    replaceIcon = "/Users/mohawke/Geektool/weather.png"

    shutil.copyfile(localIcon,replaceIcon)

except Exception, error:
    print "Unable to get weather data"
    #print error

So how about reading the system log? Even easier.

#! /usr/bin/python
# python /path/to/your/syslog.py

sysLogPath = "/var/log/system.log"
limit = 5  # How manyu lines to display.

lineCount = 0
for line in sorted(open(sysLogPath, "r"), reverse=1):
    if lineCount == limit: break

    print line

    lineCount += 1

Pretty easy stuff, but if you need assistance give me a shout. I’ve included some cool icons that I found in the download, but I could not find who made them. If you made them let me know and I’ll gladly give you credit.

Download Weather

and you simply can’t have the weather without the moon phase, right?

Download Moonphase

Editra Launch Objective-C Compiler


• March 5, 2012 • Leave a Comment

As I’m learning Objective-C I find moving between the terminal and my favorite IDE, Editra, kind of annoying. Luckily Editra has a really cool plug-in called Launch that can be configured to run code and display the results within the editor. The only problem is that compiling and running objective-c doesn’t work for a couple of reasons. No big deal, I wrote a simple command line program to compile and run the code returning any output. This will work on the command line and I also use it in Sublime Text 2 .

This little app was compiled on Lion so some minor changes may need to be made to compile for Snow Leopard or older. Source is included and I even compiled this in Editra.

There are two versions, one simple compiles and the other compiles and executes the program and returns results if any. This can be used at the terminal giving it only the script you wish to compile. See the images below for Editra and Sublime setups, changing to your path of course. This is for simple scripts (.m) for simple programs and learning, I’d use XCode for serious dev.

DOWNLOAD -

Easy Compiler (runObjC.zip) SHA1: 2ea6a435c2e666b13ab4d60d20b6f30c0218e4f0

SCREENSHOTS -

Setup in Launch Editra Plug-in

Editra compile with output

Setup in Sublime Text 2

Sublime Screenshot compile with output

Timers, Status and Code, Oh my!


• March 4, 2012 • Leave a Comment

Before I deleted my site I had posted some simple programs that fire a timer in order to count down the days to an event. I wrote this in both XCode and IronPython which can be downloaded with full source below. I also started writing this in VB.Net, but decided it’s so similar to the IronPython code why bother finishing it. I do have some code if you’re interested.

If you don’t have a copy of Visual Studio and would like to code GUI apps in C#, VB.Net, IronPython, etc. grab a copy of SharpDevelop. It has a visual GUI designer, compiles to exe and all the bells and whistles you’d expect in a modern IDE, all for free.

The XCode version I will admit may not be the greatest, but I am learning XCode and Obj-C. It’s the whole reason I wrote this. I had noticed that a lot of people were interested in running apps in the statusbar while researching so maybe pieces of this code can help someone. If nothing else, you get a free countdown clock. Right?

I am placing this in the public domain (full source code included), use at your own risk and all that jazz. If you’re running Lion I would suggest using the Lion version. I used auto reference counting so it is more likely you won’t run into bugs – I’ve been running it for a month now with no problems.

DOWNLOAD -

Lion  Stable

Snow Leopard

Windows (IronPython)

Windows (C#)  Stable

 

 

Time for change


• February 29, 2012 • Leave a Comment

If you have been here before you will notice the site is gone. To be honest, I am tired of managing a big site and I was constantly getting hacked because I’m too lazy to keep up with things. Let’s see how well WordPress can hold up to my laziness…

If you’re looking for the gauges or any other file that was once hosted here, come back shortly. I will get most of that content back up in the next few days. The AppShoot tool can be found on my older site: http://www.digitaldarknet.net/appshoot

Thanks for your patience.