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 - [WIP] GG : The Sword of Stone

Reply to topic Goto page 1, 2, 3, 4  Next
Author Message
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
[WIP] GG : The Sword of Stone
Post Posted: Mon Feb 27, 2023 7:44 pm
Hello,

After close to one year working around SMS/GG hardware, I have decided to register and share some insight in a game I have been developing for the Game Gear.

At first I did not want to share it too much before it was done (this is the type of person I am), but you do have a nice community and many tools you have created have been useful, so I wanted to thank you and share what I was able to do !

The game is called : The Sword of Stone.

It is an narrative adventure game where you travel a world and uncover its story. You can play as three different characters at first, then new possibilities will open up for a second run. The ultimate goal is to discover the truth about the story and the world.

Here are some pictures of the pixel-art I made for the game (you will be looking at months of work in an instant)... see below.

Title screen
Hero select screen
There is a huge world map, this is made small so that you cannot see all details to avoid spoiling the world :)

When entering the menu or interacting, you get a screen where you can do some actions. The game will be a bit text-heavy, I like some good story-telling (don't pay attention to inconsistencies in places names etc...)

There is a world map in-game as well that unveils as you progress

Most of the content has been drawn, and musics composed. Two stories are playable from start to finish.

Finally, some raw pixel-art :

Faces (left was targeting Megadrive with a different palette per face, right is GG with 15 colors (sprites palette) )

Backgrounds

Monsters and NPCs

This has been created using devkitsms, graphicsgale, BMP2Tile, assetstobank, deflmask (I am making all the music as well), Tiled, eclipse as IDE/Notepad++(I love regex)/Excel and Gear System to test development. I also have a McWill Game Gear and Everdrive (not sure if I should expect different behavior on a 100% original console).

Thanks to all contributors to these tools, you made it possible for someone like me to make a decent game in C. Assembly is too abstract/difficult for me and takes more time (and I am trying to spend as less time as possible, since I am doing this on my free time).
I have no real prior knowledge of pixel-art nor composing music. I have been learning everything in the process by myself. I had a strong enough knowledge of C, algorithm concepts, data structures and programing though.

If you have any question don't hesitate. Hopefully this will be of interest for you !
sword_stone (10).png (29.55 KB)
title
sword_stone (10).png
sword_stone (3).png (57.6 KB)
hero select
sword_stone (3).png
sword_stone (6).png (66.95 KB)
town
sword_stone (6).png
sword_stone (9).png (41.32 KB)
in game worldmap
sword_stone (9).png
sword_stone (7).png (47.49 KB)
castle
sword_stone (7).png
sword_stone (1).png (62.15 KB)
event1
sword_stone (1).png
sword_stone (4).png (61.13 KB)
event2
sword_stone (4).png

  View user's profile Send private message
  • Joined: 23 Jan 2010
  • Posts: 411
Reply with quote
Post Posted: Mon Feb 27, 2023 8:28 pm
Excellent graphics! You could port it for Master System?
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Mon Feb 27, 2023 9:14 pm
segarule wrote
Excellent graphics! You could port it for Master System?

Thanks :)

To make a proper port I think that everything should be redrawn with the target resolution of the console. So that would be a lot of work.

For now it is a GG project only.

Edit : also added the adventure music track in this post
sword_of_stone_adventure1_music.zip (14.54 KB)
adventure music

  View user's profile Send private message
  • Joined: 25 Feb 2006
  • Posts: 863
  • Location: Belo Horizonte, MG, Brazil
Reply with quote
Post Posted: Mon Feb 27, 2023 10:41 pm
Very impressive, so far! Please, do keep us updated.
  View user's profile Send private message Visit poster's website
  • Joined: 29 Mar 2012
  • Posts: 879
  • Location: Spain
Reply with quote
Post Posted: Mon Feb 27, 2023 10:42 pm
WOW!!
I really like it! it's a pity it's not for the SMS :-D
  View user's profile Send private message
  • Joined: 15 Jan 2018
  • Posts: 70
  • Location: Tokyo
Reply with quote
Post Posted: Tue Feb 28, 2023 1:50 am
Wow, this project got me excited. Graphics are colorful and allowing to choose 1 of 3 characters to start is great modern design.

