diff --git a/Makefile b/Makefile index 93d094a91..947c9fc00 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,9 @@ ACME=acme # https://github.com/mach-kernel/cadius CADIUS=cadius -asm: md asmfx asmprelaunch +asm: md asmlauncher asmfx asmprelaunch + +asmlauncher: $(ACME) src/4cade.a 2>build/relbase.log $(ACME) -r build/4cade.lst -DRELBASE=`cat build/relbase.log | grep "RELBASE =" | cut -d"=" -f2 | cut -d"(" -f2 | cut -d")" -f1` src/4cade.a diff --git a/res/games.conf b/res/games.conf index 7c72e64e1..7133bb676 100644 --- a/res/games.conf +++ b/res/games.conf @@ -1 +1 @@ -00,AGENT.USA=Agent U S A 11,AIRHEART=Airheart 00,ALCAZAR=Alcazar 10,ALIEN.AMBUSH=Alien Ambush 00,ALIEN.DOWNPOUR=Alien Downpour 00,ALIEN.MUNCHIES=Alien Munchies 00,ALIEN.RAIN=Alien Rain 00,ALIEN.TYPHOON=Alien Typhoon 00,ANKH=Ankh 00,CIDER.SPIDER=Apple Cider Spider 00,APPLE.PANIC=Apple Panic 00,AQUATRON=Aquatron 00,ARGOS=Argos 10,ARKANOID=Arkanoid 00,ASTEROID.BLASTR=Asteroid Blaster 10,AXIS.ASSASSIN=Axis Assassin 00,AZTEC=Aztec 11,BAD.DUDES=Bad Dudes 10,BALLBLAZER=Ballblazer 11,BATMAN=Batman 00,BATTLEZONE=Battlezone 10,BCS.QUEST=BC's Quest For Tires 00,BEER.RUN=Beer Run 00,BELLHOP=Bellhop 00,BERZAP=Berzap 00,BEYOND.WOLFEN=Beyond Castle Wolfenstein 00,BUDGETRILOGY=Bill Budge's Trilogy 10,BLACK.MAGIC=Black Magic 00,BLISTER.BALL=Blister Ball 00,BLOCKCHAIN=BlockChain 00,BOLO=Bolo 00,BOUNCING.KMNGAS=Bouncing Kamungas 00,BRAINTEASERBLVD=Brainteaser Boulevard 10,BRUCE.LEE=Bruce Lee 10,BUBBLE.BOBBLE=Bubble Bobble 00,BUCK.ROGERS=Buck Rogers: Planet of Zoom 00,BURGERTIME=BurgerTime 00,BUZZARD.BAIT=Buzzard Bait 00,CANNONBALL.BLTZ=Cannonball Blitz 00,CANYON.CLIMBER=Canyon Climber 00,CAPTN.GOODNIGHT=Captain Goodnight 00,WOLFEN84=Castle Wolfenstein 10,CEILING.ZERO=Ceiling Zero 00,CENTIPEDE=Centipede 00,CHAMP.LODERUN=Championship Lode Runner 10,CHOPLIFTER=Choplifter 01,COMMANDO=Commando 00,CONAN=Conan 00,CRAZY.MAZY=Crazy Mazey 00,CRIME.WAVE=Crime Wave 10,CRISIS.MOUNTAIN=Crisis Mountain 00,CROSSFIRE=Crossfire 00,CUBIT=Cubit 00,CYBERSTRIKE=Cyber Strike 00,CYCLOD=Cyclod 10,DAVIDS.MAGIC=David's Midnight Magic 01,DEATH.SWORD=Death Sword 10,DEFENDER=Defender 01,D.GENERATION=D-Generation 00,DIAMOND.MINE=Diamond Mine 00,DIG.DUG=Dig Dug 10,DINO.EGGS=Dino Eggs 10,DONKEY.KONG=Donkey Kong 10,DRELBS=Drelbs 00,DROL=Drol 00,DUNG.BEETLES=Dung Beetles 00,EGGS.IT=Eggs-It 00,EPOCH=Epoch 00,FALCONS=Falcons 00,FIREBIRD=Firebird 00,FS1=Flight Simulator I 00,FLIP.OUT=Flip Out 10,FORMULA.1=Formula 1 Racer 00,FREE.FALL=Free Fall 00,FROGGER=Frogger 10,FROGGER.II=Frogger II 10,GALAXIAN=Galaxian 00,GALAXY.GATES=Galaxy Gates 10,GAMMA.GOBLINS=Gamma Goblins 00,GENETIC.DRIFT=Genetic Drift 00,GOLD.RUSH=Gold Rush 00,GORGON=Gorgon 00,GREMLINS=Gremlins 00,GUMBALL=Gumball 00,HADRON=Hadron 00,HARD.HAT.MACK=Hard Hat Mack 00,HEAD.ON=Head On 11,HEAVY.BARREL=Heavy Barrel 10,HERO=H E R O 00,HIGH.RISE=High Rise 00,HORIZON.V=Horizon V 00,HUNGRYBOY=Hungry Boy 00,HYPER.HEAD.ON=Hyper Head On 00,IKARI.WARRIORS=Ikari Warriors 10,IMPOSSIBLE.MISS=Impossible Mission 01,INDIANA.JONES=Indiana Jones 10,INTL.GRAN.PRIX=International Gran Prix 00,JOUST=Joust 00,JUGGLER=Juggler 00,JUMPMAN=Jumpman 00,JUNGLE.HUNT=Jungle Hunt 10,KAMIKAZE=Kamikaze 00,KARATEKA=Karateka 00,KID.NIKI=Kid Niki 00,LABYRINTH=Labyrinth 00,LADY.TUT=Lady Tut 00,LANCASTER=Lancaster 10,LASER.BOUNCE=Laser Bounce 00,LAZER.SILK=Lazer Silk 00,LODE.RUNNER=Lode Runner 10,LOST.TOMB=Lost Tomb 10,MAD.BOMBER=Mad Bomber 10,MARBLE.MADNESS=Marble Madness 00,MARIO.BROS=Mario Bros 10,MINER.2049ER=Miner 2049er 00,MONTEZUMA=Montezuma's Revenge 00,MOON.PATROL=Moon Patrol 00,MR.COOL=Mr. Cool 10,MR.DO=Mr. Do 00,MR.ROBOT=Mr. Robot 00,MS.PACMAN=Ms. Pacman 00,NIBBLER=Nibbler 10,NIGHT.MISSION=Night Mission Pinball 00,NIGHT.STALKER=Night Stalker 00,NIGHTMARE=Nightmare Gallery 00,NORAD=N O R A D 00,ORBITRON=Orbitron 00,ORILEYS.MINE=O'Riley's Mine 00,OOTW=Out Of This World 00,OUTPOST=Outpost 00,PAC.MAN=Pac-Man 00,PAPERBOY=Paperboy 00,PEST.PATROL=Pest Patrol 10,PHANTOMS.FIVE=Phantoms Five 00,PHASER.FIRE=Phaser Fire 00,PHOTAR=Photar 00,PICNIC.PARANOIA=Picnic Paranoia 00,PIEMAN=Pie-Man 01,PIPEDREAM=Pipe Dream 10,PITFALL.II=Pitfall II 00,PITSTOP.II=Pit Stop II 00,PLASMANIA=Plasmania 11,PLATOON=Platoon 00,POLLYWOG=Pollywog 00,POOYAN=Pooyan 01,PRINCEUNP=Prince of Persia 00,PUCK.MAN=Puckman 11,QIX=Qix 10,QUADRANT.6112=Quadrant 6112 01,RADWARRIOR=Radwarrior 01,RAMPAGE=Rampage 00,RASTER.BLASTER=Raster Blaster 10,RED.ALERT=Red Alert 11,RENEGADE=Renegade 00,REPTON=Repton 00,RESCUE.RAIDERS=Rescue Raiders 00,RIBBIT=Ribbit 00,ROADBLOCK=Roadblock 01,ROBOCOP=Robocop 00,ROBOTRON=Robotron 2084 00,RUSSKI.DUCK=Russki Duck 00,SABOTAGE=Sabotage 00,SAMMY.LIGHTFOOT=Sammy Lightfoot 00,SEA.DRAGON=Sea Dragon 00,SEAFOX=Seafox 00,SERPENTINE=Serpentine 10,SHAMUS=Shamus 00,SHUFFLEBOARD=Shuffleboard 00,SITUATION.CRTCL=Situation Critical 00,SNACK.ATTACK=Snack Attack 00,SNAKE.BYTE=Snake Byte 00,SNEAKERS=Sneakers 00,SNOGGLE=Snoggle 10,SPACE.EGGS=Space Eggs 00,SPACE.QUARKS=Space Quarks 00,SPACE.RAIDERS=Space Raiders 00,SPARE.CHANGE=Spare Change 00,SPDWAY.CLASSIC=Speedway Classic 01,SPIDERBOT=Spiderbot 00,SPIDER.RAID=Spider Raid 00,SPY.HUNTER=Spy Hunter 00,SPYS.DEMISE=Spy's Demise 10,STARBLASTER=Starblaster 00,STAR.BLAZER=Star Blazer 10,STARGATE=Stargate 00,STAR.THIEF=Star Thief 00,STELLAR.7=Stellar 7 00,SUCCESSION=Succession 00,SUICIDE=Suicide! 00,SWASHBUCKLER=Swashbuckler 00,TAG.TEAM=Tag Team Wrestling 00,TAPPER=Tapper 00,TETRIS=Tetris 01,TETRIS128K=Tetris (DHGR) 00,THE.BILESTOAD=The Bilestoad 01,SUMMER.EDITION=The Games: Summer Edition 01,WINTER.EDITION=The Games: Winter Edition 10,GOONIES=The Goonies 00,SPY.STRIKES.BAK=The Spy Strikes Back 00,THEXDER=Thexder 01,THEXDER128K=Thexder (DHGR) 00,THIEF=Thief 00,THRESHOLD=Threshold 00,THUNDERBOMBS=Thunder Bombs 10,TOMAHAWK=Tomahawk 00,TRACK.AND.FIELD=Track & Field 10,TUBEWAY=Tubeway ][ 00,TUNNEL.TERROR=Tunnel Terror 00,TWERPS=Twerps 00,UP.N.DOWN=Up'n Down 01,VICTORY.ROAD=Victory Road 00,VINDICATOR=Vindicator 00,WARP.DESTROYER=Warp Destroyer 00,WAVY.NAVY=Wavy Navy 10,XEVIOUS=Xevious 10,ZAXXON=Zaxxon 00,ZENITH=Zenith [eof] # # 4cade master game list # # Format: # AB,directory=name # # A=1 if game requires joystick, 0 if playable on keyboard # B=1 if game requires 128K, 0 if playable on 64K # # all other values for A or B -> ignore entire line (like this one!) # A line beginning with '[' terminates the parsing # \ No newline at end of file +000,AGENT.USA=Agent U S A 110,AIRHEART=Airheart 000,ALCAZAR=Alcazar 100,ALIEN.AMBUSH=Alien Ambush 000,ALIEN.DOWNPOUR=Alien Downpour 000,ALIEN.MUNCHIES=Alien Munchies 000,ALIEN.RAIN=Alien Rain 000,ALIEN.TYPHOON=Alien Typhoon 000,ANKH=Ankh 000,CIDER.SPIDER=Apple Cider Spider 000,APPLE.PANIC=Apple Panic 000,AQUATRON=Aquatron 000,ARGOS=Argos 100,ARKANOID=Arkanoid 000,ASTEROID.BLASTR=Asteroid Blaster 100,AXIS.ASSASSIN=Axis Assassin 000,AZTEC=Aztec 110,BAD.DUDES=Bad Dudes 100,BALLBLAZER=Ballblazer 110,BATMAN=Batman 000,BATTLEZONE=Battlezone 100,BCS.QUEST=BC's Quest For Tires 000,BEER.RUN=Beer Run 000,BELLHOP=Bellhop 000,BERZAP=Berzap 000,BEYOND.WOLFEN=Beyond Castle Wolfenstein 000,BUDGETRILOGY=Bill Budge's Trilogy 100,BLACK.MAGIC=Black Magic 000,BLISTER.BALL=Blister Ball 000,BLOCKCHAIN=BlockChain 001,BOLO=Bolo 000,BOUNCING.KMNGAS=Bouncing Kamungas 000,BRAINTEASERBLVD=Brainteaser Boulevard 101,BRUCE.LEE=Bruce Lee 101,BUBBLE.BOBBLE=Bubble Bobble 000,BUCK.ROGERS=Buck Rogers: Planet of Zoom 002,BURGERTIME=BurgerTime 000,BUZZARD.BAIT=Buzzard Bait 000,CANNONBALL.BLTZ=Cannonball Blitz 000,CANYON.CLIMBER=Canyon Climber 000,CAPTN.GOODNIGHT=Captain Goodnight 000,WOLFEN84=Castle Wolfenstein 100,CEILING.ZERO=Ceiling Zero 000,CENTIPEDE=Centipede 000,CHAMP.LODERUN=Championship Lode Runner 100,CHOPLIFTER=Choplifter 010,COMMANDO=Commando 002,CONAN=Conan 000,CRAZY.MAZY=Crazy Mazey 000,CRIME.WAVE=Crime Wave 100,CRISIS.MOUNTAIN=Crisis Mountain 000,CROSSFIRE=Crossfire 000,CUBIT=Cubit 000,CYBERSTRIKE=Cyber Strike 000,CYCLOD=Cyclod 100,DAVIDS.MAGIC=David's Midnight Magic 010,DEATH.SWORD=Death Sword 100,DEFENDER=Defender 010,D.GENERATION=D-Generation 000,DIAMOND.MINE=Diamond Mine 001,DIG.DUG=Dig Dug 100,DINO.EGGS=Dino Eggs 101,DONKEY.KONG=Donkey Kong 100,DRELBS=Drelbs 001,DROL=Drol 000,DUNG.BEETLES=Dung Beetles 000,EGGS.IT=Eggs-It 000,EPOCH=Epoch 000,FALCONS=Falcons 000,FIREBIRD=Firebird 000,FS1=Flight Simulator I 000,FLIP.OUT=Flip Out 100,FORMULA.1=Formula 1 Racer 000,FREE.FALL=Free Fall 000,FROGGER=Frogger 100,FROGGER.II=Frogger II 100,GALAXIAN=Galaxian 000,GALAXY.GATES=Galaxy Gates 100,GAMMA.GOBLINS=Gamma Goblins 000,GENETIC.DRIFT=Genetic Drift 000,GOLD.RUSH=Gold Rush 000,GORGON=Gorgon 000,GREMLINS=Gremlins 000,GUMBALL=Gumball 000,HADRON=Hadron 000,HARD.HAT.MACK=Hard Hat Mack 000,HEAD.ON=Head On 110,HEAVY.BARREL=Heavy Barrel 100,HERO=H E R O 000,HIGH.RISE=High Rise 000,HORIZON.V=Horizon V 000,HUNGRYBOY=Hungry Boy 000,HYPER.HEAD.ON=Hyper Head On 000,IKARI.WARRIORS=Ikari Warriors 100,IMPOSSIBLE.MISS=Impossible Mission 010,INDIANA.JONES=Indiana Jones 100,INTL.GRAN.PRIX=International Gran Prix 001,JOUST=Joust 000,JUGGLER=Juggler 000,JUMPMAN=Jumpman 000,JUNGLE.HUNT=Jungle Hunt 100,KAMIKAZE=Kamikaze 000,KARATEKA=Karateka 000,KID.NIKI=Kid Niki 000,LABYRINTH=Labyrinth 000,LADY.TUT=Lady Tut 000,LANCASTER=Lancaster 100,LASER.BOUNCE=Laser Bounce 000,LAZER.SILK=Lazer Silk 000,LODE.RUNNER=Lode Runner 100,LOST.TOMB=Lost Tomb 100,MAD.BOMBER=Mad Bomber 100,MARBLE.MADNESS=Marble Madness 001,MARIO.BROS=Mario Bros 100,MINER.2049ER=Miner 2049er 001,MONTEZUMA=Montezuma's Revenge 001,MOON.PATROL=Moon Patrol 000,MR.COOL=Mr. Cool 101,MR.DO=Mr. Do 000,MR.ROBOT=Mr. Robot 001,MS.PACMAN=Ms. Pacman 000,NIBBLER=Nibbler 100,NIGHT.MISSION=Night Mission Pinball 000,NIGHT.STALKER=Night Stalker 000,NIGHTMARE=Nightmare Gallery 000,NORAD=N O R A D 000,ORBITRON=Orbitron 000,ORILEYS.MINE=O'Riley's Mine 000,OOTW=Out Of This World 000,OUTPOST=Outpost 000,PAC.MAN=Pac-Man 000,PAPERBOY=Paperboy 000,PEST.PATROL=Pest Patrol 100,PHANTOMS.FIVE=Phantoms Five 000,PHASER.FIRE=Phaser Fire 000,PHOTAR=Photar 000,PICNIC.PARANOIA=Picnic Paranoia 000,PIEMAN=Pie-Man 010,PIPEDREAM=Pipe Dream 100,PITFALL.II=Pitfall II 000,PITSTOP.II=Pit Stop II 000,PLASMANIA=Plasmania 110,PLATOON=Platoon 000,POLLYWOG=Pollywog 000,POOYAN=Pooyan 010,PRINCEUNP=Prince of Persia 000,PUCK.MAN=Puckman 110,QIX=Qix 100,QUADRANT.6112=Quadrant 6112 010,RADWARRIOR=Radwarrior 010,RAMPAGE=Rampage 000,RASTER.BLASTER=Raster Blaster 100,RED.ALERT=Red Alert 110,RENEGADE=Renegade 000,REPTON=Repton 000,RESCUE.RAIDERS=Rescue Raiders 000,RIBBIT=Ribbit 000,ROADBLOCK=Roadblock 010,ROBOCOP=Robocop 000,ROBOTRON=Robotron 2084 000,RUSSKI.DUCK=Russki Duck 000,SABOTAGE=Sabotage 000,SAMMY.LIGHTFOOT=Sammy Lightfoot 000,SEA.DRAGON=Sea Dragon 000,SEAFOX=Seafox 000,SERPENTINE=Serpentine 100,SHAMUS=Shamus 000,SHUFFLEBOARD=Shuffleboard 000,SITUATION.CRTCL=Situation Critical 000,SNACK.ATTACK=Snack Attack 000,SNAKE.BYTE=Snake Byte 001,SNEAKERS=Sneakers 000,SNOGGLE=Snoggle 100,SPACE.EGGS=Space Eggs 000,SPACE.QUARKS=Space Quarks 000,SPACE.RAIDERS=Space Raiders 000,SPARE.CHANGE=Spare Change 000,SPDWAY.CLASSIC=Speedway Classic 010,SPIDERBOT=Spiderbot 000,SPIDER.RAID=Spider Raid 000,SPY.HUNTER=Spy Hunter 000,SPYS.DEMISE=Spy's Demise 100,STARBLASTER=Starblaster 000,STAR.BLAZER=Star Blazer 100,STARGATE=Stargate 000,STAR.THIEF=Star Thief 000,STELLAR.7=Stellar 7 000,SUCCESSION=Succession 000,SUICIDE=Suicide! 000,SWASHBUCKLER=Swashbuckler 000,TAG.TEAM=Tag Team Wrestling 001,TAPPER=Tapper 000,TETRIS=Tetris 010,TETRIS128K=Tetris (DHGR) 000,THE.BILESTOAD=The Bilestoad 010,SUMMER.EDITION=The Games: Summer Edition 010,WINTER.EDITION=The Games: Winter Edition 100,GOONIES=The Goonies 000,SPY.STRIKES.BAK=The Spy Strikes Back 000,THEXDER=Thexder 010,THEXDER128K=Thexder (DHGR) 000,THIEF=Thief 000,THRESHOLD=Threshold 000,THUNDERBOMBS=Thunder Bombs 100,TOMAHAWK=Tomahawk 000,TRACK.AND.FIELD=Track & Field 100,TUBEWAY=Tubeway ][ 000,TUNNEL.TERROR=Tunnel Terror 000,TWERPS=Twerps 000,UP.N.DOWN=Up'n Down 010,VICTORY.ROAD=Victory Road 000,VINDICATOR=Vindicator 000,WARP.DESTROYER=Warp Destroyer 001,WAVY.NAVY=Wavy Navy 100,XEVIOUS=Xevious 100,ZAXXON=Zaxxon 000,ZENITH=Zenith [eof] # # 4cade master game list # # Format: # AB,directory=name # # A=1 if game requires joystick, 0 if playable on keyboard # B=1 if game requires 128K, 0 if playable on 64K # C=cheat mode category # 0=no cheats (yet!) # 1=infinite lives # 2=infinite lives & weapons # # all other values for A or B -> ignore entire line (like this one!) # A line beginning with '[' terminates the parsing # \ No newline at end of file diff --git a/src/4cade.a b/src/4cade.a index 88881d244..817ccbbbc 100644 --- a/src/4cade.a +++ b/src/4cade.a @@ -72,6 +72,7 @@ RestoreStackNextTime !source "src/ui.attract.dhgr.a" !source "src/ui.attract.shr.a" !source "src/ui.attract.gr.a" + !source "src/ui.cheats.a" !source "src/prodos.path.a" !source "src/glue.launch.a" !source "src/glue.prorwts2.a" @@ -90,7 +91,7 @@ gDFXStore gSlideshowStore !word $0800 gGlobalPrefsStore - !word $D000 + !word $D100 gGamesListStore !word $FDFD ; SMC !word Reenter ; NMI vector ($FFFA-B) diff --git a/src/4cade.init.a b/src/4cade.init.a index 253011744..840cb979c 100644 --- a/src/4cade.init.a +++ b/src/4cade.init.a @@ -215,6 +215,10 @@ OneTimeSetup !word gGamesListStore sta GameCount sta SAVE + + lda #$80 ; TODO make this a pref + sta gCheatsEnabled + ; calculate and update visible game count (3-digit decimal number as ASCII string) ldy #0 @outer diff --git a/src/constants.a b/src/constants.a index 3ec46d78f..4503d29a8 100644 --- a/src/constants.a +++ b/src/constants.a @@ -81,5 +81,10 @@ gKey = $1F01 gValLen = $1F80 gVal = $1F81 +; LC RAM 1 +gCheatsAvailable = $D000 ; master cheats table, indexed by game index in gGamesListStore + ; 1 byte per game, so max size = 256 games +gCheatsEnabled = $D0FF ; bit 7 = 1 if cheats are enabled + ; actual constants SUPPORTS_SHR = %00110000 ; AND mask for MachineStatus diff --git a/src/glue.font.a b/src/glue.font.a index 89bdd962e..3957b22a1 100644 --- a/src/glue.font.a +++ b/src/glue.font.a @@ -9,6 +9,7 @@ ; Public functions ; - DrawPage ; - Draw40Chars +; - DrawCenteredString ; - DrawString ; - DrawBuffer ; @@ -25,6 +26,12 @@ Draw40Chars +READ_RAM1_WRITE_RAM1 rts +DrawCenteredString + +READ_RAM2_WRITE_RAM2 + jsr DrawCenteredStringInternal + +READ_RAM1_WRITE_RAM1 + rts + DrawString +READ_RAM2_WRITE_RAM2 jsr DrawStringInternal diff --git a/src/glue.launch.a b/src/glue.launch.a index c7c248848..09a5e4fee 100644 --- a/src/glue.launch.a +++ b/src/glue.launch.a @@ -129,15 +129,29 @@ gCurrentlyVisibleSlideshowIndex rts .Go +; in: A/Y = lo/hi address of filename +; X = game index +STAY SAVE + +STAY + - ; TODO check if cheats are enabled and available for this game + bit gCheatsEnabled ; are cheats enabled? + bpl @noCheats + ldy gCheatsAvailable,x ; are there any cheats for this game? + beq @noCheats - jsr LoadFile ; load standard prelaunch code (|Launch| will call it) - !word kPrelaunchDirectory + jsr LoadFile ; cheats are enabled and this game has a prelaunch + !word kPrelaunchDirectory ; file that will set up the cheats, so load that ++ !word $FDFD ; SMC + !word $0106 + jmp @loadedPrelaunch + +@noCheats + jsr LoadFile ; no game-specific prelaunch file, so + !word kPrelaunchDirectory ; load standard prelaunch file instead !word kStandardPrelaunch !word $0106 +@loadedPrelaunch ldx #1 ; construct path to game's startup file sec ; which is always /X/game/game !byte $2c diff --git a/src/okvs.a b/src/okvs.a index 8c64a7df8..8f96e62f3 100644 --- a/src/okvs.a +++ b/src/okvs.a @@ -116,7 +116,8 @@ okvs_len ; +3 [word] address of key ; +5 [word] address of value ; +7 [byte] maximum length of value (or 0 to fit) -; out: all registers clobbered +; out: X = new number of records (same as calling okvs_len after okvs_append) +; A/Y clobbered ; $00/$01 clobbered ; $02/$03 clobbered ; $04/$05 has the address of the next available byte after the new record @@ -130,6 +131,7 @@ okvs_append lda (PTR),y ; A = number of keys in store clc adc #1 + pha ; will return this later sta (PTR),y ; increment number of keys iny lda (PTR),y ; get address of next free space @@ -201,6 +203,8 @@ okvs_append iny lda SRC+1 sta (PTR),y + pla + tax ; X = new OKVS length jsr GetStoreAddress ; PTR -> store ldy #1 diff --git a/src/parse.games.a b/src/parse.games.a index 6ff457423..21c9715c3 100644 --- a/src/parse.games.a +++ b/src/parse.games.a @@ -66,15 +66,17 @@ ParseGamesList @filterOnMemory jsr IncAndGetChar ; get second filter character ('1' if game requires 128K) cmp #$30 ; '0' -> no filtering on memory - beq @swallowComma + beq @parseCheatsAvailable cmp #$31 ; not '0' or '1' -> ignore entire line bne @skipLine bit zpMachineStatus bvc @skipLine ; game requires 128K but we only have 64K, so ignore entire line +@parseCheatsAvailable + jsr IncAndGetChar ; get third character (cheat category, int) + and #$0F + pha @swallowComma jsr IncAndGetChar - cmp #$2C ; ',' delimiter (required) - bne @skipLine @gatherKey jsr IncAndGetChar cmp #$3D ; '=' ends the key @@ -100,8 +102,12 @@ ParseGamesList !word gKeyLen !word gValLen !byte 0 - pla + ; X = new OKVS length + pla ; pop saved Y tay + pla ; pop cheat category + dex ; X = new OKVS length - 1 + sta gCheatsAvailable,x clc bcc @newkey ; always branches diff --git a/src/ui.browse.mode.a b/src/ui.browse.mode.a index f06a1f533..f7a63c81f 100644 --- a/src/ui.browse.mode.a +++ b/src/ui.browse.mode.a @@ -130,12 +130,10 @@ GameCount = *+1 sta UI_ToPlay,x dex bpl - - ldx #40 - lda #0 -- sta UILine1-1,x ; reset UI line 1 - dex - bne - - jsr DrawSearchBarOffscreen ; actually draw the search UI (offscreen) + ldx @index + jsr BuildUILine1WithNoDots ; build UI line 1 with bars and other shapes + ldx @index + jsr DrawSearchBarOffscreen ; actually draw the UI (offscreen) jmp ShowOtherPage ; now show everything at once ;------------------------------------------------------------------------------ diff --git a/src/ui.cheats.a b/src/ui.cheats.a new file mode 100644 index 000000000..a00342345 --- /dev/null +++ b/src/ui.cheats.a @@ -0,0 +1,145 @@ +BuildUILine1WithNoDots +; in: X = game index, or #$FF if no game selected +; out: all registers clobbered +; UILine1 contains 40-character buffer (not length-prefixed) to print + cpx #$FF + beq + + ldy gCheatsAvailable,x + +HIDE_NEXT_2_BYTES ++ + ldy #.kCheatsEnabled + + ldx #40 + lda #$00 ; horizontal bar +- sta UILine1-1,x ; first, reset entire line to solid bar + dex + bne - + + bit gCheatsEnabled + bpl @done ; if cheats are not enabled, we're done + + lda .kCheatDescriptionLo,y + sta PTR + lda .kCheatDescriptionHi,y + sta PTR+1 + ; (PTR) -> length-prefixed cheat description + ldy #0 + lda (PTR),y ; A = length of cheat description + clc + adc #8 ; extra padding (4 on each side) for string + sta @len + lda #40 + sec + sbc @len + lsr + tax + lda #$09 ; rounded bottom-right character + sta UILine1,x + ldy #1 ; fill the proper width with spaces + lda #$20 ; space character +- inx + sta UILine1,x + iny +@len=*+1 + cpy #$FD ; SMC + bne - + lda #$08 ; rounded bottom-left character + sta UILine1,x + +@done rts + +BuildCheatLine1 +; in: X = game index, or #$FF if no game is selected +; out: gPathname contains length-prefixed string to print centered +; all registers clobbered +; PTR clobbered + cpx #$FF + beq + + ldy gCheatsAvailable,x + +HIDE_NEXT_2_BYTES ++ + ldy #.kCheatsEnabled + + ldx #39 ; reset gPathname+2 to gPathname+41 to + lda #$00 ; horizontal bar character +- sta gPathname+1,x + dex + bne - + + lda #$06 ; gPathname+1 = top-left rounded corner character + sta gPathname+1 + + lda .kCheatDescriptionLo,y + sta PTR + lda .kCheatDescriptionHi,y + sta PTR+1 + ; (PTR) -> length-prefixed cheat description + ldy #0 + lda (PTR),y ; A = length of cheat description + clc + adc #8 ; extra padding (4 on each side) for string + sta gPathname ; gPathname = length + tax + lda #$07 ; gPathname+length = top-right rounded corner character + sta gPathname,x + rts + +BuildCheatLine2 +; in: X = game index, or #$FF if no game is selected +; out: gPathname contains length-prefixed string to print centered +; all registers clobbered +; PTR clobbered +; SAVE clobbered + cpx #$FF + beq + + ldy gCheatsAvailable,x + +HIDE_NEXT_2_BYTES ++ + ldy #.kCheatsEnabled + lda .kCheatDescriptionLo,y + sta SAVE + lda .kCheatDescriptionHi,y + sta SAVE+1 + ; (SAVE) -> length-prefixed cheat description + +LDADDR .sCheatDescriptionPrefix + jsr SetPath + +LDAY SAVE + jsr AddToPath + +LDADDR .sCheatDescriptionSuffix + jmp AddToPath + +.kCheatsEnabled = 3 ; index of 'cheats enabled' string in following table +.kCheatDescriptionLo + !byte <.sNoCheats + !byte <.sInfiniteLives + !byte <.sInfiniteLivesAndWeapons + !byte <.sCheatsEnabled +.kCheatDescriptionHi + !byte >.sNoCheats + !byte >.sInfiniteLives + !byte >.sInfiniteLivesAndWeapons + !byte >.sCheatsEnabled +.sNoCheats + !byte 14 + !text "no cheats yet!" +.sInfiniteLives + !byte 14 + !text "infinite lives" +.sInfiniteLivesAndWeapons + !byte 24 + !text "infinite lives & weapons" +.sCheatsEnabled + !byte 14 + !text "cheats enabled" +.sCheatDescriptionPrefix + !byte 4 + !byte $03 ; vertical line + !text " " + !byte $16 ; bolt + !text " " +.sCheatDescriptionSuffix + !byte 4 + !text " " + !byte $16 ; bolt + !text " " + !byte $03 ; vertical line diff --git a/src/ui.common.a b/src/ui.common.a index 333615718..97dd04985 100644 --- a/src/ui.common.a +++ b/src/ui.common.a @@ -142,20 +142,47 @@ CoverFade ; DrawSearchBarOffscreen ; draw 2-line search UI on the HGR page that is not currently showing ; -; in: none +; in: X = game index, or #$FF if no game is selected ; out: all flags and registers clobbered ;------------------------------------------------------------------------------ DrawSearchBarOffscreen + txa + pha lda #22 ; draw visible search bar sta VTAB lda OffscreenPage - ror ; draw on offscreen page + ror ; draw line 1 on offscreen page +LDADDR UILine1 jsr Draw40Chars lda OffscreenPage - ror ; draw on offscreen page + ror ; draw line 2 on offscreen page +LDADDR UILine2 - jmp Draw40Chars + jsr Draw40Chars + + pla + bit gCheatsEnabled + bpl @done ; if cheats are not enabled, we're done + + pha + tax + lda #20 + sta VTAB + jsr BuildCheatLine1 + lda OffscreenPage + ror + +LDADDR gPathname + jsr DrawCenteredString + + inc VTAB + pla + tax + jsr BuildCheatLine2 + lda OffscreenPage + ror + +LDADDR gPathname + jsr DrawCenteredString + +@done rts ;------------------------------------------------------------------------------ ; ClearOffscreen diff --git a/src/ui.font.a b/src/ui.font.a index dc7abec5a..27f6c13d6 100644 --- a/src/ui.font.a +++ b/src/ui.font.a @@ -10,6 +10,7 @@ ; Public functions ; - DrawPageInternal ; - Draw40CharsInternal +; - DrawCenteredStringInternal ; - DrawStringInternal ; - DrawBufferInternal ; @@ -86,6 +87,27 @@ Draw40CharsInternal stx HTAB rts +DrawCenteredStringInternal +; A/Y contains address of length-prefixed string +; carry bit clear -> draw on page 1 +; carry bit set -> draw on page 2 +; $25 contains textpage line (0..23) (this is the standard VTAB address) +; clobbers A/X/Y +; clobbers PTR/PTR+1 + +STAY PTR + + php + ldy #0 + lda (PTR),y + sta HTAB + lda #40 + sec + sbc HTAB + lsr + sta HTAB + plp + jmp + + DrawStringInternal ; A/Y contains address of length-prefixed string ; carry bit clear -> draw on page 1 @@ -97,7 +119,7 @@ DrawStringInternal +STAY PTR ldy #0 - lda (PTR),y ++ lda (PTR),y tax inc PTR bne + diff --git a/src/ui.search.mode.a b/src/ui.search.mode.a index 453533002..841495ef1 100644 --- a/src/ui.search.mode.a +++ b/src/ui.search.mode.a @@ -120,16 +120,17 @@ SearchMode ; no input, reset params and UI lda #$FF sta SelectedIndex ; no game selected - ldx #39 ; reset visible line -- lda #0 - sta UILine1,x - lda Instructions,x + ldx #39 ; copy instructions to line 2 +- lda Instructions,x sta UILine2,x dex bpl - jsr LoadTitleOffscreen - jsr DrawSearchBarOffscreen - jsr ShowOtherPage + ldx #$FF ; no game selected + jsr BuildUILine1WithNoDots; build UI line 1 with bars and other shapes + ldx #$FF ; no game selected + jsr DrawSearchBarOffscreen; draw everything at once (offscreen) + jsr ShowOtherPage ; show it all at once clc rts @@ -199,19 +200,20 @@ SearchMode sta UI_ToPlay,x dex bpl - - ldx #40 - lda #0 -- sta UILine1-1,x ; reset search bar - dex - bne - - tay + + ldx SelectedIndex + jsr BuildUILine1WithNoDots; build UI line 1 with bars and other shapes + + ; now add dots to UI line 1 to highlight matched characters + ldx #0 + ldy #0 @dotloop iny lda (SRC),y +LOW_ASCII_TO_LOWER cmp InputBuffer,x bne + - lda #$11 ; add dots to highlight matched characters + lda #$11 ; dot character sta UILine1,y inx cpx InputLength ; if input buffer is exhausted, we're done @@ -220,6 +222,7 @@ SearchMode cpy SAVE ; if game name is exhausted, we're done bne @dotloop @doneHighlight + ldx SelectedIndex jsr DrawSearchBarOffscreen; actually draw the search UI (offscreen) jmp ShowOtherPage ; now show everything at once