Codetapper's Amiga Site
R-Type 2
R-Type 2 uses the Amiga sprites to create a 64 pixel wide repeating pattern for the backgrounds on most levels. If sprites are disabled, the game looks almost identical to the Atari ST version. First up, here is midway through level 1 with sprites enabled on the left, and disabled on the right:
Level 1 with sprites enabled
Level 1 with sprites disabled
When sprites are disabled, you just see black pixels in the Bydo base.
Interestingly, at the start of the level sprites are not enabled at all, but when you approach the Bydo base, the sprite playfield will suddenly appear, covering the entire screen:
Start of level 1 with bitplane DMA disabled
Midway level 1 with bitplane DMA disabled
Curiously enough, the sprite layer scrolls onto the screen at the same speed as the background until the sprite layer completely covers the screen, then moves at half the speed to give a parallax effect. Have a look at approximately 1 minute 18 seconds in the following longplay to see the effect:
[フレーム]
By examining memory, we can extract the sprites used for the pattern:
[画像:R-Type 2 16 pixel wide sprites]
Those with a keen eye might be able to see that the pattern repeats every 64 pixels. Displaying them in blocks of 64 pixels shows each combination:
[画像:R-Type 2 64 pixel wide strips]
Only a selection is shown here, the full image is actually 1024 pixels across x 192 pixels high, which uses up 50kb of chip memory. Because there are 16 different indent levels to give pixel accurate scrolling, 64 pixels wide x 16 increments = 1024 pixels width required.
Amiga sprites are 16 pixels wide so 4 of them are required to draw a vertical strip of the background. Because each pair of sprites have their own colour palette, the game duplicates the sprite colours for all 4 sprite pairs:
Because the background pattern is 64 pixels wide, the game could multiplex the 4 sprites completely across the screen and only require 4 sprites. That would free up the remaining sprites for something else. For whatever reason, programmer Tim Round decided to multiplex all 8 across.
The Copperlist
The copperlist begins by setting up all 8 sprite pointers. Note that sprite 4 is set to the same address as sprite 0, ditto with 5 and 1, 6 and 2, and 7 and 3:
Chip Addr: Copper instructions ; Comments -------------------------------------------------- 00010378ドル: 0096 87E0 ; DMACON = 0x87E0 0001037ドルC: 0120 0006 0122 3610 ; SPR0PT = 0x00063610 00010384ドル: 0124 0006 0126 3918 ; SPR1PT = 0x00063918 0001038ドルC: 0128 0006 012A 3000 ; SPR2PT = 0x00063000 00010394ドル: 012C 0006 012E 3308 ; SPR3PT = 0x00063308 0001039ドルC: 0130 0006 0132 3610 ; SPR4PT = 0x00063610 000103ドルA4: 0134 0006 0136 3918 ; SPR5PT = 0x00063918 000103ドルAC: 0138 0006 013A 3000 ; SPR6PT = 0x00063000 000103ドルB4: 013C 0006 013E 3308 ; SPR7PT = 0x00063308
Now the game sets up the display properties, the bitplane pointers and the entire colour palette:
000103ドルBC: 0092 0038 ; DDFSTRT = 0x0038 000103ドルC0: 0094 00C8 ; DDFSTOP = 0x00C8 000103ドルC4: 008E 3F91 ; DIWSTRT = 0x3F91 000103ドルC8: 0090 0FB1 ; DIWSTOP = 0x0FB1 000103ドルCC: 3D09 FFFE ; Wait for vpos >= 0x3D and hpos >= 0x08 000103ドルD0: 0100 4200 ; BPLCON0 = 0x4200 000103ドルD4: 0102 00FF ; BPLCON1 = 0x00FF 000103ドルD8: 0104 0000 ; BPLCON2 = 0x0000 000103ドルDC: 0108 007A ; BPL1MOD = 0x007A 000103ドルE0: 010A 007A ; BPL2MOD = 0x007A 000103ドルE4: 00E0 0007 00E2 7400 ; BPL1PT = 0x00077400 000103ドルEC: 00E4 0007 00E6 7428 ; BPL2PT = 0x00077428 000103ドルF4: 00E8 0007 00EA 7450 ; BPL3PT = 0x00077450 000103ドルFC: 00EC 0007 00EE 7478 ; BPL4PT = 0x00077478 00010404ドル: 0180 0000 ; COLOR00 = 0x0000 - Transparent colour 00010408ドル: 0182 0A74 ; COLOR01 = 0x0A74 0001040ドルC: 0184 0CA7 ; COLOR02 = 0x0CA7 00010410ドル: 0186 0CB9 ; COLOR03 = 0x0CB9 00010414ドル: 0188 0EDB ; COLOR04 = 0x0EDB 00010418ドル: 018A 0666 ; COLOR05 = 0x0666 0001041ドルC: 018C 0AAA ; COLOR06 = 0x0AAA 00010420ドル: 018E 0DDD ; COLOR07 = 0x0DDD 00010424ドル: 0190 0000 ; COLOR08 = 0x0000 00010428ドル: 0192 00DF ; COLOR09 = 0x00DF 0001042ドルC: 0194 005F ; COLOR10 = 0x005F 00010430ドル: 0196 0C00 ; COLOR11 = 0x0C00 00010434ドル: 0198 0FB0 ; COLOR12 = 0x0FB0 00010438ドル: 019A 0080 ; COLOR13 = 0x0080 0001043ドルC: 019C 0D06 ; COLOR14 = 0x0D06 00010440ドル: 019E 0FFF ; COLOR15 = 0x0FFF 00010444ドル: 01A0 0000 ; COLOR16 = 0x0000 - Sprite 0 and 1 colours 00010448ドル: 01A2 0653 ; COLOR17 = 0x0653 0001044ドルC: 01A4 0774 ; COLOR18 = 0x0774 00010450ドル: 01A6 0996 ; COLOR19 = 0x0996 00010454ドル: 01A8 0000 ; COLOR20 = 0x0000 - Sprite 2 and 3 colours 00010458ドル: 01AA 0653 ; COLOR21 = 0x0653 0001045ドルC: 01AC 0774 ; COLOR22 = 0x0774 00010460ドル: 01AE 0996 ; COLOR23 = 0x0996 00010464ドル: 01B0 0000 ; COLOR24 = 0x0000 - Sprite 4 and 5 colours 00010468ドル: 01B2 0653 ; COLOR25 = 0x0653 0001046ドルC: 01B4 0774 ; COLOR26 = 0x0774 00010470ドル: 01B6 0996 ; COLOR27 = 0x0996 00010474ドル: 01B8 0000 ; COLOR28 = 0x0000 - Sprite 6 and 7 colours 00010478ドル: 01BA 0653 ; COLOR29 = 0x0653 0001047ドルC: 01BC 0774 ; COLOR30 = 0x0774 00010480ドル: 01BE 0996 ; COLOR31 = 0x0996
Now for a small trick which explains how the sprites are turned off at the start of the level but instantly appear! At the start of the level, the 1st copper pointer is set to address 146ドルd4, which happens to skip the entire sprite display section! The copperlist becomes active by strobing the jump address:
00010484ドル: 0080 0001 0082 46D4 ; COP1LC = 0x000146D4 0001048ドルC: 0084 00FF ; COPJMP1 = 0x00FF - Copper jumps to 146ドルd4
When the sprite layer is required, the game alters the word at 1048ドルc, inserting a no-operation instruction instead:
00010484ドル: 0080 0001 0082 46D4 ; COP1LC = 0x000146D4 0001048ドルC: 01FE 00FF ; NO-OP = 0x00FF - Copper continues to next instruction
Now the horizontal sprite multiplexing trick is setup on every line of the display. All 8 sprites are positioned 16 pixels from each other, giving an initial width of 128 pixels.
00010490ドル: 0140 3F48 ; SPR0POS = 0x3F48 00010494ドル: 0148 3F50 ; SPR1POS = 0x3F50 00010498ドル: 0150 3F58 ; SPR2POS = 0x3F58 0001049ドルC: 0158 3F60 ; SPR3POS = 0x3F60 000104ドルA0: 0160 3F68 ; SPR4POS = 0x3F68 000104ドルA4: 0168 3F70 ; SPR5POS = 0x3F70 000104ドルA8: 0170 3F78 ; SPR6POS = 0x3F78 000104ドルAC: 0178 3F80 ; SPR7POS = 0x3F80
The copper then waits for the beam to catch up to horizontal position 80,ドル then quickly shifts all the sprites across to their new locations (128 pixels from where they started):
000104ドルB0: 3F81 FFFE ; Wait for vpos >= 0x3F and hpos >= 0x80 000104ドルB4: 0140 3F88 ; SPR0POS = 0x3F88 000104ドルB8: 0148 3F90 ; SPR1POS = 0x3F90 000104ドルBC: 0150 3F98 ; SPR2POS = 0x3F98 000104ドルC0: 0158 3FA0 ; SPR3POS = 0x3FA0 000104ドルC4: 0160 3FA8 ; SPR4POS = 0x3FA8 000104ドルC8: 0168 3FB0 ; SPR5POS = 0x3FB0 000104ドルCC: 0170 3FB8 ; SPR6POS = 0x3FB8 000104ドルD0: 0178 3FC0 ; SPR7POS = 0x3FC0
The game has now displayed 256 pixels worth of sprites, but the display is 288 pixels wide, so two more sprites are required on each line. The game waits for the beam to reach position $c0 and repositions the final 2 sprites:
000104ドルD4: 3FB1 FFFE ; Wait for vpos >= 0x3F and hpos >= 0xB0 000104ドルD8: 3FC1 FFFE ; Wait for vpos >= 0x3F and hpos >= 0xC0 000104ドルDC: 01FE 0000 ; NO-OP = 0x0000 000104ドルE0: 0140 3FC8 ; SPR0POS = 0x3FC8 000104ドルE4: 0148 3FD0 ; SPR1POS = 0x3FD0
In actual fact, the wait at this location is completely unnecessary because by the time the 8 sprites above are repositioned, the beam will have already displayed the first 2 sprites, so they could be moved directly after the first 8!
As you can see, the next line is identical except for a different vertical location so I will not bother pasting the other 190 lines of the display:
000104ドルE8: 0140 4048 ; SPR0POS = 0x4048 000104ドルEC: 0148 4050 ; SPR1POS = 0x4050 000104ドルF0: 0150 4058 ; SPR2POS = 0x4058 000104ドルF4: 0158 4060 ; SPR3POS = 0x4060 000104ドルF8: 0160 4068 ; SPR4POS = 0x4068 000104ドルFC: 0168 4070 ; SPR5POS = 0x4070 00010500ドル: 0170 4078 ; SPR6POS = 0x4078 00010504ドル: 0178 4080 ; SPR7POS = 0x4080 00010508ドル: 4081 FFFE ; Wait for vpos >= 0x40 and hpos >= 0x80 0001050ドルC: 0140 4088 ; SPR0POS = 0x4088 00010510ドル: 0148 4090 ; SPR1POS = 0x4090 00010514ドル: 0150 4098 ; SPR2POS = 0x4098 00010518ドル: 0158 40A0 ; SPR3POS = 0x40A0 0001051ドルC: 0160 40A8 ; SPR4POS = 0x40A8 00010520ドル: 0168 40B0 ; SPR5POS = 0x40B0 00010524ドル: 0170 40B8 ; SPR6POS = 0x40B8 00010528ドル: 0178 40C0 ; SPR7POS = 0x40C0 0001052ドルC: 40B1 FFFE ; Wait for vpos >= 0x40 and hpos >= 0xB0 00010530ドル: 40C1 FFFE ; Wait for vpos >= 0x40 and hpos >= 0xC0 00010534ドル: 01FE 0000 ; NO-OP = 0x0000 00010538ドル: 0140 40C8 ; SPR0POS = 0x40C8 0001053ドルC: 0148 40D0 ; SPR1POS = 0x40D0
The final part of the copperlist sets up the score panel at the bottom of the screen by switching to different bitplane pointers, a new palette and then preparing for the next frame:
00014690ドル: FF09 FFFE ; Wait for vpos >= 0xFF and hpos >= 0x08 00014694ドル: 0102 0000 ; BPLCON1 = 0x0000 00014698ドル: 00E0 0007 00E2 F600 ; BPL1PT = 0x0007F600 000146ドルA0: 00E4 0007 00E6 F628 ; BPL2PT = 0x0007F628 000146ドルA8: 00E8 0007 00EA F650 ; BPL3PT = 0x0007F650 000146ドルB0: 00EC 0007 00EE F678 ; BPL4PT = 0x0007F678 000146ドルB8: 0709 FFFE ; Wait for vpos >= 0x07 and hpos >= 0x08 000146ドルBC: 0190 0FFF ; COLOR08 = 0x0FFF 000146ドルC0: 0182 0CFF ; COLOR01 = 0x0CFF 000146ドルC4: 0184 0CFF ; COLOR02 = 0x0CFF 000146ドルC8: 0080 0001 0082 0378 ; COP1LC = 0x00010378 000146ドルD0: FFFF FFFE ; Wait for vpos >= 0xFF and hpos >= 0xFE ; End of copperlist
At the start of the level when the sprites are disabled, the copper is pointed to 146ドルd4, which sets up a different display, again with a jump instruction swapping between a no-op to skip part of the code:
000146ドルd4: 0080 0001 0082 46f0 ; COP1LC := 0x000146f0 000146ドルdc: 01fe 00ff ; NO-OP(NULL) := 0x00ff - Jump to 146ドルf0 000146ドルe0: 0096 0020 ; DMACON := 0x0020 000146ドルe4: 0080 0001 0082 4690 ; COP1LC := 0x00014690 000146ドルec: 0088 00ff ; COPJMP1 := 0x00ff - Jump to 14690ドル 000146ドルf0: 0096 0020 ; DMACON := 0x0020 000146ドルf4: ff09 fffe ; Wait for vpos >= 0xff and hpos >= 0x08 000146ドルf8: 0102 0000 ; BPLCON1 := 0x0000 000146ドルfc: 00e0 0007 ; BPL1PTH := 0x0007 00014700ドル: 00e2 f600 ; BPL1PTL := 0xf600 00014704ドル: 00e4 0007 ; BPL2PTH := 0x0007 00014708ドル: 00e6 f628 ; BPL2PTL := 0xf628 0001470ドルc: 00e8 0007 ; BPL3PTH := 0x0007 00014710ドル: 00ea f650 ; BPL3PTL := 0xf650 00014714ドル: 00ec 0007 ; BPL4PTH := 0x0007 00014718ドル: 00ee f678 ; BPL4PTL := 0xf678 0001471ドルc: 0182 0000 ; COLOR01 := 0x0000 00014720ドル: 0184 0000 ; COLOR02 := 0x0000 00014724ドル: 0186 0000 ; COLOR03 := 0x0000 00014728ドル: 0188 0000 ; COLOR04 := 0x0000 0001472ドルc: 018a 0000 ; COLOR05 := 0x0000 00014730ドル: 018c 0000 ; COLOR06 := 0x0000 00014734ドル: 018e 0000 ; COLOR07 := 0x0000 00014738ドル: 0190 0000 ; COLOR08 := 0x0000 0001473ドルc: 0192 0000 ; COLOR09 := 0x0000 00014740ドル: 0194 0000 ; COLOR10 := 0x0000 00014744ドル: 0196 0000 ; COLOR11 := 0x0000 00014748ドル: 0198 0000 ; COLOR12 := 0x0000 0001474ドルc: 019a 0000 ; COLOR13 := 0x0000 00014750ドル: 019c 0000 ; COLOR14 := 0x0000 00014754ドル: 019e 0000 ; COLOR15 := 0x0000 00014758ドル: 0080 0001 ; COP1LCH := 0x0001 0001475ドルc: 0082 0378 ; COP1LCL := 0x0378 00014760ドル: ffff fffe ; Wait for vpos >= 0xff and hpos >= 0xfe ; End of Copperlist
Popular Sprite Tricks
2 sprites are displayed then repositioned horizontally right across the screen to create the colourful static background. The remaining sprites are used for the main character, the status bar and player bullets.
The 16-colour background layer was created by using all 8 hardware sprites and repositioning them across the screen. The same 64 pixel wide graphics are repeated across the entire play area.
One of the first jaw-droppingly beautiful Amiga games that still looks great today. Sprites were heavily re-used on the screen, along with priority changes to make them appear between the playfields.
The amazing tunnel sequence was created with a 6 frame animation sequence made with only 4 colours and mirrored vertically. The asteroid layer sits on top of this, with a status panel and player ship made of sprites sitting on top.