To be honest it's interesting you chose the Game Gear, it gets less homebrew love than the SMS. It's true that any SMS homebrew is automatically compatible with GG, but I like your style.
  View user's profile Send private message
  • Joined: 15 Jan 2018
  • Posts: 70
  • Location: Tokyo
Reply with quote
Post Posted: Tue Feb 28, 2023 6:13 am
cireza wrote
I also have a McWill Game Gear and Everdrive (not sure if I should expect different behavior on a 100% original console).

Afaik an Everdrive is 99.9999% the real deal, short of burning an EPROM. I have a MiSTer and sometimes it won't boot a Sega homebrew or hack. Don't see that happening with Everdrives except with unsupported mappers maybe.

Incidentally I've read about the Everdrive not working on a McWill modded Game Gear because the power draw was too much. Replacing the power plug with USB-C fixes the issue.
  View user's profile Send private message
  • Joined: 29 Mar 2012
  • Posts: 879
  • Location: Spain
Reply with quote
Post Posted: Tue Feb 28, 2023 7:34 am
The only real difference with an everdrive, it's that writes the VRAM and the RAM when showing the menu, so any bug related to uninitialised memory may not happen in a everdrive but happen in a cart.
  View user's profile Send private message
  • Joined: 01 Feb 2014
  • Posts: 844
Reply with quote
Post Posted: Tue Feb 28, 2023 8:01 am
Welcome. Your project looks great. I’m looking forward to playing it.
It’s nice to see one more person who does everything (code, graphics, sound) by himself join our ranks. We are few. ;)

Quote
Assembly is too abstract/difficult for me and takes more time

I read this all the time, but I think it just depends on what you’re used to. For me, assembly is much (!) easier than C. I have basic knowledge of the latter, but only use it for the occasional mini-tool for sorting data and the likes. I couldn’t imagine writing a whole game in it. Besides, C actually adds a layer of abstraction. It literally can’t get less abstract than assembly, because it addresses everything so directly.

Anyway, it’s great to have both possibilities, so everything can use what he feels most comfortable with. DevkitSMS had certainly opened up development for many and we have seen an explosion of quality homebrew as a result. I just want to encourage anyone to not write off asm too quickly. It’s fun, trust me.
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14683
  • Location: London
Reply with quote
Post Posted: Tue Feb 28, 2023 8:16 am
Did you design the art to have square or rectangular pixels? A real Game Gear has significantly squashed pixels.

What emulator are you testing on? It looks a bit unfamiliar.
  View user's profile Send private message Visit poster's website
  • Joined: 29 Mar 2012
  • Posts: 879
  • Location: Spain
Reply with quote
Post Posted: Tue Feb 28, 2023 8:40 am
Kagesan wrote

I read this all the time, but I think it just depends on what you’re used to. For me, assembly is much (!) easier than C. I have basic knowledge of the latter, but only use it for the occasional mini-tool for sorting data and the likes. I couldn’t imagine writing a whole game in it. Besides, C actually adds a layer of abstraction. It literally can’t get less abstract than assembly, because it addresses everything so directly.


My biggest challenge with assembler is structuring and managing a big project. And I think this is quite common. For instance, I'm on a Megadrive Dev group with people from several countries. There's is like two thirds doing C, and one third doing assembler. The people doing things in C have already released several projects, but no assembler project has gone past the tech demo stage, except Mindtris.

@Maxim
I think he said it's gears system
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Tue Feb 28, 2023 9:26 am
Thank you for the responses.

@Jair : thanks for the feedback. My Everdrive works with my McWill console, so I am good on this part :)

@kusfo : indeed as the Everdrive already displays a menu, it means that things might have been initialized properly. I guess that using the rom in an emulator would show these issues.

@Kagesan : I understand that some are more familiar with assembly. What makes it abstract to me is the fact that you do not manipulate your variables directly. You load things in register, and then it is only about manipulating a, b, c etc... moving around registers. And I find it difficult to keep track. It's nice to have both choices indeed, assembly and C.

@Maxim : I designed the art without thinking too much about the aspect ratio, event though I know the console stretches to 4/3. It looks fine on my Game Gear, in my opinion. The emulator is Gear System, it has some good debugging features. Do you recommend some other ? I know there is Meka but the interface is too small for me, it is a bit difficult to read for long.
  View user's profile Send private message
  • Joined: 29 Mar 2012
  • Posts: 879
  • Location: Spain
