1// MIT License
2
3// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
4
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23#include "world.h"
24#include "map.h"
25
26#define PREVIEW_SIZE (TIC80_WIDTH * TIC80_HEIGHT * TIC_PALETTE_BPP / BITS_IN_BYTE)
27
28static void drawGrid(World* world)
29{
30 tic_mem* tic = world->tic;
31 Map* map = world->map;
32 u8 color = tic_color_grey;
33
34 for(s32 c = 0; c < TIC80_WIDTH; c += TIC_MAP_SCREEN_WIDTH)
35 tic_api_line(world->tic, c, 0, c, TIC80_HEIGHT, color);
36
37 for(s32 r = 0; r < TIC80_HEIGHT; r += TIC_MAP_SCREEN_HEIGHT)
38 tic_api_line(world->tic, 0, r, TIC80_WIDTH, r, color);
39
40 tic_api_rectb(world->tic, 0, 0, TIC80_WIDTH, TIC80_HEIGHT, color);
41
42 tic_rect rect = {0, 0, TIC80_WIDTH, TIC80_HEIGHT};
43
44 if(checkMousePos(world->studio, &rect))
45 {
46 setCursor(world->studio, tic_cursor_hand);
47
48 s32 mx = tic_api_mouse(tic).x;
49 s32 my = tic_api_mouse(tic).y;
50
51 if(checkMouseDown(world->studio, &rect, tic_mouse_left))
52 {
53 map->scroll.x = (mx - TIC_MAP_SCREEN_WIDTH/2) * TIC_SPRITESIZE;
54 map->scroll.y = (my - TIC_MAP_SCREEN_HEIGHT/2) * TIC_SPRITESIZE;
55 if(map->scroll.x < 0)
56 map->scroll.x += TIC_MAP_WIDTH * TIC_SPRITESIZE;
57 if(map->scroll.y < 0)
58 map->scroll.y += TIC_MAP_HEIGHT * TIC_SPRITESIZE;
59 }
60
61 if(checkMouseClick(world->studio, &rect, tic_mouse_left))
62 setStudioMode(world->studio, TIC_MAP_MODE);
63 }
64
65 s32 x = map->scroll.x / TIC_SPRITESIZE;
66 s32 y = map->scroll.y / TIC_SPRITESIZE;
67
68 tic_api_rectb(world->tic, x, y, TIC_MAP_SCREEN_WIDTH+1, TIC_MAP_SCREEN_HEIGHT+1, tic_color_red);
69
70 if(x >= TIC_MAP_WIDTH - TIC_MAP_SCREEN_WIDTH)
71 tic_api_rectb(world->tic, x - TIC_MAP_WIDTH, y, TIC_MAP_SCREEN_WIDTH+1, TIC_MAP_SCREEN_HEIGHT+1, tic_color_red);
72
73 if(y >= TIC_MAP_HEIGHT - TIC_MAP_SCREEN_HEIGHT)
74 tic_api_rectb(world->tic, x, y - TIC_MAP_HEIGHT, TIC_MAP_SCREEN_WIDTH+1, TIC_MAP_SCREEN_HEIGHT+1, tic_color_red);
75
76 if(x >= TIC_MAP_WIDTH - TIC_MAP_SCREEN_WIDTH && y >= TIC_MAP_HEIGHT - TIC_MAP_SCREEN_HEIGHT)
77 tic_api_rectb(world->tic, x - TIC_MAP_WIDTH, y - TIC_MAP_HEIGHT, TIC_MAP_SCREEN_WIDTH+1, TIC_MAP_SCREEN_HEIGHT+1, tic_color_red);
78}
79
80static void tick(World* world)
81{
82 tic_mem* tic = world->tic;
83
84 // process scroll
85 if(tic->ram->input.mouse.scrolly > 0)
86 {
87 setStudioMode(world->studio, TIC_MAP_MODE);
88 return;
89 }
90
91 if(keyWasPressed(world->studio, tic_key_tab)) setStudioMode(world->studio, TIC_MAP_MODE);
92
93 memcpy(&tic->ram->vram, world->preview, PREVIEW_SIZE);
94
95 VBANK(tic, 1)
96 {
97 tic_api_cls(tic, tic->ram->vram.vars.clear = tic_color_black);
98 memcpy(tic->ram->vram.palette.data, getConfig(world->studio)->cart->bank0.palette.vbank0.data, sizeof(tic_palette));
99 drawGrid(world);
100 }
101}
102
103static void scanline(tic_mem* tic, s32 row, void* data)
104{
105 World* world = data;
106 if(row == 0)
107 memcpy(&tic->ram->vram.palette, getBankPalette(world->studio, false), sizeof(tic_palette));
108}
109
110void initWorld(World* world, Studio* studio, Map* map)
111{
112 if(!world->preview)
113 world->preview = malloc(PREVIEW_SIZE);
114
115 *world = (World)
116 {
117 .studio = studio,
118 .tic = getMemory(studio),
119 .map = map,
120 .tick = tick,
121 .preview = world->preview,
122 .scanline = scanline,
123 };
124
125 memset(world->preview, 0, PREVIEW_SIZE);
126 s32 colors[TIC_PALETTE_SIZE];
127
128 for(s32 i = 0; i < TIC80_WIDTH * TIC80_HEIGHT; i++)
129 {
130 u8 index = getBankMap(world->studio)->data[i];
131
132 if(index)
133 {
134 memset(colors, 0, sizeof colors);
135
136 tic_tile* tile = &getBankTiles(world->studio)->data[index];
137
138 for(s32 p = 0; p < TIC_SPRITESIZE * TIC_SPRITESIZE; p++)
139 {
140 u8 color = tic_tool_peek4(tile, p);
141
142 if(color)
143 colors[color]++;
144 }
145
146 s32 max = 0;
147
148 for(s32 c = 0; c < COUNT_OF(colors); c++)
149 if(colors[c] > colors[max]) max = c;
150
151 tic_tool_poke4(world->preview, i, max);
152 }
153 }
154}
155
156void freeWorld(World* world)
157{
158 free(world->preview);
159 free(world);
160}