(classic) New target: Nintendo Gameboy

Discussion about other targets
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

(classic) New target: Nintendo Gameboy

Post by dom »

I've just merged preliminary support the Gameboy and its associated CPU - adding 8080 support made this a fairly "easy" exercise.

The library is comprised of a modified GBDK library and our standard string, ctype and stdio functions.

The supplied example programs compile down to a .gb file that can be loaded into numerous emulators (tested with VGB and Mame).

There's still a bit of work to do:

- Fixing console input
- Making conio.h to work as expected
- Getting banking working properly
- Allow SDCC to be used as a compiler

However, it's a usable starting point.
User avatar
RobertK
Well known member
Posts: 347
Joined: Mon Feb 26, 2018 12:58 pm

Post by RobertK »

Thanks for this new target!

I have noticed on the platform list that the Generic Console should be available now.

Can we already compile out-of-the-box using the latest z88dk nightly, or is some extra configuration required?

Because whenever I try to compile any simple program like this?

Code: Select all

zcc +gb -create-app hello.c
...the compiler hangs without any console output.

The Process Monitor tool reports the last z88dk-related activity to be an access to z88dk-ucpp.exe.
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I'm in the process of binding the GBDK code to the z88dk classic library - gencon is working as far as printing text and peeking. I need to add in graphics, font support etc so there's not quite enough to support the things you need yet.

There's two examples in the kit which are compiling nightly:

Code: Select all

cd examples/gb
zcc +gb -create-app -o galaxy.bin galaxy.c
Program requires cartridge with 2 ROM banks
Notice: Available RAM space is 7914 bytes ignoring the stack
Adding main banks 0x00,0x01 (20941 bytes free)
zcc +gb -create-app -o paint.bin paint.c
Program requires cartridge with 2 ROM banks
Notice: Available RAM space is 7168 bytes ignoring the stack
Adding main banks 0x00,0x01 (19846 bytes free)
If it's hanging in z88dk-ucpp then that's the preprocessor stage failing in someway - can you run with the -v option to confirm that? I'll give it a go on windows and valgrind a linux test case to see if anything is being shown up.
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I've reproduced this now - it only occurs on windows and is triggered by the -IDESTDIR/include/arch/ in lib/config/gb.cfg, so until I figure out a fix just remove that!
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

It turns out it's a simple fix: The trailing / on the -I path gets turned into a \ on Windows. This ends up in the command line as \" and most of the rest of the command line is swallowed.

As a result there's no input file for the preprocessor and it just hangs waiting for input.
User avatar
RobertK
Well known member
Posts: 347
Joined: Mon Feb 26, 2018 12:58 pm

Post by RobertK »

Thanks, now it compiles fine.

I have noticed a small bug with the first "\n" being printed. Here is a sample, the first screenshot shows the Native Console, the second the Generic Console output.

Code: Select all

// Compile with
// zcc +gb -create-app hellogb.c -o hellogb.gb
// or
// zcc +gb -create-app -pragma-redirect:fputc_cons=fputc_cons_generic -o hellogb.gb hellogb.c 

void main()
{ 
  printf("\nHello World!\n");
  printf("\nHello 2!\n");
  printf("\n\n\nHello 3!\n");
  fgetc_cons();        // wait for keypress          
}
Image Image

gotoxy() seems to work fine already on the Generic Console.

Clearing the screen using...
printf("%c",12);
printf("\x0c");
...makes the program crash (it resets the machine).

What is the character table appearing every time, is this a test you have added or is this a feature of that machine?
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I'm glad you've got something working! Always nice to see that I've not forgotten to check something in!

As I mentioned I'm still working on the code so what I'm seeing is possibly slightly different. I'm not seeing the cls issue anymore, though previously I think there were some oddities with it. Hopefully I'll do a merge today and that one will be sorted.

The linefeed one can also be explained. The GBDK driver sets up the font when the first character is printed. This clears the screen and resets the coordinates it uses to (0,0), when the character is printed, gencon sets that coordinates to the position that it believes it's at. It looks like this is a long-standing issue (even with gbdk I think a gotoxy() before printing the first character fails) but can be fixed.