Reply with quote
Post Posted: Tue Feb 28, 2023 9:56 am
Emulicious is probably the best emulator around. It's debugging capabilities have no match.

Btw, about the uninitialised memory, usually it works fine in emulators as they tend to set ram to 0. You can make the memory random on start-up in Emulicious through a setting.
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Tue Feb 28, 2023 10:12 am
kusfo wrote
Emulicious is probably the best emulator around. It's debugging capabilities have no match.

Btw, about the uninitialised memory, usually it works fine in emulators as they tend to set ram to 0. You can make the memory random on start-up in Emulicious through a setting.

Thanks, I will check this emulator. It looks promising.
  View user's profile Send private message
  • Joined: 16 May 2002
  • Posts: 1355
  • Location: italy
Reply with quote
Post Posted: Tue Feb 28, 2023 1:12 pm
Feel free to send me a private message if you'll ever want to write a multilingual manual, I'm always up to help when it comes to interesting projects, but my only skill is being Italian :U
  View user's profile Send private message Visit poster's website
  • Joined: 29 Mar 2012
  • Posts: 879
  • Location: Spain
Reply with quote
Post Posted: Tue Feb 28, 2023 1:26 pm
I can also help with Spanish (and Catalan :-p)
  View user's profile Send private message
  • Joined: 15 Aug 2019
  • Posts: 258
  • Location: Lancashire UK
Reply with quote
Post Posted: Wed Mar 01, 2023 12:47 pm
Wow, this looks very impressive. Well done., please do keep us posted on your progress.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Mar 02, 2023 9:47 am
kusfo wrote
Btw, about the uninitialised memory, usually it works fine in emulators as they tend to set ram to 0. You can make the memory random on start-up in Emulicious through a setting.


the whole RAM is initialized (zeroed) by the crt0 module if using devkitSMS, as C requires that global variables that aren't explicitly initialized to be in fact initialized to zero... but regarding VRAM (and CRAM), usually you load your own tiles and tilemap (and palettes) so it shouldn't be an issue.

Of course, if you just presume VRAM is zeroed (or CRAM) you might run into trouble as BIOSes or EverDrives boot ROMs will of course use these.

The best approach is always to presume nothing and load a background palette and a sprite palette, a tileset and a tilemap using only the tiles in the set and, last but not least, make sure you issue at least one SMS_initSprites and one SMS_copySpritestoSAT to ensure that there aren't sprites around (well - in case you're NOT using them!)

@cireza: amazing work so far! ❤️
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Thu Mar 02, 2023 7:53 pm
sverx wrote
one SMS_copySpritestoSAT

I see.

Actually when starting the game, I have a function to set palettes to black and put zeroes everywhere in VRAM, so it should also write the sprite table to 0. Maybe that this is a bit overkill after all haha.
  View user's profile Send private message
  • Joined: 18 Jul 2020
  • Posts: 367
Reply with quote
Post Posted: Thu Mar 02, 2023 10:23 pm
Game is coming along nicely, looks like a lot of love is being poured into it.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Mar 03, 2023 10:01 am
cireza wrote
Actually when starting the game, I have a function to set palettes to black and put zeroes everywhere in VRAM, so it should also write the sprite table to 0.


Counterintuitively, I know, filling the SAT with zeroes won't disable sprites, it will instead place all 64 of them in the upper left corner and they will use the contents of tiles that might be not empty because used by the background, so you might see 'something' up there and don't understand what's going on.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Fri Mar 03, 2023 10:30 am
sverx wrote
Counterintuitively, I know, filling the SAT with zeroes won't disable sprites, it will instead place all 64 of them in the upper left corner and they will use the contents of tiles that might be not empty because used by the background, so you might see 'something' up there and don't understand what's going on.

You are right. In fact, all sprites will use tile 0 and be set at X=0 and Y=0 when I do this initialization. I will add the method call to initialize the SAT correctly.
  View user's profile Send private message
  • Joined: 08 Apr 2005
  • Posts: 474
  • Location: Netherlands
Reply with quote
Post Posted: Sat Mar 18, 2023 9:47 am
That looks truly amazing! Quite pleased with a GG specific project too as I've refound my love for the GG a few years ago. Looking forward to this!
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Mon Mar 20, 2023 7:02 pm
S.F wrote
That looks truly amazing! Quite pleased with a GG specific project too as I've refound my love for the GG a few years ago. Looking forward to this!

