├── .gitignore ├── Makefile ├── Music ├── mod.get psyched ├── mod.lose ├── mod.metal heads ├── mod.metallic bop amiga ├── mod.robot attack ├── mod.rushin in ├── mod.soundfx └── mod.win ├── PSP ├── ICON0.PNG ├── PARAM.SFO ├── PIC0.PNG ├── PIC1.PNG ├── animtiles.png ├── c64font.png ├── convertPSP.sh ├── faces.png ├── gameover.png ├── gamescreen.png ├── health.png ├── introscreen.png ├── items.png ├── keys.png ├── level-A ├── level-B ├── level-C ├── level-D ├── level-E ├── level-F ├── level-G ├── level-H ├── level-I ├── level-J ├── level-K ├── level-L ├── level-M ├── level-N ├── sprites.png └── tiles.png ├── PT2.3A_replay_cia.cpp ├── PT2.3A_replay_cia.h ├── Palette.cpp ├── Palette.h ├── Platform.cpp ├── Platform.h ├── PlatformPSP.cpp ├── PlatformPSP.h ├── README ├── Sounds ├── SOUND_BEEP.raw ├── SOUND_BEEP2.raw ├── SOUND_CYCLE_ITEM.raw ├── SOUND_CYCLE_WEAPON.raw ├── SOUND_DOOR_FASTER.raw ├── SOUND_EMP.raw ├── SOUND_ERROR.raw ├── SOUND_FOUND_ITEM.raw ├── SOUND_MAGNET2.raw ├── SOUND_MEDKIT.raw ├── SOUND_MOVE.raw ├── SOUND_PLASMA_FASTER.raw ├── SOUND_SHOCK.raw ├── sounds_dsbarexp.raw └── sounds_dspistol.raw ├── Tiletool ├── .gitignore ├── Tiletool.pro └── main.cpp ├── petrobots.cpp ├── petrobots.h └── tileset.amiga /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | .DS_Store 3 | *.psp 4 | *.prx 5 | *.map 6 | PathDefs 7 | eboot.pbp 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SDK_TOP=/usr/local/psp/devkit 2 | INCDIR=$(SDK_TOP)/include 3 | LIBDIR=$(SDK_TOP)/lib 4 | 5 | CXX=psp-g++ 6 | BIN2ELF=binary2elf 7 | 8 | DEBUGFLAGS = -g 9 | CXXFLAGS = $(DEBUGFLAGS) -Wall -fmessage-length=0 -Iinclude -I$(INCDIR) -DPLATFORM_SCREEN_WIDTH=480 -DPLATFORM_SCREEN_HEIGHT=272 -DPLATFORM_MAP_WINDOW_TILES_WIDTH=18 -DPLATFORM_MAP_WINDOW_TILES_HEIGHT=10 10 | LDFLAGS = -L$(LIBDIR) -Wl,-Map,petrobots.map 11 | SOURCES = petrobots.o Platform.o PlatformPSP.o PT2.3A_replay_cia.o 12 | 13 | LIBS = -lgu -lgum -lm -lwave 14 | LOADLIBES = $(LIBDIR)/ctrl_stub.a 15 | LOADLIBES +=$(LIBDIR)/display_stub.a 16 | LOADLIBES +=$(LIBDIR)/ge_user_stub.a 17 | LOADLIBES +=$(LIBDIR)/utility_stub.a 18 | LOADLIBES +=$(LIBDIR)/impose_stub.a 19 | 20 | OBJECTS=$(SOURCES:.cpp=.o) Tileset.o C64Font.o Faces.o Tiles.o AnimTiles.o Sprites.o Items.o Keys.o Health.o IntroScreen.o GameScreen.o GameOver.o LevelA.o LevelB.o LevelC.o LevelD.o LevelE.o LevelF.o LevelG.o LevelH.o LevelI.o LevelJ.o LevelK.o LevelL.o LevelM.o LevelN.o ModuleSoundFX.o ModuleMetalHeads.o ModuleWin.o ModuleLose.o ModuleMetallicBopAmiga.o ModuleGetPsyched.o ModuleRobotAttack.o ModuleRushinIn.o SoundExplosion.o SoundMedkit.o SoundEMP.o SoundMagnet.o SoundShock.o SoundMove.o SoundPlasma.o SoundPistol.o SoundItemFound.o SoundError.o SoundCycleWeapon.o SoundCycleItem.o SoundDoor.o SoundMenuBeep.o SoundShortBeep.o 21 | 22 | EXECUTABLE=petrobots 23 | 24 | all: $(SOURCES) $(EXECUTABLE).prx eboot.pbp 25 | 26 | $(EXECUTABLE).prx: $(OBJECTS) 27 | $(LINK.cpp) $^ $(LIBS) $(LOADLIBES) -startfiles -o $@ 28 | 29 | eboot.pbp: $(EXECUTABLE).prx 30 | psp-prx-strip -v $(EXECUTABLE).prx 31 | PrxEncrypter $(EXECUTABLE).prx encrypted.prx 32 | pack-pbp eboot.pbp PSP/PARAM.SFO PSP/ICON0.PNG /dev/null PSP/PIC0.PNG PSP/PIC1.PNG /dev/null encrypted.prx /dev/null 33 | 34 | .cpp.o: 35 | $(CXX) $(CXXFLAGS) -c $< -o $@ 36 | Tileset.o: tileset.amiga 37 | $(BIN2ELF) --PSP -s tileset -e tilesetEnd tileset.amiga Tileset.o 38 | C64Font.o: PSP/c64font.psp 39 | $(BIN2ELF) --PSP -s font -e fontEnd PSP/c64font.psp C64Font.o 40 | Faces.o: PSP/faces.psp 41 | $(BIN2ELF) --PSP -s faces -e facesEnd PSP/faces.psp Faces.o 42 | Tiles.o: PSP/tiles.psp 43 | $(BIN2ELF) --PSP -s tiles -e tilesEnd PSP/tiles.psp Tiles.o 44 | AnimTiles.o: PSP/animtiles.psp 45 | $(BIN2ELF) --PSP -s animTiles -e animTilesEnd PSP/animtiles.psp AnimTiles.o 46 | Sprites.o: PSP/sprites.psp 47 | $(BIN2ELF) --PSP -s sprites -e spritesEnd PSP/sprites.psp Sprites.o 48 | Items.o: PSP/items.psp 49 | $(BIN2ELF) --PSP -s items -e itemsEnd PSP/items.psp Items.o 50 | Keys.o: PSP/keys.psp 51 | $(BIN2ELF) --PSP -s keys -e keysEnd PSP/keys.psp Keys.o 52 | Health.o: PSP/health.psp 53 | $(BIN2ELF) --PSP -s health -e healthEnd PSP/health.psp Health.o 54 | IntroScreen.o: PSP/introscreen.psp 55 | $(BIN2ELF) --PSP -s introScreen -e introScreenEnd PSP/introscreen.psp IntroScreen.o 56 | GameScreen.o: PSP/gamescreen.psp 57 | $(BIN2ELF) --PSP -s gameScreen -e gameScreenEnd PSP/gamescreen.psp GameScreen.o 58 | GameOver.o: PSP/gameover.psp 59 | $(BIN2ELF) --PSP -s gameOver -e gameOverEnd PSP/gameover.psp GameOver.o 60 | LevelA.o: PSP/level-A 61 | $(BIN2ELF) --PSP -s levelA -e levelAEnd PSP/level-A LevelA.o 62 | LevelB.o: PSP/level-B 63 | $(BIN2ELF) --PSP -s levelB -e levelBEnd PSP/level-B LevelB.o 64 | LevelC.o: PSP/level-C 65 | $(BIN2ELF) --PSP -s levelC -e levelCEnd PSP/level-C LevelC.o 66 | LevelD.o: PSP/level-D 67 | $(BIN2ELF) --PSP -s levelD -e levelDEnd PSP/level-D LevelD.o 68 | LevelE.o: PSP/level-E 69 | $(BIN2ELF) --PSP -s levelE -e levelEEnd PSP/level-E LevelE.o 70 | LevelF.o: PSP/level-F 71 | $(BIN2ELF) --PSP -s levelF -e levelFEnd PSP/level-F LevelF.o 72 | LevelG.o: PSP/level-G 73 | $(BIN2ELF) --PSP -s levelG -e levelGEnd PSP/level-G LevelG.o 74 | LevelH.o: PSP/level-H 75 | $(BIN2ELF) --PSP -s levelH -e levelHEnd PSP/level-H LevelH.o 76 | LevelI.o: PSP/level-I 77 | $(BIN2ELF) --PSP -s levelI -e levelIEnd PSP/level-I LevelI.o 78 | LevelJ.o: PSP/level-J 79 | $(BIN2ELF) --PSP -s levelJ -e levelJEnd PSP/level-J LevelJ.o 80 | LevelK.o: PSP/level-K 81 | $(BIN2ELF) --PSP -s levelK -e levelKEnd PSP/level-K LevelK.o 82 | LevelL.o: PSP/level-L 83 | $(BIN2ELF) --PSP -s levelL -e levelLEnd PSP/level-L LevelL.o 84 | LevelM.o: PSP/level-M 85 | $(BIN2ELF) --PSP -s levelM -e levelMEnd PSP/level-M LevelM.o 86 | LevelN.o: PSP/level-N 87 | $(BIN2ELF) --PSP -s levelN -e levelNEnd PSP/level-N LevelN.o 88 | ModuleSoundFX.o: Music/mod.soundfx 89 | $(BIN2ELF) --PSP -s moduleSoundFX -e moduleSoundFXEnd Music/mod.soundfx ModuleSoundFX.o 90 | ModuleMetalHeads.o: Music/mod.metal\ heads 91 | $(BIN2ELF) --PSP -s moduleMetalHeads -e moduleMetalHeadsEnd "Music/mod.metal heads" ModuleMetalHeads.o 92 | ModuleWin.o: Music/mod.win 93 | $(BIN2ELF) --PSP -s moduleWin -e moduleWinEnd Music/mod.win ModuleWin.o 94 | ModuleLose.o: Music/mod.lose 95 | $(BIN2ELF) --PSP -s moduleLose -e moduleLoseEnd Music/mod.lose ModuleLose.o 96 | ModuleMetallicBopAmiga.o: Music/mod.metallic\ bop\ amiga 97 | $(BIN2ELF) --PSP -s moduleMetallicBopAmiga -e moduleMetallicBopAmigaEnd "Music/mod.metallic bop amiga" ModuleMetallicBopAmiga.o 98 | ModuleGetPsyched.o: Music/mod.get\ psyched 99 | $(BIN2ELF) --PSP -s moduleGetPsyched -e moduleGetPsychedEnd "Music/mod.get psyched" ModuleGetPsyched.o 100 | ModuleRobotAttack.o: Music/mod.robot\ attack 101 | $(BIN2ELF) --PSP -s moduleRobotAttack -e moduleRobotAttackEnd "Music/mod.robot attack" ModuleRobotAttack.o 102 | ModuleRushinIn.o: Music/mod.rushin\ in 103 | $(BIN2ELF) --PSP -s moduleRushinIn -e moduleRushinInEnd "Music/mod.rushin in" ModuleRushinIn.o 104 | SoundExplosion.o: Sounds/sounds_dsbarexp.raw 105 | $(BIN2ELF) --PSP -s soundExplosion -e soundExplosionEnd Sounds/sounds_dsbarexp.raw SoundExplosion.o 106 | SoundMedkit.o: Sounds/SOUND_MEDKIT.raw 107 | $(BIN2ELF) --PSP -s soundMedkit -e soundMedkitEnd Sounds/SOUND_MEDKIT.raw SoundMedkit.o 108 | SoundEMP.o: Sounds/SOUND_EMP.raw 109 | $(BIN2ELF) --PSP -s soundEMP -e soundEMPEnd Sounds/SOUND_EMP.raw SoundEMP.o 110 | SoundMagnet.o: Sounds/SOUND_MAGNET2.raw 111 | $(BIN2ELF) --PSP -s soundMagnet -e soundMagnetEnd Sounds/SOUND_MAGNET2.raw SoundMagnet.o 112 | SoundShock.o: Sounds/SOUND_SHOCK.raw 113 | $(BIN2ELF) --PSP -s soundShock -e soundShockEnd Sounds/SOUND_SHOCK.raw SoundShock.o 114 | SoundMove.o: Sounds/SOUND_MOVE.raw 115 | $(BIN2ELF) --PSP -s soundMove -e soundMoveEnd Sounds/SOUND_MOVE.raw SoundMove.o 116 | SoundPlasma.o: Sounds/SOUND_PLASMA_FASTER.raw 117 | $(BIN2ELF) --PSP -s soundPlasma -e soundPlasmaEnd Sounds/SOUND_PLASMA_FASTER.raw SoundPlasma.o 118 | SoundPistol.o: Sounds/sounds_dspistol.raw 119 | $(BIN2ELF) --PSP -s soundPistol -e soundPistolEnd Sounds/sounds_dspistol.raw SoundPistol.o 120 | SoundItemFound.o: Sounds/SOUND_FOUND_ITEM.raw 121 | $(BIN2ELF) --PSP -s soundItemFound -e soundItemFoundEnd Sounds/SOUND_FOUND_ITEM.raw SoundItemFound.o 122 | SoundError.o: Sounds/SOUND_ERROR.raw 123 | $(BIN2ELF) --PSP -s soundError -e soundErrorEnd Sounds/SOUND_ERROR.raw SoundError.o 124 | SoundCycleWeapon.o: Sounds/SOUND_CYCLE_WEAPON.raw 125 | $(BIN2ELF) --PSP -s soundCycleWeapon -e soundCycleWeaponEnd Sounds/SOUND_CYCLE_WEAPON.raw SoundCycleWeapon.o 126 | SoundCycleItem.o: Sounds/SOUND_CYCLE_ITEM.raw 127 | $(BIN2ELF) --PSP -s soundCycleItem -e soundCycleItemEnd Sounds/SOUND_CYCLE_ITEM.raw SoundCycleItem.o 128 | SoundDoor.o: Sounds/SOUND_DOOR_FASTER.raw 129 | $(BIN2ELF) --PSP -s soundDoor -e soundDoorEnd Sounds/SOUND_DOOR_FASTER.raw SoundDoor.o 130 | SoundMenuBeep.o: Sounds/SOUND_BEEP2.raw 131 | $(BIN2ELF) --PSP -s soundMenuBeep -e soundMenuBeepEnd Sounds/SOUND_BEEP2.raw SoundMenuBeep.o 132 | SoundShortBeep.o: Sounds/SOUND_BEEP.raw 133 | $(BIN2ELF) --PSP -s soundShortBeep -e soundShortBeepEnd Sounds/SOUND_BEEP.raw SoundShortBeep.o 134 | 135 | install: eboot.pbp 136 | cp -v eboot.pbp /run/media/vesuri/disk/psp/game/petrobots/ 137 | rm -f /run/media/vesuri/disk/log.txt 138 | touch /run/media/vesuri/disk/log.txt 139 | umount /run/media/vesuri/disk 140 | 141 | clean: 142 | rm -f $(OBJECTS) *.gcda *.gcno *.prx eboot.pbp 143 | 144 | #----------- rules -------------- 145 | -include PathDefs 146 | PathDefs: 147 | psp-path-setup > PathDefs || (rm -f PathDefs ; exit 1) 148 | -------------------------------------------------------------------------------- /Music/mod.get psyched: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Music/mod.get psyched -------------------------------------------------------------------------------- /Music/mod.lose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Music/mod.lose -------------------------------------------------------------------------------- /Music/mod.metal heads: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Music/mod.metal heads -------------------------------------------------------------------------------- /Music/mod.metallic bop amiga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Music/mod.metallic bop amiga -------------------------------------------------------------------------------- /Music/mod.robot attack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Music/mod.robot attack -------------------------------------------------------------------------------- /Music/mod.rushin in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Music/mod.rushin in -------------------------------------------------------------------------------- /Music/mod.soundfx: -------------------------------------------------------------------------------- 1 | soundfx@@@@@@@@@@@@@@@@M.K. -------------------------------------------------------------------------------- /Music/mod.win: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Music/mod.win -------------------------------------------------------------------------------- /PSP/ICON0.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/ICON0.PNG -------------------------------------------------------------------------------- /PSP/PARAM.SFO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/PARAM.SFO -------------------------------------------------------------------------------- /PSP/PIC0.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/PIC0.PNG -------------------------------------------------------------------------------- /PSP/PIC1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/PIC1.PNG -------------------------------------------------------------------------------- /PSP/animtiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/animtiles.png -------------------------------------------------------------------------------- /PSP/c64font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/c64font.png -------------------------------------------------------------------------------- /PSP/convertPSP.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for file in *.png 4 | do 5 | psptextureconverter "${file}" "${file%.png}.psp" 3 0 1 0 6 | done 7 | 8 | -------------------------------------------------------------------------------- /PSP/faces.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/faces.png -------------------------------------------------------------------------------- /PSP/gameover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/gameover.png -------------------------------------------------------------------------------- /PSP/gamescreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/gamescreen.png -------------------------------------------------------------------------------- /PSP/health.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/health.png -------------------------------------------------------------------------------- /PSP/introscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/introscreen.png -------------------------------------------------------------------------------- /PSP/items.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/items.png -------------------------------------------------------------------------------- /PSP/keys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/keys.png -------------------------------------------------------------------------------- /PSP/level-A: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-A -------------------------------------------------------------------------------- /PSP/level-B: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-B -------------------------------------------------------------------------------- /PSP/level-C: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-C -------------------------------------------------------------------------------- /PSP/level-D: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-D -------------------------------------------------------------------------------- /PSP/level-E: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-E -------------------------------------------------------------------------------- /PSP/level-F: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-F -------------------------------------------------------------------------------- /PSP/level-G: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-G -------------------------------------------------------------------------------- /PSP/level-H: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-H -------------------------------------------------------------------------------- /PSP/level-I: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-I -------------------------------------------------------------------------------- /PSP/level-J: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-J -------------------------------------------------------------------------------- /PSP/level-K: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-K -------------------------------------------------------------------------------- /PSP/level-L: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-L -------------------------------------------------------------------------------- /PSP/level-M: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-M -------------------------------------------------------------------------------- /PSP/level-N: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/level-N -------------------------------------------------------------------------------- /PSP/sprites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/sprites.png -------------------------------------------------------------------------------- /PSP/tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/PSP/tiles.png -------------------------------------------------------------------------------- /PT2.3A_replay_cia.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "PT2.3A_replay_cia.h" 4 | 5 | /************************************************** 6 | * ----- Protracker V2.3A Playroutine ----- * 7 | **************************************************/ 8 | 9 | /* 10 | * CIA Version 1: 11 | * Call mt_init to initialize the song. To end the song and turn 12 | * off all voices, call mt_end. 13 | * 14 | * This playroutine is not very fast, optimized or well commented, 15 | * but all the new commands in PT2.3 should work. 16 | * If it's not good enough, you'll have to change it yourself. 17 | * We'll try to write a faster routine soon... 18 | * 19 | * Changes from V1.0C playroutine: 20 | * - Vibrato depth changed to be compatible with Noisetracker 2.0. 21 | * You'll have to double all vib. depths on old PT modules. 22 | * - Funk Repeat changed to Invert Loop. 23 | * - Period set back earlier when stopping an effect. 24 | * 25 | * Converted from ProTracker_v2.3a_CIA.s by Vesuri/dA JoRMaS. 26 | */ 27 | 28 | void putLong(uint8_t* array, uint32_t offset, uint32_t value) 29 | { 30 | array[offset] = (value & 0xff000000) >> 24; 31 | array[offset + 1] = (value & 0xff0000) >> 16; 32 | array[offset + 2] = (value & 0xff00) >> 8; 33 | array[offset + 3] = value & 0xff; 34 | } 35 | 36 | void putWord(uint8_t* array, uint32_t offset, uint32_t value) 37 | { 38 | array[offset] = (value & 0xff00) >> 8; 39 | array[offset + 1] = value & 0xff; 40 | } 41 | 42 | uint32_t getLong(uint8_t* array, uint32_t offset) 43 | { 44 | return (array[offset] << 24) | (array[offset + 1] << 16) | (array[offset + 2] << 8) | array[offset + 3]; 45 | } 46 | 47 | uint16_t getWord(uint8_t* array, uint32_t offset) { 48 | return (array[offset] << 8) | array[offset + 1]; 49 | } 50 | 51 | AudioChannel::AudioChannel(uint8_t id) : 52 | id(id), 53 | data(0), 54 | length(0), 55 | period(420), 56 | volume(0), 57 | dmaStart(0), 58 | dmaCurrent(0), 59 | dmaEnd(0), 60 | dmacon(false) 61 | { 62 | } 63 | 64 | void AudioChannel::process(int16_t* buffer, uint32_t samples, uint32_t sampleRate, bool add) { 65 | if (!data || !dmacon) { 66 | if (!add) { 67 | for (uint32_t i = 0; i < samples; i++) { 68 | *buffer++ = 0; 69 | } 70 | } 71 | return; 72 | } 73 | 74 | float dmaPerSample = 7093789.2 / period / sampleRate / 2; 75 | 76 | if (add) { 77 | for (uint32_t i = 0; i < samples; i++) { 78 | *buffer++ += 32 * dmaStart[(int)dmaCurrent] * volume / 64; 79 | dmaCurrent += dmaPerSample; 80 | if (dmaCurrent >= dmaEnd) { 81 | dmaStart = data; 82 | dmaCurrent -= dmaEnd; 83 | dmaEnd = length * 2; 84 | } 85 | } 86 | } else { 87 | for (uint32_t i = 0; i < samples; i++) { 88 | *buffer++ = 32 * dmaStart[(int)dmaCurrent] * volume / 64; 89 | dmaCurrent += dmaPerSample; 90 | if (dmaCurrent >= dmaEnd) { 91 | dmaStart = data; 92 | dmaCurrent -= dmaEnd; 93 | dmaEnd = length * 2; 94 | } 95 | } 96 | } 97 | } 98 | 99 | void AudioChannel::start() { 100 | dmaStart = data; 101 | dmaCurrent = 0; 102 | dmaEnd = length * 2; 103 | dmacon = true; 104 | } 105 | 106 | void AudioChannel::stop() { 107 | dmacon = false; 108 | } 109 | 110 | // ---- CIA Interrupt ---- 111 | 112 | bool ciaapra = false; 113 | float ciatar = 0; 114 | float ciataw = 14187; 115 | AudioChannel channel0(0); 116 | AudioChannel channel1(1); 117 | AudioChannel channel2(2); 118 | AudioChannel channel3(3); 119 | AudioChannel channel4(4); 120 | AudioChannel channel5(5); 121 | AudioChannel channel6(6); 122 | AudioChannel channel7(7); 123 | void processAudio(int16_t* outputBuffer, uint32_t outputLength, uint32_t sampleRate) 124 | { 125 | float timerAdvancePerSample = 709378.92 / (float)sampleRate; 126 | 127 | int16_t *bufferPosition = outputBuffer; 128 | for (uint32_t samplesLeft = outputLength; samplesLeft > 0;) { 129 | // Number of samples to process before interrupt 130 | uint32_t samplesToProcess = MIN((uint32_t)(ciatar / timerAdvancePerSample) + 1, samplesLeft); 131 | 132 | // Process each audio channel 133 | channel0.process(bufferPosition, samplesToProcess, sampleRate, false); 134 | channel1.process(bufferPosition, samplesToProcess, sampleRate, true); 135 | channel2.process(bufferPosition, samplesToProcess, sampleRate, true); 136 | channel3.process(bufferPosition, samplesToProcess, sampleRate, true); 137 | channel4.process(bufferPosition, samplesToProcess, sampleRate, true); 138 | channel5.process(bufferPosition, samplesToProcess, sampleRate, true); 139 | channel6.process(bufferPosition, samplesToProcess, sampleRate, true); 140 | channel7.process(bufferPosition, samplesToProcess, sampleRate, true); 141 | bufferPosition += samplesToProcess; 142 | 143 | // Run the vertical blank interupt if required 144 | ciatar -= samplesToProcess * timerAdvancePerSample; 145 | if (ciatar < 0) { 146 | ciatar += ciataw; 147 | mt_music(); 148 | } 149 | 150 | // Samples left 151 | samplesLeft -= samplesToProcess; 152 | } 153 | }; 154 | 155 | // ---- Tempo ---- 156 | 157 | uint16_t RealTempo = 125; 158 | uint32_t TimerValue = 1773447; 159 | 160 | // ---- Playroutine ---- 161 | 162 | void mt_init(uint8_t* songData) 163 | { 164 | mt_end(); 165 | 166 | mt_SongDataPtr = songData; 167 | 168 | uint8_t lastPattern = 0; 169 | for (int position = 952; position < 952 + 128; position++) { 170 | uint8_t pattern = mt_SongDataPtr[position]; 171 | if (pattern > lastPattern) { 172 | lastPattern = pattern; 173 | } 174 | } 175 | 176 | for (int sample = 0, sampleDataOffset = 20, sampleStart = ((lastPattern + 1) << 10) + 1084; sample < 15; sample++, sampleDataOffset += 30) { 177 | if (getWord(mt_SongDataPtr, sampleDataOffset + 28) == 0) { 178 | putWord(mt_SongDataPtr, sampleDataOffset + 28, 1); 179 | } 180 | if (getWord(mt_SongDataPtr, sampleDataOffset + 28) == 1) { 181 | putWord(mt_SongDataPtr, sampleStart, 0); 182 | } 183 | mt_SampleStarts[sample] = (int8_t*)(mt_SongDataPtr + sampleStart); 184 | sampleStart += getWord(mt_SongDataPtr, sampleDataOffset + 22) * 2; 185 | } 186 | 187 | ciaapra = true; 188 | RealTempo = 125; 189 | mt_speed = 6; 190 | mt_counter = 0; 191 | mt_SongPos = 0; 192 | mt_PatternPos = 0; 193 | 194 | ciataw = std::floor(TimerValue / RealTempo); 195 | ciatar = ciataw; 196 | } 197 | 198 | void mt_end() 199 | { 200 | mt_Enable = false; 201 | channel0.volume = 0; 202 | channel1.volume = 0; 203 | channel2.volume = 0; 204 | channel3.volume = 0; 205 | channel4.volume = 0; 206 | channel5.volume = 0; 207 | channel6.volume = 0; 208 | channel7.volume = 0; 209 | channel0.dmacon = false; 210 | channel1.dmacon = false; 211 | channel2.dmacon = false; 212 | channel3.dmacon = false; 213 | channel4.dmacon = false; 214 | channel5.dmacon = false; 215 | channel6.dmacon = false; 216 | channel7.dmacon = false; 217 | } 218 | 219 | void mt_start() 220 | { 221 | mt_Enable = true; 222 | } 223 | 224 | void mt_music() 225 | { 226 | if (!mt_Enable) { 227 | return; 228 | } 229 | mt_counter++; 230 | if (mt_counter < mt_speed) { 231 | mt_NoNewAllChannels(); 232 | mt_NoNewPosYet(); 233 | } else { 234 | mt_counter = 0; 235 | if (mt_PattDelTime2 == 0) { 236 | mt_GetNewNote(); 237 | } else { 238 | mt_NoNewAllChannels(); 239 | } 240 | 241 | mt_PatternPos += 16; 242 | if (mt_PattDelTime != 0) { 243 | mt_PattDelTime2 = mt_PattDelTime; 244 | mt_PattDelTime = 0; 245 | } 246 | if (mt_PattDelTime2 != 0) { 247 | mt_PattDelTime2 -= 1; 248 | if (mt_PattDelTime2 != 0) { 249 | mt_PatternPos -= 16; 250 | } 251 | } 252 | if (mt_PBreakFlag != 0) { 253 | mt_PBreakFlag = 0; 254 | mt_PatternPos = mt_PBreakPos << 4; 255 | mt_PBreakPos = 0; 256 | } 257 | if (mt_PatternPos < 1024) { 258 | mt_NoNewPosYet(); 259 | } else { 260 | mt_NextPosition(); 261 | } 262 | } 263 | } 264 | 265 | void mt_NoNewAllChannels() 266 | { 267 | mt_CheckEfx(channel0, mt_chan1temp); 268 | mt_CheckEfx(channel1, mt_chan2temp); 269 | mt_CheckEfx(channel2, mt_chan3temp); 270 | mt_CheckEfx(channel3, mt_chan4temp); 271 | mt_CheckEfx(channel4, mt_chan5temp); 272 | mt_CheckEfx(channel5, mt_chan6temp); 273 | mt_CheckEfx(channel6, mt_chan7temp); 274 | mt_CheckEfx(channel7, mt_chan8temp); 275 | } 276 | 277 | void mt_GetNewNote() 278 | { 279 | int pattpo = 952; 280 | int patternOffset = (mt_SongDataPtr[pattpo + mt_SongPos] << 10) + mt_PatternPos; 281 | mt_PlayVoice(channel0, mt_chan1temp, mt_SongDataPtr + 1084, patternOffset); 282 | mt_PlayVoice(channel1, mt_chan2temp, mt_SongDataPtr + 1084, patternOffset + 4); 283 | mt_PlayVoice(channel2, mt_chan3temp, mt_SongDataPtr + 1084, patternOffset + 8); 284 | mt_PlayVoice(channel3, mt_chan4temp, mt_SongDataPtr + 1084, patternOffset + 12); 285 | if (mt_chaninputs[0].note != 0) { 286 | mt_PlayVoice(channel4, mt_chan5temp, (uint8_t*)&mt_chaninputs[0], 0); 287 | mt_chaninputs[0].note = 0; 288 | } 289 | if (mt_chaninputs[1].note != 0) { 290 | mt_PlayVoice(channel5, mt_chan6temp, (uint8_t*)&mt_chaninputs[1], 0); 291 | mt_chaninputs[1].note = 0; 292 | } 293 | if (mt_chaninputs[2].note != 0) { 294 | mt_PlayVoice(channel6, mt_chan7temp, (uint8_t*)&mt_chaninputs[2], 0); 295 | mt_chaninputs[2].note = 0; 296 | } 297 | if (mt_chaninputs[3].note != 0) { 298 | mt_PlayVoice(channel7, mt_chan8temp, (uint8_t*)&mt_chaninputs[3], 0); 299 | mt_chaninputs[3].note = 0; 300 | } 301 | channel7.data = mt_chan8temp.n_loopstart; 302 | channel7.length = mt_chan8temp.n_replen; 303 | channel6.data = mt_chan7temp.n_loopstart; 304 | channel6.length = mt_chan7temp.n_replen; 305 | channel5.data = mt_chan6temp.n_loopstart; 306 | channel5.length = mt_chan6temp.n_replen; 307 | channel4.data = mt_chan5temp.n_loopstart; 308 | channel4.length = mt_chan5temp.n_replen; 309 | channel3.data = mt_chan4temp.n_loopstart; 310 | channel3.length = mt_chan4temp.n_replen; 311 | channel2.data = mt_chan3temp.n_loopstart; 312 | channel2.length = mt_chan3temp.n_replen; 313 | channel1.data = mt_chan2temp.n_loopstart; 314 | channel1.length = mt_chan2temp.n_replen; 315 | channel0.data = mt_chan1temp.n_loopstart; 316 | channel0.length = mt_chan1temp.n_replen; 317 | } 318 | 319 | void mt_PlayVoice(AudioChannel& channel, ChanTemp& mt_chantemp, uint8_t* patternData, int patternOffset) 320 | { 321 | int sampledata = 12; 322 | if (mt_chantemp.n_note == 0 && mt_chantemp.n_cmd.word == 0) { 323 | mt_PerNop(channel, mt_chantemp); 324 | } 325 | mt_chantemp.n_note = getWord(patternData, patternOffset); 326 | mt_chantemp.n_cmd.word = getWord(patternData, patternOffset + 2); 327 | int instrument = ((mt_chantemp.n_cmd.word & 0xf000) >> 12) | ((mt_chantemp.n_note & 0xf000) >> 8); 328 | if (instrument != 0) { 329 | int instrumentOffset = sampledata + 30 * instrument; 330 | mt_chantemp.n_start = mt_SampleStarts[instrument - 1]; 331 | mt_chantemp.n_length = getWord(mt_SongDataPtr, instrumentOffset); 332 | mt_chantemp.n_finetune = mt_SongDataPtr[instrumentOffset + 2]; 333 | mt_chantemp.n_volume = mt_SongDataPtr[instrumentOffset + 3]; 334 | 335 | // Get repeat 336 | int repeat = getWord(mt_SongDataPtr, instrumentOffset + 4); 337 | 338 | // Get start 339 | // Add repeat 340 | mt_chantemp.n_loopstart = mt_chantemp.n_start + 2 * repeat; 341 | mt_chantemp.n_wavestart = mt_chantemp.n_start + 2 * repeat; 342 | 343 | // Save replen 344 | mt_chantemp.n_replen = getWord(mt_SongDataPtr, instrumentOffset + 6); 345 | 346 | if (repeat != 0) { 347 | // Get repeat 348 | // Add replen 349 | mt_chantemp.n_length = repeat + mt_chantemp.n_replen; 350 | } 351 | 352 | // Set volume 353 | channel.volume = mt_chantemp.n_volume; 354 | } 355 | 356 | // If no note 357 | uint16_t setPeriod = (mt_chantemp.n_note & 0xfff) != 0; 358 | if (setPeriod) { 359 | if ((mt_chantemp.n_cmd.word & 0xff0) == 0xe50) { 360 | mt_SetFineTune(channel, mt_chantemp); 361 | } else if ((mt_chantemp.n_cmd.word & 0xf00) == 0x300 || (mt_chantemp.n_cmd.word & 0xf00) == 0x500) { 362 | // TonePortamento 363 | mt_SetTonePorta(channel, mt_chantemp); 364 | setPeriod = false; 365 | } else if ((mt_chantemp.n_cmd.word & 0xf00) == 0x900) { 366 | // Sample Offset 367 | mt_CheckMoreEfx(channel, mt_chantemp); 368 | } 369 | } 370 | 371 | if (setPeriod) { 372 | uint16_t note = mt_chantemp.n_note & 0xfff; 373 | 374 | int periodIndex = 0; 375 | for (; note < mt_PeriodTable[periodIndex] && periodIndex < 36; periodIndex++); 376 | mt_chantemp.n_period = mt_PeriodTable[mt_chantemp.n_finetune * 36 + periodIndex]; 377 | 378 | // Notedelay 379 | if ((mt_chantemp.n_cmd.word & 0xff0) != 0x0ed0) { 380 | channel.stop(); 381 | if ((mt_chantemp.n_wavecontrol & (1 << 2)) == 0) { 382 | mt_chantemp.n_vibratopos = 0; 383 | } 384 | if ((mt_chantemp.n_wavecontrol & (1 << 6)) == 0) { 385 | mt_chantemp.n_tremolopos = 0; 386 | } 387 | 388 | // Set start 389 | channel.data = mt_chantemp.n_start; 390 | 391 | // Set length 392 | channel.length = mt_chantemp.n_length; 393 | 394 | // Set period 395 | channel.period = mt_chantemp.n_period; 396 | channel.start(); 397 | } 398 | } 399 | mt_CheckMoreEfx(channel, mt_chantemp); 400 | } 401 | 402 | void mt_NextPosition() 403 | { 404 | mt_PatternPos = mt_PBreakPos << 4; 405 | mt_PBreakPos = 0; 406 | mt_PosJumpFlag = 0; 407 | mt_SongPos = (mt_SongPos + 1) & 0x7f; 408 | if (mt_SongPos >= mt_SongDataPtr[950]) { 409 | mt_SongPos = 0; 410 | } 411 | } 412 | 413 | void mt_NoNewPosYet() 414 | { 415 | if (mt_PosJumpFlag != 0) { 416 | mt_NextPosition(); 417 | } 418 | } 419 | 420 | void mt_CheckEfx(AudioChannel& channel, ChanTemp& mt_chantemp) 421 | { 422 | mt_UpdateFunk(channel, mt_chantemp); 423 | if ((mt_chantemp.n_cmd.word & 0xfff) == 0) { 424 | mt_PerNop(channel, mt_chantemp); 425 | return; 426 | } 427 | switch (mt_chantemp.n_cmd.word & 0xf00) { 428 | case 0x000: 429 | return mt_Arpeggio(channel, mt_chantemp); 430 | case 0x100: 431 | return mt_PortaUp(channel, mt_chantemp); 432 | case 0x200: 433 | return mt_PortaDown(channel, mt_chantemp); 434 | case 0x300: 435 | return mt_TonePortamento(channel, mt_chantemp); 436 | case 0x400: 437 | return mt_Vibrato(channel, mt_chantemp); 438 | case 0x500: 439 | return mt_TonePlusVolSlide(channel, mt_chantemp); 440 | case 0x600: 441 | return mt_VibratoPlusVolSlide(channel, mt_chantemp); 442 | case 0xe00: 443 | return mt_E_Commands(channel, mt_chantemp); 444 | default: 445 | mt_PerNop(channel, mt_chantemp); 446 | if ((mt_chantemp.n_cmd.word & 0xf00) == 0x700) { 447 | mt_Tremolo(channel, mt_chantemp); 448 | } else if ((mt_chantemp.n_cmd.word & 0xf00) == 0xa00) { 449 | mt_VolumeSlide(channel, mt_chantemp); 450 | } 451 | break; 452 | } 453 | } 454 | 455 | void mt_PerNop(AudioChannel& channel, ChanTemp& mt_chantemp) 456 | { 457 | channel.period = mt_chantemp.n_period; 458 | } 459 | 460 | void mt_Arpeggio(AudioChannel& channel, ChanTemp& mt_chantemp) 461 | { 462 | int amount = 0; 463 | 464 | switch (mt_counter % 3) { 465 | case 0: 466 | channel.period = mt_chantemp.n_period; 467 | return; 468 | case 1: 469 | amount = mt_chantemp.n_cmd.byte[0] >> 4; 470 | break; 471 | default: 472 | amount = mt_chantemp.n_cmd.byte[0] & 0x0f; 473 | break; 474 | } 475 | 476 | int periodOffset = mt_chantemp.n_finetune * 36; 477 | int periodIndex = 0; 478 | for (; mt_chantemp.n_period < mt_PeriodTable[periodOffset + periodIndex] && periodIndex < 36; periodIndex++); 479 | if (periodIndex < 36) { 480 | channel.period = mt_PeriodTable[periodOffset + periodIndex + amount]; 481 | } 482 | } 483 | 484 | void mt_FinePortaUp(AudioChannel& channel, ChanTemp& mt_chantemp) 485 | { 486 | if (mt_counter != 0) { 487 | return; 488 | } 489 | mt_LowMask = 0x0f; 490 | mt_PortaUp(channel, mt_chantemp); 491 | } 492 | 493 | void mt_PortaUp(AudioChannel& channel, ChanTemp& mt_chantemp) 494 | { 495 | int amount = mt_chantemp.n_cmd.byte[0] & mt_LowMask; 496 | mt_LowMask = 0xff; 497 | mt_chantemp.n_period -= amount; 498 | if ((mt_chantemp.n_period & 0x0fff) < 113) { 499 | mt_chantemp.n_period &= 0xf000; 500 | mt_chantemp.n_period |= 113; 501 | } 502 | channel.period = mt_chantemp.n_period & 0x0fff; 503 | } 504 | 505 | void mt_FinePortaDown(AudioChannel& channel, ChanTemp& mt_chantemp) 506 | { 507 | if (mt_counter != 0) { 508 | return; 509 | } 510 | mt_LowMask = 0x0f; 511 | mt_PortaDown(channel, mt_chantemp); 512 | } 513 | 514 | void mt_PortaDown(AudioChannel& channel, ChanTemp& mt_chantemp) 515 | { 516 | uint8_t amount = mt_chantemp.n_cmd.byte[0] & mt_LowMask; 517 | mt_LowMask = 0xff; 518 | mt_chantemp.n_period += amount; 519 | if ((mt_chantemp.n_period & 0x0fff) > 856) { 520 | mt_chantemp.n_period &= 0xf000; 521 | mt_chantemp.n_period |= 856; 522 | } 523 | channel.period = mt_chantemp.n_period & 0x0fff; 524 | } 525 | 526 | void mt_SetTonePorta(AudioChannel& channel, ChanTemp& mt_chantemp) 527 | { 528 | uint16_t note = mt_chantemp.n_note & 0xfff; 529 | 530 | // 37? 531 | int periodOffset = mt_chantemp.n_finetune * 36; 532 | int periodIndex = 0; 533 | for (; note < mt_PeriodTable[periodOffset + periodIndex] && periodIndex < 36; periodIndex++); 534 | periodIndex = std::min(periodIndex, 35); 535 | uint8_t finetune = mt_chantemp.n_finetune & 8; 536 | if (finetune != 0 && periodIndex != 0) { 537 | periodIndex--; 538 | } 539 | mt_chantemp.n_wantedperiod = mt_PeriodTable[periodOffset + periodIndex]; 540 | mt_chantemp.n_toneportdirec = 0; 541 | if (mt_chantemp.n_wantedperiod == mt_chantemp.n_period) { 542 | mt_chantemp.n_wantedperiod = 0; 543 | } else if (mt_chantemp.n_wantedperiod < mt_chantemp.n_period) { 544 | mt_chantemp.n_toneportdirec = 1; 545 | } 546 | } 547 | 548 | void mt_TonePortamento(AudioChannel& channel, ChanTemp& mt_chantemp) 549 | { 550 | if (mt_chantemp.n_cmd.byte[0] != 0) { 551 | mt_chantemp.n_toneportspeed = mt_chantemp.n_cmd.byte[0]; 552 | mt_chantemp.n_cmd.byte[0] = 0; 553 | } 554 | mt_TonePortNoChange(channel, mt_chantemp); 555 | } 556 | 557 | void mt_TonePortNoChange(AudioChannel& channel, ChanTemp& mt_chantemp) 558 | { 559 | if (mt_chantemp.n_wantedperiod == 0) { 560 | return; 561 | } 562 | if (mt_chantemp.n_toneportdirec == 0) { 563 | mt_chantemp.n_period += mt_chantemp.n_toneportspeed; 564 | if (mt_chantemp.n_wantedperiod <= mt_chantemp.n_period) { 565 | mt_chantemp.n_period = mt_chantemp.n_wantedperiod; 566 | mt_chantemp.n_wantedperiod = 0; 567 | } 568 | } else { 569 | mt_chantemp.n_period -= mt_chantemp.n_toneportspeed; 570 | if (mt_chantemp.n_wantedperiod >= mt_chantemp.n_period) { 571 | mt_chantemp.n_period = mt_chantemp.n_wantedperiod; 572 | mt_chantemp.n_wantedperiod = 0; 573 | } 574 | } 575 | int16_t period = mt_chantemp.n_period; 576 | if ((mt_chantemp.n_glissfunk & 0x0f) != 0) { 577 | int periodOffset = mt_chantemp.n_finetune * 36; 578 | int periodIndex = 0; 579 | for (; period < mt_PeriodTable[periodOffset + periodIndex] && periodIndex < 36; periodIndex++); 580 | periodIndex = std::min(periodIndex, 35); 581 | period = mt_PeriodTable[periodOffset + periodIndex]; 582 | } 583 | 584 | // Set period 585 | channel.period = period; 586 | } 587 | 588 | void mt_Vibrato(AudioChannel& channel, ChanTemp& mt_chantemp) 589 | { 590 | if (mt_chantemp.n_cmd.byte[0] != 0) { 591 | uint8_t depth = mt_chantemp.n_cmd.byte[0] & 0x0f; 592 | if (depth != 0) { 593 | mt_chantemp.n_vibratocmd &= 0xf0; 594 | mt_chantemp.n_vibratocmd |= depth; 595 | } 596 | uint8_t speed = mt_chantemp.n_cmd.byte[0] & 0xf0; 597 | if (speed != 0) { 598 | mt_chantemp.n_vibratocmd &= 0x0f; 599 | mt_chantemp.n_vibratocmd |= speed; 600 | } 601 | } 602 | mt_Vibrato2(channel, mt_chantemp); 603 | } 604 | 605 | void mt_Vibrato2(AudioChannel& channel, ChanTemp& mt_chantemp) 606 | { 607 | uint8_t pos = (mt_chantemp.n_vibratopos >> 2) & 0x1f; 608 | int value = 255; 609 | switch (mt_chantemp.n_wavecontrol & 0x03) { 610 | case 0: 611 | value = mt_VibratoTable[pos]; 612 | break; 613 | case 1: 614 | pos <<= 3; 615 | value = mt_chantemp.n_vibratopos >= 0 ? pos : 255 - pos; 616 | break; 617 | default: 618 | break; 619 | } 620 | uint8_t depth = mt_chantemp.n_vibratocmd & 0x0f; 621 | value = (value * depth) / 128; 622 | channel.period = 623 | mt_chantemp.n_period + (mt_chantemp.n_vibratopos >= 0 ? value : -value); 624 | mt_chantemp.n_vibratopos = 625 | (mt_chantemp.n_vibratopos + ((mt_chantemp.n_vibratocmd >> 2) & 0x003c)) & 626 | 0xff; 627 | } 628 | 629 | void mt_TonePlusVolSlide(AudioChannel& channel, ChanTemp& mt_chantemp) 630 | { 631 | mt_TonePortNoChange(channel, mt_chantemp); 632 | mt_VolumeSlide(channel, mt_chantemp); 633 | } 634 | 635 | void mt_VibratoPlusVolSlide(AudioChannel& channel, ChanTemp& mt_chantemp) 636 | { 637 | mt_Vibrato2(channel, mt_chantemp); 638 | mt_VolumeSlide(channel, mt_chantemp); 639 | } 640 | 641 | void mt_Tremolo(AudioChannel& channel, ChanTemp& mt_chantemp) 642 | { 643 | if (mt_chantemp.n_cmd.byte[0] != 0) { 644 | uint8_t depth = mt_chantemp.n_cmd.byte[0] & 0x0f; 645 | if (depth != 0) { 646 | mt_chantemp.n_tremolocmd &= 0xf0; 647 | mt_chantemp.n_tremolocmd |= depth; 648 | } 649 | uint8_t speed = mt_chantemp.n_cmd.byte[0] & 0xf0; 650 | if (speed != 0) { 651 | mt_chantemp.n_tremolocmd &= 0x0f; 652 | mt_chantemp.n_tremolocmd |= speed; 653 | } 654 | } 655 | uint8_t pos = (mt_chantemp.n_tremolopos >> 2) & 0x1f; 656 | int value = 255; 657 | switch ((mt_chantemp.n_wavecontrol >> 4) & 0x03) { 658 | case 0: 659 | value = mt_VibratoTable[pos]; 660 | break; 661 | case 1: 662 | pos <<= 3; 663 | value = mt_chantemp.n_vibratopos >= 0 ? pos : 255 - pos; 664 | break; 665 | default: 666 | break; 667 | } 668 | uint8_t depth = mt_chantemp.n_tremolocmd & 0x0f; 669 | value = (value * depth) / 64; 670 | channel.volume = std::min( 671 | 0x40, 672 | std::max( 673 | 0, 674 | mt_chantemp.n_volume + (mt_chantemp.n_tremolopos < 128 ? value : -value) 675 | ) 676 | ); 677 | mt_chantemp.n_tremolopos = 678 | (mt_chantemp.n_tremolopos + ((mt_chantemp.n_tremolocmd >> 2) & 0x003c)) & 679 | 0xff; 680 | } 681 | 682 | void mt_SampleOffset(AudioChannel& channel, ChanTemp& mt_chantemp) 683 | { 684 | if (mt_chantemp.n_cmd.byte[0] != 0) { 685 | mt_chantemp.n_sampleoffset = mt_chantemp.n_cmd.byte[0]; 686 | } 687 | int offset = mt_chantemp.n_sampleoffset << 7; 688 | if (offset >= mt_chantemp.n_length) { 689 | mt_chantemp.n_length = 0x0001; 690 | } else { 691 | mt_chantemp.n_length -= offset; 692 | mt_chantemp.n_start += 2 * offset; 693 | } 694 | } 695 | 696 | void mt_VolumeSlide(AudioChannel& channel, ChanTemp& mt_chantemp) 697 | { 698 | int amount = mt_chantemp.n_cmd.byte[0] >> 4; 699 | if (amount == 0) { 700 | mt_VolSlideDown(channel, mt_chantemp, mt_chantemp.n_cmd.byte[0] & 0x0f); 701 | } else { 702 | mt_VolSlideUp(channel, mt_chantemp, amount); 703 | } 704 | } 705 | 706 | void mt_VolSlideUp(AudioChannel& channel, ChanTemp& mt_chantemp, int amount) 707 | { 708 | mt_chantemp.n_volume += amount; 709 | if (mt_chantemp.n_volume > 64) { 710 | mt_chantemp.n_volume = 0x40; 711 | } 712 | channel.volume = mt_chantemp.n_volume; 713 | } 714 | 715 | void mt_VolSlideDown(AudioChannel& channel, ChanTemp& mt_chantemp, int amount) 716 | { 717 | mt_chantemp.n_volume -= amount; 718 | if (mt_chantemp.n_volume < 0) { 719 | mt_chantemp.n_volume = 0; 720 | } 721 | channel.volume = mt_chantemp.n_volume; 722 | } 723 | 724 | void mt_PositionJump(AudioChannel& channel, ChanTemp& mt_chantemp) 725 | { 726 | mt_SongPos = mt_chantemp.n_cmd.byte[0] - 1; 727 | mt_PBreakPos = 0; 728 | mt_PosJumpFlag = 0xff; 729 | } 730 | 731 | void mt_VolumeChange(AudioChannel& channel, ChanTemp& mt_chantemp) 732 | { 733 | mt_chantemp.n_volume = std::min(mt_chantemp.n_cmd.byte[0], (uint8_t)0x40); 734 | channel.volume = mt_chantemp.n_volume; 735 | } 736 | 737 | void mt_PatternBreak(AudioChannel& channel, ChanTemp& mt_chantemp) 738 | { 739 | int position = (mt_chantemp.n_cmd.byte[0] >> 4) * 10 + (mt_chantemp.n_cmd.byte[0] & 0x0f); 740 | mt_PBreakPos = position <= 63 ? position : 0; 741 | mt_PosJumpFlag = 0xff; 742 | } 743 | 744 | void mt_SetSpeed(AudioChannel& channel, ChanTemp& mt_chantemp) 745 | { 746 | if (mt_chantemp.n_cmd.byte[0] == 0) { 747 | mt_end(); 748 | } else if (mt_chantemp.n_cmd.byte[0] >= 32) { 749 | RealTempo = mt_chantemp.n_cmd.byte[0]; 750 | ciataw = std::floor(TimerValue / RealTempo); 751 | } else { 752 | mt_counter = 0; 753 | mt_speed = mt_chantemp.n_cmd.byte[0]; 754 | } 755 | } 756 | 757 | void mt_CheckMoreEfx(AudioChannel& channel, ChanTemp& mt_chantemp) 758 | { 759 | mt_UpdateFunk(channel, mt_chantemp); 760 | switch (mt_chantemp.n_cmd.word & 0xf00) { 761 | case 0x900: 762 | return mt_SampleOffset(channel, mt_chantemp); 763 | case 0xb00: 764 | return mt_PositionJump(channel, mt_chantemp); 765 | case 0xd00: 766 | return mt_PatternBreak(channel, mt_chantemp); 767 | case 0xe00: 768 | return mt_E_Commands(channel, mt_chantemp); 769 | case 0xf00: 770 | return mt_SetSpeed(channel, mt_chantemp); 771 | case 0xc00: 772 | return mt_VolumeChange(channel, mt_chantemp); 773 | default: 774 | return mt_PerNop(channel, mt_chantemp); 775 | } 776 | } 777 | 778 | void mt_E_Commands(AudioChannel& channel, ChanTemp& mt_chantemp) 779 | { 780 | switch (mt_chantemp.n_cmd.byte[0] & 0xf0) { 781 | case 0x00: 782 | return mt_FilterOnOff(channel, mt_chantemp); 783 | case 0x10: 784 | return mt_FinePortaUp(channel, mt_chantemp); 785 | case 0x20: 786 | return mt_FinePortaDown(channel, mt_chantemp); 787 | case 0x30: 788 | return mt_SetGlissControl(channel, mt_chantemp); 789 | case 0x40: 790 | return mt_SetVibratoControl(channel, mt_chantemp); 791 | case 0x50: 792 | return mt_SetFineTune(channel, mt_chantemp); 793 | case 0x60: 794 | return mt_JumpLoop(channel, mt_chantemp); 795 | case 0x70: 796 | return mt_SetTremoloControl(channel, mt_chantemp); 797 | case 0x90: 798 | return mt_RetrigNote(channel, mt_chantemp); 799 | case 0xa0: 800 | return mt_VolumeFineUp(channel, mt_chantemp); 801 | case 0xb0: 802 | return mt_VolumeFineDown(channel, mt_chantemp); 803 | case 0xc0: 804 | return mt_NoteCut(channel, mt_chantemp); 805 | case 0xd0: 806 | return mt_NoteDelay(channel, mt_chantemp); 807 | case 0xe0: 808 | return mt_PatternDelay(channel, mt_chantemp); 809 | case 0xf0: 810 | return mt_FunkIt(channel, mt_chantemp); 811 | default: 812 | break; 813 | } 814 | } 815 | 816 | void mt_FilterOnOff(AudioChannel& channel, ChanTemp& mt_chantemp) 817 | { 818 | ciaapra = !!mt_chantemp.n_cmd.byte[0]; 819 | } 820 | 821 | void mt_SetGlissControl(AudioChannel& channel, ChanTemp& mt_chantemp) 822 | { 823 | mt_chantemp.n_glissfunk &= 0xf0; 824 | mt_chantemp.n_glissfunk |= mt_chantemp.n_cmd.byte[0] & 0x0f; 825 | } 826 | 827 | void mt_SetVibratoControl(AudioChannel& channel, ChanTemp& mt_chantemp) 828 | { 829 | mt_chantemp.n_wavecontrol &= 0xf0; 830 | mt_chantemp.n_wavecontrol |= mt_chantemp.n_cmd.byte[0] & 0x0f; 831 | } 832 | 833 | void mt_SetFineTune(AudioChannel& channel, ChanTemp& mt_chantemp) 834 | { 835 | mt_chantemp.n_finetune = mt_chantemp.n_cmd.byte[0] & 0x0f; 836 | } 837 | 838 | void mt_JumpLoop(AudioChannel& channel, ChanTemp& mt_chantemp) 839 | { 840 | if (mt_counter != 0) { 841 | return; 842 | } 843 | uint8_t count = mt_chantemp.n_cmd.byte[0] & 0x0f; 844 | if (count != 0) { 845 | if (mt_chantemp.n_loopcount > 0) { 846 | mt_chantemp.n_loopcount--; 847 | if (mt_chantemp.n_loopcount == 0) { 848 | return; 849 | } 850 | } else { 851 | mt_chantemp.n_loopcount = count; 852 | } 853 | mt_PBreakPos = mt_chantemp.n_pattpos; 854 | mt_PBreakFlag = 0xff; 855 | } else { 856 | mt_chantemp.n_pattpos = mt_PatternPos >> 4; 857 | } 858 | } 859 | 860 | void mt_SetTremoloControl(AudioChannel& channel, ChanTemp& mt_chantemp) 861 | { 862 | mt_chantemp.n_wavecontrol &= 0x0f; 863 | mt_chantemp.n_wavecontrol |= (mt_chantemp.n_cmd.byte[0] & 0x0f) << 4; 864 | } 865 | 866 | void mt_RetrigNote(AudioChannel& channel, ChanTemp& mt_chantemp) 867 | { 868 | uint8_t tick = mt_chantemp.n_cmd.byte[0] & 0x0f; 869 | if (tick == 0) { 870 | return; 871 | } 872 | if (mt_counter == 0) { 873 | if ((mt_chantemp.n_note & 0x0fff) != 0) { 874 | return; 875 | } 876 | } 877 | if (mt_counter % tick != 0) { 878 | return; 879 | } 880 | mt_DoRetrig(channel, mt_chantemp); 881 | } 882 | 883 | void mt_DoRetrig(AudioChannel& channel, ChanTemp& mt_chantemp) 884 | { 885 | // Channel DMA off 886 | channel.stop(); 887 | 888 | // Set sampledata pointer 889 | channel.data = mt_chantemp.n_start; 890 | 891 | // Set length 892 | channel.length = mt_chantemp.n_length; 893 | 894 | channel.start(); 895 | 896 | channel.data = mt_chantemp.n_loopstart; 897 | channel.length = mt_chantemp.n_replen; 898 | channel.period = mt_chantemp.n_period; 899 | } 900 | 901 | void mt_VolumeFineUp(AudioChannel& channel, ChanTemp& mt_chantemp) 902 | { 903 | if (mt_counter != 0) { 904 | return; 905 | } 906 | mt_VolSlideUp(channel, mt_chantemp, mt_chantemp.n_cmd.byte[0] & 0x0f); 907 | } 908 | 909 | void mt_VolumeFineDown(AudioChannel& channel, ChanTemp& mt_chantemp) 910 | { 911 | if (mt_counter != 0) { 912 | return; 913 | } 914 | mt_VolSlideDown(channel, mt_chantemp, mt_chantemp.n_cmd.byte[0] & 0x0f); 915 | } 916 | 917 | void mt_NoteCut(AudioChannel& channel, ChanTemp& mt_chantemp) 918 | { 919 | if (mt_counter != (mt_chantemp.n_cmd.byte[0] & 0x0f)) { 920 | return; 921 | } 922 | mt_chantemp.n_volume = 0; 923 | channel.volume = 0; 924 | } 925 | 926 | void mt_NoteDelay(AudioChannel& channel, ChanTemp& mt_chantemp) 927 | { 928 | if (mt_counter != (mt_chantemp.n_cmd.byte[0] & 0x0f)) { 929 | return; 930 | } 931 | if (mt_chantemp.n_note == 0) { 932 | return; 933 | } 934 | mt_DoRetrig(channel, mt_chantemp); 935 | } 936 | 937 | void mt_PatternDelay(AudioChannel& channel, ChanTemp& mt_chantemp) 938 | { 939 | if (mt_counter != 0) { 940 | return; 941 | } 942 | if (mt_PattDelTime2 == 0) { 943 | mt_PattDelTime = (mt_chantemp.n_cmd.byte[0] & 0x0f) + 1; 944 | } 945 | } 946 | 947 | void mt_FunkIt(AudioChannel& channel, ChanTemp& mt_chantemp) 948 | { 949 | if (mt_counter != 0) { 950 | return; 951 | } 952 | uint8_t amount = (mt_chantemp.n_cmd.byte[0] & 0x0f) << 4; 953 | mt_chantemp.n_glissfunk &= 0x0f; 954 | mt_chantemp.n_glissfunk |= amount; 955 | if (amount != 0) { 956 | mt_UpdateFunk(channel, mt_chantemp); 957 | } 958 | } 959 | 960 | void mt_UpdateFunk(AudioChannel& channel, ChanTemp& mt_chantemp) 961 | { 962 | int speed = mt_chantemp.n_glissfunk >> 4; 963 | if (speed == 0) { 964 | return; 965 | } 966 | uint8_t funk = mt_FunkTable[speed]; 967 | mt_chantemp.n_funkoffset += funk; 968 | if ((mt_chantemp.n_funkoffset & (1 << 7)) != 0) { 969 | return; 970 | } 971 | mt_chantemp.n_funkoffset = 0; 972 | int8_t* offset = mt_chantemp.n_loopstart + mt_chantemp.n_replen * 2; 973 | mt_chantemp.n_wavestart++; 974 | if (mt_chantemp.n_wavestart >= offset) { 975 | mt_chantemp.n_wavestart = mt_chantemp.n_loopstart; 976 | } 977 | *mt_chantemp.n_wavestart = -1 - *mt_chantemp.n_wavestart; 978 | } 979 | 980 | uint8_t mt_FunkTable[] = { 981 | 0, 982 | 5, 983 | 6, 984 | 7, 985 | 8, 986 | 10, 987 | 11, 988 | 13, 989 | 16, 990 | 19, 991 | 22, 992 | 26, 993 | 32, 994 | 43, 995 | 64, 996 | 128 997 | }; 998 | 999 | uint8_t mt_VibratoTable[] = { 1000 | 0, 1001 | 24, 1002 | 49, 1003 | 74, 1004 | 97, 1005 | 120, 1006 | 141, 1007 | 161, 1008 | 180, 1009 | 197, 1010 | 212, 1011 | 224, 1012 | 235, 1013 | 244, 1014 | 250, 1015 | 253, 1016 | 255, 1017 | 253, 1018 | 250, 1019 | 244, 1020 | 235, 1021 | 224, 1022 | 212, 1023 | 197, 1024 | 180, 1025 | 161, 1026 | 141, 1027 | 120, 1028 | 97, 1029 | 74, 1030 | 49, 1031 | 24 1032 | }; 1033 | 1034 | uint16_t mt_PeriodTable[] = { 1035 | // Tuning 0, Normal 1036 | 856, 1037 | 808, 1038 | 762, 1039 | 720, 1040 | 678, 1041 | 640, 1042 | 604, 1043 | 570, 1044 | 538, 1045 | 508, 1046 | 480, 1047 | 453, 1048 | 428, 1049 | 404, 1050 | 381, 1051 | 360, 1052 | 339, 1053 | 320, 1054 | 302, 1055 | 285, 1056 | 269, 1057 | 254, 1058 | 240, 1059 | 226, 1060 | 214, 1061 | 202, 1062 | 190, 1063 | 180, 1064 | 170, 1065 | 160, 1066 | 151, 1067 | 143, 1068 | 135, 1069 | 127, 1070 | 120, 1071 | 113, 1072 | // Tuning 1 1073 | 850, 1074 | 802, 1075 | 757, 1076 | 715, 1077 | 674, 1078 | 637, 1079 | 601, 1080 | 567, 1081 | 535, 1082 | 505, 1083 | 477, 1084 | 450, 1085 | 425, 1086 | 401, 1087 | 379, 1088 | 357, 1089 | 337, 1090 | 318, 1091 | 300, 1092 | 284, 1093 | 268, 1094 | 253, 1095 | 239, 1096 | 225, 1097 | 213, 1098 | 201, 1099 | 189, 1100 | 179, 1101 | 169, 1102 | 159, 1103 | 150, 1104 | 142, 1105 | 134, 1106 | 126, 1107 | 119, 1108 | 113, 1109 | // Tuning 2 1110 | 844, 1111 | 796, 1112 | 752, 1113 | 709, 1114 | 670, 1115 | 632, 1116 | 597, 1117 | 563, 1118 | 532, 1119 | 502, 1120 | 474, 1121 | 447, 1122 | 422, 1123 | 398, 1124 | 376, 1125 | 355, 1126 | 335, 1127 | 316, 1128 | 298, 1129 | 282, 1130 | 266, 1131 | 251, 1132 | 237, 1133 | 224, 1134 | 211, 1135 | 199, 1136 | 188, 1137 | 177, 1138 | 167, 1139 | 158, 1140 | 149, 1141 | 141, 1142 | 133, 1143 | 125, 1144 | 118, 1145 | 112, 1146 | // Tuning 3 1147 | 838, 1148 | 791, 1149 | 746, 1150 | 704, 1151 | 665, 1152 | 628, 1153 | 592, 1154 | 559, 1155 | 528, 1156 | 498, 1157 | 470, 1158 | 444, 1159 | 419, 1160 | 395, 1161 | 373, 1162 | 352, 1163 | 332, 1164 | 314, 1165 | 296, 1166 | 280, 1167 | 264, 1168 | 249, 1169 | 235, 1170 | 222, 1171 | 209, 1172 | 198, 1173 | 187, 1174 | 176, 1175 | 166, 1176 | 157, 1177 | 148, 1178 | 140, 1179 | 132, 1180 | 125, 1181 | 118, 1182 | 111, 1183 | // Tuning 4 1184 | 832, 1185 | 785, 1186 | 741, 1187 | 699, 1188 | 660, 1189 | 623, 1190 | 588, 1191 | 555, 1192 | 524, 1193 | 495, 1194 | 467, 1195 | 441, 1196 | 416, 1197 | 392, 1198 | 370, 1199 | 350, 1200 | 330, 1201 | 312, 1202 | 294, 1203 | 278, 1204 | 262, 1205 | 247, 1206 | 233, 1207 | 220, 1208 | 208, 1209 | 196, 1210 | 185, 1211 | 175, 1212 | 165, 1213 | 156, 1214 | 147, 1215 | 139, 1216 | 131, 1217 | 124, 1218 | 117, 1219 | 110, 1220 | // Tuning 5 1221 | 826, 1222 | 779, 1223 | 736, 1224 | 694, 1225 | 655, 1226 | 619, 1227 | 584, 1228 | 551, 1229 | 520, 1230 | 491, 1231 | 463, 1232 | 437, 1233 | 413, 1234 | 390, 1235 | 368, 1236 | 347, 1237 | 328, 1238 | 309, 1239 | 292, 1240 | 276, 1241 | 260, 1242 | 245, 1243 | 232, 1244 | 219, 1245 | 206, 1246 | 195, 1247 | 184, 1248 | 174, 1249 | 164, 1250 | 155, 1251 | 146, 1252 | 138, 1253 | 130, 1254 | 123, 1255 | 116, 1256 | 109, 1257 | // Tuning 6 1258 | 820, 1259 | 774, 1260 | 730, 1261 | 689, 1262 | 651, 1263 | 614, 1264 | 580, 1265 | 547, 1266 | 516, 1267 | 487, 1268 | 460, 1269 | 434, 1270 | 410, 1271 | 387, 1272 | 365, 1273 | 345, 1274 | 325, 1275 | 307, 1276 | 290, 1277 | 274, 1278 | 258, 1279 | 244, 1280 | 230, 1281 | 217, 1282 | 205, 1283 | 193, 1284 | 183, 1285 | 172, 1286 | 163, 1287 | 154, 1288 | 145, 1289 | 137, 1290 | 129, 1291 | 122, 1292 | 115, 1293 | 109, 1294 | // Tuning 7 1295 | 814, 1296 | 768, 1297 | 725, 1298 | 684, 1299 | 646, 1300 | 610, 1301 | 575, 1302 | 543, 1303 | 513, 1304 | 484, 1305 | 457, 1306 | 431, 1307 | 407, 1308 | 384, 1309 | 363, 1310 | 342, 1311 | 323, 1312 | 305, 1313 | 288, 1314 | 272, 1315 | 256, 1316 | 242, 1317 | 228, 1318 | 216, 1319 | 204, 1320 | 192, 1321 | 181, 1322 | 171, 1323 | 161, 1324 | 152, 1325 | 144, 1326 | 136, 1327 | 128, 1328 | 121, 1329 | 114, 1330 | 108, 1331 | // Tuning -8 1332 | 907, 1333 | 856, 1334 | 808, 1335 | 762, 1336 | 720, 1337 | 678, 1338 | 640, 1339 | 604, 1340 | 570, 1341 | 538, 1342 | 508, 1343 | 480, 1344 | 453, 1345 | 428, 1346 | 404, 1347 | 381, 1348 | 360, 1349 | 339, 1350 | 320, 1351 | 302, 1352 | 285, 1353 | 269, 1354 | 254, 1355 | 240, 1356 | 226, 1357 | 214, 1358 | 202, 1359 | 190, 1360 | 180, 1361 | 170, 1362 | 160, 1363 | 151, 1364 | 143, 1365 | 135, 1366 | 127, 1367 | 120, 1368 | // Tuning -7 1369 | 900, 1370 | 850, 1371 | 802, 1372 | 757, 1373 | 715, 1374 | 675, 1375 | 636, 1376 | 601, 1377 | 567, 1378 | 535, 1379 | 505, 1380 | 477, 1381 | 450, 1382 | 425, 1383 | 401, 1384 | 379, 1385 | 357, 1386 | 337, 1387 | 318, 1388 | 300, 1389 | 284, 1390 | 268, 1391 | 253, 1392 | 238, 1393 | 225, 1394 | 212, 1395 | 200, 1396 | 189, 1397 | 179, 1398 | 169, 1399 | 159, 1400 | 150, 1401 | 142, 1402 | 134, 1403 | 126, 1404 | 119, 1405 | // Tuning -6 1406 | 894, 1407 | 844, 1408 | 796, 1409 | 752, 1410 | 709, 1411 | 670, 1412 | 632, 1413 | 597, 1414 | 563, 1415 | 532, 1416 | 502, 1417 | 474, 1418 | 447, 1419 | 422, 1420 | 398, 1421 | 376, 1422 | 355, 1423 | 335, 1424 | 316, 1425 | 298, 1426 | 282, 1427 | 266, 1428 | 251, 1429 | 237, 1430 | 223, 1431 | 211, 1432 | 199, 1433 | 188, 1434 | 177, 1435 | 167, 1436 | 158, 1437 | 149, 1438 | 141, 1439 | 133, 1440 | 125, 1441 | 118, 1442 | // Tuning -5 1443 | 887, 1444 | 838, 1445 | 791, 1446 | 746, 1447 | 704, 1448 | 665, 1449 | 628, 1450 | 592, 1451 | 559, 1452 | 528, 1453 | 498, 1454 | 470, 1455 | 444, 1456 | 419, 1457 | 395, 1458 | 373, 1459 | 352, 1460 | 332, 1461 | 314, 1462 | 296, 1463 | 280, 1464 | 264, 1465 | 249, 1466 | 235, 1467 | 222, 1468 | 209, 1469 | 198, 1470 | 187, 1471 | 176, 1472 | 166, 1473 | 157, 1474 | 148, 1475 | 140, 1476 | 132, 1477 | 125, 1478 | 118, 1479 | // Tuning -4 1480 | 881, 1481 | 832, 1482 | 785, 1483 | 741, 1484 | 699, 1485 | 660, 1486 | 623, 1487 | 588, 1488 | 555, 1489 | 524, 1490 | 494, 1491 | 467, 1492 | 441, 1493 | 416, 1494 | 392, 1495 | 370, 1496 | 350, 1497 | 330, 1498 | 312, 1499 | 294, 1500 | 278, 1501 | 262, 1502 | 247, 1503 | 233, 1504 | 220, 1505 | 208, 1506 | 196, 1507 | 185, 1508 | 175, 1509 | 165, 1510 | 156, 1511 | 147, 1512 | 139, 1513 | 131, 1514 | 123, 1515 | 117, 1516 | // Tuning -3 1517 | 875, 1518 | 826, 1519 | 779, 1520 | 736, 1521 | 694, 1522 | 655, 1523 | 619, 1524 | 584, 1525 | 551, 1526 | 520, 1527 | 491, 1528 | 463, 1529 | 437, 1530 | 413, 1531 | 390, 1532 | 368, 1533 | 347, 1534 | 328, 1535 | 309, 1536 | 292, 1537 | 276, 1538 | 260, 1539 | 245, 1540 | 232, 1541 | 219, 1542 | 206, 1543 | 195, 1544 | 184, 1545 | 174, 1546 | 164, 1547 | 155, 1548 | 146, 1549 | 138, 1550 | 130, 1551 | 123, 1552 | 116, 1553 | // Tuning -2 1554 | 868, 1555 | 820, 1556 | 774, 1557 | 730, 1558 | 689, 1559 | 651, 1560 | 614, 1561 | 580, 1562 | 547, 1563 | 516, 1564 | 487, 1565 | 460, 1566 | 434, 1567 | 410, 1568 | 387, 1569 | 365, 1570 | 345, 1571 | 325, 1572 | 307, 1573 | 290, 1574 | 274, 1575 | 258, 1576 | 244, 1577 | 230, 1578 | 217, 1579 | 205, 1580 | 193, 1581 | 183, 1582 | 172, 1583 | 163, 1584 | 154, 1585 | 145, 1586 | 137, 1587 | 129, 1588 | 122, 1589 | 115, 1590 | // Tuning -1 1591 | 862, 1592 | 814, 1593 | 768, 1594 | 725, 1595 | 684, 1596 | 646, 1597 | 610, 1598 | 575, 1599 | 543, 1600 | 513, 1601 | 484, 1602 | 457, 1603 | 431, 1604 | 407, 1605 | 384, 1606 | 363, 1607 | 342, 1608 | 323, 1609 | 305, 1610 | 288, 1611 | 272, 1612 | 256, 1613 | 242, 1614 | 228, 1615 | 216, 1616 | 203, 1617 | 192, 1618 | 181, 1619 | 171, 1620 | 161, 1621 | 152, 1622 | 144, 1623 | 136, 1624 | 128, 1625 | 121, 1626 | 114 1627 | }; 1628 | 1629 | ChanTemp mt_chan1temp; 1630 | ChanTemp mt_chan2temp; 1631 | ChanTemp mt_chan3temp; 1632 | ChanTemp mt_chan4temp; 1633 | ChanTemp mt_chan5temp; 1634 | ChanTemp mt_chan6temp; 1635 | ChanTemp mt_chan7temp; 1636 | ChanTemp mt_chan8temp; 1637 | 1638 | int8_t* mt_SampleStarts[31] = {0}; 1639 | 1640 | uint8_t* mt_SongDataPtr = 0; 1641 | uint8_t mt_speed = 6; 1642 | uint8_t mt_counter = 0; 1643 | uint8_t mt_SongPos = 0; 1644 | uint8_t mt_PBreakPos = 0; 1645 | uint8_t mt_PosJumpFlag = 0; 1646 | uint8_t mt_PBreakFlag = 0; 1647 | uint8_t mt_LowMask = 0; 1648 | uint8_t mt_PattDelTime = 0; 1649 | uint8_t mt_PattDelTime2 = 0; 1650 | bool mt_Enable = false; 1651 | uint16_t mt_PatternPos = 0; 1652 | ChanInput mt_chaninputs[4]; 1653 | /* End of File */ 1654 | -------------------------------------------------------------------------------- /PT2.3A_replay_cia.h: -------------------------------------------------------------------------------- 1 | #ifndef _PT23A_REPLAY_CIA_H 2 | #define _PT23A_REPLAY_CIA_H 3 | 4 | #include "Platform.h" 5 | 6 | struct AudioChannel { 7 | public: 8 | AudioChannel(uint8_t id); 9 | void process(int16_t* buffer, uint32_t samples, uint32_t sampleRate, bool add); 10 | void start(); 11 | void stop(); 12 | 13 | uint8_t id; 14 | int8_t* data; 15 | uint16_t length; 16 | uint16_t period; 17 | uint16_t volume; 18 | int8_t* dmaStart; 19 | float dmaCurrent; 20 | float dmaEnd; 21 | bool dmacon; 22 | }; 23 | 24 | struct SampleData { 25 | char name[22]; 26 | uint16_t length; 27 | int8_t finetune; 28 | uint8_t volume; 29 | uint16_t repeatPoint; 30 | uint16_t repeatLength; 31 | }; 32 | 33 | union Cmd { 34 | uint16_t word; 35 | uint8_t byte[2]; 36 | }; 37 | 38 | struct ChanTemp { 39 | uint16_t n_note; 40 | Cmd n_cmd; 41 | int8_t* n_start; 42 | uint16_t n_length; 43 | int8_t* n_loopstart; 44 | uint16_t n_replen; 45 | int16_t n_period; 46 | uint8_t n_finetune; 47 | int8_t n_volume; 48 | uint16_t n_dmabit; 49 | uint8_t n_toneportdirec; 50 | uint8_t n_toneportspeed; 51 | uint16_t n_wantedperiod; 52 | uint8_t n_vibratocmd; 53 | int8_t n_vibratopos; 54 | uint8_t n_tremolocmd; 55 | uint8_t n_tremolopos; 56 | uint8_t n_wavecontrol; 57 | uint8_t n_glissfunk; 58 | uint8_t n_sampleoffset; 59 | uint8_t n_pattpos; 60 | uint8_t n_loopcount; 61 | uint8_t n_funkoffset; 62 | int8_t* n_wavestart; 63 | uint16_t n_padding; 64 | }; 65 | 66 | struct ChanInput { 67 | uint16_t note; 68 | uint16_t cmd; 69 | }; 70 | 71 | void putLong(uint8_t* array, uint32_t offset, uint32_t value); 72 | void putWord(uint8_t* array, uint32_t offset, uint32_t value); 73 | uint32_t getLong(uint8_t* array, uint32_t offset); 74 | uint16_t getWord(uint8_t* array, uint32_t offset); 75 | 76 | extern AudioChannel channel0; 77 | extern AudioChannel channel1; 78 | extern AudioChannel channel2; 79 | extern AudioChannel channel3; 80 | extern AudioChannel channel4; 81 | extern AudioChannel channel5; 82 | extern AudioChannel channel6; 83 | extern AudioChannel channel7; 84 | extern void processAudio(int16_t* outputBuffer, uint32_t outputLength, uint32_t sampleRate); 85 | 86 | extern void mt_init(uint8_t* songData); 87 | extern void mt_music(); 88 | extern void mt_end(); 89 | extern void mt_start(); 90 | extern void mt_music(); 91 | extern void mt_NoNewAllChannels(); 92 | extern void mt_GetNewNote(); 93 | extern void mt_PlayVoice(AudioChannel& channel, ChanTemp& mt_chantemp, uint8_t* patternData, int patternOffset); 94 | extern void mt_NextPosition(); 95 | extern void mt_NoNewPosYet(); 96 | extern void mt_CheckEfx(AudioChannel& channel, ChanTemp& mt_chantemp); 97 | extern void mt_PerNop(AudioChannel& channel, ChanTemp& mt_chantemp); 98 | extern void mt_Arpeggio(AudioChannel& channel, ChanTemp& mt_chantemp); 99 | extern void mt_FinePortaUp(AudioChannel& channel, ChanTemp& mt_chantemp); 100 | extern void mt_PortaUp(AudioChannel& channel, ChanTemp& mt_chantemp); 101 | extern void mt_FinePortaDown(AudioChannel& channel, ChanTemp& mt_chantemp); 102 | extern void mt_PortaDown(AudioChannel& channel, ChanTemp& mt_chantemp); 103 | extern void mt_SetTonePorta(AudioChannel& channel, ChanTemp& mt_chantemp); 104 | extern void mt_TonePortamento(AudioChannel& channel, ChanTemp& mt_chantemp); 105 | extern void mt_TonePortNoChange(AudioChannel& channel, ChanTemp& mt_chantemp); 106 | extern void mt_Vibrato(AudioChannel& channel, ChanTemp& mt_chantemp); 107 | extern void mt_Vibrato2(AudioChannel& channel, ChanTemp& mt_chantemp); 108 | extern void mt_TonePlusVolSlide(AudioChannel& channel, ChanTemp& mt_chantemp); 109 | extern void mt_VibratoPlusVolSlide(AudioChannel& channel, ChanTemp& mt_chantemp); 110 | extern void mt_Tremolo(AudioChannel& channel, ChanTemp& mt_chantemp); 111 | extern void mt_SampleOffset(AudioChannel& channel, ChanTemp& mt_chantemp); 112 | extern void mt_VolumeSlide(AudioChannel& channel, ChanTemp& mt_chantemp); 113 | extern void mt_VolSlideUp(AudioChannel& channel, ChanTemp& mt_chantemp, int amount); 114 | extern void mt_VolSlideDown(AudioChannel& channel, ChanTemp& mt_chantemp, int amount); 115 | extern void mt_PositionJump(AudioChannel& channel, ChanTemp& mt_chantemp); 116 | extern void mt_VolumeChange(AudioChannel& channel, ChanTemp& mt_chantemp); 117 | extern void mt_PatternBreak(AudioChannel& channel, ChanTemp& mt_chantemp); 118 | extern void mt_SetSpeed(AudioChannel& channel, ChanTemp& mt_chantemp); 119 | extern void mt_CheckMoreEfx(AudioChannel& channel, ChanTemp& mt_chantemp); 120 | extern void mt_E_Commands(AudioChannel& channel, ChanTemp& mt_chantemp); 121 | extern void mt_FilterOnOff(AudioChannel& channel, ChanTemp& mt_chantemp); 122 | extern void mt_SetGlissControl(AudioChannel& channel, ChanTemp& mt_chantemp); 123 | extern void mt_SetVibratoControl(AudioChannel& channel, ChanTemp& mt_chantemp); 124 | extern void mt_SetFineTune(AudioChannel& channel, ChanTemp& mt_chantemp); 125 | extern void mt_JumpLoop(AudioChannel& channel, ChanTemp& mt_chantemp); 126 | extern void mt_SetTremoloControl(AudioChannel& channel, ChanTemp& mt_chantemp); 127 | extern void mt_RetrigNote(AudioChannel& channel, ChanTemp& mt_chantemp); 128 | extern void mt_DoRetrig(AudioChannel& channel, ChanTemp& mt_chantemp); 129 | extern void mt_VolumeFineUp(AudioChannel& channel, ChanTemp& mt_chantemp); 130 | extern void mt_VolumeFineDown(AudioChannel& channel, ChanTemp& mt_chantemp); 131 | extern void mt_NoteCut(AudioChannel& channel, ChanTemp& mt_chantemp); 132 | extern void mt_NoteDelay(AudioChannel& channel, ChanTemp& mt_chantemp); 133 | extern void mt_PatternDelay(AudioChannel& channel, ChanTemp& mt_chantemp); 134 | extern void mt_FunkIt(AudioChannel& channel, ChanTemp& mt_chantemp); 135 | extern void mt_UpdateFunk(AudioChannel& channel, ChanTemp& mt_chantemp); 136 | 137 | extern uint8_t mt_FunkTable[]; 138 | extern uint8_t mt_VibratoTable[]; 139 | extern uint16_t mt_PeriodTable[]; 140 | 141 | extern ChanTemp mt_chan1temp; 142 | extern ChanTemp mt_chan2temp; 143 | extern ChanTemp mt_chan3temp; 144 | extern ChanTemp mt_chan4temp; 145 | extern ChanTemp mt_chan5temp; 146 | extern ChanTemp mt_chan6temp; 147 | extern ChanTemp mt_chan7temp; 148 | extern ChanTemp mt_chan8temp; 149 | extern int8_t* mt_SampleStarts[31]; 150 | extern uint8_t* mt_SongDataPtr; 151 | extern uint8_t mt_speed; 152 | extern uint8_t mt_counter; 153 | extern uint8_t mt_SongPos; 154 | extern uint8_t mt_PBreakPos; 155 | extern uint8_t mt_PosJumpFlag; 156 | extern uint8_t mt_PBreakFlag; 157 | extern uint8_t mt_LowMask; 158 | extern uint8_t mt_PattDelTime; 159 | extern uint8_t mt_PattDelTime2; 160 | extern bool mt_Enable; 161 | extern uint16_t mt_PatternPos; 162 | extern ChanInput mt_chaninputs[4]; 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /Palette.cpp: -------------------------------------------------------------------------------- 1 | #include "Palette.h" 2 | 3 | static uint8_t fadeTable[16][16]; 4 | 5 | void Palette::initialize() 6 | { 7 | for (int fade = 1; fade < 16; fade++) { 8 | for (int value = 0; value < 16; value++) { 9 | fadeTable[fade][value] = (uint8_t)((fade * value) / 15); 10 | } 11 | } 12 | } 13 | 14 | Palette::Palette(const uint16_t* palette, uint16_t colorCount, uint16_t fade, uint16_t fadeBaseColor) : 15 | sourcePalette(0), 16 | currentPalette(0), 17 | fade_(fade), 18 | fadeBaseColor(fadeBaseColor) 19 | { 20 | if (palette) { 21 | setPalette(palette, colorCount); 22 | 23 | if (fade_ != 15) { 24 | update(); 25 | } 26 | } 27 | } 28 | 29 | Palette::~Palette() 30 | { 31 | delete[] sourcePalette; 32 | delete[] currentPalette; 33 | } 34 | 35 | void Palette::setPalette(const uint16_t* palette, uint16_t colorCount) 36 | { 37 | delete[] sourcePalette; 38 | delete[] currentPalette; 39 | 40 | sourcePalette = new uint16_t[colorCount]; 41 | currentPalette = new uint16_t[colorCount]; 42 | colorCount_ = colorCount; 43 | 44 | for (int i = 0; i < colorCount; i++) { 45 | sourcePalette[i] = palette[i]; 46 | currentPalette[i] = palette[i]; 47 | } 48 | } 49 | 50 | uint16_t Palette::colorCount() const 51 | { 52 | return colorCount_; 53 | } 54 | 55 | void Palette::setFade(uint16_t fade) 56 | { 57 | fade_ = fade; 58 | update(); 59 | } 60 | 61 | uint16_t Palette::fade() const 62 | { 63 | return fade_; 64 | } 65 | 66 | void Palette::setFadeBaseColor(uint16_t fadeBaseColor) 67 | { 68 | this->fadeBaseColor = fadeBaseColor; 69 | } 70 | 71 | uint16_t* Palette::palette() const 72 | { 73 | return currentPalette; 74 | } 75 | 76 | void Palette::update() 77 | { 78 | uint16_t baseR = fadeBaseColor >> 8; 79 | uint16_t baseG = (fadeBaseColor & 0x0f0) >> 4; 80 | uint16_t baseB = fadeBaseColor & 0x00f; 81 | for (uint16_t i = 0; i < colorCount_; i++) { 82 | uint16_t color = sourcePalette[i]; 83 | uint16_t r = color >> 8; 84 | uint16_t g = (color & 0x0f0) >> 4; 85 | uint16_t b = color & 0x00f; 86 | int16_t rDelta = r - baseR; 87 | int16_t gDelta = g - baseG; 88 | int16_t bDelta = b - baseB; 89 | uint16_t fadedR = baseR + (rDelta >= 0 ? fadeTable[fade_][rDelta] : -fadeTable[fade_][-rDelta]); 90 | uint16_t fadedG = baseG + (gDelta >= 0 ? fadeTable[fade_][gDelta] : -fadeTable[fade_][-gDelta]); 91 | uint16_t fadedB = baseB + (bDelta >= 0 ? fadeTable[fade_][bDelta] : -fadeTable[fade_][-bDelta]); 92 | currentPalette[i] = (uint16_t)((fadedR << 8) | (fadedG << 4) | fadedB); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Palette.h: -------------------------------------------------------------------------------- 1 | #ifndef _PALETTE_H 2 | #define _PALETTE_H 3 | 4 | #include "Platform.h" 5 | 6 | class Palette { 7 | public: 8 | static void initialize(); 9 | 10 | Palette(const uint16_t* palette = 0, uint16_t colorCount = 0, uint16_t fade = 15, uint16_t fadeBaseColor = 0x000); 11 | ~Palette(); 12 | 13 | void setPalette(const uint16_t* palette, uint16_t colorCount); 14 | __inline uint16_t colorCount() const; 15 | void setFade(uint16_t fade); 16 | __inline uint16_t fade() const; 17 | void setFadeBaseColor(uint16_t fadeBaseColor); 18 | __inline uint16_t* palette() const; 19 | 20 | uint16_t operator[](int index) { return currentPalette[index]; } 21 | const uint16_t operator[](int index) const { return currentPalette[index]; } 22 | 23 | private: 24 | void update(); 25 | 26 | uint16_t* sourcePalette; 27 | uint16_t* currentPalette; 28 | uint16_t colorCount_; 29 | uint16_t fade_; 30 | uint16_t fadeBaseColor; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Platform.cpp: -------------------------------------------------------------------------------- 1 | #include "Platform.h" 2 | 3 | Platform::Platform() : 4 | quit(false) 5 | { 6 | } 7 | 8 | Platform::~Platform() 9 | { 10 | } 11 | 12 | void Platform::show() 13 | { 14 | } 15 | 16 | void Platform::chrout(uint8_t) 17 | { 18 | } 19 | 20 | void Platform::keyRepeat() 21 | { 22 | } 23 | 24 | bool Platform::isKeyOrJoystickPressed(bool) 25 | { 26 | return false; 27 | } 28 | 29 | uint16_t Platform::readJoystick(bool) 30 | { 31 | return 0; 32 | } 33 | 34 | void Platform::displayImage(Image) 35 | { 36 | } 37 | 38 | void Platform::updateTiles(uint8_t*, uint8_t*, uint8_t) 39 | { 40 | } 41 | 42 | void Platform::renderTiles(uint8_t, uint8_t, uint16_t, uint16_t, uint8_t, uint8_t) 43 | { 44 | } 45 | 46 | void Platform::renderItem(uint8_t, uint16_t, uint16_t) 47 | { 48 | } 49 | 50 | void Platform::renderKey(uint8_t, uint16_t, uint16_t) 51 | { 52 | } 53 | 54 | void Platform::renderHealth(uint8_t, uint16_t, uint16_t) 55 | { 56 | } 57 | 58 | void Platform::renderFace(uint8_t, uint16_t, uint16_t) 59 | { 60 | } 61 | 62 | void Platform::renderLiveMap(uint8_t*) 63 | { 64 | } 65 | 66 | void Platform::renderLiveMapTile(uint8_t*, uint8_t, uint8_t) 67 | { 68 | } 69 | 70 | void Platform::renderLiveMapUnits(uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t, bool) 71 | { 72 | } 73 | 74 | void Platform::showCursor(uint16_t, uint16_t) 75 | { 76 | } 77 | 78 | void Platform::hideCursor() 79 | { 80 | } 81 | 82 | void Platform::setCursorShape(CursorShape) 83 | { 84 | } 85 | 86 | void Platform::fillRect(uint16_t, uint16_t, uint16_t, uint16_t, uint8_t) 87 | { 88 | } 89 | 90 | void Platform::startShakeScreen() 91 | { 92 | } 93 | 94 | void Platform::shakeScreen() 95 | { 96 | } 97 | 98 | void Platform::stopShakeScreen() 99 | { 100 | } 101 | 102 | void Platform::startFadeScreen(uint16_t, uint16_t) 103 | { 104 | } 105 | 106 | void Platform::fadeScreen(uint16_t, bool) 107 | { 108 | } 109 | 110 | void Platform::stopFadeScreen() 111 | { 112 | } 113 | 114 | void Platform::playNote(uint8_t) 115 | { 116 | } 117 | 118 | void Platform::stopNote() 119 | { 120 | } 121 | 122 | void Platform::loadModule(Module) 123 | { 124 | } 125 | 126 | void Platform::playModule(Module) 127 | { 128 | } 129 | 130 | void Platform::pauseModule() 131 | { 132 | } 133 | 134 | void Platform::stopModule() 135 | { 136 | } 137 | 138 | void Platform::playSample(uint8_t) 139 | { 140 | } 141 | 142 | void Platform::stopSample() 143 | { 144 | } 145 | 146 | void Platform::renderFrame(bool) 147 | { 148 | } 149 | 150 | void Platform::waitForScreenMemoryAccess() 151 | { 152 | } 153 | 154 | Platform* platform = 0; 155 | -------------------------------------------------------------------------------- /Platform.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLATFORM_H 2 | #define _PLATFORM_H 3 | 4 | #define SCREEN_WIDTH_IN_CHARACTERS (PLATFORM_SCREEN_WIDTH / 8) 5 | #define SCREEN_HEIGHT_IN_CHARACTERS (PLATFORM_SCREEN_HEIGHT / 8) 6 | 7 | #if __cplusplus < 201103L 8 | typedef char int8_t; 9 | typedef short int16_t; 10 | typedef long int32_t; 11 | typedef unsigned char uint8_t; 12 | typedef unsigned short uint16_t; 13 | typedef unsigned long uint32_t; 14 | #define true 1 15 | #define false 0 16 | #define INT32_MAX 0x7fffffff 17 | #define INT32_MIN 0x80000000 18 | #define INT16_MAX 0x7fff 19 | #define INT16_MIN 0x8000 20 | #define INT8_MAX 0x7f 21 | #define INT8_MIN 0x80 22 | #else 23 | #include 24 | #endif 25 | 26 | #if (PLATFORM_MAP_WINDOW_TILES_WIDTH == 11 && PLATFORM_MAP_WINDOW_TILES_HEIGHT == 7) 27 | typedef uint16_t address_t; 28 | #else 29 | typedef uint32_t address_t; 30 | #endif 31 | 32 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 33 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 34 | #define ABS(a) ((a) >= 0 ? (a) : -(a)) 35 | 36 | class Platform { 37 | public: 38 | Platform(); 39 | virtual ~Platform(); 40 | 41 | enum Image { 42 | ImageIntro, 43 | ImageGame, 44 | ImageGameOver 45 | }; 46 | 47 | enum Module { 48 | ModuleSoundFX, 49 | ModuleIntro, 50 | ModuleWin, 51 | ModuleLose, 52 | ModuleInGame1, 53 | ModuleInGame2, 54 | ModuleInGame3, 55 | ModuleInGame4 56 | }; 57 | 58 | enum JoystickBits { 59 | JoystickBitRight, 60 | JoystickBitLeft, 61 | JoystickBitDown, 62 | JoystickBitUp, 63 | JoystickBitRed, 64 | JoystickBitBlue, 65 | JoystickBitGreen, 66 | JoystickBitYellow, 67 | JoystickBitPlay, 68 | JoystickBitReverse, 69 | JoystickBitForward, 70 | JoystickBitExtra 71 | }; 72 | 73 | enum JoystickMask { 74 | JoystickRight = (1 << JoystickBitRight), 75 | JoystickLeft = (1 << JoystickBitLeft), 76 | JoystickDown = (1 << JoystickBitDown), 77 | JoystickUp = (1 << JoystickBitUp), 78 | JoystickRed = (1 << JoystickBitRed), 79 | JoystickBlue = (1 << JoystickBitBlue), 80 | JoystickGreen = (1 << JoystickBitGreen), 81 | JoystickYellow = (1 << JoystickBitYellow), 82 | JoystickPlay = (1 << JoystickBitPlay), 83 | JoystickReverse = (1 << JoystickBitReverse), 84 | JoystickForward = (1 << JoystickBitForward), 85 | JoystickExtra = (1 << JoystickBitExtra) 86 | }; 87 | 88 | enum CursorShape { 89 | ShapeUse, 90 | ShapeSearch, 91 | ShapeMove 92 | }; 93 | 94 | virtual uint8_t* standardControls() const = 0; 95 | virtual void setInterrupt(void (*interrupt)(void)) = 0; 96 | virtual void show(); 97 | virtual int framesPerSecond() = 0; 98 | virtual void chrout(uint8_t); 99 | virtual uint8_t readKeyboard() = 0; 100 | virtual void keyRepeat(); 101 | virtual void clearKeyBuffer() = 0; 102 | virtual bool isKeyOrJoystickPressed(bool gamepad); 103 | virtual uint16_t readJoystick(bool gamepad); 104 | virtual uint32_t load(const char* filename, uint8_t* destination, uint32_t size, uint32_t offset = 0) = 0; 105 | virtual uint8_t* loadTileset(const char* filename) = 0; 106 | virtual void displayImage(Image image); 107 | virtual void generateTiles(uint8_t* tileData, uint8_t* tileAttributes) = 0; 108 | virtual void updateTiles(uint8_t* tileData, uint8_t* tiles, uint8_t numTiles); 109 | virtual void renderTile(uint8_t tile, uint16_t x, uint16_t y, uint8_t variant = 0, bool transparent = false) = 0; 110 | virtual void renderTiles(uint8_t backgroundTile, uint8_t foregroundTile, uint16_t x, uint16_t y, uint8_t backgroundVariant = 0, uint8_t foregroundVariant = 0); 111 | virtual void renderItem(uint8_t item, uint16_t x, uint16_t y); 112 | virtual void renderKey(uint8_t key, uint16_t x, uint16_t y); 113 | virtual void renderHealth(uint8_t health, uint16_t x, uint16_t y); 114 | virtual void renderFace(uint8_t face, uint16_t x, uint16_t y); 115 | virtual void renderLiveMap(uint8_t* map); 116 | virtual void renderLiveMapTile(uint8_t* map, uint8_t x, uint8_t y); 117 | virtual void renderLiveMapUnits(uint8_t* map, uint8_t* unitTypes, uint8_t* unitX, uint8_t* unitY, uint8_t playerColor, bool showRobots); 118 | virtual void showCursor(uint16_t x, uint16_t y); 119 | virtual void hideCursor(); 120 | virtual void setCursorShape(CursorShape shape); 121 | virtual void copyRect(uint16_t sourceX, uint16_t sourceY, uint16_t destinationX, uint16_t destinationY, uint16_t width, uint16_t height) = 0; 122 | virtual void clearRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height) = 0; 123 | virtual void fillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t color); 124 | virtual void startShakeScreen(); 125 | virtual void shakeScreen(); 126 | virtual void stopShakeScreen(); 127 | virtual void startFadeScreen(uint16_t color, uint16_t intensity); 128 | virtual void fadeScreen(uint16_t intensity, bool immediate = true); 129 | virtual void stopFadeScreen(); 130 | virtual void writeToScreenMemory(address_t address, uint8_t value) = 0; 131 | virtual void writeToScreenMemory(address_t address, uint8_t value, uint8_t color, uint8_t yOffset) = 0; 132 | virtual void playNote(uint8_t note); 133 | virtual void stopNote(); 134 | virtual void loadModule(Module module); 135 | virtual void playModule(Module module); 136 | virtual void pauseModule(); 137 | virtual void stopModule(); 138 | virtual void playSample(uint8_t sample); 139 | virtual void stopSample(); 140 | virtual void renderFrame(bool waitForNextFrame = false); 141 | virtual void waitForScreenMemoryAccess(); 142 | bool quit; 143 | }; 144 | 145 | extern Platform* platform; 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /PlatformPSP.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "PT2.3A_replay_cia.h" 20 | #include "PlatformPSP.h" 21 | 22 | SCE_MODULE_INFO(petrobots, 0, 1, 0 ); 23 | int sce_newlib_heap_kb_size = 18430; 24 | unsigned int sce_user_main_thread_stack_kb_size = 16; 25 | unsigned int sce_user_main_thread_attribute = SCE_KERNEL_TH_USE_VFPU; 26 | static const SceChar8 *SOUND_THREAD_NAME = "Sound"; 27 | 28 | #define DISPLAYLIST_SIZE (409600 / sizeof(int)) 29 | #define CACHE_SIZE 344064 30 | 31 | static ScePspFMatrix4 matrix_stack[8 + 8 + 32 + 0]; 32 | static char cache[CACHE_SIZE]; 33 | static int cacheSize = 0; 34 | 35 | #define LARGEST_MODULE_SIZE 105654 36 | #define TOTAL_SAMPLE_SIZE 75755 37 | #define AUDIO_BUFFER_SIZE 256 38 | #define SAMPLERATE 44100 39 | 40 | extern uint8_t tileset[]; 41 | extern uint32_t font[]; 42 | extern uint32_t faces[]; 43 | extern uint32_t tiles[]; 44 | extern uint32_t sprites[]; 45 | extern uint32_t animTiles[]; 46 | extern uint32_t items[]; 47 | extern uint32_t keys[]; 48 | extern uint32_t health[]; 49 | extern uint32_t introScreen[]; 50 | extern uint32_t gameScreen[]; 51 | extern uint32_t gameOver[]; 52 | extern uint8_t levelA[]; 53 | extern uint8_t levelAEnd[]; 54 | extern uint8_t levelB[]; 55 | extern uint8_t levelBEnd[]; 56 | extern uint8_t levelC[]; 57 | extern uint8_t levelCEnd[]; 58 | extern uint8_t levelD[]; 59 | extern uint8_t levelDEnd[]; 60 | extern uint8_t levelE[]; 61 | extern uint8_t levelEEnd[]; 62 | extern uint8_t levelF[]; 63 | extern uint8_t levelFEnd[]; 64 | extern uint8_t levelG[]; 65 | extern uint8_t levelGEnd[]; 66 | extern uint8_t levelH[]; 67 | extern uint8_t levelHEnd[]; 68 | extern uint8_t levelI[]; 69 | extern uint8_t levelIEnd[]; 70 | extern uint8_t levelJ[]; 71 | extern uint8_t levelJEnd[]; 72 | extern uint8_t levelK[]; 73 | extern uint8_t levelKEnd[]; 74 | extern uint8_t levelL[]; 75 | extern uint8_t levelLEnd[]; 76 | extern uint8_t levelM[]; 77 | extern uint8_t levelMEnd[]; 78 | extern uint8_t levelN[]; 79 | extern uint8_t levelNEnd[]; 80 | extern uint8_t moduleSoundFX[]; 81 | extern uint8_t moduleSoundFXEnd[]; 82 | extern uint8_t moduleMetalHeads[]; 83 | extern uint8_t moduleMetalHeadsEnd[]; 84 | extern uint8_t moduleWin[]; 85 | extern uint8_t moduleWinEnd[]; 86 | extern uint8_t moduleLose[]; 87 | extern uint8_t moduleLoseEnd[]; 88 | extern uint8_t moduleMetallicBopAmiga[]; 89 | extern uint8_t moduleMetallicBopAmigaEnd[]; 90 | extern uint8_t moduleGetPsyched[]; 91 | extern uint8_t moduleGetPsychedEnd[]; 92 | extern uint8_t moduleRobotAttack[]; 93 | extern uint8_t moduleRobotAttackEnd[]; 94 | extern uint8_t moduleRushinIn[]; 95 | extern uint8_t moduleRushinInEnd[]; 96 | extern int8_t soundExplosion[]; 97 | extern int8_t soundExplosionEnd[]; 98 | extern int8_t soundMedkit[]; 99 | extern int8_t soundMedkitEnd[]; 100 | extern int8_t soundEMP[]; 101 | extern int8_t soundEMPEnd[]; 102 | extern int8_t soundMagnet[]; 103 | extern int8_t soundMagnetEnd[]; 104 | extern int8_t soundShock[]; 105 | extern int8_t soundShockEnd[]; 106 | extern int8_t soundMove[]; 107 | extern int8_t soundMoveEnd[]; 108 | extern int8_t soundPlasma[]; 109 | extern int8_t soundPlasmaEnd[]; 110 | extern int8_t soundPistol[]; 111 | extern int8_t soundPistolEnd[]; 112 | extern int8_t soundItemFound[]; 113 | extern int8_t soundItemFoundEnd[]; 114 | extern int8_t soundError[]; 115 | extern int8_t soundErrorEnd[]; 116 | extern int8_t soundCycleWeapon[]; 117 | extern int8_t soundCycleWeaponEnd[]; 118 | extern int8_t soundCycleItem[]; 119 | extern int8_t soundCycleItemEnd[]; 120 | extern int8_t soundDoor[]; 121 | extern int8_t soundDoorEnd[]; 122 | extern int8_t soundMenuBeep[]; 123 | extern int8_t soundMenuBeepEnd[]; 124 | extern int8_t soundShortBeep[]; 125 | extern int8_t soundShortBeepEnd[]; 126 | 127 | uint32_t* images[] = { introScreen, gameScreen, gameOver }; 128 | 129 | static int8_t tileSpriteMap[256] = { 130 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 131 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 132 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 133 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 134 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 135 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 136 | 0, 1, 49, 50, 57, 58, 59, 60, -1, -1, -1, -1, -1, -1, -1, 48, 137 | -1, -1, -1, 73, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 138 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 139 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 140 | 1, 0, 3, -1, 53, 54, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 141 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 142 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 143 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 144 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 145 | -1, -1, -1, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 146 | }; 147 | static int8_t animTileMap[256] = { 148 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 149 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 150 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 151 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 152 | -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 153 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 154 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 155 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 156 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 157 | -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 158 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 159 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 160 | -1, -1, -1, -1, 8, 10, -1, -1, 12, 14, -1, -1, 20, -1, -1, -1, 161 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 162 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 163 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 164 | }; 165 | static const char* moduleFilenames[] = { 166 | "mod.soundfx", 167 | "mod.metal heads", 168 | "mod.win", 169 | "mod.lose", 170 | "mod.metallic bop amiga", 171 | "mod.get psyched", 172 | "mod.robot attack", 173 | "mod.rushin in" 174 | }; 175 | 176 | static uint8_t standardControls[] = { 177 | 0, // MOVE UP orig: 56 (8) 178 | 0, // MOVE DOWN orig: 50 (2) 179 | 0, // MOVE LEFT orig: 52 (4) 180 | 0, // MOVE RIGHT orig: 54 (6) 181 | 0, // FIRE UP 182 | 0, // FIRE DOWN 183 | 0, // FIRE LEFT 184 | 0, // FIRE RIGHT 185 | 0, // CYCLE WEAPONS 186 | 0, // CYCLE ITEMS 187 | 0, // USE ITEM 188 | 0, // SEARCH OBEJCT 189 | 0, // MOVE OBJECT 190 | 0, // LIVE MAP 191 | 0, // LIVE MAP ROBOTS 192 | 0, // PAUSE 193 | 0, // MUSIC 194 | 0, // CHEAT 195 | 0, // CURSOR UP 196 | 0, // CURSOR DOWN 197 | 0, // CURSOR LEFT 198 | 0, // CURSOR RIGHT 199 | 0, // SPACE 200 | 0, // RETURN 201 | 0, // YES 202 | 0 // NO 203 | }; 204 | 205 | void debug(const char* message, ...) 206 | { 207 | FILE* f = fopen(SCE_FATMS_ALIAS_NAME "/log.txt", "a"); 208 | va_list argList; 209 | va_start(argList, message); 210 | vfprintf(f, message, argList); 211 | fflush(f); 212 | fclose(f); 213 | va_end(argList); 214 | } 215 | 216 | uint32_t paletteIntro[] = { 217 | 0xff000000, 218 | 0xff443300, 219 | 0xff775533, 220 | 0xff997755, 221 | 0xffccaa88, 222 | 0xff882222, 223 | 0xffcc7766, 224 | 0xffee8888, 225 | 0xffaa5577, 226 | 0xff3311aa, 227 | 0xff6644cc, 228 | 0xff4488ee, 229 | 0xff33bbee, 230 | 0xff88eeee, 231 | 0xffeeeeee, 232 | 0xff55bb77 233 | }; 234 | 235 | uint32_t paletteGame[] = { 236 | 0xff000000, 237 | 0xffffffff, 238 | 0xff775544, 239 | 0xff998877, 240 | 0xffccbbaa, 241 | 0xff993300, 242 | 0xffbb6633, 243 | 0xffffaa00, 244 | 0xff006655, 245 | 0xff009977, 246 | 0xff00ddaa, 247 | 0xff004477, 248 | 0xff0077bb, 249 | 0xff00ccff, 250 | 0xff99aaee, 251 | 0xff0000ee 252 | }; 253 | 254 | #define LIVE_MAP_ORIGIN_X ((PLATFORM_SCREEN_WIDTH - 56 - 128 * 3) / 2) 255 | #define LIVE_MAP_ORIGIN_Y ((PLATFORM_SCREEN_HEIGHT - 32 - 64 * 3) / 2) 256 | 257 | uint8_t tileLiveMap[] = { 258 | 0,13, 1, 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1,13, 1, 259 | 1, 1, 1, 1, 1, 1, 1, 2, 8, 1, 1, 1, 1, 6,14,14, 260 | 15,13,14,15,15,13, 5,15, 6,13,13,12, 6,13,13,12, 261 | 1, 1, 1,12, 1, 9, 9, 6, 1, 9,15, 6,10,10, 1, 1, 262 | 1, 1, 7,13, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 263 | 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 264 | 2, 2,13,13,13,13,13,13, 1, 1, 1,13, 4, 4, 4, 0, 265 | 1, 1, 4,13, 4, 4, 4, 1, 1, 1, 2, 2, 2, 2, 2, 2, 266 | 1, 1,13,10, 1, 1,13, 9, 1, 1, 4, 5,13,13,13, 4, 267 | 1, 1, 1, 1,15, 5,15,15, 1, 1, 6, 6,15,15, 6, 5, 268 | 2, 2, 2, 5,13,13, 1, 7, 5, 3, 1, 7, 4, 4, 4,13, 269 | 1, 1, 1, 1, 1, 4, 4, 2, 3, 3, 3, 1, 3, 2, 3, 3, 270 | 3, 3, 3, 1, 4, 4, 9, 9, 4, 4, 2, 2, 5,11,12,12, 271 | 8, 8, 8, 9, 3, 3, 2,10, 1, 1, 1, 9, 1, 1, 1,10, 272 | 1, 1, 1,13, 8, 8,13,13, 8, 8,13,13, 3, 3,13,13, 273 | 13,13, 5,13,13,13,13,13,13,13,13,13,13,13,13,13 274 | }; 275 | uint8_t liveMapToPlane1[256]; 276 | uint8_t liveMapToPlane2[256]; 277 | uint8_t liveMapToPlane3[256]; 278 | uint8_t liveMapToPlane4[256]; 279 | uint8_t unitTypes[48]; 280 | uint8_t unitX[48]; 281 | uint8_t unitY[48]; 282 | 283 | PlatformPSP::PlatformPSP() : 284 | eDRAMAddress((uint8_t*)sceGeEdramGetAddr()), 285 | interrupt(0), 286 | framesPerSecond_(60), 287 | moduleData(new uint8_t[LARGEST_MODULE_SIZE]), 288 | loadedModule(ModuleSoundFX), 289 | effectChannel(0), 290 | audioBuffer(new int16_t[AUDIO_BUFFER_SIZE]), 291 | audioOutputBuffer(new SceShort16[AUDIO_BUFFER_SIZE * 2 * 2]), 292 | audioOutputBufferOffset(0), 293 | audioThreadId(0), 294 | displayList(new int[DISPLAYLIST_SIZE]), 295 | joystickStateToReturn(0), 296 | joystickState(0), 297 | palette(paletteIntro), 298 | cursorX(-1), 299 | cursorY(-1), 300 | cursorShape(ShapeUse), 301 | scaleX(1.0f), 302 | scaleY(1.0f), 303 | fadeBaseColor(0), 304 | fadeIntensity(0), 305 | drawToBuffer0(false), 306 | swapBuffers(false), 307 | isDirty(false) 308 | { 309 | // Clear the first two bytes of effect samples to enable the 2-byte no-loop loop 310 | *((uint16_t*)soundExplosion) = 0; 311 | *((uint16_t*)soundMedkit) = 0; 312 | *((uint16_t*)soundEMP) = 0; 313 | *((uint16_t*)soundMagnet) = 0; 314 | *((uint16_t*)soundShock) = 0; 315 | *((uint16_t*)soundMove) = 0; 316 | *((uint16_t*)soundPlasma) = 0; 317 | *((uint16_t*)soundPistol) = 0; 318 | *((uint16_t*)soundItemFound) = 0; 319 | *((uint16_t*)soundError) = 0; 320 | *((uint16_t*)soundCycleWeapon) = 0; 321 | *((uint16_t*)soundCycleItem) = 0; 322 | *((uint16_t*)soundDoor) = 0; 323 | *((uint16_t*)soundMenuBeep) = 0; 324 | *((uint16_t*)soundShortBeep) = 0; 325 | 326 | // Increase thread priority 327 | sceKernelChangeThreadPriority(SCE_KERNEL_TH_SELF, 40); 328 | 329 | // Set the impose language 330 | sceImposeSetLanguageMode(SCE_UTILITY_LANG_ENGLISH, SCE_UTILITY_CTRL_ASSIGN_CROSS_IS_ENTER); 331 | 332 | sceCtrlSetSamplingMode(SCE_CTRL_MODE_DIGITALONLY); 333 | 334 | if (sceWaveInit() != SCE_OK) { 335 | debug("Couldn't initialize libwave\n"); 336 | } 337 | 338 | int ret = sceWaveAudioSetFormat(0, SCE_WAVE_AUDIO_FMT_S16_STEREO); 339 | if (ret != SCE_OK && ret != (int)SCE_AUDIO_ERROR_OUTPUT_BUSY) { 340 | debug("Couldn't set audio format\n"); 341 | } 342 | 343 | sceWaveAudioSetSample(0, AUDIO_BUFFER_SIZE); 344 | sceWaveAudioSetVolume(0, SCE_WAVE_AUDIO_VOL_MAX, SCE_WAVE_AUDIO_VOL_MAX); 345 | 346 | sceGuInit(); 347 | 348 | sceGuStart(SCEGU_IMMEDIATE, displayList, DISPLAYLIST_SIZE * sizeof(int)); 349 | 350 | sceGuDrawBuffer(SCEGU_PF8888, SCEGU_VRAM_BP32_2, SCEGU_VRAM_WIDTH); 351 | sceGuDispBuffer(SCEGU_SCR_WIDTH, SCEGU_SCR_HEIGHT, SCEGU_VRAM_BP32_0, SCEGU_VRAM_WIDTH); 352 | sceGuDepthBuffer(SCEGU_VRAM_BP32_2, SCEGU_VRAM_WIDTH); 353 | 354 | sceGuOffset(SCEGU_SCR_OFFSETX, SCEGU_SCR_OFFSETY); 355 | sceGuViewport(2048, 2048, SCEGU_SCR_WIDTH, SCEGU_SCR_HEIGHT); 356 | sceGuDepthRange(100, 65535); 357 | 358 | sceGuScissor(0, 0, PLATFORM_SCREEN_WIDTH, PLATFORM_SCREEN_HEIGHT); 359 | sceGuEnable(SCEGU_SCISSOR_TEST); 360 | sceGuDisable(SCEGU_CLIP_PLANE); 361 | 362 | sceGuDepthFunc(SCEGU_LEQUAL); 363 | sceGuEnable(SCEGU_TEXTURE); 364 | 365 | sceGuColor(0xffffffff); 366 | sceGuClearColor(0xff000000); 367 | sceGuClearDepth(0); 368 | sceGuClearStencil(0); 369 | sceGuClear(SCEGU_CLEAR_ALL); 370 | 371 | sceGuTexEnvColor(0xffffff); 372 | sceGuTexScale(1.0f, 1.0f); 373 | sceGuTexOffset(0.0f, 0.0f); 374 | sceGuTexWrap(SCEGU_CLAMP, SCEGU_CLAMP); 375 | sceGuTexFilter(SCEGU_NEAREST, SCEGU_NEAREST); 376 | sceGuTexMode(SCEGU_PF8888, 0, 0, SCEGU_TEXBUF_NORMAL); 377 | sceGuModelColor(0x00000000, 0xffffffff, 0xffffffff, 0xffffffff); 378 | 379 | sceGuFrontFace(SCEGU_CW); 380 | sceGuShadeModel(SCEGU_SMOOTH); 381 | sceGuDisable(SCEGU_DEPTH_TEST); 382 | sceGuEnable(SCEGU_BLEND); 383 | sceGuDisable(SCEGU_FOG); 384 | sceGuDisable(SCEGU_LIGHTING); 385 | sceGuBlendFunc(SCEGU_ADD, SCEGU_SRC_ALPHA, SCEGU_ONE_MINUS_SRC_ALPHA, 0, 0); 386 | sceGuTexFunc(SCEGU_TEX_MODULATE, SCEGU_RGBA); 387 | 388 | sceGumSetMatrixStack(matrix_stack, 8, 8, 32, 0); 389 | sceGumMatrixMode(SCEGU_MATRIX_WORLD); 390 | sceGumLoadIdentity(); 391 | sceGumMatrixMode(SCEGU_MATRIX_VIEW); 392 | sceGumLoadIdentity(); 393 | sceGumMatrixMode(SCEGU_MATRIX_TEXTURE); 394 | sceGumLoadIdentity(); 395 | sceGumMatrixMode(SCEGU_MATRIX_PROJECTION); 396 | sceGumLoadIdentity(); 397 | sceGumOrtho(0, SCEGU_SCR_WIDTH, 0, SCEGU_SCR_HEIGHT, -1.0f, 1.0f); 398 | sceGumMatrixMode(SCEGU_MATRIX_WORLD); 399 | 400 | sceGuDisplay(SCEGU_DISPLAY_ON); 401 | 402 | sceGuFinish(); 403 | sceGuSync(SCEGU_SYNC_FINISH, SCEGU_SYNC_WAIT); 404 | 405 | sceGuStart(SCEGU_IMMEDIATE, displayList, DISPLAYLIST_SIZE * sizeof(int)); 406 | 407 | platform = this; 408 | 409 | PlatformPSP* p = this; 410 | audioThreadId = sceKernelCreateThread(SOUND_THREAD_NAME, audioThread, SCE_KERNEL_USER_HIGHEST_PRIORITY, 1024, 0, NULL); 411 | sceKernelStartThread(audioThreadId, sizeof(PlatformPSP *), &p); 412 | sceKernelStartThread(sceKernelCreateThread("update_thread", callbackThread, 0x11, 2048, 0, NULL), sizeof(PlatformPSP*), &p); 413 | sceDisplaySetVblankCallback(0, vblankHandler, p); 414 | } 415 | 416 | PlatformPSP::~PlatformPSP() 417 | { 418 | sceGuFinish(); 419 | sceGuSync(SCEGU_SYNC_FINISH, SCEGU_SYNC_WAIT); 420 | sceGuTerm(); 421 | 422 | sceDisplaySetVblankCallback(0, 0, 0); 423 | 424 | if (audioThreadId != -1) { 425 | sceKernelWaitThreadEnd(audioThreadId, NULL); 426 | } 427 | 428 | sceWaveExit(); 429 | 430 | delete[] displayList; 431 | delete[] audioOutputBuffer; 432 | delete[] audioBuffer; 433 | delete[] moduleData; 434 | 435 | sceKernelExitGame(); 436 | } 437 | 438 | int PlatformPSP::callbackThread(SceSize args, void* argp) 439 | { 440 | PlatformPSP* platform = *((PlatformPSP**)argp); 441 | sceKernelRegisterExitCallback(sceKernelCreateCallback("Exit Callback", exitCallback, platform)); 442 | 443 | // Display callback notifications 444 | while (!platform->quit) { 445 | sceDisplayWaitVblankStartCB(); 446 | } 447 | 448 | return 0; 449 | } 450 | 451 | int PlatformPSP::exitCallback(int arg1, int arg2, void* common) 452 | { 453 | PlatformPSP* platform = (PlatformPSP*)common; 454 | platform->quit = true; 455 | 456 | return 0; 457 | } 458 | 459 | SceInt32 PlatformPSP::audioThread(SceSize args, SceVoid *argb) 460 | { 461 | PlatformPSP* platform = *((PlatformPSP**)argb); 462 | 463 | // Render loop 464 | while (!platform->quit) { 465 | // Process each audio channel 466 | processAudio(platform->audioBuffer, AUDIO_BUFFER_SIZE, SAMPLERATE); 467 | 468 | // Render to the actual output buffer 469 | for (int i = 0; i < AUDIO_BUFFER_SIZE; i++) { 470 | int16_t sample = platform->audioBuffer[i]; 471 | sample = sample < -8192 ? INT16_MIN : 472 | (sample >= 8192 ? INT16_MAX : (sample << 2)); 473 | platform->audioOutputBuffer[platform->audioOutputBufferOffset + i * 2] = sample; 474 | platform->audioOutputBuffer[platform->audioOutputBufferOffset + i * 2 + 1] = sample; 475 | } 476 | 477 | // Queue the output buffer for playback 478 | sceWaveAudioWriteBlocking(0, SCE_WAVE_AUDIO_VOL_MAX, SCE_WAVE_AUDIO_VOL_MAX, platform->audioOutputBuffer + platform->audioOutputBufferOffset); 479 | 480 | // Write the next data to the other part of the output buffer 481 | platform->audioOutputBufferOffset ^= AUDIO_BUFFER_SIZE * 2; 482 | } 483 | 484 | return 0; 485 | } 486 | 487 | void PlatformPSP::vblankHandler(int idx, void* cookie) 488 | { 489 | PlatformPSP* platform = (PlatformPSP*)cookie; 490 | 491 | if (idx == 0) { 492 | if (platform->swapBuffers) { 493 | sceDisplaySetFrameBuf(platform->eDRAMAddress + (uint32_t)(platform->drawToBuffer0 ? SCEGU_VRAM_BP32_0 : SCEGU_VRAM_BP32_1), 512, SCE_DISPLAY_PIXEL_RGBA8888, SCE_DISPLAY_UPDATETIMING_NEXTHSYNC); 494 | platform->drawToBuffer0 = !platform->drawToBuffer0; 495 | platform->swapBuffers = false; 496 | } 497 | 498 | if (platform->interrupt) { 499 | (*platform->interrupt)(); 500 | } 501 | } 502 | } 503 | 504 | void PlatformPSP::drawRectangle(uint32_t color, uint32_t* texture, uint16_t tx, uint16_t ty, uint16_t x, uint16_t y, uint16_t width, uint16_t height) 505 | { 506 | if (texture) { 507 | sceGuEnable(SCEGU_TEXTURE); 508 | sceGuTexImage(0, texture[2], texture[3], texture[2], texture + 4); 509 | } else { 510 | sceGuDisable(SCEGU_TEXTURE); 511 | } 512 | sceGuColor(color); 513 | 514 | int oldCacheSize = cacheSize; 515 | float* data = (float*)(cache + cacheSize); 516 | if (texture) { 517 | data[0 * 5 + 0] = tx / (float)texture[2]; 518 | data[0 * 5 + 1] = ty / (float)texture[3]; 519 | data[0 * 5 + 2] = x; 520 | data[0 * 5 + 3] = (SCEGU_SCR_HEIGHT / scaleY) - y; 521 | data[0 * 5 + 4] = 0; 522 | data[1 * 5 + 0] = (tx + width) / (float)texture[2]; 523 | data[1 * 5 + 1] = (ty + height) / (float)texture[3]; 524 | data[1 * 5 + 2] = x + width; 525 | data[1 * 5 + 3] = (SCEGU_SCR_HEIGHT / scaleY) - (y + height); 526 | data[1 * 5 + 4] = 0; 527 | cacheSize += 2 * 5 * sizeof(float); 528 | 529 | sceKernelDcacheWritebackRange(data, cacheSize - oldCacheSize); 530 | sceGumDrawArray(SCEGU_PRIM_RECTANGLES, SCEGU_TEXTURE_FLOAT | SCEGU_VERTEX_FLOAT, 2, 0, data); 531 | } else { 532 | data[0 * 3 + 0] = x; 533 | data[0 * 3 + 1] = (SCEGU_SCR_HEIGHT / scaleY) - y; 534 | data[0 * 3 + 2] = 0; 535 | data[1 * 3 + 0] = x + width; 536 | data[1 * 3 + 1] = (SCEGU_SCR_HEIGHT / scaleY) - (y + height); 537 | data[1 * 3 + 2] = 0; 538 | cacheSize += 2 * 3 * sizeof(float); 539 | 540 | sceKernelDcacheWritebackRange(data, cacheSize - oldCacheSize); 541 | sceGumDrawArray(SCEGU_PRIM_RECTANGLES, SCEGU_VERTEX_FLOAT, 2, 0, data); 542 | } 543 | 544 | isDirty = true; 545 | } 546 | 547 | void PlatformPSP::undeltaSamples(uint8_t* module, uint32_t moduleSize) 548 | { 549 | uint8_t numPatterns = 0; 550 | for (int i = 0; i < module[950]; i++) { 551 | numPatterns = MAX(numPatterns, module[952 + i]); 552 | } 553 | numPatterns++; 554 | 555 | int8_t* samplesStart = (int8_t*)(module + 1084 + (numPatterns << 10)); 556 | int8_t* samplesEnd = (int8_t*)(module + moduleSize); 557 | 558 | int8_t sample = 0; 559 | for (int8_t* sampleData = samplesStart; sampleData < samplesEnd; sampleData++) { 560 | int8_t delta = *sampleData; 561 | sample += delta; 562 | *sampleData = sample; 563 | } 564 | } 565 | 566 | void PlatformPSP::setSampleData(uint8_t* module) 567 | { 568 | mt_SampleStarts[15 + 0] = soundExplosion; 569 | mt_SampleStarts[15 + 1] = soundShortBeep; 570 | mt_SampleStarts[15 + 2] = soundMedkit; 571 | mt_SampleStarts[15 + 3] = soundEMP; 572 | mt_SampleStarts[15 + 4] = soundMagnet; 573 | mt_SampleStarts[15 + 5] = soundShock; 574 | mt_SampleStarts[15 + 6] = soundMove; 575 | mt_SampleStarts[15 + 7] = soundShock; 576 | mt_SampleStarts[15 + 8] = soundPlasma; 577 | mt_SampleStarts[15 + 9] = soundPistol; 578 | mt_SampleStarts[15 + 10] = soundItemFound; 579 | mt_SampleStarts[15 + 11] = soundError; 580 | mt_SampleStarts[15 + 12] = soundCycleWeapon; 581 | mt_SampleStarts[15 + 13] = soundCycleItem; 582 | mt_SampleStarts[15 + 14] = soundDoor; 583 | mt_SampleStarts[15 + 15] = soundMenuBeep; 584 | 585 | SampleData* sampleData = (SampleData*)(module + 20); 586 | putWord((uint8_t*)&sampleData[15 + 0].length, 0, (uint16_t)(soundExplosionEnd - soundExplosion) >> 1); 587 | putWord((uint8_t*)&sampleData[15 + 1].length, 0, (uint16_t)(soundShortBeepEnd - soundShortBeep) >> 1); 588 | putWord((uint8_t*)&sampleData[15 + 2].length, 0, (uint16_t)(soundMedkitEnd - soundMedkit) >> 1); 589 | putWord((uint8_t*)&sampleData[15 + 3].length, 0, (uint16_t)(soundEMPEnd - soundEMP) >> 1); 590 | putWord((uint8_t*)&sampleData[15 + 4].length, 0, (uint16_t)(soundMagnetEnd - soundMagnet) >> 1); 591 | putWord((uint8_t*)&sampleData[15 + 5].length, 0, (uint16_t)(soundShockEnd - soundShock) >> 1); 592 | putWord((uint8_t*)&sampleData[15 + 6].length, 0, (uint16_t)(soundMoveEnd - soundMove) >> 1); 593 | putWord((uint8_t*)&sampleData[15 + 7].length, 0, (uint16_t)(soundShockEnd - soundShock) >> 1); 594 | putWord((uint8_t*)&sampleData[15 + 8].length, 0, (uint16_t)(soundPlasmaEnd - soundPlasma) >> 1); 595 | putWord((uint8_t*)&sampleData[15 + 9].length, 0, (uint16_t)(soundPistolEnd - soundPistol) >> 1); 596 | putWord((uint8_t*)&sampleData[15 + 10].length, 0, (uint16_t)(soundItemFoundEnd - soundItemFound) >> 1); 597 | putWord((uint8_t*)&sampleData[15 + 11].length, 0, (uint16_t)(soundErrorEnd - soundError) >> 1); 598 | putWord((uint8_t*)&sampleData[15 + 12].length, 0, (uint16_t)(soundCycleWeaponEnd - soundCycleWeapon) >> 1); 599 | putWord((uint8_t*)&sampleData[15 + 13].length, 0, (uint16_t)(soundCycleItemEnd - soundCycleItem) >> 1); 600 | putWord((uint8_t*)&sampleData[15 + 14].length, 0, (uint16_t)(soundDoorEnd - soundDoor) >> 1); 601 | putWord((uint8_t*)&sampleData[15 + 15].length, 0, (uint16_t)(soundMenuBeepEnd - soundMenuBeep) >> 1); 602 | for (int i = 0; i < 16; i++) { 603 | sampleData[15 + i].volume = 64; 604 | } 605 | } 606 | 607 | uint8_t* PlatformPSP::standardControls() const 608 | { 609 | return ::standardControls; 610 | } 611 | 612 | void PlatformPSP::setInterrupt(void (*interrupt)(void)) 613 | { 614 | this->interrupt = interrupt; 615 | } 616 | 617 | int PlatformPSP::framesPerSecond() 618 | { 619 | return framesPerSecond_; 620 | } 621 | 622 | uint8_t PlatformPSP::readKeyboard() 623 | { 624 | return 0xff; 625 | } 626 | 627 | void PlatformPSP::keyRepeat() 628 | { 629 | joystickStateToReturn = joystickState; 630 | } 631 | 632 | void PlatformPSP::clearKeyBuffer() 633 | { 634 | joystickStateToReturn = 0; 635 | } 636 | 637 | bool PlatformPSP::isKeyOrJoystickPressed(bool gamepad) 638 | { 639 | return joystickState != 0 && joystickState != JoystickPlay; 640 | } 641 | 642 | uint16_t PlatformPSP::readJoystick(bool gamepad) 643 | { 644 | uint16_t state = 0; 645 | 646 | // Read new input 647 | SceCtrlData ct; 648 | if (sceCtrlReadBufferPositive(&ct, 1) >= 0) { 649 | if (ct.Buttons & SCE_CTRL_LEFT) { 650 | state |= JoystickLeft; 651 | } 652 | if (ct.Buttons & SCE_CTRL_RIGHT) { 653 | state |= JoystickRight; 654 | } 655 | if (ct.Buttons & SCE_CTRL_UP) { 656 | state |= JoystickUp; 657 | } 658 | if (ct.Buttons & SCE_CTRL_DOWN) { 659 | state |= JoystickDown; 660 | } 661 | if (ct.Buttons & SCE_CTRL_SQUARE) { 662 | state |= JoystickGreen; 663 | } 664 | if (ct.Buttons & SCE_CTRL_CIRCLE) { 665 | state |= JoystickBlue; 666 | } 667 | if (ct.Buttons & SCE_CTRL_TRIANGLE) { 668 | state |= JoystickYellow; 669 | } 670 | if (ct.Buttons & SCE_CTRL_CROSS) { 671 | state |= JoystickRed; 672 | } 673 | if (ct.Buttons & SCE_CTRL_L) { 674 | state |= JoystickReverse; 675 | } 676 | if (ct.Buttons & SCE_CTRL_R) { 677 | state |= JoystickForward; 678 | } 679 | if (ct.Buttons & SCE_CTRL_START) { 680 | state |= JoystickExtra; 681 | } 682 | if (ct.Buttons & SCE_CTRL_SELECT) { 683 | state |= JoystickPlay; 684 | } 685 | } 686 | 687 | if (joystickState != state) { 688 | // Don't return Play button press 689 | joystickStateToReturn = state != JoystickPlay ? state : 0; 690 | joystickState = state; 691 | } 692 | 693 | uint16_t result = joystickStateToReturn; 694 | joystickStateToReturn = 0; 695 | return result; 696 | } 697 | 698 | struct FilenameMapping { 699 | const char* filename; 700 | uint8_t* data; 701 | uint32_t size; 702 | }; 703 | 704 | #define FILENAME_MAPPINGS 22 705 | 706 | static FilenameMapping filenameMappings[FILENAME_MAPPINGS] = { 707 | { "level-A", levelA, levelAEnd - levelA }, 708 | { "level-B", levelB, levelBEnd - levelB }, 709 | { "level-C", levelC, levelCEnd - levelC }, 710 | { "level-D", levelD, levelDEnd - levelD }, 711 | { "level-E", levelE, levelEEnd - levelE }, 712 | { "level-F", levelF, levelFEnd - levelF }, 713 | { "level-G", levelG, levelGEnd - levelG }, 714 | { "level-H", levelH, levelHEnd - levelH }, 715 | { "level-I", levelI, levelIEnd - levelI }, 716 | { "level-J", levelJ, levelJEnd - levelJ }, 717 | { "level-K", levelK, levelKEnd - levelK }, 718 | { "level-L", levelL, levelLEnd - levelL }, 719 | { "level-M", levelM, levelMEnd - levelM }, 720 | { "level-N", levelN, levelNEnd - levelN }, 721 | { "mod.soundfx", moduleSoundFX, moduleSoundFXEnd - moduleSoundFX }, 722 | { "mod.metal heads", moduleMetalHeads, moduleMetalHeadsEnd - moduleMetalHeads }, 723 | { "mod.win", moduleWin, moduleWinEnd - moduleWin }, 724 | { "mod.lose", moduleLose, moduleLoseEnd - moduleLose }, 725 | { "mod.metallic bop amiga", moduleMetallicBopAmiga, moduleMetallicBopAmigaEnd - moduleMetallicBopAmiga }, 726 | { "mod.get psyched", moduleGetPsyched, moduleGetPsychedEnd - moduleGetPsyched }, 727 | { "mod.robot attack", moduleRobotAttack, moduleRobotAttackEnd - moduleRobotAttack }, 728 | { "mod.rushin in", moduleRushinIn, moduleRushinInEnd - moduleRushinIn } 729 | }; 730 | 731 | uint32_t PlatformPSP::load(const char* filename, uint8_t* destination, uint32_t size, uint32_t offset) 732 | { 733 | for (int i = 0; i < FILENAME_MAPPINGS; i++) { 734 | if (strcmp(filename, filenameMappings[i].filename) == 0) { 735 | uint32_t availableSize = MIN(size, filenameMappings[i].size - offset); 736 | memcpy(destination, filenameMappings[i].data + offset, availableSize); 737 | return availableSize; 738 | } 739 | } 740 | 741 | return 0; 742 | } 743 | 744 | uint8_t* PlatformPSP::loadTileset(const char* filename) 745 | { 746 | return tileset; 747 | } 748 | 749 | void PlatformPSP::displayImage(Image image) 750 | { 751 | sceGumLoadIdentity(); 752 | scaleX = 1.0f; 753 | scaleY = 1.0f; 754 | 755 | sceGuScissor(0, 0, PLATFORM_SCREEN_WIDTH, PLATFORM_SCREEN_HEIGHT); 756 | 757 | this->clearRect(0, 0, SCEGU_SCR_WIDTH, SCEGU_SCR_HEIGHT); 758 | 759 | if (image == ImageGame) { 760 | palette = paletteGame; 761 | 762 | drawRectangle(0xffffffff, images[image], 320 - 56, 0, PLATFORM_SCREEN_WIDTH - 56, 0, 56, 128); 763 | 764 | for (int y = 128; y < (PLATFORM_SCREEN_HEIGHT - 32); y += 40) { 765 | drawRectangle(0xffffffff, images[image], 320 - 56, 128, PLATFORM_SCREEN_WIDTH - 56, y, 56, MIN(40, PLATFORM_SCREEN_HEIGHT - 32 - y)); 766 | } 767 | 768 | drawRectangle(0xffffffff, images[image], 320 - 56, 168, PLATFORM_SCREEN_WIDTH - 56, PLATFORM_SCREEN_HEIGHT - 32, 56, 32); 769 | 770 | drawRectangle(0xffffffff, images[image], 0, 168, 0, PLATFORM_SCREEN_HEIGHT - 32, 104, 8); 771 | 772 | for (int x = 104; x < (PLATFORM_SCREEN_WIDTH - 56); x += 160) { 773 | drawRectangle(0xffffffff, images[image], 104, 168, x, PLATFORM_SCREEN_HEIGHT - 32, MIN(160, PLATFORM_SCREEN_WIDTH - 56 - x), 8); 774 | } 775 | 776 | sceGuScissor(0, 0, PLATFORM_SCREEN_WIDTH - 56, PLATFORM_SCREEN_HEIGHT - 32); 777 | } else { 778 | palette = paletteIntro; 779 | 780 | scaleX = SCEGU_SCR_WIDTH / 320.0f; 781 | scaleY = SCEGU_SCR_HEIGHT / 200.0f; 782 | 783 | ScePspFVector3 vec; 784 | vec.x = scaleX; 785 | vec.y = scaleY; 786 | vec.z = 1.0f; 787 | sceGumScale(&vec); 788 | 789 | drawRectangle(0xffffffff, images[image], 0, 0, 0, 0, images[image][0], images[image][1]); 790 | } 791 | } 792 | 793 | void PlatformPSP::generateTiles(uint8_t* tileData, uint8_t* tileAttributes) 794 | { 795 | } 796 | 797 | void PlatformPSP::renderTile(uint8_t tile, uint16_t x, uint16_t y, uint8_t variant, bool transparent) 798 | { 799 | if (transparent) { 800 | if (tileSpriteMap[tile] >= 0) { 801 | renderSprite(tileSpriteMap[tile] + variant, x, y); 802 | return; 803 | } 804 | } else { 805 | if (animTileMap[tile] >= 0) { 806 | renderAnimTile(animTileMap[tile] + variant, x, y); 807 | return; 808 | } 809 | } 810 | 811 | drawRectangle(0xffffffff, tiles, (tile & 15) * 24, (tile >> 4) * 24, x, y, 24, 24); 812 | } 813 | 814 | void PlatformPSP::renderTiles(uint8_t backgroundTile, uint8_t foregroundTile, uint16_t x, uint16_t y, uint8_t backgroundVariant, uint8_t foregroundVariant) 815 | { 816 | if (animTileMap[backgroundTile] >= 0) { 817 | backgroundTile = animTileMap[backgroundTile] + backgroundVariant; 818 | drawRectangle(0xffffffff, animTiles, (backgroundTile >> 4) * 24, (backgroundTile & 15) * 24, x, y, 24, 24); 819 | } else { 820 | drawRectangle(0xffffffff, tiles, (backgroundTile & 15) * 24, (backgroundTile >> 4) * 24, x, y, 24, 24); 821 | } 822 | 823 | if (tileSpriteMap[foregroundTile] >= 0) { 824 | uint8_t sprite = tileSpriteMap[foregroundTile] + foregroundVariant; 825 | drawRectangle(0xffffffff, sprites, (sprite >> 4) * 24, (sprite & 15) * 24, x, y, 24, 24); 826 | } else { 827 | drawRectangle(0xffffffff, tiles, (foregroundTile & 15) * 24, (foregroundTile >> 4) * 24, x, y, 24, 24); 828 | } 829 | } 830 | 831 | void PlatformPSP::renderSprite(uint8_t sprite, uint16_t x, uint16_t y) 832 | { 833 | drawRectangle(0xffffffff, sprites, (sprite >> 4) * 24, (sprite & 15) * 24, x, y, 24, 24); 834 | } 835 | 836 | void PlatformPSP::renderAnimTile(uint8_t animTile, uint16_t x, uint16_t y) 837 | { 838 | drawRectangle(0xffffffff, animTiles, (animTile >> 4) * 24, (animTile & 15) * 24, x, y, 24, 24); 839 | } 840 | 841 | void PlatformPSP::renderItem(uint8_t item, uint16_t x, uint16_t y) 842 | { 843 | sceGuDisable(SCEGU_SCISSOR_TEST); 844 | 845 | drawRectangle(0xffffffff, items, 0, item * 21, x, y, 48, 21); 846 | 847 | sceGuEnable(SCEGU_SCISSOR_TEST); 848 | } 849 | 850 | void PlatformPSP::renderKey(uint8_t key, uint16_t x, uint16_t y) 851 | { 852 | sceGuDisable(SCEGU_SCISSOR_TEST); 853 | 854 | drawRectangle(0xffffffff, keys, 0, key * 14, x, y, 16, 14); 855 | 856 | sceGuEnable(SCEGU_SCISSOR_TEST); 857 | } 858 | 859 | void PlatformPSP::renderHealth(uint8_t amount, uint16_t x, uint16_t y) 860 | { 861 | sceGuDisable(SCEGU_SCISSOR_TEST); 862 | 863 | drawRectangle(0xffffffff, health, 0, amount * 51, x, y, 48, 51); 864 | 865 | sceGuEnable(SCEGU_SCISSOR_TEST); 866 | } 867 | 868 | void PlatformPSP::renderFace(uint8_t face, uint16_t x, uint16_t y) 869 | { 870 | drawRectangle(0xffffffff, faces, 0, face * 24, x, y, 16, 24); 871 | } 872 | 873 | void PlatformPSP::renderLiveMap(uint8_t* map) 874 | { 875 | clearRect(0, 0, PLATFORM_SCREEN_WIDTH - 56, LIVE_MAP_ORIGIN_Y); 876 | clearRect(0, LIVE_MAP_ORIGIN_Y, LIVE_MAP_ORIGIN_X, PLATFORM_SCREEN_HEIGHT - 32 - 2 * LIVE_MAP_ORIGIN_Y); 877 | clearRect(PLATFORM_SCREEN_WIDTH - 56 - LIVE_MAP_ORIGIN_X, LIVE_MAP_ORIGIN_Y, LIVE_MAP_ORIGIN_X, PLATFORM_SCREEN_HEIGHT - 32 - 2 * LIVE_MAP_ORIGIN_Y); 878 | clearRect(0, PLATFORM_SCREEN_HEIGHT - 32 - LIVE_MAP_ORIGIN_Y, PLATFORM_SCREEN_WIDTH - 56, LIVE_MAP_ORIGIN_Y); 879 | 880 | sceGuEnable(SCEGU_TEXTURE); 881 | sceGuTexFilter(SCEGU_LINEAR, SCEGU_LINEAR); 882 | sceGuTexImage(0, tiles[2], tiles[3], tiles[2], tiles + 4); 883 | sceGuColor(0xffffffff); 884 | 885 | int oldCacheSize = cacheSize; 886 | float* dataStart = (float*)(cache + cacheSize); 887 | float* data = dataStart; 888 | for (int mapY = 0; mapY < 64; mapY++) { 889 | for (int mapX = 0; mapX < 128; mapX++) { 890 | int tile = *map++; 891 | int x = LIVE_MAP_ORIGIN_X + mapX * 3; 892 | int y = LIVE_MAP_ORIGIN_Y + mapY * 3; 893 | int tx = (tile & 15) * 24; 894 | int ty = (tile >> 4) * 24; 895 | 896 | *data++ = tx / (float)tiles[2]; 897 | *data++ = ty / (float)tiles[3]; 898 | *data++ = x; 899 | *data++ = (SCEGU_SCR_HEIGHT / scaleY) - y; 900 | *data++ = 0; 901 | 902 | *data++ = (tx + 24) / (float)tiles[2]; 903 | *data++ = (ty + 24) / (float)tiles[3]; 904 | *data++ = x + 3; 905 | *data++ = (SCEGU_SCR_HEIGHT / scaleY) - (y + 3); 906 | *data++ = 0; 907 | } 908 | } 909 | 910 | cacheSize += 64 * 128 * 2 * 5 * sizeof(float); 911 | 912 | sceKernelDcacheWritebackRange(dataStart, cacheSize - oldCacheSize); 913 | sceGumDrawArrayN(SCEGU_PRIM_RECTANGLES, SCEGU_TEXTURE_FLOAT | SCEGU_VERTEX_FLOAT, 2, 64 * 128, 0, dataStart); 914 | 915 | for (int i = 0; i < 48; i++) { 916 | unitTypes[i] = 255; 917 | } 918 | 919 | sceGuTexFilter(SCEGU_NEAREST, SCEGU_NEAREST); 920 | 921 | isDirty = true; 922 | } 923 | 924 | void PlatformPSP::renderLiveMapTile(uint8_t* map, uint8_t mapX, uint8_t mapY) 925 | { 926 | sceGuEnable(SCEGU_TEXTURE); 927 | sceGuTexFilter(SCEGU_LINEAR, SCEGU_LINEAR); 928 | 929 | int tile = map[(mapY << 7) + mapX]; 930 | int x = LIVE_MAP_ORIGIN_X + mapX * 3; 931 | int y = LIVE_MAP_ORIGIN_Y + mapY * 3; 932 | int tx = (tile & 15) * 24; 933 | int ty = (tile >> 4) * 24; 934 | 935 | sceGuTexImage(0, tiles[2], tiles[3], tiles[2], tiles + 4); 936 | sceGuColor(0xffffffff); 937 | 938 | int oldCacheSize = cacheSize; 939 | float* data = (float*)(cache + cacheSize); 940 | data[0 * 5 + 0] = tx / (float)tiles[2]; 941 | data[0 * 5 + 1] = ty / (float)tiles[3]; 942 | data[0 * 5 + 2] = x; 943 | data[0 * 5 + 3] = (SCEGU_SCR_HEIGHT / scaleY) - y; 944 | data[0 * 5 + 4] = 0; 945 | data[1 * 5 + 0] = (tx + 24) / (float)tiles[2]; 946 | data[1 * 5 + 1] = (ty + 24) / (float)tiles[3]; 947 | data[1 * 5 + 2] = x + 3; 948 | data[1 * 5 + 3] = (SCEGU_SCR_HEIGHT / scaleY) - (y + 3); 949 | data[1 * 5 + 4] = 0; 950 | cacheSize += 2 * 5 * sizeof(float); 951 | 952 | sceKernelDcacheWritebackRange(data, cacheSize - oldCacheSize); 953 | sceGumDrawArray(SCEGU_PRIM_RECTANGLES, SCEGU_TEXTURE_FLOAT | SCEGU_VERTEX_FLOAT, 2, 0, data); 954 | 955 | sceGuTexFilter(SCEGU_NEAREST, SCEGU_NEAREST); 956 | 957 | isDirty = true; 958 | } 959 | 960 | void PlatformPSP::renderLiveMapUnits(uint8_t* map, uint8_t* unitTypes, uint8_t* unitX, uint8_t* unitY, uint8_t playerColor, bool showRobots) 961 | { 962 | for (int i = 0; i < 48; i++) { 963 | if ((i < 28 || unitTypes[i] == 22) && (unitX[i] != ::unitX[i] || unitY[i] != ::unitY[i] || (i > 0 && (!showRobots || unitTypes[i] == 22 || unitTypes[i] != ::unitTypes[i])) || (i == 0 && playerColor != ::unitTypes[i]))) { 964 | // Remove old dot if any 965 | if (::unitTypes[i] != 255) { 966 | renderLiveMapTile(map, ::unitX[i], ::unitY[i]); 967 | 968 | if (i > 0 && !showRobots) { 969 | ::unitTypes[i] = 255; 970 | } 971 | } 972 | 973 | if (i == 0 || 974 | (unitTypes[i] == 22 && (unitX[i] != unitX[0] || unitY[i] != unitY[0])) || 975 | (showRobots && 976 | (unitTypes[i] == 1 || 977 | (unitTypes[i] >= 2 && unitTypes[i] <= 5) || 978 | (unitTypes[i] >= 17 && unitTypes[i] <= 18) || 979 | unitTypes[i] == 9))) { 980 | // Render new dot 981 | int x = unitX[i]; 982 | int y = unitY[i]; 983 | drawRectangle(palette[(i > 0 || playerColor == 1) ? 1 : 0], 0, 0, 0, LIVE_MAP_ORIGIN_X + x * 3, LIVE_MAP_ORIGIN_Y + y * 3, 3, 3); 984 | 985 | ::unitTypes[i] = i == 0 ? playerColor : unitTypes[i]; 986 | ::unitX[i] = unitX[i]; 987 | ::unitY[i] = unitY[i]; 988 | } 989 | } 990 | } 991 | 992 | isDirty = true; 993 | } 994 | 995 | void PlatformPSP::showCursor(uint16_t x, uint16_t y) 996 | { 997 | cursorX = x * 24 - 2; 998 | cursorY = y * 24 -2; 999 | 1000 | isDirty = true; 1001 | } 1002 | 1003 | void PlatformPSP::hideCursor() 1004 | { 1005 | if (cursorX != -1) { 1006 | cursorX = -1; 1007 | 1008 | isDirty = true; 1009 | } 1010 | } 1011 | 1012 | void PlatformPSP::setCursorShape(CursorShape shape) 1013 | { 1014 | cursorShape = shape; 1015 | } 1016 | 1017 | void PlatformPSP::copyRect(uint16_t sourceX, uint16_t sourceY, uint16_t destinationX, uint16_t destinationY, uint16_t width, uint16_t height) 1018 | { 1019 | sceGuDisable(SCEGU_SCISSOR_TEST); 1020 | 1021 | sceGuCopyImage(SCEGU_PF8888, sourceX, sourceY, width, height, SCEGU_VRAM_WIDTH, eDRAMAddress + (uint32_t)SCEGU_VRAM_BP32_2, destinationX, destinationY, SCEGU_VRAM_WIDTH, eDRAMAddress + (uint32_t)SCEGU_VRAM_BP32_2); 1022 | 1023 | sceGuEnable(SCEGU_SCISSOR_TEST); 1024 | 1025 | isDirty = true; 1026 | } 1027 | 1028 | void PlatformPSP::clearRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height) 1029 | { 1030 | sceGuDisable(SCEGU_SCISSOR_TEST); 1031 | 1032 | drawRectangle(0xff000000, 0, 0, 0, x, y, width, height); 1033 | 1034 | sceGuEnable(SCEGU_SCISSOR_TEST); 1035 | 1036 | isDirty = true; 1037 | } 1038 | 1039 | void PlatformPSP::startFadeScreen(uint16_t color, uint16_t intensity) 1040 | { 1041 | uint32_t r = (color & 0xf00) >> 8; 1042 | uint32_t g = (color & 0x0f0) << 4; 1043 | uint32_t b = (color & 0x00f) << 16; 1044 | uint32_t bgr = r | g | b; 1045 | fadeBaseColor = bgr | (bgr << 4); 1046 | fadeIntensity = intensity; 1047 | 1048 | isDirty = true; 1049 | } 1050 | 1051 | void PlatformPSP::fadeScreen(uint16_t intensity, bool immediate) 1052 | { 1053 | if (fadeIntensity != intensity) { 1054 | if (immediate) { 1055 | fadeIntensity = intensity; 1056 | 1057 | isDirty = true; 1058 | } else { 1059 | int16_t fadeDelta = intensity > fadeIntensity ? 1 : -1; 1060 | do { 1061 | fadeIntensity += fadeDelta; 1062 | 1063 | isDirty = true; 1064 | 1065 | this->renderFrame(true); 1066 | } while (fadeIntensity != intensity); 1067 | } 1068 | } 1069 | } 1070 | 1071 | void PlatformPSP::stopFadeScreen() 1072 | { 1073 | fadeIntensity = 15; 1074 | isDirty = true; 1075 | } 1076 | 1077 | void PlatformPSP::writeToScreenMemory(address_t address, uint8_t value) 1078 | { 1079 | sceGuDisable(SCEGU_SCISSOR_TEST); 1080 | 1081 | if (scaleX == 1.0f && (address % SCREEN_WIDTH_IN_CHARACTERS) == (SCREEN_WIDTH_IN_CHARACTERS - 7)) { 1082 | return; 1083 | } 1084 | 1085 | if (value > 127) { 1086 | value &= 127; 1087 | drawRectangle(0xff55bb77, 0, 0, 0, (address % SCREEN_WIDTH_IN_CHARACTERS) << 3, (address / SCREEN_WIDTH_IN_CHARACTERS) << 3, 8, 8); 1088 | drawRectangle(0xff000000, font, (value >> 3) & 0x8, (value << 3) & 0x1ff, (address % SCREEN_WIDTH_IN_CHARACTERS) << 3, (address / SCREEN_WIDTH_IN_CHARACTERS) << 3, 8, 8); 1089 | } else { 1090 | sceGuDisable(SCEGU_BLEND); 1091 | drawRectangle(0xff55bb77, font, (value >> 3) & 0x8, (value << 3) & 0x1ff, (address % SCREEN_WIDTH_IN_CHARACTERS) << 3, (address / SCREEN_WIDTH_IN_CHARACTERS) << 3, 8, 8); 1092 | sceGuEnable(SCEGU_BLEND); 1093 | } 1094 | 1095 | sceGuEnable(SCEGU_SCISSOR_TEST); 1096 | } 1097 | 1098 | void PlatformPSP::writeToScreenMemory(address_t address, uint8_t value, uint8_t color, uint8_t yOffset) 1099 | { 1100 | sceGuDisable(SCEGU_SCISSOR_TEST); 1101 | 1102 | if (scaleX == 1.0f && (address % SCREEN_WIDTH_IN_CHARACTERS) == (SCREEN_WIDTH_IN_CHARACTERS - 7)) { 1103 | return; 1104 | } 1105 | 1106 | if (value > 127) { 1107 | value &= 127; 1108 | drawRectangle(palette[color], 0, 0, 0, (address % SCREEN_WIDTH_IN_CHARACTERS) << 3, ((address / SCREEN_WIDTH_IN_CHARACTERS) << 3) + yOffset, 8, 8); 1109 | drawRectangle(0xff000000, font, (value >> 3) & 0x8, (value << 3) & 0x1ff, (address % SCREEN_WIDTH_IN_CHARACTERS) << 3, ((address / SCREEN_WIDTH_IN_CHARACTERS) << 3) + yOffset, 8, 8); 1110 | } else { 1111 | sceGuDisable(SCEGU_BLEND); 1112 | drawRectangle(palette[color], font, (value >> 3) & 0x8, (value << 3) & 0x1ff, (address % SCREEN_WIDTH_IN_CHARACTERS) << 3, ((address / SCREEN_WIDTH_IN_CHARACTERS) << 3) + yOffset, 8, 8); 1113 | sceGuEnable(SCEGU_BLEND); 1114 | } 1115 | 1116 | sceGuEnable(SCEGU_SCISSOR_TEST); 1117 | } 1118 | 1119 | void PlatformPSP::loadModule(Module module) 1120 | { 1121 | if (loadedModule != module) { 1122 | uint32_t moduleSize = load(moduleFilenames[module], moduleData, LARGEST_MODULE_SIZE, 0); 1123 | undeltaSamples(moduleData, moduleSize); 1124 | setSampleData(moduleData); 1125 | loadedModule = module; 1126 | } 1127 | } 1128 | 1129 | void PlatformPSP::playModule(Module module) 1130 | { 1131 | stopModule(); 1132 | stopSample(); 1133 | 1134 | loadModule(module); 1135 | mt_init(moduleData); 1136 | 1137 | mt_Enable = true; 1138 | } 1139 | 1140 | void PlatformPSP::pauseModule() 1141 | { 1142 | mt_speed = 0; 1143 | mt_music(); 1144 | mt_Enable = false; 1145 | channel0.volume = 0; 1146 | channel1.volume = 0; 1147 | channel2.volume = 0; 1148 | channel3.volume = 0; 1149 | } 1150 | 1151 | void PlatformPSP::stopModule() 1152 | { 1153 | mt_end(); 1154 | } 1155 | 1156 | void PlatformPSP::playSample(uint8_t sample) 1157 | { 1158 | ChanInput* input = &mt_chaninputs[effectChannel < 2 ? effectChannel : (5 - effectChannel)]; 1159 | 1160 | effectChannel++; 1161 | effectChannel &= 3; 1162 | 1163 | putWord((uint8_t*)&input->note, 0, 0x1000 + 320); 1164 | if (sample < 16) { 1165 | putWord((uint8_t*)&input->cmd, 0, sample << 12); 1166 | } else if (sample == 16) { 1167 | putWord((uint8_t*)&input->cmd, 0, 1 << 12); 1168 | } else { 1169 | putWord((uint8_t*)&input->cmd, 0, 15 << 12); 1170 | } 1171 | } 1172 | 1173 | void PlatformPSP::stopSample() 1174 | { 1175 | for (int i = 0; i < 4; i++) { 1176 | mt_chaninputs[i].note = 0; 1177 | mt_chaninputs[i].cmd = 0; 1178 | } 1179 | } 1180 | 1181 | void PlatformPSP::renderFrame(bool waitForNextFrame) 1182 | { 1183 | if (!isDirty) { 1184 | return; 1185 | } 1186 | 1187 | while (swapBuffers); 1188 | 1189 | sceGuCopyImage(SCEGU_PF8888, 0, 0, SCEGU_SCR_WIDTH, SCEGU_SCR_HEIGHT, SCEGU_VRAM_WIDTH, eDRAMAddress + (uint32_t)SCEGU_VRAM_BP32_2, 0, 0, SCEGU_VRAM_WIDTH, eDRAMAddress + (uint32_t)(drawToBuffer0 ? SCEGU_VRAM_BP32_0 : SCEGU_VRAM_BP32_1)); 1190 | sceGuDrawBuffer(SCEGU_PF8888, drawToBuffer0 ? SCEGU_VRAM_BP32_0 : SCEGU_VRAM_BP32_1, SCEGU_VRAM_WIDTH); 1191 | sceGuDisable(SCEGU_SCISSOR_TEST); 1192 | 1193 | if (cursorX != -1) { 1194 | drawRectangle(0xffffffff, 0, 0, 0, cursorX, cursorY, 28, 2); 1195 | drawRectangle(0xffffffff, 0, 0, 0, cursorX, cursorY + 2, 2, 24); 1196 | drawRectangle(0xffffffff, 0, 0, 0, cursorX + 26, cursorY + 2, 2, 24); 1197 | drawRectangle(0xffffffff, 0, 0, 0, cursorX, cursorY + 26, 28, 2); 1198 | if (cursorShape != ShapeUse) { 1199 | renderSprite(cursorShape == ShapeSearch ? 83 : 85, cursorX + 2, cursorY + 2); 1200 | } 1201 | } 1202 | 1203 | if (fadeIntensity != 15) { 1204 | uint32_t intensity = (15 - fadeIntensity) << 24; 1205 | uint32_t abgr = intensity | (intensity << 4) | fadeBaseColor; 1206 | drawRectangle(abgr, 0, 0, 0, 0, 0, SCEGU_SCR_WIDTH, SCEGU_SCR_HEIGHT); 1207 | } 1208 | sceGuFinish(); 1209 | sceGuSync(SCEGU_SYNC_FINISH, SCEGU_SYNC_WAIT); 1210 | 1211 | swapBuffers = true; 1212 | cacheSize = 0; 1213 | 1214 | sceGuStart(SCEGU_IMMEDIATE, displayList, DISPLAYLIST_SIZE * sizeof(int)); 1215 | sceGuDrawBuffer(SCEGU_PF8888, SCEGU_VRAM_BP32_2, SCEGU_VRAM_WIDTH); 1216 | sceGuEnable(SCEGU_SCISSOR_TEST); 1217 | 1218 | isDirty = false; 1219 | } 1220 | -------------------------------------------------------------------------------- /PlatformPSP.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLATFORMPSP_H 2 | #define _PLATFORMPSP_H 3 | 4 | #define PlatformClass PlatformPSP 5 | 6 | #include 7 | #include 8 | #include "Platform.h" 9 | 10 | extern void debug(const char *message, ...); 11 | 12 | class PlatformPSP : public Platform { 13 | public: 14 | PlatformPSP(); 15 | virtual ~PlatformPSP(); 16 | 17 | virtual uint8_t* standardControls() const; 18 | virtual void setInterrupt(void (*interrupt)(void)); 19 | virtual int framesPerSecond(); 20 | virtual uint8_t readKeyboard(); 21 | virtual void keyRepeat(); 22 | virtual void clearKeyBuffer(); 23 | virtual bool isKeyOrJoystickPressed(bool gamepad); 24 | virtual uint16_t readJoystick(bool gamepad); 25 | virtual uint32_t load(const char* filename, uint8_t* destination, uint32_t size, uint32_t offset = 0); 26 | virtual uint8_t* loadTileset(const char* filename); 27 | virtual void displayImage(Image image); 28 | virtual void generateTiles(uint8_t* tileData, uint8_t* tileAttributes); 29 | virtual void renderTile(uint8_t tile, uint16_t x, uint16_t y, uint8_t variant = 0, bool transparent = false); 30 | virtual void renderTiles(uint8_t backgroundTile, uint8_t foregroundTile, uint16_t x, uint16_t y, uint8_t backgroundVariant, uint8_t foregroundVariant); 31 | virtual void renderItem(uint8_t item, uint16_t x, uint16_t y); 32 | virtual void renderKey(uint8_t key, uint16_t x, uint16_t y); 33 | virtual void renderHealth(uint8_t health, uint16_t x, uint16_t y); 34 | virtual void renderFace(uint8_t face, uint16_t x, uint16_t y); 35 | virtual void renderLiveMap(uint8_t* map); 36 | virtual void renderLiveMapTile(uint8_t* map, uint8_t x, uint8_t y); 37 | virtual void renderLiveMapUnits(uint8_t* map, uint8_t* unitTypes, uint8_t* unitX, uint8_t* unitY, uint8_t playerColor, bool showRobots); 38 | virtual void showCursor(uint16_t x, uint16_t y); 39 | virtual void hideCursor(); 40 | virtual void setCursorShape(CursorShape shape); 41 | virtual void copyRect(uint16_t sourceX, uint16_t sourceY, uint16_t destinationX, uint16_t destinationY, uint16_t width, uint16_t height); 42 | virtual void clearRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height); 43 | virtual void startFadeScreen(uint16_t color, uint16_t intensity); 44 | virtual void fadeScreen(uint16_t intensity, bool immediate); 45 | virtual void stopFadeScreen(); 46 | virtual void writeToScreenMemory(address_t address, uint8_t value); 47 | virtual void writeToScreenMemory(address_t address, uint8_t value, uint8_t color, uint8_t yOffset); 48 | virtual void loadModule(Module module); 49 | virtual void playModule(Module module); 50 | virtual void pauseModule(); 51 | virtual void stopModule(); 52 | virtual void playSample(uint8_t sample); 53 | virtual void stopSample(); 54 | virtual void renderFrame(bool waitForNextFrame); 55 | 56 | private: 57 | static int callbackThread(SceSize args, void* argp); 58 | static int exitCallback(int arg1, int arg2, void* common); 59 | static SceInt32 audioThread(SceSize args, SceVoid* argb); 60 | static void vblankHandler(int idx, void* cookie); 61 | void drawRectangle(uint32_t color, uint32_t* texture, uint16_t tx, uint16_t ty, uint16_t x, uint16_t y, uint16_t width, uint16_t height); 62 | void undeltaSamples(uint8_t* module, uint32_t moduleSize); 63 | void setSampleData(uint8_t* module); 64 | void renderSprite(uint8_t sprite, uint16_t x, uint16_t y); 65 | void renderAnimTile(uint8_t animTile, uint16_t x, uint16_t y); 66 | 67 | uint8_t* eDRAMAddress; 68 | void (*interrupt)(void); 69 | int framesPerSecond_; 70 | uint8_t* moduleData; 71 | Module loadedModule; 72 | uint8_t effectChannel; 73 | int16_t *audioBuffer; 74 | SceShort16 *audioOutputBuffer; 75 | uint32_t audioOutputBufferOffset; 76 | SceUID audioThreadId; 77 | int* displayList; 78 | uint16_t joystickStateToReturn; 79 | uint16_t joystickState; 80 | uint32_t* palette; 81 | int16_t cursorX; 82 | int16_t cursorY; 83 | CursorShape cursorShape; 84 | float scaleX; 85 | float scaleY; 86 | uint32_t fadeBaseColor; 87 | uint16_t fadeIntensity; 88 | bool drawToBuffer0; 89 | bool swapBuffers; 90 | bool isDirty; 91 | }; 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Attack of the PETSCII Robots PSP 2 | ================================ 3 | Ported by Vesa Halttunen 4 | This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. 5 | 6 | About 7 | ----- 8 | - petrobots.cpp is the main game logic ported line by line from the 6502 files PETROBOTS.ASM and BACKGROUND_TASKS.ASM 9 | - Platform.h is essentially an interface with platform specific implementation classes 10 | - Various #defines starting with PLATFORM_ can be used to build a variant with different features using the same platform implementation 11 | - To port to a new platform, create a new PlatformXYZ.cpp/h implementation based on the existing ones and instantiate it in main() (petrobots.cpp) 12 | 13 | Building 14 | -------- 15 | make 16 | mksfo petrobots param.sfo 17 | psp-prx-strip -v "petrobots.prx" 18 | psp_boot_packager c param.sfo "petrobots.prx" eboot.pbp 19 | 20 | Requirements 21 | ------------ 22 | PSP system software 6.35 23 | 24 | Controls 25 | -------- 26 | UP/DOWN/LEFT/RIGHT move 27 | TRIANGLE/CROSS/SQUARE/CIRCLE fire 28 | L search 29 | R move 30 | START use item 31 | SELECT+L cycle item 32 | SELECT+R cycle weapon 33 | SELECT+LEFT live map 34 | SELECT+DOWN live map robots 35 | SELECT+CIRCLE pause 36 | SELECT+CROSS toggle music 37 | 38 | TODO 39 | ---- 40 | - native resolution intro screen and game over screen 41 | -------------------------------------------------------------------------------- /Sounds/SOUND_BEEP.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_BEEP.raw -------------------------------------------------------------------------------- /Sounds/SOUND_BEEP2.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_BEEP2.raw -------------------------------------------------------------------------------- /Sounds/SOUND_CYCLE_ITEM.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_CYCLE_ITEM.raw -------------------------------------------------------------------------------- /Sounds/SOUND_CYCLE_WEAPON.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_CYCLE_WEAPON.raw -------------------------------------------------------------------------------- /Sounds/SOUND_DOOR_FASTER.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_DOOR_FASTER.raw -------------------------------------------------------------------------------- /Sounds/SOUND_EMP.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_EMP.raw -------------------------------------------------------------------------------- /Sounds/SOUND_ERROR.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_ERROR.raw -------------------------------------------------------------------------------- /Sounds/SOUND_FOUND_ITEM.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_FOUND_ITEM.raw -------------------------------------------------------------------------------- /Sounds/SOUND_MAGNET2.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_MAGNET2.raw -------------------------------------------------------------------------------- /Sounds/SOUND_MEDKIT.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_MEDKIT.raw -------------------------------------------------------------------------------- /Sounds/SOUND_MOVE.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_MOVE.raw -------------------------------------------------------------------------------- /Sounds/SOUND_PLASMA_FASTER.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_PLASMA_FASTER.raw -------------------------------------------------------------------------------- /Sounds/SOUND_SHOCK.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/SOUND_SHOCK.raw -------------------------------------------------------------------------------- /Sounds/sounds_dsbarexp.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/sounds_dsbarexp.raw -------------------------------------------------------------------------------- /Sounds/sounds_dspistol.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/Sounds/sounds_dspistol.raw -------------------------------------------------------------------------------- /Tiletool/.gitignore: -------------------------------------------------------------------------------- 1 | *.pro.user 2 | .qmake.stash 3 | Makefile 4 | Tiletool 5 | -------------------------------------------------------------------------------- /Tiletool/Tiletool.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2014-10-07T23:39:45 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core 8 | 9 | TARGET = Tiletool 10 | CONFIG += console 11 | CONFIG -= app_bundle 12 | 13 | TEMPLATE = app 14 | 15 | 16 | SOURCES += main.cpp 17 | -------------------------------------------------------------------------------- /Tiletool/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | QCoreApplication app(argc, argv); 13 | QTextStream standardError(stderr); 14 | 15 | // Parse command line options 16 | QCommandLineParser parser; 17 | parser.setApplicationDescription("Tiletool"); 18 | parser.addHelpOption(); 19 | parser.addVersionOption(); 20 | 21 | QStringList args; 22 | for (int i = 0; i < argc; i++) { 23 | args << argv[i]; 24 | } 25 | QCommandLineOption reverseOption(QStringList() << "r" << "reverse", QCoreApplication::translate("main", "Convert back to 16x16.")); 26 | parser.addOption(reverseOption); 27 | parser.addPositionalArgument("input", QCoreApplication::translate("main", "The name of the image to be converted.")); 28 | parser.addPositionalArgument("output", QCoreApplication::translate("main", "The basename of the converted image.")); 29 | parser.process(args); 30 | 31 | bool reverse = parser.isSet(reverseOption); 32 | 33 | const QStringList positionalArguments = parser.positionalArguments(); 34 | 35 | if (positionalArguments.count() != 2) { 36 | standardError << QCoreApplication::translate("main", "Invalid arguments") << "\n"; 37 | return 1; 38 | } 39 | 40 | QImage inputImage(positionalArguments.first()); 41 | if (inputImage.colorCount() == 0) { 42 | standardError << QCoreApplication::translate("main", "Not a paletted image") << "\n"; 43 | return 1; 44 | } 45 | 46 | standardError << QCoreApplication::translate("main", "Input image:\n"); 47 | standardError << QCoreApplication::translate("main", "Size ") << inputImage.width() << "x" << inputImage.height() << "\n"; 48 | standardError << QCoreApplication::translate("main", "Colors ") << inputImage.colorCount() << "\n"; 49 | 50 | if (reverse) { 51 | QImage outputImage(24 * 16, 24 * 16, inputImage.format()); 52 | outputImage.setColorCount(inputImage.colorCount()); 53 | outputImage.setColorTable(inputImage.colorTable()); 54 | for (int tile = 0; tile < 256; tile++) { 55 | int inputY = tile * 24; 56 | int outputX = (tile % 16) * 24; 57 | int outputY = (tile / 16) * 24; 58 | for (int y = 0; y < 24; y++) { 59 | for (int x = 0; x < 24; x++) { 60 | outputImage.setPixel(outputX + x, outputY + y, inputImage.pixelIndex(x, inputY + y)); 61 | } 62 | } 63 | } 64 | outputImage.save(positionalArguments.at(1)); 65 | 66 | } else { 67 | QImage outputImage(32, 24 * 256, inputImage.format()); 68 | outputImage.setColorCount(inputImage.colorCount()); 69 | outputImage.setColorTable(inputImage.colorTable()); 70 | for (int tile = 0; tile < 256; tile++) { 71 | int inputX = (tile % 16) * 24; 72 | int inputY = (tile / 16) * 24; 73 | int outputY = tile * 24; 74 | for (int y = 0; y < 24; y++) { 75 | for (int x = 0; x < 24; x++) { 76 | outputImage.setPixel(x, outputY + y, inputImage.pixelIndex(inputX + x, inputY + y)); 77 | } 78 | for (int x = 24; x < 32; x++) { 79 | outputImage.setPixel(x, outputY + y, 0); 80 | } 81 | } 82 | } 83 | outputImage.save(positionalArguments.at(1)); 84 | } 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /petrobots.h: -------------------------------------------------------------------------------- 1 | #ifndef _PETROBOTS_H 2 | #define _PETROBOTS_H 3 | 4 | #include "Platform.h" 5 | 6 | #define MAP_WINDOW_SIZE (PLATFORM_MAP_WINDOW_TILES_WIDTH * PLATFORM_MAP_WINDOW_TILES_HEIGHT) 7 | #define MAP_WINDOW_WIDTH (PLATFORM_MAP_WINDOW_TILES_WIDTH * 24) 8 | #define MAP_WINDOW_HEIGHT (PLATFORM_MAP_WINDOW_TILES_HEIGHT * 24) 9 | 10 | extern uint8_t *DESTRUCT_PATH; // Destruct path array (256 bytes) 11 | extern uint8_t *TILE_ATTRIB; // Tile attrib array (256 bytes) 12 | 13 | // These arrays can go anywhere in RAM 14 | extern uint8_t UNIT_TIMER_A[64]; // Primary timer for units (64 bytes) 15 | extern uint8_t UNIT_TIMER_B[64]; // Secondary timer for units (64 bytes) 16 | extern uint8_t UNIT_TILE[32]; // Current tile assigned to unit (32 bytes) 17 | extern uint8_t EXP_BUFFER[16]; // Explosion Buffer (16 bytes) 18 | extern uint8_t MAP_PRECALC[MAP_WINDOW_SIZE]; // Stores pre-calculated objects for map window (77 bytes) 19 | extern uint8_t MAP_PRECALC_DIRECTION[MAP_WINDOW_SIZE]; // Stores pre-calculated object directions for map window (77 bytes) 20 | extern uint8_t MAP_PRECALC_TYPE[MAP_WINDOW_SIZE]; // Stores pre-calculated object types for map window (77 bytes) 21 | extern uint8_t PREVIOUS_MAP_BACKGROUND[MAP_WINDOW_SIZE]; 22 | extern uint8_t PREVIOUS_MAP_FOREGROUND[MAP_WINDOW_SIZE]; 23 | extern uint8_t PREVIOUS_MAP_FOREGROUND_VARIANT[MAP_WINDOW_SIZE]; 24 | 25 | // The following are the locations where the current 26 | // key controls are stored. These must be set before 27 | // the game can start. 28 | extern uint8_t KEY_CONFIG[26]; 29 | 30 | // MAP FILES CONSIST OF EVERYTHING FROM THIS POINT ON 31 | extern uint8_t MAP_DATA[8960]; 32 | extern uint8_t* UNIT_TYPE; 33 | extern uint8_t* UNIT_LOC_X; 34 | extern uint8_t* UNIT_LOC_Y; 35 | extern uint8_t* UNIT_A; 36 | extern uint8_t* UNIT_B; 37 | extern uint8_t* UNIT_C; 38 | extern uint8_t* UNIT_D; 39 | extern int8_t* UNIT_HEALTH; 40 | extern uint8_t* MAP; 41 | // END OF MAP FILE 42 | 43 | extern uint8_t TILE; // The tile number to be plotted 44 | extern uint8_t DIRECTION; // The direction of the tile to be plotted 45 | extern uint8_t WALK_FRAME; // Player walking animation frame 46 | extern uint8_t DEMATERIALIZE_FRAME; // Dematerialize animation frame 47 | extern uint8_t MAP_X; // Current X location on map 48 | extern uint8_t MAP_Y; // Current Y location on map 49 | extern uint8_t MAP_WINDOW_X; // Top left location of what is displayed in map window 50 | extern uint8_t MAP_WINDOW_Y; // Top left location of what is displayed in map window 51 | extern uint8_t DECNUM; // a decimal number to be displayed onscreen as 3 digits. 52 | extern uint8_t ATTRIB; // Tile attribute value 53 | extern uint8_t UNIT; // Current unit being processed 54 | extern uint8_t TEMP_A; // used within some routines 55 | extern uint8_t TEMP_B; // used within some routines 56 | extern uint8_t TEMP_C; // used within some routines 57 | extern uint8_t TEMP_D; // used within some routines 58 | extern uint8_t CURSOR_X; // For on-screen cursor 59 | extern uint8_t CURSOR_Y; // For on-screen cursor 60 | extern uint8_t CURSOR_ON; // Is cursor active or not? 1=yes 0=no 61 | extern uint8_t REDRAW_WINDOW; // 1=yes 0=no 62 | extern uint8_t MOVE_RESULT; // 1=Move request success, 0=fail. 63 | extern uint8_t UNIT_FIND; // 255=no unit present. 64 | extern uint8_t MOVE_TYPE; // %00000001=WALK %00000010=HOVER 65 | extern uint8_t* CUR_PATTERN; // stores the memory location of the current musical pattern being played. 66 | 67 | //extern uint8_t LSTX; // $97 Current Key Pressed: 255 = No Key 68 | extern uint8_t NDX; // $9E No. of Chars. in Keyboard Buffer (Queue) 69 | extern uint8_t* MAP_SOURCE; // $FD 70 | extern uint8_t SCREEN_MEMORY[SCREEN_WIDTH_IN_CHARACTERS * SCREEN_HEIGHT_IN_CHARACTERS]; // $8000 71 | extern bool quit; 72 | 73 | void INIT_GAME(); 74 | 75 | extern char MAPNAME[]; 76 | extern const char* LOADMSG1; 77 | extern uint8_t KEYS; // bit0=spade bit2=heart bit3=star 78 | extern uint8_t AMMO_PISTOL; // how much ammo for the pistol 79 | extern uint8_t AMMO_PLASMA; // how many shots of the plasmagun 80 | extern uint8_t INV_BOMBS; // How many bombs do we have 81 | extern uint8_t INV_EMP; // How many EMPs do we have 82 | extern uint8_t INV_MEDKIT; // How many medkits do we have? 83 | extern uint8_t INV_MAGNET; // How many magnets do we have? 84 | extern uint8_t SELECTED_WEAPON; // 0=none 1=pistol 2=plasmagun 85 | extern uint8_t SELECTED_ITEM; // 0=none 1=bomb 2=emp 3=medkit 4=magnet 86 | extern uint8_t SELECT_TIMEOUT; // can only change weapons once it hits zero 87 | extern uint8_t ANIMATE; // 0=DISABLED 1=ENABLED 88 | extern uint8_t BIG_EXP_ACT; // 0=No explosion active 1=big explosion active 89 | extern uint8_t MAGNET_ACT; // 0=no magnet active 1=magnet active 90 | extern uint8_t PLASMA_ACT; // 0=No plasma fire active 1=plasma fire active 91 | extern uint8_t RANDOM; // used for random number generation 92 | extern uint8_t BORDER; // Used for border flash timing 93 | extern uint8_t SCREEN_SHAKE; // 1=shake 0=no shake 94 | extern uint8_t CONTROL; // 0=keyboard 1=custom keys 2=snes 95 | extern uint16_t BORDER_COLOR; // Used for border flash coloring 96 | extern char INTRO_MESSAGE[]; 97 | extern char MSG_CANTMOVE[]; 98 | extern char MSG_BLOCKED[]; 99 | extern char MSG_SEARCHING[]; 100 | extern char MSG_NOTFOUND[]; 101 | extern char MSG_FOUNDKEY[]; 102 | extern char MSG_FOUNDGUN[]; 103 | extern char MSG_FOUNDEMP[]; 104 | extern char MSG_FOUNDBOMB[]; 105 | extern char MSG_FOUNDPLAS[]; 106 | extern char MSG_FOUNDMED[]; 107 | extern char MSG_FOUNDMAG[]; 108 | extern char MSG_MUCHBET[]; 109 | extern char MSG_EMPUSED[]; 110 | extern char MSG_TERMINATED[]; 111 | extern char MSG_TRANS1[]; 112 | extern char MSG_ELEVATOR[]; 113 | extern char MSG_LEVELS[]; 114 | extern char MSG_PAUSED[]; 115 | extern char MSG_MUSICON[]; 116 | extern char MSG_MUSICOFF[]; 117 | extern uint8_t SELECTED_MAP; 118 | extern char MAP_NAMES[]; 119 | extern uint8_t MUSIC_ON; // 0=off 1=on 120 | 121 | void DISPLAY_LOAD_MESSAGE1(); 122 | void DISPLAY_LOAD_MESSAGE2(); 123 | 124 | extern char LOAD_MSG2[]; 125 | 126 | void SETUP_INTERRUPT(); 127 | void RUNIRQ(); 128 | 129 | extern uint8_t BGTIMER1; 130 | extern uint8_t BGTIMER2; 131 | extern uint8_t KEYTIMER; // Used for repeat of movement 132 | 133 | void UPDATE_GAME_CLOCK(); 134 | 135 | extern uint8_t HOURS; 136 | extern uint8_t MINUTES; 137 | extern uint8_t SECONDS; 138 | extern uint8_t CYCLES; 139 | extern uint8_t CLOCK_ACTIVE; 140 | 141 | void SET_INITIAL_TIMERS(); 142 | void MAIN_GAME_LOOP(); 143 | void AFTER_MOVE_SNES(); 144 | void TOGGLE_MUSIC(); 145 | void START_IN_GAME_MUSIC(); 146 | 147 | extern Platform::Module LEVEL_MUSIC[]; 148 | 149 | void CHEATER(); 150 | bool PAUSE_GAME(); 151 | void CLEAR_KEY_BUFFER(); 152 | void USE_ITEM(); 153 | void USE_BOMB(); 154 | void USE_MAGNET(); 155 | bool BOMB_MAGNET_COMMON1(); 156 | void BOMB_MAGNET_COMMON2(); 157 | void USE_EMP(); 158 | void USE_MEDKIT(); 159 | void FIRE_UP(); 160 | void FIRE_UP_PISTOL(); 161 | void FIRE_UP_PLASMA(); 162 | void FIRE_DOWN(); 163 | void FIRE_DOWN_PISTOL(); 164 | void FIRE_DOWN_PLASMA(); 165 | void FIRE_LEFT(); 166 | void FIRE_LEFT_PISTOL(); 167 | void FIRE_LEFT_PLASMA(); 168 | void FIRE_RIGHT(); 169 | void FIRE_RIGHT_PISTOL(); 170 | void FIRE_RIGHT_PLASMA(); 171 | void AFTER_FIRE(int X); 172 | void KEY_REPEAT(bool keyDown); 173 | void AFTER_MOVE(); 174 | 175 | extern uint8_t KEY_FAST; // 0=DEFAULT STATE 176 | 177 | void SEARCH_OBJECT(); 178 | 179 | extern uint8_t SEARCHBAR; // to count how many periods to display. 180 | 181 | void CALC_COORDINATES(); 182 | void USER_SELECT_OBJECT(); 183 | void MOVE_OBJECT(); 184 | 185 | extern uint8_t MOVTEMP_O; // origin tile 186 | extern uint8_t MOVTEMP_D; // destination tile 187 | extern uint8_t MOVTEMP_X; // x-coordinate 188 | extern uint8_t MOVTEMP_Y; // y-coordinate 189 | extern uint8_t MOVTEMP_U; // unit number (255=none) 190 | extern uint8_t MOVTEMP_UX; 191 | extern uint8_t MOVTEMP_UY; 192 | 193 | void CACULATE_AND_REDRAW(); 194 | void MAP_PRE_CALCULATE(); 195 | 196 | extern uint8_t PRECALC_ROWS[]; 197 | 198 | void INVALIDATE_PREVIOUS_MAP(); 199 | void DRAW_MAP_WINDOW(); 200 | 201 | void TOGGLE_LIVE_MAP(); 202 | void TOGGLE_LIVE_MAP_ROBOTS(); 203 | void DRAW_LIVE_MAP(); 204 | 205 | extern uint8_t LIVE_MAP_ON; 206 | extern uint8_t LIVE_MAP_ROBOTS_ON; 207 | extern uint8_t LIVE_MAP_PLAYER_BLINK; 208 | 209 | void PLOT_TILE(uint16_t destination, uint16_t x, uint16_t y); 210 | void PLOT_TRANSPARENT_TILE(uint16_t destination, uint16_t x, uint16_t y); 211 | void CHECK_FOR_WINDOW_REDRAW(); 212 | void DECWRITE(uint16_t destination, uint8_t color = 10); 213 | 214 | void TILE_LOAD_ROUTINE(); 215 | void MAP_LOAD_ROUTINE(); 216 | void DISPLAY_GAME_SCREEN(); 217 | 218 | extern char INTRO_OPTIONS[]; 219 | 220 | void DISPLAY_INTRO_SCREEN(); 221 | void DISPLAY_ENDGAME_SCREEN(); 222 | 223 | extern char DIFF_LEVEL_WORDS[]; 224 | 225 | void DECOMPRESS_SCREEN(uint8_t* source, uint8_t color = 10); 226 | 227 | extern uint8_t RPT; // repeat value 228 | 229 | void DISPLAY_PLAYER_HEALTH(); 230 | void CYCLE_ITEM(); 231 | void DISPLAY_ITEM(); 232 | void PRESELECT_ITEM(); 233 | void DISPLAY_TIMEBOMB(); 234 | void DISPLAY_EMP(); 235 | void DISPLAY_MEDKIT(); 236 | void DISPLAY_MAGNET(); 237 | void DISPLAY_BLANK_ITEM(); 238 | void CYCLE_WEAPON(); 239 | void DISPLAY_WEAPON(); 240 | void PRESELECT_WEAPON(); 241 | void DISPLAY_PLASMA_GUN(); 242 | void DISPLAY_PISTOL(); 243 | void DISPLAY_BLANK_WEAPON(); 244 | void DISPLAY_KEYS(); 245 | void GAME_OVER(); 246 | void GOM4(); 247 | 248 | extern uint8_t GAMEOVER1[]; 249 | extern uint8_t GAMEOVER2[]; 250 | extern uint8_t GAMEOVER3[]; 251 | 252 | void DISPLAY_WIN_LOSE(); 253 | 254 | extern char WIN_MSG[]; 255 | extern char LOS_MSG[]; 256 | 257 | void PRINT_INTRO_MESSAGE(); 258 | void PRINT_INFO(const char *); 259 | 260 | extern uint8_t PRINTX; 261 | 262 | void SCROLL_INFO(); 263 | void RESET_KEYS_AMMO(); 264 | void INTRO_SCREEN(); 265 | void START_INTRO_MUSIC(); 266 | bool EXEC_COMMAND(); 267 | void CYCLE_CONTROLS(); 268 | 269 | extern char CONTROLTEXT[]; 270 | extern uint8_t CONTROLSTART[]; 271 | 272 | void CYCLE_MAP(); 273 | void DISPLAY_MAP_NAME(); 274 | char* CALC_MAP_NAME(); 275 | void REVERSE_MENU_OPTION(bool reverse); 276 | 277 | extern uint8_t MENUY; // CURRENT MENU SELECTION 278 | #if (MAP_WINDOW_SIZE == 77) 279 | typedef uint8_t menu_chart_t; 280 | #else 281 | typedef uint16_t menu_chart_t; 282 | #endif 283 | extern menu_chart_t MENU_CHART[]; 284 | 285 | void CHANGE_DIFFICULTY_LEVEL(); 286 | 287 | extern uint8_t DIFF_LEVEL; // default medium 288 | extern uint8_t ROBOT_FACE[]; 289 | extern uint8_t FACE_LEVEL[]; 290 | 291 | void SET_DIFF_LEVEL(); 292 | void SET_DIFF_EASY(); 293 | void SET_DIFF_HARD(); 294 | 295 | extern uint16_t MAP_CHART[PLATFORM_MAP_WINDOW_TILES_HEIGHT]; 296 | 297 | void EMP_FLASH(); 298 | void ANIMATE_WATER(); 299 | 300 | extern uint8_t WATER_TIMER; 301 | extern uint8_t ANIM_STATE; 302 | extern uint8_t CINEMA_STATE; 303 | 304 | void ELEVATOR_SELECT(); 305 | 306 | extern uint8_t ELEVATOR_MAX_FLOOR; 307 | extern uint8_t ELEVATOR_CURRENT_FLOOR; 308 | 309 | void ELEVATOR_INVERT(); 310 | void ELEVATOR_INC(); 311 | void ELEVATOR_DEC(); 312 | void ELEVATOR_FIND_XY(); 313 | void SET_CONTROLS(); 314 | 315 | extern uint8_t STANDARD_CONTROLS[]; 316 | 317 | void SET_CUSTOM_KEYS(); 318 | 319 | extern uint8_t KEYS_DEFINED; // DEFAULT 0 320 | 321 | void PET_SCREEN_SHAKE(); 322 | void PET_BORDER_FLASH(); 323 | 324 | extern uint8_t FLASH_STATE; 325 | 326 | void DEMATERIALIZE(); 327 | void ANIMATE_PLAYER(); 328 | void PLAY_SOUND(int); 329 | 330 | void STOP_SONG(); 331 | void BACKGROUND_TASKS(); 332 | 333 | extern void (*AI_ROUTINE_CHART[])(void); 334 | 335 | void DUMMY_ROUTINE(); 336 | void WATER_RAFT_LR(); 337 | void RAFT_DELETE(); 338 | void RAFT_PLOT(); 339 | void MAGNETIZED_ROBOT(); 340 | void GENERATE_RANDOM_NUMBER(); 341 | void MAGNET(); 342 | void DEAD_ROBOT(); 343 | void UP_DOWN_ROLLERBOT(); 344 | void LEFT_RIGHT_ROLLERBOT(); 345 | void ROLLERBOT_FIRE_DETECT(); 346 | void ROLLERBOT_AFTER_FIRE(uint8_t unit, uint8_t tile); 347 | void ROLLERBOT_ANIMATE(); 348 | void TRANSPORTER_PAD(); 349 | void TRANS_PLAYER_PRESENT(); 350 | void TRANS_ACTIVE(); 351 | void TIME_BOMB(); 352 | void BIG_EXP_PHASE1(); 353 | void BEX1_NORTH(); 354 | void BEX1_SOUTH(); 355 | void BEX1_EAST(); 356 | void BEX1_WEST(); 357 | void BEX1_NE(); 358 | void BEX1_NW(); 359 | void BEX1_SE(); 360 | void BEX1_SW(); 361 | void BEX_PART1(); 362 | bool BEX_PART2(); 363 | void BEX_PART3(); 364 | void BEXCEN(); 365 | void BIG_EXP_PHASE2(); 366 | void RESTORE_TILE(); 367 | void TRASH_COMPACTOR(); 368 | void DRAW_TRASH_COMPACTOR(); 369 | extern uint8_t TCPIECE1; 370 | extern uint8_t TCPIECE2; 371 | extern uint8_t TCPIECE3; 372 | extern uint8_t TCPIECE4; 373 | void WATER_DROID(); 374 | void PISTOL_FIRE_UP(); 375 | void PISTOL_FIRE_DOWN(); 376 | void PISTOL_FIRE_LEFT(); 377 | void PISTOL_FIRE_RIGHT(); 378 | void DEACTIVATE_WEAPON(); 379 | void PISTOL_AI_COMMON(); 380 | void ALTER_AI(); 381 | void INFLICT_DAMAGE(); 382 | void SMALL_EXPLOSION(); 383 | void HOVER_ATTACK(); 384 | void CREATE_PLAYER_EXPLOSION(); 385 | void EVILBOT(); 386 | void AI_DOOR(); 387 | extern void (*AIDB[])(void); 388 | void DOOR_OPEN_A(); 389 | void DOOR_OPEN_B(); 390 | void DOOR_OPEN_FULL(); 391 | void DOOR_CLOSE_A(); 392 | void DOOR_CLOSE_B(); 393 | void DOOR_CLOSE_FULL(); 394 | void DRAW_VERTICAL_DOOR(); 395 | void DRAW_HORIZONTAL_DOOR(); 396 | extern uint8_t DOORPIECE1; 397 | extern uint8_t DOORPIECE2; 398 | extern uint8_t DOORPIECE3; 399 | void ROBOT_ATTACK_RANGE(); 400 | void DOOR_CHECK_PROXIMITY(); 401 | extern uint8_t PROX_DETECT; 402 | void ELEVATOR(); 403 | extern void (*ELDB[])(void); 404 | void ELEV_OPEN_A(); 405 | void ELEV_OPEN_B(); 406 | void ELEV_OPEN_FULL(); 407 | void ELEV_CLOSE_A(); 408 | void ELEV_CLOSE_B(); 409 | void ELEV_CLOSE_FULL(); 410 | void ELEVATOR_PANEL(); 411 | void PLOT_TILE_TO_MAP(); 412 | void GET_TILE_FROM_MAP(); 413 | void LEFT_RIGHT_DROID(); 414 | void UP_DOWN_DROID(); 415 | void HOVERBOT_ANIMATE(uint8_t X); 416 | void REQUEST_WALK_RIGHT(); 417 | void REQUEST_WALK_LEFT(); 418 | void REQUEST_WALK_DOWN(); 419 | void REQUEST_WALK_UP(); 420 | void CHECK_FOR_UNIT(); 421 | void CHECK_FOR_HIDDEN_UNIT(); 422 | 423 | extern uint8_t SCR_CUSTOM_KEYS[]; 424 | extern char CINEMA_MESSAGE[]; 425 | 426 | void convertToPETSCII(char* string); 427 | void writeToScreenMemory(address_t address, uint8_t value, uint8_t color = 10, uint8_t yOffset = 0); 428 | 429 | #endif 430 | -------------------------------------------------------------------------------- /tileset.amiga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeropolis79/PETSCIIRobots-PSP/d96ca8b45c5321aa21f3db48cbfd9a19d2411887/tileset.amiga --------------------------------------------------------------------------------