First version

This commit is contained in:
Paulo Garcia 2016-01-24 15:00:52 -05:00
commit 24cfdc0b6a
4 changed files with 499 additions and 0 deletions

94
Makefile Normal file
View File

@ -0,0 +1,94 @@
#
# Makefile
# Apple2BuildPipelineSample
#
# Part of a sample build pipeline for Apple II software development
#
# Created by Quinn Dunki on 8/15/14.
# One Girl, One Laptop Productions
# http://www.quinndunki.com
# http://www.quinndunki.com/blondihacks
#
include make/head.mk
# Customize this file to control what gets built, what machines to
# target, where in memory to put it, etc.
# The name of your system or binary file to build goes here:
PGM=gr2
# Set the config you are building for. See these pages for details:
# http://cc65.github.io/cc65/doc/apple2.html#s4
# http://cc65.github.io/cc65/doc/apple2enh.html#s4
#
# Uncomment the one you want below (the first one is the default):
# MACHINE = apple2
# MACHINE = apple2-dos33
# MACHINE = apple2-system
# MACHINE = apple2-loader
# MACHINE = apple2-reboot
# MACHINE = apple2enh
# MACHINE = apple2enh-dos33
# MACHINE = apple2enh-system
# MACHINE = apple2enh-loader
# MACHINE = apple2enh-reboot
# Uncomment and set this to your starting address in Apple II memory
# if necessary:
# START_ADDR = 6000
# Set the default CPU to assemble for. You can change this in the
# body of a .s file using control commands like ".PC02". Uncomment
# the one you want below (the first one is the default):
# CPU = 6502
# CPU = 65SC02
# CPU = 65C02
# CPU = 65816
# Note: You can assemble for 65816 in 16-bit mode but the C compiler
# will only produce 8-bit code.
# Any *.c files in your main project directory will automatically be
# built. But, if you have subdirectories with C files in them, you
# should add them to the list of C_SRCS to build. Do that by
# uncommenting the following line and changing "someSubDir" to match
# the subdirectory you have created. Add multiple lines like this
# for each subdirectory:
# C_SRCS += $(wildcard someSubDir/*.c)
# Any *.s files in your main project directory will automatically be
# built. But, if you have subdirectories with assembly files in them,
# you should add them to the list of ASM_SRCS to build. Do that by
# uncommenting the following line and changing "someSubDir" to match
# the subdirectory you have created. Add multiple lines like this
# for each subdirectory:
# ASM_SRCS += $(wildcard someSubDir/*.s)
# If you have a non-standard cc65 install, you may need to change
# some of these. Uncomment the following line and change it to the
# correct path to CC65_HOME if the default is not correct:
# export CC65_HOME := /usr/local/lib/cc65
#
# If the path to the cc65 binaries is not correct, uncomment this
# line and change it:
CC65_BIN = /usr/local/bin
# If you want to add arguments to the compile commandline, add them
# to this variable:
# CFLAGS += -Os
# If you want to add arguments to the assembly commandline, add them
# to this variable:
# ASMFLAGS += -g
# If you want to add arguments to the link commandline, add them to
# this variable:
# LDFLAGS += -v
# If you have java installed in a non-standard location, you can set
# the path to it by uncommenting the following line:
# export JAVA=/usr/bin/java
# Do not change anything else below here...
include make/tail.mk

235
a2graph.c Normal file
View File