Happy to hear that, thank you for your interest.

A small update (I won't be updating here every week, but I work on the game pretty much every week).

Since last time, I implemented :
- the third story of the game (text, events)
- made it half way through the fourth story
- made the music for the final boss
- drew the final boss
- implemented the save feature (works perfectly fine)
- took some decisions about the end game (game-design, story)
- reorganized quite a few banks
- decided to add colors in the text, to put some more life into it

This is pretty much a visual-novel, so I think it is a welcome addition. It actually proved being a bit tricky, since my letters are drawn with the sprite palette, which in reality is the "joker" palette with some gradients of each colors. I use it for pretty much everything, which means doing letters with other colors mean I can't palette swap but instead have entirely different tiles. So in the end I duplicated my letters.

I won't go into all the details of what made it complicated, but you quickly have exceptions to deal with (special characters that you might want colored or not, stopping the coloring when you reach a comma or full stop etc... Not sure that everything is 100% perfect, but it is pretty close).

The narrator speaks in beige, as it is a reference to the color of the book in the picture. Characters speak in white. Key words for places or characters use the color related to their specific kingdom.

I added a few screenshots for the text enhancements.
rom.png (3.78 KB)
text_color1
rom.png
rom-1.png (3.46 KB)
text_color2
rom-1.png
rom-2.png (3.07 KB)
text_color3
rom-2.png
rom-3.png (3.16 KB)
text_color4
rom-3.png

  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14683
  • Location: London
Reply with quote
Post Posted: Mon Mar 20, 2023 8:10 pm
If you have the tile space - and with two alphabets you probably do - you could try to make a variable width font renderer, allowing any number of colours and also font styles (like italic) and also much easier to read text. It’s a lot of work though.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Mon Mar 20, 2023 9:06 pm
Maxim wrote
If you have the tile space - and with two alphabets you probably do - you could try to make a variable width font renderer, allowing any number of colours and also font styles (like italic) and also much easier to read text. It’s a lot of work though.

Do you have an example of this ? Something like the Moldorian English patch maybe ? Not sure how this would help with colors though. Unless you edit the tile dynamically I guess.
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14683
  • Location: London
Reply with quote
Post Posted: Mon Mar 20, 2023 9:18 pm
Golden Axe Warrior does it. Basically you draw the pixels into the tiles on the fly for each letter. Thus you can use any colour you like - but you need to make code that draws letters (it can be easiest to do it a column at a time) into tiles at an arbitrary location. Calculating word wrapping is an extra challenge.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Mon Mar 20, 2023 9:28 pm
Maxim wrote
Golden Axe Warrior does it. Basically you draw the pixels into the tiles on the fly for each letter. Thus you can use any colour you like - but you need to make code that draws letters (it can be easiest to do it a column at a time) into tiles at an arbitrary location. Calculating word wrapping is an extra challenge.

Ok I see. This looks quite challenging, but it does look like a much better solution than trying to store all possible tiles when wanting to achieve this.

I think I will keep things "simple" in my case, I want to keep my ambitions in a technically reachable state so I can complete my game.

Word wrapping and window wrapping already required some thought process as I needed functions that would handle all of this logic directly (and not having to format anything by myself in the text banks). It also handles automatically which portrait to draw and codes starting by $ for coloring. That's already quite a lot for my first game (at least for me). Especially as I am debugging everything "by hand", as I code in C.

It could be an interesting subject of Proof of Concept at a later date, though.
  View user's profile Send private message
  • Joined: 14 Oct 2008
  • Posts: 508
Reply with quote
Post Posted: Tue Mar 21, 2023 1:06 am
Yeah, if it's your first time writing something, it's probably better to focus on something that functions properly before worrying about something that looks nice.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Tue Mar 21, 2023 8:09 am
cireza wrote
It actually proved being a bit tricky, since my letters are drawn with the sprite palette, which in reality is the "joker" palette with some gradients of each colors. I use it for pretty much everything, which means doing letters with other colors mean I can't palette swap but instead have entirely different tiles. So in the end I duplicated my letters.


Since the BG tiles can use both palettes, you could in theory use a single set in VRAM if you take care of using only 2 colors max at the same moment for your text and you carefully plan in advance the two palettes - which isn't easy at all, but possible.

Alternatively, you could reserve the 15th color of both palettes for text and make sure nothing else uses it, and redefine these two palette entries according to the two colors you need on screen for the text. But, yeah, it might not be as easy as I put it...
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Tue Mar 21, 2023 1:41 pm
Using two palettes is also a possibility (by using the same index and switching between BG or Sprite) but this limits to 2 colors at once indeed.

You really got me with this story of variable width. I have been thinking quite a bit about it. When I was experimenting with the console, I did write functions to merge monsters into the background by choosing which pixel to load. So this was basically tile forging on the fly (it was veeeeeery slow, especially in C and because I am not that good).

This made me understand how tiles are built. Each pixel is a reference to the number of the color in the palette, so a value between 0 and 15, and this requires 4 bits. However, these 4 bits are not contiguous, it would have been too simple.

They are scattered among the 4 first bytes of the tile. So basically, the first 4 bytes give you the information for the first line of 8 pixels. Of course writing in columns make this more complicated in this case. If it is only for choosing between color 0 and color 1, you can most probably skip 3 bytes out of the 4 bytes though.

I would have tiles ready in an array (for the characters) and they would be stacked to the left as much as possible, and another array would give me the length of the letter in pixels. Then I would write the data for only as many bits as the length. I would start writing the next letter either in the same tile by switching the bits to the right, or start a new tile when necessary.

I already have word wrapping and window wrapping. They work by counting tiles, I would simply have to count pixels instead (and use each letter's length in the process). This part doesn't sound super complicated. Multiplying is involved though, never a great thing.

For writing letters one after another I think it can be fast enough.

Well anyway, these are the thoughts coming to mind right now. Seems doable (especially if it is only black/white). However my letters use a gradient, and if I want to switch to any other color in the palette, I can't skip 3 bytes out of 4 when forging my tile. This will make it more complicated.
  View user's profile Send private message
  • Joined: 14 Oct 2008
  • Posts: 508
Reply with quote
Post Posted: Tue Mar 21, 2023 4:03 pm
For word wrapping, is it done by reading ahead one word before printing it on the screen?

I recall playing one DSi eShop game that did word wrapping only be checking one letter ahead. So it would partially print a word, before deciding it didn't fit and then erase and reprint it on the next line. Pretty ugly. (Despite a positive review on another site I read, that felt like one of the most mobile action-RPG I'd played. Aside from being microtransaction-free. :P Wouldn't be surprised if that WAS a mobile game that did it originally.)
  View user's profile Send private message
  • Joined: 01 Feb 2014
  • Posts: 844
Reply with quote
Post Posted: Tue Mar 21, 2023 6:05 pm
For fixed-width fonts, the sprite/bg palettes approach works quite well if you want to mark some words in a different color.

However, the variable-width font is where it gets interesting. Since you have to construct your tiles on the fly anyway, you can have four different text colors just by carefully building your palette. You can use the same font data for them and just put it into different bitplanes to make them different text colors.
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Tue Mar 21, 2023 7:11 pm
KingMike wrote
For word wrapping, is it done by reading ahead one word before printing it on the screen?

Yes. Read the whole word, see if it fits, if not, go to the next line or the next window.

Kagesan wrote

you can have four different text colors just by carefully building your palette.

With how I managed my text, I can have all the colors I want at once (from the sprite palette). There probably won't be many instances though, as it would become a bit jarring. But I get your point.

I started experimenting a bit this evening. However I can already see the difficulty of switching from one word to another when in the middle of creating a tile. With my current way of working, I can have a method to print one letter and go on with my life.

However in this case, I am not certain on how to proceed. It is as if the smallest entity I can deal with is a complete line, because I will never finish on a complete tile anyway. Which means having to read ahead an entire line, generate all tiles accordingly, then move on with the next line. So it is quite different from my current algorithm.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Wed Mar 22, 2023 12:54 pm
you could isolate the next whole word and calculate its width - if the remaining space on the current line is enough then render it, if it's not, then you have to start on the next line

working with variable width fonts is always interesting ;)
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Wed Mar 22, 2023 2:37 pm
sverx wrote
you could isolate the next whole word and calculate its width - if the remaining space on the current line is enough then render it, if it's not, then you have to start on the next line

working with variable width fonts is always interesting ;)

