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 - devkitSMS - develop your homebrew in C

Reply to topic Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8
Author Message
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Sat Aug 20, 2016 10:26 pm
sverx wrote
If your map is, say, 96 tiles wide and 24 tiles tall, your tilemap is 96*24*2 bytes and the tiles are stored as successive lines, the way you read a book, you see.
So the tile at x,y in your map is stored at position y*width+x, and since we've got a byte array the address is (y*width+x)*2
That's what you need for your setTile


Got it, but now i ran into a different problem. It seems to not be putting tiles mirrored. I have a tree that on in right end is not mirrored. How do i include the flags for those tiles?

   SMS_setNextTileatXY(nextTile, i);
     SMS_setTile(moltaarea1__tilemap__bin[(i*96+nextColumn)*2]);
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Sat Aug 20, 2016 10:54 pm
Orlan Rod wrote
Got it, but now i ran into a different problem. It seems to not be putting tiles mirrored. I have a tree that on in right end is not mirrored. How do i include the flags for those tiles?

   SMS_setNextTileatXY(nextTile, i);
     SMS_setTile(moltaarea1__tilemap__bin[(i*96+nextColumn)*2]);


The problem arises from the fact that the array it's an array of char instead of int, so you should cast it, as in:

*(unsigned int *)(&moltaarea1__tilemap__bin[(i*96+nextColumn)*2])
  View user's profile Send private message Visit poster's website
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Sat Aug 20, 2016 11:09 pm
sverx wrote
Orlan Rod wrote
Got it, but now i ran into a different problem. It seems to not be putting tiles mirrored. I have a tree that on in right end is not mirrored. How do i include the flags for those tiles?

   SMS_setNextTileatXY(nextTile, i);
     SMS_setTile(moltaarea1__tilemap__bin[(i*96+nextColumn)*2]);


The problem arises from the fact that the array it's an array of char instead of int, so you should cast it, as in:

*(unsigned int *)(&moltaarea1__tilemap__bin[(i*96+nextColumn)*2])


Sweet, that indeed fixed it. Thanks.

One last thing with the map. I noticed that once i scroll passed the second screen, coming onto the third screen of tiles, it starts placing data randomly. I'm not sure if i hit a limit or it's some value i did not reset.

EDIT. Nevermind, it indeed was that i needed to reset a increment to zero, after 32.
  View user's profile Send private message
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Sun Aug 21, 2016 3:36 am
Works great for the map scrolling to the left, but i can't seem to get to scroll right. Here the current function for the left.

  void manipBG (void) { if (scrollDir[0] == 1){

     if (nextColumn < 96){

     for (i=0; i < 24; i++){

     SMS_setNextTileatXY(nextTile, i);
     SMS_setTile(*(unsigned int *)(&moltaarea1__tilemap__bin[(i*96+nextColumn)*2])); //next column is after the first 32 tiles of the next screen. i is the row to pick. 96 is width of the tilemap in tiles. We cast to int, to have tile mirror flogs.
     }
     i = 0;
     nextColumn++;
     if (nextTile < 32) { nextTile++; } else { nextTile = 0; }
     }

  }

}

     ks=SMS_getKeysStatus();
    if ((ks & PORT_A_KEY_RIGHT) && (nextColumn < 96)) {
    scrollDir[0] = 1;
    scroll++;
    SMS_setBGScrollX(-(scroll));

    SMS_waitForVBlank();
    if ((scroll % 8)==0) { manipBG(); }
    }


  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Mon Aug 22, 2016 7:52 am
I suggest you create two separate functions, one for filling in the column on the right, when scrolling right, and one function for updating the column on the left, when you scroll left. Anyway they're pretty similar, so once you've got one working it's a matter of a bit of reasoning to make the other work too :)
  View user's profile Send private message Visit poster's website
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Mon Aug 22, 2016 8:39 pm
sverx wrote
I suggest you create two separate functions, one for filling in the column on the right, when scrolling right, and one function for updating the column on the left, when you scroll left. Anyway they're pretty similar, so once you've got one working it's a matter of a bit of reasoning to make the other work too :)