@ -0,0 +1,235 @@
//
// a2graph.c
// test
//
// Created by Paulo Garcia on 2015-11-26.
// Copyright © 2015 Paulo Garcia. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <peekpoke.h>
#include "a2graph.h"
void gr_setmode(unsigned int CRTMODE)
{
/* note: the following constants must be hex values
or cc65 complains that the constant is a long */
switch(CRTMODE)
{
case MODE_TEXT_PAGE_1:
POKE(0xc051,0); /* text */
POKE(0xc054,0); /* page 1 */
break;
case MODE_TEXT_PAGE_2:
POKE(0xc051,0); /* text */
POKE(0xc055,0); /* page 2 */
break;
case MODE_LORES_TEXT_PAGE_1:
POKE(0xc056,0); /* lo res */
POKE(0xc054,0); /* page 1 */
POKE(0xc050,0); /* set graphics */
break;
case MODE_LORES_FULL_PAGE_1:
POKE(0xc056,0); /* lo res */
POKE(0xc054,0); /* page 1 */
POKE(0xc050,0); /* set graphics */
POKE(0xc052,0); /* full graphics */
break;
case MODE_LORES_FULL_PAGE_2:
POKE(0xc056,0); /* lo res */
POKE(0xc055,0); /* page 2 */
POKE(0xc050,0); /* set graphics */
POKE(0xc052,0); /* full graphics */
break;
case MODE_HIRES_FULL_PAGE_2:
POKE(0xc057,0); /* hi res */
POKE(0xc055,0); /* page 2 */
POKE(0xc050,0); /* set graphics */
POKE(0xc052,0); /* full graphics */
break;
case MODE_HIRES_FULL_PAGE_1:
default:
POKE(0xc057,0); /* hi res */
POKE(0xc054,0); /* page 1 */
POKE(0xc050,0); /* set graphics */
POKE(0xc052,0); /* full graphics */
}
}
void gr_fill(int page, unsigned ch)
{
int idx;
unsigned fillcolor = ch * 0x11;
for (idx = 0; idx < 8; idx++) {
memset ((char *)textbase[idx]+page, fillcolor, 0x78);
}
}
void gr_hlin(unsigned int x1, unsigned int x2, unsigned int y, colors_t color, int page)
{
int length;
int y1, pos;
unsigned char c2 = (unsigned char ) ((int)color & 15);
unsigned char *crt, c1;
if (x2<x1) {
//swap
pos=x2;
x2=x1;
x1=pos;
}
length = x2-x1;
y1 = y >> 1;
x1 = x1 + page;
if (y&1) {
/* odd rows in high nibble mask value to preserve low nibble */
c1 = 0xf;
c2 = c2 << 0x4;
} else {
/* even rows in low nibble mask value to preserve high nibble */
c1 = 0xf0;
}
crt = malloc(length);
// Copy video memory first
memcpy((void *)crt, (void *)(textbase[y1]+x1), length);
// Apply color to all positions
if (crt) {
for (pos=0;pos<length;pos++) {
*(crt+pos) = (*(crt+pos) & c1) | c2;
}
// Copy it back to video position
memcpy((void *)(textbase[y1]+x1), (void *)crt, length);
free(crt);
}
}
void gr_vlin(unsigned int y1, unsigned int y2, unsigned int x, colors_t color, int page)
{
int pos;
unsigned char c2;
if (y2<y1) {
//swap
pos=y2;
y2=y1;
y1=pos;
}
x = x + page;
c2 = (unsigned char ) ((int)color & 15);
for (pos=y1;pos<=y2;pos++) {
gr_plot1(x,pos,c2);
}
}
void gr_plot(int x,int y,colors_t color,int page)
{
unsigned char c2;
x = x + page;
c2 = (unsigned char ) ((int)color & 15);
gr_plot1(x,y,c2);
}
/*
Internal plot - don't call directly
x already account for page, and color is calculated too
*/
void gr_plot1(int x, int y, unsigned char c2)
{
unsigned char *crt, c1;
int y1 = y >> 1;
int *pos = textbase;
if (y&1) {
/* odd rows in high nibble */
/* mask value to preserve low nibble */
c1 = 0xf;
c2 = c2 << 0x4;
} else {
/* even rows in low nibble */
/* mask value to preserve high nibble */
c1 = 0xf0;
}
crt = (unsigned char *)(*(pos+y1))+x;
*crt = (*crt & c1) | c2;
}
int gr_khit()
{
unsigned char *KP = (unsigned char*)0xC000;
unsigned char c;
/* read the keyboard buffer */
/* and return 0 if no character is waiting */
c = KP[0];
if(c<128)return 0;
return (int)c;
}
void gr_clearkey()
{
/* return the last key press */
unsigned char *KEYPRESS = (unsigned char*)0xC000;
/* clear the last key press */
unsigned char *KEYCLEAR = (unsigned char*)0xC010;
/* clear stragglers from the keyboard buffer */
while(KEYPRESS[0] > 127)KEYCLEAR[0]=0;
}
void gr_sprite(unsigned int x, unsigned int y, unsigned int w, unsigned int h, int page, unsigned char* cl)
{
int x1,y1;
unsigned char ci = 0;
unsigned char *cl1 = cl;
int plt =0; // 0 = with mask - 1 = full byte
x = x + page;
y1 = y;
do {
plt=0;
if (!(y&1) && (y1<(y+h-1))) {
// even row
plt=1; //doulbe
}
if (plt) {
y1++;
} else {
// plot single line
for (x1=x;x1<(x+w);x1++) {
gr_plot1(x1,y1,*(cl1+ci));
ci++;
}
}
y1++;
} while (y1<(y+h));
}

