I'm currently re-making an old Missile Command-esque ZX Spectrum Next game I wrote a couple of years back that, to be honest, could have been way better (but I really didn't know any better back in those days). There are some graphical differences I want to make, and one of the major considerations regarding graphics is how I can get more speed when it comes to creating linear missile trails.
Saturday, 3 September 2022
Wednesday, 17 June 2020
What is MMUFPHK?
Posted on 14:09 by kevman3d
Yes, what is MMUFPHK? I recently ran into a situation regarding file management and team production which resulted in a task I decided to call Massive Multi User File Path House Keeping. This is where you (hopefully don't) find multiple Maya project folder structures that have become buried within a singular project on a team server, and worse - production files that are referencing or importing elements from a variety of these individual project folders.
Thursday, 21 May 2020
The NEXT Generation...
Posted on 02:27 by kevman3d
Sunday, 18 November 2018
'Kit-setting' 3D for printing with Python in Maya
Posted on 23:26 by kevman3d
I've been toying about a lot with prepping models for 3D printing and one of those things where problems pop up is working out how to cleanly break up a model to minimise the need for supports. The same goes for how to deal with round shapes like spheres - if the bottom is on the bed, you can lose some of the 'sphere-ness'.
Monday, 10 September 2018
Archive those Maya projects - cleanly...
Posted on 23:51 by kevman3d
A great way to make sure that you keep the project files that made up your scene in Maya is to use Maya's File menu's Archive Scene option. One of the reasons I like Archived scenes is that it keeps things clean. It makes sure that only those files that make up the project are backed up, which then ensures we don't end up with the usual bombardment of multiple 'test' files, WIPs, etc. This is a great way to set up a project to be transported across to say, a render farm. Which was part of my original goal for developing this...
Sunday, 4 February 2018
A new home for Sega carts
Posted on 21:33 by kevman3d
I've recently been collecting game cartridges for my old Sega SC-3000. This is a home computer that is literally the same hardware sound in Sega's first game console (the SG-1000) with a little more memory housed inside a keyboard. While I am not even sure if the machine still works (it needs a missing video daughter-board) I figured that old cartridges are not always that easy to come buy so I'll grab them when I see them.
Saturday, 28 October 2017
Maya TD tips - that awesome 'toolkit' you always wanted...
Posted on 23:34 by kevman3d
I got tired - tired of seeing icons on shelves in Maya disappear and noting that even when working, flipping to shelves to change the tool set that was being used meant the pipeline tools that I'd painstakingly developed would be hidden in a shelf that probably wouldn't be set back again when needed.
Friday, 13 October 2017
Maya swatch headaches be-gone!
Posted on 01:24 by kevman3d
This was something that frustrated me this afternoon, so much that I thought I'd slap this very short and concise blog entry for anybody interested...
I loaded up a rather complex project to test that had been set up to use VRay materials, and had been choking up and causing havoc on the render-farm here.
I loaded up a rather complex project to test that had been set up to use VRay materials, and had been choking up and causing havoc on the render-farm here.
Sunday, 1 October 2017
100 days - Exhibited, and over for 2017!
Posted on 20:56 by kevman3d
Yus! 100 Days is now officially over for 2017...
In one way, its a relief since I can now just continue with the norm's of life without that 'must do 100 days' thought lingering in the back of my mind. In another way, its also sad that it was a good way to enforce drawing practice - however it has left me with a habit to just do it so its worked out.
In one way, its a relief since I can now just continue with the norm's of life without that 'must do 100 days' thought lingering in the back of my mind. In another way, its also sad that it was a good way to enforce drawing practice - however it has left me with a habit to just do it so its worked out.
Wednesday, 16 August 2017
More TD tips - Trello for task management
Posted on 01:30 by kevman3d
In any pipeline, communication is key - sharing and passing data back and forth, whether its from application or process to another or from a manager to an artist. Over the years I've developed plenty of scripts to manage file naming, server logging and automating processes. I'd also built a SQL feedback and approval system that didn't see the light of day - and after reviewing what I'd done, it was a great learning process but it was fairly limited.
Thursday, 1 June 2017
100 days - 2017 edition
Posted on 23:19 by kevman3d
Foolishly, I figured I'd again take some time to do something creative for 100 days. This time I've decided to keep it pretty much to one theme... Caricatures and Comics... as its an area I've not spent a whole lot of time playing around in.
Where 100 days comes in useful is as a way to provide plenty of compulsory "practice" time. When you have an audience (ie. the interweb) watching you, there's kinda this whole drive to not look lazy in front of the world. lol!
Where 100 days comes in useful is as a way to provide plenty of compulsory "practice" time. When you have an audience (ie. the interweb) watching you, there's kinda this whole drive to not look lazy in front of the world. lol!
Saturday, 4 March 2017
Restoring the 2600 collection - one box at a time
Posted on 23:19 by kevman3d
I've been buying carts for my 2600 to increase my library lately... However as expected over the years, most carts end up becoming loose and without boxes, manuals, etc. While I don't mind that, for a collector, it would be great if there was some way to get those missing boxes and at least display those loose carts in all their original off-the-shelf glory...
Sunday, 15 January 2017
Beeps and bleeps - playing Speccy music in python
Posted on 02:08 by kevman3d
While I was messing about with converting old UDG graphics to PNG files, I figured one of the other things I was curious to recreate was the beepy music from the ZX Spectrum. BASIC code loaded with BEEP commands created that "I wonder what does that sound like?" curiosity that made me wonder just how easily I could use python to listen to the classic Sinclair hits of the 80's...
One problem I did run into was getting the beepy-sound out nicely. I tried many of the tried-n-tested code examples online that generated a sine wave - however while it worked, the final audio sounded pretty odd and didn't have that nice clean bleep I was expecting. I figured I'd come back to this later...
Exporting aside, I felt there must be a better way to just listen to the music - afterall, its that curiosity of hearing what it sounded like I was after. Lucky python has a module designed just for the task... The winsound module. I also wanted to create pauses in the music, so I imported the sleep function from the time module as well.
Yup, winsound has a Beep function (note the uppercase B). Much like the ZX Spectrum's own beep, you just pass the note and duration. Sounds like it should be a real doddle!
Frequency = base-note * a^semitone
Where base-note is the lowest frequency of your musical scale (in this case, I decided to go for 3 octaves below which is 32.70 hertz). The value of a is calculated as the 12th root of 2 ( in nerdy math terms, its 2^(1/12) ).
In case you're wondering about the code below, 0.083 is 1 / 12.
As there were often pauses added through music, I needed a way to indicate this. I used a note value of 99 to signal a pause.
Looping through this list, I read the duration and note value. The duration is slightly different between the winsound.Beep function, and the sleep() function that I used to introduce pauses. The Beep function requires the length in milliseconds. This is simply the duration from the list multiplied by 1000. The sleep function just uses the value (number of seconds) directly.
The rest of the code was a piece of cake. I feel there's no real explanation necessary as the code can speak for itself...
To export or just listen?
I tried two methods. One was to make use of python's wave module. This is a module that allows you to work with audio files. That includes the ability to both read and write. Being able to export the music to a .wav mean't that it could be bought into those recreated games and used.One problem I did run into was getting the beepy-sound out nicely. I tried many of the tried-n-tested code examples online that generated a sine wave - however while it worked, the final audio sounded pretty odd and didn't have that nice clean bleep I was expecting. I figured I'd come back to this later...
Exporting aside, I felt there must be a better way to just listen to the music - afterall, its that curiosity of hearing what it sounded like I was after. Lucky python has a module designed just for the task... The winsound module. I also wanted to create pauses in the music, so I imported the sleep function from the time module as well.
import winsound
from time import sleep
from time import sleep
Yup, winsound has a Beep function (note the uppercase B). Much like the ZX Spectrum's own beep, you just pass the note and duration. Sounds like it should be a real doddle!
Hmmm, note vs. frequency
ZX Spectrum audio uses semitone numbers. A value of 0 is middle C. 1 is the next semitone of C# / Db, 2 is D and so on. However winsound.Beep required a frequency value (in hertz). How do I translate that number into a frequency?Did I mention I suck at maths?
Maths was never my strong suit at school, but luckily for me that's where the internet comes in with the answers! The formula for calculating a frequency is simplyFrequency = base-note * a^semitone
Where base-note is the lowest frequency of your musical scale (in this case, I decided to go for 3 octaves below which is 32.70 hertz). The value of a is calculated as the 12th root of 2 ( in nerdy math terms, its 2^(1/12) ).
Maths always looks easier in code
I created a function to calculate the correct frequency from the beep value. I calculated this from the lowest frequency of 32.70... As I knew middle C (beep value of 0) was three octaves higher, I just added 36 (which was 3 * 12 semitones) to the value first...In case you're wondering about the code below, 0.083 is 1 / 12.
def beepFreq(ZXVal):
zxNote = ZXVal + 36
a = 2.0 ** 0.083
freq = 32.70 * (a**zxNote)
return freq
zxNote = ZXVal + 36
a = 2.0 ** 0.083
freq = 32.70 * (a**zxNote)
return freq
Getting them tunes down...
The music data itself I passed as a sequence of tuples in a list, copied directly from the BEEP parameters in the spectrum listing. This isn't the most musical of pieces, but it came from a listing so it was a good test...As there were often pauses added through music, I needed a way to indicate this. I used a note value of 99 to signal a pause.
musicData = [ (.1,0),(.1,0),(.1,2),(.1,2),(1,0),(1,99),
(.1,0),(.1,4),(.1,4),(.1,0),(.1,0),(.1,2),(.1,2),
(.1,-1),(.1,-1),(.1,0),(.1,0)]
(.1,0),(.1,4),(.1,4),(.1,0),(.1,0),(.1,2),(.1,2),
(.1,-1),(.1,-1),(.1,0),(.1,0)]
Looping through this list, I read the duration and note value. The duration is slightly different between the winsound.Beep function, and the sleep() function that I used to introduce pauses. The Beep function requires the length in milliseconds. This is simply the duration from the list multiplied by 1000. The sleep function just uses the value (number of seconds) directly.
The rest of the code was a piece of cake. I feel there's no real explanation necessary as the code can speak for itself...
for musicPlay in musicData:
# Calculate the duration (in milliseconds)
duration = int(musicPlay[0] * 1000)
# Work out if we play a note, or whether this is a pause
if musicPlay[1] == 99:
sleep(musicPlay[0])
else:
note = int(beepFreq(musicPlay[1]))
# Call the Winsound Beep
winsound.Beep(note,duration)
# Calculate the duration (in milliseconds)
duration = int(musicPlay[0] * 1000)
# Work out if we play a note, or whether this is a pause
if musicPlay[1] == 99:
sleep(musicPlay[0])
else:
note = int(beepFreq(musicPlay[1]))
# Call the Winsound Beep
winsound.Beep(note,duration)
Budum-tish!
And there you have it. Go grab those old ZX Spectrum basic listings and type in the beep values to enjoy all of those bleepy tunes that were part and parcel of games in the 80'sSaturday, 14 January 2017
Retro bytes to PNG pixels with Python
Posted on 21:08 by kevman3d
After a long break from doing any retro game recreation in Python, I decided that since I had a few old personal game listings laying around from my ZX Speccy days that the idea of converting these to python could be fun at some later date.
However one thing the ZX Spectrum had that we didn't see on the ZX81 (with its lack of any real graphics capability) was user defined graphics, or UDG's as they were termed.
However one thing the ZX Spectrum had that we didn't see on the ZX81 (with its lack of any real graphics capability) was user defined graphics, or UDG's as they were termed.
Monday, 7 November 2016
Maya 2016 - small changes make for some small headaches
Posted on 21:52 by kevman3d
Lately I've been running into a few issues with projects and scripts that relate to some small changes made in Maya 2016, and 2016.5. Like most of my discoveries, I'm posting them to the blog here for those of you who may find them of use...
Saturday, 29 October 2016
Subfolders, referencing - Yes, its more Maya scripting fun!
Posted on 01:27 by kevman3d
In the last couple of weeks, I've had to modify and tweak all the scripts that I developed for my students to automate file management from Maya. In the process, I added new features and added extra functionality to handle some of the changes that this class had decided to implement.
One of my students asked me if I would be sharing these things on my blog - so yup, here we go - again... I have a few, but to keep these posts nice and short I'll start with just a couple.
One of my students asked me if I would be sharing these things on my blog - so yup, here we go - again... I have a few, but to keep these posts nice and short I'll start with just a couple.
Friday, 30 September 2016
38 days later...
Posted on 01:03 by kevman3d
I'm still going with my 100 days challenge this year - and we're already 38 days in! Time flies when you're having fun!
With a few days on and off (out of town, etc) I do have a small handful of days to catch up on, but I am glad to have made this open medium and not lock myself down to one thing. In 2014 it was all 3D - and while I could have done this again this year, I like that I can go and do what I feel like.
With a few days on and off (out of town, etc) I do have a small handful of days to catch up on, but I am glad to have made this open medium and not lock myself down to one thing. In 2014 it was all 3D - and while I could have done this again this year, I like that I can go and do what I feel like.
Thursday, 11 August 2016
Create retro-style text in illustrator.
Posted on 23:45 by kevman3d
For the logo that I needed for my 100 days project, I wanted a truly 80's vibe. I love how easy it is to create an retro 80's chrome text effect with Illustrator.
In fact, I loved it so much I thought that I'd share how you can go about making one of these yourself. I hope you enjoy this walk-through...
In fact, I loved it so much I thought that I'd share how you can go about making one of these yourself. I hope you enjoy this walk-through...
Wednesday, 10 August 2016
Decided to do it... Again...
Posted on 00:44 by kevman3d
The 100 days project is back, in about 2 weeks time. As I did in 2014 (given it didn't run in 2015) I've decided on yet another 80's themed challenge but this time leave it more open then a 3D image from an 80's 8-bit memory as was the case in 2014...
I've entitled it the "80's days challenge". We'll see how it goes - and I'll post up anything I do that I think may be of interest here.
I've entitled it the "80's days challenge". We'll see how it goes - and I'll post up anything I do that I think may be of interest here.
Saturday, 6 August 2016
Fixing a sticky stick...
Posted on 21:30 by kevman3d
As you may have seen in a previous post on the blog, I bought an old Atari 2600 a while back. It came with two sticks. One looked in better condition then the other, however while it may have looked better, it was actually a lot worse then it looked in terms of play-ability.
After a few rounds of River Raid, I found having to push extremely heavily to get a reaction out of the game indicated that perhaps the contacts in the joystick had worn down... With these old devices, its basically a set of little metal 'clickers' (best description I can think, though I'm sure there's an official name for them) that push down and make contact in a circuit - and when these lose their conductivity - well, that's when you die in River Raid, more times then you would like to!
So - I decided that perhaps one way to make sure I show everybody my true River Raid expertise would be to fix up those unreliable contacts... And what better way could there be then replacing tired old technology with modern micro switches.
Cheap as chips
I went ahead and ordered some micro-switches from Aliexpress. They cost US$1.15 (free shipping) for a bag of 50. Locally here in NZ, these can sell for NZ$0.50 each, so I definitely made a better choice spending my dollar and a half.![]() |
| 2-pin 6 x 6 x 5mm switches |
Technically I only needed about 5, but you can never have too many spares - which was lucky, as I did run into 2-3 duds...
Opening it up
The Atari stick is a real doddle to open up - just 4 screws in the bottom. The only thing to watch out for was a small spring that sat below the fire button, but other then that its just a collection of plastic bits and nothing overly technical to worry about - especially when it comes to that "Heck! How do I put this back together!?" moment.![]() |
| Nice and simple... No crazy "springs-go-everywhere" panic here! |
The 2600 Vader model I believe was released in NZ around 1984-ish, making these around 32 years old. It was covered in dust, worn plastic and the plastic coating on the PCB was bubbling in places. What I needed to do was to lift the 5 metal clickers from the PCB... Like most joysticks of this era, these are usually held down with a plastic tape/adhesive cover - and in this case, the whole board was covered in one big sticky sheet.
![]() |
| 32 year old dust... Ewww! |
With some careful craft-knife action, and a finger-nail I did pull away a lot of the plastic. I needed to ensure that I had plenty of track to solder my switches on as well.
![]() |
| Lifting the clickers - a little cut-n-scratching... |
A little methylated spirits and cotton bud action, it was looking pretty clean and ready for the switches.
![]() |
| Looks brand new - well, kinda |
Switched on
It wasn't as easy to get these switches on as I'd first thought. Each switch is pretty tiny and I needed to make sure that the switches sat over that central point where the pad had been. Also, the legs needed to be bent about to match the tracks.Holding buttons down on a smooth circuit board is tricky - they slip and slide about a little more then I'd liked. I could have glued them down first, but I didn't want to do that should I need to replace out one later on. It took a handful of 'finger pressing' and careful maneuvering of a hot soldering iron to prevent melting my skin off as I soldered each one in place.
![]() |
| Soldered on - ready to play... Almost! |
Did it work?
As I attached each individual switch, I felt I should really make sure that the switch works before carrying on to the next. I had an old app on my Samsung Tablet for testing gamepad diagnostics. There are plenty of tools for this - do a simple search on the Google play website - and its handy for such a project.I'd also just bought a 9-pin to USB adapter so I could use my old joysticks with my RPi games (retroPie) so hooking that in to the tablet let me see when a switch was pressed... It cost about $15 (free shipping) from Aliexpress and came with a pretty nifty USB adapter on the end. This saved me having to dig out my OTG cable...
![]() |
| Very cool USB adapter lets me use this on both Tablet and Pi! |
I did run across a couple of switches that didn't appear to work, and one that operated as though it was always on, and pressing down made it go off.
Since I'd actually tested these switches with a multi-meter prior to soldering them in, I'm not sure why that's the case, though some I had held down when soldering. My only real guess here is that possibly the heat, combined with the depressed button could have caused damage to the switch... But it wasn't hard to just grab another! (Given there were 50 of them).
Almost done
I finally managed to solder all of them in. They sent appropriate on-off as expected through the tablet and I started to reconstruct the joystick. However there were a few things that I had to do before this would work.![]() |
| These had to be surgically removed. |
The main one were the pins on the joystick shaft that were designed to press down on the contacts. The original pads were around a millimeter high, but these new switches were 5 mm (about the same length as these pins). That mean't I had to cut those off - in fact, I had to make sure that they were 100% flat - even a small amount of plastic was too much. But it worked.
The fire button was the same. I had to remove the pin in the center completely. I also had to remove the spring which let it bounce back up, though this wasn't an issue given that the micro-switch has its own spring loaded button.
And lastly - the switches had to be pretty accurate in where they sat on the PCB. I found the down switch was just slightly off, and that meant the joystick shaft was on one side of the button rather then directly above it. The space was pretty small, but just enough to not press down on the switch properly. A little heat and a tap with a screw driver and it was fixed.
Done!
I managed to reassemble the stick. Moving it around has a nice click to it and feels great. If anything, down sounds like it may be not quite returning back to center, but its not hard to fix later. I'm thinking if necessary, I might buy some fairly small springs (or remove some from a couple of ball-point pens) to sit around each switch just for the extra 'bounce' but we'll see how she goes with River Raid.It seemed to work with the tablet testing software. The real test will be with the 2600 when I get back to work (where its sat for a while, occassionally being pulled out after work)
Next time...
In hindsight, I should have gotten smaller 1.5mm high buttons rather then the larger 5 mm ones that I did. That would have meant no need to cut back the plastic on the stick, but definitely will consider those for the next joystick project...Roll on River Raid! Woo!
Subscribe to:
Posts (Atom)











