42bs Posted August 12, 2020 Share Posted August 12, 2020 23 minutes ago, OldAtAtari said: Ok, I'm trying to assemble the Ottelo game that Karri made available for download, and I'm getting an "Unsolved labels" error. Anyone know where I'm going wrong? These should be defined in hardware.inc . Please check this file. 1 Quote Link to comment Share on other sites More sharing options...
42bs Posted August 12, 2020 Share Posted August 12, 2020 30 minutes ago, OldAtAtari said: Ok, I'm trying to assemble the Ottelo game that Karri made available for download, and I'm getting an "Unsolved labels" error. Anyone know where I'm going wrong? These should be defined in hardware.inc . You should include it at the top , see mines.asm. Previous versions of the macros used hardcoded addresses instead of symbols. 1 Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 12, 2020 Author Share Posted August 12, 2020 36 minutes ago, 42bs said: These should be defined in hardware.inc . You should include it at the top , see mines.asm. Previous versions of the macros used hardcoded addresses instead of symbols. Yep, that did it. Thank you so much! Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 12, 2020 Author Share Posted August 12, 2020 (edited) I've been bouncing around from thing to thing, playing with the otello, mines, and game.c examples. I've been hacking away at game.c. I wanted to see if I could get the road to be stationary while the tree moves around the screen without resizing. Mission accomplished. A silly little goal, but then if I can figure out how to get either of the two sprite generators (sprpck and sp65) working, I'll be able to change that tree into a car, a robot, or whatever. Little milestones. Edited August 12, 2020 by OldAtAtari Removing excess screenshots 2 Quote Link to comment Share on other sites More sharing options...
Turbo Laser Lynx Posted August 12, 2020 Share Posted August 12, 2020 (edited) 2 hours ago, OldAtAtari said: if I can figure out how to get either of the two sprite generators (sprpck and sp65) working, I'll be able to change that tree into a car, a robot, or whatever. You can just exchange the tree.pcx file to any pcx file you want, the makefile takes care of the conversion. You can see in the makefile (in the same folder) the parameters sent to sp65 tree.c : tree.pcx $(SP) -r $< -c lynx-sprite,mode=packed,ax=94,ay=168 -w $*.c,ident=$*,bytesperline=8 The palette might get messed up, but in that case you can change around the numbers (pens) in the sprite definition (i.e. SCB i.e Sprite Control Block) in the pen palette array to point to the correct colors. The last line here: static SCB_REHV_PAL Stree = { BPP_4 | TYPE_NORMAL, 0x10, 0x20, 0, tree, 0, 0, 0x0100, 0x100, {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef} //pen palette array, change here }; Every number is a pen of its own. 0x is just for telling the compiler that it's a hex number, so 0 is one pen, 1 is one pen, 2 is one pen etc. The palette and the sprite SCB's are good to read up on: https://atarilynxdeveloper.wordpress.com/2012/10/10/programming-tutorial-part-7the-basics-of-sprites/ https://atarilynxdeveloper.wordpress.com/2012/10/14/programming-tutorial-part-8changing-appearances/ At least Aseprite and Gimp can handle pcx files. This post and thread has a lot of info on sp65: If you want to add more sprites into your game, in game.c you need to add: extern unsigned char robot[]; //add a SCB static SCB_REHV_PAL Srobot = { BPP_4 | TYPE_NORMAL, 0x10, 0x20, 0, robot, 0, 0, 0x0100, 0x100, {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef} }; //add coordinates Srobot.vpos = y; Srobot.hpos = x //draw it tgi_sprite(&Srobot); Also you need to add your new sprite/graphic into the object list in the make file: objects= \ game.o \ robot.o \ tree.o Edited August 12, 2020 by Turbo Laser Lynx 1 Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 12, 2020 Author Share Posted August 12, 2020 6 minutes ago, Turbo Laser Lynx said: You can just exchange the tree.pcx file to any pcx file you want, the makefile takes care of the conversion. You can see in the makefile (in the same folder) the parameters sent to sp65 tree.c : tree.pcx $(SP) -r $< -c lynx-sprite,mode=packed,ax=94,ay=168 -w $*.c,ident=$*,bytesperline=8 The palette might get messed up, but in that case you can change around the numbers (pens) in the sprite definition (i.e. SCB i.e Sprite Control Block) in the pen palette array to point to the correct colors. The last line here: static SCB_REHV_PAL Stree = { BPP_4 | TYPE_NORMAL, 0x10, 0x20, 0, tree, 0, 0, 0x0100, 0x100, {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef} //pen palette array, change here }; Every number is a pen of its own. 0x is just for telling the compiler that it's a hex number, so 0 is one pen, 1 is one pen, 2 is one pen etc. The palette and the sprite SCB's are good to read up on: https://atarilynxdeveloper.wordpress.com/2012/10/10/programming-tutorial-part-7the-basics-of-sprites/ https://atarilynxdeveloper.wordpress.com/2012/10/14/programming-tutorial-part-8changing-appearances/ At least Aseprite and Gimp can handle pcx files. This post and thread has a lot of info on sp65: Thank you! So much to learn. And there are also shortcuts, so that can keep it fun while I'm learning. 1 Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 12, 2020 Author Share Posted August 12, 2020 1 hour ago, Turbo Laser Lynx said: You can just exchange the tree.pcx file to any pcx file you want, the makefile takes care of the conversion. You can see in the makefile (in the same folder) the parameters sent to sp65 tree.c : tree.pcx $(SP) -r $< -c lynx-sprite,mode=packed,ax=94,ay=168 -w $*.c,ident=$*,bytesperline=8 The palette might get messed up, but in that case you can change around the numbers (pens) in the sprite definition (i.e. SCB i.e Sprite Control Block) in the pen palette array to point to the correct colors. The last line here: static SCB_REHV_PAL Stree = { BPP_4 | TYPE_NORMAL, 0x10, 0x20, 0, tree, 0, 0, 0x0100, 0x100, {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef} //pen palette array, change here }; Every number is a pen of its own. 0x is just for telling the compiler that it's a hex number, so 0 is one pen, 1 is one pen, 2 is one pen etc. The palette and the sprite SCB's are good to read up on: https://atarilynxdeveloper.wordpress.com/2012/10/10/programming-tutorial-part-7the-basics-of-sprites/ https://atarilynxdeveloper.wordpress.com/2012/10/14/programming-tutorial-part-8changing-appearances/ At least Aseprite and Gimp can handle pcx files. This post and thread has a lot of info on sp65: If you want to add more sprites into your game, in game.c you need to add: extern unsigned char robot[]; //add a SCB static SCB_REHV_PAL Srobot = { BPP_4 | TYPE_NORMAL, 0x10, 0x20, 0, robot, 0, 0, 0x0100, 0x100, {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef} }; //add coordinates Srobot.vpos = y; Srobot.hpos = x //draw it tgi_sprite(&Srobot); Also you need to add your new sprite/graphic into the object list in the make file: objects= \ game.o \ robot.o \ tree.o My questions never end... I used Gimp to turn the tree into a little guy. I kept the same tree.pcx name. I just opened it in Gimp, edited the image, and then exported as tree.pcx. But "Make" complains now: Error: Error in PCX file `tree.pcx': 770 bytes at end of pixel data Every seen anything like that before? Quote Link to comment Share on other sites More sharing options...
Turbo Laser Lynx Posted August 12, 2020 Share Posted August 12, 2020 I forgot about that, the image mode has to be indexed (can be found under image/mode). Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 13, 2020 Author Share Posted August 13, 2020 1 hour ago, Turbo Laser Lynx said: I forgot about that, the image mode has to be indexed (can be found under image/mode). Hmmmm, "indexed" is turned on in the image/mode menu... Any other ideas? In the meantime, I'll randomly click buttons. ? Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 13, 2020 Author Share Posted August 13, 2020 (edited) 2 hours ago, OldAtAtari said: Hmmmm, "indexed" is turned on in the image/mode menu... Any other ideas? In the meantime, I'll randomly click buttons. ? Ha! Ok, so this works in Windows Gimp, but not in Linux Gimp, for me anyway. Anyway, it's working. Thank you, Turbo Laser Lynx! Edited August 13, 2020 by OldAtAtari 1 Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 13, 2020 Author Share Posted August 13, 2020 (edited) Ok, not my best work. But functional. The dude can walk around. Everything else is stationary. Onwards and upwards. Thanks again, Turbo Laser Lynx! Edited August 13, 2020 by OldAtAtari 2 Quote Link to comment Share on other sites More sharing options...
Turbo Laser Lynx Posted August 13, 2020 Share Posted August 13, 2020 Woohoo! Glad to be of help! It's always the best feeling when you get a sprite-dude walking around the screen on a new retro system. Love that sprite! 1 Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 13, 2020 Author Share Posted August 13, 2020 (edited) 7 hours ago, Turbo Laser Lynx said: Woohoo! Glad to be of help! It's always the best feeling when you get a sprite-dude walking around the screen on a new retro system. Love that sprite! ? Thanks! It was very exciting indeed! Next, I want to make him jump, and I want to make that tree move on its own horizontally across the screen, back and forth, or just scrolling endlessly. I want to see if the sprite dude can jump over, or on to, the tree. And that would pretty much be a game right there. ? Edited August 13, 2020 by OldAtAtari 1 Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 13, 2020 Author Share Posted August 13, 2020 Oh, yes, back to the sprite editing issue. My indexed .PCX wouldn't work in Gimp in Linux. But it works in Gimp in Windows 10. Do any Linux users have a suggestion of how to get Linux Gimp to work, or what Linux drawing program to use instead? Thanks. Quote Link to comment Share on other sites More sharing options...
42bs Posted August 13, 2020 Share Posted August 13, 2020 I use this one. Works also on Linux: https://pulkomandy.tk/projects/GrafX2 1 Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 13, 2020 Author Share Posted August 13, 2020 50 minutes ago, 42bs said: I use this one. Works also on Linux: https://pulkomandy.tk/projects/GrafX2 That program looks amazing! Old-school and wonderful. I can't wait to try it. Thanks! Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 14, 2020 Author Share Posted August 14, 2020 Getting there. Now the boy jumps as the tree moves from right to left. And there's a score that increments each time the boy jumps. There is no collision detection yet. Code, messy with extra pieces and too few comments, but here for documentation. Feel free to pick it apart and criticize it: #include <lynx.h> #include <conio.h> #include <joystick.h> #include <tgi.h> #include <stdlib.h> unsigned char checkInput(void); extern unsigned char reset; void lynx_snd_init (); void lynx_snd_pause (); void lynx_snd_continue (); void __fastcall__ lynx_snd_play (unsigned char channel, unsigned char *music); void lynx_snd_stop (); typedef struct { unsigned char *music0; unsigned char *music1; unsigned char *music2; unsigned char *music3; } song_t; extern song_t musicptr; extern unsigned char tree[]; extern unsigned char odd_dude[]; static SCB_REHV_PAL Stree = { BPP_4 | TYPE_NORMAL, 0x10, 0x20, 0, tree, 0, 0, 0x0100, 0x100, {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef} }; static SCB_REHV_PAL Sodd_dude = { BPP_4 | TYPE_NORMAL, 0x10, 0x20, 0, odd_dude, 0, 0, 0x0100, 0x100, {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef} }; /* ----------------- Road -------------------- */ unsigned char pixel[] = { 3, 0x84, 0, 0 }; static SCB_REHVST_PAL Spixel = { BPP_1 | TYPE_BACKGROUND, 0x30, 0x20, 0, pixel, 50, 50, 0x2800, 0x800, 0x00, 0x100, {0x68} }; void polygon(int x1, int y1, int w1, int x2, int y2, int w2, unsigned char color) { Spixel.hpos = x1; Spixel.vpos = y1; Spixel.hsize = w1 << 8; Spixel.vsize = (y2 - y1 + 1) << 8; Spixel.tilt = (x2 - x1) * 256 / (y2 - y1); Spixel.stretch = (w2 - w1) * 256 / (y2 - y1); Spixel.penpal[0] = color; tgi_sprite(&Spixel); } void drawsegment(int lanes, int x1, int y1, int w1, int x2, int y2, int w2) { int l1; int l2; int r1; int r2; int lanew1; int lanew2; int lanex1; int lanex2; int lane; l1 = w1 >> (lanes + 2); l2 = w2 >> (lanes + 2); r1 = w1 >> (lanes + 1); r2 = w2 >> (lanes + 1); // Draw left yellow rumble line polygon(x1 - w1 - r1 + 1, y1, r1, x2 - w2 - r2 + 1, y2, r2, COLOR_YELLOW); // Draw road polygon(x1 - w1, y1, w1, x2 - w2, y2, w2, COLOR_GREY); lanew1 = w1 * 2 / lanes; lanew2 = w2 * 2 / lanes; lanex1 = x1 - w1 + lanew1; lanex2 = x2 - w2 + lanew2; for (lane = 1; lane < lanes; lanex1 += lanew1, lanex2 += lanew2, lane++) { polygon(lanex1 - l1 / 2, y1, l1, lanex2 - l2 / 2, y2, l2, COLOR_WHITE); } polygon(x1 - 1 + l1 / 2, y1, w1, x2 - 1 + l2 / 2, y2, w2, COLOR_GREY); // Draw right yellow rumble line polygon(x1 + w1, y1, r1, x2 + w2, y2, r2, COLOR_YELLOW); // Draw right cleanup polygon(x1 + w1 + r1 - 1, y1, r1, x2 + w2 + r2 - 1, y2, r2, COLOR_DARKGREY); } void draw_tree (int x, int y, int scale) { Stree.vpos = y; Stree.hpos = x + 0 * 256 / 256; Stree.vsize = 33; Stree.hsize = 33; tgi_sprite(&Stree); // Stree.hpos = x - 110 * 256 / 256; // tgi_sprite(&Stree); } void draw_dude (int dx, int dy, int scale) { Sodd_dude.vpos = dy; Sodd_dude.hpos = dx + 0 * 256 / 256; Sodd_dude.vsize = 35; Sodd_dude.hsize = 35; tgi_sprite(&Sodd_dude); // Sodd_dude.hpos = dx - 110 * 256 / 256; // tgi_sprite(&Sodd_dude); } void drawscreen(int x, int y, int dx, int dy, int turn, int score) { int y2; int scale1, scale2; char textScore[20]; itoa(score, textScore, 10); scale1 = 3 * y + 8; y2 = y + ((20 * scale1) >> 8); scale2 = 3 * y2 + 8; tgi_setcolor(COLOR_DARKGREY); tgi_bar(0, 0, 159, 101); tgi_setcolor(COLOR_YELLOW); tgi_outtextxy(120, 10, textScore); // drawsegment(2, x, y, (80 * scale1) >> 8, x + turn, y2, (80 * scale2) >> 8); draw_tree(x, y, scale2); draw_dude(dx, dy, scale2); } void game() { int x = 160; int dx = 10; int y = 80; int dy = 80; int turn = 0; int jump = 0; int jumpUp = 25; int jumpDown = 25; int score = 0; while (!reset) { // never use while(1). Every loop needs to be halted by the reset event if (!tgi_busy()) { unsigned char joy; // Instead of calling joy_read() directly, use checkInput() defined in resident.c . // It will return the joy state, but will handle pause and reset events too // joy = joy_read(JOY_1); joy = checkInput(); if (JOY_BTN_UP(joy)) { } if (JOY_BTN_DOWN(joy)) { } if (JOY_BTN_RIGHT(joy)) { dx++; if (dx > 150) dx = 150; } if (JOY_BTN_LEFT(joy)) { dx--; if (dx < 10) dx = 10; } if (JOY_BTN_FIRE(joy) && jump == 0) { jump=1; lynx_snd_play(1, musicptr.music3); score++; } if (jump == 1 && jumpUp != 0) { dy = dy - 2; jumpUp--; } if (jump == 1 && jumpUp == 0 && jumpDown != 0) { dy = dy + 2; jumpDown--; } if (jumpDown == 0) { jump = 0; jumpUp = 25; jumpDown = 25; } if (JOY_BTN_FIRE2(joy)) { turn--; } if (x == 0) { x=160; } x--; drawscreen(x, y, dx, dy, turn, score); tgi_updatedisplay(); } } } Quote Link to comment Share on other sites More sharing options...
42bs Posted August 14, 2020 Share Posted August 14, 2020 I suggest to use pre-increment/decrement instead of post. Post action means to save the contents of the variable, then do the action and then pull the original contents back. Modern C compilers do not care, but (new)cc65 might produce worse code. Also, use char or unsigned char if the value fits into 8 bits. 1 Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 14, 2020 Author Share Posted August 14, 2020 34 minutes ago, 42bs said: I suggest to use pre-increment/decrement instead of post. Post action means to save the contents of the variable, then do the action and then pull the original contents back. Modern C compilers do not care, but (new)cc65 might produce worse code. Also, use char or unsigned char if the value fits into 8 bits. Excellent thoughts, 42bs. Thank you! Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 14, 2020 Author Share Posted August 14, 2020 51 minutes ago, 42bs said: I suggest to use pre-increment/decrement instead of post. Post action means to save the contents of the variable, then do the action and then pull the original contents back. Modern C compilers do not care, but (new)cc65 might produce worse code. Also, use char or unsigned char if the value fits into 8 bits. Is the following a proper pre-increment, as opposed to what I did before? Is it as simple as using ++x instead of x++? Thanks. if (JOY_BTN_FIRE(joy) && jump == 0) { jump=1; lynx_snd_play(1, musicptr.music3); ++score; } Quote Link to comment Share on other sites More sharing options...
42bs Posted August 14, 2020 Share Posted August 14, 2020 Just now, OldAtAtari said: Is the following a proper pre-increment, as opposed to what I did before? Is it as simple as using ++x instead of x++? Thanks. if (JOY_BTN_FIRE(joy) && jump == 0) { jump=1; lynx_snd_play(1, musicptr.music3); ++score; } Right. You can check in the assembly. 1 Quote Link to comment Share on other sites More sharing options...
+karri Posted August 14, 2020 Share Posted August 14, 2020 36 minutes ago, 42bs said: Right. You can check in the assembly. If you run my template just go to the directory where your C-code is. If your file is game.c you can type: make game.s This makes a human readable assembly listing that helps you see how C is turned into asm. In @42bs example you would probably get: ; ; if (JOY_BTN_FIRE(joy) && jump == 0) { ; lda _joy_masks+4 and _joy pha pla beq L0287 lda _jump beq L0288 L0287: rts ; ; jump=1; ; L0288: lda #$01 sta _jump ; ; lynx_snd_play(1, musicptr.music3); ; jsr pusha lda _musicptr+6 ldx _musicptr+6+1 jsr _lynx_snd_play ; ; ++score; ; inc _score ; ; } ; rts While post-incrementing would waste a few bytes more: ; ; score++; ; lda _score ina sta _score ; ; } ; rts 1 Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 14, 2020 Author Share Posted August 14, 2020 23 minutes ago, karri said: If you run my template just go to the directory where your C-code is. If your file is game.c you can type: make game.s This makes a human readable assembly listing that helps you see how C is turned into asm. In @42bs example you would probably get: ; ; if (JOY_BTN_FIRE(joy) && jump == 0) { ; lda _joy_masks+4 and _joy pha pla beq L0287 lda _jump beq L0288 L0287: rts ; ; jump=1; ; L0288: lda #$01 sta _jump ; ; lynx_snd_play(1, musicptr.music3); ; jsr pusha lda _musicptr+6 ldx _musicptr+6+1 jsr _lynx_snd_play ; ; ++score; ; inc _score ; ; } ; rts While post-incrementing would waste a few bytes more: ; ; score++; ; lda _score ina sta _score ; ; } ; rts I love that! I didn't know you could do that. I still want to learn assembly, so it will be great to see how it translates. Thank you! Quote Link to comment Share on other sites More sharing options...
+karri Posted August 14, 2020 Share Posted August 14, 2020 15 minutes ago, OldAtAtari said: I love that! I didn't know you could do that. I still want to learn assembly, so it will be great to see how it translates. Thank you! You can also edit the game.s and optimize it by hand. If it exists the compiler will use your edited version. I often revert to the asm file when I am unhappy with performance of my game. So reading it is a greate tool for learning. 1 Quote Link to comment Share on other sites More sharing options...
OldAtAtari Posted August 14, 2020 Author Share Posted August 14, 2020 1 hour ago, karri said: You can also edit the game.s and optimize it by hand. If it exists the compiler will use your edited version. I often revert to the asm file when I am unhappy with performance of my game. So reading it is a greate tool for learning. Thanks for putting this template together, Karri. I'm learning a lot from it. 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.