The character set that appears is the on-screen keyboard! - You've used fgetc_cons() and since there's no hardware keyboard a software emulated one appears.
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Post by stefano »

.. the on screen keyboard! thanks for this gem, the gameboy on z88dk was an unreachable wish I had since 2002, or whichever year it was when the project began!
thank you Dom ! .. and thanks to Robert and many other folks for the continuous support and enthusiasm :)
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

It's nice to enact the reunion between the gbdk libraries and rpn example. It's been 20 years or so of separation but we've got there!

@RobertK, I've added simple graphics to the target now, it might be enough to run HTron. You will have to specify which font you want to use use -pragma-redirect:CRT_FONT=_font..... to get the lores graphic blocks.

I'm trying to keep the libraries compatible with GBDK so by default it uses the full IBM font which doesn't have the required glyphs.
User avatar
RobertK
Well known member
Posts: 347
Joined: Mon Feb 26, 2018 12:58 pm

Post by RobertK »

Thanks, that's fantastic news!

The clear screen issue is fixed now for both console types, and generic console text output works now. But when a custom font is specified, gotoxy() and printf() make the program crash.

Lo-Res plotting (40x36) seems to be fully working already. I have a cunning plan: could we make more targets capable of low-res-graphics by using a custom font??

games.h support works as well, but the Gameboy target should support only one Joystick named "Control Pad" including support for Buttons A, B, Select and Start.

Here is a little test program for the custom font problem (use the third compile command).

Another issue (which has low priority for me): in native console mode, the "H" character of printf("\nHello World!\n") is positioned one line too low. Use the first compile command to reproduce this.

Code: Select all

/* Compile with
zcc +gb -create-app -o hellogb2.gb hellogb2.c
zcc +gb -create-app -pragma-redirect:fputc_cons=fputc_cons_generic -o hellogb2_gencon.gb hellogb2.c 
zcc +gb -create-app -pragma-redirect:fputc_cons=fputc_cons_generic -o hellogb2_gencon_font.gb hellogb2.c -pragma-redirect:CRT_FONT=_font_8x8_bbc_system
*/

void main()
{ 
  printf("\nHello World!\n");
  fgetc_cons();        // wait for keypress
  
  // Clear the Screen
  printf("%c",12);
  printf("\x0c");
  
  gotoxy(3,10); // position the cursor at column 3 and line 10 
  printf("Hello once more!");
  fgetc_cons();        // wait for keypress          
}
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

It's odd, I thought I did the joystick naming in games.h but it seems to have got lost somewhere. Regardless it's now there.

The gotoxy() problem was a bit of a head scratch for a while but it should now be resolved. However it's potentially a recurring issue for other functions. On the LR35902 the F register only has 4 valid bits (it's arranged differently to the z80 as well) with the result that the remaining 4 bits are always set to 0. In many functions we gather the stack arguments into registers, using af as a temporary to store the return address before pushing it back again. On the Gameboy we end up pushing back the (address & ~15) so the return is to somewhere a bit wild. However, had you included <conio.h> then it wouldn't have been spotted since the _callee() variant is used there.

Regarding the native console - this is an issue in the underlying GBDK so I'm not going to fix it - I'm trying to maintain the compatibility there.
User avatar
RobertK
Well known member
Posts: 347
Joined: Mon Feb 26, 2018 12:58 pm

Post by RobertK »

No problem with the native console issue, we don't really need the native console when we have a working generic console.

gotoxy() printing works now with a custom font, but now plotting is broken, it was still functional in Saturday's build.

And there seems to be a problem with floating point calculations (this so far had never worked on this new target):

Code: Select all

// Floating point calculation test
// Author: RobertK, 2018-12-29

// Compile with:
// zcc +gal -create-app -lm -o fct floatcalctest.c
// zcc +zx81 -create-app -lm -startup=2 -o fct_zx81 floatcalctest.c
// zcc +zx80 -create-app -lm -o fct_zx80 floatcalctest.c
// zcc +gb -create-app -lm -o fctgb.gb floatcalctest.c

#include <stdio.h>

