Close

MSX Demos on Homebrew Hardware

A project log for Game Boards for RC2014

Run classic video games on your RC2014

jb-langstonJ.B. Langston 06/20/2018 at 01:350 Comments

I've been able to successfully run the Bold demo for the MSX 1 on the RC2014 with my TMS9918A video card. 

Since I have mapped the TMS9918A's RAM and register ports to 98 and 99, the same as on the MSX, the demo will output video 100% unmodified. Unfortunately there is no audio in the unmodified code because the YM2149 sound card for the RC2014 does not support the port configuration used by the MSX.  With a minor modification, however, It's possible to get sound working.

Rather than trying to get MSX-DOS to run on the RC2014, which would be a much bigger undertaking, I used my z80ctrl board to load the demo binaries directly from the SD card into memory at origin 100H. The demoa.com and demob.com files were extracted from the bold.dsk image using openMSX with the following console commands:

virtual_drive bold.dsk
diskmanipulator export virtual_drive .

One tiny modification was made to demoa.com: I poked a HALT (76) at address 152 in place of the RET that was there before. This is necessary because there's no other software to return to, so I needed to halt the processor when this part was done so I could load the next part of the demo.  demob.com was completely unmodified, and was simply loaded at 100H and run after demoa.com halted.

To get sound working, I needed to modify the routine in demob.com that sends audio commands to the YM2149.  The unmodified version looks like this:

06fa  0e a0            ..     LD C,A0H
06fc  21 f9 07         !..    LD HL,07F9H
06ff  ed 79            .y     OUT (C),A
0701  0c               .      INC C
0702  ed a3            ..     OUTI
0704  0d               .      DEC C
0705  3c               <      INC A
0706  fe 0d            ..     CP 0DH
0708  20 f5             .     JR NZ,-11
070a  ed 79            .y     OUT (C),A
070c  7e               ~      LD A,(HL)
070d  a7               .      AND A
070e  f8               .      RET M
070f  0c               .      INC C
0710  ed 79            .y     OUT (C),A
0712  c9               .      RET

Port A0H is the address port, and A1H is the data port used by the MSX for the YM2149.  The demo loads A0H into register c, then uses the out (c), a and outi commands to send data to the chip at the port address stored in c.  It switches c back and forth between A0H and A1H using the inc and dec instructions.  I had to be careful about modifying the code because any change to the length of the instructions would change the offsets of the rest of the program and cause absolute references to those addresses to become invalid. 

I had initially devised a much more complicated scheme but thanks to neon reminding me that "out (c), a" is a 2 byte instruction, the same as "out (nn), a", I was able to simply replace the "out (c), a" instructions with "out (nn), a" instructions that send data directly to the desired port.  I still had to load c with the data port address to use the outi instruction, but I no longer needed to switch c back and forth between ports, so I changed the inc c/dec c instructions to nops.  The modified version of the code that uses the default D0/D8 ports for the RC2014 YM/AY sound card looks like this:

06fa  0e d0            ..     LD C,D0H
06fc  21 f9 07         !..    LD HL,07F9H
06ff  d3 d8            ..     OUT (D8H),A
0701  00               .      NOP
0702  ed a3            ..     OUTI
0704  00               .      NOP
0705  3c               <      INC A
0706  fe 0d            ..     CP 0DH
0708  20 f5             .     JR NZ,-11
070a  d3 d8            ..     OUT (D8H),A
070c  7e               ~      LD A,(HL)
070d  a7               .      AND A
070e  f8               .      RET M
070f  00               .      NOP
0710  d3 d0            ..     OUT (D0H),A
0712  c9               .      RET

I used z80ctrl's scripting facility to load both parts of the demo into memory and then automatically patch and run them.  With this script, it's possible to run the unmodified demo binaries simply by typing "do bold" (assuming the script has been saved in a file called bold and copied to the z80ctrl's SD card along with both demoa.com and demob.com).

page 20
clkdiv 4
loadbin 100 demoa.com
poke 152 76
run 100
loadbin 100 demob.com
poke 06fb d0
poke 06ff d3
poke 0700 d8
poke 0701 00
poke 0704 00
poke 070a d3
poke 070b d8
poke 070f 00
poke 0710 d3
poke 0711 d0
run 100

First, the script selects page 20 (the start of RAM) on the 512KB RAM/ROM board I am using. Next, it sets the clock divider to 4, because the full 10MHz clock is too fast for the TMS9918A and results in video glitches when the memory writes that the TMS9918A is still processing are overrun by subsequent writes sent by the Z80.  Now it loads the first demo binary into memory at origin 100H. It pokes 76H into address 152H to change the RET instruction to a HALT, then it runs the first binary.  When this finishes, it loads the second binary and pokes the changes for the sound ports into the appropriate locations in memory. When that's finished, it runs the demo.

Update: I have posted a pre-patched version of Bold in the downloads that includes scripts to run it either on z80ctrl or CP/M.

Discussions