This emulator is a port of Cycloa, a NES emulator written in C++, to JavaScript. The aim of this development is survey of JavaScript performance. In PC browsers, this emulator runs faster than jsnes with funciton inline expansin, but source code has been very messy. In iPad (1st gen), both emulators runs at more of the same speed.
Alter Ego is a puzzle action game, originally developed by Denis Grachev in ZX Spectrum. This NES version is ported by Shiru and Kulor in 2011. Warning! This game is "free of charge", but not licensed under GPL or any "opensource" license.
111 |
You can control a hero and his "alter ego". The hero and his alter ego move in mirrored fashion each other. You can swap them with B button in limited times. To complete stage, you have to collect all items in the satage.
112 |
Alter Egoは、Denis GrachevさんがZXスペクトラム向けに2011年に開発したアクションパズルゲームで、それを同年にShiruさんとKulorさんがファミコン向けに移植したものを今回許可を頂いて転載させて頂いています。「無料」のゲームですが、GPLなどの自由なライセンスではありません。
thwaite is a shooting-game developed by Damian Yerrick. You have to break out the ICBM and save your town! Is is licensed under GPL v3 or later. Here is a "README" document.
23 | An accident at the biochemical lab has released a neurotoxin,
24 | and you've been quarantined after exposure. Maintain your
25 | sanity by playing a card-matching game.
26 |
27 | The table is littered with 10, 20, 36, 52, or 72 face-down cards.
28 | Flip two cards, and if they show the same emblem, you keep them.
29 | If they don't, flip them back.
30 |
34 | Concentration Room is designed for your Nintendo Entertainment System. This version is an NROM-128 (16 KiB PRG, 8 KiB CHR), and it has been tested on a PowerPak. It also works in PC-based emulators such as Nestopia and FCE Ultra.
35 |
40 | Play solitaire to start to work the toxin out of your system. Then defeat other contaminated technicians and children one on one.
41 |
1 Player Solitaire
42 | Select a difficulty level, then try to clear the table without having to turn back more than 99 non-matching pairs.
43 |
2 Players
44 | Two players take turns turning over cards. They can pass one controller back and forth or use one controller each. If a pair doesn't match, the other player presses the A and B Buttons and takes a turn. The first player to take half the pairs wins.
45 |
Vs. CPU
46 | Like 2 Players, except the second player is controlled by the NES.
47 |
52 | This is actually my third try. The logo and the earliest background sketch date back to 2000. It got held up because I lacked artistic skill on the 16x16 pixel canvas. The second try in 2007 finalized the appearance of the game, and I did some work on the "emblem designer" that will show up in a future release. In late November 2009, I discovered Dian Shi Mali, a gambling simulator for the Famicom (Asian version of the NES) that also uses 16x16 pixel emblems. After a few hours of pushing Start to rich, I was inspired to create a set of 36 emblems. By then, I was ready to code most of the game in spare time during December 2009.
53 |
Why are you still making games that don't scroll? You're better than that, as I saw in the President video.
54 | I saw it as something simple that I could finish fairly quickly in order to push falling block games off the front page of my web site.
55 |
GameTek already made two other Concentration games on the NES. Why did you make this one?
56 | The controls in I Can Remember nor Classic Concentration are clunky. Neither of them features a full 72-card deck. And of course, they're not free software.
57 |
In vs. modes, why end the game at half the cards matched instead of one more than half?
58 | Pairs early in a game require more skill to clear, and the last pair requires absolutely no skill. For example, a 20-card game tied at 4-4 will always end up 6-4. And at 5-3, the player in the lead likely got more early matches. So if we award no points for the last pair, the first player to reach half always wins.
59 |
What's that font?
60 | The font in the game's logo is called Wasted Collection. The font in Multiboot Menu was based on it. The monospace font for menu text originally appeared in the "Who's Cuter" demo and is based on Apple Chicago by Susan Kare. (Another fun font is on this page.)
61 |
Are you a Nazi?
62 | No, and that's why this game is called Concentration Room, not Concentration Camp.
63 |
68 | Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty.
69 |
70 | The accompanying program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License, version 3 or later. As a special exception, you may copy and distribute exact copies of the program, as published by Damian Yerrick, in iNES or UNIF executable form without source code.
71 |
72 | This product is not sponsored or endorsed by Nintendo, Ravensburger, Hasbro, Mattel, Quaker Oats, NBC Universal, GameTek, or Apple.
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/roms/croom/croom.nes:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/croom/croom.nes
--------------------------------------------------------------------------------
/roms/lj65/lj65.nes:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/lj65/lj65.nes
--------------------------------------------------------------------------------
/roms/thwaite-0.03/CHANGES.txt:
--------------------------------------------------------------------------------
1 | 0.03 (2011-12-08)
2 | * Fixed crosshair braking failure
3 | * Can play game with a Super NES Mouse in either controller port
4 | * Switched to non-DPCM-safe controller reading code because the mouse
5 | needs it
6 | * A button icon blinks after cut scenes dialogue finishes drawing
7 | * Practice mode to start on any level
8 | * Draws much of 3x3-tile explosions with sprite flipping to save CHR
9 | * CHR rearranged to allow for more distinct tiles in cut scenes
10 | * Music for 05:00
11 | * Two ! alert sounds don't play at the same time
12 | * Some later levels are harder
13 | * I am within 256 bytes of filling PRG ROM
14 |
15 | 0.02 (2011-08-26)
16 | * Includes source code, partly under GPLv3 and partly under an
17 | all-permissive license
18 | * Added HTML5 manual
19 | * Added music for 04:00 and daytime
20 | * Dual channel drums for stronger kick and snare
21 | * Villagers warp to houses after each hour, making it clearer that an
22 | hour has passed
23 |
24 | 0.01 (2011-06-01)
25 | * initial release for nesdevcompo
26 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/README.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Thwaite
4 |
5 |
6 |
7 |
10 |
19 |
20 |
thwaite
21 |
22 | By Damian Yerrick
23 |
24 | Missiles are falling from the sky. Shoot them down with your fireworks.
25 |
38 | Thwaite has been tested and runs fine on a Nintendo Entertainment System using a PowerPak and on the FCEUX, Mednafen, Nestopia, and Nintendulator emulators. It attempts to adapt the music and game speed when played on an NTSC or PAL NES. If you can solder, and you want to put it on a permanent NES or Famicom cartridge, you can use a ReproPak board or any NROM-128 game's board (see list from NesCartDB).
39 |
40 | To compile Thwaite from source code, you'll need to install these:
41 |
42 |
GNU Make and GNU Coreutils (Windows: install MSYS; Ubuntu: sudo apt-get install build-essential)
51 | Insert the Game Pak into the NES Control Deck, push it down, and turn on the NES. (Or load thwaite.nes into an NES emulator.) Press Start to skip the legal notice and development status screen. Press Up or Down to select between a single-player game and a 2-player cooperative game, and press Start.
52 |
53 | Thwaite supports a Super NES Mouse connected to port 1 or 2 through an adapter. In a 1-player game, plug the mouse into either port and click "1 Player". In a 2-player game, replace one or both controllers with a mouse and click "2 Players". When a mouse is detected, an icon to change the sensitivity is shown; click this to change the sensitivity (slow, medium, fast).
54 |
58 | A hippie guitarist who has visited your small town for years has gone rogue and launched ICBMs toward your town. Break out the fireworks that you had been saving for Independence Day, turn them into makeshift anti-ballistic missiles (ABMs), and shoot down the incoming missiles. Each of two silos starts with 15 ABMs. Place the aiming cursor in front of the incoming missile and fire an ABM to destroy it. Defend the town for seven nights (Sunday through Saturday) and you win!
59 |
60 |
Game play screen. Click to show or hide names of the game objects.
61 |
62 | You have to lead your shot a bit because it takes a split second for the ABM to arrive. But the explosion of an ABM is wide enough to destroy several missiles, so aim where the incoming missiles' paths are about to cross. Balloons and multiple independent reentry vehicle (MIRV) missiles will release a payload of multiple missiles if not shot down promptly.
63 |
64 | At the end of each round, the silos are refilled with ABMs: 15 each or 20 if only one silo remains. A destroyed silo will get rebuilt at the end of a night or once you've lasted one round with no destroyed houses. And if a house has been destroyed, one house will be rebuilt the next day. Later in the week, when more houses are gone, you need not worry about missiles aimed at wreckage.
65 |
66 | The game is over once both silos or all ten houses have been destroyed, or once you have survived all seven nights.
67 |
77 | A 2-player game requires two controllers. In a 2-player game, both B and A Buttons of each controller fire from the same silo. Player 1 controls Milo's cursor, and player 2 controls Staisy's cursor.
78 |
79 | Because a Control Pad is less precise than the mouse or trackball that other point-and-shoot games use, Thwaite uses acceleration and braking for the cursor. To move short distances, make short taps; to move farther, hold a direction longer. Let go to stop the cursor.
80 |
84 | At the end of each round, your team gets 100 points for each house and 10 points for each remaining ABM in your silos. There is no bonus for shooting down missiles, but destroying two or three missiles with one ABM can make more ammo available.
85 |
86 | Can you reach the end of the game with 300,000 points?
87 |
92 | At the title screen, choose "Practice" to begin a readiness drill. This allows practicing any of the 35 waves with buildings on the left side, the right side, or both sides. Select a day, hour, and side by pointing at it and pressing A or the mouse button, then choose Play to begin. After you select a day and hour, you can see the types of ammo and how fast the missiles will come. You will return to the practice menu if you complete the wave, fail, or press the Select button while paused.
93 |
102 | The accompanying game program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
103 |
104 | This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
105 |
106 | You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
107 |
108 | Thwaite makes explosions and smoke appear translucent by flickering them. A very small percentage of people have seizures after looking at flickering patterns in television and video games. If you have had convulsions or loss of awareness of surroundings, see a health care professional before playing any video game.
109 |
110 | Intense video games can be tiring and cause repetitive strain injury. Take a five-minute break at least every half hour or so, and don't play when you need sleep.
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/docs/de.css:
--------------------------------------------------------------------------------
1 | /* stylesheet for Thwaite docs
2 |
3 | Copyright 2011 Damian Yerrick
4 | Copying and distribution of this file, with or without modification,
5 | are permitted in any medium without royalty provided the copyright
6 | notice and this notice are preserved. This file is offered as-is,
7 | without any warranty.
8 |
9 | */
10 |
11 | /* load body text fonts */
12 | @import url('http://fonts.googleapis.com/css?family=Droid+Sans:400,700|Droid+Sans+Mono');
13 |
14 | html { background: #000 }
15 | body { background: #FFF; color: #000; margin: 0.5em auto; padding: 1em 2em; max-width: 40em; font-family: 'Droid Sans', sans-serif; }
16 | html>body code, html>body tt, html>body pre, html>body kbd { font-family: "Droid Sans Mono", monospace; font-weight: normal; font-size: 90% }
17 | h1,h2,h3,h4 { font-family: FinkHeavy, Rockwell, Lubalin Graph; font-weight: normal; margin: 1em 0 0.4em 0 }
18 | h2 { clear: right }
19 | p, pre, ul, ol, dl { margin: 0.7em 0 }
20 | pre.tip { display: table; margin: 0.7em auto; padding: 0.5em 1em; letter-spacing: 0.1em; background: #000; color: #FFF }
21 | ul.toc { border: 1px solid #AAA; padding: 1em }
22 | ul.toc li { list-style-type: none; padding: 0; margin: 0 1em 0 0; display: inline }
23 | ul.toc li:last-child { margin-right: 0 }
24 | ul.toc a { white-space: nowrap }
25 |
26 | .floatscreen { border: 1px solid black; width: 276px; float: right; margin: 0 0 1em 1em; padding: 0 8px 0.5em 8px }
27 | .floatscreen img { margin: 0 -8px 0.5em -8px; width: 292px; height: 224px; display: block }
28 |
29 | .mainscreen { border: 1px solid black; margin: 0 auto; width: 568px; padding: 0 8px 0.5em 8px; position: relative }
30 | .mainscreen img.back { margin: 0 -8px 0.5em -8px; width: 584px; height: 448px; display: block }
31 | .mainscreen img.front { position: absolute; top: 0; left: 0; width: 584px; height: 448px; display: block; z-index: 1 }
32 |
33 | table.datatable { border: 1px solid #AAA; border-collapse: collapse; border-spacing: 0 }
34 | table.datatable th { background-color: #EEE; padding: 0.1em 0.3em }
35 | table.datatable td { border: 1px solid #AAA; padding: 0.1em 0.3em }
36 | td.numalign { text-align: right }
37 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/docs/manual_ingame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/docs/manual_ingame.png
--------------------------------------------------------------------------------
/roms/thwaite-0.03/docs/manual_legend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/docs/manual_legend.png
--------------------------------------------------------------------------------
/roms/thwaite-0.03/docs/manual_practice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/docs/manual_practice.png
--------------------------------------------------------------------------------
/roms/thwaite-0.03/docs/manual_title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/docs/manual_title.png
--------------------------------------------------------------------------------
/roms/thwaite-0.03/docs/tas_words.txt:
--------------------------------------------------------------------------------
1 | Anastasia
2 | Anastasia's
3 | Dakotas
4 | Itasca
5 | Itasca's
6 | Latasha
7 | Latasha's
8 | Mistassini
9 | Mistassini's
10 | Natasha
11 | Natasha's
12 | Pocahontas
13 | Pocahontas's
14 | Qantas
15 | Qantas's
16 | Unitas
17 | Unitas's
18 | aftertaste
19 | aftertaste's
20 | aftertastes
21 | aortas
22 | apostasies
23 | apostasy
24 | apostasy's
25 | betas
26 | birettas
27 | cantatas
28 | catastrophe
29 | catastrophe's
30 | catastrophes
31 | catastrophic
32 | catastrophically
33 | celestas
34 | deltas
35 | demitasse
36 | demitasse's
37 | demitasses
38 | distaste
39 | distaste's
40 | distasteful
41 | distastefully
42 | distastes
43 | ecstasies
44 | ecstasy
45 | ecstasy's
46 | erratas
47 | fantasied
48 | fantasies
49 | fantasize
50 | fantasized
51 | fantasizes
52 | fantasizing
53 | fantastic
54 | fantastically
55 | fantasy
56 | fantasy's
57 | fantasying
58 | fiestas
59 | foretaste
60 | foretaste's
61 | foretasted
62 | foretastes
63 | foretasting
64 | inamoratas
65 | iotas
66 | juntas
67 | margaritas
68 | metastases
69 | metastasis
70 | metastasis's
71 | metastasize
72 | metastasized
73 | metastasizes
74 | metastasizing
75 | multitasking
76 | operettas
77 | pastas
78 | pesetas
79 | phantasied
80 | phantasies
81 | phantasm
82 | phantasm's
83 | phantasmagoria
84 | phantasmagoria's
85 | phantasmagorias
86 | phantasms
87 | phantasy
88 | phantasy's
89 | phantasying
90 | placentas
91 | potash
92 | potash's
93 | potassium
94 | potassium's
95 | quotas
96 | regattas
97 | siestas
98 | sonatas
99 | stash
100 | stashed
101 | stashes
102 | stashing
103 | succotash
104 | succotash's
105 | task
106 | task's
107 | tasked
108 | tasking
109 | taskmaster
110 | taskmaster's
111 | taskmasters
112 | tasks
113 | tassel
114 | tassel's
115 | tasseled
116 | tasseling
117 | tasselled
118 | tasselling
119 | tassels
120 | taste
121 | taste's
122 | tasted
123 | tasteful
124 | tastefully
125 | tasteless
126 | tastelessly
127 | tastelessness
128 | tastelessness's
129 | taster
130 | taster's
131 | tasters
132 | tastes
133 | tastier
134 | tastiest
135 | tastiness
136 | tastiness's
137 | tasting
138 | tasty
139 | vendettas
140 | vistas
141 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/makefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 | #
3 | # Makefile for Thwaite
4 | # Copyright 2011 Damian Yerrick
5 | #
6 | # Copying and distribution of this file, with or without
7 | # modification, are permitted in any medium without royalty
8 | # provided the copyright notice and this notice are preserved.
9 | # This file is offered as-is, without any warranty.
10 | #
11 | version = 0.03
12 | objlist = main random levels smoke bg missiles explosion scurry \
13 | title practice cutscene cutscripts tips \
14 | math bcd unpkb pads mouse kinematics \
15 | paldetect sound music musicseq ntscPeriods
16 |
17 | CC65 = /usr/local/bin
18 | AS65 = ca65
19 | LD65 = ld65
20 | #EMU := "/C/Program Files/nintendulator/Nintendulator.exe"
21 | EMU := mednafen -nes.pal 0 -nes.input.port1 gamepad -nes.input.port2 gamepad
22 | CC = gcc
23 | ifdef COMSPEC
24 | DOTEXE=.exe
25 | else
26 | DOTEXE=
27 | endif
28 | CFLAGS = -std=gnu99 -Wall -DNDEBUG -O
29 | CFLAGS65 =
30 | objdir = obj/nes
31 | srcdir = src
32 | imgdir = tilesets
33 |
34 | # -f while debugging code; -r while adding shuffle markup;
35 | # neither once a module has stabilized
36 | shufflemode = -r
37 |
38 | objlistntsc = $(foreach o,$(objlist),$(objdir)/$(o).o)
39 |
40 | .PHONY: run dist zip
41 |
42 | run: thwaite.nes
43 | $(EMU) $<
44 |
45 | # Actually this depends on every single file in zip.in, but currently
46 | # we use changes to thwaite.nes, makefile, and README as a heuristic
47 | # for when something was changed. Limitation: it won't see changes
48 | # to docs or tools.
49 | dist: zip
50 | zip: thwaite-$(version).zip
51 | thwaite-$(version).zip: zip.in thwaite.nes README.html $(objdir)/index.txt
52 | zip -9 -u $@ -@ < $<
53 |
54 | # Some unzip tools won't create empty folders, so put a file there.
55 | $(objdir)/index.txt: makefile CHANGES.txt
56 | echo Files produced by build tools go here, but caulk goes where? > $@
57 |
58 | $(objdir)/%.o: $(srcdir)/%.s $(srcdir)/nes.h $(srcdir)/ram.h
59 | $(AS65) $(CFLAGS65) $< -o $@
60 |
61 | $(objdir)/%.o: $(objdir)/%.s
62 | $(AS65) $(CFLAGS65) $< -o $@
63 |
64 | # incbins
65 |
66 | $(objdir)/title.o: todo.txt src/title.pkb
67 | $(objdir)/cutscene.o: src/cutscene.pkb
68 | $(objdir)/practice.o: src/practice.txt
69 |
70 | $(objdir)/ntscPeriods.s: tools/mktables.py
71 | $< period $@
72 |
73 | map.txt thwaite.prg: nes.ini $(objlistntsc)
74 | $(LD65) -C $^ -m map.txt -o thwaite.prg
75 |
76 | $(objdir)/%.chr: $(imgdir)/%.png
77 | tools/pilbmp2nes.py $< $@
78 |
79 | %.nes: %.prg %.chr
80 | cat $^ > $@
81 |
82 | thwaite.chr: $(objdir)/maingfx.chr $(objdir)/cuthouses.chr
83 | cat $^ > $@
84 |
85 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/nes.ini:
--------------------------------------------------------------------------------
1 | #
2 | # Linker script for Concentration Room (lite version)
3 | # Copyright 2010 Damian Yerrick
4 | #
5 | # Copying and distribution of this file, with or without
6 | # modification, are permitted in any medium without royalty
7 | # provided the copyright notice and this notice are preserved.
8 | # This file is offered as-is, without any warranty.
9 | #
10 | MEMORY {
11 | ZP: start = $10, size = $f0, type = rw;
12 | # use first $10 zeropage locations as locals
13 | HEADER: start = 0, size = $0010, type = ro, file = %O, fill=yes, fillval=$00;
14 | RAM: start = $0300, size = $0500, type = rw;
15 | ROM7: start = $C000, size = $4000, type = ro, file = %O, fill=yes, fillval=$FF;
16 | }
17 |
18 | SEGMENTS {
19 | INESHDR: load = HEADER, type = ro, align = $10;
20 | ZEROPAGE: load = ZP, type = zp;
21 | BSS: load = RAM, type = bss, define = yes, align = $100;
22 | CODE: load = ROM7, type = ro, align = $100;
23 | RODATA: load = ROM7, type = ro, align = $100;
24 | VECTORS: load = ROM7, type = ro, start = $FFFA;
25 | }
26 |
27 | FILES {
28 | %O: format = bin;
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/obj/nes/index.txt:
--------------------------------------------------------------------------------
1 | Files produced by build tools go here, but caulk goes where?
2 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/bcd.s:
--------------------------------------------------------------------------------
1 | ;
2 | ; Binary to decimal conversion for 8-bit numbers
3 | ; Copyright 2010 Damian Yerrick
4 | ;
5 | ; Copying and distribution of this file, with or without
6 | ; modification, are permitted in any medium without royalty provided
7 | ; the copyright notice and this notice are preserved in all source
8 | ; code copies. This file is offered as-is, without any warranty.
9 | ;
10 | .export bcd8bit
11 |
12 | .macro bcd8bit_iter value
13 | .local skip
14 | cmp value
15 | bcc skip
16 | sbc value
17 | skip:
18 | rol highDigits
19 | .endmacro
20 |
21 | ;;
22 | ; Converts a decimal number to two or three BCD digits
23 | ; in no more than 84 cycles.
24 | ; @param a the number to change
25 | ; @return a: low digit; 0: upper digits as nibbles
26 | .proc bcd8bit
27 | highDigits = 0
28 | pha
29 | lda #0
30 | sta 0
31 | pla
32 |
33 | ; Each iteration takes 11 if subtraction occurs or 10 if not.
34 | ; But if 80 is subtracted, 40 and 20 aren't, and if 200 is
35 | ; subtracted, 80 is not, and at least one of 40 and 20 is not.
36 | ; So this part takes up to 6*11-2 cycles.
37 | bcd8bit_iter #200
38 | bcd8bit_iter #100
39 | bcd8bit_iter #80
40 | bcd8bit_iter #40
41 | bcd8bit_iter #20
42 | bcd8bit_iter #10
43 | rts
44 | .endproc
45 |
46 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/cutscene.pkb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/src/cutscene.pkb
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/cutscene.s:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/src/cutscene.s
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/cutscripts.s:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/src/cutscripts.s
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/explosion.s:
--------------------------------------------------------------------------------
1 | ; explosions.s
2 | ; Explosion drawing and explosion-missile collision code for Thwaite
3 |
4 | ;;; Copyright (C) 2011 Damian Yerrick
5 | ;
6 | ; This program is free software; you can redistribute it and/or
7 | ; modify it under the terms of the GNU General Public License
8 | ; as published by the Free Software Foundation; either version 3
9 | ; of the License, or (at your option) any later version.
10 | ;
11 | ; This program is distributed in the hope that it will be useful,
12 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ; GNU General Public License for more details.
15 | ;
16 | ; You should have received a copy of the GNU General Public License
17 | ; along with this program; if not, write to
18 | ; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | ; Boston, MA 02111-1307, USA.
20 | ;
21 | ; Visit http://www.pineight.com/ for more information.
22 |
23 | .include "src/nes.h"
24 | .include "src/ram.h"
25 |
26 | ;
27 | ; Because of NES PPU limitations, only half the explosions are
28 | ; processed on each frame: even ones in even frames and odd ones in
29 | ; odd frames. This adds (predictable) flicker.
30 | ;
31 | .segment "BSS"
32 | explodeX: .res NUM_EXPLOSIONS
33 | explodeY: .res NUM_EXPLOSIONS
34 | explodeTime: .res NUM_EXPLOSIONS
35 |
36 | ; If zero, tiles for a 3x3 tile explosion are in x, x+$01, and x+$02.
37 | ; If nonzero, they're in x, x^$01, and x, with the right column
38 | ; horizontally flipped.
39 | EXPLOSION_XMIRROR = 1
40 |
41 | ; If zero, tile rows for a 3x3 tile explosion are at x, x+$10, and
42 | ; x+$20, with x an element in explodeFrameStartTile. If nonzero,
43 | ; they're in x, x^$10, and x, with the bottom row vertically flipped.
44 | EXPLOSION_YMIRROR = 1
45 |
46 | .segment "CODE"
47 |
48 | ;;
49 | ; Sets all explosions inactive.
50 | ; Does not modify memory.
51 | .proc clearExplosions
52 | lda #$FF
53 | ldx #NUM_EXPLOSIONS-1
54 | loop:
55 | sta explodeTime,x
56 | dex
57 | bpl loop
58 | rts
59 | .endproc
60 |
61 | ;;
62 | ; Makes an explosion at (x, y).
63 | ; LOCAL-8 compliant
64 | .proc makeExplosion
65 | xpos = 0
66 | ypos = 1
67 | stx xpos
68 | sty ypos
69 |
70 | ; Look for the best slot for this explosion.
71 | ; The "best" slot is the one whose explosion has been on screen
72 | ; the longest.
73 | ; y holds the index of the best slot so far
74 | ; x holds the index of the slot currently being considered
75 | ldx #NUM_EXPLOSIONS - 2
76 | ldy #NUM_EXPLOSIONS - 1
77 |
78 | findFreeSlot:
79 | ; if the time in x is less than the time in y, y is a better slot
80 | lda explodeTime,x
81 | cmp explodeTime,y
82 | bcc notBetterSlot
83 | ; otherwise x is a better slot, so set y to x
84 | txa
85 | tay
86 | notBetterSlot:
87 | dex
88 | bpl findFreeSlot
89 | lda tvSystem
90 | beq isNTSC
91 | lda #explodeTimeToFramePAL-explodeTimeToFrame
92 | isNTSC:
93 | sta explodeTime,y
94 | lda xpos
95 | sta explodeX,y
96 | lda ypos
97 | sta explodeY,y
98 |
99 | lda #SFX_BOOM_NOISE
100 | jsr start_sound
101 | lda #SFX_BOOM_SQUARE
102 | jmp start_sound
103 | .endproc
104 |
105 |
106 | ;;
107 | ; Draws explosion number X and checks for collision with missiles.
108 | ; Does not modify X.
109 | ; Not LOCAL-8 compliant, but it is called only by updateAllExplosions
110 | ; which should handle the saving and restoring.
111 | .proc updateExplosionX
112 | ; these are used during collision
113 | exploRadius = 12
114 | exploX = 13
115 | exploY = 14
116 | exploNumber = 15
117 |
118 | ; these are used only during drawing
119 | rowNum = 0
120 | curTile = 1
121 | attr2 = 2
122 | exploXHi = 3
123 | startTile = 4
124 | tileSize = exploRadius
125 |
126 | stx exploNumber
127 | ; Make sure this explosion is active (time < 128)
128 | lda explodeTime,x
129 | bmi isDone
130 | tay
131 | lda explodeTimeToFrame,y
132 | bpl runExplosionFrame
133 | sta explodeTime,x
134 | isDone:
135 | jmp bail
136 | runExplosionFrame:
137 | tay
138 | lda explodeFrameStartTile,y
139 | sta startTile
140 | lda explodeFrameTileSize,y
141 | sta tileSize
142 | asl a
143 | asl a
144 | eor #$FF
145 | pha
146 | sec
147 | adc explodeX,x
148 | sta exploX
149 | lda #$FF
150 | adc #$00
151 | sta exploXHi
152 | pla
153 | clc
154 | adc explodeY,x
155 | sta exploY
156 | ldx oamIndex
157 | lda #0
158 | sta rowNum
159 | lda #$01
160 | sta attr2
161 | rowloop:
162 | .if ::EXPLOSION_XMIRROR
163 | lda attr2
164 | and #<~$40
165 | sta attr2
166 | .endif
167 | lda startTile
168 | sta curTile
169 | ldy #0 ; y = x position within sprite
170 | tileloop:
171 | lda curTile
172 | sta OAM+1,x
173 | .if ::EXPLOSION_XMIRROR
174 | eor #%0001
175 | sta curTile
176 | .else
177 | inc curTile
178 | .endif
179 | tya
180 | asl a
181 | asl a
182 | asl a
183 | adc exploX
184 | sta OAM+3,x
185 | lda #0
186 | adc exploXHi
187 | bne skipOneTile
188 | lda attr2
189 | sta OAM+2,x
190 | lda rowNum
191 | asl a
192 | asl a
193 | asl a
194 | adc exploY
195 | cmp #224
196 | bcs skipOneTile
197 | sta OAM,x
198 | inx
199 | inx
200 | inx
201 | inx
202 | skipOneTile:
203 | iny
204 | .if ::EXPLOSION_XMIRROR
205 | cpy #2
206 | bcc nosetxflip
207 | lda attr2
208 | ora #$40
209 | sta attr2
210 | nosetxflip:
211 | .endif
212 | cpy tileSize
213 | bcc tileloop
214 |
215 | lda startTile
216 | .if ::EXPLOSION_YMIRROR
217 | eor #$10
218 | .else
219 | adc #$0F ; row width: 10; minus 1 because carry is set
220 | .endif
221 | sta startTile
222 | inc rowNum
223 | lda rowNum
224 | .if ::EXPLOSION_YMIRROR
225 | cmp #2
226 | bcc nosetyflip
227 | lda attr2
228 | ora #$80
229 | sta attr2
230 | lda rowNum
231 | nosetyflip:
232 | .endif
233 | cmp tileSize
234 | bcc rowloop
235 |
236 | ; now we're done drawing, so let's load the variables
237 | ; used for collision
238 | distSquared = rowNum
239 | stx oamIndex
240 | ldx exploNumber
241 | cpx #NUM_EXPLOSIONS
242 | bcc notOverflow
243 | lda #$0F
244 | sta debugHex1
245 | stx debugHex2
246 | jmp collision_continue
247 | notOverflow:
248 | lda explodeX,x
249 | sta exploX
250 | lda explodeY,x
251 | sta exploY
252 | ldy explodeTime,x
253 | lda explodeTimeToFrame,y
254 | tay
255 | lda explodeFrameRadiusSquared,y
256 | sta exploRadius
257 |
258 | ldx #4
259 | collision_loop:
260 | lda missileYHi,x
261 | beq collision_continue
262 | lda exploY
263 | beq collision_continue
264 | sec
265 | sbc missileYHi,x
266 | bcs yNotNeg
267 | eor #$FF
268 | adc #1
269 | bne yMadePos
270 | yNotNeg:
271 | sec
272 | ldy missileType,x
273 | sbc missileCollisionHt,y
274 | bcs yMadePos
275 | lda #0
276 | yMadePos:
277 | cmp #12
278 | bcs collision_continue
279 | tay
280 | lda xSquared,y
281 | sta distSquared
282 |
283 | lda missileXHi,x
284 | beq collision_continue
285 | sec
286 | sbc exploX
287 | bcs xNotNeg
288 | eor #$FF
289 | adc #1
290 | xNotNeg:
291 | cmp #12
292 | bcs collision_continue
293 | tay
294 | lda xSquared,y
295 | adc distSquared
296 | bcs collision_continue
297 | cmp exploRadius
298 | bcs collision_continue
299 |
300 | jmp found_explosion
301 | collision_continue:
302 | inx
303 | cpx #NUM_MISSILES
304 | bcc collision_loop
305 |
306 | ldx exploNumber
307 | ; now we're done; go to next frame
308 | inc explodeTime,x
309 |
310 | bail:
311 | ; epilog: callee-saved variables
312 | rts
313 |
314 | ; This part of the code is put down here so that the branch back to
315 | ; collision loop will be within +/- 128 bytes.
316 | found_explosion:
317 | txa
318 | pha
319 | ldy missileType,x
320 | lda missileCollisionHt,y
321 | lsr a
322 | adc missileYHi,x
323 | tay
324 | lda #0
325 | sta missileYHi,x
326 | lda missileXHi,x
327 | tax
328 | jsr makeExplosion
329 | pla
330 | tax
331 |
332 | ; if a building is threatened, take the building out of threat
333 | ; (a double-threatened building will get re-threatened next time)
334 | ldy missileTarget,x
335 | cpy #12
336 | bcs badTarget
337 | lda housesStanding,y
338 | cmp #2
339 | bne badTarget
340 | lda #1
341 | sta housesStanding,y
342 | .if ::SHOW_THREATENED
343 | lda #BG_DIRTY_HOUSES
344 | ora bgDirty
345 | sta bgDirty
346 | .endif
347 | badTarget:
348 | jmp collision_continue
349 | .endproc
350 |
351 | ;;
352 | ; Update even or odd explosions: draw them and check for collisions.
353 | ;
354 | .proc updateAllExplosions
355 |
356 | ; Save three callee saved regs
357 | lda 15
358 | pha
359 | lda 14
360 | pha
361 | lda 13
362 | pha
363 | lda 12
364 | pha
365 |
366 | ; update even explosions in even frames and odd explosions
367 | ; in odd frames, so that only half the explosions take up
368 | ; space in OAM
369 | lda nmis
370 | ora #$FE
371 | clc
372 | adc #NUM_EXPLOSIONS
373 | tax
374 | exploLoop:
375 | jsr updateExplosionX
376 | dex
377 | dex
378 | bpl exploLoop
379 |
380 | pla
381 | sta 12
382 | pla
383 | sta 13
384 | pla
385 | sta 14
386 | pla
387 | sta 15
388 | rts
389 | rts
390 | .endproc
391 |
392 | .segment "RODATA"
393 | explodeTimeToFrame:
394 | .byt 0,0,0,0,1,1,1,1,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,5,5,5,5, $FF
395 | explodeTimeToFramePAL:
396 | .byt 0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,3,4,4,4,4,5,5,5, $FF
397 | explodeFrameStartTile:
398 | .byt $20,$22,$24,$26,$28,$2A
399 | explodeFrameTileSize:
400 | .byt 1, 2, 3, 3, 3, 3
401 |
402 | ; if xSquared[abs(dx)] + ySquared[abs(dy)] < explodeFrameRadiusSquared[frame]
403 | ; then there is a hit
404 | explodeFrameRadiusSquared:
405 | .byt 24, 64, 100, 144, 144, 144
406 | xSquared:
407 | .byt 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225
408 | ; in order of MISSILE_TYPE_* at the top of missiles.s
409 | missileCollisionHt:
410 | .byt 0, 0, 10
411 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/kinematics.s:
--------------------------------------------------------------------------------
1 | ;
2 | ; acceleration/brake mechanics
3 | ; Copyright 2011 Damian Yerrick
4 | ;
5 | ; Copying and distribution of this file, with or without
6 | ; modification, are permitted in any medium without royalty provided
7 | ; the copyright notice and this notice are preserved in any source
8 | ; code copies. This file is offered as-is, without any warranty.
9 | ;
10 | .include "src/ram.h"
11 |
12 | ;;
13 | ; Applies acceleration, braking, and speed limit.
14 | ; XY untouched.
15 | .proc accelBrakeLimit
16 | lsr abl_keys
17 | bcc notAccelRight
18 |
19 | ; if traveling to left, brake instead
20 | lda abl_vel+1
21 | bmi notAccelRight
22 |
23 | ; Case 1: nonnegative velocity, accelerating positive
24 | clc
25 | lda abl_accelRate
26 | adc abl_vel
27 | sta abl_vel
28 | lda #0
29 | adc abl_vel+1
30 | sta abl_vel+1
31 |
32 | ; clamp maximum velocity
33 | lda abl_vel
34 | cmp abl_maxVel
35 | lda abl_vel+1
36 | sbc abl_maxVel+1
37 | bcc notOverPosLimit
38 | lda abl_maxVel
39 | sta abl_vel
40 | lda abl_maxVel+1
41 | sta abl_vel+1
42 | notOverPosLimit:
43 | rts
44 | notAccelRight:
45 |
46 | lsr abl_keys
47 | bcc notAccelLeft
48 | ; if traveling to right, brake instead
49 | lda abl_vel+1
50 | bmi isAccelLeft
51 | ora abl_vel
52 | bne notAccelLeft
53 | isAccelLeft:
54 |
55 | ; Case 2: nonpositive velocity, accelerating negative
56 | ;sec ; already guaranteed set from bcc statement above
57 | lda abl_accelRate
58 | eor #$FF
59 | adc abl_vel
60 | sta abl_vel
61 | lda #$FF
62 | adc abl_vel+1
63 | sta abl_vel+1
64 |
65 | ; clamp maximum velocity
66 | clc
67 | lda abl_maxVel
68 | adc abl_vel
69 | lda abl_maxVel+1
70 | adc abl_vel+1
71 | bcs notUnderNegLimit
72 | sec
73 | lda #0
74 | sbc abl_maxVel
75 | sta abl_vel
76 | lda #0
77 | sbc abl_maxVel+1
78 | sta abl_vel+1
79 | notUnderNegLimit:
80 | rts
81 | notAccelLeft:
82 |
83 | lda abl_vel+1
84 | bmi brakeNegVel
85 |
86 | ; Case 3: Velocity > 0 and brake
87 | sec
88 | lda abl_vel
89 | sbc abl_brakeRate
90 | sta abl_vel
91 | lda abl_vel+1
92 | sbc #0
93 | bcs notZeroVelocity
94 | zeroVelocity:
95 | lda #0
96 | sta abl_vel
97 | notZeroVelocity:
98 | sta abl_vel+1
99 | rts
100 |
101 | brakeNegVel:
102 | ; Case 4: Velocity < 0 and brake
103 | clc
104 | lda abl_vel
105 | adc abl_brakeRate
106 | sta abl_vel
107 | lda abl_vel+1
108 | adc #0
109 | bcs zeroVelocity
110 | sta abl_vel+1
111 | rts
112 | .endproc
113 |
114 |
115 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/levels.s:
--------------------------------------------------------------------------------
1 | ; levels.s
2 | ; Level loading code and level definitions for Thwaite
3 |
4 | ;;; Copyright (C) 2011 Damian Yerrick
5 | ;
6 | ; This program is free software; you can redistribute it and/or
7 | ; modify it under the terms of the GNU General Public License
8 | ; as published by the Free Software Foundation; either version 3
9 | ; of the License, or (at your option) any later version.
10 | ;
11 | ; This program is distributed in the hope that it will be useful,
12 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ; GNU General Public License for more details.
15 | ;
16 | ; You should have received a copy of the GNU General Public License
17 | ; along with this program; if not, write to
18 | ; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | ; Boston, MA 02111-1307, USA.
20 | ;
21 | ; Visit http://www.pineight.com/ for more information.
22 |
23 | .include "src/ram.h"
24 |
25 | .import levelTips
26 |
27 | .segment "RODATA"
28 | ; Seven parameters vary per round: the speed of the missiles, the
29 | ; number of missiles before the round ends, the time between salvos
30 | ; (groups of missiles spawned together), and the four kinds of salvos
31 | ; that appear in the round. There is an unused flags byte, which was
32 | ; originally going to store salvo types until I decided on the
33 | ; current system.
34 | ;
35 | ; Salvo types 1-5 are just that many missiles.
36 | ; 8 is a balloon (costs 2 missiles)
37 | ; 9 is a MIRV (costs 2 missiles)
38 |
39 | ; Number of days in levels.s::levelTable and tips.s::levelTips
40 | NUM_MADE_DAYS = 7
41 |
42 | ; Debug build to test balance starting at a specific day
43 | ; (0: sun; 7: sat)
44 | ; Always set to 0 for release builds.
45 | SKIP_TO_DAY = 0
46 |
47 | levelTable:
48 | ; +----------------------- missile speed (unit: px/85 frames)
49 | ; | +------------------- number of missiles
50 | ; | | +--------------- time between salvos (unit: 100 ms)
51 | ; | | | +----------- flags (unused)
52 | ; | | | | +- salvo types (1, 2, 3, 4, 5, 8, 9)
53 | ; | | | | |
54 | ;SUN spd num tim unused salvo types
55 | ; The first level is almost painfully slow. It's for nooblets
56 | ; and grandmas.
57 | .byt 16, 10, 50,%00000000, 1, 1, 2, 2
58 | .byt 17, 15, 45,%00000000, 2, 2, 3, 3
59 | .byt 18, 20, 40,%00000000, 2, 3, 4, 8
60 | .byt 19, 25, 37,%00000000, 3, 4, 4, 9
61 | .byt 20, 30, 35,%00000000, 3, 4, 5, 9
62 |
63 | ;MON spd num tim types
64 | .byt 20, 20, 30,%00000000, 8, 3, 4, 8
65 | .byt 21, 25, 25,%00000000, 9, 3, 4, 8
66 | .byt 22, 30, 20,%00000000, 9, 4, 4, 8
67 | ; Occasionally, we surprise the player with levels where the
68 | ; progression in difficulty is irregular, in order to teach the
69 | ; player to adapt to different play styles.
70 | ; Mon 04 has unusually fast missiles, but not as many of them.
71 | .byt 64, 15, 30,%00000000, 1, 1, 2, 2
72 | .byt 24, 30, 25,%00000000, 4, 4, 9, 9
73 |
74 | ;TUE
75 | ; Tue 01 is a preview of Balloon Fever.
76 | .byt 25, 30, 20,%00000000, 4, 8, 8, 8
77 | .byt 26, 30, 25,%00000000, 3, 3, 4, 8
78 | .byt 28, 30, 25,%00000000, 3, 4, 4, 8
79 | .byt 29, 32, 25,%00000000, 3, 4, 5, 8
80 | .byt 30, 32, 25,%00000000, 9, 4, 5, 8
81 |
82 | ;WED
83 | ; Wed 01 is the first of the "Balloon Fever" levels. All missiles
84 | ; are either balloons or MIRVs, and the number of missiles is
85 | ; cranked up to reflect that each balloon or MIRV uses up two
86 | ; missiles. If the aim is off or slow, watch split then boom.
87 | ; Fortunately, the player always has both silos at the beginning
88 | ; of a day, but it's easy to lose them if the player runs out of
89 | ; ammo. And it's really easy to run out of ammo when cleaning up
90 | ; after a couple splits. So for this reason don't crank up the
91 | ; ammo more than 40.
92 | .byt 44, 34, 20,%00000000, 8, 8, 8, 9
93 | .byt 32, 30, 24,%00000000, 9, 3, 4, 9
94 | ; Wed 03 is another fast level
95 | .byt 64, 20, 30,%00000000, 1, 1, 2, 2
96 | .byt 33, 28, 23,%00000000, 8, 3, 5, 8
97 | .byt 34, 35, 22,%00000000, 9, 4, 5, 8
98 |
99 | ;THU
100 | .byt 52, 36, 18,%00000000, 8, 8, 8, 9
101 | .byt 34, 25, 22,%00000000, 9, 4, 5, 9
102 | .byt 35, 25, 21,%00000000, 8, 4, 5, 8
103 | .byt 36, 30, 21,%00000000, 9, 4, 5, 9
104 | .byt 37, 35, 20,%00000000, 9, 4, 5, 8 ; yup, a wakeup call level
105 | ;FRI
106 | .byt 58, 38, 16,%00000000, 8, 8, 8, 9
107 | .byt 35, 30, 20,%00000000, 9, 4, 5, 9
108 | .byt 36, 30, 20,%00000000, 8, 4, 5, 8
109 | .byt 72, 20, 30,%00000000, 1, 2, 2, 9
110 | .byt 38, 35, 20,%00000000, 9, 4, 5, 8
111 | ;SAT
112 | .byt 64, 40, 15,%00000000, 8, 8, 8, 9
113 | .byt 37, 30, 20,%00000000, 9, 4, 5, 9
114 | .byt 38, 30, 20,%00000000, 8, 4, 5, 8
115 | .byt 39, 30, 20,%00000000, 9, 4, 5, 9
116 | .byt 40, 35, 20,%00000000, 9, 4, 5, 8
117 |
118 |
119 | .segment "BSS"
120 | ; Do not shuffle these; they must remain in the same order as in
121 | ; levelTable or level loading will fail.
122 | levelMissileSpeed: .res 1
123 | enemyMissilesLeft: .res 1
124 | levelReleasePeriod: .res 1
125 | levelMissileFlags: .res 1
126 | levelSalvoSizes: .res 4
127 |
128 | .segment "CODE"
129 |
130 | ;;
131 | ; Loads the data for a level
132 | ; @param A level number (0-63)
133 | .proc loadLevel
134 | tax
135 | lda isPractice
136 | bne noLoadTip
137 | lda levelTips,x
138 | sta curTip
139 | cpx #1
140 | bne notTwoPlayerReplace
141 | lda numPlayers
142 | cmp #2
143 | bne notTwoPlayerReplace
144 | lda #11 ; two player tip
145 | sta curTip
146 | notTwoPlayerReplace:
147 | lda #BG_DIRTY_TIP
148 | ora bgDirty
149 | sta bgDirty
150 | lda #50
151 | sta tipTimeLeft
152 | noLoadTip:
153 | txa
154 | asl a
155 | asl a
156 | asl a
157 | sta 0
158 | lda #0
159 | rol a
160 | sta 1
161 | lda #levelTable
165 | adc 1
166 | sta 1
167 | ldy #7
168 | copyloop:
169 | lda (0),y
170 | sta levelMissileSpeed,y
171 | dey
172 | bpl copyloop
173 |
174 | ; Make missiles 18.75% faster on PAL (should be 20% but
175 | ; who'll notice?)
176 | ldx tvSystem
177 | beq noPALCorrection
178 | lsr a
179 | adc levelMissileSpeed
180 | lsr a
181 | lsr a
182 | lsr a
183 | adc levelMissileSpeed
184 | sta levelMissileSpeed
185 | noPALCorrection:
186 |
187 | rts
188 | .endproc
189 |
190 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/math.s:
--------------------------------------------------------------------------------
1 | ;
2 | ; math.s
3 | ; Arithmetic and trigonometry routines for Thwaite
4 | ;
5 | ; Copyright (c) 2011 Damian Yerrick
6 | ;
7 | ; Copying and distribution of this file, with or without
8 | ; modification, are permitted in any medium without royalty provided
9 | ; the copyright notice and this notice are preserved in all source
10 | ; code copies. This file is offered as-is, without any warranty.
11 | ;
12 |
13 | ;
14 | ; The NES CPU has no FPU, nor does it have a multiplier or divider
15 | ; for integer math. So we have to implement these in software.
16 | ; Here are subroutines to compute 8x8=16-bit product, a fractional
17 | ; quotient in 0.8 fixed point, 2-argument arctangent, and rectangular
18 | ; to polar coordinate conversion. Also included are lookup tables of
19 | ; sine and cosine for angles expressed in units of 1/32 of a turn
20 | ; from due right, where cos(0) = cos(32) = sin(8) = 1.0.
21 | ;
22 | ; Further information:
23 | ; http://en.wikipedia.org/wiki/Fixed-point_arithmetic
24 | ; http://en.wikipedia.org/wiki/Binary_multiplier
25 | ; http://en.wikipedia.org/wiki/Boxing_the_compass
26 | ; http://en.wikipedia.org/wiki/Binary_scaling#Binary_angles
27 | ;
28 |
29 | .include "src/ram.h"
30 | .segment "CODE"
31 |
32 | ;;
33 | ; Multiplies two 8-bit factors to produce a 16-bit product
34 | ; in about 153 cycles.
35 | ; @param A one factor
36 | ; @param Y another factor
37 | ; @return high 8 bits in A; low 8 bits in $0000
38 | ; Y and $0001 are trashed; X is untouched
39 | .proc mul8
40 | factor2 = 1
41 | prodlo = 0
42 |
43 | ; Factor 1 is stored in the lower bits of prodlo; the low byte of
44 | ; the product is stored in the upper bits.
45 | lsr a ; prime the carry bit for the loop
46 | sta prodlo
47 | sty factor2
48 | lda #0
49 | ldy #8
50 | loop:
51 | ; At the start of the loop, one bit of prodlo has already been
52 | ; shifted out into the carry.
53 | bcc noadd
54 | clc
55 | adc factor2
56 | noadd:
57 | ror a
58 | ror prodlo ; pull another bit out for the next iteration
59 | dey ; inc/dec don't modify carry; only shifts and adds do
60 | bne loop
61 | rts
62 | .endproc
63 |
64 | ;;
65 | ; Computes 256*a/y. Useful for finding slopes.
66 | ; 0 and 1 are trashed.
67 | .proc getSlope1
68 | quotient = 0
69 | divisor = 1
70 |
71 | sty divisor
72 | ldy #1 ; when this gets ROL'd eight times, the loop ends
73 | sty quotient
74 | loop:
75 | asl a
76 | bcs alreadyGreater
77 | cmp divisor
78 | bcc nosub
79 | alreadyGreater:
80 | sbc divisor
81 | sec ; without this, results using alreadyGreater are wrong
82 | ; thx to http://6502org.wikidot.com/software-math-intdiv
83 | ; for helping solve this
84 | nosub:
85 | rol quotient
86 | bcc loop
87 | lda quotient
88 | rts
89 | .endproc
90 |
91 | ;;
92 | ; Find the angle of a vector pointing from (x1, y1) to (x2, y2),
93 | ; all coordinates unsigned.
94 | ; This is also called arctan2 or (on TI calculators) "R>Ptheta".
95 | ; @param 0 x1
96 | ; @param 1 y1
97 | ; @param 2 x2
98 | ; @param 3 y2
99 | ; @return A: angle (0-31);
100 | ; 0: slope reflected into first octant;
101 | ; 1: angle reflected into first octant;
102 | ; 2, 3: point reflected into first octant
103 | ; Trashes Y and nothing else.
104 | .proc getAngle
105 | x1 = 0
106 | y1 = 1
107 | x2 = 2
108 | y2 = 3
109 | flags = 4
110 |
111 | lda y2
112 | cmp y1
113 | bne notHorizontal
114 | lda x2
115 | cmp x1
116 | lda #0
117 | sta 1
118 | bcs :+
119 | lda #16
120 | :
121 | rts
122 |
123 | notHorizontal:
124 | ; make sure x2 > x1
125 | lda x2
126 | cmp x1
127 | bne notVertical
128 | lda y2
129 | cmp y1
130 | lda #$FF
131 | sta 3
132 | lda #0 ; store first-octant angle
133 | sta 1
134 | lda #24
135 | bcc :+
136 | lda #8
137 | :
138 | rts
139 | notVertical:
140 |
141 | ; At this point, we have already eliminated the special cases of a
142 | ; perfectly horizontal or vertical ray.
143 | ; So now compute the sign and abs of (y2 - y1)
144 | sec
145 | lda y2
146 | sbc y1
147 | bcs noVerticalFlip
148 | eor #$FF
149 | adc #1
150 | noVerticalFlip:
151 | sta y1
152 |
153 | lda #0
154 | rol a
155 | sta flags ; flag 2: SKIP y flip (angle = 16 - angle)
156 |
157 | ; Compute the sign and abs of (x2 - x1)
158 | sec
159 | lda x2
160 | sbc x1
161 | bcs noHorizontalFlip
162 | eor #$FF
163 | adc #1
164 | noHorizontalFlip:
165 | sta x1
166 | rol flags ; flag 1: SKIP x flip (angle = 8 - angle)
167 |
168 | ; if x1 > y1 then swap x1 and y1
169 | lda y1
170 | cmp x1
171 | bcc noDiagonalFlip
172 | ldy x1
173 | sty y1
174 | sta x1
175 | noDiagonalFlip:
176 | rol flags ; flag 0: PERFORM diagonal flip (angle = 4 - angle)
177 |
178 | lda y1
179 | sta y2
180 | ldy x1
181 | sty x2
182 | jsr getSlope1
183 | sta x1
184 |
185 | ldy #4
186 | tansearch:
187 | cmp tantable-1,y
188 | bcs foundTan
189 | dey
190 | bne tansearch
191 | foundTan:
192 | tya
193 | sta y1
194 |
195 | lsr flags
196 | bcc noUndoDiagonal
197 | eor #$FF ; reverse-subtract 8
198 | adc #8
199 | noUndoDiagonal:
200 |
201 | lsr flags
202 | bcs noUndoHorizontal
203 | eor #$FF ; reverse-subtract 16
204 | adc #17 ; plus one because we came in with clc
205 | noUndoHorizontal:
206 |
207 | lsr flags
208 | bcs noUndoVertical
209 | eor #$FF ; reverse-subtract 32
210 | adc #33 ; plus one because we came in with clc
211 | noUndoVertical:
212 |
213 | rts
214 | .endproc
215 |
216 | ;;
217 | ; Finds the approximate euclidean distance from the silo to the crosshair.
218 | ; @param A x1 silo X (usually 64 or 192)
219 | ; @param 2 x2 target X
220 | ; @param 3 y2 target Y
221 | ; @return A: pixel distance (high bit in carry); 3: actual angle
222 | ; Y and 0-5 are trashed
223 | .proc measureFromSilo
224 | ; first special-case pointing straight up
225 | sta 0
226 | cmp 2
227 | bne notVertical
228 | lda #SILO_Y
229 | sbc 3
230 | ldy #24
231 | sty 3
232 | rts
233 | notVertical:
234 | lda #SILO_Y
235 | sta 1
236 | jsr getAngle
237 |
238 | ; getAngle flips the coordinates into the first octant and returns
239 | ; a vector v and the angle theta within pi/16 radians of v.
240 | ; From theta we look up u, a unit vector nearly parallel to v,
241 | ; and then compute length = u dot v.
242 | ; But treat the cases where u is axis-aligned separately for speed
243 | ; and because 256*cos(90deg) = 256, which overflows 8 bits.
244 | ldy 1
245 | bne notAngle0
246 | sta 3
247 | lda 2
248 | rts
249 | notAngle0:
250 | pha
251 | lda sine256Q1,y
252 | sta 5
253 | lda cosine256Q1,y
254 | sta 4
255 | ldy 2
256 | jsr mul8
257 | sta 4
258 | ldy 3
259 | pla
260 | sta 3
261 | lda 5
262 | jsr mul8
263 | clc
264 | adc 4
265 | rts
266 | .endproc
267 |
268 |
269 | .segment "RODATA"
270 |
271 | ; Tangents of angles between the ordinary angles, used by getAngle.
272 | ; you can make trig tables even in windows calculator
273 | ; (90/16*1)t*256= 25
274 | tantable:
275 | .byt 25, 78, 137, 210
276 |
277 | ; Accurate sin/cos table used by measureFromSilo.
278 | ; These are indexed by angle in quadrant 1, and scaled by 256.
279 | ; (90*7/8)s*256=
280 | sine256Q1:
281 | .byt 0, 50, 98, 142, 181, 213, 237, 251
282 | cosine256Q1:
283 | .byt 0, 251, 237, 213, 181, 142, 98, 50
284 |
285 | ; Less precise sin/cos table used by e.g. missile smoke generation.
286 | ; These are indexed by angle through the whole circle
287 | ; and scaled by 64.
288 | ; (90*7/8)s*64=
289 | missileSine:
290 | .byt 0, 12, 24, 36, 45, 53, 59, 63
291 | missileCosine:
292 | .byt 64, 63, 59, 53, 45, 36, 24, 12
293 | .byt 0,-12,-24,-36,-45,-53,-59,-63
294 | .byt -64,-63,-59,-53,-45,-36,-24,-12
295 | .byt 0, 12, 24, 36, 45, 53, 59, 63
296 |
297 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/mouse.s:
--------------------------------------------------------------------------------
1 | .export read_mouse, mouse_change_sensitivity
2 | .exportzp cur_mbuttons, new_mbuttons
3 | .segment "ZEROPAGE"
4 | cur_mbuttons: .res 2
5 | new_mbuttons: .res 2
6 |
7 | .segment "CODE"
8 | ;;
9 | ; @param X player number
10 | .proc read_mouse
11 | lda #1
12 | sta 1
13 | sta 2
14 | sta 3
15 | :
16 | lda $4016,x
17 | lsr a
18 | rol 1
19 | bcc :-
20 | lda cur_mbuttons,x
21 | eor #$FF
22 | and 1
23 | sta new_mbuttons,x
24 | lda 1
25 | sta cur_mbuttons,x
26 | :
27 | lda $4016,x
28 | lsr a
29 | rol 2
30 | bcc :-
31 | :
32 | lda $4016,x
33 | lsr a
34 | rol 3
35 | bcc :-
36 | rts
37 | .endproc
38 |
39 | .proc mouse_change_sensitivity
40 | lda #1
41 | sta $4016
42 | lda $4016,x
43 | lda #0
44 | sta $4016
45 | rts
46 | .endproc
47 |
48 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/music.s:
--------------------------------------------------------------------------------
1 | ; music.s
2 | ; part of sound engine for LJ65, Concentration Room, and Thwaite
3 |
4 | ;;; Copyright (C) 2009-2011 Damian Yerrick
5 | ;
6 | ; This program is free software; you can redistribute it and/or
7 | ; modify it under the terms of the GNU General Public License
8 | ; as published by the Free Software Foundation; either version 3
9 | ; of the License, or (at your option) any later version.
10 | ;
11 | ; This program is distributed in the hope that it will be useful,
12 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ; GNU General Public License for more details.
15 | ;
16 | ; You should have received a copy of the GNU General Public License
17 | ; along with this program; if not, write to
18 | ; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | ; Boston, MA 02111-1307, USA.
20 | ;
21 | ; Visit http://www.pineight.com/ for more information.
22 |
23 | .importzp psg_sfx_state
24 | .import soundBSS
25 | .import start_sound
26 | .export music_playing
27 | .export init_music, stop_music, update_music, update_music_ch
28 | .include "src/musicseq.h"
29 |
30 | .ifndef SOUND_NTSC_ONLY
31 | SOUND_NTSC_ONLY = 0
32 | .endif
33 | .if (!SOUND_NTSC_ONLY)
34 | .importzp tvSystem
35 | .endif
36 |
37 | musicPatternPos = psg_sfx_state + 2
38 | conductorPos = psg_sfx_state + 16
39 | noteEnvVol = soundBSS + 0
40 | notePitch = soundBSS + 1
41 | noteRowsLeft = soundBSS + 2
42 | ; 3 is in sound.s
43 | musicPattern = soundBSS + 16
44 | patternTranspose = soundBSS + 17
45 | noteInstrument = soundBSS + 18
46 | ; 19 is in sound.s
47 | tempoCounterLo = soundBSS + 48
48 | tempoCounterHi = soundBSS + 49
49 | music_tempoLo = soundBSS + 50
50 | music_tempoHi = soundBSS + 51
51 | conductorSegno = soundBSS + 52
52 |
53 | conductorWaitRows = soundBSS + 62
54 | music_playing = soundBSS + 63
55 |
56 | FRAMES_PER_MINUTE_PAL = 3000
57 | FRAMES_PER_MINUTE_NTSC = 3606
58 |
59 |
60 | .segment "RODATA"
61 |
62 | fpmLo:
63 | .byt FRAMES_PER_MINUTE_NTSC, >FRAMES_PER_MINUTE_PAL
66 |
67 | silentPattern:
68 | .byt 26*8+7, 255
69 |
70 | durations:
71 | .byt 1, 2, 3, 4, 6, 8, 12, 16
72 |
73 | .segment "CODE"
74 | .proc init_music
75 | asl a
76 | tax
77 | lda songTable,x
78 | sta conductorPos
79 | sta conductorSegno
80 | lda songTable+1,x
81 | sta conductorPos+1
82 | sta conductorSegno+1
83 | ldx #12
84 | stx music_playing
85 | channelLoop:
86 | lda #$FF
87 | sta musicPattern,x
88 | lda #silentPattern
91 | sta musicPatternPos+1,x
92 | lda #0
93 | sta patternTranspose,x
94 | sta noteInstrument,x
95 | sta noteEnvVol,x
96 | sta noteRowsLeft,x
97 | dex
98 | dex
99 | dex
100 | dex
101 | bpl channelLoop
102 | lda #0
103 | sta conductorWaitRows
104 | lda #$FF
105 | sta tempoCounterLo
106 | sta tempoCounterHi
107 | lda #<300
108 | sta music_tempoLo
109 | lda #>300
110 | sta music_tempoHi
111 | rts
112 | .endproc
113 |
114 | .proc stop_music
115 | lda #0
116 | sta music_playing
117 | rts
118 | .endproc
119 |
120 | .proc update_music
121 | lda music_playing
122 | beq music_not_playing
123 | lda music_tempoLo
124 | clc
125 | adc tempoCounterLo
126 | sta tempoCounterLo
127 | lda music_tempoHi
128 | adc tempoCounterHi
129 | sta tempoCounterHi
130 | bcs new_tick
131 | music_not_playing:
132 | rts
133 | new_tick:
134 |
135 | .if ::SOUND_NTSC_ONLY
136 | ldy #0
137 | .else
138 | ldy tvSystem
139 | beq is_ntsc_1
140 | ldy #1
141 | is_ntsc_1:
142 | .endif
143 |
144 | ; Subtract tempo
145 | lda tempoCounterLo
146 | sbc fpmLo,y
147 | sta tempoCounterLo
148 | lda tempoCounterHi
149 | sbc fpmHi,y
150 | sta tempoCounterHi
151 |
152 | ;jmp skipConductor
153 |
154 | lda conductorWaitRows
155 | beq doConductor
156 | dec conductorWaitRows
157 | jmp skipConductor
158 |
159 | doConductor:
160 |
161 | ldy #0
162 | lda (conductorPos),y
163 | inc conductorPos
164 | bne :+
165 | inc conductorPos+1
166 | :
167 | sta 0
168 | cmp #CON_SETTEMPO
169 | bcc @notTempoChange
170 | and #%00000011
171 | sta music_tempoHi
172 |
173 | lda (conductorPos),y
174 | inc conductorPos
175 | bne :+
176 | inc conductorPos+1
177 | :
178 | sta music_tempoLo
179 | jmp doConductor
180 | @notTempoChange:
181 | cmp #CON_WAITROWS
182 | bcc conductorPlayPattern
183 | beq conductorDoWaitRows
184 |
185 | cmp #CON_FINE
186 | bne @notFine
187 | lda #0
188 | sta music_playing
189 | sta music_tempoHi
190 | sta music_tempoLo
191 | rts
192 | @notFine:
193 |
194 | cmp #CON_SEGNO
195 | bne @notSegno
196 | lda conductorPos
197 | sta conductorSegno
198 | lda conductorPos+1
199 | sta conductorSegno+1
200 | jmp doConductor
201 | @notSegno:
202 |
203 | cmp #CON_DALSEGNO
204 | bne @notDalSegno
205 | lda conductorSegno
206 | sta conductorPos
207 | lda conductorSegno+1
208 | sta conductorPos+1
209 | jmp doConductor
210 | @notDalSegno:
211 |
212 | jmp skipConductor
213 |
214 | conductorPlayPattern:
215 | and #$03
216 | asl a
217 | asl a
218 | tax
219 | lda #0
220 | sta noteRowsLeft,x
221 | lda (conductorPos),y
222 | sta musicPattern,x
223 | iny
224 | lda (conductorPos),y
225 | sta patternTranspose,x
226 | iny
227 | lda (conductorPos),y
228 | sta noteInstrument,x
229 | tya
230 | sec
231 | adc conductorPos
232 | sta conductorPos
233 | bcc :+
234 | inc conductorPos+1
235 | :
236 | jsr startPattern
237 | jmp doConductor
238 |
239 | ; this should be last so it can fall into skipConductor
240 | conductorDoWaitRows:
241 |
242 | lda (conductorPos),y
243 | inc conductorPos
244 | bne :+
245 | inc conductorPos+1
246 | :
247 | sta conductorWaitRows
248 |
249 | skipConductor:
250 |
251 | ldx #12
252 | channelLoop:
253 | lda noteRowsLeft,x
254 | bne skipNote
255 | anotherPatternByte:
256 | lda (musicPatternPos,x)
257 | cmp #255
258 | bne notStartPatternOver
259 | jsr startPattern
260 | lda (musicPatternPos,x)
261 | notStartPatternOver:
262 |
263 | inc musicPatternPos,x
264 | bne patternNotNewPage
265 | inc musicPatternPos+1,x
266 | patternNotNewPage:
267 |
268 | cmp #$D8
269 | bcc notInstChange
270 | lda (musicPatternPos,x)
271 | sta noteInstrument,x
272 | nextPatternByte:
273 | inc musicPatternPos,x
274 | bne anotherPatternByte
275 | inc musicPatternPos+1,x
276 | jmp anotherPatternByte
277 | notInstChange:
278 |
279 | ; set the note's duration
280 | pha
281 | and #$07
282 | tay
283 | lda durations,y
284 | sta noteRowsLeft,x
285 | pla
286 | lsr a
287 | lsr a
288 | lsr a
289 | cmp #25
290 | bcc isTransposedNote
291 | beq notKeyOff
292 | lda #0
293 | sta noteEnvVol,x
294 | notKeyOff:
295 | jmp skipNote
296 |
297 | isTransposedNote:
298 | cpx #12
299 | beq isDrumNote
300 | adc patternTranspose,x
301 | sta notePitch,x
302 | lda noteInstrument,x
303 | asl a
304 | asl a
305 | tay
306 | lda instrumentTable,y
307 | asl a
308 | asl a
309 | asl a
310 | asl a
311 | ora #$0C
312 | sta noteEnvVol,x
313 |
314 | skipNote:
315 | dec noteRowsLeft,x
316 | dex
317 | dex
318 | dex
319 | dex
320 | bpl channelLoop
321 |
322 | rts
323 |
324 | isDrumNote:
325 | stx 5
326 | asl a
327 | pha
328 | tax
329 | lda drumSFX,x
330 | jsr start_sound
331 | pla
332 | tax
333 | lda drumSFX+1,x
334 | bmi noSecondDrum
335 | jsr start_sound
336 | noSecondDrum:
337 | ldx 5
338 | jmp skipNote
339 |
340 | startPattern:
341 | lda musicPattern,x
342 | asl a
343 | bcc @notSilentPattern
344 | lda #silentPattern
347 | sta musicPatternPos+1,x
348 | rts
349 | @notSilentPattern:
350 | tay
351 | lda musicPatternTable,y
352 | sta musicPatternPos,x
353 | lda musicPatternTable+1,y
354 | sta musicPatternPos+1,x
355 | rts
356 | .endproc
357 |
358 | .proc update_music_ch
359 | ch_number = 0
360 | out_volume = 2
361 | out_pitch = 3
362 |
363 | lda music_playing
364 | beq silenced
365 | lda noteEnvVol,x
366 | lsr a
367 | lsr a
368 | lsr a
369 | lsr a
370 | bne notSilenced
371 | silenced:
372 | lda #0
373 | sta 2
374 | rts
375 | notSilenced:
376 | sta 2
377 | lda noteInstrument,x
378 | asl a
379 | asl a
380 | tay
381 | lda 2
382 | eor instrumentTable,y
383 | and #$0F
384 | eor instrumentTable,y
385 | sta 2
386 | lda noteEnvVol,x
387 | sec
388 | sbc instrumentTable+1,y
389 | bcc silenced
390 | sta noteEnvVol,x
391 | lda notePitch,x
392 | sta 3
393 |
394 | ; bit 7 of attribute 2: cut note when half a row remains
395 | lda instrumentTable+2,y
396 | bpl notCutNote
397 | lda noteRowsLeft,x
398 | bne notCutNote
399 |
400 | clc
401 | lda tempoCounterLo
402 | adc #<(FRAMES_PER_MINUTE_NTSC/2)
403 | lda tempoCounterHi
404 | adc #>(FRAMES_PER_MINUTE_NTSC/2)
405 | bcc notCutNote
406 | lda #0
407 | sta noteEnvVol,x
408 |
409 | notCutNote:
410 | rts
411 | .endproc
412 |
413 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/musicseq.h:
--------------------------------------------------------------------------------
1 | ; Copyright 2010 Damian Yerrick
2 | ;
3 | ; Copying and distribution of this file, with or without
4 | ; modification, are permitted in any medium without royalty provided
5 | ; the copyright notice and this notice are preserved in all source
6 | ; code copies. This file is offered as-is, without any warranty.
7 |
8 | .global drumSFX, psg_sound_table
9 | .global musicPatternTable, instrumentTable, songTable
10 |
11 | N_C = 0*8
12 | N_CS = 1*8
13 | N_D = 2*8
14 | N_DS = 3*8
15 | N_E = 4*8
16 | N_F = 5*8
17 | N_FS = 6*8
18 | N_G = 7*8
19 | N_GS = 8*8
20 | N_A = 9*8
21 | N_AS = 10*8
22 | N_B = 11*8
23 | N_DB = N_CS
24 | N_EB = N_DS
25 | N_GB = N_FS
26 | N_AB = N_GS
27 | N_BB = N_AS
28 | N_CH = N_C + 12*8
29 | N_CSH = N_CS + 12*8
30 | N_DBH = N_DB + 12*8
31 | N_DH = N_D + 12*8
32 | N_DSH = N_DS + 12*8
33 | N_EBH = N_EB + 12*8
34 | N_EH = N_E + 12*8
35 | N_FH = N_F + 12*8
36 | N_FSH = N_FS + 12*8
37 | N_GBH = N_GB + 12*8
38 | N_GH = N_G + 12*8
39 | N_GSH = N_GS + 12*8
40 | N_ABH = N_AB + 12*8
41 | N_AH = N_A + 12*8
42 | N_ASH = N_AS + 12*8
43 | N_BBH = N_BB + 12*8
44 | N_BH = N_B + 12*8
45 | N_CHH = N_CH + 12*8
46 | N_TIE = 25*8
47 | REST = 26*8
48 | INSTRUMENT = $D8
49 |
50 | ; The default duration is one row (a sixteenth note in the tracker).
51 | ; OR the pitch with one of these constants.
52 | D_8 = 1
53 | D_D8 = 2
54 | D_4 = 3
55 | D_D4 = 4
56 | D_2 = 5
57 | D_D2 = 6
58 | D_1 = 7
59 |
60 | CON_PLAYPAT = $00 ; next: pattern, transpose (if not drums), instrument (if not drums)
61 | CON_LOOPPAT = $10 ; as CON_PLAYPAT
62 | CON_WAITROWS = $20 ; next: number of rows to wait minus 1
63 | CON_FINE = $21 ; stop music now
64 | CON_SEGNO = $22 ; set loop point
65 | CON_DALSEGNO = $23 ; jump to loop point. if no point was set, jump to start of song.
66 | CON_SETTEMPO = $30 ; low bits: bits 8-9 of tempo in rows/min; next: bits 0-7 of tempo
67 |
68 | ; Conductor macros
69 | .macro playPatSq1 patid, transpose, instrument
70 | .byt CON_PLAYPAT|0, patid, transpose, instrument
71 | .endmacro
72 | .macro playPatSq2 patid, transpose, instrument
73 | .byt CON_PLAYPAT|1, patid, transpose, instrument
74 | .endmacro
75 | .macro playPatTri patid, transpose, instrument
76 | .byt CON_PLAYPAT|2, patid, transpose, instrument
77 | .endmacro
78 | .macro playPatNoise patid, transpose, instrument
79 | .byt CON_PLAYPAT|3, patid, transpose, instrument
80 | .endmacro
81 | .macro stopPatSq1
82 | .byt CON_PLAYPAT|0, 255, 0, 0
83 | .endmacro
84 | .macro stopPatSq2
85 | .byt CON_PLAYPAT|1, 255, 0, 0
86 | .endmacro
87 | .macro stopPatTri
88 | .byt CON_PLAYPAT|2, 255, 0, 0
89 | .endmacro
90 | .macro stopPatNoise
91 | .byt CON_PLAYPAT|3, 255, 0, 0
92 | .endmacro
93 | .macro waitRows n
94 | .byt CON_WAITROWS, n-1
95 | .endmacro
96 | .macro fine
97 | .byt CON_FINE
98 | .endmacro
99 | .macro segno
100 | .byt CON_SEGNO
101 | .endmacro
102 | .macro dalSegno
103 | .byt CON_DALSEGNO
104 | .endmacro
105 | .macro setTempo rowsPerMin
106 | .byt CON_SETTEMPO|>rowsPerMin, practice_txt
29 | sta 1
30 | jsr display_textfile
31 | loop:
32 | ldx #0
33 | jsr moveCrosshairPlayerX
34 | jsr drawCrosshairPlayerX
35 | jsr drawPracticeMenuSprites
36 | jsr clearRestOfOAM
37 | jsr buildBGUpdate
38 | jsr update_sound
39 |
40 | lda nmis
41 | :
42 | cmp nmis
43 | beq :-
44 | ; it's vblank!
45 | jsr blitBGUpdate
46 | lda #0
47 | sta PPUSCROLL
48 | sta PPUSCROLL
49 | sta OAMADDR
50 | lda #>OAM
51 | sta OAM_DMA
52 | lda #VBLANK_NMI|BG_0000|OBJ_1000
53 | sta PPUCTRL
54 | lda #BG_ON|OBJ_ON
55 | sta PPUMASK
56 |
57 | jsr read_pads
58 | jsr mouse_to_vel
59 | lda new_keys
60 | and #KEY_A|KEY_B
61 | beq noClick
62 | jsr practiceDoClick
63 |
64 | noClick:
65 |
66 | lda gameState
67 | cmp #STATE_NEW_LEVEL
68 | bne noReloadLevel
69 | jsr practiceSetSide
70 | jsr doStateNewLevel
71 | lda #BG_DIRTY_STATUS|BG_DIRTY_HOUSES|BG_DIRTY_PRACTICE_METER
72 | ora bgDirty
73 | sta bgDirty
74 | noReloadLevel:
75 |
76 | lda new_keys
77 | and #KEY_START
78 | beq notStart
79 | lda #1
80 | sta isPractice
81 | notStart:
82 |
83 | lda isPractice
84 | cmp #2
85 | bcc done
86 | jmp loop
87 | done:
88 |
89 | ; clear the tip so that doStateLevelReward won't
90 | ; kick us out prematurely
91 | lda #0
92 | sta curTip
93 | lda #STATE_NEW_LEVEL
94 | sta gameState
95 | rts
96 | .endproc
97 |
98 | .proc practiceDoClick
99 | lda crosshairYHi
100 | cmp #$24
101 | bcc noClick1
102 | cmp #$34
103 | bcs noDayClick
104 |
105 | ; handle day click
106 | lda crosshairXHi
107 | sec
108 | sbc #60
109 | lsr a
110 | lsr a
111 | lsr a
112 | lsr a
113 | cmp #7
114 | bcs noClick1
115 | sta practiceDay
116 | sta gameDay
117 | lda #STATE_NEW_LEVEL
118 | sta gameState
119 | noClick1:
120 | rts
121 | noDayClick:
122 |
123 | cmp #$44
124 | bcs noHourClick
125 |
126 | ; handle hour click
127 | lda crosshairXHi
128 | sec
129 | sbc #60
130 | lsr a
131 | lsr a
132 | lsr a
133 | lsr a
134 | cmp #5
135 | bcs noClick1
136 | sta practiceHour
137 | sta gameHour
138 | lda #STATE_NEW_LEVEL
139 | sta gameState
140 | rts
141 | noHourClick:
142 |
143 | cmp #$5C
144 | bcc noClick1
145 | cmp #$7C
146 | bcs noSideClick
147 | sbc #$5C
148 | and #$10
149 | beq :+
150 | lda #1
151 | :
152 | sta 0
153 | lda crosshairXHi
154 | sec
155 | sbc #$38
156 | bmi noSideClick
157 | cmp #$30
158 | lda 0
159 | rol a
160 | sta practiceSide
161 | lda #STATE_NEW_LEVEL
162 | sta gameState
163 | rts
164 |
165 | noSideClick:
166 | cmp #$8C
167 | bcs noCancelPlayClick
168 | lda crosshairXHi
169 | cmp #176
170 | bcs noCancelPlayClick
171 | cmp #92
172 | lda #0
173 | rol a
174 | sta isPractice
175 |
176 | noCancelPlayClick:
177 | rts
178 |
179 | .endproc
180 |
181 | .proc practiceSetSide
182 | firstHouseOK = 0
183 | lastHouseOK = 1
184 |
185 | ; side 0: through 6; otherwise through 12
186 | lda #12
187 | ldy practiceSide ; keep side in y
188 | bne :+
189 | lda #6
190 | :
191 | sta lastHouseOK
192 |
193 | ; side 1: start at 6; otherwise start at 0
194 | lda #0
195 | cpy #1
196 | bne :+
197 | lda #6
198 | :
199 | sta firstHouseOK
200 |
201 | ; side 3: 2 players; otherwise 1 player
202 | lda #1
203 | cpy #3
204 | bne :+
205 | lda #2
206 | :
207 | sta numPlayers
208 |
209 | ldy #11
210 | sethouseloop:
211 | lda #0
212 | cpy firstHouseOK
213 | bcc houseNotOK
214 | cpy lastHouseOK
215 | bcs houseNotOK
216 | lda #1
217 | houseNotOK:
218 | sta housesStanding,y
219 | dey
220 | bpl sethouseloop
221 | rts
222 |
223 | .endproc
224 |
225 |
226 | .proc drawPracticeMenuSprites
227 | ldx oamIndex
228 |
229 | lda #39
230 | sta OAM,x
231 | lda #55
232 | sta OAM+4,x
233 | lda practiceSide
234 | and #$02
235 | asl a
236 | asl a
237 | asl a
238 | adc #95
239 | sta OAM+8,x
240 |
241 | ; set x coords
242 | lda gameDay
243 | asl a
244 | asl a
245 | asl a
246 | asl a
247 | adc #60
248 | sta OAM+3,x
249 | lda gameHour
250 | asl a
251 | asl a
252 | asl a
253 | asl a
254 | adc #60
255 | sta OAM+7,x
256 | lda practiceSide
257 | and #$01
258 | beq :+
259 | lda #48
260 | :
261 | clc
262 | adc #60
263 | sta OAM+11,x
264 |
265 | lda #SELECTED_ARROW_TILE
266 | sta OAM+1,x
267 | sta OAM+5,x
268 | sta OAM+9,x
269 | lda #%00100001 ; behind; color set 1
270 | sta OAM+2,x
271 | sta OAM+6,x
272 | sta OAM+10,x
273 |
274 | txa
275 | clc
276 | adc #12
277 | tax
278 |
279 | ; At this point, draw the possible salvos
280 |
281 | salvoID = 0
282 | salvoY = 1
283 | salvoX = 2
284 |
285 | lda #0
286 | sta salvoID
287 | lda #39
288 | sta salvoY
289 | salvoLoop:
290 | lda #192
291 | sta salvoX
292 | ldy salvoID
293 | lda levelSalvoSizes,y
294 | cmp #8
295 | beq isBalloon
296 | bcs isMIRV
297 |
298 | ; Regular missiles; draw each
299 | tay
300 | salvoElLoop:
301 | lda #$0A
302 | mirvFinish:
303 | sta OAM+1,x
304 | lda salvoY
305 | sta OAM+0,x
306 | lda #$01
307 | sta OAM+2,x
308 | lda salvoX
309 | sta OAM+3,x
310 | clc
311 | adc #6
312 | sta salvoX
313 | inx
314 | inx
315 | inx
316 | inx
317 | dey
318 | bne salvoElLoop
319 | lda #12
320 | bne salvoAddToY
321 |
322 | isMIRV:
323 | ldy #1
324 | lda #$1A
325 | bne mirvFinish
326 |
327 | isBalloon:
328 | lda salvoY
329 | sta OAM+0,x
330 | clc
331 | adc #8
332 | sta OAM+4,x
333 | lda #$06
334 | sta OAM+1,x
335 | lda #$16
336 | sta OAM+5,x
337 | lda #$01
338 | sta OAM+2,x
339 | lsr a
340 | sta OAM+6,x
341 | lda salvoX
342 | sta OAM+3,x
343 | sta OAM+7,x
344 | txa
345 | clc
346 | adc #8
347 | tax
348 | lda #20
349 |
350 | salvoAddToY:
351 | clc
352 | adc salvoY
353 | sta salvoY
354 | inc salvoID
355 | lda salvoID
356 | cmp #4
357 | bcc salvoLoop
358 | stx oamIndex
359 | rts
360 | .endproc
361 |
362 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/practice.txt:
--------------------------------------------------------------------------------
1 | thwaite: practice
2 |
3 | Day: S M T W R F S
4 |
5 | Hour: 1 2 3 4 5
6 |
7 | Ammo Speed Delay
8 |
9 |
10 | Side: Left Right
11 |
12 | Both 2 Players
13 |
14 | (Cancel) (Play)
15 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/ram.h:
--------------------------------------------------------------------------------
1 | ; Copyright 2011 Damian Yerrick
2 | ;
3 | ; Copying and distribution of this file, with or without
4 | ; modification, are permitted in any medium without royalty provided
5 | ; the copyright notice and this notice are preserved in all source
6 | ; code copies. This file is offered as-is, without any warranty.
7 |
8 | xferBuf = $0100
9 | OAM = $0200
10 |
11 | ; Turn this on to replace the upper left tile of a threatened
12 | ; building with a !
13 | SHOW_THREATENED = 0
14 |
15 | ; Turn this on to annoy Nova
16 | CHECK_ILLEGAL_MISSILES = 1
17 | ILLEGAL_MISSILES_TIP = 13
18 |
19 | ; main fields
20 | STATE_INACTIVE = 0
21 | STATE_NEW_LEVEL = 1
22 | STATE_ACTIVE = 2
23 | STATE_LEVEL_REWARD = 3
24 | STATE_REBUILDING_SILO = 4
25 | STATE_CUTSCENE = 5
26 | STATE_REBUILDING_HOUSE = 6
27 | STATE_GAMEOVER = 7
28 | .globalzp nmis, oamIndex, numPlayers, tvSystem, mouseEnabled
29 | .globalzp debugHex1, debugHex2
30 | .globalzp gameState
31 | ; main methods
32 | .global clearRestOfOAM, doStateNewLevel
33 |
34 | ; pads fields
35 | .globalzp cur_keys, new_keys, das_timer, das_keys
36 | ; pads methods
37 | .global read_pads, autorepeat
38 |
39 | ; mouse fields
40 | .globalzp cur_mbuttons, new_mbuttons
41 | ; mouse methods
42 | .global read_mouse, mouse_change_sensitivity
43 |
44 | ; title constants
45 | SELECTED_ARROW_TILE = $02
46 | ; title methods
47 | .global titleScreen, display_textfile
48 |
49 | ; unpkb methods
50 | .global PKB_unpackblk
51 |
52 | ; random fields
53 | .globalzp rand0, rand1, rand2, rand3
54 | ; random methods
55 | .global random, initRandomTarget, chooseRandomTarget
56 | .global findRandomDestroyedHouse
57 |
58 | ; bg constants
59 | NUM_BUILDINGS = 12
60 | BG_DIRTY_HOUSES = $01
61 | BG_DIRTY_STATUS = $02
62 | BG_DIRTY_TIP = $04
63 | BG_DIRTY_PRACTICE_METER = $08
64 | BUILDING_DESTROYED = 0
65 | BUILDING_OK = 1
66 | BUILDING_THREATENED = 2
67 | ; bg fields
68 | .global housesStanding, houseX, score1s, score100s
69 | .global gameDay, gameHour, gameMinute, gameSecond, gameTenthSecond, gameSubTenth
70 | .global bgDirty, curTip, tipTimeLeft
71 | .global buildingsDestroyedThisLevel, firstDestroyedHouse
72 | .global main_palette
73 | ; bg methods
74 | .global setupGameBG, blitBGUpdate, buildBGUpdate, buildLevelRewardBar
75 | .global buildHouseRebuiltBar
76 | .global newGame, addScore, incGameClock, countHousesLeft
77 | .global puthex
78 |
79 | ; missiles constants
80 | ; missiles 0 and 2 are player 1's
81 | ; missiles 1 and 3 are player 2's
82 | ; missiles 4 through NUM_MISSILES - 1 are the enemy missiles
83 | NUM_MISSILES = 20
84 | MISSILE_SPAWN_Y = 8
85 | BALLOON_SPAWN_Y = 40 ; in range 0-63 plus this
86 | SILO_Y = 192 ; player missiles launch from here
87 | BUILDING_HIT_Y = 200
88 | ; missiles fields
89 | .global crosshairXLo, crosshairXHi, crosshairDXLo, crosshairDXHi
90 | .global crosshairYLo, crosshairYHi, crosshairDYLo, crosshairDYHi
91 | .global missileXLo, missileXHi, missileYLo, missileYHi
92 | .global missileDYHi, missileDYLo
93 | .global missileType, missileTarget, missileTime, missileAngle
94 | ; and about 400 bytes of free space to use when missiles
95 | ; are not active
96 | .global missilesOverlay
97 |
98 | ; missiles methods
99 | .global clearAllMissiles, updateMissiles
100 | .global moveCrosshairPlayerX, drawCrosshairPlayerX, mouse_to_vel
101 | .global makeMissile, makeBalloon, firePlayerMissile
102 | .global siloMissilesLeft
103 |
104 | ; explosion constants
105 | NUM_EXPLOSIONS = 8
106 | ; explosion methods
107 | .global clearExplosions, makeExplosion, updateAllExplosions
108 |
109 | ; smoke methods
110 | .global makeSmoke, clearAllSmoke, updateSmoke
111 |
112 | ; math fields
113 | .global missileSine, missileCosine
114 | ; math methods
115 | .global getAngle, getSlope1, mul8, measureFromSilo
116 |
117 | ; bcd methods
118 | .global bcd8bit
119 |
120 | ; levels constants
121 | .globalzp NUM_MADE_DAYS, SKIP_TO_DAY
122 | ; levels fields
123 | .global levelMissileSpeed, enemyMissilesLeft, levelReleasePeriod
124 | .global levelMissileTypes, levelSalvoSizes
125 | ; levels methods
126 | .global loadLevel
127 |
128 | ; scurry constants
129 | NUM_VILLAGERS = NUM_BUILDINGS
130 | ; scurry methods
131 | .global initVillagers, updateVillagers
132 | .global testMissileThreats
133 | .global villagersGoHome, warpVillagersToTargets
134 |
135 | ; paldetect constants
136 | TV_SYSTEM_NTSC = 0
137 | TV_SYSTEM_PAL = 1
138 | TV_SYSTEM_DENDY = 2
139 | TV_SYSTEM_OTHER = 3
140 | ; paldetect methods
141 | .global getTVSystem
142 |
143 | ; sound constants
144 | MUSIC_CLEARED_LEVEL = 5
145 | MUSIC_1600 = 6
146 |
147 | SFX_SPLIT = 0
148 | SFX_ALERT_A = 4
149 | SFX_ALERT_B = 5
150 | SFX_LAUNCH = 6
151 | SFX_BOOM_SQUARE = 7
152 | SFX_BOOM_NOISE = 8
153 | ; sound methods
154 | .global init_sound, start_sound, update_sound, init_music, stop_music
155 |
156 | ; cutscene fields
157 | .global character_name_offset, character_name0
158 | .global actor_paranoid
159 | ; cutscene methods
160 | .global load_cutscene, cut_choose_villagers
161 |
162 | ; kinematics args
163 | abl_vel = 0
164 | abl_maxVel = 2
165 | abl_brakeRate = 4
166 | abl_accelRate = 5
167 | abl_keys = 6
168 | ; kinematics methods
169 | .global accelBrakeLimit
170 |
171 | ; practice fields
172 | .globalzp isPractice, practiceSide
173 | ; practice methods
174 | .global practice_menu
175 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/random.s:
--------------------------------------------------------------------------------
1 | ;
2 | ; Target selection for Thwaite
3 | ; Copyright (C) 2011 Damian Yerrick
4 | ;
5 | ; This program is free software: you can redistribute it and/or modify
6 | ; it under the terms of the GNU General Public License as published by
7 | ; the Free Software Foundation, either version 3 of the License, or
8 | ; (at your option) any later version.
9 | ;
10 | ; This program is distributed in the hope that it will be useful,
11 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ; GNU General Public License for more details.
14 | ;
15 | ; You should have received a copy of the GNU General Public License
16 | ; along with this program. If not, see .
17 | ;
18 | .include "src/ram.h"
19 | ;.include "src/nes.h" ; for debugging high level shit
20 | .segment "ZEROPAGE"
21 | rand0: .res 1
22 | rand1: .res 1
23 | rand2: .res 1
24 | rand3: .res 1
25 | lastTarget: .res 1
26 | lruTargets: .res NUM_BUILDINGS
27 |
28 | .segment "CODE"
29 | ;; random
30 | ; Uses the crc32 polynomial to generate Y
31 | ; pseudorandom bits as the low_order bits of rand3.
32 | ; Average 48 cycles per bit.
33 | ;
34 | .proc random
35 | asl rand3
36 | rol rand2
37 | rol rand1
38 | rol rand0
39 | bcc @no_xor
40 | lda rand0
41 | eor #$04
42 | sta rand0
43 | lda rand1
44 | eor #$c1
45 | sta rand1
46 | lda rand2
47 | eor #$1d
48 | sta rand2
49 | lda rand3
50 | eor #$b7
51 | sta rand3
52 | @no_xor:
53 | dey
54 | bne random
55 | rts
56 | .endproc
57 |
58 | .proc chooseRandomTarget
59 | ldy #3
60 | jsr random
61 | lda #$07
62 | and rand3
63 | clc
64 | adc #NUM_BUILDINGS - 8
65 | tay
66 | lda lruTargets,y
67 | pha
68 | loop:
69 | lda lruTargets-1,y
70 | sta lruTargets,y
71 | dey
72 | bne loop
73 | pla
74 | sta lruTargets
75 | rts
76 | .endproc
77 |
78 | .proc initRandomTarget
79 | ldy #NUM_BUILDINGS - 1
80 | :
81 | lda initLRUData,y
82 | sta lruTargets,y
83 | dey
84 | bpl :-
85 | rts
86 | .endproc
87 |
88 | .proc findRandomDestroyedHouse
89 | ldx #NUM_BUILDINGS - 2
90 | stx 0
91 | ldy #3
92 | jsr random
93 | lda #$07
94 | and rand3
95 | clc
96 | adc #2
97 | tax
98 | searchloop:
99 | lda initLRUData,x
100 | tay
101 | lda housesStanding,y
102 | beq found
103 | inx
104 | cpx #NUM_BUILDINGS
105 | bcc :+
106 | ldx #2
107 | :
108 | dec 0
109 | bne searchloop
110 | ldy #$FF
111 | found:
112 | rts
113 | .endproc
114 |
115 | .segment "RODATA"
116 | ; Initial LRU data for chooseRandomTarget. Putting 2, 9 at the
117 | ; front helps new players by not immediately blowing up the silos.
118 | initLRUData:
119 | .byt 2, 9, 11, 0, 1, 10, 8, 3, 4, 7, 6, 5
120 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/smoke.s:
--------------------------------------------------------------------------------
1 | ; smoke.s
2 | ; Dissipating smoke drawing functions for Thwaite
3 |
4 | ;;; Copyright (C) 2011 Damian Yerrick
5 | ;
6 | ; This program is free software; you can redistribute it and/or
7 | ; modify it under the terms of the GNU General Public License
8 | ; as published by the Free Software Foundation; either version 3
9 | ; of the License, or (at your option) any later version.
10 | ;
11 | ; This program is distributed in the hope that it will be useful,
12 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ; GNU General Public License for more details.
15 | ;
16 | ; You should have received a copy of the GNU General Public License
17 | ; along with this program; if not, write to
18 | ; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | ; Boston, MA 02111-1307, USA.
20 | ;
21 | ; Visit http://www.pineight.com/ for more information.
22 |
23 | .include "src/nes.h"
24 | .include "src/ram.h"
25 |
26 | NUM_SMOKE = 48
27 | FIRST_SMOKE_TILE = $10
28 | SMOKE_PALETTE = $23
29 | .segment "BSS"
30 | smokeX: .res NUM_SMOKE
31 | smokeY: .res NUM_SMOKE
32 | smokeSpeed: .res NUM_SMOKE
33 | smokeTime: .res NUM_SMOKE
34 |
35 | .segment "CODE"
36 | ;;
37 | ; Makes a smoke particle at (x, y) with dissipation speed a.
38 | .proc makeSmoke
39 | xpos = 0
40 | ypos = 1
41 | dissipSpeed = 2
42 | sta dissipSpeed
43 | txa
44 | clc
45 | adc #252
46 | bcc cancelSmoke
47 | sta xpos
48 | tya
49 | adc #250
50 | sta ypos
51 | bcc cancelSmoke
52 |
53 | ; Look for the best slot for this explosion.
54 | ; The "best" slot is the one whose explosion has been on screen
55 | ; the longest.
56 | ; y holds the index of the best slot so far
57 | ; x holds the index of the slot currently being considered
58 | ldx #NUM_SMOKE - 2
59 | ldy #NUM_SMOKE - 1
60 |
61 | findFreeSlot:
62 | ; if the time in x is less than the time in y, y is a better slot
63 | lda smokeTime,x
64 | cmp smokeTime,y
65 | bcc notBetterSlot
66 | ; otherwise x is a better slot, so set y to x
67 | txa
68 | tay
69 | notBetterSlot:
70 | dex
71 | bpl findFreeSlot
72 | lda dissipSpeed
73 | sta smokeSpeed,y
74 | lda #0
75 | sta smokeTime,y
76 | lda xpos
77 | sta smokeX,y
78 | lda ypos
79 | sta smokeY,y
80 | cancelSmoke:
81 | rts
82 | .endproc
83 |
84 | .proc updateSmoke
85 | lda nmis
86 | and #$01
87 | clc
88 | adc #NUM_SMOKE - 2
89 | tax
90 | ldy oamIndex
91 | smokeloop:
92 | ; set tile number if the particle is still active
93 | lda smokeTime,x
94 | cmp #5*32
95 | bcs smokecontinue
96 | lsr a
97 | lsr a
98 | lsr a
99 | lsr a
100 | lsr a
101 | clc
102 | adc #FIRST_SMOKE_TILE
103 | sta OAM+1,y
104 |
105 | ; set (pretransformed) coordinates
106 | lda smokeY,x
107 | sta OAM,y
108 | lda smokeX,x
109 | sta OAM+3,y
110 |
111 | ; put bits 2-1 of vblank count into smoke's flip bits
112 | lda nmis
113 | ror a
114 | ror a
115 | ror a
116 | ror a
117 | and #$C0
118 | ora #SMOKE_PALETTE
119 | sta OAM+2,y
120 | lda smokeTime,x
121 | clc
122 | adc smokeSpeed,x
123 | sta smokeTime,x
124 | iny
125 | iny
126 | iny
127 | iny
128 | beq bail
129 | smokecontinue:
130 | dex
131 | dex
132 | bpl smokeloop
133 | bail:
134 | sty oamIndex
135 | rts
136 | .endproc
137 |
138 | .proc clearAllSmoke
139 | ldy #NUM_SMOKE - 1
140 | lda #$FF
141 | loop:
142 | sta smokeTime,y
143 | dey
144 | bpl loop
145 | rts
146 | .endproc
147 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/sound.s:
--------------------------------------------------------------------------------
1 | ; sound.s
2 | ; part of sound engine for LJ65, Concentration Room, and Thwaite
3 |
4 | ;;; Copyright (C) 2009-2011 Damian Yerrick
5 | ;
6 | ; This program is free software; you can redistribute it and/or
7 | ; modify it under the terms of the GNU General Public License
8 | ; as published by the Free Software Foundation; either version 3
9 | ; of the License, or (at your option) any later version.
10 | ;
11 | ; This program is distributed in the hope that it will be useful,
12 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ; GNU General Public License for more details.
15 | ;
16 | ; You should have received a copy of the GNU General Public License
17 | ; along with this program; if not, write to
18 | ; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | ; Boston, MA 02111-1307, USA.
20 | ;
21 | ; Visit http://www.pineight.com/ for more information.
22 |
23 | .import periodTableLo, periodTableHi
24 | .importzp psg_sfx_state ; a 32 byte buffer in zp?
25 | .import update_music, update_music_ch, music_playing, psg_sound_table
26 | .export init_sound, start_sound, update_sound, soundBSS
27 |
28 | SNDCHN = $4015
29 |
30 | ; Ordinarily, the effect engine will move a pulse sound effect from
31 | ; $4000 to $4004 if $4004 is idle and $4000 is not, or if $4004 has
32 | ; less sfx data left to play than $4000. Turn this off to force all
33 | ; pulse sfx to be played on $4000.
34 | SQUARE_POOLING = 1
35 |
36 | ; As of 2011-03-10, a sound effect interrupts a musical instrument on
37 | ; the same channel only if the volume of the sfx is greater than that
38 | ; of the instrument. Turn this off to force sound fx to interrupt
39 | ; the music whenever sfx data remains on that channel, even if the
40 | ; music is louder.
41 | KEEP_MUSIC_IF_LOUDER = 1
42 |
43 | .segment "BSS"
44 | soundBSS: .res 64
45 |
46 | psg_sfx_datalo = psg_sfx_state + 0
47 | psg_sfx_datahi = psg_sfx_state + 1
48 | psg_sfx_lastfreqhi = psg_sfx_state + 18
49 | psg_sfx_remainlen = psg_sfx_state + 19
50 | psg_sfx_rate = soundBSS + 3
51 | psg_sfx_ratecd = soundBSS + 19
52 |
53 | .ifndef SOUND_NTSC_ONLY
54 | SOUND_NTSC_ONLY = 0
55 | .endif
56 | .if (!SOUND_NTSC_ONLY)
57 | .importzp tvSystem
58 | .endif
59 |
60 | .segment "CODE"
61 |
62 | ;;
63 | ; Initializes all sound channels.
64 | ; Use it at the start of a program or as a "panic button" before
65 | ; entering a long stretch of code where you don't update_sound.
66 | ;
67 | .proc init_sound
68 | lda #$0F
69 | sta SNDCHN
70 | lda #$30
71 | sta $4000
72 | sta $4004
73 | sta $400C
74 | sta psg_sfx_lastfreqhi+0
75 | sta psg_sfx_lastfreqhi+8
76 | sta psg_sfx_lastfreqhi+4
77 | lda #$80
78 | sta $4008
79 | lda #8
80 | sta $4001
81 | sta $4005
82 | lda #0
83 | sta $4003
84 | sta $4007
85 | sta $400F
86 | sta psg_sfx_remainlen+0
87 | sta psg_sfx_remainlen+4
88 | sta psg_sfx_remainlen+8
89 | sta psg_sfx_remainlen+12
90 | sta music_playing
91 | lda #64
92 | sta $4011
93 | rts
94 | .endproc
95 |
96 | ;;
97 | ; Starts a sound effect.
98 | ; (Trashes $0000-$0004 and X.)
99 | ;
100 | ; @param A sound effect number (0-63)
101 | ;
102 | .proc start_sound
103 | snddatalo = 0
104 | snddatahi = 1
105 | sndchno = 2
106 | sndlen = 3
107 | sndrate = 4
108 |
109 | asl a
110 | asl a
111 | tax
112 | lda psg_sound_table,x
113 | sta snddatalo
114 | lda psg_sound_table+1,x
115 | sta snddatahi
116 | lda psg_sound_table+2,x
117 | and #$0C
118 | sta sndchno
119 | lda psg_sound_table+2,x
120 | lsr a
121 | lsr a
122 | lsr a
123 | lsr a
124 | sta sndrate
125 |
126 | lda psg_sound_table+3,x
127 | sta sndlen
128 |
129 | ; split up square wave sounds between $4000 and $4004
130 | .if ::SQUARE_POOLING
131 | lda sndchno
132 | bne not_ch0to4 ; if not ch 0, don't try moving it
133 | lda psg_sfx_remainlen+4
134 | cmp psg_sfx_remainlen
135 | bcs not_ch0to4
136 | lda #4
137 | sta sndchno
138 | not_ch0to4:
139 | .endif
140 |
141 | ldx sndchno
142 | lda sndlen
143 | cmp psg_sfx_remainlen,x
144 | bcs ch_not_full
145 | rts
146 | ch_not_full:
147 |
148 | lda snddatalo
149 | sta psg_sfx_datalo,x
150 | lda snddatahi
151 | sta psg_sfx_datahi,x
152 | lda sndlen
153 | sta psg_sfx_remainlen,x
154 | lda sndrate
155 | sta psg_sfx_rate,x
156 | lda #0
157 | sta psg_sfx_ratecd,x
158 | rts
159 | .endproc
160 |
161 |
162 | ;;
163 | ; Updates sound effect channels.
164 | ;
165 | .proc update_sound
166 | jsr update_music
167 | ldx #12
168 | loop:
169 | jsr update_music_ch
170 | jsr update_one_ch
171 | dex
172 | dex
173 | dex
174 | dex
175 | bpl loop
176 | rts
177 | .endproc
178 |
179 | .proc update_one_ch
180 |
181 | ; At this point, the music engine should have left duty and volume
182 | ; in 2 and pitch in 3.
183 | lda psg_sfx_remainlen,x
184 | bne ch_not_done
185 | lda 2
186 | bne update_channel_hw
187 |
188 | ; Turn off the channel and force a reinit of the length counter.
189 | cpx #8
190 | beq not_triangle_kill
191 | lda #$30
192 | not_triangle_kill:
193 | sta $4000,x
194 | lda #$FF
195 | sta psg_sfx_lastfreqhi,x
196 | rts
197 | ch_not_done:
198 |
199 | ; playback rate divider
200 | dec psg_sfx_ratecd,x
201 | bpl rate_divider_cancel
202 | lda psg_sfx_rate,x
203 | sta psg_sfx_ratecd,x
204 |
205 | ; fetch the instruction
206 | lda psg_sfx_datalo+1,x
207 | sta 1
208 | lda psg_sfx_datalo,x
209 | sta 0
210 | clc
211 | adc #2
212 | sta psg_sfx_datalo,x
213 | bcc :+
214 | inc psg_sfx_datahi,x
215 | :
216 | ldy #0
217 | .if ::KEEP_MUSIC_IF_LOUDER
218 | lda 2
219 | and #$0F
220 | sta 4
221 | lda (0),y
222 | and #$0F
223 |
224 | ; At this point: A = sfx volume; 4 = musc volume
225 | cmp 4
226 | bcc music_was_louder
227 | .endif
228 | lda (0),y
229 | sta 2
230 | iny
231 | lda (0),y
232 | sta 3
233 | music_was_louder:
234 | dec psg_sfx_remainlen,x
235 |
236 | update_channel_hw:
237 | lda 2
238 | ora #$30
239 | cpx #12
240 | bne notnoise
241 | sta $400C
242 | lda 3
243 | sta $400E
244 | rate_divider_cancel:
245 | rts
246 |
247 | notnoise:
248 | sta $4000,x
249 | ldy 3
250 | .ifndef ::SOUND_NTSC_ONLY
251 | lda tvSystem
252 | beq :+
253 | iny
254 | :
255 | .endif
256 | lda periodTableLo,y
257 | sta $4002,x
258 | lda periodTableHi,y
259 | cmp psg_sfx_lastfreqhi,x
260 | beq no_change_to_hi_period
261 | sta psg_sfx_lastfreqhi,x
262 | sta $4003,x
263 | no_change_to_hi_period:
264 |
265 | rts
266 | .endproc
267 |
268 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/tips.s:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/src/tips.s
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/title.pkb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/src/title.pkb
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/title.s:
--------------------------------------------------------------------------------
1 | ;
2 | ; title.s
3 | ; title screen code for Thwaite
4 |
5 | ;;; Copyright (C) 2011 Damian Yerrick
6 | ;
7 | ; This program is free software; you can redistribute it and/or
8 | ; modify it under the terms of the GNU General Public License
9 | ; as published by the Free Software Foundation; either version 3
10 | ; of the License, or (at your option) any later version.
11 | ;
12 | ; This program is distributed in the hope that it will be useful,
13 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ; GNU General Public License for more details.
16 | ;
17 | ; You should have received a copy of the GNU General Public License
18 | ; along with this program; if not, write to
19 | ; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 | ; Boston, MA 02111-1307, USA.
21 | ;
22 | ; Visit http://www.pineight.com/ for more information.
23 |
24 | .include "src/nes.h"
25 | .include "src/ram.h"
26 |
27 | B_TO_RESET = 0
28 |
29 | .segment "CODE"
30 | ;;
31 | ; Displays the text file pointed to at (0)
32 | ; starting at (2, 3) on nametable $2000.
33 | .proc display_textfile
34 | src = 0
35 | dstLo = 2
36 | dstHi = 3
37 | lda #$20
38 | sta dstHi
39 | lda #$62
40 | sta dstLo
41 | txt_rowloop:
42 | ldy dstHi
43 | sty PPUADDR
44 | ldy dstLo
45 | sty PPUADDR
46 | ldy #0
47 | txt_charloop:
48 | lda (src),y
49 | beq txt_done
50 | cmp #$0A
51 | beq is_newline
52 | sta PPUDATA
53 | iny
54 | bne txt_charloop
55 | is_newline:
56 |
57 | sec
58 | tya
59 | adc src+0
60 | sta src+0
61 | lda src+1
62 | adc #0
63 | sta src+1
64 | lda dstLo
65 | adc #32
66 | sta dstLo
67 | lda dstHi
68 | adc #0
69 | sta dstHi
70 | cmp #$23
71 | bcc txt_rowloop
72 | lda dstLo
73 | cmp #$C0
74 | bcc txt_rowloop
75 |
76 | txt_done:
77 | rts
78 | .endproc
79 |
80 | .proc display_todo
81 | lda #VBLANK_NMI
82 | ldx #$00
83 | ldy #$3F
84 | sta PPUCTRL
85 | stx PPUMASK
86 | sty PPUADDR
87 | stx PPUADDR
88 | copypal:
89 | lda title_palette,x
90 | sta PPUDATA
91 | inx
92 | cpx #32
93 | bcc copypal
94 |
95 | ; clear nt
96 | ldy #$20
97 | sty PPUADDR
98 | ldy #$00
99 | sty PPUADDR
100 | tya
101 | :
102 | sta PPUDATA
103 | sta PPUDATA
104 | sta PPUDATA
105 | sta PPUDATA
106 | dey
107 | bne :-
108 |
109 | lda #>todo_txt
110 | sta 1
111 | lda #title_pkb
180 | sta 1
181 | ldx #$20
182 | stx PPUADDR
183 | ldy #$00
184 | sty PPUADDR
185 | jsr PKB_unpackblk
186 |
187 | lda #$F0
188 | ldx #$04
189 | :
190 | sta OAM,x
191 | inx
192 | bne :-
193 |
194 | loop:
195 | jsr title_draw_sprites
196 | lda nmis
197 | :
198 | cmp nmis
199 | beq :-
200 | bit PPUSTATUS
201 |
202 | ldy #0
203 | lda #VBLANK_NMI|BG_0000|OBJ_1000
204 | ldx #>OAM
205 | sty OAMADDR
206 | sty PPUSCROLL
207 | sty PPUSCROLL
208 | sta PPUCTRL
209 | stx OAM_DMA
210 |
211 | ldx #BG_ON|OBJ_ON
212 | stx PPUMASK
213 |
214 | jsr update_sound
215 | jsr read_pads
216 | jsr title_detect_mice
217 |
218 | s0wait0:
219 | bit $2002
220 | bvs s0wait0
221 | s0wait1:
222 | bit $2002
223 | bmi s0waitfail
224 | bvc s0wait1
225 | lda #VBLANK_NMI|BG_1000|OBJ_1000
226 | sta PPUCTRL
227 | s0waitfail:
228 |
229 | jsr title_move_numPlayers
230 |
231 | .if ::B_TO_RESET
232 | lda new_keys
233 | and #KEY_B
234 | beq notB
235 | jmp ($FFFC)
236 | notB:
237 | .endif
238 |
239 | ; Let the buttons of the first mouse
240 | ldx #0
241 | lda mouseEnabled,x
242 | bne handleClick
243 | inx
244 | lda mouseEnabled,x
245 | bne handleClick
246 | doneClick:
247 | lda new_keys+0
248 | and #(KEY_START | KEY_A)
249 | beq loop
250 | done:
251 |
252 | ; mix the current time into the rng
253 | lda nmis
254 | eor rand3
255 | clc
256 | adc rand1
257 | sta rand1
258 | ldy #8
259 | jmp random ; and off we go, done with the title screen
260 |
261 | ; Appendix: How to handle mouse clicks
262 | handleClick:
263 | lda new_mbuttons,x
264 | and #MOUSE_L
265 | beq doneClick
266 | lda crosshairYHi+0
267 | sec
268 | sbc #128
269 | lsr a
270 | lsr a
271 | lsr a
272 | lsr a
273 |
274 | ; Row 0: Change speed
275 | ; Row 1: 1 player; 2: 2 player; 3: Practice
276 | beq changeSpd
277 | cmp #4
278 | bcs doneClick
279 | sta numPlayers
280 | jmp done
281 | changeSpd:
282 | ldx #0
283 | lda crosshairXHi+0
284 | bpl :+
285 | inx
286 | :
287 | jsr mouse_change_sensitivity
288 | jmp doneClick
289 | .endproc
290 |
291 | ;;
292 | ; Checks for the signature of a Super NES Mouse, which is $x1
293 | ; on the second read report.
294 | ; Stores 0 for no mouse or 1-3 for mouse sensitivity 1/4, 1/2, 1
295 | .proc title_detect_mice
296 | lda #0
297 | sta 4
298 | sta 5
299 | ldx #1
300 | loop:
301 | jsr read_mouse
302 | lda 1
303 | and #$0F
304 | cmp #1
305 | bne notMouse
306 | lda 2
307 | sta 4
308 | lda 3
309 | sta 5
310 | lda 1
311 | and #$30
312 | lsr a
313 | lsr a
314 | lsr a
315 | lsr a
316 | clc
317 | adc #1
318 | bne isMouse
319 | notMouse:
320 | lda #0
321 | isMouse:
322 | sta mouseEnabled,x
323 | dex
324 | bpl loop
325 |
326 | ; If a mouse is connected, 4 will have Y motion and 5 will have
327 | ; X motion
328 |
329 | lda 4
330 | bpl mouseNotDown
331 | eor #$7F
332 | clc
333 | adc #$01
334 | mouseNotDown:
335 | clc
336 | adc crosshairYHi+0
337 | cmp #128
338 | bcs noClipTop
339 | lda #128
340 | noClipTop:
341 | cmp #191
342 | bcc noClipBottom
343 | lda #191
344 | noClipBottom:
345 | sta crosshairYHi+0
346 |
347 | lda 5
348 | bpl mouseNotLeft
349 | eor #$7F
350 | clc
351 | adc #$01
352 | mouseNotLeft:
353 | clc
354 | adc crosshairXHi+0
355 | cmp #48
356 | bcs noClipLeft
357 | lda #48
358 | noClipLeft:
359 | cmp #207
360 | bcc noClipRight
361 | lda #207
362 | noClipRight:
363 | sta crosshairXHi+0
364 | rts
365 | .endproc
366 |
367 | .proc title_move_numPlayers
368 | ldx numPlayers
369 | lda new_keys
370 | and #KEY_SELECT
371 | beq notSelect
372 | inx
373 | cpx #4
374 | bcc notSelect
375 | ldx #1
376 | notSelect:
377 |
378 | lda new_keys
379 | and #KEY_DOWN
380 | beq notDown
381 | inx
382 | cpx #4
383 | bcc notDown
384 | dex
385 | notDown:
386 |
387 | lda new_keys
388 | and #KEY_UP
389 | beq notUp
390 | dex
391 | bne notUp
392 | inx
393 | notUp:
394 |
395 | stx numPlayers
396 | rts
397 | .endproc
398 |
399 | .proc title_draw_sprites
400 | ldx oamIndex
401 |
402 | lda mouseEnabled
403 | ora mouseEnabled+1
404 | beq noMouseCrosshair
405 | lda crosshairYHi+0
406 | sec
407 | sbc #5
408 | sta OAM,x
409 | lda crosshairXHi+0
410 | sec
411 | sbc #4
412 | sta OAM+3,x
413 | lda #4
414 | sta OAM+1,x
415 | lda #0
416 | sta OAM+2,x
417 |
418 | inx
419 | inx
420 | inx
421 | inx
422 | noMouseCrosshair:
423 |
424 | ; Draw arrow for number of players
425 | lda numPlayers
426 | asl a
427 | asl a
428 | asl a
429 | asl a
430 | pha
431 | lda nmis
432 | lsr a
433 | pla
434 | adc #130
435 | sta OAM+0,x
436 | lda #SELECTED_ARROW_TILE
437 | sta OAM+1,x
438 | lda #1
439 | sta OAM+2,x
440 | lda #76
441 | sta OAM+3,x
442 | txa
443 | clc
444 | adc #4
445 | tax
446 |
447 | ldy #1
448 | miceloop:
449 | lda mouseEnabled,y
450 | beq not_mouse
451 | jsr draw_mouse_player_y
452 |
453 | not_mouse:
454 | dey
455 | bpl miceloop
456 |
457 | stx oamIndex
458 | jsr clearRestOfOAM
459 |
460 | ; draw sprite 0, used to switch in CHR for "1 Player" text
461 | ; (which is written in FH, 15px autohinted)
462 | lda #102
463 | sta OAM+0
464 | lda #$01
465 | sta OAM+1
466 | lda #$23 ; black sprite on black bg, behind
467 | sta OAM+2
468 | lda #172
469 | sta OAM+3
470 | rts
471 |
472 | draw_mouse_player_y:
473 | ; Y coordinate
474 | lda #127
475 | sta OAM+0,x
476 | sta OAM+4,x
477 | sta OAM+8,x
478 | sta OAM+12,x
479 | lda #135
480 | sta OAM+16,x
481 | sta OAM+20,x
482 | sta OAM+24,x
483 | sta OAM+28,x
484 |
485 | ; Tile numbers
486 | tya
487 | ora #$60
488 | sta OAM+1,x
489 | ora #$10
490 | sta OAM+17,x
491 | lda mouseEnabled,y
492 | clc
493 | adc #$56
494 | sta OAM+13,X
495 | sta OAM+29,x
496 | lda #$68
497 | sta OAM+5,x
498 | lda #$69
499 | sta OAM+9,x
500 | lda #$78
501 | sta OAM+21,x
502 | lda #$79
503 | sta OAM+25,x
504 |
505 | ; Colors
506 | lda #$00
507 | sta OAM+2,x
508 | sta OAM+14,x
509 | sta OAM+18,x
510 | sta OAM+30,x
511 | lda #$02
512 | sta OAM+6,x
513 | sta OAM+10,x
514 | sta OAM+22,x
515 | sta OAM+26,x
516 |
517 | ; X coordinate
518 | lda mouse_icon_x,y
519 | sta OAM+3,x
520 | sta OAM+19,x
521 | adc #8
522 | sta OAM+7,x
523 | sta OAM+23,x
524 | adc #8
525 | sta OAM+11,x
526 | sta OAM+27,x
527 | ; and the speed lines
528 | adc #6
529 | sta OAM+15,x
530 | adc #1
531 | sta OAM+31,x
532 |
533 | txa
534 | clc
535 | adc #32
536 | tax
537 | rts
538 | .endproc
539 |
540 | .segment "RODATA"
541 | ; backdrop: black
542 | ; bg0: dark gray, light gray, white
543 | ; bg1: brown, red, white
544 | ; bg2: brown, green, white
545 | ; bg3: brown, blue, white
546 | ; obj0: blue, light blue, ? (player 1 crosshair and presents)
547 | ; obj1: red, orange, pale yellow (player 2 crosshair, missiles, balloons, and explosions)
548 | ; obj2: red, green, peach (villagers)
549 | ; obj3: gray, orange, peach (villagers, smoke)
550 |
551 | title_pkb:
552 | .incbin "src/title.pkb"
553 | todo_txt:
554 | .incbin "todo.txt"
555 | .byt 0
556 | title_palette:
557 | .byt $0F,$00,$10,$20,$0F,$17,$16,$20,$0F,$17,$2A,$20,$0F,$17,$12,$20
558 | ; grayscale arrow mouse sprite 0
559 | .byt $0F,$00,$10,$30, $0F,$16,$27,$38, $0F,$00,$10,$13, $0F,$0F,$0F,$0F
560 | mouse_icon_x:
561 | .byt 92, 140
562 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/src/unpkb.s:
--------------------------------------------------------------------------------
1 | ;
2 | ; unpkb.s - RLE unpacking
3 | ;
4 | ; Copyright (c) 2008 Damian Yerrick
5 | ;
6 | ; Copying and distribution of this file, with or without
7 | ; modification, are permitted in any medium without royalty provided
8 | ; the copyright notice and this notice are preserved in all source
9 | ; code copies. This file is offered as-is, without any warranty.
10 | ;
11 |
12 | ;;; Version history
13 | ;
14 | ; 2008 Dec: Optimized to better use the Y register, on a
15 | ; suggestion by blargg
16 | ; 2003 Oct: Ported for use with ca65 assembler
17 | ; 2000: Initial release, for x816 assembler
18 |
19 |
20 | .export PKB_unpackblk, PKB_unpack, PKB_source, PKB_len
21 |
22 |
23 | ;;; Configuration
24 | ;
25 | ; Set PKB_outport to whatever data port you want PackBits to use.
26 | ; (Slightly more modification is necessary for memory-to-memory
27 | ; unpacking.)
28 | ;
29 | PKB_outport = $2007 ;NES PPU data register
30 |
31 | ;
32 | ; Set PKB_source to the address in direct page (i.e. zero page)
33 | ; where the pointer to packed data is stored.
34 | ;
35 | PKB_source = $00
36 | PKB_len = $02
37 |
38 | .segment "CODE"
39 |
40 | ;
41 | ; PKB_unpackblk
42 | ; Unpack PackBits() encoded data from memory at (PKB_source)
43 | ; to a character device such as the NES PPU data register.
44 | ;
45 | ; This entry point assumes a 16-bit length word in network
46 | ; byte order before the data.
47 | PKB_unpackblk:
48 |
49 | ldy #0
50 | lda (PKB_source),y
51 | inc PKB_source
52 | bne :+
53 | inc PKB_source+1
54 | :
55 | sta PKB_len+1
56 | lda (PKB_source),y
57 | inc PKB_source
58 | bne :+
59 | inc PKB_source+1
60 | :
61 | sta PKB_len
62 |
63 | ; This entry point assumes a 16-bit length word in host byte order
64 | ; at PKB_len.
65 | PKB_unpack:
66 | lda PKB_len
67 | beq :+
68 | inc PKB_len+1 ;trick to allow easier 16-bit decrement
69 | :
70 | ; optimization suggested by blargg is to hold the low byte
71 | ; in Y instead of using constant Y=0; saves 3 cycles per
72 | ; compressed byte
73 | ldy PKB_source
74 | lda #0
75 | sta PKB_source
76 |
77 | @PKB_loop:
78 | lda (PKB_source),y
79 | bmi @PKB_run
80 |
81 | iny ; got a literal string
82 | bne :+
83 | inc PKB_source+1
84 | :
85 | tax
86 | inx
87 | @PKB_strloop:
88 | lda (PKB_source),y
89 | iny
90 | bne :+
91 | inc PKB_source+1
92 | :
93 | sta PKB_outport
94 | dec PKB_len
95 | bne :+
96 | dec PKB_len+1
97 | beq @PKB_rts
98 | :
99 | dex
100 | bne @PKB_strloop
101 | beq @PKB_loop
102 |
103 | @PKB_rts:
104 | sty PKB_source ; restore the address after the compressed data
105 | rts
106 |
107 | @PKB_run:
108 | iny ; got a run
109 | bne :+
110 | inc PKB_source+1
111 | :
112 | tax
113 | dex
114 | lda (PKB_source),y ; get the run contents
115 | iny
116 | bne @PKB_runloop
117 | inc PKB_source+1
118 | @PKB_runloop:
119 | sta PKB_outport
120 | dec PKB_len
121 | bne :+
122 | dec PKB_len+1
123 | beq @PKB_rts
124 | :
125 | inx
126 | bne @PKB_runloop
127 | beq @PKB_loop
128 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/thwaite.nes:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/thwaite.nes
--------------------------------------------------------------------------------
/roms/thwaite-0.03/tilesets/cuthouses.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/tilesets/cuthouses.png
--------------------------------------------------------------------------------
/roms/thwaite-0.03/tilesets/maingfx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/tilesets/maingfx.png
--------------------------------------------------------------------------------
/roms/thwaite-0.03/todo.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ledyba/CycloaJS/b8a49917b459ca3fc76e397275c2bb7c547a8184/roms/thwaite-0.03/todo.txt
--------------------------------------------------------------------------------
/roms/thwaite-0.03/tools/mktables.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Lookup table generator for Concentration Room
4 | # Copyright 2010 Damian Yerrick
5 | #
6 | # Copying and distribution of this file, with or without
7 | # modification, are permitted in any medium without royalty
8 | # provided the copyright notice and this notice are preserved.
9 | # This file is offered as-is, without any warranty.
10 | #
11 | from __future__ import with_statement, division
12 | import sys
13 |
14 | ntscOctaveBase = 39375000.0/(22 * 16 * 55)
15 | palOctaveBase = 266017125.0/(10 * 16 * 16 * 55)
16 | maxNote = 80
17 |
18 | def makePeriodTable(filename, pal=False):
19 | semitone = 2.0**(1./12)
20 | octaveBase = palOctaveBase if pal else ntscOctaveBase
21 | relFreqs = [(1 << (i // 12)) * semitone**(i % 12)
22 | for i in xrange(maxNote)]
23 | periods = [int(round(octaveBase / freq)) - 1 for freq in relFreqs]
24 | systemName = "PAL" if pal else "NTSC"
25 | with open(filename, 'wt') as outfp:
26 | outfp.write("""; %s period table generated by mktables.py
27 | .export periodTableLo, periodTableHi
28 | .segment "RODATA"
29 | periodTableLo:\n"""
30 | % systemName)
31 | for i in range(0, maxNote, 12):
32 | outfp.write(' .byt '
33 | + ','.join('$%02x' % (i % 256)
34 | for i in periods[i:i + 12])
35 | + '\n')
36 | outfp.write('periodTableHi:\n')
37 | for i in range(0, maxNote, 12):
38 | outfp.write(' .byt '
39 | + ','.join('$%02x' % (i >> 8)
40 | for i in periods[i:i + 12])
41 | + '\n')
42 |
43 | def makePALPeriodTable(filename):
44 | return makePeriodTable(filename, pal=True)
45 |
46 | tableNames = {
47 | 'period': makePeriodTable,
48 | 'palperiod': makePALPeriodTable
49 | }
50 |
51 | def main(argv):
52 | if len(argv) >= 2 and argv[1] in ('/?', '-?', '-h', '--help'):
53 | print "usage: %s TABLENAME FILENAME" % argv[0]
54 | print "known tables:", ' '.join(sorted(tableNames))
55 | elif len(argv) < 3:
56 | print "mktables: too few arguments; try %s --help" % argv[0]
57 | elif argv[1] in tableNames:
58 | tableNames[argv[1]](argv[2])
59 | else:
60 | print "mktables: no such table %s; try %s --help" % (argv[1], argv[0])
61 |
62 | if __name__=='__main__':
63 | main(sys.argv)
64 |
65 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/tools/pilbmp2nes.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Bitmap to NES CHR converter using Python Imaging Library
4 | # Copyright 2010 Damian Yerrick
5 | #
6 | # Copying and distribution of this file, with or without
7 | # modification, are permitted in any medium without royalty
8 | # provided the copyright notice and this notice are preserved.
9 | # This file is offered as-is, without any warranty.
10 | #
11 | from __future__ import with_statement
12 | from PIL import Image
13 | from time import sleep
14 |
15 | def formatTilePlanar(tile, nPlanes):
16 | import array
17 | if (tile.size != (8, 8)):
18 | return None
19 | pixels = iter(tile.getdata())
20 | outplanes = [array.array('B')
21 | for i in range(nPlanes)]
22 | for y in range(8):
23 | slivers = [0 for i in range(nPlanes)]
24 | for x in range(8):
25 | px = pixels.next()
26 | for i in range(nPlanes):
27 | slivers[i] = slivers[i] << 1
28 | if px & 0x01:
29 | slivers[i] = slivers[i] | 1
30 | px >>= 1
31 | for i in range(nPlanes):
32 | outplanes[i].append(slivers[i])
33 | out = "".join(plane.tostring() for plane in outplanes)
34 | return out
35 |
36 | def parse_argv(argv):
37 | from optparse import OptionParser
38 | parser = OptionParser(usage="usage: %prog [options] [-i] INFILE [-o] OUTFILE")
39 | parser.add_option("-i", "--image", dest="infilename",
40 | help="read image from INFILE", metavar="INFILE")
41 | parser.add_option("-o", "--output", dest="outfilename",
42 | help="write CHR data to OUTFILE", metavar="OUTFILE")
43 | parser.add_option("-W", "--tile-width", dest="tileWidth",
44 | help="set width of metatiles", metavar="HEIGHT",
45 | type="int", default=8)
46 | parser.add_option("-H", "--tile-height", dest="tileHeight",
47 | help="set height of metatiles", metavar="HEIGHT",
48 | type="int", default=8)
49 | (options, args) = parser.parse_args(argv[1:])
50 |
51 | tileWidth = int(options.tileWidth)
52 | if tileWidth <= 0:
53 | raise ValueError("tile width '%d' must be positive" % tileWidth)
54 |
55 | tileHeight = int(options.tileHeight)
56 | if tileHeight <= 0:
57 | raise ValueError("tile height '%d' must be positive" % tileHeight)
58 |
59 | # Fill unfilled roles with positional arguments
60 | argsreader = iter(args)
61 | try:
62 | infilename = options.infilename
63 | if infilename is None:
64 | infilename = argsreader.next()
65 | outfilename = options.infilename
66 | if outfilename is None:
67 | outfilename = argsreader.next()
68 | except StopIteration:
69 | raise ValueError("not enough filenames")
70 | try:
71 | argsreader.next()
72 | raise ValueError("too many filenames")
73 | except StopIteration:
74 | pass
75 |
76 | return (infilename, outfilename, tileWidth, tileHeight)
77 |
78 | argvTestingMode = True
79 |
80 | def main(argv=None):
81 | if argv is None:
82 | import sys
83 | import os
84 | argv = sys.argv
85 | print argv
86 | if (argvTestingMode and len(argv) < 2
87 | and sys.stdin.isatty() and sys.stdout.isatty()):
88 | argv.extend(raw_input('args:').split())
89 | try:
90 | (infilename, outfilename, tileWidth, tileHeight) = parse_argv(argv)
91 | except StandardError, e:
92 | import sys
93 | sys.stderr.write("%s: %s\n" % (argv[0], str(e)))
94 | sys.exit(1)
95 |
96 | print "loading", infilename
97 | im = Image.open(infilename)
98 | im.load()
99 | (w, h) = im.size
100 |
101 | out = []
102 | for mt_y in range(0, h, tileHeight):
103 | for mt_x in range(0, w, tileWidth):
104 | metatile = im.crop((mt_x, mt_y,
105 | mt_x + tileWidth, mt_y + tileHeight))
106 | for tile_y in range(0, tileHeight, 8):
107 | for tile_x in range(0, tileWidth, 8):
108 | tile = metatile.crop((tile_x, tile_y,
109 | tile_x + 8, tile_y + 8))
110 | data = formatTilePlanar(tile, 2)
111 | out.append(data)
112 | with open(outfilename, 'wb') as outfp:
113 | outfp.writelines(out)
114 |
115 | if __name__=='__main__':
116 | main()
117 |
--------------------------------------------------------------------------------
/roms/thwaite-0.03/zip.in:
--------------------------------------------------------------------------------
1 | CHANGES.txt
2 | gpl-3.0.txt
3 | makefile
4 | nes.ini
5 | README.html
6 | thwaite.nes
7 | todo.txt
8 | zip.in
9 | docs/tas_words.txt
10 | docs/tech_notes.html
11 | docs/de.css
12 | docs/manual_ingame.png
13 | docs/manual_legend.png
14 | docs/manual_practice.png
15 | docs/manual_title.png
16 | obj/nes/index.txt
17 | src/bcd.s
18 | src/bg.s
19 | src/cutscene.pkb
20 | src/cutscene.s
21 | src/cutscripts.s
22 | src/explosion.s
23 | src/kinematics.s
24 | src/levels.s
25 | src/main.s
26 | src/math.s
27 | src/missiles.s
28 | src/mouse.s
29 | src/music.s
30 | src/musicseq.h
31 | src/musicseq.s
32 | src/nes.h
33 | src/pads.s
34 | src/paldetect.s
35 | src/practice.s
36 | src/practice.txt
37 | src/ram.h
38 | src/random.s
39 | src/scurry.s
40 | src/smoke.s
41 | src/sound.s
42 | src/tips.s
43 | src/title.pkb
44 | src/title.s
45 | src/unpkb.s
46 | tilesets/maingfx.png
47 | tilesets/cuthouses.png
48 | tools/8name.py
49 | tools/mktables.py
50 | tools/pilbmp2nes.py
51 |
--------------------------------------------------------------------------------
/script.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CycloaJS: JavaScript NES Emulator
6 |
7 |
8 |
19 |
20 |
21 |
22 |
JavaScript NES Programming!
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
Software Requirements / 動作要件
47 |
Chrme/Firefox, Safari for iPad and Safari for Windows(v5). Sounds are available only for Chrome and Firefox (Web Audio API and Audio Data API).
48 |
Chrome/Firefox、iPad版Safari/Windows版Safari5での動作を確認しています。ChromeとFirefoxのみサウンドも出力されます(Web Audio API and Audio Data API)。
49 |
50 |
51 |
Control / 操作方法
52 |
53 |
54 |
Player 1
Button
55 |
56 |
57 |
A
Z
58 |
59 |
60 |
B
X
61 |
62 |
63 |
Start
Enter
64 |
65 |
66 |
Select
Space
67 |
68 |
69 |
↑
↑
70 |
71 |
72 |
→
→
73 |
74 |
75 |
←
←
76 |
77 |
78 |
↓
↓
79 |
80 |
81 |
Currently player2 is not supported. I have tried many times to support Gamepad API, but the API does not work at all... :(