Showing posts with label hacks. Show all posts
Showing posts with label hacks. Show all posts

Monday, November 1, 2021

Handheld RC2014 System (RetroChallenge (sorta))

One of the great things about making stuff is that you can make stuff that doesn't yet, or shouldn't exist.  

I honestly didn't get anything done on my RC2014 projects for RetroChallenge this year, other than an idea, and some 3D printed stuff within the final few days of the month.

I've had it in my head for a while to make a gameboy formfactor RasPi system for a while now, even though I already have a portable Pi emulation system in my Atari Lynx enclosure.  So I found a model for the "super retropipod" enclosure on Thingiverse and printed it out, and ordered and then modified a 3.5" lcd and shoved it all into the case.


I decided i didn't want to make a PCB or hack up a perfboard to support tact switches, and I had a bunch of largeish 12mm tact switches, so I modeled and 3d printed mounting boards for those too.


Then I had an awesome-horrible idea.  I would mount a RC2014 inside the enclosure as well!  If I managed to make the enclosure a little thicker (about 1cm) I could easily fit a RC2014 mini or micro inside the case along with the pi and all of its fun stuff.  I could even probably also fit in the TMS9918A video card piggybacked onto it inside the enclosure.  So I modeled and printed out the thickness extension too!

Long story short, I have the beginnings of my ultimate multipurpose Pi/RC2014/Llichen-80 handheld!  And she's a chonky beast too!

I modeled and printed a piece to sandwich between the layers of the "pi-boy" enclosure I printed, and added a space for a nice switch for power on the side.  I still need to wire it all up, but I'm on my way to having this thing be AWESOME!  

Although I still want to make a "tall-boy" at some point... take two GB DMG enclosures, and extend the screen space to be taller, and put in a rotated, vertical monitor in the space there.  eg, use a 4" or 5" lcd in portrait instead of a 3.5" in landscape...



Next actions on this project:

  • Wire up the buttons to the GPIO header
  • Wire up the LED on the front panel to the GPIO header
  • figure out a power solution for the system (batteries, recharging, etc)
  • Mounting solution for RC2014 inside the enclosure without it moving around
  • Make a 2-board backplane for the RC2014 so I can also have the TMS board internally
  • Wire the TMS to the monitor too, and figure out a quick way to switch inputs... perhaps two NC momentary buttons that disconnect the monitor from each of the two inputs, so it will auto-switch to the other input. (or short the input to ground via 75Ω resistor?)
Links:

Thursday, August 27, 2020

LaserDisc Capture Device Ecosystem


Diagram of the capture system

I've been doing a bit off and on with my Apple IIc (Early model, upgraded to Rom4X) and my LaserDisc player (Pioneer CLD-V2400), now that I have it all working.   I've created a video switching device (less prototype-ish version of it coming soon) and have made a few different serial interface adapters so I can control the LDP from the Apple IIc, Tandy "Model T" line, and my Amiga.  I plan on having stub BASIC programs for each in github eventually, here on my LaserDisc catch-all repository.

But this brings up the issue that it's a niche project for a very esoteric and specific audience.  That is to say, vintage computer enthusiasts WHO ALSO have a LaserDisc player, WHO ALSO have specific LaserDisc titles... It's the Sega 32X issue all over again. ;)

So... how to bring playability ("play" in the sense of "playing games created" as well as "playing the video discs") to a larger subset of the vintage computer enthusiasts... and also reduce reliance on super heavy players with large spinning plastic discs in them...  Of course the answer is Raspberry Pi!

The Idea 

The basic idea is to use a Raspberry Pi (Zero hopefully) as a standalone LaserDisc Player simulator.  More on that specifically in a future post, but the goal of this post is to talk about getting content for this simulator.  And, yes, there are LD simulators/emulators out there, like "Daphne", but they're generally for Arcade machine use, and simulate older players (like for Dragon's Lair), and they work VERY well, but they're quite expensive.  This will be a solution that may not work for arcade machine applications, but for home/game/toy/experimenter use, it will be super-cheap (no more than $20 total for the Pi + Serial interface... lowering the bar of entry substantially.

