Jump to content



1

Atari Programming in CC65


9 replies to this topic

#1 rchennau OFFLINE  

rchennau

    Chopper Commander

  • 173 posts
  • Location:California

Posted Fri Jul 29, 2011 9:01 PM

I am stil hacking away... I've searched far and wide for CC65 examples that were very basic. I found some but I decided to write one as I go. Here is the result.


#include <atari.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <conio.h>  // standard cc65 for 'console' based applications


/***************************************************************
* #define SAVMSC is a cc65 MACRO for the Atari 8-BIT platform. *
* SAVMSC points to hardware register at memory location 88.    *
* refer to [url="http://www.atariarchives.org/mapping/memorymap.php"]http://www.atariarchives.org/mapping/memorymap.php[/url]  *
*                                                              *
***************************************************************/
The following define for SAVMSC is to assign a pointer
#define SAVMSC *(unsigned int *) 88 // pointer to atari hardware register that holds the screen position address

/***************************************************************
* __fastcall__ is a cc65 preprocessor command to place the     *
* the variable referenced at the top of the memory heap thus   *
* enabling faster access by the cpu                            *
***************************************************************/
void __fastcall__ statusLine(int x, int y, int capture);  // debug line to display function variables.  Should convert to a constructor


int __fastcall__ getCalc(int oper, int x, int y, int z);  // calculate the operation requested


/*************************************************************
* This program is built upon exercise  2.19 found in How to  *
* program C by Dietel / Dietel.         It has been addapted *
* to work on the Atari 8-Bit platform.                       *
*                                                            *
* Things to do:                                              *
    1. Call to statusLine should be done during a VLI        *
    2. Convert statusLine to a structure to handle more cases*
    3. Use TGI (Having probelms loading driver)              *
*************************************************************/
void main(void)
{
    int sum, average, product, smallest, largest;   // create five operators for math calculations
    int i1, i2, i3;                                 // create three integers for to be used by the five operators.
    char c;                                         // character c is need to check for EOF / user exit

    cursor(1);                                      // turn the atari cursor off

    gotox(0);                                       // position the cursor on X line 0
    printf("Enter three numbers: ");
    cscanf("%d", &i1);                              // need to add test for out of range entries
    statusLine(wherex(),wherey(),i1);               // debug function to determine where cursor is and the value of i1

    gotoxy(27,0);                                   // Put cursor on Line X 0 and Y 27 as it was moved by statusLine
    cscanf("%d", &i2);
    statusLine(wherex(),wherey(),i2);

    gotoxy(30,0);
    cscanf("%d", &i3);
    statusLine(wherex(),wherey(),i3);

    gotoxy(10,6);                                   // Move cursor to center of screen and display results
    sum = getCalc(1,i1,i2,i3);
    average = getCalc(2,i1,i2,i3);
    product = getCalc(3,i1,i2,i3);
    smallest = getCalc(4,i1,i2,i3);
    largest = getCalc(5,i1,i2,i3);

    printf("The sum = %d\n", sum);
    gotox(10);
    printf("The average = %d\n", average);
    gotox(10);
    printf("The product = %d\n", product);
    gotox(10);
    printf("The smallest = %d\n", smallest);
    gotox(10);
    printf("The largest = %d\n", largest);

    cursor(0);
    gotox(10);
    printf("Press Enter to exit");


    while (1)
    {
        gotoxy(20,11);
        statusLine(wherex(),wherey(),c=cgetc());
        if (c=='\n' || c==EOF)
        {

            break;
        }
    }

    return;
}

int __fastcall__ getCalc(int operand, int x, int y, int z)
{

    switch (operand)
    {
        case 1: // calculate the sum
            operand = x + y + z;
            return operand;
        case 2: // calculate the average
            operand = (x + y + z) / 3;
            return operand;

        case 3: // calculate the product
            operand = x*y*z;
            return operand;

        case 4: // calculate the smallest
            if (x <= y && y <= z)
                return x;
            else if (x >= y && y <= z)
                return y;
            else (x >= y && x >= z);
                return z;

        case 5: // calculate the largest
            if (x > y && x > z)
                return x;
            else if (y > x && y > z)
                return y;
            else (z > x && z > y);
                return z;

        default: // no calculation
            return EOF;
    }
}

