mirror of https://github.com/zxdos/zxuno.git
sdk: moved `hardware/kartusho/roms/zx7b.exe` to `sdk/bin/zx7b.exe`, added sources
This commit is contained in:
parent
0f7aab6bf6
commit
b02f67aef5
|
@ -55,4 +55,7 @@ cores/Oric/source/_impact.log
|
|||
cores/Oric/build/oric.v4_my.bit
|
||||
|
||||
sdk/bin/sjasmplus
|
||||
sdk/bin/zx7b
|
||||
sdk/src/sjasmplus
|
||||
sdk/src/zx7b/zx7b
|
||||
sdk/src/zx7b/zx7b.exe
|
||||
|
|
|
@ -10,12 +10,15 @@ include common.mk
|
|||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
SJASMPLUS := sjasmplus.exe
|
||||
ZX7B := zx7b.exe
|
||||
else
|
||||
SJASMPLUS := sjasmplus
|
||||
ZX7B := zx7b
|
||||
endif
|
||||
|
||||
TOOLS:=\
|
||||
bin/$(SJASMPLUS)
|
||||
bin/$(SJASMPLUS) \
|
||||
bin/$(ZX7B)
|
||||
|
||||
.PHONY: all
|
||||
all: $(TOOLS)
|
||||
|
|
|
@ -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
|
|
@ -10,13 +10,16 @@ include ../common.mk
|
|||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
SJASMPLUS := sjasmplus.exe
|
||||
ZX7B := zx7b.exe
|
||||
else
|
||||
SJASMPLUS := sjasmplus
|
||||
ZX7B := zx7b
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
all: \
|
||||
../bin/$(SJASMPLUS)
|
||||
../bin/$(SJASMPLUS) \
|
||||
../bin/$(ZX7B)
|
||||
|
||||
ifneq ($(OS),Windows_NT)
|
||||
../bin/$(SJASMPLUS): sjasmplus/build/$(SJASMPLUS)
|
||||
|
@ -33,13 +36,20 @@ sjasmplus:
|
|||
tar -xzf sjasmplus.tgz
|
||||
mv sjasmplus-20190306.1 sjasmplus
|
||||
rm -f sjasmplus.tgz
|
||||
|
||||
../bin/$(ZX7B): zx7b/$(ZX7B)
|
||||
cp $< $@
|
||||
|
||||
zx7b/$(ZX7B): | zx7b
|
||||
$(MAKE) -w -C $|
|
||||
endif
|
||||
|
||||
.PHONY: clean
|
||||
ifeq ($(OS),Windows_NT)
|
||||
clean:;
|
||||
else
|
||||
clean: | sjasmplus sjasmplus.mk
|
||||
clean: | sjasmplus sjasmplus.mk zx7b
|
||||
$(MAKE) -w -C sjasmplus -f ../sjasmplus.mk clean
|
||||
rm -f ../bin/$(SJASMPLUS)
|
||||
$(MAKE) -w -C zx7b clean
|
||||
rm -f ../bin/$(SJASMPLUS) ../bin/$(ZX7B)
|
||||
endif
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue