mirror of
https://github.com/peterdell/wudsn-ide.git
synced 2024-06-03 06:29:35 +00:00
309 lines
9.4 KiB
Java
309 lines
9.4 KiB
Java
/**
|
|
* Copyright (C) 2009 - 2014 <a href="http://www.wudsn.com" target="_top">Peter Dell</a>
|
|
*
|
|
* This file is part of WUDSN IDE.
|
|
*
|
|
* WUDSN IDE 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 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* WUDSN IDE 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 WUDSN IDE. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package com.wudsn.ide.gfx.converter.atari8bit;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.TreeMap;
|
|
|
|
import org.eclipse.swt.graphics.ImageData;
|
|
|
|
import com.wudsn.ide.base.common.NumberFactory;
|
|
import com.wudsn.ide.gfx.converter.FilesConverterData;
|
|
import com.wudsn.ide.gfx.converter.ImageConverterData;
|
|
import com.wudsn.ide.gfx.converter.InverseBlock;
|
|
import com.wudsn.ide.gfx.converter.InverseBlockList;
|
|
import com.wudsn.ide.gfx.converter.Tile;
|
|
import com.wudsn.ide.gfx.converter.TileSet;
|
|
import com.wudsn.ide.gfx.converter.c64.C64Utility;
|
|
import com.wudsn.ide.gfx.converter.generic.CharMapConverter;
|
|
import com.wudsn.ide.gfx.converter.generic.CharMapMultiColorConverter;
|
|
|
|
public class CharMapGraphics12Converter extends
|
|
CharMapMultiColorConverter {
|
|
|
|
private static final Integer PF1 = NumberFactory.getInteger(1);
|
|
private static final Integer PF2 = NumberFactory.getInteger(2);
|
|
private static final Integer PF3 = NumberFactory.getInteger(3);
|
|
|
|
public CharMapGraphics12Converter() {
|
|
}
|
|
|
|
@Override
|
|
public void convertToImageDataSize(FilesConverterData data) {
|
|
data.setImageDataWidth(data.getParameters().getColumns()
|
|
* (8 + data.getParameters().getSpacingWidth()));
|
|
data.setImageDataHeight(data.getParameters().getRows()
|
|
* (8 + data.getParameters().getSpacingWidth()));
|
|
}
|
|
|
|
@Override
|
|
public boolean convertToImageData(FilesConverterData data) {
|
|
if (data == null) {
|
|
throw new IllegalArgumentException(
|
|
"Parameter 'data' must not be null.");
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
public static void convertToFileData(ImageConverterData data) {
|
|
if (data == null) {
|
|
throw new IllegalArgumentException(
|
|
"Parameter 'data' must not be null.");
|
|
}
|
|
int pixelPerColumn = 4;
|
|
int pixelPerRow = 8;
|
|
|
|
TileSet tileSet;
|
|
tileSet = new TileSet(data.getImageData(), pixelPerColumn, pixelPerRow);
|
|
|
|
int screenWidth = 48;
|
|
int rowsPerCharset = 3;
|
|
|
|
// If the actual image is larger that the screen with, it cannot be
|
|
// processed..
|
|
if (tileSet.getColumns() > screenWidth) {
|
|
data.setTargetImageData(null);
|
|
}
|
|
|
|
// If the actual image is smaller that the screen with, it shall be
|
|
// centered.
|
|
int screenOffset = (screenWidth - tileSet.getColumns()) / 2;
|
|
|
|
boolean effect = data.getParameters().getConverterId()
|
|
.equals(CharMapGraphics12Converter.class.getName());
|
|
|
|
int charSets = (tileSet.getRows() + rowsPerCharset - 1)
|
|
/ rowsPerCharset;
|
|
byte[] screenBuffer = new byte[tileSet.getRows() * screenWidth];
|
|
byte[] charSetBuffer = new byte[1024 * charSets];
|
|
|
|
Integer gridColor = C64Utility.PINK;
|
|
Integer inverseConflictColor = C64Utility.YELLOW;
|
|
|
|
ImageData targetImageData = tileSet.createTiledImageData();
|
|
|
|
int screenCharacter = 0;
|
|
int charSetCount = -1;
|
|
for (int r = 0; r < tileSet.getRows(); r++) {
|
|
if (r % rowsPerCharset == 0) {
|
|
charSetCount++;
|
|
int charSetBufferOffset = charSetCount * 1024;
|
|
for (int i = 0; i < pixelPerRow; i++) {
|
|
charSetBuffer[charSetBufferOffset + i] = (byte) 0x55;
|
|
}
|
|
screenCharacter = 1;
|
|
|
|
}
|
|
|
|
for (int c = 0; c < tileSet.getColumns(); c++) {
|
|
|
|
// Create and analyze tile
|
|
Tile tile = tileSet.getTile(c, r);
|
|
|
|
Map<Integer, Integer> pixelMapping;
|
|
List<Integer> ignoredPixelColors;
|
|
InverseBlockList inverseBlockList;
|
|
pixelMapping = new TreeMap<Integer, Integer>();
|
|
ignoredPixelColors = new ArrayList<Integer>();
|
|
inverseBlockList = new InverseBlockList();
|
|
|
|
// TODO Make hard coded mapping real parameters
|
|
if (System.getProperty("user.name").equals("d025328")) {
|
|
if (r < 10 || r > 19) {
|
|
getTileMapping1(pixelMapping, ignoredPixelColors,
|
|
inverseBlockList);
|
|
} else {
|
|
|
|
getTileMapping2(pixelMapping, ignoredPixelColors,
|
|
inverseBlockList);
|
|
}
|
|
}
|
|
|
|
InverseBlock inverseBlock;
|
|
inverseBlock = inverseBlockList.getInverseBlock(c, r);
|
|
|
|
int inverseCharacter = 0x00;
|
|
Integer inverseColor;
|
|
if (inverseBlock != null) {
|
|
inverseColor = inverseBlock.getInverseColor();
|
|
|
|
if (tile.hasPixelColor(inverseColor)) {
|
|
// Collect all mappings which map to PF3.
|
|
List<Integer> pf3colors;
|
|
pf3colors = new ArrayList<Integer>();
|
|
for (Map.Entry<Integer, Integer> entry : pixelMapping
|
|
.entrySet()) {
|
|
if (entry.getValue().equals(PF3)) {
|
|
pf3colors.add(entry.getKey());
|
|
}
|
|
}
|
|
|
|
// Set inverse color to PF3 which becomes PF4 using the
|
|
// inverse
|
|
pixelMapping.put(inverseColor, PF3);
|
|
|
|
for (Integer pf3Color : pf3colors) {
|
|
if (tile.hasPixelColor(pf3Color)) {
|
|
tile.setInverseConflict(true);
|
|
break;
|
|
}
|
|
}
|
|
if (!tile.isInverseConflict()) {
|
|
// No conflict
|
|
ignoredPixelColors.add(inverseColor);
|
|
inverseCharacter = 0x80;
|
|
} else {
|
|
if (inverseBlock.isInverseIfConflict()) {
|
|
inverseCharacter = 0x80;
|
|
} else {
|
|
inverseCharacter = 0x00;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
inverseColor = null;
|
|
}
|
|
|
|
screenBuffer[r * screenWidth + c + screenOffset] = (byte) (screenCharacter + inverseCharacter);
|
|
int charSetBufferOffset = charSetCount * 1024 + 8
|
|
* (screenCharacter & 0x7f);
|
|
screenCharacter++;
|
|
|
|
// Draw/copy tile.
|
|
Map<Integer, Integer> pixelColorCounts = tile
|
|
.getDistinctPixelColorCounts(ignoredPixelColors);
|
|
|
|
Integer lastRowMajorColor = null;
|
|
|
|
for (int r1 = 0; r1 < pixelPerRow; r1++) {
|
|
int my = r * (pixelPerRow + 1) + r1 + 1;
|
|
|
|
Map<Integer, Integer> rowPixelColorCounts = tile
|
|
.getDistinctLinePixelColorCounts(r1,
|
|
ignoredPixelColors);
|
|
|
|
int charSetByte = 0;
|
|
for (int c1 = 0; c1 < pixelPerColumn; c1++) {
|
|
int mx = c * (pixelPerColumn + 1) + c1 + 1;
|
|
|
|
Integer color = tile.getPixelColor(c1, r1);
|
|
|
|
Integer pixelBits = pixelMapping.get(color);
|
|
|
|
if (effect) {
|
|
if (pixelColorCounts.size() == 0) {
|
|
color = C64Utility.BLACK;
|
|
} else if (pixelColorCounts.size() == 1) {
|
|
color = Tile.getMajorColor(pixelColorCounts,
|
|
ignoredPixelColors);
|
|
} else if (rowPixelColorCounts.size() == 0) {
|
|
color = lastRowMajorColor;
|
|
} else if (rowPixelColorCounts.size() == 1) {
|
|
color = Tile.getMajorColor(rowPixelColorCounts,
|
|
ignoredPixelColors);
|
|
lastRowMajorColor = color;
|
|
}
|
|
|
|
if (color == null) {
|
|
color = C64Utility.BLACK;
|
|
}
|
|
if (color == inverseColor) {
|
|
color = inverseConflictColor;
|
|
}
|
|
}
|
|
|
|
targetImageData.setPixel(mx, my, color.intValue());
|
|
charSetByte = (charSetByte << 2);
|
|
if (pixelBits != null) {
|
|
charSetByte |= pixelBits.intValue();
|
|
}
|
|
}
|
|
charSetBuffer[charSetBufferOffset + r1] = (byte) charSetByte;
|
|
}
|
|
}
|
|
|
|
tileSet.drawTileBoundaries(targetImageData, gridColor,
|
|
inverseConflictColor);
|
|
}
|
|
|
|
data.setTargetFileBytes(CharMapConverter.CHAR_SET_FILE, charSetBuffer);
|
|
data.setTargetFileBytes(CharMapConverter.CHAR_MAP_FILE, screenBuffer);
|
|
|
|
data.setTargetImageData(targetImageData);
|
|
}
|
|
|
|
private static void getTileMapping2(Map<Integer, Integer> pixelMapping,
|
|
List<Integer> ignoredPixelColors, InverseBlockList inverseBlockList) {
|
|
pixelMapping.put(C64Utility.BLACK, PF1);
|
|
pixelMapping.put(C64Utility.WHITE, PF2);
|
|
pixelMapping.put(C64Utility.RED, PF3);
|
|
pixelMapping.put(C64Utility.LIGHT_GREEN, PF3);
|
|
|
|
ignoredPixelColors.add(C64Utility.BLACK);
|
|
ignoredPixelColors.add(C64Utility.WHITE);
|
|
// ignoredPixelColors.add(C64Utility.DARK_GRAY);
|
|
ignoredPixelColors.add(C64Utility.LIGHT_GREEN);
|
|
|
|
// Blue floor
|
|
inverseBlockList.add(0, 39, 8, 19, C64Utility.LIGHT_BLUE, true);
|
|
|
|
// Brown Ship
|
|
inverseBlockList.add(16, 18, 5, 7, C64Utility.BROWN, true);
|
|
// Blue Planet
|
|
inverseBlockList.add(0, 39, 0, 6, C64Utility.LIGHT_BLUE, true);
|
|
|
|
// Cybernoid
|
|
// inverseBlockList.add(0,
|
|
// 39, 8,
|
|
// 19,
|
|
// C64Utility.LIGHT_RED);
|
|
// // Red
|
|
|
|
// Yellow Explosion
|
|
inverseBlockList.add(4, 11, 20, 24, C64Utility.BROWN, false);
|
|
}
|
|
|
|
private static void getTileMapping1(Map<Integer, Integer> pixelMapping,
|
|
List<Integer> ignoredPixelColors, InverseBlockList inverseBlockList) {
|
|
pixelMapping.put(C64Utility.BLACK, PF1);
|
|
pixelMapping.put(C64Utility.WHITE, PF2);
|
|
pixelMapping.put(C64Utility.DARK_GRAY, PF3);
|
|
|
|
ignoredPixelColors.add(C64Utility.BLACK);
|
|
ignoredPixelColors.add(C64Utility.WHITE);
|
|
ignoredPixelColors.add(C64Utility.DARK_GRAY);
|
|
|
|
// Brown Ship
|
|
inverseBlockList.add(16, 18, 5, 7, C64Utility.BROWN, true);
|
|
// Blue Planet
|
|
inverseBlockList.add(0, 39, 0, 6, C64Utility.LIGHT_BLUE, true);
|
|
|
|
// Cybernoid
|
|
inverseBlockList.add(0, 39, 8, 19, C64Utility.LIGHT_RED, false);
|
|
|
|
// Yellow Explosion
|
|
inverseBlockList.add(4, 11, 20, 24, C64Utility.BROWN, true);
|
|
}
|
|
}
|