3 * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "../libsdl/print.h"
24 #include "../libcpu/m68kcpu.h"
26 //#define DEBUG_COPPERLIST
28 static void planar2chunky(uint8_t *rgb, uint8_t *bitplanes[], uint16_t palette[], int planes, int width, int y_start, int y_end)
30 uint8_t red, green, blue;
32 uint8_t word[planes], chunk;
35 /* we start memory read from the following calulated bitplane offset: */
36 i = y_start * (width / 8);
37 rgb += y_start * width * 3;
38 for (y = y_start; y < y_end; y++) {
39 for (x = 0; x < width; x += 8) {
40 for (p = 0; p < planes; p++)
41 word[p] = bitplanes[p][i];
42 for (b = 0; b < 8; b++) {
43 chunk = (word[planes - 1] >> 7);
44 word[planes - 1] <<= 1;
45 for (p = planes - 2; p >= 0; p--) {
46 chunk = (chunk << 1) | (word[p] >> 7);
49 rgb4 = palette[chunk];
50 red = (rgb4 >> 4) & 0xf0;
53 red = red | (red >> 4);
54 green = green | (green >> 4);
55 blue = blue | (blue >> 4);
65 static void planar2chunky2(uint8_t *rgb1, uint8_t *bitplanes[], uint16_t palette[], int planes, int width, int y_start, int y_end)
67 uint8_t *rgb2, red, green, blue;
69 uint8_t word[planes], chunk;
72 rgb2 = rgb1 + width * 6;
74 /* we start memory read from the following calulated bitplane offset: */
75 i = y_start * (width / 8);
76 rgb1 += 2 * y_start * width * 6;
77 rgb2 += 2 * y_start * width * 6;
78 for (y = y_start; y < y_end; y++) {
79 for (x = 0; x < width; x += 8) {
80 for (p = 0; p < planes; p++)
81 word[p] = bitplanes[p][i];
82 for (b = 0; b < 8; b++) {
83 chunk = (word[planes - 1] >> 7);
84 word[planes - 1] <<= 1;
85 for (p = planes - 2; p >= 0; p--) {
86 chunk = (chunk << 1) | (word[p] >> 7);
89 rgb4 = palette[chunk];
90 red = (rgb4 >> 4) & 0xf0;
93 red = red | (red >> 4);
94 green = green | (green >> 4);
95 blue = blue | (blue >> 4);
116 #define COP1LCH 0x080
117 #define COP1LCL 0x082
118 #define COP2LCH 0x084
119 #define COP2LCL 0x086
120 #define BPL1PTH 0x0e0
121 #define COLOR00 0x180
123 void emul_video(uint8_t *rgb, uint8_t *memory, uint16_t render_palette[], int width, int height, int diwstart, uint16_t *io, int start, int stop, int double_size)
125 uint32_t bitplane[8] = {0, 0, 0, 0, 0, 0, 0, 0};
127 uint16_t palette[16];
130 int row, last_row, line, last_line, from, to;
135 /* special case where all palette entries are white. (unknown reason, maybe due to teleporter travel) */
137 for (i = 0; i < 16; i++) {
138 if (io[i * 2 + 0x180] != 0xfff)
142 /* First set palette as specified in IO space.
143 * This is set with last IRQ, so it is used after VBL.
144 * Later the copper list causes them to be changed */
145 for (i = 0; i < 16; i++) {
146 /* use palette if all value are white, else use the palette that is used during VBL-IRQ */
148 palette[i] = io[i * 2 + 0x180];
150 /* use palette that will be set during IRQ routine.
151 * we need to copy it here, because we don't call IRQ routine for every rendered frame,
152 * so the color registers are not set by IRQ routine for every frame.
154 palette[i] = render_palette[i];
158 /* get copper list start pointer */
159 copperlist = (io[COP1LCH] << 16) | io[COP1LCL];
161 print_error("Copper list pointer not initialized, please fix!\n");
165 #ifdef DEBUG_COPPERLIST
166 printf("Copper list reading from pointer: %06x\n", copperlist);
169 /* parse copper list */
174 if (++count == 100) {
175 print_error("Copper list does not seem to terminate, please fix!\n");
178 c1 = m68k_read_memory_16(copperlist);
179 c2 = m68k_read_memory_16(copperlist + 2);
180 #ifdef DEBUG_COPPERLIST
181 printf("%06x: C1=%04x C2=%04x\n", copperlist, c1, c2);
185 copperlist = (io[COP1LCH] << 16) | io[COP1LCL];
186 #ifdef DEBUG_COPPERLIST
187 printf("switching to 1st copperlist=%06x\n", copperlist);
192 copperlist = (io[COP2LCH] << 16) | io[COP2LCL];
193 #ifdef DEBUG_COPPERLIST
194 printf("switching to 2nd copperlist=%06x\n", copperlist);
200 #ifdef DEBUG_COPPERLIST
201 printf("MOVE 0xdff%03x = 0x%04x\n", c1, c2);
203 /* get bitplane pointers */
204 if (c1 >= BPL1PTH && c1 <= BPL1PTH + 32) {
206 bitplane[(c1 - BPL1PTH) / 4] = (bitplane[(c1 - BPL1PTH) / 4] & 0xffff0000) | c2;
208 bitplane[(c1 - BPL1PTH) / 4] = (bitplane[(c1 - BPL1PTH) / 4] & 0x0000ffff) | (c2 << 16);
210 /* get color registers */
211 if (c1 >= COLOR00 && c1 <= COLOR00 + 32) {
212 palette[(c1 - COLOR00) / 2] = c2;
216 print_error("We suppport no SKIP command in copper list, please fix!\n");
220 /* get new raster position.
221 * if the value is lower or equal, we add 256 lines
222 * we ignore column, since it is not relevant for this game.
224 row = (c1 >> 8) & ((c2 >> 8) | 0x80);
225 if (row < (last_row & 0xff))
227 #ifdef DEBUG_COPPERLIST
228 printf("WAIT row = 0x%02x & 0x%02x = %d\n", c1 >> 8, (c2 >> 8) | 0x80, row);
231 /* line relative to display window start */
232 line = row - diwstart;
233 /* continue: before display window start */
234 if (line <= last_line)
236 /* render up to height */
239 /* check if bitplane pointers are set */
240 #ifdef DEBUG_COPPERLIST
241 printf("Bitplanes:");
243 for (i = 0; i < 4; i++) {
244 #ifdef DEBUG_COPPERLIST
245 printf(" %06x", bitplane[i]);
247 if (bitplane[i] == 0 || bitplane[i] + width * height / 8 >= 0x80000) {
248 #ifdef DEBUG_COPPERLIST
251 print_error("Bitplane %d in copper list not set or out of range, please fix!\n", i);
254 bitmem[i] = memory + bitplane[i];
256 #ifdef DEBUG_COPPERLIST
259 /* render portion before WAIT line */
260 #ifdef DEBUG_COPPERLIST
261 printf("Render from line %d to line %d\n", last_line, line - 1);
263 #ifdef DEBUG_COPPERLIST
265 for (i = 0; i < 16; i++) {
266 printf(" %03x", palette[i] & 0xfff);
279 planar2chunky2(rgb, bitmem, palette, 4, width, from, to);
281 planar2chunky(rgb, bitmem, palette, 4, width, from, to);
283 /* done if we rendered up to height */
286 /* remeber for next wait command */