void scrollLeft(void){

     for (i=0; i < 24; i++){

     SMS_setNextTileatXY(nextTile, i);
     SMS_setTile(*(unsigned int *)(&moltaarea1__tilemap__bin[(i*96+nextColumn)*2])); //next column is after the first 32 tiles of the next screen. i is the row to pick. 96 is width of the tilemap in tiles. We cast to int, to have tile mirror flogs.

     }
     i = 0;
     nextColumn++;
     if (nextTile < 31) { nextTile++; } else {  nextTile = 0;  }

}

    ks=SMS_getKeysStatus();
     

    if ((ks & PORT_A_KEY_RIGHT) && (screenIndex < 64)) {

    scrollDir[0] = 1;
    scroll++;

    SMS_setBGScrollX(-(scroll));

    SMS_waitForVBlank();
    if ((scroll % 8)==0) { scrollLeft();  screenIndex+= 1; }

    }


Updated the scroll code a bit, and added screenIndex to prevent it from scrolling past the width of the map. So i get i need to update the last column on the right to scroll the opposite way, but i don't get how to draw the column from the location i stopped from in memory.

Besides that problem, How do i blank the last 8 pixels on the right side of the screen?
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Tue Aug 23, 2016 8:08 am
Orlan Rod wrote
How do i blank the last 8 pixels on the right side of the screen?


As already said:
sverx wrote
Blanking the leftmost column is the correct thing to do... also because it's the only option supported by hardware.


To handle scrolling in both direction, you should have a variable holding your horizontal position on the map and remember that when you update the column on the left you should use that variable and when updating the column on the right you should use that variable+32, as you're 32 tiles on the right.
  View user's profile Send private message Visit poster's website
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Tue Aug 23, 2016 2:16 pm
sverx wrote
Orlan Rod wrote
How do i blank the last 8 pixels on the right side of the screen?


As already said:
sverx wrote
Blanking the leftmost column is the correct thing to do... also because it's the only option supported by hardware.


To handle scrolling in both direction, you should have a variable holding your horizontal position on the map and remember that when you update the column on the left you should use that variable and when updating the column on the right you should use that variable+32, as you're 32 tiles on the right.


Blanking is unnecessary as of now though. Apparently i figured out the reason i was seeing a column update on the right side. Was that i needed to put the column update code before the scrolling. A timing issue.

Ah okay. I'll try that.
  View user's profile Send private message
  • Joined: 17 Nov 2015
  • Posts: 92
  • Location: Canada
Reply with quote
Post Posted: Sun Aug 28, 2016 6:21 pm
sverx wrote

Please do! I'll be very interested to see which changes are necessary... I can surely put in some conditional defines for supporting both compilers with the same source code.


It's been difficult to find the time but hopefully I can finish most of it today. Have you got some example projects available for testing?

SMSlib is almost all assembly, written inlined in C functions. I decided just to move everything to asm, one asm function per file to allow the linker to pick up the minimum amount of code needed from the lib. What I hadn't counted on is the sheer number of functions in the lib so it's taking much longer than I thought it would. I initially thought an evening, I was quite wrong about that :P.

Some functionality is available as inlined asm defined in the header file. Inlined asm disrupts sdcc's peephole optimizer so that code generated just prior to any inlined asm will be suboptimal (this is much less important with native sdcc as sdcc itself has few peephole rules but this is a noticable issue in z88dk because there are many more rules). Inlined asm is also quite dangerous because sdcc can place important values in registers before the inlined asm and it expects those registers to hold those values after the inlined asm. If the inlined asm changes register values, this can lead to crashes. The chance of incorrect code resulting increases if the inlined asm appears in the middle of C code as opposed to the beginning or end of a function.

