Adding a Title Screen
This commit is contained in:
parent
124a858e4d
commit
117806bc32
|
@ -3,3 +3,4 @@
|
||||||
*.o
|
*.o
|
||||||
*.map
|
*.map
|
||||||
*.bak
|
*.bak
|
||||||
|
*.s
|
||||||
|
|
|
@ -19,7 +19,7 @@ linux: $(LINUX_SRC)
|
||||||
$(LINUX_CC) -o $(LINUX_OUT) $? $(LINUX_CFLAGS)
|
$(LINUX_CC) -o $(LINUX_OUT) $? $(LINUX_CFLAGS)
|
||||||
|
|
||||||
apple2: $(APPLE2_SRC)
|
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-asm: $(APPLE2_SRC)
|
||||||
$(APPLE2_CC) $(APPLE2_CFLAGS) -r -T $?
|
$(APPLE2_CC) $(APPLE2_CFLAGS) -r -T $?
|
||||||
|
|
|
@ -22,6 +22,13 @@ Two binaries will be produced.
|
||||||
|
|
||||||
Run the *add-to-disk.sh* script.
|
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/).
|
For more information, you can refer to these posts on [my blog](https://www.xtof/info/blog/).
|
||||||
|
|
Binary file not shown.
|
@ -1,19 +1,19 @@
|
||||||
#!/bin/bash
|
#!/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
|
# usage: add_to_disk PATH_TO_APPLECOMMANDER.jar
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if (( $# != 1 )); then
|
if (( $# != 3 )); then
|
||||||
echo "Bad number of arguments"
|
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
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo " . revoving previous instance of GOL form the disk"
|
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"
|
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."
|
echo "DONE."
|
||||||
|
|
|
@ -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)
|
|
|
@ -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__;
|
||||||
|
}
|
|
@ -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 );
|
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. \
|
void toggle_cell( const uint8_t x, const uint8_t y ); /* toggles the cell at the given coordinates. \
|
||||||
Returns the cursor X position */
|
Returns the cursor X position */
|
||||||
|
void title_screen( void ); /* Loads and display the title screen */
|
||||||
void run( void ); /* runs the simulation */
|
void run( void ); /* runs the simulation */
|
||||||
void __fastcall__ update( void ); /* updates the simulation */
|
void __fastcall__ update( void ); /* updates the simulation */
|
||||||
uint8_t __fastcall__ count_neighbours( uint8_t* cell ); /* counts nb neighbours of the cell */
|
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[ NB_COLUMNS ][ NB_LINES ];
|
||||||
static uint8_t Cells_Future[ 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 Cells_Initial[ NB_COLUMNS ][ NB_LINES ];
|
||||||
|
//static uint8_t Title_Screen[ 0x2000 ];
|
||||||
|
|
||||||
/******************** CODE ************************/
|
/******************** CODE ************************/
|
||||||
|
|
||||||
|
@ -94,6 +95,9 @@ int main( int argc, char** argv )
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
|
/* Displaying the Title Screen */
|
||||||
|
title_screen();
|
||||||
|
|
||||||
init_asm( (uint8_t*)Cells, (uint8_t*)Cells_Future );
|
init_asm( (uint8_t*)Cells, (uint8_t*)Cells_Future );
|
||||||
init_rnd_color();
|
init_rnd_color();
|
||||||
|
|
||||||
|
@ -211,7 +215,7 @@ void editor( void )
|
||||||
uint8_t color_pixel;
|
uint8_t color_pixel;
|
||||||
uint8_t update_color = 1;
|
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 );
|
set_text( text );
|
||||||
|
|
||||||
//Place the cursor middle screen
|
//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();
|
||||||
|
}
|
||||||
|
|
|
@ -32,13 +32,6 @@ _call_to_mli:
|
||||||
JSR popa
|
JSR popa
|
||||||
STA Mli_Call
|
STA Mli_Call
|
||||||
|
|
||||||
;+ DEBUG
|
|
||||||
; CMP #$CE
|
|
||||||
; BNE continue
|
|
||||||
;debug: JMP debug
|
|
||||||
;continue:
|
|
||||||
;- DEBUG
|
|
||||||
|
|
||||||
; Call MLI and return
|
; Call MLI and return
|
||||||
JSR $BF00 ; MLI call entry point
|
JSR $BF00 ; MLI call entry point
|
||||||
Mli_Call:
|
Mli_Call:
|
||||||
|
|
Loading…
Reference in New Issue