diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index e292e42..5193578 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.o *.map *.bak +*.s diff --git a/COPYING b/COPYING old mode 100644 new mode 100755 diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 index 7c5558a..f594b97 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ linux: $(LINUX_SRC) $(LINUX_CC) -o $(LINUX_OUT) $? $(LINUX_CFLAGS) apple2: $(APPLE2_SRC) - $(APPLE2_CL) -m $(APPLE2_MAP) -o $(APPLE2_OUT) $? $(APPLE2_CFLAGS) + $(APPLE2_CL) -m $(APPLE2_MAP) -o $(APPLE2_OUT) $? $(APPLE2_CFLAGS) -C src/game-of-life.cfg apple2-asm: $(APPLE2_SRC) $(APPLE2_CC) $(APPLE2_CFLAGS) -r -T $? diff --git a/README.md b/README.md old mode 100644 new mode 100755 index b864ffa..75cc547 --- a/README.md +++ b/README.md @@ -22,6 +22,13 @@ Two binaries will be produced. Run the *add-to-disk.sh* script. +**Title screen** + +The title screen art is located in the *assets* folder. It has to be +manually loaded on the disk image using the *AppleCommander's GUI*, for the +command line loads a corrupted file! +This screen was converted from a PNG using [*Rgb2Hires*](https://github.com/Pixinn/Rgb2Hires). + --- For more information, you can refer to these posts on [my blog](https://www.xtof/info/blog/). diff --git a/assets/gol.screen b/assets/gol.screen new file mode 100755 index 0000000..4fe72db Binary files /dev/null and b/assets/gol.screen differ diff --git a/benchs.txt b/benchs.txt old mode 100644 new mode 100755 diff --git a/disk.dsk b/disk.dsk old mode 100644 new mode 100755 index 29b6ae2..57ae836 Binary files a/disk.dsk and b/disk.dsk differ diff --git a/scripts/add-to-disk.sh b/scripts/add-to-disk.sh old mode 100644 new mode 100755 index 9bdc0d5..9affb3b --- a/scripts/add-to-disk.sh +++ b/scripts/add-to-disk.sh @@ -1,19 +1,19 @@ #!/bin/bash -# Adds the gol.a2 Apple2 binary exceutable to the provided disk.dsk +# Adds the required files to the provided disk.dsk # usage: add_to_disk PATH_TO_APPLECOMMANDER.jar set -e - -if (( $# != 1 )); then + +if (( $# != 3 )); then echo "Bad number of arguments" - echo "usage: add_to_disk.sh PATH_TO_APPLECOMMANDER.jar" + echo "usage: add_to_disk.sh PATH_TO_APPLECOMMANDER.jar PATH_TO_BINARY.a2 PATH_TO_DISK" exit fi echo " . revoving previous instance of GOL form the disk" -java -jar ${1} -d disk.dsk GOL +java -jar ${1} -d ${3} GOL echo " .. adding GOL to the disk" -java -jar ${1} -cc65 disk.dsk GOL BIN < gol.a2 +java -jar ${1} -cc65 ${3} GOL BIN < ${2} echo "DONE." diff --git a/scripts/pyHiRes.py b/scripts/pyHiRes.py deleted file mode 100755 index 0a5b464..0000000 --- a/scripts/pyHiRes.py +++ /dev/null @@ -1,131 +0,0 @@ -#! /usr/bin/env python3 - -import os.path -import argparse -from PIL import Image - -# HiRes colors -BLACK = [0x00, 0x00, 0x00] -WHITE = [0xFF, 0xFF, 0xFF] -GREEN = [0x00, 0xFF, 0x00] -BLUE = [0x00, 0x00, 0xFF] -ORANGE = [0xFF, 0x77, 0x00] -VIOLET = [0xFF, 0x00, 0xFF] - -Msg_Warning = "" -Color_Last = BLACK - -def error(msg, err_code): - print(msg) - exit(err_code) - - -# Compute the Euclidean distance between 2 colors -def distance(color1, color2): - return (color1[0] - color2[0])**2 + (color1[1] - color2[1])**2 + (color1[2] - color2[2])**2 - - -# Returns the nearest color -def nearest_color(color): - dist_black = distance(BLACK, color) - dist_white = distance(WHITE, color) - dist_green = distance(GREEN, color) - dist_blue = distance(BLUE, color) - dist_orange = distance(ORANGE, color) - dist_violet = distance(VIOLET, color) - dist_min = min([dist_black, dist_white, dist_green, dist_blue, dist_violet, dist_orange]) - if dist_min == dist_black: - return BLACK - elif dist_min == dist_white: - return WHITE - elif dist_min == dist_green: - return GREEN - elif dist_min == dist_blue: - return BLUE - elif dist_min == dist_orange: - return ORANGE - else: - return VIOLET - -# Returns True if the 7 pixel block can be converted into hires with no artifact -# Returns False otherwise -def compliant_hires(block): - global Msg_Warning - global Color_Last - # Test if colors from the two groups are in the block, aka "clashing" - group_one = False - group_two = False - nb_pixels = len(block)//3 - for i in range(0, nb_pixels): - color = block[3*i:3*(i+1)] - if color == ORANGE or color == BLUE: - group_one = True - if color == GREEN or color == VIOLET: - group_two = True - if group_one and group_two: - Msg_Warning = "Colors from two groups, some clashing will occur!" - return False - # Test if there are two consecutive different colors in the group - Msg_Warning = "Two consecutive different colors may lead to an artifact" - color = block[0:3] - if Color_Last != BLACK and Color_Last != WHITE \ - and color != BLACK and color != WHITE \ - and color != Color_Last: - return False - for i in range(0, nb_pixels-1): - color = block[3*i:3*(i+1)] - if color != BLACK and color != WHITE: - color_next = block[3*(i+1):3*(i+2)] - if color_next != BLACK and color_next != WHITE \ - and color != BLACK and color != WHITE \ - and color != color_next: - return False - Color_Last = block[3*(nb_pixels-1):3*nb_pixels] - return True - - -# PARSING COMMAND LINE ARGUMENTS -parser = argparse.ArgumentParser(description="This script converts a 24bit RGB image file into an Apple II HiRes image.") -parser.add_argument("file", help="file to convert") -parser.add_argument("-o", "--output", help="output filename", required=False) -args = parser.parse_args() - - -# SANITIZE PARAMETERS -if not os.path.exists(args.file): - error("File " + args.file + " does not exist!", -1) - - -# MAIN -try: - # Open source image - image_rgb = Image.open(args.file).convert('RGB') - w = image_rgb.size[0] - h = image_rgb.size[1] - - if w != 140 or h != 192: - error("Source image must be 140x192 pixels", -1) - - # Quantize image to the HiRes's 6 colors - image_quantized = [] - for y in range(0, h): - for x in range(0, w): - color = nearest_color(image_rgb.getpixel((x, y))) - for i in range(0, 3): - image_quantized.append(color[i]) - if len(image_quantized) != 3*140*192: - error("Bad quantized size", -1) - - # image_test = Image.frombytes('RGB', (140, 192), bytes(image_quantized)) - # image_test.show() - - # Test image conpliance to HiRes limitations - nb_pixels = 7 # nb pixels per line block - for i in range(0, 140 * 192 // nb_pixels): - block = image_quantized[3*i*nb_pixels: - 3*(i+1)*nb_pixels] - if not compliant_hires(block): - print("Warning @block #" + str(i+1) + ": " + Msg_Warning) - -except ValueError: - error(ValueError, -1) diff --git a/src/file_io.c b/src/file_io.c old mode 100644 new mode 100755 diff --git a/src/file_io.h b/src/file_io.h old mode 100644 new mode 100755 diff --git a/src/game-of-life.cfg b/src/game-of-life.cfg new file mode 100755 index 0000000..5db7b01 --- /dev/null +++ b/src/game-of-life.cfg @@ -0,0 +1,49 @@ +# Default configuration (allowing for 3KB in LC) + +FEATURES { + STARTADDRESS: default = $0803; +} +SYMBOLS { + __EXEHDR__: type = import; + __STACKSIZE__: type = weak, value = $0800; # 2k stack + __HIRESP2__: type = weak, value = $4000; # Start of HIRES PAGE2 + __BSS__: type = weak, value = $6000; # Start of BSS after HIRES PAGE2 + __HIMEM__: type = weak, value = $9600; # Presumed RAM end + __LCADDR__: type = weak, value = $D400; # Behind quit code + __LCSIZE__: type = weak, value = $0C00; # Rest of bank two +} +MEMORY { + ZP: file = "", define = yes, start = $0080, size = $001A; + HEADER: file = %O, start = %S - 4, size = $0004; + MAIN: file = %O, define = yes, start = %S, size = __HIRESP2__ - %S; + BSS: file = "", start = __BSS__, size = __HIMEM__ - __BSS__; + LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__; +} +SEGMENTS { + ZEROPAGE: load = ZP, type = zp; + EXEHDR: load = HEADER, type = ro; + STARTUP: load = MAIN, type = ro; + LOWCODE: load = MAIN, type = ro, optional = yes; + CODE: load = MAIN, type = ro; + RODATA: load = MAIN, type = ro; + DATA: load = MAIN, type = rw; + INIT: load = MAIN, type = rw; + ONCE: load = MAIN, type = ro, define = yes; + LC: load = MAIN, run = LC, type = ro, optional = yes; + BSS: load = BSS, type = bss, define = yes; +} +FEATURES { + CONDES: type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__, + segment = ONCE; + CONDES: type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__, + segment = RODATA; + CONDES: type = interruptor, + label = __INTERRUPTOR_TABLE__, + count = __INTERRUPTOR_COUNT__, + segment = RODATA, + import = __CALLIRQ__; +} diff --git a/src/gfx.asm b/src/gfx.asm old mode 100644 new mode 100755 diff --git a/src/gfx.h b/src/gfx.h old mode 100644 new mode 100755 diff --git a/src/gol_apple2.c b/src/gol_apple2.c old mode 100644 new mode 100755 index b66739c..b8f5216 --- a/src/gol_apple2.c +++ b/src/gol_apple2.c @@ -40,7 +40,7 @@ void editor( void ); /* lets the user draw some starting cell int8_t editor_load_save( const uint8_t load_or_save ); void toggle_cell( const uint8_t x, const uint8_t y ); /* toggles the cell at the given coordinates. \ Returns the cursor X position */ - +void title_screen( void ); /* Loads and display the title screen */ void run( void ); /* runs the simulation */ void __fastcall__ update( void ); /* updates the simulation */ uint8_t __fastcall__ count_neighbours( uint8_t* cell ); /* counts nb neighbours of the cell */ @@ -85,6 +85,7 @@ enum { static uint8_t Cells[ NB_COLUMNS ][ NB_LINES ]; static uint8_t Cells_Future[ NB_COLUMNS ][ NB_LINES ]; static uint8_t Cells_Initial[ NB_COLUMNS ][ NB_LINES ]; +//static uint8_t Title_Screen[ 0x2000 ]; /******************** CODE ************************/ @@ -94,6 +95,9 @@ int main( int argc, char** argv ) (void)argc; (void)argv; + /* Displaying the Title Screen */ + title_screen(); + init_asm( (uint8_t*)Cells, (uint8_t*)Cells_Future ); init_rnd_color(); @@ -211,7 +215,7 @@ void editor( void ) uint8_t color_pixel; uint8_t update_color = 1; - const char* const text = "J L I K: Move the cursor\nSPACE : Toggle a cell\n\n(L)oad - (S)ave - (D)one"; + const char* const text = "H K U J: Move the cursor\nSPACE : Toggle a cell\n\n(L)oad - (S)ave - (D)one"; set_text( text ); //Place the cursor middle screen @@ -376,3 +380,31 @@ void run( void ) } } } + +/****** HIRES SCREEN DEFINITIONS ***********/ +#define HIRES_PAGE2 (char*)0x4000 +#define HIRES_PAGE_SIZE 0x2000 +#define SWITCH_GRAPHICS *((uint8_t*)0xC050)=1 +#define SWITCH_FULLSCREEN *((uint8_t*)0xC052)=1 +#define SWITCH_PAGE2 *((uint8_t*)0xC055)=1 +#define SWITCH_HIRES *((uint8_t*)0xC057)=1 + +//The Title Screen asset is located in the "assets" folder +void title_screen( void ) +{ + uint8_t handle; + file_open("GOL.SCREEN", &handle); + if(file_read( handle, HIRES_PAGE2, HIRES_PAGE_SIZE ) != HIRES_PAGE_SIZE ) { + printf("\nERROR, CANNOT READ GOL.SCREEN\nERRNO: %x\n\n", file_error()); + file_close(handle); + exit(-1); + } + file_close(handle); + + SWITCH_GRAPHICS; + SWITCH_FULLSCREEN; + SWITCH_PAGE2; + SWITCH_HIRES; + + cgetc(); +} diff --git a/src/gol_apple2_optimized.asm b/src/gol_apple2_optimized.asm old mode 100644 new mode 100755 diff --git a/src/gol_linux.c b/src/gol_linux.c old mode 100644 new mode 100755 diff --git a/src/mli.asm b/src/mli.asm old mode 100644 new mode 100755 index 9c41296..17096ca --- a/src/mli.asm +++ b/src/mli.asm @@ -32,13 +32,6 @@ _call_to_mli: JSR popa STA Mli_Call - ;+ DEBUG -; CMP #$CE -; BNE continue -;debug: JMP debug -;continue: - ;- DEBUG - ; Call MLI and return JSR $BF00 ; MLI call entry point Mli_Call: diff --git a/src/rnd_colors.asm b/src/rnd_colors.asm old mode 100644 new mode 100755 diff --git a/src/rnd_colors.h b/src/rnd_colors.h old mode 100644 new mode 100755