News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_Arnaud

WinCPCTelera

Started by Arnaud, 20:58, 29 September 16

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Arnaud

#50
Quote from: EgoTrip on 20:27, 11 November 16
Will you be implementing it? My games also use it, so if I ever want to build a windows version of my games (assuming that becomes a thing) I won't be able to.

Here http://www.cpcwiki.eu/forum/programming/lz48-cruncherdecruncher/, i just adapt the compressor LZ48 from roudoudou for Cpctelera it could be a solution.

Arnaud

#51
Finally !

[attach=2][attach=3][attach=4]

As usual when a new project is compiled i found bugs :
- Some virtual keys were missing ('O' or 'I' for example)
- In the function cpct_drawSpriteMaskedAlignedTable the mask was applied to the byte and not to the pixel

This time i had to modify the original code to make Outlaw working :
- I replaced buffer compressed with Exomizer (Exoopt) with buffer compressed with LZ48 (i have decruncher C code only for LZ48)

- But the main problem was the direct access to CPC memory :

ex from Outlaw code :
#define LEVEL_TILEMAPS_ADDRESS 0x0AC0 //1296 bytes
#define G_levelTilemaps (u8*)LEVEL_TILEMAPS_ADDRESS

u8* tilemap = G_levelTilemaps + map * 20 * 16;


The tilemap pointer is corrupt because the data at the address 0x0AC0 can't be directly read or write, under Windows this memory area is forbidden.

To make the code working here my modifications :
#define LEVEL_TILEMAPS_ADDRESS 0x0AC0 //1296 bytes
u8* G_levelTilemaps;

void initMemory()
{
    G_levelTilemaps = GetMemory((void*)LEVEL_TILEMAPS_ADDRESS);
}


I had to call a WinCpcTelera function (GetMemory) in order to have a pointer of the "CPC memory" and store it in a variable.

The solution to have compatibility between cpcTelera and winCpcTelera could be the use of a optional function to handle CPC memory.

ex for cpctelera:
u8* cpct_getMemoryPointer(int pAddress)
{
    return (u8*) pAddress;
}


I had to speak about this solution with @ronaldo  :D


SRS

#52
Quote from: Arnaud on 14:34, 13 November 16
I had to call a WinCpcTelera function (GetMemory) in order to have a pointer of the "CPC memory" and store it in a variable.

The solution to have compatibility between cpcTelera and winCpcTelera could be the use of a optional function to handle CPC memory.

ex for cpctelera:
u8* cpct_getMemoryPointer(int pAddress)
{
    return (u8*) pAddress;
}


I had to speak about this solution with @ronaldo  :D

I'd prefer if it would be a MACRO instead of function for speed issue on CPC.

Can't you use exodecrunch C Sources from https://bitbucket.org/magli143/exomizer/wiki/Home -> in the ZIP "RAWDECRS" ?

Arnaud

Quote from: SRS on 20:40, 13 November 16
I'd prefer if it would be a MACRO instead of function for speed issue on CPC.

I can't use macro with the wincpctelera for this part, with macro the address is computed at compilation time but for Windows the allocation and the address of a variable is set at runtime.

Quote from: SRS on 20:40, 13 November 16
Can't you use exodecrunch C Sources from https://bitbucket.org/magli143/exomizer/wiki/Home -> in the ZIP "RAWDECRS" ?

I need sources of exoopt.exe and they are only in asm : https://sourceforge.net/p/emuscriptoria/code/HEAD/tree/deexo/

I tried to convert in C in primitive way but i'm not skilled enough in asm : http://www.cpcwiki.eu/forum/programming/exoopt-cpc_unexo-in-c/


ronaldo

Quote from: Arnaud on 14:34, 13 November 16

This time i had to modify the original code to make Outlaw working :
- I replaced buffer compressed with Exomizer (Exoopt) with buffer compressed with LZ48 (i have decruncher C code only for LZ48)
- But the main problem was the direct access to CPC memory :
I had to speak about this solution with @ronaldo  :D
At this point you are hitting some limitations of your approach. Programs are free to use Amstrad CPC resources at will, and there is no unified approach to prevent developers from doing it. If is possible to provide functions, as you suggest, but there is no warranty that developers will use them. In fact, as programmers wanted to be closer to hardware, they will use less approaches like a function to get a pointer to memory.

