Konami Justifier adaptor compatibility woes with the Mega-CD and older Mega Drive

Friday, 24th June 2022

Work has slowly continued in the background on the Mega Drive Justifier adaptor, as I'd love to be able to turn this into something I can build and sell to people who'd want one if they were unable to build one themselves. As the whole reason for the project is to save money, I'd need to be able to do this cheaply. The parts aren't expensive, but hand-wiring a board is very time consuming, so I thought I should design a PCB. The last time I designed a PCB was the best part of twenty years ago, so I'm pretty rusty (and I've never made a multi-layer board before), but I gave it my best shot in KiCad and sent off the designs to JLCPCB. Ten days later the boards turned up and I soldered the parts on:

The prototype circuit constructed on a PCB

I was pretty happy with the way the board turned out and was delighted to find it still worked just as well as the breadboard prototype described in the previous journal entry.

A couple of 10K resistors on the Mega Drive side of the circuit have been removed and a couple of 1K resistors have been added between ground and TR on the gun input side. The 10K resistors were connected to high-impedance logic inputs anyway so were unneccessary. TR is usually an output from the controller but here it's used to select which gun - blue or pink - is selected, so in case a Justifier is plugged into the adaptor TR is held low to select the blue gun (the pink gun uses a different physical connector so cannot be attached to this adaptor). Using a 1K resistor may prevent damage to other controllers that try to drive TR high. The updated circuit is shown below:

Updated circuit for the Light Phaser to Justifier adaptor with Justifier support
Light Phaser/Justifier to Justifier adaptor

In the process of updating that diagram I noticed a mistake in my PCB layout - pins 8 and 9 on the gun inputs are swapped, so in my case TR is connected directly to ground but the gun's GND is connected via a 1K resistor. This may be cause for concern and I've fixed it for the next PCB revision but I think I have more serious issues to contend with first!

A Mega-CD console underneath a Mega Drive

I need to be able to properly test these circuits, and the majority of games that support the Justifier light gun are not for the Mega Drive, they are for the Mega-CD. I didn't own one of these until recently, as they are ferociously expensive, but if I am to sell a product to others I have to make sure it's fit for purpose.

First, the good news: I tried the following Mega-CD games and they worked with the adaptor described above:

  • Lethal Enforcers
  • Lethal Enforcers II: Gun Fighters
  • Snatcher

The Lethal Enforcers games shouldn't be too surprising as they are not considerably different from their Mega Drive cartridge counterparts, chiefly upgraded with a CD audio soundtrack and many more sound effects. Snatcher was also developed by Konami, like the Lethal Enforcers games and the Justifier gun itself so that was not too surprising. However, the following games developed by American Laser Games do not work at all:

  • Mad Dog McCree
  • Mad Dog II: The Lost Gold
  • Crime Patrol
  • Who Shot Johnny Rock?

These games all support a number of different light guns but when started with the adaptor plugged in the best result I've got is to detect it as a "Gamegun" or "Other gun", not as a Justifier. If I plug in a real Justifier then that works, so there's definitely something up with how my circuit works. If I plug in a Justifier then swap to my adaptor I can sometimes get to the calibration screen, at which point the game either fails to respond to trigger pulls, hangs completely until the adaptor is unplugged or – if it does see the trigger pull - fail to register any shots on screen. Very disappointing, but this isn't even the worst of it…

The Mega-CD I bought came with a Mega Drive. I already have a Mega Drive (and Mega Drive II) and the adaptor works well with both of them whether playing cartridge or Mega-CD games. It doesn't work properly at all on the Mega Drive that was included with the Mega-CD. Most games don't recognise the adaptor as a Justifier at all, and if the game does happen to detect it (which it does intermittently) then it won't react to the Start button or trigger pulls in menus. I say in menus as weirdly if I get into a game of Lethal Enforcers II pulling the trigger does flash the screen (as if firing a shot) but no hits are registered and when game over occurs pulling the trigger does nothing (normally it advances the counter). Normally in the menus it advances to the next menu item, too, but not here – you can only fire blanks!

