Getting started with MSX coding (assembler)

Page 1/4
| 2 | 3 | 4

By Sdw

Resident (50)

Sdw's picture

25-09-2008, 10:24

Hi all!

I just bought my first MSX computer, a Philips NMS 8245.

Now I am looking to code some demos in assembler. I have experience from the commodore machines (VIC20, C64 etc.) and also some Z80 from doing stuff for the TI-83 calculator.

I have found a nice crossassembler called TNIAsm and I am ready to go!

However, I have a hard time finding info on how to get started. I don't even know which address to assemble my stuff to, or how to produce a file that I can test in emulator first, and then on the real thing.

The demos I've run so far come as .dsk files with the executables as .COM. Is that the easiest way to go, assemble to a .COM file and then create a .DSK that the emu can run, and then write to a 720kb disk for test on the MSX?
What about the 'BIN' format I've seen some references to?

Also, does anyone have some simple Z80 skeleton code that shows how to get a screen (text mode or graphic mode) set up and update it using the VDP?
I mean, a good start for me would be to get the MSX version of this C64 code going:

ldx #$00
sta $0400,x
bne loop

That is, output all 256 possible characters to screen!

I would guess the MSX variant would be something like

VDP code to enable text screen
VDP one char at the time to graphics memory location XXX
jmp loop

Login or register to post comments


Enlighted (6933)

ARTRAG's picture

25-09-2008, 10:51

If you work under DOS (.COM), the your code starts at 100h and it is loaded in RAM
You do not have direct access to ROM bios (actually you can use a inter slott call)
but you have 64K or ram active.
To run the .com file just type its name while in msx-dos

Under Basic (.BIN) the code can start at any address below 8000h, you have direct access
to the BIOS (and to the rom basic), but you have only 32K of RAM available.
To run the file .BIN type bload"file.bin",r while in basic

In dos, the program you need is:

   ORG 100h

        ld a,1
        ld iy, ((0xfcc0 - 1))
        ld ix, 0x005f
        call 0x001c  ; use bios to go in text mode 1
        ld   a,00h
        out (0x99),a
        ld  a,0x40 + 18h
        out (0x99),a ; set the VDP to write from 1800h - pattern name table in screen 1

        ld bc,0098h
        out (c),b  ; plot 256 tiles in reverse order
        djnz loop
        ret                 ; return to dos

By Metalion

Paragon (1622)

Metalion's picture

25-09-2008, 14:37

However, I have a hard time finding info on how to get started
All you have to do is to read the MSX Technical Data Book and/or the MSX2 Technical Handbook

By Sdw

Resident (50)

Sdw's picture

25-09-2008, 15:38

Thanks ARTRAG, just what I needed! Now I have set up a little toolchain that assembles and creates the DSK file, and your example worked as expected.

Metalion: Seems like interesting info, however the first link is broken (404)

By dvik

Prophet (2200)

dvik's picture

25-09-2008, 16:47

For me the MSX Assembly Page has been very helpful.


Enlighted (6933)

ARTRAG's picture

25-09-2008, 17:05

I agree, MAP at TNI is the best!
Lots of examples and documentationSmile

look for sjasm plus as assembler...

By Sdw

Resident (50)

Sdw's picture

26-09-2008, 10:53

Wow, SjASMPlus seems like a really powerful assembler.
I've been using Kick Assembler for my 65xx based coding and always felt that Z80 assemblers have been lacking in comparison, but this one seems to be playing in the same league!

By sjoerd

Hero (609)

sjoerd's picture

26-09-2008, 12:40

You could also take a look at Sjasm0.4. It is still in beta and does not have a scripting language, but it has a lot of improvements compared to SjASM 0.3, on which SjASMPlus is based.

Of course SjASMPlus is also a much-improved SjASM and I am the author of Sjasm, so I might be a bit biased Tongue

By Metalion

Paragon (1622)

Metalion's picture

26-09-2008, 14:13

AsMSX is also a good assembler.
It includes special macros dedicated to the MSX, which can help create easily ROMs, MegaROMs or DOS files.
However, the current version has some bugs which were to be worked out in version 0.13, but no news so far Crying

By hitchhikr

Rookie (19)

hitchhikr's picture

26-09-2008, 15:14

Under Basic (.BIN) the code can start at any address below 8000h,

He means above 0x8000 obviously :],
the various roms (system/disk/basic) are starting from 0 to 0x8000, the memory is handled by banks switching.

Alternatively you can also use msx-o-mizer packer as it's decruncher automatically gives access to the 64k of memory (by switching the first 32k banks into ram) to your program if it's depacking address is below 0x8000. Also since it deals with .bin files so it doesn't require MSXDOS which will surely be better for tape based MSX programs or if you target MSX1 as platform to begin with.

I use sjasm too.

