From 4b4fffdbf1f64f875ce8d2e24e3e91d8634b153b Mon Sep 17 00:00:00 2001 From: Lani Aung Date: Sat, 2 Oct 2021 19:18:58 -0600 Subject: [PATCH] Parse 12 vs 24 bit colors eventually --- Controllers/HomeController.cs | 38 +- Docs/fkiss.txt | 741 ++++++++++++++++++ Docs/kissfrmt.txt | 417 ++++++++++ Models/DirectoryModel.cs | 26 + Models/PaletteModel.cs | 29 +- ...{ConfigurationModel.cs => PlaysetModel.cs} | 19 +- Models/Point.cs | 6 + Scripts/main.ts | 46 ++ Services/ConfigurationReaderService.cs | 55 +- Services/FileParserService.cs | 38 + Startup.cs | 1 + Styles/main.scss | 14 +- Views/Home/Index.cshtml | 27 +- Views/Home/Play.cshtml | 10 + Views/Shared/_Layout.cshtml | 9 +- 15 files changed, 1447 insertions(+), 29 deletions(-) create mode 100755 Docs/fkiss.txt create mode 100755 Docs/kissfrmt.txt create mode 100644 Models/DirectoryModel.cs rename Models/{ConfigurationModel.cs => PlaysetModel.cs} (54%) create mode 100644 Services/FileParserService.cs create mode 100644 Views/Home/Play.cshtml diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index dffd18e..a8494c3 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; using System.Diagnostics; +using System.IO; +using System.IO.IsolatedStorage; using fxl.codes.kisekae.Models; using fxl.codes.kisekae.Services; using Microsoft.AspNetCore.Http; @@ -12,27 +15,56 @@ namespace fxl.codes.kisekae.Controllers { private readonly ILogger _logger; private readonly ConfigurationReaderService _readerService; + private readonly IsolatedStorageFile _storage; public HomeController(ILogger logger, ConfigurationReaderService readerService) { _logger = logger; _readerService = readerService; + + _storage = IsolatedStorageFile.GetUserStoreForApplication(); } [HttpGet] public IActionResult Index() { - return View(); + var directories = _storage.GetDirectoryNames(); + var model = new List(); + + foreach (var directory in directories) + { + var files = _storage.GetFileNames(Path.Combine(directory, "*.cnf")); + if (files.Length <= 0) continue; + + var doll = new DirectoryModel(directory); + foreach (var file in files) + { + doll.Configurations.Add(new ConfigurationModel(file)); + } + + model.Add(doll); + } + + return View(model); } [HttpPost] - public IActionResult LoadConfiguration(IFormFile file) + public IActionResult Upload(IFormFile file) { + _logger.LogTrace($"File uploaded: {file?.FileName}"); if (!(file?.FileName.EndsWith("cnf", StringComparison.InvariantCultureIgnoreCase) ?? false)) throw new Exception("Please select a *.cnf file"); var model = _readerService.ReadCnf(file); - return View("Index"); + return View("Play", model); + } + + [HttpPost] + public IActionResult Select(string directory, string file) + { + var stream = _storage.OpenFile(Path.Combine(directory, file), FileMode.Open); + var model = _readerService.ParseStream(stream, directory); + return View("Play", model); } public IActionResult Privacy() diff --git a/Docs/fkiss.txt b/Docs/fkiss.txt new file mode 100755 index 0000000..646077b --- /dev/null +++ b/Docs/fkiss.txt @@ -0,0 +1,741 @@ +The Wayback Machine - +https://web.archive.org/web/20090409112451/http://www.msen.com:80/~crandall/fkiss.html + +KiSS .cnf layout, FKiSS/FKiSS2 command reference, and various PlayFKiSS +notes. + + * written by Chad Randall crandall@msen.com + + + * Last updated, December 31, 1997 + + + +Terminology + + + +Action + +See Command + +Cel + +A graphical image where any pixel using color 0 is transparent. The +basic building blocks for a KiSS set. Cels are identified by name. When +issuing FKiSS events and commands, there should never be more than one +cel per KiSS set with the same name. Such instances are undefined and +undesired results may occur. + +Cherry Kiss (ckiss) + +A recent cel format allowing 24 and 32 bit color. This includes an alpha +channel for variable transparency. This format requires quite a bit of +memory and horsepower. But as computers get faster and cheaper, this may +become more widespread. PlayKis s for Acorn, WKiss32, and KissLD are the +only viewers capable of ckiss right now. The next release of PlayFKiSS +*will* have ckiss support. Internally, pfks072 can already handle it. + +Command + +A keyword that issues changes or activates something else. + +Fix + +A numerical value ranging from 0 up to 32000, applied to an object. An +object may not be moved by the user unless the fix value is equal to +zero. Any time the user clicks on the object, it's fix value is reduced +by one. + +FKiSS + +An addition to the KiSS format that allows more user interactivity. +FKiSS comprises events, commands, and the newer flags. Most FKiSS +innovations come from the Japanese side of the Pacific. + +FKiSS2 + +Extra commands and features developed by Chad Randall and John Stiles. +Included are object collision detection and relative movement. + +FKiSS2.1 + +Even more commands, including "if" conditional timers and random movement. + +Flags + +A recent FKiSS addition that allows the set creator to set certain +states without requiring a command entry. An example is the ;%t128 +portion of a cel definition line. + +Event + +A keyword specifying a group of commands that will be executed when a +specific condition occurs. + +Object + +A group of cels. This is a convenient way to issue commands and events +to a bunch of cels, such as an item of clothing. Such item can contain +one cel for the foreground, one for the inside, one for the sleeve, etc. +Objects are usually proceeded by an " #". + +Palette + +A number of colors consisting at the minimum of 16 pens up to 256 pens. +There can also be up to 10 palette groups per palette. The maximum +number of pens that can be specified is 256*10 or 2560. + +Set + +The group of cels displayed at any one time. There can be up to 10 sets +per KiSS set. + + + + + +Format of the .cnf file + +The sample layout of a .cnf file follows: + +| + +;comments + +%palette1.kcf + +%palette2.kcf + +(640,480) ; Environment size + +[0 ; border color + +;more comments + +#3 fog.cel *1 :0 1 2 3 4 5 6 7 8 9 ;%t128 transparent fog + +#0.10 dress.cel *0 :0 1 2 3 4 5 6 7 8 9 ; lady's dress + +#1.32000 body.cel *0 :0 1 2 3 4 5 6 7 8 9 ; lady + +#0.10 dress_.cel *0 :0 1 2 3 4 5 6 7 8 9 ; back of lady's dress + +;even more comments + +;@EventHandler() + +;@initalize() + +;@ unmap("fog.cel") + +;some more comments + +$0 120,50 220,150 65,65 + +$1 120,50 220,150 65,65 + +';end of file + +| + + + + + +Now to break down each line and explain what all those symbols mean. + + + +| + +%palette1.kcf + +| +|| +|| + +This indicates a palette file. There may be up to 256 pens per KiSS set. +There may be up to 16 palette files if each holds 16 pens. Any pens over +256 are ignored. Also, each palette file can hold up to 10 groups of +pens, for a total of 2560 pens. These lines are required! There is no +default pen set defined. + +This line maybe omitted in Cherry Kiss files. Since 24/32 bit graphics +define their own palettes, there is no requirement for a palette. If you +intend to mix ckiss and kiss/gs cels, this line will still be required. + +| + +(640,480) + +| +|| +|| + +This specifies the playfield size. If this line is omitted, it will +default to 448 x 320. + +| + +[0 + +| +|| +|| + +This is the border color, as a pen number. Some programs will ignore +this value. Other programs such as DOS based ones will fill the area +around the playfield with this color. It will default to 0 if omitted. + + + +| + +#0 dress.cel *0 :0 1 2 3 4 5 6 7 8 9 ;%t128 ;comment + +| + +This is broken down farther: + +| + +#0.10 + +| +|| +|| + +The object number this individual cel is grouped with. The number +following the "." is the fix value of the related object. This value is +optional and will default to 0. + +| + +dress.cel + +| +|| +|| + +The name of the cel. While this can be any name you want, there is a +certain convention to follow if you plan on distributing the file. Keep +filenames compliant to the 8.3 filename MS-DOS naming restriction. Also +use lowercase lette rs to conform under case-sensitive systems such as UNIX. + +| + +*0 + +| +|| +|| + +This indicates the offset into the palette pen group. This only applies +to those cels with 16 colors. 256 color cels will default to offset 0. + +| + +:0 1 2 3 4 5 6 7 8 9 + +| +|| +|| + +This section specifies which set groups the cel is visible in. A cel +will default to all groups if this section is omitted. + +| + +;%t128 + +| +|| +|| + +This indicates the cel's transparent value. Any number from 0 to 255 may +be used, with 0 as opaque and 255 completely invisible. This setting is +not used by older KiSS viewers, so be aware of Yours truly, target +audience. See also t ransparent() + +* I intend to allow other letters here in future releases of PlayFKiSS. +Such actions as lighten, darken, additive, subtractive, displacement, +XOR, AND, OR, and other graphics mixing operators. This will allow the +end user to recreate many PhotoShop l ayering features. + + + +Even further down we find: + +| + +;@EventHandler + +;@initalize() + +;@ unmap("fog.cel") + +| + + + +This is a section of FKiSS code. The ";@" symbols always indicate FKiSS +commands are on that line. EventHandler is a *case-sensitive* flag that +starts the FKiSS section of code. Likewise, all commands and events +*must* *be* in *lowerca se* to be properly recognized by most FKiSS +parsers. A complete list of FKiSS and FKiSS2 commands follow at the end +of this document. + + + +| + +$0 120,50 220,150 65,65 + +$1 120,50 220,150 65,65 + +| +|| +|| + +This line basically says that for set 0, use palette group 0. Place +object 0 at 120 x 50, object 1 at 220 x 150, and object 2 at 65 x 65. +Likewise, set 1 is identical except that palette group 1 is used. Don't +attempt to edit these values by hand. Most any KiSS viewer program will +save these for you. You can cut and paste them from a temporary .cnf +file into your master .cnf file if you don't wish to loose other +information such as comments. + + + + + +Standard FKiSS/FKiSS2 Events + + + +alarm(number) + +Triggered when a timer reaches zero. Note: Most viewer programs will +only accept timer numbers from 0 up to 64. The newer FKiSS2 proposal +will allow from 0 up to 511. + +apart("celname.cel", "celname2.cel") + +Triggered when cel1 no longer touches cel2, but only if they touching +before the move. A touch consists of non-transparent pixels that +overlap. *Note: This is a proposed FKiSS2.1 event and is not generally +supported by other viewers.* + +** + +** + +begin() + +Triggered after the first screen is activated. This is a good place to +start the animations using timer() + +catch(#object) / catch("celname.cel") + +Triggered when the user "grabs" an object or cel, and the fix value is +at zero (movable). + +col(number) + +Similar to set(), but triggered when the palette group is changed. Note: +col is probably short for color. + +collide("celname.cel", "celname2.cel") + +Triggered when cel1 touches cel2, but only if they were not touching +before the move. A touch consists of non-transparent pixels that +overlap. *Note: This is a proposed FKiSS2.1 event and is not generally +supported by other viewers.* + +** + +** + +drop(#object) / catch("celname.cel") + +Triggered when the user "drops" an object or cel, and the fix value is +at zero (movable). + +end() + +Triggered when the user closes the KiSS set. This is a good place to +play or display any farewell messages. + +fixcatch(#object) / fixcatch("celname.cel") + +Similar to catch(), but only triggered when the object is fixed in place. + +fixdrop(#object) / catch("celname.cel") + +Similar to drop(), but only triggered when the object is fixed in place. + +in(#object1,#object2) + +Triggered when one object's bounding boxes overlap another. The bounding +boxes are formed by adding all the visible and mapped cels's rectangles +to form a geometric shape. It is *not* the total rectangle size, but +rather a combination of individua l rectangles. This event only occurs +when 2 objects are apart and are then moved together. *Note: This is a +proposed FKiSS2 event and is not generally supported by other viewers.* + +** + +** + +initialize() + +Triggered commands before any visual information is displayed. This is a +good place to unmap cels. + +never() + +This is *never* triggered. It is a good place to hide code you don't +wish to run. Note: You can precede FKiSS2 code with this event to hide +it from older FKiSS viewers. + +out(#object1,#object2) + +Similar to in(), but triggered when 2 objects are moved apart. *Note: +This is a proposed FKiSS2 event and is not generally supported by other +viewers.* + +** + +** + +press(#object) / fixcatch("celname.cel") + +Similar to catch(), but triggered regardless of the fix value. + +release(#object) / fixcatch("celname.cel") + +Similar to drop(), but triggered regardless of the fix value. + +set(number) + +Triggered when the user or changeset() command changes the current set. + +stillin(#object1,#object2) + +Triggered when one object's bounding boxes overlap another. The bounding +boxes are formed by adding all the visible and mapped cels's rectangles +to form a geometric shape. It is *not* the total rectangle size, but +rather a combination of individua l rectangles. Unlike in(), this event +occurs whenever the object is moved and "touches" the second object, +regardless of the initial states. *Note: This is a proposed FKiSS2 event +and is not generally supported by other viewers.* + +** + +** + +stillout(#object1,#object2) + +Similar to stillin(), but triggered when 2 objects are moved apart. +*Note: This is a proposed FKiSS2 event and is not generally supported by +other viewers.* + +** + +** + +unfix(#object) + +Triggered when the fix value reaches zero. + +version(set_version_number) + +Triggered when the current viewer version is equal or greater than the +FKiSS command/event version number. This can be used to inform the user +that the KiSS set uses commands that are unsupported by the viewer. See +the extended notes at the bottom of t his file for an effective example +on the usage of this event. *Note: This is a proposed FKiSS2 event and +is not generally supported by other viewers.* + +** + + + +Standard FKiSS/FKiSS2 Commands + +altmap(#object) / altmap("celname.cel") + +Turns any mapped cels to unmapped and vice-versa. + +changecol(palette) + +Forces another palette group to become the active one. + +changeset(set) + +Forces another set to become the active one. + +debug("messagestring") + +Displays a message. Each viewer may have a different method to display +debug information. + +iffixed(#obj, timer, value) + +Sets timer if the object specified by #obj is fixed (fix value is +greater than zero). *Note: This is a proposed FKiSS2.1 event and is not +generally supported by other viewers.* + +** + +** + +ifmapped("cel", timer, value) + +Sets timer if the cel specified by "cel" is mapped. *Note: This is a +proposed FKiSS2.1 event and is not generally supported by other viewers.* + +** + +** + +ifmoved (#obj, timer, value) + +Sets timer if the object specified by #obj has been moved. An object is +defined as moved if it's coordinates are not equal to the coordinates +specified in the .CNF file. *Note: This is a proposed FKiSS2.1 event and +is not generally supported by other viewers.* + +** + +** + +ifnotfixed(#obj, timer, value) + +Sets timer if the object specified by #obj is not fixed (fix value is +equal to zero). *Note: This is a proposed FKiSS2.1 event and is not +generally supported by other viewers.* + +** + +** + +ifnotmapped("cel", timer, value) + +Sets timer if the cel specified by "cel" is not mapped. *Note: This is a +proposed FKiSS2.1 event and is not generally supported by other viewers.* + +** + +** + +ifnotmoved (#obj, timer, value) + +Sets timer if the object specified by #obj has not been moved. An object +is defined as moved if it's coordinates are not equal to the coordinates +specified in the .CNF file. *Note: This is a proposed FKiSS2.1 event and +is not generally supported by o ther viewers.* + +** + +** + +map(#object) / map("celname.cel") + +Maps all cels. + +move(#object,offsetx,offsety) + +Moves an object using the offsets specified. Note: PlayFKiSS will never +move an object off-screen, even when "Enforce Boundaries" is turned off. + +movebyx(#object,#object,offsetx) + +Moves an object using the offset from another object.*Note: This is a +proposed FKiSS2 command, and is not generally supported by other viewers*. + +movebyy(#object,#object,offsetx) + +Moves an object using the offset from another object. *Note: This is a +proposed FKiSS2 command, and is not generally supported by other viewers.* + +** + +** + +moverandx(#object,min,max) + +Moves an object using random values. The new coordinate is relative, +based on the min and max values. Ex: If min is -1 and max is 1, the new +location may be either 1 pixel less, one pixel more, or the same +location.*Note: This is a proposed FKiSS2.1 command, and is not +generally supported by other viewers*. + +moverandy(#object,min,max) + +Moves an object using random values. The new coordinate is relative, +based on the min and max values. Ex: If min is -1 and max is 1, the new +location may be either 1 pixel less, one pixel more, or the same +location.*Note: This is a proposed FKiSS2.1 command, and is not +generally supported by other viewers*. + +moveto(#object,x,y) + +Moves an object to the absolute coordinates specified. Note: PlayFKiSS +will never move an object off-screen, even when "Enforce Boundaries" is +turned off. *Note: This is a proposed FKiSS2 command, and is not +generally supported by other viewers.* + +*< /DIR> * + +** + +movetorand(#object) + +Moves an object to random coordinates. Note: PlayFKiSS will never move +an object off-screen, even when "Enforce Boundaries" is turned off. +*Note: This is a proposed FKiSS2.1 command, and is not generally +supported by other viewers.* + +** + +** + + + +music ("filename.mid") + +Plays a MIDI song. *Note: This is a proposed FKiSS2 command, and is not +generally supported by other viewers.* + +** + +** + +nop() + +Does nothing. NOP is short for "No Operation" in assembly language. + +notify("message string") + +Currently a synonym for debug() *Note: This is a proposed FKiSS2 +command, and is not generally supported by other viewers.* + +** + +** + +quit() + +Forces the viewer to exit. Note: PlayFKiSS retains this command when +saving, but will not quit when issued. + +randomtimer(number,minimum,maximum) + +Sets a timer based on a random number. + +setfix(#object,fixval) + +Manually sets the fix val for the object. If the value is 0, any unfix() +events linked to this object will be triggered. *Note: This is a +proposed FKiSS2.1 command, and is not generally supported by other viewers.* + +** + + + +sound("filename.wav") / sound("filename.au") + +Plays a sound. Not all viewers support .au format and vice-versa. If +possible, include 2 versions of your .cnf file and convert all sounds to +both formats. + +timer(number,duration) + +Starts a timer, using duration microseconds for the countdown. Setting a +timer that is already active will reset to the duration value. Setting a +timer to 0 will effectively turn it off. A microsecond is 1/100 of a +second; A timer set to 100 microsecon ds will trigger an alarm 1 second +later. Note: PlayFKiSS has a scale of 10 microseconds between each alarm +event, and will only visually update the screen every 100 microseconds. + +transparent(#object, reloffset) / transparent("celname.cel", reloffset) + +Sets the transparency level of the cels/object. reloffset is the value +to add to the current transparency level. The maximum range is from 0 +(totally opaque) up to 255 (totally transparent). Note: This command is +fairly recent and is not supported by a ll FKiSS viewers. Also, some +viewers show cels dithered and other's change to true-color mode (16 +million colors). + +unmap(#object) / unmap("celname.cel") + +First case, unmaps all cels belonging to object "#object". Second case +unmaps a specific + +viewport(x,y) + +Changes the viewport offset. Note: PlayFKiSS ignores this command, but +will retain it when saving. + +windowsize(x,y) + +Changes the window size. Note: PlayFKiSS ignores this command, but will +retain it when saving. + + + +Extended FKiSS2 information + +The commands and events marked as FKiSS2 and FKiSS2.1 are, at present, +only supported by PlayFKiSS for Win95/NT4 and PlayKiss for Acorn. French +KiSS has FKiSS2 support, minus music() and all transparency related +stuff. WKiss32g s upports a subset of FKiSS2 including (but not limited +to) music(), in(), out(), movebyx(), movebyy(), collide(), apart(), +movetorand(), and moveto(). KissLD7x also supports a few FKiSS2 +commands. If you would like to see more FKiSS2 commands, and/or set s, +spread the word. Ask your favorite KiSS programmer to implement the +commands. Ask your favorite artist to either insert FKiSS2 commands, or +create an enhanced .cnf file. Only the support of users will determine +the outcome of the entire KiSS project. + + + +To use the version() event, code your EventHandler as follows: + + + +| + +;@EventHandler + +;@nothing() ; This tricks older viewers into ignoring the next 2 lines. + +;@version(2) ; If the viewer supports FKiSS2, + +; ; revision 2, run the following commands. + +;@ unmap("warning.cel") + +; ; warning.cel is a huge poster saying + +; ; "You need a FKiSS2 viewer to play this set." + +;@begin() + +;; If this warning is only a warning (maybe the set will still work +without FKiSS2), you could allow the user to dismiss the warning by +clicking on it: + +;@release("warning.cel") + +;@ unmap("warning.cel") + +| + + + +FKiSS3 specs + + diff --git a/Docs/kissfrmt.txt b/Docs/kissfrmt.txt new file mode 100755 index 0000000..4b8dd99 --- /dev/null +++ b/Docs/kissfrmt.txt @@ -0,0 +1,417 @@ +------------------------------------------------------------------------------ + + + KISS FORMAT DOCUMENT + + This is a poor translation of kissgs.doc. Comments, questions and + corrections are greatly welcomed. + + _KISS/GS ( KISS General Specification ) Manual by K.O.S._ + + >>>>>>> + + This is an abridged translation of the official document about KISS + data format. However parts of it are undefined and will be updated + gradually. + _________________________________________________________________ + +Outline + + 1. Introduction + 2. Abstract of New Specification + 3. Basic Concepts + 4. KISS/GS New features + 5. Details of the Configuration File + 6. Details of Cel Files + 7. Palette File Detail + 8. KISS/GS Ranks + 9. Appendix + + + _________________________________________________________________ + + 1. _Introduction_ + + KISS - a paper doll program has been developped for computers + based on NEC PC-9801VM2 architecture since March 1991. Many people + have enjoyed and implemented KISS for other computers. Now KISS is + running on many platforms. + + Now we make a reference manual about new KISS data format, that + is, + + + KISS General Specification : KISS/GS + + and release this. + + 2. _Abstract of new specification_ + + New style KISS data is upper compatible with the old style. + + +* color (cel) 16 colors -> 16 or 256 colors +* color (palette) 4096 colors -> 4096 or 16,777,216 colors +* screen size 640 x 400 -> 768 x 480 or more +* cel and object max 128 -> 256 or more + + Multiple palette files available. + (-> 4-1 multipalette) + + A header is added to cel/palette files to store additional + information. At implemention some limitations may exist about + hardware and software resources. So implementation level is + indicated in the following form: + + _KISS/GSn ( n = 1,2,3,... )_ + + (-> 7 KISS/GS Ranks) + + 3. _Basic Concepts_ + + _ 3-1:_ _KISS Functions_ + KISS is a image viewer program with transparency + processing. It is able to display overlapped pictures and + allow the user to manipulate them with real-time mouse + operation. + + _3-2: _ _Files_ + KISS needs the following files. + + o Cel file + Image data to be moved. An array of pixels. Pixel code 0 + is transparent pixel. + o Palette file + Defines actual colors of pixels. + o Configuration file + Describes the overlapping order and positions of cels, + etc. KISS reads this first and refers it to read other + files. This file is a text file created with a text + editor. Some parts of it may be changed by KISS + program's save function. + + _3-3: _ _Technical terms_ + + o Cel + A minimum element of pictures. + o Object + A unit of pictures for moving; composed of one or more + cels. + o Palette group + Color information of one screen. + o Set + Data composed of a palette group and object positions. + 4. _ GS-KISS New Feature _ + + _4-1: _ _Multipalette _ + Before KISS/GS, all cels are drawn according to a single + palette table in the palette file. Now, cels can be drawn + with individual palette tables. + + The total number of colors must be less than or equal to + 256. + + Each cel requires information about which palette it + uses. + + 5. _ Details of the configuration file _ + + Each line must be shorter than 256 bytes. + + Palette/cel filenames are composed of the basename (max 8 bytes) + + the suffix (max 3 bytes). Upper and lower cases are identical. The + character set used in filenames is [_0-9a-z]. + + The character at the top of each line is one of the following: + + _ '='_ _Memory size _ + + Description: =K + + For KISS v1.0 compatibility. KISS v2.0 or later ignores it. + Its use is discouraged. + + Example: + +| +|=260K +| + + + _'('_ _ Screen size_ + + Description: (, ) + + Defines the screen size. + If omitted, (448,320) is assumed for KISS v2.18 + compatibility. Maximum size of screen is (640,400) on + KISS/GS2. (-> 7 KISS/GS Ranks) + + Example: + +| +|(640,400) +| + + + _'%'_ _Palette file_ + + Description: % + + Describes a palette file. Palette files are numbered as + 0,1,2... in the order of appearance. + + All colors in the palette file #0 are used. But the first + (transparent) color in the other palette files is ignored. + Total number of colors must be less than or equal to 256. + + All palette files must be described before description about + cel files. + + Example: + + +| +|%COL.KCF +|%COL2.KCF +| + + + _'['_ _ Border color_ + + Description: [ + + Outside of the screen is filled with this pixel code. + Example: + + +| +|[12 +| + + + _'#'_ _ Cel file_ + + Description: #. [* ] [: ...] + + : + Identification number to specify object. Cels of + the same Mark are unified and make an object. + Object number is from 0 to 255 on KISS/GS2. (->7 + KISS/GS Ranks) + + : + Fixed value. Specify this for fixed objects such as + the doll's body. An object with a big value is hard + to move. Value is a number from 0 to 32767. If + omitted, treated as 0 (not fixed). + + : + Describes the filename with suffix. + + : + Indicates which palette file this cel uses. If + omitted, treated as 0. + + : + The cel is drawn only in the sets specified here. 0 + - 9 is available. If omitted, this cel is drawn in + all sets. The order of cel file descriptions + determines the priority in drawing cels. The number + of cels is max 256. (- >7 KISS/GS Ranks) + + Example: + + +| +|#2 data1.cel ; forward (near) +|#3 data2.cel :2 3 4 ; +|#4.255 data3.cel ; fixed +|#5 data4.cel *1 :5 ; +|#2 data1_.cel ; backward (far) +| + + data1.cel and data1_.cel make one object. + + + _'$'_ _ Set information_ + + Description: $ [ ...] + + Palette group and positions of object for each set. There are + max 10 sets. This section can be overwritten by KISS save + function. + + A long description is folded, and the following lines start + with a ' ' (blank) character to indicate that the lines are + continued from the previous line. + + : + Palette group number. 0 ... 9. + + : + Position of object (from object mark 0). Max 256 + positions are described on KISS/GS2. (- >7 KISS/GS + Ranks) '*' means a non-existent object. + + Example: + + +| +|$2 192,11 * 56,176 55,21 259,62 15,24 375,63 +|$3 43,115 154,62 372,108 253,156 * * * 165,207 +| * 162,198 * 119,56 152,44 * * * +| 16,355 394,362 108,355 * * * 125,261 +|$0 192,11 * 56,176 55,21 259,62 15,24 375,63 +| + + + _';'_ _ Comment_ + + Description: ; + + This line is ignored. + + Future extension may determine how to include various + information of the data (title, author etc.) as comments. + + + Others + + Reserved for extention. + + 6. _ Details of cel files _ + + Cel files have a 32-byte header. + + +offset size contents ++0 4B Identifier 'KiSS' ( 4Bh 69h 53h 53h ) ++4 B Cel file mark ( 20h ) ++5 B bits per pixel ( 4 or 8 ) ++6 W Reserved ++8 W(L,H) Width ( 1 ... XMAX ) ++10 W(L,H) Height ( 1 ... YMAX ) ++12 W(L,H) x-offset ( 0 ... XMAX-1 ) ++14 W(L,H) y-offset ( 0 ... YMAX-1 ) ++16 16B Reserved + + Caution: the reserved field must be filled with 0. + + Cels of the same object are aligned at the top left corner. + X,y-offsets are the offsets from this alignment point. + + +32... _Pixel data_ + + + Pixel data order (4 bits/pixel) + + One raster: + + +|| || || +MSB LSB MSB LSB MSB LSB + +| pix0 | pix1 | | pix2 | pix3 | | pix4 | pix5 | ......... | pixN | + + If the width is odd, add a padding pixel of color 0. The number + of rasters is indicated in the height field. + + + Pixel data order (8 bits/pixel) + + One raster: + + +|| || || +MSB LSB MSB LSB MSB LSB + +| pix0 | | pix1 | | pix2 | ... | pixN | + + The number of rasters is indicated in the height field. + + + If the top 4-byte identifier is not 'KiSS', the file format is as + follows: + + ++0 W(L,H) Width ++2 W(L,H) Height ++4... Pixel data + + 4 bits/pixel. X and y-offset are 0. This is the conventional format. + + 7. _Palette file detail _ + + Palette files have a 32-byte header. + + +offset size contents ++0 4B Identifier 'KiSS' ( 4Bh 69h 53h 53h ) ++4 B Palette file mark ( 10h ) ++5 B bits per color ( 12 or 24 ) ++6 W Reserved ++8 W(L,H) number of colors in one palette group ( 1 ... 256 ) ++10 W(L,H) number of palette groups ( 1 ... 10 ) ++12 W Reserved ++14 W Reserved ++16 16B Reserved + + Caution: the reserved fields must be filled with 0. + + +32... _Palette data_ + + + Palette data order (12 bits = 4096 colors) + + A color consists of 2 bytes. 4 bits each for red, green, + blue. + + +|| || +MSB LSB MSB LSB + +| rrrr | bbbb | | 0000 | gggg | .... + + + Palette data order (24 bit = 16,777,216 colors) A color + consists of 3 bytes. 8 bits each for red, green, blue. + + +|| || || +MSB LSB MSB LSB MSB LSB + +| rrrrrrrr | | gggggggg | | bbbbbbbb | ... + + If the number of palette groups is less than 10, colors of the + remaining palette groups will be copied from Group 0. + + If the top 4-byte identifier is not 'KiSS', the file format is as + follows: + + +0... palette data + + 12 bits/color, 16 colors in a palette group, 10 groups. This is + the conventional format. + + 8. _ KISS/GS Ranks _ + + +Rank size colors max cels +--------------- ---------- ---- ---------- + KISS/GS1 640 x 400 16 128 ; KISS v2.24c + KISS/GS2 640 x 400 256 256 ; KISS v2.37 + KISS/GS3 768 x 480 256 256 ; draft + KISS/GS4 768 x 480 256 512 ; draft +--------------- ---------- ---- ---------- + + These are just standards. When you implement a KISS program on your + system, you should support the maximum ability of the hardware. + When you create KISS data you are encouraged to consider these + ranks. The lower rank the data conforms to, the more users can + play with it. However, you don't have to conform it to + unnecessarily low ranks. + + 9. _ Appendix _ + + This document is in public domain. Send bug reports, questions, + comments and problems to _ UHD98984@pcvan.or.jp _ (yav). Thank + you. + + + _____________________________________________________________ + + _ ITO Takayuki + Graduate student, Department of Information Science, + Faculty of Science, University of Tokyo, Japan. + _ + diff --git a/Models/DirectoryModel.cs b/Models/DirectoryModel.cs new file mode 100644 index 0000000..f7c68dc --- /dev/null +++ b/Models/DirectoryModel.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace fxl.codes.kisekae.Models +{ + public class DirectoryModel + { + public string Name { get; } + + public DirectoryModel(string name) + { + Name = name; + } + + public List Configurations { get; } = new(); + } + + public class ConfigurationModel + { + public string Name { get; } + + public ConfigurationModel(string name) + { + Name = name; + } + } +} \ No newline at end of file diff --git a/Models/PaletteModel.cs b/Models/PaletteModel.cs index 64ffc44..2861093 100644 --- a/Models/PaletteModel.cs +++ b/Models/PaletteModel.cs @@ -5,9 +5,6 @@ namespace fxl.codes.kisekae.Models public class PaletteModel { private const string Regex = "%([a-zA-Z0-9\\-]*\\.[kKcCfF]+)[\\s]*;(.*)"; - - public string FileName { get; } - public string Comment { get; } public PaletteModel(string line) { @@ -17,7 +14,7 @@ namespace fxl.codes.kisekae.Models foreach (var group in matcher.GetGroupNames()) { if (group == "0") continue; - + match.Groups.TryGetValue(group, out var value); if (string.IsNullOrEmpty(value?.Value)) continue; @@ -32,5 +29,29 @@ namespace fxl.codes.kisekae.Models } } } + + public string FileName { get; } + public string Comment { get; } + + public Color[] Colors { get; private set; } + + public void ParseColors(byte[] bytes, int depth) + { + Colors = new Color[0]; + } + } + + public class Color + { + public Color(int red, int green, int blue) + { + Red = red; + Green = green; + Blue = blue; + } + + public int Red { get; } + public int Green { get; } + public int Blue { get; } } } \ No newline at end of file diff --git a/Models/ConfigurationModel.cs b/Models/PlaysetModel.cs similarity index 54% rename from Models/ConfigurationModel.cs rename to Models/PlaysetModel.cs index 60cae5f..917195e 100644 --- a/Models/ConfigurationModel.cs +++ b/Models/PlaysetModel.cs @@ -2,20 +2,23 @@ using System.Collections.Generic; namespace fxl.codes.kisekae.Models { - public class ConfigurationModel + public class PlaysetModel { - private readonly string _originalDirectory; - - public ConfigurationModel(string originalDirectory) - { - _originalDirectory = originalDirectory; - } - public int Height { get; set; } public int Width { get; set; } public int BorderColorIndex { get; set; } public List Palettes { get; } = new(); public List Cels { get; } = new(); + public int[] CurrentPalettes = new int[10]; + + public void Reset() + { + foreach (var cel in Cels) + { + cel.CurrentPositions = cel.InitialPositions; + cel.CurrentPaletteId = cel.PaletteId; + } + } } } \ No newline at end of file diff --git a/Models/Point.cs b/Models/Point.cs index 9b956b3..a16eb95 100644 --- a/Models/Point.cs +++ b/Models/Point.cs @@ -2,6 +2,12 @@ namespace fxl.codes.kisekae.Models { public class Point { + public Point(int x, int y) + { + X = x; + Y = y; + } + public int X { get; set; } public int Y { get; set; } } diff --git a/Scripts/main.ts b/Scripts/main.ts index e69de29..0c04366 100644 --- a/Scripts/main.ts +++ b/Scripts/main.ts @@ -0,0 +1,46 @@ +import { MDCTopAppBar } from '@material/top-app-bar' + +declare global { + interface Document { + kisekae: Main + } +} + +export default class Main { + appBar: MDCTopAppBar + constructor() { + this.appBar = MDCTopAppBar.attachTo(document.querySelector(".mdc-top-app-bar")) + + this.init() + } + + init() { + let main = document.querySelector("main") + let directories = main.querySelector("ul") + let links = directories.querySelectorAll("a") + + links.forEach(link => { + link.addEventListener("click", () => { + let directory = link.attributes.getNamedItem("data-directory") + let form = document.createElement("form") + + let method = document.createAttribute("method") + method.value = "post" + let action = document.createAttribute("action") + action.value = "/Home/Select" + + form.attributes.setNamedItem(method) + form.attributes.setNamedItem(action) + + form.innerHTML = `` + + `` + + link.appendChild(form) + + form.submit() + }) + }) + } +} + +document.kisekae = new Main() \ No newline at end of file diff --git a/Services/ConfigurationReaderService.cs b/Services/ConfigurationReaderService.cs index 9d1981f..8da6ce4 100644 --- a/Services/ConfigurationReaderService.cs +++ b/Services/ConfigurationReaderService.cs @@ -1,4 +1,7 @@ +using System; using System.IO; +using System.Linq; +using System.Text; using System.Text.RegularExpressions; using fxl.codes.kisekae.Models; using Microsoft.AspNetCore.Http; @@ -9,19 +12,26 @@ namespace fxl.codes.kisekae.Services public class ConfigurationReaderService { private readonly ILogger _logger; + private readonly FileParserService _fileParser; - public ConfigurationReaderService(ILogger logger) + public ConfigurationReaderService(ILogger logger, FileParserService fileParser) { _logger = logger; + _fileParser = fileParser; } - public ConfigurationModel ReadCnf(IFormFile file) + public PlaysetModel ReadCnf(IFormFile file) { _logger.LogTrace($"Reading filename {file.FileName}"); + return ParseStream(file.OpenReadStream()); + } - var model = new ConfigurationModel(""); - - using var reader = new StreamReader(file.OpenReadStream()); + public PlaysetModel ParseStream(Stream fileStream, string directory = null) + { + var model = new PlaysetModel(); + var initialPositions = new StringBuilder(); + + using var reader = new StreamReader(fileStream); while (!reader.EndOfStream) { var line = reader.ReadLine(); @@ -44,10 +54,45 @@ namespace fxl.codes.kisekae.Services case '#': model.Cels.Add(new CelModel(line)); break; + case '$': + case ' ': + initialPositions.Append(line.Replace("\\r\\n", "").Replace("\\n", "")); + break; } } + + SetInitialPositions(model, initialPositions.ToString()); + model.Reset(); + + if (string.IsNullOrEmpty(directory)) return model; + + foreach (var palette in model.Palettes) + { + _fileParser.ParsePalette(directory, palette); + } return model; } + + private static void SetInitialPositions(PlaysetModel model, string positions) + { + var sets = positions.Split('$', StringSplitOptions.RemoveEmptyEntries); + for (var index = 0; index < sets.Length; index++) + { + var value = sets[index].Split(' ', StringSplitOptions.RemoveEmptyEntries); + model.CurrentPalettes[index] = int.Parse(value[0]); + + for (var innerIndex = 1; innerIndex < value.Length; innerIndex++) + { + if (value[innerIndex] == "*") continue; + var point = value[innerIndex].Split(',', StringSplitOptions.RemoveEmptyEntries); + + foreach (var cel in model.Cels.Where(x => x.Id == innerIndex - 1)) + { + cel.InitialPositions[index] = new Point(int.Parse(point[0]), int.Parse(point[1])); + } + } + } + } } } \ No newline at end of file diff --git a/Services/FileParserService.cs b/Services/FileParserService.cs new file mode 100644 index 0000000..f24e79a --- /dev/null +++ b/Services/FileParserService.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using System.IO.IsolatedStorage; +using System.Linq; +using System.Text; +using fxl.codes.kisekae.Models; +using Microsoft.Extensions.Logging; + +namespace fxl.codes.kisekae.Services +{ + public class FileParserService + { + private readonly ILogger _logger; + private readonly IsolatedStorageFile _storage; + + public FileParserService(ILogger logger) + { + _logger = logger; + _storage = IsolatedStorageFile.GetUserStoreForApplication(); + } + + public void ParsePalette(string directory, PaletteModel palette) + { + _logger.LogTrace($"Reading palette {palette.FileName} from {directory}"); + using var stream = _storage.OpenFile(Path.Combine(directory, palette.FileName), FileMode.Open); + if (!stream.CanRead) throw new InvalidDataException(); + + var buffer = new byte[stream.Length]; + stream.Read(buffer, 0, buffer.Length); + + var header = Encoding.ASCII.GetBytes("KiSS"); + if (buffer[..header.Length].SequenceEqual(header)) + { + // Matching header I guess? + } + } + } +} \ No newline at end of file diff --git a/Startup.cs b/Startup.cs index 6428811..049445b 100644 --- a/Startup.cs +++ b/Startup.cs @@ -23,6 +23,7 @@ namespace fxl.codes.kisekae .AddRazorRuntimeCompilation(); services.AddSingleton(); + services.AddSingleton(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/Styles/main.scss b/Styles/main.scss index 1843faf..6b73d9c 100644 --- a/Styles/main.scss +++ b/Styles/main.scss @@ -6,7 +6,7 @@ $fxl-orange: #ff6e40; $on-primary: $fxl-gray ); -@use "@material/icon-button"; +@use "@material/icon-button/icon-button"; @use "@material/top-app-bar/mdc-top-app-bar"; @use "@material/typography/mdc-typography"; @@ -17,7 +17,19 @@ html, body { } body { + @include icon-button.core-styles; + + display: flex; + flex-direction: column; + + main { + display: flex; + flex: 1; + flex-direction: column; + } + footer { font-size: smaller; + text-align: center; } } \ No newline at end of file diff --git a/Views/Home/Index.cshtml b/Views/Home/Index.cshtml index d561f08..7360216 100644 --- a/Views/Home/Index.cshtml +++ b/Views/Home/Index.cshtml @@ -1,8 +1,27 @@ -@{ - ViewData["Title"] = "Home Page"; +@model IEnumerable + +@{ + ViewData["Title"] = "Select"; } -
+ -
\ No newline at end of file + + +
    + @foreach (var directory in Model) + { +
  • + @directory.Name +
      + @foreach (var config in directory.Configurations) + { +
    • + @config.Name +
    • + } +
    +
  • + } +
\ No newline at end of file diff --git a/Views/Home/Play.cshtml b/Views/Home/Play.cshtml new file mode 100644 index 0000000..3c19b7d --- /dev/null +++ b/Views/Home/Play.cshtml @@ -0,0 +1,10 @@ +@model PlaysetModel + +@{ + ViewBag.Title = "Play"; + Layout = "_Layout"; +} + +
+@Json.Serialize(Model)
+
\ No newline at end of file diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml index 0106385..9bb6a2b 100644 --- a/Views/Shared/_Layout.cshtml +++ b/Views/Shared/_Layout.cshtml @@ -14,12 +14,13 @@
- @ViewData["Title"] + Kisekae Online - @ViewData["Title"]