Z80 Assembly programming for the MSX and MSX2

The MSX and later the MSX2 were an attermpt to create a 'PC' before the PC!... based around the 8-bit processor, an 'industry standard' compatible computer specification was created, and any manufacturer could realease compatible hardware.

With 2 extension slots, the machine was upgradable, and the end user could be confident that their hardware and software would work whatever MSX machine they had!

The last generation MSX - the Turbo-R was hugely powerful, and it's upgradability means the MSX now has the V9990... combining the Turbo-R and the V9990 (V9K) we effectively have what would have been the MSX3 if it had not been cancelled
Because each MSX has different hardware, we can only generalize, but here's the hardware specification you can expect to see!
Specs:
MSX MSX2 Turbo-R V9990
Cpu 3.5mhz Z80 3.5mhz Z80 7mhz R800 (28mhz effective)
Ram 16k 64k 256k / 512k
Vram 16k 128k 128k 512k (9x MSX2 speed)
Resolution 256x192 256x212 256x212 256x212
Colors 16 16 256 256
Sound chip AY AY AY + PCM

The V9990 can be used with the MSX, or MSX2 as well! - not just the Turbo-R

Although the Turbo-R does not use a Z80, the R800 has effectively perfect compatibility, although it's 'only'  7mhz , it uses memory caching, and in optimum circumstances can perform 4x the speed of a 7mhz Z80




The MSX1 VDP
The MSX1 VDP has 16 KB of memory

The Tile Pattern definitions use 1 byte per line for 1 bit pixel data, and 1 byte per line in the Colormap area to define color, one nibble for Foreground, and one nibble for background, in the format &FB

The Tilemap has 2 modes... normal mode uses 256 definitions, in the area &0000-&07FF...

Alternate mode uses 3 Pattern definitions, one for the first 1/3rd of the screen, another for the 2nd 3rd, and the final for the last 3rd... this allows us to simualte a bitmap screen, as we have enough tiles for each block of the screen to be unique, while only having one byte per tile in the tilemap!
From To Meaning
0000 07FF VRAM: Main Tile Patterns (1/3)
0800 0FFF VRAM: Extra Tile Patterns (2/3)
1000 17FF VRAM: Extra Tile Patterns (3/3)
1800 1AFF VRAM: Tilemap
1B00 1B7F VRAM: Sprite Attributes
1B80 1BAF VRAM: Palette Table
2000 37FF VRAM: Colormap
3800 3FFF VRAM: Sprite Patterns

The color palette is fixed, and there are no brightness or other limitations (unlike the speccy!)
0 1 2 3 4 5 6 7
8 9 A B C D E F
Note: Color 0 is transparent.


The MSX2 VDP
The MSX2 GPU has to be controlled via it's ports via OUT commands.
MSX 2 - V9938 Ports
Port When Read When Written
&98 Read Data Write Data
&99 Control Status
&9A Palette
&9B Indirect register
V9990
Port When Read When Written
&60 Read Data Write Data
&61 Palette
&62 Command
&63 Regsiter Data
&64 Register Select
&65 Status
&66 Interrupt Flag
&67 System
&6F Superimpose

To control the MSX2 GPU, we have to set it's registers, and then send a command to register 46

To Set a register, first send the value to put in the register  to the control port, then send the register number +128 to the control port.

EG lets set Reg 15 to 2...
    ld a,2
    out (&99),a
    ld a,15+128
    out (&99)dd
28 is an instruction meaning 'This is a register number'
Some registers like R#14 need more than 1 byte, just send these after the 14+128 command has been sent - the VDP will be expecting the extra data!

MSX 2 - Ports, Registers and Commands

Commands
Name Command From To Units ByteCode Function
HMMC High Spd Move CPU VRAM bytes %11110000 Fill Bytes from OUTI
YMMM High Spd MoveY VRAM VRAM bytes %11100000 Copy an area ffrom Vram to Vram
only changing Y
HMMM High Spd Move VRAM VRAM bytes %11010000 Copy an area from Vram to Vram fast (blit)
HMMV High Spd Move VDP VRAM bytes %11000000 Flood fill a square with a single byte
LMMC Logical Move CPU VRAM dots %10110000
LMCM Logical Move VRAM CPU dots %10100000
LMMM Logical Move VRAM VRAM dots %10010000 Copy an area of Vram 
with Logical conditions (Transparency)
LMMV Logical Move VDP VRAM dots %10000000
LINE Line VDP VRAM dots %01110000
SRCH Search VDP VRAM dots %01100000
PSET Pset VDP VRAM dots %01010000
POINT Point VDP VRAM dots %01000000
STOP Stop %00000000 Stop processing current task

If you want to know all the details, you should download the v9938 documentation here


