Dungeon for the SHARP x68000 (on NetBSD)

Dungeon on the x68000

Its been a while since I’ve added a new port of Dungeon (zork!) so here we go!

Building f2c was a snap on the x68000, it just took a while..

Getting data into the VM was easy, just make an ISO image, and mount it.. Getting data out was.. a challenge, as the floppy doesn’t work under NetBSD, and it didn’t seem to want to see my other hard disks, just my root.  Well thankfully it’s virtual so I just did a:

tar -cvf /dev/sd0c dungeon.tar.gz

NEVER do that on a real machine kids!!!

Anyways here you go, for anyone who loves zork & the m68k!

XM6i

While checking out the NetBSD emulation page, I came across this interesting emulator, XM6i, which can run the x68000 NetBSD port.

Wasting no time, I downloaded it, and quickly found out it is all in Japanese… But hell that is what Google translate is for!  Just be forwarned that it’ll translate things like:

# memswitch -w boot.device=ROM; memswitch -w boot.romaddr=0xeac000

into

# Boot.Device Memswitch-w = ROM; Memswitch-w = 0Xeac000 Boot.Romaddr

I was able to get all the system bits, and get it to boot up the ROM!

Sharp boot logo

As you can see, I’m emulating a 68030 with MMU, running at a blazing 25Mhz with 12MB of ram! No doubt this is top of the line!  So I generated the boot floppies as described on the XM6i page, and booted NetBSD.  The boot loader on the x68000 looks kinda cool:

Boot with the daemon!

And after waiting for an eternity, like a real machine I booted up, swapped disks, read some more and then watched the kernel initalize:

NetBSD 5.1 68000

Installation is pretty straight forward, it is like any other NetBSD platform.  Although it is *SLOW*, even after I discovered the ‘turbo mode’ … As shown below:

Turbo mode!

Even in this mode, I’m running 220% faster than the real machine… I’m sure there are more tweaks to do, but my not being able to read Japanese isn’t helping any.

I figured for future’s sake, I’d just 7zip up what I have so far, maybe it’ll save some time for me later if I try this again.. Getting & generating the ROMS was kind of involved.

After an hour I had a base machine installed!

Of course it runs NetBSD!

All my work is here, and my NetBSD 5.1 install (to save yourself an hour+) is here.  Both files will blow out a 2GB disk image… FWIW.

Also if you’ve never used a Japanese keyboard before, they aren’t quite QWERTY with symbol layouts… This cheat sheet will help!

If you don't know where the colon is, vi can be impossible to use.

The Commodore Amiga

I was enjoying that great site, stumbleupon when I came across a commented listing of the Amiga 1.2 ROM. Then it hat hit me, I’ve never really written about some of the great emulators for the Commodore Amiga.

Back when I was in highschool I wanted a Commodore Amiga, as at the time I was stuck with a Commodore 64. However the world was starting to accept the IBM PC swing of things. Windows 3.0 was out, suddenly the protected mode of the 80286 could be exploited for only a few hundred dollars, vs the thousands for a UNIX port, or what OS/2 cost. And of course the big appeal at the time was that you could build your own PC in a kit fashion (well it still is!). So I was toying with the idea of buying this 286 8Mhz board for $30 CDN when I saw this program that a kid had brought in… It needed VGA, but it could apparently emulate a Commodore Amiga!

You can still download it here.

Running it just simply threw up a picture of the Amiga’s insert a workbench diskette, and clicked the drive madly.. Passing it through a hex editor showed a copy of an Amiga ROM tacked on the end, but it didn’t actually emulate anything.

But I didn’t realize it at the time, and it cemented my decision to buy the 286.

Years later and the topic of m68k emulation came up, as there were simple cross assemblers and simulators, and I can remember in college searching to see if anyone had started an Amiga emulator… And there was one project!

UAE

Originally it stood for “Unusable Amiga Emulator” and well it was unusable. But then with enough people starting to flock to the project it suddenly could boot AmigaDOS. I used to use this on MS-DOS back in the day for ‘maximum’ speed. I was able to find one ancient version of this 0.65 that still has an MS-DOS exe. And it runs great under DOSBOX. You can find it here.

And for the heck of it, here is a screen shot with a 1.3 ROM.

UAE 0.65 under DOSBOX

UAE 0.65 under DOSBOX

Naturally transferring disks was a major pain in the butt… I luckily had a friend with a working Amiga and cross dos for AmigaDOS all configured so I could transfer some terminal emulator to my poor Amiga 500 I had picked up at a used hardware store in college. Then I used what I could of ramdisks, compression programs and whatnot to upload via some 50 foot nullmodem cable I had to transfer ADF’s of my workbench disks and an old favorite game of mine, Captain Blood. Even back at the time, Commodore was bankrupt their future was bleak. Getting spare parts then was becoming hard for my Amiga 500. And my 486SX-20 could almost run at an acceptable speed in emulation..

But time marches on.

UAE was then ported to Linux & X11, and the SVGA lib. I had some old RS232 terminal so I could keep on using my machine to ‘work’ and still play console vga stuff like doom for SVGAlib and of course UAE. Now with CPUs in the GHz++ speed range, emulation of a 8Mhz machine with 3 custom chips is more in software then raw cpu speed. The UAE project kind of died off, there hasn’t been any big updates in years, but the CPU core work lives on in all kinds of m68k derived work.

