Commodore Plus/4 Emulator `Forever?' documentation




Why Assembler & DOS?!

Used IBM PC hardware resources



Disk Drives


Video subsystem



Main Features Of The Emulator

CPU JAM instructions

I/O Ports Emulation

TED Emulation

Commodore +4 main specifications

C+4 vs C64


CPU and TED Timing

Datasette Emulation


CTF Format

C2F Format

CFG Format

Command Line Parameters


(C) Copyright

Bugs reports

History and the last updates


I think I've created an unique emulator, because I've never seen any Commodore plus/4 (16 or 116) since March 1991... I've also never been an owner of Commodore disk drive. This version of the emulator has created only from some my old and found in Internet documentation (e.g., `c64doc' by John West and Marko Makela, `Extra Instructions Of The 65XX Series CPU' by Adam Vardy) and some advice from Attila Grosz. It's written only in 100% 80486 assembler (16-bit mode).


Reprogramming the timer hardware made impossible to run the emulator from Microsoft Windows GUI environment — use DOS or Windows 95/98/Me DOS mode. For NT/2000/XP, Linux, FreeBSD users — creation a DOS boot disk (or CD-ROM) is a possibility to run this program.

Why Assembler & DOS?!

Why this old nearly completely forgotten OS is used as base for 2007 software? There are several reasons.

  1. The skeleton of the emulator was created in 1996/97 in the existing DOS atmosphere, work was stopped at the beginning of 1998 and resumed only at the end of 2002. So the emulator skeleton contains the spirit of other years.
  2. Author had found that translation to other OS and from assembler to higher level programming language is too difficult now. He has a choice. He can either continue to develop the emulator or begin big work to transfer its code to other systems.
  3. The better emulators are only available for Open Unix-like OS and Microsoft Windows (Plus4emu, Yape). Presented emulator is the best for DOS forever!
  4. Author's computer of the middle of 1990s was 486DX-120 and Assembler was the only choice in attempt to reach 100% performance with it.
  5. The programming in Assembler under DOS without debugger is very difficult and time consumptive — this makes the pleasure of emulator creation longer.

Used IBM hardware resources

The emulator completely takes-over interrupt 9 (keyboard) and intercepts interrupt 8. The emulator uses only base DOS memory. Screen size is selectable. It has direct access to the following ports: 20-21 (programmable interrupt controller); 40, 43 (timer hardware — to set IRQ0 frequency to 37288Hz); 60, 64 (keyboard); 61 (speaker); 201 (joysticks); 388, 389 (Ad Lib); 3C0, 3C1, 3C2, 3C4, 3C5, 3CE, 3CF (VGA); 3D4, 3D5, 3DA (color VGA); 3B4, 3B5, 3BA (mono VGA); 2x6, 2xA, 2xC, 2xE (Sound Blaster, x may be 2,4,6, or 8). Some VGA registers are used only for several video modes.


Some keys description:
Alt-Commodore key
F5-Change sound hardware (beeper, adlib, sb16, none)
F10-Exit to DOS (power off button)
F11-Reset button
Shift-F11-"Hardware" Reset button
F12-Emulator's file system & options
Scroll Lock-Button Play on the datasette
Num Lock-Button Record on the datasette (press only it when message "PRESS PLAY & RECORD ON TAPE" appeared)
SysRq (Alt+PrintScreen)-Immediate exit to DOS (Warning! It can interrupt any operation, e.g. with file)


You can use any combination of real analog joysticks and the keyboard keys for joystick emulation. There are two keys sets for the emulation:

Disk Drives

You can use units 8 and 9. There are two kinds of emulation of Commodore DOS:

  1. for D64-images;
  2. for IBM PC directory (FAT or CD-ROM).

The both emulations allow to use the next BASIC DOS commands and variables: DIRECTORY, DLOAD, LOAD, DSAVE, SAVE, VERIFY, INPUT#, GET#, PRINT#, OPEN, CLOSE, SCRATCH, RENAME, HEADER, COLLECT, DS, DS$, ST, CMD, COPY. The DOS commands U9/UI and U:/UJ are partially supported — they return DOS version in the DS$ and finish all i/o operations. The DOS command I (INITIALIZE) finishes all i/o operations. The DOS command M-R (MEMORY READ) may be used to read C1551 ROM and 5 256 bytes data buffers at addresses from $300 to $7ff. The DOS command P (POSITION) is fully supported.

So you can load/save programs, read/write/copy/rename/delete/... the PRG, SEQ, USR, DEL files, get drive status and see directory in the any kind of the emulation.

The emulation on the D64 images supports direct access U1/UA, U2/UB, B-A, B-F, # and B-P DOS commands that allows to use such programs as Zork, Hitchhiker's Guide, Blazin Forth, etc. The U1/UA can use the sectors map from D64 images which provide it that allows to use the programs (e.g. Typing Professor) from copy-protected disk. The COPY command is not supported for relative files only. The read-only D64-image is considered as write-protected disk by the emulator.