Yes this was my first thought (this is what I do right now already, simply with tiles instead of pixels). However, I don't really want to have to stop in the middle of writing a tile column by column, and having to resume writing in the middle of it.

It sounds a bit easier to read as many words as possible until I reach the limit of the line in terms of pixels, and then write all corresponding tiles straight. This probably makes coloring some words more difficult though.

I have prepared an algorithm I will give it a try at some point :) I will branch my code though because I am not sure to succeed.
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Thu Mar 23, 2023 9:05 pm
So I have been thinking about it and started coding something yesterday.

Here is the first result that shows some promise. Not perfect, but a good start :)
Capture.PNG (67.39 KB)
var_width
Capture.PNG
Capture2.PNG (63.38 KB)
var_width2
Capture2.PNG

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Mar 24, 2023 8:12 am
definitely promising! :)
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Fri Mar 24, 2023 9:00 am
sverx wrote
definitely promising! :)

Thanks :)


Edit 2 : well, I managed to solve the issue by simply moving the if in a dedicated function. I don't understand why it solved anything, but at least it works.

Initial post :

Well, I am currently stuck with an issue and I can't manage to find a solution.

I have a function that writes an entire line. Everything works as seen in the previous picture, except for the final tile, that has to be pushed manually at the end.

However for some strange reason, when I activate the final if that pushes the tile, it corrupts the entirety of the line, which is supposed to have been already written.

