Login
Usagyuuun Kniffel
Title:Usagyuuun Kniffel
Category:Game/Dices
Release Date:
Language:English/German/Spanish
Size:64K
Device Req.:Disk only (1 side)
Machine:PAL & NTSC
Code Type:Basic + Machine code
Distribution:Freeware
 Play Online!
Code by:Sirhadisen
Notes:AKA Usagikniffel. A multiplayer dice game for everyone who likes BASIC, machine code, and rabbits!
User Rating: 7.3/10 (3 votes)
User comments: Read comments
Usagyuuun Kniffel Title Screenshot

Usagyuuun Kniffel Screenshot


HVTC
USA, USA, USAGyuuun 8bit


Description
---------------------------------
*** USAGIKNIFFEL ***
FAN-GAME BY (private)
23.02.2023
(YEAR OF THE BUNNY)
SEINEM KOMISCHEN TIER GEWIDMET
INSPIRED BY QUAN INC.
USING TEDZAKKER 1.1 BY HERMIT
ASSEMBLERCODE RANGES:
$0333-03F2 IRQ EXT. ACCESS STUBS
$A4FF-B431 ANIMATIONS & MUSIC
---------------------------------


How to run the game
-------------------
1. Get a commodore emulator
2. Mount the disk image
3. Load the loader by typing DLOAD "LOADER" + Enter
4. Type RUN + Enter (this takes a while because it keeps the interactive mode intact)
5. Choose language, number of players, and player names of at least 2 characters each
6. Pick the dices you want to re-roll by pressing their numbers (1-5) and confirm with enter
7. After last roll, pick an unused combination from the scoreboard with arrow up/down and confirm with enter.

The top10 sequence file can be deleted to start over with an empty hall of fame. Good luck and have fun!


Here for the coders
-------------------
Beware of the run/stop button that ends the program and enters the interactive BASIC 3.5 mode. So do not press it accidentally or it will break your lucky streak ;) It was left enabled intentionally, because interrupting the game allows you to play around with the effect assembler routines, or check out and customize the commented BASIC code. Since the player variables are currently not persisted in memory, however, you won't be able to continue the game where you left it. This would be an extension worth considering.

Some commented-out GOSUB 10000 statements were left in the code. Removing the REM in front of them makes it possible to start the program in that line, which can be used to test the post-game subroutines with fake player scores.

Note that the code is self-changing at some locations, such as the STA statements during music initialization at $A96F and $A9B1 that toggle $ABF7 between RTS and JMP. This seems to cause issues if the music routine is saved in a state after having executed the initialization, probably because of misplaced RTS returns inside the IRQ-extension.

Happy retro-coding my fellow Gyuuuns!


Planned for the next release
----------------------------
- Music for the award ceremony (I tend to "Es gibt Reis" by Helge Schneider)
- Balancing of speed control between animations and music
- Let user pick color themes on the start screen that affect the entire game
- More easter eggs


Credits
-------
- Programmed in the emulator plus4emu 1.2.9.1 by Istvan Varga
- Theme inspired by Quan Inc.'s cuddlesome Usagyuuun
- Music is an 8-bit cover of Oh!YOU's splendid song
- To generate and play the song I use the TEDzakker 1.1 by Hermit (SIDRIP)
- To keep track of the code I used a Notepad in Windows (yes, I cheated)


It all began with an 8bit carrot.
---------------------------------
o
o
oooo
ooo
oooo
oooo
ooo
ooo
o
---------------------------------


