sdk: moved `hardware/kartusho/roms/zx7b.exe` to `sdk/bin/zx7b.exe`, added sources

This commit is contained in:
Ivan Tatarinov 2021-04-12 14:02:10 +03:00
parent 0f7aab6bf6
commit b02f67aef5
7 changed files with 385 additions and 4 deletions

3
.gitignore vendored
View File

@ -55,4 +55,7 @@ cores/Oric/source/_impact.log
cores/Oric/build/oric.v4_my.bit cores/Oric/build/oric.v4_my.bit
sdk/bin/sjasmplus sdk/bin/sjasmplus
sdk/bin/zx7b
sdk/src/sjasmplus sdk/src/sjasmplus
sdk/src/zx7b/zx7b
sdk/src/zx7b/zx7b.exe

View File

@ -10,12 +10,15 @@ include common.mk
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
SJASMPLUS := sjasmplus.exe SJASMPLUS := sjasmplus.exe
ZX7B := zx7b.exe
else else
SJASMPLUS := sjasmplus SJASMPLUS := sjasmplus
ZX7B := zx7b
endif endif
TOOLS:=\ TOOLS:=\
bin/$(SJASMPLUS) bin/$(SJASMPLUS) \
bin/$(ZX7B)
.PHONY: all .PHONY: all
all: $(TOOLS) all: $(TOOLS)

13
sdk/bin/zx7b.exe.license Normal file
View File

@ -0,0 +1,13 @@
SPDX-FileName: zx7b.exe
SPDX-FileType: BINARY
SPDX-FileChecksum: SHA1: de47984d9d155eb89153052297caac5ffef5e720
SPDX-LicenseConcluded: BSD-3-Clause
SPDX-LicenseComments: The concluded license is taken from https://github.com/antoniovillena/zx7b/raw/master/zx7b.c
SPDX-FileCopyrightText: Einar Saukas/AntonioVillena, 28 Dec 2013
SPDX-FileComment: ZX7 Backwards compressor v1.01 by Einar Saukas/AntonioVillena, 28 Dec 2013

View File

@ -10,13 +10,16 @@ include ../common.mk
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
SJASMPLUS := sjasmplus.exe SJASMPLUS := sjasmplus.exe
ZX7B := zx7b.exe
else else
SJASMPLUS := sjasmplus SJASMPLUS := sjasmplus
ZX7B := zx7b
endif endif
.PHONY: all .PHONY: all
all: \ all: \
../bin/$(SJASMPLUS) ../bin/$(SJASMPLUS) \
../bin/$(ZX7B)
ifneq ($(OS),Windows_NT) ifneq ($(OS),Windows_NT)
../bin/$(SJASMPLUS): sjasmplus/build/$(SJASMPLUS) ../bin/$(SJASMPLUS): sjasmplus/build/$(SJASMPLUS)
@ -33,13 +36,20 @@ sjasmplus:
tar -xzf sjasmplus.tgz tar -xzf sjasmplus.tgz
mv sjasmplus-20190306.1 sjasmplus mv sjasmplus-20190306.1 sjasmplus
rm -f sjasmplus.tgz rm -f sjasmplus.tgz
../bin/$(ZX7B): zx7b/$(ZX7B)
cp $< $@
zx7b/$(ZX7B): | zx7b
$(MAKE) -w -C $|
endif endif
.PHONY: clean .PHONY: clean
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
clean:; clean:;
else else
clean: | sjasmplus sjasmplus.mk clean: | sjasmplus sjasmplus.mk zx7b
$(MAKE) -w -C sjasmplus -f ../sjasmplus.mk clean $(MAKE) -w -C sjasmplus -f ../sjasmplus.mk clean
rm -f ../bin/$(SJASMPLUS) $(MAKE) -w -C zx7b clean
rm -f ../bin/$(SJASMPLUS) ../bin/$(ZX7B)
endif endif

31
sdk/src/zx7b/Makefile Normal file
View File

@ -0,0 +1,31 @@
# SPDX-FileCopyrightText: 2021 Ivan Tatarinov <ivan-tat@ya.ru>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Supported environments:
# * GNU on Linux, FreeBSD etc.
# * GNU on Windows NT (using MinGW/MSYS/Cygwin/WSL)
include ../../common.mk
ifeq ($(OS),Windows_NT)
ZX7B := zx7b.exe
else
ZX7B := zx7b
endif
ifneq ($(OS),Windows_NT)
$(ZX7B): zx7b.c
$(CC) $(CFLAGS) -o $@ $<
zx7b.c:
wget -c https://github.com/antoniovillena/zx7b/raw/master/zx7b.c
endif
.PHONY: clean
ifeq ($(OS),Windows_NT)
clean:;
else
clean:
rm -f $(ZX7B)
endif

