Browse Source

Compressed ROM for EaZyZ80-512, Issue #500

Thanks and credit to Paul de Bak for providing the compression utility.

Co-Authored-By: PauldB <169483608+p42db@users.noreply.github.com>
pull/626/head v3.6.0-dev.34
Wayne Warthen 4 months ago
parent
commit
10b4f98276
No known key found for this signature in database GPG Key ID: 8B34ED29C07EEB0A
  1. 1
      Doc/ChangeLog.txt
  2. 1
      Source/Clean.cmd
  3. 12
      Source/EZ512/Build.cmd
  4. 4
      Source/EZ512/Clean.cmd
  5. 11
      Source/EZ512/Makefile
  6. 151
      Source/EZ512/decomp.z80
  7. 2
      Source/ver.inc
  8. 2
      Source/ver.lib
  9. 1
      Tools/Makefile.inc
  10. BIN
      Tools/compress/compress.exe
  11. 2
      Tools/unix/Makefile
  12. 12
      Tools/unix/compress/Makefile
  13. 150
      Tools/unix/compress/compress.c

1
Doc/ChangeLog.txt

@ -33,6 +33,7 @@ Version 3.6
- HJB: Added loader for MSX
- HJB: Added IDE driver master media detect option
- WBW: Add support for S100 Serial I/O DLP Serial connection
- P?D: Generate compressed ROM for EaZyZ80 512
Version 3.5.1
-------------

1
Source/Clean.cmd

@ -27,3 +27,4 @@ pushd ZRC && call Clean & popd
pushd Z1RCC && call Clean & popd
pushd ZZRCC && call Clean & popd
pushd MSX && call Clean & popd
pushd EZ512 && call Clean & popd

12
Source/EZ512/Build.cmd

@ -3,9 +3,13 @@ setlocal
set TOOLS=../../Tools
set PATH=%TOOLS%\srecord;%PATH%
set PATH=%TOOLS%\zxcc;%TOOLS%\srecord;%TOOLS%\compress;%PATH%
for %%f in (..\..\Binary\RCZ80_ez512_*.rom) do call :build %%~nf
set CPMDIR80=%TOOLS%/cpm/
zxcc z80asm -decomp/HL
for %%f in (..\..\Binary\RCZ80_ez512_*.upd) do call :build %%~nf
goto :eof
@ -23,4 +27,8 @@ move temp.dat ..\..\Binary\%1_hd1k_prefix.dat
copy /b ..\..\Binary\%1_hd1k_prefix.dat + ..\..\Binary\hd1k_cpm22.img + ..\..\Binary\hd1k_zsdos.img + ..\..\Binary\hd1k_nzcom.img + ..\..\Binary\hd1k_cpm3.img + ..\..\Binary\hd1k_zpm3.img + ..\..\Binary\hd1k_ws4.img ..\..\Binary\%1_hd1k_combo.img || exit /b
srec_cat ..\..\Binary\%1.upd -binary -exclude 0x13700 0x14A00 -fill 0xC9 0x13700 0x14A00 -o temp.upd -binary
compress temp.upd
srec_cat decomp.hex -intel temp.upd.cmp -binary -offset 3 -o ..\..\Binary\%1_64k.rom -binary
goto :eof

4
Source/EZ512/Clean.cmd

@ -1,3 +1,7 @@
@echo off
setlocal
if exist *.upd del *.upd
if exist *.cmp del *.cmp
if exist *.hex del *.hex
if exist *.lst del *.lst

11
Source/EZ512/Makefile