Program Analysis
Name_of_Variable;Definition
A$;Temporary key
AA;Temporary key number/rank number
AR$;Active assembly routine
AS;Decimal-coded occurrence of faces in a dice roll
AUGE;Face integer cache
AUGE$;Face character cache
AVA;Avatar index per player
BF$;Pattern flag cache
BW;Language index or pattern index - 1
BS;Counter of distinguishable faces in a dice roll
C$;Temporary string with character-coded colors
C0;Score board first column number - 1
C1;Rain start column index for 1st place
C2;Rain start column index for 2nd place
CC;Continuation character number
CC$;Character-string for faces 1-6
CO$;Reference character (temporary)
CS;Carrot speed increment
CT;Color theme index
CV;Temporary color cache
FLAGS$;Flags locked patterns per player
JA$;Language-specific character for choice "yes"
HI;Temporary High-Byte
L;Temporary lenth of a string
LO:Temporary Low-Byte
MC;Direction of cursor in menue
MN;Size of largest face multiplet
NV$;Temporary array for vertical names (awards ceremony)
OSET;Offset of rows for printing of dice result
P;Page index of the custom character set
PALL;Accumulators for total score per player
PBM;Score per pattern & player
PT;Temporary cache for score
Q$;Quotation marks
R;Round index
R0;Index of 1st row for printing avatars
R1;Scoretafel 1.Zeile
RANKS;For sorting of player scores
RC$;String cache
RK$;String cache
RS$;Speech bubble graphic
S;Player index
S1;Temporary total score 1
S2;Temporary total score 2
SA;Number of players
SC;Temporary score of current round
SF$;Array with character colors of player names
SNAME$;Array of player names
SO;Sum for 1s to 6s
SP;Usagyuuun response index
TS;Array cache of top 10 scores
TN$;Array cache of top 10 names
US$;Usagyuuun responses
UU$;Usagyuuun PETSCII graphic
V;Counter of current roll
WCN;Counter per face in current roll
WDH;Numeric flags for dices chosen to be rerolled
WE;Index of a dice that was chosen to be rerolled
WI;Like WE
WURF$;Character cache of current roll
X;Temporary variable for various things

23.02.2023

Organisation of the Assembly Routines
-------------------------------------
For parallel utilization of interruptable BASIC 3.5 and assembly codes in the bank-switching-RAM region of the Commodore Plus/4, the game is stored in three separate memory regions:
1) Toggle and access-stubs within the tape buffer (pure RAM from $0333-$03F2) enable flexible activation/deactivation of IRQ-extension from the interactive BASIC mode (using SYS statements); note that this code is wiped by a soft reset.
2) Interruptable BASIC 3.5 program (starting at $1000); note that this code is wiped by a soft reset.
3) Initialization routines, animations, and musik (incl. player) are saved in the bank-switching-RAM region from $A4FF-$B431; note that in order to view&edit the assembly code in this region from the MONITOR, one has to switch $07F8 "MSB for monitor fetches from ROM=0;RAM=1", e.g. with the statement POKE 2040, 128. This code remains in memory after a soft reset.

*** 1) Routines in the tape buffer ***
$0333-$0355 General bank-switching-independent initialization and toggle of the IRQ RAM vector between $CE0E and $0357
$0357-$037D Universal RAM-access stub, which IRQ detour address (JSR $#### statement) must have been set in advance
$037F-$039F Start screen-specific initialization (music, color circle addresses, IRQ-detour address & -toggle)
$03A1-$03BE Player name query-specific initialization (color box addresses, IRQ-detour address & -toggle)
$03C0-$03CF Award ceremony-specific initialization (IRQ-detour address & -toggle)
$03D1-$03D6 Unspecific initialization (just toggling the IRQ-detour, which address must have been set in advance)

*** 2) Routines in the bank-switching-RAM ***
$A4FF-$A518 Start screen: IRQ main
$A519-$A563 Rain routine: Create new drops
$A564-$A5DA Rain routine: Move & eliminate drops
$A5DB-$A619 Color circle: Change colors within periodic region boundaries
$A61A-$A69F Color circle: Persistent storage of circle addresses as (Low-Byte, High-Byte)-pairs
$A6A0-$A6AE Player name query: IRQ main
$A6B0-$A6E4 Award ceremony: IRQ main
$A6E8-$A6F2 Rain routine: Memorize symbol and color attribute of drop X
$A6F4-$A6FE Rain routine: Retrieve symbol and color attribute of drop X and cache in $DF and $E4
$A700-$A70D Simple pseudo-random number generator
$A70F-$A737 Start screen: Oscillating brightness of Usagyuuun lettering
$A73C-$A755 Set all TED color attributes to grey
$A757-$A765 Kniffel interlude: IRQ main
$A767-$A78F Kniffel interlude: Color flickering of Kniffel lettering
$A794-$A79A Hall of fame: IRQ main
$A79C-$A7DC Hall of fame: Color flickering of top 10 score board
$A7DE-$A7EB Start screen: Initialize addresses that define the color circle
$A7ED-$A7FA Player name query: Initialize addresses that define the box frame


