diff --git a/Publish/tutorials/TIM/timtris/.gitignore b/Publish/tutorials/TIM/timtris/.gitignore new file mode 100644 index 000000000..b24d71e22 --- /dev/null +++ b/Publish/tutorials/TIM/timtris/.gitignore @@ -0,0 +1,50 @@ +# These are some examples of commonly ignored file patterns. +# You should customize this list as applicable to your project. +# Learn more about .gitignore: +# https://www.atlassian.com/git/tutorials/saving-changes/gitignore + +# Node artifact files +node_modules/ +dist/ + +# Compiled Java class files +*.class + +# Compiled Python bytecode +*.py[cod] + +# Log files +*.log + +# Package files +*.jar + +# Maven +target/ +dist/ + +# JetBrains IDE +.idea/ + +# Unit test reports +TEST*.xml + +# Generated by MacOS +.DS_Store + +# Generated by Windows +Thumbs.db + +# Applications +*.app +*.exe +*.war + +# Large media files +*.mp4 +*.tiff +*.avi +*.flv +*.mov +*.wmv + diff --git a/Publish/tutorials/TIM/timtris/README.md b/Publish/tutorials/TIM/timtris/README.md new file mode 100644 index 000000000..caa35c0ad --- /dev/null +++ b/Publish/tutorials/TIM/timtris/README.md @@ -0,0 +1,43 @@ +# TimTris v0.9 + +This repository contains source code written in [TRSE](https://lemonspawn.com/turbo-rascal-syntax-error-expected-but-begin/) by Nicolaas Groeneboom. + +TimTris is a Tetris clone for TIM-011, school computer from Ex-Yugoslavia. Original Tetris is by Alexey Pajitnov. + +Game uses graphics libraries written by me, and file libraries partially adapted from MESCC code by Miguel Garcia Lopez, both part of TRSE. + +PTX Player is by S.V.Bulba, adapted to TIM-011 by Marko Šolajić. To compile it, you'll need [ZASM](https://k1.spdns.de/Develop/Projects/zasm/Distributions/). + +"Tetris 2 Red Dawn" music is by Frantisek Fuka. + +Many thanks to Marko for helping with various TIM stuff and Mićko for TIM-011 MAME emulator! + +## Requirements + +Working TIM-011 (there maybe 10 or less left in the world, so not a huge crowd) with AY sound card (needed if you wan to hear music). + +Oooor... + +MAME emulator, compiled from latest GitHub source, version 0.263 or later. + +## Running + +On real machine, after boot, type to start it, and switch to lower case letters if needed. + +On emulator, run it with: + +``` +mame tim011 -window -v -r 720x512 -switchres -exp ay -flop1 .img +``` + +and do the same as on a real machine. + +NOTICE: Computer needs around 30-40 seconds before anything shows on screen, so be patient! + +## TODO + +* File library still cannot save content, needs debugging/fixing (so high score cannot be saved) +* Adjustments to graphics (mostly cropping) +* Adding cursor keys as input (not yet fully supported by emulator) +* Game sometimes freezes/exits, but that one is so far observed only in emulator, not on real machine, needs more investigating + diff --git a/Publish/tutorials/TIM/timtris/ayplayer/make.sh b/Publish/tutorials/TIM/timtris/ayplayer/make.sh new file mode 100755 index 000000000..8f12a41bb --- /dev/null +++ b/Publish/tutorials/TIM/timtris/ayplayer/make.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# Uses https://k1.spdns.de/Develop/Projects/zasm/Distributions/ + +./zasm ptxplay.asm -o ptxplay.bin + diff --git a/Publish/tutorials/TIM/timtris/ayplayer/ptxplay.bin b/Publish/tutorials/TIM/timtris/ayplayer/ptxplay.bin new file mode 100644 index 000000000..346c696f0 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/ayplayer/ptxplay.bin differ diff --git a/Publish/tutorials/TIM/timtris/ayplayer/tetris2.pt3 b/Publish/tutorials/TIM/timtris/ayplayer/tetris2.pt3 new file mode 100644 index 000000000..98a090805 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/ayplayer/tetris2.pt3 differ diff --git a/Publish/tutorials/TIM/timtris/figure.tru b/Publish/tutorials/TIM/timtris/figure.tru new file mode 100644 index 000000000..f24c6e9fb --- /dev/null +++ b/Publish/tutorials/TIM/timtris/figure.tru @@ -0,0 +1,391 @@ +unit Figure; + +var + // special values + const tmEM: byte = $B8; // empty (dot in the middle) + const tmEN: byte = $FF; // end of definition + + // single block characters + const tmSQ: byte = $90; // one square // 90 + const tmDS: byte = $B6; // darker one square + const tmB1: byte = $B2; // one square broken 1 + const tmB2: byte = $B4; // one square broken 2 + const tmWL: byte = $B0; // wall + + // tetromino font characters + const tmUP: byte = $96; // opening up + const tmDW: byte = $92; // opening down + const tmLF: byte = $98; // opening left + const tmRG: byte = $94; // opening right + + const tmUL: byte = $9E; // opening up-left + const tmUR: byte = $9C; // opening up-right + const tmDL: byte = $A0; // opening down-left + const tmDR: byte = $9A; // opening down-right + + const tmUA: byte = $A6; // opening up on all sides + const tmDA: byte = $A2; // opening down on all sides + const tmLA: byte = $A8; // opening left on all sides + const tmRA: byte = $A4; // opening right on all sides + + const tmHR: byte = $AA; // horizontal pipe + const tmVR: byte = $AC; // vertical pipe + const tmAR: byte = $BC; // arrow down + const tmSP: byte = $BA; // space (really empty) + +/* + O: array[64] of byte = ( + tmSQ,tmSQ,tmEM,tmEM,// * * + tmSQ,tmSQ,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmSQ,tmEM,tmEM,// * * + tmSQ,tmSQ,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmSQ,tmEM,tmEM,// * * + tmSQ,tmSQ,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmSQ,tmEM,tmEM,// * * + tmSQ,tmSQ,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + ); + + T: array[64] of byte = ( + tmEM,tmSQ,tmEM,tmEM,// * + tmSQ,tmSQ,tmSQ,tmEM,// * * * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEM,tmSQ,tmEM,tmEM,// * + tmSQ,tmSQ,tmEM,tmEM,// * * + tmEM,tmSQ,tmEN,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmSQ,tmSQ,tmEM,// * * * + tmEM,tmSQ,tmEN,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmEM,tmEM,tmEM,// * + tmSQ,tmSQ,tmEM,tmEM,// * * + tmSQ,tmEN,tmEM,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + ); + + J: array[64] of byte = ( + tmSQ,tmEM,tmEM,tmEM,// * + tmSQ,tmSQ,tmSQ,tmEM,// * * * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEM,tmSQ,tmEM,tmEM,// * + tmEM,tmSQ,tmEM,tmEM,// * + tmSQ,tmSQ,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmSQ,tmSQ,tmEM,// * * * + tmEM,tmEM,tmSQ,tmEM,// * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmSQ,tmEM,tmEM,// * * + tmSQ,tmEM,tmEM,tmEM,// * + tmSQ,tmEN,tmEM,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + ); + + L: array[64] of byte = ( + tmEM,tmEM,tmSQ,tmEM,// * + tmSQ,tmSQ,tmSQ,tmEM,// * * * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmSQ,tmEM,tmEM,// * * + tmEM,tmSQ,tmEM,tmEM,// * + tmEM,tmSQ,tmEN,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmSQ,tmSQ,tmEM,// * * * + tmSQ,tmEN,tmEM,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmEM,tmEM,tmEM,// * + tmSQ,tmEM,tmEM,tmEM,// * + tmSQ,tmSQ,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + ); + + S: array[64] of byte = ( + tmEM,tmSQ,tmSQ,tmEM,// * * + tmSQ,tmSQ,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmEM,tmEM,tmEM,// * + tmSQ,tmSQ,tmEM,tmEM,// * * + tmEM,tmSQ,tmEN,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + + tmEM,tmSQ,tmSQ,tmEM,// * * + tmSQ,tmSQ,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmEM,tmEM,tmEM,// * + tmSQ,tmSQ,tmEM,tmEM,// * * + tmEM,tmSQ,tmEN,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + ); + + Z: array[64] of byte = ( + tmSQ,tmSQ,tmEM,tmEM,// * * + tmEM,tmSQ,tmSQ,tmEN,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEM,tmSQ,tmEM,tmEM,// * + tmSQ,tmSQ,tmEM,tmEM,// * * + tmSQ,tmEN,tmEM,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + + tmSQ,tmSQ,tmEM,tmEM,// * * + tmEM,tmSQ,tmSQ,tmEN,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEM,tmSQ,tmEM,tmEM,// * + tmSQ,tmSQ,tmEM,tmEM,// * * + tmSQ,tmEN,tmEM,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + ); + + I: array[64] of byte = ( + tmEM,tmEM,tmEM,tmEM, + tmSQ,tmSQ,tmSQ,tmSQ,// * * * * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEm,tmSQ,tmEM,tmEM,// * + tmEm,tmSQ,tmEM,tmEM,// * + tmEm,tmSQ,tmEM,tmEM,// * + tmEm,tmSQ,tmEN,tmEM,// * + + tmEM,tmEM,tmEM,tmEM, + tmSQ,tmSQ,tmSQ,tmSQ,// * * * * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEm,tmSQ,tmEM,tmEM,// * + tmEm,tmSQ,tmEM,tmEM,// * + tmEm,tmSQ,tmEM,tmEM,// * + tmEm,tmSQ,tmEN,tmEM,// * + ); +*/ + O: array[64] of byte = ( + tmDR,tmDL,tmEM,tmEM,// * * + tmUR,tmUL,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmDR,tmDL,tmEM,tmEM,// * * + tmUR,tmUL,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmDR,tmDL,tmEM,tmEM,// * * + tmUR,tmUL,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmDR,tmDL,tmEM,tmEM,// * * + tmUR,tmUL,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + ); + OW: array[16] of byte = ( + tmAR, tmAR, tmSP, tmSP, + tmAR, tmAR, tmSP, tmSP, + tmAR, tmAR, tmSP, tmSP, + tmAR, tmAR, tmSP, tmSP, + ); + + T: array[64] of byte = ( + tmEM,tmDW,tmEM,tmEM,// * + tmRG,tmUA,tmLF,tmEM,// * * * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEM,tmDW,tmEM,tmEM,// * + tmRG,tmLA,tmEM,tmEM,// * * + tmEM,tmUP,tmEN,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + + tmRG,tmDA,tmLF,tmEM,// * * * + tmEM,tmUP,tmEN,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmDW,tmEM,tmEM,tmEM,// * + tmRA,tmLF,tmEM,tmEM,// * * + tmUP,tmEN,tmEM,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + ); + TW: array[16] of byte = ( + tmAR, tmAR, tmAR, tmSP, + tmAR, tmAR, tmSP, tmSP, + tmAR, tmAR, tmAR, tmSP, + tmAR, tmAR, tmSP, tmSP, + ); + + J: array[64] of byte = ( + tmDW,tmEM,tmEM,tmEM,// * + tmUR,tmHR,tmLF,tmEM,// * * * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEM,tmDW,tmEM,tmEM,// * + tmEM,tmVR,tmEM,tmEM,// * + tmRG,tmUL,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + + tmRG,tmHR,tmDL,tmEM,// * * * + tmEM,tmEM,tmUP,tmEM,// * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmDR,tmLF,tmEM,tmEM,// * * + tmVR,tmEM,tmEM,tmEM,// * + tmUP,tmEN,tmEM,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + ); + JW: array[16] of byte = ( + tmAR, tmAR, tmAR, tmSP, + tmAR, tmAR, tmSP, tmSP, + tmAR, tmAR, tmAR, tmSP, + tmAR, tmAR, tmSP, tmSP, + ); + + L: array[64] of byte = ( + tmEM,tmEM,tmDW,tmEM,// * + tmRG,tmHR,tmUL,tmEM,// * * * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmRG,tmDL,tmEM,tmEM,// * * + tmEM,tmVR,tmEM,tmEM,// * + tmEM,tmUP,tmEN,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + + tmDR,tmHR,tmLF,tmEM,// * * * + tmUP,tmEN,tmEM,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmDW,tmEM,tmEM,tmEM,// * + tmVR,tmEM,tmEM,tmEM,// * + tmUR,tmLF,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + ); + LW: array[16] of byte = ( + tmAR, tmAR, tmAR, tmSP, + tmAR, tmAR, tmSP, tmSP, + tmAR, tmAR, tmAR, tmSP, + tmAR, tmAR, tmSP, tmSP, + ); + + S: array[64] of byte = ( + tmEM,tmDR,tmLF,tmEM,// * * + tmRG,tmUL,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmDW,tmEM,tmEM,tmEM,// * + tmUR,tmDL,tmEM,tmEM,// * * + tmEM,tmUP,tmEN,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + + tmEM,tmDR,tmLF,tmEM,// * * + tmRG,tmUL,tmEN,tmEM,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmDW,tmEM,tmEM,tmEM,// * + tmUR,tmDL,tmEM,tmEM,// * * + tmEM,tmUP,tmEN,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + ); + SW: array[16] of byte = ( + tmAR, tmAR, tmAR, tmSP, + tmAR, tmAR, tmSP, tmSP, + tmAR, tmAR, tmAR, tmSP, + tmAR, tmAR, tmSP, tmSP, + ); + + Z: array[64] of byte = ( + tmRG,tmDL,tmEM,tmEM,// * * + tmEM,tmUR,tmLF,tmEN,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEM,tmDW,tmEM,tmEM,// * + tmDR,tmUL,tmEM,tmEM,// * * + tmUP,tmEN,tmEM,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + + tmRG,tmDL,tmEM,tmEM,// * * + tmEM,tmUR,tmLF,tmEN,// * * + tmEM,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEM,tmDW,tmEM,tmEM,// * + tmDR,tmUL,tmEM,tmEM,// * * + tmUP,tmEN,tmEM,tmEM,// * + tmEM,tmEM,tmEM,tmEM, + ); + ZW: array[16] of byte = ( + tmAR, tmAR, tmAR, tmSP, + tmAR, tmAR, tmSP, tmSP, + tmAR, tmAR, tmAR, tmSP, + tmAR, tmAR, tmSP, tmSP, + ); + + I: array[64] of byte = ( + tmEM,tmEM,tmEM,tmEM, + tmRG,tmHR,tmHR,tmLF,// * * * * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEm,tmDW,tmEM,tmEM,// * + tmEm,tmVR,tmEM,tmEM,// * + tmEm,tmVR,tmEM,tmEM,// * + tmEm,tmUP,tmEN,tmEM,// * + + tmEM,tmEM,tmEM,tmEM, + tmRG,tmHR,tmHR,tmLF,// * * * * + tmEN,tmEM,tmEM,tmEM, + tmEM,tmEM,tmEM,tmEM, + + tmEm,tmDW,tmEM,tmEM,// * + tmEm,tmVR,tmEM,tmEM,// * + tmEm,tmVR,tmEM,tmEM,// * + tmEm,tmUP,tmEN,tmEM,// * + ); + IW: array[16] of byte = ( + tmAR, tmAR, tmAR, tmAR, + tmSP, tmAR, tmSP, tmSP, + tmAR, tmAR, tmAR, tmAR, + tmSP, tmAR, tmSP, tmSP, + ); + + const FiguresNo: byte = 7; + //Figures: array[7] of integer = (#O, #T, #J, #L, #S, #Z, #I); + Figures: array[Figure::FiguresNo] of pointer = (#Figure::O, #Figure::T, #Figure::J, #Figure::L, #Figure::S, #Figure::Z, #Figure::I); + FigureWidths: array[Figure::FiguresNo] of pointer = (#Figure::OW, #Figure::TW, #Figure::JW, #Figure::LW, #Figure::SW, #Figure::ZW, #Figure::IW); +end. diff --git a/Publish/tutorials/TIM/timtris/images.tru b/Publish/tutorials/TIM/timtris/images.tru new file mode 100644 index 000000000..27e2b3ad9 --- /dev/null +++ b/Publish/tutorials/TIM/timtris/images.tru @@ -0,0 +1,356 @@ +unit Images; + + +@macro "gen_font" 1 + i = 0; + for (i = 0; i < p0; i++) { + // generate one row of font chars from the flf image + writeln('\t@exportsubregion "images/font2.flf" "images/font2.bin" 0 '+(i*8)+' 128 8 '); + } +@endmacro + + +@macro "gen_tpc" 3 + i = 0; + for (i = 0; i < p0; i++) { + letter = String.fromCharCode(i+97); + // delete existing image + writeln('\t@deletefile "copy_to_img/bg' + letter + p1 + '.tpc"'); + // last parameter (1) is needed for TPC as it adds TPC header to the file; dimensions must be divisable by 4 + writeln('\t@exportsubregion "images/bg' + letter + '.flf" "copy_to_img/bg' + letter + p1 + '.tpc" ' + p2 + ' 32 172 192 1'); + } +@endmacro + + +@macro "gen_compr" 3 + i = 0; + for (i = 0; i < p0; i++) { + letter = String.fromCharCode(i+97); + // delete existing image + writeln('\t@deletefile "copy_to_img/bg' + letter + p1 + '.lz4"'); + // delete temporary image + writeln('\t@deletefile "temp/bg' + letter + p1 + '.bin"'); + // export image to uncompressed temporary file + writeln('\t@exportsubregion "images/bg' + letter + '.flf" "temp/bg' + letter + p1 + '.bin" ' + p2 + ' 32 172 192 1'); + // compress image + writeln('\t@compress "temp/bg' + letter + p1 + '.bin" "copy_to_img/bg' + letter + p1 + '.lz4"'); + // add 2-byte header for loading + writeln('\t@addcpmheader "copy_to_img/bg' + letter + p1 + '.lz4"'); + } +@endmacro + + +/* + // delete compressed images + @deletefile "copy_to_img/bgaleft.lz4" + @deletefile "copy_to_img/bgbleft.lz4" + + @deletefile "copy_to_img/bgaright.lz4" + @deletefile "copy_to_img/bgbright.lz4" + + // delete temporary images + @deletefile "temp/bgaleft.bin" + @deletefile "temp/bgbleft.bin" + + @deletefile "temp/bgaright.bin" + @deletefile "temp/bgbright.bin" + + // export images to uncompressed temporary files + @exportsubregion "images/bga.flf" "temp/bgaleft.bin" 0 32 172 192 + @exportsubregion "images/bgb.flf" "temp/bgbleft.bin" 0 32 172 192 + + @exportsubregion "images/bga.flf" "temp/bgaright.bin" 340 32 172 192 + @exportsubregion "images/bgb.flf" "temp/bgbright.bin" 340 32 172 192 + + // compress images + @compress "temp/bgaleft.bin" "copy_to_img/bgaleft.lz4" + @compress "temp/bgbleft.bin" "copy_to_img/bgbleft.lz4" + + @compress "temp/bgaright.bin" "copy_to_img/bgaright.lz4" + @compress "temp/bgbright.bin" "copy_to_img/bgbright.lz4" + + // add 2-byte header for loading + @addcpmheader "copy_to_img/bgaleft.lz4" + @addcpmheader "copy_to_img/bgbleft.lz4" + + @addcpmheader "copy_to_img/bgaright.lz4" + @addcpmheader "copy_to_img/bgbright.lz4" +*/ + +var + // font generation +// @deletefile "images/font.bin" +//// font image is organized as 8-pixel high char rows, so rows must be separately exported +// @exportsubregion "images/font.flf" "images/font.bin" 0 0 128 8 // font chars +// @exportsubregion "images/font.flf" "images/font.bin" 0 8 128 8 // font chars +// @exportsubregion "images/font.flf" "images/font.bin" 0 16 128 8 // font chars +// @exportsubregion "images/font.flf" "images/font.bin" 0 24 128 8 // font chars +// @exportsubregion "images/font.flf" "images/font.bin" 0 32 128 8 // font chars +// @exportsubregion "images/font.flf" "images/font.bin" 0 40 128 8 // font chars +// @exportsubregion "images/font.flf" "images/font.bin" 0 48 128 8 // font chars +// @exportsubregion "images/font.flf" "images/font.bin" 0 56 128 8 // font chars +// @exportsubregion "images/font.flf" "images/font.bin" 0 64 128 8 // font chars +// font: incbin("images/font.bin"); // load an 8x8 font + + @deletefile "images/font2.bin" + // font image is organized as 8-pixel high char rows, so rows must be separately exported +/* + @exportsubregion "images/font2.flf" "images/font2.bin" 0 0 128 8 // font chars + @exportsubregion "images/font2.flf" "images/font2.bin" 0 8 128 8 // font chars + @exportsubregion "images/font2.flf" "images/font2.bin" 0 16 128 8 // font chars + @exportsubregion "images/font2.flf" "images/font2.bin" 0 24 128 8 // font chars + @exportsubregion "images/font2.flf" "images/font2.bin" 0 32 128 8 // font chars + @exportsubregion "images/font2.flf" "images/font2.bin" 0 40 128 8 // font chars + @exportsubregion "images/font2.flf" "images/font2.bin" 0 48 128 8 // font chars + @exportsubregion "images/font2.flf" "images/font2.bin" 0 56 128 8 // font chars + @exportsubregion "images/font2.flf" "images/font2.bin" 0 64 128 8 // font chars + @exportsubregion "images/font2.flf" "images/font2.bin" 0 72 128 8 // font chars +*/ + @gen_font(10) + font: incbin("images/font2.bin"); // load an 8x8 font + +/* + // delete existing TPC files + @deletefile "copy_to_img/bgaleft.tpc" + @deletefile "copy_to_img/bgaright.tpc" + @deletefile "copy_to_img/bgbleft.tpc" + @deletefile "copy_to_img/bgbright.tpc" + @deletefile "copy_to_img/bgcleft.tpc" + @deletefile "copy_to_img/bgcright.tpc" + @deletefile "copy_to_img/bgdleft.tpc" + @deletefile "copy_to_img/bgdright.tpc" + @deletefile "copy_to_img/bgeleft.tpc" + @deletefile "copy_to_img/bgeright.tpc" + @deletefile "copy_to_img/bgfleft.tpc" + @deletefile "copy_to_img/bgfright.tpc" + @deletefile "copy_to_img/bggleft.tpc" + @deletefile "copy_to_img/bggright.tpc" + @deletefile "copy_to_img/bghleft.tpc" + @deletefile "copy_to_img/bghright.tpc" + @deletefile "copy_to_img/bgileft.tpc" + @deletefile "copy_to_img/bgiright.tpc" + @deletefile "copy_to_img/bgjleft.tpc" + @deletefile "copy_to_img/bgjright.tpc" + @deletefile "copy_to_img/bgkleft.tpc" + @deletefile "copy_to_img/bgkright.tpc" + @deletefile "copy_to_img/bglleft.tpc" + @deletefile "copy_to_img/bglright.tpc" + @deletefile "copy_to_img/bgmleft.tpc" + @deletefile "copy_to_img/bgmright.tpc" + @deletefile "copy_to_img/bgnleft.tpc" + @deletefile "copy_to_img/bgnright.tpc" + @deletefile "copy_to_img/bgoleft.tpc" + @deletefile "copy_to_img/bgoright.tpc" + + // create TPC files + // last parameter (1) is needed for TPC as it adds TPC header to the file + @exportsubregion "images/bga.flf" "copy_to_img/bgaleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bga.flf" "copy_to_img/bgaright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgb.flf" "copy_to_img/bgbleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgb.flf" "copy_to_img/bgbright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgc.flf" "copy_to_img/bgcleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgc.flf" "copy_to_img/bgcright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgd.flf" "copy_to_img/bgdleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgd.flf" "copy_to_img/bgdright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bge.flf" "copy_to_img/bgeleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bge.flf" "copy_to_img/bgeright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgf.flf" "copy_to_img/bgfleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgf.flf" "copy_to_img/bgfright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgg.flf" "copy_to_img/bggleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgg.flf" "copy_to_img/bggright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgh.flf" "copy_to_img/bghleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgh.flf" "copy_to_img/bghright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgi.flf" "copy_to_img/bgileft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgi.flf" "copy_to_img/bgiright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgj.flf" "copy_to_img/bgjleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgj.flf" "copy_to_img/bgjright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgk.flf" "copy_to_img/bgkleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgk.flf" "copy_to_img/bgkright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgl.flf" "copy_to_img/bglleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgl.flf" "copy_to_img/bglright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgm.flf" "copy_to_img/bgmleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgm.flf" "copy_to_img/bgmright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgn.flf" "copy_to_img/bgnleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgn.flf" "copy_to_img/bgnright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgo.flf" "copy_to_img/bgoleft.tpc" 0 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 + @exportsubregion "images/bgo.flf" "copy_to_img/bgoright.tpc" 340 32 172 192 1 // image to convert to TPC format, dimensions must be divisable by 4 +*/ + @gen_tpc(15,"left",0) + @gen_tpc(15,"right",340) + + @gen_compr(15,"left",0) + @gen_compr(15,"right",340) + + + + + +/* + // delete compressed images + @deletefile "copy_to_img/bgaleft.lz4" + @deletefile "copy_to_img/bgbleft.lz4" + @deletefile "copy_to_img/bgcleft.lz4" + @deletefile "copy_to_img/bgdleft.lz4" + @deletefile "copy_to_img/bgeleft.lz4" + @deletefile "copy_to_img/bgfleft.lz4" + @deletefile "copy_to_img/bggleft.lz4" + @deletefile "copy_to_img/bghleft.lz4" + @deletefile "copy_to_img/bgileft.lz4" + @deletefile "copy_to_img/bgjleft.lz4" + @deletefile "copy_to_img/bgkleft.lz4" + @deletefile "copy_to_img/bglleft.lz4" + @deletefile "copy_to_img/bgmleft.lz4" + @deletefile "copy_to_img/bgnleft.lz4" + @deletefile "copy_to_img/bgoleft.lz4" + + @deletefile "copy_to_img/bgaright.lz4" + @deletefile "copy_to_img/bgbright.lz4" + @deletefile "copy_to_img/bgcright.lz4" + @deletefile "copy_to_img/bgdright.lz4" + @deletefile "copy_to_img/bgeright.lz4" + @deletefile "copy_to_img/bgfright.lz4" + @deletefile "copy_to_img/bggright.lz4" + @deletefile "copy_to_img/bghright.lz4" + @deletefile "copy_to_img/bgiright.lz4" + @deletefile "copy_to_img/bgjright.lz4" + @deletefile "copy_to_img/bgkright.lz4" + @deletefile "copy_to_img/bglright.lz4" + @deletefile "copy_to_img/bgmright.lz4" + @deletefile "copy_to_img/bgnright.lz4" + @deletefile "copy_to_img/bgoright.lz4" + + // delete temporary images + @deletefile "temp/bgaleft.bin" + @deletefile "temp/bgbleft.bin" + @deletefile "temp/bgcleft.bin" + @deletefile "temp/bgdleft.bin" + @deletefile "temp/bgeleft.bin" + @deletefile "temp/bgfleft.bin" + @deletefile "temp/bggleft.bin" + @deletefile "temp/bghleft.bin" + @deletefile "temp/bgileft.bin" + @deletefile "temp/bgjleft.bin" + @deletefile "temp/bgkleft.bin" + @deletefile "temp/bglleft.bin" + @deletefile "temp/bgmleft.bin" + @deletefile "temp/bgnleft.bin" + @deletefile "temp/bgoleft.bin" + + @deletefile "temp/bgaright.bin" + @deletefile "temp/bgbright.bin" + @deletefile "temp/bgcright.bin" + @deletefile "temp/bgdright.bin" + @deletefile "temp/bgeright.bin" + @deletefile "temp/bgfright.bin" + @deletefile "temp/bggright.bin" + @deletefile "temp/bghright.bin" + @deletefile "temp/bgiright.bin" + @deletefile "temp/bgjright.bin" + @deletefile "temp/bgkright.bin" + @deletefile "temp/bglright.bin" + @deletefile "temp/bgmright.bin" + @deletefile "temp/bgnright.bin" + @deletefile "temp/bgoright.bin" + + + + // export images to uncompressed temporary files + @exportsubregion "images/bga.flf" "temp/bgaleft.bin" 0 32 172 192 + @exportsubregion "images/bgb.flf" "temp/bgbleft.bin" 0 32 172 192 + @exportsubregion "images/bgc.flf" "temp/bgcleft.bin" 0 32 172 192 + @exportsubregion "images/bgd.flf" "temp/bgdleft.bin" 0 32 172 192 + @exportsubregion "images/bge.flf" "temp/bgeleft.bin" 0 32 172 192 + @exportsubregion "images/bgf.flf" "temp/bgfleft.bin" 0 32 172 192 + @exportsubregion "images/bgg.flf" "temp/bggleft.bin" 0 32 172 192 + @exportsubregion "images/bgh.flf" "temp/bghleft.bin" 0 32 172 192 + @exportsubregion "images/bgi.flf" "temp/bgileft.bin" 0 32 172 192 + @exportsubregion "images/bgj.flf" "temp/bgjleft.bin" 0 32 172 192 + @exportsubregion "images/bgk.flf" "temp/bgkleft.bin" 0 32 172 192 + @exportsubregion "images/bgl.flf" "temp/bglleft.bin" 0 32 172 192 + @exportsubregion "images/bgm.flf" "temp/bgmleft.bin" 0 32 172 192 + @exportsubregion "images/bgn.flf" "temp/bgnleft.bin" 0 32 172 192 + @exportsubregion "images/bgo.flf" "temp/bgoleft.bin" 0 32 172 192 + + @exportsubregion "images/bga.flf" "temp/bgaright.bin" 340 32 172 192 + @exportsubregion "images/bgb.flf" "temp/bgbright.bin" 340 32 172 192 + @exportsubregion "images/bgc.flf" "temp/bgcright.bin" 340 32 172 192 + @exportsubregion "images/bgd.flf" "temp/bgdright.bin" 340 32 172 192 + @exportsubregion "images/bge.flf" "temp/bgeright.bin" 340 32 172 192 + @exportsubregion "images/bgf.flf" "temp/bgfright.bin" 340 32 172 192 + @exportsubregion "images/bgg.flf" "temp/bggright.bin" 340 32 172 192 + @exportsubregion "images/bgh.flf" "temp/bghright.bin" 340 32 172 192 + @exportsubregion "images/bgi.flf" "temp/bgiright.bin" 340 32 172 192 + @exportsubregion "images/bgj.flf" "temp/bgjright.bin" 340 32 172 192 + @exportsubregion "images/bgk.flf" "temp/bgkright.bin" 340 32 172 192 + @exportsubregion "images/bgl.flf" "temp/bglright.bin" 340 32 172 192 + @exportsubregion "images/bgm.flf" "temp/bgmright.bin" 340 32 172 192 + @exportsubregion "images/bgn.flf" "temp/bgnright.bin" 340 32 172 192 + @exportsubregion "images/bgo.flf" "temp/bgoright.bin" 340 32 172 192 + + // compress images + @compress "temp/bgaleft.bin" "copy_to_img/bgaleft.lz4" + @compress "temp/bgbleft.bin" "copy_to_img/bgbleft.lz4" + @compress "temp/bgcleft.bin" "copy_to_img/bgcleft.lz4" + @compress "temp/bgdleft.bin" "copy_to_img/bgdleft.lz4" + @compress "temp/bgeleft.bin" "copy_to_img/bgeleft.lz4" + @compress "temp/bgfleft.bin" "copy_to_img/bgfleft.lz4" + @compress "temp/bggleft.bin" "copy_to_img/bggleft.lz4" + @compress "temp/bghleft.bin" "copy_to_img/bghleft.lz4" + @compress "temp/bgileft.bin" "copy_to_img/bgileft.lz4" + @compress "temp/bgjleft.bin" "copy_to_img/bgjleft.lz4" + @compress "temp/bgkleft.bin" "copy_to_img/bgkleft.lz4" + @compress "temp/bglleft.bin" "copy_to_img/bglleft.lz4" + @compress "temp/bgmleft.bin" "copy_to_img/bgmleft.lz4" + @compress "temp/bgnleft.bin" "copy_to_img/bgnleft.lz4" + @compress "temp/bgoleft.bin" "copy_to_img/bgoleft.lz4" + + @compress "temp/bgaright.bin" "copy_to_img/bgaright.lz4" + @compress "temp/bgbright.bin" "copy_to_img/bgbright.lz4" + @compress "temp/bgcright.bin" "copy_to_img/bgcright.lz4" + @compress "temp/bgdright.bin" "copy_to_img/bgdright.lz4" + @compress "temp/bgeright.bin" "copy_to_img/bgeright.lz4" + @compress "temp/bgfright.bin" "copy_to_img/bgfright.lz4" + @compress "temp/bggright.bin" "copy_to_img/bggright.lz4" + @compress "temp/bghright.bin" "copy_to_img/bghright.lz4" + @compress "temp/bgiright.bin" "copy_to_img/bgiright.lz4" + @compress "temp/bgjright.bin" "copy_to_img/bgjright.lz4" + @compress "temp/bgkright.bin" "copy_to_img/bgkright.lz4" + @compress "temp/bglright.bin" "copy_to_img/bglright.lz4" + @compress "temp/bgmright.bin" "copy_to_img/bgmright.lz4" + @compress "temp/bgnright.bin" "copy_to_img/bgnright.lz4" + @compress "temp/bgoright.bin" "copy_to_img/bgoright.lz4" + + // add 2-byte header for loading + @addcpmheader "copy_to_img/bgaleft.lz4" + @addcpmheader "copy_to_img/bgbleft.lz4" + @addcpmheader "copy_to_img/bgcleft.lz4" + @addcpmheader "copy_to_img/bgdleft.lz4" + @addcpmheader "copy_to_img/bgeleft.lz4" + @addcpmheader "copy_to_img/bgfleft.lz4" + @addcpmheader "copy_to_img/bggleft.lz4" + @addcpmheader "copy_to_img/bghleft.lz4" + @addcpmheader "copy_to_img/bgileft.lz4" + @addcpmheader "copy_to_img/bgjleft.lz4" + @addcpmheader "copy_to_img/bgkleft.lz4" + @addcpmheader "copy_to_img/bglleft.lz4" + @addcpmheader "copy_to_img/bgmleft.lz4" + @addcpmheader "copy_to_img/bgnleft.lz4" + @addcpmheader "copy_to_img/bgoleft.lz4" + + @addcpmheader "copy_to_img/bgaright.lz4" + @addcpmheader "copy_to_img/bgbright.lz4" + @addcpmheader "copy_to_img/bgcright.lz4" + @addcpmheader "copy_to_img/bgdright.lz4" + @addcpmheader "copy_to_img/bgeright.lz4" + @addcpmheader "copy_to_img/bgfright.lz4" + @addcpmheader "copy_to_img/bggright.lz4" + @addcpmheader "copy_to_img/bghright.lz4" + @addcpmheader "copy_to_img/bgiright.lz4" + @addcpmheader "copy_to_img/bgjright.lz4" + @addcpmheader "copy_to_img/bgkright.lz4" + @addcpmheader "copy_to_img/bglright.lz4" + @addcpmheader "copy_to_img/bgmright.lz4" + @addcpmheader "copy_to_img/bgnright.lz4" + @addcpmheader "copy_to_img/bgoright.lz4" +*/ +end. diff --git a/Publish/tutorials/TIM/timtris/images/Bottles.flf b/Publish/tutorials/TIM/timtris/images/Bottles.flf new file mode 100644 index 000000000..53698e4ff Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/Bottles.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bga.flf b/Publish/tutorials/TIM/timtris/images/bga.flf new file mode 100644 index 000000000..f80254d3f Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bga.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgb.flf b/Publish/tutorials/TIM/timtris/images/bgb.flf new file mode 100644 index 000000000..a0e23bf95 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgb.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgc.flf b/Publish/tutorials/TIM/timtris/images/bgc.flf new file mode 100644 index 000000000..2bcd0c494 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgc.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgd.flf b/Publish/tutorials/TIM/timtris/images/bgd.flf new file mode 100644 index 000000000..2c767f586 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgd.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bge.flf b/Publish/tutorials/TIM/timtris/images/bge.flf new file mode 100644 index 000000000..ebf2cf91e Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bge.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgf.flf b/Publish/tutorials/TIM/timtris/images/bgf.flf new file mode 100644 index 000000000..8bd9bfcba Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgf.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgg.flf b/Publish/tutorials/TIM/timtris/images/bgg.flf new file mode 100644 index 000000000..c7d497f6b Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgg.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgh.flf b/Publish/tutorials/TIM/timtris/images/bgh.flf new file mode 100644 index 000000000..e13c9e9df Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgh.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgi.flf b/Publish/tutorials/TIM/timtris/images/bgi.flf new file mode 100644 index 000000000..1cd6311a1 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgi.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgj.flf b/Publish/tutorials/TIM/timtris/images/bgj.flf new file mode 100644 index 000000000..b218c8ee0 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgj.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgk.flf b/Publish/tutorials/TIM/timtris/images/bgk.flf new file mode 100644 index 000000000..528eb5540 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgk.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgl.flf b/Publish/tutorials/TIM/timtris/images/bgl.flf new file mode 100644 index 000000000..49e8fb0aa Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgl.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgm.flf b/Publish/tutorials/TIM/timtris/images/bgm.flf new file mode 100644 index 000000000..cfd81a2a2 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgm.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgn.flf b/Publish/tutorials/TIM/timtris/images/bgn.flf new file mode 100644 index 000000000..fb4af75ac Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgn.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/bgo.flf b/Publish/tutorials/TIM/timtris/images/bgo.flf new file mode 100644 index 000000000..b453ad0c9 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/bgo.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/font.flf b/Publish/tutorials/TIM/timtris/images/font.flf new file mode 100644 index 000000000..6237e0e20 Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/font.flf differ diff --git a/Publish/tutorials/TIM/timtris/images/font2.flf b/Publish/tutorials/TIM/timtris/images/font2.flf new file mode 100644 index 000000000..e4a3f73be Binary files /dev/null and b/Publish/tutorials/TIM/timtris/images/font2.flf differ diff --git a/Publish/tutorials/TIM/timtris/readme.rtf b/Publish/tutorials/TIM/timtris/readme.rtf new file mode 100644 index 000000000..bdffe16f8 --- /dev/null +++ b/Publish/tutorials/TIM/timtris/readme.rtf @@ -0,0 +1,46 @@ +# TimTris v0.9 + +This repository contains source code written in [TRSE](https://lemonspawn.com/turbo-rascal-syntax-error-expected-but-begin/) by Nicolaas Groeneboom. +