@ -1,13 +1,15 @@
DEST=../../Binary
OTHERS=*.hex *.upd *.cmp
HD1KIMGS = $(DEST)/hd1k_cpm22.img $(DEST)/hd1k_zsdos.img $(DEST)/hd1k_nzcom.img \
$(DEST)/hd1k_cpm3.img $(DEST)/hd1k_zpm3.img $(DEST)/hd1k_ws4.img
ROMS := $(wildcard $(DEST)/RCZ80_ez512_*.rom)
ROMS := $(patsubst $(DEST)/%.rom,%,$(ROMS))
ROMS := $(wildcard $(DEST)/RCZ80_ez512_*.upd)
ROMS := $(patsubst $(DEST)/%.upd,%,$(ROMS))
OBJECTS := $(patsubst %,%_hd1k_prefix.dat,$(ROMS))
OBJECTS += $(patsubst %,%_hd1k_combo.img,$(ROMS))
OBJECTS += $(patsubst %,%_64k.rom,$(ROMS))
TOOLS = ../../Tools
@ -25,3 +27,8 @@ DIFFPATH = $(DIFFTO)/Binary
%_hd1k_combo.img: %_hd1k_prefix.dat $(HD1KIMGS)
cat $^ > $@
%_64k.rom: $(DEST)/%.upd decomp.hex
srec_cat $< -binary -exclude 0x13700 0x14A00 -fill 0xC9 0x13700 0x14A00 -o temp.upd -binary
$(COMPRESS) temp.upd
srec_cat decomp.hex -intel temp.upd.cmp -binary -offset 3 -o $@ -binary

151
Source/EZ512/decomp.z80

@ -0,0 +1,151 @@
; 251003 decomp_rom_v1.1
; Mark Pruden: Fix for omitted Bank 4
;
; 250208 decomp_rom v1.0
; Paul de Bak: Renamed and used in RomWBW utility program 'compress_upd.c'
; to compress *.upd binary files
;
;1/17/25
;decompress RomWBW v1.0 - Original version by Bill Shen
;Routine in ROM that decompress RomWBW data file into RAM and jump to it.
;copy data file to RAM starting from bank 0, addr 0.
;when encountered two consecutive bytes of same values, the tird byte following the consecutive values
; describe how many more identical bytes need to be added.
;decompression ends when 3 banks (96KB) are expanded
;compressed data is stored from address $3 to below $FF00
;decompress program is located at $FF00
;register usage
;regC points to bankreg
;regB is ROM source ($20)
;regD is RAM destination bank
;regE is previous value
;regHL is destination pointer
;regIX is source pointer
;regIY points to byte count
bankreg equ 0ch ;PIO port C is 512K RAM bank register
SIOAData equ 8h ;location of SIO chan A data
SIOACmd equ 9h ;location of SIO ch A command/status reg
SIOBData equ 0ah ;location of SIO chan B data
SIOBCmd equ 0bh ;location of SIO ch B command/status reg
PORTCData equ 0ch ;PIA port C data
PORTCCmd equ 0dh ;PIA port C command
org 0
jp 0ff00h ;do program at top of memory
dataRomWBW:
;compressed RomWBW data appended here
org 0ff00h
ld a,09h ;write to KIO command reg first, enable PIA mux
out (0eh),a ; SIO-CTC-PIO priority daisy chain
ld hl,0ff00h ;copy self into RAM
ld de,0ff00h
ld bc,100h
ldir
xor a ;PortC are all outputs. This will cause both RAM and ROM
out (PORTCCmd),a ; to be enabled until following OUT instruction, since RAM and
; ROM have same contents, this won't cause contention
ld a,00100010b ; ROM enable, RAM disable, bank$2, nRTSA, nRTSB enabled
out (PORTCData),a
;register usage
;regC points to bankreg
;regB is ROM source ($20)
;regD is RAM destination bank
;regE is previous value
;regHL is destination pointer
;regIX is source pointer
;regIY points to byte count
ld c,bankreg ;regC points to bank register IO address
ld e,0 ;make sure regE is not the same as very first byte which is 0xC3
ld b,20h ;regB is ROM source
ld d,80h ;regD is RAM destination
ld hl,0 ;destination starts from bank 0, address 0
ld ix,dataRomWBW ;regIX points to compressed RomWBW
ld iy,cSame ;regIY points to the count of same value
start:
out (c),b ;read data from ROM
;these two lines are executing program in ROM which has same program as RAM
ld a,(ix) ;read from source
out (c),d
;running in RAM
ld (hl),a ;write to destination
cp e ;two consecutive same values?
jp z,decomp
ld e,a ;update the 'previous' value
inc ix ;next value in ROM
inc hl ;next destination value
ld a,h
cp 80h ;check for address greater than 32KB
jp z,nxtDbank
jp start
nxtDbank:
ld hl,0
inc d ;next bank
ld a,d
;; cp 83h ;compare to bank 3
cp 84h ;MP compare to bank 4
jp z,decompDone
jp start
decomp:
out (c),b ;read data from ROM
;running in ROM
inc ix ;point to byte count of same value
ld a,(ix) ;get the count value
out (c),d ;switch to RAM bank
;running in RAM
dec a ;reduce by 1 because one byte is already written
ld (iy),a ;store count to cSame pointed by regIY
jp z,DoDecomp2 ;just two consecutive values
DoDecomp:
inc hl ;next destination value
ld a,h
cp 80h
jp z,nxtDbank1
DoDecomp1:
ld (hl),e ;write previous value (in regE) to destination
dec (iy)
jp nz,DoDecomp
DoDecomp2:
;done with block decompression, get ready to start over
out (c),b
;running in ROM
inc ix ;point to next data in ROM
ld e,(ix)
dec e ;make sure previous value does not match, in case of large
; block (>256) of same values
out (c),d
;running in RAM
inc hl
ld a,h
cp 80h ;check for address grater than 32KB
jp z,nxtDbank2
jp start
nxtDbank1:
ld hl,0
inc d ;next bank
ld a,d
cp 83h ;compare to bank3
jp z,decompDone
out (c),d ;update bank before continuing
jp DoDecomp1
nxtDbank2:
ld hl,0
inc d ;next bank
ld a,d
cp 83h ;compare to bank 3
jp z,decompDone
jp start
decompDone:
;decompression is done, reaching 96KB of data
ld a,80h ;ROM disable, RAM enable, bank$0, nRTSA, nRTSB enabled
out (c),a
jp 0 ;execute RomWBW
cSame: db 0 ;count of the same value
end

