Skip to content

Commit

Permalink
add WonderSwan support
Browse files Browse the repository at this point in the history
  • Loading branch information
asiekierka committed Mar 29, 2023
1 parent 8b7dbc0 commit f8e4e29
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 19 deletions.
1 change: 1 addition & 0 deletions docs/changelog/0.9.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ Improvements:
* This module checks for common flaws and bugs in ZZT 3.2 worlds.
* New module: TinyZoo Converter! (Currently CLI-only)
* Partial ZXT world support.
* Partial Weave 3 support.
16 changes: 16 additions & 0 deletions src/main/java/pl/asie/libzzt/TextVisualData.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,20 @@ public boolean isCharFull(int c) {
}
return true;
}

public int getPixelAtBorder(int chr, int cx, int cy) {
if (cx >= 0 && cy >= 0 && cx < this.getCharWidth() && cy < this.getCharHeight()) {
return (this.getCharData()[(chr * this.getCharHeight()) + cy] >> (7 - cx)) & 1;
} else {
return 0;
}
}

public int getPixelAtWrap(int chr, int cx, int cy) {
if (cx < 0) cx = 0;
else if (cx >= this.getCharWidth()) cx = this.getCharWidth() - 1;
if (cy < 0) cy = 0;
else if (cy >= this.getCharHeight()) cy = this.getCharHeight() - 1;
return (this.getCharData()[(chr * this.getCharHeight()) + cy] >> (7 - cx)) & 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ private void commitFarPointer(BinarySerializable object, int bank, int position)
private final int padByte = 0;
private final boolean padToPowerOfTwo;
private final boolean calculateChecksum;
private final boolean trim;
private final Map<BinarySerializable, Collector> collectorMap = new HashMap<>();
private final Multimap<BinarySerializable, Collector> collectorListeners = HashMultimap.create();
private BinarySerializable firstObject;
Expand Down Expand Up @@ -207,9 +208,11 @@ public void writeBankData(OutputStream stream) throws IOException, BinarySeriali
pos += data.length;
}
}
while (pos < bankSizeBytes) {
stream.write(this.padByte);
pos++;
if (!this.trim || i != maximumBank) {
while (pos < bankSizeBytes) {
stream.write(this.padByte);
pos++;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public static BinconvPlatform create(BinconvArgs args) throws IOException {
return new BinconvPlatformGb(args);
} else if ("gg".equals(args.getPlatform())) {
return new BinconvPlatformGg(args);
} else if ("ws".equals(args.getPlatform())) {
return new BinconvPlatformWs(args);
} else {
throw new RuntimeException("Unknown platform: " + args.getPlatform());
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/pl/asie/zima/binconv/BinconvPlatformGb.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public BinarySerializer createBinarySerializer() {
.bankRegionOffset(0x4000)
.bankSizeBytes(16384)
.padToPowerOfTwo(true)
.trim(false)
.build();
}

Expand Down
140 changes: 140 additions & 0 deletions src/main/java/pl/asie/zima/binconv/BinconvPlatformWs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/**
* Copyright (c) 2020, 2021, 2022 Adrian Siekierka
*
* This file is part of zima.
*
* zima is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* zima is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with zima. If not, see <http://www.gnu.org/licenses/>.
*/
package pl.asie.zima.binconv;

import pl.asie.tinyzooconv.BankingBinarySerializer;
import pl.asie.tinyzooconv.BinarySerializer;
import pl.asie.tinyzooconv.exceptions.BinarySerializerException;
import pl.asie.zima.util.FileUtils;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.stream.Collectors;

public class BinconvPlatformWs extends BinconvPlatformTinyzooGbBased {
private final byte[] baseImage;
private final Integer sramSize;
private final Map<Integer, Integer> romBanksToValue = Map.of(
2, 0x00,
4, 0x01,
8, 0x02,
16, 0x03,
32, 0x04,
48, 0x05,
64, 0x06,
96, 0x07,
128, 0x08,
256, 0x09
);
private final Map<Integer, Integer> sramKbToValue = Map.of(
32, 0x02,
128, 0x03,
256, 0x04,
512, 0x05
);

public BinconvPlatformWs(BinconvArgs args) throws IOException {
try (FileInputStream fis = new FileInputStream(args.getEngineFile())) {
this.baseImage = FileUtils.readAll(fis);
}
this.sramSize = args.getSramSize();
}

@Override
public int getViewportWidth() {
return 28;
}

@Override
public int getViewportHeight() {
return 18;
}

@Override
public int getTextWindowWidth() {
return 27;
}

@Override
public BinarySerializer createBinarySerializer() {
return BankingBinarySerializer.builder()
.firstBankIndex(0)
.maxBanks(256)
.bankRegionOffset(0x0000)
.bankSizeBytes(65536)
.padToPowerOfTwo(false)
.trim(true)
.padByte(0xFF)
.calculateChecksum(true)
.build();
}

@Override
public void write(OutputStream stream, BinarySerializer serializer) throws IOException, BinarySerializerException {
// write ROM
ByteArrayOutputStream baos = new ByteArrayOutputStream();
serializer.writeBankData(baos);
int bankSize = baos.size() + this.baseImage.length;
int bankSizeShift = 131072;
while (bankSizeShift < bankSize) {
bankSizeShift *= 2;
}
while (bankSize < bankSizeShift) {
baos.write(0xFF);
bankSize++;
}
baos.write(baseImage);
byte[] fullImage = baos.toByteArray();
int headerOffset = fullImage.length - 16;

// fix ROM size
if (this.sramSize != null) {
Integer romByte = this.romBanksToValue.get(bankSizeShift >> 16);
if (romByte == null) {
throw new BinarySerializerException("Invalid ROM size: " + bankSizeShift + " bytes. Supported values: "
+ this.romBanksToValue.keySet().stream().sorted().map(Object::toString).collect(Collectors.joining(", ")));
}
fullImage[headerOffset + 10] = (byte) romByte.intValue();
}

// fix SRAM size
if (this.sramSize != null) {
Integer sramByte = this.sramKbToValue.get(this.sramSize);
if (sramByte == null) {
throw new BinarySerializerException("Invalid SRAM size: " + this.sramSize + " KB. Supported values: "
+ this.sramKbToValue.keySet().stream().sorted().map(Object::toString).collect(Collectors.joining(", ")));
}
fullImage[headerOffset + 11] = (byte) sramByte.intValue();
}

// calculate global checksum
int globalChecksum = 0;
for (byte b : fullImage) {
globalChecksum += ((int) b) & 0xFF;
}
fullImage[fullImage.length - 2] = (byte) ((globalChecksum >> 8) & 0xFF);
fullImage[fullImage.length - 1] = (byte) (globalChecksum & 0xFF);

// write final ROM
stream.write(fullImage);
}
}
17 changes: 1 addition & 16 deletions src/main/java/pl/asie/zima/image/GmseImageMseCalculator.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,6 @@ public static class GaussianCharCache {
private final List<float[]> cache;
private final Gaussian2DKernel kernel;

private static int getCharPixelAt(TextVisualData visual, int chr, int cx, int cy) {
if (cx < 0) cx = 0;
else if (cx >= visual.getCharWidth()) cx = visual.getCharWidth() - 1;
if (cy < 0) cy = 0;
else if (cy >= visual.getCharHeight()) cy = visual.getCharHeight() - 1;
return (visual.getCharData()[(chr * visual.getCharHeight()) + cy] >> (7 - cx)) & 1;


/* if (cx >= 0 && cy >= 0 && cx < visual.getCharWidth() && cy < visual.getCharHeight()) {
return (visual.getCharData()[(chr * visual.getCharHeight()) + cy] >> (7 - cx)) & 1;
} else {
return 0;
} */
}

public GaussianCharCache(TextVisualData visual, int radius, float sigma) {
this.visual = visual;
this.kernel = new Gaussian2DKernel(sigma, radius);
Expand All @@ -85,7 +70,7 @@ public GaussianCharCache(TextVisualData visual, int radius, float sigma) {
float cv = 0.0f;
for (int ky = -radius; ky <= radius; ky++) {
for (int kx = -radius; kx <= radius; kx++) {
int v = getCharPixelAt(visual, chr, cx + kx, cy + ky);
int v = visual.getPixelAtWrap(chr, cx + kx, cy + ky);
float k = kernel.at(kx, ky);
cv += k * v;
}
Expand Down

0 comments on commit f8e4e29

Please sign in to comment.