This is all rather strange. I've tried a few points around the circuit with a logic probe and it seems to be reacting as it should but the games are definitely not happy about the adaptor on that particular Mega Drive. The real Justifier works absolutely fine on it, though! I haven't yet had the opportunity to dig through activity logs with a logic analyser to see where the difference is creeping in, but thought I should mention this to save disappointment in anyone who was planning on building these projects.

This is unrelated to the pin 8/9 swap described above, incidentally – I get the exact same behaviour in my PCB prototype adaptor, the adaptor on a breadboard I used to design it and the adaptor I built in this earlier journal post. All three boards work fine on my other Mega Drive and Mega Drive II, just not the Mega Drive included with the Mega-CD.

The only difference I can see is that this new Mega Drive is actually an old Mega Drive – it's one of the earlier models with an EXT port and the "High Definition Graphics · Stereo Sound" label around the cartridge slot, whereas my previous Mega Drive is a slightly later revision without the port and text (but not so new that it suffers from poor sound quality).

I will continue probing, and update here when I've found the solution. On the plus side, the Menacer adaptor I'd developed works fine on the Mega-CD and its accompanying Mega Drive, so this weird behavior is mercifully not shared by that adaptor!

Adding input support for the Konami Justifier to the Light Phaser to Justifier Mega Drive light gun adaptor

Tuesday, 22nd March 2022

The Sega Light Phaser to Konami Justifier adaptor project that I've spoken about in the past (and the circuit of which can be found on the "product" page here) has had some interest from people who've asked me to sell them one. I've been somewhat hesitant to get into this as I am unable to test most Justifier games as I only have a Mega Drive (and can't afford a Mega CD, which most of the games require) and wouldn't want to sell people something that doesn't work! I own a Blaze "Guncon Adaptor" for the PlayStation which allows you to use a "normal" gun (e.g. Konami Hyper Blaster) to play Guncon/G-Con 45 light gun games, however it only works with some titles (e.g. Time Crisis) – I haven't been able to get it to work with any PlayStation 2 titles, for example, and it malfunctions with some non-Namco PlayStation games too. This was a bit disappointing to me, and I don't want to be a source of disappointment in others…

However, since originally developing the project I did manage to get a pretty good deal on one Konami Justifier so I thought it would be a good opportunity to at least compare my design to the real thing. In my experience the adaptor performs just as well in-game beyond the inconvenience of the Light Phasers not having a Start button on the gun, relying instead on a button on the adaptor itself. This did make me think about the opportunity to plug a Justifier into the adaptor and use it instead of a Light Phaser. This may sound like a daft idea – why do you need an adaptor to play Justifier games with a Justifier? – but this would allow you to use two player 1 (blue) Justifiers to play two-player games, as the pink player 2 Justifier is considerably more expensive than the blue player 1 Justifier.

Updated circuit for the Light Phaser to Justifier adaptor with Justifier support
Light Phaser/Justifier to Justifier adaptor

The updated circuit is shown above, though I must stress that at this point I haven't properly checked the diagram! I've built the circuit as a prototype and then drew the diagram based on the prototype, normally I'd then build another version of the circuit from the diagram to double check I'd drawn it correctly.

The type of gun is identified by DATA3 pin, which is soldered directly to GND in the Justifier gun but not connected to anything in the Light Phaser. This is pulled high with a 10K resistor and connected to the select pin of a pair of multiplexers that switches between 0 ("Justifier") and 1 ("Light Phaser") modes. The rightmost multiplexer selects the source of the "trigger" signal - in "0/Justifier" mode this comes from DATA0, in "1/Light Phaser" mode it comes from TL. The leftmost multiplexer is used to pass the TL signal back from the console to the light gun, as the Justifier requires this pin to be pulsed to reset the gun each frame. In "1/Light Phaser" mode the multiplexer's input is pulled high so it always outputs a high level and the reversed diode on the output prevents this from interfering with the input signal from the gun's trigger. In "0/Justifier" mode the signal comes from the console's TL output, with the reversed diode allowing the console to pull the gun's TL low if required.

The start button is a bit simpler, as the Light Phaser lacks a button of its own – this is just connected to DATA1 from the gun, with a reversed diode allowing the gun to pull the signal low but preventing the button built into the adaptor from shorting the output directly to ground if the gun was driving it high.

One difference between the adaptor circuit and the real Justifier is the need to reset the gun each frame. The real Justifier latches the state of TH – when the gun sees light from the CRT TV, TH goes low and will remain low until the gun is reset by pulsing TL. The Light Phaser does not do this, TH only goes low briefly whilst it can see light from the TV. This is why the circuit needed to be adapted to allow the console to reset the gun via TL. I am not sure if this difference in behaviour has any impact on real games but it doesn't affect Lethal Enforcers or Lethal Enforcers II, the two games I have to test with. If it did cause issues then a flip-flop could be added to the TH path through the adaptor to replicate this latching behaviour, but it seems like quite a lot of added complexity for something that may not be required.

The prototype circuit on breadboard

The photo above shows the current prototype of the updated circuit. I am currently using two additional 74HC157 multiplexer chips to handle the two guns but I think that I should be able to replace them with a single 74LS153 chip – some are currently in the post on their way over to me for further testing. A short video of the adaptor in action can be found on my Twitter account.

Arcs, segments and sectors in BBC BASIC for the Sega Master System

Tuesday, 12th October 2021

More musing on tape phases

I bought a few more Acorn-format BBC BASIC cassettes to test my adaptation of BBC BASIC to the Sega Master System with, and have found a few interesting oddities since my last post. In that post I made the assertion that the phase of the recorded signals on the tapes is at 180°, i.e. each wave cycle goes negative before it goes positive (whereas a 0° phase would go positive before it goes negative). This matched the documentation I'd read, the output of tools like PlayUEF and my own tests with commercially-recorded tapes. With these new tapes I've found things are not quite so straightforward, though:

  • The "Welcome" tape for the BBC Master Series is recorded at 0°. OK, maybe that's a BBC Master weirdness?
  • One copy of the "Welcome" tape for the BBC Micro is recorded at the usual 180°, hooray, we're back to normal!
  • Another copy of the "Welcome" tape for the BBC Micro is recorded at 0°. It's also a different colour, but otherwise has identical programs on it, maybe the difference comes from different duplication plants?
  • Side A of Acornsoft's "Graphs and Charts" is recorded at 180°, Side B of the same tape is recorded at 0°. Flipping the tape flips the phase, I give up!

I am able to load the programs by changing the "phase" switch on my cassette recorder to "reverse", but not all cassette recorders have such a switch. There is a jumper setting in the tape interface circuit that the cassette loader software can check to control whether it starts timing the length of wave cycles on a falling (180°, default) or rising (0°) edge and so it can compensate for the reversed phase, but I'd rather see if I can find a way to automatically detect the phase and properly recover data without needing to rewind the tape, push a switch or type in a command, then trying again.

A "1" bit is represented by two 2400Hz cycles and a "0" bit by a single 1200Hz cycle. Each byte has at least one "1" bit before it and always starts with a "0" start bit. In theory, then, a "0" bit with the correct phase should be represented by a wave cycle that's 2× the length of a preceding 2400Hz cycle, but if the phase is incorrect it'll only be 1.5× the length. At the moment the threshold to detect the difference between a 2400Hz and 1200Hz cycle is placed at 1.5×, maybe for the start bit it needs to be at 1.3× to detect the "0" bit instead, and if after that the wave is over 1.6× it's treated as a "normal" 180° tape and loaded as normal, but if it's between 1.3× and 1.6× it's treated as a "reverse" 0° tape and an extra rising edge is checked for before loading the tape with reverse phase.

I'm not sure if that'll work and my quick initial tests didn't work very reliably so I'll need to do a bit more experimentation I think. I did encounter another oddity with formats beyond the reversed phase, though, and that's with Acornsoft's "Graphs and Charts". The tokenised BASIC programs on the tape would crash the loader or generate "Bad program" errors, and when I copied the tape to my PC and looked at the files there I could see that BBC BASIC for Windows refused to open them too. The problem is that instead of the usual <CR><FF> terminator on each program, they all end with <CR><80> instead. My loader tries to convert Acorn BBC BASIC format programs to the Z80 BBC BASIC format automatically during the load, but if it misses the terminator when stepping through the program it will either see the line as being zero bytes long (due to memory being cleared to 0) and loop infinitely when attempting to jump to the next line, or read a line length from uninitialised memory that causes it to advance to a line that doesn't start with the appropriate byte and so assume the program is not in Acorn format, skipping the conversion process and leaving a "Bad" program in memory.