void main()
{   
  printf("\nhello world\n");
  printf("\npress any key to calculate 5*0.1...\n");
  fgetc_cons();        // wait for keypress          
  printf("\n5*0.1 is %.1f\n",5*0.1);
  printf("\npress any key to exit...\n");  
  fgetc_cons();        // wait for keypress          
}
And when I try to compile my EPB program using the -lm option, I get this compiler error...

symbol 'l_long_mod' not defined

...at a position where I wouldn't expect it. Any idea what could be wrong? It could be that I did something wrong in my code, but I just can't find it.
User avatar
RobertK
Well known member
Posts: 347
Joined: Mon Feb 26, 2018 12:58 pm

Post by RobertK »

I can confirm that all issues regarding H-Tron are fixed now, and the AI logic no longer crashes, thank you.

One tiny little issue is still open: games.h should support the SELECT and START buttons and map them to MOVE_FIRE3 and MOVE_FIRE4.

The floting point issue still needs to be fixed (if possible), currently my floatcalctest.c program gives compiler errors:

Error at file 'ftoe.c' line 244: symbol 'l_gintspsp' not defined
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

RobertK wrote:One tiny little issue is still open: games.h should support the SELECT and START buttons and map them to MOVE_FIRE3 and MOVE_FIRE4.
I think they are already mapped into FIRE3 and FIRE4 - see the code: https://github.com/z88dk/z88dk/blob/mas ... ystick.asm
RobertK wrote:The floting point issue still needs to be fixed (if possible), currently my floatcalctest.c program gives compiler errors:
FP is going to be challenging, The new IEEE library uses the alternate registers a lot which leaves mbf32 as the obvious choice since it's 8080 code, however it makes a fair amount of use of the flags that aren't available on the gbz80 which will need some care to replace.

Moving to alternate libraries, there's this fragment: https://github.com/hschmitt/gbdk/blob/m ... /fp_long.s which was once part of GBDK. Or the BCD library here: https://www.devrs.com/gb/files/math.zip

I'll get around to adding floating point at some point, but it may be a while.
User avatar
RobertK
Well known member
Posts: 347
Joined: Mon Feb 26, 2018 12:58 pm

Post by RobertK »

dom wrote:
RobertK wrote:One tiny little issue is still open: games.h should support the SELECT and START buttons and map them to MOVE_FIRE3 and MOVE_FIRE4.
I think they are already mapped into FIRE3 and FIRE4 - see the code: https://github.com/z88dk/z88dk/blob/mas ... ystick.asm
I just noticed that my test program was only checking the first two buttons, so I couldn't really expect any reaction from buttons 3 and 4. :)

A new version of my game H-Tron supporting the Nintendo Gameboy is now online. Mission accomplished!

Image
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Post by stefano »

Wonderful, we can now begin the mass production of the new game ROMS
User avatar
RobertK
Well known member
Posts: 347
Joined: Mon Feb 26, 2018 12:58 pm

Post by RobertK »

I found a strange issue with the Gameboy target. The following test program should produce four random number digits between 0 and 5 by simply doing "rand() % 6".

On the Gameboy, the result is always 6, which is not what you would expect from a modulo 6 operation?

I tried to find out where exactly the problem comes from, but rand() seems to be working correctly, and so does a separate call of e.g. 4711 % 6.

Code: Select all

// RandModuloTest.c
// RobertK, 2020-02-05
/*
Compile with:
zcc +pv2000 -o RandModuloTest_PV2000 -create-app RandModuloTest.c
zcc +rx78 -o RandModuloTest_rx78 -create-app RandModuloTest.c
zcc +gb -create-app -pragma-redirect:fputc_cons=fputc_cons_generic -pragma-redirect:CRT_FONT=_font_8x8_bbc_system -o RandModuloTest_gameboy RandModuloTest.c
*/

#include <conio.h>
#include <games.h>

#define JOYSTICK_1 1
#define JOYSTICK_BUTTON_TRIGGER1 MOVE_FIRE1
        