We do have a way to inline asm safely without affecting optimization but it requires adding functions to a list compiled into the compil. This has been used for code size optimization and implementing intrinsics (a method for inlining simple instructions like "di"). Adding SMSlib specific functions would affect every port in z88dk and wouldn't make sense to do, but I can see the need so I will be looking at a way to add these sorts of functions at compile time via a user-supplied file. Anyway, before that is done I think I will turn those inlined asm functions into regular fastcall functions. The cost will be an extra call/ret but hopefully some of that is recouped from gains during peephole optimization.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Mon Aug 29, 2016 8:00 am
So you're kind of rewriting SMSlib from the ground... well, I didn't think to go that far, but that's fine with me, it's open source. What I can't do is to maintain both versions, unfortunately, but if it's OK with you, I could work on merging the two versions so to have a better (faster/smaller) SMSlib... but of course the result should still be compatible with SDCC.
  View user's profile Send private message Visit poster's website
  • Joined: 17 Nov 2015
  • Posts: 92
  • Location: Canada
Reply with quote
Post Posted: Thu Sep 01, 2016 7:24 pm
sverx wrote
So you're kind of rewriting SMSlib from the ground... well, I didn't think to go that far, but that's fine with me, it's open source. What I can't do is to maintain both versions, unfortunately, but if it's OK with you, I could work on merging the two versions so to have a better (faster/smaller) SMSlib... but of course the result should still be compatible with SDCC.


Yes that's fine. It's not really a rewrite, it's just moving the asm source out of the c source and making sure there is one function per file so that the linker is able to pull the minimum amount of code required by the program out of the library. There are a couple of things that I will change -- inlined asm macros can potentially lead to buggy code because the compiler expects register values to be preserved across the inlined asm -- so for now I've turned those into fastcall functions but will find a general solution at a later time (a short term solution would be to put push/pop around the inlined asm macros). I noticed a couple of bugs too so I will bring those to your attention when I go through everything again.

What I would like to do is find a way to do this that keeps the codebase compatible with sdcc but I'm not sure yet if that is possible. There is another large sdcc project I would like to accommodate with z88dk too - it would likely shrink the code by 20% under z88dk - but you don't want to mess up the codebase or take away sdcc compatibility since in this case sdcc is being used to target other processors.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Fri Sep 02, 2016 7:54 am
Alcoholics Anonymous wrote
I noticed a couple of bugs too so I will bring those to your attention when I go through everything again.


Thank you! :)
  View user's profile Send private message Visit poster's website
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Wed Sep 21, 2016 8:08 pm
This is the three issues i am having with the scrolling.

1. If i scroll all the way to the right of the screen, than scroll back, the column that is updating appears visible past the blank for a couple of scrolls.

2. I don't know how to implement the scroll/8 properly for the horizontal movement. It works on the x value, but not inside the bin. This would fix that issue with the column appearing a couple scrolls left.

3.I get a hitch scrolling down, before it gets to the last couple of tiles. happens at the 255 scrollV value.