I made my loader more robust by appending a suitable dummy terminator to the loaded program; if it already was a valid program with a proper terminator then it makes no difference, but it otherwise prevents the convertor from dropping off the end of the program and allows me to load the programs from the "Graphs and Charts" tape.

Drawing arcs, segments and sectors in BBC BASIC

Clown missing parts     Complete clown

I hadn't implemented all of the PLOTting routines that BBC BASIC can provide for drawing graphics on the screen, and a few of the programs on the BBC Master Series "Welcome" tape take advantage of the more advanced routines to draw circular arcs, segments and sectors. Attempting to run these programs produced results like the picture of the clown above with several parts of its face missing.

I had been putting this off as I hadn't been able to think of a good way to implement drawing these shapes. After a bit more research online I came across a paper by C. Bond entitled An Incremental Method for Drawing Circular Arcs Using Properties of Oriented Lines which turned out to be ideal.

The linked paper does a very good job of describing the technique so I would recommend reading it, but crucially it provides a solution that can be implemented easily in Z80 assembly with a few integer multiplications and additions. I was able to incorporate this into the existing circle tracing and filling code without too much effort, just an extra step in the "plot pixel" or "fill horizontal span" routines to clip against the lines that bound the arc, segment or sector.

Ship missing parts     Complete ship
Acorn rendered poorly     Acorn rendered correctly
Welcome missing parts     Welcome missing slightly fewer parts

As you can no doubt see from the "Welcome" screen at the end there are still parts missing from the final image. This is because the program only draws each required letter once and then uses the block copying PLOT routines to duplicate the letter if it's needed again instead of rendering it again from scratch – hence the second "B" from "BBC" is missing, and "MASTER" becomes "MAS  R" as the program is expecting to copy the "T" and "E" from "THE" in the line above.

Welcome in its complete form

Disabling this optimisation within the BASIC program and forcing each letter to be drawn instead of copied does improve the results, though it still doesn't entirely fit on the screen due to the much lower resolution!

Tape cycle frequencies and phases, plus VDrive3 support for BBC BASIC on the Sega Master System

Wednesday, 6th October 2021

I have now moved the tape interface circuit described in the previous entry from its breadboard prototype to a neat enclosure where I am happy to report it mostly works as well as it did before.

The tape interface installed in its enclosure.

