Home‎ > ‎Tutorials‎ > ‎SGDK‎ > ‎

Tutorial 3 : Add Z80 Syntax Highlighting to Code::Blocks

A fun feature of the SGDK environment is that it will actually compile Z80 assembly files (*.s80) found in your \src folder using SJASM 0.39g6. The output of the SJASM compiler can then be referenced in SGDK code and uploaded to the Z80. While this is great, I want more! This tutorial will show you how to add proper Z80 syntax highlighting to Code::Blocks to simplify our lives for Z80 coding. A future tutorial will deal with how to integrate Z80 source into your SGDK project and upload the output to the Z80 using SGDK.

A note on pronunciation: I am Canadian and therefore everywhere in this tutorial it is written Z80 (Zed 80) and not (Zee 80)...

Purpose

The purpose of this tutorial is to add Z80 syntax highlighting to Code::Blocks to better integrate Z80 development within SGDK.

How Syntax Highlighting Works In Code::Blocks

Within the Code::Blocks install directory, there are numerous XML files which specify the syntax highlighting of various languages. On my machine, these were found at C:\Program Files (x86)\CodeBlocks\share\CodeBlocks\lexers. Each lexer consists of two files, an XML file which specifies all highlighting, and a sample file which has a bit of code in that particular language.

A68k Lexer

The first lexer in my lexers directory is the A68K lexer, let's open that up and examine its contents.

<?xml version="1.0"?>
<!DOCTYPE CodeBlocks_lexer_properties>
<CodeBlocks_lexer_properties>
<Lexer name="Motorola 68k"
      index="100"
      filemasks="*.asm">

This data looks pretty straightforward: name, index, and filemasks attributes can be set here. Let's find out what the index attribute does. According to the Code::Blocks wiki, index is a scintilla constant which specifies a lexer_id for a particular language. I've found that there are lexer_id's specified up until 98 while the A68k lexer_id is 100. Therefore I think it's probably safe to use index 101 for our new Z80 lexer.

Create a Z80 Lexer File

We're not going to write a new lexer from scratch, instead we'll start with the A68K as a template and edit it until it meets our Z80 needs. Let's copy the lexer_A68k.sample and lexer_A68k.xml files from C:\Program Files (x86)\CodeBlocks\share\CodeBlocks\lexers to a safe location (i.e. not Program Files) where we can edit them without being harassed by Windows's uses account control. If you're very lazy you could just copy my lexer files into the lexer directory but then you wouldn't learn anything and that's no fun!

Once you've copied the two lexer files to a safe location, rename them to:
  • lexer_Z80.xml
  • lexer_Z80.sample

Edit the XML Lexer

We're not going to do much direct editing of the lexer file, but it does need a bit of tender love and care before we import it back to the Code::Blocks Program Files directory. Open lexer_Z80.xml in your favourite text editor and change the following attributes:
  • name = "Z80 Assembler"
  • index = "101
  • filemasks = "*.s80,*.i80"
    • any files matching this mask will be subject to our highlighter
The beginning of your file should look like this now. Obviously, you could give it whatever name you please...

<?xml version="1.0"?>
<!DOCTYPE CodeBlocks_lexer_properties>
<CodeBlocks_lexer_properties>
<Lexer name="Z80 Assembler"
      index="101"
      filemasks="*.s80,*.i80">

We also need to change the reference to the .sample file, at the very bottom of the XML document, change the SampleCode value attribute to point to our own .sample file.
  • value = "lexer_Z80.sample"
<SampleCode value="lexer_Z80.sample"/>
</Lexer>
</CodeBlocks_lexer_properties>

Save and close the file.

Edit the Lexer .sample