void main()
{
        int randomSeed=0;
        int i;
        int codeToBreak[4];

        printf("Modulo Rand Test\n\n");        
        printf("Press Joystick 1 Trigger...\n\n");

        while (!(joystick(JOYSTICK_1) & JOYSTICK_BUTTON_TRIGGER1))
        {
                randomSeed++;
                if (randomSeed>32766) randomSeed=0;        // reset counter to avoid overflow
        }
        
        srand(randomSeed);

        for (i=0;i<=3;i++)
                codeToBreak[i] = rand() % 6;

        for (i=0;i<=3;i++)
        {
                printf("Code digit %d: %d\n", i, codeToBreak[i]); // always 6!
        }

        msleep(500);        // Wait half a second
        
        printf("\n\nPress Joystick 1 Trigger to exit...\n");

        while (!(joystick(JOYSTICK_1) & JOYSTICK_BUTTON_TRIGGER1))
        {
        }
        
}
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

Sorry Robert, I completely missed this post and only spotted it this evening.

I've investigated and pushed a fix for both sdcc and sccz80 crt0 code - the 16 bit division routines had the wrong register setup.
User avatar
RobertK
Well known member
Posts: 347
Joined: Mon Feb 26, 2018 12:58 pm

Post by RobertK »

Thanks Dom, now everything works fine. Here is Mastermind RK on the Gameboy:

Image
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Post by Timmy »

Thanks, this is really looking wonderful!
Here's what I was working on lately:

Image

Code: Select all

/*
 * Timmy's first gb demo
 * February 2020
 *
 * Compile with:
 *    zcc +gb -create-app -o gbdemo.o gbdemo.c
 *
 * Usage:
 *    Use joypad to move sprite
 *    Hold A and move joypad to move background
 */
 
#include <gb/gb.h>

// some tile data
const unsigned char backwalls[] = {

  247,  247,  247,  247,  247,  247,    0,    0,  223,  223,  223,  223,  223,  223,    0,    0,

  248,  248,  227,  227,  207,  207,  159,  159,  191,  191,   63,   63,  127,  127,  127,  127,
  127,  127,  127,  127,   63,   63,  191,  191,  159,  159,  207,  207,  227,  227,  248,  248, 

   31,   31,  199,  199,  243,  243,  249,  249,  253,  253,  252,  252,  254,  254,  254,  254, 
  254,  254,  254,  254,  252,  252,  253,  253,  249,  249,  243,  243,  199,  199,   31,   31,

  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  
        0,0,63,63,12,12,12,12,12,12,12,12,12,12,0,0,
        0,0,63,63,12,12,12,12,12,12,12,12,63,63,0,0,
        0,0,99,99,119,119,127,127,107,107,99,99,99,99,0,0,
        0,0,51,51,51,51,30,30,12,12,12,12,12,12,0,0
};

// several backgrounds
const unsigned char bkg_tiles[] = 
{
        4,3,2,1
};

const unsigned char bkg_tiles2[] = 
{
        0,0,0,0
};

const unsigned char bkg_tiles3[] = 
{
        7,8,9,9,10
};

// sprite
const unsigned char sprites[] = 
{
7, 0, 31, 3, 63, 12, 127, 16, 127, 32, 255, 32, 255, 64, 255, 64, 255, 70, 255, 73, 255, 75, 255, 70, 255, 0, 255, 127, 255, 6, 15, 0, 
224, 0, 240, 192, 252, 48, 254, 8, 254, 196, 255, 36, 255, 18, 255, 18, 255, 210, 255, 34, 255, 98, 255, 194, 255, 0, 255, 234, 255, 160, 240, 0 

};
        
uint8_t px1[4];
uint8_t py1[4];
int8_t pdx[4];
int8_t pdy[4];
        
