Jump to content

CurtisP's Photo

CurtisP

Member Since 29 Mar 2007
OFFLINE Last Active Nov 21 2018 8:16 PM

#3952302 C02 Compiler

Posted by CurtisP on Sat Feb 3, 2018 12:35 PM

I put the C02 project on GitHub. Due to non-vcs patches to the compiler, I had to create a separate branch with a version that will compile programs in the vcs directory. This branch will eventually be merged back in.

 

The compiler can be built using gcc and Makefile or using the Pelles C compiler for Windows and the c02.ppj file. 

 

To compile a .c02 program, cd to the vcs directy and issue the command "c02 filename" on Windows or "../c02 filename" in Linux, etc... where filename does not include the .c02 extension.

 

 https://github.com/R...ree/compile-vcs




#3918716 AV connector for Atari Flashback Portable

Posted by CurtisP on Sat Dec 23, 2017 3:57 PM

I found this in my box of extra cables last night. Can't try it out until Christmas day, though.

Attached Thumbnails

  • IMG_20171222_223837.jpg



#3909954 Atari Flashback Portable 2016 vs 2017. any thoughts?

Posted by CurtisP on Mon Dec 11, 2017 10:06 PM

To get the self-test mode on my Flashback Portable 2017, I had to hold down all six round keys (A, R, S,P, L, and T) while powering on.


#3826213 Basic Programming...

Posted by CurtisP on Sat Aug 12, 2017 4:32 PM

I started to alter it into an 8k PAL Superchip version to use expanded ram instead of native (in the original program, symbols/tokens are stored in 63 bytes starting at ram $93...and tracked with ram addresses $8A and $8B). I altered these reads and writes so they would point to expanded ram instead. The larger screen area made room for line numbers 10 though 13 to be visible (also added). The problem is that the interpreter is still dreadfully limited...what is the point?

 

If you still have this code, I'd like to see it.




#3801503 Halo 2600 Source

Posted by CurtisP on Sat Jul 8, 2017 3:14 PM

I had been wanting to run this on my unmodified Supercharger which requires not accessing ROM locations $FFF8 and $FFF9, but as is the code uses every single byte of the 4K cartridge.

 

Today, I took a look at the source code, and by making a small optimization I was able to trim 5 bytes from the code so that it ends at $FFF5.

 

I changed the end of SetRespx from

    STA 0,X	; RESPx
    RTS	

to

    STA 0,X     ; RESPx
    STA $10,X   ; HMPx
    RTS

then I changed the calls to SetRespx from

    JSR SetRespx
    STA HMM1
    RTS

    JSR SetRespx
    STA HMP0

    JSR SetRespx
    STA HMBL
    RTS

to

    JMP SetRespx

    JSR SetRespx

    JMP SetRespx

Edit: After setting NTSC mode in the source and re-assembling, the game runs flawlessly on my 6-switcher using the Supercharger.

Thanks for releasing the code, Ed.




#3801409 Help with chessboard with venetian blinds

Posted by CurtisP on Sat Jul 8, 2017 12:15 PM

Also, 1K is not always recognized as a valid ROM size. Stella doesn't mind it, but MAKEWAV choked on it, so I had to change the source from

org $fc00

to

org $f800

and reassemble to make a 2k ROM before I could convert.




#3801341 Help with chessboard with venetian blinds

Posted by CurtisP on Sat Jul 8, 2017 10:49 AM

This flicker is rather noticeable in Stella, even with phosphor mode on (at least on Linux Mint). I'll load it up on my Supercharger tonight and see how it looks on my television.




#3792289 C02 Compiler

Posted by CurtisP on Sun Jun 25, 2017 3:49 PM

Neat!  I'd suggest a minor change to the strobe registers(WSYNC, RESP0, HMOVE, etc):