Here is how to set a screen mode in hardware (MSX1 modes only, i haven't explored MSX2 stuff yet):

PORT_VDP_REG	    equ	    $98	; R/W
PORT_VDP_STATE	    equ	    $99	; R/W

SCREENMODE_TEXT     equ     0
SCREENMODE_GFX1     equ     1
SCREENMODE_GFX2     equ     2

SCREEN_OFF          equ     0
SCREEN_ON           equ     0x40

SPRITES_8x8         equ     %00
SPRITES_16x16       equ     %10
SPRITES_x1          equ     %00
SPRITES_x2          equ     %01

                    ld      a, SCREENMODE_GFX1
                    ld      b, SPRITES_16x16 | SPRITES_x2
                    ld      d, SCREEN_ON
                    call    VDP_Screen_Mode

; a: Screen mode (0 to 3)
; b: Sprites type
; d: screen on/off
VDP_Screen_Mode:    push    bc
                    add     a
                    ld      b, 0
                    ld      c, a
                    ld      ix, Screen_Modes_Table
                    add     ix, bc
                    ld      a, (ix)
                    call    VDP_Write_Reg_0
                    pop     bc
                    ld      a, (ix + 1)
                    or      b
                    or      d
                    jp      VDP_Write_Reg_1

; %00000010: set if we're in gfx mode 2 (all other bits must be 0)
VDP_Write_Reg_0:    out     (PORT_VDP_STATE), a
                    ld      a, 0 | 0x80
                    out     (PORT_VDP_STATE), a

; %10000000: always 1 (4/16k vram)
; %01000000: 1: screen active / 0: screen not active
; %00100000: 1: interrupts active / 0: interrupts not active
; %00010000: 1: mode text / 0: other modes
; %00001000: 1: mode multicolor / 0: other modes
; %00000000: always 0
; %00000010: 1: sprites 16x16 / 0: sprites 8x8
; %00000001: 1: sprites *2 / 0: sprites *1
VDP_Write_Reg_1:    out     (PORT_VDP_STATE), a
                    ld      a, 1 | 0x80
                    out     (PORT_VDP_STATE), a

Screen_Modes_Table: db      %00000000, %10010000
                    db      %00000000, %10000000
                    db      %00000010, %10000000
                    db      %00000000, %10001000

Misc. code to deal with the VRAM (MSX1 only):

VDP_Read_VRAM:      ld      a, l
                    out     (PORT_VDP_STATE), a
                    ld      a, h
                    out     (PORT_VDP_STATE), a
                    in      a, (PORT_VDP_REG)

VDP_Write_VRAM:     push    af
                    ld      a, l
                    out     (PORT_VDP_STATE), a
                    ld      a, h
                    or      0x40
                    out     (PORT_VDP_STATE), a
                    pop     af
                    out     (PORT_VDP_REG), a

; %0000xxxx PNT address (* 0x400) (Patterns Names Table)
VDP_Set_PNT:        out     (PORT_VDP_STATE), a
                    ld      a, 2 | 0x80
                    out     (PORT_VDP_STATE), a

; %xxxxxxxx CT address (* 0x40) (Colours Table)
; mode 2:
;  %00000000: starts at 0x0000-0x17ff
;  %10000000: starts at 0x2000-0x37ff
;  %00000000: 1st bottom array / 1st middle array (32 bytes)
VDP_Set_CT:         out     (PORT_VDP_STATE), a
                    ld      a, 3 | 0x80
                    out     (PORT_VDP_STATE), a

; %00000xxx PGT address (* 0x800) (Patterns Generators Table)
; mode 2:
;  %00000000: starts at 0x0000-0x17ff
;  %00000100: starts at 0x2000-0x37ff
;  %00000000: 1st bottom array / 1st middle array
;  %00000001: 1st bottom array / 2nd middle array
;  %00000010: 3rd bottom array / 1st middle array
;  %00000011: 3rd bottom array / 2st middle array
;  (top array always uses 1st array)
VDP_Set_PGT:        out     (PORT_VDP_STATE), a
                    ld      a, 4 | 0x80
                    out     (PORT_VDP_STATE), a

; %0xxxxxxx SAT address (* 0x80) (Sprite Attributes)
VDP_Set_SAT:        out     (PORT_VDP_STATE), a
                    ld      a, 5 | 0x80
                    out     (PORT_VDP_STATE), a

; %00000xxx SGT address (* 0x800) (Sprites Generators Table)
VDP_Set_SGT:        out     (PORT_VDP_STATE), a
                    ld      a, 6 | 0x80
                    out     (PORT_VDP_STATE), a

; %1111xxxx : Text color
; %xxxx1111 : Background color
VDP_Write_Reg_7:    out     (PORT_VDP_STATE), a
                    ld      a, 7 | 0x80
                    out     (PORT_VDP_STATE), a

By hbarcellos

Hero (642)

hbarcellos's picture

26-09-2008, 15:40

1) Download PASMO to assemble on a PC
2) Download Notepad++ to create files
3) Use this "template"

--- CUT HERE ---
INIT32 EQU #006f


org #4000
db "AB"
dw start
db 00,00,00,00,00,00


LD HL,texto
call CHPUT
inc HL
ld a,0
cp (HL)
JR NZ, loop
jp fim

DB 'Hello World of MSX! Im SDW and I just got my NMS 8245 ',00


--- CUT HERE ---

RAM is *probably* after $c000
Save that as mycode.asm
Go to DOS and use
pasmo mycode.asm myfirst.rom

use the .ROM on BlueMSX or OpenMSX...

That's it. Direct and easy!

Page 1/4
| 2 | 3 | 4