There is no doubt that there is still a few closeted Amiga users out there, but I suspect that we don’t kick up UAE all that much these days.. But it’s still cool to watch it in action.

And of course the demos! One of my favorites was the fairlight 242 demo. Which UAE with a Kickstart 1.3 ROM will run. Even the MS-DOS version!

fairlight 242 UAE for DOS on DOSBOX

fairlight 242 UAE for DOS on DOSBOX

I should add you can find more demos here, and a Win32 version of UAE here.

Aranym, Atari 68040/mmu emulator!

Well it was the weekend, and I was playing with FORTRAN (Language systems fotran to be exact, all 30lb of it!) and anyways to check to FPU & crash issues I though I’d check it out on an actual m68k Macintosh. So as I was using Basilisk II for some stuff, I was wondering if anyone ever did upgrade the CPU emulation to 68040/mmu emulation. And it turns out that the Basilisk II emulation is taken from UAE, which in turn has been used in a few other emulators including aranym.Aranym is “Atari runs on any machine”, and what these guys have done, is fleshed out the UAE 68000 emulation enough to where it will run m68k linux!

Both a windows version and the source can be found here.

Now for the fun part!

You can download a patched kernel here that supports the virtual Ethernet, or just run a stock kernel (no networking though!)

Next you’ll want some kind of root filesystem, I would recommend the ‘etch’ disk which can be downloaded here.

Naturally, you’ll need a config, here is what I’m using..

—8<——8<——8<—

[GLOBAL]
FastRAM = 256
Floppy =
TOS =
EmuTOS =
AutoGrabMouse = No

[LILO]
Kernel = ./vmlinux
Args = root=/dev/hda1 video=atafb:vga16 stram_swap=0
debug=par
Ramdisk =

[ETH0]
Type = bridge
Tunnel = tap0

[STARTUP]
GrabMouse = No Debugger = No

[IDE0]
Present = Yes
IsCDROM = No
ByteSwap = No
ReadOnly = No
Path = etch.img
Cylinders = 2102
Heads = 16 SectorsPerTrack = 63
ModelName = Master

—8<——8<——8<—

Then finally run it like this:

aranym-mmu.exe -l -c linux.conf

I’ll have to play some with the networking to get it going, it seemed straight forward the FAQ here, however I had no luck.

Anyways, it’s no A/UX, but it’s a *NIX like thing on the m68k. Now we just have to beg the Mac people to flesh out the hardware on their emulators to support Linux, OpenBSD, NetBSD & A/UX….

Linux on Aranym

Linux on Aranym

 

Amiga Days

Do you remember the Commodore Amiga?

I certainly do!

While I was busy fiddling with my Commodore 64, a friend of mine got an Amiga in high school. The 64 was cool, but I was simply blown away by the Amiga. To say there was a gulf between the 8 bit machine, and the quasi 32/16 bit machine would be a massive understatement. His Amiga 2000 could do all kinds of neat things, from talk, run IBM XT software at 100% speed via a “bridge board”, not to mention play super snazzy games. It took me a few years to save up to buy my very own Amiga 500, and once I was ready I didn’t have enough money for a bus ride home, so I walked the FIVE miles home toting my Amiga! I was so happy to say the least!! (At least it was summer, it was flat, and there weren’t any tropical waves/hurricanes around…)

While there are a few emulation alternatives for running the old m68000 software on all kinds of machines, I’m going to talk about AROS today.

AROS is to AmigaDOS what Wine is to Windows. Once it became clear that Commodore was going to die, and that AmigaDOS and the Amiga were lost a few brave people decided that they had to take matters into their own hands. Sadly there was lots of in fighting, a tradition of the comp.sys.amiga.advocacy news group where some people get too tied into little details and let little things (like the rise of Microsoft Windows) pass them by. At any rate, Aaron Digulla knuckled down, and start to write a bug for bug clone of AmigaDOS 3.1 in C to run on the IBM PC. The result of which is AROS. It currently will either run hosted on Linux/NetBSD or natively on the i386. There is a port to the Amd64 undergoing right now. AROS even has SDL support.

So this got me thinking..

What if I were to remove all the OpenGL calls from GLFrontier, and ran it as a strictly 2d app on AROS?

So I took the first step, and I trimmed out the OpenGL support from Tom’s fix of Frontier, so it’s completely SDL 2d friendly, and cross compiled it to AROS. I built the first pass on MinGW, and got frame rates of upwards of 1000 on Vista 64!

Now for the fun part of building an AROS version. While there is now a native GCC for AROS it cannot compile the assembly listing from GLFrontier.. I suspect it’s a heap overflow. This means you have to cross compile. I have cygwin installed in a Windows 2000 VM I use with Virtual PC 2007. I’m not sure if cygwin installs on Vista, let alone Vista 64, however I do suspect it MAY have issues… I keep my dev stuff in a VM so I can move it around without losing my settings.

I downloaded and unpacked the following files into my cygwin installation:

i386-aros-cross-gcc-3.3.1-cygwin.zip

libsdl.a

And the SDL include directory from cygwin.. I think its SDL version 1.2

