A collection of information gathered from various resources into a single document to be able to program for Amstrad CPC 464/6128 machines.
CPC has the following components on the mainboard:
- Z80
- CRTC HD6845
- Gate Array (custom ASIC for video)
- PPI 8255 (various; interrupts, audio, etc. controller)
- FDC 765 (Floppy Drive)
- AY3-8912 (Sound chip)
- http://www.cpcwiki.eu/imgs/e/e1/The_Amstrad_CPC_Firmware_Guide.txt
- http://www.cpcwiki.eu/index.php/Soft968:_CPC_464/664/6128_Firmware
The CPC IN/OUT design differs from the norm in that port numbers are defined using 16 bits, as opposed to the traditional 8 bits.
IN r,(C)/OUT (C),r
instructions: Bits b15-b8
come from the B
register, bits b7-b0 come from r
IN A,(n)/OUT (n),A
instructions: Bits b15-b8
come from the A
register, bits b7-b0 come from n
Listed below are the internal hardware devices and the bit fields to which they respond. In the table:
-
means this bit is ignored,
0
means the bit must be set to 0
for the hardware device to respond,
1
means the bit must be set to 1
for the hardware device to respond.
r1
and r0
mean a bit used to define a register
Hardware device | Address | Read/Write | b15 | b14 | b13 | b12 | b11 | b10 | b9 | b8 |
---|---|---|---|---|---|---|---|---|---|---|
Gate-Array | &7f | Write Only | 0 | 1 | - | - | - | - | - | - |
RAM Configuration | &7f | Write Only | 0 | - | - | - | - | - | - | - |
CRTC | &BC-&BF | Read/Write | - | 0 | - | - | - | - | r1 | r0 |
ROM select | &DF | Write only | - | - | 0 | - | - | - | - | - |
Printer port | &EF | Write only | - | - | - | 0 | - | - | - | - |
8255 PPI | &F4-&F7 | Read/Write | - | - | - | - | 0 | - | r1 | r0 |
Expansion Peripherals | &F8-&FB | Read/Write | - | - | - | - | - | 0 | - | - |
- http://www.z80.info/z80-op.txt
- http://fms.komkon.org/comp/CPUs/z80.txt
- https://fms.komkon.org/MSX/Docs/Z80-2.txt
It is HD6845S.
I/O port address | Function | Read/Write |
---|---|---|
&BCxx | 6845 CRTC Index | Write only |
&BDxx | 6845 CRTC Data Out | Write only |
&BExx | 6845 CRTC Status | Read only |
&BFxx | 6845 CRTC Data In | Read only |
Register Index | Register Name |
---|---|
0 | Horizontal Total |
1 | Horizontal Displayed |
2 | Horizontal Sync Position |
3 | Horizontal and Vertical Sync Widths |
4 | Vertical Total |
5 | Vertical Total Adjust |
6 | Vertical Displayed |
7 | Vertical Sync position |
8 | Interlace and Skew |
9 | Maximum Raster Address |
10 | Cursor Start Raster |
11 | Cursor End Raster |
12 | Display Start Address (High) |
13 | Display Start Address (Low) |
14 | Cursor Address (High) |
15 | Cursor Address (High) |
16 | Light Pen Address (High) |
17 | Light Pen Address (High) |
.------- REG 12 --------. .------- REG 13 --------.
| | | |
15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
.--.--.--.--.--.--.--.--. .--.--.--.--.--.--.--.--.
|X |X | | | | | | | | | | | | | | | |
'--'--'--'--'--'--'--'--' '--'--'--'--'--'--'--'--'
'--.--'--.--'---------------.-----------------'
| | |
| | '------> Offset for setting
| | videoram
| | (1024 positions)
| | Bits 0..9
| |
| '-------------------------> Video Buffer : note (1)
|
'-------------------------------> Video Page : note (2)
note (1) note (2)
.--.--.--------------. .--.--.---------------.
|11|10| Video Buffer | |13|12| Video Page |
|--|--|--------------| |--|--|---------------|
| 0| 0| 16Ko | | 0| 0| 0000 - 3FFF |
|--|--|--------------| |--|--|---------------|
| 0| 1| 16Ko | | 0| 1| 4000 - 7FFF |
|--|--|--------------| |--|--|---------------|
| 1| 0| 16Ko | | 1| 0| 8000 - BFFF |
|--|--|--------------| |--|--|---------------|
| 1| 1| 32Ko | | 1| 1| C000 - FFFF |
'--'--'--------------' '--'--'---------------'
ld bc, &bc06 ;; Select Register 6 Vertical Displayed
out (c), c
ld bc, &bd80 ;; Set value &80
out (c), c
ld bc, &bc00+13 ;; Select Display Low Address
out (c), c
ld bc, &bd00+&01 ;; Set &c001 as the display address
out (c), c
An ASIC responsible for various display related tasks.
Every scanline is 64 microseconds.
What is the total number of scanlines per frame?
What is the duration of Vertical Blanking?
What is the duration of Horizontal Blanking?
I/O port address | Function | Read/Write |
---|---|---|
&7Fxx | Write |
Bit 7 | Bit 6 | Register | Function |
---|---|---|---|
0 | 0 | PENR | Select pen |
0 | 1 | INKR | Select colour for selected pen |
1 | 0 | RMR | Select screen mode, rom configuration and interrupt control |
1 | 1 | MMR | Ram Memory Management |
This register can be used to select one of the 17 color-registers (pen 0 to 15 or the border). It will remain selected until another PENR command is executed.
Bit | Value | Function |
---|---|---|
7 | 0 | Gate Array function "Pen Selection" |
6 | 0 | |
5 | x | not used |
4 | 1 | Select border |
3 | x | ignored |
2 | x | ignored |
1 | x | ignored |
0 | x | ignored |
This register takes a 5bits parameter which is a color-code. This color-code range from 0 to 31 but there's only 27 differents colors (because the Gate Array use a 3-states logic on the R,G and B signals, thus 3x3x3=27).
Bit | Value | Function |
---|---|---|
7 | 0 | Gate Array function "Colour Selection" |
6 | 1 | |
5 | x | not used |
4 | x | Colour number |
3 | x | |
2 | x | |
1 | x | |
0 | x |
Hardware Number | Colour Name | R % G % B % | Hexadecimal | RGB values |
---|---|---|---|---|
54h | Black | 0 0 0 | #000000 | 0/0/0 |
44h (or 50h) | Blue | 0 0 50 | #000080 | 0/0/128 |
55h | Bright Blue | 0 0 100 | #0000FF | 0/0/255 |
5Ch | Red | 50 0 0 | #800000 | 128/0/0 |
58h | Magenta | 50 0 50 | #800080 | 128/0/128 |
5Dh | Mauve | 50 0 100 | #8000FF | 128/0/255 |
4Ch | Bright Red | 100 0 0 | #FF0000 | 255/0/0 |
45h (or 48h) | Purple | 100 0 50 | #ff0080 | 255/0/128 |
4Dh | Bright Magenta | 100 0 100 | #FF00FF | 255/0/255 |
56h | Green | 0 50 0 | #008000 | 0/128/0 |
46h | Cyan | 0 50 50 | #008080 | 0/128/128 |
57h | Sky Blue | 0 50 100 | #0080FF | 0/128/255 |
5Eh | Yellow | 50 50 0 | #808000 | 128/128/0 |
40h (or 41h) | White | 50 50 50 | #808080 | 128/128/128 |
5Fh | Pastel Blue | 50 50 100 | #8080FF | 128/128/255 |
4Eh | Orange | 100 50 0 | #FF8000 | 255/128/0 |
47h | Pink | 100 50 50 | #FF8080 | 255/128/128 |
4Fh | Pastel Magenta | 100 50 100 | #FF80FF | 255/128/255 |
52h | Bright Green | 0 100 0 | #00FF00 | 0/255/0 |
42h (or 51h) | Sea Green | 0 100 50 | #00FF80 | 0/255/128 |
53h | Bright Cyan | 0 100 100 | #00FFFF | 0/255/255 |
5Ah | Lime | 50 100 0 | #80FF00 | 128/255/0 |
59h | Pastel Green | 50 100 50 | #80FF80 | 128/255/128 |
5Bh | Pastel Cyan | 50 100 100 | #80FFFF | 128/255/255 |
4Ah | Bright Yellow | 100 100 0 | #FFFF00 | 255/255/0 |
43h (or 49h) | Pastel Yellow | 100 100 50 | #FFFF80 | 255/255/128 |
4Bh | Bright White | 100 100 100 | #FFFFFF | 255/255/255 |
Bit | Value | Function |
---|---|---|
7 | 1 | |
6 | 0 | |
5 | 0 | |
4 | x | Reset interrupt counter |
3 | x | Upper ROM (0 enable, 1 disable) |
2 | x | Lower ROM (0 enabled, 1 disable) |
1 | x | Select Video Mode 0, 1, 2, 3 |
0 | x |
Bit 1 | Bit 0 | Screen mode |
---|---|---|
0 | 0 | Mode 0, 160x200 resolution, 16 colours |
0 | 1 | Mode 1, 320x200 resolution, 4 colours |
1 | 0 | Mode 2, 640x200 resolution, 2 colours |
1 | 1 | Mode 3, 160x200 resolution, 4 colours |
Relevant excerpt from Firmware manual about video memory mapping
in MODE 2 (where there are two colours only, each pixel needs only one
bit - either on or off)
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
p0 p1 p2 p3 p4 p5 p6 p7
(the pixels are arranged with p0 being the leftmost one, etc)
in MODE 1 (where four colours are available and so two bits are needed
for each pixel - 1 byte represents 4 pixels)
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
p0(1) p1(1) p2(1) p3(1) p0(0) p1(0) p2(0) p3(0)
(each pixel is twice as wide as in MODE 2)
in MODE 0 (where sixteen colours are possible and four bits are needed
for each pixel - 1 byte represents 2 pixels)
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
p0(0) p1(0) p0(2) p1(2) p0(1) p1(1) p0(3) p1(3)
(each pixel is four times as wide as in MODE 2)
NB: the numbers in brackets show which bit of the pixel's pen number
the screen byte bit refers to. For example in MODE 1, the 4 most
significant bits of the byte hold bit 1 of the pixel's pen value and
the 41east signifcant bits hold bit 0 of the pen value.
6128 � 464 � Size � Comments on the memory locations
&C000 &C000 &4000 normal (upper) screen area. The
alternative (lower) screen area is from
&4000 to &7FFF. The addresses of the
starts of lines and rows in the normal
screen area after a MODE instruction
are:
LINE R0W0 R0W1 R0W2 R0W3 R0W4 R0W5 R0W6 R0W7
1 C000 C800 D000 D800 E000 E800 F000 F800
2 C050 C850 D050 D850 E050 E850 F050 F850
3 C0A0 C8A0 D0A0 D8A0 E0A0 E8A0 F0A0 F8A0
4 C0F0 C8F0 D0F0 D8F0 E0F0 E8F0 F0F0 F8F0
5 C140 C940 D140 D940 E140 E940 F140 F940
6 C190 C990 D190 D990 E190 E990 F190 F990
7 C1E0 C9E0 D1E0 D9E0 E1E0 E9E0 F1E0 F9E0
8 C230 CA30 D230 DA30 E230 EA30 F230 FA30
9 C280 CA80 D280 DA80 E280 EA80 F280 FA80
10 C2D0 CAD0 D2D0 DAD0 E2D0 EAD0 F2D0 FAD0
11 C320 CB20 D320 DB20 E320 EB20 F320 FB20
12 C370 CB70 D370 DB70 E370 EB70 F370 FB70
13 C3C0 CBC0 D3C0 DBC0 E3C0 EBC0 F3C0 FBC0
14 C410 CC10 D410 DC10 E410 EC10 F410 FC10
15 C460 CC60 D460 DC60 E460 EC60 F460 FC60
16 C4B0 CCB0 D4B0 DCB0 E4B0 ECB0 F4B0 FCB0
17 C500 CD00 D500 DD00 E500 ED00 F500 FD00
18 C550 CD50 D550 DD50 E550 ED50 F550 FD50
19 C5A0 CDA0 D5A0 DDA0 E5A0 EDA0 F5A0 FDA0
20 C5F0 CDF0 D5F0 DDF0 E5F0 ED50 F550 FD50
21 C640 CE40 D640 DE40 E640 EE40 F640 FE40
22 C690 CE90 D690 DE90 E690 EE90 F690 FE90
23 C6E0 CEE0 D6E0 DEE0 E6E0 EEE0 F6E0 FEE0
24 C730 CF30 D730 DF30 E730 EF30 F730 FF30
25 C780 CF80 D780 DF80 E780 EF80 F780 FF80
spare start C7D0 CFD0 D7D0 DFD0 E7D0 EFD0 F7D0 FFD0
spare end C7FF CFFF D7FF DFFF E7FF EFFF F7FF FFFF
Once the whole screen has been scrolled in any direction, the
above table will become incorrect. On scrolling, all the above
addresses will have an offset (MOD &800) added, derived as follows:
+&02 per scroll to the left (=2, 1 or « character in MODE 2, MODE 1
or MODE 0 respectively)
-&02 per scroll to the right (=2, 1 or « character in MODE 2, MODE 1
or MODE 0 respectively)
+&50 per scroll up one line
-&50 per scroll down one line
When set to 0, &c000-&ffff reads Upper ROM
When set to 0, &0000-&3ffff reads Firmware ROM
ld bc, &7f01 ;; Select PEN 1
out (c), c
ld bc, &7f54 ;; Write INKR color-code &54 (%01011000)
out (c), c
Programmable universal I/O interface device
Datasheet: http://cpctech.cpc-live.com/docs/datasheet/msm82c55a.pdf
Bit 9 | Bit 8 | PPI Function | Read/Write status |
---|---|---|---|
0 | 0 | Port A data | Read/Write |
0 | 1 | Port B data | Read/Write |
1 | 0 | Port C data | Read/Write |
1 | 1 | Control | Write Only |
I/O address | PPI Function |
---|---|
&F4xx | Port A data |
&F5xx | Port B data |
&F6xx | Port C data |
&F7xx | Control |
PSG Data (Programmable Sound Generator)
Entire bitmap is data bus
Bit | Description Usage |
---|---|
7 | Cassette read data |
6 | Parallel/Printer port ready signal "1" = not ready, "0" = Ready |
5 | /EXP |
4 | (note 5) |
3 | (note 1) |
2 | (note 2) |
1 | (note 3) |
0 | 6845 VSYNC State of VSYNC from 6845. "1" = VSYNC active, "0" = VSYNC inactive |
ld b, &f5
.vsync_sync
in a, (c)
rra
jr nc, vsync_sync
PSG Control (Programmable Sound Generator)
Bit | Description | Usage |
---|---|---|
7 | PSG BDIR | PSG function selection |
6 | PSG BC1 | |
----- | ------------------------ | --------------------------------------------------- |
5 | Cassette Write data | |
4 | Cassette Motor Control | set bit to "1" for motor on, or "0" for motor off |
----- | ------------------------ | --------------------------------------------------- |
3 | Keyboard line | Select keyboard line to be scanned (0-15) |
2 | ||
1 | ||
0 |
PSG function selection:
Bit 7 | Bit 6 | Function |
---|---|---|
0 | 0 | Inactive |
0 | 1 | Read from selected PSG register |
1 | 0 | Write to selected PSG register |
1 | 1 | Select PSG register |
@JimmyDansbo
Hello, I used different assemblers: rasm, Protest/Maxam or WinAPE.
I also wrote more comprehensive notes here: https://neuro-sys.github.io/2019/10/01/amstrad-cpc-crtc.html