void vtsync() {
  A=2;     //Set Bit 2 (D1)
  WSYNC;   //Wait for end of Scanline
  VSYNC=A; //Turn On Vertical Sync
  WSYNC;   //Wait 2 More Scanlines
  WSYNC;  
  A=0;     //Clear Bit 2 (D1)
  WSYNC;   //Wait for End of 3rd Scanline
  VSYNC=A; //Turn On Vertical Sync
  return;
}
Makes it cleaner, less typing, and thus less chance of a mistake.

 

There are other 6502 based systems that use strobe registers so, I modified the compiler to allow implicit assignments.

IMPLICIT ASSIGNMENTS

A statement consisting of only a simple variable is treated as an 
implicit assignment of the A register to the variable in question.

This is useful on systems that use memory locations as strobe registers.

Examples:
  HMOVE;  //Move Objects (Atari VCS)
  S80VID; //Enable 80-Column Video (Apple II)

Note: An implicit assignment generates an STA opcode with the variable
as the operand.

Thanks for the idea.




#3792239 C02 Compiler

Posted by CurtisP on Sun Jun 25, 2017 2:45 PM

Even better would be to abstract the register usage when feasible:
void vtsync() {
  WSYNC;   //Wait for end of Scanline
  VSYNC=2; //Turn On Vertical Sync, Set Bit 2 (D1)
  WSYNC;   //Wait 2 More Scanlines
  WSYNC;  
  WSYNC;   //Wait for End of 3rd Scanline
  VSYNC=0; //Turn On Vertical Sync, Clear Bit 2 (D1)
  return;
}

 

Registers are already abstracted. So the code

VSYNC=2;

Compiles to

LDA #2
STA VSYNC

I allowed the use of a register as a variable as an advanced feature so redundant LDA's can be avoided.




#3792235 C02 Compiler

Posted by CurtisP on Sun Jun 25, 2017 2:41 PM

Neat!  I'd suggest a minor change to the strobe registers(WSYNC, RESP0, HMOVE, etc):

void vtsync() {
  A=2;     //Set Bit 2 (D1)
  WSYNC;   //Wait for end of Scanline
  VSYNC=A; //Turn On Vertical Sync
  WSYNC;   //Wait 2 More Scanlines
  WSYNC;  
  A=0;     //Clear Bit 2 (D1)
  WSYNC;   //Wait for End of 3rd Scanline
  VSYNC=A; //Turn On Vertical Sync
  return;
}

 

A variable by itself as statement doesn't have any meaning in C-like languages. If I implemented C-like macros then I could possibly do something like this.

#define WSYNC = WSYNC = A

WSYNC;

However, almost all code that uses strobe registers is going to be in a function that's coded in assembly language anyway, so it should not be necessary.




#3792134 C02 Compiler

Posted by CurtisP on Sun Jun 25, 2017 12:23 PM

The compiler is efficient enough that I can write most VCS code directly in C02.

Here is an example:

 

//Atari VCS Color Bars Program

#pragma origin $F800    //2k Cartridge
#include <vcshead.h02>  //TIA and RIOT Registers

/* Generate Vertical Sync Signal */
void vtsync() {
  A=2;     //Set Bit 2 (D1)
  WSYNC=A; //Wait for end of Scanline
  VSYNC=A; //Turn On Vertical Sync
  WSYNC=A; //Wait 2 More Scanlines
  WSYNC=A;
  A=0;     //Clear Bit 2 (D1)
  WSYNC=A; //Wait for End of 3rd Scanline
  VSYNC=A; //Turn On Vertical Sync
  return;
}

/* Execute Vertical Blank Code */
void vtblnk() {
  X=37; //Delay 37 Scanlines
  do {
    WSYNC=A;  //Wait for end of Scanline
    X--;
  } while (X);
  return;
}

/* Execute Kernel Code */
void kernel() {
  A=0; //Clear All Bits
  WSYNC=A;  //Wait for end of Scanline
  VBLANK=A; //Turn Off Vertical Blank
  X=0; //Draw 192 Scanlines (256-64)
  do {
    if (X & 3) {
      WSYNC = A;  //Wait for end of Scanline
      COLUBK = X; //Set Background Color
    }
    X--;
  } while (X);
  return;
}

