Expansion Port can contain ROM, RAM, I/O Ports, etc. For ROM, the first 256
bytes would contain the expansion ROM header.
For region 1, the CPU outputs a chip select signal (CPU Pin 98, /EXP).
For region 2, the CPU doesn't produce a chip select signal (the region is
intended to contain multiple I/O ports, which require an address decoder
anyways, that address decoder could treat any /RD or /WR with A13=Hi and A23=Hi
and A22=Lo as access to expansion region 2 (for /WR, A22 may be ignored;
assuming that the BIOS is read-only).
The BIOS initalizes Expansion Region 1 to 512Kbyte with 8bit bus, and Region 2
to 128 bytes with 8bit bus. However, the size and data bus-width of these
regions can be changed, see:
Memory Control
For Region 1, 32bit reads are supported even in 8bit mode (eg. 32bit opcode
fetches are automatically processed as four 8bit reads).
For Region 2, only 8bit access seems to be supported (except that probably
16bit mode allows 16bit access), anyways, larger accesses seem to cause
exceptions... not sure if that can be disabled...?
EXP2 Dual Serial Port (for TTY Debug Terminal)
EXP2 DTL-H2000 I/O Ports
EXP2 Post Registers
EXP2 Nocash Emulation Expansion
Not used by BIOS nor by any games. Seems to contain 1Mbyte RAM with 16bit
databus (ie. 512Kx16) in DTL-H2000.
Aside from the above, the Expansion regions can be used for whatever purpose,
however, mind that the BIOS is reading from the ROM header region, and is
writing to the POST register (so 1F000000h-1F0000FFh and 1F802041h should be
used only if the hardware isn't disturbed by those accesses).
The expansion port is installed only on older PSX boards, newer PSX boards and
all PSone boards don't have that port. However, the CPU should still output all
expansion signals, and there should be big soldering points on the board, so
it'd be easy to upgrade the console.
Note that A0..A23 are latched outputs, so they can be used as general purpuse
24bit outputs, provided that the system bus isn't used for other purposes (such
like /BIOS, /SPU, /CD accesses) (A0..A23 are not affected by Main RAM and GPU
addressing, nor by internal I/O ports like Timer and IRQ registers).
Address Size Content
1F000000h 4 Post-Boot Entrypoint (eg. 1F000100h and up)
1F000004h 2Ch Post-Boot ID ("Licensed by Sony Computer Entertainment Inc.")
1F000030h 50h Post-Boot TTY Message (must contain at least one 00h byte)
1F000080h 4 Pre-Boot Entrypoint (eg. 1F000100h and up)
1F000084h 2Ch Pre-Boot ID ("Licensed by Sony Computer Entertainment Inc.")
1F0000B0h 50h Not used (should be zero, but may contain code/data/io)
1F000100h .. Code, Data, I/O Ports, etc.
The entrypoints are called if their corresonding ID strings are present, return
address to BIOS is passed in R31, so the expansion ROM may return control to
BIOS, if that should be desired.
Aside from verifying the IDs, the BIOS will also display the Post-Boot ID
string (and the following message string) via TTY (done right before calling
the Post-Boot Entrypoint).
The Pre-Boot function is called almost immediately after Reset, with only some
Memory Control registers initialized, the BIOS function vectors at A0h, B0h,
and C0h are NOT yet initialized, so the Pre-Boot function can't use them.
The Post-Boot function gets called while showing the "PS" logo, but before
loading the .EXE file. The BIOS function vectors at A0h, B0h, and C0h are
already installed and can be used by the Post-Boot Function.
Note that the Post-Boot Function is called ONLY when the "PS" logo is shown
(ie. not if the CDROM drive is empty, or if it contains an Audio CD).
One common trick to hook the Kernel after BIOS initialization, but before CDROM
loading is to use the Pre-Boot handler to set a COP0 opcode fetch hardware
breakpoint at 80030000h (after returning from the Pre-Boot handler, the Kernel
will initialize important things like A0h/B0h/C0h tables, and will then break
again when starting the GUI code at 80030000h) (this trick is used by Action
Replay v2.0 and up).
Expansion ROMs are most commonly used in cheat devices,
Cheat Devices
The PSX/PSone retail BIOS contains some TTY Debug Terminal code; using an
external SCN2681 chip which can be connected to the expansion port.
Whilst supported by all PSX/PSone retail BIOSes on software side, there aren't
any known PSX consoles/devboards/expansions actually containing DUARTs on
hardware side.
7-0 Data (aka Character)
The hardware can hold max 2 Tx characters per channel (1 in the THR register,
and one currently processed in the Tx Shift Register), and max 4 Rx characters
(3 in the RHR FIFO, plus one in the Rx Shift Register) (when receiving a 5th
character, the "old newest" value in the Rx Shift Register is lost, and the
overrun flag is set).
7 RxRTS Control (0=No, 1=Yes)
6 RxINT Select (0=RxRDY, 1=FFULL)
5 Error Mode (0=Char, 1=Block)
4-3 Parity Mode (0=With Parity, 1=Force Parity, 2=No Parity, 3=Multidrop)
2 Parity Type (0=Even, 1=Odd)
1-0 Bits per Character (0=5bit, 1=6bit, 2=7bit, 3=8bit)
Note: In block error mode, block error conditions must be cleared by using the
error reset command (command 4) or a receiver reset (command 2).
7-6 Channel Mode (0=Normal, 1=Auto-Echo, 2=Local loop, 3=Remote loop)
5 TxRTS Control (0=No, 1=Yes) (when 1 --> OP0=RTSA / OP1=RTSB)
4 CTS Enable (0=No, 1=Yes) (when 1 --> IP0=CTSA / IP1=CTSB)
3-0 Tx Stop Bit Length (00h..0Fh = see below)
Stop Bit Lengths:
0=0.563 1=0.625 2=0.688 3=0.750 4=0.813 5=0.875 6=0.938 7=1.000
8=1.563 9=1.625 A=1.688 B=1.750 C=1.813 D=1.875 E=1.938 F=2.000
Add 0.5 to values shown for 0..7 if channel is programmed for 5 bits/char.
7-4 Rx Clock Select (0..0Ch=See Table, 0Dh=Timer, 0Eh=16xIP, 0Fh=1xIP)
3-0 Tx Clock Select (0..0Ch=See Table, 0Dh=Timer, 0Eh=16xIP, 0Fh=1xIP)
The 2681 has some sets of predefined baud rates (set1/set2 selected via ACR.7),
additionally, in BRG Test Mode, set3/set4 are used instead of set1/set2), the
baud rates for selections 00h..0Dh are:
Rate 00h 01h 02h 03h 04h 05h 06h 07h 08h 09h 0Ah 0Bh 0Ch
Set1 50 110 134.5 200 300 600 1200 1050 2400 4800 7200 9600 38400
Set2 75 110 134.5 150 300 600 1200 2000 2400 4800 1800 9600 19200
Set3 4800 880 1076 19200 28800 57600 115200 1050 57600 4800 57600 9600 38400
Set4 7200 880 1076 14400 28800 57600 115200 2000 57600 4800 14400 9600 19200
Selection 0Eh/0Fh are using an external clock source (derived from
IP3,IP4,IP5,IP6 pins; for TxA,RxA,TxB,RxB respectively).
7 Not used (should be 0)
6-4 Miscellaneous Commands (0..7 = see below)
3 Disable Tx (0=No change, 1=Disable)
2 Enable Tx (0=No change, 1=Enable) ;Don't use with Command 3 (Reset Rx)
1 Disable Rx (0=No change, 1=Disable)
0 Enable Rx (0=No change, 1=Enable) ;Don't use with Command 2 (Reset Tx)
The command values for CRA (or CRB) are:
0 No command ;no effect
1 Reset MR pointer ;force "FirstAccess" state for MR1A (or MR1B) access
2 Reset receiver ;reset RxA (or RxB) registers, disable Rx, flush Fifo
3 Reset transmitter ;reset TxA (or TxB) registers
4 Reset Error Flags ;reset SRA.7-4 (or SRB.7-4) to zero
5 Reset Break-Change IRQ Flag ;reset ISR.2 (or ISR.6) to zero
6 Start break ;after current char, pause Tx with TxDA=Low (or TxDB=Low)
7 Stop break ;output one High bit, then continue Tx (ie. undo pause)
Access to the upper four bits of the command register should be separated by 3
edges of the X1 clock. A disabled transmitter cannot be loaded.
7 Input Port Change (0=No, 1=Yes) (Ack via reading IPCR) ;see ACR.3-0
6 Break Change B (0=No, 1=Yes) (Ack via CRB/Command5)
5 RxRDYB/FFULLB (0=No, 1=Yes) (Ack via reading data) ;see MR1B.6
4 THRB Empty (TxRDYB) (0=No, 1=Yes) (Ack via writing data) ;same as SRB.2
3 Counter Ready (0=No, 1=Yes) (Ack via CT_STOP)
2 Break Change A (0=No, 1=Yes) (Ack via CRA/Command5)
1 RxRDYA/FFULLA (0=No, 1=Yes) (Ack via reading data) ;see MR1A.6
0 THRA Empty (TxRDYA) (0=No, 1=Yes) (Ack via writing data) ;same as SRA.2
7 Rx Received Break* (0=No, 1=Yes) ;received 00h without stop bit
6 Rx Framing Error* (0=No, 1=Yes) ;received data without stop bit
5 Rx Parity Error* (0=No, 1=Yes) ;received data with bad parity
4 Rx Overrun Error (0=No, 1=Yes) ;Rx FIFO full + RxShiftReg full
3 Tx Underrun (TxEMT) (0=No, 1=Yes) ;both TxShiftReg and THR empty
2 Tx THR Empty (TxRDY) (0=No, 1=Yes) ;same as ISR.0 / ISR.4
1 Rx FIFO Full (FFULL) (0=No, 1=Yes) ;set upon 3 or more characters
0 Rx FIFO Not Empty (RxRDY) (0=No, 1=Yes) ;set upon 1 or more characters
Bit7-5 are appended to the corresponding data character in the receive FIFO. A
read of the status provides these bits (7:5) from the top of the FIFO together
with bits (4:0). These bits are cleared by a "reset error status" command. In
character mode they are discarded when the corresponding data character is read
from the FIFO. In block error mode, block error conditions must be cleared by
using the error reset command (command 4x) or a receiver reset.
7 Select Baud Rate Generator (BRG) Set (0=Set1/Set3, 1=Set2/Set4)
6-4 Counter/Timer Mode and Source (see below)
3-0 IP3..IP0 Change Interrupt Enable Flags (0=Off, 1=On)
Counter/Timer Mode and Clock Source Settings:
Num Mode Clock Source
0h Counter External (IP2)
1h Counter TxCA - 1x clock of Channel A transmitter
2h Counter TxCB - 1x clock of Channel B transmitter
3h Counter Crystal or external clock (x1/CLK) divided by 16
4h Timer External (IP2)
5h Timer External (IP2) divided by 16
6h Timer Crystal or external clock (x1/CLK)
7h Timer Crystal or external clock (x1/CLK) divided by 16
In Counter Mode, the Counter Ready flag is set on any underflow, and the
counter wraps to FFFFh and keeps running (but may get stopped by software).
In Timer Mode, automatic reload occurs on any underflow, the counter flag
(which can be output to OP3) is toggled on any underflow, but the Counter Ready
flag is set only on each 2nd underflow (unlike as in Counter mode).
7-4 IP3..IP0 Change Occured Flags (0=No, 1=Yes) ;auto reset after read
3-0 Current IP3-IP0 Input states (0=Low, 1=High) ;Same as IP.3-0
Reading from this register automatically resets IPCR.7-4 and ISR.7.
7 Not used (always 1)
6-0 Current IP6-IP0 Input states (0=Low, 1=High) ;LSBs = Same as IPCR.3-0
IP0-6 can be used as general purpose inputs, or for following special purposes:
IP6 External RxB Clock ;see CSRB.7-4
IP5 External TxB Clock ;see CSRB.3-0
IP4 External RxA Clock ;see CSRA.7-4
IP3 External TxA Clock ;see CSRA.3-0
IP2 External Timer Input ;see AUX.6-4
IP1 Clear to Send B (CTSB) ;see MR2B.5
IP0 Clear to Send A (CTSA) ;see MR2A.5
Note: The 24pin chip doesn't have any inputs, the 28pin chip has only one input
(IP2), the 40pin/44pin chips have seven inputs (IP0-IP6).
7-0 Change "OPR" OP7-OP0 Output states (0=No change, 1=Set/Reset)
Note: The 24pin chip doesn't have any outputs, the 28pin chip has only two
outputs (OP0,OP1), the 40pin/44pin chips have eight outputs (OP0-OP7).
7 OP7 (0=OPR.7, 1=TxRDYB)
6 OP6 (0=OPR.6, 1=TxRDYA)
5 OP5 (0=OPR.5, 1=RxRDY/FFULLB)
4 OP4 (0=OPR.4, 1=RxRDY/FFULLA)
3-2 OP3 (0=OPR.3, 1=Clock/Timer Output, 2=TxCB(1x), 3=RxCB(1x))
1-0 OP2 (0=OPR.2, 1=TxCA(16x), 2=TxCA(1x), 3=RxCA(1x))
Additionally, the OP0 and OP1 outputs are controlled via MR2A.5 and MR2B.5.
7-0 Not used (just issue a dummy-read to toggle the test mode on/off)
BGR Test switches between Baud Rate Set1/Set2 and Set3/Set4.
1X/16X Test switches between whatever...?
7-0 Not used (just issue a dummy-read to strobe start/stop command)
Start: Forces reload (copies CTLR/CTUR to CTL/CTU), and starts the timer.
Stop-in-Counter-Mode: Resets ISR.3, and stops the timer.
Stop-in-Timer-Mode: Resets ISR.3, but doesn't stop the timer.
The CTLR/CTUR reload value is copied to CTL/CTU upon Start Counter Command. In
Timer mode (not in Counter mode), it is additionally copied automatically when
the timer undeflows.
Reserved.
The SCN2681 is manufactured with 24..44 pins, the differences are:
24pin basic cut-down version ;without IP0-1/OP0-1 = without CTS/RTS
28pin additional IP2,OP0,OP1,X2 ;without IP0-1 = without CTS
40pin additional IP0-IP6,OP0-OP7,X2 ;full version
44pin same as 40pin with four NC pins ;full version (SMD)
Unknown which of them is supposed to be used with the PSX?
Note: The Motorola 68681 should be the same as the Philips/Signetics 2681.
Unknown if the Interrupt signal is connected to the PSX... there seems to be no
spare IRQ for it, though it <might> share an IRQ with whatever other
hardware...?
The BIOS seems to use only one of the two channels; for the std_io functions:
BIOS TTY Console (std_io)
Aside from the external DUART, the PSX additionally contains an internal UART,
Serial Port (SIO)
The DTL-H2000 devboard uses a non-serial "ATCONS" channel for TTY stuff,
EXP2 DTL-H2000 I/O Ports
The DTL-H2000 contains extended 8Mbyte Main RAM (instead of normal 2Mbyte),
plus additional 1MByte RAM in Expansion Area at 1FA00000h, plus some I/O ports
at 1F8020xxh:
0 Unknown, used for something
1 Unknown/unused
2 Unknown, used for something
3 TTY/Atcons TX Ready (0=Busy, 1=Ready)
4 TTY/Atcons RX Available (0=None, 1=Yes)
5-7 Unknown/unused
0-7 TTY/Atcons RX/TX Data
TTY channel for message output (TX) and debug console keyboard input (RX). The
DTL-H2000 is using this "ATCONS" stuff instead of the DUART stuff used in
retail console BIOSes ("CONS" seems to refer to "Console", and "AT" might refer
to PC/AT or whatever).
0-15 Data...?
This register does expand IRQ10 (Lightgun) to more than one IRQ source. The
register contains only Secondary IRQ Flags (there seem to be no Secondary IRQ
Enable bits; at least not for Lightguns).
0 ... used for something
1 Lightgun IRQ (write: 0=No change, 1=Acknowledge) (read: 0=None, 1=IRQ)
2-3 Unknown/unused (write: 0=Normal)
4 ... acknowledged at 1FA00B04h, otherwise unused
5 ... TTY RX ?
6-7 Unknown/unused (write: 0=Normal)
8-31 Not used by DTL-H2000 BIOS (but Lightgun games write 0 to these bits)
Retail games that support IRQ10-based "Konami" Lightguns are containing code
for detecting and accessing port 1F802030h. The detection works by examining a
value in the BIOS ROM like so:
IF [BFC00104h]=00002000h then Port 1F802030h does exist (DTL-H2000)
IF [BFC00104h]=00002500h then Port 1F802030h does NOT exist
IF [BFC00104h]=00000003h then Port 1F802030h does NOT exist (default)
IF [BFC00104h]= <other> then Port 1F802030h does NOT exist
Normal consoles don't include Port 1F802030h, and IRQ10 is wired directly to
the controller port, and the value at [BFC00104h] is always 00000003h.
Accordingly, one cannot upgrade the console just by plugging a Secondary IRQ10
controller to the expansion port (instead, one would need to insert the
controller between the CPU and controller plug, and to install a BIOS with
[BFC00104h]=00002000h).
The DTL-H2000 BIOS accesses 1F802030h with 8bit load/store opcodes, however,
the Lightgun games use 32bit load/store - which is theoretically overlapping
port 1F802032h, though maybe the memory system does ignore the upper bits.
0 Used for something (CLEARED on some occassions)
1-3 Unknown/unused
4 Used for something (SET on some occassions)
5-7 Unknown/unused
0-7 DIP Value (00h..FFh, but should be usually 00h..02h)
This register selects the DTL-H2000 boot mode, for whatever reason it's called
"DIP Switch" register, although the DTL-H2000 boards don't seem to contain any
such DIP Switches (instead, it's probably configured via some I/O ports on PC
side). Possible values are:
DIP=0 --> .. long delay before TTY? with "PSX>" prompt, throws CDROM cmds
DIP=1 --> .. long delay before TTY? no "PSX>" prompt PSY-Q?
DIP=2 --> .. instant TTY? with "PSX>" prompt
DIP=3 --> Lockup
DIP=04h..FFh --> Lockup with POST=04h..FFh
0-3 Current Boot Status (00h..0Fh)
4-7 Not used by BIOS (always set to 0)
During boot, the BIOS writes incrementing values to this register, allowing to
display the current boot status on an external 7 segment display (much the same
as Port 80h used in PC BIOSes).
0-7 Post/LED value
8bit wide, otherwise same as POST 1F802041h on retail consoles.
Might be a configuration port, or it's another POST register (which is used
prior to writing the normal POST bytes to 1FA00000h).
The first write to 1F802070h is 32bit, all further writes seem to be 8bit.
Similar to POST, but PS2 BIOS uses this address.
Contains ID and Version.
Activates the Halt and Turbo Registers (when set to "ON").
When enabled (see above), doing an 8bit read from this address stops the CPU
emulation unless/until an Interrupt occurs (when "CAUSE AND SR AND FF00h"
becomes nonzero). Can be used to reduce power consumption, and to make the
emulation faster.
When enabled (see above), writing to this register activates/deactivates
"turbo" mode, which is causing new data to arrive immediately after
acknowledging the previous interrupt.
0 CDROM Turbo (0=Normal, 1=Turbo)
1 Memory Card Turbo (0=Normal, 1=Turbo)
2 Controller Turbo (0=Normal, 1=Turbo)
3-7 Reserved (must be zero)