I have attached the source files. Thanks. Yes i know the text display function is slow. Just using it for prototyping. 8p
Titanium Engineers.zip (253.78 KB)
Source file

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Thu Sep 22, 2016 8:22 am
scrollLeft(): for some reason you're doing
SMS_loadTileMap(((scrollH/8)%31), .....

but the tilemap is still 32 tiles wide, even if the leftmost column is hidden. Changing that to 32 seems to fix the horizontal scroll.

as for the vertical scroll, you should remember that even the vertical scroll value wraps at 28 tiles, so anything beyond 224 won't work as expected.
In short:
instead of
SMS_setBGScrollY(scrollV);

you should do
SMS_setBGScrollY(scrollV%224);

and that's it.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Thu Sep 22, 2016 3:45 pm
sverx wrote
STMcompressed maps can't (still?) be used for storing maps not using whole lines


I'm working on it. I remember tibone needed that...
  View user's profile Send private message Visit poster's website
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Thu Sep 22, 2016 4:25 pm
sverx wrote
scrollLeft(): for some reason you're doing
SMS_loadTileMap(((scrollH/8)%31), .....

but the tilemap is still 32 tiles wide, even if the leftmost column is hidden. Changing that to 32 seems to fix the horizontal scroll.

as for the vertical scroll, you should remember that even the vertical scroll value wraps at 28 tiles, so anything beyond 224 won't work as expected.
In short:
instead of
SMS_setBGScrollY(scrollV);

you should do
SMS_setBGScrollY(scrollV%224);

and that's it.


It looks like it does fix it, but i tried that before. If you look at the first rectangle window on the left. You can see that it becomes longer in width, when you scroll back to the left. So it's still a problem.

Yep. The vertical scroll is now fixed with that. Thanks!
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Thu Sep 22, 2016 5:06 pm
Orlan Rod wrote
It looks like it does fix it, but i tried that before. If you look at the first rectangle window on the left. You can see that it becomes longer in width, when you scroll back to the left. So it's still a problem.


Wow, I didn't notice that. So there's a second bug on the same call, probably in the source address (where to get data from ROM).
  View user's profile Send private message Visit poster's website
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Thu Sep 22, 2016 8:00 pm
sverx wrote
Orlan Rod wrote
It looks like it does fix it, but i tried that before. If you look at the first rectangle window on the left. You can see that it becomes longer in width, when you scroll back to the left. So it's still a problem.


Wow, I didn't notice that. So there's a second bug on the same call, probably in the source address (where to get data from ROM).


Needed to change the nextColumn-32 to nextColumn-34.
  View user's profile Send private message
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Thu Sep 22, 2016 10:10 pm
Oh i forgot. How would i implement the scrollH/8 into the bin for scroll right/left?
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Fri Sep 23, 2016 7:47 am
...beg your pardon?
  View user's profile Send private message Visit poster's website
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Sat Sep 24, 2016 3:27 am
sverx wrote
...beg your pardon?


This part of the code, is missing the scrollH for the bin side. So, when you scroll back and forth fast, it will be misaligned in drawing tiles.

SMS_loadTileMap(((scrollH/8)%32), iloop, &electronlvl__tilemap__bin[iloop*72*2]+(nextColumn+32), 1*2);
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Mon Sep 26, 2016 11:42 am
The matter here is that you're using two variables... if you want to do that, you should keep them absolutely synced or you'll experience problems.
I would use a single variable instead. You can use your scrollH/8 instead of having a separate nextColumn, just fixing the constants around that.

edit: if you need to load a single tile, I also wouldn't use SMS_loadTileMap. Use SMS_setNextTileatXY(x,y); SMS_setTile(tile); instead, as it's faster.
  View user's profile Send private message Visit poster's website
  • Joined: 28 May 2015
  • Posts: 55
Reply with quote
Post Posted: Mon Sep 26, 2016 9:03 pm
sverx wrote
The matter here is that you're using two variables... if you want to do that, you should keep them absolutely synced or you'll experience problems.
I would use a single variable instead. You can use your scrollH/8 instead of having a separate nextColumn, just fixing the constants around that.

edit: if you need to load a single tile, I also wouldn't use SMS_loadTileMap. Use SMS_setNextTileatXY(x,y); SMS_setTile(tile); instead, as it's faster.


I used your suggestion, and tried implementing the split screen example version. But i could not get it to work with the original code. Only re implementing the nextColumn as shown in the comments, could i get it to display correctly. But the scrollH/8 has not effect on it, it seems.


    //p=&electronlvl__tilemap__bin[iloop*(scrollH/8)+(32+nextColumn)];
  // p=&electronlvl__tilemap__bin[iloop+(32+nextColumn)];
  p=&electronlvl__tilemap__bin[(scrollH/8)+32];
for (iloop=0; iloop < 28; iloop++)
  {
    SMS_setNextTileatXY(scrollH/8,iloop);
    SMS_setTile(*p);
    p+=72;
  }
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Tue Sep 27, 2016 8:27 am
Orlan Rod wrote
I used your suggestion, and tried implementing the split screen example version. But i could not get it to work with the original code.


Actually, there's a caveat. In my split-screen example, I declared my tilemaps as unsigned int arrays, as I'm using the newer assets2banks tool instead of the old and less powerful folder2c.
This way I can easily move the p pointer n tiles ahead simply doing
p+=n;

which won't work correctly if your array is made of unsigned chars.

In general, I suggest you make a single change to your code a time... (or you start over with a new approach using assets2banks)
  View user's profile Send private message Visit poster's website
  • Joined: 01 Jan 2014
  • Posts: 294
Reply with quote
Post Posted: Tue Oct 18, 2016 11:25 pm
Hi,

What is the fastest way to write a char / int to vram. Currently updating nametable entries but running in to performance issues. The unsafe methods in tutorial are for fixed length writes based on pointers.

Currently using SMS_loadTileMap() but have since noticed, SMS_setTileatXY(), SMS_setNextTileatXY(), SMS_setTile() in this thread.

Also i noticed some odd behavior with SMS_VRAMmemcpy_brief(). It seams to be wrapping to 256 when provided with a size of zero. Yes... I am calling this potentially with zero, it is due to some palette cycling thing where it may or may not need to write to cram. I have worked around it but thought it might be good to know.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Wed Oct 19, 2016 7:57 am
If you need to write a single int, then it's SMS_setTile(), provided you've already set the target address.
If you need to load a bunch of bytes, then the fastest it's one of the UNSAFE_SMS_VRAMmemcpy**() functions, but actually I'm supporting only 32, 64 and 128 bytes (and of course this should run only when in vBlank or when screen is off).
As for SMS_VRAMmemcpy_brief(), well, I simply forgot to state it clearly that it copies from 1 to 256 bytes, where 0 means in fact 256.
For palette cycling effects I suggest calling a single SMS_setNextBGColoratIndex() or SMS_setNextSpriteColoratIndex() and the desired calls to SMS_setColor() according to how many palette entries you need to change.

edit: if your need isn't covered yet, we might work on adding some specific functions. Try to explain me what you need to do and we'll see :)
  View user's profile Send private message Visit poster's website
  • Joined: 01 Jan 2014
  • Posts: 294
Reply with quote
Post Posted: Wed Oct 19, 2016 9:53 am
I thought SMS_VRAMmemcpy_brief() behavior might be by design.

No need to add functions. I am happy to work within what you have. With the comp 2 weeks away i thought i would check the devkit out and make a small intro type entry. I am trying things out and seeing what i can get going.

I do have another question though, does SMS_copySpritestoSAT() write a complete sat table or just sprites added?

EDIT: never mind worked it out :)
  View user's profile Send private message
  • Joined: 25 Jul 2007
  • Posts: 540
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Thu Sep 14, 2017 3:24 am
Since printf() normally outputs to stdout, how is this being handled that it is able to use bitmapped text? I couldn't find the implementation in the headers or source.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Thu Sep 14, 2017 7:54 am
printf() make calls to putchar() - you can read the source in SMSlib_textrenderer.c.