It seems that whatever the value I put in this final if, it is always verified. As soon as I comment the final SMS_loadTiles (in the final if), everything returns to working fine.

Here, I am sharing the entire function in case you see something obvious. I have thought about this algorithm quite a bit, but there must be something I am missing ?

I am suspecting that for some reason I exit the initial for all the time and go through the if, but I am unsure. The very first column of each is still fine in the "corrupted" picture.

Edit : so I checked, I can tell that the condition for the if is fine, it is not always true, but works as expected. The max_valid_cpt value is 26 for the first line, so this works as well.

I tried putting some debug tiles at places. I also put all my letters at size 8, so I never validate the if (I have verified that it is the case).

If I write a letter at the very end of the function, it displays correctly (I put a B in the portrait). However, as soon as I put a SMS_loadTiles in my if (ex: loading a letter A in the portrait), right after the while, even though I never go through the if, all my letters get garbled...

I added examples of tests as pictures.


void display_line_vari(const char message[], unsigned char bank,
      unsigned char lineNb, unsigned char max_valid_cpt) {

   unsigned char i, j, letter_column_cpt = 0, mem_position = 0, tile_column_cpt = 0;
   unsigned char tile_for_mem[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
   unsigned char letter_size = 0;
   const unsigned char* letter_tile;

   //iterate until reach max_valid_cpt position for this line
   for(i = 0; i < max_valid_cpt; i++) {

      //get letter tile and letter size
      SMS_mapROMBank(bank);
      letter_tile = get_letter_vari_tile(message[i]);
      SMS_mapROMBank(bank);
      letter_size = get_letter_size(message[i]);
      letter_column_cpt = 0;

      SMS_mapROMBank(BANK_ALPHABET_VARI);

      //process all columns for the letter
      while(letter_column_cpt < letter_size) {

         //fill the current letter column in the current tile for memory column
         for(j=0; j < 32; j++)
            tile_for_mem[j] = tile_for_mem[j] | ( ( (letter_tile[j] & ((0b10000000) >> letter_column_cpt)) << letter_column_cpt ) >> tile_column_cpt ) ;

         //advance one column in tile for memory
         tile_column_cpt++;
         //advance one column in letter tile
         letter_column_cpt++;

         //when a tile is complete, write it to memory and init new tile
         if(tile_column_cpt == 8) {

            SMS_loadTiles(&tile_for_mem[0], 160+mem_position+lineNb*32, 32);

            mem_position++;

            for(j=0; j < 32; j++) tile_for_mem[j] = 0;

            tile_column_cpt = 0;
         }
      }
   }

   //complete end of line tile with black columns
   //ALWAYS TRUE, WHY ? EVEN IF I PUT > 254
   if(tile_column_cpt > 0) {

      letter_tile = get_letter_vari_tile(' ');

      while(tile_column_cpt < 8) {

         for(j=0; j < 32; j++)
            tile_for_mem[j] = tile_for_mem[j] | ( ( (letter_tile[j] & ((0b10000000) >> letter_column_cpt)) << letter_column_cpt ) >> tile_column_cpt ) ;

         tile_column_cpt++;
         letter_column_cpt++;
      }

      //IF I COMMENT THIS, NO MORE CORRUPTION IN LINES
      SMS_loadTiles(&tile_for_mem[0], 160+mem_position+lineNb*32, 32);
   }
}

Capture1.PNG (136.13 KB)
debug_size_8_A_and_B
Capture1.PNG
Capture2.PNG (131.38 KB)
debug_size_8_B_only
Capture2.PNG
Capture4.PNG (129.48 KB)
debug_size_variable_B_only
Capture4.PNG
Capture3.PNG (145.56 KB)
debug_size_variable_A_and_B
Capture3.PNG
Capture5.PNG (64.95 KB)
Victory ! :)
Capture5.PNG

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Mar 24, 2023 10:49 am
It's hard to spot an issue in that source, but I wouldn't rule out a bug in SDCC, as sometimes it happens they show up - mostly when the function gets a bit complex, so one workaround is usually to try breaking down into smaller functions and see if one can either solve or isolate a bug to submit to the SDCC team (whom are always improving their software).