Status Registers
Reg Meaning Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
S#0 Status 0 F 5S C 5SN 5SN 5SN 5SN 5SN
S#1 Status 1 FL LPS ID ID ID ID ID FH
S#2 Status 2 TR VR HR BD 1 1 EO CE
S#3 Status 3 X7 X6 X5 X4 X3 X2 X1 X0
S#4 Status 4 1 1 1 1 1 1 1 X8
S#5 Status 5 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
S#6 Status 6 1 1 1 1 1 1 Y9 Y8
S#7 Status 7 C7 C6 C5 C4 C3 C2 C1 C0
S#8 Status 8 BX7 BX6 BX5 BX4 BX3 BX2 BX1 BX0
S#9 Status 9 1 1 1 1 1 1 1 BX8
             
Note:
The firmware expects status register S#0 to be selected in R#15

Interrupts will fire until S#0 is read... so you must do this if you write your own interrupt handler!
Registers
Reg Meaning Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
R#0 mode register #0 0 DG IE2 IE1 M5 M4 M3 0
R#1 mode register #1 0 BL IE0 M1 M2 0 SI MAG
R#2 pattern name table 0 A16 A15 A14 A13 A12 A11 A10
R#3 colour table (LOW) A13 A12 A11 A10 A9 A8 A7 A6
R#4 pattern generator table 0 0 A16 A15 A14 A13 A12 A11
R#5 sprite attribute table (LOW) A14 A13 A12 A11 A10 A9 A8 A7
R#6 sprite pattern generator table 0 0 A16 A15 A14 A13 A12 A11
R#7 border colour/character colour at text mode TC3 TC2 TC1 TC0 BD3 BD2 BD1 BD0
R#8 mode register #2 MS LP TP CB VR 0 SPD BW
R#9 mode register #3 LN 0 S1 S0 IL E0 *NT DC
R#10 colour table (HIGH) 0 0 0 0 0 A16 A15 A14
R#11 sprite attribute table (HIGH) 0 0 0 0 0 0 A16 A15
R#12 character colour at text blinks T23 T22 T21 T20 BC3 BC2 BC1 BC0
R#13 blinking period ON3 ON2 ON1 ON0 OF3 OF2 OF1  OF0
R#14 VRAM access address (HIGH) 0 0 0 0 0 A16 A15 A14


A7 A6 A5 A4 A3 A2 A1 A0


0 RW A13 A12 A11 A10 A9 A8
R#15 indirect specification of S#n 0 0 0 0 S3 S2 S1 S0
R#16 indirect specification of P#n 0 0 0 0 C3 C2 C1 C0
R#17 indirect specification of R#n AII 0 R5 R4 R3 R2 R1 R0
R#18 screen location adjustment (ADJUST) V3 V2 V1 V0 H3 H2 H1 H0
R#19 scanning line number when the interrupt occurs IL7 IL6 IL5 IL4 IL3 IL2 IL1 IL0
R#20 colour burst signal 1 0 0 0 0 0 0 0 0
R#21 colour burst signal 2 0 0 1 1 1 0 1 1
R#22 colour burst signal 3 0 0 0 0 0 1 0 1
R#23 screen hard scroll DO7 DO6 DO5 DO4 DO3 DO2 DO1 DO0
R#32 SX: X-coordinate to be transferred (LOW) SX7 SX6 SX5 SX4 SX3 SX2 SX1 SX0
R#33 SX: X-coordinate to be transferred (HIGH) 0 0 0 0 0 0 0 SX8
R#34 SY: Y-coordinate to be transferred (LOW) SY7 SY6 SY5 SY4 SY3 SY2 SY1 SY0
R#35 SY: Y-coordinate to be transferred (HIGH) 0 0 0 0 0 0 SY9 SY8
R#36 DX: X-coordinate to be transferred to (LOW) DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0
R#37 DX: X-coordinate to be transferred to (HIGH) 0 0 0 0 0 0 0 DX8
R#38 DY: Y-coordinate to be transferred to (LOW) DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0
R#39 DY: Y-coordinate to be transferred to (HIGH) 0 0 0 0 0 0 DY9 DY8
R#40 NX: num. of dots to be transferred in X direction (LOW) NX7 NX6 NX5 NX4 NX3 NX2 NX1 NX0
R#41 NX: num. of dots to be transferred in X direction (HIGH) 0 0 0 0 0 0 0 NX8
R#42 NY: num. of dots to be transferred in Y direction (LOW) NY7 NY6 NY5 NY4 NY3 NY2 NY1 NY0
R#43 NY: num. of dots to be transferred in Y direction (HIGH) 0 0 0 0 0 0 NY9 NY8
R#44 CLR: for transferring data to CPU - - - - C3 C2 C1 C0


- - - - - C1 C0 G5


C7 C6 C5 C4 C3 C2 C1 C0
R#45 ARG: bank switching between VRAM and expanded VRAM 0 - MXD - DIY DIX - -
R#46 CMR: send VDP command CMD CMD CMD CMD MSK MSK MSK MSK

V9990 - Ports, Registers and Commands
Commands
Name Command From To Units ByteCode Function
STOP Stop %00000000 Stop processing current task
LMMC Logical Move CPU VRAM %00010000 Fill Bytes from OUTI
LMMV Logical Move VDP VRAM %00100000 Flood fill a square with a single byte
LMCM Logical Move VRAM CPU %00110000
LMMM Logical Move VRAM VRAM dots %01000000 Copy an area from Vram to Vram fast (blit)
CMMC Color-Develop CPU VRAM %01010000