I did have to find all the ‘exe’ files and make sure they were chmoded +x as the compiler would not run (chmod +x /usr/local/bin/exe /usr/local/i386-aros/bin/ /usr/local/lib/gcc-lib/i386-aros/3.3.1/*exe ). Once you are ready you should be able to build files with

i386-aros-gcc

I’m not sure how to build stripped files, but I suspect it’s out there somewhere. At any rate, I did this to compile my SDL 2d version of FrontierGL:

$ cd as68k

$ make
gcc -O2 -g -Wall -c -o output.o output.c
gcc -O2 -g -Wall -c -o output_c.o output_c.c
gcc -O2 -g -Wall -c -o output_i386.o output_i386.c
output_i386.c:981:1: warning: “_S” redefined
In file included from output_i386.c:6:
/usr/include/ctype.h:35:1: warning: this is the location of the previous definition
output_i386.c: In function x_loadea':
output_i386.c:1373: warning: 'out_reg' might be used uninitialized in this function
output_i386.c: In function
x_loadval’:
output_i386.c:1474: warning: ‘reg3’ might be used uninitialized in this function
output_i386.c:1474: warning: ‘out_reg’ might be used uninitialized in this function
gcc -O2 -g -Wall -c -o as68k.o as68k.c
as68k.c: In function `asm_pass1′:
as68k.c:663: warning: ‘size’ might be used uninitialized in this function
as68k.c:671: warning: ‘coutput_label’ might be used uninitialized in this function
gcc -O2 -g -Wall -c -o dict.o dict.c
gcc -O2 -g -Wall output.o output_c.o output_i386.o as68k.o dict.o -o as68k

$ cd ..

$ as68k/as68k.exe –output-i386 fe2.s
Pass 1
Pass 2
Done! 539337 bytes and 759 relocations.

$ i386-aros-gcc -c fe2.s.S

$ i386-aros-gcc -O2 -I /usr/local/i386-aros/sys-include/sdl -c audio.c
audio.c: In function Audio_Init':
audio.c:334: warning: passing arg 5 of
SDL_LoadWAV_RW’ from incompatible pointer type

$ cd src

$ i386-aros-gcc -O2 -I /usr/local/i386-aros/sys-include/sdl -c hostcall.c

$ i386-aros-gcc -O2 -I /usr/local/i386-aros/sys-include/sdl -c input.c

$ i386-aros-gcc -O2 -I /usr/local/i386-aros/sys-include/sdl -c keymap.c

$ i386-aros-gcc -O2 -I /usr/local/i386-aros/sys-include/sdl -c main.c

$ i386-aros-gcc -O2 -I /usr/local/i386-aros/sys-include/sdl -c screen.c
screen.c: In function `draw_control_panel’:
screen.c:274: warning: assignment makes integer from pointer without a cast

$ i386-aros-gcc -O2 -I /usr/local/i386-aros/sys-include/sdl -c shortcut.c

$ i386-aros-gcc *.o ../fe2.s.o -lsdl -o ../frontier

$ cd ..

$ file frontier
frontier: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

$ i386-aros-size frontier
text data bss dec hex filename
2580672 2036 1422076 4004784 3d1bb0 frontier

*REMEMBER as68k has to actually run on the host machine, so it needs to be native, you cannot use a cross compiler for that. However you do cross compile it’s output.

Naturally you’ll now want to run your exe!

For testing the binaries you’ll need some kind of Aros system, I recommend WinAROS, it’s a pre-built Qemu package, so the disk will work on all kinds of platforms. You can download it here: WinAros Developer

This is a pretty snazzy setup, I recommend booting into a 32bit depth display option, however you will want to modify the default script to look like this at the last line:

qemu.exe -L . -m 256 -localtime -boot c -hda WinArosHD.img -no-kqemu -net nic -net user

The next thing you’ll want to do is enable the networking. I don’t know why it’s disabled by default, but with a few moments in the CLI, and edit you can have it running:

To get the network running you have to go into Extras:Networking/Stacks/AROSTCP/db and edit static-routes, netbd-myhost, and interfaces.

First edit interfaces and uncomment the line that has device prm-rtl8029 and change the IP to 10.0.2.15

Second edit netbd-myhost and make it look like this:
HOST 10.0.2.15 arosbox.arosnet arosbox
DOMAIN arosnet 10.0.2.
NAMESERVER 10.0.2.3

Third edit static-routes and change the address to 10.0.2.2

Last add the following line to your user-startup
Execute Extras:Networking/Stacks/AROSTCP/S/startnet.

Now reboot. Open a shell and verify that you have a connection with “ifconfig -a”
You can also try to ping a website, but you might not get any return packets because of QEMU’s built in firewall. You should at least see the ip address for the site you ping. Or ping 10.0.2.2 to make sure you network is communicating with Qemu.

Now for the final moment, put your exe on a web server, and simply use wget to get it! I’d recommend zipping up your work directory, so it includes the ‘bin’ file, and the structure that GLFrontier expects. I like the zip file format as WinAROS includes unzip.

I do the following from AROS

Wget http://192.168.1.10/front.zip
Unzip front.zip

It’s that easy! Now you can either ‘cd’ or click on your frontier, and away it should go!

The video is a bit wonky in that it seems to only work in 8 bit or 24bit depths. So far I’ve only tested this in WinArosDeveloper.

It actually works, the keyboard is buggy as hell, but you can play with the mouse. The first key code seems to work, then it gets stuck, so I recommend the ‘enter’ key so you can thrust…

I’ve published my zip up to The AROS Archives with any luck when it’s there I’ll update it with a link to it. In the mean time, I’ll provide a dump of the screen.c that I fixed to remove the OpenGL support. Naturally blogspot will screw up the formatting, however it should work…

#include
#include “main.h”
#include “../m68000.h”
#include “screen.h”

/* new stuff */
enum RENDERERS use_renderer = R_OLD;
int len_main_palette;
unsigned short MainPalette[256];
unsigned short CtrlPalette[16];
int fe2_bgcol;
int mouse_shown = 0;
unsigned long logscreen, logscreen2, physcreen, physcreen2;
unsigned long VideoBase;
unsigned char *VideoRaster;
unsigned int MainRGBPalette[256];
unsigned int CtrlRGBPalette[16];
int screen_w=320;
int screen_h=200;
BOOL bGrabMouse = FALSE;
BOOL bInFullScreen = FALSE;
SDL_Surface *sdlscrn;

static const unsigned char font_bmp[] = {
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x80,0x80,0x80,0x80,0x80,0x0,
0x80,0x0,0x0,0x2,0xa0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x50,
0xf8,0x50,0x50,0xf8,0x50,0x0,0x0,0x6,0x20,0xf0,0xa0,0xa0,0xa0,0xa0,0xf0,0x20,
0x0,0x5,0x0,0xc8,0xd8,0x30,0x60,0xd8,0x98,0x0,0x0,0x6,0xa0,0x0,0xe0,0xa0,
0xa0,0xa0,0xe0,0x0,0x0,0x4,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,
0xc0,0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0x0,0x3,0xc0,0x40,0x40,0x40,0x40,0x40,
0x40,0xc0,0x0,0x3,0x0,0x0,0x20,0xf8,0x50,0xf8,0x20,0x0,0x0,0x6,0x0,0x0,
0x40,0xe0,0x40,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x80,
0x0,0x2,0x0,0x0,0x0,0xc0,0x0,0x0,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x0,
0x0,0x0,0x80,0x0,0x0,0x2,0x0,0x8,0x18,0x30,0x60,0xc0,0x80,0x0,0x0,0x6,
0xe0,0xa0,0xa0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x40,0xc0,0x40,0x40,0x40,0x40,
0xe0,0x0,0x0,0x4,0xe0,0x20,0x20,0xe0,0x80,0x80,0xe0,0x0,0x0,0x4,0xe0,0x20,
0x20,0xe0,0x20,0x20,0xe0,0x0,0x0,0x4,0x80,0x80,0xa0,0xa0,0xe0,0x20,0x20,0x0,
0x0,0x4,0xe0,0x80,0x80,0xe0,0x20,0x20,0xe0,0x0,0x0,0x4,0xe0,0x80,0x80,0xe0,
0xa0,0xa0,0xe0,0x0,0x0,0x4,0xe0,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x4,
0xe0,0xa0,0xa0,0xe0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0xe0,0xa0,0xa0,0xe0,0x20,0x20,
0xe0,0x0,0x0,0x4,0x0,0x0,0x0,0x80,0x0,0x80,0x0,0x0,0x0,0x2,0x0,0x0,
0x0,0x80,0x0,0x0,0x80,0x80,0x0,0x2,0xe0,0x0,0xe0,0xa0,0xa0,0xa0,0xa0,0x0,
0x0,0x4,0x0,0x0,0xe0,0x0,0xe0,0x0,0x0,0x0,0x0,0x4,0xc0,0x0,0xe0,0xa0,
0xe0,0x80,0xe0,0x0,0x0,0x4,0xe0,0x20,0x20,0xe0,0x80,0x0,0x80,0x0,0x0,0x4,
0xfe,0x82,0xba,0xa2,0xba,0x82,0xfe,0x0,0x0,0x8,0xf0,0x90,0x90,0x90,0xf0,0x90,
0x90,0x0,0x0,0x5,0xf0,0x90,0x90,0xf8,0x88,0x88,0xf8,0x0,0x0,0x6,0xe0,0x80,
0x80,0x80,0x80,0x80,0xe0,0x0,0x0,0x4,0xf8,0x48,0x48,0x48,0x48,0x48,0xf8,0x0,
0x0,0x6,0xf0,0x80,0x80,0xe0,0x80,0x80,0xf0,0x0,0x0,0x5,0xf0,0x80,0x80,0xe0,
0x80,0x80,0x80,0x0,0x0,0x4,0xf0,0x80,0x80,0x80,0xb0,0x90,0xf0,0x0,0x0,0x5,
0x90,0x90,0x90,0xf0,0x90,0x90,0x90,0x0,0x0,0x5,0xe0,0x40,0x40,0x40,0x40,0x40,
0xe0,0x0,0x0,0x4,0xf0,0x20,0x20,0x20,0x20,0x20,0xe0,0x0,0x0,0x4,0x90,0xb0,
0xe0,0xc0,0xe0,0xb0,0x90,0x0,0x0,0x5,0x80,0x80,0x80,0x80,0x80,0x80,0xe0,0x0,
0x0,0x4,0x88,0xd8,0xf8,0xa8,0x88,0x88,0x88,0x0,0x0,0x6,0x90,0xd0,0xf0,0xb0,
0x90,0x90,0x90,0x0,0x0,0x5,0xf0,0x90,0x90,0x90,0x90,0x90,0xf0,0x0,0x0,0x5,
0xf0,0x90,0x90,0xf0,0x80,0x80,0x80,0x0,0x0,0x5,0xf0,0x90,0x90,0x90,0x90,0xb0,
0xf0,0x18,0x0,0x5,0xf0,0x90,0x90,0xf0,0xe0,0xb0,0x90,0x0,0x0,0x5,0xf0,0x80,
0x80,0xf0,0x10,0x10,0xf0,0x0,0x0,0x5,0xe0,0x40,0x40,0x40,0x40,0x40,0x40,0x0,
0x0,0x3,0x90,0x90,0x90,0x90,0x90,0x90,0xf0,0x0,0x0,0x5,0x90,0x90,0x90,0xb0,
0xe0,0xc0,0x80,0x0,0x0,0x5,0x88,0x88,0x88,0xa8,0xf8,0xd8,0x88,0x0,0x0,0x6,
0x88,0xd8,0x70,0x20,0x70,0xd8,0x88,0x0,0x0,0x6,0x90,0x90,0x90,0xf0,0x20,0x20,
0x20,0x0,0x0,0x5,0xf0,0x10,0x30,0x60,0xc0,0x80,0xf0,0x0,0x0,0x5,0xa0,0x0,
0xa0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x80,0xc0,0x60,0x30,0x18,0x8,0x0,
0x0,0x6,0xe0,0xa0,0xa0,0xe0,0xa0,0xa0,0xe0,0x80,0x80,0x4,0xe0,0xa0,0xe0,0x0,
0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf8,0x0,0x6,
0xa0,0x0,0xe0,0x20,0xe0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x0,0xe0,0x20,0xe0,0xa0,
0xe0,0x0,0x0,0x4,0x80,0x80,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x0,
0xc0,0x80,0x80,0x80,0xc0,0x0,0x0,0x3,0x20,0x20,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,
0x0,0x4,0x0,0x0,0xe0,0xa0,0xe0,0x80,0xe0,0x0,0x0,0x4,0xc0,0x80,0x80,0xc0,
0x80,0x80,0x80,0x0,0x0,0x3,0x0,0x0,0xe0,0xa0,0xa0,0xa0,0xe0,0x20,0xe0,0x4,
0x80,0x80,0xe0,0xa0,0xa0,0xa0,0xa0,0x0,0x0,0x4,0x80,0x0,0x80,0x80,0x80,0x80,
0x80,0x0,0x0,0x2,0x40,0x0,0x40,0x40,0x40,0x40,0x40,0xc0,0x0,0x3,0x80,0x80,
0xb0,0xe0,0xe0,0xb0,0x90,0x0,0x0,0x5,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x0,
0x0,0x2,0x0,0x0,0xf8,0xa8,0xa8,0xa8,0xa8,0x0,0x0,0x6,0x0,0x0,0xe0,0xa0,
0xa0,0xa0,0xa0,0x0,0x0,0x4,0x0,0x0,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,
0x0,0x0,0xe0,0xa0,0xa0,0xa0,0xe0,0x80,0x80,0x4,0x0,0x0,0xe0,0xa0,0xa0,0xa0,
0xe0,0x20,0x30,0x4,0x0,0x0,0xc0,0x80,0x80,0x80,0x80,0x0,0x0,0x3,0x0,0x0,
0xc0,0x80,0xc0,0x40,0xc0,0x0,0x0,0x3,0x80,0x80,0xc0,0x80,0x80,0x80,0xc0,0x0,
0x0,0x3,0x0,0x0,0xa0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x0,0xa0,0xa0,
0xe0,0xc0,0x80,0x0,0x0,0x4,0x0,0x0,0x88,0xa8,0xf8,0xd8,0x88,0x0,0x0,0x6,
0x0,0x0,0xa0,0xe0,0x40,0xe0,0xa0,0x0,0x0,0x4,0x0,0x0,0xa0,0xa0,0xa0,0xa0,
0xe0,0x20,0xe0,0x4,0x0,0x0,0xf0,0x30,0x60,0xc0,0xf0,0x0,0x0,0x5,0x81,0x8d,
0xe1,0xa0,0xa0,0xa0,0xa0,0x0,0x0,0x9,0x2,0x1a,0xc2,0x80,0xc0,0x40,0xc0,0x0,
0x0,0x8,0xfe,0xfc,0xf8,0xfc,0xfe,0xdf,0x8e,0x4,0x0,0x7,0x7f,0x3f,0x1f,0x3f,
0x7f,0xfb,0x71,0x20,0x0,0x8,0x4,0x8e,0xdf,0xfe,0xfc,0xf8,0xfc,0xfe,0x0,0x8,
0x20,0x71,0xfb,0x7f,0x3f,0x1f,0x3f,0x7f,0x0,0x7,0xff,0x81,0x81,0x81,0x81,0x81,
0x81,0xff,0x0,0x9,0x0,0x0,0xe0,0x80,0x80,0x80,0xe0,0x40,0xc0,0x4,0x60,0x0,
0xe0,0xa0,0xe0,0x80,0xe0,0x0,0x0,0x4,0xc0,0x0,0xa0,0xa0,0xa0,0xa0,0xe0,0x0,
0x0,0x4,0x40,0xa0,0x40,0x40,0x40,0x40,0x40,0x0,0x0,0x4,0x40,0xa0,0xe0,0x20,
0xe0,0xa0,0xe0,0x0,0x0,0x4,0x40,0xa0,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,
0x40,0xa0,0xe0,0xa0,0xe0,0x80,0xe0,0x0,0x0,0x4,0xe0,0x0,0xa0,0xa0,0xa0,0xa0,
0xe0,0x0,0x0,0x4,0xc0,0x0,0xe0,0x20,0xe0,0xa0,0xe0,0x0,0x0,0x4,0xe0,0xa0,
0xa0,0xa0,0xe0,0xa0,0xa0,0x0,0x0,0x4,0xc0,0xa0,0xa0,0xc0,0xa0,0xa0,0xc0,0x0,
0x0,0x4,0xe0,0x80,0x80,0x80,0x80,0x80,0xe0,0x0,0x0,0x4,0xc0,0xa0,0xa0,0xa0,
0xa0,0xa0,0xc0,0x0,0x0,0x4,0xe0,0x80,0x80,0xe0,0x80,0x80,0xe0,0x0,0x0,0x4,
0xe0,0x80,0x80,0xe0,0x80,0x80,0x80,0x0,0x0,0x4
};

static inline void read_m68k_vertex (int st_vptr, int output[3])
{
output[0] = STMemory_ReadLong (st_vptr);
output[1] = STMemory_ReadLong (st_vptr+4);
output[2] = -STMemory_ReadLong (st_vptr+8);
}

struct ZNode {
unsigned int z;
struct ZNode *less, *more;
void *data;
};

#define MAX_OBJ_DATA (2<<17)
static unsigned char obj_data_area[MAX_OBJ_DATA];
static int obj_data_pos;
#define MAX_ZNODES 1000
static struct ZNode znode_buf[MAX_ZNODES];
static int znode_buf_pos;
static struct ZNode *znode_start;
static struct ZNode *znode_cur;

enum NuPrimitive {
NU_END,
NU_TRIANGLE,
NU_QUAD,
NU_LINE,
NU_BEZIER_LINE,
NU_TEARDROP,
NU_COMPLEX_SNEXT,
NU_COMPLEX_START,
NU_COMPLEX_END,
NU_COMPLEX_INNER,
NU_COMPLEX_BEZIER,
NU_TWINKLYCIRCLE,
NU_PLANET,
NU_CIRCLE,
NU_CYLINDER,
NU_BLOB,
NU_OVALTHINGY,
NU_POINT,
NU_2DLINE,
NU_MAX
};

#define MAX_QUEUED_STRINGS 200
struct QueuedString {
int x, y, col;
unsigned char str[64];
} queued_strings[MAX_QUEUED_STRINGS];
int queued_string_pos;
static bool no_znodes_kthx;

/*********PROTOTYPES****************/
static void _BuildRGBPalette (unsigned int *rgb, unsigned short *st, int len);
static void draw_3dview (struct ZNode *node);
static int DrawChar (int col, int xoffset, char *scrline, int chr);
static void Nu_DrawPrimitive (void *data);
static inline int znode_rdlong (void **data);
static void add_node (struct ZNode **node, unsigned int zval);
static void znode_insert (struct ZNode *node, unsigned int zval);
static inline void end_node ();
static inline void znode_databegin ();
static inline void znode_wrlong (int val);

int DrawStr (int xpos, int ypos, int col, unsigned char *str, bool shadowed)
{
int x, y, chr;
char *screen;

x = xpos;
y = ypos;

if ((y > 192) || (y<0)) return x;
set_line:
screen = LOGSCREEN2;
screen += SCREENBYTES_LINE * y;

while (*str) {
chr = *(str++);

if (chr < 0x1e) {
if (chr == ‘\r’) {
y += 10;
x = xpos;
goto set_line;
}
else if (chr == 1) col = *(str++);
continue;
} else if (chr == 0x1e) {
/* read new xpos */
x = *(str++);
x *= 2;
continue;
} else if (chr < 0x20) {
/* Read new position */
x = *(str++);
x *= 2;
y = *(str++);
goto set_line;
}

//if (x > 316) continue;

if (shadowed) {
DrawChar (0, x+1, screen+SCREENBYTES_LINE, chr-0x20);
}
x = DrawChar (col, x, screen, chr-0x20);
}

return x;
printf (“DrawStr [%s]\n”,str);
return 0;
}

void Nu_PutColoredPoint()
{}

void Nu_ComplexSNext()
{}
void Nu_DrawComplexSNext()
{}

void Nu_DrawComplexStart()
{}
void Nu_DrawComplexEnd()
{}

void Nu_ComplexStartInner()
{}
void Nu_DrawComplexStartInner()
{}
void Nu_ComplexBezier()
{}
void Nu_DrawComplexBezier()
{}

void draw_control_panel()
{
unsigned int *pal;
// Lock surface if needed
if (SDL_MUSTLOCK(sdlscrn))
if (SDL_LockSurface(sdlscrn) < 0)
return;

// Declare a couple of variables
int y, x, yofs, ofs;

// Draw to screen
yofs = 0;
pal=MainRGBPalette;
for (y = 0; y < screen_h; y++)
{
if(y==168)pal=CtrlRGBPalette; //bottom has differnet palette
for (x = 0, ofs = yofs; x < screen_w; x++, ofs++)
{
//((unsigned int*)sdlscrn->pixels)[ofs] = pal[VideoRaster[ofs]];

switch (sdlscrn->format->BytesPerPixel)
{
case 1: // 8-bpp
{
Uint8 *bufp;
bufp = (Uint8 *)sdlscrn->pixels + y*sdlscrn->pitch + x;
*bufp =(Uint8*) pal[VideoRaster[ofs]];
}
break;
case 2: // 15-bpp or 16-bpp
{
Uint16 *bufp;
bufp = (Uint16 *)sdlscrn->pixels + y*sdlscrn->pitch/2 + x;
*bufp = pal[VideoRaster[ofs]];
}
break;
case 3: // 24-bpp mode, usually not used
{
Uint8 *bufp;
bufp = (Uint8 *)sdlscrn->pixels + y*sdlscrn->pitch + x * 3;
if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
{
bufp[0] = pal[VideoRaster[ofs]];
bufp[1] = pal[VideoRaster[ofs]] >> 8;
bufp[2] = pal[VideoRaster[ofs]] >> 16;
} else {
bufp[2] = pal[VideoRaster[ofs]];
bufp[1] = pal[VideoRaster[ofs]] >> 8;
bufp[0] = pal[VideoRaster[ofs]] >> 16;
}
}
break;
case 4: // 32-bpp
{
Uint32 *bufp;
bufp = (Uint32 *)sdlscrn->pixels + y*sdlscrn->pitch/4 + x;
*bufp = pal[VideoRaster[ofs]];
}
break;
}

}
//yofs += sdlscrn->pitch / 4;
yofs += sdlscrn->pitch / sdlscrn->format->BytesPerPixel;
}

// Unlock if needed
if (SDL_MUSTLOCK(sdlscrn))
SDL_UnlockSurface(sdlscrn);

// Tell SDL to update the whole screen
SDL_UpdateRect(sdlscrn, 0, 0, screen_w, screen_h);

//printf(“draw_control_panel\n”);
}

void Nu_DrawScreen()
{
_BuildRGBPalette (MainRGBPalette, MainPalette, len_main_palette);
_BuildRGBPalette (CtrlRGBPalette, CtrlPalette, 16);
//printf (“Frame: %d znodex.\n”,znode_buf_pos);
//draw_3dview (znode_start);
if (mouse_shown) {
SDL_ShowCursor (SDL_ENABLE);
mouse_shown = 0;
} else {
SDL_ShowCursor (SDL_DISABLE);
}
draw_control_panel();
//set_main_viewport();

//printf(“Nu_DrawScreen\n”);

}

void Nu_PutBezierLine()
{}
void Nu_DrawBezierLine()
{}

void Nu_3DViewInit()
{
queued_string_pos = 0;
//printf (“3dviewinit()\n”);
znode_buf_pos = 0;
//printf (“%d bytes object data\n”, obj_data_pos);
obj_data_pos = 0;

znode_start = NULL;
znode_cur = NULL;
no_znodes_kthx = FALSE;
}
void Nu_InsertZNode()
{
unsigned int zval = GetReg (4);
if (use_renderer == R_OLD) return;
if (no_znodes_kthx) return;
if (znode_start == NULL) {
add_node (&znode_start, zval);
} else {
znode_insert (znode_start, zval);
}
}

void Nu_PutCircle()
{}
void Nu_DrawCircle()
{}

void Nu_PutOval()
{}
void Nu_DrawOval()
{}

void Nu_PutCylinder()
{}
void Nu_DrawCylinder()
{}

void Nu_QueueDrawStr()
{}
void Nu_IsGLRenderer()
{
SetReg(0,0);
}

void Nu_PutPlanet()
{}
void Nu_DrawPlanet()
{}

void Nu_Put2Line()
{}
void Nu_Draw2Line()
{}

void Nu_PutQuad()
{}
void Nu_DrawQuad()
{}

void Nu_GLClearArea()
{}
void Nu_PutBlob()
{use_renderer=R_OLD;}
void Nu_DrawBlob()
{}

void Nu_Put2DLine()
{}
void Nu_Draw2DLine()
{}

void Nu_PutLine()
{}
void Nu_DrawLine()
{}

void Nu_UnInit()
{}

void Nu_PutTeardrop()
{}
void Nu_DrawTeardrop()
{}

void Nu_PutPoint()
{
printf(“Nu_PutPoint\n”);
}
void Nu_DrawPoint()
{}

void Nu_PutTwinklyCircle()
{}
void Nu_DrawTwinklyCircle()
{}

void Nu_ComplexStart()
{}

void Nu_PutTriangle()
{}
void Nu_DrawTriangle()
{}

void Nu_ComplexSBegin()
{}

void Nu_ComplexEnd()
{}

void Nu_32ViewInit()
{}

void Screen_ToggleRenderer ()
{
use_renderer = R_OLD;
}

void change_vidmode(void);

void Screen_Init(void)
{
change_vidmode();
SDL_WM_SetCaption(PROG_NAME, “Frontier”);
SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_ENABLE);
SDL_EventState(SDL_MOUSEBUTTONUP, SDL_ENABLE);
SDL_ShowCursor(SDL_ENABLE);
use_renderer=R_OLD;
printf(“Screen_Init\n”);
}