void main()
{
  uint8_t i, j, x, y, px, py;

  disable_interrupts();
  DISPLAY_OFF;
  LCDC_REG = 0x67;

  /* Set palettes */
  BGP_REG = 94; 
  OBP0_REG = OBP1_REG = 30; 

  /* Initialise background */
  set_bkg_data(0, 11, backwalls);
 
  for(i = 0; i < 32; i+=2)
    for(j = 0; j < 32; j+=2)
          if ((i+j)&2)
                  set_bkg_tiles(i, j, 2, 2, bkg_tiles);
          else
                  set_bkg_tiles(i, j, 2, 2, bkg_tiles2);
          
  set_bkg_tiles(14, 16, 5, 1, bkg_tiles3);

  
  // Set Screen back to top left corner
  SCX_REG = 0;
  SCY_REG = 0;
  
  
        /* Push Sprite data to VRAM */
        set_sprite_data(0, 4, sprites);

        // Regular sprites
        set_sprite_tile(0, 0);
        set_sprite_tile(1, 2);
        move_sprite(0, 8,   16);
        move_sprite(1, 8+8, 16);
        set_sprite_prop(0,0);
        set_sprite_prop(1,0);

        // Y flipped sprites
        set_sprite_tile(2, 0);
        set_sprite_tile(3, 2);
        move_sprite(2, 8+16,   32);
        move_sprite(3, 8+16+8, 32);
        set_sprite_prop(2,S_FLIPY);
        set_sprite_prop(3,S_FLIPY);

        // X flipped sprites
        // Note: you have to flip the x positions of these 2 sprites too!
        set_sprite_tile(4, 2);
        set_sprite_tile(5, 0);
        move_sprite(4, 8+32+8, 48);
        move_sprite(5, 8+32,   48);
        set_sprite_prop(4,S_FLIPX);
        set_sprite_prop(5,S_FLIPX);

        set_sprite_tile(6, 0);
        set_sprite_tile(7, 2);
        set_sprite_tile(8, 0);
        set_sprite_tile(9, 2);
        
  // Ok! Done!
  // Let's open the display again
  DISPLAY_ON;
  enable_interrupts();

  x = 0; y = 0;
  px = 8, py = 16;
  
  px1[0] = 100; py1[0] =  32; pdx[0]= 1; pdy[0]=-2;
  px1[1] =  64; py1[1] =  80; pdx[1]= 2; pdy[1]= 2;
  px1[2] =  32; py1[2] = 100; pdx[2]=-2; pdy[2]=-1;
  px1[3] = 140; py1[3] =  64; pdx[3]=-1; pdy[3]= 1;
  while(1) 
  {
        //wait_vbl_done();

        i = joypad();

          
        if(!(i & J_A))
        {
                if(i & J_UP)
                {
                  if (py>0) py-=2;
                }
                if(i & J_DOWN)
                {
                  if (py<160) py+=2;
                }
                if(i & J_LEFT)
                {
                  if (px>0) px-=2;
                }
                if(i & J_RIGHT)
                {
                  if (px<160+8) px+=2;
                }
        }
        else
        {
                if(i & J_UP)
                {
                  if (y>0) y--;
                }
                if(i & J_DOWN)
                {
                  if (y<128) y++;
                }
                if(i & J_LEFT)
                {
                  if (x>0) x--;
                }
                if(i & J_RIGHT)
                {
                  if (x<128) x++;
                }                
        }
        
        for (j=0; j<4; j++)
        {
                px1[j] += pdx[j];
                py1[j] += pdy[j];
                if (px1[j]<8) pdx[j]=-pdx[j];
                if (px1[j]>8+144) pdx[j]=-pdx[j];
                if (py1[j]<16) pdy[j]=-pdy[j];
                if (py1[j]>16+128) pdy[j]=-pdy[j];
        }
                
        DISPLAY_OFF;
        SCX_REG = x;
        SCY_REG = y;
        move_sprite(0, px,   py);
        move_sprite(1, px+8, py);
        for (j=0; j<4; j++)
        {
                move_sprite(j*2+2, px1[j],   py1[j]);
                move_sprite(j*2+3, px1[j]+8, py1[j]);
        }
        DISPLAY_ON;
  }
}
User avatar
RobertK
Well known member
Posts: 347
Joined: Mon Feb 26, 2018 12:58 pm

Post by RobertK »

I just compiled it, that looks fantastic! I'm looking forward to the game that you will hopefully make out of this!
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Post by Timmy »