before using that you should load a font (either full color or 1bpp), set some colors in the palette, configure the text renderer to map chars to tiles (see SMS_configureTextRenderer() in the same source) and turn on the screen.
If you're just experimenting, you can use SMS_autoSetUpTextRenderer() which will do all that for you (you'll use a standard font and BG colors 0 and 1 in that case)
  View user's profile Send private message Visit poster's website
  • Joined: 25 Jul 2007
  • Posts: 540
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Thu Sep 14, 2017 8:11 am
That makes sense now.

I'm already using the auto text function for prototyping a text based engine.

I noticed it was not handling \n newline character and wanted to either extend the existing function or roll my own.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Thu Sep 14, 2017 10:03 am
yes, it doesn't handle any console chars, as it's just a very plain simple text renderer (in fact it simply doesn't do anything more than an ASCII to tile translation)
  View user's profile Send private message Visit poster's website
  • Joined: 25 Jul 2007
  • Posts: 540
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Thu Sep 21, 2017 11:52 am
Is there a function or way of getting the current address or location that SMS_setTile will point to?
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Thu Sep 21, 2017 12:16 pm
Unfortunately no, there's no way of reading the VDP address register, thus it's impossible. Depending on what you need to do, you should either keep track of the location yourself or issue more SMS_setNextTileatXY calls to ensure you're setting tiles where you'd like to.

Post here what you're trying to achieve, we'll try to help you :)
  View user's profile Send private message Visit poster's website
  • Joined: 25 Jul 2007
  • Posts: 540
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Fri Sep 22, 2017 3:26 am
As mentioned earlier I am writing a text based engine (for old school text based adventures). As part of that I was writing my own printf function to handle console control characters.

In order to position text within the screen it's necessary to know where the current cursor (in this case sms_settile) is pointing.