The emulation on the IBM PC filesystems provides support for all types of standard files and some DOS commands (C, R, S, P, N, V). It doesn't support direct access commands like U1, B-A, M-W, etc. The relative files and COPY command are fully supported. The HEADER command simply clears current directory from all not locked (not read-only) PRG and X00 files. The COLLECT command doesn't produce any effect. The read-only files are considered as locked by the emulator.

You can use pattern (like A??B*=P) in any command which allows it (SCRATCH, DIRECTORY, ...). The SAVE/OPEN command supports usage of @ replacement prefix.

The both units are assigned to the current PC directory at the start of the emulator. Use F7 in the menus for reassignments of the units.

Usage of IBM PC filesystems emulation gives more space and flexibility especially for such programs like Austrospeed Basic Compiler or SVS B.A.L. System. So extract files from D64 and get some benefit!

The following table shows all features of the DOS commands emulation.
DOS BASICD64 PC directory
N HEADER + %[1]
C COPY %[3] %[4]
V COLLECT + +[2]
I + +
P (RECORD) + +
U1, UA + -
U2, UB + -
B-R - -
B-W - -
B-P + -
B-A + -
B-F + -
B-E - -
M-R +[5] +[5]
M-W - -
M-E - -
U3..U8, UC..UH - -
U9, UI + +
U:, UJ + +
%R +[7] +[7]
%S -[6] +[7]
%number - -
& - -

[1] - doesn't remove r/o files
[2] - the splat files are impossible for DOS on PC filesystem
[3] - it can't copy relative files
[4] - it can't correctly combine relative files with different record size
[5] - it can be used to access to memory ranges at $300-$7ff (RAM) and $c000-$ffff (ROM). The IEC emulations algorithms is not the exact copy of C1551 subroutines — so the automatic distribution of the 256 bytes buffers for i/o operations may differ from C1551
[6] - the sector interleave is always (except directory) set to 1 (C1551 default is 17)
[7] - does nothing

The following table shows supported OPEN modes.
ModeD64 PC directory
Channel 0 (LOAD) + +
Channel 0 ($) + +
Channel 1 (SAVE) + +
Channel 1 (SAVE@) + +
Channels 2..14 R+ +
Channels 2..14 W @+ +
Channels 2..14 A+ +
Channels 2..14 M- -
Channels 2..14 L+ +
Channels 2..14 $+ +
Channel 15 (COMMAND) + +
SEQ, PRG, USR files+ +
DEL files+ +
REL files+ +


The emulator can use three kind of hardware for sound generation:

  1. Standard PC speaker digital sound at 37287Hz;
  2. Adlib FM sound;
  3. Sound Blaster digital sound at 18643Hz. The direct mode is used, it is a bit slow so it requires at least 300Mhz CPU. The BLASTER environment variable is required to set up Sound Blaster hardware.

Video subsystem

The following modes are supported
#Hardware ResolutionC= Window SizeVideo Card Type
0,7320x200320x200VGA, VBE
6,8400x300368x288Super VGA, VBE

All these modes must be compatible with modern TFT-LCD monitors. Mode 0 is set as default. Second mode number is VBE mode.


Left button-Emulator's file system & options
Right button-exit to DOS


The emulator can possibility to change/add any ROM-chip. When emulator starts it looks for the next ROM-image files in the start-up directory:
8-C1551.ROM-C1551 ROM.

Any of these files must have exactly 16KB length. If one or more of the such files are missed then standard (build-in in the emulator program body) ROM contents will be used instead.

Some ROM images in the Internet have 16386 bytes length (for unknown for me reason 2 bytes added to theirs start) — remove first 2 bytes from them.

Make the separate directory for every cartridge ROM and then run the emulator from the appropriate directory.

It is more convinient way to use ROMs — specify ROM-filenames in the command line parameters. The first column in the above table indicates ROM-bank number.

Main Features Of The Emulator

It supports:
all standard opcodes +
exact opcodes timing +
decimal mode +
extra opcodes support+
RMW instructions algorithm+
build-in port %[1]
interrupts +
video +[2]
sound +[2][3]
timers +
memory management +
interrupts +
keyboard +
double/single clock +
exact CPU timing +
-Parallel i/o chip (6529B) %[4]
-Serial i/o chip (6551A) -
-Keyboard +
-Joysticks +
-Serial Bus -
-Serial Bus devices -
-C-1551 disk drives %[5]
-Datasette +
-ROM cartridges (up to 64K) +

[1] - full support of datasette lines only (Cassette Read/Write/Motor) and bit 5 is always set to 0.
[2] - 99% compatible.
[3] - only for PC speaker, Adlib or Sound Blaster compatible cards. It's nearly impossible to produce digital sound effects on the Adlib-cards family — use Speaker or Sound Blaster to hear them.
[4] - only Cassette Sense line.
[5] - Turbo-Loaders and some operations are still not supported.

Internal features of the emulator:

It can run only on the computer with 80486 compatible CPU (at least P200 is required for 100% speed emulation, DPMI can reduce performance of emulator down more than twice so use pure DOS for maximum performance) and VGA or VESA compatible card.

CPU JAM/HLT instructions

JAM instructions work like hardware reset. If Reset vector points on any HLT type instruction then the emulator begins meditation after reset.

I/O Ports Emulation

FD10-FD1FPIO %[1]

[1] - only Cassette Sense line.