87
a2graph.h Normal file
View File

@ -0,0 +1,87 @@
//
// a2graph.h
// test
//
// Created by Paulo Garcia on 2015-11-26.
// Copyright © 2015 Paulo Garcia. All rights reserved.
//
#ifndef a2graph_h
#define a2graph_h
#define PAGE_1 0
#define PAGE_2 1024
#define MODE_TEXT_PAGE_1 0x0
#define MODE_TEXT_PAGE_2 0x1
#define MODE_LORES_FULL_PAGE_1 0x2
#define MODE_LORES_FULL_PAGE_2 0x3
#define MODE_HIRES_FULL_PAGE_1 0x4
#define MODE_HIRES_FULL_PAGE_2 0x5
#define MODE_LORES_TEXT_PAGE_1 0x6
/* Colors */
typedef enum {
BLACK = 0,
MAGENTA,
DARK_BLUE,
PURPLE,
DARK_GREEN,
GREY,
MEDIUM_BLUE,
LIGHT_BLUE,
BROWN,
ORANGE,
GREY_2,
PINK,
GREEN,
YELLOW,
AQUA,
WHITE
} colors_t;
/* base addresses for primary text page */
/* also the base addresses for the 48 scanline pairs */
/* for lores graphics mode 40 x 48 x 16 colors */
int textbase[24]={
0x0400,
0x0480,
0x0500,
0x0580,
0x0600,
0x0680,
0x0700,
0x0780,
0x0428,
0x04A8,
0x0528,
0x05A8,
0x0628,
0x06A8,
0x0728,
0x07A8,
0x0450,
0x04D0,
0x0550,
0x05D0,
0x0650,
0x06D0,
0x0750,
0x07D0
};
/* Function Prototypes */
extern void gr_setmode(unsigned int CRTMODE);
extern void gr_plot(int x,int y, colors_t color,int page);
extern void gr_hlin(unsigned int x1, unsigned int x2, unsigned int y, colors_t color, int page);
extern void gr_vlin(unsigned int y1, unsigned int y2, unsigned int x, colors_t color, int page);
extern void gr_fill(int page, unsigned ch);
extern int gr_khit();
extern void gr_clearkey();
extern void gr_sprite(unsigned int x, unsigned int y, unsigned int w, unsigned int h, int page, unsigned char *);
/* private functions */
void gr_plot1(int x, int y, unsigned char c2);
#endif /* a2graph_h */

83
main.c Normal file
View File

@ -0,0 +1,83 @@
/*
* main.c
* gr2
*
* Created by Paulo Garcia on 2015-12-16.
* Copyright (c) 2015 Paulo Garcia. All rights reserved.
*
*/
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <peekpoke.h>
#include "a2graph.h"
unsigned char sprite[36] = { BLACK, BLACK, BLACK, MAGENTA, MAGENTA, BLACK,
BLACK, BLACK, BLACK, MAGENTA, BLACK, BLACK,
BLACK, WHITE, BLACK, MAGENTA, BLACK, BLACK,
WHITE, WHITE, WHITE, WHITE, WHITE, WHITE,
BLACK, BLACK, BLACK, MAGENTA, BLACK, BLACK,
BLACK, BLACK, BLACK, MAGENTA, MAGENTA, BLACK};
int my_test()
{
int page=0;
int x,y;
//fill_screen(PAGE_1,0);
for (x=5;x<35;x++) {
for(y=10;y<36;y+=2) {
gr_plot(x, y, DARK_BLUE, page);
}
}
for (y=10;y<35;y++) {
for(x=5;x<36;x+=2) {
gr_plot(x, y, YELLOW, page);
}
}
}
int main(void)
{
int i,j;
gr_clearkey();
printf("Press any key to start...");
while(gr_khit()==0);
gr_setmode(MODE_LORES_TEXT_PAGE_1);
gr_fill(PAGE_1, BLACK);
while(gr_khit()==0);
my_test();
j=0;
for(i=0;i<48;i++) {
gr_hlin(39,0,i,j,PAGE_1);
j++;
if (j==16) j=0;
}
j=0;
for(i=0;i<40;i++) {
gr_vlin(47,0,i,j,PAGE_1);
j++;
if (j==16) j=0;
}
gr_clearkey();
while(gr_khit()==0);
for (i=33;i>0;i--) {
gr_sprite(i, 10, 6, 6, PAGE_1, sprite);
}
gr_clearkey();
while(gr_khit()==0);
for (i=0;i<16;i++) {
gr_fill(0, i);
}
return 0;
}