Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - .asciitable equivalent on vasm (or how to code it myself)

Reply to topic
Author Message
  • Joined: 03 Dec 2021
  • Posts: 54
Reply with quote
.asciitable equivalent on vasm (or how to code it myself)
Post Posted: Sat Jul 23, 2022 11:32 pm
Hello everyone!

I have just started the journey of learning assembly for the sega master system. I am following the (excellent) maxim's tutorial, other than chibiakumas' one.

I started with the Hello World example (of course), but instead of using WLA-DX I am using vasm as my assembler of choice.

I am a bit stuck in figuring out how to "translate" the .asciitable directive into an equivalent in vasm (if any). Looking at this link (which BTW I hope is the correct one to look at, I am still super noob), I can't see any immediate replacement. I have used "text" in place of ".asc", but it seems there is no mapping directive to convert ASCII text as far as I can tell.

Does anybody know if this is true? If so, should I try to write complicate code like the one shown in chibiakumas' website (https://www.chibiakumas.com/z80/helloworld.php#LessonH8, section "Printing a character to the screen") where he shows how to print strings and characters, step by step?

Thank you in advance for any suggestion!
  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Sun Jul 24, 2022 6:45 am
You have a few options as I see it:

1) You could store your string as raw ASCII, keep the tile indexes as they are and subtract the value of the space character inside the loop that sets up the screen map. Since you know the value of the space character ($20) you could express this as an addition if you wanted (adding -$20). You could also use a define to get rid of the magic number.


-:  ld a,(hl)
    cp $ff
    jr z,+
    add -$20 ; WB: added this line
    out (VDPData),a
    xor a
    out (VDPData),a
    inc hl
    jr -
+:


This is simple but isn't anywhere near as efficient as pre-mapping the ASCII codes because it's happening at runtime every time the loop is run.

2) Shift your tile definitions so that they start at an offset of $20 x 32 = $0400


    ld a,$00
    out ($bf),a
    ld a,$44 ; WB: changed from $40 to $44
    out ($bf),a


This is more efficient in terms of execution, and is more straightforward to reason about because each tile in your font lives at the position equal to its real ASCII code.

However it does leave a gap of 32 tiles at the beginning of the pattern generator which may or may not bother you. You could use that gap for other things. It's unlikely you'd use it for ASCII characters as everything below 32 is non-printable.

3) Switch to WLA-DX! It really is an excellent assembler for writing SMS games. I resisted it for the longest time, mostly because I didn't like the mandatory memory mapping directives, but once I got over that I wished I'd used it from the beginning - it's got so many super powerful directives designed specifically to make retro game development a more pleasant experience.

There may well be another option of writing a macro which maps a given sequence of characters to a set $20 lower. This would effectively emulate WLA-DX's .asciitable directive, but I don't know enough about vasm to know whether its macros are powerful enough to express that.
  View user's profile Send private message Visit poster's website
  • Joined: 03 Dec 2021
  • Posts: 54
Reply with quote
Post Posted: Sun Jul 24, 2022 9:07 pm
Thank you for your feedback!

I think I'll give option 2 a try and report back once I do.

As for using WLA-DX: I am doing this all "just" for the sake of learning as much as I can and for a good challenge (other than the fact the SMS was my first console :) ). My interest right now is not making a game, but just to understand how I can make one. I will keep this in mind if I'll change my mind in the future, thank you!

BTW, I had to research on the thing about the space character: I did not now fonts in general begins with it and I got confused (I still have to study a lot as you can see :) )
  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Mon Jul 25, 2022 8:08 am
umbe1987 wrote
BTW, I had to research on the thing about the space character: I did not now fonts in general begins with it and I got confused (I still have to study a lot as you can see :) )


You can design a font that has its characters in any order, but this one starts with a space to take advantage of the fact that most assemblers default to ASCII encoding for literal string data, and also that the space is the first printable character in ASCII.

The ASCII table is actually laid out with a few clever features; when you split it by bits 6-4 and bits 3-0 as in this image you see some cool patterns (note this image uses a very strange convention of counting bits starting with 1, but I don't, so just ignore the legend in the image!):

- The printable characters are in columns 2 to 7, i.e. when bits 6-4 are >= 2; alternatively you can OR bits 6 and 5 and if the result is 1 then it's a printable character.
- The numerals are in column 3, i.e. when bit 6 is 0 and bits 5 and 4 are 1. They also map directly for bits 3-0, which means if you have a number between 0 and 9 in a byte, you can get to its ASCII code simply by setting the top four bits to 0011.
- Similarly, all the alphabetical characters are in columns 4-6, so bit 6 must always be 1 for alphabetical characters. The uppercase characters have bits 6 and 5 set to 10 and the lowercase characters have bits 6 and 5 set to 11, and uppercase and lowercase characters share the same code points for bits 4-0, so converting a character from uppercase to lowercase simply involves flipping bit 5.
- Otherwise the alphabetical characters map bits 4-0 starting from 00001 for A/a, which I always thought was a little strange not to start from 00000. I suspect it might be to make it easier to design a reduced character set with only the alphabetical characters - that way you can decide to put your space character in the 00000 slot.
- On which subject, having space in the 00000 slot I think is particularly clever, because you typically need a space character to clear a screen / implement blank characters - not just for spaces between words. On the SMS you can supply minimal character data to clear the screen simply by writing 32x$00 bytes into VRAM from address $0000 to set up your "space" character, and then filling the screen map (usually from $3800) with 1,536x$00 bytes - i.e. 768 space characters. And not a single 1 bit in sight :)
asciichart.jpeg (95.21 KB)
asciichart.jpeg

  View user's profile Send private message Visit poster's website
  • Joined: 03 Dec 2021
  • Posts: 54