+TimTris is a Tetris clone for TIM-011, school computer from Ex-Yugoslavia. Original Tetris is by Alexey Pajitnov. +

+Game uses graphics libraries written by me, and file libraries partially adapted from MESCC code by Miguel Garcia Lopez, both part of TRSE. +

+PTX Player is by S.V.Bulba, adapted to TIM-011 by Marko Šolajić. To compile it, you'll need [ZASM](https://k1.spdns.de/Develop/Projects/zasm/Distributions/). +

+"Tetris 2 Red Dawn" music is by Frantisek Fuka. +

+Many thanks to Marko for helping with various TIM stuff and Mićko for TIM-011 MAME emulator! +

+## Requirements +

+Working TIM-011 (there maybe 10 or less left in the world, so not a huge crowd) with AY sound card (needed if you wan to hear music). +

+Oooor... +

+MAME emulator, compiled from latest GitHub source, version 0.263 or later. +

+## Running +

+On real machine, after boot, type to start it, and switch to lower case letters if needed. +

+On emulator, run it with: +

+ +mame tim011 -window -v -r 720x512 -switchres -exp ay -flop1 .img + +

+and do the same as on a real machine. +

+NOTICE: Computer needs around 30-40 seconds before anything shows on screen, so be patient! +

+## TODO +