/* Execute Overscan Code */
void ovrscn() {
  WSYNC=A;  //Wait for end of Scanline
  A=2;      //Set Bit 2 (D1)
  VBLANK=A; //Turn On Vertical Blank
  X=27; //Delay 27 Scanlines
  do {
    WSYNC=X;  //Wait for end of Scanline
    X--;
  } while(X);
  return;
}

start:
  asm("","SEI","");
  asm("","CLD","");
  A = 0;
  X = A;
  Y = A;
  do {
    X--;
    asm("","TXS","");
    push 0;
  } while (X);
irqbrk: //Code to Execute when BRK Instruction is Encountered
main:  //Start of Program Code
  vtsync(); //Generate Vertical Sync Signal  
  vtblnk(); //Generate Vertical Blank Signal  
  kernel(); //Execute Kernal Code
  ovrscn(); //Execute Overscan Code
  goto main;

#include <vcsfoot.h02>  //Finalization Code

And here is the Assembly Language that's created:

        PROCESSOR 6502         
        ORG $F800        
; ======== Assembler File  include/vcshead.a02  =======
VSYNC   EQU $00  ;0000 00x0   Vertical Sync Set-Clear
VBLANK  EQU $01  ;xx00 00x0   Vertical Blank Set-Clear
WSYNC   EQU $02  ;---- ----   Wait for Horizontal Blank
COLUBK  EQU $09  ;xxxx xxx0   Color-Luminance Background
; ==========================================
VTSYNC:                  ;VOID VTSYNC() {
        LDA #2           ;  A = 2
        STA WSYNC        ;  WSYNC = A;
        STA VSYNC        ;  VSYNC = A;
        STA WSYNC        ;  WSYNC = A;
        STA WSYNC        ;  WSYNC = A;
        LDA #0           ;  A = 0;
        STA WSYNC        ;  WSYNC = A;
        STA VSYNC        ;  VSYNC = A;
        RTS              ;  RETURN; }
VTBLNK:                  ;VOID VTBLNK() {
        LDA #37          ;  X = 37;
        TAX              ;
L_0001:                  ;  DO {
        STA WSYNC        ;    WSYNC = A;
        DEX              ;    X--;
        TXA              ;  } WHILE(X);
        BEQ L_0000       
        JMP L_0001       ;
L_0000: RTS              ;  RETURN; }
KERNEL:                  ;VOID KERNEL() {
        LDA #0           ;  A = 0;
        STA WSYNC        ;  WSYNC = A;
        STA VBLANK       ;  VBLANK = A;
        LDA #0           ;  X = 0 ;
        TAX              ;  
L_0003: TXA              ;  DO {  
        AND #3           ;    IF ( X & 3 ) {
        BEQ L_0004       ;
        STA WSYNC        ;      WSYNC= A
        TXA              ;      COLUBK = X;
        STA COLUBK       ;    }
L_0004: DEX              ;    X--;
        TXA              ;  } WHILE (X);
        BEQ L_0002       ;
        JMP L_0003       ;
L_0002: RTS              ;  RETURN; }
OVRSCN:                  ;VOID OVRSCN() {
        STA WSYNC        ;  WSYNC= A;
        LDA #2           ;  A = 2;
        STA VBLANK       ;  VBLANK= A;
        LDA #27          ;  X = 27;
        TAX              ;
L_0006: TXA              ;  DO { 
        STA WSYNC        ;  WSYNC= X;
        DEX              ;  X--;
        TXA              ;  } WHILE (X);
        BEQ L_0005       ;
        JMP L_0006       ;
L_0005: RTS              ;  RETURN; }
START:                   ;START:
        SEI              ;  ASM("","SEI","");
        CLD              ;  ASM("","CLD","");
        LDA #0           ;  A = 0;
        TAX              ;  X = A;
        TAY              ;  Y = A;