Also never rule out a bug in devkitSMS too, I found many myself.

As an added suggestion though I think it's not a good idea to have local arrays in a function, they end up being pretty slow and may make SDCC generate more overhead than usual. It's better to have some static temporary array outside the functions, and you can reuse that for many things too. It's not a huge waste of memory, after all.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Fri Mar 24, 2023 12:51 pm
sverx wrote
It's hard to spot an issue in that source, but I wouldn't rule out a bug in SDCC, as sometimes it happens they show up - mostly when the function gets a bit complex, so one workaround is usually to try breaking down into smaller functions and see if one can either solve or isolate a bug to submit to the SDCC team (whom are always improving their software).

Also never rule out a bug in devkitSMS too, I found many myself.

I tend to rarely incriminate tools I use, because 99% of the time the error is my own. I did happen to find at a few occasions issues in some tools I used in my job (like a database driver, for example).

I do suspect though that something strange is happening at compilation in my case, and using a separate function actually solved the issue.

sverx wrote

As an added suggestion though I think it's not a good idea to have local arrays in a function, they end up being pretty slow and may make SDCC generate more overhead than usual. It's better to have some static temporary array outside the functions, and you can reuse that for many things too. It's not a huge waste of memory, after all.

Thank you, your advice is appreciated. I moved the array outside the function. I still have to optimize all of this, I was searching for a working feature first and foremost :)
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Mar 24, 2023 1:42 pm
cireza wrote
I tend to rarely incriminate tools I use, because 99% of the time the error is my own. I did happen to find at a few occasions issues in some tools I used in my job (like a database driver, for example).


Yes, it almost always turns out that it's your own code at fault - and I didn't mean to say "yeah, SDCC is buggy" but just wanted to warn you that sometimes it happens, and in that case the only workaround is to do something differently.

For example, this is the last SDCC bug (now fixed) I submitted regarding code generation. That could have affected your code too, for instance, hard to tell without checking the generated asm.
  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14683
  • Location: London
Reply with quote
Post Posted: Fri Mar 24, 2023 3:37 pm
I’m simultaneously impressed with your results and apologetic for sending you down this path :) But it is clearly a massive improvement to readability. I’d also suggest you should test on a real Game Gear as maybe it needs a chunkier font.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Fri Mar 24, 2023 5:46 pm
Maxim wrote
I’m simultaneously impressed with your results and apologetic for sending you down this path :)

I am going to be very honest : I had a hard week because of this xD

I am relieved that it works, however performance is not where it should be. I have to change my algorithm. I already have an idea, but I think I will implement this in a couple days. At least it ended up not taking much more code space (currently at 80% and I still have to implement the end of the game). Code banking is a thing, I know, but I am planning on keeping it below 32 KB.

I will also try on a Game Gear, to make sure. Not sure of the meaning of "chunkier" though (I am French). Does it mean I have to make bigger/larger characters ?

Right now I have tried two things :
- without space between letters
- with space between most letters

See pictures below (I implemented back the color feature as well).

