├── Encounter.7z ├── Encounter ├── Encounter.md ├── encounter-js.html ├── encounter.cwa ├── encounter.nfo ├── encounter.png ├── encounter.uw8 ├── index.html ├── js │ ├── controls.js │ ├── main.js │ ├── renderer.js │ └── utils.js ├── playground.png └── styles.css ├── Murkwood.tic.zip ├── README.md ├── Sapere-Aude-C64.zip ├── Sapere-Aude-C64 ├── sapere-aude.asm ├── sapere-aude.nfo ├── sapere-aude.png └── sapere-aude.prg ├── chaos_rose.zip ├── chaos_rose ├── Chaos_Rose.cwa ├── Chaos_Rose.nfo ├── Chaos_Rose.png └── Chaos_Rose.uw8 ├── dekabyte.zip ├── dekabyte ├── dekabyte.asm ├── dekabyte.nfo ├── dekabyte.png └── dekabyte.xex ├── dirt_race.zip ├── dirt_race ├── dirt_race.asm ├── dirt_race.nfo ├── dirt_race.png └── dirt_race.xex ├── graphite32.zip ├── graphite32 ├── graphite32.asm ├── graphite32.nfo ├── graphite32.png └── graphite32.xex ├── midnight_dream.zip ├── midnight_dream ├── Midnight_Dream.cwa ├── Midnight_Dream.nfo ├── Midnight_Dream.png └── Midnight_Dream.uw8 ├── murkwood.zip ├── murkwood ├── murkwood.asm ├── murkwood.nfo ├── murkwood.png ├── murkwood.xex ├── murkwood_safe_random.xex └── pal_notes.inc ├── parenthood.zip ├── parenthood ├── bonus │ ├── emba.jpg │ ├── with_eyes_no_show.asm │ └── with_eyes_no_show.xex ├── parenthood.asm ├── parenthood.nfo ├── parenthood.png └── parenthood.xex ├── phase_of_haze.zip ├── phase_of_haze ├── phase_of_haze.asm ├── phase_of_haze.nfo ├── phase_of_haze.png └── phase_of_haze.xex ├── rescue_on_mars!.zip ├── rescue_on_mars! ├── rescue_on_mars!.asm ├── rescue_on_mars!.nfo ├── rescue_on_mars!.png └── rescue_on_mars!.xex ├── stairs_in_the_sky.zip ├── stairs_in_the_sky ├── stairs_in_the_sky.asm ├── stairs_in_the_sky.nfo ├── stairs_in_the_sky.png └── stairs_in_the_sky.xex ├── sunrise8.zip ├── sunrise8 ├── sunrise8.asm ├── sunrise8.png ├── sunrise8.xex └── sunrise8b.nfo ├── thrive.zip ├── thrive ├── thrive.gif ├── thrive.lua ├── thrive.nfo └── thrive.tic ├── ukr.tic ├── urban_drift.zip └── urban_drift ├── index.html ├── js ├── controls.js ├── engine.js ├── main.js ├── renderer.js └── utils.js ├── styles.css ├── urban_drift.cwa ├── urban_drift.jpg ├── urban_drift.nfo ├── urban_drift.uw8 └── urban_drift_js_version.html /Encounter.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/Encounter.7z -------------------------------------------------------------------------------- /Encounter/Encounter.md: -------------------------------------------------------------------------------- 1 | # Encounter - 256 bytes intro for WASM MicroW8 fantasy console 2 | 3 | ## What is it? 4 | 5 | Attempt to bring a cinematic experience in 256 bytes. 6 | 7 | ## Watch 8 | 9 | You can watch it on YouTube (recommended to select 720p60 quality) 10 | 11 | [![Watch the video](https://img.youtube.com/vi/4QY9WqbS61g/maxresdefault.jpg)](https://www.youtube.com/watch?v=4QY9WqbS61g) 12 | 13 | or click the following link if you have the FireFox browser (Chrome’s implementation of WebAssembly has much worse performance). Mobile Firefox should also work well on relatively new mobile phones. The 256 bytes are encoded in the URL: 14 | 15 | [https://exoticorn.github.io/microw8/v0.2.2/#AgMvvqs+jH95brXMAYjUjZwn1apTrm62ncvO+qq+kAesx0vh5NB3sa3YEg8JasHVk0OOFeN09Qi/yWyEuuIHweJv5+qt4lQhS0q/exKHo4rtSsnqkY7oWUwXXgbWfGEwKrTto4wxOG4JXZck7ehBB9YHmyanOZxFZeCkpib2M/JXhCmCfPb3mF6tq++ZG2Mm73NopaaKwUFHm2KjpEjYFMEzCZsu98uZmvhD5GzCUXSw8G5Z1V8nfv9uiIQ1+5N+rcjpFezbIXG5/haUR7Lnre3xZVJcp+I6rXkboKqK6SoG5h92w/jndB3sdZyT4G9Lq872lkEkUIM7ciqdsyYJMg==](https://exoticorn.github.io/microw8/v0.2.2/#AgMvvqs+jH95brXMAYjUjZwn1apTrm62ncvO+qq+kAesx0vh5NB3sa3YEg8JasHVk0OOFeN09Qi/yWyEuuIHweJv5+qt4lQhS0q/exKHo4rtSsnqkY7oWUwXXgbWfGEwKrTto4wxOG4JXZck7ehBB9YHmyanOZxFZeCkpib2M/JXhCmCfPb3mF6tq++ZG2Mm73NopaaKwUFHm2KjpEjYFMEzCZsu98uZmvhD5GzCUXSw8G5Z1V8nfv9uiIQ1+5N+rcjpFezbIXG5/haUR7Lnre3xZVJcp+I6rXkboKqK6SoG5h92w/jndB3sdZyT4G9Lq872lkEkUIM7ciqdsyYJMg==) 16 | 17 | I personally love seeing creative process of the others (“making of”) and If you are interested in the steps I went through to create this intro, check the following recording: 18 | 19 | [![Watch the video](https://img.youtube.com/vi/X-g7d5NUV2s/mqdefault.jpg)](https://youtu.be/X-g7d5NUV2s) 20 | 21 | ## Play 22 | 23 | I added also a **[JavaScript playground](https://ilmenit.github.io/sizecoding/Encounter/index.html)** so you can play with different parameters of this effect. 24 | 25 | [![Enter playground](https://github.com/ilmenit/sizecoding/blob/f95de6823d48975adc001a81a289e7a960ac2bfe/Encounter/playground.png)](https://ilmenit.github.io/sizecoding/Encounter/index.html) 26 | 27 | ## Why? 28 | 29 | I love intellectual challenges, art, computer science and in May 2024 there was another [Outline demoscene party](https://outlinedemoparty.nl) with size-coding competition. I did some 256 byte intros in the past (like drawing **[Mona Lisa](https://www.pouet.net/prod.php?which=62917)** for 6502 8bit Atari, ported to a [crazy number of platforms](https://codegolf.stackexchange.com/questions/126738/lets-draw-mona-lisa) or **[Thrive](https://www.pouet.net/prod.php?which=91578)** for TIC-80 showing a [growing tree through the seasons](https://youtu.be/qU5EGLvFXd8)), so I decided to join the competition once again. 30 | 31 | If you don’t know what a demoscene is, it’s a computer subculture with roots in Europe [https://en.wikipedia.org/wiki/Demoscene](https://en.wikipedia.org/wiki/Demoscene) similar to [Hacker Camps](https://hackaday.com/2022/06/06/outline-2022-everyone-should-go-to-a-demo-party/). 32 | 33 | A large collection of demoscene productions you can find on [https://demozoo.org](https://demozoo.org/) or [https://www.pouet.net](https://www.pouet.net/) 34 | 35 | ## How? 36 | 37 | The intro is done for [MicroW8](https://exoticorn.github.io/microw8) platform, which is a [Fantasy Console](https://en.wikipedia.org/wiki/Fantasy_video_game_console) similar to [PICO-8](https://www.lexaloffle.com/pico-8.php), [TIC-80](https://tic80.com/) or [WASM-4](https://wasm4.org). 38 | 39 | MicroW8 has capabilities close to DOS-era machines (16 bit real-mode x86 with FPU and VGA): 40 | 41 | * Screen: 320x240, 256 colors, 60Hz, customizable palette. 42 | * Memory: 256KB 43 | 44 | but with a MUCH faster CPU powered by WebAssembly (therefore more like running nowadays [FreeDOS](https://www.freedos.org) on a modern PC). 45 | 46 | Important note: the compiled “virtual cartridge” is compressed, therefore 256 bytes is not equal to 256 bytes of WASM code. The WASM code needs to be interconnected with the MicroW8 platform and the compression negates this overhead, leading to (according to sizecoding gurus) “code density” in 256 bytes similar to uncompressed x86/FPU code. The compression brings more benefits the bigger the code/data is, however in x86 you can also make tiny code decompressors, that you cannot do easily in WebAssembly due to executable code space separation, therefore for size-constrained programming DOS with x86 and [all the tricks it offers](http://www.sizecoding.org/wiki/DOS) can still be the king. 47 | 48 | ## Commented code 49 | 50 | WebAssembly is a stack-based virtual machine, which makes it easy to represent as an Abstract Syntax Tree or… in infix syntax. That’s the idea behind [CurlyWAS language](https://github.com/exoticorn/curlywas), that compiles Rust-like syntax into a WASM code. 51 | 52 | CurlyWAS has ability to use keywords like “inline” (expression is evaluated every time, works similarly to C’s #define), or “lazy” (which uses the local.tee instruction which combines local.set and local.get and therefore saves on bytes). 53 | 54 | In WebAssembly the 32bit integers are encoded in [LEB128 format](https://en.wikipedia.org/wiki/LEB128) and CurlyWAS has sugar syntax of adding _f to a constant to convert integer to 32bit float: 55 | 56 | (320_f) is equal to (320 as f32) 57 | 58 | ``` 59 | include "include/microw8-api.cwa" 60 | 61 | export fn upd() { 62 | 63 | let fx: f32; 64 | let prev_wave_height: f32; 65 | let inline t: f32 = time(); 66 | 67 | let inline screen_width = 320_f; 68 | let inline screen_height = 240_f; // 256_f shorter but bit slower 69 | 70 | loop xloop { 71 | 72 | let fy: f32 = 0_f; 73 | loop yloop { 74 | 75 | // define the vanishing point coordinates 76 | let inline vp_x: f32 = 160_f; // center of the screen 77 | let inline vp_y: f32 = 120.5; // horizon, +0.5 to avoid div by 0 78 | 79 | // define the distance 80 | let inline d: f32 = 160_f; 81 | 82 | // calculate the distance from the center 83 | let inline cx: f32 = vp_x - fx; 84 | let inline cy: f32 = vp_y - fy; 85 | 86 | // calculate the angle mapping 87 | let inline nx: f32 = cx / 2_f / cy; 88 | let inline ny: f32 = d * 2_f / cy; 89 | 90 | // A variable to store the total height 91 | let wave_height = cos(fx*fy)*max(0_f,t-80_f); // matrix-like effect at the end 92 | 93 | // Calculate the height of the superposition of waves at a given position and time 94 | let i: f32=0_f; 95 | 96 | // select either water or sky 97 | let inline iterations: f32 = select(fy<120_f,4_f,16_f); 98 | 99 | loop wave_iterations { 100 | 101 | let inline amplitude = i/40_f; 102 | let inline frequency = 2_f+cos(i); 103 | let inline phase = cos(i*i); 104 | // dx and dy are the components of the direction of the wave 105 | let inline dx = sin(i*i); // serves as PRNG 106 | let inline dy = cos(i*i*i); // serves as PRNG 107 | let inline time_shift = t/14_f*iterations; 108 | 109 | wave_height -= amplitude * (abs(sin(frequency * (ny * dy + nx * dx) + time_shift + phase))); 110 | 111 | branch_if (i := i + 1_f) < iterations: wave_iterations; 112 | } 113 | let inline dist = sqrt(cx*cx + cy*cy); 114 | 115 | // how big are waves in time 116 | let inline wave_scale = min(2_f*t,40_f); 117 | let inline perspective_height = wave_height * wave_scale * cy / d; 118 | 119 | // minimalistic water reflection+refraction 120 | let inline h_color: f32 = 1_f-abs(perspective_height-prev_wave_height)/6_f; 121 | 122 | // alien blob/ship 123 | let inline radius = min(2_f*t-70_f,50_f); 124 | let inline blob_color = dist/radius; 125 | let inline color: f32 = select(dist 2 | 3 | 4 | MicroW8 Wave Effect 5 | 19 | 20 | 21 | 22 | 156 | 157 | -------------------------------------------------------------------------------- /Encounter/encounter.cwa: -------------------------------------------------------------------------------- 1 | include "include/microw8-api.cwa" 2 | 3 | export fn upd() { 4 | let fx: f32; 5 | let prev_wave_height: f32; 6 | 7 | let inline t: f32 = time(); 8 | 9 | let inline screen_width = 320_f; 10 | let inline screen_height = 240_f; // 256_f shorter but bit slower 11 | 12 | loop xloop { 13 | let fy: f32 = 0_f; 14 | 15 | loop yloop { 16 | 17 | // define the vanishing point coordinates 18 | let inline vp_x: f32 = 160_f; // center of the screen 19 | let inline vp_y: f32 = 120.5; // horizon, +0.5 to avoid div by 0 20 | 21 | // define the distance 22 | let inline d: f32 = 160_f; 23 | 24 | // calculate the distance from the center 25 | let inline cx: f32 = vp_x - fx; 26 | let lazy cy: f32 = vp_y - fy; 27 | 28 | // calculate the angle mapping 29 | let inline nx: f32 = cx / cy / 2_f; 30 | let inline ny: f32 = 320_f / cy; 31 | 32 | let lazy dist = sqrt(cx*cx + cy*cy); 33 | 34 | // A variable to store the total height 35 | let wave_height = sin(40_f*dist)*max(0_f,t/2_f-40_f); // effect at the end 36 | 37 | // Calculate the height of the superposition of waves at a given position and time 38 | let i: f32=0_f; 39 | 40 | // select either water or sky 41 | let inline iterations: f32 = select(fy<120_f,4_f,16_f); 42 | loop wave_iterations { 43 | let inline amplitude = i/40_f; 44 | let inline frequency = 2_f+cos(i); 45 | // dx and dy are the components of the direction of the wave 46 | let inline dx = sin(i*i); 47 | let inline dy = cos(i*i*i); 48 | let inline time_shift = t/14_f*iterations; 49 | wave_height -= amplitude * (abs(sin(frequency * (ny * dy + nx * dx) + time_shift))); 50 | branch_if (i := i + 1_f) < iterations: wave_iterations; 51 | } 52 | 53 | 54 | // how big the waves are in time 55 | let inline wave_scale = min(2_f*t,40_f); 56 | let lazy perspective_height = wave_height * wave_scale * cy / d; // + cx/(80_f-wave_scale)*sin(t); // for some waving 57 | 58 | // minimalistic water reflection+refraction 59 | let inline h_color: f32 = 1_f-abs(perspective_height-prev_wave_height)/6_f; 60 | 61 | // alien blob/ship 62 | let inline radius = min(2_f*t-70_f,50_f); 63 | let inline blob_color = dist/radius; 64 | let inline color: f32 = select(dist 2 | 3 | 4 | Ocean Wave Effect 5 | 6 | 7 | 8 |
9 |
10 |

Resolution & View Mode

11 |
12 | 13 | 19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | 27 | 1.0 28 |
29 |
30 | 31 |
32 |

Time Control

33 |
34 | 35 | 36 |
37 |
38 | 39 | 40 | 0s 41 |
42 |
43 | 44 |
45 |

Effects

46 |
47 | 48 | 49 |
50 |
51 | 52 | 53 |
54 |
55 | 56 | 57 |
58 |
59 | 60 | 61 |
62 |
63 | 64 |
65 |

Wave Parameters