Reserved memory and required initialization of values before IRQ-toggles
------------------------------------------------------------------------
Some parameters of the animations are initialized/modified from BASIC with POKE statements, some are initialized by other assembly routines. Usagyuuun deserves some chaos after all.

1) Start screen
General:
$D3 reserved for slowing counter of animation routines
$D6-$D7 reserved for indirectly indexed addressing by the music routine
$DD reserved for slowing counter of the music routine

Rain routine (sorry, no sprites for the Plus4!):
$D8-$D9 reserved for indirectly indexed addressing of TED attributes
$DA-$DB reserved for indirectly indexed addressing of TED characters
$DC max. number of drops >0 and <16 (z.B. 6) - do not change while routine is running!
$DE reset value of the slowing counter; must be >0 (uneven numbers like 7 seem to produce better RNG results)
$DF symbol for new rain drops (e.g. the carrot uses #$66, the $ character can be set with poke 223, 36)
$E0 random seed (z.B. 123)
$E4 color attribute of rain drops (e.g. the carrot uses #$43, the $ character uses gold = #$48),
also used as a switch which value #$00 indicates that the RAM-access stub is to be executed only once
$E6 Byte-frame for "double width - 1" of the region in which rain drops fall (e.g. #$1F for start screen, #$0F for avatars in the award ceremony)
$E7-$E8 Low byte, high byte of the origin position of the region in which rain drops fall (e.g. #$73, #$0D)
$0662-$0671 cache for low-bytes of positions of rain drops = TED-address ("Charpointer")
$0672-$0681 cache for high-bytes of positions of rain drops = TED-address ("Charpointer")
$0682-$0691 cache for chars to be restored behind rain drops as they move
$0692-$06A1 cache for attriutes of chars to be restored behind rain drops as they move
$06A2-$06B1 cache for symbol per rain drop (they differ between 1st and 2nd place)
$06B2-$06C1 cache for basis color per rain drop (drops change brightness as they fall)

Color circle / box frame:
Y-register starts at #$00
$E1-$E2 reserved for holding addresses of color attributes accessed by indirectly indexed addressing
? Clarify: Should E1 E2 be used instead of D6 D7 for the music routine?
$E3 has been set to default color (e.g. #$67 for start screen)
$E4 has been set to basis color (lowest brightness) of the rotating stream in the color circle (e.g. #$50 for the start screen)
$E5 reserved for double number of addresses that define the color circle
$A61C-$A64F reserved for cache of rotating address bytes of the color circle

2) Player name query
$DD reserved for slowing counter of the music routine
$DE reset value of the slowing counter; must be >0 (uneven numbers like 7 seem to produce better RNG results)
$E5 reserved for double number of addresses that define the color box

3) Kniffel interlude
$DD reserved for slowing counter of the music routine
$DE reset value of the slowing counter; must be >0 (uneven numbers like 7 seem to produce better RNG results)
$036F-$0370 the jump address in the RAM-access stub needs to be set to $A757 from BASIC using POKE statements
The attribute column ($0991, $09B9, $09E1, $0A09, $0A31) must hold colors greater 0 as a seed for the flickering

4) Award ceremony
$DC max. number of drops >0 and <16 (e.g. 6)
$DD reserved for slowing counter of the music routine
$DE reset value of the slowing counter; must be >0 (uneven numbers like 7 seem to produce better RNG results)
$E6 Byte-frame for "double width - 1" of the region in which rain drops fall (e.g. #$1F for start screen, #$0F for avatars in the award ceremony)
$E7 low-bytes of the origin positions for 1st and 2nd place avatars have been POKEd directly into the IRQ main of the award ceremony:
$A6C1 = 1st place
$A6D2 = 2nd place
$E8 high-byte of all origin positions is #$0C

5) Greying out the score board
$D8-$D9 reserved for indirectly indexed addressing of TED attributes
$E4 in this context used as a switch which value #$00 indicates that the RAM-access stub is to be executed only once

This is how to use the RAM-access stub for initiation of a single execution of an assembly routine from BASIC:
1. Let rain drops settle and do not create new ones:
POKE 220, 0 - set number of drops to be falling to 0
FOR I=1 TO 400:NEXT - wait until remaining drops have fallen
2. Disable rain IRQ-main and prepare the RAM-access stub to be used for a single execution
SYS 995 - disable IRQ-extension for rain
POKE 228, 0 - set $E4 to #$00 to indicate that the stub won't be used for an IRQ-extension
POKE 879, 60 - set low-byte of the start address of the one time routine to #$3C
POKE 880, 167 - set high-byte of the start address of the one time routine to #$A7
SYS 870 - start routine that greys out all TED chars via RAM-access stub

6) Hall of Fame
$D8-$D9 reserved for indirectly indexed addressing of TED attributes
$DA-$DB reserved for indirectly indexed addressing of TED characters
$036F-$0370 the jump address in the RAM-access stub needs to be set to $A794 from BASIC using POKE statements
The attribute column ($094C, $0974, $099C, $09C4, $09EC) must hold colors greater 0 as a seed for the flickering


Assembler Code Listing
----------------------
*** 1) Routines in the tape buffer ***

--- $0333-$0355 General bank-switching-independent initialization and toggle of the IRQ RAM vector between $CE0E and $0357
.0333 LDA #$0E
EOR #$57
EOR $0314
STA $0314
LDA #$CE
EOR #$03
EOR $0315
STA $0315
-- Reset slowing counter
LDA $DE
STA $DD
-- Set all high-bytes of the rain drop buffer between $0673-$0681 to #$00 to mark the corresponding drops as inactive (=not containing drop info)
LDX #$0F
LDA #$00
.034F STA $0672,X
DEX
BNE $034F
RTS

--- $0357-$037D Universal RAM-access stub, which IRQ detour address (JSR $#### statement) must have been set in advance
-- Decrement slowing counter and skip IRQ-extension if >0
.0357 DEC $DD
BNE $037B
LDA $02 - slow musik with constant countdowns from #$02
?? This speed also applies to effects on screens other than the start screen. It would have to be derived from $DE to be dynamic, but there is not enough room at the moment...
STA $DD
-- Raster line synchronization for music (must happen outside the SEI CLI block!)
.035F LDA #$10 - line #$10 seems to be a good balance for musik speed; should probably be derived from $DE with LSR
.0361 CMP $FF1D
BNE $0361
-- .0366 is the entry point for single execution of a code in the bank-switching-RAM
.0366 SEI
-- Bank-Switching: Memorize the "ROM select"-status by putting it on the stack before entering the IRQ-extension
LDA $FF3E
PHA
STA $FF3F - set RAM_ON
JSR $0000 - the detour address is set from other routines or POKE-Statements ($A4FF / $A6A0 / $A6B0 / ...)
-- Bank-Switching: Restore the "ROM select"-status from the stack
PLA
STA $FF3E - set ROM_ON (as expected by BASIC)
CLI
-- If $E4 = #$00, do an RTS, as the stub only serves a single execution, otherwise resume with system-IRQ tasks at $CE0E
LDA $E4
BNE $037B
RTS
.037B JMP $CE0E

--- $037F-$039F Start screen-specific initialization (music, color circle addresses, IRQ-detour address & -toggle)
.037F SEI
-- General initialization and toggle execution of the universal RAM-access stub as a general IRQ-extension
JSR $0333
-- Bank-Switching: Memorize the "ROM select"-status by putting it on the stack before entering the IRQ-extension
LDA $FF3E
PHA
STA $FF3F - set RAM_ON
-- Music initialization
?? To be clarified with Hermit: Do we need another LDA #$00 here to avoid issues with saves of initialized code?
JSR $A96A
-- Copy circle addresses of the start screen from $A61A- to $A61C-
JSR $A7DE
-- Bank-Switching: Restore the "ROM select"-status from the stack
PLA
STA $FF3E - set ROM_ON
- Set the detour address in the RAM-access stub to $A4FF
LDA #$FF
STA $036F
LDA #$A4
STA $0370
CLI
.039F RTS

--- $03A1-$03BE Player name query-specific initialization (color box addresses, IRQ-detour address & -toggle)
.03A1 SEI
-- General initialization and toggle execution of the universal RAM-access stub as a general IRQ-extension
JSR $0333
-- Bank-Switching: Memorize the "ROM select"-status by putting it on the stack before entering the IRQ-extension
LDA $FF3E
PHA
STA $FF3F - set RAM_ON
- Copy box addresses of the frame around the player name query from $A670- to $A61C-
JSR $A7ED
-- Bank-Switching: Restore the "ROM select"-status from the stack
PLA
STA $FF3E - set ROM_ON
- Set the detour address in the RAM-access stub to $A6A0
LDA #$A0
STA $036F
LDA #$A6
STA $0370
CLI
.03BE RTS

--- $03C0-$03CF Award ceremony-specific initialization (IRQ-detour address & -toggle)
.03C0 SEI
-- General initialization and toggle execution of the universal RAM-access stub as a general IRQ-extension
JSR $0333
- Set the detour address in the RAM-access stub to $A6B0
LDA #$B0
STA $036F
LDA #$A6
STA $0370
CLI
.03CF RTS

--- $03D1-$03D6 Unspecific initialization (just toggling the IRQ-detour, which address must have been set in advance)
.03D1 SEI
-- General initialization and toggle execution of the universal RAM-access stub as a general IRQ-extension
JSR $0333
CLI
.03D6 RTS


*** 2) Routines in the bank-switching-RAM ***

--- $A4FF-$A518 Start screen: IRQ main
-- Play one music frame each call
.A4FF JSR $A9BF
-- Apply slowing counter only to the animation routines
DEC $D0
BNE $A563
LDA $DE
STA $D0
LDY #$00
JSR $A519
JSR $A564
JSR $A5DB
JSR $A710
.A518 RTS


--- $A519-$A563 Rain routine: Create new drops
-- Loop over all drop indices (irrespective of whether they are active or not)
.A519 LDX $DC
CPX #$00
BEQ $A563
.A51F LDA $0672, X
-- If drop X is already active, as indicated by a position high-byte <> #$00, skip drop creation for this index
CMP #$00
BNE $A560
-- Otherwise generate pseudo-random number for a drop creation attempt and convert it to a column-offset between 0 and the double width of the rain region, whereby the 0-bit is used to decide, whether the drop shall be created
JSR $A700
-- "Double width - 1" of the rain region is read from $E6
AND $E6
-- 0-bit is used to decide whether the creation is skipped
LSR
BCC $A560
-- Add the random 1-byte column-offset to the 2-byte origin (in $E7-E8) of the rain region and store the result as the starting position (=TED address) of the new rain drop
CLC
ADC $E7
STA $DA
STA $0662, X
STA $D8
LDA #$00
ADC $E8
STA $DB
STA $0672, X
SEC
SBC #$04
STA $D9
-- Memorize the symbol that is overwritten at the starting position, as long as it is not that of a drop (from a previous iteration):
-- Otherwise the drop must be eliminated again, as we cannot allow multidrops that would cause stripes by restoring prev-iteration-drops instead of the overwritten background
LDA ($DA),Y
CMP $DF
BNE $A553
LDA #$00
STA $0672, X
BEQ $A560
.A553 STA $0682, X
-- Memorize attribute of the overwritten symbol
LDA ($D8),Y
STA $0692,X
-- Memorize symbol and color attribute of drop X
JSR $A6E8
NOP
NOP
.A560 DEX
BNE $A51F
RTS

--- $A564-$A5DA Rain routine: Move & eliminate drops
-- Loop over all drop indices (not only the $DC existing drops, because then the code would crash when we set it to #$00 while it rains!)
.A564 LDX #$10
.A566 LDA $0672, X
-- Skip drops that are not active
CMP #$00
BEQ $A5D7
-- Copy address bytes for indirectly indexed addressing of the TED char pointer in $DA-$DB and of the TED attribute pointer in $D8-$D9 (which has the same low-byte and the high-byte - #$04)
LDA $0662, X
STA $DA
STA $D8
LDA $0672, X
STA $DB
SEC
SBC #$04
STA $D9
-- Cache symbol of drop X in $DF and its color attribute in $E4
.A57E JSR $A6F4
?? ToDo: This should only happen during the award ceremony, as it hinders changes of $E4 on the start screen
?? As a workaround, JSR is modified to LDA with POKE 42366,173 in order to skip the call of the routine at $A6F4, and then LDA is modified to JSR again with POKE 42366,32
NOP
NOP
-- Restore overwritten background symbol at the current drop position from the buffer, IF it is not a drop symbol (this prevents stripes in the case of adjacent drops)
LDA $0682, X
CMP $DF - compare to the symbol of the drop with index X
BEQ $A5AF
STA ($DA), Y
-- Restore attribute of the background symbol from the buffer
LDA $0692, X
STA ($D8), Y
-- Let drop fall one row by 2-byte addition of #$28 to the position address
LDA $DA
CLC
ADC #$28
STA $DA
STA $0662, X
STA $D8
LDA $DB
ADC #$00
STA $DB
STA $0672, X
SEC
SBC #$04
STA $D9
-- Eliminate drop once it "hits the ground", meaning its high-byte reaches #$0C, or when it hits a drop symbol (= was one iteration faster than an adjacent drop in the same column)
CMP #$0C
BNE $A5B6
.A5AF LDA #$00
STA $0672, X
BEQ $A5D7
-- Memorize symbol and color attribute of background at the new position of the drop..
.A5B6 LDA ($DA), Y
STA $0682, X
LDA ($D8),Y
STA $0692,X
-- ..and overwrite it with the drop symbol from $DF
LDA $DF
STA ($DA), Y
-- Calculate dynamic color attribute of the drop (changing brightness) from its row/128
CLC
LDA $DB
SBC #$0E
LSR
ROR $DA
LDA $DA
LSR
LSR
AND #$F0
-- To change brightness add a multiple of #$10 to the symbol-specific (golden $ and silver *) basis color = n*$10+$E4
CLC
ADC $E4
STA ($D8), Y
.A5D7 DEX
BNE $A566
RTS

--- $A5DB-$A619 Color circle: Change colors within periodic region boundaries
-- "1" to "30" represent addresses of TED attributes in the region $0800-0BFF, which values change in a rotating manner:
-- "1" = address of the low-byte of the attribute of the 1st point of the shape (circle or box)
-- "2" = address of the high-byte of the attribute of the 1st point of the shape (circle or box) etc.
-- The initial values for the definition of the circle and direction of the rotation have been initialized by $A7DE-$A7EB or $A7ED-$A7FA
-- Initialize pointer to flexible number of addresses (=index of last address) that define the object
.A5DB LDY $E5
-- Copy address of the last circle (or box) position directly in front of the list of addresses, and to $E1-$E2 for indirect addressing
LDA $"1",Y
STA $"1"
STA $E1
LDA $"2",Y
STA $"2"
STA $E2
-- Restore default color at the address of the last point of the shape
LDA $E3
LDY #$00
STA ($E1), Y
LDY $E5
-- Move all addresses one position (=2 bytes) up in the shape
.A5F5 LDA $"0", Y
STA $"2", Y
LDA $"-1", Y
STA $"1", Y
DEY
DEY
BNE $A5F5
-- For the 5th point of the shape apply an oscillating brigthness on the basis color
LDA $"21"
STA $E1
LDA $"22"
STA $E2
-- Trail with an oscillating brightness: n*$10+$E4
LDA $00A5
AND #$30
CLC
ADC $E4
STA ($E1), Y
RTS

--- $A61A-$A69F Color circle: Persistent storage of circle addresses as (Low-Byte, High-Byte)-pairs
-- Active circle addresses
.A61A 00 - cache1
.A61B 00 - cache2
.A61C-A64F
-- Definition of the TED-addresses of the color circle on the start screen
.A650 CF 09 F9 09 4A 0A C3 0A
3A 0B 89 0B AF 0B A6 0B
7C 0B 2B 0B B2 0A 3B 0A
EC 09 C6 09
-- Definition of the TED-addresses of the frame around the player name query
.A670 7A 08 7E 08 82 08 86 08
8A 08 8E 08 92 08 96 08
9A 08 42 0B 3E 0B 3A 0B
36 0B 32 0B 2E 0B 2A 0B
26 0B 22 0B

--- $A6A0-$A6AE Player name query: IRQ main
.A6A0 JSR $A5DB
?? Here I left some room for creativity: Calling another music routine, context-specific slowing counters and other fancy stuff
11* NOP
.A6AE RTS

--- $A6B0-$A6E4 Award ceremony: IRQ main
--- Let it rain golden dollar symbols for 1st place and silver stars for the 2nd place
-- The high-bytes of all needed reference positions are #$0C
.A6B0 LDA #$0C
STA $E8
?? 8 bytes are what one would need for a context-specific slowing counter
8* NOP
- Initialize the low-byte of the reference position at $E7, the symbol at $DF, and the basis color at $E4 before each call to the rain drop generating routine
LDA #$24
STA $DF
LDA #$00 - to be initialized from BASIC: Byte for the Position of the avatar of the 1st place
STA $E7
LDA #$48
STA $E4
LDY #$00
JSR $A519
LDA #$2A
STA $DF
LDA #$00 - to be initialized from BASIC: Byte for the Position of the avatar of the 2nd place
STA $E7
LDA #$31
STA $E4
LDY #$00
JSR $A519
JSR $A564
?? 3 bytes are what one would need for a JSR statement to anther music routine
3* NOP
.A6E4 RTS

--- $A6E8-$A6F2 Rain routine: Memorize symbol and color attribute of drop X
.A6E8 LDA $DF
STA $06A2, X
LDA $E4
STA $06B2, X
.A6F2 RTS

--- $A6F4-$A6FE Rain routine: Retrieve symbol and color attribute of drop X and cache in $DF and $E4
.A6F4 LDA $06A2, X
STA $DF
LDA $06B2, X
STA $E4
RTS

--- $A700-$A70D Simple pseudo-random number generator from https://codebase64.org/doku.php?id=base:small_fast_8-bit_prng
.A700 LDA $E0
BEQ $A709
ASL
BEQ $A70B
BCC $A70B
.A709 EOR #$1D
.A70B STA $E0
RTS

--- $A70F-$A737 Start screen: Oscillating brightness of Usagyuuun lettering
-- Fun fact: Change .A70F to F1 and #$E0 to #$E1 for a rainbow effect
-- Loop over all TED char addresses in region $0C00-$0CC7
.A70F 10 - this address stores the increment for the color attribute change: #$10 to increase brightness or by #$E0 to decrease brightness
.A710 LDX #$C8 - #$C8 = 5 rows * 40 columns
.A712 LDA $0BFF,X
-- Compare to whitespace code #$20 that indicates empty cells (also the cells right of the lettering must be #$20 to avoid unintentional flickering)
CMP #$20
BEQ $A734
-- If there is a character at that position add value from $A70F to color attribute
LDA $07FF,X
CLC
ADC $A70F
BPL $A731
-- Toggle increment at $A70F
LDA $A70F
EOR #$E0
STA $A70F
-- Add increment to color attribute
LDA $07FF,X
CLC
ADC $A70F
.A731 STA $07FF,X
.A734 DEX
BNE $A712
RTS

--- $A73C-$A755 Set all TED color attributes to grey
.A73C LDA #$00
STA $D8
LDA #$08
STA $D9
-- Outer loop over high-bytes of attribute addresses
.A744 LDA #$61
LDY #$00
-- Inner loop over low-bytes of attribute addresses
.A749 STA ($D8),Y
DEY
BNE $A748
INC $D9
LDA $D9
CMP #$0C
BNE $A744
.A755 RTS

--- $A757-$A765 Kniffelinterlude: IRQ main
.A757 JSR $A768
?? 11 bytes would be enough for a context-specific slowing counter and a JSR statement that calls another music routine
11* NOP
.A765 RTS

--- $A767-$A78F Kniffelinterlude: Color flickering of Kniffel lettering
.A767 10 - increment for color (brightness) change
.A768 LDX #$C8 - #$C8 = 5 rows * 40 columns
.A76A LDA $0D8F,X - Lettering starts in 10th row -> the address of the first cell is $0D90
CMP #$20
BEQ $A78C
LDA $098F,X
CLC
ADC $A767
BPL $A789
-- Toggle increment at $A767
LDA $A767
EOR #$E1
STA $A767
-- Add increment to color attribute
LDA $098F,X
CLC
ADC $A767
.A789 STA $0990,X
.A78C DEX
BNE $A76A
.A78F RTS

--- $A794-$A79A Hall of fame: IRQ main
.A794 JSR $A79D
NOP
NOP
NOP
RTS

--- $A79C-$A7DC Hall of fame: Color flickering of top 10 score board
.A79C F1 - increment for chaotic color change
-- Initialize low- and high-bytes of addresses of first TED character in $DA-$DB and TED attribute in $D8-$D9; The top 10 table starts in row 9 -> the address of the first cell is $0D4B
.A79D LDA #$4B
STA $DA
STA $D8
LDA #$0D
STA $DB
LDA #$09 - high-byte of attribute = high-byte of character - #$04
STA $D9
-- Loop over 10 rows * 40 columns = 400, but 512 work as well, so we run Y from #$00 to #$FF and use two STA statements
.A7AB LDY #$00
-- Alternative 1: Change color at characters <> #$20 (whitespace)
--.A7AD LDA ($DA),Y
--CMP #$20
-- Alternative 2: Change color at attributes <> #$10 (white)
.A7AD LDA ($D8), Y
CMP #$10
BEQ $A7CF
LDA ($D8),Y
CLC
ADC $A79C
BPL $A7C9
-- Toggle increment at $A70F
LDA $A79C
EOR #$E1
STA $A79C
-- Add increment to color attribute (using indirectly indexed addressing, because region >#$FF)
LDA ($D8),Y
CLC
ADC $A79C
-- To achieve flowing color effect, we want to save the attribute one behind (!) the source cell; So we increment the low-byte for indirectly indexed addressing stored at $D8 by 1..
INC $D8
.A7CB STA ($D8),Y
DEC $D8
.A7CF DEY
BNE $A7AD
-- ..and restore its original value afterwards for the loop
?? There might well be a more clever way of achieving this, so go ahead and try!
INC $DB
INC $D9
LDA $DB
CMP #$0F
BNE $A7AB
.A7DC RTS

--- $A7DE-$A7EB Start screen: Initialize addresses that define the color circle
.A7DE LDX #$1C
STX $E5
.A7E2 LDA $A64F, X
STA $A61B,X
DEX
BNE $A7E2
.A7EB RTS

--- $A7ED-$A7FA Player name query: Initialize addresses that define the box frame
.A7ED LDX #$24
STX $E5
.$A7F1 LDA $A66F, X
STA $A61B,X
DEX
BNE $A7F1
.A7FA RTS

Copyright © Plus/4 World Team, 2001-2024