PC-FX

The PC-FX is a video game system by NEC and Hudson Soft.

I became interested in it in late April 2014. Being a Virtual Boy programmer, it appealed to me as it is based on the NEC V810 architecture. I started collecting information about it and here is a summary of everything I know. I hope this helps those who are interested in writing homebrew software for the PC-FX.

I do not actually own a PC-FX because of the high price and shipping cost.

Currently, this page is a dumping ground, but it may be better organized in the future.

I do not guarantee any accuracy of this information. Use at your own risk.

My PC-FX games

Example code

All of this code requires at least MV810ASM - see Development software below. Also see the rest of this page for more programming notes.

Documentation

The documentation for the 7up chips is intended for the PC Engine, but it also applies to the PC-FX.

Development software

I will primarily concentrate on DOS and Win32, and how to develop using only legally obtainable software (not Hudson's original development software, which is hard to legally obtain).

MV810ASM

MV810ASM is my V810 assembler. It is flexible, well-documented, and very easy to use.

You can assemble your code and create a PC-FX CD image with a simple batch file.

@MV810ASM %1 temp.bin %2 %3 %4 %5 %6 %7 %8 %9
@IF NOT ERRORLEVEL 1 PCFX-CDLINK makecd.txt cdout

It requires PCFX-CDLink (makecd.txt is its configuration file) - see below.

PCFX-CDLink

PCFX-CDLink (or "pcfx-cdlink" for the nihilistic) is a program by Alex Marshall that generates PC-FX CD images. You will need it regardless of whether you use MV810ASM or GCC. It is part of Eris - see below.

The program requires a text file that specifies the CD metadata. For example:

binary temp.bin
name Untitled
maker Matej Horvat
makerid MH!
date 20141223
country 1
version 256

GCC

For Win32, there is a precompiled version available. It also runs on DOS with the HX DOS extender.

For other platforms, you will have to get the source code and patches and compile it yourself. Good luck, because I haven't been able to do it on Win32 with Cygwin, OS X, or Haiku. Rumor has it that it cannot be compiled with GCC 3 or later (quality!) and apparently not even Haiku's patched GCC 2.95 is good enough.

Alex Marshall has written a library for GCC called Eris. You can download my precompiled version, which also includes Win32 versions of the BinCat and PCFX-CDLink programs and has makefiles adjusted for use in Windows. Note: my version is based on the revision from March 31, 2012, so you will have to apply any changes made since then yourself (and then please share them with me). Or you can ask nicely and I will do it.

You will probably want to use batch files to automate usage of GCC as much as possible. First, you will have to set environment variables:

@REM Set this to your GCC directory. The variable name is of no significance,
@REM but it is used by Eris makefiles.
@SET V810DEV=X:\gccpcfx

@REM Set your PATH to include GCC and more, e.g. PCFX-CDLink and the MagicKit
@REM PC Engine assembler.
@SET PATH=%V810DEV%\bin;%PATH%

@REM (In the lib directory, the subdirectories "eris" and "eris\low" must exist
@REM for Eris.)
@SET LIBRARY_PATH=%V810DEV%\lib
@SET C_INCLUDE_PATH=%V810DEV%\include

Then, to compile a minimal C project where the whole program fits into RAM and nothing is loaded from the CD (as I haven't experimented with that yet), something like this (assuming that environment variables are already set):

@ECHO OFF

REM Compile object files. In this example, we only use one. Using more is left
REM as an exercise for the reader.
gcc -I%V810DEV%\include -mv810 -O2 main.c -c -o temp.o

REM Add libraries and produce an ELF executable.
ld temp.o -L%V810DEV%\lib\ -lgcc -T pcfx.ld -o main.elf

REM Create a raw executable from ELF.
objcopy -O binary -R .stack -R .zdata main.elf temp.bin

REM Concatenate (or just pad in this case) the raw executable.
REM pcfxout.bin is the output file, pcfxlbas.h contains the CD sector numbers
REM of concatenated files.
bincat pcfxout.bin pcfxlbas.h temp.bin
REM In this example, we do everything in one step, so this file isn't needed:
DEL pcfxlbas.h

REM Make a CD image (cdout.cue and cdout.bin) with metadata from pcfxcdlk.txt.
pcfx-cdlink pcfxcdlk.txt cdout

REM Produce a disassembly, if you are curious.
objdump -d main.elf > main.lst

REM Delete temporary files.
DEL temptemp.*
DEL pcfxout.bin
DEL main.elf

The batch file above depends on this linker script, here called pcfx.ld. Note: if LD complains about a missing _start symbol, change ENTRY(_start) to ENTRY(__text_start).

MagicKit PC Engine assembler

This assembler is useful because of its ability to convert PCX pictures into the 7up background tile and sprite formats with the .incchr, .inctile, .incmap, .incspr, .incpal, and .incbat directives (see its DOC\PCE\USAGE.TXT file for details).

It is distributed as a DOS executable (BIN\PCEAS.EXE in the archive) and comes with source code which should be possible to compile on other platforms as well.

Emulators

MagicEngine FX appears to be unable to use CD images.

Xe has a nonstandard(?) CD image format that cannot easily be converted from images created with PCFX-CDLink.

Additional information

This section contains information I've found out myself that isn't explicitly mentioned in other documentation.

All assembly code is for MV810ASM (see above).

Booting homebrew code

The PC-FX can boot in three ways:

Alternatively, one could boot from a CD containing a program that would listen to one of the controller ports (or both). Then, a custom (parallel port?) adapter could be used on a PC to "bit-bang" data to the PC-FX. This might be the most convenient option for development (as long as you can fit everything into RAM, or maybe KRAM), but very awkward otherwise.

Corrections to Alex Marshall's documentation

Booting from backup memory

The PC-FX can boot from external (but not internal) backup memory. For this, a certain structure must be present on the backup memory:

OffsetContents
0x28"PCFXBoot" - not "PCFXBOOT" as Alex Marshall's documentation says (8 ASCII characters)
0x30Offset of code on backup memory (word)
0x34RAM address to load to (word)
0x38Number of bytes to load (word)
0x3CStarting PC (word)

To boot from backup memory in Mednafen:

  1. Run Mednafen with any CD image, or insert an audio CD into your CD drive and run Mednafen with the parameters -physcd -force_module pcfx to force the PC-FX module to be used. Note: since version 0.9.38, Mednafen does not support physical CDs anymore.
  2. On exit, it should create a new 64K save file whose name is the CD image's filename (or "cdrom." for a real CD) followed by some kind of hash - if it doesn't, use the debugger's memory editor to play around with the memory at 0xE8000000. Note: I think it's set to compress save files by default, so turn that off first. This file represents the backup memory for that CD. The first 32K are the internal backup memory and the second 32K are the external backup memory.
  3. Use MV810ASM's ROM-hacking mode to set up the "master boot record" (see above) and write your code to the external backup memory in that file.
  4. Run Mednafen with the same parameters and the same CD image or CD, as the file is associated with it. Press Alt+A to pause execution, enter the debugger, place a breakpoint at 0x8000, leave it, resume with Alt+R, and you will see it start executing the code there.

KING BG2/BG3 BAT/CG addresses

The BG2 BAT and CG address registers are 0x28 and 0x29 respectively, not 0x26 and 0x27.

The BG3 BAT and CG address registers are 0x2A and 0x2B respectively, not 0x28 and 0x29.

The gap in register numbers is therefore on 0x26 and 0x27, not 0x2A and 0x2B.

The size of KING register 0xF

Register 0xF is a word, not a halfword.

KING background notes

7up notes

Registers 0xA to 0xE

These registers specify the resolution and position of the image that the 7up chips produce. According to the Eris source code, they should only be set on 7up A.

Here are some reference values for different Tetsu resolutions:

Register256262 (from Eris 7up sprite example)320262 (obtained by me experimentally in Mednafen)
0xA0x2020x400
0xB0x41F0x629
0xC0x11020x1104
0xD0xEF0xEF
0xE20

Note: if you use my values for 320262, the produced image will exceed the size of the display. To display a sprite at the top-left corner, set its X coordinate to 0x1D and its Y coordinate to 0x40.

Reading the Tetsu raster position and waiting for the next frame

The Tetsu chip has a bug which must be worked around when reading the raster position. It must be read twice and it must be ensured that the read values are the same.

Mednafen only ever returns the first or last raster position. The following code shows how you can use the current raster position to wait for the next video frame (for 262-line modes - not tested on others):

pcfxTetsuWaitFrame:
	; Waits until the start of the next video frame.

	?mov 0x20A0, $12	; Last raster
	?mov 0x3FE0, $13	; Raster mask

	; First, wait until Tetsu is finished with the current frame.
.readAgain1:
	in.h 0x300[$0], $10
	in.h 0x300[$0], $11	; Read twice because of hardware bug
	and $13, $10		; Get the raster
	and $13, $11
	cmp $10, $11
	bne .readAgain1
	cmp $10, $12
	bne .readAgain1

	; Then wait until it starts the next frame.
.readAgain2:
	in.h 0x300[$0], $10
	in.h 0x300[$0], $11
	and $13, $10
	and $13, $11
	cmp $10, $11
	bne .readAgain2
	cmp $10, $12
	be .readAgain2		; This line is different!

	jmp $LP

Special thanks


First published on .
Last updated on .

Table of contents

Contact me