+* File library still cannot save content, needs debugging/fixing (so high score cannot be saved) +

+* Adjustments to graphics (mostly cropping) +

+* Adding cursor keys as input (not yet fully supported by emulator) +

+* Game sometimes freezes/exits, but that one is so far observed only in emulator, not on real machine, needs more investigating + diff --git a/Publish/tutorials/TIM/timtris/strmath.tru b/Publish/tutorials/TIM/timtris/strmath.tru new file mode 100644 index 000000000..a0bd03499 --- /dev/null +++ b/Publish/tutorials/TIM/timtris/strmath.tru @@ -0,0 +1,162 @@ +Unit StrMath; + +var + s, sout: pointer; // used as string pointers + i,j,k,n: byte; // temp and input variables + len: byte = 8; // number of digits in string + code_0: byte = $30; // code for char '0' + code_9: byte = $39; // code for char '9' + o1, o2: byte; // variables used for overflow + +/** + Sets string length for StrMath functions (default is 6).
+ Strings must contain only codes for characters 0-9. +**/ +procedure SetLen(i: global byte); +begin + len := i; +end; + + +/** + Sets value for character code for zero (default is $30) +**/ +procedure SetCodeZero(n: global byte); +begin + code_0 := n; + code_9 := n + 9; +end; + + +/** + Adds first string to second one. Both must be the same length, set by SetLen function.
+ Strings must contain only codes for characters 0-9.
+ Returns overflow from most significant digit (0 value means everything is OK). +**/ +function AddStrStr(s, sout: global pointer): byte; +begin + i := len - 1; + o1 := 0; + // loop finishes when i overflows to $FF + while i < len do begin + j := s[i] + sout[i] - code_0; + if j > code_9 then begin + j -= 10; + if i > 0 then begin + sout[i-1] += 1; + end else o1 += 1; + end; + sout[i] := j; + i -= 1; + end; + + ReturnValue(o1); +end; + + +/** + Multiplies byte value by first string and writes the result to second string.
+ Not very efficient (just calls AddStrStr in a loop).
+ Strings must contain only codes for characters 0-9.
+ Returns overflow from most significant digit (0 value means everything is OK).