Currently I have a kind of hack way of handling this by calculating the current row based on characters output divided by the number of columns:


void q_printf(const char * format, ...)
{
   va_list args;
   char buffer[1024];
   int i;
   int tabstop = 4;

   va_start (args, format);
   vsprintf(buffer, format, args);
   va_end (args);
   
   for(i=0; i<1024; i++)
   {
      if(buffer[i] == NULL) break;
      else if (buffer[i] == '\n')
      {
         int row = (i / 32) + 1;
         SMS_setNextTileatXY(0, row);
      else if (buffer[i] == '\t')
      {
         //
      }
      } else
         SMS_setTile(buffer[i]-32);
   }
}


This obviously won't work for any text that doesn't originate at 0,0

Normally with objects (sprites, tiles) they would have their own structure that tracks the current x,y position, but since we are dealing with serialized output that won't work.

I suppose I could wrap the SMS_setNextTileatXY function and have it update a global variable with the x,y position and make the q_printf function update those coordinates based on number of output characters.
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 11873
  • Location: London
Reply with quote
Post Posted: Fri Sep 22, 2017 6:22 am
The console routine needs to maintain its own x, y and use that to set the VRAM x, y. The Zexall code implements this (in assembly), including newlines. You should probably take it one step further and support word wrap too.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1940
Reply with quote
Post Posted: Fri Sep 22, 2017 6:46 am
devkitSMS/SMSlib doesn't offer any 'real' console functions at the moment, but just a very basic text renderer, as you can see. You might get away with a simple solution, for instance if you just need to manage line breaks - or you might need something more powerful... and I can suggest you to check z88dk's 'speechbubbles' demo, here.

I might later work on adding proper console functions, if there's request.
  View user's profile Send private message Visit poster's website
  • Joined: 25 Jul 2007
  • Posts: 540
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Fri Sep 22, 2017 7:37 am
I already made a functional prototype after my last post and thinking about it:


#include "SMSLib.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>

unsigned int cursor_x = 0, cursor_y = 0;

void q_SMS_setNextTileatXY(unsigned int x, unsigned int y);
void q_printf(const char * format, ...);

void main(void)
{
   char description[] = "You are in a room. A most wonderful room.\nWe have the best rooms here!\n1\n\t2\n3";    
   SMS_autoSetUpTextRenderer();
   
   q_printf("%s", description);
}

void q_SMS_setNextTileatXY(unsigned int x, unsigned int y)
{
   cursor_x = x;
   cursor_y = y;
   SMS_setNextTileatXY(x, y);
}

void q_printf(const char * format, ...)
{
   va_list args;
   char buffer[1024];
   int i;
   int tabstop = 4;

   va_start (args, format);
   vsprintf(buffer, format, args);
   va_end (args);
   
   for(i=0; i<1024; i++)
   {
      if(buffer[i] == NULL) break;
      else if (buffer[i] == '\n')
      {
         q_SMS_setNextTileatXY(0, ++cursor_y);
      }
      else if (buffer[i] == '\t')
      {
         //
      } else
         SMS_setTile(buffer[i]-32);
      
      if(++cursor_x == 32)
      {
         cursor_y++;
         cursor_x = 0;
      }
   }
}


Ultimately I will flesh this out to a proper console routine.

To put it a different way, it's not that I didn't know how to implement this myself, rather the point usually of using a standard library is not having to do that yourself so I wanted to try and work with what was already available. Unfortunately without compiling a customized version of devkitsms that wasn't possible because some of the required internal routines are not exposed via the library.
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 11873
  • Location: London
Reply with quote
Post Posted: Fri Sep 22, 2017 8:06 am
A regular console won't do word wrapping for you. However, a console handler (maybe even in a window) would be the sort of thing you could share...
  View user's profile Send private message Visit poster's website
  • Joined: 17 Nov 2015
  • Posts: 92
  • Location: Canada
Reply with quote
Post Posted: Fri Sep 22, 2017 4:44 pm
djbass wrote

To put it a different way, it's not that I didn't know how to implement this myself, rather the point usually of using a standard library is not having to do that yourself so I wanted to try and work with what was already available. Unfortunately without compiling a customized version of devkitsms that wasn't possible because some of the required internal routines are not exposed via the library.