2
Source/ver.inc

@ -2,7 +2,7 @@
#DEFINE RMN 6
#DEFINE RUP 0
#DEFINE RTP 0
#DEFINE BIOSVER "3.6.0-dev.33"
#DEFINE BIOSVER "3.6.0-dev.34"
#define rmj RMJ
#define rmn RMN
#define rup RUP

2
Source/ver.lib

@ -3,5 +3,5 @@ rmn equ 6
rup equ 0
rtp equ 0
biosver macro
db "3.6.0-dev.33"
db "3.6.0-dev.34"
endm

1
Tools/Makefile.inc

@ -45,6 +45,7 @@ OPENSPIN=$(BINDIR)/openspin
CPMCP=$(BINDIR)/cpmcp
CPMLS=$(BINDIR)/cpmls
CPMCHATTR=$(BINDIR)/cpmchattr
COMPRESS=$(BINDIR)/compress
#
# directory containing cpm binaries

BIN
Tools/compress/compress.exe

Binary file not shown.

2
Tools/unix/Makefile

@ -13,7 +13,7 @@ ifeq ($(UNAME), Darwin)
SUFFIX=osx
endif
SUBDIRS = OpenSpin uz80as zxcc cpmtools bin2asm lzsa
SUBDIRS = OpenSpin uz80as zxcc cpmtools bin2asm lzsa compress
all:
@chmod +x casefn.sh

12
Tools/unix/compress/Makefile

@ -0,0 +1,12 @@
APP := compress
OBJS := compress.o
UNAME := $(shell uname)
all: $(APP)
cp -p $(APP) ../../$(UNAME)
$(APP): $(OBJS)
$(CC) $^ -o $@
clean:
@rm -rf $(APP) $(OBJS)

150
Tools/unix/compress/compress.c