void change_vidmode (void)
{
const SDL_VideoInfo *info = NULL;
int modes;

info = SDL_GetVideoInfo ();

assert (info != NULL);

modes = SDL_SWSURFACE;// SDL_ANYFORMAT | (bInFullScreen ? SDL_FULLSCREEN : 0 );

if ((sdlscrn = SDL_SetVideoMode (screen_w, screen_h,
info->vfmt->BitsPerPixel, modes)) == 0) {
fprintf (stderr, “Video mode set failed: %s\n”, SDL_GetError ());
SDL_Quit ();
exit (-1);
}
printf(“change_vidmode %d x %d %d deep\n”,screen_w,screen_h,info->vfmt->BitsPerPixel);
}

void Screen_UnInit(void)
{}
void Screen_ToggleFullScreen()
{
}

static void _BuildRGBPalette (unsigned int *rgb, unsigned short *st, int len)
{
int i;
int st_col, r, g, b;

for (i=0; i>4;
rgb[i] = 0xff000000 | (b<<16) | (g<<8) | (r);
}
}

static int DrawChar (int col, int xoffset, char *scrline, int chr)
{
const char *font_pos;
char *pix;
int i;

font_pos = font_bmp;
font_pos += (chr&0xff)*10;
scrline += xoffset;

if (xoffset < 0) {
font_pos += 9;
return xoffset + *font_pos;
}

for (i=0; i<8; i++, font_pos++, scrline += SCREENBYTES_LINE) {
pix = scrline;
if (xoffset > 319) continue;
if (*font_pos & 0x80) *pix = col;
pix++;
if (xoffset+1 > 319) continue;
if (*font_pos & 0x40) *pix = col;
pix++;
if (xoffset+2 > 319) continue;
if (*font_pos & 0x20) *pix = col;
pix++;
if (xoffset+3 > 319) continue;
if (*font_pos & 0x10) *pix = col;
pix++;
if (xoffset+4 > 319) continue;
if (*font_pos & 0x8) *pix = col;
pix++;
if (xoffset+5 > 319) continue;
if (*font_pos & 0x4) *pix = col;
pix++;
if (xoffset+6 > 319) continue;
if (*font_pos & 0x2) *pix = col;
pix++;
if (xoffset+7 > 319) continue;
if (*font_pos & 0x1) *pix = col;
}
/* width of character */
font_pos++;
i = *font_pos;
return xoffset + i;
}
/*
* znode_start is the head of a btree of znodes, each with a linked list
* of GL display lists to draw (in list order).
*
* Draw this crap starting from biggest value znodes.
*/
static void draw_3dview (struct ZNode *node)
{
if (node == NULL) return;
if (node->more) draw_3dview (node->more);

if (use_renderer) {
printf (“Z=%d “, node->z);
Nu_DrawPrimitive (node->data);
}

if (node->less) draw_3dview (node->less);
printf(“draw_3dview\n”);
}

