Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
New Game Block Dude (Port)
#11
site with dev sources still available on web.archive.org

https://web.archive.org/web/202104111600...pdroms.de/
Reply
#12
(02-09-2022, 09:04 AM)Flavor Wrote:
(02-09-2022, 07:28 AM)winteriscoming Wrote: For those seriously dabbling in NGPC development, the FlashMasta cart is the way to go.  I end up testing most of my code iterations on hardware and the workflow for the FlashMasta is the fastest.

FlashMasta workflow:
1. Compile your code into NGPC rom.
2. Plug your cart into PC.
3. Open FlashMasta program, choose slot, and write your latest rom to the cart.
4. When it's done, unplug and put it in your NGPC for testing.

FYI, you may also be able to use the CLI (command-line) app under the "Old/CLI" heading here: https://www.flashmasta.com/software-downloads/ to skip some mouse clicks.

Great!  I had not paid attention to the CLI app prior to now.  Now I have a simple bat file set up to write my rom to the first slot.  Definitely saves some mouse clicks!
FlashMasta workflow is now:
1. Compile your code into NGPC rom.
2. Plug your cart into PC.
3. Run bat file to flash the cart.
4. When it's done, unplug and put it in your NGPC for testing.
Reply
#13
Happy New Year,
This thread should be moved to Homebrew instead of software development, but ver0.9 of Neo Block Dude is released!

https://drive.google.com/drive/folders/1...sp=sharing

The game is fully playable in both emulation and real hardware with 24 levels of puzzle-platforming action. The code is also uploaded in a .zip for anyone in the future, and might make a good generic platformer engine, although i am a poor coder so probably not the best person to copy from.

The reason it is version 0.9 is for two main issues:
1. Sound: this has been a bane for the whole project. Just getting NeoTracker to (partially) work took wayyy too long, and while i can get WinterisComing's code working for new projects, i haven't been able to integrated it on existing code. Something to do with the V-blanking, i think. Currently the NeoTracker BGM plays fine in emulation, but no loops and only through headphones on actual hardware, not the speaker. Possibly because of mono-vs-stereo? Argh, sound just sucks on this game and it's been very frustrating, sorry
2. Saving Data: I haven't dug too deep into this feature but while I'm able to get the flash save working in emulation (NeoPOP-Win32), it does not work on real hardware (flashmasta). The game freezes when trying to load or retrieve the data, so I commented the test code out. The goal is to save two strings: one for step records and one for calculator pieces collected. There isn't a whole lot of documentation or examples for saving home brew game data: any pointers would be appreciated. 

There are a few story/extra character features that didn't make sense without saving, so I left them out. 

I plan on continuing to work on this, but need a break since I'm seeing C-code in my sleep :/ Let me know if you're able to find any bugs, or improvements, or just enjoyed the game.

Finally, I'm more of an social media lurker, so while I didn't respond too readily on this thread, your help/comments over the past few years (!) has been appreciated. 
Thanks!
-scomico


Attached Files Thumbnail(s)
   
Reply
#14
@scomico,
Saving data: you need a buffer of 256 bytes (u8) where the 4 first bytes are reserved for a "magic number".
This number is just a way to know if something has already been saved.
So you have 252 bytes for your own data starting at index 4.
You can then transfert the content of this buffer to your own data structure.
Reply
#15
Excellent news - I'll have a look through your code when I get a minute and see if I can give you a worked example to do the saving - edit: the most likely thing is that you haven't padded the ngp file to 2mb, it needs the empty space at the end of the file in order to save

With the sound - it's best to pick the old neotracker code out of the project and put WIC's code in on it's own - I'll see if I can pop that in for you as well if you'd like
Reply
#16
So, I had a look at your project and couldn't really figure out where you wanted to insert your load/save - so, what I've done in DDMR etc is to abstract the save code into it's own functions


Code:
void GetDDMRData(u16 *Palette, u8 *Difficulty, SCORE *scoretable)
{
    u32 data[256];
    u8 iScoreLoop;

    GetFlash(&data);

    // Set defaults
    *Palette=RGB(0,15,15);
    *Difficulty=1;

    switch(data[0])
    {
        case MAGIC_NB:
            {
                // Restore from
                SetRandomCounterSeed((u16)data[1]);
                *Palette=(u16)data[2];
                *Difficulty=(u8)data[3];
                for(iScoreLoop=0;iScoreLoop<(HST_SIZE*3);iScoreLoop++)
                {
                    scoretable[iScoreLoop].Initial1=(data[4+(iScoreLoop<<1)]&0xff000000)>>24;
                    scoretable[iScoreLoop].Initial2=(data[4+(iScoreLoop<<1)]&0x00ff0000)>>16;
                    scoretable[iScoreLoop].Initial3=(data[4+(iScoreLoop<<1)]&0x0000ff00)>>8;
                    scoretable[iScoreLoop].Score=(u16)(data[5+(iScoreLoop<<1)]&0x0000ffff);
                }
            }
            break;
        case MAGIC_NB+1:
            {
                // Set defaults
                InitialiseQRandom();
                for(iScoreLoop=0;iScoreLoop<(HST_SIZE*3);iScoreLoop++)
                {
                    scoretable[iScoreLoop].Initial1=65;
                    scoretable[iScoreLoop].Initial2=65;
                    scoretable[iScoreLoop].Initial3=65;
                    scoretable[iScoreLoop].Score=0;
                }
            }
            break;
        default:
            // Shouldn't be anything else
            break;
    }
}