The .sample file is used by Code::Blocks to give a preview to the user during editing of the syntax highlighting properties. Basically, we just need a regular Z80 assembly file which shows most of the syntactical features of the language. Here I just used part of an .s80 file I already had. You can obviously go nuts here and write your own "quick brown fox" type example which uses every single syntactical feature, or just use mine included here (which doesn't use every syntactical feature). Save your new lexer_Z80.sample and close it.

;******************************************************************************
; include
;******************************************************************************
                include "dbWaitMacros.i80"      ; wait macros
                include "dbZ80macros.i80"       ; Z80 macro definition file
                include "dbYM2612macros.i80"    ; YM2612 macro definition file

;******************************************************************************
; reset
;******************************************************************************

                org     $0000
reset
                di                              ; disable interrupts
                ld      sp, STACK               ; setup stack pointer
                im      $01                     ; set interrupt mode 1

        ; start by clearing the command space
        ; first word of command space = 0 indicates to 68k that we are not ready
                xor     a                       ; clear a
                ld      b, a                    ; clear b, counter = 256
                ld      hl, COMMAND68K          ; point to beginning of comd space
.clearCmd68k
                ld     (hl), a                  ; clear memory location
                inc     hl                      ; point to next memory location
                djnz    .clearCmd68k            ; do it 256 times
                
        ; zero all pcm buffers with $80, DAC is unsigned
                or      %10000000               ; load a with $80, PCM signed zero value
                ld      hl, PCM0Buffer          ; point to PCM0 buffer start address
.clearPCM0
                ld      (hl), a                 ; clear memory location
                inc     hl                      ; point to next memory location
                djnz    .clearPCM0              ; do it 256 times

        ; PCM1 buffer is +256 from PCM0, no need to reload hl
.clearPCM1
                ld      (hl), a                 ; clear memory location
                inc     hl                      ; point to next memory location
                djnz    .clearPCM1              ; do it 256 times

Copy XML and .sample Back Into Code::Blocks Directory

Make sure Code::Blocks is closed, then, simply copy your two new files back into the Code::Blocks lexer directory - C:\Program Files (x86)\CodeBlocks\share\CodeBlocks\lexers. Windows may warn you to provide admin credentials in order to copy files into the Program Files directory - just click through these warnings: we know what we're doing!

Edit Syntax Highlighting In Code::Blocks

Open Code::Blocks, go to Settings -> Editor -> Syntax highlighting. In the dropdown list for "Syntax highlighting for:" you should see the "Z80 Assembler" entry at the very bottom of the list. If you don't see it there, then there may be a typo in your XML file which is preventing Code::Blocks from parsing it properly.


Select "Z80 Assemblerfrom the dropdown list "Syntax highlighting for:".

Edit Keywords For Each Category

Because we created the lexer_Z80.xml file as a copy of the A68k file, we have all the categories which were found in the A68k file. This is great because both of these are assembly language highlighters and their needs should be roughly similar. Now we have to change all of the A68k keywords to Z80 keyboards. 
  • Click on the "Keywords" button on the top right, you should see this:

You can toggle through each set of Keywords by using the up and down arrows on this form. The Keyword sets already defined here are:
  • 1 - CPU instructions
  • 2 - Registers
  • 3 - Directives
  • 4 - Extended instructions
  • 5 - Comment special words
  • 6 - Doxygen keywords
  • 7, 8 and 9 are blank
As far as I can tell the Keywords are NOT case-sensitive so if you're anal you'll probably have to repeat all of the keywords in upper case as well.

CPU Instructions

Replace the A68k CPU instructions with Z80 CPU instructions:

adc add and bit call ccf cp cpd cpdr cpi cpir cpl daa dec di djnz ei ex exx halt im in inc ind indr ini inir jp jr ld ldd lddr ldi ldir neg nop or otdr otir out outd outi pop push res ret reti retn rl rla rlc rlca rld rr rra rrc rrca rrd rst sbc scf set sla sll sra srl sub xor

Registers

Replace the A68k registers with Z80 registers:

a f b c d e h l af bc de hl ix ixh ixl iy iyh iyl i r af' sp pc

Directives

Replace the A68k directives with SJASM directives:

org assign define idefine undef xdefine xidefine db dc dd dt dw dz byte word dword defb defm defw defd ds block abyte abytec abytez asc ascmap struct endstruct defpage code output incbin include incdir equ repeat endrepeat while endwhile macro macro.recursive endmacro endm exitmacro xexitmacro if elseif ifb elseif ifdef elseifdef ifdir elseifdir ifdifi elseifdifi ifexists elseifexists ifid elseifid ifidn elseifidn ifidni elseifidni ifin elseifin ifini elseifini ifnum elseifnum ifstr elseifstr ifnb elseifnb ifndef elseifndef ifnexists elseifnexists ifnid elseifnid ifnnum elseifnnum ifnstr elseifnstr endif

Extended Instructions

Replace the A68k extended instructions with Z80 opcode parameters. I know I know, I could've put the extended Z80 instructions here but I already wrote out all of the Z80 instructions and I don't really feel like starting over. I could've also renamed "Extended Instructions" to "Opcode Parameters" in the XML file but alas...

z nz nc po pe p m

When you're done, press "OK'. Note that you won't see your changes immediately in the sample file. You must close and reload the "Configure Editor" form before the changes are loaded into Code::Blocks.

Adjust Keyword Colours

Re-open the syntax editing window by selecting Settings -> Editor -> Syntax highlighting. Select "Z80 Assembler" from the dropdown list "Syntax highlighting for:". From here, all syntax categories available are listed in a listbox. The choices you see should contain:
  • Default
  • Comment
  • CPU Instruction
  • Extended Instruction
  • etc...
I won't dictate how to set your colours. Simply select the category and adjust the colours according to your preferences. Foreground colour sets the font colour. As you make changes you should see those being updated in the sample window.


When you're all done, click "OK". My next tutorial will deal with how to combine SGDK and Z80 source files into a single project.

Deep in the Rabbit Hole

I've only scratched the surface of how custom syntax-highlighting can be configured in Code::Blocks. You can obviously dive down much further into customizations; what I've shown here is simply the strict minimum I wanted in order to add Z80 coding support to Code::Blocks.

In case you try to re-open the lexer_Z80.xml file to see our changes, you will notice that none of our changes are in it. WTF?! Actually, Code::Blocks stores our changes to the "Z80 Assembler" highlighter in \AppData\Roaming\CodeBlocks\default.conf. If you browse through this file you will eventually find all of the Z80 syntax we added. If you want to make a portable Z80 lexer XML file you could re-edit the XML file and save it with your changes - or start from mine found here.