typedef void (*NU_DRAWFUNC) (void **);
NU_DRAWFUNC nu_drawfuncs[NU_MAX] = {
NULL,
&Nu_DrawTriangle,
&Nu_DrawQuad,
&Nu_DrawLine,
&Nu_DrawBezierLine,
&Nu_DrawTeardrop,
&Nu_DrawComplexSNext, // 6
&Nu_DrawComplexStart,
&Nu_DrawComplexEnd,
&Nu_DrawComplexStartInner, // 9
&Nu_DrawComplexBezier,
&Nu_DrawTwinklyCircle,
&Nu_DrawPlanet,
&Nu_DrawCircle,
&Nu_DrawCylinder,
&Nu_DrawBlob,
&Nu_DrawOval,
&Nu_DrawPoint,
&Nu_Draw2DLine
};

static void Nu_DrawPrimitive (void *data)
{
int fnum;

for (;;) {
fnum = znode_rdlong (&data);
//fprintf (stderr, “%d “, fnum);
if (!fnum) return;
nu_drawfuncs[fnum] (&data);
}
}

static inline int znode_rdlong (void **data)
{
int val = *((int*)(*data));
(*data) += 4;
return val;
}

static void add_node (struct ZNode **node, unsigned int zval)
{
assert (znode_buf_pos < MAX_ZNODES);
/* end previous znode display list!!!!!!! */
if (znode_cur) end_node ();

*node = znode_cur = &znode_buf[znode_buf_pos++];
znode_cur->z = zval;
znode_cur->less = NULL;
znode_cur->more = NULL;
znode_databegin ();
}