Reply with quote
Post Posted: Tue Jul 26, 2022 9:13 pm
willbritton wrote

2) Shift your tile definitions so that they start at an offset of $20 x 32 = $0400


    ld a,$00
    out ($bf),a
    ld a,$44 ; WB: changed from $40 to $44
    out ($bf),a


This is more efficient in terms of execution, and is more straightforward to reason about because each tile in your font lives at the position equal to its real ASCII code.

However it does leave a gap of 32 tiles at the beginning of the pattern generator which may or may not bother you. You could use that gap for other things. It's unlikely you'd use it for ASCII characters as everything below 32 is non-printable.


I kind of understood and was able to do one part of this, replicating the same space of 32 tiles which as far as I can see corresponds to the number of tiles before the fonts loaded when the SEGA logo appears (as can be seen by inspecting the "Tiles Viewer" window in MEKA, see first image).



However, I was not able to translate the initial Message data in the example into a readable ASCII message as I wanted. The result is the one of the second image. Perhaps I am just not using the right vasm directive, or maybe there is something else wrong going on...



Another thing I noticed is that I still don't know how the palette and the tiles are related to each other, but this is yet something else I should research more (i.e. black now appeared in the game screen, while before these last modifications the text was yellow and the bg was blue).

The way I modified my code is the following:



    ld hl,$0000 | VRAMWrite+$0400 ; VRAMWrite equ $4000
    call SetVDPAddress
...
    ld hl,$3800 | VRAMWrite
    call SetVDPAddress
    ld hl,Message
    ld bc,MessageEnd-Message  ; Counter for number of bytes to write
...
Message:
    text "Hello World!"
MessageEnd:


For completeness, I have attached the whole code as well.

Please bear in mind I am still in the learning process so there might be some obvious mistake that I still don't see ;)
sega_logo_tiles.png (69.51 KB)
sega logo tile viewer in meka
sega_logo_tiles.png
hello_world.png (66.5 KB)
my attempt
hello_world.png
Hello World.asm (4.84 KB)
whole code

  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Tue Jul 26, 2022 10:10 pm
Your patterns are set up fine, but you are only writing one byte per tile to the screen map here:

ld hl,Message
    ld bc,MessageEnd-Message  ; Counter for number of bytes to write
    WriteTextLoop:
        ld a,(hl)    ; Get data byte
        out (VdpData),a
        inc hl       ; Point to next letter
        dec bc
        ld a,b
        or c
        jr nz,WriteTextLoop


Each tile in the screen map consists of 16 bits. The first 8 bits are the least significant 8 bits of the tile index (i.e. your ASCII code) and the second 8 bits are various flags which affect the way the tile is displayed, plus also the 9th bit of the tile index.

So you actually want something like this:

ld hl,Message
    ld bc,MessageEnd-Message  ; Counter for number of bytes to write
    WriteTextLoop:
        ld a,(hl)    ; Get data byte
        out (VdpData),a
        xor a ; WB: set a to $00
        out (VdpData), a ; WB: write second byte to screen map
        inc hl       ; Point to next letter
        dec bc
        ld a,b
        or c
        jr nz,WriteTextLoop
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 597
  • Location: London, UK
Reply with quote
Post Posted: Tue Jul 26, 2022 10:23 pm
umbe1978 wrote
Another thing I noticed is that I still don't know how the palette and the tiles are related to each other, but this is yet something else I should research more (i.e. black now appeared in the game screen, while before these last modifications the text was yellow and the bg was blue).


This is also to do with the missing bytes. You should find that once you've fixed the code all your tiles should again be yellow on blue.

Basically when you only wrote one byte instead of two to the screen map, the even bytes were being used to set the tile flags instead of being used to represent characters. That's why you were missing all the characters except the "o" and also why the colours were strange.

Bit 3 of the second byte controls whether you are using either colours 0-15 (when bit 3 is 0) or colours 16-31 (when bit 3 is 1).
  View user's profile Send private message Visit poster's website
Reply to topic



Back to the top of this page

Back to SMS Power!