TED Emulation

IndexBit(s)Function Emulation
00 0-7 Timer 1 low byte +
01 0-7 Timer 1 high byte+
02 0-7 Timer 2 low byte +
03 0-7 Timer 2 high byte+
04 0-7 Timer 3 low byte +
05 0-7 Timer 3 high byte+
06 0-2 Screen Vertical Offset+
3 0/1 - 24/25 rows +
4 0/1 - Screen off/on +
5 0/1 - Bit Map off/on+
6 0/1 - Extended color mode off/on+
7 TEST -[2]
07 0-2 Screen Horizontal offset+
3 0/1 - 38/40 columns +
4 0/1 - Multicolor mode off/on+
5 0/1 - Freeze off/on -[2]
6 0/1 - PAL/NTSC -[2][1]
7 0/1 - Hardware reverse on/off+
08 0-7 Keyboard/Joysticks latch+
09 0 unused +
1 0/1 - Request for raster interrupt no/yes+
2 0/1 - Request for light pen interrupt no/yes?[4]
3 0/1 - Request for Timer 1 interrupt no/yes+
4 0/1 - Request for Timer 2 interrupt no/yes+
5 unused +
6 0/1 - Request for Timer 3 interrupt no/yes+
7 0/1 - any TED interrupt request presents no/yes+
0A 0 bit 8 raster interrupt set+
1 0/1 - Mask raster interrupt yes/no+
2 0/1 - Mask light pen interrupt yes/no?[2]
3 0/1 - Mask Timer 1 interrupt yes/no+
4 0/1 - Mask Timer 2 interrupt yes/no+
5 unused +
6 0/1 - Mask Timer 3 interrupt yes/no+
7 unused +
0B 0-7 raster interrupt set, bits 0-7+
0C 0-1 bits 8-9 of cursor position+
2-7 unused +
0D 0-7 bits 0-7 of cursor position+
0E 0-7 bits 0-7 of voice 2 frequency number+
0F 0-7 bits 0-7 of voice 1 frequency number+
10 0-1 bits 8-9 of voice 2 frequency number+
2-7 unused ?[2]
11 0-3 Volume control (from 0 to 8)+
4 Voice 1 select +
5 Voice 2 select +[5]
6 Voice 2 noise select +
7 Sound Reload +[6]
12 0-1 bits 8-9 of voice 1 frequency number+
2 0/1 - Character generator or Bit map in RAM/ROM+
3-5 bits 13-15 (other bits are equal to 0) of Bit map address+
6-7 unused +
13 0 RAM/ROM status +
1 0/1 - Set CPU single clock for overscan off/on+
2 bit 10 of Character generator address, it is usable only when bit 7 of register 7 (Hardware reverse) is set to 1+
3-7 bits 11-15 (other bits are equal to 0) of character generator address+
14 0-2 unused +
3-7 bits 11-15 (other bits are equal to 0) of color memory base+
15 0-3 Color 1 +
4-6 Luminance 1 +
7 unused +
16 0-3 Color 2 +
4-6 Luminance 2 +
7 unused +
17 0-3 Color 3 +
4-6 Luminance 3 +
7 unused +
18 0-3 Color 4 +
4-6 Luminance 4 +
7 unused +
19 0-3 Overscan Color +
4-6 Overscan Luminance +
7 unused +
1A 0-1 bits 8-9 of current character position +
2-7 unused +
1B 0-7 bits 0-7 of current character position+
1C 0 Vertical line bit 8 +
1-7 unused +
1D 0-7 Vertical line bits 0-7 +
1E 0 bit 0 of horizontal dot position %[4]
1-7 bits 1-7 of horizontal dot position +
1F 0-2 Vertical subaddress +
3-6 Blink counter +
7 unused +
3E Selects ROM +
3F Selects RAM +

[1] - always PAL.
[2] - you may use this bit as ordinal RAM storage.
[4] - always 0.
[5] - bit 5 has higher priority than bit 6.
[6] - its value 1 mutes both sound channels for Adlib — for PC speaker and Sound Blaster this bit supported properly.

Commodore +4 main specifications

[1] - raster interrupts can make this limitation softer.

C+4 vs C64

C+4 and C64 are very similar. Why does success come only for C64?