So for capturing a disc, One method might be to just capture the audio and composite output of a disc, and have the PI run something like the VLC player application, which might still be the solution, but I thought I'd experiment with making a custom player, since it will probably be cumbersome to do this with VLC, being how there is a large level of control needed.

The issue comes in when you realize that playback requires frame-specific actions being done with the disc itself.  This is usually fine, but for some content, there's a 2-3 pulldown put in to convert the original 24fps film content to 29.97fps NTSC composite-video LaserDisc content.  The short-short version of this is that if you were to just step through frame by frame, you'd see repeated frames, as well as some frames that are interleaved with each other.  This is not what consumers expect when they hit frame-forward or frame-backwards on their player.  Instead, when you use those functions, the player jumps around, skipping duplicated as well as interleaved frames.  This is handled invisibly by the player, as it accesses the frames from the disc, which are marked as being "full frames".  (this is a gross overview, but generally correct-ish.)

So you can capture the video stream, and play that back via VLC (or other media player) but the results won't be accurate to a LDP.  You'll have to manually skip frames, and offset per the 2-3 pulldown... it gets messy, but you can get an "okayish" approximation.  This is what my Javascript "Rollercoaster" laserdisc simulation did.  And it worked decently.  But it's not good enough.

The Domesday Duplicator Project

I had the idea to capture discs in a more "raw" form, so I started looking into what was available for this.  I looked into the Domesday Duplicator for capturing LaserDiscs, and use their "ld-decode" software to decode it and play it back, since it would be ideal.  I could capture the raw RF content stored on the LD, and play it back exactly as a LDP.  There are some issues with this though...

First of all, I do not have the right LaserDisc player to capture the content, nor full documentation about the hack necessary, nor the expensive hardware needed to sample the RF stream... It is a substantial overhead to capture discs.  Perfect for their archival use, but it's massive overkill for playing some homebrew games.

Secondly, for their captures, each side of a disk requires approximately 103 gigabytes of storage space, which is inconvenient. ;)

My Solution

The solution I decided to run with is to simply step through the disc, frame by frame, and capture each composite video frame individually, then capture the audio separately, and sync them back up in the playback application.

Video would be captured frame-specific on the disc... that is to say only unique 480p-ish frames will be captured, so file "32908.png" will be frame 32908.  No need to convert or deal with if a title has 
a 3-2 pulldown, or it's 29.97 fps, or whatever...  Playback of video might be odd, but this could always be augmented with video files for playback of segments, using these files as still-frame files.

For video capture, I'm using my Canon Optura Xi DV camcorder as a video-firewire bridge, and capturing the video frames using imagesnap, which can save jpeg or png images captured from standard Mac video sources, including firewire-DV connected devices.  It could just as easily been done through some USB Composite AV capture device, but I do not have access to one.