This means that technically exigent games will not work in WinCPCtelera, using this approach.  However, your approach is nice for most software already developed and probably most that will be. More indepth approaches will require much more time to develop.

Arnaud

Joystick support added !

It's really better to play Outlaw with joypad  :)

Arnaud

#56
SDL support is working (for window creation, render and input keyboard / joystick).

Hope it will be useful for someone.

[attach=2]

Arnaud

#57
A little update :

       
  • Correction of cpct_memset when used in VRam, data are now filled in the right order.

       
  • I added a file helper for both cpctelera and wincpctelera project in order to keep compatibility and add some debug tools with same code.
It takes only 10 bytes in memory for CPC.

u8* WinCpcTelera_GetMemPtr(u16 memAddress);
Get memory pointer of specific address -> just cast u16 in u8* in CPC

WinCpcTelera_Process()
Process windows message loop -> Do/take nothing in CPC

WinCpcTelera_Wait(X)
Tempo in ms  -> Do nothing in CPC

WinCpcTelera_PrintXXX
Draw value in console  -> Do/take nothing in CPC

[attach=2]

awergh

#58
So its been a little while since I've looked at this. (I can be so slack sometimes)
In compiling wincpctelera it was a bit confusing with cpct_sprites.c as as there are two source files with the same name (one which would work and one which would cause link errors).


Anyway after resolving that and building a lib file I compiled the game I wrote for CPCRetroDev2016.
This was fine just needed to comment out __sdcc_heap_init(); as it is SDCC specific.


On the first level everything seemed fine but once I got to level 2 performance was really bad. It turns out if I exit the level (ESC) and go back into it repeatedly there is a memory leak.
This didn't happen when I was using an early version of wincpctelera (it was super useful then for resolving the memory leaks) so I'm assuming there must be some other reason then my code which works fine with cpctelera on a real CPC.


I don't think I did anything particularly out of the ordinary (Unless I did things in a way I wasn't supposed to which is quite possible.) except perhaps scrolling which also does not work as expected.
Here are the snapshots heaps snapshots from Visual Studio for reference starting from the menu and then quiting until the game stopped working (screen goes white nothing seems to work anymore).





Arnaud

#59
Hello,

Quote from: awergh on 10:58, 09 February 17
In compiling wincpctelera it was a bit confusing with cpct_sprites.c as as there are two source files with the same name (one which would work and one which would cause link errors).

Thanks for reporting, it's a commit error, cpct_sprites.c shall not be duplicated in String directory

Quote from: awergh on 10:58, 09 February 17
This was fine just needed to comment out __sdcc_heap_init(); as it is SDCC specific.
__sdcc_heap_init() is ignored in compilation now

Quote from: awergh on 10:58, 09 February 17
On the first level everything seemed fine but once I got to level 2 performance was really bad. It turns out if I exit the level (ESC) and go back into it repeatedly there is a memory leak.
This didn't happen when I was using an early version of wincpctelera (it was super useful then for resolving the memory leaks) so I'm assuming there must be some other reason then my code which works fine with cpctelera on a real CPC.
I compiled your game and i have not the problem with the new version of Wincpctelera, could you try with the last one please ?

Wincpctelera is just updated on Github.

Some other corrections :
- Correction of cpct_keyboardStatusBuffer[], the buffer is updated with the right key code.
- Add missing palette default colors (only 4 colors were defined)
- Add/Use double buffer in GDI / SDL render
- Remove some useless functions

awergh

So tried it out and it runs much better, the game is playable to the end, and feels much like it should playing on CPC.
However the scrolling is still not quite right. Things really are hard to hit when the projectile doesn't go in a straight line.  :P




Arnaud