I think it is only one answer: C64 is two years elder! Below I place a table with quality/quantity comparison of the main features of both machines. Who has won this data competition?...

                            C64     C+4     Notes

   Version                  2.0     3.5
   Free memory, bytes       38911   60671
   Total tokens             77      128
   Special disk commands    -       +
   Graphics commands        -       +
   Structural commands      -       +
   Sound commands           -       +
   Joysticks commands       -       +

  Build-in Monitor
    with (dis)assembler     -       +

  Build-in Full Screen Text
    Editor, Spreadsheet
    and DataBase            -       +

  Speed                     =       =       In full screen modes C64 is
                                            slightly faster than C+4, but in
                                            screen blank case C+4 is faster
   Total                    64K     64K
   Holes, byte              4098    548     C+4: CPU=2,IO=512(ACIA=16,PIO=16,
                                                 KBD=16,MAGIC VOICE SOUND=16,
                                            C64: CPU=2,VIC=1024,SID=1024,
                                            * These holes reduce total usable
                                            RAM/ROM capacity

   Total                    2*8K+4K 4*16K   C+4 can work only with one 16K
                            =20K    =64K    Kernal ROM and use other 3 16K
                                            ROM slots in any manner (e.g. to
                                            view/save any ROM chip content)
   Max                      3*8K+4K 8*16K-3*802-546
                            =28K    =128K-2952=125.1171875K
   Total keys               66      67+Reset
   Reset button             -       +
   Design                   worse   better

   Colors                   16      121
   Max. Resolution          320x200 320x200
   Extended mode            +       +
   Multicolor mode          +       +
   Bit Map Mode             +       +
   Hardware cursor          -       +
   256 chars. on screen     +       +
   Hardware reverse         -       +       This allows automatically to
                                            produce inverted characters
                                            saving 2K characters ROM
   38/40 columns modes      +       +
   24/25 rows modes         +       +
   X/Y-scrolling            +       +
   Fixed color RAM          +       -       This makes C+4 more flexible
   Color RAM                0.5K    -       Color RAM helps C64 be some 
                                            faster than C+4 in the text 
                                            modes, and increases free RAM 
                                            storage for some modes
                                            (C+4 takes 1K of main memory
                                            for keeping color information)
   Hardware sprites         +       -       C64 can manage up to 8 24x21
                                            sprites, automatically detects
                                            their collisions, etc.
   Channels                 3       2       C+4's second channel can produce
                                            either white noise or music
   Frequency range          0-      109Hz-
                             3.9KHz  110KHz
   Wave forms               wide    square  C64 can produce various different
                            range   only    types of special sound effects
                                            and high quality music synthesis

   2-bytes timers           4       3       C64 timers have wider range of
                                            working modes than on C+4
   4-bytes RTC              2       -

   NMI                      +       -
   IRQ                      +       +
   Reset                    worse   better  C64 has no simple user usable
                                            Reset switch, C+4 has one
   Interrupts sources
    Cassette Read/
     Serial Bus SRQ         1       -       C64 has 13 types of interrupt
    Timers                  4       3       sources: 4 from VIC, 5 from CIA1
    RTC                     1       -       and 4 from CIA2 - VIC (IRQ),
    Raster                  1       1       CIA1 (IRQ) and CIA2 (NMI) can
    Sprite's                2       -       produce only one interrupt signal;
    Synchro Serial Port     2       -       C+4 has 6 types of internal
    Light Pen               1       1       interrupt sources: 5 from TED and 
    RS-232C                 1       1       1 from ACIA

  Serial Bus                +       +       C+4 doesn't support SRQ line

  Digital Joysticks         2       2

  Paddles                   4       -       This allows to connect to C64
                                            up to 2 4-buttons analog
                                            joysticks (instead 2 digital)

  User Port
   Centronics               1       1       C64 and C+4 can use only RS-232C
   TTL RS-232C              1       1       or Centronics in the same time,
     Max. speed, bauds      300     19200   but not both
   Synchro Serial Ports     2       -

  Datasette                 1       1

  Fast C1551 drives         -       +       These drives connected directly to
                                            the CPU bus, C64 theoretically can
                                            use similar drives...


It's a functional copy of the MS-DOS DEBUGGER. It has almost the same commands set (see table below).

AssembleA A +
Compare C C +
Dump D D +
Enter E E +[1]
Fill F F +[1]
Go G G +[6]
Go Line <miss>GL![6][10]
Hex H H +
Load L L +
Move M M +
Name N N +
watchpOint<miss>O ![7]
Proceed P P +[3][6]
Quit Q Q +[4]
RegisterR R +[12]
Search S S +[1]
Trace T T +[5]
View <miss>V ![2]
Write W W +
cYcle of TED<miss>Y![11]
eXtra <miss> X ![14]
Zoom <miss> Z ![8]
? ? ? +
! !![9]

[1] - It doesn't support string literals (i.e. this command supports only hex literals).
[2] - It shows the plus/4 screen.
[3] - This command is equivalent of G (Go) command with breakpoint set to the next assembler instruction, it is very useful for fast tracing subroutines (JSR) and back loops (BNE, BEQ, ...). Using P for trace JMP instruction or forward conditional branches has no viewable sense.
[4] - It returns to the emulator and turns emulator to the non-debugger mode.
[5] - This command outputs time of instruction(s) execution. It hides interrupts during its execution but the interrupt execution time is displayed. Some interrupt handlers may change interrupt return point — this may throw T-command into endless loop — press F9 in this case.
[6] - After these commands emulator turns into debugger mode. In this mode F9 causes to return to last debugger screen.
[7] - It has the same syntax as G command but instead of breakpoints it sets watchpoints (they break program execution if any byte at given addresses is rewritten).
[8] - It selects 25 or 50 rows debugger mode.
[9] - Immediate exit from emulator.
[10] - It breaks execution at given line.
[11] - This command is TED oriented — it invokes special mode of debugger — any other command returns debugger to the normal mode
[12] - It also shows LINE (TED 1C & 1D registers pair value), POS (TED 1E register) and 2CPU (cycles performed by CPU for current instruction).
[14] - This command shows internal TED and emulated video display values, hardware vectors, and TED registers.

Breakpoint(s) and watchpoint(s) set by G (Go), GL (Go Line), P (Proceed), or O (Watchpoint) commands slow the emulator but only on several percents.

It uses the next mnemonics for (un)assemble CPU commands:

    BRK               ;00           NOP2    #$nn      ;80
    ORA     ($nn,X)   ;01           STA     ($nn,X)   ;81
    JAM               ;02           NOP2    #$nn      ;82
    ASLORA  ($nn,X)   ;03           STXSTA  ($nn,X)   ;83
    NOP2    $nn       ;04           STY     $nn       ;84
    ORA     $nn       ;05           STA     $nn       ;85
    ASL     $nn       ;06           STX     $nn       ;86
    ASLORA  $nn       ;07           STXSTA  $nn       ;87
    PHP               ;08           DEY               ;88
    ORA     #$nn      ;09           NOP2    #$nn      ;89
    ASL               ;0A           TXA               ;8A
    ANC     #$nn      ;0B           TXAAND  #$nn      ;8B
    NOP3    $nnnn     ;0C           STY     $nnnn     ;8C
    ORA     $nnnn     ;0D           STA     $nnnn     ;8D
    ASL     $nnnn     ;0E           STX     $nnnn     ;8E
    ASLORA  $nnnn     ;0F           STXSTA  $nnnn     ;8F
    BPL     $nnnn     ;10           BCC     $nnnn     ;90
    ORA     ($nn),Y   ;11           STA     ($nn),Y   ;91
    JAM               ;12           JAM               ;92
    ASLORA  ($nn),Y   ;13           SHA     ($nn),Y   ;93
    NOP2    $nn,X     ;14           STY     $nn,X     ;94
    ORA     $nn,X     ;15           STA     $nn,X     ;95
    ASL     $nn,X     ;16           STX     $nn,Y     ;96
    ASLORA  $nn,X     ;17           STXSTA  $nn,Y     ;97
    CLC               ;18           TYA               ;98
    ORA     $nnnn,Y   ;19           STA     $nnnn,Y   ;99
    NOP1              ;1A           TXS               ;9A
    ASLORA  $nnnn,Y   ;1B           SHS     $nnnn,Y   ;9B
    NOP2    $nnnn,X   ;1C           SHY     $nnnn,X   ;9C
    ORA     $nnnn,X   ;1D           STA     $nnnn,X   ;9D
    ASL     $nnnn,X   ;1E           SHX     $nnnn,Y   ;9E
    ASLORA  $nnnn,X   ;1F           SHA     $nnnn,Y   ;9F
    JSR     $nnnn     ;20           LDY     #$nn      ;A0
    AND     ($nn,X)   ;21           LDA     ($nn,X)   ;A1
    JAM               ;22           LDX     #$nn      ;A2
    ROLAND  ($nn,X)   ;23           LDXLDA  ($nn,X)   ;A3
    BIT     $nn       ;24           LDY     $nn       ;A4
    AND     $nn       ;25           LDA     $nn       ;A5
    ROL     $nn       ;26           LDX     $nn       ;A6
    ROLAND  $nn       ;27           LDXLDA  $nn       ;A7
    PLP               ;28           TAY               ;A8
    AND     #$nn      ;29           LDA     #$nn      ;A9
    ROL               ;2A           TAX               ;AA
    ANC     #$nn      ;2B           LXA     #$nn      ;AB
    BIT     $nnnn     ;2C           LDY     $nnnn     ;AC
    AND     $nnnn     ;2D           LDA     $nnnn     ;AD
    ROL     $nnnn     ;2E           LDX     $nnnn     ;AE
    ROLAND  $nnnn     ;2F           LDXLDA  $nnnn     ;AF
    BMI     $nnnn     ;30           BCS     $nnnn     ;B0
    AND     ($nn),Y   ;31           LDA     ($nn),Y   ;B1
    JAM               ;32           JAM               ;B2
    ROLAND  ($nn),Y   ;33           LDXLDA  ($nn),Y   ;B3
    NOP2    $nn,X     ;34           LDY     $nn,X     ;B4
    AND     $nn,X     ;35           LDA     $nn,X     ;B5
    ROL     $nn,X     ;36           LDX     $nn,Y     ;B6
    ROLAND  $nn,X     ;37           LDXLDA  $nn,Y     ;B7
    SEC               ;38           CLV               ;B8
    AND     $nnnn,Y   ;39           LDA     $nnnn,Y   ;B9
    NOP1              ;3A           TSX               ;BA
    ROLAND  $nnnn,Y   ;3B           LAS     $nnnn,Y   ;BB
    NOP3    $nnnn,X   ;3C           LDY     $nnnn,X   ;BC
    AND     $nnnn,X   ;3D           LDA     $nnnn,X   ;BD
    ROL     $nnnn,X   ;3E           LDX     $nnnn,Y   ;BE
    ROLAND  $nnnn,X   ;3F           LDXLDA  $nnnn,Y   ;BF
    RTI               ;40           CPY     #$nn      ;C0
    EOR     ($nn,X)   ;41           CMP     ($nn,X)   ;C1
    JAM               ;42           NOP2    #$nn      ;C2
    LSREOR  ($nn,X)   ;43           DECCMP  ($nn,X)   ;C3
    NOP2    $nn       ;44           CPY     $nn       ;C4
    EOR     $nn       ;45           CMP     $nn       ;C5
    LSR     $nn       ;46           DEC     $nn       ;C6
    LSREOR  $nn       ;47           DECCMP  $nn       ;C7
    PHA               ;48           INY               ;C8
    EOR     #$nn      ;49           CMP     #$nn      ;C9
    LSR               ;4A           DEX               ;CA
    ANDLSR  #$nn      ;4B           SBX     #$nn      ;CB
    JMP     $nnnn     ;4C           CPY     $nnnn     ;CC
    EOR     $nnnn     ;4D           CMP     $nnnn     ;CD
    LSR     $nnnn     ;4E           DEC     $nnnn     ;CE
    LSREOR  $nnnn     ;4F           DECCMP  $nnnn     ;CF
    BVC     $nnnn     ;50           BNE     $nnnn     ;D0
    EOR     ($nn),Y   ;51           CMP     ($nn),Y   ;D1
    JAM               ;52           JAM               ;D2
    LSREOR  ($nn),Y   ;53           DECCMP  ($nn),Y   ;D3
    NOP2    $nn,X     ;54           NOP2    $nn,X     ;D4
    EOR     $nn,X     ;55           CMP     $nn,X     ;D5
    LSR     $nn,X     ;56           DEC     $nn,X     ;D6
    LSREOR  $nn,X     ;57           DECCMP  $nn,X     ;D7
    CLI               ;58           CLD               ;D8
    EOR     $nnnn,Y   ;59           CMP     $nnnn,Y   ;D9
    NOP1              ;5A           NOP1              ;DA
    LSREOR  $nnnn,Y   ;5B           DECCMP  $nnnn,Y   ;DB
    NOP2    $nnnn,X   ;5C           NOP3    $nnnn,X   ;DC
    EOR     $nnnn,X   ;5D           CMP     $nnnn,X   ;DD
    LSR     $nnnn,X   ;5E           DEC     $nnnn,X   ;DE
    LSREOR  $nnnn,X   ;5F           DECCMP  $nnnn,X   ;DF
    RTS               ;60           CPX     #$nn      ;E0
    ADC     ($nn,X)   ;61           SBC     ($nn,X)   ;E1
    JAM               ;62           NOP2    #$nn      ;E2
    RORADC  ($nn,X)   ;63           INCSBC  ($nn,X)   ;E3
    NOP2    $nn       ;64           CPX     $nn       ;E4
    ADC     $nn       ;65           SBC     $nn       ;E5
    ROR     $nn       ;66           INC     $nn       ;E6
    RORADC  $nn       ;67           INCSBC  $nn       ;E7
    PLA               ;68           INX               ;E8
    ADC     #$nn      ;69           SBC     #$nn      ;E9
    ROR               ;6A           NOP               ;EA
    ANDROR  #$nn      ;6B           SBC     #$nn      ;EB
    JMP     ($nnnn)   ;6C           CPX     $nnnn     ;EC
    ADC     $nnnn     ;6D           SBC     $nnnn     ;ED
    ROR     $nnnn     ;6E           INC     $nnnn     ;EE
    RORADC  $nnnn     ;6F           INCSBC  $nnnn     ;EF
    BVS     $nnnn     ;70           BEQ     $nnnn     ;F0
    ADC     ($nn),Y   ;71           SBC     ($nn),Y   ;F1
    JAM               ;72           JAM               ;F2
    RORADC  ($nn),Y   ;73           INCSBC  ($nn),Y   ;F3
    NOP2    $nn,X     ;74           NOP2    $nn,X     ;F4
    ADC     $nn,X     ;75           SBC     $nn,X     ;F5
    ROR     $nn,X     ;76           INC     $nn,X     ;F6
    RORADC  $nn,X     ;77           INCSBC  $nn,X     ;F7
    SEI               ;78           SED               ;F8
    ADC     $nnnn,Y   ;79           SBC     $nnnn,Y   ;F9
    NOP1              ;7A           NOP1              ;FA
    RORADC  $nnnn,Y   ;7B           INCSBC  $nnnn,Y   ;FB
    NOP3    $nnnn,X   ;7C           NOP3    $nnnn,X   ;FC
    ADC     $nnnn,X   ;7D           SBC     $nnnn,X   ;FD
    ROR     $nnnn,X   ;7E           INC     $nnnn,X   ;FE
    RORADC  $nnnn,X   ;7F           INCSBC  $nnnn,X   ;FF

You must enter all 2 or 4 digits in operands: don't miss leading zero(s)! This limitation is only applicable for entering 8501 assembler mnemonics, not debugger commands. All spaces are ignored in the entered mnemonics between its natural delimiters (comma, brackets, $, #), e.g. you may enter: BNE$0672, LDA # $ 01, etc.). Some instructions (NOP1, NOP2, JAM, etc.) have the same mnemonics and operands structure: during assembling the minimal appropriate opcode is gotten.

The debugger uses command line editor which is built-in in the any DOS core: thus you may use F1, F2, F3, F4, F5, Insert, Delete, Esc, and BackSpace keys for edit in any kind of DOS. You may also use ^C (Control-C) and ^S (Control-S) keys during text output. Some DOSes have extended command line editors or command like HISTORY.COM which can extend features of the editor.

If you want to save some debugger disassembler or dump output in a file, you may use standard DOS streams redirection technique, e.g.
will start normal emulator execution but after F9 all input will get from CMDS file and all output will send to LISTING. CMDS file must consists of debugger's commands (one command per a line) and last line in it ought to be Q.

The debugger correct works with PRG and supports pure binary formats (with some other formats it can work as with pure binaries).

NOTE! The i/o menus are not available from the debugger, i.e. during execution G, O, or P commands.

CPU and TED Timing

Since version of 1.32 of the emulator the timing becomes 99.9% exact. FLI demos must work.

The emulator maximum frame rate is limited (for synchronization with the real plus/4) to approximately 50.3Hz (it's possible to change emulator speed).

Datasette Emulation

The CTF format is the best (at least for now) for the emulation of datasette. It has some features, which let CTF-file to look slightly better than real cassette.

Before cassette read, you can place datasette's head exactly on desired block (using menus). After reading last block on tape, head automatically moved to the position of the first block (= auto rewind).

The datasette automatically moves head to the start of the tape's free space when the write operation begins. After writing the head is placed on the start of first block on the tape.

WARNING!!! Activation of the tape motor not for i/o operation and then making attempt to access to the Commodore serial bus may produce a block of garbage on the tape (this situation is fully adequate the real one: press play & record on the real datasette with the tape then try to access to the serial bus and you get some unsense noise on the cassette...) or a block starting with garbage (this block may not be recognized in menus). To evade these small inconveniences press PLAY (& RECORD) on tape (Scroll Lock button on the PC keyboard) only after appropriate prompts.

TAP format is also supported for read operations only.


Menus accessible only when debugger is off. They provide a lot of the useful features missed on the real plus/4: freeze/restore current computer state (e.g. save game in any moment), devices manipulation, fast load/save and export/import data and programs, etc.

'Size' column shows size depend on image file type: in bytes for CTF files and in the blocks for D64 ones.

If in the 'Type' column for a block of a CTF file placed '?' (and appropriate size is equal to 0) then this means that this block is a turbo-block or a garbage-block.

Menus support mouse.

CTF Format

CTF — Commodore Tape File. It was developed before TAP format appeared. The CTF is 100% real cassette compatible (like TAP) and provides some structural information which allows to move head position to the beginning of every tape block (like T64). The CTF has unlimited capacity. The T64 doesn't reflect the block nature of CBM method used for writing on the tape. For example, it can't work with data files (via OPEN, PRINT#, CLOSE, ...) and turbo loaders and savers.

It's easy to convert T64 to CTF or CTF to TAP. Backward conversion is not formal and requires some AI. It's nearly impossible to convert general CTF or TAP data to T64 format. Conversion from TAP to CTF is much easier. CTF-file size is several times smaller than for the same data in the TAP format.

TAP is only intermediate format to transfer data from the real tapes. It is the best for its fields but if you want to feel the taste of the full scaled job with datasette (data files, turbo savers, ...) then use CTF! Utility CTF2TAP may always convert CTF-file to the TAP form.

The table below shows CTF-file structure.

6       BLOCK #1 POINTER
        (TO THE END OF
                                POSITION (NNNN)
                                MAXIMUM FREQUENCY WAVES
0BH     DATA             ?
        CONSTANT         1

Data at offset 0BH consist of bits which are value in the CPU datasette port through fix time periods (time constant at 0AH is equal to this period).

Standard Commodore 264 tape block starts and ends with gap from max frequency waves. Each byte of the information has the next structure:

[Bn]=[T0][T1], if [Bn]=0;
[Bn]=[T1][T0], if [Bn]=1.

[SM] - Start of byte Marker, [Bn] - Bit of information number n, [T0] - a max. frequency (=F0) period, [T1] - a period with frequency 2*F0, [T2] - a period with frequency 4*F0. [B9] - a parity bit, odd parity is used. Last byte of block of data contains XOR of all previous bytes. Each block is written to tape two times (with gap between them). The next nine bytes precede a block first time: 89h, 88h, .. 81h; and the next nine bytes precede a block second time: 9, 8, ..1.

Therefore each byte of data on the tape in standard Commodore 264 format occupies (9*6+12)*2=132bits=16.5bytes. The length of block in CTF file (in standard format) is approximately equal to [start gap length =4096]+[gap between blocks length =110]+[end gap length =49]+16.5*([length of block]+10). Many of the turbo savers (like NOVALOAD) may produce less than 3 bytes per each saved byte in a CTF file.

Each block (except program body block) in the standard Commodore 264 tape format after 9 marker bytes contains type specification byte, e.g.:

1 - standard (BASIC) program header (next block loaded at $1001)
2 - data block (created by PRINT# or CLOSE)
3 - machine code program header (next block loaded at a given address)
4 - header of the data file (created by OPEN)
5 - End Of Tape (EOT) marker block.

C2F Format

C2F - Commodore 264 Freeze format. The table below shows its structure.


------- FORMAT SPECIFICATION -----------
0       VERSION         2       1 SINCE VERSION 1.10 OF THE EMULATOR

2       CPU TIME        1       TICKS TO CPU (UNUSED SINCE VER. 1.32)

------- CPU REGISTERS ------------------
3       PC              2
5       SP              2       HIGH BYTE = 1
7       XR              2       HIGH BYTE = 0
9       YR              2       HIGH BYTE = 0
0BH     SR              1
0CH     AC              1

------- CPU PORTS ----------------------
0DH     $0              1
0EH     $1              1

------- MEMORY CONFIGURATION -----------
0FH     ROMMAP          1
10H                     1       BITS 0-1 - SOUND HARDWARE (0-PC,
                                  1-Adlib, 2-None, 3-Sound Blaster)
                                BITS 2-4 - JOYSTICK2 HARDWARE
                                  (0-K1, 1-K2, 2-J1, 3-J2, 4-None)
                                BITS 5-7 - JOYSTICK1 HARDWARE

------- TED ----------------------------
        VALUE           2

13H     LED             1       KBD LED INDICATOR DATA - CapsLock, Play,
                                   and Record buttons state

------- TED ----------------------------
14H     TED REGISTERS   20H(32)

------- RAM ----------------------------
34H     $2-$FFFF        0FFFEH(65534)

CFG file format

First byte is a video mode number multiplied by 2, second byte is a frame skipping determinant (1 — no skips, 3 — to skip 2/3 of frames, 5 — to skip 4/5 of frames, etc.), third byte determines sound card (0 — PC Speaker, 1 — Adlib, 2 — no sound; 3 — Sound Blaster).

PLUS4.CFG is the name of the CFG-file.

It is also possible to load CFG-file with any name (and CFG extension) from the command line.

Command Line Parameters

It is possible to use up to 12 parameters at the command line — the names of PRG/P0N/D64/CTF/TAP/C2F/ROM/CFG-files. These files will be loaded/attached automatically during startup of the emulator.

plus4 a.prg x\b.prg c.p01 e.d64 f.tap
will load `a', `b' (from subdirectory `x'), and `c' programs into memory, attach disk image `e' to device 8, and attach tape image `f'.

It is possible to set exact device number for d64-image by `/8' (default) or `/9' prefix.

So plus4 e.d64 /9g.d64,
will attach disk image `e' to device 8 and disk image `g' to device 9.

Within the parameters list it is possible to set working directory. This setting will affect all followed relative filesystem addresses. The working directory may be set several times in one parameters list.

plus4 c:\cplus4\d64\ disk.d64 /9..\d2.d64 d:\ cbm\a.prg
will set working directory, attach `disk.d64' from it, attach `d2.d64' from `c:\cplus4\', set new working directory, and load `a.prg' from `d:\cbm\'.

NOTE! Do not omit extension for any file name. The working directory must be ended by `\'. The order of parameters is important — the next parameter may override effect of previous one.

The name of the ROM-image file may be preceded by /N, where N is ROM-bank number (to see the table). The default number is 4.

plus4 c:\crt\c16tutor\ c16tutor_1.rom /5c16tutor2.rom,
will load two ROM-images to banks 4 and 5.

It is also possible to set video mode via appropriate parameter. Use `#vid' form to set video mode #.
plus4 1vid
should set video mode to 320x240 — this setting will override default CFG-file setting. The number should be hexadecimal, so you have to use `A' instead of 10.

The sound hardware may be set in the same way. Use `#snd' form to set it. The numbers are the same as in CFG or C2F files.

plus4 1snd
selects Adlib card.

The option ? (question mark) may be used to show summary of command line parameters.


You need FASM V1.67 or newer for sources compilation.

`fasm plus4.asm'
creates the emulator executable file. Use FASM under the pure DOS (without memory managers like EMM386) or with DPMI services or under any Linux.

You must have C+4 ROM images files BASIC.ROM (16K), KERNAL.ROM (16K), 3P1.ROM (32K), and 1551.ROM (16K) in the directory which contains CV subdirectory during compilation. The third and fourth files are unnecessary and may contain anything.

(C) Copyright

Almost all data and program files of this package are written by V.Lidovski in the X/1996-IV/1997;VI-VIII,XII/1998;IV/2000;XI/2002; VII-VIII/2003;II,V-VIII,X,XII/2004;VI-VIII,XI,XII/2005;I,V,VII-VIII/2006; I-III,VIII,XII/2007;I,VIII/2008.

All source code is Copyright (C) 1997-2008 Vladimir Lidovski. This program is distributed under the GNU General Public License, Version 2, or, at your discretion, any later version. The GNU General Public License is available via the Web here. The GPL is designed to allow you to alter and redistribute the package, as long as you do not remove that freedom from others.


Please send messages about any discovered bugs to author's email —

History and the last updates

The first version of this emulator was finally compiled at the 9th of April of 1997. It was uploaded to at the 30th of June of 1997.

The changes list history is here.

v1.42 (VIII-2008)