William Lohan Posted February 18, 2020 Share Posted February 18, 2020 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 Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted February 18, 2020 Share Posted February 18, 2020 I'd recommend using the stdint.h for variable types, e.g. uint16_t etc to be clear on the bit sizes used. Quote Link to comment Share on other sites More sharing options...
William Lohan Posted February 18, 2020 Author Share Posted February 18, 2020 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 Quote Link to comment Share on other sites More sharing options...
explorer Posted February 18, 2020 Share Posted February 18, 2020 while (1 < 2) is an infinite loop... Quote Link to comment Share on other sites More sharing options...
William Lohan Posted February 18, 2020 Author Share Posted February 18, 2020 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. Quote Link to comment Share on other sites More sharing options...
dmsc Posted February 18, 2020 Share Posted February 18, 2020 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! 1 Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted February 21, 2020 Share Posted February 21, 2020 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 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.