Edit : I experimented quite a bit and decided to go with larger letters, I believe this is what you suggested. I tried several other things in the process, but nothing turned out great, so I stayed on this solution for the best readability (latest_version picture)

By the way I checked Golden Axe Warrior and the developers actually use a 10 pixels high font, which is absolutely insane. They write 4 lines of text in 5 lines of tiles.
Capture.PNG (60.17 KB)
latest_version
Capture.PNG

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sat Mar 25, 2023 1:21 pm
cireza wrote
By the way I checked Golden Axe Warrior and the developers actually use a 10 pixels high font, which is absolutely insane. They write 4 lines of text in 5 lines of tiles.


At that point it's probably closer to having a bitmap mode and address pixels directly. But I didn't check the code, just wondering.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 122
  • Location: France
Reply with quote
Post Posted: Sat Apr 08, 2023 8:27 am
Hello,

I have been making good progress recently with the game. However, there is one little thing that I have witnessed ever since I created my functions for fadeIn fadeOut effects : I get some random colored dots on screen for a fraction of a second.

The issue disappears if I make the effect slower (more use of vblanks). See picture for example.

My understanding is that I might be updating the palettes at a moment that is not appropriate, but I am not too sure.

I can share the code if it helps. I will keep searching in case I find the solution by myself, but any advice will be appreciated.
rom-1.png (1.32 KB)
fadeIn issue
rom-1.png

  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 593
  • Location: London, UK
Reply with quote
Post Posted: Sat Apr 08, 2023 8:59 am
They are so-called "CRAM dots" - if you write a value to CRAM during active display the write operation briefly overrides the colour value sent to the display, appearing as a dot on screen.

Assuming you're using SMSLib's new-ish SMS_loadBGPaletteafterColorSubtraction functionality? I'm seeing the dots too on my latest game.

You can see from Event Viewer on Emulicious that the CRAM writes do indeed encroach into active display (see attached). The SMS_loadBGPaletteafterColorSubtraction function loops 16 times, calculates a new value and writes to CRAM. Not sure whether it can be optimised much further than it is - one for @sverx I guess!
cram.png (14.49 KB)
cram.png

  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 593
  • Location: London, UK
Reply with quote
Post Posted: Sat Apr 08, 2023 9:20 am
UPDATE: @cireza, not sure if you are making the same mistake as me, but I've figured out an improvement at least on my side.

I was trying to fade both background and sprite palettes within a single frame, which doesn't fit very well at all.

I tried moving one of my SMS_waitForVBlank calls between the two palette fades and now I see much fewer dots, although there are still some in the bottom border. I guess that's pretty much unavoidable though, without trying to finesse a delay so that the code runs in vblank proper.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sat Apr 08, 2023 9:33 am
Last edited by sverx on Sat Apr 08, 2023 9:45 am; edited 1 time in total
there's a way to avoid CRAM dots appearing on screen, but you need to time exactly the moment your update takes place.
Basically during vblank the VDP draws the bottom border, the retraces the beam to the top part of the screen, then draws the top border. If you update the palettes exactly in the retrace part you won't see any CRAM dot on the top/bottom border.

But this is easier said than done, as the retrace is pretty quick and to time to that even correctly you have to poll the vCount counter and act accordingly to the 50/60 Hz refresh rate of your TV/consolle. (There was a thread where we were discussing these numbers, let me see if I can find it...)

edit: it's here. Scroll for the PAL values.
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 593
  • Location: London, UK
Reply with quote
Post Posted: Sat Apr 08, 2023 9:39 am
Last edited by willbritton on Sat Apr 08, 2023 9:58 am; edited 2 times in total
Super super hacky, but I managed to finesse my fade in / out wrapper code so that it doesn't update in the border, here:

https://gist.github.com/willbritton/6f2218094561e758bc4a5870bd1661d5/232bb8b031d...

As you can see I've butchered the functions from SMSLib and put them inline.

As sverx says, will depend on refresh rate, plus almost certainly sensitive to compiler optimisation (I am using --opt-code-speed on this one) and SDCC version etc.

Looking at vcount during the pre-calc loop would be an optimisation.
  View user's profile Send private message Visit poster's website
Reply to topic Goto page 1, 2, 3, 4  Next



Back to the top of this page

Back to SMS Power!