static inline void end_node ()
{
znode_wrlong (0);
}

static void znode_insert (struct ZNode *node, unsigned int zval)
{
if (zval > node->z) {
if (node->more) {
znode_insert (node->more, zval);
} else {
add_node (&node->more, zval);
}
} else {
if (node->less) {
znode_insert (node->less, zval);
} else {
add_node (&node->less, zval);
}
}
}

static inline void znode_databegin ()
{
znode_cur->data = &obj_data_area[obj_data_pos];
}

static inline void znode_wrlong (int val)
{
*((int*)(obj_data_area+obj_data_pos)) = val;
obj_data_pos+=4;
}

GLFrontier

Frontier Elite

GLFrontier

While on the topic of Frontier Elite this week, I was wondering if they by any chance ever released the source code… It appears not, however there were largely two versions the original being in 68000 assembly then a port to 80286 real mode ASM.
But then I found this:
Tom Morton has taken the Atari ST version of Frontier, and removed the hardware access from the assembly, then tweaked a m68k assembler to either output in C or i386 asm… So he’s basically reversed a copy of Frontier to allow it to run natively!
And he’s added OpenGL support to some degree! It’s VERY cool!
At a minimum I bet there are people out there that would LOVE this guys programs to convert m68k assembly listings into either C or i386 asm. Or a chance to hack the ‘source’ like crazy.
I’ve also come across this great site http://www.jongware.com/galaxy1.html which goes over various algorithms from the game.