@ -0,0 +1,150 @@
/* =====================================================================
* compress v1.1 - 251012 Paul de Bak, with help from Le Chat AI
*
* =====================================================================
* This RomWBW utility program will attempt to compress any file using
* a straightforward RLE approach.
*
* The output file will have the name of the input file with ".cmp"
* appended.
*
* =====================================================================
* To compile in Linux (or Windows using MinGW):
*
* gcc -o compress_upd(.exe) compress_upd.c
*
* =====================================================================
* Usage: compress(.exe) <input file>
*
* If compression is successful, an ouput file is created with the name
* of the input file + ".cmp".
*
* =====================================================================
* Program exit codes
* 0: Success. An output file is created.
* 1: Incorrect usage or input file not found.
* 2: Unable to create output file.
*
* =====================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//#include <string.h>
//#include <libgen.h> // For basename function
#define VERSION "compress v1.1 - 251012 Paul de Bak & Le Chat AI"
#define MAX_COUNT 0x100 // Maximum count is 256
#define BUFFER_SIZE 65536
size_t calculate_original_size(FILE *input) {
fseek(input, 0, SEEK_END);
return ftell(input);
}
size_t calculate_compressed_size(FILE *input) {
uint8_t buffer[BUFFER_SIZE];
size_t size, compressed_size = 0;
while ((size = fread(buffer, 1, BUFFER_SIZE, input)) > 0) {
size_t i = 0;
while (i < size) {
uint8_t byte = buffer[i];
size_t count = 1;
// Count the number of repetitions of the current byte
while (i + count < size && buffer[i + count] == byte && count < MAX_COUNT) {
count++;
}
if (count >= 2) {
compressed_size += 3; // Two bytes + count
} else {
compressed_size += 1; // Single byte
}
i += count;
}
}
return compressed_size;
}
int compress_file(FILE *input, FILE *output) {
uint8_t buffer[BUFFER_SIZE];
size_t size;
uint8_t repeat_count;
while ((size = fread(buffer, 1, BUFFER_SIZE, input)) > 0) {
size_t i = 0;
while (i < size) {
uint8_t byte = buffer[i];
size_t count = 1;
// Count the number of repetitions of the current byte
while (i + count < size && buffer[i + count] == byte && count < MAX_COUNT) {
count++;
}
if (count >= 2) {
fwrite(&byte, 1, 1, output);
fwrite(&byte, 1, 1, output);
repeat_count = count - 1;
fwrite(&repeat_count, 1, 1, output);
} else {
fwrite(&byte, 1, 1, output);
}
i += count;
}
}
return 1;
}
int main(int argc, char *argv[]) {
char *input_filename;
long free_bytes;
FILE *input;
size_t original_size;
size_t compressed_size;
char output_filename[256];
char *base_name;
char *dot;
FILE *output;
printf("\n%s\n\n", VERSION);
if (argc != 2) {
printf("Usage: %s <input file>\n", argv[0]);
printf("Example: %s RCZ80_ez512_std.upd\n", argv[0]);
return 1; // Error: Incorrect usage
}
input_filename = argv[1];
input = fopen(input_filename, "rb");
if (!input) {
fprintf(stderr, "Error: Input file '%s' not found\n", input_filename);
return 1; // Error: Input file not found
}
// Calculate the original file size
original_size = calculate_original_size(input);
rewind(input);
// Calculate the compressed size first
compressed_size = calculate_compressed_size(input);
rewind(input);
// Construct the output filename
snprintf(output_filename, sizeof(output_filename), "%s.cmp", input_filename);
printf("Compressing %s to %s...\n", input_filename, output_filename);
output = fopen(output_filename, "wb");
if (!output) {
fprintf(stderr, "Error: Unable to create output file '%s'\n", output_filename);
fclose(input);
return 2; // Error: Unable to create output file
}
compress_file(input, output);
fclose(input);
fclose(output);
printf("Compressed from %lu bytes to %lu bytes (%lu%% reduction)\n", original_size, compressed_size, (((original_size - compressed_size) * 100) / original_size));
return 0; // Success
}
Loading…
Cancel
Save