void __fastcall__ statusLine(int x,int y, int capture)
{
    gotoxy(0,20);
    printf("You entered: %d\n", capture);
    printf("Position x = %d\n" ,x);
    printf("Position y = %d ",y);

    return;
}




#2 rchennau OFFLINE  

rchennau

    Chopper Commander

  • 173 posts
  • Location:California

Posted Sun Jul 31, 2011 11:35 AM

Another good CC65 example may be found here: Google Translator to AtariOnline.pl


1. Araknoid (brick breaker) : Google Translator to AtariOnline.pl

[b][font="Courier New"]#include < atari.h > 
#include < stdio.h > 
#include < peekpoke.h > 
#include < joystick.h > 

#define SCREEN_SIZE 40 
#define PADDLE_SIZE 6 
#define PADDLE_Y 20 

#define COLOR1 0x2C5 
#define COLOR2 0x2C6 
#define CDTMV3 0x21C 
#define RANDOM PEEK(0xD20A) 
// 29 is '=' character in ANTIC character set 
#define BRICK 29 
#define PADDLE 213 
#define BALL 84 

// Global variables 

unsigned char *video_ptr; 
unsigned char total_bricks; 
unsigned char paddle_pos=0; 
unsigned char ball_x,ball_y; 
signed char ball_dx,ball_dy; 
unsigned char lives=6; 

// Joystick 

extern char joy_driver; 
unsigned char joy; 

// Helper macros 
#define set_char(x,y,a) video_ptr[(x)+(y)*SCREEN_SIZE]=(a); 
#define get_char(x,y) video_ptr[(x)+(y)*SCREEN_SIZE] 

void set_colors() 
{ 
POKE(COLOR1,0xFF); // font color 
POKE(COLOR2,0); // background color 
} 

void draw_bricks() 
{ 
for (total_bricks=0;total_bricks < 4*SCREEN_SIZE;total_bricks++) 
video_ptr[total_bricks]=BRICK; 
} 

void draw_paddle() 
{ 
register unsigned char s; 
for (s=0;s < PADDLE_SIZE;++s) 
set_char(s+paddle_pos,PADDLE_Y,PADDLE); 
set_char(paddle_pos-1,PADDLE_Y,0); 
set_char(paddle_pos+PADDLE_SIZE,PADDLE_Y,0); 
} 

void win() 
{ 
for(;;) 
puts("Win!"); 
} 

void next_life() 
{ 
unsigned char i; 
--lives; 
if (lives==0) 
{ 
for(;;) 
puts("Game over"); 
} 
// show available balls 
for (i=0;i < lives;++i) 
set_char(i,PADDLE_Y+2,BALL); 
set_char(i,PADDLE_Y+2,0); 

// set_ball_position 

ball_x=paddle_pos+3; 
ball_y=18; 
ball_dy=-1; 
ball_dx=RANDOM%2?1:-1; 
} 


void move_ball() 
{ 
// remove ball 
set_char(ball_x,ball_y,0); 

// bounce ball on the top of the screen 
if (ball_y==0) 
ball_dy=1; 
else if (ball_y==PADDLE_Y-1) // ball on the line of the paddle 
{ 
// hit the paddle? 
if (ball_x > =paddle_pos && ball_x < paddle_pos+PADDLE_SIZE) 
ball_dy=-1; 
else // ball missed the paddle 
{ 
next_life(); 
return; 
} 
} 

// bounce the ball on the borders 
if (ball_x==0) 
ball_dx=1; 
else if (ball_x==SCREEN_SIZE-1) 
ball_dx=-1; 

// change the ball position 
ball_x+=ball_dx; 
ball_y+=ball_dy; 

// ball hit the brick 
if (get_char(ball_x,ball_y)==BRICK) 
{ 
if (--total_bricks==0) 
win(); 
ball_dy*=-1; 
} 

// draw ball 
set_char(ball_x,ball_y,BALL); 
} 