66 |
67 | 68 | 69 | 16 70 |
71 |
72 | 73 | 74 | 4 75 |
76 |
77 | 78 | 79 | 40 80 |
81 |
82 | 83 | 84 | 2.0 85 |
86 |
87 | 88 | 89 | 40 90 |
91 |
92 |
93 | 94 |
95 | 96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /Encounter/js/controls.js: -------------------------------------------------------------------------------- 1 | class Controls { 2 | constructor() { 3 | this.settings = { ...CONFIG.defaults }; 4 | this.initializeControls(); 5 | this.setupEventListeners(); 6 | } 7 | 8 | initializeControls() { 9 | this.elements = { 10 | resolution: document.getElementById('resolution'), 11 | autoTime: document.getElementById('auto-time'), 12 | currentTime: document.getElementById('current-time'), 13 | showHeightmap: document.getElementById('show-heightmap'), 14 | showBlob: document.getElementById('show-blob'), 15 | showVignette: document.getElementById('show-vignette'), 16 | showFilmGrain: document.getElementById('show-film-grain'), 17 | showEndingEffect: document.getElementById('show-ending-effect'), 18 | waterIterations: document.getElementById('water-iterations'), 19 | skyIterations: document.getElementById('sky-iterations'), 20 | waveAmplitude: document.getElementById('wave-amplitude'), 21 | waveFrequency: document.getElementById('wave-frequency'), 22 | heightmapZoom: document.getElementById('heightmap-zoom'), 23 | }; 24 | 25 | // Initialize all controls with default values 26 | Object.entries(this.elements).forEach(([key, element]) => { 27 | if (element) { 28 | const settingKey = this.getSettingKey(element.id); 29 | const defaultValue = this.settings[settingKey]; 30 | 31 | if (element.type === 'checkbox') { 32 | element.checked = defaultValue; 33 | } else if (element.type === 'range') { 34 | element.value = defaultValue; 35 | const display = element.nextElementSibling; 36 | if (display) { 37 | display.textContent = this.formatValue(element.id, Number(defaultValue)); 38 | } 39 | } else if (element.tagName === 'SELECT') { 40 | const defaultRes = `${defaultValue.width}x${defaultValue.height}`; 41 | element.value = defaultRes; 42 | } 43 | } 44 | }); 45 | 46 | this.updateDisabledStates(); 47 | } 48 | 49 | setupEventListeners() { 50 | document.querySelectorAll('input[type="range"]').forEach(input => { 51 | const display = input.nextElementSibling; 52 | if (display) { 53 | input.addEventListener('input', () => { 54 | const value = Number(input.value); 55 | display.textContent = this.formatValue(input.id, value); 56 | this.updateSetting(input.id, value); 57 | }); 58 | } 59 | }); 60 | 61 | document.querySelectorAll('input[type="checkbox"], select').forEach(input => { 62 | input.addEventListener('change', () => { 63 | const value = input.type === 'checkbox' ? input.checked : input.value; 64 | this.updateSetting(input.id, value); 65 | if (input.id === 'auto-time') { 66 | if (input.checked) { 67 | startTime = performance.now() - (this.settings.currentTime * 1000); 68 | } 69 | this.updateDisabledStates(); 70 | } else if (input.id === 'show-heightmap') { 71 | this.updateDisabledStates(); 72 | } 73 | }); 74 | }); 75 | } 76 | 77 | formatValue(id, value) { 78 | const numValue = Number(value); 79 | switch(id) { 80 | case 'current-time': 81 | return numValue + 's'; 82 | case 'wave-frequency': 83 | case 'heightmap-zoom': 84 | return numValue.toFixed(1); 85 | default: 86 | return numValue.toString(); 87 | } 88 | } 89 | 90 | updateSetting(id, value) { 91 | if (id === 'resolution') { 92 | const [width, height] = value.split('x').map(Number); 93 | this.settings.resolution = { width, height }; 94 | if (app && app.renderer) { 95 | app.renderer.resize(width, height); 96 | } 97 | return; 98 | } 99 | 100 | const settingKey = this.getSettingKey(id); 101 | this.settings[settingKey] = value; 102 | } 103 | 104 | getSettingKey(id) { 105 | return id.replace(/-([a-z])/g, g => g[1].toUpperCase()); 106 | } 107 | 108 | updateDisabledStates() { 109 | if (this.elements.currentTime) { 110 | this.elements.currentTime.disabled = this.elements.autoTime.checked; 111 | } 112 | 113 | // Control heightmap zoom 114 | if (this.elements.heightmapZoom) { 115 | this.elements.heightmapZoom.disabled = !this.elements.showHeightmap.checked; 116 | } 117 | } 118 | 119 | getSettings() { 120 | return { ...this.settings }; 121 | } 122 | } -------------------------------------------------------------------------------- /Encounter/js/main.js: -------------------------------------------------------------------------------- 1 | class App { 2 | constructor() { 3 | this.canvas = document.getElementById('screen'); 4 | this.controls = new Controls(); 5 | this.renderer = new Renderer(this.canvas); 6 | 7 | requestAnimationFrame(this.render.bind(this)); 8 | } 9 | 10 | render() { 11 | this.renderer.render(this.controls.getSettings()); 12 | requestAnimationFrame(this.render.bind(this)); 13 | } 14 | } 15 | 16 | // Global app instance 17 | let app; 18 | 19 | window.addEventListener('load', () => { 20 | app = new App(); 21 | }); -------------------------------------------------------------------------------- /Encounter/js/renderer.js: -------------------------------------------------------------------------------- 1 | class Renderer { 2 | constructor(canvas) { 3 | this.canvas = canvas; 4 | this.ctx = canvas.getContext('2d'); 5 | this.palette = new Uint32Array(256); 6 | this.updatePalette(); 7 | this.resize(CONFIG.defaults.resolution.width, CONFIG.defaults.resolution.height); 8 | } 9 | 10 | resize(width, height) { 11 | this.width = width; 12 | this.height = height; 13 | this.canvas.width = width; 14 | this.canvas.height = height; 15 | this.centerX = this.width / 2; 16 | this.centerY = this.height / 2; 17 | this.baseScale = Math.sqrt((this.width * this.height) / (320 * 240)); 18 | this.imageData = this.ctx.createImageData(width, height); 19 | this.data = this.imageData.data; 20 | this.ctx.clearRect(0, 0, width, height); 21 | } 22 | 23 | updatePalette() { 24 | for (let i = 0; i < 32; i++) { 25 | const step = i * 0x203; 26 | for (let j = 0; j < 4; j++) { 27 | const idx = i * 4 + j; 28 | this.palette[idx] = 29 | ((step & 0xFF0000) << 8) | 30 | ((step & 0x00FF00) << 8) | 31 | ((step & 0x0000FF) << 8) | 32 | 0xFF; 33 | } 34 | } 35 | 36 | const lastStep = 31 * 0x203; 37 | const lastR = (lastStep & 0xFF0000) >> 16; 38 | const lastG = (lastStep & 0x00FF00) >> 8; 39 | const lastB = lastStep & 0x0000FF; 40 | 41 | for (let i = 128; i < 256; i++) { 42 | const t = (i - 128) / 127; 43 | const r = Math.floor(lastR + t * (0xFF - lastR)); 44 | const g = Math.floor(lastG + t * (0xFF - lastG)); 45 | const b = Math.floor(lastB + t * (0xE0 - lastB)); 46 | const color = (r << 16) | (g << 8) | b; 47 | this.palette[i] = 48 | ((color & 0xFF0000) << 8) | 49 | ((color & 0x00FF00) << 8) | 50 | ((color & 0x0000FF) << 8) | 51 | 0xFF; 52 | } 53 | } 54 | 55 | line(x, y1, y2, color) { 56 | const xx = Math.floor(x); 57 | const startY = Math.floor(Math.min(y1, y2)); 58 | const endY = Math.ceil(Math.max(y1, y2)); 59 | 60 | if (xx < 0 || xx >= this.width) return; 61 | 62 | for (let y = startY; y <= endY; y++) { 63 | if (y >= 0 && y < this.height) { 64 | const idx = (y * this.width + xx) * 4; 65 | const paletteColor = this.palette[color & 0xFF]; 66 | this.data[idx] = (paletteColor >> 24) & 0xFF; // R 67 | this.data[idx + 1] = (paletteColor >> 16) & 0xFF; // G 68 | this.data[idx + 2] = (paletteColor >> 8) & 0xFF; // B 69 | this.data[idx + 3] = paletteColor & 0xFF; // A 70 | } 71 | } 72 | } 73 | 74 | calculateWaveHeight(fx, fy, t, settings) { 75 | if (settings.showHeightmap) { 76 | // For heightmap view, calculate direct 2D mapping with zoom 77 | const zoom = settings.heightmapZoom; 78 | const dx = (fx - this.centerX) * zoom; 79 | const dy = (fy - this.centerY) * zoom; 80 | const dist = Math.sqrt(dx * dx + dy * dy); 81 | 82 | let wave_height = 0; 83 | 84 | // Add ending effect if enabled 85 | if (settings.showEndingEffect) { 86 | wave_height = Math.sin(settings.waveAmplitude * dist) * Math.max(0, t/2-40); 87 | } 88 | 89 | // Use same iterations for both sky and water in heightmap mode 90 | const iterations = settings.waterIterations; 91 | for (let i = 0; i < iterations; i++) { 92 | const amplitude = (i * settings.waveAmplitude) / 1000; 93 | const frequency = settings.waveFrequency + Math.cos(i); 94 | const wave_dx = Math.sin(i*i); 95 | const wave_dy = Math.cos(i*i*i); 96 | const time_shift = t/14*iterations; 97 | wave_height += amplitude * Math.sin( 98 | (frequency * ((fy * zoom/this.height) * wave_dy + (fx * zoom/this.width) * wave_dx)) + time_shift 99 | ); 100 | } 101 | 102 | return wave_height; 103 | } else { 104 | // For perspective view 105 | const vp_x = this.centerX; 106 | const vp_y = this.centerY + 0.5; 107 | const d = this.centerX; 108 | const cx = vp_x - fx; 109 | const cy = vp_y - fy; 110 | const nx = cx / cy / 2; 111 | const ny = this.width / cy; 112 | const dist = Math.sqrt(cx*cx + cy*cy); 113 | 114 | let wave_height = 0; 115 | 116 | // Add ending effect if enabled 117 | if (settings.showEndingEffect) { 118 | wave_height = Math.sin(settings.waveAmplitude * dist / this.baseScale) * Math.max(0, t/2-40); 119 | } 120 | 121 | // Add wave iterations 122 | const iterations = fy < this.centerY ? settings.skyIterations : settings.waterIterations; 123 | for (let i = 0; i < iterations; i++) { 124 | const amplitude = (i * settings.waveAmplitude) / 1000; 125 | const frequency = settings.waveFrequency + Math.cos(i); 126 | const dx = Math.sin(i*i); 127 | const dy = Math.cos(i*i*i); 128 | const time_shift = t/14*iterations; 129 | wave_height -= amplitude * Math.abs(Math.sin( 130 | (frequency * (ny * dy + nx * dx)) + time_shift 131 | )); 132 | } 133 | 134 | return wave_height; 135 | } 136 | } 137 | 138 | render(settings) { 139 | const t = time(); 140 | this.updatePalette(); 141 | 142 | for (let fx = 0; fx < this.width; fx++) { 143 | let prev_wave_height = 0; 144 | 145 | for (let fy = 0; fy < this.height; fy++) { 146 | const wave_height = this.calculateWaveHeight(fx, fy, t, settings); 147 | const wave_scale = Math.min(2*t, settings.maxWaveScale); 148 | 149 | if (settings.showHeightmap) { 150 | // For heightmap, normalize the wave height to 0-255 range 151 | const normalized_height = (wave_height + 1) / 2; // Now properly maps -1 to 1 range to 0 to 1 152 | const final_color = Math.floor(Math.max(0, Math.min(255, normalized_height * 255))); 153 | this.line(fx, fy, fy, final_color); 154 | } else { 155 | // For perspective view 156 | const vp_x = this.centerX; 157 | const vp_y = this.centerY + 0.5; 158 | const d = this.centerX; 159 | const cx = vp_x - fx; 160 | const cy = vp_y - fy; 161 | const dist = Math.sqrt(cx*cx + cy*cy); 162 | 163 | const perspective_height = wave_height * wave_scale * cy / d; 164 | const h_color = 1 - Math.abs(perspective_height - prev_wave_height)/6; 165 | const radius = Math.min(2*t-70, 50); 166 | const blob_color = dist/radius; 167 | const color = (settings.showBlob && dist < radius) ? blob_color : h_color; 168 | 169 | let p_color; 170 | if (settings.showVignette) { 171 | p_color = Math.max(0, color + (cy - dist)/(512 * this.baseScale)); 172 | } else { 173 | p_color = color; 174 | } 175 | 176 | let final_color = Math.min(255, Math.floor(250 * p_color)); 177 | 178 | if (settings.showFilmGrain) { 179 | final_color += 6 * randomf(); 180 | } 181 | 182 | this.line( 183 | fx, 184 | fy + Math.floor(perspective_height), 185 | fy + Math.floor(prev_wave_height), 186 | Math.floor(final_color) 187 | ); 188 | 189 | prev_wave_height = perspective_height; 190 | } 191 | } 192 | } 193 | 194 | this.ctx.putImageData(this.imageData, 0, 0); 195 | } 196 | } -------------------------------------------------------------------------------- /Encounter/js/utils.js: -------------------------------------------------------------------------------- 1 | const CONFIG = { 2 | defaults: { 3 | resolution: { width: 320, height: 240 }, 4 | autoTime: true, 5 | currentTime: 0, 6 | showBlob: true, 7 | showVignette: true, 8 | showFilmGrain: true, 9 | showEndingEffect: true, 10 | waterIterations: 16, 11 | skyIterations: 4, 12 | waveAmplitude: 40, 13 | waveFrequency: 2, 14 | maxWaveScale: 40, 15 | showHeightmap: false, 16 | heightmapZoom: 1 17 | } 18 | }; 19 | 20 | let startTime = performance.now(); 21 | 22 | function randomf() { 23 | return Math.random(); 24 | } 25 | 26 | function time() { 27 | if (app && app.controls) { 28 | if (!app.controls.settings.autoTime) { 29 | return Number(app.controls.settings.currentTime); 30 | } 31 | } 32 | return (performance.now() - startTime) / 1000; 33 | } -------------------------------------------------------------------------------- /Encounter/playground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/Encounter/playground.png -------------------------------------------------------------------------------- /Encounter/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | background: #1a1a1a; 5 | color: #fff; 6 | font-family: system-ui, -apple-system, sans-serif; 7 | min-height: 100vh; 8 | display: flex; 9 | overflow: hidden; 10 | } 11 | 12 | .controls { 13 | background: #2a2a2a; 14 | padding: 16px; 15 | width: 320px; 16 | min-width: 320px; 17 | height: 100vh; 18 | overflow-y: auto; 19 | display: flex; 20 | flex-direction: column; 21 | gap: 16px; 22 | box-shadow: 2px 0 10px rgba(0, 0, 0, 0.3); 23 | } 24 | 25 | .control-group { 26 | display: flex; 27 | flex-direction: column; 28 | gap: 8px; 29 | padding: 12px; 30 | background: #333; 31 | border-radius: 6px; 32 | } 33 | 34 | .control-group h3 { 35 | margin: 0 0 8px 0; 36 | font-size: 14px; 37 | color: #aaa; 38 | font-weight: 600; 39 | text-transform: uppercase; 40 | letter-spacing: 0.5px; 41 | } 42 | 43 | .control-row { 44 | display: flex; 45 | align-items: center; 46 | gap: 8px; 47 | } 48 | 49 | select, input[type="range"] { 50 | background: #444; 51 | border: 1px solid #555; 52 | color: #fff; 53 | padding: 4px 8px; 54 | border-radius: 4px; 55 | font-size: 14px; 56 | } 57 | 58 | select { 59 | width: 120px; 60 | } 61 | 62 | input[type="range"] { 63 | flex: 1; 64 | } 65 | 66 | input[type="checkbox"] { 67 | margin: 0; 68 | width: 16px; 69 | height: 16px; 70 | } 71 | 72 | label { 73 | font-size: 14px; 74 | min-width: 100px; 75 | } 76 | 77 | .value-display { 78 | font-size: 14px; 79 | color: #aaa; 80 | min-width: 45px; 81 | text-align: right; 82 | } 83 | 84 | .canvas-container { 85 | flex: 1; 86 | display: flex; 87 | justify-content: center; 88 | align-items: center; 89 | background: #000; 90 | padding: 16px; 91 | } 92 | 93 | canvas { 94 | image-rendering: pixelated; 95 | max-width: 100%; 96 | max-height: 100%; 97 | aspect-ratio: 4/3; 98 | object-fit: contain; 99 | } 100 | 101 | /* Scrollbar styling */ 102 | .controls::-webkit-scrollbar { 103 | width: 8px; 104 | } 105 | 106 | .controls::-webkit-scrollbar-track { 107 | background: #1a1a1a; 108 | } 109 | 110 | .controls::-webkit-scrollbar-thumb { 111 | background: #444; 112 | border-radius: 4px; 113 | } 114 | 115 | .controls::-webkit-scrollbar-thumb:hover { 116 | background: #555; 117 | } -------------------------------------------------------------------------------- /Murkwood.tic.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/Murkwood.tic.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Hello sizecoding world! 2 | -------------------------------------------------------------------------------- /Sapere-Aude-C64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/Sapere-Aude-C64.zip -------------------------------------------------------------------------------- /Sapere-Aude-C64/sapere-aude.asm: -------------------------------------------------------------------------------- 1 | ; @com.wudsn.ide.asm.hardware=C64 2 | 3 | ; My very first intro for C64, for Outline 2021 4 | ; Why C64? Well... there are not enough tiny intros for this platform! 5 | ; By the Compo Rules header size is not counted into the final size. Without the header it is 256 bytes. 6 | ; I used therefore 'safe header' (according to my limited C64 knowledge) 7 | ; 8 | ; The intro is not very well optimized, but I had limited time before the party deadline. 9 | ; With more optimizations I believe a better music could fit. 10 | ; 11 | ; Done in MADS Assembler but should easily work with any other. 12 | ; 13 | ; Ilmenit / Agenda, May 2021 14 | 15 | SIDV3FREQLO = $d40e 16 | SIDV3FREQHI = $d40f 17 | SIDV3PWLO = $d410 18 | SIDV3PWHI = $d411 19 | SIDV3CTRL = $d412 20 | SIDV3AD = $d413 21 | SIDV3SR = $d414 22 | 23 | SIDFCLO = $d415 24 | SIDFCHI = $d416 25 | 26 | SIDRESFILT = $d417 27 | SIDMODEVOL = $d418 ; Mute3/ HiPass/ BandPass/ LowPass | Main Volume 0-15 28 | 29 | 30 | SCR_CTRL equ $D011 31 | VIC_CTRL equ $D016 32 | MEM_SETUP equ $D018 33 | BORDER_COLOR equ $D020 34 | BACKGROUND_COLOR equ $D021 35 | COLOR0 equ $D022 36 | COLOR1 equ $D023 37 | COLOR2 equ $D024 38 | FONT_RAM equ $3000 39 | DITHER_SHIFTED equ 0 40 | 41 | ;TIMER_SLOW equ $A1 42 | ;TIMER_FAST equ $A2 43 | NOTE_ID equ $FB 44 | TIMER equ $FC 45 | TIMER_SLOW equ $c2 46 | TIMER_FAST equ $c3 47 | 48 | EOR_VALUE equ $2 49 | temp equ $3 50 | Y_VALUE equ $87 51 | sine equ $5 52 | 53 | ADRESS equ $BB 54 | 55 | SCREEN equ $400 56 | 57 | opt h-f+ ;Disable ATARI headers, enable fill mode (no memory gaps) 58 | 59 | org $0801-2 60 | .word load ;BASIC load address 61 | 62 | ;BASIC Tokens for "10 SYS2061" 63 | load 64 | .word nextline 65 | .word 10 66 | .byte $9e, '2061', 0 67 | nextline 68 | .word 0 69 | 70 | ;start = $080d = 2061 71 | 72 | start 73 | 74 | .local init_sid 75 | lda #15 76 | sta NOTE_ID 77 | sta SIDMODEVOL 78 | sta TIMER 79 | 80 | ; lda #$F0 81 | ; sta SIDV3SR 82 | lda #$2B 83 | sta SIDV3AD 84 | 85 | .endl 86 | 87 | lda #%11011000 ; turn on multicolor mode 88 | sta VIC_CTRL 89 | 90 | lda #(%00010000 | %1100) ; keep memory at $400 (%00010000) and select character set to $3000 (%1100) 91 | sta MEM_SETUP 92 | 93 | ;;;;;;;;;;; CLEAR FONT MEMORY 94 | ldx #0 ; TAX 95 | stx BACKGROUND_COLOR 96 | stx BORDER_COLOR 97 | txa 98 | loop0 99 | sta FONT_RAM+$80,x 100 | dex 101 | bne loop0 102 | 103 | .local make_chars 104 | loop: 105 | txa ; a has byte index 106 | .if DITHER_SHIFTED = 1 107 | :2 lsr ; /4 108 | .else 109 | :3 lsr ; /8 110 | asl ; *2 111 | .endif 112 | tay ; y has dither_index 113 | txa ; a has byte index 114 | ror ; move lowest bit to carry 115 | bcc skip 116 | iny ; increase dither_index 117 | skip 118 | lda DITHER_DATA,y 119 | sta FONT_RAM,x 120 | inx 121 | bpl loop 122 | .endl 123 | 124 | ldx #$FF 125 | stx TIMER_SLOW 126 | stx TIMER_FAST 127 | 128 | NEXT_FRAME: 129 | inc TIMER_FAST 130 | bne skip_sine_generation 131 | 132 | inc COLOR1 133 | 134 | .local gen_sine 135 | ; X=FF, Y=0 136 | 137 | inc TIMER_SLOW 138 | lda TIMER_SLOW 139 | and #15 140 | tay 141 | lda nice_patterns,y 142 | sta EOR_VALUE 143 | 144 | txa 145 | ; a=ff 146 | ldy #Y_VALUE 147 | loop1: 148 | dex 149 | loop2: 150 | sta sine-1,y 151 | eor EOR_VALUE 152 | dey 153 | beq exit_loops 154 | stx temp 155 | adc temp 156 | bmi loop1 157 | inx 158 | jmp loop2 159 | exit_loops: 160 | .endl 161 | skip_sine_generation 162 | 163 | dec timer 164 | bne exit_irq 165 | 166 | lda note_id 167 | inc note_id 168 | and #7 169 | tax 170 | 171 | asl SIDV3CTRL 172 | 173 | lda freqlotab,x 174 | sta SIDV3FREQLO 175 | lda freqhitab,x 176 | sta SIDV3FREQHI 177 | 178 | lda #$21 179 | sta SIDV3CTRL 180 | 181 | lda dt,x 182 | sta timer 183 | 184 | exit_irq: 185 | 186 | ; end of the screen 187 | lda #$07 188 | sta ADRESS+1 189 | lda #$97 190 | sta ADRESS 191 | 192 | 193 | ldx #24 ; row 194 | NEXT_ROW: 195 | LDA ADRESS 196 | SEC 197 | SBC #40 198 | STA ADRESS 199 | BCS skip ;if no borrow 200 | DEC ADRESS+1 ;adjust high byte 201 | skip 202 | 203 | ldy #40 ; column 204 | 205 | ROW_LOOP: 206 | lda TIMER_FAST 207 | adc sine,y 208 | adc sine,x 209 | and #$1F 210 | sta (adress),y 211 | dey 212 | bne ROW_LOOP 213 | dex 214 | bpl NEXT_ROW 215 | bmi NEXT_FRAME 216 | 217 | DITHER_DATA ; 32 bytes 218 | c0 219 | .byte %00000000 220 | .byte %00000000 221 | 222 | .byte %01000000 ; $40 223 | .byte %00000100 ; $4 224 | 225 | .byte %00010001 ; $11 226 | .byte %01000100 ; $44 227 | 228 | .byte %00010101 ; $15 229 | .byte %01010001 ; $51 230 | 231 | c1 232 | .byte %01010101 233 | .byte %01010101 234 | 235 | .byte %10010101 236 | .byte %01011001 237 | 238 | .byte %01100110 239 | .byte %10011001 240 | 241 | .byte %01101010 242 | .byte %10100110 243 | c2 244 | .byte %10101010 245 | .byte %10101010 246 | 247 | .byte %11101010 248 | .byte %10101110 249 | 250 | .byte %10111011 251 | .byte %11101110 252 | 253 | .byte %10111111 254 | .byte %11111011 255 | c3 256 | .byte %11111111 257 | .byte %11111111 258 | 259 | ; dither back to c0 260 | .byte %00111111 261 | .byte %11110011 262 | 263 | .byte %11001100 264 | .byte %00110011 265 | 266 | .byte %11000000 267 | .byte %00001100 268 | 269 | .if DITHER_SHIFTED = 1 270 | ; filler 271 | .byte %00000000 272 | .endif 273 | 274 | 275 | ; D#2, C2, G2, G2, D#2, C2, A#2, F2 276 | freqlotab 277 | dta 251,48,71,251,48,119,152,0 278 | freqhitab 279 | dta 4,4,6,4,4,7,5,0 280 | 281 | dt 282 | dta 75,89,118,75,89,89,89,1 283 | 284 | nice_patterns: ; 16 285 | .byte $80 286 | .byte $82 287 | .byte $83 288 | .byte $f8 289 | 290 | .byte $40 291 | .byte $10 292 | .byte $11 293 | .byte $12 294 | 295 | .byte $c2 296 | .byte $74 297 | .byte $f1 298 | .byte $e2 299 | 300 | .byte $60 301 | .byte $5f 302 | .byte $51 303 | .byte $00 304 | 305 | 306 | .print "TOTAL: ", *-start -------------------------------------------------------------------------------- /Sapere-Aude-C64/sapere-aude.nfo: -------------------------------------------------------------------------------- 1 | "Sapere Aude" - dare to know things 2 | 3 | My very first intro for C64. 4 | 5 | Why C64? Well... there are not enough tiny intros for this platform! 6 | By Compo Rules header is not counted into the final size. Without the header 7 | it is 256 bytes. I used safe header "SYS2061" that has 14 bytes. 8 | 9 | The main effect code base on my previous 64 byte Atari intro "Unfolding". 10 | I'm not very happy with the repetitive tune but I had no time to optimize 11 | the code more (before the submission deadline) to squeeze there something 12 | more appealing. 13 | 14 | Greetings to all sizecoders! 15 | 16 | Ilmenit / Agenda 17 | Outline Party '2021 18 | -------------------------------------------------------------------------------- /Sapere-Aude-C64/sapere-aude.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/Sapere-Aude-C64/sapere-aude.png -------------------------------------------------------------------------------- /Sapere-Aude-C64/sapere-aude.prg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/Sapere-Aude-C64/sapere-aude.prg -------------------------------------------------------------------------------- /chaos_rose.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/chaos_rose.zip -------------------------------------------------------------------------------- /chaos_rose/Chaos_Rose.cwa: -------------------------------------------------------------------------------- 1 | include "include/microw8-api.cwa" 2 | 3 | global mut frame: i32 = 0; 4 | 5 | export fn upd() { 6 | cls(0); 7 | randomSeed(0); 8 | let factor: f32 = 56_f; 9 | let offsetX: f32 = 160_f; 10 | let offsetY: f32 = 120_f; 11 | let pi: f32 = 3.125; // 3.25 12 | let angle: f32 = (frame as f32) / 220_f; 13 | 14 | if !(frame % 31) { 15 | let inline channel: i32 = frame%3; 16 | let inline note = 48 + (frame*5 + frame/33)%8; 17 | playNote(channel, note); 18 | } 19 | frame = frame + 1; 20 | 21 | let x: f32; 22 | loop xloop { 23 | let t: f32=0_f; 24 | loop tloop { 25 | 26 | let lazy phi: f32 = 1.5 * exp(-t / 25_f) * max(1_f,10_f-angle); 27 | let p1: f32 = (1_f - (fmod((3.5 * t),6_f)) / pi); 28 | let p2: f32 = (1.25 * p1 * p1 - 0.25); 29 | let X: f32 = 1_f - p2 * p2 / 2_f; 30 | 31 | let p3: f32 = (1.125 * x - 1_f); 32 | let y: f32 = 2_f * x * x * p3 * p3 * sin(phi); 33 | 34 | let inline r: f32 = X * factor * (x * sin(phi) + y * cos(phi)) * max(1_f,10_f-angle); 35 | 36 | let pX: f32 = r * sin(t); 37 | let pY: f32 = r * cos(t); 38 | let pZ: f32 = X * factor * (x * cos(phi) - y * sin(phi)); 39 | let inline color: f32 = ((0x52) as f32) + pZ/4_f * max(1_f,10_f-angle); 40 | 41 | let inline xnew: f32 = offsetX + pX * cos(angle) - pY * sin(angle) + randomf()+ randomf(); 42 | let inline ynew: f32 = offsetY + pX * sin(angle) + pY * cos(angle) + randomf()+ randomf(); 43 | 44 | setPixel(xnew as i32, (ynew - pZ/2_f) as i32, color as i32); 45 | 46 | branch_if (t := t + 0.0311279296875) < 56_f: tloop; 47 | } 48 | branch_if (x := x + 0.0311279296875) < 1_f: xloop; 49 | } 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /chaos_rose/Chaos_Rose.nfo: -------------------------------------------------------------------------------- 1 | [Chaos Rose] 2 | 3 | Rose generation idea by Paul Nylander: 4 | https://nylander.wordpress.com/2006/06/21/rose-shaped-parametric-surface/ 5 | 6 | For Lovebyte party 2024 7 | 256 Byte High-End Tiny Intro Competition 8 | MicroW8 0.2.2 platform 9 | 10 | Greetings to all SizeCoders, especially: 11 | 42Bastian, Blossom, Blueberry, Busy, Dalthon, 12 | Digimind, Dresdenboy, exoticorn, F#READY, gopher, 13 | HellMood, iONic, ivop, iq, KilledByAPixel, 14 | Kuemmel, Mentor, pestis, p01, Rrrola, sensenstahl, 15 | SerzhSoft, sheriff, SuN, Superogue, TomCat. 16 | 17 | -------------------------------------------------------------------------------- /chaos_rose/Chaos_Rose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/chaos_rose/Chaos_Rose.png -------------------------------------------------------------------------------- /chaos_rose/Chaos_Rose.uw8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/chaos_rose/Chaos_Rose.uw8 -------------------------------------------------------------------------------- /dekabyte.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/dekabyte.zip -------------------------------------------------------------------------------- /dekabyte/dekabyte.asm: -------------------------------------------------------------------------------- 1 | TIMER1 equ $13 ; slower one 2 | TIMER2 equ $14 ; faster one 3 | VCOUNT equ $D40B 4 | AUDC2 equ $D203 5 | HPOSP0 equ $D000 ; Player 0 Horizontal Position 6 | HPOSP1 equ $D001 ; Player 1 Horizontal Position 7 | GRAFP0 equ $D00D ; Player 0 Graphics Pattern 8 | COLPM0 equ $D012 ; Player/Missile 0 color, GTIA 9-color playfield color 0 for Background 9 | 10 | openmode equ $ef9c 11 | 12 | org $80 13 | vc .ds[1] 14 | start 15 | 16 | lda #1 17 | jsr openmode 18 | loop: 19 | ; x=0 to 3 20 | tax 21 | asl 22 | ; y=0,2,4,6 23 | sta branch 24 | 25 | lda TIMER2 26 | and patterns,x 27 | sta AUDC2 28 | 29 | lda vcount 30 | sta vc ; because vcount address is 2 bytes long and we need it to be 1 byte long 31 | 32 | lda TIMER2 33 | bcc @+ 34 | branch equ *-1 35 | next 36 | @ 37 | adc vc 38 | @ 39 | adc vc 40 | @ 41 | eor vc 42 | @ 43 | 44 | ; x=0-3 45 | inx 46 | regs: 47 | sta GRAFP0,x 48 | sta COLPM0,x 49 | dex 50 | bpl regs 51 | 52 | sta HPOSP0 53 | eor #$FF 54 | sta HPOSP1 55 | 56 | lda TIMER1 57 | lsr 58 | eor #$FF 59 | and #3 60 | bpl loop ; infinite loop 61 | 62 | patterns 63 | .byte %00101011 64 | .byte %00111000 65 | .byte %00101000 66 | .byte %00111000 67 | -------------------------------------------------------------------------------- /dekabyte/dekabyte.nfo: -------------------------------------------------------------------------------- 1 | [Dekabyte] 2 | 3 | Less than hectobyte 4 | 5 | For Lovebyte party 2022, "Combined 64 byte intro compo" 6 | Requires Atari XL/XE OS Rev2 7 | Code: Ilmenit / Agenda '2022 8 | 9 | By the compo rules the header size is not included into the final size. 10 | 11 | Greetings to all sizecoders! 12 | -------------------------------------------------------------------------------- /dekabyte/dekabyte.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/dekabyte/dekabyte.png -------------------------------------------------------------------------------- /dekabyte/dekabyte.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/dekabyte/dekabyte.xex -------------------------------------------------------------------------------- /dirt_race.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/dirt_race.zip -------------------------------------------------------------------------------- /dirt_race/dirt_race.asm: -------------------------------------------------------------------------------- 1 | TIMER1 equ $13 ; slower one 2 | TIMER2 equ $14 ; faster one 3 | 4 | HPOSP0 = $D000 ; Player 0 Horizontal Position 5 | HPOSP1 = $D001 ; Player 1 Horizontal Position 6 | HPOSP2 = $D002 ; Player 2 Horizontal Position 7 | ; 8 | HPOSM0 = $D004 ; Missile 0 Horizontal Position 9 | HPOSM1 = $D005 ; Missile 1 Horizontal Position 10 | HPOSM2 = $D006 ; Missile 2 Horizontal Position 11 | HPOSM3 = $D007 ; Missile 3 Horizontal Position 12 | ; 13 | SIZEP0 = $D008 ; Player 0 Size 14 | SIZEP1 = $D009 ; Player 1 Size 15 | SIZEP2 = $D00A ; Player 2 Size 16 | SIZEP3 = $D00B ; Player 3 Size 17 | SIZEM = $D00C ; Missiles Sizes (2 bits per missile) 18 | ; 19 | COLPM0 = $D012 ; Player/Missile 0 color, GTIA 9-color playfield color 0 for Background 20 | COLPM1 = $D013 ; Player/Missile 1 color, GTIA 9-color playfield color 1 21 | COLPM2 = $D014 ; Player/Missile 2 color, GTIA 9-color playfield color 2 22 | COLPM3 = $D015 ; Player/Missile 3 color, GTIA 9-color playfield color 3 23 | 24 | GRAFP0 = $D00D ; Player 0 Graphics Pattern 25 | GRAFP1 = $D00E ; Player 1 Graphics Pattern 26 | GRAFP2 = $D00F ; Player 2 Graphics Pattern 27 | GRAFP3 = $D010 ; Player 3 Graphics Pattern 28 | GRAFM = $D011 ; Missile Graphics Pattern (2 bits per missile) 29 | 30 | COLPF0 equ $D016 31 | COLPF1 equ $D017 32 | COLPF2 equ $D018 33 | COLPF3 equ $D019 34 | COLBK equ $D01A 35 | GRACTL equ $D01D ; Graphics Control, P/M DMA and joystick trigger latches 36 | 37 | AUDF1 equ $D200 38 | AUDC1 equ $D201 39 | AUDF2 equ $D202 40 | AUDC2 equ $D203 41 | AUDF3 equ $D204 42 | AUDC3 equ $D205 43 | AUDF4 equ $D206 44 | AUDC4 equ $D207 45 | AUDCTL equ $D208 46 | RANDOM equ $D20A 47 | SKCTL equ $D20F 48 | 49 | PMBASE equ $D407 ; Player/Missile Base Address (high) 50 | WSYNC equ $D40A 51 | VCOUNT equ $D40B 52 | 53 | SDMCTL equ $022F 54 | 55 | PCOLR0 equ $02C0 ;p/m 0 color 56 | PCOLR1 equ $02C1 ;p/m 1 color 57 | PCOLR2 equ $02C2 ;p/m 2 color 58 | PCOLR3 equ $02C3 ;p/m 3 color 59 | 60 | COLOR0 equ $02c4 61 | COLOR1 equ $02c5 62 | COLOR2 equ $02c6 63 | COLOR3 equ $02c7 64 | COLOR4 equ $02c8 65 | 66 | rom_rnd equ $F711 67 | 68 | road_pos equ $6a ; C0 on zero page 69 | 70 | bike_pmg equ p0_shape+$60 71 | 72 | org $2000 73 | start: 74 | 75 | ldx #%1101100 76 | stx SDMCTL ; #%0001000 ; enable players, double resolution, no playfield so no color needed 77 | dex 78 | ;lda #7 ; 2=players, 3=p&m 79 | stx GRACTL 80 | stx SIZEP1 ; road 81 | stx AUDC1 ; engine sound 82 | 83 | .local init_loop 84 | ;init colors, bike 85 | lda bike_data-1,x 86 | sta bike_pmg-1,x 87 | dex 88 | bne init_loop 89 | .endl 90 | ; A=$30 91 | sta PCOLR2 ; mud 92 | sta PMBASE 93 | 94 | .local init_table 95 | loop: 96 | lda rom_rnd,x 97 | sta mud_pos,x 98 | 99 | and #%10 100 | clc 101 | adc road_pos,x 102 | sbc #0 103 | sta road_pos+1,x 104 | 105 | lda #%11111111 106 | sta p1_shape,x ; alterantive - sta grafp0 in line 107 | 108 | inx 109 | bpl loop 110 | .endl 111 | sta PCOLR0 ; bike 112 | 113 | screen_loop: 114 | ; in A we have HPOSP1 (road) from the previous line 115 | ldy VCOUNT 116 | sta wsync 117 | ; set bike 118 | cpy #$64 ; $5F - no bike move 119 | bne skip_pos 120 | adc #16-4 121 | sta HPOSP0 ; bike pos 122 | sta AUDF1 123 | skip_pos: 124 | tya ; vcount 125 | sbc TIMER2 126 | sta GRAFP2 127 | 128 | lsr ; a=vcount/2 129 | tax ; move to index 130 | 131 | and #7 132 | eor #$E7 ; revert gradient - looks more like bumps 133 | sta COLPM1 ; road 134 | 135 | ; ground color 136 | txa 137 | and #$30 138 | adc #$A4 139 | sta COLBK 140 | 141 | lda road_pos,x 142 | sbc VCOUNT 143 | sta HPOSP1 144 | 145 | tay 146 | sbc mud_pos,x 147 | sta HPOSP2 ; mud pos 148 | tya 149 | bne screen_loop 150 | 151 | bike_data: 152 | .byte %00110000 ; $30 153 | .byte %01100110 ; $66 154 | .byte %01111111 ; $7f 155 | .byte %11110110 ; $F6 156 | .byte %01110000 ; $70 157 | .byte %11000000 ; $C0 158 | .byte %11000000 ; $C0 159 | 160 | org $3000 161 | pmg: 162 | unused .ds [768/2] 163 | missile .ds [256/2] 164 | p0_shape .ds[256/2] 165 | p1_shape .ds[256/2] 166 | p2_shape .ds[256/2] 167 | p3_shape .ds[256/2] 168 | mud_pos .ds[256] 169 | 170 | -------------------------------------------------------------------------------- /dirt_race/dirt_race.nfo: -------------------------------------------------------------------------------- 1 | [Dirt Race] 2 | 3 | Loud, fast and dirty! 4 | 5 | For Lovebyte party 2025, "128 Byte Intro Oldschool Competition" 6 | Requires Atari XL/XE OS Rev2 7 | Code: Ilmenit / Agenda 8 | 9 | Greetings to all sizecoders! 10 | -------------------------------------------------------------------------------- /dirt_race/dirt_race.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/dirt_race/dirt_race.png -------------------------------------------------------------------------------- /dirt_race/dirt_race.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/dirt_race/dirt_race.xex -------------------------------------------------------------------------------- /graphite32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/graphite32.zip -------------------------------------------------------------------------------- /graphite32/graphite32.asm: -------------------------------------------------------------------------------- 1 | ; OS 2 | TIMER1 equ $13 3 | TIMER2 equ $14 4 | ATRACT equ $4D 5 | RANDOM equ $d20a 6 | ;;;;;; SOUND 7 | AUDC2 equ $D203 8 | 9 | ; Aliases, because orig reg names are hard to remember ;) 10 | ROWCRS equ $54 ;Row of cursor, 1 byte 11 | COLCRS equ $55 ;Column of cursor, 2 bytes 12 | cursor_y equ ROWCRS 13 | cursor_x equ COLCRS 14 | 15 | ; OS functions 16 | os_openmode equ $ef9c 17 | os_drawpoint_mid equ $F1DB 18 | 19 | org $80 20 | 21 | start: 22 | lda #9 ; 2 bytes 23 | jsr os_openmode ; 3 bytes 24 | sta TIMER1 25 | LOOP: 26 | lda TIMER2 27 | sta cursor_x 28 | isb cursor_y 29 | eor cursor_x 30 | sta ATRACT 31 | jsr os_drawpoint_mid 32 | lda TIMER2 33 | and #%00101000 34 | eor TIMER1 35 | sta AUDC2 36 | bvc loop 37 | -------------------------------------------------------------------------------- /graphite32/graphite32.nfo: -------------------------------------------------------------------------------- 1 | [Graphite32] 2 | 3 | Carbon Fiber-reinforced polymer 4 | 5 | For Lovebyte party 2022, "Combined 32 byte intro compo" 6 | Requires Atari XL/XE OS Rev2 7 | Code: Ilmenit / Agenda '2022 8 | 9 | By the compo rules the file header does not count to the size. 10 | 11 | Greetings to all sizecoders! 12 | -------------------------------------------------------------------------------- /graphite32/graphite32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/graphite32/graphite32.png -------------------------------------------------------------------------------- /graphite32/graphite32.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/graphite32/graphite32.xex -------------------------------------------------------------------------------- /midnight_dream.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/midnight_dream.zip -------------------------------------------------------------------------------- /midnight_dream/Midnight_Dream.cwa: -------------------------------------------------------------------------------- 1 | include "include/microw8-api.cwa" 2 | 3 | const ANCHORS_PER_LIMB = 3; 4 | const LIMBS = 6; 5 | const ANCHORS_TOTAL = ANCHORS_PER_LIMB * LIMBS; 6 | const ANCHOR_ANGLE_MIN = 0 * ANCHORS_TOTAL; 7 | const ANCHOR_ANGLE_RANGE = 1 * ANCHORS_TOTAL; 8 | const ANCHOR_ANGLE_PHASE = 2 * ANCHORS_TOTAL; 9 | const MUSIC_NOTES = 3 * ANCHORS_TOTAL; 10 | const ANCHORS = ANCHOR_ANGLE_MIN; 11 | const ANCHOR_CENTER = ANCHOR_ANGLE_MIN+11; // in the anchor data we have good 2 values to use for center 12 | 13 | const HORIZON = 128; 14 | const LINES = 112; 15 | 16 | global mut frame = 0; 17 | 18 | export fn upd() { 19 | 20 | let it: i32; 21 | 22 | //// music 23 | if !(frame % 31) { 24 | let inline channel: i32 = frame%4; 25 | let inline note: i32 = ((frame+frame/992)%8)?MUSIC_NOTES; // 31*32 = 992, 31 because of %31 26 | playNote(channel, note); 27 | } 28 | frame = frame + 1; 29 | 30 | cls(0); 31 | randomSeed(0); 32 | 33 | loop next_it { 34 | 35 | // draw background 36 | 37 | let inline px: i32 = (random()+frame*it/12)%(384); // 512 38 | // the advantage of compressed cart 39 | setPixel(px,it+HORIZON,it); 40 | setPixel(px,it+HORIZON,it); 41 | setPixel(px,it+HORIZON,it); 42 | setPixel(px,it+HORIZON,it); 43 | setPixel(px,it+HORIZON,it); 44 | setPixel(px,it+HORIZON,it); 45 | setPixel(px,it+HORIZON,it); 46 | setPixel(px,it+HORIZON,it); 47 | setPixel(px,it+HORIZON,it); 48 | setPixel(px,it+HORIZON,it); 49 | setPixel(px,it+HORIZON,it); 50 | setPixel(px,it+HORIZON,it); 51 | setPixel(px,it+HORIZON,it); 52 | setPixel(px,it+HORIZON,it); 53 | setPixel(px,it+HORIZON,it); 54 | 55 | // draw horse 56 | 57 | let prev_x: f32; 58 | let prev_y: f32; 59 | 60 | if (it < ANCHORS_TOTAL) { 61 | 62 | // time 63 | 64 | if !(it%ANCHORS_PER_LIMB) { 65 | // half of the anchors on the left side, half on the right side 66 | prev_x = (((it / (ANCHORS_TOTAL/2) ) ? (ANCHOR_CENTER))+1248) as f32 - min(frame as f32,1248 as f32); 67 | prev_y = 112_f; // CENTER_Y 68 | } 69 | 70 | // draw anchor 71 | 72 | let inline c = 31_f; 73 | let inline angle_phase = (it?ANCHOR_ANGLE_PHASE); 74 | let inline angle_min = ((it?ANCHOR_ANGLE_MIN) as f32); 75 | let inline range = (it?ANCHOR_ANGLE_RANGE); 76 | 77 | // calculate move there and back 78 | let inline for_abs = (fmod( ((range*(frame+angle_phase)) as f32) /c, (range + range) as f32 ) - range as f32); 79 | let inline angle = (angle_min + abs(for_abs))/c; 80 | 81 | let inline x = prev_x + c * sin(angle); 82 | let inline y = prev_y + c * cos(angle); 83 | 84 | 85 | // moon - shorter output when drawn here 86 | circle(248_f,31_f,31_f,190); 87 | 88 | line(x,y,prev_x,prev_y,15*(it%ANCHORS_PER_LIMB)); 89 | 90 | prev_x = x; 91 | prev_y = y; 92 | } 93 | 94 | // end loop 95 | branch_if (it := it + 1) < LINES: next_it; 96 | }; 97 | } 98 | 99 | data ANCHORS { 100 | i8( 101 | /// - front leg 1 - | - front leg 2 - | ---- head ----- | -- back leg 1 - | -- back leg 2 - | ---- tail ----- | 102 | // angle min 103 | 0xB0, 0x99, 0xAA, 0xB0, 0x99, 0xAA, 0x7A, 0x81, 0x99, 0xCB, 0xB6, 0x92, 0xCB, 0xB6, 0x92, 0x35, 0x20, 0x20, 104 | 105 | // range = max-min 106 | 0x18, 0x4B, 0x55, 0x18, 0x4B, 0x55, 0x08, 0x10, 0x10, 0x1B, 0x38, 0x48, 0x1B, 0x38, 0x48, 0x14, 0x18, 0x18, 107 | 108 | // angle phase 109 | 0x00, 0x00, 0x74, 0x31, 0x31, 0xA4, 0x49, 0x49, 0x35, 0xC3, 0xD0, 0x19, 0xF3, 0x00, 0x4A, 0x80, 0x89, 0x7A, 110 | 111 | // music notes 112 | 53, 56, 60, 61, 63, 65, 68, 56 113 | ) 114 | } 115 | 116 | 117 | -------------------------------------------------------------------------------- /midnight_dream/Midnight_Dream.nfo: -------------------------------------------------------------------------------- 1 | [Midnight Dream] 2 | 3 | The silver moonlight weaves our dreams. 4 | 5 | For Lovebyte party 2024 6 | 256 Byte High-End Tiny Intro Competition 7 | MicroW8 0.2.2 platform 8 | Code: Ilmenit / Agenda, 2024 9 | 10 | Greetings to all SizeCoders, especially: 11 | 42Bastian, Blossom, Blueberry, Busy, Dalthon, 12 | Digimind, Dresdenboy, exoticorn, F#READY, gopher, 13 | HellMood, iONic, ivop, iq, KilledByAPixel, 14 | Kuemmel, Mentor, pestis, p01, Rrrola, sensenstahl, 15 | SerzhSoft, sheriff, SuN, Superogue, TomCat. 16 | 17 | -------------------------------------------------------------------------------- /midnight_dream/Midnight_Dream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/midnight_dream/Midnight_Dream.png -------------------------------------------------------------------------------- /midnight_dream/Midnight_Dream.uw8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/midnight_dream/Midnight_Dream.uw8 -------------------------------------------------------------------------------- /murkwood.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/murkwood.zip -------------------------------------------------------------------------------- /murkwood/murkwood.asm: -------------------------------------------------------------------------------- 1 | SAFE_VERSION = 0 2 | 3 | ROWCRS equ $54 ;Row of cursor, 1 byte 4 | COLCRS equ $55 ;Column of cursor, 2 bytes 5 | 6 | OLDROW equ $5A 7 | OLDCOL equ $5B ; 2 bytes 8 | 9 | SAVMSC equ $58 ; screen address 10 | 11 | ; Aliases, because orig reg names are hard to remember ;) 12 | cursor_y equ ROWCRS 13 | cursor_x equ COLCRS 14 | prev_y equ OLDROW 15 | prev_x equ OLDCOL 16 | 17 | TIMER1 equ $13 18 | TIMER2 equ $14 19 | 20 | ; colors 21 | 22 | HPOSM0 equ $D004 ; Missile 0 Horizontal Position 23 | GRAFM equ $D011 24 | 25 | AUDF1 equ $D200 26 | AUDC1 equ $D201 27 | AUDCTL equ $D208 28 | SKCTL equ $D20F 29 | RANDOM equ $d20a 30 | 31 | INSTRUMENT equ $A0 32 | 33 | COLOR equ $2fb ;Color for graphics operations 34 | VCOUNT equ $D40B 35 | 36 | SCREEN_WIDTH equ 40 37 | SCREEN_HEIGHT equ 192 38 | 39 | ; OS functions 40 | openmode equ $ef9c 41 | drawpoint equ $f1d8 42 | drawto equ $f9c2 43 | ZXLY equ $DA48 ; zero data on zero page 44 | 45 | icl "pal_notes.inc" 46 | 47 | org $80 48 | tree_width .ds[1] 49 | tree_color .ds[1] 50 | music_zero_addr ; from this address we zero 14 bytes 51 | .ds[2] ; buffer expand for zero 52 | tree_count .ds[1] 53 | delay .ds[4] 54 | volume .ds[4] 55 | index .ds[3] 56 | index4 .byte $8c ; potentially set this one in delays and add it to all 57 | delays 58 | .byte 0 59 | .byte 192 60 | .byte 128 61 | .byte 64 62 | notes 63 | .byte F_2, GS_2, C_3, CS_3 64 | .byte DS_3, F_3, GS_3, GS_2 65 | 66 | .local screen 67 | frame: 68 | 69 | .local rain ; thnx to Koala for idea 70 | infi: 71 | lda RANDOM 72 | pha 73 | lda TIMER2 74 | tax 75 | loop 76 | ldy $100,x 77 | sty GRAFM 78 | sty HPOSM0 79 | dex 80 | cmp TIMER2 81 | beq loop 82 | .endl 83 | 84 | ldx #3 85 | .IF SAFE_VERSION=1 86 | stx SKCTL ; 3 - init sound for proper loading from DOS 87 | .ENDIF 88 | channel_loop: 89 | ; x=channel 90 | 91 | ; channel*2 to y 92 | txa 93 | asl 94 | tay 95 | 96 | ; check if delay 97 | dec delay,x 98 | bne play_note 99 | new_note: 100 | lda #128 ; channel volume 101 | sta volume,x 102 | lda delays,x ; opt to some my code or ROM location 103 | sta delay,x 104 | 105 | txa ; value to add is channel number 106 | sec ; +1, so moves 107 | adc index,x 108 | sta index,x 109 | and #7 110 | clc 111 | adc #notes 112 | sta note_smc 113 | 114 | note_smc equ *+1 115 | lda notes 116 | sta AUDF1,y 117 | 118 | play_note 119 | lda volume,x 120 | beq skip_playing 121 | :5 lsr 122 | adc #INSTRUMENT 123 | sta AUDC1,y 124 | dec volume,x 125 | skip_playing 126 | 127 | channel_next 128 | dex 129 | bpl channel_loop 130 | bmi frame 131 | .endl 132 | 133 | start: 134 | lda #9 135 | jsr openmode 136 | ; A=00 X=15 Y=01 137 | 138 | ; clear screen 139 | lda #175 ; set color to clear and at the same time size 140 | sta tree_color 141 | jsr draw_tree 142 | 143 | ldy #14 144 | sty tree_color 145 | ; 5 bytes, zero music data + 1 for initial = 6, a bit shorter than having the 8 146 | ldx #music_zero_addr 147 | jsr ZXLY ; clear: x = adress on ZP, y = len 148 | rom_address equ *-2 149 | ; A=0 150 | sta AUDCTL ; 0 151 | 152 | .local draw_trees 153 | lda tree_color 154 | .IF SAFE_VERSION=0 155 | asl 156 | .ENDIF 157 | sta tree_count 158 | loop 159 | 160 | .local dots 161 | lda tree_color 162 | cmp #5 ; limit to background layers 163 | bmi dots_end 164 | dots_loop: 165 | lda RANDOM 166 | sta cursor_y 167 | jsr drawpoint 168 | inc cursor_x 169 | bpl dots_loop 170 | dots_end 171 | .endl 172 | 173 | jsr draw_tree 174 | 175 | dec tree_count 176 | bpl loop 177 | 178 | .local draw_terrain 179 | lda #79 180 | sta cursor_x 181 | sta prev_x 182 | 183 | lda tree_color 184 | :3 asl 185 | eor #$FF 186 | adc #160 187 | sta cursor_y 188 | loop 189 | lda #SCREEN_HEIGHT 190 | sta prev_y 191 | jsr drawto 192 | 193 | lda RANDOM 194 | bpl skip 195 | inc cursor_y 196 | inc cursor_y 197 | skip 198 | dec cursor_y 199 | 200 | dec prev_x 201 | dec cursor_x 202 | bpl loop 203 | .endl 204 | 205 | dec tree_color 206 | ; bne draw_trees 207 | bpl draw_trees 208 | .endl 209 | 210 | .local fix_top_line ; using spare bytes to fix the top line 211 | ldy #39 212 | lda #0 213 | fix: 214 | sta (savmsc),y 215 | dey 216 | bpl fix 217 | .endl 218 | 219 | jmp screen 220 | 221 | .proc draw_tree 222 | lda tree_color 223 | sta color 224 | bmi nonrandom 225 | next_rand 226 | .IF SAFE_VERSION=1 227 | lda RANDOM 228 | .ELSE 229 | dec rom_address 230 | lda (rom_address),y 231 | rol 232 | .ENDIF 233 | lsr 234 | sta cursor_x 235 | sta prev_x 236 | nonrandom 237 | lda tree_color 238 | eor #$FF 239 | adc #8 240 | sta tree_width 241 | 242 | lda #(SCREEN_HEIGHT-1) 243 | sta cursor_y 244 | 245 | loop 246 | lda #0 247 | sta prev_y 248 | 249 | jsr drawto 250 | 251 | inc cursor_x 252 | dec tree_width 253 | bpl loop 254 | rts 255 | .endp 256 | ; we have space for the RUN 257 | RUN start -------------------------------------------------------------------------------- /murkwood/murkwood.nfo: -------------------------------------------------------------------------------- 1 | [Murkwood] 2 | 3 | Enjoy the moment of a procedural melancholy. 4 | 5 | For Lovebyte party 2022, "Oldschool 256 byte intro compo" 6 | Requires Atari XL/XE OS Rev2 7 | Code: Ilmenit / Agenda 8 | Rain code idea: Koala / Agenda 9 | 10 | The intro has a procedurally generated forest, rain and music on 4 channels. 11 | 12 | Greetings to all sizecoders! 13 | -------------------------------------------------------------------------------- /murkwood/murkwood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/murkwood/murkwood.png -------------------------------------------------------------------------------- /murkwood/murkwood.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/murkwood/murkwood.xex -------------------------------------------------------------------------------- /murkwood/murkwood_safe_random.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/murkwood/murkwood_safe_random.xex -------------------------------------------------------------------------------- /murkwood/pal_notes.inc: -------------------------------------------------------------------------------- 1 | H_0 equ $ff 2 | C_1 equ $f1 3 | CS_1 equ $e3 4 | D_1 equ $d7 5 | DS_1 equ $cb 6 | E_1 equ $bf 7 | F_1 equ $b4 8 | FS_1 equ $aa 9 | G_1 equ $a1 10 | GS_1 equ $98 11 | A_1 equ $8f 12 | AS_1 equ $87 13 | H_1 equ $7f 14 | C_2 equ $78 15 | CS_2 equ $71 16 | D_2 equ $6b 17 | DS_2 equ $65 18 | E_2 equ $5f 19 | F_2 equ $5a 20 | FS_2 equ $55 21 | G_2 equ $50 22 | GS_2 equ $4b 23 | A_2 equ $47 24 | AS_2 equ $43 25 | H_2 equ $3f 26 | C_3 equ $3c 27 | CS_3 equ $38 28 | D_3 equ $35 29 | DS_3 equ $32 30 | E_3 equ $2f 31 | F_3 equ $2c 32 | FS_3 equ $2a 33 | G_3 equ $27 34 | GS_3 equ $25 35 | A_3 equ $23 36 | AS_3 equ $21 37 | H_3 equ $1f 38 | C_4 equ $1d 39 | CS_4 equ $1c 40 | D_4 equ $1a 41 | DS_4 equ $18 42 | E_4 equ $17 43 | F_4 equ $16 44 | FS_4 equ $14 45 | G_4 equ $13 46 | GS_4 equ $12 47 | A_4 equ $11 48 | AS_4 equ $10 49 | H_4 equ $0f 50 | C_5 equ $0e 51 | CS_5 equ $0d 52 | D_5 equ $0c 53 | DS_5 equ $0c 54 | E_5 equ $0b 55 | F_5 equ $0a 56 | FS_5 equ $0a 57 | G_5 equ $09 58 | GS_5 equ $09 59 | A_5 equ $08 60 | AS_5 equ $07 61 | H_5 equ $07 62 | C_6 equ $07 63 | CS_6 equ $06 64 | D_6 equ $06 65 | DS_6 equ $05 66 | E_6 equ $05 67 | F_6 equ $05 68 | FS_6 equ $04 69 | G_6 equ $04 70 | GS_6 equ $04 71 | A_6 equ $03 72 | AS_6 equ $03 73 | H_6 equ $03 74 | C_7 equ $03 75 | CS_7 equ $03 76 | D_7 equ $02 77 | DS_7 equ $02 78 | E_7 equ $02 79 | F_7 equ $02 80 | FS_7 equ $02 81 | G_7 equ $02 82 | GS_7 equ $01 83 | A_7 equ $01 84 | AS_7 equ $01 85 | H_7 equ $01 86 | C_8 equ $01 87 | CS_8 equ $01 88 | D_8 equ $01 89 | DS_8 equ $01 90 | E_8 equ $01 91 | F_8 equ $00 92 | FS_8 equ $00 93 | G_8 equ $00 94 | GS_8 equ $00 95 | A_8 equ $00 96 | AS_8 equ $00 97 | H_8 equ $00 98 | 99 | B_0 equ H_0 100 | B_1 equ H_1 101 | B_2 equ H_2 102 | B_3 equ H_3 103 | B_4 equ H_4 104 | B_5 equ H_5 105 | B_6 equ H_6 106 | B_7 equ H_7 107 | B_8 equ H_8 108 | -------------------------------------------------------------------------------- /parenthood.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/parenthood.zip -------------------------------------------------------------------------------- /parenthood/bonus/emba.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/parenthood/bonus/emba.jpg -------------------------------------------------------------------------------- /parenthood/bonus/with_eyes_no_show.asm: -------------------------------------------------------------------------------- 1 | COLOR0 equ $02c4 2 | COLOR1 equ $02c5 3 | COLOR2 equ $02c6 4 | COLOR3 equ $02c7 5 | COLOR4 equ $02c8 6 | 7 | RANDOM equ $d20a 8 | 9 | ; OS functions 10 | openmode equ $ef9c 11 | drawto equ $f9c2 12 | 13 | COLOR equ $2fb ;Color for graphics operations 14 | 15 | ROWCRS equ $54 ;Row of cursor, 1 byte 16 | COLCRS equ $55 ;Column of cursor, 2 bytes 17 | 18 | OLDROW equ $5A 19 | OLDCOL equ $5B ; 2 bytes 20 | 21 | ; Aliases, because orig reg names are hard to remember ;) 22 | cursor_y equ ROWCRS 23 | cursor_x equ COLCRS 24 | prev_y equ OLDROW 25 | prev_x equ OLDCOL 26 | 27 | ; I had plenty of space so I didn't have to use stack like in https://www.pouet.net/prod.php?which=55951 28 | 29 | org $80 30 | start: 31 | lda #8 32 | jsr openmode 33 | sty COLOR2 34 | draw: 35 | dec point 36 | ldy point 37 | lda point_y,y 38 | sta cursor_y 39 | sta color 40 | lda point_x,y 41 | sta cursor_x 42 | jsr drawto 43 | bvc draw 44 | 45 | ;point .byte 45 46 | point .byte 127 47 | point_x: 48 | .byte 146,156,162,230,213,191,169,163,179,191,168,162,165,185,190,216 49 | .byte 231,254,218,174,174,151,148,138,134,136,137,125,125,135,153,153 50 | .byte 145,144,139,139,134,136,133,102,84,66,98,98,92 51 | point_y: 52 | .byte 151,151,146,71,59,57,63,69,67,71,71,75,79,79,83,83 53 | .byte 99,171,177,191,191,189,181,181,177,173,151,131,111,91,73,65 54 | .byte 59,51,49,43,37,23,19,19,5,0,29,37,46 55 | -------------------------------------------------------------------------------- /parenthood/bonus/with_eyes_no_show.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/parenthood/bonus/with_eyes_no_show.xex -------------------------------------------------------------------------------- /parenthood/parenthood.asm: -------------------------------------------------------------------------------- 1 | COLOR0 equ $02c4 2 | COLOR1 equ $02c5 3 | COLOR2 equ $02c6 4 | COLOR3 equ $02c7 5 | COLOR4 equ $02c8 6 | 7 | RANDOM equ $d20a 8 | SAVMSC equ $58 ; screen address 9 | 10 | ; OS functions 11 | openmode equ $ef9c 12 | drawto equ $f9c2 13 | drawto2 equ $f9c4 14 | drawpoint equ $f1d8 15 | drawpoint2 equ $f1dB 16 | getpoint equ $f18f 17 | 18 | COLOR equ $2fb ;Color for graphics operations 19 | 20 | ROWCRS equ $54 ;Row of cursor, 1 byte 21 | COLCRS equ $55 ;Column of cursor, 2 bytes 22 | 23 | OLDROW equ $5A 24 | OLDCOL equ $5B ; 2 bytes 25 | 26 | ; Aliases, because orig reg names are hard to remember ;) 27 | cursor_y equ ROWCRS 28 | cursor_x equ COLCRS 29 | prev_y equ OLDROW 30 | prev_x equ OLDCOL 31 | 32 | code_load equ $100-code_size 33 | 34 | org code_load 35 | start: 36 | lda #8 37 | jsr openmode 38 | ; sty color2 ; bw 39 | ldx #$FF 40 | ; stx color2 ; yellow 41 | txs 42 | rol SAVMSC+1 43 | draw: 44 | pla 45 | sta color 46 | beq show 47 | sta cursor_x 48 | pla 49 | jsr drawto2 ; jumping to "middle of function" to avoid sta cursor_y 50 | stx color2 ; grey 51 | bvc draw 52 | show 53 | show_loop 54 | ror SAVMSC+1 55 | jsr drawpoint2 ; jumping to "middle of function" to avoid storing of color 56 | rol SAVMSC+1 57 | inc cursor_x 58 | lda RANDOM 59 | sta cursor_y 60 | jsr getpoint 61 | bvc show 62 | 63 | code_size equ *-start 64 | .print "CODE SIZE: ", code_size 65 | 66 | data: 67 | .byte 64,0,83,6,101,20,133,20,135,23,133,38,139,44,139,49,143,52,145,59,153,66,153,73,135,92 68 | .byte 125,112,125,131,137,152,135,174,133,178,137,182,147,182,151,191,217,178,253,171,231,99,215,84,189,83,185,80 69 | .byte 165,79,161,75,167,72,191,71,179,67,163,70,169,64,191,57,213,60,160,148,147,154 70 | -------------------------------------------------------------------------------- /parenthood/parenthood.nfo: -------------------------------------------------------------------------------- 1 | [Parenthood] 2 | 3 | Moments matter. 4 | 5 | For Lovebyte party 2022, "Combined 128 byte intro compo" 6 | Got reclassifed to "256 byte Executable Graphics compo". 7 | 8 | Requires Atari XL/XE OS Rev2, Basic disabled 9 | Code: Ilmenit / Agenda '2022 10 | Gfx: Emba 11 | 12 | No fancy picture generation algorithm. 13 | Smoke & mirros by using hardware & OS capabilities. 14 | 15 | Original Emba's picture for me is a masterpiece of minimalism. 16 | 17 | Greetings to all sizecoders! -------------------------------------------------------------------------------- /parenthood/parenthood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/parenthood/parenthood.png -------------------------------------------------------------------------------- /parenthood/parenthood.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/parenthood/parenthood.xex -------------------------------------------------------------------------------- /phase_of_haze.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/phase_of_haze.zip -------------------------------------------------------------------------------- /phase_of_haze/phase_of_haze.asm: -------------------------------------------------------------------------------- 1 | ;;;;;; SOUND 2 | AUDF1 equ $D200 3 | AUDC1 equ $D201 4 | AUDCTL equ $D208 5 | SKCTL equ $D20F 6 | 7 | ;;;;;; GFX 8 | CHBAS equ $2F4 9 | 10 | GPRIOR equ $026F 11 | ADRESS equ $64 12 | 13 | ; OS functions 14 | TIMER1 equ $13 15 | TIMER2 equ $14 16 | SUBSTRACT equ $F57A 17 | 18 | EOR_VALUE equ $4 ; RAMLO 19 | 20 | COLOR4 equ $02c8 21 | 22 | generated equ $4000 23 | 24 | font equ $8000 25 | 26 | org $8A-$15 ; $8A is ptr address but also opcode for TXA 27 | start: 28 | ; this chargen is inspired by Dotty Veil (Blueberry) which is sooo cool that it's a sin not to use it ;) 29 | ; here optimized for Atari font and for zero page 30 | ;;;;; font generator 31 | ldy #0 32 | loop: 33 | tya 34 | asl 35 | asl 36 | asl 37 | beq next 38 | asl 39 | asl 40 | asl 41 | beq char 42 | bcc next 43 | dec ptr 44 | .byte $A9 45 | next: 46 | inc ptr 47 | char: 48 | 49 | ptr equ *+1 50 | lda char_table-1 51 | 52 | sta font,y ; we use Y to have it zeroes 53 | iny 54 | bne loop 55 | 56 | ; y=0 57 | sty TIMER1 58 | 59 | ;;;;; set gfx 60 | lda #$40 61 | sta GPRIOR 62 | asl ; #$80 63 | sta CHBAS 64 | sta COLOR4 65 | 66 | 67 | NEXT_FRAME: 68 | ; Y must be 0 69 | tya 70 | adc TIMER2 71 | adc #$40 72 | asl 73 | and #%10111000 74 | sta AUDC1 75 | bne skip_generation 76 | 77 | .local gen_function 78 | ; X=FF, Y=0 79 | lda TIMER1 80 | lsr 81 | and #7 82 | tax 83 | lda patterns,x 84 | sta AUDF1 85 | sta eor_value 86 | loop 87 | adc #1 88 | eor_value equ *+1 89 | eor #$0 90 | sta (generated_ptr),y ; tab on ZP? sty zp,x 91 | inc loop+1 92 | iny 93 | bne loop 94 | .endl 95 | 96 | 97 | skip_generation 98 | ; end of the screen 99 | ;y=0 100 | dey ; y=$FF 101 | sty ADRESS 102 | lda #$BF 103 | sta ADRESS+1 104 | ldx #23 ; row 105 | NEXT_ROW: 106 | 107 | ldy #40 ; column 108 | tya 109 | jsr substract 110 | ROW_LOOP: 111 | 112 | lda TIMER2 113 | adc (generated_ptr),y 114 | generated_ptr equ *+1 115 | adc generated,x 116 | sta (adress),y 117 | dey 118 | bne ROW_LOOP 119 | dex 120 | bpl NEXT_ROW 121 | bmi NEXT_FRAME 122 | 123 | char_table: 124 | patterns equ *+3 125 | .byte $FF,$FF,$FF,$FF 126 | .byte $E7,$C3,$B1,$81,$61,$40,$31 127 | 128 | 129 | -------------------------------------------------------------------------------- /phase_of_haze/phase_of_haze.nfo: -------------------------------------------------------------------------------- 1 | [Phase Of haze] 2 | 3 | Passing haze of discontent. 4 | 5 | For Lovebyte party 2022, "Combined 128 byte intro compo" 6 | Requires Atari XL/XE OS Rev2, Basic disabled 7 | Code: Ilmenit / Agenda '2022 8 | Chargen inspired by Blueberry (cheers!) 9 | 10 | Greetings to all sizecoders! 11 | -------------------------------------------------------------------------------- /phase_of_haze/phase_of_haze.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/phase_of_haze/phase_of_haze.png -------------------------------------------------------------------------------- /phase_of_haze/phase_of_haze.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/phase_of_haze/phase_of_haze.xex -------------------------------------------------------------------------------- /rescue_on_mars!.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/rescue_on_mars!.zip -------------------------------------------------------------------------------- /rescue_on_mars!/rescue_on_mars!.asm: -------------------------------------------------------------------------------- 1 | SAFE_VERSION = 0 2 | 3 | SCREEN_WIDTH equ 160 4 | SCREEN_HEIGHT equ 96 5 | screen_page_in_dl equ $AF9D 6 | 7 | CAMERA_HEIGHT equ 110 8 | MAX_DISTANCE equ 64 9 | MAX_HEIGHT equ (SCREEN_HEIGHT/2) 10 | LINES equ 8 11 | DISTANCE_STEP equ (MAX_DISTANCE / LINES) 12 | 13 | ;;;;;;;;;;;;;;;;; 14 | ROWCRS equ $54 ;Row of cursor, 1 byte 15 | COLCRS equ $55 ;Column of cursor, 2 bytes 16 | cursor_y equ ROWCRS 17 | cursor_x equ COLCRS 18 | 19 | ADRESS equ $64 ; current plot address 20 | SAVMSC equ $58 ; screen address 21 | 22 | ;;;;;; GFX 23 | COLOR0 equ $02c4 24 | 25 | ; SFX 26 | AUDF1 equ $D200 27 | 28 | RANDOM equ $d20a 29 | 30 | ; OS functions 31 | os_openmode equ $ef9c 32 | os_drawpoint equ $f1d8 33 | os_clrscr equ $f420 ; clear ADRESS up 34 | os_sms equ $F9A6 ; copy SAVMSC -> ADRESS 35 | ;;;;;;;;;;;;;;;;; CODE ;;;;;;;;;;;;;;;;;;;; 36 | 37 | org $3 38 | line_step_hi 39 | projected_distance_hi .ds[1] 40 | line_step_lo 41 | projected_distance_lo .ds[1] 42 | 43 | org $20 44 | plot_y .ds[1] 45 | 46 | line_x 47 | calc_height .ds[2] 48 | 49 | terrain_gen_val .ds[1] 50 | 51 | line_index .ds[1] 52 | move_counter .ds[1] 53 | 54 | org $42 ; should be 0, we need 0 for lower byte of the pointer 55 | projection_table_ptr .ds[2] 56 | 57 | org $7B-1 58 | 59 | program_data 60 | .IF SAFE_VERSION=0 61 | bvc start 62 | .ENDIF 63 | delta_data equ *-1 ; $7B will become 0 on open_mode 64 | .byte 1, 3, 2 65 | distance .byte MAX_DISTANCE-1 ; becomes -1 after calc_projection 66 | .byte -3,-2 67 | terrain_line_ptr .word (terrain_line + 256*(LINES-1)) ; lower byte must be 0 and we can use this 0 for the delta_data 68 | delta_data_end 69 | 70 | start: 71 | .local init_gfx 72 | 73 | lda #7 ; 2 bytes 74 | jsr os_openmode ; 3 bytes, Changes $7B (SWPFLG) on zero page to zero so we can't load data there 75 | ; A=00 X=07 Y=01 76 | .endl 77 | 78 | .local calc_projection 79 | 80 | ; for (distance = MAX_DISTANCE-1; distance < MAX_DISTANCE; --distance) 81 | distance_loop: 82 | jsr set_projection_ptr_by_distance 83 | 84 | ldy #(CAMERA_HEIGHT-1) 85 | ; for (height = CAMERA_HEIGHT-1; height < CAMERA_HEIGHT; --height) 86 | height_loop: 87 | 88 | ; high-byte 89 | ; calc_height.B.h = CAMERA_HEIGHT - height; 90 | 91 | ; reverse substraction 92 | ; https://wiki.nesdev.org/w/index.php/Synthetic_instructions#Reverse_subtraction 93 | tya 94 | sta AUDF1-3,y ; sound 6/10 95 | eor #$FF 96 | adc #(CAMERA_HEIGHT) 97 | 98 | STA calc_height+1 99 | 100 | ; projected_distance.W = (word)distance * 16; 101 | ; idea for *16 by barrym 102 | 103 | lda distance 104 | sta projected_distance_lo 105 | lda #$10 106 | mul_loop: 107 | asl projected_distance_lo 108 | rol 109 | bcc mul_loop 110 | sta projected_distance_hi 111 | 112 | ; ++projected_distance.B.h; 113 | inc projected_distance_hi 114 | 115 | ; plot_y = calc_height.W / (projected_distance.W); 116 | 117 | .local divide 118 | // *** dividend / divisor = quotient 119 | // result must fit in 1 byte (!) 120 | ldx #$FF 121 | loop: 122 | inx 123 | jsr substract_word 124 | bcs loop 125 | .endl 126 | ; result is in X, move to A 127 | txa 128 | ; store it 129 | sta (projection_table_ptr),y 130 | sta COLOR0-52,y ; set colors to red/pink 131 | 132 | next_height: 133 | 134 | dst_adr ; in copy_buffer becomes ZP pointer $6088 135 | dst_adr_hi equ dst_adr+1 136 | dey 137 | bpl height_loop 138 | 139 | next_distance: 140 | dec distance 141 | bpl distance_loop 142 | .endl 143 | 144 | .local gen_lines 145 | 146 | next_line_loop: 147 | next_pixel_loop: 148 | 149 | ; if (random_byte() & 1) 150 | ; ++terrain_gen_delta; 151 | ; else 152 | ; --terrain_gen_delta; 153 | 154 | ; X reg is terrain_gen_delta 155 | lda RANDOM 156 | bpl decrease_x 157 | inx 158 | inx 159 | decrease_x: 160 | dex 161 | 162 | ; terrain_gen_val += delta_vals[terrain_gen_delta & 7]; 163 | 164 | txa 165 | and #7 166 | tax 167 | lda delta_data,x 168 | clc ; must be present (?) - adjust table? 169 | adc terrain_gen_val 170 | ; if (terrain_gen_val > SCREEN_SIZE_Y) // below 0 171 | bmi negative 172 | cmp #MAX_HEIGHT 173 | bcc store 174 | 175 | too_high: 176 | inx ; more peaks, less flat 177 | lda #MAX_HEIGHT 178 | bne store 179 | 180 | negative: 181 | lda #0 182 | ; txa ; potential optimization by 1 byte, x is delta_data index 0-7, close enough to 0 183 | store: 184 | sta terrain_gen_val 185 | sta (terrain_line_ptr),y 186 | next_pixel: 187 | dey 188 | bne next_pixel_loop 189 | next_line: 190 | dec terrain_line_ptr+1 191 | bmi next_line_loop ; because terrain data starts at $8000 192 | .endl 193 | 194 | 195 | .local main_loop 196 | infinite_loop: 197 | 198 | .local copy_buffer 199 | init_addresses: 200 | 201 | jsr os_sms ; copy SAVMSC -> ADRESS 202 | asl ; $60 ; lda #>new_screen_memory 203 | sta screen_page_in_dl 204 | sta calc_projection.dst_adr_hi 205 | 206 | ; ldx #$00 ; not needed, we don't care how much we copy from the first page 207 | ldx #14 ; pages to copy 208 | copy_page: 209 | lda (adress),y 210 | sta (calc_projection.dst_adr),y 211 | iny 212 | bne copy_page 213 | 214 | inc adress+1 215 | inc calc_projection.dst_adr_hi 216 | 217 | dex 218 | bpl copy_page 219 | .endl 220 | 221 | jsr os_clrscr ; clear also y_buffer, which is placed after the screen memory 222 | 223 | .local draw_lines 224 | ldx #(LINES-1) 225 | stx line_index 226 | 227 | ; distance = move_counter % LINES; 228 | lda move_counter 229 | sax distance ; and #(LINES-1) ; sta distance 230 | 231 | ; for (line_index = LINES-1; line_index < LINES; --line_index) 232 | loop: 233 | ; current_line = ((move_counter/8) + line_index) % LINES; 234 | lda move_counter 235 | :3 lsr ; /8 236 | clc ; must be present 237 | adc line_index 238 | and #(LINES-1) 239 | 240 | .local draw_line 241 | ; set pointer to data 242 | adc #>terrain_line 243 | sta terrain_line_ptr+1 244 | 245 | ; set pointer to projection 246 | jsr set_projection_ptr_by_distance 247 | 248 | ; line_x.B.h = 64 + 127 + distance; 249 | ; lda distance ; we set distance related value to A in set_projection_ptr_by_distance 250 | sta line_x+1 251 | ; line_x.B.l = 0; 252 | ldy #0 253 | sty line_x 254 | ;line_step.B.h = 1; 255 | iny 256 | sty line_step_hi 257 | ;line_step.B.l = distance * 4; 258 | lda distance 259 | :2 asl 260 | sta line_step_lo 261 | 262 | ; cursor_x = SCREEN_SIZE_X - 1; 263 | lda #SCREEN_WIDTH-1 264 | sta cursor_x 265 | plot_loop: 266 | 267 | ; byte height = lines_height[current_line][line_x.B.h]; 268 | lda line_x+1 269 | tay 270 | lda (terrain_line_ptr),y 271 | ; A = height 272 | 273 | ; cursor_y = projection_table[distance][height]; 274 | tay 275 | lda (projection_table_ptr),y 276 | sta cursor_y 277 | 278 | ; if (cursor_y < y_buffer[cursor_x]) 279 | ldy cursor_x 280 | eor #$FF ; negate A (cursor_y), because we have y_buffer reversed 281 | cmp y_buffer,y 282 | bcc skip_drawing 283 | 284 | ; y_buffer[cursor_x] = cursor_y; 285 | sta y_buffer,y 286 | 287 | ; plot 288 | jsr os_drawpoint 289 | 290 | skip_drawing 291 | ; line_x.W -= line_step.W; 292 | jsr substract_word 293 | 294 | next_plot: 295 | dec cursor_x 296 | bne plot_loop 297 | .endl 298 | 299 | ; distance += DISTANCE_STEP; 300 | clc 301 | lda distance 302 | adc #DISTANCE_STEP 303 | sta distance 304 | next_loop: 305 | dec line_index 306 | bpl loop 307 | 308 | ; fly forward 309 | dec move_counter 310 | .endl 311 | 312 | jmp infinite_loop 313 | .endl 314 | 315 | 316 | .proc substract_word 317 | ; sec 318 | lda calc_height 319 | sbc projected_distance_lo 320 | sta calc_height 321 | lda calc_height+1 322 | sbc projected_distance_hi 323 | sta calc_height+1 324 | rts 325 | .endp 326 | 327 | .proc set_projection_ptr_by_distance 328 | clc 329 | lda #>projection_table 330 | adc distance 331 | sta projection_table_ptr+1 332 | rts 333 | .endp 334 | 335 | org $1000; $1000 - $5000 - projection table 336 | projection_table .ds[256*MAX_DISTANCE] 337 | 338 | org $8000 ; now needs to be at $8000 339 | terrain_line .ds[256*LINES] 340 | 341 | org $6088 342 | new_screen_memory .ds[256*14] 343 | 344 | org $BF60 ; we clear it with the screen so we have to use reversed height here 345 | y_buffer .ds[SCREEN_WIDTH] ; on the first/last line drawn set to max_height 346 | 347 | .IF SAFE_VERSION=1 348 | RUN start 349 | .ENDIF 350 | 351 | -------------------------------------------------------------------------------- /rescue_on_mars!/rescue_on_mars!.nfo: -------------------------------------------------------------------------------- 1 | [Rescue on Mars!] 2 | 3 | A flight over a procedurally generated Martian terrain. 4 | Real-time, full-screen, double-buffered. 5 | 6 | For Lovebyte party 2022, "Oldschool 256 byte intro compo" 7 | Requires Atari XL/XE OS Rev2, Basic disabled 8 | Code: Ilmenit / Agenda, 2022 9 | 10 | PCs had "Comanche: Maximum Overkill" 11 | 8bits had "Rescue on Fractalus!" 12 | 13 | Greetings to all sizecoders! 14 | -------------------------------------------------------------------------------- /rescue_on_mars!/rescue_on_mars!.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/rescue_on_mars!/rescue_on_mars!.png -------------------------------------------------------------------------------- /rescue_on_mars!/rescue_on_mars!.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/rescue_on_mars!/rescue_on_mars!.xex -------------------------------------------------------------------------------- /stairs_in_the_sky.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/stairs_in_the_sky.zip -------------------------------------------------------------------------------- /stairs_in_the_sky/stairs_in_the_sky.asm: -------------------------------------------------------------------------------- 1 | ROWCRS EQU $0054 ;1-byte cursor row 2 | COLCRS EQU $0055 ;2-byte cursor column 3 | OLDROW EQU $005A ;1-byte prior row 4 | OLDCOL EQU $005B ;2-byte prior column 5 | 6 | ; Aliases, because orig reg names are hard to remember ;) 7 | cursor_y equ ROWCRS 8 | cursor_x equ COLCRS 9 | prev_y equ OLDROW 10 | prev_x equ OLDCOL 11 | 12 | COLOR equ $2fb ;Color for graphics operations 13 | 14 | PCOLR0 equ $02C0 ;p/m 0 color 15 | PCOLR1 equ $02C1 ;p/m 1 color 16 | PCOLR2 equ $02C2 ;p/m 2 color 17 | PCOLR3 equ $02C3 ;p/m 3 color 18 | COLOR0 equ $02c4 19 | 20 | 21 | COLPF0 equ $D016 22 | COLPF1 equ $D017 23 | COLPF2 equ $D018 24 | COLPF3 equ $D019 25 | COLBK equ $D01A 26 | 27 | 28 | HPOSP0 = $D000 ; Player 0 Horizontal Position 29 | HPOSP1 = $D001 ; Player 1 Horizontal Position 30 | HPOSP2 = $D002 ; Player 2 Horizontal Position 31 | HPOSP3 = $D003 ; Player 3 Horizontal Position 32 | 33 | SIZEP0 = $D008 ; Player 0 Size 34 | COLPM2 = $D014 ; Player/Missile 2 color, GTIA 9-color playfield color 2 35 | 36 | AUDCTL equ $D208 37 | 38 | WSYNC equ $D40A ; Wait for Horizontal Sync 39 | 40 | VCOUNT equ $D40B 41 | 42 | ; OS functions 43 | os_openmode equ $ef9c 44 | os_drawto equ $f9c2 45 | 46 | ;; intro defines 47 | 48 | STAIRS_BOTTOM equ $A2 49 | ;STAIRS_RIGHT equ $5D 50 | STAIRS_RIGHT equ $50 51 | 52 | ;SAVMSC is $A150 53 | 54 | screen_y equ $0 55 | temp equ $3 56 | 57 | org $80 58 | bvc start 59 | 60 | data 61 | sky_hi_location 62 | .byte $FF ; yellow color p2 for rays 63 | left 64 | .byte $0F ; white for clouds 65 | colors 66 | .byte 7 ; gray 67 | sky_lo_location 68 | .byte 0 ; black 69 | .byte $8F ; white 70 | gate_height 71 | .byte $24 ; not used in this mode 72 | .byte $86 ; background middle-blue 73 | start: 74 | lda #15 75 | 76 | jsr os_openmode 77 | ; a=?/0, x=15, y=1 78 | 79 | .local set_colors 80 | loop: 81 | lda $C9A0,x 82 | sta AUDCTL-8,x 83 | 84 | lda #$FF 85 | sta SIZEP0-4,x 86 | lda colors-(colors-data),x ; sets also colors of player 87 | sta color0-(colors-data),x 88 | dex 89 | rom_location 90 | bpl loop 91 | ; x = 0, A = last reg 92 | .endl 93 | 94 | lda #STAIRS_BOTTOM 95 | 96 | .local draw_stairs 97 | ; last register A value from loop ; lda #STAIRS_BOTTOM 98 | sta cursor_y 99 | sta prev_y 100 | 101 | lda #STAIRS_RIGHT 102 | sta cursor_x 103 | loop: 104 | inc color 105 | dec cursor_y 106 | 107 | lda left 108 | sta prev_x 109 | 110 | jsr os_drawto 111 | ; x=2, y=1 112 | next_loop: 113 | lda cursor_y 114 | and #%1000 115 | beq vertical 116 | diagonal: 117 | dec color 118 | :2 inc left 119 | inc cursor_x 120 | vertical: 121 | bpl loop 122 | .endl 123 | 124 | 125 | .local draw_gate 126 | loop: 127 | lda left 128 | sta prev_x 129 | jsr os_drawto 130 | next_loop: 131 | dec cursor_y 132 | dec prev_y 133 | dec gate_height 134 | bne loop 135 | .endl 136 | 137 | screen_loop: 138 | ldy VCOUNT 139 | tya 140 | asl 141 | sta COLPF2 142 | adc #$6D 143 | sta HPOSP2 144 | tya 145 | adc (sky_lo_location),y 146 | sta (sky_lo_location),y 147 | lda (sky_hi_location),y 148 | sbc #0 149 | sta (sky_hi_location),y 150 | adc (set_colors.rom_location),y ; add "random" rom value - 1 byte shorter version of "adc $F048,y" 151 | sta wsync 152 | sta HPOSP3 153 | jmp screen_loop 154 | -------------------------------------------------------------------------------- /stairs_in_the_sky/stairs_in_the_sky.nfo: -------------------------------------------------------------------------------- 1 | [Stairs In The Sky] 2 | 3 | The exit you were looking for. 4 | 5 | For Lovebyte party 2022, "Combined 128 byte intro compo" 6 | Requires Atari XL/XE OS Rev2 7 | Code: Ilmenit / Agenda '2022 8 | 9 | Greetings to all sizecoders! 10 | -------------------------------------------------------------------------------- /stairs_in_the_sky/stairs_in_the_sky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/stairs_in_the_sky/stairs_in_the_sky.png -------------------------------------------------------------------------------- /stairs_in_the_sky/stairs_in_the_sky.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/stairs_in_the_sky/stairs_in_the_sky.xex -------------------------------------------------------------------------------- /sunrise8.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/sunrise8.zip -------------------------------------------------------------------------------- /sunrise8/sunrise8.asm: -------------------------------------------------------------------------------- 1 | org $22C 2 | loop 3 | jsr $ED8A 4 | STX $D01A 5 | bvc loop 6 | -------------------------------------------------------------------------------- /sunrise8/sunrise8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/sunrise8/sunrise8.png -------------------------------------------------------------------------------- /sunrise8/sunrise8.xex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/sunrise8/sunrise8.xex -------------------------------------------------------------------------------- /sunrise8/sunrise8b.nfo: -------------------------------------------------------------------------------- 1 | [Sunrise8b] 2 | 3 | Day by day 4 | 5 | For Lovebyte party 2022, "8-16 byte intro showcase" 6 | Requires Atari XL/XE OS Rev2 7 | Code: Ilmenit / Agenda 8 | 9 | org $22C 10 | loop 11 | jsr $ED8A 12 | STX $D01A 13 | bvc loop 14 | 15 | I never thought of doing 8 byte intro 16 | ... but guys from Agenda started ;-) 17 | 18 | Greetings to all sizecoders! 19 | -------------------------------------------------------------------------------- /thrive.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/thrive.zip -------------------------------------------------------------------------------- /thrive/thrive.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/thrive/thrive.gif -------------------------------------------------------------------------------- /thrive/thrive.lua: -------------------------------------------------------------------------------- 1 | -- title: Thrive 2 | -- author: Ilmenit / Agenda 3 | -- desc: What will grow out of a tiny seed? 4 | -- script: lua 5 | 6 | function b(x,y,a,l) 7 | for i=0,l do 8 | -- position with rotation by angle 9 | j=y+i*s(a)+3*s(i/9)*s(a-8) 10 | k=x+i*s(a-8)-3*s(i/9)*s(a) 11 | 12 | -- leaves 13 | circ(k, 14 | -- random * growth by time * falling by time / growth time divider 15 | j+s(i)*m(t-633,4)*m(1133-t,1), 16 | -- negative size is hiding leaves 17 | m(t-633-i,1), 18 | -- color of leaves modified by time, with time limit 19 | 3*s(i/9)-m(t/36,36)) 20 | 21 | -- branch gets thinner in time 22 | n=l-i 23 | 24 | -- tree 25 | rect(k,j,n/33,n/33,0) 26 | -- snow on the branches, appearing in time 27 | rect(k,j,n/33,m(t-1633-i,1),-m(t-1633-i,133)/33) 28 | 29 | -- sub-branch 30 | if i%14==9 then 31 | b(k,j,a+s(i)+s(t/33)/33,n-33) 32 | end 33 | end 34 | end 35 | 36 | function TIC() 37 | -- the full screen 38 | for i=0,32639 do 39 | -- background, substracting from color divided y position + dither 40 | poke4(i,63-i/3333+i*s(i)%1) 41 | 42 | -- 60*.4=24, 1000/41.6=24 43 | -- 60*.36=21.6, 1000/46=21.7 44 | 45 | t=time()/46 46 | 47 | -- falling snow 48 | pix(i%333,t-2433+i*s(i*i)/33,12) 49 | end 50 | 51 | --t=t+.36 52 | 53 | 54 | b(123,123,5,m(t,263)) 55 | end 56 | s=math.sin 57 | m=math.min 58 | --t=0 -------------------------------------------------------------------------------- /thrive/thrive.nfo: -------------------------------------------------------------------------------- 1 | [Thrive] 2 | 3 | What will grow out of a tiny seed? 4 | 5 | Tic-80 fantasy console (1.0.2164) 6 | Code: Ilmenit / Agenda, 2022 7 | 8 | Dedicated to my daughter Olive. 9 | Thrive, my little one! 10 | 11 | Greetings to all sizecoders! 12 | -------------------------------------------------------------------------------- /thrive/thrive.tic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/thrive/thrive.tic -------------------------------------------------------------------------------- /ukr.tic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/ukr.tic -------------------------------------------------------------------------------- /urban_drift.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/urban_drift.zip -------------------------------------------------------------------------------- /urban_drift/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Urban Drift 5 | 6 | 7 | 8 |
9 |
10 |

Resolution & Quality

11 |
12 | 13 | 19 |
20 |
21 | 22 | 29 |
30 |
31 | 32 |
33 |

Day/Night Cycle

34 |
35 | 36 | 37 |
38 |
39 | 40 | 41 | 50% 42 |
43 |
44 | 45 | 46 | 64 47 |
48 |
49 | 50 |
51 |

Camera Movement

52 |
53 | 54 | 55 |
56 |
57 | 58 | 59 | 60 |
61 |
62 | 63 | 64 | 16 65 |
66 |
67 | 68 |
69 |

Building Parameters

70 |
71 | 72 | 73 | 0.014 74 |
75 |
76 | 77 | 78 | 0.44 79 |
80 |
81 | 82 |
83 |

Reflections

84 |
85 | 86 | 87 |
88 |
89 | 90 | 91 |
92 |
93 | 94 | 95 | 8 96 |
97 |
98 | 99 |
100 |

Windows

101 |
102 | 103 | 104 | 0.88 105 |
106 |
107 | 108 | 109 | 0.88 110 |
111 |
112 | 113 | 114 |
115 |
116 | 117 |
118 |

Shadows

119 |
120 | 121 | 122 |
123 |
124 | 125 | 126 | 16 127 |
128 |
129 | 130 |
131 |

Ray Casting

132 |
133 | 134 | 135 | 64 136 |
137 |
138 |
139 | 140 |
141 | 142 |
143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /urban_drift/js/controls.js: -------------------------------------------------------------------------------- 1 | class Controls { 2 | constructor() { 3 | this.settings = { ...CONFIG.defaults }; 4 | this.initializeControls(); 5 | this.setupEventListeners(); 6 | } 7 | 8 | initializeControls() { 9 | this.elements = { 10 | resolution: document.getElementById('resolution'), 11 | bayerPattern: document.getElementById('bayer-pattern'), 12 | autoRotate: document.getElementById('auto-rotate'), 13 | rotationAngle: document.getElementById('rotation-angle'), 14 | rotationSpeed: document.getElementById('rotation-speed'), 15 | shadowsEnabled: document.getElementById('shadows-enabled'), 16 | shadowQuality: document.getElementById('shadow-quality'), 17 | raycastSteps: document.getElementById('raycast-steps'), 18 | autoDaytime: document.getElementById('auto-daytime'), 19 | dayTime: document.getElementById('day-time'), 20 | daySpeed: document.getElementById('day-speed'), 21 | epsilon: document.getElementById('epsilon'), 22 | buildingSize: document.getElementById('building-size'), 23 | windowSizeH: document.getElementById('window-size-h'), 24 | windowSizeV: document.getElementById('window-size-v'), 25 | reflectionsEnabled: document.getElementById('reflections-enabled'), 26 | infiniteReflections: document.getElementById('infinite-reflections'), 27 | reflectionDepth: document.getElementById('reflection-depth'), 28 | windowLightsEnabled: document.getElementById('window-lights-enabled') 29 | }; 30 | 31 | this.updateValueDisplays(); 32 | this.updateDisabledStates(); 33 | } 34 | 35 | setupEventListeners() { 36 | document.querySelectorAll('input[type="range"]').forEach(input => { 37 | const display = input.nextElementSibling; 38 | if (display) { 39 | input.addEventListener('input', () => { 40 | const value = this.convertInputToValue(input.id, input.value); 41 | display.textContent = this.formatValue(input.id, value); 42 | this.updateSetting(input.id, value); 43 | }); 44 | } 45 | }); 46 | 47 | document.querySelectorAll('input[type="checkbox"], select').forEach(input => { 48 | input.addEventListener('change', () => { 49 | const value = input.type === 'checkbox' ? input.checked : input.value; 50 | this.updateSetting(input.id, value); 51 | if (input.type === 'checkbox') { 52 | this.updateDisabledStates(); 53 | } 54 | }); 55 | }); 56 | } 57 | 58 | convertInputToValue(id, value) { 59 | switch(id) { 60 | case 'epsilon': 61 | return Number(value) / 1000; 62 | case 'building-size': 63 | return Number(value) / 100; 64 | case 'window-size-h': 65 | case 'window-size-v': 66 | return Number(value) / 100; 67 | default: 68 | return Number(value); 69 | } 70 | } 71 | 72 | updateSetting(id, value) { 73 | if (id === 'resolution') { 74 | const [width, height] = value.split('x').map(Number); 75 | this.settings.resolution = { width, height }; 76 | this.onSettingsChange({ resolution: { width, height }}); 77 | return; 78 | } 79 | 80 | const settingKey = this.getSettingKey(id); 81 | this.settings[settingKey] = value; 82 | 83 | // Handle reflection depth calculations 84 | this.updateReflectionSettings(id, value); 85 | 86 | this.onSettingsChange({ [settingKey]: value }); 87 | } 88 | 89 | updateReflectionSettings(id, value) { 90 | if (id === 'reflections-enabled' || id === 'infinite-reflections' || id === 'reflection-depth') { 91 | const reflectionsEnabled = this.elements.reflectionsEnabled.checked; 92 | const infiniteReflections = this.elements.infiniteReflections.checked; 93 | const depthValue = Number(this.elements.reflectionDepth.value); 94 | 95 | this.settings.reflectionDepth = !reflectionsEnabled ? 0 : 96 | infiniteReflections ? -1 : 97 | depthValue; 98 | } 99 | } 100 | 101 | getSettingKey(id) { 102 | return id.replace(/-([a-z])/g, g => g[1].toUpperCase()); 103 | } 104 | 105 | formatValue(id, value) { 106 | switch(id) { 107 | case 'rotation-angle': 108 | return value + '°'; 109 | case 'day-time': 110 | return value + '%'; 111 | case 'epsilon': 112 | case 'building-size': 113 | case 'window-size-h': 114 | case 'window-size-v': 115 | return value.toFixed(3); 116 | default: 117 | return value.toString(); 118 | } 119 | } 120 | 121 | updateValueDisplays() { 122 | document.querySelectorAll('input[type="range"]').forEach(input => { 123 | const display = input.nextElementSibling; 124 | if (display) { 125 | const value = this.convertInputToValue(input.id, input.value); 126 | display.textContent = this.formatValue(input.id, value); 127 | } 128 | }); 129 | } 130 | 131 | updateDisabledStates() { 132 | this.elements.rotationSpeed.disabled = !this.elements.autoRotate.checked; 133 | this.elements.rotationAngle.disabled = this.elements.autoRotate.checked; 134 | this.elements.daySpeed.disabled = !this.elements.autoDaytime.checked; 135 | this.elements.dayTime.disabled = this.elements.autoDaytime.checked; 136 | 137 | // Update reflection controls disabled states 138 | const reflectionsEnabled = this.elements.reflectionsEnabled.checked; 139 | this.elements.infiniteReflections.disabled = !reflectionsEnabled; 140 | this.elements.reflectionDepth.disabled = !reflectionsEnabled || this.elements.infiniteReflections.checked; 141 | 142 | // Update reflection settings when disabled states change 143 | this.updateReflectionSettings('reflections-enabled', reflectionsEnabled); 144 | } 145 | 146 | getSettings() { 147 | return { ...this.settings }; 148 | } 149 | 150 | onSettingsChange(changedSettings) { 151 | if (app) { 152 | if (changedSettings.resolution) { 153 | app.renderer.resize(changedSettings.resolution.width, changedSettings.resolution.height); 154 | } 155 | if (changedSettings.bayerPattern) { 156 | app.renderer.updateBayerMatrix(changedSettings.bayerPattern); 157 | } 158 | app.engine.updateSettings(this.settings); 159 | } 160 | } 161 | } -------------------------------------------------------------------------------- /urban_drift/js/engine.js: -------------------------------------------------------------------------------- 1 | class Engine { 2 | constructor(settings) { 3 | this.updateSettings(settings); 4 | } 5 | 6 | updateSettings(settings) { 7 | this.settings = settings; 8 | } 9 | 10 | sdf(px, py, pz) { 11 | const gx = Math.floor(px); 12 | const gz = Math.floor(pz); 13 | let d = py; 14 | 15 | for (let i = 0; i < 9; i++) { 16 | const dx = Math.floor(i / 3) - 1; 17 | const dz = (i % 3) - 1; 18 | 19 | const gxDx = gx + dx; 20 | const pxOffset = px - (gxDx + 0.5); 21 | const absX = MathUtils.abs(pxOffset) - this.settings.buildingSize; 22 | 23 | const h2 = Math.fround(((gxDx ^ (gz + dz)) & 7) / 4); 24 | const pzOffset = pz - ((gz + dz) + 0.5); 25 | const absZ = MathUtils.abs(pzOffset) - this.settings.buildingSize; 26 | const absY = MathUtils.abs(py - h2) - h2; 27 | 28 | d = MathUtils.min(d, MathUtils.max(absX, MathUtils.max(absY, absZ))); 29 | } 30 | return d; 31 | } 32 | 33 | raycast(px, py, pz, rdX, rdY, rdZ, reflectionDepth = -1) { 34 | let dist = 0; 35 | const day_time = this.calculateDayTime(); 36 | 37 | for (let step = 0; step < this.settings.raycastSteps; step++) { 38 | let h = this.sdf(px, py, pz); 39 | 40 | if (h < this.settings.epsilon) { 41 | const nx = this.sdf(px + this.settings.epsilon, py, pz) - h; 42 | const ny = this.sdf(px, py + this.settings.epsilon, pz) - h; 43 | const nz = this.sdf(px, py, pz + this.settings.epsilon) - h; 44 | const nl = 1.0078125 / MathUtils.sqrt(nx * nx + ny * ny + nz * nz); 45 | 46 | let light = (nx + ny * day_time - nz * day_time) * nl; 47 | 48 | if (this.settings.shadowsEnabled) { 49 | let t = 0.1248779296875; 50 | let shadow_hit = false; 51 | 52 | for (let j = 0; j < this.settings.shadowQuality && !shadow_hit; j++) { 53 | const sh = this.sdf( 54 | px + t, 55 | py + t * day_time, 56 | pz - t * day_time 57 | ); 58 | if (sh < this.settings.epsilon) { 59 | light /= 8; 60 | shadow_hit = true; 61 | } else { 62 | light = MathUtils.min(light, sh * (8/t)); 63 | t = t + sh; 64 | } 65 | } 66 | } 67 | 68 | if (MathUtils.abs(ny * nl) < this.settings.epsilon) { 69 | const w = MathUtils.abs(nx) > MathUtils.abs(nz) ? pz : px; 70 | const is_window_frame = MathUtils.abs(MathUtils.fmod(4 * w, 1)) <= this.settings.windowSizeH; 71 | const is_window_frame2 = MathUtils.abs(MathUtils.fmod(4 * py, 1)) <= this.settings.windowSizeV; 72 | 73 | if (is_window_frame && is_window_frame2) { 74 | if (this.settings.reflectionsEnabled && reflectionDepth !== 0) { 75 | const ndotrd = 2 * (nx * rdX + ny * rdY + nz * rdZ) * nl * nl; 76 | const rrX = rdX - ndotrd * nx; 77 | const rrY = rdY - ndotrd * ny; 78 | const rrZ = rdZ - ndotrd * nz; 79 | 80 | const nextDepth = reflectionDepth > 0 ? reflectionDepth - 1 : reflectionDepth; 81 | const reflLight = this.raycast( 82 | px + rrX * this.settings.epsilon, 83 | py + rrY * this.settings.epsilon, 84 | pz + rrZ * this.settings.epsilon, 85 | rrX, rrY, rrZ, 86 | nextDepth 87 | ); 88 | 89 | light = MathUtils.min((light + reflLight) * 0.5, 1); 90 | } 91 | 92 | if (this.settings.windowLightsEnabled) { 93 | const wx = Math.floor(w * 16); 94 | const wy = Math.floor(py * 16); 95 | 96 | if (((wx ^ wy ^ Math.floor(wx / 2)) & 28) === 0) { 97 | light = 3 + (light - 3) * day_time; 98 | } 99 | } 100 | } 101 | } 102 | 103 | light += (day_time - light) / 8 * dist; 104 | return MathUtils.min(MathUtils.max(light, 0), 0.875); 105 | } 106 | 107 | h /= 4; 108 | px += rdX * h; 109 | py += rdY * h; 110 | pz += rdZ * h; 111 | dist += h; 112 | } 113 | return day_time; 114 | } 115 | 116 | calculateDayTime() { 117 | if (this.settings.autoDaytime) { 118 | return MathUtils.abs(MathUtils.fmod(MathUtils.time() / this.settings.daySpeed, 2) - 1); 119 | } 120 | return this.settings.dayTime / 100; 121 | } 122 | } -------------------------------------------------------------------------------- /urban_drift/js/main.js: -------------------------------------------------------------------------------- 1 | // Main application class 2 | class App { 3 | constructor() { 4 | this.canvas = document.getElementById('canvas'); 5 | this.controls = new Controls(); 6 | this.engine = new Engine(this.controls.getSettings()); 7 | this.renderer = new Renderer(this.canvas, this.engine); 8 | 9 | const initialSettings = this.controls.getSettings(); 10 | this.renderer.resize(initialSettings.resolution.width, initialSettings.resolution.height); 11 | 12 | requestAnimationFrame(this.render.bind(this)); 13 | } 14 | 15 | render() { 16 | this.renderer.render(this.controls.getSettings()); 17 | requestAnimationFrame(this.render.bind(this)); 18 | } 19 | } 20 | 21 | // Global app instance (needed for controls callbacks) 22 | let app; 23 | 24 | // Initialize when the page loads 25 | window.addEventListener('load', () => { 26 | app = new App(); 27 | }); -------------------------------------------------------------------------------- /urban_drift/js/renderer.js: -------------------------------------------------------------------------------- 1 | class Renderer { 2 | constructor(canvas, engine) { 3 | this.canvas = canvas; 4 | this.engine = engine; 5 | this.ctx = canvas.getContext('2d'); 6 | this.frameCount = 0; 7 | this.bayerSize = 8; 8 | this.updateBayerMatrix(16); 9 | } 10 | 11 | updateBayerMatrix(size) { 12 | this.bayerMatrix = new Uint8Array(this.bayerSize * this.bayerSize); 13 | for(let y = 0; y < this.bayerSize; y++) { 14 | for(let x = 0; x < this.bayerSize; x++) { 15 | let m = 0; 16 | for(let bit = 0; bit < 6; bit++) { 17 | const mask = 1 << bit; 18 | m |= (((x & mask) >> bit) << (2 * bit + 1)) | 19 | (((y & mask) >> bit) << (2 * bit)); 20 | } 21 | this.bayerMatrix[y * this.bayerSize + x] = m; 22 | } 23 | } 24 | this.bayerDivisor = size; 25 | } 26 | 27 | resize(width, height) { 28 | this.canvas.width = width; 29 | this.canvas.height = height; 30 | this.imageData = this.ctx.createImageData(width, height); 31 | this.calculateScaleFactor(); 32 | } 33 | 34 | calculateScaleFactor() { 35 | // Get the container dimensions 36 | const container = this.canvas.parentElement; 37 | const containerWidth = container.clientWidth; 38 | const containerHeight = container.clientHeight; 39 | 40 | // Calculate the scale needed to fit the canvas to the container 41 | const containerRatio = containerWidth / containerHeight; 42 | const canvasRatio = this.canvas.width / this.canvas.height; 43 | 44 | if (containerRatio > canvasRatio) { 45 | // Container is wider than needed 46 | this.canvas.style.height = containerHeight + 'px'; 47 | this.canvas.style.width = (containerHeight * canvasRatio) + 'px'; 48 | } else { 49 | // Container is taller than needed 50 | this.canvas.style.width = containerWidth + 'px'; 51 | this.canvas.style.height = (containerWidth / canvasRatio) + 'px'; 52 | } 53 | 54 | // Calculate scale factors for internal use 55 | this.scaleX = this.canvas.width / 320; // Base scale factor 56 | this.scaleY = this.canvas.height / 240; 57 | } 58 | 59 | calculateAngle(settings) { 60 | if (settings.autoRotate) { 61 | return MathUtils.time() / settings.rotationSpeed; 62 | } 63 | return settings.rotationAngle * (Math.PI / 180); 64 | } 65 | 66 | render(settings) { 67 | const angle = this.calculateAngle(settings); 68 | const s = MathUtils.sin(angle); 69 | const c = MathUtils.cos(angle); 70 | 71 | const patternOffset = this.frameCount % this.bayerDivisor; 72 | const data = this.imageData.data; 73 | 74 | for (let y = 0; y < this.canvas.height; y++) { 75 | const v = (100 - y / this.scaleY) / 100; 76 | 77 | for (let x = 0; x < this.canvas.width; x++) { 78 | // Use Bayer matrix for temporal sampling 79 | const bayerX = Math.floor(x / this.scaleX) % this.bayerSize; 80 | const bayerY = Math.floor(y / this.scaleY) % this.bayerSize; 81 | const bayerValue = this.bayerMatrix[bayerY * this.bayerSize + bayerX]; 82 | 83 | if ((bayerValue % this.bayerDivisor) !== patternOffset) { 84 | continue; 85 | } 86 | 87 | const u = (160 - x / this.scaleX) / 100; 88 | const rdX = -c * u - 2 * s; 89 | const rdY = v - 0.7; 90 | const rdZ = s * u - 2 * c; 91 | 92 | const light = this.engine.raycast( 93 | 4 * s, 94 | 4 - Math.abs(MathUtils.fmod(angle/4, 2)-1), 95 | 4 * c, 96 | rdX, rdY, rdZ, 97 | settings.reflectionDepth // Pass the reflection depth directly from settings 98 | ); 99 | 100 | const color = Math.floor(240 * light); 101 | const idx = (y * this.canvas.width + x) * 4; 102 | 103 | data[idx] = color; 104 | data[idx + 1] = color; 105 | data[idx + 2] = color; 106 | data[idx + 3] = 255; 107 | } 108 | } 109 | 110 | this.ctx.putImageData(this.imageData, 0, 0); 111 | this.frameCount++; 112 | } 113 | } -------------------------------------------------------------------------------- /urban_drift/js/utils.js: -------------------------------------------------------------------------------- 1 | // Math utility functions 2 | const MathUtils = { 3 | abs: Math.abs, 4 | min: Math.min, 5 | max: Math.max, 6 | sin: Math.sin, 7 | cos: Math.cos, 8 | sqrt: Math.sqrt, 9 | fmod: (x, y) => x % y, 10 | time: () => performance.now() / 1000 11 | }; 12 | 13 | // Default configuration 14 | const CONFIG = { 15 | defaults: { 16 | resolution: { width: 320, height: 240 }, 17 | bayerPattern: 16, 18 | autoRotate: true, 19 | rotationAngle: 0, 20 | rotationSpeed: 16, 21 | shadowsEnabled: true, 22 | shadowQuality: 16, 23 | raycastSteps: 64, 24 | autoDaytime: true, 25 | dayTime: 50, 26 | daySpeed: 64, 27 | epsilon: 0.013671875, 28 | buildingSize: 0.4375, 29 | windowSizeH: 0.875, 30 | windowSizeV: 0.875, 31 | reflectionsEnabled: true, 32 | infiniteReflections: true, 33 | reflectionDepth: 8, 34 | windowLightsEnabled: true 35 | } 36 | }; -------------------------------------------------------------------------------- /urban_drift/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | background: #1a1a1a; 5 | color: #fff; 6 | font-family: system-ui, -apple-system, sans-serif; 7 | min-height: 100vh; 8 | display: flex; 9 | overflow: hidden; 10 | } 11 | 12 | .controls { 13 | background: #2a2a2a; 14 | padding: 16px; 15 | width: 320px; 16 | min-width: 320px; 17 | height: 100vh; 18 | overflow-y: auto; 19 | display: flex; 20 | flex-direction: column; 21 | gap: 16px; 22 | box-shadow: 2px 0 10px rgba(0, 0, 0, 0.3); 23 | } 24 | 25 | .control-group { 26 | display: flex; 27 | flex-direction: column; 28 | gap: 8px; 29 | padding: 12px; 30 | background: #333; 31 | border-radius: 6px; 32 | } 33 | 34 | .control-group h3 { 35 | margin: 0 0 8px 0; 36 | font-size: 14px; 37 | color: #aaa; 38 | font-weight: 600; 39 | text-transform: uppercase; 40 | letter-spacing: 0.5px; 41 | } 42 | 43 | .control-row { 44 | display: flex; 45 | align-items: center; 46 | gap: 8px; 47 | } 48 | 49 | select, input[type="range"] { 50 | background: #444; 51 | border: 1px solid #555; 52 | color: #fff; 53 | padding: 4px 8px; 54 | border-radius: 4px; 55 | font-size: 14px; 56 | } 57 | 58 | select { 59 | width: 120px; 60 | } 61 | 62 | input[type="range"] { 63 | flex: 1; 64 | } 65 | 66 | input[type="checkbox"] { 67 | margin: 0; 68 | width: 16px; 69 | height: 16px; 70 | } 71 | 72 | label { 73 | font-size: 14px; 74 | min-width: 100px; 75 | } 76 | 77 | .value-display { 78 | font-size: 14px; 79 | color: #aaa; 80 | min-width: 45px; 81 | text-align: right; 82 | } 83 | 84 | .canvas-container { 85 | flex: 1; 86 | display: flex; 87 | justify-content: center; 88 | align-items: center; 89 | background: #000; 90 | padding: 16px; 91 | } 92 | 93 | canvas { 94 | image-rendering: pixelated; 95 | max-width: 100%; 96 | max-height: 100%; 97 | aspect-ratio: 4/3; 98 | object-fit: contain; 99 | } 100 | 101 | /* Scrollbar styling */ 102 | .controls::-webkit-scrollbar { 103 | width: 8px; 104 | } 105 | 106 | .controls::-webkit-scrollbar-track { 107 | background: #1a1a1a; 108 | } 109 | 110 | .controls::-webkit-scrollbar-thumb { 111 | background: #444; 112 | border-radius: 4px; 113 | } 114 | 115 | .controls::-webkit-scrollbar-thumb:hover { 116 | background: #555; 117 | } -------------------------------------------------------------------------------- /urban_drift/urban_drift.cwa: -------------------------------------------------------------------------------- 1 | include "include/microw8-api.cwa" 2 | 3 | //const EPSILON: f32 = 0.00009765625; 4 | //const EPSILON: f32 = 0.0048828125; 5 | //const EPSILON: f32 = 0.009765625; 6 | const EPSILON: f32 = 0.013671875; 7 | const BUILDING_SIZE: f32 = 0.4375; 8 | const RAYCAST_STEPS: i32 = 64; 9 | 10 | const ALMOST_0_9 = 0.875; 11 | 12 | fn sdf(px: f32, py: f32, pz: f32) -> f32 { 13 | let inline gx = px as i32; 14 | let inline gz = pz as i32; 15 | let d = py; 16 | let i: i32 = 0; 17 | loop grid_loop { 18 | let inline dx = (i / 3) - 1; 19 | let inline dz = (i % 3) - 1; 20 | 21 | let gxDx = gx + dx; 22 | let inline pxOffset = px - ((gxDx as f32) + 0.5); 23 | let inline absX = abs(pxOffset) - BUILDING_SIZE; 24 | 25 | let h2 = (((gxDx ^ (gz + dz)) & 7) as f32) / 4_f; 26 | let inline pzOffset = pz - ((gz + dz) as f32 + 0.5); 27 | let inline absZ = abs(pzOffset) - BUILDING_SIZE; 28 | let inline absY = abs(py - h2) - h2; 29 | 30 | d = min(d, max(absX, max(absY, absZ))); 31 | 32 | branch_if (i := i + 1) < 9: grid_loop; 33 | } 34 | d 35 | } 36 | 37 | fn raycast(px: f32, py: f32, pz: f32, rdX: f32, rdY: f32, rdZ: f32) -> f32 { 38 | let dist: f32; 39 | let step: i32; 40 | 41 | let day_time: f32 = abs(fmod(time()/64_f,2_f)-1_f); 42 | 43 | loop raycast_loop { 44 | let h = sdf(px, py, pz); 45 | 46 | if h < EPSILON { 47 | 48 | let nx = sdf(px + EPSILON, py, pz) - h; 49 | let ny = sdf(px, py + EPSILON, pz) - h; 50 | let nz = sdf(px, py, pz + EPSILON) - h; 51 | let nl = 1.0078125 / sqrt(nx * nx + ny * ny + nz * nz); 52 | 53 | let light = (nx + ny * day_time - nz * day_time) * nl; 54 | 55 | // Soft shadows 56 | let t: f32 = 0.1248779296875; 57 | let j: i32 = 0; 58 | block shadow_calc { 59 | loop shadow_loop { 60 | let sh = sdf( 61 | px + t, 62 | py + t * day_time, 63 | pz - t * day_time 64 | ); 65 | if sh < EPSILON { 66 | light /= 8_f; 67 | 68 | branch shadow_calc; 69 | } 70 | light = min(light, sh * (8_f/t)); 71 | t = t + sh; 72 | branch_if (j := j + 1) < 16: shadow_loop; 73 | } 74 | } 75 | 76 | // Window reflections 77 | if abs(ny * nl) < EPSILON { 78 | let inline w = if abs(nx) > abs(nz) { pz } else { px }; 79 | let inline is_window_frame = abs(fmod(4_f * w, 1_f)) <= ALMOST_0_9; 80 | let inline is_window_frame2 = abs(fmod(4_f * py, 1_f)) <= ALMOST_0_9; 81 | if (is_window_frame & is_window_frame2) { 82 | let lazy ndotrd = 2_f * (nx * rdX + ny * rdY + nz * rdZ) * nl * nl; 83 | let lazy rrX = rdX - ndotrd * nx; 84 | let lazy rrY = rdY - ndotrd * ny; 85 | let lazy rrZ = rdZ - ndotrd * nz; 86 | 87 | let inline reflLight = raycast( 88 | px + rrX * EPSILON, 89 | py + rrY * EPSILON, 90 | pz + rrZ * EPSILON, 91 | rrX, rrY, rrZ 92 | ); 93 | 94 | let inline wx = (w * 16_f) as i32; 95 | let inline wy = (py * 16_f) as i32; 96 | 97 | if (wx ^ wy ^ (wx / 2) & 28) == 0 { 98 | // bright windows 99 | light = 3_f + (light - 3_f) * day_time; 100 | } 101 | // min to avoid overflow with bright windows 102 | light = min((light + reflLight) * 0.5,1_f); 103 | } 104 | } 105 | 106 | // Add distance fog 107 | light += (day_time - light) / 8_f * dist; 108 | 109 | return min(max(light,0_f),ALMOST_0_9); 110 | } 111 | 112 | h /= 4_f; 113 | px += rdX * h; 114 | py += rdY * h; 115 | pz += rdZ * h; 116 | dist += h; 117 | branch_if (step := step + 1) < RAYCAST_STEPS: raycast_loop; 118 | } 119 | day_time 120 | } 121 | 122 | export fn upd() { 123 | // Camera setup 124 | let inline angle = time() / 16_f; 125 | let inline s = sin(angle); 126 | let inline c = cos(angle); 127 | 128 | let y: i32; 129 | loop y_loop { 130 | let inline v = (100_f - y as f32) / 100_f; 131 | let x: i32 = 0; 132 | 133 | // set palette 134 | let inline i = 4*y; 135 | i!0x13000 = 0x010101*y; 136 | 137 | loop x_loop { 138 | let lazy u = (160_f - x as f32) / 100_f; 139 | let inline rdX = -c * u - 2_f * s; 140 | let inline rdY = v - 0.7; 141 | let inline rdZ = s * u - 2_f * c; 142 | 143 | let light = raycast(4_f * s, 4_f-abs(fmod(time()/64_f,2_f)-1_f), 4_f * c, rdX, rdY, rdZ); 144 | let inline color = (240_f * light) as i32; 145 | setPixel(x, y, color); 146 | branch_if (x := x + 1) < 320: x_loop; 147 | } 148 | branch_if (y := y + 1) < 240: y_loop; 149 | } 150 | } -------------------------------------------------------------------------------- /urban_drift/urban_drift.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/urban_drift/urban_drift.jpg -------------------------------------------------------------------------------- /urban_drift/urban_drift.nfo: -------------------------------------------------------------------------------- 1 | [Urban Drift] 2 | 3 | Time flows differently when reflections 4 | chase each other through steel canyons. 5 | 6 | For Lovebyte party 2025 7 | 512 Byte High-End Intro Competition 8 | MicroW8 0.4.0 platform 9 | 10 | Greetings to all SizeCoders, including: 11 | 42bastian, blossom, blueberry, busy, dalthon, 12 | digimind, dresdenboy, exoticorn, f#ready, gopher, 13 | hellmood, ionic, ivop, iq, killedbyapixel, kuemmel, 14 | mentor, pellicus, pestis, p01, rrrola, sensenstahl, 15 | serzhsoft, sheriff, sun, superogue, tomcat. 16 | -------------------------------------------------------------------------------- /urban_drift/urban_drift.uw8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ilmenit/sizecoding/e678d165a156fb5cd8bf16d08d1e505c760b63cd/urban_drift/urban_drift.uw8 -------------------------------------------------------------------------------- /urban_drift/urban_drift_js_version.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Urban Drift 5 | 23 | 24 | 25 | 26 | 235 | 236 | --------------------------------------------------------------------------------