Quote from: awergh on 12:50, 10 February 17
So tried it out and it runs much better, the game is playable to the end, and feels much like it should playing on CPC.
Good news.

Quote from: awergh on 12:50, 10 February 17
However the scrolling is still not quite right. Things really are hard to hit when the projectile doesn't go in a straight line.  :P
Well, i done a nasty hack to simulate hardware scroll, it works very well on the CPCTelera example but not perfectly in your game.  :(

I have to think once again how simulate the video ram  :doh:






awergh

Isn't it typical though, you work hard at making something perfect and then someone has to break it and you have to rethink how to do it.


I can't say I have any advice of how to get it to work. I had actually considered whether to port my game to Windows with Allegro as a programming exercise but I never decided if I go for the code reuse route or the write in an OO way using C++. I would say that watching the video about the making Retro City Rampage for MS-DOS the other day that I was more motivated to do multiple ports.
I haven't looked at how you did hardware scroll but I imagine I would just move the columns of the screen around to simulate scrolling.

Arnaud

Quote from: awergh on 13:47, 12 February 17
Isn't it typical though, you work hard at making something perfect and then someone has to break it and you have to rethink how to do it.
In fact it's a good way to found bug  ;)

Quote from: awergh on 13:47, 12 February 17
I can't say I have any advice of how to get it to work. I had actually considered whether to port my game to Windows with Allegro as a programming exercise but I never decided if I go for the code reuse route or the write in an OO way using C++. I would say that watching the video about the making Retro City Rampage for MS-DOS the other day that I was more motivated to do multiple ports.
I you want to have a version of WinCPCTelera with scrolling working for your code, it's easy, i just have to comment some code.

Quote from: awergh on 13:47, 12 February 17
I haven't looked at how you did hardware scroll but I imagine I would just move the columns of the screen around to simulate scrolling.
When i do hardware scrolling the video buffer is a bitmap, and applied a byte offset move one line.
On CPC it's 8 lines of offset, and as you said, to do that i moved columns to simulate the effect.

awergh

Quote from: Arnaud on 15:58, 12 February 17
In fact it's a good way to found bug  ;)

I'm glad you see it that way and are looking to make WinCPCtelera the best it can be :)

[/size]
Quote from: Arnaud on 15:58, 12 February 17I you want to have a version of WinCPCTelera with scrolling working for your code, it's easy, i just have to comment some code.
When i do hardware scrolling the video buffer is a bitmap, and applied a byte offset move one line.
On CPC it's 8 lines of offset, and as you said, to do that i moved columns to simulate the effect.


I'm happy to wait for you to release something you are completely happy with for its robustness.
Thinking about writing multiple versions is mostly just me thinking aloud.

Arnaud

I updated Wincpctelera with compressors support :
- Exomizer (not the optimized version) from Magnus Lind
- Lz48 from Roudoudou

In the _compressor directory you'll find, the decompressor code for cpctelera (asm), the decompressor code for Wincpctelera (full C version) and the executable compressor (Windows) for each.

You just have to add the source code of the compressor you want in your project in order to use it.

Arnaud

WinCPCTelera is compatible with the latest version of CPCTelera 1.4.2.

It support the updated API and the memory paging.

Hope it help for the CPCRetrodev 2017 developper  ;)

https://github.com/Arnaud6128/wincpctelera/releases

awergh


So I just tried to compile WinCPCtelera 1.4.2 and have got an error that banks.h is missing.
Was the file missed when adding to Git or something?


I feel like I really should have tried this a bit sooner given its over a year since you updated it.
I only switched to CPCtelera 1.4.2 this year as I had already started with 1.4 last year when it came out and didn't wish to change anything at that point.


ronaldo