I don't think I'll make a game out of exactly this... I might just want to make a scrolling platformer or a overhead view adventure or something else. This is just a demo program I made to test things, and I've made the same thing for the Spectrum and MSX as well (these can all be found here in the forums.)

I feel like perhaps it's time to make a separate board for this target, because this target is very promising!

Anyway, this post here is to update my code... It seems turning off and on the display every frame is probably too much, so instead I use wait_vbl_done() instead. With this change, windowing is working too!

So here's a new version, with windowing.

Code: Select all

/*
 * Timmy's first gb demo, version 20200227
 * February 2020
 *
 * Compile with:
 *    zcc +gb -create-app -o gbdemo.o gbdemo.c
 *
 * Usage:
 *    Use joypad to move sprite
 *    Hold A and move joypad to move background
 *    Hold B and move joypad to move window
 */
 
#include <gb/gb.h>

// some tile data
const unsigned char backwalls[] = {

  247,  247,  247,  247,  247,  247,    0,    0,  223,  223,  223,  223,  223,  223,    0,    0,

  248,  248,  227,  227,  207,  207,  159,  159,  191,  191,   63,   63,  127,  127,  127,  127,
  127,  127,  127,  127,   63,   63,  191,  191,  159,  159,  207,  207,  227,  227,  248,  248, 

   31,   31,  199,  199,  243,  243,  249,  249,  253,  253,  252,  252,  254,  254,  254,  254, 
  254,  254,  254,  254,  252,  252,  253,  253,  249,  249,  243,  243,  199,  199,   31,   31,

  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  
        0,0,63,63,12,12,12,12,12,12,12,12,12,12,0,0,
        0,0,63,63,12,12,12,12,12,12,12,12,63,63,0,0,
        0,0,99,99,119,119,127,127,107,107,99,99,99,99,0,0,
        0,0,51,51,51,51,30,30,12,12,12,12,12,12,0,0
};

// several backgrounds
const unsigned char bkg_tiles[] = 
{
        4,3,2,1
};

const unsigned char bkg_tiles2[] = 
{
        0,0,0,0
};

const unsigned char bkg_tiles3[] = 
{
        7,8,9,9,10
};

// sprite
const unsigned char sprites[] = 
{
7, 0, 31, 3, 63, 12, 127, 16, 127, 32, 255, 32, 255, 64, 255, 64, 255, 70, 255, 73, 255, 75, 255, 70, 255, 0, 255, 127, 255, 6, 15, 0, 
224, 0, 240, 192, 252, 48, 254, 8, 254, 196, 255, 36, 255, 18, 255, 18, 255, 210, 255, 34, 255, 98, 255, 194, 255, 0, 255, 234, 255, 160, 240, 0 

};
        
uint8_t px1[4];
uint8_t py1[4];
int8_t pdx[4];
int8_t pdy[4];

uint8_t winx, winy;
        
