#zxspectrum — Public Fediverse posts
Live and recent posts from across the Fediverse tagged #zxspectrum, aggregated by home.social.
-
RC2014/Z80 Minimal ROM
I want to ROM-ify the messing about I’ve been doing with the AY-3-8910 driver and video code, so I need to figure out what boot-strapping is required to get a basic Z80 machine up and running from power-on. Then I can programme it all into a ROM and just have it startup automatically.
Some key resources:
- Minimal RC2014 boot and initialisation: https://github.com/RC2014Z80/RC2014/blob/master/ROMs/init/rc2014init.asm
- Z80 boot template: https://jacobielectronix.wordpress.com/2015/12/07/z80-cpu-boot-asm-template/
- ZX Spectrum ROM Dissassembly (book and online): https://skoolkid.github.io/rom/
To start, we can note the following from the Z80 User Manual:
“RESET. Reset (input, active Low).”
“RESET initializes the CPU as follows: it resets the interrupt enable flip-flop, clears the Program Counter and registers I and R, and sets the interrupt status to Mode 0. During reset time, the address and data bus enter a high-imped ance state, and all control output signals enter an inactive state. R must be active for a minimum of three full clock cycles before a reset operation is complete.”
So execution will be starting from address $0000 (a cleared Program Counter).
There are several special addresses that will require code – these are the RST locations associated with the RST instruction as described here: https://jnz.dk/z80/rst_p.html. RST is basically a 1-byte CALL equivalent, but it can only call one of eight locations: $00, $08, $10, $18, $20, $28, $30, $38.
A key location for me will be RST $38 which is the interrupt handler I’ll need to handle for the /INT 50Hz interrupt.
Other things that will have to be done on first power up include:
- Any required memory initialisation – e.g. if any of it has to be set to zero or copied from ROM to RAM or anything that needs presetting to a specific value.
- Any required hardware initialisation – e.g. for a R2014 this usually means getting the serial link up and running.
- Set the stack pointer to somewhere at the top of RAM.
- Initialise any hardware registers and then jump to the main application.
I don’t think I need to do anything special to the CPU registers or flags, but happy to be corrected! I haven’t found an obvious “this is what you do to start a Z80” type resource so far, so I’m just inferring from the references listed above right now.
AY Driver ROM
Most of the code and data for the AY driver and tune can be relocated to ROM, but there are several blocks of state variables that must be placed in RAM. Consequently, I’ve had to do the following:
- Create a RAM block at origin $8000 for the state variables.
- Remove the origin statements for Code_Start and Data_Start, but I’ve replaced them with assembler labels.
- Add in some code to pre-initialise the state variables all to zero on startup.
- As well as the AY driver state variables, there are a few additional state variables associated with the following:
- Positions related to the display harness
- Some values associated with the CLOCK, one of which (FIFTY) also needs initialising to 50 on power up.
- The AY driver’s internal “stack” (e.g. SP_A).
- And it also turns out that it has to be able to clear the keypress that my own harness pre-sets to “0” otherwise it constantly resets to play the first tune. So I need to move that to RAM too.
My initialisation code is as follows:
; RESET and Bootstrap
.org $00
jp AYSTART
; RST jump tables
.org $08
ret
.org $10
ret
.org $18
ret
.org $20
ret
.org $28
ret
.org $30
ret
.org $38 ; Maskable /INT
ei
reti ; Return from interrupt
.org $66 ; Non-maskable /NMI
retn ; Return from non-maskable interrupt
; Bootstrap code
.org $100
AYSTART:
; Initialise stack
ld sp, $FF00
; Set all AYVars in RAM to 0
xor a
VARINITLoop:
ld hl, AYVARSTART
ld bc,(AYVAREND-AYVARSTART)
ld (hl),a
inc hl
dec bc
jp nz,VARINITLoop
; Initialise any specific variable values
ld hl,FIFTY
ld a,50
ld (hl),a
; Preset the keypress for first tune
ld hl,LASTK
ld a,48 ; Preset keypress to "0" for the first tune
ld (hl),a
; Enable the 50Hz Interrupt
im 1
ei
; Run the driver
jp Code_StartThere are a couple of hard-coded references to address 50000 (decimal) which is Data_Start. These have had to be changed. The locations/definitions between the original CODE_BOT: and DATA_TOP: labels are now as follows:
CODE_BOT:
CALC1: EQU CODE_BOT-CODE_TOP
;--------------------------------------
; ORG Data_Start
Data_Start:
NTUNES: EQU 1
NEFFECTS: EQU 1
;--------------------------------------
CALC2: DW CALC
Tunes: DB NTUNES
Effects: DB NEFFECTS
;--------------------------------------
DATA_TOP:The original code has 5 tunes and 21 effects which can be selected by pressing a key. I’ve not ported any keyboard handling over as yet, so it only plays the one tune. I’ve cleared out the data for four of the tunes and all the effects bar one. I’ve left one effect in as I don’t know how the code handles having zero effects.
This has an advantage in that all fixed data and code now fits within 8K, which is the standard, common ROM block size for RC2014.
Programming
I can now take the standard ROM that came with my Classic II from here: https://github.com/RC2014Z80/RC2014/blob/master/ROMs/Factory/R0000009.BIN, which has the following ROMs built in:
$0000-$1FFFRC2014 32K BASIC$2000-$3FFF
$4000-$5FFF
$6000-$7FFF
$A000-$BFFF
$C000-$DFFFUnused$E000-$EFFFSCM Z80 MonitorI can thus load this image into a programmer and then add in the HEX records for the AY driver at location $2000-3FFF remembering not to clear the loaded contents first. Then it will be selectable via the ROM jumpers
The above location are EEPROM locations. The jumpers control the state of A13, A14, A15 as seen by the EEPROM. From the RC2014 point of view any selected image will always appear at address $0000-$1FFF in the wider memory map no matter its position in the EPROM.
I’ve programmed it to W27C512s and used it with my RC2014 micro module, which takes 27C512 ROMS. My Classic II is described as also taking 27C512 ROMs, but the latest revision of the board actually uses half of a 128K ST39SF010.
Conclusion
It is great to be able to just turn on the RC2014 and have it come up playing the AY music. This means that for a complete player I now have:
- A RC2014 backplane (any will do).
- RC2014 micro system with custom ROM.
- My ZX Spectrum Compatible Video for RC2014 (V2 with the 50Hz interrupt).
- Either Ed Brindley’s AY-3-8910 for RC2014 or the WhyEm sound card.
Kevin
#ay38910 #rc2014 #zxSpectrum -
RC2014/Z80 Minimal ROM
I want to ROM-ify the messing about I’ve been doing with the AY-3-8910 driver and video code, so I need to figure out what boot-strapping is required to get a basic Z80 machine up and running from power-on. Then I can programme it all into a ROM and just have it startup automatically.
Some key resources:
- Minimal RC2014 boot and initialisation: https://github.com/RC2014Z80/RC2014/blob/master/ROMs/init/rc2014init.asm
- Z80 boot template: https://jacobielectronix.wordpress.com/2015/12/07/z80-cpu-boot-asm-template/
- ZX Spectrum ROM Dissassembly (book and online): https://skoolkid.github.io/rom/
To start, we can note the following from the Z80 User Manual:
“RESET. Reset (input, active Low).”
“RESET initializes the CPU as follows: it resets the interrupt enable flip-flop, clears the Program Counter and registers I and R, and sets the interrupt status to Mode 0. During reset time, the address and data bus enter a high-imped ance state, and all control output signals enter an inactive state. R must be active for a minimum of three full clock cycles before a reset operation is complete.”
So execution will be starting from address $0000 (a cleared Program Counter).
There are several special addresses that will require code – these are the RST locations associated with the RST instruction as described here: https://jnz.dk/z80/rst_p.html. RST is basically a 1-byte CALL equivalent, but it can only call one of eight locations: $00, $08, $10, $18, $20, $28, $30, $38.
A key location for me will be RST $38 which is the interrupt handler I’ll need to handle for the /INT 50Hz interrupt.
Other things that will have to be done on first power up include:
- Any required memory initialisation – e.g. if any of it has to be set to zero or copied from ROM to RAM or anything that needs presetting to a specific value.
- Any required hardware initialisation – e.g. for a R2014 this usually means getting the serial link up and running.
- Set the stack pointer to somewhere at the top of RAM.
- Initialise any hardware registers and then jump to the main application.
I don’t think I need to do anything special to the CPU registers or flags, but happy to be corrected! I haven’t found an obvious “this is what you do to start a Z80” type resource so far, so I’m just inferring from the references listed above right now.
AY Driver ROM
Most of the code and data for the AY driver and tune can be relocated to ROM, but there are several blocks of state variables that must be placed in RAM. Consequently, I’ve had to do the following:
- Create a RAM block at origin $8000 for the state variables.
- Remove the origin statements for Code_Start and Data_Start, but I’ve replaced them with assembler labels.
- Add in some code to pre-initialise the state variables all to zero on startup.
- As well as the AY driver state variables, there are a few additional state variables associated with the following:
- Positions related to the display harness
- Some values associated with the CLOCK, one of which (FIFTY) also needs initialising to 50 on power up.
- The AY driver’s internal “stack” (e.g. SP_A).
- And it also turns out that it has to be able to clear the keypress that my own harness pre-sets to “0” otherwise it constantly resets to play the first tune. So I need to move that to RAM too.
My initialisation code is as follows:
; RESET and Bootstrap
.org $00
jp AYSTART
; RST jump tables
.org $08
ret
.org $10
ret
.org $18
ret
.org $20
ret
.org $28
ret
.org $30
ret
.org $38 ; Maskable /INT
ei
reti ; Return from interrupt
.org $66 ; Non-maskable /NMI
retn ; Return from non-maskable interrupt
; Bootstrap code
.org $100
AYSTART:
; Initialise stack
ld sp, $FF00
; Set all AYVars in RAM to 0
xor a
VARINITLoop:
ld hl, AYVARSTART
ld bc,(AYVAREND-AYVARSTART)
ld (hl),a
inc hl
dec bc
jp nz,VARINITLoop
; Initialise any specific variable values
ld hl,FIFTY
ld a,50
ld (hl),a
; Preset the keypress for first tune
ld hl,LASTK
ld a,48 ; Preset keypress to "0" for the first tune
ld (hl),a
; Enable the 50Hz Interrupt
im 1
ei
; Run the driver
jp Code_StartThere are a couple of hard-coded references to address 50000 (decimal) which is Data_Start. These have had to be changed. The locations/definitions between the original CODE_BOT: and DATA_TOP: labels are now as follows:
CODE_BOT:
CALC1: EQU CODE_BOT-CODE_TOP
;--------------------------------------
; ORG Data_Start
Data_Start:
NTUNES: EQU 1
NEFFECTS: EQU 1
;--------------------------------------
CALC2: DW CALC
Tunes: DB NTUNES
Effects: DB NEFFECTS
;--------------------------------------
DATA_TOP:The original code has 5 tunes and 21 effects which can be selected by pressing a key. I’ve not ported any keyboard handling over as yet, so it only plays the one tune. I’ve cleared out the data for four of the tunes and all the effects bar one. I’ve left one effect in as I don’t know how the code handles having zero effects.
This has an advantage in that all fixed data and code now fits within 8K, which is the standard, common ROM block size for RC2014.
Programming
I can now take the standard ROM that came with my Classic II from here: https://github.com/RC2014Z80/RC2014/blob/master/ROMs/Factory/R0000009.BIN, which has the following ROMs built in:
$0000-$1FFFRC2014 32K BASIC$2000-$3FFF
$4000-$5FFF
$6000-$7FFF
$A000-$BFFF
$C000-$DFFFUnused$E000-$EFFFSCM Z80 MonitorI can thus load this image into a programmer and then add in the HEX records for the AY driver at location $2000-3FFF remembering not to clear the loaded contents first. Then it will be selectable via the ROM jumpers
The above location are EEPROM locations. The jumpers control the state of A13, A14, A15 as seen by the EEPROM. From the RC2014 point of view any selected image will always appear at address $0000-$1FFF in the wider memory map no matter its position in the EPROM.
I’ve programmed it to W27C512s and used it with my RC2014 micro module, which takes 27C512 ROMS. My Classic II is described as also taking 27C512 ROMs, but the latest revision of the board actually uses half of a 128K ST39SF010.
Conclusion
It is great to be able to just turn on the RC2014 and have it come up playing the AY music. This means that for a complete player I now have:
- A RC2014 backplane (any will do).
- RC2014 micro system with custom ROM.
- My ZX Spectrum Compatible Video for RC2014 (V2 with the 50Hz interrupt).
- Either Ed Brindley’s AY-3-8910 for RC2014 or the WhyEm sound card.
Kevin
#ay38910 #rc2014 #zxSpectrum -
Work in progress, it's going to take a while. Layer2 is now wired, and sprites are buggy. Tiles are not implemented at all, and it won't be able to boot NextZXOS for a while because it requires FAT handling. Clock speed is kind of random right now, needs to be worked on to match a real Next. It has no idea about loading NEX files at all, although all things considered, it's a pretty well specified format, shouldn't be a lot harder than loading traditional snapshots.
BUT, it implements NEXTREG and it can correctly composite the existing graphic mode layers and sprites in the specified order. Z80N emulation seems to be good, with a test harness to match Z80N behaviour against CSpect across all extended Z80N instructions.
I was able to boot it using a +3 ROM set, and used Layer 2 to paint a red pixel using the Next machinery and it worked. A fully-featured Next is probably months away.
#ZXSpectrumNext #SpectrumNext #ZXSpectrum #Speccy #Spectrum #retrocomputing #zenzx #emulator #golang #foss
-
Work in progress, it's going to take a while. Layer2 is now wired, and sprites are buggy. Tiles are not implemented at all, and it won't be able to boot NextZXOS for a while because it requires FAT handling. Clock speed is kind of random right now, needs to be worked on to match a real Next. It has no idea about loading NEX files at all, although all things considered, it's a pretty well specified format, shouldn't be a lot harder than loading traditional snapshots.
BUT, it implements NEXTREG and it can correctly composite the existing graphic mode layers and sprites in the specified order. Z80N emulation seems to be good, with a test harness to match Z80N behaviour against CSpect across all extended Z80N instructions.
I was able to boot it using a +3 ROM set, and used Layer 2 to paint a red pixel using the Next machinery and it worked. A fully-featured Next is probably months away.
#ZXSpectrumNext #SpectrumNext #ZXSpectrum #Speccy #Spectrum #retrocomputing #zenzx #emulator #golang #foss
-
Work in progress, it's going to take a while. Layer2 is now wired, and sprites are buggy. Tiles are not implemented at all, and it won't be able to boot NextZXOS for a while because it requires FAT handling. Clock speed is kind of random right now, needs to be worked on to match a real Next. It has no idea about loading NEX files at all, although all things considered, it's a pretty well specified format, shouldn't be a lot harder than loading traditional snapshots.
BUT, it implements NEXTREG and it can correctly composite the existing graphic mode layers and sprites in the specified order. Z80N emulation seems to be good, with a test harness to match Z80N behaviour against CSpect across all extended Z80N instructions.
I was able to boot it using a +3 ROM set, and used Layer 2 to paint a red pixel using the Next machinery and it worked. A fully-featured Next is probably months away.
#ZXSpectrumNext #SpectrumNext #ZXSpectrum #Speccy #Spectrum #retrocomputing #zenzx #emulator #golang #foss
-
Work in progress, it's going to take a while. Layer2 is now wired, and sprites are buggy. Tiles are not implemented at all, and it won't be able to boot NextZXOS for a while because it requires FAT handling. Clock speed is kind of random right now, needs to be worked on to match a real Next. It has no idea about loading NEX files at all, although all things considered, it's a pretty well specified format, shouldn't be a lot harder than loading traditional snapshots.
BUT, it implements NEXTREG and it can correctly composite the existing graphic mode layers and sprites in the specified order. Z80N emulation seems to be good, with a test harness to match Z80N behaviour against CSpect across all extended Z80N instructions.
I was able to boot it using a +3 ROM set, and used Layer 2 to paint a red pixel using the Next machinery and it worked. A fully-featured Next is probably months away.
#ZXSpectrumNext #SpectrumNext #ZXSpectrum #Speccy #Spectrum #retrocomputing #zenzx #emulator #golang #foss
-
Work in progress, it's going to take a while. Layer2 is now wired, and sprites are buggy. Tiles are not implemented at all, and it won't be able to boot NextZXOS for a while because it requires FAT handling. Clock speed is kind of random right now, needs to be worked on to match a real Next. It has no idea about loading NEX files at all, although all things considered, it's a pretty well specified format, shouldn't be a lot harder than loading traditional snapshots.
BUT, it implements NEXTREG and it can correctly composite the existing graphic mode layers and sprites in the specified order. Z80N emulation seems to be good, with a test harness to match Z80N behaviour against CSpect across all extended Z80N instructions.
I was able to boot it using a +3 ROM set, and used Layer 2 to paint a red pixel using the Next machinery and it worked. A fully-featured Next is probably months away.
#ZXSpectrumNext #SpectrumNext #ZXSpectrum #Speccy #Spectrum #retrocomputing #zenzx #emulator #golang #foss
-
012_000010B3.stc by Yerzmyey
./u/SpejsSzip.ay
Title: 012_000010B3.stc
Author: Yerzmyey
#ZXSpectrum
#chiptune -
012_000010B3.stc by Yerzmyey
./u/SpejsSzip.ay
Title: 012_000010B3.stc
Author: Yerzmyey
#ZXSpectrum
#chiptune -
012_000010B3.stc by Yerzmyey
./u/SpejsSzip.ay
Title: 012_000010B3.stc
Author: Yerzmyey
#ZXSpectrum
#chiptune -
012_000010B3.stc by Yerzmyey
./u/SpejsSzip.ay
Title: 012_000010B3.stc
Author: Yerzmyey
#ZXSpectrum
#chiptune -
012_000010B3.stc by Yerzmyey
./u/SpejsSzip.ay
Title: 012_000010B3.stc
Author: Yerzmyey
#ZXSpectrum
#chiptune -
Brand new Spectrum game: Space Trolls of Mahlsdorf, by Papi & Sohn.
Download:
https://papi-sohn.itch.io/space-trolls-of-mahlsdorf -
Brand new Spectrum game: Space Trolls of Mahlsdorf, by Papi & Sohn.
Download:
https://papi-sohn.itch.io/space-trolls-of-mahlsdorf -
Brand new Spectrum game: Space Trolls of Mahlsdorf, by Papi & Sohn.
Download:
https://papi-sohn.itch.io/space-trolls-of-mahlsdorf -
Brand new Spectrum game: Space Trolls of Mahlsdorf, by Papi & Sohn.
Download:
https://papi-sohn.itch.io/space-trolls-of-mahlsdorf -
Brand new Spectrum game: Space Trolls of Mahlsdorf, by Papi & Sohn.
Download:
https://papi-sohn.itch.io/space-trolls-of-mahlsdorf -
Brand new Spectrum game: War of the Zikoi, by Papi & Sohn.
-
Brand new Spectrum game: War of the Zikoi, by Papi & Sohn.
-
Brand new Spectrum game: War of the Zikoi, by Papi & Sohn.
-
Brand new Spectrum game: War of the Zikoi, by Papi & Sohn.
-
Brand new Spectrum game: War of the Zikoi, by Papi & Sohn.
-
B1K-Gammon (2026) by Dr Beep (zx81coder) for ZX Spectrum.
Is a proper game of backgammon possible in 1K? See for yourself
-
B1K-Gammon (2026) by Dr Beep (zx81coder) for ZX Spectrum.
Is a proper game of backgammon possible in 1K? See for yourself
-
B1K-Gammon (2026) by Dr Beep (zx81coder) for ZX Spectrum.
Is a proper game of backgammon possible in 1K? See for yourself
-
B1K-Gammon (2026) by Dr Beep (zx81coder) for ZX Spectrum.
Is a proper game of backgammon possible in 1K? See for yourself
-
B1K-Gammon (2026) by Dr Beep (zx81coder) for ZX Spectrum.
Is a proper game of backgammon possible in 1K? See for yourself
-
Murder (2026) by Kanon WinVega for ZX Spectrum.
A crime boss's wife wants him dead. You're the psychopath she hired. Thirty mobster-filled streets stand between you and Salvatore. Classic arcade carnage for the 48k.⚰
-
Murder (2026) by Kanon WinVega for ZX Spectrum.
A crime boss's wife wants him dead. You're the psychopath she hired. Thirty mobster-filled streets stand between you and Salvatore. Classic arcade carnage for the 48k.⚰
-
Murder (2026) by Kanon WinVega for ZX Spectrum.
A crime boss's wife wants him dead. You're the psychopath she hired. Thirty mobster-filled streets stand between you and Salvatore. Classic arcade carnage for the 48k.⚰
-
Murder (2026) by Kanon WinVega for ZX Spectrum.
A crime boss's wife wants him dead. You're the psychopath she hired. Thirty mobster-filled streets stand between you and Salvatore. Classic arcade carnage for the 48k.⚰
-
Murder (2026) by Kanon WinVega for ZX Spectrum.
A crime boss's wife wants him dead. You're the psychopath she hired. Thirty mobster-filled streets stand between you and Salvatore. Classic arcade carnage for the 48k.⚰
-
Astrodrone (2025) by Steve Tyson for ZX Spectrum.
Your starship is damaged. Send three drones into an asteroid for crystals. But the walls are deadly, fuel runs out, and Exonite can revive a downed drone.
-
Astrodrone (2025) by Steve Tyson for ZX Spectrum.
Your starship is damaged. Send three drones into an asteroid for crystals. But the walls are deadly, fuel runs out, and Exonite can revive a downed drone.
-
Astrodrone (2025) by Steve Tyson for ZX Spectrum.
Your starship is damaged. Send three drones into an asteroid for crystals. But the walls are deadly, fuel runs out, and Exonite can revive a downed drone.
-
Astrodrone (2025) by Steve Tyson for ZX Spectrum.
Your starship is damaged. Send three drones into an asteroid for crystals. But the walls are deadly, fuel runs out, and Exonite can revive a downed drone.
-
Astrodrone (2025) by Steve Tyson for ZX Spectrum.
Your starship is damaged. Send three drones into an asteroid for crystals. But the walls are deadly, fuel runs out, and Exonite can revive a downed drone.
-
Runaway Nose (2025) by Chentzilla for ZX Spectrum.
A nose flees its owner and bends minds with scent. Short, nonlinear, multiple endings. 👃
-
Runaway Nose (2025) by Chentzilla for ZX Spectrum.
A nose flees its owner and bends minds with scent. Short, nonlinear, multiple endings. 👃
-
Runaway Nose (2025) by Chentzilla for ZX Spectrum.
A nose flees its owner and bends minds with scent. Short, nonlinear, multiple endings. 👃
-
Runaway Nose (2025) by Chentzilla for ZX Spectrum.
A nose flees its owner and bends minds with scent. Short, nonlinear, multiple endings. 👃
-
Runaway Nose (2025) by Chentzilla for ZX Spectrum.
A nose flees its owner and bends minds with scent. Short, nonlinear, multiple endings. 👃
-
Basterdale Farm (2025) by The Death Squad for ZX Spectrum.
A Sabre Wulf style maze chase: gather all 100 diamonds to buy back the farm. 128K music by Lee Bee.💎
🎁 https://death-squad.itch.io/basterdale-farm -
Basterdale Farm (2025) by The Death Squad for ZX Spectrum.
A Sabre Wulf style maze chase: gather all 100 diamonds to buy back the farm. 128K music by Lee Bee.💎
🎁 https://death-squad.itch.io/basterdale-farm -
Basterdale Farm (2025) by The Death Squad for ZX Spectrum.
A Sabre Wulf style maze chase: gather all 100 diamonds to buy back the farm. 128K music by Lee Bee.💎
🎁 https://death-squad.itch.io/basterdale-farm -
Basterdale Farm (2025) by The Death Squad for ZX Spectrum.
A Sabre Wulf style maze chase: gather all 100 diamonds to buy back the farm. 128K music by Lee Bee.💎
🎁 https://death-squad.itch.io/basterdale-farm -
Basterdale Farm (2025) by The Death Squad for ZX Spectrum.
A Sabre Wulf style maze chase: gather all 100 diamonds to buy back the farm. 128K music by Lee Bee.💎
🎁 https://death-squad.itch.io/basterdale-farm -
Si te apasionan los RPG clásicos, tienes que probar Hafoc Tor para #ZXSpectrum. Continúa el lore de Wycheweald llevándote a un mundo más abierto, con combates más inmersivos y una campaña inédita que te atrapará. 🕹️⚔️
Descárgalo en: https://redzebra.itch.io/hafoc-tor 😃👍🏻 #retrogaming #rpg -
Si te apasionan los RPG clásicos, tienes que probar Hafoc Tor para #ZXSpectrum. Continúa el lore de Wycheweald llevándote a un mundo más abierto, con combates más inmersivos y una campaña inédita que te atrapará. 🕹️⚔️
Descárgalo en: https://redzebra.itch.io/hafoc-tor 😃👍🏻 #retrogaming #rpg -
Si te apasionan los RPG clásicos, tienes que probar Hafoc Tor para #ZXSpectrum. Continúa el lore de Wycheweald llevándote a un mundo más abierto, con combates más inmersivos y una campaña inédita que te atrapará. 🕹️⚔️
Descárgalo en: https://redzebra.itch.io/hafoc-tor 😃👍🏻 #retrogaming #rpg