321
sdk/src/zx7b/zx7b.c Normal file
View File

@ -0,0 +1,321 @@
/*
* ZX7b (c) Copyright 2013 by Antonio Villena. All rights reserved.
*
* Based on ZX7 <http://www.worldofspectrum.org/infoseekid.cgi?id=0027996>
* (c) Copyright 2012 by Einar Saukas. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The name of its author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* SPDX-FileCopyrightText: ZX7b (c) Copyright 2013 by Antonio Villena. All rights reserved.
*
* SPDX-FileNotice: Based on ZX7 <http://www.worldofspectrum.org/infoseekid.cgi?id=0027996>
* SPDX-FileNotice: (c) Copyright 2012 by Einar Saukas. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* SPDX-LicenseComments: License's text is equals to one from https://directory.fsf.org/wiki/License:BSD-3-Clause
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_OFFSET 2176 /* range 1..2176 */
#define MAX_LEN 65536 /* range 2..65536 */
typedef struct match_t {
size_t index;
struct match_t *next;
} Match;
typedef struct optimal_t {
size_t bits;
int offset;
int len;
} Optimal;
Optimal *optimize(unsigned char *input_data, size_t input_size);
unsigned char *compress(Optimal *optimal, unsigned char *input_data, size_t input_size, size_t *output_size);
int main(int argc, char *argv[]) {
FILE *ifp;
FILE *ofp;
unsigned char *input_data;
unsigned char *output_data;
size_t input_size;
size_t output_size;
size_t partial_counter;
size_t total_counter;
char *output_name;
int i, j;
if( argc==1 )
printf("\nZX7 Backwards compressor v1.01 by Einar Saukas/AntonioVillena, 28 Dec 2013\n\n"
" zx7b <input_file> <output_file>\n\n"
" <input_file> Raw input file\n"
" <output_file> Compressed output file\n\n"
"Example: zx7b Cobra.scr Cobra.zx7b\n"),
exit(0);
if( argc!=3 )
printf("\nInvalid number of parameters\n"),
exit(-1);
/* open input file */
ifp= fopen(argv[1], "rb");
if( !ifp )
fprintf(stderr, "Error: Cannot access input file %s\n", argv[1]),
exit(1);
/* determine input size */
fseek(ifp, 0L, SEEK_END);
input_size= ftell(ifp);
fseek(ifp, 0L, SEEK_SET);
if( !input_size )
fprintf(stderr, "Error: Empty input file %s\n", argv[1]),
exit(1);
/* allocate input buffer */
input_data= (unsigned char *)malloc(input_size);
if( !input_data )
fprintf(stderr, "Error: Insufficient memory\n"),
exit(1);
/* read input file */
total_counter= 0;
do {
partial_counter = fread(input_data+total_counter, sizeof(char), input_size-total_counter, ifp);
total_counter += partial_counter;
} while ( partial_counter > 0 );
if( total_counter != input_size )
fprintf(stderr, "Error: Cannot read input file %s\n", argv[1]),
exit(1);
/* close input file */
fclose(ifp);
/* create output file */
ofp= fopen(argv[2], "wb");
if( !ofp )
fprintf(stderr, "Error: Cannot create output file %s\n", argv[2]),
exit(1);
for ( i= 0; i<input_size>>1; i++ )
j= input_data[i],
input_data[i]= input_data[input_size-1-i],
input_data[input_size-1-i]= j;
/* generate output file */
output_data= compress(optimize(input_data, input_size), input_data, input_size, &output_size);
for ( i= 0; i<output_size>>1; i++ )
j= output_data[i],
output_data[i]= output_data[output_size-1-i],
output_data[output_size-1-i]= j;
/* write output file */
if( fwrite(output_data, sizeof(char), output_size, ofp) != output_size )
fprintf(stderr, "Error: Cannot write output file %s\n", output_name),
exit(1);
/* close output file */
fclose(ofp);
/* done! */
printf("\nFile %s compressed from %s (%d to %d bytes)\n", argv[2], argv[1], (int) input_size, (int) output_size);
return 0;
}
unsigned char* output_data;
size_t output_index;
size_t bit_index;
int bit_mask;
void write_byte(int value) {
output_data[output_index++] = value;
}
void write_bit(int value) {
if( bit_mask == 0 )
bit_mask = 128,
bit_index = output_index,
write_byte(0);
if( value > 0 )
output_data[bit_index] |= bit_mask;
bit_mask >>= 1;
}
int elias_gamma_bits(int value) {
int bits;
bits= 1;
while ( value > 1 )
bits+= 2,
value>>= 1;
return bits;
}
void write_elias_gamma(int value) {
int bits= 0, rvalue= 0;
while ( value>1 )
++bits,
rvalue<<= 1,
rvalue|= value&1,
value>>= 1;
while ( bits-- )
write_bit(0),
write_bit(rvalue & 1),
rvalue>>= 1;
write_bit(1);
}
unsigned char *compress(Optimal *optimal, unsigned char *input_data, size_t input_size, size_t *output_size) {
size_t input_index;
size_t input_prev;
int offset1;
int mask;
int i;
/* calculate and allocate output buffer */
input_index= input_size-1;
*output_size= (optimal[input_index].bits+16+7)/8;
output_data= (unsigned char *)malloc(*output_size);
if( !output_data )
fprintf(stderr, "Error: Insufficient memory\n"),
exit(1);
/* un-reverse optimal sequence */
optimal[input_index].bits= 0;
while ( input_index > 0 )
input_prev= input_index - (optimal[input_index].len > 0 ? optimal[input_index].len : 1),
optimal[input_prev].bits= input_index,
input_index= input_prev;
output_index= 0;
bit_mask= 0;
/* first byte is always literal */
write_byte(input_data[0]);
/* process remaining bytes */
while ( (input_index= optimal[input_index].bits) > 0)
if( optimal[input_index].len == 0)
write_bit(0),
write_byte(input_data[input_index]);
else{
/* sequence indicator */
write_bit(1);
/* sequence length */
write_elias_gamma(optimal[input_index].len-1);
/* sequence offset */
offset1= optimal[input_index].offset-1;
if( offset1 < 128 )
write_byte(offset1);
else{
offset1-= 128;
write_byte((offset1 & 127) | 128);
for ( mask= 1024; mask > 127; mask >>= 1)
write_bit(offset1 & mask);
}
}
/* end mark */
write_bit(1);
write_elias_gamma(0xff);
return output_data;
}
int count_bits(int offset, int len) {
return 1 + (offset > 128 ? 12 : 8) + elias_gamma_bits(len-1);
}
Optimal* optimize(unsigned char *input_data, size_t input_size) {
size_t *min;
size_t *max;
Match *matches;
Match *match_slots;
Optimal *optimal;
Match *match;
int match_index;
int offset;
size_t len;
size_t best_len;
size_t bits;
size_t i;
/* allocate all data structures at once */
min = (size_t *)calloc(MAX_OFFSET+1, sizeof(size_t));
max = (size_t *)calloc(MAX_OFFSET+1, sizeof(size_t));
matches = (Match *)calloc(256*256, sizeof(Match));
match_slots = (Match *)calloc(input_size, sizeof(Match));
optimal = (Optimal *)calloc(input_size, sizeof(Optimal));
if (!min || !max || !matches || !match_slots || !optimal) {
fprintf(stderr, "Error: Insufficient memory\n");
exit(1);
}
/* first byte is always literal */
optimal[0].bits = 8;
/* process remaining bytes */
for ( i= 1; i < input_size; i++ ){
optimal[i].bits= optimal[i-1].bits + 9;
match_index= input_data[i-1] << 8 | input_data[i];
best_len= 1;
for ( match= &matches[match_index]; match->next != NULL && best_len < MAX_LEN; match = match->next){
offset= i - match->next->index;
if( offset > MAX_OFFSET ){
match->next = NULL;
break;
}
for ( len= 2; len <= MAX_LEN; len++ ){
if( len > best_len && len&0xff ){
best_len= len;
bits= optimal[i-len].bits + count_bits(offset, len);
if( optimal[i].bits > bits )
optimal[i].bits= bits,
optimal[i].offset= offset,
optimal[i].len= len;
}
else if ( i+1 == max[offset]+len && max[offset] != 0 ){
len= i-min[offset];
if( len > best_len )
len= best_len;
}
if( i < offset+len || input_data[i-len] != input_data[i-len-offset] )
break;
}
min[offset]= i+1-len;
max[offset]= i;
}
match_slots[i].index= i;
match_slots[i].next= matches[match_index].next;
matches[match_index].next= &match_slots[i];
}
/* save time by releasing the largest block only, the O.S. will clean everything else later */
free(match_slots);
return optimal;
}