Jump to content
Sign in to follow this  
damosan

cc65: Graphics 8 pixel plotters...

Recommended Posts

Posted (edited)

Attached is a link to a graphics mode 8 pixel plotting test harness.  It includes all sorts of ways to plot a single pixel on a graphics 8 screen from the slowest (~13 pixels / jiffy)  to the fastest I've managed (~332 pixels / jiffy) on an NTSC machine (on a PAL machine the counts are ~17 / ~427 pixels per jiffy).

 

The various methods are all general purpose routines meant to plot a pixel at a given location.  There are two "cheat" tests that are optimized for the use case of filling a screen.  The project also serves as an example of interfacing CC65 with external assembly code, how to pass variables using the zeropage, and how (in some cases) not to plot pixels.  It also includes a routine to plot text on a gr8 screen.

 

This little project was made possible by all the code folks have published over the years as well as the conversations I've had on AtariAge.

 

Next step is to add sprites...

 

https://github.com/damosan314/gr8

gfx.xex

Edited by damosan
Added binary.
  • Like 2

Share this post


Link to post
Share on other sites
$ cl65 -Osir -C gfx.cfg -t atari gfx.c gr8sprite.s -o gfx.xex
gr8.h(4): Error: Include file `common.h' not found
gfx.c(122): Error: Undefined symbol: `OS'
gfx.c(122): Error: Struct expected
gfx.c(122): Error: Struct/union has no field named `rtclok'
gfx.c(122): Error: Subscripted value is neither array nor pointer
gfx.c(122): Error: Struct expected
gfx.c(122): Error: Struct/union has no field named `rtclok'
gfx.c(122): Error: Subscripted value is neither array nor pointer
gfx.c(152): Error: Undefined symbol: `OS'
gfx.c(152): Error: Struct expected
gfx.c(152): Error: Struct/union has no field named `rtclok'
gfx.c(152): Fatal: Too many errors

Am I missing something?

Share this post


Link to post
Share on other sites
32 minutes ago, atarixle said:

Am I missing something?

 

Yes...  a header named common.h.

 

I forgot to add it to github - it's there now.  Sorry about that.

Share this post


Link to post
Share on other sites
1 hour ago, atarixle said:

gfx.c(122): Error: Undefined symbol: `OS' gfx.c(122): Error: Struct expected

 

@damosan already added the missing header.

The problems with the missing "OS"-symbol are reasoned by a more than 3 year old cc65 version.

See also here:

 

  • Like 1

Share this post


Link to post
Share on other sites
Posted (edited)
10 hours ago, damosan said:

The various methods are all general purpose routines meant to plot a pixel at a given location. 

Looking good, the only thing to optimize would be rewriting to ASM function plot_pixel_lookups_zp4 (with 2 lookup tables for X under and over 256).

Btw, the tables you can generate shorter:

.align  256

yindexlo:    .res 256
yindexhi:    .res 256

bitmask_table:
.repeat 32
    .byte $80, $40, $20, $10, $08, $04, $02, $01
.endrep

byteoffset_table:
.repeat 256,i
    .byte i/8
.endrep

byteoffset256_table:
.repeat 256,i
    .byte 4+i/8
.endrep

also instead of using hardcoded addresses on ZP you could define them with pragmas https://cc65.github.io/doc/cc65.html#ss7.20

Edited by ilmenit

Share this post


Link to post
Share on other sites

Yeah - I had aligns in there initially but the linker would complain about the code segment not being aligned.  It'd still work of course - I need to modify the linker config to align the data segment to a page.  I made some changes to the assembly (using res) but kept the other tables as they were as someone new to 6502 assembly and ca65 may be confused with the repeat/endrep stuff.

 

I'm thinking of new ways to plot pixels where the LDA/ORA/STA sequence will work with absolute addresses instead of lookups.  It's going to take a lot of space of course.

 

 

 

Share this post


Link to post
Share on other sites
2 minutes ago, damosan said:

I'm thinking of new ways to plot pixels where the LDA/ORA/STA sequence will work with absolute addresses instead of lookups.  It's going to take a lot of space of course.

You can also place screen memory at selected/aligned locations to squeeze some cycles with the code. If speed is the most critical then even place each screen line at the beginning of a page (like in some demoscene effects).

Share this post


Link to post
Share on other sites

I did something like this in modes 9 and 11 just as a programming exercise to see how quick cc65 was.

 

This is a little demo of the result, plots 1000 point, draws 16 lines and draws 16 boxes.

 

I'm about 90% through a re-write in assembler

art.xex art1.xex

  • Like 1

Share this post


Link to post
Share on other sites

Well, now if you get these errors (like I did):

 

$ cl65 -Osir -C gfx.cfg -t atari gfx.c gr8sprite.s -o gfx.xex
common.h(4): Error: Multiple definition for 'word'
common.h(7): Error: Multiple definition for 'byte'

just remove the definition in common.h which now looks like this:

#ifndef __COMMON_H
#define __COMMON_H

//typedef unsigned int  word;
typedef unsigned int  u16;
typedef int           s16;
//typedef unsigned char byte;
typedef unsigned char u8;
typedef signed char   sbyte;
typedef signed char   s8;

#endif

... and wow that is going freaking fast at the end!

Share this post


Link to post
Share on other sites
Posted (edited)

You can get rid of your modified custom linker cfg by compiling with

cl65 -Osir -t atari -Wl -D__STACKSIZE__=0x400 -Wl -D__RESERVED_MEMORY__=0x2000 gfx.c gr8sprite.s -o gfx.xex

Edited by sanny

Share this post


Link to post
Share on other sites
5 hours ago, atarixle said:

Well, now if you get these errors (like I did):

 

$ cl65 -Osir -C gfx.cfg -t atari gfx.c gr8sprite.s -o gfx.xex
common.h(4): Error: Multiple definition for 'word'
common.h(7): Error: Multiple definition for 'byte'

 

 

What version of the compiler are you using?  I'm running 2.19.

Share this post


Link to post
Share on other sites

I run a freshly downloaded sources for version 2.19 from GitHub, still reporting 2.18, built on macOS Monterey.

Share this post


Link to post
Share on other sites
6 hours ago, atarixle said:

I run a freshly downloaded sources for version 2.19 from GitHub, still reporting 2.18, built on macOS Monterey.

Huh.  They must of added definitions of byte/word in that release...

Share this post


Link to post
Share on other sites
31 minutes ago, damosan said:

Huh.  They must of added definitions of byte/word in that release..

I'm running 2.19 on Windoze and "word" & "byte" are not defined, I get errors, if I define them it compiles 

Share this post


Link to post
Share on other sites

ok, one last try (I mean it just worked with my modifications, but it's worth the try that late in the evening). I downloaded the cc65-master.zip and am compiling it right now.

Let's see what version it attempts to produce and if it works like your versions do.

 

(Hell, I love it! Compiling without ./configure, without errors, even without warnings, on every system from PowerPC Leopard, over 32 bit Intel Linux, up to 64 bit macOS Monterey. But it needs a PREFIX to be added manually - something is always as we say in german.)

 

ok, now it reported the 2.19 as the current version.

 

....aaaaaaaand:

it compiles, no matter if I comment out the definition for word and byte. strange.

 

$ vim common.h 
removing the definitions of word and byte
$ cl65 -Osir -C gfx.cfg -t atari gfx.c gr8sprite.s -o gfx.xex
$ vim common.h 
adding the definitions of word and byte 
$ cl65 -Osir -C gfx.cfg -t atari gfx.c gr8sprite.s -o gfx.xex
$ 

No errors on both compiles. Do they both work? ...

(let pass some time ...)

Both compiles work.

Share this post


Link to post
Share on other sites
Posted (edited)

WHAT the heck!

 

cc65 2.19 from the master breaks all my other projects. No way, that I keep that installed!

Edited by atarixle

Share this post


Link to post
Share on other sites
1 hour ago, atarixle said:

cc65 2.19 from the master breaks all my other projects. No way, that I keep that installed!

 

Please explain resp. give examples.

Share this post


Link to post
Share on other sites
Posted (edited)

Well may be I over-reacted.

I more meant that as a funny, more a sarcastic statement.

I really guess I either write bad styled C code, or I write C style of an older ISO standard of code.

Actually only one - the largest project - is breaking. All others compile with warnings that never appeared before, but run even faster at the end 😳👍😃

cc65 2.18 lets me use text as an unsigned char, and it casts it without any error or warning. 2.19 now brings tons of warnings that casting between char* and unsigned char* does something with the signess. But it still works somehow.

The project that breaks uses a struct with self referencing pointers (e.g. *next, *prev for chains). This compiles in 2.18 but horrorbly breaks in errors in 2.19-master.

 

Edited by atarixle

Share this post


Link to post
Share on other sites
1 hour ago, atarixle said:

The project that breaks uses a struct with self referencing pointers (e.g. *next, *prev for chains). This compiles in 2.18 but horrorbly breaks in errors in 2.19-master.

 

show here a minimal example of the code and we will try to help.

Share this post


Link to post
Share on other sites
Posted (edited)

deleted post, as I found a typo that strangely enough caused no error in 2.18

Edited by atarixle
I guess I had a typo which caused no error in 2.18 ... be back soon

Share this post


Link to post
Share on other sites
Posted (edited)

If I remember my C you probably need to put an incomplete type first so that it knows the name of the struct, something like

typedef struct node node;

struct node {
  char *name;
  node *parent;
};
Edited by danwinslow

Share this post


Link to post
Share on other sites
Posted (edited)

Yeah I was thinking that too, but now it compiles without errors, because a closer look at this time of day revealed that this wasn't causing the error.

Beside a typo (which strangely did not throw and error on 2.18) I also had an invalid lvalue, which I fixed with a pair of brackets.

 

Now it compiles the whole project but the outcome results in errors while runtime.

 

Time now to remove all warnings I guess.

Edited by atarixle

Share this post


Link to post
Share on other sites
Posted (edited)

ok this is even weirder to me:

The project now works, as I removed the cast in 

memset((unsigned char*)PST, 170, SCREEN_WIDTH);
 
originally, I added this cast to avoid the Warning: Converting integer to pointer without a cast
 
Most of my projects run way faster than before: a per-pixel-scroller in GR.8 feels like 3x the speed as before, and my prime-number-generator speed up from 22 seconds down to 17 seconds for the very same task (calculating primes from 2 to 32000).
Edited by atarixle
SPEED

Share this post


Link to post
Share on other sites
29 minutes ago, atarixle said:

The project now works, as I removed the cast in 

You shouldn't need the cast as long as PST has been defined as char *PST

Also all pointers are unsigned, they are purely 16 bit addresses so "unsigned" is also not needed.

I think that definition may have somehow confused the compiler

Share this post


Link to post
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...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...