int main(void) 
{ 
joy_install(&joy_driver); 
_graphics(0); 
set_colors(); 

// get screen memory pointer 
video_ptr=(unsigned char*)(PEEKW( PEEKW(560)+4 )); 
draw_bricks(); 

paddle_pos=(SCREEN_SIZE-PADDLE_SIZE)/2; 
next_life(); 

for(;;) 
{ 
// wait a moment and read the joystick state after that 
POKE(CDTMV3,3); 
while(PEEK(CDTMV3)); 
POKE(0x4D,0); // Disable Attract mode 

joy=joy_read(JOY_1); 
if (JOY_BTN_LEFT(joy)) 
{ 
if (paddle_pos > 0) 
--paddle_pos; 
} 
if (JOY_BTN_RIGHT(joy)) 
{ 
if (paddle_pos < SCREEN_SIZE-PADDLE_SIZE) 
++paddle_pos; 
} 
draw_paddle(); 
move_ball(); 
} 
return 0; 
}[/font][/b] 


#3 ilmenit OFFLINE  

ilmenit

    Chopper Commander

  • 136 posts

Posted Mon Aug 1, 2011 4:38 AM

Here is a topic with many examples of CC65 codes:
http://atarionline.p...6&page=1#Item_0

3 parts of the programming tutorial:
http://atarionline.p...at=1&ct=nowinki
http://atarionline.p...at=1&ct=nowinki
http://atarionline.p...action=showfull

#4 funkheld OFFLINE  

funkheld

    Space Invader

  • 26 posts

Posted Thu Jan 19, 2012 9:01 AM

he, can you PM in the GRAFIK 7 or GRAFIK 23 with the CC65 ??? :?

thanks

#5 Shawn Jefferson OFFLINE  

Shawn Jefferson

    Stargunner

  • 1,538 posts
  • Location:Victoria, Canada

Posted Fri Jan 20, 2012 12:18 AM

There are no built in functions in cc65 for doing PMG, but you can get to the hardware easily with C.

BTW the explanation of fastcall in the code posted above is wrong. fastcall does something different in C code than in assembly code in the cc65 toolchain. Using fastcall in C will save some bytes but not really speed up execution. What it does, used in C code like shown in the code posted above, is move the "jsr pushax" into the function being called, rather than being done in the caller (saving bytes in your program, multiplied by how many times you are calling it.) Still a good thing to do though.

Better is to rewrite the code in assembly, and use fastcall there, which will expect the last argument to the function to be passed via the A and X register. That does speed up your programs...

Edited by Shawn Jefferson, Fri Jan 20, 2012 12:41 AM.


#6 flashjazzcat OFFLINE  

flashjazzcat

    Quadrunner

  • 5,408 posts
  • Jumping through hOOPs...
  • Location:United Kingdom

Posted Fri Jan 20, 2012 2:22 AM

Are the sources for the A8 library available anywhere?

#7 Irgendwer OFFLINE  

Irgendwer

    Dragonstomper

  • 566 posts
  • Location:Germany

Posted Fri Jan 20, 2012 3:36 AM

View Postflashjazzcat, on Fri Jan 20, 2012 2:22 AM, said:

Are the sources for the A8 library available anywhere?

All sources, for all components are available at cc65.org.

#8 flashjazzcat OFFLINE  

flashjazzcat

    Quadrunner

  • 5,408 posts
  • Jumping through hOOPs...
  • Location:United Kingdom

Posted Fri Jan 20, 2012 3:51 AM

Ah - got it - thanks. Don't know how I missed them! :)

#9 funkheld OFFLINE  

funkheld

    Space Invader

  • 26 posts

Posted Fri Jan 20, 2012 1:15 PM

sorry, I meant grafik7 and pm or pm and grafik7 and text.
have here with this xforth.

goes the same with the CC65?

Attached Thumbnails

  • grafik7-pm.jpg
  • grafik7-pm-text.jpg

Edited by funkheld, Fri Jan 20, 2012 1:15 PM.


#10 Shawn Jefferson OFFLINE  

Shawn Jefferson

    Stargunner

  • 1,538 posts
  • Location:Victoria, Canada

Posted Sat Jan 21, 2012 2:58 PM

There is a command to change graphics modes, like the BASIC command GRAPHICS, but no drawing primitives. There is a cross-platform library callged TGI (Tiny Graphics Interface) that has some limited graphics mode support and graphics primitives like plot, line, etc...

You could use other people's work and re-use it. There are some examples of graphics and PM manipulation with CC65 around the forum.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users