Quote from: awergh on 12:27, 05 August 18
I feel like I really should have tried this a bit sooner given its over a year since you updated it.
I only switched to CPCtelera 1.4.2 this year as I had already started with 1.4 last year when it came out and didn't wish to change anything at that point.
I expect to be launching CPCtelera 1.5 by september. It will have many new features and improvements. They are already available if you get current CPCtelera development branch. It is mostly stable at this momment (No bugs that I know, although they may always appear at some point, that's why I say "mostly").

Arnaud

Quote from: awergh on 12:27, 05 August 18
So I just tried to compile WinCPCtelera 1.4.2 and have got an error that banks.h is missing.
Was the file missed when adding to Git or something?
Thanks for reporting @awergh , i forgot to commit this file, all should be ok now.

Quote from: ronaldo on 11:59, 06 August 18
I expect to be launching CPCtelera 1.5 by september.
:D

awergh

Quote from: Arnaud on 09:08, 07 August 18
Thanks for reporting @awergh , i forgot to commit this file, all should be ok now.

Excellent all good now.  :)


Question I've found previously with last years project and the current progress I've made this year that I need to do a full rebuild every time I make a code change otherwise it doesn't run as expected. For example I'll have a struct that was previously initialised earlier will suddenly be all 0 when I go to use it.
Rebuilding/clean build will fix the problem and everything will work fine. Building normally with CPCtelera never has a problem.

Quote from: ronaldo on 11:59, 06 August 18
I expect to be launching CPCtelera 1.5 by september. It will have many new features and improvements. They are already available if you get current CPCtelera development branch. It is mostly stable at this momment (No bugs that I know, although they may always appear at some point, that's why I say "mostly").

:D  Glad to hear that a new version is coming although I suspect I will decide to go with the safest route and keep everything the same rather than switching part way unless there is a feature that I have to have.

ronaldo

Quote from: awergh on 13:51, 07 August 18
Question I've found previously with last years project and the current progress I've made this year that I need to do a full rebuild every time I make a code change otherwise it doesn't run as expected. For example I'll have a struct that was previously initialised earlier will suddenly be all 0 when I go to use it.
This is usually due to an existing bug in iDSK. The new version of CPCtelera has a workaround and no need to completely rebuild every time.

Quote from: awergh on 13:51, 07 August 18:D  Glad to hear that a new version is coming although I suspect I will decide to go with the safest route and keep everything the same rather than switching part way unless there is a feature that I have to have.
Well, you may find some of the new features quite interesting. Concretely, I have finished right now the integration of ZX7B with the build system. Now automating the compression of files into an array that you can later decrunch during execution is as easy as converting assets. Moreover, it has the same advantages: when sources are changed, a simple 'make' command generates the new version of the compressed array.
Still some work to do on documenting it, but I'm quite sure it will be a killer feature :) .

awergh


So I've found another bug in WinCPCtelera (you did tell me this was a good thing  ;D )
I have been experimenting with copying the video memory from one location with cpct_memcpy and displaying it elsewhere.
When running it in WinAPE everything works correctly however when using WinCPCtelera it displays the junk whenever you change direction.
So initially there is junk and then it is good until you change direction and then junk is drawn again but is ok after that.


#include <cpctelera.h>

#define TILE_HEIGHT 16
#define TILE_WIDTH_BYTES 4

const u8 G_background_test[64] = {
0xA3, 0xF3, 0xF3, 0x53,
0xA3, 0xF3, 0xF3, 0x53,
0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03,
0xA3, 0xF3, 0xF3, 0x53,
0xA3, 0xF3, 0xF3, 0x53,
0xA3, 0xF3, 0xF3, 0x53,
0xA3, 0xF3, 0xF3, 0x53,
0xA3, 0xF3, 0xF3, 0x53,
0xA3, 0xF3, 0xF3, 0x53,
0xA3, 0xF3, 0xF3, 0x53,
0xA3, 0xF3, 0xF3, 0x53,
0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03,
0xA3, 0xF3, 0xF3, 0x53,
0xA3, 0xF3, 0xF3, 0x53};

const u8 G_background_test2[64] = {
0x53, 0xF3, 0xF3, 0xA3,
0x53, 0xF3, 0xF3, 0xA3,
0xA3, 0xF3, 0xF3, 0x53,
0xA3, 0xA3, 0x53, 0x53,
0xF3, 0x53, 0xA3, 0xF3,
0xF3, 0x53, 0xA3, 0xF3,
0xA3, 0xA3, 0x53, 0x53,
0xA3, 0xF3, 0x53, 0x53,
0xA3, 0xA3, 0xF3, 0x53,
0xA3, 0xA3, 0x53, 0x53,
0xF3, 0x53, 0xA3, 0xF3,
0xF3, 0x53, 0xA3, 0xF3,
0xA3, 0xA3, 0x53, 0x53,
0xA3, 0xF3, 0xF3, 0x53,
0x53, 0xF3, 0xF3, 0xA3,
0x53, 0xF3, 0xF3, 0xA3 };

void main(void)
{
    // Pointer to video memory
    u8* memory; 
    u8 spriteCopy[64];
    u8 i = 0;

    //disable the firmware to prevent it from interfering with setVideoMode
    cpct_disableFirmware();

    //set video mode to mode 0
    cpct_setVideoMode(0);

    // Clear Screen
    cpct_memset(CPCT_VMEM_START, 0, 0x4000);

    //draws G_background_test to (24,24)
    memory = cpct_getScreenPtr(CPCT_VMEM_START, 24, 24);
    cpct_drawSprite(G_background_test, memory, TILE_WIDTH_BYTES, TILE_HEIGHT);

    //copy the content of 24,24 into spriteCopy (this must be done one line at a time)
    for(i=0; i<TILE_HEIGHT; ++i)
    {
        cpct_memcpy(spriteCopy + (i * TILE_WIDTH_BYTES), cpct_getScreenPtr(CPCT_VMEM_START, 24, 24+i), TILE_WIDTH_BYTES);
    }

    //draw G_background_test2 to (24,24) (this is drawing over the old sprite)
    cpct_drawSprite(G_background_test2, memory, TILE_WIDTH_BYTES, TILE_HEIGHT);

    //draw the previously copied memory to (30,24)
    memory = cpct_getScreenPtr(CPCT_VMEM_START, 30, 24);
    cpct_drawSprite(spriteCopy, memory, TILE_WIDTH_BYTES, TILE_HEIGHT);

    // Loop forever
    while (1)
    {

    }
}




Quote from: ronaldo on 19:20, 07 August 18
This is usually due to an existing bug in iDSK. The new version of CPCtelera has a workaround and no need to completely rebuild every time.
Hmm ok although I was assuming this was related to WinCPCtelera in this instance but its manageable so it's not huge concern (especially when build times are fast with only a few source files).

Arnaud

#73
Hello @awergh,
thanks for reporting  ;)

