Crap Game: Snake but the only instruction is LD
Crap Game: Snake but the only instruction is LD
Z80 machine code has a lot of instructions, and it can be difficult trying to keep track of them all. Does PUSH decrement the stack pointer before or afterwards? What's the difference between IFF1 and IFF2? And what exactly does DAA even do?
Well, here's some good news: you don't have to memorise any of these instructions, since it turns out that all of them are in fact useless! (Cries of 'blow me down' and 'well I never'. Ed.) Well, it's true. And to prove it, here's a version of that gaming classic, Snake, where every single instruction is replaced with the humble LD. Nope, there's no trickery or self-modifying code going on here - it's all just LD instructions.
Download here: snake.tap
Runs on any 48K/128K Spectrum. Controls are QAOP or 5678.
Planned features: Extra levels, redefinable keys, multiple speed settings, online leaderboard, ability to make phone calls, VR support, Rolos dispensed when you win...
Source code available here if you want to experience the true horror. Viewer discretion is advised.
Re: Crap Game: Snake but the only instruction is LD
This could be useful, to someone starting to implement an emulator, since there are less instructions to implement to have something working on screen
But this is borderline madness
But this is borderline madness
Re: Crap Game: Snake but the only instruction is LD
This is brilliant!
ZX Soft - ALIEN(BUGFIX) - GB Soft - Demoscene
- Ast A. Moore
- Rick Dangerous
- Posts: 2643
- Joined: Mon Nov 13, 2017 3:16 pm
Re: Crap Game: Snake but the only instruction is LD
Hah! This is as insane as it is brilliant.
Every man should plant a tree, build a house, and write a ZX Spectrum game.
Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Re: Crap Game: Snake but the only instruction is LD
Nope. It's too early in the morning for me to work out how you've made a functioning game with only LD instructions.
Are you loading opcodes into where the PC is?
Nice wee snake game, I can manage 19 (EDIT - didn't realise we had QAOP)
Are you loading opcodes into where the PC is?
Nice wee snake game, I can manage 19 (EDIT - didn't realise we had QAOP)
Re: Crap Game: Snake but the only instruction is LD
MetooNope. It's too early in the morning for me to work out how you've made a functioning game with only LD instructions.
So how does it work? You need loops, you need comparisons, you need jumps. Are you using self-modified code a lot to create these instructions with LDs to proper places in memory?
Re: Crap Game: Snake but the only instruction is LD
He did mention ...
So go have a lookdjnzx48 wrote: ↑Tue May 29, 2018 10:28 am ... Nope, there's no trickery or self-modifying code going on here - it's all just LD instructions.
...
Source code available here if you want to experience the true horror. Viewer discretion is advised.
Spoiler
He did use some other instructions ... but it's mostly LDs.
Re: Crap Game: Snake but the only instruction is LD
I did. Still can't figure out how he engineers a jump.
I'm guessing there are some long waits of repeated instructions and some pre-defined jump (or return stack) values being set up, so possibly waiting around for an interrupt to occur to trigger a jump..?
Though after all that effort, relying on ROM routines to read the keyboard seems a bit of a cop-out...
I'm guessing there are some long waits of repeated instructions and some pre-defined jump (or return stack) values being set up, so possibly waiting around for an interrupt to occur to trigger a jump..?
Though after all that effort, relying on ROM routines to read the keyboard seems a bit of a cop-out...
Re: Crap Game: Snake but the only instruction is LD
Okay, now I'm after work. I looked at the code. I traced it in emulator with a debugger. And I don't still understand anything
An explanation is warmly welcomed
An explanation is warmly welcomed
Re: Crap Game: Snake but the only instruction is LD
Thanks guys!
It's actually quite simple how it works. If you want to do a comparison between, say, B and C, you can just use:
LD H, somewhere
LD L, B
LD (HL), false
LD L, C
LD (HL), true
LD L, B
LD A, (HL)
Basically you're just loading some value into the memory location pointed to by B, and then doing the same for C. Then you load back the value from the first location. If you get back what you started, you know that it can't have been overwritten by C and so B <> C. However, if you get back the new value, B and C must be equal. Once you have the result from a comparison, you use that to index into one of many lookup tables, which is what the first 2000 lines of the code are setting up!
The jumps rely on IM1. I don't see how I can switch them off when I can't use DI! The stack pointer is set to point to somewhere in the first few bytes of ROM, so that when the interrupt returns, it jumps to not the original return address but whatever value's in ROM. This is used to either jump back to the main loop, the setup phase for when you die, or a delay loop to slow the game down.
However, you're restricted in what addresses you can jump to because the interrupt calls the keyboard routine, and this must return properly so that the EI can execute and interrupts can occur again. So when this occurs the stack pointer must be in RAM. There's another trick though. The interrupt routine PUSHes AF, HL, BC and DE before calling the keyboard routine. Since an interrupt can only occur during the large block of dummy instructions at the end of the program, we don't care if these registers get corrupted. So that gives 8 possible addresses to jump to depending on which registers get PUSHed to ROM. Some of these addresses are too high in memory to be used, and some are too low and risk interfering with BASIC, so the three addresses used here are AFF3, C3FF, and CBC3.
Of course, if you used a +3, you could simply fill the entire memory up with LD instructions and then just wrap around when you reached the end, so none of this would be necessary.
There's a paper here where someone made a functioning Turing machine just using the MOV instruction on x86. They cheated though by using a JMP! Even crazier, there's an an entire C compiler using this idea!
It's actually quite simple how it works. If you want to do a comparison between, say, B and C, you can just use:
LD H, somewhere
LD L, B
LD (HL), false
LD L, C
LD (HL), true
LD L, B
LD A, (HL)
Basically you're just loading some value into the memory location pointed to by B, and then doing the same for C. Then you load back the value from the first location. If you get back what you started, you know that it can't have been overwritten by C and so B <> C. However, if you get back the new value, B and C must be equal. Once you have the result from a comparison, you use that to index into one of many lookup tables, which is what the first 2000 lines of the code are setting up!
The jumps rely on IM1. I don't see how I can switch them off when I can't use DI! The stack pointer is set to point to somewhere in the first few bytes of ROM, so that when the interrupt returns, it jumps to not the original return address but whatever value's in ROM. This is used to either jump back to the main loop, the setup phase for when you die, or a delay loop to slow the game down.
However, you're restricted in what addresses you can jump to because the interrupt calls the keyboard routine, and this must return properly so that the EI can execute and interrupts can occur again. So when this occurs the stack pointer must be in RAM. There's another trick though. The interrupt routine PUSHes AF, HL, BC and DE before calling the keyboard routine. Since an interrupt can only occur during the large block of dummy instructions at the end of the program, we don't care if these registers get corrupted. So that gives 8 possible addresses to jump to depending on which registers get PUSHed to ROM. Some of these addresses are too high in memory to be used, and some are too low and risk interfering with BASIC, so the three addresses used here are AFF3, C3FF, and CBC3.
Of course, if you used a +3, you could simply fill the entire memory up with LD instructions and then just wrap around when you reached the end, so none of this would be necessary.
There's a paper here where someone made a functioning Turing machine just using the MOV instruction on x86. They cheated though by using a JMP! Even crazier, there's an an entire C compiler using this idea!
Well if you can find a peripheral for the Spectrum that uses memory-mapped IO, I'll gladly change it!
Re: Crap Game: Snake but the only instruction is LD
This is flippin’ genius. Infinite hats doffed to you!
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
Re: Crap Game: Snake but the only instruction is LD
I half expected the game code to start screaming at me to let it die. Viewer discretion indeed
Re: Crap Game: Snake but the only instruction is LD
Are there any other instructions this could be done with other than LD? I was thinking that the shift/rotate instructions look like the best bet, plus you can use the undocumented instructions such as LD B, RLC (IX+d). You could use this along with an address in ROM to effectively load a value into a register, except you'd have to account for the value being shifted over one.
Re: Crap Game: Snake but the only instruction is LD
Ah no, that wouldn't work because there doesn't seem to be a way to do jumps without somehow modifying the stack pointer, which you can't do with shifts/rotates. Using the all-RAM configuration on a +3 wouldn't really work either because the screen would get in the way.
I did consider either moving the stack to the location of the FRAMES system variable, or setting IY to point to the stack, so that when the interrupt routine increments FRAMES it increments the return address. This would only let you do 256 byte jumps, but if the calling code is after $FF00 it could potentially be used to jump into ROM which then does a RET to the desired location? So maybe a sequel is possible after all
I did consider either moving the stack to the location of the FRAMES system variable, or setting IY to point to the stack, so that when the interrupt routine increments FRAMES it increments the return address. This would only let you do 256 byte jumps, but if the calling code is after $FF00 it could potentially be used to jump into ROM which then does a RET to the desired location? So maybe a sequel is possible after all
Re: Crap Game: Snake but the only instruction is LD
I'm still getting my head around this one! I can see how it loops by repeating LD A,(HL) and changing the stack so the interrupt does it for you, but I need to put a cold flannel on my head and work out how you can do everything else without even using CP!
I wouldn't have thought this possible.
Re: Crap Game: Snake but the only instruction is LD
Well this technique is very limited
Instead of thinking of branches and choosing whether to do some computation or not based on a condition, you basically always do the computation, but set it up so that if the condition is false you end up with what you had before. So for example, the food always gets drawn every frame, but if there's still food on the screen or if the screen position where it's supposed to appear is occupied, it just draws whatever colour is already on the screen and so nothing changes. There's still a lot of things that are basically impossible to do without resorting to complicated loops, even just adding two numbers or checking whether one value is greater than another.
Instead of thinking of branches and choosing whether to do some computation or not based on a condition, you basically always do the computation, but set it up so that if the condition is false you end up with what you had before. So for example, the food always gets drawn every frame, but if there's still food on the screen or if the screen position where it's supposed to appear is occupied, it just draws whatever colour is already on the screen and so nothing changes. There's still a lot of things that are basically impossible to do without resorting to complicated loops, even just adding two numbers or checking whether one value is greater than another.
Re: Crap Game: Snake but the only instruction is LD
is there a version for the WinAPE?
Re: Crap Game: Snake but the only instruction is LD
please remap the keys to traditional arrow or wasd pleasedjnzx48 wrote: ↑Tue May 29, 2018 10:28 am
Z80 machine code has a lot of instructions, and it can be difficult trying to keep track of them all. Does PUSH decrement the stack pointer before or afterwards? What's the difference between IFF1 and IFF2? And what exactly does DAA even do?
Well, here's some good news: you don't have to memorise any of these instructions, since it turns out that all of them are in fact useless! (Cries of 'blow me down' and 'well I never'. Ed.) Well, it's true. And to prove it, here's a version of that gaming classic, Snake, where every single instruction is replaced with the humble LD. Nope, there's no trickery or self-modifying code going on here - it's all just LD instructions.
Download here: snake.tap
Runs on any 48K/128K Spectrum. Controls are QAOP or 5678.
Planned features: Extra levels, redefinable keys, multiple speed settings, online leaderboard, ability to make phone calls, VR support, Rolos dispensed when you win...
Source code available here if you want to experience the true horror. Viewer discretion is advised.
Re: Crap Game: Snake but the only instruction is LD
5678 *is* traditional arrow.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
Re: Crap Game: Snake but the only instruction is LD
Plays like a dream!
Re: Crap Game: Snake but the only instruction is LD
I was thinking of adding WASD keys but that clashes with QAOP which is more 'traditional', IMHO. I'll probably add redefinable keys in a future update. I don't know anything about Amstrad machines, so no idea if anything like this is possible there.
EDIT: Would ESDF do? It's the same basic configuration but just shifted over one.
EDIT: Would ESDF do? It's the same basic configuration but just shifted over one.
Re: Crap Game: Snake but the only instruction is LD
[mention]MrPixel[/mention] there's a new update here adding ESDF controls in addition to the old QAOP and 5678 controls.
Re: Crap Game: Snake but the only instruction is LD
what about I,j,k,l or plain arrow keys. i'm on a latop so the traditional 5,6,7,8 keys are in a straight vertical line, not marked. good game though. i'm amazed that you were able to pull this off. won't run in zxspin assembler thoughdjnzx48 wrote: ↑Thu May 31, 2018 12:46 am I was thinking of adding WASD keys but that clashes with QAOP which is more 'traditional', IMHO. I'll probably add redefinable keys in a future update. I don't know anything about Amstrad machines, so no idea if anything like this is possible there.
EDIT: Would ESDF do? It's the same basic configuration but just shifted over one.
Re: Crap Game: Snake but the only instruction is LD
so, the base game is good, impressive even. however, the snake lacks any sort of ability to reverse direction. maybe add in some sort of bumper (like in sonic CD in Collision Chaos) that would help the snake reverse direction. also, some music. take advantage of the Spectrum 128's capabilities and create something suitable. i would also suggest you remove the ground barriers as well as the ceiling as i had some trouble with them. your decision but keep it in mind. happy coding
Re: Crap Game: Snake but the only instruction is LD
Yeah there are probably too many obstacles, I spent about 5 minutes making the layout for the game so it could definitely be improved. I'd like to add music but there's no way to play it with just the LD instruction, so it would have to be done with some ROM routine and things could get quite tricky. Not sure quite what you mean about reversing direction?