organized as client/server, started uxn sprite stuff

This commit is contained in:
Iris Lightshard 2021-08-11 14:14:53 -06:00
parent e85bf2c4e5
commit c35d47c8b8
Signed by: Iris Lightshard
GPG key ID: 3B7FBC22144E6398
29 changed files with 200 additions and 3 deletions

6
.gitignore vendored
View file

@ -1,3 +1,3 @@
*.o
xrxs
carts/*/realms/
server/*.o
server/xrxs
uxn-client/xrxs.rom

8
server/LICENSE Normal file
View file

@ -0,0 +1,8 @@
Copyright 2021 Derek Stevens
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

81
server/README.md Normal file
View file

@ -0,0 +1,81 @@
# xrxs
`xrxs` is an experimental game server using the Plan 9 protocol `9p`.
The client is intended to be a specialized [uxn](https://wiki.xxiivv.com/site/uxn.html) ROM that can load other ROMs (possibly preserving its own code to maintain a common menu system or interface to `xrxs`).
## design
This is the working structure of the 9p filesystem:
* `/ctl`: Read/write control file for inputing system commands. Reading the file shows the status of the last input command: 1 for success, 0 for failure; `logout` is a special case, and the status code will be -1 if it was succesful. the following are valid command syntax:
* `login PW`: Authenticate with `xrxs` -- password is hashed against realm password hash.
* `logout`: Gracefully remove yourself from the users table.
* `load CART`: Load a cartridge.
* `chunk TYPE N`: Load data of type TYPE and chunk number N.
* `create REALM`: Create a new realm (start a new game) -- must have a cartridge loaded
* `protect PW`: Protect the curent realm with a password if you are the master.
* `transfer USER`: Transfer ownership of the realm to another user.
* `delete REALM`: Delete the realm off the server if you are the master and it is empty.
* `enter REALM`: Join an existing realm.
* `leave`: Leave the current realm.
* `unload`: Unload the cartridge.
* `/users`: Read-only; Self and others in the realm are readable from here, one per line. It contains only yourself before joining a realm. Your username on your machine is used as your username in `xrxs` -- if your name is taken, you will get an error on attaching.
* `/carts`: Available game/app cartridges for this server, read only; Carts are listed per line upon reading the file. It is backed by files on the server in a directory structure like `carts/CART_NAME/{CART_NAME.rom, data/, realms/}`.
* `/slot`: After loading the cartridge, its ROM is read from here; Read-only.
* `/data/`: Any supporting data that comes with the cartridge will be found here; They are in three parts: `sprite`, `audio`, and `text`. Because `uxn` is limited to 64-128kb input files, the filesizes of these data blobs should be 64kb max, and the `chunk` command should be used to page different files into the service when needed. The files on the server should be like `TYPEN` where `TYPE` is one of `sprite`, `audio`, and `text`, and `N` is any sequence of characters (canonically a nonnegative integer). When first loading the cartridge, `N == 0`. Issuing the command `chunk TYPE XXX` will attempt to load data from file `carts/CART_NAME/data/TYPEXXX` into the correct data file. If `TYPE` is not one of `sprite`, `audio`, or `text`, or the ifle `TYPEXXX` doesn't exist in the data directory, the `chunk` command does nothing.
* `/realms`: Open/saved realms, read-only. Realms and their associated universe are backed by real files on the server so that they can be preserved across service instantiations, in a directory structure like: `carts/CART_NAME/realms/REALM_NAME/{realm, universe}`. Realms can either be solo, open, or protected; Open or protected realms can have limited member numbers. Depending on the cartridge, these settings can be user-managed or managed by the cartridge itself. Realms are listed per line upon reading the file like: `REALM_NAME 1 4 1`. First would obviously be the name of the realm. The first number is number of members, second is member limit, third is 1 if protected, 0 if not. `0 1 1` represents a protected solo realm that is empty (saved game with password). `0 1 0` represents an unprotected solo realm that is empty (saved game with no password).
* `/universe`: Write here to update serverside state for this cart/realm; Read from here to get the complete current state. This is backed by a key-value-pair list on the server.
* `/scope`: Write here to tell the server the names of the `Atom`s (key/value pair of a `Universe`) you're interested in (one per line), and read from here to retrieve their values (one per line). In many cases this will be preferrable to fetching the entire `Universe`.
* `/random`: Read-only, get a random number from 0 to 99.
* `/grandom`: Read-only, get a random number from 0 to 99 -- These are doled out on a per-realm basis, and the number stays the same until everyone in the realm has had a chance to read it. If you've already read it this round or aren't in a realm, it will be empty.
### realm format
Each realm directory on the server should have the following files:
* `realm`: Basic data for the realm, file should contain only the maximum number of members, the master's name, and the password hash, if any (otherwise 0), separated by spaces.
* `universe`: The actual game state for the realm as key value pairs, one per line, like `KEY = VALUE`; limit 15 characters for keys, 63 for values.
The realm should be synchronized to disc when realm membership, limit, or password change. Fenagling some periodic autosave should be possible...
## configuration
`config.h` in the source contains the following configuration macros:
* `MAX_USERS`: the maximum number of simultaneous users able to attach to the `xrxs` service
* `DATA_DIR`: the path to the root of the cartridge and realm storage; can be absolute or relative to the `xrxs` executable, but must have the trailing `/`
## build/run
`xrxs` is built/tested in a Linux environment with `plan9port` and the C standard library as the only dependencies. With minimal modifications it will probably run just as well on Plan9, *BSD, WSL, and MacOS.
Running `./build.sh` from the repository root should build the `xrxs` executable.
You can run a local server (for testing, split-screen games, or single-player games) with:
```
./xrxs -m /path/to/mountpoint
```
or expose a service on the network (uses `9pserve` to support multiple users and gracefully handle disconnects) with:
```
./xrxs-srv.sh start
```
Similarly, you can stop the service with:
```
./xrxs-srv.sh stop
```

View file

View file

View file

@ -0,0 +1 @@
4 0

View file

BIN
uxn-client/test.chr Normal file

Binary file not shown.

BIN
uxn-client/xrxs.chr Normal file

Binary file not shown.

BIN
uxn-client/xrxs.rom Normal file

Binary file not shown.

107
uxn-client/xrxs.tal Normal file
View file

@ -0,0 +1,107 @@
( utility macros )
%+ { ADD } %- { SUB } %* { MUL } %/ { DIV }
%< { LTH } %> { GTH } %= { EQU } %! { NEQ }
%++ { ADD2 } %-- { SUB2 } %** { MUL2 } %// { DIV2 }
%<< { LTH2 } %>> { GTH2 } %== { EQU2 } %!! { NEQ2 }
%INC-X { .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 } ( -- )
%INC-Y { .Screen/y DEI2 #0008 ADD2 .Screen/y DEO2 } ( -- )
%CENTER-X { .Screen/width DEI2 #01 SFT2 }
%CENTER-Y { .Screen/height DEI2 #01 SFT2 }
%MOD { DIVk MUL SUB }
%MOD2 { DIV2k MUL2 SUB2 }
%NEXT-TILE { DUP2 #0010 ADD2 }
%DEBUG { ;print-hex JSR2 #0a .Console/write DEO }
%DEBUG2 { SWP ;print-hex JSR2 ;print-hex JSR2 #0a .Console/write DEO }
%RTN { JMP2r }
( devices )
|00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 ]
|10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|30 @Audio0 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|40 @Audio1 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|50 @Audio2 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|60 @Audio3 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|80 @Controller [ &vector $2 &button $1 &key $1 ]
|90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ]
|a0 @File [ &vector $2 &success $2 &offset $2 &pad $2 &name $2 &length $2 &load $2 &save $2 ]
|b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ]
( variables )
|0000
@state $1
@cart $64
@realm $64
( program )
|0100 ( -> )
( theme )
#02c1 .System/r DEO2
#02cd .System/g DEO2
#02cb .System/b DEO2
;spritesheet .File/name DEO2
#0100 .File/length DEO2
#0000 .File/offset DEO2
;uxnlogo .File/load DEO2
#0200 .File/offset DEO2
;xrxslogo .File/load DEO2
;draw-uxn-logo JSR2
;draw-xrxs-logo JSR2
BRK
@draw-uxn-logo ( -> )
CENTER-X #0020 SUB2 .Screen/x DEO2
CENTER-Y #0010 SUB2 .Screen/y DEO2
#0100 #0000 &while EQU2k ,&end JCN
DUP2 ;uxnlogo ADD2 .Screen/addr DEO2
#81 .Screen/sprite DEO INC-X
NEXT-TILE #0040 MOD2 #0000 NEQ2 ,&no-inc-y JCN
CENTER-X #0020 SUB2 .Screen/x DEO2
INC-Y
&no-inc-y
#0010 ADD2 ,&while JMP &end POP2 POP2
RTN
@draw-xrxs-logo ( -> )
CENTER-X .Screen/x DEO2
CENTER-Y #0010 SUB2 .Screen/y DEO2
#0100 #0000 &while EQU2k ,&end JCN
DUP2 ;xrxslogo ADD2 .Screen/addr DEO2
#81 .Screen/sprite DEO INC-X
NEXT-TILE #0040 MOD2 #0000 NEQ2 ,&no-inc-y JCN
CENTER-X .Screen/x DEO2
INC-Y
&no-inc-y
#0010 ADD2 ,&while JMP &end POP2 POP2
RTN
( constants )
@spritesheet "xrxs.chr 00
( sprites )
@uxnlogo $128
@xrxslogo $128