|
ForumsSega Master System / Mark III / Game GearSG-1000 / SC-3000 / SF-7000 / OMV |
Home - Forums - Games - Scans - Maps - Cheats - Credits Music - Videos - Development - Hacks - Translations - Homebrew |
Goto page Previous 1, 2, 3 ... 7, 8, 9, 10, 11 ... 15, 16, 17 Next |
Author | Message |
---|---|
|
Posted: Thu Nov 30, 2017 4:52 pm Last edited by sverx on Tue May 29, 2018 11:21 am; edited 1 time in total |
I suggest you keep the current version of PSGlib library, tools and assets with your existing projects (and current projects possibly) and switch to the new version with your next project - this is the "zero burden" approach. |
|
|
Posted: Tue Dec 19, 2017 10:25 am |
I thought that I saw somewhere in this topic an estimate about how many cycles functions like SMS_setNextTileatXY, SMS_setTile take, and how it compares to SMS_loadTiles. But I've not found it anywhere.
I'll explain what I want to know with an example: what would be faster? Changing six non contiguous positions in the tilemap or loading three non contiguos tiles to VRAM? (because each tile I want to change, it's repeated twice) In my first thought, I think It'll be faster to update the nametable, but just to be sure... |
|
|
Posted: Tue Dec 19, 2017 10:33 am |
ah, nice question! I will run a few tests and tell you later :)
(I'd guess it's "changing six non contiguous positions in the tilemap" given they're at fixed locations, thus no math required to find the spot) |
|
|
Posted: Tue Dec 19, 2017 10:43 am |
I'll clarify my need as:
+I need to update some tiles of a background, not always the same ones, but usually no more than 4-5 pairs per frame. +I use the word pair because when I change a tile in the upper part of the screen, there's always another equal tile to change in the bottom part. +Computing the tiles to update is not a big deal, but they're quite random. +I can just update the nametable, or use a fixed nametable when the bottom part is the upper part flipped vertically, and just update a tile loading it to VRAM. |
|
|
Posted: Tue Dec 19, 2017 10:55 am |
SMS_setNextTileatXY(x,y)
which is in fact SMS_setAddr(XYtoADDR((x),(y)))
which becomes an RST 08h, takes 39 cycles, according to Calindro's wonderful Emulicious profiler [this doesn't include the time taken to set HL to the desired value, the RST and RET opcode cycles] 41 cycles needed for SMS_setTile(tile)
which becomes an RST 18h, again according to Emulicious profiler [once more this doesn't include the time taken to set HL to the desired value, the RST and RET opcode cycles] Thus I would say it'll take you: (39+41+(10+11+10)*2)*6= (39+41+62)*6= 852 cycles Loading 4 contiguous tiles to VRAM using UNSAFE_SMS_load4Tiles()
takes 2249 cycles plus overhead, loading 3 noncontinuous tiles would take more than 3/4 of this surely, thus more than 1687 cycles. Updating the tilemap seems to be the faster option by a tad :) |
|
|
Posted: Tue Dec 19, 2017 11:00 am |
if your update of the tilemap may become too heavy in some situation, and cause a slowdown, then the other option may be preferable, as it would always cost the same number of cycles, making the whole thing somehow easier to manage, if you get what I mean. |
|
|
Posted: Tue Dec 19, 2017 11:01 am |
wow! thanks for trying it so fast! :-D
I was expecting nametable updating to be faster, but that it's a clear win :-) However, I'll test my particular case, to see which one is the best option! Thank you sverx! |
|
|
Posted: Tue Dec 19, 2017 1:14 pm |
Loading a tile is two address writes and 32 data writes. Setting a name table entry is two address writes and two data writes. The tile writing will always dominate, and the VDP access dominates the other logic. | |
|
Posted: Tue Dec 19, 2017 1:32 pm |
@Maxim: surely you push to VRAM much more data updating a tile compared to setting a few entries in the map, anyway I suspect that there's a point where the math needed to calculate the tilemap addresses, the call overheads and the set-address-then-set-data work itself could cost more than just pushing a bunch of bytes to VRAM during vblank. In short then I guess the only correct answer it's "it depends". | |
|
Posted: Tue Dec 19, 2017 2:04 pm |
It's true that for small numbers of tiles it may be the case that the logic gets more significant. I'd always kind of assumed that you start animating tiles after you run out of space to animate the references, but as you say it does depend on exactly what you're animating. | |
|
Posted: Wed Jan 03, 2018 10:43 am |
Happy 2018! :)
I just pushed the updated BMP2Tile's STM plugin (it requires BMP2Tile 0.43) - the file format has changed (a 1-byte header holding the map's width has been added) and the official name of this format is now ShrunkTileMap - I know it's silly but Sverx's TileMap was even worse) The asm decompressor (for those that are using WLA-DX) is now interrupt and VRAM safe. [HL = compressed tilemap binary (source), DE = VRAM address (destination)] The update on the devkitSMS side (on the functions to load STMcompressed maps) will happen ASAP. |
|
|
Posted: Wed Jan 03, 2018 11:54 am |
great news! :-D | |
|
Posted: Wed Jan 03, 2018 12:53 pm |
devkitSMS updated - now SMS_loadSTMcompressedTileMap loads STM tilemaps of any width (and this info is now into STM file) - SMS_loadSTMcompressedTileMapArea so has been deprecated.
On a side note, calculation of the destination VRAM address turned into an XYtoADDR(x,y)
macro call, thus if you use constants in your invocation, such as SMS_loadSTMcompressedTileMap(0,0,bg__tilemap__stmcompr);
they'll turn into constant addresses such as ;main.c:243: SMS_loadSTMcompressedTileMap(0,0,bg__tilemap__stmcompr);
ld hl, #_bg__tilemap__stmcompr push hl ld hl, #0x7800 push hl call _SMS_loadSTMcompressedTileMapatAddr |
|
|
Posted: Wed Jan 03, 2018 2:24 pm |
Great!
Lets begin new project with the update! |
|
|
Posted: Wed Jan 03, 2018 2:31 pm |
SDCC 3.6.9 (#10195) suggested - released Jan 1 :) | |
|
Posted: Fri Jan 05, 2018 6:37 am |
Why? 31/12/2017 or 2/1/2018 versions dont work???? Is there a crítical change on sdcc? | |
|
Posted: Fri Jan 05, 2018 9:19 am |
no, I just mean to suggest the snapshot I'm using, as it seems to work correctly (they patched a lot of bugs I encountered in the past months) | |
|
Posted: Sat Jan 13, 2018 9:16 am |
Hi sverx!!!
I dont forget you' simple no Rush! ... Can you explained Us the functions sms_addtwoadjoiningsprites (It draws two sprites horizontally? If so, What happens if i have usetallsprites enabled?) And setclippingwindow and addspriteclipping? The reason is that i have a function to draw an array of sprites and discard those rows/cols which are outside screen' but maybe your functions Will be faster than my plain ANSI c one. Regards. |
|
|
Posted: Sat Jan 13, 2018 12:08 pm |
As the name suggests, it places two sprites, the first at requested x,y and the second right at his side, at same y and at x+sprite_width.
It works with sprites of any size (normal, tall, even zoomed) and it's way faster than placing two sprites with two separate calls. No window clipping is performed - but any sprite outside of screen won't be wasted thus for example if you place your two sprites at x=253, the 'left' sprite will be placed and will partially appear on screen while the 'right' sprite will just be skipped, as it x coordinate would overflow making it appear on the left of the screen I hope this clears your doubts. |
|
|
Posted: Thu Jan 18, 2018 3:53 am |
I don't know how to use the clipping window. Is it suppose to hide the sprite when it's not inside the boundaries? I placed sprites[1] in multiple areas and it's not working for me. Here is my code.
sprites[1] = SMS_addSpriteClipping(sprPos[2], sprPos[3], SPR_TILES+2); SMS_setClippingWindow (8, 8, 96, 96); |
|
|
Posted: Thu Jan 18, 2018 9:14 am |
clipping is performed by software - thus you should *first* set the window, then place the sprite(s): those falling outside the defined window won't be placed.
mind that it can't hide *part* of the sprite, just ensure that no sprite falling *completely* outside the window will appear. |
|
|
Posted: Sun Feb 18, 2018 3:18 am |
Might have found a bug. Your compression for tilemap is not working for maps larger then the screen. Using loadSTMcompressedTileMapArea, i can load a single screen, but a 3x3 screen is not working. Garbled or black screen.
Here is an example source attached. it loads my titlescreen to check if code is working. Go into the source and uncomment the other one to load the other map, and see the bug i'm talking about. |
|
|
Posted: Sun Feb 18, 2018 12:02 pm |
I don't think it's a bug but... yes, you can't have tilemaps larger than the screen (you wouldn't be able to scroll them anyway if you did...)
If you need to handle big maps, there's Psidum wonderful GSLib, which includes a C wrapper so that you can use it from your project. |
|
|
Posted: Sun Feb 18, 2018 5:52 pm |
Ah okay, i was making sure. Yeah, i'm now using it. |
|
|
Posted: Mon Mar 05, 2018 12:57 pm |
I'm writing here on behalf of one fellow member in a spanish forum, he's having problems trying to make a road effect using scanline interruptions.
The problem seems like the effect is happening sometimes in every scanline (the intended effect), sometimes every 2, sometimes every 3, and any possible combination of those. I supposed that maybe he was trying to do too much process in HBLANK, but he even has implemented stripped down versions of background scroll functions, to no avail. He just posted the code and a screenshot, first screenshot has a very noticeable defect, while second is using the stripped down version of the background calls, and the defect is not so visible. Maybe sverx would be able to see what's the problem. Original post in: https://www.elotrolado.net/hilo_tutorial-muy-basico-de-c-para-master-system_2208028_s370#p1745438338 inline void SS_write_VDPRegister (unsigned char VDPReg, unsigned char value) { VDPControlPort=value; VDPControlPort=VDPReg|0x80; } void SS_setLineCounter (unsigned char count) { SS_write_VDPRegister(0x0A,count); } void lineInterruptHandler(void) { SS_write_VDPRegister(0x08,offsetVector[offsCounter++]); } void main() { init_console(); load_graphics2vram(); SMS_enableLineInterrupt(); SMS_setLineInterruptHandler(&lineInterruptHandler); SS_setLineCounter (0); while (1) { // Leo input del player. SMS_waitForVBlank(); SMS_disableLineInterrupt(); // Calculo nuevos valores para el array offsetVector LoadLevelPalette (); SMS_enableLineInterrupt(); SS_setLineCounter(0); } } |
|
|
Posted: Mon Mar 05, 2018 1:37 pm |
the code is basically correct - the point is to have the line handler as fast as possible if you want to scroll at each and every scanline.
for setting the line/interval you can use SMS_setLineCounter (unsigned char count);
for the scroll, you can use SMS_setBGScrollX (unsigned char scrollX);
your handler would be something like void lineInterruptHandler(void)
{ SMS_setBGScrollX(*offsetPointer++); } in your main, you can set the handler and the line/interval value and enable the lineIRQ outside the loop and start the loop when ready SMS_setLineInterruptHandler(&lineInterruptHandler);
SMS_setLineCounter(0); SMS_enableLineInterrupt(); while (1) { SMS_waitForVBlank(); // calculate new values for the offset Array here, reset offsetPointer to &offArray[1] do_your_math(); offsetPointer=&offArray[1]; // set uppermost line value SMS_setBGScrollX(offArray[0]); } edit: you should disable the leftmost column too! Add: SMS_VDPturnOnFeature (VDPFEATURE_LEFTCOLBLANK);
right at the beginning :) edit 2:sorry, there was a * missing in the handler edit 3:to be completely honest, devkitSMS/SMSlib isn't optimized for such a heavy use of line interrupts. If I had to do something like that, I'd probably tweak the ISR, in this part: 1$: ; line interrupt
push bc push de push iy ld hl,(_SMS_theLineInterruptHandler) call ___sdcc_call_hl pop iy pop de pop bc 2$: putting there some Z80 ASM code that does the H-scrolling as fast as possible, maybe even just saving (push/pop) only the registers really used. After all, you've got only 228 CPU cycles per scanline, and the line interrupt overhead isn't negligible... |
|
|
Posted: Tue Feb 04, 2020 3:13 pm |
Resurrecting quite old, but official devkitSMS topic just to ask about the best way to deal with something I'm fighting with:
What would be the best way to include LUT tables on a bank? (together with Graphics) I can compile the LUT to get a .rel, but how I can have as a .bin and then pack it with other assets using assets2banks? PD: Maybe this is quite easy, but I'm not getting how to compile to pure bin. |
|
|
Posted: Tue Feb 04, 2020 4:08 pm |
if you put all the LUTs together you can compile a .rel and have them all together in the same bank, by themselves - this is the easy approach and I mainly suggest this.
otherwise, if you want them handled by assets2banks, an approach could be either: - have each single LUT in form of a binary file (but AFAIK you can't easily create a LUT in a C source file and compile that to some bin file that contains only the LUT) - which means you're probably going to edit some file with hex editor :( edit: try googling txt2bin, there are a few interesting results! - if LUT(s) is(are) small, you can abuse assets2banks' :append attribute and create an empty file in the assets folder, one for each LUT, name it the way you want the LUT to be called and then in assets2banks.cfg for each empty file you append the data for example as in: test_char_LUT.bin
:append 0 1 2 3 4 5 6 7 8 or in test_int_LUT.bin
:format unsigned int :append 0x1234 0x5678 |
|
|
Posted: Wed Feb 05, 2020 8:48 am |
My problem is that I'm using also complex structures on some files I would like to put in a bank. For instance, an example of content I'll like to put ina bank together with its graphics is:
https://github.com/kusfo/mastersystembrawler/blob/master/playercharacter.h This is not really easy to convert to bin (I know I'll also need to get rid of pointers and so, but it's an example). I think I saw some people doing similar things and using assembly data to fill the structs... |
|
|
Posted: Wed Feb 05, 2020 11:36 am |
yeah, those structures need a compiler (and also need to be output as RELs since you've got pointers that the linker should initialize)
so if you need to keep that data in the same bank as some graphics, you could move those graphics out of the general 'asset' folder to a specific folder, then use folder2c to turn the data in there into C sources so you then merge (juxtapose) the generated C file with your source that contains those structures - and you finally compile this resulting file into a REL, that you will link with all the other code/data in the end. |
|
|
Posted: Wed Feb 05, 2020 1:18 pm |
Mmm, the merge solution is not a bad solution at all!
Thanks, I'll think a bit about it! |
|
|
Posted: Wed Oct 28, 2020 6:59 am |
I'm experimenting with SDCC snapshot (v4.0.3) and devkitSMS.
I modified SGlib to suit the SC-3000 but now when I recompile SGlib it places an EI at the beginning of SG_isr screwing up everything during execution, eg. pushing stuff on stack forever. The only thing I modified is crt0_sg.s stackpointer (pointing to c7f0) and VDP values in SGlib.c. What is causing this? 0038: jp 08A1h ... 08A1: ei 08A2: push af 08A3: push bc 08A4: push de ... |
|
|
Posted: Wed Oct 28, 2020 10:26 am |
According to the updated SDCC manual, with version 4.0.x they slightly changed how the interrupts are declared (it's on page 46).
So you might want to try switching from void SG_isr (void) __interrupt {
to void SG_isr (void) __critical __interrupt(0) {
to signal that you don't want your interrupt routine to be interrupted (!) Let me know if that works and generate correct code. |
|
|
Posted: Wed Oct 28, 2020 2:54 pm |
Okay, didn't even imagine someone wanting the interrupt routine to be interrupted. But that solution indeed does work and generates correct code. Thanks sverx! |
|
|
Posted: Wed Oct 28, 2020 3:16 pm |
I'm curious now... is there a single EI or two of them before the RETI in the generated code? |
|
|
Posted: Wed Oct 28, 2020 3:54 pm |
This is how it looks before correcting SGlib.c: ;SGlib.c:384: void SG_isr (void) __interrupt { ; --------------------------------- ; Function SG_isr ; --------------------------------- _SG_isr:: ei push af push bc push de push hl push iy push ix ld ix,#0 add ix,sp dec sp ;SGlib.c:385: volatile unsigned char VDPStatus=VDPStatusPort; /* this also aknowledge interrupt at VDP */ in a, (_VDPStatusPort) ;SGlib.c:390: if (VDPStatus & 0x80) { ld -1 (ix), a rlca jr NC, 00102$ ;SGlib.c:391: VDPBlank=true; /* frame interrupt */ ld iy, #_VDPBlank ld 0 (iy), #0x01 ;SGlib.c:393: PreviousKeysStatus=KeysStatus; ld hl, (_KeysStatus) ld (_PreviousKeysStatus), hl ;SGlib.c:394: KeysStatus=~(((IOPortH)<<8)|IOPortL); in a, (_IOPortH) ld b, a xor a, a ld c, #0x00 in a, (_IOPortL) ld e, a ld d, #0x00 ld a, c or a, e ld c, a ld a, b or a, d cpl ld (_KeysStatus+1), a ld a, c cpl ld (_KeysStatus+0), a 00102$: ;SGlib.c:397: ENABLE_INTERRUPTS; ei ;SGlib.c:398: } inc sp pop ix pop iy pop hl pop de pop bc pop af reti With the correction in place, there's only one EI at the end of routine. |
|
|
Posted: Wed Oct 28, 2020 4:02 pm |
so it looks like they add EI at the beginning of the routine if they want to allow for an ISR that can be interrupted but they don't care to add EI before the RETI if one wants an ISR that can't be interrupted.
I'll ask them. |
|
|
Posted: Sun Apr 11, 2021 11:55 pm |
Is there a way to read the tile index at the current location? essentially SMS_getTile
Also more generally, since I need to track the status of each tile would you just create an array for the metadata, would that be the most efficient way? eg unsigned int tiles[32][24];
or alternatively struct _tiledata {
unsigned int index; unsigned int status; }; struct _tiledata tiles[32][24]; |
|
|
Posted: Mon Apr 12, 2021 8:16 am |
While you can read back from VRAM, it’s not very fast. As the game logic is usually not based on 8x8 metatiles (and may not have a 1:1 relationship between tiles and behaviour), it’s also not very useful in general. | |
|
Posted: Mon Apr 12, 2021 11:12 am |
well, what Maxim just said. But if you for some reason really need to read back from VRAM anyway, we can code a specific function | |
|
Posted: Tue Apr 13, 2021 9:14 am |
If it serves no genuine purpose don't worry too much, I've found a better way to do what I need anyway. | |
|
Posted: Fri Apr 01, 2022 11:16 am |
Reviving this old thread just to mention I pushed a few updates to address the Game Gear timing issues. So newest SMSlib should no longer create SMS or GG code that could have VRAM issues on some Game Gears.
I also unified the different crt0s - there's now only a single crt0.rel for both SMS/GG and it's always VRAM safe and supports code banking. Please let me know should you find bugs / have issues with something. |
|
|
Posted: Sat Jun 18, 2022 12:20 am |
Hi, I was mucking about with devkit sms, and I'm not quite clear on what SMS_loadTileMapArea does, and what the parameters do in detail. I found an example of it being used, and it only served to confuse me further XD I'm wondering if anyone could shed some light on it.
I'm using sdcc 4.2, and the devkit sms sdcc4.2 branch. EDIT: I backed tracked this topic, and I found out information on it. The problem is that it doesn't seem to work correctly. Using SMS_loadTileMap works just fine however. When I swap that for the SMS_loadTileMapArea, things go very wrong. Not sure what the issue is. The image is 27 tiles wide, and 3 tiles high. #include "lib\SMSlib.h"
#include "lib\PSGlib.h" #include <stdio.h> #include <stdlib.h> #include "bank2.h" SMS_EMBED_SEGA_ROM_HEADER(9999, 1); SMS_EMBED_SDSC_HEADER_AUTO_DATE(1, 0, "test", "test", "test"); void LoadGraphics() { SMS_displayOff(); SMS_mapROMBank(title_bg_pal_bin_bank); SMS_loadBGPalette(title_bg_pal_bin); SMS_loadSpritePalette(title_spr_pal_bin); SMS_loadTiles(title_tmn_tiles_bin, 0, title_tmn_tiles_bin_size); //SMS_loadTileMap(0, 1, title_tmn_map_bin, title_tmn_map_bin_size); SMS_loadTileMapArea(1, 1, title_tmn_map_bin, 27, 3); SMS_displayOn(); } void main() { SMS_init(); LoadGraphics(); for (;;) { SMS_waitForVBlank(); } } |
|
|
Posted: Sat Jun 18, 2022 8:17 pm |
I agree SMS_loadTileMapArea isn't well described in the documentation - also it doesn't perform any clipping.
The way it is now, it simply loads a tilemap on an area of the screen, but the source image should match the area of the screen you want to update - so if you want to update an area 27 tiles wide and 3 tiles tall, your original image should be 27*8 pixel wide and 3*8 pixels tall to generate the correct title_tmn_map_bin file you will use. I hope it's clearer now. edit: you don't need to call SMS_init(); if you're using the devkitSMS provided crt0.rel as that gets already done before going to your main.
|
|
|
Posted: Sat Jun 18, 2022 8:38 pm |
See, that's the issue I'm having. The image is definitely 27 * 8 in width and 3 * 8 in height (I have attached it to this post). The function gets the bottom 2 rows fine, but the top one is all jarbbled. So this should achieve that: SMS_loadTileMapArea(1, 1, title_tmn_map_bin, 27, 3), correct? I did read about the crt0.rel before, I have it linked in the compile.bat file, probably a remnant of copy and pasting. |
|
|
Posted: Sat Jun 18, 2022 9:04 pm |
This is very weird, given it's a very simple loop of row transfers, see the source code. So there should be something else going on. Can you isolate the issue in a separate source and see if it does it again? Are you handling the assets using assets2banks? |
|
|
Posted: Sun Jun 19, 2022 3:58 am |
Yes, I have put together a bare bones example of the issue. I understand what the code is achieving, but if you could just try and run the test (https://www.pyxosoft.com/projects/sms_tmnt/test.zip) using the lib versions I mentioned previously, that would be awesome. That way I can maybe see if it's environmental, an emulator issue, dumbass coding on my part etc.. etc.. some sort of trouble shooting. Everything else that I have used in the library has worked as expected, and very nice. This is a great thing you have put together, and very intuitive. I barely had to do any research in getting this up and running. Thank you for helping, and your time. |
|
|
Posted: Sun Jun 19, 2022 3:06 pm |
I'm not sure what's going on here, looks like it's mixing calling convention which means you might be mixing compiler versions and/or files
What's your SDCC version? What devkitSMS branch did you download? |
|
|
Posted: Sun Jun 19, 2022 5:55 pm |
Hmmm, that may be it. I have sdcc v 4.2.0 #13081 (MINGW64) installed, and I believe the sdcc4.2 branch from github. Probably should have used the master branch when I think about it. I'll overwrite with master. Edit: Oh wait, your instructions said to get sdcc 4.1.11 at the most lol, how did I miss that? Edit Edit: That worked! I brought in sdcc 4.1 and devkit sms master branch, and now it functions as expected. On one more question, is there a method/macro to clear the vram? Thank you so much for your help. |
|
|
Posted: Sun Jun 19, 2022 8:28 pm |
yeah you can use the sdcc4.2 branch of devkitSMS only with SDCC 4.2.0 or the master branch with SDCC 4.1.0 -> 4.1.11.
If you were using SDCC 4.2.0 and the sdcc4.2 branch of devkitSMS it should have worked, or it means I've got a bug somewhere, but I've not experienced it. |
|
Goto page Previous 1, 2, 3 ... 7, 8, 9, 10, 11 ... 15, 16, 17 Next |