Although I understand you're adding this capability for sdcc, I'll just mention that z88dk has a complete stdio implementation including windowed text terminals that coexists with devkitSMS.

"helloworld" and "speech bubbles" show it being used here:
https://github.com/z88dk/z88dk/tree/master/libsrc/_DEVELOPMENT/EXAMPLES/sms
  View user's profile Send private message Visit poster's website
  • Joined: 25 Jul 2007
  • Posts: 540
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Sat Sep 23, 2017 5:50 am
Alcoholics Anonymous wrote

Although I understand you're adding this capability for sdcc, I'll just mention that z88dk has a complete stdio implementation including windowed text terminals that coexists with devkitSMS.

"helloworld" and "speech bubbles" show it being used here:
https://github.com/z88dk/z88dk/tree/master/libsrc/_DEVELOPMENT/EXAMPLES/sms


I'm not adding it to sdcc so much as the SMS in general. SDCC seems to have a decent enough stdio implementation but the console stuff has to be done at a hardware level.

I'm mostly using SDCC because that's what devkitsms is authored in and sverx has done a nice job of documenting the functions. If you have some good documentation for using z88dk with the SMS that would help (or at least a reference of all the function calls).

I think there is also some misconception about my goals for this project. Essentially I'm looking to have ANSI compatible console output on the SMS. Interestingly z88dk does have ANSI support, but I would have to write a clib for the SMS and I'm not particularly good with assembler.

I have two choices, write an emulation at the application level in C (easy), or dig in and try to do it at the hardware level (hard).
  View user's profile Send private message
  • Joined: 17 Nov 2015
  • Posts: 92
  • Location: Canada
Reply with quote
Post Posted: Sat Sep 23, 2017 7:33 am
djbass wrote

I'm not adding it to sdcc so much as the SMS in general. SDCC seems to have a decent enough stdio implementation but the console stuff has to be done at a hardware level.


It doesn't actually have a stdio implementation :) There's no concept of FILE* or device independent io. If you look you'll see there's no scanf either. What it has is a printf that sends characters to a putchar function that is supplied by the target.

sdcc's library implementation is "unhosted" which means it skips parts of the standard that are usually implemented in part by a host operating system. This is fine because sdcc is meant to target typical embedded systems which are normally unhosted.

For the sms this is probably good enough.

The other part of it is sdcc's library is implemented in c to keep it portable for all its cpu targets. Its library code compiles to something that is much larger than, eg, z88dk's which is written in assembler. z88dk targets z80 machines specifically so it's not unreasonable to have things implemented in asm.

Quote

I'm mostly using SDCC because that's what devkitsms is authored in and sverx has done a nice job of documenting the functions.


sdcc is used by z88dk too - it's one of the c compilers inside the package - and devkitSMS has also been incorporated. The main difference between standalone sdcc and z88dk/sdcc (zsdcc) is that the latter has access to z88dk's library code.

Quote

project. Essentially I'm looking to have ANSI compatible console output on the SMS. Interestingly z88dk does have ANSI support, but I would have to write a clib for the SMS and I'm not particularly good with assembler.


There are two c libraries in z88dk at the moment - there is the original one called "classic" and the new one called "newlib".

devkitsms is in the newlib's sms target. The ansi driver is only available for the classic library. Newlib has a new stdio implementation that is object oriented. Drivers are written by inheriting library code that implements some set of behaviours. So for console, there is a library base class that handles text windows with scrolling / cursor placement / edit lines, etc and the drivers must implement a small set of functions specific to the target hardware. Terminal emulation (eg ansi) is done similarly by inheriting from a functional driver and intercepting tty messages that interpret the character sequence that is sent on the stream. There is no ansi driver in newlib yet but there is a "z88dk" tty that has special codes for cursor movement, etc. There is one such driver implemented for the sms that does these things plus allows printing attributes to be changed like mirror, etc.

Anyway, writing drivers does have to be done in asm if it's done this way.
  View user's profile Send private message Visit poster's website
Reply to topic Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8



Back to the top of this page

Back to SMS Power!