Effectively the cpct_memcpy doesn't works between Video and Memory a convertion is needed.
I have updated cpct_video.c, cpct_memutils.c and winCpctelera.h to solve your problem, but i think i have to work more on this issue.

awergh

So as its almost time to start an entry for CPCRetroDev 2019 I thought it was time I reported a bug I had with wincpctelera.
Just the one bug (I thought I had a few but it turned out my code was the problem even if wincptelera vs cpc did not produce exactly the same result consistently)
I saw you did some changes for CPCtelera 1.5 which I haven't checked out but it probably still applies.

So here is my example of reading a key from the user (based on one of the examples on cpcwiki somewhere).
The problem is that not all the key codes work when using wincpctelera.
The following keys are not detected: z, x, v, del, space



#include <cpctelera.h>
#include <stdio.h>

cpct_keyID getKey();
void interruptHandler();

void main(void)
{
    //default to anything
    cpct_keyID chosenKey = Key_A;
    u8 letterCount = 0;
    u8* memory = 0;
    u8* memortAlt = 0;

    //disable the firmware to prevent it from interfering with setVideoMode
    cpct_disableFirmware();

    //setup interruptHandler for keyboard scanning
    cpct_setInterruptHandler(interruptHandler);

    //set video mode to mode 0
    cpct_setVideoMode(0);

    memory = cpct_getScreenPtr(CPCT_VMEM_START, 8, 12);
    memortAlt = cpct_getScreenPtr(CPCT_VMEM_START, 8, 24);

    //loop forever
    while (1)
    {
        u8 chosenCharacter = 0;

        //get the next character from the user
        chosenKey = getKey();

        switch (chosenKey)
        {
            case Key_A:
                chosenCharacter = 'a';
            break;

            case Key_B:
                chosenCharacter = 'b';
            break;

            case Key_C:
                chosenCharacter = 'c';
            break;

            case Key_D:
                chosenCharacter = 'd';
            break;

            case Key_E:
                chosenCharacter = 'e';
            break;

            case Key_F:
                chosenCharacter = 'f';
            break;

            case Key_G:
                chosenCharacter = 'g';
            break;

            case Key_H:
                chosenCharacter = 'h';
            break;

            case Key_I:
                chosenCharacter = 'i';
            break;

            case Key_J:
                chosenCharacter = 'j';
            break;

            case Key_K:
                chosenCharacter = 'k';
            break;

            case Key_L:
                chosenCharacter = 'l';
            break;

            case Key_M:
                chosenCharacter = 'm';
            break;

            case Key_N:
                chosenCharacter = 'n';
            break;

            case Key_O:
                chosenCharacter = 'o';
            break;

            case Key_P:
                chosenCharacter = 'p';
            break;

            case Key_Q:
                chosenCharacter = 'q';
            break;

            case Key_R:
                chosenCharacter = 'r';
            break;

            case Key_S:
                chosenCharacter = 's';
            break;

            case Key_T:
                chosenCharacter = 't';
            break;

            case Key_U:
                chosenCharacter = 'u';
            break;

            case Key_V:
                chosenCharacter = 'v';
            break;

            //doesnt work on wincpctelera
            case Key_W:
                chosenCharacter = 'w';
            break;

            //doesnt work on wincpctelera
            case Key_X:
                chosenCharacter = 'x';
            break;

            case Key_Y:
                chosenCharacter = 'y';
            break;

            //doesnt work on wincpctelera
            case Key_Z:
                chosenCharacter = 'z';
            break;

            //space does not work on wincpctelera
            case Key_Space:
                chosenCharacter = 0;
                cpct_drawStringM0("space", memortAlt, 1, 0);
            break;

            //del doesn't work with cpctelera but 16386 does
            //case 16386:
            case Key_Del:
                chosenCharacter = 0;
                cpct_drawStringM0("del", memortAlt, 1, 0);
            break;

            default:
                chosenCharacter = 0;
                cpct_drawStringM0("default", memortAlt, 1, 0);
            break;
        }

        if (chosenCharacter)
        {
            //draw letter
            cpct_drawCharM0(memory, 1, 0, chosenCharacter);
        }
    }
}