L_0008:                  ;  DO {
        DEX              ;    X--;
        TXS              ;  ASM("","TXS","");
        LDA #0           ;  PUSH 0;
        PHA              ;
        TXA              ;  } WHILE (X);
        BEQ L_0007       ;
        JMP L_0008       ;
L_0007:                  ;
IRQBRK:                  ;IRQBRK:
MAIN:                    ;MAIN:
        JSR VTSYNC       ;  VTSYNC();
        JSR VTBLNK       ;  VTBLNK();
        JSR KERNEL       ;  KERNEL(;)
        JSR OVRSCN       ;  OVRSCN(;)
        JMP MAIN         ;  GOTO MAIN;
; ======== Assembler File  include/vcsfoot.a02  =======
        ORG  $FFF8   ;Control and Interrupt Registers
SCCTL   DC.B $00     ;$FFF8 Supercharger Control Register
SCAUD   DC.B $00     ;$FFF9 Supercharger Audio Data
        DC.W $0000   ;$FFFA Non-Maskable Interrupt Vector (Unused)
        DC.W START   ;$FFFC Reset Vector
        DC.W IRQBRK  ;$FFFE Interrupt Vector
; ==========================================



#3792106 C02 Compiler

Posted by CurtisP on Sun Jun 25, 2017 11:48 AM

This is something that had been bouncing around in my head for at least ten years. I originally started it about five years ago, but then got distracted and finally picked it up again a couple months ago.

The language and compiler are still in the alpha stage of development. The code is currently a bit of a mess, and I'm still wrestling with design decisions.
 
Here is some explanation from the beginning of the documentation that I have written:

INTRODUCTION

C02 is a simple C-syntax language designed to generate highly optimized
code for the 6502 microprocessor. The C02 specification is a highly
specific subset of the C standard with some modifications and extensions

PURPOSE

Why create a whole new language, particularly one with severe restrictions,
when there are already full-featured C compilers available? It can be
argued that standard C is a poor fit for processors like the 6502. The C 
was language designed to translate directly to machine language instructions 
whenever possible. This works well on 32-bit processors, but requires either 
a byte-code interpreter or the generation of complex code on a typical
8-bit processor. C02, on the other hand, has been designed to translate 
directly to 6502 machine language instructions.
 
The C02 language and compiler were designed with two goals in mind.

The first goal is the ability to target machines with low memory: a few 
kilobytes of RAM (assuming the generated object code is to be loaded into 
and ran from RAM), or as little as 128 bytes of RAM and 2 kilobytes of ROM
(assuming the object code is to be run from a ROM or PROM). 

The compiler is agnostic with regard to system calls and library functions. 
Calculations and comparisons are done with 8 bit precision. Intermediate 
results, array indexing, and function calls use the 6502 internal registers.
While this results in compiled code with virtually no overhead, it severely 
restricts the syntax of the language.

The second goal is to port the compiler to C02 code so that it may be
compiled by itself and run on any 6502 based machine with sufficient memory
and appropriate peripherals. This slightly restricts the implementation of
code structures.

 




#2154630 Is Droid Sans Mono the perfect monospaced font?

Posted by CurtisP on Thu Dec 9, 2010 9:12 PM

I just don't understand all the fuss. I love Courier (and not that New one either).


#2154582 Atari User Issue 2

Posted by CurtisP on Thu Dec 9, 2010 8:16 PM

I really hate to be negative, and don't want to discourage you, but I have to admit that the preview comes across as ameteurish, particularly the lack of copy editing. I'm afraid that this might dissuade others from paying for the actual issues, just as it has dissuaded me.


#1807838 Atari 2600 Homebrew Mascot

Posted by CurtisP on Mon Aug 3, 2009 7:42 PM

Ari Ant as a 16 line high single player. I'm pretty happy with the front and back view. The side view could use some work though.

Attached Thumbnails

  • AriAnt.GIF