CMMM Color-Develop VRAM VRAM %01110000
BMXL Linear BMP L-VRAM VRAM %10000000
BMLX Linear BMP VRAM L-VRAM %10010000
BMLL Linear BMP L-VRAM L-VRAM %10100000
LINE Line %10110000
SEARCH Search %11000000
POINT Point %11010000
PSET Pset %11100000
ADVANCE %11110000

If you want to know all the details, you should download the v9938 documentation here


Status 
Reg Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
Port &65 TR VR HR BD 0 MCS EO CE
         
Check CE to see if VDP is busy...
   
Note:
Even if you:re using the VDP, you need to check the MSX status port in your interrupt handler as usual!
Registers
Reg Meaning Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
R#0 Vram Write L L L L L L L L L
R#1 Vram Write H H H H H H H H H
R#2 Vram Write X X X X X X X X X
R#3 Vram Read L L L L L L L L L
R#4 Vram Read H H H H H H H H H
R#5 Vram Read X X X X X X X X X
R#6 Screen Mode D D C C X X B B
R#7 Screen Mode
R#8 Control D S Y S W 0 1 0
R#9 Interrupt
R#10 Interrupt
R#11 Interrupt
R#12 Interrupt
R#13 Palette Control
R#14 Palette Pointer (autoinc) Num Num Num Num Num Num Chn Chn
R#15 Back drop color - - B B B B B B
R#16 Display Adjust V V V V H H H H
R#17 Scroll Control
R#18 Scroll Control
R#19 Scroll Control
R#20 Scroll Control
R#21 Scroll Control
R#22 Scroll Control
R#23 Scroll Control
R#24 Scroll Control
R#25 Sprite Generator Base Address
R#26 LCD Control
R#27 Priority Control
R#28 Cursor Sprite Palette Offset
R#32 SX L L L L L L L L L
R#33 SX H H H H H H H H H
R#34 SY L L L L L L L L L
R#35 SY H H H H H H H H H
R#36 DX L L L L L L L L L
R#37 DX H H H H H H H H H
R#38 DY L L L L L L L L L
R#39 DY H H H H H H H H H
R#40 NX L L L L L L L L L
R#41 NX H H H H H H H H H
R#42 NY L L L L L L L L L
R#43 NY H H H H H H H H H
R#44 Move 0 0 0 0 DIY DIX NEQ NAJ
R#45 Logical Operation 0 0 0 TP L11 L10 L01 L00
R#46 Write Mask L L L L L L L L L
R#47 Write Mask H H H H H H H H H
R#48 Foreground Font Color L L L L L L L L L
R#49 Foreground Font Color H H H H H H H H H
R#50 Background Font Color L L L L L L L L L
R#51 Background Font Color H H H H H H H H H
R#52 Operation Code C C C C - - - -
R#53 Search Command B B B B B B B B
R#54 Search Command - - - - - B B B

AY Sound Chip:
Register Meaning Bit Meaning Details
0 Tone Pitch L - Channel A LLLLLLLL Lower value = Higher pitch
1 Tone Pitch H - Channel A ----HHHH Lower value = Higher pitch
2 Tone Pitch L - Channel B LLLLLLLL Lower value = Higher pitch
3 Tone Pitch H - Channel B ----HHHH Lower value = Higher pitch
4 Tone Pitch L - Channel C LLLLLLLL Lower value = Higher pitch
5 Tone Pitch H - Channel C ----HHHH Lower value = Higher pitch
6 Noise Generator ---NNNNN Higer = Faster noise
7 Mixer  --NNNTTT   N=Noise T=Tone (Channel --CBACBA 1=mute 0=normal)
8 Amplitude - Channel A ---EVVVV E=Envelope (1=Enabled) VVVV=Volume
9 Amplitude - Channel B ---EVVVV E=Envelope (1=Enabled) VVVV=Volume
10 Amplitude - Channel C ---EVVVV E=Envelope (1=Enabled) VVVV=Volume
11 Envelope L (Volume over time)  LLLLLLLL Lower=Faster Envelope
12 Envelope H (Volume over time)  HHHHHHHH Lower=Faster Envelope
13 Envelope Selection ----EEEE Envelope number (See PDF)
For more details, please see the AY sound chip PDF

MSX and MSX2 Programming Tutorials:
Lesson P5 - Bitmap graphics on the TI-83 and MSX
Lesson P7 - Keyreading on the MSX, Enterprise and TI-83
Lesson P10 - Tilemap graphics on the MSX1
Lesson P11 - Tilemap graphics on the MSX2

General Z80 Assembly Tutorials:
B. Beginner series - Learn the basics
A. Advanced series - In more detail
M. Multiplatform series - programming methods that work on all systems




Visit www.ChibiAkumas.com to get my games and their source code! | Support me on patreon