Each of the pairs of audio tracks will be captured directly from the analog audio output from the player.  (I have not done this part, but I plan on using sox to do this, probably, although some tests I've done so far have had dropouts while recording... which is less than ideal... audio capture could be accomplished using a more modern computer or recording device...)

The diagram at the top of this post shows this workflow.

For controlling the LDP, I have a simple python script that connects using the standard serial libraries to a USB-Serial interface, which is wired to my player via RS/232 (4800 baud).  I don't have a store-bought USB serial device, but any of them should work fine.  I decided to just throw together something using stuff I had, which can be seen in this image:

This is my USB-RS232 interface. There are many functionally like it, but this one is mine.

There really is nothing special to this, it's just a USB-RS232 adapter.... using an old USB-Ipod serial dock adapter, FTDI extension wire, and then a cobbled-together TTL-RS232 level shifter. :)

Results

All of this is working as expected. (python script will be posted to github soon.)  I have the LDP spin up the disk ("PL"), seek to the lead-out (end) of the side ("FRLOSE"), get the frame count ("F?"), then seek back to frame 0 ("FR00000SE").  Most discs seem to have between 32,000 and 45,000 frames per side, providing about 30 minutes of content.

Each frame of 704x480 (I know, i was expecting 720x480, but this is what I got.) as JPG is about 140 kilobytes, and as PNG is about 600 kilobytes.  The issue with it though is that it was slow to capture.  The frame seek and stepping was quick, but the capture tool was slow, capturing about 27 PNG frames per minute, or about 35 JPG files per minute.  This would be hours to capture a single side of a disc.  Which is fine, since it's completely automated.  It would produce about 7 gigabytes of video frames per side.

I experimented with capturing audio as well.  I couldn't capture from the firewire/DV stream, but I just hooked the LDP directly in to the Mac Mini I was testing with.  I used SOX to capture some content, and it had a few dropouts.  This could have been because the computer is ancient... So more tests are necessary on that front.

The plan for the capture software is to have it query the LDP to get more meta-content out of the disc as well.  It can get data about the disc, player serial number, number of audio tracks, etc.  From that it could completely automate capturing each of the two potential pairs of  audio streams, or as individual tracks, depending on the needs of the disc... as well as all video frames, and perhaps a DV stream as well... maybe.  


Remember to set the DV Camcorder/Bridge for "video in"

Currently, I've got the software doing the following process:

  • Initialize the player:
    • "PL" Spin up the disc, and "Play"
    • "FRLOSE" When that's done, seek to the frame at the lead-out at the end of the disk
    • "F?" Query to get the current frame number (the number of frames)
    • "FR1SE" seek back to frame 1 on the disc (*)
    • "SR" Step in reverse, back 1 step (*)
  • For each frame:
    • "FRxSE" seek to frame x (the current frame number)
    • run: "imagesnap outdir/x.png" to capture a video frame to a PNG file


This is currently working.  Eventually, I'll add in the additional commands to query available audio tracks, and run "sox -d discname_audio.wav" to capture that.

Saturday, November 9, 2019

RC2019-10 - A102 project - The end of the month of hacking



The short version is that I was super productive on these projects this past month.  I didn't complete it, but I never realistically thought I would be able to.  I lost a week's worth of time, or so, prepping our yearly Halloween Hack (blog post soon)... not to mention losing some time to work on building my Lego Saab 900... (blog post soon too).
One thing I will say, is that by combining the projects together, I tricked my brain into quite effectively "being okay with" working on one project or another, by them all being part of the same project.  So I would say that the month was quite successful.


So Anyway, I'm going to first go through a bunch of goals for the month, for the RC challenge, and in general, and briefly discuss my progress on them at a meta-level.  Then I'll get more into details about the actual work.

Overview and goals


Raspberry Pi / Emulation

I wanted to get the Pi 3 configured and booting right into an emulated  Amiga/Amibian environment.  I got the pi configured with standard raspian instead of Amibian, since I wanted this to be more of a general use machine.  It'd be nice to be able to use it for firmware development of the LL530 as well as the machine that it's targeted for.

So the target changed on this, but it is complete for now.

LL530 Development

I wanted to have the LL530 (USB Interface to Amiga serial keyboards, Amiga/Atari controllers and mice) fully finished.  Although I did not finish the firmware this month, I got more done on the project this month than I had in the past 6 months.  However, I was able to test the DIN pinout to discover that it's backwards, so I need to rev the board for those...

I didn't fully succeed, but I was successful.... if that makes any sense.

RC2014 Integration

I wanted to have an RC2014 Z80 computer built in as well, that I can connect to via serial port, for doing RC dev work without an emulator.  This aspect sadly got the least amount of attention.  I have an RC2014 mini installed, connected to the serial port on the Pi 3.  I've rewired the connection twice now, and I still cannot get it to connect using this wiring.

I spent time focusing on the other aspects.  So... 25% success.

Integration / Battery / Monitor / Enclosure

Most of the effort this past month was in this area.  I wanted to have the entire thing as a finished unit; to be able to be brought to a coffee shop, pull it out, turn it on and use it wirelessly. I can do all of these things right now with it.

So I would say this aspect was completely successful... although It does need improvements, particularly with the screen.


Installing The Linux

I started with a base Raspian image from their site.  I had the Pi hooked up to a HDMI monitor with USB keyboard and mouse.  After using Balena Etcher to get the image onto an SD card, I booted the  machine up.  I went through the basic setup, and updates.

I launched raspi-config from a terminal window, and went through to  enable ssh, i2c, and serial.

Next I installed some useful software packages:

apt-get install screen fs-uae-launcher stella

I made sure that serial was enabled  in /boot/config.txt,

enable_uart=1

I use screen as my quick and dirty way to connect to the RC2014 which is wired up to the uart on the raspi per the diagram above.  The reset line is wired to GPIO 4, so i use this shell script to "hit the reset button":

#!/usr/bin/python

import RPi.GPIO as GPIO
import time

print "Resetting the RC2014."

# setup GPIO4 as an output
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(4,GPIO.OUT)

# send LOW (reset) for 1 second, then restore HIGH (normal run)
GPIO.output(4,GPIO.LOW)
time.sleep(1)
GPIO.output(4,GPIO.HIGH)

print "Done."
# return to high-z state
GPIO.setup(4,GPIO.IN)

The Red and Green LEDs are wired to GPIO18 and GPIO12, and I can run this script to do a nice fadey display on them:

#!/usr/bin/python

import RPi.GPIO as GPIO
import time

red = 18
green = 12

GPIO.setmode(GPIO.BCM)
GPIO.setup(red,GPIO.OUT)
GPIO.setup(green,GPIO.OUT)

r = GPIO.PWM(red, 100)  # channel=12 frequency=50Hz
g = GPIO.PWM(green, 100)  # channel=12 frequency=50Hz
r.start(0)
g.start(1)
try:
while 1:
for dc in range(0, 101, 5):
r.ChangeDutyCycle(dc)
g.ChangeDutyCycle(100-dc)
time.sleep(0.01)

r.ChangeDutyCycle( 100 )
g.ChangeDutyCycle( 0 )
time.sleep( 1 )

for dc in range(100, -1, -5):
r.ChangeDutyCycle(dc)
g.ChangeDutyCycle(100-dc)
time.sleep(0.01)

r.ChangeDutyCycle( 0 )
g.ChangeDutyCycle( 100 )
time.sleep( 1 )

except KeyboardInterrupt:
pass
r.stop()
g.stop()
GPIO.cleanup()

I may rewire these, or wire up additional LEDs to the ones specified with the Amibian/UAE led indicators, which are defined as GPIO4 for activity, GPIO16 for "Power", and GPIO16 for a clean shutdown button.

LCD Monitor


For a monitor, I'm using a $10 3.5" composite monitor.  I had to do a few things to get it to work however.

I had to hack the power input so that it would run off of 5v.  These are made to be used in cars, so they expect 12v of power.  At the time I did this, there were examples of doing this modification on
other displays, but not this model.  I powered it up using 12v, then probed the outputs in the power supply section for a 5v rail... and I soldered a 5V input there.

Once I had done this, I connected it to the 5v power in the enclosure, and hooked up the video input from the composite output on the Pi 3.

One snag I hit though, is that it wouldn't work right, It would flash on when the Pi booted, but it wouldn't show the desktop. Testing the Pi with HDMI or a known working composite input worked just fine though.

I was trying all sorts of things, and eventually decided upon trying PAL  video modes instead of NTSC, and that worked.  I spent some time tweaking the overscan settings as well, to stretch the screen to fit.  I also noticed that the contrast viewing range was substantially better on the top side of the display, so I ended up mounting it in the enclosure upside down, and I flip the video in the pi's config too.

So the changes that all this amounts to for /boot/config.txt are:

disable_overscan=1
display_rotate=2

overscan_left=0
overscan_right=0
overscan_top=5
overscan_bottom=5

sdtv_mode=2
sdtv_disable_colourburst=0

framebuffer_width=320
framebuffer_height=288

Although, as you can see from the screenshot above, it's basically unreadable.  So I was able to get it to work, but any future development on this will need to be with a different display.  Something with at least 480 rows, so that Amiga emulation can be reasonable on it.

Combining it all, and the Future...

I spent a few evenings rewiring that keyboard which mostly works really well.  I'm using a 5000mAh battery and get an undetermined-but-better-than-my-old-iBook amount of time with it.

The display is garbage.  I'm currently looking into replacing it with an HDMI-based 4" Waveshare IPS display with an 800x480 resolution for about $40.  Surely that will require moving around hardware inside of this enclosure, and since the display is meant to piggyback on the Pi, I will lose my integration board.

Obviously, I'll need to install the Amiga emulator, Tandy 102 emulator, my Model-T-Shell, and the Arduino IDE so that I can continue development on the LL530

In short, I'm super happy with where things are now, it just needs some tweaks to get it to be usable as a primary system. :D

Wednesday, October 2, 2019

RC2019-10 - The Globbing Of The Projects... Globjects?



Hey.  Long time no post.  How y'all doing?  I'm still here. I've gotten a lot of small things done over the past half year, and a lot of things almost done as well... and some long-standing projects not done too.  So, I've been almost productive...  Anyway, I hope to try something different this month for the RetroChallenge RC2019-10...  Let me explain...

The main projects I've been trying to work on recently are:


LL530 USB interface for Amiga serial keyboards and controllers

I've been poking at it a little over time, and am really damn close to getting the proper firmware done for it, but I just haven't finished it.  Which is stupid because I can actually sell these things once I'm ready!  I have keyboard working for all but my A1000 keyboards, and I have joystick/mouse/paddle working... but not at the same time in a way that I'd be proud of.  I also will eventually need to rev the board to fix three layout issues; a power/ground short, lack of ICSP programming header, and lack of pull-up resistor for VCS paddle sampling.


Llichen-80 Computer (LL80)

Okay, so it's not really a whole other completely new computer... but it is a specific configuration of the RC2014 Z80 computer.  It started out this year as a whole lot of customizations to standard (but old, obsoleted) RC2014 boards to add bank switching, using the 8 bit parallel IO board (the one with all the LEDs and switches!).   Now, I reworked the idea so that I just use the standard "Switching ROM" board and the "64k RAM" board.  That simplifies the design; making it easier to get to the LL80 spec, since just using those two cards replaces two RAM boards, one ROM board, and one IO board... plus no modifications to any of the boards are necessary.

The other part of the LL80 computer is the "LLSuper" board.  This is an arduino-based supervisor of sorts that sits on the serial console port.  It acts as your usb-serial interface for when you use a desktop computer as a console.  This board used a CH376S USB Drive interface to access any flash drive as mass storage (it's a neat part.. like $2 for a board with a USB A port... it talks TTLRS232, SPI or parallel, and handles all of the disk switching, FAT filesystem etc. So there's very little overhead on a tiny ATmega micro.  I also have an I2C based clock chip board for this.  This sits between your console and the RC, and lets you have a kind of shell access to the disk from the console, as well as from the RC.  The RC side of things also got direct access to virtual disk image files with a sector-based interface, as well as direct fileio...

The next steps would have been to write a CPM BIOS and make the thing boot into that.

But I've come to realize that even the LLSuper board is unnecessary.  I can accomplish near-similar things using the standard  "Pi Serial Console" board.  If i use a RasPi Zero, and boot linux on it (or adapt the code in the PiGFX kernel, I can put in my serial-disk IO stuff, for cheaper, without needing to fab up my own board.  I started to mess around with this using my new RC2014 Micro, a Pi Zero, and a slight hack to attach the reset line of the RC to a GPIO of the Pi, so i can now reset the RC from the Pi.

I do have the protocol all worked out for the serial interface using unused ANSI escape codes, which are made for custom purposes like this.

A102 - Portable Emulated Amiga in a Tandy 102 shell

This is one i've wanted to work on since last year. I was trying to get it done before Rochester MakerFaire last November, but burned out on it.  It essentially is a project that joins together a bunch of parts... all of which I have:

  • Raspberry Pi 3, with Amibian... booting right into an emulated Amiga environment
  • Tandy 102 shell, rescued from some unrepairable 102's
  • Tandy 102 keyboard, also rescued (keys bind as they're pressed though)
  • Amiga 500 keyboard interface board, from a long-gone computer
  • My LL530 USB serial keyboard interface board
  • Amiga mouse
  • 3.5" composite LCD panel (new, $10 online!)
  • large Power Bank battery pack
This project entailed hacking the keyboard (removing the wiring/traces on the board) to convert the scan matrix to match an Amiga 500 keyboard.  This gets connected to the LL530, which is plugged into the Pi.  All of it gets jammed into the 102 shell, and becomes a portable computer. 

I waffled a bit on this... mainly because the keyboard stuff would be a chore.  I want to remove every key, and clean their travel tubes, to eliminate the keys binding.  Wiping out the traces and rewiring the board seems like it's going to be a tedious process... So i kept thinking that maybe I should make a cherry-mx switch based board to fit the keyboard space instead... and... yeah... i just kept going down that same path of "maybe i should do this other thing" instead... instead of actually moving forward on any of it.

I also pondered putting the entire Llichen 80 computer into this shell... which brings us to...

RC2019-10!

So that's where RC2019-10 comes in.  Why almost fail at three projects when I can almost fail at ONE project! Seems a lot more efficient!

The end result for this month will be to have a working portable laptop computer that runs Amibian (Linux), RC2014 (via serial connection to the Pi) and general Linuxy stuff.

Or, more granularly, here are the tasks as I see them now: (in no particular order)

  • Finish the Keyboard + Joystick/Mouse firmware for the LL530
  • remove the wires on the 102 keyboard PCB
  • clean the travel tubes on the keyboard
  • rewire the keyboard to match the Amiga's matrix
  • Wire the keyboard to the Amiga 500 interface board
  • Connect the RC2014 Micro via the Pi's serial interface pins
  • Additional buttons on the device to cleanly shut it all down
  • Have it all powered from a 5V/USB powerbank mounted internally
  • Serial-console textmode app for Linux that provides the beginnings of a backchannel to 
Stretch goals:
  • Full drive interface for the RC2014
  • CP/M BIOS for the RC2014 that uses the serial protocol
  • Fit the RC2014 Mini + 64k RAM + switching ROM + TMS9918A cards inside the case
  • Have the video switchable between the Pi and the TMS9918A video card

Not sure how far i'll get, but it globs together all of the recent projects in a way that I won't feel like I'm neglecting one project by working on the others... since they're all the same project now. :D

Friday, September 28, 2018

More Laserdisc Stuff! A wild Pioneer CLD-V2400 appears!



I just picked up this Pioneer CLD-V2400 in full working order, and in excellent condition.  It was made in 1993, around the same vintage as my Pioneer CLD-S201... but with one major difference... a SERIAL PORT!


It's missing a couple of the more "industrial" commands that allow it to seek quickly (+/- 100 frames) without noticeable glitches/squelching.. so it's not ideal for laserdisc video games, which were crafted so that you could play a game non sequentially without seeing pauses as the disc seeks.  I guess it's able to move the head super quickly within the VBLANK section of the disk

I'm getting ahead of myself...



This thing has a DB-15 connector On the back for the RS-232 serial interface, which includes TTL Serial (0-5v) and RS-232 serial (+/- 12v).

Since I couldn't find my USB-Serial interface, I tried making a TTL cable, and connecting that via FTDI cable to my Mac... I wasn't able to get it to reliably work. I think it might be a that the FTDI/Mac combo couldn't do the 4800 baud rate or something.





Instead I made a DB15-DB9 Null modem cable, and decided to plug it into the 9 pin serial port on... something?

I had a hard time finding any of my machines with DB9 serial, but eventually remembered that my tiny Toshiba Libretto 50 has one! So yeah! Windows 98 and HyperTerminal it is... and it worked great!

Next, I went through the V2400/V2600 manual, (and the V4400 manual) to figure out some commands that I could do.

I had some experiments I wanted to do with using the "user area" of the on screen text of the player.




First of all, I wanted to see how to do it.. which you can see in this pic.  I had my CAV Duran Duran disc playing, obviously.

My thought is that I can do thing similar to the "Rollercoaster" project and just command the thing to play scenes, but it can be taken a step further.

Another option available is to get a user number press from the remote.  The user presses 0..9 and you get that back through the serial port.

It would be possible to make a modern game or interactive video thing using onscreen text for the output, and remote for the input.






The display area on this player is 10 lines of 20 characters each.  Not a lot, but enough for activities.

Perhaps I could encapsulate the game and logic inside of an Arduino would work... but that still brings up the TTL serial issue.










I scoured my basement, looking for my Belkin USB-Serial dongle, which I'm starting to believe I never actually had... I eventually gave up and decided to kludge together this monstrosity.

The nice serial cable I made was a null-modem cable, but the serial level interface (blue board) had the wrong gender and pins for my use, so i tacked on some wires to the correct connector.

The Arduino is a Pro Micro (ATmega 32u4/"Leonardo") made for another project. so it already had the microSD socket and external FTDI connector for a serial peripheral, so this went together substantially quicker than looking for the USB interface.



Regardless, this somehow worked... really well.  I needed to make a simple Arduino program that just reads in from "Serial" port, the USB side of the Leonardo and writes to the "Serial1" port, which is on pins D0 and D1.

The trick was to have both open at 4800 baud.  I had the LD side at 4800 baud, and the USB side at 115200, but that didn't work.

I've made it so I can type on my mac, and control the player... or have the Arduino autonomously control the player.


One of the things you can monkey with is disabling the squelch of the video and audio.  This is what blanks/blues the screen and mutes the audio while seeking, or while doing pause in CLV mode.  When it's off, you can play multispeed/stillframe with audio, stillframe on CLV (which doesn't really work, but it's neat!) and do chapter seeks while still seeing the content.  It's really fun to mess around with...

I think I need to make a script that seeks to the end of the disc to get the duration, then randomly seeks around, plays a second or two, and then repeats that... Especially with squelch off!

Tuesday, August 14, 2018

Commanding Laserdiscs

Coming soon...
For the past couple evenings, I've been poking at controlling video playback programmatically... I was inspired by Kevin Savetz' recent project to resurrect the Rollercoaster Apple ][ Laserdisc game.  He got it working, fixed it, enhanced it to work for the DVD version of the game, and was showing it off at KansasFest.

My first quick hack, as seen before on this blog, was to screen-scrape an Infocom game (Hitchhiker's Guide to the Galaxy), and based on text from that, force VLC to play back certain frames or tracks of video from the Hitchhiker's Guide TV show.

I've been poking at actually making Rollercoster be playable inside the browser for my next trick. I'm basing it all on the source code, which Kevin has made available to us, and using a HD transfer of the movie, which hopefully is the same edit of the film as the Discovision Laserdisc.

There will be more on this later, but the short version is that I'm using jsbasic to run Applesoft Basic right in the browser (no emulation of an Apple ][ ), simulating the Super Serial port (6551 ACIA chip), capturing the BASIC game's laserdisc commands being sent to said serial port, and then using that information to control a fakeo-laserdisc player, which is just an HTML 5 video player.  I'm still working through all of this.  The cool thing is that when I'm done with this, it could be a great test system for people wanting to make more LD-AppleII games.  As long as you use video files that can be properly frame-associated with real discs, it should be a drop-in kind of thing.

NOTE: if I learn more information, I'll note it in this post.  I'm really green when it comes to Apple II hardware, and really Apple II programming in general. This is really my first deep-dive into Apple II serial hardware and specifics of Applesoft BASIC!

Super Serial card

The Super Serial for this game is in slot 2, and is fitted with a 6551 ACIA serial interface chip. Writes to the ACIA get sent out immediately, they are not buffered.  The ACIA has one bit on its status port 0x08 or b00001000 that goes high when there's a byte to read.  The LDP will send a 'R' when its current task is complete.

The Super Serial card, being in slot 2 means that its four registers are at decimal locations:

  • 49320 - Data 
    • Read from here to read characters sent to the Apple
    • Write to this to send out characters to the LDP
  • 49321 - Status
    • Read from here to get error codes, 
    • Read and mask off 0x08 to get the "is a character ready to be read from the LDP?
  • 49322 - Command
  • 49323 - Control
    • These two are used to configure the port, for baud rate, parity, etc.  For this project, I'm simulating the behavior of the device at a very high level, so i basically ignore all of this stuff.
    • The real hardware runs at 4800 baud, 8-N-1
This means that to write a character (newline) out to the LDP:
  • POKE 49320,13

LDP Simulation

Anyway. there's been some interest in others wanting to simulate the Laserdisc player (LDP) using other methods (using VLC for example), so I thought I'd just do a quick post to explain my current understanding of the specific commands used by the game. You can look up specifics of the protocol in the LD-V4400 User's Manual, or in the DVD-V8000 User's Manual  All commands are two-letter sequences, uppercase (although the manual says that it accepts lowercase as well.) and can have a number BEFORE the opcode.

There are a lot of commands that these can handle, but these are the commands that we care about for this game:

FR
Go into "frame mode".  This means that any addresses will be in number of frames from the start of the disc.  Frame 0 is the first frame on the disc, the final frame is dependent on the duration of the disc.  CAV discs are about 30 minutes of content. at 29.97FPS (NTSC), that is roughly 54,000 frames.

(address) SE
Seek to the address (frame number) and go into still-frame mode.  Reading from the ACIA, 

(address) PL
Play, and go to still-frame mode when the address (frame number) is reached.

Additionally, the game's command strings use '/' to indicate a carriage return (CR) character, which is sent as decimal value 13.  The player will then execute the command, and will send back an "R" character (decimal 82) when it completes.

Let's go through a couple real examples...


"FR2818SE/"
  • Switch the LDP into frame mode
  • Seek to frame 2818, and still-frame there
  • LDP will send "R" when it has completed.
AKA: Still frame on frame 2818, will send "R" when done.


"FR2134PL/"
  • Switch the LDP into frame mode
  • From the current position, play until the frame number reaches 2134, and still-frame there
  • LDP will send an "R" when it has completed
AKA: Play until frame 2134, will send "R" when it reaches there.

"FR6726SE/FR6959PL/"
  • Switch the LDP into frame mode
  • Seek to frame 6726, and stillframe
  • LDP will send "R" when ready
  • (switch to frame mode)
  • Play until frame 6959, and then stillframe
  • LDP will send "R" when ready
AKA: Play from frame 6726 through 6959, send "R" when done.

Game implementations

The serial port configuration and setup is at line 31000.  The sequence it does is that it POKEs 11 to 49322, and 28 to 49323, which sets up the serial port configuration (baud, parity, etc).  It also does something with CHR$(4); "PR#2" or "PR#0".  I'm honestly not entirely sure what those are for, something with sending data to the serial card.

The BASIC code to send the command strings is at line 40000, and the command string is stored in VC$.  So in the program you'll see stuff like:
34000 VC$ = "FR2818SE/": GOSUB 40000 
34011 VC$ = "FR6726SE/FR6959PL/": GOSUB 40000
You already know what these do from the above examples!


The LDP communication code at 40000 is:
40000  REM  PLAY VIDEO CLIP
40010  IF  NOT DISC THEN  RETURN
40020  FOR I = 1 TO  LEN (VC$)
40030  IF  MID$ (VC$,I,1) = "/" THEN  POKE 49320,13: WAIT 49321,8:J =  PEEK (49320): GOTO 40060
40040  POKE 49320, ASC ( MID$ (VC$,I,1))
40060  NEXT I
40070  RETURN
Or, in human readable terms:
  • if "DISC" is set 0, then there's no VDP, so just return
  • For each character of the command string:
    • if the character is a '/', then send the VDP a carriage return, and wait for "R" response
    • otherwise just send the current command string character to the VDP

The code also uses the "WAIT" command, which was not implemented in the javascript library I was using.  This command essentially blocks, and waits until the conditions are met.  In the above code it essentially is PEEKing at 49321 (ACIA status) for bit 8 to be set; for a character to be ready to read in.. It then reads the character to variable J, which is then ignored. ;)  But it knows the LDP is done with the task.