(classic) New target: Nintendo Gameboy
(classic) New target: Nintendo Gameboy
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.
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.
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?
...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.
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 Process Monitor tool reports the last z88dk-related activity to be an access to z88dk-ucpp.exe.
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:
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.
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)
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.
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?
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
}
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?
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.
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.
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.
@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.
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.
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
}
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.
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.
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):
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.
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
}
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.
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
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
I think they are already mapped into FIRE3 and FIRE4 - see the code: https://github.com/z88dk/z88dk/blob/mas ... ystick.asmRobertK 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.
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.RobertK wrote:The floting point issue still needs to be fixed (if possible), currently my floatcalctest.c program gives compiler errors:
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.
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.dom wrote:I think they are already mapped into FIRE3 and FIRE4 - see the code: https://github.com/z88dk/z88dk/blob/mas ... ystick.asmRobertK 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.
A new version of my game H-Tron supporting the Nintendo Gameboy is now online. Mission accomplished!
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.
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))
{
}
}
Thanks, this is really looking wonderful!
Here's what I was working on lately:
Here's what I was working on lately:
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;
}
}
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.
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]);
}
}
}