I have spotted two issues, though. The first affects my small cassette recorder but not the large one, and is related to reading files from tape via the file IO routines (such as OPENIN then BGET# to retrieve a single byte, not from LOAD). Files are stored on tape in 256 byte blocks, and when the file is opened a whole 256 byte block is read from the tape and copied to the Master System's RAM. When the BASIC program requests a byte from the tape it is read from this local copy of the block instead, and when the read pointer reaches the end of the 256 byte block the next block is fetched from the tape and the local copy updated with this new data. The motor control comes in handy here, with the file system library stopping and starting the tape playback as desired.

The problem I was having was that the first block would read fine, but when the time came to read the second block the tape started playing but the file system library never seemed to be able to detect any data – it would just work its way along to the end of the tape, never displaying any errors, but never reading any meaningful data either.

The issue ended up being some code I'd added somewhat recently to automatically calibrate the threshold between a 1200Hz ("zero" bit) and a 2400Hz ("one" bit) tone. The code reads bits by counting the length of each wave cycle and comparing this to a threshold value - if it's longer, it's the 1200Hz "zero" bit tone, if it's shorter, it's the 2400Hz "one" bit tone. Before and after each file, and between each block, is a section of 2400Hz "carrier" tone. By detecting a large number of wave cycles that were all around the same length (say, within four length units of each other) you could assume that you were receiving the 2400Hz carrier tone and use that to calculate a suitable threshold for loading in data later.

The main bug was that I was comparing the length of the wave cycle just received with the length of the previous wave cycle rather than the length of the first wave cycle. This becomes a problem when you start a tape that was paused in the middle of a carrier tone (e.g. between blocks) as the tape will take some time to come up to speed, during which time the period of each wave cycle will gradually decrease. As the reference length we're checking the current wave length against is changing over time it means we end up compensating for the tape's speed increasing and so end up accepting the slower (longer) wave cycle lengths as part of the calculation of the threshold between "zero" and "one" bit wave cycle lengths.

As the wave cycle length threshold is now longer than it should be, all incoming wave cycles get interpreted as short ones and so it looks like we're just getting a stream of "one" bits - which looks like the carrier, so the code never starts trying to decode any blocks. My larger tape recorder comes up to speed much more quickly than the small one, or at least doesn't audibly ramp up in speed, and so isn't affected by this problem.

Fortunately the fix is very easy, just check the length of wave cycles against the first wave received rather than the previous one. This way if the timings drift over time (as they would during the period that the tape is coming up to speed) then they'll eventually go out of the permitted range. Changing this fixed the issue.

You may wonder why I'm calculating the threshold at runtime instead of just using a hard-coded value if the expected frequencies are a fixed 1200Hz and 2400Hz. My main intention was to be able to handle tapes that were running at the wrong speed due to a miscalibrated cassette recorder, but this does also open up the possibility to load from tapes at higher rates. Without any further adjustment my code can already load from audio generated at 2320 baud, i.e. with the two frequencies at 2320Hz and 4640Hz, without any further adjustment. This is a slightly annoying figure as 2400 baud would be the obvious target (being double the intended rate!) but at this speed the current code fails to latch on to the signal so I slowed the "tape" speed down until I found a value that worked. It's perhaps worth mentioning that the audio in this case was coming from PlayUEF running on my phone rather than an analogue cassette tape with the BAUD (or LOW) parameter used to adjust the speed, I'm not sure that a 93% boost in loading speed would be achievable from a tape!

Little and large tape recorders.

I mentioned above that there were two issues. The slow speed-up issue affected the small cassette recorder, but the large cassette recorder had a new issue that only became apparerent after moving the circuit to its final enclosure. The Master System should be able to start and stop the cassette remotely, handled by a reed relay that is then plugged into the cassette recorder's "remote" socket. The Master System was able to start both tape recorders without any issues, but was unable to stop the large one – the "motor" status light would switch off, but the tape would continue playing. Tapping the relay sharply would be the only way to get it to switch off.

I tried plugging in a 2.5mm TS plug into the side of the large tape recorder and used the very scientific approach of shorting its connections with a screwdriver to simulate the relay switching "on" and was surprised to see quite large sparks. I measured the DC current through the remote control switch when the cassette was running and it was only around 70mA at its highest – well below the 1A rating of the relay – however I reckon there is a very large inrush current when the motor kicks in that is sufficient to weld the reed switch contacts together, causing it to get stuck.

Why didn't this affect the circuit on the breadboard? In that setup I was using a 3.5mm TS extension cable connected to a 3.5mm male-to-male adaptor cable which was then connected to a 3.5mm to a 2.5mm adaptor cable. My assumption is that all of the extra contact resistances were helping to limit the inrush current, preventing the contacts from welding together.

It's very likely not the best sort of snubber circuit for this application but for the time being I've put a 10Ω resistor in series with the relay contacts, which limits the inrush current enough for the relay not to get stuck:

Tape interface circuit for the Sega Master System with added 10Ω resistor on the relay contacts to limit inrush current.

One matter that I've also been testing is the phase of the audio signal. As far as I can tell Acorn's tape format assumes a 180° phase; that is to say that each wave cycle starts at 180° and runs to 180°+360°=540° for a complete cycle rather than starting at 0° and running to 360°. The result of this is that instead of the signal starting at an amplitude of 0, then going positive before negative (as you'd expect for a typical sine wave) the signal goes negative first:

0° and 180° phase.

I have confirmed this by looking at the output of tools like PlayUEF as well as looking at the signals coming directly off commercially pre-recorded tapes with BBC Micro software on them, after first confirming that my sound card doesn't invert the signal by briefly connecting its input to a positive DC power supply and seeing that the received signal goes positive when that happens. Here's an example of a commercially-released tape, where you can see that after the high-frequency cycles in the first longer wave (a "zero" bit, acting as the start bit, starting at around 12.7065) starts low then goes high:

Plot of the signal from a commercially-released tape showing the 180° phase.

I then generated a test tone that alternates between 0 and 1 bits, i.e. one complete 1200Hz cycle then two complete 2400Hz cycles with the appropriate 180° phase:

Plot of the test signal showing the 180° phase.

This pattern should make it easy to spot the phase of recordings. I first tried running the test tone straight back into my PC to ensure that the phase was not being reversed by the PC, and got the same signal back in compared to to what I played out, as you'd expect. I then tried recording the signal to tape with my Grundig recorder, and found something interesting when playing it back:

Plot of the test signal recovered from the Grundig tape recorder.

The phase there is very clearly reversed – the signal I played into the tape recorder goes low before it goes high, whereas the signal I've recovered goes high before it goes low. I repeated the test with the Alba tape recorder:

Plot of the test signal recovered from the Alba tape recorder.

This shows the same thing – the phase on the tape is at 0° even though the test signal was at 180°. I also have a Sony digital voice recorder (an ICD-BX140) that I've been using as well as a tape recorder, so I tried the test with that too:

Plot of the test signal recovered from the Sony digital voice recorder.

Apart from the much lower recording level this once again shows the same thing – the signal phase is inverted when recorded.

I had previously encountered an issue where I had tried to make a tape from a UEF image by playing the audio generated by PlayUEF into a tape recorder. Attempting to load the data directly from PlayUEF worked fine, but the tape recording of the same signal wouldn't load. My Grundig tape recorder has a phase reversal switch, and setting it to "reverse" would allow me to load the tape created by recording the output of PlayUEF. However, in that reverse setting, I lost the ability to load from my commercially-recorded tapes. I think the above tests indicate why this is the case – the recorders all invert the signal when creating the tape recording. I find it particularly interesting that the Sony digital voice recorder does the same thing!

I did check to see if the phase switch on the Grundig tape recorder had any influence on the recording, but it doesn't – whether it's set to "normal" or "reverse" the recording to tape still ends up inverted. The phase switch only appears to affect playback.

PlayUEF does have an option to set the output phase to 0° instead of its default 180°. By doing that and recording its output to tape I was able to load the programs directly from either of my tape recorders.

Of course, it would be nice if the loader was able to handle either phase, and in practice I've found it does sometimes handle the "incorrect" phase quite well but it does seem to be more a lot more error prone – some programs load without any problem, others report problems with some blocks and others fail to be detected at all! I think I'll see if there's a way to reliably detect the phase and switch to the appropriate handler, but for the time being I've added a crude workaround – pulling pin 1 of the controller port (the d-pad "Up" input) to ground tells the loader to assume the phase is inverted. As I hope this won't be necessary in future I've left this as a jumper in my current tape interface circuit (visible below in the top left corner) rather than add a switch!

The tape interface circuit board.

A lot of the work has been focused on the tape loader, but tapes are not the most practical storage media these days. Finding a working tape recorder is a challenge in its own right, and a lot of the old tapes are tricky to work with as they've become sticky with age. In an attempt to be a bit more modern I've started integrating support for the VDrive3 to BBC BASIC. This is an inexpensive module that lets you access files on a USB mass storage device via simple commands sent over a serial interface. I'd previously used the VMusic2 device in another project and that uses the same firmware commands so I already had a little experience with it (the VMusic is pretty much a VDrive with an MP3 decoder bolted on top). I already had some serial routines written so it was a reasonably easy job to plumb in some code to handle LOADing and SAVEing programs, and from a hardware perspective all you need is a cable to connect the module directly to the Master System's controller port – the VDrive3 uses 3.3V signalling levels but its I/O lines are 5V tolerant.

The VDrive3 alongside the tape interface and RS-232 modules.

One notable advantage of the VDrive3 over the tape interface is that it allows for proper random-access of files rather than just sequential access. I've been working on implementing all of the required BASIC statements to support this (OPENIN, OPENOUT, OPENUP, BGET#, BPUT#, PTR#, EXT#, EOF#, CLOSE# etc). For a bit of fun I wrote a BASIC program that loads an image file from disk (or tape) and displays it on screen. I needed to add user-defined character support to the new reduced-resolution MODE 2 to handle this (something that was not implemented before due to a lack of VRAM) but with that in place it's working pretty well.

Loading a picture of a duck from a USB drive.

It's not fast, taking 2m45s to load from from tape and 1m19s from a USB flash drive, but it's a fun diversion!

Refining the tape interface for BBC BASIC on the Sega Master System

Tuesday, 28th September 2021

It's been quite a while since my last post but work has continued with the version of BBC BASIC (Z80) for the Sega Master System. Most of the features I have been working have not been particularly exciting to write about on their own, but here are some of the notable changes:

  • All VDU code (for text and graphics output) has been moved to a separate ROM bank, freeing up around 16KB of extra ROM space. It makes calling the code slightly more complicated but in the previous post I mentioned that I had less than 100 bytes of free ROM space so this was definitely required.
  • Simplified the video mode driver interface. Each video mode has its own driver code which exposes a number of different functions. Previously, each function had its own vector in RAM which was fast but consumed a lot of precious work RAM. Now only a couple of functions (which need to be called frequently and as quickly as possible) are vectored, and all of the other functions are called via a single generic function with a parameter for which specific operation to carry out (e.g. "reset the graphics viewport", "change the text colour").
  • Rewrote the triangle filling routine and line drawing routine to ensure that the same pixels are covered whether you fill a triangle or trace its outline – previously there would be some stray pixels that leaked outside the perimeter of a filled triangle.
  • Changed the output resolution for most video modes to 240×192 with a logical to physical pixel scale factor of 5⅓ for a total logical resolution of 1280×1024, the same as the BBC Micro – graphics programs designed for the BBC Micro now properly fit on the screen.
  • Changed MODE 2 to use a smaller resolution of 160×128 with a pixel scale factor of 8. Unfortunately, there is not enough video RAM to have a unique pattern in VRAM for every character position on-screen when using all 16 colours (as in mode 2) at the higher 240×192 resolution. The new lower resolution avoids screen corruption that previously occurred when running out of VRAM:
Corrupt MODE 2 graphics     Fixed but letterboxed MODE 2 graphics
MODE 2 graphics at the full-screen 240×192 and reduced 160×128 resolutions
  • Added support for scrolling the text viewport down as well as up, this is used by the line editor which now allows very long lines to be edited in small viewports by scrolling and repainting as necessary.
  • Reworked the keyboard input routines for greater reliability and performance, including proper mapping of key codes in *FX 4,1 and *FX 4,2 and removal of "clever" (but flawed) interrupt-based detection of when a key is available (that had a habit of dropping keys and resulted in worse performance than just periodically polling the keyboard anyway).

The most significant changes have been all to do with loading and saving from tape, though. Since my previous post I have been doing a lot of work testing and refining both the hardware and software of the tape cassette interface. The hardware has now been tested with a couple of different tape recorders, as well as a pocket digital recorder, my mobile phone and my PC's sound card. The loader is much more robust and if a single block fails to load from the tape you can usually just rewind the tape a short way and it will try again, no need to rewind back to the start and start from scratch. I was previously counting the duration of half-wave cycles from the tape and comparing these to some fixed thresholds baked into the code to determine the difference between a "0" and a "1", I've now changed this to measure full-wave cycles (which aren't affected by any duty-cycle shifts in the recordings) and to calibrate the thresholds during the initial carrier tone, which allows the code to compensate for tape recorders that aren't quite running at the correct speed. On a more practical basis I've also added the ability to save to tape, motor control via a reed relay (so the tape will automatically stop after a file is loaded), and support for opening files on tape for reading or writing and accessing them on a byte-by-byte basis. As tapes are sequential access there are some limitations to this (for example, you can only advance the read pointer later in the file, you can't seek backwards) but it works quite well otherwise.

A selection of tapes and a tape data recorder.

Of course, to test all of this I needed a tape recorder! I purchased the above Grundig DCR 001 data cassette recorder as well as some blank cassettes and a couple of commercially-prerecorded ones to do so. The DCR 001 has a few nice features that make it great for loading programs:

  • A dedicated "data" mode that sets the output level at an appropriate fixed level – no need to guess about finding a suitable volume level.
  • An optional "monitor" in data mode that lets you listen to the data on the tape as it's loading.
  • A "phase" switch that can be used to reverse the phase output, to compensate for the case where the data has been recorded with a 180° phase shift.
  • An "Automatic Programme Detecting System" that lets you skip ahead to the next program or back to the previous one by pressing Rewind or Fast Forward when Play is pressed – this stops when it detects a silent gap between recorded sections of data on the tape.
Tape interface circuit for the Sega Master System.

Above is the cassette interface circuit I came up with. It's quite simple and has a notable lack of analogue sections (no op-amp chips here!) – it uses a NOT gate with a 10KΩ negative feedback resistor to turn the analogue signal from the tape recorder's earphone output into a clean digital signal that can be fed into the Sega Master System. I've tested this with an SN74LS04N, SN74HCU04N and SN74F04N and all worked well, however for best results I'd recommend the SN74LS04N. The filtering capacitors clean up some high-frequency pulses/glitches that may otherwise end up on the output; this is not something I found was much of a problem with a cassette recorder or the audio output from my phone or PC, but a pocket digital voice recorder I have seems to produce glitchy high-frequency pulses in its output (I'm not sure if that's an artefact of its DAC or in the MP3 compression it uses for its voice clips) and those capacitors clean up the signal enough to be able to read it reliably.

The remote motor control relay is a reed relay, and must be a low current device to avoid overloading the Master System's controller power supply and to also allow it to be driven directly by the hex inverter chip. I found the EDR201A0500 perfect for this role!

A grubby ALBA tape recorder.

Being able to save and load back programs on one cassette recorder is fair enough, but to really be sure my hardware and software are working as they should I thought I should see if I was able to save a program to tape on one tape recorder and then load the same program back on a different tape recorder. To this end I bought the above cassette recorder. It was clear from the listing that the record button and counter reset button were damaged, and the whole thing was quite grubby, but I thought it worth a punt.

Getting inside was very easy as all but one of the screws was missing, and it was clear that someone had got there before me as the damaged plastic parts (including two of the main screw posts as well as the snapped-off parts of the record button and counter reset mechanism) had been removed at some point. After giving the tape path a very thorough clean and replacing one of the drive belts that was turning into a tarry mess I was able to get it to play a tape, so I took everything out of the enclosure to give that a good scrub and prepared to fix the damaged plastic parts.

Repairing the record button.

By tracing the arm from one of the other buttons onto a piece of scrap ABS plastic I was able to make a replacement arm for the damaged record button, which I then glued on with cyanoacrylate and some two-part epoxy resin to fill in the gaps. The result is not especially pretty but it does the job and my blobby repair is not going to be visible unless you take the recorder apart.

Repairing the counter reset button.

The counter reset button was a bit more fiddly; the reset mechanism seems to rely on the "n" shaped bit of plastic shown above in the top left photo, and though it looked like something used to be attached to it that had snapped off I wasn't sure what it would have originally looked like. I cut up some more scraps of ABS sheet to make up a new counter reset button which seems to work pretty well, though!

A somewhat refurbished ALBA tape recorder.

The final addition was a couple of new knobs for the tone and volume sliders – these are cheap generic parts and they don't quite line up with the markings (the original sliders have off-centre indicators) but overall I think this turned out pretty well, and my main concern – being able to save a program to tape on one machine and then load it back from another – has been thoroughly tested now and I'm happy with the results. My next task is to transplant the circuit from its current breadboard layout to a neat project box!

Page 1 of 49 1 2 3 4 549

Older posts RSSSearchBrowse by dateIndexTags