+ Can be used to init string to zeros with MulByteStr(0,0,#str) +**/ +function MulByteStr(n: global byte, s, sout: global pointer): byte; +begin + o2 := 0; + if n > 0 then begin + //Memory::MemCpyLDIR(s, sout, len); + memcpy(s, sout, len); + if n > 1 then + for k:= 1 to n do begin + o2 += AddStrStr(s, sout); + end; + end else begin + for i := 0 to len do sout[i] := code_0; + end; + + ReturnValue(o2); +end; + + +/** + Adds byte value to string.
+ String must contain only codes for characters 0-9.
+ Returns overflow from most significant digit (0 value means everything is OK). +**/ +function AddByteStr(n: global byte, sout: global pointer): byte; +begin + o1 := 0; + i := len - 3; + while n >= 100 do begin + sout[i] += 1; + n -= 100; + end; + + i := len - 1; + k := i - 1; + // loop finishes when i overflows to $FF + while i < len do begin + j := sout[i] + n; + n := 0; + while j > code_9 do begin + j -= 10; + if k < len then begin + sout[k] += 1; + end else o1 += 1; + end; + sout[i] := j; + i -= 1; + k -= 1; + end; + + ReturnValue(o1); +end; + + +/** + Adds integer value to string.
+ String must contain only codes for characters 0-9.
+ Returns overflow from most significant digit (0 value means everything is OK). +**/ +function AddIntStr(nn: integer, sout: global pointer): byte; +begin + i := len - 5; + while nn >= 10000 do begin + sout[i] += 1; + nn -= 10000; + end; + + i += 1; + while nn >= 1000 do begin + sout[i] += 1; + nn -= 1000; + end; + + i += 1; + while nn >= 100 do begin + sout[i] += 1; + nn -= 100; + end; + + ReturnValue(AddByteStr(Lo(nn), sout)); +end; + + +/** + Compares values in two strings.
+ Strings must be of the same size.
+ Returns 0 if strings are equal, 1 if first is bigger, or $FF if second is bigger. +**/ +function CmpStrStr(s, sout: global pointer): byte; +begin + for i := 0 to len do begin + if s[i] > sout[i] then ReturnValue(1) + else if s[i] < sout[i] then ReturnValue($FF); + end; + + ReturnValue(0); +end; + + +end. diff --git a/Publish/tutorials/TIM/timtris/timtris.ras b/Publish/tutorials/TIM/timtris/timtris.ras new file mode 100644 index 000000000..955e8b90d --- /dev/null +++ b/Publish/tutorials/TIM/timtris/timtris.ras @@ -0,0 +1,931 @@ +program Timtris; +@use "random" +@use "memory" +@use "system/z80cpm" +@use "system/system" +@use "system/screen" +@use "system/file" + +//@use "tetromino" +@use "figure" +@use "images" +@use "title" +@use "strmath" + +var + // constants for playfield + const playFieldWidth: byte = 10; + const playFieldHeight: byte = 20; + const fieldWidth: byte = playFieldWidth + 2; // wall on left and right + const fieldHeight: byte = playFieldHeight + 1; // wall on bottom + // 4 additional playfield lines that are not drawn, for figure entering + const entryFieldWidth: byte = fieldWidth; + const entryFieldHeight: byte = 4; + + // location of playfield on screen + const fieldScreenX: byte = 64 - fieldWidth*3/2; // figure chars are 1.5 regular char width + const fieldScreenY: byte = 12; + + const pictureY: byte = 10; + + // table for multiplying with "fieldWidth" + fieldWidthMulTable: array[fieldHeight] of byte = buildtable("i * FIELDWIDTH"); + + // global irq byte variables + ib_irq, jb_irq, kb_irq, lb_irq: byte; + + // helper field when figure starts to fall down + entryField: array[entryFieldWidth*entryFieldHeight] of byte; + // main field that holds currently occupied squares + field: array[fieldWidth*fieldHeight] of byte; + // fields for drawing, content of previous ones is copied there + drawEntryField: array[entryFieldWidth*entryFieldHeight] of byte; + drawField: array[fieldWidth*fieldHeight] of byte; + + spaceLine: array[fieldWidth] of byte = buildtable("0xBA"); + + // pointers used for placing a figure and checking if it can be placed + figPt_irq, fieldPt_irq: pointer of byte; + // phase, x and y coordinates and starting line of the figure, used for placing and checking + figPhase_irq, figX_irq, figY_irq, startLine_irq: byte; + + // current figure + figurePhase, figureX, figureY: byte; + figurePt, figureWPt, figPt, fieldPt: pointer of byte; + + // keyboard reading + newKey: boolean; + keyCode: byte; + + // game speed + dropTime: byte; + dropTimeInitial: byte; + + // do we need to redraw the playfield + doRedraw: boolean; + + // game control + gamePaused: boolean; + gameOver: boolean; + + // random selection of figures + figureNo, nextFigureNo: byte; + randomBucket1: array[Figure::FiguresNo] of byte; + randomBucket2: array[Figure::FiguresNo] of byte; + randomBucketPos: byte; + + // detection of full lines + fullLines: array[4] of byte; + fullLinesCnt: byte; + prevLinesCnt: byte; + fullLinePhase: byte; + fullLineTime: byte; + const fullLineDuration: byte = 5; //10 + + // screen shaking effect tables + const shake1TableSize: byte = 20; + shake1Table: array[shake1TableSize] of byte = buildtable("256-Math.cos((SHAKE1TABLESIZE-i)/20.0*Math.PI*2.0)*i/5"); + const shake2TableSize: byte = 40; + shake2Table: array[shake2TableSize] of byte = buildtable("256-Math.cos((SHAKE2TABLESIZE-i)/20.0*Math.PI*2.0)*i/5"); + const shake3TableSize: byte = 60; + shake3Table: array[shake3TableSize] of byte = buildtable("256-Math.cos((SHAKE3TABLESIZE-i)/20.0*Math.PI*2.0)*i/5"); + const shake4TableSize: byte = 100; + shake4Table: array[shake4TableSize] of byte = buildtable("256-Math.cos((SHAKE4TABLESIZE-i)/20.0*Math.PI*2.0)*i/5"); + shakeTableSize: array[4] of byte = (shake1TableSize, shake2TableSize, shake3TableSize, shake4TableSize); + shakeTablePtrs: array[4] of pointer = (#shake1Table, #shake2Table, #shake3Table, #shake4Table); + shakeCnt: byte; + shakeTablePtr: pointer; + + // next figure drawing + const nextFigWidth: byte = 4+2; + const nextFigHeight: byte = 4+2; + const nextFigScrX:byte = fieldScreenX + fieldWidth*3 + 8; + const nextFigScrY:byte = fieldScreenY + 4; + nextFigField: array[nextFigWidth*nextFigHeight] of byte; + doRedrawNext: boolean; + + // global main code byte variables + ib,jb,kb,lb: byte; + + // debug string + //dbgStr: string = ("AAAAAAAAAAAAAAA"); + + // scores + const scoLen: byte = 8; + scoLines: string = ("00000000"); + scoScore: string = ("00000000"); + scoLevel: string = (" 1"); + dropPoints: byte; + + const scoScoreX: byte = fieldScreenX - scoLen*2 - 8; + const scoLinesX: byte = scoScoreX; + const scoLevelX: byte = scoScoreX + 12; + const scoLinesY: byte = fieldScreenY + 4; + const scoScoreY: byte = scoLinesY+6; + const scoLevelY: byte = scoScoreY+6; + + // points table + scoLines1L1: string = ("00000100"); + scoLines2L1: string = ("00000300"); + scoLines3L1: string = ("00000500"); + scoLines4L1: string = ("00000800"); + scoLines4B2BL1: string = ("00000400"); + scoLines0: string = ("00000000"); // *LEVEL + scoLines1: string = ("00000100"); // *LEVEL + scoLines2: string = ("00000300"); // *LEVEL + scoLines3: string = ("00000500"); // *LEVEL + scoLines4: string = ("00000800"); // *LEVEL + scoLines4B2B: string = ("00000400"); // *LEVEL + scoLinesPtrs: array[5] of pointer = (#scoLines0, #scoLines1, #scoLines2, #scoLines3, #scoLines4); + scoSoftDr: string = ("00000001"); + scoHardDr: string = ("00000002"); + nextLevelLines: integer; + level: byte; + timtrisFile: File::Handle; + + // pic loading + picLoadPhase: byte = 0; + picLoadCnt: byte = 0; + const picLoadCntInit: byte = 5; + tpcLeft: string = ("bgaleft.tpc"); + tpcRight: string = ("bgaright.tpc"); + tpcChar: byte; + + const imgLoad: address = $7000; + const imgUnpack: address = $9000; + img: File::Handle; + imgPtr: pointer; + scrPtr: pointer; + imgLeft: string = ("bgaleft.lz4"); + imgRight: string = ("bgaright.lz4"); + + ptxplay: incbin("ayplayer/ptxplay.bin", $5000); + pt3tune: incbin("ayplayer/tetris2.pt3", $5A9D); + + +procedure genLevelString(); +begin + if level < 10 then begin + scoLevel[0] := ' '; + scoLevel[1] := ASCII::NUM0 + level; + end else begin + scoLevel[0] := '1'; + scoLevel[1] := ASCII::NUM0 + level - 10; + end; +end; + +procedure CalcStartingLevelNumbers(); +begin + level := Title::level; + + StrMath::MulByteStr(level, #scoLines1L1, #scoLines1); + StrMath::MulByteStr(level, #scoLines2L1, #scoLines2); + StrMath::MulByteStr(level, #scoLines3L1, #scoLines3); + StrMath::MulByteStr(level, #scoLines4L1, #scoLines4); + StrMath::MulByteStr(level, #scoLines4B2BL1, #scoLines4B2B); + + // WHEN STARTING FROM LEVEL > 1, ALL THE LINES FOR PREVIOUS LEVEL PLUS FOR THE CURENT ONE + // FOR EXAMPLE, IF STARTING FROM LEVEL 4, 5+10+15+20=50 LINES + // (LEVEL/2)*(2*START_POINTS + (LEVEL-1)*DIFFERENCE) = LEVEL*(2*5 + (LEVEL-1)*5)/2 = ((10+(LEVEL-1)*5)*LEVEL)>>1 + nextLevelLines := 10 + (level - 1) * 5; + nextLevelLines := (nextLevelLines * level) >> 1; + + dropTimeInitial := 51 - level*3; + genLevelString(); + + tpcChar := ASCII::lower_a; + if level > 2 then tpcChar += level - 2; + tpcLeft[2] := tpcChar; + tpcRight[2] := tpcChar; + if Title::picMode = 0 then begin + picLoadPhase := 0; + end else begin + picLoadPhase := 4; + end; + +end; + + +procedure CalcNextLevelNumbers(); +begin + if level < 15 then begin + level += 1; + + StrMath::AddStrStr(#scoLines1L1, #scoLines1); + StrMath::AddStrStr(#scoLines2L1, #scoLines2); + StrMath::AddStrStr(#scoLines3L1, #scoLines3); + StrMath::AddStrStr(#scoLines4L1, #scoLines4); + StrMath::AddStrStr(#scoLines4B2BL1, #scoLines4B2B); + + // NEXT LEVEL LINES: LEVEL*5 + nextLevelLines := level * 5; + + dropTimeInitial -= 3; + genLevelString(); + end else begin + nextLevelLines := 30000; + end; + + if level > 2 then begin + tpcChar := tpcLeft[2]; + tpcChar += 1; + if tpcChar > ASCII::lower_o then tpcChar := ASCII::lower_a; + tpcLeft[2] := tpcChar; + tpcRight[2] := tpcChar; + end; + + if ((Title::picMode = 0) and (level > 2)) then begin + picLoadPhase := 0; + end; +end; + + +procedure DrawScores(); +begin + Screen::GotoXY(scoLinesX, scoLinesY); + Screen::PrintStr(#scoLines); + Screen::GotoXY(scoScoreX, scoScoreY); + Screen::PrintStr(#scoScore); + Screen::GotoXY(scoLevelX, scoLevelY); + Screen::PrintStr(#scoLevel); +end; + + +procedure DrawScoreHeaders(); +begin + Screen::GotoXY(scoLinesX+6,scoLinesY-2); + Screen::PrintStr("LINES"); + Screen::GotoXY(scoScoreX+6,scoScoreY-2); + Screen::PrintStr("SCORE"); + Screen::GotoXY(scoScoreX+6,scoLevelY-2); + Screen::PrintStr("LEVEL"); +end; + + +procedure InitField(); +begin + ib_irq := 0; + for jb_irq := 0 to playFieldHeight do begin + field[ib_irq] := Figure::tmWL; + ib_irq += 1; + for kb_irq := 0 to playFieldWidth do begin // TODO replace with memcpy + field[ib_irq] := Figure::tmEM; + ib_irq += 1; + end; + field[ib_irq] := Figure::tmWL; + ib_irq += 1; + end; + for jb_irq := 0 to fieldWidth do begin + field[ib_irq] := Figure::tmWL; + ib_irq += 1; + end; + + ib_irq := 0; + for jb_irq := 0 to entryFieldHeight do begin + entryField[ib_irq] := Figure::tmWL; + ib_irq += 1; + for kb_irq := 0 to playFieldWidth do begin // TODO replace with memcpy + entryField[ib_irq] := Figure::tmEM; + ib_irq += 1; + end; + entryField[ib_irq] := Figure::tmWL; + ib_irq += 1; + end; + + if Title::rndLines > 0 then begin + ib_irq := (playFieldHeight-1)*fieldWidth + 1; + for lb_irq := 0 to Title::rndLines do begin + for jb_irq := 0 to 10 do field[ib_irq+jb_irq] := Figure::tmDS; + for jb_irq := 0 to 5 do begin + kb_irq := Random::RandomByte() & $0F; + if kb_irq > 9 then kb_irq -= 8; + field[ib_irq+kb_irq] := Figure::tmEM; + end; + ib_irq -= fieldWidth; + end; + end; + + for ib_irq := 0 to nextFigHeight*nextFigWidth do nextFigField[ib_irq] := Figure::tmWL; +end; + + +procedure ShuffleRandomBucket2(); +begin + for ib_irq := 0 to Figure::FiguresNo do begin + jb_irq := Random::RandomByte() & $07; + if jb_irq >= Figure::FiguresNo then continue; + kb_irq := Random::RandomByte() & $07; + if kb_irq >= Figure::FiguresNo then continue; + lb_irq := randomBucket2[jb_irq]; + randomBucket2[jb_irq] := randomBucket2[kb_irq]; + randomBucket2[kb_irq] := lb_irq; + end; +end; + + +function GetRandomFigure(): byte; +var + GetRandomFigureValue: byte; +begin + if Title::rndMode = 0 then begin + if randomBucketPos = Figure::FiguresNo then begin + memcpy(#randomBucket2, #randomBucket1, Figure::FiguresNo); + ShuffleRandomBucket2(); + randomBucketPos := 0; + end; + GetRandomFigureValue := randomBucket1[randomBucketPos]; + randomBucketPos += 1; + end else begin + GetRandomFigureValue := Figure::FiguresNo; + while GetRandomFigureValue >= Figure::FiguresNo do + GetRandomFigureValue := Random::RandomByte() & $07; + end; + ReturnValue(GetRandomFigureValue); +end; + + +// places figure into a drawing field +procedure DrawFigure(tmpt1: pointer, tmphase1, tmx1, tmy1: byte); +var + fieldpt1: pointer of byte; +begin + tmpt1 += tmphase1 << 4; + if tmy1 < entryFieldHeight then begin + fieldpt1 := #drawEntryField; + end else begin + fieldpt1 := #drawField; + tmy1 -= entryFieldHeight; + end; + //fieldpt1 += tmx1 + (tmy1 * fieldWidth); + fieldpt1 += tmx1 + fieldWidthMulTable[tmy1]; + for ib := 0 to 4 do begin + for jb := 0 to 4 do begin + if tmpt1[jb] = Figure::tmEN then + return; + if tmpt1[jb] <> Figure::tmEM then + fieldpt1[jb] := tmpt1[jb]; + end; + fieldpt1 += fieldWidth; + tmpt1 += 4; + end; +end; + + +// draws next figure on screen +procedure DrawNextFigure(drawCurrent: boolean); +begin + // place figure into next figure field + if drawCurrent then begin + figPt := Figure::Figures[figureNo]; + figPt += figurePhase << 4; + end else + figPt := Figure::Figures[nextFigureNo]; + fieldPt := #nextFigField + nextFigWidth + 1; + for ib := 0 to 4 do begin + for jb := 0 to 4 do begin + fieldPt[jb] := figPt[jb]; + if figPt[jb] = Figure::tmEN then fieldPt[jb] := Figure::tmEM; + end; + fieldPt += nextFigWidth; + figPt += 4; + end; + + if drawCurrent then + Screen::GotoXY(nextFigScrX+2,nextFigScrY-2) + else + Screen::GotoXY(nextFigScrX+2,nextFigScrY-2+24); + if drawCurrent then begin + Screen::PrintStr("CURRENT"); + jb := nextFigScrY; + end else begin + Screen::PrintStr("NEXT"); + jb := nextFigScrY + 24; + end; + // draw next figure field + ib := 0; + for kb := 0 to nextFigHeight do begin + Screen::GotoXY(nextFigScrX, jb); + Screen::PrintNStr15(#nextFigField[ib], nextFigWidth); + ib += nextFigWidth; + jb += 2; + end; +end; + + +procedure DrawField(); +var +begin + ib := 0; + jb := fieldScreenY; + for kb := 0 to fieldHeight do begin + Screen::GotoXY(fieldScreenX, jb); + Screen::PrintNStr15(#drawField[ib], fieldWidth); + ib += fieldWidth; + jb += 2; + end; +end; + + +// places the figure into a main playfield +procedure PlaceFigure(figPt_irq: global pointer, figPhase_irq, figX_irq, figY_irq: global byte); +begin + figPt_irq += figPhase_irq << 4; + if figY_irq < entryFieldHeight then begin + fieldPt_irq := #entryField; + end else begin + fieldPt_irq := #field; + figY_irq -= entryFieldHeight; + end; + //fieldPt_irq += figX_irq + (figY_irq * fieldWidth); + fieldPt_irq += figX_irq + fieldWidthMulTable[figY_irq]; + for ib_irq := 0 to 4 do begin + for jb_irq := 0 to 4 do begin + if figPt_irq[jb_irq] = Figure::tmEN then + return; + if figPt_irq[jb_irq] <> Figure::tmEM then + fieldPt_irq[jb_irq] := figPt_irq[jb_irq]; + end; + fieldPt_irq += fieldWidth; + figPt_irq += 4; + end; +end; + + +function CheckTetromino(figPt_irq: global pointer, figPhase_irq, figX_irq, figY_irq: global byte): boolean; +begin + figPt_irq += figPhase_irq << 4; + if figY_irq < entryFieldHeight then begin + fieldPt_irq := #entryField; + end else begin + fieldPt_irq := #field; + figY_irq -= entryFieldHeight; + end; + //fieldPt_irq += figX_irq + (figY_irq * fieldWidth); + fieldPt_irq += figX_irq + fieldWidthMulTable[figY_irq]; + for ib_irq := 0 to 4 do begin + for jb_irq := 0 to 4 do begin + if figPt_irq[jb_irq] = Figure::tmEN then + ReturnValue(true); + if ( (figPt_irq[jb_irq] <> Figure::tmEM) and (fieldPt_irq[jb_irq] <> Figure::tmEM) ) then + ReturnValue(false); + end; + fieldPt_irq += fieldWidth; + figPt_irq += 4; + end; + ReturnValue(true); +end; + +function FullLine(): boolean; +begin + for lb_irq := 0 to playFieldWidth do + if fieldPt_irq[lb_irq] = Figure::tmEM then + ReturnValue(false); + ReturnValue(true); +end; + +function FindFullLines(startLine_irq: global byte): byte; +var + lineIndex: byte; +begin + if startLine_irq < entryFieldHeight then startLine_irq := 0 + else startLine_irq -= entryFieldHeight; + lineIndex := fieldWidthMulTable[startLine_irq] + 1; + fieldPt_irq := #field + lineIndex; + fullLinesCnt := 0; + + for ib_irq := 0 to 4 do fullLines[ib_irq] := $FF; + + for ib_irq := 0 to 4 do begin + if FullLine() then begin + fullLines[fullLinesCnt] := lineIndex; + fullLinesCnt += 1; + for jb_irq := 0 to playFieldWidth do + fieldPt_irq[jb_irq] := Figure::tmSQ; + end; + startLine_irq += 1; + if startLine_irq >= playFieldHeight then break; + fieldPt_irq += fieldWidth; + lineIndex += fieldWidth; + end; + ReturnValue(fullLinesCnt); +end; + +/* +procedure RemoveLines(startLine_irq: global byte); +var + rlines_count1, rlines_count2: byte; +begin + for ib_irq := 0 to 4 do begin + if fullLines[ib_irq] = $FF then break; + rlines_count1 := fullLines[ib_irq] + playFieldWidth; // end of line + rlines_count2 := rlines_count1 - fieldWidth; // end of previous line + Memory::MemCpyLDDR(#field + rlines_count2, #field + rlines_count1, rlines_count2); + end; + gameOver := false; + for jb_irq := 1 to playFieldWidth+1 do begin + if field[jb_irq] <> Figure::tmEM then begin + Screen::GotoXY(0,0);Screen::PrintStr("OVER:RemoveLines"); + gameOver := true; + break; + end; + end; +end; +*/ + +procedure HandleKeyLeft(); +begin + if figureX > 0 then begin + if CheckTetromino(figurePt, figurePhase, figureX-1, figureY) then begin + figureX -= 1; + doRedraw := true; + end; + end; + newKey := false; +end; + +procedure HandleKeyRight(); +begin + if CheckTetromino(figurePt, figurePhase, figureX+1, figureY) then begin + figureX += 1; + doRedraw := true; + end; + newKey := false; +end; + + +procedure HandleKeyRotate(rotateValue: byte); +var + irqtmp: byte; +begin + irqtmp := (figurePhase + rotateValue) & $03; + if CheckTetromino(figurePt, irqtmp, figureX, figureY) then begin + figurePhase := irqtmp; + doRedraw := true; + end + else if CheckTetromino(figurePt, irqtmp, figureX+1, figureY) then begin + figureX += 1; + figurePhase := irqtmp; + doRedraw := true; + end + else if CheckTetromino(figurePt, irqtmp, figureX-1, figureY) then begin + figureX -= 1; + figurePhase := irqtmp; + doRedraw := true; + end; + newKey := false; +end; + + +procedure MainInterrupt(); +begin + if fullLinePhase > 0 then begin + fullLineTime -= 1; + if fullLineTime = 0 then begin + fullLineTime := fullLineDuration; + fullLinePhase -= 1; + if fullLinePhase > 0 then begin + // fill full lines with next square + if fullLinePhase = 2 then kb_irq := Figure::tmB1 + else if fullLinePhase = 1 then kb_irq := Figure::tmB2 + else kb_irq := Figure::tmSQ; + for ib_irq := 0 to 4 do begin + if fullLines[ib_irq] = $FF then break; + fieldPt_irq := #field + fullLines[ib_irq]; + for jb_irq := 0 to playFieldWidth do + fieldPt_irq[jb_irq] := kb_irq; + end; + end else begin + // remove full lines + for ib_irq := 0 to 4 do begin + if fullLines[ib_irq] = $FF then break; + jb_irq := fullLines[ib_irq] + playFieldWidth; // end of full line, destination + kb_irq := jb_irq - fieldWidth; // end of previous line, source + Memory::MemCpyLDDR(#field + kb_irq, #field + jb_irq, kb_irq); + end; + // check if game is over (is there anything in top line) + gameOver := false; + for jb_irq := 1 to playFieldWidth+1 do begin + if field[jb_irq] <> Figure::tmEM then begin + gameOver := true; + break; + end; + end; + // get next figure + figureNo := nextFigureNo; + nextFigureNo := GetRandomFigure(); + doRedrawNext := true; + figurePt := Figure::Figures[figureNo]; + figureWPt := Figure::FigureWidths[figureNo]; + figurePhase := 0; + figureX := 5; + figureY := 1; + // prepare screen shake + if fullLinesCnt > 0 then begin + shakeCnt := shakeTableSize[fullLinesCnt-1]-1; + shakeTablePtr := shakeTablePtrs[fullLinesCnt-1]; + end; + end; + doRedraw := true; + end; + return; + end; + if shakeCnt > 0 then begin + System::SetScreenPos(shakeTablePtr[shakeCnt]); + shakeCnt -= 1; + end; + if (gamePaused or gameOver) then return; + dropTime -= 1; + if picLoadCnt > 0 then picLoadCnt -= 1; + if dropTime = 0 then begin + dropTime := dropTimeInitial; + if not CheckTetromino(figurePt, figurePhase, figureX, figureY+1) then begin + PlaceFigure(figurePt, figurePhase, figureX, figureY); + if FindFullLines(figureY) then begin + fullLinePhase := 3; + fullLineTime := fullLineDuration; + end else begin + fullLinePhase := 1; + fullLineTime := 1; + end; + end else begin + figureY += 1; + end; + doRedraw := true; + end; + + if newKey then begin + case keyCode of + ASCII::lower_a: HandleKeyLeft(); + ASCII::lower_d: HandleKeyRight(); + ASCII::lower_s: HandleKeyRotate(1); + ASCII::lower_w: HandleKeyRotate($FF); + end; + end; +end; + + +procedure GameLoop(); +begin + // clear screen + //dbgStr[4] += 1; + Screen::ClearBox(0, 0, 128, 64, 0); + + if Title::picMode = 1 then begin + File::ShowPic(0, pictureY, #tpcLeft); + File::ShowPic(85, pictureY, #tpcRight); + end; + + DrawScoreHeaders(); + +// File::ShowPic(0, pictureY, "bg1left.tpc"); +// File::ShowPic(85, pictureY, "bg1right.tpc"); + + // initialize next figure random values + //dbgStr[5] += 1; + Random::SetRSeed(); + for ib_irq := 0 to Figure::FiguresNo do randomBucket2[ib_irq] := ib_irq; + ShuffleRandomBucket2(); + randomBucketPos := Figure::FiguresNo; + + //dbgStr[6] += 1; + + fullLinesCnt := 0; + prevLinesCnt := 0; + dropPoints := 0; + + newKey := false; + keyCode := 0; + dropTime := 1; + + //dbgStr[7] += 1; + figureNo := GetRandomFigure(); + nextFigureNo := GetRandomFigure(); + figurePt := Figure::Figures[figureNo]; + figureWPt := Figure::FigureWidths[figureNo]; + figurePhase := 0; + figureX := 5; + figureY := 1; + + //dbgStr[8] += 1; + doRedraw := true; + doRedrawNext := true; + gamePaused := false; + gameOver := false; + + //dbgStr[9] += 1; + InitField(); + + //dbgStr[10] += 1; + Screen::GotoXY(12,6); + //Screen::PrintStr(" A/D-Move S/W-Rotate X-Down Space-Drop P-Pause Q-Quit E/R-Speed");_addr + //Screen::PrintStr("AD-Move SW-Rotate X-Down Spc-Drop P-Pause Q-Quit ER-Speed N-NewP"); + // 123456789012345678901234567890123456789012345678901234567890 + Screen::PrintStr("A/D-Move S/W-Rotate X-Down Space-Drop P-Pause Q-Quit"); + + // sets function to be called from TIM's interrupt (every 100ms by default) + //dbgStr[11] += 1; + System::SetTimerFunction(#MainInterrupt); + // sets timer interrupt to fire faster, roughly 25 times a second + System::SetTimerCountdown(30); + + //dbgStr[12] += 1; + while keyCode <> ASCII::lower_q do begin + if Z80CPM::KeyPressed() then begin + keyCode := Z80CPM::GetChar(); + newKey := true; + end; + + + if ((picLoadPhase < 3) and (picLoadCnt = 0)) then case picLoadPhase of + 0: begin + File::PreparePic(0, pictureY, #tpcLeft); + picLoadPhase := 1; + picLoadCnt := picLoadCntInit; + end; + 1: begin + if not File::ShowIncrementalPic() then begin + File::PreparePic(85, pictureY, #tpcRight); + picLoadPhase := 2; + DrawScoreHeaders(); + DrawScores(); + end; + picLoadCnt := picLoadCntInit; + end; + 2: begin + if not File::ShowIncrementalPic() then begin + picLoadPhase := 3; + DrawNextFigure(true); + DrawNextFigure(false); + end; + picLoadCnt := picLoadCntInit; + end; + end; + + if newKey then begin +/* if keyCode = ASCII::lower_r then begin + newKey := false; + if dropTimeInitial > 4 then dropTimeInitial -= 2; + end + else if keyCode = ASCII::lower_e then begin + newKey := false; + if dropTimeInitial < 52 then dropTimeInitial += 2; + end + else */ + if keyCode = ASCII::lower_p then begin + newKey := false; + gamePaused := not gamePaused; + Screen::GotoXY(60,2); + if gamePaused then Screen::PrintStr("PAUSED") + else Screen::PrintStr(" "); + end + else if keyCode = ASCII::lower_x then begin + newKey := false; + dropTime := 1; + dropPoints += 1; + end + else if keyCode = ASCII::lower_n then begin + newKey := false; + if picLoadPhase = 3 then picLoadPhase := 0; + end + else if keyCode = ASCII::SPACE then begin + newKey := false; + gamePaused := true; + while CheckTetromino(figurePt, figurePhase, figureX, figureY+1) do begin + figureY += 1; + dropPoints += 2; + end; + dropTime := 1; + gamePaused := false; + end + else if keyCode = ASCII::lower_m then begin + newKey := false; + Title::ToggleMusic(); + end; + + end; + + if doRedraw then begin + doRedraw := false; + memcpy(#field, #drawField, fieldWidth*fieldHeight); + memcpy(#entryField, #drawEntryField, entryFieldWidth*entryFieldHeight); + if fullLinePhase = 0 then + DrawFigure(figurePt, figurePhase, figureX, figureY); + DrawField(); + if figureY < 5 then begin + Screen::GotoXY(fieldScreenX+2, fieldScreenY-2); + Screen::PrintNStr15(#spaceLine,10); + if figureY < 4 then begin + Screen::GotoXY(fieldScreenX+(figureX<<1)+figureX, fieldScreenY-2); + Screen::PrintNStr15(#figureWPt[figurePhase<<2],4); + end; + end; + DrawNextFigure(true); + // debug string + //Screen::GotoXY(10,4); + //Screen::PrintStr(#dbgStr); + end; + + if doRedrawNext then begin + doRedrawNext := false; + DrawNextFigure(true); + DrawNextFigure(false); + StrMath::AddStrStr(scoLinesPtrs[fullLinesCnt], #scoScore); + StrMath::AddByteStr(dropPoints, #scoScore); + dropPoints := 0; + StrMath::AddByteStr(fullLinesCnt, #scoLines); + if ((prevLinesCnt = 4) and (fullLinesCnt = 4)) then + StrMath::AddStrStr(#scoLines4B2B, #scoScore); + if fullLinesCnt <> 0 then + prevLinesCnt := fullLinesCnt; + if ((fullLinesCnt > 0) and (fullLinesCnt >= nextLevelLines)) then begin + fullLinesCnt -= nextLevelLines; + CalcNextLevelNumbers(); + if ((Title::picMode = 1) and (level > 2)) then begin + gamePaused := true; + File::ShowPic(0, pictureY, #tpcLeft); + DrawScoreHeaders(); + DrawScores(); + File::ShowPic(85, pictureY, #tpcRight); + DrawNextFigure(true); + DrawNextFigure(false); + gamePaused := false; + end; + end; + nextLevelLines -= fullLinesCnt; + DrawScores(); + end; + + if gameOver then break; + end; + if picLoadPhase < 3 then File::PicFile.Close(); + Screen::GotoXY(40,0);Screen::PrintStr("GAME OVER, press any key"); + DrawField(); + Z80CPM::GetChar(); +end; + +begin + //dbgStr[0] += 1; + Z80CPM::Startup(); + + Title::ToggleMusic(); + +/* + Screen::ClearBox(0, 0, 128, 64, $AA); + ib := 4; // image 0-14 + imgLeft[2] := ASCII::lower_a + ib; + imgRight[2] := ASCII::lower_a + ib; + + img.LoadCompressedFile(#imgLeft, #imgUnpack, #imgLoad); + imgPtr := imgUnpack; + scrPtr := $8000 + 0*4*256 + fieldScreenY; + for ib:= 0 to 43 do begin + Memory::MemCpyOut(#imgPtr, #scrPtr, 192); + imgPtr += 192; + scrPtr += $100; + end; + + img.LoadCompressedFile(#imgRight, #imgUnpack, #imgLoad); + imgPtr := imgUnpack; + scrPtr := $8000 + 85*4*256 + fieldScreenY; + for ib:= 0 to 43 do begin + Memory::MemCpyOut(#imgPtr, #scrPtr, 192); + imgPtr += 192; + scrPtr += $100; + end; +*/ + + // turn off terminal cursor + //dbgStr[1] += 1; + System::CursorOff(); + + + + // set hardware scroll to 0 (otherwise graphics coordinates could be translated) + //dbgStr[2] += 1; + System::SetScreenPos(0); + + // set printing font + //dbgStr[3] += 1; + Screen::SetFont(#Images::font); + + Title::Init(); + + while Title::TitleLoop(#scoScore) <> ASCII::lower_q do begin + // clear lines and score + StrMath::MulByteStr(0,0,#scoLines); + StrMath::MulByteStr(0,0,#scoScore); + CalcStartingLevelNumbers(); + GameLoop(); + end; + + // clear screen + Screen::ClearBox(0, 0, 128, 64, 0); + + System::SetTimerFunction(0); + System::SetTimerCountdown(0); + + // turn on terminal cursor + System::CursorOn(); + + Z80CPM::Exit(); +end. diff --git a/Publish/tutorials/TIM/timtris/timtris.trse b/Publish/tutorials/TIM/timtris/timtris.trse new file mode 100644 index 000000000..5828b0b2a --- /dev/null +++ b/Publish/tutorials/TIM/timtris/timtris.trse @@ -0,0 +1,99 @@ +zeropages = ,$02, $04, $08, $16, $0B, $0D, $10, $12, $22, $24, $68 +temp_zeropages = ,$54, $56, $58, $5A +zeropage_screenmemory = $fd +zeropage_colormemory = $fb +zeropage_decrunch1 = $47 +zeropage_decrunch2 = $48 +zeropage_decrunch3 = $4a +zeropage_decrunch4 = $4b +pascal_settings_use_local_variables = 0 +system = TIM +main_ras_file = none +dirart_flf_file = none +d64name = main +zeropage_internal1 = $4c +zeropage_internal2 = $4e +zeropage_internal3 = $50 +zeropage_internal4 = $52 +post_optimizer_passlda = 1 +post_optimizer_passjmp = 1 +post_optimizer_passldatax = 1 +post_optimizer_passstalda = 1 +post_optimizer_passldx = 1 +post_optimizer_passcmp = 1 +post_optimizer_passphapla = 1 +machine_state = $35 +exomize_toggle = 0 +show_all_files = 1 +use_vice_c1541 = 0 +border_color = 0 +background_color = 0 +override_target_settings = 0 +remove_unused_symbols = 1 +override_target_settings_org = $810 +override_target_settings_ignore_sys = 0 +override_target_settings_ignore_prg = 0 +output_debug_symbols = 1 +ignore_initial_jump = 0 +var_zeropages = , +zeropages_userdefined = , +global_defines = , +custom_system_cpu = 6502 +custom_system_methods = C64 +custom_system_assembler = From System +custom_system_assembler_custom = 0 +custom_system_emulator = 0 +custom_system_emulator_parameters = 0 +custom_system_assembler_parameters = 0 +custom_system_ending = 0 +petmodel = 2001-8N +amstradcpc_model = 464 +qemu = No +use_tripe = 0 +amstradcpc_options = 0 +spectrum_model = 0 +dosbox_cycles = 0 +dosbox_x86_system = default +cpu_x86_system = 8086 +cpu_x86_output = exe +columns = 40 +vic_memory_config = none +via_zeropages = , +output_type = prg +d64_paw_file = none +d64_paw_file_disk2 = none +override_target_settings_basic = 0 +override_target_settings_sys = 0 +override_target_settings_prg = 0 +build_list = , +exomizer_toggle = 0 +data_header_images:image1.flf = 0 +data_header_images/image1.flf = 0 +data_header_images/image2.flf = 0 +cc1541_disk_type = d64 +disable_compiler_comments = 0 +use_track_19 = 1 +data_header_images/tiles.flf = 0 +data_header_images/lalala.flf = 6.93633e-310 +charset_ = :resources/character.rom +data_header_images/font.flf = 0 +data_header_images/bottles.flf = 0 +data_header_images/font2.flf = 0 +data_header_bga.flf = 6.91611e-310 +data_header_images/bga.flf = 6.91611e-310 +data_header_images/bgb.flf = 6.91611e-310 +data_header_images/bgc.flf = 6.91611e-310 +data_header_images/bgd.flf = 6.91611e-310 +data_header_bge.flf = 6.91611e-310 +data_header_images/bgf.flf = 6.91611e-310 +data_header_images/bgg.flf = 6.91611e-310 +data_header_images/bgh.flf = 6.91611e-310 +data_header_images/bgi.flf = 6.91611e-310 +data_header_images/bgj.flf = 6.91611e-310 +data_header_bgk.flf = 6.91611e-310 +data_header_bgl.flf = 6.91611e-310 +data_header_bgm.flf = 6.91611e-310 +data_header_bgn.flf = 6.91611e-310 +data_header_bgo.flf = 6.91611e-310 +data_header_images/bgo.flf = 6.91611e-310 +use_python = 0 diff --git a/Publish/tutorials/TIM/timtris/title.tru b/Publish/tutorials/TIM/timtris/title.tru new file mode 100644 index 000000000..19912e09c --- /dev/null +++ b/Publish/tutorials/TIM/timtris/title.tru @@ -0,0 +1,346 @@ +Unit Title; + +@use "memory" +@use "system/z80cpm" +@use "system/system" +@use "system/screen" +@use "system/ascii" + +var + Logo: string = ( + // 1 2 3 4 + //1234567890123456789012345678901234567890 + " ", + " XXXXX X X X XXXXX XXXX X XXX ", + " X X XX XX X X X X X ", + " X X X X X X XXXX X XXX ", + " X X X X X X X X X ", + " X X X X X X X X XXX ", + " " + ); + + const LogoW: byte = 35; + const LogoH: byte = 7; + const LogoWScr: byte = LogoW * 3; // * 2 * 15 / 10 + const LogoHScr: byte = LogoH * 2; + + const LogoWTblSize: byte = 40; + LogoWTbl: array[LogoWTblSize] of byte = buildtable("Math.cos(i*Math.PI*2.0/(LOGOWTBLSIZE))*(128-LOGOWSCR)/2+(128-LOGOWSCR)/2+0.5"); + const LogoHTblSize: byte = 25; + LogoHTbl: array[LogoHTblSize] of byte = buildtable("Math.cos(i*Math.PI*2.0/(LOGOHTBLSIZE))*(20-LOGOHSCR)/2+(20-LOGOHSCR)/2+0.5"); + + LogoX: byte; + LogoY: byte; + i,j,k,l,m: byte; + tblW: byte; + tblH: byte; + doDraw: boolean; + key: byte; + newKey: boolean; + pos: byte; + level: byte = 1; + levelStr: string = ("01"); + rndMode: byte = 0; + picMode: byte = 1; + rndLines:byte = 0; + rndLinesStr: string = ("00"); + + score, name: pointer; + + scoreTbl: string = ( + //123456789012345678901234567890 + "00100000 Zarko ", + "00090000 Marko ", + "00080000 Leuat ", + "00070000 Micko ", + "00060000 Popmilo ", + "00050000 Once Upon ", + "00040000 a Byte ", + "00030000 8 Bit Chip", + "00020000 C64 > ZX ", + "00010000 TimTris! " + ); + const oneScore: byte = 20; + const lastScore: byte = oneScore * 9; + + //xscore: string = ("00009000"); + xscore: pointer; + xname: string = ("MILOJE "); + const enterNameX: byte = 21; + const enterNameY: byte = 16; //62; + + scrollStr: string = ( + "TimTris v0.9 by Zarko Zivanov for Revision 2024 ", + "Original Tetris by Alexey Pajitnov ", + "Game is made with TRSE by Nicolaas Groeneboom, using TIM-011 gfx libs by me, startup/file code adapted from MESCC by Miguel Garcia Lopez, " + "PTX Player by S.V.Bulba, and Tetris 2 Red Dawn music by Frantisek Fuka ", + "Many thanks to Marko for helping with various TIM stuff and Micko for TIM-011 emulator! " + ); + + playMusic: byte = 0; + +procedure Init(); +begin + k := LogoW * LogoH; + for i := 0 to k do begin + if Logo[i] = Ascii::X then Logo[i] := $90 + else Logo[i] := $BA; + end; +end; + + +procedure StartStopMusic(); +begin + if playMusic = 1 then begin + asm(" + call $5000 + "); + end else if playMusic = 2 then begin + asm(" + call $5003 + "); + end; +end; + + +procedure ToggleMusic(); +begin + if playMusic = 1 then begin + playMusic := 2; + end else begin + playMusic := 1; + end; + StartStopMusic(); +end; + +procedure DrawLogo(); +begin + if LogoX >= 2 then k := LogoX - 2 + else k := 0; + Screen::ClearBox(k, LogoY, 4, LogoHScr, $00); + k := LogoX + LogoWScr; + if k > 124 then k := 124; + Screen::ClearBox(k, LogoY, 4, LogoHScr, $00); + + LogoX := LogoWTbl[tblW]; + LogoY := LogoHTbl[tblH]; + j := 0; + k := LogoY; + for i := 0 to LogoH do begin + Screen::GotoXY(LogoX, k); + Screen::PrintNStr15(#Logo[j], LogoW); + j += LogoW; + k += 2; + end; +end; + +procedure DrawHiScore(); +begin + j := 0; + k := 26; + for i :=0 to 10 do begin + Screen::GotoXY(47, k); + if i = 0 then Screen::SetPrintInv(true) + else Screen::SetPrintInv(false); + if i < 9 then begin + Screen::PrintChr(' '); + Screen::PrintChr(ASCII::NUM1 + i); + end else begin + Screen::PrintChr('1'); + Screen::PrintChr('0'); + end; + Screen::PrintChr(' '); + + //Screen::GotoXY(53, k); + Screen::PrintNStr(#scoreTbl[j], oneScore); + j += oneScore; + k += 2; + end; +end; + +procedure DrawText(); +begin + //Screen::GotoXY(34, 20); + //// 123456789012345678901234567890 + //Screen::PrintStr("v1.0, Zarko Zivanov [c] 2023"); + + Screen::GotoXY(6, 48); + // 1234567890123456789012345678901234567890 + Screen::PrintStr("Starting level [A/S]: "); + Screen::PrintStr(#levelStr); + Screen::PrintStr(" Random lines [D/F]: "); + Screen::PrintStr(#rndLinesStr); + + Screen::GotoXY(6, 52); + Screen::PrintStr("[N]ext figure: "); + if rndMode = 0 then Screen::PrintStr("Bucket") + else Screen::PrintStr("Random"); + Screen::PrintStr(" [P]ictures loading: "); + case picMode of + 0: Screen::PrintStr("Background"); + 1: Screen::PrintStr("Pause game"); + 2: Screen::PrintStr("No loading"); + end; + + Screen::GotoXY(6, 56); + // 1 2 3 4 5 6 + // 1234567890123456789012345678901234567890123456789012345678901234567890 + Screen::PrintStr("SPACE - Start game Q - Quit game M - Toggle music"); +end; + +procedure TitleTimer(); +begin + tblW += 1; + if tblW >= LogoWTblSize then tblW := 0; + tblH += 1; + if tblH >= LogoHTblSize then tblH := 0; + doDraw := true; +end; + +function IsNewHighScore(score: global pointer): byte; +var + smaller: boolean; +begin + j := 0; + for i :=0 to 10 do begin + // check new score against the current one + l := j + 8; + m := 0; + smaller := false; + for k := j to l do begin + if score[m] > scoreTbl[k] then ReturnValue(j) + else if score[m] < scoreTbl[k] then begin + smaller := true; + break; + end; + m += 1; + end; + // check if equal + if not smaller then ReturnValue(j); + j += oneScore; + end; + ReturnValue($FF); +end; + +procedure InsertNewScore(pos: global byte, score, name: global pointer); +begin + if pos < lastScore then begin + Memory::MemCpyLDDR(#scoreTbl + lastScore - 1, #scoreTbl + lastScore + oneScore - 1, 200 - pos - oneScore); + end; + Memory::MemCpyLDIR(score, #scoreTbl + pos, 8); + Memory::MemCpyLDIR(name, #scoreTbl + pos + 8 + 2, 10); +end; + +procedure EnterName(name: global pointer); +begin + for i := 0 to 10 do name[i] := ASCII::SPACE; + key := 0; + i := 0; + while key <> Ascii::CR do begin + Screen::GotoXY(enterNameX, enterNameY); + // 1234567890123456789012345678901234567890 + Screen::PrintStr("New high score, enter your name : "); + Screen::PrintNStr(name, 10); + key := Z80CPM::GetChar(); + if ((key >= Ascii::SPACE) and (key <= Ascii::lower_z)) then begin + if i < 10 then begin + name[i] := key; + i += 1; + end; + end; + if key = Ascii::BACKSP then begin + if i>0 then begin + i -= 1; + name[i] := Ascii::SPACE + end; + end; + end; + Screen::ClearBox(0, enterNameY, 128, 2, $00); +end; + + +function TitleLoop(xscore: global pointer): byte; +begin + Screen::ClearBox(0, 0, 128, 64, $00); + System::SetScreenPos(0); + + LogoX := 0; + LogoY := 0; + tblW := 0; + tblH := 0; + doDraw := false; + + Screen::SetScroll(20, 20, 44, #scrollStr); + + DrawHiScore(); + DrawText(); + + System::SetTimerFunction(#TitleTimer); + System::SetTimerCountdown(60); + + pos := IsNewHighScore(#xscore); + if pos <> $FF then begin + EnterName(#xname); + InsertNewScore(pos, #xscore, #xname); + DrawHiScore(); + end; + + key := 0; + newKey := false; + while true do begin + if Z80CPM::KeyPressed() then begin + key := Z80CPM::GetChar(); + newKey := true; + end; + + if newKey then begin + case key of + ASCII::SPACE: break; + ASCII::lower_q: break; + ASCII::lower_s: if level < 15 then level += 1; + ASCII::lower_a: if level > 1 then level -= 1; + ASCII::lower_f: if rndLines < 15 then rndLines += 1; + ASCII::lower_d: if rndLines <> 0 then rndLines -= 1; + ASCII::lower_n: begin + rndMode += 1; + if rndMode > 1 then rndMode := 0; + end; + ASCII::lower_p: begin + picMode += 1; + if picMode > 2 then picMode := 0; + end; + ASCII::lower_m: ToggleMusic(); + end; + if level < 10 then begin + levelStr[0] := ASCII::NUM0; + levelStr[1] := ASCII::NUM0 + level; + end else begin + levelStr[0] := ASCII::NUM1; + levelStr[1] := ASCII::NUM0 + level - 10; + end; + if rndLines < 10 then begin + rndLinesStr[0] := ASCII::NUM0; + rndLinesStr[1] := ASCII::NUM0 + rndLines; + end else begin + rndLinesStr[0] := ASCII::NUM1; + rndLinesStr[1] := ASCII::NUM0 + rndLines - 10; + end; + + DrawText(); + newKey := false; + end; + + if doDraw then begin + doDraw := false; + DrawLogo(); + Screen::DoScroll(); + end; + end; + + System::SetTimerFunction(0); + System::SetTimerCountdown(0); + + ReturnValue(key); +end; + +end. diff --git a/resources.qrc b/resources.qrc index 953e41155..766d930b6 100644 --- a/resources.qrc +++ b/resources.qrc @@ -771,5 +771,6 @@ resources/images/FOENIX.png resources/images/AGON.png resources/images/PRIMO.png + resources/images/tutorials/timtris.png diff --git a/resources/images/tutorials/timtris.png b/resources/images/tutorials/timtris.png new file mode 100644 index 000000000..794b82953 Binary files /dev/null and b/resources/images/tutorials/timtris.png differ diff --git a/resources/text/tutorials.txt b/resources/text/tutorials.txt index 6fdb49f6b..5a3b4a371 100644 --- a/resources/text/tutorials.txt +++ b/resources/text/tutorials.txt @@ -80,6 +80,7 @@ AMSTRADCPC; SuperSki2021 (text game); AMSTRADCPC/SuperSki2021/;

SuperSki2021< AMSTRADCPC; Unit tests; AMSTRADCPC/UnitTests/;

Unit tests

Z80/CPC unit tests. SPECTRUM; ZX Spectrum tutorials; SPECTRUM/tutorials/;

Main ZX Spectrum tutorials

Main ZX spectrum tutorials in TRSE. TIM; Main TIM011 tutorials; TIM/tutorials/;

Main TIM011 tutorials

The TIM-001 is a Serbian Z180 microcomputer that was developed in 1983/84. With its mesmerising 4-colour green palette, excellent 512x256 resolution, wonderful Z180 CPU and a multitide of TRSE libraries/tutorials, there is no reason why you shouldn't start coding for it today! +TIM; Timtris; TIM/timtris/;

Timtris - Tetris for the TIM

TimTris is a Tetris clone for TIM-011, written by Zarko Zivanov TIM; Unit tests; TIM/unittests/;

Unit tests

Internal TRSE Z180 unit tests TVC; Main TVC tutorials; TVC/tutorials/;

Main TVC tutorials

tutorials under construction TVC; TVC tutorials by Zsolt Bertók; TVC/tutorials_bertok/;

TVC tutorials made by Zsolt Bertók

Three example programs made by Bertók: 1: SpaceWar, a small game, 2: sprite displayer example 3: TRSE welcome tutorial