cpct_keyID getKey()
{
    // Traverse the keystatus vector from end to start, to help
    // the compiler better optimise this code
    u8 i = 10;
    u8* keys = cpct_keyboardStatusBuffer + 9;
    u16 keypressed = 0;

    // wait for any previous key presses to clear first
    while (cpct_isAnyKeyPressed());

    //then wait for the desired key press
    while (!cpct_isAnyKeyPressed());


    // Analyse which key has been pressed and return its keycode
    do
    {
        // We analyse groups of keys byte by byte (8 by 8, 1 bit per key)
        // If no single key is pressed in this group, all bits will be on, and the byte will be 0xFF
        // Then, XORing the byte with 0xFF will result in 0 unless some key from this group is pressed
        keypressed = *keys ^ 0xFF;

        if (keypressed)
        {
            return (keypressed << + (i - 1); // Convert to cpct_keyID format: 8 first bits = key mask, 8 next bits, keyboard row (0-9)
        }

        --keys;
    } while (--i);

    // No key was pressed
    return 0;
}

void interruptHandler()
{
    //scan for any keyboard changes
    cpct_scanKeyboard_if();
}



Have you completed your changes for CPCtelera 1.5?
I haven't decided if I should be using 1.4.2 or grabbing the latest 1.5 from github.

Powered by SMFPacks Menu Editor Mod