void main()
{
  uint8_t i, j, x, y, px, py;

  disable_interrupts();
  DISPLAY_OFF;
  LCDC_REG = 0x67;

  /* Set palettes */
  BGP_REG = 94; 
  OBP0_REG = OBP1_REG = 30; 

  /* Initialise background */
  set_bkg_data(0, 11, backwalls);
 
  for(i = 0; i < 32; i+=2)
    for(j = 0; j < 32; j+=2)
          if ((i+j)&2)
                  set_bkg_tiles(i, j, 2, 2, bkg_tiles);
          else
                  set_bkg_tiles(i, j, 2, 2, bkg_tiles2);
          
  set_bkg_tiles(14, 16, 5, 1, bkg_tiles3);

  
  // Set Screen back to top left corner
  SCX_REG = 0;
  SCY_REG = 0;
  
  
        /* Push Sprite data to VRAM */
        set_sprite_data(0, 4, sprites);

        // Regular sprites
        set_sprite_tile(0, 0);
        set_sprite_tile(1, 2);
        move_sprite(0, 8,   16);
        move_sprite(1, 8+8, 16);
        set_sprite_prop(0,0);
        set_sprite_prop(1,0);

        // Y flipped sprites
        set_sprite_tile(2, 0);
        set_sprite_tile(3, 2);
        move_sprite(2, 8+16,   32);
        move_sprite(3, 8+16+8, 32);
        set_sprite_prop(2,S_FLIPY);
        set_sprite_prop(3,S_FLIPY);

        // X flipped sprites
        // Note: you have to flip the x positions of these 2 sprites too!
        set_sprite_tile(4, 2);
        set_sprite_tile(5, 0);
        move_sprite(4, 8+32+8, 48);
        move_sprite(5, 8+32,   48);
        set_sprite_prop(4,S_FLIPX);
        set_sprite_prop(5,S_FLIPX);

        set_sprite_tile(6, 0);
        set_sprite_tile(7, 2);
        set_sprite_tile(8, 0);
        set_sprite_tile(9, 2);
        
        winx = 7 + 40;
        winy = 128;
        WX_REG = winx;
        WY_REG = winy;
        set_win_tiles(1, 1, 5, 1, bkg_tiles3);
        
  // Ok! Done!
  // Let's open the display again
  DISPLAY_ON;
  enable_interrupts();

  x = 0; y = 0;
  px = 8, py = 16;
  
  px1[0] = 100; py1[0] =  32; pdx[0]= 1; pdy[0]=-2;
  px1[1] =  64; py1[1] =  80; pdx[1]= 2; pdy[1]= 2;
  px1[2] =  32; py1[2] = 100; pdx[2]=-2; pdy[2]=-1;
  px1[3] = 140; py1[3] =  64; pdx[3]=-1; pdy[3]= 1;
  while(1) 
  {
        //wait_vbl_done();

        i = joypad();

          
        if((i & J_A))
        {
                if(i & J_UP)
                {
                  if (y>0) y--;
                }
                if(i & J_DOWN)
                {
                  if (y<128) y++;
                }
                if(i & J_LEFT)
                {
                  if (x>0) x--;
                }
                if(i & J_RIGHT)
                {
                  if (x<128) x++;
                }                
        }
        else
        if((i & J_B))
        {
                if(i & J_UP)
                {
                  if (winy>0) winy-=2;
                }
                if(i & J_DOWN)
                {
                  if (winy<160) winy+=2;
                }
                if(i & J_LEFT)
                {
                  if (winx>8) winx-=2;
                }
                if(i & J_RIGHT)
                {
                  if (winx<160+8) winx+=2;
                }
        }
        else
        {
                if(i & J_UP)
                {
                  if (py>0) py-=2;
                }
                if(i & J_DOWN)
                {
                  if (py<160) py+=2;
                }
                if(i & J_LEFT)
                {
                  if (px>0) px-=2;
                }
                if(i & J_RIGHT)
                {
                  if (px<160+8) px+=2;
                }
        }
        
        
        for (j=0; j<4; j++)
        {
                px1[j] += pdx[j];
                py1[j] += pdy[j];
                if (px1[j]<8) pdx[j]=-pdx[j];
                if (px1[j]>8+144) pdx[j]=-pdx[j];
                if (py1[j]<16) pdy[j]=-pdy[j];
                if (py1[j]>16+128) pdy[j]=-pdy[j];
        }
                
        wait_vbl_done();
        SCX_REG = x;
        SCY_REG = y;
        WX_REG = winx;
        WY_REG = winy;
        move_sprite(0, px,   py);
        move_sprite(1, px+8, py);
        for (j=0; j<4; j++)
        {
                move_sprite(j*2+2, px1[j],   py1[j]);
                move_sprite(j*2+3, px1[j]+8, py1[j]);
        }
  }
}
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Post by Timmy »

Is it possible to write inline assembly with z88dk for this target?

I probably won't need it and I doubt it's possible, but I just want to know if I'd have to write in z80 assembly, or in some other language, or neither.

Thanks in advance for the answer.
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

It's the same as any other target, so inline assembler is possible. The gbz80 opcodes are supported should you need them. As a gotcha, some useful z80 instructions are emulated (eg ldir, ex (sp),hl) which might not be what is expected.
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Post by Timmy »

Thanks for the information. I am still not planning to write any inline assembly, yet.
But the fact that it can, is great to hear!
Post Reply