Jump to content
IGNORED

POKE causes infinite loop


Recommended Posts

I'm trying to implement the PMG BASIC program in 

 but in C with cc65. So far I have:

 

#include <stdio.h>
#include <stdlib.h>
#include <atari.h>
#include <peekpoke.h>

/* OS.ramtop is 0x006A (106) - *((unsigned char *) 0x006A) */
/* OS.sdmctl is 0x022F (559) - *((unsigned char *) 0x022F) */

#define PMBASE 0xD407 /* (54279) */
#define ENABLE_PMG 0xD01D /* (53277) */
#define PLYR_COLR 0x02C0 /* (704) */
#define X_POS 0xD000 /* (53248) */
#define PLYR_WIDTH 0xD008 /* (53256) */

/* PMG base mem */
unsigned short int playerBase;
/* player 1 base mem */
unsigned short int player1;

/* setup PMG */
void setup(void)
{
  unsigned char newTop;

  /* - 8 pages is 2KB */
  newTop = OS.ramtop - 8;
  OS.ramtop = newTop;
  /* _graphics(3 + 16); */
  playerBase = newTop * 256;
  printf("playerBase: %u\n", playerBase);
  /* set where PMG mem is */
  POKE(PMBASE, newTop);
  /* single line res */
  OS.sdmctl = 62;
  /* enable PMG */
  POKE(ENABLE_PMG, 3);
  /* player color */
  POKE(704, 84); /* ?? PLYR_COLR */
  /* X position */
  POKE(X_POS, 120);
  /* normal width */
  POKE((int)53256, (int)0); /* ?? PLYR_WIDTH */
}

/* clear mem for player 1 */
void cleanMem(void)
{
  unsigned short int j;

  /* fill with zeros */
  for (j = 0; j < 256; ++j) {
    printf("j: %u\n", j);
    POKE(player1 + j, 0);
  }
}

void drawShip(void)
{
  unsigned short int y, i;
  unsigned char shipData[15] = { 64, 96, 112, 112, 254, 254, 255, 235, 255, 254, 254, 112, 112, 96, 64 };

  y = player1 + 120;
  for (i = 0; i < 15; ++i) {
    printf("y: %u\n", y);
    /* POKE(y + i, shipData[i]); */
  }
}

void move(void)
{
  /* TODO */
}

int main(void)
{
  setup();
  /* player data */
  player1 = playerBase + 1024;
  printf("player1: %u\n", player1);
  cleanMem();
  /* drawShip(); */
  while (1 < 2) {
    /* move(); */
  }
  return EXIT_SUCCESS;
}

running with:

cl65 -t atari -c --create-dep obj/atari/main.d  -o obj/atari/main.o src/main.c
cl65 -t atari  -o .\dist\atari\hello-world.atari obj/atari/main.o
Altirra /debug /run .\dist\atari\hello-world.atari

 

The first problem I run into is in `cleanMem()`; if I comment out `POKE(player1 + j, 0);` it printf s 0 through 255 but with the POKE it loops through a rage of numbers and never finishes `cleanMem()` and I can figure out why. PS I can pushthe project to a github but its really just this code in a `main.c` file in a src folder

Link to comment
Share on other sites

6 hours ago, Wrathchild said:

I'd recommend using the stdint.h for variable types, e.g. uint16_t etc to be clear on the bit sizes used.

 
   

Thanks for the tip
 

#include <stdio.h>
#include <stdlib.h>
#include <atari.h>
#include <peekpoke.h>
#include <stdint.h>

/* OS.ramtop is 0x006A (106) - *((unsigned char *) 0x006A) */
/* OS.sdmctl is 0x022F (559) - *((unsigned char *) 0x022F) */

#define PMBASE 0xD407 /* (54279) */
#define ENABLE_PMG 0xD01D /* (53277) */
#define PLYR_COLR 0x02C0 /* (704) */
#define X_POS 0xD000 /* (53248) */
#define PLYR_WIDTH 0xD008 /* (53256) */

/* PMG base mem */
uint16_t playerBase;
/* player 1 base mem */
uint16_t player1;

/* setup PMG */
void setup(void)
{
  uint8_t newTop;

  /* - 8 pages is 2KB */
  newTop = OS.ramtop - 8;
  OS.ramtop = newTop;
  /* _graphics(3 + 16); */
  playerBase = newTop * 256;
  printf("playerBase: %u\n", playerBase);
  /* set where PMG mem is */
  POKE(PMBASE, newTop);
  /* single line res */
  OS.sdmctl = 62;
  /* enable PMG */
  POKE(ENABLE_PMG, 3);
  /* player color */
  POKE(704, 84); /* ?? PLYR_COLR */
  /* X position */
  POKE(X_POS, 120);
  /* normal width */
  POKE((int)53256, (int)0); /* ?? PLYR_WIDTH */
}

