diff --git a/Makefile b/Makefile index 4c9967f..fc3a841 100755 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ LINUX_OUT := gol.out APPLE2_CL := $(CC65_HOME)/bin/cl65 APPLE2_CC := $(CC65_HOME)/bin/cc65 -APPLE2_SRC := gol_apple2.c gol_apple2_optimized.asm +APPLE2_SRC := gol_apple2.c gol_apple2_optimized.asm gfx.asm APPLE2_MAP := gol_apple2.map APPLE2_CFLAGS := -Oirs -v -t apple2 APPLE2_OUT := gol.a2 diff --git a/gfx.asm b/gfx.asm new file mode 100755 index 0000000..5a5277c --- /dev/null +++ b/gfx.asm @@ -0,0 +1,270 @@ + .include "apple2.inc" + .include "zeropage.inc" + + .import pusha + .import popa + + .export _mode_text + .export _gfx_init + .export _gfx_fill + .export _gfx_pixel + .export _gfx_refresh + + + .define FULLSCREEN #0 + .define SPLIT #1 + .define LOWRES #0 + .define HIRES #1 + .define PAGE_1 #1 + .define PAGE_2 #2 + +.BSS +Page_Current: .byte 0 +Page_Future: .byte 0 + +.DATA +;Pages are composed of lines. Here are their 1st pixel adress +Page1: .word $400, $480, $500, $580, $600, $680, $700, $780, $428, $4A8, $528, $5A8, $628, $6A8, $728, $7A8, $450, $4D0, $550, $5D0, $650, $6D0, $750, $7D0 +Page2: .word $800, $880, $900, $980, $A00, $A80, $B00, $B80, $828, $8A8, $928, $9A8, $A28, $AA8, $B28, $BA8, $850, $8D0, $950, $9D0, $A50, $AD0, $B50, $BD0 + + +.CODE + + +;will put the adress of the future page into ptr1 +.macro GET_PAGE_FUTURE + .local get_page_future_page_1, get_page_future_page_2, get_page_future_end + LDA Page_Current + CMP PAGE_1 + BEQ get_page_future_page_2 + ;storing the low and high bytes of the page address into ptr1 + get_page_future_page_1: + LDA #Page1 + STA ptr1+1 + CLC + BCC get_page_future_end + get_page_future_page_2: + LDA #Page1 + STA ptr1+1 + get_page_future_end: +.endmacro + + + + +;************************** +;void __fastcall__ mode_text( void ); +_mode_text: + LDA $C054 ;page 1 + LDA $C051 ;text + RTS + + + + +;************************** +;void __fastcall__ gfx_init( uint8_t RES, uint8_t MODE ) +; Switches to the desired res and mode. +; Always displays page 1 +_gfx_init: +res: TAX + LDY #0 + LDA (sp),Y + CMP LOWRES + BNE hires +lores: LDA $C056 + CLC + BCC mode +hires: LDA $C057 +mode: CPX FULLSCREEN + BNE split +fullscr:LDA $C052 + CLC + BCC init_end +split: LDA $C053 +init_end: + LDA $C054 ;page 1 + LDA $C050 ;graphics + LDA PAGE_1 + STA Page_Current + JSR popa ;the parameter on stack + RTS + + + + + +;************************** +;void __fastcall__ gfx_fill( uint8_t color ) +; Fills the screen with the given color +; TMP1 and PTR1 and PTR2 are overwritten +_gfx_fill: +; TODO SWITCH PAGES !! + ;saving the context + TAX + LDA tmp1 + jsr pusha + LDA ptr1 + jsr pusha + LDA ptr2 + jsr pusha + TXA + ;duplicate nybble color + STA tmp1 + ASL A + ASL A + ASL A + ASL A + ORA tmp1 + STA tmp1 + ;select to page to write into + LDA Page_Current + CMP PAGE_1 + BNE page_2 + ;storing the low and high bytes of the page address into ptr1 +page_1: LDA #Page1 + STA ptr1+1 + CLC + BCC fill +page_2: LDA #Page1 + STA ptr1+1 +fill: + ;iterating on X: the line number +for_lines: + ;getting the 16 bit line adress and storing it in ptr2 + TXA + ASL + TAY + LDA (ptr1),Y + STA ptr2 + INY + LDA (ptr1),Y + STA ptr2+1 + ;iterating on Y to fill a line + LDY #0 +fill_line: + LDA tmp1 ;reload the color + STA (ptr2),Y ;color the current pixel + INY ;next pixel + CPY #40 ;nb pixels per line + BNE fill_line + INX + CPX #24 ;nb lines + BNE for_lines +fill_end: + ;displaying the page we filled + ; TODO SWITCH PAGES !! + ;restoring the context + jsr popa + STA ptr2 + jsr popa + STA ptr1 + jsr popa + STA tmp1 + RTS + + +;************************** +;void __fastcall__ gfx_pixel( uint8_t color, uint8_t coord_x, uint8_t coord_y ) +; Draws a pixel at the given coordinates on the Page_Future +_gfx_pixel: + ;saving the context + TAX + LDA tmp3 + jsr pusha + LDA tmp2 + jsr pusha + LDA ptr1 + jsr pusha + LDA ptr2 + jsr pusha + TXA + + STA tmp3 ;coord_y + ; Modify the color depending on the pixel's line parity + AND #1 + BEQ even +odd: ; pixel is on an odd line + LDY #(1+4) ;there were 4 pushes to save registers + LDA (sp),Y ;color + ASL ;shift the color to put it on high nybble + ASL + ASL + ASL + CLC + BCC oddeven +even: ; pixel is on an even line + LDY #(1+4) ;there were 4 pushes to save registers + LDA (sp),Y ;color +oddeven: + STA tmp2 + + ; FIXME : switching to Page 2 does not work + ; dont get the future page and work on page 1 + ;GET_PAGE_FUTURE + LDA #Page1 + STA ptr1+1 + + ; get the line adress and store it in ptr2 + LDA tmp3 + LSR + ASL + TAY + LDA (ptr1),Y + STA ptr2 + INY + LDA (ptr1),Y + STA ptr2+1 + + ; get coord_x + LDY #4 ;there were 4 pushes to save registers + LDA (sp),Y + ; draw + TAY + LDA tmp2 ;color + STA (ptr2),Y + + ;restoring the context + JSR popa + STA ptr2 + JSR popa + STA ptr1 + JSR popa + STA tmp2 + JSR popa + STA tmp3 + JSR popa ;the 2 parameters on stack + JSR popa + RTS + + +;************************** +;void __fastcall__ gfx_refresh( void ) +; Updates the screen by displaying the Future Page which becomes Current +_gfx_refresh: + LDA Page_Current + CMP PAGE_1 + BEQ switch_to_page_2 + +switch_to_page_1: + LDA $C054 ;page 1 + LDA PAGE_1 + CLC + BCC switch_to_page_end +switch_to_page_2: + LDA $C055 ;page 2 + LDA PAGE_2 + +switch_to_page_end: + STA Page_Current + RTS diff --git a/gfx.h b/gfx.h new file mode 100755 index 0000000..5735339 --- /dev/null +++ b/gfx.h @@ -0,0 +1,38 @@ +#ifndef __GFX_H__ +#define __GFX_H__ + + +void __fastcall__ mode_text( void ); +void __fastcall__ gfx_init( uint8_t resolution, uint8_t mode ); +void __fastcall__ gfx_fill( uint8_t color ); +void __fastcall__ gfx_pixel( uint8_t color, uint8_t coord_x, uint8_t coord_y ); +void __fastcall__ gfx_refresh( void ); + +enum eMode { + FULLSCREEN = 0, + SPLIT = 1 +}; +enum eResolution { + LOWRES = 0, + HIRES = 1 +}; +enum eColor { + BLACK = 0, + MAGENTA, + DARKBLUE, + PURPLE, + DARKGREEN, + GREY, + MEDIUMBLUE, + LIGHTBLUE, + BROWN, + ORANGE, + GREY2, + PINK, + GREEN, + YELLOW, + AQUA, + WHITE +}; + +#endif diff --git a/gol_apple2.c b/gol_apple2.c index 8992db3..0d172e7 100755 --- a/gol_apple2.c +++ b/gol_apple2.c @@ -7,6 +7,8 @@ /* Specific headers */ #include +#include "gfx.h" + /******************* FUNCTION DEFINITIONS **************/ void __fastcall__ init_asm( uint8_t* p_cell, uint8_t* p_cells_future ); /* Inits the variables used in the ASM scope */ @@ -22,6 +24,7 @@ void __fastcall__ update( void ); /* updates the simulation */ void __fastcall__ update_asm( void ); /* updates the simulation */ uint8_t __fastcall__ count_neighbours( uint8_t* cell ); /* counts nb neighbours of the cell */ + void quit( void ); /******************* CUSTOM TYPES AND VALUES DEFINITIONS ****************/ @@ -76,6 +79,7 @@ int main( int argc, char** argv ) State = STATE_EDITOR; break; case STATE_EDITOR: + mode_text(); editor(); State = STATE_RUN; break; @@ -92,6 +96,7 @@ int main( int argc, char** argv ) } break; default: + mode_text(); printf("ERROR!"); State = STATE_QUIT; break; @@ -105,6 +110,7 @@ int main( int argc, char** argv ) void quit( void ) { uint8_t x, y; + mode_text(); screensize (&x, &y); gotoxy( 1u, y-1u ); printf("BYE BYE!"); @@ -209,11 +215,14 @@ uint8_t toggle_cell( const uint8_t x, const uint8_t y ) void run( void ) { + uint8_t i; char str_nb_iteration [5]; uint16_t nb_iterations = 2u; KeyPressed = NO_KEY; - cursor(0); + gfx_init( LOWRES, SPLIT ); + gfx_fill( BLACK ); + cursor(0); gotoxy( 0u, NB_LINES ); printf("Iteration:1 (R)eset (E)ditor (Q)uit"); while( KeyPressed == NO_KEY) @@ -224,7 +233,7 @@ void run( void ) gotoxy(10u, NB_LINES); printf( itoa(nb_iterations++, str_nb_iteration, 10) ); /* Testing key pressed */ - if( kbhit() ){ + if( kbhit() ) { KeyPressed = cgetc(); break; } @@ -251,11 +260,13 @@ void __fastcall__ update( void ) (nb_neighbours < 2u || nb_neighbours > 3u ) ) { *cell_future_line = DEAD; - cputcxy( x, y, SPRITE_DEAD ); + //cputcxy( x, y, SPRITE_DEAD ); + gfx_pixel( BLACK, x, 2*y ); } else if( *cell_curr == DEAD && nb_neighbours == 3u ) { *cell_future_line = ALIVE; - cputcxy( x, y, SPRITE_ALIVE ); + gfx_pixel( WHITE, x, 2*y ); + //cputcxy( x, y, SPRITE_ALIVE ); } cell_curr += NB_LINES; cell_neighbourhoud_line += NB_LINES;