/**********************************
*     Saves data into flash memory:
*  - QRandom() seed
*  - Mr Robot's palette
*  - High score table
*
* First byte will be the MAGIC_NB
* and subsequent bytes will be the stored data
* data[1] == Random Seed
* data[2] == Mr Robot Palette
* data[3]-data[3+(HST_SIZE*2)] == HighScore Table
* High Score entry
* byte0=INITIALS
* byte1=SCORE
**********************************/
void SaveDDMR(u16 MrRobotPalette, u8 Difficulty, SCORE HighScoreTable[])
{

    u32 data[256];
    u8 iScoreLoop;

    GetFlash(&data);
    data[0]=MAGIC_NB;
    data[1]=GetRandomCounterSeed();
    data[2]=MrRobotPalette;
    data[3]=Difficulty;
    for(iScoreLoop=0;iScoreLoop<(HST_SIZE*3);iScoreLoop++)
    {
        data[4+(iScoreLoop<<1)]=((u32)HighScoreTable[iScoreLoop].Initial1<<24)+((u32)HighScoreTable[iScoreLoop].Initial2<<16)+((u32)HighScoreTable[iScoreLoop].Initial3<<8);
        data[5+(iScoreLoop<<1)]=((u32)HighScoreTable[iScoreLoop].Score);
    }
    SetFlash(data);

}

And then changed (a little bit by trial and error) the original library.c functions like so:

Code:
void SetFlash(void *data) {
    
    // The "data" array needs to have the magic number (MAGIC_NB)
    // in position zero

    // Calling function needs to set this as follows:
    // data[0]=MAGIC_NB
    // What you do with the remaining elements is up to you

    // Set the save offset and block number
    // These need to be equal to the ptr number in GetFlash()
    // SAVEOFFSET 0x1FA000
    // +
    // BLOCK_NB 0x21
    // = 0x3FA000
    // No, I don't quite get it either, but these are the numbers that
    // seem to work...

    __ASM("SAVEOFFSET    EQU    0x1FA000");
    __ASM("BLOCK_NB        EQU    0x21");

    // Other variables are fixed and refer to the various system calls required by the flash write
    __ASM("VECT_FLASHWRITE    EQU    6");
    __ASM("VECT_FLASHERS    EQU    8");
    __ASM("rWDCR        EQU    0x6f");
    __ASM("WD_CLR        EQU    0x4e");

    // Erase block first (mandatory) : 64kb for only 256 bytes
    __ASM("    ld    ra3,0");
    __ASM("    ld    rb3,BLOCK_NB");
    __ASM("    ld    rw3,VECT_FLASHERS");
    __ASM("    ld    (rWDCR),WD_CLR");
    __ASM("    swi    1");

    // Then write data
    // Set low/high data size (0 low + 2 high=512 bytes, I think?)
    __ASM("    ld    ra3,0"); 
    __ASM("    ld    rbc3,2");    // 512 bytes
    // Call the Flash write routine
    __ASM("    ld    xhl,(xsp+4)");
    __ASM("    ld    xhl3,xhl");
    __ASM("    ld    xde3,SAVEOFFSET");
    __ASM("    ld    rw3,VECT_FLASHWRITE");
    __ASM("    ld    (rWDCR),WD_CLR");
    __ASM("    swi    1");

    __ASM("    ld    (rWDCR),WD_CLR");
}

void GetFlash(void *data) {
    
    // Set the pointers up to the flash memory address
    // Needs to be the same as address used in SetFlash()

    u32 *ptr = (u32*)(0x3FA000);
    u32 *ptrData = (u32*)data;
    u8 i;
    // Check the read data for the "magic" number
    // Basically, an arbitary number that we have in data[0]
    // If this isn't set then the data hasn't been initialised

    if (*ptr == MAGIC_NB) // Data saved
    {
        for (i=0;i<128;i++)
            ptrData[i] = ptr[i];
    }
    else // No data
    {
        // If the magic number is not set, then set MAGIC_NB+1 to the first element of the array
        // and then set everything else to zero
        // The calling routine can then set the array up as you see fit (default values etc)
        // and then set data[0]=MAGIC_NB to enable writing
        ptrData[0] = MAGIC_NB+1;
        for (i=1;i<128;i++)
            ptrData[i] = 0x00;
    }
}

The magic number can be anything you like, it's literally just a sequence of bytes that you wouldn't expect to see normally. Thor's original one was to use 0xcafebabe and I didn't see the need to change that

The last piece of the puzzle, at least when you flash to flashmasta/retrohq is to pad the ROM file to 2mb - winteriscoming used a .py script for that, but I used the following windows command script to do the same thing (so I don't have to have python installed) - certutil and fsutil should be available on any standard Win10/11 installation

Code:
ECHO Padding:
echo ff ff ff ff ff ff ff ff>ff.txt
certutil -decodehex ff.txt ff.pad
FOR /L %%f IN (1,1,18) DO (
    ECHO PASS %%f
    COPY /b ff.pad+ff.pad ff.pad2 >NUL
    DEL ff.pad
    REN ff.pad2 ff.pad
)
copy /b MRROBOT.ngp+ff.pad TEMP.ngp
del MRROBOT.ngp
del ff.txt
del ff.pad
ren TEMP.ngp MRROBOT.ngp
fsutil file setEOF MRROBOT.ngp 2097152
Reply
#17
Anyway, cute little game - I really enjoyed the manual Big Grin
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)