/* clear mem for player 1 */
void cleanMem(void)
{
  uint16_t j;

  /* fill with zeros */
  for (j = 0; j < 256; ++j)
  {
    printf("j: %u\n", j);
    /* POKE(player1 + j, 0); */
  }
}

void drawShip(void)
{
  uint16_t y, i;
  uint8_t shipData[15] = {64, 96, 112, 112, 254, 254, 255, 235, 255, 254, 254, 112, 112, 96, 64};

  y = player1 + 120;
  for (i = 0; i < 15; ++i)
  {
    printf("y: %u\n", y);
    /* POKE(y + i, shipData[i]); */
  }
}

void move(void)
{
  /* TODO */
}

int main(void)
{
  setup();
  /* player data */
  player1 = playerBase + 1024;
  printf("player1: %u\n", player1);
  cleanMem();
  /* drawShip(); */
  while (1 < 2)
  {
    /* move(); */
  }
  return EXIT_SUCCESS;
}

same result though

Link to comment
Share on other sites

12 hours ago, explorer said:

while (1 < 2)

is an infinite loop...

Sorry yes, that was to setup the animation loop which I haven't even got to (thus the TODO comment in move() ) I should have removed that for clarity. but the loop happens in the "for" statement of `cleanMem()`, before it even gets to that point.

Link to comment
Share on other sites

Hi!

1 hour ago, William Lohan said:

Sorry yes, that was to setup the animation loop which I haven't even got to (thus the TODO comment in move() ) I should have removed that for clarity. but the loop happens in the "for" statement of `cleanMem()`, before it even gets to that point.

For questions about CC65, it is probably better to just ask via the github page, as not all the developers read this forum, and I think that not many people uses CC65 directly here.

 

You have two main problems with your code:

 

1: You are altering the RAMTOP OS variable, to reserve 2kB of RAM at the end of the current memory. For this to work, you need to set a new graphics mode so that the OS would move the screen, if not you are just trashing your P/M data with the screen data, resulting in garbage in the screen.

 

2: You are assuming that memory management in the CC65 libraries work like in BASIC - it does not work the same. In the CC65 startup library, all memory available to the program is reserved at start, there is no memory free for the OS. This means that you can't move RAMTOP, as at the current top of memory is the C stack with all your local variables. This explains why when you alter the memory you overwrite the variables and trash the runtime.

 

So, you need to specify to the linker (at compile time) that you want to reserve memory from the C runtime, that memory then is available to your programs. Compile with:

cl65 -t atari -Osir -Wl -D__RESERVED_MEMORY__=8192 myprogram.c

The "-Osir" activates all optimizations (making the program smaller and faster), the "-Wl" option passes the next option to the linker and the "-D__RESERVED_MEMORY__=####" tells the linker to reserve that amount of bytes. After this, uncomment your "_graphics()" call, a simple "_graphics(16)" should suffice to set graphics 0 without text window.

 

Have Fun!

  • Like 1
Link to comment
Share on other sites

hello,

few comments:

Quote

#define PMBASE 0xD407 /* (54279) */
#define ENABLE_PMG 0xD01D /* (53277) */
#define PLYR_COLR 0x02C0 /* (704) */
#define X_POS 0xD000 /* (53248) */
#define PLYR_WIDTH 0xD008 /* (53256) */

 

if you include <atari.h>

you will be able to use OS and GTIA writing directly as in the following example:

Quote

GTIA_WRITE.gractl = GRACTL_MISSLES + GRACTL_PLAYERS;
ANTIC.pmbase = PMG_MEM >> 8;
GTIA_WRITE.hposp0 = 0x40;

GTIA_WRITE.sizep0 = 1;

OS.pcolr0 = 0x24;

OS.gprior = PRIOR_PF03_P03;

you can find the exact constants under <os.h> and <gtia.h> in the include folder of the shipped CC65.

 

instead of writing this:

Quote

void cleanMem(void)
{
  uint16_t j;

  /* fill with zeros */
  for (j = 0; j < 256; ++j)
  {
    printf("j: %u\n", j);
    /* POKE(player1 + j, 0); */
  }
}

try to use this, which is much faster and optimized:

Quote

bzero ((void*)player1,0x100);

for that you need to include <string.h>

 

same way, instead of using this:

Quote

void drawShip(void)
{
  uint16_t y, i;
  uint8_t shipData[15] = {64, 96, 112, 112, 254, 254, 255, 235, 255, 254, 254, 112, 112, 96, 64};

  y = player1 + 120;
  for (i = 0; i < 15; ++i)
  {
    printf("y: %u\n", y);
    /* POKE(y + i, shipData[i]); */
  }
}

try to remove the for loop with this:

Quote

// use this as a global variable and set it as unsigned char
shipData[15] = 
{64, 96, 112, 112, 254, 254, 255, 235, 255, 254, 254, 112, 112, 96, 64};

void drawShip(void)
{
   memcpy((void*)player1+120,(void*)shipData,15);
}

again, much faster, and for memcpy you will need to include <string.h>

 

 

hope this helps

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...