Upcoming Trixter Sighting + Retroprogramming
Posted by Trixter on May 15, 2013
June 14-16 you should be able to see me at @party in Boston. (If anyone is looking to share a hotel room, drop me a line!) I am scheduled to give a 30-minute version of the PCjr presentation I had worked on for NOTACON, and hopefully enter a compo or two with some oldskool hardware I will be shipping to arrive ahead of me.
Speaking of entering a compo: I really, really dig retroprogramming. The cool part is, after 10 years of retroprogramming in spare time, my kung fu is getting advanced enough where I not only know how to do what I want in assembly, but I know the fastest possible method to getting it done on the target hardware. For example, I recently implemented a vertical-retrace interrupt in software because the hardware one wasn’t good enough. It’s sick that I know how to do that, but sicker that I know why I need to do that.
I still get a kick out of impressing Jim-of-20-years-ago.
reenigne said
Okay, I’ll bite: a vertical retrace interrupt in software? How do you do that then?
Trixter said
Wha?? It’s YOUR calculations I’m using! (14.31818MHz / 12 / ((912*262) / 12) = 59.92 Hz so if I plug ((912*262) / 12)=19912 in as the PIT interval, the system timer will fire on the same scanline every time. So, reprogram Interrupt 8 (IRQ0) to fire with an interval of 19912 right when vertical retrace starts, et voila, you have a vertical retrace interrupt in software.
PCjr has a real hardware one! Why am I not using it? I know you know the answer :-) but for those not familiar with what we’re doing: Because I want slightly more time to do things before the screen starts drawing. I programmed PCjr’s VINT (IRQ5) to change the border color so I could see where it was firing and I saw nothing, which means it really is firing right as the beam is going back up the screen. However, there is a border around the drawable area, so by making my own interrupt that fires right after the last scanline is drawn, I get some extra time to do things “invisibly” as long as I’m not changing the border color itself.
Code for timing when to start the interrupt:
reenigne said
Ah, okay – I thought it must be something like that but I was confused because I didn’t know (or had forgotten) that the PCjr has a hardware vertical retrace interrupt, and couldn’t think of a machine that did and which this trick would work on. Also, I wouldn’t describe that as “implemented in software” – it’s still a hardware interrupt, it just comes from a different piece of hardware. But I’m nitpicking – I look forward to see what effects you make with this!
Trixter said
Well, it’s a “video hardware vertical retrace interrupt” simulated in software, how’s that? :-)
Unfortunately, I discovered last night that the PCjr palette register mechanism will output random garbage while the palette change is in progress, which is likely why they built a hardware vertical retrace interrupt into the system — so that you could change the entire palette without affecting the picture. So they traded one type of “CGA snow” for another…! And your tricks for getting the system into lockstep don’t work on PCjr, it has a completely different DRAM refresh mechanism that is handled by the video circuitry. Finally, I found that something — I’m not sure what yet — can actually halt the system timer for short periods of time on PCjr (likely something to do with the NMI). I had a border change built into the interrupt so I could see where it was firing, and at some point after some keyboard and joystick handling, it started firing in the middle of the screen!
In other words, I’m not sure what kinds of raster effects are possible with these glitches, but I’ll experiment.
The PCjr is likely easier to get into lockstep *because* it doesn’t have DMA — everything is handled by the CPU. But I’m going to go back to PC+CGA programming before I try to get that deep into PCjr.
reenigne said
Ah, that snow is annoying. I guess lockstep is the way to go for that then. Hope the PCjr’s wait states are as cooperative as the CGA’s were.
The apparent system timer halt is very strange – I just looked at the schematic and the system timer clock depends only on signals which are coming straight from the 8284, so NMI shouldn’t be able to affect it. Are you by any chance doing 2 interrupts per frame (9956 count) and getting a skipped interrupt due to running with interrupts off for ~8ms? Otherwise it sounds like a faulty 8253, which is sometimes going into the wrong phase. If you’re using mode 3, it might work better in mode 2.
Trixter said
I’m definitely able to reproduce it now, and it’s always by pressing a key, and the PCjr doesn’t have a keyboard controller (CPU does everything) so I think your theory has merit. I will also try to reproduce it in mode 2 (I am indeed setting it to mode 3).
Trixter said
Crap, no I’m not, already in mode 2. oh well, I’ll just re-sync the interrupt after a keypress I guess :-/
Peter Lund said
You don’t need a vertical retrace interrupt for this trick. You can poll the status register and synch “manually” at first and then use a timer value that is a little to short so you start your interrupt handler with a little loop to wait for the actual blanking interval start.
Trixter said
That’s exactly how I coded the software vertical retrace interrupt in IntroJR (I wanted a little extra raster time; the hardware VINT, while a cool addition on that platform, fires only at the start of vertical retrace)